2017-02-13 84 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

相關問題