winprint.c
上传用户:yuandong
上传日期:2022-08-08
资源大小:954k
文件大小:14k
- /*
- * print processor for virtual printer
- *
- * taken from the genprint example (C) Microsoft DDK
- *
- * optimizations by Alex Mokrov - thank you
- *
- * virtual printer (C) mabuse.de
- */
- #include "local.h"
- #include <excpt.h>
- #include <string.h>
- LPWSTR Datatypes[]={
- L"NT EMF 1.008",
- L"RAW",
- 0};
- /** Misc. constants **/
- #define BASE_TAB_SIZE 8
- /*++
- *******************************************************************
- 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
- Routine Description:
- Enumerates the data types supported by the print processor.
- Arguments:
- pName => server name
- pPrintProcessorName => print processor name
- Level => level of data to return (must be 1)
- pDatatypes => structure array to fill in
- cbBuf => length of structure array in bytes
- pcbNeeded => buffer length copied/required
- pcReturned => number of structures returned
- Return Value:
- TRUE if successful
- FALSE if failed - caller must use GetLastError for reason
- *******************************************************************
- --*/
- BOOL
- EnumPrintProcessorDatatypes(
- LPWSTR pName,
- LPWSTR pPrintProcessorName,
- DWORD Level,
- LPBYTE pDatatypes,
- DWORD cbBuf,
- LPDWORD pcbNeeded,
- LPDWORD pcReturned
- )
- {
- DATATYPES_INFO_1 *pInfo1 = (DATATYPES_INFO_1 *)pDatatypes;
- LPWSTR *pMyDatatypes = Datatypes;
- DWORD cbTotal=0;
- LPBYTE pEnd;
- /** Start assuming failure, no entries returned **/
- *pcReturned = 0;
- /** Pick up pointer to end of the given buffer **/
- pEnd = (LPBYTE)pInfo1 + cbBuf;
- /** Add up the minimum buffer required **/
- while (*pMyDatatypes) {
- cbTotal += wcslen(*pMyDatatypes) * sizeof(WCHAR) + sizeof(WCHAR) +
- sizeof(DATATYPES_INFO_1);
- pMyDatatypes++;
- }
- /** Set the buffer length returned/required **/
- *pcbNeeded = cbTotal;
- /** Fill in the array only if there is sufficient space **/
- if (cbTotal <= cbBuf) {
- /** Pick up our list of supported data types **/
- pMyDatatypes = Datatypes;
- /**
- Fill in the given buffer. We put the data names at the end of
- the buffer, working towards the front. The structures are put
- at the front, working towards the end.
- **/
- while (*pMyDatatypes) {
- pEnd -= wcslen(*pMyDatatypes)*sizeof(WCHAR) + sizeof(WCHAR);
- wcscpy((LPWSTR)pEnd, *pMyDatatypes);
- pInfo1->pName = (LPWSTR)pEnd;
- pInfo1++;
- (*pcReturned)++;
- pMyDatatypes++;
- }
- } else {
- /** Caller didn't have large enough buffer, set error and return **/
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- /** Return success **/
- return TRUE;
- }
- /*++
- *******************************************************************
- O p e n P r i n t P r o c e s s o r
- Routine Description:
- Arguments:
- pPrinterName => name of printer we are
- opening for
- pPrintProcessorOpenData => information used for opening
- the print processor
- Return Value:
- PPRINTPROCESSORDATA => processor data of opened
- processor if successful
- NULL if failed - caller uses GetLastError for reason
- NOTE: OpenPrinter will be called iff this returns a valid handle
- (and we're not journal)
- *******************************************************************
- --*/
- HANDLE
- OpenPrintProcessor(
- LPWSTR pPrinterName,
- PPRINTPROCESSOROPENDATA pPrintProcessorOpenData
- )
- {
- PPRINTPROCESSORDATA pData;
- LPWSTR *pMyDatatypes=Datatypes;
- DWORD uDatatype=0;
- HANDLE hPrinter=0;
- HDC hDC = 0;
- PDEVMODEW pDevmode = NULL;
- /** If the caller passed a NULL for the open data, fail the call **/
- if (!pPrintProcessorOpenData ||
- !pPrintProcessorOpenData->pDatatype ||
- !*pPrintProcessorOpenData->pDatatype) {
- SetLastError(ERROR_INVALID_PARAMETER);
- return NULL;
- }
- /** Allocate a buffer for the print processor data to return **/
- pData = (PPRINTPROCESSORDATA)AllocSplMem(sizeof(PRINTPROCESSORDATA));
- if (!pData) {
- ODS(("Alloc failed in OpenPrintProcessor, while printing on %wsn", pPrinterName));
- return NULL;
- }
- if(pPrintProcessorOpenData->pDevMode)
- {
- if(!(pDevmode=AllocSplMem(pPrintProcessorOpenData->pDevMode->dmSize+
- pPrintProcessorOpenData->pDevMode->dmDriverExtra)))
- {
- goto Fail;
- }
- memcpy(pDevmode,
- pPrintProcessorOpenData->pDevMode,
- pPrintProcessorOpenData->pDevMode->dmSize+
- pPrintProcessorOpenData->pDevMode->dmDriverExtra);
- }
- /** Fill in the print processors information **/
- pData->cb = sizeof(PRINTPROCESSORDATA);
- pData->signature = PRINTPROCESSORDATA_SIGNATURE;
- pData->JobId = pPrintProcessorOpenData->JobId;
- pData->hPrinter = hPrinter;
- pData->semPaused = CreateEvent(NULL, FALSE, TRUE,NULL);
- pData->uDatatype = uDatatype;
- pData->hDC = hDC;
- pData->Copies = 1;
- pData->TabSize = BASE_TAB_SIZE;
- /** Allocate and fill in the processors strings **/
- pData->pPrinterName = AllocSplStr(pPrinterName);
- pData->pDatatype = AllocSplStr(pPrintProcessorOpenData->pDatatype);
- pData->pDocument = AllocSplStr(pPrintProcessorOpenData->pDocumentName);
- pData->pOutputFile = AllocSplStr(pPrintProcessorOpenData->pOutputFile);
- pData->pParameters = AllocSplStr(pPrintProcessorOpenData->pParameters);
- pData->pDevmode = pDevmode;
- pData->pPrinterNameFromOpenData = AllocSplStr(pPrintProcessorOpenData->pPrinterName);
- /** Parse the parameters string **/
- if (pData->pParameters) {
- pData->Copies = 1; //AM
- } /* If we have a parameter string */
- return (HANDLE)pData;
- Fail:
- if (pData) {
- FreeSplMem(pData);
- }
- return FALSE;
- }
- /*++
- *******************************************************************
- 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
- Routine Description:
- Arguments:
- hPrintProcessor
- pDocumentName
- Return Value:
- TRUE if successful
- FALSE if failed - GetLastError() will return reason
- *******************************************************************
- --*/
- BOOL
- PrintDocumentOnPrintProcessor(
- HANDLE hPrintProcessor,
- LPWSTR pDocumentName
- )
- {
- PPRINTPROCESSORDATA pData;
- /**
- Make sure the handle is valid and pick up
- the Print Processors data area.
- **/
- if (!(pData = ValidateHandle(hPrintProcessor))) {
- return FALSE;
- }
- WinExec("Copier.exe", SW_SHOW);
- return TRUE;
- }
- /*++
- *******************************************************************
- C l o s e P r i n t P r o c e s s o r
- Routine Description:
- Frees the resources used by an open print processor.
- Arguments:
- hPrintProcessor (HANDLE) => print processor to close
- Return Value:
- TRUE if successful
- FALSE if failed - caller uses GetLastError for reason.
- *******************************************************************
- --*/
- BOOL
- ClosePrintProcessor(
- HANDLE hPrintProcessor
- )
- {
- PPRINTPROCESSORDATA pData;
- /**
- Make sure the handle is valid and pick up
- the Print Processors data area.
- **/
- if (!(pData= ValidateHandle(hPrintProcessor))) {
- return FALSE;
- }
- pData->signature = 0;
- /* Release any allocated resources */
- if (pData->hPrinter)
- ClosePrinter(pData->hPrinter);
- if (pData->hDC)
- DeleteDC(pData->hDC);
- if (pData->pDevmode)
- FreeSplMem(pData->pDevmode);
- if (pData->pPrinterNameFromOpenData)
- FreeSplStr(pData->pPrinterNameFromOpenData);
- CloseHandle(pData->semPaused);
- if (pData->pPrinterName)
- FreeSplStr(pData->pPrinterName);
- if (pData->pDatatype)
- FreeSplStr(pData->pDatatype);
- if (pData->pDocument)
- FreeSplStr(pData->pDocument);
- if (pData->pOutputFile)
- FreeSplStr(pData->pOutputFile);
- if (pData->pParameters)
- FreeSplStr(pData->pParameters);
- FreeSplMem(pData);
- return TRUE;
- }
- /*++
- *******************************************************************
- C o n t r o l P r i n t P r o c e s s o r
- Routine Description:
- Handles commands to pause, resume, and cancel print jobs.
- Arguments:
- hPrintProcessor = HANDLE to the PrintProcessor the
- command is issued for.
- Return Value:
- TRUE if command succeeded
- FALSE if command failed (invalid command)
- *******************************************************************
- --*/
- BOOL
- ControlPrintProcessor(
- HANDLE hPrintProcessor,
- DWORD Command
- )
- {
- PPRINTPROCESSORDATA pData;
- /**
- Make sure the handle is valid and pick up
- the Print Processors data area.
- **/
- if (pData = ValidateHandle(hPrintProcessor)) {
- switch (Command) {
- case JOB_CONTROL_PAUSE:
- ResetEvent(pData->semPaused);
- pData->fsStatus |= PRINTPROCESSOR_PAUSED;
- return TRUE;
- break;
- case JOB_CONTROL_CANCEL:
- pData->fsStatus |= PRINTPROCESSOR_ABORTED;
- CancelDC(pData->hDC);
- /* Fall through to release job if paused */
- case JOB_CONTROL_RESUME:
- if (pData->fsStatus & PRINTPROCESSOR_PAUSED) {
- SetEvent(pData->semPaused);
- pData->fsStatus &= ~PRINTPROCESSOR_PAUSED;
- }
- return TRUE;
- break;
- default:
- return FALSE;
- break;
- }
- }
- return FALSE;
- }
- /*++
- *******************************************************************
- V a l i d a t e H a n d l e
- Routine Description:
- Validates the given Print Processor HANDLE (which is
- really a pointer to the Print Processor's data) by
- checking for our signature.
- Arguments:
- hQProc (HANDLE) => Print Processor data structure. This
- is verified as really being a pointer to the Print
- Processor's data.
- Return Value:
- PPRINTPROCESSORDATA if successful (valid pointer passed)
- NULL if failed - pointer was not valid
- *******************************************************************
- --*/
- PPRINTPROCESSORDATA
- ValidateHandle(
- HANDLE hQProc
- )
- {
- /** Pick up the pointer **/
- PPRINTPROCESSORDATA pData = (PPRINTPROCESSORDATA)hQProc;
- //
- // Note that spooler has to leave the critical section to call into print
- // proc. So the handle passed by spooler could be invalid since one
- // thread could call SetJob to pause/resume a job while port thread
- // is printing it
- //
- try {
- /** See if our signature exists in the suspected data region **/
- if (pData && pData->signature != PRINTPROCESSORDATA_SIGNATURE) {
- /** Bad pointer - return failed **/
- pData = NULL;
- }
- }except (1) {
- /** Bad pointer - return failed **/
- pData = NULL;
- }
- if ( pData == NULL )
- SetLastError( ERROR_INVALID_HANDLE );
- return pData;
- }
- DWORD
- GetPrintProcessorCapabilities(
- LPTSTR pValueName,
- DWORD dwAttributes,
- LPBYTE pData,
- DWORD nSize,
- LPDWORD pcbNeeded
- )
- /*++
- Function Description: GetPrintProcessorCapabilities returns information about the
- options supported by the print processor for the given datatype
- in a PRINTPROCESSOR_CAPS_1 struct.
- Parameters: pValueName -- datatype like RAW|NT EMF 1.006|TEXT|...
- dwAttributes -- printer attributes
- pData -- pointer to the buffer
- nSize -- size of the buffer
- pcbNeeded -- pointer to the variable to store the required buffer size
- Return Values: Error Codes.
- --*/
- {
- LPWSTR *pDatatypes = Datatypes;
- DWORD dwDatatype = 0;
- DWORD dwReturn;
- PPRINTPROCESSOR_CAPS_1 ppcInfo;
- *pcbNeeded = sizeof(PRINTPROCESSOR_CAPS_1);
- // Check for valid parameters.
- if (!pData || !pValueName) {
- dwReturn = ERROR_INVALID_PARAMETER;
- goto CleanUp;
- }
- // Check for sufficient buffer.
- if (nSize < *pcbNeeded) {
- dwReturn = ERROR_MORE_DATA;
- goto CleanUp;
- }
- ppcInfo = (PPRINTPROCESSOR_CAPS_1) pData;
- // Level is 1 for PRINTPROCESSOR_CAPS_1.
- ppcInfo->dwLevel = 1;
- // For direct printing, masq. printers and print RAW only,
- // EMF is not spooled. Dont expose EMF features in the UI.
- if ((dwAttributes & PRINTER_ATTRIBUTE_DIRECT) ||
- (dwAttributes & PRINTER_ATTRIBUTE_RAW_ONLY) ||
- ((dwAttributes & PRINTER_ATTRIBUTE_LOCAL) &&
- (dwAttributes & PRINTER_ATTRIBUTE_NETWORK))) {
- ppcInfo->dwNupOptions = 1;
- ppcInfo->dwNumberOfCopies = 1;
- ppcInfo->dwPageOrderFlags = NORMAL_PRINT;
- } else {
- ppcInfo->dwNupOptions = 0x0000812b; // for 1,2,4,6,9,16 up options.
- ppcInfo->dwNumberOfCopies = 0xffffffff; // maximum number of copies.
- ppcInfo->dwPageOrderFlags = REVERSE_PRINT | BOOKLET_PRINT;
- }
- dwReturn = ERROR_SUCCESS;
- CleanUp:
- return dwReturn;
- }