⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prprint.cpp

📁 虚拟打印机
💻 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 + -