64 Declare Function help (1 Viewer)

drjdbb

New member
Local time
Tomorrow, 01:24
Joined
Oct 26, 2016
Messages
9
I have been trying to prepare a db for use in the 2013 32 / 64 bit versions of access runtime. (preferentially 64bit).
One of my forms causes the application to shut down. I have error trapping on all procedures, and some initial fiddling with the Declare statements has improved but not fixed the problem.
I am working on the following premise - the fact that I can't trap the error means the problem lies within the Declaration section of the VBA. (The fact that some fiddling has already improved the situation also tells me that I'm on the right path.)
My research on 64 bit declare statement has me confused. Micrsoft has said that you need to use LongPtr and LongLong, but yet their list of examples contaradicts this: eg
Code:
Declare PtrSafe Function WaitForSingleObjectEx Lib "kernel32" Alias "WaitForSingleObjectEx" (ByVal hHandle As LongPtr, ByVal dwMilliseconds As Long, ByVal bAlertable As Long) As Long
Published by Microsoft. Note the As Long at the end!

So here is my code - any help / corrections would be appreciated.
Also, why would this issue not be arising on my 64bit installation - even when using the runtime emulation mode?
Code:
#If VBA7 Then
    #If Win64 Then
        Private Declare PtrSafe Function WaitForSingleObject Lib "kernel32" _
            Alias "WaitForSingleObjectEx" (ByVal hHandle As LongPtr, _
            ByVal dwMilliseconds As Long) As Long
        Private Declare PtrSafe Function CloseHandle Lib "kernel32" ( _
            ByVal hObject As LongPtr) As LongPtr
        Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
            (ByVal dwAccess As Long, _
            ByVal fInherit As Long, _
            ByVal hObject As Long) As LongPtr
       #Else
        Private Declare Function WaitForSingleObject Lib "kernel32" _
            (ByVal hHandle As Long, _
            ByVal dwMilliseconds As Long) As Long
        Private Declare Function CloseHandle Lib "kernel32" (ByVal _
            hObject As Long) As Long
        Private Declare Function OpenProcess Lib "kernel32.dll" _
            (ByVal dwAccess As Long, _
            ByVal fInherit As Integer, _
            ByVal hObject _
            As Long) As Long
    #End If
#Else
#End If
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 09:54
Joined
Feb 28, 2001
Messages
27,003
PtrLong and LongLong are 64 bit items, but not all items returned by a function are pointers. For example, hWnd (window handles) are WORD, not LONG, even for the 64-bit library. I suspect that the object being returned as a long is a system status, a 32-bit encoded value that you USUALLY see as the reason-code on a blue-screen of death.
 

drjdbb

New member
Local time
Tomorrow, 01:24
Joined
Oct 26, 2016
Messages
9
For example, hWnd (window handles) are WORD, not LONG, even for the 64-bit library.
Not sure about that. Every Microsoft reference I have seen on this shows hWnd using the Long or LongPtr variable type.
Direct from MS...
... locate and modify all data types within these Declare statements that reference handles or pointers to use the new 64-bit compatible LongPtr type alias, and types that need to hold 64-bit integrals with the new LongLong data type. ...To write code that can port between both 32-bit and 64-bit versions of Office you only need to use the new LongPtr type alias instead of Long or LongLong for all pointers and handle values. The LongPtr type alias will resolve to the correct Long or LongLong data type depending on which version of Office is running.

Specifically however, the Declare statement below as specified by...
Microsoft
Code:
Declare PtrSafe Function OpenProcess Lib "kernel32" Alias "OpenProcess" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As [B]Long[/B], ByVal dwProcessId As Long) As [B]LongPtr[/B]
And how I had it originally from the original source of the form and which was working on my system...
Code:
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwAccess As Long, ByVal fInherit As [B]Integer[/B], ByVal hObject As Long) As Long
Differences in bold

Microsoft also imply on their help page that the LongPtr type alias will resolve into the correct type no matter which bit system you are using. BUT then they go on to use the #IF WIN64...#ELSE statement to declare the functions differently? Why - if the PtrSafe and LongPtr words work in both bit systems?

It's all voodoo.
 

Frothingslosh

Premier Pale Stale Ale
Local time
Today, 10:54
Joined
Oct 17, 2012
Messages
3,276
Seriously, just try using LongLong at the end of the Win64 section. It may well fix the problem, and might even save you a millisecond or two in processing time (the system won't need to make a determination) :D . Not to mention I don't know how many hours (and employer dollars) in trying to troubleshoot why LongPtr isn't doing precisely what the MSDN website says.

Also, I note that your first function in the Win64 section is being declared as Long, rather than LongPtr or LongLong, not to mention all the Long declarations IN the functions.
 

sneuberg

AWF VIP
Local time
Today, 07:54
Joined
Oct 17, 2014
Messages
3,506
Microsoft also imply on their help page that the LongPtr type alias will resolve into the correct type no matter which bit system you are using. BUT then they go on to use the #IF WIN64...#ELSE statement to declare the functions differently? Why - if the PtrSafe and LongPtr words work in both bit systems?

I assume you are talking about this Web page. When they start talking about #IF WIN64...#ELSE statement it's under the heading, Writing code that works on both Microsoft Office 2010 (32-bit or 64-bit) and previous versions of Office. so unless you are dealing with Office 2010 I'd ignore that part. It would seem that if you put a #IF WIN64...#ELSE statement in you would have to distribute different runtime systems as I believe it doesn't get compiled on a runtime system. I believe statements like #IF WIN64...#ELSE are just compiler directives.

In your original post why wasn't the the Long in red changed to LongPtr
Code:
 Private Declare PtrSafe Function WaitForSingleObject Lib "kernel32" _
            Alias "WaitForSingleObjectEx" (ByVal hHandle As LongPtr, _
            ByVal dwMilliseconds As Long) As[COLOR="Red"] Long[/COLOR]

Also Microsoft's web page on this doesn't give any examples that have parameters. Have you found anything about whether they should be changed to LongPtr?
 

drjdbb

New member
Local time
Tomorrow, 01:24
Joined
Oct 26, 2016
Messages
9
In your original post why wasn't the the Long in red changed to LongPtr
Also Microsoft's web page on this doesn't give any examples that have parameters. Have you found anything about whether they should be changed to LongPtr?

I was going by this page I stumbled across:
cadsharp.com/docs/Win32API_PtrSafe.txt - sorry, haven't reached 10 posts yet!
They have it as Long and not LongPtr.
That's why it all seems like voodoo to me. No consistency between advice statements and examples given.
 

sneuberg

AWF VIP
Local time
Today, 07:54
Joined
Oct 17, 2014
Messages
3,506
http://cadsharp.com/docs/Win32API_PtrSafe.txt also has "' and Microsoft Office 2010 ...." in its heading whereas https://msdn.microsoft.com/library/gg264421.aspx has at the beginning "Office 2013 and later" Maybe that's the reason for the inconsistency.

I really hope some forum member has a definite answer to this. While I don't have your problem right now I'm sure it's bound to come up. If nobody can answer this on this forum I suggest posting this on the other forums with of course the statement that the post is a crosspost and put in links to the other posts.
 

Frothingslosh

Premier Pale Stale Ale
Local time
Today, 10:54
Joined
Oct 17, 2012
Messages
3,276
When I've run into the issue, I have converted all Long references in the Win64 section to LongLong and have run into zero problems to date.

My intention has always been that if I encounter an issue, I can start reverting back.

Also, to address another issue I saw mentioned, when using conditional compilation, you only need to release two separate versions if you're dealing with an accde or an accde that was turned into an acccdr. An accdb and (in my experience) an accdr made from an accdb will both compile that declaration at runtime. Also, note that when you create an executable, the bit version will be that of the version of Access you use to compile. As far as I'm aware (please prove me wrong), you cannot CHOOSE which condition gets compiled.

For reference, the project I'm currently updating uses the following:
Code:
#If Win64 Then
    Declare PtrSafe Function aht_apiGetOpenFileName Lib "comdlg32.dll" _
        Alias "GetOpenFileNameA" (OFN As tagOPENFILENAME) As Boolean
    Declare PtrSafe Function aht_apiGetSaveFileName Lib "comdlg32.dll" _
        Alias "GetSaveFileNameA" (OFN As tagOPENFILENAME) As Boolean
    Declare PtrSafe Function CommDlgExtendedError Lib "comdlg32.dll" () As LongLong
#Else
    Declare Function aht_apiGetOpenFileName Lib "comdlg32.dll" _
        Alias "GetOpenFileNameA" (OFN As tagOPENFILENAME) As Boolean
    Declare Function aht_apiGetSaveFileName Lib "comdlg32.dll" _
        Alias "GetSaveFileNameA" (OFN As tagOPENFILENAME) As Boolean
    Declare Function CommDlgExtendedError Lib "comdlg32.dll" () As Long
#End If
Code:
#If Win64 Then
    Private Declare PtrSafe Function apiGetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As LongLong) As LongLong
    Private Declare PtrSafe Function GetSystemMenu Lib "user32" (ByVal hwnd As LongLong, ByVal wRevert As LongLong) As LongLong
    Private Declare PtrSafe Function EnableMenuItem Lib "user32" (ByVal hMenu As LongLong, ByVal wIDEnableItem As LongLong, ByVal wEnable As LongLong) As LongLong
#Else
    Private Declare Function apiGetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
    Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal wRevert As Long) As Long
    Private Declare Function EnableMenuItem Lib "user32" (ByVal hMenu As Long, ByVal wIDEnableItem As Long, ByVal wEnable As Long) As Long
#End If
And, believe it or not, this one works fine too:
Code:
#If Win64 Then
    Private Declare PtrSafe Function lstrlenW Lib "kernel32" (ByVal lpString As LongLong) As Long
    
    Private Declare PtrSafe Function SHGetFolderPath Lib "shfolder.dll" Alias "SHGetFolderPathA" _
       (ByVal hwndOwner As Long, _
        ByVal nFolder As Long, _
        ByVal hToken As Long, _
        ByVal dwReserved As Long, _
        ByVal lpszPath As String) As Long
#Else
    Private Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long
    
    Private Declare Function SHGetFolderPath Lib "shfolder.dll" Alias "SHGetFolderPathA" _
       (ByVal hwndOwner As Long, _
        ByVal nFolder As Long, _
        ByVal hToken As Long, _
        ByVal dwReserved As Long, _
        ByVal lpszPath As String) As Long
#End If
This application is currently run simultaneously on Windows 7 (A2010), Windows 8 (A2013), and Windows 10 (O365/A2016) machines without issue.
 
Last edited:

sneuberg

AWF VIP
Local time
Today, 07:54
Joined
Oct 17, 2014
Messages
3,506
]This application is currently run simultaneously on Windows 7 (A2010), Windows 8 (A2013), and Windows 10 (O365/A2016) machines without issue.

Do all of these only have Access runtime and not full Access?
 

Frothingslosh

Premier Pale Stale Ale
Local time
Today, 10:54
Joined
Oct 17, 2012
Messages
3,276
Do all of these only have Access runtime and not full Access?

Hmmm...you know, I think I've managed to avoid that. I've used accdb's turned into accdr's before at previous jobs without issue, but this company just springs for Access licenses whenever someone needs the program. I've tested them AS runtimes here, but that may not process the same.
 

Users who are viewing this thread

Top Bottom