1 /*
2 * PROJECT: ReactOS Spooler Router
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Functions for managing print Forms
5 * COPYRIGHT: Copyright 2020 ReactOS
6 */
7
8 #include "precomp.h"
9
10 #define FORMINFOSIG '.2'
11 #define FORMMAXNAMESIZE CCHDEVICENAME-1
12
13 typedef struct _FORM_INFO_LIST
14 {
15 LIST_ENTRY List;
16 DWORD Sig;
17 DWORD Index;
18 FORM_INFO_2W;
19 } FORM_INFO_LIST, *PFORM_INFO_LIST;
20
21 LIST_ENTRY FormList;
22 static DWORD _dwLastForm;
23
24 // Local Constants
25 static DWORD dwFormInfo1Offsets[] = {
26 FIELD_OFFSET(FORM_INFO_1W, pName),
27 MAXDWORD
28 };
29
30 static DWORD dwFormInfo2Offsets[] = {
31 FIELD_OFFSET(FORM_INFO_2W, pName),
32 FIELD_OFFSET(FORM_INFO_2W, pKeyword),
33 FIELD_OFFSET(FORM_INFO_2W, pMuiDll),
34 FIELD_OFFSET(FORM_INFO_2W, pDisplayName),
35 MAXDWORD
36 };
37
38
39 // Built in Form names
40 WCHAR wszLetter[] = L"Letter";
41 WCHAR wszLetterSmall[] = L"Letter Small";
42 WCHAR wszTabloid[] = L"Tabloid";
43 WCHAR wszLedger[] = L"Ledger";
44 WCHAR wszLegal[] = L"Legal";
45 WCHAR wszStatement[] = L"Statement";
46 WCHAR wszExecutive[] = L"Executive";
47 WCHAR wszA3[] = L"A3";
48 WCHAR wszA4[] = L"A4";
49 WCHAR wszA4Small[] = L"A4 Small";
50 WCHAR wszA5[] = L"A5";
51 WCHAR wszB4JIS[] = L"B4 (JIS)";
52 WCHAR wszB5JIS[] = L"B5 (JIS)";
53 WCHAR wszFolio[] = L"Folio";
54 WCHAR wszQuarto[] = L"Quarto";
55 WCHAR wsz10x14[] = L"10 x 14";
56 WCHAR wsz11x17[] = L"11 x 17";
57 WCHAR wszNote[] = L"Note";
58 WCHAR wszEnvelope9[] = L"Envelope #9";
59 WCHAR wszEnvelope10[] = L"Envelope #10";
60 WCHAR wszEnvelope11[] = L"Envelope #11";
61 WCHAR wszEnvelope12[] = L"Envelope #12";
62 WCHAR wszEnvelope14[] = L"Envelope #14";
63 WCHAR wszCsizesheet[] = L"C size sheet";
64 WCHAR wszDsizesheet[] = L"D size sheet";
65 WCHAR wszEsizesheet[] = L"E size sheet";
66 WCHAR wszEnvelopeDL[] = L"Envelope DL";
67 WCHAR wszEnvelopeC5[] = L"Envelope C5";
68 WCHAR wszEnvelopeC3[] = L"Envelope C3";
69 WCHAR wszEnvelopeC4[] = L"Envelope C4";
70 WCHAR wszEnvelopeC6[] = L"Envelope C6";
71 WCHAR wszEnvelope65[] = L"Envelope 65";
72 WCHAR wszEnvelopeB4[] = L"Envelope B4";
73 WCHAR wszEnvelopeB5[] = L"Envelope B5";
74 WCHAR wszEnvelopeB6[] = L"Envelope B6";
75 WCHAR wszEnvelope[] = L"Envelope";
76 WCHAR wszEnvelopeMonarch[] = L"Envelope Monarch";
77 WCHAR wsz634Envelope[] = L"6 3/4 Envelope";
78 WCHAR wszUSStdFanfold[] = L"US Std Fanfold";
79 WCHAR wszGermanStdFanfold[] = L"German Std Fanfold";
80 WCHAR wszGermanLegalFanfold[] = L"German Legal Fanfold";
81 WCHAR wszB4ISO[] = L"B4 (ISO)";
82 WCHAR wszJapanesePostcard[] = L"Japanese Postcard";
83 WCHAR wsz9x11[] = L"9 x 11";
84 WCHAR wsz10x11[] = L"10 x 11";
85 WCHAR wsz15x11[] = L"15 x 11";
86 WCHAR wszEnvelopeInvite[] = L"Envelope Invite";
87 WCHAR wszReserved48[] = L"Reserved48";
88 WCHAR wszReserved49[] = L"Reserved49";
89 WCHAR wszLetterExtra[] = L"Letter Extra";
90 WCHAR wszLegalExtra[] = L"Legal Extra";
91 WCHAR wszTabloidExtra[] = L"Tabloid Extra";
92 WCHAR wszA4Extra[] = L"A4 Extra";
93 WCHAR wszLetterTransverse[] = L"Letter Transverse";
94 WCHAR wszA4Transverse[] = L"A4 Transverse";
95 WCHAR wszLetterExtraTransverse[] = L"Letter Extra Transverse";
96 WCHAR wszSuperA[] = L"Super A";
97 WCHAR wszSuperB[] = L"Super B";
98 WCHAR wszLetterPlus[] = L"Letter Plus";
99 WCHAR wszA4Plus[] = L"A4 Plus";
100 WCHAR wszA5Transverse[] = L"A5 Transverse";
101 WCHAR wszB5JISTransverse[] = L"B5 (JIS) Transverse";
102 WCHAR wszA3Extra[] = L"A3 Extra";
103 WCHAR wszA5Extra[] = L"A5 Extra";
104 WCHAR wszB5ISOExtra[] = L"B5 (ISO) Extra";
105 WCHAR wszA0[] = L"A0";
106 WCHAR wszA3Transverse[] = L"A3 Transverse";
107 WCHAR wszA3ExtraTransverse[] = L"A3 Extra Transverse";
108 WCHAR wszJapaneseDoublePostcard[] = L"Japanese Double Postcard";
109 WCHAR wszA1[] = L"A1";
110 WCHAR wszJapaneseEnvelopeKaku2[] = L"Japanese Envelope Kaku #2";
111 WCHAR wszJapaneseEnvelopeKaku3[] = L"Japanese Envelope Kaku #3";
112 WCHAR wszJapaneseEnvelopeChou3[] = L"Japanese Envelope Chou #3";
113 WCHAR wszJapaneseEnvelopeChou4[] = L"Japanese Envelope Chou #4";
114 WCHAR wszLetterRotated[] = L"Letter Rotated";
115 WCHAR wszA3Rotated[] = L"A3 Rotated";
116 WCHAR wszA4Rotated[] = L"A4 Rotated";
117 WCHAR wszA5Rotated[] = L"A5 Rotated";
118 WCHAR wszB4JISRotated[] = L"B4 (JIS) Rotated";
119 WCHAR wszB5JISRotated[] = L"B5 (JIS) Rotated";
120 WCHAR wszJapanesePostcardRotated[] = L"Japanese Postcard Rotated";
121 WCHAR wszDoubleJapanPostcardRotated[] = L"Double Japan Postcard Rotated";
122 WCHAR wsA6Rotatedz[] = L"A6 Rotated";
123 WCHAR wszJapanEnvelopeKaku2Rotated[] = L"Japan Envelope Kaku #2 Rotated";
124 WCHAR wszJapanEnvelopeKaku3Rotated[] = L"Japan Envelope Kaku #3 Rotated";
125 WCHAR wszJapanEnvelopeChou3Rotated[] = L"Japan Envelope Chou #3 Rotated";
126 WCHAR wszJapanEnvelopeChou4Rotated[] = L"Japan Envelope Chou #4 Rotated";
127 WCHAR wszB6JIS[] = L"B6 (JIS)";
128 WCHAR wszB6JISRotated[] = L"B6 (JIS) Rotated";
129 WCHAR wsz12x11[] = L"12 x 11";
130 WCHAR wszJapanEnvelopeYou4[] = L"Japan Envelope You #4";
131 WCHAR wszJapanEnvelopeYou4Rotated[] = L"Japan Envelope You #4 Rotated";
132 WCHAR wszPRC16K[] = L"PRC 16K";
133 WCHAR wszPRC32K[] = L"PRC 32K";
134 WCHAR wszPRC32KBig[] = L"PRC 32K(Big)";
135 WCHAR wszPRCEnvelope1[] = L"PRC Envelope #1";
136 WCHAR wszPRCEnvelope2[] = L"PRC Envelope #2";
137 WCHAR wszPRCEnvelope3[] = L"PRC Envelope #3";
138 WCHAR wszPRCEnvelope4[] = L"PRC Envelope #4";
139 WCHAR wszPRCEnvelope5[] = L"PRC Envelope #5";
140 WCHAR wszPRCEnvelope6[] = L"PRC Envelope #6";
141 WCHAR wszPRCEnvelope7[] = L"PRC Envelope #7";
142 WCHAR wszPRCEnvelope8[] = L"PRC Envelope #8";
143 WCHAR wszPRCEnvelope9[] = L"PRC Envelope #9";
144 WCHAR wszPRCEnvelope10[] = L"PRC Envelope #10";
145 WCHAR wszPRC16KRotated[] = L"PRC 16K Rotated";
146 WCHAR wszPRC32KRotated[] = L"PRC 32K Rotated";
147 WCHAR wszPRC32KBigRotated[] = L"PRC 32K(Big) Rotated";
148 WCHAR wszPRCEnvelope1Rotated[] = L"PRC Envelope #1 Rotated";
149 WCHAR wszPRCEnvelope2Rotated[] = L"PRC Envelope #2 Rotated";
150 WCHAR wszPRCEnvelope3Rotated[] = L"PRC Envelope #3 Rotated";
151 WCHAR wszPRCEnvelope4Rotated[] = L"PRC Envelope #4 Rotated";
152 WCHAR wszPRCEnvelope5Rotated[] = L"PRC Envelope #5 Rotated";
153 WCHAR wszPRCEnvelope6Rotated[] = L"PRC Envelope #6 Rotated";
154 WCHAR wszPRCEnvelope7Rotated[] = L"PRC Envelope #7 Rotated";
155 WCHAR wszPRCEnvelope8Rotated[] = L"PRC Envelope #8 Rotated";
156 WCHAR wszPRCEnvelope9Rotated[] = L"PRC Envelope #9 Rotated";
157 WCHAR wszPRCEnvelope10Rotated[] = L"PRC Envelope #10 Rotated";
158
159 // Built in Forms
160 FORM_INFO_1W BuiltInForms[] =
161 {
162 { FORM_USER, wszLetter, {215900, 279400},{ 0, 0, 215900, 279400}},
163 { FORM_USER, wszLetterSmall, {215900, 279400},{ 0, 0, 215900, 279400}},
164 { FORM_USER, wszTabloid, {279400, 431800},{ 0, 0, 279400, 431800}},
165 { FORM_USER, wszLedger, {431800, 279400},{ 0, 0, 431800, 279400}},
166 { FORM_USER, wszLegal, {215900, 355600},{ 0, 0, 215900, 355600}},
167 { FORM_USER, wszStatement, {139700, 215900},{ 0, 0, 139700, 215900}},
168 { FORM_USER, wszExecutive, {184150, 266700},{ 0, 0, 184150, 266700}},
169 { FORM_USER, wszA3, {297000, 420000},{ 0, 0, 297000, 420000}},
170 { FORM_USER, wszA4, {210000, 297000},{ 0, 0, 210000, 297000}},
171 { FORM_USER, wszA4Small, {210000, 297000},{ 0, 0, 210000, 297000}},
172 { FORM_USER, wszA5, {148000, 210000},{ 0, 0, 148000, 210000}},
173 { FORM_USER, wszB4JIS, {257000, 364000},{ 0, 0, 257000, 364000}},
174 { FORM_USER, wszB5JIS, {182000, 257000},{ 0, 0, 182000, 257000}},
175 { FORM_USER, wszFolio, {215900, 330200},{ 0, 0, 215900, 330200}},
176 { FORM_USER, wszQuarto, {215000, 275000},{ 0, 0, 215000, 275000}},
177 { FORM_USER, wsz10x14, {254000, 355600},{ 0, 0, 254000, 355600}},
178 { FORM_USER, wsz11x17, {279400, 431800},{ 0, 0, 279400, 431800}},
179 { FORM_USER, wszNote, {215900, 279400},{ 0, 0, 215900, 279400}},
180 { FORM_USER, wszEnvelope9, { 98425, 225425},{ 0, 0, 98425, 225425}},
181 { FORM_USER, wszEnvelope10, {104775, 241300},{ 0, 0, 104775, 241300}},
182 { FORM_USER, wszEnvelope11, {114300, 263525},{ 0, 0, 114300, 263525}},
183 { FORM_USER, wszEnvelope12, {120650, 279400},{ 0, 0, 120650, 279400}},
184 { FORM_USER, wszEnvelope14, {127000, 292100},{ 0, 0, 127000, 292100}},
185 { FORM_USER, wszCsizesheet, {431800, 558800},{ 0, 0, 431800, 558800}},
186 { FORM_USER, wszDsizesheet, {558800, 863600},{ 0, 0, 558800, 863600}},
187 { FORM_USER, wszEsizesheet, {863600,1117600},{ 0, 0, 863600,1117600}},
188 { FORM_USER, wszEnvelopeDL, {110000, 220000},{ 0, 0, 110000, 220000}},
189 { FORM_USER, wszEnvelopeC5, {162000, 229000},{ 0, 0, 162000, 229000}},
190 { FORM_USER, wszEnvelopeC3, {324000, 458000},{ 0, 0, 324000, 458000}},
191 { FORM_USER, wszEnvelopeC4, {229000, 324000},{ 0, 0, 229000, 324000}},
192 { FORM_USER, wszEnvelopeC6, {114000, 162000},{ 0, 0, 114000, 162000}},
193 { FORM_USER, wszEnvelope65, {114000, 229000},{ 0, 0, 114000, 229000}},
194 { FORM_USER, wszEnvelopeB4, {250000, 353000},{ 0, 0, 250000, 353000}},
195 { FORM_USER, wszEnvelopeB5, {176000, 250000},{ 0, 0, 176000, 250000}},
196 { FORM_USER, wszEnvelopeB6, {176000, 125000},{ 0, 0, 176000, 125000}},
197 { FORM_USER, wszEnvelope, {110000, 230000},{ 0, 0, 110000, 230000}},
198 { FORM_USER, wszEnvelopeMonarch, { 98425, 190500},{ 0, 0, 98425, 190500}},
199 { FORM_USER, wsz634Envelope, { 92075, 165100},{ 0, 0, 92075, 165100}},
200 { FORM_USER, wszUSStdFanfold, {377825, 279400},{ 0, 0, 377825, 279400}},
201 { FORM_USER, wszGermanStdFanfold, {215900, 304800},{ 0, 0, 215900, 304800}},
202 { FORM_USER, wszGermanLegalFanfold, {215900, 330200},{ 0, 0, 215900, 330200}},
203 // add more, I'm lazy
204 { FORM_USER, wszDoubleJapanPostcardRotated,{148000, 200000},{ 0, 0, 148000, 200000}},
205 //
206 { FORM_USER, wszPRCEnvelope10Rotated, {458000, 324009},{ 0, 0, 458000, 324009}},
207 { FORM_USER, 0, { 0, 0},{ 0, 0, 0, 0}}
208 };
209
210 //
211 // Form information Registry entry stucture, in correct format.
212 //
213 // Example : 11 x 17 REG_BINARY 68 43 04 00 b8 96 06 00 00 00 00 00 00 00 00 00 68 43 04 00 b8 96 06 00 01 00 00 00 02 00 00 00
214 // [ Size | ImageableArea | Index 1 + | Flags ] , is FORM_PRINTER.
215 //
216 typedef struct _REGISTRYFORMINFO
217 {
218 SIZEL Size;
219 RECTL ImageableArea;
220 DWORD Index;
221 DWORD Flags;
222 } REGISTRYFORMINFO, *PREGISTRYFORMINFO;
223
224 HKEY hFormCKey = NULL;
225 HKEY hFormsKey = NULL;
226
227 BOOL
InitializeFormList(VOID)228 InitializeFormList(VOID)
229 {
230 DWORD dwErrorCode;
231 PFORM_INFO_LIST pfil;
232 REGISTRYFORMINFO rfi;
233
234 FIXME("InitializeFormList\n");
235
236 dwErrorCode = (DWORD)RegCreateKeyExW( HKEY_LOCAL_MACHINE,
237 L"SYSTEM\\CurrentControlSet\\Control\\Print\\Forms",
238 0,
239 NULL,
240 REG_OPTION_VOLATILE,
241 KEY_ALL_ACCESS,
242 NULL,
243 &hFormCKey,
244 NULL ); // KEY_OPENED_EXISTING_KEY );
245
246 if ( dwErrorCode != ERROR_SUCCESS && dwErrorCode != ERROR_ALREADY_EXISTS )
247 {
248 ERR("RegCreateKeyExW failed for the Forms with error %lu!\n", dwErrorCode);
249 goto Cleanup;
250 }
251
252 // Open some registry keys and leave them open. We need them multiple times throughout the Local Spooler.
253 dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Forms", 0, KEY_ALL_ACCESS, &hFormsKey);
254 if (dwErrorCode != ERROR_SUCCESS)
255 {
256 ERR("RegOpenKeyExW failed for \"Forms\" with error %lu!\n", dwErrorCode);
257 goto Cleanup;
258 }
259
260 _dwLastForm = 1;
261
262 InitializeListHead(&FormList);
263
264 {
265 int i = 0, Size;
266 while ( BuiltInForms[ i ].pName != NULL )
267 {
268 TRACE("InitializeFormList L s %S\n",BuiltInForms[ i ].pName );
269
270 Size = sizeof(FORM_INFO_LIST) + ((wcslen(BuiltInForms[ i ].pName) + 1) * sizeof(WCHAR));
271
272 pfil = DllAllocSplMem( Size );
273
274 pfil->pName = wcscpy( (PWSTR)(pfil+1), BuiltInForms[ i ].pName );
275 pfil->Flags = BuiltInForms[ i ].Flags;
276 pfil->Size = BuiltInForms[ i ].Size;
277 pfil->ImageableArea = BuiltInForms[ i ].ImageableArea;
278 pfil->Sig = FORMINFOSIG;
279 pfil->Index = _dwLastForm++;
280 pfil->pKeyword = NULL;
281 pfil->StringType = STRING_NONE;
282 pfil->pMuiDll = NULL;
283 pfil->dwResourceId = 0;
284 pfil->pDisplayName = NULL;
285 pfil->wLangId = 0;
286
287 InsertTailList( &FormList, &pfil->List );
288
289 rfi.Size = pfil->Size;
290 rfi.ImageableArea = pfil->ImageableArea;
291 rfi.Index = pfil->Index;
292 rfi.Flags = pfil->Flags;
293
294 dwErrorCode = RegSetValueExW( hFormsKey, pfil->pName, 0, REG_BINARY, (PBYTE)&rfi, sizeof( rfi ) );
295 if ( dwErrorCode == ERROR_SUCCESS )
296 {
297 TRACE("Init : RQVEW : %S added\n",pfil->pName);
298 }
299
300 i++;
301 }
302 }
303
304 Cleanup:
305 return TRUE;
306 }
307
308 PFORM_INFO_LIST
309 FASTCALL
FindForm(WCHAR * pFormName,WCHAR * pKeyword)310 FindForm( WCHAR * pFormName, WCHAR * pKeyword )
311 {
312 PLIST_ENTRY ListEntry;
313 PFORM_INFO_LIST pfil;
314
315 ListEntry = FormList.Flink;
316
317 while (ListEntry != &FormList)
318 {
319 pfil = CONTAINING_RECORD(ListEntry, FORM_INFO_LIST, List);
320
321 ListEntry = ListEntry->Flink;
322
323 if ( pFormName && !_wcsicmp( pfil->pName, pFormName ) )
324 return pfil;
325
326 if ( pKeyword && !_wcsicmp( (WCHAR*)pfil->pKeyword, pKeyword ) )
327 return pfil;
328 }
329 return NULL;
330 }
331
332 static void
_LocalGetFormLevel1(PFORM_INFO_LIST pfil,PFORM_INFO_1W * ppFormInfo,PBYTE * ppFormInfoEnd,PDWORD pcbNeeded)333 _LocalGetFormLevel1(PFORM_INFO_LIST pfil, PFORM_INFO_1W* ppFormInfo, PBYTE* ppFormInfoEnd, PDWORD pcbNeeded)
334 {
335 DWORD n;
336 PCWSTR pwszStrings[1];
337
338 pwszStrings[0] = pfil->pName;
339
340 // Calculate the string lengths.
341 if (!ppFormInfo)
342 {
343 for (n = 0; n < _countof(pwszStrings); ++n)
344 {
345 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
346 }
347
348 *pcbNeeded += sizeof(FORM_INFO_1W);
349 return;
350 }
351
352 (*ppFormInfo)->Flags = pfil->Flags;
353 (*ppFormInfo)->Size = pfil->Size;
354 (*ppFormInfo)->ImageableArea = pfil->ImageableArea;
355
356 // Finally copy the structure and advance to the next one in the output buffer.
357 *ppFormInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppFormInfo), dwFormInfo1Offsets, *ppFormInfoEnd);
358 (*ppFormInfo)++;
359 }
360
361 static void
_LocalGetFormLevel2(PFORM_INFO_LIST pfil,PFORM_INFO_2W * ppFormInfo,PBYTE * ppFormInfoEnd,PDWORD pcbNeeded)362 _LocalGetFormLevel2(PFORM_INFO_LIST pfil, PFORM_INFO_2W* ppFormInfo, PBYTE* ppFormInfoEnd, PDWORD pcbNeeded)
363 {
364 DWORD n;
365 PCWSTR pwszStrings[4];
366
367 pwszStrings[0] = pfil->pName;
368 pwszStrings[1] = (PCWSTR)pfil->pKeyword;
369 pwszStrings[2] = pfil->pMuiDll;
370 pwszStrings[3] = pfil->pDisplayName;
371
372 // Calculate the string lengths.
373 if (!ppFormInfo)
374 {
375 for (n = 0; n < _countof(pwszStrings); ++n)
376 {
377 if (pwszStrings[n])
378 {
379 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
380 }
381 }
382 *pcbNeeded += sizeof(FORM_INFO_2W);
383 return;
384 }
385
386 (*ppFormInfo)->Flags = pfil->Flags;
387 (*ppFormInfo)->Size = pfil->Size;
388 (*ppFormInfo)->ImageableArea = pfil->ImageableArea;
389 (*ppFormInfo)->StringType = pfil->StringType; //// If caller is remote, set STRING_LANGPAIR always;
390 (*ppFormInfo)->dwResourceId = pfil->dwResourceId;
391
392 // Finally copy the structure and advance to the next one in the output buffer.
393 *ppFormInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppFormInfo), dwFormInfo2Offsets, *ppFormInfoEnd);
394 (*ppFormInfo)++;
395 }
396
397 typedef void (*PLocalGetFormLevelFunc)(PFORM_INFO_LIST, PVOID, PBYTE*, PDWORD);
398
399 static const PLocalGetFormLevelFunc pfnGetFormLevels[] = {
400 NULL,
401 (PLocalGetFormLevelFunc)&_LocalGetFormLevel1,
402 (PLocalGetFormLevelFunc)&_LocalGetFormLevel2
403 };
404
405 //
406 // API Functions
407 //
408 BOOL WINAPI
LocalAddForm(HANDLE hPrinter,DWORD Level,PBYTE pForm)409 LocalAddForm(HANDLE hPrinter, DWORD Level, PBYTE pForm)
410 {
411 DWORD dwErrorCode, Size, cbNeeded;
412 PFORM_INFO_LIST pfil;
413 PLOCAL_HANDLE pHandle;
414 REGISTRYFORMINFO rfi;
415 PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
416 PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
417
418 FIXME("AddForm(%p, %lu, %p)\n", hPrinter, Level, pForm);
419
420 // Check if this is a printer handle.
421 pHandle = (PLOCAL_HANDLE)hPrinter;
422 if (pHandle->HandleType != HandleType_Printer)
423 {
424 dwErrorCode = ERROR_INVALID_HANDLE;
425 goto Cleanup;
426 }
427
428 // Only support 1 & 2
429 if (Level < 1 || Level > 2)
430 {
431 // The caller supplied an invalid level.
432 dwErrorCode = ERROR_INVALID_LEVEL;
433 goto Cleanup;
434 }
435
436 pfil = FindForm( pfi1w->pName, NULL );
437 if ( pfil )
438 {
439 dwErrorCode = ERROR_FILE_EXISTS;
440 goto Cleanup;
441 }
442
443 dwErrorCode = RegQueryValueExW( hFormsKey, pfi1w->pName, NULL, NULL, NULL, &cbNeeded );
444 if ( dwErrorCode == ERROR_SUCCESS )
445 {
446 dwErrorCode = ERROR_FILE_EXISTS;
447 goto Cleanup;
448 }
449
450 if ( wcslen(pfi1w->pName) > FORMMAXNAMESIZE ) // Limit REG Name size.
451 {
452 dwErrorCode = ERROR_INVALID_PARAMETER;
453 goto Cleanup;
454 }
455
456 Size = sizeof(FORM_INFO_LIST) + ((MAX_PATH + 1) * sizeof(WCHAR));
457
458 pfil = DllAllocSplMem( Size );
459 if ( !pfil )
460 {
461 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
462 goto Cleanup;
463 }
464
465 pfil->Sig = FORMINFOSIG;
466 pfil->Index = _dwLastForm++;
467 pfil->pName = wcscpy( (PWSTR)(pfil+1), pfi1w->pName );
468 pfil->Flags = pfi1w->Flags;
469 pfil->Size = pfi1w->Size;
470 pfil->ImageableArea = pfi1w->ImageableArea;
471 pfil->StringType = STRING_NONE;
472
473 if ( Level > 1 )
474 {
475 pfil->pKeyword = pfi2w->pKeyword;
476 pfil->pMuiDll = pfi2w->pMuiDll;
477 pfil->pDisplayName = pfi2w->pDisplayName;
478 pfil->StringType = pfi2w->StringType;
479 pfil->dwResourceId = pfi2w->dwResourceId;
480 }
481
482 rfi.Size = pfil->Size;
483 rfi.ImageableArea = pfil->ImageableArea;
484 rfi.Index = pfil->Index;
485 rfi.Flags = pfil->Flags;
486
487 dwErrorCode = RegSetValueExW( hFormsKey, pfil->pName, 0, REG_BINARY, (PBYTE)&rfi, sizeof( rfi ) );
488
489 BroadcastChange(pHandle);
490
491 InsertTailList( &FormList, &pfil->List );
492
493 Cleanup:
494 SetLastError(dwErrorCode);
495 return (dwErrorCode == ERROR_SUCCESS);
496 }
497
498 BOOL WINAPI
LocalDeleteForm(HANDLE hPrinter,PWSTR pFormName)499 LocalDeleteForm(HANDLE hPrinter, PWSTR pFormName)
500 {
501 DWORD dwErrorCode, cbNeeded;
502 PFORM_INFO_LIST pfil;
503 REGISTRYFORMINFO rfi;
504 PLOCAL_HANDLE pHandle;
505
506 FIXME("DeleteForm(%p, %S)\n", hPrinter, pFormName);
507
508 // Check if this is a printer handle.
509 pHandle = (PLOCAL_HANDLE)hPrinter;
510 if (pHandle->HandleType != HandleType_Printer)
511 {
512 dwErrorCode = ERROR_INVALID_HANDLE;
513 goto Cleanup;
514 }
515
516 pfil = FindForm( pFormName, NULL );
517 if ( !pfil )
518 {
519 dwErrorCode = ERROR_INVALID_PARAMETER;
520 goto Cleanup;
521 }
522
523 dwErrorCode = RegQueryValueExW( hFormsKey, pFormName, NULL, NULL, (PBYTE)&rfi, &cbNeeded );
524 if ( dwErrorCode != ERROR_SUCCESS )
525 {
526 goto Cleanup;
527 }
528
529 dwErrorCode = RegDeleteValueW(hFormsKey, pFormName);
530 if ( dwErrorCode != ERROR_SUCCESS )
531 {
532 goto Cleanup;
533 }
534
535 RemoveEntryList(&pfil->List);
536
537 DllFreeSplMem(pfil);
538
539 BroadcastChange(pHandle);
540
541 dwErrorCode = ERROR_SUCCESS;
542
543 Cleanup:
544 SetLastError(dwErrorCode);
545 return (dwErrorCode == ERROR_SUCCESS);
546 }
547
548 BOOL WINAPI
LocalEnumForms(HANDLE hPrinter,DWORD Level,PBYTE pForm,DWORD cbBuf,PDWORD pcbNeeded,PDWORD pcReturned)549 LocalEnumForms(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
550 {
551 DWORD dwErrorCode;
552 PFORM_INFO_LIST pfil = NULL;
553 PBYTE pEnd = &pForm[cbBuf];
554 PLOCAL_HANDLE pHandle;
555 PLIST_ENTRY ListEntry;
556
557 FIXME("EnumForms(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
558
559 // Check if this is a printer handle.
560 pHandle = (PLOCAL_HANDLE)hPrinter;
561 if (pHandle->HandleType != HandleType_Printer)
562 {
563 dwErrorCode = ERROR_INVALID_HANDLE;
564 goto Cleanup;
565 }
566
567 // Only support 1 & 2
568 if (Level < 1 || Level > 2)
569 {
570 // The caller supplied an invalid level.
571 dwErrorCode = ERROR_INVALID_LEVEL;
572 goto Cleanup;
573 }
574
575 // Count the required buffer size.
576 *pcbNeeded = 0;
577
578 ListEntry = FormList.Flink;
579
580 if (IsListEmpty(ListEntry))
581 {
582 dwErrorCode = ERROR_INVALID_PARAMETER;
583 goto Cleanup;
584 }
585
586 while ( ListEntry != &FormList )
587 {
588 pfil = CONTAINING_RECORD(ListEntry, FORM_INFO_LIST, List);
589 ListEntry = ListEntry->Flink;
590
591 pfnGetFormLevels[Level](pfil, NULL, NULL, pcbNeeded);
592 }
593
594 // Check if the supplied buffer is large enough.
595 if (cbBuf < *pcbNeeded)
596 {
597 ERR("Insuffisient Buffer size\n");
598 dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
599 goto Cleanup;
600 }
601
602 // Copy over the information.
603 pEnd = &pForm[*pcbNeeded];
604
605 ListEntry = FormList.Flink;
606
607 while ( ListEntry != &FormList )
608 {
609 pfil = CONTAINING_RECORD(ListEntry, FORM_INFO_LIST, List);
610 ListEntry = ListEntry->Flink;
611
612 pfnGetFormLevels[Level](pfil, &pForm, &pEnd, NULL);
613 (*pcReturned)++;
614 }
615
616 dwErrorCode = ERROR_SUCCESS;
617
618 Cleanup:
619 SetLastError(dwErrorCode);
620 return (dwErrorCode == ERROR_SUCCESS);
621 }
622
623 BOOL WINAPI
LocalGetForm(HANDLE hPrinter,PWSTR pFormName,DWORD Level,PBYTE pForm,DWORD cbBuf,PDWORD pcbNeeded)624 LocalGetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded)
625 {
626 DWORD dwErrorCode;
627 PFORM_INFO_LIST pfil;
628 PBYTE pEnd = &pForm[cbBuf];
629 PLOCAL_HANDLE pHandle;
630
631 FIXME("GetForm(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded);
632
633 // Check if this is a printer handle.
634 pHandle = (PLOCAL_HANDLE)hPrinter;
635 if (pHandle->HandleType != HandleType_Printer)
636 {
637 dwErrorCode = ERROR_INVALID_HANDLE;
638 goto Cleanup;
639 }
640
641 // Only support 1 & 2
642 if (Level < 1 || Level > 2)
643 {
644 // The caller supplied an invalid level.
645 dwErrorCode = ERROR_INVALID_LEVEL;
646 goto Cleanup;
647 }
648
649 pfil = FindForm( pFormName, NULL );
650 if ( !pfil )
651 {
652 dwErrorCode = ERROR_INVALID_PARAMETER;
653 goto Cleanup;
654 }
655
656 // Count the required buffer size.
657 *pcbNeeded = 0;
658
659 pfnGetFormLevels[Level](pfil, NULL, NULL, pcbNeeded);
660
661 // Check if the supplied buffer is large enough.
662 if (cbBuf < *pcbNeeded)
663 {
664 ERR("Insuffisient Buffer size\n");
665 dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
666 goto Cleanup;
667 }
668
669 // Copy over the information.
670 pEnd = &pForm[*pcbNeeded];
671
672 pfnGetFormLevels[Level](pfil, &pForm, &pEnd, NULL);
673
674 dwErrorCode = ERROR_SUCCESS;
675
676 Cleanup:
677 SetLastError(dwErrorCode);
678 return (dwErrorCode == ERROR_SUCCESS);
679 }
680
681 BOOL WINAPI
LocalSetForm(HANDLE hPrinter,PWSTR pFormName,DWORD Level,PBYTE pForm)682 LocalSetForm(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm)
683 {
684 DWORD dwErrorCode, cbNeeded;
685 PFORM_INFO_LIST pfil;
686 REGISTRYFORMINFO rfi;
687 PLOCAL_HANDLE pHandle;
688 PFORM_INFO_1W pfi1w = (PFORM_INFO_1W)pForm;
689 PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm;
690
691 FIXME("SetFormW(%p, %S, %lu, %p)\n", hPrinter, pFormName, Level, pForm);
692
693 // Check if this is a printer handle.
694 pHandle = (PLOCAL_HANDLE)hPrinter;
695 if (pHandle->HandleType != HandleType_Printer)
696 {
697 dwErrorCode = ERROR_INVALID_HANDLE;
698 goto Cleanup;
699 }
700
701 // Only support 1 & 2
702 if (Level < 1 || Level > 2)
703 {
704 // The caller supplied an invalid level.
705 dwErrorCode = ERROR_INVALID_LEVEL;
706 goto Cleanup;
707 }
708
709 pfil = FindForm( pFormName, NULL );
710 if ( !pfil )
711 {
712 dwErrorCode = ERROR_INVALID_PARAMETER;
713 goto Cleanup;
714 }
715
716 dwErrorCode = RegQueryValueExW( hFormsKey, pFormName, NULL, NULL, (PBYTE)&rfi, &cbNeeded) ;
717 if ( dwErrorCode != ERROR_SUCCESS )
718 {
719 goto Cleanup;
720 }
721
722 pfil->Flags = pfi1w->Flags;
723 pfil->Size = pfi1w->Size;
724 pfil->ImageableArea = pfi1w->ImageableArea;
725
726 if ( Level > 1 )
727 {
728 pfil->pKeyword = pfi2w->pKeyword;
729 pfil->pMuiDll = pfi2w->pMuiDll;
730 pfil->pDisplayName = pfi2w->pDisplayName;
731 pfil->StringType = pfi2w->StringType;
732 pfil->dwResourceId = pfi2w->dwResourceId;
733 }
734
735 rfi.Size = pfil->Size;
736 rfi.ImageableArea = pfil->ImageableArea;
737 rfi.Flags = pfil->Flags;
738
739 dwErrorCode = RegSetValueExW( hFormsKey, pfil->pName, 0, REG_BINARY, (PBYTE)&rfi, sizeof( rfi ) );
740
741 BroadcastChange(pHandle);
742
743 Cleanup:
744 SetLastError(dwErrorCode);
745 return (dwErrorCode == ERROR_SUCCESS);
746 }
747