📄 prprint.cpp
字号:
/* * * prprint.cpp * */#include "prprint.h"#include "..\lib\debug.h"#include "..\lib\devmode.h"#include "..\lib\prspoolerdatafile.h"#include "..\lib\printResizerCommon.h"#include "..\lib\prutils.h"#include "..\lib\utils.h"#include <windows.h>#include <wchar.h>#include <winspool.h>#include <winsplp.h>#include <winddi.h>#include <winddiui.h>extern "C" {#include <winppi.h>}#include <tchar.h>#include <strsafe.h>#include <malloc.h>//#include <excpt.h>// DEBUG / FIX//#undef STATICBOOLBREAK//#define STATICBOOLBREAK FALSEtypedef struct _PRPRINTDATA { DWORD dwJobID; HWND hwndPreviewApp; LPTSTR lptstrPrinterNameFromOpenData; ::PrintProcessorParameter ppp; // 6/25 DEBUG/FIX PDEVMODE pdm; LPTSTR lptstrDocName; //7/7 DEBUG/FIX BOOL bTempFileWritten;} PRPRINTDATA;typedef PRPRINTDATA *PPRPRINTDATA;// put raw and text back for now -- doesn't seem to work w/o "raw" in thereLPTSTR gatstrDatatypes[] = { L"RAW", L"NT EMF 1.006", L"NT EMF 1.007", L"NT EMF 1.008", L"TEXT", 0};enum { PRINTPROCESSOR_TYPE_EMF_50_1 = 1, PRINTPROCESSOR_TYPE_EMF_50_2 = 2, PRINTPROCESSOR_TYPE_EMF_50_3 = 3};VOID ReleasePRPRINTDATA(IN PPRPRINTDATA pData) ;BOOL CALLBACK DllMain( HANDLE hModule, DWORD dwReason, LPVOID lpRes ) { return TRUE;} BOOL WINAPI EnumPrintProcessorDatatypesW( IN LPWSTR pName, IN LPWSTR pPrintProcessorName, IN DWORD Level, OUT LPBYTE pDatatypes, IN DWORD cbBuf, OUT LPDWORD pcbNeeded, OUT LPDWORD pcReturned){ DATATYPES_INFO_1 *pInfo1 = (DATATYPES_INFO_1 *)pDatatypes; LPWSTR *pMyDatatypes = gatstrDatatypes; DWORD cbTotal=0; ULONG cchBuf =0; LPBYTE pEnd; if ( NULL == pcbNeeded || NULL == pcReturned ) { return FALSE; SetLastError (ERROR_INVALID_PARAMETER); } /** Start assuming failure, no entries returned **/ *pcReturned = 0; /** Add up the minimum buffer required **/ while (*pMyDatatypes) { cbTotal += (DWORD) 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) { if ( NULL == pInfo1 ) //pInfo1 is same as pDatatypes { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } /** Pick up pointer to end of the given buffer **/ pEnd = (LPBYTE)pInfo1 + cbBuf; /** Pick up our list of supported data types **/ pMyDatatypes = gatstrDatatypes; /** 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) { cchBuf = (DWORD) wcslen(*pMyDatatypes) + 1; //+1 is for \0. pEnd -= cchBuf*sizeof(WCHAR); StringCchCopy ( (LPWSTR)pEnd, cchBuf, *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;}HANDLE OpenPrintProcessor( LPWSTR pPrinterName, PPRINTPROCESSOROPENDATA pppod ) { PPRPRINTDATA pData = NULL; LPWSTR *pMyDatatypes = gatstrDatatypes; DWORD uDatatype = 0; HANDLE hPrinter = NULL; TCHAR tcSep = L','; LPTSTR lptstrParam = NULL; LPTSTR lptstrSep = NULL; // DEBUG / FIX static BOOL b = STATICBOOLBREAK; if (b) { ::DebugBreak(); } // If the caller passed a NULL for the open data, fail the call. // pppod->pDevMode can be NULL if (pppod == NULL || pppod->pDatatype == NULL || *pppod->pDatatype == NULL //*pppod->pDatatype == NULL // WHY IS THIS IN genprint? ) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; } /** Search for the data type index we are opening for **/ while (*pMyDatatypes) { if (!_wcsicmp(*pMyDatatypes,pppod->pDatatype)) { break; } ++pMyDatatypes; ++uDatatype; } /** Allocate a buffer for the print processor data to return **/ pData = (PPRPRINTDATA) malloc(sizeof(*pData)); if (pData == NULL) { goto Fail; } ZeroMemory ( pData, sizeof(*pData) ); /** Open the processor accordingly **/ switch (uDatatype) { case PRINTPROCESSOR_TYPE_EMF_50_1: case PRINTPROCESSOR_TYPE_EMF_50_2: case PRINTPROCESSOR_TYPE_EMF_50_3: break; default: SetLastError(ERROR_INVALID_DATATYPE); goto Fail; } pData->dwJobID = pppod->JobId; pData->lptstrPrinterNameFromOpenData = ::StringDuplicate(pppod->pPrinterName); if (pData->lptstrPrinterNameFromOpenData == NULL) { SetLastError(ERROR_OUTOFMEMORY); goto Fail; } if (! ::ParsePrintProcessorParameter(pData->ppp, pppod->pParameters)) { ::SetLastError(ERROR_INVALID_PARAMETER); goto Fail; } // THE PREVIEW APP SHOULD BE LAUNCHED // IT IS THE PREVIEW APP THAT WILL DELETE THE TEMP FILE if (! ::IsWindow(pData->ppp.hwndPreviewApp)) { ::SetLastError(ERROR_INVALID_PARAMETER); goto Fail; } // 6/25 DEBUG / FIX pData->pdm = ::DM_Duplicate( pppod->pDevMode ); pData->lptstrDocName = ::StringDuplicate( pppod->pDocumentName ); return (HANDLE) pData;Fail: ReleasePRPRINTDATA(pData); return NULL;}BOOL PrintDocumentOnPrintProcessor( HANDLE hPrintProcessor, LPWSTR pDocumentName ) { BOOL bRetValue = FALSE; PPRPRINTDATA pData = (PPRPRINTDATA) hPrintProcessor; // DEBUG / FIX static BOOL b = STATICBOOLBREAK; if (b) { ::DebugBreak(); } const TCHAR atstrJob[] = TEXT(",Job "); DWORD dwcChBuff = lstrlen(pData->lptstrPrinterNameFromOpenData) + lstrlen(atstrJob) + MAX_PRINTED_DIGITS(pData->dwJobID) + 1; LPTSTR lptstrPrinterName = (LPTSTR) ::malloc(dwcChBuff * sizeof(TCHAR)); if (lptstrPrinterName != NULL) { if (::StringCchPrintf(lptstrPrinterName, dwcChBuff, TEXT("%ls%ls%d"), pData->lptstrPrinterNameFromOpenData, atstrJob, pData->dwJobID) == S_OK) { HANDLE hPrinter; BOOL b = ::OpenPrinter(lptstrPrinterName, &hPrinter, NULL); if (b) { if(PRSpoolerDataFile::WritePrintProcessorData(pData->ppp.atstrFullTempFileName, hPrinter)) { bRetValue = TRUE; //7/7 DEBUG/FIX MOVED //PostMessage(pData->ppp.hwndPreviewApp, WM_TEMPFILEWRITTEN, 0, 0); pData->bTempFileWritten = TRUE; } ::ClosePrinter(hPrinter); } // OpenPrinter SUCCESS } // if (::StringCchPrintf(...) == S_OK) free(lptstrPrinterName); } // if (lptstrPrinterName != NULL) // 6/25 DEBUG / FIX#if 0 HANDLE hspl = ::GdiGetSpoolFileHandle( pData->lptstrPrinterNameFromOpenData, pData->pdm, pData->lptstrDocName ); if (hspl != NULL) { uint nPage = ::GdiGetPageCount( hspl ); for(uint k = 0; k < nPage; ++k) { PDEVMODE pdmCurrent, pdmLast; int k2; if (! ::GdiGetDevmodeForPage(hspl, k, &pdmCurrent, &pdmLast) ) { k2 = 0; ++k2; } ++k2; } ::GdiDeleteSpoolFileHandle( hspl ); }#endif return bRetValue;}BOOL ClosePrintProcessor( HANDLE hPrintProcessor ) { PPRPRINTDATA pData = (PPRPRINTDATA) hPrintProcessor; // 7/7 DEBUG/FIX if (pData->bTempFileWritten) { ::PostMessage(pData->ppp.hwndPreviewApp, WM_TEMPFILEWRITTEN, 0, 0); } ReleasePRPRINTDATA(pData); return TRUE;}VOID ReleasePRPRINTDATA(IN PPRPRINTDATA pData) { if (pData->lptstrPrinterNameFromOpenData != NULL) { free(pData->lptstrPrinterNameFromOpenData); } // 6/25 DEBUG / FIX free(pData->pdm); free(pData->lptstrDocName);}BOOL ControlPrintProcessor( HANDLE hPrintProcessor, DWORD Command ) { BOOL bRetValue = FALSE; switch (Command) { // 7/7 DEBUG/FIX TRY TO GET SPOOLER TO DELETE JOBS AFTER PRINT AS REQUESTED //case JOB_CONTROL_PAUSE: //case JOB_CONTROL_CANCEL: //case JOB_CONTROL_RESUME: case JOB_CONTROL_PAUSE: case JOB_CONTROL_RESUME: case JOB_CONTROL_CANCEL: case JOB_CONTROL_RESTART: case JOB_CONTROL_DELETE: case JOB_CONTROL_SENT_TO_PRINTER: case JOB_CONTROL_LAST_PAGE_EJECTED: bRetValue = TRUE; break; default: break; } return bRetValue;}DWORD GetPrintProcessorCapabilities( LPTSTR pValueName, DWORD dwAttributes, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) { LPWSTR *pDatatypes = gatstrDatatypes; DWORD dwDatatype = 0; DWORD dwReturn; PPRINTPROCESSOR_CAPS_1 ppcInfo; // Check for valid parameters. if ( !pcbNeeded || !pData || !pValueName) { dwReturn = ERROR_INVALID_PARAMETER; goto CleanUp; } *pcbNeeded = sizeof(PRINTPROCESSOR_CAPS_1); // Check for sufficient buffer. if (nSize < *pcbNeeded) { dwReturn = ERROR_MORE_DATA; goto CleanUp; } // Loop to find the index of the datatype. while (*pDatatypes) { if (!_wcsicmp(*pDatatypes,pValueName)) { break; } pDatatypes++; dwDatatype++; } ppcInfo = (PPRINTPROCESSOR_CAPS_1) pData; // Level is 1 for PRINTPROCESSOR_CAPS_1. ppcInfo->dwLevel = 1; switch (dwDatatype) { //case PRINTPROCESSOR_TYPE_RAW: //case PRINTPROCESSOR_TYPE_TEXT: case PRINTPROCESSOR_TYPE_EMF_50_1: case PRINTPROCESSOR_TYPE_EMF_50_2: case PRINTPROCESSOR_TYPE_EMF_50_3: // 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 = 0; // 0x0000812b; // for 1,2,4,6,9,16 up options. // ppcInfo->dwNumberOfCopies = 1; //0xffffffff; // maximum number of copies. // ppcInfo->dwPageOrderFlags = 0; //REVERSE_PRINT | BOOKLET_PRINT; //} ppcInfo->dwNupOptions = 1; ppcInfo->dwNumberOfCopies = 1; ppcInfo->dwPageOrderFlags = NORMAL_PRINT; break; default: // Should not happen since the spooler must check if the datatype is // supported before calling this print processor. dwReturn = ERROR_INVALID_DATATYPE; goto CleanUp; } dwReturn = ERROR_SUCCESS;CleanUp: return dwReturn;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -