* Sync up to trunk head (r64959).
[reactos.git] / ntoskrnl / config / cmkeydel.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmkeydel.c
5 * PURPOSE: Configuration Manager - Key Body Deletion
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "ntoskrnl.h"
12 #define NDEBUG
13 #include "debug.h"
14
15 /* FUNCTIONS *****************************************************************/
16
17 BOOLEAN
18 NTAPI
19 CmpMarkKeyDirty(IN PHHIVE Hive,
20 IN HCELL_INDEX Cell,
21 IN BOOLEAN CheckNoSubkeys)
22 {
23 PCELL_DATA CellData, ListData, SecurityData, ValueData;
24 ULONG i;
25
26 /* Get the cell data for our target */
27 CellData = HvGetCell(Hive, Cell);
28 if (!CellData) return FALSE;
29
30 /* Check if sanity checks requested */
31 if (CheckNoSubkeys)
32 {
33 /* Do them */
34 ASSERT(CellData->u.KeyNode.SubKeyCounts[Stable] == 0);
35 ASSERT(CellData->u.KeyNode.SubKeyCounts[Volatile] == 0);
36 }
37
38 /* If this is an exit hive, there's nothing to do */
39 if (CellData->u.KeyNode.Flags & KEY_HIVE_EXIT)
40 {
41 /* Release the cell and get out */
42 HvReleaseCell(Hive, Cell);
43 return TRUE;
44 }
45
46 /* Otherwise, mark it dirty and release it */
47 HvMarkCellDirty(Hive, Cell, FALSE);
48 HvReleaseCell(Hive, Cell);
49
50 /* Check if we have a class */
51 if (CellData->u.KeyNode.Class != HCELL_NIL)
52 {
53 /* Mark it dirty */
54 HvMarkCellDirty(Hive, CellData->u.KeyNode.Class, FALSE);
55 }
56
57 /* Check if we have security */
58 if (CellData->u.KeyNode.Security != HCELL_NIL)
59 {
60 /* Mark it dirty */
61 HvMarkCellDirty(Hive, CellData->u.KeyNode.Security, FALSE);
62
63 /* Get the security data and release it */
64 SecurityData = HvGetCell(Hive, CellData->u.KeyNode.Security);
65 if (!SecurityData) ASSERT(FALSE);
66 HvReleaseCell(Hive, CellData->u.KeyNode.Security);
67
68 /* Mark the security links dirty too */
69 HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Flink, FALSE);
70 HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Blink, FALSE);
71 }
72
73 /* Check if we have any values */
74 if (CellData->u.KeyNode.ValueList.Count > 0)
75 {
76 /* Dirty the value list */
77 HvMarkCellDirty(Hive, CellData->u.KeyNode.ValueList.List, FALSE);
78
79 /* Get the list data itself, and release it */
80 ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
81 if (!ListData) ASSERT(FALSE);
82 HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
83
84 /* Loop all values */
85 for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
86 {
87 /* Dirty each value */
88 HvMarkCellDirty(Hive, ListData->u.KeyList[i], FALSE);
89
90 /* Get the value data and release it */
91 ValueData = HvGetCell(Hive, ListData->u.KeyList[i]);
92 ASSERT(ValueData);
93 HvReleaseCell(Hive,ListData->u.KeyList[i]);
94
95 /* Mark the value data dirty too */
96 if (!CmpMarkValueDataDirty(Hive, &ValueData->u.KeyValue))
97 {
98 /* Failure */
99 return FALSE;
100 }
101 }
102 }
103
104 /* If this is an entry hive, we're done */
105 if (CellData->u.KeyNode.Flags & KEY_HIVE_ENTRY) return TRUE;
106
107 /* Otherwise mark the index dirty too */
108 if (!CmpMarkIndexDirty(Hive, CellData->u.KeyNode.Parent, Cell))
109 {
110 /* Failure */
111 return FALSE;
112 }
113
114 /* Finally, mark the parent dirty */
115 HvMarkCellDirty(Hive, CellData->u.KeyNode.Parent, FALSE);
116 return TRUE;
117 }
118
119 BOOLEAN
120 NTAPI
121 CmpFreeKeyBody(IN PHHIVE Hive,
122 IN HCELL_INDEX Cell)
123 {
124 PCELL_DATA CellData;
125
126 /* Get the key node */
127 CellData = HvGetCell(Hive, Cell);
128 if (!CellData) ASSERT(FALSE);
129
130 /* Check if we can delete the child cells */
131 if (!(CellData->u.KeyNode.Flags & KEY_HIVE_EXIT))
132 {
133 /* Check if we have a security cell */
134 if (CellData->u.KeyNode.Security != HCELL_NIL)
135 {
136 /* Free the security cell */
137 HvFreeCell(Hive, CellData->u.KeyNode.Security);
138 }
139
140 /* Check if we have a class */
141 if (CellData->u.KeyNode.ClassLength > 0)
142 {
143 /* Free it */
144 HvFreeCell(Hive, CellData->u.KeyNode.Class);
145 }
146 }
147
148 /* Release and free the cell */
149 HvReleaseCell(Hive, Cell);
150 HvFreeCell(Hive, Cell);
151 return TRUE;
152 }
153
154 NTSTATUS
155 NTAPI
156 CmpFreeKeyByCell(IN PHHIVE Hive,
157 IN HCELL_INDEX Cell,
158 IN BOOLEAN Unlink)
159 {
160 PCELL_DATA CellData, ParentData, ListData;
161 ULONG i;
162 BOOLEAN Result;
163
164 /* Mark the entire key dirty */
165 CmpMarkKeyDirty(Hive, Cell ,TRUE);
166
167 /* Get the target node and release it */
168 CellData = HvGetCell(Hive, Cell);
169 if (!CellData) ASSERT(FALSE);
170 HvReleaseCell(Hive, Cell);
171
172 /* Make sure we don't have subkeys */
173 ASSERT((CellData->u.KeyNode.SubKeyCounts[Stable] +
174 CellData->u.KeyNode.SubKeyCounts[Volatile]) == 0);
175
176 /* Check if we have to unlink */
177 if (Unlink)
178 {
179 /* Remove the subkey */
180 Result = CmpRemoveSubKey(Hive, CellData->u.KeyNode.Parent, Cell);
181 if (!Result) return STATUS_INSUFFICIENT_RESOURCES;
182
183 /* Get the parent node and release it */
184 ParentData = HvGetCell(Hive, CellData->u.KeyNode.Parent);
185 if (!ParentData) ASSERT(FALSE);
186 HvReleaseCell(Hive, CellData->u.KeyNode.Parent);
187
188 /* Check if the parent node has no more subkeys */
189 if (!(ParentData->u.KeyNode.SubKeyCounts[Stable] +
190 ParentData->u.KeyNode.SubKeyCounts[Volatile]))
191 {
192 /* Then free the cached name/class lengths */
193 ParentData->u.KeyNode.MaxNameLen = 0;
194 ParentData->u.KeyNode.MaxClassLen = 0;
195 }
196 }
197
198 /* Check if we have any values */
199 if (CellData->u.KeyNode.ValueList.Count > 0)
200 {
201 /* Get the value list and release it */
202 ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
203 if (!ListData) ASSERT(FALSE);
204 HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
205
206 /* Loop every value */
207 for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
208 {
209 /* Free it */
210 if (!CmpFreeValue(Hive, ListData->u.KeyList[i])) ASSERT(FALSE);
211 }
212
213 /* Free the value list */
214 HvFreeCell(Hive, CellData->u.KeyNode.ValueList.List);
215 }
216
217 /* Free the key body itself, and then return our status */
218 if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
219 return STATUS_SUCCESS;
220 }