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)
12 static DWORD dwDriverInfo1Offsets
[] = {
13 FIELD_OFFSET(DRIVER_INFO_1W
, pName
),
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
),
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
),
40 ToMultiSz(LPWSTR pString
)
52 _LocalGetPrinterDriverLevel1(PLOCAL_PRINTER_HANDLE pHandle
, PDRIVER_INFO_1W
* ppDriverInfo
, PBYTE
* ppDriverInfoEnd
, PDWORD pcbNeeded
)
55 PCWSTR pwszStrings
[1];
57 /* This value is only here to send something, I have not verified if it is actually correct */
58 pwszStrings
[0] = pHandle
->pPrinter
->pwszPrinterDriver
;
60 // Calculate the string lengths.
63 for (n
= 0; n
< _countof(pwszStrings
); ++n
)
65 *pcbNeeded
+= (wcslen(pwszStrings
[n
]) + 1) * sizeof(WCHAR
);
68 *pcbNeeded
+= sizeof(DRIVER_INFO_1W
);
73 // Finally copy the structure and advance to the next one in the output buffer.
74 *ppDriverInfoEnd
= PackStrings(pwszStrings
, (PBYTE
)(*ppDriverInfo
), dwDriverInfo1Offsets
, *ppDriverInfoEnd
);
79 _LocalGetPrinterDriverLevel2(PLOCAL_PRINTER_HANDLE pHandle
, PDRIVER_INFO_2W
* ppDriverInfo
, PBYTE
* ppDriverInfoEnd
, PDWORD pcbNeeded
)
82 PCWSTR pwszStrings
[5];
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
91 // Calculate the string lengths.
94 for (n
= 0; n
< _countof(pwszStrings
); ++n
)
96 *pcbNeeded
+= (wcslen(pwszStrings
[n
]) + 1) * sizeof(WCHAR
);
99 *pcbNeeded
+= sizeof(DRIVER_INFO_2W
);
103 (*ppDriverInfo
)->cVersion
= 3;
105 // Finally copy the structure and advance to the next one in the output buffer.
106 *ppDriverInfoEnd
= PackStrings(pwszStrings
, (PBYTE
)(*ppDriverInfo
), dwDriverInfo2Offsets
, *ppDriverInfoEnd
);
111 _LocalGetPrinterDriverLevel3(PLOCAL_PRINTER_HANDLE pHandle
, PDRIVER_INFO_3W
* ppDriverInfo
, PBYTE
* ppDriverInfoEnd
, PDWORD pcbNeeded
)
114 PCWSTR pwszStrings
[9];
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
128 // Calculate the string lengths.
131 for (n
= 0; n
< _countof(pwszStrings
); ++n
)
135 *pcbNeeded
+= (wcslen(pwszStrings
[n
]) + 1) * sizeof(WCHAR
);
139 *pcbNeeded
+= sizeof(DRIVER_INFO_3W
);
143 (*ppDriverInfo
)->cVersion
= 3;
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
);
152 BOOL WINAPI
LocalGetPrinterDriver(HANDLE hPrinter
, LPWSTR pEnvironment
, DWORD Level
, LPBYTE pDriverInfo
, DWORD cbBuf
, LPDWORD pcbNeeded
)
155 PBYTE pEnd
= &pDriverInfo
[cbBuf
];
156 PLOCAL_HANDLE pHandle
;
157 PLOCAL_PRINTER_HANDLE pPrinterHandle
;
159 TRACE("LocalGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter
, pEnvironment
, Level
, pDriverInfo
, cbBuf
, pcbNeeded
);
161 // Check if this is a printer handle.
162 pHandle
= (PLOCAL_HANDLE
)hPrinter
;
163 if (pHandle
->HandleType
!= HandleType_Printer
)
165 dwErrorCode
= ERROR_INVALID_HANDLE
;
169 pPrinterHandle
= (PLOCAL_PRINTER_HANDLE
)pHandle
->pSpecificHandle
;
171 // Only support 3 levels for now
174 // The caller supplied an invalid level.
175 dwErrorCode
= ERROR_INVALID_LEVEL
;
179 // Count the required buffer size.
183 _LocalGetPrinterDriverLevel1(pPrinterHandle
, NULL
, NULL
, pcbNeeded
);
185 _LocalGetPrinterDriverLevel2(pPrinterHandle
, NULL
, NULL
, pcbNeeded
);
187 _LocalGetPrinterDriverLevel3(pPrinterHandle
, NULL
, NULL
, pcbNeeded
);
189 // Check if the supplied buffer is large enough.
190 if (cbBuf
< *pcbNeeded
)
192 dwErrorCode
= ERROR_INSUFFICIENT_BUFFER
;
196 // Copy over the information.
197 pEnd
= &pDriverInfo
[*pcbNeeded
];
200 _LocalGetPrinterDriverLevel1(pPrinterHandle
, (PDRIVER_INFO_1W
*)&pDriverInfo
, &pEnd
, NULL
);
202 _LocalGetPrinterDriverLevel2(pPrinterHandle
, (PDRIVER_INFO_2W
*)&pDriverInfo
, &pEnd
, NULL
);
204 _LocalGetPrinterDriverLevel3(pPrinterHandle
, (PDRIVER_INFO_3W
*)&pDriverInfo
, &pEnd
, NULL
);
206 dwErrorCode
= ERROR_SUCCESS
;
209 SetLastError(dwErrorCode
);
210 return (dwErrorCode
== ERROR_SUCCESS
);