Search code examples
vba32bit-64bit

What is the purpose of the ptrSafe attribute of a declare statement


In VBA, I need to declare a function in a DLL with the ptrSafe attribute if I am using it in a 64-bit Office environment.

As far as I can see, the ptrSafe does not technically change anything so that I am not sure what the purpose of the ptrSafe attribute actually is.


Solution

  • Realistically, as far as I am concerned, the keyword serves no function other than ensuring that old code will not compile in VBA7.

    Existing Declare statements won't compile in 64-bit VBA until they've been marked as safe for 64-bit by using the PtrSafe attribute

    Office Client Development

    This having the impact that Microsoft Office could provide a standard error to users which try to run 32-bit code in VBA7 and force VBA developers to re-assess their code. If code was simply ran, it might cause a crash, which in some cases could happen on Workbook_Open or similarly "randomly".

    Personally, I feel that introduction of the keyword is awful design, and contributes to the schism between VBA and VB6. The use of keyword PtrSafe provides no guarantees in reality, other than that the user has added the keyword. It does not guarantee they have checked for handles and converted those to LongPtr. And as a result of this bad design, we now need to use complex macros to compile code for both 64 and 32 bit office...

    #if Win64 then
        Private Const NULL_PTR as LongLong = 0^
    #else
        Private Const NULL_PTR as Long = 0&
    #end if
    
    #if VBA7 then
        Private Declare PtrSafe Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = NULL_PTR) As Long
        '...
    #else
        Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As Long = NULL_PTR) As Long
        '...
    #end if
    

    No, instead, Microsoft would have been better:

    1. Releasing a patch for 32-bit VBA and VB6 which adds the LongPtr type.
    2. Kept old declare syntax as it was

    If this were done, the following would suffice for both 32 and 64 bit systems:

    Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
    

    And hell even if they didn't release a patch for 32-bit VBA/VB6 we could still use macros and an Enum:

    #If VBA7 = 0 then
      Enum LongPtr
        [_]
      End Enum
    #End If
    Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
    '...
    

    But alas, because of the introduction of this keyword we now have to define all our statements twice if we want to remain compatible:

    #If VBA7 then
      Private Declare PtrSafe Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
      '...
    #Else 
      Enum LongPtr
        [_]
      End Enum
      Private Declare Function OpenClipboard Lib "user32" (Optional ByVal hWnd As LongPtr = 0) As Long
      '...
    #End If
    

    If I were Microsoft I'd make PtrSafe keyword optional. Doing so would do a world of good.