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)
11 static DWORD dwDriverInfo1Offsets
[] = {
12 FIELD_OFFSET(DRIVER_INFO_1W
, pName
),
16 static DWORD dwDriverInfo2Offsets
[] = {
17 FIELD_OFFSET(DRIVER_INFO_2W
, pName
),
18 FIELD_OFFSET(DRIVER_INFO_2W
, pEnvironment
),
19 FIELD_OFFSET(DRIVER_INFO_2W
, pDriverPath
),
20 FIELD_OFFSET(DRIVER_INFO_2W
, pDataFile
),
21 FIELD_OFFSET(DRIVER_INFO_2W
, pConfigFile
),
25 static DWORD dwDriverInfo3Offsets
[] = {
26 FIELD_OFFSET(DRIVER_INFO_3W
, pName
),
27 FIELD_OFFSET(DRIVER_INFO_3W
, pEnvironment
),
28 FIELD_OFFSET(DRIVER_INFO_3W
, pDriverPath
),
29 FIELD_OFFSET(DRIVER_INFO_3W
, pDataFile
),
30 FIELD_OFFSET(DRIVER_INFO_3W
, pConfigFile
),
31 FIELD_OFFSET(DRIVER_INFO_3W
, pHelpFile
),
32 FIELD_OFFSET(DRIVER_INFO_3W
, pDependentFiles
),
33 FIELD_OFFSET(DRIVER_INFO_3W
, pMonitorName
),
34 FIELD_OFFSET(DRIVER_INFO_3W
, pDefaultDataType
),
38 static DWORD dwDriverInfo4Offsets
[] = {
39 FIELD_OFFSET(DRIVER_INFO_4W
, pName
),
40 FIELD_OFFSET(DRIVER_INFO_4W
, pEnvironment
),
41 FIELD_OFFSET(DRIVER_INFO_4W
, pDriverPath
),
42 FIELD_OFFSET(DRIVER_INFO_4W
, pDataFile
),
43 FIELD_OFFSET(DRIVER_INFO_4W
, pConfigFile
),
44 FIELD_OFFSET(DRIVER_INFO_4W
, pHelpFile
),
45 FIELD_OFFSET(DRIVER_INFO_4W
, pDependentFiles
),
46 FIELD_OFFSET(DRIVER_INFO_4W
, pMonitorName
),
47 FIELD_OFFSET(DRIVER_INFO_4W
, pDefaultDataType
),
48 FIELD_OFFSET(DRIVER_INFO_4W
, pszzPreviousNames
),
52 static DWORD dwDriverInfo5Offsets
[] = {
53 FIELD_OFFSET(DRIVER_INFO_5W
, pName
),
54 FIELD_OFFSET(DRIVER_INFO_5W
, pEnvironment
),
55 FIELD_OFFSET(DRIVER_INFO_5W
, pDriverPath
),
56 FIELD_OFFSET(DRIVER_INFO_5W
, pDataFile
),
57 FIELD_OFFSET(DRIVER_INFO_5W
, pConfigFile
),
62 ToMultiSz(LPWSTR pString
)
74 _LocalGetPrinterDriverLevel1(PLOCAL_PRINTER_HANDLE pHandle
, PDRIVER_INFO_1W
* ppDriverInfo
, PBYTE
* ppDriverInfoEnd
, PDWORD pcbNeeded
)
77 PCWSTR pwszStrings
[1];
79 /* This value is only here to send something, I have not verified if it is actually correct */
80 pwszStrings
[0] = pHandle
->pPrinter
->pwszPrinterDriver
;
82 // Calculate the string lengths.
85 for (n
= 0; n
< _countof(pwszStrings
); ++n
)
87 *pcbNeeded
+= (wcslen(pwszStrings
[n
]) + 1) * sizeof(WCHAR
);
90 *pcbNeeded
+= sizeof(DRIVER_INFO_1W
);
95 // Finally copy the structure and advance to the next one in the output buffer.
96 *ppDriverInfoEnd
= PackStrings(pwszStrings
, (PBYTE
)(*ppDriverInfo
), dwDriverInfo1Offsets
, *ppDriverInfoEnd
);
101 _LocalGetPrinterDriverLevel2(PLOCAL_PRINTER_HANDLE pHandle
, PDRIVER_INFO_2W
* ppDriverInfo
, PBYTE
* ppDriverInfoEnd
, PDWORD pcbNeeded
)
104 PCWSTR pwszStrings
[5];
106 /* Clearly these things should not be hardcoded, so when it is needed, someone can add meaningfull values here */
107 pwszStrings
[0] = pHandle
->pPrinter
->pwszPrinterDriver
; // pName
108 pwszStrings
[1] = wszCurrentEnvironment
; // pEnvironment
109 pwszStrings
[2] = L
"c:\\reactos\\system32\\localspl.dll"; // pDriverPath
110 pwszStrings
[3] = L
"c:\\reactos\\system32\\localspl.dll"; // pDataFile
111 pwszStrings
[4] = L
"c:\\reactos\\system32\\localspl.dll"; // pConfigFile
113 // Calculate the string lengths.
116 for (n
= 0; n
< _countof(pwszStrings
); ++n
)
118 *pcbNeeded
+= (wcslen(pwszStrings
[n
]) + 1) * sizeof(WCHAR
);
121 *pcbNeeded
+= sizeof(DRIVER_INFO_2W
);
125 (*ppDriverInfo
)->cVersion
= 3;
127 // Finally copy the structure and advance to the next one in the output buffer.
128 *ppDriverInfoEnd
= PackStrings(pwszStrings
, (PBYTE
)(*ppDriverInfo
), dwDriverInfo2Offsets
, *ppDriverInfoEnd
);
133 _LocalGetPrinterDriverLevel3(PLOCAL_PRINTER_HANDLE pHandle
, PDRIVER_INFO_3W
* ppDriverInfo
, PBYTE
* ppDriverInfoEnd
, PDWORD pcbNeeded
)
136 PCWSTR pwszStrings
[9];
138 /* Clearly these things should not be hardcoded, so when it is needed, someone can add meaningfull values here */
139 pwszStrings
[0] = pHandle
->pPrinter
->pwszPrinterDriver
; // pName
140 pwszStrings
[1] = wszCurrentEnvironment
; // pEnvironment
141 pwszStrings
[2] = L
"c:\\reactos\\system32\\localspl.dll"; // pDriverPath
142 pwszStrings
[3] = L
"c:\\reactos\\system32\\localspl.dll"; // pDataFile
143 pwszStrings
[4] = L
"c:\\reactos\\system32\\printui.dll"; // pConfigFile
144 pwszStrings
[5] = L
""; // pHelpFile
145 pwszStrings
[6] = L
"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
146 pwszStrings
[7] = NULL
; // pMonitorName
147 pwszStrings
[8] = NULL
; // pDefaultDataType
150 // Calculate the string lengths.
153 for (n
= 0; n
< _countof(pwszStrings
); ++n
)
157 *pcbNeeded
+= (wcslen(pwszStrings
[n
]) + 1) * sizeof(WCHAR
);
161 *pcbNeeded
+= sizeof(DRIVER_INFO_3W
);
165 (*ppDriverInfo
)->cVersion
= 3;
167 // Finally copy the structure and advance to the next one in the output buffer.
168 *ppDriverInfoEnd
= PackStrings(pwszStrings
, (PBYTE
)(*ppDriverInfo
), dwDriverInfo3Offsets
, *ppDriverInfoEnd
);
169 ToMultiSz((*ppDriverInfo
)->pDependentFiles
);
174 _LocalGetPrinterDriverLevel4(PLOCAL_PRINTER_HANDLE pHandle
, PDRIVER_INFO_4W
* ppDriverInfo
, PBYTE
* ppDriverInfoEnd
, PDWORD pcbNeeded
)
177 PCWSTR pwszStrings
[10];
179 /* Clearly these things should not be hardcoded, so when it is needed, someone can add meaningfull values here */
180 pwszStrings
[0] = pHandle
->pPrinter
->pwszPrinterDriver
; // pName
181 pwszStrings
[1] = wszCurrentEnvironment
; // pEnvironment
182 pwszStrings
[2] = L
"c:\\reactos\\system32\\localspl.dll"; // pDriverPath
183 pwszStrings
[3] = L
"c:\\reactos\\system32\\localspl.dll"; // pDataFile
184 pwszStrings
[4] = L
"c:\\reactos\\system32\\printui.dll"; // pConfigFile
185 pwszStrings
[5] = L
""; // pHelpFile
186 pwszStrings
[6] = L
"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
187 pwszStrings
[7] = NULL
; // pMonitorName
188 pwszStrings
[8] = NULL
; // pDefaultDataType
189 pwszStrings
[9] = NULL
; // pszzPreviousNames
191 // Calculate the string lengths.
194 for (n
= 0; n
< _countof(pwszStrings
); ++n
)
198 *pcbNeeded
+= (wcslen(pwszStrings
[n
]) + 1) * sizeof(WCHAR
);
202 *pcbNeeded
+= sizeof(DRIVER_INFO_4W
);
206 (*ppDriverInfo
)->cVersion
= 3;
208 // Finally copy the structure and advance to the next one in the output buffer.
209 *ppDriverInfoEnd
= PackStrings(pwszStrings
, (PBYTE
)(*ppDriverInfo
), dwDriverInfo4Offsets
, *ppDriverInfoEnd
);
210 ToMultiSz((*ppDriverInfo
)->pDependentFiles
);
215 _LocalGetPrinterDriverLevel5(PLOCAL_PRINTER_HANDLE pHandle
, PDRIVER_INFO_5W
* ppDriverInfo
, PBYTE
* ppDriverInfoEnd
, PDWORD pcbNeeded
)
218 PCWSTR pwszStrings
[5];
220 /* Clearly these things should not be hardcoded, so when it is needed, someone can add meaningfull values here */
221 pwszStrings
[0] = pHandle
->pPrinter
->pwszPrinterDriver
; // pName
222 pwszStrings
[1] = wszCurrentEnvironment
; // pEnvironment
223 pwszStrings
[2] = L
"c:\\reactos\\system32\\localspl.dll"; // pDriverPath UniDrv.dll
224 pwszStrings
[3] = L
"c:\\reactos\\system32\\localspl.dll"; // pDataFile.ppd
225 pwszStrings
[4] = L
"c:\\reactos\\system32\\printui.dll"; // pConfigFile UniDrvUI.dll
227 // Calculate the string lengths.
230 for (n
= 0; n
< _countof(pwszStrings
); ++n
)
234 *pcbNeeded
+= (wcslen(pwszStrings
[n
]) + 1) * sizeof(WCHAR
);
238 *pcbNeeded
+= sizeof(DRIVER_INFO_5W
);
242 (*ppDriverInfo
)->cVersion
= 3;
243 // Driver attributes, like UMPD/KMPD.
244 (*ppDriverInfo
)->dwDriverAttributes
= 0; // UMPD/KMPD, So where are they?
245 // Number of times the configuration file for this driver has been upgraded or downgraded since the last spooler restart.
246 (*ppDriverInfo
)->dwConfigVersion
= 1;
247 // Number of times the driver file for this driver has been upgraded or downgraded since the last spooler restart.
248 (*ppDriverInfo
)->dwDriverVersion
= 1;
250 // Finally copy the structure and advance to the next one in the output buffer.
251 *ppDriverInfoEnd
= PackStrings(pwszStrings
, (PBYTE
)(*ppDriverInfo
), dwDriverInfo5Offsets
, *ppDriverInfoEnd
);
255 BOOL WINAPI
LocalGetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
, DWORD Level
, LPBYTE pDriverInfo
, DWORD cbBuf
, LPDWORD pcbNeeded
)
258 PBYTE pEnd
= &pDriverInfo
[cbBuf
];
259 PLOCAL_HANDLE pHandle
;
260 PLOCAL_PRINTER_HANDLE pPrinterHandle
;
262 TRACE("LocalGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter
, pEnvironment
, Level
, pDriverInfo
, cbBuf
, pcbNeeded
);
264 // Check if this is a printer handle.
265 pHandle
= (PLOCAL_HANDLE
)hPrinter
;
266 if (pHandle
->HandleType
!= HandleType_Printer
)
268 dwErrorCode
= ERROR_INVALID_HANDLE
;
272 pPrinterHandle
= (PLOCAL_PRINTER_HANDLE
)pHandle
->pSpecificHandle
;
274 // Only support 5 levels for now
277 // The caller supplied an invalid level.
278 dwErrorCode
= ERROR_INVALID_LEVEL
;
282 // Count the required buffer size.
286 _LocalGetPrinterDriverLevel1(pPrinterHandle
, NULL
, NULL
, pcbNeeded
);
288 _LocalGetPrinterDriverLevel2(pPrinterHandle
, NULL
, NULL
, pcbNeeded
);
290 _LocalGetPrinterDriverLevel3(pPrinterHandle
, NULL
, NULL
, pcbNeeded
);
292 _LocalGetPrinterDriverLevel4(pPrinterHandle
, NULL
, NULL
, pcbNeeded
);
294 _LocalGetPrinterDriverLevel5(pPrinterHandle
, NULL
, NULL
, pcbNeeded
);
296 // Check if the supplied buffer is large enough.
297 if (cbBuf
< *pcbNeeded
)
299 dwErrorCode
= ERROR_INSUFFICIENT_BUFFER
;
303 // Copy over the information.
304 pEnd
= &pDriverInfo
[*pcbNeeded
];
307 _LocalGetPrinterDriverLevel1(pPrinterHandle
, (PDRIVER_INFO_1W
*)&pDriverInfo
, &pEnd
, NULL
);
309 _LocalGetPrinterDriverLevel2(pPrinterHandle
, (PDRIVER_INFO_2W
*)&pDriverInfo
, &pEnd
, NULL
);
311 _LocalGetPrinterDriverLevel3(pPrinterHandle
, (PDRIVER_INFO_3W
*)&pDriverInfo
, &pEnd
, NULL
);
313 _LocalGetPrinterDriverLevel4(pPrinterHandle
, (PDRIVER_INFO_4W
*)&pDriverInfo
, &pEnd
, NULL
);
315 _LocalGetPrinterDriverLevel5(pPrinterHandle
, (PDRIVER_INFO_5W
*)&pDriverInfo
, &pEnd
, NULL
);
317 dwErrorCode
= ERROR_SUCCESS
;
320 SetLastError(dwErrorCode
);
321 return (dwErrorCode
== ERROR_SUCCESS
);