From 30da982e368a5d48388c0de4e641ec9ad7b8508e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 17 Jan 2016 00:50:03 +0000 Subject: [PATCH] [MKHIVE] - Make mkhive tool correctly initialize the Max(Value)[Name|Data]Length members of HHIVE structure. CORE-10794 #resolve - Add default security hive descriptors to our mkhive-built registry hives. CORE-10795 #resolve - Make MKHIVE fully using the CMLIB library. CORE-10802 CORE-10793 svn path=/trunk/; revision=70602 --- reactos/tools/mkhive/cmi.c | 612 ++++++++++-------------------- reactos/tools/mkhive/cmi.h | 38 +- reactos/tools/mkhive/mkhive.c | 5 +- reactos/tools/mkhive/mkhive.h | 6 +- reactos/tools/mkhive/registry.c | 646 ++++++++++++++++++++++++-------- reactos/tools/mkhive/rtl.c | 20 +- 6 files changed, 715 insertions(+), 612 deletions(-) diff --git a/reactos/tools/mkhive/cmi.c b/reactos/tools/mkhive/cmi.c index 11db109cc14..912413c7f9e 100644 --- a/reactos/tools/mkhive/cmi.c +++ b/reactos/tools/mkhive/cmi.c @@ -16,7 +16,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* COPYRIGHT: See COPYING in the top level directory +/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS hive maker * FILE: tools/mkhive/cmi.c * PURPOSE: Registry file manipulation routines @@ -33,7 +34,7 @@ CmpAllocate( IN BOOLEAN Paged, IN ULONG Tag) { - return (PVOID) malloc((size_t)Size); + return (PVOID)malloc((size_t)Size); } VOID @@ -69,9 +70,10 @@ CmpFileWrite( { PCMHIVE CmHive = (PCMHIVE)RegistryHive; FILE *File = CmHive->FileHandles[HFILE_TYPE_PRIMARY]; - if (0 != fseek (File, *FileOffset, SEEK_SET)) + if (fseek(File, *FileOffset, SEEK_SET) != 0) return FALSE; - return BufferLength == fwrite (Buffer, 1, BufferLength, File); + + return (fwrite(Buffer, 1, BufferLength, File) == BufferLength); } static BOOLEAN @@ -96,25 +98,24 @@ CmpFileFlush( { PCMHIVE CmHive = (PCMHIVE)RegistryHive; FILE *File = CmHive->FileHandles[HFILE_TYPE_PRIMARY]; - return 0 == fflush (File); + return (fflush(File) == 0); } NTSTATUS -CmiInitializeTempHive( - IN OUT PCMHIVE Hive) +CmiInitializeHive( + IN OUT PCMHIVE Hive, + IN PCWSTR Name) { NTSTATUS Status; - RtlZeroMemory ( - Hive, - sizeof(CMHIVE)); + RtlZeroMemory(Hive, sizeof(*Hive)); DPRINT("Hive 0x%p\n", Hive); Status = HvInitialize(&Hive->Hive, HINIT_CREATE, - 0, - 0, + HIVE_NOLAZYFLUSH, + HFILE_TYPE_PRIMARY, 0, CmpAllocate, CmpFree, @@ -129,200 +130,158 @@ CmiInitializeTempHive( return Status; } - if (!CmCreateRootNode (&Hive->Hive, L"")) + // HACK: See the HACK from r31253 + if (!CmCreateRootNode(&Hive->Hive, Name)) { - HvFree (&Hive->Hive); + HvFree(&Hive->Hive); return STATUS_INSUFFICIENT_RESOURCES; } - Hive->Flags = HIVE_NO_FILE; - /* Add the new hive to the hive list */ InsertTailList(&CmiHiveListHead, &Hive->HiveList); - VERIFY_REGISTRY_HIVE (Hive); - return STATUS_SUCCESS; } -static NTSTATUS -CmiAddKeyToHashTable( - IN PCMHIVE RegistryHive, - IN OUT PCM_KEY_FAST_INDEX HashCell, - IN HCELL_INDEX HashCellIndex, - IN PCM_KEY_NODE NewKeyCell, - IN HCELL_INDEX NKBOffset) +NTSTATUS +CmiCreateSecurityKey( + IN PHHIVE Hive, + IN HCELL_INDEX Cell, + IN PUCHAR Descriptor, + IN ULONG DescriptorLength) { - ULONG i; - ULONG HashKey = 0; + HCELL_INDEX SecurityCell; + PCM_KEY_NODE Node; + PCM_KEY_SECURITY Security; - if (NewKeyCell->Flags & KEY_COMP_NAME) + Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell); + SecurityCell = HvAllocateCell(Hive, + FIELD_OFFSET(CM_KEY_SECURITY, Descriptor) + + DescriptorLength, + Stable, + HCELL_NIL); + if (SecurityCell == HCELL_NIL) { - RtlCopyMemory( - &HashKey, - NewKeyCell->Name, - min(NewKeyCell->NameLength, sizeof(ULONG))); + HvReleaseCell(Hive, Cell); + return STATUS_INSUFFICIENT_RESOURCES; } - for (i = 0; i < HashCell->Count; i++) - { - if (HashCell->List[i].HashKey > HashKey) - break; - } + Node->Security = SecurityCell; + Security = (PCM_KEY_SECURITY)HvGetCell(Hive, SecurityCell); + Security->Signature = CM_KEY_SECURITY_SIGNATURE; + Security->ReferenceCount = 1; + Security->DescriptorLength = DescriptorLength; - if (i < HashCell->Count) - { - RtlMoveMemory(HashCell->List + i + 1, - HashCell->List + i, - (HashCell->Count - i) * - sizeof(HashCell->List[0])); - } + RtlMoveMemory(&Security->Descriptor, + Descriptor, + DescriptorLength); + + Security->Flink = Security->Blink = SecurityCell; + + HvReleaseCell(Hive, SecurityCell); + HvReleaseCell(Hive, Cell); - HashCell->List[i].Cell = NKBOffset; - HashCell->List[i].HashKey = HashKey; - HashCell->Count++; - HvMarkCellDirty(&RegistryHive->Hive, HashCellIndex, FALSE); return STATUS_SUCCESS; } -static NTSTATUS -CmiAllocateHashTableCell ( - IN PCMHIVE RegistryHive, - OUT PCM_KEY_FAST_INDEX *HashBlock, - OUT HCELL_INDEX *HBOffset, - IN USHORT SubKeyCount, - IN HSTORAGE_TYPE Storage) -{ - PCM_KEY_FAST_INDEX NewHashBlock; - ULONG NewHashSize; - NTSTATUS Status; - - Status = STATUS_SUCCESS; - *HashBlock = NULL; - NewHashSize = FIELD_OFFSET(CM_KEY_FAST_INDEX, List) + - (SubKeyCount * sizeof(CM_INDEX)); - *HBOffset = HvAllocateCell(&RegistryHive->Hive, NewHashSize, Storage, HCELL_NIL); - - if (*HBOffset == HCELL_NIL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - NewHashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (&RegistryHive->Hive, *HBOffset); - NewHashBlock->Signature = CM_KEY_FAST_LEAF; - NewHashBlock->Count = 0; - *HashBlock = NewHashBlock; - } - - return Status; -} - static NTSTATUS CmiCreateSubKey( IN PCMHIVE RegistryHive, IN HCELL_INDEX ParentKeyCellOffset, IN PCUNICODE_STRING SubKeyName, - IN ULONG CreateOptions, + IN BOOLEAN VolatileKey, OUT HCELL_INDEX* pNKBOffset) { HCELL_INDEX NKBOffset; PCM_KEY_NODE NewKeyCell; - ULONG NewBlockSize; - NTSTATUS Status; - USHORT NameLength; - PWSTR NamePtr; - BOOLEAN Packable; + UNICODE_STRING KeyName; HSTORAGE_TYPE Storage; - ULONG i; - /* Skip leading backslash */ - if (SubKeyName->Buffer[0] == L'\\') + /* Skip leading path separator if present */ + if (SubKeyName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) { - NamePtr = &SubKeyName->Buffer[1]; - NameLength = SubKeyName->Length - sizeof(WCHAR); + KeyName.Buffer = &SubKeyName->Buffer[1]; + KeyName.Length = KeyName.MaximumLength = SubKeyName->Length - sizeof(WCHAR); } else { - NamePtr = SubKeyName->Buffer; - NameLength = SubKeyName->Length; + KeyName = *SubKeyName; } - /* Check whether key name can be packed */ - Packable = TRUE; - for (i = 0; i < NameLength / sizeof(WCHAR); i++) - { - if (NamePtr[i] & 0xFF00) - { - Packable = FALSE; - break; - } - } + Storage = (VolatileKey ? Volatile : Stable); - /* Adjust name size */ - if (Packable) - { - NameLength = NameLength / sizeof(WCHAR); - } - - Status = STATUS_SUCCESS; - - Storage = (CreateOptions & REG_OPTION_VOLATILE) ? Volatile : Stable; - NewBlockSize = FIELD_OFFSET(CM_KEY_NODE, Name) + NameLength; - NKBOffset = HvAllocateCell(&RegistryHive->Hive, NewBlockSize, Storage, HCELL_NIL); + NKBOffset = HvAllocateCell(&RegistryHive->Hive, + FIELD_OFFSET(CM_KEY_NODE, Name) + + CmpNameSize(&RegistryHive->Hive, &KeyName), + Storage, + HCELL_NIL); if (NKBOffset == HCELL_NIL) { - Status = STATUS_INSUFFICIENT_RESOURCES; + return STATUS_INSUFFICIENT_RESOURCES; + } + + NewKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, NKBOffset); + if (NewKeyCell == NULL) + { + HvFreeCell(&RegistryHive->Hive, NKBOffset); + return STATUS_INSUFFICIENT_RESOURCES; + } + + NewKeyCell->Signature = CM_KEY_NODE_SIGNATURE; + NewKeyCell->Flags = (VolatileKey ? KEY_IS_VOLATILE : 0); + KeQuerySystemTime(&NewKeyCell->LastWriteTime); + NewKeyCell->Parent = ParentKeyCellOffset; + NewKeyCell->SubKeyCounts[Stable] = 0; + NewKeyCell->SubKeyCounts[Volatile] = 0; + NewKeyCell->SubKeyLists[Stable] = HCELL_NIL; + NewKeyCell->SubKeyLists[Volatile] = HCELL_NIL; + NewKeyCell->ValueList.Count = 0; + NewKeyCell->ValueList.List = HCELL_NIL; + NewKeyCell->Security = HCELL_NIL; + NewKeyCell->Class = HCELL_NIL; + NewKeyCell->ClassLength = 0; + NewKeyCell->MaxNameLen = 0; + NewKeyCell->MaxClassLen = 0; + NewKeyCell->MaxValueNameLen = 0; + NewKeyCell->MaxValueDataLen = 0; + NewKeyCell->NameLength = CmpCopyName(&RegistryHive->Hive, NewKeyCell->Name, &KeyName); + if (NewKeyCell->NameLength < KeyName.Length) NewKeyCell->Flags |= KEY_COMP_NAME; + + /* Inherit the security from the parent */ + if (ParentKeyCellOffset == HCELL_NIL) + { + // We are in fact creating a root key. + // This is not handled there, but when we + // call CmCreateRootNode instead. + ASSERT(FALSE); } else { - NewKeyCell = (PCM_KEY_NODE)HvGetCell (&RegistryHive->Hive, NKBOffset); - NewKeyCell->Signature = CM_KEY_NODE_SIGNATURE; - if (CreateOptions & REG_OPTION_VOLATILE) - { - NewKeyCell->Flags = KEY_IS_VOLATILE; - } - else - { - NewKeyCell->Flags = 0; - } - KeQuerySystemTime(&NewKeyCell->LastWriteTime); - NewKeyCell->Parent = ParentKeyCellOffset; - NewKeyCell->SubKeyCounts[Stable] = 0; - NewKeyCell->SubKeyCounts[Volatile] = 0; - NewKeyCell->SubKeyLists[Stable] = HCELL_NIL; - NewKeyCell->SubKeyLists[Volatile] = HCELL_NIL; - NewKeyCell->ValueList.Count = 0; - NewKeyCell->ValueList.List = HCELL_NIL; - NewKeyCell->Security = HCELL_NIL; - NewKeyCell->Class = HCELL_NIL; + /* Get the parent node */ + PCM_KEY_NODE ParentKeyCell; + ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset); - /* Pack the key name */ - NewKeyCell->NameLength = NameLength; - if (Packable) + if (ParentKeyCell) { - NewKeyCell->Flags |= KEY_COMP_NAME; - for (i = 0; i < NameLength; i++) + /* Inherit the security block of the parent */ + NewKeyCell->Security = ParentKeyCell->Security; + if (NewKeyCell->Security != HCELL_NIL) { - ((PCHAR)NewKeyCell->Name)[i] = (CHAR)(NamePtr[i] & 0x00FF); + PCM_KEY_SECURITY Security; + Security = (PCM_KEY_SECURITY)HvGetCell(&RegistryHive->Hive, NewKeyCell->Security); + ++Security->ReferenceCount; + HvReleaseCell(&RegistryHive->Hive, NewKeyCell->Security); } - } - else - { - RtlCopyMemory(NewKeyCell->Name, - NamePtr, - NameLength); - } - VERIFY_KEY_CELL(NewKeyCell); + HvReleaseCell(&RegistryHive->Hive, ParentKeyCellOffset); + } } - if (NT_SUCCESS(Status)) - { - *pNKBOffset = NKBOffset; - } - return Status; + HvReleaseCell(&RegistryHive->Hive, NKBOffset); + + *pNKBOffset = NKBOffset; + return STATUS_SUCCESS; } NTSTATUS @@ -330,291 +289,156 @@ CmiAddSubKey( IN PCMHIVE RegistryHive, IN HCELL_INDEX ParentKeyCellOffset, IN PCUNICODE_STRING SubKeyName, - IN ULONG CreateOptions, - OUT PCM_KEY_NODE *pSubKeyCell, + IN BOOLEAN VolatileKey, OUT HCELL_INDEX *pBlockOffset) { PCM_KEY_NODE ParentKeyCell; HCELL_INDEX NKBOffset; NTSTATUS Status; - ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset); - if (!ParentKeyCell) - return STATUS_UNSUCCESSFUL; - VERIFY_KEY_CELL(ParentKeyCell); - /* Create the new key */ - Status = CmiCreateSubKey(RegistryHive, ParentKeyCellOffset, SubKeyName, CreateOptions, &NKBOffset); + Status = CmiCreateSubKey(RegistryHive, ParentKeyCellOffset, SubKeyName, VolatileKey, &NKBOffset); if (!NT_SUCCESS(Status)) - { return Status; - } + + /* Mark the parent cell as dirty */ + HvMarkCellDirty(&RegistryHive->Hive, ParentKeyCellOffset, FALSE); if (!CmpAddSubKey(&RegistryHive->Hive, ParentKeyCellOffset, NKBOffset)) { /* FIXME: delete newly created cell */ + // CmpFreeKeyByCell(&RegistryHive->Hive, NewCell /*NKBOffset*/, FALSE); + ASSERT(FALSE); return STATUS_UNSUCCESSFUL; } + /* Get the parent node */ + ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset); + if (!ParentKeyCell) + { + /* FIXME: delete newly created cell */ + return STATUS_UNSUCCESSFUL; + } + VERIFY_KEY_CELL(ParentKeyCell); + + /* Update the timestamp */ KeQuerySystemTime(&ParentKeyCell->LastWriteTime); - HvMarkCellDirty(&RegistryHive->Hive, ParentKeyCellOffset, FALSE); + + /* Check if we need to update name maximum, update it if so */ + if (ParentKeyCell->MaxNameLen < SubKeyName->Length) + ParentKeyCell->MaxNameLen = SubKeyName->Length; + + /* Release the cell */ + HvReleaseCell(&RegistryHive->Hive, ParentKeyCellOffset); *pBlockOffset = NKBOffset; return STATUS_SUCCESS; } -#if 0 // Those two functions seem to be unused, but keep them just in case we may need to use them in the future... -static BOOLEAN -CmiCompareHash( - IN PCUNICODE_STRING KeyName, - IN PCHAR HashString) -{ - CHAR Buffer[4]; - - Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0; - Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0; - Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0; - Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0; - - return (strncmp(Buffer, HashString, 4) == 0); -} - -static BOOLEAN -CmiCompareHashI( - IN PCUNICODE_STRING KeyName, - IN PCHAR HashString) -{ - CHAR Buffer[4]; - - Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0; - Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0; - Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0; - Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0; - - return (strncasecmp(Buffer, HashString, 4) == 0); -} -#endif - -NTSTATUS -CmiScanForSubKey( - IN PCMHIVE RegistryHive, - IN HCELL_INDEX ParentKeyCellOffset, - IN PCUNICODE_STRING SubKeyName, - IN ULONG Attributes, - OUT PCM_KEY_NODE *pSubKeyCell, - OUT HCELL_INDEX *pBlockOffset) -{ - PCM_KEY_NODE KeyCell; - PCM_KEY_FAST_INDEX HashBlock; - PCM_KEY_NODE CurSubKeyCell; - BOOLEAN CaseInsensitive; - ULONG Storage; - ULONG i; - - KeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset); - if (!KeyCell) - return STATUS_UNSUCCESSFUL; - VERIFY_KEY_CELL(KeyCell); - - ASSERT(RegistryHive); - - *pSubKeyCell = NULL; - CaseInsensitive = (Attributes & OBJ_CASE_INSENSITIVE) != 0; - - for (Storage = Stable; Storage < HTYPE_COUNT; Storage++) - { - if (KeyCell->SubKeyLists[Storage] == HCELL_NIL) - { - /* The key does not have any subkeys */ - continue; - } - - /* Get hash table */ - HashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (&RegistryHive->Hive, KeyCell->SubKeyLists[Storage]); - if (!HashBlock || HashBlock->Signature != CM_KEY_FAST_LEAF) - return STATUS_UNSUCCESSFUL; - - for (i = 0; i < KeyCell->SubKeyCounts[Storage]; i++) - { - if ((HashBlock->List[i].HashKey == 0) || - (CmCompareHash(SubKeyName, (PCHAR)&HashBlock->List[i].HashKey, CaseInsensitive))) - { - CurSubKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, - HashBlock->List[i].Cell); - - if (CmCompareKeyName(CurSubKeyCell, SubKeyName, CaseInsensitive)) - { - *pSubKeyCell = CurSubKeyCell; - *pBlockOffset = HashBlock->List[i].Cell; - return STATUS_SUCCESS; - } - } - } - } - - return STATUS_OBJECT_NAME_NOT_FOUND; -} - -static USHORT -CmiGetPackedNameLength( - IN PCUNICODE_STRING Name, - OUT PBOOLEAN pPackable) -{ - USHORT i; - - *pPackable = TRUE; - - for (i = 0; i < Name->Length / sizeof(WCHAR); i++) - { - if (Name->Buffer[i] & 0xFF00) - { - *pPackable = FALSE; - return Name->Length; - } - } - - return (Name->Length / sizeof(WCHAR)); -} - -static NTSTATUS -CmiAllocateValueCell( - IN PCMHIVE RegistryHive, - OUT PCM_KEY_VALUE *ValueCell, - OUT HCELL_INDEX *VBOffset, - IN PCUNICODE_STRING ValueName, - IN HSTORAGE_TYPE Storage) -{ - PCM_KEY_VALUE NewValueCell; - BOOLEAN Packable; - USHORT NameLength, i; - NTSTATUS Status; - - Status = STATUS_SUCCESS; - - NameLength = CmiGetPackedNameLength(ValueName, &Packable); - - DPRINT("ValueName->Length %u NameLength %u\n", ValueName->Length, NameLength); - - *VBOffset = HvAllocateCell(&RegistryHive->Hive, sizeof(CM_KEY_VALUE) + NameLength, Storage, HCELL_NIL); - if (*VBOffset == HCELL_NIL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - NewValueCell = (PCM_KEY_VALUE)HvGetCell (&RegistryHive->Hive, *VBOffset); - NewValueCell->Signature = CM_KEY_VALUE_SIGNATURE; - NewValueCell->NameLength = (USHORT)NameLength; - if (Packable) - { - /* Pack the value name */ - for (i = 0; i < NameLength; i++) - { - ((PCHAR)NewValueCell->Name)[i] = (CHAR)ValueName->Buffer[i]; - } - NewValueCell->Flags |= VALUE_COMP_NAME; - } - else - { - /* Copy the value name */ - RtlCopyMemory(NewValueCell->Name, - ValueName->Buffer, - NameLength); - NewValueCell->Flags = 0; - } - NewValueCell->Type = 0; - NewValueCell->DataLength = 0; - NewValueCell->Data = HCELL_NIL; - *ValueCell = NewValueCell; - } - - return Status; -} - NTSTATUS CmiAddValueKey( IN PCMHIVE RegistryHive, - IN HCELL_INDEX KeyCellOffset, + IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING ValueName, OUT PCM_KEY_VALUE *pValueCell, OUT HCELL_INDEX *pValueCellOffset) { - PVALUE_LIST_CELL ValueListCell; - PCM_KEY_NODE KeyCell; + PCELL_DATA ValueListCell; PCM_KEY_VALUE NewValueCell; HCELL_INDEX ValueListCellOffset; HCELL_INDEX NewValueCellOffset; ULONG CellSize; HSTORAGE_TYPE Storage; - NTSTATUS Status; - KeyCell = HvGetCell(&RegistryHive->Hive, KeyCellOffset); - if (!KeyCell) - return STATUS_UNSUCCESSFUL; +#ifndef FIELD_SIZE +#define FIELD_SIZE(type, field) (sizeof(((type *)0)->field)) +#endif - Storage = (KeyCell->Flags & KEY_IS_VOLATILE) ? Volatile : Stable; - if (KeyCell->ValueList.List == HCELL_NIL) + Storage = (Parent->Flags & KEY_IS_VOLATILE) ? Volatile : Stable; + if (Parent->ValueList.List == HCELL_NIL) { /* Allocate some room for the value list */ - CellSize = sizeof(VALUE_LIST_CELL) + (3 * sizeof(HCELL_INDEX)); + CellSize = FIELD_SIZE(CELL_DATA, u.KeyList) + (3 * sizeof(HCELL_INDEX)); ValueListCellOffset = HvAllocateCell(&RegistryHive->Hive, CellSize, Storage, HCELL_NIL); if (ValueListCellOffset == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES; - ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, ValueListCellOffset); + ValueListCell = (PCELL_DATA)HvGetCell(&RegistryHive->Hive, ValueListCellOffset); if (!ValueListCell) + { + HvFreeCell(&RegistryHive->Hive, ValueListCellOffset); return STATUS_UNSUCCESSFUL; + } - KeyCell->ValueList.List = ValueListCellOffset; - HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE); + Parent->ValueList.List = ValueListCellOffset; } else { - ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List); + ValueListCell = (PCELL_DATA)HvGetCell(&RegistryHive->Hive, Parent->ValueList.List); if (!ValueListCell) return STATUS_UNSUCCESSFUL; CellSize = ABS_VALUE(HvGetCellSize(&RegistryHive->Hive, ValueListCell)); - if (KeyCell->ValueList.Count >= CellSize / sizeof(HCELL_INDEX)) + if (Parent->ValueList.Count >= CellSize / sizeof(HCELL_INDEX)) { CellSize *= 2; - ValueListCellOffset = HvReallocateCell(&RegistryHive->Hive, KeyCell->ValueList.List, CellSize); + ValueListCellOffset = HvReallocateCell(&RegistryHive->Hive, Parent->ValueList.List, CellSize); if (ValueListCellOffset == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES; - ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, ValueListCellOffset); + ValueListCell = (PCELL_DATA)HvGetCell(&RegistryHive->Hive, ValueListCellOffset); if (!ValueListCell) return STATUS_UNSUCCESSFUL; - KeyCell->ValueList.List = ValueListCellOffset; - HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE); + Parent->ValueList.List = ValueListCellOffset; } } - Status = CmiAllocateValueCell(RegistryHive, - &NewValueCell, - &NewValueCellOffset, - ValueName, - Storage); - if (!NT_SUCCESS(Status)) - return Status; - ValueListCell->ValueOffset[KeyCell->ValueList.Count] = NewValueCellOffset; - KeyCell->ValueList.Count++; - if (NewValueCell->Flags & VALUE_COMP_NAME) + NewValueCellOffset = HvAllocateCell(&RegistryHive->Hive, + FIELD_OFFSET(CM_KEY_VALUE, Name) + + CmpNameSize(&RegistryHive->Hive, (PUNICODE_STRING)ValueName), + Storage, + HCELL_NIL); + if (NewValueCellOffset == HCELL_NIL) { - if (NewValueCell->NameLength*sizeof(WCHAR) > KeyCell->MaxValueNameLen) - KeyCell->MaxValueNameLen = NewValueCell->NameLength*sizeof(WCHAR); + return STATUS_INSUFFICIENT_RESOURCES; + } + + NewValueCell = (PCM_KEY_VALUE)HvGetCell(&RegistryHive->Hive, NewValueCellOffset); + if (NewValueCell == NULL) + { + HvFreeCell(&RegistryHive->Hive, NewValueCellOffset); + return STATUS_INSUFFICIENT_RESOURCES; + } + + NewValueCell->Signature = CM_KEY_VALUE_SIGNATURE; + NewValueCell->NameLength = CmpCopyName(&RegistryHive->Hive, + NewValueCell->Name, + (PUNICODE_STRING)ValueName); + + /* Check for compressed name */ + if (NewValueCell->NameLength < ValueName->Length) + { + /* This is a compressed name */ + NewValueCell->Flags = VALUE_COMP_NAME; } else { - if (NewValueCell->NameLength > KeyCell->MaxValueNameLen) - KeyCell->MaxValueNameLen = NewValueCell->NameLength; + /* No flags to set */ + NewValueCell->Flags = 0; } - HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE); - HvMarkCellDirty(&RegistryHive->Hive, KeyCell->ValueList.List, FALSE); + NewValueCell->Type = 0; + NewValueCell->DataLength = 0; + NewValueCell->Data = HCELL_NIL; + + + ValueListCell->u.KeyList[Parent->ValueList.Count] = NewValueCellOffset; + Parent->ValueList.Count++; + + HvMarkCellDirty(&RegistryHive->Hive, Parent->ValueList.List, FALSE); HvMarkCellDirty(&RegistryHive->Hive, NewValueCellOffset, FALSE); *pValueCell = NewValueCell; @@ -622,53 +446,3 @@ CmiAddValueKey( return STATUS_SUCCESS; } - -NTSTATUS -CmiScanForValueKey( - IN PCMHIVE RegistryHive, - IN HCELL_INDEX KeyCellOffset, - IN PCUNICODE_STRING ValueName, - OUT PCM_KEY_VALUE *pValueCell, - OUT HCELL_INDEX *pValueCellOffset) -{ - PCM_KEY_NODE KeyCell; - PVALUE_LIST_CELL ValueListCell; - PCM_KEY_VALUE CurValueCell; - ULONG i; - - KeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, KeyCellOffset); - if (!KeyCell) - return STATUS_UNSUCCESSFUL; - - *pValueCell = NULL; - *pValueCellOffset = HCELL_NIL; - - /* The key does not have any values */ - if (KeyCell->ValueList.List == HCELL_NIL) - { - return STATUS_OBJECT_NAME_NOT_FOUND; - } - - ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List); - - VERIFY_VALUE_LIST_CELL(ValueListCell); - - for (i = 0; i < KeyCell->ValueList.Count; i++) - { - CurValueCell = (PCM_KEY_VALUE)HvGetCell(&RegistryHive->Hive, - ValueListCell->ValueOffset[i]); - - if (CmComparePackedNames(ValueName, - (PUCHAR)CurValueCell->Name, - CurValueCell->NameLength, - (CurValueCell->Flags & VALUE_COMP_NAME) ? TRUE : FALSE, - TRUE)) - { - *pValueCell = CurValueCell; - *pValueCellOffset = ValueListCell->ValueOffset[i]; - return STATUS_SUCCESS; - } - } - - return STATUS_OBJECT_NAME_NOT_FOUND; -} diff --git a/reactos/tools/mkhive/cmi.h b/reactos/tools/mkhive/cmi.h index a61f65f58fa..2d1762392ea 100644 --- a/reactos/tools/mkhive/cmi.h +++ b/reactos/tools/mkhive/cmi.h @@ -16,7 +16,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* COPYRIGHT: See COPYING in the top level directory +/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS hive maker * FILE: tools/mkhive/cmi.h * PURPOSE: Registry file manipulation routines @@ -24,42 +25,31 @@ */ #define VERIFY_KEY_CELL(key) -#define VERIFY_VALUE_LIST_CELL(cell) NTSTATUS -CmiInitializeTempHive( - IN OUT PCMHIVE Hive); +CmiInitializeHive( + IN OUT PCMHIVE Hive, + IN PCWSTR Name); + +NTSTATUS +CmiCreateSecurityKey( + IN PHHIVE Hive, + IN HCELL_INDEX Cell, + IN PUCHAR Descriptor, + IN ULONG DescriptorLength); NTSTATUS CmiAddSubKey( IN PCMHIVE RegistryHive, IN HCELL_INDEX ParentKeyCellOffset, IN PCUNICODE_STRING SubKeyName, - IN ULONG CreateOptions, - OUT PCM_KEY_NODE *pSubKeyCell, - OUT HCELL_INDEX *pBlockOffset); - -NTSTATUS -CmiScanForSubKey( - IN PCMHIVE RegistryHive, - IN HCELL_INDEX ParentKeyCellOffset, - IN PCUNICODE_STRING SubKeyName, - IN ULONG Attributes, - OUT PCM_KEY_NODE *pSubKeyCell, + IN BOOLEAN VolatileKey, OUT HCELL_INDEX *pBlockOffset); NTSTATUS CmiAddValueKey( IN PCMHIVE RegistryHive, - IN HCELL_INDEX KeyCellOffset, - IN PCUNICODE_STRING ValueName, - OUT PCM_KEY_VALUE *pValueCell, - OUT HCELL_INDEX *pValueCellOffset); - -NTSTATUS -CmiScanForValueKey( - IN PCMHIVE RegistryHive, - IN HCELL_INDEX KeyCellOffset, + IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING ValueName, OUT PCM_KEY_VALUE *pValueCell, OUT HCELL_INDEX *pValueCellOffset); diff --git a/reactos/tools/mkhive/mkhive.c b/reactos/tools/mkhive/mkhive.c index e647e6a03e1..5d657ef05aa 100644 --- a/reactos/tools/mkhive/mkhive.c +++ b/reactos/tools/mkhive/mkhive.c @@ -16,7 +16,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* COPYRIGHT: See COPYING in the top level directory +/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS hive maker * FILE: tools/mkhive/mkhive.c * PURPOSE: Hive maker @@ -33,7 +34,7 @@ #ifdef _MSC_VER #include #define PATH_MAX _MAX_PATH -#endif//_MSC_VER +#endif // _MSC_VER #ifndef _WIN32 #ifndef PATH_MAX diff --git a/reactos/tools/mkhive/mkhive.h b/reactos/tools/mkhive/mkhive.h index 6c31d78ac0f..02f623c06b7 100644 --- a/reactos/tools/mkhive/mkhive.h +++ b/reactos/tools/mkhive/mkhive.h @@ -16,7 +16,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* COPYRIGHT: See COPYING in the top level directory +/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS hive maker * FILE: tools/mkhive/mkhive.h * PURPOSE: Hive maker @@ -54,6 +55,7 @@ unsigned char BitScanReverse(ULONG * const Index, unsigned long Mask); typedef DWORD REGSAM; typedef LPVOID LPSECURITY_ATTRIBUTES; +typedef HANDLE HKEY, *PHKEY; NTSTATUS NTAPI RtlAnsiStringToUnicodeString( @@ -122,8 +124,6 @@ RegOpenKeyW( #define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\') -#define HIVE_NO_FILE 2 -#define VERIFY_REGISTRY_HIVE(hive) extern LIST_ENTRY CmiHiveListHead; #define ABS_VALUE(V) (((V) < 0) ? -(V) : (V)) #define PAGED_CODE() diff --git a/reactos/tools/mkhive/registry.c b/reactos/tools/mkhive/registry.c index 7174ebd62c3..0c678b08adf 100644 --- a/reactos/tools/mkhive/registry.c +++ b/reactos/tools/mkhive/registry.c @@ -16,7 +16,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* COPYRIGHT: See COPYING in the top level directory +/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS hive maker * FILE: tools/mkhive/registry.c * PURPOSE: Registry code @@ -25,9 +26,7 @@ /* * TODO: - * - Implement RegDeleteKeyW() - * - Implement RegEnumValue() - * - Implement RegQueryValueExW() + * - Implement RegDeleteKeyW() and RegDeleteValueW() */ #include @@ -37,9 +36,6 @@ #define NDEBUG #include "mkhive.h" -#define REG_DATA_SIZE_MASK 0x7FFFFFFF -#define REG_DATA_IN_OFFSET 0x80000000 - static CMHIVE RootHive; static PMEMKEY RootKey; CMHIVE DefaultHive; /* \Registry\User\.DEFAULT */ @@ -49,6 +45,291 @@ CMHIVE SoftwareHive; /* \Registry\Machine\SOFTWARE */ CMHIVE SystemHive; /* \Registry\Machine\SYSTEM */ CMHIVE BcdHive; /* \Registry\Machine\BCD00000000 */ +// +// TODO: Write these values in a more human-readable form. +// See http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/Registry%20Structure%20-%20Appendices%20V4.pdf +// Appendix 12 "The Registry NT Security Descriptor" for more information. +// +// Those SECURITY_DESCRIPTORs were obtained by dumping the security block "sk" +// of registry hives created by setting their permissions to be the same as +// the ones of the BCD, SOFTWARE, or SYSTEM, SAM and .DEFAULT system hives. +// A cross-check was subsequently done with the system hives to verify that +// the security descriptors were the same. +// +UCHAR BcdSecurity[] = +{ + // SECURITY_DESCRIPTOR_RELATIVE + 0x01, // Revision + 0x00, // Sbz1 + 0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) | + // SE_DACL_PROTECTED (0x1000) | + // SE_DACL_AUTO_INHERITED (0x0400) | + // SE_DACL_PRESENT (0x0004) + 0x48, 0x00, 0x00, 0x00, // Owner + 0x58, 0x00, 0x00, 0x00, // Group + 0x00, 0x00, 0x00, 0x00, // Sacl (None) + 0x14, 0x00, 0x00, 0x00, // Dacl + + // DACL + 0x02, // AclRevision + 0x00, // Sbz1 + 0x34, 0x00, // AclSize + 0x02, 0x00, // AceCount + 0x00, 0x00, // Sbz2 + + // (1st ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x18, 0x00, // AceSize + 0x19, 0x00, 0x06, 0x00, // ACCESS_MASK: "Write DAC" (0x00040000) | + // "Read Control" (0x00020000) | + // "Notify" (0x00000010) | + // "Enumerate Subkeys" (0x00000008) | + // "Query Value" (0x00000001) + // (SidStart: S-1-5-32-544 "Administrators") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, + + // (2nd ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x14, 0x00, // AceSize + 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) + // (SidStart: S-1-5-18 "Local System") + 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x12, 0x00, 0x00, 0x00, + + // Owner SID (S-1-5-32-544 "Administrators") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, + + // Group SID (S-1-5-21-domain-513 "Domain Users") + 0x01, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x15, 0x00, 0x00, 0x00, + 0xAC, 0xD0, 0x49, 0xCB, + 0xE6, 0x52, 0x47, 0x9C, + 0xE4, 0x31, 0xDB, 0x5C, + 0x01, 0x02, 0x00, 0x00 +}; + +UCHAR SoftwareSecurity[] = +{ + // SECURITY_DESCRIPTOR_RELATIVE + 0x01, // Revision + 0x00, // Sbz1 + 0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) | + // SE_DACL_PROTECTED (0x1000) | + // SE_DACL_AUTO_INHERITED (0x0400) | + // SE_DACL_PRESENT (0x0004) + 0xA0, 0x00, 0x00, 0x00, // Owner + 0xB0, 0x00, 0x00, 0x00, // Group + 0x00, 0x00, 0x00, 0x00, // Sacl (None) + 0x14, 0x00, 0x00, 0x00, // Dacl + + // DACL + 0x02, // AclRevision + 0x00, // Sbz1 + 0x8C, 0x00, // AclSize + 0x06, 0x00, // AceCount + 0x00, 0x00, // Sbz2 + + // (1st ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x18, 0x00, // AceSize + 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) + // (SidStart: S-1-5-32-544 "Administrators") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, + + // (2nd ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x0A, // AceFlags: INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE + 0x14, 0x00, // AceSize + 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) + // (SidStart: S-1-3-0 "Creator Owner") + 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, + + // (3rd ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x14, 0x00, // AceSize + 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) + // (SidStart: S-1-5-18 "Local System") + 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x12, 0x00, 0x00, 0x00, + + // (4th ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x14, 0x00, // AceSize + 0x1F, 0x00, 0x03, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | + // "Delete" (0x00010000) | + // "Notify" (0x00000010) | + // "Enumerate Subkeys" (0x00000008) | + // "Create Subkey" (0x00000004) | + // "Set Value" (0x00000002) | + // "Query Value" (0x00000001) + // (SidStart: S-1-5-13 "Terminal Server Users") + 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x0D, 0x00, 0x00, 0x00, + + // (5th ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x18, 0x00, // AceSize + 0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | + // "Notify" (0x00000010) | + // "Enumerate Subkeys" (0x00000008) | + // "Query Value" (0x00000001) + // (SidStart: S-1-5-32-545 "Users") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x21, 0x02, 0x00, 0x00, + + // (6th ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x18, 0x00, // AceSize + 0x1F, 0x00, 0x03, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | + // "Delete" (0x00010000) | + // "Notify" (0x00000010) | + // "Enumerate Subkeys" (0x00000008) | + // "Create Subkey" (0x00000004) | + // "Set Value" (0x00000002) | + // "Query Value" (0x00000001) + // (SidStart: S-1-5-32-547 "Power Users") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x23, 0x02, 0x00, 0x00, + + // Owner SID (S-1-5-32-544 "Administrators") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, + + // Group SID (S-1-5-21-domain-513 "Domain Users") + 0x01, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x15, 0x00, 0x00, 0x00, + 0xAC, 0xD0, 0x49, 0xCB, + 0xE6, 0x52, 0x47, 0x9C, + 0xE4, 0x31, 0xDB, 0x5C, + 0x01, 0x02, 0x00, 0x00 +}; + +// Same security for SYSTEM, SAM and .DEFAULT +UCHAR SystemSecurity[] = +{ + // SECURITY_DESCRIPTOR_RELATIVE + 0x01, // Revision + 0x00, // Sbz1 + 0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) | + // SE_DACL_PROTECTED (0x1000) | + // SE_DACL_AUTO_INHERITED (0x0400) | + // SE_DACL_PRESENT (0x0004) + 0x8C, 0x00, 0x00, 0x00, // Owner + 0x9C, 0x00, 0x00, 0x00, // Group + 0x00, 0x00, 0x00, 0x00, // Sacl (None) + 0x14, 0x00, 0x00, 0x00, // Dacl + + // DACL + 0x02, // AclRevision + 0x00, // Sbz1 + 0x78, 0x00, // AclSize + 0x05, 0x00, // AceCount + 0x00, 0x00, // Sbz2 + + // (1st ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x18, 0x00, // AceSize + 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) + // (SidStart: S-1-5-32-544 "Administrators") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, + + // (2nd ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x0A, // AceFlags: INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE + 0x14, 0x00, // AceSize + 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) + // (SidStart: S-1-3-0 "Creator Owner") + 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, + + // (3rd ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x14, 0x00, // AceSize + 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) + // (SidStart: S-1-5-18 "Local System") + 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x12, 0x00, 0x00, 0x00, + + // (4th ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x18, 0x00, // AceSize + 0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | + // "Notify" (0x00000010) | + // "Enumerate Subkeys" (0x00000008) | + // "Query Value" (0x00000001) + // (SidStart: S-1-5-32-545 "Users") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x21, 0x02, 0x00, 0x00, + + // (5th ACE) + 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE + 0x02, // AceFlags: CONTAINER_INHERIT_ACE + 0x18, 0x00, // AceSize + 0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | + // "Notify" (0x00000010) | + // "Enumerate Subkeys" (0x00000008) | + // "Query Value" (0x00000001) + // (SidStart: S-1-5-32-547 "Power Users") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x23, 0x02, 0x00, 0x00, + + // Owner SID (S-1-5-32-544 "Administrators") + 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x20, 0x00, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, + + // Group SID (S-1-5-21-domain-513 "Domain Users") + 0x01, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, + 0x15, 0x00, 0x00, 0x00, + 0xAC, 0xD0, 0x49, 0xCB, + 0xE6, 0x52, 0x47, 0x9C, + 0xE4, 0x31, 0xDB, 0x5C, + 0x01, 0x02, 0x00, 0x00 +}; + static PMEMKEY CreateInMemoryStructure( IN PCMHIVE RegistryHive, @@ -56,7 +337,7 @@ CreateInMemoryStructure( { PMEMKEY Key; - Key = (PMEMKEY) malloc (sizeof(MEMKEY)); + Key = (PMEMKEY)malloc(sizeof(MEMKEY)); if (!Key) return NULL; @@ -83,13 +364,14 @@ RegpOpenOrCreateKey( PMEMKEY CurrentKey; PCMHIVE ParentRegistryHive; HCELL_INDEX ParentCellOffset; + PCM_KEY_NODE ParentKeyCell; PLIST_ENTRY Ptr; PCM_KEY_NODE SubKeyCell; HCELL_INDEX BlockOffset; DPRINT("RegpCreateOpenKey('%S')\n", KeyName); - if (*KeyName == L'\\') + if (*KeyName == OBJ_NAME_PATH_SEPARATOR) { KeyName++; ParentRegistryHive = RootKey->RegistryHive; @@ -102,14 +384,14 @@ RegpOpenOrCreateKey( } else { - ParentRegistryHive = HKEY_TO_MEMKEY(RootKey)->RegistryHive; - ParentCellOffset = HKEY_TO_MEMKEY(RootKey)->KeyCellOffset; + ParentRegistryHive = HKEY_TO_MEMKEY(hParentKey)->RegistryHive; + ParentCellOffset = HKEY_TO_MEMKEY(hParentKey)->KeyCellOffset; } LocalKeyName = (PWSTR)KeyName; for (;;) { - End = (PWSTR)strchrW(LocalKeyName, '\\'); + End = (PWSTR)strchrW(LocalKeyName, OBJ_NAME_PATH_SEPARATOR); if (End) { KeyString.Buffer = LocalKeyName; @@ -121,19 +403,22 @@ RegpOpenOrCreateKey( RtlInitUnicodeString(&KeyString, LocalKeyName); if (KeyString.Length == 0) { - /* Trailing backslash char; we're done */ + /* Trailing path separator: we're done */ break; } } - Status = CmiScanForSubKey(ParentRegistryHive, - ParentCellOffset, - &KeyString, - OBJ_CASE_INSENSITIVE, - &SubKeyCell, - &BlockOffset); - if (NT_SUCCESS(Status)) + ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&ParentRegistryHive->Hive, ParentCellOffset); + if (!ParentKeyCell) + return STATUS_UNSUCCESSFUL; + + VERIFY_KEY_CELL(ParentKeyCell); + + BlockOffset = CmpFindSubKeyByName(&ParentRegistryHive->Hive, ParentKeyCell, &KeyString); + if (BlockOffset != HCELL_NIL) { + Status = STATUS_SUCCESS; + /* Search for a possible reparse point */ Ptr = CmiReparsePointsHead.Flink; while (Ptr != &CmiReparsePointsHead) @@ -149,19 +434,20 @@ RegpOpenOrCreateKey( Ptr = Ptr->Flink; } } - else if (Status == STATUS_OBJECT_NAME_NOT_FOUND && AllowCreation) + else if (AllowCreation) // && (BlockOffset == HCELL_NIL) { Status = CmiAddSubKey(ParentRegistryHive, ParentCellOffset, &KeyString, - Volatile ? REG_OPTION_VOLATILE : 0, - &SubKeyCell, + Volatile, &BlockOffset); } + + HvReleaseCell(&ParentRegistryHive->Hive, ParentCellOffset); + if (!NT_SUCCESS(Status)) return ERROR_UNSUCCESSFUL; -nextsubkey: ParentCellOffset = BlockOffset; if (End) LocalKeyName = End + 1; @@ -172,6 +458,7 @@ nextsubkey: CurrentKey = CreateInMemoryStructure(ParentRegistryHive, ParentCellOffset); if (!CurrentKey) return ERROR_OUTOFMEMORY; + *Key = MEMKEY_TO_HKEY(CurrentKey); return ERROR_SUCCESS; @@ -186,56 +473,16 @@ RegCreateKeyW( return RegpOpenOrCreateKey(hKey, lpSubKey, TRUE, FALSE, phkResult); } -static PWSTR -MultiByteToWideChar( - IN PCSTR MultiByteString) -{ - ANSI_STRING Source; - UNICODE_STRING Destination; - NTSTATUS Status; - - RtlInitAnsiString(&Source, MultiByteString); - Status = RtlAnsiStringToUnicodeString(&Destination, &Source, TRUE); - if (!NT_SUCCESS(Status)) - return NULL; - return Destination.Buffer; -} - LONG WINAPI RegDeleteKeyW( IN HKEY hKey, IN LPCWSTR lpSubKey) { - DPRINT1("FIXME: implement RegDeleteKeyW!\n"); + DPRINT1("RegDeleteKeyW(0x%p, '%S') is UNIMPLEMENTED!\n", + hKey, (lpSubKey ? lpSubKey : L"")); return ERROR_SUCCESS; } -LONG WINAPI -RegDeleteKeyA( - IN HKEY hKey, - IN LPCSTR lpSubKey) -{ - PWSTR lpSubKeyW = NULL; - LONG rc; - - if (lpSubKey != NULL && strchr(lpSubKey, '\\') != NULL) - return ERROR_INVALID_PARAMETER; - - if (lpSubKey) - { - lpSubKeyW = MultiByteToWideChar(lpSubKey); - if (!lpSubKeyW) - return ERROR_OUTOFMEMORY; - } - - rc = RegDeleteKeyW(hKey, lpSubKeyW); - - if (lpSubKey) - free(lpSubKeyW); - - return rc; -} - LONG WINAPI RegOpenKeyW( IN HKEY hKey, @@ -264,57 +511,6 @@ RegCreateKeyExW( phkResult); } -LONG WINAPI -RegOpenKeyA( - IN HKEY hKey, - IN LPCSTR lpSubKey, - OUT PHKEY phkResult) -{ - PWSTR lpSubKeyW; - LONG rc; - - lpSubKeyW = MultiByteToWideChar(lpSubKey); - if (!lpSubKeyW) - return ERROR_OUTOFMEMORY; - - rc = RegOpenKeyW(hKey, lpSubKeyW, phkResult); - free(lpSubKeyW); - return rc; -} - -static LONG -RegpOpenOrCreateValue( - IN HKEY hKey, - IN LPCWSTR ValueName, - IN BOOL AllowCreation, - OUT PCM_KEY_VALUE *ValueCell, - OUT PHCELL_INDEX ValueCellOffset) -{ - PMEMKEY ParentKey; - UNICODE_STRING ValueString; - NTSTATUS Status; - - ParentKey = HKEY_TO_MEMKEY(hKey); - RtlInitUnicodeString(&ValueString, ValueName); - - Status = CmiScanForValueKey(ParentKey->RegistryHive, - ParentKey->KeyCellOffset, - &ValueString, - ValueCell, - ValueCellOffset); - if (AllowCreation && Status == STATUS_OBJECT_NAME_NOT_FOUND) - { - Status = CmiAddValueKey(ParentKey->RegistryHive, - ParentKey->KeyCellOffset, - &ValueString, - ValueCell, - ValueCellOffset); - } - if (!NT_SUCCESS(Status)) - return ERROR_UNSUCCESSFUL; - return ERROR_SUCCESS; -} - LONG WINAPI RegSetValueExW( IN HKEY hKey, @@ -324,49 +520,84 @@ RegSetValueExW( IN const UCHAR* lpData, IN USHORT cbData) { - PMEMKEY Key, DestKey; - PHKEY phKey; + PMEMKEY Key = HKEY_TO_MEMKEY(hKey); // ParentKey + PHHIVE Hive; + PCM_KEY_NODE KeyNode; // ParentNode PCM_KEY_VALUE ValueCell; - HCELL_INDEX ValueCellOffset; + HCELL_INDEX CellIndex; + UNICODE_STRING ValueNameString; + PVOID DataCell; LONG DataCellSize; NTSTATUS Status; if (dwType == REG_LINK) { + PMEMKEY DestKey; + /* Special handling of registry links */ if (cbData != sizeof(PVOID)) return STATUS_INVALID_PARAMETER; - phKey = (PHKEY)lpData; - Key = HKEY_TO_MEMKEY(hKey); - DestKey = HKEY_TO_MEMKEY(*phKey); + DestKey = HKEY_TO_MEMKEY(*(PHKEY)lpData); + + // FIXME: Add additional checks for the validity of DestKey /* Create the link in registry hive (if applicable) */ if (Key->RegistryHive != DestKey->RegistryHive) return STATUS_SUCCESS; + DPRINT1("Save link to registry\n"); return STATUS_NOT_IMPLEMENTED; } - if ((cbData & REG_DATA_SIZE_MASK) != cbData) + if ((cbData & ~CM_KEY_VALUE_SPECIAL_SIZE) != cbData) return STATUS_UNSUCCESSFUL; - Key = HKEY_TO_MEMKEY(hKey); + Hive = &Key->RegistryHive->Hive; + + KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Key->KeyCellOffset); + if (!KeyNode) + return ERROR_UNSUCCESSFUL; + + ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE); + + /* Mark the parent as dirty since we are going to create a new value in it */ + HvMarkCellDirty(Hive, Key->KeyCellOffset, FALSE); + + /* Initialize value name string */ + RtlInitUnicodeString(&ValueNameString, lpValueName); + CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString); + if (CellIndex == HCELL_NIL) + { + /* The value doesn't exist, create a new one */ + Status = CmiAddValueKey(Key->RegistryHive, + KeyNode, + &ValueNameString, + &ValueCell, + &CellIndex); + } + else + { + /* The value already exists, use it. Get the value cell. */ + ValueCell = HvGetCell(&Key->RegistryHive->Hive, CellIndex); + ASSERT(ValueCell != NULL); + } + + // /**/HvReleaseCell(Hive, CellIndex);/**/ - Status = RegpOpenOrCreateValue(hKey, lpValueName, TRUE, &ValueCell, &ValueCellOffset); if (!NT_SUCCESS(Status)) return ERROR_UNSUCCESSFUL; - /* Get size of the allocated cellule (if any) */ - if (!(ValueCell->DataLength & REG_DATA_IN_OFFSET) && - (ValueCell->DataLength & REG_DATA_SIZE_MASK) != 0) + /* Get size of the allocated cell (if any) */ + if (!(ValueCell->DataLength & CM_KEY_VALUE_SPECIAL_SIZE) && + (ValueCell->DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE) != 0) { - DataCell = HvGetCell(&Key->RegistryHive->Hive, ValueCell->Data); + DataCell = HvGetCell(Hive, ValueCell->Data); if (!DataCell) return ERROR_UNSUCCESSFUL; - DataCellSize = -HvGetCellSize(&Key->RegistryHive->Hive, DataCell); + DataCellSize = -HvGetCellSize(Hive, DataCell); } else { @@ -379,12 +610,11 @@ RegSetValueExW( /* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */ DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength); if (DataCell) - HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data); + HvFreeCell(Hive, ValueCell->Data); RtlCopyMemory(&ValueCell->Data, lpData, cbData); - ValueCell->DataLength = (ULONG)(cbData | REG_DATA_IN_OFFSET); + ValueCell->DataLength = (ULONG)(cbData | CM_KEY_VALUE_SPECIAL_SIZE); ValueCell->Type = dwType; - HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE); } else { @@ -396,7 +626,7 @@ RegSetValueExW( DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength); - NewOffset = HvAllocateCell(&Key->RegistryHive->Hive, cbData, Stable, HCELL_NIL); + NewOffset = HvAllocateCell(Hive, cbData, Stable, HCELL_NIL); if (NewOffset == HCELL_NIL) { DPRINT("HvAllocateCell() failed with status 0x%08x\n", Status); @@ -404,52 +634,114 @@ RegSetValueExW( } if (DataCell) - HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data); + HvFreeCell(Hive, ValueCell->Data); ValueCell->Data = NewOffset; - DataCell = (PVOID)HvGetCell(&Key->RegistryHive->Hive, NewOffset); + DataCell = (PVOID)HvGetCell(Hive, NewOffset); } - /* Copy new contents to cellule */ + /* Copy new contents to cell */ RtlCopyMemory(DataCell, lpData, cbData); - ValueCell->DataLength = (ULONG)(cbData & REG_DATA_SIZE_MASK); + ValueCell->DataLength = (ULONG)(cbData & ~CM_KEY_VALUE_SPECIAL_SIZE); ValueCell->Type = dwType; - HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCell->Data, FALSE); - HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE); + HvMarkCellDirty(Hive, ValueCell->Data, FALSE); } - HvMarkCellDirty(&Key->RegistryHive->Hive, Key->KeyCellOffset, FALSE); + HvMarkCellDirty(Hive, CellIndex, FALSE); + + /* Check if the maximum value name length changed, update it if so */ + if (KeyNode->MaxValueNameLen < ValueNameString.Length) + KeyNode->MaxValueNameLen = ValueNameString.Length; + + /* Check if the maximum data length changed, update it if so */ + if (KeyNode->MaxValueDataLen < cbData) + KeyNode->MaxValueDataLen = cbData; + + /* Save the write time */ + KeQuerySystemTime(&KeyNode->LastWriteTime); DPRINT("Return status 0x%08x\n", Status); return Status; } + +// Synced with freeldr/windows/registry.c +static +VOID +RepGetValueData( + IN PHHIVE Hive, + IN PCM_KEY_VALUE ValueCell, + OUT ULONG* Type OPTIONAL, + OUT PUCHAR Data OPTIONAL, + IN OUT ULONG* DataSize OPTIONAL) +{ + ULONG DataLength; + PVOID DataCell; + + /* Does the caller want the type? */ + if (Type != NULL) + *Type = ValueCell->Type; + + /* Does the caller provide DataSize? */ + if (DataSize != NULL) + { + // NOTE: CmpValueToData doesn't support big data (the function will + // bugcheck if so), FreeLdr is not supposed to read such data. + // If big data is needed, use instead CmpGetValueData. + // CmpGetValueData(Hive, ValueCell, DataSize, &DataCell, ...); + DataCell = CmpValueToData(Hive, ValueCell, &DataLength); + + /* Does the caller want the data? */ + if ((Data != NULL) && (*DataSize != 0)) + { + RtlCopyMemory(Data, + DataCell, + min(*DataSize, DataLength)); + } + + /* Return the actual data length */ + *DataSize = DataLength; + } +} + +// Similar to RegQueryValue in freeldr/windows/registry.c LONG WINAPI RegQueryValueExW( IN HKEY hKey, IN LPCWSTR lpValueName, IN PULONG lpReserved, - OUT PULONG lpType, - OUT PUCHAR lpData, - OUT PSIZE_T lpcbData) + OUT PULONG lpType OPTIONAL, + OUT PUCHAR lpData OPTIONAL, + IN OUT PSIZE_T lpcbData OPTIONAL) { - //ParentKey = HKEY_TO_MEMKEY(RootKey); + PMEMKEY ParentKey = HKEY_TO_MEMKEY(hKey); + PHHIVE Hive = &ParentKey->RegistryHive->Hive; + PCM_KEY_NODE KeyNode; PCM_KEY_VALUE ValueCell; - HCELL_INDEX ValueCellOffset; - LONG rc; + HCELL_INDEX CellIndex; + UNICODE_STRING ValueNameString; - rc = RegpOpenOrCreateValue(hKey, - lpValueName, - FALSE, - &ValueCell, - &ValueCellOffset); - if (rc != ERROR_SUCCESS) - return rc; + KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey->KeyCellOffset); + if (!KeyNode) + return ERROR_UNSUCCESSFUL; - DPRINT1("RegQueryValueExW(%S) not implemented\n", lpValueName); - /* ValueCell and ValueCellOffset are valid */ + ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE); - return ERROR_UNSUCCESSFUL; + /* Initialize value name string */ + RtlInitUnicodeString(&ValueNameString, lpValueName); + CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString); + if (CellIndex == HCELL_NIL) + return ERROR_FILE_NOT_FOUND; + + /* Get the value cell */ + ValueCell = HvGetCell(Hive, CellIndex); + ASSERT(ValueCell != NULL); + + RepGetValueData(Hive, ValueCell, lpType, lpData, lpcbData); + + HvReleaseCell(Hive, CellIndex); + + return ERROR_SUCCESS; } LONG WINAPI @@ -457,14 +749,18 @@ RegDeleteValueW( IN HKEY hKey, IN LPCWSTR lpValueName OPTIONAL) { - DPRINT1("RegDeleteValueW() unimplemented\n"); + DPRINT1("RegDeleteValueW(0x%p, '%S') is UNIMPLEMENTED!\n", + hKey, (lpValueName ? lpValueName : L"")); return ERROR_UNSUCCESSFUL; } + static BOOL ConnectRegistry( IN HKEY RootKey, IN PCMHIVE HiveToConnect, + IN PUCHAR Descriptor, + IN ULONG DescriptorLength, IN LPCWSTR Path) { NTSTATUS Status; @@ -476,14 +772,32 @@ ConnectRegistry( if (!ReparsePoint) return FALSE; - Status = CmiInitializeTempHive(HiveToConnect); + /* + * Use a dummy root key name: + * - On 2k/XP/2k3, this is "$$$PROTO.HIV" + * - On Vista+, this is "CMI-CreateHive{guid}" + * See https://github.com/libyal/winreg-kb/blob/master/documentation/Registry%20files.asciidoc + * for more information. + */ + Status = CmiInitializeHive(HiveToConnect, L"$$$PROTO.HIV"); if (!NT_SUCCESS(Status)) { - DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status); + DPRINT1("CmiInitializeHive() failed with status 0x%08x\n", Status); free(ReparsePoint); return FALSE; } + /* + * Add security to the root key. + * NOTE: One can implement this using the lpSecurityAttributes + * parameter of RegCreateKeyExW. + */ + Status = CmiCreateSecurityKey(&HiveToConnect->Hive, + HiveToConnect->Hive.BaseBlock->RootCell, + Descriptor, DescriptorLength); + if (!NT_SUCCESS(Status)) + DPRINT1("Failed to add security for root key '%S'\n", Path); + /* Create key */ rc = RegCreateKeyExW(RootKey, Path, @@ -523,10 +837,10 @@ RegInitializeRegistry(VOID) InitializeListHead(&CmiHiveListHead); InitializeListHead(&CmiReparsePointsHead); - Status = CmiInitializeTempHive(&RootHive); + Status = CmiInitializeHive(&RootHive, L""); if (!NT_SUCCESS(Status)) { - DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status); + DPRINT1("CmiInitializeHive() failed with status 0x%08x\n", Status); return; } @@ -536,31 +850,37 @@ RegInitializeRegistry(VOID) /* Create DEFAULT key */ ConnectRegistry(NULL, &DefaultHive, + SystemSecurity, sizeof(SystemSecurity), L"Registry\\User\\.DEFAULT"); /* Create SAM key */ ConnectRegistry(NULL, &SamHive, + SystemSecurity, sizeof(SystemSecurity), L"Registry\\Machine\\SAM"); /* Create SECURITY key */ ConnectRegistry(NULL, &SecurityHive, + NULL, 0, L"Registry\\Machine\\SECURITY"); /* Create SOFTWARE key */ ConnectRegistry(NULL, &SoftwareHive, + SoftwareSecurity, sizeof(SoftwareSecurity), L"Registry\\Machine\\SOFTWARE"); /* Create BCD key */ ConnectRegistry(NULL, &BcdHive, + BcdSecurity, sizeof(BcdSecurity), L"Registry\\Machine\\BCD00000000"); /* Create SYSTEM key */ ConnectRegistry(NULL, &SystemHive, + SystemSecurity, sizeof(SystemSecurity), L"Registry\\Machine\\SYSTEM"); /* Create 'ControlSet001' key */ diff --git a/reactos/tools/mkhive/rtl.c b/reactos/tools/mkhive/rtl.c index 24b7410abd7..4275cf358ba 100644 --- a/reactos/tools/mkhive/rtl.c +++ b/reactos/tools/mkhive/rtl.c @@ -1,4 +1,5 @@ -/* COPYRIGHT: See COPYING in the top level directory +/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS hive maker * FILE: tools/mkhive/rtl.c * PURPOSE: Runtime Library @@ -217,6 +218,23 @@ RtlAssert(PVOID FailedAssertion, //DbgBreakPoint(); } +// DECLSPEC_NORETURN +VOID +NTAPI +KeBugCheckEx( + IN ULONG BugCheckCode, + IN ULONG_PTR BugCheckParameter1, + IN ULONG_PTR BugCheckParameter2, + IN ULONG_PTR BugCheckParameter3, + IN ULONG_PTR BugCheckParameter4) +{ + char Buffer[70]; + printf("*** STOP: 0x%08lX (0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX)", + BugCheckCode, BugCheckParameter1, BugCheckParameter2, + BugCheckParameter3, BugCheckParameter4); + ASSERT(FALSE); +} + unsigned char BitScanForward(ULONG * Index, unsigned long Mask) { *Index = 0;