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.

549 lines
10 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. binvals.c
  5. Abstract:
  6. Routines to manage binary blocks associated with memdb keys.
  7. Author:
  8. Jim Schmidt (jimschm) 8-Aug-1996
  9. Revision History:
  10. Jim Schmidt (jimschm) 21-Oct-1997 Split from memdb.c
  11. --*/
  12. #include "pch.h"
  13. #include "memdbp.h"
  14. #ifndef UNICODE
  15. #error UNICODE required
  16. #endif
  17. static PBINARYBLOCK g_FirstBlockPtr = NULL;
  18. //
  19. // Implementation
  20. //
  21. PBYTE
  22. pGetBinaryData (
  23. IN PBINARYBLOCK BlockPtr
  24. )
  25. /*++
  26. Routine Description:
  27. pGetBinaryData returns a pointer to the data portion of a
  28. BINARYBLOCK struct.
  29. Arguments:
  30. BlockPtr - A pointer to a BINARYBLOCK struct.
  31. Return Value:
  32. A pointer to the binary data of BlockPtr, or NULL if BlockPtr
  33. is invalid.
  34. --*/
  35. {
  36. #ifdef DEBUG
  37. // Verify checked block is valid
  38. if (BlockPtr && BlockPtr->Signature != SIGNATURE) {
  39. DEBUGMSG ((
  40. DBG_ERROR,
  41. "Signature of %x is invalid, can't get binary data",
  42. g_FirstBlockPtr
  43. ));
  44. return NULL;
  45. }
  46. #endif
  47. if (!BlockPtr) {
  48. return NULL;
  49. }
  50. return BlockPtr->Data;
  51. }
  52. DWORD
  53. pGetBinaryDataSize (
  54. IN PBINARYBLOCK BlockPtr
  55. )
  56. {
  57. #ifdef DEBUG
  58. // Verify checked block is valid
  59. if (BlockPtr && BlockPtr->Signature != SIGNATURE) {
  60. DEBUGMSG ((
  61. DBG_ERROR,
  62. "Signature of %x is invalid, can't get binary data",
  63. g_FirstBlockPtr
  64. ));
  65. return 0;
  66. }
  67. #endif
  68. if (!BlockPtr) {
  69. return 0;
  70. }
  71. return BlockPtr->Size - sizeof (BINARYBLOCK);
  72. }
  73. PCBYTE
  74. GetKeyStructBinaryData (
  75. PKEYSTRUCT KeyStruct
  76. )
  77. {
  78. if (!KeyStruct || !(KeyStruct->Flags & KSF_BINARY)) {
  79. return NULL;
  80. }
  81. return pGetBinaryData (KeyStruct->BinaryPtr);
  82. }
  83. DWORD
  84. GetKeyStructBinarySize (
  85. PKEYSTRUCT KeyStruct
  86. )
  87. {
  88. if (!KeyStruct || !(KeyStruct->Flags & KSF_BINARY)) {
  89. return 0;
  90. }
  91. return pGetBinaryDataSize (KeyStruct->BinaryPtr);
  92. }
  93. PBINARYBLOCK
  94. pGetFirstBinaryBlock (
  95. VOID
  96. )
  97. /*++
  98. Routine Description:
  99. pGetFristBinaryBlock returns a pointer to the first allocated
  100. BINARYBLOCK struct, or NULL if no structs are allocated. This
  101. routine is used with pGetNextBinaryBlock to walk all allocated
  102. blocks.
  103. Arguments:
  104. none
  105. Return Value:
  106. A pointer to the the first allocated BINARYBLOCK struct, or NULL
  107. if there are no structs allocated.
  108. --*/
  109. {
  110. #ifdef DEBUG
  111. // Verify checked block is valid
  112. if (g_FirstBlockPtr && g_FirstBlockPtr->Signature != SIGNATURE) {
  113. DEBUGMSG ((DBG_ERROR, "First binary block %x signature is invalid", g_FirstBlockPtr));
  114. return NULL;
  115. }
  116. #endif
  117. return g_FirstBlockPtr;
  118. }
  119. PBINARYBLOCK
  120. pGetNextBinaryBlock (
  121. IN PBINARYBLOCK BlockPtr
  122. )
  123. /*++
  124. Routine Description:
  125. pGetNextBinaryBlock returns a pointer to the next allocated
  126. BINARYBLOCK struct, or NULL if no more blocks are allocated.
  127. Arguments:
  128. BlockPtr - The non-NULL return value of pGetFirstBinaryBlock or
  129. pGetNextBinaryBlock
  130. Return Value:
  131. A pointer to the next BINARYBLOCK struct, or NULL if no more blocks
  132. are allocated.
  133. --*/
  134. {
  135. if (!BlockPtr) {
  136. return NULL;
  137. }
  138. #ifdef DEBUG
  139. // Verify checked block is valid
  140. if (BlockPtr->NextPtr && BlockPtr->NextPtr->Signature != SIGNATURE) {
  141. DEBUGMSG ((DBG_ERROR, "Binary block %x signature is invalid", BlockPtr->NextPtr));
  142. return NULL;
  143. }
  144. #endif
  145. return BlockPtr->NextPtr;
  146. }
  147. PBINARYBLOCK
  148. AllocBinaryBlock (
  149. IN PCBYTE Data,
  150. IN DWORD DataSize,
  151. IN DWORD OwningKey
  152. )
  153. /*++
  154. Routine Description:
  155. AllocBinaryBlock returns a pointer to an initialized BINARYBLOCK
  156. structure, or NULL if the structure could not be allocated. If
  157. the structure is allocated, Data is copied to the newly allocated
  158. block. Call pFreeBinaryBlock to clean up this allocation.
  159. Arguments:
  160. Data - A pointer to a block of binary data to be copied into
  161. the newly allocated structure
  162. DataSize - The number of bytes to copy (may be zero)
  163. OwningKey - The offset of the key who owns the data block
  164. Return Value:
  165. A pointer to the binary block structure, or NULL if it could not
  166. be allocated.
  167. --*/
  168. {
  169. PBINARYBLOCK BlockPtr;
  170. DWORD AllocSize;
  171. AllocSize = DataSize + sizeof (BINARYBLOCK);
  172. BlockPtr = (PBINARYBLOCK) MemAlloc (g_hHeap, 0, AllocSize);
  173. if (!BlockPtr) {
  174. // DataSize must be bigger than 2G
  175. OutOfMemory_Terminate();
  176. }
  177. //
  178. // Initialize block struct
  179. //
  180. if (DataSize) {
  181. CopyMemory (BlockPtr->Data, Data, DataSize);
  182. }
  183. BlockPtr->Size = AllocSize;
  184. BlockPtr->OwningKey = OwningKey;
  185. #ifdef DEBUG
  186. BlockPtr->Signature = SIGNATURE;
  187. #endif
  188. //
  189. // Link block to list of allocated blocks
  190. //
  191. BlockPtr->NextPtr = g_FirstBlockPtr;
  192. if (g_FirstBlockPtr) {
  193. g_FirstBlockPtr->PrevPtr = BlockPtr;
  194. }
  195. g_FirstBlockPtr = BlockPtr;
  196. BlockPtr->PrevPtr = NULL;
  197. //
  198. // Return
  199. //
  200. return BlockPtr;
  201. }
  202. VOID
  203. pFreeBinaryBlock (
  204. PBINARYBLOCK BlockPtr,
  205. BOOL Delink
  206. )
  207. /*++
  208. Routine Description:
  209. pFreeBinaryBlock frees memory allocated for a binary block and optionally
  210. delinks it from the allocation list.
  211. Arguments:
  212. BlockPtr - A pointer to the block to delete
  213. Delink - TRUE if structure should be delinked from allocation list,
  214. or FALSE if the allocation list does not need to be maintained
  215. Return Value:
  216. none
  217. --*/
  218. {
  219. if (!BlockPtr) {
  220. return;
  221. }
  222. #ifdef DEBUG
  223. if (BlockPtr->Signature != SIGNATURE) {
  224. DEBUGMSG ((DBG_ERROR, "Can't free block %x because signature is invalid", BlockPtr));
  225. return;
  226. }
  227. #endif
  228. if (Delink) {
  229. #ifdef DEBUG
  230. if (BlockPtr->PrevPtr && BlockPtr->PrevPtr->Signature != SIGNATURE) {
  231. DEBUGMSG ((DBG_ERROR, "Can't free block %x because prev block (%x) signature is invalid", BlockPtr, BlockPtr->PrevPtr));
  232. return;
  233. }
  234. if (BlockPtr->NextPtr && BlockPtr->NextPtr->Signature != SIGNATURE) {
  235. DEBUGMSG ((DBG_ERROR, "Can't free block %x because next block (%x) signature is invalid", BlockPtr, BlockPtr->NextPtr));
  236. return;
  237. }
  238. #endif
  239. if (BlockPtr->PrevPtr) {
  240. BlockPtr->PrevPtr->NextPtr = BlockPtr->NextPtr;
  241. } else {
  242. g_FirstBlockPtr = BlockPtr->NextPtr;
  243. }
  244. if (BlockPtr->NextPtr) {
  245. BlockPtr->NextPtr->PrevPtr = BlockPtr->PrevPtr;
  246. }
  247. }
  248. MemFree (g_hHeap, 0, BlockPtr);
  249. }
  250. VOID
  251. FreeKeyStructBinaryBlock (
  252. PKEYSTRUCT KeyStruct
  253. )
  254. /*++
  255. Routine Description:
  256. FreeKeyStructBinaryBlock frees a binary block and resets the
  257. KSF_BINARY flag, if the key struct has a binary block allocated.
  258. Arguments:
  259. none
  260. Return Value:
  261. none
  262. --*/
  263. {
  264. if (KeyStruct->Flags & KSF_BINARY) {
  265. pFreeBinaryBlock (KeyStruct->BinaryPtr, TRUE);
  266. KeyStruct->BinaryPtr = NULL;
  267. KeyStruct->Flags &= ~KSF_BINARY;
  268. }
  269. }
  270. VOID
  271. FreeAllBinaryBlocks (
  272. VOID
  273. )
  274. /*++
  275. Routine Description:
  276. FreeAllBinaryBlocks removes all memory associated with binary
  277. blocks. This function is used for final cleanup.
  278. Arguments:
  279. none
  280. Return Value:
  281. none
  282. --*/
  283. {
  284. PBINARYBLOCK NextBlockPtr;
  285. while (g_FirstBlockPtr) {
  286. NextBlockPtr = g_FirstBlockPtr->NextPtr;
  287. pFreeBinaryBlock (g_FirstBlockPtr, FALSE);
  288. g_FirstBlockPtr = NextBlockPtr;
  289. }
  290. }
  291. BOOL
  292. LoadBinaryBlocks (
  293. HANDLE File
  294. )
  295. {
  296. BOOL b;
  297. DWORD Count;
  298. DWORD Owner = 0;
  299. DWORD Size;
  300. DWORD Read;
  301. DWORD d;
  302. PBYTE TempBuf = NULL;
  303. PBINARYBLOCK NewBlock;
  304. b = ReadFile (File, &Count, sizeof (DWORD), &Read, NULL);
  305. if (b && Count) {
  306. //
  307. // Alloc binary objects
  308. //
  309. for (d = 0 ; b && d < Count ; d++) {
  310. // Get Size and Owner
  311. b = ReadFile (File, &Size, sizeof (DWORD), &Read, NULL);
  312. if (Size > BLOCK_SIZE * 32) {
  313. b = FALSE;
  314. }
  315. if (b) {
  316. b = ReadFile (File, &Owner, sizeof (DWORD), &Read, NULL);
  317. }
  318. // Alloc a temporary buffer to read in data
  319. if (b) {
  320. TempBuf = (PBYTE) MemAlloc (g_hHeap, 0, Size);
  321. b = ReadFile (File, TempBuf, Size, &Read, NULL);
  322. // If data read OK, create binary block object
  323. if (b) {
  324. NewBlock = AllocBinaryBlock (TempBuf, Size, Owner);
  325. if (!NewBlock) {
  326. b = FALSE;
  327. } else {
  328. // Link owner to new memory location
  329. MYASSERT (GetKeyStruct (Owner)->Flags & KSF_BINARY);
  330. GetKeyStruct(Owner)->BinaryPtr = NewBlock;
  331. }
  332. }
  333. MemFree (g_hHeap, 0, TempBuf);
  334. TempBuf = NULL;
  335. }
  336. }
  337. }
  338. if (TempBuf) {
  339. MemFree (g_hHeap, 0, TempBuf);
  340. }
  341. return b;
  342. }
  343. BOOL
  344. SaveBinaryBlocks (
  345. HANDLE File
  346. )
  347. {
  348. BOOL b;
  349. DWORD Count;
  350. DWORD Size;
  351. PBINARYBLOCK BinaryPtr;
  352. DWORD Written;
  353. //
  354. // Count the binary objects
  355. //
  356. BinaryPtr = pGetFirstBinaryBlock();
  357. Count = 0;
  358. while (BinaryPtr) {
  359. Count++;
  360. BinaryPtr = pGetNextBinaryBlock (BinaryPtr);
  361. }
  362. //
  363. // Write count to disk
  364. //
  365. b = WriteFile (File, &Count, sizeof (DWORD), &Written, NULL);
  366. if (b) {
  367. //
  368. // Write the binary objects
  369. //
  370. BinaryPtr = pGetFirstBinaryBlock();
  371. while (b && BinaryPtr) {
  372. //
  373. // Format per object:
  374. //
  375. // Size (DWORD)
  376. // Owner (DWORD)
  377. // Data (Size)
  378. //
  379. Size = pGetBinaryDataSize (BinaryPtr);
  380. b = WriteFile (File, &Size, sizeof (DWORD), &Written, NULL);
  381. if (b) {
  382. b = WriteFile (File, &BinaryPtr->OwningKey, sizeof (DWORD), &Written, NULL);
  383. }
  384. if (b && Size) {
  385. b = WriteFile (File, pGetBinaryData (BinaryPtr), Size, &Written, NULL);
  386. if (Written != Size) {
  387. b = FALSE;
  388. }
  389. }
  390. BinaryPtr = pGetNextBinaryBlock(BinaryPtr);
  391. }
  392. }
  393. return b;
  394. }