Declare statement in Win64 VBA Office
Asked Answered
O

2

0

I have used vba code in Windows 32 bit. Now that I've migrated to Windows 10 64 bit I got the message "The code in this project should be updated for use on 64-bit systems. Please review and update Declare statements and then mark them with PtrSafe attribute." The Declare commands I have are the following:

Public Declare Function GetUserNameEx Lib "Secur32.dll" Alias "GetUserNameExA" ( _
  ByVal NameFormat As EXTENDED_NAME_FORMAT, _
  ByVal lpNameBuffer As String, _
  ByRef lpnSize As Long) As Long

Public Enum EXTENDED_NAME_FORMAT
  NameUnknown = 0
  NameFullyQualifiedDN = 1
  NameSamCompatible = 2
  NameDisplay = 3
  NameUniqueId = 6
  NameCanonical = 7
  NameUserPrincipal = 8
  NameCanonicalEx = 9
  NameServicePrincipal = 10
  NameDnsDomain = 12
End Enum

Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias _
"GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long

Private Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As String
    lpstrCustomFilter As String
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As String
    nMaxFile As Long
    lpstrFileTitle As String
    nMaxFileTitle As Long
    lpstrInitialDir As String
    lpstrTitle As String
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As String
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
End Type

Public Declare Function ShellExecute _
    Lib "shell32.dll" _
    Alias "ShellExecuteA" ( _
    ByVal hwnd As Long, _
    ByVal lpOperation As String, _
    ByVal lpFile As String, _
    ByVal lpParameters As String, _
    ByVal lpDirectory As String, _
    ByVal nShowCmd As Long) _
    As Long

I've looked at some documentation but I can not really understand when using the LongLong and LongPtr statements. Or if it's only declare PtrSafe in the Declare statement.

Link to MicroSoft documentation https://msdn.microsoft.com/en-us/library/office/ee691831(v=office.14).aspx

Can someone help me?

Ostwald answered 26/9, 2017 at 13:56 Comment(1)
You use LongPtr when the data type needs to represent a pointer or a pointer-sized data type (e.g. a handle). You use LongLong when you need a 64-bit integer that will always be 64 bits regardless of the pointer size. Look up in the MSDN the original C++ signatures of the functions and structures you are using, refer to msdn.microsoft.com/en-us/library/windows/desktop/… to learn which ones boil down to PVOID or have an #if that gives them different size depending on the platform, and those will be LongPtrs.Yap
U
1

You use LongPtr when it concerns a memory address and Long when it is just a number. Include PtrSafe whenever you use a LongPtr in your declaration. So your ShellExecute declaration will be (tested):

#If VBA7 Then
Public Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
        ByVal hWnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, _
        ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPtr
#Else
Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
  (ByVal hWnd As Long, ByVal lpOperation As String, _
  ByVal lpFile As String, ByVal lpParameters As String, _
  ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#End If
Unblown answered 20/10, 2017 at 13:11 Comment(4)
when it concerns a memory address - no, it's when it concerns a pointer-sized anything. That includes OS handles (which are not memory addresses).Yap
If anything is pointer-sized, it is because a memory address needs to fit in there. Like a handle which is often one.Unblown
Someone edited out the #If, #Else and #End If directives. I have no idea why. But now it is no longer tested.Unblown
It's not no longer tested, it's no longer valid. Don't hesitate to roll back invalid edits.Yap
T
0

Try replacing them with these (untested)


GetUserNameEx 64 bit / 64 bit

Public Enum EXTENDED_NAME_FORMAT
  NameUnknown = 0
  NameFullyQualifiedDN = 1
  NameSamCompatible = 2
  NameDisplay = 3
  NameUniqueId = 6
  NameCanonical = 7
  NameUserPrincipal = 8
  NameCanonicalEx = 9
  NameServicePrincipal = 10
  NameDnsDomain = 12
End Enum

#If VBA7 Then
    Public Declare PtrSafe Function GetUserNameEx Lib "Secur32.dll" Alias "GetUserNameExA" (ByVal NameFormat As EXTENDED_NAME_FORMAT, ByVal lpNameBuffer As String, ByRef lpnSize As Long) As Long
#Else
    Public Declare Function GetUserNameEx Lib "Secur32.dll" Alias "GetUserNameExA" (ByVal NameFormat As EXTENDED_NAME_FORMAT, ByVal lpNameBuffer As String, ByRef lpnSize As Long) As Long
#End If

GetOpenFileName 64 bit / 64 bit

Type OPENFILENAME
        lStructSize As Long
        hwndOwner As LongPtr
        hInstance As LongPtr
        lpstrFilter As String
        lpstrCustomFilter As String
        nMaxCustFilter As Long
        nFilterIndex As Long
        lpstrFile As String
        nMaxFile As Long
        lpstrFileTitle As String
        nMaxFileTitle As Long
        lpstrInitialDir As String
        lpstrTitle As String
        flags As Long
        nFileOffset As Integer
        nFileExtension As Integer
        lpstrDefExt As String
        lCustData As LongPtr
        lpfnHook As LongPtr
        lpTemplateName As String
'#if (_WIN32_WINNT >= 0x0500)
        pvReserved As LongPtr
        dwReserved As Long
        FlagsEx As Long
'#endif // (_WIN32_WINNT >= 0x0500)
End Type

#If VBA7 Then
    Private Declare PtrSafe Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
#Else
    Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
#End If

ShellExecute 64 bit / 64 bit

#If VBA7 Then
    Private Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPtr
#Else
    Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#End If
Trochaic answered 27/9, 2017 at 0:11 Comment(5)
I believe some of your Longs should be LongPtr for VBA 7. I doubt this will work reliably. I'm not familiar with all these functions, though.Sissified
Thanks to Paul Bica for the contribution. I don't know yet if it works or not. I just realize that all Long variables that handle Recordcount must to change to LongLong. So I can't really test if your solution work. First I need to convert all my Long variables and there are a lot.Ostwald
Function ShellExecute ... (ByVal hwnd As LongPtr, ...) as LongPtr, otherwise I believe you got it right.Yap
Thanks @Yap - that was the signature I couldn't find in MSDN (still untested, unless Julio Garcia will confirm it)Trochaic
It's msdn.microsoft.com/en-us/library/windows/desktop/…, and you put LongPtr under the wrong branch of the #If.Yap

© 2022 - 2024 — McMap. All rights reserved.