Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1107 lines
30 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: dbcomp.cpp
  7. //
  8. // Contents: Hash Database Compactor
  9. //
  10. // History: 9-8-1998 kirtd Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <global.hxx>
  14. //+---------------------------------------------------------------------------
  15. //
  16. // Member: CHashDbCompactor::CHashDbCompactor, public
  17. //
  18. // Synopsis: Constructor
  19. //
  20. //----------------------------------------------------------------------------
  21. CHashDbCompactor::CHashDbCompactor ()
  22. {
  23. m_hDbLock = NULL;
  24. m_pwszDbDirectory = NULL;
  25. m_cUniqueCatalogs = 0;
  26. m_cAllocatedUniqueCatalogs = 0;
  27. m_aUniqueCatalogs = NULL;
  28. m_iLastUniqueCatalogFoundByName = 0;
  29. m_pwszTempKeyPath[0] = L'\0';
  30. m_pwszTempDataPath[0] = L'\0';
  31. }
  32. //+---------------------------------------------------------------------------
  33. //
  34. // Member: CHashDbCompactor::~CHashDbCompactor, public
  35. //
  36. // Synopsis: Destructor
  37. //
  38. //----------------------------------------------------------------------------
  39. CHashDbCompactor::~CHashDbCompactor ()
  40. {
  41. if ( m_hDbLock != NULL )
  42. {
  43. CloseHandle( m_hDbLock );
  44. }
  45. if ( m_pwszTempKeyPath[ 0 ] != L'\0' )
  46. {
  47. DeleteFileU( m_pwszTempKeyPath );
  48. }
  49. if ( m_pwszTempDataPath[ 0 ] != L'\0' )
  50. {
  51. DeleteFileU( m_pwszTempDataPath );
  52. }
  53. delete m_pwszDbDirectory;
  54. delete m_aUniqueCatalogs;
  55. }
  56. //+---------------------------------------------------------------------------
  57. //
  58. // Member: CHashDbCompactor::Initialize, public
  59. //
  60. // Synopsis: initialize the compactor
  61. //
  62. //----------------------------------------------------------------------------
  63. BOOL
  64. CHashDbCompactor::Initialize (
  65. IN LPCWSTR pwszDbLock,
  66. IN LPCWSTR pwszDbDirectory
  67. )
  68. {
  69. if ( ( m_hDbLock = CreateMutexU( NULL, FALSE, pwszDbLock ) ) == NULL )
  70. {
  71. return( FALSE );
  72. }
  73. m_pwszDbDirectory = new WCHAR [ wcslen( pwszDbDirectory ) + 1 ];
  74. if ( m_pwszDbDirectory != NULL )
  75. {
  76. wcscpy( m_pwszDbDirectory, pwszDbDirectory );
  77. }
  78. else
  79. {
  80. SetLastError( E_OUTOFMEMORY );
  81. return( FALSE );
  82. }
  83. if ( GrowUniqueCatalogs( INITIAL_UNIQUE_CATALOGS ) == FALSE )
  84. {
  85. return( FALSE );
  86. }
  87. assert( m_aUniqueCatalogs != NULL );
  88. assert( m_cAllocatedUniqueCatalogs == INITIAL_UNIQUE_CATALOGS );
  89. if ( ( GetTempFileNameU(
  90. pwszDbDirectory,
  91. L"",
  92. 0,
  93. m_pwszTempKeyPath
  94. ) == FALSE ) ||
  95. ( GetTempFileNameU(
  96. pwszDbDirectory,
  97. L"",
  98. 0,
  99. m_pwszTempDataPath
  100. ) == FALSE ) )
  101. {
  102. return( FALSE );
  103. }
  104. return( TRUE );
  105. }
  106. //+---------------------------------------------------------------------------
  107. //
  108. // Member: CHashDbCompactor::LockDatabase, public
  109. //
  110. // Synopsis: lock the database
  111. //
  112. //----------------------------------------------------------------------------
  113. VOID
  114. CHashDbCompactor::LockDatabase ()
  115. {
  116. WaitForSingleObject( m_hDbLock, INFINITE );
  117. }
  118. //+---------------------------------------------------------------------------
  119. //
  120. // Member: CHashDbCompactor::UnlockDatabase, public
  121. //
  122. // Synopsis: unlock the database
  123. //
  124. //----------------------------------------------------------------------------
  125. VOID
  126. CHashDbCompactor::UnlockDatabase ()
  127. {
  128. ReleaseMutex( m_hDbLock );
  129. }
  130. //+---------------------------------------------------------------------------
  131. //
  132. // Member: CHashDbCompactor::MapDatabase, public
  133. //
  134. // Synopsis: map the database
  135. //
  136. //----------------------------------------------------------------------------
  137. BOOL
  138. CHashDbCompactor::MapDatabase (
  139. IN LPCWSTR pwszDbName,
  140. OUT PCRYPT_DATA_BLOB pKey,
  141. OUT LPWSTR* ppwszKeyPath,
  142. OUT PCRYPT_DATA_BLOB pData,
  143. OUT LPWSTR* ppwszDataPath
  144. )
  145. {
  146. BOOL fResult = TRUE;
  147. LPWSTR pwszKeyDbPath = NULL;
  148. LPWSTR pwszDataDbPath = NULL;
  149. DWORD cwDirectory = 0;
  150. DWORD cwName = 0;
  151. HANDLE hKeyFile = INVALID_HANDLE_VALUE;
  152. HANDLE hDataFile = INVALID_HANDLE_VALUE;
  153. HANDLE hMappedKeyFile = NULL;
  154. HANDLE hMappedDataFile = NULL;
  155. LPBYTE pbKey = NULL;
  156. LPBYTE pbData = NULL;
  157. DWORD cwKeyExt = 0;
  158. DWORD cwDataExt = 0;
  159. DWORD cbKeyFileSize = 0;
  160. DWORD cbDataFileSize = 0;
  161. cwDirectory = wcslen( m_pwszDbDirectory );
  162. cwName = wcslen( pwszDbName );
  163. cwKeyExt = wcslen( DB_KEY_EXT );
  164. cwDataExt = wcslen( DB_DATA_EXT );
  165. pwszKeyDbPath = new WCHAR [ cwDirectory + cwName + cwKeyExt + 2 ];
  166. pwszDataDbPath = new WCHAR [ cwDirectory + cwName + cwDataExt + 2 ];
  167. if ( ( pwszKeyDbPath != NULL ) && ( pwszDataDbPath != NULL ) )
  168. {
  169. wcscpy( pwszKeyDbPath, m_pwszDbDirectory );
  170. wcscat( pwszKeyDbPath, L"\\" );
  171. wcscat( pwszKeyDbPath, pwszDbName );
  172. wcscpy( pwszDataDbPath, pwszKeyDbPath );
  173. wcscat( pwszKeyDbPath, DB_KEY_EXT );
  174. wcscat( pwszDataDbPath, DB_DATA_EXT );
  175. }
  176. else
  177. {
  178. SetLastError( E_OUTOFMEMORY );
  179. fResult = FALSE;
  180. }
  181. if ( fResult == TRUE )
  182. {
  183. DWORD dwErr = 0;
  184. hKeyFile = CreateFileU(
  185. pwszKeyDbPath,
  186. GENERIC_READ,
  187. FILE_SHARE_READ,
  188. NULL,
  189. OPEN_EXISTING,
  190. FILE_ATTRIBUTE_NORMAL,
  191. NULL
  192. );
  193. if (hKeyFile == INVALID_HANDLE_VALUE)
  194. {
  195. dwErr = GetLastError();
  196. }
  197. hDataFile = CreateFileU(
  198. pwszDataDbPath,
  199. GENERIC_READ,
  200. FILE_SHARE_READ,
  201. NULL,
  202. OPEN_EXISTING,
  203. FILE_ATTRIBUTE_NORMAL,
  204. NULL
  205. );
  206. if (hDataFile == INVALID_HANDLE_VALUE)
  207. {
  208. dwErr = GetLastError();
  209. }
  210. if ( ( hKeyFile != INVALID_HANDLE_VALUE ) &&
  211. ( hDataFile != INVALID_HANDLE_VALUE ) )
  212. {
  213. cbKeyFileSize = GetFileSize( hKeyFile, NULL );
  214. cbDataFileSize = GetFileSize( hDataFile, NULL );
  215. if ( cbKeyFileSize > 0 )
  216. {
  217. hMappedKeyFile = CreateFileMapping(
  218. hKeyFile,
  219. NULL,
  220. PAGE_READONLY,
  221. 0,
  222. 0,
  223. NULL
  224. );
  225. }
  226. if ( cbDataFileSize > 0 )
  227. {
  228. hMappedDataFile = CreateFileMapping(
  229. hDataFile,
  230. NULL,
  231. PAGE_READONLY,
  232. 0,
  233. 0,
  234. NULL
  235. );
  236. }
  237. }
  238. if ( hMappedKeyFile != NULL )
  239. {
  240. pbKey = (LPBYTE)MapViewOfFile(
  241. hMappedKeyFile,
  242. FILE_MAP_READ,
  243. 0,
  244. 0,
  245. 0
  246. );
  247. }
  248. if ( hMappedDataFile != NULL )
  249. {
  250. pbData = (LPBYTE)MapViewOfFile(
  251. hMappedDataFile,
  252. FILE_MAP_READ,
  253. 0,
  254. 0,
  255. 0
  256. );
  257. }
  258. if ( ( ( pbKey == NULL ) && ( cbKeyFileSize != 0 ) ) ||
  259. ( ( pbData == NULL ) && ( cbDataFileSize != 0 ) ) )
  260. {
  261. fResult = FALSE;
  262. }
  263. }
  264. if ( fResult == TRUE )
  265. {
  266. pKey->cbData = cbKeyFileSize;
  267. pKey->pbData = pbKey;
  268. *ppwszKeyPath = pwszKeyDbPath;
  269. pData->cbData = cbDataFileSize;
  270. pData->pbData = pbData;
  271. *ppwszDataPath = pwszDataDbPath;
  272. }
  273. else
  274. {
  275. delete pwszKeyDbPath;
  276. delete pwszDataDbPath;
  277. }
  278. if ( hKeyFile != INVALID_HANDLE_VALUE )
  279. {
  280. CloseHandle( hKeyFile );
  281. }
  282. if ( hDataFile != INVALID_HANDLE_VALUE )
  283. {
  284. CloseHandle( hDataFile );
  285. }
  286. if ( hMappedKeyFile != NULL )
  287. {
  288. CloseHandle( hMappedKeyFile );
  289. }
  290. if ( hMappedDataFile != NULL )
  291. {
  292. CloseHandle( hMappedDataFile );
  293. }
  294. return( fResult );
  295. }
  296. //+---------------------------------------------------------------------------
  297. //
  298. // Member: CHashDbCompactor::UnmapDatabase, public
  299. //
  300. // Synopsis: unmap the database
  301. //
  302. //----------------------------------------------------------------------------
  303. VOID
  304. CHashDbCompactor::UnmapDatabase (
  305. IN PCRYPT_DATA_BLOB pKey,
  306. IN PCRYPT_DATA_BLOB pData
  307. )
  308. {
  309. FlushCompactionAnalysis();
  310. if ( pKey->pbData != NULL )
  311. {
  312. UnmapViewOfFile( pKey->pbData );
  313. }
  314. if ( pData->pbData != NULL )
  315. {
  316. UnmapViewOfFile( pData->pbData );
  317. }
  318. }
  319. //+---------------------------------------------------------------------------
  320. //
  321. // Member: CHashDbCompactor::AnalyzeDataForCompaction, public
  322. //
  323. // Synopsis: analyze the database data for compaction
  324. //
  325. //----------------------------------------------------------------------------
  326. BOOL
  327. CHashDbCompactor::AnalyzeDataForCompaction (
  328. IN PCRYPT_DATA_BLOB pData,
  329. IN OPTIONAL LPCSTR pszUnwantedCatalog
  330. )
  331. {
  332. BOOL fResult = TRUE;
  333. HashMastRec* pHashMastRecord;
  334. DWORD cbToNextRecord;
  335. DWORD cRecord;
  336. DWORD cCount;
  337. PUNIQUE_CATALOG pUniqueCatalog;
  338. if ( m_cUniqueCatalogs > 0 )
  339. {
  340. if ( FlushCompactionAnalysis() == FALSE )
  341. {
  342. return( FALSE );
  343. }
  344. }
  345. pHashMastRecord = (HashMastRec *)(
  346. pData->pbData + BFILE_HEADERSIZE + sizeof( DWORD )
  347. );
  348. cbToNextRecord = sizeof( HashMastRec ) + sizeof( DWORD );
  349. if ( pData->cbData < BFILE_HEADERSIZE )
  350. {
  351. cRecord = 0;
  352. }
  353. else
  354. {
  355. cRecord = ( pData->cbData - BFILE_HEADERSIZE ) / cbToNextRecord;
  356. }
  357. for ( cCount = 0; ( fResult == TRUE ) && ( cCount < cRecord ); cCount++ )
  358. {
  359. if ( ( pszUnwantedCatalog == NULL ) ||
  360. ( _strnicmp(
  361. pHashMastRecord->CatName,
  362. pszUnwantedCatalog,
  363. MAX_PATH
  364. ) != 0 ) )
  365. {
  366. pUniqueCatalog = FindUniqueCatalogByName(
  367. pHashMastRecord->CatName
  368. );
  369. if ( ( pUniqueCatalog == NULL ) &&
  370. ( CatalogFileExists(
  371. pHashMastRecord->CatName,
  372. MAX_PATH
  373. ) == TRUE ) )
  374. {
  375. fResult = AddUniqueCatalog( pHashMastRecord );
  376. }
  377. }
  378. pHashMastRecord = (HashMastRec *)(
  379. (LPBYTE)pHashMastRecord + cbToNextRecord
  380. );
  381. }
  382. return( fResult );
  383. }
  384. //+---------------------------------------------------------------------------
  385. //
  386. // Member: CHashDbCompactor::FlushCompactionAnalysis, public
  387. //
  388. // Synopsis: flush the last compaction analysis done
  389. //
  390. //----------------------------------------------------------------------------
  391. BOOL
  392. CHashDbCompactor::FlushCompactionAnalysis ()
  393. {
  394. DWORD cAllocatedUniqueCatalogs;
  395. DWORD cUniqueCatalogs;
  396. PUNIQUE_CATALOG aUniqueCatalogs;
  397. if ( m_cAllocatedUniqueCatalogs == INITIAL_UNIQUE_CATALOGS )
  398. {
  399. m_cUniqueCatalogs = 0;
  400. m_iLastUniqueCatalogFoundByName = 0;
  401. return( TRUE );
  402. }
  403. aUniqueCatalogs = m_aUniqueCatalogs;
  404. cUniqueCatalogs = m_cUniqueCatalogs;
  405. cAllocatedUniqueCatalogs = m_cAllocatedUniqueCatalogs;
  406. m_aUniqueCatalogs = NULL;
  407. m_cUniqueCatalogs = 0;
  408. m_cAllocatedUniqueCatalogs = 0;
  409. if ( GrowUniqueCatalogs( INITIAL_UNIQUE_CATALOGS ) == FALSE )
  410. {
  411. m_aUniqueCatalogs = aUniqueCatalogs;
  412. m_cUniqueCatalogs = cUniqueCatalogs;
  413. m_cAllocatedUniqueCatalogs = cAllocatedUniqueCatalogs;
  414. return( FALSE );
  415. }
  416. delete aUniqueCatalogs;
  417. m_iLastUniqueCatalogFoundByName = 0;
  418. return( TRUE );
  419. }
  420. //+---------------------------------------------------------------------------
  421. //
  422. // Member: CHashDbCompactor::WriteCompactedDatabase, public
  423. //
  424. // Synopsis: write the compacted database
  425. //
  426. //----------------------------------------------------------------------------
  427. BOOL
  428. CHashDbCompactor::WriteCompactedDatabase (
  429. IN PCRYPT_DATA_BLOB pKey,
  430. IN PCRYPT_DATA_BLOB pData,
  431. IN OPTIONAL LPCSTR pszUnwantedCatalog
  432. )
  433. {
  434. BOOL fResult = FALSE;
  435. HANDLE hFile;
  436. HANDLE hDataFile;
  437. HANDLE hMap;
  438. DWORD cCount;
  439. DWORD cbSize;
  440. LPBYTE pbDataFile = NULL;
  441. LPBYTE pbFile = NULL;
  442. HashMastRec* pHashMastRecord;
  443. PUNIQUE_CATALOG pUniqueCatalog;
  444. LPDWORD pdw;
  445. DWORD RecordId;
  446. DWORD cKey;
  447. LPBYTE pbKey;
  448. LPBYTE pb;
  449. BFILE_HEADER* pHeader = NULL;
  450. hDataFile = CreateFileU(
  451. m_pwszTempDataPath,
  452. GENERIC_READ | GENERIC_WRITE,
  453. 0,
  454. NULL,
  455. CREATE_ALWAYS,
  456. FILE_ATTRIBUTE_NORMAL,
  457. NULL
  458. );
  459. if ( hDataFile == INVALID_HANDLE_VALUE )
  460. {
  461. return( FALSE );
  462. }
  463. cbSize = ( sizeof( DWORD ) + sizeof( HashMastRec ) ) * m_cUniqueCatalogs;
  464. cbSize += BFILE_HEADERSIZE;
  465. if ( SetFilePointer( hDataFile, cbSize, NULL, FILE_BEGIN ) != 0xFFFFFFFF )
  466. {
  467. fResult = SetEndOfFile( hDataFile );
  468. }
  469. if ( fResult == TRUE )
  470. {
  471. if ( ( hMap = CreateFileMapping(
  472. hDataFile,
  473. NULL,
  474. PAGE_READWRITE,
  475. 0,
  476. 0,
  477. NULL
  478. ) ) != NULL )
  479. {
  480. pbDataFile = (LPBYTE)MapViewOfFile( hMap, FILE_MAP_WRITE, 0, 0, 0 );
  481. CloseHandle( hMap );
  482. }
  483. if ( pbDataFile != NULL )
  484. {
  485. memcpy( pbDataFile, BFILE_SIG, BFILE_SIZEOFSIG );
  486. pHeader = (BFILE_HEADER *)( pbDataFile + BFILE_SIZEOFSIG );
  487. memset( pHeader, 0, sizeof( BFILE_HEADER ) );
  488. pHeader->sVersion = BFILE_VERSION_1;
  489. pHeader->sIntVersion = CATDB_VERSION_1;
  490. pHeader->cbKey = KEY_SIZE;
  491. pHeader->cbData = sizeof( HashMastRec );
  492. }
  493. else
  494. {
  495. fResult = FALSE;
  496. }
  497. }
  498. pdw = (LPDWORD)( pbDataFile + BFILE_HEADERSIZE );
  499. pHashMastRecord = (HashMastRec *)( (LPBYTE)pdw + sizeof( DWORD ) );
  500. for ( cCount = 0;
  501. ( cCount < m_cUniqueCatalogs ) && ( fResult == TRUE );
  502. cCount++ )
  503. {
  504. RecordId = cCount + 1;
  505. memcpy( pdw, &RecordId, sizeof( DWORD ) );
  506. memcpy(
  507. pHashMastRecord,
  508. &m_aUniqueCatalogs[ cCount ].HashDbRecord,
  509. sizeof( HashMastRec )
  510. );
  511. pdw = (LPDWORD)(
  512. (LPBYTE)pdw + sizeof( HashMastRec ) + sizeof( DWORD )
  513. );
  514. pHashMastRecord = (HashMastRec *)( (LPBYTE)pdw + sizeof( DWORD ) );
  515. }
  516. if ( fResult == FALSE )
  517. {
  518. if ( pbDataFile != NULL )
  519. {
  520. UnmapViewOfFile( pbDataFile );
  521. }
  522. CloseHandle( hDataFile );
  523. return( FALSE );
  524. }
  525. fResult = FALSE;
  526. pbFile = NULL;
  527. hFile = CreateFileU(
  528. m_pwszTempKeyPath,
  529. GENERIC_READ | GENERIC_WRITE,
  530. 0,
  531. NULL,
  532. CREATE_ALWAYS,
  533. FILE_ATTRIBUTE_NORMAL,
  534. NULL
  535. );
  536. if ( hFile == INVALID_HANDLE_VALUE )
  537. {
  538. UnmapViewOfFile( pbDataFile );
  539. CloseHandle( hDataFile );
  540. return( FALSE );
  541. }
  542. if ( SetFilePointer( hFile, pKey->cbData, NULL, FILE_BEGIN ) != 0xFFFFFFFF )
  543. {
  544. fResult = SetEndOfFile( hFile );
  545. }
  546. if ( ( fResult == TRUE ) && ( pKey->cbData > 0 ) )
  547. {
  548. if ( ( hMap = CreateFileMapping(
  549. hFile,
  550. NULL,
  551. PAGE_READWRITE,
  552. 0,
  553. 0,
  554. NULL
  555. ) ) != NULL )
  556. {
  557. pbFile = (LPBYTE)MapViewOfFile( hMap, FILE_MAP_WRITE, 0, 0, 0 );
  558. CloseHandle( hMap );
  559. }
  560. if ( pbFile == NULL )
  561. {
  562. fResult = FALSE;
  563. }
  564. }
  565. cKey = pKey->cbData / KEY_RECORD_SIZE;
  566. pdw = (LPDWORD)( pKey->pbData + KEY_SIZE );
  567. pbKey = pKey->pbData;
  568. pb = pbFile;
  569. RecordId = 0;
  570. __try
  571. {
  572. for ( cCount = 0; ( cCount < cKey ) && ( fResult == TRUE ); cCount++ )
  573. {
  574. if ( ( *pdw + sizeof( HashMastRec ) + sizeof( DWORD ) ) <= pData->cbData )
  575. {
  576. pHashMastRecord = (HashMastRec *)(
  577. pData->pbData + *pdw + sizeof( DWORD )
  578. );
  579. if ( ( pszUnwantedCatalog == NULL ) ||
  580. ( _strnicmp(
  581. pHashMastRecord->CatName,
  582. pszUnwantedCatalog,
  583. MAX_PATH
  584. ) != 0 ) )
  585. {
  586. pUniqueCatalog = FindUniqueCatalogByName(
  587. pHashMastRecord->CatName
  588. );
  589. if ( pUniqueCatalog == NULL )
  590. {
  591. pdw = (LPDWORD)( (LPBYTE)pdw + KEY_RECORD_SIZE );
  592. pbKey += KEY_RECORD_SIZE;
  593. continue;
  594. }
  595. memcpy(
  596. pb,
  597. pbKey,
  598. KEY_SIZE
  599. );
  600. pb += KEY_SIZE;
  601. memcpy(
  602. pb,
  603. (LPBYTE)&pUniqueCatalog->UniqueOffset,
  604. sizeof( DWORD )
  605. );
  606. pb += sizeof( DWORD );
  607. RecordId += 1;
  608. }
  609. }
  610. pdw = (LPDWORD)( (LPBYTE)pdw + KEY_RECORD_SIZE );
  611. pbKey += KEY_RECORD_SIZE;
  612. }
  613. }
  614. __except( EXCEPTION_EXECUTE_HANDLER )
  615. {
  616. SetLastError( GetExceptionCode() );
  617. fResult = FALSE;
  618. }
  619. if ( pbFile != NULL )
  620. {
  621. UnmapViewOfFile( pbFile );
  622. }
  623. if ( fResult == TRUE )
  624. {
  625. cbSize = RecordId * KEY_RECORD_SIZE;
  626. pHeader->cbSortedEOF = cbSize;
  627. pHeader->dwLastRecNum = ( RecordId > 0 ) ? ( RecordId - 1 ) : 0;
  628. pHeader->fDirty = FALSE;
  629. if ( SetFilePointer( hFile, cbSize, NULL, FILE_BEGIN ) != 0xFFFFFFFF )
  630. {
  631. fResult = SetEndOfFile( hFile );
  632. }
  633. }
  634. UnmapViewOfFile( pbDataFile );
  635. CloseHandle( hDataFile );
  636. CloseHandle( hFile );
  637. return( fResult );
  638. }
  639. BOOL MyMoveFileEx(
  640. LPCWSTR lpExistingFileName,
  641. LPCWSTR lpNewFileName,
  642. DWORD dwFlags
  643. )
  644. {
  645. BYTE rgbExisting[_MAX_PATH];
  646. BYTE rgbNew[_MAX_PATH];
  647. char * szExisting = NULL;
  648. char * szNew = NULL;
  649. BOOL bResult = FALSE;
  650. if (FIsWinNT())
  651. {
  652. return(MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags));
  653. }
  654. if ((MkMBStr(rgbExisting, _MAX_PATH, lpExistingFileName, &szExisting)) &&
  655. (MkMBStr(rgbNew, _MAX_PATH, lpNewFileName, &szNew)))
  656. {
  657. bResult = DeleteFile(szNew);
  658. if (bResult)
  659. {
  660. bResult = MoveFileA(szExisting, szNew);
  661. }
  662. }
  663. FreeMBStr(rgbExisting, szExisting);
  664. FreeMBStr(rgbNew, szNew);
  665. return (bResult);
  666. }
  667. //+---------------------------------------------------------------------------
  668. //
  669. // Member: CHashDbCompactor::CommitCompactedDatabase, public
  670. //
  671. // Synopsis: commit the compacted database
  672. //
  673. //----------------------------------------------------------------------------
  674. BOOL
  675. CHashDbCompactor::CommitCompactedDatabase (
  676. IN LPCWSTR pwszFinalKeyPath,
  677. IN LPCWSTR pwszFinalDataPath
  678. )
  679. {
  680. DWORD dwErr = 0;
  681. if ( MyMoveFileEx(
  682. m_pwszTempKeyPath,
  683. pwszFinalKeyPath,
  684. MOVEFILE_COPY_ALLOWED |
  685. MOVEFILE_REPLACE_EXISTING |
  686. MOVEFILE_WRITE_THROUGH
  687. ) == FALSE )
  688. {
  689. dwErr = GetLastError();
  690. return( FALSE );
  691. }
  692. return( MyMoveFileEx(
  693. m_pwszTempDataPath,
  694. pwszFinalDataPath,
  695. MOVEFILE_COPY_ALLOWED |
  696. MOVEFILE_REPLACE_EXISTING |
  697. MOVEFILE_WRITE_THROUGH
  698. ) );
  699. }
  700. //+---------------------------------------------------------------------------
  701. //
  702. // Member: CHashDbCompactor::FreeString, public
  703. //
  704. // Synopsis: free allocated string
  705. //
  706. //----------------------------------------------------------------------------
  707. VOID
  708. CHashDbCompactor::FreeString (IN LPWSTR pwsz)
  709. {
  710. delete pwsz;
  711. }
  712. //+---------------------------------------------------------------------------
  713. //
  714. // Member: CHashDbCompactor::GrowUniqueCatalogs, public
  715. //
  716. // Synopsis: grow the unique catalogs array
  717. //
  718. //----------------------------------------------------------------------------
  719. BOOL
  720. CHashDbCompactor::GrowUniqueCatalogs (DWORD cGrow)
  721. {
  722. BOOL fResult = FALSE;
  723. DWORD cAllocatedUniqueCatalogs;
  724. PUNIQUE_CATALOG aUniqueCatalogs;
  725. cAllocatedUniqueCatalogs = m_cAllocatedUniqueCatalogs + cGrow;
  726. aUniqueCatalogs = new UNIQUE_CATALOG [ cAllocatedUniqueCatalogs ];
  727. if ( aUniqueCatalogs == NULL )
  728. {
  729. SetLastError( E_OUTOFMEMORY );
  730. return( FALSE );
  731. }
  732. memset(
  733. aUniqueCatalogs,
  734. 0,
  735. sizeof( UNIQUE_CATALOG ) * cAllocatedUniqueCatalogs
  736. );
  737. if ( m_aUniqueCatalogs != NULL )
  738. {
  739. memcpy(
  740. aUniqueCatalogs,
  741. m_aUniqueCatalogs,
  742. m_cUniqueCatalogs * sizeof( UNIQUE_CATALOG )
  743. );
  744. delete m_aUniqueCatalogs;
  745. }
  746. m_cAllocatedUniqueCatalogs = cAllocatedUniqueCatalogs;
  747. m_aUniqueCatalogs = aUniqueCatalogs;
  748. return( TRUE );
  749. }
  750. //+---------------------------------------------------------------------------
  751. //
  752. // Member: CHashDbCompactor::FindUniqueCatalogByName, public
  753. //
  754. // Synopsis: find a unique catalog entry given a catalog name
  755. //
  756. //----------------------------------------------------------------------------
  757. PUNIQUE_CATALOG
  758. CHashDbCompactor::FindUniqueCatalogByName (LPCSTR pszCatalogName)
  759. {
  760. DWORD cCount;
  761. if ( ( m_iLastUniqueCatalogFoundByName < m_cUniqueCatalogs ) &&
  762. ( _strnicmp(
  763. m_aUniqueCatalogs[ m_iLastUniqueCatalogFoundByName ].HashDbRecord.CatName,
  764. pszCatalogName,
  765. MAX_PATH
  766. ) == 0 ) )
  767. {
  768. return( &m_aUniqueCatalogs[ m_iLastUniqueCatalogFoundByName ] );
  769. }
  770. for ( cCount = 0; cCount < m_cUniqueCatalogs; cCount++ )
  771. {
  772. if ( _strnicmp(
  773. m_aUniqueCatalogs[ cCount ].HashDbRecord.CatName,
  774. pszCatalogName,
  775. MAX_PATH
  776. ) == 0 )
  777. {
  778. m_iLastUniqueCatalogFoundByName = cCount;
  779. return( &m_aUniqueCatalogs[ cCount ] );
  780. }
  781. }
  782. return( NULL );
  783. }
  784. //+---------------------------------------------------------------------------
  785. //
  786. // Member: CHashDbCompactor::AddUniqueCatalog, public
  787. //
  788. // Synopsis: add a unique catalog to the array
  789. //
  790. //----------------------------------------------------------------------------
  791. BOOL
  792. CHashDbCompactor::AddUniqueCatalog (HashMastRec* pHashMastRecord)
  793. {
  794. DWORD UniqueOffset;
  795. if ( m_cUniqueCatalogs == m_cAllocatedUniqueCatalogs )
  796. {
  797. if ( GrowUniqueCatalogs( GROW_UNIQUE_CATALOGS ) == FALSE )
  798. {
  799. return( FALSE );
  800. }
  801. }
  802. UniqueOffset = ( m_cUniqueCatalogs * (
  803. sizeof( HashMastRec ) + sizeof( DWORD )
  804. ) ) + BFILE_HEADERSIZE;
  805. m_aUniqueCatalogs[ m_cUniqueCatalogs ].HashDbRecord = *pHashMastRecord;
  806. m_aUniqueCatalogs[ m_cUniqueCatalogs ].UniqueOffset = UniqueOffset;
  807. m_cUniqueCatalogs += 1;
  808. return( TRUE );
  809. }
  810. //+---------------------------------------------------------------------------
  811. //
  812. // Member: CHashDbCompactor::CatalogFileExists, public
  813. //
  814. // Synopsis: check if the catalog file exists in the database directory
  815. //
  816. //----------------------------------------------------------------------------
  817. BOOL
  818. CHashDbCompactor::CatalogFileExists (LPCSTR pszCatalogName, DWORD cbName)
  819. {
  820. BOOL fResult = FALSE;
  821. WCHAR pwszFile[ MAX_PATH ];
  822. WCHAR pwszPath[ MAX_PATH ];
  823. HANDLE hFile;
  824. if ( MultiByteToWideChar(
  825. CP_ACP,
  826. 0,
  827. pszCatalogName,
  828. cbName,
  829. pwszFile,
  830. MAX_PATH
  831. ) == 0 )
  832. {
  833. return( FALSE );
  834. }
  835. if ( ( wcslen( m_pwszDbDirectory ) + wcslen( pwszFile ) + 2 ) > MAX_PATH )
  836. {
  837. return( FALSE );
  838. }
  839. wcscpy( pwszPath, m_pwszDbDirectory );
  840. wcscat( pwszPath, L"\\" );
  841. wcscat( pwszPath, pwszFile );
  842. if ( ( hFile = CreateFileU(
  843. pwszPath,
  844. GENERIC_READ,
  845. FILE_SHARE_READ | FILE_SHARE_WRITE,
  846. NULL,
  847. OPEN_EXISTING,
  848. FILE_ATTRIBUTE_NORMAL,
  849. NULL
  850. ) ) != INVALID_HANDLE_VALUE )
  851. {
  852. CloseHandle( hFile );
  853. fResult = TRUE;
  854. }
  855. return( fResult );
  856. }
  857. //+---------------------------------------------------------------------------
  858. //
  859. // Function: CatalogCompactHashDatabase
  860. //
  861. // Synopsis: API for compacting the catalog hash database
  862. //
  863. //----------------------------------------------------------------------------
  864. BOOL WINAPI
  865. CatalogCompactHashDatabase (
  866. IN LPCWSTR pwszDbLock,
  867. IN LPCWSTR pwszDbDirectory,
  868. IN LPCWSTR pwszDbName,
  869. IN OPTIONAL LPCWSTR pwszUnwantedCatalog
  870. )
  871. {
  872. BOOL fResult;
  873. CHashDbCompactor HashDbCompactor;
  874. LPWSTR pwszKeyPath = NULL;
  875. LPWSTR pwszDataPath = NULL;
  876. CRYPT_DATA_BLOB KeyMap;
  877. CRYPT_DATA_BLOB DataMap;
  878. BOOL fDatabaseMapped = FALSE;
  879. CHAR szUnwantedCatalog[ MAX_PATH + 1 ];
  880. LPSTR pszUnwantedCatalog = NULL;
  881. if ( pwszUnwantedCatalog != NULL )
  882. {
  883. pszUnwantedCatalog = szUnwantedCatalog;
  884. if ( WideCharToMultiByte(
  885. CP_ACP,
  886. 0,
  887. pwszUnwantedCatalog,
  888. -1,
  889. pszUnwantedCatalog,
  890. MAX_PATH,
  891. NULL,
  892. NULL
  893. ) == FALSE )
  894. {
  895. return( FALSE );
  896. }
  897. }
  898. fResult = HashDbCompactor.Initialize( pwszDbLock, pwszDbDirectory );
  899. if ( fResult == FALSE )
  900. {
  901. return( FALSE );
  902. }
  903. HashDbCompactor.LockDatabase();
  904. __try
  905. {
  906. fResult = HashDbCompactor.MapDatabase(
  907. pwszDbName,
  908. &KeyMap,
  909. &pwszKeyPath,
  910. &DataMap,
  911. &pwszDataPath
  912. );
  913. if ( fResult == TRUE )
  914. {
  915. fDatabaseMapped = TRUE;
  916. fResult = HashDbCompactor.AnalyzeDataForCompaction(
  917. &DataMap,
  918. pszUnwantedCatalog
  919. );
  920. }
  921. if ( fResult == TRUE )
  922. {
  923. fResult = HashDbCompactor.WriteCompactedDatabase(
  924. &KeyMap,
  925. &DataMap,
  926. pszUnwantedCatalog
  927. );
  928. }
  929. if ( fDatabaseMapped == TRUE )
  930. {
  931. HashDbCompactor.UnmapDatabase( &KeyMap, &DataMap );
  932. }
  933. if ( fResult == TRUE )
  934. {
  935. fResult = HashDbCompactor.CommitCompactedDatabase(
  936. pwszKeyPath,
  937. pwszDataPath
  938. );
  939. }
  940. }
  941. __except( EXCEPTION_EXECUTE_HANDLER )
  942. {
  943. SetLastError( GetExceptionCode() );
  944. fResult = FALSE;
  945. }
  946. HashDbCompactor.UnlockDatabase();
  947. if ( pwszKeyPath != NULL )
  948. {
  949. HashDbCompactor.FreeString( pwszKeyPath );
  950. }
  951. if ( pwszDataPath != NULL )
  952. {
  953. HashDbCompactor.FreeString( pwszDataPath );
  954. }
  955. return( fResult );
  956. }