[Printing] Fix ups and Implementations.
[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 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 HeapFree(GetProcessHeap(), 0, keynameW);
93 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 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 =
223 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
224
225 if (dwBufSize < ppev->cbValueName)
226 dwBufSize = ppev->cbValueName;
227
228 if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ ||
229 ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
230 dwBufSize = ppev->cbData;
231 }
232
233 TRACE ("Largest Unicode name or value is %i bytes\n", dwBufSize);
234
235 pBuffer = HeapAlloc (hHeap, 0, dwBufSize);
236 if (pBuffer == NULL)
237 {
238 ERR ("Failed to allocate %i bytes from process heap\n", dwBufSize);
239 return ERROR_OUTOFMEMORY;
240 }
241
242 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
243 {
244 PPRINTER_ENUM_VALUESW ppev =
245 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
246
247 len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName,
248 ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL,
249 NULL);
250 if (len == 0)
251 {
252 ret = GetLastError ();
253 ERR ("WideCharToMultiByte failed with code %i\n", ret);
254 if (HeapFree (hHeap, 0, pBuffer) == 0)
255 WARN ("HeapFree failed with code %i\n", GetLastError ());
256 return ret;
257 }
258
259 memcpy (ppev->pValueName, pBuffer, len);
260
261 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
262
263 if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ &&
264 ppev->dwType != REG_MULTI_SZ)
265 continue;
266
267 len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData,
268 ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL);
269 if (len == 0)
270 {
271 ret = GetLastError ();
272 ERR ("WideCharToMultiByte failed with code %i\n", ret);
273 if (HeapFree (hHeap, 0, pBuffer) == 0)
274 WARN ("HeapFree failed with code %i\n", GetLastError ());
275 return ret;
276 }
277
278 memcpy (ppev->pData, pBuffer, len);
279
280 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
281 TRACE (" (only first string of REG_MULTI_SZ printed)\n");
282 }
283
284 if (HeapFree (hHeap, 0, pBuffer) == 0)
285 {
286 ret = GetLastError ();
287 ERR ("HeapFree failed with code %i\n", ret);
288 return ret;
289 }
290
291 return ERROR_SUCCESS;
292 }
293
294 DWORD WINAPI
295 EnumPrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
296 {
297 TRACE("EnumPrinterDataExW(%p, %S, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
298 UNIMPLEMENTED;
299 return ERROR_NOT_SUPPORTED;
300 }
301
302 DWORD WINAPI
303 EnumPrinterDataW(HANDLE hPrinter, DWORD dwIndex, PWSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
304 {
305 TRACE("EnumPrinterDataW(%p, %lu, %S, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
306 UNIMPLEMENTED;
307 return ERROR_NOT_SUPPORTED;
308 }
309
310 DWORD WINAPI
311 EnumPrinterKeyA(HANDLE hPrinter, PCSTR pKeyName, PSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
312 {
313 TRACE("EnumPrinterKeyA(%p, %s, %s, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
314 UNIMPLEMENTED;
315 return ERROR_NOT_SUPPORTED;
316 }
317
318 DWORD WINAPI
319 EnumPrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName, PWSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
320 {
321 TRACE("EnumPrinterKeyW(%p, %S, %S, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
322 UNIMPLEMENTED;
323 return ERROR_NOT_SUPPORTED;
324 }
325
326 DWORD WINAPI
327 GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
328 {
329 TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
330 return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
331 }
332
333 DWORD WINAPI
334 GetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
335 {
336 DWORD cbUnicodeData;
337 DWORD cch;
338 DWORD dwReturnValue;
339 DWORD dwType;
340 POSVERSIONINFOEXA pInfoA;
341 POSVERSIONINFOEXW pInfoW;
342 PVOID pUnicodeData = NULL;
343 PWSTR pwszKeyName = NULL;
344 PWSTR pwszValueName = NULL;
345
346 TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
347
348 if (pKeyName)
349 {
350 // Convert pKeyName to a Unicode string pwszKeyName
351 cch = strlen(pKeyName);
352
353 pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
354 if (!pwszKeyName)
355 {
356 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
357 ERR("HeapAlloc failed!\n");
358 goto Cleanup;
359 }
360
361 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
362 }
363
364 if (pValueName)
365 {
366 // Convert pValueName to a Unicode string pwszValueName
367 cch = strlen(pValueName);
368
369 pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
370 if (!pwszValueName)
371 {
372 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
373 ERR("HeapAlloc failed!\n");
374 goto Cleanup;
375 }
376
377 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
378 }
379
380 // We need the data type information, even if no pData was passed.
381 if (!pType)
382 pType = &dwType;
383
384 // Call GetPrinterDataExW for the first time.
385 // 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.
386 dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, pType, pData, nSize, pcbNeeded);
387
388 // If a critical error occurred, just return it. We cannot do anything else in this case.
389 if (dwReturnValue != ERROR_SUCCESS && dwReturnValue != ERROR_MORE_DATA)
390 goto Cleanup;
391
392 // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size.
393 cbUnicodeData = *pcbNeeded;
394
395 if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
396 {
397 // This is a string that needs to be converted from Unicode to ANSI.
398 // Output the required buffer size for the ANSI string.
399 *pcbNeeded /= sizeof(WCHAR);
400 }
401 else if (*pType == REG_NONE)
402 {
403 if (cbUnicodeData == sizeof(OSVERSIONINFOW) && wcsicmp(pwszValueName, SPLREG_OS_VERSION) == 0)
404 {
405 // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA.
406 *pcbNeeded = sizeof(OSVERSIONINFOA);
407 }
408 else if (cbUnicodeData == sizeof(OSVERSIONINFOEXW) && wcsicmp(pwszValueName, SPLREG_OS_VERSIONEX) == 0)
409 {
410 // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA.
411 *pcbNeeded = sizeof(OSVERSIONINFOEXA);
412 }
413 else
414 {
415 // Other REG_NONE value, nothing to do.
416 goto Cleanup;
417 }
418 }
419
420 // Check if the supplied buffer is large enough for the ANSI data.
421 if (nSize < *pcbNeeded)
422 {
423 dwReturnValue = ERROR_MORE_DATA;
424 goto Cleanup;
425 }
426
427 // Allocate a temporary buffer for the Unicode data.
428 pUnicodeData = HeapAlloc(hProcessHeap, 0, cbUnicodeData);
429 if (!pUnicodeData)
430 {
431 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
432 ERR("HeapAlloc failed!\n");
433 goto Cleanup;
434 }
435
436 if (dwReturnValue == ERROR_SUCCESS)
437 {
438 // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string,
439 // so the Unicode string has been copied into pData. Copy it to pUnicodeData.
440 CopyMemory(pUnicodeData, pData, cbUnicodeData);
441 }
442 else
443 {
444 // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string.
445 // We have to call GetPrinterDataExW again with the temporary buffer.
446 dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, NULL, (PBYTE)pUnicodeData, cbUnicodeData, &cbUnicodeData);
447 if (dwReturnValue != ERROR_SUCCESS)
448 goto Cleanup;
449 }
450
451 if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
452 {
453 // Convert the Unicode string to ANSI.
454 WideCharToMultiByte(CP_ACP, 0, (PWSTR)pUnicodeData, -1, (PSTR)pData, *pcbNeeded, NULL, NULL);
455 }
456 else
457 {
458 // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW.
459 // Copy the fields and convert the Unicode CSD Version string to ANSI.
460 pInfoW = (POSVERSIONINFOEXW)pUnicodeData;
461 pInfoA = (POSVERSIONINFOEXA)pData;
462 pInfoA->dwMajorVersion = pInfoW->dwMajorVersion;
463 pInfoA->dwMinorVersion = pInfoW->dwMinorVersion;
464 pInfoA->dwBuildNumber = pInfoW->dwBuildNumber;
465 pInfoA->dwPlatformId = pInfoW->dwPlatformId;
466 WideCharToMultiByte(CP_ACP, 0, pInfoW->szCSDVersion, -1, pInfoA->szCSDVersion, sizeof(pInfoA->szCSDVersion), NULL, NULL);
467
468 if (cbUnicodeData == sizeof(OSVERSIONINFOW))
469 {
470 pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
471 }
472 else
473 {
474 pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
475 pInfoA->wServicePackMajor = pInfoW->wServicePackMajor;
476 pInfoA->wServicePackMinor = pInfoW->wServicePackMinor;
477 pInfoA->wSuiteMask = pInfoW->wSuiteMask;
478 pInfoA->wProductType = pInfoW->wProductType;
479 pInfoA->wReserved = pInfoW->wReserved;
480 }
481 }
482
483 Cleanup:
484 if (pwszKeyName)
485 HeapFree(hProcessHeap, 0, pwszKeyName);
486
487 if (pwszValueName)
488 HeapFree(hProcessHeap, 0, pwszValueName);
489
490 if (pUnicodeData)
491 HeapFree(hProcessHeap, 0, pUnicodeData);
492
493 return dwReturnValue;
494 }
495
496 DWORD WINAPI
497 GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
498 {
499 const WCHAR wszEmptyString[] = L"";
500
501 BYTE DummyData;
502 DWORD dwErrorCode;
503 DWORD dwType = REG_NONE;
504 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
505
506 TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
507
508 // Sanity checks
509 if (!pHandle)
510 return ERROR_INVALID_HANDLE;
511
512 // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way),
513 // Windows does it differently for GetPrinterDataExW and points them to empty variables.
514 if (!pKeyName)
515 pKeyName = wszEmptyString;
516
517 if (!pType)
518 pType = &dwType;
519
520 if (!pData && !nSize)
521 pData = &DummyData;
522
523 // Do the RPC call
524 RpcTryExcept
525 {
526 dwErrorCode = _RpcGetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
527 }
528 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
529 {
530 dwErrorCode = RpcExceptionCode();
531 }
532 RpcEndExcept;
533
534 return dwErrorCode;
535 }
536
537 DWORD WINAPI
538 GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
539 {
540 TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
541 return GetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
542 }
543
544 DWORD WINAPI
545 SetPrinterDataA(HANDLE hPrinter, PSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
546 {
547 TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
548 return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type, pData, cbData);
549 }
550
551 DWORD WINAPI
552 SetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
553 {
554 DWORD cch;
555 DWORD dwReturnValue;
556 PWSTR pwszKeyName = NULL;
557 PWSTR pwszValueName = NULL;
558 PWSTR pUnicodeData = NULL;
559
560 TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
561
562 if (pKeyName)
563 {
564 // Convert pKeyName to a Unicode string pwszKeyName
565 cch = strlen(pKeyName);
566
567 pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
568 if (!pwszKeyName)
569 {
570 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
571 ERR("HeapAlloc failed!\n");
572 goto Cleanup;
573 }
574
575 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
576 }
577
578 if (pValueName)
579 {
580 // Convert pValueName to a Unicode string pwszValueName
581 cch = strlen(pValueName);
582
583 pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
584 if (!pwszValueName)
585 {
586 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
587 ERR("HeapAlloc failed!\n");
588 goto Cleanup;
589 }
590
591 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
592 }
593
594 if (Type == REG_SZ || Type == REG_MULTI_SZ || Type == REG_EXPAND_SZ)
595 {
596 // Convert pData to a Unicode string pUnicodeData.
597 pUnicodeData = HeapAlloc(hProcessHeap, 0, cbData * sizeof(WCHAR));
598 if (!pUnicodeData)
599 {
600 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
601 ERR("HeapAlloc failed!\n");
602 goto Cleanup;
603 }
604
605 MultiByteToWideChar(CP_ACP, 0, (PCSTR)pData, -1, pUnicodeData, cbData);
606
607 pData = (PBYTE)pUnicodeData;
608 cbData *= sizeof(WCHAR);
609 }
610
611 dwReturnValue = SetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, Type, pData, cbData);
612
613 Cleanup:
614 if (pwszKeyName)
615 HeapFree(hProcessHeap, 0, pwszKeyName);
616
617 if (pwszValueName)
618 HeapFree(hProcessHeap, 0, pwszValueName);
619
620 if (pUnicodeData)
621 HeapFree(hProcessHeap, 0, pUnicodeData);
622
623 return dwReturnValue;
624 }
625
626 DWORD WINAPI
627 SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
628 {
629 const WCHAR wszEmptyString[] = L"";
630
631 DWORD dwErrorCode;
632 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
633
634 TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
635
636 // Sanity checks
637 if (!pHandle)
638 return ERROR_INVALID_HANDLE;
639
640 if (!pKeyName)
641 pKeyName = wszEmptyString;
642
643 // Do the RPC call
644 RpcTryExcept
645 {
646 dwErrorCode = _RpcSetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, Type, pData, cbData);
647 }
648 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
649 {
650 dwErrorCode = RpcExceptionCode();
651 }
652 RpcEndExcept;
653
654 return dwErrorCode;
655 }
656
657 DWORD WINAPI
658 SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
659 {
660 TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
661 return SetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, Type, pData, cbData);
662 }