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