2 * PROJECT: ReactOS Spooler API
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Functions related to Print Processors
5 * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org)
9 #include <marshalling/printprocessors.h>
10 #include <prtprocenv.h>
13 AddPrintProcessorA(PSTR pName
, PSTR pEnvironment
, PSTR pPathName
, PSTR pPrintProcessorName
)
15 UNICODE_STRING NameW
, EnvW
, PathW
, ProcessorW
;
18 TRACE("AddPrintProcessorA(%s, %s, %s, %s)\n", pName
, pEnvironment
, pPathName
, pPrintProcessorName
);
20 AsciiToUnicode(&NameW
, pName
);
21 AsciiToUnicode(&EnvW
, pEnvironment
);
22 AsciiToUnicode(&PathW
, pPathName
);
23 AsciiToUnicode(&ProcessorW
, pPrintProcessorName
);
25 Ret
= AddPrintProcessorW(NameW
.Buffer
, EnvW
.Buffer
, PathW
.Buffer
, ProcessorW
.Buffer
);
27 RtlFreeUnicodeString(&ProcessorW
);
28 RtlFreeUnicodeString(&PathW
);
29 RtlFreeUnicodeString(&EnvW
);
30 RtlFreeUnicodeString(&NameW
);
36 AddPrintProcessorW(PWSTR pName
, PWSTR pEnvironment
, PWSTR pPathName
, PWSTR pPrintProcessorName
)
40 TRACE("AddPrintProcessorW(%S, %S, %S, %S)\n", pName
, pEnvironment
, pPathName
, pPrintProcessorName
);
44 dwErrorCode
= _RpcAddPrintProcessor( pName
, pEnvironment
, pPathName
, pPrintProcessorName
);
46 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
48 dwErrorCode
= RpcExceptionCode();
49 ERR("_RpcPrintProcessor failed with exception code %lu!\n", dwErrorCode
);
53 SetLastError(dwErrorCode
);
54 return (dwErrorCode
== ERROR_SUCCESS
);
58 DeletePrintProcessorA(PSTR pName
, PSTR pEnvironment
, PSTR pPrintProcessorName
)
60 UNICODE_STRING NameW
, EnvW
, ProcessorW
;
63 TRACE("DeletePrintProcessorA(%s, %s, %s)\n", pName
, pEnvironment
, pPrintProcessorName
);
65 AsciiToUnicode(&NameW
, pName
);
66 AsciiToUnicode(&EnvW
, pEnvironment
);
67 AsciiToUnicode(&ProcessorW
, pPrintProcessorName
);
69 Ret
= DeletePrintProcessorW(NameW
.Buffer
, EnvW
.Buffer
, ProcessorW
.Buffer
);
71 RtlFreeUnicodeString(&ProcessorW
);
72 RtlFreeUnicodeString(&EnvW
);
73 RtlFreeUnicodeString(&NameW
);
79 DeletePrintProcessorW(PWSTR pName
, PWSTR pEnvironment
, PWSTR pPrintProcessorName
)
83 TRACE("DeletePrintProcessorW(%S, %S, %S)\n", pName
, pEnvironment
, pPrintProcessorName
);
87 dwErrorCode
= _RpcDeletePrintProcessor( pName
, pEnvironment
, pPrintProcessorName
);
89 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
91 dwErrorCode
= RpcExceptionCode();
92 ERR("_RpcDeletePrintProcessor failed with exception code %lu!\n", dwErrorCode
);
96 SetLastError(dwErrorCode
);
97 return (dwErrorCode
== ERROR_SUCCESS
);
101 EnumPrintProcessorDatatypesA(PSTR pName
, LPSTR pPrintProcessorName
, DWORD Level
, PBYTE pDatatypes
, DWORD cbBuf
, PDWORD pcbNeeded
, PDWORD pcReturned
)
103 TRACE("EnumPrintProcessorDatatypesA(%s, %s, %lu, %p, %lu, %p, %p)\n", pName
, pPrintProcessorName
, Level
, pDatatypes
, cbBuf
, pcbNeeded
, pcReturned
);
109 EnumPrintProcessorDatatypesW(PWSTR pName
, LPWSTR pPrintProcessorName
, DWORD Level
, PBYTE pDatatypes
, DWORD cbBuf
, PDWORD pcbNeeded
, PDWORD pcReturned
)
113 TRACE("EnumPrintProcessorDatatypesW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName
, pPrintProcessorName
, Level
, pDatatypes
, cbBuf
, pcbNeeded
, pcReturned
);
118 dwErrorCode
= ERROR_INVALID_LEVEL
;
125 dwErrorCode
= _RpcEnumPrintProcessorDatatypes(pName
, pPrintProcessorName
, Level
, pDatatypes
, cbBuf
, pcbNeeded
, pcReturned
);
127 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
129 dwErrorCode
= RpcExceptionCode();
130 ERR("_RpcEnumPrintProcessorDatatypes failed with exception code %lu!\n", dwErrorCode
);
134 if (dwErrorCode
== ERROR_SUCCESS
)
136 // Replace relative offset addresses in the output by absolute pointers.
137 MarshallUpStructuresArray(cbBuf
, pDatatypes
, *pcReturned
, DatatypesInfo1Marshalling
.pInfo
, DatatypesInfo1Marshalling
.cbStructureSize
, TRUE
);
141 SetLastError(dwErrorCode
);
142 return (dwErrorCode
== ERROR_SUCCESS
);
146 EnumPrintProcessorsA(PSTR pName
, PSTR pEnvironment
, DWORD Level
, PBYTE pPrintProcessorInfo
, DWORD cbBuf
, PDWORD pcbNeeded
, PDWORD pcReturned
)
149 LPBYTE bufferW
= NULL
;
153 DWORD numentries
= 0;
156 TRACE("EnumPrintProcessorsA(%s, %s, %d, %p, %d, %p, %p)\n", debugstr_a(pName
), debugstr_a(pEnvironment
), Level
, pPrintProcessorInfo
, cbBuf
, pcbNeeded
, pcReturned
);
158 /* convert names to unicode */
161 len
= MultiByteToWideChar(CP_ACP
, 0, pName
, -1, NULL
, 0);
162 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
163 MultiByteToWideChar(CP_ACP
, 0, pName
, -1, nameW
, len
);
167 len
= MultiByteToWideChar(CP_ACP
, 0, pEnvironment
, -1, NULL
, 0);
168 envW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
169 MultiByteToWideChar(CP_ACP
, 0, pEnvironment
, -1, envW
, len
);
172 /* alloc (userbuffersize*sizeof(WCHAR) and try to enum the monitors */
173 needed
= cbBuf
* sizeof(WCHAR
);
174 if (needed
) bufferW
= HeapAlloc(GetProcessHeap(), 0, needed
);
175 res
= EnumPrintProcessorsW(nameW
, envW
, Level
, bufferW
, needed
, pcbNeeded
, pcReturned
);
177 if (!res
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER
))
179 if (pcbNeeded
) needed
= *pcbNeeded
;
180 /* HeapReAlloc return NULL, when bufferW was NULL */
181 bufferW
= (bufferW
) ? HeapReAlloc(GetProcessHeap(), 0, bufferW
, needed
) :
182 HeapAlloc(GetProcessHeap(), 0, needed
);
184 /* Try again with the large Buffer */
185 res
= EnumPrintProcessorsW(nameW
, envW
, Level
, bufferW
, needed
, pcbNeeded
, pcReturned
);
187 numentries
= pcReturned
? *pcReturned
: 0;
192 /* EnumPrintProcessorsW collected all Data. Parse them to calculate ANSI-Size */
195 PPRINTPROCESSOR_INFO_1W ppiw
;
196 PPRINTPROCESSOR_INFO_1A ppia
;
198 /* First pass: calculate the size for all Entries */
199 ppiw
= (PPRINTPROCESSOR_INFO_1W
) bufferW
;
200 ppia
= (PPRINTPROCESSOR_INFO_1A
) pPrintProcessorInfo
;
202 while (index
< numentries
)
205 needed
+= sizeof(PRINTPROCESSOR_INFO_1A
);
206 TRACE("%p: parsing #%d (%s)\n", ppiw
, index
, debugstr_w(ppiw
->pName
));
208 needed
+= WideCharToMultiByte(CP_ACP
, 0, ppiw
->pName
, -1,
209 NULL
, 0, NULL
, NULL
);
211 ppiw
= (PPRINTPROCESSOR_INFO_1W
) (((LPBYTE
)ppiw
) + sizeof(PRINTPROCESSOR_INFO_1W
));
212 ppia
= (PPRINTPROCESSOR_INFO_1A
) (((LPBYTE
)ppia
) + sizeof(PRINTPROCESSOR_INFO_1A
));
215 /* check for errors and quit on failure */
218 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
223 len
= numentries
* sizeof(PRINTPROCESSOR_INFO_1A
); /* room for structs */
224 ptr
= (LPSTR
) &pPrintProcessorInfo
[len
]; /* start of strings */
225 cbBuf
-= len
; /* free Bytes in the user-Buffer */
226 ppiw
= (PPRINTPROCESSOR_INFO_1W
) bufferW
;
227 ppia
= (PPRINTPROCESSOR_INFO_1A
) pPrintProcessorInfo
;
229 /* Second Pass: Fill the User Buffer (if we have one) */
230 while ((index
< numentries
) && pPrintProcessorInfo
)
233 TRACE("%p: writing PRINTPROCESSOR_INFO_1A #%d\n", ppia
, index
);
235 len
= WideCharToMultiByte(CP_ACP
, 0, ppiw
->pName
, -1,
236 ptr
, cbBuf
, NULL
, NULL
);
240 ppiw
= (PPRINTPROCESSOR_INFO_1W
) (((LPBYTE
)ppiw
) + sizeof(PRINTPROCESSOR_INFO_1W
));
241 ppia
= (PPRINTPROCESSOR_INFO_1A
) (((LPBYTE
)ppia
) + sizeof(PRINTPROCESSOR_INFO_1A
));
246 if (pcbNeeded
) *pcbNeeded
= needed
;
247 if (pcReturned
) *pcReturned
= (res
) ? numentries
: 0;
249 if (nameW
) HeapFree(GetProcessHeap(), 0, nameW
);
250 if (envW
) HeapFree(GetProcessHeap(), 0, envW
);
251 if (bufferW
) HeapFree(GetProcessHeap(), 0, bufferW
);
253 TRACE("returning %d with %d (%d byte for %d entries)\n", (res
), GetLastError(), needed
, numentries
);
260 EnumPrintProcessorsW(PWSTR pName
, PWSTR pEnvironment
, DWORD Level
, PBYTE pPrintProcessorInfo
, DWORD cbBuf
, PDWORD pcbNeeded
, PDWORD pcReturned
)
264 TRACE("EnumPrintProcessorsW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName
, pEnvironment
, Level
, pPrintProcessorInfo
, cbBuf
, pcbNeeded
, pcReturned
);
266 // Choose our current environment if the caller didn't give any.
268 pEnvironment
= (PWSTR
)wszCurrentEnvironment
;
273 dwErrorCode
= _RpcEnumPrintProcessors(pName
, pEnvironment
, Level
, pPrintProcessorInfo
, cbBuf
, pcbNeeded
, pcReturned
);
275 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
277 dwErrorCode
= RpcExceptionCode();
281 if (dwErrorCode
== ERROR_SUCCESS
)
283 // Replace relative offset addresses in the output by absolute pointers.
284 MarshallUpStructuresArray(cbBuf
, pPrintProcessorInfo
, *pcReturned
, PrintProcessorInfo1Marshalling
.pInfo
, PrintProcessorInfo1Marshalling
.cbStructureSize
, TRUE
);
287 SetLastError(dwErrorCode
);
288 return (dwErrorCode
== ERROR_SUCCESS
);
292 GetPrintProcessorDirectoryA(PSTR pName
, PSTR pEnvironment
, DWORD Level
, PBYTE pPrintProcessorInfo
, DWORD cbBuf
, PDWORD pcbNeeded
)
294 BOOL bReturnValue
= FALSE
;
296 PWSTR pwszName
= NULL
;
297 PWSTR pwszEnvironment
= NULL
;
298 PWSTR pwszPrintProcessorInfo
= NULL
;
300 TRACE("GetPrintProcessorDirectoryA(%s, %s, %lu, %p, %lu, %p)\n", pName
, pEnvironment
, Level
, pPrintProcessorInfo
, cbBuf
, pcbNeeded
);
304 // Convert pName to a Unicode string pwszName.
307 pwszName
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
310 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
311 ERR("HeapAlloc failed!\n");
315 MultiByteToWideChar(CP_ACP
, 0, pName
, -1, pwszName
, cch
+ 1);
320 // Convert pEnvironment to a Unicode string pwszEnvironment.
321 cch
= strlen(pEnvironment
);
323 pwszEnvironment
= HeapAlloc(hProcessHeap
, 0, (cch
+ 1) * sizeof(WCHAR
));
324 if (!pwszEnvironment
)
326 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
327 ERR("HeapAlloc failed!\n");
331 MultiByteToWideChar(CP_ACP
, 0, pEnvironment
, -1, pwszEnvironment
, cch
+ 1);
334 if (cbBuf
&& pPrintProcessorInfo
)
336 // Allocate a temporary buffer for the Unicode result.
337 // We can just go with cbBuf here. The user should have set it based on pcbNeeded returned in a previous call and our
338 // pcbNeeded is the same for the A and W functions.
339 pwszPrintProcessorInfo
= HeapAlloc(hProcessHeap
, 0, cbBuf
);
340 if (!pwszPrintProcessorInfo
)
342 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
343 ERR("HeapAlloc failed!\n");
348 bReturnValue
= GetPrintProcessorDirectoryW(pwszName
, pwszEnvironment
, Level
, (PBYTE
)pwszPrintProcessorInfo
, cbBuf
, pcbNeeded
);
352 // Convert pwszPrintProcessorInfo to an ANSI string pPrintProcessorInfo.
353 WideCharToMultiByte(CP_ACP
, 0, pwszPrintProcessorInfo
, -1, (PSTR
)pPrintProcessorInfo
, cbBuf
, NULL
, NULL
);
358 HeapFree(hProcessHeap
, 0, pwszName
);
361 HeapFree(hProcessHeap
, 0, pwszEnvironment
);
363 if (pwszPrintProcessorInfo
)
364 HeapFree(hProcessHeap
, 0, pwszPrintProcessorInfo
);
370 GetPrintProcessorDirectoryW(PWSTR pName
, PWSTR pEnvironment
, DWORD Level
, PBYTE pPrintProcessorInfo
, DWORD cbBuf
, PDWORD pcbNeeded
)
374 TRACE("GetPrintProcessorDirectoryW(%S, %S, %lu, %p, %lu, %p)\n", pName
, pEnvironment
, Level
, pPrintProcessorInfo
, cbBuf
, pcbNeeded
);
379 dwErrorCode
= ERROR_INVALID_LEVEL
;
383 // Choose our current environment if the caller didn't give any.
385 pEnvironment
= (PWSTR
)wszCurrentEnvironment
;
390 dwErrorCode
= _RpcGetPrintProcessorDirectory(pName
, pEnvironment
, Level
, pPrintProcessorInfo
, cbBuf
, pcbNeeded
);
392 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
394 dwErrorCode
= RpcExceptionCode();
399 SetLastError(dwErrorCode
);
400 return (dwErrorCode
== ERROR_SUCCESS
);