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)
11 AdvancedDocumentPropertiesA(HWND hWnd
, HANDLE hPrinter
, PSTR pDeviceName
, PDEVMODEA pDevModeOutput
, PDEVMODEA pDevModeInput
)
13 TRACE("AdvancedDocumentPropertiesA(%p, %p, %s, %p, %p)\n", hWnd
, hPrinter
, pDeviceName
, pDevModeOutput
, pDevModeInput
);
19 AdvancedDocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
, PWSTR pDeviceName
, PDEVMODEW pDevModeOutput
, PDEVMODEW pDevModeInput
)
21 TRACE("AdvancedDocumentPropertiesW(%p, %p, %S, %p, %p)\n", hWnd
, hPrinter
, pDeviceName
, pDevModeOutput
, pDevModeInput
);
27 DeletePrinterDataA(HANDLE hPrinter
, PSTR pValueName
)
29 TRACE("DeletePrinterDataA(%p, %s)\n", hPrinter
, pValueName
);
31 return ERROR_NOT_SUPPORTED
;
35 DeletePrinterDataExA(HANDLE hPrinter
, PCSTR pKeyName
, PCSTR pValueName
)
37 TRACE("DeletePrinterDataExA(%p, %s, %s)\n", hPrinter
, pKeyName
, pValueName
);
39 return ERROR_NOT_SUPPORTED
;
43 DeletePrinterDataExW(HANDLE hPrinter
, PCWSTR pKeyName
, PCWSTR pValueName
)
45 TRACE("DeletePrinterDataExW(%p, %S, %S)\n", hPrinter
, pKeyName
, pValueName
);
47 return ERROR_NOT_SUPPORTED
;
51 DeletePrinterDataW(HANDLE hPrinter
, PWSTR pValueName
)
53 TRACE("DeletePrinterDataW(%p, %S)\n", hPrinter
, pValueName
);
55 return ERROR_NOT_SUPPORTED
;
59 DeletePrinterKeyA(HANDLE hPrinter
, PCSTR pKeyName
)
61 TRACE("DeletePrinterKeyA(%p, %s)\n", hPrinter
, pKeyName
);
63 return ERROR_NOT_SUPPORTED
;
67 DeletePrinterKeyW(HANDLE hPrinter
, PCWSTR pKeyName
)
69 TRACE("DeletePrinterKeyW(%p, %S)\n", hPrinter
, pKeyName
);
71 return ERROR_NOT_SUPPORTED
;
75 EnumPrinterDataA(HANDLE hPrinter
, DWORD dwIndex
, PSTR pValueName
, DWORD cbValueName
, PDWORD pcbValueName
, PDWORD pType
, PBYTE pData
, DWORD cbData
, PDWORD pcbData
)
77 TRACE("EnumPrinterDataA(%p, %lu, %s, %lu, %p, %p, %p, %lu, %p)\n", hPrinter
, dwIndex
, pValueName
, cbValueName
, pcbValueName
, pType
, pData
, cbData
, pcbData
);
79 return ERROR_NOT_SUPPORTED
;
83 EnumPrinterDataExA(HANDLE hPrinter
, PCSTR pKeyName
, PBYTE pEnumValues
, DWORD cbEnumValues
, PDWORD pcbEnumValues
, PDWORD pnEnumValues
)
85 TRACE("EnumPrinterDataExA(%p, %s, %p, %lu, %p, %p)\n", hPrinter
, pKeyName
, pEnumValues
, cbEnumValues
, pcbEnumValues
, pnEnumValues
);
87 return ERROR_NOT_SUPPORTED
;
91 EnumPrinterDataExW(HANDLE hPrinter
, PCWSTR pKeyName
, PBYTE pEnumValues
, DWORD cbEnumValues
, PDWORD pcbEnumValues
, PDWORD pnEnumValues
)
93 TRACE("EnumPrinterDataExW(%p, %S, %p, %lu, %p, %p)\n", hPrinter
, pKeyName
, pEnumValues
, cbEnumValues
, pcbEnumValues
, pnEnumValues
);
95 return ERROR_NOT_SUPPORTED
;
99 EnumPrinterDataW(HANDLE hPrinter
, DWORD dwIndex
, PWSTR pValueName
, DWORD cbValueName
, PDWORD pcbValueName
, PDWORD pType
, PBYTE pData
, DWORD cbData
, PDWORD pcbData
)
101 TRACE("EnumPrinterDataW(%p, %lu, %S, %lu, %p, %p, %p, %lu, %p)\n", hPrinter
, dwIndex
, pValueName
, cbValueName
, pcbValueName
, pType
, pData
, cbData
, pcbData
);
103 return ERROR_NOT_SUPPORTED
;
107 EnumPrinterKeyA(HANDLE hPrinter
, PCSTR pKeyName
, PSTR pSubkey
, DWORD cbSubkey
, PDWORD pcbSubkey
)
109 TRACE("EnumPrinterKeyA(%p, %s, %s, %lu, %p)\n", hPrinter
, pKeyName
, pSubkey
, cbSubkey
, pcbSubkey
);
111 return ERROR_NOT_SUPPORTED
;
115 EnumPrinterKeyW(HANDLE hPrinter
, PCWSTR pKeyName
, PWSTR pSubkey
, DWORD cbSubkey
, PDWORD pcbSubkey
)
117 TRACE("EnumPrinterKeyW(%p, %S, %S, %lu, %p)\n", hPrinter
, pKeyName
, pSubkey
, cbSubkey
, pcbSubkey
);
119 return ERROR_NOT_SUPPORTED
;
123 GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
125 TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
126 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
, pData
, nSize
, pcbNeeded
);
130 GetPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
, LPCSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
136 POSVERSIONINFOEXA pInfoA
;
137 POSVERSIONINFOEXW pInfoW
;
138 PVOID pUnicodeData
= NULL
;
139 PWSTR pwszKeyName
= NULL
;
140 PWSTR pwszValueName
= NULL
;
142 TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter
, pKeyName
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
146 // Convert pKeyName to a Unicode string pwszKeyName
147 cch
= strlen(pKeyName
);
149 pwszKeyName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
152 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
153 ERR("HeapAlloc failed!\n");
157 MultiByteToWideChar(CP_ACP
, 0, pKeyName
, -1, pwszKeyName
, cch
+ 1);
162 // Convert pValueName to a Unicode string pwszValueName
163 cch
= strlen(pValueName
);
165 pwszValueName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
168 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
169 ERR("HeapAlloc failed!\n");
173 MultiByteToWideChar(CP_ACP
, 0, pValueName
, -1, pwszValueName
, cch
+ 1);
176 // We need the data type information, even if no pData was passed.
180 // Call GetPrinterDataExW for the first time.
181 // 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.
182 dwReturnValue
= GetPrinterDataExW(hPrinter
, pwszKeyName
, pwszValueName
, pType
, pData
, nSize
, pcbNeeded
);
184 // If a critical error occurred, just return it. We cannot do anything else in this case.
185 if (dwReturnValue
!= ERROR_SUCCESS
&& dwReturnValue
!= ERROR_MORE_DATA
)
188 // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size.
189 cbUnicodeData
= *pcbNeeded
;
191 if (*pType
== REG_SZ
|| *pType
== REG_MULTI_SZ
|| *pType
== REG_EXPAND_SZ
)
193 // This is a string that needs to be converted from Unicode to ANSI.
194 // Output the required buffer size for the ANSI string.
195 *pcbNeeded
/= sizeof(WCHAR
);
197 else if (*pType
== REG_NONE
)
199 if (cbUnicodeData
== sizeof(OSVERSIONINFOW
) && wcsicmp(pwszValueName
, SPLREG_OS_VERSION
) == 0)
201 // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA.
202 *pcbNeeded
= sizeof(OSVERSIONINFOA
);
204 else if (cbUnicodeData
== sizeof(OSVERSIONINFOEXW
) && wcsicmp(pwszValueName
, SPLREG_OS_VERSIONEX
) == 0)
206 // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA.
207 *pcbNeeded
= sizeof(OSVERSIONINFOEXA
);
211 // Other REG_NONE value, nothing to do.
216 // Check if the supplied buffer is large enough for the ANSI data.
217 if (nSize
< *pcbNeeded
)
219 dwReturnValue
= ERROR_MORE_DATA
;
223 // Allocate a temporary buffer for the Unicode data.
224 pUnicodeData
= HeapAlloc(hProcessHeap
, 0, cbUnicodeData
);
227 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
228 ERR("HeapAlloc failed!\n");
232 if (dwReturnValue
== ERROR_SUCCESS
)
234 // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string,
235 // so the Unicode string has been copied into pData. Copy it to pUnicodeData.
236 CopyMemory(pUnicodeData
, pData
, cbUnicodeData
);
240 // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string.
241 // We have to call GetPrinterDataExW again with the temporary buffer.
242 dwReturnValue
= GetPrinterDataExW(hPrinter
, pwszKeyName
, pwszValueName
, NULL
, (PBYTE
)pUnicodeData
, cbUnicodeData
, &cbUnicodeData
);
243 if (dwReturnValue
!= ERROR_SUCCESS
)
247 if (*pType
== REG_SZ
|| *pType
== REG_MULTI_SZ
|| *pType
== REG_EXPAND_SZ
)
249 // Convert the Unicode string to ANSI.
250 WideCharToMultiByte(CP_ACP
, 0, (PWSTR
)pUnicodeData
, -1, (PSTR
)pData
, *pcbNeeded
, NULL
, NULL
);
254 // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW.
255 // Copy the fields and convert the Unicode CSD Version string to ANSI.
256 pInfoW
= (POSVERSIONINFOEXW
)pUnicodeData
;
257 pInfoA
= (POSVERSIONINFOEXA
)pData
;
258 pInfoA
->dwMajorVersion
= pInfoW
->dwMajorVersion
;
259 pInfoA
->dwMinorVersion
= pInfoW
->dwMinorVersion
;
260 pInfoA
->dwBuildNumber
= pInfoW
->dwBuildNumber
;
261 pInfoA
->dwPlatformId
= pInfoW
->dwPlatformId
;
262 WideCharToMultiByte(CP_ACP
, 0, pInfoW
->szCSDVersion
, -1, pInfoA
->szCSDVersion
, sizeof(pInfoA
->szCSDVersion
), NULL
, NULL
);
264 if (cbUnicodeData
== sizeof(OSVERSIONINFOW
))
266 pInfoA
->dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
270 pInfoA
->dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEXA
);
271 pInfoA
->wServicePackMajor
= pInfoW
->wServicePackMajor
;
272 pInfoA
->wServicePackMinor
= pInfoW
->wServicePackMinor
;
273 pInfoA
->wSuiteMask
= pInfoW
->wSuiteMask
;
274 pInfoA
->wProductType
= pInfoW
->wProductType
;
275 pInfoA
->wReserved
= pInfoW
->wReserved
;
281 HeapFree(hProcessHeap
, 0, pwszKeyName
);
284 HeapFree(hProcessHeap
, 0, pwszValueName
);
287 HeapFree(hProcessHeap
, 0, pUnicodeData
);
289 return dwReturnValue
;
293 GetPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
, LPCWSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
295 const WCHAR wszEmptyString
[] = L
"";
299 DWORD dwType
= REG_NONE
;
300 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hPrinter
;
302 TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter
, pKeyName
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
306 return ERROR_INVALID_HANDLE
;
308 // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way),
309 // Windows does it differently for GetPrinterDataExW and points them to empty variables.
311 pKeyName
= wszEmptyString
;
316 if (!pData
&& !nSize
)
322 dwErrorCode
= _RpcGetPrinterDataEx(pHandle
->hPrinter
, pKeyName
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
324 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
326 dwErrorCode
= RpcExceptionCode();
334 GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
336 TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
337 return GetPrinterDataExW(hPrinter
, L
"PrinterDriverData", pValueName
, pType
, pData
, nSize
, pcbNeeded
);
341 SetPrinterDataA(HANDLE hPrinter
, PSTR pValueName
, DWORD Type
, PBYTE pData
, DWORD cbData
)
343 TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter
, pValueName
, Type
, pData
, cbData
);
344 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
, pData
, cbData
);
348 SetPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
, LPCSTR pValueName
, DWORD Type
, LPBYTE pData
, DWORD cbData
)
352 PWSTR pwszKeyName
= NULL
;
353 PWSTR pwszValueName
= NULL
;
354 PWSTR pUnicodeData
= NULL
;
356 TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter
, pKeyName
, pValueName
, Type
, pData
, cbData
);
360 // Convert pKeyName to a Unicode string pwszKeyName
361 cch
= strlen(pKeyName
);
363 pwszKeyName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
366 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
367 ERR("HeapAlloc failed!\n");
371 MultiByteToWideChar(CP_ACP
, 0, pKeyName
, -1, pwszKeyName
, cch
+ 1);
376 // Convert pValueName to a Unicode string pwszValueName
377 cch
= strlen(pValueName
);
379 pwszValueName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
382 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
383 ERR("HeapAlloc failed!\n");
387 MultiByteToWideChar(CP_ACP
, 0, pValueName
, -1, pwszValueName
, cch
+ 1);
390 if (Type
== REG_SZ
|| Type
== REG_MULTI_SZ
|| Type
== REG_EXPAND_SZ
)
392 // Convert pData to a Unicode string pUnicodeData.
393 pUnicodeData
= HeapAlloc(hProcessHeap
, 0, cbData
* sizeof(WCHAR
));
396 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
397 ERR("HeapAlloc failed!\n");
401 MultiByteToWideChar(CP_ACP
, 0, (PCSTR
)pData
, -1, pUnicodeData
, cbData
);
403 pData
= (PBYTE
)pUnicodeData
;
404 cbData
*= sizeof(WCHAR
);
407 dwReturnValue
= SetPrinterDataExW(hPrinter
, pwszKeyName
, pwszValueName
, Type
, pData
, cbData
);
411 HeapFree(hProcessHeap
, 0, pwszKeyName
);
414 HeapFree(hProcessHeap
, 0, pwszValueName
);
417 HeapFree(hProcessHeap
, 0, pUnicodeData
);
419 return dwReturnValue
;
423 SetPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
, LPCWSTR pValueName
, DWORD Type
, LPBYTE pData
, DWORD cbData
)
425 const WCHAR wszEmptyString
[] = L
"";
428 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hPrinter
;
430 TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter
, pKeyName
, pValueName
, Type
, pData
, cbData
);
434 return ERROR_INVALID_HANDLE
;
437 pKeyName
= wszEmptyString
;
442 dwErrorCode
= _RpcSetPrinterDataEx(pHandle
->hPrinter
, pKeyName
, pValueName
, Type
, pData
, cbData
);
444 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
446 dwErrorCode
= RpcExceptionCode();
454 SetPrinterDataW(HANDLE hPrinter
, PWSTR pValueName
, DWORD Type
, PBYTE pData
, DWORD cbData
)
456 TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter
, pValueName
, Type
, pData
, cbData
);
457 return SetPrinterDataExW(hPrinter
, L
"PrinterDriverData", pValueName
, Type
, pData
, cbData
);