安装打印处理器

若要安装打印处理器,安装应用程序必须调用后台处理程序的 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;
}