How to determine word length of operating system at run time in C++?

267 Views Asked by At

I have a C++ program which is compiled for x86 (32 bit). It is calling a kernel mode driver. The driver is compiled for the word size of the OS both are running on. The target operating systems may be 32 or 64 bit (in my case windows).

My problem is to determine the size of a pointer returned by the driver, as it is needed by an OS call.

The following call of the user mode program worked if the system had a word size of 32 bit:

HANDLE device = OpenDevice();
HANDLE packageReceivedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
bool result = DeviceIoControl(
    device,
    IOCTL_CODE,
    &packageReceivedEvent, //for signaling
    sizeof(HANDLE), //TODO does not work for 64 bit
    nullptr,
    0,
    &recvBytes,
    nullptr);

The definitions come from standard winbase.h and winnt.h.

I cannot use any compile time solutions like sizeof(int), as they would only regard the user mode program, not the driver compilation it is depending on.

Probably it would suffice to set the DeviceIoControl's nInBufferSize simply to the highest expected word size, but is there a nicer solution?

1

There are 1 best solutions below

2
On

you need code like this

union {
    __int64 v;
    HANDLE packageReceivedEvent;
};
v = 0;
BOOL fOk = FALSE;
if (packageReceivedEvent = CreateEvent(NULL, FALSE, FALSE, NULL))
{
    BOOL Wow64Process;
    if (IsWow64Process(NtCurrentProcess(), &Wow64Process))
    {
        fOk = DeviceIoControl(
            device,
            IOCTL_CODE,
            &packageReceivedEvent, //for signaling
            Wow64Process ? 8 : 4,
            nullptr,
            0,
            &recvBytes,
            nullptr);
    }
}
ULONG err = fOk ? NOERROR : GetLastError();

and not "word length" (this is always 2 bytes) but pointer length, which is 4 bytes for 32bit code and 8 bytes for 64bit code. drivers is always must be 'native' - so only 64bit drivers can run in 64bit windows, when user mode applications can be 32 or 64 bit. for determinate it in run time - use IsWow64Process. some drivers accept only 64bit layout structures, some can determinate 32bit process by call IoIs32bitProcess and wait 32bit layout structures from 32bit process. obviously your driver accept only 64bit layout structures. so you need pass 8 or 4 bytes as input size, depended from windows 64 or 32


Probably it would suffice to set the DeviceIoControl's nInBufferSize simply to the highest expected word size, but is there a nicer solution?

this not solution:

  • in 32 bit system driver can check that InputBufferLength == sizeof(HANDLE) (and return STATUS_INFO_LENGTH_MISMATCH if false) or that InputBufferLength >= sizeof(HANDLE)
  • in 64 bit system if you simply say that InputBufferLength == 8, but what data will be in high 32 bits of input buffer ? in your code you init only low 32bits by packageReceivedEvent = CreateEvent(NULL,FALSE, FALSE, NULL); - so you need allocate 8 byte buffer first and correct init it