1 /* 2 * PROJECT: ReactOS Local Spooler 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Functions for printer driver information 5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org) 6 * Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 7 */ 8 9 #include "precomp.h" 10 #include <strsafe.h> 11 12 typedef struct { 13 WCHAR src[MAX_PATH+MAX_PATH]; 14 WCHAR dst[MAX_PATH+MAX_PATH]; 15 DWORD srclen; 16 DWORD dstlen; 17 DWORD copyflags; 18 BOOL lazy; 19 } apd_data_t; 20 21 static const WCHAR backslashW[] = {'\\',0}; 22 static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0}; 23 static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0}; 24 static const WCHAR data_fileW[] = {'D','a','t','a',' ','F','i','l','e',0}; 25 static const WCHAR dependent_filesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0}; 26 static const WCHAR driverW[] = {'D','r','i','v','e','r',0}; 27 static const WCHAR emptyW[] = {0}; 28 static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\', 29 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 30 'c','o','n','t','r','o','l','\\', 31 'P','r','i','n','t','\\', 32 'E','n','v','i','r','o','n','m','e','n','t','s','\\', 33 '%','s','\\','D','r','i','v','e','r','s','%','s',0 }; 34 static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0}; 35 static const WCHAR previous_namesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0}; 36 37 static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0}; 38 39 static const WCHAR spoolW[] = {'\\','s','p','o','o','l',0}; 40 static const WCHAR driversW[] = {'\\','d','r','i','v','e','r','s','\\',0}; 41 static const WCHAR ia64_envnameW[] = {'W','i','n','d','o','w','s',' ','I','A','6','4',0}; 42 static const WCHAR ia64_subdirW[] = {'i','a','6','4',0}; 43 static const WCHAR version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0}; 44 static const WCHAR version3_subdirW[] = {'\\','3',0}; 45 static const WCHAR version0_regpathW[] = {'\\','V','e','r','s','i','o','n','-','0',0}; 46 static const WCHAR version0_subdirW[] = {'\\','0',0}; 47 static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0}; 48 static const WCHAR x64_envnameW[] = {'W','i','n','d','o','w','s',' ','x','6','4',0}; 49 static const WCHAR x64_subdirW[] = {'x','6','4',0}; 50 static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0}; 51 static const WCHAR x86_subdirW[] = {'w','3','2','x','8','6',0}; 52 static const WCHAR win40_envnameW[] = {'W','i','n','d','o','w','s',' ','4','.','0',0}; 53 static const WCHAR win40_subdirW[] = {'w','i','n','4','0',0}; 54 55 static PRINTENV_T env_ia64 = {ia64_envnameW, ia64_subdirW, 3, version3_regpathW, version3_subdirW}; 56 57 static PRINTENV_T env_x86 = {x86_envnameW, x86_subdirW, 3, version3_regpathW, version3_subdirW}; 58 59 static PRINTENV_T env_x64 = {x64_envnameW, x64_subdirW, 3, version3_regpathW, version3_subdirW}; 60 61 static PRINTENV_T env_win40 = {win40_envnameW, win40_subdirW, 0, version0_regpathW, version0_subdirW}; 62 63 static PPRINTENV_T all_printenv[] = {&env_x86, &env_x64, &env_ia64, &env_win40}; 64 65 static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W), 66 sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W), 67 sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W), 68 0, sizeof(DRIVER_INFO_8W)}; 69 70 static WCHAR wszScratchPad[MAX_PATH] = L""; 71 72 static WCHAR wszLocalSplFile[MAX_PATH] = L""; 73 static WCHAR wszPrintUiFile[MAX_PATH] = L""; 74 static WCHAR wszDriverPath[MAX_PATH] = L""; 75 76 BOOL 77 InitializePrinterDrivers(VOID) 78 { 79 WCHAR szSysDir[MAX_PATH]; 80 DWORD cbBuf; 81 82 if (wszLocalSplFile[0] && wszPrintUiFile[0]) 83 return TRUE; 84 85 if (!GetSystemDirectoryW(szSysDir, _countof(szSysDir))) 86 { 87 ERR("GetSystemDirectoryW failed\n"); 88 return FALSE; 89 } 90 91 StringCbCopyW(wszLocalSplFile, sizeof(wszLocalSplFile), szSysDir); 92 StringCbCatW(wszLocalSplFile, sizeof(wszLocalSplFile), L"\\localspl.dll"); 93 94 StringCbCopyW(wszPrintUiFile, sizeof(wszPrintUiFile), szSysDir); 95 StringCbCatW(wszPrintUiFile, sizeof(wszPrintUiFile), L"\\printui.dll"); 96 97 if (!LocalGetPrinterDriverDirectory( NULL, (PWSTR)wszCurrentEnvironment, 1, (PBYTE)szSysDir, cbBuf, &cbBuf ) ) 98 { 99 ERR("LocalGetPrinterDriverDirectory failed\n"); 100 return FALSE; 101 } 102 103 StringCbCopyW(wszDriverPath, sizeof(wszDriverPath), szSysDir); 104 StringCbCatW(wszDriverPath, sizeof(wszDriverPath), version3_subdirW); 105 StringCbCatW(wszDriverPath, sizeof(wszDriverPath), backslashW); 106 107 // HAX! need to get it from the Reg Key L"Driver"! 108 StringCbCatW(wszDriverPath, sizeof(wszDriverPath), L"UniDrv.dll"); 109 110 FIXME("DriverPath : %S\n",wszDriverPath); 111 112 return TRUE; 113 } 114 115 // Local Constants 116 static DWORD dwDriverInfo1Offsets[] = { 117 FIELD_OFFSET(DRIVER_INFO_1W, pName), 118 MAXDWORD 119 }; 120 121 static DWORD dwDriverInfo2Offsets[] = { 122 FIELD_OFFSET(DRIVER_INFO_2W, pName), 123 FIELD_OFFSET(DRIVER_INFO_2W, pEnvironment), 124 FIELD_OFFSET(DRIVER_INFO_2W, pDriverPath), 125 FIELD_OFFSET(DRIVER_INFO_2W, pDataFile), 126 FIELD_OFFSET(DRIVER_INFO_2W, pConfigFile), 127 MAXDWORD 128 }; 129 130 static DWORD dwDriverInfo3Offsets[] = { 131 FIELD_OFFSET(DRIVER_INFO_3W, pName), 132 FIELD_OFFSET(DRIVER_INFO_3W, pEnvironment), 133 FIELD_OFFSET(DRIVER_INFO_3W, pDriverPath), 134 FIELD_OFFSET(DRIVER_INFO_3W, pDataFile), 135 FIELD_OFFSET(DRIVER_INFO_3W, pConfigFile), 136 FIELD_OFFSET(DRIVER_INFO_3W, pHelpFile), 137 FIELD_OFFSET(DRIVER_INFO_3W, pDependentFiles), 138 FIELD_OFFSET(DRIVER_INFO_3W, pMonitorName), 139 FIELD_OFFSET(DRIVER_INFO_3W, pDefaultDataType), 140 MAXDWORD 141 }; 142 143 static DWORD dwDriverInfo4Offsets[] = { 144 FIELD_OFFSET(DRIVER_INFO_4W, pName), 145 FIELD_OFFSET(DRIVER_INFO_4W, pEnvironment), 146 FIELD_OFFSET(DRIVER_INFO_4W, pDriverPath), 147 FIELD_OFFSET(DRIVER_INFO_4W, pDataFile), 148 FIELD_OFFSET(DRIVER_INFO_4W, pConfigFile), 149 FIELD_OFFSET(DRIVER_INFO_4W, pHelpFile), 150 FIELD_OFFSET(DRIVER_INFO_4W, pDependentFiles), 151 FIELD_OFFSET(DRIVER_INFO_4W, pMonitorName), 152 FIELD_OFFSET(DRIVER_INFO_4W, pDefaultDataType), 153 FIELD_OFFSET(DRIVER_INFO_4W, pszzPreviousNames), 154 MAXDWORD 155 }; 156 157 static DWORD dwDriverInfo5Offsets[] = { 158 FIELD_OFFSET(DRIVER_INFO_5W, pName), 159 FIELD_OFFSET(DRIVER_INFO_5W, pEnvironment), 160 FIELD_OFFSET(DRIVER_INFO_5W, pDriverPath), 161 FIELD_OFFSET(DRIVER_INFO_5W, pDataFile), 162 FIELD_OFFSET(DRIVER_INFO_5W, pConfigFile), 163 MAXDWORD 164 }; 165 166 static DWORD dwDriverInfo6Offsets[] = { 167 FIELD_OFFSET(DRIVER_INFO_6W, pName), 168 FIELD_OFFSET(DRIVER_INFO_6W, pEnvironment), 169 FIELD_OFFSET(DRIVER_INFO_6W, pDriverPath), 170 FIELD_OFFSET(DRIVER_INFO_6W, pDataFile), 171 FIELD_OFFSET(DRIVER_INFO_6W, pConfigFile), 172 FIELD_OFFSET(DRIVER_INFO_6W, pHelpFile), 173 FIELD_OFFSET(DRIVER_INFO_6W, pDependentFiles), 174 FIELD_OFFSET(DRIVER_INFO_6W, pMonitorName), 175 FIELD_OFFSET(DRIVER_INFO_6W, pDefaultDataType), 176 FIELD_OFFSET(DRIVER_INFO_6W, pszzPreviousNames), 177 FIELD_OFFSET(DRIVER_INFO_6W, pszMfgName), 178 FIELD_OFFSET(DRIVER_INFO_6W, pszOEMUrl), 179 FIELD_OFFSET(DRIVER_INFO_6W, pszHardwareID), 180 FIELD_OFFSET(DRIVER_INFO_6W, pszProvider), 181 MAXDWORD 182 }; 183 184 static DWORD dwDriverInfo8Offsets[] = { 185 FIELD_OFFSET(DRIVER_INFO_8W, pName), 186 FIELD_OFFSET(DRIVER_INFO_8W, pEnvironment), 187 FIELD_OFFSET(DRIVER_INFO_8W, pDriverPath), 188 FIELD_OFFSET(DRIVER_INFO_8W, pDataFile), 189 FIELD_OFFSET(DRIVER_INFO_8W, pConfigFile), 190 FIELD_OFFSET(DRIVER_INFO_8W, pHelpFile), 191 FIELD_OFFSET(DRIVER_INFO_8W, pDependentFiles), 192 FIELD_OFFSET(DRIVER_INFO_8W, pMonitorName), 193 FIELD_OFFSET(DRIVER_INFO_8W, pDefaultDataType), 194 FIELD_OFFSET(DRIVER_INFO_8W, pszzPreviousNames), 195 FIELD_OFFSET(DRIVER_INFO_8W, pszMfgName), 196 FIELD_OFFSET(DRIVER_INFO_8W, pszOEMUrl), 197 FIELD_OFFSET(DRIVER_INFO_8W, pszHardwareID), 198 FIELD_OFFSET(DRIVER_INFO_8W, pszProvider), 199 FIELD_OFFSET(DRIVER_INFO_8W, pszPrintProcessor), 200 FIELD_OFFSET(DRIVER_INFO_8W, pszVendorSetup), 201 FIELD_OFFSET(DRIVER_INFO_8W, pszzColorProfiles), 202 FIELD_OFFSET(DRIVER_INFO_8W, pszInfPath), 203 FIELD_OFFSET(DRIVER_INFO_8W, pszzCoreDriverDependencies), 204 MAXDWORD 205 }; 206 207 static void 208 ToMultiSz(LPWSTR pString) 209 { 210 while (*pString) 211 { 212 if (*pString == '|') 213 *pString = '\0'; 214 pString++; 215 } 216 } 217 218 static void 219 _LocalGetPrinterDriverLevel1(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_1W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 220 { 221 DWORD n; 222 PCWSTR pwszStrings[1]; 223 224 /* This value is only here to send something, I have not verified if it is actually correct */ 225 pwszStrings[0] = pPrinter->pwszPrinterDriver; 226 227 // Calculate the string lengths. 228 if (!ppDriverInfo) 229 { 230 for (n = 0; n < _countof(pwszStrings); ++n) 231 { 232 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 233 } 234 235 *pcbNeeded += sizeof(DRIVER_INFO_1W); 236 return; 237 } 238 239 // Finally copy the structure and advance to the next one in the output buffer. 240 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo1Offsets, *ppDriverInfoEnd); 241 (*ppDriverInfo)++; 242 } 243 244 static void 245 _LocalGetPrinterDriverLevel2(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_2W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 246 { 247 DWORD n; 248 PCWSTR pwszStrings[5]; 249 250 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName 251 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment 252 pwszStrings[2] = wszDriverPath; // pDriverPath 253 pwszStrings[3] = wszLocalSplFile; // pDataFile 254 pwszStrings[4] = wszPrintUiFile; // pConfigFile 255 256 // Calculate the string lengths. 257 if (!ppDriverInfo) 258 { 259 for (n = 0; n < _countof(pwszStrings); ++n) 260 { 261 if (pwszStrings[n]) 262 { 263 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 264 } 265 } 266 267 *pcbNeeded += sizeof(DRIVER_INFO_2W); 268 return; 269 } 270 271 (*ppDriverInfo)->cVersion = 3; 272 273 // Finally copy the structure and advance to the next one in the output buffer. 274 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo2Offsets, *ppDriverInfoEnd); 275 (*ppDriverInfo)++; 276 } 277 278 static void 279 _LocalGetPrinterDriverLevel3(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_3W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 280 { 281 DWORD n; 282 PCWSTR pwszStrings[9]; 283 284 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName 285 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment 286 pwszStrings[2] = wszDriverPath; // pDriverPath 287 pwszStrings[3] = wszLocalSplFile; // pDataFile 288 pwszStrings[4] = wszPrintUiFile; // pConfigFile 289 pwszStrings[5] = L""; // pHelpFile 290 pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator! 291 pwszStrings[7] = NULL; 292 if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor) 293 { 294 pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName; 295 } 296 pwszStrings[8] = pPrinter->pwszDefaultDatatype; 297 298 299 // Calculate the string lengths. 300 if (!ppDriverInfo) 301 { 302 for (n = 0; n < _countof(pwszStrings); ++n) 303 { 304 if (pwszStrings[n]) 305 { 306 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 307 } 308 } 309 310 *pcbNeeded += sizeof(DRIVER_INFO_3W); 311 return; 312 } 313 314 (*ppDriverInfo)->cVersion = 3; 315 316 // Finally copy the structure and advance to the next one in the output buffer. 317 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo3Offsets, *ppDriverInfoEnd); 318 ToMultiSz((*ppDriverInfo)->pDependentFiles); 319 (*ppDriverInfo)++; 320 } 321 322 static void 323 _LocalGetPrinterDriverLevel4(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_4W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 324 { 325 DWORD n; 326 PCWSTR pwszStrings[10]; 327 328 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName 329 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment 330 pwszStrings[2] = wszDriverPath; // pDriverPath 331 pwszStrings[3] = wszLocalSplFile; // pDataFile 332 pwszStrings[4] = wszPrintUiFile; // pConfigFile 333 pwszStrings[5] = L""; // pHelpFile 334 pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator! 335 pwszStrings[7] = NULL; 336 if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor) 337 { 338 pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName; 339 } 340 pwszStrings[8] = pPrinter->pwszDefaultDatatype; 341 pwszStrings[9] = NULL; // pszzPreviousNames 342 343 // Calculate the string lengths. 344 if (!ppDriverInfo) 345 { 346 for (n = 0; n < _countof(pwszStrings); ++n) 347 { 348 if (pwszStrings[n]) 349 { 350 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 351 } 352 } 353 354 *pcbNeeded += sizeof(DRIVER_INFO_4W); 355 return; 356 } 357 358 (*ppDriverInfo)->cVersion = 3; 359 360 // Finally copy the structure and advance to the next one in the output buffer. 361 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo4Offsets, *ppDriverInfoEnd); 362 ToMultiSz((*ppDriverInfo)->pDependentFiles); 363 (*ppDriverInfo)++; 364 } 365 366 static void 367 _LocalGetPrinterDriverLevel5(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_5W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 368 { 369 DWORD n; 370 PCWSTR pwszStrings[5]; 371 372 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName 373 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment 374 pwszStrings[2] = wszDriverPath; // pDriverPath UniDrv.dll 375 pwszStrings[3] = wszLocalSplFile; // pDataFile.ppd 376 pwszStrings[4] = wszPrintUiFile; // pConfigFile UniDrvUI.dll 377 378 // Calculate the string lengths. 379 if (!ppDriverInfo) 380 { 381 for (n = 0; n < _countof(pwszStrings); ++n) 382 { 383 if (pwszStrings[n]) 384 { 385 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 386 } 387 } 388 389 *pcbNeeded += sizeof(DRIVER_INFO_5W); 390 return; 391 } 392 393 (*ppDriverInfo)->cVersion = 3; 394 // Driver attributes, like UMPD/KMPD. 395 (*ppDriverInfo)->dwDriverAttributes = 0; // UMPD/KMPD, So where are they? 396 // Number of times the configuration file for this driver has been upgraded or downgraded since the last spooler restart. 397 (*ppDriverInfo)->dwConfigVersion = 1; 398 // Number of times the driver file for this driver has been upgraded or downgraded since the last spooler restart. 399 (*ppDriverInfo)->dwDriverVersion = 1; 400 401 // Finally copy the structure and advance to the next one in the output buffer. 402 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo5Offsets, *ppDriverInfoEnd); 403 (*ppDriverInfo)++; 404 } 405 406 407 static void 408 _LocalGetPrinterDriverLevel6(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_6W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 409 { 410 DWORD n; 411 PCWSTR pwszStrings[14]; 412 413 StringCbCopyW(wszScratchPad, sizeof(wszPrintProviderInfo[1]), wszPrintProviderInfo[1]); // Provider Name 414 415 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName 416 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment 417 pwszStrings[2] = wszDriverPath; // pDriverPath 418 pwszStrings[3] = wszLocalSplFile; // pDataFile 419 pwszStrings[4] = wszPrintUiFile; // pConfigFile 420 pwszStrings[5] = L""; // pHelpFile 421 pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator! 422 pwszStrings[7] = NULL; 423 if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor) 424 { 425 pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName; 426 } 427 pwszStrings[8] = pPrinter->pwszDefaultDatatype; 428 pwszStrings[9] = NULL; // pszzPreviousNames 429 pwszStrings[10] = NULL; // pszMfgName 430 pwszStrings[11] = NULL; // pszOEMUrl 431 pwszStrings[12] = NULL; // pszHardwareID 432 pwszStrings[13] = wszScratchPad; 433 434 // Calculate the string lengths. 435 if (!ppDriverInfo) 436 { 437 for (n = 0; n < _countof(pwszStrings); ++n) 438 { 439 if (pwszStrings[n]) 440 { 441 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 442 } 443 } 444 445 *pcbNeeded += sizeof(DRIVER_INFO_6W); 446 return; 447 } 448 449 (*ppDriverInfo)->cVersion = 3; 450 451 // Finally copy the structure and advance to the next one in the output buffer. 452 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo6Offsets, *ppDriverInfoEnd); 453 ToMultiSz((*ppDriverInfo)->pDependentFiles); 454 (*ppDriverInfo)++; 455 } 456 457 static void 458 _LocalGetPrinterDriverLevel8(PLOCAL_PRINTER pPrinter, PDRIVER_INFO_8W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded) 459 { 460 DWORD n; 461 PCWSTR pwszStrings[19]; 462 463 StringCbCopyW(wszScratchPad, sizeof(wszPrintProviderInfo[1]), wszPrintProviderInfo[1]); // Provider Name 464 465 pwszStrings[0] = pPrinter->pwszPrinterDriver; // pName 466 pwszStrings[1] = wszCurrentEnvironment; // pEnvironment 467 pwszStrings[2] = wszDriverPath; // pDriverPath 468 pwszStrings[3] = wszLocalSplFile; // pDataFile 469 pwszStrings[4] = wszPrintUiFile; // pConfigFile 470 pwszStrings[5] = L""; // pHelpFile 471 pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator! 472 pwszStrings[7] = NULL; 473 if (pPrinter->pPort && pPrinter->pPort->pPrintMonitor) 474 { 475 pwszStrings[7] = pPrinter->pPort->pPrintMonitor->pwszName; 476 } 477 pwszStrings[8] = pPrinter->pwszDefaultDatatype; 478 pwszStrings[9] = NULL; // pszzPreviousNames 479 pwszStrings[10] = NULL; // pszMfgName 480 pwszStrings[11] = NULL; // pszOEMUrl 481 pwszStrings[12] = NULL; // pszHardwareID 482 pwszStrings[13] = wszScratchPad; 483 pwszStrings[14] = NULL; 484 if ( pPrinter->pPrintProcessor ) 485 { 486 pwszStrings[14] = pPrinter->pPrintProcessor->pwszName; 487 } 488 pwszStrings[15] = NULL; // pszVendorSetup 489 pwszStrings[16] = NULL; // pszzColorProfiles 490 pwszStrings[17] = NULL; // pszInfPath 491 pwszStrings[18] = NULL; // pszzCoreDriverDependencies 492 493 // Calculate the string lengths. 494 if (!ppDriverInfo) 495 { 496 for (n = 0; n < _countof(pwszStrings); ++n) 497 { 498 if (pwszStrings[n]) 499 { 500 *pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR); 501 } 502 } 503 504 *pcbNeeded += sizeof(DRIVER_INFO_8W); 505 return; 506 } 507 508 (*ppDriverInfo)->cVersion = 3; 509 510 // Finally copy the structure and advance to the next one in the output buffer. 511 *ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo8Offsets, *ppDriverInfoEnd); 512 ToMultiSz((*ppDriverInfo)->pDependentFiles); 513 (*ppDriverInfo)++; 514 } 515 516 typedef void (*PLocalPrinterDriverLevelFunc)(PLOCAL_PRINTER, PVOID, PBYTE*, PDWORD); 517 518 static const PLocalPrinterDriverLevelFunc pfnPrinterDriverLevels[] = { 519 NULL, 520 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel1, 521 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel2, 522 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel3, 523 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel4, 524 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel5, 525 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel6, 526 NULL, 527 (PLocalPrinterDriverLevelFunc)&_LocalGetPrinterDriverLevel8 528 }; 529 530 BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded) 531 { 532 DWORD dwErrorCode; 533 PBYTE pEnd = &pDriverInfo[cbBuf]; 534 PLOCAL_HANDLE pHandle; 535 PLOCAL_PRINTER_HANDLE pPrinterHandle; 536 537 TRACE("LocalGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); 538 539 // Check if this is a printer handle. 540 pHandle = (PLOCAL_HANDLE)hPrinter; 541 if (pHandle->HandleType != HandleType_Printer) 542 { 543 dwErrorCode = ERROR_INVALID_HANDLE; 544 goto Cleanup; 545 } 546 547 pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; 548 549 // Only support 8 levels and not 7 550 if (Level < 1 || Level == 7 || Level > 8) 551 { 552 // The caller supplied an invalid level. 553 dwErrorCode = ERROR_INVALID_LEVEL; 554 goto Cleanup; 555 } 556 557 // Count the required buffer size. 558 *pcbNeeded = 0; 559 560 pfnPrinterDriverLevels[Level](pPrinterHandle->pPrinter, NULL, NULL, pcbNeeded); 561 562 // Check if the supplied buffer is large enough. 563 if (cbBuf < *pcbNeeded) 564 { 565 ERR("Insuffisient Buffer size\n"); 566 dwErrorCode = ERROR_INSUFFICIENT_BUFFER; 567 goto Cleanup; 568 } 569 570 // Copy over the information. 571 pEnd = &pDriverInfo[*pcbNeeded]; 572 573 pfnPrinterDriverLevels[Level](pPrinterHandle->pPrinter, &pDriverInfo, &pEnd, NULL); 574 575 dwErrorCode = ERROR_SUCCESS; 576 577 Cleanup: 578 SetLastError(dwErrorCode); 579 return (dwErrorCode == ERROR_SUCCESS); 580 } 581 582 BOOL WINAPI LocalGetPrinterDriverEx( 583 HANDLE hPrinter, 584 LPWSTR pEnvironment, 585 DWORD Level, 586 LPBYTE pDriverInfo, 587 DWORD cbBuf, 588 LPDWORD pcbNeeded, 589 DWORD dwClientMajorVersion, 590 DWORD dwClientMinorVersion, 591 PDWORD pdwServerMajorVersion, 592 PDWORD pdwServerMinorVersion ) 593 { 594 FIXME("LocalGetPrinterDriverEx(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion); 595 //// HACK-plement 596 return LocalGetPrinterDriver( hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded ); 597 } 598 599 BOOL WINAPI 600 LocalEnumPrinterDrivers(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) 601 { 602 DWORD dwErrorCode; 603 PSKIPLIST_NODE pNode; 604 PBYTE pEnd; 605 PLOCAL_PRINTER pPrinter; 606 607 FIXME("LocalEnumPrinterDrivers(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned); 608 609 // Only support 8 levels and not 7 610 if (Level < 1 || Level == 7 || Level > 8) 611 { 612 // The caller supplied an invalid level. 613 dwErrorCode = ERROR_INVALID_LEVEL; 614 goto Cleanup; 615 } 616 617 // Count the required buffer size. 618 *pcbNeeded = 0; 619 620 // Count the required buffer size and the number of printers. 621 for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0]) 622 { 623 pPrinter = (PLOCAL_PRINTER)pNode->Element; 624 625 pfnPrinterDriverLevels[Level](pPrinter, NULL, NULL, pcbNeeded); 626 } 627 628 // Check if the supplied buffer is large enough. 629 if (cbBuf < *pcbNeeded) 630 { 631 dwErrorCode = ERROR_INSUFFICIENT_BUFFER; 632 goto Cleanup; 633 } 634 635 // Copy over the Printer information. 636 pEnd = &pDriverInfo[*pcbNeeded]; 637 638 for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0]) 639 { 640 pPrinter = (PLOCAL_PRINTER)pNode->Element; 641 642 pfnPrinterDriverLevels[Level](pPrinter, &pDriverInfo, &pEnd, NULL); 643 (*pcReturned)++; 644 } 645 646 dwErrorCode = ERROR_SUCCESS; 647 648 Cleanup: 649 SetLastError(dwErrorCode); 650 return (dwErrorCode == ERROR_SUCCESS); 651 } 652 653 /****************************************************************** 654 * Return the number of bytes for an multi_sz string. 655 * The result includes all \0s 656 * (specifically the extra \0, that is needed as multi_sz terminator). 657 */ 658 static int multi_sz_lenW(const WCHAR *str) 659 { 660 const WCHAR *ptr = str; 661 if (!str) return 0; 662 do 663 { 664 ptr += lstrlenW(ptr) + 1; 665 } while (*ptr); 666 667 return (ptr - str + 1) * sizeof(WCHAR); 668 } 669 670 671 /****************************************************************** 672 * validate_envW [internal] 673 * 674 * validate the user-supplied printing-environment 675 * 676 * PARAMS 677 * env [I] PTR to Environment-String or NULL 678 * 679 * RETURNS 680 * Success: PTR to printenv_t 681 * Failure: NULL and ERROR_INVALID_ENVIRONMENT 682 * 683 * NOTES 684 * An empty string is handled the same way as NULL. 685 * 686 */ 687 PPRINTENV_T validate_envW(LPCWSTR env) 688 { 689 PPRINTENV_T result = NULL; 690 unsigned int i; 691 692 TRACE("(%s)\n", debugstr_w(env)); 693 if (env && env[0]) 694 { 695 for (i = 0; i < ARRAYSIZE(all_printenv); i++) 696 { 697 if (lstrcmpiW(env, all_printenv[i]->envname) == 0) 698 { 699 result = all_printenv[i]; 700 break; 701 } 702 } 703 if (result == NULL) 704 { 705 FIXME("unsupported Environment: %s\n", debugstr_w(env)); 706 SetLastError(ERROR_INVALID_ENVIRONMENT); 707 } 708 /* on win9x, only "Windows 4.0" is allowed, but we ignore this */ 709 } 710 else 711 { 712 result = (GetVersion() & 0x80000000) ? &env_win40 : &env_x86; 713 } 714 715 TRACE("=> using %p: %s\n", result, debugstr_w(result ? result->envname : NULL)); 716 return result; 717 } 718 719 /***************************************************************************** 720 * open_driver_reg [internal] 721 * 722 * opens the registry for the printer drivers depending on the given input 723 * variable pEnvironment 724 * 725 * RETURNS: 726 * Success: the opened hkey 727 * Failure: NULL 728 */ 729 HKEY open_driver_reg(LPCWSTR pEnvironment) 730 { 731 HKEY retval = NULL; 732 LPWSTR buffer; 733 const PRINTENV_T * env; 734 735 TRACE("(%s)\n", debugstr_w(pEnvironment)); 736 737 env = validate_envW(pEnvironment); 738 if (!env) return NULL; 739 740 buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(fmt_driversW) + 741 (lstrlenW(env->envname) + lstrlenW(env->versionregpath)) * sizeof(WCHAR)); 742 743 if (buffer) 744 { 745 wsprintfW(buffer, fmt_driversW, env->envname, env->versionregpath); 746 RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval); 747 HeapFree(GetProcessHeap(), 0, buffer); 748 } 749 return retval; 750 } 751 752 753 /****************************************************************************** 754 * LocalGetPrintProcessorDirectory [exported through PRINTPROVIDOR] 755 * 756 * Return the PATH for the Print-Processors 757 * 758 * PARAMS 759 * pName [I] Servername or NULL (this computer) 760 * pEnvironment [I] Printing-Environment or NULL (Default) 761 * level [I] Structure-Level (must be 1) 762 * pPPInfo [O] PTR to Buffer that receives the Result 763 * cbBuf [I] Size of Buffer at pPPInfo 764 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPPInfo 765 * 766 * RETURNS 767 * Success: TRUE 768 * Failure: FALSE and in pcbNeeded the Bytes required for pPPInfo, if cbBuf is too small 769 * 770 * Native Values returned in pPPInfo on Success for this computer: 771 *| NT(Windows x64): "%winsysdir%\\spool\\PRTPROCS\\x64" 772 *| NT(Windows NT x86): "%winsysdir%\\spool\\PRTPROCS\\w32x86" 773 *| NT(Windows 4.0): "%winsysdir%\\spool\\PRTPROCS\\win40" 774 * 775 * "%winsysdir%" is the Value from GetSystemDirectoryW() 776 * 777 */ 778 BOOL WINAPI LocalGetPrinterDriverDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded) 779 { 780 DWORD needed; 781 const PRINTENV_T * env = NULL; 782 WCHAR * const dir = (WCHAR *)pDriverDirectory; 783 784 FIXME("LocalGetPrinterDriverDirectory(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded); 785 786 if (pName != NULL && pName[0]) 787 { 788 FIXME("server %s not supported\n", debugstr_w(pName)); 789 SetLastError(ERROR_INVALID_PARAMETER); 790 return FALSE; 791 } 792 793 env = validate_envW(pEnvironment); 794 if (!env) return FALSE; /* pEnvironment invalid or unsupported */ 795 796 /* GetSystemDirectoryW returns number of WCHAR including the '\0' */ 797 needed = GetSystemDirectoryW(NULL, 0); 798 /* add the Size for the Subdirectories */ 799 needed += lstrlenW(spoolW); 800 needed += lstrlenW(driversW); 801 needed += lstrlenW(env->subdir); 802 needed *= sizeof(WCHAR); /* return-value is size in Bytes */ 803 804 *pcbNeeded = needed; 805 806 if (needed > cbBuf) 807 { 808 SetLastError(ERROR_INSUFFICIENT_BUFFER); 809 return FALSE; 810 } 811 812 if (dir == NULL) 813 { 814 /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */ 815 SetLastError(ERROR_INVALID_USER_BUFFER); 816 return FALSE; 817 } 818 819 GetSystemDirectoryW( dir, cbBuf / sizeof(WCHAR) ); 820 /* add the Subdirectories */ 821 lstrcatW( dir, spoolW ); 822 CreateDirectoryW( dir, NULL ); 823 lstrcatW( dir, driversW ); 824 CreateDirectoryW( dir, NULL ); 825 lstrcatW( dir, env->subdir ); 826 CreateDirectoryW( dir, NULL ); 827 828 FIXME( "=> %s\n", debugstr_w( dir ) ); 829 return TRUE; 830 } 831 832 /****************************************************************** 833 * apd_copyfile [internal] 834 * 835 * Copy a file from the driverdirectory to the versioned directory 836 * 837 * RETURNS 838 * Success: TRUE 839 * Failure: FALSE 840 * 841 */ 842 static BOOL apd_copyfile( WCHAR *pathname, WCHAR *file_part, apd_data_t *apd ) 843 { 844 WCHAR *srcname; 845 BOOL res; 846 847 apd->src[apd->srclen] = '\0'; 848 apd->dst[apd->dstlen] = '\0'; 849 850 if (!pathname || !pathname[0]) { 851 /* nothing to copy */ 852 return TRUE; 853 } 854 855 if (apd->copyflags & APD_COPY_FROM_DIRECTORY) 856 srcname = pathname; 857 else 858 { 859 srcname = apd->src; 860 lstrcatW( srcname, file_part ); 861 } 862 lstrcatW( apd->dst, file_part ); 863 864 FIXME("%s => %s\n", debugstr_w(srcname), debugstr_w(apd->dst)); 865 866 /* FIXME: handle APD_COPY_NEW_FILES */ 867 res = CopyFileW(srcname, apd->dst, FALSE); 868 FIXME("got %d with %u\n", res, GetLastError()); 869 870 return apd->lazy || res; 871 } 872 873 /****************************************************************** 874 * driver_load [internal] 875 * 876 * load a driver user interface dll 877 * 878 * On failure, NULL is returned 879 * 880 */ 881 882 static HMODULE driver_load(const PRINTENV_T * env, LPWSTR dllname) 883 { 884 WCHAR fullname[MAX_PATH]; 885 HMODULE hui; 886 DWORD len; 887 888 FIXME("(%p, %s)\n", env, debugstr_w(dllname)); 889 890 /* build the driverdir */ 891 len = sizeof(fullname) - (lstrlenW(env->versionsubdir) + 1 + lstrlenW(dllname) + 1) * sizeof(WCHAR); 892 893 if (!LocalGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, (LPBYTE) fullname, len, &len)) 894 { 895 /* Should never fail */ 896 SetLastError(ERROR_BUFFER_OVERFLOW); 897 return NULL; 898 } 899 900 lstrcatW(fullname, env->versionsubdir); 901 lstrcatW(fullname, backslashW); 902 lstrcatW(fullname, dllname); 903 904 hui = LoadLibraryW(fullname); 905 FIXME("%p: LoadLibrary(%s) %d\n", hui, debugstr_w(fullname), GetLastError()); 906 907 return hui; 908 } 909 910 static inline WCHAR *get_file_part( WCHAR *name ) 911 { 912 WCHAR *ptr = wcsrchr( name, '\\' ); 913 if (ptr) return ptr + 1; 914 return name; 915 } 916 917 /****************************************************************************** 918 * myAddPrinterDriverEx [internal] 919 * 920 * Install a Printer Driver with the Option to upgrade / downgrade the Files 921 * and a special mode with lazy error checking. 922 * 923 */ 924 BOOL myAddPrinterDriverEx(DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags, BOOL lazy) 925 { 926 const PRINTENV_T *env; 927 apd_data_t apd; 928 DRIVER_INFO_8W di; 929 BOOL (WINAPI *pDrvDriverEvent)(DWORD, DWORD, LPBYTE, LPARAM); 930 HMODULE hui; 931 WCHAR *file; 932 HKEY hroot; 933 HKEY hdrv; 934 DWORD disposition; 935 DWORD len; 936 LONG lres; 937 BOOL res; 938 939 /* we need to set all entries in the Registry, independent from the Level of 940 DRIVER_INFO, that the caller supplied */ 941 942 ZeroMemory(&di, sizeof(di)); 943 if (pDriverInfo && (level < ARRAYSIZE(di_sizeof))) 944 { 945 memcpy(&di, pDriverInfo, di_sizeof[level]); 946 } 947 948 /* dump the most used infos */ 949 FIXME("%p: .cVersion : 0x%x/%d\n", pDriverInfo, di.cVersion, di.cVersion); 950 FIXME("%p: .pName : %s\n", di.pName, debugstr_w(di.pName)); 951 FIXME("%p: .pEnvironment: %s\n", di.pEnvironment, debugstr_w(di.pEnvironment)); 952 FIXME("%p: .pDriverPath : %s\n", di.pDriverPath, debugstr_w(di.pDriverPath)); 953 FIXME("%p: .pDataFile : %s\n", di.pDataFile, debugstr_w(di.pDataFile)); 954 FIXME("%p: .pConfigFile : %s\n", di.pConfigFile, debugstr_w(di.pConfigFile)); 955 FIXME("%p: .pHelpFile : %s\n", di.pHelpFile, debugstr_w(di.pHelpFile)); 956 /* dump only the first of the additional Files */ 957 FIXME("%p: .pDependentFiles: %s\n", di.pDependentFiles, debugstr_w(di.pDependentFiles)); 958 959 960 /* check environment */ 961 env = validate_envW(di.pEnvironment); 962 if (env == NULL) return FALSE; /* ERROR_INVALID_ENVIRONMENT */ 963 964 /* fill the copy-data / get the driverdir */ 965 len = sizeof(apd.src) - sizeof(version3_subdirW) - sizeof(WCHAR); 966 if (!LocalGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, (LPBYTE) apd.src, len, &len)) 967 { 968 /* Should never fail */ 969 return FALSE; 970 } 971 memcpy(apd.dst, apd.src, len); 972 lstrcatW(apd.src, backslashW); 973 apd.srclen = lstrlenW(apd.src); 974 lstrcatW(apd.dst, env->versionsubdir); 975 lstrcatW(apd.dst, backslashW); 976 apd.dstlen = lstrlenW(apd.dst); 977 apd.copyflags = dwFileCopyFlags; 978 apd.lazy = lazy; 979 CreateDirectoryW(apd.src, NULL); 980 CreateDirectoryW(apd.dst, NULL); 981 982 hroot = open_driver_reg(env->envname); 983 if (!hroot) 984 { 985 ERR("Can't create Drivers key\n"); 986 return FALSE; 987 } 988 989 /* Fill the Registry for the Driver */ 990 if ((lres = RegCreateKeyExW(hroot, di.pName, 0, NULL, REG_OPTION_NON_VOLATILE, 991 KEY_WRITE | KEY_QUERY_VALUE, NULL, 992 &hdrv, &disposition)) != ERROR_SUCCESS) 993 { 994 ERR("can't create driver %s: %u\n", debugstr_w(di.pName), lres); 995 RegCloseKey(hroot); 996 SetLastError(lres); 997 return FALSE; 998 } 999 RegCloseKey(hroot); 1000 1001 /* Verified with the Adobe PS Driver, that w2k does not use di.Version */ 1002 RegSetValueExW(hdrv, versionW, 0, REG_DWORD, (const BYTE*) &env->driverversion, 1003 sizeof(DWORD)); 1004 1005 file = get_file_part( di.pDriverPath ); 1006 RegSetValueExW( hdrv, driverW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) ); 1007 apd_copyfile( di.pDriverPath, file, &apd ); 1008 1009 file = get_file_part( di.pDataFile ); 1010 RegSetValueExW( hdrv, data_fileW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) ); 1011 apd_copyfile( di.pDataFile, file, &apd ); 1012 1013 file = get_file_part( di.pConfigFile ); 1014 RegSetValueExW( hdrv, configuration_fileW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) ); 1015 apd_copyfile( di.pConfigFile, file, &apd ); 1016 1017 /* settings for level 3 */ 1018 if (di.pHelpFile) 1019 { 1020 file = get_file_part( di.pHelpFile ); 1021 RegSetValueExW( hdrv, help_fileW, 0, REG_SZ, (LPBYTE)file, (lstrlenW( file ) + 1) * sizeof(WCHAR) ); 1022 apd_copyfile( di.pHelpFile, file, &apd ); 1023 } 1024 else 1025 RegSetValueExW( hdrv, help_fileW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW) ); 1026 1027 if (di.pDependentFiles && *di.pDependentFiles) 1028 { 1029 WCHAR *reg, *reg_ptr, *in_ptr; 1030 reg = reg_ptr = HeapAlloc( GetProcessHeap(), 0, multi_sz_lenW( di.pDependentFiles ) ); 1031 1032 for (in_ptr = di.pDependentFiles; *in_ptr; in_ptr += lstrlenW( in_ptr ) + 1) 1033 { 1034 file = get_file_part( in_ptr ); 1035 len = lstrlenW( file ) + 1; 1036 memcpy( reg_ptr, file, len * sizeof(WCHAR) ); 1037 reg_ptr += len; 1038 apd_copyfile( in_ptr, file, &apd ); 1039 } 1040 *reg_ptr = 0; 1041 1042 RegSetValueExW( hdrv, dependent_filesW, 0, REG_MULTI_SZ, (LPBYTE)reg, (reg_ptr - reg + 1) * sizeof(WCHAR) ); 1043 HeapFree( GetProcessHeap(), 0, reg ); 1044 } 1045 else 1046 RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW)); 1047 1048 /* The language-Monitor was already copied by the caller to "%SystemRoot%\system32" */ 1049 if (di.pMonitorName) 1050 RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (LPBYTE) di.pMonitorName, 1051 (lstrlenW(di.pMonitorName)+1)* sizeof(WCHAR)); 1052 else 1053 RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW)); 1054 1055 if (di.pDefaultDataType) 1056 RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (LPBYTE) di.pDefaultDataType, 1057 (lstrlenW(di.pDefaultDataType)+1)* sizeof(WCHAR)); 1058 else 1059 RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW)); 1060 1061 /* settings for level 4 */ 1062 if (di.pszzPreviousNames) 1063 RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (LPBYTE) di.pszzPreviousNames, 1064 multi_sz_lenW(di.pszzPreviousNames)); 1065 else 1066 RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW)); 1067 1068 if (level > 5) FIXME("level %u for Driver %s is incomplete\n", level, debugstr_w(di.pName)); 1069 1070 RegCloseKey(hdrv); 1071 1072 // 1073 // Locate driver and send the event. 1074 // 1075 1076 hui = driver_load(env, di.pConfigFile); 1077 1078 pDrvDriverEvent = (void *)GetProcAddress(hui, "DrvDriverEvent"); 1079 1080 if (hui && pDrvDriverEvent) 1081 { 1082 /* Support for DrvDriverEvent is optional */ 1083 TRACE("DRIVER_EVENT_INITIALIZE for %s (%s)\n", debugstr_w(di.pName), debugstr_w(di.pConfigFile)); 1084 /* MSDN: level for DRIVER_INFO is 1 to 3 */ 1085 res = pDrvDriverEvent(DRIVER_EVENT_INITIALIZE, 3, (LPBYTE) &di, 0); 1086 TRACE("got %d from DRIVER_EVENT_INITIALIZE\n", res); 1087 } 1088 FreeLibrary(hui); 1089 1090 FIXME("=> TRUE with %u\n", GetLastError()); 1091 return TRUE; 1092 } 1093 1094 /****************************************************************************** 1095 * AddPrinterDriverEx [exported through PRINTPROVIDOR] 1096 * 1097 * Install a Printer Driver with the Option to upgrade / downgrade the Files 1098 * 1099 * PARAMS 1100 * pName [I] Servername or NULL (local Computer) 1101 * level [I] Level for the supplied DRIVER_INFO_*W struct 1102 * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter 1103 * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files 1104 * 1105 * RESULTS 1106 * Success: TRUE 1107 * Failure: FALSE 1108 * 1109 */ 1110 BOOL WINAPI LocalAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags) 1111 { 1112 LONG lres; 1113 1114 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags); 1115 1116 lres = copy_servername_from_name(pName, NULL); 1117 1118 if (lres) 1119 { 1120 FIXME("server %s not supported\n", debugstr_w(pName)); 1121 SetLastError(ERROR_ACCESS_DENIED); 1122 return FALSE; 1123 } 1124 1125 if ((dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY) != APD_COPY_ALL_FILES) 1126 { 1127 TRACE("Flags 0x%x ignored (using APD_COPY_ALL_FILES)\n", dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY); 1128 } 1129 1130 return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE); 1131 } 1132 1133 BOOL WINAPI LocalAddPrinterDriver(LPWSTR pName, DWORD level, LPBYTE pDriverInfo) 1134 { 1135 LONG lres; 1136 1137 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo); 1138 1139 lres = copy_servername_from_name(pName, NULL); 1140 1141 if (lres) 1142 { 1143 FIXME("server %s not supported\n", debugstr_w(pName)); 1144 SetLastError(ERROR_ACCESS_DENIED); 1145 return FALSE; 1146 } 1147 1148 // Should be APD_COPY_NEW_FILES. Cheap wine. 1149 1150 return myAddPrinterDriverEx(level, pDriverInfo, APD_COPY_NEW_FILES, TRUE); 1151 } 1152