要允许 32 位应用程序在 64 位作系统上运行,除了 64 位应用程序所需的 64 位用户模式显示驱动程序外,还必须提供 32 位用户模式显示驱动程序。 但是,64 位作系统上只需要 64 位版本的显示微型端口驱动程序。 Windows 上的 Windows(WOW64)使 32 位应用程序能够在 64 位操作系统上运行。
Windows 上的 Windows (WOW64) 使 Microsoft Win32 用户模式应用程序能够在 64 位 Windows 上运行。 在转换到 64 位内核之前,它通过截获 Win32 函数调用并将参数从 32 位指针类型转换为 64 位指针类型(视情况转换为 64 位指针类型)来执行此操作。 对于所有 Win32 函数,此转换(称为 thunking)会自动完成,但有一个重要例外:传递给 DeviceIoControl 的数据缓冲区。 这些缓冲区的内容(由 InputBuffer 和 OutputBuffer 参数指向)不会被弹出,因为它们的结构特定于驱动程序。
注意尽管缓冲区 内容 未受到限制,但缓冲区 指针 将转换为 64 位指针。
用户模式应用程序调用 DeviceIoControl 以将 I/O 请求直接发送到指定的内核模式驱动程序。 此请求包含 I/O 控制代码 (IOCTL) 或文件系统控制代码 (FSCTL) 和指向输入和输出数据缓冲区的指针。 这些数据缓冲区的格式特定于 IOCTL 或 FSCTL,后者又由内核模式驱动程序定义。 由于缓冲区格式是任意的,并且驱动程序知道它,而不是 WOW64,因此将数据转换的任务留给驱动程序。
如果满足以下所有条件,则 64 位驱动程序必须支持 32 位 I/O:
- 驱动程序向用户模式应用程序公开 IOCTL (或 FSCTL) 。
- IOCTL 使用的至少一个 I/O 缓冲区包含指针精度数据类型。
- 无法轻松重写 IOCTL 代码,以消除指针精度缓冲区数据类型的使用。
若要在 64 位作系统上安装 32 位用户模式显示驱动程序,必须在图形设备的显示微型端口驱动程序的 INF 文件的外接程序注册表部分中设置以下条目。 必须发生这种情况,以便在驱动程序安装过程中将 32 位用户模式显示驱动程序的 DLL 名称添加到注册表:
[Xxx_SoftwareDeviceSettings]
...
HKR,, UserModeDriverNameWow, %REG_MULTI_SZ%, Xxx.dll
...
INF 文件必须包含信息,以指示作系统将 32 位用户模式显示驱动程序复制到系统的 %systemroot%\SysWOW64 目录。
由于 WOW64 无法处理不透明或非类型化数据结构,例如通过 pfnAllocateCb 函数传递的D3DDDICB_ALLOCATE结构,因此无法执行从 32 位到 64 位的自动转换。 因此,若要使 WOW64 正常工作,在编写要在 64 位作系统上运行的 32 位用户模式显示驱动程序时,必须考虑以下各项:
避免对多操作系统(如 SIZE_T 或 HANDLE)敏感的指针或数据类型。 除了调整整个结构变量的大小外,这些可变宽度数据类型使各个成员的对齐和位置不同。 如果可变宽度成员不可避免,可以添加另一个成员以指示数据结构源自 32 位用户模式显示驱动程序。 然后,64 位显示微型端口驱动程序可以正确执行转换。
即使不存在可变宽度成员,也可能需要考虑特定于体系结构的对齐要求。 例如,在 x64 上,UINT64(或 QWORD)应是8字节对齐的。 由于由标准 32 位编译器编译的 32 位用户模式显示驱动程序可能无法正确对齐这些本机 64 位类型,因此 64 位显示微型端口驱动程序可能无法准确访问来自 32 位用户模式显示驱动程序的数据。 但是,可以使用适当的 编译指示 编译器指令强制对齐。 尽管使用 杂注 编译器指令可能会导致 32 位操作系统上的空间略有浪费,但这允许你在 32 位和 64 位操作系统上使用相同的 32 位用户模式显示驱动程序。 如果无法使用适当的 杂注 编译器指令强制对齐,则在 WOW64 上运行于 64 位操作系统的 32 位用户模式显示驱动程序必须与运行于 32 位操作系统的 32 位用户模式显示驱动程序不同。