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