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