[WINSPOOL] Add tracing to all exported APIs.
[reactos.git] / win32ss / printing / base / winspool / printerdata.c
1 /*
2 * PROJECT: ReactOS Spooler API
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Functions related to Printer Configuration Data
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
6 */
7
8 #include "precomp.h"
9
10 LONG WINAPI
11 AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput)
12 {
13 TRACE("AdvancedDocumentPropertiesW(%p, %p, %S, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput);
14 UNIMPLEMENTED;
15 return FALSE;
16 }
17
18 DWORD WINAPI
19 GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
20 {
21 TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
22 return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
23 }
24
25 DWORD WINAPI
26 GetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
27 {
28 DWORD cbUnicodeData;
29 DWORD cch;
30 DWORD dwReturnValue;
31 DWORD dwType;
32 POSVERSIONINFOEXA pInfoA;
33 POSVERSIONINFOEXW pInfoW;
34 PVOID pUnicodeData = NULL;
35 PWSTR pwszKeyName = NULL;
36 PWSTR pwszValueName = NULL;
37
38 TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
39
40 if (pKeyName)
41 {
42 // Convert pKeyName to a Unicode string pwszKeyName
43 cch = strlen(pKeyName);
44
45 pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
46 if (!pwszKeyName)
47 {
48 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
49 ERR("HeapAlloc failed!\n");
50 goto Cleanup;
51 }
52
53 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
54 }
55
56 if (pValueName)
57 {
58 // Convert pValueName to a Unicode string pwszValueName
59 cch = strlen(pValueName);
60
61 pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
62 if (!pwszValueName)
63 {
64 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
65 ERR("HeapAlloc failed!\n");
66 goto Cleanup;
67 }
68
69 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
70 }
71
72 // We need the data type information, even if no pData was passed.
73 if (!pType)
74 pType = &dwType;
75
76 // Call GetPrinterDataExW for the first time.
77 // If we're lucky, the supplied buffer is already large enough and we don't need to do the expensive RPC call a second time.
78 dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, pType, pData, nSize, pcbNeeded);
79
80 // If a critical error occurred, just return it. We cannot do anything else in this case.
81 if (dwReturnValue != ERROR_SUCCESS && dwReturnValue != ERROR_MORE_DATA)
82 goto Cleanup;
83
84 // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size.
85 cbUnicodeData = *pcbNeeded;
86
87 if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
88 {
89 // This is a string that needs to be converted from Unicode to ANSI.
90 // Output the required buffer size for the ANSI string.
91 *pcbNeeded /= sizeof(WCHAR);
92 }
93 else if (*pType == REG_NONE)
94 {
95 if (cbUnicodeData == sizeof(OSVERSIONINFOW) && wcsicmp(pwszValueName, SPLREG_OS_VERSION) == 0)
96 {
97 // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA.
98 *pcbNeeded = sizeof(OSVERSIONINFOA);
99 }
100 else if (cbUnicodeData == sizeof(OSVERSIONINFOEXW) && wcsicmp(pwszValueName, SPLREG_OS_VERSIONEX) == 0)
101 {
102 // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA.
103 *pcbNeeded = sizeof(OSVERSIONINFOEXA);
104 }
105 else
106 {
107 // Other REG_NONE value, nothing to do.
108 goto Cleanup;
109 }
110 }
111
112 // Check if the supplied buffer is large enough for the ANSI data.
113 if (nSize < *pcbNeeded)
114 {
115 dwReturnValue = ERROR_MORE_DATA;
116 goto Cleanup;
117 }
118
119 // Allocate a temporary buffer for the Unicode data.
120 pUnicodeData = HeapAlloc(hProcessHeap, 0, cbUnicodeData);
121 if (!pUnicodeData)
122 {
123 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
124 ERR("HeapAlloc failed!\n");
125 goto Cleanup;
126 }
127
128 if (dwReturnValue == ERROR_SUCCESS)
129 {
130 // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string,
131 // so the Unicode string has been copied into pData. Copy it to pUnicodeData.
132 CopyMemory(pUnicodeData, pData, cbUnicodeData);
133 }
134 else
135 {
136 // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string.
137 // We have to call GetPrinterDataExW again with the temporary buffer.
138 dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, NULL, (PBYTE)pUnicodeData, cbUnicodeData, &cbUnicodeData);
139 if (dwReturnValue != ERROR_SUCCESS)
140 goto Cleanup;
141 }
142
143 if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
144 {
145 // Convert the Unicode string to ANSI.
146 WideCharToMultiByte(CP_ACP, 0, (PWSTR)pUnicodeData, -1, (PSTR)pData, *pcbNeeded, NULL, NULL);
147 }
148 else
149 {
150 // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW.
151 // Copy the fields and convert the Unicode CSD Version string to ANSI.
152 pInfoW = (POSVERSIONINFOEXW)pUnicodeData;
153 pInfoA = (POSVERSIONINFOEXA)pData;
154 pInfoA->dwMajorVersion = pInfoW->dwMajorVersion;
155 pInfoA->dwMinorVersion = pInfoW->dwMinorVersion;
156 pInfoA->dwBuildNumber = pInfoW->dwBuildNumber;
157 pInfoA->dwPlatformId = pInfoW->dwPlatformId;
158 WideCharToMultiByte(CP_ACP, 0, pInfoW->szCSDVersion, -1, pInfoA->szCSDVersion, sizeof(pInfoA->szCSDVersion), NULL, NULL);
159
160 if (cbUnicodeData == sizeof(OSVERSIONINFOW))
161 {
162 pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
163 }
164 else
165 {
166 pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
167 pInfoA->wServicePackMajor = pInfoW->wServicePackMajor;
168 pInfoA->wServicePackMinor = pInfoW->wServicePackMinor;
169 pInfoA->wSuiteMask = pInfoW->wSuiteMask;
170 pInfoA->wProductType = pInfoW->wProductType;
171 pInfoA->wReserved = pInfoW->wReserved;
172 }
173 }
174
175 Cleanup:
176 if (pwszKeyName)
177 HeapFree(hProcessHeap, 0, pwszKeyName);
178
179 if (pwszValueName)
180 HeapFree(hProcessHeap, 0, pwszValueName);
181
182 if (pUnicodeData)
183 HeapFree(hProcessHeap, 0, pUnicodeData);
184
185 return dwReturnValue;
186 }
187
188 DWORD WINAPI
189 GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
190 {
191 const WCHAR wszEmptyString[] = L"";
192
193 BYTE DummyData;
194 DWORD dwErrorCode;
195 DWORD dwType = REG_NONE;
196 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
197
198 TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
199
200 // Sanity checks
201 if (!pHandle)
202 return ERROR_INVALID_HANDLE;
203
204 // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way),
205 // Windows does it differently for GetPrinterDataExW and points them to empty variables.
206 if (!pKeyName)
207 pKeyName = wszEmptyString;
208
209 if (!pType)
210 pType = &dwType;
211
212 if (!pData && !nSize)
213 pData = &DummyData;
214
215 // Do the RPC call
216 RpcTryExcept
217 {
218 dwErrorCode = _RpcGetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
219 }
220 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
221 {
222 dwErrorCode = RpcExceptionCode();
223 }
224 RpcEndExcept;
225
226 return dwErrorCode;
227 }
228
229 DWORD WINAPI
230 GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
231 {
232 TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
233 return GetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
234 }
235
236 DWORD WINAPI
237 SetPrinterDataA(HANDLE hPrinter, PSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
238 {
239 TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
240 return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type, pData, cbData);
241 }
242
243 DWORD WINAPI
244 SetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
245 {
246 DWORD cch;
247 DWORD dwReturnValue;
248 PWSTR pwszKeyName = NULL;
249 PWSTR pwszValueName = NULL;
250 PWSTR pUnicodeData = NULL;
251
252 TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
253
254 if (pKeyName)
255 {
256 // Convert pKeyName to a Unicode string pwszKeyName
257 cch = strlen(pKeyName);
258
259 pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
260 if (!pwszKeyName)
261 {
262 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
263 ERR("HeapAlloc failed!\n");
264 goto Cleanup;
265 }
266
267 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
268 }
269
270 if (pValueName)
271 {
272 // Convert pValueName to a Unicode string pwszValueName
273 cch = strlen(pValueName);
274
275 pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
276 if (!pwszValueName)
277 {
278 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
279 ERR("HeapAlloc failed!\n");
280 goto Cleanup;
281 }
282
283 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
284 }
285
286 if (Type == REG_SZ || Type == REG_MULTI_SZ || Type == REG_EXPAND_SZ)
287 {
288 // Convert pData to a Unicode string pUnicodeData.
289 pUnicodeData = HeapAlloc(hProcessHeap, 0, cbData * sizeof(WCHAR));
290 if (!pUnicodeData)
291 {
292 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
293 ERR("HeapAlloc failed!\n");
294 goto Cleanup;
295 }
296
297 MultiByteToWideChar(CP_ACP, 0, (PCSTR)pData, -1, pUnicodeData, cbData);
298
299 pData = (PBYTE)pUnicodeData;
300 cbData *= sizeof(WCHAR);
301 }
302
303 dwReturnValue = SetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, Type, pData, cbData);
304
305 Cleanup:
306 if (pwszKeyName)
307 HeapFree(hProcessHeap, 0, pwszKeyName);
308
309 if (pwszValueName)
310 HeapFree(hProcessHeap, 0, pwszValueName);
311
312 if (pUnicodeData)
313 HeapFree(hProcessHeap, 0, pUnicodeData);
314
315 return dwReturnValue;
316 }
317
318 DWORD WINAPI
319 SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
320 {
321 const WCHAR wszEmptyString[] = L"";
322
323 DWORD dwErrorCode;
324 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
325
326 TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
327
328 // Sanity checks
329 if (!pHandle)
330 return ERROR_INVALID_HANDLE;
331
332 if (!pKeyName)
333 pKeyName = wszEmptyString;
334
335 // Do the RPC call
336 RpcTryExcept
337 {
338 dwErrorCode = _RpcSetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, Type, pData, cbData);
339 }
340 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
341 {
342 dwErrorCode = RpcExceptionCode();
343 }
344 RpcEndExcept;
345
346 return dwErrorCode;
347 }
348
349 DWORD WINAPI
350 SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
351 {
352 TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
353 return SetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, Type, pData, cbData);
354 }