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.

1301 lines
31 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. keydata.c
  5. Abstract:
  6. Routines that manage data for the memdb key structures.
  7. Author:
  8. Matthew Vanderzee (mvander) 13-Aug-1999
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include "memdbp.h"
  13. //
  14. // KeyStruct Data Functions
  15. //
  16. BOOL
  17. KeyStructSetValue (
  18. IN UINT KeyIndex,
  19. IN UINT Value
  20. )
  21. /*++
  22. Routine Description:
  23. sets the value for a key
  24. Arguments:
  25. KeyIndex - index of key
  26. Value - value to put in key
  27. Return Value:
  28. TRUE if successful
  29. --*/
  30. {
  31. PKEYSTRUCT KeyStruct;
  32. KeyStruct = GetKeyStruct(KeyIndex);
  33. MYASSERT(KeyStruct);
  34. KeyStruct->Value = Value;
  35. KeyStruct->DataFlags |= DATAFLAG_VALUE;
  36. return TRUE;
  37. }
  38. BOOL
  39. KeyStructSetFlags (
  40. IN UINT KeyIndex,
  41. IN BOOL ReplaceFlags,
  42. IN UINT SetFlags,
  43. IN UINT ClearFlags
  44. )
  45. /*++
  46. Routine Description:
  47. sets the flags for a key
  48. Arguments:
  49. KeyIndex - index of key
  50. ReplaceFlags - Specifies if the existing flags are to be replaced. If TRUE then we only
  51. consider SetFlags as the replacing flags, ClearFlags will be ignored
  52. SetFlags - Specifies the bit flags that need to be set (if ReplaceFlags is FALSE) or the
  53. replacement flags (if ReplaceFlags is TRUE).
  54. ClearFlags - Specifies the bit flags that should be cleared (ignored if ReplaceFlags is TRUE).
  55. Return Value:
  56. TRUE if successful, FALSE otherwise.
  57. --*/
  58. {
  59. PKEYSTRUCT KeyStruct;
  60. KeyStruct = GetKeyStruct(KeyIndex);
  61. MYASSERT(KeyStruct);
  62. if (KeyStruct->DataFlags & DATAFLAG_FLAGS) {
  63. if (ReplaceFlags) {
  64. KeyStruct->Flags = SetFlags;
  65. } else {
  66. KeyStruct->Flags &= ~ClearFlags;
  67. KeyStruct->Flags |= SetFlags;
  68. }
  69. } else {
  70. KeyStruct->Flags = SetFlags;
  71. KeyStruct->DataFlags |= DATAFLAG_FLAGS;
  72. }
  73. return TRUE;
  74. }
  75. // LINT - in the next function keystruct is thought to be possibly NULL.
  76. // If we examine the code we'll see that this is not a possibility so...
  77. //lint -save -e794
  78. UINT g_TotalData = 0;
  79. UINT
  80. pAllocateNewDataStruct (
  81. IN UINT DataSize,
  82. IN UINT AltDataSize
  83. )
  84. /*++
  85. Routine Description:
  86. pAllocateNewDataStruct allocates a block of memory in the single
  87. heap, for holding a data structure.
  88. Arguments:
  89. DataSize - Size of the binary data that needs to be stored here
  90. Return Value:
  91. An Index to the new structure.
  92. --*/
  93. {
  94. UINT size;
  95. PKEYSTRUCT keyStruct = NULL;
  96. UINT offset;
  97. UINT prevDel;
  98. UINT result;
  99. MYASSERT (g_CurrentDatabase);
  100. size = DataSize + KEYSTRUCT_SIZE;
  101. //
  102. // Look for free block
  103. //
  104. prevDel = INVALID_OFFSET;
  105. offset = g_CurrentDatabase->FirstKeyDeleted;
  106. while (offset != INVALID_OFFSET) {
  107. keyStruct = GetKeyStructFromOffset (offset);
  108. MYASSERT (keyStruct);
  109. if ((keyStruct->Size >= size) && (keyStruct->Size < (size + ALLOC_TOLERANCE))) {
  110. break;
  111. }
  112. prevDel = offset;
  113. offset = keyStruct->NextDeleted;
  114. }
  115. if (offset == INVALID_OFFSET) {
  116. //
  117. // We could not find one so we need to allocate a new block
  118. //
  119. g_TotalData ++;
  120. offset = DatabaseAllocBlock (size + AltDataSize);
  121. if (offset == INVALID_OFFSET) {
  122. return INVALID_OFFSET;
  123. }
  124. #ifdef DEBUG
  125. //
  126. // if we are in debug mode, and we are using debug structs, set
  127. // pointer normally and set Signature DWORD. if we are not using
  128. // debug structs, then set pointer to 4 bytes below actual offset,
  129. // so all members are shifted down.
  130. //
  131. if (g_UseDebugStructs) {
  132. keyStruct = (PKEYSTRUCT)OFFSET_TO_PTR (offset);
  133. keyStruct->Signature = KEYSTRUCT_SIGNATURE;
  134. } else {
  135. keyStruct = (PKEYSTRUCT)OFFSET_TO_PTR (offset - KEYSTRUCT_HEADER_SIZE);
  136. }
  137. #else
  138. keyStruct = (PKEYSTRUCT)OFFSET_TO_PTR(offset);
  139. #endif
  140. keyStruct->Size = size + AltDataSize;
  141. } else {
  142. //
  143. // Delink free block if recovering free space
  144. //
  145. if (prevDel != INVALID_OFFSET) {
  146. GetKeyStructFromOffset (prevDel)->NextDeleted = keyStruct->NextDeleted;
  147. } else {
  148. g_CurrentDatabase->FirstKeyDeleted = keyStruct->NextDeleted;
  149. }
  150. #ifdef DEBUG
  151. keyStruct->KeyFlags &= ~KSF_DELETED;
  152. #endif
  153. }
  154. //
  155. // Init new block
  156. //
  157. keyStruct->DataSize = DataSize;
  158. keyStruct->DataStructIndex = INVALID_OFFSET;
  159. keyStruct->NextLevelTree = INVALID_OFFSET;
  160. keyStruct->PrevLevelIndex = INVALID_OFFSET;
  161. keyStruct->Flags = 0;
  162. keyStruct->KeyFlags = KSF_DATABLOCK;
  163. keyStruct->DataFlags = 0;
  164. result = AddKeyOffsetToBuffer (offset);
  165. return result;
  166. }
  167. //lint -restore
  168. UINT
  169. KeyStructAddBinaryData (
  170. IN UINT KeyIndex,
  171. IN BYTE Type,
  172. IN BYTE Instance,
  173. IN PCBYTE Data,
  174. IN UINT DataSize
  175. )
  176. /*++
  177. Routine Description:
  178. KeyStructAddBinaryData adds a certain type of binary data to a key
  179. if it doesn't exist yet. If it does, the function fails.
  180. Arguments:
  181. KeyIndex - index of key
  182. Type - type of data
  183. Instance - instance of data
  184. Data - pointer to the data
  185. DataSize - size of data
  186. Return Value:
  187. A valid data handle if successfull, INVALID_OFFSET otherwise.
  188. --*/
  189. {
  190. PKEYSTRUCT prevStruct,dataStruct,nextStruct,keyStruct;
  191. UINT dataIndex, prevIndex;
  192. BOOL found = FALSE;
  193. keyStruct = GetKeyStruct (KeyIndex);
  194. MYASSERT (keyStruct);
  195. // check to see if the data is already there
  196. dataIndex = keyStruct->DataStructIndex;
  197. prevIndex = KeyIndex;
  198. prevStruct = keyStruct;
  199. while (dataIndex != INVALID_OFFSET) {
  200. dataStruct = GetKeyStruct (dataIndex);
  201. MYASSERT (dataStruct);
  202. if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK)== Type) &&
  203. ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance)
  204. ) {
  205. found = TRUE;
  206. break;
  207. }
  208. if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) ||
  209. (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) &&
  210. ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance)
  211. )
  212. ) {
  213. break;
  214. }
  215. prevIndex = dataIndex;
  216. prevStruct = dataStruct;
  217. dataIndex = dataStruct->DataStructIndex;
  218. }
  219. if (found) {
  220. return INVALID_OFFSET;
  221. }
  222. dataIndex = pAllocateNewDataStruct (DataSize, 0);
  223. if (dataIndex == INVALID_OFFSET) {
  224. return INVALID_OFFSET;
  225. }
  226. keyStruct = GetKeyStruct (KeyIndex);
  227. MYASSERT (keyStruct);
  228. prevStruct = GetKeyStruct (prevIndex);
  229. MYASSERT (prevStruct);
  230. dataStruct = GetKeyStruct (dataIndex);
  231. MYASSERT (dataStruct);
  232. keyStruct->DataFlags |= Type;
  233. dataStruct->DataFlags |= Type;
  234. dataStruct->DataFlags |= Instance;
  235. CopyMemory (dataStruct->Data, Data, DataSize);
  236. dataStruct->DataStructIndex = prevStruct->DataStructIndex;
  237. dataStruct->PrevLevelIndex = prevIndex;
  238. prevStruct->DataStructIndex = dataIndex;
  239. if (dataStruct->DataStructIndex != INVALID_OFFSET) {
  240. nextStruct = GetKeyStruct (dataStruct->DataStructIndex);
  241. MYASSERT (nextStruct);
  242. nextStruct->PrevLevelIndex = dataIndex;
  243. }
  244. return dataIndex;
  245. }
  246. // LINT - in the next function keystruct is thought to be possibly NULL.
  247. // If we examine the code we'll see that this is not a possibility so...
  248. //lint -save -e771
  249. UINT
  250. KeyStructGrowBinaryData (
  251. IN UINT KeyIndex,
  252. IN BYTE Type,
  253. IN BYTE Instance,
  254. IN PCBYTE Data,
  255. IN UINT DataSize
  256. )
  257. /*++
  258. Routine Description:
  259. KeyStructGrowBinaryData appends a certain type of binary data to a key
  260. if it does exist. If it doesn't, the new data is added.
  261. Arguments:
  262. KeyIndex - index of key
  263. Type - type of data
  264. Instance - instance of data
  265. Data - pointer to the data
  266. DataSize - size of data
  267. Return Value:
  268. A valid data handle if successfull, INVALID_OFFSET otherwise.
  269. --*/
  270. {
  271. PKEYSTRUCT prevStruct;
  272. PKEYSTRUCT dataStruct;
  273. PKEYSTRUCT keyStruct;
  274. PKEYSTRUCT nextStruct;
  275. PKEYSTRUCT newStruct;
  276. UINT dataIndex;
  277. UINT newIndex;
  278. UINT prevIndex;
  279. BOOL found = FALSE;
  280. MYASSERT (g_CurrentDatabase);
  281. keyStruct = GetKeyStruct (KeyIndex);
  282. MYASSERT (keyStruct);
  283. // check to see if the data is already there
  284. dataIndex = keyStruct->DataStructIndex;
  285. prevStruct = keyStruct;
  286. prevIndex = KeyIndex;
  287. while (dataIndex != INVALID_OFFSET) {
  288. dataStruct = GetKeyStruct (dataIndex);
  289. MYASSERT (dataStruct);
  290. if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK)== Type) &&
  291. ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance)
  292. ) {
  293. found = TRUE;
  294. break;
  295. }
  296. if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) ||
  297. (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) &&
  298. ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance)
  299. )
  300. ) {
  301. break;
  302. }
  303. prevStruct = dataStruct;
  304. prevIndex = dataIndex;
  305. dataIndex = dataStruct->DataStructIndex;
  306. }
  307. if ((dataIndex == INVALID_OFFSET) || (!found)) {
  308. return KeyStructAddBinaryData (KeyIndex, Type, Instance, Data, DataSize);
  309. }
  310. if (dataStruct->Size >= KEYSTRUCT_SIZE + DataSize + dataStruct->DataSize) {
  311. CopyMemory (dataStruct->Data + dataStruct->DataSize, Data, DataSize);
  312. dataStruct->DataSize += DataSize;
  313. return dataIndex;
  314. } else {
  315. newIndex = pAllocateNewDataStruct (DataSize + dataStruct->DataSize, min (dataStruct->DataSize, 65536));
  316. if (newIndex == INVALID_OFFSET) {
  317. return INVALID_OFFSET;
  318. }
  319. // now we need to reget all keystructs used so far because the database
  320. // might have moved
  321. keyStruct = GetKeyStruct (KeyIndex);
  322. MYASSERT (keyStruct);
  323. dataStruct = GetKeyStruct (dataIndex);
  324. MYASSERT (dataStruct);
  325. prevStruct = GetKeyStruct (prevIndex);
  326. MYASSERT (prevStruct);
  327. newStruct = GetKeyStruct (newIndex);
  328. MYASSERT (newStruct);
  329. newStruct->DataSize = dataStruct->DataSize + DataSize;
  330. newStruct->DataFlags = dataStruct->DataFlags;
  331. newStruct->DataStructIndex = dataStruct->DataStructIndex;
  332. newStruct->PrevLevelIndex = dataStruct->PrevLevelIndex;
  333. CopyMemory (newStruct->Data, dataStruct->Data, dataStruct->DataSize);
  334. CopyMemory (newStruct->Data + dataStruct->DataSize, Data, DataSize);
  335. prevStruct->DataStructIndex = newIndex;
  336. if (newStruct->DataStructIndex != INVALID_OFFSET) {
  337. nextStruct = GetKeyStruct (newStruct->DataStructIndex);
  338. MYASSERT (nextStruct);
  339. nextStruct->PrevLevelIndex = newIndex;
  340. }
  341. // now simply remove the block
  342. //
  343. // Donate block to free space
  344. //
  345. dataStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
  346. g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (dataIndex);
  347. #ifdef DEBUG
  348. dataStruct->KeyFlags |= KSF_DELETED;
  349. #endif
  350. // let's empty the keystruct (for better compression)
  351. ZeroMemory (dataStruct->Data, dataStruct->Size - KEYSTRUCT_SIZE);
  352. RemoveKeyOffsetFromBuffer (dataIndex);
  353. return newIndex;
  354. }
  355. }
  356. //lint -restore
  357. UINT
  358. KeyStructGrowBinaryDataByIndex (
  359. IN UINT OldIndex,
  360. IN PCBYTE Data,
  361. IN UINT DataSize
  362. )
  363. /*++
  364. Routine Description:
  365. KeyStructGrowBinaryDataByIndex appends a certain type of binary data to
  366. an existing structure identified by OldIndex. The old structure is
  367. deleted and a new one is allocated holding both old and new data.
  368. Arguments:
  369. OldIndex - index of data
  370. Data - pointer to the data
  371. DataSize - size of data
  372. Return Value:
  373. A valid data index if successfull, INVALID_OFFSET otherwise.
  374. --*/
  375. {
  376. UINT newIndex;
  377. PKEYSTRUCT oldStruct, newStruct, prevStruct, nextStruct;
  378. MYASSERT (g_CurrentDatabase);
  379. oldStruct = GetKeyStruct (OldIndex);
  380. MYASSERT (oldStruct);
  381. if (oldStruct->Size >= KEYSTRUCT_SIZE + DataSize + oldStruct->DataSize) {
  382. CopyMemory (oldStruct->Data + oldStruct->DataSize, Data, DataSize);
  383. oldStruct->DataSize += DataSize;
  384. return OldIndex;
  385. } else {
  386. newIndex = pAllocateNewDataStruct (DataSize + oldStruct->DataSize, min (oldStruct->DataSize, 65536));
  387. if (newIndex == INVALID_OFFSET) {
  388. return INVALID_OFFSET;
  389. }
  390. // now we need to reget all keystructs used so far because the database
  391. // might have moved
  392. oldStruct = GetKeyStruct (OldIndex);
  393. MYASSERT (oldStruct);
  394. newStruct = GetKeyStruct (newIndex);
  395. MYASSERT (newStruct);
  396. newStruct->DataStructIndex = oldStruct->DataStructIndex;
  397. newStruct->PrevLevelIndex = oldStruct->PrevLevelIndex;
  398. newStruct->DataFlags = oldStruct->DataFlags;
  399. CopyMemory (newStruct->Data, oldStruct->Data, oldStruct->DataSize);
  400. CopyMemory (newStruct->Data + oldStruct->DataSize, Data, DataSize);
  401. prevStruct = GetKeyStruct (newStruct->PrevLevelIndex);
  402. MYASSERT (prevStruct);
  403. prevStruct->DataStructIndex = newIndex;
  404. if (newStruct->DataStructIndex != INVALID_OFFSET) {
  405. nextStruct = GetKeyStruct (newStruct->DataStructIndex);
  406. MYASSERT (nextStruct);
  407. nextStruct->PrevLevelIndex = newIndex;
  408. }
  409. // now simply remove the block
  410. //
  411. // Donate block to free space
  412. //
  413. oldStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
  414. g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (OldIndex);
  415. #ifdef DEBUG
  416. oldStruct->KeyFlags |= KSF_DELETED;
  417. #endif
  418. // let's empty the keystruct (for better compression)
  419. ZeroMemory (oldStruct->Data, oldStruct->Size - KEYSTRUCT_SIZE);
  420. RemoveKeyOffsetFromBuffer (OldIndex);
  421. return newIndex;
  422. }
  423. }
  424. // LINT - in the next function prevstruct is thought to be possibly not initialized.
  425. // If we examine the code we'll see that this is not a possibility so...
  426. //lint -save -e771
  427. BOOL
  428. KeyStructDeleteBinaryData (
  429. IN UINT KeyIndex,
  430. IN BYTE Type,
  431. IN BYTE Instance
  432. )
  433. /*++
  434. Routine Description:
  435. KeyStructDeleteBinaryData deletes a certain type of binary data from a key
  436. if it exists. If it doesn't, the function will simply return success.
  437. Arguments:
  438. KeyIndex - index of key
  439. Type - type of data
  440. Instance - instance of data
  441. Return Value:
  442. TRUE if successfull, FALSE if not.
  443. --*/
  444. {
  445. PKEYSTRUCT prevStruct, nextStruct, dataStruct, keyStruct;
  446. UINT dataIndex, prevIndex;
  447. BOOL found = FALSE;
  448. UINT typeInstances = 0;
  449. MYASSERT (g_CurrentDatabase);
  450. keyStruct = GetKeyStruct (KeyIndex);
  451. MYASSERT (keyStruct);
  452. if (!(keyStruct->DataFlags & Type)) {
  453. // no such type of data, exiting
  454. return TRUE;
  455. }
  456. // check to see if the data is already there
  457. dataIndex = keyStruct->DataStructIndex;
  458. prevIndex = KeyIndex;
  459. prevStruct = keyStruct;
  460. while (dataIndex != INVALID_OFFSET) {
  461. dataStruct = GetKeyStruct (dataIndex);
  462. MYASSERT (dataStruct);
  463. if ((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) {
  464. typeInstances ++;
  465. if ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance) {
  466. found = TRUE;
  467. //
  468. // now let's see if we have more instances of this binary type
  469. //
  470. if (dataStruct->DataStructIndex != INVALID_OFFSET) {
  471. nextStruct = GetKeyStruct (dataStruct->DataStructIndex);
  472. if ((nextStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) {
  473. typeInstances ++;
  474. }
  475. }
  476. break;
  477. } else if ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance) {
  478. break;
  479. }
  480. } else if ((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) {
  481. break;
  482. }
  483. prevIndex = dataIndex;
  484. prevStruct = dataStruct;
  485. dataIndex = dataStruct->DataStructIndex;
  486. }
  487. if ((dataIndex == INVALID_OFFSET) || (!found)) {
  488. return TRUE;
  489. }
  490. // remove the linkage
  491. prevStruct->DataStructIndex = dataStruct->DataStructIndex;
  492. if (dataStruct->DataStructIndex != INVALID_OFFSET) {
  493. nextStruct = GetKeyStruct (dataStruct->DataStructIndex);
  494. MYASSERT (nextStruct);
  495. nextStruct->PrevLevelIndex = prevIndex;
  496. }
  497. // now simply remove the block
  498. //
  499. // Donate block to free space
  500. //
  501. dataStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
  502. g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (dataIndex);
  503. #ifdef DEBUG
  504. dataStruct->KeyFlags |= KSF_DELETED;
  505. #endif
  506. // let's empty the keystruct (for better compression)
  507. ZeroMemory (dataStruct->Data, dataStruct->Size - KEYSTRUCT_SIZE);
  508. RemoveKeyOffsetFromBuffer (dataIndex);
  509. //
  510. // finally, fix the keystruct if this was the only instance of this type
  511. //
  512. MYASSERT (typeInstances >= 1);
  513. if (typeInstances == 1) {
  514. keyStruct->DataFlags &= ~Type;
  515. }
  516. return TRUE;
  517. }
  518. //lint -restore
  519. BOOL
  520. KeyStructDeleteBinaryDataByIndex (
  521. IN UINT DataIndex
  522. )
  523. /*++
  524. Routine Description:
  525. KeyStructDeleteBinaryDataByIndex deletes a certain type of binary data from a key.
  526. Arguments:
  527. DataIndex - index of data
  528. Return Value:
  529. TRUE if successfull, FALSE if not.
  530. --*/
  531. {
  532. PKEYSTRUCT prevStruct, nextStruct, dataStruct, keyStruct;
  533. BYTE type = 0;
  534. UINT typeInstances = 0;
  535. MYASSERT (g_CurrentDatabase);
  536. dataStruct = GetKeyStruct (DataIndex);
  537. MYASSERT (dataStruct);
  538. type = dataStruct->DataFlags & DATAFLAG_BINARYMASK;
  539. typeInstances ++;
  540. prevStruct = GetKeyStruct (dataStruct->PrevLevelIndex);
  541. MYASSERT (prevStruct);
  542. if ((prevStruct->DataFlags & DATAFLAG_BINARYMASK) == type) {
  543. typeInstances ++;
  544. }
  545. prevStruct->DataStructIndex = dataStruct->DataStructIndex;
  546. if (dataStruct->DataStructIndex != INVALID_OFFSET) {
  547. nextStruct = GetKeyStruct (dataStruct->DataStructIndex);
  548. MYASSERT (nextStruct);
  549. if ((nextStruct->DataFlags & DATAFLAG_BINARYMASK) == type) {
  550. typeInstances ++;
  551. }
  552. nextStruct->PrevLevelIndex = dataStruct->PrevLevelIndex;
  553. }
  554. // now simply remove the block
  555. //
  556. // Donate block to free space
  557. //
  558. dataStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
  559. g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (DataIndex);
  560. #ifdef DEBUG
  561. dataStruct->KeyFlags |= KSF_DELETED;
  562. #endif
  563. // let's empty the keystruct (for better compression)
  564. ZeroMemory (dataStruct->Data, dataStruct->Size - KEYSTRUCT_SIZE);
  565. RemoveKeyOffsetFromBuffer (DataIndex);
  566. //
  567. // finally, fix the keystruct if this was the only instance of this type
  568. //
  569. MYASSERT (typeInstances >= 1);
  570. if (typeInstances == 1) {
  571. // first we need to find the key starting with the current database struct
  572. keyStruct = dataStruct;
  573. while (keyStruct->KeyFlags & KSF_DATABLOCK) {
  574. // still a datablock
  575. if (keyStruct->PrevLevelIndex == INVALID_OFFSET) {
  576. // something is wrong, the first level is a datablock??
  577. break;
  578. }
  579. keyStruct = GetKeyStruct (keyStruct->PrevLevelIndex);
  580. MYASSERT (keyStruct);
  581. }
  582. if (!(keyStruct->KeyFlags & KSF_DATABLOCK)) {
  583. keyStruct->DataFlags &= ~type;
  584. }
  585. }
  586. return TRUE;
  587. }
  588. UINT
  589. KeyStructReplaceBinaryDataByIndex (
  590. IN UINT OldIndex,
  591. IN PCBYTE Data,
  592. IN UINT DataSize
  593. )
  594. {
  595. UINT newIndex;
  596. PKEYSTRUCT oldStruct, newStruct, prevStruct, nextStruct;
  597. MYASSERT (g_CurrentDatabase);
  598. // NTRAID#NTBUG9-153308-2000/08/01-jimschm Optimize this by keeping the current structure is big enough.
  599. newIndex = pAllocateNewDataStruct (DataSize, 0);
  600. if (newIndex == INVALID_OFFSET) {
  601. return INVALID_OFFSET;
  602. }
  603. oldStruct = GetKeyStruct (OldIndex);
  604. MYASSERT (oldStruct);
  605. newStruct = GetKeyStruct (newIndex);
  606. MYASSERT (newStruct);
  607. newStruct->DataStructIndex = oldStruct->DataStructIndex;
  608. newStruct->PrevLevelIndex = oldStruct->PrevLevelIndex;
  609. newStruct->DataFlags = oldStruct->DataFlags;
  610. CopyMemory (newStruct->Data, Data, DataSize);
  611. prevStruct = GetKeyStruct (newStruct->PrevLevelIndex);
  612. MYASSERT (prevStruct);
  613. prevStruct->DataStructIndex = newIndex;
  614. if (newStruct->DataStructIndex != INVALID_OFFSET) {
  615. nextStruct = GetKeyStruct (newStruct->DataStructIndex);
  616. MYASSERT (nextStruct);
  617. nextStruct->PrevLevelIndex = newIndex;
  618. }
  619. // now simply remove the block
  620. //
  621. // Donate block to free space
  622. //
  623. oldStruct->NextDeleted = g_CurrentDatabase->FirstKeyDeleted;
  624. g_CurrentDatabase->FirstKeyDeleted = KeyIndexToOffset (OldIndex);
  625. #ifdef DEBUG
  626. oldStruct->KeyFlags |= KSF_DELETED;
  627. #endif
  628. // let's empty the keystruct (for better compression)
  629. ZeroMemory (oldStruct->Data, oldStruct->Size - KEYSTRUCT_SIZE);
  630. RemoveKeyOffsetFromBuffer (OldIndex);
  631. return newIndex;
  632. }
  633. // LINT - in the next function prevstruct is thought to be possibly not initialized.
  634. // If we examine the code we'll see that this is not a possibility so...
  635. //lint -save -e771
  636. PBYTE
  637. KeyStructGetBinaryData (
  638. IN UINT KeyIndex,
  639. IN BYTE Type,
  640. IN BYTE Instance,
  641. OUT PUINT DataSize,
  642. OUT PUINT DataIndex //OPTIONAL
  643. )
  644. {
  645. PKEYSTRUCT dataStruct,keyStruct;
  646. UINT dataIndex;
  647. BOOL found = FALSE;
  648. keyStruct = GetKeyStruct (KeyIndex);
  649. MYASSERT (keyStruct);
  650. if (!(keyStruct->DataFlags & Type)) {
  651. return NULL;
  652. }
  653. // check to see if the data is already there
  654. dataIndex = keyStruct->DataStructIndex;
  655. while (dataIndex != INVALID_OFFSET) {
  656. dataStruct = GetKeyStruct (dataIndex);
  657. MYASSERT (dataStruct);
  658. if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK)== Type) &&
  659. ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance)
  660. ) {
  661. found = TRUE;
  662. break;
  663. }
  664. if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) ||
  665. (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) &&
  666. ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance)
  667. )
  668. ) {
  669. break;
  670. }
  671. dataIndex = dataStruct->DataStructIndex;
  672. }
  673. if ((dataIndex == INVALID_OFFSET) || (!found)) {
  674. return NULL;
  675. }
  676. if (DataSize) {
  677. *DataSize = dataStruct->DataSize;
  678. }
  679. if (DataIndex) {
  680. *DataIndex = dataIndex;
  681. }
  682. return dataStruct->Data;
  683. }
  684. //lint -restore
  685. PBYTE
  686. KeyStructGetBinaryDataByIndex (
  687. IN UINT DataIndex,
  688. OUT PUINT DataSize
  689. )
  690. {
  691. PKEYSTRUCT dataStruct;
  692. dataStruct = GetKeyStruct (DataIndex);
  693. MYASSERT (dataStruct);
  694. if (DataSize) {
  695. *DataSize = dataStruct->DataSize;
  696. }
  697. return dataStruct->Data;
  698. }
  699. UINT
  700. KeyStructGetDataIndex (
  701. IN UINT KeyIndex,
  702. IN BYTE Type,
  703. IN BYTE Instance
  704. )
  705. /*++
  706. Routine Description:
  707. KeyStructGetDataIndex looks for a certain type of data and returns it's index
  708. if it exists. If it doesn't, the function will simply return INVALID_OFFSET.
  709. Arguments:
  710. KeyIndex - index of key
  711. Type - type of data
  712. Instance - instance of data
  713. Return Value:
  714. A data index if successfull, INVALID_OFFSET if not.
  715. --*/
  716. {
  717. PKEYSTRUCT keyStruct, dataStruct;
  718. UINT dataIndex;
  719. BOOL found = FALSE;
  720. keyStruct = GetKeyStruct (KeyIndex);
  721. MYASSERT (keyStruct);
  722. if (!(keyStruct->DataFlags & Type)) {
  723. return INVALID_OFFSET;
  724. }
  725. // check to see if we have the data there
  726. dataIndex = keyStruct->DataStructIndex;
  727. while (dataIndex != INVALID_OFFSET) {
  728. dataStruct = GetKeyStruct (dataIndex);
  729. MYASSERT (dataStruct);
  730. if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK)== Type) &&
  731. ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) == Instance)
  732. ) {
  733. found = TRUE;
  734. break;
  735. }
  736. if (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) > Type) ||
  737. (((dataStruct->DataFlags & DATAFLAG_BINARYMASK) == Type) &&
  738. ((dataStruct->DataFlags & DATAFLAG_INSTANCEMASK) > Instance)
  739. )
  740. ) {
  741. break;
  742. }
  743. dataIndex = dataStruct->DataStructIndex;
  744. }
  745. if (!found) {
  746. return INVALID_OFFSET;
  747. }
  748. return dataIndex;
  749. }
  750. DATAHANDLE
  751. KeyStructAddLinkage (
  752. IN UINT KeyIndex,
  753. IN BYTE Type,
  754. IN BYTE Instance,
  755. IN UINT Linkage,
  756. IN BOOL AllowDuplicates
  757. )
  758. {
  759. BOOL toBeAdded = TRUE;
  760. UINT result = INVALID_OFFSET;
  761. PUINT linkArray;
  762. UINT linkSize;
  763. if (!AllowDuplicates) {
  764. //
  765. // check to see if we already have this linkage added
  766. //
  767. linkArray = (PUINT)KeyStructGetBinaryData (KeyIndex, Type, Instance, &linkSize, &result);
  768. if (linkArray) {
  769. while (linkSize >= SIZEOF (UINT)) {
  770. if (*linkArray == Linkage) {
  771. toBeAdded = FALSE;
  772. break;
  773. }
  774. linkArray ++;
  775. linkSize -= SIZEOF (UINT);
  776. }
  777. }
  778. }
  779. if (toBeAdded) {
  780. if (result != INVALID_OFFSET) {
  781. result = KeyStructGrowBinaryDataByIndex (result, (PBYTE)(&Linkage), SIZEOF (UINT));
  782. } else {
  783. result = KeyStructGrowBinaryData (KeyIndex, Type, Instance, (PBYTE)(&Linkage), SIZEOF (UINT));
  784. }
  785. }
  786. return result;
  787. }
  788. DATAHANDLE
  789. KeyStructAddLinkageByIndex (
  790. IN UINT DataIndex,
  791. IN UINT Linkage,
  792. IN BOOL AllowDuplicates
  793. )
  794. {
  795. BOOL toBeAdded = TRUE;
  796. UINT result = INVALID_OFFSET;
  797. PUINT linkArray;
  798. UINT linkSize;
  799. if (!AllowDuplicates) {
  800. //
  801. // check to see if we already have this linkage added
  802. //
  803. linkArray = (PUINT)KeyStructGetBinaryDataByIndex (DataIndex, &linkSize);
  804. if (linkArray) {
  805. while (linkSize >= SIZEOF (UINT)) {
  806. if (*linkArray == Linkage) {
  807. toBeAdded = FALSE;
  808. break;
  809. }
  810. linkArray ++;
  811. linkSize -= SIZEOF (UINT);
  812. }
  813. }
  814. }
  815. if (toBeAdded) {
  816. result = KeyStructGrowBinaryDataByIndex (DataIndex, (PBYTE)(&Linkage), SIZEOF (UINT));
  817. } else {
  818. result = DataIndex;
  819. }
  820. return result;
  821. }
  822. BOOL
  823. KeyStructDeleteLinkage (
  824. IN UINT KeyIndex,
  825. IN BYTE Type,
  826. IN BYTE Instance,
  827. IN UINT Linkage,
  828. IN BOOL FirstOnly
  829. )
  830. {
  831. BOOL checking = TRUE;
  832. BOOL result = FALSE;
  833. PUINT srcArray, destArray, newArray;
  834. UINT srcSize, newSize;
  835. UINT dataIndex;
  836. srcArray = (PUINT)KeyStructGetBinaryData (KeyIndex, Type, Instance, &srcSize, &dataIndex);
  837. if (srcArray) {
  838. newArray = MemDbGetMemory (srcSize);
  839. if (newArray) {
  840. destArray = newArray;
  841. newSize = 0;
  842. while (srcSize >= SIZEOF (UINT)) {
  843. if ((*srcArray == Linkage) &&
  844. (checking)
  845. ) {
  846. if (FirstOnly) {
  847. checking = FALSE;
  848. }
  849. } else {
  850. *destArray = *srcArray;
  851. newSize += SIZEOF (UINT);
  852. destArray ++;
  853. }
  854. srcArray ++;
  855. srcSize -= SIZEOF (UINT);
  856. }
  857. if (newSize) {
  858. result = (KeyStructReplaceBinaryDataByIndex (dataIndex, (PBYTE)newArray, newSize) != INVALID_OFFSET);
  859. } else {
  860. result = KeyStructDeleteBinaryDataByIndex (dataIndex);
  861. }
  862. MemDbReleaseMemory (newArray);
  863. }
  864. }
  865. return result;
  866. }
  867. BOOL
  868. KeyStructDeleteLinkageByIndex (
  869. IN UINT DataIndex,
  870. IN UINT Linkage,
  871. IN BOOL FirstOnly
  872. )
  873. {
  874. BOOL checking = TRUE;
  875. BOOL result = FALSE;
  876. PUINT srcArray, destArray, newArray;
  877. UINT srcSize, newSize;
  878. srcArray = (PUINT)KeyStructGetBinaryDataByIndex (DataIndex, &srcSize);
  879. if (srcArray) {
  880. newArray = MemDbGetMemory (srcSize);
  881. if (newArray) {
  882. destArray = newArray;
  883. newSize = 0;
  884. while (srcSize >= SIZEOF (UINT)) {
  885. if ((*srcArray == Linkage) &&
  886. (checking)
  887. ) {
  888. if (FirstOnly) {
  889. checking = FALSE;
  890. }
  891. } else {
  892. *destArray = *srcArray;
  893. newSize += SIZEOF (UINT);
  894. destArray ++;
  895. }
  896. srcArray ++;
  897. srcSize -= SIZEOF (UINT);
  898. }
  899. if (newSize) {
  900. result = (KeyStructReplaceBinaryDataByIndex (DataIndex, (PBYTE)newArray, newSize) != INVALID_OFFSET);
  901. } else {
  902. result = KeyStructDeleteBinaryDataByIndex (DataIndex);
  903. }
  904. MemDbReleaseMemory (newArray);
  905. }
  906. }
  907. return result;
  908. }
  909. BOOL
  910. KeyStructTestLinkage (
  911. IN UINT KeyIndex,
  912. IN BYTE Type,
  913. IN BYTE Instance,
  914. IN KEYHANDLE Linkage
  915. )
  916. {
  917. BOOL result = FALSE;
  918. PUINT srcArray;
  919. UINT srcSize = 0;
  920. srcArray = (PUINT)KeyStructGetBinaryData (KeyIndex, Type, Instance, &srcSize, NULL);
  921. while (srcSize >= SIZEOF (KEYHANDLE)) {
  922. if (*srcArray == Linkage) {
  923. result = TRUE;
  924. break;
  925. }
  926. srcSize -= SIZEOF (KEYHANDLE);
  927. srcArray++;
  928. }
  929. return result;
  930. }
  931. BOOL
  932. KeyStructTestLinkageByIndex (
  933. IN UINT DataIndex,
  934. IN UINT Linkage
  935. )
  936. {
  937. BOOL result = FALSE;
  938. PUINT srcArray;
  939. UINT srcSize;
  940. srcArray = (PUINT)KeyStructGetBinaryDataByIndex (DataIndex, &srcSize);
  941. while (srcSize >= SIZEOF (UINT)) {
  942. if (*srcArray == Linkage) {
  943. result = TRUE;
  944. break;
  945. }
  946. srcSize -= SIZEOF (UINT);
  947. srcArray++;
  948. }
  949. return result;
  950. }
  951. BOOL
  952. KeyStructGetValue (
  953. IN PKEYSTRUCT KeyStruct,
  954. OUT PUINT Value
  955. )
  956. {
  957. if (!Value) {
  958. return TRUE;
  959. }
  960. if (!(KeyStruct->DataFlags & DATAFLAG_VALUE)) {
  961. //
  962. // there is no value, but we still set output to
  963. // zero and return TRUE
  964. //
  965. *Value = 0;
  966. return TRUE;
  967. }
  968. *Value = KeyStruct->Value;
  969. return TRUE;
  970. }
  971. BOOL
  972. KeyStructGetFlags (
  973. IN PKEYSTRUCT KeyStruct,
  974. OUT PUINT Flags
  975. )
  976. {
  977. if (!Flags) {
  978. return TRUE;
  979. }
  980. if (!(KeyStruct->DataFlags & DATAFLAG_FLAGS)) {
  981. //
  982. // there are no flags, but we still set output to
  983. // zero and return TRUE
  984. //
  985. *Flags = 0;
  986. return TRUE;
  987. }
  988. *Flags = KeyStruct->Flags;
  989. return TRUE;
  990. }
  991. VOID
  992. KeyStructFreeAllData (
  993. PKEYSTRUCT KeyStruct
  994. )
  995. /*++
  996. Routine Description:
  997. KeyStructFreeDataBlock frees a data block and resets the
  998. the KSF data flags, if the key struct has a data block allocated.
  999. --*/
  1000. {
  1001. // NTRAID#NTBUG9-153308-2000/08/01-jimschm Reimplement free routine
  1002. //KeyStructFreeData (KeyStruct);
  1003. KeyStruct->Value = 0;
  1004. KeyStruct->Flags = 0;
  1005. KeyStruct->DataFlags &= ~DATAFLAG_VALUE;
  1006. KeyStruct->DataFlags &= ~DATAFLAG_FLAGS;
  1007. }