Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1019 lines
29 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. drvupgrd.c
  5. Abstract:
  6. When the system is upgraded from one release to another printer drivers
  7. (e.g. RASDD ) wants to upgrade is PrinterDriverData to match the new mini driver.
  8. Setup from NT 4.0 on do this by calling EnumPrinterDriver and then AddPrinterDriver
  9. for each printer driver that we have installed.
  10. We call DrvUpgrade each time a printer driver is upgraded.
  11. For Example, pre NT 3.51 RASDD used to store its regstiry PrinterDriverData
  12. based on internal indexes into the mini drivers, which was not valid beween
  13. different updates of the mini driver, so before 3.51 it was by luck if there
  14. were problems in retriving the settings. With 3.51 RASDD will convert these
  15. indexes back to meaningful key names ( like Memory ) so hopefully in future
  16. we don't have an upgrade problem.
  17. Note also that other than upgrade time ( which happens once ) DrvUpgrade needs to
  18. be called on Point and Print whenever a Driver file gets updated. See Driver.C
  19. for details. Or anyone updates a printer driver by calling AddPrinterDriver.
  20. Author:
  21. Matthew A Felton ( MattFe ) March 11 1995
  22. Revision History:
  23. --*/
  24. #include <precomp.h>
  25. #pragma hdrstop
  26. #include "clusspl.h"
  27. #include <winddiui.h>
  28. BOOL
  29. UpdateUpgradeInfoStruct(
  30. LPBYTE pDriverUpgradeInfo,
  31. DWORD dwLevel,
  32. LPWSTR pPrinterNameWithToken,
  33. LPWSTR pOldDriverDir,
  34. LPBYTE pDriverInfo
  35. )
  36. /*++
  37. Function Description: This function fills in the Upgrade_Info struct with the
  38. other parameters
  39. Parameters: pDriverUpgradeInfo -- pointer Upgrade_Info_* struct
  40. dwLevel -- Upgrade_Info level
  41. pPrinterNameWithToken -- printer name
  42. pOldDriverDir -- Directory containing the old driver files
  43. pDriverInfo -- pointer to driver_info_4 struct
  44. Return Values: TRUE for sucesss;
  45. FALSE otherwise
  46. --*/
  47. {
  48. BOOL bReturn = TRUE;
  49. PDRIVER_UPGRADE_INFO_1 pDrvUpgInfo1;
  50. PDRIVER_UPGRADE_INFO_2 pDrvUpgInfo2;
  51. PDRIVER_INFO_4 pDriver4;
  52. switch (dwLevel) {
  53. case 1:
  54. pDrvUpgInfo1 = (PDRIVER_UPGRADE_INFO_1) pDriverUpgradeInfo;
  55. pDrvUpgInfo1->pPrinterName = pPrinterNameWithToken;
  56. pDrvUpgInfo1->pOldDriverDirectory = pOldDriverDir;
  57. break;
  58. case 2:
  59. if (pDriver4 = (PDRIVER_INFO_4) pDriverInfo) {
  60. pDrvUpgInfo2 = (PDRIVER_UPGRADE_INFO_2) pDriverUpgradeInfo;
  61. pDrvUpgInfo2->pPrinterName = pPrinterNameWithToken;
  62. pDrvUpgInfo2->pOldDriverDirectory = pOldDriverDir;
  63. pDrvUpgInfo2->cVersion = pDriver4->cVersion;
  64. pDrvUpgInfo2->pName = pDriver4->pName;
  65. pDrvUpgInfo2->pEnvironment = pDriver4->pEnvironment;
  66. pDrvUpgInfo2->pDriverPath = pDriver4->pDriverPath;
  67. pDrvUpgInfo2->pDataFile = pDriver4->pDataFile;
  68. pDrvUpgInfo2->pConfigFile = pDriver4->pConfigFile;
  69. pDrvUpgInfo2->pHelpFile = pDriver4->pHelpFile;
  70. pDrvUpgInfo2->pDependentFiles = pDriver4->pDependentFiles;
  71. pDrvUpgInfo2->pMonitorName = pDriver4->pMonitorName;
  72. pDrvUpgInfo2->pDefaultDataType = pDriver4->pDefaultDataType;
  73. pDrvUpgInfo2->pszzPreviousNames = pDriver4->pszzPreviousNames;
  74. } else {
  75. bReturn = FALSE;
  76. }
  77. break;
  78. default:
  79. bReturn = FALSE;
  80. break;
  81. }
  82. return bReturn;
  83. }
  84. BOOL
  85. bIsNewFile(
  86. LPWSTR pDriverFile,
  87. PINTERNAL_DRV_FILE pInternalDriverFiles,
  88. DWORD dwFileCount
  89. )
  90. /*++
  91. Function Description: This function checks to see if a driver file was updated
  92. Parameters: pDriverFile -- driver file
  93. pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  94. dwFileCount -- number of files in file set
  95. Return Values: TRUE for sucesss;
  96. FALSE otherwise
  97. --*/
  98. {
  99. DWORD dwIndex;
  100. LPCWSTR psz;
  101. BOOL bRet = FALSE;
  102. //
  103. // Must have some files.
  104. //
  105. SPLASSERT( dwFileCount );
  106. //
  107. // Search for pDriverFile in ppFileNames array
  108. //
  109. for ( dwIndex = 0; dwIndex < dwFileCount ; ++dwIndex ) {
  110. if( pInternalDriverFiles[dwIndex].pFileName ) {
  111. //
  112. // Find the filename portion of a path
  113. //
  114. psz = FindFileName(pInternalDriverFiles[dwIndex].pFileName );
  115. if( psz ){
  116. if( !lstrcmpi(pDriverFile, psz) ){
  117. //
  118. // Check if the file was updated
  119. //
  120. bRet = pInternalDriverFiles[dwIndex].bUpdated;
  121. break;
  122. }
  123. }
  124. }
  125. }
  126. return bRet;
  127. }
  128. BOOL
  129. DriversShareFiles(
  130. PINIDRIVER pIniDriver1,
  131. PINIDRIVER pIniDriver2,
  132. PINTERNAL_DRV_FILE pInternalDriverFiles,
  133. DWORD dwFileCount
  134. )
  135. /*++
  136. Function Description: Determines if the drivers have common files and
  137. if the common files were updated
  138. Parameters: pIniDriver1 -- driver #1
  139. pIniDriver2 -- driver #2
  140. pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  141. dwFileCount -- number of files in file set
  142. pUpdateStatusBitMap -- map of bits that tells what files in the file set were actually updated
  143. Return Values: TRUE if files are shared;
  144. FALSE otherwise
  145. --*/
  146. {
  147. LPWSTR pStr1, pStr2;
  148. if (!pIniDriver1 || !pIniDriver2) {
  149. return FALSE;
  150. }
  151. if (pIniDriver1->cVersion != pIniDriver2->cVersion) {
  152. return FALSE;
  153. }
  154. //
  155. // Compare the file names and if they were updated
  156. //
  157. if (pIniDriver1->pDriverFile && pIniDriver2->pDriverFile &&
  158. !lstrcmpi(pIniDriver1->pDriverFile, pIniDriver2->pDriverFile) &&
  159. bIsNewFile(pIniDriver1->pDriverFile, pInternalDriverFiles, dwFileCount)) {
  160. return TRUE;
  161. }
  162. if (pIniDriver1->pConfigFile && pIniDriver2->pConfigFile &&
  163. !lstrcmpi(pIniDriver1->pConfigFile, pIniDriver2->pConfigFile) &&
  164. bIsNewFile(pIniDriver1->pConfigFile, pInternalDriverFiles, dwFileCount)) {
  165. return TRUE;
  166. }
  167. if (pIniDriver1->pHelpFile && pIniDriver2->pHelpFile &&
  168. !lstrcmpi(pIniDriver1->pHelpFile, pIniDriver2->pHelpFile) &&
  169. bIsNewFile(pIniDriver1->pHelpFile, pInternalDriverFiles, dwFileCount)) {
  170. return TRUE;
  171. }
  172. if (pIniDriver1->pDataFile && pIniDriver2->pDataFile &&
  173. !lstrcmpi(pIniDriver1->pDataFile, pIniDriver2->pDataFile) &&
  174. bIsNewFile(pIniDriver1->pDataFile, pInternalDriverFiles, dwFileCount)) {
  175. return TRUE;
  176. }
  177. // Compare each pair of files from the Dependent file list
  178. for (pStr1 = pIniDriver1->pDependentFiles;
  179. pStr1 && *pStr1;
  180. pStr1 += wcslen(pStr1) + 1) {
  181. for (pStr2 = pIniDriver2->pDependentFiles;
  182. pStr2 && *pStr2;
  183. pStr2 += wcslen(pStr2) + 1) {
  184. if (!lstrcmpi(pStr1, pStr2) &&
  185. bIsNewFile(pStr1, pInternalDriverFiles, dwFileCount)) {
  186. return TRUE;
  187. }
  188. }
  189. }
  190. return FALSE;
  191. }
  192. BOOL
  193. ForEachPrinterCallDriverDrvUpgrade(
  194. PINISPOOLER pIniSpooler,
  195. PINIDRIVER pIniDriver,
  196. LPCWSTR pOldDriverDir,
  197. PINTERNAL_DRV_FILE pInternalDriverFiles,
  198. DWORD dwFileCount,
  199. LPBYTE pDriverInfo
  200. )
  201. /*++
  202. Routine Description:
  203. This routine is called at Spooler Initialization time if an upgrade is detected.
  204. It will loop through all printers and then call the Printer Drivers DrvUpgrade
  205. entry point giving it a chance to upgrade any configuration data ( PrinterDriverData )
  206. passing them a pointer to the old Drivers Directory.
  207. This routine also converts devmode to current version by calling the driver.
  208. If driver does not support devmode conversion we will NULL the devmode so
  209. that we do not have devmodes of different version in the system.
  210. SECURITY NOTE - This routine Stops impersonation, because the printer drivers UI dll
  211. needs to call SetPrinterData even if the user doesn't have permission to do it.
  212. That is because the driver upgrading the settings.
  213. Arguments:
  214. pIniSpooler - Pointer to Spooler
  215. pIniVersion - Pointer to the version of driver added
  216. pOldDriverDir - Point to Directory where old driver files are stored.
  217. pInternalDriverFiles - array of INTERNAL_DRV_FILE structures
  218. dwFileCount - number of files in array
  219. pUpdateStatusBitMap - map of bits that tells what files in the file set were actually updated
  220. pDriverInfo - Driver Info buffer
  221. Return Value:
  222. TRUE - Success
  223. FALSE - something major failed, like allocating memory.
  224. --*/
  225. {
  226. PINIPRINTER pIniPrinter = NULL;
  227. LPWSTR pPrinterNameWithToken = NULL;
  228. DWORD dwNeeded;
  229. DWORD dwServerMajorVersion;
  230. DWORD dwServerMinorVersion;
  231. BOOL bInSem = TRUE;
  232. LPWSTR pConfigFile = NULL;
  233. HMODULE hModuleDriverUI = NULL;
  234. HANDLE hPrinter = NULL;
  235. BOOL (*pfnDrvUpgrade)() = NULL;
  236. BOOL bReturnValue = FALSE;
  237. DRIVER_UPGRADE_INFO_1 DriverUpgradeInfo1;
  238. DRIVER_UPGRADE_INFO_2 DriverUpgradeInfo2;
  239. WCHAR ErrorBuffer[ 11 ];
  240. HANDLE hToken = INVALID_HANDLE_VALUE;
  241. LPDEVMODE pNewDevMode = NULL;
  242. try {
  243. SplInSem();
  244. SPLASSERT( ( pIniSpooler != NULL ) &&
  245. ( pIniSpooler->signature == ISP_SIGNATURE ));
  246. if (!pOldDriverDir && !pDriverInfo) {
  247. leave;
  248. }
  249. //
  250. // Stop Impersonating User
  251. // So drivers can call SetPrinterData even if the user is not admin.
  252. //
  253. hToken = RevertToPrinterSelf();
  254. //
  255. // Loop Through All Printers. Skip the printers that use drivers that doesn't share files with
  256. // the updated driver. Skip the printers that share files,but the files weren't updated.
  257. //
  258. for ( pIniPrinter = pIniSpooler->pIniPrinter ;
  259. pIniPrinter ;
  260. pIniPrinter = pIniPrinter->pNext ) {
  261. SPLASSERT( pIniPrinter->signature == IP_SIGNATURE );
  262. SPLASSERT( pIniPrinter->pName != NULL );
  263. SplInSem();
  264. // Verify if DrvUpgradePrinter needs to be called on this printer
  265. if (!DriversShareFiles( pIniPrinter->pIniDriver,
  266. pIniDriver,
  267. pInternalDriverFiles,
  268. dwFileCount)) {
  269. continue;
  270. }
  271. //
  272. // Cleanup from previous iteration
  273. //
  274. FreeSplStr( pPrinterNameWithToken );
  275. FreeSplStr(pConfigFile);
  276. FreeSplMem(pNewDevMode);
  277. pPrinterNameWithToken = NULL;
  278. pConfigFile = NULL;
  279. pNewDevMode = NULL;
  280. //
  281. // If we download a driver of newer version we need to update
  282. // pIniPrinter->pIniDriver
  283. //
  284. pIniPrinter->pIniDriver = FindLocalDriver(pIniPrinter->pIniSpooler, pIniPrinter->pIniDriver->pName);
  285. if ( pIniPrinter->pIniDriver->pIniLangMonitor == NULL )
  286. pIniPrinter->Attributes &= ~PRINTER_ATTRIBUTE_ENABLE_BIDI;
  287. // Prepare PrinterName to be passed to DrvUpgrade
  288. // The name passed is "PrinterName, UpgradeToken"
  289. // So that OpenPrinter can do an open without opening
  290. // the port in the downlevel connection case.
  291. // ( see openprn.c for details )
  292. pPrinterNameWithToken = pszGetPrinterName( pIniPrinter,
  293. TRUE,
  294. pszLocalOnlyToken );
  295. if ( pPrinterNameWithToken == NULL ) {
  296. DBGMSG( DBG_WARNING, ("FEPCDDU Failed to allocated ScratchBuffer %d\n", GetLastError() ));
  297. leave;
  298. }
  299. DBGMSG( DBG_TRACE, ("FEPCDDU PrinterNameWithToken %ws\n", pPrinterNameWithToken ));
  300. pConfigFile = GetConfigFilePath(pIniPrinter);
  301. if ( !pConfigFile ) {
  302. DBGMSG( DBG_WARNING, ("FEPCDDU failed SplGetPrinterDriverEx %d\n", GetLastError() ));
  303. leave;
  304. }
  305. INCPRINTERREF(pIniPrinter);
  306. LeaveSplSem();
  307. SplOutSem();
  308. bInSem = FALSE;
  309. //
  310. // Load the UI DLL
  311. //
  312. hModuleDriverUI = LoadDriver(pConfigFile);
  313. if ( hModuleDriverUI == NULL ) {
  314. DBGMSG( DBG_WARNING, ("FEPCDDU failed LoadLibrary %ws error %d\n", pConfigFile, GetLastError() ));
  315. StringCchPrintf(ErrorBuffer, COUNTOF(ErrorBuffer), L"%d", GetLastError());
  316. SplLogEvent( pLocalIniSpooler,
  317. LOG_ERROR,
  318. MSG_DRIVER_FAILED_UPGRADE,
  319. FALSE,
  320. pPrinterNameWithToken,
  321. pConfigFile,
  322. ErrorBuffer,
  323. NULL );
  324. SplOutSem();
  325. EnterSplSem();
  326. bInSem = TRUE;
  327. DECPRINTERREF( pIniPrinter );
  328. continue;
  329. }
  330. DBGMSG( DBG_TRACE, ("FEPCDDU successfully loaded %ws\n", pConfigFile ));
  331. //
  332. // Call DrvUpgrade
  333. //
  334. pfnDrvUpgrade = (BOOL (*)())GetProcAddress( hModuleDriverUI, "DrvUpgradePrinter" );
  335. if ( pfnDrvUpgrade != NULL ) {
  336. try {
  337. SPLASSERT( pPrinterNameWithToken != NULL );
  338. SplOutSem();
  339. //
  340. // Call Driver UI DrvUpgrade
  341. //
  342. if (UpdateUpgradeInfoStruct((LPBYTE) &DriverUpgradeInfo2, 2,
  343. pPrinterNameWithToken, (LPWSTR) pOldDriverDir,
  344. pDriverInfo)) {
  345. bReturnValue = (*pfnDrvUpgrade)(2 , &DriverUpgradeInfo2);
  346. }
  347. if ( bReturnValue == FALSE ) {
  348. UpdateUpgradeInfoStruct((LPBYTE) &DriverUpgradeInfo1, 1,
  349. pPrinterNameWithToken, (LPWSTR) pOldDriverDir,
  350. NULL);
  351. bReturnValue = (*pfnDrvUpgrade)(1 , &DriverUpgradeInfo1);
  352. }
  353. if ( bReturnValue == FALSE ) {
  354. DBGMSG( DBG_WARNING, ("FEPCDDU Driver returned FALSE, doesn't support level %d error %d\n", 1, GetLastError() ));
  355. StringCchPrintf(ErrorBuffer, COUNTOF(ErrorBuffer), L"%d", GetLastError());
  356. SplLogEvent( pLocalIniSpooler,
  357. LOG_ERROR,
  358. MSG_DRIVER_FAILED_UPGRADE,
  359. FALSE,
  360. pPrinterNameWithToken,
  361. pConfigFile,
  362. ErrorBuffer,
  363. NULL );
  364. }
  365. } except(1) {
  366. SetLastError( GetExceptionCode() );
  367. DBGMSG( DBG_ERROR, ("FEPCDDU ExceptionCode %x Driver %ws Error %d\n", GetLastError(), pConfigFile, GetLastError() ));
  368. //
  369. // Despite the exception in this driver we'll continue to do all printers
  370. //
  371. }
  372. } else {
  373. // Note this is non fatal, since a driver might not have a DrvUpgrade Entry Point.
  374. DBGMSG( DBG_TRACE, ("FEPCDDU failed GetProcAddress DrvUpgrade error %d\n", GetLastError() ));
  375. }
  376. SplOutSem();
  377. EnterSplSem();
  378. bInSem = TRUE;
  379. //
  380. // Call ConvertDevMode -- On upgrading we will either convert devmode,
  381. // or set to driver default, or NULL it. This way we can make sure
  382. // we do not have any different version devmodes
  383. //
  384. pNewDevMode = ConvertDevModeToSpecifiedVersion(pIniPrinter,
  385. pIniPrinter->pDevMode,
  386. pConfigFile,
  387. pPrinterNameWithToken,
  388. CURRENT_VERSION);
  389. SplInSem();
  390. FreeSplMem(pIniPrinter->pDevMode);
  391. pIniPrinter->pDevMode = (LPDEVMODE) pNewDevMode;
  392. if ( pNewDevMode ) {
  393. pIniPrinter->cbDevMode = ((LPDEVMODE)pNewDevMode)->dmSize
  394. + ((LPDEVMODE)pNewDevMode)->dmDriverExtra;
  395. SPLASSERT(pIniPrinter->cbDevMode);
  396. } else {
  397. StringCchPrintf(ErrorBuffer, COUNTOF(ErrorBuffer), L"%d", GetLastError());
  398. SplLogEvent(pLocalIniSpooler,
  399. LOG_ERROR,
  400. MSG_DRIVER_FAILED_UPGRADE,
  401. TRUE,
  402. pIniPrinter->pName,
  403. pIniPrinter->pIniDriver->pName,
  404. ErrorBuffer,
  405. NULL);
  406. pIniPrinter->cbDevMode = 0;
  407. }
  408. pNewDevMode = NULL;
  409. SplInSem();
  410. if ( !UpdatePrinterIni(pIniPrinter, UPDATE_CHANGEID)) {
  411. DBGMSG(DBG_WARNING, ("FEPCDDU: UpdatePrinterIni failed with %d\n", GetLastError()));
  412. }
  413. //
  414. // Clean Up - Free UI DLL
  415. //
  416. LeaveSplSem();
  417. SplOutSem();
  418. UnloadDriver( hModuleDriverUI );
  419. EnterSplSem();
  420. SplInSem();
  421. hModuleDriverUI = NULL;
  422. //
  423. // End of Loop, Move to Next Printer
  424. //
  425. SPLASSERT( pIniPrinter->signature == IP_SIGNATURE );
  426. DECPRINTERREF( pIniPrinter );
  427. }
  428. //
  429. // Done
  430. //
  431. bReturnValue = TRUE;
  432. DBGMSG( DBG_TRACE, ("FEPCDDU - Success\n" ));
  433. } finally {
  434. //
  435. // Clean Up
  436. //
  437. FreeSplStr(pConfigFile);
  438. FreeSplMem(pNewDevMode);
  439. FreeSplStr(pPrinterNameWithToken);
  440. if ( hModuleDriverUI != NULL )
  441. UnloadDriver( hModuleDriverUI );
  442. if ( !bInSem )
  443. EnterSplSem();
  444. if ( hToken != INVALID_HANDLE_VALUE )
  445. ImpersonatePrinterClient(hToken);
  446. }
  447. SplInSem();
  448. return bReturnValue;
  449. }
  450. BOOL
  451. GetFileNamesFromDriverVersionInfo (
  452. IN LPDRIVER_INFO_VERSION pDriverInfo,
  453. OUT LPWSTR *ppszDriverPath,
  454. OUT LPWSTR *ppszConfigFile,
  455. OUT LPWSTR *ppszDataFile,
  456. OUT LPWSTR *ppszHelpFile
  457. )
  458. /*++
  459. Routine Name:
  460. GetFileNamesFromDriverVersionInfo
  461. Routine Description:
  462. Get the name of Driver, Config, Data, Help file from an
  463. array of DRIVER_FILE_INFO structures.
  464. Arguments:
  465. pDriverInfo - Pointer to LPDRIVER_INFO_VERSION buffer.
  466. ppszDriverPath - out pointer to driver file string
  467. ppszConfigFile - out pointer to config file string
  468. ppszDataFile - out pointer to data file string
  469. ppszHelpFile - out pointer to help file string
  470. Return Value:
  471. TRUE if file pointers successfully returned.
  472. --*/
  473. {
  474. BOOL bRetValue = FALSE;
  475. DWORD dwIndex;
  476. if (pDriverInfo && pDriverInfo->pFileInfo)
  477. {
  478. bRetValue = TRUE;
  479. for (dwIndex = 0; dwIndex < pDriverInfo->dwFileCount; dwIndex++)
  480. {
  481. switch (pDriverInfo->pFileInfo[dwIndex].FileType)
  482. {
  483. case DRIVER_FILE:
  484. if (ppszDriverPath)
  485. {
  486. *ppszDriverPath = MakePTR(pDriverInfo,
  487. pDriverInfo->pFileInfo[dwIndex].FileNameOffset);
  488. }
  489. break;
  490. case CONFIG_FILE:
  491. if (ppszConfigFile)
  492. {
  493. *ppszConfigFile = MakePTR(pDriverInfo,
  494. pDriverInfo->pFileInfo[dwIndex].FileNameOffset);
  495. }
  496. break;
  497. case DATA_FILE:
  498. if (ppszDataFile)
  499. {
  500. *ppszDataFile = MakePTR(pDriverInfo,
  501. pDriverInfo->pFileInfo[dwIndex].FileNameOffset);
  502. }
  503. break;
  504. case HELP_FILE:
  505. if (ppszHelpFile)
  506. {
  507. *ppszHelpFile = MakePTR(pDriverInfo,
  508. pDriverInfo->pFileInfo[dwIndex].FileNameOffset);
  509. }
  510. break;
  511. case DEPENDENT_FILE:
  512. break;
  513. default:
  514. bRetValue = FALSE;
  515. break;
  516. }
  517. }
  518. }
  519. return bRetValue;
  520. }
  521. BOOL
  522. BuildDependentFilesFromDriverInfo (
  523. IN LPDRIVER_INFO_VERSION pDriverInfo,
  524. OUT LPWSTR *ppDependentFiles
  525. )
  526. /*++
  527. Routine Name:
  528. BuildDependentFilesFromDriverInfo
  529. Routine Description:
  530. Build a multisz string of driver dependent files from
  531. a DRIVER_INFO_VERSION structure.
  532. Arguments:
  533. pDriverInfo - pointer to DRIVER_INFO_VERSION structure
  534. ppDependentFiles - pointer to allocated multi-sz string
  535. Return Value:
  536. TRUE if SUCCESS
  537. --*/
  538. {
  539. BOOL bRetValue = TRUE;
  540. DWORD dwIndex;
  541. SIZE_T Length = 0;
  542. LPWSTR pszDllFile = NULL;
  543. if (ppDependentFiles && pDriverInfo && pDriverInfo->pFileInfo)
  544. {
  545. *ppDependentFiles = NULL;
  546. for (dwIndex = 0;
  547. bRetValue && dwIndex < pDriverInfo->dwFileCount;
  548. dwIndex++)
  549. {
  550. switch (pDriverInfo->pFileInfo[dwIndex].FileType)
  551. {
  552. case DRIVER_FILE:
  553. case CONFIG_FILE:
  554. case DATA_FILE:
  555. case HELP_FILE:
  556. break;
  557. case DEPENDENT_FILE:
  558. {
  559. Length += wcslen(MakePTR(pDriverInfo,
  560. pDriverInfo->pFileInfo[dwIndex].FileNameOffset)) + 1;
  561. break;
  562. }
  563. default:
  564. {
  565. bRetValue = FALSE;
  566. break;
  567. }
  568. }
  569. }
  570. if (bRetValue && Length > 0)
  571. {
  572. Length++;
  573. Length *= sizeof(WCHAR);
  574. pszDllFile = (LPWSTR)AllocSplMem((DWORD)Length);
  575. if (pszDllFile)
  576. {
  577. *ppDependentFiles = pszDllFile;
  578. for (dwIndex = 0;
  579. bRetValue && dwIndex < pDriverInfo->dwFileCount;
  580. dwIndex++)
  581. {
  582. switch (pDriverInfo->pFileInfo[dwIndex].FileType)
  583. {
  584. case DRIVER_FILE:
  585. case CONFIG_FILE:
  586. case DATA_FILE:
  587. case HELP_FILE:
  588. break;
  589. case DEPENDENT_FILE:
  590. {
  591. StrCchCopyMultipleStr(pszDllFile,
  592. Length,
  593. MakePTR(pDriverInfo,pDriverInfo->pFileInfo[dwIndex].FileNameOffset),
  594. &pszDllFile,
  595. &Length);
  596. break;
  597. }
  598. default:
  599. {
  600. bRetValue = FALSE;
  601. break;
  602. }
  603. }
  604. }
  605. }
  606. else
  607. {
  608. bRetValue = FALSE;
  609. }
  610. }
  611. }
  612. if (bRetValue == FALSE && ppDependentFiles)
  613. {
  614. FreeSplMem(*ppDependentFiles);
  615. *ppDependentFiles = NULL;
  616. }
  617. return bRetValue;
  618. }
  619. BOOL
  620. DriverAddedOrUpgraded (
  621. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  622. IN DWORD dwFileCount
  623. )
  624. /*++
  625. Routine Name:
  626. DriverAddedOrUpgraded
  627. Routine Description:
  628. Checks the Internal driver file array to see if at least
  629. one driver file was updated. This is a performance optimization
  630. for calling DrvUpgradePrinter for ecah printer using the upgraded
  631. driver or a driver sharing files in common with upgraded driver
  632. (see ForEachPrinterCallDriverDrvUpgrade).
  633. Arguments:
  634. pInternalDriverFiles - array of INTERNAL_DRV_FILE structures
  635. dwFileCount - number of files in array
  636. Return Value:
  637. TRUE if driver files where added or upgraded.
  638. --*/
  639. {
  640. BOOL bDriverAddedOrUpgraded = FALSE;
  641. DWORD dwIndex;
  642. for (dwIndex = 0; dwIndex < dwFileCount; dwIndex++)
  643. {
  644. if (pInternalDriverFiles[dwIndex].bUpdated)
  645. {
  646. bDriverAddedOrUpgraded = TRUE;
  647. break;
  648. }
  649. }
  650. return bDriverAddedOrUpgraded;
  651. }
  652. VOID
  653. CleanupInternalDriverInfo(
  654. PINTERNAL_DRV_FILE pInternalDriverFiles,
  655. DWORD FileCount
  656. )
  657. /*++
  658. Routine Name:
  659. CleanupInternalDriverInfo
  660. Routine Description:
  661. Frees array of INTERNAL_DRV_FILE.
  662. FileCount gives the element count in the array.
  663. Arguments:
  664. pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  665. FileCount -- number of files in file set
  666. Return Value:
  667. Nothing.
  668. --*/
  669. {
  670. DWORD dwIndex;
  671. if (pInternalDriverFiles)
  672. {
  673. for (dwIndex = 0; dwIndex < FileCount; dwIndex++)
  674. {
  675. FreeSplStr(pInternalDriverFiles[dwIndex].pFileName);
  676. if (pInternalDriverFiles[dwIndex].hFileHandle != INVALID_HANDLE_VALUE)
  677. {
  678. CloseHandle(pInternalDriverFiles[dwIndex].hFileHandle);
  679. }
  680. }
  681. FreeSplMem(pInternalDriverFiles);
  682. }
  683. }
  684. BOOL
  685. GetDriverFileVersionsFromNames(
  686. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  687. IN DWORD dwCount
  688. )
  689. /*++
  690. Routine Name:
  691. GetDriverFileVersionsFromNames
  692. Routine Description:
  693. Fills the array of INTERNAL_DRV_FILE with driver minor version,
  694. by calling GetPrintDriverVersion for each file.
  695. The array already has the file names filled in.
  696. Arguments:
  697. pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  698. FileCount -- number of files in file set
  699. Return Value:
  700. TRUE if SUCCESS
  701. --*/
  702. {
  703. DWORD Count, Size;
  704. BOOL bReturnValue = TRUE;
  705. if (!pInternalDriverFiles || !dwCount)
  706. {
  707. bReturnValue = FALSE;
  708. SetLastError(ERROR_INVALID_DATA);
  709. }
  710. else
  711. {
  712. for (Count = 0 ; Count < dwCount ; ++Count)
  713. {
  714. if (IsEXEFile(pInternalDriverFiles[Count].pFileName))
  715. {
  716. if (!GetPrintDriverVersion(pInternalDriverFiles[Count].pFileName,
  717. NULL,
  718. &pInternalDriverFiles[Count].dwVersion))
  719. {
  720. bReturnValue = FALSE;
  721. break;
  722. }
  723. }
  724. }
  725. }
  726. return bReturnValue;
  727. }
  728. BOOL
  729. GetDriverFileVersions(
  730. IN LPDRIVER_INFO_VERSION pDriverVersion,
  731. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  732. IN DWORD dwCount
  733. )
  734. /*++
  735. Routine Name:
  736. GetDriverFileVersions
  737. Routine Description:
  738. Fills the array of INTERNAL_DRV_FILE with driver minor version
  739. stored in DRIVER_INFO_VERSION structure.
  740. Arguments:
  741. pDriverVersion - pointer to DRIVER_INFO_VERSION
  742. pInternalDriverFiles - pointer to array of INTERNAL_DRV_FILE
  743. dwCount - number of elemnts in array
  744. Return Value:
  745. TRUE if succeeded.
  746. --*/
  747. {
  748. DWORD Count, Size;
  749. BOOL bReturnValue = TRUE;
  750. DWORD dwMajorVersion;
  751. if (!pDriverVersion ||
  752. !pDriverVersion->pFileInfo ||
  753. pDriverVersion->dwFileCount != dwCount)
  754. {
  755. bReturnValue = FALSE;
  756. SetLastError(ERROR_INVALID_DATA);
  757. }
  758. else
  759. {
  760. for (Count = 0; Count < pDriverVersion->dwFileCount; Count++)
  761. {
  762. pInternalDriverFiles[Count].dwVersion = pDriverVersion->pFileInfo[Count].FileVersion;
  763. }
  764. }
  765. return bReturnValue;
  766. }