Does the bitness of the OS ever matter, or is it just the application I need to worry about?
Asked Answered
T

2

1

Some assumptions: (correct me if wrong)

Ignoring 16-bit stuff, VBA can be run on 32 or 64-bit Office hosts. 64-bit Office can only be run on a 64-bit OS, whereas you can run 32-Bit office on a 32 or 64-bit version of Windows/macOS/other Operating System.

As of VBA7, we have the LongPtr type, which becomes a Long on 32-bit Office (#Win64 = False), LongLong on 64-bit Office (#Win64 = True), regardless of the OS bitness

My question: In APIs that deal with pointers (addresses in memory), does the OS bitness ever matter, or is it only the application running the code that we care about (32/64-bit Office host/VBA)?


Current understanding:

On the one hand I can see why it might not matter:

  • VBA running in 32-bit Excel will have a 32-bit address space (regardless of OS)
  • Therefore any pointers to its own memory should be 32-bits (i.e. Longs - LongPtr gives us this)
  • Similarly 64-bit VBA (necessarily in 64-bit OS, but really could be anywhere) has a 64 bit address space (each pointer is itself 64-bits long and refers to a 64-bit wide block of memory)
  • Therefore any pointers to its own memory should be 64-bits (i.e. LongLongs - LongPtr gives us this)
  • So LongPtr accurately represents a pointer to my code's own memory, regardless of OS bitness

However I can imagine times where the OS bitness could matter

  • Running 32-bit VBA on 64-bit OS, but wanting to refer to areas in memory of a different 64-bit application, the LongPtr type would evaluate to Long and would be too short to represent the maximum pointer size available in that OS.
  • Similarly a 64-bit VBA accessing memory of a 32-bit application would find its pointer type too large to hold the address
  • Now the much trusted LongPtr type is actually the wrong length to represent a pointer to an address in memory outside VBA's own address space!

Problems can now arise depending on OS bitness, not Office/VBA bitness. If we're running VBA7 on 32-bit OS, then LongPtr will be the right length for any chunk of memory you could want to throw at it; it is a suitable pointer datatype in 99.9% of cases since everything the OS does is 32-bit (ignoring 16 bit).

However the same 32-bit VBA7 code instead running on a 64-bit OS would run into difficulties when trying to use LongPtr to hold 32-bit addresses. I feel it's quite common to mix 32-bit and 64-bit applications on a 64-bit OS so this could be a real issue.

32-bit VBA6 and earlier applications running on 32 vs 64 bit Operating Systems could face similar issues, only without the help of LongPtr


Now I appreciate that's a pretty contrived situation, who would ever want to access another application's memory, right? In fact it's so contrived that I'm not sure I could ever come up with a situation where this is important and worth worrying about. Could an application ever obtain an address to the memory of another application with different bitness? Maybe there are some read-write protections preventing this.

Perhaps accessing another application's window handle would be one such occasion; that's public memory and perhaps the bitness of the window handle reflects the bitness of the application or the Operating system, in which case it would be feasible for my 32-bit VBA to want to hold a reference to a 64-bit Hwnd, I'm not sure...


PS I'm aware there are situations other than pointer length where OS bitness may be important. I know of one; the SetWindowLong function required different declarations on 64-bit vs 32-bit Windows - although IIUC that's now been solved with the SetWindowLongPtr function which is identical for both. But any other similar quirks would be useful to know about, I'm only focussing on pointer length here because I have a problem that requires that specific info.

PPS come to think of it, can you even get OS bitness at compile time; I think you can infer it from MAC_OFFICE_VERSION, and ofc Win64 = True means 64-bit Office and de-facto 64-bit OS. But I'm not sure if there's a way to tell whether 32-bit VBA is running on 64-bit Windows...

Tillfourd answered 8/7, 2019 at 14:50 Comment(11)
Sure it does. The bitness of the OS would impact the number of bytes for LongPtr as you pointed out. This is probably only really impacts those who have 32 bit office on 64 bit systems and the API uses 8 bytes for a param. I guess, just use the correct type given the API specs being aware LongPtr can have differing values?Hic
32-bit VBA to want to hold a reference to a 64-bit Hwnd At least for Hwnd it does not matter, as even the 64-bit OS works with 32-Bit Handles: learn.microsoft.com/en-us/windows/win32/winprog64/… The link also holds some information on how you would go about such a thing.Adey
Also: accroding to https://mcmap.net/q/122054/-how-can-i-share-hwnd-between-32-and-64-bit-applications-in-win-x64 Hwnd is an index not a Pointer, so the bitness of OS should not really have an inpact.Adey
@Adey how would a a 64 bit return value fit in 32 bits?Hic
@RyanWildry True, if an API requires 8 bytes (64 bits) of data, then users on 32 bit Office may be tripped up when LongPtr doesn't turn out to be as long as they thought. But firstly, that's not really the problem I'm concerned about. Suppose the API function is QueryPerformanceFrequency. I would argue that in your example the user is using the wrong data-type - the API asks for a LARGE_INTEGER, not a pointer, so while LongPtr happens to work out for them in 64 bit and doesn't in 32 bit office, it's the wrong choice either way.Tillfourd
@RyanWildry According to this MS Docs Entry: learn.microsoft.com/en-us/windows/win32/winprog64/… 64-bit versions of Windows use 32-bit handles for interoperability. When sharing a handle between 32-bit and 64-bit applications, only the lower 32 bits are significant so it is safe to truncate the handle (when passing it from 64-bit to 32-bit) or sign-extend the handle (when passing it from 32-bit to 64-bit)Adey
@Adey Wasn't referring to handles.Hic
@RyanWildry I'm concerned about whether the LongPtr is suitable as a pointer in all situations, or whether the bitness of the OS can sometimes change the semantic meaning of an address in memory, and change how long a pointer data type needs to be. Secondly, I don't think OS bitness matters in the situation you describe.Tillfourd
@RyanWildry I was referring to Handles only so the question is kinda moot. 64-bit values can not fit into 32 bit, but in certain cases (like Hwnd) the design allows to switch between the two since even in the 64-bit value only the lower 32 bit are significant.Adey
Good Read on Pointers in VBA: codeproject.com/Articles/19239/…Adey
Anyway, as to your actual question, IF You want to go the extra mile and need OS-native Pointers, there are other Ways to obtain the OS-bitness. The only reason for this would be to write some function that "Modifies" a Pointer without "Using" it, as the 32-bit code has no reason to "Use" the 64-bit Pointer. Some more info: codekabinett.com/… (which you probably already know) So no, LongPtr is suitable only if you have to "Use" the pointer, as it fits your version of VBA, but not when modifiying some arbitrary pointer.Adey
R
4

A LongPtr is always correct for your process. You do not need to worry about its size. You do not need the WIN64 constant to use it. In fact, the only constant you normally need is VBA7 that tells you whether the LongPtr is even available. If it is, use it, if it's not, you are definitely x86 so use Long.

Additionally, Windows x64 has an entire compatibility layer called WoW64. As a 32-bit app running on 64-bit Windows, you do not notice anything and you run as if the OS was 32-bit. Your pointer size is four bytes, your pointer-sized data types such as HWNDs are four bytes, so again, you do not need to worry about any of that if you only consult VBA7 and correctly place LongPtr in all places where a pointer-sized argument must appear.

So, for routine things inside your process, and for interacting with the OS and its objects, you don't need to worry about either your own or the OS'es bitness, and you don't need the WIN64 constant either.


Now, you specifically mention obtaining and using pointers that are valid for processes with different bitness than your own. Yes, that might be a problem, but this problem is not specific to VBA.

If, as a VBA app, you find yourself in a need to read memory of an arbitrary process of arbitrary bitness, you do need to compare your own bitness to its bitness. At this point you could make use of the WIN64 constant, but it's much more convenient in this case to check the Len(long_ptr_variable) at runtime than to have separate code branches.

Having made the test,

  • If your bitness is higher, you can read the other process'es memory without restrictions.
  • If your bitness is smaller, you can reach as far up the big guy's virtual memory as your 4-byte pointer allows.
    • And if you need to reach beyond that, you would have to fail (or not).

But note that even in this case, you don't care about the OS bitness or the WIN64 const either! You only care about your process bitness vs the other process bitness.

Respondence answered 8/7, 2019 at 18:32 Comment(0)
Q
3

Certainly, bitness of the OS matters.

You can see this answer for a case where we need specific code for 32-bits office on 64-bits Windows (registering COM DLLs properly for use in 32-bits applications).

The test I use there is:

#If Win64 Then
    Const Win64 = True
#Else
    Const Win64 = False
#End If
If Not Win64 And Environ$("ProgramW6432") <> vbNullString Then
    '32 bits Office on Win 64
Else
    'Either 32-bits Windows, or 64-bits Office on 64-bits windows
End If

Afaik, you can't determine this at compile time, only at runtime.

When working with external APIs/applications, it can often matter. I'm not going to compile a list of possible scenario's since it'll never be full, but there are many possible cases.

For memory access, it shouldn't matter, though, since accessing another processes non-global memory should throw a segfault and hard-crash your application. And if you're working with globals it's not really a problem.

Quagga answered 8/7, 2019 at 17:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.