1 /*
2 * PROJECT: ReactOS Standard Print Processor
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Main functions
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
6 */
7
8 #include "precomp.h"
9
10 // Local Constants
11 static PCWSTR _pwszDatatypes[] = {
12 L"RAW",
13 0
14 };
15
16
17 /**
18 * @name ClosePrintProcessor
19 *
20 * Closes a Print Processor Handle that has previously been opened through OpenPrintProcessor.
21 *
22 * @param hPrintProcessor
23 * The return value of a previous successful OpenPrintProcessor call.
24 *
25 * @return
26 * TRUE if the Print Processor Handle was successfully closed, FALSE otherwise.
27 * A more specific error code can be obtained through GetLastError.
28 */
29 BOOL WINAPI
ClosePrintProcessor(HANDLE hPrintProcessor)30 ClosePrintProcessor(HANDLE hPrintProcessor)
31 {
32 DWORD dwErrorCode;
33 PWINPRINT_HANDLE pHandle;
34
35 TRACE("ClosePrintProcessor(%p)\n", hPrintProcessor);
36
37 // Sanity checks
38 if (!hPrintProcessor)
39 {
40 dwErrorCode = ERROR_INVALID_HANDLE;
41 goto Cleanup;
42 }
43
44 pHandle = (PWINPRINT_HANDLE)hPrintProcessor;
45
46 // Free all structure fields for which memory has been allocated.
47 if (pHandle->pwszDatatype)
48 DllFreeSplStr(pHandle->pwszDatatype);
49
50 if (pHandle->pwszDocumentName)
51 DllFreeSplStr(pHandle->pwszDocumentName);
52
53 if (pHandle->pwszOutputFile)
54 DllFreeSplStr(pHandle->pwszOutputFile);
55
56 if (pHandle->pwszPrinterPort)
57 DllFreeSplStr(pHandle->pwszPrinterPort);
58
59 // Finally free the WINSPOOL_HANDLE structure itself.
60 DllFreeSplMem(pHandle);
61 dwErrorCode = ERROR_SUCCESS;
62
63 Cleanup:
64 SetLastError(dwErrorCode);
65 return (dwErrorCode == ERROR_SUCCESS);
66 }
67
68 BOOL WINAPI
ControlPrintProcessor(HANDLE hPrintProcessor,DWORD Command)69 ControlPrintProcessor(HANDLE hPrintProcessor, DWORD Command)
70 {
71 TRACE("ControlPrintProcessor(%p, %lu)\n", hPrintProcessor, Command);
72
73 UNIMPLEMENTED;
74 return FALSE;
75 }
76
77 /**
78 * @name EnumPrintProcessorDatatypesW
79 *
80 * Obtains an array of all datatypes supported by this Print Processor.
81 *
82 * @param pName
83 * Server Name. Ignored here, because every caller of EnumPrintProcessorDatatypesW is interested in this Print Processor's information.
84 *
85 * @param pPrintProcessorName
86 * Print Processor Name. Ignored here, because every caller of EnumPrintProcessorDatatypesW is interested in this Print Processor's information.
87 *
88 * @param Level
89 * The level of the structure supplied through pDatatypes. This must be 1.
90 *
91 * @param pDatatypes
92 * Pointer to the buffer that receives an array of DATATYPES_INFO_1W structures.
93 * Can be NULL if you just want to know the required size of the buffer.
94 *
95 * @param cbBuf
96 * Size of the buffer you supplied for pDatatypes, in bytes.
97 *
98 * @param pcbNeeded
99 * Pointer to a variable that receives the required size of the buffer for pDatatypes, in bytes.
100 * This parameter mustn't be NULL!
101 *
102 * @param pcReturned
103 * Pointer to a variable that receives the number of elements of the DATATYPES_INFO_1W array.
104 * This parameter mustn't be NULL!
105 *
106 * @return
107 * TRUE if we successfully copied the array into pDatatypes, FALSE otherwise.
108 * A more specific error code can be obtained through GetLastError.
109 */
110 BOOL WINAPI
EnumPrintProcessorDatatypesW(PWSTR pName,PWSTR pPrintProcessorName,DWORD Level,PBYTE pDatatypes,DWORD cbBuf,PDWORD pcbNeeded,PDWORD pcReturned)111 EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
112 {
113 DWORD cbDatatype;
114 DWORD dwDatatypeCount = 0;
115 DWORD dwOffsets[_countof(_pwszDatatypes)];
116 PCWSTR* pCurrentDatatype;
117 PDWORD pCurrentOffset = dwOffsets;
118
119 TRACE("EnumPrintProcessorDatatypesW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
120
121 // Sanity checks
122 if (Level != 1 || !pcbNeeded || !pcReturned)
123 return FALSE;
124
125 // Count the required buffer size and the number of datatypes.
126 *pcbNeeded = 0;
127 *pcReturned = 0;
128
129 for (pCurrentDatatype = _pwszDatatypes; *pCurrentDatatype; pCurrentDatatype++)
130 {
131 cbDatatype = (wcslen(*pCurrentDatatype) + 1) * sizeof(WCHAR);
132 *pcbNeeded += sizeof(DATATYPES_INFO_1W) + cbDatatype;
133
134 // Also calculate the offset in the output buffer of the pointer to this datatype string.
135 *pCurrentOffset = dwDatatypeCount * sizeof(DATATYPES_INFO_1W) + FIELD_OFFSET(DATATYPES_INFO_1W, pName);
136
137 dwDatatypeCount++;
138 pCurrentOffset++;
139 }
140
141 // Check if the supplied buffer is large enough.
142 if (cbBuf < *pcbNeeded)
143 {
144 SetLastError(ERROR_INSUFFICIENT_BUFFER);
145 return FALSE;
146 }
147
148 // Check if a buffer was supplied at all.
149 if (!pDatatypes)
150 {
151 SetLastError(ERROR_INVALID_PARAMETER);
152 return FALSE;
153 }
154
155 // Copy over all datatypes.
156 *pCurrentOffset = MAXDWORD;
157 PackStrings(_pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]);
158
159 *pcReturned = dwDatatypeCount;
160 return TRUE;
161 }
162
163
164 DWORD WINAPI
GetPrintProcessorCapabilities(PWSTR pValueName,DWORD dwAttributes,PBYTE pData,DWORD nSize,PDWORD pcbNeeded)165 GetPrintProcessorCapabilities(PWSTR pValueName, DWORD dwAttributes, PBYTE pData, DWORD nSize, PDWORD pcbNeeded)
166 {
167 TRACE("GetPrintProcessorCapabilities(%S, %lu, %p, %lu, %p)\n", pValueName, dwAttributes, pData, nSize, pcbNeeded);
168
169 UNIMPLEMENTED;
170 return 0;
171 }
172
173 /**
174 * @name OpenPrintProcessor
175 *
176 * Prepares this Print Processor for processing a document.
177 *
178 * @param pPrinterName
179 * String in the format "\\COMPUTERNAME\Port:, Port" that is passed to OpenPrinterW for writing to the Print Monitor on the specified port.
180 *
181 * @param pPrintProcessorOpenData
182 * Pointer to a PRINTPROCESSOROPENDATA structure containing details about the print job to be processed.
183 *
184 * @return
185 * A Print Processor handle on success or NULL in case of a failure. This handle has to be passed to PrintDocumentOnPrintProcessor to do the actual processing.
186 * A more specific error code can be obtained through GetLastError.
187 */
188 HANDLE WINAPI
OpenPrintProcessor(PWSTR pPrinterName,PPRINTPROCESSOROPENDATA pPrintProcessorOpenData)189 OpenPrintProcessor(PWSTR pPrinterName, PPRINTPROCESSOROPENDATA pPrintProcessorOpenData)
190 {
191 DWORD dwErrorCode;
192 HANDLE hReturnValue = NULL;
193 PWINPRINT_HANDLE pHandle = NULL;
194
195 TRACE("OpenPrintProcessor(%S, %p)\n", pPrinterName, pPrintProcessorOpenData);
196
197 // Sanity checks
198 // This time a datatype needs to be given. We can't fall back to a default here.
199 if (!pPrintProcessorOpenData || !pPrintProcessorOpenData->pDatatype || !*pPrintProcessorOpenData->pDatatype)
200 {
201 dwErrorCode = ERROR_INVALID_PARAMETER;
202 goto Cleanup;
203 }
204
205 // Create a new WINPRINT_HANDLE structure and fill the relevant fields.
206 pHandle = DllAllocSplMem(sizeof(WINPRINT_HANDLE));
207
208 // Check what datatype was given.
209 if (_wcsicmp(pPrintProcessorOpenData->pDatatype, L"RAW") == 0)
210 {
211 pHandle->Datatype = RAW;
212 }
213 else
214 {
215 dwErrorCode = ERROR_INVALID_DATATYPE;
216 goto Cleanup;
217 }
218
219 // Fill the relevant fields.
220 pHandle->dwJobID = pPrintProcessorOpenData->JobId;
221 pHandle->pwszDatatype = AllocSplStr(pPrintProcessorOpenData->pDatatype);
222 pHandle->pwszDocumentName = AllocSplStr(pPrintProcessorOpenData->pDocumentName);
223 pHandle->pwszOutputFile = AllocSplStr(pPrintProcessorOpenData->pOutputFile);
224 pHandle->pwszPrinterPort = AllocSplStr(pPrinterName);
225
226 // We were successful! Return the handle and don't let the cleanup routine free it.
227 dwErrorCode = ERROR_SUCCESS;
228 hReturnValue = pHandle;
229 pHandle = NULL;
230
231 Cleanup:
232 if (pHandle)
233 DllFreeSplMem(pHandle);
234
235 SetLastError(dwErrorCode);
236 return hReturnValue;
237 }
238
239 /**
240 * @name PrintDocumentOnPrintProcessor
241 *
242 * Prints a document on this Print Processor after a handle for the document has been opened through OpenPrintProcessor.
243 *
244 * @param hPrintProcessor
245 * The return value of a previous successful OpenPrintProcessor call.
246 *
247 * @param pDocumentName
248 * String in the format "Printer, Job N" describing the spooled job that is to be processed.
249 *
250 * @return
251 * TRUE if the document was successfully processed by this Print Processor, FALSE otherwise.
252 * A more specific error code can be obtained through GetLastError.
253 */
254 BOOL WINAPI
PrintDocumentOnPrintProcessor(HANDLE hPrintProcessor,PWSTR pDocumentName)255 PrintDocumentOnPrintProcessor(HANDLE hPrintProcessor, PWSTR pDocumentName)
256 {
257 DWORD dwErrorCode;
258 PWINPRINT_HANDLE pHandle;
259
260 TRACE("PrintDocumentOnPrintProcessor(%p, %S)\n", hPrintProcessor, pDocumentName);
261
262 // Sanity checks
263 if (!hPrintProcessor)
264 {
265 dwErrorCode = ERROR_INVALID_HANDLE;
266 goto Cleanup;
267 }
268
269 pHandle = (PWINPRINT_HANDLE)hPrintProcessor;
270
271 // Call the corresponding Print function for the datatype.
272 if (pHandle->Datatype == RAW)
273 dwErrorCode = PrintRawJob(pHandle, pDocumentName);
274
275 Cleanup:
276 SetLastError(dwErrorCode);
277 return (dwErrorCode == ERROR_SUCCESS);
278 }
279