7d8a0e65d9e5fcf28a93464432db6a09c6ea7dc5
[reactos.git] / win32ss / printing / base / winspool / forms.c
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
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
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
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
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
177 EnumFormsA(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
178 {
179 DWORD dwErrorCode, i;
180 PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
181
182 TRACE("EnumFormsA(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
183
184 if ( EnumFormsW( hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned ) )
185 {
186 for ( i = 0; i < *pcReturned; i++ )
187 {
188 switch ( Level )
189 {
190 case 2:
191 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pKeyword);
192 if (dwErrorCode != ERROR_SUCCESS)
193 {
194 goto Cleanup;
195 }
196 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pMuiDll);
197 if (dwErrorCode != ERROR_SUCCESS)
198 {
199 goto Cleanup;
200 }
201 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pDisplayName);
202 if (dwErrorCode != ERROR_SUCCESS)
203 {
204 goto Cleanup;
205 }
206 // Fall through...
207 case 1:
208 dwErrorCode = UnicodeToAnsiInPlace(pfi2w[i].pName);
209 if (dwErrorCode != ERROR_SUCCESS)
210 {
211 goto Cleanup;
212 }
213 }
214 }
215 return TRUE;
216 }
217 Cleanup:
218 return FALSE;
219 }
220
221 BOOL WINAPI
222 EnumFormsW(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
223 {
224 DWORD dwErrorCode;
225 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
226
227 TRACE("EnumFormsW(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
228
229 // Sanity checks.
230 if (!pHandle)
231 {
232 dwErrorCode = ERROR_INVALID_HANDLE;
233 goto Cleanup;
234 }
235
236 if ((Level < 1) || (Level > 2))
237 {
238 ERR("Level = %d, unsupported!\n", Level);
239 dwErrorCode = ERROR_INVALID_LEVEL;
240 goto Cleanup;
241 }
242
243 // Do the RPC call
244 RpcTryExcept
245 {
246 dwErrorCode = _RpcEnumForms(pHandle->hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
247 }
248 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
249 {
250 dwErrorCode = RpcExceptionCode();
251 ERR("_RpcEnumForms failed with exception code %lu!\n", dwErrorCode);
252 }
253 RpcEndExcept;
254
255 if (dwErrorCode == ERROR_SUCCESS)
256 {
257 // Replace relative offset addresses in the output by absolute pointers.
258 ASSERT(Level >= 1 && Level <= 2);
259 MarshallUpStructuresArray(cbBuf, pForm, *pcReturned, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE);
260 }
261
262 Cleanup:
263 SetLastError(dwErrorCode);
264 return (dwErrorCode == ERROR_SUCCESS);
265 }
266
267 BOOL WINAPI
268 GetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
269 {
270 DWORD dwErrorCode, len;
271 LPWSTR FormNameW = NULL;
272 FORM_INFO_2W* pfi2w = (FORM_INFO_2W*)pForm;
273
274 TRACE("GetFormA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
275
276 if (pFormName)
277 {
278 len = MultiByteToWideChar(CP_ACP, 0, pFormName, -1, NULL, 0);
279 FormNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
280 MultiByteToWideChar(CP_ACP, 0, pFormName, -1, FormNameW, len);
281 }
282
283 if ( GetFormW( hPrinter, FormNameW, Level, pForm, cbBuf, pcbNeeded ) )
284 {
285 switch ( Level )
286 {
287 case 2:
288 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pKeyword);
289 if (dwErrorCode != ERROR_SUCCESS)
290 {
291 goto Cleanup;
292 }
293 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pMuiDll);
294 if (dwErrorCode != ERROR_SUCCESS)
295 {
296 goto Cleanup;
297 }
298 dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pDisplayName);
299 if (dwErrorCode != ERROR_SUCCESS)
300 {
301 goto Cleanup;
302 }
303 // Fall through...
304 case 1:
305 dwErrorCode = UnicodeToAnsiInPlace(pfi2w->pName);
306 if (dwErrorCode != ERROR_SUCCESS)
307 {
308 goto Cleanup;
309 }
310 break;
311
312 default:
313 ERR("Level = %d, unsupported!\n", Level);
314 dwErrorCode = ERROR_INVALID_HANDLE;
315 SetLastError(dwErrorCode);
316 break;
317 }
318 }
319 Cleanup:
320 if (FormNameW) HeapFree(GetProcessHeap(), 0, FormNameW);
321 return (dwErrorCode == ERROR_SUCCESS);
322 }
323
324 BOOL WINAPI
325 GetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
326 {
327 DWORD dwErrorCode;
328 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
329
330 TRACE("GetFormW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
331
332 // Sanity checks.
333 if (!pHandle)
334 {
335 dwErrorCode = ERROR_INVALID_HANDLE;
336 goto Cleanup;
337 }
338
339 // Dismiss invalid levels already at this point.
340 if ((Level < 1) || (Level > 2))
341 {
342 ERR("Level = %d, unsupported!\n", Level);
343 dwErrorCode = ERROR_INVALID_LEVEL;
344 goto Cleanup;
345 }
346
347 if (cbBuf && pForm)
348 ZeroMemory(pForm, cbBuf);
349
350 // Do the RPC call
351 RpcTryExcept
352 {
353 dwErrorCode = _RpcGetForm(pHandle->hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
354 }
355 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
356 {
357 dwErrorCode = RpcExceptionCode();
358 ERR("_RpcGetForm failed with exception code %lu!\n", dwErrorCode);
359 }
360 RpcEndExcept;
361
362 if (dwErrorCode == ERROR_SUCCESS)
363 {
364 // Replace relative offset addresses in the output by absolute pointers.
365 ASSERT(Level >= 1 && Level <= 2);
366 MarshallUpStructure(cbBuf, pForm, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE);
367 }
368
369 Cleanup:
370 SetLastError(dwErrorCode);
371 return (dwErrorCode == ERROR_SUCCESS);
372 }
373
374 BOOL WINAPI
375 SetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm)
376 {
377 FORM_INFO_2W pfi2W;
378 FORM_INFO_2A * pfi2A;
379 LPWSTR FormNameW = NULL;
380 DWORD len;
381 BOOL res;
382
383 pfi2A = (FORM_INFO_2A *) pForm;
384
385 TRACE("SetFormA(%p, %s, %lu, %p)\n", hPrinter, pFormName, Level, pForm);
386
387 if ((Level < 1) || (Level > 2))
388 {
389 ERR("Level = %d, unsupported!\n", Level);
390 SetLastError(ERROR_INVALID_LEVEL);
391 return FALSE;
392 }
393
394 if (!pfi2A)
395 {
396 SetLastError(ERROR_INVALID_PARAMETER);
397 return FALSE;
398 }
399
400 if (pFormName)
401 {
402 len = MultiByteToWideChar(CP_ACP, 0, pFormName, -1, NULL, 0);
403 FormNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
404 MultiByteToWideChar(CP_ACP, 0, pFormName, -1, FormNameW, len);
405 }
406
407 ZeroMemory(&pfi2W, sizeof(FORM_INFO_2W));
408
409 if (pfi2A->pName)
410 {
411 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, NULL, 0);
412 pfi2W.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
413 MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, pfi2W.pName, len);
414 }
415
416 pfi2W.Flags = pfi2A->Flags;
417 pfi2W.Size = pfi2A->Size;
418 pfi2W.ImageableArea = pfi2A->ImageableArea;
419
420 if (Level > 1)
421 {
422 if (pfi2A->pKeyword)
423 {
424 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, NULL, 0);
425 pfi2W.pKeyword = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
426 MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, (LPWSTR)pfi2W.pKeyword, len);
427 }
428
429 if (pfi2A->pMuiDll)
430 {
431 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, NULL, 0);
432 pfi2W.pMuiDll = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
433 MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, (LPWSTR)pfi2W.pMuiDll, len);
434 }
435
436 if (pfi2A->pDisplayName)
437 {
438 len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, NULL, 0);
439 pfi2W.pDisplayName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
440 MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, (LPWSTR)pfi2W.pDisplayName, len);
441 }
442 pfi2W.StringType = pfi2A->StringType;
443 pfi2W.dwResourceId = pfi2A->dwResourceId;
444 pfi2W.wLangId = pfi2A->wLangId;
445 }
446
447 res = SetFormW( hPrinter, FormNameW, Level, (PBYTE)&pfi2W );
448
449 if (FormNameW) HeapFree(GetProcessHeap(), 0, FormNameW);
450 if (pfi2W.pName) HeapFree(GetProcessHeap(), 0, pfi2W.pName);
451 if (pfi2W.pKeyword) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pKeyword);
452 if (pfi2W.pMuiDll) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pMuiDll);
453 if (pfi2W.pDisplayName) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pDisplayName);
454
455 return res;
456 }
457
458 BOOL WINAPI
459 SetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm)
460 {
461 DWORD dwErrorCode;
462 WINSPOOL_FORM_CONTAINER FormInfoContainer;
463 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
464
465 TRACE("SetFormW(%p, %S, %lu, %p)\n", hPrinter, pFormName, Level, pForm);
466
467 // Sanity checks.
468 if (!pHandle)
469 {
470 ERR("Level = %d, unsupported!\n", Level);
471 dwErrorCode = ERROR_INVALID_HANDLE;
472 return FALSE;
473 }
474
475 FormInfoContainer.FormInfo.pFormInfo1 = (WINSPOOL_FORM_INFO_1*)pForm;
476 FormInfoContainer.Level = Level;
477
478 // Do the RPC call
479 RpcTryExcept
480 {
481 dwErrorCode = _RpcSetForm(pHandle->hPrinter, pFormName, &FormInfoContainer);
482 }
483 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
484 {
485 dwErrorCode = RpcExceptionCode();
486 }
487 RpcEndExcept;
488
489 SetLastError(dwErrorCode);
490 return (dwErrorCode == ERROR_SUCCESS);
491 }