// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved. #include "stdafx.h" /*++ Routine Name: CreatePrintJobWithImagePassThrough Routine Description: This routine creates a print job for the "Microsoft XPS Document Writer" printer. A .jpg image is sent using an image escape. A fixed page XAML is sent that references the image. Arguments: Return Value: S_OK if successful, E_* if there is an error --*/ HRESULT CreatePrintJobWithImagePassThrough( VOID ) { HDC hdcMXDW = NULL; HRESULT hr = S_OK; PTPC_STATE_INFO si = {0}; IStream *pPTStream = NULL; PBYTE pbPTBuf = NULL; DWORD cbPTBuf = 0; PBYTE pEscData = NULL; DWORD cbEscData = 0; BOOL bStartPageSent = FALSE; BOOL bStartDocSent = FALSE; PBYTE pImgEscData = NULL; DWORD cbImgEscData = 0; CHAR szURI[MAX_PATH] = "/Documents/1/Resources/Images/image1.jpg"; LPSTR pFixedPage = "" "" ""; hr = StringCchCopy(si.szPrinterName, CCHOF(si.szPrinterName), gszPrinterName); if ( SUCCEEDED(hr) ) { GetUserPrintTicketStream(&si, &pPTStream); } if ( SUCCEEDED(hr) ) { hr = ConvertPTStreamToBuffer(pPTStream, &pbPTBuf, &cbPTBuf ); } // Create Print Ticket Escape for sending to Printer if ( SUCCEEDED(hr) ) { hr = PutTogetherEscapeStructureForPrintTicket( MXDCOP_PRINTTICKET_FIXED_DOC, pbPTBuf, cbPTBuf, &pEscData, &cbEscData); } // // Make sure the printer is installed and we can create its DC. // if (SUCCEEDED (hr) ) { hdcMXDW = CreateDC( NULL, si.szPrinterName, NULL, NULL); if(NULL == hdcMXDW) { DWORD dwLastError = GetLastError(); vFormatAndPrint(IDS_APP_CREATEDC_FAILED); if ( ERROR_INVALID_PRINTER_NAME == dwLastError ) { vFormatAndPrint(IDS_APP_MXDWPRINTER_NOTINSTALLED); } hr = HRESULT_FROM_WIN32(dwLastError); } } // // Make sure driver is a XPSDrv driver. i.e. it can accept XPS content. // if (SUCCEEDED (hr) ) { hr = IsXPSCapableDriver(hdcMXDW); } // // Send the Print Ticket // If return value is S_OK, it means driver is XPS capable // If return value is S_FALSE, it means driver is not XPS capable // If return value is E_FAIL, it means something bad happened // while we were querying the driver. // if (S_OK != hr) { vFormatAndPrint(IDS_APP_XPS_CAPABLE_PRINTER_NOTINSTALLED); hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); } else { DOCINFO DocInfo = { sizeof(DOCINFO), L"Fixed Page PrintTicket Sample", // Title of the print job NULL, // Not specifying output file. Determined by Printer NULL, // Not specifying data type. 0 }; if( StartDoc(hdcMXDW, &DocInfo) > 0) { bStartDocSent = TRUE; } else { // Sometimes StartDoc fails if the specified output file cannot be opened. // Sometimes it happens when a viewer is viewing the file, while the driver // is trying to write to it. hr = HRESULT_FROM_WIN32(GetLastError()); } } if ( SUCCEEDED (hr) ) { if( StartPage(hdcMXDW) > 0) { bStartPageSent = TRUE; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } } // Send Print Ticket for the above page if ( SUCCEEDED (hr) ) { if( ExtEscape(hdcMXDW, MXDC_ESCAPE, cbEscData, (LPCSTR) pEscData, 0, NULL) <= 0 ) { hr = HRESULT_FROM_WIN32(GetLastError()); } } // Send Image as an escape // Note: Here the image has been including within the .exe as a resource. This makes it // easier to distribute the .exe as a single package without the need to bundle an extra .jpg file. // But in real world, you'll likely need to load the .jpg file separately. if ( SUCCEEDED(hr) ) { DWORD cbImage = 0; LPVOID pImage = NULL; HRSRC hrsrc = FindResource(NULL, L"#201", L"JPGIMAGE"); if ( NULL != hrsrc ) { cbImage = SizeofResource(NULL, hrsrc); HGLOBAL hResData = LoadResource(NULL, hrsrc); if ( NULL != hResData) { pImage = LockResource(hResData); } } else { hr = HRESULT_FROM_WIN32(GetLastError() ); } if ( SUCCEEDED(hr) ) { hr = PutTogetherEscapeStructureForImage( MXDCOP_SET_S0PAGE_RESOURCE, (PBYTE)pImage, cbImage, szURI, &pImgEscData, &cbImgEscData); } } // // Send the image using escape created above // if ( SUCCEEDED (hr) ) { if( ExtEscape(hdcMXDW, MXDC_ESCAPE, cbImgEscData, (LPCSTR) pImgEscData, 0, NULL) <= 0 ) { vFormatAndPrint(IDS_APP_EXTESCAPE_FAILED); hr = HRESULT_FROM_WIN32(GetLastError()); } } // // Send XAML to reference the image just sent // if ( SUCCEEDED(hr) ) { size_t cbFixedPage = 0; PBYTE pFixedPageEscData = NULL; DWORD cbFixedPageEscData = 0; cbFixedPage = strlen(pFixedPage); if ( SUCCEEDED(hr) ) { hr = PutTogetherEscapeStructureForFixedPage( MXDCOP_SET_S0PAGE, (PBYTE)pFixedPage, (DWORD)cbFixedPage, &pFixedPageEscData, &cbFixedPageEscData); } if ( SUCCEEDED (hr) ) { if( ExtEscape(hdcMXDW, MXDC_ESCAPE, cbFixedPageEscData, (LPCSTR) pFixedPageEscData, 0, NULL) <= 0 ) { vFormatAndPrint(IDS_APP_EXTESCAPE_FAILED); hr = HRESULT_FROM_WIN32(GetLastError()); } } } if (bStartPageSent) { EndPage(hdcMXDW); } if ( bStartDocSent) { EndDoc(hdcMXDW); } // Clean up if(pEscData != NULL) { MemFree (pEscData); pEscData = NULL; } if ( NULL != pbPTBuf ) { CoTaskMemFree(pbPTBuf); pbPTBuf = NULL; } if ( NULL != pPTStream ) { pPTStream->Release(); pPTStream = NULL; } if(hdcMXDW != NULL) { DeleteDC(hdcMXDW); hdcMXDW = NULL; } RelaseStateInfoContents(&si); return hr; }