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.

6527 lines
169 KiB

  1. /*++
  2. Copyright (c) 1996, 1997 Microsoft Corporation
  3. Module Name:
  4. catdbsvc.cpp
  5. Abstract:
  6. This module contains routines associated with the service
  7. side of the catalog database
  8. Author:
  9. Reid Kuhn (reidk) 19-Nov-97
  10. --*/
  11. /*
  12. This comment section gives a picture of an example catalog database,
  13. with example catalog files added and the resulting database tables.
  14. The database schema can be seen clearly by looking at the picture of
  15. the database tables. This comment section also contains psuedo code
  16. for the add catalog algorithm.
  17. Catalogs added to the catalog database are stored in the FILE SYSTEM
  18. --------------------------------------------------------------------
  19. -------- -------- -------- -------- -------- --------
  20. Catname: | CatA | | CatB | | CatC | | CatD | | CatE | | CatF |
  21. -------- -------- -------- -------- -------- --------
  22. HashList: | 111 | | 111 | | 444 | | 333 | | 333 | | 555 |
  23. | 222 | | 222 | | | | | | 555 | | |
  24. | 333 | | | | | | | | | | |
  25. -------- -------- -------- -------- -------- --------
  26. Resulting Database Tables (above catalogs where added in order)
  27. --------------------------------------------------------------------
  28. HashCatNameTable
  29. ----------------------------------
  30. | HashCol | CatNameListCol |
  31. |-----------|--------------------|
  32. | 111 | CatA - CatB |
  33. | 222 | CatA - CatB |
  34. | 333 | CatA - CatD - CatE |
  35. | 444 | CatC |
  36. | 555 | CatE - CatF |
  37. ----------------------------------
  38. CatNameBuddyTable
  39. ---------------------------------------------
  40. | CatNameCol | BuddyListCol |
  41. ---------------------------------------------
  42. | CatA | CatB - CatD - CatE |
  43. | CatB | CatA |
  44. | CatD | CatA - CatB - CatE |
  45. | CatE | CatA - CatB - CatD - CatF |
  46. | CatF | CatE - CatA - CatB - CatD |
  47. ---------------------------------------------
  48. Add Catalog Algorithm
  49. ---------------------
  50. AddCat(<CatToAdd>)
  51. {
  52. For each hash <i> contained in catalog <CatToAdd>
  53. {
  54. if (<i> is not contained in HashCol of HashCatNameTable)
  55. {
  56. add row to HashCatNameTable with <i> in HashCol and <CatToAdd> in CatNameListCol
  57. }
  58. else
  59. {
  60. create row in CatNameBuddyTable with <CatToAdd> in CatNameCol
  61. for each CatName <CatNameIn-CatNameListCol> contained in <i>'s CatNameListCol
  62. {
  63. if (<CatNameIn-CatNameListCol> is not contained in CatNameCol of CatNameBuddyTable
  64. {
  65. create row in CatNameBuddyTable with <CatNameIn-CatNameListCol> in CatNameCol
  66. }
  67. add <CatNameIn-CatNameListCol> to <CatToAdd>'s BuddyListCol
  68. for each CatName <CatNameIn-BuddyListCol> contained in <CatNameIn-CatNameListCol>'s BuddyListCol - (may be empty)
  69. {
  70. add <CatNameIn-BuddyListCol> to <CatToAdd>'s BuddyListCol
  71. }
  72. add <CatToAdd> to <CatNameIn-CatNameListCol>'s BuddyListCol
  73. }
  74. add <CatToAdd> to <i>'s CatNameListCol
  75. }
  76. }
  77. }
  78. */
  79. #include <windows.h>
  80. #include <wincrypt.h>
  81. #include <wintrust.h>
  82. #include <dbgdef.h>
  83. #include <esent.h>
  84. #include <assert.h>
  85. #include <stdio.h>
  86. #include "catdb.h" // header file generated by MIDL compiler
  87. #include "dbutils.h"
  88. #include "voidlist.h"
  89. #include "catutil.h"
  90. #include "resource.h"
  91. #include "errlog.h"
  92. #include "mscat.h"
  93. #define CATDB_MAX_CATNAME_LENGTH 255
  94. #define WSZ_REG_TEMP_FILES_KEY L"Software\\Microsoft\\Cryptography\\CatDBTempFiles"
  95. #define WSZ_REG_CATALOGDB_VALUES L"Software\\Microsoft\\Cryptography\\CatalogDB"
  96. #define WSZ_REG_CALLBACK_TIMER L"CallbackTime"
  97. #define WSZ_REG_DATABASE_TIMEOUT L"DatabaseTimeout"
  98. #define SZ_CATALOG_FILE_BASE_DIRECTORY "CatRoot"
  99. #define WSZ_CATALOG_FILE_BASE_DIRECTORY L"CatRoot"
  100. #define SZ_DATABASE_FILE_BASE_DIRECTORY "CatRoot2"
  101. #define WSZ_DATABASE_FILE_BASE_DIRECTORY L"CatRoot2"
  102. #define SZ_DBFILE_NAME "catdb"
  103. #define WSZ_DBFILE_NAME L"catdb"
  104. #define WSZ_TIME_STAMP_FILE L"TimeStamp"
  105. #define CATDBSVC_LOGERR_LASTERR() ErrLog_LogError(NULL, \
  106. ERRLOG_CLIENT_ID_CATDBSCV, \
  107. __LINE__, \
  108. 0, \
  109. FALSE, \
  110. FALSE);
  111. #define CATDBSVC_SETERR_LOG_RETURN(x, y) SetLastError(x); \
  112. ErrLog_LogError(NULL, \
  113. ERRLOG_CLIENT_ID_CATDBSCV, \
  114. __LINE__, \
  115. 0, \
  116. FALSE, \
  117. FALSE); \
  118. goto y;
  119. #define CATDBSVC_LOGERR(x) ErrLog_LogError(NULL, \
  120. ERRLOG_CLIENT_ID_CATDBSCV, \
  121. __LINE__, \
  122. x, \
  123. FALSE, \
  124. FALSE);
  125. #define CATDBSVC_LOGWARN(x) ErrLog_LogError(NULL, \
  126. ERRLOG_CLIENT_ID_CATDBSCV, \
  127. __LINE__, \
  128. x, \
  129. TRUE, \
  130. FALSE);
  131. #define ALLOCATION_BLOCK_SIZE 8
  132. typedef struct _JET_DB_STRUCT
  133. {
  134. LPSTR pszDBFileName;
  135. JET_SESID JetSesID;
  136. JET_DBID JetDBID;
  137. // Hash-CatName Table
  138. JET_TABLEID JetHashCatNameTableID;
  139. JET_COLUMNID JetHashCatNameTable_HashColumnID;
  140. JET_COLUMNID JetHashCatNameTable_CatNameColumnID;
  141. // CatName Buddy Table
  142. JET_TABLEID JetCatNameBuddyTableID;
  143. JET_COLUMNID JetCatNameBuddyTable_CatNameColumnID;
  144. JET_COLUMNID JetCatNameBuddyTable_BuddyColumnID;
  145. } JET_DB_STRUCT, *PJET_DB_STRUCT;
  146. typedef struct _CATALOG_DIR_CACHE_STRUCT
  147. {
  148. JET_DB_STRUCT JetDBStruct;
  149. LPWSTR pwszSubSysGUID;
  150. BOOL fDBCurrentlyInUse;
  151. BOOL fReadOnly;
  152. DWORD dwTimeLastTouched;
  153. HANDLE hRegisterWaitForServiceShutdown;
  154. } CATALOG_DIR_CACHE_STRUCT, *PCATALOG_DIR_CACHE_STRUCT;
  155. typedef struct _NOTIFICATION_STRUCT
  156. {
  157. DWORD ProcessID;
  158. HANDLE hClientProcess;
  159. HANDLE hRegisterWaitFor;
  160. HANDLE hNotificationHandle;
  161. HANDLE hDuplicatedNotificationHandle;
  162. LONG lNotificationID;
  163. } NOTIFICATION_STRUCT, *PNOTIFICATION_STRUCT;
  164. //
  165. // Global variables
  166. //
  167. extern HINSTANCE g_hInst;
  168. BOOL g_fDBSvcInitialized = FALSE;
  169. CRITICAL_SECTION g_CatDBAddDeleteCS;
  170. CRITICAL_SECTION g_CatDBRegisterNotifyCS;
  171. CRITICAL_SECTION g_CatDirCashCS;
  172. CRITICAL_SECTION g_CatClientCountCS;
  173. CRITICAL_SECTION g_InitializeJetCS;
  174. CRITICAL_SECTION g_CleanupTempFilesCS;
  175. LONG g_lOpenedDBCount = 0;
  176. BOOL g_fJetInitialized = FALSE;
  177. JET_INSTANCE g_JetInstance = 0;
  178. BOOL g_fCleaninUpTempFiles = FALSE;
  179. NOTIFICATION_STRUCT *g_rgNotificationStructs = NULL;
  180. DWORD g_NumNotificationStructs = 0;
  181. LIST g_CatalogDBCacheList;
  182. HANDLE g_hCatalogCacheCallbackEvent = NULL;
  183. BOOL g_fCatalogCacheCallbackEventSet = FALSE;
  184. DWORD g_dwClientCount = 0;
  185. LONG g_lNotificationID = 0;
  186. LPWSTR g_pwszCatalogFileBaseDirectory = NULL;
  187. LPWSTR g_pwszDatabaseFileBaseDirectory = NULL;
  188. DWORD g_dwCatalogDatabaseCacheTimeout = (1000 * 60); // default one minute
  189. DWORD g_dwCatalogDatabaseCacheCallbackTime= (1000 * 60 * 2); // default two minutes
  190. //
  191. // Forward declarations
  192. //
  193. //
  194. // General supporting DB file functions
  195. //
  196. BOOL
  197. _CatDBClientEnter(void);
  198. void
  199. _CatDBClientExit(void);
  200. void
  201. _CatDBTouchTimeStampFile(
  202. LPCWSTR pwszSubSysGUID);
  203. BOOL
  204. _CatDBInitializeJet(
  205. BOOL fInRecursiveCall);
  206. BOOL
  207. _CatDBTermJet();
  208. BOOL
  209. _CatDBAcquireOpenDatabaseFromCache(
  210. PJET_DB_STRUCT *ppJetDBStruct,
  211. LPCWSTR pwszSubSysGUID,
  212. BOOL fReadOnly,
  213. BOOL fInRecursiveCall
  214. );
  215. BOOL
  216. _CatDBReleaseDatabaseToCache(
  217. PJET_DB_STRUCT pJetDBStruct
  218. );
  219. BOOL
  220. _CatDBCloseSingleCachedDatabase(
  221. CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct
  222. );
  223. BOOL
  224. _CatDBCloseCachedDatabases();
  225. VOID CALLBACK
  226. _CatDBWaitOrTimerCallback(
  227. PVOID lpParameter,
  228. BOOLEAN fTimedOut
  229. );
  230. //
  231. // Supporting functions for s_SSCatDBAddCatalog
  232. //
  233. DWORD _CatDBAddCatalog(
  234. handle_t h,
  235. DWORD dwFlags,
  236. LPCWSTR pwszSubSysGUID,
  237. LPCWSTR pwszCatalogFile,
  238. LPCWSTR pwszCatName,
  239. BOOL fInRecursiveCall,
  240. LPWSTR __RPC_FAR *ppwszCatalogNameUsed);
  241. BOOL
  242. _CatDBAddCatalogEntriesToDatabase(
  243. PJET_DB_STRUCT pJetDBStruct,
  244. PCCTL_CONTEXT pCTLContext,
  245. LPWSTR pwszNewCatalogName
  246. );
  247. BOOL
  248. _CatDBAddHashCatNamePair(
  249. PJET_DB_STRUCT pJetDBStruct,
  250. PCRYPT_DATA_BLOB pHashBlob,
  251. LPWSTR pwszCatBaseName
  252. );
  253. BOOL
  254. _CatDBAddNewRowToHashCatNameTable(
  255. PJET_DB_STRUCT pJetDBStruct,
  256. PCRYPT_DATA_BLOB pHashBlob,
  257. LPWSTR pwszCatBaseName
  258. );
  259. BOOL
  260. _CatDBAddValueToExistingHashCatNameRow(
  261. PJET_DB_STRUCT pJetDBStruct,
  262. PCRYPT_DATA_BLOB pHashBlob,
  263. LPWSTR pwszCatBaseName
  264. );
  265. BOOL
  266. _CatDBCatnameAlreadyInHashesListOfCats(
  267. PJET_DB_STRUCT pJetDBStruct,
  268. PCRYPT_DATA_BLOB pHashBlob,
  269. LPWSTR pwszCatBaseName
  270. );
  271. BOOL
  272. _CatDBAddNewRowToCatNameBuddyTableIfNotExists(
  273. PJET_DB_STRUCT pJetDBStruct,
  274. LPWSTR pwszCatBaseName
  275. );
  276. BOOL
  277. _CatDBAddNewRowToCatNameBuddyTable(
  278. PJET_DB_STRUCT pJetDBStruct,
  279. LPWSTR pwszCatBaseName
  280. );
  281. BOOL
  282. _CatDBAddNameToBuddyList(
  283. PJET_DB_STRUCT pJetDBStruct,
  284. LPWSTR pwszNameToAdd,
  285. LPWSTR pwszListToAddTo
  286. );
  287. BOOL
  288. _CatDBAddWholeBuddyList(
  289. PJET_DB_STRUCT pJetDBStruct,
  290. LPWSTR pwszBuddyToAddTo,
  291. LPWSTR pwszBuddyListName
  292. );
  293. BOOL
  294. _CatDBMoveInUseFileToTempLocation(
  295. LPWSTR pwszFile
  296. );
  297. void
  298. _CatDBCleanupTempFiles();
  299. //
  300. // Supporting functions for s_SSCatDBDeleteCatalog
  301. //
  302. BOOL
  303. _CatDBDeleteCatalogEntriesFromDatabase(
  304. PJET_DB_STRUCT pJetDBStruct,
  305. LPWSTR pwszCatalogName
  306. );
  307. BOOL
  308. _CatDBRemoveCatNameFromHashesListOfCatNames(
  309. PJET_DB_STRUCT pJetDBStruct,
  310. PCRYPT_DATA_BLOB pHashBlob,
  311. LPWSTR pwszCatBaseName
  312. );
  313. BOOL
  314. _CatDBRemoveCatNameFromMultiValuedColumn(
  315. PJET_DB_STRUCT pJetDBStruct,
  316. JET_TABLEID jetTableID,
  317. JET_COLUMNID jetColumnID,
  318. LPWSTR pwszCatBaseName
  319. );
  320. BOOL
  321. _CatDBRemoveCatNameFromCatNameTable(
  322. PJET_DB_STRUCT pJetDBStruct,
  323. LPWSTR pwszCatBaseName
  324. );
  325. BOOL
  326. _CatDBRemoveCatNameFromBuddyTable(
  327. PJET_DB_STRUCT pJetDBStruct,
  328. LPWSTR pwszCatBaseName
  329. );
  330. //
  331. // Supporting functions for s_SSCatDBEnumCatalogs
  332. //
  333. BOOL
  334. _CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames(
  335. PJET_DB_STRUCT pJetDBStruct,
  336. LPWSTR pwszCatName,
  337. DWORD __RPC_FAR *pdwNumCatalogNames,
  338. LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames,
  339. BOOL fRecursiveCall);
  340. BOOL
  341. _CatDBAddCatNameToReturnBuddyListIfNotExist(
  342. LPWSTR pwszBuddy,
  343. DWORD __RPC_FAR *pdwNumCatalogNames,
  344. LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames
  345. );
  346. //
  347. // More general supporting functions
  348. //
  349. JET_ERR
  350. _CatDBSeekInCatNameBuddyTable(
  351. PJET_DB_STRUCT pJetDBStruct,
  352. LPWSTR pwszBuddyRow
  353. );
  354. JET_ERR
  355. _CatDBSeekInHashCatNameTable(
  356. PJET_DB_STRUCT pJetDBStruct,
  357. PCRYPT_DATA_BLOB pHashBlob
  358. );
  359. void
  360. _CatDBNotifyClients(void);
  361. LPWSTR
  362. _CatDBCreateNewCatalogFileName(
  363. LPCWSTR pwszCatalogFileDir,
  364. LPCWSTR pwszCatName,
  365. BOOL *pfFileAlreadyExists
  366. );
  367. BOOL
  368. _CatDBFindAndDecodeHashInCatEntry(
  369. PCTL_ENTRY pctlEntry,
  370. SPC_INDIRECT_DATA_CONTENT **ppIndirectData
  371. );
  372. DWORD
  373. _CatDBMapJetError(
  374. JET_ERR jerr);
  375. BOOL
  376. _CatDBJET_errFailure(
  377. JET_ERR jerr);
  378. BOOL
  379. _CatDBInitJetDatabaseParams(
  380. JET_INSTANCE *pJetInstance);
  381. BOOL
  382. _CatDBAttachAndOpenDatabase(
  383. JET_DB_STRUCT *pJetDBStruct,
  384. BOOL fReadOnly);
  385. BOOL
  386. _CatDBCloseDatabaseFile(
  387. PJET_DB_STRUCT pJetDBStruct);
  388. BOOL
  389. _CatDBCatalogFileAlreadyInstalled(
  390. LPCWSTR pwszCatalogToBeAdded,
  391. LPCWSTR pwszExistingCatalog);
  392. #define LOGEVENT_STRING_PARAMTYPE 1
  393. #define LOGEVENT_INT_PARAMTYPE 2
  394. #define LOGEVENT_NONE_PARAMTYPE 3
  395. //
  396. // Use these for memory that is transferred across an LRPC call
  397. //
  398. extern "C"
  399. {
  400. extern void __RPC_FAR * __RPC_API midl_user_allocate(size_t len);
  401. extern void __RPC_API midl_user_free(void __RPC_FAR * ptr);
  402. extern void __RPC_FAR * __RPC_API midl_user_reallocate(void __RPC_FAR * ptr, size_t len);
  403. }
  404. //
  405. // general allocation routines
  406. //
  407. void * _CatDBAlloc(size_t len)
  408. {
  409. void *temp;
  410. temp = LocalAlloc(LMEM_ZEROINIT, len);
  411. if (temp == NULL)
  412. {
  413. SetLastError(E_OUTOFMEMORY);
  414. }
  415. return(temp);
  416. }
  417. void * _CatDBReAlloc(void *p, size_t len)
  418. {
  419. void *temp;
  420. temp = LocalReAlloc(p, len, LMEM_MOVEABLE | LMEM_ZEROINIT);
  421. if (temp == NULL)
  422. {
  423. SetLastError(E_OUTOFMEMORY);
  424. }
  425. return(temp);
  426. }
  427. void _CatDBFree(void *p)
  428. {
  429. if (p != NULL)
  430. {
  431. LocalFree(p);
  432. }
  433. }
  434. LPSTR
  435. _CatDBGetCatrootDirA()
  436. {
  437. LPSTR pszTempPath = NULL;
  438. char szDefaultSystemDir[MAX_PATH + 1];
  439. DWORD dwLength;
  440. //
  441. // Get System default directory
  442. //
  443. szDefaultSystemDir[0] = NULL;
  444. if (0 == GetSystemDirectoryA(&szDefaultSystemDir[0], MAX_PATH))
  445. {
  446. CATDBSVC_LOGERR_LASTERR()
  447. return (NULL);
  448. }
  449. //
  450. // Calculate length
  451. //
  452. dwLength = strlen(szDefaultSystemDir) + strlen(SZ_DATABASE_FILE_BASE_DIRECTORY) + 3;
  453. //
  454. // Allocate space for the full path
  455. //
  456. if (NULL == (pszTempPath = (LPSTR) malloc(sizeof(char) * dwLength)))
  457. {
  458. CATDBSVC_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  459. return (NULL);
  460. }
  461. //
  462. // Make the path
  463. //
  464. strcpy(pszTempPath, szDefaultSystemDir);
  465. if ((pszTempPath[0]) &&
  466. (pszTempPath[strlen(&pszTempPath[0]) - 1] != '\\'))
  467. {
  468. strcat(pszTempPath, "\\");
  469. }
  470. strcat(pszTempPath, SZ_DATABASE_FILE_BASE_DIRECTORY);
  471. strcat(pszTempPath, "\\");
  472. ErrorMemory:
  473. return (pszTempPath);
  474. }
  475. LPWSTR
  476. _CatDBGetCatrootDirW(
  477. BOOL fCatroot2)
  478. {
  479. LPWSTR pwszTempPath = NULL;
  480. WCHAR wszDefaultSystemDir[MAX_PATH + 1];
  481. DWORD dwLength;
  482. //
  483. // Get System default directory
  484. //
  485. wszDefaultSystemDir[0] = NULL;
  486. if (0 == GetSystemDirectoryW(&wszDefaultSystemDir[0], MAX_PATH))
  487. {
  488. CATDBSVC_LOGERR_LASTERR()
  489. return (NULL);
  490. }
  491. //
  492. // Calculate length
  493. //
  494. dwLength = wcslen(wszDefaultSystemDir) + 3;
  495. if (fCatroot2)
  496. {
  497. dwLength += wcslen(WSZ_DATABASE_FILE_BASE_DIRECTORY);
  498. }
  499. else
  500. {
  501. dwLength += wcslen(WSZ_CATALOG_FILE_BASE_DIRECTORY);
  502. }
  503. //
  504. // Allocate space for the full path
  505. //
  506. if (NULL == (pwszTempPath = (LPWSTR) malloc(sizeof(WCHAR) * dwLength)))
  507. {
  508. CATDBSVC_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
  509. return (NULL);
  510. }
  511. //
  512. // Make the path
  513. //
  514. wcscpy(pwszTempPath, wszDefaultSystemDir);
  515. if ((pwszTempPath[0]) &&
  516. (pwszTempPath[wcslen(&pwszTempPath[0]) - 1] != L'\\'))
  517. {
  518. wcscat(pwszTempPath, L"\\");
  519. }
  520. if (fCatroot2)
  521. {
  522. wcscat(pwszTempPath, WSZ_DATABASE_FILE_BASE_DIRECTORY);
  523. }
  524. else
  525. {
  526. wcscat(pwszTempPath, WSZ_CATALOG_FILE_BASE_DIRECTORY);
  527. }
  528. wcscat(pwszTempPath, L"\\");
  529. ErrorMemory:
  530. return (pwszTempPath);
  531. }
  532. LPWSTR
  533. _CatDBCreatePath(
  534. IN LPCWSTR pwsz1,
  535. IN LPCWSTR pwsz2)
  536. {
  537. LPWSTR pwszTemp = NULL;
  538. int nTotalLen = 0;
  539. int nLenStr1 = 0;
  540. //
  541. // Calculate the length of the resultant string as the sum of the length
  542. // of psz1, a '\', the length of psz2, and a NULL char
  543. //
  544. nLenStr1 = wcslen(pwsz1);
  545. nTotalLen = nLenStr1 + wcslen(pwsz2) + 2;
  546. //
  547. // Allocate the string and copy pwsz1 into the buffer
  548. //
  549. if (NULL == (pwszTemp = (LPWSTR) malloc(sizeof(WCHAR) * nTotalLen)))
  550. {
  551. CATDBSVC_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorReturn)
  552. }
  553. wcscpy(pwszTemp, pwsz1);
  554. //
  555. // Add the extra '\' if needed
  556. //
  557. if (pwsz1[nLenStr1 - 1] != L'\\')
  558. {
  559. wcscat(pwszTemp, L"\\");
  560. }
  561. //
  562. // Tack on psz2
  563. //
  564. wcscat(pwszTemp, pwsz2);
  565. CommonReturn:
  566. return (pwszTemp);
  567. ErrorReturn:
  568. goto CommonReturn;
  569. }
  570. BOOL
  571. _CatDBDeleteFiles(
  572. IN LPCWSTR pwszPath,
  573. IN LPCWSTR pwszSearch)
  574. {
  575. BOOL fRet = TRUE;
  576. HANDLE hFindHandle = INVALID_HANDLE_VALUE;
  577. WIN32_FIND_DATAW FindData;
  578. DWORD dwErr;
  579. LPWSTR pwszDelete = NULL;
  580. //
  581. // Do the initial find
  582. //
  583. hFindHandle = FindFirstFileW(pwszSearch, &FindData);
  584. if (hFindHandle == INVALID_HANDLE_VALUE)
  585. {
  586. //
  587. // See if a real error occurred, or just no files
  588. //
  589. dwErr = GetLastError();
  590. if ((dwErr == ERROR_NO_MORE_FILES) ||
  591. (dwErr == ERROR_FILE_NOT_FOUND))
  592. {
  593. //
  594. // There are no files of this type to delete
  595. //
  596. return (TRUE);
  597. }
  598. else
  599. {
  600. CATDBSVC_LOGERR_LASTERR()
  601. goto ErrorReturn;
  602. }
  603. }
  604. while (1)
  605. {
  606. //
  607. // Only care about files
  608. //
  609. if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  610. {
  611. pwszDelete = _CatDBCreatePath(pwszPath, FindData.cFileName);
  612. if (pwszDelete == NULL)
  613. {
  614. CATDBSVC_LOGERR_LASTERR()
  615. goto ErrorReturn;
  616. }
  617. if (!DeleteFileW(pwszDelete))
  618. {
  619. CATDBSVC_LOGERR_LASTERR()
  620. goto ErrorReturn;
  621. }
  622. free(pwszDelete);
  623. pwszDelete = NULL;
  624. }
  625. //
  626. // Get next file
  627. //
  628. if (!FindNextFileW(hFindHandle, &FindData))
  629. {
  630. if (GetLastError() == ERROR_NO_MORE_FILES)
  631. {
  632. break;
  633. }
  634. else
  635. {
  636. CATDBSVC_LOGERR_LASTERR()
  637. goto ErrorReturn;
  638. }
  639. }
  640. }
  641. CommonReturn:
  642. if (pwszDelete != NULL)
  643. {
  644. free(pwszDelete);
  645. }
  646. return (fRet);
  647. ErrorReturn:
  648. fRet = FALSE;
  649. goto CommonReturn;
  650. }
  651. BOOL
  652. _CatDBDeleteJetFiles()
  653. {
  654. BOOL fRet = TRUE;
  655. LPWSTR pwszCatroot2 = NULL;
  656. LPWSTR pwszDelete = NULL;
  657. LPWSTR pwszSearch = NULL;
  658. LPWSTR pwszPathName = NULL;
  659. HANDLE hFindHandle = INVALID_HANDLE_VALUE;
  660. WIN32_FIND_DATAW FindData;
  661. DWORD dwErr;
  662. //
  663. // Get the directory where the jet files live
  664. //
  665. pwszCatroot2 = _CatDBGetCatrootDirW(TRUE);
  666. if (pwszCatroot2 == NULL)
  667. {
  668. CATDBSVC_LOGERR_LASTERR()
  669. goto ErrorReturn;
  670. }
  671. //
  672. // build the search string for jet log files and delete them
  673. // (there are two forms of log files).
  674. //
  675. pwszDelete = _CatDBCreatePath(pwszCatroot2, L"edb*.log");
  676. if (pwszDelete == NULL)
  677. {
  678. CATDBSVC_LOGERR_LASTERR()
  679. goto ErrorReturn;
  680. }
  681. if (!_CatDBDeleteFiles(pwszCatroot2, pwszDelete))
  682. {
  683. CATDBSVC_LOGERR_LASTERR()
  684. goto ErrorReturn;
  685. }
  686. free(pwszDelete);
  687. pwszDelete = NULL;
  688. pwszDelete = _CatDBCreatePath(pwszCatroot2, L"res*.log");
  689. if (pwszDelete == NULL)
  690. {
  691. CATDBSVC_LOGERR_LASTERR()
  692. goto ErrorReturn;
  693. }
  694. if (!_CatDBDeleteFiles(pwszCatroot2, pwszDelete))
  695. {
  696. CATDBSVC_LOGERR_LASTERR()
  697. goto ErrorReturn;
  698. }
  699. free(pwszDelete);
  700. pwszDelete = NULL;
  701. //
  702. // Delete the "catdb" and "timestamp" files in each directory
  703. //
  704. //
  705. // Build a search string for catdb directories
  706. //
  707. pwszSearch = _CatDBCreatePath(pwszCatroot2, L"{????????????????????????????????????}");
  708. if (pwszSearch == NULL)
  709. {
  710. CATDBSVC_LOGERR_LASTERR()
  711. goto ErrorReturn;
  712. }
  713. //
  714. // Do the initial find
  715. //
  716. hFindHandle = FindFirstFileW(pwszSearch, &FindData);
  717. if (hFindHandle == INVALID_HANDLE_VALUE)
  718. {
  719. //
  720. // See if a real error occurred, or just no directories
  721. //
  722. dwErr = GetLastError();
  723. if ((dwErr == ERROR_NO_MORE_FILES) ||
  724. (dwErr == ERROR_PATH_NOT_FOUND) ||
  725. (dwErr == ERROR_FILE_NOT_FOUND))
  726. {
  727. //
  728. // There are no directories of this form
  729. //
  730. goto CommonReturn;
  731. }
  732. else
  733. {
  734. CATDBSVC_LOGERR_LASTERR()
  735. goto ErrorReturn;
  736. }
  737. }
  738. while (1)
  739. {
  740. //
  741. // Only care about directories
  742. //
  743. if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  744. {
  745. pwszPathName = _CatDBCreatePath(pwszCatroot2, FindData.cFileName);
  746. if (pwszPathName == NULL)
  747. {
  748. CATDBSVC_LOGERR_LASTERR()
  749. goto ErrorReturn;
  750. }
  751. //
  752. // Delete the "catdb" file
  753. //
  754. pwszDelete = _CatDBCreatePath(pwszPathName, WSZ_DBFILE_NAME);
  755. if (pwszDelete == NULL)
  756. {
  757. CATDBSVC_LOGERR_LASTERR()
  758. goto ErrorReturn;
  759. }
  760. DeleteFileW(pwszDelete);
  761. free(pwszDelete);
  762. pwszDelete = NULL;
  763. //
  764. // Delete the "timestamp" file
  765. //
  766. pwszDelete = _CatDBCreatePath(pwszPathName, WSZ_TIME_STAMP_FILE);
  767. if (pwszDelete == NULL)
  768. {
  769. CATDBSVC_LOGERR_LASTERR()
  770. goto ErrorReturn;
  771. }
  772. DeleteFileW(pwszDelete);
  773. free(pwszDelete);
  774. pwszDelete = NULL;
  775. free(pwszPathName);
  776. pwszPathName = NULL;
  777. }
  778. //
  779. // Get next file
  780. //
  781. if (!FindNextFileW(hFindHandle, &FindData))
  782. {
  783. if (GetLastError() == ERROR_NO_MORE_FILES)
  784. {
  785. break;
  786. }
  787. else
  788. {
  789. CATDBSVC_LOGERR_LASTERR()
  790. goto ErrorReturn;
  791. }
  792. }
  793. }
  794. CommonReturn:
  795. if (pwszCatroot2 != NULL)
  796. {
  797. free(pwszCatroot2);
  798. }
  799. if (pwszDelete != NULL)
  800. {
  801. free(pwszDelete);
  802. }
  803. if (pwszSearch != NULL)
  804. {
  805. free(pwszSearch);
  806. }
  807. if (pwszPathName != NULL)
  808. {
  809. free(pwszPathName);
  810. }
  811. return (fRet);
  812. ErrorReturn:
  813. fRet = FALSE;
  814. goto CommonReturn;
  815. }
  816. BOOL
  817. _CatDBRebuildDB(
  818. LPCWSTR pwszPathName,
  819. LPCWSTR pwszDatabaseGUID)
  820. {
  821. BOOL fRet = TRUE;
  822. LPWSTR pwszSearch = NULL;
  823. LPWSTR pwszCatalog = NULL;
  824. HANDLE hFindHandle = INVALID_HANDLE_VALUE;
  825. WIN32_FIND_DATAW FindData;
  826. DWORD dwErr;
  827. LPWSTR __RPC_FAR pwszCatalogNameUsed = NULL;
  828. WCHAR wszTempFile[MAX_PATH];
  829. JET_DB_STRUCT *pJetDBStruct = NULL;
  830. //
  831. // First, just make sure the database gets created by doing
  832. // an open and close
  833. //
  834. if (!_CatDBAcquireOpenDatabaseFromCache(
  835. &pJetDBStruct,
  836. pwszDatabaseGUID,
  837. FALSE,
  838. TRUE))
  839. {
  840. CATDBSVC_LOGERR_LASTERR()
  841. goto ErrorReturn;
  842. }
  843. _CatDBReleaseDatabaseToCache(pJetDBStruct);
  844. //
  845. // Find all catalogs in direcotry and add each one
  846. //
  847. //
  848. // Build a search string for catalog files
  849. //
  850. pwszSearch = _CatDBCreatePath(pwszPathName, L"*.cat");
  851. if (pwszSearch == NULL)
  852. {
  853. CATDBSVC_LOGERR_LASTERR()
  854. goto ErrorReturn;
  855. }
  856. //
  857. // Do the initial find
  858. //
  859. hFindHandle = FindFirstFileW(pwszSearch, &FindData);
  860. if (hFindHandle == INVALID_HANDLE_VALUE)
  861. {
  862. //
  863. // See if a real error occurred, or just no directories
  864. //
  865. dwErr = GetLastError();
  866. if ((dwErr == ERROR_NO_MORE_FILES) ||
  867. (dwErr == ERROR_FILE_NOT_FOUND))
  868. {
  869. //
  870. // There are no files of this form
  871. //
  872. goto CommonReturn;
  873. }
  874. else
  875. {
  876. CATDBSVC_LOGERR_LASTERR()
  877. goto ErrorReturn;
  878. }
  879. }
  880. //
  881. // Get a temporary file name which will be used to when adding each catalog
  882. //
  883. if (0 == GetTempFileNameW(
  884. g_pwszCatalogFileBaseDirectory,
  885. L"TMP",
  886. 0,
  887. wszTempFile))
  888. {
  889. CATDBSVC_LOGERR_LASTERR()
  890. goto ErrorReturn;
  891. }
  892. //
  893. // GetTempFileName actually creates the file, so delete it
  894. //
  895. DeleteFileW(wszTempFile);
  896. while (1)
  897. {
  898. //
  899. // Only care about files
  900. //
  901. if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  902. {
  903. pwszCatalog = _CatDBCreatePath(pwszPathName, FindData.cFileName);
  904. if (pwszCatalog == NULL)
  905. {
  906. CATDBSVC_LOGERR_LASTERR()
  907. goto ErrorReturn;
  908. }
  909. //
  910. // Copy the catalog file to a temporary location and add it from there
  911. //
  912. if (!CopyFileW(pwszCatalog, wszTempFile, TRUE))
  913. {
  914. CATDBSVC_LOGERR_LASTERR()
  915. goto ErrorReturn;
  916. }
  917. _CatDBAddCatalog(
  918. NULL,
  919. 0,
  920. pwszDatabaseGUID,
  921. wszTempFile,
  922. FindData.cFileName,
  923. TRUE,
  924. &pwszCatalogNameUsed);
  925. DeleteFileW(wszTempFile);
  926. if (pwszCatalogNameUsed != NULL)
  927. {
  928. MIDL_user_free(pwszCatalogNameUsed);
  929. pwszCatalogNameUsed = NULL;
  930. }
  931. free(pwszCatalog);
  932. pwszCatalog = NULL;
  933. }
  934. //
  935. // Get next file
  936. //
  937. if (!FindNextFileW(hFindHandle, &FindData))
  938. {
  939. if (GetLastError() == ERROR_NO_MORE_FILES)
  940. {
  941. break;
  942. }
  943. else
  944. {
  945. CATDBSVC_LOGERR_LASTERR()
  946. goto ErrorReturn;
  947. }
  948. }
  949. }
  950. CommonReturn:
  951. if (pwszSearch != NULL)
  952. {
  953. free(pwszSearch);
  954. }
  955. if (pwszCatalog != NULL)
  956. {
  957. free(pwszCatalog);
  958. }
  959. return (fRet);
  960. ErrorReturn:
  961. fRet = FALSE;
  962. goto CommonReturn;
  963. }
  964. BOOL
  965. _CatDBRebuildAllDBs()
  966. {
  967. BOOL fRet = TRUE;
  968. LPWSTR pwszCatroot = NULL;
  969. LPWSTR pwszSearch = NULL;
  970. LPWSTR pwszPathName = NULL;
  971. HANDLE hFindHandle = INVALID_HANDLE_VALUE;
  972. WIN32_FIND_DATAW FindData;
  973. DWORD dwErr;
  974. //
  975. // Get the directory where the catalog files live
  976. //
  977. pwszCatroot = _CatDBGetCatrootDirW(FALSE);
  978. if (pwszCatroot == NULL)
  979. {
  980. CATDBSVC_LOGERR_LASTERR()
  981. goto ErrorReturn;
  982. }
  983. //
  984. // Build a search string for the catalog directories
  985. //
  986. pwszSearch = _CatDBCreatePath(pwszCatroot, L"{????????????????????????????????????}");
  987. if (pwszSearch == NULL)
  988. {
  989. CATDBSVC_LOGERR_LASTERR()
  990. goto ErrorReturn;
  991. }
  992. //
  993. // Do the initial find
  994. //
  995. hFindHandle = FindFirstFileW(pwszSearch, &FindData);
  996. if (hFindHandle == INVALID_HANDLE_VALUE)
  997. {
  998. //
  999. // See if a real error occurred, or just no directories
  1000. //
  1001. dwErr = GetLastError();
  1002. if ((dwErr == ERROR_NO_MORE_FILES) ||
  1003. (dwErr == ERROR_PATH_NOT_FOUND) ||
  1004. (dwErr == ERROR_FILE_NOT_FOUND))
  1005. {
  1006. //
  1007. // There are no directories of this form
  1008. //
  1009. goto CommonReturn;
  1010. }
  1011. else
  1012. {
  1013. CATDBSVC_LOGERR_LASTERR()
  1014. goto ErrorReturn;
  1015. }
  1016. }
  1017. while (1)
  1018. {
  1019. //
  1020. // Only care about directories
  1021. //
  1022. if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1023. {
  1024. pwszPathName = _CatDBCreatePath(pwszCatroot, FindData.cFileName);
  1025. if (pwszPathName == NULL)
  1026. {
  1027. CATDBSVC_LOGERR_LASTERR()
  1028. goto ErrorReturn;
  1029. }
  1030. if (!_CatDBRebuildDB(pwszPathName, FindData.cFileName))
  1031. {
  1032. CATDBSVC_LOGERR_LASTERR()
  1033. goto ErrorReturn;
  1034. }
  1035. free(pwszPathName);
  1036. pwszPathName = NULL;
  1037. }
  1038. //
  1039. // Get next file
  1040. //
  1041. if (!FindNextFileW(hFindHandle, &FindData))
  1042. {
  1043. if (GetLastError() == ERROR_NO_MORE_FILES)
  1044. {
  1045. break;
  1046. }
  1047. else
  1048. {
  1049. CATDBSVC_LOGERR_LASTERR()
  1050. goto ErrorReturn;
  1051. }
  1052. }
  1053. }
  1054. CommonReturn:
  1055. if (pwszCatroot != NULL)
  1056. {
  1057. free(pwszCatroot);
  1058. }
  1059. if (pwszSearch != NULL)
  1060. {
  1061. free(pwszSearch);
  1062. }
  1063. if (pwszPathName != NULL)
  1064. {
  1065. free(pwszPathName);
  1066. }
  1067. return (fRet);
  1068. ErrorReturn:
  1069. fRet = FALSE;
  1070. goto CommonReturn;
  1071. }
  1072. /////////////////////////////////////////////////////////////////////////////////////////
  1073. //
  1074. // LPC-exposed functions
  1075. //
  1076. // these functions return a DWORD equivalent to GetLastError(). The client side stub
  1077. // code will check if the return code is not ERROR_SUCCESS, and if this is the case,
  1078. // the client stub will return FALSE and SetLastError() to this DWORD.
  1079. //
  1080. /////////////////////////////////////////////////////////////////////////////////////////
  1081. DWORD _CatDBAddCatalog(
  1082. handle_t h,
  1083. DWORD dwFlags,
  1084. LPCWSTR pwszSubSysGUID,
  1085. LPCWSTR pwszCatalogFile,
  1086. LPCWSTR pwszCatName,
  1087. BOOL fInRecursiveCall,
  1088. LPWSTR __RPC_FAR *ppwszCatalogNameUsed)
  1089. {
  1090. DWORD dwRet = ERROR_SUCCESS;
  1091. RPC_STATUS RpcStatus;
  1092. LPWSTR pwszCatalogFileDir = NULL;
  1093. BOOL fImpersonating = FALSE;
  1094. JET_DB_STRUCT *pJetDBStruct = NULL;
  1095. BOOL fCatalogDatabaseAcquiredFromCache = FALSE;
  1096. PCCTL_CONTEXT pCTLContext = NULL;
  1097. LPWSTR pwszNewCatalogName = NULL;
  1098. HANDLE hMappedFile = NULL;
  1099. BYTE *pbMappedFile = NULL;
  1100. BOOL fTransactionBegun = FALSE;
  1101. BOOL fFileAlreadyExists = FALSE;
  1102. WCHAR wszTempFile[MAX_PATH];
  1103. JET_ERR jerr;
  1104. BOOL fTempFileCreated = FALSE;
  1105. BOOL fCSEntered = FALSE;
  1106. //
  1107. // Initialize out param
  1108. //
  1109. *ppwszCatalogNameUsed = NULL;
  1110. //
  1111. // Only allow one add or delete at a time
  1112. //
  1113. __try
  1114. {
  1115. EnterCriticalSection(&g_CatDBAddDeleteCS);
  1116. }
  1117. __except(EXCEPTION_EXECUTE_HANDLER)
  1118. {
  1119. CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorEnterCS)
  1120. }
  1121. fCSEntered = TRUE;
  1122. //
  1123. // Impersonate client if needed
  1124. //
  1125. if (h != NULL)
  1126. {
  1127. if (ERROR_SUCCESS != (RpcStatus = RpcImpersonateClient(h)))
  1128. {
  1129. CATDBSVC_SETERR_LOG_RETURN(RpcStatus, ErrorImpersonateClient);
  1130. }
  1131. fImpersonating = TRUE;
  1132. }
  1133. //
  1134. // Create the path to the catalog files
  1135. //
  1136. if (NULL == (pwszCatalogFileDir = _CATDBConstructWSTRPath(
  1137. g_pwszCatalogFileBaseDirectory,
  1138. pwszSubSysGUID)))
  1139. {
  1140. CATDBSVC_LOGERR_LASTERR()
  1141. goto ErrorReturn;
  1142. }
  1143. //
  1144. // Get the fully qualified path name of the new catalog file
  1145. //
  1146. if (NULL == (pwszNewCatalogName = _CatDBCreateNewCatalogFileName(
  1147. pwszCatalogFileDir,
  1148. pwszCatName,
  1149. &fFileAlreadyExists)))
  1150. {
  1151. CATDBSVC_LOGERR_LASTERR()
  1152. goto ErrorReturn;
  1153. }
  1154. if (NULL == (*ppwszCatalogNameUsed = (LPWSTR)
  1155. midl_user_allocate((wcslen(pwszNewCatalogName) + 1) * sizeof(WCHAR))))
  1156. {
  1157. CATDBSVC_SETERR_LOG_RETURN(E_OUTOFMEMORY, ErrorMemory)
  1158. }
  1159. wcscpy(*ppwszCatalogNameUsed, pwszNewCatalogName);
  1160. //
  1161. // Open a CTL context on the catalog being added
  1162. //
  1163. if (!CatUtil_CreateCTLContextFromFileName(
  1164. pwszCatalogFile,
  1165. &hMappedFile,
  1166. &pbMappedFile,
  1167. &pCTLContext,
  1168. FALSE))
  1169. {
  1170. CATDBSVC_LOGERR_LASTERR()
  1171. goto ErrorReturn;
  1172. }
  1173. //
  1174. // If we are replacing an existing catalog, save a copy of the old one
  1175. // in case the commit fails
  1176. //
  1177. if (fFileAlreadyExists)
  1178. {
  1179. if (0 == GetTempFileNameW(
  1180. g_pwszCatalogFileBaseDirectory,
  1181. L"TMP",
  1182. 0,
  1183. wszTempFile))
  1184. {
  1185. //
  1186. // If the entries couldn't be deleted because the user doesn't
  1187. // have write rights, then do a check to see if the catalog
  1188. // they are trying to add already exists, if it does, then
  1189. // retrun ERROR_ALREADY_EXISTS instead of ACCESS_DENIED
  1190. //
  1191. if (GetLastError() == ERROR_ACCESS_DENIED)
  1192. {
  1193. if (_CatDBCatalogFileAlreadyInstalled(
  1194. pwszCatalogFile,
  1195. pwszNewCatalogName))
  1196. {
  1197. SetLastError(ERROR_ALREADY_EXISTS);
  1198. goto ErrorReturn;
  1199. }
  1200. }
  1201. else
  1202. {
  1203. CATDBSVC_LOGERR_LASTERR()
  1204. goto ErrorGetTempFileName;
  1205. }
  1206. }
  1207. //
  1208. // Copy the old catalog file to a temporary location
  1209. //
  1210. if (!CopyFileW(pwszNewCatalogName, wszTempFile, FALSE))
  1211. {
  1212. CATDBSVC_LOGERR_LASTERR()
  1213. goto ErrorCopyFile;
  1214. }
  1215. fTempFileCreated = TRUE;
  1216. }
  1217. //
  1218. // Open the database file
  1219. //
  1220. if (!_CatDBAcquireOpenDatabaseFromCache(
  1221. &pJetDBStruct,
  1222. pwszSubSysGUID,
  1223. FALSE,
  1224. fInRecursiveCall))
  1225. {
  1226. CATDBSVC_LOGERR_LASTERR()
  1227. goto ErrorReturn;
  1228. }
  1229. fCatalogDatabaseAcquiredFromCache = TRUE;
  1230. //
  1231. // Start transaction
  1232. //
  1233. if (_CatDBJET_errFailure(jerr =
  1234. JetBeginTransaction(pJetDBStruct->JetSesID)))
  1235. {
  1236. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetBeginTransaction)
  1237. }
  1238. fTransactionBegun = TRUE;
  1239. if (fFileAlreadyExists)
  1240. {
  1241. if (!_CatDBDeleteCatalogEntriesFromDatabase(
  1242. pJetDBStruct,
  1243. pwszNewCatalogName))
  1244. {
  1245. CATDBSVC_LOGERR_LASTERR()
  1246. goto ErrorReturn;
  1247. }
  1248. }
  1249. //
  1250. // Add the new DB entries
  1251. //
  1252. if (!_CatDBAddCatalogEntriesToDatabase(
  1253. pJetDBStruct,
  1254. pCTLContext,
  1255. pwszNewCatalogName))
  1256. {
  1257. CATDBSVC_LOGERR_LASTERR()
  1258. goto ErrorReturn;
  1259. }
  1260. //
  1261. // Don't need the CTL context anymore
  1262. //
  1263. CertFreeCTLContext(pCTLContext);
  1264. pCTLContext = NULL;
  1265. UnmapViewOfFile(pbMappedFile);
  1266. pbMappedFile = NULL;
  1267. CloseHandle(hMappedFile);
  1268. hMappedFile = NULL;
  1269. //
  1270. // Now, copy the new catalog file to its location
  1271. //
  1272. if (!CopyFileW(pwszCatalogFile, pwszNewCatalogName, FALSE))
  1273. {
  1274. if (!fFileAlreadyExists)
  1275. {
  1276. CATDBSVC_LOGERR_LASTERR()
  1277. goto ErrorCopyFile;
  1278. }
  1279. //
  1280. // Since that failed, try renaming the destination file, and then re-copy.
  1281. // BTW, the above copy will fail if another client already has the
  1282. // destination file memory mapped in their catalog cache.
  1283. //
  1284. if (!_CatDBMoveInUseFileToTempLocation(pwszNewCatalogName))
  1285. {
  1286. CATDBSVC_LOGERR_LASTERR()
  1287. goto ErrorReturn;
  1288. }
  1289. //
  1290. // Now, retry the copy... this better work!
  1291. //
  1292. if (!CopyFileW(pwszCatalogFile, pwszNewCatalogName, FALSE))
  1293. {
  1294. CATDBSVC_LOGERR_LASTERR()
  1295. goto ErrorCopyFile;
  1296. }
  1297. }
  1298. SetFileAttributesW(pwszNewCatalogName, FILE_ATTRIBUTE_SYSTEM);
  1299. //
  1300. // At this stage do the commit.
  1301. //
  1302. if (_CatDBJET_errFailure(jerr =
  1303. JetCommitTransaction(
  1304. pJetDBStruct->JetSesID,
  1305. 0)))
  1306. {
  1307. //
  1308. // Since there was an error doing the commit, copy back the original
  1309. // catalog file
  1310. //
  1311. if (0 == CopyFileW(wszTempFile, pwszNewCatalogName, FALSE))
  1312. {
  1313. // THE ABOVE COOPY FAILED... THE DATABASE IS NOW INCONSISTENT!!!!!
  1314. CATDBSVC_LOGERR_LASTERR()
  1315. }
  1316. else
  1317. {
  1318. SetFileAttributesW(pwszNewCatalogName, FILE_ATTRIBUTE_SYSTEM);
  1319. }
  1320. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetCommitTransaction)
  1321. }
  1322. fTransactionBegun = FALSE;
  1323. _CatDBTouchTimeStampFile(pwszSubSysGUID);
  1324. //
  1325. // Release DB back to the cache
  1326. //
  1327. _CatDBReleaseDatabaseToCache(pJetDBStruct);
  1328. //
  1329. // Notify client of changes
  1330. //
  1331. _CatDBNotifyClients();
  1332. CommonReturn:
  1333. if (fTempFileCreated)
  1334. {
  1335. DeleteFileW(wszTempFile);
  1336. }
  1337. if (pwszNewCatalogName != NULL)
  1338. {
  1339. _CatDBFree(pwszNewCatalogName);
  1340. }
  1341. if (pwszCatalogFileDir != NULL)
  1342. {
  1343. _CatDBFree(pwszCatalogFileDir);
  1344. }
  1345. if (pCTLContext != NULL)
  1346. {
  1347. CertFreeCTLContext(pCTLContext);
  1348. }
  1349. if (pbMappedFile != NULL)
  1350. {
  1351. UnmapViewOfFile(pbMappedFile);
  1352. }
  1353. if (hMappedFile != NULL)
  1354. {
  1355. CloseHandle(hMappedFile);
  1356. }
  1357. if (fImpersonating)
  1358. {
  1359. RpcRevertToSelf();
  1360. }
  1361. if (fCSEntered)
  1362. {
  1363. LeaveCriticalSection(&g_CatDBAddDeleteCS);
  1364. }
  1365. return dwRet;
  1366. ErrorReturn:
  1367. dwRet = GetLastError();
  1368. if (0 == dwRet)
  1369. {
  1370. dwRet = (DWORD) E_UNEXPECTED;
  1371. }
  1372. if (fTransactionBegun)
  1373. {
  1374. JetRollback(pJetDBStruct->JetSesID, 0);
  1375. }
  1376. if (fCatalogDatabaseAcquiredFromCache)
  1377. {
  1378. _CatDBReleaseDatabaseToCache(pJetDBStruct);
  1379. }
  1380. if (*ppwszCatalogNameUsed != NULL)
  1381. {
  1382. midl_user_free(*ppwszCatalogNameUsed);
  1383. *ppwszCatalogNameUsed = NULL;
  1384. }
  1385. goto CommonReturn;
  1386. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorImpersonateClient)
  1387. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetBeginTransaction)
  1388. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetCommitTransaction)
  1389. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory)
  1390. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorEnterCS)
  1391. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorCopyFile)
  1392. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorGetTempFileName)
  1393. }
  1394. DWORD s_SSCatDBAddCatalog(
  1395. /* [in] */ handle_t h,
  1396. /* [in] */ DWORD ProcessID,
  1397. /* [in] */ DWORD dwFlags,
  1398. /* [in] */ LPCWSTR pwszSubSysGUID,
  1399. /* [in] */ LPCWSTR pwszCatalogFile,
  1400. /* [unique][in] */ LPCWSTR pwszCatName,
  1401. /* [out] */ LPWSTR __RPC_FAR *ppwszCatalogNameUsed)
  1402. {
  1403. DWORD dwRet;
  1404. if (!_CatDBClientEnter())
  1405. {
  1406. CATDBSVC_LOGERR_LASTERR()
  1407. return (GetLastError());
  1408. }
  1409. //
  1410. // Check input params
  1411. //
  1412. if (h == NULL)
  1413. {
  1414. CATDBSVC_SETERR_LOG_RETURN(ERROR_BAD_ARGUMENTS, ErrorReturn)
  1415. }
  1416. dwRet = _CatDBAddCatalog(
  1417. h,
  1418. dwFlags,
  1419. pwszSubSysGUID,
  1420. pwszCatalogFile,
  1421. pwszCatName,
  1422. FALSE,
  1423. ppwszCatalogNameUsed);
  1424. _CatDBClientExit();
  1425. CommonReturn:
  1426. return (dwRet);
  1427. ErrorReturn:
  1428. dwRet = GetLastError();
  1429. goto CommonReturn;
  1430. }
  1431. DWORD s_SSCatDBDeleteCatalog(
  1432. /* [in] */ handle_t h,
  1433. /* [in] */ DWORD ProcessID,
  1434. /* [in] */ DWORD dwFlags,
  1435. /* [in] */ LPCWSTR pwszSubSysGUID,
  1436. /* [in] */ LPCWSTR pwszCatalogFile)
  1437. {
  1438. DWORD dwRet = 0;
  1439. RPC_STATUS RpcStatus;
  1440. BOOL fImpersonating = FALSE;
  1441. JET_DB_STRUCT *pJetDBStruct = NULL;
  1442. BOOL fCatalogDatabaseAcquiredFromCache = FALSE;
  1443. JET_ERR jerr;
  1444. BOOL fCSEntered = FALSE;
  1445. LPWSTR pwszCatalogFileFullPath = NULL;
  1446. BOOL fTransactionBegun = FALSE;
  1447. LPWSTR pwszCatalogFileDir = NULL;
  1448. if (!_CatDBClientEnter())
  1449. {
  1450. CATDBSVC_LOGERR_LASTERR()
  1451. return (GetLastError());
  1452. }
  1453. //
  1454. // Check input params
  1455. //
  1456. if (h == NULL)
  1457. {
  1458. CATDBSVC_SETERR_LOG_RETURN(E_INVALIDARG, ErrorInvalidArg)
  1459. }
  1460. //
  1461. // Only allow one add or delete at a time
  1462. //
  1463. __try
  1464. {
  1465. EnterCriticalSection(&g_CatDBAddDeleteCS);
  1466. }
  1467. __except(EXCEPTION_EXECUTE_HANDLER)
  1468. {
  1469. CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorEnterCS)
  1470. }
  1471. fCSEntered = TRUE;
  1472. //
  1473. // Impersonate client
  1474. //
  1475. if (ERROR_SUCCESS != (RpcStatus = RpcImpersonateClient(h)))
  1476. {
  1477. CATDBSVC_SETERR_LOG_RETURN(RpcStatus, ErrorImpersonateClient)
  1478. }
  1479. fImpersonating = TRUE;
  1480. //
  1481. // Create the path to the catalog files
  1482. //
  1483. if (NULL == (pwszCatalogFileDir = _CATDBConstructWSTRPath(
  1484. g_pwszCatalogFileBaseDirectory,
  1485. pwszSubSysGUID)))
  1486. {
  1487. CATDBSVC_LOGERR_LASTERR()
  1488. goto ErrorReturn;
  1489. }
  1490. //
  1491. // Construct full path to catalog being deleted
  1492. //
  1493. if (NULL == (pwszCatalogFileFullPath =
  1494. _CATDBConstructWSTRPath(pwszCatalogFileDir, pwszCatalogFile)))
  1495. {
  1496. CATDBSVC_LOGERR_LASTERR()
  1497. goto ErrorReturn;
  1498. }
  1499. //
  1500. // Open the database file
  1501. //
  1502. if (!_CatDBAcquireOpenDatabaseFromCache(
  1503. &pJetDBStruct,
  1504. pwszSubSysGUID,
  1505. FALSE,
  1506. FALSE))
  1507. {
  1508. CATDBSVC_LOGERR_LASTERR()
  1509. goto ErrorReturn;
  1510. }
  1511. fCatalogDatabaseAcquiredFromCache = TRUE;
  1512. //
  1513. // Start transaction
  1514. //
  1515. if (_CatDBJET_errFailure(jerr =
  1516. JetBeginTransaction(pJetDBStruct->JetSesID)))
  1517. {
  1518. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetBeginTransaction)
  1519. }
  1520. fTransactionBegun = TRUE;
  1521. //
  1522. // Delete the entries of the catalog file from the DB
  1523. //
  1524. if (!_CatDBDeleteCatalogEntriesFromDatabase(
  1525. pJetDBStruct,
  1526. pwszCatalogFileFullPath))
  1527. {
  1528. CATDBSVC_LOGERR_LASTERR()
  1529. goto ErrorReturn;
  1530. }
  1531. //
  1532. // At this stage do the commit.
  1533. //
  1534. if (_CatDBJET_errFailure(jerr =
  1535. JetCommitTransaction(
  1536. pJetDBStruct->JetSesID,
  1537. 0)))
  1538. {
  1539. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetCommitTransaction)
  1540. }
  1541. fTransactionBegun = FALSE;
  1542. if (!DeleteFileW(pwszCatalogFileFullPath))
  1543. {
  1544. //
  1545. // Maybe the delete failed since the file doesn't even exist
  1546. //
  1547. if (GetLastError() != ERROR_FILE_NOT_FOUND)
  1548. {
  1549. //
  1550. // If the delete failed for a reason other than NOT_FOUND
  1551. // then another client is probably already accessing the file,
  1552. // so just copy it to a temp location and log it for deletion
  1553. //
  1554. if (!_CatDBMoveInUseFileToTempLocation(pwszCatalogFileFullPath))
  1555. {
  1556. CATDBSVC_LOGERR_LASTERR()
  1557. //
  1558. // Don't return an error, since this isn't fatal
  1559. //
  1560. }
  1561. }
  1562. }
  1563. //
  1564. // Release DB back to the cache
  1565. //
  1566. _CatDBReleaseDatabaseToCache(pJetDBStruct);
  1567. //
  1568. // Notify client of changes
  1569. //
  1570. _CatDBNotifyClients();
  1571. _CatDBTouchTimeStampFile(pwszSubSysGUID);
  1572. CommonReturn:
  1573. if (pwszCatalogFileFullPath != NULL)
  1574. {
  1575. _CatDBFree(pwszCatalogFileFullPath);
  1576. }
  1577. if (pwszCatalogFileDir != NULL)
  1578. {
  1579. _CatDBFree(pwszCatalogFileDir);
  1580. }
  1581. if(fImpersonating)
  1582. {
  1583. RpcRevertToSelf();
  1584. }
  1585. if (fCSEntered)
  1586. {
  1587. LeaveCriticalSection(&g_CatDBAddDeleteCS);
  1588. }
  1589. _CatDBClientExit();
  1590. return dwRet;
  1591. ErrorReturn:
  1592. dwRet = GetLastError();
  1593. if (0 == dwRet)
  1594. {
  1595. dwRet = (DWORD) E_UNEXPECTED;
  1596. }
  1597. if (fTransactionBegun)
  1598. {
  1599. JetRollback(pJetDBStruct->JetSesID, 0);
  1600. }
  1601. if (fCatalogDatabaseAcquiredFromCache)
  1602. {
  1603. _CatDBReleaseDatabaseToCache(pJetDBStruct);
  1604. }
  1605. goto CommonReturn;
  1606. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorInvalidArg)
  1607. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorImpersonateClient)
  1608. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetBeginTransaction)
  1609. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetCommitTransaction)
  1610. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorEnterCS)
  1611. }
  1612. DWORD s_SSCatDBEnumCatalogs(
  1613. /* [in] */ handle_t h,
  1614. /* [in] */ DWORD ProcessID,
  1615. /* [in] */ DWORD dwFlags,
  1616. /* [in] */ LPCWSTR pwszSubSysGUID,
  1617. /* [size_is][in] */ BYTE __RPC_FAR *pbHash,
  1618. /* [in] */ DWORD cbHash,
  1619. /* [out] */ DWORD __RPC_FAR *pdwNumCatalogNames,
  1620. /* [size_is][size_is][out] */ LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames)
  1621. {
  1622. DWORD dwRet = ERROR_SUCCESS;
  1623. RPC_STATUS RpcStatus;
  1624. JET_DB_STRUCT *pJetDBStruct;
  1625. JET_ERR jerr;
  1626. BOOL fCatalogDatabaseAcquiredFromCache = FALSE;
  1627. CRYPT_HASH_BLOB HashBlob;
  1628. JET_RETINFO JetRetInfo;
  1629. WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH];
  1630. DWORD dwLength;
  1631. DWORD i;
  1632. if (!_CatDBClientEnter())
  1633. {
  1634. CATDBSVC_LOGERR_LASTERR()
  1635. return (GetLastError());
  1636. }
  1637. if (h == NULL)
  1638. {
  1639. CATDBSVC_SETERR_LOG_RETURN(E_INVALIDARG, ErrorInvalidArg)
  1640. }
  1641. //
  1642. // Init out vars
  1643. //
  1644. *pdwNumCatalogNames = 0;
  1645. *pppwszCatalogNames = NULL;
  1646. //
  1647. // Open the database file
  1648. //
  1649. if (!_CatDBAcquireOpenDatabaseFromCache(
  1650. &pJetDBStruct,
  1651. pwszSubSysGUID,
  1652. TRUE,
  1653. FALSE))
  1654. {
  1655. CATDBSVC_LOGERR_LASTERR()
  1656. goto ErrorReturn;
  1657. }
  1658. fCatalogDatabaseAcquiredFromCache = TRUE;
  1659. //
  1660. // Try to find the hash
  1661. //
  1662. HashBlob.pbData = pbHash;
  1663. HashBlob.cbData = cbHash;
  1664. jerr = _CatDBSeekInHashCatNameTable(pJetDBStruct, &HashBlob);
  1665. if (jerr == JET_errSuccess)
  1666. {
  1667. //
  1668. // Add all names from the Hashes CatNameList, plus all the buddys
  1669. // of those CatNames
  1670. //
  1671. // NOTE: the order in which the CatNames are added to the list results in
  1672. // only the first CatName of the list being guaranteed to contain the
  1673. // hash... all other CatNames may or may not contain the hash. This
  1674. // is OK because the client side code only assumes the first CatName
  1675. // contains the hash, and then explicitly searches all others for the hash.
  1676. //
  1677. memset(&JetRetInfo, 0, sizeof(JetRetInfo));
  1678. JetRetInfo.cbStruct = sizeof(JetRetInfo);
  1679. JetRetInfo.itagSequence = 1;
  1680. jerr = JetRetrieveColumn(
  1681. pJetDBStruct->JetSesID,
  1682. pJetDBStruct->JetHashCatNameTableID,
  1683. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  1684. wszCatalogName,
  1685. CATDB_MAX_CATNAME_LENGTH,
  1686. &dwLength,
  1687. JET_bitRetrieveCopy,
  1688. &JetRetInfo);
  1689. while (jerr == JET_errSuccess)
  1690. {
  1691. if (!_CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames(
  1692. pJetDBStruct,
  1693. wszCatalogName,
  1694. pdwNumCatalogNames,
  1695. pppwszCatalogNames,
  1696. FALSE))
  1697. {
  1698. CATDBSVC_LOGERR_LASTERR()
  1699. goto ErrorReturn;
  1700. }
  1701. //
  1702. // Setup for next loop
  1703. //
  1704. JetRetInfo.itagSequence++;
  1705. jerr = JetRetrieveColumn(
  1706. pJetDBStruct->JetSesID,
  1707. pJetDBStruct->JetHashCatNameTableID,
  1708. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  1709. wszCatalogName,
  1710. CATDB_MAX_CATNAME_LENGTH,
  1711. &dwLength,
  1712. JET_bitRetrieveCopy,
  1713. &JetRetInfo);
  1714. }
  1715. //
  1716. // Check to see if a real error occurred and not just a JET_wrnColumnNull
  1717. //
  1718. if (_CatDBJET_errFailure(jerr))
  1719. {
  1720. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  1721. }
  1722. }
  1723. else if ((jerr != JET_errRecordNotFound) && _CatDBJET_errFailure(jerr))
  1724. {
  1725. //
  1726. // Some real error occurred
  1727. //
  1728. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  1729. }
  1730. CommonReturn:
  1731. if (fCatalogDatabaseAcquiredFromCache)
  1732. {
  1733. _CatDBReleaseDatabaseToCache(pJetDBStruct);
  1734. }
  1735. _CatDBClientExit();
  1736. return dwRet;
  1737. ErrorReturn:
  1738. dwRet = GetLastError();
  1739. if (0 == dwRet)
  1740. {
  1741. dwRet = (DWORD) E_UNEXPECTED;
  1742. }
  1743. for (i=0; i<(*pdwNumCatalogNames); i++)
  1744. {
  1745. midl_user_free((*pppwszCatalogNames)[i]);
  1746. }
  1747. if ((*pppwszCatalogNames) != NULL)
  1748. {
  1749. midl_user_free(*pppwszCatalogNames);
  1750. *pppwszCatalogNames = NULL;
  1751. }
  1752. *pdwNumCatalogNames = 0;
  1753. goto CommonReturn;
  1754. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorInvalidArg)
  1755. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  1756. }
  1757. //---------------------------------------------------------------------------------------
  1758. //
  1759. // _CatDBProcessExitCallback
  1760. //
  1761. //---------------------------------------------------------------------------------------
  1762. VOID CALLBACK
  1763. _CatDBProcessExitCallback(
  1764. PVOID lpParameter,
  1765. BOOLEAN TimerOrWaitFired)
  1766. {
  1767. LONG lNotificationID = PtrToLong(lpParameter);
  1768. DWORD i;
  1769. HANDLE h;
  1770. __try
  1771. {
  1772. EnterCriticalSection(&g_CatDBRegisterNotifyCS);
  1773. }
  1774. __except(EXCEPTION_EXECUTE_HANDLER)
  1775. {
  1776. return;
  1777. }
  1778. //
  1779. // Search through the array to make sure the handle wasn't already unregistered
  1780. //
  1781. i = 0;
  1782. while ( (i < g_NumNotificationStructs) &&
  1783. (g_rgNotificationStructs[i].lNotificationID != lNotificationID))
  1784. {
  1785. i++;
  1786. }
  1787. //
  1788. // If it was found, then clean it up.
  1789. //
  1790. if (i < g_NumNotificationStructs)
  1791. {
  1792. g_rgNotificationStructs[i].ProcessID = 0;
  1793. CloseHandle(g_rgNotificationStructs[i].hClientProcess);
  1794. g_rgNotificationStructs[i].hClientProcess = NULL;
  1795. h = (HANDLE) InterlockedExchangePointer(
  1796. &(g_rgNotificationStructs[i].hRegisterWaitFor),
  1797. NULL);
  1798. if (h != NULL)
  1799. {
  1800. UnregisterWait(g_rgNotificationStructs[i].hRegisterWaitFor);
  1801. }
  1802. g_rgNotificationStructs[i].hNotificationHandle = INVALID_HANDLE_VALUE;
  1803. CloseHandle(g_rgNotificationStructs[i].hDuplicatedNotificationHandle);
  1804. g_rgNotificationStructs[i].hDuplicatedNotificationHandle =
  1805. INVALID_HANDLE_VALUE;
  1806. g_rgNotificationStructs[i].lNotificationID = 0;
  1807. }
  1808. LeaveCriticalSection(&g_CatDBRegisterNotifyCS);
  1809. }
  1810. DWORD s_SSCatDBRegisterForChangeNotification(
  1811. /* [in] */ handle_t h,
  1812. /* [in] */ DWORD ProcessID,
  1813. /* [in] */ DWORD_PTR EventHandle,
  1814. /* [in] */ DWORD dwFlags,
  1815. /* [in] */ LPCWSTR pwszSubSysGUID,
  1816. /* [in] */ BOOL fUnRegister)
  1817. {
  1818. DWORD dwRet = ERROR_SUCCESS;
  1819. HANDLE hDuplicate = INVALID_HANDLE_VALUE;
  1820. DWORD i, j;
  1821. BOOL fCSEntered = FALSE;
  1822. HANDLE hWaitForToUnregister = NULL;
  1823. HANDLE hClientProcess = NULL;
  1824. LONG lLocalNotificationID = 0;
  1825. NOTIFICATION_STRUCT *rghTemp;
  1826. if (!_CatDBClientEnter())
  1827. {
  1828. CATDBSVC_LOGERR_LASTERR()
  1829. return (GetLastError());
  1830. }
  1831. if (h == NULL)
  1832. {
  1833. CATDBSVC_SETERR_LOG_RETURN(E_INVALIDARG, ErrorInvalidArg)
  1834. goto ErrorInvalidArg;
  1835. }
  1836. //
  1837. // NOTE: this is a implementation that just notifies
  1838. // all clients when an add/delete catalog occurs... regardless
  1839. // of what catalog sub-system has been modified and what sub-system
  1840. // the client is operating in. Because of this implementation
  1841. // pwszCatalogDir is NOT USED. If this changes, the client side code
  1842. // will also need to change. See the NOTE in the
  1843. // _CatAdminRegisterForChangeNotification() function of catadnew.cpp
  1844. //
  1845. __try
  1846. {
  1847. EnterCriticalSection(&g_CatDBRegisterNotifyCS);
  1848. }
  1849. __except(EXCEPTION_EXECUTE_HANDLER)
  1850. {
  1851. CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorEnterCS)
  1852. }
  1853. fCSEntered = TRUE;
  1854. //
  1855. // First check to see whether we are registering or unregestering
  1856. //
  1857. if (!fUnRegister)
  1858. {
  1859. //
  1860. // Make sure we can get a slot to add the handle to
  1861. //
  1862. i = 0;
  1863. while ( (i < g_NumNotificationStructs) &&
  1864. (g_rgNotificationStructs[i].hClientProcess != NULL))
  1865. {
  1866. i++;
  1867. }
  1868. //
  1869. // If no space, allocate more
  1870. //
  1871. if (i >= g_NumNotificationStructs)
  1872. {
  1873. if (g_NumNotificationStructs == 0)
  1874. {
  1875. //
  1876. // None allocated yet, so allocate and initialize
  1877. //
  1878. if (NULL == (g_rgNotificationStructs = (NOTIFICATION_STRUCT *)
  1879. _CatDBAlloc(sizeof(NOTIFICATION_STRUCT) *
  1880. ALLOCATION_BLOCK_SIZE)))
  1881. {
  1882. CATDBSVC_LOGERR_LASTERR()
  1883. goto ErrorMemory;
  1884. }
  1885. g_NumNotificationStructs = ALLOCATION_BLOCK_SIZE;
  1886. for (j = 0; j < g_NumNotificationStructs; j++)
  1887. {
  1888. g_rgNotificationStructs[j].ProcessID = 0;
  1889. g_rgNotificationStructs[j].hClientProcess = NULL;
  1890. g_rgNotificationStructs[j].hRegisterWaitFor = NULL;
  1891. g_rgNotificationStructs[j].hNotificationHandle =
  1892. INVALID_HANDLE_VALUE;
  1893. g_rgNotificationStructs[j].hDuplicatedNotificationHandle =
  1894. INVALID_HANDLE_VALUE;
  1895. g_rgNotificationStructs[j].lNotificationID = 0;
  1896. }
  1897. // set i so it can just be used as open slot
  1898. i = 0;
  1899. }
  1900. else
  1901. {
  1902. rghTemp = g_rgNotificationStructs;
  1903. if (NULL == (g_rgNotificationStructs = (NOTIFICATION_STRUCT *)
  1904. _CatDBReAlloc(g_rgNotificationStructs,
  1905. sizeof(NOTIFICATION_STRUCT) *
  1906. (g_NumNotificationStructs +
  1907. ALLOCATION_BLOCK_SIZE))))
  1908. {
  1909. g_rgNotificationStructs = rghTemp;
  1910. CATDBSVC_LOGERR_LASTERR()
  1911. goto ErrorMemory;
  1912. }
  1913. for ( j = g_NumNotificationStructs;
  1914. j < (g_NumNotificationStructs + ALLOCATION_BLOCK_SIZE);
  1915. j++)
  1916. {
  1917. g_rgNotificationStructs[j].ProcessID = 0;
  1918. g_rgNotificationStructs[j].hClientProcess = NULL;
  1919. g_rgNotificationStructs[j].hRegisterWaitFor = NULL;
  1920. g_rgNotificationStructs[j].hNotificationHandle =
  1921. INVALID_HANDLE_VALUE;
  1922. g_rgNotificationStructs[j].hDuplicatedNotificationHandle =
  1923. INVALID_HANDLE_VALUE;
  1924. g_rgNotificationStructs[j].lNotificationID = 0;
  1925. }
  1926. // set i so it can just be used as open slot
  1927. i = g_NumNotificationStructs;
  1928. g_NumNotificationStructs += ALLOCATION_BLOCK_SIZE;
  1929. }
  1930. }
  1931. //
  1932. // Open the process' handle that is registering a notification since we need
  1933. // the process handle to duplicate the event handle that they want signaled,
  1934. // plus, we wait on it in case of process exit
  1935. //
  1936. if (NULL == (hClientProcess = OpenProcess(
  1937. PROCESS_DUP_HANDLE | SYNCHRONIZE,
  1938. FALSE,
  1939. ProcessID)))
  1940. {
  1941. CATDBSVC_LOGERR_LASTERR()
  1942. goto ErrorOpenProcess;
  1943. }
  1944. //
  1945. // Duplicate the handle
  1946. //
  1947. if (0 == (DuplicateHandle(
  1948. hClientProcess,
  1949. (HANDLE) EventHandle,
  1950. GetCurrentProcess(),
  1951. &hDuplicate,
  1952. EVENT_MODIFY_STATE, //0,
  1953. FALSE,
  1954. 0))) //DUPLICATE_SAME_ACCESS)))
  1955. {
  1956. CATDBSVC_LOGERR_LASTERR()
  1957. goto ErrorDuplicateHandle;
  1958. }
  1959. //
  1960. // Register a callback in cass the process exits without unregistering
  1961. //
  1962. lLocalNotificationID = InterlockedIncrement(&g_lNotificationID);
  1963. if (!RegisterWaitForSingleObject(
  1964. &(g_rgNotificationStructs[i].hRegisterWaitFor),
  1965. hClientProcess,
  1966. _CatDBProcessExitCallback,
  1967. ULongToPtr(lLocalNotificationID), // use ULongToPtr instead of LongToPtr because
  1968. // ULongToPtr zero extends instead of sign extends
  1969. INFINITE,
  1970. WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE))
  1971. {
  1972. CATDBSVC_LOGERR_LASTERR()
  1973. goto ErrorReturn;
  1974. }
  1975. g_rgNotificationStructs[i].ProcessID = ProcessID;
  1976. g_rgNotificationStructs[i].hClientProcess = hClientProcess;
  1977. hClientProcess = NULL;
  1978. g_rgNotificationStructs[i].hNotificationHandle = (HANDLE) EventHandle;
  1979. g_rgNotificationStructs[i].hDuplicatedNotificationHandle = hDuplicate;
  1980. hDuplicate = INVALID_HANDLE_VALUE;
  1981. g_rgNotificationStructs[i].lNotificationID = lLocalNotificationID;
  1982. }
  1983. else
  1984. {
  1985. //
  1986. // Search through the array to find the handle being unregisterd
  1987. //
  1988. i = 0;
  1989. while (i < g_NumNotificationStructs)
  1990. {
  1991. //
  1992. // Match client based on ProcessID And EventHandle which is a unique pair
  1993. //
  1994. if ((g_rgNotificationStructs[i].hNotificationHandle == (HANDLE) EventHandle) &&
  1995. (g_rgNotificationStructs[i].ProcessID == ProcessID))
  1996. {
  1997. break;
  1998. }
  1999. i++;
  2000. }
  2001. //
  2002. // Make sure we found the handle
  2003. //
  2004. if (i < g_NumNotificationStructs)
  2005. {
  2006. g_rgNotificationStructs[i].ProcessID = 0;
  2007. hWaitForToUnregister = (HANDLE)
  2008. InterlockedExchangePointer(
  2009. &(g_rgNotificationStructs[i].hRegisterWaitFor),
  2010. NULL);
  2011. hClientProcess = g_rgNotificationStructs[i].hClientProcess;
  2012. g_rgNotificationStructs[i].hClientProcess = NULL;
  2013. g_rgNotificationStructs[i].hNotificationHandle = INVALID_HANDLE_VALUE;
  2014. CloseHandle(g_rgNotificationStructs[i].hDuplicatedNotificationHandle);
  2015. g_rgNotificationStructs[i].hDuplicatedNotificationHandle =
  2016. INVALID_HANDLE_VALUE;
  2017. g_rgNotificationStructs[i].lNotificationID = 0;
  2018. //
  2019. // Leave the RegisterNotitifyCS before calling UnregisterWait()
  2020. //
  2021. LeaveCriticalSection(&g_CatDBRegisterNotifyCS);
  2022. fCSEntered = FALSE;
  2023. if (hWaitForToUnregister != NULL)
  2024. {
  2025. UnregisterWaitEx(
  2026. hWaitForToUnregister,
  2027. INVALID_HANDLE_VALUE);
  2028. }
  2029. CloseHandle(hClientProcess);
  2030. hClientProcess = NULL;
  2031. }
  2032. }
  2033. CommonReturn:
  2034. if (fCSEntered)
  2035. {
  2036. LeaveCriticalSection(&g_CatDBRegisterNotifyCS);
  2037. }
  2038. if (hClientProcess != NULL)
  2039. {
  2040. CloseHandle(hClientProcess);
  2041. }
  2042. if (hDuplicate != INVALID_HANDLE_VALUE)
  2043. {
  2044. CloseHandle(hDuplicate);
  2045. }
  2046. _CatDBClientExit();
  2047. return dwRet;
  2048. ErrorReturn:
  2049. dwRet = GetLastError();
  2050. if (0 == dwRet)
  2051. {
  2052. dwRet = (DWORD) E_UNEXPECTED;
  2053. }
  2054. goto CommonReturn;
  2055. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorInvalidArg)
  2056. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorEnterCS)
  2057. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory)
  2058. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorOpenProcess)
  2059. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorDuplicateHandle)
  2060. }
  2061. #define CATDB_RETRY_PAUSE_COUNT 10
  2062. #define CATDB_PAUSE_RETRY_INTERNVAL 1000
  2063. DWORD s_SSCatDBPauseResumeService(
  2064. /* [in] */ handle_t h,
  2065. /* [in] */ DWORD ProcessID,
  2066. /* [in] */ DWORD dwFlags,
  2067. /* [in] */ BOOL fResume)
  2068. {
  2069. return (E_NOTIMPL);
  2070. }
  2071. /////////////////////////////////////////////////////////////////////////////////////////
  2072. //
  2073. // Supporting functions
  2074. //
  2075. /////////////////////////////////////////////////////////////////////////////////////////
  2076. //---------------------------------------------------------------------------------------
  2077. //
  2078. // _CatDBServiceInit
  2079. //
  2080. //---------------------------------------------------------------------------------------
  2081. BOOL
  2082. _CatDBServiceInit(BOOL fUnInit)
  2083. {
  2084. BOOL fRet = TRUE;
  2085. DWORD dwErr = 0;
  2086. JET_ERR jerr;
  2087. HKEY hKey;
  2088. DWORD dwDisposition;
  2089. DWORD dw;
  2090. WCHAR wszDefaultSystemDir[MAX_PATH + 1];
  2091. DWORD dwType;
  2092. DWORD dwValue = 0;
  2093. DWORD cbSize;
  2094. DWORD i;
  2095. DWORD NumCritSecsInitialized = 0;
  2096. LIST_NODE *pListNode = NULL;
  2097. CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct = NULL;
  2098. PVOID pvoid;
  2099. BOOL fLeaveCritSec = TRUE;
  2100. if (fUnInit && g_fDBSvcInitialized)
  2101. {
  2102. //
  2103. // Set the g_fCatalogCacheCallbackEventSet BOOL so that no more
  2104. // callbacks are registered
  2105. //
  2106. fLeaveCritSec = TRUE;
  2107. __try
  2108. {
  2109. EnterCriticalSection(&g_CatDirCashCS);
  2110. }
  2111. __except(EXCEPTION_EXECUTE_HANDLER)
  2112. {
  2113. fLeaveCritSec = FALSE;
  2114. g_fCatalogCacheCallbackEventSet = TRUE;
  2115. }
  2116. g_fCatalogCacheCallbackEventSet = TRUE;
  2117. if (fLeaveCritSec)
  2118. {
  2119. LeaveCriticalSection(&g_CatDirCashCS);
  2120. }
  2121. //
  2122. // This will force all callback threads to be cleared
  2123. //
  2124. SetEvent(g_hCatalogCacheCallbackEvent);
  2125. //
  2126. // Cycle through all open DBs and wait for the registered callbacks
  2127. // to be completed
  2128. //
  2129. pListNode = LIST_GetFirst(&g_CatalogDBCacheList);
  2130. while (pListNode != NULL)
  2131. {
  2132. pCatDirCacheStruct = (CATALOG_DIR_CACHE_STRUCT *) LIST_GetElement(pListNode);
  2133. pvoid = InterlockedExchangePointer(
  2134. &pCatDirCacheStruct->hRegisterWaitForServiceShutdown,
  2135. NULL);
  2136. if (pvoid != NULL)
  2137. {
  2138. UnregisterWaitEx((HANDLE) pvoid, INVALID_HANDLE_VALUE);
  2139. }
  2140. pListNode = LIST_GetNext(pListNode);
  2141. }
  2142. CloseHandle(g_hCatalogCacheCallbackEvent);
  2143. g_hCatalogCacheCallbackEvent = NULL;
  2144. //
  2145. // Cleanup the cached catalog dirs
  2146. //
  2147. if (!_CatDBCloseCachedDatabases())
  2148. {
  2149. CATDBSVC_LOGERR_LASTERR()
  2150. //
  2151. // Nothing we can do but log an error
  2152. //
  2153. }
  2154. _CatDBTermJet();
  2155. if (g_pwszCatalogFileBaseDirectory != NULL)
  2156. {
  2157. _CatDBFree(g_pwszCatalogFileBaseDirectory);
  2158. g_pwszCatalogFileBaseDirectory = NULL;
  2159. }
  2160. if (g_pwszDatabaseFileBaseDirectory != NULL)
  2161. {
  2162. _CatDBFree(g_pwszDatabaseFileBaseDirectory);
  2163. g_pwszDatabaseFileBaseDirectory = NULL;
  2164. }
  2165. DeleteCriticalSection(&g_CatDBAddDeleteCS);
  2166. DeleteCriticalSection(&g_CatDBRegisterNotifyCS);
  2167. DeleteCriticalSection(&g_CatDirCashCS);
  2168. DeleteCriticalSection(&g_CatClientCountCS);
  2169. DeleteCriticalSection(&g_InitializeJetCS);
  2170. DeleteCriticalSection(&g_CleanupTempFilesCS);
  2171. g_fDBSvcInitialized = FALSE;
  2172. }
  2173. else if (!fUnInit)
  2174. {
  2175. __try
  2176. {
  2177. InitializeCriticalSection(&g_CatDBAddDeleteCS);
  2178. NumCritSecsInitialized++;
  2179. InitializeCriticalSection(&g_CatDBRegisterNotifyCS);
  2180. NumCritSecsInitialized++;
  2181. InitializeCriticalSection(&g_CatDirCashCS);
  2182. NumCritSecsInitialized++;
  2183. InitializeCriticalSection(&g_CatClientCountCS);
  2184. NumCritSecsInitialized++;
  2185. InitializeCriticalSection(&g_InitializeJetCS);
  2186. NumCritSecsInitialized++;
  2187. InitializeCriticalSection(&g_CleanupTempFilesCS);
  2188. NumCritSecsInitialized++;
  2189. }
  2190. __except(EXCEPTION_EXECUTE_HANDLER)
  2191. {
  2192. SetLastError(GetExceptionCode());
  2193. CATDBSVC_LOGERR_LASTERR()
  2194. goto ErrorReturn;
  2195. }
  2196. g_fCatalogCacheCallbackEventSet = FALSE;
  2197. //
  2198. // Get System default directory
  2199. //
  2200. wszDefaultSystemDir[0] = NULL;
  2201. if (0 == GetSystemDirectoryW(wszDefaultSystemDir, MAX_PATH))
  2202. {
  2203. CATDBSVC_LOGERR_LASTERR()
  2204. goto ErrorReturn;
  2205. }
  2206. //
  2207. // Create default dirs for catalog files and CatDB files
  2208. //
  2209. if (NULL == (g_pwszCatalogFileBaseDirectory =
  2210. _CATDBConstructWSTRPath(
  2211. wszDefaultSystemDir,
  2212. WSZ_CATALOG_FILE_BASE_DIRECTORY)))
  2213. {
  2214. CATDBSVC_LOGERR_LASTERR()
  2215. goto ErrorReturn;
  2216. }
  2217. if (NULL == (g_pwszDatabaseFileBaseDirectory =
  2218. _CATDBConstructWSTRPath(
  2219. wszDefaultSystemDir,
  2220. WSZ_DATABASE_FILE_BASE_DIRECTORY)))
  2221. {
  2222. CATDBSVC_LOGERR_LASTERR()
  2223. goto ErrorReturn;
  2224. }
  2225. //
  2226. // Get values to be used for timer callback, and database cache timeout
  2227. //
  2228. if (RegCreateKeyExW(
  2229. HKEY_LOCAL_MACHINE,
  2230. WSZ_REG_CATALOGDB_VALUES,
  2231. 0,
  2232. NULL,
  2233. REG_OPTION_NON_VOLATILE,
  2234. KEY_READ,
  2235. NULL,
  2236. &hKey,
  2237. &dwDisposition) == ERROR_SUCCESS)
  2238. {
  2239. cbSize = sizeof(DWORD);
  2240. if (RegQueryValueExW(
  2241. hKey,
  2242. WSZ_REG_DATABASE_TIMEOUT,
  2243. NULL,
  2244. &dwType,
  2245. (BYTE *) &dwValue,
  2246. &cbSize) == ERROR_SUCCESS)
  2247. {
  2248. g_dwCatalogDatabaseCacheTimeout = dwValue;
  2249. }
  2250. dwValue = 0;
  2251. cbSize = sizeof(DWORD);
  2252. if (RegQueryValueExW(
  2253. hKey,
  2254. WSZ_REG_CALLBACK_TIMER,
  2255. NULL,
  2256. &dwType,
  2257. (BYTE *) &dwValue,
  2258. &cbSize) == ERROR_SUCCESS)
  2259. {
  2260. g_dwCatalogDatabaseCacheCallbackTime = dwValue;
  2261. }
  2262. RegCloseKey(hKey);
  2263. }
  2264. //
  2265. // Create the event to be used in the call to RegisterWaitForSingleObject
  2266. //
  2267. if (NULL == (g_hCatalogCacheCallbackEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
  2268. {
  2269. CATDBSVC_LOGERR_LASTERR()
  2270. goto ErrorReturn;
  2271. }
  2272. LIST_Initialize(&g_CatalogDBCacheList);
  2273. g_fDBSvcInitialized = TRUE;
  2274. }
  2275. CommonReturn:
  2276. return fRet;
  2277. ErrorReturn:
  2278. dwErr = GetLastError();
  2279. if (NumCritSecsInitialized >= 1)
  2280. {
  2281. DeleteCriticalSection(&g_CatDBAddDeleteCS);
  2282. }
  2283. if (NumCritSecsInitialized >= 2)
  2284. {
  2285. DeleteCriticalSection(&g_CatDBRegisterNotifyCS);
  2286. }
  2287. if (NumCritSecsInitialized >= 3)
  2288. {
  2289. DeleteCriticalSection(&g_CatDirCashCS);
  2290. }
  2291. if (NumCritSecsInitialized >= 4)
  2292. {
  2293. DeleteCriticalSection(&g_CatClientCountCS);
  2294. }
  2295. if (NumCritSecsInitialized >= 5)
  2296. {
  2297. DeleteCriticalSection(&g_InitializeJetCS);
  2298. }
  2299. if (NumCritSecsInitialized >= 6)
  2300. {
  2301. DeleteCriticalSection(&g_CleanupTempFilesCS);
  2302. }
  2303. if (g_pwszCatalogFileBaseDirectory != NULL)
  2304. {
  2305. _CatDBFree(g_pwszCatalogFileBaseDirectory);
  2306. }
  2307. if (g_pwszDatabaseFileBaseDirectory != NULL)
  2308. {
  2309. _CatDBFree(g_pwszDatabaseFileBaseDirectory);
  2310. }
  2311. if (g_hCatalogCacheCallbackEvent != NULL)
  2312. {
  2313. CloseHandle(g_hCatalogCacheCallbackEvent);
  2314. g_hCatalogCacheCallbackEvent = NULL;
  2315. }
  2316. SetLastError(dwErr);
  2317. fRet = FALSE;
  2318. goto CommonReturn;
  2319. }
  2320. //---------------------------------------------------------------------------------------
  2321. //
  2322. // _CatDBClientEnter
  2323. //
  2324. //---------------------------------------------------------------------------------------
  2325. BOOL
  2326. _CatDBClientEnter(void)
  2327. {
  2328. BOOL fRet = TRUE;
  2329. __try
  2330. {
  2331. EnterCriticalSection(&g_CatClientCountCS);
  2332. }
  2333. __except(EXCEPTION_EXECUTE_HANDLER)
  2334. {
  2335. SetLastError(GetExceptionCode());
  2336. CATDBSVC_LOGERR_LASTERR()
  2337. return FALSE;
  2338. }
  2339. g_dwClientCount++;
  2340. LeaveCriticalSection(&g_CatClientCountCS);
  2341. return fRet;
  2342. }
  2343. //---------------------------------------------------------------------------------------
  2344. //
  2345. // _CatDBClientExit
  2346. //
  2347. //---------------------------------------------------------------------------------------
  2348. void
  2349. _CatDBClientExit(void)
  2350. {
  2351. __try
  2352. {
  2353. EnterCriticalSection(&g_CatClientCountCS);
  2354. }
  2355. __except(EXCEPTION_EXECUTE_HANDLER)
  2356. {
  2357. SetLastError(GetExceptionCode());
  2358. CATDBSVC_LOGERR_LASTERR()
  2359. assert(0);
  2360. return;
  2361. }
  2362. g_dwClientCount--;
  2363. LeaveCriticalSection(&g_CatClientCountCS);
  2364. }
  2365. //---------------------------------------------------------------------------------------
  2366. //
  2367. // _CatDBTouchTimeStampFile
  2368. //
  2369. //---------------------------------------------------------------------------------------
  2370. void
  2371. _CatDBTouchTimeStampFile(
  2372. LPCWSTR pwszSubSysGUID)
  2373. {
  2374. LPWSTR pwsz = NULL;
  2375. if (NULL != (pwsz = _CATDBConstructWSTRPath(
  2376. g_pwszDatabaseFileBaseDirectory,
  2377. pwszSubSysGUID)))
  2378. {
  2379. TimeStampFile_Touch(pwsz);
  2380. _CatDBFree(pwsz);
  2381. }
  2382. else
  2383. {
  2384. CATDBSVC_LOGERR_LASTERR()
  2385. }
  2386. }
  2387. //---------------------------------------------------------------------------------------
  2388. //
  2389. // _CatDBInitializeJet
  2390. //
  2391. //---------------------------------------------------------------------------------------
  2392. BOOL
  2393. _CatDBInitializeJet(
  2394. BOOL fInRecursiveCall)
  2395. {
  2396. BOOL fRet = TRUE;
  2397. BOOL fCSEntered = FALSE;
  2398. JET_ERR jerr;
  2399. __try
  2400. {
  2401. EnterCriticalSection(&g_InitializeJetCS);
  2402. }
  2403. __except(EXCEPTION_EXECUTE_HANDLER)
  2404. {
  2405. CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorReturn)
  2406. }
  2407. fCSEntered = TRUE;
  2408. if (g_fJetInitialized)
  2409. {
  2410. goto CommonReturn;
  2411. }
  2412. //
  2413. // Initialize Jets parameters
  2414. //
  2415. if (!_CatDBInitJetDatabaseParams(&g_JetInstance))
  2416. {
  2417. CATDBSVC_LOGERR_LASTERR()
  2418. goto ErrorReturn;
  2419. }
  2420. //
  2421. // Jet will start up at this point
  2422. //
  2423. jerr = JetInit(&g_JetInstance);
  2424. //
  2425. // Check for specific JET errors, if we got one of those errors then
  2426. // the DB is corrupt in some way and we need to try and cleanup the
  2427. // catroot2 dir, and rebuild the DB.
  2428. //
  2429. // Of course we should only do this if we are not already recursing
  2430. //
  2431. if (!fInRecursiveCall &&
  2432. ((jerr == JET_errMissingLogFile) ||
  2433. (jerr == JET_errLogFileCorrupt) ||
  2434. (jerr == JET_errReadVerifyFailure) ||
  2435. (jerr == JET_errPageNotInitialized)))
  2436. {
  2437. CATDBSVC_LOGERR(jerr)
  2438. JetTerm(g_JetInstance);
  2439. g_JetInstance = 0;
  2440. //
  2441. // Cleanup the catroot 2 directory and then rebuild the DB
  2442. //
  2443. if (_CatDBDeleteJetFiles() && _CatDBRebuildAllDBs())
  2444. {
  2445. jerr = JET_errSuccess;
  2446. }
  2447. }
  2448. if (_CatDBJET_errFailure(jerr))
  2449. {
  2450. CATDBSVC_SETERR_LOG_RETURN(jerr, ErrorReturn)
  2451. }
  2452. g_fJetInitialized = TRUE;
  2453. CommonReturn:
  2454. if (fCSEntered)
  2455. {
  2456. LeaveCriticalSection(&g_InitializeJetCS);
  2457. }
  2458. return (fRet);
  2459. ErrorReturn:
  2460. fRet = FALSE;
  2461. goto CommonReturn;
  2462. }
  2463. //---------------------------------------------------------------------------------------
  2464. //
  2465. // _CatDBTermJet
  2466. //
  2467. //---------------------------------------------------------------------------------------
  2468. BOOL
  2469. _CatDBTermJet()
  2470. {
  2471. BOOL fRet = TRUE;
  2472. BOOL fCSEntered = FALSE;
  2473. JET_ERR jerr;
  2474. __try
  2475. {
  2476. EnterCriticalSection(&g_InitializeJetCS);
  2477. }
  2478. __except(EXCEPTION_EXECUTE_HANDLER)
  2479. {
  2480. CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorReturn)
  2481. }
  2482. fCSEntered = TRUE;
  2483. if (!g_fJetInitialized ||
  2484. (g_lOpenedDBCount != 0))
  2485. {
  2486. goto CommonReturn;
  2487. }
  2488. //
  2489. // Shut Jet down!!
  2490. //
  2491. jerr = JetTerm(g_JetInstance);
  2492. g_JetInstance = 0;
  2493. g_fJetInitialized = FALSE;
  2494. if (_CatDBJET_errFailure(jerr))
  2495. {
  2496. SetLastError(jerr);
  2497. CATDBSVC_LOGERR(jerr)
  2498. }
  2499. CommonReturn:
  2500. if (fCSEntered)
  2501. {
  2502. LeaveCriticalSection(&g_InitializeJetCS);
  2503. }
  2504. return (fRet);
  2505. ErrorReturn:
  2506. fRet = FALSE;
  2507. goto CommonReturn;
  2508. }
  2509. //---------------------------------------------------------------------------------------
  2510. //
  2511. // _CatDBAcquireOpenDatabaseFromCache
  2512. //
  2513. //---------------------------------------------------------------------------------------
  2514. BOOL
  2515. _CatDBAcquireOpenDatabaseFromCache(
  2516. PJET_DB_STRUCT *ppJetDBStruct,
  2517. LPCWSTR pwszSubSysGUID,
  2518. BOOL fReadOnly,
  2519. BOOL fInRecursiveCall)
  2520. {
  2521. BOOL fRet = TRUE;
  2522. JET_ERR jerr;
  2523. LPSTR pszDatabaseFileDir = NULL;
  2524. LPSTR pszSubSysGUID = NULL;
  2525. LPSTR pszTemp = NULL;
  2526. BOOL fJetInitialized = FALSE;
  2527. BOOL fJetSessionBegun = FALSE;
  2528. BOOL fJetDBFileOpen = FALSE;
  2529. BOOL fCSEntered = FALSE;
  2530. DWORD i;
  2531. DWORD dwNewCacheStructIndex = 0;
  2532. BOOL fNewCacheStructUsed = FALSE;
  2533. PJET_DB_STRUCT pJetDBStruct = NULL;
  2534. LIST_NODE *pListNode = NULL;
  2535. CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct = NULL;
  2536. CATALOG_DIR_CACHE_STRUCT *pNewCatDirCacheStruct = NULL;
  2537. DWORD dwErr = 0;
  2538. //
  2539. // Do this here to ensure that JetTerm isn't called after the
  2540. // initialize below is called. This reference will be removed
  2541. // if an actuall cached DB is used.
  2542. //
  2543. InterlockedIncrement(&g_lOpenedDBCount);
  2544. //
  2545. // Make sure Jet is initialized
  2546. //
  2547. if (!_CatDBInitializeJet(fInRecursiveCall))
  2548. {
  2549. CATDBSVC_LOGERR_LASTERR()
  2550. goto ErrorReturn;
  2551. }
  2552. //
  2553. // First check to see if there is a cached session available
  2554. //
  2555. __try
  2556. {
  2557. EnterCriticalSection(&g_CatDirCashCS);
  2558. }
  2559. __except(EXCEPTION_EXECUTE_HANDLER)
  2560. {
  2561. CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorReturn)
  2562. }
  2563. fCSEntered = TRUE;
  2564. pListNode = LIST_GetFirst(&g_CatalogDBCacheList);
  2565. while (pListNode != NULL)
  2566. {
  2567. pCatDirCacheStruct = (CATALOG_DIR_CACHE_STRUCT *) LIST_GetElement(pListNode);
  2568. if ((!pCatDirCacheStruct->fDBCurrentlyInUse) &&
  2569. (_wcsicmp(pCatDirCacheStruct->pwszSubSysGUID, pwszSubSysGUID) == 0)) /*&&
  2570. (pCatDirCacheStruct->fReadOnly == fReadOnly))*/
  2571. {
  2572. break;
  2573. }
  2574. pListNode = LIST_GetNext(pListNode);
  2575. }
  2576. if (pListNode != NULL)
  2577. {
  2578. //
  2579. // Using a cached DB, which already has a ref count, so get rid of the
  2580. // one added at the beginning of the function
  2581. //
  2582. InterlockedDecrement(&g_lOpenedDBCount);
  2583. pCatDirCacheStruct->fDBCurrentlyInUse = TRUE;
  2584. pCatDirCacheStruct->dwTimeLastTouched = GetTickCount();
  2585. *ppJetDBStruct = &(pCatDirCacheStruct->JetDBStruct);
  2586. goto CommonReturn;
  2587. }
  2588. //
  2589. // There are either no cached DBs for this dir, or they are already in use...
  2590. // So open a new instance
  2591. //
  2592. if (NULL == (pNewCatDirCacheStruct = (CATALOG_DIR_CACHE_STRUCT *)
  2593. _CatDBAlloc(sizeof(CATALOG_DIR_CACHE_STRUCT))))
  2594. {
  2595. CATDBSVC_LOGERR_LASTERR()
  2596. goto ErrorReturn;
  2597. }
  2598. memset(&(pNewCatDirCacheStruct->JetDBStruct), 0, sizeof(JET_DB_STRUCT));
  2599. pNewCatDirCacheStruct->pwszSubSysGUID = NULL;
  2600. pNewCatDirCacheStruct->fDBCurrentlyInUse = TRUE;
  2601. pNewCatDirCacheStruct->dwTimeLastTouched = GetTickCount();
  2602. pNewCatDirCacheStruct->fReadOnly = fReadOnly;
  2603. //
  2604. // Make a copy of the catalog database GUID
  2605. //
  2606. if (NULL == (pNewCatDirCacheStruct->pwszSubSysGUID = (LPWSTR)
  2607. _CatDBAlloc((wcslen(pwszSubSysGUID) + 1) * sizeof(WCHAR))))
  2608. {
  2609. CATDBSVC_LOGERR_LASTERR()
  2610. goto ErrorReturn;
  2611. }
  2612. wcscpy(pNewCatDirCacheStruct->pwszSubSysGUID, pwszSubSysGUID);
  2613. pJetDBStruct = &(pNewCatDirCacheStruct->JetDBStruct);
  2614. //
  2615. // Begin a session
  2616. //
  2617. if (_CatDBJET_errFailure(jerr =
  2618. JetBeginSession(
  2619. g_JetInstance,
  2620. &(pJetDBStruct->JetSesID),
  2621. NULL,
  2622. NULL)))
  2623. {
  2624. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  2625. }
  2626. fJetSessionBegun = TRUE;
  2627. //
  2628. // Get the fully qualified name of the database file
  2629. //
  2630. pszDatabaseFileDir = _CatDBConvertWszToSz(g_pwszDatabaseFileBaseDirectory);
  2631. if (pszDatabaseFileDir == NULL)
  2632. {
  2633. CATDBSVC_LOGERR_LASTERR()
  2634. goto ErrorReturn;
  2635. }
  2636. pszSubSysGUID = _CatDBConvertWszToSz(pwszSubSysGUID);
  2637. if (pszSubSysGUID == NULL)
  2638. {
  2639. CATDBSVC_LOGERR_LASTERR()
  2640. goto ErrorReturn;
  2641. }
  2642. if (NULL == (pszTemp = _CATDBConstructPath(pszDatabaseFileDir, pszSubSysGUID)))
  2643. {
  2644. CATDBSVC_LOGERR_LASTERR()
  2645. goto ErrorReturn;
  2646. }
  2647. if (NULL == (pJetDBStruct->pszDBFileName =
  2648. _CATDBConstructPath(pszTemp, SZ_DBFILE_NAME)))
  2649. {
  2650. CATDBSVC_LOGERR_LASTERR()
  2651. goto ErrorReturn;
  2652. }
  2653. //
  2654. // Open the DB file... create it if it doesn't already exist
  2655. //
  2656. if (!_CatDBAttachAndOpenDatabase(pJetDBStruct, fReadOnly))
  2657. {
  2658. CATDBSVC_LOGERR_LASTERR()
  2659. goto ErrorReturn;
  2660. }
  2661. fJetDBFileOpen = TRUE;
  2662. //
  2663. // Register a close callback for this database
  2664. //
  2665. if (!RegisterWaitForSingleObject(
  2666. &(pNewCatDirCacheStruct->hRegisterWaitForServiceShutdown),
  2667. g_hCatalogCacheCallbackEvent,
  2668. _CatDBWaitOrTimerCallback,
  2669. pNewCatDirCacheStruct, // Context
  2670. g_dwCatalogDatabaseCacheCallbackTime,
  2671. WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE))
  2672. {
  2673. CATDBSVC_LOGERR_LASTERR()
  2674. goto ErrorReturn;
  2675. }
  2676. //
  2677. // Add the opened database to the cache list
  2678. //
  2679. if (!LIST_AddTail(&g_CatalogDBCacheList, pNewCatDirCacheStruct))
  2680. {
  2681. CATDBSVC_LOGERR_LASTERR()
  2682. goto ErrorReturn;
  2683. }
  2684. *ppJetDBStruct = &(pNewCatDirCacheStruct->JetDBStruct);
  2685. CommonReturn:
  2686. if (fCSEntered)
  2687. {
  2688. LeaveCriticalSection(&g_CatDirCashCS);
  2689. }
  2690. if (pszDatabaseFileDir != NULL)
  2691. {
  2692. _CatDBFree(pszDatabaseFileDir);
  2693. }
  2694. if (pszSubSysGUID != NULL)
  2695. {
  2696. _CatDBFree(pszSubSysGUID);
  2697. }
  2698. if (pszTemp != NULL)
  2699. {
  2700. _CatDBFree(pszTemp);
  2701. }
  2702. return fRet;
  2703. ErrorReturn:
  2704. dwErr = GetLastError();
  2705. if (fJetDBFileOpen)
  2706. {
  2707. JetCloseDatabase(pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, 0);
  2708. }
  2709. if (fJetSessionBegun)
  2710. {
  2711. JetEndSession(pJetDBStruct->JetSesID, 0);
  2712. }
  2713. if (pNewCatDirCacheStruct != NULL)
  2714. {
  2715. if (pNewCatDirCacheStruct->JetDBStruct.pszDBFileName != NULL)
  2716. {
  2717. _CatDBFree(pNewCatDirCacheStruct->JetDBStruct.pszDBFileName);
  2718. }
  2719. if (pNewCatDirCacheStruct->pwszSubSysGUID != NULL)
  2720. {
  2721. _CatDBFree(pNewCatDirCacheStruct->pwszSubSysGUID);
  2722. }
  2723. _CatDBFree(pNewCatDirCacheStruct);
  2724. }
  2725. InterlockedDecrement(&g_lOpenedDBCount);
  2726. SetLastError(dwErr);
  2727. fRet = FALSE;
  2728. goto CommonReturn;
  2729. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  2730. }
  2731. //---------------------------------------------------------------------------------------
  2732. //
  2733. // _CatDBReleaseDatabaseToCache
  2734. //
  2735. //---------------------------------------------------------------------------------------
  2736. BOOL
  2737. _CatDBReleaseDatabaseToCache(
  2738. PJET_DB_STRUCT pJetDBStruct)
  2739. {
  2740. //
  2741. // This cast works because the JET_DB_STRUCT is the first member of the
  2742. // CATALOG_DIR_CACHE_STRUCT
  2743. //
  2744. CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct =
  2745. (CATALOG_DIR_CACHE_STRUCT *) pJetDBStruct;
  2746. pCatDirCacheStruct->dwTimeLastTouched = GetTickCount();
  2747. pCatDirCacheStruct->fDBCurrentlyInUse = FALSE;
  2748. return TRUE;
  2749. }
  2750. //---------------------------------------------------------------------------------------
  2751. //
  2752. // _CatDBCloseSingleCachedDatabase
  2753. //
  2754. //---------------------------------------------------------------------------------------
  2755. BOOL
  2756. _CatDBCloseSingleCachedDatabase(
  2757. CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct)
  2758. {
  2759. BOOL fRet = TRUE;
  2760. PVOID pvoid;
  2761. __try
  2762. {
  2763. EnterCriticalSection(&g_CatDirCashCS);
  2764. }
  2765. __except(EXCEPTION_EXECUTE_HANDLER)
  2766. {
  2767. SetLastError(GetExceptionCode());
  2768. CATDBSVC_LOGERR_LASTERR()
  2769. return FALSE;
  2770. }
  2771. //
  2772. // unregister the callback
  2773. //
  2774. pvoid = InterlockedExchangePointer(
  2775. &pCatDirCacheStruct->hRegisterWaitForServiceShutdown,
  2776. NULL);
  2777. if (pvoid != NULL)
  2778. {
  2779. UnregisterWait((HANDLE) pvoid);
  2780. }
  2781. //
  2782. // If the DB is not in use and its timed out, then close
  2783. //
  2784. if (!(pCatDirCacheStruct->fDBCurrentlyInUse) &&
  2785. (((GetTickCount() - pCatDirCacheStruct->dwTimeLastTouched) >
  2786. g_dwCatalogDatabaseCacheTimeout)))
  2787. {
  2788. if (!_CatDBCloseDatabaseFile(&(pCatDirCacheStruct->JetDBStruct)))
  2789. {
  2790. fRet = FALSE;
  2791. CATDBSVC_LOGERR_LASTERR()
  2792. }
  2793. //
  2794. // if that was the last open DB, then terminate Jet
  2795. //
  2796. if (0 == InterlockedDecrement(&g_lOpenedDBCount))
  2797. {
  2798. _CatDBTermJet();
  2799. }
  2800. _CatDBFree(pCatDirCacheStruct->JetDBStruct.pszDBFileName);
  2801. _CatDBFree(pCatDirCacheStruct->pwszSubSysGUID);
  2802. LIST_RemoveElement(&g_CatalogDBCacheList, pCatDirCacheStruct);
  2803. _CatDBFree(pCatDirCacheStruct);
  2804. }
  2805. else
  2806. {
  2807. if (!g_fCatalogCacheCallbackEventSet)
  2808. {
  2809. //
  2810. // Register for another callback if we aren't in shutdown mode
  2811. //
  2812. if (!RegisterWaitForSingleObject(
  2813. &(pCatDirCacheStruct->hRegisterWaitForServiceShutdown),
  2814. g_hCatalogCacheCallbackEvent,
  2815. _CatDBWaitOrTimerCallback,
  2816. pCatDirCacheStruct, // Context
  2817. g_dwCatalogDatabaseCacheCallbackTime,
  2818. WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE))
  2819. {
  2820. CATDBSVC_LOGERR_LASTERR()
  2821. }
  2822. }
  2823. }
  2824. LeaveCriticalSection(&g_CatDirCashCS);
  2825. return fRet;
  2826. }
  2827. //---------------------------------------------------------------------------------------
  2828. //
  2829. // _CatDBCloseCachedDatabases
  2830. //
  2831. //---------------------------------------------------------------------------------------
  2832. BOOL
  2833. _CatDBCloseCachedDatabases()
  2834. {
  2835. BOOL fRet = TRUE;
  2836. DWORD i;
  2837. BOOL fDatabaseFoundThatIsInUse = FALSE;
  2838. BOOL fCloseFailed = FALSE;
  2839. LIST_NODE *pListNode = NULL;
  2840. CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct = NULL;
  2841. __try
  2842. {
  2843. EnterCriticalSection(&g_CatDirCashCS);
  2844. }
  2845. __except(EXCEPTION_EXECUTE_HANDLER)
  2846. {
  2847. SetLastError(GetExceptionCode());
  2848. CATDBSVC_LOGERR_LASTERR()
  2849. return FALSE;
  2850. }
  2851. //
  2852. // Cycle through all open DBs and close them
  2853. //
  2854. pListNode = LIST_GetFirst(&g_CatalogDBCacheList);
  2855. while (pListNode != NULL)
  2856. {
  2857. pCatDirCacheStruct = (CATALOG_DIR_CACHE_STRUCT *) LIST_GetElement(pListNode);
  2858. if (!(pCatDirCacheStruct->fDBCurrentlyInUse))
  2859. {
  2860. if (!_CatDBCloseDatabaseFile(&(pCatDirCacheStruct->JetDBStruct)))
  2861. {
  2862. fCloseFailed = TRUE;
  2863. CATDBSVC_LOGERR_LASTERR()
  2864. }
  2865. _CatDBFree(pCatDirCacheStruct->JetDBStruct.pszDBFileName);
  2866. _CatDBFree(pCatDirCacheStruct->pwszSubSysGUID);
  2867. pListNode = LIST_GetNext(pListNode);
  2868. LIST_RemoveElement(&g_CatalogDBCacheList, pCatDirCacheStruct);
  2869. _CatDBFree(pCatDirCacheStruct);
  2870. }
  2871. else
  2872. {
  2873. fDatabaseFoundThatIsInUse = TRUE;
  2874. pListNode = LIST_GetNext(pListNode);
  2875. }
  2876. }
  2877. if (fDatabaseFoundThatIsInUse || fCloseFailed)
  2878. {
  2879. fRet = FALSE;
  2880. }
  2881. LeaveCriticalSection(&g_CatDirCashCS);
  2882. return fRet;
  2883. }
  2884. //---------------------------------------------------------------------------------------
  2885. //
  2886. // _CatDBWaitOrTimerCallback
  2887. //
  2888. //---------------------------------------------------------------------------------------
  2889. VOID CALLBACK
  2890. _CatDBWaitOrTimerCallback(
  2891. PVOID lpParameter,
  2892. BOOLEAN fTimedOut)
  2893. {
  2894. //
  2895. // If we are being called because we timed out (the event wasn't set), that
  2896. // means we should close the database if possible... otherwise, the event
  2897. // was set because we are shutting down, so don't do anything and just let the
  2898. // shutdown-cleanup code handle it.
  2899. //
  2900. if (fTimedOut)
  2901. {
  2902. if (!_CatDBCloseSingleCachedDatabase((CATALOG_DIR_CACHE_STRUCT *) lpParameter))
  2903. {
  2904. CATDBSVC_LOGERR_LASTERR()
  2905. }
  2906. }
  2907. //
  2908. // Since we have a thread, try to clean up the temp files
  2909. //
  2910. _CatDBCleanupTempFiles();
  2911. }
  2912. //---------------------------------------------------------------------------------------
  2913. //
  2914. // _CatDBAddCatalogEntriesToDatabase
  2915. //
  2916. //---------------------------------------------------------------------------------------
  2917. BOOL
  2918. _CatDBAddCatalogEntriesToDatabase(
  2919. PJET_DB_STRUCT pJetDBStruct,
  2920. PCCTL_CONTEXT pCTLContext,
  2921. LPWSTR pwszNewCatalogName)
  2922. {
  2923. BOOL fRet = TRUE;
  2924. JET_ERR jerr;
  2925. WCHAR *pwszCatBaseName;
  2926. DWORD i;
  2927. CRYPT_DATA_BLOB CryptDataBlob;
  2928. SPC_INDIRECT_DATA_CONTENT *pIndirectData = NULL;
  2929. CryptDataBlob.pbData = NULL;
  2930. //
  2931. // Extract the base name from the full path name
  2932. //
  2933. if (NULL == (pwszCatBaseName = wcsrchr(pwszNewCatalogName, L'\\')))
  2934. {
  2935. pwszCatBaseName = wcsrchr(pwszNewCatalogName, L':');
  2936. }
  2937. if (pwszCatBaseName != NULL)
  2938. {
  2939. pwszCatBaseName++;
  2940. }
  2941. else
  2942. {
  2943. pwszCatBaseName = pwszNewCatalogName;
  2944. }
  2945. //
  2946. // Loop for each hash in the catalog file
  2947. //
  2948. for (i=0; i<pCTLContext->pCtlInfo->cCTLEntry; i++)
  2949. {
  2950. if (!_CatDBFindAndDecodeHashInCatEntry(
  2951. &(pCTLContext->pCtlInfo->rgCTLEntry[i]),
  2952. &pIndirectData))
  2953. {
  2954. CATDBSVC_LOGERR_LASTERR()
  2955. goto ErrorReturn;
  2956. }
  2957. if (!_CatDBAddHashCatNamePair(
  2958. pJetDBStruct,
  2959. &(pIndirectData->Digest),
  2960. pwszCatBaseName))
  2961. {
  2962. CATDBSVC_LOGERR_LASTERR()
  2963. goto ErrorReturn;
  2964. }
  2965. _CatDBFree(pIndirectData);
  2966. pIndirectData = NULL;
  2967. }
  2968. CommonReturn:
  2969. return fRet;
  2970. ErrorReturn:
  2971. if (pIndirectData != NULL)
  2972. {
  2973. _CatDBFree(pIndirectData);
  2974. }
  2975. fRet = FALSE;
  2976. goto CommonReturn;
  2977. }
  2978. //---------------------------------------------------------------------------------------
  2979. //
  2980. // _CatDBAddHashCatNamePair
  2981. //
  2982. //---------------------------------------------------------------------------------------
  2983. BOOL
  2984. _CatDBAddHashCatNamePair(
  2985. PJET_DB_STRUCT pJetDBStruct,
  2986. PCRYPT_DATA_BLOB pHashBlob,
  2987. LPWSTR pwszCatBaseName)
  2988. {
  2989. BOOL fRet = TRUE;
  2990. JET_ERR jerr;
  2991. //
  2992. // First, try to find the hash in the HashCatName table.
  2993. //
  2994. jerr = _CatDBSeekInHashCatNameTable(pJetDBStruct, pHashBlob);
  2995. if (jerr == JET_errRecordNotFound)
  2996. {
  2997. //
  2998. // not found
  2999. //
  3000. if (!_CatDBAddNewRowToHashCatNameTable(
  3001. pJetDBStruct,
  3002. pHashBlob,
  3003. pwszCatBaseName))
  3004. {
  3005. goto ErrorReturn;
  3006. }
  3007. }
  3008. else if (jerr == JET_errSuccess)
  3009. {
  3010. //
  3011. // found
  3012. //
  3013. if (!_CatDBAddValueToExistingHashCatNameRow(
  3014. pJetDBStruct,
  3015. pHashBlob,
  3016. pwszCatBaseName))
  3017. {
  3018. goto ErrorReturn;
  3019. }
  3020. }
  3021. else if (_CatDBJET_errFailure(jerr))
  3022. {
  3023. //
  3024. // error
  3025. //
  3026. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3027. }
  3028. CommonReturn:
  3029. return fRet;
  3030. ErrorReturn:
  3031. fRet = FALSE;
  3032. goto CommonReturn;
  3033. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  3034. }
  3035. //---------------------------------------------------------------------------------------
  3036. //
  3037. // _CatDBAddNewRowToHashCatNameTable
  3038. //
  3039. //---------------------------------------------------------------------------------------
  3040. BOOL
  3041. _CatDBAddNewRowToHashCatNameTable(
  3042. PJET_DB_STRUCT pJetDBStruct,
  3043. PCRYPT_DATA_BLOB pHashBlob,
  3044. LPWSTR pwszCatBaseName)
  3045. {
  3046. BOOL fRet = TRUE;
  3047. JET_ERR jerr;
  3048. JET_SETINFO JetSetInfo;
  3049. //
  3050. // Create the new row, and insert the values
  3051. //
  3052. if (_CatDBJET_errFailure(jerr =
  3053. JetPrepareUpdate(
  3054. pJetDBStruct->JetSesID,
  3055. pJetDBStruct->JetHashCatNameTableID,
  3056. JET_prepInsert)))
  3057. {
  3058. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3059. }
  3060. // hash
  3061. if (_CatDBJET_errFailure(jerr =
  3062. JetSetColumn(
  3063. pJetDBStruct->JetSesID,
  3064. pJetDBStruct->JetHashCatNameTableID,
  3065. pJetDBStruct->JetHashCatNameTable_HashColumnID,
  3066. pHashBlob->pbData,
  3067. pHashBlob->cbData,
  3068. 0,
  3069. NULL)))
  3070. {
  3071. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3072. }
  3073. // catname
  3074. memset(&JetSetInfo, 0, sizeof(JetSetInfo));
  3075. JetSetInfo.cbStruct = sizeof(JetSetInfo);
  3076. JetSetInfo.itagSequence = 1;
  3077. if (_CatDBJET_errFailure(jerr =
  3078. JetSetColumn(
  3079. pJetDBStruct->JetSesID,
  3080. pJetDBStruct->JetHashCatNameTableID,
  3081. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  3082. (BYTE const *) pwszCatBaseName,
  3083. (wcslen(pwszCatBaseName) + 1) * sizeof(WCHAR),
  3084. 0,
  3085. &JetSetInfo)))
  3086. {
  3087. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3088. }
  3089. if (_CatDBJET_errFailure(jerr =
  3090. JetUpdate(
  3091. pJetDBStruct->JetSesID,
  3092. pJetDBStruct->JetHashCatNameTableID,
  3093. NULL,
  3094. 0,
  3095. NULL)))
  3096. {
  3097. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3098. }
  3099. CommonReturn:
  3100. return fRet;
  3101. ErrorReturn:
  3102. fRet = FALSE;
  3103. goto CommonReturn;
  3104. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  3105. }
  3106. //---------------------------------------------------------------------------------------
  3107. //
  3108. // _CatDBAddValueToExistingHashCatNameRow
  3109. //
  3110. //---------------------------------------------------------------------------------------
  3111. BOOL
  3112. _CatDBAddValueToExistingHashCatNameRow(
  3113. PJET_DB_STRUCT pJetDBStruct,
  3114. PCRYPT_DATA_BLOB pHashBlob,
  3115. LPWSTR pwszCatBaseName)
  3116. {
  3117. BOOL fRet = TRUE;
  3118. JET_ERR jerr;
  3119. JET_SETINFO JetSetInfo;
  3120. WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH];
  3121. DWORD dwLength;
  3122. JET_RETINFO JetRetInfo;
  3123. //
  3124. // Make sure we are not here because a single hash is in the same catalog twice...
  3125. //
  3126. //
  3127. if (_CatDBCatnameAlreadyInHashesListOfCats(
  3128. pJetDBStruct,
  3129. pHashBlob,
  3130. pwszCatBaseName))
  3131. {
  3132. goto CommonReturn;
  3133. }
  3134. //
  3135. // Create a row in the CatNameBuddy Table for the current catalog if it
  3136. // doesn't already exist
  3137. //
  3138. if (!_CatDBAddNewRowToCatNameBuddyTableIfNotExists(
  3139. pJetDBStruct,
  3140. pwszCatBaseName))
  3141. {
  3142. CATDBSVC_LOGERR_LASTERR()
  3143. goto ErrorReturn;
  3144. }
  3145. //
  3146. // Get each catalog name in the current hashes CatNameList and add it to the
  3147. // current catalogs buddy list
  3148. //
  3149. memset(&JetRetInfo, 0, sizeof(JetRetInfo));
  3150. JetRetInfo.cbStruct = sizeof(JetRetInfo);
  3151. JetRetInfo.itagSequence = 1;
  3152. jerr = JetRetrieveColumn(
  3153. pJetDBStruct->JetSesID,
  3154. pJetDBStruct->JetHashCatNameTableID,
  3155. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  3156. wszCatalogName,
  3157. CATDB_MAX_CATNAME_LENGTH,
  3158. &dwLength,
  3159. JET_bitRetrieveCopy,
  3160. &JetRetInfo);
  3161. while (jerr == JET_errSuccess)
  3162. {
  3163. if (!_CatDBAddNewRowToCatNameBuddyTableIfNotExists(
  3164. pJetDBStruct,
  3165. wszCatalogName))
  3166. {
  3167. CATDBSVC_LOGERR_LASTERR()
  3168. goto ErrorReturn;
  3169. }
  3170. //
  3171. // Add the buddy that was found to the current catalogs buddy list
  3172. //
  3173. if (!_CatDBAddNameToBuddyList(
  3174. pJetDBStruct,
  3175. wszCatalogName,
  3176. pwszCatBaseName))
  3177. {
  3178. CATDBSVC_LOGERR_LASTERR()
  3179. goto ErrorReturn;
  3180. }
  3181. //
  3182. // Add the buddys of the buddy that was found, to current catalogs buddy list
  3183. //
  3184. if (!_CatDBAddWholeBuddyList(
  3185. pJetDBStruct,
  3186. pwszCatBaseName,
  3187. wszCatalogName))
  3188. {
  3189. CATDBSVC_LOGERR_LASTERR()
  3190. goto ErrorReturn;
  3191. }
  3192. //
  3193. // Add the current catalog to the buddy list of the buddy that was found
  3194. //
  3195. if (!_CatDBAddNameToBuddyList(
  3196. pJetDBStruct,
  3197. pwszCatBaseName,
  3198. wszCatalogName))
  3199. {
  3200. CATDBSVC_LOGERR_LASTERR()
  3201. goto ErrorReturn;
  3202. }
  3203. //
  3204. // Setup for next loop
  3205. //
  3206. JetRetInfo.itagSequence++;
  3207. jerr = JetRetrieveColumn(
  3208. pJetDBStruct->JetSesID,
  3209. pJetDBStruct->JetHashCatNameTableID,
  3210. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  3211. wszCatalogName,
  3212. CATDB_MAX_CATNAME_LENGTH,
  3213. &dwLength,
  3214. JET_bitRetrieveCopy,
  3215. &JetRetInfo);
  3216. }
  3217. //
  3218. // Check to see if a real error occurred and not just a JET_wrnColumnNull
  3219. //
  3220. if (_CatDBJET_errFailure(jerr))
  3221. {
  3222. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3223. }
  3224. //
  3225. // Add the current catalog to the CatNameList of the current hash
  3226. //
  3227. if (_CatDBJET_errFailure(jerr =
  3228. JetPrepareUpdate(
  3229. pJetDBStruct->JetSesID,
  3230. pJetDBStruct->JetHashCatNameTableID,
  3231. JET_prepReplace)))
  3232. {
  3233. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3234. }
  3235. memset(&JetSetInfo, 0, sizeof(JetSetInfo));
  3236. JetSetInfo.cbStruct = sizeof(JetSetInfo);
  3237. JetSetInfo.itagSequence = 0; // insert into next open position
  3238. if (_CatDBJET_errFailure(jerr =
  3239. JetSetColumn(
  3240. pJetDBStruct->JetSesID,
  3241. pJetDBStruct->JetHashCatNameTableID,
  3242. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  3243. (BYTE const *) pwszCatBaseName,
  3244. (wcslen(pwszCatBaseName) + 1) * sizeof(WCHAR),
  3245. 0,
  3246. &JetSetInfo)))
  3247. {
  3248. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3249. }
  3250. if (_CatDBJET_errFailure(jerr =
  3251. JetUpdate(
  3252. pJetDBStruct->JetSesID,
  3253. pJetDBStruct->JetHashCatNameTableID,
  3254. NULL,
  3255. 0,
  3256. NULL)))
  3257. {
  3258. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3259. }
  3260. CommonReturn:
  3261. return fRet;
  3262. ErrorReturn:
  3263. fRet = FALSE;
  3264. goto CommonReturn;
  3265. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  3266. }
  3267. //---------------------------------------------------------------------------------------
  3268. //
  3269. // _CatDBCatnameAlreadyInHashesListOfCats
  3270. //
  3271. //---------------------------------------------------------------------------------------
  3272. BOOL
  3273. _CatDBCatnameAlreadyInHashesListOfCats(
  3274. PJET_DB_STRUCT pJetDBStruct,
  3275. PCRYPT_DATA_BLOB pHashBlob,
  3276. LPWSTR pwszCatBaseName)
  3277. {
  3278. JET_ERR jerr;
  3279. WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH];
  3280. DWORD dwLength;
  3281. JET_RETINFO JetRetInfo;
  3282. //
  3283. // Get each catalog name in the current hashes CatNameList see if it is the same
  3284. // as pwszCatBaseName
  3285. //
  3286. memset(&JetRetInfo, 0, sizeof(JetRetInfo));
  3287. JetRetInfo.cbStruct = sizeof(JetRetInfo);
  3288. JetRetInfo.itagSequence = 1;
  3289. jerr = JetRetrieveColumn(
  3290. pJetDBStruct->JetSesID,
  3291. pJetDBStruct->JetHashCatNameTableID,
  3292. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  3293. wszCatalogName,
  3294. CATDB_MAX_CATNAME_LENGTH,
  3295. &dwLength,
  3296. JET_bitRetrieveCopy,
  3297. &JetRetInfo);
  3298. while (jerr == JET_errSuccess)
  3299. {
  3300. if (_wcsicmp(wszCatalogName, pwszCatBaseName) == 0)
  3301. {
  3302. //
  3303. // Duplicate found
  3304. //
  3305. return TRUE;
  3306. }
  3307. //
  3308. // Setup for next loop
  3309. //
  3310. JetRetInfo.itagSequence++;
  3311. jerr = JetRetrieveColumn(
  3312. pJetDBStruct->JetSesID,
  3313. pJetDBStruct->JetHashCatNameTableID,
  3314. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  3315. wszCatalogName,
  3316. CATDB_MAX_CATNAME_LENGTH,
  3317. &dwLength,
  3318. JET_bitRetrieveCopy,
  3319. &JetRetInfo);
  3320. }
  3321. //
  3322. // No duplicates were found
  3323. //
  3324. return FALSE;
  3325. }
  3326. //---------------------------------------------------------------------------------------
  3327. //
  3328. // _CatDBAddNewRowToCatNameBuddyTableIfNotExists
  3329. //
  3330. //---------------------------------------------------------------------------------------
  3331. BOOL
  3332. _CatDBAddNewRowToCatNameBuddyTableIfNotExists(
  3333. PJET_DB_STRUCT pJetDBStruct,
  3334. LPWSTR pwszCatBaseName)
  3335. {
  3336. BOOL fRet = TRUE;
  3337. JET_ERR jerr;
  3338. //
  3339. // Try to find the CatName in the CatNameBuddy table.
  3340. //
  3341. jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszCatBaseName);
  3342. if (jerr == JET_errRecordNotFound)
  3343. {
  3344. //
  3345. // not found, so add the row
  3346. //
  3347. if (!_CatDBAddNewRowToCatNameBuddyTable(pJetDBStruct, pwszCatBaseName))
  3348. {
  3349. CATDBSVC_LOGERR_LASTERR()
  3350. goto ErrorReturn;
  3351. }
  3352. }
  3353. else if (_CatDBJET_errFailure(jerr))
  3354. {
  3355. //
  3356. // error
  3357. //
  3358. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3359. }
  3360. // else, it was found, so just return successfully
  3361. CommonReturn:
  3362. return fRet;
  3363. ErrorReturn:
  3364. fRet = FALSE;
  3365. goto CommonReturn;
  3366. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  3367. }
  3368. //---------------------------------------------------------------------------------------
  3369. //
  3370. // _CatDBAddNewRowToCatNameBuddyTable
  3371. //
  3372. //---------------------------------------------------------------------------------------
  3373. BOOL
  3374. _CatDBAddNewRowToCatNameBuddyTable(
  3375. PJET_DB_STRUCT pJetDBStruct,
  3376. LPWSTR pwszCatBaseName)
  3377. {
  3378. BOOL fRet = TRUE;
  3379. JET_ERR jerr;
  3380. JET_SETINFO JetSetInfo;
  3381. //
  3382. // Create the new row, and insert the values
  3383. //
  3384. if (_CatDBJET_errFailure(jerr =
  3385. JetPrepareUpdate(
  3386. pJetDBStruct->JetSesID,
  3387. pJetDBStruct->JetCatNameBuddyTableID,
  3388. JET_prepInsert)))
  3389. {
  3390. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3391. }
  3392. // catname
  3393. if (_CatDBJET_errFailure(jerr =
  3394. JetSetColumn(
  3395. pJetDBStruct->JetSesID,
  3396. pJetDBStruct->JetCatNameBuddyTableID,
  3397. pJetDBStruct->JetCatNameBuddyTable_CatNameColumnID,
  3398. (BYTE const *) pwszCatBaseName,
  3399. (wcslen(pwszCatBaseName) + 1) * sizeof(WCHAR),
  3400. 0,
  3401. NULL)))
  3402. {
  3403. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3404. }
  3405. if (_CatDBJET_errFailure(jerr =
  3406. JetUpdate(
  3407. pJetDBStruct->JetSesID,
  3408. pJetDBStruct->JetCatNameBuddyTableID,
  3409. NULL,
  3410. 0,
  3411. NULL)))
  3412. {
  3413. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3414. }
  3415. CommonReturn:
  3416. return fRet;
  3417. ErrorReturn:
  3418. fRet = FALSE;
  3419. goto CommonReturn;
  3420. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  3421. }
  3422. //---------------------------------------------------------------------------------------
  3423. //
  3424. // _CatDBAddNameToBuddyList
  3425. //
  3426. //---------------------------------------------------------------------------------------
  3427. BOOL
  3428. _CatDBAddNameToBuddyList(
  3429. PJET_DB_STRUCT pJetDBStruct,
  3430. LPWSTR pwszNameToAdd,
  3431. LPWSTR pwszListToAddTo)
  3432. {
  3433. BOOL fRet = TRUE;
  3434. JET_ERR jerr;
  3435. JET_SETINFO JetSetInfo;
  3436. JET_RETINFO JetRetInfo;
  3437. WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH];
  3438. DWORD dwLength;
  3439. //
  3440. // Don't add the same name to itself
  3441. //
  3442. if (_wcsicmp(pwszNameToAdd, pwszListToAddTo) == 0)
  3443. {
  3444. goto CommonReturn;
  3445. }
  3446. //
  3447. // seek to the pwszListToAddTo row in the CatNameBuddy table
  3448. //
  3449. jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszListToAddTo);
  3450. if (jerr == JET_errRecordNotFound)
  3451. {
  3452. //
  3453. // this bad, since we know the row should exist
  3454. //
  3455. CATDBSVC_SETERR_LOG_RETURN(JET_errRecordNotFound, ErrorJetDatabase)
  3456. }
  3457. else if (_CatDBJET_errFailure(jerr))
  3458. {
  3459. //
  3460. // error
  3461. //
  3462. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3463. }
  3464. //
  3465. // Check to see if the buddy being added is already there.
  3466. //
  3467. memset(&JetRetInfo, 0, sizeof(JetRetInfo));
  3468. JetRetInfo.cbStruct = sizeof(JetRetInfo);
  3469. JetRetInfo.itagSequence = 1;
  3470. jerr = JetRetrieveColumn(
  3471. pJetDBStruct->JetSesID,
  3472. pJetDBStruct->JetCatNameBuddyTableID,
  3473. pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID,
  3474. wszCatalogName,
  3475. CATDB_MAX_CATNAME_LENGTH,
  3476. &dwLength,
  3477. JET_bitRetrieveCopy,
  3478. &JetRetInfo);
  3479. while (jerr == JET_errSuccess)
  3480. {
  3481. //
  3482. // Compare to see if this is the name we are supposed to add,
  3483. // if so, we are done, so get out
  3484. //
  3485. if (_wcsicmp(pwszNameToAdd, wszCatalogName) == 0)
  3486. {
  3487. goto CommonReturn;
  3488. }
  3489. //
  3490. // Setup for next loop
  3491. //
  3492. JetRetInfo.itagSequence++;
  3493. jerr = JetRetrieveColumn(
  3494. pJetDBStruct->JetSesID,
  3495. pJetDBStruct->JetCatNameBuddyTableID,
  3496. pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID,
  3497. wszCatalogName,
  3498. CATDB_MAX_CATNAME_LENGTH,
  3499. &dwLength,
  3500. JET_bitRetrieveCopy,
  3501. &JetRetInfo);
  3502. }
  3503. //
  3504. // Check to see if a real error occurred and not just a JET_wrnColumnNull
  3505. //
  3506. if (_CatDBJET_errFailure(jerr))
  3507. {
  3508. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3509. }
  3510. //
  3511. // Prepare, then insert the new buddy name into the list
  3512. //
  3513. if (_CatDBJET_errFailure(jerr =
  3514. JetPrepareUpdate(
  3515. pJetDBStruct->JetSesID,
  3516. pJetDBStruct->JetCatNameBuddyTableID,
  3517. JET_prepReplace)))
  3518. {
  3519. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3520. }
  3521. memset(&JetSetInfo, 0, sizeof(JetSetInfo));
  3522. JetSetInfo.cbStruct = sizeof(JetSetInfo);
  3523. JetSetInfo.itagSequence = 0; // insert in next open position
  3524. if (_CatDBJET_errFailure(jerr =
  3525. JetSetColumn(
  3526. pJetDBStruct->JetSesID,
  3527. pJetDBStruct->JetCatNameBuddyTableID,
  3528. pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID,
  3529. (BYTE const *) pwszNameToAdd,
  3530. (wcslen(pwszNameToAdd) + 1) * sizeof(WCHAR),
  3531. 0,
  3532. &JetSetInfo)))
  3533. {
  3534. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3535. }
  3536. if (_CatDBJET_errFailure(jerr =
  3537. JetUpdate(
  3538. pJetDBStruct->JetSesID,
  3539. pJetDBStruct->JetCatNameBuddyTableID,
  3540. NULL,
  3541. 0,
  3542. NULL)))
  3543. {
  3544. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3545. }
  3546. CommonReturn:
  3547. return fRet;
  3548. ErrorReturn:
  3549. fRet = FALSE;
  3550. goto CommonReturn;
  3551. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  3552. }
  3553. //---------------------------------------------------------------------------------------
  3554. //
  3555. // _CatDBAddWholeBuddyList
  3556. //
  3557. //---------------------------------------------------------------------------------------
  3558. BOOL
  3559. _CatDBAddWholeBuddyList(
  3560. PJET_DB_STRUCT pJetDBStruct,
  3561. LPWSTR pwszBuddyToAddTo,
  3562. LPWSTR pwszBuddyListName)
  3563. {
  3564. BOOL fRet = TRUE;
  3565. JET_ERR jerr;
  3566. JET_RETINFO JetRetInfo;
  3567. WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH];
  3568. DWORD dwLength;
  3569. //
  3570. // seek to the pwszBuddyListName row in the CatNameBuddy table
  3571. //
  3572. jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszBuddyListName);
  3573. if (jerr == JET_errRecordNotFound)
  3574. {
  3575. //
  3576. // this bad, since we know the row should exist
  3577. //
  3578. CATDBSVC_SETERR_LOG_RETURN(JET_errRecordNotFound, ErrorJetDatabase)
  3579. }
  3580. else if (_CatDBJET_errFailure(jerr))
  3581. {
  3582. //
  3583. // error
  3584. //
  3585. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3586. }
  3587. //
  3588. // Get each buddy in the list and add it to pwszBuddyToAddTo's buddy list
  3589. //
  3590. memset(&JetRetInfo, 0, sizeof(JetRetInfo));
  3591. JetRetInfo.cbStruct = sizeof(JetRetInfo);
  3592. JetRetInfo.itagSequence = 1;
  3593. jerr = JetRetrieveColumn(
  3594. pJetDBStruct->JetSesID,
  3595. pJetDBStruct->JetCatNameBuddyTableID,
  3596. pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID,
  3597. wszCatalogName,
  3598. CATDB_MAX_CATNAME_LENGTH,
  3599. &dwLength,
  3600. JET_bitRetrieveCopy,
  3601. &JetRetInfo);
  3602. while (jerr == JET_errSuccess)
  3603. {
  3604. //
  3605. // Add the buddy that was found to the current catalogs buddy list
  3606. //
  3607. if (!_CatDBAddNameToBuddyList(
  3608. pJetDBStruct,
  3609. wszCatalogName,
  3610. pwszBuddyToAddTo))
  3611. {
  3612. CATDBSVC_LOGERR_LASTERR()
  3613. goto ErrorReturn;
  3614. }
  3615. //
  3616. // setup for next loop
  3617. //
  3618. //
  3619. // NOTE - we have to re-seek since the cursor was reset in
  3620. // the _CatDBAddNameToBuddyList call
  3621. //
  3622. jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszBuddyListName);
  3623. if (jerr == JET_errRecordNotFound)
  3624. {
  3625. //
  3626. // this bad, since we know the row should exist
  3627. //
  3628. CATDBSVC_SETERR_LOG_RETURN(JET_errRecordNotFound, ErrorJetDatabase)
  3629. }
  3630. else if (jerr != JET_errSuccess)
  3631. {
  3632. //
  3633. // error
  3634. //
  3635. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3636. }
  3637. JetRetInfo.itagSequence++;
  3638. jerr = JetRetrieveColumn(
  3639. pJetDBStruct->JetSesID,
  3640. pJetDBStruct->JetCatNameBuddyTableID,
  3641. pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID,
  3642. wszCatalogName,
  3643. CATDB_MAX_CATNAME_LENGTH,
  3644. &dwLength,
  3645. JET_bitRetrieveCopy,
  3646. &JetRetInfo);
  3647. }
  3648. //
  3649. // Check to see if a real error occurred and not just a JET_wrnColumnNull
  3650. //
  3651. if (_CatDBJET_errFailure(jerr))
  3652. {
  3653. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  3654. }
  3655. CommonReturn:
  3656. return fRet;
  3657. ErrorReturn:
  3658. fRet = FALSE;
  3659. goto CommonReturn;
  3660. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  3661. }
  3662. //---------------------------------------------------------------------------------------
  3663. //
  3664. // _CatDBMoveInUseFileToTempLocation
  3665. //
  3666. //---------------------------------------------------------------------------------------
  3667. BOOL
  3668. _CatDBMoveInUseFileToTempLocation(
  3669. LPWSTR pwszFile
  3670. )
  3671. {
  3672. BOOL fRet = TRUE;
  3673. WCHAR wszTempFile[MAX_PATH];
  3674. HKEY hKey = NULL;
  3675. HKEY hKey2 = NULL;
  3676. DWORD dwDisposition;
  3677. DWORD i;
  3678. //
  3679. // Get the temp file name that the file will be renamed to
  3680. //
  3681. if (0 == GetTempFileNameW(
  3682. g_pwszCatalogFileBaseDirectory,
  3683. L"TMP",
  3684. 0,
  3685. wszTempFile))
  3686. {
  3687. CATDBSVC_LOGERR_LASTERR()
  3688. goto ErrorGetTempFileName;
  3689. }
  3690. //
  3691. // GetTempFileName actually creates the file, so delete it before doing
  3692. // the move
  3693. //
  3694. DeleteFileW(wszTempFile);
  3695. //
  3696. // Move the file to a temporary name
  3697. //
  3698. if (!MoveFileW(pwszFile, wszTempFile))
  3699. {
  3700. CATDBSVC_LOGERR_LASTERR()
  3701. goto ErrorMoveFile;
  3702. }
  3703. //
  3704. // The moved copy is still being accessed, so log the name of the file
  3705. // to make sure it gets cleaned up later.
  3706. //
  3707. if (RegCreateKeyExW(
  3708. HKEY_LOCAL_MACHINE,
  3709. WSZ_REG_TEMP_FILES_KEY,
  3710. 0,
  3711. NULL,
  3712. REG_OPTION_NON_VOLATILE,
  3713. KEY_ALL_ACCESS,
  3714. NULL,
  3715. &hKey,
  3716. &dwDisposition) == ERROR_SUCCESS)
  3717. {
  3718. //
  3719. // convert all '\\' to '*'
  3720. //
  3721. for (i=0; i<wcslen(wszTempFile); i++)
  3722. {
  3723. if (wszTempFile[i] == L'\\')
  3724. {
  3725. wszTempFile[i] = L'*';
  3726. }
  3727. }
  3728. if (RegCreateKeyW(
  3729. hKey,
  3730. wszTempFile,
  3731. &hKey2) == ERROR_SUCCESS)
  3732. {
  3733. RegCloseKey(hKey2);
  3734. }
  3735. }
  3736. CommonReturn:
  3737. if (hKey != NULL)
  3738. {
  3739. RegCloseKey(hKey);
  3740. }
  3741. return fRet;
  3742. ErrorReturn:
  3743. fRet = FALSE;
  3744. goto CommonReturn;
  3745. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorGetTempFileName)
  3746. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMoveFile)
  3747. }
  3748. //---------------------------------------------------------------------------------------
  3749. //
  3750. // _CatDBCleanupTempFiles
  3751. //
  3752. //---------------------------------------------------------------------------------------
  3753. void
  3754. _CatDBCleanupTempFiles()
  3755. {
  3756. HKEY hKey = NULL;
  3757. DWORD dwIndex = 0;
  3758. DWORD dwRet = 0;
  3759. DWORD dwDisposition;
  3760. WCHAR wszFileToDelete[MAX_PATH + 1];
  3761. DWORD i;
  3762. //
  3763. // Make sure only one thread does the cleanup at a time
  3764. //
  3765. __try
  3766. {
  3767. EnterCriticalSection(&g_CleanupTempFilesCS);
  3768. }
  3769. __except(EXCEPTION_EXECUTE_HANDLER)
  3770. {
  3771. SetLastError(GetExceptionCode());
  3772. CATDBSVC_LOGERR_LASTERR()
  3773. return;
  3774. }
  3775. if (g_fCleaninUpTempFiles)
  3776. {
  3777. LeaveCriticalSection(&g_CleanupTempFilesCS);
  3778. return;
  3779. }
  3780. g_fCleaninUpTempFiles = TRUE;
  3781. LeaveCriticalSection(&g_CleanupTempFilesCS);
  3782. //
  3783. // Open the key that contains all the tempfile name keys
  3784. //
  3785. if (RegCreateKeyExW(
  3786. HKEY_LOCAL_MACHINE,
  3787. WSZ_REG_TEMP_FILES_KEY,
  3788. 0,
  3789. NULL,
  3790. REG_OPTION_NON_VOLATILE,
  3791. KEY_ALL_ACCESS,
  3792. NULL,
  3793. &hKey,
  3794. &dwDisposition) == ERROR_SUCCESS)
  3795. {
  3796. //
  3797. // Query to see how many keys there are
  3798. //
  3799. if (RegQueryInfoKey(
  3800. hKey,
  3801. NULL,
  3802. NULL,
  3803. NULL,
  3804. &dwIndex,
  3805. NULL,
  3806. NULL,
  3807. NULL,
  3808. NULL,
  3809. NULL,
  3810. NULL,
  3811. NULL) == ERROR_SUCCESS)
  3812. {
  3813. dwIndex--;
  3814. //
  3815. // Enumerate through all the keys and try to delete the
  3816. // corresponding temp files
  3817. //
  3818. while (RegEnumKeyW(
  3819. hKey,
  3820. dwIndex,
  3821. wszFileToDelete,
  3822. MAX_PATH + 1) == ERROR_SUCCESS)
  3823. {
  3824. //
  3825. // convert all '*' back to '\\'
  3826. //
  3827. for (i=0; i<wcslen(wszFileToDelete); i++)
  3828. {
  3829. if (wszFileToDelete[i] == L'*')
  3830. {
  3831. wszFileToDelete[i] = L'\\';
  3832. }
  3833. }
  3834. dwRet = DeleteFileW(wszFileToDelete);
  3835. if ((dwRet != 0) || (GetLastError() == ERROR_FILE_NOT_FOUND))
  3836. {
  3837. //
  3838. // convert all '\\' back to '*' and get delete the key
  3839. // that represents the file which has now been deleted
  3840. //
  3841. for (i=0; i<wcslen(wszFileToDelete); i++)
  3842. {
  3843. if (wszFileToDelete[i] == L'\\')
  3844. {
  3845. wszFileToDelete[i] = L'*';
  3846. }
  3847. }
  3848. RegDeleteKey(hKey, wszFileToDelete);
  3849. }
  3850. dwIndex--;
  3851. }
  3852. }
  3853. RegCloseKey(hKey);
  3854. }
  3855. __try
  3856. {
  3857. EnterCriticalSection(&g_CleanupTempFilesCS);
  3858. }
  3859. __except(EXCEPTION_EXECUTE_HANDLER)
  3860. {
  3861. SetLastError(GetExceptionCode());
  3862. CATDBSVC_LOGERR_LASTERR()
  3863. g_fCleaninUpTempFiles = FALSE;
  3864. return;
  3865. }
  3866. g_fCleaninUpTempFiles = FALSE;
  3867. LeaveCriticalSection(&g_CleanupTempFilesCS);
  3868. }
  3869. //---------------------------------------------------------------------------------------
  3870. //
  3871. // _CatDBDeleteCatalogEntriesFromDatabase
  3872. //
  3873. //---------------------------------------------------------------------------------------
  3874. BOOL
  3875. _CatDBDeleteCatalogEntriesFromDatabase(
  3876. PJET_DB_STRUCT pJetDBStruct,
  3877. LPWSTR pwszCatalogName)
  3878. {
  3879. BOOL fRet = TRUE;
  3880. PCCTL_CONTEXT pCTLContext = NULL;
  3881. HANDLE hMappedFile = NULL;
  3882. BYTE *pbMappedFile = NULL;
  3883. WCHAR *pwszCatBaseName;
  3884. DWORD i;
  3885. SPC_INDIRECT_DATA_CONTENT *pIndirectData = NULL;
  3886. BOOL fDeleteUsingName = TRUE;
  3887. DWORD dwErr = 0;
  3888. //
  3889. // Extract the base name from the full path name
  3890. //
  3891. if (NULL == (pwszCatBaseName = wcsrchr(pwszCatalogName, L'\\')))
  3892. {
  3893. pwszCatBaseName = wcsrchr(pwszCatalogName, L':');
  3894. }
  3895. if (pwszCatBaseName != NULL)
  3896. {
  3897. pwszCatBaseName++;
  3898. }
  3899. else
  3900. {
  3901. pwszCatBaseName = pwszCatalogName;
  3902. }
  3903. //
  3904. // Open a CTL context on the catalog file whose entries are being deleted
  3905. //
  3906. if (CatUtil_CreateCTLContextFromFileName(
  3907. pwszCatalogName,
  3908. &hMappedFile,
  3909. &pbMappedFile,
  3910. &pCTLContext,
  3911. FALSE))
  3912. {
  3913. //
  3914. // Since we can create a CTL context on the catalog, first try to
  3915. // delete without walking the whole HashCatnameTable, which we will
  3916. // have to do if we delete using the catalog name only
  3917. //
  3918. fDeleteUsingName = FALSE;
  3919. //
  3920. // Loop for each hash in the catalog file
  3921. //
  3922. for (i=0; i<pCTLContext->pCtlInfo->cCTLEntry; i++)
  3923. {
  3924. if (!_CatDBFindAndDecodeHashInCatEntry(
  3925. &(pCTLContext->pCtlInfo->rgCTLEntry[i]),
  3926. &pIndirectData))
  3927. {
  3928. //
  3929. // Since this failed, fallback and try to delete the catalog
  3930. // from the DB using the catalogs name only
  3931. //
  3932. fDeleteUsingName = TRUE;
  3933. break;
  3934. }
  3935. if (!_CatDBRemoveCatNameFromHashesListOfCatNames(
  3936. pJetDBStruct,
  3937. &(pIndirectData->Digest),
  3938. pwszCatBaseName))
  3939. {
  3940. //
  3941. // Since this failed, fallback and try to delete the catalog
  3942. // from the DB using the catalogs name only
  3943. //
  3944. fDeleteUsingName = TRUE;
  3945. break;
  3946. }
  3947. _CatDBFree(pIndirectData);
  3948. pIndirectData = NULL;
  3949. }
  3950. }
  3951. if (fDeleteUsingName)
  3952. {
  3953. //
  3954. // Since that failed, the catalog is most likely corrupt, so just use
  3955. // the catalog name to delete its entries from the HashCatName table
  3956. //
  3957. if (!_CatDBRemoveCatNameFromCatNameTable(
  3958. pJetDBStruct,
  3959. pwszCatBaseName))
  3960. {
  3961. CATDBSVC_LOGERR_LASTERR()
  3962. goto ErrorReturn;
  3963. }
  3964. }
  3965. //
  3966. // Delete all occurences of CatName from buddy table
  3967. //
  3968. if (!_CatDBRemoveCatNameFromBuddyTable(
  3969. pJetDBStruct,
  3970. pwszCatBaseName))
  3971. {
  3972. CATDBSVC_LOGERR_LASTERR()
  3973. goto ErrorReturn;
  3974. }
  3975. CommonReturn:
  3976. dwErr = GetLastError();
  3977. if (pIndirectData != NULL)
  3978. {
  3979. _CatDBFree(pIndirectData);
  3980. }
  3981. if (pCTLContext != NULL)
  3982. {
  3983. CertFreeCTLContext(pCTLContext);
  3984. }
  3985. if (pbMappedFile != NULL)
  3986. {
  3987. UnmapViewOfFile(pbMappedFile);
  3988. }
  3989. if (hMappedFile != NULL)
  3990. {
  3991. CloseHandle(hMappedFile);
  3992. }
  3993. SetLastError(dwErr);
  3994. return fRet;
  3995. ErrorReturn:
  3996. fRet = FALSE;
  3997. goto CommonReturn;
  3998. }
  3999. //---------------------------------------------------------------------------------------
  4000. //
  4001. // _CatDBRemoveCatNameFromHashesListOfCatNames
  4002. //
  4003. //---------------------------------------------------------------------------------------
  4004. BOOL
  4005. _CatDBRemoveCatNameFromHashesListOfCatNames(
  4006. PJET_DB_STRUCT pJetDBStruct,
  4007. PCRYPT_DATA_BLOB pHashBlob,
  4008. LPWSTR pwszCatBaseName)
  4009. {
  4010. BOOL fRet = TRUE;
  4011. JET_ERR jerr;
  4012. //
  4013. // First, try to find the hash in the HashCatName table.
  4014. //
  4015. jerr = _CatDBSeekInHashCatNameTable(pJetDBStruct, pHashBlob);
  4016. if (jerr == JET_errRecordNotFound)
  4017. {
  4018. //
  4019. // Not found, this is OK since a single catalog may contain the same hash
  4020. // twice, in which case by the second time the hash is being looked for
  4021. // the row may already be gone.
  4022. //
  4023. goto CommonReturn;
  4024. }
  4025. else if (jerr == JET_errSuccess)
  4026. {
  4027. //
  4028. // found
  4029. //
  4030. if (!_CatDBRemoveCatNameFromMultiValuedColumn(
  4031. pJetDBStruct,
  4032. pJetDBStruct->JetHashCatNameTableID,
  4033. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  4034. pwszCatBaseName))
  4035. {
  4036. CATDBSVC_LOGERR_LASTERR()
  4037. goto ErrorReturn;
  4038. }
  4039. }
  4040. else if (_CatDBJET_errFailure(jerr))
  4041. {
  4042. //
  4043. // error
  4044. //
  4045. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4046. }
  4047. CommonReturn:
  4048. return fRet;
  4049. ErrorReturn:
  4050. fRet = FALSE;
  4051. goto CommonReturn;
  4052. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  4053. }
  4054. //---------------------------------------------------------------------------------------
  4055. //
  4056. // _CatDBRemoveCatNameFromMultiValuedColumn
  4057. //
  4058. //---------------------------------------------------------------------------------------
  4059. BOOL
  4060. _CatDBRemoveCatNameFromMultiValuedColumn(
  4061. PJET_DB_STRUCT pJetDBStruct,
  4062. JET_TABLEID jetTableID,
  4063. JET_COLUMNID jetColumnID,
  4064. LPWSTR pwszCatBaseName)
  4065. {
  4066. BOOL fRet = TRUE;
  4067. JET_ERR jerr;
  4068. JET_SETINFO JetSetInfo;
  4069. WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH];
  4070. DWORD dwLength;
  4071. JET_RETINFO JetRetInfo;
  4072. BOOL fDeleteRow = FALSE;
  4073. unsigned long iValueToDelete = 0;
  4074. //
  4075. // Search for the CatName in the current row
  4076. //
  4077. memset(&JetRetInfo, 0, sizeof(JetRetInfo));
  4078. JetRetInfo.cbStruct = sizeof(JetRetInfo);
  4079. JetRetInfo.itagSequence = 1;
  4080. jerr = JetRetrieveColumn(
  4081. pJetDBStruct->JetSesID,
  4082. jetTableID,
  4083. jetColumnID,
  4084. wszCatalogName,
  4085. CATDB_MAX_CATNAME_LENGTH,
  4086. &dwLength,
  4087. JET_bitRetrieveCopy,
  4088. &JetRetInfo);
  4089. while (jerr == JET_errSuccess)
  4090. {
  4091. //
  4092. // See if this is the one
  4093. //
  4094. if (0 == _wcsicmp(pwszCatBaseName, wszCatalogName))
  4095. {
  4096. iValueToDelete = JetRetInfo.itagSequence;
  4097. if (JetRetInfo.itagSequence == 1)
  4098. {
  4099. //
  4100. // If this CatName is the only one in the row, then
  4101. // set a flag to just delete the row
  4102. //
  4103. JetRetInfo.itagSequence = 2;
  4104. jerr = JetRetrieveColumn(
  4105. pJetDBStruct->JetSesID,
  4106. jetTableID,
  4107. jetColumnID,
  4108. wszCatalogName,
  4109. CATDB_MAX_CATNAME_LENGTH,
  4110. &dwLength,
  4111. JET_bitRetrieveCopy,
  4112. &JetRetInfo);
  4113. if (jerr == JET_wrnColumnNull)
  4114. {
  4115. jerr = JET_errSuccess;
  4116. fDeleteRow = TRUE;
  4117. }
  4118. }
  4119. break;
  4120. }
  4121. //
  4122. // Setup for next loop
  4123. //
  4124. JetRetInfo.itagSequence++;
  4125. jerr = JetRetrieveColumn(
  4126. pJetDBStruct->JetSesID,
  4127. jetTableID,
  4128. jetColumnID,
  4129. wszCatalogName,
  4130. CATDB_MAX_CATNAME_LENGTH,
  4131. &dwLength,
  4132. JET_bitRetrieveCopy,
  4133. &JetRetInfo);
  4134. }
  4135. //
  4136. // Make sure the CatName was found
  4137. //
  4138. if (jerr == JET_wrnColumnNull)
  4139. {
  4140. //
  4141. // Not found, this is OK
  4142. //
  4143. goto CommonReturn;
  4144. }
  4145. else if (_CatDBJET_errFailure(jerr))
  4146. {
  4147. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4148. }
  4149. //
  4150. // If this CatName is the only one in the row, then just delete the row,
  4151. // otherwise, remove it from the multi-valued column
  4152. //
  4153. if (fDeleteRow)
  4154. {
  4155. if (_CatDBJET_errFailure(jerr =
  4156. JetDelete(
  4157. pJetDBStruct->JetSesID,
  4158. jetTableID)))
  4159. {
  4160. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4161. }
  4162. }
  4163. else
  4164. {
  4165. //
  4166. // Remove the CatName from the current row
  4167. //
  4168. if (_CatDBJET_errFailure(jerr =
  4169. JetPrepareUpdate(
  4170. pJetDBStruct->JetSesID,
  4171. jetTableID,
  4172. JET_prepReplace)))
  4173. {
  4174. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4175. }
  4176. memset(&JetSetInfo, 0, sizeof(JetSetInfo));
  4177. JetSetInfo.cbStruct = sizeof(JetSetInfo);
  4178. JetSetInfo.itagSequence = iValueToDelete;
  4179. if (_CatDBJET_errFailure(jerr =
  4180. JetSetColumn(
  4181. pJetDBStruct->JetSesID,
  4182. jetTableID,
  4183. jetColumnID,
  4184. NULL,
  4185. 0,
  4186. 0,
  4187. &JetSetInfo)))
  4188. {
  4189. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4190. }
  4191. if (_CatDBJET_errFailure(jerr =
  4192. JetUpdate(
  4193. pJetDBStruct->JetSesID,
  4194. jetTableID,
  4195. NULL,
  4196. 0,
  4197. NULL)))
  4198. {
  4199. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4200. }
  4201. }
  4202. CommonReturn:
  4203. return fRet;
  4204. ErrorReturn:
  4205. fRet = FALSE;
  4206. goto CommonReturn;
  4207. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  4208. }
  4209. //---------------------------------------------------------------------------------------
  4210. //
  4211. // _CatDBRemoveCatNameFromCatNameTable
  4212. //
  4213. //---------------------------------------------------------------------------------------
  4214. BOOL
  4215. _CatDBRemoveCatNameFromCatNameTable(
  4216. PJET_DB_STRUCT pJetDBStruct,
  4217. LPWSTR pwszCatBaseName)
  4218. {
  4219. BOOL fRet = TRUE;
  4220. JET_ERR jerr;
  4221. //
  4222. // Delete this CatName from every row that contains it
  4223. //
  4224. jerr = JetMove(
  4225. pJetDBStruct->JetSesID,
  4226. pJetDBStruct->JetHashCatNameTableID,
  4227. JET_MoveFirst,
  4228. 0);
  4229. while (jerr == JET_errSuccess)
  4230. {
  4231. if (!_CatDBRemoveCatNameFromMultiValuedColumn(
  4232. pJetDBStruct,
  4233. pJetDBStruct->JetHashCatNameTableID,
  4234. pJetDBStruct->JetHashCatNameTable_CatNameColumnID,
  4235. pwszCatBaseName))
  4236. {
  4237. CATDBSVC_LOGERR_LASTERR()
  4238. goto ErrorReturn;
  4239. }
  4240. //
  4241. // Setup for next loop
  4242. //
  4243. jerr = JetMove(
  4244. pJetDBStruct->JetSesID,
  4245. pJetDBStruct->JetHashCatNameTableID,
  4246. JET_MoveNext,
  4247. 0);
  4248. }
  4249. //
  4250. // See if this was a real error, or just no more records
  4251. //
  4252. if ((jerr != JET_errNoCurrentRecord) && _CatDBJET_errFailure(jerr))
  4253. {
  4254. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4255. }
  4256. CommonReturn:
  4257. return fRet;
  4258. ErrorReturn:
  4259. fRet = FALSE;
  4260. goto CommonReturn;
  4261. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  4262. }
  4263. //---------------------------------------------------------------------------------------
  4264. //
  4265. // _CatDBRemoveCatNameFromBuddyTable
  4266. //
  4267. //---------------------------------------------------------------------------------------
  4268. BOOL
  4269. _CatDBRemoveCatNameFromBuddyTable(
  4270. PJET_DB_STRUCT pJetDBStruct,
  4271. LPWSTR pwszCatBaseName)
  4272. {
  4273. BOOL fRet = TRUE;
  4274. JET_ERR jerr;
  4275. //
  4276. // First, delete this CatName's buddy list
  4277. //
  4278. jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszCatBaseName);
  4279. if (jerr == JET_errSuccess)
  4280. {
  4281. if (_CatDBJET_errFailure(jerr =
  4282. JetDelete(
  4283. pJetDBStruct->JetSesID,
  4284. pJetDBStruct->JetCatNameBuddyTableID)))
  4285. {
  4286. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4287. }
  4288. }
  4289. //
  4290. // Second, delete this CatName from everyone elses buddy list
  4291. //
  4292. jerr = JetMove(
  4293. pJetDBStruct->JetSesID,
  4294. pJetDBStruct->JetCatNameBuddyTableID,
  4295. JET_MoveFirst,
  4296. 0);
  4297. while (jerr == JET_errSuccess)
  4298. {
  4299. if (!_CatDBRemoveCatNameFromMultiValuedColumn(
  4300. pJetDBStruct,
  4301. pJetDBStruct->JetCatNameBuddyTableID,
  4302. pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID,
  4303. pwszCatBaseName))
  4304. {
  4305. CATDBSVC_LOGERR_LASTERR()
  4306. goto ErrorReturn;
  4307. }
  4308. //
  4309. // Setup for next loop
  4310. //
  4311. jerr = JetMove(
  4312. pJetDBStruct->JetSesID,
  4313. pJetDBStruct->JetCatNameBuddyTableID,
  4314. JET_MoveNext,
  4315. 0);
  4316. }
  4317. //
  4318. // See if this was a real error, or just no more records
  4319. //
  4320. if ((jerr != JET_errNoCurrentRecord) && _CatDBJET_errFailure(jerr))
  4321. {
  4322. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4323. }
  4324. CommonReturn:
  4325. return fRet;
  4326. ErrorReturn:
  4327. fRet = FALSE;
  4328. goto CommonReturn;
  4329. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  4330. }
  4331. //---------------------------------------------------------------------------------------
  4332. //
  4333. // _CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames
  4334. //
  4335. //---------------------------------------------------------------------------------------
  4336. BOOL
  4337. _CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames(
  4338. PJET_DB_STRUCT pJetDBStruct,
  4339. LPWSTR pwszCatName,
  4340. DWORD __RPC_FAR *pdwNumCatalogNames,
  4341. LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames,
  4342. BOOL fRecursiveCall)
  4343. {
  4344. BOOL fRet = TRUE;
  4345. JET_ERR jerr;
  4346. JET_RETINFO JetRetInfo;
  4347. WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH];
  4348. DWORD dwLength;
  4349. //
  4350. // First add the original catname
  4351. //
  4352. if (!_CatDBAddCatNameToReturnBuddyListIfNotExist(
  4353. pwszCatName,
  4354. pdwNumCatalogNames,
  4355. pppwszCatalogNames))
  4356. {
  4357. CATDBSVC_LOGERR_LASTERR()
  4358. goto ErrorReturn;
  4359. }
  4360. //
  4361. // Seek to the catname's buddy list
  4362. //
  4363. jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszCatName);
  4364. if (jerr == JET_errSuccess)
  4365. {
  4366. //
  4367. // Add all the catname's buddies, and catname's buddies' buddies (only do one recursion)
  4368. //
  4369. memset(&JetRetInfo, 0, sizeof(JetRetInfo));
  4370. JetRetInfo.cbStruct = sizeof(JetRetInfo);
  4371. JetRetInfo.itagSequence = 1;
  4372. jerr = JetRetrieveColumn(
  4373. pJetDBStruct->JetSesID,
  4374. pJetDBStruct->JetCatNameBuddyTableID,
  4375. pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID,
  4376. wszCatalogName,
  4377. CATDB_MAX_CATNAME_LENGTH,
  4378. &dwLength,
  4379. JET_bitRetrieveCopy,
  4380. &JetRetInfo);
  4381. while (jerr == JET_errSuccess)
  4382. {
  4383. if (fRecursiveCall)
  4384. {
  4385. if (!_CatDBAddCatNameToReturnBuddyListIfNotExist(
  4386. wszCatalogName,
  4387. pdwNumCatalogNames,
  4388. pppwszCatalogNames))
  4389. {
  4390. CATDBSVC_LOGERR_LASTERR()
  4391. goto ErrorReturn;
  4392. }
  4393. }
  4394. else
  4395. {
  4396. //
  4397. // Recurse to get the buddies' buddies
  4398. //
  4399. if (!_CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames(
  4400. pJetDBStruct,
  4401. wszCatalogName,
  4402. pdwNumCatalogNames,
  4403. pppwszCatalogNames,
  4404. TRUE))
  4405. {
  4406. CATDBSVC_LOGERR_LASTERR()
  4407. goto ErrorReturn;
  4408. }
  4409. }
  4410. //
  4411. // Re-seek to the catname's buddy list, since it could have moved in the
  4412. // recursive call to this function
  4413. //
  4414. jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszCatName);
  4415. if (_CatDBJET_errFailure(jerr))
  4416. {
  4417. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4418. }
  4419. //
  4420. // Setup for next loop
  4421. //
  4422. JetRetInfo.itagSequence++;
  4423. jerr = JetRetrieveColumn(
  4424. pJetDBStruct->JetSesID,
  4425. pJetDBStruct->JetCatNameBuddyTableID,
  4426. pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID,
  4427. wszCatalogName,
  4428. CATDB_MAX_CATNAME_LENGTH,
  4429. &dwLength,
  4430. JET_bitRetrieveCopy,
  4431. &JetRetInfo);
  4432. }
  4433. //
  4434. // Check to see if a real error occurred and not just a JET_wrnColumnNull
  4435. //
  4436. if (_CatDBJET_errFailure(jerr))
  4437. {
  4438. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4439. }
  4440. }
  4441. CommonReturn:
  4442. return fRet;
  4443. ErrorReturn:
  4444. fRet = FALSE;
  4445. goto CommonReturn;
  4446. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  4447. }
  4448. //---------------------------------------------------------------------------------------
  4449. //
  4450. // _CatDBAddCatNameToReturnBuddyListIfNotExist
  4451. //
  4452. //---------------------------------------------------------------------------------------
  4453. BOOL
  4454. _CatDBAddCatNameToReturnBuddyListIfNotExist(
  4455. LPWSTR pwszBuddy,
  4456. DWORD __RPC_FAR *pdwNumCatalogNames,
  4457. LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames)
  4458. {
  4459. BOOL fRet = TRUE;
  4460. DWORD i;
  4461. BOOL fAlreadyExists = FALSE;
  4462. LPWSTR *rgTemp = NULL;
  4463. //
  4464. // First, see if the name already exists in the list
  4465. //
  4466. for (i=0; i<(*pdwNumCatalogNames); i++)
  4467. {
  4468. if (_wcsicmp((*pppwszCatalogNames)[i], pwszBuddy) == 0)
  4469. {
  4470. fAlreadyExists = TRUE;
  4471. break;
  4472. }
  4473. }
  4474. //
  4475. // Add it if it doesn't already exist
  4476. //
  4477. if (!fAlreadyExists)
  4478. {
  4479. //
  4480. // Allocate a new slot in the array of buddy names
  4481. //
  4482. if ((*pdwNumCatalogNames) == 0)
  4483. {
  4484. *pppwszCatalogNames = (LPWSTR __RPC_FAR *)
  4485. midl_user_allocate(sizeof(LPWSTR));
  4486. }
  4487. else
  4488. {
  4489. rgTemp = *pppwszCatalogNames;
  4490. *pppwszCatalogNames = (LPWSTR __RPC_FAR *)
  4491. midl_user_reallocate(
  4492. *pppwszCatalogNames,
  4493. ((*pdwNumCatalogNames) + 1) * sizeof(LPWSTR));
  4494. }
  4495. //
  4496. // Make sure allocation worked
  4497. //
  4498. if ((*pppwszCatalogNames) == NULL)
  4499. {
  4500. *pppwszCatalogNames = rgTemp;
  4501. CATDBSVC_SETERR_LOG_RETURN(E_OUTOFMEMORY, ErrorMemory)
  4502. }
  4503. (*pppwszCatalogNames)[(*pdwNumCatalogNames)] = (LPWSTR)
  4504. midl_user_allocate((wcslen(pwszBuddy) + 1) * sizeof(WCHAR));
  4505. if ((*pppwszCatalogNames)[(*pdwNumCatalogNames)] == NULL)
  4506. {
  4507. CATDBSVC_SETERR_LOG_RETURN(E_OUTOFMEMORY, ErrorMemory)
  4508. }
  4509. wcscpy((*pppwszCatalogNames)[(*pdwNumCatalogNames)], pwszBuddy);
  4510. (*pdwNumCatalogNames)++;
  4511. }
  4512. CommonReturn:
  4513. return fRet;
  4514. ErrorReturn:
  4515. fRet = FALSE;
  4516. goto CommonReturn;
  4517. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory)
  4518. }
  4519. //---------------------------------------------------------------------------------------
  4520. //
  4521. // _CatDBSeekInCatNameBuddyTable
  4522. //
  4523. //---------------------------------------------------------------------------------------
  4524. JET_ERR
  4525. _CatDBSeekInCatNameBuddyTable(
  4526. PJET_DB_STRUCT pJetDBStruct,
  4527. LPWSTR pwszBuddyRow)
  4528. {
  4529. JET_ERR jerr;
  4530. if (_CatDBJET_errFailure(jerr =
  4531. JetMakeKey(
  4532. pJetDBStruct->JetSesID,
  4533. pJetDBStruct->JetCatNameBuddyTableID,
  4534. (BYTE const *) pwszBuddyRow,
  4535. (wcslen(pwszBuddyRow) + 1) * sizeof(WCHAR),
  4536. JET_bitNewKey)))
  4537. {
  4538. return jerr;
  4539. }
  4540. jerr = JetSeek(
  4541. pJetDBStruct->JetSesID,
  4542. pJetDBStruct->JetCatNameBuddyTableID,
  4543. JET_bitSeekEQ);
  4544. return jerr;
  4545. }
  4546. //---------------------------------------------------------------------------------------
  4547. //
  4548. // _CatDBSeekInHashCatNameTable
  4549. //
  4550. //---------------------------------------------------------------------------------------
  4551. JET_ERR
  4552. _CatDBSeekInHashCatNameTable(
  4553. PJET_DB_STRUCT pJetDBStruct,
  4554. PCRYPT_DATA_BLOB pHashBlob)
  4555. {
  4556. JET_ERR jerr;
  4557. if (_CatDBJET_errFailure(jerr =
  4558. JetMakeKey(
  4559. pJetDBStruct->JetSesID,
  4560. pJetDBStruct->JetHashCatNameTableID,
  4561. pHashBlob->pbData,
  4562. pHashBlob->cbData,
  4563. JET_bitNewKey)))
  4564. {
  4565. return jerr;
  4566. }
  4567. jerr = JetSeek(
  4568. pJetDBStruct->JetSesID,
  4569. pJetDBStruct->JetHashCatNameTableID,
  4570. JET_bitSeekEQ);
  4571. return jerr;
  4572. }
  4573. //---------------------------------------------------------------------------------------
  4574. //
  4575. // _CatDBNotifyClients
  4576. //
  4577. //---------------------------------------------------------------------------------------
  4578. void
  4579. _CatDBNotifyClients(void)
  4580. {
  4581. DWORD i = 0;
  4582. while (i < g_NumNotificationStructs)
  4583. {
  4584. if (g_rgNotificationStructs[i].hDuplicatedNotificationHandle !=
  4585. INVALID_HANDLE_VALUE)
  4586. {
  4587. SetEvent(g_rgNotificationStructs[i].hDuplicatedNotificationHandle);
  4588. }
  4589. i++;
  4590. }
  4591. }
  4592. //---------------------------------------------------------------------------------------
  4593. //
  4594. // _CatDBCreateNewCatalogFileName
  4595. //
  4596. //---------------------------------------------------------------------------------------
  4597. #define SZ_UNIQUE_CAT_FILENAME_FORMAT L"%X.CAT"
  4598. #define MAX_UNIQUE_CAT_FILES 0xffffffff
  4599. LPWSTR
  4600. _CatDBCreateNewCatalogFileName(
  4601. LPCWSTR pwszCatalogFileDir,
  4602. LPCWSTR pwszCatName,
  4603. BOOL *pfFileAlreadyExists)
  4604. {
  4605. LPWSTR pwszFullyQualifiedCatName = NULL;
  4606. WCHAR pwszTempBaseName[56];
  4607. BOOL fUniqueFileNameFound;
  4608. DWORD dw;
  4609. HANDLE hTestFile = INVALID_HANDLE_VALUE;
  4610. DWORD dwLastErr = 0;
  4611. if (pwszCatName != NULL)
  4612. {
  4613. //
  4614. // The caller specified the cat name to use, so just concatenate the
  4615. // the path and the name
  4616. //
  4617. if (NULL == (pwszFullyQualifiedCatName = _CATDBConstructWSTRPath(
  4618. pwszCatalogFileDir,
  4619. pwszCatName)))
  4620. {
  4621. CATDBSVC_LOGERR_LASTERR()
  4622. goto ErrorReturn;
  4623. }
  4624. //
  4625. // See if this file already exists by trying to create the file
  4626. //
  4627. hTestFile = CreateFileW(
  4628. pwszFullyQualifiedCatName,
  4629. GENERIC_WRITE | GENERIC_READ,
  4630. 0, // dwShareMode
  4631. NULL,
  4632. OPEN_EXISTING,
  4633. FILE_ATTRIBUTE_NORMAL,
  4634. NULL); // hTemplateFile
  4635. dwLastErr = GetLastError();
  4636. if ((hTestFile == INVALID_HANDLE_VALUE) &&
  4637. ( (dwLastErr == ERROR_FILE_NOT_FOUND) ||
  4638. (dwLastErr == ERROR_PATH_NOT_FOUND) ||
  4639. (dwLastErr == ERROR_BAD_NETPATH)))
  4640. {
  4641. *pfFileAlreadyExists = FALSE;
  4642. }
  4643. else if (hTestFile == INVALID_HANDLE_VALUE)
  4644. {
  4645. *pfFileAlreadyExists = TRUE;
  4646. }
  4647. else
  4648. {
  4649. *pfFileAlreadyExists = TRUE;
  4650. CloseHandle(hTestFile);
  4651. }
  4652. }
  4653. else
  4654. {
  4655. *pfFileAlreadyExists = FALSE;
  4656. //
  4657. // Create a unique name for the directory in question
  4658. //
  4659. fUniqueFileNameFound = FALSE;
  4660. dw = 1;
  4661. while ((!fUniqueFileNameFound) && (dw != 0)) // (dw == 0) after rollover.
  4662. {
  4663. wsprintfW(pwszTempBaseName, SZ_UNIQUE_CAT_FILENAME_FORMAT, dw);
  4664. if (NULL == (pwszFullyQualifiedCatName = _CATDBConstructWSTRPath(
  4665. pwszCatalogFileDir,
  4666. pwszTempBaseName)))
  4667. if (pwszFullyQualifiedCatName == NULL)
  4668. {
  4669. CATDBSVC_LOGERR_LASTERR()
  4670. goto ErrorReturn;
  4671. }
  4672. //
  4673. // See if this is a unique file name by trying to create the file
  4674. //
  4675. hTestFile = CreateFileW(
  4676. pwszFullyQualifiedCatName,
  4677. GENERIC_WRITE | GENERIC_READ,
  4678. 0, // dwShareMode
  4679. NULL,
  4680. OPEN_EXISTING,
  4681. FILE_ATTRIBUTE_NORMAL,
  4682. NULL); // hTemplateFile
  4683. if (hTestFile == INVALID_HANDLE_VALUE)
  4684. {
  4685. fUniqueFileNameFound = TRUE;
  4686. }
  4687. else
  4688. {
  4689. CloseHandle(hTestFile);
  4690. //
  4691. // Setup for next iteration
  4692. //
  4693. _CatDBFree(pwszFullyQualifiedCatName);
  4694. pwszFullyQualifiedCatName = NULL;
  4695. dw++;
  4696. }
  4697. }
  4698. }
  4699. CommonReturn:
  4700. return pwszFullyQualifiedCatName;
  4701. ErrorReturn:
  4702. if (pwszFullyQualifiedCatName != NULL)
  4703. {
  4704. _CatDBFree(pwszFullyQualifiedCatName);
  4705. }
  4706. pwszFullyQualifiedCatName = NULL;
  4707. goto CommonReturn;
  4708. }
  4709. //---------------------------------------------------------------------------------------
  4710. //
  4711. // _CatDBFindAndDecodeHashInCatEntry
  4712. //
  4713. //---------------------------------------------------------------------------------------
  4714. BOOL
  4715. _CatDBFindAndDecodeHashInCatEntry(
  4716. PCTL_ENTRY pctlEntry,
  4717. SPC_INDIRECT_DATA_CONTENT **ppIndirectData)
  4718. {
  4719. BOOL fRet = TRUE;
  4720. DWORD i;
  4721. DWORD cbIndirectData = 0;
  4722. *ppIndirectData = NULL;
  4723. //
  4724. // Search for the hash in the attributes
  4725. //
  4726. for (i=0; i<pctlEntry->cAttribute; i++)
  4727. {
  4728. if (strcmp(pctlEntry->rgAttribute[i].pszObjId, SPC_INDIRECT_DATA_OBJID) == 0)
  4729. {
  4730. break;
  4731. }
  4732. }
  4733. //
  4734. // Make sure the hash was found
  4735. //
  4736. if (i >= pctlEntry->cAttribute)
  4737. {
  4738. CATDBSVC_LOGERR_LASTERR()
  4739. goto ErrorInvalidCatalogFormat;
  4740. }
  4741. //
  4742. // decode the indirect data
  4743. //
  4744. if (!CryptDecodeObject(
  4745. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  4746. SPC_INDIRECT_DATA_CONTENT_STRUCT,
  4747. pctlEntry->rgAttribute[i].rgValue[0].pbData,
  4748. pctlEntry->rgAttribute[i].rgValue[0].cbData,
  4749. 0,
  4750. NULL,
  4751. &cbIndirectData))
  4752. {
  4753. CATDBSVC_LOGERR_LASTERR()
  4754. goto ErrorCryptDecodeObject;
  4755. }
  4756. if (NULL == (*ppIndirectData = (SPC_INDIRECT_DATA_CONTENT *)
  4757. _CatDBAlloc(cbIndirectData)))
  4758. {
  4759. CATDBSVC_LOGERR_LASTERR()
  4760. goto ErrorMemory;
  4761. }
  4762. if (!CryptDecodeObject(
  4763. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  4764. SPC_INDIRECT_DATA_CONTENT_STRUCT,
  4765. pctlEntry->rgAttribute[i].rgValue[0].pbData,
  4766. pctlEntry->rgAttribute[i].rgValue[0].cbData,
  4767. 0,
  4768. *ppIndirectData,
  4769. &cbIndirectData))
  4770. {
  4771. CATDBSVC_LOGERR_LASTERR()
  4772. goto ErrorCryptDecodeObject;
  4773. }
  4774. CommonReturn:
  4775. return fRet;
  4776. ErrorReturn:
  4777. fRet = FALSE;
  4778. goto CommonReturn;
  4779. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorInvalidCatalogFormat)
  4780. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorCryptDecodeObject)
  4781. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory)
  4782. }
  4783. #define SZ_HASH_CATNAME_TABLE "HashCatNameTable"
  4784. #define SZ_HASH_CATNAME_TABLE_HASHCOL "HashCatNameTable_HashCol"
  4785. #define SZ_HASH_CATNAME_TABLE_CATNAMECOL "HashCatNameTable_CatNameCol"
  4786. #define SZ_HASH_CATNAME_TABLE_INDEX "HashCatNameTable_Index"
  4787. #define SZ_HASH_CATNAME_TABLE_INDEX_DEF "+HashCatNameTable_HashCol\0"
  4788. #define SZ_CATNAME_BUDDY_TABLE "CatNameBuddyTable"
  4789. #define SZ_CATNAME_BUDDY_TABLE_CATNAMECOL "CatNameBuddyTable_CatNameCol"
  4790. #define SZ_CATNAME_BUDDY_TABLE_BUDDYCOL "CatNameBuddyTable_BuddyCol"
  4791. #define SZ_CATNAME_BUDDY_TABLE_INDEX "CatNameBuddyTable_Index"
  4792. #define SZ_CATNAME_BUDDY_TABLE_INDEX_DEF "+CatNameBuddyTable_CatNameCol\0"
  4793. //---------------------------------------------------------------------------------------
  4794. //
  4795. // _CatDBInitJetDatabaseParams
  4796. //
  4797. //---------------------------------------------------------------------------------------
  4798. typedef struct _DBJETPARAM
  4799. {
  4800. DWORD paramid;
  4801. DWORD lParam;
  4802. char *pszParam;
  4803. } DBJETPARAM;
  4804. DBJETPARAM g_rgJetParams[] = {
  4805. #define JP_LOGPATH 0
  4806. { JET_paramLogFilePath, 0, NULL},
  4807. #define JP_SYSTEMPATH 1
  4808. { JET_paramSystemPath, 0, NULL},
  4809. #define JP_TEMPPATH 2
  4810. { JET_paramTempPath, 0, NULL},
  4811. { JET_paramEventSource, 0, "Catalog Database"},
  4812. { JET_paramMaxVerPages, 1024, NULL},
  4813. #if !defined(_M_IA64) && !defined(_M_AXP64)
  4814. { JET_paramEventLogCache, 32768, NULL},
  4815. #endif
  4816. { JET_paramCircularLog, 1, NULL},
  4817. { JET_paramNoInformationEvent, 1, NULL},
  4818. { JET_paramAccessDeniedRetryPeriod, 1000, NULL}
  4819. };
  4820. #define CDBPARAM (sizeof(g_rgJetParams)/sizeof(g_rgJetParams[0]))
  4821. BOOL
  4822. _CatDBInitJetDatabaseParams(
  4823. JET_INSTANCE *pJetInstance)
  4824. {
  4825. BOOL fRet = TRUE;
  4826. JET_ERR jerr;
  4827. DWORD dw;
  4828. LPSTR pszTempPath = NULL;
  4829. DBJETPARAM const *pjp;
  4830. //
  4831. // Create a temp path for cat db
  4832. //
  4833. if (NULL == (pszTempPath = _CatDBGetCatrootDirA()))
  4834. {
  4835. CATDBSVC_LOGERR_LASTERR()
  4836. goto ErrorGetSystemDirectory;
  4837. }
  4838. //
  4839. // Initialize the Jet Parameters
  4840. //
  4841. g_rgJetParams[JP_LOGPATH].pszParam = pszTempPath;
  4842. g_rgJetParams[JP_SYSTEMPATH].pszParam = pszTempPath;
  4843. g_rgJetParams[JP_TEMPPATH].pszParam = pszTempPath;
  4844. for (pjp = g_rgJetParams; pjp < &g_rgJetParams[CDBPARAM]; pjp++)
  4845. {
  4846. if (_CatDBJET_errFailure(jerr =
  4847. JetSetSystemParameter(
  4848. pJetInstance,
  4849. 0,
  4850. pjp->paramid,
  4851. pjp->lParam,
  4852. pjp->pszParam)))
  4853. {
  4854. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4855. }
  4856. }
  4857. CommonReturn:
  4858. if (pszTempPath != NULL)
  4859. {
  4860. free(pszTempPath);
  4861. }
  4862. return fRet;
  4863. ErrorReturn:
  4864. fRet = FALSE;
  4865. goto CommonReturn;
  4866. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  4867. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorGetSystemDirectory)
  4868. }
  4869. //---------------------------------------------------------------------------------------
  4870. //
  4871. // _CatDBGetColumnIDs
  4872. //
  4873. //---------------------------------------------------------------------------------------
  4874. BOOL
  4875. _CatDBGetColumnIDs(
  4876. PJET_DB_STRUCT pJetDBStruct)
  4877. {
  4878. BOOL fRet = TRUE;
  4879. JET_ERR jerr;
  4880. JET_COLUMNDEF JetColumnDef;
  4881. BOOL fHashCatNameTableOpen = FALSE;
  4882. BOOL fCatNameBuddyTableOpen = FALSE;
  4883. DWORD dwErr = 0;
  4884. //
  4885. // Hash-CatName table and columns
  4886. //
  4887. if (_CatDBJET_errFailure(jerr =
  4888. JetOpenTable(
  4889. pJetDBStruct->JetSesID,
  4890. pJetDBStruct->JetDBID,
  4891. SZ_HASH_CATNAME_TABLE,
  4892. NULL,
  4893. 0,
  4894. 0,
  4895. &(pJetDBStruct->JetHashCatNameTableID))))
  4896. {
  4897. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4898. }
  4899. fHashCatNameTableOpen = TRUE;
  4900. if (_CatDBJET_errFailure(jerr =
  4901. JetGetColumnInfo(
  4902. pJetDBStruct->JetSesID,
  4903. pJetDBStruct->JetDBID,
  4904. SZ_HASH_CATNAME_TABLE,
  4905. SZ_HASH_CATNAME_TABLE_HASHCOL,
  4906. &JetColumnDef,
  4907. sizeof(JetColumnDef),
  4908. JET_ColInfo)))
  4909. {
  4910. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4911. }
  4912. pJetDBStruct->JetHashCatNameTable_HashColumnID = JetColumnDef.columnid;
  4913. if (_CatDBJET_errFailure(jerr =
  4914. JetGetColumnInfo(
  4915. pJetDBStruct->JetSesID,
  4916. pJetDBStruct->JetDBID,
  4917. SZ_HASH_CATNAME_TABLE,
  4918. SZ_HASH_CATNAME_TABLE_CATNAMECOL,
  4919. &JetColumnDef,
  4920. sizeof(JetColumnDef),
  4921. JET_ColInfo)))
  4922. {
  4923. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4924. }
  4925. pJetDBStruct->JetHashCatNameTable_CatNameColumnID = JetColumnDef.columnid;
  4926. //
  4927. // CatNameBuddy table and columns
  4928. //
  4929. if (_CatDBJET_errFailure(jerr =
  4930. JetOpenTable(
  4931. pJetDBStruct->JetSesID,
  4932. pJetDBStruct->JetDBID,
  4933. SZ_CATNAME_BUDDY_TABLE,
  4934. NULL,
  4935. 0,
  4936. 0,
  4937. &(pJetDBStruct->JetCatNameBuddyTableID))))
  4938. {
  4939. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4940. }
  4941. fCatNameBuddyTableOpen = TRUE;
  4942. if (_CatDBJET_errFailure(jerr =
  4943. JetGetColumnInfo(
  4944. pJetDBStruct->JetSesID,
  4945. pJetDBStruct->JetDBID,
  4946. SZ_CATNAME_BUDDY_TABLE,
  4947. SZ_CATNAME_BUDDY_TABLE_CATNAMECOL,
  4948. &JetColumnDef,
  4949. sizeof(JetColumnDef),
  4950. JET_ColInfo)))
  4951. {
  4952. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4953. }
  4954. pJetDBStruct->JetCatNameBuddyTable_CatNameColumnID = JetColumnDef.columnid;
  4955. if (_CatDBJET_errFailure(jerr =
  4956. JetGetColumnInfo(
  4957. pJetDBStruct->JetSesID,
  4958. pJetDBStruct->JetDBID,
  4959. SZ_CATNAME_BUDDY_TABLE,
  4960. SZ_CATNAME_BUDDY_TABLE_BUDDYCOL,
  4961. &JetColumnDef,
  4962. sizeof(JetColumnDef),
  4963. JET_ColInfo)))
  4964. {
  4965. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  4966. }
  4967. pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID = JetColumnDef.columnid;
  4968. CommonReturn:
  4969. return fRet;
  4970. ErrorReturn:
  4971. dwErr = GetLastError();
  4972. if (fHashCatNameTableOpen)
  4973. {
  4974. JetCloseTable(pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID);
  4975. }
  4976. if (fCatNameBuddyTableOpen)
  4977. {
  4978. JetCloseTable(pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID);
  4979. }
  4980. SetLastError(dwErr);
  4981. fRet = FALSE;
  4982. goto CommonReturn;
  4983. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  4984. }
  4985. //---------------------------------------------------------------------------------------
  4986. //
  4987. // _CatDBCreateDBFile
  4988. //
  4989. //---------------------------------------------------------------------------------------
  4990. BOOL
  4991. _CatDBCreateDBFile(
  4992. PJET_DB_STRUCT pJetDBStruct,
  4993. LPSTR pszDBFileName)
  4994. {
  4995. BOOL fRet = TRUE;
  4996. JET_ERR jerr;
  4997. JET_COLUMNDEF JetColumnDef;
  4998. BOOL fDBFileOpen = FALSE;
  4999. BOOL fDBFileCreated = FALSE;
  5000. BOOL fTransactionBegun = FALSE;
  5001. DWORD dwErr = 0;
  5002. JET_DBID LocalJetDBID = 0;
  5003. JET_TABLEID LocalJetHashCatNameTableID = 0;
  5004. JET_COLUMNID LocalJetHashCatNameTable_HashColumnID = 0;
  5005. JET_COLUMNID LocalJetHashCatNameTable_CatNameColumnID = 0;
  5006. JET_TABLEID LocalJetCatNameBuddyTableID = 0;
  5007. JET_COLUMNID LocalJetCatNameBuddyTable_CatNameColumnID = 0;
  5008. JET_COLUMNID LocalJetCatNameBuddyTable_BuddyColumnID = 0;
  5009. //
  5010. // Create the actual db file
  5011. //
  5012. if (_CatDBJET_errFailure(jerr =
  5013. JetCreateDatabase(
  5014. pJetDBStruct->JetSesID,
  5015. pszDBFileName,
  5016. NULL,
  5017. &(LocalJetDBID),
  5018. 0)))
  5019. {
  5020. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5021. }
  5022. fDBFileCreated = TRUE;
  5023. fDBFileOpen = TRUE;
  5024. if (_CatDBJET_errFailure(jerr =
  5025. JetCloseDatabase(
  5026. pJetDBStruct->JetSesID,
  5027. LocalJetDBID,
  5028. 0)))
  5029. {
  5030. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5031. }
  5032. fDBFileOpen = FALSE;
  5033. if (_CatDBJET_errFailure(jerr =
  5034. JetOpenDatabase(
  5035. pJetDBStruct->JetSesID,
  5036. pszDBFileName,
  5037. NULL,
  5038. &(LocalJetDBID),
  5039. 0)))
  5040. {
  5041. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5042. }
  5043. fDBFileOpen = TRUE;
  5044. //
  5045. // Add the whole schema to the db file (tables, columns, indexes)
  5046. //
  5047. if (_CatDBJET_errFailure(jerr =
  5048. JetBeginTransaction(pJetDBStruct->JetSesID)))
  5049. {
  5050. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5051. }
  5052. fTransactionBegun = TRUE;
  5053. //
  5054. // Create the hash-catname table, columns, and indexes
  5055. //
  5056. if (_CatDBJET_errFailure(jerr =
  5057. JetCreateTable(
  5058. pJetDBStruct->JetSesID,
  5059. LocalJetDBID,
  5060. SZ_HASH_CATNAME_TABLE,
  5061. 4,
  5062. 100,
  5063. &(LocalJetHashCatNameTableID))))
  5064. {
  5065. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5066. }
  5067. if (_CatDBJET_errFailure(jerr =
  5068. JetCloseTable(
  5069. pJetDBStruct->JetSesID,
  5070. LocalJetHashCatNameTableID)))
  5071. {
  5072. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5073. }
  5074. if (_CatDBJET_errFailure(jerr =
  5075. JetOpenTable(
  5076. pJetDBStruct->JetSesID,
  5077. LocalJetDBID,
  5078. SZ_HASH_CATNAME_TABLE,
  5079. NULL,
  5080. 0,
  5081. 0,
  5082. &(LocalJetHashCatNameTableID))))
  5083. {
  5084. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5085. }
  5086. // Hash column
  5087. memset(&JetColumnDef, 0, sizeof(JetColumnDef));
  5088. JetColumnDef.cbStruct = sizeof(JetColumnDef);
  5089. JetColumnDef.langid = 0x409;
  5090. JetColumnDef.wCountry = 1;
  5091. JetColumnDef.coltyp = JET_coltypBinary;
  5092. JetColumnDef.grbit = JET_bitColumnNotNULL;
  5093. if (_CatDBJET_errFailure(jerr =
  5094. JetAddColumn(
  5095. pJetDBStruct->JetSesID,
  5096. LocalJetHashCatNameTableID,
  5097. SZ_HASH_CATNAME_TABLE_HASHCOL,
  5098. &JetColumnDef,
  5099. NULL,
  5100. 0,
  5101. &(LocalJetHashCatNameTable_HashColumnID))))
  5102. {
  5103. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5104. }
  5105. // CatName column
  5106. memset(&JetColumnDef, 0, sizeof(JetColumnDef));
  5107. JetColumnDef.cbStruct = sizeof(JetColumnDef);
  5108. JetColumnDef.cp = 1200; // unicode (1200) instead of Ascii (1252)
  5109. JetColumnDef.langid = 0x409;
  5110. JetColumnDef.wCountry = 1;
  5111. JetColumnDef.coltyp = JET_coltypText;
  5112. JetColumnDef.cbMax = 255;
  5113. JetColumnDef.grbit = JET_bitColumnMultiValued | JET_bitColumnTagged;
  5114. if (_CatDBJET_errFailure(jerr =
  5115. JetAddColumn(
  5116. pJetDBStruct->JetSesID,
  5117. LocalJetHashCatNameTableID,
  5118. SZ_HASH_CATNAME_TABLE_CATNAMECOL,
  5119. &JetColumnDef,
  5120. NULL,
  5121. 0,
  5122. &(LocalJetHashCatNameTable_CatNameColumnID))))
  5123. {
  5124. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5125. }
  5126. // Hash-CatName table index
  5127. if (_CatDBJET_errFailure(jerr =
  5128. JetCreateIndex(
  5129. pJetDBStruct->JetSesID,
  5130. LocalJetHashCatNameTableID,
  5131. SZ_HASH_CATNAME_TABLE_INDEX,
  5132. JET_bitIndexPrimary,
  5133. SZ_HASH_CATNAME_TABLE_INDEX_DEF,
  5134. strlen(SZ_HASH_CATNAME_TABLE_INDEX_DEF) + 2,
  5135. 80)))
  5136. {
  5137. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5138. }
  5139. //
  5140. // Create the CatName-Buddy table, columns, and indexes
  5141. //
  5142. if (_CatDBJET_errFailure(jerr =
  5143. JetCreateTable(
  5144. pJetDBStruct->JetSesID,
  5145. LocalJetDBID,
  5146. SZ_CATNAME_BUDDY_TABLE,
  5147. 4,
  5148. 100,
  5149. &(LocalJetCatNameBuddyTableID))))
  5150. {
  5151. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5152. }
  5153. if (_CatDBJET_errFailure(jerr =
  5154. JetCloseTable(
  5155. pJetDBStruct->JetSesID,
  5156. LocalJetCatNameBuddyTableID)))
  5157. {
  5158. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5159. }
  5160. if (_CatDBJET_errFailure(jerr =
  5161. JetOpenTable(
  5162. pJetDBStruct->JetSesID,
  5163. LocalJetDBID,
  5164. SZ_CATNAME_BUDDY_TABLE,
  5165. NULL,
  5166. 0,
  5167. 0,
  5168. &(LocalJetCatNameBuddyTableID))))
  5169. {
  5170. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5171. }
  5172. // CatName column
  5173. memset(&JetColumnDef, 0, sizeof(JetColumnDef));
  5174. JetColumnDef.cbStruct = sizeof(JetColumnDef);
  5175. JetColumnDef.cp = 1200; // unicode (1200) instead of Ascii (1252)
  5176. JetColumnDef.langid = 0x409;
  5177. JetColumnDef.wCountry = 1;
  5178. JetColumnDef.coltyp = JET_coltypText;
  5179. JetColumnDef.cbMax = 255;
  5180. JetColumnDef.grbit = JET_bitColumnNotNULL;
  5181. if (_CatDBJET_errFailure(jerr =
  5182. JetAddColumn(
  5183. pJetDBStruct->JetSesID,
  5184. LocalJetCatNameBuddyTableID,
  5185. SZ_CATNAME_BUDDY_TABLE_CATNAMECOL,
  5186. &JetColumnDef,
  5187. NULL,
  5188. 0,
  5189. &(LocalJetCatNameBuddyTable_CatNameColumnID))))
  5190. {
  5191. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5192. }
  5193. // Buddy column
  5194. memset(&JetColumnDef, 0, sizeof(JetColumnDef));
  5195. JetColumnDef.cbStruct = sizeof(JetColumnDef);
  5196. JetColumnDef.cp = 1200; // unicode (1200) instead of Ascii (1252)
  5197. JetColumnDef.langid = 0x409;
  5198. JetColumnDef.wCountry = 1;
  5199. JetColumnDef.coltyp = JET_coltypText;
  5200. JetColumnDef.cbMax = 255;
  5201. JetColumnDef.grbit = JET_bitColumnMultiValued | JET_bitColumnTagged;
  5202. if (_CatDBJET_errFailure(jerr =
  5203. JetAddColumn(
  5204. pJetDBStruct->JetSesID,
  5205. LocalJetCatNameBuddyTableID,
  5206. SZ_CATNAME_BUDDY_TABLE_BUDDYCOL,
  5207. &JetColumnDef,
  5208. NULL,
  5209. 0,
  5210. &(LocalJetCatNameBuddyTable_BuddyColumnID))))
  5211. {
  5212. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5213. }
  5214. // CatName-Buddy table index
  5215. if (_CatDBJET_errFailure(jerr =
  5216. JetCreateIndex(
  5217. pJetDBStruct->JetSesID,
  5218. LocalJetCatNameBuddyTableID,
  5219. SZ_CATNAME_BUDDY_TABLE_INDEX,
  5220. JET_bitIndexPrimary,
  5221. SZ_CATNAME_BUDDY_TABLE_INDEX_DEF,
  5222. strlen(SZ_CATNAME_BUDDY_TABLE_INDEX_DEF) + 2,
  5223. 80)))
  5224. {
  5225. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5226. }
  5227. //
  5228. // Now that all the schema has been successfully added, COMMIT
  5229. //
  5230. if (_CatDBJET_errFailure(jerr =
  5231. JetCommitTransaction(
  5232. pJetDBStruct->JetSesID,
  5233. 0)))
  5234. {
  5235. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5236. }
  5237. if (_CatDBJET_errFailure(jerr =
  5238. JetCloseDatabase(
  5239. pJetDBStruct->JetSesID,
  5240. LocalJetDBID,
  5241. 0)))
  5242. {
  5243. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5244. }
  5245. CommonReturn:
  5246. return fRet;
  5247. ErrorReturn:
  5248. dwErr = GetLastError();
  5249. if (fTransactionBegun)
  5250. {
  5251. JetRollback(pJetDBStruct->JetSesID, 0);
  5252. }
  5253. if (fDBFileOpen)
  5254. {
  5255. JetCloseDatabase(
  5256. pJetDBStruct->JetSesID,
  5257. LocalJetDBID,
  5258. 0);
  5259. }
  5260. if (fDBFileCreated)
  5261. {
  5262. DeleteFileA(pszDBFileName);
  5263. }
  5264. SetLastError(dwErr);
  5265. fRet = FALSE;
  5266. goto CommonReturn;
  5267. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  5268. }
  5269. //---------------------------------------------------------------------------------------
  5270. //
  5271. // _CatDBAttachAndOpenDatabase
  5272. //
  5273. //---------------------------------------------------------------------------------------
  5274. BOOL
  5275. _CatDBAttachAndOpenDatabase(
  5276. JET_DB_STRUCT *pJetDBStruct,
  5277. BOOL fReadOnly)
  5278. {
  5279. BOOL fRet = TRUE;
  5280. JET_ERR jerr;
  5281. BOOL fJetDBFileOpen = FALSE;
  5282. DWORD dwErr = 0;
  5283. //
  5284. // Try to attach the existing database, if it doesn't already exist,
  5285. // then create it
  5286. //
  5287. jerr = JetAttachDatabase(
  5288. pJetDBStruct->JetSesID,
  5289. pJetDBStruct->pszDBFileName,
  5290. 0); //fReadOnly ? JET_bitDbReadOnly : 0);
  5291. if (jerr == JET_errFileNotFound)
  5292. {
  5293. //
  5294. // The DB file doesn't exist yet, so create it
  5295. //
  5296. if (!_CatDBCreateDBFile(
  5297. pJetDBStruct,
  5298. pJetDBStruct->pszDBFileName))
  5299. {
  5300. CATDBSVC_LOGERR_LASTERR()
  5301. goto ErrorReturn;
  5302. }
  5303. }
  5304. else if (_CatDBJET_errFailure(jerr))
  5305. {
  5306. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5307. }
  5308. if (_CatDBJET_errFailure(jerr =
  5309. JetOpenDatabase(
  5310. pJetDBStruct->JetSesID,
  5311. pJetDBStruct->pszDBFileName,
  5312. NULL,
  5313. &(pJetDBStruct->JetDBID),
  5314. 0)))
  5315. {
  5316. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5317. }
  5318. fJetDBFileOpen = TRUE;
  5319. if (!_CatDBGetColumnIDs(pJetDBStruct))
  5320. {
  5321. CATDBSVC_LOGERR_LASTERR()
  5322. goto ErrorReturn;
  5323. }
  5324. //
  5325. // Set the current indexes for both tables so all seeks work
  5326. //
  5327. if (_CatDBJET_errFailure(jerr =
  5328. JetSetCurrentIndex(
  5329. pJetDBStruct->JetSesID,
  5330. pJetDBStruct->JetHashCatNameTableID,
  5331. NULL))) // NULL == primary index
  5332. {
  5333. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5334. }
  5335. if (_CatDBJET_errFailure(jerr =
  5336. JetSetCurrentIndex(
  5337. pJetDBStruct->JetSesID,
  5338. pJetDBStruct->JetCatNameBuddyTableID,
  5339. NULL))) // NULL == primary index
  5340. {
  5341. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5342. }
  5343. CommonReturn:
  5344. return fRet;
  5345. ErrorReturn:
  5346. dwErr = GetLastError();
  5347. if (fJetDBFileOpen)
  5348. {
  5349. JetCloseDatabase(pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, 0);
  5350. }
  5351. SetLastError(dwErr);
  5352. fRet = FALSE;
  5353. goto CommonReturn;
  5354. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  5355. }
  5356. //---------------------------------------------------------------------------------------
  5357. //
  5358. // _CatDBCloseDatabaseFile
  5359. //
  5360. //---------------------------------------------------------------------------------------
  5361. BOOL
  5362. _CatDBCloseDatabaseFile(
  5363. PJET_DB_STRUCT pJetDBStruct)
  5364. {
  5365. BOOL fRet = TRUE;
  5366. JET_ERR jerr;
  5367. if (_CatDBJET_errFailure(jerr =
  5368. JetCloseTable(
  5369. pJetDBStruct->JetSesID,
  5370. pJetDBStruct->JetHashCatNameTableID)))
  5371. {
  5372. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5373. }
  5374. if (_CatDBJET_errFailure(jerr =
  5375. JetCloseTable(
  5376. pJetDBStruct->JetSesID,
  5377. pJetDBStruct->JetCatNameBuddyTableID)))
  5378. {
  5379. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5380. }
  5381. if (_CatDBJET_errFailure(jerr =
  5382. JetCloseDatabase(
  5383. pJetDBStruct->JetSesID,
  5384. pJetDBStruct->JetDBID,
  5385. 0)))
  5386. {
  5387. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5388. }
  5389. if (_CatDBJET_errFailure(jerr =
  5390. JetDetachDatabase(
  5391. pJetDBStruct->JetSesID,
  5392. pJetDBStruct->pszDBFileName)))
  5393. {
  5394. //
  5395. // Only log the error it it isn't a JET_errDatabaseInUse error
  5396. //
  5397. if (jerr != JET_errDatabaseInUse)
  5398. {
  5399. CATDBSVC_LOGERR(_CatDBMapJetError(jerr))
  5400. }
  5401. }
  5402. if (_CatDBJET_errFailure(jerr =
  5403. JetEndSession(
  5404. pJetDBStruct->JetSesID,
  5405. 0)))
  5406. {
  5407. CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase)
  5408. }
  5409. CommonReturn:
  5410. return fRet;
  5411. ErrorReturn:
  5412. fRet = FALSE;
  5413. goto CommonReturn;
  5414. TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase)
  5415. }
  5416. //---------------------------------------------------------------------------------------
  5417. //
  5418. // _CatDBCatalogFileAlreadyInstalled
  5419. //
  5420. //---------------------------------------------------------------------------------------
  5421. BOOL
  5422. _CatDBCatalogFileAlreadyInstalled(
  5423. LPCWSTR pwszCatalogToBeAdded,
  5424. LPCWSTR pwszExistingCatalog)
  5425. {
  5426. BOOL fRet = TRUE;
  5427. HANDLE h1 = NULL;
  5428. HANDLE h2 = NULL;
  5429. BYTE rgbHash1[20];
  5430. BYTE rgbHash2[20];
  5431. DWORD cbHash1 = 20;
  5432. DWORD cbHash2 = 20;
  5433. //
  5434. // Open both files
  5435. //
  5436. h1 = CreateFileW(
  5437. pwszCatalogToBeAdded,
  5438. GENERIC_READ,
  5439. FILE_SHARE_READ | FILE_SHARE_WRITE,
  5440. NULL,
  5441. OPEN_EXISTING,
  5442. FILE_ATTRIBUTE_NORMAL,
  5443. NULL); // hTemplateFile
  5444. if (h1 == NULL)
  5445. {
  5446. CATDBSVC_LOGERR_LASTERR()
  5447. goto ErrorReturn;
  5448. }
  5449. h2 = CreateFileW(
  5450. pwszExistingCatalog,
  5451. GENERIC_READ,
  5452. FILE_SHARE_READ | FILE_SHARE_WRITE,
  5453. NULL,
  5454. OPEN_EXISTING,
  5455. FILE_ATTRIBUTE_NORMAL,
  5456. NULL); // hTemplateFile
  5457. if (h1 == NULL)
  5458. {
  5459. CATDBSVC_LOGERR_LASTERR()
  5460. goto ErrorReturn;
  5461. }
  5462. //
  5463. // Get the hash for each file
  5464. //
  5465. if (!CryptCATAdminCalcHashFromFileHandle(
  5466. h1,
  5467. &cbHash1,
  5468. rgbHash1,
  5469. 0))
  5470. {
  5471. CATDBSVC_LOGERR_LASTERR()
  5472. goto ErrorReturn;
  5473. }
  5474. if (!CryptCATAdminCalcHashFromFileHandle(
  5475. h2,
  5476. &cbHash2,
  5477. rgbHash2,
  5478. 0))
  5479. {
  5480. CATDBSVC_LOGERR_LASTERR()
  5481. goto ErrorReturn;
  5482. }
  5483. //
  5484. // Compare the hashes to see if they are the same
  5485. //
  5486. if (memcmp(rgbHash1, rgbHash2, 20) == 0)
  5487. {
  5488. fRet = TRUE;
  5489. }
  5490. Return:
  5491. if (h1 != NULL)
  5492. {
  5493. CloseHandle(h1);
  5494. }
  5495. if (h2 != NULL)
  5496. {
  5497. CloseHandle(h2);
  5498. }
  5499. return fRet;
  5500. ErrorReturn:
  5501. fRet = FALSE;
  5502. goto Return;
  5503. }
  5504. //---------------------------------------------------------------------------------------
  5505. //
  5506. // _CatDBJET_errFailure
  5507. //
  5508. //---------------------------------------------------------------------------------------
  5509. BOOL
  5510. _CatDBJET_errFailure(
  5511. JET_ERR jerr)
  5512. {
  5513. if (jerr == JET_errSuccess)
  5514. {
  5515. return FALSE;
  5516. }
  5517. else if (jerr & 0x80000000)
  5518. {
  5519. //
  5520. // Jet errors are negative numbers, jet warnings are positive
  5521. //
  5522. return TRUE;
  5523. }
  5524. else
  5525. {
  5526. CATDBSVC_LOGWARN(_CatDBMapJetError(jerr))
  5527. return FALSE;
  5528. }
  5529. }
  5530. //---------------------------------------------------------------------------------------
  5531. //
  5532. // _CatDBMapJetError
  5533. //
  5534. //---------------------------------------------------------------------------------------
  5535. DWORD
  5536. _CatDBMapJetError(JET_ERR jerr)
  5537. {
  5538. // FIX FIX
  5539. return jerr;//ERROR_DATABASE_FAILURE;
  5540. }