2 * PROJECT: ReactOS Spooler API
3 * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
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
)
18 GetPrinterDataA(HANDLE hPrinter
, LPSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
20 return GetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, pType
, pData
, nSize
, pcbNeeded
);
24 GetPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
, LPCSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
30 POSVERSIONINFOEXA pInfoA
;
31 POSVERSIONINFOEXW pInfoW
;
32 PVOID pUnicodeData
= NULL
;
33 PWSTR pwszKeyName
= NULL
;
34 PWSTR pwszValueName
= NULL
;
38 // Convert pKeyName to a Unicode string pwszKeyName
39 cch
= strlen(pKeyName
);
41 pwszKeyName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
44 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
45 ERR("HeapAlloc failed!\n");
49 MultiByteToWideChar(CP_ACP
, 0, pKeyName
, -1, pwszKeyName
, cch
+ 1);
54 // Convert pValueName to a Unicode string pwszValueName
55 cch
= strlen(pValueName
);
57 pwszValueName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
60 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
61 ERR("HeapAlloc failed!\n");
65 MultiByteToWideChar(CP_ACP
, 0, pValueName
, -1, pwszValueName
, cch
+ 1);
68 // We need the data type information, even if no pData was passed.
72 // Call GetPrinterDataExW for the first time.
73 // 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.
74 dwReturnValue
= GetPrinterDataExW(hPrinter
, pwszKeyName
, pwszValueName
, pType
, pData
, nSize
, pcbNeeded
);
76 // If a critical error occurred, just return it. We cannot do anything else in this case.
77 if (dwReturnValue
!= ERROR_SUCCESS
&& dwReturnValue
!= ERROR_MORE_DATA
)
80 // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size.
81 cbUnicodeData
= *pcbNeeded
;
83 if (*pType
== REG_SZ
|| *pType
== REG_MULTI_SZ
|| *pType
== REG_EXPAND_SZ
)
85 // This is a string that needs to be converted from Unicode to ANSI.
86 // Output the required buffer size for the ANSI string.
87 *pcbNeeded
/= sizeof(WCHAR
);
89 else if (*pType
== REG_NONE
)
91 if (cbUnicodeData
== sizeof(OSVERSIONINFOW
) && wcsicmp(pwszValueName
, SPLREG_OS_VERSION
) == 0)
93 // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA.
94 *pcbNeeded
= sizeof(OSVERSIONINFOA
);
96 else if (cbUnicodeData
== sizeof(OSVERSIONINFOEXW
) && wcsicmp(pwszValueName
, SPLREG_OS_VERSIONEX
) == 0)
98 // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA.
99 *pcbNeeded
= sizeof(OSVERSIONINFOEXA
);
103 // Other REG_NONE value, nothing to do.
108 // Check if the supplied buffer is large enough for the ANSI data.
109 if (nSize
< *pcbNeeded
)
111 dwReturnValue
= ERROR_MORE_DATA
;
115 // Allocate a temporary buffer for the Unicode data.
116 pUnicodeData
= HeapAlloc(hProcessHeap
, 0, cbUnicodeData
);
119 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
120 ERR("HeapAlloc failed!\n");
124 if (dwReturnValue
== ERROR_SUCCESS
)
126 // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string,
127 // so the Unicode string has been copied into pData. Copy it to pUnicodeData.
128 CopyMemory(pUnicodeData
, pData
, cbUnicodeData
);
132 // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string.
133 // We have to call GetPrinterDataExW again with the temporary buffer.
134 dwReturnValue
= GetPrinterDataExW(hPrinter
, pwszKeyName
, pwszValueName
, NULL
, (PBYTE
)pUnicodeData
, cbUnicodeData
, &cbUnicodeData
);
135 if (dwReturnValue
!= ERROR_SUCCESS
)
139 if (*pType
== REG_SZ
|| *pType
== REG_MULTI_SZ
|| *pType
== REG_EXPAND_SZ
)
141 // Convert the Unicode string to ANSI.
142 WideCharToMultiByte(CP_ACP
, 0, (PWSTR
)pUnicodeData
, -1, (PSTR
)pData
, *pcbNeeded
, NULL
, NULL
);
146 // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW.
147 // Copy the fields and convert the Unicode CSD Version string to ANSI.
148 pInfoW
= (POSVERSIONINFOEXW
)pUnicodeData
;
149 pInfoA
= (POSVERSIONINFOEXA
)pData
;
150 pInfoA
->dwMajorVersion
= pInfoW
->dwMajorVersion
;
151 pInfoA
->dwMinorVersion
= pInfoW
->dwMinorVersion
;
152 pInfoA
->dwBuildNumber
= pInfoW
->dwBuildNumber
;
153 pInfoA
->dwPlatformId
= pInfoW
->dwPlatformId
;
154 WideCharToMultiByte(CP_ACP
, 0, pInfoW
->szCSDVersion
, -1, pInfoA
->szCSDVersion
, sizeof(pInfoA
->szCSDVersion
), NULL
, NULL
);
156 if (cbUnicodeData
== sizeof(OSVERSIONINFOW
))
158 pInfoA
->dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
162 pInfoA
->dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEXA
);
163 pInfoA
->wServicePackMajor
= pInfoW
->wServicePackMajor
;
164 pInfoA
->wServicePackMinor
= pInfoW
->wServicePackMinor
;
165 pInfoA
->wSuiteMask
= pInfoW
->wSuiteMask
;
166 pInfoA
->wProductType
= pInfoW
->wProductType
;
167 pInfoA
->wReserved
= pInfoW
->wReserved
;
173 HeapFree(hProcessHeap
, 0, pwszKeyName
);
176 HeapFree(hProcessHeap
, 0, pwszValueName
);
179 HeapFree(hProcessHeap
, 0, pUnicodeData
);
181 return dwReturnValue
;
185 GetPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
, LPCWSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
187 const WCHAR wszEmptyString
[] = L
"";
191 DWORD dwType
= REG_NONE
;
192 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hPrinter
;
196 return ERROR_INVALID_HANDLE
;
198 // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way),
199 // Windows does it differently for GetPrinterDataExW and points them to empty variables.
201 pKeyName
= wszEmptyString
;
206 if (!pData
&& !nSize
)
212 dwErrorCode
= _RpcGetPrinterDataEx(pHandle
->hPrinter
, pKeyName
, pValueName
, pType
, pData
, nSize
, pcbNeeded
);
214 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
216 dwErrorCode
= RpcExceptionCode();
224 GetPrinterDataW(HANDLE hPrinter
, LPWSTR pValueName
, LPDWORD pType
, LPBYTE pData
, DWORD nSize
, LPDWORD pcbNeeded
)
226 return GetPrinterDataExW(hPrinter
, L
"PrinterDriverData", pValueName
, pType
, pData
, nSize
, pcbNeeded
);
230 SetPrinterDataA(HANDLE hPrinter
, PSTR pValueName
, DWORD Type
, PBYTE pData
, DWORD cbData
)
232 return SetPrinterDataExA(hPrinter
, "PrinterDriverData", pValueName
, Type
, pData
, cbData
);
236 SetPrinterDataExA(HANDLE hPrinter
, LPCSTR pKeyName
, LPCSTR pValueName
, DWORD Type
, LPBYTE pData
, DWORD cbData
)
240 PWSTR pwszKeyName
= NULL
;
241 PWSTR pwszValueName
= NULL
;
242 PWSTR pUnicodeData
= NULL
;
246 // Convert pKeyName to a Unicode string pwszKeyName
247 cch
= strlen(pKeyName
);
249 pwszKeyName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
252 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
253 ERR("HeapAlloc failed!\n");
257 MultiByteToWideChar(CP_ACP
, 0, pKeyName
, -1, pwszKeyName
, cch
+ 1);
262 // Convert pValueName to a Unicode string pwszValueName
263 cch
= strlen(pValueName
);
265 pwszValueName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
268 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
269 ERR("HeapAlloc failed!\n");
273 MultiByteToWideChar(CP_ACP
, 0, pValueName
, -1, pwszValueName
, cch
+ 1);
276 if (Type
== REG_SZ
|| Type
== REG_MULTI_SZ
|| Type
== REG_EXPAND_SZ
)
278 // Convert pData to a Unicode string pUnicodeData.
279 pUnicodeData
= HeapAlloc(hProcessHeap
, 0, cbData
* sizeof(WCHAR
));
282 dwReturnValue
= ERROR_NOT_ENOUGH_MEMORY
;
283 ERR("HeapAlloc failed!\n");
287 MultiByteToWideChar(CP_ACP
, 0, (PCSTR
)pData
, -1, pUnicodeData
, cbData
);
289 pData
= (PBYTE
)pUnicodeData
;
290 cbData
*= sizeof(WCHAR
);
293 dwReturnValue
= SetPrinterDataExW(hPrinter
, pwszKeyName
, pwszValueName
, Type
, pData
, cbData
);
297 HeapFree(hProcessHeap
, 0, pwszKeyName
);
300 HeapFree(hProcessHeap
, 0, pwszValueName
);
303 HeapFree(hProcessHeap
, 0, pUnicodeData
);
305 return dwReturnValue
;
309 SetPrinterDataExW(HANDLE hPrinter
, LPCWSTR pKeyName
, LPCWSTR pValueName
, DWORD Type
, LPBYTE pData
, DWORD cbData
)
311 const WCHAR wszEmptyString
[] = L
"";
314 PSPOOLER_HANDLE pHandle
= (PSPOOLER_HANDLE
)hPrinter
;
318 return ERROR_INVALID_HANDLE
;
321 pKeyName
= wszEmptyString
;
326 dwErrorCode
= _RpcSetPrinterDataEx(pHandle
->hPrinter
, pKeyName
, pValueName
, Type
, pData
, cbData
);
328 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
330 dwErrorCode
= RpcExceptionCode();
338 SetPrinterDataW(HANDLE hPrinter
, PWSTR pValueName
, DWORD Type
, PBYTE pData
, DWORD cbData
)
340 return SetPrinterDataExW(hPrinter
, L
"PrinterDriverData", pValueName
, Type
, pData
, cbData
);