prcache.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 8k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //---------------------------------------------------------------------------
  2. // prcache.c
  3. //
  4. // implements an Open Printer cache and Printer_ functions which use it.
  5. //
  6. //---------------------------------------------------------------------------
  7. #include "shellprv.h"
  8. #pragma  hdrstop
  9. #include "printer.h"
  10. #include "copy.h"
  11. #ifdef WINNT
  12. HANDLE Printer_OpenPrinterAdmin(LPCTSTR lpszPrinterName)
  13. {
  14.     HANDLE hPrinter = NULL;
  15.     PRINTER_DEFAULTS PrinterDefaults;
  16.     PrinterDefaults.pDatatype = NULL;
  17.     PrinterDefaults.pDevMode  = NULL;
  18.     PrinterDefaults.DesiredAccess  = PRINTER_ALL_ACCESS;
  19.     // PRINTER_READ ? READ_CONTROL
  20.     if (!OpenPrinter((LPTSTR)lpszPrinterName, &hPrinter, &PrinterDefaults))
  21.     {
  22.         hPrinter = NULL; // OpenPrinter may trash hPrinter
  23.     }
  24.     return(hPrinter);
  25. }
  26. #endif
  27. HANDLE Printer_OpenPrinter(LPCTSTR lpszPrinterName)
  28. {
  29.     HANDLE hPrinter = NULL;
  30.     if (!OpenPrinter((LPTSTR)lpszPrinterName, &hPrinter, NULL))
  31.     {
  32.         hPrinter = NULL; // OpenPrinter may trash hPrinter
  33.     }
  34.     return(hPrinter);
  35. }
  36. VOID Printer_ClosePrinter(HANDLE hPrinter)
  37. {
  38.     ClosePrinter(hPrinter);
  39. }
  40. BOOL Printers_DeletePrinter(HWND hWnd, LPCTSTR pszFullPrinter, DWORD dwAttributes, LPCTSTR pszServer)
  41. {
  42.     DWORD dwCommand = MSP_REMOVEPRINTER;
  43.     if (SHIsRestricted(hWnd, REST_NOPRINTERDELETE))
  44.         return FALSE;
  45. #ifdef WINNT
  46.     if (pszServer && pszServer[0])
  47.     {
  48.         //
  49.         // It's a printer on the remote server.  (Skip \ prefix on server.)
  50.         //
  51.         if (ShellMessageBox(HINST_THISDLL, hWnd,
  52.             MAKEINTRESOURCE(IDS_SUREDELETEREMOTE),
  53.             MAKEINTRESOURCE(IDS_PRINTERS), MB_YESNO|MB_ICONQUESTION,
  54.             pszFullPrinter, SkipServerSlashes(pszServer)) != IDYES)
  55.         {
  56.             return FALSE;
  57.         }
  58.     }
  59.     else if (dwAttributes & PRINTER_ATTRIBUTE_NETWORK)
  60.     {
  61.         TCHAR szScratch[MAXNAMELENBUFFER];
  62.         LPTSTR pszPrinter, pszServer;
  63.         if (!(dwAttributes & PRINTER_ATTRIBUTE_LOCAL))
  64.         {
  65.             //
  66.             // If it's not local, then it must be a remote connection.  Note
  67.             // that we can't just check for PRINTER_ATTRIBUTE_NETWORK because
  68.             // NT's spooler has 'masq' printers that are local printers
  69.             // that masquarade as network printers.  Even though they
  70.             // are created by connecting to a printer, the have both LOCAL
  71.             // and NETWORK bits set.
  72.             //
  73.             dwCommand = MSP_REMOVENETPRINTER;
  74.         }
  75.         Printer_SplitFullName(szScratch, pszFullPrinter, &pszServer, &pszPrinter);
  76.         if (pszServer && *pszServer)
  77.         {
  78.             //
  79.             // It's a printer connection.
  80.             //
  81.             if (ShellMessageBox(HINST_THISDLL, hWnd,
  82.                 MAKEINTRESOURCE(IDS_SUREDELETECONNECTION),
  83.                 MAKEINTRESOURCE(IDS_PRINTERS), MB_YESNO|MB_ICONQUESTION,
  84.                 pszPrinter, SkipServerSlashes(pszServer)) != IDYES)
  85.             {
  86.                 return FALSE;
  87.             }
  88.         }
  89.         else
  90.         {
  91.             //
  92.             // It's a printer connection with a printer name that 
  93.             // does not have a server name prefix i.e. \serverprinter.  This
  94.             // is true for the http connected printer, which have printer names
  95.             // of the form http://server/printer on NT these printers are 
  96.             // 'masq' printers.  A 'masq' printer is a printer which 
  97.             // is a local printer acting as network connection.
  98.             //
  99.             if (ShellMessageBox(HINST_THISDLL, hWnd,
  100.                 MAKEINTRESOURCE(IDS_SUREDELETECONNECTIONNOSERVERNAME),
  101.                 MAKEINTRESOURCE(IDS_PRINTERS), MB_YESNO|MB_ICONQUESTION,
  102.                 pszPrinter) != IDYES)
  103.             {
  104.                 return FALSE;
  105.             }
  106.         }
  107.     }
  108.     else
  109.     //
  110.     // Neither a remote printer nor a local connection.  The final
  111.     // upcoming else clause is a local printer.
  112.     //
  113. #endif
  114.     if (ShellMessageBox(HINST_THISDLL, hWnd, MAKEINTRESOURCE(IDS_SUREDELETE),
  115.         MAKEINTRESOURCE(IDS_PRINTERS), MB_YESNO|MB_ICONQUESTION, pszFullPrinter)
  116.         != IDYES)
  117.     {
  118.         return FALSE;
  119.     }
  120.     if (CallPrinterCopyHooks(hWnd, PO_DELETE, 0, pszFullPrinter, 0, NULL, 0)
  121.         != IDYES)
  122.     {
  123.         return FALSE;
  124.     }
  125.     //
  126.     // Cast away const.  Safe since Printers_PrinterSetup only modifies
  127.     // pszPrinter if dwCommand is MSP_NEWDRIVER.
  128.     //
  129.     return BOOLFROMPTR(Printers_PrinterSetup(hWnd, dwCommand,
  130.         (LPTSTR)pszFullPrinter, pszServer));
  131. }
  132. BOOL Printer_GPI2CB(LPVOID lpData, HANDLE hPrinter, DWORD dwLevel,
  133.     LPBYTE pBuf, DWORD dwSize, DWORD *lpdwNeeded, DWORD *lpdwNum)
  134. {
  135.     return GetPrinter(hPrinter, dwLevel, pBuf, dwSize, lpdwNeeded);
  136. }
  137. #ifdef WINNT
  138. //
  139. // Old NT printers don't support the level 5.  So we try for the 2 after 5.
  140. // Win96 WILL PROBABLY WANT TO DO THIS TOO!
  141. //
  142. LPPRINTER_INFO_5 Printer_MakePrinterInfo5( HANDLE hPrinter )
  143. {
  144.     LPPRINTER_INFO_5 pPI5;
  145.     DWORD cbPI5;
  146.     DWORD cbName;
  147.     LPPRINTER_INFO_2 pPI2 = Printer_EnumProps(hPrinter, 2, NULL, Printer_GPI2CB, (LPVOID)0);
  148.     if (!pPI2)
  149.         return NULL;
  150.     cbName = (lstrlen(pPI2->pPrinterName)+1) * SIZEOF(TCHAR);
  151.     cbPI5 = SIZEOF(PRINTER_INFO_5) + cbName;
  152.     //
  153.     // Port name may not be supported (e.g., downlevel machines).
  154.     //
  155.     if (pPI2->pPortName)
  156.     {
  157.         cbPI5 += (lstrlen(pPI2->pPortName)+1) * SIZEOF(TCHAR);
  158.     }
  159.     pPI5 = (LPPRINTER_INFO_5)LocalAlloc(LPTR, cbPI5);
  160.     if (pPI5)
  161.     {
  162.         ASSERT(pPI5->pPrinterName==NULL);   // These should be null for the
  163.         ASSERT(pPI5->pPortName==NULL);      // no names case
  164.         if (pPI2->pPrinterName)
  165.         {
  166.             pPI5->pPrinterName = (LPTSTR)(pPI5+1);
  167.             lstrcpy(pPI5->pPrinterName, pPI2->pPrinterName);
  168.         }
  169.         if (pPI2->pPortName)
  170.         {
  171.             pPI5->pPortName    = (LPTSTR)((LPBYTE)(pPI5+1) + cbName);
  172.             lstrcpy(pPI5->pPortName, pPI2->pPortName);
  173.         }
  174.         pPI5->Attributes = pPI2->Attributes;
  175.         pPI5->DeviceNotSelectedTimeout = 0;
  176.         pPI5->TransmissionRetryTimeout = 0;
  177.     }
  178.     LocalFree(pPI2);
  179.     return(pPI5);
  180. }
  181. #endif
  182. LPVOID Printer_GetPrinterInfo(HANDLE hPrinter, DWORD dwLevel)
  183. {
  184.     LPVOID pPrinter = Printer_EnumProps(hPrinter, dwLevel, NULL, Printer_GPI2CB, (LPVOID)0);
  185. #ifdef WINNT
  186.     //
  187.     // Old NT printers don't support the level 5.  So we try for the 2 after 5.
  188.     // Win96 WILL PROBABLY WANT TO DO THIS TOO!
  189.     //
  190.     if (!pPrinter && dwLevel == 5)
  191.         return(Printer_MakePrinterInfo5(hPrinter));
  192. #endif
  193.     return pPrinter;
  194. }
  195. LPVOID Printer_GetPrinterInfoStr(LPCTSTR lpszPrinterName, DWORD dwLevel)
  196. {
  197.     LPPRINTER_INFO_2 pPI2 = NULL;
  198.     HANDLE hPrinter = Printer_OpenPrinter(lpszPrinterName);
  199.     if (hPrinter)
  200.     {
  201.         pPI2 = Printer_GetPrinterInfo(hPrinter, dwLevel);
  202.         Printer_ClosePrinter(hPrinter);
  203.     }
  204.     return pPI2;
  205. }
  206. // Generate a SHCNE_RENAMEITEM event for this name change.
  207. void Printer_SHChangeNotifyRename(LPTSTR pOldName, LPTSTR pNewName)
  208. {
  209.     LPITEMIDLIST pidlParent = SHCloneSpecialIDList(NULL, CSIDL_PRINTERS, FALSE);
  210.     if (pidlParent)
  211.     {
  212.         IDPRINTER idpOld;
  213.         LPITEMIDLIST pidlOld;
  214.         Printers_FillPidl(&idpOld, pOldName);
  215.         *(USHORT *)((LPBYTE)(&idpOld) + idpOld.cb) = 0;
  216.         pidlOld = ILCombine(pidlParent, (LPCITEMIDLIST)&idpOld);
  217.         if (pidlOld)
  218.         {
  219.             IDPRINTER idpNew;
  220.             LPITEMIDLIST pidlNew;
  221.             Printers_FillPidl(&idpNew, pNewName);
  222.             pidlNew = ILCombine(pidlParent, (LPCITEMIDLIST)&idpNew);
  223.             if (pidlNew)
  224.             {
  225.                 SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_IDLIST, pidlOld, pidlNew);
  226.                 ILFree(pidlNew);
  227.             }
  228.             ILFree(pidlOld);
  229.         }
  230.         ILFree(pidlParent);
  231.     }
  232. }