Author: fireball Date: Thu Nov 22 21:38:32 2007 New Revision: 30680
URL: http://svn.reactos.org/svn/reactos?rev=30680&view=rev Log: - Fix prototype of NtLoadKeyEx. - Refactor CmiLoadHives using new config routines instead of deprecated cm routines. - Stop using deprecated CmiScanKeyForValue (delete regfile.c as a result). - Add code for parallel hive loading to speed up boot process, but don't yet fully use it due to changes required in linking hives. - Add code for new hive linking process (CmpCreateLinkNode/CmpDoOpen). Not yet used to avoid too many changes in one patch. - Add new code in CmiLoadHives to deal with updated linking process when it becomes used. - Implement NtLoadKey2 to cal NtLoadKeyEx. - Implement NtLoadKeyEx as a new config routine, using CmLoadKey, move out of Cm. - Add some more code in CmpInitializeSystemHive to deal with SYSTEM hive creation during setup, once hive linking is refactored. - Implement a new command except for flushing -- open: CmpCmdHiveOpen. Used by CmLoadKey. - Add support for impersonating the SYSTEM account if the hive can't be open in the current client security context. - Fill out CmpMachineHiveList, to be used in parallel hive loading.
Removed: trunk/reactos/ntoskrnl/cm/regfile.c Modified: trunk/reactos/include/ndk/cmfuncs.h trunk/reactos/ntoskrnl/cm/ntfunc.c trunk/reactos/ntoskrnl/cm/registry.c trunk/reactos/ntoskrnl/cm/regobj.c trunk/reactos/ntoskrnl/config/cm.h trunk/reactos/ntoskrnl/config/cmapi.c trunk/reactos/ntoskrnl/config/cmdata.c trunk/reactos/ntoskrnl/config/cmlazy.c trunk/reactos/ntoskrnl/config/cmparse.c trunk/reactos/ntoskrnl/config/cmsysini.c trunk/reactos/ntoskrnl/config/ntapi.c trunk/reactos/ntoskrnl/ntoskrnl.rbuild trunk/reactos/ntoskrnl/sysfuncs.lst
Modified: trunk/reactos/include/ndk/cmfuncs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/cmfuncs.h?rev=3... ============================================================================== --- trunk/reactos/include/ndk/cmfuncs.h (original) +++ trunk/reactos/include/ndk/cmfuncs.h Thu Nov 22 21:38:32 2007 @@ -139,10 +139,7 @@ IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags, - IN HANDLE TrustClassKey, - IN HANDLE Event, - IN ACCESS_MASK DesiredAccess, - OUT PHANDLE RootHandle + IN HANDLE TrustClassKey );
NTSTATUS
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/ntfunc.c?rev=30... ============================================================================== --- trunk/reactos/ntoskrnl/cm/ntfunc.c (original) +++ trunk/reactos/ntoskrnl/cm/ntfunc.c Thu Nov 22 21:38:32 2007 @@ -578,65 +578,25 @@ return Status; }
-/* - * NOTE: - * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and - * KeyObjectAttributes->Name specifies the name of the key to load. - * Flags can be 0 or REG_NO_LAZY_FLUSH. - */ -NTSTATUS -NTAPI -NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes, - IN POBJECT_ATTRIBUTES FileObjectAttributes, - IN ULONG Flags) -{ - NTSTATUS Status; - PAGED_CODE(); - DPRINT ("NtLoadKey2() called\n"); - -#if 0 - if (!SeSinglePrivilegeCheck (SeRestorePrivilege, ExGetPreviousMode ())) - return STATUS_PRIVILEGE_NOT_HELD; -#endif - - /* Acquire hive lock */ - KeEnterCriticalRegion(); - ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE); - - Status = CmiLoadHive (KeyObjectAttributes, - FileObjectAttributes->ObjectName, - Flags); - if (!NT_SUCCESS (Status)) - { - DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status); - } - - /* Release hive lock */ - ExReleaseResourceLite(&CmpRegistryLock); - KeLeaveCriticalRegion(); - - return Status; -} - NTSTATUS NTAPI NtInitializeRegistry (IN USHORT Flag) { NTSTATUS Status; - + PAGED_CODE(); - + if (CmiRegistryInitialized == TRUE) return STATUS_ACCESS_DENIED;
/* Save boot log file */ IopSaveBootLogToFile(); - + Status = CmiInitHives (Flag); - + CmpCmdInit(Flag); CmiRegistryInitialized = TRUE; - + return Status; }
Removed: trunk/reactos/ntoskrnl/cm/regfile.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regfile.c?rev=3... ============================================================================== --- trunk/reactos/ntoskrnl/cm/regfile.c (original) +++ trunk/reactos/ntoskrnl/cm/regfile.c (removed) @@ -1,84 +1,0 @@ -/* - * PROJECT: ReactOS Kernel - * COPYRIGHT: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/cm/regfile.c - * PURPOSE: Registry file manipulation routines - * - * PROGRAMMERS: Casper Hornstrup - * Eric Kohl - * Filip Navara - */ - -#include <ntoskrnl.h> -#define NDEBUG -#include <internal/debug.h> -#include "cm.h" - -/* LOCAL MACROS *************************************************************/ - -#define ABS_VALUE(V) (((V) < 0) ? -(V) : (V)) -#define REG_DATA_SIZE_MASK 0x7FFFFFFF -#define REG_DATA_IN_OFFSET 0x80000000 - -/* FUNCTIONS ****************************************************************/ - -NTSTATUS -CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, - IN PCUNICODE_STRING FileName, - IN ULONG Flags) -{ - PCMHIVE Hive = NULL; - NTSTATUS Status; - BOOLEAN Allocate = TRUE; - - DPRINT ("CmiLoadHive(Filename %wZ)\n", FileName); - - if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER; - - Status = CmpInitHiveFromFile(FileName, - (Flags & REG_NO_LAZY_FLUSH) ? HIVE_NOLAZYFLUSH : 0, - &Hive, - &Allocate, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CmpInitHiveFromFile() failed (Status %lx)\n", Status); - if (Hive) ExFreePool(Hive); - return Status; - } - - Status = CmiConnectHive(KeyObjectAttributes, Hive); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status); - // CmiRemoveRegistryHive (Hive); - } - - DPRINT ("CmiLoadHive() done\n"); - return Status; -} - -NTSTATUS -CmiScanKeyForValue(IN PCMHIVE RegistryHive, - IN PCM_KEY_NODE KeyCell, - IN PUNICODE_STRING ValueName, - OUT PCM_KEY_VALUE *ValueCell, - OUT HCELL_INDEX *ValueCellOffset) -{ - HCELL_INDEX CellIndex; - - /* Assume failure */ - *ValueCell = NULL; - if (ValueCellOffset) *ValueCellOffset = HCELL_NIL; - - /* Call newer Cm API */ - CellIndex = CmpFindValueByName(&RegistryHive->Hive, KeyCell, ValueName); - if (CellIndex == HCELL_NIL) return STATUS_OBJECT_NAME_NOT_FOUND; - - /* Otherwise, get the cell data back too */ - if (ValueCellOffset) *ValueCellOffset = CellIndex; - *ValueCell = (PCM_KEY_VALUE)HvGetCell(&RegistryHive->Hive, CellIndex); - return STATUS_SUCCESS; -} - -/* EOF */
Modified: trunk/reactos/ntoskrnl/cm/registry.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/registry.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/cm/registry.c (original) +++ trunk/reactos/ntoskrnl/cm/registry.c Thu Nov 22 21:38:32 2007 @@ -328,6 +328,8 @@ ULONG BufferSize; ULONG ResultSize; PWSTR EndPtr; + PCMHIVE CmHive; + BOOLEAN Allocate = TRUE;
DPRINT("CmiInitHives() called\n");
@@ -379,138 +381,172 @@ wcscpy(ConfigPath, L"\SystemRoot"); } wcscat(ConfigPath, L"\system32\config"); - DPRINT("ConfigPath: %S\n", ConfigPath); - EndPtr = ConfigPath + wcslen(ConfigPath);
- /* FIXME: Save boot log */ - + /* Setup the file name for the SECURITY hive */ + wcscpy(EndPtr, REG_SEC_FILE_NAME); + RtlInitUnicodeString(&FileName, ConfigPath); + DPRINT ("ConfigPath: %S\n", ConfigPath); + + /* Load the hive */ + Status = CmpInitHiveFromFile(&FileName, + 0, + &CmHive, + &Allocate, + 0); + + /* Setup the key name for the SECURITY hive */ + RtlInitUnicodeString(&KeyName, REG_SEC_KEY_NAME); + + Status = CmpLinkHiveToMaster(&KeyName, + NULL, + CmHive, + FALSE, + NULL); + + /* Connect the SOFTWARE hive */ + wcscpy(EndPtr, REG_SOFTWARE_FILE_NAME); + RtlInitUnicodeString(&FileName, ConfigPath); + DPRINT ("ConfigPath: %S\n", ConfigPath); + + /* Load the hive */ + Status = CmpInitHiveFromFile(&FileName, + 0, + &CmHive, + &Allocate, + 0); + + /* Setup the key name for the SECURITY hive */ + RtlInitUnicodeString (&KeyName, REG_SOFTWARE_KEY_NAME); + + Status = CmpLinkHiveToMaster(&KeyName, + NULL, + CmHive, + FALSE, + NULL); + /* Connect the SYSTEM hive only if it has been created */ if (SetupBoot == TRUE) { wcscpy(EndPtr, REG_SYSTEM_FILE_NAME); + RtlInitUnicodeString(&FileName, ConfigPath); DPRINT ("ConfigPath: %S\n", ConfigPath); - - RtlInitUnicodeString (&KeyName, - REG_SYSTEM_KEY_NAME); - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - RtlInitUnicodeString (&FileName, - ConfigPath); - Status = CmiLoadHive (&ObjectAttributes, - &FileName, - 0); - if (!NT_SUCCESS(Status)) +#if 0 + HANDLE PrimaryHandle, LogHandle; + ULONG PrimaryDisposition, SecondaryDisposition; + ULONG ClusterSize, Length; + + /* Build the file name */ + wcscpy(EndPtr, REG_SYSTEM_FILE_NAME); + RtlInitUnicodeString(&FileName, ConfigPath); + DPRINT ("ConfigPath: %S\n", ConfigPath); + + /* Hive already exists */ + CmHive = CmpMachineHiveList[3].CmHive; + + /* Open the hive file and log */ + Status = CmpOpenHiveFiles(&FileName, + L".LOG", + &PrimaryHandle, + &LogHandle, + &PrimaryDisposition, + &SecondaryDisposition, + TRUE, + TRUE, + FALSE, + &ClusterSize); + if (!(NT_SUCCESS(Status)) || !(LogHandle)) { - DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status); - return Status; + /* Bugcheck */ + KeBugCheck(BAD_SYSTEM_CONFIG_INFO); } + + /* Save the file handles */ + CmHive->FileHandles[HFILE_TYPE_LOG] = LogHandle; + CmHive->FileHandles[HFILE_TYPE_PRIMARY] = PrimaryHandle; + + /* Allow lazy flushing since the handles are there */ + ASSERT(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH); + CmHive->Hive.HiveFlags &= ~HIVE_NOLAZYFLUSH; + + /* Get the real size of the hive */ + Length = CmHive->Hive.Storage[Stable].Length + HBLOCK_SIZE; + + /* Check if the cluster size doesn't match */ + if (CmHive->Hive.Cluster != ClusterSize) ASSERT(FALSE); + + /* Set the file size */ + if (!CmpFileSetSize((PHHIVE)CmHive, HFILE_TYPE_PRIMARY, Length, Length)) + { + /* This shouldn't fail */ + ASSERT(FALSE); + } + + /* Setup the key name for the SECURITY hive */ + RtlInitUnicodeString (&KeyName, REG_SYSTEM_KEY_NAME); +#else + /* Load the hive */ + Status = CmpInitHiveFromFile(&FileName, + 0, + &CmHive, + &Allocate, + 0); + + /* Setup the key name for the SECURITY hive */ + RtlInitUnicodeString (&KeyName, REG_SYSTEM_KEY_NAME); + + Status = CmpLinkHiveToMaster(&KeyName, + NULL, + CmHive, + FALSE, + NULL);
Status = CmiInitControlSetLink (); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status); - return(Status); - } - } - - /* Connect the SOFTWARE hive */ - wcscpy(EndPtr, REG_SOFTWARE_FILE_NAME); - RtlInitUnicodeString (&FileName, - ConfigPath); +#endif + } + + /* Connect the DEFAULT hive */ + wcscpy(EndPtr, REG_DEFAULT_USER_FILE_NAME); + RtlInitUnicodeString(&FileName, ConfigPath); DPRINT ("ConfigPath: %S\n", ConfigPath);
- RtlInitUnicodeString (&KeyName, - REG_SOFTWARE_KEY_NAME); - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = CmiLoadHive (&ObjectAttributes, - &FileName, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); - return(Status); - } + /* Load the hive */ + Status = CmpInitHiveFromFile(&FileName, + 0, + &CmHive, + &Allocate, + 0); + + /* Setup the key name for the SECURITY hive */ + RtlInitUnicodeString (&KeyName, REG_DEFAULT_USER_KEY_NAME); + + Status = CmpLinkHiveToMaster(&KeyName, + NULL, + CmHive, + FALSE, + NULL);
/* Connect the SAM hive */ wcscpy(EndPtr, REG_SAM_FILE_NAME); - RtlInitUnicodeString (&FileName, - ConfigPath); + RtlInitUnicodeString(&FileName, ConfigPath); DPRINT ("ConfigPath: %S\n", ConfigPath); - - RtlInitUnicodeString (&KeyName, - REG_SAM_KEY_NAME); - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = CmiLoadHive (&ObjectAttributes, - &FileName, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); - return(Status); - } - - /* Connect the SECURITY hive */ - wcscpy(EndPtr, REG_SEC_FILE_NAME); - RtlInitUnicodeString (&FileName, - ConfigPath); - DPRINT ("ConfigPath: %S\n", ConfigPath); - - RtlInitUnicodeString (&KeyName, - REG_SEC_KEY_NAME); - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = CmiLoadHive (&ObjectAttributes, - &FileName, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); - return(Status); - } - - /* Connect the DEFAULT hive */ - wcscpy(EndPtr, REG_DEFAULT_USER_FILE_NAME); - RtlInitUnicodeString (&FileName, - ConfigPath); - DPRINT ("ConfigPath: %S\n", ConfigPath); - - RtlInitUnicodeString (&KeyName, - REG_DEFAULT_USER_KEY_NAME); - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = CmiLoadHive (&ObjectAttributes, - &FileName, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); - return(Status); - } - - DPRINT("CmiInitHives() done\n"); - - return(STATUS_SUCCESS); + + /* Load the hive */ + Status = CmpInitHiveFromFile(&FileName, + 0, + &CmHive, + &Allocate, + 0); + + /* Setup the key name for the SECURITY hive */ + RtlInitUnicodeString(&KeyName, REG_SAM_KEY_NAME); + Status = CmpLinkHiveToMaster(&KeyName, + NULL, + CmHive, + FALSE, + NULL); + return Status; }
VOID
Modified: trunk/reactos/ntoskrnl/cm/regobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regobj.c?rev=30... ============================================================================== --- trunk/reactos/ntoskrnl/cm/regobj.c (original) +++ trunk/reactos/ntoskrnl/cm/regobj.c Thu Nov 22 21:38:32 2007 @@ -838,22 +838,20 @@ UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"SymbolicLinkValue"); PCM_KEY_VALUE ValueCell; PVOID DataCell; - NTSTATUS Status; + HCELL_INDEX Cell;
DPRINT("CmiGetLinkTarget() called\n");
- /* Get Value block of interest */ - Status = CmiScanKeyForValue(RegistryHive, - KeyCell, - &LinkName, - &ValueCell, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CmiScanKeyForValue() failed (Status %lx)\n", Status); - return(Status); - } - + /* Find the cell */ + Cell = CmpFindValueByName(&RegistryHive->Hive, KeyCell, &LinkName); + if (Cell == HCELL_NIL) + { + DPRINT1("CmiScanKeyForValue() failed\n"); + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* Get the cell data */ + ValueCell = (PCM_KEY_VALUE)HvGetCell(&RegistryHive->Hive, Cell); if (ValueCell->Type != REG_LINK) { DPRINT1("Type != REG_LINK\n!");
Modified: trunk/reactos/ntoskrnl/config/cm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cm.h?rev=30... ============================================================================== --- trunk/reactos/ntoskrnl/config/cm.h (original) +++ trunk/reactos/ntoskrnl/config/cm.h Thu Nov 22 21:38:32 2007 @@ -86,11 +86,16 @@ #define MAXIMUM_CACHED_DATA 2 * PAGE_SIZE
// +// Hives to load on startup +// +#define CM_NUMBER_OF_MACHINE_HIVES 6 + +// // Number of items that can fit inside an Allocation Page // #define CM_KCBS_PER_PAGE \ PAGE_SIZE / sizeof(CM_KEY_CONTROL_BLOCK) -#define CM_DELAYS_PER_PAGE \ +#define CM_DELAYS_PER_PAGE \ PAGE_SIZE / sizeof(CM_DELAYED_CLOSE_ENTRY)
// @@ -429,9 +434,8 @@ // typedef struct _HIVE_LIST_ENTRY { - PWCHAR FileName; - PWCHAR BaseName; - PWCHAR RegRootName; + PWSTR Name; + PWSTR BaseName; PCMHIVE CmHive; ULONG HHiveFlags; ULONG CmHiveFlags; @@ -439,7 +443,6 @@ BOOLEAN ThreadFinished; BOOLEAN ThreadStarted; BOOLEAN Allocate; - BOOLEAN WinPERequired; } HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY;
// @@ -759,6 +762,12 @@ IN ULONG CheckFlags );
+VOID +NTAPI +CmpInitializeHiveList( + IN USHORT Flag +); + // // Registry Utility Functions // @@ -956,7 +965,7 @@ );
// -// Flush Routines +// Command Routines (Flush, Open, Close, Init); // BOOLEAN NTAPI @@ -974,6 +983,16 @@ NTAPI CmpCmdInit( IN BOOLEAN SetupBoot +); + +NTSTATUS +NTAPI +CmpCmdHiveOpen( + IN POBJECT_ATTRIBUTES FileAttributes, + IN PSECURITY_CLIENT_CONTEXT ImpersonationContext, + IN OUT PBOOLEAN Allocate, + OUT PCMHIVE *NewHive, + IN ULONG CheckFlags );
VOID @@ -1351,7 +1370,7 @@ extern ULONG CmpConfigurationAreaSize; extern PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData; extern UNICODE_STRING CmTypeName[]; -extern HIVE_LIST_ENTRY CmpMachineHiveList[5]; +extern HIVE_LIST_ENTRY CmpMachineHiveList[]; extern UNICODE_STRING CmSymbolicLinkValueName; extern UNICODE_STRING CmpSystemStartOptions; extern UNICODE_STRING CmpLoadOptions;
Modified: trunk/reactos/ntoskrnl/config/cmapi.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmapi.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmapi.c (original) +++ trunk/reactos/ntoskrnl/config/cmapi.c Thu Nov 22 21:38:32 2007 @@ -12,9 +12,6 @@ #include "cm.h" #define NDEBUG #include "debug.h" - -NTSTATUS -CmiFlushRegistryHive(PCMHIVE RegistryHive);
/* FUNCTIONS *****************************************************************/
@@ -892,7 +889,7 @@ Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen; Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen; Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen; - Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen; + Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
/* Check if we have a class */ if (Node->ClassLength > 0) @@ -1202,3 +1199,121 @@ /* Return the status */ return Status; } + +NTSTATUS +NTAPI +CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey, + IN POBJECT_ATTRIBUTES SourceFile, + IN ULONG Flags, + IN PKEY_OBJECT KeyBody) +{ + SECURITY_QUALITY_OF_SERVICE ServiceQos; + SECURITY_CLIENT_CONTEXT ClientSecurityContext; + HANDLE KeyHandle; + BOOLEAN Allocate = TRUE; + PCMHIVE CmHive; + NTSTATUS Status; + + /* Check if we have a trust key */ + if (KeyBody) + { + /* Fail */ + DPRINT1("Trusted classes not yet supported\n"); + return STATUS_NOT_IMPLEMENTED; + } + + /* Build a service QoS for a security context */ + ServiceQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); + ServiceQos.ImpersonationLevel = SecurityImpersonation; + ServiceQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; + ServiceQos.EffectiveOnly = TRUE; + Status = SeCreateClientSecurity(PsGetCurrentThread(), + &ServiceQos, + FALSE, + &ClientSecurityContext); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + DPRINT1("Security context failed\n"); + return Status; + } + + /* Open the target key */ + Status = ZwOpenKey(&KeyHandle, KEY_READ, TargetKey); + if (!NT_SUCCESS(Status)) KeyHandle = NULL; + + /* Open the hive */ + Status = CmpCmdHiveOpen(SourceFile, + &ClientSecurityContext, + &Allocate, + &CmHive, + 0); + + /* Get rid of the security context */ + SeDeleteClientSecurity(&ClientSecurityContext); + + /* See if we failed */ + if (!NT_SUCCESS(Status)) + { + /* See if the target already existed */ + if (KeyHandle) + { + /* Lock the registry */ + CmpLockRegistryExclusive(); + + /* FIXME: Check if we are already loaded */ + + /* Release the registry */ + CmpUnlockRegistry(); + } + + /* Close the key handle if we had one */ + if (KeyHandle) ZwClose(KeyHandle); + DPRINT1("Failed: %lx\n", Status); + return Status; + } + + /* Lock the registry shared */ + //CmpLockRegistry(); + + /* Lock the hive to this thread */ + CmHive->Hive.HiveFlags |= HIVE_IS_UNLOADING; + CmHive->CreatorOwner = KeGetCurrentThread(); + + /* Set flag */ + if (Flags & REG_NO_LAZY_FLUSH) CmHive->Hive.HiveFlags |= HIVE_NOLAZYFLUSH; + + /* Link the hive */ + Status = CmpLinkHiveToMaster(TargetKey->ObjectName, + TargetKey->RootDirectory, + CmHive, + FALSE, + TargetKey->SecurityDescriptor); + if (NT_SUCCESS(Status)) + { + /* FIXME: Add to HiveList key */ + + /* Sync the hive if necessary */ + if (Allocate) + { + /* Sync it */ + HvSyncHive(&CmHive->Hive); + } + + /* Release the hive */ + CmHive->Hive.HiveFlags &= ~HIVE_IS_UNLOADING; + CmHive->CreatorOwner = NULL; + } + else + { + /* FIXME: TODO */ + + } + + /* Unlock the registry */ + //CmpUnlockRegistry(); + + /* Close handle and return */ + if (KeyHandle) ZwClose(KeyHandle); + return Status; +}
Modified: trunk/reactos/ntoskrnl/config/cmdata.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmdata.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmdata.c (original) +++ trunk/reactos/ntoskrnl/config/cmdata.c Thu Nov 22 21:38:32 2007 @@ -38,7 +38,16 @@
EX_PUSH_LOCK CmpHiveListHeadLock, CmpLoadHiveLock;
-HIVE_LIST_ENTRY CmpMachineHiveList[5]; +HIVE_LIST_ENTRY CmpMachineHiveList[] = +{ + { L"HARDWARE", L"MACHINE\", NULL, HIVE_VOLATILE , 0 , NULL, FALSE, FALSE, FALSE}, + { L"SECURITY", L"MACHINE\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE}, + { L"SOFTWARE", L"MACHINE\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE}, + { L"SYSTEM", L"MACHINE\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE}, + { L"DEFAULT", L"USER\.DEFAULT", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE}, + { L"SAM", L"MACHINE\", NULL, HIVE_NOLAZYFLUSH , 0 , NULL, FALSE, FALSE, FALSE}, + { NULL, NULL, 0, 0 , 0 , NULL, FALSE, FALSE, FALSE} +};
UNICODE_STRING CmSymbolicLinkValueName = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
Modified: trunk/reactos/ntoskrnl/config/cmlazy.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmlazy.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmlazy.c (original) +++ trunk/reactos/ntoskrnl/config/cmlazy.c Thu Nov 22 21:38:32 2007 @@ -238,6 +238,56 @@
/* Testing: Force Lazy Flushing */ CmpHoldLazyFlush = FALSE; + + /* Setup the hive list */ + CmpInitializeHiveList(SetupBoot); +} + +NTSTATUS +NTAPI +CmpCmdHiveOpen(IN POBJECT_ATTRIBUTES FileAttributes, + IN PSECURITY_CLIENT_CONTEXT ImpersonationContext, + IN OUT PBOOLEAN Allocate, + OUT PCMHIVE *NewHive, + IN ULONG CheckFlags) +{ + PUNICODE_STRING FileName; + NTSTATUS Status; + PAGED_CODE(); + + /* Open the file in the current security context */ + FileName = FileAttributes->ObjectName; + Status = CmpInitHiveFromFile(FileName, + 0, + NewHive, + Allocate, + CheckFlags); + if (((Status == STATUS_ACCESS_DENIED) || + (Status == STATUS_NO_SUCH_USER) || + (Status == STATUS_WRONG_PASSWORD) || + (Status == STATUS_ACCOUNT_EXPIRED) || + (Status == STATUS_ACCOUNT_DISABLED) || + (Status == STATUS_ACCOUNT_RESTRICTION)) && + (ImpersonationContext)) + { + /* We failed due to an account/security error, impersonate SYSTEM */ + Status = SeImpersonateClientEx(ImpersonationContext, NULL); + if (NT_SUCCESS(Status)) + { + /* Now try again */ + Status = CmpInitHiveFromFile(FileName, + 0, + NewHive, + Allocate, + CheckFlags); + + /* Restore impersonation token */ + PsRevertToSelf(); + } + } + + /* Return status of open attempt */ + return Status; }
VOID
Modified: trunk/reactos/ntoskrnl/config/cmparse.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmparse.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmparse.c (original) +++ trunk/reactos/ntoskrnl/config/cmparse.c Thu Nov 22 21:38:32 2007 @@ -416,3 +416,299 @@ ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock); return Status; } + +NTSTATUS +NTAPI +CmpDoOpen(IN PHHIVE Hive, + IN HCELL_INDEX Cell, + IN PCM_KEY_NODE Node, + IN PACCESS_STATE AccessState, + IN KPROCESSOR_MODE AccessMode, + IN ULONG Attributes, + IN PCM_PARSE_CONTEXT Context OPTIONAL, + IN ULONG ControlFlags, + IN OUT PCM_KEY_CONTROL_BLOCK *CachedKcb, + IN PUNICODE_STRING KeyName, + OUT PVOID *Object) +{ + NTSTATUS Status; + PKEY_OBJECT KeyBody = NULL; + PCM_KEY_CONTROL_BLOCK Kcb = NULL; + + /* Make sure the hive isn't locked */ + if ((Hive->HiveFlags & HIVE_IS_UNLOADING) && + (((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread())) + { + /* It is, don't touch it */ + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* If we have a KCB, make sure it's locked */ + ASSERT(CmpIsKcbLockedExclusive(*CachedKcb)); + + /* Create the KCB */ + Kcb = CmpCreateKeyControlBlock(Hive, Cell, Node, *CachedKcb, 0, KeyName); + if (!Kcb) return STATUS_INSUFFICIENT_RESOURCES; + + /* Make sure it's also locked, and set the pointer */ + ASSERT(CmpIsKcbLockedExclusive(Kcb)); + *CachedKcb = Kcb; + + /* Allocate the key object */ + Status = ObCreateObject(AccessMode, + CmpKeyObjectType, + NULL, + AccessMode, + NULL, + sizeof(KEY_OBJECT), + 0, + 0, + Object); + if (NT_SUCCESS(Status)) + { + /* Get the key body and fill it out */ + KeyBody = (PKEY_OBJECT)(*Object); + KeyBody->KeyControlBlock = Kcb; + KeyBody->SubKeyCounts = 0; + KeyBody->SubKeys = NULL; + KeyBody->SizeOfSubKeys = 0; + InsertTailList(&CmiKeyObjectListHead, &KeyBody->KeyBodyList); + } + else + { + /* Failed, dereference the KCB */ + CmpDereferenceKeyControlBlockWithLock(Kcb, FALSE); + } + + /* Return status */ + return Status; +} + +/* Remove calls to CmCreateRootNode once this is used! */ +NTSTATUS +NTAPI +CmpCreateLinkNode(IN PHHIVE Hive, + IN HCELL_INDEX Cell, + IN PACCESS_STATE AccessState, + IN UNICODE_STRING Name, + IN KPROCESSOR_MODE AccessMode, + IN ULONG CreateOptions, + IN PCM_PARSE_CONTEXT Context, + IN PCM_KEY_CONTROL_BLOCK ParentKcb, + OUT PVOID *Object) +{ + NTSTATUS Status; + HCELL_INDEX KeyCell, LinkCell, ChildCell; + PKEY_OBJECT KeyBody; + LARGE_INTEGER TimeStamp; + PCM_KEY_NODE KeyNode; + PCM_KEY_CONTROL_BLOCK Kcb = ParentKcb; + + /* Link nodes only allowed on the master */ + if (Hive != &CmiVolatileHive->Hive) + { + /* Fail */ + DPRINT1("Invalid link node attempt\n"); + return STATUS_ACCESS_DENIED; + } + + /* Acquire the flusher locks */ + ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock); + ExAcquirePushLockShared((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock); + + /* Check if the parent is being deleted */ + if (ParentKcb->Delete) + { + /* It is, quit */ + ASSERT(FALSE); + Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto Exit; + } + + /* Allocate a link node */ + LinkCell = HvAllocateCell(Hive, + FIELD_OFFSET(CM_KEY_NODE, Name) + + CmpNameSize(Hive, &Name), + Stable, + HCELL_NIL); + if (LinkCell == HCELL_NIL) + { + /* Fail */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Exit; + } + + /* Get the key cell */ + KeyCell = Context->ChildHive.KeyCell; + if (KeyCell != HCELL_NIL) + { + /* Hive exists! */ + ChildCell = KeyCell; + + /* Get the node data */ + KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, ChildCell); + if (!KeyNode) + { + /* Fail */ + ASSERT(FALSE); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Exit; + } + + /* Fill out the data */ + KeyNode->Parent = LinkCell; + KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE; + HvReleaseCell(Context->ChildHive.KeyHive, ChildCell); + + /* Now open the key cell */ + KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, KeyCell); + if (!KeyNode) + { + /* Fail */ + ASSERT(FALSE); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Exit; + } + + /* Open the parent */ + Status = CmpDoOpen(Context->ChildHive.KeyHive, + KeyCell, + KeyNode, + AccessState, + AccessMode, + CreateOptions, + NULL, + 0, + &Kcb, + &Name, + Object); + HvReleaseCell(Context->ChildHive.KeyHive, KeyCell); + } + else + { + /* Do the actual create operation */ + Status = CmpDoCreateChild(Context->ChildHive.KeyHive, + Cell, + NULL, + AccessState, + &Name, + AccessMode, + &Context->Class, + ParentKcb, + KEY_HIVE_ENTRY | KEY_NO_DELETE, + &ChildCell, + Object); + if (NT_SUCCESS(Status)) + { + /* Setup root pointer */ + Context->ChildHive.KeyHive->BaseBlock->RootCell = ChildCell; + } + } + + /* Check if open or create suceeded */ + if (NT_SUCCESS(Status)) + { + /* Mark the cell dirty */ + HvMarkCellDirty(Context->ChildHive.KeyHive, ChildCell, FALSE); + + /* Get the key node */ + KeyNode = HvGetCell(Context->ChildHive.KeyHive, ChildCell); + if (!KeyNode) + { + /* Fail */ + ASSERT(FALSE); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Exit; + } + + /* Release it */ + HvReleaseCell(Context->ChildHive.KeyHive, ChildCell); + + /* Set the parent adn flags */ + KeyNode->Parent = LinkCell; + KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE; + + /* Get the link node */ + KeyNode = HvGetCell(Hive, LinkCell); + if (!KeyNode) + { + /* Fail */ + ASSERT(FALSE); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Exit; + } + + /* Set it up */ + KeyNode->Signature = CM_LINK_NODE_SIGNATURE; + KeyNode->Flags = KEY_HIVE_EXIT | KEY_NO_DELETE; + KeyNode->Parent = Cell; + KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, &Name); + if (KeyNode->NameLength < Name.Length) KeyNode->Flags |= KEY_COMP_NAME; + KeQuerySystemTime(&TimeStamp); + KeyNode->LastWriteTime = TimeStamp; + + /* Clear out the rest */ + KeyNode->SubKeyCounts[Stable] = 0; + KeyNode->SubKeyCounts[Volatile] = 0; + KeyNode->SubKeyLists[Stable] = HCELL_NIL; + KeyNode->SubKeyLists[Volatile] = HCELL_NIL; + KeyNode->ValueList.Count = 0; + KeyNode->ValueList.List = HCELL_NIL; + KeyNode->ClassLength = 0; + + /* Reference the root node */ + //KeyNode->ChildHiveReference.KeyHive = Context->ChildHive.KeyHive; + //KeyNode->ChildHiveReference.KeyCell = ChildCell; + HvReleaseCell(Hive, LinkCell); + + /* Get the parent node */ + KeyNode = HvGetCell(Hive, Cell); + if (!KeyNode) + { + /* Fail */ + ASSERT(FALSE); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Exit; + } + + /* Now add the subkey */ + if (!CmpAddSubKey(Hive, Cell, LinkCell)) + { + /* Failure! We don't handle this yet! */ + ASSERT(FALSE); + } + + /* Get the key body */ + KeyBody = (PKEY_OBJECT)*Object; + + /* Sanity checks */ + ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell); + ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive); + //ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen); + + /* Update the timestamp */ + KeQuerySystemTime(&TimeStamp); + KeyNode->LastWriteTime = TimeStamp; + + /* Check if we need to update name maximum */ + if (KeyNode->MaxNameLen < Name.Length) + { + /* Do it */ + KeyNode->MaxNameLen = Name.Length; + KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name.Length; + } + + /* Check if we need toupdate class length maximum */ + if (KeyNode->MaxClassLen < Context->Class.Length) + { + /* Update it */ + KeyNode->MaxClassLen = Context->Class.Length; + } + } + +Exit: + /* Release the flusher locks and return status */ + ExReleasePushLock((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock); + ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock); + return Status; +}
Modified: trunk/reactos/ntoskrnl/config/cmsysini.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmsysini.c?... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmsysini.c (original) +++ trunk/reactos/ntoskrnl/config/cmsysini.c Thu Nov 22 21:38:32 2007 @@ -15,6 +15,8 @@
KGUARDED_MUTEX CmpSelfHealQueueLock; LIST_ENTRY CmpSelfHealQueueListHead; +KEVENT CmpLoadWorkerEvent; +LONG CmpLoadWorkerIncrement; PEPROCESS CmpSystemProcess; BOOLEAN HvShutdownComplete; PVOID CmpRegistryLockCallerCaller, CmpRegistryLockCaller; @@ -496,11 +498,11 @@ } else { + /* Create it */ #if 0 - /* Create it */ - Status = CmpInitializeHive((PCMHIVE*)&SystemHive, + Status = CmpInitializeHive(&SystemHive, HINIT_CREATE, - HIVE_NOLAZYFLUSH, + 0, //HIVE_NOLAZYFLUSH, HFILE_TYPE_LOG, NULL, NULL, @@ -509,8 +511,10 @@ &HiveName, 0); if (!NT_SUCCESS(Status)) return FALSE; + + /* Set the hive filename */ + RtlCreateUnicodeString(&SystemHive->FileFullPath, SYSTEM_REG_FILE); #endif - /* Tell CmpLinkHiveToMaster to allocate a hive */ Allocate = TRUE; } @@ -746,6 +750,314 @@ return TRUE; }
+VOID +NTAPI +CmpLoadHiveThread(IN PVOID StartContext) +{ + WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH]; + UNICODE_STRING TempName, FileName, RegName; + ULONG FileStart, RegStart, i, ErrorResponse, ClusterSize, WorkerCount; + ULONG PrimaryDisposition, SecondaryDisposition, Length; + PCMHIVE CmHive; + HANDLE PrimaryHandle, LogHandle; + NTSTATUS Status = STATUS_SUCCESS; + PVOID ErrorParameters; + PAGED_CODE(); + + /* Get the hive index, make sure it makes sense */ + i = (ULONG)StartContext; + ASSERT(CmpMachineHiveList[i].Name != NULL); + DPRINT1("[HiveLoad] Parallel Thread: %d\n", i); + + /* We were started */ + CmpMachineHiveList[i].ThreadStarted = TRUE; + + /* Build the file name and registry name strings */ + RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH); + RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH); + + /* Now build the system root path */ + RtlInitUnicodeString(&TempName, L"\SystemRoot\System32\Config\"); + RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName); + FileStart = FileName.Length; + + /* And build the registry root path */ + RtlInitUnicodeString(&TempName, L"\REGISTRY\"); + RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); + RegStart = RegName.Length; + + /* Build the base name */ + RegName.Length = RegStart; + RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName); + RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); + + /* Check if this is a child of the root */ + if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\') + { + /* Then setup the whole name */ + RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name); + RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); + } + + /* Now Add tge rest if the file name */ + RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name); + FileName.Length = FileStart; + RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName); + if (!CmpMachineHiveList[i].CmHive) + { + /* We need to allocate a ne whive structure */ + CmpMachineHiveList[i].Allocate = TRUE; + + /* Load the hive file */ + DPRINT1("[HiveLoad]: Load from file %wZ\n", &FileName); + CmpMachineHiveList[i].CmHive2 = (PVOID)0xBAADBEEF; + goto Later; + Status = CmpInitHiveFromFile(&FileName, + CmpMachineHiveList[i].HHiveFlags, + &CmHive, + &CmpMachineHiveList[i].Allocate, + 0); + if (!(NT_SUCCESS(Status)) || !(CmHive->FileHandles[HFILE_TYPE_LOG])) + { + /* We failed or couldn't get a log file, raise a hard error */ + ErrorParameters = &FileName; + NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE, + 1, + 1, + (PULONG_PTR)&ErrorParameters, + OptionOk, + &ErrorResponse); + } + + /* Set the hive flags and newly allocated hive pointer */ + CmHive->Flags = CmpMachineHiveList[i].CmHiveFlags; + CmpMachineHiveList[i].CmHive2 = CmHive; + } + else + { + /* We already have a hive, is it volatile? */ + CmHive = CmpMachineHiveList[i].CmHive; + if (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE)) + { + DPRINT1("[HiveLoad]: Open from file %wZ\n", &FileName); + CmpMachineHiveList[i].CmHive2 = CmHive; + goto Later; + + /* It's now, open the hive file and log */ + Status = CmpOpenHiveFiles(&FileName, + L".LOG", + &PrimaryHandle, + &LogHandle, + &PrimaryDisposition, + &SecondaryDisposition, + TRUE, + TRUE, + FALSE, + &ClusterSize); + if (!(NT_SUCCESS(Status)) || !(LogHandle)) + { + /* Couldn't open the hive or its log file, raise a hard error */ + ErrorParameters = &FileName; + NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE, + 1, + 1, + (PULONG_PTR)&ErrorParameters, + OptionOk, + &ErrorResponse); + + /* And bugcheck for posterity's sake */ + KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 9, 0, i, Status); + } + + /* Save the file handles. This should remove our sync hacks */ + CmHive->FileHandles[HFILE_TYPE_LOG] = LogHandle; + CmHive->FileHandles[HFILE_TYPE_PRIMARY] = PrimaryHandle; + + /* Allow lazy flushing since the handles are there -- remove sync hacks */ + ASSERT(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH); + CmHive->Hive.HiveFlags &= ~HIVE_NOLAZYFLUSH; + + /* Get the real size of the hive */ + Length = CmHive->Hive.Storage[Stable].Length + HBLOCK_SIZE; + + /* Check if the cluster size doesn't match */ + if (CmHive->Hive.Cluster != ClusterSize) ASSERT(FALSE); + + /* Set the file size */ + if (!CmpFileSetSize((PHHIVE)CmHive, HFILE_TYPE_PRIMARY, Length, Length)) + { + /* This shouldn't fail */ + ASSERT(FALSE); + } + + /* Another thing we don't support is NTLDR-recovery */ + if (CmHive->Hive.BaseBlock->BootRecover) ASSERT(FALSE); + + /* Finally, set our allocated hive to the same hive we've had */ + CmpMachineHiveList[i].CmHive2 = CmHive; + ASSERT(CmpMachineHiveList[i].CmHive == CmpMachineHiveList[i].CmHive2); + } + } + + /* We're done */ +Later: + CmpMachineHiveList[i].ThreadFinished = TRUE; + + /* Check if we're the last worker */ + WorkerCount = InterlockedIncrement(&CmpLoadWorkerIncrement); + if (WorkerCount == CM_NUMBER_OF_MACHINE_HIVES) + + { + /* Signal the event */ + KeSetEvent(&CmpLoadWorkerEvent, 0, FALSE); + } + + /* Kill the thread */ + PsTerminateSystemThread(Status); +} + +VOID +NTAPI +CmpInitializeHiveList(IN USHORT Flag) +{ + WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH]; + UNICODE_STRING TempName, FileName, RegName; + HANDLE Thread; + NTSTATUS Status; + ULONG FileStart, RegStart, i; + PSECURITY_DESCRIPTOR SecurityDescriptor; + PAGED_CODE(); + + /* Allow writing for now */ + CmpNoWrite = FALSE; + + /* Build the file name and registry name strings */ + RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH); + RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH); + + /* Now build the system root path */ + RtlInitUnicodeString(&TempName, L"\SystemRoot\System32\Config\"); + RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName); + FileStart = FileName.Length; + + /* And build the registry root path */ + RtlInitUnicodeString(&TempName, L"\REGISTRY\"); + RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); + RegStart = RegName.Length; + + /* Setup the event to synchronize workers */ + KeInitializeEvent(&CmpLoadWorkerEvent, SynchronizationEvent, FALSE); + + /* Enter special boot condition */ + CmpSpecialBootCondition = TRUE; + + /* Create the SD for the root hives */ + SecurityDescriptor = CmpHiveRootSecurityDescriptor(); + + /* Loop every hive we care about */ + for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++) + { + /* Make sure the list is setup */ + ASSERT(CmpMachineHiveList[i].Name != NULL); + + /* Create a thread to handle this hive */ + Status = PsCreateSystemThread(&Thread, + THREAD_ALL_ACCESS, + NULL, + 0, + NULL, + CmpLoadHiveThread, + (PVOID)i); + if (NT_SUCCESS(Status)) + { + /* We don't care about the handle -- the thread self-terminates */ + ZwClose(Thread); + } + else + { + /* Can't imagine this happening */ + KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 9, 3, i, Status); + } + } + + /* Make sure we've reached the end of the list */ + ASSERT(CmpMachineHiveList[i].Name == NULL); + + /* Wait for hive loading to finish */ + KeWaitForSingleObject(&CmpLoadWorkerEvent, + Executive, + KernelMode, + FALSE, + NULL); + + /* Exit the special boot condition and make sure all workers completed */ + CmpSpecialBootCondition = FALSE; + ASSERT(CmpLoadWorkerIncrement == CM_NUMBER_OF_MACHINE_HIVES); + + /* Loop hives again */ + for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++) + { + /* Make sure the thread ran and finished */ + ASSERT(CmpMachineHiveList[i].ThreadFinished == TRUE); + ASSERT(CmpMachineHiveList[i].ThreadStarted == TRUE); + + /* Check if this was a new hive */ + if (!CmpMachineHiveList[i].CmHive) + { + /* Make sure we allocated something */ + ASSERT(CmpMachineHiveList[i].CmHive2 != NULL); + + /* Build the base name */ + RegName.Length = RegStart; + RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName); + RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); + + /* Check if this is a child of the root */ + if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\') + { + /* Then setup the whole name */ + RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name); + RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); + } + + /* Now link the hive to its master */ + DPRINT1("[HiveLoad]: Link %wZ\n", &RegName); +#if 0 + Status = CmpLinkHiveToMaster(&RegName, + NULL, + CmpMachineHiveList[i].CmHive2, + CmpMachineHiveList[i].Allocate, + SecurityDescriptor); + if (Status != STATUS_SUCCESS) + { + /* Linking needs to work */ + KeBugCheckEx(CONFIG_LIST_FAILED, 11, Status, i, (ULONG_PTR)&RegName); + } + + /* Check if we had to allocate a new hive */ + if (CmpMachineHiveList[i].Allocate) + { + /* Sync the new hive */ + HvSyncHive((PHHIVE)(CmpMachineHiveList[i].CmHive2)); + } +#endif + } + + /* Check if we created a new hive */ + if (CmpMachineHiveList[i].CmHive2) + { + /* TODO: Add to HiveList key */ + } + } + + /* Get rid of the SD */ + ExFreePool(SecurityDescriptor); + + /* FIXME: Link SECURITY to SAM */ + + /* FIXME: Link S-1-5-18 to .Default */ +} + BOOLEAN NTAPI CmInitSystem1(VOID)
Modified: trunk/reactos/ntoskrnl/config/ntapi.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/ntapi.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/config/ntapi.c (original) +++ trunk/reactos/ntoskrnl/config/ntapi.c Thu Nov 22 21:38:32 2007 @@ -494,16 +494,69 @@
NTSTATUS NTAPI +NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes, + IN POBJECT_ATTRIBUTES FileObjectAttributes, + IN ULONG Flags) +{ + return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, Flags, NULL); +} + +NTSTATUS +NTAPI +CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey, + IN POBJECT_ATTRIBUTES SourceFile, + IN ULONG Flags, + IN PKEY_OBJECT KeyBody); + +NTSTATUS +NTAPI NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags, - IN HANDLE TrustClassKey, - IN HANDLE Event, - IN ACCESS_MASK DesiredAccess, - OUT PHANDLE RootHandle) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + IN HANDLE TrustClassKey) +{ + NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + PKEY_OBJECT KeyBody = NULL; + PAGED_CODE(); + + /* Validate flags */ + if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER; + + /* Validate privilege */ + if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode)) + { + /* Fail */ + DPRINT1("Restore Privilege missing!\n"); + //return STATUS_PRIVILEGE_NOT_HELD; + } + + /* Block APCs */ + KeEnterCriticalRegion(); + + /* Check if we have a trust class */ + if (TrustClassKey) + { + /* Reference it */ + Status = ObReferenceObjectByHandle(TrustClassKey, + 0, + CmpKeyObjectType, + PreviousMode, + (PVOID *)&KeyBody, + NULL); + } + + /* Call the internal API */ + Status = CmLoadKey(TargetKey, SourceFile, Flags, KeyBody); + + /* Dereference the trust key, if any */ + if (KeyBody) ObDereferenceObject(KeyBody); + + /* Bring back APCs */ + KeLeaveCriticalRegion(); + + /* Return status */ + return Status; }
NTSTATUS
Modified: trunk/reactos/ntoskrnl/ntoskrnl.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.rbuild?re... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl.rbuild (original) +++ trunk/reactos/ntoskrnl/ntoskrnl.rbuild Thu Nov 22 21:38:32 2007 @@ -140,7 +140,6 @@ </directory> <directory name="cm"> <file>ntfunc.c</file> - <file>regfile.c</file> <file>registry.c</file> <file>regobj.c</file> </directory>
Modified: trunk/reactos/ntoskrnl/sysfuncs.lst URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/sysfuncs.lst?rev=3... ============================================================================== --- trunk/reactos/ntoskrnl/sysfuncs.lst (original) +++ trunk/reactos/ntoskrnl/sysfuncs.lst Thu Nov 22 21:38:32 2007 @@ -101,7 +101,7 @@ NtLoadDriver 1 NtLoadKey 2 NtLoadKey2 3 -NtLoadKeyEx 7 +NtLoadKeyEx 4 NtLockFile 10 NtLockProductActivationKeys 2 NtLockRegistryKey 1