1 /*
2 * PROJECT: ReactOS Spooler API
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Functions related to Forms
5 * COPYRIGHT: Copyright 2017 Colin Finck (colin@reactos.org)
6 */
7
8 #include "precomp.h"
9 #include <marshalling/forms.h>
10
11 BOOL WINAPI
AddFormA(HANDLE hPrinter,DWORD Level,PBYTE pForm)12 AddFormA(HANDLE hPrinter, DWORD Level, PBYTE pForm)
13 {
14 FORM_INFO_2W pfi2W;
15 PFORM_INFO_2A pfi2A;
16 DWORD len;
17 BOOL res;
18
19 pfi2A = (PFORM_INFO_2A)pForm;
20
21 TRACE("AddFormA(%p, %lu, %p)\n", hPrinter, Level, pForm);
22
23 if ((Level < 1) || (Level > 2))
24 {
25 ERR("Level = %d, unsupported!\n", Level);
26 SetLastError(ERROR_INVALID_LEVEL);
27 return FALSE;
28 }
29
30 if (!pfi2A)
31 {
32 SetLastError(ERROR_INVALID_PARAMETER);
33 return FALSE;
34 }
35
36 ZeroMemory(&pfi2W, sizeof(FORM_INFO_2W));
37
38 if (pfi2A->pName)
39 {
40 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, NULL, 0);
41 pfi2W.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
42 MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, pfi2W.pName, len);
43 }
44
45 pfi2W.Flags = pfi2A->Flags;
46 pfi2W.Size = pfi2A->Size;
47 pfi2W.ImageableArea = pfi2A->ImageableArea;
48
49 if (Level > 1)
50 {
51 if (pfi2A->pKeyword)
52 {
53 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, NULL, 0);
54 pfi2W.pKeyword = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
55 MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, (LPWSTR)pfi2W.pKeyword, len);
56 }
57
58 if (pfi2A->pMuiDll)
59 {
60 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, NULL, 0);
61 pfi2W.pMuiDll = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
62 MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, (LPWSTR)pfi2W.pMuiDll, len);
63 }
64
65 if (pfi2A->pDisplayName)
66 {
67 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, NULL, 0);
68 pfi2W.pDisplayName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
69 MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, (LPWSTR)pfi2W.pDisplayName, len);
70 }
71 pfi2W.StringType = pfi2A->StringType;
72 pfi2W.dwResourceId = pfi2A->dwResourceId;
73 pfi2W.wLangId = pfi2A->wLangId;
74 }
75
76 res = AddFormW( hPrinter, Level, (PBYTE)&pfi2W );
77
78 if (pfi2W.pName) HeapFree(GetProcessHeap(), 0, pfi2W.pName);
79 if (pfi2W.pKeyword) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pKeyword);
80 if (pfi2W.pMuiDll) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pMuiDll);
81 if (pfi2W.pDisplayName) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pDisplayName);
82
83 return res;
84 }
85
86 BOOL WINAPI
AddFormW(HANDLE hPrinter,DWORD Level,PBYTE pForm)87 AddFormW(HANDLE hPrinter, DWORD Level, PBYTE pForm)
88 {
89 DWORD dwErrorCode;
90 WINSPOOL_FORM_CONTAINER FormInfoContainer;
91 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
92
93 TRACE("AddFormW(%p, %lu, %p)\n", hPrinter, Level, pForm);
94
95 // Sanity checks.
96 if (!pHandle)
97 {
98 dwErrorCode = ERROR_INVALID_HANDLE;
99 return FALSE;
100 }
101
102 if ((Level < 1) || (Level > 2))
103 {
104 ERR("Level = %d, unsupported!\n", Level);
105 SetLastError(ERROR_INVALID_LEVEL);
106 return FALSE;
107 }
108
109 FormInfoContainer.FormInfo.pFormInfo1 = (WINSPOOL_FORM_INFO_1*)pForm;
110 FormInfoContainer.Level = Level;
111
112 // Do the RPC call
113 RpcTryExcept
114 {
115 dwErrorCode = _RpcAddForm(pHandle->hPrinter, &FormInfoContainer);
116 }
117 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
118 {
119 dwErrorCode = RpcExceptionCode();
120 ERR("_RpcAddForm failed with exception code %lu!\n", dwErrorCode);
121 }
122 RpcEndExcept;
123
124 SetLastError(dwErrorCode);
125 return (dwErrorCode == ERROR_SUCCESS);
126 }
127
128 BOOL WINAPI
DeleteFormA(HANDLE hPrinter,PSTR pFormName)129 DeleteFormA(HANDLE hPrinter, PSTR pFormName)
130 {
131 UNICODE_STRING FormNameW;
132 BOOL Ret;
133
134 TRACE("DeleteFormA(%p, %s)\n", hPrinter, pFormName);
135
136 AsciiToUnicode(&FormNameW, pFormName);
137
138 Ret = DeleteFormW( hPrinter, FormNameW.Buffer );
139
140 RtlFreeUnicodeString(&FormNameW);
141
142 return Ret;
143 }
144
145 BOOL WINAPI
DeleteFormW(HANDLE hPrinter,PWSTR pFormName)146 DeleteFormW(HANDLE hPrinter, PWSTR pFormName)
147 {
148 DWORD dwErrorCode;
149 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
150
151 TRACE("DeleteFormW(%p, %S)\n", hPrinter, pFormName);
152
153 // Sanity checks.
154 if (!pHandle)
155 {
156 dwErrorCode = ERROR_INVALID_HANDLE;
157 return FALSE;
158 }
159
160 // Do the RPC call
161 RpcTryExcept
162 {
163 dwErrorCode = _RpcDeleteForm(pHandle->hPrinter, pFormName);
164 }
165 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
166 {
167 dwErrorCode = RpcExceptionCode();
168 ERR("_RpcDeleteForm failed with exception code %lu!\n", dwErrorCode);
169 }
170 RpcEndExcept;
171
172 SetLastError(dwErrorCode);
173 return (dwErrorCode == ERROR_SUCCESS);
174 }
175
176 BOOL WINAPI
EnumFormsA(HANDLE hPrinter,DWORD Level,PBYTE pForm,DWORD cbBuf,PDWORD pcbNeeded,PDWORD pcReturned)177 EnumFormsA(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
178 {
179 DWORD dwErrorCode, i;
180 PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
181 PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
182
183 TRACE("EnumFormsA(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
184
185 if ( EnumFormsW( hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned ) )
186 {
187 for ( i = 0; i < *pcReturned; i++ )
188 {
189 switch ( Level )
190 {
191 case 2:
192 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pKeyword);
193 if (dwErrorCode != ERROR_SUCCESS)
194 {
195 goto Cleanup;
196 }
197 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pMuiDll);
198 if (dwErrorCode != ERROR_SUCCESS)
199 {
200 goto Cleanup;
201 }
202 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pDisplayName);
203 if (dwErrorCode != ERROR_SUCCESS)
204 {
205 goto Cleanup;
206 }
207 dwErrorCode = UnicodeToAnsiInPlace(pfi2w[i].pName);
208 if (dwErrorCode != ERROR_SUCCESS)
209 {
210 goto Cleanup;
211 }
212 break;
213 case 1:
214 dwErrorCode = UnicodeToAnsiInPlace(pfi1w[i].pName);
215 if (dwErrorCode != ERROR_SUCCESS)
216 {
217 goto Cleanup;
218 }
219 }
220 }
221 return TRUE;
222 }
223 Cleanup:
224 return FALSE;
225 }
226
227 BOOL WINAPI
EnumFormsW(HANDLE hPrinter,DWORD Level,PBYTE pForm,DWORD cbBuf,PDWORD pcbNeeded,PDWORD pcReturned)228 EnumFormsW(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
229 {
230 DWORD dwErrorCode;
231 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
232
233 TRACE("EnumFormsW(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
234
235 // Sanity checks.
236 if (!pHandle)
237 {
238 dwErrorCode = ERROR_INVALID_HANDLE;
239 goto Cleanup;
240 }
241
242 if ((Level < 1) || (Level > 2))
243 {
244 ERR("Level = %d, unsupported!\n", Level);
245 dwErrorCode = ERROR_INVALID_LEVEL;
246 goto Cleanup;
247 }
248
249 // Do the RPC call
250 RpcTryExcept
251 {
252 dwErrorCode = _RpcEnumForms(pHandle->hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
253 }
254 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
255 {
256 dwErrorCode = RpcExceptionCode();
257 ERR("_RpcEnumForms failed with exception code %lu!\n", dwErrorCode);
258 }
259 RpcEndExcept;
260
261 if (dwErrorCode == ERROR_SUCCESS)
262 {
263 // Replace relative offset addresses in the output by absolute pointers.
264 ASSERT(Level >= 1 && Level <= 2);
265 MarshallUpStructuresArray(cbBuf, pForm, *pcReturned, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE);
266 }
267
268 Cleanup:
269 SetLastError(dwErrorCode);
270 return (dwErrorCode == ERROR_SUCCESS);
271 }
272
273 BOOL WINAPI
GetFormA(HANDLE hPrinter,PSTR pFormName,DWORD Level,PBYTE pForm,DWORD cbBuf,PDWORD pcbNeeded)274 GetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
275 {
276 DWORD dwErrorCode, len;
277 LPWSTR FormNameW = NULL;
278 PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
279 PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
280
281 TRACE("GetFormA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
282
283 if (pFormName)
284 {
285 len = MultiByteToWideChar(CP_ACP, 0, pFormName, -1, NULL, 0);
286 FormNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
287 MultiByteToWideChar(CP_ACP, 0, pFormName, -1, FormNameW, len);
288 }
289
290 if ( GetFormW( hPrinter, FormNameW, Level, pForm, cbBuf, pcbNeeded ) )
291 {
292 switch ( Level )
293 {
294 case 2:
295 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pKeyword);
296 if (dwErrorCode != ERROR_SUCCESS)
297 {
298 goto Cleanup;
299 }
300 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pMuiDll);
301 if (dwErrorCode != ERROR_SUCCESS)
302 {
303 goto Cleanup;
304 }
305 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pDisplayName);
306 if (dwErrorCode != ERROR_SUCCESS)
307 {
308 goto Cleanup;
309 }
310 dwErrorCode = UnicodeToAnsiInPlace(pfi2w->pName);
311 if (dwErrorCode != ERROR_SUCCESS)
312 {
313 goto Cleanup;
314 }
315 break;
316 case 1:
317 dwErrorCode = UnicodeToAnsiInPlace(pfi1w->pName);
318 if (dwErrorCode != ERROR_SUCCESS)
319 {
320 goto Cleanup;
321 }
322 }
323 }
324 Cleanup:
325 if (FormNameW) HeapFree(GetProcessHeap(), 0, FormNameW);
326 return (dwErrorCode == ERROR_SUCCESS);
327 }
328
329 BOOL WINAPI
GetFormW(HANDLE hPrinter,PWSTR pFormName,DWORD Level,PBYTE pForm,DWORD cbBuf,PDWORD pcbNeeded)330 GetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
331 {
332 DWORD dwErrorCode;
333 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
334
335 TRACE("GetFormW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
336
337 // Sanity checks.
338 if (!pHandle)
339 {
340 dwErrorCode = ERROR_INVALID_HANDLE;
341 goto Cleanup;
342 }
343
344 // Dismiss invalid levels already at this point.
345 if ((Level < 1) || (Level > 2))
346 {
347 ERR("Level = %d, unsupported!\n", Level);
348 dwErrorCode = ERROR_INVALID_LEVEL;
349 goto Cleanup;
350 }
351
352 if (cbBuf && pForm)
353 ZeroMemory(pForm, cbBuf);
354
355 // Do the RPC call
356 RpcTryExcept
357 {
358 dwErrorCode = _RpcGetForm(pHandle->hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
359 }
360 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
361 {
362 dwErrorCode = RpcExceptionCode();
363 ERR("_RpcGetForm failed with exception code %lu!\n", dwErrorCode);
364 }
365 RpcEndExcept;
366
367 if (dwErrorCode == ERROR_SUCCESS)
368 {
369 // Replace relative offset addresses in the output by absolute pointers.
370 ASSERT(Level >= 1 && Level <= 2);
371 MarshallUpStructure(cbBuf, pForm, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE);
372 }
373
374 Cleanup:
375 SetLastError(dwErrorCode);
376 return (dwErrorCode == ERROR_SUCCESS);
377 }
378
379 BOOL WINAPI
SetFormA(HANDLE hPrinter,PSTR pFormName,DWORD Level,PBYTE pForm)380 SetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm)
381 {
382 FORM_INFO_2W pfi2W;
383 FORM_INFO_2A * pfi2A;
384 LPWSTR FormNameW = NULL;
385 DWORD len;
386 BOOL res;
387
388 pfi2A = (FORM_INFO_2A *) pForm;
389
390 TRACE("SetFormA(%p, %s, %lu, %p)\n", hPrinter, pFormName, Level, pForm);
391
392 if ((Level < 1) || (Level > 2))
393 {
394 ERR("Level = %d, unsupported!\n", Level);
395 SetLastError(ERROR_INVALID_LEVEL);
396 return FALSE;
397 }
398
399 if (!pfi2A)
400 {
401 SetLastError(ERROR_INVALID_PARAMETER);
402 return FALSE;
403 }
404
405 if (pFormName)
406 {
407 len = MultiByteToWideChar(CP_ACP, 0, pFormName, -1, NULL, 0);
408 FormNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
409 MultiByteToWideChar(CP_ACP, 0, pFormName, -1, FormNameW, len);
410 }
411
412 ZeroMemory(&pfi2W, sizeof(FORM_INFO_2W));
413
414 if (pfi2A->pName)
415 {
416 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, NULL, 0);
417 pfi2W.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
418 MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, pfi2W.pName, len);
419 }
420
421 pfi2W.Flags = pfi2A->Flags;
422 pfi2W.Size = pfi2A->Size;
423 pfi2W.ImageableArea = pfi2A->ImageableArea;
424
425 if (Level > 1)
426 {
427 if (pfi2A->pKeyword)
428 {
429 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, NULL, 0);
430 pfi2W.pKeyword = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
431 MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, (LPWSTR)pfi2W.pKeyword, len);
432 }
433
434 if (pfi2A->pMuiDll)
435 {
436 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, NULL, 0);
437 pfi2W.pMuiDll = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
438 MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, (LPWSTR)pfi2W.pMuiDll, len);
439 }
440
441 if (pfi2A->pDisplayName)
442 {
443 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, NULL, 0);
444 pfi2W.pDisplayName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
445 MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, (LPWSTR)pfi2W.pDisplayName, len);
446 }
447 pfi2W.StringType = pfi2A->StringType;
448 pfi2W.dwResourceId = pfi2A->dwResourceId;
449 pfi2W.wLangId = pfi2A->wLangId;
450 }
451
452 res = SetFormW( hPrinter, FormNameW, Level, (PBYTE)&pfi2W );
453
454 if (FormNameW) HeapFree(GetProcessHeap(), 0, FormNameW);
455 if (pfi2W.pName) HeapFree(GetProcessHeap(), 0, pfi2W.pName);
456 if (pfi2W.pKeyword) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pKeyword);
457 if (pfi2W.pMuiDll) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pMuiDll);
458 if (pfi2W.pDisplayName) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pDisplayName);
459
460 return res;
461 }
462
463 BOOL WINAPI
SetFormW(HANDLE hPrinter,PWSTR pFormName,DWORD Level,PBYTE pForm)464 SetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm)
465 {
466 DWORD dwErrorCode;
467 WINSPOOL_FORM_CONTAINER FormInfoContainer;
468 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
469
470 TRACE("SetFormW(%p, %S, %lu, %p)\n", hPrinter, pFormName, Level, pForm);
471
472 // Sanity checks.
473 if (!pHandle)
474 {
475 ERR("Level = %d, unsupported!\n", Level);
476 dwErrorCode = ERROR_INVALID_HANDLE;
477 return FALSE;
478 }
479
480 FormInfoContainer.FormInfo.pFormInfo1 = (WINSPOOL_FORM_INFO_1*)pForm;
481 FormInfoContainer.Level = Level;
482
483 // Do the RPC call
484 RpcTryExcept
485 {
486 dwErrorCode = _RpcSetForm(pHandle->hPrinter, pFormName, &FormInfoContainer);
487 }
488 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
489 {
490 dwErrorCode = RpcExceptionCode();
491 }
492 RpcEndExcept;
493
494 SetLastError(dwErrorCode);
495 return (dwErrorCode == ERROR_SUCCESS);
496 }
497