Author: ion Date: Fri Oct 6 10:27:52 2006 New Revision: 24420
URL: http://svn.reactos.org/svn/reactos?rev=24420&view=rev Log: - Define HIVE_LIST_ENTRY, CM_PARSE_CONTEXT. - Stub CmpReportNotify. - Implement CmpHiveRootSecurityDescriptor, CmpLinkHiveToMaster, CmpInitializeSystemHive. - Rename CmInitializeRegistry to CmInitSystem1 and detect PE boot (/MININT).
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cm.h branches/alex-cm-branch/reactos/ntoskrnl/cm/cmapi.c branches/alex-cm-branch/reactos/ntoskrnl/cm/cmhive.c branches/alex-cm-branch/reactos/ntoskrnl/cm/cminit.c
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cm.h URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cm.h (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cm.h Fri Oct 6 10:27:52 2006 @@ -560,6 +560,40 @@ } CM_CACHED_VALUE, *PCM_CACHED_VALUE;
// +// Hive List Entry +// +typedef struct _HIVE_LIST_ENTRY +{ + PWCHAR FileName; + PWCHAR BaseName; + PWCHAR RegRootName; + PCMHIVE CmHive; + ULONG HHiveFlags; + ULONG CmHiveFlags; + PCMHIVE CmHive2; + BOOLEAN ThreadFinished; + BOOLEAN ThreadStarted; + BOOLEAN Allocate; + BOOLEAN WinPERequired; +} HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY; + +// +// Parse context for Key Object +// +typedef struct _CM_PARSE_CONTEXT +{ + ULONG TitleIndex; + UNICODE_STRING Class; + ULONG CreateOptions; + ULONG Disposition; + CM_KEY_REFERENCE ChildHive; + BOOLEAN CreateLink; + BOOLEAN Flag2; + HANDLE PredefinedHandle; + ULONG PostActions; +} CM_PARSE_CONTEXT, *PCM_PARSE_CONTEXT; + +// // Registry Validation Functions // BOOLEAN @@ -567,6 +601,17 @@ CmCheckRegistry( IN PCMHIVE Hive, IN BOOLEAN CleanFlag +); + +// +// Notification Routines +// +VOID +CmpReportNotify( + IN PCM_KEY_CONTROL_BLOCK Kcb, + IN PHHIVE Hive, + IN HCELL_INDEX Cell, + IN ULONG Filter );
// @@ -666,6 +711,22 @@ IN PUNICODE_STRING FileName );
+PSECURITY_DESCRIPTOR +NTAPI +CmpHiveRootSecurityDescriptor( + VOID +); + +NTSTATUS +NTAPI +CmpLinkHiveToMaster( + IN PUNICODE_STRING LinkName, + IN HANDLE RootDirectory, + IN PCMHIVE CmHive, + IN BOOLEAN Allocate, + IN PSECURITY_DESCRIPTOR SecurityDescriptor +); + // // Registry Utility Functions //
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cmapi.c URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cmapi.c (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cmapi.c Fri Oct 6 10:27:52 2006 @@ -43,3 +43,13 @@ ExReleasePushLock(&CmpHiveListHeadLock); return Flushed; } + +VOID +CmpReportNotify(IN PCM_KEY_CONTROL_BLOCK Kcb, + IN PHHIVE Hive, + IN HCELL_INDEX Cell, + IN ULONG Filter) +{ + /* FIXME: TODO */ + ASSERT(FALSE); +}
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cmhive.c URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cmhive.c (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cmhive.c Fri Oct 6 10:27:52 2006 @@ -323,3 +323,243 @@ return STATUS_SUCCESS; }
+PSECURITY_DESCRIPTOR +NTAPI +CmpHiveRootSecurityDescriptor(VOID) +{ + SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY; + SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; + PSID WorldSid; + PSID RestrictedSid; + PSID SystemSid; + PSID AdminSid; + NTSTATUS Status; + ULONG AceSize, AclSize; + PACL Acl, SdAcl; + PACE_HEADER AceHeader; + PSECURITY_DESCRIPTOR HiveSd; + PAGED_CODE(); + + /* Allocate all the SIDs */ + WorldSid = ExAllocatePoolWithTag(PagedPool, + RtlLengthRequiredSid(1), + TAG_CM); + RestrictedSid = ExAllocatePoolWithTag(PagedPool, + RtlLengthRequiredSid(1), + TAG_CM); + SystemSid = ExAllocatePoolWithTag(PagedPool, + RtlLengthRequiredSid(1), + TAG_CM); + AdminSid = ExAllocatePoolWithTag(PagedPool, + RtlLengthRequiredSid(2), + TAG_CM); + + /* Make sure that all were allocated */ + if (!(WorldSid) || !(RestrictedSid) || !(SystemSid) || !(AdminSid)) + { + /* Fail */ + KeBugCheckEx(REGISTRY_ERROR, 10, 0, 0, 0); + } + + /* Now initialize all the SIDs */ + Status = RtlInitializeSid(WorldSid, &WorldAuthority, 1); + if (NT_SUCCESS(Status)) + { + Status = RtlInitializeSid(RestrictedSid, &NtAuthority, 1); + } + if (NT_SUCCESS(Status)) + { + Status = RtlInitializeSid(SystemSid, &NtAuthority, 1); + } + if (NT_SUCCESS(Status)) + { + Status = RtlInitializeSid(AdminSid, &NtAuthority, 2); + } + if (NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 10, 1, 0, 0); + + /* Setup the sub-authority SIDs */ + *(RtlSubAuthoritySid(WorldSid, 0)) = SECURITY_WORLD_RID; + *(RtlSubAuthoritySid(RestrictedSid, 0)) = SECURITY_RESTRICTED_CODE_RID; + *(RtlSubAuthoritySid(SystemSid, 0)) = SECURITY_LOCAL_SYSTEM_RID; + *(RtlSubAuthoritySid(AdminSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID; + *(RtlSubAuthoritySid(AdminSid, 1)) = DOMAIN_ALIAS_RID_ADMINS; + + /* Sanity checks */ + ASSERT(RtlValidSid(WorldSid)); + ASSERT(RtlValidSid(RestrictedSid)); + ASSERT(RtlValidSid(SystemSid)); + ASSERT(RtlValidSid(AdminSid)); + + /* Calculate length of the ACE */ + AceSize = (SeLengthSid(WorldSid) - + sizeof(ULONG) + sizeof(ACCESS_ALLOWED_ACE)) + + (SeLengthSid(RestrictedSid) - + sizeof(ULONG) + sizeof(ACCESS_ALLOWED_ACE))+ + (SeLengthSid(SystemSid) - + sizeof(ULONG) + sizeof(ACCESS_ALLOWED_ACE)) + + (SeLengthSid(AdminSid) - + sizeof(ULONG) + sizeof(ACCESS_ALLOWED_ACE)); + + /* Calculate the ACL length and allocate it */ + AclSize = AceSize + sizeof(ACL); + Acl = ExAllocatePoolWithTag(PagedPool, AclSize, TAG_CM); + if (!Acl) KeBugCheckEx(REGISTRY_ERROR, 10, 2, 0, 0); + + /* Create it */ + Status = RtlCreateAcl(Acl, AclSize, ACL_REVISION); + if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 10, 3, 0, 0); + + /* Add our ACEs */ + Status = RtlAddAccessAllowedAce(Acl, + ACL_REVISION, + KEY_ALL_ACCESS, + SystemSid); + if (NT_SUCCESS(Status)) + { + Status = RtlAddAccessAllowedAce(Acl, + ACL_REVISION, + KEY_ALL_ACCESS, + AdminSid); + } + if (NT_SUCCESS(Status)) + { + Status = RtlAddAccessAllowedAce(Acl, + ACL_REVISION, + KEY_READ, + WorldSid); + } + if (NT_SUCCESS(Status)) + { + Status = RtlAddAccessAllowedAce(Acl, + ACL_REVISION, + KEY_READ, + RestrictedSid); + } + if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 10, 4, 0, 0); + + /* Get every ACE and turn on the inherit flag */ + Status = RtlGetAce(Acl,0,&AceHeader); + ASSERT(NT_SUCCESS(Status)); + AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; + Status = RtlGetAce(Acl,1,&AceHeader); + ASSERT(NT_SUCCESS(Status)); + AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; + Status = RtlGetAce(Acl,2,&AceHeader); + ASSERT(NT_SUCCESS(Status)); + AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; + Status = RtlGetAce(Acl,3,&AceHeader); + ASSERT(NT_SUCCESS(Status)); + AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; + + /* Allocate the SD */ + HiveSd = ExAllocatePoolWithTag(PagedPool, + AclSize + sizeof(SECURITY_DESCRIPTOR), + TAG_CM); + if (!HiveSd) KeBugCheckEx(REGISTRY_ERROR, 10, 5, 0, 0); + + /* Copy the ACL into it */ + SdAcl = (PACL)((PISECURITY_DESCRIPTOR)HiveSd + 1); + RtlMoveMemory(SdAcl, Acl, AclSize); + + /* Create the SD */ + Status = RtlCreateSecurityDescriptor(HiveSd, SECURITY_DESCRIPTOR_REVISION); + if (!NT_SUCCESS(Status)) + { + /* Failed, free the descriptor and bugcheck */ + ExFreePool(HiveSd); + KeBugCheckEx(REGISTRY_ERROR, 10, 6, 0, 0); + } + + /* Set the DACL */ + Status = RtlSetDaclSecurityDescriptor(HiveSd, TRUE, SdAcl, FALSE); + if (!NT_SUCCESS(Status)) + { + /* Failed, free the descriptor and bugcheck */ + ExFreePool(HiveSd); + KeBugCheckEx(REGISTRY_ERROR, 10, 7, 0, 0); + } + + /* Free all allocations */ + ExFreePool(WorldSid); + ExFreePool(RestrictedSid); + ExFreePool(SystemSid); + ExFreePool(AdminSid); + ExFreePool(Acl); + + /* Return the SD */ + return HiveSd; +} + +NTSTATUS +NTAPI +CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName, + IN HANDLE RootDirectory, + IN PCMHIVE CmHive, + IN BOOLEAN Allocate, + IN PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + CM_PARSE_CONTEXT ParseContext; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + NTSTATUS Status; + PCM_KEY_BODY KeyBody; + PAGED_CODE(); + + /* Fill out the parse context */ + ParseContext.TitleIndex = 0; + ParseContext.Class.Length = 0; + ParseContext.Class.MaximumLength = 0; + ParseContext.Class.Buffer = NULL; + ParseContext.CreateOptions = 0; + ParseContext.CreateLink = TRUE; + ParseContext.Flag2 = TRUE; + ParseContext.PostActions = 0; + ParseContext.ChildHive.KeyHive = &CmHive->Hive; + + /* Check if we're allocating */ + if (Allocate) + { + /* Set no child */ + ParseContext.ChildHive.KeyCell = HCELL_NIL; + } + else + { + /* Otherwise, set the root cell */ + ParseContext.ChildHive.KeyCell = CmHive->Hive.HiveHeader->RootCell; + } + + /* Open the key */ + InitializeObjectAttributes(&ObjectAttributes, + LinkName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + RootDirectory, + SecurityDescriptor); + Status = ObOpenObjectByName(&ObjectAttributes, + CmpKeyObjectType, + KernelMode, + NULL, + KEY_READ | KEY_WRITE, + &ParseContext, + &KeyHandle); + if (!NT_SUCCESS(Status)) return Status; + + /* Reference the key body */ + Status = ObReferenceObjectByHandle(KeyHandle, + 0, + CmpKeyObjectType, + KernelMode, + &KeyBody, + NULL); + ASSERT(NT_SUCCESS(Status)); + + /* Send a notification */ + CmpReportNotify(KeyBody->KeyControlBlock, + KeyBody->KeyControlBlock->KeyHive, + KeyBody->KeyControlBlock->KeyCell, + REG_NOTIFY_CHANGE_NAME); + + /* Dereference the key and close the handle */ + ObDereferenceObject((PVOID)KeyBody); + ZwClose(KeyHandle); + return STATUS_SUCCESS; +}
Modified: branches/alex-cm-branch/reactos/ntoskrnl/cm/cminit.c URL: http://svn.reactos.org/svn/reactos/branches/alex-cm-branch/reactos/ntoskrnl/... ============================================================================== --- branches/alex-cm-branch/reactos/ntoskrnl/cm/cminit.c (original) +++ branches/alex-cm-branch/reactos/ntoskrnl/cm/cminit.c Fri Oct 6 10:27:52 2006 @@ -12,16 +12,29 @@ #define NDEBUG #include <debug.h>
+UNICODE_STRING CmRegistryMachineSystemName = + RTL_CONSTANT_STRING(L"\REGISTRY\MACHINE\SYSTEM"); +UNICODE_STRING CmpSystemFileName = + RTL_CONSTANT_STRING(L"SYSTEM"); + +BOOLEAN CmpMiniNTBoot; +BOOLEAN CmpShareSystemHives; +ULONG CmpBootType; + PEPROCESS CmpSystemProcess; PCMHIVE CmpMasterHive; HANDLE CmpRegistryRootHandle;
+BOOLEAN CmSelfHeal, CmpSelfHeal; KGUARDED_MUTEX CmpSelfHealQueueLock; LIST_ENTRY CmpSelfHealQueueListHead;
+HIVE_LIST_ENTRY CmpMachineHiveList[]; + EX_PUSH_LOCK CmpLoadHiveLock;
UNICODE_STRING CmpSystemStartOptions; +UNICODE_STRING CmpLoadOptions;
ULONG CmpCallBackCount;
@@ -237,9 +250,113 @@ NtClose(KeyHandle); }
+BOOLEAN +NTAPI +CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + PCMHIVE SystemHive; + PVOID HiveImageBase; + BOOLEAN Allocate = FALSE; + PSECURITY_DESCRIPTOR SecurityDescriptor; + NTSTATUS Status; + STRING TempString; + PAGED_CODE(); + + /* Create ANSI_STRING from the loader options */ + RtlInitAnsiString(&TempString, LoaderBlock->LoadOptions); + + /* Setup UNICODE_STRING */ + CmpLoadOptions.Length = 0; + CmpLoadOptions.MaximumLength = TempString.Length * sizeof(WCHAR) + + sizeof(UNICODE_NULL); + CmpLoadOptions.Buffer = ExAllocatePoolWithTag(PagedPool, + CmpLoadOptions.MaximumLength, + TAG_CM); + if (!CmpLoadOptions.Buffer) + { + /* Fail */ + KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 5, 6, 0, 0); + } + + /* Convert it to Unicode and nul-terminate it */ + RtlAnsiStringToUnicodeString(&CmpLoadOptions, &TempString, FALSE); + CmpLoadOptions.Buffer[TempString.Length] = UNICODE_NULL; + CmpLoadOptions.Length += sizeof(WCHAR); + + /* Get the image base */ + HiveImageBase = LoaderBlock->RegistryBase; + if (!HiveImageBase) + { + /* Don't have a system hive, create it */ + Status = CmpInitializeHive(&SystemHive, + HINIT_CREATE, + 0, + HFILE_TYPE_ALTERNATE, + NULL, + NULL, + NULL, + NULL, + NULL, + &CmpSystemFileName); + if (!NT_SUCCESS(Status)) return FALSE; + Allocate = TRUE; + } + else + { + /* Make a copy of the loaded hive */ + Status = CmpInitializeHive(&SystemHive, + HINIT_MEMORY, + 0, + HFILE_TYPE_ALTERNATE, + HiveImageBase, + NULL, + NULL, + NULL, + NULL, + &CmpSystemFileName); + if (!NT_SUCCESS(Status)) return FALSE; + + /* Check if we loaded with shared hives */ + if (CmpShareSystemHives) SystemHive->Hive.HvBinHeadersUse = 0; + + /* Set the boot type */ + CmpBootType = SystemHive->Hive.HiveHeader->BootType; + + /* Check if we loaded in self-healing mode */ + if (!CmSelfHeal) + { + /* We didn't, check the boot type */ + if (CmpBootType & 4) + { + /* Invalid boot type */ + CmpSelfHeal = FALSE; + KeBugCheckEx(REGISTRY_ERROR, 3, 3, (ULONG_PTR)SystemHive, 0); + } + } + } + + /* Create security descriptor */ + SecurityDescriptor = CmpHiveRootSecurityDescriptor(); + + /* Link the hive to the master */ + Status = CmpLinkHiveToMaster(&CmRegistryMachineSystemName, + NULL, + SystemHive, + Allocate, + SecurityDescriptor); + + /* Free the descriptor and check for success */ + ExFreePool(SecurityDescriptor); + if (!NT_SUCCESS(Status)) return FALSE; + + /* Save the hive */ + CmpMachineHiveList[3].CmHive = SystemHive; + return TRUE; +} + VOID NTAPI -CmInitializeRegistry(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +CmInitSystem1(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; @@ -248,6 +365,14 @@ HANDLE KeyHandle; NTSTATUS Status; PAGED_CODE(); + + /* Check if this is PE-boot */ + if (ExpIsWinPEMode) + { + /* Set registry to PE mode */ + CmpMiniNTBoot = TRUE; + CmpShareSystemHives = TRUE; + }
/* Initialize the hive list and lock */ InitializeListHead(&CmpHiveListHead);