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 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 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 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 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 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 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