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.

840 lines
21 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. database.c
  5. Abstract:
  6. Routines that manage the memdb database memory
  7. Author:
  8. Jim Schmidt (jimschm) 8-Aug-1996
  9. Revision History:
  10. calinn 12-Jan-2000 prepare for 5.1 release
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "memdbp.h"
  17. #define DBG_MEMDB "MemDb"
  18. //
  19. // Strings
  20. //
  21. // None
  22. //
  23. // Constants
  24. //
  25. // None
  26. //
  27. // Macros
  28. //
  29. #define MAX_MEMDB_SIZE 0x80000000 //02 GB
  30. #define INIT_BLOCK_SIZE 0x00010000 //64 KB
  31. //
  32. // Types
  33. //
  34. typedef struct {
  35. HANDLE hFile;
  36. HANDLE hMap;
  37. CHAR FileName[MAX_PATH];
  38. PDATABASE Database;
  39. } DATABASECONTROL, *PDATABASECONTROL;
  40. //
  41. // Globals
  42. //
  43. BOOL g_DatabaseInitialized = FALSE;
  44. DATABASECONTROL g_PermanentDatabaseControl;
  45. DATABASECONTROL g_TemporaryDatabaseControl;
  46. PDATABASE g_CurrentDatabase = NULL;
  47. BYTE g_CurrentDatabaseIndex = DB_NOTHING;
  48. PSTR g_CurrentDatabasePath = NULL;
  49. #ifdef DEBUG
  50. BOOL g_UseDebugStructs = TRUE;
  51. #endif
  52. //
  53. // Macro expansion list
  54. //
  55. // None
  56. //
  57. // Private function prototypes
  58. //
  59. // None
  60. //
  61. // Macro expansion definition
  62. //
  63. // None
  64. //
  65. // Code
  66. //
  67. BOOL
  68. SelectDatabase (
  69. IN BYTE DatabaseIndex
  70. )
  71. {
  72. switch (DatabaseIndex) {
  73. case DB_PERMANENT:
  74. g_CurrentDatabase = g_PermanentDatabaseControl.Database;
  75. g_CurrentDatabaseIndex = DB_PERMANENT;
  76. break;
  77. case DB_TEMPORARY:
  78. g_CurrentDatabase = g_TemporaryDatabaseControl.Database;
  79. g_CurrentDatabaseIndex = DB_TEMPORARY;
  80. break;
  81. default:
  82. SetLastError (ERROR_INVALID_PARAMETER);
  83. return FALSE;
  84. }
  85. if (g_CurrentDatabase == NULL) {
  86. SetLastError (ERROR_OPEN_FAILED);
  87. return FALSE;
  88. }
  89. return TRUE;
  90. }
  91. BOOL
  92. pMapDatabaseFile (
  93. PDATABASECONTROL DatabaseControl
  94. )
  95. {
  96. MYASSERT(DatabaseControl);
  97. DatabaseControl->Database = (PDATABASE) MapFileFromHandle (DatabaseControl->hFile, &DatabaseControl->hMap);
  98. return DatabaseControl->Database != NULL;
  99. }
  100. BOOL
  101. pUnmapDatabaseFile (
  102. PDATABASECONTROL DatabaseControl
  103. )
  104. {
  105. MYASSERT(DatabaseControl);
  106. UnmapFileFromHandle (
  107. (PBYTE)DatabaseControl->Database,
  108. DatabaseControl->hMap
  109. );
  110. DatabaseControl->hMap = NULL;
  111. DatabaseControl->Database = NULL;
  112. return TRUE;
  113. }
  114. BOOL
  115. pGetTempFileName (
  116. IN OUT PSTR FileName,
  117. IN BOOL TryCurrent
  118. )
  119. {
  120. PCHAR a, b;
  121. CHAR Extension[6];
  122. UINT Number = 0;
  123. a = (PCHAR) GetFileNameFromPathA (FileName);
  124. b = (PCHAR) GetDotExtensionFromPathA (FileName);
  125. if (!a) {
  126. a = (PCHAR) GetEndOfStringA (FileName);
  127. } else if (b && a<b && TryCurrent) {
  128. //
  129. // if we have a filename and we want to try the current file...
  130. //
  131. if (!DoesFileExistA (FileName)) {
  132. return TRUE;
  133. }
  134. }
  135. if (b) {
  136. StringCopyA (Extension, b);
  137. *b = 0;
  138. } else {
  139. b = (PCHAR) GetEndOfStringA (FileName);
  140. Extension [0] = 0;
  141. }
  142. if (a >= b) { //lint !e613
  143. a = b;
  144. *(a++) = 'T'; //lint !e613
  145. } else {
  146. a++; //lint !e613
  147. }
  148. if (a+7 == b) {
  149. b = a;
  150. while (*b) {
  151. if (*b < '0' || *b > '9') {
  152. break;
  153. }
  154. b++;
  155. }
  156. if (!(*b)) {
  157. Number = (UINT)atoi(a);
  158. Number++;
  159. }
  160. }
  161. do {
  162. if (Number > 9999999) {
  163. return FALSE;
  164. }
  165. wsprintfA (a, "%07lu", Number);
  166. StringCatA (a, Extension);
  167. Number++;
  168. if (!DoesFileExistA (FileName)) {
  169. return TRUE;
  170. }
  171. } while (TRUE);
  172. return TRUE;
  173. }
  174. BOOL
  175. SizeDatabaseBuffer (
  176. IN BYTE DatabaseIndex,
  177. IN UINT NewSize
  178. )
  179. /*++
  180. Routine Description:
  181. SizeDatabaseBuffer will resize the file that backs up the existent allocated
  182. memory and will remap the file.
  183. Arguments:
  184. DatabaseIndex - specifies which database we are talking about
  185. NewSize - specifies the new size of the buffer
  186. Return Value:
  187. TRUE if the function succeeded, FALSE if not.
  188. --*/
  189. {
  190. DWORD bytes;
  191. BOOL resetCurrentDatabase = FALSE;
  192. PDATABASECONTROL databaseControl;
  193. switch (DatabaseIndex) {
  194. case DB_PERMANENT:
  195. databaseControl = &g_PermanentDatabaseControl;
  196. break;
  197. case DB_TEMPORARY:
  198. databaseControl = &g_TemporaryDatabaseControl;
  199. break;
  200. default:
  201. return FALSE;
  202. }
  203. resetCurrentDatabase = (databaseControl->Database == g_CurrentDatabase);
  204. MYASSERT(databaseControl->hFile);
  205. if (databaseControl->Database) {
  206. //
  207. // if we already have a database, unmap current file from memory.
  208. //
  209. if (!pUnmapDatabaseFile (databaseControl)) {
  210. return FALSE;
  211. }
  212. }
  213. if (SetFilePointer(
  214. databaseControl->hFile,
  215. 0,
  216. NULL,
  217. FILE_BEGIN
  218. ) == INVALID_SET_FILE_POINTER) {
  219. DEBUGMSG ((DBG_ERROR, "MemDb Databases: Cannot set file pointer"));
  220. return FALSE;
  221. }
  222. if (NewSize) {
  223. //
  224. // if size argument is not 0, fix file size indicator at beginning
  225. //
  226. if (!WriteFile (databaseControl->hFile, (PBYTE) &NewSize, sizeof (UINT), &bytes, NULL)) {
  227. return FALSE;
  228. }
  229. } else {
  230. //
  231. // if size argument is 0, that means look at first UINT in file
  232. // which is database->allocsize, and size the file to that size
  233. //
  234. if (!ReadFile (databaseControl->hFile, (PBYTE) &NewSize, sizeof (UINT), &bytes, NULL)) {
  235. return FALSE;
  236. }
  237. }
  238. // in the next call, we know that NewSize cannot exceed MAX_MEMDB_SIZE
  239. // which is 2GB (so casting an unsigned to a signed is safe).
  240. if (!SetSizeOfFile (databaseControl->hFile, (LONGLONG)NewSize)) {
  241. DEBUGMSG ((DBG_ERROR, "MemDb Databases: Cannot set size of file"));
  242. return FALSE;
  243. }
  244. //
  245. // now map file into memory, so everything can use ->Buf for access.
  246. //
  247. if (!pMapDatabaseFile(databaseControl)) {
  248. DEBUGMSG ((DBG_ERROR, "MemDb Databases: Cannot map database file to memory"));
  249. return FALSE;
  250. }
  251. MYASSERT(databaseControl->Database->AllocSize == NewSize);
  252. if (resetCurrentDatabase) {
  253. SelectDatabase (DatabaseIndex);
  254. }
  255. return TRUE;
  256. }
  257. UINT
  258. DatabaseAllocBlock (
  259. UINT Size
  260. )
  261. /*++
  262. Routine Description:
  263. DatabaseAllocBlock allocates a block of memory in the single
  264. heap of size Size, expanding it if necessary.
  265. This function may move the database buffer. Pointers
  266. into the database might not be valid afterwards.
  267. Arguments:
  268. Size - size of block to allocate
  269. Return Value:
  270. An offset to block that was allocated
  271. --*/
  272. {
  273. UINT blockSize;
  274. UINT offset;
  275. MYASSERT (g_CurrentDatabase);
  276. if (Size + g_CurrentDatabase->End + sizeof(DATABASE) > g_CurrentDatabase->AllocSize) {
  277. if (g_CurrentDatabase->AllocSize >= MAX_MEMDB_SIZE) {
  278. DEBUGMSG ((DBG_ERROR, "MemDb Databases: Cannot allocate any more database memory (1)"));
  279. return INVALID_OFFSET;
  280. }
  281. blockSize = INIT_BLOCK_SIZE * (1 + (g_CurrentDatabase->AllocSize / (INIT_BLOCK_SIZE*8)));
  282. if (g_CurrentDatabase->AllocSize + blockSize > MAX_MEMDB_SIZE) {
  283. blockSize = MAX_MEMDB_SIZE - g_CurrentDatabase->AllocSize;
  284. if (blockSize < Size) {
  285. DEBUGMSG ((DBG_ERROR, "MemDb Databases: Cannot allocate any more database memory (2)"));
  286. return INVALID_OFFSET;
  287. }
  288. }
  289. if (blockSize < Size) {
  290. // we want even more
  291. blockSize = INIT_BLOCK_SIZE * (1 + (Size / INIT_BLOCK_SIZE));
  292. }
  293. if (!SizeDatabaseBuffer (g_CurrentDatabaseIndex, g_CurrentDatabase->AllocSize + blockSize)) {
  294. DEBUGMSG ((DBG_ERROR, "MemDb Databases: Cannot allocate any more database memory (2)"));
  295. return INVALID_OFFSET;
  296. }
  297. }
  298. offset = g_CurrentDatabase->End;
  299. g_CurrentDatabase->End += Size;
  300. return offset;
  301. }
  302. BOOL
  303. pInitializeDatabase (
  304. IN BYTE DatabaseIndex
  305. )
  306. {
  307. PDATABASECONTROL databaseControl;
  308. MYASSERT (g_CurrentDatabasePath);
  309. switch (DatabaseIndex) {
  310. case DB_PERMANENT:
  311. databaseControl = &g_PermanentDatabaseControl;
  312. StringCopyA (databaseControl->FileName, g_CurrentDatabasePath);
  313. StringCopyA (AppendWackA (databaseControl->FileName), "p0000000.db");
  314. break;
  315. case DB_TEMPORARY:
  316. databaseControl = &g_TemporaryDatabaseControl;
  317. StringCopyA (databaseControl->FileName, g_CurrentDatabasePath);
  318. StringCopyA (AppendWackA (databaseControl->FileName), "t0000000.db");
  319. break;
  320. default:
  321. return FALSE;
  322. }
  323. if (!pGetTempFileName (databaseControl->FileName, TRUE)) {
  324. DEBUGMSG ((
  325. DBG_ERROR,
  326. "MemDb Databases: Can't get temporary file name for %s",
  327. databaseControl->FileName
  328. ));
  329. return FALSE;
  330. }
  331. databaseControl->hMap = NULL;
  332. databaseControl->Database = NULL;
  333. databaseControl->hFile = BfCreateFileA (databaseControl->FileName);
  334. if (!databaseControl->hFile) {
  335. DEBUGMSG ((DBG_ERROR, "MemDb Databases: Cannot open database file"));
  336. return FALSE;
  337. }
  338. if ((!SizeDatabaseBuffer (DatabaseIndex, INIT_BLOCK_SIZE)) ||
  339. (databaseControl->Database == NULL)
  340. ) {
  341. DEBUGMSG ((DBG_ERROR, "MemDb Databases: Cannot initialize database"));
  342. CloseHandle (databaseControl->hFile);
  343. DeleteFileA (databaseControl->FileName);
  344. return FALSE;
  345. }
  346. databaseControl->Database->End = 0;
  347. databaseControl->Database->FirstLevelTree = INVALID_OFFSET;
  348. databaseControl->Database->FirstKeyDeleted = INVALID_OFFSET;
  349. databaseControl->Database->FirstBinTreeDeleted = INVALID_OFFSET;
  350. databaseControl->Database->FirstBinTreeNodeDeleted = INVALID_OFFSET;
  351. databaseControl->Database->FirstBinTreeListElemDeleted = INVALID_OFFSET;
  352. databaseControl->Database->HashTable = CreateHashBlock();
  353. MYASSERT (databaseControl->Database->HashTable);
  354. ZeroMemory (&databaseControl->Database->OffsetBuffer, sizeof (GROWBUFFER));
  355. databaseControl->Database->OffsetBufferFirstDeletedIndex = INVALID_OFFSET;
  356. return TRUE;
  357. }
  358. BOOL
  359. pDestroyDatabase (
  360. IN BYTE DatabaseIndex
  361. )
  362. {
  363. PDATABASECONTROL databaseControl;
  364. switch (DatabaseIndex) {
  365. case DB_PERMANENT:
  366. databaseControl = &g_PermanentDatabaseControl;
  367. break;
  368. case DB_TEMPORARY:
  369. databaseControl = &g_TemporaryDatabaseControl;
  370. break;
  371. default:
  372. return FALSE;
  373. }
  374. //
  375. // Free all resources for the database
  376. //
  377. if (databaseControl->Database) {
  378. FreeHashBlock (databaseControl->Database->HashTable);
  379. GbFree (&databaseControl->Database->OffsetBuffer);
  380. }
  381. pUnmapDatabaseFile (databaseControl);
  382. if (databaseControl->hFile) {
  383. CloseHandle (databaseControl->hFile);
  384. databaseControl->hFile = NULL;
  385. }
  386. DeleteFileA (databaseControl->FileName);
  387. ZeroMemory (databaseControl, sizeof (DATABASECONTROL));
  388. switch (DatabaseIndex) {
  389. case DB_PERMANENT:
  390. if (g_PermanentDatabaseControl.Database) {
  391. g_CurrentDatabase = g_TemporaryDatabaseControl.Database;
  392. g_CurrentDatabaseIndex = DB_TEMPORARY;
  393. } else {
  394. g_CurrentDatabase = NULL;
  395. g_CurrentDatabaseIndex = DB_NOTHING;
  396. }
  397. break;
  398. case DB_TEMPORARY:
  399. if (g_PermanentDatabaseControl.Database) {
  400. g_CurrentDatabase = g_PermanentDatabaseControl.Database;
  401. g_CurrentDatabaseIndex = DB_PERMANENT;
  402. } else {
  403. g_CurrentDatabase = NULL;
  404. g_CurrentDatabaseIndex = DB_NOTHING;
  405. }
  406. break;
  407. default:
  408. return FALSE;
  409. }
  410. return g_CurrentDatabase != NULL;
  411. }
  412. BOOL
  413. pDatabasesInitialize (
  414. IN PCSTR DatabasePath OPTIONAL
  415. )
  416. {
  417. DWORD databasePathSize = 0;
  418. g_CurrentDatabase = NULL;
  419. g_CurrentDatabaseIndex = DB_NOTHING;
  420. if (DatabasePath) {
  421. g_CurrentDatabasePath = DuplicatePathStringA (DatabasePath, 0);
  422. } else {
  423. databasePathSize = GetCurrentDirectoryA (0, NULL);
  424. if (databasePathSize == 0) {
  425. return FALSE;
  426. }
  427. g_CurrentDatabasePath = AllocPathStringA (databasePathSize + 1);
  428. databasePathSize = GetCurrentDirectoryA (databasePathSize, g_CurrentDatabasePath);
  429. if (databasePathSize == 0) {
  430. FreePathStringA (g_CurrentDatabasePath);
  431. g_CurrentDatabasePath = NULL;
  432. return FALSE;
  433. }
  434. }
  435. //
  436. // Empty the database memory block
  437. //
  438. ZeroMemory (&g_PermanentDatabaseControl, sizeof (DATABASECONTROL));
  439. if (!pInitializeDatabase (DB_PERMANENT)) {
  440. return FALSE;
  441. }
  442. ZeroMemory (&g_TemporaryDatabaseControl, sizeof (DATABASECONTROL));
  443. if (!pInitializeDatabase (DB_TEMPORARY)) {
  444. pDestroyDatabase (DB_PERMANENT);
  445. return FALSE;
  446. }
  447. g_DatabaseInitialized = TRUE;
  448. return SelectDatabase (DB_PERMANENT);
  449. }
  450. BOOL
  451. DatabasesInitializeA (
  452. IN PCSTR DatabasePath OPTIONAL
  453. )
  454. {
  455. return pDatabasesInitialize (DatabasePath);
  456. }
  457. BOOL
  458. DatabasesInitializeW (
  459. IN PCWSTR DatabasePath OPTIONAL
  460. )
  461. {
  462. PCSTR databasePath = NULL;
  463. BOOL result = FALSE;
  464. if (DatabasePath) {
  465. databasePath = ConvertWtoA (DatabasePath);
  466. }
  467. result = pDatabasesInitialize (databasePath);
  468. if (databasePath) {
  469. FreeConvertedStr (databasePath);
  470. databasePath = NULL;
  471. }
  472. return result;
  473. }
  474. VOID
  475. DatabasesTerminate (
  476. IN BOOL EraseDatabasePath
  477. )
  478. {
  479. if (g_DatabaseInitialized) {
  480. //
  481. // Free all database blocks
  482. //
  483. pDestroyDatabase (DB_TEMPORARY);
  484. pDestroyDatabase (DB_PERMANENT);
  485. g_CurrentDatabase = NULL;
  486. g_CurrentDatabaseIndex = DB_NOTHING;
  487. }
  488. if (g_CurrentDatabasePath) {
  489. if (EraseDatabasePath) {
  490. if (!FiRemoveAllFilesInTreeA (g_CurrentDatabasePath)) {
  491. DEBUGMSG ((
  492. DBG_ERROR,
  493. "Can't remove all files in temporary directory %s",
  494. g_CurrentDatabasePath
  495. ));
  496. }
  497. }
  498. FreePathStringA (g_CurrentDatabasePath);
  499. g_CurrentDatabasePath = NULL;
  500. }
  501. ELSE_DEBUGMSG ((DBG_MEMDB, "DatabaseTerminate: no database path was set"));
  502. }
  503. PCSTR
  504. DatabasesGetBasePath (
  505. VOID
  506. )
  507. {
  508. return g_CurrentDatabasePath;
  509. }
  510. PCWSTR
  511. SelectHiveW (
  512. IN PCWSTR FullKeyStr
  513. )
  514. {
  515. PCWSTR result = FullKeyStr;
  516. if (FullKeyStr) {
  517. switch (FullKeyStr[0]) {
  518. case L'~':
  519. g_CurrentDatabase = g_TemporaryDatabaseControl.Database;
  520. g_CurrentDatabaseIndex = DB_TEMPORARY;
  521. result ++;
  522. break;
  523. default:
  524. g_CurrentDatabase = g_PermanentDatabaseControl.Database;
  525. g_CurrentDatabaseIndex = DB_PERMANENT;
  526. }
  527. }
  528. if (!g_CurrentDatabase) {
  529. SetLastError (ERROR_OPEN_FAILED);
  530. return NULL;
  531. }
  532. return result;
  533. }
  534. BYTE
  535. GetCurrentDatabaseIndex (
  536. VOID
  537. )
  538. {
  539. return g_CurrentDatabaseIndex;
  540. }
  541. #ifdef DEBUG
  542. #include "bintree.h"
  543. UINT g_DatabaseCheckLevel = 0;
  544. BOOL
  545. CheckDatabase (
  546. IN UINT Level
  547. )
  548. {
  549. UINT offset,currOffset;
  550. BOOL deleted;
  551. PKEYSTRUCT keyStruct, newStruct;
  552. PDWORD signature;
  553. UINT blockSize;
  554. MYASSERT (g_CurrentDatabase);
  555. if (Level >= MEMDB_CHECKLEVEL1) {
  556. // first let's walk the deleted structures making sure that the signature is good
  557. offset = g_CurrentDatabase->FirstKeyDeleted;
  558. while (offset != INVALID_OFFSET) {
  559. keyStruct = GetKeyStructFromOffset (offset);
  560. MYASSERT (keyStruct);
  561. if (keyStruct->Signature != KEYSTRUCT_SIGNATURE) {
  562. DEBUGMSG ((DBG_ERROR, "Invalid KEYSTRUCT signature found at offset: 0x%8X", offset));
  563. return FALSE;
  564. }
  565. offset = keyStruct->NextDeleted;
  566. }
  567. }
  568. if (Level >= MEMDB_CHECKLEVEL2) {
  569. // now let's look in the offset array and examine all keystructs pointed from there
  570. offset = 0;
  571. while (offset < g_CurrentDatabase->OffsetBuffer.End) {
  572. // now let's look if offset is deleted or not
  573. deleted = FALSE;
  574. currOffset = g_CurrentDatabase->OffsetBufferFirstDeletedIndex;
  575. while (currOffset != INVALID_OFFSET) {
  576. if (currOffset == offset) {
  577. deleted = TRUE;
  578. break;
  579. }
  580. currOffset = *(PUINT)(g_CurrentDatabase->OffsetBuffer.Buf + currOffset);
  581. }
  582. if (!deleted) {
  583. keyStruct = GetKeyStruct (GET_INDEX (offset));
  584. if (!keyStruct) {
  585. DEBUGMSG ((DBG_ERROR, "Invalid offset found: 0x%8X!", GET_INDEX (offset)));
  586. return FALSE;
  587. }
  588. if (keyStruct->Signature != KEYSTRUCT_SIGNATURE) {
  589. DEBUGMSG ((DBG_ERROR, "Invalid KEYSTRUCT signature found at offset: 0x%8X", GET_INDEX(offset)));
  590. return FALSE;
  591. }
  592. if (keyStruct->DataStructIndex != INVALID_OFFSET) {
  593. newStruct = GetKeyStruct (keyStruct->DataStructIndex);
  594. if (newStruct->Signature != KEYSTRUCT_SIGNATURE) {
  595. DEBUGMSG ((DBG_ERROR, "Invalid KEYSTRUCT signature found at offset: 0x%8X", keyStruct->DataStructIndex));
  596. return FALSE;
  597. }
  598. }
  599. if (keyStruct->NextLevelTree != INVALID_OFFSET) {
  600. if (!BinTreeCheck (keyStruct->NextLevelTree)) {
  601. DEBUGMSG ((DBG_ERROR, "Invalid Binary tree found at offset: 0x%8X", keyStruct->NextLevelTree));
  602. return FALSE;
  603. }
  604. }
  605. if (keyStruct->PrevLevelIndex != INVALID_OFFSET) {
  606. newStruct = GetKeyStruct (keyStruct->PrevLevelIndex);
  607. if (newStruct->Signature != KEYSTRUCT_SIGNATURE) {
  608. DEBUGMSG ((DBG_ERROR, "Invalid KEYSTRUCT signature found at offset: 0x%8X", keyStruct->PrevLevelIndex));
  609. return FALSE;
  610. }
  611. }
  612. }
  613. offset += SIZEOF (UINT);
  614. }
  615. }
  616. if (Level >= MEMDB_CHECKLEVEL3) {
  617. // now let's walk the actual database buffer looking for all valid structures stored here
  618. offset = 0;
  619. while (offset < g_CurrentDatabase->End) {
  620. signature = (PDWORD)OFFSET_TO_PTR (offset);
  621. switch (*signature) {
  622. case KEYSTRUCT_SIGNATURE:
  623. if (!FindKeyStructInDatabase (offset)) {
  624. DEBUGMSG ((DBG_ERROR, "Could not find KeyStruct (Offset 0x%lX) in database or deleted list!", offset));
  625. return FALSE;
  626. }
  627. keyStruct = GetKeyStructFromOffset (offset);
  628. if (keyStruct->DataStructIndex != INVALID_OFFSET) {
  629. newStruct = GetKeyStruct (keyStruct->DataStructIndex);
  630. if (newStruct->Signature != KEYSTRUCT_SIGNATURE) {
  631. DEBUGMSG ((DBG_ERROR, "Invalid KEYSTRUCT signature found at offset: 0x%8X", keyStruct->DataStructIndex));
  632. return FALSE;
  633. }
  634. }
  635. if (keyStruct->NextLevelTree != INVALID_OFFSET) {
  636. if (!BinTreeCheck (keyStruct->NextLevelTree)) {
  637. DEBUGMSG ((DBG_ERROR, "Invalid Binary tree found at offset: 0x%8X", keyStruct->NextLevelTree));
  638. return FALSE;
  639. }
  640. }
  641. if (keyStruct->PrevLevelIndex != INVALID_OFFSET) {
  642. newStruct = GetKeyStruct (keyStruct->PrevLevelIndex);
  643. if (newStruct->Signature != KEYSTRUCT_SIGNATURE) {
  644. DEBUGMSG ((DBG_ERROR, "Invalid KEYSTRUCT signature found at offset: 0x%8X", keyStruct->PrevLevelIndex));
  645. return FALSE;
  646. }
  647. }
  648. blockSize = keyStruct->Size;
  649. break;
  650. case NODESTRUCT_SIGNATURE:
  651. case BINTREE_SIGNATURE:
  652. case LISTELEM_SIGNATURE:
  653. if (!BinTreeFindStructInDatabase (*signature, offset)) {
  654. DEBUGMSG ((DBG_ERROR, "Could not find BinTree struct (Offset 0x%lX) in database or deleted list!", offset));
  655. return FALSE;
  656. }
  657. blockSize = BinTreeGetSizeOfStruct(*signature);
  658. break;
  659. default:
  660. DEBUGMSG ((DBG_ERROR, "Invalid structure found in database buffer!"));
  661. return FALSE;
  662. }
  663. if (blockSize==0) {
  664. DEBUGMSG ((DBG_ERROR, "Invalid block size found in database buffer!"));
  665. return FALSE;
  666. }
  667. offset += blockSize;
  668. }
  669. }
  670. return TRUE;
  671. }
  672. #endif