- Refactor the registry initialization code to be somewhat closer to the Cm rewrite branch.

- No actual code/implementation changes per-se, simply moved code into new routines, deleted old routines, renamed some routines and added more error-checking.
- Also performed registry initialization in an order more analogous to Windows.
- Added cmsysini.c from the branch, but it's not used at the moment.

svn path=/trunk/; revision=26669
This commit is contained in:
Alex Ionescu 2007-05-10 00:02:04 +00:00
parent 83bd3b5fc0
commit 0285323c9d
5 changed files with 1061 additions and 288 deletions

View file

@ -22,8 +22,6 @@
/* GLOBALS ******************************************************************/
static BOOLEAN CmiHardwareHiveImported = FALSE;
/* FUNCTIONS ****************************************************************/
static BOOLEAN
@ -85,14 +83,13 @@ CmImportBinaryHive (PCHAR ChunkBase,
}
BOOLEAN INIT_FUNCTION
BOOLEAN
INIT_FUNCTION
CmImportSystemHive(PCHAR ChunkBase,
ULONG ChunkSize)
ULONG ChunkSize,
OUT PEREGISTRY_HIVE *RegistryHive)
{
OBJECT_ATTRIBUTES ObjectAttributes;
PEREGISTRY_HIVE RegistryHive;
UNICODE_STRING KeyName;
NTSTATUS Status;
*RegistryHive = NULL;
DPRINT ("CmImportSystemHive() called\n");
@ -105,56 +102,38 @@ CmImportSystemHive(PCHAR ChunkBase,
DPRINT ("Found '%.*s' magic\n", 4, ChunkBase);
/* Import the binary system hive (non-volatile, offset-based, permanent) */
if (!CmImportBinaryHive (ChunkBase, ChunkSize, 0, &RegistryHive))
if (!CmImportBinaryHive (ChunkBase, ChunkSize, 0, RegistryHive))
{
DPRINT1 ("CmiImportBinaryHive() failed\n");
return FALSE;
}
/* Attach it to the machine key */
RtlInitUnicodeString (&KeyName,
REG_SYSTEM_KEY_NAME);
InitializeObjectAttributes (&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = CmiConnectHive (&ObjectAttributes,
RegistryHive);
if (!NT_SUCCESS(Status))
{
DPRINT1 ("CmiConnectHive(%wZ) failed (Status %lx)\n", &KeyName, Status);
return FALSE;
}
/* Set the hive filename */
RtlCreateUnicodeString (&RegistryHive->HiveFileName,
RtlCreateUnicodeString (&(*RegistryHive)->HiveFileName,
SYSTEM_REG_FILE);
/* Set the log filename */
RtlCreateUnicodeString (&RegistryHive->LogFileName,
RtlCreateUnicodeString (&(*RegistryHive)->LogFileName,
SYSTEM_LOG_FILE);
return TRUE;
}
BOOLEAN INIT_FUNCTION
BOOLEAN
INIT_FUNCTION
CmImportHardwareHive(PCHAR ChunkBase,
ULONG ChunkSize)
ULONG ChunkSize,
OUT PEREGISTRY_HIVE *RegistryHive)
{
OBJECT_ATTRIBUTES ObjectAttributes;
PEREGISTRY_HIVE RegistryHive;
UNICODE_STRING KeyName;
HANDLE HardwareKey;
ULONG Disposition;
NTSTATUS Status;
*RegistryHive = NULL;
DPRINT ("CmImportHardwareHive() called\n");
if (CmiHardwareHiveImported == TRUE)
return TRUE;
if (ChunkBase == NULL &&
ChunkSize == 0)
{
@ -260,39 +239,20 @@ CmImportHardwareHive(PCHAR ChunkBase,
DPRINT ("ChunkBase %lx ChunkSize %lu\n", ChunkBase, ChunkSize);
/* Import the binary system hive (volatile, offset-based, permanent) */
if (!CmImportBinaryHive (ChunkBase, ChunkSize, HIVE_NO_FILE, &RegistryHive))
if (!CmImportBinaryHive (ChunkBase, ChunkSize, HIVE_NO_FILE, RegistryHive))
{
DPRINT1 ("CmiImportBinaryHive() failed\n");
return FALSE;
}
/* Attach it to the machine key */
RtlInitUnicodeString (&KeyName,
REG_HARDWARE_KEY_NAME);
InitializeObjectAttributes (&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = CmiConnectHive (&ObjectAttributes,
RegistryHive);
if (!NT_SUCCESS(Status))
{
DPRINT1 ("CmiConnectHive(%wZ) failed (Status %lx)\n", &KeyName, Status);
// CmiRemoveRegistryHive(RegistryHive);
return FALSE;
}
/* Set the hive filename */
RtlInitUnicodeString (&RegistryHive->HiveFileName,
RtlInitUnicodeString (&(*RegistryHive)->HiveFileName,
NULL);
/* Set the log filename */
RtlInitUnicodeString (&RegistryHive->LogFileName,
RtlInitUnicodeString (&(*RegistryHive)->LogFileName,
NULL);
CmiHardwareHiveImported = TRUE;
return TRUE;
}

View file

@ -54,6 +54,18 @@ VOID
CmiCheckKey(BOOLEAN Verbose,
HANDLE Key);
BOOLEAN
INIT_FUNCTION
CmImportSystemHive(PCHAR ChunkBase,
ULONG ChunkSize,
OUT PEREGISTRY_HIVE *RegistryHive);
BOOLEAN
INIT_FUNCTION
CmImportHardwareHive(PCHAR ChunkBase,
ULONG ChunkSize,
OUT PEREGISTRY_HIVE *RegistryHive);
static NTSTATUS
CmiCreateCurrentControlSetLink(VOID);
@ -66,6 +78,8 @@ CmiHiveSyncDpcRoutine(PKDPC Dpc,
extern LIST_ENTRY CmiCallbackHead;
extern FAST_MUTEX CmiCallbackLock;
UNICODE_STRING CmpSystemStartOptions;
UNICODE_STRING CmpLoadOptions;
/* FUNCTIONS ****************************************************************/
VOID STDCALL
@ -129,99 +143,13 @@ CmiWorkerThread(PVOID Param)
}
}
VOID INIT_FUNCTION
CmInit2(PCHAR CommandLine)
PVOID
NTAPI
CmpRosGetHardwareHive(OUT PULONG Length)
{
ULONG PiceStart = 4;
BOOLEAN MiniNT = FALSE;
NTSTATUS Status;
UNICODE_STRING TempString;
/* Create the 'CurrentControlSet' link. */
Status = CmiCreateCurrentControlSetLink();
if (!NT_SUCCESS(Status))
KEBUGCHECK(CONFIG_INITIALIZATION_FAILED);
/*
* Write the system boot device to registry.
*/
RtlCreateUnicodeStringFromAsciiz(&TempString, KeLoaderBlock->ArcBootDeviceName);
Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
L"SystemBootDevice",
REG_SZ,
TempString.Buffer,
TempString.MaximumLength);
RtlFreeUnicodeString(&TempString);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(CONFIG_INITIALIZATION_FAILED);
}
/*
* Parse the system start options.
*/
if (strstr(KeLoaderBlock->LoadOptions, "DEBUGPORT=PICE") != NULL)
PiceStart = 1;
MiniNT = strstr(KeLoaderBlock->LoadOptions, "MININT") != NULL;
/*
* Write the system start options to registry.
*/
RtlCreateUnicodeStringFromAsciiz(&TempString, KeLoaderBlock->LoadOptions);
Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
L"SystemStartOptions",
REG_SZ,
TempString.Buffer,
TempString.MaximumLength);
RtlFreeUnicodeString(&TempString);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(CONFIG_INITIALIZATION_FAILED);
}
/*
* Create a CurrentControlSet\Control\MiniNT key that is used
* to detect WinPE/MiniNT systems.
*/
if (MiniNT)
{
Status = RtlCreateRegistryKey(RTL_REGISTRY_CONTROL, L"MiniNT");
if (!NT_SUCCESS(Status))
KEBUGCHECK(CONFIG_INITIALIZATION_FAILED);
}
/* Set PICE 'Start' value to 1, if PICE debugging is enabled */
Status = RtlWriteRegistryValue(
RTL_REGISTRY_SERVICES,
L"\\Pice",
L"Start",
REG_DWORD,
&PiceStart,
sizeof(ULONG));
if (!NT_SUCCESS(Status))
KEBUGCHECK(CONFIG_INITIALIZATION_FAILED);
}
VOID
INIT_FUNCTION
STDCALL
CmInitHives(BOOLEAN SetupBoot)
{
PCHAR BaseAddress;
PLIST_ENTRY ListHead, NextEntry;
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock = NULL;
/* Load Registry Hives. This one can be missing. */
BaseAddress = KeLoaderBlock->RegistryBase;
if (BaseAddress)
{
CmImportSystemHive(BaseAddress,
KeLoaderBlock->RegistryLength);
}
/* Loop the memory descriptors */
ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
NextEntry = ListHead->Flink;
@ -236,7 +164,8 @@ CmInitHives(BOOLEAN SetupBoot)
if (MdBlock->MemoryType == LoaderRegistryData)
{
/* Check if it's not the SYSTEM hive that we already initialized */
if ((MdBlock->BasePage) != ((ULONG_PTR)BaseAddress >> PAGE_SHIFT))
if ((MdBlock->BasePage) !=
((ULONG_PTR)KeLoaderBlock->RegistryBase >> PAGE_SHIFT))
{
/* Hardware hive break out */
break;
@ -249,16 +178,239 @@ CmInitHives(BOOLEAN SetupBoot)
/* We need a hardware hive */
ASSERT(MdBlock);
*Length = MdBlock->PageCount << PAGE_SHIFT;
return (PVOID)(MdBlock->BasePage << PAGE_SHIFT);
}
BaseAddress = (PCHAR)(MdBlock->BasePage << PAGE_SHIFT);
CmImportHardwareHive(BaseAddress,
MdBlock->PageCount << PAGE_SHIFT);
NTSTATUS
NTAPI
CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName,
IN HANDLE RootDirectory,
IN PEREGISTRY_HIVE RegistryHive,
IN BOOLEAN Allocate,
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
{
OBJECT_ATTRIBUTES ObjectAttributes;
/* Create dummy keys if no hardware hive was found */
CmImportHardwareHive (NULL, 0);
/* Don't do anything if we don't actually have a hive */
if (Allocate) return STATUS_SUCCESS;
/* Initialize volatile registry settings */
if (SetupBoot == FALSE) CmInit2(KeLoaderBlock->LoadOptions);
/* Setup the object attributes */
InitializeObjectAttributes(&ObjectAttributes,
LinkName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
RootDirectory,
SecurityDescriptor);
/* Connect the hive */
return CmiConnectHive(&ObjectAttributes, RegistryHive);
}
NTSTATUS
NTAPI
CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName, ValueName;
HANDLE KeyHandle;
NTSTATUS Status;
ASSERT(LoaderBlock != NULL);
if (ExpInTextModeSetup) return STATUS_SUCCESS;
/* Setup attributes for loader options */
RtlInitUnicodeString(&KeyName,
L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\"
L"Control");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
if (!NT_SUCCESS(Status)) goto Quickie;
/* Key opened, now write to the key */
RtlInitUnicodeString(&KeyName, L"SystemStartOptions");
Status = NtSetValueKey(KeyHandle,
&KeyName,
0,
REG_SZ,
CmpSystemStartOptions.Buffer,
CmpSystemStartOptions.Length);
if (!NT_SUCCESS(Status)) goto Quickie;
/* Free the options now */
ExFreePool(CmpSystemStartOptions.Buffer);
/* Setup value name for system boot device */
RtlInitUnicodeString(&KeyName, L"SystemBootDevice");
RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->NtBootPathName);
Status = NtSetValueKey(KeyHandle,
&KeyName,
0,
REG_SZ,
ValueName.Buffer,
ValueName.Length);
Quickie:
/* Free the buffers */
RtlFreeUnicodeString(&ValueName);
/* Close the key and return */
NtClose(KeyHandle);
/* Return the status */
return Status;
}
BOOLEAN
NTAPI
CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PVOID HiveBase;
ANSI_STRING LoadString;
PVOID Buffer;
ULONG Length;
NTSTATUS Status;
BOOLEAN Allocate;
UNICODE_STRING KeyName;
PEREGISTRY_HIVE SystemHive;
PAGED_CODE();
/* Setup the ansi string */
RtlInitAnsiString(&LoadString, LoaderBlock->LoadOptions);
/* Allocate the unicode buffer */
Length = LoadString.Length * sizeof(WCHAR) + sizeof(UNICODE_NULL);
Buffer = ExAllocatePoolWithTag(PagedPool, Length, 0);
if (!Buffer)
{
/* Fail */
KEBUGCHECKEX(BAD_SYSTEM_CONFIG_INFO, 3, 1, (ULONG_PTR)LoaderBlock, 0);
}
/* Setup the unicode string */
RtlInitEmptyUnicodeString(&CmpLoadOptions, Buffer, Length);
/* Add the load options and null-terminate */
RtlAnsiStringToUnicodeString(&CmpLoadOptions, &LoadString, FALSE);
CmpLoadOptions.Buffer[LoadString.Length] = UNICODE_NULL;
CmpLoadOptions.Length += sizeof(WCHAR);
/* Get the System Hive base address */
HiveBase = LoaderBlock->RegistryBase;
if (HiveBase)
{
/* Import it */
Status = CmImportSystemHive(HiveBase,
LoaderBlock->RegistryLength,
&SystemHive);
if (!NT_SUCCESS(Status)) return FALSE;
/* We imported, no need to create a new hive */
Allocate = FALSE;
}
else
{
/* FIXME: Create an empty hive */
Allocate = TRUE;
}
/* Attach it to the system key */
RtlInitUnicodeString(&KeyName, REG_SYSTEM_KEY_NAME);
Status = CmpLinkHiveToMaster(&KeyName, NULL, SystemHive, Allocate, NULL);
if (!NT_SUCCESS(Status)) return FALSE;
/* Success! */
return TRUE;
}
NTSTATUS
NTAPI
CmpCreateObjectTypes(VOID)
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
PAGED_CODE();
/* Initialize the Key object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Key");
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(KEY_OBJECT);
ObjectTypeInitializer.GenericMapping = CmiKeyMapping;
ObjectTypeInitializer.PoolType = PagedPool;
ObjectTypeInitializer.ValidAccessMask = KEY_ALL_ACCESS;
ObjectTypeInitializer.UseDefaultObject = TRUE;
ObjectTypeInitializer.DeleteProcedure = CmiObjectDelete;
ObjectTypeInitializer.ParseProcedure = CmiObjectParse;
ObjectTypeInitializer.SecurityProcedure = CmiObjectSecurity;
ObjectTypeInitializer.QueryNameProcedure = CmiObjectQueryName;
/* Create it */
return ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmiKeyType);
}
BOOLEAN
NTAPI
CmpCreateRegistryRoot(VOID)
{
UNICODE_STRING KeyName;
OBJECT_ATTRIBUTES ObjectAttributes;
PKEY_OBJECT RootKey;
HANDLE RootKeyHandle;
NTSTATUS Status;
/* Create '\Registry' key. */
RtlInitUnicodeString(&KeyName, REG_ROOT_KEY_NAME);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ObCreateObject(KernelMode,
CmiKeyType,
&ObjectAttributes,
KernelMode,
NULL,
sizeof(KEY_OBJECT),
0,
0,
(PVOID*)&RootKey);
if (!NT_SUCCESS(Status)) return FALSE;
/* Setup the root key */
RootKey->RegistryHive = CmiVolatileHive;
RootKey->KeyCellOffset = CmiVolatileHive->Hive.HiveHeader->RootCell;
RootKey->KeyCell = HvGetCell(&CmiVolatileHive->Hive, RootKey->KeyCellOffset);
RootKey->ParentKey = RootKey;
RootKey->Flags = 0;
RootKey->SubKeyCounts = 0;
RootKey->SubKeys = NULL;
RootKey->SizeOfSubKeys = 0;
InsertTailList(&CmiKeyObjectListHead, &RootKey->ListEntry);
Status = RtlpCreateUnicodeString(&RootKey->Name, L"Registry", NonPagedPool);
/* Insert the key into the namespace */
Status = ObInsertObject(RootKey,
NULL,
KEY_ALL_ACCESS,
0,
NULL,
&RootKeyHandle);
if (!NT_SUCCESS(Status)) return FALSE;
/* Reference the key again so that we never lose it */
Status = ObReferenceObjectByHandle(RootKeyHandle,
KEY_READ,
NULL,
KernelMode,
(PVOID*)&RootKey,
NULL);
if (!NT_SUCCESS(Status)) return FALSE;
/* Completely sucessful */
return TRUE;
}
BOOLEAN
@ -266,159 +418,172 @@ INIT_FUNCTION
NTAPI
CmInitSystem1(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
PKEY_OBJECT RootKey;
#if 0
PCM_KEY_SECURITY RootSecurityCell;
#endif
HANDLE RootKeyHandle;
HANDLE KeyHandle;
NTSTATUS Status;
LARGE_INTEGER DueTime;
HANDLE ThreadHandle;
CLIENT_ID ThreadId;
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
HANDLE KeyHandle;
NTSTATUS Status;
LARGE_INTEGER DueTime;
HANDLE ThreadHandle;
CLIENT_ID ThreadId;
PEREGISTRY_HIVE HardwareHive;
BOOLEAN Allocate = FALSE;
PVOID BaseAddress;
ULONG Length;
PAGED_CODE();
DPRINT("Creating Registry Object Type\n");
/* Initialize the Key object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Key");
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(KEY_OBJECT);
ObjectTypeInitializer.GenericMapping = CmiKeyMapping;
ObjectTypeInitializer.PoolType = PagedPool;
ObjectTypeInitializer.ValidAccessMask = KEY_ALL_ACCESS;
ObjectTypeInitializer.UseDefaultObject = TRUE;
ObjectTypeInitializer.DeleteProcedure = CmiObjectDelete;
ObjectTypeInitializer.ParseProcedure = CmiObjectParse;
ObjectTypeInitializer.SecurityProcedure = CmiObjectSecurity;
ObjectTypeInitializer.QueryNameProcedure = CmiObjectQueryName;
/* Initialize the hive list */
InitializeListHead(&CmiHiveListHead);
ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmiKeyType);
/* Initialize registry lock */
ExInitializeResourceLite(&CmiRegistryLock);
/* Initialize the hive list */
InitializeListHead(&CmiHiveListHead);
/* Initialize the key object list */
InitializeListHead(&CmiKeyObjectListHead);
InitializeListHead(&CmiConnectedHiveList);
/* Initialize registry lock */
ExInitializeResourceLite(&CmiRegistryLock);
/* Initialize the worker timer */
KeInitializeTimerEx(&CmiWorkerTimer, SynchronizationTimer);
/* Initialize the key object list */
InitializeListHead(&CmiKeyObjectListHead);
InitializeListHead(&CmiConnectedHiveList);
/* Initialize the worker thread */
Status = PsCreateSystemThread(&ThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&ThreadId,
CmiWorkerThread,
NULL);
if (!NT_SUCCESS(Status)) return FALSE;
/* Initialize the worker timer */
KeInitializeTimerEx(&CmiWorkerTimer, SynchronizationTimer);
/* Start the timer */
DueTime.QuadPart = -1;
KeSetTimerEx(&CmiWorkerTimer, DueTime, 5000, NULL); /* 5sec */
/* Initialize the worker thread */
Status = PsCreateSystemThread(&ThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&ThreadId,
CmiWorkerThread,
NULL);
if (!NT_SUCCESS(Status)) return FALSE;
InitializeListHead(&CmiCallbackHead);
ExInitializeFastMutex(&CmiCallbackLock);
/* Start the timer */
DueTime.QuadPart = -1;
KeSetTimerEx(&CmiWorkerTimer, DueTime, 5000, NULL); /* 5sec */
/* Create the key object types */
Status = CmpCreateObjectTypes();
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 1, Status, 0);
}
/* Build volatile registry store */
Status = CmiCreateVolatileHive (&CmiVolatileHive);
ASSERT(NT_SUCCESS(Status));
/* Build volatile registry store */
Status = CmiCreateVolatileHive(&CmiVolatileHive);
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 2, Status, 0);
}
InitializeListHead(&CmiCallbackHead);
ExInitializeFastMutex(&CmiCallbackLock);
/* Create the \REGISTRY key node */
if (!CmpCreateRegistryRoot())
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 4, 0, 0);
}
/* Create '\Registry' key. */
RtlInitUnicodeString(&KeyName, REG_ROOT_KEY_NAME);
InitializeObjectAttributes(&ObjectAttributes, &KeyName, 0, NULL, NULL);
Status = ObCreateObject(KernelMode,
CmiKeyType,
&ObjectAttributes,
KernelMode,
NULL,
sizeof(KEY_OBJECT),
0,
0,
(PVOID *) &RootKey);
ASSERT(NT_SUCCESS(Status));
Status = ObInsertObject(RootKey,
NULL,
KEY_ALL_ACCESS,
0,
NULL,
&RootKeyHandle);
ASSERT(NT_SUCCESS(Status));
RootKey->RegistryHive = CmiVolatileHive;
RootKey->KeyCellOffset = CmiVolatileHive->Hive.HiveHeader->RootCell;
RootKey->KeyCell = HvGetCell (&CmiVolatileHive->Hive, RootKey->KeyCellOffset);
RootKey->ParentKey = RootKey;
RootKey->Flags = 0;
RootKey->SubKeyCounts = 0;
RootKey->SubKeys = NULL;
RootKey->SizeOfSubKeys = 0;
InsertTailList(&CmiKeyObjectListHead, &RootKey->ListEntry);
Status = RtlpCreateUnicodeString(&RootKey->Name, L"Registry", NonPagedPool);
ASSERT(NT_SUCCESS(Status));
/* Create '\Registry\Machine' key. */
RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
NULL);
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 5, Status, 0);
}
#if 0
Status = CmiAllocateCell(CmiVolatileHive,
0x10, //LONG CellSize,
(PVOID *)&RootSecurityCell,
&RootKey->KeyCell->SecurityKeyOffset);
ASSERT(NT_SUCCESS(Status));
/* Close the handle */
NtClose(KeyHandle);
/* Copy the security descriptor */
/* Create '\Registry\User' key. */
RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\USER");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
NULL);
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 6, Status, 0);
}
CmiVolatileHive->RootSecurityCell = RootSecurityCell;
#endif
/* Close the handle */
NtClose(KeyHandle);
/* Initialize the system hive */
if (!CmpInitializeSystemHive(KeLoaderBlock))
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 7, 0, 0);
}
/* Create '\Registry\Machine' key. */
RtlInitUnicodeString(&KeyName,
L"Machine");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
0,
RootKeyHandle,
NULL);
Status = ZwCreateKey(&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
NULL);
ASSERT(NT_SUCCESS(Status));
/* Create the 'CurrentControlSet' link. */
Status = CmiCreateCurrentControlSetLink();
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 8, Status, 0);
}
/* Create '\Registry\User' key. */
RtlInitUnicodeString(&KeyName,
L"User");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
0,
RootKeyHandle,
NULL);
Status = ZwCreateKey(&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
NULL);
ASSERT(NT_SUCCESS(Status));
/* Initialize the hardware hive */
BaseAddress = CmpRosGetHardwareHive(&Length);
if (!CmImportHardwareHive(BaseAddress, Length, &HardwareHive))
{
/* Create dummy keys if no hardware hive was found */
if (!CmImportHardwareHive (NULL, 0, &HardwareHive))
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 11, Status, 0);
}
/* Import and Load Registry Hives */
CmInitHives(ExpInTextModeSetup);
return TRUE;
/* Don't actually link anything below */
Allocate = TRUE;
}
/* Attach it to the machine key */
RtlInitUnicodeString(&KeyName, REG_HARDWARE_KEY_NAME);
Status = CmpLinkHiveToMaster(&KeyName, NULL, HardwareHive, FALSE, NULL);
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 12, Status, 0);
}
/* Initialize volatile registry settings */
Status = CmpSetSystemValues(KeLoaderBlock);
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 15, Status, 0);
}
/* Free the load options */
ExFreePool(CmpLoadOptions.Buffer);
/* If we got here, all went well */
return TRUE;
}
static NTSTATUS
CmiCreateCurrentControlSetLink(VOID)
{
@ -435,6 +600,7 @@ CmiCreateCurrentControlSetLink(VOID)
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
if (ExpInTextModeSetup) return STATUS_SUCCESS;
DPRINT("CmiCreateCurrentControlSetLink() called\n");

View file

@ -0,0 +1,646 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmsysini.c
* PURPOSE: Configuration Manager - System Initialization Code
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
#if 0
/* GLOBALS *******************************************************************/
UNICODE_STRING CmSymbolicLinkValueName =
RTL_CONSTANT_STRING(L"SymbolicLinkValue");
UNICODE_STRING CmpSystemStartOptions;
UNICODE_STRING CmpLoadOptions;
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName, ValueName;
HANDLE KeyHandle;
NTSTATUS Status;
ASSERT(LoaderBlock != NULL);
/* Setup attributes for loader options */
RtlInitUnicodeString(&KeyName,
L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\"
L"Control");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
if (!NT_SUCCESS(Status)) goto Quickie;
/* Key opened, now write to the key */
RtlInitUnicodeString(&KeyName, L"SystemStartOptions");
Status = NtSetValueKey(KeyHandle,
&KeyName,
0,
REG_SZ,
CmpSystemStartOptions.Buffer,
CmpSystemStartOptions.Length);
if (!NT_SUCCESS(Status)) goto Quickie;
/* Free the options now */
ExFreePool(CmpSystemStartOptions.Buffer);
/* Setup value name for system boot device */
RtlInitUnicodeString(&KeyName, L"SystemBootDevice");
RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->NtBootPathName);
Status = NtSetValueKey(KeyHandle,
&KeyName,
0,
REG_SZ,
ValueName.Buffer,
ValueName.Length);
Quickie:
/* Free the buffers */
RtlFreeUnicodeString(&ValueName);
/* Close the key and return */
NtClose(KeyHandle);
/* Return the status */
return Status;
}
NTSTATUS
NTAPI
CmpHwProfileDefaultSelect(IN PVOID ProfileList,
OUT PULONG ProfileIndexToUse,
IN PVOID Context)
{
/* Clear the index and return success */
*ProfileIndexToUse = 0;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpAddDockingInfo(IN HANDLE Key,
IN PPROFILE_PARAMETER_BLOCK ProfileBlock)
{
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING KeyName;
ULONG Value;
PAGED_CODE ();
/* Get the Value from the profile block, create a Name for it and set it */
Value = ProfileBlock->DockingState;
RtlInitUnicodeString(&KeyName, L"DockingState");
Status = NtSetValueKey(Key,
&KeyName,
0,
REG_DWORD,
&Value,
sizeof(Value));
if (!NT_SUCCESS(Status)) return Status;
/* Get the Value from the profile block, create a Name for it and set it */
Value = ProfileBlock->Capabilities;
RtlInitUnicodeString(&KeyName, L"Capabilities");
Status = NtSetValueKey(Key,
&KeyName,
0,
REG_DWORD,
&Value,
sizeof(Value));
if (!NT_SUCCESS(Status)) return Status;
/* Get the Value from the profile block, create a Name for it and set it */
Value = ProfileBlock->DockID;
RtlInitUnicodeString(&KeyName, L"DockID");
Status = NtSetValueKey(Key,
&KeyName,
0,
REG_DWORD,
&Value,
sizeof(Value));
if (!NT_SUCCESS(Status)) return Status;
/* Get the Value from the profile block, create a Name for it and set it */
Value = ProfileBlock->SerialNumber;
RtlInitUnicodeString(&KeyName, L"SerialNumber");
Status = NtSetValueKey(Key,
&KeyName,
0,
REG_DWORD,
&Value,
sizeof(Value));
/* Return Status */
return Status;
}
NTSTATUS
NTAPI
CmpAddAliasEntry(IN HANDLE IDConfigDB,
IN PPROFILE_PARAMETER_BLOCK ProfileBlock,
IN ULONG ProfileNumber)
{
UNICODE_STRING KeyName;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status = STATUS_SUCCESS;
CHAR Buffer[128];
WCHAR UnicodeBuffer[128];
ANSI_STRING TempString;
HANDLE AliasHandle = NULL, AliasIdHandle = NULL;
ULONG Value;
ULONG Disposition;
ULONG AliasId = 0;
PAGED_CODE ();
/* Open the alias key */
RtlInitUnicodeString(&KeyName, L"Alias");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
IDConfigDB,
NULL);
Status = NtOpenKey(&AliasHandle, KEY_READ | KEY_WRITE, &ObjectAttributes);
/* Check if we failed to open it */
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
/* Create it instead */
Status = NtCreateKey(&AliasHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
}
/* Check if we failed */
if (!NT_SUCCESS (Status))
{
/* Cleanup and exit */
AliasHandle = NULL;
goto Exit;
}
/* Loop every alias ID */
while (AliasId++ < 200)
{
/* Build the KeyName */
sprintf(Buffer, "%04ld", AliasId);
RtlInitAnsiString(&TempString, Buffer);
/* Convert it to Unicode */
KeyName.MaximumLength = sizeof(UnicodeBuffer);
KeyName.Buffer = UnicodeBuffer;
Status = RtlAnsiStringToUnicodeString(&KeyName,
&TempString,
FALSE);
ASSERT (STATUS_SUCCESS == Status);
/* Open the key */
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
AliasHandle,
NULL);
Status = NtOpenKey(&AliasIdHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes);
if (NT_SUCCESS (Status))
{
/* We opened it, close and keep looping */
NtClose(AliasIdHandle);
}
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
/* We couldn't find it, change Status and break out */
Status = STATUS_SUCCESS;
break;
}
else
{
/* Any other error, break out */
break;
}
}
/* Check if we failed in the alias loop */
if (!NT_SUCCESS(Status))
{
/* Cleanup and exit */
AliasIdHandle = 0;
goto Exit;
}
/* Otherwise, create the alias key */
Status = NtCreateKey(&AliasIdHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
if (!NT_SUCCESS(Status))
{
/* Cleanup and exit */
AliasIdHandle = 0;
goto Exit;
}
/* Add docking information */
CmpAddDockingInfo(AliasIdHandle, ProfileBlock);
/* Set the profile number */
Value = ProfileNumber;
RtlInitUnicodeString(&KeyName, L"ProfileNumber");
Status = NtSetValueKey(AliasIdHandle,
&KeyName,
0,
REG_DWORD,
&Value,
sizeof(Value));
Exit:
/* Close every opened key */
if (AliasHandle) NtClose(AliasHandle);
if (AliasIdHandle) NtClose(AliasIdHandle);
/* Return Status */
return Status;
}
NTSTATUS
NTAPI
CmSetAcpiHwProfile(IN PPROFILE_ACPI_DOCKING_STATE NewDockState,
IN PVOID Select,
IN PVOID Context,
OUT PHANDLE NewProfile,
OUT PBOOLEAN ProfileChanged)
{
/* FIXME: TODO */
*ProfileChanged = FALSE;
*NewProfile = NULL;
ASSERT(FALSE);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpCloneHwProfile(IN HANDLE ConfigHandle,
IN HANDLE Parent,
IN HANDLE OldProfile,
IN ULONG OldProfileNumber,
IN USHORT DockingState,
OUT PHANDLE NewProfile,
OUT PULONG NewProfileNumber)
{
/* FIXME: TODO */
*NewProfileNumber = FALSE;
*NewProfile = NULL;
ASSERT(FALSE);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpCreateCurrentControlSetLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
UNICODE_STRING ConfigName = RTL_CONSTANT_STRING(L"Control\\ConfigHandle");
UNICODE_STRING SelectName =
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\Select");
UNICODE_STRING KeyName;
OBJECT_ATTRIBUTES ObjectAttributes;
CHAR ValueInfoBuffer[128];
PKEY_VALUE_FULL_INFORMATION ValueInfo;
CHAR Buffer[128];
WCHAR UnicodeBuffer[128];
HANDLE SelectHandle, KeyHandle, ConfigHandle = NULL, ProfileHandle = NULL;
HANDLE ParentHandle = NULL, AcpiHandle;
ULONG ControlSet, HwProfile;
ANSI_STRING TempString;
NTSTATUS Status;
ULONG ResultLength, Disposition;
BOOLEAN AcpiProfile = FALSE;
PLOADER_PARAMETER_EXTENSION LoaderExtension;
PROFILE_ACPI_DOCKING_STATE AcpiDockState;
BOOLEAN Active;
PAGED_CODE();
/* Open the select key */
InitializeObjectAttributes(&ObjectAttributes,
&SelectName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey(&SelectHandle, KEY_READ, &ObjectAttributes);
if (!NT_SUCCESS(Status))return(Status);
/* Open the current value */
RtlInitUnicodeString(&KeyName, L"Current");
Status = NtQueryValueKey(SelectHandle,
&KeyName,
KeyValueFullInformation,
ValueInfoBuffer,
sizeof(ValueInfoBuffer),
&ResultLength);
NtClose(SelectHandle);
if (!NT_SUCCESS(Status)) return Status;
/* Get the actual value pointer, and get the control set ID */
ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
ControlSet = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
/* Create the current control set key */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\System\\CurrentControlSet");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtCreateKey(&KeyHandle,
KEY_CREATE_LINK,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
&Disposition);
if (!NT_SUCCESS(Status)) return Status;
/* Sanity check */
ASSERT(Disposition == REG_CREATED_NEW_KEY);
/* Initialize the symbolic link name */
sprintf(Buffer,
"\\Registry\\Machine\\System\\ControlSet%03ld",
ControlSet);
RtlInitAnsiString(&TempString, Buffer);
/* Create a Unicode string out of it */
KeyName.MaximumLength = sizeof(UnicodeBuffer);
KeyName.Buffer = UnicodeBuffer;
Status = RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE);
/* Set the value */
Status = NtSetValueKey(KeyHandle,
&CmSymbolicLinkValueName,
0,
REG_LINK,
KeyName.Buffer,
KeyName.Length);
if (!NT_SUCCESS(Status)) return Status;
/* Get the configuration database key */
InitializeObjectAttributes(&ObjectAttributes,
&ConfigName,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
Status = NtOpenKey(&ConfigHandle, KEY_READ, &ObjectAttributes);
NtClose(KeyHandle);
/* Check if we don't have one */
if (!NT_SUCCESS(Status))
{
/* Cleanup and exit */
ConfigHandle = 0;
goto Cleanup;
}
/* Now get the current config */
RtlInitUnicodeString(&KeyName, L"CurrentConfig");
Status = NtQueryValueKey(ConfigHandle,
&KeyName,
KeyValueFullInformation,
ValueInfoBuffer,
sizeof(ValueInfoBuffer),
&ResultLength);
/* Set pointer to buffer */
ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
/* Check if we failed or got a non DWORD-value */
if (!(NT_SUCCESS(Status)) || (ValueInfo->Type != REG_DWORD)) goto Cleanup;
/* Get the hadware profile */
HwProfile = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
/* Open the hardware profile key */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\System\\CurrentControlSet"
L"\\Hardware Profiles");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey(&ParentHandle, KEY_READ, &ObjectAttributes);
/* Check if there is no hardware profile key */
if (!NT_SUCCESS (Status))
{
/* Exit and clean up */
ParentHandle = 0;
goto Cleanup;
}
/* Build the profile name */
sprintf(Buffer, "%04ld",HwProfile);
RtlInitAnsiString(&TempString, Buffer);
/* Convert it to Unicode */
KeyName.MaximumLength = sizeof(UnicodeBuffer);
KeyName.Buffer = UnicodeBuffer;
Status = RtlAnsiStringToUnicodeString(&KeyName,
&TempString,
FALSE);
ASSERT(Status == STATUS_SUCCESS);
/* Open the associated key */
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ParentHandle,
NULL);
Status = NtOpenKey(&ProfileHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes);
/* Check if there's no such key */
if (!NT_SUCCESS (Status))
{
/* Cleanup and exit */
ProfileHandle = 0;
goto Cleanup;
}
/* Check if we have a loader block extension */
LoaderExtension = LoaderBlock->Extension;
if (LoaderExtension)
{
/* Check the hardware profile status */
switch (LoaderExtension->Profile.Status)
{
/* Cloned status */
case 3:
/* Clone it */
Status = CmpCloneHwProfile(ConfigHandle,
ParentHandle,
ProfileHandle,
HwProfile,
LoaderExtension->
Profile.DockingState,
&ProfileHandle,
&HwProfile);
if (!NT_SUCCESS(Status))
{
/* Cloning failed, cleanup and exit */
ProfileHandle = 0;
goto Cleanup;
}
/* Set the current config key */
RtlInitUnicodeString(&KeyName, L"CurrentConfig");
Status = NtSetValueKey(ConfigHandle,
&KeyName,
0,
REG_DWORD,
&HwProfile,
sizeof (HwProfile));
if (!NT_SUCCESS (Status)) goto Cleanup;
/* Alias status */
case 1:
/* Create an alias entry */
Status = CmpAddAliasEntry(ConfigHandle,
&LoaderExtension->Profile,
HwProfile);
/* Docking status */
case 2:
/* Create the current dock info key */
RtlInitUnicodeString(&KeyName,
L"CurrentDockInfo");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ConfigHandle,
NULL);
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
&Disposition);
ASSERT (STATUS_SUCCESS == Status);
/* Add the docking information */
Status = CmpAddDockingInfo(KeyHandle,
&LoaderExtension->Profile);
break;
/* Other cases */
case 0:
case 0xC001:
break;
/* Unknown status */
default:
ASSERT(FALSE);
}
}
/* Create the current hardware profile key */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\System\\CurrentControlSet\\"
L"Hardware Profiles\\Current");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtCreateKey(&KeyHandle,
KEY_CREATE_LINK,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
&Disposition);
if (NT_SUCCESS(Status))
{
/* Sanity check */
ASSERT(Disposition == REG_CREATED_NEW_KEY);
/* Create the profile name */
sprintf(Buffer,
"\\Registry\\Machine\\System\\CurrentControlSet\\"
"Hardware Profiles\\%04ld",
HwProfile);
RtlInitAnsiString(&TempString, Buffer);
/* Convert it to Unicode */
KeyName.MaximumLength = sizeof(UnicodeBuffer);
KeyName.Buffer = UnicodeBuffer;
Status = RtlAnsiStringToUnicodeString(&KeyName,
&TempString,
FALSE);
ASSERT (STATUS_SUCCESS == Status);
/* Set it */
Status = NtSetValueKey(KeyHandle,
&CmSymbolicLinkValueName,
0,
REG_LINK,
KeyName.Buffer,
KeyName.Length);
NtClose(KeyHandle);
}
/* Check if we have to set the ACPI Profile */
if (AcpiProfile)
{
/* Setup the docking state to undocked */
AcpiDockState.DockingState = 1;
AcpiDockState.SerialLength = 2;
AcpiDockState.SerialNumber[0] = L'\0';
/* Set the ACPI profile */
Status = CmSetAcpiHwProfile(&AcpiDockState,
CmpHwProfileDefaultSelect,
NULL,
&AcpiHandle,
&Active);
ASSERT(NT_SUCCESS(Status));
/* Close the key */
NtClose(AcpiHandle);
}
/* Close every opened handle */
Cleanup:
if (ConfigHandle) NtClose(ConfigHandle);
if (ProfileHandle) NtClose(ProfileHandle);
if (ParentHandle) NtClose(ParentHandle);
/* Return success */
return STATUS_SUCCESS;
}
#endif

View file

@ -73,8 +73,8 @@ typedef struct __DESCRIPTOR
BOOLEAN NTAPI ObInit(VOID);
BOOLEAN NTAPI CmInitSystem1(VOID);
VOID CmShutdownRegistry(VOID);
BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
BOOLEAN CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize);
//BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
//BOOLEAN CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize);
BOOLEAN NTAPI KdInitSystem(ULONG Reserved, PLOADER_PARAMETER_BLOCK LoaderBlock);
/* FIXME - RtlpCreateUnicodeString is obsolete and should be removed ASAP! */

View file

@ -92,6 +92,7 @@
<file>cmname.c</file>
<file>cmparse.c</file>
<file>cmsecach.c</file>
<file>cmsysini.c</file>
<file>cmvalue.c</file>
</directory>
<directory name="cm">