1 /*
2  * PROJECT:     ReactOS Standard Print Processor
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Printing a job with RAW datatype
5  * COPYRIGHT:   Copyright 2015 Colin Finck (colin@reactos.org)
6  */
7 
8 #include "precomp.h"
9 
10 /**
11  * @name PrintRawJob
12  *
13  * @param pHandle
14  * Pointer to a WINPRINT_HANDLE structure containing information about this job.
15  *
16  * @param pwszPrinterAndJob
17  * String in the format "Printer, Job N" that is passed to OpenPrinterW to read from the spooled print job.
18  *
19  * @return
20  * An error code indicating success or failure.
21  */
22 DWORD
23 PrintRawJob(PWINPRINT_HANDLE pHandle, PWSTR pwszPrinterAndJob)
24 {
25     // Use a read buffer of 256 KB size like Windows does.
26     const DWORD cbReadBuffer = 262144;
27 
28     BOOL bStartedDoc = FALSE;
29     DOC_INFO_1W DocInfo1;
30     DWORD cbRead;
31     DWORD cbWritten;
32     DWORD dwErrorCode;
33     HANDLE hPrintJob;
34     HANDLE hPrintMonitor = NULL;
35     PBYTE pBuffer = NULL;
36 
37     // Open the spooled job to read from it.
38     if (!OpenPrinterW(pwszPrinterAndJob, &hPrintJob, NULL))
39     {
40         dwErrorCode = GetLastError();
41         ERR("OpenPrinterW failed for \"%S\" with error %lu!\n", pwszPrinterAndJob, GetLastError());
42         goto Cleanup;
43     }
44 
45     // Open a Print Monitor handle to write to it.
46     if (!OpenPrinterW(pHandle->pwszPrinterPort, &hPrintMonitor, NULL))
47     {
48         dwErrorCode = GetLastError();
49         ERR("OpenPrinterW failed for \"%S\" with error %lu!\n", pHandle->pwszPrinterPort, GetLastError());
50         goto Cleanup;
51     }
52 
53     // Fill the Document Information.
54     DocInfo1.pDatatype = pHandle->pwszDatatype;
55     DocInfo1.pDocName = pHandle->pwszDocumentName;
56     DocInfo1.pOutputFile = pHandle->pwszOutputFile;
57 
58     // Tell the Print Monitor that we're starting a new document.
59     if (!StartDocPrinterW(hPrintMonitor, 1, (PBYTE)&DocInfo1))
60     {
61         dwErrorCode = GetLastError();
62         ERR("StartDocPrinterW failed with error %lu!\n", GetLastError());
63         goto Cleanup;
64     }
65 
66     bStartedDoc = TRUE;
67 
68     // Allocate a read buffer on the heap. This would easily exceed the stack size.
69     pBuffer = DllAllocSplMem(cbReadBuffer);
70     if (!pBuffer)
71     {
72         dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
73         ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
74         goto Cleanup;
75     }
76 
77     // Loop as long as data is available.
78     while (ReadPrinter(hPrintJob, pBuffer, cbReadBuffer, &cbRead) && cbRead)
79     {
80         // Write it to the Print Monitor.
81         WritePrinter(hPrintMonitor, pBuffer, cbRead, &cbWritten);
82     }
83 
84     dwErrorCode = ERROR_SUCCESS;
85 
86 Cleanup:
87     if (pBuffer)
88         DllFreeSplMem(pBuffer);
89 
90     if (bStartedDoc)
91         EndDocPrinter(hPrintMonitor);
92 
93     if (hPrintMonitor)
94         ClosePrinter(hPrintMonitor);
95 
96     if (hPrintJob)
97         ClosePrinter(hPrintJob);
98 
99     return dwErrorCode;
100 }
101