创建插件

重要

建议使用 Microsoft 的 IPP 收件箱类驱动程序以及打印支持应用 (PSA) ,自定义 Windows 10 和 11 中的打印体验,以便进行打印机设备开发。

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

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

创建 用户界面插件呈现插件时,应将代码基于 示例 UI 插件 或 WDK 中提供 的示例呈现插件

若要创建任一类型的插件,必须执行以下操作:

  1. 定义 Windows SDK 文档 () 中所述的 DllMain 函数。

    这是所有 Win32 DLL 的入口点。

  2. 定义和导出 DllGetClassObject 函数, (Windows SDK 文档) 中所述。

    打印机驱动程序调用此函数以获取对 Windows SDK 文档) 中所述的 IClassFactory 接口 (插件实现的访问权限。 当驱动程序调用 DllGetClassObject 时,它会指定 prcomoem.h) 中定义的以下类标识符 (之一:

    CLSID_OEMUI - UI 插件

    CLSID_OEMRENDER - 用于呈现插件

    驱动程序还指定 IID_IClassFactory的接口标识符。

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

  3. 实现 IClassFactory COM 接口。

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

    IPrintOemUIIPrintOemUI2IPrintOemUniIPrintOemUni2IPrintOemUni3IPrintOemPSIPrintOemPS2

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

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

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

  5. 定义和导出 Windows SDK 文档) 中所述的 DllCanUnloadNow 函数 (。

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

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

    例如,如果插件 DLL 必须保持加载 (,则当它创建使用插件 DLL) 的线程时,该线程必须使用对 LoadLibrary 函数的调用来加载 DLL。 当线程完成 DLL 时,它应调用 FreeLibraryAndExitThread 函数来卸载它。 在线程已调用 LoadLibrary 的情况下,驱动程序对 FreeLibrary 的调用只会递减 DLL 的引用计数,从而阻止卸载 DLL。 Windows SDK 文档中介绍了 LoadLibrary、FreeLibrary 和 FreeLibraryAndExitThread 函数。