Prettify usetup a bit, show a warranty page before continuing installation (not a...
[reactos.git] / reactos / ntoskrnl / ex / init.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/init.c
5 * PURPOSE: Executive initalization
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
8 * and optimized/cleaned it.
9 * Eric Kohl (ekohl@abo.rhein-zeitung.de)
10 */
11
12 #include <ntoskrnl.h>
13 #include <ntos/bootvid.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* DATA **********************************************************************/
18
19 extern ULONG MmCoreDumpType;
20 extern CHAR KiTimerSystemAuditing;
21 extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
22 extern ADDRESS_RANGE KeMemoryMap[64];
23 extern ULONG KeMemoryMapRangeCount;
24 extern ULONG_PTR FirstKrnlPhysAddr;
25 extern ULONG_PTR LastKrnlPhysAddr;
26 extern ULONG_PTR LastKernelAddress;
27 extern LOADER_MODULE KeLoaderModules[64];
28 extern PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
29 extern LIST_ENTRY KiProfileListHead;
30 extern LIST_ENTRY KiProfileSourceListHead;
31 extern KSPIN_LOCK KiProfileLock;
32 BOOLEAN SetupMode = TRUE;
33
34 VOID PspPostInitSystemProcess(VOID);
35
36 /* FUNCTIONS ****************************************************************/
37
38 static
39 VOID
40 INIT_FUNCTION
41 InitSystemSharedUserPage (PCSZ ParameterLine)
42 {
43 UNICODE_STRING ArcDeviceName;
44 UNICODE_STRING ArcName;
45 UNICODE_STRING BootPath;
46 UNICODE_STRING DriveDeviceName;
47 UNICODE_STRING DriveName;
48 WCHAR DriveNameBuffer[20];
49 PCHAR ParamBuffer;
50 PWCHAR ArcNameBuffer;
51 PCHAR p;
52 NTSTATUS Status;
53 ULONG Length;
54 OBJECT_ATTRIBUTES ObjectAttributes;
55 HANDLE Handle;
56 ULONG i;
57 BOOLEAN BootDriveFound = FALSE;
58
59 /*
60 * NOTE:
61 * The shared user page has been zeroed-out right after creation.
62 * There is NO need to do this again.
63 */
64 Ki386SetProcessorFeatures();
65
66 /* Set the Version Data */
67 SharedUserData->NtProductType = NtProductWinNt;
68 SharedUserData->ProductTypeIsValid = TRUE;
69 SharedUserData->NtMajorVersion = 5;
70 SharedUserData->NtMinorVersion = 0;
71
72 /*
73 * Retrieve the current dos system path
74 * (e.g.: C:\reactos) from the given arc path
75 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
76 * Format: "<arc_name>\<path> [options...]"
77 */
78
79 /* Create local parameter line copy */
80 ParamBuffer = ExAllocatePool(PagedPool, 256);
81 strcpy (ParamBuffer, (char *)ParameterLine);
82 DPRINT("%s\n", ParamBuffer);
83
84 /* Cut options off */
85 p = strchr (ParamBuffer, ' ');
86 if (p) *p = 0;
87 DPRINT("%s\n", ParamBuffer);
88
89 /* Extract path */
90 p = strchr (ParamBuffer, '\\');
91 if (p) {
92
93 DPRINT("Boot path: %s\n", p);
94 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
95 *p = 0;
96
97 } else {
98
99 DPRINT("Boot path: %s\n", "\\");
100 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
101 }
102 DPRINT("Arc name: %s\n", ParamBuffer);
103
104 /* Only ARC Name left - Build full ARC Name */
105 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
106 swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
107 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
108 DPRINT("Arc name: %wZ\n", &ArcName);
109
110 /* Free ParamBuffer */
111 ExFreePool (ParamBuffer);
112
113 /* Allocate ARC Device Name string */
114 ArcDeviceName.Length = 0;
115 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
116 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
117
118 /* Open the Symbolic Link */
119 InitializeObjectAttributes(&ObjectAttributes,
120 &ArcName,
121 OBJ_OPENLINK,
122 NULL,
123 NULL);
124 Status = NtOpenSymbolicLinkObject(&Handle,
125 SYMBOLIC_LINK_ALL_ACCESS,
126 &ObjectAttributes);
127
128 /* Free the String */
129 ExFreePool(ArcName.Buffer);
130
131 /* Check for Success */
132 if (!NT_SUCCESS(Status)) {
133
134 /* Free the Strings */
135 RtlFreeUnicodeString(&BootPath);
136 ExFreePool(ArcDeviceName.Buffer);
137 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", Status);
138 KEBUGCHECK(0);
139 }
140
141 /* Query the Link */
142 Status = NtQuerySymbolicLinkObject(Handle,
143 &ArcDeviceName,
144 &Length);
145 NtClose (Handle);
146
147 /* Check for Success */
148 if (!NT_SUCCESS(Status)) {
149
150 /* Free the Strings */
151 RtlFreeUnicodeString(&BootPath);
152 ExFreePool(ArcDeviceName.Buffer);
153 CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
154 KEBUGCHECK(0);
155 }
156 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
157
158 /* Allocate Device Name string */
159 DriveDeviceName.Length = 0;
160 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
161 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
162
163 /* Loop Drives */
164 for (i = 0; i < 26; i++) {
165
166 /* Setup the String */
167 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
168 RtlInitUnicodeString(&DriveName,
169 DriveNameBuffer);
170
171 /* Open the Symbolic Link */
172 InitializeObjectAttributes(&ObjectAttributes,
173 &DriveName,
174 OBJ_OPENLINK,
175 NULL,
176 NULL);
177 Status = NtOpenSymbolicLinkObject(&Handle,
178 SYMBOLIC_LINK_ALL_ACCESS,
179 &ObjectAttributes);
180
181 /* If it failed, skip to the next drive */
182 if (!NT_SUCCESS(Status)) {
183 DPRINT("Failed to open link %wZ\n", &DriveName);
184 continue;
185 }
186
187 /* Query it */
188 Status = NtQuerySymbolicLinkObject(Handle,
189 &DriveDeviceName,
190 &Length);
191
192 /* If it failed, skip to the next drive */
193 if (!NT_SUCCESS(Status)) {
194 DPRINT("Failed to query link %wZ\n", &DriveName);
195 continue;
196 }
197 DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
198
199 /* See if we've found the boot drive */
200 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
201
202 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
203 swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
204 BootDriveFound = TRUE;
205 }
206
207 /* Close this Link */
208 NtClose (Handle);
209 }
210
211 /* Free all the Strings we have in memory */
212 RtlFreeUnicodeString (&BootPath);
213 ExFreePool(DriveDeviceName.Buffer);
214 ExFreePool(ArcDeviceName.Buffer);
215
216 /* Make sure we found the Boot Drive */
217 if (BootDriveFound == FALSE) {
218
219 DbgPrint("No system drive found!\n");
220 KEBUGCHECK (NO_BOOT_DEVICE);
221 }
222 }
223
224 inline
225 VOID
226 STDCALL
227 ExecuteRuntimeAsserts(VOID)
228 {
229 /*
230 * Fail at runtime if someone has changed various structures without
231 * updating the offsets used for the assembler code.
232 */
233 ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
234 ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
235 ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
236 ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
237 ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
238 ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
239 ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
240 ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
241 ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
242 ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
243 ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
244 ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
245 ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
246 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
247 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
248 ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
249 ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
250 ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
251 ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
252 ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
253 ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
254 ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
255 ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
256 ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
257 }
258
259 inline
260 VOID
261 STDCALL
262 ParseAndCacheLoadedModules(VOID)
263 {
264 ULONG i;
265 PCHAR Name;
266
267 /* Loop the Module List and get the modules we want */
268 for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
269
270 /* Get the Name of this Module */
271 if (!(Name = strrchr((PCHAR)KeLoaderModules[i].String, '\\'))) {
272
273 /* Save the name */
274 Name = (PCHAR)KeLoaderModules[i].String;
275
276 } else {
277
278 /* No name, skip */
279 Name++;
280 }
281
282 /* Now check for any of the modules we will need later */
283 if (!_stricmp(Name, "ansi.nls")) {
284
285 CachedModules[AnsiCodepage] = &KeLoaderModules[i];
286
287 } else if (!_stricmp(Name, "oem.nls")) {
288
289 CachedModules[OemCodepage] = &KeLoaderModules[i];
290
291 } else if (!_stricmp(Name, "casemap.nls")) {
292
293 CachedModules[UnicodeCasemap] = &KeLoaderModules[i];
294
295 } else if (!_stricmp(Name, "system") || !_stricmp(Name, "system.hiv")) {
296
297 CachedModules[SystemRegistry] = &KeLoaderModules[i];
298 SetupMode = FALSE;
299
300 } else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv")) {
301
302 CachedModules[HardwareRegistry] = &KeLoaderModules[i];
303 }
304 }
305 }
306
307 inline
308 VOID
309 STDCALL
310 ParseCommandLine(PULONG MaxMem,
311 PBOOLEAN NoGuiBoot,
312 PBOOLEAN BootLog,
313 PBOOLEAN ForceAcpiDisable)
314 {
315 PCHAR p1, p2;
316
317 p1 = (PCHAR)KeLoaderBlock.CommandLine;
318 while(*p1 && (p2 = strchr(p1, '/'))) {
319
320 p2++;
321 if (!_strnicmp(p2, "MAXMEM", 6)) {
322
323 p2 += 6;
324 while (isspace(*p2)) p2++;
325
326 if (*p2 == '=') {
327
328 p2++;
329
330 while(isspace(*p2)) p2++;
331
332 if (isdigit(*p2)) {
333 while (isdigit(*p2)) {
334 *MaxMem = *MaxMem * 10 + *p2 - '0';
335 p2++;
336 }
337 break;
338 }
339 }
340 } else if (!_strnicmp(p2, "NOGUIBOOT", 9)) {
341
342 p2 += 9;
343 *NoGuiBoot = TRUE;
344
345 } else if (!_strnicmp(p2, "CRASHDUMP", 9)) {
346
347 p2 += 9;
348 if (*p2 == ':') {
349
350 p2++;
351 if (!_strnicmp(p2, "FULL", 4)) {
352
353 MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
354
355 } else {
356
357 MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
358 }
359 }
360 } else if (!_strnicmp(p2, "BOOTLOG", 7)) {
361
362 p2 += 7;
363 *BootLog = TRUE;
364 } else if (!_strnicmp(p2, "NOACPI", 6)) {
365
366 p2 += 6;
367 *ForceAcpiDisable = TRUE;
368 }
369
370 p1 = p2;
371 }
372 }
373
374 VOID
375 INIT_FUNCTION
376 ExpDisplayNotice(VOID)
377 {
378 CHAR str[50];
379
380 if (SetupMode)
381 {
382 HalDisplayString(
383 "\n\n\n ReactOS " KERNEL_VERSION_STR " Setup \n");
384 HalDisplayString(
385 " \xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD");
386 HalDisplayString(
387 "\xCD\xCD\n");
388 return;
389 }
390
391 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
392 KERNEL_VERSION_BUILD_STR")\n");
393 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
394 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
395 "Public License, and you\n");
396 HalDisplayString("are welcome to change it and/or distribute copies of it "
397 "under certain\n");
398 HalDisplayString("conditions. There is absolutely no warranty for "
399 "ReactOS.\n\n");
400
401 /* Display number of Processors */
402 sprintf(str,
403 "Found %x system processor(s). [%lu MB Memory]\n",
404 (int)KeNumberProcessors,
405 (KeLoaderBlock.MemHigher + 1088)/ 1024);
406 HalDisplayString(str);
407
408 }
409
410 VOID
411 INIT_FUNCTION
412 STDCALL
413 ExpInitializeExecutive(VOID)
414 {
415 UNICODE_STRING EventName;
416 HANDLE InitDoneEventHandle;
417 OBJECT_ATTRIBUTES ObjectAttributes;
418 BOOLEAN NoGuiBoot = FALSE;
419 BOOLEAN BootLog = FALSE;
420 ULONG MaxMem = 0;
421 BOOLEAN ForceAcpiDisable = FALSE;
422 LARGE_INTEGER Timeout;
423 HANDLE ProcessHandle;
424 HANDLE ThreadHandle;
425 NTSTATUS Status;
426
427 /* Check if the structures match the ASM offset constants */
428 ExecuteRuntimeAsserts();
429
430 /* Sets up the Text Sections of the Kernel and HAL for debugging */
431 LdrInit1();
432
433 /* Lower the IRQL to Dispatch Level */
434 KeLowerIrql(DISPATCH_LEVEL);
435
436 /* Sets up the VDM Data */
437 NtEarlyInitVdm();
438
439 /* Parse Command Line Settings */
440 ParseCommandLine(&MaxMem, &NoGuiBoot, &BootLog, &ForceAcpiDisable);
441
442 /* Initialize Kernel Memory Address Space */
443 MmInit1(FirstKrnlPhysAddr,
444 LastKrnlPhysAddr,
445 LastKernelAddress,
446 (PADDRESS_RANGE)&KeMemoryMap,
447 KeMemoryMapRangeCount,
448 MaxMem > 8 ? MaxMem : 4096);
449
450 /* Parse the Loaded Modules (by FreeLoader) and cache the ones we'll need */
451 ParseAndCacheLoadedModules();
452
453 /* Initialize the kernel debugger parameters */
454 KdInitSystem(0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
455
456 /* Initialize the Dispatcher, Clock and Bug Check Mechanisms. */
457 KeInit2();
458
459 /* Bring back the IRQL to Passive */
460 KeLowerIrql(PASSIVE_LEVEL);
461
462 /* Initialize Profiling */
463 InitializeListHead(&KiProfileListHead);
464 InitializeListHead(&KiProfileSourceListHead);
465 KeInitializeSpinLock(&KiProfileLock);
466
467 /* Load basic Security for other Managers */
468 if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
469
470 /* Create the Basic Object Manager Types to allow new Object Types */
471 ObInit();
472
473 /* Initialize Lookaside Lists */
474 ExInit2();
475
476 /* Set up Region Maps, Sections and the Paging File */
477 MmInit2();
478
479 /* Initialize Tokens now that the Object Manager is ready */
480 if (!SeInit2()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
481
482 /* Set 1 CPU for now, we'll increment this later */
483 KeNumberProcessors = 1;
484
485 /* Initalize the Process Manager */
486 PiInitProcessManager();
487
488 /* Break into the Debugger if requested */
489 if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
490
491 /* Initialize all processors */
492 while (!HalAllProcessorsStarted()) {
493
494 PVOID ProcessorStack;
495
496 /* Set up the Kernel and Process Manager for this CPU */
497 KePrepareForApplicationProcessorInit(KeNumberProcessors);
498 KeCreateApplicationProcessorIdleThread(KeNumberProcessors);
499
500 /* Allocate a stack for use when booting the processor */
501 ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE;
502
503 /* Tell HAL a new CPU is being started */
504 HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
505 KeNumberProcessors++;
506 }
507
508 /* Do Phase 1 HAL Initalization */
509 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
510
511 /* Initialize Basic System Objects and Worker Threads */
512 ExInit3();
513
514 /* Create the system handle table, assign it to the system process, create
515 the client id table and assign a PID for the system process. This needs
516 to be done before the worker threads are initialized so the system
517 process gets the first PID (4) */
518 PspPostInitSystemProcess();
519
520 /* initialize the worker threads */
521 ExpInitializeWorkerThreads();
522
523 /* initialize callbacks */
524 ExpInitializeCallbacks();
525
526 /* Call KD Providers at Phase 1 */
527 KdInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
528
529 /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
530 IoInit();
531
532 /* TBD */
533 PoInit((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock, ForceAcpiDisable);
534
535 /* Initialize the Registry (Hives are NOT yet loaded!) */
536 CmInitializeRegistry();
537
538 /* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
539 MmInit3();
540
541 /* Initialize Cache Views */
542 CcInit();
543
544 /* Initialize File Locking */
545 FsRtlpInitFileLockingImplementation();
546
547 /* Report all resources used by hal */
548 HalReportResourceUsage();
549
550 /* Clear the screen to blue */
551 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
552
553 /* Display version number and copyright/warranty message */
554 ExpDisplayNotice();
555
556 /* Call KD Providers at Phase 2 */
557 KdInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
558
559 /* Import and create NLS Data and Sections */
560 RtlpInitNls();
561
562 /* Import and Load Registry Hives */
563 CmInitHives(SetupMode);
564
565 /* Initialize the time zone information from the registry */
566 ExpInitTimeZoneInfo();
567
568 /* Enter the kernel debugger before starting up the boot drivers */
569 if (KdDebuggerEnabled) KdbEnter();
570
571 /* Setup Drivers and Root Device Node */
572 IoInit2(BootLog);
573
574 /* Display the boot screen image if not disabled */
575 if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
576
577 /* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
578 IoInit3();
579
580 /* Load the System DLL and its Entrypoints */
581 LdrpInitializeSystemDll();
582
583 /* Initialize the Default Locale */
584 PiInitDefaultLocale();
585
586 /* Initialize shared user page. Set dos system path, dos device map, etc. */
587 InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
588
589 /* Create 'ReactOSInitDone' event */
590 RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
591 InitializeObjectAttributes(&ObjectAttributes,
592 &EventName,
593 0,
594 NULL,
595 NULL);
596 Status = ZwCreateEvent(&InitDoneEventHandle,
597 EVENT_ALL_ACCESS,
598 &ObjectAttributes,
599 SynchronizationEvent,
600 FALSE);
601
602 /* Check for Success */
603 if (!NT_SUCCESS(Status)) {
604
605 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
606 InitDoneEventHandle = INVALID_HANDLE_VALUE;
607 }
608
609 /* Launch initial process */
610 Status = LdrLoadInitialProcess(&ProcessHandle,
611 &ThreadHandle);
612
613 /* Check for success, Bugcheck if we failed */
614 if (!NT_SUCCESS(Status)) {
615
616 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
617 }
618
619 /* Wait on the Completion Event */
620 if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
621
622 HANDLE Handles[2]; /* Init event, Initial process */
623
624 /* Setup the Handles to wait on */
625 Handles[0] = InitDoneEventHandle;
626 Handles[1] = ProcessHandle;
627
628 /* Wait for the system to be initialized */
629 Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
630 Status = ZwWaitForMultipleObjects(2,
631 Handles,
632 WaitAny,
633 FALSE,
634 &Timeout);
635 if (!NT_SUCCESS(Status)) {
636
637 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
638
639 } else if (Status == STATUS_TIMEOUT) {
640
641 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
642
643 } else if (Status == STATUS_WAIT_0 + 1) {
644
645 /* Crash the system if the initial process was terminated. */
646 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
647 }
648
649 /* Disable the Boot Logo */
650 if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
651
652 /* Signal the Event and close the handle */
653 ZwSetEvent(InitDoneEventHandle, NULL);
654 ZwClose(InitDoneEventHandle);
655
656 } else {
657
658 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
659 if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
660
661 /* Crash the system if the initial process terminates within 5 seconds. */
662 Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
663 Status = ZwWaitForSingleObject(ProcessHandle,
664 FALSE,
665 &Timeout);
666
667 /* Check for timeout, crash if the initial process didn't initalize */
668 if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
669 }
670
671 /* Enable the Clock, close remaining handles */
672 KiTimerSystemAuditing = 1;
673 ZwClose(ThreadHandle);
674 ZwClose(ProcessHandle);
675 }
676
677 VOID INIT_FUNCTION
678 ExInit2(VOID)
679 {
680 ExpInitLookasideLists();
681 }
682
683 VOID INIT_FUNCTION
684 ExInit3 (VOID)
685 {
686 ExpInitializeEventImplementation();
687 ExpInitializeEventPairImplementation();
688 ExpInitializeMutantImplementation();
689 ExpInitializeSemaphoreImplementation();
690 ExpInitializeTimerImplementation();
691 LpcpInitSystem();
692 ExpInitializeProfileImplementation();
693 ExpWin32kInit();
694 ExpInitUuids();
695 ExpInitializeHandleTables();
696 }
697
698 /* EOF */