[PRINTING]
[reactos.git] / reactos / win32ss / printing / base / winspool / printprocessors.c
1 /*
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 Print Processors
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin@reactos.org>
6 */
7
8 #include "precomp.h"
9 #include <prtprocenv.h>
10
11 static void
12 _MarshallUpDatatypesInfo(PDATATYPES_INFO_1W* ppDatatypesInfo1)
13 {
14 // Replace relative offset addresses in the output by absolute pointers.
15 PDATATYPES_INFO_1W pDatatypesInfo1 = *ppDatatypesInfo1;
16 pDatatypesInfo1->pName = (PWSTR)((ULONG_PTR)pDatatypesInfo1->pName + (ULONG_PTR)pDatatypesInfo1);
17 *ppDatatypesInfo1 += sizeof(DATATYPES_INFO_1W);
18 }
19
20 static void
21 _MarshallUpPrintProcessorInfo(PPRINTPROCESSOR_INFO_1W* ppPrintProcessorInfo1)
22 {
23 // Replace relative offset addresses in the output by absolute pointers.
24 PPRINTPROCESSOR_INFO_1W pPrintProcessorInfo1 = *ppPrintProcessorInfo1;
25 pPrintProcessorInfo1->pName = (PWSTR)((ULONG_PTR)pPrintProcessorInfo1->pName + (ULONG_PTR)pPrintProcessorInfo1);
26 *ppPrintProcessorInfo1 += sizeof(PRINTPROCESSOR_INFO_1W);
27 }
28
29 BOOL WINAPI
30 AddPrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPathName, PWSTR pPrintProcessorName)
31 {
32 UNIMPLEMENTED;
33 return FALSE;
34 }
35
36 BOOL WINAPI
37 DeletePrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPrintProcessorName)
38 {
39 UNIMPLEMENTED;
40 return FALSE;
41 }
42
43 BOOL WINAPI
44 EnumPrintProcessorDatatypesA(PSTR pName, LPSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
45 {
46 UNIMPLEMENTED;
47 return FALSE;
48 }
49
50 BOOL WINAPI
51 EnumPrintProcessorDatatypesW(PWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
52 {
53 DWORD dwErrorCode;
54
55 // Sanity checks
56 if (Level != 1)
57 {
58 dwErrorCode = ERROR_INVALID_LEVEL;
59 goto Cleanup;
60 }
61
62 // Do the RPC call
63 RpcTryExcept
64 {
65 dwErrorCode = _RpcEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
66 }
67 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
68 {
69 dwErrorCode = RpcExceptionCode();
70 ERR("_RpcEnumPrintProcessorDatatypes failed with exception code %lu!\n", dwErrorCode);
71 }
72 RpcEndExcept;
73
74 if (dwErrorCode == ERROR_SUCCESS)
75 {
76 DWORD i;
77 PDATATYPES_INFO_1W p = (PDATATYPES_INFO_1W)pDatatypes;
78
79 for (i = 0; i < *pcReturned; i++)
80 _MarshallUpDatatypesInfo(&p);
81 }
82
83 Cleanup:
84 SetLastError(dwErrorCode);
85 return (dwErrorCode == ERROR_SUCCESS);
86 }
87
88 BOOL WINAPI
89 EnumPrintProcessorsW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
90 {
91 DWORD dwErrorCode;
92
93 // Choose our current environment if the caller didn't give any.
94 if (!pEnvironment)
95 pEnvironment = (PWSTR)wszCurrentEnvironment;
96
97 // Do the RPC call
98 RpcTryExcept
99 {
100 dwErrorCode = _RpcEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
101 }
102 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
103 {
104 dwErrorCode = RpcExceptionCode();
105 }
106 RpcEndExcept;
107
108 if (dwErrorCode == ERROR_SUCCESS)
109 {
110 DWORD i;
111 PPRINTPROCESSOR_INFO_1W p = (PPRINTPROCESSOR_INFO_1W)pPrintProcessorInfo;
112
113 for (i = 0; i < *pcReturned; i++)
114 _MarshallUpPrintProcessorInfo(&p);
115 }
116
117 SetLastError(dwErrorCode);
118 return (dwErrorCode == ERROR_SUCCESS);
119 }
120
121 BOOL WINAPI
122 GetPrintProcessorDirectoryA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded)
123 {
124 BOOL bReturnValue = FALSE;
125 DWORD cch;
126 PWSTR pwszName = NULL;
127 PWSTR pwszEnvironment = NULL;
128 PWSTR pwszPrintProcessorInfo = NULL;
129
130 if (pName)
131 {
132 // Convert pName to a Unicode string pwszName.
133 cch = strlen(pName);
134
135 pwszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
136 if (!pwszName)
137 {
138 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
139 ERR("HeapAlloc failed!\n");
140 goto Cleanup;
141 }
142
143 MultiByteToWideChar(CP_ACP, 0, pName, -1, pwszName, cch + 1);
144 }
145
146 if (pEnvironment)
147 {
148 // Convert pEnvironment to a Unicode string pwszEnvironment.
149 cch = strlen(pEnvironment);
150
151 pwszEnvironment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
152 if (!pwszEnvironment)
153 {
154 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
155 ERR("HeapAlloc failed!\n");
156 goto Cleanup;
157 }
158
159 MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, pwszEnvironment, cch + 1);
160 }
161
162 if (cbBuf && pPrintProcessorInfo)
163 {
164 // Allocate a temporary buffer for the Unicode result.
165 // We can just go with cbBuf here. The user should have set it based on pcbNeeded returned in a previous call and our
166 // pcbNeeded is the same for the A and W functions.
167 pwszPrintProcessorInfo = HeapAlloc(hProcessHeap, 0, cbBuf);
168 if (!pwszPrintProcessorInfo)
169 {
170 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
171 ERR("HeapAlloc failed!\n");
172 goto Cleanup;
173 }
174 }
175
176 bReturnValue = GetPrintProcessorDirectoryW(pwszName, pwszEnvironment, Level, (PBYTE)pwszPrintProcessorInfo, cbBuf, pcbNeeded);
177
178 if (bReturnValue)
179 {
180 // Convert pwszPrintProcessorInfo to an ANSI string pPrintProcessorInfo.
181 WideCharToMultiByte(CP_ACP, 0, pwszPrintProcessorInfo, -1, (PSTR)pPrintProcessorInfo, cbBuf, NULL, NULL);
182 }
183
184 Cleanup:
185 if (pwszName)
186 HeapFree(hProcessHeap, 0, pwszName);
187
188 if (pwszEnvironment)
189 HeapFree(hProcessHeap, 0, pwszEnvironment);
190
191 if (pwszPrintProcessorInfo)
192 HeapFree(hProcessHeap, 0, pwszPrintProcessorInfo);
193
194 return bReturnValue;
195 }
196
197 BOOL WINAPI
198 GetPrintProcessorDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded)
199 {
200 DWORD dwErrorCode;
201
202 // Sanity checks
203 if (Level != 1)
204 {
205 dwErrorCode = ERROR_INVALID_LEVEL;
206 goto Cleanup;
207 }
208
209 // Choose our current environment if the caller didn't give any.
210 if (!pEnvironment)
211 pEnvironment = (PWSTR)wszCurrentEnvironment;
212
213 // Do the RPC call
214 RpcTryExcept
215 {
216 dwErrorCode = _RpcGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);
217 }
218 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
219 {
220 dwErrorCode = RpcExceptionCode();
221 }
222 RpcEndExcept;
223
224 Cleanup:
225 SetLastError(dwErrorCode);
226 return (dwErrorCode == ERROR_SUCCESS);
227 }