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