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.

330 lines
8.1 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. offsetbuf.c
  5. Abstract:
  6. Routines that manage the keystruct offsetbuffer
  7. Author:
  8. Matthew Vanderzee (mvander) 13-Aug-1999
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include "memdbp.h"
  13. //
  14. // we store index flags in the top two bits of the UINT offsets in
  15. // the buffer, because offsets never have a top two bits set
  16. //
  17. // if the user links a key, we want to mark that index, so we
  18. // dont add it to the deleted index list. if a key is linked,
  19. // and then deleted, we want to keep that key's index pointing
  20. // to INVALID_OFFSET, instead of reusing the index.
  21. //
  22. // if a key is moved, we replace the key's original offset with
  23. // the index of the new key's offset. then we flag that the
  24. // offset has been redirected.
  25. //
  26. // if an index is marked or redirected, when that key is deleted,
  27. // we just set the true index (the index that any redirected indices
  28. // point to) to INVALID_OFFSET.
  29. //
  30. #define INDEX_FLAG_BITS 2
  31. #define INDEX_MOVE_BITS_TO_POS(bits) (((UINT)(bits)) << (8*sizeof(UINT)-INDEX_FLAG_BITS))
  32. #define INDEX_MARKED_FLAG INDEX_MOVE_BITS_TO_POS(0x01)
  33. #define INDEX_REDIRECTED_FLAG INDEX_MOVE_BITS_TO_POS(0x02)
  34. #define INDEX_FLAG_MASK INDEX_MOVE_BITS_TO_POS(0x03)
  35. #define GET_UINT_AT_INDEX(index) (*(PUINT)(g_CurrentDatabase->OffsetBuffer.Buf + (index)))
  36. #define SET_UINT_AT_INDEX(index, offset) ((*(PUINT)(g_CurrentDatabase->OffsetBuffer.Buf + (index)))=(offset))
  37. #define MARK_INDEX(Index) (GET_UINT_AT_INDEX(Index) |= INDEX_MARKED_FLAG)
  38. #define IS_INDEX_MARKED(Index) ((BOOL)(GET_UINT_AT_INDEX(Index) & INDEX_FLAG_MASK))
  39. VOID
  40. MarkIndexList (
  41. IN PUINT IndexList,
  42. IN UINT IndexListSize
  43. )
  44. {
  45. BYTE CurrentDatabase;
  46. UINT i;
  47. CurrentDatabase = g_CurrentDatabaseIndex;
  48. //
  49. // iterate through whole list, switch to correct
  50. // database, and mark list as linked.
  51. //
  52. for (i = 0; i < IndexListSize; i++) {
  53. SelectDatabase (GET_DATABASE (IndexList[i]));
  54. MARK_INDEX (GET_INDEX (IndexList[i]));
  55. #ifdef _DEBUG
  56. if (GET_UINT_AT_INDEX (GET_INDEX (IndexList[i])) != INVALID_OFFSET) {
  57. MYASSERT (GetKeyStruct (GET_INDEX (IndexList[i])));
  58. }
  59. #endif
  60. }
  61. SelectDatabase (CurrentDatabase);
  62. }
  63. VOID
  64. RedirectKeyIndex (
  65. IN UINT Index,
  66. IN UINT TargetIndex
  67. )
  68. /*++
  69. Routine Description:
  70. sets the offset at Index to TargetIndex, with INDEX_REDIRECTED_FLAG
  71. set in the top byte. also, we mark TargetIndex, indicating it has
  72. something redirected to it.
  73. --*/
  74. {
  75. MYASSERT(!(Index & INDEX_FLAG_MASK));
  76. MYASSERT(!(TargetIndex & INDEX_FLAG_MASK));
  77. MYASSERT(!(GET_UINT_AT_INDEX(Index) & INDEX_REDIRECTED_FLAG));
  78. MYASSERT(!(GET_UINT_AT_INDEX(TargetIndex) & INDEX_REDIRECTED_FLAG));
  79. SET_UINT_AT_INDEX(Index, TargetIndex | INDEX_REDIRECTED_FLAG);
  80. MARK_INDEX(TargetIndex);
  81. }
  82. UINT
  83. pGetTrueIndex (
  84. IN UINT Index
  85. )
  86. /*++
  87. Routine Description:
  88. takes and index and returns the true index, which is the index that
  89. actually holds the offset of the keystruct. indexes with the
  90. redirected flag hold the index they are redirected to.
  91. --*/
  92. {
  93. MYASSERT(!(Index & INDEX_FLAG_MASK));
  94. while (GET_UINT_AT_INDEX(Index) & INDEX_REDIRECTED_FLAG) {
  95. Index = GET_UINT_AT_INDEX(Index) & ~INDEX_FLAG_MASK;
  96. }
  97. return Index;
  98. }
  99. UINT
  100. KeyIndexToOffset (
  101. IN UINT Index
  102. )
  103. /*++
  104. Routine Description:
  105. KeyIndexToOffset converts an index of a Keystruct
  106. (in g_CurrentDatabase->OffsetBuffer) to the Keystruct's offset in the database.
  107. Arguments:
  108. Index - index in OffsetBuffer. must be valid
  109. Return Value:
  110. Offset of Keystruct.
  111. --*/
  112. {
  113. MYASSERT(!(Index & INDEX_FLAG_MASK));
  114. MYASSERT (Index <= g_CurrentDatabase->OffsetBuffer.End-sizeof(UINT));
  115. MYASSERT (g_CurrentDatabase);
  116. if (!g_CurrentDatabase->OffsetBuffer.Buf) {
  117. return INVALID_OFFSET;
  118. }
  119. do {
  120. Index = GET_UINT_AT_INDEX(Index);
  121. if (Index == INVALID_OFFSET) {
  122. return INVALID_OFFSET;
  123. }
  124. if (!(Index & INDEX_REDIRECTED_FLAG)) {
  125. //
  126. // we have found a non-redirected index, so check
  127. // that this points to a real keystruct, and return it.
  128. //
  129. MYASSERT(GetKeyStructFromOffset(Index & ~INDEX_FLAG_MASK));
  130. return Index & ~INDEX_FLAG_MASK;
  131. }
  132. Index &= ~INDEX_FLAG_MASK;
  133. MYASSERT (Index <= g_CurrentDatabase->OffsetBuffer.End-sizeof(UINT));
  134. } while (TRUE); //lint !e506
  135. }
  136. UINT
  137. AddKeyOffsetToBuffer (
  138. IN UINT Offset
  139. )
  140. /*++
  141. Routine Description:
  142. gets a space in g_CurrentDatabase->OffsetBuffer and sets it to Offset
  143. Arguments:
  144. Offset - value to put in buffer space
  145. Return Value:
  146. Index of space in g_CurrentDatabase->OffsetBuffer
  147. --*/
  148. {
  149. PUINT Ptr;
  150. MYASSERT (g_CurrentDatabase);
  151. if (Offset & INDEX_FLAG_MASK) {
  152. DEBUGMSG ((DBG_ERROR, "Offset to be put in list is too big, 0x%08lX", Offset));
  153. return FALSE;
  154. }
  155. //
  156. // this will check that Offset is valid and points to Keystruct
  157. //
  158. MYASSERT(GetKeyStructFromOffset(Offset));
  159. if (g_CurrentDatabase->OffsetBufferFirstDeletedIndex != INVALID_OFFSET)
  160. {
  161. //
  162. // if we have deleted offsets from offset list, we
  163. // find an open index, the first of which is stored
  164. // in g_CurrentDatabase->OffsetBufferFirstDeletedIndex. the value at
  165. // this index in the buffer is the next open index,
  166. // and the value at that index is the next one, etc.
  167. //
  168. Ptr = &GET_UINT_AT_INDEX(g_CurrentDatabase->OffsetBufferFirstDeletedIndex);
  169. g_CurrentDatabase->OffsetBufferFirstDeletedIndex = *Ptr;
  170. } else {
  171. //
  172. // otherwise, make g_CurrentDatabase->OffsetBuffer bigger to hold new offset.
  173. //
  174. Ptr = (PUINT) GbGrow (&g_CurrentDatabase->OffsetBuffer, sizeof(UINT));
  175. }
  176. *Ptr = Offset;
  177. return (UINT)((UBINT)Ptr - (UBINT)g_CurrentDatabase->OffsetBuffer.Buf);
  178. }
  179. VOID
  180. RemoveKeyOffsetFromBuffer(
  181. IN UINT Index
  182. )
  183. /*++
  184. Routine Description:
  185. frees a space in g_CurrentDatabase->OffsetBuffer (adds to deleted index list)
  186. Arguments:
  187. Index - position of space to free
  188. --*/
  189. {
  190. if (Index == INVALID_OFFSET) {
  191. return;
  192. }
  193. MYASSERT (g_CurrentDatabase);
  194. if (IS_INDEX_MARKED(Index)) {
  195. //
  196. // if index is marked, either it is redirected or something
  197. // is linked to this index. either way, we do not want to
  198. // reuse the index, so just set true index (not a redirected
  199. // one) to INVALID_OFFSET.
  200. //
  201. SET_UINT_AT_INDEX(pGetTrueIndex(Index), INVALID_OFFSET);
  202. } else {
  203. //
  204. // index not marked, so we can reuse this index by
  205. // putting it in the deleted index list.
  206. //
  207. SET_UINT_AT_INDEX(Index, g_CurrentDatabase->OffsetBufferFirstDeletedIndex);
  208. g_CurrentDatabase->OffsetBufferFirstDeletedIndex = Index;
  209. }
  210. }
  211. BOOL
  212. WriteOffsetBlock (
  213. IN PGROWBUFFER pOffsetBuffer,
  214. IN OUT PBYTE *Buf
  215. )
  216. {
  217. MYASSERT(pOffsetBuffer);
  218. *(((PUINT)*Buf)++) = pOffsetBuffer->End;
  219. CopyMemory (*Buf, pOffsetBuffer->Buf, pOffsetBuffer->End);
  220. *Buf += pOffsetBuffer->End;
  221. return TRUE;
  222. }
  223. BOOL
  224. ReadOffsetBlock (
  225. OUT PGROWBUFFER pOffsetBuffer,
  226. IN OUT PBYTE *Buf
  227. )
  228. {
  229. UINT OffsetBufferSize;
  230. MYASSERT(pOffsetBuffer);
  231. ZeroMemory (pOffsetBuffer, sizeof (GROWBUFFER));
  232. OffsetBufferSize = *(((PUINT)*Buf)++);
  233. if (OffsetBufferSize > 0) {
  234. if (!GbGrow(pOffsetBuffer, OffsetBufferSize)) {
  235. return FALSE;
  236. }
  237. CopyMemory (pOffsetBuffer->Buf, *Buf, OffsetBufferSize);
  238. *Buf += OffsetBufferSize;
  239. }
  240. return TRUE;
  241. }
  242. UINT GetOffsetBufferBlockSize (
  243. IN PGROWBUFFER pOffsetBuffer
  244. )
  245. {
  246. return sizeof (UINT) + pOffsetBuffer->End;
  247. }