HRESULT: Use "Long" and Not "LongPtr"

If the return type of an API function call is an HRESULT in the C++ header file, it should be declared as a Long in VBA (and not a LongPtr).

HRESULT: Use "Long" and Not "LongPtr"

There's a lot of confusion in the VBA world when it comes to converting 32-bit-only VBA code to 64-bit-compatible code (myself included).

As I've written in the past, the best resource in this area is Philipp Stiefel's article: How to convert Windows API declarations in VBA for 64-bit.


tl;dr: HRESULT => Long (not LongPtr)


Long vs. LongPtr

Much of the confusion centers around whether to convert a declared Long type to a LongPtr type.  Here's a relevant excerpt from Philipp's excellent explainer (emphasis mine):

LongPtr is the perfect type for any pointer or handle in your Declare Statement. You can use this data type in both environments, and it will always be appropriately sized to handle the pointer size of your environment.

Misconception: “You should change all Long variables in your Declare Statements and Type declarations to be LongPtr variables when adapting your code for 64-bit.”

...

Only if a function parameter or return value is representing a pointer to a memory location or a handle ... should [it] be declared as LongPtr.

The Leading "H" Heuristic

When converting API declarations, the most reliable resource is the Win32API_PtrSafe.txt file, available from Microsoft.  

If you look through that file, you will notice that many of the parameters that get declared as LongPtr have a single letter "h" prefixing their name.  For example:

  • hWnd: Window handle
  • hPrinter: Printer handle
  • hDevice: Device handle
  • hThread: Thread handle

As you've likely guessed, the "h" prefix stands for "handle."  This represents a pointer to a memory location where the object (Window, Printer, Device, Thread, etc.) is located.  In 32-bit Office, the length of this memory address is 32 bits.  In 64-bit Office, the memory address length is 64 bits.

So, if you are converting an API call that is not included in the Win32API_PtrSafe.txt file linked above, a good rule of thumb is that a parameter with a letter "h" prefix is a memory handle and thus should be declared As LongPtr.

The Big Exception

Many COM and Windows API functions return an HRESULT.

What is an HRESULT?  It's a 32-bit integer result code where 0 (zero) equals success and every other number is an error code.

Note what HRESULT is not... It is NOT a handle to a memory address.  An HRESULT is a 32-bit integer code in both 32-bit VBA AND 64-bit VBA.

Thus, if the return type of an API function call is an HRESULT in the C++ header file, it should be declared as a Long in VBA.

For example, here's the syntax for the CoCreateGuid function from the original C++ header file:

HRESULT CoCreateGuid(
  [out] GUID *pguid
);

And here's the associated VBA API declaration line for CoCreateGuid:

Declare PtrSafe Function CoCreateGuid Lib "ole32.dll" (Guid As GUID_TYPE) As Long
NOTE: The declaration for GUID_TYPE is not shown as it is not relevant to the discussion.

Notice the return type is a Long and NOT a LongPtr.

So Why Is It Called an HRESULT Then?

I covered that in a previous article:

In the world of COM, a leading "H" in a variable name usually indicates a "handle" (i.e., memory address) to an object.

That's not the case with an HRESULT, though.  An HRESULT is simply a coded number–it is NOT a handle to an object.

Why the leading "H" then?

According to Microsoft's Raymond Chen, the original COM design called for returning objects (rather than long integers) as the standard return from a function or method call.  This allowed doing some very interesting things, but ultimately it was determined to be overkill.  For simplicity and performance, the object became a simple 32-bit integer.

The original name stuck, leaving us with a term that literally defies convention.

External references

Windows API declarations in VBA for 64-bit
How to convert your API Declarations to 64-bit. - Common myths debunked, key factors explained!

Referenced articles

Breaking Down Windows Error Codes
Did you know there is a method to the madness behind those crazy-looking VBA error numbers like 0x80070005 or its decimal equivalent -2,147,024,891?

Image by Tumisu, please consider ☕ Thank you! 🤗 from Pixabay

All original code samples by Mike Wolfe are licensed under CC BY 4.0