共用方式為


為何需要 Thunking

內核模式驅動程式必須驗證從使用者模式應用程式傳入的任何 I/O 緩衝區大小。 如果 32 位應用程式將包含指標有效位數數據類型的緩衝區傳遞至 64 位驅動程式,而且不會發生任何 Thunking,則驅動程式會預期緩衝區大於實際值。 這是因為指標精確度是 32 位 Microsoft Windows 上的 32 位,而 64 位 Windows 上的 64 位。 例如,請考慮下列結構定義:

typedef struct _DRIVER_DATA
{
    HANDLE           Event;
    UNICODE_STRING   ObjectName;
} DRIVER_DATA;

在 32 位 Windows 上,DRIVER_DATA 結構的大小為 12 個字節。 下表顯示 DRIVER_DATA結構之 Event 成員和 ObjectName 成員的大小:

事件 ObjectName (USHORT Length) ObjectName (USHORT 最大長度) ObjectName (PWSTR Buffer)
32 位元 16 位元 16 位元 32 位元
(4 個字節) (2 個字節) (2 個字節) (4 個字節)

在 64 位 Windows 上,DRIVER_DATA 結構的大小為 24 個字節。 (需要 4 個字節的結構填補,才能在 8 位元組界限上對齊 Buffer 成員。)

事件 ObjectName (USHORT Length) ObjectName (USHORT 最大長度) 空 (結構填補) ObjectName (PWSTR Buffer)
64 位元 16 位元 16 位元 32 位元 64 位元
(8 個字節) (2 個字節) (2 個字節) (4 個字節) (8 個字節)

如果 64 位驅動程式在預期為 24 個字節時收到 12 個字節的 DRIVER_DATA,大小驗證將會失敗。 若要避免這種情況,驅動程式必須偵測 32 位應用程式是否傳送DRIVER_DATA結構,如果是的話,請在執行驗證之前適當地叫用它。

例如,上述DRIVER_DATA結構的 Thunked 版本可以定義如下:

typedef struct _DRIVER_DATA32
{
    VOID *POINTER_32   Event;
    UNICODE_STRING32   ObjectName;
} DRIVER_DATA32;

因為它只包含固定有效位數數據類型,所以這個新結構在32位Windows和64位 Windows 上的大小相同。

事件 ObjectName (USHORT Length) ObjectName (USHORT 最大長度) ULONG 緩衝區
32 位元 16 位元 16 位元 32 位元
(4 個字節) (2 個字節) (2 個字節) (4 個字節)