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