[NTOS:KE/x64] Handle NMI vs swapgs race condition
[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 AdvancedSetupDialog(HWND hWnd, INT Unknown, PDEVMODEA pDevModeInput, PDEVMODEA pDevModeOutput)
12 {
13 HANDLE hPrinter;
14 LONG Ret = -1;
15
16 TRACE("AdvancedSetupDialog(%p, %d, %p, %p)\n", hWnd, Unknown, pDevModeOutput, pDevModeInput);
17
18 if ( OpenPrinterA( (LPSTR)pDevModeInput->dmDeviceName, &hPrinter, NULL ) )
19 {
20 Ret = AdvancedDocumentPropertiesA( hWnd, hPrinter, (PSTR)pDevModeInput->dmDeviceName, pDevModeOutput, pDevModeInput );
21 ClosePrinter(hPrinter);
22 }
23 return Ret;
24 }
25
26 LONG WINAPI
27 AdvancedDocumentPropertiesA(HWND hWnd, HANDLE hPrinter, PSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput)
28 {
29 TRACE("AdvancedDocumentPropertiesA(%p, %p, %s, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput);
30 UNIMPLEMENTED;
31 return 0;
32 }
33
34 LONG WINAPI
35 AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput)
36 {
37 TRACE("AdvancedDocumentPropertiesW(%p, %p, %S, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput);
38 UNIMPLEMENTED;
39 return 0;
40 }
41
42 DWORD WINAPI
43 DeletePrinterDataA(HANDLE hPrinter, PSTR pValueName)
44 {
45 LPWSTR valuenameW = NULL;
46 INT len;
47 DWORD res;
48
49 TRACE("DeletePrinterDataA(%p, %s)\n", hPrinter, pValueName);
50
51 if (pValueName)
52 {
53 len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0);
54 valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
55 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len);
56 }
57
58 res = DeletePrinterDataW( hPrinter, valuenameW );
59
60 if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW);
61
62 return res;
63
64 }
65
66 DWORD WINAPI
67 DeletePrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PCSTR pValueName)
68 {
69 LPWSTR keynameW = NULL;
70 LPWSTR valuenameW = NULL;
71 INT len;
72 DWORD res;
73
74 TRACE("DeletePrinterDataExA(%p, %s, %s)\n", hPrinter, pKeyName, pValueName);
75
76 if (pKeyName)
77 {
78 len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0);
79 keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
80 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len);
81 }
82
83 if (pValueName)
84 {
85 len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0);
86 valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
87 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len);
88 }
89
90 res = DeletePrinterDataExW( hPrinter, keynameW, valuenameW );
91
92 if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW);
93 if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW);
94
95 return res;
96 }
97
98 DWORD WINAPI
99 DeletePrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName)
100 {
101 TRACE("DeletePrinterDataExW(%p, %S, %S)\n", hPrinter, pKeyName, pValueName);
102 UNIMPLEMENTED;
103 return ERROR_NOT_SUPPORTED;
104 }
105
106 DWORD WINAPI
107 DeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName)
108 {
109 TRACE("DeletePrinterDataW(%p, %S)\n", hPrinter, pValueName);
110 UNIMPLEMENTED;
111 return ERROR_NOT_SUPPORTED;
112 }
113
114 DWORD WINAPI
115 DeletePrinterKeyA(HANDLE hPrinter, PCSTR pKeyName)
116 {
117 LPWSTR keynameW = NULL;
118 INT len;
119 DWORD res;
120
121 TRACE("DeletePrinterKeyA(%p, %s)\n", hPrinter, pKeyName);
122
123 if (pKeyName)
124 {
125 len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0);
126 keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
127 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len);
128 }
129
130 res = DeletePrinterKeyW( hPrinter, keynameW );
131
132 if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW);
133
134 return res;
135 }
136
137 DWORD WINAPI
138 DeletePrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName)
139 {
140 TRACE("DeletePrinterKeyW(%p, %S)\n", hPrinter, pKeyName);
141 UNIMPLEMENTED;
142 return ERROR_NOT_SUPPORTED;
143 }
144
145 DWORD WINAPI
146 EnumPrinterDataA(HANDLE hPrinter, DWORD dwIndex, PSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
147 {
148 TRACE("EnumPrinterDataA(%p, %lu, %s, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
149 UNIMPLEMENTED;
150 return ERROR_NOT_SUPPORTED;
151 }
152
153 DWORD WINAPI
154 EnumPrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
155 {
156 INT len;
157 LPWSTR pKeyNameW;
158 DWORD ret, dwIndex, dwBufSize;
159 HANDLE hHeap;
160 LPSTR pBuffer;
161
162 TRACE("EnumPrinterDataExA(%p, %s, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
163
164 if (pKeyName == NULL || *pKeyName == 0)
165 return ERROR_INVALID_PARAMETER;
166
167 len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0);
168 if (len == 0)
169 {
170 ret = GetLastError ();
171 ERR ("MultiByteToWideChar failed with code %i\n", ret);
172 return ret;
173 }
174
175 hHeap = GetProcessHeap ();
176 if (hHeap == NULL)
177 {
178 ERR ("GetProcessHeap failed\n");
179 return ERROR_OUTOFMEMORY;
180 }
181
182 pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR));
183 if (pKeyNameW == NULL)
184 {
185 ERR ("Failed to allocate %i bytes from process heap\n",
186 (LONG)(len * sizeof (WCHAR)));
187 return ERROR_OUTOFMEMORY;
188 }
189
190 if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0)
191 {
192 ret = GetLastError ();
193 ERR ("MultiByteToWideChar failed with code %i\n", ret);
194 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
195 WARN ("HeapFree failed with code %i\n", GetLastError ());
196 return ret;
197 }
198
199 ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
200
201 if (ret != ERROR_SUCCESS)
202 {
203 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
204 WARN ("HeapFree failed with code %i\n", GetLastError ());
205 TRACE ("EnumPrinterDataExW returned %i\n", ret);
206 return ret;
207 }
208
209 if (HeapFree (hHeap, 0, pKeyNameW) == 0)
210 {
211 ret = GetLastError ();
212 ERR ("HeapFree failed with code %i\n", ret);
213 return ret;
214 }
215
216 if (*pnEnumValues == 0) /* empty key */
217 return ERROR_SUCCESS;
218
219 dwBufSize = 0;
220 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
221 {
222 PPRINTER_ENUM_VALUESW ppev = &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
223
224 if (dwBufSize < ppev->cbValueName)
225 dwBufSize = ppev->cbValueName;
226
227 if ( dwBufSize < ppev->cbData &&
228 (ppev->dwType == REG_SZ || ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
229 dwBufSize = ppev->cbData;
230 }
231
232 FIXME ("Largest Unicode name or value is %i bytes\n", dwBufSize);
233
234 pBuffer = HeapAlloc (hHeap, 0, dwBufSize);
235 if (pBuffer == NULL)
236 {
237 ERR ("Failed to allocate %i bytes from process heap\n", dwBufSize);
238 return ERROR_OUTOFMEMORY;
239 }
240
241 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
242 {
243 PPRINTER_ENUM_VALUESW ppev =
244 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
245
246 len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName,
247 ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL,
248 NULL);
249 if (len == 0)
250 {
251 ret = GetLastError ();
252 ERR ("WideCharToMultiByte failed with code %i\n", ret);
253 if (HeapFree (hHeap, 0, pBuffer) == 0)
254 WARN ("HeapFree failed with code %i\n", GetLastError ());
255 return ret;
256 }
257
258 memcpy (ppev->pValueName, pBuffer, len);
259
260 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
261
262 if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ &&
263 ppev->dwType != REG_MULTI_SZ)
264 continue;
265
266 len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData,
267 ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL);
268 if (len == 0)
269 {
270 ret = GetLastError ();
271 ERR ("WideCharToMultiByte failed with code %i\n", ret);
272 if (HeapFree (hHeap, 0, pBuffer) == 0)
273 WARN ("HeapFree failed with code %i\n", GetLastError ());
274 return ret;
275 }
276
277 memcpy (ppev->pData, pBuffer, len);
278
279 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
280 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
281 }
282
283 if (HeapFree (hHeap, 0, pBuffer) == 0)
284 {
285 ret = GetLastError ();
286 ERR ("HeapFree failed with code %i\n", ret);
287 return ret;
288 }
289
290 return ERROR_SUCCESS;
291 }
292
293 DWORD WINAPI
294 EnumPrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
295 {
296 TRACE("EnumPrinterDataExW(%p, %S, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
297 UNIMPLEMENTED;
298 return ERROR_NOT_SUPPORTED;
299 }
300
301 DWORD WINAPI
302 EnumPrinterDataW(HANDLE hPrinter, DWORD dwIndex, PWSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
303 {
304 TRACE("EnumPrinterDataW(%p, %lu, %S, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
305 UNIMPLEMENTED;
306 return ERROR_NOT_SUPPORTED;
307 }
308
309 DWORD WINAPI
310 EnumPrinterKeyA(HANDLE hPrinter, PCSTR pKeyName, PSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
311 {
312 TRACE("EnumPrinterKeyA(%p, %s, %s, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
313 UNIMPLEMENTED;
314 return ERROR_NOT_SUPPORTED;
315 }
316
317 DWORD WINAPI
318 EnumPrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName, PWSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
319 {
320 TRACE("EnumPrinterKeyW(%p, %S, %S, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
321 UNIMPLEMENTED;
322 return ERROR_NOT_SUPPORTED;
323 }
324
325 DWORD WINAPI
326 GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
327 {
328 TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
329 return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
330 }
331
332 DWORD WINAPI
333 GetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
334 {
335 DWORD cbUnicodeData;
336 DWORD cch;
337 DWORD dwReturnValue;
338 DWORD dwType;
339 POSVERSIONINFOEXA pInfoA;
340 POSVERSIONINFOEXW pInfoW;
341 PVOID pUnicodeData = NULL;
342 PWSTR pwszKeyName = NULL;
343 PWSTR pwszValueName = NULL;
344
345 TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
346
347 if (pKeyName)
348 {
349 // Convert pKeyName to a Unicode string pwszKeyName
350 cch = strlen(pKeyName);
351
352 pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
353 if (!pwszKeyName)
354 {
355 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
356 ERR("HeapAlloc failed!\n");
357 goto Cleanup;
358 }
359
360 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
361 }
362
363 if (pValueName)
364 {
365 // Convert pValueName to a Unicode string pwszValueName
366 cch = strlen(pValueName);
367
368 pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
369 if (!pwszValueName)
370 {
371 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
372 ERR("HeapAlloc failed!\n");
373 goto Cleanup;
374 }
375
376 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
377 }
378
379 // We need the data type information, even if no pData was passed.
380 if (!pType)
381 pType = &dwType;
382
383 // Call GetPrinterDataExW for the first time.
384 // 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.
385 dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, pType, pData, nSize, pcbNeeded);
386
387 // If a critical error occurred, just return it. We cannot do anything else in this case.
388 if (dwReturnValue != ERROR_SUCCESS && dwReturnValue != ERROR_MORE_DATA)
389 goto Cleanup;
390
391 // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size.
392 cbUnicodeData = *pcbNeeded;
393
394 if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
395 {
396 // This is a string that needs to be converted from Unicode to ANSI.
397 // Output the required buffer size for the ANSI string.
398 *pcbNeeded /= sizeof(WCHAR);
399 }
400 else if (*pType == REG_NONE)
401 {
402 if (cbUnicodeData == sizeof(OSVERSIONINFOW) && wcsicmp(pwszValueName, SPLREG_OS_VERSION) == 0)
403 {
404 // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA.
405 *pcbNeeded = sizeof(OSVERSIONINFOA);
406 }
407 else if (cbUnicodeData == sizeof(OSVERSIONINFOEXW) && wcsicmp(pwszValueName, SPLREG_OS_VERSIONEX) == 0)
408 {
409 // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA.
410 *pcbNeeded = sizeof(OSVERSIONINFOEXA);
411 }
412 else
413 {
414 // Other REG_NONE value, nothing to do.
415 goto Cleanup;
416 }
417 }
418
419 // Check if the supplied buffer is large enough for the ANSI data.
420 if (nSize < *pcbNeeded)
421 {
422 dwReturnValue = ERROR_MORE_DATA;
423 goto Cleanup;
424 }
425
426 // Allocate a temporary buffer for the Unicode data.
427 pUnicodeData = HeapAlloc(hProcessHeap, 0, cbUnicodeData);
428 if (!pUnicodeData)
429 {
430 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
431 ERR("HeapAlloc failed!\n");
432 goto Cleanup;
433 }
434
435 if (dwReturnValue == ERROR_SUCCESS)
436 {
437 // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string,
438 // so the Unicode string has been copied into pData. Copy it to pUnicodeData.
439 CopyMemory(pUnicodeData, pData, cbUnicodeData);
440 }
441 else
442 {
443 // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string.
444 // We have to call GetPrinterDataExW again with the temporary buffer.
445 dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, NULL, (PBYTE)pUnicodeData, cbUnicodeData, &cbUnicodeData);
446 if (dwReturnValue != ERROR_SUCCESS)
447 goto Cleanup;
448 }
449
450 if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
451 {
452 // Convert the Unicode string to ANSI.
453 WideCharToMultiByte(CP_ACP, 0, (PWSTR)pUnicodeData, -1, (PSTR)pData, *pcbNeeded, NULL, NULL);
454 }
455 else
456 {
457 // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW.
458 // Copy the fields and convert the Unicode CSD Version string to ANSI.
459 pInfoW = (POSVERSIONINFOEXW)pUnicodeData;
460 pInfoA = (POSVERSIONINFOEXA)pData;
461 pInfoA->dwMajorVersion = pInfoW->dwMajorVersion;
462 pInfoA->dwMinorVersion = pInfoW->dwMinorVersion;
463 pInfoA->dwBuildNumber = pInfoW->dwBuildNumber;
464 pInfoA->dwPlatformId = pInfoW->dwPlatformId;
465 WideCharToMultiByte(CP_ACP, 0, pInfoW->szCSDVersion, -1, pInfoA->szCSDVersion, sizeof(pInfoA->szCSDVersion), NULL, NULL);
466
467 if (cbUnicodeData == sizeof(OSVERSIONINFOW))
468 {
469 pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
470 }
471 else
472 {
473 pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
474 pInfoA->wServicePackMajor = pInfoW->wServicePackMajor;
475 pInfoA->wServicePackMinor = pInfoW->wServicePackMinor;
476 pInfoA->wSuiteMask = pInfoW->wSuiteMask;
477 pInfoA->wProductType = pInfoW->wProductType;
478 pInfoA->wReserved = pInfoW->wReserved;
479 }
480 }
481
482 Cleanup:
483 if (pwszKeyName)
484 HeapFree(hProcessHeap, 0, pwszKeyName);
485
486 if (pwszValueName)
487 HeapFree(hProcessHeap, 0, pwszValueName);
488
489 if (pUnicodeData)
490 HeapFree(hProcessHeap, 0, pUnicodeData);
491
492 return dwReturnValue;
493 }
494
495 DWORD WINAPI
496 GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
497 {
498 const WCHAR wszEmptyString[] = L"";
499
500 BYTE DummyData;
501 DWORD dwErrorCode;
502 DWORD dwType = REG_NONE;
503 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
504
505 TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
506
507 // Sanity checks
508 if (!pHandle)
509 return ERROR_INVALID_HANDLE;
510
511 // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way),
512 // Windows does it differently for GetPrinterDataExW and points them to empty variables.
513 if (!pKeyName)
514 pKeyName = wszEmptyString;
515
516 if (!pType)
517 pType = &dwType;
518
519 if (!pData && !nSize)
520 pData = &DummyData;
521
522 // Do the RPC call
523 RpcTryExcept
524 {
525 dwErrorCode = _RpcGetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
526 }
527 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
528 {
529 dwErrorCode = RpcExceptionCode();
530 }
531 RpcEndExcept;
532
533 return dwErrorCode;
534 }
535
536 DWORD WINAPI
537 GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
538 {
539 TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
540 return GetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
541 }
542
543 DWORD WINAPI
544 SetPrinterDataA(HANDLE hPrinter, PSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
545 {
546 TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
547 return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type, pData, cbData);
548 }
549
550 DWORD WINAPI
551 SetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
552 {
553 DWORD cch;
554 DWORD dwReturnValue;
555 PWSTR pwszKeyName = NULL;
556 PWSTR pwszValueName = NULL;
557 PWSTR pUnicodeData = NULL;
558
559 TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
560
561 if (pKeyName)
562 {
563 // Convert pKeyName to a Unicode string pwszKeyName
564 cch = strlen(pKeyName);
565
566 pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
567 if (!pwszKeyName)
568 {
569 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
570 ERR("HeapAlloc failed!\n");
571 goto Cleanup;
572 }
573
574 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
575 }
576
577 if (pValueName)
578 {
579 // Convert pValueName to a Unicode string pwszValueName
580 cch = strlen(pValueName);
581
582 pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
583 if (!pwszValueName)
584 {
585 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
586 ERR("HeapAlloc failed!\n");
587 goto Cleanup;
588 }
589
590 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
591 }
592
593 if (Type == REG_SZ || Type == REG_MULTI_SZ || Type == REG_EXPAND_SZ)
594 {
595 // Convert pData to a Unicode string pUnicodeData.
596 pUnicodeData = HeapAlloc(hProcessHeap, 0, cbData * sizeof(WCHAR));
597 if (!pUnicodeData)
598 {
599 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
600 ERR("HeapAlloc failed!\n");
601 goto Cleanup;
602 }
603
604 MultiByteToWideChar(CP_ACP, 0, (PCSTR)pData, -1, pUnicodeData, cbData);
605
606 pData = (PBYTE)pUnicodeData;
607 cbData *= sizeof(WCHAR);
608 }
609
610 dwReturnValue = SetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, Type, pData, cbData);
611
612 Cleanup:
613 if (pwszKeyName)
614 HeapFree(hProcessHeap, 0, pwszKeyName);
615
616 if (pwszValueName)
617 HeapFree(hProcessHeap, 0, pwszValueName);
618
619 if (pUnicodeData)
620 HeapFree(hProcessHeap, 0, pUnicodeData);
621
622 return dwReturnValue;
623 }
624
625 DWORD WINAPI
626 SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
627 {
628 const WCHAR wszEmptyString[] = L"";
629
630 DWORD dwErrorCode;
631 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
632
633 TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
634
635 // Sanity checks
636 if (!pHandle)
637 return ERROR_INVALID_HANDLE;
638
639 if (!pKeyName)
640 pKeyName = wszEmptyString;
641
642 // Do the RPC call
643 RpcTryExcept
644 {
645 dwErrorCode = _RpcSetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, Type, pData, cbData);
646 }
647 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
648 {
649 dwErrorCode = RpcExceptionCode();
650 }
651 RpcEndExcept;
652
653 return dwErrorCode;
654 }
655
656 DWORD WINAPI
657 SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
658 {
659 TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
660 return SetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, Type, pData, cbData);
661 }