xref: /reactos/win32ss/printing/base/winspool/forms.c (revision 62c4b828)
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