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