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 AdvancedDocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
, PWSTR pDeviceName
, PDEVMODEW pDevModeOutput
, PDEVMODEW pDevModeInput
)
13 TRACE("AdvancedDocumentPropertiesW(%p, %p, %S, %p, %p)\n", hWnd
, hPrinter
, pDeviceName
, pDevModeOutput
, pDevModeInput
);
19 GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
21 TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
22 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
, pData
, nSize
, pcbNeeded
);
26 GetPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
, LPCSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
32 POSVERSIONINFOEXA pInfoA
;
33 POSVERSIONINFOEXW pInfoW
;
34 PVOID pUnicodeData
= NULL
;
35 PWSTR pwszKeyName
= NULL
;
36 PWSTR pwszValueName
= NULL
;
38 TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter
, pKeyName
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
42 // Convert pKeyName to a Unicode string pwszKeyName
43 cch
= strlen(pKeyName
);
45 pwszKeyName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
48 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
49 ERR("HeapAlloc failed!\n");
53 MultiByteToWideChar(CP_ACP
, 0, pKeyName
, -1, pwszKeyName
, cch
+ 1);
58 // Convert pValueName to a Unicode string pwszValueName
59 cch
= strlen(pValueName
);
61 pwszValueName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
64 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
65 ERR("HeapAlloc failed!\n");
69 MultiByteToWideChar(CP_ACP
, 0, pValueName
, -1, pwszValueName
, cch
+ 1);
72 // We need the data type information, even if no pData was passed.
76 // Call GetPrinterDataExW for the first time.
77 // 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.
78 dwReturnValue
= GetPrinterDataExW(hPrinter
, pwszKeyName
, pwszValueName
, pType
, pData
, nSize
, pcbNeeded
);
80 // If a critical error occurred, just return it. We cannot do anything else in this case.
81 if (dwReturnValue
!= ERROR_SUCCESS
&& dwReturnValue
!= ERROR_MORE_DATA
)
84 // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size.
85 cbUnicodeData
= *pcbNeeded
;
87 if (*pType
== REG_SZ
|| *pType
== REG_MULTI_SZ
|| *pType
== REG_EXPAND_SZ
)
89 // This is a string that needs to be converted from Unicode to ANSI.
90 // Output the required buffer size for the ANSI string.
91 *pcbNeeded
/= sizeof(WCHAR
);
93 else if (*pType
== REG_NONE
)
95 if (cbUnicodeData
== sizeof(OSVERSIONINFOW
) && wcsicmp(pwszValueName
, SPLREG_OS_VERSION
) == 0)
97 // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA.
98 *pcbNeeded
= sizeof(OSVERSIONINFOA
);
100 else if (cbUnicodeData
== sizeof(OSVERSIONINFOEXW
) && wcsicmp(pwszValueName
, SPLREG_OS_VERSIONEX
) == 0)
102 // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA.
103 *pcbNeeded
= sizeof(OSVERSIONINFOEXA
);
107 // Other REG_NONE value, nothing to do.
112 // Check if the supplied buffer is large enough for the ANSI data.
113 if (nSize
< *pcbNeeded
)
115 dwReturnValue
= ERROR_MORE_DATA
;
119 // Allocate a temporary buffer for the Unicode data.
120 pUnicodeData
= HeapAlloc(hProcessHeap
, 0, cbUnicodeData
);
123 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
124 ERR("HeapAlloc failed!\n");
128 if (dwReturnValue
== ERROR_SUCCESS
)
130 // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string,
131 // so the Unicode string has been copied into pData. Copy it to pUnicodeData.
132 CopyMemory(pUnicodeData
, pData
, cbUnicodeData
);
136 // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string.
137 // We have to call GetPrinterDataExW again with the temporary buffer.
138 dwReturnValue
= GetPrinterDataExW(hPrinter
, pwszKeyName
, pwszValueName
, NULL
, (PBYTE
)pUnicodeData
, cbUnicodeData
, &cbUnicodeData
);
139 if (dwReturnValue
!= ERROR_SUCCESS
)
143 if (*pType
== REG_SZ
|| *pType
== REG_MULTI_SZ
|| *pType
== REG_EXPAND_SZ
)
145 // Convert the Unicode string to ANSI.
146 WideCharToMultiByte(CP_ACP
, 0, (PWSTR
)pUnicodeData
, -1, (PSTR
)pData
, *pcbNeeded
, NULL
, NULL
);
150 // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW.
151 // Copy the fields and convert the Unicode CSD Version string to ANSI.
152 pInfoW
= (POSVERSIONINFOEXW
)pUnicodeData
;
153 pInfoA
= (POSVERSIONINFOEXA
)pData
;
154 pInfoA
->dwMajorVersion
= pInfoW
->dwMajorVersion
;
155 pInfoA
->dwMinorVersion
= pInfoW
->dwMinorVersion
;
156 pInfoA
->dwBuildNumber
= pInfoW
->dwBuildNumber
;
157 pInfoA
->dwPlatformId
= pInfoW
->dwPlatformId
;
158 WideCharToMultiByte(CP_ACP
, 0, pInfoW
->szCSDVersion
, -1, pInfoA
->szCSDVersion
, sizeof(pInfoA
->szCSDVersion
), NULL
, NULL
);
160 if (cbUnicodeData
== sizeof(OSVERSIONINFOW
))
162 pInfoA
->dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
166 pInfoA
->dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEXA
);
167 pInfoA
->wServicePackMajor
= pInfoW
->wServicePackMajor
;
168 pInfoA
->wServicePackMinor
= pInfoW
->wServicePackMinor
;
169 pInfoA
->wSuiteMask
= pInfoW
->wSuiteMask
;
170 pInfoA
->wProductType
= pInfoW
->wProductType
;
171 pInfoA
->wReserved
= pInfoW
->wReserved
;
177 HeapFree(hProcessHeap
, 0, pwszKeyName
);
180 HeapFree(hProcessHeap
, 0, pwszValueName
);
183 HeapFree(hProcessHeap
, 0, pUnicodeData
);
185 return dwReturnValue
;
189 GetPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
, LPCWSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
191 const WCHAR wszEmptyString
[] = L
"";
195 DWORD dwType
= REG_NONE
;
196 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hPrinter
;
198 TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter
, pKeyName
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
202 return ERROR_INVALID_HANDLE
;
204 // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way),
205 // Windows does it differently for GetPrinterDataExW and points them to empty variables.
207 pKeyName
= wszEmptyString
;
212 if (!pData
&& !nSize
)
218 dwErrorCode
= _RpcGetPrinterDataEx(pHandle
->hPrinter
, pKeyName
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
220 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
222 dwErrorCode
= RpcExceptionCode();
230 GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
232 TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
233 return GetPrinterDataExW(hPrinter
, L
"PrinterDriverData", pValueName
, pType
, pData
, nSize
, pcbNeeded
);
237 SetPrinterDataA(HANDLE hPrinter
, PSTR pValueName
, DWORD Type
, PBYTE pData
, DWORD cbData
)
239 TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter
, pValueName
, Type
, pData
, cbData
);
240 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
, pData
, cbData
);
244 SetPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
, LPCSTR pValueName
, DWORD Type
, LPBYTE pData
, DWORD cbData
)
248 PWSTR pwszKeyName
= NULL
;
249 PWSTR pwszValueName
= NULL
;
250 PWSTR pUnicodeData
= NULL
;
252 TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter
, pKeyName
, pValueName
, Type
, pData
, cbData
);
256 // Convert pKeyName to a Unicode string pwszKeyName
257 cch
= strlen(pKeyName
);
259 pwszKeyName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
262 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
263 ERR("HeapAlloc failed!\n");
267 MultiByteToWideChar(CP_ACP
, 0, pKeyName
, -1, pwszKeyName
, cch
+ 1);
272 // Convert pValueName to a Unicode string pwszValueName
273 cch
= strlen(pValueName
);
275 pwszValueName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
278 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
279 ERR("HeapAlloc failed!\n");
283 MultiByteToWideChar(CP_ACP
, 0, pValueName
, -1, pwszValueName
, cch
+ 1);
286 if (Type
== REG_SZ
|| Type
== REG_MULTI_SZ
|| Type
== REG_EXPAND_SZ
)
288 // Convert pData to a Unicode string pUnicodeData.
289 pUnicodeData
= HeapAlloc(hProcessHeap
, 0, cbData
* sizeof(WCHAR
));
292 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
293 ERR("HeapAlloc failed!\n");
297 MultiByteToWideChar(CP_ACP
, 0, (PCSTR
)pData
, -1, pUnicodeData
, cbData
);
299 pData
= (PBYTE
)pUnicodeData
;
300 cbData
*= sizeof(WCHAR
);
303 dwReturnValue
= SetPrinterDataExW(hPrinter
, pwszKeyName
, pwszValueName
, Type
, pData
, cbData
);
307 HeapFree(hProcessHeap
, 0, pwszKeyName
);
310 HeapFree(hProcessHeap
, 0, pwszValueName
);
313 HeapFree(hProcessHeap
, 0, pUnicodeData
);
315 return dwReturnValue
;
319 SetPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
, LPCWSTR pValueName
, DWORD Type
, LPBYTE pData
, DWORD cbData
)
321 const WCHAR wszEmptyString
[] = L
"";
324 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hPrinter
;
326 TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter
, pKeyName
, pValueName
, Type
, pData
, cbData
);
330 return ERROR_INVALID_HANDLE
;
333 pKeyName
= wszEmptyString
;
338 dwErrorCode
= _RpcSetPrinterDataEx(pHandle
->hPrinter
, pKeyName
, pValueName
, Type
, pData
, cbData
);
340 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
342 dwErrorCode
= RpcExceptionCode();
350 SetPrinterDataW(HANDLE hPrinter
, PWSTR pValueName
, DWORD Type
, PBYTE pData
, DWORD cbData
)
352 TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter
, pValueName
, Type
, pData
, cbData
);
353 return SetPrinterDataExW(hPrinter
, L
"PrinterDriverData", pValueName
, Type
, pData
, cbData
);