1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:     ReactOS Spooler API
3c2c66affSColin Finck  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4c2c66affSColin Finck  * PURPOSE:     Functions related to Printer Configuration Data
5c2c66affSColin Finck  * COPYRIGHT:   Copyright 2015-2017 Colin Finck (colin@reactos.org)
6c2c66affSColin Finck  */
7c2c66affSColin Finck 
8c2c66affSColin Finck #include "precomp.h"
9c2c66affSColin Finck 
10c2c66affSColin Finck LONG WINAPI
11*46b91659SColin Finck AdvancedDocumentPropertiesA(HWND hWnd, HANDLE hPrinter, PSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput)
12*46b91659SColin Finck {
13*46b91659SColin Finck     TRACE("AdvancedDocumentPropertiesA(%p, %p, %s, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput);
14*46b91659SColin Finck     UNIMPLEMENTED;
15*46b91659SColin Finck     return 0;
16*46b91659SColin Finck }
17*46b91659SColin Finck 
18*46b91659SColin Finck LONG WINAPI
19c2c66affSColin Finck AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput)
20c2c66affSColin Finck {
211f6f08ecSColin Finck     TRACE("AdvancedDocumentPropertiesW(%p, %p, %S, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput);
22c2c66affSColin Finck     UNIMPLEMENTED;
23*46b91659SColin Finck     return 0;
24*46b91659SColin Finck }
25*46b91659SColin Finck 
26*46b91659SColin Finck DWORD WINAPI
27*46b91659SColin Finck DeletePrinterDataA(HANDLE hPrinter, PSTR pValueName)
28*46b91659SColin Finck {
29*46b91659SColin Finck     TRACE("DeletePrinterDataA(%p, %s)\n", hPrinter, pValueName);
30*46b91659SColin Finck     UNIMPLEMENTED;
31*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
32*46b91659SColin Finck }
33*46b91659SColin Finck 
34*46b91659SColin Finck DWORD WINAPI
35*46b91659SColin Finck DeletePrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PCSTR pValueName)
36*46b91659SColin Finck {
37*46b91659SColin Finck     TRACE("DeletePrinterDataExA(%p, %s, %s)\n", hPrinter, pKeyName, pValueName);
38*46b91659SColin Finck     UNIMPLEMENTED;
39*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
40*46b91659SColin Finck }
41*46b91659SColin Finck 
42*46b91659SColin Finck DWORD WINAPI
43*46b91659SColin Finck DeletePrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName)
44*46b91659SColin Finck {
45*46b91659SColin Finck     TRACE("DeletePrinterDataExW(%p, %S, %S)\n", hPrinter, pKeyName, pValueName);
46*46b91659SColin Finck     UNIMPLEMENTED;
47*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
48*46b91659SColin Finck }
49*46b91659SColin Finck 
50*46b91659SColin Finck DWORD WINAPI
51*46b91659SColin Finck DeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName)
52*46b91659SColin Finck {
53*46b91659SColin Finck     TRACE("DeletePrinterDataW(%p, %S)\n", hPrinter, pValueName);
54*46b91659SColin Finck     UNIMPLEMENTED;
55*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
56*46b91659SColin Finck }
57*46b91659SColin Finck 
58*46b91659SColin Finck DWORD WINAPI
59*46b91659SColin Finck DeletePrinterKeyA(HANDLE hPrinter, PCSTR pKeyName)
60*46b91659SColin Finck {
61*46b91659SColin Finck     TRACE("DeletePrinterKeyA(%p, %s)\n", hPrinter, pKeyName);
62*46b91659SColin Finck     UNIMPLEMENTED;
63*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
64*46b91659SColin Finck }
65*46b91659SColin Finck 
66*46b91659SColin Finck DWORD WINAPI
67*46b91659SColin Finck DeletePrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName)
68*46b91659SColin Finck {
69*46b91659SColin Finck     TRACE("DeletePrinterKeyW(%p, %S)\n", hPrinter, pKeyName);
70*46b91659SColin Finck     UNIMPLEMENTED;
71*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
72*46b91659SColin Finck }
73*46b91659SColin Finck 
74*46b91659SColin Finck DWORD WINAPI
75*46b91659SColin Finck EnumPrinterDataA(HANDLE hPrinter, DWORD dwIndex, PSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
76*46b91659SColin Finck {
77*46b91659SColin Finck     TRACE("EnumPrinterDataA(%p, %lu, %s, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
78*46b91659SColin Finck     UNIMPLEMENTED;
79*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
80*46b91659SColin Finck }
81*46b91659SColin Finck 
82*46b91659SColin Finck DWORD WINAPI
83*46b91659SColin Finck EnumPrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
84*46b91659SColin Finck {
85*46b91659SColin Finck     TRACE("EnumPrinterDataExA(%p, %s, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
86*46b91659SColin Finck     UNIMPLEMENTED;
87*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
88*46b91659SColin Finck }
89*46b91659SColin Finck 
90*46b91659SColin Finck DWORD WINAPI
91*46b91659SColin Finck EnumPrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
92*46b91659SColin Finck {
93*46b91659SColin Finck     TRACE("EnumPrinterDataExW(%p, %S, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
94*46b91659SColin Finck     UNIMPLEMENTED;
95*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
96*46b91659SColin Finck }
97*46b91659SColin Finck 
98*46b91659SColin Finck DWORD WINAPI
99*46b91659SColin Finck EnumPrinterDataW(HANDLE hPrinter, DWORD dwIndex, PWSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
100*46b91659SColin Finck {
101*46b91659SColin Finck     TRACE("EnumPrinterDataW(%p, %lu, %S, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
102*46b91659SColin Finck     UNIMPLEMENTED;
103*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
104*46b91659SColin Finck }
105*46b91659SColin Finck 
106*46b91659SColin Finck DWORD WINAPI
107*46b91659SColin Finck EnumPrinterKeyA(HANDLE hPrinter, PCSTR pKeyName, PSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
108*46b91659SColin Finck {
109*46b91659SColin Finck     TRACE("EnumPrinterKeyA(%p, %s, %s, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
110*46b91659SColin Finck     UNIMPLEMENTED;
111*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
112*46b91659SColin Finck }
113*46b91659SColin Finck 
114*46b91659SColin Finck DWORD WINAPI
115*46b91659SColin Finck EnumPrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName, PWSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
116*46b91659SColin Finck {
117*46b91659SColin Finck     TRACE("EnumPrinterKeyW(%p, %S, %S, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
118*46b91659SColin Finck     UNIMPLEMENTED;
119*46b91659SColin Finck     return ERROR_NOT_SUPPORTED;
120c2c66affSColin Finck }
121c2c66affSColin Finck 
122c2c66affSColin Finck DWORD WINAPI
123c2c66affSColin Finck GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
124c2c66affSColin Finck {
1251f6f08ecSColin Finck     TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
126c2c66affSColin Finck     return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
127c2c66affSColin Finck }
128c2c66affSColin Finck 
129c2c66affSColin Finck DWORD WINAPI
130c2c66affSColin Finck GetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
131c2c66affSColin Finck {
132c2c66affSColin Finck     DWORD cbUnicodeData;
133c2c66affSColin Finck     DWORD cch;
134c2c66affSColin Finck     DWORD dwReturnValue;
135c2c66affSColin Finck     DWORD dwType;
136c2c66affSColin Finck     POSVERSIONINFOEXA pInfoA;
137c2c66affSColin Finck     POSVERSIONINFOEXW pInfoW;
138c2c66affSColin Finck     PVOID pUnicodeData = NULL;
139c2c66affSColin Finck     PWSTR pwszKeyName = NULL;
140c2c66affSColin Finck     PWSTR pwszValueName = NULL;
141c2c66affSColin Finck 
1421f6f08ecSColin Finck     TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
1431f6f08ecSColin Finck 
144c2c66affSColin Finck     if (pKeyName)
145c2c66affSColin Finck     {
146c2c66affSColin Finck         // Convert pKeyName to a Unicode string pwszKeyName
147c2c66affSColin Finck         cch = strlen(pKeyName);
148c2c66affSColin Finck 
149c2c66affSColin Finck         pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
150c2c66affSColin Finck         if (!pwszKeyName)
151c2c66affSColin Finck         {
152c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
153c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
154c2c66affSColin Finck             goto Cleanup;
155c2c66affSColin Finck         }
156c2c66affSColin Finck 
157c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
158c2c66affSColin Finck     }
159c2c66affSColin Finck 
160c2c66affSColin Finck     if (pValueName)
161c2c66affSColin Finck     {
162c2c66affSColin Finck         // Convert pValueName to a Unicode string pwszValueName
163c2c66affSColin Finck         cch = strlen(pValueName);
164c2c66affSColin Finck 
165c2c66affSColin Finck         pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
166c2c66affSColin Finck         if (!pwszValueName)
167c2c66affSColin Finck         {
168c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
169c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
170c2c66affSColin Finck             goto Cleanup;
171c2c66affSColin Finck         }
172c2c66affSColin Finck 
173c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
174c2c66affSColin Finck     }
175c2c66affSColin Finck 
176c2c66affSColin Finck     // We need the data type information, even if no pData was passed.
177c2c66affSColin Finck     if (!pType)
178c2c66affSColin Finck         pType = &dwType;
179c2c66affSColin Finck 
180c2c66affSColin Finck     // Call GetPrinterDataExW for the first time.
181c2c66affSColin Finck     // 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.
182c2c66affSColin Finck     dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, pType, pData, nSize, pcbNeeded);
183c2c66affSColin Finck 
184c2c66affSColin Finck     // If a critical error occurred, just return it. We cannot do anything else in this case.
185c2c66affSColin Finck     if (dwReturnValue != ERROR_SUCCESS && dwReturnValue != ERROR_MORE_DATA)
186c2c66affSColin Finck         goto Cleanup;
187c2c66affSColin Finck 
188c2c66affSColin Finck     // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size.
189c2c66affSColin Finck     cbUnicodeData = *pcbNeeded;
190c2c66affSColin Finck 
191c2c66affSColin Finck     if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
192c2c66affSColin Finck     {
193c2c66affSColin Finck         // This is a string that needs to be converted from Unicode to ANSI.
194c2c66affSColin Finck         // Output the required buffer size for the ANSI string.
195c2c66affSColin Finck         *pcbNeeded /= sizeof(WCHAR);
196c2c66affSColin Finck     }
197c2c66affSColin Finck     else if (*pType == REG_NONE)
198c2c66affSColin Finck     {
199c2c66affSColin Finck         if (cbUnicodeData == sizeof(OSVERSIONINFOW) && wcsicmp(pwszValueName, SPLREG_OS_VERSION) == 0)
200c2c66affSColin Finck         {
201c2c66affSColin Finck             // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA.
202c2c66affSColin Finck             *pcbNeeded = sizeof(OSVERSIONINFOA);
203c2c66affSColin Finck         }
204c2c66affSColin Finck         else if (cbUnicodeData == sizeof(OSVERSIONINFOEXW) && wcsicmp(pwszValueName, SPLREG_OS_VERSIONEX) == 0)
205c2c66affSColin Finck         {
206c2c66affSColin Finck             // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA.
207c2c66affSColin Finck             *pcbNeeded = sizeof(OSVERSIONINFOEXA);
208c2c66affSColin Finck         }
209c2c66affSColin Finck         else
210c2c66affSColin Finck         {
211c2c66affSColin Finck             // Other REG_NONE value, nothing to do.
212c2c66affSColin Finck             goto Cleanup;
213c2c66affSColin Finck         }
214c2c66affSColin Finck     }
215c2c66affSColin Finck 
216c2c66affSColin Finck     // Check if the supplied buffer is large enough for the ANSI data.
217c2c66affSColin Finck     if (nSize < *pcbNeeded)
218c2c66affSColin Finck     {
219c2c66affSColin Finck         dwReturnValue = ERROR_MORE_DATA;
220c2c66affSColin Finck         goto Cleanup;
221c2c66affSColin Finck     }
222c2c66affSColin Finck 
223c2c66affSColin Finck     // Allocate a temporary buffer for the Unicode data.
224c2c66affSColin Finck     pUnicodeData = HeapAlloc(hProcessHeap, 0, cbUnicodeData);
225c2c66affSColin Finck     if (!pUnicodeData)
226c2c66affSColin Finck     {
227c2c66affSColin Finck         dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
228c2c66affSColin Finck         ERR("HeapAlloc failed!\n");
229c2c66affSColin Finck         goto Cleanup;
230c2c66affSColin Finck     }
231c2c66affSColin Finck 
232c2c66affSColin Finck     if (dwReturnValue == ERROR_SUCCESS)
233c2c66affSColin Finck     {
234c2c66affSColin Finck         // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string,
235c2c66affSColin Finck         // so the Unicode string has been copied into pData. Copy it to pUnicodeData.
236c2c66affSColin Finck         CopyMemory(pUnicodeData, pData, cbUnicodeData);
237c2c66affSColin Finck     }
238c2c66affSColin Finck     else
239c2c66affSColin Finck     {
240c2c66affSColin Finck         // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string.
241c2c66affSColin Finck         // We have to call GetPrinterDataExW again with the temporary buffer.
242c2c66affSColin Finck         dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, NULL, (PBYTE)pUnicodeData, cbUnicodeData, &cbUnicodeData);
243c2c66affSColin Finck         if (dwReturnValue != ERROR_SUCCESS)
244c2c66affSColin Finck             goto Cleanup;
245c2c66affSColin Finck     }
246c2c66affSColin Finck 
247c2c66affSColin Finck     if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
248c2c66affSColin Finck     {
249c2c66affSColin Finck         // Convert the Unicode string to ANSI.
250c2c66affSColin Finck         WideCharToMultiByte(CP_ACP, 0, (PWSTR)pUnicodeData, -1, (PSTR)pData, *pcbNeeded, NULL, NULL);
251c2c66affSColin Finck     }
252c2c66affSColin Finck     else
253c2c66affSColin Finck     {
254c2c66affSColin Finck         // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW.
255c2c66affSColin Finck         // Copy the fields and convert the Unicode CSD Version string to ANSI.
256c2c66affSColin Finck         pInfoW = (POSVERSIONINFOEXW)pUnicodeData;
257c2c66affSColin Finck         pInfoA = (POSVERSIONINFOEXA)pData;
258c2c66affSColin Finck         pInfoA->dwMajorVersion = pInfoW->dwMajorVersion;
259c2c66affSColin Finck         pInfoA->dwMinorVersion = pInfoW->dwMinorVersion;
260c2c66affSColin Finck         pInfoA->dwBuildNumber = pInfoW->dwBuildNumber;
261c2c66affSColin Finck         pInfoA->dwPlatformId = pInfoW->dwPlatformId;
262c2c66affSColin Finck         WideCharToMultiByte(CP_ACP, 0, pInfoW->szCSDVersion, -1, pInfoA->szCSDVersion, sizeof(pInfoA->szCSDVersion), NULL, NULL);
263c2c66affSColin Finck 
264c2c66affSColin Finck         if (cbUnicodeData == sizeof(OSVERSIONINFOW))
265c2c66affSColin Finck         {
266c2c66affSColin Finck             pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
267c2c66affSColin Finck         }
268c2c66affSColin Finck         else
269c2c66affSColin Finck         {
270c2c66affSColin Finck             pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
271c2c66affSColin Finck             pInfoA->wServicePackMajor = pInfoW->wServicePackMajor;
272c2c66affSColin Finck             pInfoA->wServicePackMinor = pInfoW->wServicePackMinor;
273c2c66affSColin Finck             pInfoA->wSuiteMask = pInfoW->wSuiteMask;
274c2c66affSColin Finck             pInfoA->wProductType = pInfoW->wProductType;
275c2c66affSColin Finck             pInfoA->wReserved = pInfoW->wReserved;
276c2c66affSColin Finck         }
277c2c66affSColin Finck     }
278c2c66affSColin Finck 
279c2c66affSColin Finck Cleanup:
280c2c66affSColin Finck     if (pwszKeyName)
281c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pwszKeyName);
282c2c66affSColin Finck 
283c2c66affSColin Finck     if (pwszValueName)
284c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pwszValueName);
285c2c66affSColin Finck 
286c2c66affSColin Finck     if (pUnicodeData)
287c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pUnicodeData);
288c2c66affSColin Finck 
289c2c66affSColin Finck     return dwReturnValue;
290c2c66affSColin Finck }
291c2c66affSColin Finck 
292c2c66affSColin Finck DWORD WINAPI
293c2c66affSColin Finck GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
294c2c66affSColin Finck {
295c2c66affSColin Finck     const WCHAR wszEmptyString[] = L"";
296c2c66affSColin Finck 
297c2c66affSColin Finck     BYTE DummyData;
298c2c66affSColin Finck     DWORD dwErrorCode;
299c2c66affSColin Finck     DWORD dwType = REG_NONE;
300c2c66affSColin Finck     PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
301c2c66affSColin Finck 
3021f6f08ecSColin Finck     TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
3031f6f08ecSColin Finck 
304c2c66affSColin Finck     // Sanity checks
305c2c66affSColin Finck     if (!pHandle)
306c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
307c2c66affSColin Finck 
308c2c66affSColin Finck     // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way),
309c2c66affSColin Finck     // Windows does it differently for GetPrinterDataExW and points them to empty variables.
310c2c66affSColin Finck     if (!pKeyName)
311c2c66affSColin Finck         pKeyName = wszEmptyString;
312c2c66affSColin Finck 
313c2c66affSColin Finck     if (!pType)
314c2c66affSColin Finck         pType = &dwType;
315c2c66affSColin Finck 
316c2c66affSColin Finck     if (!pData && !nSize)
317c2c66affSColin Finck         pData = &DummyData;
318c2c66affSColin Finck 
319c2c66affSColin Finck     // Do the RPC call
320c2c66affSColin Finck     RpcTryExcept
321c2c66affSColin Finck     {
322c2c66affSColin Finck         dwErrorCode = _RpcGetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
323c2c66affSColin Finck     }
324c2c66affSColin Finck     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
325c2c66affSColin Finck     {
326c2c66affSColin Finck         dwErrorCode = RpcExceptionCode();
327c2c66affSColin Finck     }
328c2c66affSColin Finck     RpcEndExcept;
329c2c66affSColin Finck 
330c2c66affSColin Finck     return dwErrorCode;
331c2c66affSColin Finck }
332c2c66affSColin Finck 
333c2c66affSColin Finck DWORD WINAPI
334c2c66affSColin Finck GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
335c2c66affSColin Finck {
3361f6f08ecSColin Finck     TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
337c2c66affSColin Finck     return GetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
338c2c66affSColin Finck }
339c2c66affSColin Finck 
340c2c66affSColin Finck DWORD WINAPI
341c2c66affSColin Finck SetPrinterDataA(HANDLE hPrinter, PSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
342c2c66affSColin Finck {
3431f6f08ecSColin Finck     TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
344c2c66affSColin Finck     return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type, pData, cbData);
345c2c66affSColin Finck }
346c2c66affSColin Finck 
347c2c66affSColin Finck DWORD WINAPI
348c2c66affSColin Finck SetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
349c2c66affSColin Finck {
350c2c66affSColin Finck     DWORD cch;
351c2c66affSColin Finck     DWORD dwReturnValue;
352c2c66affSColin Finck     PWSTR pwszKeyName = NULL;
353c2c66affSColin Finck     PWSTR pwszValueName = NULL;
354c2c66affSColin Finck     PWSTR pUnicodeData = NULL;
355c2c66affSColin Finck 
3561f6f08ecSColin Finck     TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
3571f6f08ecSColin Finck 
358c2c66affSColin Finck     if (pKeyName)
359c2c66affSColin Finck     {
360c2c66affSColin Finck         // Convert pKeyName to a Unicode string pwszKeyName
361c2c66affSColin Finck         cch = strlen(pKeyName);
362c2c66affSColin Finck 
363c2c66affSColin Finck         pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
364c2c66affSColin Finck         if (!pwszKeyName)
365c2c66affSColin Finck         {
366c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
367c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
368c2c66affSColin Finck             goto Cleanup;
369c2c66affSColin Finck         }
370c2c66affSColin Finck 
371c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
372c2c66affSColin Finck     }
373c2c66affSColin Finck 
374c2c66affSColin Finck     if (pValueName)
375c2c66affSColin Finck     {
376c2c66affSColin Finck         // Convert pValueName to a Unicode string pwszValueName
377c2c66affSColin Finck         cch = strlen(pValueName);
378c2c66affSColin Finck 
379c2c66affSColin Finck         pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
380c2c66affSColin Finck         if (!pwszValueName)
381c2c66affSColin Finck         {
382c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
383c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
384c2c66affSColin Finck             goto Cleanup;
385c2c66affSColin Finck         }
386c2c66affSColin Finck 
387c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
388c2c66affSColin Finck     }
389c2c66affSColin Finck 
390c2c66affSColin Finck     if (Type == REG_SZ || Type == REG_MULTI_SZ || Type == REG_EXPAND_SZ)
391c2c66affSColin Finck     {
392c2c66affSColin Finck         // Convert pData to a Unicode string pUnicodeData.
393c2c66affSColin Finck         pUnicodeData = HeapAlloc(hProcessHeap, 0, cbData * sizeof(WCHAR));
394c2c66affSColin Finck         if (!pUnicodeData)
395c2c66affSColin Finck         {
396c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
397c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
398c2c66affSColin Finck             goto Cleanup;
399c2c66affSColin Finck         }
400c2c66affSColin Finck 
401c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, (PCSTR)pData, -1, pUnicodeData, cbData);
402c2c66affSColin Finck 
403c2c66affSColin Finck         pData = (PBYTE)pUnicodeData;
404c2c66affSColin Finck         cbData *= sizeof(WCHAR);
405c2c66affSColin Finck     }
406c2c66affSColin Finck 
407c2c66affSColin Finck     dwReturnValue = SetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, Type, pData, cbData);
408c2c66affSColin Finck 
409c2c66affSColin Finck Cleanup:
410c2c66affSColin Finck     if (pwszKeyName)
411c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pwszKeyName);
412c2c66affSColin Finck 
413c2c66affSColin Finck     if (pwszValueName)
414c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pwszValueName);
415c2c66affSColin Finck 
416c2c66affSColin Finck     if (pUnicodeData)
417c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pUnicodeData);
418c2c66affSColin Finck 
419c2c66affSColin Finck     return dwReturnValue;
420c2c66affSColin Finck }
421c2c66affSColin Finck 
422c2c66affSColin Finck DWORD WINAPI
423c2c66affSColin Finck SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
424c2c66affSColin Finck {
425c2c66affSColin Finck     const WCHAR wszEmptyString[] = L"";
426c2c66affSColin Finck 
427c2c66affSColin Finck     DWORD dwErrorCode;
428c2c66affSColin Finck     PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
429c2c66affSColin Finck 
4301f6f08ecSColin Finck     TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
4311f6f08ecSColin Finck 
432c2c66affSColin Finck     // Sanity checks
433c2c66affSColin Finck     if (!pHandle)
434c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
435c2c66affSColin Finck 
436c2c66affSColin Finck     if (!pKeyName)
437c2c66affSColin Finck         pKeyName = wszEmptyString;
438c2c66affSColin Finck 
439c2c66affSColin Finck     // Do the RPC call
440c2c66affSColin Finck     RpcTryExcept
441c2c66affSColin Finck     {
442c2c66affSColin Finck         dwErrorCode = _RpcSetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, Type, pData, cbData);
443c2c66affSColin Finck     }
444c2c66affSColin Finck     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
445c2c66affSColin Finck     {
446c2c66affSColin Finck         dwErrorCode = RpcExceptionCode();
447c2c66affSColin Finck     }
448c2c66affSColin Finck     RpcEndExcept;
449c2c66affSColin Finck 
450c2c66affSColin Finck     return dwErrorCode;
451c2c66affSColin Finck }
452c2c66affSColin Finck 
453c2c66affSColin Finck DWORD WINAPI
454c2c66affSColin Finck SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
455c2c66affSColin Finck {
4561f6f08ecSColin Finck     TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
457c2c66affSColin Finck     return SetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, Type, pData, cbData);
458c2c66affSColin Finck }
459