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

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