安装打印处理器
若要安装打印处理器,安装应用程序必须调用后台处理程序的 AddPrintProcessor 函数。 若要将打印处理器与打印队列相关联,请在 PrintProcessor 条目的 INF 文件中列出其文件名。 对于要与打印处理器关联的每个打印队列,必须包含此项。 有关详细信息,请参阅 打印机 INF 文件。
当安装应用程序调用后台处理程序的 AddPrinter 函数时,使用 {PRINTER_INFO_2] (/windows/win32/printdocs/printer-info-2) 结构作为输入参数,它将指定 (从 INF 文件) 获取的打印处理器名称作为结构成员。
将打印处理器与已安装 pnp 的打印队列相关联
如果 即插即用 (PnP) 管理器在运行 Windows 2000 或 Windows XP 的系统上检测到并安装打印队列,并且用于安装打印队列的 INF 文件包含默认 Windows 打印处理器 WinPrint 以外的 PrintProcessor 条目,则打印处理器将不会与打印队列关联。 但是,将安装打印处理器。
请注意,如果使用“添加打印机”向导安装打印队列,则打印处理器与打印队列正确关联。
另请注意,Microsoft Windows Server 2003 及更高版本中的 PnP 管理器将打印处理器与打印队列正确关联。
若要将打印处理器与在 Windows 2000 和 Windows XP 上安装即插即用的打印队列相关联,请在打印机接口 DLL 的 DrvPrinterEvent 函数中包含PRINTER_EVENT_INITIALIZE事例。 对于 Microsoft Windows Server 2003 及更高版本,无需在 DrvPrinterEvent 函数中添加PRINTER_EVENT_INITIALIZE事例。
下面的代码示例将 PRINTER_INFO_2 结构的 pPrintProcessor 成员设置为打印处理器的名称,然后调用 SetPrinter 函数来更新打印机的设置。 请注意, gszPrintProc 中打印处理器的名称必须与 INF 文件中 PrintProcessor 条目的名称相同。
BOOL
DrvPrinterEvent(
LPWSTR pPrinterName,
INT Event,
DWORD Flags,
LPARAM lParam
)
{
PRINTER_DEFAULTS PrinterDef = {NULL, NULL, PRINTER_ALL_ACCESS};
HANDLE hPrinter;
LPPRINTER_INFO_2 pInfo = NULL;
DWORD cbNeeded;
TCHAR gszPrintProc[] = TEXT("<Print processor name>");
BOOL bRet = TRUE;
switch (Event)
{
case PRINTER_EVENT_INITIALIZE:
if (OpenPrinter(pPrinterName, &hPrinter, &PrinterDef))
{
if ( !GetPrinter( hPrinter, 2, (LPBYTE) pInfo, 0, &cbNeeded ) &&
(GetLastError() != ERROR_INSUFFICIENT_BUFFER) )
{
bRet = FALSE;
}
if (bRet == TRUE)
{
pInfo = (LPPRINTER_INFO_2) LocalAlloc(LPTR, cbNeeded);
bRet = pInfo ? TRUE : FALSE;
}
if (bRet == TRUE)
{
if (GetPrinter(hPrinter, 2, (LPBYTE) pInfo, cbNeeded, &cbNeeded))
{
pInfo->pPrintProcessor = gszPrintProc;
SetPrinter(hPrinter, 2, (LPBYTE) pInfo, 0);
}
else
{
bRet = FALSE;
}
if (pInfo)
{
LocalFree(pInfo);
}
}
ClosePrinter(hPrinter);
}
else // OpenPrinter failed
{
bRet = FALSE;
}
break;
// cases for other events
default:
break;
} // end switch
return bRet;
}
在打印机驱动程序升级期间将打印处理器与打印队列相关联
更新打印机驱动程序时,更新的打印队列的打印处理器不会更改。 如果新的打印机驱动程序需要特定的打印处理器,打印机接口 DLL 的 DrvUpgradePrinter 函数必须将 PRINTER_INFO_2 结构的 pPrintProcessor 成员设置为新打印处理器的名称。 发生这种情况后,此函数调用 SetPrinter 以更新打印机的设置。 后台处理程序为每个打印机调用 一次 DrvUpgradePrinter 函数,这可确保使用该驱动程序的所有打印机也使用所需的打印处理器。 下面的代码示例演示了这些点。
BOOL
DrvUpgradePrinter(
DWORD Level,
LPBYTE pDriverUpgradeInfo
)
{
HANDLE hPrinter;
PRINTER_DEFAULTS PrinterDef = {NULL, NULL, PRINTER_ALL_ACCESS};
PDRIVER_UPGRADE_INFO_2 pDUI2;
LPPRINTER_INFO_2 pInfo = NULL;
DWORD cbNeeded;
TCHAR gszPrintProc[] = TEXT("<Print processor name>");
TCHAR gszPrintDriver[] = TEXT("<Printer driver name>");
BOOL bRet = TRUE;
if ((Level == 2) &&
(pDUI2 = (PDRIVER_UPGRADE_INFO_2)pDriverUpgradeInfo) &&
(OpenPrinter(pDUI2->pPrinterName, &hPrinter, &PrinterDef)))
{
if ( !GetPrinter( hPrinter, 2, (LPBYTE) pInfo, 0, &cbNeeded ) &&
(GetLastError() != ERROR_INSUFFICIENT_BUFFER) )
{
bRet = FALSE;
}
if (bRet == TRUE)
{
pInfo = (LPPRINTER_INFO_2) LocalAlloc(LPTR, cbNeeded);
bRet = pInfo ? TRUE : FALSE;
}
if (bRet == TRUE)
{
if (GetPrinter(hPrinter, 2, (LPBYTE) pInfo, cbNeeded, &cbNeeded))
{
//
// This function is called for every printer queue that uses a driver
// for which one or more files were updated. However, we only want to
// update the printer queue's "driver" by a particular driver.
//
if ( !lstrcmpi(pInfo->pDriverName, gszPrintDriver) )
{
pInfo->pPrintProcessor = gszPrintProc;
SetPrinter(hPrinter, 2, (LPBYTE) pInfo, 0);
}
else // GetPrinter
{
bRet = FALSE;
}
if (pInfo)
{
LocalFree(pInfo);
}
ClosePrinter(hPrinter);
}
else // Level != 2 or pDUI2 == NULL or OpenPrinter failed
{
bRet = FALSE;
}
return bRet;
}