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

882 lines
21 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. catalog.cxx
  5. Abstract:
  6. This module provides all the public exported APIs relating to the
  7. catalog-based Spooler Apis for the Local Print Provider
  8. AddDriverCatalog
  9. Author:
  10. Larry Zhu (LZhu) 30-Mar-2001 Created
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include "catalog.hxx"
  16. #include <spapip.h>
  17. #include "ssp.hxx"
  18. /*++
  19. Routine Name:
  20. LocalAddDriverCatalog
  21. Routine Description:
  22. This routine implements the private print provider interface AddDriverCatalog.
  23. Arguments:
  24. hPrinter - This must be a server handle
  25. dwLevel - DRIVER_INFCAT_INFO Level, only 1 and 2 is supported
  26. pvDriverInfCatInfo - Points to a DRIVER_INFCAT_INFO_X structure
  27. dwCatalogCopyFlags - Catalog file copy flags
  28. Return Value:
  29. A BOOL - TRUE if success; FALSE otherwise, Call GetLastError()
  30. to get the Error code
  31. --*/
  32. BOOL
  33. LocalAddDriverCatalog(
  34. IN HANDLE hPrinter,
  35. IN DWORD dwLevel,
  36. IN VOID *pvDriverInfCatInfo,
  37. IN DWORD dwCatalogCopyFlags
  38. )
  39. {
  40. HRESULT hRetval = E_FAIL;
  41. hRetval = hPrinter && pvDriverInfCatInfo ? S_OK : E_INVALIDARG;
  42. if (SUCCEEDED(hRetval))
  43. {
  44. hRetval = SplAddDriverCatalog(hPrinter,
  45. dwLevel,
  46. pvDriverInfCatInfo,
  47. dwCatalogCopyFlags) ? S_OK : GetLastErrorAsHResult();
  48. }
  49. if (FAILED(hRetval))
  50. {
  51. SetLastError(HRESULT_CODE(hRetval));
  52. }
  53. return SUCCEEDED(hRetval);
  54. }
  55. /*++
  56. Routine Name:
  57. SplAddDriverCatalog
  58. Routine Description:
  59. This is the Spl call for AddDriverCatalog.
  60. Arguments:
  61. hPrinter - This must be a server handle
  62. dwLevel - DRIVER_INFCAT_INFO Level, only 1 and 2 is supported
  63. pvDriverInfCatInfo - Points to a DRIVER_INFCAT_INFO_X structure
  64. dwCatalogCopyFlags - Catalog file copy flags
  65. Return Value:
  66. A BOOL - TRUE if success; FALSE otherwise, Call GetLastError()
  67. to get the Error code
  68. --*/
  69. BOOL
  70. SplAddDriverCatalog(
  71. IN HANDLE hPrinter,
  72. IN DWORD dwLevel,
  73. IN VOID *pvDriverInfCatInfo,
  74. IN DWORD dwCatalogCopyFlags
  75. )
  76. {
  77. HRESULT hRetval = E_FAIL;
  78. SPOOL *pSpool = reinterpret_cast<SPOOL*>(hPrinter);
  79. DBGMSG(DBG_TRACE, ("AddDriverCatalog\n"));
  80. hRetval = pSpool && (pSpool->TypeofHandle & PRINTER_HANDLE_SERVER) && pvDriverInfCatInfo ? S_OK : E_INVALIDARG;
  81. if (SUCCEEDED(hRetval))
  82. {
  83. EnterSplSem();
  84. hRetval = ValidateSpoolHandle(pSpool, 0) ? S_OK : GetLastErrorAsHResult();
  85. if (SUCCEEDED(hRetval))
  86. {
  87. hRetval = ValidateObjectAccess(SPOOLER_OBJECT_SERVER,
  88. SERVER_ACCESS_ADMINISTER,
  89. NULL, NULL, pSpool->pIniSpooler) ? S_OK : GetLastErrorAsHResult();
  90. }
  91. if (SUCCEEDED(hRetval))
  92. {
  93. hRetval = InternalAddDriverCatalog(hPrinter,
  94. dwLevel,
  95. pvDriverInfCatInfo,
  96. dwCatalogCopyFlags) ? S_OK : GetLastErrorAsHResult();;
  97. }
  98. LeaveSplSem();
  99. }
  100. if (FAILED(hRetval))
  101. {
  102. SetLastError(HRESULT_CODE(hRetval));
  103. }
  104. return SUCCEEDED(hRetval);
  105. }
  106. /*++
  107. Routine Name:
  108. CatalogAppendUniqueTag
  109. Routine Description:
  110. This routine makes the scratch directory unique w.r.t process id and thread
  111. id that executes this function.
  112. Arguments:
  113. cchBuffer - size of buffer in number of chars including the NULL
  114. terminating character
  115. pszBuffer - Points to the buffer
  116. Return Value:
  117. An HRESULT
  118. --*/
  119. HRESULT
  120. CatalogAppendUniqueTag(
  121. IN UINT cchBuffer,
  122. IN OUT PWSTR pszBuffer
  123. )
  124. {
  125. HRESULT hRetval = E_FAIL;
  126. DWORD dwPID = 0;
  127. DWORD dwTID = 0;
  128. DWORD cchLen = 0;
  129. hRetval = pszBuffer && cchBuffer ? S_OK : E_INVALIDARG;
  130. if (SUCCEEDED(hRetval))
  131. {
  132. cchLen = wcslen(pszBuffer);
  133. dwPID = GetCurrentProcessId();
  134. dwTID = GetCurrentThreadId();
  135. if ((pszBuffer[cchLen - 1] != L'\\') && (cchLen + 1 < cchBuffer - 1))
  136. {
  137. pszBuffer[cchLen++] = L'\\';
  138. pszBuffer[cchLen] = 0;
  139. }
  140. hRetval = cchBuffer > cchLen && SUCCEEDED(StringCchPrintf(pszBuffer + cchLen, cchBuffer - cchLen, L"%d_%d", dwPID, dwTID)) ? S_OK : HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  141. }
  142. return hRetval;
  143. }
  144. /*++
  145. Routine Name:
  146. CatalogGetScratchDirectory
  147. Routine Description:
  148. This routine returns the catalog scratch directory.
  149. Arguments:
  150. hPrinter - Server handle
  151. cchBuffer - Size of buffer in number of chars including the NULL
  152. character
  153. pszCatalogDir - Points to the buffer
  154. Return Value:
  155. An HRESULT
  156. --*/
  157. HRESULT
  158. CatalogGetScratchDirectory(
  159. IN HANDLE hPrinter,
  160. IN UINT cchBuffer,
  161. OUT PWSTR pszCatalogDir
  162. )
  163. {
  164. HRESULT hRetval = E_FAIL;
  165. DWORD dwNeeded = 0;
  166. hRetval = hPrinter && cchBuffer && pszCatalogDir ? S_OK : E_INVALIDARG;
  167. if (SUCCEEDED(hRetval))
  168. {
  169. hRetval = SplGetPrinterDriverDirectory(NULL, // local machine
  170. LOCAL_ENVIRONMENT,
  171. 1,
  172. reinterpret_cast<BYTE*>(pszCatalogDir),
  173. cchBuffer * sizeof(WCHAR),
  174. &dwNeeded,
  175. reinterpret_cast<SPOOL*>(hPrinter)->pIniSpooler) ? S_OK : GetLastErrorAsHResult();
  176. }
  177. if (SUCCEEDED(hRetval))
  178. {
  179. hRetval = CatalogAppendUniqueTag(cchBuffer, pszCatalogDir);
  180. }
  181. return hRetval;
  182. }
  183. /*++
  184. Routine Name:
  185. CatalogCopyFile
  186. Routine Description:
  187. This routine copies the catalog file to the scratch directory.
  188. Arguments:
  189. pszSourcePath - Source Path
  190. pszDestDir - Destination directory
  191. pszFileName - File name
  192. Return Value:
  193. An HRESULT
  194. --*/
  195. HRESULT
  196. CatalogCopyFile(
  197. IN PCWSTR pszSourcePath,
  198. IN PCWSTR pszDestDir,
  199. IN PCWSTR pszFileName
  200. )
  201. {
  202. HRESULT hRetval = E_FAIL;
  203. WCHAR szPath[MAX_PATH] = {0};
  204. hRetval = pszSourcePath && pszDestDir && pszFileName ? S_OK : E_INVALIDARG;
  205. if (SUCCEEDED(hRetval))
  206. {
  207. hRetval = SUCCEEDED(StringCchPrintf(szPath, COUNTOF(szPath), L"%s\\%s", pszDestDir, pszFileName)) ? S_OK : HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
  208. }
  209. if (SUCCEEDED(hRetval))
  210. {
  211. hRetval = CopyFile(pszSourcePath, szPath, FALSE) ? S_OK : GetLastErrorAsHResult();
  212. }
  213. return hRetval;
  214. }
  215. /*++
  216. Routine Name:
  217. CatalogCreateScratchDirectory
  218. Routine Description:
  219. This routine creates the catalog scratch directory. If the scratch
  220. directory already exists, this routine does nothing
  221. Arguments:
  222. pszScratchDir - Scratch directory
  223. Return Value:
  224. An HRESULT
  225. --*/
  226. HRESULT
  227. CatalogCreateScratchDirectory(
  228. IN PCWSTR pszScratchDir
  229. )
  230. {
  231. HRESULT hRetval = E_FAIL;
  232. hRetval = pszScratchDir ? S_OK : E_INVALIDARG;
  233. if (SUCCEEDED(hRetval) && !DirectoryExists(const_cast<PWSTR>(pszScratchDir)))
  234. {
  235. hRetval = CreateDirectoryWithoutImpersonatingUser(const_cast<PWSTR>(pszScratchDir)) ? S_OK : GetLastErrorAsHResult();
  236. }
  237. return hRetval;
  238. }
  239. /*++
  240. Routine Name:
  241. CatalogCleanUpScratchDirectory
  242. Routine Description:
  243. This routine cleans up the scratch directory and it does nothing when the
  244. scratch directory does not exist.
  245. Arguments:
  246. pszScratchDir - Scratch Path
  247. Return Value:
  248. An HRESULT
  249. --*/
  250. HRESULT
  251. CatalogCleanUpScratchDirectory(
  252. IN PCWSTR pszScratchDir
  253. )
  254. {
  255. HRESULT hRetval = E_FAIL;
  256. hRetval = pszScratchDir ? S_OK : E_INVALIDARG;
  257. if (SUCCEEDED(hRetval))
  258. {
  259. (void)DeleteAllFilesAndDirectory(const_cast<PWSTR>(pszScratchDir),
  260. FALSE);
  261. }
  262. return hRetval;
  263. }
  264. /*++
  265. Routine Name:
  266. CatalogCopyFileToDir
  267. Routine Description:
  268. This routine copy catalog files to a directory.
  269. Arguments:
  270. pszPath - Source Path
  271. pszDir - Destination directory
  272. Return Value:
  273. An HRESULT
  274. --*/
  275. CatalogCopyFileToDir(
  276. IN PCWSTR pszPath,
  277. IN PCWSTR pszDir
  278. )
  279. {
  280. HRESULT hRetval = E_FAIL;
  281. PCWSTR pszFileName = NULL;
  282. hRetval = pszPath && pszDir ? S_OK : E_FAIL;
  283. if (SUCCEEDED(hRetval))
  284. {
  285. hRetval = GetFileNamePart(pszPath, &pszFileName);
  286. }
  287. if (SUCCEEDED(hRetval))
  288. {
  289. hRetval = CatalogCopyFile(pszPath, pszDir, pszFileName);
  290. }
  291. return hRetval;
  292. }
  293. /*++
  294. Routine Name:
  295. CatalogCopyFilesByLevel
  296. Routine Description:
  297. This routine copy catalog files to a scratch directory.
  298. Arguments:
  299. dwLevel - DRIVER_INFCAT_INFO Level, only 1 and 2 is supported
  300. pvDriverInfCatInfo - Points to a DRIVER_INFCAT_INFO_X structure
  301. pszScratchDirectory - Catalog Scratch directory
  302. Return Value:
  303. An HRESULT
  304. --*/
  305. HRESULT
  306. CatalogCopyFilesByLevel(
  307. IN DWORD dwLevel,
  308. IN VOID *pvDriverInfCatInfo,
  309. IN PCWSTR pszScratchDirectory
  310. )
  311. {
  312. HRESULT hRetval = E_FAIL;
  313. hRetval = pvDriverInfCatInfo && pszScratchDirectory? S_OK : E_INVALIDARG;
  314. if (SUCCEEDED(hRetval))
  315. {
  316. switch (dwLevel)
  317. {
  318. case 1:
  319. hRetval = CatalogCopyFileToDir(reinterpret_cast<DRIVER_INFCAT_INFO_1*>(pvDriverInfCatInfo)->pszCatPath,
  320. pszScratchDirectory);
  321. break;
  322. case 2:
  323. hRetval = CatalogCopyFileToDir(reinterpret_cast<DRIVER_INFCAT_INFO_2*>(pvDriverInfCatInfo)->pszCatPath,
  324. pszScratchDirectory);
  325. if (SUCCEEDED(hRetval))
  326. {
  327. hRetval = CatalogCopyFileToDir(reinterpret_cast<DRIVER_INFCAT_INFO_2*>(pvDriverInfCatInfo)->pszInfPath,
  328. pszScratchDirectory);
  329. }
  330. break;
  331. default:
  332. hRetval = HRESULT_FROM_WIN32(ERROR_INVALID_LEVEL);
  333. break;
  334. }
  335. }
  336. return hRetval;
  337. }
  338. /*++
  339. Routine Name:
  340. CatalogInstallLevel1
  341. Routine Description:
  342. This routine installs driver catalog using CrypoAPI for level 1.
  343. Arguments:
  344. pDriverInfCatInfo1 - Points to a DRIVER_INFCAT_INFO_1 structure
  345. pszScratchDirectory - Catalog Scratch directory
  346. Return Value:
  347. An HRESULT
  348. --*/
  349. HRESULT
  350. CatalogInstallLevel1(
  351. IN DRIVER_INFCAT_INFO_1 *pDriverInfCatInfo1,
  352. IN BOOL bUseOriginalCatName,
  353. IN PCWSTR pszCatalogScratchDirectory
  354. )
  355. {
  356. HRESULT hRetval = E_FAIL;
  357. WCHAR szPath[MAX_PATH] = {0};
  358. PCWSTR pszFileName = NULL;
  359. TSSP ssp;
  360. hRetval = pDriverInfCatInfo1 && pszCatalogScratchDirectory ? S_OK : E_FAIL;
  361. if (SUCCEEDED(hRetval))
  362. {
  363. hRetval = ssp.IsValid();
  364. }
  365. if (SUCCEEDED(hRetval))
  366. {
  367. hRetval = GetFileNamePart(pDriverInfCatInfo1->pszCatPath, &pszFileName);
  368. }
  369. if (SUCCEEDED(hRetval))
  370. {
  371. hRetval = pszFileName && SUCCEEDED(StringCchPrintf(szPath, COUNTOF(szPath), L"%s\\%s", pszCatalogScratchDirectory, pszFileName)) ? S_OK : HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
  372. }
  373. if (SUCCEEDED(hRetval))
  374. {
  375. hRetval = ssp.VerifyCatalog(szPath);
  376. }
  377. if (SUCCEEDED(hRetval))
  378. {
  379. hRetval = ssp.AddCatalogDirect(szPath,
  380. bUseOriginalCatName ? pszFileName : pDriverInfCatInfo1->pszCatNameOnSystem);
  381. }
  382. return hRetval;
  383. }
  384. /*++
  385. Routine Name:
  386. CatalogInstallLevel2
  387. Routine Description:
  388. This routine installs driver catalog using setup api for level 2.
  389. Arguments:
  390. pDriverInfCatInfo2 - Points to a DRIVER_INFCAT_INFO_2 structure
  391. pszScratchDirectory - Catalog Scratch directory
  392. Return Value:
  393. An HRESULT
  394. --*/
  395. HRESULT
  396. CatalogInstallLevel2(
  397. IN DRIVER_INFCAT_INFO_2 *pDriverInfCatInfo2,
  398. IN PCWSTR pszCatalogScratchDirectory
  399. )
  400. {
  401. HRESULT hRetval = E_FAIL;
  402. WCHAR szPath[MAX_PATH] = {0};
  403. PCWSTR pszFileName = NULL;
  404. BOOL bIsSetupNonInteractive = TRUE;
  405. hRetval = pDriverInfCatInfo2 && pszCatalogScratchDirectory ? S_OK : E_FAIL;
  406. if (SUCCEEDED(hRetval))
  407. {
  408. hRetval = GetFileNamePart(pDriverInfCatInfo2->pszInfPath, &pszFileName);
  409. }
  410. if (SUCCEEDED(hRetval))
  411. {
  412. hRetval = pszFileName && SUCCEEDED(StringCchPrintf(szPath, COUNTOF(szPath), L"%s\\%s", pszCatalogScratchDirectory, pszFileName)) ? S_OK : HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
  413. }
  414. if (SUCCEEDED(hRetval))
  415. {
  416. hRetval = CatalogCopyOEMInf(szPath,
  417. pDriverInfCatInfo2->pszSrcLoc,
  418. pDriverInfCatInfo2->dwMediaType,
  419. pDriverInfCatInfo2->dwCopyStyle);
  420. }
  421. return hRetval;
  422. }
  423. /*++
  424. Routine Name:
  425. CatalogCopyOEMInf
  426. Routine Description:
  427. This routine installs driver catalog using setup api for level 2.
  428. Arguments:
  429. pszInfPath - Inf Path
  430. pszSrcLoc - Source location string
  431. dwMediaType - Media type, aka whether is WU/URL, or disk location
  432. dwCopyStyle - SetupCopyOEMInf CopyStyle
  433. Return Value:
  434. An HRESULT
  435. --*/
  436. HRESULT
  437. CatalogCopyOEMInf(
  438. IN PCWSTR pszInfPath,
  439. IN PCWSTR pszSrcLoc, OPTIONAL
  440. IN DWORD dwMediaType,
  441. IN DWORD dwCopyStyle
  442. )
  443. {
  444. HRESULT hRetval = E_FAIL;
  445. HMODULE hLibrary = NULL;
  446. PFuncSetupCopyOEMInfW pfnSetupCopyOEMInfW = NULL;
  447. PFuncpSetupModifyGlobalFlags pfnpSetupModifyGlobalFlags = NULL;
  448. hRetval = pszInfPath ? S_OK : E_INVALIDARG;
  449. if (SUCCEEDED(hRetval))
  450. {
  451. hLibrary = LoadLibrary(L"setupapi.dll");
  452. hRetval = hLibrary ? S_OK : GetLastErrorAsHResult();
  453. }
  454. if (SUCCEEDED(hRetval))
  455. {
  456. pfnSetupCopyOEMInfW = reinterpret_cast<PFuncSetupCopyOEMInfW>(GetProcAddress(hLibrary, "SetupCopyOEMInfW"));
  457. hRetval = pfnSetupCopyOEMInfW ? S_OK : GetLastErrorAsHResult();
  458. }
  459. if (SUCCEEDED(hRetval))
  460. {
  461. pfnpSetupModifyGlobalFlags = reinterpret_cast<PFuncpSetupModifyGlobalFlags>(GetProcAddress(hLibrary, "pSetupModifyGlobalFlags"));
  462. hRetval = pfnpSetupModifyGlobalFlags ? S_OK : GetLastErrorAsHResult();
  463. }
  464. if (SUCCEEDED(hRetval))
  465. {
  466. //
  467. // Prohibit all UIs and pSetupModifyGlobalFlags can not fail
  468. //
  469. (void)pfnpSetupModifyGlobalFlags(PSPGF_NONINTERACTIVE, PSPGF_NONINTERACTIVE);
  470. hRetval = pfnSetupCopyOEMInfW(pszInfPath,
  471. pszSrcLoc,
  472. dwMediaType,
  473. dwCopyStyle,
  474. NULL, 0, 0, NULL) ? S_OK : GetLastErrorAsHResult();
  475. }
  476. if (hLibrary)
  477. {
  478. (void)FreeLibrary(hLibrary);
  479. }
  480. return hRetval;
  481. }
  482. /*++
  483. Routine Name:
  484. CatalogInstallByLevel
  485. Routine Description:
  486. This routine installs driver catalog using CrypoAPI for level 1 and using
  487. setup api for level 2.
  488. Arguments:
  489. dwLevel - DRIVER_INFCAT_INFO Level, only 1 and 2 is supported
  490. pvDriverInfCatInfo - Points to a DRIVER_INFCAT_INFO_X structure
  491. dwCatalogCopyFlags - Catalog file copy flags
  492. pszScratchDirectory - Catalog Scratch directory
  493. Return Value:
  494. An HRESULT
  495. --*/
  496. HRESULT
  497. CatalogInstallByLevel(
  498. IN DWORD dwLevel,
  499. IN VOID *pvDriverInfCatInfo,
  500. IN DWORD dwCatalogCopyFlags,
  501. IN PCWSTR pszCatalogScratchDirectory
  502. )
  503. {
  504. HRESULT hRetval = E_FAIL;
  505. hRetval = pvDriverInfCatInfo && pszCatalogScratchDirectory? S_OK : E_INVALIDARG;
  506. if (SUCCEEDED(hRetval))
  507. {
  508. switch (dwLevel)
  509. {
  510. case 1:
  511. hRetval = CatalogInstallLevel1(reinterpret_cast<DRIVER_INFCAT_INFO_1*>(pvDriverInfCatInfo),
  512. dwCatalogCopyFlags & APDC_USE_ORIGINAL_CAT_NAME,
  513. pszCatalogScratchDirectory);
  514. break;
  515. case 2:
  516. hRetval = CatalogInstallLevel2(reinterpret_cast<DRIVER_INFCAT_INFO_2*>(pvDriverInfCatInfo),
  517. pszCatalogScratchDirectory);
  518. break;
  519. default:
  520. hRetval = HRESULT_FROM_WIN32(ERROR_INVALID_LEVEL);
  521. break;
  522. }
  523. }
  524. return hRetval;
  525. }
  526. /*++
  527. Routine Name:
  528. CatalogInstall
  529. Routine Description:
  530. This routine installs driver catalog.
  531. Arguments:
  532. dwLevel - DRIVER_INFCAT_INFO Level, only 1 and 2 is supported
  533. pvDriverInfCatInfo - Points to a DRIVER_INFCAT_INFO_X structure
  534. pszScratchDirectory - Catalog Scratch directory
  535. dwCatalogCopyFlags - Catalog file copy flags
  536. Return Value:
  537. An HRESULT
  538. --*/
  539. HRESULT
  540. CatalogInstall(
  541. IN DWORD dwLevel,
  542. IN VOID *pvDriverInfCatInfo,
  543. IN DWORD dwCatalogCopyFlags,
  544. IN PCWSTR pszScratchDirectory
  545. )
  546. {
  547. HRESULT hRetval = E_FAIL;
  548. HANDLE hToken = NULL;
  549. hRetval = pvDriverInfCatInfo && pszScratchDirectory? S_OK : E_INVALIDARG;
  550. if (SUCCEEDED(hRetval))
  551. {
  552. hRetval = CatalogCopyFilesByLevel(dwLevel, pvDriverInfCatInfo, pszScratchDirectory);
  553. }
  554. if (SUCCEEDED(hRetval))
  555. {
  556. hToken = RevertToPrinterSelf();
  557. hRetval = CatalogInstallByLevel(dwLevel, pvDriverInfCatInfo, dwCatalogCopyFlags, pszScratchDirectory);
  558. }
  559. if (hToken)
  560. {
  561. (void)ImpersonatePrinterClient(hToken);
  562. }
  563. return hRetval;
  564. }
  565. /*++
  566. Routine Name:
  567. InternalAddDriverCatalog
  568. Routine Description:
  569. This routine implements the private print provider interface AddDriverCatalog.
  570. Arguments:
  571. hPrinter - This must be a server handle
  572. dwLevel - DRIVER_INFCAT_INFO Level, only 1 and 2 is supported
  573. pvDriverInfCatInfo - Points to a DRIVER_INFCAT_INFO_X structure
  574. dwCatalogCopyFlags - Catalog file copy flags
  575. Return Value:
  576. A BOOL - TRUE if success; FALSE otherwise, Call GetLastError()
  577. to get the Error code
  578. --*/
  579. BOOL
  580. InternalAddDriverCatalog(
  581. IN HANDLE hPrinter,
  582. IN DWORD dwLevel,
  583. IN VOID *pvDriverInfCatInfo,
  584. IN DWORD dwCatalogCopyFlags
  585. )
  586. {
  587. HRESULT hRetval = E_FAIL;
  588. WCHAR szCatalogScratchDirectory[MAX_PATH] = {0};
  589. hRetval = hPrinter && pvDriverInfCatInfo ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  590. //
  591. // When in system context, we may not have permission to read the catalog
  592. // file, so we copy it to a scratch directory while still in impersonation
  593. // context
  594. //
  595. if (SUCCEEDED(hRetval))
  596. {
  597. hRetval = CatalogGetScratchDirectory(hPrinter, COUNTOF(szCatalogScratchDirectory), szCatalogScratchDirectory);
  598. if (FAILED(hRetval) && ERROR_INSUFFICIENT_BUFFER == HRESULT_CODE(hRetval))
  599. {
  600. hRetval = HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
  601. }
  602. }
  603. if (SUCCEEDED(hRetval))
  604. {
  605. hRetval = CatalogCreateScratchDirectory(szCatalogScratchDirectory);
  606. if (SUCCEEDED(hRetval))
  607. {
  608. hRetval = CatalogInstall(dwLevel, pvDriverInfCatInfo, dwCatalogCopyFlags, szCatalogScratchDirectory);
  609. }
  610. (void)CatalogCleanUpScratchDirectory(szCatalogScratchDirectory);
  611. }
  612. if (FAILED(hRetval))
  613. {
  614. SetLastError(HRESULT_CODE(hRetval));
  615. }
  616. return SUCCEEDED(hRetval);
  617. }