reactos/reactos/ntoskrnl/ex/init.c
Thomas Bluemel 656411d9b8 - support for kernel handles
- attach to owning process before accessing the handle table if necessary

svn path=/trunk/; revision=20038
2005-12-10 16:38:04 +00:00

775 lines
24 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/init.c
* PURPOSE: Executive initalization
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
* and optimized/cleaned it.
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
*/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* DATA **********************************************************************/
extern ULONG MmCoreDumpType;
extern CHAR KiTimerSystemAuditing;
extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
extern ADDRESS_RANGE KeMemoryMap[64];
extern ULONG KeMemoryMapRangeCount;
extern ULONG_PTR FirstKrnlPhysAddr;
extern ULONG_PTR LastKrnlPhysAddr;
extern ULONG_PTR LastKernelAddress;
extern LOADER_MODULE KeLoaderModules[64];
extern PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
extern LIST_ENTRY KiProfileListHead;
extern LIST_ENTRY KiProfileSourceListHead;
extern KSPIN_LOCK KiProfileLock;
BOOLEAN SetupMode = TRUE;
VOID PspPostInitSystemProcess(VOID);
static VOID INIT_FUNCTION InitSystemSharedUserPage (PCSZ ParameterLine);
VOID INIT_FUNCTION ExpDisplayNotice(VOID);
INIT_FUNCTION NTSTATUS ExpLoadInitialProcess(PHANDLE ProcessHandle, PHANDLE ThreadHandle);
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, InitSystemSharedUserPage)
#pragma alloc_text(INIT, ExpDisplayNotice)
#pragma alloc_text(INIT, ExpLoadInitialProcess)
#pragma alloc_text(INIT, ExpInitializeExecutive)
#pragma alloc_text(INIT, ExInit2)
#endif
/* FUNCTIONS ****************************************************************/
static
VOID
INIT_FUNCTION
InitSystemSharedUserPage (PCSZ ParameterLine)
{
UNICODE_STRING ArcDeviceName;
UNICODE_STRING ArcName;
UNICODE_STRING BootPath;
UNICODE_STRING DriveDeviceName;
UNICODE_STRING DriveName;
WCHAR DriveNameBuffer[20];
PCHAR ParamBuffer;
PWCHAR ArcNameBuffer;
PCHAR p;
NTSTATUS Status;
ULONG Length;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE Handle;
ULONG i;
BOOLEAN BootDriveFound = FALSE;
/*
* NOTE:
* The shared user page has been zeroed-out right after creation.
* There is NO need to do this again.
*/
Ki386SetProcessorFeatures();
/* Set the Version Data */
SharedUserData->NtProductType = NtProductWinNt;
SharedUserData->ProductTypeIsValid = TRUE;
SharedUserData->NtMajorVersion = 5;
SharedUserData->NtMinorVersion = 0;
/*
* Retrieve the current dos system path
* (e.g.: C:\reactos) from the given arc path
* (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
* Format: "<arc_name>\<path> [options...]"
*/
/* Create local parameter line copy */
ParamBuffer = ExAllocatePool(PagedPool, 256);
strcpy (ParamBuffer, (const char *)ParameterLine);
DPRINT("%s\n", ParamBuffer);
/* Cut options off */
p = strchr (ParamBuffer, ' ');
if (p) *p = 0;
DPRINT("%s\n", ParamBuffer);
/* Extract path */
p = strchr (ParamBuffer, '\\');
if (p) {
DPRINT("Boot path: %s\n", p);
RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
*p = 0;
} else {
DPRINT("Boot path: %s\n", "\\");
RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
}
DPRINT("Arc name: %s\n", ParamBuffer);
/* Only ARC Name left - Build full ARC Name */
ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
RtlInitUnicodeString (&ArcName, ArcNameBuffer);
DPRINT("Arc name: %wZ\n", &ArcName);
/* Free ParamBuffer */
ExFreePool (ParamBuffer);
/* Allocate ARC Device Name string */
ArcDeviceName.Length = 0;
ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
/* Open the Symbolic Link */
InitializeObjectAttributes(&ObjectAttributes,
&ArcName,
OBJ_OPENLINK,
NULL,
NULL);
Status = NtOpenSymbolicLinkObject(&Handle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes);
/* Free the String */
ExFreePool(ArcName.Buffer);
/* Check for Success */
if (!NT_SUCCESS(Status)) {
/* Free the Strings */
RtlFreeUnicodeString(&BootPath);
ExFreePool(ArcDeviceName.Buffer);
CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", Status);
KEBUGCHECK(0);
}
/* Query the Link */
Status = NtQuerySymbolicLinkObject(Handle,
&ArcDeviceName,
&Length);
NtClose (Handle);
/* Check for Success */
if (!NT_SUCCESS(Status)) {
/* Free the Strings */
RtlFreeUnicodeString(&BootPath);
ExFreePool(ArcDeviceName.Buffer);
CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
KEBUGCHECK(0);
}
DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
/* Allocate Device Name string */
DriveDeviceName.Length = 0;
DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
/* Loop Drives */
for (i = 0; i < 26; i++) {
/* Setup the String */
swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
RtlInitUnicodeString(&DriveName,
DriveNameBuffer);
/* Open the Symbolic Link */
InitializeObjectAttributes(&ObjectAttributes,
&DriveName,
OBJ_OPENLINK,
NULL,
NULL);
Status = NtOpenSymbolicLinkObject(&Handle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes);
/* If it failed, skip to the next drive */
if (!NT_SUCCESS(Status)) {
DPRINT("Failed to open link %wZ\n", &DriveName);
continue;
}
/* Query it */
Status = NtQuerySymbolicLinkObject(Handle,
&DriveDeviceName,
&Length);
/* If it failed, skip to the next drive */
if (!NT_SUCCESS(Status)) {
DPRINT("Failed to query link %wZ\n", &DriveName);
continue;
}
DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
/* See if we've found the boot drive */
if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
BootDriveFound = TRUE;
}
/* Close this Link */
NtClose (Handle);
}
/* Free all the Strings we have in memory */
RtlFreeUnicodeString (&BootPath);
ExFreePool(DriveDeviceName.Buffer);
ExFreePool(ArcDeviceName.Buffer);
/* Make sure we found the Boot Drive */
if (BootDriveFound == FALSE) {
DbgPrint("No system drive found!\n");
KEBUGCHECK (NO_BOOT_DEVICE);
}
}
__inline
VOID
STDCALL
ExecuteRuntimeAsserts(VOID)
{
/*
* Fail at runtime if someone has changed various structures without
* updating the offsets used for the assembler code.
*/
ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCall) == 0x300);
ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
}
__inline
VOID
STDCALL
ParseAndCacheLoadedModules(VOID)
{
ULONG i;
PCHAR Name;
/* Loop the Module List and get the modules we want */
for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
/* Get the Name of this Module */
if (!(Name = strrchr((PCHAR)KeLoaderModules[i].String, '\\'))) {
/* Save the name */
Name = (PCHAR)KeLoaderModules[i].String;
} else {
/* No name, skip */
Name++;
}
/* Now check for any of the modules we will need later */
if (!_stricmp(Name, "ansi.nls")) {
CachedModules[AnsiCodepage] = &KeLoaderModules[i];
} else if (!_stricmp(Name, "oem.nls")) {
CachedModules[OemCodepage] = &KeLoaderModules[i];
} else if (!_stricmp(Name, "casemap.nls")) {
CachedModules[UnicodeCasemap] = &KeLoaderModules[i];
} else if (!_stricmp(Name, "system") || !_stricmp(Name, "system.hiv")) {
CachedModules[SystemRegistry] = &KeLoaderModules[i];
SetupMode = FALSE;
} else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv")) {
CachedModules[HardwareRegistry] = &KeLoaderModules[i];
}
}
}
__inline
VOID
STDCALL
ParseCommandLine(PULONG MaxMem,
PBOOLEAN NoGuiBoot,
PBOOLEAN BootLog,
PBOOLEAN ForceAcpiDisable)
{
PCHAR p1, p2;
p1 = (PCHAR)KeLoaderBlock.CommandLine;
while(*p1 && (p2 = strchr(p1, '/'))) {
p2++;
if (!_strnicmp(p2, "MAXMEM", 6)) {
p2 += 6;
while (isspace(*p2)) p2++;
if (*p2 == '=') {
p2++;
while(isspace(*p2)) p2++;
if (isdigit(*p2)) {
while (isdigit(*p2)) {
*MaxMem = *MaxMem * 10 + *p2 - '0';
p2++;
}
break;
}
}
} else if (!_strnicmp(p2, "NOGUIBOOT", 9)) {
p2 += 9;
*NoGuiBoot = TRUE;
} else if (!_strnicmp(p2, "CRASHDUMP", 9)) {
p2 += 9;
if (*p2 == ':') {
p2++;
if (!_strnicmp(p2, "FULL", 4)) {
MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
} else {
MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
}
}
} else if (!_strnicmp(p2, "BOOTLOG", 7)) {
p2 += 7;
*BootLog = TRUE;
} else if (!_strnicmp(p2, "NOACPI", 6)) {
p2 += 6;
*ForceAcpiDisable = TRUE;
}
p1 = p2;
}
}
VOID
INIT_FUNCTION
ExpDisplayNotice(VOID)
{
CHAR str[50];
if (SetupMode)
{
HalDisplayString(
"\n\n\n ReactOS " KERNEL_VERSION_STR " Setup \n");
HalDisplayString(
" \xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD");
HalDisplayString(
"\xCD\xCD\n");
return;
}
HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
KERNEL_VERSION_BUILD_STR")\n");
HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
"Public License, and you\n");
HalDisplayString("are welcome to change it and/or distribute copies of it "
"under certain\n");
HalDisplayString("conditions. There is absolutely no warranty for "
"ReactOS.\n\n");
/* Display number of Processors */
sprintf(str,
"Found %x system processor(s). [%lu MB Memory]\n",
(int)KeNumberProcessors,
(KeLoaderBlock.MemHigher + 1088)/ 1024);
HalDisplayString(str);
}
INIT_FUNCTION
NTSTATUS
ExpLoadInitialProcess(PHANDLE ProcessHandle,
PHANDLE ThreadHandle)
{
UNICODE_STRING ImagePath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\smss.exe");
HANDLE SystemProcessHandle;
NTSTATUS Status;
PRTL_USER_PROCESS_PARAMETERS Params=NULL;
RTL_USER_PROCESS_INFORMATION Info;
/* Create a handle to the process */
Status = ObpCreateHandle(PsInitialSystemProcess,
PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION,
OBJ_KERNEL_HANDLE,
&SystemProcessHandle);
if(!NT_SUCCESS(Status))
{
DPRINT1("Failed to create a handle for the system process!\n");
return Status;
}
/* Create the Parameters */
Status = RtlCreateProcessParameters(&Params,
&ImagePath,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if(!NT_SUCCESS(Status))
{
DPRINT1("Failed to create ppb!\n");
ZwClose(SystemProcessHandle);
return Status;
}
DPRINT("Creating process\n");
Status = RtlCreateUserProcess(&ImagePath,
OBJ_CASE_INSENSITIVE,
Params,
NULL,
NULL,
SystemProcessHandle,
FALSE,
NULL,
NULL,
&Info);
/* Close the handle and free the params */
ZwClose(SystemProcessHandle);
RtlDestroyProcessParameters(Params);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateProcess() failed (Status %lx)\n", Status);
return(Status);
}
/* Start it up */
ZwResumeThread(Info.ThreadHandle, NULL);
/* Return Handles */
*ProcessHandle = Info.ProcessHandle;
*ThreadHandle = Info.ThreadHandle;
DPRINT("Process created successfully\n");
return STATUS_SUCCESS;
}
VOID
INIT_FUNCTION
STDCALL
ExpInitializeExecutive(VOID)
{
UNICODE_STRING EventName;
HANDLE InitDoneEventHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
BOOLEAN NoGuiBoot = FALSE;
BOOLEAN BootLog = FALSE;
ULONG MaxMem = 0;
BOOLEAN ForceAcpiDisable = FALSE;
LARGE_INTEGER Timeout;
HANDLE ProcessHandle;
HANDLE ThreadHandle;
NTSTATUS Status;
/* Check if the structures match the ASM offset constants */
ExecuteRuntimeAsserts();
/* Sets up the Text Sections of the Kernel and HAL for debugging */
LdrInit1();
/* Lower the IRQL to Dispatch Level */
KeLowerIrql(DISPATCH_LEVEL);
/* Sets up the VDM Data */
NtEarlyInitVdm();
/* Parse Command Line Settings */
ParseCommandLine(&MaxMem, &NoGuiBoot, &BootLog, &ForceAcpiDisable);
/* Initialize Kernel Memory Address Space */
MmInit1(FirstKrnlPhysAddr,
LastKrnlPhysAddr,
LastKernelAddress,
(PADDRESS_RANGE)&KeMemoryMap,
KeMemoryMapRangeCount,
MaxMem > 8 ? MaxMem : 4096);
/* Parse the Loaded Modules (by FreeLoader) and cache the ones we'll need */
ParseAndCacheLoadedModules();
/* Initialize the Dispatcher, Clock and Bug Check Mechanisms. */
KeInit2();
/* Bring back the IRQL to Passive */
KeLowerIrql(PASSIVE_LEVEL);
/* Initialize Profiling */
InitializeListHead(&KiProfileListHead);
InitializeListHead(&KiProfileSourceListHead);
KeInitializeSpinLock(&KiProfileLock);
/* Load basic Security for other Managers */
if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
/* Create the Basic Object Manager Types to allow new Object Types */
ObInit();
/* Initialize Lookaside Lists */
ExpInitLookasideLists();
/* Set up Region Maps, Sections and the Paging File */
MmInit2();
/* Initialize Tokens now that the Object Manager is ready */
if (!SeInit2()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
/* Set 1 CPU for now, we'll increment this later */
KeNumberProcessors = 1;
/* Initalize the Process Manager */
PiInitProcessManager();
/* Break into the Debugger if requested */
if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
/* Initialize all processors */
while (!HalAllProcessorsStarted()) {
PVOID ProcessorStack;
/* Set up the Kernel and Process Manager for this CPU */
KePrepareForApplicationProcessorInit(KeNumberProcessors);
KeCreateApplicationProcessorIdleThread(KeNumberProcessors);
/* Allocate a stack for use when booting the processor */
ProcessorStack = RVA(Ki386InitialStackArray[((int)KeNumberProcessors)], MM_STACK_SIZE);
/* Tell HAL a new CPU is being started */
HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
KeNumberProcessors++;
}
/* Do Phase 1 HAL Initalization */
HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
/* Initialize Basic System Objects and Worker Threads */
ExInit2();
/* Create the system handle table, assign it to the system process, create
the client id table and assign a PID for the system process. This needs
to be done before the worker threads are initialized so the system
process gets the first PID (4) */
PspPostInitSystemProcess();
/* initialize the worker threads */
ExpInitializeWorkerThreads();
/* initialize callbacks */
ExpInitializeCallbacks();
/* Call KD Providers at Phase 1 */
KdInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
/* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
IoInit();
/* TBD */
PoInit((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock, ForceAcpiDisable);
/* Initialize the Registry (Hives are NOT yet loaded!) */
CmInitializeRegistry();
/* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
MmInit3();
/* Initialize Cache Views */
CcInit();
/* Initialize File Locking */
FsRtlpInitFileLockingImplementation();
/* Report all resources used by hal */
HalReportResourceUsage();
/* Clear the screen to blue */
HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
/* Display version number and copyright/warranty message */
ExpDisplayNotice();
/* Call KD Providers at Phase 2 */
KdInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
/* Import and create NLS Data and Sections */
RtlpInitNls();
/* Import and Load Registry Hives */
CmInitHives(SetupMode);
/* Initialize the time zone information from the registry */
ExpInitTimeZoneInfo();
/* Enter the kernel debugger before starting up the boot drivers */
if (KdDebuggerEnabled && KdpEarlyBreak)
DbgBreakPoint();
/* Setup Drivers and Root Device Node */
IoInit2(BootLog);
/* Display the boot screen image if not disabled */
if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
/* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
IoInit3();
/* Load the System DLL and its Entrypoints */
PsLocateSystemDll();
/* Initialize the Default Locale */
PiInitDefaultLocale();
/* Initialize shared user page. Set dos system path, dos device map, etc. */
InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
/* Create 'ReactOSInitDone' event */
RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
InitializeObjectAttributes(&ObjectAttributes,
&EventName,
0,
NULL,
NULL);
Status = ZwCreateEvent(&InitDoneEventHandle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
SynchronizationEvent,
FALSE);
/* Check for Success */
if (!NT_SUCCESS(Status)) {
DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
InitDoneEventHandle = INVALID_HANDLE_VALUE;
}
/* Launch initial process */
Status = ExpLoadInitialProcess(&ProcessHandle,
&ThreadHandle);
/* Check for success, Bugcheck if we failed */
if (!NT_SUCCESS(Status)) {
KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
}
/* Wait on the Completion Event */
if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
HANDLE Handles[2]; /* Init event, Initial process */
/* Setup the Handles to wait on */
Handles[0] = InitDoneEventHandle;
Handles[1] = ProcessHandle;
/* Wait for the system to be initialized */
Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
Status = ZwWaitForMultipleObjects(2,
Handles,
WaitAny,
FALSE,
&Timeout);
if (!NT_SUCCESS(Status)) {
DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
} else if (Status == STATUS_TIMEOUT) {
DPRINT1("WARNING: System not initialized after 120 seconds.\n");
} else if (Status == STATUS_WAIT_0 + 1) {
/* Crash the system if the initial process was terminated. */
KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
}
/* Disable the Boot Logo */
if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
/* Signal the Event and close the handle */
ZwSetEvent(InitDoneEventHandle, NULL);
ZwClose(InitDoneEventHandle);
} else {
/* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
/* Crash the system if the initial process terminates within 5 seconds. */
Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
Status = ZwWaitForSingleObject(ProcessHandle,
FALSE,
&Timeout);
/* Check for timeout, crash if the initial process didn't initalize */
if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
}
/* Enable the Clock, close remaining handles */
KiTimerSystemAuditing = 1;
ZwClose(ThreadHandle);
ZwClose(ProcessHandle);
}
VOID
STDCALL
INIT_FUNCTION
ExInit2(VOID)
{
ExpInitializeEventImplementation();
ExpInitializeEventPairImplementation();
ExpInitializeMutantImplementation();
ExpInitializeSemaphoreImplementation();
ExpInitializeTimerImplementation();
LpcpInitSystem();
ExpInitializeProfileImplementation();
ExpWin32kInit();
ExpInitUuids();
ExpInitializeHandleTables();
}
/* EOF */