Source code of Windows XP (NT5)
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.

10443 lines
319 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. Module Name:
  4. driver.c
  5. Abstract:
  6. This module provides all the public exported APIs relating to the
  7. Driver-based Spooler Apis for the Local Print Providor
  8. LocalAddPrinterDriver
  9. LocalDeletePrinterDriver
  10. SplGetPrinterDriver
  11. LocalGetPrinterDriverDirectory
  12. LocalEnumPrinterDriver
  13. Support Functions in driver.c
  14. CopyIniDriverToDriver -- KrishnaG
  15. GetDriverInfoSize -- KrishnaG
  16. DeleteDriverIni -- KrishnaG
  17. WriteDriverIni -- KrishnaG
  18. Author:
  19. Dave Snipp (DaveSn) 15-Mar-1991
  20. Revision History:
  21. Felix Maxa (amaxa) 18-Jun-2000
  22. Modified registry functions to take pIniSpooler
  23. Added code to propagate drivers to the cluster disk
  24. Khaled Sedky (khaleds) 2 Feb 1999
  25. Modified CompleteDriverUpgrade to enable upgrading v.2 drivers to newer v.2 drivers
  26. Ramanathan Venkatapathy (RamanV) 14 Feb 1997
  27. Modified CreateVersionEntry,CreateDriverEntry, LocalDeletePrinterDriver,
  28. SplDeletePrinterDriver.
  29. Added Driver File RefCounting functions, DeletePrinterDriverEx functions.
  30. Muhunthan Sivapragasam (MuhuntS) 26 May 1995
  31. Changes to support DRIVER_INFO_3
  32. Matthew A Felton (MattFe) 27 June 1994
  33. pIniSpooler
  34. Matthew A Felton (MattFe) 23 Feb 1995
  35. CleanUp InternalAddPrinterDriver for win32spl use so it allows copying from non local
  36. directories.
  37. Matthew A Felton (MattFe) 23 Mar 1994
  38. Added DrvUpgradePrinter calls, changes required to AddPrinterDriver so to save old
  39. files.
  40. --*/
  41. #include <precomp.h>
  42. #include <lm.h>
  43. #include <offsets.h>
  44. #include <wingdip.h>
  45. #include "clusspl.h"
  46. //
  47. // Private Declarations
  48. //
  49. #define COMPATIBLE_SPOOLER_VERSION 2
  50. //
  51. // This definition is duplicated from oak\inc\winddi.h.
  52. //
  53. #define DRVQUERY_USERMODE 1
  54. extern NET_API_STATUS (*pfnNetShareAdd)();
  55. extern SHARE_INFO_2 PrintShareInfo;
  56. extern NET_API_STATUS (*pfnNetShareSetInfo)();
  57. #define MAX_DWORD_LENGTH 11
  58. typedef struct _DRVFILE {
  59. struct _DRVFILE *pnext;
  60. LPCWSTR pFileName;
  61. } DRVFILE, *PDRVFILE;
  62. DWORD
  63. CopyICMToClusterDisk(
  64. IN PINISPOOLER pIniSpooler
  65. );
  66. DWORD
  67. PropagateMonitorToCluster(
  68. IN LPCWSTR pszName,
  69. IN LPCWSTR pszDDLName,
  70. IN LPCWSTR pszEnvName,
  71. IN LPCWSTR pszEnvDir,
  72. IN PINISPOOLER pIniSpooler
  73. );
  74. BOOL
  75. CheckFilePlatform(
  76. IN LPWSTR pszFileName,
  77. IN LPWSTR pszEnvironment
  78. );
  79. LPBYTE
  80. CopyIniDriverToDriverInfo(
  81. PINIENVIRONMENT pIniEnvironment,
  82. PINIVERSION pIniVersion,
  83. PINIDRIVER pIniDriver,
  84. DWORD Level,
  85. LPBYTE pDriverInfo,
  86. LPBYTE pEnd,
  87. LPWSTR lpRemote,
  88. PINISPOOLER pIniSpooler
  89. );
  90. LPBYTE
  91. CopyIniDriverToDriverInfoVersion(
  92. IN PINIENVIRONMENT pIniEnvironment,
  93. IN PINIVERSION pIniVersion,
  94. IN PINIDRIVER pIniDriver,
  95. IN LPBYTE pDriverInfo,
  96. IN LPBYTE pEnd,
  97. IN LPWSTR lpRemote,
  98. IN PINISPOOLER pIniSpooler
  99. );
  100. LPBYTE
  101. CopyIniDriverFilesToDriverInfo(
  102. IN LPDRIVER_INFO_VERSION pDriverVersion,
  103. IN PINIVERSION pIniVersion,
  104. IN PINIDRIVER pIniDriver,
  105. IN LPCWSTR pszDriverVersionDir,
  106. IN LPBYTE pEnd
  107. );
  108. LPBYTE
  109. FillDriverInfo (
  110. IN LPDRIVER_INFO_VERSION pDriverFile,
  111. IN DWORD Index,
  112. IN PINIVERSION pIniVersion,
  113. IN LPCWSTR pszPrefix,
  114. IN LPCWSTR pszFileName,
  115. IN DRIVER_FILE_TYPE FileType,
  116. IN LPBYTE pEnd
  117. );
  118. BOOL GetDriverFileCachedVersion(
  119. IN PINIVERSION pIniVersion,
  120. IN LPCWSTR pFileName,
  121. OUT DWORD *pFileVersion
  122. );
  123. BOOL
  124. DriverAddedOrUpgraded (
  125. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  126. IN DWORD dwFileCount
  127. );
  128. BOOL
  129. BuildDependentFilesFromDriverInfo (
  130. IN LPDRIVER_INFO_VERSION pDriverInfo,
  131. OUT LPWSTR *ppDependentFiles
  132. );
  133. VOID
  134. UpdateDriverFileVersion(
  135. IN PINIVERSION pIniVersion,
  136. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  137. IN DWORD FileCount
  138. );
  139. BOOL SaveDriverVersionForUpgrade(
  140. IN HKEY hDriverKey,
  141. IN PDRIVER_INFO_VERSION pDriverVersion,
  142. IN LPWSTR pName,
  143. IN DWORD dwDriverMoved,
  144. IN DWORD dwVersion
  145. );
  146. DWORD
  147. CopyFileToClusterDirectory (
  148. IN PINISPOOLER pIniSpooler,
  149. IN PINIENVIRONMENT pIniEnvironment,
  150. IN PINIVERSION pIniVersion,
  151. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  152. IN DWORD FileCount
  153. );
  154. VOID
  155. CleanupInternalDriverInfo(
  156. PINTERNAL_DRV_FILE pInternalDriverFiles,
  157. DWORD FileCount
  158. );
  159. BOOL
  160. GetDriverFileVersionsFromNames(
  161. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  162. IN DWORD dwCount
  163. );
  164. BOOL
  165. GetDriverFileVersions(
  166. IN LPDRIVER_INFO_VERSION pDriverVersion,
  167. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  168. IN DWORD dwCount
  169. );
  170. BOOL
  171. GetFileNamesFromDriverVersionInfo (
  172. IN LPDRIVER_INFO_VERSION pDriverInfo,
  173. OUT LPWSTR *ppszDriverPath,
  174. OUT LPWSTR *ppszConfigFile,
  175. OUT LPWSTR *ppszDataFile,
  176. OUT LPWSTR *ppszHelpFile
  177. );
  178. BOOL
  179. WaitRequiredForDriverUnload(
  180. IN PINISPOOLER pIniSpooler,
  181. IN PINIENVIRONMENT pIniEnvironment,
  182. IN PINIVERSION pIniVersion,
  183. IN PINIDRIVER pIniDriver,
  184. IN DWORD dwLevel,
  185. IN LPBYTE pDriverInfo,
  186. IN DWORD dwFileCopyFlags,
  187. IN OUT PINTERNAL_DRV_FILE pInternalDriverFiles,
  188. IN DWORD dwFileCount,
  189. IN DWORD dwVersion,
  190. IN BOOL bDriverMoved,
  191. OUT LPBOOL pbSuccess
  192. );
  193. BOOL FilesUnloaded(
  194. PINIENVIRONMENT pIniEnvironment,
  195. LPWSTR pDriverFile,
  196. LPWSTR pConfigFile,
  197. DWORD dwDriverAttributes);
  198. DWORD StringSizeInBytes(
  199. LPWSTR pString,
  200. BOOL bMultiSz);
  201. BOOL SaveParametersForUpgrade(
  202. LPWSTR pName,
  203. BOOL bDriverMoved,
  204. DWORD dwLevel,
  205. LPBYTE pDriverInfo,
  206. DWORD dwVersion);
  207. VOID CleanUpResources(
  208. LPWSTR pKeyName,
  209. LPWSTR pSplName,
  210. PDRIVER_INFO_6 pDriverInfo,
  211. PINTERNAL_DRV_FILE *pInternalDriverFiles,
  212. DWORD dwFileCount);
  213. BOOL RestoreParametersForUpgrade(
  214. HKEY hUpgradeKey,
  215. DWORD dwIndex,
  216. LPWSTR *pKeyName,
  217. LPWSTR *pSplName,
  218. LPDWORD pdwLevel,
  219. LPDWORD pdwDriverMoved,
  220. PDRIVER_INFO_6 *ppDriverInfo);
  221. VOID CleanUpgradeDirectories();
  222. VOID FreeDriverInfo6(
  223. PDRIVER_INFO_6 pDriver6
  224. );
  225. BOOL RegGetValue(
  226. HKEY hDriverKey,
  227. LPWSTR pValueName,
  228. LPBYTE *pValue
  229. );
  230. BOOL
  231. WriteDriverIni(
  232. PINIDRIVER pIniDriver,
  233. PINIVERSION pIniVersion,
  234. PINIENVIRONMENT pIniEnvironment,
  235. PINISPOOLER pIniSpooler
  236. );
  237. BOOL
  238. DeleteDriverIni(
  239. PINIDRIVER pIniDriver,
  240. PINIVERSION pIniVersion,
  241. PINIENVIRONMENT pIniEnvironment,
  242. PINISPOOLER pIniSpooler
  243. );
  244. BOOL
  245. CreateVersionDirectory(
  246. PINIVERSION pIniVersion,
  247. PINIENVIRONMENT pIniEnvironment,
  248. BOOL bUpdate,
  249. PINISPOOLER pIniSpooler
  250. );
  251. DWORD
  252. GetDriverInfoSize(
  253. PINIDRIVER pIniDriver,
  254. DWORD Level,
  255. PINIVERSION pIniVersion,
  256. PINIENVIRONMENT pIniEnvironment,
  257. LPWSTR lpRemote,
  258. PINISPOOLER pIniSpooler
  259. );
  260. BOOL
  261. DeleteDriverVersionIni(
  262. PINIVERSION pIniVersion,
  263. PINIENVIRONMENT pIniEnvironment,
  264. PINISPOOLER pIniSpooler
  265. );
  266. BOOL
  267. WriteDriverVersionIni(
  268. PINIVERSION pIniVersion,
  269. PINIENVIRONMENT pIniEnvironment,
  270. PINISPOOLER pIniSpooler
  271. );
  272. PINIDRIVER
  273. FindDriverEntry(
  274. PINIVERSION pIniVersion,
  275. LPWSTR pszName
  276. );
  277. PINIDRIVER
  278. CreateDriverEntry(
  279. IN PINIENVIRONMENT pIniEnvironment,
  280. IN PINIVERSION pIniVersion,
  281. IN DWORD Level,
  282. IN LPBYTE pDriverInfo,
  283. IN DWORD dwFileCopyFlags,
  284. IN PINISPOOLER pIniSpooler,
  285. IN OUT PINTERNAL_DRV_FILE pInternalDriverFiles,
  286. IN DWORD FileCount,
  287. IN DWORD dwTempDir,
  288. IN PINIDRIVER pOldIniDriver
  289. );
  290. BOOL
  291. IsKMPD(
  292. LPWSTR pDriverName
  293. );
  294. VOID
  295. CheckDriverAttributes(
  296. PINISPOOLER pIniSpooler,
  297. PINIENVIRONMENT pIniEnvironment,
  298. PINIVERSION pIniVersion,
  299. PINIDRIVER pIniDriver
  300. );
  301. BOOL
  302. NotifyDriver(
  303. PINISPOOLER pIniSpooler,
  304. PINIENVIRONMENT pIniEnvironment,
  305. PINIVERSION pIniVersion,
  306. PINIDRIVER pIniDriver,
  307. DWORD dwDriverEvent,
  308. DWORD dwParameter
  309. );
  310. BOOL
  311. AddTempDriver(
  312. IN PINISPOOLER pIniSpooler,
  313. IN PINIENVIRONMENT pIniEnvironment,
  314. IN PINIVERSION pIniVersion,
  315. IN DWORD dwLevel,
  316. IN LPBYTE pDriverInfo,
  317. IN DWORD dwFileCopyFlags,
  318. IN OUT PINTERNAL_DRV_FILE pInternalDriverFiles,
  319. IN DWORD dwFileCount,
  320. IN DWORD dwVersion,
  321. IN BOOL bDriverMoved
  322. );
  323. BOOL
  324. CompleteDriverUpgrade(
  325. IN PINISPOOLER pIniSpooler,
  326. IN PINIENVIRONMENT pIniEnvironment,
  327. IN PINIVERSION pIniVersion,
  328. IN PINIDRIVER pIniDriver,
  329. IN DWORD dwLevel,
  330. IN LPBYTE pDriverInfo,
  331. IN DWORD dwFileCopyFlags,
  332. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  333. IN DWORD dwFileCount,
  334. IN DWORD dwVersion,
  335. IN DWORD dwTempDir,
  336. IN BOOL bDriverMoved,
  337. IN BOOL bDriverFileMoved,
  338. IN BOOL bConfigFileMoved
  339. );
  340. BOOL
  341. FilesInUse(
  342. PINIVERSION pIniVersion,
  343. PINIDRIVER pIniDriver
  344. );
  345. BOOL
  346. UpdateDriverFileRefCnt(
  347. PINIENVIRONMENT pIniEnvironment,
  348. PINIVERSION pIniVersion,
  349. PINIDRIVER pIniDriver,
  350. LPCWSTR pDirectory,
  351. DWORD dwDeleteFlag,
  352. BOOL bIncrementFlag
  353. );
  354. PDRVREFCNT
  355. IncrementFileRefCnt(
  356. PINIVERSION pIniVersion,
  357. LPCWSTR szFileName
  358. );
  359. PDRVREFCNT
  360. DecrementFileRefCnt(
  361. PINIENVIRONMENT pIniEnvironment,
  362. PINIVERSION pIniVersion,
  363. PINIDRIVER pIniDriver,
  364. LPCWSTR szFileName,
  365. LPCWSTR szDirectory,
  366. DWORD dwDeleteFlag
  367. );
  368. VOID
  369. RemovePendingUpgradeForDeletedDriver(
  370. LPWSTR pDriverName,
  371. DWORD dwVersion,
  372. PINISPOOLER pIniSpooler
  373. );
  374. VOID
  375. RemoveDriverTempFiles(
  376. PINISPOOLER pIniSpooler,
  377. PINIENVIRONMENT pIniEnvironment,
  378. PINIVERSION pIniVersion,
  379. PINIDRIVER pIniDriver
  380. );
  381. VOID
  382. DeleteDriverEntry(
  383. PINIVERSION pIniVersion,
  384. PINIDRIVER pIniDriver
  385. );
  386. PINIVERSION
  387. CreateVersionEntry(
  388. PINIENVIRONMENT pIniEnvironment,
  389. DWORD dwVersion,
  390. PINISPOOLER pInispooler
  391. );
  392. DWORD
  393. GetEnvironmentScratchDirectory(
  394. LPWSTR pDir,
  395. DWORD MaxLength,
  396. PINIENVIRONMENT pIniEnvironment,
  397. BOOL Remote
  398. );
  399. VOID
  400. SetOldDateOnDriverFilesInScratchDirectory(
  401. PINTERNAL_DRV_FILE pInternalDriverFiles,
  402. DWORD FileCount,
  403. PINISPOOLER pIniSpooler
  404. );
  405. BOOL
  406. CopyFilesToFinalDirectory(
  407. PINISPOOLER pIniSpooler,
  408. PINIENVIRONMENT pIniEnvironment,
  409. PINIVERSION pIniVersion,
  410. PINTERNAL_DRV_FILE pInternalDriverFiles,
  411. DWORD dwFileCount,
  412. DWORD dwFileCopyFlags,
  413. BOOL bImpersonateOnCreate,
  414. LPBOOL pbFilesMoved
  415. );
  416. BOOL
  417. CreateInternalDriverFileArray(
  418. IN DWORD Level,
  419. IN LPBYTE pDriverInfo,
  420. OUT PINTERNAL_DRV_FILE *pInternalDriverFiles,
  421. OUT LPDWORD pFileCount,
  422. IN BOOL bUseScratchDir,
  423. IN PINIENVIRONMENT pIniEnvironment,
  424. IN BOOL bFileNamesOnly
  425. );
  426. BOOL
  427. CheckFileCopyOptions(
  428. PINIENVIRONMENT pIniEnvironment,
  429. PINIVERSION pIniVersion,
  430. PINIDRIVER pIniDriver,
  431. PINTERNAL_DRV_FILE pInternalDriverFiles,
  432. DWORD dwFileCount,
  433. DWORD dwFileCopyFlags,
  434. LPBOOL pbUpgrade
  435. );
  436. /*++
  437. Routine Name
  438. FindIndexInDrvFileInfo
  439. Routine Description:
  440. Checks if a certain driver file is present in an DRIVER_FILE_INFO
  441. file set. The search is done by the type of the file. The index
  442. to the first occurence of the file is returned.
  443. Arguments:
  444. pDrvFileInfo - pointer to DRIVER_FILE_INFO array
  445. cElements - count of elements in pDrvFileInfo
  446. kFileType - file type to search for
  447. pIndex - on success contains the index of the found file in
  448. the pDrvFileInfo array
  449. Return Value:
  450. S_OK - the file was found and pIndex is usable
  451. S_FALSE - the file was not found, pIndex is not usable
  452. E_INVALIDARG - invalid arguments were passed in
  453. --*/
  454. HRESULT
  455. FindIndexInDrvFileInfo(
  456. IN DRIVER_FILE_INFO *pDrvFileInfo,
  457. IN DWORD cElements,
  458. IN DRIVER_FILE_TYPE kFileType,
  459. OUT DWORD *pIndex
  460. )
  461. {
  462. HRESULT hr = E_INVALIDARG;
  463. if (pDrvFileInfo && pIndex)
  464. {
  465. DWORD i;
  466. //
  467. // Not found
  468. //
  469. hr = S_FALSE;
  470. for (i = 0; i < cElements; i++)
  471. {
  472. if (pDrvFileInfo[i].FileType == kFileType)
  473. {
  474. *pIndex = i;
  475. hr = S_OK;
  476. break;
  477. }
  478. }
  479. }
  480. return hr;
  481. }
  482. BOOL
  483. LocalStartSystemRestorePoint(
  484. IN PCWSTR pszDriverName,
  485. OUT HANDLE *phRestorePoint
  486. );
  487. /*++
  488. Routine Name
  489. IsDriverInstalled
  490. Routine Description:
  491. Checks if a certain driver is already installed.
  492. Arguments:
  493. pDriver2 - pointer to DRIVER_INFO_2
  494. pIniSpooler - pointer to spooler structure
  495. Return Value:
  496. TRUE - driver is installed on the pIniSpooler
  497. FALSE - driver is not present in pIniSpooler
  498. --*/
  499. BOOL
  500. IsDriverInstalled(
  501. DRIVER_INFO_2 *pDriver2,
  502. PINISPOOLER pIniSpooler
  503. )
  504. {
  505. BOOL bReturn = FALSE;
  506. if (pIniSpooler &&
  507. pDriver2 &&
  508. pDriver2->pName)
  509. {
  510. PINIENVIRONMENT pIniEnv;
  511. PINIVERSION pIniVer;
  512. EnterSplSem();
  513. if ((pIniEnv = FindEnvironment(pDriver2->pEnvironment && *pDriver2->pEnvironment ?
  514. pDriver2->pEnvironment : szEnvironment,
  515. pIniSpooler)) &&
  516. (pIniVer = FindVersionEntry(pIniEnv, pDriver2->cVersion)) &&
  517. FindDriverEntry(pIniVer, pDriver2->pName))
  518. {
  519. bReturn = TRUE;
  520. }
  521. LeaveSplSem();
  522. }
  523. DBGMSG(DBG_CLUSTER, ("IsDriverInstalled returns %u\n", bReturn));
  524. return bReturn;
  525. }
  526. BOOL
  527. LocalAddPrinterDriver(
  528. LPWSTR pName,
  529. DWORD Level,
  530. LPBYTE pDriverInfo
  531. )
  532. {
  533. return LocalAddPrinterDriverEx( pName,
  534. Level,
  535. pDriverInfo,
  536. APD_COPY_NEW_FILES );
  537. }
  538. BOOL
  539. LocalAddPrinterDriverEx(
  540. LPWSTR pName,
  541. DWORD Level,
  542. LPBYTE pDriverInfo,
  543. DWORD dwFileCopyFlags
  544. )
  545. {
  546. PINISPOOLER pIniSpooler;
  547. BOOL bReturn = TRUE;
  548. if (Level == 7)
  549. {
  550. bReturn = FALSE;
  551. SetLastError(ERROR_INVALID_LEVEL);
  552. }
  553. else if (dwFileCopyFlags & APD_COPY_TO_ALL_SPOOLERS)
  554. {
  555. //
  556. // Mask flag otherwise SplAddPrinterDriverEx will be fail.
  557. // This flag is used by Windows Update to update all the
  558. // drivers for all the spoolers hosted by the local machine
  559. //
  560. dwFileCopyFlags = dwFileCopyFlags & ~APD_COPY_TO_ALL_SPOOLERS;
  561. for (pIniSpooler = pLocalIniSpooler;
  562. pIniSpooler && bReturn;
  563. pIniSpooler = pIniSpooler->pIniNextSpooler)
  564. {
  565. //
  566. // We do not want to add a driver to a pIniSpooler. We want to update
  567. // an existing driver. That is why we check if the driver is already
  568. // installed
  569. //
  570. if ((pIniSpooler->SpoolerFlags & SPL_TYPE_LOCAL ||
  571. pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER) &&
  572. IsDriverInstalled((DRIVER_INFO_2 *)pDriverInfo, pIniSpooler))
  573. {
  574. EnterSplSem();
  575. INCSPOOLERREF(pIniSpooler);
  576. LeaveSplSem();
  577. //
  578. // The 6th parameter indicates whether to use the scratch
  579. // directory (TRUE) or not (FALSE)
  580. //
  581. bReturn = SplAddPrinterDriverEx(pName,
  582. Level,
  583. pDriverInfo,
  584. dwFileCopyFlags,
  585. pIniSpooler,
  586. !(dwFileCopyFlags & APD_COPY_FROM_DIRECTORY),
  587. IMPERSONATE_USER);
  588. DBGMSG(DBG_CLUSTER, ("LocalAddPrinterDriverEx adding driver to "TSTR" bRet %u\n",
  589. pIniSpooler->pMachineName, bReturn));
  590. EnterSplSem();
  591. DECSPOOLERREF(pIniSpooler);
  592. LeaveSplSem();
  593. }
  594. }
  595. }
  596. else
  597. {
  598. if (!(pIniSpooler = FindSpoolerByNameIncRef(pName, NULL)))
  599. {
  600. return ROUTER_UNKNOWN;
  601. }
  602. else
  603. {
  604. //
  605. // The 6th parameter indicates whether to use the scratch
  606. // directory (TRUE) or not (FALSE)
  607. //
  608. bReturn = SplAddPrinterDriverEx(pName,
  609. Level,
  610. pDriverInfo,
  611. dwFileCopyFlags,
  612. pIniSpooler,
  613. !(dwFileCopyFlags & APD_COPY_FROM_DIRECTORY),
  614. IMPERSONATE_USER);
  615. }
  616. FindSpoolerByNameDecRef(pIniSpooler);
  617. }
  618. return bReturn;
  619. }
  620. BOOL
  621. SplAddPrinterDriverEx(
  622. LPWSTR pName,
  623. DWORD Level,
  624. LPBYTE pDriverInfo,
  625. DWORD dwFileCopyFlags,
  626. PINISPOOLER pIniSpooler,
  627. BOOL bUseScratchDir,
  628. BOOL bImpersonateOnCreate
  629. )
  630. {
  631. PINISPOOLER pTempIniSpooler = pIniSpooler;
  632. DBGMSG( DBG_TRACE, ("AddPrinterDriver\n"));
  633. if (!MyName( pName, pIniSpooler )) {
  634. return FALSE;
  635. }
  636. // Right now all drivers are global ie they are shared between all IniSpoolers
  637. // If we want to impersonate the user then lets validate against pLocalIniSpooler
  638. // whilch causes all the security checking to happen, rather than using the passed
  639. // in IniSpooler which might not. See win32spl for detail of point and print.
  640. if ( bImpersonateOnCreate ) {
  641. pTempIniSpooler = pLocalIniSpooler;
  642. }
  643. if ( !ValidateObjectAccess( SPOOLER_OBJECT_SERVER,
  644. SERVER_ACCESS_ADMINISTER,
  645. NULL, NULL, pTempIniSpooler)) {
  646. return FALSE;
  647. }
  648. return ( InternalAddPrinterDriverEx( pName,
  649. Level,
  650. pDriverInfo,
  651. dwFileCopyFlags,
  652. pIniSpooler,
  653. bUseScratchDir,
  654. bImpersonateOnCreate ) );
  655. }
  656. /*++
  657. SendDriverInfo7
  658. IN HANDLE hPipe - the handle to the pipe to send the data down.
  659. IN LPDRIVER_INFO_7 pDriverInfo7 - contains info to send
  660. Sends the Flags and the Driver info 7 information across the named pipe.
  661. Sending sequence: 1. Size of string to come for Driver name - there must be a driver name.
  662. 2. Driver name
  663. 3. Size of string to come for inf name - if there is no inf name, send 0 and jump to 5
  664. 4. inf name
  665. 5. Size of string to come for source name - if there is no source name, send 0 and complete
  666. 6. Source name
  667. --*/
  668. BOOL
  669. SendDriverInfo7(
  670. HANDLE hPipe,
  671. LPDRIVER_INFO_7 pDriverInfo7
  672. )
  673. {
  674. DWORD dwLength = wcslen(pDriverInfo7->pszDriverName);
  675. DWORD dwDontCare;
  676. DWORD dwLastError = ERROR_SUCCESS;
  677. OVERLAPPED Ov;
  678. ZeroMemory( &Ov,sizeof(Ov));
  679. if ( !(Ov.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL)) )
  680. {
  681. return FALSE;
  682. }
  683. //
  684. // Ensure that we have a connection at the other end.
  685. //
  686. if( !ConnectNamedPipe( hPipe, &Ov ))
  687. {
  688. dwLastError = GetLastError();
  689. if(!( dwLastError == ERROR_PIPE_CONNECTED || dwLastError == ERROR_IO_PENDING ))
  690. {
  691. if ( Ov.hEvent )
  692. CloseHandle(Ov.hEvent);
  693. return FALSE;
  694. }
  695. }
  696. //
  697. // Wait to connect as long as we're not connected already.
  698. //
  699. if( dwLastError != ERROR_PIPE_CONNECTED )
  700. {
  701. if( WaitForSingleObject(Ov.hEvent, gdwServerInstallTimeOut) == WAIT_TIMEOUT )
  702. {
  703. CancelIo(hPipe);
  704. WaitForSingleObject(Ov.hEvent, INFINITE);
  705. }
  706. if( !GetOverlappedResult(hPipe, &Ov, &dwDontCare, FALSE) )
  707. {
  708. if ( Ov.hEvent )
  709. CloseHandle(Ov.hEvent);
  710. return FALSE;
  711. }
  712. }
  713. if ( Ov.hEvent )
  714. CloseHandle(Ov.hEvent);
  715. //
  716. // Write the length of the Driver Name.
  717. //
  718. if(!WriteOverlapped( hPipe, &dwLength, sizeof(dwLength), &dwDontCare ))
  719. return FALSE;
  720. //
  721. // Write the driver name
  722. //
  723. if(!WriteOverlapped( hPipe, pDriverInfo7->pszDriverName, dwLength*sizeof(WCHAR), &dwDontCare ))
  724. return FALSE;
  725. if(pDriverInfo7->pszInfName)
  726. {
  727. dwLength = wcslen(pDriverInfo7->pszInfName);
  728. //
  729. // Write the length of the inf name.
  730. //
  731. if(!WriteOverlapped( hPipe, &dwLength, sizeof(dwLength), &dwDontCare ))
  732. return FALSE;
  733. //
  734. // Write the inf name
  735. //
  736. if(!WriteOverlapped( hPipe, pDriverInfo7->pszInfName, dwLength*sizeof(WCHAR), &dwDontCare ))
  737. return FALSE;
  738. }
  739. else
  740. {
  741. //
  742. // Write a 0 to say no inf name
  743. //
  744. dwLength = 0;
  745. if(!WriteOverlapped( hPipe, &dwLength, sizeof(dwLength), &dwDontCare ))
  746. return FALSE;
  747. }
  748. if(pDriverInfo7->pszInstallSourceRoot)
  749. {
  750. dwLength = wcslen(pDriverInfo7->pszInstallSourceRoot);
  751. //
  752. // Write the length of the install source root.
  753. //
  754. if(!WriteOverlapped( hPipe, &dwLength, sizeof(dwLength), &dwDontCare ))
  755. return FALSE;
  756. //
  757. // Write the install source root
  758. //
  759. if(!WriteOverlapped( hPipe, pDriverInfo7->pszInstallSourceRoot, dwLength*sizeof(WCHAR), &dwDontCare ))
  760. return FALSE;
  761. }
  762. else
  763. {
  764. //
  765. // Write a 0 to say no install source path.
  766. //
  767. dwLength = 0;
  768. if(!WriteOverlapped( hPipe, &dwLength, sizeof(dwLength), &dwDontCare ))
  769. return FALSE;
  770. }
  771. return TRUE;
  772. }
  773. DWORD
  774. GetPipeName(
  775. OUT LPWSTR *ppszPipe
  776. )
  777. {
  778. LPCWSTR pszPrefix = L"\\\\.\\pipe\\SRVINST";
  779. DWORD Error = ERROR_INVALID_PARAMETER;
  780. if (ppszPipe)
  781. {
  782. WCHAR ProcID[MAX_DWORD_LENGTH];
  783. WCHAR ThreadID[MAX_DWORD_LENGTH];
  784. *ppszPipe = NULL;
  785. _itow( GetCurrentProcessId(), ProcID, 10 );
  786. _itow( GetCurrentThreadId(), ThreadID, 10 );
  787. Error = StrCatAlloc(ppszPipe, pszPrefix, ProcID, ThreadID, NULL);
  788. }
  789. return Error;
  790. }
  791. /*++
  792. Description:
  793. This function creates a process for a driver to be installed in and launches an entry point
  794. from ntprint.dll to install the driver inside that process. This install will take a driver info 7
  795. struct and do an inf based install with the information in that structure.
  796. Arguments:
  797. pDriverInfo7 -- driver_info_7 structure
  798. Returns:
  799. TRUE on success; FALSE otherwise
  800. The function sets the last error in case of failure
  801. Notes:
  802. If the driver info pszInfName field is anything other than NULL, this call will fail.
  803. --*/
  804. BOOL
  805. InternalINFInstallDriver(
  806. LPDRIVER_INFO_7 pDriverInfo7
  807. )
  808. {
  809. DWORD Error = ERROR_INVALID_PARAMETER;
  810. LPWSTR pszPipe = NULL;
  811. //
  812. // Passing with an inf name is not supported.
  813. //
  814. if (!pDriverInfo7->pszInfName &&
  815. (Error = GetPipeName(&pszPipe)) == ERROR_SUCCESS)
  816. {
  817. LPWSTR pszCmdString = NULL;
  818. HANDLE hPipe = INVALID_HANDLE_VALUE;
  819. LPCWSTR pszRundllName = L"rundll32.exe";
  820. LPCWSTR pszRundllArgs = L"rundll32.exe ntprint.dll,ServerInstall 0 ";
  821. LPWSTR pszRundllPath = NULL;
  822. //
  823. // We use FILE_FLAG_FIRST_PIPE_INSTANCE to make sure we are the creator of the pipe.
  824. // Otherwise a malicious process could create the pipe first and exploit the
  825. // spooler connecting to it. CreateNamedPipe will fail with access denied if the
  826. // pipe was already created.
  827. //
  828. hPipe = CreateNamedPipe(pszPipe,
  829. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
  830. PIPE_TYPE_BYTE,
  831. PIPE_UNLIMITED_INSTANCES,
  832. 1024,
  833. 1024,
  834. NMPWAIT_USE_DEFAULT_WAIT,
  835. NULL);
  836. Error = hPipe != INVALID_HANDLE_VALUE ? ERROR_SUCCESS : GetLastError();
  837. if (Error == ERROR_SUCCESS &&
  838. (Error = StrCatAlloc(&pszCmdString,
  839. pszRundllArgs,
  840. pszPipe,
  841. NULL)) == ERROR_SUCCESS &&
  842. (Error = StrCatSystemPath(pszRundllName,
  843. kSystemDir,
  844. &pszRundllPath)) == ERROR_SUCCESS)
  845. {
  846. DWORD dwDontCare;
  847. PROCESS_INFORMATION ProcInfo;
  848. STARTUPINFO StartupInfo = {0};
  849. StartupInfo.cb = sizeof(StartupInfo);
  850. //
  851. // Now do the Process creation and wait for install to complete.
  852. //
  853. if (CreateProcess(pszRundllPath,
  854. pszCmdString,
  855. NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP, NULL, NULL,
  856. &StartupInfo,
  857. &ProcInfo))
  858. {
  859. if (SendDriverInfo7(hPipe, pDriverInfo7))
  860. {
  861. DWORD ReadError;
  862. //
  863. // Error receives the return code from the add driver operation
  864. // performed by the rundll process. ReadError indicates if
  865. // ReadOverlapped succeeded.
  866. //
  867. if ((ReadError = ReadOverlapped(hPipe,
  868. &Error,
  869. sizeof(Error),
  870. &dwDontCare)) != ERROR_SUCCESS)
  871. {
  872. Error = ReadError;
  873. }
  874. DisconnectNamedPipe(hPipe);
  875. }
  876. else
  877. {
  878. Error = GetLastError();
  879. }
  880. CloseHandle(ProcInfo.hProcess);
  881. CloseHandle(ProcInfo.hThread);
  882. }
  883. else
  884. {
  885. Error = GetLastError();
  886. }
  887. }
  888. if (hPipe != INVALID_HANDLE_VALUE) CloseHandle(hPipe);
  889. if (pszCmdString) FreeSplMem(pszCmdString);
  890. if (pszRundllPath) FreeSplMem(pszRundllPath);
  891. if (pszPipe) FreeSplMem(pszPipe);
  892. }
  893. if (Error != ERROR_SUCCESS)
  894. {
  895. SetLastError(Error);
  896. }
  897. return Error == ERROR_SUCCESS;
  898. }
  899. BOOL
  900. BuildTrueDependentFileField(
  901. LPWSTR pDriverPath,
  902. LPWSTR pDataFile,
  903. LPWSTR pConfigFile,
  904. LPWSTR pHelpFile,
  905. LPWSTR pInputDependentFiles,
  906. LPWSTR *ppDependentFiles
  907. )
  908. {
  909. LPWSTR psz, psz2;
  910. LPCWSTR pszFileNamePart;
  911. DWORD dwSize;
  912. if ( !pInputDependentFiles )
  913. return TRUE;
  914. for ( psz = pInputDependentFiles, dwSize = 0 ;
  915. psz && *psz ; psz += wcslen(psz) + 1 ) {
  916. pszFileNamePart = FindFileName(psz);
  917. if( !pszFileNamePart ){
  918. break;
  919. }
  920. if ( wstrcmpEx(FindFileName(pDriverPath), pszFileNamePart, FALSE) &&
  921. wstrcmpEx(FindFileName(pDataFile), pszFileNamePart, FALSE) &&
  922. wstrcmpEx(FindFileName(pConfigFile), pszFileNamePart, FALSE) &&
  923. wstrcmpEx(FindFileName(pHelpFile), pszFileNamePart, FALSE) ) {
  924. dwSize += wcslen(psz) + 1;
  925. }
  926. }
  927. if ( !dwSize )
  928. return TRUE;
  929. // for the last \0
  930. ++dwSize;
  931. *ppDependentFiles = AllocSplMem(dwSize*sizeof(WCHAR));
  932. if ( !*ppDependentFiles )
  933. return FALSE;
  934. psz = pInputDependentFiles;
  935. psz2 = *ppDependentFiles;
  936. while ( *psz ) {
  937. pszFileNamePart = FindFileName(psz);
  938. if( !pszFileNamePart ){
  939. break;
  940. }
  941. if ( wstrcmpEx(FindFileName(pDriverPath), pszFileNamePart, FALSE) &&
  942. wstrcmpEx(FindFileName(pDataFile), pszFileNamePart, FALSE) &&
  943. wstrcmpEx(FindFileName(pConfigFile), pszFileNamePart, FALSE) &&
  944. wstrcmpEx(FindFileName(pHelpFile), pszFileNamePart, FALSE) ) {
  945. wcscpy(psz2, psz);
  946. psz2 += wcslen(psz) + 1;
  947. }
  948. psz += wcslen(psz) + 1;
  949. }
  950. return TRUE;
  951. }
  952. DWORD
  953. IsCompatibleDriver(
  954. LPWSTR pszDriverName,
  955. LPWSTR pszDeviceDriverPath,
  956. LPWSTR pszEnvironment,
  957. DWORD dwMajorVersion,
  958. DWORD *pdwBlockingStatus
  959. )
  960. /*++
  961. Function Description: Call this function to prevent bad drivers from getting installed.
  962. Check if driver is listed in printupg.inf (lists all known bad driver files ).
  963. Since printupg.inf contains only driver name, this function should be called
  964. only for verions 2 drivers.
  965. Otherwise,it will treat a version 3 driver "DriverName" as bad,
  966. if it is a bad version 2 driver.
  967. Parameters: pszDriverName -- driver name
  968. pszDeviceDriverPath -- filename for the file that contains the device driver
  969. pszEnvironment -- environment string for the driver such as "Windows NT x86"
  970. dwMajorVersion -- major version of the driver
  971. pdwBlockingStatus -- driver blocking status
  972. Return Value: ERROR_SUCCESS if succeeded
  973. ERROR_INVALID_PARAMETER if invalid parameters
  974. GetLastError for any other errors
  975. --*/
  976. {
  977. WIN32_FIND_DATA DeviceDriverData;
  978. pfPSetupIsCompatibleDriver pfnPSetupIsCompatibleDriver;
  979. UINT uOldErrMode;
  980. HANDLE hFileExists = INVALID_HANDLE_VALUE;
  981. HANDLE hLibrary = NULL;
  982. DWORD LastError = ERROR_SUCCESS;
  983. DWORD dwBlockingStatus = BSP_PRINTER_DRIVER_OK;
  984. uOldErrMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  985. if( !pszDriverName || !pszDeviceDriverPath || !pszEnvironment ||
  986. !*pszDriverName || !*pszDeviceDriverPath || !*pszEnvironment || !pdwBlockingStatus) {
  987. LastError = ERROR_INVALID_PARAMETER;
  988. goto End;
  989. }
  990. *pdwBlockingStatus = BSP_PRINTER_DRIVER_OK;
  991. hFileExists = FindFirstFile( pszDeviceDriverPath, &DeviceDriverData );
  992. if (hFileExists == INVALID_HANDLE_VALUE) {
  993. LastError = GetLastError();
  994. goto End;
  995. }
  996. if( !(hLibrary = LoadLibrary( TEXT("ntprint.dll"))) ){
  997. LastError = GetLastError();
  998. goto End;
  999. }
  1000. pfnPSetupIsCompatibleDriver = (pfPSetupIsCompatibleDriver)GetProcAddress( hLibrary, "PSetupIsCompatibleDriver" );
  1001. if( !pfnPSetupIsCompatibleDriver){
  1002. LastError = GetLastError();
  1003. goto End;
  1004. }
  1005. //
  1006. // NULL server name is OK since we know this is the local machine.
  1007. // PSetupIsCompatibleDriver uses this to determine the blocking
  1008. // level.
  1009. //
  1010. if ((pfnPSetupIsCompatibleDriver)( NULL,
  1011. pszDriverName,
  1012. pszDeviceDriverPath,
  1013. pszEnvironment,
  1014. dwMajorVersion,
  1015. &DeviceDriverData.ftLastWriteTime,
  1016. &dwBlockingStatus,
  1017. NULL)) {
  1018. *pdwBlockingStatus = dwBlockingStatus;
  1019. } else {
  1020. LastError = GetLastError();
  1021. }
  1022. End:
  1023. if( hFileExists != INVALID_HANDLE_VALUE ){
  1024. FindClose(hFileExists);
  1025. }
  1026. if( hLibrary ){
  1027. FreeLibrary( hLibrary );
  1028. }
  1029. SetErrorMode( uOldErrMode );
  1030. return LastError;
  1031. }
  1032. BOOL
  1033. IsAnICMFile(
  1034. LPCWSTR pszFileName
  1035. )
  1036. /*++
  1037. Function Description: Checks for ICM extension on the filename
  1038. Parameters: pszFileName - file name
  1039. Return Values: TRUE for ICM files; FALSE otherwise
  1040. --*/
  1041. {
  1042. DWORD dwLen = wcslen(pszFileName);
  1043. LPWSTR psz = (LPWSTR)pszFileName+dwLen-4;
  1044. if ( dwLen > 3 &&
  1045. ( !_wcsicmp(psz, L".ICM") || !_wcsicmp(psz, L".ICC")) )
  1046. return TRUE;
  1047. return FALSE;
  1048. }
  1049. BOOL
  1050. ValidateDriverInfo(
  1051. IN LPBYTE pDriverInfo,
  1052. IN DWORD Level,
  1053. IN DWORD dwFileCopyFlags,
  1054. IN BOOL bCopyFilesToClusterDisk,
  1055. IN PINISPOOLER pIniSpooler
  1056. )
  1057. /*++
  1058. Routine Name:
  1059. ValidateDriverInfo
  1060. Routine Description:
  1061. Validates information contained in a buffer depending on level and
  1062. file copy flags.
  1063. Arguments:
  1064. pDriverInfo - pointer to a buffer containing DRIVER_INFO_ data.
  1065. Level - 2, 3 ,4 ,6 , 7, DRIVER_INFO_VERSION_LEVEL
  1066. dwFileCopyFlags - file copy flags
  1067. bCopyFilesToClusterDisk - cluster flags
  1068. pIniSpooler - pointer to Spooler structure
  1069. Return Value:
  1070. TRUE if the structure is valid.
  1071. --*/
  1072. {
  1073. BOOL bRetValue = FALSE;
  1074. DWORD LastError = ERROR_SUCCESS;
  1075. LPWSTR pszDriverName = NULL;
  1076. LPWSTR pszDriverPath = NULL;
  1077. LPWSTR pszConfigFile = NULL;
  1078. LPWSTR pszDataFile = NULL;
  1079. LPWSTR pszEnvironment = NULL;
  1080. LPWSTR pszMonitorName = NULL;
  1081. LPWSTR pszDefaultDataType = NULL;
  1082. DWORD dwMajorVersion;
  1083. PDRIVER_INFO_2 pDriver2 = NULL;
  1084. PDRIVER_INFO_3 pDriver3 = NULL;
  1085. PDRIVER_INFO_VERSION pDriverVersion = NULL;
  1086. PINIENVIRONMENT pIniEnvironment = NULL;
  1087. PINIMONITOR pIniLangMonitor = NULL;
  1088. try {
  1089. if (!pDriverInfo)
  1090. {
  1091. LastError = ERROR_INVALID_PARAMETER;
  1092. leave;
  1093. }
  1094. switch (Level)
  1095. {
  1096. case 2:
  1097. {
  1098. pDriver2 = (PDRIVER_INFO_2) pDriverInfo;
  1099. pszDriverName = pDriver2->pName;
  1100. pszDriverPath = pDriver2->pDriverPath;
  1101. pszConfigFile = pDriver2->pConfigFile;
  1102. pszDataFile = pDriver2->pDataFile;
  1103. dwMajorVersion = pDriver2->cVersion;
  1104. if (pDriver2->pEnvironment && *pDriver2->pEnvironment)
  1105. {
  1106. pszEnvironment = pDriver2->pEnvironment;
  1107. }
  1108. break;
  1109. }
  1110. case 3:
  1111. case 4:
  1112. case 6:
  1113. {
  1114. pDriver3 = (PDRIVER_INFO_3) pDriverInfo;
  1115. pszDriverName = pDriver3->pName;
  1116. pszDriverPath = pDriver3->pDriverPath;
  1117. pszConfigFile = pDriver3->pConfigFile;
  1118. pszDataFile = pDriver3->pDataFile;
  1119. dwMajorVersion = pDriver3->cVersion;
  1120. pszMonitorName = pDriver3->pMonitorName;
  1121. pszDefaultDataType = pDriver3->pDefaultDataType;
  1122. if (pDriver3->pEnvironment && *pDriver3->pEnvironment)
  1123. {
  1124. pszEnvironment = pDriver3->pEnvironment;
  1125. }
  1126. break;
  1127. }
  1128. case 7:
  1129. {
  1130. LPDRIVER_INFO_7 pDriverInfo7 = (LPDRIVER_INFO_7)pDriverInfo;
  1131. if (!pDriverInfo7 ||
  1132. pDriverInfo7->cbSize < sizeof(DRIVER_INFO_7)||
  1133. !pDriverInfo7->pszDriverName ||
  1134. !*pDriverInfo7->pszDriverName ||
  1135. wcslen(pDriverInfo7->pszDriverName) >= MAX_PATH)
  1136. {
  1137. LastError = ERROR_INVALID_PARAMETER;
  1138. }
  1139. //
  1140. // We don't want to do any more of the validation below, so leave.
  1141. //
  1142. leave;
  1143. break;
  1144. }
  1145. case DRIVER_INFO_VERSION_LEVEL:
  1146. {
  1147. pDriverVersion = (LPDRIVER_INFO_VERSION)pDriverInfo;
  1148. pszDriverName = pDriverVersion->pName;
  1149. if (!GetFileNamesFromDriverVersionInfo(pDriverVersion,
  1150. &pszDriverPath,
  1151. &pszConfigFile,
  1152. &pszDataFile,
  1153. NULL))
  1154. {
  1155. LastError = ERROR_INVALID_PARAMETER;
  1156. leave;
  1157. }
  1158. if (pDriverVersion->pEnvironment != NULL &&
  1159. *pDriverVersion->pEnvironment != L'\0')
  1160. {
  1161. pszEnvironment = pDriverVersion->pEnvironment;
  1162. }
  1163. pszMonitorName = pDriverVersion->pMonitorName;
  1164. pszDefaultDataType = pDriverVersion->pDefaultDataType;
  1165. dwMajorVersion = pDriverVersion->cVersion;
  1166. pszDriverName = pDriverVersion->pName;
  1167. break;
  1168. }
  1169. default:
  1170. {
  1171. LastError = ERROR_INVALID_LEVEL;
  1172. leave;
  1173. }
  1174. }
  1175. //
  1176. // Validate driver name, driver file, config file and data file.
  1177. //
  1178. if ( !pszDriverName || !*pszDriverName || wcslen(pszDriverName) >= MAX_PATH ||
  1179. !pszDriverPath || !*pszDriverPath || wcslen(pszDriverPath) >= MAX_PATH ||
  1180. !pszConfigFile || !*pszConfigFile || wcslen(pszConfigFile) >= MAX_PATH ||
  1181. !pszDataFile || !*pszDataFile || wcslen(pszDataFile) >= MAX_PATH )
  1182. {
  1183. LastError = ERROR_INVALID_PARAMETER;
  1184. leave;
  1185. }
  1186. //
  1187. // We don't use Scratch directory when this flag is set.
  1188. // When APD_COPY_FROM_DIRECTORY is set, the temporay directory must
  1189. // be on the local machine.
  1190. // IsLocalFile checks is the file is on the same machine specified by
  1191. // the passed in spooler.
  1192. //
  1193. if (dwFileCopyFlags & APD_COPY_FROM_DIRECTORY)
  1194. {
  1195. if (!IsLocalFile(pszDriverPath, pIniSpooler) ||
  1196. !IsLocalFile(pszConfigFile, pIniSpooler))
  1197. {
  1198. LastError = ERROR_INVALID_PARAMETER;
  1199. leave;
  1200. }
  1201. }
  1202. //
  1203. // Validate default data type (except for Win95 drivers)
  1204. //
  1205. if ( pszDefaultDataType &&
  1206. *pszDefaultDataType &&
  1207. _wcsicmp(pszEnvironment, szWin95Environment) &&
  1208. !FindDatatype(NULL, pszDefaultDataType))
  1209. {
  1210. LastError = ERROR_INVALID_DATATYPE;
  1211. leave;
  1212. }
  1213. //
  1214. // Validate monitor name (except for Win95 drivers)
  1215. //
  1216. if ( pszMonitorName &&
  1217. *pszMonitorName &&
  1218. _wcsicmp(pszEnvironment, szWin95Environment))
  1219. {
  1220. //
  1221. // Out driver is not a Win9x driver and it has a language monitor
  1222. //
  1223. if (pIniLangMonitor = FindMonitor(pszMonitorName, pLocalIniSpooler))
  1224. {
  1225. //
  1226. // Check if our pIniSpooler is a cluster spooler and we need to copy the
  1227. // language monitor file to disk. Note that FinEnvironment cannot fail.
  1228. // The environment has been validated by now.
  1229. //
  1230. if (bCopyFilesToClusterDisk &&
  1231. (pIniEnvironment = FindEnvironment(pszEnvironment, pIniSpooler)))
  1232. {
  1233. DBGMSG(DBG_CLUSTER, ("InternalAddPrinterDriverEx pIniLangMonitor = %x\n", pIniLangMonitor));
  1234. if ((LastError = PropagateMonitorToCluster(pIniLangMonitor->pName,
  1235. pIniLangMonitor->pMonitorDll,
  1236. pIniEnvironment->pName,
  1237. pIniEnvironment->pDirectory,
  1238. pIniSpooler)) != ERROR_SUCCESS)
  1239. {
  1240. //
  1241. // We failed to propagate the montior to the cluster disk. Fail the call
  1242. //
  1243. leave;
  1244. }
  1245. }
  1246. }
  1247. else
  1248. {
  1249. DBGMSG(DBG_CLUSTER, ("InternalAddPrinterDriverEx pIniLangMonitor = %x Not found\n", pIniLangMonitor));
  1250. LastError = ERROR_UNKNOWN_PRINT_MONITOR;
  1251. leave;
  1252. }
  1253. }
  1254. //
  1255. // Validate environment.
  1256. //
  1257. SPLASSERT(pszEnvironment != NULL);
  1258. if (!FindEnvironment(pszEnvironment, pIniSpooler))
  1259. {
  1260. LastError = ERROR_INVALID_ENVIRONMENT;
  1261. leave;
  1262. }
  1263. } finally {
  1264. if (LastError != ERROR_SUCCESS)
  1265. {
  1266. SetLastError(LastError);
  1267. }
  1268. else
  1269. {
  1270. bRetValue = TRUE;
  1271. }
  1272. }
  1273. return bRetValue;
  1274. }
  1275. BOOL
  1276. InternalAddPrinterDriverEx(
  1277. LPWSTR pName,
  1278. DWORD Level,
  1279. LPBYTE pDriverInfo,
  1280. DWORD dwFileCopyFlags,
  1281. PINISPOOLER pIniSpooler,
  1282. BOOL bUseScratchDir,
  1283. BOOL bImpersonateOnCreate
  1284. )
  1285. /*++
  1286. Function Description: This function adds/upgrades printer drivers. The new files may not be
  1287. used until the old drivers are unloaded. Thus the new functionality
  1288. associated with the new files may take a while to show up; either until
  1289. the DC count in the system goes to 0 or when the machine is rebooted.
  1290. Parameters: pName -- driver name
  1291. Level -- level of driver_info struct
  1292. pDriverInfo -- driver_info buffer
  1293. dwFileCopyFlags -- file copy options
  1294. pIniSpooler -- pointer to INISPOOLER struct
  1295. bUseScratchDir -- flag indicating location of the driver files
  1296. bImpersonateOnCreate -- flag for impersonating the client on creating and
  1297. moving files
  1298. Return Value: TRUE on success; FALSE otherwise
  1299. --*/
  1300. {
  1301. DWORD LastError = ERROR_SUCCESS;
  1302. BOOL bReturnValue = FALSE;
  1303. BOOL bDriverMoved = FALSE, bNewIniDriverCreated = FALSE;
  1304. LPWSTR pEnvironment = szEnvironment;
  1305. PINTERNAL_DRV_FILE pInternalDriverFiles = NULL;
  1306. DWORD dwMajorVersion;
  1307. PINIDRIVER pIniDriver = NULL;
  1308. PINIENVIRONMENT pIniEnvironment;
  1309. PINIVERSION pIniVersion;
  1310. LPWSTR pszDriverPath;
  1311. LPWSTR pszDriverName;
  1312. DWORD dwBlockingStatus = BSP_PRINTER_DRIVER_OK;
  1313. BOOL bCopyFilesToClusterDisk;
  1314. BOOL bBadDriver = FALSE;
  1315. HANDLE hRestorePoint = NULL;
  1316. BOOL bSetSystemRestorePoint = FALSE;
  1317. BOOL bIsSystemRestorePointSet = FALSE;
  1318. DWORD FileCount = 0;
  1319. //
  1320. // If the pIniSpooler where we add the driver is a cluster type spooler,
  1321. // then besides its normal tasks, it also needs to propagte the driver
  1322. // files to the cluster disk. Thus the driver files will be available
  1323. // on each node where the cluster spooler fails over. SplAddPrinterDriverEx
  1324. // is the function that calls this one. SplAddPrinterDriverEx can be called
  1325. // in 2 types of context:
  1326. // 1) The caller is cluster unaware and wants to add a driver. Then InternalAdd
  1327. // PrinterDriverEX will propagate driver files to the cluster disk, if the
  1328. // pIniSpooler happens to be of cluster type
  1329. // 2) The caller of this function is SplCreateSpooler when pIniSpooler is a
  1330. // cluster spooler. In this case that caller uses the files on the cluster
  1331. // disk and calls the function to add the driver from the cluster disk to the
  1332. // local node. The driver files will be installed on the local machine. They will
  1333. // not be shared with the pLocalIniSpooler. We need the driver files locally.
  1334. // We can't load them off the driver disk. Otherwise, on a fail over, apps
  1335. // who loaded a driver file will get an in page error.
  1336. // The following flag is used to distinguish the case 2). When SplCreateSpooler
  1337. // is the caller of SplAddPrinterDriverEx, then we do not need to copy the files
  1338. // to the disk. It would be redundant.
  1339. //
  1340. bCopyFilesToClusterDisk = pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER &&
  1341. pIniSpooler->SpoolerFlags & SPL_PRINT &&
  1342. !(dwFileCopyFlags & APD_DONT_COPY_FILES_TO_CLUSTER);
  1343. //
  1344. // We want to set a system restore point unless the installer has already told
  1345. // us that the driver is signed. To really get this working properly, we would
  1346. // have to redesign AddPrinterDriver to be signing aware. For now it is the
  1347. // honor system (it is not obvious why an OEM installer would not want us to
  1348. // check point here though).
  1349. //
  1350. bSetSystemRestorePoint = !bCopyFilesToClusterDisk && !(dwFileCopyFlags & APD_DONT_SET_CHECKPOINT);
  1351. //
  1352. // We mask APD_DONT_COPY_FILES_TO_CLUSTER. The subsequent uses of dwFilecopyFlags exptect it
  1353. // to have a single bit set. They don't use it bitwise. They compare
  1354. // dwords agains it. The same goes for APD_DRIVER_SIGNATURE_VALID.
  1355. //
  1356. dwFileCopyFlags = dwFileCopyFlags & ~(APD_DONT_COPY_FILES_TO_CLUSTER);
  1357. DBGMSG(DBG_TRACE, ("InternalAddPrinterDriverEx( %x, %d, %x, %x)\n",
  1358. pName, Level, pDriverInfo, pIniSpooler));
  1359. try {
  1360. EnterSplSem();
  1361. if (!MyName(pName, pIniSpooler) ||
  1362. !ValidateDriverInfo(pDriverInfo,
  1363. Level,
  1364. dwFileCopyFlags,
  1365. bCopyFilesToClusterDisk,
  1366. pIniSpooler))
  1367. {
  1368. leave;
  1369. }
  1370. if (Level == 7)
  1371. {
  1372. //
  1373. // We can't be inside the semaphore to make this call.
  1374. //
  1375. LeaveSplSem();
  1376. bReturnValue = InternalINFInstallDriver( (DRIVER_INFO_7*)pDriverInfo );
  1377. EnterSplSem();
  1378. leave;
  1379. }
  1380. pszDriverName = ((DRIVER_INFO_2*)pDriverInfo)->pName;
  1381. pEnvironment = ((DRIVER_INFO_2*)pDriverInfo)->pEnvironment;
  1382. //
  1383. // If the driver hasn't gone through our class installer, then we want to
  1384. // create a sysem restore point here. Since Level 7 drivers are by
  1385. // definition signed, we can do this after the InternalINFInstallDriver.
  1386. // Since check-pointing takes from 25-30 seconds, this must take place
  1387. // outside the CS.
  1388. //
  1389. if (bSetSystemRestorePoint)
  1390. {
  1391. LeaveSplSem();
  1392. bIsSystemRestorePointSet = LocalStartSystemRestorePoint(pszDriverName, &hRestorePoint);
  1393. EnterSplSem();
  1394. //
  1395. // This only fails if something completely unexpected happens in
  1396. // setting the checkpoint. Some skus don't support check points
  1397. // in which case hRestorePoint will be NULL even though the function
  1398. // succeeds.
  1399. //
  1400. if (!bIsSystemRestorePointSet)
  1401. {
  1402. leave;
  1403. }
  1404. }
  1405. pIniEnvironment = FindEnvironment(pEnvironment, pIniSpooler );
  1406. if (!CreateInternalDriverFileArray(Level,
  1407. pDriverInfo,
  1408. &pInternalDriverFiles,
  1409. &FileCount,
  1410. bUseScratchDir,
  1411. pIniEnvironment,
  1412. FALSE))
  1413. {
  1414. leave;
  1415. }
  1416. //
  1417. // For the driver and config files in the scratch directory do a version
  1418. // check else use the version passed in rather than calling
  1419. // GetPrintDriverVersion which will cause a LoadLibrary - possibly
  1420. // over the network.
  1421. // Same for CheckFilePlatform. We shouldn't hit the network for files
  1422. // in Scratch or temporary directory.
  1423. //
  1424. //
  1425. if (bUseScratchDir || dwFileCopyFlags & APD_COPY_FROM_DIRECTORY)
  1426. {
  1427. if (!GetPrintDriverVersion(pInternalDriverFiles[0].pFileName,
  1428. &dwMajorVersion,
  1429. NULL))
  1430. {
  1431. leave;
  1432. }
  1433. else
  1434. {
  1435. //
  1436. // ntprint.dll doesn't fill in cVersion. We need to set it correctly
  1437. // just in case we need to call Save/RestoreParametersForUpgrade.
  1438. // For this case we need to have a corect version since no more validation are done.
  1439. //
  1440. ((DRIVER_INFO_2*)pDriverInfo)->cVersion = dwMajorVersion;
  1441. }
  1442. if (!CheckFilePlatform(pInternalDriverFiles[0].pFileName, pEnvironment) ||
  1443. !CheckFilePlatform(pInternalDriverFiles[1].pFileName, pEnvironment))
  1444. {
  1445. LastError = ERROR_EXE_MACHINE_TYPE_MISMATCH;
  1446. leave;
  1447. }
  1448. }
  1449. else
  1450. {
  1451. dwMajorVersion = ((DRIVER_INFO_2*)pDriverInfo)->cVersion;
  1452. }
  1453. LeaveSplSem();
  1454. LastError = IsCompatibleDriver(pszDriverName,
  1455. pInternalDriverFiles[0].pFileName,
  1456. ((DRIVER_INFO_2*)pDriverInfo)->pEnvironment,
  1457. dwMajorVersion,
  1458. &dwBlockingStatus);
  1459. EnterSplSem();
  1460. if (LastError != ERROR_SUCCESS)
  1461. {
  1462. leave;
  1463. }
  1464. //
  1465. // If the printer driver is blocked, we consider it a bad driver.
  1466. //
  1467. bBadDriver = (dwBlockingStatus & BSP_BLOCKING_LEVEL_MASK) == BSP_PRINTER_DRIVER_BLOCKED;
  1468. if (bBadDriver)
  1469. {
  1470. LastError = ERROR_PRINTER_DRIVER_BLOCKED;
  1471. }
  1472. //
  1473. // if the driver is not blocked and we are not instructed to install
  1474. // warned driver, check for warned driver.
  1475. //
  1476. if(!bBadDriver && !(dwFileCopyFlags & APD_INSTALL_WARNED_DRIVER))
  1477. {
  1478. bBadDriver = (dwBlockingStatus & BSP_BLOCKING_LEVEL_MASK) == BSP_PRINTER_DRIVER_WARNED;
  1479. if (bBadDriver)
  1480. {
  1481. LastError = ERROR_PRINTER_DRIVER_WARNED;
  1482. }
  1483. }
  1484. if (bBadDriver)
  1485. {
  1486. //
  1487. // Win2k server does not recognize the new error code so we should
  1488. // returns ERROR_UNKNOWN_PRINTER_DRIVER to get the right error
  1489. // message on win2k and nt4.
  1490. //
  1491. // Client from Whistler or later will set
  1492. // APD_RETURN_BLOCKING_STATUS_CODE before call AddPrinterDrver
  1493. //
  1494. if (!(dwFileCopyFlags & APD_RETURN_BLOCKING_STATUS_CODE))
  1495. {
  1496. LastError = ERROR_UNKNOWN_PRINTER_DRIVER;
  1497. }
  1498. SplLogEvent(pIniSpooler,
  1499. LOG_ERROR,
  1500. MSG_BAD_OEM_DRIVER,
  1501. TRUE,
  1502. pszDriverName,
  1503. NULL);
  1504. leave;
  1505. }
  1506. #ifdef _WIN64
  1507. //
  1508. // Disallow installation of WIN64 KMPD.
  1509. //
  1510. if (pEnvironment &&
  1511. !_wcsicmp(LOCAL_ENVIRONMENT, pEnvironment) &&
  1512. IsKMPD(pInternalDriverFiles[0].pFileName))
  1513. {
  1514. LastError = ERROR_KM_DRIVER_BLOCKED;
  1515. leave;
  1516. }
  1517. #endif
  1518. pIniVersion = FindVersionEntry( pIniEnvironment, dwMajorVersion );
  1519. if (pIniVersion == NULL)
  1520. {
  1521. pIniVersion = CreateVersionEntry(pIniEnvironment,
  1522. dwMajorVersion,
  1523. pIniSpooler);
  1524. if (pIniVersion == NULL)
  1525. {
  1526. leave;
  1527. }
  1528. }
  1529. else
  1530. {
  1531. //
  1532. // Version exists, try and create directory even if it
  1533. // exists. This is a slight performance hit, but since you
  1534. // install drivers rarely, this is ok. This fixes the problem
  1535. // where the version directory is accidentally deleted.
  1536. //
  1537. if (!CreateVersionDirectory(pIniVersion,
  1538. pIniEnvironment,
  1539. FALSE,
  1540. pIniSpooler))
  1541. {
  1542. leave;
  1543. }
  1544. }
  1545. //
  1546. // Check for existing driver
  1547. //
  1548. pIniDriver = FindDriverEntry(pIniVersion, pszDriverName);
  1549. //
  1550. // Clear this flag since subsequent calls doesn't check bitwise.
  1551. //
  1552. dwFileCopyFlags &= ~(APD_COPY_FROM_DIRECTORY | APD_INSTALL_WARNED_DRIVER | APD_RETURN_BLOCKING_STATUS_CODE | APD_DONT_SET_CHECKPOINT);
  1553. if (!CheckFileCopyOptions(pIniEnvironment,
  1554. pIniVersion,
  1555. pIniDriver,
  1556. pInternalDriverFiles,
  1557. FileCount,
  1558. dwFileCopyFlags,
  1559. &bReturnValue))
  1560. {
  1561. //
  1562. // We don't need to do anything because either the operation
  1563. // failed (strict upgrade with older src files), or because
  1564. // it's an upgrade and the dest is newer. bReturnValue indicates
  1565. // if the AddPrinterDriver call succeeds.
  1566. //
  1567. leave;
  1568. }
  1569. //
  1570. // Copy files to the correct directories
  1571. //
  1572. if (!CopyFilesToFinalDirectory(pIniSpooler,
  1573. pIniEnvironment,
  1574. pIniVersion,
  1575. pInternalDriverFiles,
  1576. FileCount,
  1577. dwFileCopyFlags,
  1578. bImpersonateOnCreate,
  1579. &bDriverMoved))
  1580. {
  1581. leave;
  1582. }
  1583. //
  1584. // If pIniSpooler is a cluster spooler, then copy driver files to cluster disk
  1585. // if the driver is not being installed from the cluster disk (as part of the
  1586. // SplCreatespooler)
  1587. //
  1588. if (bCopyFilesToClusterDisk)
  1589. {
  1590. LastError = CopyFileToClusterDirectory(pIniSpooler,
  1591. pIniEnvironment,
  1592. pIniVersion,
  1593. pInternalDriverFiles,
  1594. FileCount);
  1595. if (LastError == ERROR_SUCCESS)
  1596. {
  1597. //
  1598. // Here we propagate the ICM profiles to the cluster disk
  1599. //
  1600. CopyICMFromLocalDiskToClusterDisk(pIniSpooler);
  1601. }
  1602. else
  1603. {
  1604. leave;
  1605. }
  1606. }
  1607. //
  1608. // Check if the drivers need to be unloaded
  1609. // WaitRequiredForDriverUnload returns TRUE if the driver is loaded by Spooler process.
  1610. // If not loaded by Spooler itself, the config file could be loaded by any client app.
  1611. // In this case we move the loaded files in "Old" directory. When reload the confing file,
  1612. // the client apps(WINSPOOL.DRV) will figure that the driver was upgraded and reload the dll.
  1613. // See RefCntLoad and RefCntUnload in Winspool.drv. GDI32.DLL uses the same mechanism for
  1614. // Driver file.
  1615. //
  1616. if (WaitRequiredForDriverUnload(pIniSpooler,
  1617. pIniEnvironment,
  1618. pIniVersion,
  1619. pIniDriver,
  1620. Level,
  1621. pDriverInfo,
  1622. dwFileCopyFlags,
  1623. pInternalDriverFiles,
  1624. FileCount,
  1625. dwMajorVersion,
  1626. bDriverMoved,
  1627. &bReturnValue) &&
  1628. bReturnValue)
  1629. {
  1630. if (pIniDriver)
  1631. {
  1632. //
  1633. // Store information in the registry to complete the call later
  1634. //
  1635. bReturnValue = SaveParametersForUpgrade(pIniSpooler->pMachineName, bDriverMoved,
  1636. Level, pDriverInfo, dwMajorVersion);
  1637. leave;
  1638. }
  1639. else
  1640. {
  1641. //
  1642. // Add driver in a temp directory
  1643. //
  1644. bReturnValue = AddTempDriver(pIniSpooler,
  1645. pIniEnvironment,
  1646. pIniVersion,
  1647. Level,
  1648. pDriverInfo,
  1649. dwFileCopyFlags,
  1650. pInternalDriverFiles,
  1651. FileCount,
  1652. dwMajorVersion,
  1653. bDriverMoved
  1654. );
  1655. leave;
  1656. }
  1657. }
  1658. } finally {
  1659. //
  1660. // This code is only for clusters
  1661. //
  1662. if (bReturnValue && pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER)
  1663. {
  1664. SYSTEMTIME SysTime = {0};
  1665. if (bCopyFilesToClusterDisk)
  1666. {
  1667. //
  1668. // We are in the case where the add printer driver call comes from outside
  1669. // the spooler. We need to get the local time and write the time stamp in the
  1670. // locl regsitry and in the cluster database
  1671. //
  1672. GetLocalTime(&SysTime);
  1673. //
  1674. // Write timestamp to registry. Doesn't matter if any of them fails
  1675. // The time stamp is for faster cluster spooler initialization
  1676. //
  1677. WriteTimeStamp(pIniSpooler->hckRoot,
  1678. SysTime,
  1679. pIniSpooler->pszRegistryEnvironments,
  1680. pIniEnvironment->pName,
  1681. szDriversKey,
  1682. pIniVersion->pName,
  1683. pszDriverName,
  1684. pIniSpooler);
  1685. }
  1686. else
  1687. {
  1688. //
  1689. // We are in the case where the add printer driver call came from inside
  1690. // the spooler (SplCreateSpooler). This is the case when our local node
  1691. // doesn't already have the driver installed. We do not need to get a new
  1692. // time stamp. (this would case the time stamp in the cluster db to be updated,
  1693. // and then whenever we fail over the time stamps will be always different)
  1694. // We just get the time stamp from the cluster db and update the local registry
  1695. //
  1696. ReadTimeStamp(pIniSpooler->hckRoot,
  1697. &SysTime,
  1698. pIniSpooler->pszRegistryEnvironments,
  1699. pIniEnvironment->pName,
  1700. szDriversKey,
  1701. pIniVersion->pName,
  1702. pszDriverName,
  1703. pIniSpooler);
  1704. }
  1705. WriteTimeStamp(HKEY_LOCAL_MACHINE,
  1706. SysTime,
  1707. ipszRegistryClusRepository,
  1708. pIniSpooler->pszClusResID,
  1709. pIniEnvironment->pName,
  1710. pIniVersion->pName,
  1711. pszDriverName,
  1712. NULL);
  1713. }
  1714. if (!bReturnValue && LastError == ERROR_SUCCESS)
  1715. {
  1716. LastError = GetLastError();
  1717. //
  1718. // We failed the call because bDriverMoved was FALSE and the driver was loaded
  1719. //
  1720. if(LastError == ERROR_SUCCESS && !bDriverMoved)
  1721. {
  1722. LastError = ERROR_NO_SYSTEM_RESOURCES;
  1723. }
  1724. SPLASSERT(LastError != ERROR_SUCCESS);
  1725. }
  1726. if (bUseScratchDir && FileCount)
  1727. {
  1728. SetOldDateOnDriverFilesInScratchDirectory(pInternalDriverFiles,
  1729. FileCount,
  1730. pIniSpooler);
  1731. }
  1732. LeaveSplSem();
  1733. if (FileCount)
  1734. {
  1735. CleanupInternalDriverInfo(pInternalDriverFiles, FileCount);
  1736. }
  1737. CleanUpgradeDirectories();
  1738. //
  1739. // End the system restore point once everything is done. Cancel it if the
  1740. // function fails.
  1741. //
  1742. if (hRestorePoint)
  1743. {
  1744. (VOID)EndSystemRestorePoint(hRestorePoint, !bReturnValue);
  1745. }
  1746. if (!bReturnValue)
  1747. {
  1748. DBGMSG( DBG_WARNING, ("InternalAddPrinterDriver Failed %d\n", LastError ));
  1749. SetLastError(LastError);
  1750. }
  1751. }
  1752. return bReturnValue;
  1753. }
  1754. BOOL
  1755. AddTempDriver(
  1756. IN PINISPOOLER pIniSpooler,
  1757. IN PINIENVIRONMENT pIniEnvironment,
  1758. IN PINIVERSION pIniVersion,
  1759. IN DWORD dwLevel,
  1760. IN LPBYTE pDriverInfo,
  1761. IN DWORD dwFileCopyFlags,
  1762. IN OUT PINTERNAL_DRV_FILE pInternalDriverFiles,
  1763. IN DWORD dwFileCount,
  1764. IN DWORD dwVersion,
  1765. IN BOOL bDriverMoved
  1766. )
  1767. /*++
  1768. Function Description: For new drivers which require driver files to be unloaded,
  1769. add the driver into a temp directory and mark it for upgrade on
  1770. reboot OR when the files are unloaded
  1771. Parameters: pIniSpooler -- pointer to INISPOOLER
  1772. pIniEnvironment -- pointer to INIENVIRONMENT
  1773. pIniVersion -- pointer to INVERSION
  1774. dwLevel -- driver_info level
  1775. pDriverInfo -- pointer to driver_info
  1776. dwFileCopyFlags -- File copy flags that make it to the spooler
  1777. pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  1778. dwFileCount -- number of files in file set
  1779. dwVersion -- driver version
  1780. bDriverMoved -- Were any files moved to the Old directory ?
  1781. Return Values: TRUE if the driver was added;
  1782. FALSE otherwise
  1783. --*/
  1784. {
  1785. BOOL bReturn = FALSE;
  1786. WCHAR szVersionDir[MAX_PATH], szNewDir[MAX_PATH+5];
  1787. WCHAR szDriverFile[MAX_PATH], szOldFile[MAX_PATH], szNewFile[MAX_PATH];
  1788. WCHAR *pTempDir = NULL;
  1789. DWORD dwIndex, dwTempDir;
  1790. HANDLE hToken = NULL, hFile;
  1791. LPWSTR pFileName;
  1792. hToken = RevertToPrinterSelf();
  1793. // get the version directory
  1794. // szVersionDir shouldn't be bigger than MAX_PATH - 5 since is used later
  1795. // to build another file paths.
  1796. if((StrNCatBuff(szVersionDir,
  1797. MAX_PATH - 5,
  1798. pIniSpooler->pDir,
  1799. L"\\drivers\\",
  1800. pIniEnvironment->pDirectory,
  1801. L"\\",
  1802. pIniVersion->szDirectory,
  1803. NULL) != ERROR_SUCCESS))
  1804. {
  1805. goto CleanUp;
  1806. }
  1807. dwIndex = CreateNumberedTempDirectory((LPWSTR)szVersionDir, &pTempDir);
  1808. if (dwIndex == -1) {
  1809. goto CleanUp;
  1810. }
  1811. dwTempDir = dwIndex;
  1812. wsprintf(szNewDir, L"%ws\\New", szVersionDir);
  1813. // copy the files into the temp directory and mark them for deletion on
  1814. // reboot
  1815. for (dwIndex = 0; dwIndex < dwFileCount; dwIndex++) {
  1816. pFileName = (LPWSTR) FindFileName(pInternalDriverFiles[dwIndex].pFileName);
  1817. if((StrNCatBuff(szNewFile,MAX_PATH,szNewDir ,L"\\", pFileName, NULL) != ERROR_SUCCESS) ||
  1818. (StrNCatBuff(szOldFile,MAX_PATH,szVersionDir, L"\\", pFileName, NULL) != ERROR_SUCCESS) ||
  1819. (StrNCatBuff(szDriverFile,MAX_PATH,pTempDir, L"\\", pFileName, NULL) != ERROR_SUCCESS))
  1820. {
  1821. goto CleanUp;
  1822. }
  1823. hFile = CreateFile(szNewFile, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  1824. FILE_ATTRIBUTE_NORMAL, NULL);
  1825. if (hFile == INVALID_HANDLE_VALUE) {
  1826. CopyFile(szOldFile, szDriverFile, FALSE);
  1827. } else {
  1828. CloseHandle(hFile);
  1829. hFile = INVALID_HANDLE_VALUE;
  1830. CopyFile(szNewFile, szDriverFile, FALSE);
  1831. }
  1832. SplMoveFileEx(szDriverFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  1833. }
  1834. // Delete the directory on reboot
  1835. SplMoveFileEx(szNewDir, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  1836. // Update driver structures and make event call backs and
  1837. // store information in the registry to complete the call later
  1838. bReturn = CompleteDriverUpgrade(pIniSpooler,
  1839. pIniEnvironment,
  1840. pIniVersion,
  1841. NULL,
  1842. dwLevel,
  1843. pDriverInfo,
  1844. dwFileCopyFlags,
  1845. pInternalDriverFiles,
  1846. dwFileCount,
  1847. dwVersion,
  1848. dwTempDir,
  1849. bDriverMoved,
  1850. TRUE,
  1851. TRUE) &&
  1852. SaveParametersForUpgrade(pIniSpooler->pMachineName,
  1853. bDriverMoved,
  1854. dwLevel,
  1855. pDriverInfo,
  1856. dwVersion);
  1857. CleanUp:
  1858. if (hToken) {
  1859. ImpersonatePrinterClient(hToken);
  1860. }
  1861. FreeSplMem(pTempDir);
  1862. return bReturn;
  1863. }
  1864. BOOL
  1865. WaitRequiredForDriverUnload(
  1866. IN PINISPOOLER pIniSpooler,
  1867. IN PINIENVIRONMENT pIniEnvironment,
  1868. IN PINIVERSION pIniVersion,
  1869. IN PINIDRIVER pIniDriver,
  1870. IN DWORD dwLevel,
  1871. IN LPBYTE pDriverInfo,
  1872. IN DWORD dwFileCopyFlags,
  1873. IN OUT PINTERNAL_DRV_FILE pInternalDriverFiles,
  1874. IN DWORD dwFileCount,
  1875. IN DWORD dwVersion,
  1876. IN BOOL bDriverMoved,
  1877. OUT LPBOOL pbSuccess
  1878. )
  1879. /*++
  1880. Function Description: Determine if the driver upgrade has to be defered till the
  1881. dlls can be unloaded. GDI and the client side of the spooler are
  1882. notified to continue the pending upgrade when the dll is unloaded.
  1883. Parameters: pIniSpooler -- pointer to INISPOOLER
  1884. pIniEnvironment -- pointer to INIENVIRONMENT
  1885. pIniVersion -- pointer to INVERSION
  1886. pIniDriver -- pointer to INIDRIVER
  1887. dwLevel -- driver_info level
  1888. pDriverInfo -- pointer to driver_info
  1889. dwFileCopyFlags -- copy flags for the driver.
  1890. pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  1891. dwFileCount -- number of files in file set
  1892. dwVersion -- driver version
  1893. bDriverMoved -- Were any files moved to the Old directory ?
  1894. pbSuccess -- pointer to Success flag
  1895. Return Values: TRUE if the driver was unloaded and upgraded;
  1896. FALSE if the driver cant be unloaded
  1897. --*/
  1898. {
  1899. BOOL bUnloaded,bDriverFileMoved, bConfigFileMoved;
  1900. LPWSTR pDriverFile, pConfigFile;
  1901. WCHAR szDriverFile[MAX_PATH], szOldDir[MAX_PATH], szNewDir[MAX_PATH];
  1902. WCHAR szTempFile[MAX_PATH], szCurrDir[MAX_PATH], szConfigFile[MAX_PATH];
  1903. HANDLE hFile, hToken = NULL;
  1904. DWORD dwDriverAttributes = 0;
  1905. hToken = RevertToPrinterSelf();
  1906. *pbSuccess = FALSE;
  1907. // Set up Driver, Old and New directories
  1908. if((StrNCatBuff(szCurrDir,
  1909. MAX_PATH,
  1910. pIniSpooler->pDir,
  1911. L"\\drivers\\",
  1912. pIniEnvironment->pDirectory,
  1913. L"\\",
  1914. pIniVersion->szDirectory,
  1915. NULL) != ERROR_SUCCESS) ||
  1916. (StrNCatBuff(szOldDir,
  1917. MAX_PATH,
  1918. szCurrDir,
  1919. L"\\Old",
  1920. NULL) != ERROR_SUCCESS) ||
  1921. (StrNCatBuff(szNewDir,
  1922. MAX_PATH,
  1923. szCurrDir,
  1924. L"\\New",
  1925. NULL) != ERROR_SUCCESS) ||
  1926. (StrNCatBuff(szDriverFile,
  1927. MAX_PATH,
  1928. szCurrDir,
  1929. L"\\",
  1930. FindFileName(pInternalDriverFiles[0].pFileName),
  1931. NULL) != ERROR_SUCCESS) ||
  1932. (StrNCatBuff(szConfigFile,
  1933. MAX_PATH,
  1934. szCurrDir,
  1935. L"\\",
  1936. FindFileName(pInternalDriverFiles[1].pFileName),
  1937. NULL) != ERROR_SUCCESS) ||
  1938. (StrNCatBuff(szTempFile,
  1939. MAX_PATH,szNewDir,
  1940. L"\\",
  1941. FindFileName(pInternalDriverFiles[0].pFileName),
  1942. NULL) != ERROR_SUCCESS))
  1943. {
  1944. bUnloaded = TRUE;
  1945. goto CleanUp;
  1946. }
  1947. // Check if the new driver file needs to be copied
  1948. hFile = CreateFile(szTempFile, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  1949. FILE_ATTRIBUTE_NORMAL, NULL);
  1950. if (hFile != INVALID_HANDLE_VALUE) {
  1951. CloseHandle(hFile);
  1952. pDriverFile = szDriverFile;
  1953. if (pIniDriver) {
  1954. dwDriverAttributes = pIniDriver->dwDriverAttributes;
  1955. } else {
  1956. dwDriverAttributes = IsKMPD(szDriverFile) ? DRIVER_KERNELMODE
  1957. : DRIVER_USERMODE;
  1958. }
  1959. } else {
  1960. pDriverFile = NULL;
  1961. }
  1962. if((StrNCatBuff(szTempFile,
  1963. MAX_PATH,
  1964. szNewDir,
  1965. L"\\",
  1966. FindFileName(pInternalDriverFiles[1].pFileName), NULL)
  1967. != ERROR_SUCCESS))
  1968. {
  1969. bUnloaded = TRUE;
  1970. goto CleanUp;
  1971. }
  1972. // Check if the new config file needs to be copied
  1973. hFile = CreateFile(szTempFile, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  1974. FILE_ATTRIBUTE_NORMAL, NULL);
  1975. if (hFile != INVALID_HANDLE_VALUE) {
  1976. CloseHandle(hFile);
  1977. pConfigFile = szConfigFile;
  1978. } else {
  1979. pConfigFile = NULL;
  1980. }
  1981. bUnloaded = FilesUnloaded(pIniEnvironment, pDriverFile, pConfigFile,
  1982. dwDriverAttributes);
  1983. if (bUnloaded) {
  1984. // Move the driver files
  1985. if (MoveNewDriverRelatedFiles(szNewDir,
  1986. szCurrDir,
  1987. szOldDir,
  1988. pInternalDriverFiles,
  1989. dwFileCount,
  1990. &bDriverFileMoved,
  1991. &bConfigFileMoved)) {
  1992. // Update driver structures and make event call backs
  1993. *pbSuccess = CompleteDriverUpgrade(pIniSpooler,
  1994. pIniEnvironment,
  1995. pIniVersion,
  1996. pIniDriver,
  1997. dwLevel,
  1998. pDriverInfo,
  1999. dwFileCopyFlags,
  2000. pInternalDriverFiles,
  2001. dwFileCount,
  2002. dwVersion,
  2003. 0,
  2004. bDriverMoved,
  2005. bDriverFileMoved,
  2006. bConfigFileMoved
  2007. );
  2008. }
  2009. }
  2010. else {
  2011. //
  2012. // We care if the files are marked to be moved from New to Version directory only if the drivers are loaded
  2013. // and we left the updated files in New directory. Then it is imperative MoveFileEx to have succeeded.
  2014. // Fail the api call if bDriverMoved is FALSE;
  2015. //
  2016. *pbSuccess = bDriverMoved;
  2017. }
  2018. CleanUp:
  2019. if (hToken) {
  2020. ImpersonatePrinterClient(hToken);
  2021. }
  2022. return (!bUnloaded);
  2023. }
  2024. BOOL FilesUnloaded(
  2025. PINIENVIRONMENT pIniEnvironment,
  2026. LPWSTR pDriverFile,
  2027. LPWSTR pConfigFile,
  2028. DWORD dwDriverAttributes)
  2029. {
  2030. BOOL bReturn = TRUE;
  2031. fnWinSpoolDrv fnList;
  2032. // Drivers belonging to other environments are not loaded
  2033. if (!pIniEnvironment ||
  2034. lstrcmpi(pIniEnvironment->pName, szEnvironment)) {
  2035. return bReturn;
  2036. }
  2037. if (pDriverFile) {
  2038. bReturn = GdiArtificialDecrementDriver(pDriverFile,
  2039. dwDriverAttributes);
  2040. }
  2041. if (bReturn && pConfigFile && SplInitializeWinSpoolDrv(&fnList)) {
  2042. bReturn = (* (fnList.pfnForceUnloadDriver))(pConfigFile);
  2043. }
  2044. return bReturn;
  2045. }
  2046. DWORD StringSizeInBytes(
  2047. LPWSTR pString,
  2048. BOOL bMultiSz)
  2049. /*++
  2050. Function Description: Computes the number of bytes in the string
  2051. Parameters: pString -- string pointer
  2052. bMultiSz -- flag for multi_sz strings
  2053. Return Values: number of bytes
  2054. --*/
  2055. {
  2056. DWORD dwReturn = 0, dwLength;
  2057. if (!pString) {
  2058. return dwReturn;
  2059. }
  2060. if (!bMultiSz) {
  2061. dwReturn = (wcslen(pString) + 1) * sizeof(WCHAR);
  2062. } else {
  2063. while (dwLength = wcslen(pString)) {
  2064. pString += (dwLength + 1);
  2065. dwReturn += (dwLength + 1) * sizeof(WCHAR);
  2066. }
  2067. dwReturn += sizeof(WCHAR);
  2068. }
  2069. return dwReturn;
  2070. }
  2071. DWORD LocalRegSetValue(
  2072. HKEY hKey,
  2073. LPWSTR pValueName,
  2074. DWORD dwType,
  2075. LPBYTE pValueData)
  2076. /*++
  2077. Function Description: This function is a wrapper around RegSetValueEx which puts in
  2078. NULL strings for NULL pointers.
  2079. Parameters: hKey - handle to registry key
  2080. pValueName - value name
  2081. dwType - type of value data (REG_DWORD , REG_SZ ...)
  2082. pValueData - data buffer
  2083. Return Values: Last error returned by RegSetValueEx
  2084. --*/
  2085. {
  2086. DWORD dwSize;
  2087. WCHAR pNull[2];
  2088. LPBYTE pData = pValueData;
  2089. if (!pValueName) {
  2090. return ERROR_SUCCESS;
  2091. }
  2092. pNull[0] = pNull[1] = L'\0';
  2093. switch (dwType) {
  2094. case REG_DWORD:
  2095. dwSize = sizeof(DWORD);
  2096. break;
  2097. case REG_SZ:
  2098. if (!pData) {
  2099. pData = (LPBYTE) pNull;
  2100. dwSize = sizeof(WCHAR);
  2101. } else {
  2102. dwSize = StringSizeInBytes((LPWSTR) pData, FALSE);
  2103. }
  2104. break;
  2105. case REG_MULTI_SZ:
  2106. if (!pData || !*pData) {
  2107. pData = (LPBYTE) pNull;
  2108. dwSize = 2 * sizeof(WCHAR);
  2109. } else {
  2110. dwSize = StringSizeInBytes((LPWSTR) pData, TRUE);
  2111. }
  2112. break;
  2113. default:
  2114. // only dword, sz and msz are written to the registry
  2115. return ERROR_INVALID_PARAMETER;
  2116. }
  2117. return RegSetValueEx(hKey, pValueName, 0, dwType, pData, dwSize);
  2118. }
  2119. BOOL SaveParametersForUpgrade(
  2120. LPWSTR pName,
  2121. BOOL bDriverMoved,
  2122. DWORD dwLevel,
  2123. LPBYTE pDriverInfo,
  2124. DWORD dwVersion)
  2125. /*++
  2126. Function Description: Saves data for the driver upgrade which has to be
  2127. deferred till the new driver can be loaded
  2128. Parameters: pName -- pIniSpooler->pName
  2129. bDriverMoved -- Were any of the old driver files moved?
  2130. dwLevel -- Driver_Info level
  2131. pDriverInfo -- Driver_Info pointer
  2132. dwVersion -- Driver version number
  2133. Return Values: TRUE if successful; FALSE otherwise
  2134. --*/
  2135. {
  2136. HANDLE hToken = NULL;
  2137. HKEY hRootKey = NULL, hUpgradeKey = NULL, hVersionKey = NULL;
  2138. HKEY hDriverKey = NULL;
  2139. DWORD dwDriverMoved = (DWORD) bDriverMoved;
  2140. BOOL bReturn = FALSE;
  2141. WCHAR pBuffer[MAX_PATH];
  2142. PDRIVER_INFO_2 pDriver2;
  2143. PDRIVER_INFO_3 pDriver3;
  2144. PDRIVER_INFO_4 pDriver4;
  2145. PDRIVER_INFO_6 pDriver6;
  2146. pDriver2 = (PDRIVER_INFO_2) pDriverInfo;
  2147. // Stop impersonation for modifying the registry
  2148. hToken = RevertToPrinterSelf();
  2149. wsprintf(pBuffer, L"Version-%d", dwVersion);
  2150. // Create the registry keys
  2151. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRegistryRoot, 0,
  2152. NULL, 0, KEY_WRITE, NULL, &hRootKey, NULL) ||
  2153. RegCreateKeyEx(hRootKey, szPendingUpgrades, 0,
  2154. NULL, 0, KEY_WRITE, NULL, &hUpgradeKey, NULL) ||
  2155. RegCreateKeyEx(hUpgradeKey, pBuffer, 0,
  2156. NULL, 0, KEY_WRITE, NULL, &hVersionKey, NULL) ||
  2157. RegCreateKeyEx(hVersionKey, pDriver2->pName, 0,
  2158. NULL, 0, KEY_WRITE, NULL, &hDriverKey, NULL)) {
  2159. goto CleanUp;
  2160. }
  2161. if (dwLevel == DRIVER_INFO_VERSION_LEVEL) {
  2162. bReturn = SaveDriverVersionForUpgrade(hDriverKey, (PDRIVER_INFO_VERSION)pDriverInfo,
  2163. pName, bDriverMoved, dwVersion);
  2164. goto CleanUp;
  2165. }
  2166. // Add the spooler name and driver info level
  2167. if (LocalRegSetValue(hDriverKey, L"SplName", REG_SZ, (LPBYTE) pName) ||
  2168. LocalRegSetValue(hDriverKey, L"Level", REG_DWORD, (LPBYTE) &dwLevel) ||
  2169. LocalRegSetValue(hDriverKey, L"DriverMoved", REG_DWORD, (LPBYTE) &dwDriverMoved)) {
  2170. goto CleanUp;
  2171. }
  2172. // Add Driver_Info_2 data
  2173. if (LocalRegSetValue(hDriverKey, L"cVersion", REG_DWORD, (LPBYTE) &dwVersion) ||
  2174. LocalRegSetValue(hDriverKey, L"pName", REG_SZ, (LPBYTE) pDriver2->pName) ||
  2175. LocalRegSetValue(hDriverKey, L"pEnvironment", REG_SZ, (LPBYTE) pDriver2->pEnvironment) ||
  2176. LocalRegSetValue(hDriverKey, L"pDriverPath", REG_SZ, (LPBYTE) pDriver2->pDriverPath) ||
  2177. LocalRegSetValue(hDriverKey, L"pDataFile", REG_SZ, (LPBYTE) pDriver2->pDataFile) ||
  2178. LocalRegSetValue(hDriverKey, L"pConfigFile", REG_SZ, (LPBYTE) pDriver2->pConfigFile)) {
  2179. goto CleanUp;
  2180. }
  2181. if (dwLevel != 2) {
  2182. pDriver3 = (PDRIVER_INFO_3) pDriverInfo;
  2183. // Add Driver_Info_3 data
  2184. if (LocalRegSetValue(hDriverKey, L"pHelpFile", REG_SZ, (LPBYTE) pDriver3->pHelpFile) ||
  2185. LocalRegSetValue(hDriverKey, L"pDependentFiles", REG_MULTI_SZ,
  2186. (LPBYTE) pDriver3->pDependentFiles) ||
  2187. LocalRegSetValue(hDriverKey, L"pMonitorName", REG_SZ,
  2188. (LPBYTE) pDriver3->pMonitorName) ||
  2189. LocalRegSetValue(hDriverKey, L"pDefaultDataType", REG_SZ,
  2190. (LPBYTE) pDriver3->pDefaultDataType)) {
  2191. goto CleanUp;
  2192. }
  2193. if (dwLevel == 4 || dwLevel == 6) {
  2194. pDriver4 = (PDRIVER_INFO_4) pDriverInfo;
  2195. // Add Driver_Info_4 data
  2196. if (LocalRegSetValue(hDriverKey, L"pszzPreviousNames", REG_MULTI_SZ, (LPBYTE) pDriver4->pszzPreviousNames))
  2197. {
  2198. goto CleanUp;
  2199. }
  2200. }
  2201. if (dwLevel == 6) {
  2202. pDriver6 = (PDRIVER_INFO_6) pDriverInfo;
  2203. // Add Driver_Info6 data
  2204. if (RegSetValueEx(hDriverKey, L"ftDriverDate", 0, REG_BINARY, (LPBYTE)&pDriver6->ftDriverDate, sizeof(FILETIME)) ||
  2205. RegSetValueEx(hDriverKey, L"dwlDriverVersion", 0, REG_BINARY, (LPBYTE)&pDriver6->dwlDriverVersion, sizeof(DWORDLONG)) ||
  2206. LocalRegSetValue(hDriverKey, L"pszMfgName", REG_SZ, (LPBYTE)pDriver6->pszMfgName) ||
  2207. LocalRegSetValue(hDriverKey, L"pszOEMUrl", REG_SZ, (LPBYTE)pDriver6->pszOEMUrl) ||
  2208. LocalRegSetValue(hDriverKey, L"pszHardwareID", REG_SZ, (LPBYTE)pDriver6->pszHardwareID) ||
  2209. LocalRegSetValue(hDriverKey, L"pszProvider", REG_SZ, (LPBYTE)pDriver6->pszProvider)
  2210. )
  2211. {
  2212. goto CleanUp;
  2213. }
  2214. }
  2215. }
  2216. bReturn = TRUE;
  2217. CleanUp:
  2218. if (hDriverKey) {
  2219. RegCloseKey(hDriverKey);
  2220. }
  2221. if (hVersionKey) {
  2222. RegCloseKey(hVersionKey);
  2223. }
  2224. if (hUpgradeKey) {
  2225. RegCloseKey(hUpgradeKey);
  2226. }
  2227. if (hRootKey) {
  2228. RegCloseKey(hRootKey);
  2229. }
  2230. if (hToken) {
  2231. ImpersonatePrinterClient(hToken);
  2232. }
  2233. return bReturn;
  2234. }
  2235. BOOL SaveDriverVersionForUpgrade(
  2236. IN HKEY hDriverKey,
  2237. IN PDRIVER_INFO_VERSION pDriverVersion,
  2238. IN LPWSTR pName,
  2239. IN DWORD dwDriverMoved,
  2240. IN DWORD dwVersion
  2241. )
  2242. /*++
  2243. Routine Name:
  2244. SaveDriverVersionForUpgrade
  2245. Routine Description:
  2246. Save a DRIVER_INFO_VERSION into registry for pending driver upgrade purposes.
  2247. It is called by SaveParametersForUpgrade.
  2248. For simplicity, it will save it in the same format DRIVER_INFO_6
  2249. is saved in the registry.
  2250. Arguments:
  2251. hDriverKey - the registry key where to save data
  2252. pDriverVersion - pointer to DRIVER_INFO_VERSION structure
  2253. pName - driver name
  2254. dwDriverMoved - information about the way files where move between directories
  2255. dwVersion - driver version
  2256. Return Value:
  2257. TRUE if success.
  2258. --*/
  2259. {
  2260. BOOL bRetValue = FALSE;
  2261. DWORD dwLevel = 6;
  2262. PWSTR pDllFiles = NULL;
  2263. PWSTR pszDriverPath, pszDataFile, pszConfigFile, pszHelpFile, pDependentFiles ;
  2264. pszDriverPath = pszDataFile = pszConfigFile = pszHelpFile = NULL;
  2265. if (!GetFileNamesFromDriverVersionInfo(pDriverVersion,
  2266. &pszDriverPath,
  2267. &pszConfigFile,
  2268. &pszDataFile,
  2269. &pszHelpFile))
  2270. {
  2271. goto CleanUp;
  2272. }
  2273. if (!BuildDependentFilesFromDriverInfo(pDriverVersion,
  2274. &pDllFiles))
  2275. {
  2276. goto CleanUp;
  2277. }
  2278. if (LocalRegSetValue(hDriverKey, L"SplName", REG_SZ, (LPBYTE) pName) ||
  2279. LocalRegSetValue(hDriverKey, L"Level", REG_DWORD, (LPBYTE) &dwLevel) ||
  2280. LocalRegSetValue(hDriverKey, L"DriverMoved", REG_DWORD, (LPBYTE) &dwDriverMoved) ||
  2281. LocalRegSetValue(hDriverKey, L"Level", REG_DWORD, (LPBYTE) &dwLevel) ||
  2282. LocalRegSetValue(hDriverKey, L"cVersion", REG_DWORD, (LPBYTE) &dwVersion) ||
  2283. LocalRegSetValue(hDriverKey, L"pName", REG_SZ, (LPBYTE) pDriverVersion->pName) ||
  2284. LocalRegSetValue(hDriverKey, L"pEnvironment", REG_SZ, (LPBYTE) pDriverVersion->pEnvironment)||
  2285. LocalRegSetValue(hDriverKey, L"pDriverPath", REG_SZ, (LPBYTE) pszDriverPath) ||
  2286. LocalRegSetValue(hDriverKey, L"pDataFile", REG_SZ, (LPBYTE) pszDataFile) ||
  2287. LocalRegSetValue(hDriverKey, L"pConfigFile", REG_SZ, (LPBYTE) pszConfigFile) ||
  2288. LocalRegSetValue(hDriverKey, L"pHelpFile", REG_SZ, (LPBYTE) pszHelpFile) ||
  2289. LocalRegSetValue(hDriverKey, L"pDependentFiles", REG_MULTI_SZ, (LPBYTE) pDllFiles) ||
  2290. LocalRegSetValue(hDriverKey, L"pMonitorName", REG_SZ,
  2291. (LPBYTE) pDriverVersion->pMonitorName) ||
  2292. LocalRegSetValue(hDriverKey, L"pDefaultDataType", REG_SZ,
  2293. (LPBYTE) pDriverVersion->pDefaultDataType) ||
  2294. LocalRegSetValue(hDriverKey, L"pszzPreviousNames", REG_MULTI_SZ,
  2295. (LPBYTE) pDriverVersion->pszzPreviousNames) ||
  2296. RegSetValueEx(hDriverKey, L"ftDriverDate", 0, REG_BINARY,
  2297. (LPBYTE)&pDriverVersion->ftDriverDate, sizeof(FILETIME)) ||
  2298. RegSetValueEx(hDriverKey, L"dwlDriverVersion", 0, REG_BINARY,
  2299. (LPBYTE)&pDriverVersion->dwlDriverVersion, sizeof(DWORDLONG)) ||
  2300. LocalRegSetValue(hDriverKey, L"pszMfgName", REG_SZ,
  2301. (LPBYTE)pDriverVersion->pszMfgName) ||
  2302. LocalRegSetValue(hDriverKey, L"pszOEMUrl", REG_SZ,
  2303. (LPBYTE)pDriverVersion->pszOEMUrl) ||
  2304. LocalRegSetValue(hDriverKey, L"pszHardwareID", REG_SZ,
  2305. (LPBYTE)pDriverVersion->pszHardwareID) ||
  2306. LocalRegSetValue(hDriverKey, L"pszProvider", REG_SZ,
  2307. (LPBYTE)pDriverVersion->pszProvider))
  2308. {
  2309. goto CleanUp;
  2310. }
  2311. bRetValue = TRUE;
  2312. CleanUp:
  2313. FreeSplMem(pDllFiles);
  2314. return bRetValue;
  2315. }
  2316. BOOL
  2317. MoveNewDriverRelatedFiles(
  2318. LPWSTR pNewDir,
  2319. LPWSTR pCurrDir,
  2320. LPWSTR pOldDir,
  2321. PINTERNAL_DRV_FILE pInternalDriverFiles,
  2322. DWORD dwFileCount,
  2323. LPBOOL pbDriverFileMoved,
  2324. LPBOOL pbConfigFileMoved)
  2325. /*++
  2326. Function Description: Moves driver files in the New directory to the correct directory.
  2327. Parameters: pNewDir -- name of the New (source) directory
  2328. pCurrDir -- name of the destination directory
  2329. pOldDir -- name of the Old (temp) directory
  2330. pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  2331. dwFileCount -- number of files in file set
  2332. pbDriverFileMoved -- flag to return if new driver file has been moved;
  2333. We assume entry 0 for driver file in pInternalDriverFiles array
  2334. pbDriverFileMoved should be NULL when this assumption is FALSE
  2335. ( see SplCopyNumberOfFiles )
  2336. pbConfigFileMoved -- flag to return if new config file has been moved;
  2337. We assume entry 0 for config file in pInternalDriverFiles array
  2338. pbConfigFileMoved should be NULL when this assumption is FALSE
  2339. ( see SplCopyNumberOfFiles )
  2340. Return Values: NONE
  2341. --*/
  2342. {
  2343. HANDLE hFile;
  2344. DWORD dwIndex, dwBackupIndex;
  2345. WCHAR szDriverFile[MAX_PATH], szNewFile[MAX_PATH], szOldFile[MAX_PATH];
  2346. WCHAR *pszTempOldDirectory = NULL;
  2347. LPWSTR pFileName;
  2348. BOOL bRetValue = FALSE;
  2349. BOOL bFailedToMove = FALSE;
  2350. if (pbDriverFileMoved)
  2351. {
  2352. *pbDriverFileMoved = FALSE;
  2353. }
  2354. if (pbConfigFileMoved)
  2355. {
  2356. *pbConfigFileMoved = FALSE;
  2357. }
  2358. if (CreateNumberedTempDirectory(pOldDir, &pszTempOldDirectory) != -1) {
  2359. for (dwIndex = 0; dwIndex < dwFileCount; dwIndex++) {
  2360. BOOL FileCopied = FALSE;
  2361. pFileName = (LPWSTR) FindFileName(pInternalDriverFiles[dwIndex].pFileName);
  2362. if((StrNCatBuff(szNewFile,MAX_PATH,pNewDir, L"\\", pFileName, NULL) == ERROR_SUCCESS) &&
  2363. (StrNCatBuff(szDriverFile,MAX_PATH,pCurrDir, L"\\", pFileName, NULL) == ERROR_SUCCESS) &&
  2364. (StrNCatBuff(szOldFile,MAX_PATH,pszTempOldDirectory, L"\\", pFileName, NULL) == ERROR_SUCCESS))
  2365. {
  2366. hFile = CreateFile(szNewFile, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  2367. FILE_ATTRIBUTE_NORMAL, NULL);
  2368. if (hFile != INVALID_HANDLE_VALUE)
  2369. {
  2370. CloseHandle(hFile);
  2371. if (!SplMoveFileEx(szDriverFile, szOldFile, MOVEFILE_REPLACE_EXISTING)) {
  2372. bFailedToMove = TRUE;
  2373. dwBackupIndex = dwIndex;
  2374. break;
  2375. }
  2376. if (!SplMoveFileEx(szNewFile, szDriverFile, MOVEFILE_REPLACE_EXISTING)) {
  2377. bFailedToMove = TRUE;
  2378. dwBackupIndex = dwIndex + 1;
  2379. break;
  2380. }
  2381. FileCopied = TRUE;
  2382. //
  2383. // We could come in here from a pending upgrade
  2384. //
  2385. pInternalDriverFiles[dwIndex].bUpdated = TRUE;
  2386. }
  2387. }
  2388. switch (dwIndex)
  2389. {
  2390. case 0:
  2391. if (pbDriverFileMoved)
  2392. {
  2393. *pbDriverFileMoved = FileCopied;
  2394. }
  2395. break;
  2396. case 1:
  2397. if (pbConfigFileMoved)
  2398. {
  2399. *pbConfigFileMoved = FileCopied;
  2400. }
  2401. break;
  2402. }
  2403. }
  2404. if ( bFailedToMove ) {
  2405. //
  2406. // Restore the initial file set in version directory.
  2407. // Old\N has the replaced files. Move them back to Version directory.
  2408. //
  2409. for (dwIndex = 0; dwIndex < dwBackupIndex; dwIndex++) {
  2410. pFileName = (LPWSTR) FindFileName(pInternalDriverFiles[dwIndex].pFileName);
  2411. if( (StrNCatBuff(szDriverFile,MAX_PATH,pCurrDir, L"\\", pFileName, NULL) == ERROR_SUCCESS) &&
  2412. (StrNCatBuff(szOldFile,MAX_PATH,pszTempOldDirectory, L"\\", pFileName, NULL) == ERROR_SUCCESS)) {
  2413. SplMoveFileEx(szOldFile, szDriverFile, MOVEFILE_REPLACE_EXISTING);
  2414. }
  2415. pInternalDriverFiles[dwIndex].bUpdated = FALSE;
  2416. }
  2417. } else {
  2418. bRetValue = TRUE;
  2419. }
  2420. }
  2421. FreeSplMem(pszTempOldDirectory);
  2422. return bRetValue;
  2423. }
  2424. BOOL LocalDriverUnloadComplete(
  2425. LPWSTR pDriverFile)
  2426. /*++
  2427. Function Description: This function is called in response to some driver file
  2428. being unloaded. The spooler tries to complete driver upgrades
  2429. that were waiting for this file to unload.
  2430. Parameters: pDriverFile -- Driver file which was unloaded
  2431. Return Values: TRUE
  2432. --*/
  2433. {
  2434. HANDLE hToken = NULL;
  2435. hToken = RevertToPrinterSelf();
  2436. PendingDriverUpgrades(pDriverFile);
  2437. if (hToken) {
  2438. ImpersonatePrinterClient(hToken);
  2439. }
  2440. return TRUE;
  2441. }
  2442. BOOL RestoreVersionKey(
  2443. HKEY hUpgradeKey,
  2444. DWORD dwIndex,
  2445. HKEY *phVersionKey)
  2446. /*++
  2447. Function Description: Gets the version key from the pending upgrade key
  2448. Parameters: hUpgradeKey -- upgrade key
  2449. dwIndex -- version index
  2450. phVersionKey -- pointer to buffer for version key
  2451. Return Values: TRUE if version key is found
  2452. FALSE otherwise
  2453. --*/
  2454. {
  2455. WCHAR pBuffer[MAX_PATH];
  2456. DWORD dwSize = MAX_PATH;
  2457. *phVersionKey = NULL;
  2458. if (RegEnumKeyEx(hUpgradeKey, dwIndex, pBuffer, &dwSize,
  2459. NULL, NULL, NULL, NULL)) {
  2460. return FALSE;
  2461. }
  2462. if (RegCreateKeyEx(hUpgradeKey, pBuffer, 0,
  2463. NULL, 0, KEY_ALL_ACCESS, NULL, phVersionKey, NULL)) {
  2464. return FALSE;
  2465. }
  2466. return TRUE;
  2467. }
  2468. VOID PendingDriverUpgrades(
  2469. LPWSTR pDriverFile)
  2470. /*++
  2471. Function Description: Loops thru the list of pending upgrades and completes them if
  2472. driver files have been unloaded. This function will try all the
  2473. drivers on spooler startup.
  2474. Parameters: pDriverFile -- name of the file which was unloaded
  2475. Return Values: NONE
  2476. --*/
  2477. {
  2478. DWORD dwIndex, dwLevel, dwDriverMoved, dwFileCount, dwVersion, dwVersionIndex;
  2479. LPWSTR pKeyName, pSplName,pEnvironment;
  2480. PINTERNAL_DRV_FILE pInternalDriverFiles = NULL;
  2481. HKEY hRootKey = NULL, hVersionKey = NULL, hUpgradeKey = NULL;
  2482. WCHAR szDir[MAX_PATH], szDriverFile[MAX_PATH], szConfigFile[MAX_PATH];
  2483. BOOL bSuccess;
  2484. PDRIVER_INFO_6 pDriverInfo;
  2485. PINISPOOLER pIniSpooler;
  2486. PINIENVIRONMENT pIniEnvironment;
  2487. PINIVERSION pIniVersion;
  2488. PINIDRIVER pIniDriver;
  2489. // struct for maintaining keynames to be deleted at the end
  2490. struct StringList {
  2491. struct StringList *pNext;
  2492. LPWSTR pKeyName;
  2493. DWORD dwVersionIndex;
  2494. } *pStart, *pTemp;
  2495. pStart = pTemp = NULL;
  2496. EnterSplSem();
  2497. // Open the registry key
  2498. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRegistryRoot, 0,
  2499. NULL, 0, KEY_ALL_ACCESS, NULL, &hRootKey, NULL) ||
  2500. RegCreateKeyEx(hRootKey, szPendingUpgrades, 0,
  2501. NULL, 0, KEY_ALL_ACCESS, NULL, &hUpgradeKey, NULL)) {
  2502. goto CleanUp;
  2503. }
  2504. // Loop thru each version entry
  2505. for (dwVersionIndex = 0, hVersionKey = NULL;
  2506. RestoreVersionKey(hUpgradeKey, dwVersionIndex, &hVersionKey);
  2507. RegCloseKey(hVersionKey), hVersionKey = NULL, ++dwVersionIndex) {
  2508. // Loop thru each driver upgrade
  2509. for (dwIndex = 0, dwFileCount = 0, pInternalDriverFiles = NULL;
  2510. RestoreParametersForUpgrade(hVersionKey,
  2511. dwIndex,
  2512. &pKeyName,
  2513. &pSplName,
  2514. &dwLevel,
  2515. &dwDriverMoved,
  2516. &pDriverInfo);
  2517. CleanUpResources(pKeyName, pSplName, pDriverInfo,
  2518. &pInternalDriverFiles, dwFileCount),
  2519. ++dwIndex, dwFileCount = 0, pInternalDriverFiles = NULL) {
  2520. // The driver_info struct validity has been checked while updating
  2521. // the registry.
  2522. // Set pIniSpooler to LocalIniSpooler
  2523. if (!(pIniSpooler = pLocalIniSpooler)) {
  2524. continue;
  2525. }
  2526. // Set pIniEnvironment
  2527. pEnvironment = szEnvironment;
  2528. if (pDriverInfo->pEnvironment && *(pDriverInfo->pEnvironment)) {
  2529. pEnvironment = pDriverInfo->pEnvironment;
  2530. }
  2531. pIniEnvironment = FindEnvironment(pEnvironment, pIniSpooler);
  2532. if (!pIniEnvironment) {
  2533. continue;
  2534. }
  2535. // Set pIniVersion
  2536. dwVersion = pDriverInfo->cVersion;
  2537. pIniVersion = FindVersionEntry(pIniEnvironment, dwVersion);
  2538. if (!pIniVersion) {
  2539. continue;
  2540. }
  2541. // Set pIniDriver
  2542. pIniDriver = FindDriverEntry(pIniVersion, pDriverInfo->pName);
  2543. if (!pIniDriver) {
  2544. continue;
  2545. }
  2546. // Check for the file name which was unloaded
  2547. if (pDriverFile) {
  2548. if((StrNCatBuff(szDir,
  2549. MAX_PATH,
  2550. pIniSpooler->pDir,
  2551. L"\\drivers\\",
  2552. pIniEnvironment->pDirectory,
  2553. L"\\",
  2554. pIniVersion->szDirectory,
  2555. NULL) != ERROR_SUCCESS) ||
  2556. (StrNCatBuff(szDriverFile,
  2557. MAX_PATH,
  2558. szDir,
  2559. L"\\",
  2560. FindFileName(pIniDriver->pDriverFile),
  2561. NULL) != ERROR_SUCCESS) ||
  2562. (StrNCatBuff(szConfigFile,
  2563. MAX_PATH,szDir,
  2564. L"\\",
  2565. FindFileName(pIniDriver->pConfigFile),
  2566. NULL) != ERROR_SUCCESS))
  2567. continue;
  2568. if (_wcsicmp(pDriverFile, szDriverFile) &&
  2569. _wcsicmp(pDriverFile, szConfigFile)) {
  2570. continue;
  2571. }
  2572. }
  2573. if (!CreateInternalDriverFileArray(dwLevel,
  2574. (LPBYTE)pDriverInfo,
  2575. &pInternalDriverFiles,
  2576. &dwFileCount,
  2577. FALSE,
  2578. pIniEnvironment,
  2579. TRUE))
  2580. {
  2581. continue;
  2582. }
  2583. if (!WaitRequiredForDriverUnload(pIniSpooler,
  2584. pIniEnvironment,
  2585. pIniVersion,
  2586. pIniDriver,
  2587. dwLevel,
  2588. (LPBYTE) pDriverInfo,
  2589. APD_STRICT_UPGRADE,
  2590. pInternalDriverFiles,
  2591. dwFileCount,
  2592. dwVersion,
  2593. (BOOL) dwDriverMoved,
  2594. &bSuccess) &&
  2595. bSuccess) {
  2596. // Upgrade has been completed, delete the registry key
  2597. if (pKeyName && (pTemp = AllocSplMem(sizeof(struct StringList)))) {
  2598. pTemp->pKeyName = pKeyName;
  2599. pTemp->dwVersionIndex = dwVersionIndex;
  2600. pTemp->pNext = pStart;
  2601. pStart = pTemp;
  2602. } else {
  2603. FreeSplMem(pKeyName);
  2604. }
  2605. pKeyName = NULL;
  2606. }
  2607. }
  2608. }
  2609. // Delete the keys for driver that have completed the upgrade
  2610. while (pTemp = pStart) {
  2611. pStart = pTemp->pNext;
  2612. hVersionKey = NULL;
  2613. if (RestoreVersionKey(hUpgradeKey,
  2614. pTemp->dwVersionIndex,
  2615. &hVersionKey)) {
  2616. RegDeleteKey(hVersionKey, pTemp->pKeyName);
  2617. RegCloseKey(hVersionKey);
  2618. }
  2619. FreeSplMem(pTemp->pKeyName);
  2620. FreeSplMem(pTemp);
  2621. }
  2622. CleanUp:
  2623. LeaveSplSem();
  2624. if (hUpgradeKey) {
  2625. RegCloseKey(hUpgradeKey);
  2626. }
  2627. if (hRootKey) {
  2628. RegCloseKey(hRootKey);
  2629. }
  2630. CleanUpgradeDirectories();
  2631. return;
  2632. }
  2633. VOID CleanUpResources(
  2634. LPWSTR pKeyName,
  2635. LPWSTR pSplName,
  2636. PDRIVER_INFO_6 pDriverInfo,
  2637. PINTERNAL_DRV_FILE *ppInternalDriverFiles,
  2638. DWORD dwFileCount)
  2639. /*++
  2640. Function Description: Frees resources allocated for driver upgrades
  2641. Parameters: pKeyName - registry key name
  2642. pSplName - IniSpooler name
  2643. pDriverInfo - driver info 4 pointer
  2644. pInternalDriverFiles - array of INTERNAL_DRV_FILE structures
  2645. dwFileCount -- number of files in file set
  2646. Return Values: NONE
  2647. --*/
  2648. {
  2649. if (pKeyName) {
  2650. FreeSplStr(pKeyName);
  2651. }
  2652. if (pSplName) {
  2653. FreeSplStr(pSplName);
  2654. }
  2655. FreeDriverInfo6(pDriverInfo);
  2656. CleanupInternalDriverInfo(*ppInternalDriverFiles, dwFileCount);
  2657. *ppInternalDriverFiles = NULL;
  2658. return;
  2659. }
  2660. BOOL RestoreParametersForUpgrade(
  2661. HKEY hUpgradeKey,
  2662. DWORD dwIndex,
  2663. LPWSTR *pKeyName,
  2664. LPWSTR *pSplName,
  2665. LPDWORD pdwLevel,
  2666. LPDWORD pdwDriverMoved,
  2667. PDRIVER_INFO_6 *ppDriverInfo)
  2668. /*++
  2669. Function Description: Retrieves the parameters for pending driver upgrades
  2670. Parameters: hUpgradeKey -- Registry key containing the upgrade information
  2671. dwIndex -- Index to enumerate
  2672. pKeyName -- pointer to a string containing the key name
  2673. pSplName -- pIniSpooler->pName
  2674. pdwLevel -- pointer to the driver_info level
  2675. pdwDriverMoved -- pointer to the flag indicating if any of the old driver files
  2676. were moved.
  2677. pDriverInfo -- pointer to driver_info struct
  2678. Return Values: TRUE if some driver has to be upgraded and the
  2679. parameters can be retrieved;
  2680. FALSE otherwise
  2681. --*/
  2682. {
  2683. BOOL bReturn = FALSE;
  2684. LPWSTR pDriverName = NULL;
  2685. PDRIVER_INFO_6 pDriver6 = NULL;
  2686. DWORD dwError, dwSize, *pVersion;
  2687. HKEY hDriverKey = NULL;
  2688. // Initialize pSplName & pKeyName
  2689. *pSplName = NULL;
  2690. *pKeyName = NULL;
  2691. *ppDriverInfo = NULL;
  2692. dwSize = MAX_PATH+1;
  2693. if (!(pDriver6 = AllocSplMem(sizeof(DRIVER_INFO_6))) ||
  2694. !(pDriverName = AllocSplMem(dwSize*sizeof (WCHAR)))) {
  2695. // Allocation failed
  2696. goto CleanUp;
  2697. }
  2698. dwError = RegEnumKeyEx(hUpgradeKey, dwIndex, pDriverName, &dwSize,
  2699. NULL, NULL, NULL, NULL);
  2700. if (dwError == ERROR_MORE_DATA) {
  2701. // Need a bigger buffer
  2702. FreeSplMem(pDriverName);
  2703. dwSize++; // count null terminator
  2704. if (!(pDriverName = AllocSplMem(dwSize*sizeof (WCHAR)))) {
  2705. // Allocation failed
  2706. goto CleanUp;
  2707. }
  2708. dwError = RegEnumKeyEx(hUpgradeKey, dwIndex, pDriverName, &dwSize,
  2709. NULL, NULL, NULL, NULL);
  2710. }
  2711. if (dwError) {
  2712. goto CleanUp;
  2713. }
  2714. if (RegCreateKeyEx(hUpgradeKey, pDriverName, 0,
  2715. NULL, 0, KEY_READ, NULL, &hDriverKey, NULL) ||
  2716. !RegGetValue(hDriverKey, L"Level", (LPBYTE *)&pdwLevel) ||
  2717. !RegGetValue(hDriverKey, L"DriverMoved", (LPBYTE *)&pdwDriverMoved) ||
  2718. !RegGetValue(hDriverKey, L"SplName", (LPBYTE *)&pSplName)) {
  2719. goto CleanUp;
  2720. }
  2721. switch (*pdwLevel) {
  2722. case 6:
  2723. dwSize = sizeof(FILETIME);
  2724. if (RegQueryValueEx( hDriverKey,
  2725. L"ftDriverDate",
  2726. NULL,
  2727. NULL,
  2728. (LPBYTE)&pDriver6->ftDriverDate,
  2729. &dwSize
  2730. )!=ERROR_SUCCESS) {
  2731. goto CleanUp;
  2732. }
  2733. dwSize = sizeof(DWORDLONG);
  2734. if (RegQueryValueEx( hDriverKey,
  2735. L"dwlDriverVersion",
  2736. NULL,
  2737. NULL,
  2738. (LPBYTE)&pDriver6->dwlDriverVersion,
  2739. &dwSize
  2740. )!=ERROR_SUCCESS){
  2741. goto CleanUp;
  2742. }
  2743. if (!RegGetValue(hDriverKey, L"pszMfgName", (LPBYTE *)&pDriver6->pszMfgName) ||
  2744. !RegGetValue(hDriverKey, L"pszOEMUrl", (LPBYTE *)&pDriver6->pszOEMUrl) ||
  2745. !RegGetValue(hDriverKey, L"pszHardwareID", (LPBYTE *)&pDriver6->pszHardwareID) ||
  2746. !RegGetValue(hDriverKey, L"pszProvider", (LPBYTE *)&pDriver6->pszProvider)
  2747. )
  2748. {
  2749. goto CleanUp;
  2750. }
  2751. case 4:
  2752. if (!RegGetValue(hDriverKey, L"pszzPreviousNames",
  2753. (LPBYTE *)&pDriver6->pszzPreviousNames)) {
  2754. goto CleanUp;
  2755. }
  2756. case 3:
  2757. if (!RegGetValue(hDriverKey, L"pDefaultDataType",
  2758. (LPBYTE *)&pDriver6->pDefaultDataType) ||
  2759. !RegGetValue(hDriverKey, L"pMonitorName",
  2760. (LPBYTE *)&pDriver6->pMonitorName) ||
  2761. !RegGetValue(hDriverKey, L"pDependentFiles",
  2762. (LPBYTE *)&pDriver6->pDependentFiles) ||
  2763. !RegGetValue(hDriverKey, L"pHelpFile",
  2764. (LPBYTE *)&pDriver6->pHelpFile)) {
  2765. goto CleanUp;
  2766. }
  2767. case 2:
  2768. pVersion = &pDriver6->cVersion;
  2769. if (!RegGetValue(hDriverKey, L"pConfigFile",
  2770. (LPBYTE *)&pDriver6->pConfigFile) ||
  2771. !RegGetValue(hDriverKey, L"pDataFile",
  2772. (LPBYTE *)&pDriver6->pDataFile) ||
  2773. !RegGetValue(hDriverKey, L"pDriverPath",
  2774. (LPBYTE *)&pDriver6->pDriverPath) ||
  2775. !RegGetValue(hDriverKey, L"pName",
  2776. (LPBYTE *)&pDriver6->pName) ||
  2777. !RegGetValue(hDriverKey, L"pEnvironment",
  2778. (LPBYTE *)&pDriver6->pEnvironment) ||
  2779. !RegGetValue(hDriverKey, L"cVersion",
  2780. (LPBYTE *)&pVersion)) {
  2781. goto CleanUp;
  2782. }
  2783. break;
  2784. default:
  2785. // Invalid level
  2786. goto CleanUp;
  2787. }
  2788. *ppDriverInfo = pDriver6;
  2789. *pKeyName = pDriverName;
  2790. pDriver6 = NULL;
  2791. pDriverName = NULL;
  2792. bReturn = TRUE;
  2793. CleanUp:
  2794. if (!bReturn) {
  2795. FreeDriverInfo6(pDriver6);
  2796. FreeSplMem(*pSplName);
  2797. *pSplName = NULL;
  2798. FreeSplMem(pDriverName);
  2799. }
  2800. if (hDriverKey) {
  2801. RegCloseKey(hDriverKey);
  2802. }
  2803. return bReturn;
  2804. }
  2805. VOID FreeDriverInfo6(
  2806. PDRIVER_INFO_6 pDriver6)
  2807. /*++
  2808. Function Description: Frees a driver_info_6 struct and the strings inside it.
  2809. Parameters: pDriver6 -- pointer to the driver_info_6 struct
  2810. Return Values: NONE
  2811. --*/
  2812. {
  2813. if (!pDriver6) {
  2814. return;
  2815. }
  2816. if (pDriver6->pName) {
  2817. FreeSplMem(pDriver6->pName);
  2818. }
  2819. if (pDriver6->pEnvironment) {
  2820. FreeSplMem(pDriver6->pEnvironment);
  2821. }
  2822. if (pDriver6->pDriverPath) {
  2823. FreeSplMem(pDriver6->pDriverPath);
  2824. }
  2825. if (pDriver6->pConfigFile) {
  2826. FreeSplMem(pDriver6->pConfigFile);
  2827. }
  2828. if (pDriver6->pHelpFile) {
  2829. FreeSplMem(pDriver6->pHelpFile);
  2830. }
  2831. if (pDriver6->pDataFile) {
  2832. FreeSplMem(pDriver6->pDataFile);
  2833. }
  2834. if (pDriver6->pDependentFiles) {
  2835. FreeSplMem(pDriver6->pDependentFiles);
  2836. }
  2837. if (pDriver6->pMonitorName) {
  2838. FreeSplMem(pDriver6->pMonitorName);
  2839. }
  2840. if (pDriver6->pDefaultDataType) {
  2841. FreeSplMem(pDriver6->pDefaultDataType);
  2842. }
  2843. if (pDriver6->pszzPreviousNames) {
  2844. FreeSplMem(pDriver6->pszzPreviousNames);
  2845. }
  2846. if (pDriver6->pszMfgName) {
  2847. FreeSplMem(pDriver6->pszMfgName);
  2848. }
  2849. if (pDriver6->pszOEMUrl) {
  2850. FreeSplMem(pDriver6->pszOEMUrl);
  2851. }
  2852. if (pDriver6->pszHardwareID) {
  2853. FreeSplMem(pDriver6->pszHardwareID);
  2854. }
  2855. if (pDriver6->pszProvider) {
  2856. FreeSplMem(pDriver6->pszProvider);
  2857. }
  2858. FreeSplMem(pDriver6);
  2859. return;
  2860. }
  2861. BOOL RegGetValue(
  2862. HKEY hDriverKey,
  2863. LPWSTR pValueName,
  2864. LPBYTE *pValue)
  2865. /*++
  2866. Function Description: This function retrieves values from the registry. It allocates the
  2867. necessary buffers which should be freed later. The value types are
  2868. DWORD, SZ or MULTI_SZ.
  2869. Parameters: hDriverKey -- handle to the registry key
  2870. pValueName -- name of the value to be queried
  2871. pValue -- pointer to pointer to store the result
  2872. Return Values: TRUE if successful; FALSE otherwise
  2873. --*/
  2874. {
  2875. BOOL bReturn = FALSE;
  2876. DWORD dwError, dwSize = 0, dwType;
  2877. LPBYTE pBuffer = NULL;
  2878. dwError = RegQueryValueEx(hDriverKey, pValueName, NULL, NULL, NULL, &dwSize);
  2879. if ((dwError == ERROR_SUCCESS) && (pBuffer = AllocSplMem(dwSize))) {
  2880. if (dwError = RegQueryValueEx(hDriverKey, pValueName,
  2881. NULL, &dwType, pBuffer, &dwSize)) {
  2882. goto CleanUp;
  2883. }
  2884. } else {
  2885. goto CleanUp;
  2886. }
  2887. if (dwType == REG_DWORD) {
  2888. // Store DWORD values directly in the location.
  2889. *((LPDWORD)*pValue) = *((LPDWORD)pBuffer);
  2890. FreeSplMem(pBuffer);
  2891. pBuffer = NULL;
  2892. } else {
  2893. // Return pointers for strings and MultiSz strings.
  2894. *((LPBYTE *)pValue) = pBuffer;
  2895. }
  2896. bReturn = TRUE;
  2897. CleanUp:
  2898. if (!bReturn && pBuffer) {
  2899. FreeSplMem(pBuffer);
  2900. }
  2901. return bReturn;
  2902. }
  2903. DWORD GetDriverFileVersion(
  2904. PINIVERSION pIniVersion,
  2905. LPWSTR pFileName)
  2906. /*++
  2907. Function Description: Retrieves the version number of the file
  2908. Parameters: pIniVersion -- pointer to PINIVERSION
  2909. pFileName -- file name
  2910. Return Values: file version number
  2911. --*/
  2912. {
  2913. PDRVREFCNT pdrc;
  2914. DWORD dwReturn = 0;
  2915. SplInSem();
  2916. if (!pIniVersion || !pFileName || !(*pFileName)) {
  2917. return dwReturn;
  2918. }
  2919. for (pdrc = pIniVersion->pDrvRefCnt;
  2920. pdrc;
  2921. pdrc = pdrc->pNext) {
  2922. if (lstrcmpi(pFileName,pdrc->szDrvFileName) == 0) {
  2923. dwReturn = pdrc->dwVersion;
  2924. break;
  2925. }
  2926. }
  2927. return dwReturn;
  2928. }
  2929. BOOL GetDriverFileCachedVersion(
  2930. IN PINIVERSION pIniVersion,
  2931. IN LPCWSTR pFileName,
  2932. OUT DWORD *pFileVersion
  2933. )
  2934. /*++
  2935. Routine Name:
  2936. GetDriverFileCachedVersion
  2937. Routine Description:
  2938. This routine returns a file's minor version.
  2939. The file must be an executable( file name ended in .DLL or .EXE )
  2940. pIniVersion keeps a linked list with information about all driver files.
  2941. To avoid service start up delays, the entries in this list aren't initialized
  2942. when Spooler starts. GetPrintDriverVersion loads the executable's data segment
  2943. and this will increase Spooler initialization time.
  2944. If the cache entry isn't initialized, call GetPrintDriverVersion and initialize it.
  2945. Else, return cached information.
  2946. When pIniVersion is NULL, just call GetPrintDriverVersion.
  2947. Arguments:
  2948. pIniVersion - pointer to PINIVERSION structure. Can be NULL.
  2949. pFileName - file name
  2950. pFileVersion - retrieve cached file version
  2951. VersionType - specifies which version to return
  2952. Return Value:
  2953. TRUE file version was successfully returned.
  2954. --*/
  2955. {
  2956. PDRVREFCNT pdrc;
  2957. BOOL bRetValue = FALSE;
  2958. BOOL bFound = FALSE;
  2959. SplInSem();
  2960. if (pFileVersion && pFileName && *pFileName)
  2961. {
  2962. *pFileVersion = 0;
  2963. //
  2964. // Don't do anything for non-executable files
  2965. //
  2966. if (!IsEXEFile(pFileName))
  2967. {
  2968. bRetValue = TRUE;
  2969. }
  2970. else
  2971. {
  2972. //
  2973. // If pIniVersion is NULL, then we cannot access cached information.
  2974. // This code path was written for calls from SplCopyNumberOfFiles(files.c)
  2975. //
  2976. if (!pIniVersion)
  2977. {
  2978. bRetValue = GetPrintDriverVersion(pFileName,
  2979. NULL,
  2980. pFileVersion);
  2981. }
  2982. else
  2983. {
  2984. //
  2985. // Search the entry in pIniVersion's list of files
  2986. //
  2987. for (pdrc = pIniVersion->pDrvRefCnt;
  2988. pdrc;
  2989. pdrc = pdrc->pNext)
  2990. {
  2991. LPCWSTR pFile = FindFileName(pFileName);
  2992. if (pFile && lstrcmpi(pFile, pdrc->szDrvFileName) == 0)
  2993. {
  2994. //
  2995. // Return cached information.
  2996. //
  2997. if(pdrc->bInitialized)
  2998. {
  2999. *pFileVersion = pdrc->dwFileMinorVersion;
  3000. bRetValue = TRUE;
  3001. }
  3002. else if (GetPrintDriverVersion(pFileName,
  3003. &pdrc->dwFileMajorVersion,
  3004. &pdrc->dwFileMinorVersion))
  3005. {
  3006. //
  3007. // Mark the entry as initialized so next time we don't have
  3008. // to do the work of calling GetPrintDriverVersion.
  3009. //
  3010. pdrc->bInitialized = TRUE;
  3011. *pFileVersion = pdrc->dwFileMinorVersion;
  3012. bRetValue = TRUE;
  3013. }
  3014. //
  3015. // Break the loop when file found.
  3016. //
  3017. bFound = TRUE;
  3018. break;
  3019. }
  3020. }
  3021. }
  3022. }
  3023. }
  3024. if (!bFound)
  3025. {
  3026. bRetValue = TRUE;
  3027. }
  3028. return bRetValue;
  3029. }
  3030. VOID IncrementFileVersion(
  3031. PINIVERSION pIniVersion,
  3032. LPCWSTR pFileName)
  3033. /*++
  3034. Function Description: Increments the version number of the file.
  3035. Parameters: pIniVersion -- pointer to PINIVERSION
  3036. pFileName -- file name
  3037. Return Values: NONE
  3038. --*/
  3039. {
  3040. PDRVREFCNT pdrc;
  3041. SplInSem();
  3042. if (!pIniVersion || !pFileName || !(*pFileName)) {
  3043. return;
  3044. }
  3045. for (pdrc = pIniVersion->pDrvRefCnt;
  3046. pdrc;
  3047. pdrc = pdrc->pNext) {
  3048. if (lstrcmpi(pFileName,pdrc->szDrvFileName) == 0) {
  3049. pdrc->dwVersion++;
  3050. break;
  3051. }
  3052. }
  3053. return;
  3054. }
  3055. BOOL
  3056. CompleteDriverUpgrade(
  3057. IN PINISPOOLER pIniSpooler,
  3058. IN PINIENVIRONMENT pIniEnvironment,
  3059. IN PINIVERSION pIniVersion,
  3060. IN PINIDRIVER pIniDriver,
  3061. IN DWORD dwLevel,
  3062. IN LPBYTE pDriverInfo,
  3063. IN DWORD dwFileCopyFlags,
  3064. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  3065. IN DWORD dwFileCount,
  3066. IN DWORD dwVersion,
  3067. IN DWORD dwTempDir,
  3068. IN BOOL bDriverMoved,
  3069. IN BOOL bDriverFileMoved,
  3070. IN BOOL bConfigFileMoved
  3071. )
  3072. /*++
  3073. Function Description: This functions updates the INIDRIVER struct and calls DrvUpgradePrinter
  3074. and DrvDriverEvent. An event for adding printer drivers is logged.
  3075. Parameters: pIniSpooler -- pointer to INISPOOLER
  3076. pIniEnvironment -- pointer to INIENVIRONMENT
  3077. pIniVersion -- pointer to INIVERSION
  3078. pIniDriver -- pointer to INIDRIVER
  3079. dwLevel -- driver_info level
  3080. pDriverInfo -- pointer to driver_info
  3081. dwFileCopyFlags -- AddPrinterDriver file copy flags.
  3082. pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  3083. dwFileCount -- number of files in file set
  3084. dwVersion -- driver version
  3085. dwTempDir -- temp directory number for loaded drivers
  3086. bDriverMoved -- Were any files moved to the Old directory ?
  3087. bDriverFileMoved -- driver file moved ?
  3088. bConfigFileMoved -- config file moved ?
  3089. Return Values: TRUE if successful; FALSE otherwise
  3090. --*/
  3091. {
  3092. WCHAR szDirectory[MAX_PATH];
  3093. LPWSTR pOldDir, pTemp, pEnvironment = szEnvironment;
  3094. LPBYTE pDriver4 = NULL, pUpgradeInfo2 = NULL;
  3095. DWORD cbBuf;
  3096. PINIMONITOR pIniLangMonitor = NULL;
  3097. PINISPOOLER pTempIniSpooler, pIniNextSpooler;
  3098. PINIDRIVER pTempIniDriver = NULL;
  3099. PINIPRINTER pFixUpIniPrinter;
  3100. PINIVERSION pTempIniVersion;
  3101. LPDRIVER_INFO_4 pDrvInfo4 = NULL;
  3102. BOOL bUpdatePrinters = FALSE;
  3103. // Save the driver_info_4 struct for the old driver. This is passed to the
  3104. // DrvUpgradePrinter call.
  3105. if (pIniDriver && bDriverMoved) {
  3106. cbBuf = GetDriverInfoSize(pIniDriver, 4, pIniVersion, pIniEnvironment,
  3107. NULL, pIniSpooler);
  3108. if (pDriver4 = (LPBYTE) AllocSplMem(cbBuf)) {
  3109. pUpgradeInfo2 = CopyIniDriverToDriverInfo(pIniEnvironment, pIniVersion,
  3110. pIniDriver, 4, pDriver4,
  3111. pDriver4 + cbBuf, NULL, pIniSpooler);
  3112. }
  3113. }
  3114. // Update the driver struct
  3115. pIniDriver = CreateDriverEntry(pIniEnvironment,
  3116. pIniVersion,
  3117. dwLevel,
  3118. pDriverInfo,
  3119. dwFileCopyFlags,
  3120. pIniSpooler,
  3121. pInternalDriverFiles,
  3122. dwFileCount,
  3123. dwTempDir,
  3124. pIniDriver);
  3125. // Fail the call if pIniDriver failed
  3126. if (pIniDriver == NULL) {
  3127. return FALSE;
  3128. }
  3129. // Increment version numbers
  3130. if (bDriverFileMoved) {
  3131. IncrementFileVersion(pIniVersion, FindFileName(pInternalDriverFiles[0].pFileName));
  3132. }
  3133. if (bConfigFileMoved) {
  3134. IncrementFileVersion(pIniVersion, FindFileName(pInternalDriverFiles[1].pFileName));
  3135. }
  3136. pDrvInfo4 = (LPDRIVER_INFO_4) pDriverInfo;
  3137. if (pDrvInfo4->pEnvironment &&
  3138. *pDrvInfo4->pEnvironment) {
  3139. pEnvironment = pDrvInfo4->pEnvironment;
  3140. }
  3141. if ((dwLevel == 3 || dwLevel == 4 || dwLevel ==6) &&
  3142. pDrvInfo4->pMonitorName &&
  3143. *pDrvInfo4->pMonitorName &&
  3144. _wcsicmp(pEnvironment, szWin95Environment)) {
  3145. pIniLangMonitor = FindMonitor(pDrvInfo4->pMonitorName,
  3146. pLocalIniSpooler);
  3147. }
  3148. if (pIniLangMonitor &&
  3149. pIniDriver->pIniLangMonitor != pIniLangMonitor) {
  3150. if (pIniDriver->pIniLangMonitor)
  3151. pIniDriver->pIniLangMonitor->cRef--;
  3152. if (pIniLangMonitor)
  3153. pIniLangMonitor->cRef++;
  3154. pIniDriver->pIniLangMonitor = pIniLangMonitor;
  3155. }
  3156. // Increment cRefs for leaving SplSem
  3157. INCSPOOLERREF( pIniSpooler );
  3158. INCDRIVERREF( pIniDriver );
  3159. pIniEnvironment->cRef++;
  3160. // Call DrvDriverEvent in the Driver. Environment and version checks are
  3161. // done inside NotifyDriver.
  3162. NotifyDriver(pIniSpooler,
  3163. pIniEnvironment,
  3164. pIniVersion,
  3165. pIniDriver,
  3166. DRIVER_EVENT_INITIALIZE,
  3167. 0);
  3168. bUpdatePrinters = DriverAddedOrUpgraded(pInternalDriverFiles, dwFileCount);
  3169. //
  3170. // Call DrvUprgadePrinter if the driver added belongs to this version
  3171. // and environment. And the pIniSpooler is not a cluster spooler
  3172. //
  3173. if (!(pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER) &&
  3174. pThisEnvironment == pIniEnvironment) {
  3175. // Walk through all pIniSpoolers that print.
  3176. INCSPOOLERREF( pLocalIniSpooler );
  3177. for( pTempIniSpooler = pLocalIniSpooler;
  3178. pTempIniSpooler;
  3179. pTempIniSpooler = pIniNextSpooler ){
  3180. //
  3181. // Do not touch the driver belonging to cluster spoolers. Cluster spoolers
  3182. // handle thier drivers themselves
  3183. //
  3184. if (pTempIniSpooler->SpoolerFlags & SPL_PRINT && !(pTempIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER)){
  3185. // Walk all the printers and see if anyone is using this driver.
  3186. for ( pFixUpIniPrinter = pTempIniSpooler->pIniPrinter;
  3187. pFixUpIniPrinter != NULL;
  3188. pFixUpIniPrinter = pFixUpIniPrinter->pNext ) {
  3189. // Does this Printer Have this driver ?
  3190. if ( lstrcmpi( pFixUpIniPrinter->pIniDriver->pName,
  3191. pIniDriver->pName ) == STRINGS_ARE_EQUAL ) {
  3192. pTempIniDriver = FindCompatibleDriver( pIniEnvironment,
  3193. &pTempIniVersion,
  3194. pIniDriver->pName,
  3195. dwVersion,
  3196. FIND_COMPATIBLE_VERSION | DRIVER_UPGRADE);
  3197. SPLASSERT( pTempIniDriver != NULL );
  3198. //
  3199. // Does this Printer Has a Newer Driver it should be using ?
  3200. // Note: within the same version, pIniPrinter->pIniDriver
  3201. // does not change (the fields are updated in an upgrade,
  3202. // but the same pIniDriver is used).
  3203. //
  3204. // Version 2 is not compatible with anything else,
  3205. // so the pIniDrivers won't change in SUR.
  3206. //
  3207. if ( pTempIniDriver != pFixUpIniPrinter->pIniDriver ) {
  3208. DECDRIVERREF( pFixUpIniPrinter->pIniDriver );
  3209. pFixUpIniPrinter->pIniDriver = pTempIniDriver;
  3210. INCDRIVERREF( pFixUpIniPrinter->pIniDriver );
  3211. }
  3212. }
  3213. }
  3214. pOldDir = NULL;
  3215. if ( !bDriverMoved ) {
  3216. // Use older version of the driver
  3217. pTempIniDriver = FindCompatibleDriver( pIniEnvironment,
  3218. &pTempIniVersion,
  3219. pIniDriver->pName,
  3220. (dwVersion>2)?(dwVersion - 1):dwVersion,
  3221. FIND_ANY_VERSION | DRIVER_UPGRADE);
  3222. if ( pTempIniDriver != NULL ) {
  3223. SPLASSERT( pTempIniVersion != NULL );
  3224. GetDriverVersionDirectory( szDirectory,
  3225. COUNTOF(szDirectory),
  3226. pIniSpooler,
  3227. pThisEnvironment,
  3228. pTempIniVersion,
  3229. pTempIniDriver,
  3230. NULL );
  3231. if ( DirectoryExists( szDirectory )) {
  3232. pOldDir = (LPWSTR) szDirectory;
  3233. }
  3234. cbBuf = GetDriverInfoSize(pTempIniDriver, 4, pTempIniVersion,
  3235. pIniEnvironment, NULL, pIniSpooler);
  3236. if (pDriver4 = (LPBYTE) AllocSplMem(cbBuf)) {
  3237. pUpgradeInfo2 = CopyIniDriverToDriverInfo(pIniEnvironment,
  3238. pTempIniVersion,
  3239. pTempIniDriver,
  3240. 4,
  3241. pDriver4,
  3242. pDriver4 + cbBuf,
  3243. NULL,
  3244. pIniSpooler);
  3245. }
  3246. }
  3247. } else {
  3248. if((StrNCatBuff(szDirectory,
  3249. MAX_PATH,
  3250. pIniSpooler->pDir,
  3251. L"\\drivers\\",
  3252. pIniEnvironment->pDirectory,
  3253. L"\\",
  3254. pIniVersion->szDirectory,
  3255. L"\\Old",
  3256. NULL) == ERROR_SUCCESS))
  3257. {
  3258. pOldDir = (LPWSTR) szDirectory;
  3259. }
  3260. else
  3261. {
  3262. // ?????
  3263. }
  3264. }
  3265. INCDRIVERREF(pIniDriver);
  3266. if( bUpdatePrinters) {
  3267. ForEachPrinterCallDriverDrvUpgrade(pTempIniSpooler,
  3268. pIniDriver,
  3269. pOldDir,
  3270. pInternalDriverFiles,
  3271. dwFileCount,
  3272. pUpgradeInfo2 ? pDriver4
  3273. : NULL);
  3274. }
  3275. DECDRIVERREF(pIniDriver);
  3276. }
  3277. pIniNextSpooler = pTempIniSpooler->pIniNextSpooler;
  3278. if ( pIniNextSpooler ) {
  3279. INCSPOOLERREF( pIniNextSpooler );
  3280. }
  3281. DECSPOOLERREF( pTempIniSpooler );
  3282. }
  3283. }
  3284. //
  3285. // Perform driver upgrade if the pIniSpooler is a cluster spooler
  3286. //
  3287. if (pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER &&
  3288. !lstrcmpi(pIniEnvironment->pName, szEnvironment)) {
  3289. DBGMSG(DBG_CLUSTER, ("CompleteDriverUpgrade searching for cluster spooler printers\n"));
  3290. //
  3291. // Walk all the printers and see if anyone is using this driver.
  3292. //
  3293. for ( pFixUpIniPrinter = pIniSpooler->pIniPrinter;
  3294. pFixUpIniPrinter != NULL;
  3295. pFixUpIniPrinter = pFixUpIniPrinter->pNext )
  3296. {
  3297. //
  3298. // Does this Printer Have this driver ?
  3299. //
  3300. if (lstrcmpi(pFixUpIniPrinter->pIniDriver->pName, pIniDriver->pName) == STRINGS_ARE_EQUAL)
  3301. {
  3302. pTempIniDriver = FindCompatibleDriver(pIniEnvironment,
  3303. &pTempIniVersion,
  3304. pIniDriver->pName,
  3305. dwVersion,
  3306. FIND_COMPATIBLE_VERSION | DRIVER_UPGRADE);
  3307. SPLASSERT( pTempIniDriver != NULL );
  3308. //
  3309. // Does this Printer Has a Newer Driver it should be using ?
  3310. // Note: within the same version, pIniPrinter->pIniDriver
  3311. // does not change (the fields are updated in an upgrade,
  3312. // but the same pIniDriver is used).
  3313. //
  3314. // Version 2 is not compatible with anything else,
  3315. // so the pIniDrivers won't change in SUR.
  3316. //
  3317. if ( pTempIniDriver != pFixUpIniPrinter->pIniDriver )
  3318. {
  3319. DECDRIVERREF( pFixUpIniPrinter->pIniDriver );
  3320. pFixUpIniPrinter->pIniDriver = pTempIniDriver;
  3321. INCDRIVERREF( pFixUpIniPrinter->pIniDriver );
  3322. }
  3323. }
  3324. }
  3325. pOldDir = NULL;
  3326. if ( !bDriverMoved )
  3327. {
  3328. // Use older version of the driver
  3329. pTempIniDriver = FindCompatibleDriver( pIniEnvironment,
  3330. &pTempIniVersion,
  3331. pIniDriver->pName,
  3332. (dwVersion>2)?(dwVersion - 1):dwVersion,
  3333. FIND_ANY_VERSION | DRIVER_UPGRADE);
  3334. if ( pTempIniDriver != NULL )
  3335. {
  3336. SPLASSERT( pTempIniVersion != NULL );
  3337. GetDriverVersionDirectory( szDirectory,
  3338. COUNTOF(szDirectory),
  3339. pIniSpooler,
  3340. pIniEnvironment,
  3341. pTempIniVersion,
  3342. pTempIniDriver,
  3343. NULL );
  3344. if ( DirectoryExists( szDirectory ))
  3345. {
  3346. pOldDir = (LPWSTR) szDirectory;
  3347. }
  3348. cbBuf = GetDriverInfoSize(pTempIniDriver, 4, pTempIniVersion, pIniEnvironment, NULL, pIniSpooler);
  3349. if (pDriver4 = (LPBYTE) AllocSplMem(cbBuf))
  3350. {
  3351. pUpgradeInfo2 = CopyIniDriverToDriverInfo(pIniEnvironment,
  3352. pTempIniVersion,
  3353. pTempIniDriver,
  3354. 4,
  3355. pDriver4,
  3356. pDriver4 + cbBuf,
  3357. NULL,
  3358. pIniSpooler);
  3359. }
  3360. }
  3361. else
  3362. {
  3363. if((StrNCatBuff(szDirectory,
  3364. MAX_PATH,
  3365. pIniSpooler->pDir,
  3366. L"\\drivers\\",
  3367. pIniEnvironment->pDirectory,
  3368. L"\\",
  3369. pIniVersion->szDirectory,
  3370. L"\\Old",
  3371. NULL) == ERROR_SUCCESS))
  3372. {
  3373. pOldDir = (LPWSTR) szDirectory;
  3374. }
  3375. }
  3376. INCDRIVERREF(pIniDriver);
  3377. if( bUpdatePrinters)
  3378. {
  3379. ForEachPrinterCallDriverDrvUpgrade(pIniSpooler,
  3380. pIniDriver,
  3381. pOldDir,
  3382. pInternalDriverFiles,
  3383. dwFileCount,
  3384. pUpgradeInfo2 ? pDriver4 : NULL);
  3385. }
  3386. DECDRIVERREF(pIniDriver);
  3387. }
  3388. }
  3389. if (pDriver4) {
  3390. FreeSplMem(pDriver4);
  3391. pDriver4 = NULL;
  3392. }
  3393. // Log Event - Successfully adding the printer driver.
  3394. //
  3395. // Note we use pLocalIniSpooler here because drivers are currently
  3396. // global accross all spoolers and we always want it logged
  3397. pTemp = BuildFilesCopiedAsAString(pInternalDriverFiles, dwFileCount);
  3398. SplLogEvent(pLocalIniSpooler,
  3399. LOG_WARNING,
  3400. MSG_DRIVER_ADDED,
  3401. TRUE,
  3402. pIniDriver->pName,
  3403. pIniEnvironment->pName,
  3404. pIniVersion->pName,
  3405. pTemp,
  3406. NULL);
  3407. FreeSplMem(pTemp);
  3408. // Decrement cRefs after reentering SplSem
  3409. DECSPOOLERREF( pIniSpooler );
  3410. DECDRIVERREF( pIniDriver );
  3411. pIniEnvironment->cRef--;
  3412. SetPrinterChange(NULL,
  3413. NULL,
  3414. NULL,
  3415. PRINTER_CHANGE_ADD_PRINTER_DRIVER,
  3416. pLocalIniSpooler );
  3417. return TRUE;
  3418. }
  3419. VOID CleanUpgradeDirectories()
  3420. /*++
  3421. Function Description: Deletes the Old and New directories if there are
  3422. no pending driver upgrades.
  3423. Parameters: NONE
  3424. Return Values: NONE
  3425. --*/
  3426. {
  3427. DWORD dwError, dwSize, dwVersionIndex;
  3428. BOOL bPendingUpgrade = FALSE;
  3429. HKEY hRootKey = NULL, hUpgradeKey = NULL, hVersionKey = NULL;
  3430. WCHAR pDriverDir[MAX_PATH], pCleanupDir[MAX_PATH];
  3431. PINIENVIRONMENT pIniEnvironment;
  3432. PINIVERSION pIniVersion;
  3433. // Open the registry key
  3434. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRegistryRoot, 0,
  3435. NULL, 0, KEY_ALL_ACCESS, NULL, &hRootKey, NULL) ||
  3436. RegCreateKeyEx(hRootKey, szPendingUpgrades, 0,
  3437. NULL, 0, KEY_ALL_ACCESS, NULL, &hUpgradeKey, NULL)) {
  3438. goto CleanUp;
  3439. }
  3440. // loop thru the version entries
  3441. for (dwVersionIndex = 0, hVersionKey = NULL;
  3442. RestoreVersionKey(hUpgradeKey, dwVersionIndex, &hVersionKey);
  3443. RegCloseKey(hVersionKey), hVersionKey = NULL, ++dwVersionIndex) {
  3444. // Search for pending upgrade keys
  3445. dwSize = MAX_PATH;
  3446. dwError = RegEnumKeyEx(hVersionKey, 0, pDriverDir, &dwSize,
  3447. NULL, NULL, NULL, NULL);
  3448. if (dwError != ERROR_NO_MORE_ITEMS) {
  3449. bPendingUpgrade = TRUE;
  3450. break;
  3451. }
  3452. }
  3453. // If there aren't any pending driver upgrades, delete the Old and
  3454. // new directories and the files within.
  3455. if ( pLocalIniSpooler) {
  3456. PINISPOOLER pIniSpooler;
  3457. for (pIniSpooler = pLocalIniSpooler;
  3458. pIniSpooler;
  3459. pIniSpooler = pIniSpooler->pIniNextSpooler) {
  3460. if (pIniSpooler->SpoolerFlags & SPL_TYPE_LOCAL ||
  3461. pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER) {
  3462. for (pIniEnvironment = pIniSpooler->pIniEnvironment;
  3463. pIniEnvironment;
  3464. pIniEnvironment = pIniEnvironment->pNext) {
  3465. for (pIniVersion = pIniEnvironment->pIniVersion;
  3466. pIniVersion;
  3467. pIniVersion = pIniVersion->pNext) {
  3468. if( StrNCatBuff( pDriverDir,
  3469. COUNTOF(pDriverDir),
  3470. pIniSpooler->pDir,
  3471. L"\\drivers\\",
  3472. pIniEnvironment->pDirectory,
  3473. L"\\",
  3474. pIniVersion->szDirectory,
  3475. NULL) != ERROR_SUCCESS )
  3476. continue;
  3477. if( StrNCatBuff( pCleanupDir,
  3478. COUNTOF(pCleanupDir),
  3479. pDriverDir,
  3480. L"\\Old",
  3481. NULL) != ERROR_SUCCESS )
  3482. continue;
  3483. DeleteDirectoryRecursively(pCleanupDir, FALSE);
  3484. if( StrNCatBuff( pCleanupDir,
  3485. COUNTOF(pCleanupDir),
  3486. pDriverDir,
  3487. L"\\New",
  3488. NULL) != ERROR_SUCCESS )
  3489. continue;
  3490. if (!bPendingUpgrade) {
  3491. DeleteAllFilesAndDirectory(pCleanupDir, FALSE);
  3492. }
  3493. }
  3494. }
  3495. }
  3496. }
  3497. }
  3498. CleanUp:
  3499. if (hVersionKey) {
  3500. RegCloseKey(hVersionKey);
  3501. }
  3502. if (hUpgradeKey) {
  3503. RegCloseKey(hUpgradeKey);
  3504. }
  3505. if (hRootKey) {
  3506. RegCloseKey(hRootKey);
  3507. }
  3508. return;
  3509. }
  3510. BOOL
  3511. CheckFileCopyOptions(
  3512. PINIENVIRONMENT pIniEnvironment,
  3513. PINIVERSION pIniVersion,
  3514. PINIDRIVER pIniDriver,
  3515. PINTERNAL_DRV_FILE pInternalDriverFiles,
  3516. DWORD dwFileCount,
  3517. DWORD dwFileCopyFlags,
  3518. LPBOOL pbSucceeded
  3519. )
  3520. /*++
  3521. Function Description:
  3522. CheckFileCopyOptions examines the timestamps of the source and
  3523. target files and determines if strict upgrade/downgrade can fail.
  3524. Parameters:
  3525. pIniEnvironment - pointer to a PINIENVIRONMENT structure
  3526. pIniVersion - pointer to a PINIVERSION structure
  3527. pIniDriver - pointer to the old INIDRIVER structure
  3528. pInternalDriverFiles - array of INTERNAL_DRV_FILE structures
  3529. dwFileCount - number of files in file set
  3530. dwFileCopyFlags - file copying options.
  3531. pbSucceeded - flag to indicate the AddPrinterDriver call succeeded.
  3532. Return Values:
  3533. TRUE - We need to copy any files. *pbSucceeded is unchanged.
  3534. FALSE - We don't need to copy, either because the entire call failed
  3535. (e.g., strict upgrade but older source files), or because we don't
  3536. need to do anything. *pbSucceeded indicates if the API call should
  3537. succeed (the latter case).
  3538. --*/
  3539. {
  3540. BOOL bReturn = FALSE, bInSem = TRUE, bSameMainDriverName = FALSE;
  3541. LPWSTR pDrvDestDir = NULL, pICMDestDir = NULL, pNewDestDir = NULL;
  3542. LPWSTR pTargetFileName = NULL, pFileName;
  3543. DWORD dwCount;
  3544. WIN32_FIND_DATA DestFileData, SourceFileData;
  3545. HANDLE hFileExists;
  3546. DWORD TimeStampComparison;
  3547. enum { Equal, Newer, Older } DriverComparison;
  3548. DWORD dwDriverVersion;
  3549. if (!pbSucceeded) {
  3550. goto CleanUp;
  3551. }
  3552. *pbSucceeded = FALSE;
  3553. SplInSem();
  3554. switch (dwFileCopyFlags) {
  3555. case APD_COPY_ALL_FILES:
  3556. // Nothing to check
  3557. bReturn = TRUE;
  3558. break;
  3559. case APD_COPY_NEW_FILES:
  3560. // Check if the driver file sets are different
  3561. if (pIniDriver)
  3562. {
  3563. pFileName = wcsrchr(pInternalDriverFiles[0].pFileName, L'\\');
  3564. if (pFileName && pIniDriver->pDriverFile &&
  3565. !_wcsicmp(pFileName+1, pIniDriver->pDriverFile))
  3566. {
  3567. bSameMainDriverName = TRUE;
  3568. }
  3569. }
  3570. case APD_STRICT_UPGRADE:
  3571. case APD_STRICT_DOWNGRADE:
  3572. // Set up the destination directories
  3573. if (!(pDrvDestDir = AllocSplMem( INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH + 1 )) ||
  3574. !(pNewDestDir = AllocSplMem( INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH + 1 )) ||
  3575. !(pTargetFileName = AllocSplMem( INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH + 1 ))) {
  3576. goto CleanUp;
  3577. }
  3578. // Regular driver directory
  3579. if( !GetEnvironmentScratchDirectory( pDrvDestDir, MAX_PATH, pIniEnvironment, FALSE ) ) {
  3580. goto CleanUp;
  3581. }
  3582. wcscat(pDrvDestDir, L"\\" );
  3583. wcscat(pDrvDestDir, pIniVersion->szDirectory );
  3584. // New driver files directory where files may be stored temporarily
  3585. wcscpy(pNewDestDir, pDrvDestDir);
  3586. wcscat(pNewDestDir, L"\\New");
  3587. if (!wcscmp(pIniEnvironment->pName, szWin95Environment)) {
  3588. if (!(pICMDestDir = AllocSplMem( INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH + 1 ))) {
  3589. goto CleanUp;
  3590. }
  3591. // ICM directory for win95
  3592. wcscpy(pICMDestDir, pDrvDestDir);
  3593. wcscat(pICMDestDir, L"\\Color");
  3594. }
  3595. if (pIniDriver) {
  3596. INCDRIVERREF(pIniDriver);
  3597. }
  3598. LeaveSplSem();
  3599. bInSem = FALSE;
  3600. // Examine the timestamps for the source and the target files.
  3601. for (dwCount = 0; dwCount < dwFileCount; ++dwCount) {
  3602. // Get Source File Date & Time Stamp
  3603. hFileExists = FindFirstFile(pInternalDriverFiles[dwCount].pFileName, &SourceFileData );
  3604. if (hFileExists == INVALID_HANDLE_VALUE) {
  3605. goto CleanUp;
  3606. } else {
  3607. FindClose(hFileExists);
  3608. }
  3609. if (!(pFileName = wcsrchr(pInternalDriverFiles[dwCount].pFileName, L'\\'))) {
  3610. goto CleanUp;
  3611. }
  3612. //
  3613. // Skip past the backslash.
  3614. //
  3615. ++pFileName;
  3616. if (pICMDestDir && IsAnICMFile(pInternalDriverFiles[dwCount].pFileName)) {
  3617. // Check in the Color Directory
  3618. wsprintf(pTargetFileName, L"%ws\\%ws", pICMDestDir, pFileName);
  3619. hFileExists = FindFirstFile(pTargetFileName, &DestFileData);
  3620. } else {
  3621. LPWSTR pszTestFileName;
  3622. if ((dwCount == 0) && !bSameMainDriverName && pIniDriver) {
  3623. //
  3624. // We're processing the main driver file. The server's
  3625. // file doesn't exist on the client, but the client does
  3626. // have a version of this driver.
  3627. //
  3628. // Instead of checking the server's file name on the
  3629. // client, we want to check the client's IniDriver->pDriver
  3630. // to see which is newer.
  3631. //
  3632. // For example, server has rasdd, while client has unidrv.
  3633. // Client does not have rasdd, so we would normally copy
  3634. // rasdd down to the client and change the DRIVER_INFO.
  3635. //
  3636. // Instead, we want to see if the server's unidrv is
  3637. // newer than the client's rasdd. If so, then we
  3638. // need to upgrade.
  3639. //
  3640. // Even if the client did have a new unidrv (even a
  3641. // really new one), we still want to upgrade the
  3642. // client's DRIVER_INFO.
  3643. //
  3644. pszTestFileName = pIniDriver->pDriverFile;
  3645. } else {
  3646. pszTestFileName = pFileName;
  3647. }
  3648. // Check in the new directory first
  3649. wsprintf(pTargetFileName, L"%ws\\%ws", pNewDestDir, pszTestFileName);
  3650. hFileExists = FindFirstFile(pTargetFileName, &DestFileData);
  3651. if (hFileExists == INVALID_HANDLE_VALUE) {
  3652. // Check in the regular driver directory
  3653. wsprintf(pTargetFileName, L"%ws\\%ws", pDrvDestDir, pszTestFileName);
  3654. hFileExists = FindFirstFile(pTargetFileName, &DestFileData);
  3655. }
  3656. }
  3657. if (hFileExists != INVALID_HANDLE_VALUE) {
  3658. FindClose(hFileExists);
  3659. EnterSplSem();
  3660. if (pIniDriver) {
  3661. DECDRIVERREF(pIniDriver);
  3662. }
  3663. bInSem = TRUE;
  3664. if (!GetDriverFileCachedVersion(pIniVersion, pTargetFileName, &dwDriverVersion)) {
  3665. SetLastError(ERROR_CAN_NOT_COMPLETE);
  3666. goto CleanUp;
  3667. }
  3668. if (pIniDriver) {
  3669. INCDRIVERREF(pIniDriver);
  3670. }
  3671. LeaveSplSem();
  3672. bInSem = FALSE;
  3673. DriverComparison = pInternalDriverFiles[dwCount].dwVersion == dwDriverVersion ?
  3674. Equal :
  3675. pInternalDriverFiles[dwCount].dwVersion > dwDriverVersion ?
  3676. Newer :
  3677. Older;
  3678. if (DriverComparison == Equal) {
  3679. TimeStampComparison = CompareFileTime( &SourceFileData.ftLastWriteTime,
  3680. &DestFileData.ftLastWriteTime );
  3681. DriverComparison = TimeStampComparison == 1 ?
  3682. Newer :
  3683. TimeStampComparison == -1 ?
  3684. Older :
  3685. Equal;
  3686. }
  3687. switch (DriverComparison) {
  3688. case Newer:
  3689. // Source file newer than the target. Strict downgrade will fail.
  3690. if (dwFileCopyFlags == APD_STRICT_DOWNGRADE) {
  3691. SetLastError(ERROR_CAN_NOT_COMPLETE);
  3692. goto CleanUp;
  3693. }
  3694. break;
  3695. case Older:
  3696. // Target file newer than the source. Strict upgrade will fail.
  3697. if (dwFileCopyFlags == APD_STRICT_UPGRADE) {
  3698. SetLastError(ERROR_CAN_NOT_COMPLETE);
  3699. goto CleanUp;
  3700. } else {
  3701. //
  3702. // If we are doing a copy new files (non-strict upgrade),
  3703. // and the main driver files are different, and
  3704. // the driver is already installed, then we want to use
  3705. // the existing driver.
  3706. //
  3707. if ((dwFileCopyFlags == APD_COPY_NEW_FILES) &&
  3708. (dwCount == 0) && !bSameMainDriverName &&
  3709. pIniDriver)
  3710. {
  3711. *pbSucceeded = TRUE;
  3712. goto CleanUp;
  3713. }
  3714. }
  3715. break;
  3716. default:
  3717. // file times are the same
  3718. break;
  3719. }
  3720. }
  3721. }
  3722. bReturn = TRUE;
  3723. break;
  3724. default:
  3725. // Unknown flag
  3726. SetLastError(ERROR_INVALID_PARAMETER);
  3727. break;
  3728. }
  3729. CleanUp:
  3730. if (!bInSem) {
  3731. EnterSplSem();
  3732. if (pIniDriver) {
  3733. DECDRIVERREF(pIniDriver);
  3734. }
  3735. }
  3736. if (pDrvDestDir) {
  3737. FreeSplMem(pDrvDestDir);
  3738. }
  3739. if (pTargetFileName) {
  3740. FreeSplMem(pTargetFileName);
  3741. }
  3742. if (pICMDestDir) {
  3743. FreeSplMem(pICMDestDir);
  3744. }
  3745. if (pNewDestDir) {
  3746. FreeSplMem(pNewDestDir);
  3747. }
  3748. return bReturn;
  3749. }
  3750. BOOL
  3751. LocalDeletePrinterDriver(
  3752. LPWSTR pName,
  3753. LPWSTR pEnvironment,
  3754. LPWSTR pDriverName
  3755. )
  3756. {
  3757. BOOL bReturn;
  3758. bReturn = LocalDeletePrinterDriverEx( pName,
  3759. pEnvironment,
  3760. pDriverName,
  3761. 0,
  3762. 0);
  3763. return bReturn;
  3764. }
  3765. BOOL
  3766. LocalDeletePrinterDriverEx(
  3767. LPWSTR pName,
  3768. LPWSTR pEnvironment,
  3769. LPWSTR pDriverName,
  3770. DWORD dwDeleteFlag,
  3771. DWORD dwVersionNum
  3772. )
  3773. {
  3774. PINISPOOLER pIniSpooler;
  3775. BOOL bReturn;
  3776. pIniSpooler = FindSpoolerByNameIncRef( pName, NULL );
  3777. if( !pIniSpooler ){
  3778. return ROUTER_UNKNOWN;
  3779. }
  3780. bReturn = SplDeletePrinterDriverEx( pName,
  3781. pEnvironment,
  3782. pDriverName,
  3783. pIniSpooler,
  3784. dwDeleteFlag,
  3785. dwVersionNum);
  3786. FindSpoolerByNameDecRef( pIniSpooler );
  3787. return bReturn;
  3788. }
  3789. BOOL
  3790. SplDeletePrinterDriverEx(
  3791. LPWSTR pName,
  3792. LPWSTR pEnvironment,
  3793. LPWSTR pDriverName,
  3794. PINISPOOLER pIniSpooler,
  3795. DWORD dwDeleteFlag,
  3796. DWORD dwVersionNum
  3797. )
  3798. /*++
  3799. Function Description: Deletes specific or all versions of a printer driver. Removes unused
  3800. or all files associated with the driver.
  3801. Parameters: pName - name of the server. NULL implies local machine.
  3802. pEnvironment - string containing the environment of the driver to be deleted.
  3803. NULL implies use local environment.
  3804. pDriverName - string containing the name of the driver.
  3805. pIniSpooler - Pointer to INISPOOLER struct.
  3806. dwDeleteFlag - combination of DPD_DELETE_SPECIFIC_VERSION and
  3807. DPD_DELETE_UNUSED_FILES or DPD_DELETE_ALL_FILES. The defaults
  3808. are delete all versions and dont delete the files.
  3809. dwVersionNum - version number (0-3) of the driver. Used only if dwDeleteFlag
  3810. contains DPD_DELETE_SPECIFIC_VERSION.
  3811. Return Values: TRUE if deleted.
  3812. FALSE otherwise.
  3813. --*/
  3814. {
  3815. PINIENVIRONMENT pIniEnvironment;
  3816. PINIVERSION pIniVersion;
  3817. PINIDRIVER pIniDriver;
  3818. BOOL bRefCount = FALSE,bEnteredSplSem = FALSE,bReturn = TRUE;
  3819. BOOL bFileRefCount = FALSE;
  3820. BOOL bThisVersion,bSetPrinterChange = FALSE;
  3821. BOOL bFoundDriver = FALSE, bSpecificVersionDeleted = FALSE;
  3822. LPWSTR pIndex;
  3823. WCHAR szDirectory[MAX_PATH];
  3824. HANDLE hImpersonationToken;
  3825. DWORD dwRet;
  3826. DBGMSG(DBG_TRACE, ("DeletePrinterDriverEx\n"));
  3827. // Check if the call is for the local machine.
  3828. if ( pName && *pName ) {
  3829. if ( !MyName( pName, pIniSpooler )) {
  3830. bReturn = FALSE;
  3831. goto CleanUp;
  3832. }
  3833. }
  3834. // Invalid Input and Access Checks
  3835. if ( !pDriverName || !*pDriverName ) {
  3836. SetLastError(ERROR_INVALID_PARAMETER);
  3837. bReturn = FALSE;
  3838. goto CleanUp;
  3839. }
  3840. if (dwDeleteFlag & ~(DPD_DELETE_SPECIFIC_VERSION
  3841. | DPD_DELETE_ALL_FILES
  3842. | DPD_DELETE_UNUSED_FILES)) {
  3843. SetLastError(ERROR_INVALID_PARAMETER);
  3844. bReturn = FALSE;
  3845. goto CleanUp;
  3846. }
  3847. if ( !ValidateObjectAccess( SPOOLER_OBJECT_SERVER,
  3848. SERVER_ACCESS_ADMINISTER,
  3849. NULL, NULL, pIniSpooler )) {
  3850. bReturn = FALSE;
  3851. goto CleanUp;
  3852. }
  3853. EnterSplSem();
  3854. bEnteredSplSem = TRUE;
  3855. pIniEnvironment = FindEnvironment(pEnvironment, pIniSpooler);
  3856. if ( !pIniEnvironment ) {
  3857. SetLastError(ERROR_INVALID_ENVIRONMENT);
  3858. bReturn = FALSE;
  3859. goto CleanUp;
  3860. }
  3861. pIniVersion = pIniEnvironment->pIniVersion;
  3862. while ( pIniVersion ) {
  3863. if ((pIniDriver = FindDriverEntry(pIniVersion, pDriverName))) {
  3864. bFoundDriver = TRUE;
  3865. // bThisVersion indicates if this version is to be deleted.
  3866. bThisVersion = !(dwDeleteFlag & DPD_DELETE_SPECIFIC_VERSION) ||
  3867. (pIniVersion->cMajorVersion == dwVersionNum);
  3868. if ((pIniDriver->cRef) && bThisVersion) {
  3869. bRefCount = TRUE;
  3870. break;
  3871. }
  3872. if (bThisVersion &&
  3873. (dwDeleteFlag & DPD_DELETE_ALL_FILES) &&
  3874. FilesInUse(pIniVersion,pIniDriver)) {
  3875. bFileRefCount = TRUE;
  3876. break;
  3877. }
  3878. }
  3879. pIniVersion = pIniVersion->pNext;
  3880. }
  3881. if ( !bFoundDriver ) {
  3882. SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
  3883. bReturn = FALSE;
  3884. goto CleanUp;
  3885. }
  3886. if ( bRefCount ) {
  3887. SetLastError( ERROR_PRINTER_DRIVER_IN_USE );
  3888. bReturn = FALSE;
  3889. goto CleanUp;
  3890. }
  3891. if ( bFileRefCount ) {
  3892. // New error code has to added.
  3893. SetLastError( ERROR_PRINTER_DRIVER_IN_USE );
  3894. bReturn = FALSE;
  3895. goto CleanUp;
  3896. }
  3897. pIniVersion = pIniEnvironment->pIniVersion;
  3898. while ( pIniVersion && (!bSpecificVersionDeleted) ) {
  3899. if ( !(dwDeleteFlag & DPD_DELETE_SPECIFIC_VERSION) ||
  3900. (bSpecificVersionDeleted = (pIniVersion->cMajorVersion == dwVersionNum))) {
  3901. if (( pIniDriver = FindDriverEntry( pIniVersion, pDriverName ))) {
  3902. //
  3903. // Remove pending driver upgrades for local environment
  3904. //
  3905. if (!lstrcmpi(pIniEnvironment->pName, szEnvironment)) {
  3906. RemovePendingUpgradeForDeletedDriver(pDriverName,
  3907. pIniVersion->cMajorVersion,
  3908. pIniSpooler);
  3909. RemoveDriverTempFiles(pIniSpooler, pIniEnvironment,
  3910. pIniVersion, pIniDriver);
  3911. }
  3912. if ( !DeleteDriverIni( pIniDriver,
  3913. pIniVersion,
  3914. pIniEnvironment,
  3915. pIniSpooler )) {
  3916. DBGMSG( DBG_CLUSTER, ("Error - driverini not deleted %d\n", GetLastError()));
  3917. bReturn = FALSE;
  3918. goto CleanUp;
  3919. }
  3920. bSetPrinterChange = TRUE;
  3921. hImpersonationToken = RevertToPrinterSelf();
  3922. SPLASSERT(pIniSpooler->pDir!=NULL);
  3923. dwRet = StrNCatBuff(szDirectory,
  3924. COUNTOF(szDirectory),
  3925. pIniSpooler->pDir,
  3926. L"\\drivers\\",
  3927. pIniEnvironment->pDirectory,
  3928. L"\\",
  3929. pIniVersion->szDirectory,
  3930. L"\\",
  3931. NULL);
  3932. if (dwRet != ERROR_SUCCESS)
  3933. {
  3934. if (hImpersonationToken)
  3935. {
  3936. ImpersonatePrinterClient(hImpersonationToken);
  3937. }
  3938. bReturn = FALSE;
  3939. SetLastError(dwRet);
  3940. goto CleanUp;
  3941. }
  3942. //
  3943. // Before we leave for the driver event. Mark this printer driver as
  3944. // pending deletion. This prevents other calls from mistakenly using
  3945. // this driver, even though it is about to be deleted. Drivers should
  3946. // not expect to find any other information about the driver during this
  3947. // call other than what they were presented with.
  3948. //
  3949. pIniDriver->dwDriverFlags |= PRINTER_DRIVER_PENDING_DELETION;
  3950. //
  3951. // Increment cRefs for leaving SplSem, this prevent SplDeletePrinterDriver
  3952. // from being called twice.
  3953. //
  3954. INCSPOOLERREF( pIniSpooler );
  3955. INCDRIVERREF( pIniDriver );
  3956. pIniEnvironment->cRef++;
  3957. // Call DrvDriverEvent in the Driver.
  3958. NotifyDriver(pIniSpooler,
  3959. pIniEnvironment,
  3960. pIniVersion,
  3961. pIniDriver,
  3962. DRIVER_EVENT_DELETE,
  3963. dwDeleteFlag);
  3964. // Decrement cRefs after reentering SplSem
  3965. DECDRIVERREF( pIniDriver );
  3966. DECSPOOLERREF( pIniSpooler );
  3967. pIniEnvironment->cRef--;
  3968. // Update the file reference counts for the version of the driver that
  3969. // has been deleted.
  3970. UpdateDriverFileRefCnt(pIniEnvironment,pIniVersion,pIniDriver,szDirectory,dwDeleteFlag,FALSE);
  3971. if (hImpersonationToken) {
  3972. ImpersonatePrinterClient(hImpersonationToken);
  3973. }
  3974. DeleteDriverEntry( pIniVersion, pIniDriver );
  3975. }
  3976. }
  3977. pIniVersion = pIniVersion->pNext;
  3978. }
  3979. if (bSetPrinterChange) {
  3980. SetPrinterChange( NULL,
  3981. NULL,
  3982. NULL,
  3983. PRINTER_CHANGE_DELETE_PRINTER_DRIVER,
  3984. pIniSpooler );
  3985. }
  3986. CleanUp:
  3987. if (bEnteredSplSem) {
  3988. LeaveSplSem();
  3989. }
  3990. return bReturn;
  3991. }
  3992. VOID
  3993. RemoveDriverTempFiles(
  3994. PINISPOOLER pIniSpooler,
  3995. PINIENVIRONMENT pIniEnvironment,
  3996. PINIVERSION pIniVersion,
  3997. PINIDRIVER pIniDriver
  3998. )
  3999. /*++
  4000. Function Description: Removes temp directory associated with the driver
  4001. Parameters: pIniSpooler - pointer to INISPOOLER
  4002. pIniEnvironment - pointer to INIENVIRONMENT
  4003. pIniVersion - pointer to INIVERSION
  4004. pIniDriver - pointer to INIDRIVER
  4005. Return Values: NONE
  4006. --*/
  4007. {
  4008. WCHAR szDriverDir[MAX_PATH], szDriverFile[MAX_PATH];
  4009. LPCWSTR pszDriverFile, pszConfigFile;
  4010. DWORD DriverFileSize, ConfigFileSize, MaxFileSize;
  4011. fnWinSpoolDrv fnList;
  4012. pszDriverFile = FindFileName(pIniDriver->pDriverFile);
  4013. pszConfigFile = FindFileName(pIniDriver->pConfigFile);
  4014. DriverFileSize = pszDriverFile ? wcslen(pszDriverFile) : 0 ;
  4015. ConfigFileSize = pszConfigFile ? wcslen(pszConfigFile) : 0 ;
  4016. MaxFileSize = ConfigFileSize > DriverFileSize ?
  4017. ConfigFileSize :
  4018. DriverFileSize;
  4019. if (pIniDriver->dwTempDir &&
  4020. GetDriverVersionDirectory(szDriverDir,
  4021. COUNTOF(szDriverDir) - MaxFileSize -1,
  4022. pIniSpooler,
  4023. pIniEnvironment,
  4024. pIniVersion,
  4025. pIniDriver,
  4026. NULL))
  4027. {
  4028. // Unload the driver files if neccessary
  4029. if( pszDriverFile &&
  4030. StrNCatBuff (szDriverFile,
  4031. COUNTOF(szDriverFile),
  4032. szDriverDir,
  4033. L"\\",
  4034. pszDriverFile,
  4035. NULL) == ERROR_SUCCESS ) {
  4036. GdiArtificialDecrementDriver(szDriverFile, pIniDriver->dwDriverAttributes);
  4037. }
  4038. if( pszConfigFile &&
  4039. StrNCatBuff (szDriverFile,
  4040. COUNTOF(szDriverFile),
  4041. szDriverDir,
  4042. L"\\",
  4043. pszConfigFile,
  4044. NULL) == ERROR_SUCCESS ) {
  4045. if (SplInitializeWinSpoolDrv(&fnList)) {
  4046. (* (fnList.pfnForceUnloadDriver))(szDriverFile);
  4047. }
  4048. }
  4049. // Delete the files and the directory
  4050. DeleteAllFilesAndDirectory(szDriverDir, FALSE);
  4051. }
  4052. return;
  4053. }
  4054. VOID RemovePendingUpgradeForDeletedDriver(
  4055. LPWSTR pDriverName,
  4056. DWORD dwVersion,
  4057. PINISPOOLER pIniSpooler
  4058. )
  4059. /*++
  4060. Function Description: Removes pending upgrade keys for deleted drivers.
  4061. Parameters: pDriverName - driver name (eg. HP LaserJet 5)
  4062. dwVersion - version number being deleted
  4063. Return Values: NONE
  4064. --*/
  4065. {
  4066. HKEY hRootKey = NULL, hUpgradeKey = NULL, hVersionKey = NULL;
  4067. HANDLE hToken = NULL;
  4068. WCHAR pDriver[MAX_PATH];
  4069. BOOL bAllocMem = FALSE;
  4070. DWORD dwSize;
  4071. // Parameter check
  4072. if (!pDriverName || !*pDriverName) {
  4073. // Invalid strings
  4074. return;
  4075. }
  4076. hToken = RevertToPrinterSelf();
  4077. DBGMSG(DBG_CLUSTER, ("RemovePendingUpgradeForDeletedDriver Driver "TSTR"\n", pDriverName));
  4078. wsprintf(pDriver, L"Version-%d", dwVersion);
  4079. //
  4080. // The local spooler and cluster spooler have different sets of drivers.
  4081. // The root registry is different.
  4082. //
  4083. if (pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG)
  4084. {
  4085. hRootKey = pIniSpooler->hckRoot;
  4086. }
  4087. else
  4088. {
  4089. SplRegCreateKey(HKEY_LOCAL_MACHINE,
  4090. szRegistryRoot,
  4091. 0,
  4092. KEY_ALL_ACCESS,
  4093. NULL,
  4094. &hRootKey,
  4095. NULL,
  4096. NULL);
  4097. }
  4098. // Open the registry key
  4099. if (hRootKey &&
  4100. SplRegCreateKey(hRootKey,
  4101. szPendingUpgrades,
  4102. 0,
  4103. KEY_ALL_ACCESS,
  4104. NULL,
  4105. &hUpgradeKey,
  4106. NULL,
  4107. pIniSpooler) == ERROR_SUCCESS &&
  4108. SplRegCreateKey(hUpgradeKey,
  4109. pDriver,
  4110. 0,
  4111. KEY_ALL_ACCESS,
  4112. NULL,
  4113. &hVersionKey,
  4114. NULL,
  4115. pIniSpooler) == ERROR_SUCCESS)
  4116. {
  4117. // Delete driver subkey, if any (since reg apis are not case sensitive)
  4118. SplRegDeleteKey(hVersionKey, pDriverName, pIniSpooler);
  4119. }
  4120. if (hVersionKey) {
  4121. SplRegCloseKey(hVersionKey, pIniSpooler);
  4122. }
  4123. if (hUpgradeKey) {
  4124. SplRegCloseKey(hUpgradeKey, pIniSpooler);
  4125. }
  4126. //
  4127. // Do not close the root key if the spooler is a cluster spooler
  4128. //
  4129. if (hRootKey && !(pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG)) {
  4130. SplRegCloseKey(hRootKey, pIniSpooler);
  4131. }
  4132. if (hToken) {
  4133. ImpersonatePrinterClient(hToken);
  4134. }
  4135. return;
  4136. }
  4137. BOOL
  4138. NotifyDriver(
  4139. PINISPOOLER pIniSpooler,
  4140. PINIENVIRONMENT pIniEnvironment,
  4141. PINIVERSION pIniVersion,
  4142. PINIDRIVER pIniDriver,
  4143. DWORD dwDriverEvent,
  4144. DWORD dwParameter
  4145. )
  4146. /*++
  4147. Function description: Calls DrvDriverEvent, to allow the driver to cleanup some of it's
  4148. private files. The function is called inside SplSem.
  4149. Parameters: pIniSpooler - pointer to INISPOOLER struct.
  4150. pIniEnvironment - pointer to INIENVIRONMENT struct.
  4151. pIniVersion - pointer to INIVERSION struct.
  4152. pIniDriver - pointer to the INIDRIVER struct of the driver to be notified.
  4153. dwDriverEvent - the type of Driver Event (delete | initialize)
  4154. dwParameter - LPARAM to pass to DrvDriverEvent. Contains dwDeleteFlag for
  4155. DRIVER_EVENT_DELETE
  4156. Return Values: TRUE if DrvDriverEvent returns TRUE or if it need not be called.
  4157. FALSE if DrvDriverEvent could not be called or if it returns FALSE.
  4158. --*/
  4159. {
  4160. WCHAR szDriverLib[MAX_PATH];
  4161. FARPROC pfnDrvDriverEvent;
  4162. HINSTANCE hDrvLib = NULL;
  4163. LPBYTE pDriverInfo = NULL;
  4164. DWORD cbBuf;
  4165. BOOL bReturn = FALSE;
  4166. SplInSem();
  4167. // Check if the driver could have been used by the system. Version number should be
  4168. // 2 or 3, Environment should match with the global szEnvironment.
  4169. if (((pIniVersion->cMajorVersion != SPOOLER_VERSION) &&
  4170. (pIniVersion->cMajorVersion != COMPATIBLE_SPOOLER_VERSION)) ||
  4171. lstrcmpi(pIniEnvironment->pName,szEnvironment)) {
  4172. return TRUE;
  4173. }
  4174. // Get the directory where the driver files are stored.
  4175. if( pIniDriver->pConfigFile &&
  4176. GetDriverVersionDirectory(szDriverLib,
  4177. (DWORD)(COUNTOF(szDriverLib) - wcslen(pIniDriver->pConfigFile) - 2),
  4178. pIniSpooler, pIniEnvironment,
  4179. pIniVersion, pIniDriver, NULL)) {
  4180. if((StrNCatBuff(szDriverLib,
  4181. COUNTOF(szDriverLib),
  4182. szDriverLib,
  4183. L"\\",
  4184. pIniDriver->pConfigFile,
  4185. NULL) == ERROR_SUCCESS))
  4186. {
  4187. // Load the driver dll for the version being deleted.
  4188. if (hDrvLib = LoadDriver(szDriverLib))
  4189. {
  4190. if (pfnDrvDriverEvent = GetProcAddress(hDrvLib, "DrvDriverEvent")) {
  4191. // If the DrvDriverEvent is supported Copy pIniDriver Info into a
  4192. // DRIVER_INFO_3 struct and call the DrvDriverEvent Function.
  4193. cbBuf = GetDriverInfoSize( pIniDriver, 3, pIniVersion, pIniEnvironment,
  4194. NULL, pIniSpooler );
  4195. if (pDriverInfo = (LPBYTE) AllocSplMem(cbBuf)) {
  4196. if (CopyIniDriverToDriverInfo( pIniEnvironment,
  4197. pIniVersion,
  4198. pIniDriver,
  4199. 3,
  4200. pDriverInfo,
  4201. pDriverInfo + cbBuf,
  4202. NULL,
  4203. pIniSpooler )) {
  4204. // Leave the semaphore before calling into the spooler
  4205. LeaveSplSem();
  4206. SplOutSem();
  4207. try {
  4208. bReturn = (BOOL) pfnDrvDriverEvent(dwDriverEvent,
  4209. 3,
  4210. pDriverInfo,
  4211. (LPARAM) dwParameter);
  4212. } except(EXCEPTION_EXECUTE_HANDLER) {
  4213. SetLastError( GetExceptionCode() );
  4214. DBGMSG(DBG_ERROR,
  4215. ("NotifyDriver ExceptionCode %x Driver %ws Error %d\n",
  4216. GetLastError(), szDriverLib, GetLastError() ));
  4217. bReturn = FALSE;
  4218. }
  4219. // Reenter the semaphore
  4220. EnterSplSem();
  4221. }
  4222. }
  4223. }
  4224. }
  4225. }
  4226. }
  4227. if (pDriverInfo) {
  4228. FreeSplMem(pDriverInfo);
  4229. }
  4230. if (hDrvLib) {
  4231. UnloadDriver(hDrvLib);
  4232. }
  4233. return bReturn;
  4234. }
  4235. VOID
  4236. DeleteScratchDriverFile(
  4237. LPCWSTR pszDirectory,
  4238. LPCWSTR pszFileName,
  4239. DWORD dwSize)
  4240. /*++
  4241. Function Description : Deletes the driver file from the spooler scratch directory. Applications
  4242. and print UI place the driver files here before calling AddPrinterDriver.
  4243. Parameters : pszDirectory - Directory where the driver file is placed (scratch\version\)
  4244. pszFileName - Name of the file to be removed
  4245. dwSize - Memory required to store the entire file name
  4246. Return Values : NONE
  4247. --*/
  4248. {
  4249. WCHAR szDelFile[MAX_PATH];
  4250. LPWSTR pszDelFile = NULL, pSwitch;
  4251. BOOL bAllocMem = FALSE;
  4252. if (!pszDirectory || !*pszDirectory ||
  4253. !pszFileName || !*pszFileName) {
  4254. // Nothing to delete
  4255. return;
  4256. }
  4257. // Allocate memory for the file name (if necessary)
  4258. if (dwSize > MAX_PATH) {
  4259. if (pszDelFile = (LPWSTR) AllocSplMem(dwSize)) {
  4260. bAllocMem = TRUE;
  4261. } else {
  4262. return;
  4263. }
  4264. } else {
  4265. pszDelFile = (LPWSTR) szDelFile;
  4266. }
  4267. // Remove the version entry in the directory name
  4268. wcscpy(pszDelFile, pszDirectory);
  4269. if (pSwitch = wcsrchr(pszDelFile, L'\\')) {
  4270. *pSwitch = L'\0';
  4271. }
  4272. if (pSwitch = wcsrchr(pszDelFile, L'\\')) {
  4273. *(pSwitch + 1) = L'\0';
  4274. }
  4275. wcscat(pszDelFile, pszFileName);
  4276. // No need to try to delete the files on reboot, since these dll's are
  4277. // never loaded
  4278. SplDeleteFile(pszDelFile);
  4279. // Free Allocated memory (if any)
  4280. if (bAllocMem) {
  4281. FreeSplMem(pszDelFile);
  4282. }
  4283. return;
  4284. }
  4285. PDRVREFCNT
  4286. DecrementFileRefCnt(
  4287. PINIENVIRONMENT pIniEnvironment,
  4288. PINIVERSION pIniVersion,
  4289. PINIDRIVER pIniDriver,
  4290. LPCWSTR pszFileName,
  4291. LPCWSTR pszDirectory,
  4292. DWORD dwDeleteFlag
  4293. )
  4294. /*++
  4295. Function description: Decrements the driver file usage reference counts and deletes unused
  4296. files depending on dwDeleteFlag.
  4297. Paramaters: pIniEnvironment - pointer to INIENVIRONMENT
  4298. pIniVersion - pointer to INIVERSION struct. This struct contains the ref counts.
  4299. pIniDriver - pointer to INIDRIVER
  4300. szFileName - driver file name whose ref count is to be decremented.
  4301. szDirectory - Directory where the files are located.
  4302. dwDeleteFlag - unused files are deleted if this flag contains
  4303. DPD_DELETE_UNUSED_FILES or DPD_DELETE_ALL_FILES
  4304. Return Value: pointer to the DRVREFCNT which was decremented
  4305. NULL if memory allocation fails.
  4306. --*/
  4307. {
  4308. PDRVREFCNT pdrc,*pprev;
  4309. LPWSTR pszDelFile=NULL;
  4310. WCHAR szTempDir[MAX_PATH+5],szTempFile[MAX_PATH];
  4311. DWORD dwSize;
  4312. PDRVREFCNT pReturn = NULL;
  4313. SplInSem();
  4314. pdrc = pIniVersion->pDrvRefCnt;
  4315. pprev = &(pIniVersion->pDrvRefCnt);
  4316. // Go thru the list of ref count nodes in the Iniversion struct and find the node
  4317. // corresponding to szFileName.
  4318. while (pdrc != NULL) {
  4319. if (lstrcmpi(pszFileName,pdrc->szDrvFileName) == 0) {
  4320. if (pdrc->refcount == 1 &&
  4321. ((dwDeleteFlag & DPD_DELETE_UNUSED_FILES) ||
  4322. (dwDeleteFlag & DPD_DELETE_ALL_FILES)) ) {
  4323. // Delete the file.
  4324. dwSize = sizeof(pszDirectory[0])*(wcslen(pszDirectory)+1);
  4325. dwSize += sizeof(pszFileName[0])*(wcslen(pszFileName)+1);
  4326. pszDelFile = (LPWSTR) AllocSplMem(dwSize);
  4327. if (!pszDelFile) {
  4328. pReturn = NULL;
  4329. goto CleanUp;
  4330. }
  4331. wcscpy(pszDelFile, pszDirectory);
  4332. wcscat(pszDelFile, pszFileName);
  4333. if (pIniDriver) {
  4334. if (!lstrcmpi(pszFileName, pIniDriver->pDriverFile)) {
  4335. FilesUnloaded(pIniEnvironment, pszDelFile,
  4336. NULL, pIniDriver->dwDriverAttributes);
  4337. }
  4338. else if (!lstrcmpi(pszFileName, pIniDriver->pConfigFile)) {
  4339. FilesUnloaded(pIniEnvironment, NULL,
  4340. pszDelFile, pIniDriver->dwDriverAttributes);
  4341. }
  4342. }
  4343. //
  4344. // We are about to delete a driver file. Delete the same file from
  4345. // the cluster disk too (if applicable)
  4346. //
  4347. if (pIniEnvironment->pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER)
  4348. {
  4349. WCHAR szFilePath[MAX_PATH] = {0};
  4350. //
  4351. // If DeleteFile fails, there isn't much we can do about it.
  4352. // The file will remain on the cluster disk.
  4353. //
  4354. if (StrNCatBuff(szFilePath,
  4355. MAX_PATH,
  4356. pIniEnvironment->pIniSpooler->pszClusResDriveLetter,
  4357. L"\\",
  4358. szClusterDriverRoot,
  4359. L"\\",
  4360. pIniEnvironment->pDirectory,
  4361. L"\\",
  4362. pIniVersion->szDirectory,
  4363. L"\\",
  4364. pszFileName,
  4365. NULL) == ERROR_SUCCESS &&
  4366. SplDeleteFile(szFilePath))
  4367. {
  4368. DBGMSG(DBG_CLUSTER, ("DecrementFilesRefCnt Deleted szFilePath "TSTR" from cluster\n", szFilePath));
  4369. }
  4370. }
  4371. if (!SplDeleteFile(pszDelFile)) {
  4372. // Move the file to a temp directory and delete on REBOOT.
  4373. // Create the temp directory and new tempfile.
  4374. wcscpy(szTempDir, pszDirectory);
  4375. wcscat(szTempDir, L"temp");
  4376. //
  4377. // Fix for 420824. CreateDirectory will fail, if szTempDir already
  4378. // exists. Since we don't check for any errors, subsequent functions
  4379. // may fail.
  4380. //
  4381. CreateDirectory(szTempDir,NULL);
  4382. GetTempFileName(szTempDir,pszFileName,0,szTempFile);
  4383. SplMoveFileEx(pszDelFile,szTempFile,MOVEFILE_REPLACE_EXISTING);
  4384. SplMoveFileEx(szTempFile,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
  4385. }
  4386. // Delete the corresponding file from the scratch directory
  4387. DeleteScratchDriverFile(pszDirectory, pszFileName, dwSize);
  4388. *pprev = pdrc->pNext;
  4389. }
  4390. // Decrement the ref cnt for the file.
  4391. if (pdrc->refcount > 0) pdrc->refcount--;
  4392. pReturn = pdrc;
  4393. break;
  4394. }
  4395. pprev = &(pdrc->pNext);
  4396. pdrc = pdrc->pNext;
  4397. }
  4398. CleanUp:
  4399. if (pszDelFile) {
  4400. FreeSplMem(pszDelFile);
  4401. }
  4402. return pReturn;
  4403. }
  4404. BOOL
  4405. SplGetPrinterDriver(
  4406. HANDLE hPrinter,
  4407. LPWSTR pEnvironment,
  4408. DWORD Level,
  4409. LPBYTE pDriverInfo,
  4410. DWORD cbBuf,
  4411. LPDWORD pcbNeeded
  4412. )
  4413. {
  4414. DWORD dwDontCare;
  4415. return SplGetPrinterDriverEx(hPrinter,
  4416. pEnvironment,
  4417. Level,
  4418. pDriverInfo,
  4419. cbBuf,
  4420. pcbNeeded,
  4421. 0,
  4422. 0,
  4423. &dwDontCare,
  4424. &dwDontCare
  4425. );
  4426. }
  4427. BOOL
  4428. LocalGetPrinterDriverDirectory(
  4429. LPWSTR pName,
  4430. LPWSTR pEnvironment,
  4431. DWORD Level,
  4432. LPBYTE pDriverInfo,
  4433. DWORD cbBuf,
  4434. LPDWORD pcbNeeded
  4435. )
  4436. {
  4437. PINISPOOLER pIniSpooler;
  4438. BOOL bReturn;
  4439. pIniSpooler = FindSpoolerByNameIncRef( pName, NULL );
  4440. if( !pIniSpooler ){
  4441. return ROUTER_UNKNOWN;
  4442. }
  4443. bReturn = SplGetPrinterDriverDirectory( pName,
  4444. pEnvironment,
  4445. Level,
  4446. pDriverInfo,
  4447. cbBuf,
  4448. pcbNeeded,
  4449. pIniSpooler );
  4450. FindSpoolerByNameDecRef( pIniSpooler );
  4451. return bReturn;
  4452. }
  4453. BOOL
  4454. SplGetPrinterDriverDirectory(
  4455. LPWSTR pName,
  4456. LPWSTR pEnvironment,
  4457. DWORD Level,
  4458. LPBYTE pDriverInfo,
  4459. DWORD cbBuf,
  4460. LPDWORD pcbNeeded,
  4461. PINISPOOLER pIniSpooler
  4462. )
  4463. {
  4464. DWORD cb;
  4465. WCHAR string[MAX_PATH];
  4466. BOOL bRemote=FALSE;
  4467. PINIENVIRONMENT pIniEnvironment;
  4468. HANDLE hImpersonationToken;
  4469. DWORD ParmError;
  4470. SHARE_INFO_1501 ShareInfo1501;
  4471. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  4472. PSHARE_INFO_2 pShareInfo = (PSHARE_INFO_2)pIniSpooler->pDriversShareInfo;
  4473. DBGMSG( DBG_TRACE, ("GetPrinterDriverDirectory\n"));
  4474. if ( pName && *pName ) {
  4475. if ( !MyName( pName, pIniSpooler )) {
  4476. return FALSE;
  4477. } else {
  4478. bRemote = TRUE;
  4479. }
  4480. }
  4481. if ( !ValidateObjectAccess( SPOOLER_OBJECT_SERVER,
  4482. SERVER_ACCESS_ENUMERATE,
  4483. NULL, NULL, pIniSpooler )) {
  4484. return FALSE;
  4485. }
  4486. EnterSplSem();
  4487. pIniEnvironment = FindEnvironment( pEnvironment, pIniSpooler );
  4488. if ( !pIniEnvironment ) {
  4489. LeaveSplSem();
  4490. SetLastError( ERROR_INVALID_ENVIRONMENT );
  4491. return FALSE;
  4492. }
  4493. // Ensure that the directory exists
  4494. GetDriverDirectory( string, COUNTOF(string), pIniEnvironment, NULL, pIniSpooler );
  4495. hImpersonationToken = RevertToPrinterSelf();
  4496. CreateCompleteDirectory( string );
  4497. ImpersonatePrinterClient( hImpersonationToken );
  4498. cb = GetDriverDirectory( string, COUNTOF(string), pIniEnvironment, bRemote ? pName : NULL, pIniSpooler )
  4499. * sizeof(WCHAR) + sizeof(WCHAR);
  4500. *pcbNeeded = cb;
  4501. LeaveSplSem();
  4502. if (cb > cbBuf) {
  4503. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  4504. return FALSE;
  4505. }
  4506. wcscpy( (LPWSTR)pDriverInfo, string );
  4507. memset( &ShareInfo1501, 0, sizeof ShareInfo1501 );
  4508. // Also ensure the drivers share exists
  4509. if ( bRemote ) {
  4510. NET_API_STATUS rc;
  4511. if ( rc = (*pfnNetShareAdd)(NULL, 2, (LPBYTE)pIniSpooler->pDriversShareInfo, &ParmError )) {
  4512. DBGMSG( DBG_WARNING, ("NetShareAdd failed: Error %d, Parm %d\n", rc, ParmError));
  4513. }
  4514. else if (pSecurityDescriptor = CreateDriversShareSecurityDescriptor( )) {
  4515. ShareInfo1501.shi1501_security_descriptor = pSecurityDescriptor;
  4516. if (rc = (*pfnNetShareSetInfo)(NULL, pShareInfo->shi2_netname, 1501,
  4517. &ShareInfo1501, &ParmError)) {
  4518. DBGMSG( DBG_WARNING, ("NetShareSetInfo failed: Error %d, Parm %d\n", rc, ParmError));
  4519. }
  4520. LocalFree(pSecurityDescriptor);
  4521. }
  4522. }
  4523. return TRUE;
  4524. }
  4525. BOOL
  4526. LocalEnumPrinterDrivers(
  4527. LPWSTR pName,
  4528. LPWSTR pEnvironment,
  4529. DWORD Level,
  4530. LPBYTE pDriverInfo,
  4531. DWORD cbBuf,
  4532. LPDWORD pcbNeeded,
  4533. LPDWORD pcReturned
  4534. )
  4535. {
  4536. PINISPOOLER pIniSpooler;
  4537. BOOL bReturn;
  4538. pIniSpooler = FindSpoolerByNameIncRef( pName, NULL );
  4539. if( !pIniSpooler ){
  4540. return ROUTER_UNKNOWN;
  4541. }
  4542. bReturn = SplEnumPrinterDrivers( pName, pEnvironment, Level, pDriverInfo,
  4543. cbBuf, pcbNeeded, pcReturned,
  4544. pIniSpooler);
  4545. FindSpoolerByNameDecRef( pIniSpooler );
  4546. return bReturn;
  4547. }
  4548. /*++
  4549. Routine Name
  4550. FindDriverInList
  4551. Routine Description:
  4552. Finds a certain driver in a list of drivers. None of the arguments
  4553. can or will be null.
  4554. Arguments:
  4555. pDriverList - array of DRIVER INFO 6 strucutres
  4556. cDrivers - number of drivers in the list
  4557. pszName - name of the driver we are looking for
  4558. pszEnv - environment of the driver we are looking for
  4559. dwVersion - version of the driver we are looking for
  4560. Return Value:
  4561. valid pointer to driver info 6 structure if the driver is found
  4562. NULL if the driver was not found
  4563. --*/
  4564. DRIVER_INFO_6*
  4565. FindDriverInList(
  4566. DRIVER_INFO_6 *pDriverList,
  4567. DWORD cDrivers,
  4568. LPCWSTR pszName,
  4569. LPCWSTR pszEnv,
  4570. DWORD dwVersion
  4571. )
  4572. {
  4573. DWORD uIndex;
  4574. DRIVER_INFO_6 *pDrv6 = NULL;
  4575. for (pDrv6 = pDriverList, uIndex = 0;
  4576. pDrv6 && uIndex < cDrivers;
  4577. pDrv6++, uIndex++)
  4578. {
  4579. if (!_wcsicmp(pDrv6->pName, pszName) &&
  4580. !_wcsicmp(pDrv6->pEnvironment, pszEnv) &&
  4581. pDrv6->cVersion == dwVersion)
  4582. {
  4583. break;
  4584. }
  4585. }
  4586. //
  4587. // Check if driver was found
  4588. //
  4589. return uIndex == cDrivers ? NULL : pDrv6;
  4590. }
  4591. /*++
  4592. Routine Name
  4593. GetBufferSizeForPrinterDrivers
  4594. Routine Description:
  4595. Helper function for SplEnumAllClusterPrinterDrivers. Calculates the
  4596. bytes needed to hold all printer driver strucutres on all the spoolers
  4597. hosted by the spooler process. Note that we may ask for more bytes
  4598. than we really need. This is beacuse we enumerate the drivers on the
  4599. local spooler and on cluster spoolers and we count duplicates again.
  4600. In order to count the exact number of bytes needed, we would need to
  4601. loop through the drivers and search each of them in all spoolers. This
  4602. would be too slow.
  4603. Arguments:
  4604. pszRemote - NULL if the caller is local on the machine, a string otherwise
  4605. Return Value:
  4606. Count of bytes needed to store all the drivers
  4607. --*/
  4608. DWORD
  4609. GetBufferSizeForPrinterDrivers(
  4610. LPWSTR pszRemote
  4611. )
  4612. {
  4613. PINISPOOLER pIniSpooler;
  4614. PINIENVIRONMENT pIniEnvironment;
  4615. PINIVERSION pIniVersion;
  4616. PINIDRIVER pIniDriver;
  4617. DWORD cbNeeded = 0;
  4618. SplInSem();
  4619. for (pIniSpooler = pLocalIniSpooler;
  4620. pIniSpooler;
  4621. pIniSpooler = pIniSpooler->pIniNextSpooler)
  4622. {
  4623. //
  4624. // We want either a pIniSpooler that is not a clusrer, or
  4625. // a pIniSpooler that is a cluster spooler that is not
  4626. // in pending deletion or offline
  4627. //
  4628. if (!(pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER) ||
  4629. pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER &&
  4630. !(pIniSpooler->SpoolerFlags & SPL_PENDING_DELETION ||
  4631. pIniSpooler->SpoolerFlags & SPL_OFFLINE))
  4632. {
  4633. for (pIniEnvironment = pIniSpooler->pIniEnvironment;
  4634. pIniEnvironment;
  4635. pIniEnvironment = pIniEnvironment->pNext)
  4636. {
  4637. for (pIniVersion = pIniEnvironment->pIniVersion;
  4638. pIniVersion;
  4639. pIniVersion = pIniVersion->pNext)
  4640. {
  4641. for (pIniDriver = pIniVersion->pIniDriver;
  4642. pIniDriver;
  4643. pIniDriver = pIniDriver->pNext)
  4644. {
  4645. //
  4646. // Omit drivers that are currently in a pending deletion
  4647. // state.
  4648. //
  4649. if (!(pIniDriver->dwDriverFlags & PRINTER_DRIVER_PENDING_DELETION))
  4650. {
  4651. cbNeeded += GetDriverInfoSize(pIniDriver,
  4652. 6,
  4653. pIniVersion,
  4654. pIniEnvironment,
  4655. pszRemote,
  4656. pIniSpooler);
  4657. }
  4658. }
  4659. }
  4660. }
  4661. }
  4662. }
  4663. return cbNeeded;
  4664. }
  4665. /*++
  4666. Routine Name
  4667. PackClusterPrinterDrivers
  4668. Routine Description:
  4669. Helper function for SplEnumAllClusterPrinterDrivers. This function relies on
  4670. its caller to validate the arguments. This function loops through all the
  4671. drivers on all pIniSpooler and stores driver information in a buffer. There
  4672. won't be duplicate drivers in the list. If 2 pIniSpooler have the same driver,
  4673. then the oldest is enumerated.
  4674. Arguments:
  4675. pszRemote - NULL if the caller is local on the machine, a string otherwise
  4676. pDriverBuf - buffer to hold the strcutures
  4677. cbBuf - buffer size in bytes
  4678. pcReturned - number of structures returned
  4679. Return Value:
  4680. Win32 error code
  4681. --*/
  4682. DWORD
  4683. PackClusterPrinterDrivers(
  4684. LPWSTR pszRemote,
  4685. LPBYTE pDriverBuf,
  4686. DWORD cbBuf,
  4687. LPDWORD pcReturned
  4688. )
  4689. {
  4690. PINIDRIVER pIniDriver;
  4691. PINIENVIRONMENT pIniEnvironment;
  4692. PINIVERSION pIniVersion;
  4693. PINISPOOLER pIniSpooler;
  4694. DRIVER_INFO_6 *pListHead = (DRIVER_INFO_6 *)pDriverBuf;
  4695. LPBYTE pEnd = pDriverBuf + cbBuf;
  4696. DWORD dwError = ERROR_SUCCESS;
  4697. SplInSem();
  4698. for (pIniSpooler = pLocalIniSpooler;
  4699. pIniSpooler;
  4700. pIniSpooler = pIniSpooler->pIniNextSpooler)
  4701. {
  4702. //
  4703. // Either pIniSpooler is not a cluster, or it is a cluster and
  4704. // it is not pending deletion or offline
  4705. //
  4706. if (!(pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER) ||
  4707. pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER &&
  4708. !(pIniSpooler->SpoolerFlags & SPL_PENDING_DELETION ||
  4709. pIniSpooler->SpoolerFlags & SPL_OFFLINE))
  4710. {
  4711. for (pIniEnvironment = pIniSpooler->pIniEnvironment;
  4712. pIniEnvironment;
  4713. pIniEnvironment = pIniEnvironment->pNext)
  4714. {
  4715. for (pIniVersion = pIniEnvironment->pIniVersion;
  4716. pIniVersion;
  4717. pIniVersion = pIniVersion->pNext)
  4718. {
  4719. for (pIniDriver = pIniVersion->pIniDriver;
  4720. pIniDriver;
  4721. pIniDriver = pIniDriver->pNext)
  4722. {
  4723. //
  4724. // Make sure that we don't enumerate drivers that are pending deletion.
  4725. //
  4726. if (!(pIniDriver->dwDriverFlags & PRINTER_DRIVER_PENDING_DELETION))
  4727. {
  4728. DRIVER_INFO_6 *pDrv6 = NULL;
  4729. if (pDrv6 = FindDriverInList(pListHead,
  4730. *pcReturned,
  4731. pIniDriver->pName,
  4732. pIniEnvironment->pName,
  4733. pIniDriver->cVersion))
  4734. {
  4735. //
  4736. // The driver that we are currently enumerating is older than the
  4737. // driver that we have in the list. We need to update the driver
  4738. // time in the list. The list always has the oldest driver.
  4739. //
  4740. if (CompareFileTime(&pDrv6->ftDriverDate, &pIniDriver->ftDriverDate) > 0)
  4741. {
  4742. pDrv6->ftDriverDate = pIniDriver->ftDriverDate;
  4743. }
  4744. }
  4745. else
  4746. {
  4747. //
  4748. // Add the driver to the driver list
  4749. //
  4750. if (pEnd = CopyIniDriverToDriverInfo(pIniEnvironment,
  4751. pIniVersion,
  4752. pIniDriver,
  4753. 6,
  4754. pDriverBuf,
  4755. pEnd,
  4756. pszRemote,
  4757. pIniSpooler))
  4758. {
  4759. pDriverBuf += sizeof(DRIVER_INFO_6);
  4760. (*pcReturned)++;
  4761. }
  4762. else
  4763. {
  4764. //
  4765. // Severe error occured
  4766. //
  4767. dwError = ERROR_INSUFFICIENT_BUFFER;
  4768. goto CleanUp;
  4769. }
  4770. }
  4771. }
  4772. }
  4773. }
  4774. }
  4775. }
  4776. }
  4777. CleanUp:
  4778. return dwError;
  4779. }
  4780. /*++
  4781. Routine Name
  4782. SplEnumAllClusterPrinterDrivers
  4783. Routine Description:
  4784. Enumerates the driver on all the spoolers hosted by the spooler process.
  4785. It does not enumerate duplicates. This function is a helper function
  4786. for EnumPrinterDrivers, when the latter is called with "allcluster"
  4787. environment. The only consumer for this is Windows Update. Windows
  4788. update needs to update all the drivers on all the spoolers on a machine,
  4789. and uses EnumPrinterDrivers with "allcluster" environment.
  4790. Arguments:
  4791. pszRemote - NULL if the caller is local on the machine, a string otherwise
  4792. Level - must be 6
  4793. pDriverInfo - buffer to hold the strcutures
  4794. cbBuf - buffer size in bytes
  4795. pcbNeeded - pointer to receive the count of bytes needed
  4796. pcReturned - number of structures returned. Must be a valid pointer
  4797. Return Value:
  4798. TRUE, if getting the drivers was successful
  4799. FALSE, otherwise. Use GetLastError for error code
  4800. --*/
  4801. BOOL
  4802. SplEnumAllClusterPrinterDrivers(
  4803. LPWSTR pszRemote,
  4804. DWORD dwLevel,
  4805. LPBYTE pDriverInfo,
  4806. DWORD cbBuf,
  4807. LPDWORD pcbNeeded,
  4808. LPDWORD pcReturned)
  4809. {
  4810. DWORD dwError = ERROR_INVALID_PARAMETER;
  4811. if (pcbNeeded && pcReturned)
  4812. {
  4813. *pcReturned = 0;
  4814. if (dwLevel == 6)
  4815. {
  4816. EnterSplSem();
  4817. //
  4818. // Calculate the bytes needed for our driver structures
  4819. //
  4820. *pcbNeeded = GetBufferSizeForPrinterDrivers(pszRemote);
  4821. dwError = cbBuf < *pcbNeeded ? ERROR_INSUFFICIENT_BUFFER :
  4822. PackClusterPrinterDrivers(pszRemote,
  4823. pDriverInfo,
  4824. cbBuf,
  4825. pcReturned);
  4826. LeaveSplSem();
  4827. }
  4828. else
  4829. {
  4830. dwError = ERROR_INVALID_LEVEL;
  4831. }
  4832. }
  4833. SetLastError(dwError);
  4834. return dwError == ERROR_SUCCESS;
  4835. }
  4836. BOOL
  4837. SplEnumPrinterDrivers(
  4838. LPWSTR pName,
  4839. LPWSTR pEnvironment,
  4840. DWORD Level,
  4841. LPBYTE pDriverInfo,
  4842. DWORD cbBuf,
  4843. LPDWORD pcbNeeded,
  4844. LPDWORD pcReturned,
  4845. PINISPOOLER pIniSpooler
  4846. )
  4847. {
  4848. PINIDRIVER pIniDriver;
  4849. PINIVERSION pIniVersion;
  4850. BOOL bAllDrivers;
  4851. DWORD cb, cbStruct;
  4852. LPBYTE pEnd;
  4853. LPWSTR lpRemote = NULL;
  4854. PINIENVIRONMENT pIniEnvironment;
  4855. DBGMSG( DBG_TRACE, ("EnumPrinterDrivers\n"));
  4856. if ( pName && *pName ) {
  4857. if ( !MyName( pName, pIniSpooler )) {
  4858. return FALSE;
  4859. } else {
  4860. lpRemote = pName;
  4861. }
  4862. }
  4863. if ( !ValidateObjectAccess( SPOOLER_OBJECT_SERVER,
  4864. SERVER_ACCESS_ENUMERATE,
  4865. NULL, NULL, pIniSpooler )) {
  4866. return FALSE;
  4867. }
  4868. if (!_wcsicmp(pEnvironment, EPD_ALL_LOCAL_AND_CLUSTER))
  4869. {
  4870. return SplEnumAllClusterPrinterDrivers(lpRemote,
  4871. Level,
  4872. pDriverInfo,
  4873. cbBuf,
  4874. pcbNeeded,
  4875. pcReturned);
  4876. }
  4877. switch (Level) {
  4878. case 1:
  4879. cbStruct = sizeof(DRIVER_INFO_1);
  4880. break;
  4881. case 2:
  4882. cbStruct = sizeof(DRIVER_INFO_2);
  4883. break;
  4884. case 3:
  4885. cbStruct = sizeof(DRIVER_INFO_3);
  4886. break;
  4887. case 4:
  4888. cbStruct = sizeof(DRIVER_INFO_4);
  4889. break;
  4890. case 5:
  4891. cbStruct = sizeof(DRIVER_INFO_5);
  4892. break;
  4893. case 6:
  4894. cbStruct = sizeof(DRIVER_INFO_6);
  4895. break;
  4896. }
  4897. *pcReturned=0;
  4898. cb=0;
  4899. bAllDrivers = !_wcsicmp(pEnvironment, L"All");
  4900. EnterSplSem();
  4901. if ( bAllDrivers )
  4902. pIniEnvironment = pIniSpooler->pIniEnvironment;
  4903. else
  4904. pIniEnvironment = FindEnvironment( pEnvironment, pIniSpooler );
  4905. if ( !pIniEnvironment ) {
  4906. LeaveSplSem();
  4907. SetLastError(ERROR_INVALID_ENVIRONMENT);
  4908. return FALSE;
  4909. }
  4910. do {
  4911. pIniVersion = pIniEnvironment->pIniVersion;
  4912. while ( pIniVersion ) {
  4913. pIniDriver = pIniVersion->pIniDriver;
  4914. while ( pIniDriver ) {
  4915. //
  4916. // Don't consider drivers that are pending deletion for enumeration.
  4917. //
  4918. if (!(pIniDriver->dwDriverFlags & PRINTER_DRIVER_PENDING_DELETION))
  4919. {
  4920. DBGMSG( DBG_TRACE, ("Driver found - %ws\n", pIniDriver->pName));
  4921. cb += GetDriverInfoSize( pIniDriver, Level, pIniVersion,
  4922. pIniEnvironment, lpRemote, pIniSpooler );
  4923. }
  4924. pIniDriver = pIniDriver->pNext;
  4925. }
  4926. pIniVersion = pIniVersion->pNext;
  4927. }
  4928. if ( bAllDrivers )
  4929. pIniEnvironment = pIniEnvironment->pNext;
  4930. else
  4931. break;
  4932. } while ( pIniEnvironment );
  4933. *pcbNeeded=cb;
  4934. DBGMSG( DBG_TRACE, ("Required is %d and Available is %d\n", cb, cbBuf));
  4935. if (cbBuf < cb) {
  4936. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  4937. LeaveSplSem();
  4938. return FALSE;
  4939. }
  4940. DBGMSG( DBG_TRACE, ("Now copying contents into DRIVER_INFO structures\n"));
  4941. if ( bAllDrivers )
  4942. pIniEnvironment = pIniSpooler->pIniEnvironment;
  4943. pEnd = pDriverInfo+cbBuf;
  4944. do {
  4945. pIniVersion = pIniEnvironment->pIniVersion;
  4946. while ( pIniVersion ) {
  4947. pIniDriver = pIniVersion->pIniDriver;
  4948. while ( pIniDriver ) {
  4949. //
  4950. // Don't consider printer drivers that are pending deletion for
  4951. // enumeration.
  4952. //
  4953. if (!(pIniDriver->dwDriverFlags & PRINTER_DRIVER_PENDING_DELETION))
  4954. {
  4955. if (( pEnd = CopyIniDriverToDriverInfo( pIniEnvironment,
  4956. pIniVersion,
  4957. pIniDriver,
  4958. Level,
  4959. pDriverInfo,
  4960. pEnd,
  4961. lpRemote,
  4962. pIniSpooler )) == NULL){
  4963. LeaveSplSem();
  4964. return FALSE;
  4965. }
  4966. pDriverInfo += cbStruct;
  4967. (*pcReturned)++;
  4968. }
  4969. pIniDriver = pIniDriver->pNext;
  4970. }
  4971. pIniVersion = pIniVersion->pNext;
  4972. }
  4973. if ( bAllDrivers )
  4974. pIniEnvironment = pIniEnvironment->pNext;
  4975. else
  4976. break;
  4977. } while ( pIniEnvironment );
  4978. LeaveSplSem();
  4979. return TRUE;
  4980. }
  4981. DWORD
  4982. GetDriverInfoSize(
  4983. PINIDRIVER pIniDriver,
  4984. DWORD Level,
  4985. PINIVERSION pIniVersion,
  4986. PINIENVIRONMENT pIniEnvironment,
  4987. LPWSTR lpRemote,
  4988. PINISPOOLER pIniSpooler
  4989. )
  4990. {
  4991. DWORD cbDir, cb=0, cchLen;
  4992. WCHAR string[INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH + 1];
  4993. LPWSTR pStr;
  4994. DWORD cFiles = 0;
  4995. switch (Level) {
  4996. case 1:
  4997. cb=sizeof(DRIVER_INFO_1) + wcslen(pIniDriver->pName)*sizeof(WCHAR) +
  4998. sizeof(WCHAR);
  4999. break;
  5000. case 2:
  5001. case 3:
  5002. case 4:
  5003. case 5:
  5004. case 6:
  5005. case DRIVER_INFO_VERSION_LEVEL:
  5006. cbDir = GetDriverVersionDirectory( string, COUNTOF(string), pIniSpooler, pIniEnvironment,
  5007. pIniVersion, pIniDriver, lpRemote) + 1;
  5008. SPLASSERT(pIniDriver->pDriverFile);
  5009. cb+=wcslen(pIniDriver->pDriverFile) + 1 + cbDir;
  5010. SPLASSERT(pIniDriver->pDataFile);
  5011. cb+=wcslen(pIniDriver->pDataFile) + 1 + cbDir;
  5012. SPLASSERT(pIniDriver->pConfigFile);
  5013. cb+=wcslen(pIniDriver->pConfigFile) + 1 + cbDir;
  5014. cb += wcslen( pIniDriver->pName ) + 1 + wcslen( pIniEnvironment->pName ) + 1;
  5015. if ((Level == 2) || (Level == 5)) {
  5016. // For the strings in the struct
  5017. cb *= sizeof(WCHAR);
  5018. if (Level == 2) {
  5019. cb += sizeof( DRIVER_INFO_2 );
  5020. } else { // Level 5
  5021. cb += sizeof( DRIVER_INFO_5 );
  5022. }
  5023. } else { // level 3 or 4 or 6
  5024. if ( pIniDriver->pHelpFile && *pIniDriver->pHelpFile )
  5025. cb += wcslen(pIniDriver->pHelpFile) + cbDir + 1;
  5026. if ( pIniDriver->pMonitorName && *pIniDriver->pMonitorName )
  5027. cb += wcslen(pIniDriver->pMonitorName) + 1;
  5028. if ( pIniDriver->pDefaultDataType && *pIniDriver->pDefaultDataType)
  5029. cb += wcslen(pIniDriver->pDefaultDataType) + 1;
  5030. if ( (pStr=pIniDriver->pDependentFiles) && *pStr ) {
  5031. //
  5032. // There are 4 distinctive files in the file set
  5033. // (driver, data , config, help).
  5034. //
  5035. cFiles = 4;
  5036. while ( *pStr ) {
  5037. cchLen = wcslen(pStr) + 1;
  5038. cb += cchLen + cbDir;
  5039. pStr += cchLen;
  5040. cFiles++;
  5041. }
  5042. ++cb; //for final \0
  5043. }
  5044. if ( (Level == 4 || Level == 6 || Level == DRIVER_INFO_VERSION_LEVEL) &&
  5045. (pStr = pIniDriver->pszzPreviousNames) &&
  5046. *pStr) {
  5047. while ( *pStr ) {
  5048. cchLen = wcslen(pStr) + 1;
  5049. cb += cchLen;
  5050. pStr += cchLen;
  5051. }
  5052. ++cb; //for final \0
  5053. }
  5054. if (Level==6 || Level == DRIVER_INFO_VERSION_LEVEL) {
  5055. if (pIniDriver->pszMfgName && *pIniDriver->pszMfgName)
  5056. cb += wcslen(pIniDriver->pszMfgName) + 1;
  5057. if (pIniDriver->pszOEMUrl && *pIniDriver->pszOEMUrl)
  5058. cb += wcslen(pIniDriver->pszOEMUrl) + 1;
  5059. if (pIniDriver->pszHardwareID && *pIniDriver->pszHardwareID)
  5060. cb += wcslen(pIniDriver->pszHardwareID) + 1;
  5061. if (pIniDriver->pszProvider && *pIniDriver->pszProvider)
  5062. cb += wcslen(pIniDriver->pszProvider) + 1;
  5063. }
  5064. cb *= sizeof(WCHAR);
  5065. switch (Level) {
  5066. case 3:
  5067. cb += sizeof( DRIVER_INFO_3 );
  5068. break;
  5069. case 4:
  5070. cb += sizeof( DRIVER_INFO_4 );
  5071. break;
  5072. case 6:
  5073. cb += sizeof( DRIVER_INFO_6 );
  5074. break;
  5075. case DRIVER_INFO_VERSION_LEVEL:
  5076. cb += sizeof( DRIVER_INFO_VERSION ) +
  5077. cFiles * sizeof(DRIVER_FILE_INFO) +
  5078. sizeof(ULONG_PTR);
  5079. break;
  5080. }
  5081. }
  5082. break;
  5083. default:
  5084. DBGMSG(DBG_ERROR,
  5085. ("GetDriverInfoSize: level can not be %d", Level) );
  5086. cb = 0;
  5087. break;
  5088. }
  5089. return cb;
  5090. }
  5091. LPBYTE
  5092. CopyMultiSzFieldToDriverInfo(
  5093. LPWSTR pszz,
  5094. LPBYTE pEnd,
  5095. LPWSTR pszPrefix,
  5096. DWORD cchPrefix
  5097. )
  5098. /*++
  5099. Routine Description:
  5100. Copies a multi sz field from IniDriver to DriverInfo structure.
  5101. If a pszPrefix is specified that is appended before each string.
  5102. Arguments:
  5103. pszz : entry in pIniDriver (this could be dependent files
  5104. ex. PSCRIPT.DLL\0QMS810.PPD\0PSCRPTUI.DLL\0PSPCRIPTUI.HLP\0PSTEST.TXT\0\0
  5105. or previous names
  5106. ex. OldName1\0OldName2\0\0 )
  5107. pEnd : end of buffer to which it needs to be copied
  5108. pszPrefix : Prefix to copy when copying to user buffer. For dependent
  5109. files this will be driver directory path
  5110. cchPrefix : length of prefix
  5111. Return Value:
  5112. after copying where is the buffer end to copy next field
  5113. History:
  5114. Written by MuhuntS (Muhunthan Sivapragasam)June 95
  5115. --*/
  5116. {
  5117. LPWSTR pStr1, pStr2;
  5118. DWORD cchSize, cchLen;
  5119. if ( !pszz || !*pszz )
  5120. return pEnd;
  5121. pStr1 = pszz;
  5122. cchSize = 0;
  5123. while ( *pStr1 ) {
  5124. cchLen = wcslen(pStr1) + 1;
  5125. cchSize += cchPrefix + cchLen;
  5126. pStr1 += cchLen;
  5127. }
  5128. // For the last \0
  5129. ++cchSize;
  5130. pEnd -= cchSize * sizeof(WCHAR);
  5131. pStr1 = pszz;
  5132. pStr2 = (LPWSTR) pEnd;
  5133. while ( *pStr1 ) {
  5134. if ( pszPrefix ) {
  5135. wcsncpy(pStr2, pszPrefix, cchPrefix);
  5136. pStr2 += cchPrefix;
  5137. }
  5138. wcscpy(pStr2, pStr1);
  5139. cchLen = wcslen(pStr1) + 1;
  5140. pStr2 += cchLen;
  5141. pStr1 += cchLen;
  5142. }
  5143. *pStr2 = '\0';
  5144. return pEnd;
  5145. }
  5146. LPBYTE
  5147. CopyIniDriverToDriverInfo(
  5148. PINIENVIRONMENT pIniEnvironment,
  5149. PINIVERSION pIniVersion,
  5150. PINIDRIVER pIniDriver,
  5151. DWORD Level,
  5152. LPBYTE pDriverInfo,
  5153. LPBYTE pEnd,
  5154. LPWSTR lpRemote,
  5155. PINISPOOLER pIniSpooler
  5156. )
  5157. /*++
  5158. Routine Description:
  5159. This routine copies data from the IniDriver structure to
  5160. an DRIVER_INFO_X structure.
  5161. Arguments:
  5162. pIniEnvironment pointer to the INIENVIRONMENT structure
  5163. pIniVersion pointer to the INIVERSION structure.
  5164. pIniDriver pointer to the INIDRIVER structure.
  5165. Level Level of the DRIVER_INFO_X structure
  5166. pDriverInfo Buffer of the DRIVER_INFO_X structure
  5167. pEnd pointer to the end of the pDriverInfo
  5168. lpRemote flag which determines whether Remote or Local
  5169. pIniSpooler pointer to the INISPOOLER structure
  5170. Return Value:
  5171. if the call is successful, the return value is the updated pEnd value.
  5172. if the call is unsuccessful, the return value is NULL.
  5173. Note:
  5174. --*/
  5175. {
  5176. LPWSTR *pSourceStrings, *SourceStrings;
  5177. WCHAR string[INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH + 1];
  5178. DWORD i, j;
  5179. DWORD *pOffsets;
  5180. LPWSTR pTempDriverPath=NULL;
  5181. LPWSTR pTempConfigFile=NULL;
  5182. LPWSTR pTempDataFile=NULL;
  5183. LPWSTR pTempHelpFile=NULL;
  5184. switch (Level) {
  5185. case DRIVER_INFO_VERSION_LEVEL:
  5186. return CopyIniDriverToDriverInfoVersion(pIniEnvironment,
  5187. pIniVersion,
  5188. pIniDriver,
  5189. pDriverInfo,
  5190. pEnd,
  5191. lpRemote,
  5192. pIniSpooler);
  5193. break;
  5194. case 1:
  5195. pOffsets = DriverInfo1Strings;
  5196. break;
  5197. case 2:
  5198. case 5:
  5199. pOffsets = DriverInfo2Strings;
  5200. break;
  5201. case 3:
  5202. case 4:
  5203. pOffsets = DriverInfo3Strings;
  5204. break;
  5205. case 6:
  5206. pOffsets = DriverInfo6Strings;
  5207. break;
  5208. default:
  5209. SetLastError(ERROR_INVALID_LEVEL);
  5210. return NULL;
  5211. }
  5212. for (j=0; pOffsets[j] != -1; j++) {
  5213. }
  5214. SourceStrings = pSourceStrings = AllocSplMem(j * sizeof(LPWSTR));
  5215. if ( pSourceStrings ) {
  5216. switch (Level) {
  5217. case 1:
  5218. *pSourceStrings++=pIniDriver->pName;
  5219. pEnd = PackStrings(SourceStrings, pDriverInfo, pOffsets, pEnd);
  5220. break;
  5221. case 2:
  5222. case 3:
  5223. case 4:
  5224. case 5:
  5225. case 6:
  5226. i = GetDriverVersionDirectory(string, (DWORD)(COUNTOF(string) - wcslen(pIniDriver->pDriverFile) - 1), pIniSpooler, pIniEnvironment,
  5227. pIniVersion, pIniDriver, lpRemote);
  5228. if(!i) {
  5229. pEnd = NULL;
  5230. goto Fail;
  5231. }
  5232. string[i++] = L'\\';
  5233. *pSourceStrings++ = pIniDriver->pName;
  5234. *pSourceStrings++ = pIniEnvironment->pName;
  5235. wcscpy( &string[i], pIniDriver->pDriverFile );
  5236. if (( pTempDriverPath = AllocSplStr(string) ) == NULL){
  5237. DBGMSG( DBG_WARNING, ("CopyIniDriverToDriverInfo: AlloSplStr failed\n"));
  5238. pEnd = NULL;
  5239. goto Fail;
  5240. }
  5241. *pSourceStrings++ = pTempDriverPath;
  5242. wcscpy( &string[i], pIniDriver->pDataFile );
  5243. if (( pTempDataFile = AllocSplStr(string) ) == NULL){
  5244. DBGMSG( DBG_WARNING, ("CopyIniDriverToDriverInfo: AlloSplStr failed\n"));
  5245. pEnd = NULL;
  5246. goto Fail;
  5247. }
  5248. *pSourceStrings++ = pTempDataFile;
  5249. if ( pIniDriver->pConfigFile && *pIniDriver->pConfigFile ) {
  5250. wcscpy( &string[i], pIniDriver->pConfigFile );
  5251. if (( pTempConfigFile = AllocSplStr(string) ) == NULL) {
  5252. DBGMSG( DBG_WARNING, ("CopyIniDriverToDriverInfo: AlloSplStr failed\n"));
  5253. pEnd = NULL;
  5254. goto Fail;
  5255. }
  5256. *pSourceStrings++ = pTempConfigFile;
  5257. } else {
  5258. *pSourceStrings++=0;
  5259. }
  5260. if ( Level == 3 || Level == 4 || Level == 6 ) {
  5261. if ( pIniDriver->pHelpFile && *pIniDriver->pHelpFile ) {
  5262. wcscpy( &string[i], pIniDriver->pHelpFile );
  5263. if (( pTempHelpFile = AllocSplStr(string) ) == NULL) {
  5264. DBGMSG(DBG_WARNING,
  5265. ("CopyIniDriverToDriverInfo: AlloSplStr failed\n"));
  5266. pEnd = NULL;
  5267. goto Fail;
  5268. }
  5269. *pSourceStrings++ = pTempHelpFile;
  5270. } else {
  5271. *pSourceStrings++=0;
  5272. }
  5273. *pSourceStrings++ = pIniDriver->pMonitorName;
  5274. *pSourceStrings++ = pIniDriver->pDefaultDataType;
  5275. }
  5276. if (Level == 6) {
  5277. ((PDRIVER_INFO_6)pDriverInfo)->ftDriverDate = pIniDriver->ftDriverDate;
  5278. ((PDRIVER_INFO_6)pDriverInfo)->dwlDriverVersion = pIniDriver->dwlDriverVersion;
  5279. *pSourceStrings++ = pIniDriver->pszMfgName;
  5280. *pSourceStrings++ = pIniDriver->pszOEMUrl;
  5281. *pSourceStrings++ = pIniDriver->pszHardwareID;
  5282. *pSourceStrings++ = pIniDriver->pszProvider;
  5283. }
  5284. pEnd = PackStrings( SourceStrings, pDriverInfo, pOffsets, pEnd );
  5285. if ( Level == 3 || Level == 4 || Level == 6 ) {
  5286. //
  5287. // Dependent files need to be copied till \0\0
  5288. // so need to do it outside PackStirngs
  5289. //
  5290. if ( pIniDriver->cchDependentFiles ) {
  5291. pEnd = CopyMultiSzFieldToDriverInfo(
  5292. pIniDriver->pDependentFiles,
  5293. pEnd,
  5294. string,
  5295. i);
  5296. ((PDRIVER_INFO_3)pDriverInfo)->pDependentFiles = (LPWSTR) pEnd;
  5297. }
  5298. else {
  5299. ((PDRIVER_INFO_3)pDriverInfo)->pDependentFiles = NULL;
  5300. }
  5301. //
  5302. // pszzPreviousNames is multi-sz too
  5303. //
  5304. if ( Level == 4 || Level == 6) {
  5305. if ( pIniDriver->cchPreviousNames ) {
  5306. pEnd = CopyMultiSzFieldToDriverInfo(
  5307. pIniDriver->pszzPreviousNames,
  5308. pEnd,
  5309. NULL,
  5310. 0);
  5311. ((PDRIVER_INFO_4)pDriverInfo)->pszzPreviousNames = (LPWSTR) pEnd;
  5312. } else {
  5313. ((PDRIVER_INFO_4)pDriverInfo)->pszzPreviousNames = NULL;
  5314. }
  5315. }
  5316. ((PDRIVER_INFO_3)pDriverInfo)->cVersion = pIniDriver->cVersion;
  5317. } else {
  5318. //Level == 2 or Level = 5
  5319. if (Level == 2) {
  5320. ((PDRIVER_INFO_2)pDriverInfo)->cVersion = pIniDriver->cVersion;
  5321. } else {
  5322. PDRIVER_INFO_5 pDriver5;
  5323. pDriver5 = (PDRIVER_INFO_5) pDriverInfo;
  5324. pDriver5->cVersion = pIniDriver->cVersion;
  5325. if (!pIniDriver->dwDriverAttributes) {
  5326. // Driver Attributes has not been initialized as yet; do it now
  5327. CheckDriverAttributes(pIniSpooler, pIniEnvironment,
  5328. pIniVersion, pIniDriver);
  5329. }
  5330. pDriver5->dwDriverAttributes = pIniDriver->dwDriverAttributes;
  5331. pDriver5->dwConfigVersion = GetDriverFileVersion(pIniVersion,
  5332. pIniDriver->pConfigFile);
  5333. pDriver5->dwDriverVersion = GetDriverFileVersion(pIniVersion,
  5334. pIniDriver->pDriverFile);
  5335. }
  5336. }
  5337. break;
  5338. }
  5339. Fail:
  5340. FreeSplStr( pTempDriverPath );
  5341. FreeSplStr( pTempConfigFile );
  5342. FreeSplStr( pTempDataFile );
  5343. FreeSplStr( pTempHelpFile );
  5344. FreeSplMem( SourceStrings );
  5345. } else {
  5346. DBGMSG( DBG_WARNING, ("Failed to alloc driver source strings.\n"));
  5347. pEnd = NULL;
  5348. }
  5349. return pEnd;
  5350. }
  5351. LPBYTE
  5352. CopyIniDriverToDriverInfoVersion(
  5353. IN PINIENVIRONMENT pIniEnvironment,
  5354. IN PINIVERSION pIniVersion,
  5355. IN PINIDRIVER pIniDriver,
  5356. IN LPBYTE pDriverInfo,
  5357. IN LPBYTE pEnd,
  5358. IN LPWSTR lpRemote,
  5359. IN PINISPOOLER pIniSpooler
  5360. )
  5361. /*++
  5362. Routine Name:
  5363. CopyIniDriverToDriverInfoVersion
  5364. Routine Description:
  5365. This routine copy data from pIniDriver to the pDriverInfo as a DRIVER_INFO_VERSION
  5366. Arguments:
  5367. pIniEnvironment pointer to the INIENVIRONMENT structure
  5368. pIniVersion pointer to the INIVERSION structure.
  5369. pIniDriver pointer to the INIDRIVER structure.
  5370. pDriverInfo Buffer big enough to fit a DRIVER_INFO_VERSION and
  5371. the strings that needs to be packed
  5372. pEnd pointer to the end of the pDriverInfo
  5373. lpRemote flag which determines whether Remote or Local
  5374. pIniSpooler pointer to the INISPOOLER structure
  5375. Return Value:
  5376. Returns the pointer to the "end" of pDriverInfo if success.
  5377. NULL if it failes.
  5378. --*/
  5379. {
  5380. LPWSTR *pSourceStrings = NULL;
  5381. LPWSTR *SourceStrings = NULL;
  5382. DRIVER_INFO_VERSION *pDriverVersion;
  5383. WCHAR szDriverVersionDir[INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH + 1];
  5384. DWORD cStrings;
  5385. LPWSTR pTempDllFile = NULL;
  5386. pDriverVersion = (DRIVER_INFO_VERSION *)pDriverInfo;
  5387. if (!GetDriverVersionDirectory(szDriverVersionDir,
  5388. COUNTOF(szDriverVersionDir),
  5389. pIniSpooler,
  5390. pIniEnvironment,
  5391. pIniVersion,
  5392. pIniDriver,
  5393. lpRemote))
  5394. {
  5395. pEnd = NULL;
  5396. }
  5397. else
  5398. {
  5399. for (cStrings=0; DriverInfoVersionStrings[cStrings] != 0xFFFFFFFF; cStrings++);
  5400. if (!(pSourceStrings = SourceStrings = AllocSplMem(cStrings * sizeof(LPWSTR))))
  5401. {
  5402. DBGMSG( DBG_WARNING, ("Failed to alloc driver source strings.\n"));
  5403. pEnd = NULL;
  5404. }
  5405. else
  5406. {
  5407. *pSourceStrings++ = pIniDriver->pName;
  5408. *pSourceStrings++ = pIniEnvironment->pName;
  5409. *pSourceStrings++ = pIniDriver->pMonitorName;
  5410. *pSourceStrings++ = pIniDriver->pDefaultDataType;
  5411. *pSourceStrings++ = pIniDriver->pszMfgName;
  5412. *pSourceStrings++ = pIniDriver->pszOEMUrl;
  5413. *pSourceStrings++ = pIniDriver->pszHardwareID;
  5414. *pSourceStrings++ = pIniDriver->pszProvider;
  5415. //
  5416. // Pack the strings at the end of pDriverInfo
  5417. //
  5418. pEnd = PackStrings( SourceStrings, pDriverInfo, DriverInfoVersionStrings, pEnd );
  5419. if (pEnd)
  5420. {
  5421. if (pIniDriver->cchPreviousNames == 0)
  5422. {
  5423. pDriverVersion->pszzPreviousNames = NULL;
  5424. }
  5425. else
  5426. {
  5427. pEnd = CopyMultiSzFieldToDriverInfo(pIniDriver->pszzPreviousNames,
  5428. pEnd,
  5429. NULL,
  5430. 0);
  5431. if (pEnd)
  5432. {
  5433. pDriverVersion->pszzPreviousNames = (LPWSTR) pEnd;
  5434. }
  5435. }
  5436. if (pEnd)
  5437. {
  5438. pDriverVersion->cVersion = pIniDriver->cVersion;
  5439. pDriverVersion->ftDriverDate = pIniDriver->ftDriverDate;
  5440. pDriverVersion->dwlDriverVersion = pIniDriver->dwlDriverVersion;
  5441. pDriverVersion->dwFileCount = 3;
  5442. if (pIniDriver->pHelpFile && *pIniDriver->pHelpFile)
  5443. {
  5444. pDriverVersion->dwFileCount++;
  5445. }
  5446. if (pIniDriver->cchDependentFiles)
  5447. {
  5448. for (pTempDllFile = pIniDriver->pDependentFiles;
  5449. *pTempDllFile;
  5450. pTempDllFile += wcslen(pTempDllFile) + 1,
  5451. pDriverVersion->dwFileCount++ );
  5452. }
  5453. //
  5454. // Pack in the file names and versions in pDriverVersion->pFileInfo.
  5455. //
  5456. pEnd = CopyIniDriverFilesToDriverInfo(pDriverVersion,
  5457. pIniVersion,
  5458. pIniDriver,
  5459. szDriverVersionDir,
  5460. pEnd);
  5461. //
  5462. // When we are done, the end shoud not be less than the
  5463. // start of the buffer plus the driver info version buffer
  5464. // size. If these have overlapped, we are in serious trouble.
  5465. //
  5466. SPLASSERT(pEnd >= pDriverInfo + sizeof(DRIVER_INFO_VERSION));
  5467. }
  5468. }
  5469. }
  5470. }
  5471. FreeSplMem(SourceStrings);
  5472. return pEnd;
  5473. }
  5474. LPBYTE
  5475. CopyIniDriverFilesToDriverInfo(
  5476. IN LPDRIVER_INFO_VERSION pDriverVersion,
  5477. IN PINIVERSION pIniVersion,
  5478. IN PINIDRIVER pIniDriver,
  5479. IN LPCWSTR pszDriverVersionDir,
  5480. IN LPBYTE pEnd
  5481. )
  5482. /*++
  5483. Routine Name:
  5484. CopyIniDriverFilesToDriverInfo
  5485. Routine Description:
  5486. This routine copy data from pIniDriver to the pDriverInfo->pFileInfo.
  5487. The number of files is already filled in pDriverInfo->dwFileCount
  5488. Arguments:
  5489. pDriverVersion pointer to a DRIVER_INFO_VERSION structure
  5490. pIniVersion pointer to the INIVERSION structure.
  5491. pIniDriver pointer to the INIDRIVER structure.
  5492. pszDriverVersionDir string containing the driver version directory
  5493. pEnd pointer to the end of the pDriverInfo
  5494. Return Value:
  5495. Returns the pointer to the "end" of pDriverInfo if success.
  5496. NULL if it failes.
  5497. --*/
  5498. {
  5499. DWORD dwIndex = 0;
  5500. LPWSTR pTempDllFile = NULL;
  5501. DWORD dwFileSetCount = pDriverVersion->dwFileCount;
  5502. //
  5503. // Reserve space for DRIVER_FILE_INFO array
  5504. //
  5505. pEnd = (LPBYTE)ALIGN_DOWN(pEnd, ULONG_PTR);
  5506. pEnd -= dwFileSetCount * sizeof(DRIVER_FILE_INFO);
  5507. pDriverVersion->pFileInfo = (DRIVER_FILE_INFO*)pEnd;
  5508. //
  5509. // For each file call FillDriverInfo and fill in the entry
  5510. // in the array of DRIVER_FILE_INFO.
  5511. //
  5512. if (dwIndex >= pDriverVersion->dwFileCount ||
  5513. !(pEnd = FillDriverInfo(pDriverVersion,
  5514. dwIndex++,
  5515. pIniVersion,
  5516. pszDriverVersionDir,
  5517. pIniDriver->pDriverFile,
  5518. DRIVER_FILE,
  5519. pEnd)))
  5520. {
  5521. goto End;
  5522. }
  5523. if (dwIndex >= dwFileSetCount ||
  5524. !(pEnd = FillDriverInfo(pDriverVersion,
  5525. dwIndex++,
  5526. pIniVersion,
  5527. pszDriverVersionDir,
  5528. pIniDriver->pConfigFile,
  5529. CONFIG_FILE,
  5530. pEnd)))
  5531. {
  5532. goto End;
  5533. }
  5534. if (dwIndex >= dwFileSetCount ||
  5535. !(pEnd = FillDriverInfo(pDriverVersion,
  5536. dwIndex++,
  5537. pIniVersion,
  5538. pszDriverVersionDir,
  5539. pIniDriver->pDataFile,
  5540. DATA_FILE,
  5541. pEnd)))
  5542. {
  5543. goto End;
  5544. }
  5545. if (pIniDriver->pHelpFile && *pIniDriver->pHelpFile)
  5546. {
  5547. if (dwIndex >= dwFileSetCount ||
  5548. !(pEnd = FillDriverInfo(pDriverVersion,
  5549. dwIndex++,
  5550. pIniVersion,
  5551. pszDriverVersionDir,
  5552. pIniDriver->pHelpFile,
  5553. HELP_FILE,
  5554. pEnd)))
  5555. {
  5556. goto End;
  5557. }
  5558. }
  5559. if (pIniDriver->cchDependentFiles)
  5560. {
  5561. for (pTempDllFile = pIniDriver->pDependentFiles;
  5562. *pTempDllFile;
  5563. pTempDllFile += wcslen(pTempDllFile) + 1)
  5564. {
  5565. if (dwIndex >= dwFileSetCount ||
  5566. !(pEnd = FillDriverInfo(pDriverVersion,
  5567. dwIndex++,
  5568. pIniVersion,
  5569. pszDriverVersionDir,
  5570. pTempDllFile,
  5571. DEPENDENT_FILE,
  5572. pEnd)))
  5573. {
  5574. goto End;
  5575. }
  5576. }
  5577. }
  5578. End:
  5579. return pEnd;
  5580. }
  5581. LPBYTE
  5582. FillDriverInfo (
  5583. LPDRIVER_INFO_VERSION pDriverVersion,
  5584. DWORD Index,
  5585. PINIVERSION pIniVersion,
  5586. LPCWSTR pszPrefix,
  5587. LPCWSTR pszFileName,
  5588. DRIVER_FILE_TYPE FileType,
  5589. LPBYTE pEnd
  5590. )
  5591. /*++
  5592. Routine Name:
  5593. FillDriverInfo
  5594. Routine Description:
  5595. This routine copy a file name and version into the pDriverInfo->pFileInfo entry
  5596. Arguments:
  5597. pDriverVersion pointer to a DRIVER_INFO_VERSION structure
  5598. Index index in the pDriverInfo->pFileInfo array of
  5599. pIniVersion pointer to the INIVERSION structure.
  5600. pszPrefix prefix string for file name.
  5601. This should be the driver version directory
  5602. pszFileName file name, no path
  5603. FileType file type: Driver, Config, Data, etc
  5604. pEnd pointer to the end of the pDriverInfo
  5605. Return Value:
  5606. Returns the pointer to the "end" of pDriverInfo if success.
  5607. NULL if it failes.
  5608. --*/
  5609. {
  5610. LPWSTR pszTempFilePath = NULL;
  5611. LPBYTE pszNewEnd = NULL;
  5612. DWORD dwRet = ERROR_SUCCESS;
  5613. if ((dwRet = StrCatAlloc(&pszTempFilePath,
  5614. pszPrefix,
  5615. L"\\",
  5616. pszFileName,
  5617. NULL)) != ERROR_SUCCESS)
  5618. {
  5619. SetLastError(dwRet);
  5620. pszNewEnd = NULL;
  5621. }
  5622. else
  5623. {
  5624. //
  5625. // Packs the file name into pDriverInfo
  5626. //
  5627. pszNewEnd = PackStringToEOB(pszTempFilePath, pEnd);
  5628. //
  5629. // Fills in the offset in pDriverVersion where the string was packed.
  5630. // We cannot store pointers because we don't marshall anything else
  5631. // but the structure at the begining of the buffer. We could marshall
  5632. // the array of DRIVER_FILE_INFO but there is no way to update the buffer
  5633. // size between 32 and 64 bits in Win32spl.dll ( UpdateBufferSize ) since we
  5634. // don't know how many files are by that time.
  5635. //
  5636. pDriverVersion->pFileInfo[Index].FileNameOffset = MakeOffset((LPVOID)pszNewEnd, (LPVOID)pDriverVersion);
  5637. pDriverVersion->pFileInfo[Index].FileVersion = 0;
  5638. pDriverVersion->pFileInfo[Index].FileType = FileType;
  5639. if (!GetDriverFileCachedVersion(pIniVersion,
  5640. (LPWSTR)pszNewEnd,
  5641. &pDriverVersion->pFileInfo[Index].FileVersion))
  5642. {
  5643. pszNewEnd = NULL;
  5644. }
  5645. }
  5646. FreeSplMem(pszTempFilePath);
  5647. return pszNewEnd;
  5648. }
  5649. BOOL
  5650. WriteDriverIni(
  5651. PINIDRIVER pIniDriver,
  5652. PINIVERSION pIniVersion,
  5653. PINIENVIRONMENT pIniEnvironment,
  5654. PINISPOOLER pIniSpooler
  5655. )
  5656. {
  5657. HKEY hEnvironmentsRootKey, hEnvironmentKey, hDriversKey, hDriverKey;
  5658. HKEY hVersionKey;
  5659. HANDLE hToken;
  5660. DWORD dwLastError=ERROR_SUCCESS;
  5661. PINIDRIVER pUpdateIniDriver;
  5662. hToken = RevertToPrinterSelf();
  5663. if ((dwLastError = SplRegCreateKey(pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ? pIniSpooler->hckRoot : HKEY_LOCAL_MACHINE,
  5664. pIniSpooler->pszRegistryEnvironments,
  5665. 0,
  5666. KEY_WRITE,
  5667. NULL,
  5668. &hEnvironmentsRootKey,
  5669. NULL,
  5670. pIniSpooler)) == ERROR_SUCCESS) {
  5671. DBGMSG(DBG_TRACE, ("WriteDriverIni Created key %ws\n", pIniSpooler->pszRegistryEnvironments));
  5672. if ((dwLastError = SplRegCreateKey(hEnvironmentsRootKey,
  5673. pIniEnvironment->pName,
  5674. 0,
  5675. KEY_WRITE,
  5676. NULL,
  5677. &hEnvironmentKey,
  5678. NULL,
  5679. pIniSpooler)) == ERROR_SUCCESS) {
  5680. DBGMSG(DBG_TRACE, ("WriteDriverIni Created key %ws\n", pIniEnvironment->pName));
  5681. if ((dwLastError = SplRegCreateKey(hEnvironmentKey,
  5682. szDriversKey,
  5683. 0,
  5684. KEY_WRITE,
  5685. NULL,
  5686. &hDriversKey,
  5687. NULL,
  5688. pIniSpooler)) == ERROR_SUCCESS) {
  5689. DBGMSG(DBG_TRACE, ("WriteDriverIni Created key %ws\n", szDriversKey));
  5690. DBGMSG(DBG_TRACE, ("WriteDriverIni Trying to create version key %ws\n", pIniVersion->pName));
  5691. if ((dwLastError = SplRegCreateKey(hDriversKey,
  5692. pIniVersion->pName,
  5693. 0,
  5694. KEY_WRITE,
  5695. NULL,
  5696. &hVersionKey,
  5697. NULL,
  5698. pIniSpooler)) == ERROR_SUCCESS) {
  5699. DBGMSG(DBG_TRACE, ("WriteDriverIni Created key %ws\n", pIniVersion->pName));
  5700. if ((dwLastError = SplRegCreateKey(hVersionKey,
  5701. pIniDriver->pName,
  5702. 0,
  5703. KEY_WRITE,
  5704. NULL,
  5705. &hDriverKey,
  5706. NULL,
  5707. pIniSpooler)) == ERROR_SUCCESS) {
  5708. DBGMSG(DBG_TRACE,(" WriteDriverIni Created key %ws\n", pIniDriver->pName));
  5709. RegSetString(hDriverKey, szConfigurationKey, pIniDriver->pConfigFile, &dwLastError, pIniSpooler);
  5710. RegSetString(hDriverKey, szDataFileKey, pIniDriver->pDataFile, &dwLastError, pIniSpooler);
  5711. RegSetString(hDriverKey, szDriverFile, pIniDriver->pDriverFile, &dwLastError, pIniSpooler);
  5712. RegSetString(hDriverKey, szHelpFile, pIniDriver->pHelpFile, &dwLastError, pIniSpooler);
  5713. RegSetString(hDriverKey, szMonitor, pIniDriver->pMonitorName, &dwLastError, pIniSpooler);
  5714. RegSetString(hDriverKey, szDatatype, pIniDriver->pDefaultDataType, &dwLastError, pIniSpooler);
  5715. RegSetMultiString(hDriverKey, szDependentFiles, pIniDriver->pDependentFiles, pIniDriver->cchDependentFiles, &dwLastError, pIniSpooler);
  5716. RegSetMultiString(hDriverKey, szPreviousNames, pIniDriver->pszzPreviousNames, pIniDriver->cchPreviousNames, &dwLastError, pIniSpooler);
  5717. RegSetDWord(hDriverKey, szDriverVersion, pIniDriver->cVersion, &dwLastError, pIniSpooler);
  5718. RegSetDWord(hDriverKey, szTempDir, pIniDriver->dwTempDir, &dwLastError, pIniSpooler);
  5719. RegSetDWord(hDriverKey, szAttributes, pIniDriver->dwDriverAttributes, &dwLastError, pIniSpooler);
  5720. RegSetString(hDriverKey, szMfgName, pIniDriver->pszMfgName, &dwLastError, pIniSpooler);
  5721. RegSetString(hDriverKey, szOEMUrl, pIniDriver->pszOEMUrl, &dwLastError, pIniSpooler);
  5722. RegSetString(hDriverKey, szHardwareID, pIniDriver->pszHardwareID, &dwLastError, pIniSpooler);
  5723. RegSetString(hDriverKey, szProvider, pIniDriver->pszProvider, &dwLastError, pIniSpooler);
  5724. RegSetBinaryData(hDriverKey,
  5725. szDriverDate,
  5726. (LPBYTE)&pIniDriver->ftDriverDate,
  5727. sizeof(FILETIME),
  5728. &dwLastError,
  5729. pIniSpooler);
  5730. RegSetBinaryData(hDriverKey,
  5731. szLongVersion,
  5732. (LPBYTE)&pIniDriver->dwlDriverVersion,
  5733. sizeof(DWORDLONG),
  5734. &dwLastError,
  5735. pIniSpooler);
  5736. SplRegCloseKey(hDriverKey, pIniSpooler);
  5737. if(dwLastError != ERROR_SUCCESS) {
  5738. SplRegDeleteKey(hVersionKey, pIniDriver->pName, pIniSpooler);
  5739. }
  5740. }
  5741. SplRegCloseKey(hVersionKey, pIniSpooler);
  5742. }
  5743. SplRegCloseKey(hDriversKey, pIniSpooler);
  5744. }
  5745. SplRegCloseKey(hEnvironmentKey, pIniSpooler);
  5746. }
  5747. SplRegCloseKey(hEnvironmentsRootKey, pIniSpooler);
  5748. }
  5749. ImpersonatePrinterClient( hToken );
  5750. if ( dwLastError != ERROR_SUCCESS ) {
  5751. SetLastError( dwLastError );
  5752. return FALSE;
  5753. } else {
  5754. return TRUE;
  5755. }
  5756. }
  5757. BOOL
  5758. DeleteDriverIni(
  5759. PINIDRIVER pIniDriver,
  5760. PINIVERSION pIniVersion,
  5761. PINIENVIRONMENT pIniEnvironment,
  5762. PINISPOOLER pIniSpooler
  5763. )
  5764. {
  5765. HKEY hEnvironmentsRootKey, hEnvironmentKey, hDriversKey;
  5766. HANDLE hToken;
  5767. HKEY hVersionKey;
  5768. DWORD LastError= 0;
  5769. DWORD dwRet = 0;
  5770. hToken = RevertToPrinterSelf();
  5771. if ((dwRet = SplRegCreateKey(pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ? pIniSpooler->hckRoot : HKEY_LOCAL_MACHINE,
  5772. pIniSpooler->pszRegistryEnvironments,
  5773. 0,
  5774. KEY_WRITE,
  5775. NULL,
  5776. &hEnvironmentsRootKey,
  5777. NULL,
  5778. pIniSpooler) == ERROR_SUCCESS)) {
  5779. if ((dwRet = SplRegOpenKey(hEnvironmentsRootKey,
  5780. pIniEnvironment->pName,
  5781. KEY_WRITE,
  5782. &hEnvironmentKey,
  5783. pIniSpooler)) == ERROR_SUCCESS) {
  5784. if ((dwRet = SplRegOpenKey(hEnvironmentKey,
  5785. szDriversKey,
  5786. KEY_WRITE,
  5787. &hDriversKey,
  5788. pIniSpooler)) == ERROR_SUCCESS) {
  5789. if ((dwRet = SplRegOpenKey(hDriversKey,
  5790. pIniVersion->pName,
  5791. KEY_WRITE,
  5792. &hVersionKey,
  5793. pIniSpooler)) == ERROR_SUCCESS) {
  5794. if ((dwRet = SplRegDeleteKey(hVersionKey, pIniDriver->pName, pIniSpooler)) != ERROR_SUCCESS) {
  5795. LastError = dwRet;
  5796. DBGMSG( DBG_WARNING, ("Error:RegDeleteKey failed with %d\n", dwRet));
  5797. }
  5798. SplRegCloseKey(hVersionKey, pIniSpooler);
  5799. } else {
  5800. LastError = dwRet;
  5801. DBGMSG( DBG_WARNING, ("Error: RegOpenKeyEx <version> failed with %d\n", dwRet));
  5802. }
  5803. SplRegCloseKey(hDriversKey, pIniSpooler);
  5804. } else {
  5805. LastError = dwRet;
  5806. DBGMSG( DBG_WARNING, ("Error:RegOpenKeyEx <Drivers>failed with %d\n", dwRet));
  5807. }
  5808. SplRegCloseKey(hEnvironmentKey, pIniSpooler);
  5809. } else {
  5810. LastError = dwRet;
  5811. DBGMSG( DBG_WARNING, ("Error:RegOpenKeyEx <Environment> failed with %d\n", dwRet));
  5812. }
  5813. SplRegCloseKey(hEnvironmentsRootKey, pIniSpooler);
  5814. } else {
  5815. LastError = dwRet;
  5816. DBGMSG( DBG_WARNING, ("Error:RegCreateKeyEx <Environments> failed with %d\n", dwRet));
  5817. }
  5818. ImpersonatePrinterClient( hToken );
  5819. if (LastError) {
  5820. SetLastError(LastError);
  5821. return FALSE;
  5822. }
  5823. return TRUE;
  5824. }
  5825. VOID
  5826. SetOldDateOnSingleDriverFile(
  5827. LPWSTR pFileName
  5828. )
  5829. /*++
  5830. Routine Description:
  5831. This routine changes the Date / Time of the file.
  5832. The reason for doing this is that, when AddPrinterDriver is called we move the Driver
  5833. file from the ScratchDiretory to a \version directory. We then want to mark the original
  5834. file for deletion. However Integraphs install program ( an possibly others ) rely on the
  5835. file still being located in the scratch directory. By setting the files date / time
  5836. back to an earlier date / time we will not attemp to copy this file again to the \version
  5837. directory since it will be an older date.
  5838. It is then marked for deletion at reboot.
  5839. Arguments:
  5840. pFileName Just file Name ( not fully qualified )
  5841. pDir Directory where file to be deleted is located
  5842. Return Value:
  5843. None
  5844. Note:
  5845. --*/
  5846. {
  5847. FILETIME WriteFileTime;
  5848. HANDLE hFile;
  5849. if ( pFileName ) {
  5850. DBGMSG( DBG_TRACE,("Attempting to delete file %ws\n", pFileName));
  5851. hFile = CreateFile(pFileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  5852. if ( hFile != INVALID_HANDLE_VALUE ) {
  5853. DBGMSG( DBG_TRACE, ("CreateFile %ws succeeded\n", pFileName));
  5854. DosDateTimeToFileTime(0xc3, 0x3000, &WriteFileTime);
  5855. SetFileTime(hFile, &WriteFileTime, &WriteFileTime, &WriteFileTime);
  5856. CloseHandle(hFile);
  5857. } else {
  5858. DBGMSG( DBG_WARNING, ("CreateFile %ws failed with %d\n", pFileName, GetLastError()));
  5859. }
  5860. }
  5861. }
  5862. VOID
  5863. SetOldDateOnDriverFilesInScratchDirectory(
  5864. PINTERNAL_DRV_FILE pInternalDriverFiles,
  5865. DWORD FileCount,
  5866. PINISPOOLER pIniSpooler
  5867. )
  5868. {
  5869. HANDLE hToken;
  5870. SPLASSERT(FileCount);
  5871. // Run as SYSTEM so we don't run into problems
  5872. // Changing the file time or date
  5873. hToken = RevertToPrinterSelf();
  5874. do {
  5875. SetOldDateOnSingleDriverFile(pInternalDriverFiles[--FileCount].pFileName);
  5876. } while (FileCount);
  5877. ImpersonatePrinterClient(hToken);
  5878. }
  5879. PINIVERSION
  5880. FindVersionEntry(
  5881. PINIENVIRONMENT pIniEnvironment,
  5882. DWORD dwVersion
  5883. )
  5884. {
  5885. PINIVERSION pIniVersion;
  5886. pIniVersion = pIniEnvironment->pIniVersion;
  5887. while (pIniVersion) {
  5888. if (pIniVersion->cMajorVersion == dwVersion) {
  5889. return pIniVersion;
  5890. } else {
  5891. pIniVersion = pIniVersion->pNext;
  5892. }
  5893. }
  5894. return NULL;
  5895. }
  5896. PINIVERSION
  5897. CreateVersionEntry(
  5898. PINIENVIRONMENT pIniEnvironment,
  5899. DWORD dwVersion,
  5900. PINISPOOLER pIniSpooler
  5901. )
  5902. {
  5903. PINIVERSION pIniVersion = NULL;
  5904. WCHAR szTempBuffer[MAX_PATH];
  5905. BOOL bSuccess = FALSE;
  5906. try {
  5907. pIniVersion = AllocSplMem(sizeof(INIVERSION));
  5908. if ( pIniVersion == NULL ) {
  5909. leave;
  5910. }
  5911. pIniVersion->signature = IV_SIGNATURE;
  5912. wsprintf( szTempBuffer, L"Version-%d", dwVersion );
  5913. pIniVersion->pName = AllocSplStr( szTempBuffer );
  5914. if ( pIniVersion->pName == NULL ) {
  5915. leave;
  5916. }
  5917. wsprintf( szTempBuffer, L"%d", dwVersion );
  5918. pIniVersion->szDirectory = AllocSplStr(szTempBuffer);
  5919. if ( pIniVersion->szDirectory == NULL ) {
  5920. leave;
  5921. }
  5922. pIniVersion->cMajorVersion = dwVersion;
  5923. // Initialize the Driver Files Reference count list.
  5924. pIniVersion->pDrvRefCnt = NULL;
  5925. //
  5926. // Create the version directory. This will write it out to the
  5927. // registry since it will create a new directory.
  5928. //
  5929. if ( !CreateVersionDirectory( pIniVersion,
  5930. pIniEnvironment,
  5931. TRUE,
  5932. pIniSpooler )) {
  5933. //
  5934. // Something Went Wrong Clean Up Registry Entry
  5935. //
  5936. DeleteDriverVersionIni( pIniVersion, pIniEnvironment, pIniSpooler );
  5937. leave;
  5938. }
  5939. //
  5940. // insert version entry into version list
  5941. //
  5942. InsertVersionList( &pIniEnvironment->pIniVersion, pIniVersion );
  5943. bSuccess = TRUE;
  5944. } finally {
  5945. if ( !bSuccess && pIniVersion != NULL ) {
  5946. FreeSplStr( pIniVersion->pName );
  5947. FreeSplStr( pIniVersion->szDirectory );
  5948. FreeSplMem( pIniVersion );
  5949. pIniVersion = NULL;
  5950. }
  5951. }
  5952. return pIniVersion;
  5953. }
  5954. BOOL
  5955. SetDependentFiles(
  5956. IN OUT LPWSTR *ppszDependentFiles,
  5957. IN OUT LPDWORD pcchDependentFiles,
  5958. IN OUT PINTERNAL_DRV_FILE pInternalDriverFiles,
  5959. IN DWORD FileCount,
  5960. IN BOOL bFixICM,
  5961. IN BOOL bMergeDependentFiles
  5962. )
  5963. /*++
  5964. Routine Description:
  5965. Sets dependentFiles field in IniDriver
  5966. Arguments:
  5967. pDependentFiles : copy the field to this (copy file names only, not full path)
  5968. cchDependentFiles : this is the character count (inc. \0\0) of the field
  5969. pInternalDriverFiles: array of INTERNAL_DRV_FILE structures
  5970. FileCount : number of entries in previous array
  5971. bFixICM : For Win95 drivers ICM files should be used as
  5972. Color\<icm-file> in the dependent file list since
  5973. that is how SMB point and print needs it.
  5974. Return Value:
  5975. TRUE success (memory will be allocated)
  5976. FALSE else
  5977. History:
  5978. Written by MuhuntS (Muhunthan Sivapragasam) June 95
  5979. --*/
  5980. {
  5981. BOOL bRet = TRUE;
  5982. LPCWSTR pFileName = NULL;
  5983. LPWSTR pStr = NULL;
  5984. LPWSTR pszDependentFiles = NULL;
  5985. DWORD cchDependentFiles = 0;
  5986. DWORD i;
  5987. SPLASSERT(FileCount);
  5988. for ( i = cchDependentFiles = 0; i < FileCount && bRet ; ++i ) {
  5989. pFileName = FindFileName(pInternalDriverFiles[i].pFileName);
  5990. if (pFileName)
  5991. {
  5992. cchDependentFiles += wcslen(pFileName)+1;
  5993. if ( bFixICM && IsAnICMFile(pInternalDriverFiles[i].pFileName) )
  5994. cchDependentFiles += 6;
  5995. }
  5996. else
  5997. {
  5998. bRet = FALSE;
  5999. SetLastError(ERROR_FILE_NOT_FOUND);
  6000. }
  6001. }
  6002. // For last \0
  6003. ++(cchDependentFiles);
  6004. if (bRet)
  6005. {
  6006. pszDependentFiles = AllocSplMem(cchDependentFiles*sizeof(WCHAR));
  6007. bRet = pszDependentFiles != NULL;
  6008. }
  6009. if (bRet)
  6010. {
  6011. for ( i=0, pStr = pszDependentFiles; i < FileCount && bRet ; ++i ) {
  6012. pFileName = FindFileName(pInternalDriverFiles[i].pFileName);
  6013. if (pFileName)
  6014. {
  6015. if ( bFixICM && IsAnICMFile(pInternalDriverFiles[i].pFileName) ) {
  6016. wcscpy(pStr, L"Color\\");
  6017. wcscat(pStr, pFileName);
  6018. } else {
  6019. wcscpy(pStr, pFileName);
  6020. }
  6021. pStr += wcslen(pStr) + 1;
  6022. }
  6023. else
  6024. {
  6025. bRet = FALSE;
  6026. SetLastError(ERROR_FILE_NOT_FOUND);
  6027. }
  6028. }
  6029. *pStr = '\0';
  6030. }
  6031. //
  6032. // If everything succeeded so far, we have two multi-sz strings that
  6033. // represent the old and the new dependent files, what we want to do
  6034. // is to merge the resulting set of files together
  6035. //
  6036. if (bRet && bMergeDependentFiles)
  6037. {
  6038. PWSTR pszNewDependentFiles = pszDependentFiles;
  6039. DWORD cchNewDependentFiles = cchDependentFiles;
  6040. pszDependentFiles = NULL; cchDependentFiles = 0;
  6041. bRet = MergeMultiSz(*ppszDependentFiles, *pcchDependentFiles, pszNewDependentFiles, cchNewDependentFiles, &pszDependentFiles, &cchDependentFiles);
  6042. FreeSplMem(pszNewDependentFiles);
  6043. }
  6044. if (bRet)
  6045. {
  6046. *ppszDependentFiles = pszDependentFiles;
  6047. pszDependentFiles = NULL;
  6048. *pcchDependentFiles = cchDependentFiles;
  6049. }
  6050. else
  6051. {
  6052. *pcchDependentFiles = 0;
  6053. *ppszDependentFiles = NULL;
  6054. }
  6055. FreeSplMem(pszDependentFiles);
  6056. return bRet;
  6057. }
  6058. PINIDRIVER
  6059. CreateDriverEntry(
  6060. IN PINIENVIRONMENT pIniEnvironment,
  6061. IN PINIVERSION pIniVersion,
  6062. IN DWORD Level,
  6063. IN LPBYTE pDriverInfo,
  6064. IN DWORD dwFileCopyFlags,
  6065. IN PINISPOOLER pIniSpooler,
  6066. IN OUT PINTERNAL_DRV_FILE pInternalDriverFiles,
  6067. IN DWORD FileCount,
  6068. IN DWORD dwTempDir,
  6069. IN PINIDRIVER pOldIniDriver
  6070. )
  6071. /*++
  6072. Function Description - Creates a INIDRIVER struct and adds it to the list in pIniVersion
  6073. Parameters:
  6074. Return Values:
  6075. --*/
  6076. {
  6077. PINIDRIVER pIniDriver;
  6078. PDRIVER_INFO_2 pDriver = (PDRIVER_INFO_2)pDriverInfo;
  6079. PDRIVER_INFO_3 pDriver3 = (PDRIVER_INFO_3)pDriverInfo;
  6080. PDRIVER_INFO_4 pDriver4 = (PDRIVER_INFO_4)pDriverInfo;
  6081. PDRIVER_INFO_6 pDriver6 = (PDRIVER_INFO_6)pDriverInfo;
  6082. PDRIVER_INFO_VERSION pDriverVersion = (PDRIVER_INFO_VERSION)pDriverInfo;
  6083. LPWSTR pszzPreviousNames;
  6084. BOOL bFail = FALSE, bUpdate;
  6085. BOOL bCoreFilesSame = TRUE;
  6086. DWORD dwDepFileIndex, dwDepFileCount, dwLen;
  6087. bUpdate = pOldIniDriver != NULL;
  6088. if ( !(pIniDriver = (PINIDRIVER) AllocSplMem(sizeof(INIDRIVER))) ) {
  6089. return NULL;
  6090. }
  6091. else
  6092. {
  6093. pIniDriver->DriverFileMinorVersion = 0;
  6094. pIniDriver->DriverFileMajorVersion = 0;
  6095. }
  6096. // If it is an update pIniDriver is just a place holder for strings
  6097. if ( !bUpdate ) {
  6098. pIniDriver->signature = ID_SIGNATURE;
  6099. pIniDriver->cVersion = pIniVersion->cMajorVersion;
  6100. } else {
  6101. UpdateDriverFileRefCnt(pIniEnvironment, pIniVersion, pOldIniDriver, NULL, 0, FALSE);
  6102. CopyMemory(pIniDriver, pOldIniDriver, sizeof(INIDRIVER));
  6103. }
  6104. //
  6105. // For the core driver files, we want to see if any of them have changed, if
  6106. // they are the same and the behaviour is APD_COPY_NEW_FILES, then we merge
  6107. // the dependent files. This is to handle plugins correctly.
  6108. //
  6109. AllocOrUpdateStringAndTestSame(&pIniDriver->pDriverFile,
  6110. FindFileName(pInternalDriverFiles[0].pFileName),
  6111. bUpdate ? pOldIniDriver->pDriverFile : NULL,
  6112. FALSE,
  6113. &bFail,
  6114. &bCoreFilesSame);
  6115. AllocOrUpdateStringAndTestSame(&pIniDriver->pConfigFile,
  6116. FindFileName(pInternalDriverFiles[1].pFileName),
  6117. bUpdate ? pOldIniDriver->pConfigFile : NULL,
  6118. FALSE,
  6119. &bFail,
  6120. &bCoreFilesSame);
  6121. AllocOrUpdateStringAndTestSame(&pIniDriver->pDataFile,
  6122. FindFileName(pInternalDriverFiles[2].pFileName),
  6123. bUpdate ? pOldIniDriver->pDataFile : NULL,
  6124. FALSE,
  6125. &bFail,
  6126. &bCoreFilesSame);
  6127. pIniDriver->dwTempDir = dwTempDir;
  6128. switch (Level) {
  6129. case 2:
  6130. AllocOrUpdateString(&pIniDriver->pName,
  6131. pDriver->pName,
  6132. bUpdate ? pOldIniDriver->pName : NULL,
  6133. FALSE,
  6134. &bFail);
  6135. pIniDriver->pHelpFile = pIniDriver->pDependentFiles
  6136. = pIniDriver->pMonitorName
  6137. = pIniDriver->pDefaultDataType
  6138. = pIniDriver->pszzPreviousNames
  6139. = NULL;
  6140. pIniDriver->cchDependentFiles = pIniDriver->cchPreviousNames
  6141. = 0;
  6142. break;
  6143. case 3:
  6144. case 4:
  6145. pIniDriver->pszMfgName = NULL;
  6146. pIniDriver->pszOEMUrl = NULL;
  6147. pIniDriver->pszHardwareID = NULL;
  6148. pIniDriver->pszProvider = NULL;
  6149. case DRIVER_INFO_VERSION_LEVEL :
  6150. case 6:
  6151. AllocOrUpdateString(&pIniDriver->pName,
  6152. pDriver3->pName,
  6153. bUpdate ? pOldIniDriver->pName : NULL,
  6154. FALSE,
  6155. &bFail);
  6156. dwDepFileIndex = 3;
  6157. dwDepFileCount = FileCount - 3;
  6158. //
  6159. // Look for the help file
  6160. //
  6161. {
  6162. LPWSTR pszHelpFile = NULL;
  6163. if (Level == DRIVER_INFO_VERSION_LEVEL)
  6164. {
  6165. DWORD HelpFileIndex;
  6166. //
  6167. // Search for the help file in the array of file infos. All inbox
  6168. // drivers have a help file, but IHV printer drivers may not have
  6169. // one. Therefore it is not safe to assume we always have a help file
  6170. //
  6171. if (S_OK == FindIndexInDrvFileInfo(pDriverVersion->pFileInfo,
  6172. pDriverVersion->dwFileCount,
  6173. HELP_FILE,
  6174. &HelpFileIndex))
  6175. {
  6176. pszHelpFile = (LPWSTR)((LPBYTE)pDriverVersion +
  6177. pDriverVersion->pFileInfo[HelpFileIndex].FileNameOffset);
  6178. }
  6179. }
  6180. else
  6181. {
  6182. //
  6183. // Level is 3,4 or 6
  6184. //
  6185. pszHelpFile = pDriver3->pHelpFile;
  6186. }
  6187. if (pszHelpFile && *pszHelpFile)
  6188. {
  6189. AllocOrUpdateString(&pIniDriver->pHelpFile,
  6190. FindFileName(pInternalDriverFiles[3].pFileName),
  6191. bUpdate ? pOldIniDriver->pHelpFile : NULL,
  6192. FALSE,
  6193. &bFail);
  6194. ++dwDepFileIndex;
  6195. --dwDepFileCount;
  6196. }
  6197. else
  6198. {
  6199. pIniDriver->pHelpFile = NULL;
  6200. }
  6201. }
  6202. if ( dwDepFileCount ) {
  6203. //
  6204. // We want to merge the dependent files if:
  6205. // 1. None of the Core files have changed.
  6206. // 2. The call was made with APD_COPY_NEW_FILES.
  6207. //
  6208. BOOL bMergeDependentFiles = bCoreFilesSame && dwFileCopyFlags & APD_COPY_NEW_FILES;
  6209. if ( !bFail &&
  6210. !SetDependentFiles(&pIniDriver->pDependentFiles,
  6211. &pIniDriver->cchDependentFiles,
  6212. pInternalDriverFiles+dwDepFileIndex,
  6213. dwDepFileCount,
  6214. !wcscmp(pIniEnvironment->pName, szWin95Environment),
  6215. bMergeDependentFiles) ) {
  6216. bFail = TRUE;
  6217. }
  6218. } else {
  6219. pIniDriver->pDependentFiles = NULL;
  6220. pIniDriver->cchDependentFiles = 0;
  6221. }
  6222. AllocOrUpdateString(&pIniDriver->pMonitorName,
  6223. (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6224. pDriverVersion->pMonitorName : pDriver3->pMonitorName,
  6225. bUpdate ? pOldIniDriver->pMonitorName : NULL,
  6226. FALSE,
  6227. &bFail);
  6228. AllocOrUpdateString(&pIniDriver->pDefaultDataType,
  6229. (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6230. pDriverVersion->pDefaultDataType : pDriver3->pDefaultDataType,
  6231. bUpdate ? pOldIniDriver->pDefaultDataType : NULL,
  6232. FALSE,
  6233. &bFail);
  6234. pIniDriver->cchPreviousNames = 0;
  6235. if ( Level == 4 || Level == 6 || Level == DRIVER_INFO_VERSION_LEVEL) {
  6236. pszzPreviousNames = (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6237. pDriverVersion->pszzPreviousNames :
  6238. pDriver4->pszzPreviousNames;
  6239. for ( ; pszzPreviousNames && *pszzPreviousNames; pszzPreviousNames += dwLen) {
  6240. dwLen = wcslen(pszzPreviousNames) + 1;
  6241. pIniDriver->cchPreviousNames += dwLen;
  6242. }
  6243. if ( pIniDriver->cchPreviousNames ) {
  6244. pIniDriver->cchPreviousNames++;
  6245. if ( !(pIniDriver->pszzPreviousNames
  6246. = AllocSplMem(pIniDriver->cchPreviousNames
  6247. * sizeof(WCHAR))) ) {
  6248. bFail = TRUE;
  6249. } else {
  6250. CopyMemory(
  6251. (LPBYTE)(pIniDriver->pszzPreviousNames),
  6252. (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6253. pDriverVersion->pszzPreviousNames :
  6254. pDriver4->pszzPreviousNames,
  6255. pIniDriver->cchPreviousNames * sizeof(WCHAR));
  6256. }
  6257. } else {
  6258. pIniDriver->pszzPreviousNames = NULL;
  6259. }
  6260. }
  6261. if (Level == 6 || Level == DRIVER_INFO_VERSION_LEVEL) {
  6262. AllocOrUpdateString(&pIniDriver->pszMfgName,
  6263. (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6264. pDriverVersion->pszMfgName : pDriver6->pszMfgName,
  6265. bUpdate ? pOldIniDriver->pszMfgName : NULL,
  6266. FALSE,
  6267. &bFail);
  6268. AllocOrUpdateString(&pIniDriver->pszOEMUrl,
  6269. (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6270. pDriverVersion->pszOEMUrl : pDriver6->pszOEMUrl,
  6271. bUpdate ? pOldIniDriver->pszOEMUrl : NULL,
  6272. FALSE,
  6273. &bFail);
  6274. AllocOrUpdateString(&pIniDriver->pszHardwareID,
  6275. (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6276. pDriverVersion->pszHardwareID : pDriver6->pszHardwareID,
  6277. bUpdate ? pOldIniDriver->pszHardwareID : NULL,
  6278. FALSE,
  6279. &bFail);
  6280. AllocOrUpdateString(&pIniDriver->pszProvider,
  6281. (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6282. pDriverVersion->pszProvider : pDriver6->pszProvider,
  6283. bUpdate ? pOldIniDriver->pszProvider : NULL,
  6284. FALSE,
  6285. &bFail);
  6286. pIniDriver->dwlDriverVersion = (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6287. pDriverVersion->dwlDriverVersion : pDriver6->dwlDriverVersion;
  6288. pIniDriver->ftDriverDate = (Level == DRIVER_INFO_VERSION_LEVEL) ?
  6289. pDriverVersion->ftDriverDate : pDriver6->ftDriverDate;
  6290. }
  6291. break;
  6292. default: //can not be
  6293. DBGMSG(DBG_ERROR,
  6294. ("CreateDriverEntry: level can not be %d", Level) );
  6295. return NULL;
  6296. }
  6297. // Added calls to update driver files ref counts.
  6298. if ( !bFail && UpdateDriverFileRefCnt(pIniEnvironment,pIniVersion,pIniDriver,NULL,0,TRUE) ) {
  6299. //
  6300. // Update the files minor version
  6301. //
  6302. UpdateDriverFileVersion(pIniVersion, pInternalDriverFiles, FileCount);
  6303. // UMPD\KMPD detection
  6304. CheckDriverAttributes(pIniSpooler, pIniEnvironment,
  6305. pIniVersion, pIniDriver);
  6306. if ( WriteDriverIni(pIniDriver, pIniVersion, pIniEnvironment, pIniSpooler)) {
  6307. if ( bUpdate ) {
  6308. CopyNewOffsets((LPBYTE) pOldIniDriver,
  6309. (LPBYTE) pIniDriver,
  6310. IniDriverOffsets);
  6311. // Remove temp files and directory, if any
  6312. if (pOldIniDriver->dwTempDir && (dwTempDir == 0)) {
  6313. RemoveDriverTempFiles(pIniSpooler,
  6314. pIniEnvironment,
  6315. pIniVersion,
  6316. pOldIniDriver);
  6317. }
  6318. pOldIniDriver->dwDriverAttributes = pIniDriver->dwDriverAttributes;
  6319. pOldIniDriver->cchDependentFiles = pIniDriver->cchDependentFiles;
  6320. pOldIniDriver->dwTempDir = pIniDriver->dwTempDir;
  6321. pOldIniDriver->cchPreviousNames = pIniDriver->cchPreviousNames;
  6322. if(Level == 6)
  6323. {
  6324. pOldIniDriver->dwlDriverVersion = pIniDriver->dwlDriverVersion;
  6325. pOldIniDriver->ftDriverDate = pIniDriver->ftDriverDate;
  6326. }
  6327. FreeSplMem( pIniDriver );
  6328. return pOldIniDriver;
  6329. } else {
  6330. pIniDriver->pNext = pIniVersion->pIniDriver;
  6331. pIniVersion->pIniDriver = pIniDriver;
  6332. return pIniDriver;
  6333. }
  6334. }
  6335. }
  6336. //
  6337. // Get here only for failure cases.
  6338. //
  6339. FreeStructurePointers((LPBYTE) pIniDriver,
  6340. (LPBYTE) pOldIniDriver,
  6341. IniDriverOffsets);
  6342. FreeSplMem( pIniDriver );
  6343. return NULL;
  6344. }
  6345. BOOL
  6346. IsKMPD(
  6347. LPWSTR pDriverName
  6348. )
  6349. /*++
  6350. Function Description: Determines if the driver is kernel or user mode. If the dll
  6351. cant be loaded or the required export is not found, the spooler
  6352. assumes that the driver runs in kernel mode.
  6353. Parameters: pDriverName -- Driver file name
  6354. Return Values: TRUE if kernel mode;
  6355. FALSE otherwise
  6356. --*/
  6357. {
  6358. DWORD dwOldErrorMode, dwUserMode, cb;
  6359. HANDLE hInst;
  6360. BOOL bReturn = TRUE;
  6361. BOOL (*pfnDrvQuery)(DWORD, PVOID, DWORD, PDWORD);
  6362. // Avoid popups from loadlibrary failures
  6363. dwOldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  6364. hInst = LoadLibraryExW(pDriverName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  6365. if (hInst) {
  6366. // Check if the printer driver DLL exports DrvQueryDriverInfo entrypoint
  6367. pfnDrvQuery = (BOOL (*)(DWORD, PVOID, DWORD, PDWORD))
  6368. GetProcAddress(hInst, "DrvQueryDriverInfo");
  6369. if ( pfnDrvQuery ) {
  6370. try {
  6371. if ( pfnDrvQuery(DRVQUERY_USERMODE, &dwUserMode,
  6372. sizeof(dwUserMode), &cb) )
  6373. bReturn = (dwUserMode == 0);
  6374. } except(EXCEPTION_EXECUTE_HANDLER) {
  6375. SetLastError( GetExceptionCode() );
  6376. DBGMSG(DBG_ERROR,
  6377. ("IsKMPD ExceptionCode %x Driver %ws Error %d\n",
  6378. GetLastError(), pDriverName, GetLastError() ));
  6379. }
  6380. }
  6381. FreeLibrary(hInst);
  6382. }
  6383. SetErrorMode(dwOldErrorMode);
  6384. return bReturn;
  6385. }
  6386. BOOL
  6387. IniDriverIsKMPD (
  6388. PINISPOOLER pIniSpooler,
  6389. PINIENVIRONMENT pIniEnvironment,
  6390. PINIVERSION pIniVersion,
  6391. PINIDRIVER pIniDriver
  6392. )
  6393. /*++
  6394. Function Description:
  6395. Determines if the driver is kernel or user mode.
  6396. For Whistler we save pIniDriver->dwDriverAttributes under registry.
  6397. pIniDriver->dwDriverAttributes could be un-initialized at the time we do
  6398. the check to see if a driver is KM or UM.
  6399. Parameters: pIniSpooler -- pointer to INISPOOLER
  6400. pIniEnvironment -- pointer to INIENVIRONMENT
  6401. pIniVersion -- pointer to INVERSION
  6402. pIniDriver -- pointer to INIDRIVER
  6403. Return Values: TRUE if kernel mode;
  6404. FALSE otherwise
  6405. --*/
  6406. {
  6407. //
  6408. // Call IsKMPD if dwDriverAttributes is not initialized
  6409. //
  6410. if ( pIniDriver->dwDriverAttributes == 0 ) {
  6411. CheckDriverAttributes(pIniSpooler, pIniEnvironment, pIniVersion, pIniDriver);
  6412. }
  6413. return (BOOL)(pIniDriver->dwDriverAttributes & DRIVER_KERNELMODE);
  6414. }
  6415. VOID
  6416. CheckDriverAttributes(
  6417. PINISPOOLER pIniSpooler,
  6418. PINIENVIRONMENT pIniEnvironment,
  6419. PINIVERSION pIniVersion,
  6420. PINIDRIVER pIniDriver
  6421. )
  6422. /*++
  6423. Function Description: Updates the pIniDriver->dwDriverAttributes field
  6424. Parameters: pIniSpooler -- pointer to INISPOOLER
  6425. pIniEnvironment -- pointer to INIENVIRONMENT
  6426. pIniVersion -- pointer to INVERSION
  6427. pIniDriver -- pointer to INIDRIVER
  6428. Return Values: NONE
  6429. --*/
  6430. {
  6431. WCHAR szDriverFile[MAX_PATH];
  6432. PINIDRIVER pUpdateIniDriver;
  6433. if( GetDriverVersionDirectory( szDriverFile,
  6434. COUNTOF(szDriverFile),
  6435. pIniSpooler,
  6436. pIniEnvironment,
  6437. pIniVersion,
  6438. pIniDriver,
  6439. NULL) &&
  6440. StrNCatBuff(szDriverFile,
  6441. COUNTOF(szDriverFile),
  6442. szDriverFile,
  6443. L"\\",
  6444. FindFileName(pIniDriver->pDriverFile),
  6445. NULL) == ERROR_SUCCESS )
  6446. {
  6447. pIniDriver->dwDriverAttributes = IsKMPD(szDriverFile) ? DRIVER_KERNELMODE
  6448. : DRIVER_USERMODE;
  6449. // Update other pIniDriver structs with the new driver attributes.
  6450. for (pUpdateIniDriver = pIniVersion->pIniDriver;
  6451. pUpdateIniDriver;
  6452. pUpdateIniDriver = pUpdateIniDriver->pNext) {
  6453. if (pUpdateIniDriver == pIniDriver) {
  6454. // Already updated this driver
  6455. continue;
  6456. }
  6457. if (!_wcsicmp(FindFileName(pIniDriver->pDriverFile),
  6458. FindFileName(pUpdateIniDriver->pDriverFile))) {
  6459. pUpdateIniDriver->dwDriverAttributes = pIniDriver->dwDriverAttributes;
  6460. }
  6461. }
  6462. }
  6463. return;
  6464. }
  6465. BOOL
  6466. FileInUse(
  6467. PINIVERSION pIniVersion,
  6468. LPWSTR pFileName
  6469. )
  6470. /*++
  6471. Function Description: Finds if the file specified by pFileName is used by any driver.
  6472. Parameters: pIniVersion - pointer to INIVERSION struct where the ref counts are
  6473. stored
  6474. pFileName - Name of the driver related file
  6475. Return Value: TRUE if file is in Use
  6476. FALSE otherwise
  6477. --*/
  6478. {
  6479. PDRVREFCNT pdrc;
  6480. if (!pFileName || !(*pFileName)) {
  6481. return FALSE;
  6482. }
  6483. pdrc = pIniVersion->pDrvRefCnt;
  6484. while (pdrc != NULL) {
  6485. if (_wcsicmp(pFileName,pdrc->szDrvFileName) == 0) {
  6486. return (pdrc->refcount > 1);
  6487. }
  6488. pdrc = pdrc->pNext;
  6489. }
  6490. return FALSE;
  6491. }
  6492. BOOL
  6493. FilesInUse(
  6494. PINIVERSION pIniVersion,
  6495. PINIDRIVER pIniDriver
  6496. )
  6497. /*++
  6498. Function Description: FilesInUse checks if any of the driver files are used by another
  6499. driver
  6500. Parameters: pIniVersion - pointer to INIVERSION struct where the ref counts are
  6501. stored
  6502. pIniDriver - pointer to INIDRIVER struct where the filenames are stored
  6503. Return Value: TRUE if any file is in Use
  6504. FALSE otherwise
  6505. --*/
  6506. {
  6507. LPWSTR pIndex;
  6508. if (FileInUse(pIniVersion,pIniDriver->pDriverFile)) {
  6509. return TRUE;
  6510. }
  6511. if (FileInUse(pIniVersion,pIniDriver->pConfigFile)) {
  6512. return TRUE;
  6513. }
  6514. if (FileInUse(pIniVersion,pIniDriver->pDataFile)) {
  6515. return TRUE;
  6516. }
  6517. if (FileInUse(pIniVersion,pIniDriver->pHelpFile)) {
  6518. return TRUE;
  6519. }
  6520. pIndex = pIniDriver->pDependentFiles;
  6521. while (pIndex && *pIndex) {
  6522. if (FileInUse(pIniVersion,pIndex)) return TRUE;
  6523. pIndex += wcslen(pIndex) + 1;
  6524. }
  6525. return FALSE;
  6526. }
  6527. BOOL
  6528. DuplicateFile(
  6529. PDRVFILE *ppfile,
  6530. LPCWSTR pFileName,
  6531. BOOL *pbDuplicate
  6532. )
  6533. /*++
  6534. Function Description: Detects repeated filenames in INIDRIVER struct.
  6535. The function adds nodes to the list of filenames.
  6536. Parameters: ppfile - pointer to a list of filenames seen till now
  6537. pFileName - name of the file
  6538. pbDuplicate - pointer to flag to indicate duplication
  6539. Return Values: TRUE - if successful
  6540. FALSE - otherwise
  6541. --*/
  6542. {
  6543. PDRVFILE pfile = *ppfile,pfiletemp;
  6544. *pbDuplicate = FALSE;
  6545. if (!pFileName || !(*pFileName)) {
  6546. return TRUE;
  6547. }
  6548. while (pfile) {
  6549. if (pfile->pFileName && (lstrcmpi(pFileName,pfile->pFileName) == 0)) {
  6550. *pbDuplicate = TRUE;
  6551. return TRUE;
  6552. }
  6553. pfile = pfile->pnext;
  6554. }
  6555. if (!(pfiletemp = AllocSplMem(sizeof(DRVFILE)))) {
  6556. return FALSE;
  6557. }
  6558. pfiletemp->pnext = *ppfile;
  6559. pfiletemp->pFileName = pFileName;
  6560. *ppfile = pfiletemp;
  6561. return TRUE;
  6562. }
  6563. BOOL
  6564. InternalIncrement(
  6565. PDRVREFNODE *pNew,
  6566. PDRVFILE *ppfile,
  6567. PINIVERSION pIniVersion,
  6568. LPCWSTR pFileName
  6569. )
  6570. /*++
  6571. Function Description: InternalIncrement calls IncrementFileRefCnt and saves the pointer to
  6572. to the DRVREFCNT in a DRVREFNODE. These pointers are used to readjust
  6573. the ref counts if any intermediate call to IncrementFileRefCnt fails.
  6574. Parameters: pNew - pointer to a variable which contains a pointer to a DRVREFNODE.
  6575. The new DRVREFNODE is assigned to this variable.
  6576. ppfile - list of filenames seen so far.
  6577. pIniVersion - pointer to INIVERSION struct.
  6578. pFileName - Name of the file whose ref cnt is to be incremented.
  6579. Return Value: TRUE if memory allocation and call to IncrementFileRefCnt succeeds
  6580. FALSE otherwise.
  6581. --*/
  6582. {
  6583. PDRVREFNODE ptemp;
  6584. BOOL bDuplicate;
  6585. if (!pFileName || !pFileName[0]) {
  6586. return TRUE;
  6587. }
  6588. if (!DuplicateFile(ppfile, pFileName, &bDuplicate)) {
  6589. return FALSE;
  6590. }
  6591. if (bDuplicate) {
  6592. return TRUE;
  6593. }
  6594. if (!(ptemp = AllocSplMem(sizeof(DRVREFNODE)))) {
  6595. return FALSE;
  6596. }
  6597. ptemp->pNext = *pNew;
  6598. *pNew = ptemp;
  6599. if ((*pNew)->pdrc = IncrementFileRefCnt(pIniVersion,pFileName)) {
  6600. return TRUE;
  6601. } else {
  6602. return FALSE;
  6603. }
  6604. }
  6605. BOOL
  6606. InternalDecrement(
  6607. PDRVREFNODE *pNew,
  6608. PDRVFILE *ppfile,
  6609. PINIENVIRONMENT pIniEnvironment,
  6610. PINIVERSION pIniVersion,
  6611. PINIDRIVER pIniDriver,
  6612. LPCWSTR pFileName,
  6613. LPCWSTR pDirectory,
  6614. DWORD dwDeleteFlag
  6615. )
  6616. /*++
  6617. Function Description: InternalDecrement calls DecrementFileRefCnt and saves the pointer to
  6618. to the DRVREFCNT in a DRVREFNODE. These pointers are used to readjust
  6619. the ref counts if any intermediate call to DecrementFileRefCnt fails.
  6620. Parameters: pNew - pointer to a variable which contains a pointer to a DRVREFNODE.
  6621. The new DRVREFNODE is assigned to this variable.
  6622. ppfile - list of filenames seen so far.
  6623. pIniEnvironment - pointer to INIENVIRONMENT.
  6624. pIniVersion - pointer to INIVERSION struct.
  6625. pIniDriver - pointer to INIDRIVER.
  6626. pFileName - Name of the file whose ref cnt is to be decremented.
  6627. pDirectory - Directory where the files are stored.
  6628. dwDeleteFlag - Flag to delete files.
  6629. Return Value: TRUE if memory allocation and call to DecrementFileRefCnt succeeds
  6630. FALSE otherwise.
  6631. --*/
  6632. {
  6633. PDRVREFNODE ptemp;
  6634. BOOL bDuplicate;
  6635. if( !pFileName || !pFileName[0] ){
  6636. return TRUE;
  6637. }
  6638. if (!DuplicateFile(ppfile, pFileName, &bDuplicate)) {
  6639. return FALSE;
  6640. }
  6641. if (bDuplicate) {
  6642. return TRUE;
  6643. }
  6644. if (!(ptemp = AllocSplMem(sizeof(DRVREFNODE)))) {
  6645. return FALSE;
  6646. }
  6647. ptemp->pNext = *pNew;
  6648. *pNew = ptemp;
  6649. if ((*pNew)->pdrc = DecrementFileRefCnt(pIniEnvironment,pIniVersion,pIniDriver,pFileName,
  6650. pDirectory,dwDeleteFlag)) {
  6651. return TRUE;
  6652. } else {
  6653. return FALSE;
  6654. }
  6655. }
  6656. BOOL
  6657. UpdateDriverFileRefCnt(
  6658. PINIENVIRONMENT pIniEnvironment,
  6659. PINIVERSION pIniVersion,
  6660. PINIDRIVER pIniDriver,
  6661. LPCWSTR pDirectory,
  6662. DWORD dwDeleteFlag,
  6663. BOOL bIncrementFlag
  6664. )
  6665. /*++
  6666. Function Description: UpdateDriverRefCnt calls the functions to increment or decrement
  6667. the ref cnts for the driver related files. If any call fails, the
  6668. ref cnts are returned to their previous values.
  6669. Parameters: pIniEnvironment : pointer to INIENVIRONMENT
  6670. pIniVersion : pointer to INIVERSION struct which contains the ref cnts.
  6671. pIniDriver : pointer to INIDRIVER struct which contains driver info.
  6672. pDirectory : Directory where the files are stored.
  6673. dwDeleteFlag: Flag to delete the files.
  6674. bIncrementFlag: TRUE if driver added
  6675. FALSE if driver deleted.
  6676. Return Values: TRUE if success
  6677. FALSE otherwise.
  6678. --*/
  6679. {
  6680. LPWSTR pIndex;
  6681. PDRVREFNODE phead=NULL,ptemp=NULL;
  6682. BOOL bReturn = TRUE;
  6683. PDRVFILE pfile = NULL,pfiletemp;
  6684. PDRVREFCNT pDrvRefCnt, *ppDrvRefCnt;
  6685. pIndex = pIniDriver->pDependentFiles;
  6686. if (bIncrementFlag) {
  6687. // Adding driver entry. Increment fileref counts.
  6688. if (!InternalIncrement(&phead,&pfile,pIniVersion,pIniDriver->pDriverFile)
  6689. || !InternalIncrement(&phead,&pfile,pIniVersion,pIniDriver->pConfigFile)
  6690. || !InternalIncrement(&phead,&pfile,pIniVersion,pIniDriver->pHelpFile)
  6691. || !InternalIncrement(&phead,&pfile,pIniVersion,pIniDriver->pDataFile)) {
  6692. bReturn = FALSE;
  6693. goto CleanUp;
  6694. }
  6695. while (pIndex && *pIndex) {
  6696. if (!InternalIncrement(&phead,&pfile,pIniVersion,pIndex)) {
  6697. bReturn = FALSE;
  6698. goto CleanUp;
  6699. }
  6700. pIndex += wcslen(pIndex) + 1;
  6701. }
  6702. } else {
  6703. // Deleting driver entry. Decrement fileref counts.
  6704. if (!InternalDecrement(&phead,&pfile,pIniEnvironment,pIniVersion,pIniDriver,pIniDriver->pDriverFile,
  6705. pDirectory,dwDeleteFlag)
  6706. || !InternalDecrement(&phead,&pfile,pIniEnvironment,pIniVersion,pIniDriver,pIniDriver->pConfigFile,
  6707. pDirectory,dwDeleteFlag)
  6708. || !InternalDecrement(&phead,&pfile,pIniEnvironment,pIniVersion,pIniDriver,pIniDriver->pHelpFile,
  6709. pDirectory,dwDeleteFlag)
  6710. || !InternalDecrement(&phead,&pfile,pIniEnvironment,pIniVersion,pIniDriver,pIniDriver->pDataFile,
  6711. pDirectory,dwDeleteFlag)) {
  6712. bReturn = FALSE;
  6713. goto CleanUp;
  6714. }
  6715. while (pIndex && *pIndex) {
  6716. if (!InternalDecrement(&phead,&pfile,pIniEnvironment,pIniVersion,pIniDriver,pIndex,pDirectory,dwDeleteFlag)) {
  6717. bReturn = FALSE;
  6718. goto CleanUp;
  6719. }
  6720. pIndex += wcslen(pIndex) + 1;
  6721. }
  6722. }
  6723. CleanUp:
  6724. if (bReturn) {
  6725. //
  6726. // When delete the file, remove the RefCnt nodes with count = 0.
  6727. // We want to keep the node when we don't delete the file because the node
  6728. // contains info about how many times the file was updated (dwVersion).
  6729. // Client apps (WINSPOOL.DRV) rely on this when decide to reload the driver files.
  6730. //
  6731. while (ptemp = phead) {
  6732. if (ptemp->pdrc &&
  6733. ptemp->pdrc->refcount == 0 &&
  6734. (dwDeleteFlag & DPD_DELETE_UNUSED_FILES ||
  6735. dwDeleteFlag & DPD_DELETE_ALL_FILES)) {
  6736. FreeSplStr(ptemp->pdrc->szDrvFileName);
  6737. FreeSplMem(ptemp->pdrc);
  6738. }
  6739. phead = phead->pNext;
  6740. FreeSplMem(ptemp);
  6741. }
  6742. } else {
  6743. // Adjust the ref counts.
  6744. while (ptemp = phead) {
  6745. if (ptemp->pdrc) {
  6746. if (bIncrementFlag) {
  6747. ptemp->pdrc->refcount--;
  6748. } else {
  6749. ptemp->pdrc->refcount++;
  6750. if (ptemp->pdrc->refcount == 1) {
  6751. ptemp->pdrc->pNext = pIniVersion->pDrvRefCnt;
  6752. pIniVersion->pDrvRefCnt = ptemp->pdrc;
  6753. }
  6754. }
  6755. }
  6756. phead = phead->pNext;
  6757. FreeSplMem(ptemp);
  6758. }
  6759. //
  6760. // When delete the file, remove the RefCnt nodes with count = 0.
  6761. // We want to keep the node when we don't delete the file because the node
  6762. // contains info about how many times the file was updated (dwVersion).
  6763. // Client apps (WINSPOOL.DRV) rely on this when decide to reload the driver files.
  6764. //
  6765. ppDrvRefCnt = &(pIniVersion->pDrvRefCnt);
  6766. while (pDrvRefCnt = *ppDrvRefCnt) {
  6767. if (pDrvRefCnt->refcount == 0 && dwDeleteFlag) {
  6768. *ppDrvRefCnt = pDrvRefCnt->pNext;
  6769. FreeSplStr(pDrvRefCnt->szDrvFileName);
  6770. FreeSplMem(pDrvRefCnt);
  6771. } else {
  6772. ppDrvRefCnt = &(pDrvRefCnt->pNext);
  6773. }
  6774. }
  6775. }
  6776. while (pfiletemp = pfile) {
  6777. pfile = pfile->pnext;
  6778. FreeSplMem(pfiletemp);
  6779. }
  6780. return bReturn;
  6781. }
  6782. VOID
  6783. UpdateDriverFileVersion(
  6784. IN PINIVERSION pIniVersion,
  6785. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  6786. IN DWORD FileCount
  6787. )
  6788. {
  6789. PDRVREFCNT pdrc;
  6790. DWORD dwIndex;
  6791. SplInSem();
  6792. if (pInternalDriverFiles && pIniVersion)
  6793. {
  6794. for (dwIndex = 0 ; dwIndex < FileCount ; dwIndex ++)
  6795. {
  6796. //
  6797. // Don't do anything for non-executable files
  6798. //
  6799. if (!IsEXEFile(pInternalDriverFiles[dwIndex].pFileName))
  6800. {
  6801. continue;
  6802. }
  6803. //
  6804. // Search the entry in pIniVersion's list of files
  6805. //
  6806. for (pdrc = pIniVersion->pDrvRefCnt;
  6807. pdrc &&
  6808. lstrcmpi(FindFileName(pInternalDriverFiles[dwIndex].pFileName),
  6809. pdrc->szDrvFileName) != 0;
  6810. pdrc = pdrc->pNext);
  6811. if (pdrc)
  6812. {
  6813. if (pInternalDriverFiles[dwIndex].hFileHandle == INVALID_HANDLE_VALUE)
  6814. {
  6815. //
  6816. // We can come in here from a pending upgrade when we don't know the
  6817. // version.
  6818. //
  6819. pdrc->bInitialized = FALSE;
  6820. }
  6821. else if (pInternalDriverFiles[dwIndex].bUpdated)
  6822. {
  6823. pdrc->dwFileMinorVersion = pInternalDriverFiles[dwIndex].dwVersion;
  6824. pdrc->bInitialized = TRUE;
  6825. }
  6826. }
  6827. }
  6828. }
  6829. }
  6830. PDRVREFCNT
  6831. IncrementFileRefCnt(
  6832. PINIVERSION pIniVersion,
  6833. LPCWSTR pFileName
  6834. )
  6835. /*++
  6836. Function Description: IncrementFileRefCnt increments/initializes to 1 the ref count node
  6837. for pFileName in the IniVersion Struct.
  6838. Parameters: pIniversion - pointer to the INIVERSION struct.
  6839. pFileName - Name of the file whose ref cnt is to be incremented.
  6840. Return Values: Pointer to the ref cnt that was incremented
  6841. NULL if memory allocation fails.
  6842. --*/
  6843. {
  6844. PDRVREFCNT pdrc;
  6845. SplInSem();
  6846. if (!pIniVersion || !pFileName || !(*pFileName)) {
  6847. return NULL;
  6848. }
  6849. pdrc = pIniVersion->pDrvRefCnt;
  6850. while (pdrc != NULL) {
  6851. if (lstrcmpi(pFileName,pdrc->szDrvFileName) == 0) {
  6852. pdrc->refcount++;
  6853. return pdrc;
  6854. }
  6855. pdrc = pdrc->pNext;
  6856. }
  6857. if (!(pdrc = (PDRVREFCNT) AllocSplMem(sizeof(DRVREFCNT)))) return NULL;
  6858. pdrc->refcount = 1;
  6859. pdrc->dwVersion = 0;
  6860. pdrc->dwFileMinorVersion = 0;
  6861. pdrc->dwFileMajorVersion = 0;
  6862. pdrc->bInitialized = 0;
  6863. if (!(pdrc->szDrvFileName = AllocSplStr(pFileName))) {
  6864. FreeSplMem(pdrc);
  6865. return NULL;
  6866. }
  6867. pdrc->pNext = pIniVersion->pDrvRefCnt;
  6868. pIniVersion->pDrvRefCnt = pdrc;
  6869. return pdrc;
  6870. }
  6871. DWORD
  6872. GetEnvironmentScratchDirectory(
  6873. LPWSTR pDir,
  6874. DWORD MaxLength,
  6875. PINIENVIRONMENT pIniEnvironment,
  6876. BOOL Remote
  6877. )
  6878. {
  6879. PINISPOOLER pIniSpooler = pIniEnvironment->pIniSpooler;
  6880. if (Remote) {
  6881. if( StrNCatBuff( pDir,
  6882. MaxLength,
  6883. pIniSpooler->pMachineName,
  6884. L"\\",
  6885. pIniSpooler->pszDriversShare,
  6886. L"\\",
  6887. pIniEnvironment->pDirectory,
  6888. NULL) != ERROR_SUCCESS )
  6889. return 0;
  6890. } else {
  6891. if( StrNCatBuff( pDir,
  6892. MaxLength,
  6893. pIniSpooler->pDir,
  6894. L"\\",
  6895. szDriverDir,
  6896. L"\\",
  6897. pIniEnvironment->pDirectory,
  6898. NULL) != ERROR_SUCCESS ) {
  6899. return 0;
  6900. }
  6901. }
  6902. return wcslen(pDir);
  6903. }
  6904. BOOL
  6905. CreateVersionDirectory(
  6906. PINIVERSION pIniVersion,
  6907. PINIENVIRONMENT pIniEnvironment,
  6908. BOOL bUpdate,
  6909. PINISPOOLER pIniSpooler
  6910. )
  6911. /*++
  6912. Routine Description:
  6913. Creates a version directory if necessary for the environment.
  6914. If a version number file exists instead of a directory, a tmp
  6915. directory is created, and pIniVersion is updated appropriately.
  6916. We will update the registry if we need to create a directory by
  6917. re-writing the entire version entry. This is how the version
  6918. entry in the registry is initially created.
  6919. Arguments:
  6920. pIniVersion - Version of drivers that the directory will hold.
  6921. If the directory already exists, we will modify
  6922. pIniVersion->szDirectory to a temp name and write
  6923. it to the registry.
  6924. pIniEnvironment - Environment to use.
  6925. bUpdate - Indicates whether we should write out the IniVersion
  6926. registry entries. We need to do this if we just alloced
  6927. the pIniVersion, or if we have changed directories.
  6928. pIniSpooler
  6929. Return Value:
  6930. BOOL - TRUE = Version directory and registry created/updated.
  6931. FALSE = Failure, call GetLastError().
  6932. --*/
  6933. {
  6934. WCHAR ParentDir[MAX_PATH];
  6935. WCHAR Directory[MAX_PATH];
  6936. DWORD dwParentLen=0;
  6937. DWORD dwAttributes = 0;
  6938. BOOL bCreateDirectory = FALSE;
  6939. BOOL bReturn = TRUE;
  6940. HANDLE hToken;
  6941. if((StrNCatBuff ( ParentDir,
  6942. COUNTOF(ParentDir),
  6943. pIniSpooler->pDir,
  6944. L"\\drivers\\" ,
  6945. pIniEnvironment->pDirectory,
  6946. NULL) != ERROR_SUCCESS ) ||
  6947. (StrNCatBuff ( Directory,
  6948. COUNTOF(Directory),
  6949. pIniSpooler->pDir,
  6950. L"\\drivers\\",
  6951. pIniEnvironment->pDirectory,
  6952. L"\\",
  6953. pIniVersion->szDirectory,
  6954. NULL) != ERROR_SUCCESS ) )
  6955. {
  6956. bReturn = FALSE;
  6957. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  6958. goto End;
  6959. }
  6960. DBGMSG( DBG_TRACE, ("The name of the version directory is %ws\n", Directory));
  6961. dwAttributes = GetFileAttributes( Directory );
  6962. hToken = RevertToPrinterSelf();
  6963. if (dwAttributes == 0xffffffff) {
  6964. bCreateDirectory = TRUE;
  6965. } else if (!(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  6966. LPWSTR pszOldDirectory = pIniVersion->szDirectory;
  6967. DBGMSG(DBG_WARNING, ("CreateVersionDirectory: a file <not a dir> exists by the name of %ws\n", Directory));
  6968. GetTempFileName(ParentDir, L"SPL", 0, Directory);
  6969. //
  6970. // GetTempFileName creates the file. (Small window where someone
  6971. // else could grab our file name.)
  6972. //
  6973. SplDeleteFile(Directory);
  6974. //
  6975. // We created a new dir, so modify the string.
  6976. //
  6977. dwParentLen = wcslen(ParentDir);
  6978. pIniVersion->szDirectory = AllocSplStr(&Directory[dwParentLen+1]);
  6979. if (!pIniVersion->szDirectory) {
  6980. pIniVersion->szDirectory = pszOldDirectory;
  6981. //
  6982. // Memory allocation failed, just revert back to old and
  6983. // let downwind code handle failure case.
  6984. //
  6985. bReturn = FALSE;
  6986. } else {
  6987. FreeSplStr(pszOldDirectory);
  6988. bCreateDirectory = TRUE;
  6989. }
  6990. }
  6991. if( bCreateDirectory ){
  6992. if( CreateCompleteDirectory( Directory )){
  6993. //
  6994. // Be sure to update the registry entries.
  6995. //
  6996. bUpdate = TRUE;
  6997. } else {
  6998. //
  6999. // Fail the operation since we couldn't create the directory.
  7000. //
  7001. bReturn = FALSE;
  7002. }
  7003. }
  7004. if( bUpdate ){
  7005. //
  7006. // Directory exists, update registry.
  7007. //
  7008. bReturn = WriteDriverVersionIni( pIniVersion,
  7009. pIniEnvironment,
  7010. pIniSpooler);
  7011. }
  7012. ImpersonatePrinterClient( hToken );
  7013. End:
  7014. return bReturn;
  7015. }
  7016. BOOL
  7017. WriteDriverVersionIni(
  7018. PINIVERSION pIniVersion,
  7019. PINIENVIRONMENT pIniEnvironment,
  7020. PINISPOOLER pIniSpooler
  7021. )
  7022. /*++
  7023. Routine Description:
  7024. Writes out the driver version registry entries.
  7025. Note: assumes we are running in the system context; callee must
  7026. call RevertToPrinterSelf()!
  7027. Arguments:
  7028. pIniVersion - version to write out
  7029. pIniEnvironment - environment the version belongs to
  7030. pIniSpooler
  7031. Return Value:
  7032. TRUE = success
  7033. FALSE = failure, call GetLastError()
  7034. --*/
  7035. {
  7036. HKEY hEnvironmentsRootKey = NULL;
  7037. HKEY hEnvironmentKey = NULL;
  7038. HKEY hDriversKey = NULL;
  7039. HKEY hVersionKey = NULL;
  7040. DWORD dwLastError = ERROR_SUCCESS;
  7041. BOOL bReturnValue;
  7042. try {
  7043. //
  7044. // The local spooler and cluster spoolers do not share the same resgirty location
  7045. // for environments, drivers, processors etc.
  7046. //
  7047. if ( !PrinterCreateKey( pIniSpooler->SpoolerFlags & SPL_CLUSTER_REG ? pIniSpooler->hckRoot : HKEY_LOCAL_MACHINE,
  7048. (LPWSTR)pIniSpooler->pszRegistryEnvironments,
  7049. &hEnvironmentsRootKey,
  7050. &dwLastError,
  7051. pIniSpooler )) {
  7052. leave;
  7053. }
  7054. if ( !PrinterCreateKey( hEnvironmentsRootKey,
  7055. pIniEnvironment->pName,
  7056. &hEnvironmentKey,
  7057. &dwLastError,
  7058. pIniSpooler )) {
  7059. leave;
  7060. }
  7061. if ( !PrinterCreateKey( hEnvironmentKey,
  7062. szDriversKey,
  7063. &hDriversKey,
  7064. &dwLastError,
  7065. pIniSpooler )) {
  7066. leave;
  7067. }
  7068. if ( !PrinterCreateKey( hDriversKey,
  7069. pIniVersion->pName,
  7070. &hVersionKey,
  7071. &dwLastError,
  7072. pIniSpooler )) {
  7073. leave;
  7074. }
  7075. RegSetString( hVersionKey, szDirectory, pIniVersion->szDirectory, &dwLastError, pIniSpooler );
  7076. RegSetDWord( hVersionKey, szMajorVersion, pIniVersion->cMajorVersion, &dwLastError, pIniSpooler );
  7077. RegSetDWord( hVersionKey, szMinorVersion, pIniVersion->cMinorVersion ,&dwLastError, pIniSpooler );
  7078. } finally {
  7079. if (hVersionKey)
  7080. SplRegCloseKey(hVersionKey, pIniSpooler);
  7081. if (hDriversKey)
  7082. SplRegCloseKey(hDriversKey, pIniSpooler);
  7083. if (hEnvironmentKey)
  7084. SplRegCloseKey(hEnvironmentKey, pIniSpooler);
  7085. if (hEnvironmentsRootKey)
  7086. SplRegCloseKey(hEnvironmentsRootKey, pIniSpooler);
  7087. if (dwLastError != ERROR_SUCCESS) {
  7088. SetLastError(dwLastError);
  7089. bReturnValue = FALSE;
  7090. } else {
  7091. bReturnValue = TRUE;
  7092. }
  7093. }
  7094. return bReturnValue;
  7095. }
  7096. BOOL
  7097. DeleteDriverVersionIni(
  7098. PINIVERSION pIniVersion,
  7099. PINIENVIRONMENT pIniEnvironment,
  7100. PINISPOOLER pIniSpooler
  7101. )
  7102. {
  7103. HKEY hEnvironmentsRootKey, hEnvironmentKey, hDriversKey;
  7104. HANDLE hToken;
  7105. HKEY hVersionKey;
  7106. BOOL bReturnValue = FALSE;
  7107. DWORD Status;
  7108. hToken = RevertToPrinterSelf();
  7109. if ( RegCreateKeyEx( HKEY_LOCAL_MACHINE, pIniSpooler->pszRegistryEnvironments, 0,
  7110. NULL, 0, KEY_WRITE, NULL, &hEnvironmentsRootKey, NULL) == ERROR_SUCCESS) {
  7111. if ( RegOpenKeyEx( hEnvironmentsRootKey, pIniEnvironment->pName, 0,
  7112. KEY_WRITE, &hEnvironmentKey) == ERROR_SUCCESS) {
  7113. if ( RegOpenKeyEx( hEnvironmentKey, szDriversKey, 0,
  7114. KEY_WRITE, &hDriversKey) == ERROR_SUCCESS) {
  7115. Status = RegDeleteKey( hDriversKey, pIniVersion->pName );
  7116. if ( Status == ERROR_SUCCESS ) {
  7117. bReturnValue = TRUE;
  7118. } else {
  7119. DBGMSG( DBG_WARNING, ( "DeleteDriverVersionIni failed RegDeleteKey %x %ws error %d\n",
  7120. hDriversKey,
  7121. pIniVersion->pName,
  7122. Status ));
  7123. }
  7124. RegCloseKey(hDriversKey);
  7125. }
  7126. RegCloseKey(hEnvironmentKey);
  7127. }
  7128. RegCloseKey(hEnvironmentsRootKey);
  7129. }
  7130. ImpersonatePrinterClient( hToken );
  7131. return bReturnValue;
  7132. }
  7133. BOOL
  7134. SplGetPrinterDriverEx(
  7135. HANDLE hPrinter,
  7136. LPWSTR pEnvironment,
  7137. DWORD Level,
  7138. LPBYTE pDriverInfo,
  7139. DWORD cbBuf,
  7140. LPDWORD pcbNeeded,
  7141. DWORD dwClientMajorVersion,
  7142. DWORD dwClientMinorVersion,
  7143. PDWORD pdwServerMajorVersion,
  7144. PDWORD pdwServerMinorVersion
  7145. )
  7146. {
  7147. PINIDRIVER pIniDriver=NULL;
  7148. PINIVERSION pIniVersion=NULL;
  7149. PINIENVIRONMENT pIniEnvironment;
  7150. DWORD cb;
  7151. LPBYTE pEnd;
  7152. PSPOOL pSpool = (PSPOOL)hPrinter;
  7153. PINISPOOLER pIniSpooler;
  7154. LPWSTR psz;
  7155. if ((dwClientMajorVersion == (DWORD)-1) && (dwClientMinorVersion == (DWORD)-1)) {
  7156. dwClientMajorVersion = dwMajorVersion;
  7157. dwClientMinorVersion = dwMinorVersion;
  7158. }
  7159. EnterSplSem();
  7160. if (!ValidateSpoolHandle(pSpool, PRINTER_HANDLE_SERVER )) {
  7161. LeaveSplSem();
  7162. return FALSE;
  7163. }
  7164. pIniSpooler = pSpool->pIniSpooler;
  7165. if (!(pIniEnvironment = FindEnvironment(pEnvironment, pIniSpooler))) {
  7166. LeaveSplSem();
  7167. SetLastError(ERROR_INVALID_ENVIRONMENT);
  7168. return FALSE;
  7169. }
  7170. //
  7171. // if the printer handle is remote or a non-native driver is asked for,
  7172. // then return back a compatible driver; Else return pIniPrinter->pIniDriver
  7173. //
  7174. if ( (pSpool->TypeofHandle & PRINTER_HANDLE_REMOTE_CALL) ||
  7175. lstrcmpi(szEnvironment, pIniEnvironment->pName) ) {
  7176. pIniDriver = FindCompatibleDriver(pIniEnvironment,
  7177. &pIniVersion,
  7178. pSpool->pIniPrinter->pIniDriver->pName,
  7179. dwClientMajorVersion,
  7180. FIND_COMPATIBLE_VERSION | DRIVER_SEARCH);
  7181. //
  7182. // For Windows 9x drivers if no driver with same name is found
  7183. // then we look for a driver with name in the pszzPreviousNames field
  7184. //
  7185. if ( !pIniDriver &&
  7186. !wcscmp(pIniEnvironment->pName, szWin95Environment) &&
  7187. (psz = pSpool->pIniPrinter->pIniDriver->pszzPreviousNames) ) {
  7188. for ( ; !pIniDriver && *psz ; psz += wcslen(psz) + 1 )
  7189. pIniDriver = FindCompatibleDriver(pIniEnvironment,
  7190. &pIniVersion,
  7191. psz,
  7192. 0,
  7193. FIND_COMPATIBLE_VERSION | DRIVER_SEARCH);
  7194. if ( !pIniDriver && Level == 1 ) {
  7195. //
  7196. // SMB code calls GetPrinterDriver level 1 to findout which
  7197. // driver name to send to Win9x client in GetPrinter info
  7198. // If we do not have Win9x printer driver installed and previous
  7199. // names field is not NULL our best guess is the first one in
  7200. // the pszzPreviousNames. This is expected to be the popular
  7201. // driver on Win9x. If client already has the driver they can
  7202. // print
  7203. //
  7204. psz = pSpool->pIniPrinter->pIniDriver->pszzPreviousNames;
  7205. *pcbNeeded = ( wcslen(psz) + 1 ) * sizeof(WCHAR)
  7206. + sizeof(DRIVER_INFO_1);
  7207. if ( *pcbNeeded > cbBuf ) {
  7208. LeaveSplSem();
  7209. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  7210. return FALSE;
  7211. }
  7212. ((LPDRIVER_INFO_1)pDriverInfo)->pName
  7213. = (LPWSTR)(pDriverInfo + sizeof(DRIVER_INFO_1));
  7214. wcscpy(((LPDRIVER_INFO_1)pDriverInfo)->pName, psz);
  7215. LeaveSplSem();
  7216. return TRUE;
  7217. }
  7218. }
  7219. if ( !pIniDriver ) {
  7220. LeaveSplSem();
  7221. return FALSE;
  7222. }
  7223. } else {
  7224. pIniDriver = pSpool->pIniPrinter->pIniDriver;
  7225. pIniVersion = FindVersionForDriver(pIniEnvironment, pIniDriver);
  7226. }
  7227. cb = GetDriverInfoSize( pIniDriver, Level, pIniVersion,pIniEnvironment,
  7228. pSpool->TypeofHandle & PRINTER_HANDLE_REMOTE_CALL ?
  7229. pSpool->pFullMachineName : NULL,
  7230. pSpool->pIniSpooler );
  7231. *pcbNeeded=cb;
  7232. if (cb > cbBuf) {
  7233. LeaveSplSem();
  7234. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  7235. return FALSE;
  7236. }
  7237. pEnd = pDriverInfo+cbBuf;
  7238. if (!CopyIniDriverToDriverInfo(pIniEnvironment, pIniVersion, pIniDriver,
  7239. Level, pDriverInfo, pEnd,
  7240. pSpool->TypeofHandle & PRINTER_HANDLE_REMOTE_CALL ?
  7241. pSpool->pFullMachineName : NULL,
  7242. pIniSpooler)) {
  7243. LeaveSplSem();
  7244. SetLastError(ERROR_OUTOFMEMORY);
  7245. return FALSE;
  7246. }
  7247. LeaveSplSem();
  7248. return TRUE;
  7249. }
  7250. PINIVERSION
  7251. FindCompatibleVersion(
  7252. PINIENVIRONMENT pIniEnvironment,
  7253. DWORD dwMajorVersion,
  7254. int FindAnyVersion
  7255. )
  7256. {
  7257. PINIVERSION pIniVersion;
  7258. if (!pIniEnvironment) {
  7259. return NULL;
  7260. }
  7261. for ( pIniVersion = pIniEnvironment->pIniVersion;
  7262. pIniVersion != NULL;
  7263. pIniVersion = pIniVersion->pNext ) {
  7264. if ( (FindAnyVersion & DRIVER_UPGRADE) ?
  7265. (pIniVersion->cMajorVersion >= dwMajorVersion) :
  7266. (pIniVersion->cMajorVersion <= dwMajorVersion))
  7267. {
  7268. //
  7269. // Pre version 2 is not comparable with version 2 or newer
  7270. //
  7271. if ( dwMajorVersion >= 2 &&
  7272. pIniVersion->cMajorVersion < 2 &&
  7273. ((FindAnyVersion & FIND_ANY_VERSION)==FIND_COMPATIBLE_VERSION) &&
  7274. lstrcmpi(pIniEnvironment->pName, szWin95Environment) ) {
  7275. return NULL;
  7276. }
  7277. return pIniVersion;
  7278. }
  7279. }
  7280. return NULL;
  7281. }
  7282. PINIDRIVER
  7283. FindCompatibleDriver(
  7284. PINIENVIRONMENT pIniEnvironment,
  7285. PINIVERSION * ppIniVersion,
  7286. LPWSTR pDriverName,
  7287. DWORD dwMajorVersion,
  7288. int FindAnyDriver
  7289. )
  7290. {
  7291. PINIVERSION pIniVersion;
  7292. PINIDRIVER pIniDriver = NULL;
  7293. try {
  7294. *ppIniVersion = NULL;
  7295. if (!pIniEnvironment) {
  7296. leave;
  7297. }
  7298. pIniVersion = FindCompatibleVersion( pIniEnvironment, dwMajorVersion, FindAnyDriver );
  7299. if ( pIniVersion == NULL) {
  7300. leave;
  7301. }
  7302. while (pIniVersion){
  7303. //
  7304. // Pre version 2 is not comparable with version 2 or newer
  7305. //
  7306. if ( dwMajorVersion >= 2 &&
  7307. ((FindAnyDriver & FIND_ANY_VERSION) == FIND_COMPATIBLE_VERSION) &&
  7308. pIniVersion->cMajorVersion < 2 ) {
  7309. break;
  7310. }
  7311. if ( pIniDriver = FindDriverEntry( pIniVersion, pDriverName ) ) {
  7312. *ppIniVersion = pIniVersion;
  7313. leave; // Success
  7314. }
  7315. pIniVersion = pIniVersion->pNext;
  7316. }
  7317. } finally {
  7318. if ( pIniDriver == NULL ) {
  7319. SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
  7320. }
  7321. }
  7322. return pIniDriver;
  7323. }
  7324. VOID
  7325. InsertVersionList(
  7326. PINIVERSION* ppIniVersionHead,
  7327. PINIVERSION pIniVersion
  7328. )
  7329. /*++
  7330. Routine Description:
  7331. Insert a version entry into the verions linked list.
  7332. Versions are stored in decending order (2, 1, 0) so that
  7333. when a version is needed, we get the highest first.
  7334. Arguments:
  7335. ppIniVersionHead - Pointer to the head of the pIniVersion head.
  7336. pIniVersion - Version structure we want to add.
  7337. Return Value:
  7338. --*/
  7339. {
  7340. SplInSem();
  7341. //
  7342. // Insert into single-linked list code. We take the address of
  7343. // the head pointer so that we can avoid special casing the
  7344. // insert into empty list case.
  7345. //
  7346. for( ; *ppIniVersionHead; ppIniVersionHead = &(*ppIniVersionHead)->pNext ){
  7347. //
  7348. // If the major version of the pIniVersion we're inserting
  7349. // is > the next pIniVersion on the list, insert it before
  7350. // that one.
  7351. //
  7352. // 4 3 2 1
  7353. // ^
  7354. // New '3' gets inserted here. (Note: duplicate versions should
  7355. // never be added.)
  7356. //
  7357. if( pIniVersion->cMajorVersion > (*ppIniVersionHead)->cMajorVersion ){
  7358. break;
  7359. }
  7360. }
  7361. //
  7362. // Link up the new version.
  7363. //
  7364. pIniVersion->pNext = *ppIniVersionHead;
  7365. *ppIniVersionHead = pIniVersion;
  7366. }
  7367. PINIDRIVER
  7368. FindDriverEntry(
  7369. PINIVERSION pIniVersion,
  7370. LPWSTR pszName
  7371. )
  7372. {
  7373. PINIDRIVER pIniDriver;
  7374. if (!pIniVersion) {
  7375. return NULL;
  7376. }
  7377. if (!pszName || !*pszName) {
  7378. DBGMSG( DBG_WARNING, ("Passing a Null Printer Driver Name to FindDriverEntry\n"));
  7379. return NULL;
  7380. }
  7381. pIniDriver = pIniVersion->pIniDriver;
  7382. //
  7383. // Only return the driver if it is not pending deletion.
  7384. //
  7385. while (pIniDriver) {
  7386. if (!lstrcmpi(pIniDriver->pName, pszName) &&
  7387. !(pIniDriver->dwDriverFlags & PRINTER_DRIVER_PENDING_DELETION)) {
  7388. return pIniDriver;
  7389. }
  7390. pIniDriver = pIniDriver->pNext;
  7391. }
  7392. return NULL;
  7393. }
  7394. VOID
  7395. DeleteDriverEntry(
  7396. PINIVERSION pIniVersion,
  7397. PINIDRIVER pIniDriver
  7398. )
  7399. { PINIDRIVER pPrev, pCurrent;
  7400. if (!pIniVersion) {
  7401. return;
  7402. }
  7403. if (!pIniVersion->pIniDriver) {
  7404. return;
  7405. }
  7406. pPrev = pCurrent = NULL;
  7407. pCurrent = pIniVersion->pIniDriver;
  7408. while (pCurrent) {
  7409. if (pCurrent == pIniDriver) {
  7410. if (pPrev == NULL) {
  7411. pIniVersion->pIniDriver = pCurrent->pNext;
  7412. } else{
  7413. pPrev->pNext = pCurrent->pNext;
  7414. }
  7415. //
  7416. // Free all the entries in the entry
  7417. //
  7418. FreeStructurePointers((LPBYTE) pIniDriver, NULL, IniDriverOffsets);
  7419. FreeSplMem(pIniDriver);
  7420. return;
  7421. }
  7422. pPrev = pCurrent;
  7423. pCurrent = pCurrent->pNext;
  7424. }
  7425. return;
  7426. }
  7427. BOOL CheckFileCopy(
  7428. PINIVERSION pIniVersion,
  7429. LPWSTR pTargetFile,
  7430. LPWSTR pSourceFile,
  7431. PWIN32_FIND_DATA pSourceData,
  7432. DWORD dwSourceVersion,
  7433. DWORD dwFileCopyFlags,
  7434. LPBOOL pbCopyFile,
  7435. LPBOOL pbTargetExists)
  7436. /*++
  7437. Function Description: This functions determines if the target exists and if it should
  7438. be overwritten.
  7439. Parameters:
  7440. Return Values: TRUE if successful; FALSE otherwise.
  7441. --*/
  7442. {
  7443. WIN32_FIND_DATA DestFileData, SourceFileData, *pSourceFileData;
  7444. HANDLE hFileExists;
  7445. BOOL bReturn = FALSE, bSourceFileHandleCreated = FALSE;
  7446. DWORD dwTargetVersion = 0;
  7447. LeaveSplSem();
  7448. *pbCopyFile = *pbTargetExists = FALSE;
  7449. pSourceFileData = pSourceData ? pSourceData : &SourceFileData;
  7450. // Get Source File Date & Time Stamp
  7451. hFileExists = FindFirstFile( pSourceFile, pSourceFileData );
  7452. if (hFileExists == INVALID_HANDLE_VALUE) {
  7453. goto CleanUp;
  7454. }
  7455. FindClose( hFileExists );
  7456. // Get Target File Date Time
  7457. hFileExists = FindFirstFile( pTargetFile, &DestFileData );
  7458. if (hFileExists == INVALID_HANDLE_VALUE) {
  7459. if (GetLastError() == ERROR_FILE_NOT_FOUND) {
  7460. // Copy the source since there is no target
  7461. *pbCopyFile = TRUE;
  7462. bReturn = TRUE;
  7463. }
  7464. goto CleanUp;
  7465. }
  7466. *pbTargetExists = TRUE;
  7467. FindClose(hFileExists);
  7468. //
  7469. // Check Source File version and LastWrite Times vs Target File if only new files
  7470. // are to be copied
  7471. //
  7472. if (dwFileCopyFlags == APD_COPY_NEW_FILES) {
  7473. EnterSplSem();
  7474. bReturn = GetDriverFileCachedVersion (pIniVersion, pTargetFile, &dwTargetVersion);
  7475. LeaveSplSem();
  7476. if(!bReturn) {
  7477. goto CleanUp;
  7478. }
  7479. if (dwSourceVersion > dwTargetVersion) {
  7480. *pbCopyFile = TRUE;
  7481. } else {
  7482. if (dwSourceVersion == dwTargetVersion) {
  7483. if(CompareFileTime(&(pSourceFileData->ftLastWriteTime),
  7484. &DestFileData.ftLastWriteTime)
  7485. != FIRST_FILE_TIME_GREATER_THAN_SECOND) {
  7486. // Target File is up to date Nothing to do.
  7487. DBGMSG( DBG_TRACE, ("UpdateFile Target file is up to date\n"));
  7488. } else {
  7489. *pbCopyFile = TRUE;
  7490. }
  7491. }
  7492. }
  7493. } else {
  7494. *pbCopyFile = TRUE;
  7495. }
  7496. bReturn = TRUE;
  7497. CleanUp:
  7498. EnterSplSem();
  7499. return bReturn;
  7500. }
  7501. BOOL
  7502. UpdateFile(
  7503. PINIVERSION pIniVersion,
  7504. HANDLE hSourceFile,
  7505. LPWSTR pSourceFile,
  7506. DWORD dwVersion,
  7507. LPWSTR pDestDir,
  7508. DWORD dwFileCopyFlags,
  7509. BOOL bImpersonateOnCreate,
  7510. LPBOOL pbFileUpdated,
  7511. LPBOOL pbFileMoved,
  7512. BOOL bSameEnvironment,
  7513. BOOL bWin95Environment
  7514. )
  7515. /*++
  7516. Function Description: The file times are checked to verify if the file needs to be copied.
  7517. If the file already exists in the version directory, then it is copied
  7518. into ...\environment\version\new. The corresponding file, which is
  7519. present in environment\version, is copied to \version\old. The new file
  7520. is marked for move on REBOOT.
  7521. New files are copied into env\version.
  7522. Parameters: hSourceFile -- file handle
  7523. pSourceFile -- file name
  7524. pDestDir -- driver directory (e.g system32\spool\w32x86\3)
  7525. bImpersonateOnCreate -- flag to impersonate client on any file creation
  7526. pbFilesUpdated -- Have any new files been copied or moved ?
  7527. pbFileMoved -- Have any old files been moved ?
  7528. bSameEnvironment -- flag to indicate if the machine env == driver env
  7529. bWin95Environment -- flag to indicate if the driver env == win95
  7530. Return Values: TRUE if successful; FALSE otherwise
  7531. --*/
  7532. {
  7533. HANDLE hToken = INVALID_HANDLE_VALUE;
  7534. WCHAR szTargetFile[MAX_PATH], szNewFile[MAX_PATH];
  7535. LPWSTR pFileName;
  7536. BOOL bReturn = FALSE, bCopyFile, bTargetExists;
  7537. DWORD FileAttrib;
  7538. WIN32_FIND_DATA SourceFileData;
  7539. *pbFileMoved = FALSE;
  7540. pFileName = wcsrchr(pSourceFile, L'\\');
  7541. if (!pFileName || !pDestDir || !*pDestDir) {
  7542. // Wrong file name
  7543. SetLastError(ERROR_INVALID_PARAMETER);
  7544. goto CleanUp;
  7545. }
  7546. // Set the target directory
  7547. if(StrNCatBuff(szTargetFile,
  7548. COUNTOF(szTargetFile),
  7549. pDestDir,
  7550. NULL) != ERROR_SUCCESS)
  7551. {
  7552. goto CleanUp;
  7553. }
  7554. if (bWin95Environment && IsAnICMFile(pSourceFile)) {
  7555. if((StrNCatBuff(szTargetFile,
  7556. COUNTOF(szTargetFile),
  7557. szTargetFile,
  7558. L"\\Color",
  7559. NULL)!=ERROR_SUCCESS))
  7560. {
  7561. goto CleanUp;
  7562. }
  7563. }
  7564. if((StrNCatBuff(szTargetFile,
  7565. COUNTOF(szTargetFile),
  7566. szTargetFile,
  7567. pFileName,
  7568. NULL)!=ERROR_SUCCESS))
  7569. {
  7570. goto CleanUp;
  7571. }
  7572. // Check if the file has to be copied
  7573. if (!CheckFileCopy(pIniVersion, szTargetFile, pSourceFile, &SourceFileData, dwVersion,
  7574. dwFileCopyFlags, &bCopyFile, &bTargetExists)) {
  7575. goto CleanUp;
  7576. }
  7577. if (bCopyFile) {
  7578. if (!bImpersonateOnCreate) {
  7579. hToken = RevertToPrinterSelf();
  7580. }
  7581. if((StrNCatBuff(szNewFile,
  7582. COUNTOF(szNewFile),
  7583. pDestDir,
  7584. L"\\New",
  7585. pFileName,
  7586. NULL)!=ERROR_SUCCESS))
  7587. {
  7588. goto CleanUp;
  7589. }
  7590. // Leave semaphore for copying the files
  7591. LeaveSplSem();
  7592. if (!InternalCopyFile(hSourceFile, &SourceFileData,
  7593. szNewFile, OVERWRITE_IF_TARGET_EXISTS)) {
  7594. // InternalCopyFile failed
  7595. EnterSplSem();
  7596. goto CleanUp;
  7597. }
  7598. EnterSplSem();
  7599. } else {
  7600. *pbFileMoved = TRUE;
  7601. bReturn = TRUE;
  7602. goto CleanUp;
  7603. }
  7604. if (bCopyFile) {
  7605. if (!bSameEnvironment) {
  7606. if (bTargetExists) {
  7607. DWORD dwAttr;
  7608. dwAttr = GetFileAttributes(szTargetFile);
  7609. //
  7610. // Check if the function succeeded and the target file is write protected.
  7611. // Some non native drivers, notably Win 9x drivers, can be copied over to
  7612. // the drivers directory and have the read only attribute. When we update
  7613. // a non native driver, we want to make sure that it is not write protected.
  7614. //
  7615. if (dwAttr != (DWORD)-1 &&
  7616. dwAttr & FILE_ATTRIBUTE_READONLY) {
  7617. SetFileAttributes(szTargetFile, dwAttr & ~FILE_ATTRIBUTE_READONLY);
  7618. }
  7619. }
  7620. if (!SplMoveFileEx(szNewFile, szTargetFile, MOVEFILE_REPLACE_EXISTING)) {
  7621. // MoveFile failed
  7622. goto CleanUp;
  7623. }
  7624. } else {
  7625. if (bTargetExists) {
  7626. // Move the file on REBOOT. It may get moved earlier if the driver
  7627. // can be unloaded.
  7628. if (SplMoveFileEx(szNewFile, szTargetFile, MOVEFILE_DELAY_UNTIL_REBOOT)) {
  7629. *pbFileMoved = TRUE;
  7630. //
  7631. // Don't fail the call here. MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOOT will just write the registry.
  7632. // We'll need this only if the driver is still loaded, which we find out only later.
  7633. // If the driver is not loaded, we'll actually move these files later and this call won't make sense.
  7634. // So,don't fail the api call at this point because MoveFileEx. Hopefully, one day MoveFileEx won't
  7635. // be hard-coded to write only two PendingFileRenameOperations values.
  7636. //
  7637. }
  7638. } else {
  7639. if (!SplMoveFileEx(szNewFile, szTargetFile, MOVEFILE_REPLACE_EXISTING)) {
  7640. // MoveFile failed
  7641. goto CleanUp;
  7642. }
  7643. *pbFileMoved = TRUE;
  7644. }
  7645. }
  7646. *pbFileUpdated = TRUE;
  7647. }
  7648. bReturn = TRUE;
  7649. CleanUp:
  7650. if (hToken != INVALID_HANDLE_VALUE) {
  7651. ImpersonatePrinterClient(hToken);
  7652. }
  7653. return bReturn;
  7654. }
  7655. BOOL
  7656. CopyAllFilesAndDeleteOldOnes(
  7657. PINIVERSION pIniVersion,
  7658. PINTERNAL_DRV_FILE pInternalDriverFiles,
  7659. DWORD dwFileCount,
  7660. LPWSTR pDestDir,
  7661. DWORD dwFileCopyFlags,
  7662. BOOL bImpersonateOnCreate,
  7663. LPBOOL pbFileMoved,
  7664. BOOL bSameEnvironment,
  7665. BOOL bWin95Environment
  7666. )
  7667. /*++
  7668. Function Description: This function loops thru all the files in the driver_info
  7669. struct and calls an update routine.
  7670. Parameters: pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  7671. dwFileCount -- number of files in file set
  7672. pDestDir -- driver directory (e.g system32\spool\w32x86\3)
  7673. bImpersonateOnCreate -- flag to impersonate client on any file creation
  7674. pbFileMoved -- Have any old files been moved ?
  7675. bSameEnvironment -- flag to indicate if the machine env == driver env
  7676. bWin95Environment -- flag to indicate if the driver env == win95
  7677. Return Values: TRUE if successful; FALSE otherwise
  7678. --*/
  7679. {
  7680. BOOL bRet = TRUE;
  7681. DWORD dwCount;
  7682. BOOL bFilesUpdated;
  7683. BOOL bFilesMoved = TRUE;
  7684. *pbFileMoved = TRUE;
  7685. for (dwCount = 0 ; dwCount < dwFileCount ; ++dwCount) {
  7686. bFilesUpdated = FALSE;
  7687. if (!(bRet = UpdateFile(pIniVersion,
  7688. pInternalDriverFiles[dwCount].hFileHandle,
  7689. pInternalDriverFiles[dwCount].pFileName,
  7690. pInternalDriverFiles[dwCount].dwVersion,
  7691. pDestDir,
  7692. dwFileCopyFlags,
  7693. bImpersonateOnCreate,
  7694. &bFilesUpdated,
  7695. &bFilesMoved,
  7696. bSameEnvironment,
  7697. bWin95Environment))) {
  7698. // Files could not be copied correctly
  7699. break;
  7700. }
  7701. if (bFilesUpdated) {
  7702. pInternalDriverFiles[dwCount].bUpdated = TRUE;
  7703. }
  7704. if(!bFilesMoved) {
  7705. *pbFileMoved = FALSE;
  7706. }
  7707. }
  7708. return bRet;
  7709. }
  7710. BOOL
  7711. CopyFilesToFinalDirectory(
  7712. PINISPOOLER pIniSpooler,
  7713. PINIENVIRONMENT pIniEnvironment,
  7714. PINIVERSION pIniVersion,
  7715. PINTERNAL_DRV_FILE pInternalDriverFiles,
  7716. DWORD dwFileCount,
  7717. DWORD dwFileCopyFlags,
  7718. BOOL bImpersonateOnCreate,
  7719. LPBOOL pbFilesMoved
  7720. )
  7721. /*++
  7722. Function Description: This function copies all the new files into the the correct
  7723. directory i.e ...\environment\version.
  7724. The files which already exist in the version directory are copied
  7725. in ...\environment\version\new. The corresponding files, which are
  7726. present in environment\version, are copied to \version\old.
  7727. The common files are upgraded when the old files can be unloaded
  7728. from either the kernel (for KMPD) or the spooler (for UMPD)
  7729. Parameters: pIniSpooler -- pointer to the INISPOOLER struct
  7730. pIniEnvironment -- pointer to the driver environment struct
  7731. pIniVersion -- pointer to the driver version struct
  7732. pInternalDriverFiles -- array of INTERNAL_DRV_FILE structures
  7733. dwFileCount -- number of files in file setes
  7734. dwFileCount -- number of files
  7735. bImpersonateOnCreate -- flag to impersonate client on any file creation
  7736. pbFileMoved -- Have any old files been moved ?
  7737. Return Values: TRUE if successful; FALSE otherwise
  7738. --*/
  7739. {
  7740. WCHAR szDestDir[INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH + 1];
  7741. LPWSTR pStringEnd = NULL;
  7742. DWORD dwIndex;
  7743. BOOL bRet = FALSE, bSameEnvironment, bWin95Environment;
  7744. //
  7745. // Initialize szDestDir to an empty string. This is to due a bogus prefix
  7746. // bug. In practice GetEnvironment scratch directory cannot fail under
  7747. // these conditions.
  7748. //
  7749. szDestDir[0] = L'\0';
  7750. SplInSem();
  7751. GetEnvironmentScratchDirectory( szDestDir, MAX_PATH, pIniEnvironment, FALSE );
  7752. wcscat( szDestDir, L"\\" );
  7753. wcscat( szDestDir, pIniVersion->szDirectory );
  7754. // pStringEnd points to the NULL character in szDestDir
  7755. pStringEnd = (LPWSTR) szDestDir + wcslen(szDestDir);
  7756. bSameEnvironment = !lstrcmpi(pIniEnvironment->pName, szEnvironment);
  7757. // Create the Old directory
  7758. wcscat(szDestDir, L"\\Old");
  7759. if (!DirectoryExists(szDestDir) &&
  7760. !CreateDirectoryWithoutImpersonatingUser(szDestDir)) {
  7761. // Failed to create Old directory
  7762. goto CleanUp;
  7763. }
  7764. *pStringEnd = L'\0';
  7765. // Create the New Directory
  7766. wcscat(szDestDir, L"\\New");
  7767. if (!DirectoryExists(szDestDir) &&
  7768. !CreateDirectoryWithoutImpersonatingUser(szDestDir)) {
  7769. // Failed to create New directory
  7770. goto CleanUp;
  7771. }
  7772. *pStringEnd = L'\0';
  7773. // Create the Color Directory if necessary
  7774. if (!wcscmp(pIniEnvironment->pName, szWin95Environment)) {
  7775. for (dwIndex = 0 ; dwIndex < dwFileCount ; ++dwIndex) {
  7776. // Search for ICM files that need the Color directory
  7777. if (IsAnICMFile(pInternalDriverFiles[dwIndex].pFileName)) {
  7778. // Create the Color Directory
  7779. wcscat(szDestDir, L"\\Color");
  7780. if (!DirectoryExists(szDestDir) &&
  7781. !CreateDirectoryWithoutImpersonatingUser(szDestDir)) {
  7782. // Failed to create Color directory
  7783. goto CleanUp;
  7784. }
  7785. *pStringEnd = L'\0';
  7786. break;
  7787. }
  7788. }
  7789. bWin95Environment = TRUE;
  7790. } else {
  7791. bWin95Environment = FALSE;
  7792. }
  7793. DBGMSG(DBG_CLUSTER, ("CopyFilesToFinalDirectory szDestDir "TSTR"\n", szDestDir));
  7794. bRet = CopyAllFilesAndDeleteOldOnes(pIniVersion,
  7795. pInternalDriverFiles,
  7796. dwFileCount,
  7797. szDestDir,
  7798. dwFileCopyFlags,
  7799. bImpersonateOnCreate,
  7800. pbFilesMoved,
  7801. bSameEnvironment,
  7802. bWin95Environment);
  7803. CleanUp:
  7804. if (!bRet) {
  7805. SPLASSERT( GetLastError() != ERROR_SUCCESS );
  7806. }
  7807. return bRet;
  7808. }
  7809. DWORD
  7810. GetDriverVersionDirectory(
  7811. LPWSTR pDir,
  7812. DWORD MaxLength,
  7813. PINISPOOLER pIniSpooler,
  7814. PINIENVIRONMENT pIniEnvironment,
  7815. PINIVERSION pIniVersion,
  7816. PINIDRIVER pIniDriver,
  7817. LPWSTR lpRemote
  7818. )
  7819. {
  7820. WCHAR pTempDir[MAX_PATH];
  7821. if (lpRemote) {
  7822. if( StrNCatBuff(pDir,
  7823. MaxLength,
  7824. lpRemote,
  7825. L"\\",
  7826. pIniSpooler->pszDriversShare,
  7827. L"\\",
  7828. pIniEnvironment->pDirectory,
  7829. L"\\",
  7830. pIniVersion->szDirectory,
  7831. NULL) != ERROR_SUCCESS ) {
  7832. return 0;
  7833. }
  7834. } else {
  7835. if( StrNCatBuff(pDir,
  7836. MaxLength,
  7837. pIniSpooler->pDir,
  7838. L"\\",
  7839. szDriverDir,
  7840. L"\\",
  7841. pIniEnvironment->pDirectory,
  7842. L"\\",
  7843. pIniVersion->szDirectory,
  7844. NULL) != ERROR_SUCCESS ) {
  7845. return 0;
  7846. }
  7847. }
  7848. if (pIniDriver && pIniDriver->dwTempDir) {
  7849. wsprintf(pTempDir, L"%d", pIniDriver->dwTempDir);
  7850. if( StrNCatBuff(pDir,
  7851. MaxLength,
  7852. pDir,
  7853. L"\\",
  7854. pTempDir,
  7855. NULL) != ERROR_SUCCESS ) {
  7856. return 0;
  7857. }
  7858. }
  7859. return wcslen(pDir);
  7860. }
  7861. PINIVERSION
  7862. FindVersionForDriver(
  7863. PINIENVIRONMENT pIniEnvironment,
  7864. PINIDRIVER pIniDriver
  7865. )
  7866. {
  7867. PINIVERSION pIniVersion;
  7868. PINIDRIVER pIniVerDriver;
  7869. pIniVersion = pIniEnvironment->pIniVersion;
  7870. while (pIniVersion) {
  7871. pIniVerDriver = pIniVersion->pIniDriver;
  7872. while (pIniVerDriver) {
  7873. if ( pIniVerDriver == pIniDriver ) {
  7874. return pIniVersion;
  7875. }
  7876. pIniVerDriver = pIniVerDriver->pNext;
  7877. }
  7878. pIniVersion = pIniVersion->pNext;
  7879. }
  7880. return NULL;
  7881. }
  7882. LPWSTR
  7883. GetFileNameInScratchDir(
  7884. LPWSTR pPathName,
  7885. PINIENVIRONMENT pIniEnvironment
  7886. )
  7887. {
  7888. WCHAR szDir[INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH + 1];
  7889. LPCWSTR pszFileName;
  7890. LPWSTR pszReturn = NULL;
  7891. //
  7892. // Initialize the szDir to a known string value. This was a bogus prefix bug,
  7893. // but, it is probably a good idea anyway.
  7894. //
  7895. szDir[0] = L'\0';
  7896. if ((pszFileName = FindFileName(pPathName)) &&
  7897. wcslen(pszFileName) < MAX_PATH &&
  7898. GetEnvironmentScratchDirectory(szDir, (DWORD)(COUNTOF(szDir) - wcslen(pszFileName) - 2), pIniEnvironment, FALSE))
  7899. {
  7900. wcscat(szDir, L"\\");
  7901. wcscat(szDir, pszFileName);
  7902. pszReturn = AllocSplStr(szDir);
  7903. }
  7904. return pszReturn;
  7905. }
  7906. BOOL
  7907. CreateInternalDriverFileArray(
  7908. DWORD Level,
  7909. LPBYTE pDriverInfo,
  7910. INTERNAL_DRV_FILE **ppInternalDriverFiles,
  7911. LPDWORD pFileCount,
  7912. BOOL bUseScratchDir,
  7913. PINIENVIRONMENT pIniEnvironment,
  7914. BOOL bFileNamesOnly
  7915. )
  7916. /*++
  7917. Routine Description:
  7918. Creates the array of INTERNAL_DRV_FILE structures.
  7919. For each file in file set, we build an array with information
  7920. about the file: file name, driver minor version, file handle,
  7921. if the file was updated.
  7922. The field regrading updating is initialized to FALSE and modified later.
  7923. Arguments:
  7924. Level : level of driver info structure
  7925. pDriverInfo : pointer to driver info structure
  7926. pInternalDriverFiles : allocate memory to this array for list of file names
  7927. pFileCount : will point to number of files on return
  7928. bUseScratchDir : Should a scratch directory be used for file names
  7929. pIniEnvironment : environment the version belongs to
  7930. Return Value:
  7931. TRUE = success
  7932. *ppInternalDriverFiles will (routine allocates memory) give
  7933. the internal list of files
  7934. *pFileCount will give number of files specified by the driver info
  7935. FALSE = failure, call GetLastError()
  7936. History:
  7937. Written by MuhuntS (Muhunthan Sivapragasam) June 95
  7938. --*/
  7939. {
  7940. LPWSTR pStr;
  7941. DWORD dDepFileCount = 0, dFirstDepFileIndex, Count, Size;
  7942. BOOL bReturnValue = TRUE, bInSplSem = TRUE;
  7943. PDRIVER_INFO_2 pDriverInfo2 = NULL;
  7944. PDRIVER_INFO_3 pDriverInfo3 = NULL;
  7945. PDRIVER_INFO_VERSION pDriverVersion = NULL;
  7946. LPWSTR pDependentFiles = NULL, pDependentFilestoFree = NULL;
  7947. LPWSTR pFileName = NULL;
  7948. SplInSem();
  7949. if ( !ppInternalDriverFiles || !pFileCount) {
  7950. bReturnValue = FALSE;
  7951. SetLastError(ERROR_INVALID_DATA);
  7952. goto End;
  7953. }
  7954. *pFileCount = 0;
  7955. *ppInternalDriverFiles = NULL;
  7956. switch (Level) {
  7957. case 2:
  7958. *pFileCount = 3;
  7959. pDriverInfo2 = (PDRIVER_INFO_2) pDriverInfo;
  7960. break;
  7961. case 3:
  7962. case 4:
  7963. case 6:
  7964. *pFileCount = 3;
  7965. dFirstDepFileIndex = 3;
  7966. pDriverInfo3 = (PDRIVER_INFO_3) pDriverInfo;
  7967. //
  7968. // For any environment other than Win95 we build dependent files
  7969. // without other DRIVER_INFO_3 files (i.e. ConfigFile etc)
  7970. //
  7971. if ( _wcsicmp(pIniEnvironment->pName, szWin95Environment) ) {
  7972. if ( !BuildTrueDependentFileField(pDriverInfo3->pDriverPath,
  7973. pDriverInfo3->pDataFile,
  7974. pDriverInfo3->pConfigFile,
  7975. pDriverInfo3->pHelpFile,
  7976. pDriverInfo3->pDependentFiles,
  7977. &pDependentFiles) ) {
  7978. bReturnValue = FALSE;
  7979. SetLastError(ERROR_INVALID_DATA);
  7980. pDependentFilestoFree = NULL;
  7981. goto End;
  7982. }
  7983. pDependentFilestoFree = pDependentFiles;
  7984. } else {
  7985. pDependentFiles = pDriverInfo3->pDependentFiles;
  7986. }
  7987. if ( pDriverInfo3->pHelpFile && *pDriverInfo3->pHelpFile ) {
  7988. if(wcslen(pDriverInfo3->pHelpFile) >= MAX_PATH) {
  7989. bReturnValue = FALSE;
  7990. SetLastError(ERROR_INVALID_DATA);
  7991. *pFileCount = 0;
  7992. goto End;
  7993. }
  7994. ++*pFileCount;
  7995. ++dFirstDepFileIndex;
  7996. }
  7997. for ( dDepFileCount = 0, pStr = pDependentFiles ;
  7998. pStr && *pStr ;
  7999. pStr += wcslen(pStr) + 1) {
  8000. if(wcslen(pStr) >= MAX_PATH) {
  8001. bReturnValue = FALSE;
  8002. SetLastError(ERROR_INVALID_DATA);
  8003. *pFileCount = 0;
  8004. goto End;
  8005. }
  8006. ++dDepFileCount;
  8007. }
  8008. *pFileCount += dDepFileCount;
  8009. break;
  8010. case DRIVER_INFO_VERSION_LEVEL:
  8011. pDriverVersion = (LPDRIVER_INFO_VERSION)pDriverInfo;
  8012. *pFileCount = pDriverVersion->dwFileCount;
  8013. break;
  8014. default:
  8015. bReturnValue = FALSE;
  8016. SetLastError(ERROR_INVALID_DATA);
  8017. goto End;
  8018. break;
  8019. }
  8020. try {
  8021. *ppInternalDriverFiles = (INTERNAL_DRV_FILE *) AllocSplMem(*pFileCount * sizeof(INTERNAL_DRV_FILE));
  8022. if ( !*ppInternalDriverFiles ) {
  8023. bReturnValue = FALSE;
  8024. leave;
  8025. }
  8026. for ( Count = 0; Count < *pFileCount; Count++ ) {
  8027. (*ppInternalDriverFiles)[Count].pFileName = NULL;
  8028. (*ppInternalDriverFiles)[Count].hFileHandle = INVALID_HANDLE_VALUE;
  8029. (*ppInternalDriverFiles)[Count].dwVersion = 0;
  8030. (*ppInternalDriverFiles)[Count].bUpdated = FALSE;
  8031. }
  8032. switch (Level) {
  8033. case 2:
  8034. if ( bUseScratchDir ) {
  8035. (*ppInternalDriverFiles)[0].pFileName = GetFileNameInScratchDir(
  8036. pDriverInfo2->pDriverPath,
  8037. pIniEnvironment);
  8038. (*ppInternalDriverFiles)[1].pFileName = GetFileNameInScratchDir(
  8039. pDriverInfo2->pConfigFile,
  8040. pIniEnvironment);
  8041. (*ppInternalDriverFiles)[2].pFileName = GetFileNameInScratchDir(
  8042. pDriverInfo2->pDataFile,
  8043. pIniEnvironment);
  8044. } else {
  8045. (*ppInternalDriverFiles)[0].pFileName = AllocSplStr(pDriverInfo2->pDriverPath);
  8046. (*ppInternalDriverFiles)[1].pFileName = AllocSplStr(pDriverInfo2->pConfigFile);
  8047. (*ppInternalDriverFiles)[2].pFileName = AllocSplStr(pDriverInfo2->pDataFile);
  8048. }
  8049. break;
  8050. case 3:
  8051. case 4:
  8052. case 5:
  8053. case 6:
  8054. if ( bUseScratchDir ) {
  8055. (*ppInternalDriverFiles)[0].pFileName = GetFileNameInScratchDir(
  8056. pDriverInfo3->pDriverPath,
  8057. pIniEnvironment);
  8058. (*ppInternalDriverFiles)[1].pFileName = GetFileNameInScratchDir(
  8059. pDriverInfo3->pConfigFile,
  8060. pIniEnvironment);
  8061. (*ppInternalDriverFiles)[2].pFileName = GetFileNameInScratchDir(
  8062. pDriverInfo3->pDataFile,
  8063. pIniEnvironment);
  8064. if ( pDriverInfo3->pHelpFile && *pDriverInfo3->pHelpFile ) {
  8065. (*ppInternalDriverFiles)[3].pFileName = GetFileNameInScratchDir(
  8066. pDriverInfo3->pHelpFile,
  8067. pIniEnvironment);
  8068. }
  8069. } else {
  8070. (*ppInternalDriverFiles)[0].pFileName = AllocSplStr(pDriverInfo3->pDriverPath);
  8071. (*ppInternalDriverFiles)[1].pFileName = AllocSplStr(pDriverInfo3->pConfigFile);
  8072. (*ppInternalDriverFiles)[2].pFileName = AllocSplStr(pDriverInfo3->pDataFile);
  8073. if ( pDriverInfo3->pHelpFile && *pDriverInfo3->pHelpFile ) {
  8074. (*ppInternalDriverFiles)[3].pFileName = AllocSplStr(pDriverInfo3->pHelpFile);
  8075. }
  8076. }
  8077. if ( dDepFileCount ) {
  8078. for (pStr = pDependentFiles, Count = dFirstDepFileIndex;
  8079. *pStr ; pStr += wcslen(pStr) + 1) {
  8080. if ( bUseScratchDir ) {
  8081. (*ppInternalDriverFiles)[Count++].pFileName = GetFileNameInScratchDir(
  8082. pStr,
  8083. pIniEnvironment);
  8084. }
  8085. else {
  8086. (*ppInternalDriverFiles)[Count++].pFileName = AllocSplStr(pStr);
  8087. }
  8088. }
  8089. }
  8090. break;
  8091. case DRIVER_INFO_VERSION_LEVEL:
  8092. for ( Count = 0 ; Count < *pFileCount ; Count++ ) {
  8093. pFileName = MakePTR(pDriverVersion, pDriverVersion->pFileInfo[Count].FileNameOffset);
  8094. if ( bUseScratchDir ) {
  8095. (*ppInternalDriverFiles)[Count].pFileName = GetFileNameInScratchDir(
  8096. pFileName,
  8097. pIniEnvironment);
  8098. } else {
  8099. (*ppInternalDriverFiles)[Count].pFileName = AllocSplStr(pFileName);
  8100. }
  8101. }
  8102. break;
  8103. }
  8104. for ( Count = 0 ; Count < *pFileCount ; ) {
  8105. if ( !(*ppInternalDriverFiles)[Count++].pFileName ) {
  8106. DBGMSG( DBG_WARNING,
  8107. ("CreateInternalDriverFileArray failed to allocate memory %d\n",
  8108. GetLastError()) );
  8109. bReturnValue = FALSE;
  8110. leave;
  8111. }
  8112. }
  8113. if (bFileNamesOnly) {
  8114. leave;
  8115. }
  8116. //
  8117. // CreateFile may take a long time, if we are trying to copy files
  8118. // from a server and server crashed we want a deadlock to be
  8119. // detected during stress.
  8120. //
  8121. pIniEnvironment->cRef++;
  8122. LeaveSplSem();
  8123. SplOutSem();
  8124. bInSplSem = FALSE;
  8125. for ( Count = 0 ; Count < *pFileCount ; ++Count ) {
  8126. (*ppInternalDriverFiles)[Count].hFileHandle = CreateFile((*ppInternalDriverFiles)[Count].pFileName,
  8127. GENERIC_READ,
  8128. FILE_SHARE_READ,
  8129. NULL,
  8130. OPEN_EXISTING,
  8131. FILE_FLAG_SEQUENTIAL_SCAN,
  8132. NULL);
  8133. if ( (*ppInternalDriverFiles)[Count].hFileHandle == INVALID_HANDLE_VALUE ) {
  8134. DBGMSG( DBG_WARNING,
  8135. ("CreateFileNames failed to Open %ws %d\n",
  8136. (*ppInternalDriverFiles)[Count].pFileName, GetLastError()) );
  8137. bReturnValue = FALSE;
  8138. leave;
  8139. }
  8140. }
  8141. //
  8142. // Build the array of file versions.
  8143. // Stay out of Spooler CS since we might do a LoadLibrary over the network.
  8144. //
  8145. if (Level == DRIVER_INFO_VERSION_LEVEL) {
  8146. bReturnValue = GetDriverFileVersions((DRIVER_INFO_VERSION*)pDriverInfo,
  8147. *ppInternalDriverFiles,
  8148. *pFileCount);
  8149. } else {
  8150. bReturnValue = GetDriverFileVersionsFromNames(*ppInternalDriverFiles,
  8151. *pFileCount);
  8152. }
  8153. } finally {
  8154. if (!bReturnValue) {
  8155. CleanupInternalDriverInfo(*ppInternalDriverFiles, *pFileCount);
  8156. *pFileCount = 0;
  8157. *ppInternalDriverFiles = NULL;
  8158. }
  8159. }
  8160. FreeSplMem(pDependentFilestoFree);
  8161. End:
  8162. if ( !bInSplSem ) {
  8163. SplOutSem();
  8164. EnterSplSem();
  8165. SPLASSERT(pIniEnvironment->signature == IE_SIGNATURE);
  8166. pIniEnvironment->cRef--;
  8167. }
  8168. return bReturnValue;
  8169. }
  8170. DWORD
  8171. CopyFileToClusterDirectory (
  8172. IN PINISPOOLER pIniSpooler,
  8173. IN PINIENVIRONMENT pIniEnvironment,
  8174. IN PINIVERSION pIniVersion,
  8175. IN PINTERNAL_DRV_FILE pInternalDriverFiles,
  8176. IN DWORD FileCount
  8177. )
  8178. /*++
  8179. Routine Name:
  8180. CopyFileToClusterDirectory
  8181. Routine Description:
  8182. Copy the updated driver files on the cluster disk
  8183. Arguments:
  8184. pIniSpooler - Spooler
  8185. pIniEnvironment - Environment
  8186. pIniVersion - Version
  8187. pInternalDriverFiles - pointer to array of INTERNAL_DRV_FILE
  8188. FileCount - number of elemnts in array
  8189. Return Value:
  8190. Last error
  8191. --*/
  8192. {
  8193. DWORD uIndex;
  8194. DWORD LastError = ERROR_SUCCESS;
  8195. for (uIndex = 0;
  8196. uIndex < FileCount && LastError == ERROR_SUCCESS;
  8197. uIndex++)
  8198. {
  8199. //
  8200. // If the file was updated, it needs to go onto the cluster disk
  8201. //
  8202. if (pInternalDriverFiles[uIndex].bUpdated)
  8203. {
  8204. WCHAR szDir[MAX_PATH] = {0};
  8205. if ((LastError = StrNCatBuff(szDir,
  8206. MAX_PATH,
  8207. pIniSpooler->pszClusResDriveLetter,
  8208. L"\\",
  8209. szClusterDriverRoot,
  8210. NULL)) == ERROR_SUCCESS)
  8211. {
  8212. //
  8213. // Let's assume foo is an x86 version 3 driver and k: is the
  8214. // cluster drive letter. The file foo.dll will be copied to the
  8215. // K:\PrinterDrivers\W32x86\3\foo.dll. If foo.icm is an ICM file
  8216. // installed with a 9x driver, then it will be copied to
  8217. // K:\PrinterDrivers\WIN40\0\foo.icm. This is the design. We keep
  8218. // 9x ICM files in the Color subdirectory.
  8219. //
  8220. LastError = CopyFileToDirectory(pInternalDriverFiles[uIndex].pFileName,
  8221. szDir,
  8222. pIniEnvironment->pDirectory,
  8223. pIniVersion->szDirectory,
  8224. IsAnICMFile(pInternalDriverFiles[uIndex].pFileName) &&
  8225. !_wcsicmp(pIniEnvironment->pName, szWin95Environment) ? L"Color" : NULL);
  8226. }
  8227. }
  8228. }
  8229. return LastError;
  8230. }
  8231. /*++
  8232. Routine Name
  8233. LocalStartSystemRestorePoint
  8234. Routine Description:
  8235. This starts a system restore point, if we are on the right sku (PER or PRO).
  8236. Arguments:
  8237. pszDriverName - The name of the driver to install.
  8238. phRestorePoint - The restore point handle to be used in EndSystemRestorePoint.
  8239. Return Value:
  8240. TRUE - The system restore point was set, or it didn't have to be set.
  8241. FALSE - An error occurred, Last Error is set.
  8242. --*/
  8243. BOOL
  8244. LocalStartSystemRestorePoint(
  8245. IN PCWSTR pszDriverName,
  8246. OUT HANDLE *phRestorePoint
  8247. )
  8248. {
  8249. #ifndef _WIN64
  8250. BOOL bRet = FALSE;
  8251. OSVERSIONINFOEX osvi = { 0 };
  8252. HANDLE hRestorePoint = NULL;
  8253. DWORDLONG dwlConditionMask = 0;
  8254. osvi.dwOSVersionInfoSize = sizeof(osvi);
  8255. osvi.wProductType = VER_NT_WORKSTATION;
  8256. VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_LESS_EQUAL);
  8257. //
  8258. // We only do checkpointing on server and we don't do it for remote
  8259. // admin cases. We are invoked during upgrade before the SR client
  8260. // is installed, since it doesn't make sense to put in a restore
  8261. // point here anyway, also fail the call.
  8262. //
  8263. if (!dwUpgradeFlag &&
  8264. VerifyVersionInfo( &osvi,
  8265. VER_PRODUCT_TYPE,
  8266. dwlConditionMask) &&
  8267. IsLocalCall())
  8268. {
  8269. hRestorePoint = StartSystemRestorePoint( NULL,
  8270. pszDriverName,
  8271. hInst,
  8272. IDS_DRIVER_CHECKPOINT);
  8273. bRet = hRestorePoint != NULL;
  8274. }
  8275. else
  8276. {
  8277. //
  8278. // On SRV skus, we don't set system restore points, but that is OK.
  8279. //
  8280. bRet = TRUE;
  8281. }
  8282. *phRestorePoint = hRestorePoint;
  8283. return bRet;
  8284. #else
  8285. *phRestorePoint = NULL;
  8286. return TRUE;
  8287. #endif
  8288. }