- New ERESOURCE implementation: fixes the return value of some functions (VOID vs...
[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 /* Initialize resources */
547 ExpResourceInitialization();
548
549 /* Load basic Security for other Managers */
550 if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
551
552 /* Create the Basic Object Manager Types to allow new Object Types */
553 ObInit();
554
555 /* Initialize Lookaside Lists */
556 ExpInitLookasideLists();
557
558 /* Set up Region Maps, Sections and the Paging File */
559 MmInit2();
560
561 /* Initialize Tokens now that the Object Manager is ready */
562 if (!SeInit2()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
563
564 /* Set 1 CPU for now, we'll increment this later */
565 KeNumberProcessors = 1;
566
567 /* Initalize the Process Manager */
568 PiInitProcessManager();
569
570 /* Break into the Debugger if requested */
571 if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
572
573 /* Initialize all processors */
574 while (!HalAllProcessorsStarted()) {
575
576 PVOID ProcessorStack;
577
578 /* Set up the Kernel and Process Manager for this CPU */
579 KePrepareForApplicationProcessorInit(KeNumberProcessors);
580 KeCreateApplicationProcessorIdleThread(KeNumberProcessors);
581
582 /* Allocate a stack for use when booting the processor */
583 ProcessorStack = RVA(Ki386InitialStackArray[((int)KeNumberProcessors)], MM_STACK_SIZE);
584
585 /* Tell HAL a new CPU is being started */
586 HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
587 KeNumberProcessors++;
588 }
589
590 /* Do Phase 1 HAL Initalization */
591 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
592
593 /* Initialize Basic System Objects and Worker Threads */
594 ExInit2();
595
596 /* Create the system handle table, assign it to the system process, create
597 the client id table and assign a PID for the system process. This needs
598 to be done before the worker threads are initialized so the system
599 process gets the first PID (4) */
600 PspPostInitSystemProcess();
601
602 /* initialize the worker threads */
603 ExpInitializeWorkerThreads();
604
605 /* initialize callbacks */
606 ExpInitializeCallbacks();
607
608 /* Call KD Providers at Phase 1 */
609 KdInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
610
611 /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
612 IoInit();
613
614 /* TBD */
615 PoInit((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock, ForceAcpiDisable);
616
617 /* Initialize the Registry (Hives are NOT yet loaded!) */
618 CmInitializeRegistry();
619
620 /* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
621 MmInit3();
622
623 /* Initialize Cache Views */
624 CcInit();
625
626 /* Initialize File Locking */
627 FsRtlpInitFileLockingImplementation();
628
629 /* Report all resources used by hal */
630 HalReportResourceUsage();
631
632 /* Clear the screen to blue */
633 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
634
635 /* Display version number and copyright/warranty message */
636 if (NoGuiBoot) ExpDisplayNotice();
637
638 /* Call KD Providers at Phase 2 */
639 KdInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
640
641 /* Import and create NLS Data and Sections */
642 RtlpInitNls();
643
644 /* Import and Load Registry Hives */
645 CmInitHives(SetupMode);
646
647 /* Initialize the time zone information from the registry */
648 ExpInitTimeZoneInfo();
649
650 /* Enter the kernel debugger before starting up the boot drivers */
651 if (KdDebuggerEnabled && KdpEarlyBreak)
652 DbgBreakPoint();
653
654 /* Setup Drivers and Root Device Node */
655 IoInit2(BootLog);
656
657 /* Display the boot screen image if not disabled */
658 if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
659
660 /* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
661 IoInit3();
662
663 /* Load the System DLL and its Entrypoints */
664 PsLocateSystemDll();
665
666 /* Initialize the Default Locale */
667 PiInitDefaultLocale();
668
669 /* Initialize shared user page. Set dos system path, dos device map, etc. */
670 InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
671
672 /* Create 'ReactOSInitDone' event */
673 RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
674 InitializeObjectAttributes(&ObjectAttributes,
675 &EventName,
676 0,
677 NULL,
678 NULL);
679 Status = ZwCreateEvent(&InitDoneEventHandle,
680 EVENT_ALL_ACCESS,
681 &ObjectAttributes,
682 SynchronizationEvent,
683 FALSE);
684
685 /* Check for Success */
686 if (!NT_SUCCESS(Status)) {
687
688 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
689 InitDoneEventHandle = INVALID_HANDLE_VALUE;
690 }
691
692 /* Launch initial process */
693 Status = ExpLoadInitialProcess(&ProcessHandle,
694 &ThreadHandle);
695
696 /* Check for success, Bugcheck if we failed */
697 if (!NT_SUCCESS(Status)) {
698
699 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
700 }
701
702 /* Wait on the Completion Event */
703 if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
704
705 HANDLE Handles[2]; /* Init event, Initial process */
706
707 /* Setup the Handles to wait on */
708 Handles[0] = InitDoneEventHandle;
709 Handles[1] = ProcessHandle;
710
711 /* Wait for the system to be initialized */
712 Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
713 Status = ZwWaitForMultipleObjects(2,
714 Handles,
715 WaitAny,
716 FALSE,
717 &Timeout);
718 if (!NT_SUCCESS(Status)) {
719
720 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
721
722 } else if (Status == STATUS_TIMEOUT) {
723
724 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
725
726 } else if (Status == STATUS_WAIT_0 + 1) {
727
728 /* Crash the system if the initial process was terminated. */
729 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
730 }
731
732 /*
733 * FIXME: FILIP!
734 * Disable the Boot Logo
735 */
736 if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
737
738 /* Signal the Event and close the handle */
739 ZwSetEvent(InitDoneEventHandle, NULL);
740 ZwClose(InitDoneEventHandle);
741
742 } else {
743
744 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
745 if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
746
747 /* Crash the system if the initial process terminates within 5 seconds. */
748 Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
749 Status = ZwWaitForSingleObject(ProcessHandle,
750 FALSE,
751 &Timeout);
752
753 /* Check for timeout, crash if the initial process didn't initalize */
754 if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
755 }
756
757 /* Enable the Clock, close remaining handles */
758 KiTimerSystemAuditing = 1;
759 ZwClose(ThreadHandle);
760 ZwClose(ProcessHandle);
761 }
762
763 VOID
764 STDCALL
765 INIT_FUNCTION
766 ExInit2(VOID)
767 {
768 ExpInitializeEventImplementation();
769 ExpInitializeEventPairImplementation();
770 ExpInitializeMutantImplementation();
771 ExpInitializeSemaphoreImplementation();
772 ExpInitializeTimerImplementation();
773 LpcpInitSystem();
774 ExpInitializeProfileImplementation();
775 ExpWin32kInit();
776 ExpInitUuids();
777 ExpInitializeHandleTables();
778 }
779
780 /* EOF */