1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/config/cmhvlist.c 5 * PURPOSE: Configuration Manager - Hives file list management 6 * PROGRAMMERS: Hermes BELUSCA - MAITO 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include "ntoskrnl.h" 12 #define NDEBUG 13 #include "debug.h" 14 15 /* GLOBALS ********************************************************************/ 16 17 UNICODE_STRING HiveListValueName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\hivelist"); 18 19 /* FUNCTIONS ******************************************************************/ 20 21 /* Note: the caller is expected to free the HiveName string buffer */ 22 BOOLEAN 23 NTAPI 24 CmpGetHiveName(IN PCMHIVE Hive, 25 OUT PUNICODE_STRING HiveName) 26 { 27 HCELL_INDEX RootCell, LinkCell; 28 PCELL_DATA RootData, LinkData, ParentData; 29 ULONG ParentNameSize, LinkNameSize; 30 SIZE_T NameSize; 31 PWCHAR p; 32 UNICODE_STRING RegistryName = RTL_CONSTANT_STRING(L"\\REGISTRY\\"); 33 34 /* Get the root cell of this hive */ 35 RootCell = Hive->Hive.BaseBlock->RootCell; 36 RootData = HvGetCell(&Hive->Hive, RootCell); 37 if (!RootData) return FALSE; 38 39 /* Get the cell index at which this hive is linked to, and its parent */ 40 LinkCell = RootData->u.KeyNode.Parent; 41 HvReleaseCell(&Hive->Hive, RootCell); 42 43 /* Sanity check */ 44 ASSERT((&CmiVolatileHive->Hive)->ReleaseCellRoutine == NULL); 45 46 /* Get the cell data for link and parent */ 47 LinkData = HvGetCell(&CmiVolatileHive->Hive, LinkCell); 48 if (!LinkData) return FALSE; 49 ParentData = HvGetCell(&CmiVolatileHive->Hive, LinkData->u.KeyNode.Parent); 50 if (!ParentData) return FALSE; 51 52 /* Get the size of the parent name */ 53 if (ParentData->u.KeyNode.Flags & KEY_COMP_NAME) 54 { 55 ParentNameSize = CmpCompressedNameSize(ParentData->u.KeyNode.Name, 56 ParentData->u.KeyNode.NameLength); 57 } 58 else 59 { 60 ParentNameSize = ParentData->u.KeyNode.NameLength; 61 } 62 63 /* Get the size of the link name */ 64 if (LinkData->u.KeyNode.Flags & KEY_COMP_NAME) 65 { 66 LinkNameSize = CmpCompressedNameSize(LinkData->u.KeyNode.Name, 67 LinkData->u.KeyNode.NameLength); 68 } 69 else 70 { 71 LinkNameSize = LinkData->u.KeyNode.NameLength; 72 } 73 74 /* No need to account for terminal NULL character since we deal with counted UNICODE strings */ 75 NameSize = RegistryName.Length + ParentNameSize + sizeof(WCHAR) + LinkNameSize; 76 77 /* Allocate the memory */ 78 HiveName->Buffer = ExAllocatePoolWithTag(PagedPool, NameSize, TAG_CM); 79 if (!HiveName->Buffer) 80 { 81 /* Fail */ 82 DPRINT1("CmpGetHiveName: Unable to allocate memory\n"); 83 return FALSE; 84 } 85 86 /* Build the string for it */ 87 HiveName->Length = HiveName->MaximumLength = (USHORT)NameSize; 88 p = HiveName->Buffer; 89 90 /* Copy the parent name */ 91 RtlCopyMemory(p, RegistryName.Buffer, RegistryName.Length); 92 p += RegistryName.Length / sizeof(WCHAR); 93 if (ParentData->u.KeyNode.Flags & KEY_COMP_NAME) 94 { 95 CmpCopyCompressedName(p, 96 ParentNameSize, 97 ParentData->u.KeyNode.Name, 98 ParentData->u.KeyNode.NameLength); 99 } 100 else 101 { 102 RtlCopyMemory(p, ParentData->u.KeyNode.Name, ParentNameSize); 103 } 104 105 /* Add a path separator between parent and link */ 106 p += ParentNameSize / sizeof(WCHAR); 107 *p = OBJ_NAME_PATH_SEPARATOR; 108 ++p; 109 110 /* Now copy the link name */ 111 if (LinkData->u.KeyNode.Flags & KEY_COMP_NAME) 112 { 113 CmpCopyCompressedName(p, 114 LinkNameSize, 115 LinkData->u.KeyNode.Name, 116 LinkData->u.KeyNode.NameLength); 117 118 } 119 else 120 { 121 RtlCopyMemory(p, LinkData->u.KeyNode.Name, LinkNameSize); 122 } 123 124 /* All done */ 125 return TRUE; 126 } 127 128 NTSTATUS 129 NTAPI 130 CmpAddToHiveFileList(IN PCMHIVE Hive) 131 { 132 NTSTATUS Status; 133 OBJECT_ATTRIBUTES ObjectAttributes; 134 HANDLE KeyHandle; 135 UNICODE_STRING HivePath; 136 PWCHAR FilePath; 137 ULONG Length; 138 OBJECT_NAME_INFORMATION DummyNameInfo; 139 POBJECT_NAME_INFORMATION FileNameInfo; 140 141 HivePath.Buffer = NULL; 142 FileNameInfo = NULL; 143 144 /* Create or open the hive list key */ 145 InitializeObjectAttributes(&ObjectAttributes, 146 &HiveListValueName, 147 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 148 NULL, 149 NULL); 150 Status = ZwCreateKey(&KeyHandle, 151 KEY_READ | KEY_WRITE, 152 &ObjectAttributes, 153 0, 154 NULL, 155 REG_OPTION_VOLATILE, 156 NULL); 157 if (!NT_SUCCESS(Status)) 158 { 159 /* Fail */ 160 DPRINT1("CmpAddToHiveFileList: Creation or opening of the hive list failed, status = 0x%08lx\n", Status); 161 return Status; 162 } 163 164 /* Retrieve the name of the hive */ 165 if (!CmpGetHiveName(Hive, &HivePath)) 166 { 167 /* Fail */ 168 DPRINT1("CmpAddToHiveFileList: Unable to retrieve the hive name\n"); 169 Status = STATUS_NO_MEMORY; 170 goto Quickie; 171 } 172 173 /* Get the name of the corresponding file */ 174 if (!(Hive->Hive.HiveFlags & HIVE_VOLATILE)) 175 { 176 /* Determine the right buffer size and allocate */ 177 Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY], 178 ObjectNameInformation, 179 &DummyNameInfo, 180 sizeof(DummyNameInfo), 181 &Length); 182 if (Status != STATUS_BUFFER_OVERFLOW) 183 { 184 DPRINT1("CmpAddToHiveFileList: Hive file name size query failed, status = 0x%08lx\n", Status); 185 goto Quickie; 186 } 187 188 FileNameInfo = ExAllocatePoolWithTag(PagedPool, 189 Length + sizeof(UNICODE_NULL), 190 TAG_CM); 191 if (FileNameInfo == NULL) 192 { 193 Status = STATUS_INSUFFICIENT_RESOURCES; 194 goto Quickie; 195 } 196 197 /* Try to get the value */ 198 Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY], 199 ObjectNameInformation, 200 FileNameInfo, 201 Length, 202 &Length); 203 if (NT_SUCCESS(Status)) 204 { 205 /* Null-terminate and add the length of the terminator */ 206 Length -= sizeof(OBJECT_NAME_INFORMATION); 207 FilePath = FileNameInfo->Name.Buffer; 208 FilePath[Length / sizeof(WCHAR)] = UNICODE_NULL; 209 Length += sizeof(UNICODE_NULL); 210 } 211 else 212 { 213 /* Fail */ 214 DPRINT1("CmpAddToHiveFileList: Hive file name query failed, status = 0x%08lx\n", Status); 215 goto Quickie; 216 } 217 } 218 else 219 { 220 /* No name */ 221 FilePath = L""; 222 Length = sizeof(UNICODE_NULL); 223 } 224 225 /* Set the entry in the hive list */ 226 Status = ZwSetValueKey(KeyHandle, 227 &HivePath, 228 0, 229 REG_SZ, 230 FilePath, 231 Length); 232 if (!NT_SUCCESS(Status)) 233 { 234 /* Fail */ 235 DPRINT1("CmpAddToHiveFileList: Setting of entry in the hive list failed, status = 0x%08lx\n", Status); 236 } 237 238 Quickie: 239 /* Cleanup and return status */ 240 if (HivePath.Buffer) 241 { 242 ExFreePoolWithTag(HivePath.Buffer, TAG_CM); 243 } 244 if (FileNameInfo) 245 { 246 ExFreePoolWithTag(FileNameInfo, TAG_CM); 247 } 248 ObCloseHandle(KeyHandle, KernelMode); 249 return Status; 250 } 251 252 VOID 253 NTAPI 254 CmpRemoveFromHiveFileList(IN PCMHIVE Hive) 255 { 256 NTSTATUS Status; 257 OBJECT_ATTRIBUTES ObjectAttributes; 258 HANDLE KeyHandle; 259 UNICODE_STRING HivePath; 260 261 /* Open the hive list key */ 262 InitializeObjectAttributes(&ObjectAttributes, 263 &HiveListValueName, 264 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 265 NULL, 266 NULL); 267 Status = ZwOpenKey(&KeyHandle, 268 KEY_READ | KEY_WRITE, 269 &ObjectAttributes); 270 if (!NT_SUCCESS(Status)) 271 { 272 /* Fail */ 273 DPRINT1("CmpRemoveFromHiveFileList: Opening of the hive list failed, status = 0x%08lx\n", Status); 274 return; 275 } 276 277 /* Get the hive path name */ 278 CmpGetHiveName(Hive, &HivePath); 279 280 /* Delete the hive path name from the list */ 281 ZwDeleteValueKey(KeyHandle, &HivePath); 282 283 /* Cleanup allocation and handle */ 284 ExFreePoolWithTag(HivePath.Buffer, TAG_CM); 285 ObCloseHandle(KeyHandle, KernelMode); 286 } 287 288 /* EOF */ 289