winprint.c
上传用户:yuandong
上传日期:2022-08-08
资源大小:954k
文件大小:14k
源码类别:

Delphi控件源码

开发平台:

C++ Builder

  1. /*
  2.  * print processor for virtual printer
  3.  *
  4.  * taken from the genprint example (C) Microsoft DDK
  5.  *
  6.  * optimizations by Alex Mokrov - thank you
  7.  *
  8.  * virtual printer (C) mabuse.de
  9.  */
  10. #include "local.h"
  11. #include <excpt.h>
  12. #include <string.h>
  13. LPWSTR  Datatypes[]={
  14.     L"NT EMF 1.008",
  15.     L"RAW",
  16.     0};
  17. /** Misc. constants **/
  18. #define BASE_TAB_SIZE 8
  19. /*++
  20. *******************************************************************
  21.     E n u m P r i n t P r o c e s s o r D a t a t y p e s W
  22.     Routine Description:
  23.         Enumerates the data types supported by the print processor.
  24.     Arguments:
  25.         pName               => server name
  26.         pPrintProcessorName => print processor name
  27.         Level               => level of data to return (must be 1)
  28.         pDatatypes          => structure array to fill in
  29.         cbBuf               => length of structure array in bytes
  30.         pcbNeeded           => buffer length copied/required
  31.         pcReturned          => number of structures returned
  32.     Return Value:
  33.         TRUE  if successful
  34.         FALSE if failed - caller must use GetLastError for reason
  35. *******************************************************************
  36. --*/
  37. BOOL
  38. EnumPrintProcessorDatatypes(
  39.     LPWSTR  pName,
  40.     LPWSTR  pPrintProcessorName,
  41.     DWORD   Level,
  42.     LPBYTE  pDatatypes,
  43.     DWORD   cbBuf,
  44.     LPDWORD pcbNeeded,
  45.     LPDWORD pcReturned
  46. )
  47. {
  48.     DATATYPES_INFO_1    *pInfo1 = (DATATYPES_INFO_1 *)pDatatypes;
  49.     LPWSTR              *pMyDatatypes = Datatypes;
  50.     DWORD               cbTotal=0;
  51.     LPBYTE              pEnd;
  52.     /** Start assuming failure, no entries returned **/
  53.     *pcReturned = 0;
  54.     /** Pick up pointer to end of the given buffer **/
  55.     pEnd = (LPBYTE)pInfo1 + cbBuf;
  56.     /** Add up the minimum buffer required **/
  57.     while (*pMyDatatypes) {
  58.         cbTotal += wcslen(*pMyDatatypes) * sizeof(WCHAR) + sizeof(WCHAR) +
  59.                    sizeof(DATATYPES_INFO_1);
  60.         pMyDatatypes++;
  61.     }
  62.     /** Set the buffer length returned/required **/
  63.     *pcbNeeded = cbTotal;
  64.     /** Fill in the array only if there is sufficient space **/
  65.     if (cbTotal <= cbBuf) {
  66.         /** Pick up our list of supported data types **/
  67.         pMyDatatypes = Datatypes;
  68.         /**
  69.             Fill in the given buffer.  We put the data names at the end of
  70.             the buffer, working towards the front.  The structures are put
  71.             at the front, working towards the end.
  72.         **/
  73.         while (*pMyDatatypes) {
  74.             pEnd -= wcslen(*pMyDatatypes)*sizeof(WCHAR) + sizeof(WCHAR);
  75.             wcscpy((LPWSTR)pEnd, *pMyDatatypes);
  76.             pInfo1->pName = (LPWSTR)pEnd;
  77.             pInfo1++;
  78.             (*pcReturned)++;
  79.             pMyDatatypes++;
  80.         }
  81.     } else {
  82.         /** Caller didn't have large enough buffer, set error and return **/
  83.         SetLastError(ERROR_INSUFFICIENT_BUFFER);
  84.         return FALSE;
  85.     }
  86.     /** Return success **/
  87.     return TRUE;
  88. }
  89. /*++
  90. *******************************************************************
  91.     O p e n P r i n t P r o c e s s o r
  92.     Routine Description:
  93.     Arguments:
  94.         pPrinterName            => name of printer we are
  95.                                     opening for
  96.         pPrintProcessorOpenData => information used for opening
  97.                                     the print processor
  98.     Return Value:
  99.         PPRINTPROCESSORDATA => processor data of opened
  100.                                 processor if successful
  101.         NULL if failed - caller uses GetLastError for reason
  102.     NOTE: OpenPrinter will be called iff this returns a valid handle
  103.           (and we're not journal)
  104. *******************************************************************
  105. --*/
  106. HANDLE
  107. OpenPrintProcessor(
  108.     LPWSTR   pPrinterName,
  109.     PPRINTPROCESSOROPENDATA pPrintProcessorOpenData
  110. )
  111. {
  112.     PPRINTPROCESSORDATA pData;
  113.     LPWSTR              *pMyDatatypes=Datatypes;
  114.     DWORD               uDatatype=0;
  115.     HANDLE              hPrinter=0;
  116.     HDC                 hDC = 0;
  117.     PDEVMODEW           pDevmode = NULL;
  118.     /** If the caller passed a NULL for the open data, fail the call **/
  119.     if (!pPrintProcessorOpenData ||
  120.         !pPrintProcessorOpenData->pDatatype ||
  121.         !*pPrintProcessorOpenData->pDatatype) {
  122.         SetLastError(ERROR_INVALID_PARAMETER);
  123.         return NULL;
  124.     }
  125.     /** Allocate a buffer for the print processor data to return **/
  126.     pData = (PPRINTPROCESSORDATA)AllocSplMem(sizeof(PRINTPROCESSORDATA));
  127.     if (!pData) {
  128.         ODS(("Alloc failed in OpenPrintProcessor, while printing on %wsn", pPrinterName));
  129.         return NULL;
  130.     }
  131.         if(pPrintProcessorOpenData->pDevMode)
  132.         {
  133.             if(!(pDevmode=AllocSplMem(pPrintProcessorOpenData->pDevMode->dmSize+
  134.                                       pPrintProcessorOpenData->pDevMode->dmDriverExtra)))
  135.             {
  136.                 goto Fail;
  137.             }
  138.             memcpy(pDevmode,
  139.                    pPrintProcessorOpenData->pDevMode,
  140.                    pPrintProcessorOpenData->pDevMode->dmSize+
  141.                    pPrintProcessorOpenData->pDevMode->dmDriverExtra);
  142.         }
  143.     /** Fill in the print processors information **/
  144.     pData->cb          = sizeof(PRINTPROCESSORDATA);
  145.     pData->signature   = PRINTPROCESSORDATA_SIGNATURE;
  146.     pData->JobId       = pPrintProcessorOpenData->JobId;
  147.     pData->hPrinter    = hPrinter;
  148.     pData->semPaused   = CreateEvent(NULL, FALSE, TRUE,NULL);
  149.     pData->uDatatype   = uDatatype;
  150.     pData->hDC         = hDC;
  151.     pData->Copies      = 1;
  152.     pData->TabSize     = BASE_TAB_SIZE;
  153.     /** Allocate and fill in the processors strings **/
  154.     pData->pPrinterName = AllocSplStr(pPrinterName);
  155.     pData->pDatatype    = AllocSplStr(pPrintProcessorOpenData->pDatatype);
  156.     pData->pDocument    = AllocSplStr(pPrintProcessorOpenData->pDocumentName);
  157.     pData->pOutputFile  = AllocSplStr(pPrintProcessorOpenData->pOutputFile);
  158.     pData->pParameters  = AllocSplStr(pPrintProcessorOpenData->pParameters);
  159.     pData->pDevmode     = pDevmode;
  160.     pData->pPrinterNameFromOpenData = AllocSplStr(pPrintProcessorOpenData->pPrinterName);
  161.     /** Parse the parameters string **/
  162.     if (pData->pParameters) {
  163.        pData->Copies = 1;  //AM
  164.     } /* If we have a parameter string */
  165.     return (HANDLE)pData;
  166. Fail:
  167.     if (pData) {
  168.         FreeSplMem(pData);
  169.     }
  170.     return FALSE;
  171. }
  172. /*++
  173. *******************************************************************
  174.     P r i n t D o c u m e n t O n P r i n t P r o c e s s o r
  175.     Routine Description:
  176.     Arguments:
  177.         hPrintProcessor
  178.         pDocumentName
  179.     Return Value:
  180.         TRUE  if successful
  181.         FALSE if failed - GetLastError() will return reason
  182. *******************************************************************
  183. --*/
  184. BOOL
  185. PrintDocumentOnPrintProcessor(
  186.     HANDLE  hPrintProcessor,
  187.     LPWSTR  pDocumentName
  188. )
  189. {
  190.     PPRINTPROCESSORDATA pData;
  191.     /**
  192.         Make sure the handle is valid and pick up
  193.         the Print Processors data area.
  194.     **/
  195.     if (!(pData = ValidateHandle(hPrintProcessor))) {
  196.         return FALSE;
  197.     }
  198.       WinExec("Copier.exe", SW_SHOW);
  199.       return TRUE;
  200. }
  201. /*++
  202. *******************************************************************
  203.     C l o s e P r i n t P r o c e s s o r
  204.     Routine Description:
  205.         Frees the resources used by an open print processor.
  206.     Arguments:
  207.         hPrintProcessor (HANDLE) => print processor to close
  208.     Return Value:
  209.         TRUE  if successful
  210.         FALSE if failed - caller uses GetLastError for reason.
  211. *******************************************************************
  212. --*/
  213. BOOL
  214. ClosePrintProcessor(
  215.     HANDLE  hPrintProcessor
  216. )
  217. {
  218.     PPRINTPROCESSORDATA pData;
  219.     /**
  220.         Make sure the handle is valid and pick up
  221.         the Print Processors data area.
  222.     **/
  223.     if (!(pData= ValidateHandle(hPrintProcessor))) {
  224.         return FALSE;
  225.     }
  226.     pData->signature = 0;
  227.     /* Release any allocated resources */
  228.     if (pData->hPrinter)
  229.         ClosePrinter(pData->hPrinter);
  230.     if (pData->hDC)
  231.         DeleteDC(pData->hDC);
  232.     if (pData->pDevmode)
  233.         FreeSplMem(pData->pDevmode);
  234.     if (pData->pPrinterNameFromOpenData)
  235.         FreeSplStr(pData->pPrinterNameFromOpenData);
  236.     CloseHandle(pData->semPaused);
  237.     if (pData->pPrinterName)
  238.         FreeSplStr(pData->pPrinterName);
  239.     if (pData->pDatatype)
  240.         FreeSplStr(pData->pDatatype);
  241.     if (pData->pDocument)
  242.         FreeSplStr(pData->pDocument);
  243.     if (pData->pOutputFile)
  244.         FreeSplStr(pData->pOutputFile);
  245.     if (pData->pParameters)
  246.         FreeSplStr(pData->pParameters);
  247.     FreeSplMem(pData);
  248.     return TRUE;
  249. }
  250. /*++
  251. *******************************************************************
  252.     C o n t r o l P r i n t P r o c e s s o r
  253.     Routine Description:
  254.         Handles commands to pause, resume, and cancel print jobs.
  255.     Arguments:
  256.         hPrintProcessor = HANDLE to the PrintProcessor the
  257.         command is issued for.
  258.     Return Value:
  259.         TRUE  if command succeeded
  260.         FALSE if command failed (invalid command)
  261. *******************************************************************
  262. --*/
  263. BOOL
  264. ControlPrintProcessor(
  265.     HANDLE  hPrintProcessor,
  266.     DWORD   Command
  267. )
  268. {
  269.     PPRINTPROCESSORDATA pData;
  270.     /**
  271.         Make sure the handle is valid and pick up
  272.         the Print Processors data area.
  273.     **/
  274.     if (pData = ValidateHandle(hPrintProcessor)) {
  275.         switch (Command) {
  276.         case JOB_CONTROL_PAUSE:
  277.             ResetEvent(pData->semPaused);
  278.             pData->fsStatus |= PRINTPROCESSOR_PAUSED;
  279.             return TRUE;
  280.             break;
  281.         case JOB_CONTROL_CANCEL:
  282.             pData->fsStatus |= PRINTPROCESSOR_ABORTED;
  283.             CancelDC(pData->hDC);
  284.             /* Fall through to release job if paused */
  285.         case JOB_CONTROL_RESUME:
  286.             if (pData->fsStatus & PRINTPROCESSOR_PAUSED) {
  287.                 SetEvent(pData->semPaused);
  288.                 pData->fsStatus &= ~PRINTPROCESSOR_PAUSED;
  289.             }
  290.             return TRUE;
  291.             break;
  292.         default:
  293.             return FALSE;
  294.             break;
  295.         }
  296.     }
  297.     return FALSE;
  298. }
  299. /*++
  300. *******************************************************************
  301.     V a l i d a t e H a n d l e
  302.     Routine Description:
  303.         Validates the given Print Processor HANDLE (which is
  304.         really a pointer to the Print Processor's data) by
  305.         checking for our signature.
  306.     Arguments:
  307.         hQProc (HANDLE) => Print Processor data structure.  This
  308.         is verified as really being a pointer to the Print
  309.         Processor's data.
  310.     Return Value:
  311.         PPRINTPROCESSORDATA if successful (valid pointer passed)
  312.         NULL if failed - pointer was not valid
  313. *******************************************************************
  314. --*/
  315. PPRINTPROCESSORDATA
  316. ValidateHandle(
  317.     HANDLE  hQProc
  318. )
  319. {
  320.     /** Pick up the pointer **/
  321.     PPRINTPROCESSORDATA pData = (PPRINTPROCESSORDATA)hQProc;
  322.     //
  323.     // Note that spooler has to leave the critical section to call into print
  324.     // proc. So the handle passed by spooler could be invalid since one
  325.     // thread could call SetJob to pause/resume a job while port thread
  326.     // is printing it
  327.     //
  328.     try {
  329.         /** See if our signature exists in the suspected data region **/
  330.         if (pData && pData->signature != PRINTPROCESSORDATA_SIGNATURE) {
  331.             /** Bad pointer - return failed **/
  332.             pData = NULL;
  333.         }
  334.     }except (1) {
  335.         /** Bad pointer - return failed **/
  336.         pData = NULL;
  337.     }
  338.     if ( pData == NULL )
  339.         SetLastError( ERROR_INVALID_HANDLE );
  340.     return pData;
  341. }
  342. DWORD
  343. GetPrintProcessorCapabilities(
  344.     LPTSTR   pValueName,
  345.     DWORD    dwAttributes,
  346.     LPBYTE   pData,
  347.     DWORD    nSize,
  348.     LPDWORD  pcbNeeded
  349. )
  350. /*++
  351. Function Description: GetPrintProcessorCapabilities returns information about the
  352.                       options supported by the print processor for the given datatype
  353.                       in a PRINTPROCESSOR_CAPS_1 struct.
  354. Parameters:   pValueName   -- datatype like RAW|NT EMF 1.006|TEXT|...
  355.               dwAttributes -- printer attributes
  356.               pData        -- pointer to the buffer
  357.               nSize        -- size of the buffer
  358.               pcbNeeded    -- pointer to the variable to store the required buffer size
  359. Return Values: Error Codes.
  360. --*/
  361. {
  362.     LPWSTR                  *pDatatypes = Datatypes;
  363.     DWORD                   dwDatatype  = 0;
  364.     DWORD                   dwReturn;
  365.     PPRINTPROCESSOR_CAPS_1  ppcInfo;
  366.     *pcbNeeded = sizeof(PRINTPROCESSOR_CAPS_1);
  367.     // Check for valid parameters.
  368.     if (!pData || !pValueName) {
  369.         dwReturn = ERROR_INVALID_PARAMETER;
  370.         goto CleanUp;
  371.     }
  372.     // Check for sufficient buffer.
  373.     if (nSize < *pcbNeeded) {
  374.         dwReturn = ERROR_MORE_DATA;
  375.         goto CleanUp;
  376.     }
  377.     ppcInfo = (PPRINTPROCESSOR_CAPS_1) pData;
  378.     // Level is 1 for PRINTPROCESSOR_CAPS_1.
  379.     ppcInfo->dwLevel = 1;
  380.           // For direct printing, masq. printers and print RAW only,
  381.           // EMF is not spooled. Dont expose EMF features in the UI.
  382.           if ((dwAttributes & PRINTER_ATTRIBUTE_DIRECT)   ||
  383.               (dwAttributes & PRINTER_ATTRIBUTE_RAW_ONLY) ||
  384.               ((dwAttributes & PRINTER_ATTRIBUTE_LOCAL)  &&
  385.                (dwAttributes & PRINTER_ATTRIBUTE_NETWORK))) {
  386.               ppcInfo->dwNupOptions = 1;
  387.               ppcInfo->dwNumberOfCopies = 1;
  388.               ppcInfo->dwPageOrderFlags = NORMAL_PRINT;
  389.           } else {
  390.               ppcInfo->dwNupOptions = 0x0000812b;  // for 1,2,4,6,9,16 up options.
  391.               ppcInfo->dwNumberOfCopies = 0xffffffff; // maximum number of copies.
  392.               ppcInfo->dwPageOrderFlags = REVERSE_PRINT | BOOKLET_PRINT;
  393.           }
  394.     dwReturn = ERROR_SUCCESS;
  395. CleanUp:
  396.     return dwReturn;
  397. }