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