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.

2238 lines
73 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. printupg.cxx
  6. Abstract:
  7. Code to implement printupg. Please refer to printupg.hxx for an overview
  8. of printupg feature set.
  9. Author:
  10. Larry Zhu (LZhu) 20-Feb-2001
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include "printupg.hxx"
  16. /*++
  17. Routine Name
  18. PSetupIsCompatibleDriver
  19. Routine Description:
  20. Check whether the driver is blocked or warned and if the driver is blocked
  21. or warned, return the blocking status and the replacement driver, if any.
  22. Arguments:
  23. pszServer - The server that needs to check for bad driver. If
  24. pszServer is NULL, that means the local machine
  25. pszDriverModel - The name of the driver to check
  26. pszDriverPath - The path of the driver, this can be a full path
  27. or the filename
  28. pszEnvironment - The environment of the server, such as
  29. "Windows NT x86"
  30. dwVersion - The major version of the driver
  31. pFileTimeDriver - The FileTime of the driver
  32. puBlockingStatus - Points to status of blocking
  33. ppszReplacementDriver - Points to the NULL terminating name of the replacement
  34. driver. A *NULL* string (instead of an empty string)
  35. means there is no replacement driver
  36. Return Value:
  37. A BOOL - TRUE if success; FALSE otherwise, Call GetLastError()
  38. to get the Error code. Pass a NULL to ppszReplacementDriver
  39. will not receive the name of replacement driver otherwise
  40. Call PSetupFreeMem to free the received string pointed by
  41. ppszReplacementDriver
  42. --*/
  43. BOOL
  44. PSetupIsCompatibleDriver(
  45. IN LPCTSTR pszServer, OPTIONAL
  46. IN LPCTSTR pszDriverModel,
  47. IN LPCTSTR pszDriverPath, // main rendering driver dll
  48. IN LPCTSTR pszEnvironment,
  49. IN DWORD dwVersion,
  50. IN FILETIME *pFileTimeDriver,
  51. OUT DWORD *pdwBlockingStatus,
  52. OUT LPTSTR *ppszReplacementDriver OPTIONAL // caller must free it.
  53. )
  54. {
  55. HRESULT hRetval = E_FAIL;
  56. UINT uBlockingStatus = 0;
  57. TString strReplacementDriver;
  58. hRetval = pszDriverModel && pszDriverPath && pszEnvironment && pFileTimeDriver && pdwBlockingStatus ? S_OK : E_INVALIDARG;
  59. if (SUCCEEDED(hRetval))
  60. {
  61. *pdwBlockingStatus = 0;
  62. if (ppszReplacementDriver)
  63. {
  64. *ppszReplacementDriver = NULL;
  65. }
  66. hRetval = IsLocalMachineServer();
  67. }
  68. if (SUCCEEDED(hRetval))
  69. {
  70. hRetval = InternalCompatibleDriverCheck(pszDriverModel,
  71. pszDriverPath,
  72. pszEnvironment,
  73. pFileTimeDriver,
  74. cszUpgradeInf,
  75. dwVersion,
  76. S_OK == hRetval ? TRUE : FALSE, // bIsServer
  77. &uBlockingStatus,
  78. &strReplacementDriver);
  79. }
  80. if (SUCCEEDED(hRetval))
  81. {
  82. *pdwBlockingStatus = uBlockingStatus;
  83. if ((BSP_PRINTER_DRIVER_OK != (*pdwBlockingStatus & BSP_BLOCKING_LEVEL_MASK)) && ppszReplacementDriver && !strReplacementDriver.bEmpty())
  84. {
  85. *ppszReplacementDriver = AllocStr(strReplacementDriver);
  86. hRetval = ppszReplacementDriver ? S_OK : E_OUTOFMEMORY;
  87. if (SUCCEEDED(hRetval))
  88. {
  89. *pdwBlockingStatus |= BSP_INBOX_DRIVER_AVAILABLE;
  90. }
  91. }
  92. }
  93. SetLastError(SUCCEEDED(hRetval) ? ERROR_SUCCESS : HRESULT_CODE(hRetval));
  94. return SUCCEEDED(hRetval);
  95. }
  96. /*++
  97. Routine Name:
  98. AddPrinterDriverUsingCorrectLevelWithPrintUpgRetry
  99. Routine Description:
  100. This routine tries to add the printer driver and it is blocked or
  101. warned, it popups a message box either indicates the driver is blocked
  102. and installation will abort or at the case of warned driver, whether
  103. to preceed the driver installation.
  104. Arguments:
  105. pszServer - The server that needs to check for bad driver. If
  106. pszServer is NULL, that means the local machine
  107. pDriverInfo6 - Points to DRINVER_INFO_6 structor
  108. dwAddDrvFlags - Flags used in AddPrinterDriver
  109. bIsDriverPathFullPath - Whether the driverpath is a full path
  110. bOfferReplacement - Whether to offer replacement
  111. bPopupUI - Whether to popup UI
  112. ppszReplacementDriver - Points to the replacement driver
  113. pdwBlockingStatus - Points to blocking status of the driver
  114. Return Value:
  115. An BOOL - GetLastError() on failure
  116. --*/
  117. BOOL
  118. AddPrinterDriverUsingCorrectLevelWithPrintUpgRetry(
  119. IN LPCTSTR pszServer, OPTIONAL
  120. IN DRIVER_INFO_6 *pDriverInfo6,
  121. IN DWORD dwAddDrvFlags,
  122. IN BOOL bIsDriverPathFullPath,
  123. IN BOOL bOfferReplacement,
  124. IN BOOL bPopupUI,
  125. OUT LPTSTR *ppszReplacementDriver,
  126. OUT DWORD *pdwBlockingStatus
  127. )
  128. {
  129. HRESULT hRetval = E_FAIL;
  130. DWORD dwLevel = 6;
  131. FILETIME DriverFileTime;
  132. hRetval = pDriverInfo6 && ppszReplacementDriver && pdwBlockingStatus ? S_OK : E_INVALIDARG;
  133. //
  134. // Set APD_NO_UI flag and call AddPrinterDriver.
  135. //
  136. if (SUCCEEDED(hRetval))
  137. {
  138. *pdwBlockingStatus = BSP_PRINTER_DRIVER_OK;
  139. *ppszReplacementDriver = NULL;
  140. dwAddDrvFlags |= APD_NO_UI;
  141. hRetval = AddPrinterDriverEx(const_cast<LPTSTR>(pszServer),
  142. dwLevel,
  143. reinterpret_cast<BYTE*>(pDriverInfo6),
  144. dwAddDrvFlags) ? ERROR_SUCCESS : GetLastErrorAsHResult();
  145. }
  146. for ( dwLevel = 4; (FAILED(hRetval) && (ERROR_INVALID_LEVEL == HRESULT_CODE(hRetval))) && (dwLevel > 1) ; --dwLevel ) {
  147. //
  148. // Since DRIVER_INFO_2, 3, 4 are subsets of DRIVER_INFO_6 and all fields
  149. // are at the beginning these calls can be made with same buffer
  150. //
  151. hRetval = AddPrinterDriverEx(const_cast<LPTSTR>(pszServer),
  152. dwLevel,
  153. reinterpret_cast<BYTE*>(pDriverInfo6),
  154. dwAddDrvFlags) ? S_OK : GetLastErrorAsHResult();
  155. }
  156. //
  157. // Set the blocking status information (either blocked or warned) from the
  158. // server.
  159. //
  160. // Show printupg ui and get the replacement driver from printupg.inf on
  161. // client and get user's response and retry AddPrinterDriver with level
  162. // dwLevel.
  163. //
  164. if (FAILED(hRetval) && bPopupUI && ((ERROR_PRINTER_DRIVER_BLOCKED == HRESULT_CODE(hRetval)) || (ERROR_PRINTER_DRIVER_WARNED == HRESULT_CODE(hRetval))))
  165. {
  166. *pdwBlockingStatus = (ERROR_PRINTER_DRIVER_BLOCKED == HRESULT_CODE(hRetval)) ? BSP_PRINTER_DRIVER_BLOCKED : BSP_PRINTER_DRIVER_WARNED;
  167. hRetval = PrintUpgRetry(pszServer,
  168. dwLevel,
  169. pDriverInfo6,
  170. dwAddDrvFlags,
  171. bIsDriverPathFullPath,
  172. bOfferReplacement,
  173. pdwBlockingStatus,
  174. ppszReplacementDriver);
  175. }
  176. SetLastError(SUCCEEDED(hRetval) ? ERROR_SUCCESS : HRESULT_CODE(hRetval));
  177. return SUCCEEDED(hRetval);
  178. }
  179. /*++
  180. Routine Name:
  181. BlockedDriverPrintUpgUI
  182. Routine Description:
  183. This routine checks the printupg.inf and see if the driver is there. If the
  184. driver is there, consider it blocked even if it is warned. Then it popups a
  185. message box either indicates the driver is blocked and ask whether the user
  186. wants to proceed to install a replacement driver it has one.
  187. Arguments:
  188. pszServer - The server that needs to check for bad driver. If
  189. pszServer is NULL, that means the local machine
  190. pDriverInfo6 - Points to DRINVER_INFO_6 structor
  191. bIsDriverPathFullPath - Whether the driverpath is a full path
  192. bOfferReplacement - Whether to offer replacement
  193. bPopupUI - Whether to popup UI
  194. ppszReplacementDriver - Points to the replacement driver
  195. pdwBlockingStatus - Points to blocking status of the driver
  196. Return Value:
  197. An BOOL - GetLastError() on failure
  198. --*/
  199. BOOL
  200. BlockedDriverPrintUpgUI(
  201. IN LPCTSTR pszServer, OPTIONAL
  202. IN DRIVER_INFO_6 *pDriverInfo6,
  203. IN BOOL bIsDriverPathFullPath,
  204. IN BOOL bOfferReplacement,
  205. IN BOOL bPopupUI,
  206. OUT LPTSTR *ppszReplacementDriver,
  207. OUT DWORD *pdwBlockingStatus
  208. )
  209. {
  210. HRESULT hRetval = E_FAIL;
  211. DWORD dwBlockingStatusOnClient = BSP_PRINTER_DRIVER_OK;
  212. hRetval = pDriverInfo6 && ppszReplacementDriver && pdwBlockingStatus ? S_OK : E_INVALIDARG;
  213. if (SUCCEEDED(hRetval))
  214. {
  215. *pdwBlockingStatus = BSP_PRINTER_DRIVER_OK;
  216. *ppszReplacementDriver = NULL;
  217. hRetval = IsDriverBadLocally(pszServer,
  218. pDriverInfo6,
  219. bIsDriverPathFullPath,
  220. &dwBlockingStatusOnClient,
  221. ppszReplacementDriver);
  222. //
  223. // Get the replacement driver information
  224. //
  225. if (SUCCEEDED(hRetval) && (BSP_PRINTER_DRIVER_OK != (dwBlockingStatusOnClient & BSP_BLOCKING_LEVEL_MASK)))
  226. {
  227. *pdwBlockingStatus |= (dwBlockingStatusOnClient & ~BSP_BLOCKING_LEVEL_MASK) | BSP_PRINTER_DRIVER_BLOCKED;
  228. }
  229. }
  230. if (SUCCEEDED(hRetval) && bPopupUI && (BSP_PRINTER_DRIVER_BLOCKED & *pdwBlockingStatus))
  231. {
  232. hRetval = PrintUpgRetry(pszServer,
  233. 6, // dwLevel, do not care in the case of blocked driver
  234. pDriverInfo6,
  235. 0, // dwAddDrvFlags, do not care in the case of blocked driver
  236. bIsDriverPathFullPath,
  237. bOfferReplacement,
  238. pdwBlockingStatus,
  239. ppszReplacementDriver);
  240. }
  241. SetLastError(SUCCEEDED(hRetval) ? ERROR_SUCCESS : HRESULT_CODE(hRetval));
  242. return SUCCEEDED(hRetval);
  243. }
  244. /*++
  245. Routine Name:
  246. PrintUpgRetry
  247. Routine Description:
  248. This routine popups up a message box either indicates the driver is blocked
  249. or warned and asks the user how to preceed. In the case of warned driver,
  250. whether to preceed the driver installation and retry AddPrinterDriver if
  251. the user wants to proceed with a warned driver.
  252. Arguments:
  253. pszServer - Remote machine that has the driver files
  254. dwLevel - Driver info level, since DRIVER_INFO_6
  255. is a super set of level 4, 3, and 2,
  256. the driver info structure is shared
  257. pDriverInfo6 - Points to DRIVER_INFO_6 structure
  258. dwAddDrvFlags - Flags used to AddPrinterDriver
  259. bIsDriverPathFullPath - Whether the driverpath is a full path
  260. bOffereReplacement - Whether to offer a replacement driver
  261. pdwBlockingStatus - Points to blocking status on server
  262. ppszReplacementDriver - Points to the replacement driver
  263. Return Value:
  264. An HRESULT
  265. --*/
  266. HRESULT
  267. PrintUpgRetry(
  268. IN LPCTSTR pszServer, OPTIONAL
  269. IN DWORD dwLevel,
  270. IN DRIVER_INFO_6 *pDriverInfo6,
  271. IN DWORD dwAddDrvFlags,
  272. IN BOOL bIsDriverPathFullPath,
  273. IN BOOL bOfferReplacement,
  274. IN OUT DWORD *pdwBlockingStatus,
  275. OUT LPTSTR *ppszReplacementDriver
  276. )
  277. {
  278. HRESULT hRetval = E_FAIL;
  279. hRetval = pDriverInfo6 && pdwBlockingStatus && ppszReplacementDriver && ((6 == dwLevel) || (dwLevel >= 2) && (dwLevel <= 4)) ? S_OK : E_INVALIDARG;
  280. if (SUCCEEDED(hRetval))
  281. {
  282. *ppszReplacementDriver = NULL;
  283. hRetval = PrintUpgUI(pszServer,
  284. pDriverInfo6,
  285. bIsDriverPathFullPath,
  286. bOfferReplacement,
  287. pdwBlockingStatus,
  288. ppszReplacementDriver);
  289. //
  290. // There are 4 cases here:
  291. // 1. For warned driver and the user instructs to install it, try
  292. // AddPrinterDriverEx again with APD_INSTALL_WARNED_DRIVER.
  293. // 2. If the user wants to cancel, set the last error correctly and
  294. // abort.
  295. // 3. If the user wants to install the replacement driver, we will
  296. // set the error code correctly and do not install the replacement
  297. // driver at this moment since we shall clean ourself up first.
  298. // 4. If other errors occur, we will just return the correct error
  299. // code.
  300. //
  301. // For case 1, 2, 4, we do not return the replacement driver because
  302. // I can not see any reason to do so.
  303. //
  304. if (FAILED(hRetval) || !(*pdwBlockingStatus & BSP_PRINTER_DRIVER_REPLACED)) // except case 3
  305. {
  306. LocalFreeMem(*ppszReplacementDriver);
  307. *ppszReplacementDriver = NULL;
  308. }
  309. if (SUCCEEDED(hRetval) && (*pdwBlockingStatus & BSP_PRINTER_DRIVER_PROCEEDED)) // case 1
  310. {
  311. dwAddDrvFlags |= APD_INSTALL_WARNED_DRIVER;
  312. hRetval = AddPrinterDriverEx(const_cast<LPTSTR>(pszServer),
  313. dwLevel,
  314. reinterpret_cast<BYTE*>(pDriverInfo6),
  315. dwAddDrvFlags) ? ERROR_SUCCESS : GetLastErrorAsHResult();
  316. }
  317. else if (SUCCEEDED(hRetval) && (*pdwBlockingStatus & BSP_PRINTER_DRIVER_CANCELLED)) // case 2
  318. {
  319. hRetval = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  320. }
  321. else if (SUCCEEDED(hRetval) && (*pdwBlockingStatus & BSP_PRINTER_DRIVER_REPLACED)) // case 3
  322. {
  323. hRetval = HResultFromWin32((*pdwBlockingStatus & BSP_PRINTER_DRIVER_BLOCKED) ? ERROR_PRINTER_DRIVER_BLOCKED : ERROR_PRINTER_DRIVER_WARNED);
  324. }
  325. }
  326. return hRetval;
  327. }
  328. /*++
  329. Routine Name:
  330. PrintUpgUI
  331. Routine Description:
  332. This routine asks ntprint.dll to popup a message box either indicates
  333. the driver is blocked and installation will abort or at the case of
  334. warned driver, whether to preceed the driver installation.
  335. Arguments:
  336. pszServer - Remote machine that has the driver files
  337. pDriverInfo6 - Points to DRINVER_INFO_6 structor
  338. bIsDriverPathFullPath - Whether the driverpath is a full path
  339. bOffereReplacement - Whether to offer a replacement driver
  340. pdwBlockingStatus - Points to blocking status on server
  341. ppszReplacementDriver - Points to the replacement driver
  342. Return Value:
  343. An HRESULT
  344. --*/
  345. HRESULT
  346. PrintUpgUI(
  347. IN LPCTSTR pszServer, OPTIONAL
  348. IN DRIVER_INFO_6 *pDriverInfo6,
  349. IN BOOL bIsDriverPathFullPath,
  350. IN BOOL bOfferReplacement,
  351. IN OUT DWORD *pdwBlockingStatus,
  352. OUT LPTSTR *ppszReplacementDriver
  353. )
  354. {
  355. HRESULT hRetval = E_FAIL;
  356. DWORD dwBlockingStatusOnClient = BSP_PRINTER_DRIVER_OK;
  357. hRetval = pDriverInfo6 && pdwBlockingStatus && ppszReplacementDriver ? S_OK : E_INVALIDARG;
  358. //
  359. // Take the replacement driver information from local client.
  360. //
  361. if (SUCCEEDED(hRetval) && bOfferReplacement)
  362. {
  363. *ppszReplacementDriver = NULL;
  364. hRetval = IsDriverBadLocally(pszServer,
  365. pDriverInfo6,
  366. bIsDriverPathFullPath,
  367. &dwBlockingStatusOnClient,
  368. ppszReplacementDriver);
  369. //
  370. // Get the replacement driver information
  371. //
  372. if (SUCCEEDED(hRetval))
  373. {
  374. *pdwBlockingStatus |= (dwBlockingStatusOnClient & ~BSP_BLOCKING_LEVEL_MASK);
  375. }
  376. }
  377. //
  378. // Get the user's response
  379. //
  380. if (SUCCEEDED(hRetval))
  381. {
  382. *pdwBlockingStatus &= ~BSP_USER_RESPONSE_MASK;
  383. hRetval = InternalPrintUpgUI(pDriverInfo6->pName,
  384. pDriverInfo6->pDriverPath, // main rendering driver dll
  385. pDriverInfo6->pEnvironment,
  386. pDriverInfo6->cVersion,
  387. pdwBlockingStatus);
  388. }
  389. return hRetval;
  390. }
  391. /*++
  392. Routine Name
  393. InfIsCompatibleDriver
  394. Routine Description:
  395. Check whether the driver is blocked or warned and if the driver is blocked
  396. or warned, return the blocking status and the replacement driver, if any.
  397. Arguments:
  398. pszDriverModel - The name of the driver to check
  399. pszDriverPath - The path of the driver, this can be a full path
  400. or the filename
  401. pszEnvironment - The environment of the server, such as
  402. "Windows NT x86"
  403. hInf - Handle to printupg inf
  404. puBlockingStatus - Points to status of blocking
  405. ppszReplacementDriver - Points to the NULL terminating name of the replacement
  406. driver. A *NULL* string (instead of an empty string)
  407. means there is no replacement driver
  408. Return Value:
  409. A BOOL - TRUE if success; FALSE otherwise, Call GetLastError()
  410. to get the Error code. Pass a NULL to ppszReplacementDriver
  411. will not receive the name of replacement driver otherwise
  412. Call PSetupFreeMem to free the received string pointed by
  413. ppszReplacementDriver
  414. --*/
  415. BOOL
  416. InfIsCompatibleDriver(
  417. IN LPCTSTR pszDriverModel,
  418. IN LPCTSTR pszDriverPath, // main rendering driver dll
  419. IN LPCTSTR pszEnvironment,
  420. IN HINF hInf,
  421. OUT DWORD *pdwBlockingStatus,
  422. OUT LPTSTR *ppszReplacementDriver OPTIONAL // caller must free it.
  423. )
  424. {
  425. HRESULT hRetval = E_FAIL;
  426. UINT uBlockingStatus = 0;
  427. DWORD dwMajorVersion = 0;
  428. BOOL bIsServer = FALSE;
  429. TString strReplacementDriver;
  430. FILETIME DriverFileTime;
  431. hRetval = pszDriverModel && pszDriverPath && pszEnvironment && (hInf != INVALID_HANDLE_VALUE) && pdwBlockingStatus ? S_OK : E_INVALIDARG;
  432. if (SUCCEEDED(hRetval))
  433. {
  434. *pdwBlockingStatus = 0;
  435. if (ppszReplacementDriver)
  436. {
  437. *ppszReplacementDriver = NULL;
  438. }
  439. hRetval = GetPrinterDriverVersion(pszDriverPath, &dwMajorVersion, NULL);
  440. }
  441. if (SUCCEEDED(hRetval))
  442. {
  443. hRetval = IsLocalMachineServer();
  444. }
  445. if (SUCCEEDED(hRetval))
  446. {
  447. bIsServer = S_OK == hRetval ? TRUE : FALSE;
  448. hRetval = GetFileTimeByName(pszDriverPath, &DriverFileTime);
  449. }
  450. if (S_OK == hRetval)
  451. {
  452. hRetval = InternalCompatibleInfDriverCheck(pszDriverModel,
  453. pszDriverPath,
  454. pszEnvironment,
  455. &DriverFileTime,
  456. hInf,
  457. dwMajorVersion,
  458. bIsServer,
  459. &uBlockingStatus,
  460. &strReplacementDriver);
  461. }
  462. if (SUCCEEDED(hRetval))
  463. {
  464. *pdwBlockingStatus = uBlockingStatus;
  465. if ((BSP_PRINTER_DRIVER_OK != (*pdwBlockingStatus & BSP_BLOCKING_LEVEL_MASK)) && ppszReplacementDriver && !strReplacementDriver.bEmpty())
  466. {
  467. *ppszReplacementDriver = AllocStr(strReplacementDriver);
  468. hRetval = ppszReplacementDriver ? S_OK : E_OUTOFMEMORY;
  469. if (SUCCEEDED(hRetval))
  470. {
  471. *pdwBlockingStatus |= BSP_INBOX_DRIVER_AVAILABLE;
  472. }
  473. }
  474. }
  475. SetLastError(SUCCEEDED(hRetval) ? ERROR_SUCCESS : HRESULT_CODE(hRetval));
  476. return SUCCEEDED(hRetval);
  477. }
  478. /*++
  479. Routine Name:
  480. GetPrinterDriverVersion
  481. Routine Description:
  482. Gets version information about an executable file. If the file is not an
  483. executable, it will return 0 for both major and minor version.
  484. Arguments:
  485. pszFileName - file name, this is either a full path for
  486. the file is under the path in the search
  487. sequence specified used the LoadLibrary
  488. function.
  489. pdwFileMajorVersion - pointer to major version
  490. pdwFileMinorVersion - pointer to minor version
  491. Return Value:
  492. An HRESULT
  493. --*/
  494. HRESULT
  495. GetPrinterDriverVersion(
  496. IN LPCTSTR pszFileName,
  497. OUT DWORD *pdwFileMajorVersion, OPTIONAL
  498. OUT DWORD *pdwFileMinorVersion OPTIONAL
  499. )
  500. {
  501. HRESULT hRetval = E_FAIL;
  502. DWORD dwSize = 0;
  503. UINT uLen = 0;
  504. BYTE *pbBlock = NULL;
  505. VS_FIXEDFILEINFO *pFileVersion = NULL;
  506. hRetval = pszFileName && *pszFileName ? S_OK : E_INVALIDARG;
  507. if (SUCCEEDED(hRetval))
  508. {
  509. dwSize = GetFileVersionInfoSize(const_cast<LPTSTR>(pszFileName), 0);
  510. if (dwSize == 0)
  511. {
  512. hRetval = GetLastErrorAsHResult();
  513. }
  514. }
  515. if (SUCCEEDED(hRetval))
  516. {
  517. pbBlock = new BYTE[dwSize];
  518. hRetval = pbBlock ? S_OK : E_OUTOFMEMORY;
  519. }
  520. if (SUCCEEDED(hRetval))
  521. {
  522. hRetval = GetFileVersionInfo(const_cast<LPTSTR>(pszFileName), 0, dwSize, pbBlock) ? S_OK : GetLastErrorAsHResult();
  523. }
  524. //
  525. // VerQueryValue does not set last error.
  526. //
  527. if (SUCCEEDED(hRetval))
  528. {
  529. hRetval = VerQueryValue(pbBlock, _T("\\"), reinterpret_cast<VOID **> (&pFileVersion), &uLen) && pFileVersion && uLen ? S_OK : E_INVALIDARG;
  530. }
  531. if (SUCCEEDED(hRetval))
  532. {
  533. hRetval = GetDriverVersionFromFileVersion(pFileVersion, pdwFileMajorVersion, pdwFileMinorVersion);
  534. }
  535. delete [] pbBlock;
  536. return hRetval;
  537. }
  538. /*++
  539. Routine Name:
  540. GetDriverVersionFromFileVersion
  541. Routine Description:
  542. Gets driver info from a FileVersion structure.
  543. Arguments:
  544. pFileVersion - Points to a file info structure
  545. pdwFileMajorVersion - pointer to major version
  546. pdwFileMinorVersion - pointer to minor version
  547. Return Value:
  548. An HRESULT
  549. --*/
  550. HRESULT
  551. GetDriverVersionFromFileVersion(
  552. IN VS_FIXEDFILEINFO *pFileVersion,
  553. OUT DWORD *pdwFileMajorVersion, OPTIONAL
  554. OUT DWORD *pdwFileMinorVersion OPTIONAL
  555. )
  556. {
  557. HRESULT hRetval = E_FAIL;
  558. hRetval = pFileVersion ? S_OK : E_INVALIDARG;
  559. //
  560. // Return versions for drivers designed for Windows NT/Windows 2000,
  561. // and marked as printer drivers.
  562. // Hold for all dlls Pre-Daytona.
  563. // After Daytona, printer driver writers must support
  564. // version control or we'll dump them as Version 0 drivers.
  565. //
  566. if (SUCCEEDED(hRetval))
  567. {
  568. if (pdwFileMajorVersion)
  569. {
  570. *pdwFileMajorVersion = 0;
  571. }
  572. if (pdwFileMinorVersion)
  573. {
  574. *pdwFileMinorVersion = 0;
  575. }
  576. if (VOS_NT_WINDOWS32 == pFileVersion->dwFileOS)
  577. {
  578. if ((VFT_DRV == pFileVersion->dwFileType) && (VFT2_DRV_VERSIONED_PRINTER == pFileVersion->dwFileSubtype))
  579. {
  580. if (pdwFileMajorVersion)
  581. {
  582. *pdwFileMajorVersion = pFileVersion->dwFileVersionMS;
  583. }
  584. if (pdwFileMinorVersion)
  585. {
  586. *pdwFileMinorVersion = pFileVersion->dwFileVersionLS;
  587. }
  588. }
  589. else if (pdwFileMajorVersion)
  590. {
  591. if (pFileVersion->dwProductVersionMS == pFileVersion->dwFileVersionMS)
  592. {
  593. *pdwFileMajorVersion = 0;
  594. }
  595. else
  596. {
  597. *pdwFileMajorVersion = pFileVersion->dwFileVersionMS;
  598. }
  599. }
  600. }
  601. }
  602. return hRetval;
  603. }
  604. /*++
  605. Routine Name:
  606. IsDriverBadLocally
  607. Routine Description:
  608. This routine loads the file and gets the FILETIME of the driver and check
  609. whether the driver is blokced or warned according the printupg.inf on the
  610. local machine.
  611. Arguments:
  612. pszServer - The server that has the driver files
  613. pDriverInfo6 - Points to DRINVER_INFO_6 structor
  614. dwAddDrvFlags - Flags used in AddPrinterDriver
  615. bIsDriverPathFullPath - Whether the driverpath is a full path
  616. pdwBlockingStatus - Points to blocking status of the driver
  617. ppszReplacementDriver - Points to the replacement driver
  618. Return Value:
  619. An HRESULT
  620. --*/
  621. HRESULT
  622. IsDriverBadLocally(
  623. IN LPCTSTR pszServer, OPTIONAL
  624. IN DRIVER_INFO_6 *pDriverInfo6,
  625. IN BOOL bIsDriverPathFullPath,
  626. OUT DWORD *pdwBlockingStatus,
  627. OUT LPTSTR *ppszReplacementDriver
  628. )
  629. {
  630. HRESULT hRetval = E_FAIL;
  631. DWORD dwMajorVersion = 0;
  632. FILETIME DriverFileTime;
  633. TString strDriverFullPath;
  634. hRetval = pDriverInfo6 && pdwBlockingStatus && ppszReplacementDriver ? S_OK : E_INVALIDARG;
  635. if (SUCCEEDED(hRetval))
  636. {
  637. hRetval = GetPrinterDriverPath(pszServer,
  638. pDriverInfo6->pDriverPath,
  639. pDriverInfo6->pEnvironment,
  640. bIsDriverPathFullPath,
  641. &strDriverFullPath);
  642. }
  643. if (SUCCEEDED(hRetval))
  644. {
  645. hRetval = GetFileTimeByName(strDriverFullPath, &DriverFileTime);
  646. }
  647. if (SUCCEEDED(hRetval))
  648. {
  649. hRetval = GetPrinterDriverVersion(strDriverFullPath, &dwMajorVersion, NULL);
  650. }
  651. if (SUCCEEDED(hRetval))
  652. {
  653. hRetval = PSetupIsCompatibleDriver(NULL,
  654. pDriverInfo6->pName,
  655. pDriverInfo6->pDriverPath,
  656. pDriverInfo6->pEnvironment,
  657. dwMajorVersion,
  658. &DriverFileTime,
  659. pdwBlockingStatus,
  660. ppszReplacementDriver) ? S_OK : GetLastErrorAsHResult();
  661. }
  662. if (FAILED(hRetval) && ppszReplacementDriver && *ppszReplacementDriver)
  663. {
  664. LocalFreeMem(*ppszReplacementDriver);
  665. *ppszReplacementDriver = NULL;
  666. }
  667. return hRetval;
  668. }
  669. /*++
  670. Routine Name:
  671. InternalPrintUpgUI
  672. Routine Description:
  673. This routine asks ntprint.dll to popup a message box either indicates
  674. the driver is blocked and installation will abort or at the case of
  675. warned driver, whether to preceed the driver installation.
  676. Arguments:
  677. pszDriverModel - The name of the driver to check
  678. pszDriverPath - The path of the driver, this can be a full path
  679. or the filename
  680. pszEnvironment - The environment of the server, such as
  681. "Windows NT x86"
  682. dwVersion - The major version of the driver
  683. pdwBlockingStatus - Points to blocking status on the client
  684. ppszReplacementDriver - Points to the name of replacement driver
  685. Return Value:
  686. An HRESULT - When this function is successful, user choose
  687. either proceed to install warned driver or install
  688. replacement driver.
  689. --*/
  690. HRESULT
  691. InternalPrintUpgUI(
  692. IN LPCTSTR pszDriverModel,
  693. IN LPCTSTR pszDriverPath, // main rendering driver dll
  694. IN LPCTSTR pszEnvironment,
  695. IN DWORD dwVersion,
  696. IN OUT DWORD *pdwBlockingStatus
  697. )
  698. {
  699. DWORD hRetval = E_FAIL;
  700. HWND hWndParent = NULL;
  701. DWORD dwStatusResponsed = BSP_PRINTER_DRIVER_OK;
  702. hRetval = pszDriverModel && pszDriverPath && pszEnvironment && pdwBlockingStatus ? S_OK : E_INVALIDARG;
  703. if (SUCCEEDED(hRetval) && (BSP_PRINTER_DRIVER_OK != (*pdwBlockingStatus & BSP_BLOCKING_LEVEL_MASK)))
  704. {
  705. *pdwBlockingStatus &= ~BSP_USER_RESPONSE_MASK;
  706. hWndParent = SUCCEEDED(GetCurrentThreadLastPopup(&hWndParent)) ? hWndParent : NULL;
  707. //
  708. // Ask the user what they want to do. If they don't want to proceed,
  709. // then the error is what the would get from the localspl call.
  710. //
  711. // PSetupShowBlockedDriverUI can not fail!
  712. //
  713. *pdwBlockingStatus |= (PSetupShowBlockedDriverUI(hWndParent, *pdwBlockingStatus) & BSP_USER_RESPONSE_MASK);
  714. }
  715. return hRetval;
  716. }
  717. //
  718. // This function is trying to get the last active popup of the top
  719. // level owner of the current thread active window.
  720. //
  721. HRESULT
  722. GetCurrentThreadLastPopup(
  723. OUT HWND *phwnd
  724. )
  725. {
  726. HWND hwndOwner, hwndParent;
  727. HRESULT hr = E_INVALIDARG;
  728. GUITHREADINFO ti = {0};
  729. if( phwnd )
  730. {
  731. hr = E_FAIL;
  732. *phwnd = NULL;
  733. ti.cbSize = sizeof(ti);
  734. if( GetGUIThreadInfo(0, &ti) && ti.hwndActive )
  735. {
  736. *phwnd = ti.hwndActive;
  737. // climb up to the top parent in case it's a child window...
  738. while( hwndParent = GetParent(*phwnd) )
  739. {
  740. *phwnd = hwndParent;
  741. }
  742. // get the owner in case the top parent is owned
  743. hwndOwner = GetWindow(*phwnd, GW_OWNER);
  744. if( hwndOwner )
  745. {
  746. *phwnd = hwndOwner;
  747. }
  748. // get the last popup of the owner window
  749. *phwnd = GetLastActivePopup(*phwnd);
  750. hr = (*phwnd) ? S_OK : E_FAIL;
  751. }
  752. }
  753. return hr;
  754. }
  755. /*++
  756. Routine Name
  757. GetPrinterDriverPath
  758. Routine Description:
  759. Get the file full path of the driver.
  760. Arguments:
  761. pszServer - The server that needs to check for bad driver. If
  762. pszServer is NULL, that means the local machine
  763. pszDriverPath - The path of the driver, this can be a full path or
  764. the filename
  765. pszEnvironment - The environment of the server, such as
  766. "Windows NT x86"
  767. bIsDriverpathFullPath - Whether pszDriverPath is the full path or just the
  768. the file name of the driver
  769. pstrFull - The full path of the driver
  770. Return Value:
  771. An HRESULT
  772. --*/
  773. HRESULT
  774. GetPrinterDriverPath(
  775. IN LPCTSTR pszServer, OPTIONAL
  776. IN LPCTSTR pszDriverPath,
  777. IN LPCTSTR pszEnvironment,
  778. IN BOOL bIsDriverPathFullPath,
  779. OUT TString *pstrFullPath
  780. )
  781. {
  782. HRESULT hRetval = E_FAIL;
  783. TCHAR szDir[MAX_PATH] = {0};
  784. DWORD dwNeeded = 0;
  785. hRetval = pszEnvironment && *pszEnvironment && pszDriverPath && *pszDriverPath && pstrFullPath ? S_OK : E_INVALIDARG;
  786. if (SUCCEEDED(hRetval) && !bIsDriverPathFullPath)
  787. {
  788. hRetval = GetPrinterDriverDirectory(const_cast<LPTSTR>(pszServer), // This API is designed wrongly.
  789. const_cast<LPTSTR>(pszEnvironment),
  790. 1, // This value must be 1
  791. (LPBYTE)szDir,
  792. sizeof(szDir),
  793. &dwNeeded) ? S_OK : GetLastErrorAsHResult();
  794. }
  795. if (FAILED(hRetval) && (ERROR_INSUFFICIENT_BUFFER == HRESULT_CODE(hRetval)))
  796. {
  797. hRetval = HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
  798. }
  799. //
  800. // Add 1 '\\' between driverpath and filename. Note if the path is too
  801. // long StrNCatBuff will truncate it and StrNCatBuff always NULL terminates
  802. // the buffer.
  803. //
  804. if (SUCCEEDED(hRetval))
  805. {
  806. hRetval = HResultFromWin32(StrNCatBuff(szDir, COUNTOF(szDir), szDir, *szDir ? _T("\\") : _T(""), pszDriverPath, NULL));
  807. }
  808. if (SUCCEEDED(hRetval))
  809. {
  810. hRetval = pstrFullPath->bUpdate(szDir) ? S_OK : E_OUTOFMEMORY;
  811. }
  812. return hRetval;
  813. }
  814. /*++
  815. Routine Name
  816. GetFileTimeByName
  817. Routine Description:
  818. Get the file time of the file given a full path.
  819. Arguments:
  820. pszPath - Full path of the driver
  821. pFileTime - Points to the file time
  822. Return Value:
  823. An HRESULT
  824. --*/
  825. HRESULT
  826. GetFileTimeByName(
  827. IN LPCTSTR pszPath,
  828. OUT FILETIME *pFileTime
  829. )
  830. {
  831. HRESULT hRetval = E_FAIL;
  832. HANDLE hFile = INVALID_HANDLE_VALUE;
  833. hRetval = pszPath && *pszPath && pFileTime ? S_OK : E_INVALIDARG;
  834. if (SUCCEEDED(hRetval))
  835. {
  836. hFile = CreateFile(pszPath,
  837. GENERIC_READ,
  838. FILE_SHARE_READ,
  839. NULL,
  840. OPEN_EXISTING,
  841. FILE_ATTRIBUTE_NORMAL,
  842. NULL);
  843. hRetval = (INVALID_HANDLE_VALUE == hFile) ? S_OK : GetLastErrorAsHResult();
  844. }
  845. if (SUCCEEDED(hRetval))
  846. {
  847. hRetval = GetFileTime(hFile, NULL, NULL, pFileTime) ? S_OK : GetLastErrorAsHResult();
  848. }
  849. if (hFile != INVALID_HANDLE_VALUE)
  850. {
  851. CloseHandle(hFile);
  852. }
  853. return hRetval;
  854. }
  855. /*++
  856. Routine Name
  857. InternalCompatibleDriverCheck
  858. Routine Description:
  859. Check whether the driver is blocked or warned and if the driver
  860. is blocked or warned, return the replacement driver.
  861. Arguments:
  862. pszDriverModel - The name of the driver to check
  863. pszDriverPath - The path of the driver, this can be a full path or
  864. the filename
  865. pszEnvironment - The environment of the server, such as
  866. "Windows NT x86"
  867. pFileTimeDriver - The FileTime of the driver
  868. pszPrintUpgInf - The PrintUpg Inf filename
  869. uVersion - The major version of the driver
  870. bIsServer - Where the printing services runs on an NT Server SKU
  871. puBlockingStatus - Points to status of blocking
  872. pstrReplacementDriver - The replacement driver.
  873. Return Value:
  874. An HRESULT
  875. --*/
  876. HRESULT
  877. InternalCompatibleDriverCheck(
  878. IN LPCTSTR pszDriverModel,
  879. IN LPCTSTR pszDriverPath,
  880. IN LPCTSTR pszEnvironment,
  881. IN FILETIME *pFileTimeDriver,
  882. IN LPCTSTR pszPrintUpgInf,
  883. IN UINT uVersion,
  884. IN BOOL bIsServer,
  885. OUT UINT *puBlockingStatus,
  886. OUT TString *pstrReplacementDriver
  887. )
  888. {
  889. DBG_MSG(DBG_TRACE, (_T("In the InternalCompatibleDriverCheck routine\n")));
  890. HRESULT hRetval = E_FAIL;
  891. HINF hInf = INVALID_HANDLE_VALUE;
  892. hRetval = pszDriverModel && pszDriverPath && pszEnvironment && pFileTimeDriver && pszPrintUpgInf && puBlockingStatus && pstrReplacementDriver ? S_OK : E_INVALIDARG;
  893. if (SUCCEEDED(hRetval))
  894. {
  895. *puBlockingStatus = 0;
  896. hInf = SetupOpenInfFile(pszPrintUpgInf, NULL, INF_STYLE_WIN4, NULL);
  897. hRetval = (INVALID_HANDLE_VALUE == hInf) ? S_OK : GetLastErrorAsHResult();
  898. }
  899. if (SUCCEEDED(hRetval))
  900. {
  901. hRetval = InternalCompatibleInfDriverCheck(pszDriverModel,
  902. pszDriverPath,
  903. pszEnvironment,
  904. pFileTimeDriver,
  905. hInf,
  906. uVersion,
  907. bIsServer,
  908. puBlockingStatus,
  909. pstrReplacementDriver);
  910. }
  911. if (INVALID_HANDLE_VALUE != hInf)
  912. {
  913. SetupCloseInfFile(hInf);
  914. }
  915. return hRetval;
  916. }
  917. /*++
  918. Routine Name
  919. InternalCompatibleInfDriverCheck
  920. Routine Description:
  921. Check whether the driver is blocked or warned and if the driver
  922. is blocked or warned, return the replacement driver.
  923. Arguments:
  924. pszDriverModel - The name of the driver to check
  925. pszDriverPath - The path of the driver, this can be a full path or
  926. the filename
  927. pszEnvironment - The environment of the server, such as
  928. "Windows NT x86"
  929. pFileTimeDriver - The FileTime of the driver
  930. hPrintUpgInf - The handle to the PrintUpg Inf file
  931. uVersion - The major version of the driver
  932. bIsServer - Where the printing services runs on an NT Server SKU
  933. puBlockingStatus - Points to status of blocking
  934. pstrReplacementDriver - The replacement driver.
  935. Return Value:
  936. An HRESULT
  937. --*/
  938. HRESULT
  939. InternalCompatibleInfDriverCheck(
  940. IN LPCTSTR pszModelName,
  941. IN LPCTSTR pszDriverPath,
  942. IN LPCTSTR pszEnvironment,
  943. IN FILETIME *pFileTimeDriver,
  944. IN HINF hPrintUpgInf,
  945. IN UINT uVersion,
  946. IN BOOL bIsServer,
  947. OUT UINT *puBlockingStatus,
  948. OUT TString *pstrReplacementDriver OPTIONAL
  949. )
  950. {
  951. HRESULT hRetval = E_FAIL;
  952. HINF hInf = INVALID_HANDLE_VALUE;
  953. UINT uWarnLevelSrv = 0;
  954. UINT uWarnLevelWks = 0;
  955. UINT uWarnLevel = 0;
  956. FILETIME FileTimeOfDriverInInf;
  957. hRetval = pszModelName && pszDriverPath && pszEnvironment && pFileTimeDriver && (INVALID_HANDLE_VALUE != hPrintUpgInf) && puBlockingStatus && pstrReplacementDriver? S_OK : E_INVALIDARG;
  958. if (SUCCEEDED(hRetval))
  959. {
  960. hRetval = IsDriverDllInExcludedSection(pszDriverPath, hPrintUpgInf);
  961. }
  962. if (S_FALSE == hRetval)
  963. {
  964. hRetval = IsDriverInMappingSection(pszModelName,
  965. pszEnvironment,
  966. uVersion,
  967. hPrintUpgInf,
  968. pFileTimeDriver,
  969. &uWarnLevelSrv,
  970. &uWarnLevelWks,
  971. pstrReplacementDriver);
  972. if (S_OK == hRetval)
  973. {
  974. hRetval = GetBlockingStatusByWksType(uWarnLevelSrv, uWarnLevelWks, bIsServer, puBlockingStatus);
  975. }
  976. }
  977. if (SUCCEEDED(hRetval))
  978. {
  979. DBG_MSG(DBG_TRACE, (_T("Driver \"%s\" Driverpath \"%s\" Environment \"%s\" Version %d WarnLevel Server %d WarnLevel Wks %d bIsServer %d *Blocking Status* 0X%X *Replacement Driver* \"%s\"\n"), pszModelName, pszDriverPath, pszEnvironment,uVersion, uWarnLevelSrv, uWarnLevelSrv, bIsServer, *puBlockingStatus, static_cast<LPCTSTR>(*pstrReplacementDriver)));
  980. hRetval = (BSP_PRINTER_DRIVER_OK == (*puBlockingStatus & BSP_BLOCKING_LEVEL_MASK)) ? S_OK : S_FALSE;
  981. }
  982. return hRetval;
  983. }
  984. /*++
  985. Routine Name
  986. IsDriverInMappingSection
  987. Routine Description:
  988. Check whether the driver is mapped, aka a bad driver.
  989. Arguments:
  990. pszDriverModel - The name of the driver to check
  991. pszEnvironment - The environment of the server, such as
  992. uVersion - The major version of the driver
  993. hPrintUpgInf - The handle to the PrintUpg Inf file
  994. pFileTimeDriver - Points to the file time of the driver
  995. pdwWarnLevelSrv - Points to the warning level for server SKU
  996. pdwWarnLevelWks - Points to the warning level for wks SKU
  997. pstrReplacementDriver - The replacement driver
  998. Return Value:
  999. An HRESULT - S_OK means the driver is a bad driver and is mapped to
  1000. some inbox driver, S_FALSE means the driver is not.
  1001. --*/
  1002. HRESULT
  1003. IsDriverInMappingSection(
  1004. IN LPCTSTR pszModelName,
  1005. IN LPCTSTR pszEnvironment,
  1006. IN UINT uVersion,
  1007. IN HINF hPrintUpgInf,
  1008. IN FILETIME *pFileTimeDriver,
  1009. OUT UINT *puWarnLevelSrv,
  1010. OUT UINT *puWarnLevelWks,
  1011. OUT TString *pstrReplacementDriver
  1012. )
  1013. {
  1014. DBG_MSG(DBG_TRACE, (_T("In the IsDriverInMappingSection routine\n")));
  1015. HRESULT hRetval = E_FAIL;
  1016. UINT uWarnLevelSrv = 0;
  1017. UINT uWarnLevelWks = 0;
  1018. INFCONTEXT InfContext;
  1019. TString strMappingSection;
  1020. TString strReplacementDriver;
  1021. hRetval = pszModelName && pszEnvironment && (INVALID_HANDLE_VALUE != hPrintUpgInf) && pFileTimeDriver && puWarnLevelSrv && puWarnLevelWks && pstrReplacementDriver ? S_OK : E_INVALIDARG;
  1022. if (SUCCEEDED(hRetval))
  1023. {
  1024. *puWarnLevelSrv = 0;
  1025. *puWarnLevelWks = 0;
  1026. hRetval = GetSectionName(pszEnvironment, uVersion, &strMappingSection);
  1027. }
  1028. if (SUCCEEDED(hRetval))
  1029. {
  1030. hRetval = SetupFindFirstLine(hPrintUpgInf, strMappingSection, pszModelName, &InfContext) ? S_FALSE : GetLastErrorAsHResult();
  1031. }
  1032. //
  1033. // This code assumes that:
  1034. //
  1035. // There can be multiple lines for the same printer driver, but they
  1036. // are sorted in non-descreasing order by date, the last field of the
  1037. // line. The fist line that has the date no older than the driver's
  1038. // date is used.
  1039. //
  1040. // An interesting case would be like (since date is optional)
  1041. //
  1042. // "HP LaserJet 4" = "HP LaserJet 4", 1, 2, "11/28/1999"
  1043. // "HP LaserJet 4" = "HP LaserJet 4", 2, 1
  1044. //
  1045. // If a date is empty then the driver of all dates are blocked, hence
  1046. // an empty date means close to a very late date in the future.
  1047. //
  1048. for (;S_FALSE == hRetval;)
  1049. {
  1050. hRetval = IsDateInLineNoOlderThanDriverDate(&InfContext, pFileTimeDriver, &uWarnLevelSrv, &uWarnLevelWks, &strReplacementDriver);
  1051. if (S_FALSE == hRetval)
  1052. {
  1053. hRetval = SetupFindNextMatchLine(&InfContext, pszModelName, &InfContext) ? S_FALSE : GetLastErrorAsHResult();
  1054. }
  1055. }
  1056. //
  1057. // ERROR_LINE_NOT_FOUND is an HRESULT!
  1058. //
  1059. if (FAILED(hRetval) && (HRESULT_CODE(ERROR_LINE_NOT_FOUND) == HRESULT_CODE(hRetval)))
  1060. {
  1061. DBG_MSG(DBG_TRACE, (_T("Driver \"%s\" is not mapped\n"), pszModelName));
  1062. hRetval = S_FALSE;
  1063. }
  1064. if (S_OK == hRetval)
  1065. {
  1066. DBG_MSG(DBG_TRACE, (_T("Driver \"%s\" is mapped\n"), pszModelName));
  1067. *puWarnLevelSrv = uWarnLevelSrv;
  1068. *puWarnLevelWks = uWarnLevelWks;
  1069. hRetval = pstrReplacementDriver->bUpdate(strReplacementDriver) ? S_OK : E_OUTOFMEMORY;
  1070. }
  1071. return hRetval;
  1072. }
  1073. /*++
  1074. Routine Name
  1075. IsDateInLineNoOlderThanDriverDate
  1076. Routine Description:
  1077. This routines process the current line of inf and determinate whether the
  1078. date in the line is not older than that of driver.
  1079. Arguments:
  1080. pInfContext - Points to the current context of an INF
  1081. pDriverFileTime - File time of the actual driver
  1082. pdwWarnLevelSrv - Points to the warning level for server SKU
  1083. pdwWarnLevelWks - Points to the warning level for wks SKU
  1084. pstrReplacementDriver - The replacement driver.
  1085. Return Value:
  1086. An HRESULT - S_OK means the date in the current line is no older
  1087. than that of the driver
  1088. --*/
  1089. HRESULT
  1090. IsDateInLineNoOlderThanDriverDate(
  1091. IN INFCONTEXT *pInfContext,
  1092. IN FILETIME *pDriverFileTime,
  1093. OUT UINT *puWarnLevelSrv,
  1094. OUT UINT *puWarnLevelWks,
  1095. OUT TString *pstrReplacementDriver
  1096. )
  1097. {
  1098. HRESULT hRetval = E_FAIL;
  1099. INT iWarnLevel = 0;
  1100. FILETIME FileTimeInInf;
  1101. hRetval = pInfContext && pDriverFileTime && puWarnLevelSrv && puWarnLevelWks && pstrReplacementDriver ? S_OK : E_INVALIDARG;
  1102. if (SUCCEEDED(hRetval))
  1103. {
  1104. hRetval = SetupGetIntField(pInfContext, kWarnLevelSrv, &iWarnLevel) ? S_OK: GetLastErrorAsHResult();
  1105. if (SUCCEEDED(hRetval))
  1106. {
  1107. *puWarnLevelSrv = iWarnLevel;
  1108. hRetval = SetupGetIntField(pInfContext, kWarnLevelWks, &iWarnLevel) ? S_OK: GetLastErrorAsHResult();
  1109. }
  1110. if (SUCCEEDED(hRetval))
  1111. {
  1112. *puWarnLevelWks = iWarnLevel;
  1113. hRetval = InfGetString(pInfContext, kReplacementDriver, pstrReplacementDriver);
  1114. }
  1115. if (SUCCEEDED(hRetval))
  1116. {
  1117. hRetval = InfGetStringAsFileTime(pInfContext, kFileTime, &FileTimeInInf);
  1118. //
  1119. // Date field is optional.
  1120. //
  1121. if (FAILED(hRetval) && (ERROR_INVALID_PARAMETER == HRESULT_CODE(hRetval)))
  1122. {
  1123. DBG_MSG(DBG_TRACE, (_T("Date in inf is empty, drivers of all dates are blocked.\n")));
  1124. hRetval = S_OK;
  1125. }
  1126. else if (SUCCEEDED(hRetval))
  1127. {
  1128. hRetval = CompareFileTime(pDriverFileTime, &FileTimeInInf) <= 0 ? S_OK : S_FALSE ;
  1129. }
  1130. }
  1131. }
  1132. return hRetval;
  1133. }
  1134. /*++
  1135. Routine Name
  1136. GetSectionName
  1137. Routine Description:
  1138. Get the Section name in terms of environment and driver version.
  1139. Arguments:
  1140. pszEnvironment - The environment of the server, such as
  1141. uVersion - The major version of the driver
  1142. pstrSection - Points the name of section of driver mapping
  1143. Return Value:
  1144. An HRESULT
  1145. --*/
  1146. HRESULT
  1147. GetSectionName(
  1148. IN LPCTSTR pszEnvironment,
  1149. IN UINT uVersion,
  1150. OUT TString *pstrSection
  1151. )
  1152. {
  1153. HRESULT hRetval = E_FAIL;
  1154. hRetval = pszEnvironment && pstrSection ? S_OK : E_INVALIDARG;
  1155. if (SUCCEEDED(hRetval))
  1156. {
  1157. hRetval = pstrSection->bFormat(_T("%s_%s_%s %d"), cszPrintDriverMapping, pszEnvironment, cszVersion, uVersion);
  1158. }
  1159. return hRetval;
  1160. }
  1161. /*++
  1162. Routine Name
  1163. InfGetString
  1164. Routine Description:
  1165. This routine is a wrapper to SetupGetStringField using TString.
  1166. Arguments:
  1167. pInfContext - The context of the inf
  1168. uFieldIndex - The field index of the string to retrieve
  1169. pstrField - Points to the string field as TString
  1170. Return Value:
  1171. An HRESULT
  1172. --*/
  1173. HRESULT
  1174. InfGetString(
  1175. IN INFCONTEXT *pInfContext,
  1176. IN UINT uFieldIndex,
  1177. OUT TString *pstrField
  1178. )
  1179. {
  1180. HRESULT hRetval = E_FAIL;
  1181. TCHAR szField[MAX_PATH] = {0};
  1182. DWORD dwNeeded = 0;
  1183. TCHAR *pszField = NULL;
  1184. hRetval = pInfContext && pstrField ? S_OK : E_INVALIDARG;
  1185. if (SUCCEEDED(hRetval))
  1186. {
  1187. hRetval = SetupGetStringField(pInfContext,
  1188. uFieldIndex,
  1189. szField,
  1190. COUNTOF(szField),
  1191. &dwNeeded) ? S_OK : GetLastErrorAsHResult();
  1192. if (SUCCEEDED(hRetval))
  1193. {
  1194. hRetval = pstrField->bUpdate(szField) ? S_OK : E_OUTOFMEMORY;
  1195. }
  1196. else if (FAILED(hRetval) && (ERROR_INSUFFICIENT_BUFFER == HRESULT_CODE(hRetval)))
  1197. {
  1198. pszField = new TCHAR[dwNeeded];
  1199. hRetval = pszField ? S_OK : E_OUTOFMEMORY;
  1200. DBG_MSG(DBG_TRACE, (_T("Long string encountered\n")));
  1201. if (SUCCEEDED(hRetval))
  1202. {
  1203. hRetval = SetupGetStringField(pInfContext,
  1204. uFieldIndex,
  1205. pszField,
  1206. dwNeeded,
  1207. &dwNeeded) ? S_OK : GetLastErrorAsHResult();
  1208. }
  1209. if (SUCCEEDED(hRetval))
  1210. {
  1211. hRetval = pstrField->bUpdate(pszField) ? S_OK : E_OUTOFMEMORY;
  1212. }
  1213. }
  1214. }
  1215. delete [] pszField;
  1216. return hRetval;
  1217. }
  1218. /*++
  1219. Routine Name
  1220. InfGetStringAsFileTime
  1221. Routine Description:
  1222. This routine get the time of driver in printupg and converts it to FILETIME.
  1223. Arguments:
  1224. pInfContext - The context of the inf
  1225. uFieldIndex - The field index of the string to retrieve
  1226. pFielTime - Points to the FILETIME structure
  1227. Return Value:
  1228. An HRESULT
  1229. --*/
  1230. HRESULT
  1231. InfGetStringAsFileTime(
  1232. IN INFCONTEXT *pInfContext,
  1233. IN UINT uFieldIndex,
  1234. OUT FILETIME *pFileTime
  1235. )
  1236. {
  1237. HRESULT hRetval = E_FAIL;
  1238. TString strDate;
  1239. hRetval = pInfContext && pFileTime ? S_OK : E_INVALIDARG;
  1240. if (SUCCEEDED(hRetval))
  1241. {
  1242. hRetval = InfGetString(pInfContext, uFieldIndex, &strDate);
  1243. }
  1244. if (SUCCEEDED(hRetval))
  1245. {
  1246. DBG_MSG(DBG_TRACE, (_T("FileTime in INF as string \"%s\"\n"), static_cast<LPCTSTR>(strDate)));
  1247. hRetval = StringTimeToFileTime(strDate, pFileTime);
  1248. }
  1249. return hRetval;
  1250. }
  1251. /*++
  1252. Routine Name
  1253. StringTimeToFileTime
  1254. Routine Description:
  1255. Converts a string of time in the form of "11/27/1999" to FILETIME.
  1256. Arguments:
  1257. pszFileTime - The file time as string such as "11/27/1999"
  1258. pFileTime - Points to the converted FILETIME
  1259. Return Value:
  1260. An HRESULT
  1261. --*/
  1262. HRESULT
  1263. StringTimeToFileTime(
  1264. IN LPCTSTR pszFileTime,
  1265. OUT FILETIME *pFileTime
  1266. )
  1267. {
  1268. HRESULT hRetval = E_FAIL;
  1269. SYSTEMTIME SystemTime;
  1270. hRetval = pszFileTime && pFileTime ? S_OK : E_INVALIDARG;
  1271. if (SUCCEEDED(hRetval))
  1272. {
  1273. //
  1274. // StringToDate should take pszFileTime as const.
  1275. //
  1276. hRetval = StringToDate(const_cast<LPTSTR>(pszFileTime), &SystemTime) ? S_OK : GetLastErrorAsHResult();
  1277. }
  1278. if (SUCCEEDED(hRetval))
  1279. {
  1280. hRetval = SystemTimeToFileTime(&SystemTime, pFileTime) ? S_OK : GetLastErrorAsHResult();
  1281. }
  1282. return hRetval;
  1283. }
  1284. /*++
  1285. Routine Name
  1286. GetBlockingStatusByWksType
  1287. Routine Description:
  1288. Fill out the status of blocking according to the type of SKU that runs the
  1289. service.
  1290. Arguments:
  1291. uWarnLevelSrv - The warn level for server SKU
  1292. uWarnLevelSrv - The warn level for wks SKU
  1293. bIsServer - Whether the SKU running printing service is server
  1294. puBlockingStatus - Points to the result as status of blocking
  1295. Return Value:
  1296. An HRESULT
  1297. --*/
  1298. HRESULT
  1299. GetBlockingStatusByWksType(
  1300. IN UINT uWarnLevelSrv,
  1301. IN UINT uWarnLevelWks,
  1302. IN BOOL bIsServer,
  1303. OUT UINT *puBlockingStatus
  1304. )
  1305. {
  1306. HRESULT hRetval = E_FAIL;
  1307. UINT uWarnLevel = 0;
  1308. hRetval = puBlockingStatus ? S_OK : E_INVALIDARG;
  1309. if (SUCCEEDED(hRetval))
  1310. {
  1311. *puBlockingStatus &= ~BSP_BLOCKING_LEVEL_MASK;
  1312. *puBlockingStatus |= BSP_PRINTER_DRIVER_OK;
  1313. uWarnLevel = bIsServer ? uWarnLevelSrv : uWarnLevelWks;
  1314. switch (uWarnLevel)
  1315. {
  1316. case kBlocked:
  1317. *puBlockingStatus |= BSP_PRINTER_DRIVER_BLOCKED;
  1318. break;
  1319. case kWarned:
  1320. *puBlockingStatus |= BSP_PRINTER_DRIVER_WARNED;
  1321. break;
  1322. default:
  1323. hRetval = E_FAIL;
  1324. break;
  1325. }
  1326. }
  1327. return hRetval;
  1328. }
  1329. /*++
  1330. Routine Name
  1331. IsDriverDllInExcludedSection
  1332. Routine Description:
  1333. Determine Whether the driver dll name is in the excluded section of printupg.
  1334. Arguments:
  1335. pszDriverPath - The path of the driver and this can be a full path or
  1336. the file name
  1337. hPrintUpgInf - The handle to printupg INF file
  1338. Return Value:
  1339. An HRESULT - S_OK means the driver dll is in the excluded section,
  1340. S_FALSE means it is not.
  1341. --*/
  1342. HRESULT
  1343. IsDriverDllInExcludedSection(
  1344. IN LPCTSTR pszDriverPath,
  1345. IN HINF hPrintUpgInf
  1346. )
  1347. {
  1348. DBG_MSG(DBG_TRACE, (_T("In the IsDriverDllInExcludedSection routine\n")));
  1349. HRESULT hRetval = E_FAIL;
  1350. TString strDriverFileName;
  1351. INFCONTEXT InfContext;
  1352. hRetval = pszDriverPath && (INVALID_HANDLE_VALUE != hPrintUpgInf) ? S_OK : E_INVALIDARG;
  1353. if (SUCCEEDED(hRetval))
  1354. {
  1355. hRetval = strDriverFileName.bUpdate(FileNamePart(pszDriverPath)) ? S_OK : E_OUTOFMEMORY;
  1356. }
  1357. if (SUCCEEDED(hRetval) && !strDriverFileName.bEmpty())
  1358. {
  1359. hRetval = SetupFindFirstLine(hPrintUpgInf,
  1360. cszExcludeSection,
  1361. strDriverFileName,
  1362. &InfContext) ? S_OK : GetLastErrorAsHResult();
  1363. //
  1364. // ERROR_LINE_NOT_FOUND is an HRESULT!
  1365. //
  1366. if (FAILED(hRetval) && (HRESULT_CODE(ERROR_LINE_NOT_FOUND) == HRESULT_CODE(hRetval)))
  1367. {
  1368. hRetval = S_FALSE;
  1369. }
  1370. DBG_MSG(DBG_TRACE, (_T("Driver Path %s driver dll %s excluded section \"%s\" Is not excluded? %d\n"), pszDriverPath, static_cast<LPCTSTR>(strDriverFileName), cszExcludeSection, hRetval));
  1371. }
  1372. return hRetval;
  1373. }
  1374. /*++
  1375. Routine Name
  1376. IsEnvironmentAndVersionNeededToCheck
  1377. Routine Description:
  1378. This routine looks up a table of environment and version to see whether it
  1379. is necessary to check for blocked/warned driver.
  1380. Arguments:
  1381. pszEnvironment - The environment where the driver runs
  1382. uVersion - The major version of the driver.
  1383. Return Value:
  1384. An HRESULT
  1385. --*/
  1386. HRESULT
  1387. IsEnvironmentAndVersionNeededToCheck(
  1388. IN LPCTSTR pszEnvironment,
  1389. IN UINT uVersion
  1390. )
  1391. {
  1392. HRESULT hRetval = E_FAIL;
  1393. static struct TPrintUPGCheckListItem
  1394. {
  1395. LPCTSTR pszEnvironment;
  1396. UINT uVersion;
  1397. } aPrintUpgCheckList[] = {
  1398. {X86_ENVIRONMENT, 2},
  1399. {X86_ENVIRONMENT, 3},
  1400. {IA64_ENVIRONMENT, 3},
  1401. };
  1402. hRetval = pszEnvironment ? S_FALSE : E_INVALIDARG;
  1403. if (SUCCEEDED(hRetval))
  1404. {
  1405. for (UINT i = 0; i < COUNTOF(aPrintUpgCheckList); i++)
  1406. {
  1407. if (!lstrcmpi(aPrintUpgCheckList[i].pszEnvironment, pszEnvironment) && (aPrintUpgCheckList[i].uVersion == uVersion))
  1408. {
  1409. hRetval = S_OK;
  1410. break;
  1411. }
  1412. }
  1413. }
  1414. return hRetval;
  1415. }
  1416. /*++
  1417. Routine Name
  1418. IsLocalMachineServer
  1419. Routine Description:
  1420. This routine determines whether the local machine is a server SKU.
  1421. Arguments:
  1422. None
  1423. Return Value:
  1424. An HRESULT - S_OK if it is a server, S_FALSE otherwise.
  1425. --*/
  1426. HRESULT
  1427. IsLocalMachineServer(
  1428. VOID
  1429. )
  1430. {
  1431. HRESULT hRetval = E_FAIL;
  1432. DWORDLONG dwlConditionMask = 0;
  1433. OSVERSIONINFOEX OsVerEx;
  1434. (VOID)ZeroMemory(&OsVerEx, sizeof(OSVERSIONINFOEX));
  1435. OsVerEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1436. OsVerEx.wProductType = VER_NT_SERVER;
  1437. VER_SET_CONDITION( dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL );
  1438. hRetval = VerifyVersionInfo(&OsVerEx, VER_PRODUCT_TYPE, dwlConditionMask) ? S_OK : GetLastErrorAsHResult();
  1439. if (FAILED(hRetval) && (ERROR_OLD_WIN_VERSION == HRESULT_CODE(hRetval)))
  1440. {
  1441. hRetval = S_FALSE;
  1442. }
  1443. return hRetval;
  1444. }
  1445. #if DBG_PRINTUPG
  1446. LPTSTR
  1447. ReadDigit(
  1448. LPTSTR ptr,
  1449. LPWORD pW
  1450. )
  1451. {
  1452. TCHAR c;
  1453. //
  1454. // Skip spaces
  1455. //
  1456. while ( !iswdigit(c = *ptr) && c != TEXT('\0') )
  1457. ++ptr;
  1458. if ( c == TEXT('\0') )
  1459. return NULL;
  1460. //
  1461. // Read field
  1462. //
  1463. for ( *pW = 0 ; iswdigit(c = *ptr) ; ++ptr )
  1464. *pW = *pW * 10 + c - TEXT('0');
  1465. return ptr;
  1466. }
  1467. BOOL
  1468. StringToDate(
  1469. LPTSTR pszDate,
  1470. SYSTEMTIME *pInfTime
  1471. )
  1472. {
  1473. BOOL bRet = FALSE;
  1474. ZeroMemory(pInfTime, sizeof(*pInfTime));
  1475. bRet = (pszDate = ReadDigit(pszDate, &(pInfTime->wMonth))) &&
  1476. (pszDate = ReadDigit(pszDate, &(pInfTime->wDay))) &&
  1477. (pszDate = ReadDigit(pszDate, &(pInfTime->wYear)));
  1478. //
  1479. // Y2K compatible check
  1480. //
  1481. if ( bRet && pInfTime->wYear < 100 ) {
  1482. if ( pInfTime->wYear < 10 )
  1483. pInfTime->wYear += 2000;
  1484. else
  1485. pInfTime->wYear += 1900;
  1486. }
  1487. return bRet;
  1488. }
  1489. LPTSTR
  1490. FileNamePart(
  1491. IN LPCTSTR pszFullName
  1492. )
  1493. {
  1494. LPTSTR pszSlash, pszTemp;
  1495. if ( !pszFullName )
  1496. return NULL;
  1497. //
  1498. // First find the : for the drive
  1499. //
  1500. if ( pszTemp = lstrchr(pszFullName, TEXT(':')) )
  1501. pszFullName = pszFullName + 1;
  1502. for ( pszTemp = (LPTSTR)pszFullName ;
  1503. pszSlash = lstrchr(pszTemp, TEXT('\\')) ;
  1504. pszTemp = pszSlash + 1 )
  1505. ;
  1506. return *pszTemp ? pszTemp : NULL;
  1507. }
  1508. PVOID
  1509. LocalAllocMem(
  1510. IN UINT cbSize
  1511. )
  1512. {
  1513. return LocalAlloc( LPTR, cbSize );
  1514. }
  1515. VOID
  1516. LocalFreeMem(
  1517. IN PVOID p
  1518. )
  1519. {
  1520. LocalFree(p);
  1521. }
  1522. /*++
  1523. Routine Description:
  1524. Allocate memory and make a copy of a string field
  1525. Arguments:
  1526. pszStr : String to copy
  1527. Return Value:
  1528. Pointer to the copied string. Memory is allocated.
  1529. --*/
  1530. LPTSTR
  1531. AllocStr(
  1532. IN LPCTSTR pszStr
  1533. )
  1534. {
  1535. LPTSTR pszRet = NULL;
  1536. if ( pszStr && *pszStr ) {
  1537. pszRet = reinterpret_cast<LPTSTR>(LocalAllocMem((lstrlen(pszStr) + 1) * sizeof(*pszRet)));
  1538. if ( pszRet )
  1539. lstrcpy(pszRet, pszStr);
  1540. }
  1541. return pszRet;
  1542. }
  1543. //
  1544. // For some reason these are needed by spllib when you use StrNCatBuf.
  1545. // This doesn't make any sense, but just implement them.
  1546. //
  1547. extern "C"
  1548. LPVOID
  1549. DllAllocSplMem(
  1550. DWORD cbSize
  1551. )
  1552. {
  1553. return LocalAllocMem(cbSize);
  1554. }
  1555. HRESULT
  1556. TestPrintUpgOne(
  1557. IN LPCTSTR pszDriverModel,
  1558. IN LPCTSTR pszDriverPath,
  1559. IN LPCTSTR pszEnvironment,
  1560. IN LPCTSTR pszDriverTime,
  1561. IN LPCTSTR pszPrintUpgInf,
  1562. IN UINT uVersion,
  1563. IN BOOL bIsServer,
  1564. IN UINT uBlockingStatusInput,
  1565. IN LPCTSTR pszReplacementDriver,
  1566. IN BOOL bSuccess
  1567. )
  1568. {
  1569. HRESULT hRetval = E_FAIL;
  1570. UINT uBlockingStatus = 0;
  1571. TString strReplacementDriver;
  1572. FILETIME FileTimeDriver;
  1573. hRetval = pszDriverModel && pszDriverPath && pszEnvironment && pszDriverTime && pszPrintUpgInf && pszReplacementDriver ? S_OK : E_INVALIDARG;
  1574. if (SUCCEEDED(hRetval))
  1575. {
  1576. hRetval = StringTimeToFileTime(pszDriverTime, &FileTimeDriver);
  1577. }
  1578. //if (SUCCEEDED(hRetval))
  1579. //{
  1580. // hRetval = IsEnvironmentAndVersionNeededToCheck(pszEnvironment, uVersion);
  1581. //}
  1582. //if (S_OK == hRetval)
  1583. if (SUCCEEDED(hRetval))
  1584. {
  1585. DBG_MSG(DBG_TRACE, (_T("TEST case: Driver of time %s Expected status %d Expected Replacement \"%s\"\n"), pszDriverTime, uBlockingStatusInput, pszReplacementDriver));
  1586. hRetval = InternalCompatibleDriverCheck(pszDriverModel,
  1587. pszDriverPath,
  1588. pszEnvironment,
  1589. &FileTimeDriver,
  1590. pszPrintUpgInf,
  1591. uVersion,
  1592. bIsServer,
  1593. &uBlockingStatus,
  1594. &strReplacementDriver);
  1595. }
  1596. if (SUCCEEDED(hRetval))
  1597. {
  1598. hRetval = ((uBlockingStatusInput & BSP_BLOCKING_LEVEL_MASK) == (uBlockingStatus & BSP_BLOCKING_LEVEL_MASK)) ? S_OK : S_FALSE;
  1599. }
  1600. if ((S_OK == hRetval) && (BSP_PRINTER_DRIVER_OK != (uBlockingStatus & BSP_BLOCKING_LEVEL_MASK)))
  1601. {
  1602. hRetval = !lstrcmp(pszReplacementDriver, strReplacementDriver) ? S_OK : S_FALSE;
  1603. //
  1604. // we can not test whether BSP_INBOX_DRIVER_AVAILABLE is set
  1605. //
  1606. //if((S_OK == hRetval) && pszReplacemtDriver && *ppszReplacementDriver)
  1607. //{
  1608. // hRetval = (BSP_INBOX_DRIVER_AVAILABLE & uBlockingStatus) ? S_OK : S_FALSE;
  1609. //}
  1610. }
  1611. if (SUCCEEDED(hRetval))
  1612. {
  1613. hRetval = (((S_FALSE == hRetval) && !bSuccess) || (S_OK == hRetval) && bSuccess) ? S_OK : E_FAIL;
  1614. }
  1615. return hRetval;
  1616. }
  1617. TCHAR szModel1[] = _T("HP LaserJet 4");
  1618. TCHAR szModel2[] = _T("HP LaserJet 4P");
  1619. TCHAR szModel3[] = _T("");
  1620. TCHAR szModel4[] = _T("HP LaserJet 4M Plus");
  1621. TCHAR szModel5[] = _T("HP LaserJet 4Si");
  1622. TCHAR szModel6[] = _T("HP LaserJet 4PPP");
  1623. TCHAR szModel7[] = _T("Lexmark Optra T612");
  1624. TCHAR szModel8[] = _T("HP LaserJet 4V");
  1625. TCHAR szModel9[] = _T("Apple LaserJet 400PS");
  1626. TCHAR szModel0[] = _T("HP Laserjet 4Si mx");
  1627. TCHAR szDriverPath1[] = _T("H:\\WINDOWS\\system32\\spool\\drivers\\w32x86\\3\\ps5ui.dll");
  1628. TCHAR szDriverPath2[] = _T("pscript5.dll");
  1629. TCHAR szDriverPath3[] = _T("H:\\WINDOWS\\system32\\spool\\drivers\\w32x86\\3\\ps5ui.dll");
  1630. TCHAR szDriverPath4[] = _T("psCrIpt5.dll");
  1631. TCHAR szDriverPath5[] = _T("ps5ui.dll");
  1632. TCHAR szEnvironment1[] = _T("Windows NT x86");
  1633. TCHAR szEnvironment2[] = _T("Windows 4.0");
  1634. TCHAR szEnvironment3[] = _T("Windows IA64");
  1635. TCHAR szEnvironment4[] = _T("Windows XP");
  1636. TCHAR szDriverTime1[] = _T("11/27/1999");
  1637. TCHAR szDriverTime2[] = _T("11/27/2999");
  1638. TCHAR szDriverTime3[] = _T("11/27/2001");
  1639. TCHAR szDriverTime4[] = _T("10/27/1999");
  1640. TCHAR szDriverTime5[] = _T("11/28/1998");
  1641. TCHAR szDriverTime6[] = _T("11/28/1999");
  1642. TCHAR szDriverTime7[] = _T("10/28/1999");
  1643. DWORD dwStatus1 = BSP_PRINTER_DRIVER_OK;
  1644. DWORD dwStatus2 = BSP_PRINTER_DRIVER_WARNED;
  1645. DWORD dwStatus3 = BSP_PRINTER_DRIVER_BLOCKED;
  1646. TCHAR cszUpgradeInf[] = _T("printupg.inf");
  1647. TCHAR cszPrintDriverMapping[] = _T("Printer Driver Mapping");
  1648. TCHAR cszVersion[] = _T("Version");
  1649. TCHAR cszExcludeSection[] = _T("Excluded Driver Files");
  1650. TCHAR cszPrintUpgInf[] = _T("\\\\lzhu0\\zdrive\\sdroot\\printscan\\print\\spooler\\test\\printupg\\printupg.inf");
  1651. HRESULT
  1652. TestPrintUpgAll(
  1653. VOID
  1654. )
  1655. {
  1656. HRESULT hRetval = S_OK;
  1657. const struct PrintUpgTest aPrintUpgTests [] =
  1658. {
  1659. //
  1660. // model driverPath environment drivertime ver isServer status replacement isSuccess
  1661. //
  1662. {szModel1, szDriverPath1, szEnvironment1, szDriverTime4, 2, TRUE, dwStatus2, szModel1, TRUE},
  1663. {szModel1, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus3, szModel1, TRUE},
  1664. {szModel1, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus1, szModel1, TRUE},
  1665. {szModel1, szDriverPath1, szEnvironment1, szDriverTime2, 2, TRUE, dwStatus1, szModel1, TRUE},
  1666. {szModel2, szDriverPath1, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus3, szModel6, TRUE},
  1667. {szModel2, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus2, szModel6, TRUE},
  1668. {szModel2, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus1, szModel6, TRUE},
  1669. {szModel2, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus1, szModel1, TRUE},
  1670. {szModel1, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus2, szModel1, FALSE},
  1671. {szModel1, szDriverPath1, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus3, szModel1, FALSE},
  1672. {szModel1, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus2, szModel1, FALSE},
  1673. {szModel1, szDriverPath1, szEnvironment1, szDriverTime2, 2, TRUE, dwStatus3, szModel1, FALSE},
  1674. {szModel2, szDriverPath1, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus3, szModel1, FALSE},
  1675. {szModel2, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus2, szModel6, FALSE},
  1676. {szModel2, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus1, szModel6, FALSE},
  1677. {szModel2, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus2, szModel1, FALSE},
  1678. //
  1679. // case 16 is next
  1680. //
  1681. {szModel7, szDriverPath1, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus3, szModel3, TRUE},
  1682. {szModel7, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus2, szModel3, TRUE},
  1683. {szModel7, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus1, szModel3, TRUE},
  1684. {szModel7, szDriverPath1, szEnvironment1, szDriverTime2, 2, TRUE, dwStatus1, szModel3, TRUE},
  1685. {szModel8, szDriverPath1, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus2, szModel3, TRUE},
  1686. {szModel8, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus3, szModel3, TRUE},
  1687. {szModel8, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus1, szModel3, TRUE},
  1688. {szModel8, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus1, szModel3, TRUE},
  1689. {szModel7, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus3, szModel7, FALSE},
  1690. {szModel7, szDriverPath1, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus2, szModel7, FALSE},
  1691. {szModel7, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus2, szModel7, FALSE},
  1692. {szModel7, szDriverPath1, szEnvironment1, szDriverTime2, 2, TRUE, dwStatus3, szModel7, FALSE},
  1693. {szModel8, szDriverPath1, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus2, szModel7, FALSE},
  1694. {szModel8, szDriverPath1, szEnvironment1, szDriverTime2, 2, FALSE, dwStatus3, szModel8, FALSE},
  1695. {szModel8, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus1, szModel8, FALSE},
  1696. {szModel8, szDriverPath1, szEnvironment1, szDriverTime1, 2, FALSE, dwStatus2, szModel7, FALSE},
  1697. //
  1698. // case 32 is next
  1699. //
  1700. {szModel4, szDriverPath2, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus3, szModel4, FALSE},
  1701. {szModel4, szDriverPath5, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus3, szModel4, FALSE},
  1702. {szModel4, szDriverPath5, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus2, szModel4, FALSE},
  1703. {szModel4, szDriverPath4, szEnvironment1, szDriverTime1, 2, TRUE, dwStatus1, szModel7, TRUE},
  1704. {szModel4, szDriverPath1, szEnvironment1, szDriverTime1, 3, TRUE, dwStatus3, szModel4, TRUE},
  1705. {szModel4, szDriverPath1, szEnvironment1, szDriverTime1, 3, FALSE, dwStatus2, szModel4, TRUE},
  1706. {szModel4, szDriverPath1, szEnvironment1, szDriverTime2, 3, FALSE, dwStatus1, szModel4, TRUE},
  1707. {szModel4, szDriverPath1, szEnvironment1, szDriverTime2, 3, TRUE, dwStatus1, szModel4, TRUE},
  1708. {szModel4, szDriverPath1, szEnvironment1, szDriverTime1, 3, FALSE, dwStatus3, szModel4, FALSE},
  1709. {szModel4, szDriverPath1, szEnvironment1, szDriverTime1, 3, TRUE, dwStatus2, szModel4, FALSE},
  1710. {szModel4, szDriverPath1, szEnvironment1, szDriverTime2, 3, FALSE, dwStatus2, szModel4, FALSE},
  1711. {szModel4, szDriverPath1, szEnvironment1, szDriverTime2, 3, TRUE, dwStatus3, szModel4, FALSE},
  1712. {szModel0, szDriverPath1, szEnvironment1, szDriverTime1, 3, TRUE, dwStatus3, szModel3, TRUE},
  1713. {szModel0, szDriverPath1, szEnvironment1, szDriverTime1, 3, FALSE, dwStatus2, szModel3, TRUE},
  1714. {szModel0, szDriverPath1, szEnvironment1, szDriverTime2, 3, FALSE, dwStatus1, szModel3, TRUE},
  1715. {szModel0, szDriverPath1, szEnvironment1, szDriverTime2, 3, TRUE, dwStatus1, szModel3, TRUE},
  1716. //
  1717. // case 48 is next
  1718. //
  1719. {szModel4, szDriverPath1, szEnvironment3, szDriverTime1, 3, TRUE, dwStatus2, szModel8, FALSE},
  1720. {szModel4, szDriverPath1, szEnvironment3, szDriverTime1, 3, FALSE, dwStatus2, szModel2, TRUE},
  1721. {szModel4, szDriverPath1, szEnvironment3, szDriverTime2, 3, FALSE, dwStatus1, szModel8, TRUE},
  1722. {szModel4, szDriverPath1, szEnvironment3, szDriverTime2, 3, TRUE, dwStatus1, szModel8, TRUE},
  1723. {szModel4, szDriverPath1, szEnvironment3, szDriverTime1, 3, FALSE, dwStatus2, szModel8, FALSE},
  1724. {szModel4, szDriverPath1, szEnvironment3, szDriverTime1, 3, TRUE, dwStatus3, szModel8, FALSE},
  1725. {szModel4, szDriverPath1, szEnvironment3, szDriverTime2, 3, FALSE, dwStatus2, szModel8, FALSE},
  1726. {szModel4, szDriverPath1, szEnvironment3, szDriverTime2, 3, TRUE, dwStatus3, szModel8, FALSE},
  1727. {szModel5, szDriverPath1, szEnvironment3, szDriverTime1, 3, TRUE, dwStatus3, szModel3, TRUE},
  1728. {szModel5, szDriverPath1, szEnvironment3, szDriverTime1, 3, FALSE, dwStatus2, szModel3, TRUE},
  1729. {szModel5, szDriverPath1, szEnvironment3, szDriverTime2, 3, FALSE, dwStatus1, szModel3, TRUE},
  1730. {szModel5, szDriverPath1, szEnvironment3, szDriverTime2, 3, TRUE, dwStatus1, szModel3, TRUE},
  1731. {szModel5, szDriverPath1, szEnvironment2, szDriverTime1, 3, TRUE, dwStatus1, szModel3, TRUE},
  1732. {szModel5, szDriverPath1, szEnvironment3, szDriverTime1, 1, FALSE, dwStatus2, szModel3, FALSE},
  1733. {szModel9, szDriverPath1, szEnvironment1, szDriverTime2, 3, FALSE, dwStatus1, szModel3, TRUE},
  1734. {szModel9, szDriverPath1, szEnvironment1, szDriverTime2, 3, TRUE, dwStatus2, szModel3, FALSE},
  1735. //
  1736. // case 64 is next
  1737. //
  1738. {szModel4, szDriverPath1, szEnvironment3, szDriverTime1, 2, TRUE, dwStatus3, szModel8, TRUE},
  1739. {szModel4, szDriverPath1, szEnvironment3, szDriverTime1, 3, FALSE, dwStatus2, szModel2, TRUE},
  1740. {szModel1, szDriverPath1, szEnvironment1, szDriverTime5, 2, TRUE, dwStatus3, szModel1, TRUE},
  1741. {szModel1, szDriverPath1, szEnvironment1, szDriverTime6, 2, TRUE, dwStatus2, szModel1, TRUE},
  1742. {szModel1, szDriverPath1, szEnvironment1, szDriverTime7, 2, TRUE, dwStatus2, szModel1, TRUE},
  1743. {szModel2, szDriverPath1, szEnvironment3, szDriverTime2, 3, TRUE, dwStatus2, szModel3, TRUE},
  1744. {szModel2, szDriverPath1, szEnvironment3, szDriverTime2, 3, FALSE, dwStatus3, szModel3, TRUE},
  1745. {szModel2, szDriverPath1, szEnvironment4, szDriverTime2, 3, FALSE, dwStatus1, szModel3, TRUE},
  1746. {szModel2, szDriverPath1, szEnvironment3, szDriverTime2, 4, FALSE, dwStatus1, szModel3, TRUE},
  1747. };
  1748. DBG_MSG(DBG_TRACE, (L"tests started\n"));
  1749. for (int i = 0; SUCCEEDED(hRetval) && i < COUNTOF(aPrintUpgTests); i++)
  1750. {
  1751. DBG_MSG(DBG_TRACE, (_T("************************ %d **********************\n"), i));
  1752. hRetval = TestPrintUpgOne(aPrintUpgTests[i].pszDriverModel,
  1753. aPrintUpgTests[i].pszDriverPath,
  1754. aPrintUpgTests[i].pszEnvironment,
  1755. aPrintUpgTests[i].pszDriverTime,
  1756. cszPrintUpgInf,
  1757. aPrintUpgTests[i].uVersion,
  1758. aPrintUpgTests[i].bIsServer,
  1759. aPrintUpgTests[i].uBlockingStatus,
  1760. aPrintUpgTests[i].pszReplacementDriver,
  1761. aPrintUpgTests[i].bSuccess);
  1762. }
  1763. DBG_MSG(DBG_TRACE, (L"tests ended\n"));
  1764. return hRetval;
  1765. }
  1766. #endif // DBG_PRINTUPG