5

I have just been given the task of updating a legacy application from 32-bit to 64-bit. While reviewing the extent of the task, I discovered the following definition immediately before the inclusion of external (eg. platform) headers:

#define POINTER_32

I cannot find what uses this definition or what effect it has, but it looks like the kind of thing that will be directly relevant to my task!

What is it for? What uses it? Will it be safe to remove it immediately (I presume it will be necessary to remove it in the long run)?

This is using MS VC++ 2008, soon to be 2010.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Andy Patrick
  • 280
  • 1
  • 4
  • 11

3 Answers3

7

This is a macro that's normally declared in a Windows SDK header, BaseTsd.h header file. When compiling in 32-bit mode, it is defined as you showed. When compiling in 64-bit mode it is defined as

 #define POINTER_32 __ptr32

which is an MSVC compiler extension to declare 32-bit pointers in a 64-bit code model. There's also a 64-bit flavor for 32-bit code:

 #define POINTER_64 __ptr64

You'd use it if you write a 64-bit program and need to interop with structures that are used by 32-bit code in another process. For example:

typedef struct _SCSI_PASS_THROUGH_DIRECT32 {
    USHORT Length;
    UCHAR ScsiStatus;
    UCHAR PathId;
    UCHAR TargetId;
    UCHAR Lun;
    UCHAR CdbLength;
    UCHAR SenseInfoLength;
    UCHAR DataIn;
    ULONG DataTransferLength;
    ULONG TimeOutValue;
    VOID * POINTER_32 DataBuffer;      // <== here
    ULONG SenseInfoOffset;
    UCHAR Cdb[16];
}SCSI_PASS_THROUGH_DIRECT32, *PSCSI_PASS_THROUGH_DIRECT32;
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
1

Used to get around the Warning C4244 . Provides a 32-bit pointer in both 32-bit and 64-bit models

DumbCoder
  • 5,696
  • 3
  • 29
  • 40
  • 1
    That is just evil: GCC makes that warning an error FYI, and it should be. But that's just my two cents. C++ provides `(u)intptr_t` and `ptr_diff` to store pointers in integral types. – rubenvb Aug 10 '10 at 12:51
  • For anyone stumbling on this answer... POINTER_32 doesn't provide a 32-bit pointer. It provides a truncated 64-bit pointer. – EKW Jul 10 '15 at 14:18
  • Be cautious about using `__ptr32` or `POINTER_32`. Unless the `__uptr` modifier is specified, if this gets copied into a 64-bit pointer it will be sign-extended by default, yielding a senseless address. – Dave Ruske Jul 16 '18 at 18:35
0

My guest is that it was originally created for VLM (Very Large Memory) in Alpha AXP, because Windows NT for Alpha is the first Windows with some 64-bit support. The OS is still 32-bit but it has the VLM API for applications to allocate large 64-bit memory if necessary, hence there must be some way to declare both 32 and 64-bit pointers in the same program

VLM returns POINTER_64 that the app has to store. POINTER_32/__ptr32 are used by default, and POINTER_64/__ptr64 will be used in 64-bit handling code

You can still even see some relics of AXP in Windows documentation and header files related to POINTER_32

POINTER_32 is defined in Ntdef.h and Winnt.h.

#ifdef (__AXP64__)
#define POINTER_32 _ptr32
#else
#define POINTER_32
#endif

Warning C4244

__AXP64__ is meant for Alpha AXP. You can also find lots of other references to Alpha AXP in Ntdef.h and Winnt.h even though Windows no longer runs on that platform

Because of this there are also POINTER_SIGNED and POINTER_UNSIGNED macros to specify how the 32-bit address is extended to the 64-bit one. They'll be expanded to __sptr and __uptr


Another usage would be for 32-bit pointers when disabling LARGEADDRESSAWARE in a 64-bit application

It's exactly the same as x32 ABI in Linux where long and pointers are 32-bit wide

By default, 64-bit Microsoft Windows-based applications have a user-mode address space of several terabytes. For precise values, see Memory Limits for Windows and Windows Server Releases. However, applications can specify that the system should allocate all memory for the application below 2 gigabytes. This feature is beneficial for 64-bit applications if the following conditions are true:

  • A 2 GB address space is sufficient.
  • The code has many pointer truncation warnings.
  • Pointers and integers are freely mixed.
  • The code has polymorphism using 32-bit data types.

All pointers are still 64-bit pointers, but the system ensures that every memory allocation occurs below the 2 GB limit, so that if the application truncates a pointer, no significant data is lost. Pointers can be truncated to 32-bit values, then extended to 64-bit values by either sign extension or zero extension.

Virtual Address Space

When setting /LARGEADDRESSAWARE:NO the size of pointers are still 64-bit wide even though the high 32 bits has no significant values. Therefore to save memory for the pointer we must declare them as POINTER_32

See How to detect X32 on Windows?

phuclv
  • 37,963
  • 15
  • 156
  • 475