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*7bffb703SJames Tabor AdvancedSetupDialog(HWND hWnd, INT Unknown, PDEVMODEA pDevModeInput, PDEVMODEA pDevModeOutput)
12*7bffb703SJames Tabor {
13*7bffb703SJames Tabor    HANDLE hPrinter;
14*7bffb703SJames Tabor    LONG Ret = -1;
15*7bffb703SJames Tabor 
16*7bffb703SJames Tabor     TRACE("AdvancedSetupDialog(%p, %d, %p, %p)\n", hWnd, Unknown, pDevModeOutput, pDevModeInput);
17*7bffb703SJames Tabor 
18*7bffb703SJames Tabor     if ( OpenPrinterA( (LPSTR)pDevModeInput->dmDeviceName, &hPrinter, NULL ) )
19*7bffb703SJames Tabor     {
20*7bffb703SJames Tabor         Ret = AdvancedDocumentPropertiesA( hWnd, hPrinter, (PSTR)pDevModeInput->dmDeviceName, pDevModeOutput, pDevModeInput );
21*7bffb703SJames Tabor         ClosePrinter(hPrinter);
22*7bffb703SJames Tabor     }
23*7bffb703SJames Tabor     return Ret;
24*7bffb703SJames Tabor }
25*7bffb703SJames Tabor 
26*7bffb703SJames Tabor LONG WINAPI
2746b91659SColin Finck AdvancedDocumentPropertiesA(HWND hWnd, HANDLE hPrinter, PSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput)
2846b91659SColin Finck {
2946b91659SColin Finck     TRACE("AdvancedDocumentPropertiesA(%p, %p, %s, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput);
3046b91659SColin Finck     UNIMPLEMENTED;
3146b91659SColin Finck     return 0;
3246b91659SColin Finck }
3346b91659SColin Finck 
3446b91659SColin Finck LONG WINAPI
35c2c66affSColin Finck AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput)
36c2c66affSColin Finck {
371f6f08ecSColin Finck     TRACE("AdvancedDocumentPropertiesW(%p, %p, %S, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput);
38c2c66affSColin Finck     UNIMPLEMENTED;
3946b91659SColin Finck     return 0;
4046b91659SColin Finck }
4146b91659SColin Finck 
4246b91659SColin Finck DWORD WINAPI
4346b91659SColin Finck DeletePrinterDataA(HANDLE hPrinter, PSTR pValueName)
4446b91659SColin Finck {
45*7bffb703SJames Tabor     LPWSTR  valuenameW = NULL;
46*7bffb703SJames Tabor     INT     len;
47*7bffb703SJames Tabor     DWORD   res;
48*7bffb703SJames Tabor 
4946b91659SColin Finck     TRACE("DeletePrinterDataA(%p, %s)\n", hPrinter, pValueName);
50*7bffb703SJames Tabor 
51*7bffb703SJames Tabor     if (pValueName)
52*7bffb703SJames Tabor     {
53*7bffb703SJames Tabor         len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0);
54*7bffb703SJames Tabor         valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
55*7bffb703SJames Tabor         MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len);
56*7bffb703SJames Tabor     }
57*7bffb703SJames Tabor 
58*7bffb703SJames Tabor     res = DeletePrinterDataW( hPrinter, valuenameW );
59*7bffb703SJames Tabor 
60*7bffb703SJames Tabor     HeapFree(GetProcessHeap(), 0, valuenameW);
61*7bffb703SJames Tabor 
62*7bffb703SJames Tabor     return res;
63*7bffb703SJames Tabor 
6446b91659SColin Finck }
6546b91659SColin Finck 
6646b91659SColin Finck DWORD WINAPI
6746b91659SColin Finck DeletePrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PCSTR pValueName)
6846b91659SColin Finck {
69*7bffb703SJames Tabor     LPWSTR  keynameW = NULL;
70*7bffb703SJames Tabor     LPWSTR  valuenameW = NULL;
71*7bffb703SJames Tabor     INT     len;
72*7bffb703SJames Tabor     DWORD   res;
73*7bffb703SJames Tabor 
7446b91659SColin Finck     TRACE("DeletePrinterDataExA(%p, %s, %s)\n", hPrinter, pKeyName, pValueName);
75*7bffb703SJames Tabor 
76*7bffb703SJames Tabor     if (pKeyName)
77*7bffb703SJames Tabor     {
78*7bffb703SJames Tabor         len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0);
79*7bffb703SJames Tabor         keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
80*7bffb703SJames Tabor         MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len);
81*7bffb703SJames Tabor     }
82*7bffb703SJames Tabor 
83*7bffb703SJames Tabor     if (pValueName)
84*7bffb703SJames Tabor     {
85*7bffb703SJames Tabor         len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0);
86*7bffb703SJames Tabor         valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
87*7bffb703SJames Tabor         MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len);
88*7bffb703SJames Tabor     }
89*7bffb703SJames Tabor 
90*7bffb703SJames Tabor     res = DeletePrinterDataExW( hPrinter, keynameW, valuenameW );
91*7bffb703SJames Tabor 
92*7bffb703SJames Tabor     HeapFree(GetProcessHeap(), 0, keynameW);
93*7bffb703SJames Tabor     HeapFree(GetProcessHeap(), 0, valuenameW);
94*7bffb703SJames Tabor 
95*7bffb703SJames Tabor     return res;
9646b91659SColin Finck }
9746b91659SColin Finck 
9846b91659SColin Finck DWORD WINAPI
9946b91659SColin Finck DeletePrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName)
10046b91659SColin Finck {
10146b91659SColin Finck     TRACE("DeletePrinterDataExW(%p, %S, %S)\n", hPrinter, pKeyName, pValueName);
10246b91659SColin Finck     UNIMPLEMENTED;
10346b91659SColin Finck     return ERROR_NOT_SUPPORTED;
10446b91659SColin Finck }
10546b91659SColin Finck 
10646b91659SColin Finck DWORD WINAPI
10746b91659SColin Finck DeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName)
10846b91659SColin Finck {
10946b91659SColin Finck     TRACE("DeletePrinterDataW(%p, %S)\n", hPrinter, pValueName);
11046b91659SColin Finck     UNIMPLEMENTED;
11146b91659SColin Finck     return ERROR_NOT_SUPPORTED;
11246b91659SColin Finck }
11346b91659SColin Finck 
11446b91659SColin Finck DWORD WINAPI
11546b91659SColin Finck DeletePrinterKeyA(HANDLE hPrinter, PCSTR pKeyName)
11646b91659SColin Finck {
117*7bffb703SJames Tabor     LPWSTR  keynameW = NULL;
118*7bffb703SJames Tabor     INT     len;
119*7bffb703SJames Tabor     DWORD   res;
120*7bffb703SJames Tabor 
12146b91659SColin Finck     TRACE("DeletePrinterKeyA(%p, %s)\n", hPrinter, pKeyName);
122*7bffb703SJames Tabor 
123*7bffb703SJames Tabor     if (pKeyName)
124*7bffb703SJames Tabor     {
125*7bffb703SJames Tabor         len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0);
126*7bffb703SJames Tabor         keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
127*7bffb703SJames Tabor         MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len);
128*7bffb703SJames Tabor     }
129*7bffb703SJames Tabor 
130*7bffb703SJames Tabor     res = DeletePrinterKeyW( hPrinter, keynameW );
131*7bffb703SJames Tabor 
132*7bffb703SJames Tabor     HeapFree(GetProcessHeap(), 0, keynameW);
133*7bffb703SJames Tabor 
134*7bffb703SJames Tabor     return res;
13546b91659SColin Finck }
13646b91659SColin Finck 
13746b91659SColin Finck DWORD WINAPI
13846b91659SColin Finck DeletePrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName)
13946b91659SColin Finck {
14046b91659SColin Finck     TRACE("DeletePrinterKeyW(%p, %S)\n", hPrinter, pKeyName);
14146b91659SColin Finck     UNIMPLEMENTED;
14246b91659SColin Finck     return ERROR_NOT_SUPPORTED;
14346b91659SColin Finck }
14446b91659SColin Finck 
14546b91659SColin Finck DWORD WINAPI
14646b91659SColin Finck EnumPrinterDataA(HANDLE hPrinter, DWORD dwIndex, PSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
14746b91659SColin Finck {
14846b91659SColin Finck     TRACE("EnumPrinterDataA(%p, %lu, %s, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
14946b91659SColin Finck     UNIMPLEMENTED;
15046b91659SColin Finck     return ERROR_NOT_SUPPORTED;
15146b91659SColin Finck }
15246b91659SColin Finck 
15346b91659SColin Finck DWORD WINAPI
15446b91659SColin Finck EnumPrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
15546b91659SColin Finck {
156*7bffb703SJames Tabor     INT	    len;
157*7bffb703SJames Tabor     LPWSTR  pKeyNameW;
158*7bffb703SJames Tabor     DWORD   ret, dwIndex, dwBufSize;
159*7bffb703SJames Tabor     HANDLE  hHeap;
160*7bffb703SJames Tabor     LPSTR   pBuffer;
161*7bffb703SJames Tabor 
16246b91659SColin Finck     TRACE("EnumPrinterDataExA(%p, %s, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
163*7bffb703SJames Tabor 
164*7bffb703SJames Tabor     if (pKeyName == NULL || *pKeyName == 0)
165*7bffb703SJames Tabor 	return ERROR_INVALID_PARAMETER;
166*7bffb703SJames Tabor 
167*7bffb703SJames Tabor     len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0);
168*7bffb703SJames Tabor     if (len == 0)
169*7bffb703SJames Tabor     {
170*7bffb703SJames Tabor 	ret = GetLastError ();
171*7bffb703SJames Tabor 	ERR ("MultiByteToWideChar failed with code %i\n", ret);
172*7bffb703SJames Tabor 	return ret;
173*7bffb703SJames Tabor     }
174*7bffb703SJames Tabor 
175*7bffb703SJames Tabor     hHeap = GetProcessHeap ();
176*7bffb703SJames Tabor     if (hHeap == NULL)
177*7bffb703SJames Tabor     {
178*7bffb703SJames Tabor 	ERR ("GetProcessHeap failed\n");
179*7bffb703SJames Tabor 	return ERROR_OUTOFMEMORY;
180*7bffb703SJames Tabor     }
181*7bffb703SJames Tabor 
182*7bffb703SJames Tabor     pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR));
183*7bffb703SJames Tabor     if (pKeyNameW == NULL)
184*7bffb703SJames Tabor     {
185*7bffb703SJames Tabor 	ERR ("Failed to allocate %i bytes from process heap\n",
186*7bffb703SJames Tabor              (LONG)(len * sizeof (WCHAR)));
187*7bffb703SJames Tabor 	return ERROR_OUTOFMEMORY;
188*7bffb703SJames Tabor     }
189*7bffb703SJames Tabor 
190*7bffb703SJames Tabor     if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0)
191*7bffb703SJames Tabor     {
192*7bffb703SJames Tabor 	ret = GetLastError ();
193*7bffb703SJames Tabor 	ERR ("MultiByteToWideChar failed with code %i\n", ret);
194*7bffb703SJames Tabor 	if (HeapFree (hHeap, 0, pKeyNameW) == 0)
195*7bffb703SJames Tabor 	    WARN ("HeapFree failed with code %i\n", GetLastError ());
196*7bffb703SJames Tabor 	return ret;
197*7bffb703SJames Tabor     }
198*7bffb703SJames Tabor 
199*7bffb703SJames Tabor     ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
200*7bffb703SJames Tabor 
201*7bffb703SJames Tabor     if (ret != ERROR_SUCCESS)
202*7bffb703SJames Tabor     {
203*7bffb703SJames Tabor 	if (HeapFree (hHeap, 0, pKeyNameW) == 0)
204*7bffb703SJames Tabor 	    WARN ("HeapFree failed with code %i\n", GetLastError ());
205*7bffb703SJames Tabor 	TRACE ("EnumPrinterDataExW returned %i\n", ret);
206*7bffb703SJames Tabor 	return ret;
207*7bffb703SJames Tabor     }
208*7bffb703SJames Tabor 
209*7bffb703SJames Tabor     if (HeapFree (hHeap, 0, pKeyNameW) == 0)
210*7bffb703SJames Tabor     {
211*7bffb703SJames Tabor 	ret = GetLastError ();
212*7bffb703SJames Tabor 	ERR ("HeapFree failed with code %i\n", ret);
213*7bffb703SJames Tabor 	return ret;
214*7bffb703SJames Tabor     }
215*7bffb703SJames Tabor 
216*7bffb703SJames Tabor     if (*pnEnumValues == 0)	/* empty key */
217*7bffb703SJames Tabor 	return ERROR_SUCCESS;
218*7bffb703SJames Tabor 
219*7bffb703SJames Tabor     dwBufSize = 0;
220*7bffb703SJames Tabor     for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
221*7bffb703SJames Tabor     {
222*7bffb703SJames Tabor 	PPRINTER_ENUM_VALUESW ppev =
223*7bffb703SJames Tabor 		&((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
224*7bffb703SJames Tabor 
225*7bffb703SJames Tabor 	if (dwBufSize < ppev->cbValueName)
226*7bffb703SJames Tabor 	    dwBufSize = ppev->cbValueName;
227*7bffb703SJames Tabor 
228*7bffb703SJames Tabor 	if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ ||
229*7bffb703SJames Tabor 		ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
230*7bffb703SJames Tabor 	    dwBufSize = ppev->cbData;
231*7bffb703SJames Tabor     }
232*7bffb703SJames Tabor 
233*7bffb703SJames Tabor     TRACE ("Largest Unicode name or value is %i bytes\n", dwBufSize);
234*7bffb703SJames Tabor 
235*7bffb703SJames Tabor     pBuffer = HeapAlloc (hHeap, 0, dwBufSize);
236*7bffb703SJames Tabor     if (pBuffer == NULL)
237*7bffb703SJames Tabor     {
238*7bffb703SJames Tabor 	ERR ("Failed to allocate %i bytes from process heap\n", dwBufSize);
239*7bffb703SJames Tabor 	return ERROR_OUTOFMEMORY;
240*7bffb703SJames Tabor     }
241*7bffb703SJames Tabor 
242*7bffb703SJames Tabor     for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
243*7bffb703SJames Tabor     {
244*7bffb703SJames Tabor 	PPRINTER_ENUM_VALUESW ppev =
245*7bffb703SJames Tabor 		&((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
246*7bffb703SJames Tabor 
247*7bffb703SJames Tabor 	len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName,
248*7bffb703SJames Tabor 		ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL,
249*7bffb703SJames Tabor 		NULL);
250*7bffb703SJames Tabor 	if (len == 0)
251*7bffb703SJames Tabor 	{
252*7bffb703SJames Tabor 	    ret = GetLastError ();
253*7bffb703SJames Tabor 	    ERR ("WideCharToMultiByte failed with code %i\n", ret);
254*7bffb703SJames Tabor 	    if (HeapFree (hHeap, 0, pBuffer) == 0)
255*7bffb703SJames Tabor 		WARN ("HeapFree failed with code %i\n", GetLastError ());
256*7bffb703SJames Tabor 	    return ret;
257*7bffb703SJames Tabor 	}
258*7bffb703SJames Tabor 
259*7bffb703SJames Tabor 	memcpy (ppev->pValueName, pBuffer, len);
260*7bffb703SJames Tabor 
261*7bffb703SJames Tabor 	TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
262*7bffb703SJames Tabor 
263*7bffb703SJames Tabor 	if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ &&
264*7bffb703SJames Tabor 		ppev->dwType != REG_MULTI_SZ)
265*7bffb703SJames Tabor 	    continue;
266*7bffb703SJames Tabor 
267*7bffb703SJames Tabor 	len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData,
268*7bffb703SJames Tabor 		ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL);
269*7bffb703SJames Tabor 	if (len == 0)
270*7bffb703SJames Tabor 	{
271*7bffb703SJames Tabor 	    ret = GetLastError ();
272*7bffb703SJames Tabor 	    ERR ("WideCharToMultiByte failed with code %i\n", ret);
273*7bffb703SJames Tabor 	    if (HeapFree (hHeap, 0, pBuffer) == 0)
274*7bffb703SJames Tabor 		WARN ("HeapFree failed with code %i\n", GetLastError ());
275*7bffb703SJames Tabor 	    return ret;
276*7bffb703SJames Tabor 	}
277*7bffb703SJames Tabor 
278*7bffb703SJames Tabor 	memcpy (ppev->pData, pBuffer, len);
279*7bffb703SJames Tabor 
280*7bffb703SJames Tabor 	TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
281*7bffb703SJames Tabor 	TRACE ("  (only first string of REG_MULTI_SZ printed)\n");
282*7bffb703SJames Tabor     }
283*7bffb703SJames Tabor 
284*7bffb703SJames Tabor     if (HeapFree (hHeap, 0, pBuffer) == 0)
285*7bffb703SJames Tabor     {
286*7bffb703SJames Tabor 	ret = GetLastError ();
287*7bffb703SJames Tabor 	ERR ("HeapFree failed with code %i\n", ret);
288*7bffb703SJames Tabor 	return ret;
289*7bffb703SJames Tabor     }
290*7bffb703SJames Tabor 
291*7bffb703SJames Tabor     return ERROR_SUCCESS;
29246b91659SColin Finck }
29346b91659SColin Finck 
29446b91659SColin Finck DWORD WINAPI
29546b91659SColin Finck EnumPrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
29646b91659SColin Finck {
29746b91659SColin Finck     TRACE("EnumPrinterDataExW(%p, %S, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
29846b91659SColin Finck     UNIMPLEMENTED;
29946b91659SColin Finck     return ERROR_NOT_SUPPORTED;
30046b91659SColin Finck }
30146b91659SColin Finck 
30246b91659SColin Finck DWORD WINAPI
30346b91659SColin Finck EnumPrinterDataW(HANDLE hPrinter, DWORD dwIndex, PWSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
30446b91659SColin Finck {
30546b91659SColin Finck     TRACE("EnumPrinterDataW(%p, %lu, %S, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
30646b91659SColin Finck     UNIMPLEMENTED;
30746b91659SColin Finck     return ERROR_NOT_SUPPORTED;
30846b91659SColin Finck }
30946b91659SColin Finck 
31046b91659SColin Finck DWORD WINAPI
31146b91659SColin Finck EnumPrinterKeyA(HANDLE hPrinter, PCSTR pKeyName, PSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
31246b91659SColin Finck {
31346b91659SColin Finck     TRACE("EnumPrinterKeyA(%p, %s, %s, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
31446b91659SColin Finck     UNIMPLEMENTED;
31546b91659SColin Finck     return ERROR_NOT_SUPPORTED;
31646b91659SColin Finck }
31746b91659SColin Finck 
31846b91659SColin Finck DWORD WINAPI
31946b91659SColin Finck EnumPrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName, PWSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
32046b91659SColin Finck {
32146b91659SColin Finck     TRACE("EnumPrinterKeyW(%p, %S, %S, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
32246b91659SColin Finck     UNIMPLEMENTED;
32346b91659SColin Finck     return ERROR_NOT_SUPPORTED;
324c2c66affSColin Finck }
325c2c66affSColin Finck 
326c2c66affSColin Finck DWORD WINAPI
327c2c66affSColin Finck GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
328c2c66affSColin Finck {
3291f6f08ecSColin Finck     TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
330c2c66affSColin Finck     return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
331c2c66affSColin Finck }
332c2c66affSColin Finck 
333c2c66affSColin Finck DWORD WINAPI
334c2c66affSColin Finck GetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
335c2c66affSColin Finck {
336c2c66affSColin Finck     DWORD cbUnicodeData;
337c2c66affSColin Finck     DWORD cch;
338c2c66affSColin Finck     DWORD dwReturnValue;
339c2c66affSColin Finck     DWORD dwType;
340c2c66affSColin Finck     POSVERSIONINFOEXA pInfoA;
341c2c66affSColin Finck     POSVERSIONINFOEXW pInfoW;
342c2c66affSColin Finck     PVOID pUnicodeData = NULL;
343c2c66affSColin Finck     PWSTR pwszKeyName = NULL;
344c2c66affSColin Finck     PWSTR pwszValueName = NULL;
345c2c66affSColin Finck 
3461f6f08ecSColin Finck     TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
3471f6f08ecSColin Finck 
348c2c66affSColin Finck     if (pKeyName)
349c2c66affSColin Finck     {
350c2c66affSColin Finck         // Convert pKeyName to a Unicode string pwszKeyName
351c2c66affSColin Finck         cch = strlen(pKeyName);
352c2c66affSColin Finck 
353c2c66affSColin Finck         pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
354c2c66affSColin Finck         if (!pwszKeyName)
355c2c66affSColin Finck         {
356c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
357c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
358c2c66affSColin Finck             goto Cleanup;
359c2c66affSColin Finck         }
360c2c66affSColin Finck 
361c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
362c2c66affSColin Finck     }
363c2c66affSColin Finck 
364c2c66affSColin Finck     if (pValueName)
365c2c66affSColin Finck     {
366c2c66affSColin Finck         // Convert pValueName to a Unicode string pwszValueName
367c2c66affSColin Finck         cch = strlen(pValueName);
368c2c66affSColin Finck 
369c2c66affSColin Finck         pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
370c2c66affSColin Finck         if (!pwszValueName)
371c2c66affSColin Finck         {
372c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
373c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
374c2c66affSColin Finck             goto Cleanup;
375c2c66affSColin Finck         }
376c2c66affSColin Finck 
377c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
378c2c66affSColin Finck     }
379c2c66affSColin Finck 
380c2c66affSColin Finck     // We need the data type information, even if no pData was passed.
381c2c66affSColin Finck     if (!pType)
382c2c66affSColin Finck         pType = &dwType;
383c2c66affSColin Finck 
384c2c66affSColin Finck     // Call GetPrinterDataExW for the first time.
385c2c66affSColin 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.
386c2c66affSColin Finck     dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, pType, pData, nSize, pcbNeeded);
387c2c66affSColin Finck 
388c2c66affSColin Finck     // If a critical error occurred, just return it. We cannot do anything else in this case.
389c2c66affSColin Finck     if (dwReturnValue != ERROR_SUCCESS && dwReturnValue != ERROR_MORE_DATA)
390c2c66affSColin Finck         goto Cleanup;
391c2c66affSColin Finck 
392c2c66affSColin Finck     // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size.
393c2c66affSColin Finck     cbUnicodeData = *pcbNeeded;
394c2c66affSColin Finck 
395c2c66affSColin Finck     if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
396c2c66affSColin Finck     {
397c2c66affSColin Finck         // This is a string that needs to be converted from Unicode to ANSI.
398c2c66affSColin Finck         // Output the required buffer size for the ANSI string.
399c2c66affSColin Finck         *pcbNeeded /= sizeof(WCHAR);
400c2c66affSColin Finck     }
401c2c66affSColin Finck     else if (*pType == REG_NONE)
402c2c66affSColin Finck     {
403c2c66affSColin Finck         if (cbUnicodeData == sizeof(OSVERSIONINFOW) && wcsicmp(pwszValueName, SPLREG_OS_VERSION) == 0)
404c2c66affSColin Finck         {
405c2c66affSColin Finck             // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA.
406c2c66affSColin Finck             *pcbNeeded = sizeof(OSVERSIONINFOA);
407c2c66affSColin Finck         }
408c2c66affSColin Finck         else if (cbUnicodeData == sizeof(OSVERSIONINFOEXW) && wcsicmp(pwszValueName, SPLREG_OS_VERSIONEX) == 0)
409c2c66affSColin Finck         {
410c2c66affSColin Finck             // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA.
411c2c66affSColin Finck             *pcbNeeded = sizeof(OSVERSIONINFOEXA);
412c2c66affSColin Finck         }
413c2c66affSColin Finck         else
414c2c66affSColin Finck         {
415c2c66affSColin Finck             // Other REG_NONE value, nothing to do.
416c2c66affSColin Finck             goto Cleanup;
417c2c66affSColin Finck         }
418c2c66affSColin Finck     }
419c2c66affSColin Finck 
420c2c66affSColin Finck     // Check if the supplied buffer is large enough for the ANSI data.
421c2c66affSColin Finck     if (nSize < *pcbNeeded)
422c2c66affSColin Finck     {
423c2c66affSColin Finck         dwReturnValue = ERROR_MORE_DATA;
424c2c66affSColin Finck         goto Cleanup;
425c2c66affSColin Finck     }
426c2c66affSColin Finck 
427c2c66affSColin Finck     // Allocate a temporary buffer for the Unicode data.
428c2c66affSColin Finck     pUnicodeData = HeapAlloc(hProcessHeap, 0, cbUnicodeData);
429c2c66affSColin Finck     if (!pUnicodeData)
430c2c66affSColin Finck     {
431c2c66affSColin Finck         dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
432c2c66affSColin Finck         ERR("HeapAlloc failed!\n");
433c2c66affSColin Finck         goto Cleanup;
434c2c66affSColin Finck     }
435c2c66affSColin Finck 
436c2c66affSColin Finck     if (dwReturnValue == ERROR_SUCCESS)
437c2c66affSColin Finck     {
438c2c66affSColin Finck         // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string,
439c2c66affSColin Finck         // so the Unicode string has been copied into pData. Copy it to pUnicodeData.
440c2c66affSColin Finck         CopyMemory(pUnicodeData, pData, cbUnicodeData);
441c2c66affSColin Finck     }
442c2c66affSColin Finck     else
443c2c66affSColin Finck     {
444c2c66affSColin Finck         // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string.
445c2c66affSColin Finck         // We have to call GetPrinterDataExW again with the temporary buffer.
446c2c66affSColin Finck         dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, NULL, (PBYTE)pUnicodeData, cbUnicodeData, &cbUnicodeData);
447c2c66affSColin Finck         if (dwReturnValue != ERROR_SUCCESS)
448c2c66affSColin Finck             goto Cleanup;
449c2c66affSColin Finck     }
450c2c66affSColin Finck 
451c2c66affSColin Finck     if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
452c2c66affSColin Finck     {
453c2c66affSColin Finck         // Convert the Unicode string to ANSI.
454c2c66affSColin Finck         WideCharToMultiByte(CP_ACP, 0, (PWSTR)pUnicodeData, -1, (PSTR)pData, *pcbNeeded, NULL, NULL);
455c2c66affSColin Finck     }
456c2c66affSColin Finck     else
457c2c66affSColin Finck     {
458c2c66affSColin Finck         // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW.
459c2c66affSColin Finck         // Copy the fields and convert the Unicode CSD Version string to ANSI.
460c2c66affSColin Finck         pInfoW = (POSVERSIONINFOEXW)pUnicodeData;
461c2c66affSColin Finck         pInfoA = (POSVERSIONINFOEXA)pData;
462c2c66affSColin Finck         pInfoA->dwMajorVersion = pInfoW->dwMajorVersion;
463c2c66affSColin Finck         pInfoA->dwMinorVersion = pInfoW->dwMinorVersion;
464c2c66affSColin Finck         pInfoA->dwBuildNumber = pInfoW->dwBuildNumber;
465c2c66affSColin Finck         pInfoA->dwPlatformId = pInfoW->dwPlatformId;
466c2c66affSColin Finck         WideCharToMultiByte(CP_ACP, 0, pInfoW->szCSDVersion, -1, pInfoA->szCSDVersion, sizeof(pInfoA->szCSDVersion), NULL, NULL);
467c2c66affSColin Finck 
468c2c66affSColin Finck         if (cbUnicodeData == sizeof(OSVERSIONINFOW))
469c2c66affSColin Finck         {
470c2c66affSColin Finck             pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
471c2c66affSColin Finck         }
472c2c66affSColin Finck         else
473c2c66affSColin Finck         {
474c2c66affSColin Finck             pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
475c2c66affSColin Finck             pInfoA->wServicePackMajor = pInfoW->wServicePackMajor;
476c2c66affSColin Finck             pInfoA->wServicePackMinor = pInfoW->wServicePackMinor;
477c2c66affSColin Finck             pInfoA->wSuiteMask = pInfoW->wSuiteMask;
478c2c66affSColin Finck             pInfoA->wProductType = pInfoW->wProductType;
479c2c66affSColin Finck             pInfoA->wReserved = pInfoW->wReserved;
480c2c66affSColin Finck         }
481c2c66affSColin Finck     }
482c2c66affSColin Finck 
483c2c66affSColin Finck Cleanup:
484c2c66affSColin Finck     if (pwszKeyName)
485c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pwszKeyName);
486c2c66affSColin Finck 
487c2c66affSColin Finck     if (pwszValueName)
488c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pwszValueName);
489c2c66affSColin Finck 
490c2c66affSColin Finck     if (pUnicodeData)
491c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pUnicodeData);
492c2c66affSColin Finck 
493c2c66affSColin Finck     return dwReturnValue;
494c2c66affSColin Finck }
495c2c66affSColin Finck 
496c2c66affSColin Finck DWORD WINAPI
497c2c66affSColin Finck GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
498c2c66affSColin Finck {
499c2c66affSColin Finck     const WCHAR wszEmptyString[] = L"";
500c2c66affSColin Finck 
501c2c66affSColin Finck     BYTE DummyData;
502c2c66affSColin Finck     DWORD dwErrorCode;
503c2c66affSColin Finck     DWORD dwType = REG_NONE;
504c2c66affSColin Finck     PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
505c2c66affSColin Finck 
5061f6f08ecSColin Finck     TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
5071f6f08ecSColin Finck 
508c2c66affSColin Finck     // Sanity checks
509c2c66affSColin Finck     if (!pHandle)
510c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
511c2c66affSColin Finck 
512c2c66affSColin Finck     // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way),
513c2c66affSColin Finck     // Windows does it differently for GetPrinterDataExW and points them to empty variables.
514c2c66affSColin Finck     if (!pKeyName)
515c2c66affSColin Finck         pKeyName = wszEmptyString;
516c2c66affSColin Finck 
517c2c66affSColin Finck     if (!pType)
518c2c66affSColin Finck         pType = &dwType;
519c2c66affSColin Finck 
520c2c66affSColin Finck     if (!pData && !nSize)
521c2c66affSColin Finck         pData = &DummyData;
522c2c66affSColin Finck 
523c2c66affSColin Finck     // Do the RPC call
524c2c66affSColin Finck     RpcTryExcept
525c2c66affSColin Finck     {
526c2c66affSColin Finck         dwErrorCode = _RpcGetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
527c2c66affSColin Finck     }
528c2c66affSColin Finck     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
529c2c66affSColin Finck     {
530c2c66affSColin Finck         dwErrorCode = RpcExceptionCode();
531c2c66affSColin Finck     }
532c2c66affSColin Finck     RpcEndExcept;
533c2c66affSColin Finck 
534c2c66affSColin Finck     return dwErrorCode;
535c2c66affSColin Finck }
536c2c66affSColin Finck 
537c2c66affSColin Finck DWORD WINAPI
538c2c66affSColin Finck GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
539c2c66affSColin Finck {
5401f6f08ecSColin Finck     TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
541c2c66affSColin Finck     return GetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
542c2c66affSColin Finck }
543c2c66affSColin Finck 
544c2c66affSColin Finck DWORD WINAPI
545c2c66affSColin Finck SetPrinterDataA(HANDLE hPrinter, PSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
546c2c66affSColin Finck {
5471f6f08ecSColin Finck     TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
548c2c66affSColin Finck     return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type, pData, cbData);
549c2c66affSColin Finck }
550c2c66affSColin Finck 
551c2c66affSColin Finck DWORD WINAPI
552c2c66affSColin Finck SetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
553c2c66affSColin Finck {
554c2c66affSColin Finck     DWORD cch;
555c2c66affSColin Finck     DWORD dwReturnValue;
556c2c66affSColin Finck     PWSTR pwszKeyName = NULL;
557c2c66affSColin Finck     PWSTR pwszValueName = NULL;
558c2c66affSColin Finck     PWSTR pUnicodeData = NULL;
559c2c66affSColin Finck 
5601f6f08ecSColin Finck     TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
5611f6f08ecSColin Finck 
562c2c66affSColin Finck     if (pKeyName)
563c2c66affSColin Finck     {
564c2c66affSColin Finck         // Convert pKeyName to a Unicode string pwszKeyName
565c2c66affSColin Finck         cch = strlen(pKeyName);
566c2c66affSColin Finck 
567c2c66affSColin Finck         pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
568c2c66affSColin Finck         if (!pwszKeyName)
569c2c66affSColin Finck         {
570c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
571c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
572c2c66affSColin Finck             goto Cleanup;
573c2c66affSColin Finck         }
574c2c66affSColin Finck 
575c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
576c2c66affSColin Finck     }
577c2c66affSColin Finck 
578c2c66affSColin Finck     if (pValueName)
579c2c66affSColin Finck     {
580c2c66affSColin Finck         // Convert pValueName to a Unicode string pwszValueName
581c2c66affSColin Finck         cch = strlen(pValueName);
582c2c66affSColin Finck 
583c2c66affSColin Finck         pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
584c2c66affSColin Finck         if (!pwszValueName)
585c2c66affSColin Finck         {
586c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
587c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
588c2c66affSColin Finck             goto Cleanup;
589c2c66affSColin Finck         }
590c2c66affSColin Finck 
591c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
592c2c66affSColin Finck     }
593c2c66affSColin Finck 
594c2c66affSColin Finck     if (Type == REG_SZ || Type == REG_MULTI_SZ || Type == REG_EXPAND_SZ)
595c2c66affSColin Finck     {
596c2c66affSColin Finck         // Convert pData to a Unicode string pUnicodeData.
597c2c66affSColin Finck         pUnicodeData = HeapAlloc(hProcessHeap, 0, cbData * sizeof(WCHAR));
598c2c66affSColin Finck         if (!pUnicodeData)
599c2c66affSColin Finck         {
600c2c66affSColin Finck             dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
601c2c66affSColin Finck             ERR("HeapAlloc failed!\n");
602c2c66affSColin Finck             goto Cleanup;
603c2c66affSColin Finck         }
604c2c66affSColin Finck 
605c2c66affSColin Finck         MultiByteToWideChar(CP_ACP, 0, (PCSTR)pData, -1, pUnicodeData, cbData);
606c2c66affSColin Finck 
607c2c66affSColin Finck         pData = (PBYTE)pUnicodeData;
608c2c66affSColin Finck         cbData *= sizeof(WCHAR);
609c2c66affSColin Finck     }
610c2c66affSColin Finck 
611c2c66affSColin Finck     dwReturnValue = SetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, Type, pData, cbData);
612c2c66affSColin Finck 
613c2c66affSColin Finck Cleanup:
614c2c66affSColin Finck     if (pwszKeyName)
615c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pwszKeyName);
616c2c66affSColin Finck 
617c2c66affSColin Finck     if (pwszValueName)
618c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pwszValueName);
619c2c66affSColin Finck 
620c2c66affSColin Finck     if (pUnicodeData)
621c2c66affSColin Finck         HeapFree(hProcessHeap, 0, pUnicodeData);
622c2c66affSColin Finck 
623c2c66affSColin Finck     return dwReturnValue;
624c2c66affSColin Finck }
625c2c66affSColin Finck 
626c2c66affSColin Finck DWORD WINAPI
627c2c66affSColin Finck SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
628c2c66affSColin Finck {
629c2c66affSColin Finck     const WCHAR wszEmptyString[] = L"";
630c2c66affSColin Finck 
631c2c66affSColin Finck     DWORD dwErrorCode;
632c2c66affSColin Finck     PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
633c2c66affSColin Finck 
6341f6f08ecSColin Finck     TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
6351f6f08ecSColin Finck 
636c2c66affSColin Finck     // Sanity checks
637c2c66affSColin Finck     if (!pHandle)
638c2c66affSColin Finck         return ERROR_INVALID_HANDLE;
639c2c66affSColin Finck 
640c2c66affSColin Finck     if (!pKeyName)
641c2c66affSColin Finck         pKeyName = wszEmptyString;
642c2c66affSColin Finck 
643c2c66affSColin Finck     // Do the RPC call
644c2c66affSColin Finck     RpcTryExcept
645c2c66affSColin Finck     {
646c2c66affSColin Finck         dwErrorCode = _RpcSetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, Type, pData, cbData);
647c2c66affSColin Finck     }
648c2c66affSColin Finck     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
649c2c66affSColin Finck     {
650c2c66affSColin Finck         dwErrorCode = RpcExceptionCode();
651c2c66affSColin Finck     }
652c2c66affSColin Finck     RpcEndExcept;
653c2c66affSColin Finck 
654c2c66affSColin Finck     return dwErrorCode;
655c2c66affSColin Finck }
656c2c66affSColin Finck 
657c2c66affSColin Finck DWORD WINAPI
658c2c66affSColin Finck SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
659c2c66affSColin Finck {
6601f6f08ecSColin Finck     TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
661c2c66affSColin Finck     return SetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, Type, pData, cbData);
662c2c66affSColin Finck }
663