创建插件

重要

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

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

所有打印机驱动程序插件都必须定义 DllMain、DllGetClassObject 和 DllCanUnloadNow 函数。 它们还必须实现 IClassFactory COM 接口和 IPrintOemUIIPrintOemUI2IPrintOemUniIPrintOemUni2IPrintOemUni3IPrintOemPSIPrintOemPS2 COM 接口之一。

创建用户界面插件呈现插件时,应以 WDK 中提供的示例 UI 插件示例呈现插件为基础来编写代码。

要创建这两种类型的插件,则必须执行以下操作:

  1. 定义 DllMain 函数(在 Windows SDK 文档中进行介绍)。

    这是所有 Win32 DLL 的入口点。

  2. 定义并导出 DllGetClassObject 函数(在 Windows SDK 文档中进行介绍)。

    打印机驱动程序调用该函数以访问插件的 IClassFactory 接口实现(在 Windows SDK 文档中进行介绍)。 当驱动程序调用 DllGetClassObject 时,它会指定下列类标识符之一(在 prcomoem.h 中定义):

    CLSID_OEMUI - 用于 UI 插件

    CLSID_OEMRENDER - 用于呈现插件

    驱动程序还指定了一个接口标识符 IID_IClassFactory

    如示例代码所示,DllGetClassObject 函数必须创建一个 IClassFactory 接口的实例,并返回一个指向该实例的指针。

  3. 实现 IClassFactory COM 接口。

    IClassFactory 接口的 CreateInstance 方法应为插件创建下列 COM 接口之一的实现实例:

    IPrintOemUIIPrintOemUI2IPrintOemUniIPrintOemUni2IPrintOemUni3IPrintOemPSIPrintOemPS2

    CreateInstance 方法的输入之一是接口标识符。 驱动程序调用 CreateInstance 时使用的接口标识符为 IID_IUnknown,这意味着 CreateInstance 方法必须返回一个指向所创建实例的 IUnknown 接口(在 Windows SDK 文档中进行介绍)的指针,如示例代码所示。

  4. 如示例代码所示,实现 IPrintOemUI、IPrintOemUI2、IPrintOemUni、IPrintOemUni2、IPrintOemUni3、IPrintOemPS 或 IPrintOemPS2 COM 接口之一,包括标准 IUnknown 接口。

    驱动程序调用的第一个实现方法是 IUnknown 接口的 QueryInterface 方法(在 Windows SDK 文档中进行介绍)。 此方法会接收打印机驱动程序接口标识符之一作为输入参数。 驱动程序调用该方法以确定插件支持哪个版本的接口,并接收指向支持的接口的指针。

  5. 定义并导出 DllCanUnloadNow 函数(在 Windows SDK 文档中进行介绍)。

    如果插件实现的 IPrintOemUI、IPrintOemUI2、IPrintOemUni、IPrintOemUni2、IPrintOemUni3、IPrintOemPS 或 IPrintOemPS2 COM 接口的所有实例都已释放,则 DllCanUnloadNow 函数必须返回 S_OK。 S_OK 返回值向驱动程序表明插件可以卸载。

    请注意,当打印机驱动程序卸载插件 DLL 时,它会首先调用插件的 DllCanUnloadNow 函数。 无论 DllCanUnloadNow 返回什么值,打印机驱动程序都会通过调用 FreeLibrary 函数来卸载插件 DLL。 这样做是为了确保在卸载驱动程序之前卸载插件 DLL。

    如果插件 DLL 必须保持加载状态(例如,在创建使用插件 DLL 的线程时),则线程必须通过调用 LoadLibrary 函数来加载 DLL。 当线程使用完 DLL 后,应调用 FreeLibraryAndExitThread 函数将 DLL 卸载。 在线程调用了 LoadLibrary 的情况下,驱动程序对 FreeLibrary 的调用只是递减 DLL 的引用计数,从而阻止 DLL 被卸载。 Windows SDK 文档对 LoadLibrary、FreeLibrary 和 FreeLibraryAndExitThread 函数进行了介绍。