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 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 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 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 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 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 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 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 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 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