4 * Copyright (C) 2001 Rex Jolliff
5 * Copyright (C) 2001 Eric Kohl
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #define REG_HIVE_ID 0x66676572 /* "regf" */
28 #define REG_BIN_ID 0x6e696268 /* "hbin" */
29 #define REG_KEY_CELL_ID 0x6b6e
30 #define REG_HASH_TABLE_BLOCK_ID 0x666c
31 #define REG_VALUE_CELL_ID 0x6b76
33 #define REG_BLOCK_SIZE 4096
34 #define REG_HBIN_DATA_OFFSET 32
35 #define REG_INIT_BLOCK_LIST_SIZE 32
36 #define REG_INIT_HASH_TABLE_SIZE 3
37 #define REG_EXTEND_HASH_TABLE_SIZE 4
38 #define REG_VALUE_LIST_CELL_MULTIPLE 4
41 #define ABS_VALUE(V) (((V) < 0) ? -(V) : (V))
44 /* BLOCK_OFFSET = offset in file after header block */
45 typedef ULONG BLOCK_OFFSET
, *PBLOCK_OFFSET
;
47 /* header for registry hive file : */
48 typedef struct _HIVE_HEADER
50 /* Hive identifier "regf" (0x66676572) */
59 /* When this hive file was last modified */
60 ULONGLONG DateModified
;
62 /* Registry format major version (1) */
65 /* Registry format minor version (3)
66 Version 3 added fast indexes, version 5 has large value optimizations */
69 /* Registry file type (0 - Primary, 1 - Log) */
72 /* Registry format (1 is the only defined value so far) */
75 /* Offset into file from the byte after the end of the base block.
76 If the hive is volatile, this is the actual pointer to the KEY_CELL */
77 BLOCK_OFFSET RootKeyOffset
;
79 /* Size of each hive block ? */
85 /* Name of hive file */
90 /* Checksum of first 0x200 bytes */
92 } __attribute__((packed
)) HIVE_HEADER
, *PHIVE_HEADER
;
95 typedef struct _BIN_HEADER
97 /* Bin identifier "hbin" (0x6E696268) */
100 /* Block offset of this bin */
101 BLOCK_OFFSET BinOffset
;
103 /* Size in bytes, multiple of the block size (4KB) */
108 /* When this bin was last modified */
109 ULONGLONG DateModified
;
111 /* ? (In-memory only) */
113 } __attribute__((packed
)) HBIN
, *PHBIN
;
116 typedef struct _CELL_HEADER
118 /* <0 if used, >0 if free */
120 } __attribute__((packed
)) CELL_HEADER
, *PCELL_HEADER
;
123 typedef struct _KEY_CELL
125 /* Size of this cell */
128 /* Key cell identifier "kn" (0x6b6e) */
134 /* Time of last flush */
135 ULONGLONG LastWriteTime
; /* FILETIME */
140 /* Block offset of parent key cell */
141 BLOCK_OFFSET ParentKeyOffset
;
143 /* Count of sub keys for the key in this key cell */
144 ULONG NumberOfSubKeys
;
149 /* Block offset of has table for FIXME: subkeys/values? */
150 BLOCK_OFFSET HashTableOffset
;
155 /* Count of values contained in this key cell */
156 ULONG NumberOfValues
;
158 /* Block offset of VALUE_LIST_CELL */
159 BLOCK_OFFSET ValueListOffset
;
161 /* Block offset of security cell */
162 BLOCK_OFFSET SecurityKeyOffset
;
164 /* Block offset of registry key class */
165 BLOCK_OFFSET ClassNameOffset
;
170 /* Size in bytes of key name */
173 /* Size of class name in bytes */
176 /* Name of key (not zero terminated) */
178 } __attribute__((packed
)) KEY_CELL
, *PKEY_CELL
;
181 /* KEY_CELL.Type constants */
182 #define REG_LINK_KEY_CELL_TYPE 0x10
183 #define REG_KEY_NAME_PACKED 0x20
184 #define REG_ROOT_KEY_CELL_TYPE 0x0c
188 // HashValue=four letters of value's name
189 typedef struct _HASH_RECORD
191 BLOCK_OFFSET KeyOffset
;
193 } __attribute__((packed
)) HASH_RECORD
, *PHASH_RECORD
;
196 typedef struct _HASH_TABLE_CELL
200 USHORT HashTableSize
;
201 HASH_RECORD Table
[0];
202 } __attribute__((packed
)) HASH_TABLE_CELL
, *PHASH_TABLE_CELL
;
205 typedef struct _VALUE_LIST_CELL
208 BLOCK_OFFSET ValueOffset
[0];
209 } __attribute__((packed
)) VALUE_LIST_CELL
, *PVALUE_LIST_CELL
;
212 typedef struct _VALUE_CELL
216 USHORT NameSize
; // length of Name
217 ULONG DataSize
; // length of datas in the cell pointed by DataOffset
218 BLOCK_OFFSET DataOffset
;// datas are here if high bit of DataSize is set
222 CHAR Name
[0]; /* warning : not zero terminated */
223 } __attribute__((packed
)) VALUE_CELL
, *PVALUE_CELL
;
225 /* VALUE_CELL.Flags constants */
226 #define REG_VALUE_NAME_PACKED 0x0001
228 /* VALUE_CELL.DataSize mask constants */
229 #define REG_DATA_SIZE_MASK 0x7FFFFFFF
230 #define REG_DATA_IN_OFFSET 0x80000000
233 typedef struct _DATA_CELL
237 } __attribute__((packed
)) DATA_CELL
, *PDATA_CELL
;
240 typedef struct _REGISTRY_HIVE
243 PHIVE_HEADER HiveHeader
;
248 PCELL_HEADER
*FreeList
;
249 BLOCK_OFFSET
*FreeListOffset
;
250 } REGISTRY_HIVE
, *PREGISTRY_HIVE
;
253 static PVOID MbBase
= NULL
;
254 static ULONG MbSize
= 0;
256 /* FUNCTIONS ****************************************************************/
259 InitMbMemory (PVOID ChunkBase
)
267 AllocateMbMemory (ULONG MemSize
)
273 MbBase
= (PVOID
)((ULONG
)MbBase
+ MemSize
);
286 GetMbAllocatedSize (VOID
)
293 CmiCreateDefaultHiveHeader (PHIVE_HEADER Header
)
296 memset (Header
, 0, REG_BLOCK_SIZE
);
297 Header
->BlockId
= REG_HIVE_ID
;
298 Header
->UpdateCounter1
= 0;
299 Header
->UpdateCounter2
= 0;
300 Header
->DateModified
= 0;
301 Header
->MajorVersion
= 1;
302 Header
->MinorVersion
= 3;
306 Header
->RootKeyOffset
= -1;
307 Header
->BlockSize
= REG_BLOCK_SIZE
;
308 Header
->Checksum
= 0;
313 CmiCreateDefaultBinCell (PHBIN BinCell
)
316 memset (BinCell
, 0, REG_BLOCK_SIZE
);
317 BinCell
->HeaderId
= REG_BIN_ID
;
318 BinCell
->DateModified
= 0ULL;
319 BinCell
->BinSize
= REG_BLOCK_SIZE
;
324 CmiCreateDefaultRootKeyCell (PKEY_CELL RootKeyCell
, PCWSTR KeyName
)
330 BOOL Packable
= TRUE
;
332 assert (RootKeyCell
);
334 BaseKeyName
= wcsrchr(KeyName
, L
'\\') + 1;
335 NameSize
= wcslen(BaseKeyName
);
336 for (i
= 0; i
< NameSize
; i
++)
338 if (KeyName
[i
] & 0xFF00)
341 NameSize
*= sizeof(WCHAR
);
346 CellSize
= ROUND_UP(sizeof(KEY_CELL
) + NameSize
, 16);
348 memset (RootKeyCell
, 0, CellSize
);
349 RootKeyCell
->CellSize
= -CellSize
;
350 RootKeyCell
->Id
= REG_KEY_CELL_ID
;
351 RootKeyCell
->Flags
= REG_ROOT_KEY_CELL_TYPE
;
352 RootKeyCell
->LastWriteTime
= 0ULL;
353 RootKeyCell
->ParentKeyOffset
= 0;
354 RootKeyCell
->NumberOfSubKeys
= 0;
355 RootKeyCell
->HashTableOffset
= -1;
356 RootKeyCell
->NumberOfValues
= 0;
357 RootKeyCell
->ValueListOffset
= -1;
358 RootKeyCell
->SecurityKeyOffset
= 0;
359 RootKeyCell
->ClassNameOffset
= -1;
360 RootKeyCell
->NameSize
= NameSize
;
361 RootKeyCell
->ClassSize
= 0;
364 for(i
= 0; i
< NameSize
; i
++)
366 ((PCHAR
)RootKeyCell
->Name
)[i
] = BaseKeyName
[i
];
368 RootKeyCell
->Flags
|= REG_KEY_NAME_PACKED
;
372 memcpy (RootKeyCell
->Name
, BaseKeyName
, NameSize
);
377 static PREGISTRY_HIVE
378 CmiCreateHive (PCWSTR KeyName
)
381 PCELL_HEADER FreeCell
;
382 PKEY_CELL RootKeyCell
;
385 Hive
= (PREGISTRY_HIVE
) MmAllocateMemory (sizeof(REGISTRY_HIVE
));
390 memset (Hive
, 0, sizeof(REGISTRY_HIVE
));
392 DbgPrint((DPRINT_REGISTRY
, "Hive %x\n", Hive
));
394 /* Create hive beader (aka 'base block') */
395 Hive
->HiveHeader
= (PHIVE_HEADER
) AllocateMbMemory (REG_BLOCK_SIZE
);
396 if (Hive
->HiveHeader
== NULL
)
401 CmiCreateDefaultHiveHeader(Hive
->HiveHeader
);
402 Hive
->FileSize
= REG_BLOCK_SIZE
;
404 /* Allocate block list */
405 Hive
->BlockListSize
= 1;
406 Hive
->BlockList
= MmAllocateMemory (sizeof(PHBIN
) * Hive
->BlockListSize
);
407 if (Hive
->BlockList
== NULL
)
413 /* Allocate free cell list */
414 Hive
->FreeListMax
= 32;
415 Hive
->FreeList
= MmAllocateMemory(sizeof(PCELL_HEADER
) * Hive
->FreeListMax
);
416 if (Hive
->FreeList
== NULL
)
418 MmFreeMemory (Hive
->BlockList
);
422 Hive
->FreeListOffset
= MmAllocateMemory(sizeof(BLOCK_OFFSET
) * Hive
->FreeListMax
);
423 if (Hive
->FreeListOffset
== NULL
)
425 MmFreeMemory (Hive
->FreeList
);
426 MmFreeMemory (Hive
->BlockList
);
431 /* Allocate first bin */
432 Hive
->BlockList
[0] = (PHBIN
) AllocateMbMemory (REG_BLOCK_SIZE
);
433 if (Hive
->BlockList
[0] == NULL
)
435 MmFreeMemory (Hive
->FreeListOffset
);
436 MmFreeMemory (Hive
->FreeList
);
437 MmFreeMemory (Hive
->BlockList
);
441 Hive
->FileSize
+= REG_BLOCK_SIZE
;
444 BinCell
= (PHBIN
)Hive
->BlockList
[0];
445 CmiCreateDefaultBinCell(BinCell
);
446 BinCell
->BinOffset
= 0;
448 /* Init root key cell */
449 RootKeyCell
= (PKEY_CELL
)((ULONG
)BinCell
+ REG_HBIN_DATA_OFFSET
);
450 CmiCreateDefaultRootKeyCell(RootKeyCell
, KeyName
);
451 Hive
->HiveHeader
->RootKeyOffset
= REG_HBIN_DATA_OFFSET
;
454 FreeCell
= (PCELL_HEADER
)((ULONG
)RootKeyCell
- RootKeyCell
->CellSize
);
455 FreeCell
->CellSize
= REG_BLOCK_SIZE
- (REG_HBIN_DATA_OFFSET
- RootKeyCell
->CellSize
);
457 Hive
->FreeList
[0] = FreeCell
;
458 Hive
->FreeListOffset
[0] = REG_HBIN_DATA_OFFSET
- RootKeyCell
->CellSize
;
459 Hive
->FreeListSize
++;
466 CmiCleanupHive(PREGISTRY_HIVE Hive
, BOOL Release
)
468 MmFreeMemory (Hive
->FreeListOffset
);
469 MmFreeMemory (Hive
->FreeList
);
470 MmFreeMemory (Hive
->BlockList
);
481 CmiGetBin (PREGISTRY_HIVE Hive
,
482 BLOCK_OFFSET BlockOffset
)
486 if (BlockOffset
== (ULONG
) -1)
489 BlockIndex
= BlockOffset
/ REG_BLOCK_SIZE
;
490 if (BlockIndex
>= Hive
->BlockListSize
)
493 return Hive
->BlockList
[BlockIndex
];
498 CmiMergeFree(PREGISTRY_HIVE RegistryHive
,
499 PCELL_HEADER FreeBlock
,
500 BLOCK_OFFSET FreeOffset
)
502 BLOCK_OFFSET BlockOffset
;
503 BLOCK_OFFSET BinOffset
;
509 DbgPrint((DPRINT_REGISTRY
, "CmiMergeFree(Block %lx Offset %lx Size %lx) called\n",
510 FreeBlock
, FreeOffset
, FreeBlock
->CellSize
));
512 Bin
= CmiGetBin (RegistryHive
, FreeOffset
);
516 DbgPrint((DPRINT_REGISTRY
, "Bin %p\n", Bin
));
518 BinOffset
= Bin
->BinOffset
;
519 BinSize
= Bin
->BinSize
;
520 DbgPrint((DPRINT_REGISTRY
, "Bin %p Offset %lx Size %lx\n", Bin
, BinOffset
, BinSize
));
522 for (i
= 0; i
< RegistryHive
->FreeListSize
; i
++)
524 BlockOffset
= RegistryHive
->FreeListOffset
[i
];
525 BlockSize
= RegistryHive
->FreeList
[i
]->CellSize
;
526 if (BlockOffset
> BinOffset
&&
527 BlockOffset
< BinOffset
+ BinSize
)
529 DbgPrint((DPRINT_REGISTRY
, "Free block: Offset %lx Size %lx\n",
530 BlockOffset
, BlockSize
));
532 if ((i
< (RegistryHive
->FreeListSize
- 1)) &&
533 (BlockOffset
+ BlockSize
== FreeOffset
) &&
534 (FreeOffset
+ FreeBlock
->CellSize
== RegistryHive
->FreeListOffset
[i
+ 1]))
536 DbgPrint((DPRINT_REGISTRY
, "Merge current block with previous and next block\n"));
538 RegistryHive
->FreeList
[i
]->CellSize
+=
539 (FreeBlock
->CellSize
+ RegistryHive
->FreeList
[i
+ 1]->CellSize
);
541 FreeBlock
->CellSize
= 0;
542 RegistryHive
->FreeList
[i
+ 1]->CellSize
= 0;
545 if ((i
+ 2) < RegistryHive
->FreeListSize
)
547 memmove (&RegistryHive
->FreeList
[i
+ 1],
548 &RegistryHive
->FreeList
[i
+ 2],
549 sizeof(RegistryHive
->FreeList
[0])
550 * (RegistryHive
->FreeListSize
- i
- 2));
551 memmove (&RegistryHive
->FreeListOffset
[i
+ 1],
552 &RegistryHive
->FreeListOffset
[i
+ 2],
553 sizeof(RegistryHive
->FreeListOffset
[0])
554 * (RegistryHive
->FreeListSize
- i
- 2));
556 RegistryHive
->FreeListSize
--;
560 else if (BlockOffset
+ BlockSize
== FreeOffset
)
562 DbgPrint((DPRINT_REGISTRY
, "Merge current block with previous block\n"));
564 RegistryHive
->FreeList
[i
]->CellSize
+= FreeBlock
->CellSize
;
565 FreeBlock
->CellSize
= 0;
569 else if (FreeOffset
+ FreeBlock
->CellSize
== BlockOffset
)
571 DbgPrint((DPRINT_REGISTRY
, "Merge current block with next block\n"));
573 FreeBlock
->CellSize
+= RegistryHive
->FreeList
[i
]->CellSize
;
574 RegistryHive
->FreeList
[i
]->CellSize
= 0;
575 RegistryHive
->FreeList
[i
] = FreeBlock
;
576 RegistryHive
->FreeListOffset
[i
] = FreeOffset
;
588 CmiAddFree(PREGISTRY_HIVE RegistryHive
,
589 PCELL_HEADER FreeBlock
,
590 BLOCK_OFFSET FreeOffset
,
591 BOOL MergeFreeBlocks
)
593 PCELL_HEADER
*tmpList
;
594 BLOCK_OFFSET
*tmpListOffset
;
599 assert(RegistryHive
);
602 DbgPrint((DPRINT_REGISTRY
, "FreeBlock %.08lx FreeOffset %.08lx\n",
603 FreeBlock
, FreeOffset
));
605 /* Merge free blocks */
606 if (MergeFreeBlocks
== TRUE
)
608 if (CmiMergeFree(RegistryHive
, FreeBlock
, FreeOffset
))
612 if ((RegistryHive
->FreeListSize
+ 1) > RegistryHive
->FreeListMax
)
614 tmpList
= MmAllocateMemory (sizeof(PCELL_HEADER
) * (RegistryHive
->FreeListMax
+ 32));
620 tmpListOffset
= MmAllocateMemory (sizeof(BLOCK_OFFSET
) * (RegistryHive
->FreeListMax
+ 32));
621 if (tmpListOffset
== NULL
)
623 MmFreeMemory (tmpList
);
627 if (RegistryHive
->FreeListMax
)
630 RegistryHive
->FreeList
,
631 sizeof(PCELL_HEADER
) * (RegistryHive
->FreeListMax
));
632 memmove (tmpListOffset
,
633 RegistryHive
->FreeListOffset
,
634 sizeof(BLOCK_OFFSET
) * (RegistryHive
->FreeListMax
));
635 MmFreeMemory (RegistryHive
->FreeList
);
636 MmFreeMemory (RegistryHive
->FreeListOffset
);
638 RegistryHive
->FreeList
= tmpList
;
639 RegistryHive
->FreeListOffset
= tmpListOffset
;
640 RegistryHive
->FreeListMax
+= 32;
643 /* Add new offset to free list, maintaining list in ascending order */
644 if ((RegistryHive
->FreeListSize
== 0)
645 || (RegistryHive
->FreeListOffset
[RegistryHive
->FreeListSize
-1] < FreeOffset
))
647 /* Add to end of list */
648 RegistryHive
->FreeList
[RegistryHive
->FreeListSize
] = FreeBlock
;
649 RegistryHive
->FreeListOffset
[RegistryHive
->FreeListSize
++] = FreeOffset
;
651 else if (RegistryHive
->FreeListOffset
[0] > FreeOffset
)
653 /* Add to begin of list */
654 memmove (&RegistryHive
->FreeList
[1],
655 &RegistryHive
->FreeList
[0],
656 sizeof(RegistryHive
->FreeList
[0]) * RegistryHive
->FreeListSize
);
657 memmove (&RegistryHive
->FreeListOffset
[1],
658 &RegistryHive
->FreeListOffset
[0],
659 sizeof(RegistryHive
->FreeListOffset
[0]) * RegistryHive
->FreeListSize
);
660 RegistryHive
->FreeList
[0] = FreeBlock
;
661 RegistryHive
->FreeListOffset
[0] = FreeOffset
;
662 RegistryHive
->FreeListSize
++;
666 /* Search where to insert */
668 maxInd
= RegistryHive
->FreeListSize
- 1;
669 while ((maxInd
- minInd
) > 1)
671 medInd
= (minInd
+ maxInd
) / 2;
672 if (RegistryHive
->FreeListOffset
[medInd
] > FreeOffset
)
678 /* Insert before maxInd */
679 memmove (&RegistryHive
->FreeList
[maxInd
+1],
680 &RegistryHive
->FreeList
[maxInd
],
681 sizeof(RegistryHive
->FreeList
[0]) * (RegistryHive
->FreeListSize
- minInd
));
682 memmove (&RegistryHive
->FreeListOffset
[maxInd
+ 1],
683 &RegistryHive
->FreeListOffset
[maxInd
],
684 sizeof(RegistryHive
->FreeListOffset
[0]) * (RegistryHive
->FreeListSize
-minInd
));
685 RegistryHive
->FreeList
[maxInd
] = FreeBlock
;
686 RegistryHive
->FreeListOffset
[maxInd
] = FreeOffset
;
687 RegistryHive
->FreeListSize
++;
695 CmiAddBin(PREGISTRY_HIVE RegistryHive
,
698 PBLOCK_OFFSET NewBlockOffset
)
700 PCELL_HEADER tmpBlock
;
706 BinSize
= BlockCount
* REG_BLOCK_SIZE
;
707 tmpBin
= AllocateMbMemory (BinSize
);
712 memset (tmpBin
, 0, BinSize
);
714 tmpBin
->HeaderId
= REG_BIN_ID
;
715 tmpBin
->BinOffset
= RegistryHive
->FileSize
- REG_BLOCK_SIZE
;
716 RegistryHive
->FileSize
+= BinSize
;
717 tmpBin
->BinSize
= BinSize
;
718 tmpBin
->DateModified
= 0ULL;
719 tmpBin
->MemAlloc
= 0;
721 /* Increase size of list of blocks */
722 BlockList
= MmAllocateMemory (sizeof(PHBIN
) * (RegistryHive
->BlockListSize
+ BlockCount
));
723 if (BlockList
== NULL
)
728 if (RegistryHive
->BlockListSize
> 0)
731 RegistryHive
->BlockList
,
732 sizeof(PHBIN
) * RegistryHive
->BlockListSize
);
733 MmFreeMemory (RegistryHive
->BlockList
);
736 RegistryHive
->BlockList
= BlockList
;
737 for (i
= 0; i
< BlockCount
; i
++)
738 RegistryHive
->BlockList
[RegistryHive
->BlockListSize
+ i
] = tmpBin
;
739 RegistryHive
->BlockListSize
+= BlockCount
;
741 /* Initialize a free block in this heap : */
742 tmpBlock
= (PCELL_HEADER
)((ULONG
) tmpBin
+ REG_HBIN_DATA_OFFSET
);
743 tmpBlock
->CellSize
= (REG_BLOCK_SIZE
- REG_HBIN_DATA_OFFSET
);
745 *NewBlock
= (PVOID
) tmpBlock
;
748 *NewBlockOffset
= tmpBin
->BinOffset
+ REG_HBIN_DATA_OFFSET
;
755 CmiAllocateCell (PREGISTRY_HIVE RegistryHive
,
758 PBLOCK_OFFSET pBlockOffset
)
760 PCELL_HEADER NewBlock
;
765 /* Round to 16 bytes multiple */
766 CellSize
= ROUND_UP(CellSize
, 16);
768 /* first search in free blocks */
770 for (i
= 0; i
< RegistryHive
->FreeListSize
; i
++)
772 if (RegistryHive
->FreeList
[i
]->CellSize
>= CellSize
)
774 NewBlock
= RegistryHive
->FreeList
[i
];
776 *pBlockOffset
= RegistryHive
->FreeListOffset
[i
];
778 if ((i
+ 1) < RegistryHive
->FreeListSize
)
780 memmove (&RegistryHive
->FreeList
[i
],
781 &RegistryHive
->FreeList
[i
+ 1],
782 sizeof(RegistryHive
->FreeList
[0])
783 * (RegistryHive
->FreeListSize
- i
- 1));
784 memmove (&RegistryHive
->FreeListOffset
[i
],
785 &RegistryHive
->FreeListOffset
[i
+ 1],
786 sizeof(RegistryHive
->FreeListOffset
[0])
787 * (RegistryHive
->FreeListSize
- i
- 1));
789 RegistryHive
->FreeListSize
--;
794 /* Need to extend hive file */
795 if (NewBlock
== NULL
)
797 /* Add a new block */
798 if (!CmiAddBin(RegistryHive
,
799 ((sizeof(HBIN
) + CellSize
- 1) / REG_BLOCK_SIZE
) + 1,
800 (PVOID
*)(PVOID
)&NewBlock
,
807 /* Split the block in two parts */
808 if (NewBlock
->CellSize
> CellSize
)
810 NewBlock
= (PCELL_HEADER
) ((ULONG
)NewBlock
+ CellSize
);
811 NewBlock
->CellSize
= ((PCELL_HEADER
) (*Block
))->CellSize
- CellSize
;
812 CmiAddFree (RegistryHive
,
814 *pBlockOffset
+ CellSize
,
817 else if (NewBlock
->CellSize
< CellSize
)
822 memset(*Block
, 0, CellSize
);
823 ((PCELL_HEADER
)(*Block
))->CellSize
= -CellSize
;
830 CmiGetCell (PREGISTRY_HIVE Hive
,
831 BLOCK_OFFSET BlockOffset
)
836 if (BlockOffset
== (ULONG
) -1)
839 BlockIndex
= BlockOffset
/ REG_BLOCK_SIZE
;
840 if (BlockIndex
>= Hive
->BlockListSize
)
843 Bin
= Hive
->BlockList
[BlockIndex
];
847 return (PVOID
)((ULONG
)Bin
+ (BlockOffset
- Bin
->BinOffset
));
852 CmiAllocateHashTableCell (PREGISTRY_HIVE Hive
,
853 PBLOCK_OFFSET HBOffset
,
856 PHASH_TABLE_CELL HashCell
;
860 NewHashSize
= sizeof(HASH_TABLE_CELL
) +
861 (SubKeyCount
* sizeof(HASH_RECORD
));
862 Status
= CmiAllocateCell (Hive
,
864 (PVOID
*)(PVOID
)&HashCell
,
866 if ((HashCell
== NULL
) || (Status
== FALSE
))
871 HashCell
->Id
= REG_HASH_TABLE_BLOCK_ID
;
872 HashCell
->HashTableSize
= SubKeyCount
;
879 CmiAddKeyToParentHashTable (PREGISTRY_HIVE Hive
,
880 BLOCK_OFFSET ParentKeyOffset
,
881 PKEY_CELL NewKeyCell
,
882 BLOCK_OFFSET NKBOffset
)
884 PHASH_TABLE_CELL HashBlock
;
885 PKEY_CELL ParentKeyCell
;
888 ParentKeyCell
= CmiGetCell (Hive
, ParentKeyOffset
);
889 if (ParentKeyCell
== NULL
)
891 DbgPrint((DPRINT_REGISTRY
, "CmiGetCell() failed\n"));
895 HashBlock
=CmiGetCell (Hive
, ParentKeyCell
->HashTableOffset
);
896 if (HashBlock
== NULL
)
898 DbgPrint((DPRINT_REGISTRY
, "CmiGetCell() failed\n"));
902 for (i
= 0; i
< HashBlock
->HashTableSize
; i
++)
904 if (HashBlock
->Table
[i
].KeyOffset
== 0)
906 HashBlock
->Table
[i
].KeyOffset
= NKBOffset
;
907 memcpy (&HashBlock
->Table
[i
].HashValue
,
909 min(NewKeyCell
->NameSize
, sizeof(ULONG
)));
910 ParentKeyCell
->NumberOfSubKeys
++;
920 CmiAllocateValueListCell (PREGISTRY_HIVE Hive
,
921 PBLOCK_OFFSET ValueListOffset
,
924 PVALUE_LIST_CELL ValueListCell
;
928 ValueListSize
= sizeof(VALUE_LIST_CELL
) +
929 (ValueCount
* sizeof(BLOCK_OFFSET
));
930 Status
= CmiAllocateCell (Hive
,
932 (PVOID
)&ValueListCell
,
934 if ((ValueListCell
== NULL
) || (Status
== FALSE
))
936 DbgPrint((DPRINT_REGISTRY
, "CmiAllocateCell() failed\n"));
945 CmiAllocateValueCell(PREGISTRY_HIVE Hive
,
946 PVALUE_CELL
*ValueCell
,
947 BLOCK_OFFSET
*ValueCellOffset
,
950 PVALUE_CELL NewValueCell
;
953 BOOLEAN Packable
= TRUE
;
956 NameSize
= (ValueName
== NULL
) ? 0 : wcslen (ValueName
);
957 for (i
= 0; i
< NameSize
; i
++)
959 if (ValueName
[i
] & 0xFF00)
961 NameSize
*= sizeof(WCHAR
);
966 Status
= CmiAllocateCell (Hive
,
967 sizeof(VALUE_CELL
) + NameSize
,
968 (PVOID
*)(PVOID
)&NewValueCell
,
970 if ((NewValueCell
== NULL
) || (Status
== FALSE
))
972 DbgPrint((DPRINT_REGISTRY
, "CmiAllocateCell() failed\n"));
976 NewValueCell
->Id
= REG_VALUE_CELL_ID
;
977 NewValueCell
->NameSize
= NameSize
;
978 NewValueCell
->Flags
= 0;
983 for (i
= 0; i
< NameSize
; i
++)
985 ((PCHAR
)NewValueCell
->Name
)[i
] = (CHAR
)ValueName
[i
];
987 NewValueCell
->Flags
|= REG_VALUE_NAME_PACKED
;
991 memcpy (NewValueCell
->Name
,
996 NewValueCell
->DataType
= 0;
997 NewValueCell
->DataSize
= 0;
998 NewValueCell
->DataOffset
= -1;
1000 *ValueCell
= NewValueCell
;
1007 CmiAddValueToKeyValueList(PREGISTRY_HIVE Hive
,
1008 BLOCK_OFFSET KeyCellOffset
,
1009 BLOCK_OFFSET ValueCellOffset
)
1011 PVALUE_LIST_CELL ValueListCell
;
1014 KeyCell
= CmiGetCell (Hive
, KeyCellOffset
);
1015 if (KeyCell
== NULL
)
1017 DbgPrint((DPRINT_REGISTRY
, "CmiGetCell() failed\n"));
1021 ValueListCell
= CmiGetCell (Hive
, KeyCell
->ValueListOffset
);
1022 if (ValueListCell
== NULL
)
1024 DbgPrint((DPRINT_REGISTRY
, "CmiGetCell() failed\n"));
1028 ValueListCell
->ValueOffset
[KeyCell
->NumberOfValues
] = ValueCellOffset
;
1029 KeyCell
->NumberOfValues
++;
1035 CmiExportValue (PREGISTRY_HIVE Hive
,
1036 BLOCK_OFFSET KeyCellOffset
,
1040 BLOCK_OFFSET ValueCellOffset
;
1041 BLOCK_OFFSET DataCellOffset
;
1042 PVALUE_CELL ValueCell
;
1043 PDATA_CELL DataCell
;
1048 DbgPrint((DPRINT_REGISTRY
, "CmiExportValue('%S') called\n",
1049 (Value
== NULL
) ? "<default>" : (PCHAR
)Value
->Name
));
1050 DbgPrint((DPRINT_REGISTRY
, "DataSize %lu\n",
1051 (Value
== NULL
) ? Key
->DataSize
: Value
->DataSize
));
1053 /* Allocate value cell */
1054 if (!CmiAllocateValueCell(Hive
, &ValueCell
, &ValueCellOffset
, (Value
== NULL
) ? NULL
: Value
->Name
))
1059 if (!CmiAddValueToKeyValueList(Hive
, KeyCellOffset
, ValueCellOffset
))
1066 DataType
= Key
->DataType
;
1067 DataSize
= Key
->DataSize
;
1072 DataType
= Value
->DataType
;
1073 DataSize
= Value
->DataSize
;
1077 if (DataSize
<= sizeof(BLOCK_OFFSET
))
1079 ValueCell
->DataSize
= DataSize
| REG_DATA_IN_OFFSET
;
1080 ValueCell
->DataType
= DataType
;
1081 memcpy (&ValueCell
->DataOffset
,
1087 /* Allocate data cell */
1088 if (!CmiAllocateCell (Hive
,
1089 sizeof(CELL_HEADER
) + DataSize
,
1090 (PVOID
*)(PVOID
)&DataCell
,
1096 ValueCell
->DataOffset
= DataCellOffset
;
1097 ValueCell
->DataSize
= DataSize
;
1098 ValueCell
->DataType
= DataType
;
1100 memcpy (DataCell
->Data
,
1110 CmiExportSubKey (PREGISTRY_HIVE Hive
,
1111 BLOCK_OFFSET ParentKeyOffset
,
1112 FRLDRHKEY ParentKey
,
1115 BLOCK_OFFSET NKBOffset
;
1116 PKEY_CELL NewKeyCell
;
1123 BOOLEAN Packable
= TRUE
;
1127 DbgPrint((DPRINT_REGISTRY
, "CmiExportSubKey('%S') called\n", Key
->Name
));
1129 /* Don't export links */
1130 if (Key
->DataType
== REG_LINK
)
1133 NameSize
= (Key
->NameSize
- sizeof(WCHAR
)) / sizeof(WCHAR
);
1134 for (i
= 0; i
< NameSize
; i
++)
1136 if (Key
->Name
[i
] & 0xFF00)
1139 NameSize
*= sizeof(WCHAR
);
1144 /* Allocate key cell */
1145 KeyCellSize
= sizeof(KEY_CELL
) + NameSize
;
1146 if (!CmiAllocateCell (Hive
, KeyCellSize
, (PVOID
)&NewKeyCell
, &NKBOffset
))
1148 DbgPrint((DPRINT_REGISTRY
, "CmiAllocateCell() failed\n"));
1152 /* Initialize key cell */
1153 NewKeyCell
->Id
= REG_KEY_CELL_ID
;
1154 NewKeyCell
->Flags
= 0;
1155 NewKeyCell
->LastWriteTime
= 0ULL;
1156 NewKeyCell
->ParentKeyOffset
= ParentKeyOffset
;
1157 NewKeyCell
->NumberOfSubKeys
= 0;
1158 NewKeyCell
->HashTableOffset
= -1;
1159 NewKeyCell
->NumberOfValues
= 0;
1160 NewKeyCell
->ValueListOffset
= -1;
1161 NewKeyCell
->SecurityKeyOffset
= -1;
1162 NewKeyCell
->ClassNameOffset
= -1;
1163 NewKeyCell
->NameSize
= NameSize
;
1164 NewKeyCell
->ClassSize
= 0;
1167 for (i
= 0; i
< NameSize
; i
++)
1169 ((PCHAR
)NewKeyCell
->Name
)[i
] = (CHAR
)Key
->Name
[i
];
1171 NewKeyCell
->Flags
|= REG_KEY_NAME_PACKED
;
1176 memcpy (NewKeyCell
->Name
,
1181 /* Add key cell to the parent key's hash table */
1182 if (!CmiAddKeyToParentHashTable (Hive
,
1187 DbgPrint((DPRINT_REGISTRY
, "CmiAddKeyToParentHashTable() failed\n"));
1191 ValueCount
= RegGetValueCount (Key
);
1192 DbgPrint((DPRINT_REGISTRY
, "ValueCount: %u\n", ValueCount
));
1195 /* Allocate value list cell */
1196 if (!CmiAllocateValueListCell (Hive
,
1197 &NewKeyCell
->ValueListOffset
,
1200 DbgPrint((DPRINT_REGISTRY
, "CmiAllocateValueListCell() failed\n"));
1204 if (Key
->DataSize
!= 0)
1206 if (!CmiExportValue (Hive
, NKBOffset
, Key
, NULL
))
1210 /* Enumerate values */
1211 Entry
= Key
->ValueList
.Flink
;
1212 while (Entry
!= &Key
->ValueList
)
1214 Value
= CONTAINING_RECORD(Entry
,
1218 if (!CmiExportValue (Hive
, NKBOffset
, Key
, Value
))
1221 Entry
= Entry
->Flink
;
1225 SubKeyCount
= RegGetSubKeyCount (Key
);
1226 DbgPrint((DPRINT_REGISTRY
, "SubKeyCount: %u\n", SubKeyCount
));
1227 if (SubKeyCount
> 0)
1229 /* Allocate hash table cell */
1230 if (!CmiAllocateHashTableCell (Hive
,
1231 &NewKeyCell
->HashTableOffset
,
1234 DbgPrint((DPRINT_REGISTRY
, "CmiAllocateHashTableCell() failed\n"));
1238 /* Enumerate subkeys */
1239 Entry
= Key
->SubKeyList
.Flink
;
1240 while (Entry
!= &Key
->SubKeyList
)
1242 SubKey
= CONTAINING_RECORD(Entry
,
1246 if (!CmiExportSubKey (Hive
, NKBOffset
, Key
, SubKey
))
1249 Entry
= Entry
->Flink
;
1258 CmiCalcHiveChecksum (PREGISTRY_HIVE Hive
)
1264 Buffer
= (ULONG
*)Hive
->HiveHeader
;
1266 for (i
= 0; i
< 127; i
++)
1269 Hive
->HiveHeader
->Checksum
= Sum
;
1274 CmiExportHive (PREGISTRY_HIVE Hive
,
1285 DbgPrint((DPRINT_REGISTRY
, "CmiExportHive(%x, '%S') called\n", Hive
, KeyName
));
1287 if (RegOpenKey (NULL
, KeyName
, &Key
) != ERROR_SUCCESS
)
1289 DbgPrint((DPRINT_REGISTRY
, "RegOpenKey() failed\n"));
1293 KeyCell
= CmiGetCell (Hive
, Hive
->HiveHeader
->RootKeyOffset
);
1294 if (KeyCell
== NULL
)
1296 DbgPrint((DPRINT_REGISTRY
, "CmiGetBlock() failed\n"));
1300 ValueCount
= RegGetValueCount (Key
);
1301 DbgPrint((DPRINT_REGISTRY
, "ValueCount: %u\n", ValueCount
));
1304 /* Allocate value list cell */
1305 if (!CmiAllocateValueListCell (Hive
,
1306 &KeyCell
->ValueListOffset
,
1309 DbgPrint((DPRINT_REGISTRY
, "CmiAllocateValueListCell() failed\n"));
1313 if (Key
->DataSize
!= 0)
1315 if (!CmiExportValue (Hive
, Hive
->HiveHeader
->RootKeyOffset
, Key
, NULL
))
1319 /* Enumerate values */
1320 Entry
= Key
->ValueList
.Flink
;
1321 while (Entry
!= &Key
->ValueList
)
1323 Value
= CONTAINING_RECORD(Entry
,
1327 if (!CmiExportValue (Hive
, Hive
->HiveHeader
->RootKeyOffset
, Key
, Value
))
1330 Entry
= Entry
->Flink
;
1334 SubKeyCount
= RegGetSubKeyCount (Key
);
1335 DbgPrint((DPRINT_REGISTRY
, "SubKeyCount: %u\n", SubKeyCount
));
1336 if (SubKeyCount
> 0)
1338 /* Allocate hash table cell */
1339 if (!CmiAllocateHashTableCell (Hive
,
1340 &KeyCell
->HashTableOffset
,
1343 DbgPrint((DPRINT_REGISTRY
, "CmiAllocateHashTableCell() failed\n"));
1347 /* Enumerate subkeys */
1348 Entry
= Key
->SubKeyList
.Flink
;
1349 while (Entry
!= &Key
->SubKeyList
)
1351 SubKey
= CONTAINING_RECORD(Entry
,
1355 if (!CmiExportSubKey (Hive
, Hive
->HiveHeader
->RootKeyOffset
, Key
, SubKey
))
1358 Entry
= Entry
->Flink
;
1362 CmiCalcHiveChecksum (Hive
);
1369 RegImportValue (PHBIN RootBin
,
1370 PVALUE_CELL ValueCell
,
1373 PDATA_CELL DataCell
;
1379 if (ValueCell
->CellSize
>= 0 || ValueCell
->Id
!= REG_VALUE_CELL_ID
)
1381 DbgPrint((DPRINT_REGISTRY
, "Invalid key cell!\n"));
1385 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1387 wName
= MmAllocateMemory ((ValueCell
->NameSize
+ 1)*sizeof(WCHAR
));
1388 for (i
= 0; i
< ValueCell
->NameSize
; i
++)
1390 wName
[i
] = ((PCHAR
)ValueCell
->Name
)[i
];
1392 wName
[ValueCell
->NameSize
] = 0;
1396 wName
= MmAllocateMemory (ValueCell
->NameSize
+ sizeof(WCHAR
));
1399 ValueCell
->NameSize
);
1400 wName
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
1403 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1405 DbgPrint((DPRINT_REGISTRY
, "ValueName: '%S'\n", wName
));
1406 DbgPrint((DPRINT_REGISTRY
, "DataSize: %u\n", DataSize
));
1408 if (DataSize
<= sizeof(BLOCK_OFFSET
) && (ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1410 Error
= RegSetValue(Key
,
1412 ValueCell
->DataType
,
1413 (PCHAR
)&ValueCell
->DataOffset
,
1415 if (Error
!= ERROR_SUCCESS
)
1417 DbgPrint((DPRINT_REGISTRY
, "RegSetValue() failed!\n"));
1418 MmFreeMemory (wName
);
1424 DataCell
= (PDATA_CELL
)((PUCHAR
)RootBin
+ ValueCell
->DataOffset
);
1425 DbgPrint((DPRINT_REGISTRY
, "DataCell: %x\n", DataCell
));
1427 if (DataCell
->CellSize
>= 0)
1429 DbgPrint((DPRINT_REGISTRY
, "Invalid data cell size!\n"));
1430 MmFreeMemory (wName
);
1434 Error
= RegSetValue (Key
,
1436 ValueCell
->DataType
,
1440 if (Error
!= ERROR_SUCCESS
)
1442 DbgPrint((DPRINT_REGISTRY
, "RegSetValue() failed!\n"));
1443 MmFreeMemory (wName
);
1448 MmFreeMemory (wName
);
1455 RegImportSubKey(PHBIN RootBin
,
1457 FRLDRHKEY ParentKey
)
1459 PHASH_TABLE_CELL HashCell
;
1460 PKEY_CELL SubKeyCell
;
1461 PVALUE_LIST_CELL ValueListCell
;
1462 PVALUE_CELL ValueCell
= NULL
;
1469 DbgPrint((DPRINT_REGISTRY
, "KeyCell: %x\n", KeyCell
));
1470 DbgPrint((DPRINT_REGISTRY
, "KeyCell->CellSize: %x\n", KeyCell
->CellSize
));
1471 DbgPrint((DPRINT_REGISTRY
, "KeyCell->Id: %x\n", KeyCell
->Id
));
1472 if (KeyCell
->Id
!= REG_KEY_CELL_ID
|| KeyCell
->CellSize
>= 0)
1474 DbgPrint((DPRINT_REGISTRY
, "Invalid key cell id!\n"));
1478 if (KeyCell
->Flags
& REG_KEY_NAME_PACKED
)
1480 wName
= MmAllocateMemory ((KeyCell
->NameSize
+ 1) * sizeof(WCHAR
));
1481 for (i
= 0; i
< KeyCell
->NameSize
; i
++)
1483 wName
[i
] = ((PCHAR
)KeyCell
->Name
)[i
];
1485 wName
[KeyCell
->NameSize
] = 0;
1489 wName
= MmAllocateMemory (KeyCell
->NameSize
+ sizeof(WCHAR
));
1493 wName
[KeyCell
->NameSize
/sizeof(WCHAR
)] = 0;
1496 DbgPrint((DPRINT_REGISTRY
, "KeyName: '%S'\n", wName
));
1498 /* Create new sub key */
1499 Error
= RegCreateKey (ParentKey
,
1502 MmFreeMemory (wName
);
1503 if (Error
!= ERROR_SUCCESS
)
1505 DbgPrint((DPRINT_REGISTRY
, "RegCreateKey() failed!\n"));
1508 DbgPrint((DPRINT_REGISTRY
, "Subkeys: %u\n", KeyCell
->NumberOfSubKeys
));
1509 DbgPrint((DPRINT_REGISTRY
, "Values: %u\n", KeyCell
->NumberOfValues
));
1511 /* Enumerate and add values */
1512 if (KeyCell
->NumberOfValues
> 0)
1514 ValueListCell
= (PVALUE_LIST_CELL
)((PUCHAR
)RootBin
+ KeyCell
->ValueListOffset
);
1515 DbgPrint((DPRINT_REGISTRY
, "ValueListCell: %x\n", ValueListCell
));
1517 for (i
= 0; i
< KeyCell
->NumberOfValues
; i
++)
1519 DbgPrint((DPRINT_REGISTRY
, "ValueOffset[%d]: %x\n", i
, ValueListCell
->ValueOffset
[i
]));
1521 ValueCell
= (PVALUE_CELL
)((PUCHAR
)RootBin
+ ValueListCell
->ValueOffset
[i
]);
1523 DbgPrint((DPRINT_REGISTRY
, "ValueCell[%d]: %x\n", i
, ValueCell
));
1525 if (!RegImportValue(RootBin
, ValueCell
, SubKey
))
1530 /* Enumerate and add subkeys */
1531 if (KeyCell
->NumberOfSubKeys
> 0)
1533 HashCell
= (PHASH_TABLE_CELL
)((PUCHAR
)RootBin
+ KeyCell
->HashTableOffset
);
1534 DbgPrint((DPRINT_REGISTRY
, "HashCell: %x\n", HashCell
));
1536 for (i
= 0; i
< KeyCell
->NumberOfSubKeys
; i
++)
1538 DbgPrint((DPRINT_REGISTRY
, "KeyOffset[%d]: %x\n", i
, HashCell
->Table
[i
].KeyOffset
));
1540 SubKeyCell
= (PKEY_CELL
)((PUCHAR
)RootBin
+ HashCell
->Table
[i
].KeyOffset
);
1542 DbgPrint((DPRINT_REGISTRY
, "SubKeyCell[%d]: %x\n", i
, SubKeyCell
));
1544 if (!RegImportSubKey(RootBin
, SubKeyCell
, SubKey
))
1554 RegImportBinaryHive(PCHAR ChunkBase
,
1557 PHIVE_HEADER HiveHeader
;
1560 PHASH_TABLE_CELL HashCell
;
1561 PKEY_CELL SubKeyCell
;
1562 FRLDRHKEY SystemKey
;
1566 DbgPrint((DPRINT_REGISTRY
, "RegImportBinaryHive(%x, %u) called\n",ChunkBase
,ChunkSize
));
1568 HiveHeader
= (PHIVE_HEADER
)ChunkBase
;
1569 DbgPrint((DPRINT_REGISTRY
, "HiveHeader: %x\n", HiveHeader
));
1570 if (HiveHeader
->BlockId
!= REG_HIVE_ID
)
1572 DbgPrint((DPRINT_REGISTRY
, "Invalid hive id!\n"));
1576 RootBin
= (PHBIN
)((ULONG
)HiveHeader
+ REG_BLOCK_SIZE
);
1577 DbgPrint((DPRINT_REGISTRY
, "RootBin: %x\n", RootBin
));
1578 if (RootBin
->HeaderId
!= REG_BIN_ID
|| RootBin
->BinSize
== 0)
1580 DbgPrint((DPRINT_REGISTRY
, "Invalid bin id!\n"));
1584 KeyCell
= (PKEY_CELL
)((ULONG
)RootBin
+ REG_HBIN_DATA_OFFSET
);
1585 DbgPrint((DPRINT_REGISTRY
, "KeyCell: %x\n", KeyCell
));
1586 DbgPrint((DPRINT_REGISTRY
, "KeyCell->CellSize: %x\n", KeyCell
->CellSize
));
1587 DbgPrint((DPRINT_REGISTRY
, "KeyCell->Id: %x\n", KeyCell
->Id
));
1588 if (KeyCell
->Id
!= REG_KEY_CELL_ID
|| KeyCell
->CellSize
>= 0)
1590 DbgPrint((DPRINT_REGISTRY
, "Invalid key cell id!\n"));
1594 DbgPrint((DPRINT_REGISTRY
, "Subkeys: %u\n", KeyCell
->NumberOfSubKeys
));
1595 DbgPrint((DPRINT_REGISTRY
, "Values: %u\n", KeyCell
->NumberOfValues
));
1597 /* Open 'System' key */
1598 Error
= RegOpenKey(NULL
,
1599 L
"\\Registry\\Machine\\SYSTEM",
1601 if (Error
!= ERROR_SUCCESS
)
1603 DbgPrint((DPRINT_REGISTRY
, "Failed to open 'system' key!\n"));
1607 /* Enumerate and add subkeys */
1608 if (KeyCell
->NumberOfSubKeys
> 0)
1610 HashCell
= (PHASH_TABLE_CELL
)((ULONG
)RootBin
+ KeyCell
->HashTableOffset
);
1611 DbgPrint((DPRINT_REGISTRY
, "HashCell: %x\n", HashCell
));
1613 for (i
= 0; i
< KeyCell
->NumberOfSubKeys
; i
++)
1615 DbgPrint((DPRINT_REGISTRY
, "KeyOffset[%d]: %x\n", i
, HashCell
->Table
[i
].KeyOffset
));
1617 SubKeyCell
= (PKEY_CELL
)((ULONG
)RootBin
+ HashCell
->Table
[i
].KeyOffset
);
1619 DbgPrint((DPRINT_REGISTRY
, "SubKeyCell[%d]: %x\n", i
, SubKeyCell
));
1621 if (!RegImportSubKey(RootBin
, SubKeyCell
, SystemKey
))
1631 RegExportBinaryHive(PCWSTR KeyName
,
1635 PREGISTRY_HIVE Hive
;
1637 DbgPrint((DPRINT_REGISTRY
, "Creating binary hardware hive\n"));
1640 InitMbMemory (ChunkBase
);
1642 Hive
= CmiCreateHive (KeyName
);
1646 if (!CmiExportHive (Hive
, KeyName
))
1648 CmiCleanupHive (Hive
, TRUE
);
1652 CmiCleanupHive (Hive
, FALSE
);
1654 *ChunkSize
= GetMbAllocatedSize ();