写 64 位打印机驱动程序

重要

新式打印平台是 Windows 与打印机通信的首选方式。 建议使用 Microsoft 的 IPP 收件箱类驱动程序以及打印支持应用 (PSA) 来自定义 Windows 10 和 11 中的打印体验,以便进行打印机设备开发。

有关详细信息,请参阅新式打印平台打印支持应用设计指南

如果正在编写 64 位驱动程序,或者正在编写可编译为在 32 位和 64 位系统上运行的驱动程序,请遵循将驱动程序移植到 64 位 Windows 中的 64 位移植指南。 本主题介绍在编写 64 位打印机驱动程序时可能遇到的一些限制和问题。

有关使用装饰来识别 64 位体系结构的详细信息,请参阅以下主题:

设备上下文句柄的限制

如果 32 位应用程序在 64 位版本的 Microsoft Windows 操作系统上运行,则在 Splwow64.exe thunk 进程上下文中运行的打印机驱动程序插件不应调用 GDI CreateDC 函数;此调用将失败。

编写 64 位驱动程序时的问题

在现有的 32 位驱动程序代码中,请注意指针类型与 DWORD 或 ULONG 等整数类型之间的转换。 如果拥有为 32 位计算机编写代码的经验,则可能会习惯于认为指针值适合放在 DWORD 或 ULONG 中。 对于 64 位代码,此假设很危险。 如果将指针转换为 DWORD 或 ULONG 类型,则 64 位指针可能会被截断。

相反,应将指针转换为 DWORD_PTR 或 ULONG_PTR 类型。 无论代码是针对 32 位还是 64 位计算机编译,DWORD_PTR 或 ULONG_PTR 类型的无符号整数总是足以存储整个指针。

例如,OEMCUIPPARAM 结构中的 pDrvOptItems.UserData 指针字段是 ULONG_PTR 类型。 以下代码示例演示了将 64 位指针值复制到该字段时的禁忌。

PUSERDATA pData;
OEMCUIPPARAM->pDrvOptItems.UserData = (ULONG)pData;  // Wrong

前面的代码示例将 pData 指针赋值给 ULONG 类型,如果 sizeof(pData) >sizeof(ULONG) 时,则指针值会被截断。 正确的方法是将指针转为 ULONG_PTR,如以下代码示例所示。

PUSERDATA pData;
OEMCUIPPARAM->pDrvOptItems.UserData = (ULONG_PTR)pData;  // Correct

前面的代码示例保留了指针值的全部 64 位。

诸如 PtrToUlongUlongToPtr 等内联 64 位函数可安全地在指针和整数类型之间进行转换,而无需依赖对这些类型相对大小的假设。 如果一种类型比另一个类型短,则必须在转换为较长类型时对其进行扩展。 如果通过填充符号位或零来扩展较短类型,则每个 Win64 函数都可以处理这些情况。 请考虑以下代码示例。

ULONG ulHWPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = ULONG(pulPhysHWBuffer) + HW_BUFFER_SIZE;  // wrong

应该用下面的代码示例替换前面的代码示例。

ULONG_PTR ulHWPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = PtrToUlong(pulPhysHWBuffer) + HW_BUFFER_SIZE;  // correct

虽然第二个代码示例可能表示的

ulSlotPhysAddr

硬件寄存器的值只有 32 位,而不是 64 位,但它是首选。 有关用于在指针和整数类型之间转换的所有新 Win64 帮助程序函数的列表,请参阅新数据类型