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