2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmvalue.c
5 * PURPOSE: Configuration Manager - Cell Values
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* FUNCTIONS *****************************************************************/
19 CmpMarkValueDataDirty(IN PHHIVE Hive
,
20 IN PCM_KEY_VALUE Value
)
25 /* Make sure there's actually any data */
26 if (Value
->Data
!= HCELL_NIL
)
28 /* If this is a small key, there's no need to have it dirty */
29 if (CmpIsKeyValueSmall(&KeySize
, Value
->DataLength
)) return TRUE
;
31 /* Check if this is a big key */
32 ASSERT_VALUE_BIG(Hive
, KeySize
);
34 /* Normal value, just mark it dirty */
35 HvMarkCellDirty(Hive
, Value
->Data
, FALSE
);
38 /* Operation complete */
44 CmpFreeValueData(IN PHHIVE Hive
,
45 IN HCELL_INDEX DataCell
,
51 /* If this is a small key, the data is built-in */
52 if (!CmpIsKeyValueSmall(&KeySize
, DataLength
))
54 /* If there's no data cell, there's nothing to do */
55 if (DataCell
== HCELL_NIL
) return TRUE
;
57 /* Make sure the data cell is allocated */
58 //ASSERT(HvIsCellAllocated(Hive, DataCell));
60 /* Unsupported value type */
61 ASSERT_VALUE_BIG(Hive
, KeySize
);
63 /* Normal value, just free the data cell */
64 HvFreeCell(Hive
, DataCell
);
67 /* Operation complete */
73 CmpFreeValue(IN PHHIVE Hive
,
79 /* Get the cell data */
80 Value
= (PCM_KEY_VALUE
)HvGetCell(Hive
, Cell
);
81 if (!Value
) ASSERT(FALSE
);
84 if (!CmpFreeValueData(Hive
, Value
->Data
, Value
->DataLength
))
86 /* We failed to free the data, return failure */
87 HvReleaseCell(Hive
, Cell
);
91 /* Release the cell and free it */
92 HvReleaseCell(Hive
, Cell
);
93 HvFreeCell(Hive
, Cell
);
99 CmpFindValueByName(IN PHHIVE Hive
,
100 IN PCM_KEY_NODE KeyNode
,
101 IN PUNICODE_STRING Name
)
103 HCELL_INDEX CellIndex
;
105 /* Call the main function */
106 if (!CmpFindNameInList(Hive
,
113 ASSERT(CellIndex
== HCELL_NIL
);
116 /* Return the index */
122 CmpGetValueData(IN PHHIVE Hive
,
123 IN PCM_KEY_VALUE Value
,
126 OUT PBOOLEAN BufferAllocated
,
127 OUT PHCELL_INDEX CellToRelease
)
132 ASSERT(Value
->Signature
== CM_KEY_VALUE_SIGNATURE
);
134 /* Set failure defaults */
135 *BufferAllocated
= FALSE
;
137 *CellToRelease
= HCELL_NIL
;
139 /* Check if this is a small key */
140 if (CmpIsKeyValueSmall(Length
, Value
->DataLength
))
142 /* Return the data immediately */
143 *Buffer
= &Value
->Data
;
148 ASSERT_VALUE_BIG(Hive
, *Length
);
150 /* Get the data from the cell */
151 *Buffer
= HvGetCell(Hive
, Value
->Data
);
152 if (!(*Buffer
)) return FALSE
;
154 /* Return success and the cell to be released */
155 *CellToRelease
= Value
->Data
;
161 CmpValueToData(IN PHHIVE Hive
,
162 IN PCM_KEY_VALUE Value
,
166 BOOLEAN BufferAllocated
;
167 HCELL_INDEX CellToRelease
;
171 ASSERT(Hive
->ReleaseCellRoutine
== NULL
);
173 /* Get the actual data */
174 if (!CmpGetValueData(Hive
,
182 ASSERT(BufferAllocated
== FALSE
);
183 ASSERT(Buffer
== NULL
);
187 /* This should never happen!*/
190 /* Free the buffer and bugcheck */
192 KeBugCheckEx(REGISTRY_ERROR
, 8, 0, (ULONG_PTR
)Hive
, (ULONG_PTR
)Value
);
195 /* Otherwise, return the cell data */
201 CmpAddValueToList(IN PHHIVE Hive
,
202 IN HCELL_INDEX ValueCell
,
205 IN OUT PCHILD_LIST ChildList
)
207 HCELL_INDEX ListCell
;
208 ULONG ChildCount
, Length
, i
;
213 ASSERT((((LONG
)Index
) >= 0) && (Index
<= ChildList
->Count
));
215 /* Get the number of entries in the child list */
216 ChildCount
= ChildList
->Count
;
220 /* The cell should be dirty at this point */
221 ASSERT(HvIsCellDirty(Hive
, ChildList
->List
));
223 /* Check if we have less then 100 children */
224 if (ChildCount
< 100)
226 /* Allocate just enough as requested */
227 Length
= ChildCount
* sizeof(HCELL_INDEX
);
231 /* Otherwise, we have quite a few, so allocate a batch */
232 Length
= ROUND_UP(ChildCount
, 100) * sizeof(HCELL_INDEX
);
233 if (Length
> HBLOCK_SIZE
)
235 /* But make sure we don't allocate beyond our block size */
236 Length
= ROUND_UP(Length
, HBLOCK_SIZE
);
240 /* Perform the allocation */
241 ListCell
= HvReallocateCell(Hive
, ChildList
->List
, Length
);
245 /* This is our first child, so allocate a single cell */
246 ListCell
= HvAllocateCell(Hive
, sizeof(HCELL_INDEX
), Type
, HCELL_NIL
);
249 /* Fail if we couldn't get a cell */
250 if (ListCell
== HCELL_NIL
) return STATUS_INSUFFICIENT_RESOURCES
;
252 /* Set this cell as the child list's list cell */
253 ChildList
->List
= ListCell
;
255 /* Get the actual key list memory */
256 CellData
= HvGetCell(Hive
, ListCell
);
257 ASSERT(CellData
!= NULL
);
259 /* Loop all the children */
260 for (i
= ChildCount
- 1; i
> Index
; i
--)
262 /* Move them all down */
263 CellData
->u
.KeyList
[i
] = CellData
->u
.KeyList
[i
- 1];
266 /* Insert us on top now */
267 CellData
->u
.KeyList
[Index
] = ValueCell
;
268 ChildList
->Count
= ChildCount
;
270 /* Release the list cell and make sure the value cell is dirty */
271 HvReleaseCell(Hive
, ListCell
);
272 ASSERT(HvIsCellDirty(Hive
, ValueCell
));
274 /* We're done here */
275 return STATUS_SUCCESS
;
280 CmpSetValueDataNew(IN PHHIVE Hive
,
283 IN ULONG StorageType
,
284 IN HCELL_INDEX ValueCell
,
285 OUT PHCELL_INDEX DataCell
)
289 ASSERT(DataSize
> CM_KEY_VALUE_SMALL
);
291 /* Check if this is a big key */
292 ASSERT_VALUE_BIG(Hive
, DataSize
);
294 /* Allocate a data cell */
295 *DataCell
= HvAllocateCell(Hive
, DataSize
, StorageType
, HCELL_NIL
);
296 if (*DataCell
== HCELL_NIL
) return STATUS_INSUFFICIENT_RESOURCES
;
298 /* Get the actual data */
299 CellData
= HvGetCell(Hive
, *DataCell
);
300 if (!CellData
) ASSERT(FALSE
);
302 /* Copy our buffer into it */
303 RtlCopyMemory(CellData
, Data
, DataSize
);
306 return STATUS_SUCCESS
;
311 CmpRemoveValueFromList(IN PHHIVE Hive
,
313 IN OUT PCHILD_LIST ChildList
)
321 ASSERT((((LONG
)Index
) >= 0) && (Index
<= ChildList
->Count
));
323 /* Get the new count after removal */
324 Count
= ChildList
->Count
- 1;
327 /* Get the actual list array */
328 CellData
= HvGetCell(Hive
, ChildList
->List
);
329 if (!CellData
) return STATUS_INSUFFICIENT_RESOURCES
;
331 /* Make sure cells data have been made dirty */
332 ASSERT(HvIsCellDirty(Hive
, ChildList
->List
));
333 ASSERT(HvIsCellDirty(Hive
, CellData
->u
.KeyList
[Index
]));
336 while (Index
< Count
)
338 /* Move everything up */
339 CellData
->u
.KeyList
[Index
] = CellData
->u
.KeyList
[Index
+ 1];
343 /* Re-allocate the cell for the list by decreasing the count */
344 NewCell
= HvReallocateCell(Hive
,
346 Count
* sizeof(HCELL_INDEX
));
347 ASSERT(NewCell
!= HCELL_NIL
);
348 HvReleaseCell(Hive
,ChildList
->List
);
350 /* Update the list cell */
351 ChildList
->List
= NewCell
;
355 /* Otherwise, we were the last entry, so free the list entirely */
356 HvFreeCell(Hive
, ChildList
->List
);
357 ChildList
->List
= HCELL_NIL
;
360 /* Update the child list with the new count */
361 ChildList
->Count
= Count
;
362 return STATUS_SUCCESS
;
367 CmpCopyKeyValueList(IN PHHIVE SourceHive
,
368 IN PCHILD_LIST SrcValueList
,
369 IN PHHIVE DestinationHive
,
370 IN OUT PCHILD_LIST DestValueList
,
371 IN HSTORAGE_TYPE StorageType
)
374 NTSTATUS Status
= STATUS_SUCCESS
;
375 HCELL_INDEX CellIndex
= HCELL_NIL
;
377 PCELL_DATA SrcListData
= NULL
;
378 PCELL_DATA DestListData
= NULL
;
383 DestValueList
->Count
= SrcValueList
->Count
;
385 /* Check if the list is empty */
386 if (!DestValueList
->Count
)
388 DestValueList
->List
= HCELL_NIL
;
389 return STATUS_SUCCESS
;
392 /* Create a simple copy of the list */
393 CellIndex
= CmpCopyCell(SourceHive
,
397 if (CellIndex
== HCELL_NIL
) return STATUS_INSUFFICIENT_RESOURCES
;
399 /* Get the source and the destination value list */
400 SrcListData
= HvGetCell(SourceHive
, SrcValueList
->List
);
401 DestListData
= HvGetCell(DestinationHive
, CellIndex
);
403 /* Copy the actual values */
404 for (Index
= 0; Index
< SrcValueList
->Count
; Index
++)
406 DestListData
->u
.KeyList
[Index
] = CmpCopyCell(SourceHive
,
407 SrcListData
->u
.KeyList
[Index
],
410 if (DestListData
->u
.KeyList
[Index
] == HCELL_NIL
)
412 Status
= STATUS_INSUFFICIENT_RESOURCES
;
417 /* Release the cells */
418 if (SrcListData
) HvReleaseCell(SourceHive
, SrcValueList
->List
);
419 if (DestListData
) HvReleaseCell(DestinationHive
, CellIndex
);