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
AdvancedSetupDialog(HWND hWnd,INT Unknown,PDEVMODEA pDevModeInput,PDEVMODEA pDevModeOutput)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
AdvancedDocumentPropertiesA(HWND hWnd,HANDLE hPrinter,PSTR pDeviceName,PDEVMODEA pDevModeOutput,PDEVMODEA pDevModeInput)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
AdvancedDocumentPropertiesW(HWND hWnd,HANDLE hPrinter,PWSTR pDeviceName,PDEVMODEW pDevModeOutput,PDEVMODEW pDevModeInput)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
DeletePrinterDataA(HANDLE hPrinter,PSTR pValueName)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
DeletePrinterDataExA(HANDLE hPrinter,PCSTR pKeyName,PCSTR pValueName)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
DeletePrinterDataExW(HANDLE hPrinter,PCWSTR pKeyName,PCWSTR pValueName)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
DeletePrinterDataW(HANDLE hPrinter,PWSTR pValueName)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
DeletePrinterKeyA(HANDLE hPrinter,PCSTR pKeyName)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
DeletePrinterKeyW(HANDLE hPrinter,PCWSTR pKeyName)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
EnumPrinterDataA(HANDLE hPrinter,DWORD dwIndex,PSTR pValueName,DWORD cbValueName,PDWORD pcbValueName,PDWORD pType,PBYTE pData,DWORD cbData,PDWORD pcbData)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
EnumPrinterDataExA(HANDLE hPrinter,PCSTR pKeyName,PBYTE pEnumValues,DWORD cbEnumValues,PDWORD pcbEnumValues,PDWORD pnEnumValues)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
EnumPrinterDataExW(HANDLE hPrinter,PCWSTR pKeyName,PBYTE pEnumValues,DWORD cbEnumValues,PDWORD pcbEnumValues,PDWORD pnEnumValues)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
EnumPrinterDataW(HANDLE hPrinter,DWORD dwIndex,PWSTR pValueName,DWORD cbValueName,PDWORD pcbValueName,PDWORD pType,PBYTE pData,DWORD cbData,PDWORD pcbData)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
EnumPrinterKeyA(HANDLE hPrinter,PCSTR pKeyName,PSTR pSubkey,DWORD cbSubkey,PDWORD pcbSubkey)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
EnumPrinterKeyW(HANDLE hPrinter,PCWSTR pKeyName,PWSTR pSubkey,DWORD cbSubkey,PDWORD pcbSubkey)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
GetPrinterDataA(HANDLE hPrinter,LPSTR pValueName,LPDWORD pType,LPBYTE pData,DWORD nSize,LPDWORD pcbNeeded)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
GetPrinterDataExA(HANDLE hPrinter,LPCSTR pKeyName,LPCSTR pValueName,LPDWORD pType,LPBYTE pData,DWORD nSize,LPDWORD pcbNeeded)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
GetPrinterDataExW(HANDLE hPrinter,LPCWSTR pKeyName,LPCWSTR pValueName,LPDWORD pType,LPBYTE pData,DWORD nSize,LPDWORD pcbNeeded)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
GetPrinterDataW(HANDLE hPrinter,LPWSTR pValueName,LPDWORD pType,LPBYTE pData,DWORD nSize,LPDWORD pcbNeeded)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
SetPrinterDataA(HANDLE hPrinter,PSTR pValueName,DWORD Type,PBYTE pData,DWORD cbData)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
SetPrinterDataExA(HANDLE hPrinter,LPCSTR pKeyName,LPCSTR pValueName,DWORD Type,LPBYTE pData,DWORD cbData)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
SetPrinterDataExW(HANDLE hPrinter,LPCWSTR pKeyName,LPCWSTR pValueName,DWORD Type,LPBYTE pData,DWORD cbData)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
SetPrinterDataW(HANDLE hPrinter,PWSTR pValueName,DWORD Type,PBYTE pData,DWORD cbData)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 }
662