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 UCHAR Buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR)]; 138 ULONG Length = sizeof(Buffer); 139 POBJECT_NAME_INFORMATION FileNameInfo = (POBJECT_NAME_INFORMATION)Buffer; 140 141 HivePath.Buffer = NULL; 142 143 /* Create or open the hive list key */ 144 InitializeObjectAttributes(&ObjectAttributes, 145 &HiveListValueName, 146 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 147 NULL, 148 NULL); 149 Status = ZwCreateKey(&KeyHandle, 150 KEY_READ | KEY_WRITE, 151 &ObjectAttributes, 152 0, 153 NULL, 154 REG_OPTION_VOLATILE, 155 NULL); 156 if (!NT_SUCCESS(Status)) 157 { 158 /* Fail */ 159 DPRINT1("CmpAddToHiveFileList: Creation or opening of the hive list failed, status = 0x%08lx\n", Status); 160 return Status; 161 } 162 163 /* Retrieve the name of the hive */ 164 if (!CmpGetHiveName(Hive, &HivePath)) 165 { 166 /* Fail */ 167 DPRINT1("CmpAddToHiveFileList: Unable to retrieve the hive name\n"); 168 Status = STATUS_NO_MEMORY; 169 goto Quickie; 170 } 171 172 /* Get the name of the corresponding file */ 173 if (!(Hive->Hive.HiveFlags & HIVE_VOLATILE)) 174 { 175 /* Try to get the value */ 176 Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY], 177 ObjectNameInformation, 178 FileNameInfo, 179 Length, 180 &Length); 181 if (NT_SUCCESS(Status)) 182 { 183 /* Null-terminate and add the length of the terminator */ 184 Length -= sizeof(OBJECT_NAME_INFORMATION); 185 FilePath = FileNameInfo->Name.Buffer; 186 FilePath[Length / sizeof(WCHAR)] = UNICODE_NULL; 187 Length += sizeof(UNICODE_NULL); 188 } 189 else 190 { 191 /* Fail */ 192 DPRINT1("CmpAddToHiveFileList: Hive file name query failed, status = 0x%08lx\n", Status); 193 goto Quickie; 194 } 195 } 196 else 197 { 198 /* No name */ 199 FilePath = L""; 200 Length = sizeof(UNICODE_NULL); 201 } 202 203 /* Set the entry in the hive list */ 204 Status = ZwSetValueKey(KeyHandle, 205 &HivePath, 206 0, 207 REG_SZ, 208 FilePath, 209 Length); 210 if (!NT_SUCCESS(Status)) 211 { 212 /* Fail */ 213 DPRINT1("CmpAddToHiveFileList: Setting of entry in the hive list failed, status = 0x%08lx\n", Status); 214 } 215 216 Quickie: 217 /* Cleanup and return status */ 218 if (HivePath.Buffer) ExFreePoolWithTag(HivePath.Buffer, TAG_CM); 219 ObCloseHandle(KeyHandle, KernelMode); 220 return Status; 221 } 222 223 VOID 224 NTAPI 225 CmpRemoveFromHiveFileList(IN PCMHIVE Hive) 226 { 227 NTSTATUS Status; 228 OBJECT_ATTRIBUTES ObjectAttributes; 229 HANDLE KeyHandle; 230 UNICODE_STRING HivePath; 231 232 /* Open the hive list key */ 233 InitializeObjectAttributes(&ObjectAttributes, 234 &HiveListValueName, 235 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 236 NULL, 237 NULL); 238 Status = ZwOpenKey(&KeyHandle, 239 KEY_READ | KEY_WRITE, 240 &ObjectAttributes); 241 if (!NT_SUCCESS(Status)) 242 { 243 /* Fail */ 244 DPRINT1("CmpRemoveFromHiveFileList: Opening of the hive list failed, status = 0x%08lx\n", Status); 245 return; 246 } 247 248 /* Get the hive path name */ 249 CmpGetHiveName(Hive, &HivePath); 250 251 /* Delete the hive path name from the list */ 252 ZwDeleteValueKey(KeyHandle, &HivePath); 253 254 /* Cleanup allocation and handle */ 255 ExFreePoolWithTag(HivePath.Buffer, TAG_CM); 256 ObCloseHandle(KeyHandle, KernelMode); 257 } 258 259 /* EOF */ 260