- 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.
svn path=/trunk/; revision=30680
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
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;
}
+++ /dev/null
-/*
- * 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 */
ULONG BufferSize;
ULONG ResultSize;
PWSTR EndPtr;
+ PCMHIVE CmHive;
+ BOOLEAN Allocate = TRUE;
DPRINT("CmiInitHives() called\n");
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);
}
-
- Status = CmiInitControlSetLink ();
- if (!NT_SUCCESS(Status))
+
+ /* 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))
{
- DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status);
- return(Status);
+ /* This shouldn't fail */
+ ASSERT(FALSE);
}
- }
-
- /* Connect the SOFTWARE hive */
- wcscpy(EndPtr, REG_SOFTWARE_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);
- }
-
- /* Connect the SAM hive */
- wcscpy(EndPtr, REG_SAM_FILE_NAME);
- 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);
+
+ /* 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);
- 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);
+ Status = CmiInitControlSetLink ();
+#endif
}
/* Connect the DEFAULT hive */
wcscpy(EndPtr, REG_DEFAULT_USER_FILE_NAME);
- RtlInitUnicodeString (&FileName,
- ConfigPath);
+ 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");
+ /* 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);
- return(STATUS_SUCCESS);
+ /* Connect the SAM hive */
+ wcscpy(EndPtr, REG_SAM_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_SAM_KEY_NAME);
+ Status = CmpLinkHiveToMaster(&KeyName,
+ NULL,
+ CmHive,
+ FALSE,
+ NULL);
+ return Status;
}
VOID
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))
+ /* Find the cell */
+ Cell = CmpFindValueByName(&RegistryHive->Hive, KeyCell, &LinkName);
+ if (Cell == HCELL_NIL)
{
- DPRINT1("CmiScanKeyForValue() failed (Status %lx)\n", Status);
- return(Status);
+ 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!");
//
#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)
//
//
typedef struct _HIVE_LIST_ENTRY
{
- PWCHAR FileName;
- PWCHAR BaseName;
- PWCHAR RegRootName;
+ PWSTR Name;
+ PWSTR BaseName;
PCMHIVE CmHive;
ULONG HHiveFlags;
ULONG CmHiveFlags;
BOOLEAN ThreadFinished;
BOOLEAN ThreadStarted;
BOOLEAN Allocate;
- BOOLEAN WinPERequired;
} HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY;
//
IN ULONG CheckFlags
);
+VOID
+NTAPI
+CmpInitializeHiveList(
+ IN USHORT Flag
+);
+
//
// Registry Utility Functions
//
);
//
-// Flush Routines
+// Command Routines (Flush, Open, Close, Init);
//
BOOLEAN
NTAPI
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
NTAPI
CmpLazyFlush(
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;
#define NDEBUG
#include "debug.h"
-NTSTATUS
-CmiFlushRegistryHive(PCMHIVE RegistryHive);
-
/* FUNCTIONS *****************************************************************/
BOOLEAN
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)
/* 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;
+}
\r
EX_PUSH_LOCK CmpHiveListHeadLock, CmpLoadHiveLock;\r
\r
-HIVE_LIST_ENTRY CmpMachineHiveList[5];\r
+HIVE_LIST_ENTRY CmpMachineHiveList[] =\r
+{\r
+ { L"HARDWARE", L"MACHINE\\", NULL, HIVE_VOLATILE , 0 , NULL, FALSE, FALSE, FALSE},\r
+ { L"SECURITY", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},\r
+ { L"SOFTWARE", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},\r
+ { L"SYSTEM", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},\r
+ { L"DEFAULT", L"USER\\.DEFAULT", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},\r
+ { L"SAM", L"MACHINE\\", NULL, HIVE_NOLAZYFLUSH , 0 , NULL, FALSE, FALSE, FALSE},\r
+ { NULL, NULL, 0, 0 , 0 , NULL, FALSE, FALSE, FALSE}\r
+};\r
\r
UNICODE_STRING CmSymbolicLinkValueName =\r
RTL_CONSTANT_STRING(L"SymbolicLinkValue");\r
/* 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
ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);\r
return Status;\r
}\r
+\r
+NTSTATUS\r
+NTAPI\r
+CmpDoOpen(IN PHHIVE Hive,\r
+ IN HCELL_INDEX Cell,\r
+ IN PCM_KEY_NODE Node,\r
+ IN PACCESS_STATE AccessState,\r
+ IN KPROCESSOR_MODE AccessMode,\r
+ IN ULONG Attributes,\r
+ IN PCM_PARSE_CONTEXT Context OPTIONAL,\r
+ IN ULONG ControlFlags,\r
+ IN OUT PCM_KEY_CONTROL_BLOCK *CachedKcb,\r
+ IN PUNICODE_STRING KeyName,\r
+ OUT PVOID *Object)\r
+{\r
+ NTSTATUS Status;\r
+ PKEY_OBJECT KeyBody = NULL;\r
+ PCM_KEY_CONTROL_BLOCK Kcb = NULL;\r
+\r
+ /* Make sure the hive isn't locked */\r
+ if ((Hive->HiveFlags & HIVE_IS_UNLOADING) &&\r
+ (((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread()))\r
+ {\r
+ /* It is, don't touch it */\r
+ return STATUS_OBJECT_NAME_NOT_FOUND;\r
+ }\r
+\r
+ /* If we have a KCB, make sure it's locked */\r
+ ASSERT(CmpIsKcbLockedExclusive(*CachedKcb));\r
+\r
+ /* Create the KCB */\r
+ Kcb = CmpCreateKeyControlBlock(Hive, Cell, Node, *CachedKcb, 0, KeyName);\r
+ if (!Kcb) return STATUS_INSUFFICIENT_RESOURCES;\r
+\r
+ /* Make sure it's also locked, and set the pointer */\r
+ ASSERT(CmpIsKcbLockedExclusive(Kcb));\r
+ *CachedKcb = Kcb;\r
+\r
+ /* Allocate the key object */\r
+ Status = ObCreateObject(AccessMode,\r
+ CmpKeyObjectType,\r
+ NULL,\r
+ AccessMode,\r
+ NULL,\r
+ sizeof(KEY_OBJECT),\r
+ 0,\r
+ 0,\r
+ Object);\r
+ if (NT_SUCCESS(Status))\r
+ {\r
+ /* Get the key body and fill it out */\r
+ KeyBody = (PKEY_OBJECT)(*Object); \r
+ KeyBody->KeyControlBlock = Kcb;\r
+ KeyBody->SubKeyCounts = 0;\r
+ KeyBody->SubKeys = NULL;\r
+ KeyBody->SizeOfSubKeys = 0;\r
+ InsertTailList(&CmiKeyObjectListHead, &KeyBody->KeyBodyList);\r
+ }\r
+ else\r
+ {\r
+ /* Failed, dereference the KCB */\r
+ CmpDereferenceKeyControlBlockWithLock(Kcb, FALSE);\r
+ }\r
+\r
+ /* Return status */\r
+ return Status;\r
+}\r
+\r
+/* Remove calls to CmCreateRootNode once this is used! */\r
+NTSTATUS\r
+NTAPI\r
+CmpCreateLinkNode(IN PHHIVE Hive,\r
+ IN HCELL_INDEX Cell,\r
+ IN PACCESS_STATE AccessState,\r
+ IN UNICODE_STRING Name,\r
+ IN KPROCESSOR_MODE AccessMode,\r
+ IN ULONG CreateOptions,\r
+ IN PCM_PARSE_CONTEXT Context,\r
+ IN PCM_KEY_CONTROL_BLOCK ParentKcb,\r
+ OUT PVOID *Object)\r
+{\r
+ NTSTATUS Status;\r
+ HCELL_INDEX KeyCell, LinkCell, ChildCell;\r
+ PKEY_OBJECT KeyBody;\r
+ LARGE_INTEGER TimeStamp;\r
+ PCM_KEY_NODE KeyNode;\r
+ PCM_KEY_CONTROL_BLOCK Kcb = ParentKcb;\r
+ \r
+ /* Link nodes only allowed on the master */\r
+ if (Hive != &CmiVolatileHive->Hive)\r
+ {\r
+ /* Fail */\r
+ DPRINT1("Invalid link node attempt\n");\r
+ return STATUS_ACCESS_DENIED;\r
+ }\r
+ \r
+ /* Acquire the flusher locks */\r
+ ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock);\r
+ ExAcquirePushLockShared((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock);\r
+\r
+ /* Check if the parent is being deleted */\r
+ if (ParentKcb->Delete)\r
+ {\r
+ /* It is, quit */\r
+ ASSERT(FALSE);\r
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+ \r
+ /* Allocate a link node */\r
+ LinkCell = HvAllocateCell(Hive,\r
+ FIELD_OFFSET(CM_KEY_NODE, Name) +\r
+ CmpNameSize(Hive, &Name),\r
+ Stable,\r
+ HCELL_NIL);\r
+ if (LinkCell == HCELL_NIL)\r
+ {\r
+ /* Fail */\r
+ Status = STATUS_INSUFFICIENT_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ \r
+ /* Get the key cell */\r
+ KeyCell = Context->ChildHive.KeyCell;\r
+ if (KeyCell != HCELL_NIL)\r
+ {\r
+ /* Hive exists! */\r
+ ChildCell = KeyCell;\r
+ \r
+ /* Get the node data */\r
+ KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, ChildCell);\r
+ if (!KeyNode)\r
+ {\r
+ /* Fail */\r
+ ASSERT(FALSE);\r
+ Status = STATUS_INSUFFICIENT_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ \r
+ /* Fill out the data */\r
+ KeyNode->Parent = LinkCell;\r
+ KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;\r
+ HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);\r
+ \r
+ /* Now open the key cell */\r
+ KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, KeyCell);\r
+ if (!KeyNode)\r
+ {\r
+ /* Fail */\r
+ ASSERT(FALSE);\r
+ Status = STATUS_INSUFFICIENT_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ \r
+ /* Open the parent */\r
+ Status = CmpDoOpen(Context->ChildHive.KeyHive,\r
+ KeyCell,\r
+ KeyNode,\r
+ AccessState,\r
+ AccessMode,\r
+ CreateOptions,\r
+ NULL,\r
+ 0,\r
+ &Kcb,\r
+ &Name,\r
+ Object);\r
+ HvReleaseCell(Context->ChildHive.KeyHive, KeyCell);\r
+ }\r
+ else\r
+ {\r
+ /* Do the actual create operation */\r
+ Status = CmpDoCreateChild(Context->ChildHive.KeyHive,\r
+ Cell,\r
+ NULL,\r
+ AccessState,\r
+ &Name,\r
+ AccessMode,\r
+ &Context->Class,\r
+ ParentKcb,\r
+ KEY_HIVE_ENTRY | KEY_NO_DELETE,\r
+ &ChildCell,\r
+ Object);\r
+ if (NT_SUCCESS(Status))\r
+ {\r
+ /* Setup root pointer */\r
+ Context->ChildHive.KeyHive->BaseBlock->RootCell = ChildCell;\r
+ }\r
+ }\r
+ \r
+ /* Check if open or create suceeded */\r
+ if (NT_SUCCESS(Status))\r
+ {\r
+ /* Mark the cell dirty */\r
+ HvMarkCellDirty(Context->ChildHive.KeyHive, ChildCell, FALSE);\r
+ \r
+ /* Get the key node */\r
+ KeyNode = HvGetCell(Context->ChildHive.KeyHive, ChildCell);\r
+ if (!KeyNode)\r
+ {\r
+ /* Fail */\r
+ ASSERT(FALSE);\r
+ Status = STATUS_INSUFFICIENT_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ \r
+ /* Release it */\r
+ HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);\r
+ \r
+ /* Set the parent adn flags */\r
+ KeyNode->Parent = LinkCell;\r
+ KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;\r
+ \r
+ /* Get the link node */\r
+ KeyNode = HvGetCell(Hive, LinkCell);\r
+ if (!KeyNode)\r
+ {\r
+ /* Fail */\r
+ ASSERT(FALSE);\r
+ Status = STATUS_INSUFFICIENT_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ \r
+ /* Set it up */\r
+ KeyNode->Signature = CM_LINK_NODE_SIGNATURE;\r
+ KeyNode->Flags = KEY_HIVE_EXIT | KEY_NO_DELETE;\r
+ KeyNode->Parent = Cell;\r
+ KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, &Name);\r
+ if (KeyNode->NameLength < Name.Length) KeyNode->Flags |= KEY_COMP_NAME;\r
+ KeQuerySystemTime(&TimeStamp);\r
+ KeyNode->LastWriteTime = TimeStamp;\r
+ \r
+ /* Clear out the rest */\r
+ KeyNode->SubKeyCounts[Stable] = 0;\r
+ KeyNode->SubKeyCounts[Volatile] = 0;\r
+ KeyNode->SubKeyLists[Stable] = HCELL_NIL;\r
+ KeyNode->SubKeyLists[Volatile] = HCELL_NIL;\r
+ KeyNode->ValueList.Count = 0;\r
+ KeyNode->ValueList.List = HCELL_NIL;\r
+ KeyNode->ClassLength = 0;\r
+ \r
+ /* Reference the root node */\r
+ //KeyNode->ChildHiveReference.KeyHive = Context->ChildHive.KeyHive;\r
+ //KeyNode->ChildHiveReference.KeyCell = ChildCell;\r
+ HvReleaseCell(Hive, LinkCell);\r
+ \r
+ /* Get the parent node */\r
+ KeyNode = HvGetCell(Hive, Cell);\r
+ if (!KeyNode)\r
+ {\r
+ /* Fail */\r
+ ASSERT(FALSE);\r
+ Status = STATUS_INSUFFICIENT_RESOURCES;\r
+ goto Exit; \r
+ }\r
+ \r
+ /* Now add the subkey */\r
+ if (!CmpAddSubKey(Hive, Cell, LinkCell))\r
+ {\r
+ /* Failure! We don't handle this yet! */\r
+ ASSERT(FALSE);\r
+ }\r
+ \r
+ /* Get the key body */\r
+ KeyBody = (PKEY_OBJECT)*Object;\r
+\r
+ /* Sanity checks */\r
+ ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell);\r
+ ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive);\r
+ //ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);\r
+ \r
+ /* Update the timestamp */\r
+ KeQuerySystemTime(&TimeStamp);\r
+ KeyNode->LastWriteTime = TimeStamp;\r
+ \r
+ /* Check if we need to update name maximum */\r
+ if (KeyNode->MaxNameLen < Name.Length)\r
+ {\r
+ /* Do it */\r
+ KeyNode->MaxNameLen = Name.Length;\r
+ KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name.Length;\r
+ }\r
+ \r
+ /* Check if we need toupdate class length maximum */\r
+ if (KeyNode->MaxClassLen < Context->Class.Length)\r
+ {\r
+ /* Update it */\r
+ KeyNode->MaxClassLen = Context->Class.Length;\r
+ }\r
+ }\r
+ \r
+Exit:\r
+ /* Release the flusher locks and return status */\r
+ ExReleasePushLock((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock);\r
+ ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);\r
+ return Status;\r
+}\r
\r
KGUARDED_MUTEX CmpSelfHealQueueLock;\r
LIST_ENTRY CmpSelfHealQueueListHead;\r
+KEVENT CmpLoadWorkerEvent;\r
+LONG CmpLoadWorkerIncrement;\r
PEPROCESS CmpSystemProcess;\r
BOOLEAN HvShutdownComplete;\r
PVOID CmpRegistryLockCallerCaller, CmpRegistryLockCaller;\r
}\r
else\r
{\r
-#if 0\r
/* Create it */\r
- Status = CmpInitializeHive((PCMHIVE*)&SystemHive,\r
+#if 0\r
+ Status = CmpInitializeHive(&SystemHive,\r
HINIT_CREATE,\r
- HIVE_NOLAZYFLUSH,\r
+ 0, //HIVE_NOLAZYFLUSH,\r
HFILE_TYPE_LOG,\r
NULL,\r
NULL,\r
&HiveName,\r
0);\r
if (!NT_SUCCESS(Status)) return FALSE;\r
+ \r
+ /* Set the hive filename */\r
+ RtlCreateUnicodeString(&SystemHive->FileFullPath, SYSTEM_REG_FILE);\r
#endif\r
-\r
/* Tell CmpLinkHiveToMaster to allocate a hive */\r
Allocate = TRUE;\r
}\r
return TRUE;\r
}\r
\r
+VOID\r
+NTAPI\r
+CmpLoadHiveThread(IN PVOID StartContext)\r
+{\r
+ WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH];\r
+ UNICODE_STRING TempName, FileName, RegName;\r
+ ULONG FileStart, RegStart, i, ErrorResponse, ClusterSize, WorkerCount;\r
+ ULONG PrimaryDisposition, SecondaryDisposition, Length;\r
+ PCMHIVE CmHive;\r
+ HANDLE PrimaryHandle, LogHandle;\r
+ NTSTATUS Status = STATUS_SUCCESS;\r
+ PVOID ErrorParameters;\r
+ PAGED_CODE();\r
+ \r
+ /* Get the hive index, make sure it makes sense */\r
+ i = (ULONG)StartContext;\r
+ ASSERT(CmpMachineHiveList[i].Name != NULL);\r
+ DPRINT1("[HiveLoad] Parallel Thread: %d\n", i);\r
+ \r
+ /* We were started */\r
+ CmpMachineHiveList[i].ThreadStarted = TRUE;\r
+ \r
+ /* Build the file name and registry name strings */\r
+ RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH);\r
+ RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH);\r
+ \r
+ /* Now build the system root path */\r
+ RtlInitUnicodeString(&TempName, L"\\SystemRoot\\System32\\Config\\");\r
+ RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName);\r
+ FileStart = FileName.Length;\r
+ \r
+ /* And build the registry root path */\r
+ RtlInitUnicodeString(&TempName, L"\\REGISTRY\\");\r
+ RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);\r
+ RegStart = RegName.Length;\r
+ \r
+ /* Build the base name */\r
+ RegName.Length = RegStart;\r
+ RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName);\r
+ RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);\r
+ \r
+ /* Check if this is a child of the root */\r
+ if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\\')\r
+ {\r
+ /* Then setup the whole name */\r
+ RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);\r
+ RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);\r
+ }\r
+ \r
+ /* Now Add tge rest if the file name */\r
+ RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);\r
+ FileName.Length = FileStart;\r
+ RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName);\r
+ if (!CmpMachineHiveList[i].CmHive)\r
+ {\r
+ /* We need to allocate a ne whive structure */\r
+ CmpMachineHiveList[i].Allocate = TRUE;\r
+ \r
+ /* Load the hive file */\r
+ DPRINT1("[HiveLoad]: Load from file %wZ\n", &FileName);\r
+ CmpMachineHiveList[i].CmHive2 = (PVOID)0xBAADBEEF;\r
+ goto Later;\r
+ Status = CmpInitHiveFromFile(&FileName,\r
+ CmpMachineHiveList[i].HHiveFlags,\r
+ &CmHive,\r
+ &CmpMachineHiveList[i].Allocate,\r
+ 0);\r
+ if (!(NT_SUCCESS(Status)) || !(CmHive->FileHandles[HFILE_TYPE_LOG]))\r
+ {\r
+ /* We failed or couldn't get a log file, raise a hard error */\r
+ ErrorParameters = &FileName;\r
+ NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE,\r
+ 1,\r
+ 1,\r
+ (PULONG_PTR)&ErrorParameters,\r
+ OptionOk,\r
+ &ErrorResponse);\r
+ }\r
+ \r
+ /* Set the hive flags and newly allocated hive pointer */\r
+ CmHive->Flags = CmpMachineHiveList[i].CmHiveFlags;\r
+ CmpMachineHiveList[i].CmHive2 = CmHive;\r
+ }\r
+ else\r
+ {\r
+ /* We already have a hive, is it volatile? */\r
+ CmHive = CmpMachineHiveList[i].CmHive;\r
+ if (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE))\r
+ {\r
+ DPRINT1("[HiveLoad]: Open from file %wZ\n", &FileName);\r
+ CmpMachineHiveList[i].CmHive2 = CmHive;\r
+ goto Later;\r
+ \r
+ /* It's now, open the hive file and log */\r
+ Status = CmpOpenHiveFiles(&FileName,\r
+ L".LOG",\r
+ &PrimaryHandle,\r
+ &LogHandle,\r
+ &PrimaryDisposition,\r
+ &SecondaryDisposition,\r
+ TRUE,\r
+ TRUE,\r
+ FALSE,\r
+ &ClusterSize);\r
+ if (!(NT_SUCCESS(Status)) || !(LogHandle))\r
+ {\r
+ /* Couldn't open the hive or its log file, raise a hard error */\r
+ ErrorParameters = &FileName;\r
+ NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE,\r
+ 1,\r
+ 1,\r
+ (PULONG_PTR)&ErrorParameters,\r
+ OptionOk,\r
+ &ErrorResponse);\r
+ \r
+ /* And bugcheck for posterity's sake */\r
+ KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 9, 0, i, Status);\r
+ }\r
+ \r
+ /* Save the file handles. This should remove our sync hacks */\r
+ CmHive->FileHandles[HFILE_TYPE_LOG] = LogHandle;\r
+ CmHive->FileHandles[HFILE_TYPE_PRIMARY] = PrimaryHandle;\r
+ \r
+ /* Allow lazy flushing since the handles are there -- remove sync hacks */\r
+ ASSERT(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH);\r
+ CmHive->Hive.HiveFlags &= ~HIVE_NOLAZYFLUSH;\r
+ \r
+ /* Get the real size of the hive */\r
+ Length = CmHive->Hive.Storage[Stable].Length + HBLOCK_SIZE;\r
+ \r
+ /* Check if the cluster size doesn't match */\r
+ if (CmHive->Hive.Cluster != ClusterSize) ASSERT(FALSE);\r
+ \r
+ /* Set the file size */\r
+ if (!CmpFileSetSize((PHHIVE)CmHive, HFILE_TYPE_PRIMARY, Length, Length))\r
+ {\r
+ /* This shouldn't fail */\r
+ ASSERT(FALSE);\r
+ }\r
+ \r
+ /* Another thing we don't support is NTLDR-recovery */\r
+ if (CmHive->Hive.BaseBlock->BootRecover) ASSERT(FALSE);\r
+ \r
+ /* Finally, set our allocated hive to the same hive we've had */\r
+ CmpMachineHiveList[i].CmHive2 = CmHive;\r
+ ASSERT(CmpMachineHiveList[i].CmHive == CmpMachineHiveList[i].CmHive2);\r
+ }\r
+ }\r
+ \r
+ /* We're done */\r
+Later:\r
+ CmpMachineHiveList[i].ThreadFinished = TRUE;\r
+ \r
+ /* Check if we're the last worker */\r
+ WorkerCount = InterlockedIncrement(&CmpLoadWorkerIncrement);\r
+ if (WorkerCount == CM_NUMBER_OF_MACHINE_HIVES)\r
+ \r
+ {\r
+ /* Signal the event */\r
+ KeSetEvent(&CmpLoadWorkerEvent, 0, FALSE);\r
+ }\r
+\r
+ /* Kill the thread */\r
+ PsTerminateSystemThread(Status);\r
+}\r
+\r
+VOID\r
+NTAPI\r
+CmpInitializeHiveList(IN USHORT Flag)\r
+{\r
+ WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH];\r
+ UNICODE_STRING TempName, FileName, RegName;\r
+ HANDLE Thread;\r
+ NTSTATUS Status;\r
+ ULONG FileStart, RegStart, i;\r
+ PSECURITY_DESCRIPTOR SecurityDescriptor;\r
+ PAGED_CODE();\r
+ \r
+ /* Allow writing for now */\r
+ CmpNoWrite = FALSE;\r
+ \r
+ /* Build the file name and registry name strings */\r
+ RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH);\r
+ RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH);\r
+ \r
+ /* Now build the system root path */\r
+ RtlInitUnicodeString(&TempName, L"\\SystemRoot\\System32\\Config\\");\r
+ RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName);\r
+ FileStart = FileName.Length;\r
+ \r
+ /* And build the registry root path */\r
+ RtlInitUnicodeString(&TempName, L"\\REGISTRY\\");\r
+ RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);\r
+ RegStart = RegName.Length;\r
+ \r
+ /* Setup the event to synchronize workers */\r
+ KeInitializeEvent(&CmpLoadWorkerEvent, SynchronizationEvent, FALSE);\r
+ \r
+ /* Enter special boot condition */\r
+ CmpSpecialBootCondition = TRUE;\r
+ \r
+ /* Create the SD for the root hives */\r
+ SecurityDescriptor = CmpHiveRootSecurityDescriptor(); \r
+ \r
+ /* Loop every hive we care about */\r
+ for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++)\r
+ {\r
+ /* Make sure the list is setup */\r
+ ASSERT(CmpMachineHiveList[i].Name != NULL);\r
+ \r
+ /* Create a thread to handle this hive */\r
+ Status = PsCreateSystemThread(&Thread,\r
+ THREAD_ALL_ACCESS,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ CmpLoadHiveThread,\r
+ (PVOID)i);\r
+ if (NT_SUCCESS(Status))\r
+ {\r
+ /* We don't care about the handle -- the thread self-terminates */\r
+ ZwClose(Thread);\r
+ }\r
+ else\r
+ {\r
+ /* Can't imagine this happening */\r
+ KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 9, 3, i, Status);\r
+ }\r
+ }\r
+ \r
+ /* Make sure we've reached the end of the list */\r
+ ASSERT(CmpMachineHiveList[i].Name == NULL);\r
+ \r
+ /* Wait for hive loading to finish */\r
+ KeWaitForSingleObject(&CmpLoadWorkerEvent,\r
+ Executive,\r
+ KernelMode,\r
+ FALSE,\r
+ NULL);\r
+ \r
+ /* Exit the special boot condition and make sure all workers completed */\r
+ CmpSpecialBootCondition = FALSE;\r
+ ASSERT(CmpLoadWorkerIncrement == CM_NUMBER_OF_MACHINE_HIVES);\r
+ \r
+ /* Loop hives again */\r
+ for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++)\r
+ {\r
+ /* Make sure the thread ran and finished */\r
+ ASSERT(CmpMachineHiveList[i].ThreadFinished == TRUE);\r
+ ASSERT(CmpMachineHiveList[i].ThreadStarted == TRUE);\r
+ \r
+ /* Check if this was a new hive */\r
+ if (!CmpMachineHiveList[i].CmHive)\r
+ {\r
+ /* Make sure we allocated something */\r
+ ASSERT(CmpMachineHiveList[i].CmHive2 != NULL);\r
+ \r
+ /* Build the base name */\r
+ RegName.Length = RegStart;\r
+ RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName);\r
+ RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);\r
+ \r
+ /* Check if this is a child of the root */\r
+ if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\\')\r
+ {\r
+ /* Then setup the whole name */\r
+ RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);\r
+ RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);\r
+ }\r
+ \r
+ /* Now link the hive to its master */\r
+ DPRINT1("[HiveLoad]: Link %wZ\n", &RegName);\r
+#if 0\r
+ Status = CmpLinkHiveToMaster(&RegName,\r
+ NULL,\r
+ CmpMachineHiveList[i].CmHive2,\r
+ CmpMachineHiveList[i].Allocate,\r
+ SecurityDescriptor);\r
+ if (Status != STATUS_SUCCESS)\r
+ {\r
+ /* Linking needs to work */\r
+ KeBugCheckEx(CONFIG_LIST_FAILED, 11, Status, i, (ULONG_PTR)&RegName);\r
+ }\r
+ \r
+ /* Check if we had to allocate a new hive */\r
+ if (CmpMachineHiveList[i].Allocate)\r
+ {\r
+ /* Sync the new hive */\r
+ HvSyncHive((PHHIVE)(CmpMachineHiveList[i].CmHive2));\r
+ }\r
+#endif \r
+ }\r
+ \r
+ /* Check if we created a new hive */\r
+ if (CmpMachineHiveList[i].CmHive2)\r
+ {\r
+ /* TODO: Add to HiveList key */\r
+ }\r
+ }\r
+ \r
+ /* Get rid of the SD */\r
+ ExFreePool(SecurityDescriptor);\r
+\r
+ /* FIXME: Link SECURITY to SAM */\r
+ \r
+ /* FIXME: Link S-1-5-18 to .Default */\r
+}\r
+\r
BOOLEAN\r
NTAPI\r
CmInitSystem1(VOID)\r
return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0);
}
+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)
+ IN HANDLE TrustClassKey)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ 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
</directory>
<directory name="cm">
<file>ntfunc.c</file>
- <file>regfile.c</file>
<file>registry.c</file>
<file>regobj.c</file>
</directory>
NtLoadDriver 1
NtLoadKey 2
NtLoadKey2 3
-NtLoadKeyEx 7
+NtLoadKeyEx 4
NtLockFile 10
NtLockProductActivationKeys 2
NtLockRegistryKey 1