1 /* 2 * PROJECT: ReactOS Local Spooler 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Functions for printer driver information 5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #include "precomp.h" 9 10 11 // Local Constants 12 static DWORD dwDriverInfo1Offsets[] = { 13 FIELD_OFFSET(DRIVER_INFO_1W, pName), 14 MAXDWORD 15 }; 16 17 static DWORD dwDriverInfo2Offsets[] = { 18 FIELD_OFFSET(DRIVER_INFO_2W, pName), 19 FIELD_OFFSET(DRIVER_INFO_2W, pEnvironment), 20 FIELD_OFFSET(DRIVER_INFO_2W, pDriverPath), 21 FIELD_OFFSET(DRIVER_INFO_2W, pDataFile), 22 FIELD_OFFSET(DRIVER_INFO_2W, pConfigFile), 23 MAXDWORD 24 }; 25 26 static DWORD dwDriverInfo3Offsets[] = { 27 FIELD_OFFSET(DRIVER_INFO_3W, pName), 28 FIELD_OFFSET(DRIVER_INFO_3W, pEnvironment), 29 FIELD_OFFSET(DRIVER_INFO_3W, pDriverPath), 30 FIELD_OFFSET(DRIVER_INFO_3W, pDataFile), 31 FIELD_OFFSET(DRIVER_INFO_3W, pConfigFile), 32 FIELD_OFFSET(DRIVER_INFO_3W, pHelpFile), 33 FIELD_OFFSET(DRIVER_INFO_3W, pDependentFiles), 34 FIELD_OFFSET(DRIVER_INFO_3W, pMonitorName), 35 FIELD_OFFSET(DRIVER_INFO_3W, pDefaultDataType), 36 MAXDWORD 37 }; 38 39 static void 40 ToMultiSz(LPWSTR pString) 41 { 42 while (*pString) 43 { 44 if (*pString == '|') 45 *pString = '\0'; 46 pString++; 47 } 48 } 49 50 51 static void 52 _LocalGetPrinterDriverLevel1(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_1W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 53 { 54 DWORD n; 55 PCWSTR pwszStrings[1]; 56 57 /* This value is only here to send something, I have not verified if it is actually correct */ 58 pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; 59 60 // Calculate the string lengths. 61 if (!ppDriverInfo) 62 { 63 for (n = 0; n < _countof(pwszStrings); ++n) 64 { 65 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 66 } 67 68 *pcbNeeded += sizeof(DRIVER_INFO_1W); 69 return; 70 } 71 72 73 // Finally copy the structure and advance to the next one in the output buffer. 74 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo1Offsets, *ppDriverInfoEnd); 75 (*ppDriverInfo)++; 76 } 77 78 static void 79 _LocalGetPrinterDriverLevel2(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_2W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 80 { 81 DWORD n; 82 PCWSTR pwszStrings[5]; 83 84 /* Clearly these things should not be hardcoded, so when it is needed, someone can add meaningfull values here */ 85 pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName 86 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment 87 pwszStrings[2] = L"c:\\reactos\\system32\\localspl.dll"; // pDriverPath 88 pwszStrings[3] = L"c:\\reactos\\system32\\localspl.dll"; // pDataFile 89 pwszStrings[4] = L"c:\\reactos\\system32\\localspl.dll"; // pConfigFile 90 91 // Calculate the string lengths. 92 if (!ppDriverInfo) 93 { 94 for (n = 0; n < _countof(pwszStrings); ++n) 95 { 96 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 97 } 98 99 *pcbNeeded += sizeof(DRIVER_INFO_2W); 100 return; 101 } 102 103 (*ppDriverInfo)->cVersion = 3; 104 105 // Finally copy the structure and advance to the next one in the output buffer. 106 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo2Offsets, *ppDriverInfoEnd); 107 (*ppDriverInfo)++; 108 } 109 110 static void 111 _LocalGetPrinterDriverLevel3(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_3W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 112 { 113 DWORD n; 114 PCWSTR pwszStrings[9]; 115 116 /* Clearly these things should not be hardcoded, so when it is needed, someone can add meaningfull values here */ 117 pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName 118 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment 119 pwszStrings[2] = L"c:\\reactos\\system32\\localspl.dll"; // pDriverPath 120 pwszStrings[3] = L"c:\\reactos\\system32\\localspl.dll"; // pDataFile 121 pwszStrings[4] = L"c:\\reactos\\system32\\printui.dll"; // pConfigFile 122 pwszStrings[5] = L""; // pHelpFile 123 pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator! 124 pwszStrings[7] = NULL; // pMonitorName 125 pwszStrings[8] = NULL; // pDefaultDataType 126 127 128 // Calculate the string lengths. 129 if (!ppDriverInfo) 130 { 131 for (n = 0; n < _countof(pwszStrings); ++n) 132 { 133 if (pwszStrings[n]) 134 { 135 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 136 } 137 } 138 139 *pcbNeeded += sizeof(DRIVER_INFO_3W); 140 return; 141 } 142 143 (*ppDriverInfo)->cVersion = 3; 144 145 // Finally copy the structure and advance to the next one in the output buffer. 146 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo3Offsets, *ppDriverInfoEnd); 147 ToMultiSz((*ppDriverInfo)->pDependentFiles); 148 (*ppDriverInfo)++; 149 } 150 151 152 BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded) 153 { 154 DWORD dwErrorCode; 155 PBYTE pEnd = &pDriverInfo[cbBuf]; 156 PLOCAL_HANDLE pHandle; 157 PLOCAL_PRINTER_HANDLE pPrinterHandle; 158 159 TRACE("LocalGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); 160 161 // Check if this is a printer handle. 162 pHandle = (PLOCAL_HANDLE)hPrinter; 163 if (pHandle->HandleType != HandleType_Printer) 164 { 165 dwErrorCode = ERROR_INVALID_HANDLE; 166 goto Cleanup; 167 } 168 169 pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; 170 171 // Only support 3 levels for now 172 if (Level > 3) 173 { 174 // The caller supplied an invalid level. 175 dwErrorCode = ERROR_INVALID_LEVEL; 176 goto Cleanup; 177 } 178 179 // Count the required buffer size. 180 *pcbNeeded = 0; 181 182 if (Level == 1) 183 _LocalGetPrinterDriverLevel1(pPrinterHandle, NULL, NULL, pcbNeeded); 184 else if (Level == 2) 185 _LocalGetPrinterDriverLevel2(pPrinterHandle, NULL, NULL, pcbNeeded); 186 else if (Level == 3) 187 _LocalGetPrinterDriverLevel3(pPrinterHandle, NULL, NULL, pcbNeeded); 188 189 // Check if the supplied buffer is large enough. 190 if (cbBuf < *pcbNeeded) 191 { 192 dwErrorCode = ERROR_INSUFFICIENT_BUFFER; 193 goto Cleanup; 194 } 195 196 // Copy over the information. 197 pEnd = &pDriverInfo[*pcbNeeded]; 198 199 if (Level == 1) 200 _LocalGetPrinterDriverLevel1(pPrinterHandle, (PDRIVER_INFO_1W*)&pDriverInfo, &pEnd, NULL); 201 else if (Level == 2) 202 _LocalGetPrinterDriverLevel2(pPrinterHandle, (PDRIVER_INFO_2W*)&pDriverInfo, &pEnd, NULL); 203 else if (Level == 3) 204 _LocalGetPrinterDriverLevel3(pPrinterHandle, (PDRIVER_INFO_3W*)&pDriverInfo, &pEnd, NULL); 205 206 dwErrorCode = ERROR_SUCCESS; 207 208 Cleanup: 209 SetLastError(dwErrorCode); 210 return (dwErrorCode == ERROR_SUCCESS); 211 } 212