2 * PROJECT: registry manipulation library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
5 * Copyright 2001 - 2005 Eric Kohl
13 * @name HvpVerifyHiveHeader
15 * Internal function to verify that a hive header has valid format.
20 PHBASE_BLOCK HiveHeader
)
22 if (HiveHeader
->Signature
!= HV_SIGNATURE
||
23 HiveHeader
->Major
!= HV_MAJOR_VER
||
24 HiveHeader
->Minor
> HV_MINOR_VER
||
25 HiveHeader
->Type
!= HV_TYPE_PRIMARY
||
26 HiveHeader
->Format
!= HV_FORMAT_MEMORY
||
27 HiveHeader
->Cluster
!= 1 ||
28 HiveHeader
->Sequence1
!= HiveHeader
->Sequence2
||
29 HvpHiveHeaderChecksum(HiveHeader
) != HiveHeader
->Checksum
)
31 DPRINT1("Verify Hive Header failed: \n");
32 DPRINT1(" Signature: 0x%x and not 0x%x, Major: 0x%x and not 0x%x\n",
33 HiveHeader
->Signature
, HV_SIGNATURE
, HiveHeader
->Major
, HV_MAJOR_VER
);
34 DPRINT1(" Minor: 0x%x is not > 0x%x, Type: 0x%x and not 0x%x\n",
35 HiveHeader
->Minor
, HV_MINOR_VER
, HiveHeader
->Type
, HV_TYPE_PRIMARY
);
36 DPRINT1(" Format: 0x%x and not 0x%x, Cluster: 0x%x and not 1\n",
37 HiveHeader
->Format
, HV_FORMAT_MEMORY
, HiveHeader
->Cluster
);
38 DPRINT1(" Sequence: 0x%x and not 0x%x, Checksum: 0x%x and not 0x%x\n",
39 HiveHeader
->Sequence1
, HiveHeader
->Sequence2
,
40 HvpHiveHeaderChecksum(HiveHeader
), HiveHeader
->Checksum
);
48 * @name HvpFreeHiveBins
50 * Internal function to free all bin storage associated with hive
62 for (Storage
= HvStable
; Storage
< HvMaxStorageType
; Storage
++)
65 for (i
= 0; i
< Hive
->Storage
[Storage
].Length
; i
++)
67 if (Hive
->Storage
[Storage
].BlockList
[i
].Bin
== (ULONG_PTR
)NULL
)
69 if (Hive
->Storage
[Storage
].BlockList
[i
].Bin
!= (ULONG_PTR
)Bin
)
71 Bin
= (PHBIN
)Hive
->Storage
[Storage
].BlockList
[i
].Bin
;
72 Hive
->Free((PHBIN
)Hive
->Storage
[Storage
].BlockList
[i
].Bin
);
74 Hive
->Storage
[Storage
].BlockList
[i
].Bin
= (ULONG_PTR
)NULL
;
75 Hive
->Storage
[Storage
].BlockList
[i
].Block
= (ULONG_PTR
)NULL
;
78 if (Hive
->Storage
[Storage
].Length
)
79 Hive
->Free(Hive
->Storage
[Storage
].BlockList
);
86 * Internal helper function to initalize hive descriptor structure for
96 PHBASE_BLOCK HiveHeader
;
99 HiveHeader
= RegistryHive
->Allocate(sizeof(HBASE_BLOCK
), FALSE
);
100 if (HiveHeader
== NULL
)
101 return STATUS_NO_MEMORY
;
102 RtlZeroMemory(HiveHeader
, sizeof(HBASE_BLOCK
));
103 HiveHeader
->Signature
= HV_SIGNATURE
;
104 HiveHeader
->Major
= HV_MAJOR_VER
;
105 HiveHeader
->Minor
= HV_MINOR_VER
;
106 HiveHeader
->Type
= HV_TYPE_PRIMARY
;
107 HiveHeader
->Format
= HV_FORMAT_MEMORY
;
108 HiveHeader
->Cluster
= 1;
109 HiveHeader
->RootCell
= HCELL_NULL
;
110 HiveHeader
->Length
= HV_BLOCK_SIZE
;
111 HiveHeader
->Sequence1
= 1;
112 HiveHeader
->Sequence2
= 1;
113 /* FIXME: Fill in the file name */
114 HiveHeader
->Checksum
= HvpHiveHeaderChecksum(HiveHeader
);
116 RegistryHive
->HiveHeader
= HiveHeader
;
117 for (Index
= 0; Index
< 24; Index
++)
119 RegistryHive
->Storage
[HvStable
].FreeDisplay
[Index
] = HCELL_NULL
;
120 RegistryHive
->Storage
[HvVolatile
].FreeDisplay
[Index
] = HCELL_NULL
;
122 RtlInitializeBitMap(&RegistryHive
->DirtyVector
, NULL
, 0);
124 return STATUS_SUCCESS
;
128 * @name HvpInitializeMemoryHive
130 * Internal helper function to initalize hive descriptor structure for
131 * a hive stored in memory. The data of the hive are copied and it is
132 * prepared for read/write access.
138 HvpInitializeMemoryHive(
149 if (ChunkSize
< sizeof(HBASE_BLOCK
) ||
150 !HvpVerifyHiveHeader((PHBASE_BLOCK
)ChunkBase
))
152 DPRINT1("Registry is corrupt: ChunkSize %d < sizeof(HBASE_BLOCK) %d, "
153 "or HvpVerifyHiveHeader() failed\n", ChunkSize
, sizeof(HBASE_BLOCK
));
154 return STATUS_REGISTRY_CORRUPT
;
157 Hive
->HiveHeader
= Hive
->Allocate(sizeof(HBASE_BLOCK
), FALSE
);
158 if (Hive
->HiveHeader
== NULL
)
160 return STATUS_NO_MEMORY
;
162 RtlCopyMemory(Hive
->HiveHeader
, (PVOID
)ChunkBase
, sizeof(HBASE_BLOCK
));
165 * Build a block list from the in-memory chunk and copy the data as
169 Hive
->Storage
[HvStable
].Length
= (ChunkSize
/ HV_BLOCK_SIZE
) - 1;
170 Hive
->Storage
[HvStable
].BlockList
=
171 Hive
->Allocate(Hive
->Storage
[HvStable
].Length
*
172 sizeof(HMAP_ENTRY
), FALSE
);
173 if (Hive
->Storage
[HvStable
].BlockList
== NULL
)
175 DPRINT1("Allocating block list failed\n");
176 Hive
->Free(Hive
->HiveHeader
);
177 return STATUS_NO_MEMORY
;
180 for (BlockIndex
= 0; BlockIndex
< Hive
->Storage
[HvStable
].Length
; )
182 Bin
= (PHBIN
)((ULONG_PTR
)ChunkBase
+ (BlockIndex
+ 1) * HV_BLOCK_SIZE
);
183 if (Bin
->Signature
!= HV_BIN_SIGNATURE
||
184 (Bin
->Size
% HV_BLOCK_SIZE
) != 0)
186 Hive
->Free(Hive
->HiveHeader
);
187 Hive
->Free(Hive
->Storage
[HvStable
].BlockList
);
188 return STATUS_REGISTRY_CORRUPT
;
191 NewBin
= Hive
->Allocate(Bin
->Size
, TRUE
);
194 Hive
->Free(Hive
->HiveHeader
);
195 Hive
->Free(Hive
->Storage
[HvStable
].BlockList
);
196 return STATUS_NO_MEMORY
;
199 Hive
->Storage
[HvStable
].BlockList
[BlockIndex
].Bin
= (ULONG_PTR
)NewBin
;
200 Hive
->Storage
[HvStable
].BlockList
[BlockIndex
].Block
= (ULONG_PTR
)NewBin
;
202 RtlCopyMemory(NewBin
, Bin
, Bin
->Size
);
204 if (Bin
->Size
> HV_BLOCK_SIZE
)
206 for (i
= 1; i
< Bin
->Size
/ HV_BLOCK_SIZE
; i
++)
208 Hive
->Storage
[HvStable
].BlockList
[BlockIndex
+ i
].Bin
= (ULONG_PTR
)NewBin
;
209 Hive
->Storage
[HvStable
].BlockList
[BlockIndex
+ i
].Block
=
210 ((ULONG_PTR
)NewBin
+ (i
* HV_BLOCK_SIZE
));
214 BlockIndex
+= Bin
->Size
/ HV_BLOCK_SIZE
;
217 if (HvpCreateHiveFreeCellList(Hive
))
219 HvpFreeHiveBins(Hive
);
220 Hive
->Free(Hive
->HiveHeader
);
221 return STATUS_NO_MEMORY
;
224 BitmapSize
= ROUND_UP(Hive
->Storage
[HvStable
].Length
,
225 sizeof(ULONG
) * 8) / 8;
226 BitmapBuffer
= (PULONG
)Hive
->Allocate(BitmapSize
, TRUE
);
227 if (BitmapBuffer
== NULL
)
229 HvpFreeHiveBins(Hive
);
230 Hive
->Free(Hive
->HiveHeader
);
231 return STATUS_NO_MEMORY
;
234 RtlInitializeBitMap(&Hive
->DirtyVector
, BitmapBuffer
, BitmapSize
* 8);
235 RtlClearAllBits(&Hive
->DirtyVector
);
237 return STATUS_SUCCESS
;
241 * @name HvpInitializeMemoryInplaceHive
243 * Internal helper function to initalize hive descriptor structure for
244 * a hive stored in memory. The in-memory data of the hive are directly
245 * used and it is read-only accessible.
251 HvpInitializeMemoryInplaceHive(
256 if (ChunkSize
< sizeof(HBASE_BLOCK
) ||
257 !HvpVerifyHiveHeader((PHBASE_BLOCK
)ChunkBase
))
259 return STATUS_REGISTRY_CORRUPT
;
262 Hive
->HiveHeader
= (PHBASE_BLOCK
)ChunkBase
;
263 Hive
->ReadOnly
= TRUE
;
266 return STATUS_SUCCESS
;
272 * Allocate a new hive descriptor structure and intialize it.
274 * @param RegistryHive
275 * Output variable to store pointer to the hive descriptor.
277 * - HV_OPERATION_CREATE_HIVE
278 * Create a new hive for read/write access.
279 * - HV_OPERATION_MEMORY
280 * Load and copy in-memory hive for read/write access. The
281 * pointer to data passed to this routine can be freed after
282 * the function is executed.
283 * - HV_OPERATION_MEMORY_INPLACE
284 * Load an in-memory hive for read-only access. The pointer
285 * to data passed to this routine MUSTN'T be freed until
288 * Pointer to hive data.
290 * Size of passed hive data.
293 * STATUS_NO_MEMORY - A memory allocation failed.
294 * STATUS_REGISTRY_CORRUPT - Registry corruption was detected.
306 PALLOCATE_ROUTINE Allocate
,
308 PFILE_READ_ROUTINE FileRead
,
309 PFILE_WRITE_ROUTINE FileWrite
,
310 PFILE_SET_SIZE_ROUTINE FileSetSize
,
311 PFILE_FLUSH_ROUTINE FileFlush
,
312 IN PUNICODE_STRING FileName
)
315 PHHIVE Hive
= RegistryHive
;
318 * Create a new hive structure that will hold all the maintenance data.
321 RtlZeroMemory(Hive
, sizeof(HHIVE
));
323 Hive
->Allocate
= Allocate
;
325 Hive
->FileRead
= FileRead
;
326 Hive
->FileWrite
= FileWrite
;
327 Hive
->FileSetSize
= FileSetSize
;
328 Hive
->FileFlush
= FileFlush
;
332 case HV_OPERATION_CREATE_HIVE
:
333 Status
= HvpCreateHive(Hive
);
336 case HV_OPERATION_MEMORY
:
337 Status
= HvpInitializeMemoryHive(Hive
, ChunkBase
, ChunkSize
);
340 case HV_OPERATION_MEMORY_INPLACE
:
341 Status
= HvpInitializeMemoryInplaceHive(Hive
, ChunkBase
, ChunkSize
);
345 /* FIXME: A better return status value is needed */
346 Status
= STATUS_NOT_IMPLEMENTED
;
350 if (!NT_SUCCESS(Status
))
362 * Free all stroage and handles associated with hive descriptor.
369 if (!RegistryHive
->ReadOnly
)
371 /* Release hive bitmap */
372 if (RegistryHive
->DirtyVector
.Buffer
)
374 RegistryHive
->Free(RegistryHive
->DirtyVector
.Buffer
);
377 HvpFreeHiveBins(RegistryHive
);
380 RegistryHive
->Free(RegistryHive
);