2017-02-13 78 views
1

我有一个编译为x86(32位)的C++程序。它正在调用内核模式驱动程序。驱动程序编译为操作系统的字大小都在运行。目标操作系统可能是32位或64位(在我的情况下是windows)。如何用C++在运行时确定操作系统的字长?

我的问题是确定由驱动程序返回的指针的大小,因为它是OS调用所需要的。

用户模式程序下面的调用工作如果系统有32位字长:

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); 

的定义来自标准WINBASE.H和WINNT.H。

我不能使用像sizeof(int)这样的编译时解决方案,因为它们只考虑用户模式程序,而不是它依赖的驱动程序编译。

也许只需将DeviceIoControlnInBufferSize简单地设置为最高期望的字大小就足够了,但有没有更好的解决方案?

+0

你检查这实际上是一个问题?通常操作系统是聪明的,不需要大量的锅炉代码来使用指针,如果你是一个32位程序和一个有效的64位指针,只要给你一个有效的32位指针一个64位程序。 – nwp

+1

在64位系统上使用64位版本的程序。这是默认的。在32位系统上使用32位版本的程序。那些现在很少见。 –

+1

“32位编译器”是什么意思?编译器是生成可执行文件的可执行文件。由于Windows可执行文件可以是32位和64位,因此有4种理论组合,只有64位编译器生成64位可执行文件才明确地不是“32位编译器”。 – MSalters

回答

1

需要这样

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(); 

而不是“字长的”代码(这始终是2个字节),但长度指针,这是4个字节用于32位代码和64位代码的8个字节。驱动程序始终必须是“本机” - 所以只有64位驱动程序可以在64位窗口中运行,而用户模式应用程序可以是32位或64位。在运行时确定它 - 使用IsWow64Process。有些驱动程序只接受64位布局结构,有些驱动程序可以通过调用IoIs32bitProcess确定32位进程,并等待32位进程的32位布局结构。显然你的驱动程序只接受64位布局结构。所以你需要通过8首或4个字节输入大小,从Windows 64依赖或32


也许就足够了DeviceIoControl的的nInBufferSize 设置简单到最高预期字词大小,但有一个更好 解决方案?

这不是解决办法:

  • 在32位系统的驱动程序可以检查InputBufferLength == sizeof(HANDLE)(如果假返回STATUS_INFO_LENGTH_MISMATCH) 或者,如果你简单地说InputBufferLength == 8InputBufferLength >= sizeof(HANDLE)
  • 在64位系统,但是 什么数据将在高32位的输入缓冲区中?在你的代码 通过packageReceivedEvent = CreateEvent(NULL,FALSE, FALSE, NULL); init仅低32位 - 所以你需要首先分配8个字节的缓冲区和 正确初始化它
+1

“字大小”是指*机器字*的大小,而不是Windows的'WORD' typedef,而不是intel的汇编语法-w后缀或“word ptr” - 所有这些都是16位的向后兼容性。大多数现代英特尔处理器的字大小是64位。 – conio

+0

@conio - 在这种情况下,我认为更正确的说*注册大小*(一般)。从Windows视图完全需要说* *指针大小*(相等*寄存器大小*) – RbMm

相关问题