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.

3149 lines
87 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: catadnew.cpp
  8. //
  9. // Contents: Microsoft Internet Security Catalog Utilities
  10. //
  11. // Functions: CryptCATAdminAcquireContext
  12. // CryptCATAdminReleaseContext
  13. // CryptCATAdminAddCatalog
  14. // CryptCATAdminRemoveCatalog
  15. // CryptCATAdminEnumCatalogFromHash
  16. // CryptCATCatalogInfoFromContext
  17. // CryptCATAdminReleaseCatalogContext
  18. // CryptCATAdminResolveCatalogPath
  19. // CryptCATAdminPauseServiceForBackup
  20. // CryptCATAdminCalcHashFromFileHandle
  21. // I_CryptCatAdminMigrateToNewCatDB
  22. // CatAdminDllMain
  23. //
  24. // History: 01-Jan-2000 reidk created
  25. //
  26. //--------------------------------------------------------------------------
  27. #include "global.hxx"
  28. #include "cryptreg.h"
  29. #include "wintrust.h"
  30. #include "softpub.h"
  31. #include "eventlst.h"
  32. #include "sipguids.h"
  33. #include "mscat32.h"
  34. #include "catdb.h"
  35. #include "voidlist.h"
  36. #include "catutil.h"
  37. #include "..\..\common\catdbsvc\catdbcli.h"
  38. #include "errlog.h"
  39. //
  40. // default system guid for apps that just make calls to CryptCATAdminAddCatalog with
  41. // hCatAdmin == NULL...
  42. //
  43. // {127D0A1D-4EF2-11d1-8608-00C04FC295EE}
  44. //
  45. #define DEF_CAT_SUBSYS_ID \
  46. { \
  47. 0x127d0a1d, \
  48. 0x4ef2, \
  49. 0x11d1, \
  50. { 0x86, 0x8, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee } \
  51. }
  52. #define WSZ_CATALOG_FILE_BASE_DIRECTORY L"CatRoot"
  53. #define WSZ_DATABASE_FILE_BASE_DIRECTORY L"CatRoot2"
  54. #define WSZ_REG_FILES_NOT_TO_BACKUP L"System\\CurrentControlSet\\Control\\BackupRestore\\FilesNotToBackup"
  55. #define WSZ_REG_CATALOG_DATABASE_VALUE L"Catalog Database"
  56. #define WSZ_PATH_NOT_TO_BACKUP L"%SystemRoot%\\System32\\CatRoot2\\* /s\0"
  57. static WCHAR *gpwszDatabaseFileBaseDirectory = NULL;
  58. static WCHAR *gpwszCatalogFileBaseDirectory = NULL;
  59. #define WSZ_CATALOG_SUBSYTEM_SEARCH_STRING L"{????????????????????????????????????}"
  60. #define CATADMIN_LOGERR_LASTERR() ErrLog_LogError(NULL, \
  61. ERRLOG_CLIENT_ID_CATADMIN, \
  62. __LINE__, \
  63. 0, \
  64. FALSE, \
  65. FALSE);
  66. #define CATADMIN_SETERR_LOG_RETURN(x, y) SetLastError(x); \
  67. ErrLog_LogError(NULL, \
  68. ERRLOG_CLIENT_ID_CATADMIN, \
  69. __LINE__, \
  70. 0, \
  71. FALSE, \
  72. FALSE); \
  73. goto y;
  74. typedef struct CATALOG_INFO_CONTEXT_
  75. {
  76. HANDLE hMappedFile;
  77. BYTE *pbMappedFile;
  78. WCHAR *pwszCatalogFile;
  79. PCCTL_CONTEXT pCTLContext;
  80. BOOL fResultOfAdd;
  81. } CATALOG_INFO_CONTEXT;
  82. typedef struct CRYPT_CAT_ADMIN_
  83. {
  84. DWORD cbStruct;
  85. BOOL fUseDefSubSysId;
  86. LPWSTR pwszSubSysGUID;
  87. LPWSTR pwszCatalogFileDir; // full path to .cat files
  88. LPWSTR pwszDatabaseFileDir; // full path to CatDB file
  89. DWORD dwLastDBError;
  90. LIST CatalogInfoContextList;
  91. int nOpenCatInfoContexts;
  92. CRITICAL_SECTION CriticalSection;
  93. BOOL fCSInitialized;
  94. BOOL fCSEntered;
  95. HANDLE hClearCacheEvent;
  96. HANDLE hRegisterWaitForClearCache;
  97. BOOL fRegisteredForChangeNotification;
  98. } CRYPT_CAT_ADMIN;
  99. #define CATINFO_CONTEXT_ALLOCATION_SIZE 64
  100. LPWSTR ppwszFilesToDelete[] = {L"hashmast.cbd",
  101. L"hashmast.cbk",
  102. L"catmast.cbd",
  103. L"catmast.cbk",
  104. L"sysmast.cbd",
  105. L"sysmast.cbk"};
  106. #define NUM_FILES_TO_DELETE (sizeof(ppwszFilesToDelete) / \
  107. sizeof(ppwszFilesToDelete[0]))
  108. BOOL
  109. _CatAdminMigrateSingleDatabase(
  110. LPWSTR pwszDatabaseGUID);
  111. BOOL
  112. _CatAdminSetupDefaults(void);
  113. void
  114. _CatAdminCleanupDefaults(void);
  115. BOOL
  116. _CatAdminTimeStampFilesInSync(
  117. LPWSTR pwszDatabaseGUID,
  118. BOOL *pfInSync);
  119. BOOL
  120. _CatAdminRegisterForChangeNotification(
  121. CRYPT_CAT_ADMIN *pCatAdmin
  122. );
  123. BOOL
  124. _CatAdminFreeCachedCatalogs(
  125. CRYPT_CAT_ADMIN *pCatAdmin
  126. );
  127. VOID CALLBACK
  128. _CatAdminWaitOrTimerCallback(
  129. PVOID lpParameter,
  130. BOOLEAN TimerOrWaitFired
  131. );
  132. BOOL
  133. _CatAdminAddCatalogsToCache(
  134. CRYPT_CAT_ADMIN *pCatAdmin,
  135. LPWSTR pwszSubSysGUID,
  136. CRYPT_DATA_BLOB *pCryptDataBlob,
  137. LIST_NODE **ppFirstListNodeAdded
  138. );
  139. BOOL
  140. _CatAdminAddSingleCatalogToCache(
  141. CRYPT_CAT_ADMIN *pCatAdmin,
  142. LPWSTR pwszCatalog,
  143. LIST_NODE **ppListNodeAdded
  144. );
  145. BOOL
  146. _CatAdminMigrateCatalogDatabase(
  147. LPWSTR pwszFrom,
  148. LPWSTR pwszTo
  149. );
  150. void
  151. _CatAdminBToHex (
  152. LPBYTE pbDigest,
  153. DWORD iByte,
  154. LPWSTR pwszHashTag
  155. );
  156. BOOL
  157. _CatAdminCreateHashTag(
  158. BYTE *pbHash,
  159. DWORD cbHash,
  160. LPWSTR *ppwszHashTag,
  161. CRYPT_DATA_BLOB *pCryptDataBlob
  162. );
  163. BOOL
  164. _CatAdminRecursiveCreateDirectory(
  165. IN LPCWSTR pwszDir,
  166. LPSECURITY_ATTRIBUTES lpSecurityAttributes
  167. );
  168. LPWSTR
  169. _CatAdminCreatePath(
  170. IN LPCWSTR pwsz1,
  171. IN LPCWSTR pwsz2,
  172. IN BOOL fAddEndingSlash
  173. );
  174. void __RPC_FAR * __RPC_API MIDL_user_allocate(size_t len)
  175. {
  176. return(LocalAlloc(LMEM_ZEROINIT, len));
  177. }
  178. void __RPC_API MIDL_user_free(void __RPC_FAR * ptr)
  179. {
  180. if (ptr != NULL)
  181. {
  182. LocalFree(ptr);
  183. }
  184. }
  185. //---------------------------------------------------------------------------------------
  186. //
  187. // CryptCATAdminAcquireContext
  188. //
  189. //---------------------------------------------------------------------------------------
  190. BOOL WINAPI
  191. CryptCATAdminAcquireContext_Internal(
  192. HCATADMIN *phCatAdmin,
  193. const GUID *pgSubsystem,
  194. DWORD dwFlags,
  195. BOOL fCalledFromMigrate)
  196. {
  197. GUID gDefault = DEF_CAT_SUBSYS_ID;
  198. const GUID *pgCatroot = &gDefault;
  199. CRYPT_CAT_ADMIN *pCatAdmin = NULL;
  200. BOOL fRet = TRUE;
  201. DWORD dwErr = 0;
  202. WCHAR wszGUID[256];
  203. BOOL fInSync;
  204. //
  205. // Validata parameters
  206. //
  207. if (phCatAdmin == NULL)
  208. {
  209. CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
  210. }
  211. *phCatAdmin = NULL;
  212. //
  213. // Allocate a new CatAdmin state struct
  214. //
  215. if (NULL == (pCatAdmin = (CRYPT_CAT_ADMIN *) malloc(sizeof(CRYPT_CAT_ADMIN))))
  216. {
  217. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  218. }
  219. memset(pCatAdmin, 0, sizeof(CRYPT_CAT_ADMIN));
  220. pCatAdmin->cbStruct = sizeof(CRYPT_CAT_ADMIN);
  221. LIST_Initialize(&(pCatAdmin->CatalogInfoContextList));
  222. //
  223. // Check to see if caller specified the Catroot dir to use
  224. //
  225. if (pgSubsystem == NULL)
  226. {
  227. pCatAdmin->fUseDefSubSysId = TRUE;
  228. }
  229. else
  230. {
  231. pgCatroot = pgSubsystem;
  232. }
  233. guid2wstr(pgCatroot, wszGUID);
  234. //
  235. // Initialize the critical section
  236. //
  237. __try
  238. {
  239. InitializeCriticalSection(&(pCatAdmin->CriticalSection));
  240. }
  241. __except(EXCEPTION_EXECUTE_HANDLER)
  242. {
  243. SetLastError(GetExceptionCode());
  244. CATADMIN_LOGERR_LASTERR()
  245. goto ErrorReturn;
  246. }
  247. pCatAdmin->fCSInitialized = TRUE;
  248. pCatAdmin->fCSEntered = FALSE;
  249. //
  250. // Save a copy of the GUID as a string
  251. //
  252. if (NULL == (pCatAdmin->pwszSubSysGUID = (LPWSTR)
  253. malloc((wcslen(wszGUID) + 1) * sizeof(WCHAR))))
  254. {
  255. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  256. }
  257. wcscpy(pCatAdmin->pwszSubSysGUID, wszGUID);
  258. //
  259. // Get the complete paths for the catalog files and the db file
  260. //
  261. if (NULL == (pCatAdmin->pwszCatalogFileDir = _CatAdminCreatePath(
  262. gpwszCatalogFileBaseDirectory,
  263. wszGUID,
  264. TRUE)))
  265. {
  266. CATADMIN_LOGERR_LASTERR()
  267. goto ErrorReturn;
  268. }
  269. if (NULL == (pCatAdmin->pwszDatabaseFileDir = _CatAdminCreatePath(
  270. gpwszDatabaseFileBaseDirectory,
  271. wszGUID,
  272. TRUE)))
  273. {
  274. CATADMIN_LOGERR_LASTERR()
  275. goto ErrorReturn;
  276. }
  277. //
  278. // Make sure catalog file and database file sub-directories exists
  279. //
  280. if (!_CatAdminRecursiveCreateDirectory(
  281. pCatAdmin->pwszCatalogFileDir,
  282. NULL))
  283. {
  284. CATADMIN_LOGERR_LASTERR()
  285. goto ErrorReturn;
  286. }
  287. if (!_CatAdminRecursiveCreateDirectory(
  288. pCatAdmin->pwszDatabaseFileDir,
  289. NULL))
  290. {
  291. CATADMIN_LOGERR_LASTERR()
  292. goto ErrorReturn;
  293. }
  294. //
  295. // Create the event which is notified when the catalog db changes, and register
  296. // a callback for when the event is signaled
  297. //
  298. if (NULL == (pCatAdmin->hClearCacheEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
  299. {
  300. CATADMIN_LOGERR_LASTERR()
  301. goto ErrorCreateEvent;
  302. }
  303. if (!RegisterWaitForSingleObject(
  304. &(pCatAdmin->hRegisterWaitForClearCache),
  305. pCatAdmin->hClearCacheEvent,
  306. _CatAdminWaitOrTimerCallback,
  307. pCatAdmin,
  308. INFINITE,
  309. WT_EXECUTEDEFAULT))
  310. {
  311. CATADMIN_LOGERR_LASTERR()
  312. goto ErrorRegisterWaitForSingleObject;
  313. }
  314. //
  315. // If we are being called by a real client (not the migrate code) then make sure
  316. // the TimeStamp files are in a consistent state, and if not, migrate (re-add)
  317. // the catalog files for that database
  318. //
  319. if (!fCalledFromMigrate)
  320. {
  321. if (_CatAdminTimeStampFilesInSync(wszGUID, &fInSync))
  322. {
  323. if (!fInSync)
  324. {
  325. //
  326. // FIX FIX - may need to migrate
  327. // all DBs if the wszGUID is DEF_CAT_SUBSYS_ID
  328. //
  329. if (!_CatAdminMigrateSingleDatabase(wszGUID))
  330. {
  331. CATADMIN_LOGERR_LASTERR()
  332. goto ErrorReturn;
  333. }
  334. }
  335. }
  336. else
  337. {
  338. CATADMIN_LOGERR_LASTERR()
  339. goto ErrorReturn;
  340. }
  341. }
  342. //
  343. // NOTE:
  344. // Defer registering with the service for the change notificatation so we
  345. // don't rely on the service during an acquire context
  346. //
  347. *phCatAdmin = (HCATADMIN)pCatAdmin;
  348. CommonReturn:
  349. return(fRet);
  350. ErrorReturn:
  351. if (pCatAdmin != NULL)
  352. {
  353. dwErr = GetLastError();
  354. if (pCatAdmin->hRegisterWaitForClearCache != NULL)
  355. {
  356. UnregisterWaitEx(
  357. pCatAdmin->hRegisterWaitForClearCache,
  358. INVALID_HANDLE_VALUE);
  359. }
  360. // call UnregisterWaitEx before deteling the critical section
  361. // because the cb thread tries to enter it
  362. if (pCatAdmin->fCSInitialized)
  363. {
  364. DeleteCriticalSection(&(pCatAdmin->CriticalSection));
  365. }
  366. if (pCatAdmin->hClearCacheEvent != NULL)
  367. {
  368. CloseHandle(pCatAdmin->hClearCacheEvent);
  369. }
  370. if (pCatAdmin->pwszSubSysGUID != NULL)
  371. {
  372. free(pCatAdmin->pwszSubSysGUID);
  373. }
  374. if (pCatAdmin->pwszCatalogFileDir != NULL)
  375. {
  376. free(pCatAdmin->pwszCatalogFileDir);
  377. }
  378. if (pCatAdmin->pwszDatabaseFileDir != NULL)
  379. {
  380. free(pCatAdmin->pwszDatabaseFileDir);
  381. }
  382. free(pCatAdmin);
  383. SetLastError(dwErr);
  384. }
  385. fRet = FALSE;
  386. goto CommonReturn;
  387. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
  388. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
  389. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorRegisterWaitForSingleObject)
  390. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCreateEvent)
  391. }
  392. BOOL WINAPI
  393. CryptCATAdminAcquireContext(
  394. OUT HCATADMIN *phCatAdmin,
  395. IN const GUID *pgSubsystem,
  396. IN DWORD dwFlags)
  397. {
  398. return (CryptCATAdminAcquireContext_Internal(
  399. phCatAdmin,
  400. pgSubsystem,
  401. dwFlags,
  402. FALSE));
  403. }
  404. //---------------------------------------------------------------------------------------
  405. //
  406. // CryptCATAdminReleaseContext
  407. //
  408. //---------------------------------------------------------------------------------------
  409. BOOL WINAPI
  410. CryptCATAdminReleaseContext(
  411. IN HCATADMIN hCatAdmin,
  412. IN DWORD dwFlags)
  413. {
  414. CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
  415. BOOL fRet = TRUE;
  416. int i = 0;
  417. LIST_NODE *pListNode = NULL;
  418. //
  419. // Validate input params
  420. //
  421. if ((pCatAdmin == NULL) ||
  422. (pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)))
  423. {
  424. CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
  425. }
  426. //
  427. // Un-Register for change notifications from DB process
  428. //
  429. // This needs to happen first thing, so that no callbacks
  430. // happen during cleanup
  431. //
  432. if (pCatAdmin->fRegisteredForChangeNotification)
  433. {
  434. Client_SSCatDBRegisterForChangeNotification(
  435. (DWORD_PTR) pCatAdmin->hClearCacheEvent,
  436. 0,
  437. pCatAdmin->pwszSubSysGUID,
  438. TRUE);
  439. }
  440. UnregisterWaitEx(pCatAdmin->hRegisterWaitForClearCache, INVALID_HANDLE_VALUE);
  441. CloseHandle(pCatAdmin->hClearCacheEvent);
  442. _CatAdminFreeCachedCatalogs(pCatAdmin);
  443. free(pCatAdmin->pwszSubSysGUID);
  444. free(pCatAdmin->pwszCatalogFileDir);
  445. free(pCatAdmin->pwszDatabaseFileDir);
  446. DeleteCriticalSection(&(pCatAdmin->CriticalSection));
  447. free(pCatAdmin);
  448. CommonReturn:
  449. return(fRet);
  450. ErrorReturn:
  451. fRet = FALSE;
  452. goto CommonReturn;
  453. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
  454. }
  455. //---------------------------------------------------------------------------------------
  456. //
  457. // CryptCATAdminAddCatalog
  458. //
  459. //---------------------------------------------------------------------------------------
  460. HCATINFO WINAPI
  461. CryptCATAdminAddCatalog(
  462. IN HCATADMIN hCatAdmin,
  463. IN WCHAR *pwszCatalogFile,
  464. IN WCHAR *pwszSelectBaseName,
  465. IN DWORD dwFlags)
  466. {
  467. CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
  468. CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
  469. BOOL fRet;
  470. LPWSTR pwszName = NULL;
  471. DWORD dwErr = 0;
  472. LPWSTR pwszCatalogNameUsed = NULL;
  473. LPWSTR pwszCatalogNameUsedCopy = NULL;
  474. LPWSTR pwszFullyQualifiedCatalogFile = NULL;
  475. DWORD dwLength = 0;
  476. LIST_NODE *pListNode = NULL;
  477. WCHAR wszTmp[1];
  478. if ((pCatAdmin == NULL) ||
  479. (pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)) ||
  480. (pwszCatalogFile == NULL) ||
  481. (dwFlags != 0))
  482. {
  483. CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
  484. }
  485. ErrLog_LogString(NULL, L"Adding Catalog File: ", pwszSelectBaseName, TRUE);
  486. //
  487. // first, check the catalog...
  488. //
  489. if (!(IsCatalogFile(INVALID_HANDLE_VALUE, pwszCatalogFile)))
  490. {
  491. if (GetLastError() == ERROR_FILE_NOT_FOUND)
  492. {
  493. CATADMIN_LOGERR_LASTERR()
  494. goto ErrorReturn;
  495. }
  496. CATADMIN_SETERR_LOG_RETURN(ERROR_BAD_FORMAT, ErrorBadFileFormat)
  497. }
  498. __try
  499. {
  500. EnterCriticalSection(&(pCatAdmin->CriticalSection));
  501. }
  502. __except(EXCEPTION_EXECUTE_HANDLER)
  503. {
  504. SetLastError(GetExceptionCode());
  505. CATADMIN_LOGERR_LASTERR()
  506. return NULL;
  507. }
  508. pCatAdmin->fCSEntered = TRUE;
  509. if (!_CatAdminRegisterForChangeNotification(pCatAdmin))
  510. {
  511. CATADMIN_LOGERR_LASTERR()
  512. goto ErrorReturn;
  513. }
  514. //
  515. // Clear the cache, since doing the add may change things
  516. //
  517. _CatAdminFreeCachedCatalogs(pCatAdmin);
  518. //
  519. // If the file name specified by pwszCatalogFile is not a fully qualified
  520. // path name, we need to build one before calling the service.
  521. //
  522. if ((wcschr(pwszCatalogFile, L'\\') == NULL) &&
  523. (wcschr(pwszCatalogFile, L':') == NULL))
  524. {
  525. dwLength = GetCurrentDirectoryW(1, wszTmp) * sizeof(WCHAR);
  526. dwLength += (wcslen(pwszCatalogFile) + 1) * sizeof(WCHAR);
  527. if (NULL == (pwszFullyQualifiedCatalogFile = (LPWSTR) malloc(dwLength)))
  528. {
  529. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  530. }
  531. if (!GetCurrentDirectoryW(
  532. dwLength / sizeof(WCHAR),
  533. pwszFullyQualifiedCatalogFile))
  534. {
  535. CATADMIN_LOGERR_LASTERR()
  536. goto ErrorReturn;
  537. }
  538. if ((pwszFullyQualifiedCatalogFile[wcslen(pwszFullyQualifiedCatalogFile) - 1]
  539. != L'\\'))
  540. {
  541. wcscat(pwszFullyQualifiedCatalogFile, L"\\");
  542. }
  543. wcscat(pwszFullyQualifiedCatalogFile, pwszCatalogFile);
  544. }
  545. //
  546. // Call the DB process to add the catalog
  547. //
  548. if (0 != (dwErr = Client_SSCatDBAddCatalog(
  549. 0,
  550. pCatAdmin->pwszSubSysGUID,
  551. (pwszFullyQualifiedCatalogFile != NULL) ?
  552. pwszFullyQualifiedCatalogFile :
  553. pwszCatalogFile,
  554. pwszSelectBaseName,
  555. &pwszCatalogNameUsed)))
  556. {
  557. CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorCatDBProcess)
  558. }
  559. //
  560. // Touch the TimeStamp file
  561. //
  562. TimeStampFile_Touch(pCatAdmin->pwszCatalogFileDir);
  563. //
  564. // create a psuedo list entry, that really isn't part of the list...
  565. // this is so the caller can call CryptCATCatalogInfoFromContext
  566. //
  567. if (NULL == (pwszCatalogNameUsedCopy = (LPWSTR)
  568. malloc((wcslen(pwszCatalogNameUsed) + 1) * sizeof(WCHAR))))
  569. {
  570. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  571. }
  572. wcscpy(pwszCatalogNameUsedCopy, pwszCatalogNameUsed);
  573. if (NULL == (pCatInfoContext = (CATALOG_INFO_CONTEXT *)
  574. malloc(sizeof(CATALOG_INFO_CONTEXT))))
  575. {
  576. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  577. }
  578. memset(pCatInfoContext, 0, sizeof(CATALOG_INFO_CONTEXT));
  579. pCatInfoContext->pwszCatalogFile = pwszCatalogNameUsedCopy;
  580. pCatInfoContext->fResultOfAdd = TRUE;
  581. if (NULL == (pListNode = (LIST_NODE *) malloc(sizeof(LIST_NODE))))
  582. {
  583. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  584. }
  585. memset(pListNode, 0, sizeof(LIST_NODE));
  586. pListNode->pElement = pCatInfoContext;
  587. CommonReturn:
  588. MIDL_user_free(pwszCatalogNameUsed);
  589. if (pwszFullyQualifiedCatalogFile != NULL)
  590. {
  591. free(pwszFullyQualifiedCatalogFile);
  592. }
  593. if ((pCatAdmin != NULL) &&
  594. (pCatAdmin->fCSEntered))
  595. {
  596. pCatAdmin->fCSEntered = FALSE;
  597. LeaveCriticalSection(&(pCatAdmin->CriticalSection));
  598. }
  599. ErrLog_LogString(NULL, L"DONE Adding Catalog File: ", pwszSelectBaseName, TRUE);
  600. return((HCATINFO) pListNode);
  601. ErrorReturn:
  602. if (pwszCatalogNameUsedCopy != NULL)
  603. {
  604. free(pwszCatalogNameUsedCopy);
  605. }
  606. if (pCatInfoContext != NULL)
  607. {
  608. free(pCatInfoContext);
  609. }
  610. goto CommonReturn;
  611. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
  612. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorBadFileFormat)
  613. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCatDBProcess)
  614. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
  615. }
  616. //---------------------------------------------------------------------------------------
  617. //
  618. // CryptCATAdminRemoveCatalog
  619. //
  620. //---------------------------------------------------------------------------------------
  621. BOOL WINAPI
  622. CryptCATAdminRemoveCatalog(
  623. IN HCATADMIN hCatAdmin,
  624. IN LPCWSTR pwszCatalogFile,
  625. IN DWORD dwFlags)
  626. {
  627. BOOL fRet = TRUE;
  628. DWORD dwErr = 0;
  629. CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
  630. //
  631. // Call the DB process to delete the catalog
  632. //
  633. if (0 != (dwErr = Client_SSCatDBDeleteCatalog(
  634. 0,
  635. pCatAdmin->pwszSubSysGUID,
  636. pwszCatalogFile)))
  637. {
  638. CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorCatDBProcess)
  639. }
  640. //
  641. // Touch the TimeStamp file
  642. //
  643. TimeStampFile_Touch(pCatAdmin->pwszCatalogFileDir);
  644. CommonReturn:
  645. return(fRet);
  646. ErrorReturn:
  647. fRet = FALSE;
  648. goto CommonReturn;
  649. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCatDBProcess)
  650. }
  651. //---------------------------------------------------------------------------------------
  652. //
  653. // CryptCATAdminEnumCatalogFromHash
  654. //
  655. //---------------------------------------------------------------------------------------
  656. HCATINFO WINAPI
  657. CryptCATAdminEnumCatalogFromHash(
  658. IN HCATADMIN hCatAdmin,
  659. IN BYTE *pbHash,
  660. IN DWORD cbHash,
  661. IN DWORD dwFlags,
  662. IN HCATINFO *phPrevCatInfo)
  663. {
  664. CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
  665. BOOL fFindFirstOnly;
  666. BOOL fInitializeEnum = FALSE;
  667. int i = 0;
  668. CRYPT_DATA_BLOB CryptDataBlobHash;
  669. CRYPT_DATA_BLOB CryptDataBlobHashTag;
  670. LPWSTR pwszSearch = NULL;
  671. HANDLE hFindHandle = INVALID_HANDLE_VALUE;
  672. WIN32_FIND_DATAW FindData;
  673. LPWSTR pwszHashTag = NULL;
  674. DWORD dwErr = 0;
  675. LIST_NODE *pPrevListNode = NULL;
  676. LIST_NODE *pListNodeToReturn = NULL;
  677. LIST_NODE *pListNode = NULL;
  678. CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
  679. //
  680. // Validate input params
  681. //
  682. if ((pCatAdmin == NULL) ||
  683. (pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)) ||
  684. (cbHash == 0) ||
  685. (cbHash > MAX_HASH_LEN) ||
  686. (dwFlags != 0))
  687. {
  688. CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
  689. }
  690. if (!_CatAdminRegisterForChangeNotification(pCatAdmin))
  691. {
  692. CATADMIN_LOGERR_LASTERR()
  693. goto ErrorReturn;
  694. }
  695. //
  696. // If phPrevCatInfo is NULL then that means the caller is only interested
  697. // in the first catalog that contains the hash, thus no enum state is
  698. // started. If phPrevCatInfo is non NULL, then it contains NULL, or a
  699. // HCATINFO that was returned from a previous call to
  700. // CryptCATAdminEnumCatalogFromHash. If it contains NULL, then this is
  701. // the start of an enum, otherwise it is enuming the next catalog containing
  702. // the hash.
  703. //
  704. if (phPrevCatInfo == NULL)
  705. {
  706. fFindFirstOnly = TRUE;
  707. }
  708. else
  709. {
  710. fFindFirstOnly = FALSE;
  711. pPrevListNode = (LIST_NODE *) *phPrevCatInfo;
  712. }
  713. //
  714. // Only allow one thread to view/modify at a time
  715. //
  716. __try
  717. {
  718. EnterCriticalSection(&(pCatAdmin->CriticalSection));
  719. }
  720. __except(EXCEPTION_EXECUTE_HANDLER)
  721. {
  722. SetLastError(GetExceptionCode());
  723. CATADMIN_LOGERR_LASTERR()
  724. return FALSE;
  725. }
  726. pCatAdmin->fCSEntered = TRUE;
  727. __try
  728. {
  729. //
  730. // This data blob is used to do the find in the database
  731. //
  732. CryptDataBlobHash.pbData = pbHash;
  733. CryptDataBlobHash.cbData = cbHash;
  734. //
  735. // Create the tag to be used for calls to CertFindSubjectInSortedCTL
  736. //
  737. if (!_CatAdminCreateHashTag(pbHash, cbHash, &pwszHashTag, &CryptDataBlobHashTag))
  738. {
  739. CATADMIN_LOGERR_LASTERR()
  740. goto ErrorReturn;
  741. }
  742. //
  743. // The enum works as follows:
  744. //
  745. // if enum-state is not being initialized OR this is the first call to start an enum
  746. //
  747. // loop through all currently cached catalogs until a catalog containing the
  748. // the hash is found, and return it
  749. //
  750. // if a catalog was not found in the cache, then call the DB process to try and
  751. // find one
  752. //
  753. // else (enum state has already been started)
  754. //
  755. // loop through currently cached catalogs, starting with the catalog just after
  756. // the current catalog, and until a catalog containing the hash is found
  757. //
  758. if ((fFindFirstOnly) || (pPrevListNode == NULL))
  759. {
  760. pListNode = LIST_GetFirst(&(pCatAdmin->CatalogInfoContextList));
  761. while (pListNode != NULL)
  762. {
  763. pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
  764. if (CertFindSubjectInSortedCTL(
  765. &CryptDataBlobHashTag,
  766. pCatInfoContext->pCTLContext,
  767. NULL,
  768. NULL,
  769. NULL))
  770. {
  771. pListNodeToReturn = pListNode;
  772. goto CommonReturn;
  773. }
  774. pListNode = LIST_GetNext(pListNode);
  775. }
  776. //
  777. // If we are here, that means we did not find a cached catalog that contained
  778. // the hash, so call the DB process to try and find one or more.
  779. //
  780. // Call the DB process once if we are not using the default sub-system ID,
  781. // otherwise call the DB process once for each sub-system.
  782. if (!pCatAdmin->fUseDefSubSysId)
  783. {
  784. if (_CatAdminAddCatalogsToCache(
  785. pCatAdmin,
  786. pCatAdmin->pwszSubSysGUID,
  787. &CryptDataBlobHash,
  788. &pListNodeToReturn))
  789. {
  790. if (pListNodeToReturn == NULL)
  791. {
  792. SetLastError(ERROR_NOT_FOUND);
  793. //CATADMIN_LOGERR_LASTERR()
  794. goto CatNotFound;
  795. }
  796. goto CommonReturn;
  797. }
  798. else
  799. {
  800. CATADMIN_LOGERR_LASTERR()
  801. goto ErrorReturn;
  802. }
  803. }
  804. else
  805. {
  806. //
  807. // For each subdir, add all the catalogs that contain the hash
  808. //
  809. //
  810. // Create search string to find all subdirs
  811. //
  812. if (NULL == (pwszSearch = _CatAdminCreatePath(
  813. gpwszDatabaseFileBaseDirectory,
  814. WSZ_CATALOG_SUBSYTEM_SEARCH_STRING,
  815. FALSE)))
  816. {
  817. CATADMIN_LOGERR_LASTERR()
  818. goto ErrorReturn;
  819. }
  820. //
  821. // Do the initial find
  822. //
  823. hFindHandle = FindFirstFileU(pwszSearch, &FindData);
  824. if (hFindHandle == INVALID_HANDLE_VALUE)
  825. {
  826. dwErr = GetLastError();
  827. //
  828. // no sub dirs found
  829. //
  830. if ((dwErr == ERROR_NO_MORE_FILES) ||
  831. (dwErr == ERROR_PATH_NOT_FOUND) ||
  832. (dwErr == ERROR_FILE_NOT_FOUND))
  833. {
  834. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_FOUND, CatNotFound)
  835. }
  836. else
  837. {
  838. goto ErrorFindFirstFile;
  839. }
  840. }
  841. while (1)
  842. {
  843. //
  844. // Only care about directories
  845. //
  846. if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  847. {
  848. //
  849. // Add all the catalogs in this subdir that contain the hash to
  850. // the catalog cache
  851. //
  852. if (!_CatAdminAddCatalogsToCache(
  853. pCatAdmin,
  854. FindData.cFileName,
  855. &CryptDataBlobHash,
  856. (pListNodeToReturn == NULL) ?
  857. &pListNodeToReturn : NULL))
  858. {
  859. CATADMIN_LOGERR_LASTERR()
  860. goto ErrorReturn;
  861. }
  862. }
  863. //
  864. // Get next subdir
  865. //
  866. if (!FindNextFileU(hFindHandle, &FindData))
  867. {
  868. if (GetLastError() == ERROR_NO_MORE_FILES)
  869. {
  870. break;
  871. }
  872. else
  873. {
  874. goto ErrorFindNextFile;
  875. }
  876. }
  877. }
  878. if (pListNodeToReturn == NULL)
  879. {
  880. SetLastError(ERROR_NOT_FOUND);
  881. //CATADMIN_LOGERR_LASTERR()
  882. goto CatNotFound;
  883. }
  884. }
  885. }
  886. else
  887. {
  888. //
  889. // Enum state already started, so just search through the rest of the cached
  890. // catalogs to try and find one that contains the hash
  891. //
  892. pListNode = LIST_GetNext(pPrevListNode);
  893. while (pListNode != NULL)
  894. {
  895. pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
  896. if (CertFindSubjectInSortedCTL(
  897. &CryptDataBlobHashTag,
  898. pCatInfoContext->pCTLContext,
  899. NULL,
  900. NULL,
  901. NULL))
  902. {
  903. pListNodeToReturn = pListNode;
  904. goto CommonReturn;
  905. }
  906. pListNode = LIST_GetNext(pListNode);
  907. }
  908. //
  909. // If we get here that means no catalog was found
  910. //
  911. SetLastError(ERROR_NOT_FOUND);
  912. }
  913. }
  914. __except(EXCEPTION_EXECUTE_HANDLER)
  915. {
  916. CATADMIN_SETERR_LOG_RETURN(GetExceptionCode(), ErrorException)
  917. }
  918. CommonReturn:
  919. dwErr = GetLastError();
  920. if (pwszHashTag != NULL)
  921. {
  922. free(pwszHashTag);
  923. }
  924. if (pwszSearch != NULL)
  925. {
  926. free(pwszSearch);
  927. }
  928. if (hFindHandle != INVALID_HANDLE_VALUE)
  929. {
  930. FindClose(hFindHandle);
  931. }
  932. if (pListNodeToReturn != NULL)
  933. {
  934. pCatAdmin->nOpenCatInfoContexts++;
  935. }
  936. if (pPrevListNode != NULL)
  937. {
  938. *phPrevCatInfo = NULL;
  939. //
  940. // Decrement, since this is the equivalent of
  941. // calling CryptCATAdminReleaseCatalogContext
  942. //
  943. pCatAdmin->nOpenCatInfoContexts--;
  944. }
  945. if ((pCatAdmin != NULL) &&
  946. (pCatAdmin->fCSEntered))
  947. {
  948. pCatAdmin->fCSEntered = FALSE;
  949. LeaveCriticalSection(&(pCatAdmin->CriticalSection));
  950. }
  951. SetLastError(dwErr);
  952. return((HCATINFO) pListNodeToReturn);
  953. ErrorReturn:
  954. goto CommonReturn;
  955. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
  956. TRACE_ERROR_EX(DBG_SS_TRUST, CatNotFound)
  957. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
  958. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
  959. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorException)
  960. }
  961. //---------------------------------------------------------------------------------------
  962. //
  963. // CryptCATCatalogInfoFromContext
  964. //
  965. //---------------------------------------------------------------------------------------
  966. BOOL WINAPI
  967. CryptCATCatalogInfoFromContext(
  968. IN HCATINFO hCatInfo,
  969. IN OUT CATALOG_INFO *psCatInfo,
  970. IN DWORD dwFlags)
  971. {
  972. BOOL fRet = TRUE;
  973. LIST_NODE *pListNode = (LIST_NODE *) hCatInfo;
  974. CATALOG_INFO_CONTEXT *pContext = NULL;
  975. if ((pListNode == NULL) || (psCatInfo == NULL))
  976. {
  977. CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
  978. }
  979. pContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
  980. if (pContext->pwszCatalogFile != NULL)
  981. {
  982. if ((wcslen(pContext->pwszCatalogFile) + 1) > MAX_PATH)
  983. {
  984. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorTooLong)
  985. }
  986. wcscpy(psCatInfo->wszCatalogFile, pContext->pwszCatalogFile);
  987. }
  988. CommonReturn:
  989. return(fRet);
  990. ErrorReturn:
  991. fRet = FALSE;
  992. goto CommonReturn;
  993. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
  994. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorTooLong)
  995. }
  996. //---------------------------------------------------------------------------------------
  997. //
  998. // CryptCATAdminReleaseCatalogContext
  999. //
  1000. //---------------------------------------------------------------------------------------
  1001. BOOL WINAPI
  1002. CryptCATAdminReleaseCatalogContext(
  1003. IN HCATADMIN hCatAdmin,
  1004. IN HCATINFO hCatInfo,
  1005. IN DWORD dwFlags)
  1006. {
  1007. BOOL fRet = TRUE;
  1008. CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
  1009. LIST_NODE *pListNode = (LIST_NODE *) hCatInfo;
  1010. CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
  1011. if ((pCatAdmin == NULL) ||
  1012. (pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)) ||
  1013. (pListNode == NULL))
  1014. {
  1015. CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
  1016. }
  1017. //
  1018. // check to see if this is from and add operation, if so, then clean
  1019. // up allocated memory, otherwise, just decrement ref count
  1020. //
  1021. pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
  1022. if (pCatInfoContext->fResultOfAdd)
  1023. {
  1024. free(pCatInfoContext->pwszCatalogFile);
  1025. free(pCatInfoContext);
  1026. free(pListNode);
  1027. }
  1028. else
  1029. {
  1030. // FIX FIX - may need to be smarter about this... like verify
  1031. // the node is actually in the list.
  1032. pCatAdmin->nOpenCatInfoContexts--;
  1033. }
  1034. CommonReturn:
  1035. return(fRet);
  1036. ErrorReturn:
  1037. fRet = FALSE;
  1038. goto CommonReturn;
  1039. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam);
  1040. }
  1041. //---------------------------------------------------------------------------------------
  1042. //
  1043. // CryptCATAdminResolveCatalogPath
  1044. //
  1045. //---------------------------------------------------------------------------------------
  1046. BOOL WINAPI
  1047. CryptCATAdminResolveCatalogPath(
  1048. IN HCATADMIN hCatAdmin,
  1049. IN WCHAR *pwszCatalogFile,
  1050. IN OUT CATALOG_INFO *psCatInfo,
  1051. IN DWORD dwFlags)
  1052. {
  1053. BOOL fRet = TRUE;
  1054. CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
  1055. if ((pCatAdmin == NULL) ||
  1056. (pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)) ||
  1057. (pwszCatalogFile == NULL) ||
  1058. (psCatInfo == NULL) ||
  1059. (psCatInfo->cbStruct != sizeof(CATALOG_INFO)) ||
  1060. (dwFlags != 0))
  1061. {
  1062. CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
  1063. }
  1064. if ((wcslen(pCatAdmin->pwszCatalogFileDir) +
  1065. wcslen(pwszCatalogFile) +
  1066. 1) > MAX_PATH)
  1067. {
  1068. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorTooLong)
  1069. }
  1070. wcscpy(psCatInfo->wszCatalogFile, pCatAdmin->pwszCatalogFileDir);
  1071. wcscat(psCatInfo->wszCatalogFile, pwszCatalogFile);
  1072. CommonReturn:
  1073. return(fRet);
  1074. ErrorReturn:
  1075. fRet = FALSE;
  1076. goto CommonReturn;
  1077. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
  1078. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorTooLong)
  1079. }
  1080. //---------------------------------------------------------------------------------------
  1081. //
  1082. // CryptCATAdminPauseServiceForBackup
  1083. //
  1084. //---------------------------------------------------------------------------------------
  1085. BOOL WINAPI
  1086. CryptCATAdminPauseServiceForBackup(
  1087. IN DWORD dwFlags,
  1088. IN BOOL fResume)
  1089. {
  1090. BOOL fRet = TRUE;
  1091. DWORD dwErr = 0;
  1092. //
  1093. // Call the DB process to delete the catalog
  1094. //
  1095. if (0 != (dwErr = Client_SSCatDBPauseResumeService(
  1096. 0,
  1097. fResume)))
  1098. {
  1099. CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorCatDBProcess)
  1100. }
  1101. CommonReturn:
  1102. return(fRet);
  1103. ErrorReturn:
  1104. fRet = FALSE;
  1105. goto CommonReturn;
  1106. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCatDBProcess)
  1107. }
  1108. //---------------------------------------------------------------------------------------
  1109. //
  1110. // CryptCATAdminCalcHashFromFileHandle
  1111. //
  1112. //---------------------------------------------------------------------------------------
  1113. BOOL WINAPI
  1114. CryptCATAdminCalcHashFromFileHandle(
  1115. IN HANDLE hFile,
  1116. IN OUT DWORD *pcbHash,
  1117. IN BYTE *pbHash,
  1118. IN DWORD dwFlags)
  1119. {
  1120. BYTE *pbRet = NULL;
  1121. SIP_INDIRECT_DATA *pbIndirectData = NULL;
  1122. BOOL fRet;
  1123. GUID gSubject;
  1124. SIP_DISPATCH_INFO sSip;
  1125. if ((hFile == NULL) ||
  1126. (hFile == INVALID_HANDLE_VALUE) ||
  1127. (pcbHash == NULL) ||
  1128. (dwFlags != 0))
  1129. {
  1130. CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, InvalidParam)
  1131. }
  1132. if (!CryptSIPRetrieveSubjectGuidForCatalogFile(L"CATADMIN", hFile, &gSubject))
  1133. {
  1134. goto ErrorMemory;
  1135. }
  1136. memset(&sSip, 0x00, sizeof(SIP_DISPATCH_INFO));
  1137. sSip.cbSize = sizeof(SIP_DISPATCH_INFO);
  1138. if (!CryptSIPLoad(&gSubject, 0, &sSip))
  1139. {
  1140. CATADMIN_LOGERR_LASTERR()
  1141. goto SIPLoadError;
  1142. }
  1143. SIP_SUBJECTINFO sSubjInfo;
  1144. DWORD cbIndirectData;
  1145. memset(&sSubjInfo, 0x00, sizeof(SIP_SUBJECTINFO));
  1146. sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO);
  1147. sSubjInfo.DigestAlgorithm.pszObjId = (char *)CertAlgIdToOID(CALG_SHA1);
  1148. sSubjInfo.dwFlags = SPC_INC_PE_RESOURCES_FLAG |
  1149. SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG |
  1150. MSSIP_FLAGS_PROHIBIT_RESIZE_ON_CREATE;
  1151. sSubjInfo.pgSubjectType = &gSubject;
  1152. sSubjInfo.hFile = hFile;
  1153. sSubjInfo.pwsFileName = L"CATADMIN";
  1154. sSubjInfo.dwEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
  1155. cbIndirectData = 0;
  1156. sSip.pfCreate(&sSubjInfo, &cbIndirectData, NULL);
  1157. if (cbIndirectData == 0)
  1158. {
  1159. SetLastError(E_NOTIMPL);
  1160. //CATADMIN_LOGERR_LASTERR()
  1161. goto SIPError;
  1162. }
  1163. if (NULL == (pbIndirectData = (SIP_INDIRECT_DATA *) malloc(cbIndirectData)))
  1164. {
  1165. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  1166. }
  1167. if (!(sSip.pfCreate(&sSubjInfo, &cbIndirectData, pbIndirectData)))
  1168. {
  1169. if (GetLastError() == 0)
  1170. {
  1171. SetLastError(ERROR_INVALID_DATA);
  1172. }
  1173. CATADMIN_LOGERR_LASTERR()
  1174. goto SIPError;
  1175. }
  1176. if ((pbIndirectData->Digest.cbData == 0) ||
  1177. (pbIndirectData->Digest.cbData > MAX_HASH_LEN))
  1178. {
  1179. SetLastError( ERROR_INVALID_DATA );
  1180. goto SIPError;
  1181. }
  1182. if (NULL == (pbRet = (BYTE *) malloc(pbIndirectData->Digest.cbData)))
  1183. {
  1184. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  1185. }
  1186. memcpy(pbRet, pbIndirectData->Digest.pbData, pbIndirectData->Digest.cbData);
  1187. fRet = TRUE;
  1188. CommonReturn:
  1189. if (pbRet)
  1190. {
  1191. if (*pcbHash < pbIndirectData->Digest.cbData)
  1192. {
  1193. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1194. fRet = FALSE;
  1195. }
  1196. else if (pbHash)
  1197. {
  1198. memcpy(pbHash, pbRet, pbIndirectData->Digest.cbData);
  1199. }
  1200. *pcbHash = pbIndirectData->Digest.cbData;
  1201. free(pbRet);
  1202. }
  1203. if (pbIndirectData)
  1204. {
  1205. free(pbIndirectData);
  1206. }
  1207. if ((GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
  1208. (pbHash == NULL))
  1209. {
  1210. fRet = TRUE;
  1211. }
  1212. return(fRet);
  1213. ErrorReturn:
  1214. free(pbRet);
  1215. fRet = FALSE;
  1216. goto CommonReturn;
  1217. TRACE_ERROR_EX(DBG_SS_TRUST, SIPLoadError)
  1218. TRACE_ERROR_EX(DBG_SS_TRUST, SIPError)
  1219. TRACE_ERROR_EX(DBG_SS_TRUST, InvalidParam)
  1220. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
  1221. }
  1222. //---------------------------------------------------------------------------------------
  1223. //
  1224. // I_CryptCatAdminMigrateToNewCatDB
  1225. //
  1226. //---------------------------------------------------------------------------------------
  1227. BOOL WINAPI
  1228. I_CryptCatAdminMigrateToNewCatDB()
  1229. {
  1230. BOOL fRet = TRUE;
  1231. LPWSTR pwszSearchCatDirs = NULL;
  1232. LPWSTR pwszDeleteFile = NULL;
  1233. LPWSTR pwsz = NULL;
  1234. LPWSTR pwszMigrateFromDir = NULL;
  1235. HCATADMIN hCatAdmin = NULL;
  1236. GUID gDefault = DEF_CAT_SUBSYS_ID;
  1237. HANDLE hFindHandleCatDirs = INVALID_HANDLE_VALUE;
  1238. WIN32_FIND_DATAW FindDataCatDirs;
  1239. DWORD dwErr = 0;
  1240. HKEY hKey;
  1241. DWORD dwDisposition;
  1242. int i;
  1243. BOOL fInSync;
  1244. WCHAR wszGUID[256];
  1245. LPWSTR pwszCatalogFileDir = NULL;
  1246. LPWSTR pwszDatabaseFileDir = NULL;
  1247. //
  1248. // FIRST!!
  1249. //
  1250. // Clean up the old reg based catroot entry, and if needed, move
  1251. // the old style catalog database from its old directory to the new directory,
  1252. // then do the migrate from there
  1253. //
  1254. if (RegCreateKeyExU(
  1255. HKEY_LOCAL_MACHINE,
  1256. REG_MACHINE_SETTINGS_KEY,
  1257. 0,
  1258. NULL,
  1259. REG_OPTION_NON_VOLATILE,
  1260. KEY_ALL_ACCESS,
  1261. NULL,
  1262. &hKey,
  1263. &dwDisposition) == ERROR_SUCCESS)
  1264. {
  1265. DWORD dwType;
  1266. DWORD cbSize;
  1267. cbSize = 0;
  1268. RegQueryValueExU(
  1269. hKey,
  1270. WSZ_CATALOG_FILE_BASE_DIRECTORY,
  1271. NULL,
  1272. &dwType,
  1273. NULL,
  1274. &cbSize);
  1275. if (cbSize > 0)
  1276. {
  1277. if (NULL == (pwszMigrateFromDir = (LPWSTR)
  1278. malloc(sizeof(WCHAR) * ((cbSize / sizeof(WCHAR)) + 3))))
  1279. {
  1280. RegCloseKey(hKey);
  1281. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  1282. }
  1283. pwszMigrateFromDir[0] = NULL;
  1284. RegQueryValueExU(
  1285. hKey,
  1286. WSZ_CATALOG_FILE_BASE_DIRECTORY,
  1287. NULL,
  1288. &dwType,
  1289. (BYTE *)pwszMigrateFromDir,
  1290. &cbSize);
  1291. if (!_CatAdminMigrateCatalogDatabase(
  1292. pwszMigrateFromDir,
  1293. gpwszCatalogFileBaseDirectory))
  1294. {
  1295. RegCloseKey(hKey);
  1296. CATADMIN_LOGERR_LASTERR()
  1297. goto ErrorReturn;
  1298. }
  1299. RegDeleteValueU(hKey, WSZ_CATALOG_FILE_BASE_DIRECTORY);
  1300. }
  1301. RegCloseKey(hKey);
  1302. }
  1303. //
  1304. // NOW, that we are in a consistent state
  1305. //
  1306. // For each catalog sub-system, enumerate all catalogs and add them to the
  1307. // new catalog database under the same sub-system GUID.
  1308. //
  1309. //
  1310. // Create search string to find all catalog sub dirs
  1311. //
  1312. if (NULL == (pwszSearchCatDirs = _CatAdminCreatePath(
  1313. gpwszCatalogFileBaseDirectory,
  1314. WSZ_CATALOG_SUBSYTEM_SEARCH_STRING,
  1315. FALSE)))
  1316. {
  1317. CATADMIN_LOGERR_LASTERR()
  1318. goto ErrorReturn;
  1319. }
  1320. //
  1321. // Do the initial find
  1322. //
  1323. hFindHandleCatDirs = FindFirstFileU(pwszSearchCatDirs, &FindDataCatDirs);
  1324. if (hFindHandleCatDirs == INVALID_HANDLE_VALUE)
  1325. {
  1326. //
  1327. // See if a real error occurred, or just no files
  1328. //
  1329. dwErr = GetLastError();
  1330. if ((dwErr == ERROR_NO_MORE_FILES) ||
  1331. (dwErr == ERROR_PATH_NOT_FOUND) ||
  1332. (dwErr == ERROR_FILE_NOT_FOUND))
  1333. {
  1334. //
  1335. // There is nothing to do
  1336. //
  1337. SetLastError(0);
  1338. goto RegKeyAdd;
  1339. }
  1340. else
  1341. {
  1342. CATADMIN_LOGERR_LASTERR()
  1343. goto ErrorFindFirstFile;
  1344. }
  1345. }
  1346. while (1)
  1347. {
  1348. //
  1349. // Only care about directories
  1350. //
  1351. if (FindDataCatDirs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1352. {
  1353. _CatAdminMigrateSingleDatabase(FindDataCatDirs.cFileName);
  1354. }
  1355. //
  1356. // Get rid of old files
  1357. //
  1358. dwErr = GetLastError();
  1359. if (NULL != (pwsz = _CatAdminCreatePath(
  1360. gpwszCatalogFileBaseDirectory,
  1361. FindDataCatDirs.cFileName,
  1362. FALSE)))
  1363. {
  1364. for (i=0; i<NUM_FILES_TO_DELETE; i++)
  1365. {
  1366. if (NULL != (pwszDeleteFile = _CatAdminCreatePath(
  1367. pwsz,
  1368. ppwszFilesToDelete[i],
  1369. FALSE)))
  1370. {
  1371. if (!DeleteFileU(pwszDeleteFile))
  1372. {
  1373. //
  1374. // If delete fails, then log for delete after reboot
  1375. //
  1376. MoveFileExW(pwszDeleteFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  1377. }
  1378. free(pwszDeleteFile);
  1379. }
  1380. }
  1381. free(pwsz);
  1382. }
  1383. SetLastError(dwErr);
  1384. //
  1385. // Get next subdir
  1386. //
  1387. if (!FindNextFileU(hFindHandleCatDirs, &FindDataCatDirs))
  1388. {
  1389. if (GetLastError() == ERROR_NO_MORE_FILES)
  1390. {
  1391. SetLastError(0);
  1392. break;
  1393. }
  1394. else
  1395. {
  1396. CATADMIN_LOGERR_LASTERR()
  1397. goto ErrorFindNextFile;
  1398. }
  1399. }
  1400. }
  1401. //
  1402. // Get rid of old files
  1403. //
  1404. dwErr = GetLastError();
  1405. for (i=0; i<NUM_FILES_TO_DELETE; i++)
  1406. {
  1407. if (NULL != (pwszDeleteFile = _CatAdminCreatePath(
  1408. gpwszCatalogFileBaseDirectory,
  1409. ppwszFilesToDelete[i],
  1410. FALSE)))
  1411. {
  1412. if (!DeleteFileU(pwszDeleteFile))
  1413. {
  1414. //
  1415. // If delete fails, then log for delete after reboot
  1416. //
  1417. MoveFileExW(pwszDeleteFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  1418. }
  1419. free(pwszDeleteFile);
  1420. }
  1421. }
  1422. SetLastError(dwErr);
  1423. RegKeyAdd:
  1424. //
  1425. // Set reg key so backup does not backup the catroot2 directory
  1426. // which contains jet db files
  1427. //
  1428. if (RegCreateKeyExW(
  1429. HKEY_LOCAL_MACHINE,
  1430. WSZ_REG_FILES_NOT_TO_BACKUP,
  1431. 0,
  1432. NULL,
  1433. REG_OPTION_NON_VOLATILE,
  1434. KEY_ALL_ACCESS,
  1435. NULL,
  1436. &hKey,
  1437. &dwDisposition) == ERROR_SUCCESS)
  1438. {
  1439. if (RegSetValueExW(
  1440. hKey,
  1441. WSZ_REG_CATALOG_DATABASE_VALUE,
  1442. 0,
  1443. REG_MULTI_SZ,
  1444. (BYTE *) WSZ_PATH_NOT_TO_BACKUP,
  1445. (wcslen(WSZ_PATH_NOT_TO_BACKUP) + 2) * sizeof(WCHAR)) != ERROR_SUCCESS)
  1446. {
  1447. CATADMIN_LOGERR_LASTERR()
  1448. }
  1449. RegCloseKey(hKey);
  1450. }
  1451. else
  1452. {
  1453. CATADMIN_LOGERR_LASTERR()
  1454. }
  1455. //
  1456. // Force the default DB to be created
  1457. //
  1458. if (CryptCATAdminAcquireContext_Internal(
  1459. &hCatAdmin,
  1460. &gDefault,
  1461. NULL,
  1462. TRUE))
  1463. {
  1464. BYTE rgHash[20] = {0};
  1465. HCATINFO hCatInfo = NULL;
  1466. hCatInfo = CryptCATAdminEnumCatalogFromHash(
  1467. hCatAdmin,
  1468. rgHash,
  1469. 20,
  1470. 0,
  1471. NULL);
  1472. if (hCatInfo != NULL)
  1473. {
  1474. CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
  1475. }
  1476. CryptCATAdminReleaseContext(hCatAdmin, 0);
  1477. //
  1478. // Need to create the timestamp files if they don't exist
  1479. //
  1480. guid2wstr(&gDefault, wszGUID);
  1481. //
  1482. // Construct full subdir path to Catalog files TimeStamp location
  1483. //
  1484. if (NULL == (pwszCatalogFileDir = _CatAdminCreatePath(
  1485. gpwszCatalogFileBaseDirectory,
  1486. wszGUID,
  1487. FALSE)))
  1488. {
  1489. CATADMIN_LOGERR_LASTERR()
  1490. goto CommonReturn; // non fatal for the function, so don't error out
  1491. }
  1492. //
  1493. // Construct full subdir path to Database files TimeStamp location
  1494. //
  1495. if (NULL == (pwszDatabaseFileDir = _CatAdminCreatePath(
  1496. gpwszDatabaseFileBaseDirectory,
  1497. wszGUID,
  1498. FALSE)))
  1499. {
  1500. CATADMIN_LOGERR_LASTERR()
  1501. goto CommonReturn; // non fatal for the function, so don't error out
  1502. }
  1503. //
  1504. // See if they are in sync (if they don't exist, that equals out of sync)
  1505. //
  1506. if (TimeStampFile_InSync(
  1507. pwszCatalogFileDir,
  1508. pwszDatabaseFileDir,
  1509. &fInSync))
  1510. {
  1511. if (!fInSync)
  1512. {
  1513. TimeStampFile_Touch(pwszCatalogFileDir);
  1514. TimeStampFile_Touch(pwszDatabaseFileDir);
  1515. }
  1516. }
  1517. else
  1518. {
  1519. CATADMIN_LOGERR_LASTERR()
  1520. }
  1521. }
  1522. else
  1523. {
  1524. CATADMIN_LOGERR_LASTERR()
  1525. }
  1526. CommonReturn:
  1527. dwErr = GetLastError();
  1528. if (pwszMigrateFromDir != NULL)
  1529. {
  1530. free(pwszMigrateFromDir);
  1531. }
  1532. if (pwszSearchCatDirs != NULL)
  1533. {
  1534. free(pwszSearchCatDirs);
  1535. }
  1536. if (hFindHandleCatDirs != INVALID_HANDLE_VALUE)
  1537. {
  1538. FindClose(hFindHandleCatDirs);
  1539. }
  1540. if (pwszCatalogFileDir != NULL)
  1541. {
  1542. free(pwszCatalogFileDir);
  1543. }
  1544. if (pwszDatabaseFileDir != NULL)
  1545. {
  1546. free(pwszDatabaseFileDir);
  1547. }
  1548. SetLastError(dwErr);
  1549. return(fRet);
  1550. ErrorReturn:
  1551. fRet = FALSE;
  1552. goto CommonReturn;
  1553. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory);
  1554. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
  1555. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
  1556. }
  1557. //---------------------------------------------------------------------------------------
  1558. //
  1559. // _CatAdminMigrateSingleDatabase
  1560. //
  1561. //---------------------------------------------------------------------------------------
  1562. BOOL
  1563. _CatAdminMigrateSingleDatabase(
  1564. LPWSTR pwszDatabaseGUID)
  1565. {
  1566. BOOL fRet = TRUE;
  1567. LPWSTR pwszCatalogFile = NULL;
  1568. LPWSTR pwszSearchCatalogsInDir = NULL;
  1569. HANDLE hFindHandleCatalogsInDir = INVALID_HANDLE_VALUE;
  1570. WIN32_FIND_DATAW FindDataCatalogsInDir;
  1571. GUID guid;
  1572. HCATINFO hCatInfo = NULL;
  1573. HCATADMIN hCatAdmin = NULL;
  1574. DWORD dwErr = 0;
  1575. LPWSTR pwszSubDir = NULL;
  1576. LPWSTR pwszTempDir = NULL;
  1577. LPWSTR pwszTempCatalogFile = NULL;
  1578. //
  1579. // Acquire the catadmin context to add the catalog files to
  1580. //
  1581. if (!wstr2guid(pwszDatabaseGUID, &guid))
  1582. {
  1583. CATADMIN_LOGERR_LASTERR()
  1584. goto ErrorReturn;
  1585. }
  1586. if (!CryptCATAdminAcquireContext_Internal(&hCatAdmin, &guid, NULL, TRUE))
  1587. {
  1588. CATADMIN_LOGERR_LASTERR()
  1589. goto ErrorReturn;
  1590. }
  1591. //
  1592. // Construct full subdir path so we can search for all cat files
  1593. //
  1594. if (NULL == (pwszSubDir = _CatAdminCreatePath(
  1595. gpwszCatalogFileBaseDirectory,
  1596. pwszDatabaseGUID,
  1597. FALSE)))
  1598. {
  1599. CATADMIN_LOGERR_LASTERR()
  1600. goto ErrorReturn;
  1601. }
  1602. //
  1603. // Construct temp directory path, and create the directory to back it
  1604. //
  1605. if (NULL == (pwszTempDir = _CatAdminCreatePath(
  1606. pwszSubDir,
  1607. L"TempDir",
  1608. FALSE)))
  1609. {
  1610. CATADMIN_LOGERR_LASTERR()
  1611. goto ErrorReturn;
  1612. }
  1613. if (!_CatAdminRecursiveCreateDirectory(
  1614. pwszTempDir,
  1615. NULL))
  1616. {
  1617. CATADMIN_LOGERR_LASTERR()
  1618. goto ErrorReturn;
  1619. }
  1620. //
  1621. // Construct the search string
  1622. //
  1623. if (NULL == (pwszSearchCatalogsInDir = _CatAdminCreatePath(
  1624. pwszSubDir,
  1625. L"*",
  1626. FALSE)))
  1627. {
  1628. CATADMIN_LOGERR_LASTERR()
  1629. goto ErrorReturn;
  1630. }
  1631. //
  1632. // First copy all the catalogs to a temp directory, then add each catalog
  1633. // to the database from the temporary location
  1634. //
  1635. //
  1636. // Copy each file
  1637. //
  1638. memset(&FindDataCatalogsInDir, 0, sizeof(FindDataCatalogsInDir));
  1639. hFindHandleCatalogsInDir = FindFirstFileU(
  1640. pwszSearchCatalogsInDir,
  1641. &FindDataCatalogsInDir);
  1642. if (hFindHandleCatalogsInDir == INVALID_HANDLE_VALUE)
  1643. {
  1644. dwErr = GetLastError();
  1645. //
  1646. // no files found
  1647. //
  1648. if ((dwErr == ERROR_NO_MORE_FILES) ||
  1649. (dwErr == ERROR_FILE_NOT_FOUND))
  1650. {
  1651. SetLastError(0);
  1652. }
  1653. else
  1654. {
  1655. CATADMIN_LOGERR_LASTERR()
  1656. goto ErrorFindFirstFile;
  1657. }
  1658. }
  1659. else
  1660. {
  1661. while (1)
  1662. {
  1663. //
  1664. // Only care about files
  1665. //
  1666. if (!(FindDataCatalogsInDir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1667. {
  1668. //
  1669. // Construct fully qualified path name to catalog file
  1670. //
  1671. if (NULL == (pwszCatalogFile = _CatAdminCreatePath(
  1672. pwszSubDir,
  1673. FindDataCatalogsInDir.cFileName,
  1674. FALSE)))
  1675. {
  1676. CATADMIN_LOGERR_LASTERR()
  1677. goto ErrorReturn;
  1678. }
  1679. //
  1680. // Verify that this is a catalog and then copy it to the temp dir
  1681. // which is where it will be installed from
  1682. //
  1683. if (IsCatalogFile(NULL, pwszCatalogFile))
  1684. {
  1685. if (NULL == (pwszTempCatalogFile = _CatAdminCreatePath(
  1686. pwszTempDir,
  1687. FindDataCatalogsInDir.cFileName,
  1688. FALSE)))
  1689. {
  1690. CATADMIN_LOGERR_LASTERR()
  1691. goto ErrorReturn;
  1692. }
  1693. if (!CopyFileU(pwszCatalogFile, pwszTempCatalogFile, FALSE))
  1694. {
  1695. CATADMIN_LOGERR_LASTERR()
  1696. goto ErrorReturn;
  1697. }
  1698. free(pwszTempCatalogFile);
  1699. pwszTempCatalogFile = NULL;
  1700. }
  1701. free(pwszCatalogFile);
  1702. pwszCatalogFile = NULL;
  1703. }
  1704. //
  1705. // Get next catalog file
  1706. //
  1707. if (!FindNextFileU(hFindHandleCatalogsInDir, &FindDataCatalogsInDir))
  1708. {
  1709. if (GetLastError() == ERROR_NO_MORE_FILES)
  1710. {
  1711. SetLastError(0);
  1712. break;
  1713. }
  1714. else
  1715. {
  1716. CATADMIN_LOGERR_LASTERR()
  1717. goto ErrorFindNextFile;
  1718. }
  1719. }
  1720. }
  1721. }
  1722. //
  1723. // Free up stuff used for find
  1724. //
  1725. free(pwszSearchCatalogsInDir);
  1726. pwszSearchCatalogsInDir = NULL;
  1727. FindClose(hFindHandleCatalogsInDir);
  1728. hFindHandleCatalogsInDir = INVALID_HANDLE_VALUE;
  1729. memset(&FindDataCatalogsInDir, 0, sizeof(FindDataCatalogsInDir));
  1730. //
  1731. // Construct the new search string which point to the temp dir
  1732. //
  1733. if (NULL == (pwszSearchCatalogsInDir = _CatAdminCreatePath(
  1734. pwszTempDir,
  1735. L"*",
  1736. FALSE)))
  1737. {
  1738. CATADMIN_LOGERR_LASTERR()
  1739. goto ErrorReturn;
  1740. }
  1741. //
  1742. // Add each catalog in the temp dir to the database
  1743. //
  1744. hFindHandleCatalogsInDir = FindFirstFileU(
  1745. pwszSearchCatalogsInDir,
  1746. &FindDataCatalogsInDir);
  1747. if (hFindHandleCatalogsInDir == INVALID_HANDLE_VALUE)
  1748. {
  1749. dwErr = GetLastError();
  1750. //
  1751. // no files found
  1752. //
  1753. if ((dwErr == ERROR_NO_MORE_FILES) ||
  1754. (dwErr == ERROR_FILE_NOT_FOUND))
  1755. {
  1756. SetLastError(0);
  1757. }
  1758. else
  1759. {
  1760. CATADMIN_LOGERR_LASTERR()
  1761. goto ErrorFindFirstFile;
  1762. }
  1763. }
  1764. else
  1765. {
  1766. while (1)
  1767. {
  1768. //
  1769. // Only care about files
  1770. //
  1771. if (!(FindDataCatalogsInDir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1772. {
  1773. //
  1774. // Construct fully qualified path name to catalog file
  1775. //
  1776. if (NULL == (pwszCatalogFile = _CatAdminCreatePath(
  1777. pwszTempDir,
  1778. FindDataCatalogsInDir.cFileName,
  1779. FALSE)))
  1780. {
  1781. CATADMIN_LOGERR_LASTERR()
  1782. goto ErrorReturn;
  1783. }
  1784. hCatInfo = CryptCATAdminAddCatalog(
  1785. hCatAdmin,
  1786. pwszCatalogFile,
  1787. FindDataCatalogsInDir.cFileName,
  1788. NULL);
  1789. if (hCatInfo != NULL)
  1790. {
  1791. CryptCATAdminReleaseCatalogContext(
  1792. hCatAdmin,
  1793. hCatInfo,
  1794. NULL);
  1795. hCatInfo = NULL;
  1796. }
  1797. else
  1798. {
  1799. // Log error
  1800. CATADMIN_LOGERR_LASTERR()
  1801. }
  1802. free(pwszCatalogFile);
  1803. pwszCatalogFile = NULL;
  1804. }
  1805. //
  1806. // Get next catalog file
  1807. //
  1808. if (!FindNextFileU(hFindHandleCatalogsInDir, &FindDataCatalogsInDir))
  1809. {
  1810. if (GetLastError() == ERROR_NO_MORE_FILES)
  1811. {
  1812. SetLastError(0);
  1813. break;
  1814. }
  1815. else
  1816. {
  1817. CATADMIN_LOGERR_LASTERR()
  1818. goto ErrorFindNextFile;
  1819. }
  1820. }
  1821. }
  1822. }
  1823. CommonReturn:
  1824. dwErr = GetLastError();
  1825. if (pwszSubDir != NULL)
  1826. {
  1827. free(pwszSubDir);
  1828. }
  1829. if (pwszCatalogFile != NULL)
  1830. {
  1831. free(pwszCatalogFile);
  1832. }
  1833. if (pwszSearchCatalogsInDir != NULL)
  1834. {
  1835. free(pwszSearchCatalogsInDir);
  1836. }
  1837. if (pwszTempDir != NULL)
  1838. {
  1839. I_RecursiveDeleteDirectory(pwszTempDir);
  1840. free(pwszTempDir);
  1841. }
  1842. if (pwszTempCatalogFile != NULL)
  1843. {
  1844. free(pwszTempCatalogFile);
  1845. }
  1846. if (hFindHandleCatalogsInDir != INVALID_HANDLE_VALUE)
  1847. {
  1848. FindClose(hFindHandleCatalogsInDir);
  1849. }
  1850. if (hCatAdmin != NULL)
  1851. {
  1852. CryptCATAdminReleaseContext(hCatAdmin, NULL);
  1853. }
  1854. SetLastError(dwErr);
  1855. return(fRet);
  1856. ErrorReturn:
  1857. fRet = FALSE;
  1858. goto CommonReturn;
  1859. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
  1860. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
  1861. }
  1862. //---------------------------------------------------------------------------------------
  1863. //
  1864. // CatAdminDllMain
  1865. //
  1866. //---------------------------------------------------------------------------------------
  1867. BOOL WINAPI
  1868. CatAdminDllMain(
  1869. HANDLE hInstDLL,
  1870. DWORD fdwReason,
  1871. LPVOID lpvReserved)
  1872. {
  1873. BOOL fRet = TRUE;
  1874. switch (fdwReason)
  1875. {
  1876. case DLL_PROCESS_ATTACH:
  1877. fRet = _CatAdminSetupDefaults();
  1878. break;
  1879. case DLL_PROCESS_DETACH:
  1880. _CatAdminCleanupDefaults();
  1881. break;
  1882. }
  1883. return(fRet);
  1884. }
  1885. //---------------------------------------------------------------------------------------
  1886. //---------------------------------------------------------------------------------------
  1887. // Internal functions
  1888. //---------------------------------------------------------------------------------------
  1889. //---------------------------------------------------------------------------------------
  1890. //---------------------------------------------------------------------------------------
  1891. //
  1892. // _CatAdminSetupDefaults
  1893. //
  1894. //---------------------------------------------------------------------------------------
  1895. BOOL
  1896. _CatAdminSetupDefaults(void)
  1897. {
  1898. BOOL fRet = TRUE;
  1899. WCHAR wszDefaultSystemDir[MAX_PATH + 1];
  1900. //
  1901. // Get System default directory
  1902. //
  1903. wszDefaultSystemDir[0] = NULL;
  1904. if (0 == GetSystemDirectoryW(wszDefaultSystemDir, MAX_PATH))
  1905. {
  1906. CATADMIN_LOGERR_LASTERR()
  1907. goto ErrorSystemError;
  1908. }
  1909. //
  1910. // Get catalog file base directory
  1911. //
  1912. if (NULL == (gpwszCatalogFileBaseDirectory =
  1913. _CatAdminCreatePath(
  1914. wszDefaultSystemDir,
  1915. WSZ_CATALOG_FILE_BASE_DIRECTORY,
  1916. TRUE)))
  1917. {
  1918. CATADMIN_LOGERR_LASTERR()
  1919. goto ErrorReturn;
  1920. }
  1921. //
  1922. // Get database file base directory
  1923. //
  1924. if (NULL == (gpwszDatabaseFileBaseDirectory =
  1925. _CatAdminCreatePath(
  1926. wszDefaultSystemDir,
  1927. WSZ_DATABASE_FILE_BASE_DIRECTORY,
  1928. TRUE)))
  1929. {
  1930. CATADMIN_LOGERR_LASTERR()
  1931. goto ErrorReturn;
  1932. }
  1933. CommonReturn:
  1934. return(fRet);
  1935. ErrorReturn:
  1936. if (gpwszCatalogFileBaseDirectory != NULL)
  1937. {
  1938. free(gpwszCatalogFileBaseDirectory);
  1939. gpwszCatalogFileBaseDirectory = NULL;
  1940. }
  1941. fRet = FALSE;
  1942. goto CommonReturn;
  1943. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorSystemError);
  1944. }
  1945. //---------------------------------------------------------------------------------------
  1946. //
  1947. // _CatAdminCleanupDefaults
  1948. //
  1949. //---------------------------------------------------------------------------------------
  1950. void _CatAdminCleanupDefaults(void)
  1951. {
  1952. if (gpwszCatalogFileBaseDirectory != NULL)
  1953. {
  1954. free(gpwszCatalogFileBaseDirectory);
  1955. gpwszCatalogFileBaseDirectory = NULL;
  1956. }
  1957. if (gpwszDatabaseFileBaseDirectory != NULL)
  1958. {
  1959. free(gpwszDatabaseFileBaseDirectory);
  1960. gpwszDatabaseFileBaseDirectory = NULL;
  1961. }
  1962. }
  1963. //---------------------------------------------------------------------------------------
  1964. //
  1965. // _CatAdminTimeStampFilesInSync
  1966. //
  1967. //---------------------------------------------------------------------------------------
  1968. BOOL
  1969. _CatAdminTimeStampFilesInSync(
  1970. LPWSTR pwszDatabaseGUID,
  1971. BOOL *pfInSync)
  1972. {
  1973. LPWSTR pwszCatalogFileDir = NULL;
  1974. LPWSTR pwszDatabaseFileDir = NULL;
  1975. BOOL fRet = TRUE;
  1976. *pfInSync = FALSE;
  1977. //
  1978. // Construct full subdir path to Catalog files TimeStamp location
  1979. //
  1980. if (NULL == (pwszCatalogFileDir = _CatAdminCreatePath(
  1981. gpwszCatalogFileBaseDirectory,
  1982. pwszDatabaseGUID,
  1983. FALSE)))
  1984. {
  1985. CATADMIN_LOGERR_LASTERR()
  1986. goto ErrorReturn;
  1987. }
  1988. //
  1989. // Construct full subdir path to Database files TimeStamp location
  1990. //
  1991. if (NULL == (pwszDatabaseFileDir = _CatAdminCreatePath(
  1992. gpwszDatabaseFileBaseDirectory,
  1993. pwszDatabaseGUID,
  1994. FALSE)))
  1995. {
  1996. CATADMIN_LOGERR_LASTERR()
  1997. goto ErrorReturn;
  1998. }
  1999. fRet = TimeStampFile_InSync(
  2000. pwszCatalogFileDir,
  2001. pwszDatabaseFileDir,
  2002. pfInSync);
  2003. CommonReturn:
  2004. if (pwszCatalogFileDir != NULL)
  2005. {
  2006. free(pwszCatalogFileDir);
  2007. }
  2008. if (pwszDatabaseFileDir != NULL)
  2009. {
  2010. free(pwszDatabaseFileDir);
  2011. }
  2012. return(fRet);
  2013. ErrorReturn:
  2014. fRet = FALSE;
  2015. goto CommonReturn;
  2016. }
  2017. //---------------------------------------------------------------------------------------
  2018. //
  2019. // _CatAdminRegisterForChangeNotification
  2020. //
  2021. //---------------------------------------------------------------------------------------
  2022. BOOL
  2023. _CatAdminRegisterForChangeNotification(
  2024. CRYPT_CAT_ADMIN *pCatAdmin
  2025. )
  2026. {
  2027. BOOL fRet = TRUE;
  2028. DWORD dwErr = 0;
  2029. //
  2030. // See if already registered
  2031. //
  2032. if (pCatAdmin->fRegisteredForChangeNotification)
  2033. {
  2034. goto CommonReturn;
  2035. }
  2036. //
  2037. // NOTE:
  2038. // Currently the service ignores the pwszSubSysGUID when registering a change
  2039. // notification because it DOES NOT do notifications on a per pwszSubSysDir basis...
  2040. // it really should at some point.
  2041. // When it does start to do notifications on per pwszSubSysGUID this will need to
  2042. // change. CryptCatAdminAcquireContext can be called with a NULL subSysGUID,
  2043. // in which case all SubSysDirs are used, so we would need to register a
  2044. // change notification for all of them.
  2045. //
  2046. //
  2047. // Register the event with the DB process, so the DB process can SetEvent() it
  2048. // when a changed occurs
  2049. //
  2050. if (0 != (dwErr = Client_SSCatDBRegisterForChangeNotification(
  2051. (DWORD_PTR) pCatAdmin->hClearCacheEvent,
  2052. 0,
  2053. pCatAdmin->pwszSubSysGUID,
  2054. FALSE)))
  2055. {
  2056. CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorCatDBProcess)
  2057. }
  2058. pCatAdmin->fRegisteredForChangeNotification = TRUE;
  2059. CommonReturn:
  2060. return fRet;
  2061. ErrorReturn:
  2062. fRet = FALSE;
  2063. goto CommonReturn;
  2064. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCatDBProcess)
  2065. }
  2066. //---------------------------------------------------------------------------------------
  2067. //
  2068. // _CatAdminFreeCachedCatalogs
  2069. //
  2070. //---------------------------------------------------------------------------------------
  2071. BOOL
  2072. _CatAdminFreeCachedCatalogs(
  2073. CRYPT_CAT_ADMIN *pCatAdmin)
  2074. {
  2075. BOOL fRet = TRUE;
  2076. LIST_NODE *pListNode = NULL;
  2077. CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
  2078. //
  2079. // NOTE: the caller of this function must have entered the Critical Section for
  2080. // the CatAdminContext
  2081. //
  2082. //
  2083. // Enumerate through all the cached CATALOG_INFO_CONTEXTs and free all the
  2084. // resources for each
  2085. //
  2086. pListNode = LIST_GetFirst(&(pCatAdmin->CatalogInfoContextList));
  2087. while (pListNode != NULL)
  2088. {
  2089. pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
  2090. free(pCatInfoContext->pwszCatalogFile);
  2091. CertFreeCTLContext(pCatInfoContext->pCTLContext);
  2092. UnmapViewOfFile(pCatInfoContext->pbMappedFile);
  2093. CloseHandle(pCatInfoContext->hMappedFile);
  2094. free(pCatInfoContext);
  2095. pListNode = LIST_GetNext(pListNode);
  2096. }
  2097. LIST_RemoveAll(&(pCatAdmin->CatalogInfoContextList));
  2098. return(fRet);
  2099. }
  2100. //---------------------------------------------------------------------------------------
  2101. //
  2102. // _CatAdminWaitOrTimerCallback
  2103. //
  2104. //---------------------------------------------------------------------------------------
  2105. VOID CALLBACK
  2106. _CatAdminWaitOrTimerCallback(
  2107. PVOID lpParameter,
  2108. BOOLEAN TimerOrWaitFired)
  2109. {
  2110. CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *) lpParameter;
  2111. int i = 0;
  2112. LIST_NODE *pListNode = NULL;
  2113. CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
  2114. //
  2115. // Enter the CS before wacking anything
  2116. //
  2117. __try
  2118. {
  2119. EnterCriticalSection(&(pCatAdmin->CriticalSection));
  2120. }
  2121. __except(EXCEPTION_EXECUTE_HANDLER)
  2122. {
  2123. SetLastError(GetExceptionCode());
  2124. CATADMIN_LOGERR_LASTERR()
  2125. return;
  2126. }
  2127. pCatAdmin->fCSEntered = TRUE;
  2128. //
  2129. // If there is an open ref count, then we can't clean up
  2130. //
  2131. if (pCatAdmin->nOpenCatInfoContexts != 0)
  2132. {
  2133. pCatAdmin->fCSEntered = FALSE;
  2134. LeaveCriticalSection(&(pCatAdmin->CriticalSection));
  2135. return;
  2136. }
  2137. //
  2138. // Cleanup all the cached CATALOG_INFO_CONTEXTs
  2139. //
  2140. _CatAdminFreeCachedCatalogs(pCatAdmin);
  2141. pCatAdmin->fCSEntered = FALSE;
  2142. LeaveCriticalSection(&(pCatAdmin->CriticalSection));
  2143. }
  2144. //---------------------------------------------------------------------------------------
  2145. //
  2146. // _CatAdminAddCatalogsToCache
  2147. //
  2148. //---------------------------------------------------------------------------------------
  2149. BOOL
  2150. _CatAdminAddCatalogsToCache(
  2151. CRYPT_CAT_ADMIN *pCatAdmin,
  2152. LPWSTR pwszSubSysGUID,
  2153. CRYPT_DATA_BLOB *pCryptDataBlob,
  2154. LIST_NODE **ppFirstListNodeAdded)
  2155. {
  2156. BOOL fRet = TRUE;
  2157. LPWSTR pwszCopy = NULL;
  2158. DWORD i;
  2159. DWORD dwNumCatalogNames = 0;
  2160. LPWSTR *ppwszCatalogNames = NULL;
  2161. DWORD dwErr = 0;
  2162. LIST_NODE *pListNode = NULL;
  2163. LPWSTR pwszSubSysDir = NULL;
  2164. BOOL fFirstCatalogAdded = FALSE;
  2165. if (ppFirstListNodeAdded != NULL)
  2166. {
  2167. *ppFirstListNodeAdded = NULL;
  2168. }
  2169. if (NULL == (pwszSubSysDir = _CatAdminCreatePath(
  2170. gpwszCatalogFileBaseDirectory,
  2171. pwszSubSysGUID,
  2172. FALSE)))
  2173. {
  2174. CATADMIN_LOGERR_LASTERR()
  2175. goto ErrorReturn;
  2176. }
  2177. //
  2178. // Call DB process and get list of catalogs into ppwszCatalogNames
  2179. //
  2180. // NOTE: the order in which the service adds CatNames to the list results in
  2181. // only the first CatName of the list being guaranteed to contain the
  2182. // hash... all other CatNames may or may not contain the hash. Which
  2183. // is OK because this code only assumes the first CatName contains the
  2184. // hash, and then searches all other CatNames for the hash before returning them.
  2185. //
  2186. if (0 != (dwErr = Client_SSCatDBEnumCatalogs(
  2187. 0,
  2188. pwszSubSysGUID,
  2189. pCryptDataBlob->pbData,
  2190. pCryptDataBlob->cbData,
  2191. &dwNumCatalogNames,
  2192. &ppwszCatalogNames)))
  2193. {
  2194. CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorServiceError)
  2195. }
  2196. //
  2197. // Loop for each catalog and create the CTL context
  2198. //
  2199. for (i=0; i<dwNumCatalogNames; i++)
  2200. {
  2201. //
  2202. // Make a copy of the catalog file name
  2203. //
  2204. if (NULL == (pwszCopy = _CatAdminCreatePath(
  2205. pwszSubSysDir,
  2206. ppwszCatalogNames[i],
  2207. FALSE)))
  2208. {
  2209. CATADMIN_LOGERR_LASTERR()
  2210. goto ErrorReturn;
  2211. }
  2212. if (!_CatAdminAddSingleCatalogToCache(
  2213. pCatAdmin,
  2214. pwszCopy,
  2215. &pListNode))
  2216. {
  2217. //
  2218. // if this isn't the first catalog, then continue since the
  2219. // macro operation may still succeed without the current catalog
  2220. //
  2221. if (i != 0)
  2222. {
  2223. CATADMIN_LOGERR_LASTERR()
  2224. continue;
  2225. }
  2226. CATADMIN_LOGERR_LASTERR()
  2227. goto ErrorReturn;
  2228. }
  2229. //
  2230. // This will only be set for the first catalog added,
  2231. // as per the NOTE above
  2232. //
  2233. if ((ppFirstListNodeAdded != NULL) &&
  2234. (*ppFirstListNodeAdded == NULL))
  2235. {
  2236. *ppFirstListNodeAdded = pListNode;
  2237. }
  2238. }
  2239. CommonReturn:
  2240. if (ppwszCatalogNames != NULL)
  2241. {
  2242. for (i=0; i<dwNumCatalogNames; i++)
  2243. {
  2244. MIDL_user_free(ppwszCatalogNames[i]);
  2245. }
  2246. MIDL_user_free(ppwszCatalogNames);
  2247. }
  2248. if (pwszSubSysDir != NULL)
  2249. {
  2250. free(pwszSubSysDir);
  2251. }
  2252. return(fRet);
  2253. ErrorReturn:
  2254. if (pwszCopy != NULL)
  2255. {
  2256. free(pwszCopy);
  2257. }
  2258. fRet = FALSE;
  2259. goto CommonReturn;
  2260. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorServiceError)
  2261. }
  2262. //---------------------------------------------------------------------------------------
  2263. //
  2264. // _CatAdminAddSingleCatalogToCache
  2265. //
  2266. //---------------------------------------------------------------------------------------
  2267. BOOL
  2268. _CatAdminAddSingleCatalogToCache(
  2269. CRYPT_CAT_ADMIN *pCatAdmin,
  2270. LPWSTR pwszCatalog,
  2271. LIST_NODE **ppListNodeAdded)
  2272. {
  2273. BOOL fRet = TRUE;
  2274. DWORD dwErr = 0;
  2275. LIST_NODE *pListNode = NULL;
  2276. CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
  2277. CATALOG_INFO_CONTEXT *pCatInfoContextAdd = NULL;
  2278. *ppListNodeAdded = NULL;
  2279. //
  2280. // If there is already a copy of this catalog, then just get out
  2281. //
  2282. pListNode = LIST_GetFirst(&(pCatAdmin->CatalogInfoContextList));
  2283. while (pListNode != NULL)
  2284. {
  2285. pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
  2286. if (_wcsicmp(pCatInfoContext->pwszCatalogFile, pwszCatalog) == 0)
  2287. {
  2288. *ppListNodeAdded = pListNode;
  2289. goto CommonReturn;
  2290. }
  2291. pListNode = LIST_GetNext(pListNode);
  2292. }
  2293. //
  2294. // Allocate space for a new cached catalog context
  2295. //
  2296. if (NULL == (pCatInfoContextAdd = (CATALOG_INFO_CONTEXT *)
  2297. malloc(sizeof(CATALOG_INFO_CONTEXT))))
  2298. {
  2299. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  2300. }
  2301. memset(pCatInfoContextAdd, 0, sizeof(CATALOG_INFO_CONTEXT));
  2302. pCatInfoContextAdd->fResultOfAdd = FALSE;
  2303. //
  2304. // Open, create a file mapping, and create the CTL context for
  2305. // the catalog file
  2306. //
  2307. if (!CatUtil_CreateCTLContextFromFileName(
  2308. pwszCatalog,
  2309. &pCatInfoContextAdd->hMappedFile,
  2310. &pCatInfoContextAdd->pbMappedFile,
  2311. &pCatInfoContextAdd->pCTLContext,
  2312. TRUE))
  2313. {
  2314. CATADMIN_LOGERR_LASTERR()
  2315. ErrLog_LogString(NULL, L"The following file was not found - ", pwszCatalog, TRUE);
  2316. goto ErrorReturn;
  2317. }
  2318. pCatInfoContextAdd->pwszCatalogFile = pwszCatalog;
  2319. //
  2320. // Add to the list of cached catalog contexts
  2321. //
  2322. if (NULL == (pListNode = LIST_AddTail(
  2323. &(pCatAdmin->CatalogInfoContextList),
  2324. pCatInfoContextAdd)))
  2325. {
  2326. CATADMIN_LOGERR_LASTERR()
  2327. goto ErrorReturn;
  2328. }
  2329. *ppListNodeAdded = pListNode;
  2330. CommonReturn:
  2331. return(fRet);
  2332. ErrorReturn:
  2333. dwErr = GetLastError();
  2334. if (pCatInfoContextAdd != NULL)
  2335. {
  2336. if (pCatInfoContextAdd->pCTLContext != NULL)
  2337. {
  2338. CertFreeCTLContext(pCatInfoContextAdd->pCTLContext);
  2339. }
  2340. if (pCatInfoContextAdd->pbMappedFile != NULL)
  2341. {
  2342. UnmapViewOfFile(pCatInfoContextAdd->pbMappedFile);
  2343. }
  2344. if (pCatInfoContextAdd->hMappedFile != NULL)
  2345. {
  2346. CloseHandle(pCatInfoContextAdd->hMappedFile);
  2347. }
  2348. free(pCatInfoContextAdd);
  2349. }
  2350. SetLastError(dwErr);
  2351. fRet = FALSE;
  2352. goto CommonReturn;
  2353. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
  2354. }
  2355. //---------------------------------------------------------------------------------------
  2356. //
  2357. // _CatAdminMigrateCatalogDatabase
  2358. //
  2359. // This migration code deals with very old catalog databases. In the olden days, the
  2360. // catroot dir location could be specified by a particular registry key... that is no
  2361. // longer true. So, if an old system is being upgraded that has the registry key, this
  2362. // code moves all the catalog files from the location specified by the registry key to
  2363. // the %SystemDefaultDir%\Catroot dir. Then it shwacks the registry key.
  2364. //
  2365. //---------------------------------------------------------------------------------------
  2366. BOOL
  2367. _CatAdminMigrateCatalogDatabase(
  2368. LPWSTR pwszFrom,
  2369. LPWSTR pwszTo)
  2370. {
  2371. DWORD dwAttr = 0;
  2372. WCHAR wszFrom[MAX_PATH];
  2373. WCHAR wszTo[MAX_PATH];
  2374. //
  2375. // If they are the same dir then just get out
  2376. //
  2377. if (((wcslen(pwszFrom) + 1) > MAX_PATH) ||
  2378. ((wcslen(pwszFrom) + 1) > MAX_PATH))
  2379. {
  2380. return TRUE;
  2381. }
  2382. wcscpy(wszFrom, pwszFrom);
  2383. wcscpy(wszTo, pwszTo);
  2384. if (wszFrom[wcslen(wszFrom) - 1] != L'\\')
  2385. {
  2386. wcscat(wszFrom, L"\\");
  2387. }
  2388. if (wszTo[wcslen(wszTo) - 1] != L'\\')
  2389. {
  2390. wcscat(wszTo, L"\\");
  2391. }
  2392. if (_wcsicmp(wszFrom, wszTo) == 0)
  2393. {
  2394. return TRUE;
  2395. }
  2396. //
  2397. // if the pwszTo dir already exists, then don't do a thing.
  2398. //
  2399. dwAttr = GetFileAttributesU(pwszTo);
  2400. if (0xFFFFFFFF != dwAttr)
  2401. {
  2402. if (FILE_ATTRIBUTE_DIRECTORY & dwAttr)
  2403. {
  2404. //
  2405. // dir already exists...
  2406. //
  2407. return TRUE;
  2408. }
  2409. else
  2410. {
  2411. //
  2412. // something exists with pwszTo name, but it isn't a dir
  2413. //
  2414. CATADMIN_LOGERR_LASTERR()
  2415. return FALSE;
  2416. }
  2417. }
  2418. //
  2419. // if the pwszFrom dir does not exist, then don't do a thing.
  2420. //
  2421. dwAttr = GetFileAttributesU(pwszFrom);
  2422. if ((0xFFFFFFFF == dwAttr) || (!(FILE_ATTRIBUTE_DIRECTORY & dwAttr)))
  2423. {
  2424. return TRUE;
  2425. }
  2426. if (!_CatAdminRecursiveCreateDirectory(pwszTo, NULL))
  2427. {
  2428. CATADMIN_LOGERR_LASTERR()
  2429. return FALSE;
  2430. }
  2431. if (!I_RecursiveCopyDirectory(pwszFrom, pwszTo))
  2432. {
  2433. CATADMIN_LOGERR_LASTERR()
  2434. return FALSE;
  2435. }
  2436. //
  2437. // Don't check for error on delete since this operation is NOT mandatory
  2438. //
  2439. I_RecursiveDeleteDirectory(pwszFrom);
  2440. return TRUE;
  2441. }
  2442. //---------------------------------------------------------------------------------------
  2443. //
  2444. // _CatAdminBToHex
  2445. //
  2446. //---------------------------------------------------------------------------------------
  2447. WCHAR rgHexDigit[] = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7',
  2448. L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
  2449. void
  2450. _CatAdminBToHex (
  2451. LPBYTE pbDigest,
  2452. DWORD iByte,
  2453. LPWSTR pwszHashTag)
  2454. {
  2455. DWORD iTag;
  2456. DWORD iHexDigit1;
  2457. DWORD iHexDigit2;
  2458. iTag = iByte * 2;
  2459. iHexDigit1 = (pbDigest[iByte] & 0xF0) >> 4;
  2460. iHexDigit2 = (pbDigest[iByte] & 0x0F);
  2461. pwszHashTag[iTag] = rgHexDigit[iHexDigit1];
  2462. pwszHashTag[iTag + 1] = rgHexDigit[iHexDigit2];
  2463. }
  2464. //---------------------------------------------------------------------------------------
  2465. //
  2466. // _CatAdminCreateHashTag
  2467. //
  2468. //---------------------------------------------------------------------------------------
  2469. BOOL
  2470. _CatAdminCreateHashTag(
  2471. BYTE *pbHash,
  2472. DWORD cbHash,
  2473. LPWSTR *ppwszHashTag,
  2474. CRYPT_DATA_BLOB *pCryptDataBlob)
  2475. {
  2476. DWORD cwTag;
  2477. DWORD cCount;
  2478. cwTag = ((cbHash * 2) + 1);
  2479. if (NULL == (*ppwszHashTag = (LPWSTR) malloc(cwTag * sizeof(WCHAR))))
  2480. {
  2481. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2482. CATADMIN_LOGERR_LASTERR()
  2483. return(FALSE);
  2484. }
  2485. for (cCount = 0; cCount < cbHash; cCount++)
  2486. {
  2487. _CatAdminBToHex(pbHash, cCount, *ppwszHashTag);
  2488. }
  2489. (*ppwszHashTag)[cwTag - 1] = L'\0';
  2490. pCryptDataBlob->pbData = (BYTE *) *ppwszHashTag;
  2491. pCryptDataBlob->cbData = cwTag * sizeof(WCHAR);
  2492. return (TRUE);
  2493. }
  2494. //---------------------------------------------------------------------------------------
  2495. //
  2496. // _CatAdminRecursiveCreateDirectory
  2497. //
  2498. //---------------------------------------------------------------------------------------
  2499. BOOL
  2500. _CatAdminRecursiveCreateDirectory(
  2501. IN LPCWSTR pwszDir,
  2502. LPSECURITY_ATTRIBUTES lpSecurityAttributes
  2503. )
  2504. {
  2505. BOOL fResult;
  2506. DWORD dwAttr;
  2507. DWORD dwErr;
  2508. LPCWSTR pwsz;
  2509. DWORD cch;
  2510. WCHAR wch;
  2511. LPWSTR pwszParent = NULL;
  2512. //
  2513. // if last char is a '\', then just strip it and recurse
  2514. //
  2515. if (pwszDir[wcslen(pwszDir) - 1] == L'\\')
  2516. {
  2517. cch = wcslen(pwszDir);
  2518. if (NULL == (pwszParent = (LPWSTR) malloc(cch * sizeof(WCHAR))))
  2519. {
  2520. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  2521. }
  2522. memcpy(pwszParent, pwszDir, (cch - 1) * sizeof(WCHAR));
  2523. pwszParent[cch - 1] = L'\0';
  2524. fResult = _CatAdminRecursiveCreateDirectory(
  2525. pwszParent,
  2526. lpSecurityAttributes);
  2527. goto CommonReturn;
  2528. }
  2529. //
  2530. // See if dir already exists
  2531. //
  2532. dwAttr = GetFileAttributesU(pwszDir);
  2533. if (0xFFFFFFFF != dwAttr)
  2534. {
  2535. if (FILE_ATTRIBUTE_DIRECTORY & dwAttr)
  2536. {
  2537. return TRUE;
  2538. }
  2539. CATADMIN_LOGERR_LASTERR()
  2540. goto InvalidDirectoryAttr;
  2541. }
  2542. //
  2543. // If it was an error other than file/path not found, error out
  2544. //
  2545. dwErr = GetLastError();
  2546. if (!(ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr))
  2547. {
  2548. CATADMIN_LOGERR_LASTERR()
  2549. goto GetFileAttrError;
  2550. }
  2551. //
  2552. // Try creating the new dir
  2553. //
  2554. if (CreateDirectoryU(
  2555. pwszDir,
  2556. lpSecurityAttributes))
  2557. {
  2558. SetFileAttributesU(pwszDir, FILE_ATTRIBUTE_NORMAL);
  2559. return TRUE;
  2560. }
  2561. dwErr = GetLastError();
  2562. if (!(ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr))
  2563. {
  2564. CATADMIN_LOGERR_LASTERR()
  2565. goto CreateDirectoryError;
  2566. }
  2567. //
  2568. // Peal off the last path name component
  2569. //
  2570. cch = wcslen(pwszDir);
  2571. pwsz = pwszDir + cch;
  2572. while (L'\\' != *pwsz)
  2573. {
  2574. if (pwsz == pwszDir)
  2575. {
  2576. // Path didn't have a \.
  2577. CATADMIN_SETERR_LOG_RETURN(ERROR_BAD_PATHNAME, BadDirectoryPath)
  2578. }
  2579. pwsz--;
  2580. }
  2581. cch = (DWORD)(pwsz - pwszDir);
  2582. if (0 == cch)
  2583. {
  2584. // Detected leading \Path
  2585. CATADMIN_SETERR_LOG_RETURN(ERROR_BAD_PATHNAME, BadDirectoryPath)
  2586. }
  2587. // Check for leading \\ or x:\.
  2588. wch = *(pwsz - 1);
  2589. if ((1 == cch && L'\\' == wch) || (2 == cch && L':' == wch))
  2590. {
  2591. CATADMIN_SETERR_LOG_RETURN(ERROR_BAD_PATHNAME, BadDirectoryPath)
  2592. }
  2593. if (NULL == (pwszParent = (LPWSTR) malloc((cch + 1) * sizeof(WCHAR))))
  2594. {
  2595. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  2596. }
  2597. memcpy(pwszParent, pwszDir, cch * sizeof(WCHAR));
  2598. pwszParent[cch] = L'\0';
  2599. if (!_CatAdminRecursiveCreateDirectory(pwszParent, lpSecurityAttributes))
  2600. {
  2601. CATADMIN_LOGERR_LASTERR()
  2602. goto ErrorReturn;
  2603. }
  2604. if (!CreateDirectoryU(
  2605. pwszDir,
  2606. lpSecurityAttributes))
  2607. {
  2608. CATADMIN_LOGERR_LASTERR()
  2609. goto CreateDirectory2Error;
  2610. }
  2611. SetFileAttributesU(pwszDir, FILE_ATTRIBUTE_NORMAL);
  2612. fResult = TRUE;
  2613. CommonReturn:
  2614. if (pwszParent != NULL)
  2615. {
  2616. free(pwszParent);
  2617. }
  2618. return fResult;
  2619. ErrorReturn:
  2620. fResult = FALSE;
  2621. goto CommonReturn;
  2622. TRACE_ERROR_EX(DBG_SS_TRUST, InvalidDirectoryAttr)
  2623. TRACE_ERROR_EX(DBG_SS_TRUST, GetFileAttrError)
  2624. TRACE_ERROR_EX(DBG_SS_TRUST, CreateDirectoryError)
  2625. TRACE_ERROR_EX(DBG_SS_TRUST, BadDirectoryPath)
  2626. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
  2627. TRACE_ERROR_EX(DBG_SS_TRUST, CreateDirectory2Error)
  2628. }
  2629. //---------------------------------------------------------------------------------------
  2630. //
  2631. // _CatAdminCreatePath
  2632. //
  2633. //---------------------------------------------------------------------------------------
  2634. LPWSTR
  2635. _CatAdminCreatePath(
  2636. IN LPCWSTR pwsz1,
  2637. IN LPCWSTR pwsz2,
  2638. IN BOOL fAddEndingSlash
  2639. )
  2640. {
  2641. LPWSTR pwszTemp = NULL;
  2642. int nTotalLen = 0;
  2643. int nLenStr1 = 0;
  2644. //
  2645. // Calculate the length of the resultant string as the sum of the length
  2646. // of pwsz1, length of pwsz2, a NULL char, and a possible extra '\' char
  2647. //
  2648. nLenStr1 = wcslen(pwsz1);
  2649. nTotalLen = nLenStr1 + wcslen(pwsz2) + 2;
  2650. if (fAddEndingSlash)
  2651. {
  2652. nTotalLen++;
  2653. }
  2654. //
  2655. // Allocate the string and copy pwsz1 into the buffer
  2656. //
  2657. if (NULL == (pwszTemp = (LPWSTR) malloc(sizeof(WCHAR) * nTotalLen)))
  2658. {
  2659. CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  2660. }
  2661. wcscpy(pwszTemp, pwsz1);
  2662. //
  2663. // Add the extra '\' if needed
  2664. //
  2665. if (pwsz1[nLenStr1 - 1] != L'\\')
  2666. {
  2667. wcscat(pwszTemp, L"\\");
  2668. }
  2669. //
  2670. // Tack on pwsz2
  2671. //
  2672. wcscat(pwszTemp, pwsz2);
  2673. if (fAddEndingSlash)
  2674. {
  2675. wcscat(pwszTemp, L"\\");
  2676. }
  2677. CommonReturn:
  2678. return (pwszTemp);
  2679. ErrorReturn:
  2680. goto CommonReturn;
  2681. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory)
  2682. }