- Complete and utter reimplementation of V86 Mode for Ke386CallBios. Details below...
[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(KPCR, IRR) == KPCR_IRR);
264 ASSERT(KeGetPcr()->IRR == 0);
265 ASSERT(FIELD_OFFSET(KPCR, IDR) == KPCR_IDR);
266 ASSERT(FIELD_OFFSET(KPCR, Irql) == KPCR_IRQL);
267 ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
268 ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
269 ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
270 ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
271 ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
272 }
273
274 __inline
275 VOID
276 STDCALL
277 ParseAndCacheLoadedModules(VOID)
278 {
279 ULONG i;
280 PCHAR Name;
281
282 /* Loop the Module List and get the modules we want */
283 for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
284
285 /* Get the Name of this Module */
286 if (!(Name = strrchr((PCHAR)KeLoaderModules[i].String, '\\'))) {
287
288 /* Save the name */
289 Name = (PCHAR)KeLoaderModules[i].String;
290
291 } else {
292
293 /* No name, skip */
294 Name++;
295 }
296
297 /* Now check for any of the modules we will need later */
298 if (!_stricmp(Name, "ansi.nls")) {
299
300 CachedModules[AnsiCodepage] = &KeLoaderModules[i];
301
302 } else if (!_stricmp(Name, "oem.nls")) {
303
304 CachedModules[OemCodepage] = &KeLoaderModules[i];
305
306 } else if (!_stricmp(Name, "casemap.nls")) {
307
308 CachedModules[UnicodeCasemap] = &KeLoaderModules[i];
309
310 } else if (!_stricmp(Name, "system") || !_stricmp(Name, "system.hiv")) {
311
312 CachedModules[SystemRegistry] = &KeLoaderModules[i];
313 SetupMode = FALSE;
314
315 } else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv")) {
316
317 CachedModules[HardwareRegistry] = &KeLoaderModules[i];
318 }
319 }
320 }
321
322 __inline
323 VOID
324 STDCALL
325 ParseCommandLine(PULONG MaxMem,
326 PBOOLEAN NoGuiBoot,
327 PBOOLEAN BootLog,
328 PBOOLEAN ForceAcpiDisable)
329 {
330 PCHAR p1, p2;
331
332 p1 = (PCHAR)KeLoaderBlock.CommandLine;
333 while(*p1 && (p2 = strchr(p1, '/'))) {
334
335 p2++;
336 if (!_strnicmp(p2, "MAXMEM", 6)) {
337
338 p2 += 6;
339 while (isspace(*p2)) p2++;
340
341 if (*p2 == '=') {
342
343 p2++;
344
345 while(isspace(*p2)) p2++;
346
347 if (isdigit(*p2)) {
348 while (isdigit(*p2)) {
349 *MaxMem = *MaxMem * 10 + *p2 - '0';
350 p2++;
351 }
352 break;
353 }
354 }
355 } else if (!_strnicmp(p2, "NOGUIBOOT", 9)) {
356
357 p2 += 9;
358 *NoGuiBoot = TRUE;
359
360 } else if (!_strnicmp(p2, "CRASHDUMP", 9)) {
361
362 p2 += 9;
363 if (*p2 == ':') {
364
365 p2++;
366 if (!_strnicmp(p2, "FULL", 4)) {
367
368 MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
369
370 } else {
371
372 MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
373 }
374 }
375 } else if (!_strnicmp(p2, "BOOTLOG", 7)) {
376
377 p2 += 7;
378 *BootLog = TRUE;
379 } else if (!_strnicmp(p2, "NOACPI", 6)) {
380
381 p2 += 6;
382 *ForceAcpiDisable = TRUE;
383 }
384
385 p1 = p2;
386 }
387 }
388
389 VOID
390 INIT_FUNCTION
391 ExpDisplayNotice(VOID)
392 {
393 CHAR str[50];
394
395 if (SetupMode)
396 {
397 HalDisplayString(
398 "\n\n\n ReactOS " KERNEL_VERSION_STR " Setup \n");
399 HalDisplayString(
400 " \xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD");
401 HalDisplayString(
402 "\xCD\xCD\n");
403 return;
404 }
405
406 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
407 KERNEL_VERSION_BUILD_STR")\n");
408 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
409 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
410 "Public License, and you\n");
411 HalDisplayString("are welcome to change it and/or distribute copies of it "
412 "under certain\n");
413 HalDisplayString("conditions. There is absolutely no warranty for "
414 "ReactOS.\n\n");
415
416 /* Display number of Processors */
417 sprintf(str,
418 "Found %x system processor(s). [%lu MB Memory]\n",
419 (int)KeNumberProcessors,
420 (KeLoaderBlock.MemHigher + 1088)/ 1024);
421 HalDisplayString(str);
422
423 }
424
425 INIT_FUNCTION
426 NTSTATUS
427 ExpLoadInitialProcess(PHANDLE ProcessHandle,
428 PHANDLE ThreadHandle)
429 {
430 UNICODE_STRING CurrentDirectory;
431 UNICODE_STRING ImagePath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\smss.exe");
432 NTSTATUS Status;
433 PRTL_USER_PROCESS_PARAMETERS Params=NULL;
434 RTL_USER_PROCESS_INFORMATION Info;
435
436 RtlInitUnicodeString(&CurrentDirectory,
437 SharedUserData->NtSystemRoot);
438
439 /* Create the Parameters */
440 Status = RtlCreateProcessParameters(&Params,
441 &ImagePath,
442 NULL,
443 &CurrentDirectory,
444 NULL,
445 NULL,
446 NULL,
447 NULL,
448 NULL,
449 NULL);
450 if(!NT_SUCCESS(Status))
451 {
452 DPRINT1("Failed to create ppb!\n");
453 return Status;
454 }
455
456 DPRINT("Creating process\n");
457 Status = RtlCreateUserProcess(&ImagePath,
458 OBJ_CASE_INSENSITIVE,
459 Params,
460 NULL,
461 NULL,
462 NULL,
463 FALSE,
464 NULL,
465 NULL,
466 &Info);
467
468 /* Close the handle and free the params */
469 RtlDestroyProcessParameters(Params);
470
471 if (!NT_SUCCESS(Status))
472 {
473 DPRINT1("NtCreateProcess() failed (Status %lx)\n", Status);
474 return(Status);
475 }
476
477 /* Start it up */
478 ZwResumeThread(Info.ThreadHandle, NULL);
479
480 /* Return Handles */
481 *ProcessHandle = Info.ProcessHandle;
482 *ThreadHandle = Info.ThreadHandle;
483 DPRINT("Process created successfully\n");
484 return STATUS_SUCCESS;
485 }
486
487 VOID
488 INIT_FUNCTION
489 STDCALL
490 ExpInitializeExecutive(VOID)
491 {
492 UNICODE_STRING EventName;
493 HANDLE InitDoneEventHandle;
494 OBJECT_ATTRIBUTES ObjectAttributes;
495 BOOLEAN BootLog = FALSE;
496 ULONG MaxMem = 0;
497 BOOLEAN ForceAcpiDisable = FALSE;
498 LARGE_INTEGER Timeout;
499 HANDLE ProcessHandle;
500 HANDLE ThreadHandle;
501 NTSTATUS Status;
502
503 /* Check if the structures match the ASM offset constants */
504 ExecuteRuntimeAsserts();
505
506 /* Set 1 CPU for now, we'll increment this later */
507 KeNumberProcessors = 1;
508
509 /* Sets up the Text Sections of the Kernel and HAL for debugging */
510 LdrInit1();
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 /* Initialize the Dispatcher, Clock and Bug Check Mechanisms. */
533 KeInit2();
534
535 /* Bring back the IRQL to Passive */
536 KeLowerIrql(PASSIVE_LEVEL);
537
538 /* Initialize Profiling */
539 InitializeListHead(&KiProfileListHead);
540 InitializeListHead(&KiProfileSourceListHead);
541 KeInitializeSpinLock(&KiProfileLock);
542
543 /* Initialize resources */
544 ExpResourceInitialization();
545
546 /* Load basic Security for other Managers */
547 if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
548
549 /* Initialize Lookaside Lists */
550 ExpInitLookasideLists();
551
552 /* Create the Basic Object Manager Types to allow new Object Types */
553 ObInit();
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 /* Initalize the Process Manager */
562 PiInitProcessManager();
563
564 /* Break into the Debugger if requested */
565 if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
566
567 /* Initialize all processors */
568 while (!HalAllProcessorsStarted()) {
569
570 PVOID ProcessorStack;
571
572 /* Set up the Kernel and Process Manager for this CPU */
573 KePrepareForApplicationProcessorInit(KeNumberProcessors);
574 KeCreateApplicationProcessorIdleThread(KeNumberProcessors);
575
576 /* Allocate a stack for use when booting the processor */
577 ProcessorStack = RVA(Ki386InitialStackArray[((int)KeNumberProcessors)], KERNEL_STACK_SIZE);
578
579 /* Tell HAL a new CPU is being started */
580 HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
581 KeNumberProcessors++;
582 }
583
584 /* Do Phase 1 HAL Initalization */
585 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
586
587 /* Initialize Basic System Objects and Worker Threads */
588 ExInit2();
589
590 /* Create the system handle table, assign it to the system process, create
591 the client id table and assign a PID for the system process. This needs
592 to be done before the worker threads are initialized so the system
593 process gets the first PID (4) */
594 PspPostInitSystemProcess();
595
596 /* initialize the worker threads */
597 ExpInitializeWorkerThreads();
598
599 /* initialize callbacks */
600 ExpInitializeCallbacks();
601
602 /* Call KD Providers at Phase 1 */
603 KdInitSystem(1, (PROS_LOADER_PARAMETER_BLOCK)&KeLoaderBlock);
604
605 /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
606 IoInit();
607
608 /* TBD */
609 PoInit((PROS_LOADER_PARAMETER_BLOCK)&KeLoaderBlock, ForceAcpiDisable);
610
611 /* Initialize the Registry (Hives are NOT yet loaded!) */
612 CmInitializeRegistry();
613
614 /* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
615 MmInit3();
616
617 /* Initialize Cache Views */
618 CcInit();
619
620 /* Initialize File Locking */
621 FsRtlpInitFileLockingImplementation();
622
623 /* Report all resources used by hal */
624 HalReportResourceUsage();
625
626 /* Clear the screen to blue */
627 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
628
629 /* Display version number and copyright/warranty message */
630 if (NoGuiBoot) ExpDisplayNotice();
631
632 /* Call KD Providers at Phase 2 */
633 KdInitSystem(2, (PROS_LOADER_PARAMETER_BLOCK)&KeLoaderBlock);
634
635 /* Import and create NLS Data and Sections */
636 RtlpInitNls();
637
638 /* Import and Load Registry Hives */
639 CmInitHives(SetupMode);
640
641 /* Initialize VDM support */
642 KeI386VdmInitialize();
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 shared user page. Set dos system path, dos device map, etc. */
664 InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
665
666 /* Create 'ReactOSInitDone' event */
667 RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
668 InitializeObjectAttributes(&ObjectAttributes,
669 &EventName,
670 0,
671 NULL,
672 NULL);
673 Status = ZwCreateEvent(&InitDoneEventHandle,
674 EVENT_ALL_ACCESS,
675 &ObjectAttributes,
676 SynchronizationEvent,
677 FALSE);
678
679 /* Check for Success */
680 if (!NT_SUCCESS(Status)) {
681
682 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
683 InitDoneEventHandle = INVALID_HANDLE_VALUE;
684 }
685
686 /* Launch initial process */
687 Status = ExpLoadInitialProcess(&ProcessHandle,
688 &ThreadHandle);
689
690 /* Check for success, Bugcheck if we failed */
691 if (!NT_SUCCESS(Status)) {
692
693 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
694 }
695
696 /* Wait on the Completion Event */
697 if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
698
699 HANDLE Handles[2]; /* Init event, Initial process */
700
701 /* Setup the Handles to wait on */
702 Handles[0] = InitDoneEventHandle;
703 Handles[1] = ProcessHandle;
704
705 /* Wait for the system to be initialized */
706 Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
707 Status = ZwWaitForMultipleObjects(2,
708 Handles,
709 WaitAny,
710 FALSE,
711 &Timeout);
712 if (!NT_SUCCESS(Status)) {
713
714 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
715
716 } else if (Status == STATUS_TIMEOUT) {
717
718 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
719
720 } else if (Status == STATUS_WAIT_0 + 1) {
721
722 /* Crash the system if the initial process was terminated. */
723 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
724 }
725
726 /*
727 * FIXME: FILIP!
728 * Disable the Boot Logo
729 */
730 if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
731
732 /* Signal the Event and close the handle */
733 ZwSetEvent(InitDoneEventHandle, NULL);
734 ZwClose(InitDoneEventHandle);
735
736 } else {
737
738 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
739 if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
740
741 /* Crash the system if the initial process terminates within 5 seconds. */
742 Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
743 Status = ZwWaitForSingleObject(ProcessHandle,
744 FALSE,
745 &Timeout);
746
747 /* Check for timeout, crash if the initial process didn't initalize */
748 if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
749 }
750
751 /* Enable the Clock, close remaining handles */
752 KiTimerSystemAuditing = 1;
753 ZwClose(ThreadHandle);
754 ZwClose(ProcessHandle);
755 }
756
757 VOID
758 STDCALL
759 INIT_FUNCTION
760 ExInit2(VOID)
761 {
762 ExpInitializeEventImplementation();
763 ExpInitializeEventPairImplementation();
764 ExpInitializeMutantImplementation();
765 ExpInitializeSemaphoreImplementation();
766 ExpInitializeTimerImplementation();
767 LpcpInitSystem();
768 ExpInitializeProfileImplementation();
769 ExpWin32kInit();
770 ExpInitUuids();
771 ExpInitializeHandleTables();
772 }
773
774 /* EOF */