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