/*
* PROJECT: ReactOS Kernel
- * LICENSE: GPL - See COPYING in the top level directory
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: ntoskrnl/config/cmsysini.c
* PURPOSE: Configuration Manager - System Initialization Code
- * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ * Alex Ionescu (alex.ionescu@reactos.org)
*/
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
PEPROCESS CmpSystemProcess;
BOOLEAN HvShutdownComplete;
PVOID CmpRegistryLockCallerCaller, CmpRegistryLockCaller;
-BOOLEAN CmpFlushStarveWriters;
BOOLEAN CmpFlushOnLockRelease;
BOOLEAN CmpSpecialBootCondition;
BOOLEAN CmpNoWrite;
-BOOLEAN CmpForceForceFlush;
BOOLEAN CmpWasSetupBoot;
+BOOLEAN CmpProfileLoaded;
+ULONG CmpTraceLevel = 0;
+extern LONG CmpFlushStarveWriters;
extern BOOLEAN CmFirstTime;
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN
+NTAPI
+CmpLinkKeyToHive(
+ _In_z_ PWSTR LinkKeyName,
+ _In_z_ PWSTR TargetKeyName)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING LinkKeyName_U;
+ HANDLE TargetKeyHandle;
+ ULONG Disposition;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ /* Initialize the object attributes */
+ RtlInitUnicodeString(&LinkKeyName_U, LinkKeyName);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &LinkKeyName_U,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+
+ /* Create the link key */
+ Status = ZwCreateKey(&TargetKeyHandle,
+ KEY_CREATE_LINK,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
+ &Disposition);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CM: CmpLinkKeyToHive: couldn't create %S Status = 0x%lx\n",
+ LinkKeyName, Status);
+ return FALSE;
+ }
+
+ /* Check if the new key was actually created */
+ if (Disposition != REG_CREATED_NEW_KEY)
+ {
+ DPRINT1("CM: CmpLinkKeyToHive: %S already exists!\n", LinkKeyName);
+ ZwClose(TargetKeyHandle);
+ return FALSE;
+ }
+
+ /* Set the target key name as link target */
+ Status = ZwSetValueKey(TargetKeyHandle,
+ &CmSymbolicLinkValueName,
+ 0,
+ REG_LINK,
+ TargetKeyName,
+ wcslen(TargetKeyName) * sizeof(WCHAR));
+
+ /* Close the link key handle */
+ ObCloseHandle(TargetKeyHandle, KernelMode);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CM: CmpLinkKeyToHive: couldn't create symbolic link for %S\n",
+ TargetKeyName);
+ return FALSE;
+ }
+
+ return TRUE;
+}
VOID
NTAPI
REG_POST_OPERATION_INFORMATION PostOperationInfo;
NTSTATUS Status;
PAGED_CODE();
-
+
/* First off, prepare the handle close information callback */
PostOperationInfo.Object = KeyBody;
KeyHandleCloseInfo.Object = KeyBody;
CmiCallRegisteredCallbacks(RegNtPostKeyHandleClose, &PostOperationInfo);
return;
}
-
+
/* Acquire hive lock */
CmpLockRegistry();
-
+
/* Make sure this is a valid key body */
- if (KeyBody->Type == TAG('k', 'y', '0', '2'))
+ if (KeyBody->Type == '20yk')
{
/* Get the KCB */
Kcb = KeyBody->KeyControlBlock;
{
/* Delist the key */
DelistKeyBodyFromKCB(KeyBody, FALSE);
+
+ /* Dereference the KCB */
+ CmpDelayDerefKeyControlBlock(Kcb);
}
-
- /* Dereference the KCB */
- CmpDelayDerefKeyControlBlock(Kcb);
-
}
-
+
/* Release the registry lock */
CmpUnlockRegistry();
-
+
/* Do the post callback */
PostOperationInfo.Status = STATUS_SUCCESS;
CmiCallRegisteredCallbacks(RegNtPostKeyHandleClose, &PostOperationInfo);
{
PCM_KEY_BODY KeyBody = (PCM_KEY_BODY)Object;
PAGED_CODE();
-
+
/* Don't do anything if we're not the last handle */
if (SystemHandleCount > 1) return;
-
+
/* Make sure we're a valid key body */
- if (KeyBody->Type == TAG('k', 'y', '0', '2'))
+ if (KeyBody->Type == '20yk')
{
/* Don't do anything if we don't have a notify block */
if (!KeyBody->NotifyBlock) return;
-
+
/* This shouldn't happen yet */
ASSERT(FALSE);
}
OUT PULONG ReturnLength,
IN KPROCESSOR_MODE PreviousMode)
{
- DPRINT1("CmpQueryKeyName() called\n");
- while (TRUE);
- return STATUS_SUCCESS;
+ PUNICODE_STRING KeyName;
+ ULONG BytesToCopy;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCM_KEY_BODY KeyBody = (PCM_KEY_BODY)ObjectBody;
+ PCM_KEY_CONTROL_BLOCK Kcb = KeyBody->KeyControlBlock;
+
+ /* Acquire hive lock */
+ CmpLockRegistry();
+
+ /* Lock KCB shared */
+ CmpAcquireKcbLockShared(Kcb);
+
+ /* Check if it's a deleted block */
+ if (Kcb->Delete)
+ {
+ /* Release the locks */
+ CmpReleaseKcbLock(Kcb);
+ CmpUnlockRegistry();
+
+ /* Let the caller know it's deleted */
+ return STATUS_KEY_DELETED;
+ }
+
+ /* Get the name */
+ KeyName = CmpConstructName(Kcb);
+
+ /* Release the locks */
+ CmpReleaseKcbLock(Kcb);
+ CmpUnlockRegistry();
+
+ /* Check if we got the name */
+ if (!KeyName) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Set the returned length */
+ *ReturnLength = KeyName->Length + sizeof(OBJECT_NAME_INFORMATION) + sizeof(WCHAR);
+
+ /* Calculate amount of bytes to copy into the buffer */
+ BytesToCopy = KeyName->Length + sizeof(WCHAR);
+
+ /* Check if the provided buffer is too small to fit even anything */
+ if ((Length <= sizeof(OBJECT_NAME_INFORMATION)) ||
+ ((Length < (*ReturnLength)) && (BytesToCopy < sizeof(WCHAR))))
+ {
+ /* Free the buffer allocated by CmpConstructName */
+ ExFreePoolWithTag(KeyName, TAG_CM);
+
+ /* Return buffer length failure without writing anything there because nothing fits */
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* Check if the provided buffer can be partially written */
+ if (Length < (*ReturnLength))
+ {
+ /* Yes, indicate so in the return status */
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+
+ /* Calculate amount of bytes which the provided buffer could handle */
+ BytesToCopy = Length - sizeof(OBJECT_NAME_INFORMATION);
+ }
+
+ /* Remove the null termination character from the size */
+ BytesToCopy -= sizeof(WCHAR);
+
+ /* Fill in the result */
+ _SEH2_TRY
+ {
+ /* Return data to user */
+ ObjectNameInfo->Name.Buffer = (PWCHAR)(ObjectNameInfo + 1);
+ ObjectNameInfo->Name.MaximumLength = KeyName->Length;
+ ObjectNameInfo->Name.Length = KeyName->Length;
+
+ /* Copy string content*/
+ RtlCopyMemory(ObjectNameInfo->Name.Buffer,
+ KeyName->Buffer,
+ BytesToCopy);
+
+ /* Null terminate it */
+ ObjectNameInfo->Name.Buffer[BytesToCopy / sizeof(WCHAR)] = 0;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the status */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Free the buffer allocated by CmpConstructName */
+ ExFreePoolWithTag(KeyName, TAG_CM);
+
+ /* Return status */
+ return Status;
}
NTSTATUS
NTSTATUS
NTAPI
+INIT_FUNCTION
CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING KeyName, ValueName = {0};
- HANDLE KeyHandle;
+ UNICODE_STRING KeyName, ValueName = { 0, 0, NULL };
+ HANDLE KeyHandle = NULL;
NTSTATUS Status;
ASSERT(LoaderBlock != NULL);
CmpLoadOptions.Length);
if (!NT_SUCCESS(Status)) goto Quickie;
- /* Setup value name for system boot device */
+ /* Setup value name for system boot device in ARC format */
RtlInitUnicodeString(&KeyName, L"SystemBootDevice");
- RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->NtBootPathName);
+ RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->ArcBootDeviceName);
Status = NtSetValueKey(KeyHandle,
&KeyName,
0,
RtlFreeUnicodeString(&ValueName);
/* Close the key and return */
- NtClose(KeyHandle);
+ if (KeyHandle) NtClose(KeyHandle);
/* Return the status */
return (ExpInTextModeSetup ? STATUS_SUCCESS : Status);
NTSTATUS
NTAPI
+INIT_FUNCTION
CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
UNICODE_STRING ConfigName = RTL_CONSTANT_STRING(L"Control\\IDConfigDB");
LoaderExtension = LoaderBlock->Extension;
if (LoaderExtension)
{
- ASSERTMSG("ReactOS doesn't support NTLDR Profiles yet!\n", FALSE);
+ DPRINT("ReactOS doesn't support NTLDR Profiles yet!\n");
}
/* Create the current hardware profile key */
HANDLE KeyHandle;
PCM_KEY_BODY KeyBody;
PAGED_CODE();
-
+
/* Setup the object attributes */
InitializeObjectAttributes(&ObjectAttributes,
LinkName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
RootDirectory,
SecurityDescriptor);
-
+
/* Setup the parse context */
ParseContext.CreateLink = TRUE;
ParseContext.CreateOperation = TRUE;
ParseContext.ChildHive.KeyHive = &RegistryHive->Hive;
-
+
/* Check if we have a root keycell or if we need to create it */
if (Allocate)
{
else
{
/* We have one */
- ParseContext.ChildHive.KeyCell = RegistryHive->Hive.BaseBlock->RootCell;
+ ParseContext.ChildHive.KeyCell = RegistryHive->Hive.BaseBlock->RootCell;
}
/* Create the link node */
(PVOID)&ParseContext,
&KeyHandle);
if (!NT_SUCCESS(Status)) return Status;
-
+
/* Mark the hive as clean */
RegistryHive->Hive.DirtyFlag = FALSE;
-
+
/* ReactOS Hack: Keep alive */
Status = ObReferenceObjectByHandle(KeyHandle,
0,
/* Close the extra handle */
ZwClose(KeyHandle);
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
BOOLEAN
NTAPI
+INIT_FUNCTION
CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PVOID HiveBase;
if (!Buffer)
{
/* Fail */
- KEBUGCHECKEX(BAD_SYSTEM_CONFIG_INFO, 3, 1, (ULONG_PTR)LoaderBlock, 0);
+ KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 3, 1, (ULONG_PTR)LoaderBlock, 0);
}
/* Setup the unicode string */
if (HiveBase)
{
/* Import it */
- ((PHBASE_BLOCK)HiveBase)->Length = LoaderBlock->RegistryLength;
Status = CmpInitializeHive((PCMHIVE*)&SystemHive,
HINIT_MEMORY,
HIVE_NOLAZYFLUSH,
&HiveName,
0);
if (!NT_SUCCESS(Status)) return FALSE;
-
+
/* Set the hive filename */
RtlCreateUnicodeString(&SystemHive->FileFullPath,
L"\\SystemRoot\\System32\\Config\\SYSTEM");
}
/* Save the boot type */
- if (SystemHive) CmpBootType = SystemHive->Hive.BaseBlock->BootType;
+ CmpBootType = SystemHive->Hive.BaseBlock->BootType;
/* Are we in self-healing mode? */
if (!CmSelfHeal)
if (CmpBootType & 4)
{
/* We're disabled, so bugcheck */
- KEBUGCHECKEX(BAD_SYSTEM_CONFIG_INFO,
+ KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO,
3,
3,
(ULONG_PTR)SystemHive,
SecurityDescriptor);
/* Free the security descriptor */
- ExFreePool(SecurityDescriptor);
+ ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
if (!NT_SUCCESS(Status)) return FALSE;
/* Add the hive to the hive list */
NTSTATUS
NTAPI
+INIT_FUNCTION
CmpCreateObjectTypes(VOID)
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
ObjectTypeInitializer.QueryNameProcedure = CmpQueryKeyName;
ObjectTypeInitializer.CloseProcedure = CmpCloseKeyObject;
ObjectTypeInitializer.SecurityRequired = TRUE;
+ ObjectTypeInitializer.InvalidAttributes = OBJ_EXCLUSIVE | OBJ_PERMANENT;
/* Create it */
return ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmpKeyObjectType);
BOOLEAN
NTAPI
+INIT_FUNCTION
CmpCreateRootNode(IN PHHIVE Hive,
IN PCWSTR Name,
OUT PHCELL_INDEX Index)
BOOLEAN
NTAPI
+INIT_FUNCTION
CmpCreateRegistryRoot(VOID)
{
UNICODE_STRING KeyName;
0,
0,
(PVOID*)&RootKey);
- ExFreePool(SecurityDescriptor);
+ ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
if (!NT_SUCCESS(Status)) return FALSE;
/* Sanity check, and get the key cell */
/* Initialize the object */
RootKey->KeyControlBlock = Kcb;
- RootKey->Type = TAG('k', 'y', '0', '2');
+ RootKey->Type = '20yk';
RootKey->NotifyBlock = NULL;
RootKey->ProcessID = PsGetCurrentProcessId();
KEY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status)) return Status;
-
+
/* Allocate the buffer */
BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
ValueInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_CM);
if (!NT_SUCCESS(Status))
{
/* Fail */
- ExFreePool(ValueInfo);
+ ExFreePoolWithTag(ValueInfo, TAG_CM);
return Status;
}
ValueInfo->Data,
ValueInfo->DataLength);
ConfigPath[ValueInfo->DataLength / sizeof(WCHAR)] = UNICODE_NULL;
- ExFreePool(ValueInfo);
+ ExFreePoolWithTag(ValueInfo, TAG_CM);
}
else
{
{
WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH], ConfigPath[MAX_PATH];
UNICODE_STRING TempName, FileName, RegName;
- ULONG FileStart, RegStart, i, ErrorResponse, WorkerCount, Length;
+ ULONG i, ErrorResponse, WorkerCount, Length;
+ USHORT FileStart;
+ //ULONG RegStart;
ULONG PrimaryDisposition, SecondaryDisposition, ClusterSize;
PCMHIVE CmHive;
- HANDLE PrimaryHandle, LogHandle;
+ HANDLE PrimaryHandle = NULL, LogHandle = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PVOID ErrorParameters;
PAGED_CODE();
-
+
/* Get the hive index, make sure it makes sense */
- i = (ULONG)StartContext;
+ i = PtrToUlong(StartContext);
ASSERT(CmpMachineHiveList[i].Name != NULL);
-
+
/* 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 */
CmpGetRegistryPath(ConfigPath);
RtlInitUnicodeString(&TempName, ConfigPath);
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;
-
+ //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] == '\\')
{
RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);
RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
}
-
+
/* Now add the rest of the file name */
RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);
FileName.Length = FileStart;
{
/* We need to allocate a new hive structure */
CmpMachineHiveList[i].Allocate = TRUE;
-
+
/* Load the hive file */
Status = CmpInitHiveFromFile(&FileName,
CmpMachineHiveList[i].HHiveFlags,
OptionOk,
&ErrorResponse);
}
-
+
/* Set the hive flags and newly allocated hive pointer */
CmHive->Flags = CmpMachineHiveList[i].CmHiveFlags;
CmpMachineHiveList[i].CmHive2 = CmHive;
(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;
/* 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 */
+ DPRINT("FIXME: Should set file size: %lx\n", Length);
//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 */
CmpMachineHiveList[i].ThreadFinished = TRUE;
-
+
/* Check if we're the last worker */
WorkerCount = InterlockedIncrement(&CmpLoadWorkerIncrement);
if (WorkerCount == CM_NUMBER_OF_MACHINE_HIVES)
UNICODE_STRING TempName, FileName, RegName;
HANDLE Thread;
NTSTATUS Status;
- ULONG FileStart, RegStart, i;
+ ULONG i;
+ USHORT RegStart;
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 */
CmpGetRegistryPath(ConfigPath);
RtlInitUnicodeString(&TempName, ConfigPath);
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();
-
+ 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,
0,
NULL,
CmpLoadHiveThread,
- (PVOID)i);
+ UlongToPtr(i));
if (NT_SUCCESS(Status))
{
/* We don't care about the handle -- the thread self-terminates */
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] == '\\')
{
RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);
RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
}
-
+
/* Now link the hive to its master */
Status = CmpLinkHiveToMaster(&RegName,
NULL,
/* 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)
+ if (CmpMachineHiveList[i].Allocate)
{
/* Sync the new hive */
- //HvSyncHive((PHHIVE)(CmpMachineHiveList[i].CmHive2));
- }
+ //HvSyncHive((PHHIVE)(CmpMachineHiveList[i].CmHive2));
+ }
}
-
+
/* Check if we created a new hive */
if (CmpMachineHiveList[i].CmHive2)
{
- /* TODO: Add to HiveList key */
+ /* Add to HiveList key */
+ CmpAddToHiveFileList(CmpMachineHiveList[i].CmHive2);
}
}
-
+
/* Get rid of the SD */
- ExFreePool(SecurityDescriptor);
+ ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
+
+ /* Link SECURITY to SAM */
+ CmpLinkKeyToHive(L"\\Registry\\Machine\\Security\\SAM",
+ L"\\Registry\\Machine\\SAM\\SAM");
- /* FIXME: Link SECURITY to SAM */
-
- /* FIXME: Link S-1-5-18 to .Default */
+ /* Link S-1-5-18 to .Default */
+ CmpLinkKeyToHive(L"\\Registry\\User\\S-1-5-18",
+ L"\\Registry\\User\\.Default");
}
BOOLEAN
NTAPI
+INIT_FUNCTION
CmInitSystem1(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
/* Initialize the hive list and lock */
InitializeListHead(&CmpHiveListHead);
- ExInitializePushLock((PVOID)&CmpHiveListHeadLock);
- ExInitializePushLock((PVOID)&CmpLoadHiveLock);
+ ExInitializePushLock(&CmpHiveListHeadLock);
+ ExInitializePushLock(&CmpLoadHiveLock);
/* Initialize registry lock */
ExInitializeResourceLite(&CmpRegistryLock);
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 1, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 1, Status, 0);
}
/* Build the master hive */
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 2, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 2, Status, 0);
}
/* Create the \REGISTRY key node */
if (!CmpCreateRegistryRoot())
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 3, 0, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 3, 0, 0);
}
/* Create the default security descriptor */
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 5, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 5, Status, 0);
}
/* Close the handle */
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 6, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 6, Status, 0);
}
/* Close the handle */
if (!CmpInitializeSystemHive(KeLoaderBlock))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 7, 0, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 7, 0, 0);
}
/* Create the 'CurrentControlSet' link. */
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 8, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 8, Status, 0);
}
/* Create the hardware hive */
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 11, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 11, Status, 0);
}
-
+
/* Add the hive to the hive list */
CmpMachineHiveList[0].CmHive = (PCMHIVE)HardwareHive;
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 12, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 12, Status, 0);
}
-
- /* FIXME: Add to HiveList key */
-
+
+ /* Add to HiveList key */
+ CmpAddToHiveFileList(HardwareHive);
+
/* Free the security descriptor */
- ExFreePool(SecurityDescriptor);
+ ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
/* Fill out the Hardware key with the ARC Data from the Loader */
Status = CmpInitializeHardwareConfiguration(KeLoaderBlock);
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 13, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 13, Status, 0);
}
/* Initialize machine-dependent information into the registry */
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 14, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 14, Status, 0);
}
/* Initialize volatile registry settings */
if (!NT_SUCCESS(Status))
{
/* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 15, Status, 0);
+ KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 15, Status, 0);
}
/* Free the load options */
- ExFreePool(CmpLoadOptions.Buffer);
+ ExFreePoolWithTag(CmpLoadOptions.Buffer, TAG_CM);
/* If we got here, all went well */
return TRUE;
}
+VOID
+NTAPI
+INIT_FUNCTION
+CmpFreeDriverList(IN PHHIVE Hive,
+ IN PLIST_ENTRY DriverList)
+{
+ PLIST_ENTRY NextEntry, OldEntry;
+ PBOOT_DRIVER_NODE DriverNode;
+ PAGED_CODE();
+
+ /* Parse the current list */
+ NextEntry = DriverList->Flink;
+ while (NextEntry != DriverList)
+ {
+ /* Get the driver node */
+ DriverNode = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_NODE, ListEntry.Link);
+
+ /* Get the next entry now, since we're going to free it later */
+ OldEntry = NextEntry;
+ NextEntry = NextEntry->Flink;
+
+ /* Was there a name? */
+ if (DriverNode->Name.Buffer)
+ {
+ /* Free it */
+ CmpFree(DriverNode->Name.Buffer, DriverNode->Name.Length);
+ }
+
+ /* Was there a registry path? */
+ if (DriverNode->ListEntry.RegistryPath.Buffer)
+ {
+ /* Free it */
+ CmpFree(DriverNode->ListEntry.RegistryPath.Buffer,
+ DriverNode->ListEntry.RegistryPath.MaximumLength);
+ }
+
+ /* Was there a file path? */
+ if (DriverNode->ListEntry.FilePath.Buffer)
+ {
+ /* Free it */
+ CmpFree(DriverNode->ListEntry.FilePath.Buffer,
+ DriverNode->ListEntry.FilePath.MaximumLength);
+ }
+
+ /* Now free the node, and move on */
+ CmpFree(OldEntry, sizeof(BOOT_DRIVER_NODE));
+ }
+}
+
+PUNICODE_STRING*
+NTAPI
+INIT_FUNCTION
+CmGetSystemDriverList(VOID)
+{
+ LIST_ENTRY DriverList;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ PCM_KEY_BODY KeyBody;
+ PHHIVE Hive;
+ HCELL_INDEX RootCell, ControlCell;
+ HANDLE KeyHandle;
+ UNICODE_STRING KeyName;
+ PLIST_ENTRY NextEntry;
+ ULONG i;
+ PUNICODE_STRING* ServicePath = NULL;
+ BOOLEAN Success, AutoSelect;
+ PBOOT_DRIVER_LIST_ENTRY DriverEntry;
+ PAGED_CODE();
+
+ /* Initialize the driver list */
+ InitializeListHead(&DriverList);
+
+ /* Open the system hive key */
+ RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
+ if (!NT_SUCCESS(Status)) return NULL;
+
+ /* Reference the key object to get the root hive/cell to access directly */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_QUERY_VALUE,
+ CmpKeyObjectType,
+ KernelMode,
+ (PVOID*)&KeyBody,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail */
+ NtClose(KeyHandle);
+ return NULL;
+ }
+
+ /* Do all this under the registry lock */
+ CmpLockRegistryExclusive();
+
+ /* Get the hive and key cell */
+ Hive = KeyBody->KeyControlBlock->KeyHive;
+ RootCell = KeyBody->KeyControlBlock->KeyCell;
+
+ /* Open the current control set key */
+ RtlInitUnicodeString(&KeyName, L"Current");
+ ControlCell = CmpFindControlSet(Hive, RootCell, &KeyName, &AutoSelect);
+ if (ControlCell == HCELL_NIL) goto EndPath;
+
+ /* Find all system drivers */
+ Success = CmpFindDrivers(Hive, ControlCell, SystemLoad, NULL, &DriverList);
+ if (!Success) goto EndPath;
+
+ /* Sort by group/tag */
+ if (!CmpSortDriverList(Hive, ControlCell, &DriverList)) goto EndPath;
+
+ /* Remove circular dependencies (cycles) and sort */
+ if (!CmpResolveDriverDependencies(&DriverList)) goto EndPath;
+
+ /* Loop the list to count drivers */
+ for (i = 0, NextEntry = DriverList.Flink;
+ NextEntry != &DriverList;
+ i++, NextEntry = NextEntry->Flink);
+
+ /* Allocate the array */
+ ServicePath = ExAllocatePool(NonPagedPool, (i + 1) * sizeof(PUNICODE_STRING));
+ if (!ServicePath) KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 2, 1, 0, 0);
+
+ /* Loop the driver list */
+ for (i = 0, NextEntry = DriverList.Flink;
+ NextEntry != &DriverList;
+ i++, NextEntry = NextEntry->Flink)
+ {
+ /* Get the entry */
+ DriverEntry = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_LIST_ENTRY, Link);
+
+ /* Allocate the path for the caller and duplicate the registry path */
+ ServicePath[i] = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING));
+ RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+ &DriverEntry->RegistryPath,
+ ServicePath[i]);
+ }
+
+ /* Terminate the list */
+ ServicePath[i] = NULL;
+
+EndPath:
+ /* Free the driver list if we had one */
+ if (!IsListEmpty(&DriverList)) CmpFreeDriverList(Hive, &DriverList);
+
+ /* Unlock the registry */
+ CmpUnlockRegistry();
+
+ /* Close the key handle and dereference the object, then return the path */
+ ObDereferenceObject(KeyBody);
+ NtClose(KeyHandle);
+ return ServicePath;
+}
+
VOID
NTAPI
CmpLockRegistryExclusive(VOID)
/* Enter a critical region and lock the registry */
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
-
+
/* Sanity check */
ASSERT(CmpFlushStarveWriters == 0);
RtlGetCallersAddress(&CmpRegistryLockCaller, &CmpRegistryLockCallerCaller);
{
/* Enter a critical region */
KeEnterCriticalRegion();
-
+
/* Check if we have to starve writers */
if (CmpFlushStarveWriters)
{
return !ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock) ? FALSE : TRUE;
}
+VOID
+NTAPI
+CmpLockHiveFlusherExclusive(IN PCMHIVE Hive)
+{
+ /* Lock the flusher. We should already be in a critical section */
+ CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(Hive);
+ ASSERT((ExIsResourceAcquiredShared(Hive->FlusherLock) == 0) &&
+ (ExIsResourceAcquiredExclusiveLite(Hive->FlusherLock) == 0));
+ ExAcquireResourceExclusiveLite(Hive->FlusherLock, TRUE);
+}
+
+VOID
+NTAPI
+CmpLockHiveFlusherShared(IN PCMHIVE Hive)
+{
+ /* Lock the flusher. We should already be in a critical section */
+ CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(Hive);
+ ASSERT((ExIsResourceAcquiredShared(Hive->FlusherLock) == 0) &&
+ (ExIsResourceAcquiredExclusiveLite(Hive->FlusherLock) == 0));
+ ExAcquireResourceSharedLite(Hive->FlusherLock, TRUE);
+}
+
+VOID
+NTAPI
+CmpUnlockHiveFlusher(IN PCMHIVE Hive)
+{
+ /* Sanity check */
+ CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(Hive);
+ CMP_ASSERT_FLUSH_LOCK(Hive);
+
+ /* Release the lock */
+ ExReleaseResourceLite(Hive->FlusherLock);
+}
+
+BOOLEAN
+NTAPI
+CmpTestHiveFlusherLockShared(IN PCMHIVE Hive)
+{
+ /* Test the lock */
+ return !ExIsResourceAcquiredSharedLite(Hive->FlusherLock) ? FALSE : TRUE;
+}
+
+BOOLEAN
+NTAPI
+CmpTestHiveFlusherLockExclusive(IN PCMHIVE Hive)
+{
+ /* Test the lock */
+ return !ExIsResourceAcquiredExclusiveLite(Hive->FlusherLock) ? FALSE : TRUE;
+}
+
VOID
NTAPI
CmpUnlockRegistry(VOID)
{
/* Sanity check */
CMP_ASSERT_REGISTRY_LOCK();
-
+
/* Check if we should flush the registry */
if (CmpFlushOnLockRelease)
{
/* The registry should be exclusively locked for this */
CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK();
-
+
/* Flush the registry */
CmpDoFlushAll(TRUE);
CmpFlushOnLockRelease = FALSE;
}
-
+ else
+ {
+ /* Lazy flush the registry */
+ CmpLazyFlush();
+ }
+
/* Release the lock and leave the critical region */
ExReleaseResourceLite(&CmpRegistryLock);
KeLeaveCriticalRegion();
IN ULONG ConvKey2)
{
ULONG Index1, Index2;
-
+
/* Sanity check */
CMP_ASSERT_REGISTRY_LOCK();
{
/* Grab the second one first, then the first */
CmpAcquireKcbLockExclusiveByKey(ConvKey2);
- if (Index1 != Index2) CmpAcquireKcbLockExclusiveByKey(ConvKey1);
+ if (Index1 != Index2) CmpAcquireKcbLockExclusiveByKey(ConvKey1);
}
}
IN ULONG ConvKey2)
{
ULONG Index1, Index2;
-
+
/* Sanity check */
CMP_ASSERT_REGISTRY_LOCK();
-
+
/* Get hash indexes */
Index1 = GET_HASH_INDEX(ConvKey1);
Index2 = GET_HASH_INDEX(ConvKey2);
ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey2).Owner == KeGetCurrentThread()) ||
(CmpTestRegistryLockExclusive()));
-
+
/* See which one is highest */
if (Index1 < Index2)
{
NTAPI
CmShutdownSystem(VOID)
{
- /* Kill the workers and flush all hives */
+ /* Kill the workers */
if (!CmFirstTime) CmpShutdownWorkers();
+
+ /* Flush all hives */
+ CmpLockRegistryExclusive();
CmpDoFlushAll(TRUE);
+ CmpUnlockRegistry();
}
+
+VOID
+NTAPI
+CmpSetVersionData(VOID)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ UNICODE_STRING ValueName;
+ UNICODE_STRING ValueData;
+ HANDLE SoftwareKeyHandle = NULL;
+ HANDLE MicrosoftKeyHandle = NULL;
+ HANDLE WindowsNtKeyHandle = NULL;
+ HANDLE CurrentVersionKeyHandle = NULL;
+ WCHAR Buffer[128];
+ NTSTATUS Status;
+
+ /* Open the 'CurrentVersion' key */
+ RtlInitUnicodeString(&KeyName,
+ L"\\REGISTRY\\MACHINE\\SOFTWARE");
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtCreateKey(&SoftwareKeyHandle,
+ KEY_CREATE_SUB_KEY,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ 0,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
+ return;
+ }
+
+ /* Open the 'CurrentVersion' key */
+ RtlInitUnicodeString(&KeyName,
+ L"Microsoft");
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ SoftwareKeyHandle,
+ NULL);
+
+ Status = NtCreateKey(&MicrosoftKeyHandle,
+ KEY_CREATE_SUB_KEY,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ 0,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
+ goto done;
+ }
+
+ /* Open the 'CurrentVersion' key */
+ RtlInitUnicodeString(&KeyName,
+ L"Windows NT");
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ MicrosoftKeyHandle,
+ NULL);
+
+ Status = NtCreateKey(&WindowsNtKeyHandle,
+ KEY_CREATE_SUB_KEY,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ 0,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
+ goto done;
+ }
+
+ /* Open the 'CurrentVersion' key */
+ RtlInitUnicodeString(&KeyName,
+ L"CurrentVersion");
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ WindowsNtKeyHandle,
+ NULL);
+
+ Status = NtCreateKey(&CurrentVersionKeyHandle,
+ KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ 0,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
+ goto done;
+ }
+
+ /* Set the 'CurrentType' value */
+ RtlInitUnicodeString(&ValueName,
+ L"CurrentType");
+
+#ifdef CONFIG_SMP
+ wcscpy(Buffer, L"Multiprocessor");
+#else
+ wcscpy(Buffer, L"Uniprocessor");
+#endif
+
+ wcscat(Buffer, L" ");
+
+#if (DBG == 1)
+ wcscat(Buffer, L"Checked");
+#else
+ wcscat(Buffer, L"Free");
+#endif
+
+ RtlInitUnicodeString(&ValueData,
+ Buffer);
+
+ NtSetValueKey(CurrentVersionKeyHandle,
+ &ValueName,
+ 0,
+ REG_SZ,
+ ValueData.Buffer,
+ ValueData.Length + sizeof(WCHAR));
+
+done:;
+ /* Close the keys */
+ if (CurrentVersionKeyHandle != NULL)
+ NtClose(CurrentVersionKeyHandle);
+
+ if (WindowsNtKeyHandle != NULL)
+ NtClose(WindowsNtKeyHandle);
+
+ if (MicrosoftKeyHandle != NULL)
+ NtClose(MicrosoftKeyHandle);
+
+ if (SoftwareKeyHandle != NULL)
+ NtClose(SoftwareKeyHandle);
+}
+
+/* EOF */