3 * Copyright (C) 2006 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS hive maker
22 * FILE: tools/mkhive/cmi.c
23 * PURPOSE: Registry file manipulation routines
24 * PROGRAMMER: Hervé Poussineau
37 return (PVOID
)malloc((size_t)Size
);
52 IN PHHIVE RegistryHive
,
56 IN SIZE_T BufferLength
)
58 PCMHIVE CmHive
= (PCMHIVE
)RegistryHive
;
59 FILE *File
= CmHive
->FileHandles
[HFILE_TYPE_PRIMARY
];
60 if (fseek(File
, *FileOffset
, SEEK_SET
) != 0)
63 return (fread(Buffer
, 1, BufferLength
, File
) == BufferLength
);
69 IN PHHIVE RegistryHive
,
73 IN SIZE_T BufferLength
)
75 PCMHIVE CmHive
= (PCMHIVE
)RegistryHive
;
76 FILE *File
= CmHive
->FileHandles
[HFILE_TYPE_PRIMARY
];
77 if (fseek(File
, *FileOffset
, SEEK_SET
) != 0)
80 return (fwrite(Buffer
, 1, BufferLength
, File
) == BufferLength
);
86 IN PHHIVE RegistryHive
,
91 DPRINT1("CmpFileSetSize() unimplemented\n");
98 IN PHHIVE RegistryHive
,
100 PLARGE_INTEGER FileOffset
,
103 PCMHIVE CmHive
= (PCMHIVE
)RegistryHive
;
104 FILE *File
= CmHive
->FileHandles
[HFILE_TYPE_PRIMARY
];
105 return (fflush(File
) == 0);
115 RtlZeroMemory(Hive
, sizeof(*Hive
));
117 DPRINT("Hive 0x%p\n", Hive
);
119 Status
= HvInitialize(&Hive
->Hive
,
132 if (!NT_SUCCESS(Status
))
137 // HACK: See the HACK from r31253
138 if (!CmCreateRootNode(&Hive
->Hive
, Name
))
141 return STATUS_INSUFFICIENT_RESOURCES
;
144 /* Add the new hive to the hive list */
145 InsertTailList(&CmiHiveListHead
,
148 return STATUS_SUCCESS
;
152 CmiCreateSecurityKey(
155 IN PUCHAR Descriptor
,
156 IN ULONG DescriptorLength
)
158 HCELL_INDEX SecurityCell
;
160 PCM_KEY_SECURITY Security
;
162 Node
= (PCM_KEY_NODE
)HvGetCell(Hive
, Cell
);
163 SecurityCell
= HvAllocateCell(Hive
,
164 FIELD_OFFSET(CM_KEY_SECURITY
, Descriptor
) +
168 if (SecurityCell
== HCELL_NIL
)
170 HvReleaseCell(Hive
, Cell
);
171 return STATUS_INSUFFICIENT_RESOURCES
;
174 Node
->Security
= SecurityCell
;
175 Security
= (PCM_KEY_SECURITY
)HvGetCell(Hive
, SecurityCell
);
176 Security
->Signature
= CM_KEY_SECURITY_SIGNATURE
;
177 Security
->ReferenceCount
= 1;
178 Security
->DescriptorLength
= DescriptorLength
;
180 RtlMoveMemory(&Security
->Descriptor
,
184 Security
->Flink
= Security
->Blink
= SecurityCell
;
186 HvReleaseCell(Hive
, SecurityCell
);
187 HvReleaseCell(Hive
, Cell
);
189 return STATUS_SUCCESS
;
194 IN PCMHIVE RegistryHive
,
195 IN HCELL_INDEX ParentKeyCellOffset
,
196 IN PCUNICODE_STRING SubKeyName
,
197 IN BOOLEAN VolatileKey
,
198 OUT HCELL_INDEX
* pNKBOffset
)
200 HCELL_INDEX NKBOffset
;
201 PCM_KEY_NODE NewKeyCell
;
202 UNICODE_STRING KeyName
;
203 HSTORAGE_TYPE Storage
;
205 /* Skip leading path separator if present */
206 if (SubKeyName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
208 KeyName
.Buffer
= &SubKeyName
->Buffer
[1];
209 KeyName
.Length
= KeyName
.MaximumLength
= SubKeyName
->Length
- sizeof(WCHAR
);
213 KeyName
= *SubKeyName
;
216 Storage
= (VolatileKey
? Volatile
: Stable
);
218 NKBOffset
= HvAllocateCell(&RegistryHive
->Hive
,
219 FIELD_OFFSET(CM_KEY_NODE
, Name
) +
220 CmpNameSize(&RegistryHive
->Hive
, &KeyName
),
223 if (NKBOffset
== HCELL_NIL
)
225 return STATUS_INSUFFICIENT_RESOURCES
;
228 NewKeyCell
= (PCM_KEY_NODE
)HvGetCell(&RegistryHive
->Hive
, NKBOffset
);
229 if (NewKeyCell
== NULL
)
231 HvFreeCell(&RegistryHive
->Hive
, NKBOffset
);
232 return STATUS_INSUFFICIENT_RESOURCES
;
235 NewKeyCell
->Signature
= CM_KEY_NODE_SIGNATURE
;
236 NewKeyCell
->Flags
= (VolatileKey
? KEY_IS_VOLATILE
: 0);
237 KeQuerySystemTime(&NewKeyCell
->LastWriteTime
);
238 NewKeyCell
->Parent
= ParentKeyCellOffset
;
239 NewKeyCell
->SubKeyCounts
[Stable
] = 0;
240 NewKeyCell
->SubKeyCounts
[Volatile
] = 0;
241 NewKeyCell
->SubKeyLists
[Stable
] = HCELL_NIL
;
242 NewKeyCell
->SubKeyLists
[Volatile
] = HCELL_NIL
;
243 NewKeyCell
->ValueList
.Count
= 0;
244 NewKeyCell
->ValueList
.List
= HCELL_NIL
;
245 NewKeyCell
->Security
= HCELL_NIL
;
246 NewKeyCell
->Class
= HCELL_NIL
;
247 NewKeyCell
->ClassLength
= 0;
248 NewKeyCell
->MaxNameLen
= 0;
249 NewKeyCell
->MaxClassLen
= 0;
250 NewKeyCell
->MaxValueNameLen
= 0;
251 NewKeyCell
->MaxValueDataLen
= 0;
252 NewKeyCell
->NameLength
= CmpCopyName(&RegistryHive
->Hive
, NewKeyCell
->Name
, &KeyName
);
253 if (NewKeyCell
->NameLength
< KeyName
.Length
) NewKeyCell
->Flags
|= KEY_COMP_NAME
;
255 /* Inherit the security from the parent */
256 if (ParentKeyCellOffset
== HCELL_NIL
)
258 // We are in fact creating a root key.
259 // This is not handled there, but when we
260 // call CmCreateRootNode instead.
265 /* Get the parent node */
266 PCM_KEY_NODE ParentKeyCell
;
267 ParentKeyCell
= (PCM_KEY_NODE
)HvGetCell(&RegistryHive
->Hive
, ParentKeyCellOffset
);
271 /* Inherit the security block of the parent */
272 NewKeyCell
->Security
= ParentKeyCell
->Security
;
273 if (NewKeyCell
->Security
!= HCELL_NIL
)
275 PCM_KEY_SECURITY Security
;
276 Security
= (PCM_KEY_SECURITY
)HvGetCell(&RegistryHive
->Hive
, NewKeyCell
->Security
);
277 ++Security
->ReferenceCount
;
278 HvReleaseCell(&RegistryHive
->Hive
, NewKeyCell
->Security
);
281 HvReleaseCell(&RegistryHive
->Hive
, ParentKeyCellOffset
);
285 HvReleaseCell(&RegistryHive
->Hive
, NKBOffset
);
287 *pNKBOffset
= NKBOffset
;
288 return STATUS_SUCCESS
;
293 IN PCMHIVE RegistryHive
,
294 IN HCELL_INDEX ParentKeyCellOffset
,
295 IN PCUNICODE_STRING SubKeyName
,
296 IN BOOLEAN VolatileKey
,
297 OUT HCELL_INDEX
*pBlockOffset
)
299 PCM_KEY_NODE ParentKeyCell
;
300 HCELL_INDEX NKBOffset
;
303 /* Create the new key */
304 Status
= CmiCreateSubKey(RegistryHive
, ParentKeyCellOffset
, SubKeyName
, VolatileKey
, &NKBOffset
);
305 if (!NT_SUCCESS(Status
))
308 /* Mark the parent cell as dirty */
309 HvMarkCellDirty(&RegistryHive
->Hive
, ParentKeyCellOffset
, FALSE
);
311 if (!CmpAddSubKey(&RegistryHive
->Hive
, ParentKeyCellOffset
, NKBOffset
))
313 /* FIXME: delete newly created cell */
314 // CmpFreeKeyByCell(&RegistryHive->Hive, NewCell /*NKBOffset*/, FALSE);
316 return STATUS_UNSUCCESSFUL
;
319 /* Get the parent node */
320 ParentKeyCell
= (PCM_KEY_NODE
)HvGetCell(&RegistryHive
->Hive
, ParentKeyCellOffset
);
323 /* FIXME: delete newly created cell */
324 return STATUS_UNSUCCESSFUL
;
326 VERIFY_KEY_CELL(ParentKeyCell
);
328 /* Update the timestamp */
329 KeQuerySystemTime(&ParentKeyCell
->LastWriteTime
);
331 /* Check if we need to update name maximum, update it if so */
332 if (ParentKeyCell
->MaxNameLen
< SubKeyName
->Length
)
333 ParentKeyCell
->MaxNameLen
= SubKeyName
->Length
;
335 /* Release the cell */
336 HvReleaseCell(&RegistryHive
->Hive
, ParentKeyCellOffset
);
338 *pBlockOffset
= NKBOffset
;
339 return STATUS_SUCCESS
;
344 IN PCMHIVE RegistryHive
,
345 IN PCM_KEY_NODE Parent
,
346 IN PCUNICODE_STRING ValueName
,
347 OUT PCM_KEY_VALUE
*pValueCell
,
348 OUT HCELL_INDEX
*pValueCellOffset
)
350 PCELL_DATA ValueListCell
;
351 PCM_KEY_VALUE NewValueCell
;
352 HCELL_INDEX ValueListCellOffset
;
353 HCELL_INDEX NewValueCellOffset
;
355 HSTORAGE_TYPE Storage
;
358 #define FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
361 Storage
= (Parent
->Flags
& KEY_IS_VOLATILE
) ? Volatile
: Stable
;
362 if (Parent
->ValueList
.List
== HCELL_NIL
)
364 /* Allocate some room for the value list */
365 CellSize
= FIELD_SIZE(CELL_DATA
, u
.KeyList
) + (3 * sizeof(HCELL_INDEX
));
366 ValueListCellOffset
= HvAllocateCell(&RegistryHive
->Hive
, CellSize
, Storage
, HCELL_NIL
);
367 if (ValueListCellOffset
== HCELL_NIL
)
368 return STATUS_INSUFFICIENT_RESOURCES
;
370 ValueListCell
= (PCELL_DATA
)HvGetCell(&RegistryHive
->Hive
, ValueListCellOffset
);
373 HvFreeCell(&RegistryHive
->Hive
, ValueListCellOffset
);
374 return STATUS_UNSUCCESSFUL
;
377 Parent
->ValueList
.List
= ValueListCellOffset
;
381 ValueListCell
= (PCELL_DATA
)HvGetCell(&RegistryHive
->Hive
, Parent
->ValueList
.List
);
383 return STATUS_UNSUCCESSFUL
;
385 CellSize
= ABS_VALUE(HvGetCellSize(&RegistryHive
->Hive
, ValueListCell
));
387 if (Parent
->ValueList
.Count
>= CellSize
/ sizeof(HCELL_INDEX
))
390 ValueListCellOffset
= HvReallocateCell(&RegistryHive
->Hive
, Parent
->ValueList
.List
, CellSize
);
391 if (ValueListCellOffset
== HCELL_NIL
)
392 return STATUS_INSUFFICIENT_RESOURCES
;
394 ValueListCell
= (PCELL_DATA
)HvGetCell(&RegistryHive
->Hive
, ValueListCellOffset
);
396 return STATUS_UNSUCCESSFUL
;
398 Parent
->ValueList
.List
= ValueListCellOffset
;
403 NewValueCellOffset
= HvAllocateCell(&RegistryHive
->Hive
,
404 FIELD_OFFSET(CM_KEY_VALUE
, Name
) +
405 CmpNameSize(&RegistryHive
->Hive
, (PUNICODE_STRING
)ValueName
),
408 if (NewValueCellOffset
== HCELL_NIL
)
410 return STATUS_INSUFFICIENT_RESOURCES
;
413 NewValueCell
= (PCM_KEY_VALUE
)HvGetCell(&RegistryHive
->Hive
, NewValueCellOffset
);
414 if (NewValueCell
== NULL
)
416 HvFreeCell(&RegistryHive
->Hive
, NewValueCellOffset
);
417 return STATUS_INSUFFICIENT_RESOURCES
;
420 NewValueCell
->Signature
= CM_KEY_VALUE_SIGNATURE
;
421 NewValueCell
->NameLength
= CmpCopyName(&RegistryHive
->Hive
,
423 (PUNICODE_STRING
)ValueName
);
425 /* Check for compressed name */
426 if (NewValueCell
->NameLength
< ValueName
->Length
)
428 /* This is a compressed name */
429 NewValueCell
->Flags
= VALUE_COMP_NAME
;
433 /* No flags to set */
434 NewValueCell
->Flags
= 0;
437 NewValueCell
->Type
= 0;
438 NewValueCell
->DataLength
= 0;
439 NewValueCell
->Data
= HCELL_NIL
;
442 ValueListCell
->u
.KeyList
[Parent
->ValueList
.Count
] = NewValueCellOffset
;
443 Parent
->ValueList
.Count
++;
445 HvMarkCellDirty(&RegistryHive
->Hive
, Parent
->ValueList
.List
, FALSE
);
446 HvMarkCellDirty(&RegistryHive
->Hive
, NewValueCellOffset
, FALSE
);
448 *pValueCell
= NewValueCell
;
449 *pValueCellOffset
= NewValueCellOffset
;
451 return STATUS_SUCCESS
;