1

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?

WolfgangS
  • 154
  • 5
  • 11
  • Have you checked if this is actually an issue? Usually OS's are smart and don't require huge amounts of boiler plate code to use a pointer and just give you a valid 32-bit-pointer if you are a 32-bit-program and a valid 64-bit-pointer if you are a 64-bit-program. – nwp Feb 13 '17 at 10:30
  • 1
    Use a 64-bit version of your program on a 64-bit system. That's sort of default. Use 32-bit version of your program on a 32-bit system. Those are rare now. – Cheers and hth. - Alf Feb 13 '17 at 10:38
  • 1
    What do you mean by a "32 bit compiler"? The compiler is an executable which produces executables. Since Windows executables can be 32 and 64 bits, there are 4 theoretical combinations, and only a 64 bits compiler producing 64 bits executables is unambiguously _not_ a "32 bits compiler". – MSalters Feb 13 '17 at 12:07
  • @nwp: The pointer would be translated by the OS correctly, but before that the driver throws an error as it sees a buffer too small to fit its pointer size. – WolfgangS Feb 13 '17 at 12:28
  • @MSalters: You are right. I meant the compilation target, not the compiler itself. I edited the question accordingly. – WolfgangS Feb 13 '17 at 12:36
  • I suspect there's a bigger problem here. Are you trying to pass a 32 bits `HANDLE` to a 64 bits driver? I recall that there's a caveat, but not the details. I'm fairly certain I read the details on Old New Thing (Raymond Chen's blog) but I can't find the article. – MSalters Feb 13 '17 at 13:07

1 Answers1

1

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
RbMm
  • 31,280
  • 3
  • 35
  • 56
  • 1
    "Word size" refers to the size of the *machine word*, not the Windows `WORD` typedef and not the intel assembly syntax -w postfix of or "word ptr" - all of which are 16-bit for backwards compatibility. The word size in most modern Intel processors is 64-bit. – conio Feb 13 '17 at 13:40
  • @conio - in this case i think more correct say about *register size* (general) . from windows view exactly need say about *pointer size* (which equal *register size*) – RbMm Feb 13 '17 at 13:54