Merge 25584, 25588.
[reactos.git] / reactos / ntoskrnl / ex / init.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ex/init.c
5 * PURPOSE: Executive Initialization Code
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Eric Kohl (ekohl@rz-online.de)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15
16 /* DATA **********************************************************************/
17
18 /* HACK */
19 extern BOOLEAN KiClockSetupComplete;
20
21 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
22
23 /* NT Version Info */
24 ULONG NtMajorVersion = 5;
25 ULONG NtMinorVersion = 0;
26 ULONG NtOSCSDVersion = BUILD_OSCSDVERSION(4, 0);
27 ULONG NtBuildNumber = KERNEL_VERSION_BUILD;
28 ULONG NtGlobalFlag;
29 ULONG ExSuiteMask;
30
31 /* Init flags and settings */
32 ULONG ExpInitializationPhase;
33 BOOLEAN ExpInTextModeSetup;
34 BOOLEAN IoRemoteBootClient;
35 ULONG InitSafeBootMode;
36
37 BOOLEAN NoGuiBoot = FALSE;
38
39 /* NT Boot Path */
40 UNICODE_STRING NtSystemRoot;
41
42 /* Boot NLS information */
43 PVOID ExpNlsTableBase;
44 ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
45 ULONG ExpUnicodeCaseTableDataOffset;
46 NLSTABLEINFO ExpNlsTableInfo;
47 ULONG ExpNlsTableSize;
48 PVOID ExpNlsSectionPointer;
49
50 /* FUNCTIONS ****************************************************************/
51
52 NTSTATUS
53 NTAPI
54 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
55 {
56 UNICODE_STRING LinkName;
57 OBJECT_ATTRIBUTES ObjectAttributes;
58 HANDLE LinkHandle;
59 NTSTATUS Status;
60 ANSI_STRING AnsiName;
61 CHAR Buffer[256];
62 ANSI_STRING TargetString;
63 UNICODE_STRING TargetName;
64
65 /* Initialize the ArcName tree */
66 RtlInitUnicodeString(&LinkName, L"\\ArcName");
67 InitializeObjectAttributes(&ObjectAttributes,
68 &LinkName,
69 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
70 NULL,
71 SePublicDefaultSd);
72
73 /* Create it */
74 Status = NtCreateDirectoryObject(&LinkHandle,
75 DIRECTORY_ALL_ACCESS,
76 &ObjectAttributes);
77 if (!NT_SUCCESS(Status))
78 {
79 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 1, 0, 0);
80 }
81
82 /* Close the LinkHandle */
83 NtClose(LinkHandle);
84
85 /* Initialize the Device tree */
86 RtlInitUnicodeString(&LinkName, L"\\Device");
87 InitializeObjectAttributes(&ObjectAttributes,
88 &LinkName,
89 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
90 NULL,
91 SePublicDefaultSd);
92
93 /* Create it */
94 Status = NtCreateDirectoryObject(&LinkHandle,
95 DIRECTORY_ALL_ACCESS,
96 &ObjectAttributes);
97 if (!NT_SUCCESS(Status))
98 {
99 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 2, 0, 0);
100 }
101
102 /* Close the LinkHandle */
103 ObCloseHandle(LinkHandle, KernelMode);
104
105 /* Create the system root symlink name */
106 RtlInitAnsiString(&AnsiName, "\\SystemRoot");
107 Status = RtlAnsiStringToUnicodeString(&LinkName, &AnsiName, TRUE);
108 if (!NT_SUCCESS(Status))
109 {
110 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 3, 0, 0);
111 }
112
113 /* Initialize the attributes for the link */
114 InitializeObjectAttributes(&ObjectAttributes,
115 &LinkName,
116 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
117 NULL,
118 SePublicDefaultSd);
119
120 /* Build the ARC name */
121 sprintf(Buffer,
122 "\\ArcName\\%s%s",
123 LoaderBlock->ArcBootDeviceName,
124 LoaderBlock->NtBootPathName);
125 Buffer[strlen(Buffer) - 1] = ANSI_NULL;
126
127 /* Convert it to Unicode */
128 RtlInitString(&TargetString, Buffer);
129 Status = RtlAnsiStringToUnicodeString(&TargetName,
130 &TargetString,
131 TRUE);
132 if (!NT_SUCCESS(Status))
133 {
134 /* We failed, bugcheck */
135 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 4, 0, 0);
136 }
137
138 /* Create it */
139 Status = NtCreateSymbolicLinkObject(&LinkHandle,
140 SYMBOLIC_LINK_ALL_ACCESS,
141 &ObjectAttributes,
142 &TargetName);
143
144 /* Free the strings */
145 RtlFreeUnicodeString(&LinkName);
146 RtlFreeUnicodeString(&TargetName);
147
148 /* Check if creating the link failed */
149 if (!NT_SUCCESS(Status))
150 {
151 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 5, 0, 0);
152 }
153
154 /* Close the handle and return success */
155 ObCloseHandle(LinkHandle, KernelMode);
156 return STATUS_SUCCESS;
157 }
158
159 VOID
160 NTAPI
161 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
162 {
163 LARGE_INTEGER SectionSize;
164 NTSTATUS Status;
165 HANDLE NlsSection;
166 PVOID SectionBase = NULL;
167 ULONG ViewSize = 0;
168 LARGE_INTEGER SectionOffset = {{0}};
169 PLIST_ENTRY ListHead, NextEntry;
170 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
171
172 /* Check if this is boot-time phase 0 initialization */
173 if (!ExpInitializationPhase)
174 {
175 /* Loop the memory descriptors */
176 ListHead = &LoaderBlock->MemoryDescriptorListHead;
177 NextEntry = ListHead->Flink;
178 while (NextEntry != ListHead)
179 {
180 /* Get the current block */
181 MdBlock = CONTAINING_RECORD(NextEntry,
182 MEMORY_ALLOCATION_DESCRIPTOR,
183 ListEntry);
184
185 /* Check if this is an NLS block */
186 if (MdBlock->MemoryType == LoaderNlsData)
187 {
188 /* Increase the table size */
189 ExpNlsTableSize += MdBlock->PageCount * PAGE_SIZE;
190 }
191
192 /* Go to the next block */
193 NextEntry = MdBlock->ListEntry.Flink;
194 }
195
196 /*
197 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
198 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
199 */
200 ExpNlsTableSize += 2 * PAGE_SIZE; // BIAS FOR FREELDR. HACK!
201
202 /* Allocate the a new buffer since loader memory will be freed */
203 ExpNlsTableBase = ExAllocatePoolWithTag(NonPagedPool,
204 ExpNlsTableSize,
205 TAG('R', 't', 'l', 'i'));
206 if (!ExpNlsTableBase) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
207
208 /* Copy the codepage data in its new location. */
209 RtlCopyMemory(ExpNlsTableBase,
210 LoaderBlock->NlsData->AnsiCodePageData,
211 ExpNlsTableSize);
212
213 /* Initialize and reset the NLS TAbles */
214 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
215 ExpAnsiCodePageDataOffset),
216 (PVOID)((ULONG_PTR)ExpNlsTableBase +
217 ExpOemCodePageDataOffset),
218 (PVOID)((ULONG_PTR)ExpNlsTableBase +
219 ExpUnicodeCaseTableDataOffset),
220 &ExpNlsTableInfo);
221 RtlResetRtlTranslations(&ExpNlsTableInfo);
222 return;
223 }
224
225 /* Set the section size */
226 SectionSize.QuadPart = ExpNlsTableSize;
227
228 /* Create the NLS Section */
229 Status = ZwCreateSection(&NlsSection,
230 SECTION_ALL_ACCESS,
231 NULL,
232 &SectionSize,
233 PAGE_READWRITE,
234 SEC_COMMIT,
235 NULL);
236 if (!NT_SUCCESS(Status))
237 {
238 /* Failed */
239 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 1, 0, 0);
240 }
241
242 /* Get a pointer to the section */
243 Status = ObReferenceObjectByHandle(NlsSection,
244 SECTION_ALL_ACCESS,
245 MmSectionObjectType,
246 KernelMode,
247 &ExpNlsSectionPointer,
248 NULL);
249 ZwClose(NlsSection);
250 if (!NT_SUCCESS(Status))
251 {
252 /* Failed */
253 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 2, 0, 0);
254 }
255
256 /* Map the NLS Section in system space */
257 Status = MmMapViewInSystemSpace(ExpNlsSectionPointer,
258 &SectionBase,
259 &ExpNlsTableSize);
260 if (!NT_SUCCESS(Status))
261 {
262 /* Failed */
263 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 3, 0, 0);
264 }
265
266 /* Copy the codepage data in its new location. */
267 RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
268
269 /* Free the previously allocated buffer and set the new location */
270 ExFreePool(ExpNlsTableBase);
271 ExpNlsTableBase = SectionBase;
272
273 /* Initialize the NLS Tables */
274 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
275 ExpAnsiCodePageDataOffset),
276 (PVOID)((ULONG_PTR)ExpNlsTableBase +
277 ExpOemCodePageDataOffset),
278 (PVOID)((ULONG_PTR)ExpNlsTableBase +
279 ExpUnicodeCaseTableDataOffset),
280 &ExpNlsTableInfo);
281 RtlResetRtlTranslations(&ExpNlsTableInfo);
282
283 /* Reset the base to 0 */
284 SectionBase = NULL;
285
286 /* Map the section in the system process */
287 Status = MmMapViewOfSection(ExpNlsSectionPointer,
288 PsGetCurrentProcess(),
289 &SectionBase,
290 0L,
291 0L,
292 &SectionOffset,
293 &ViewSize,
294 ViewShare,
295 0L,
296 PAGE_READWRITE);
297 if (!NT_SUCCESS(Status))
298 {
299 /* Failed */
300 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 5, 0, 0);
301 }
302
303 /* Copy the table into the system process and set this as the base */
304 RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
305 ExpNlsTableBase = SectionBase;
306 }
307
308 VOID
309 INIT_FUNCTION
310 ExpDisplayNotice(VOID)
311 {
312 CHAR str[50];
313
314 if (ExpInTextModeSetup)
315 {
316 HalDisplayString(
317 "\n\n\n ReactOS " KERNEL_VERSION_STR " Setup \n");
318 HalDisplayString(
319 " \xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD");
320 HalDisplayString(
321 "\xCD\xCD\n");
322 return;
323 }
324
325 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
326 KERNEL_VERSION_BUILD_STR")\n");
327 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
328 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
329 "Public License, and you\n");
330 HalDisplayString("are welcome to change it and/or distribute copies of it "
331 "under certain\n");
332 HalDisplayString("conditions. There is absolutely no warranty for "
333 "ReactOS.\n\n");
334
335 /* Display number of Processors */
336 sprintf(str,
337 "Found %x system processor(s). [%lu MB Memory]\n",
338 (int)KeNumberProcessors,
339 (MmFreeLdrMemHigher + 1088)/ 1024);
340 HalDisplayString(str);
341
342 }
343
344 NTSTATUS
345 NTAPI
346 ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
347 IN PHANDLE ThreadHandle)
348 {
349 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
350 NTSTATUS Status;
351 ULONG Size;
352 RTL_USER_PROCESS_INFORMATION ProcessInformation;
353 PWSTR p;
354 UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
355 UNICODE_STRING SmssName, Environment, SystemDriveString;
356
357 /* Allocate memory for the process parameters */
358 Size = sizeof(RTL_USER_PROCESS_PARAMETERS) +
359 ((MAX_PATH * 4) * sizeof(WCHAR));
360 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
361 (PVOID)&ProcessParameters,
362 0,
363 &Size,
364 MEM_COMMIT,
365 PAGE_READWRITE);
366 if (!NT_SUCCESS(Status))
367 {
368 /* Failed */
369 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED, Status, 0, 0, 0);
370 }
371
372 /* Setup the basic header, and give the process the low 1MB to itself */
373 ProcessParameters->Length = Size;
374 ProcessParameters->MaximumLength = Size;
375 ProcessParameters->Flags = RTL_USER_PROCESS_PARAMETERS_NORMALIZED |
376 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
377
378 /* Allocate a page for the environment */
379 Size = PAGE_SIZE;
380 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
381 (PVOID)&ProcessParameters->Environment,
382 0,
383 &Size,
384 MEM_COMMIT,
385 PAGE_READWRITE);
386 if (!NT_SUCCESS(Status))
387 {
388 /* Failed */
389 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
390 }
391
392 /* Make a buffer for the DOS path */
393 p = (PWSTR)(ProcessParameters + 1);
394 ProcessParameters->CurrentDirectory.DosPath.Buffer = p;
395 ProcessParameters->
396 CurrentDirectory.DosPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
397
398 /* Copy the DOS path */
399 RtlCopyUnicodeString(&ProcessParameters->CurrentDirectory.DosPath,
400 &NtSystemRoot);
401
402 /* Make a buffer for the DLL Path */
403 p = (PWSTR)((PCHAR)ProcessParameters->CurrentDirectory.DosPath.Buffer +
404 ProcessParameters->CurrentDirectory.DosPath.MaximumLength);
405 ProcessParameters->DllPath.Buffer = p;
406 ProcessParameters->DllPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
407
408 /* Copy the DLL path and append the system32 directory */
409 RtlCopyUnicodeString(&ProcessParameters->DllPath,
410 &ProcessParameters->CurrentDirectory.DosPath);
411 RtlAppendUnicodeToString(&ProcessParameters->DllPath, L"\\System32");
412
413 /* Make a buffer for the image name */
414 p = (PWSTR)((PCHAR)ProcessParameters->DllPath.Buffer +
415 ProcessParameters->DllPath.MaximumLength);
416 ProcessParameters->ImagePathName.Buffer = p;
417 ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
418
419 /* Append the system path and session manager name */
420 RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
421 L"\\SystemRoot\\System32");
422 RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
423 L"\\smss.exe");
424
425 /* Create the environment string */
426 RtlInitEmptyUnicodeString(&Environment,
427 ProcessParameters->Environment,
428 (USHORT)Size);
429
430 /* Append the DLL path to it */
431 RtlAppendUnicodeToString(&Environment, L"Path=" );
432 RtlAppendUnicodeStringToString(&Environment, &ProcessParameters->DllPath);
433 RtlAppendUnicodeStringToString(&Environment, &NullString );
434
435 /* Create the system drive string */
436 SystemDriveString = NtSystemRoot;
437 SystemDriveString.Length = 2 * sizeof(WCHAR);
438
439 /* Append it to the environment */
440 RtlAppendUnicodeToString(&Environment, L"SystemDrive=");
441 RtlAppendUnicodeStringToString(&Environment, &SystemDriveString);
442 RtlAppendUnicodeStringToString(&Environment, &NullString);
443
444 /* Append the system root to the environment */
445 RtlAppendUnicodeToString(&Environment, L"SystemRoot=");
446 RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
447 RtlAppendUnicodeStringToString(&Environment, &NullString);
448
449 /* Get and set the command line equal to the image path */
450 ProcessParameters->CommandLine = ProcessParameters->ImagePathName;
451 SmssName = ProcessParameters->ImagePathName;
452
453 /* Create SMSS process */
454 Status = RtlCreateUserProcess(&SmssName,
455 OBJ_CASE_INSENSITIVE,
456 RtlDeNormalizeProcessParams(
457 ProcessParameters),
458 NULL,
459 NULL,
460 NULL,
461 FALSE,
462 NULL,
463 NULL,
464 &ProcessInformation);
465 if (!NT_SUCCESS(Status))
466 {
467 /* Failed */
468 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED, Status, 0, 0, 0);
469 }
470
471 /* Resume the thread */
472 Status = ZwResumeThread(ProcessInformation.ThreadHandle, NULL);
473 if (!NT_SUCCESS(Status))
474 {
475 /* Failed */
476 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
477 }
478
479 /* Return Handles */
480 *ProcessHandle = ProcessInformation.ProcessHandle;
481 *ThreadHandle = ProcessInformation.ThreadHandle;
482 return STATUS_SUCCESS;
483 }
484
485 ULONG
486 NTAPI
487 ExComputeTickCountMultiplier(IN ULONG ClockIncrement)
488 {
489 ULONG MsRemainder = 0, MsIncrement;
490 ULONG IncrementRemainder;
491 ULONG i;
492
493 /* Count the number of milliseconds for each clock interrupt */
494 MsIncrement = ClockIncrement / (10 * 1000);
495
496 /* Count the remainder from the division above, with 24-bit precision */
497 IncrementRemainder = ClockIncrement - (MsIncrement * (10 * 1000));
498 for (i= 0; i < 24; i++)
499 {
500 /* Shift the remainders */
501 MsRemainder <<= 1;
502 IncrementRemainder <<= 1;
503
504 /* Check if we've went past 1 ms */
505 if (IncrementRemainder >= (10 * 1000))
506 {
507 /* Increase the remainder by one, and substract from increment */
508 IncrementRemainder -= (10 * 1000);
509 MsRemainder |= 1;
510 }
511 }
512
513 /* Return the increment */
514 return (MsIncrement << 24) | MsRemainder;
515 }
516
517 BOOLEAN
518 NTAPI
519 ExpInitSystemPhase0(VOID)
520 {
521 /* Initialize EXRESOURCE Support */
522 ExpResourceInitialization();
523
524 /* Initialize the environment lock */
525 ExInitializeFastMutex(&ExpEnvironmentLock);
526
527 /* Initialize the lookaside lists and locks */
528 ExpInitLookasideLists();
529
530 /* Initialize the Firmware Table resource and listhead */
531 InitializeListHead(&ExpFirmwareTableProviderListHead);
532 ExInitializeResourceLite(&ExpFirmwareTableResource);
533
534 /* Set the suite mask to maximum and return */
535 ExSuiteMask = 0xFFFFFFFF;
536 return TRUE;
537 }
538
539 BOOLEAN
540 NTAPI
541 ExpInitSystemPhase1(VOID)
542 {
543 /* Initialize worker threads */
544 ExpInitializeWorkerThreads();
545
546 /* Initialize pushlocks */
547 ExpInitializePushLocks();
548
549 /* Initialize events and event pairs */
550 ExpInitializeEventImplementation();
551 ExpInitializeEventPairImplementation();
552
553 /* Initialize callbacks */
554 ExpInitializeCallbacks();
555
556 /* Initialize mutants */
557 ExpInitializeMutantImplementation();
558
559 /* Initialize semaphores */
560 ExpInitializeSemaphoreImplementation();
561
562 /* Initialize timers */
563 ExpInitializeTimerImplementation();
564
565 /* Initialize profiling */
566 ExpInitializeProfileImplementation();
567
568 /* Initialize UUIDs */
569 ExpInitUuids();
570
571 /* Initialize Win32K */
572 ExpWin32kInit();
573 return TRUE;
574 }
575
576 BOOLEAN
577 NTAPI
578 ExInitSystem(VOID)
579 {
580 /* Check the initialization phase */
581 switch (ExpInitializationPhase)
582 {
583 case 0:
584
585 /* Do Phase 0 */
586 return ExpInitSystemPhase0();
587
588 case 1:
589
590 /* Do Phase 1 */
591 return ExpInitSystemPhase1();
592
593 default:
594
595 /* Don't know any other phase! Bugcheck! */
596 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL);
597 return FALSE;
598 }
599 }
600
601 BOOLEAN
602 NTAPI
603 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
604 {
605 PLOADER_PARAMETER_EXTENSION Extension;
606
607 /* Get the loader extension */
608 Extension = LoaderBlock->Extension;
609
610 /* Validate the size (larger structures are OK, we'll just ignore them) */
611 if (Extension->Size < sizeof(LOADER_PARAMETER_EXTENSION)) return FALSE;
612
613 /* Don't validate upper versions */
614 if (Extension->MajorVersion > 5) return TRUE;
615
616 /* Fail if this is NT 4 */
617 if (Extension->MajorVersion < 5) return FALSE;
618
619 /* Fail if this is XP */
620 if (Extension->MinorVersion < 2) return FALSE;
621
622 /* This is 2003 or newer, approve it */
623 return TRUE;
624 }
625
626 VOID
627 NTAPI
628 ExpInitializeExecutive(IN ULONG Cpu,
629 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
630 {
631 PNLS_DATA_BLOCK NlsData;
632 CHAR Buffer[256];
633 ANSI_STRING AnsiPath;
634 NTSTATUS Status;
635
636 /* Validate Loader */
637 if (!ExpIsLoaderValid(LoaderBlock))
638 {
639 /* Invalid loader version */
640 KeBugCheckEx(MISMATCHED_HAL,
641 3,
642 LoaderBlock->Extension->Size,
643 LoaderBlock->Extension->MajorVersion,
644 LoaderBlock->Extension->MinorVersion);
645 }
646
647 /* Initialize PRCB pool lookaside pointers */
648 ExInitPoolLookasidePointers();
649
650 /* Check if this is an application CPU */
651 if (Cpu)
652 {
653 /* Then simply initialize it with HAL */
654 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
655 {
656 /* Initialization failed */
657 KeBugCheck(HAL_INITIALIZATION_FAILED);
658 }
659
660 /* We're done */
661 return;
662 }
663
664 /* Assume no text-mode or remote boot */
665 ExpInTextModeSetup = FALSE;
666 IoRemoteBootClient = FALSE;
667
668 /* Check if we have a setup loader block */
669 if (LoaderBlock->SetupLdrBlock)
670 {
671 /* Check if this is text-mode setup */
672 if (LoaderBlock->SetupLdrBlock->Flags & 1) ExpInTextModeSetup = TRUE;
673
674 /* Check if this is network boot */
675 if (LoaderBlock->SetupLdrBlock->Flags & 2)
676 {
677 /* Set variable */
678 IoRemoteBootClient = TRUE;
679
680 /* Make sure we're actually booting off the network */
681 ASSERT(!_memicmp(LoaderBlock->ArcBootDeviceName, "net(0)", 6));
682 }
683 }
684
685 /* Set phase to 0 */
686 ExpInitializationPhase = 0;
687
688 /* Setup NLS Base and offsets */
689 NlsData = LoaderBlock->NlsData;
690 ExpNlsTableBase = NlsData->AnsiCodePageData;
691 ExpAnsiCodePageDataOffset = 0;
692 ExpOemCodePageDataOffset = ((ULONG_PTR)NlsData->OemCodePageData -
693 (ULONG_PTR)NlsData->AnsiCodePageData);
694 ExpUnicodeCaseTableDataOffset = ((ULONG_PTR)NlsData->UnicodeCodePageData -
695 (ULONG_PTR)NlsData->AnsiCodePageData);
696
697 /* Initialize the NLS Tables */
698 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
699 ExpAnsiCodePageDataOffset),
700 (PVOID)((ULONG_PTR)ExpNlsTableBase +
701 ExpOemCodePageDataOffset),
702 (PVOID)((ULONG_PTR)ExpNlsTableBase +
703 ExpUnicodeCaseTableDataOffset),
704 &ExpNlsTableInfo);
705 RtlResetRtlTranslations(&ExpNlsTableInfo);
706
707 /* Now initialize the HAL */
708 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
709 {
710 /* HAL failed to initialize, bugcheck */
711 KeBugCheck(HAL_INITIALIZATION_FAILED);
712 }
713
714 /* Make sure interrupts are active now */
715 _enable();
716
717 /* Clear the crypto exponent */
718 SharedUserData->CryptoExponent = 0;
719
720 /* Set global flags for the checked build */
721 #if DBG
722 NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS |
723 FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
724 #endif
725
726 /* Setup NT System Root Path */
727 sprintf(Buffer, "C:%s", LoaderBlock->NtBootPathName);
728
729 /* Convert to ANSI_STRING and null-terminate it */
730 RtlInitString(&AnsiPath, Buffer );
731 Buffer[--AnsiPath.Length] = ANSI_NULL;
732
733 /* Get the string from KUSER_SHARED_DATA's buffer */
734 NtSystemRoot.Buffer = SharedUserData->NtSystemRoot;
735 NtSystemRoot.MaximumLength = sizeof(SharedUserData->NtSystemRoot) / sizeof(WCHAR);
736 NtSystemRoot.Length = 0;
737
738 /* Now fill it in */
739 Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
740 if (!NT_SUCCESS(Status)) KEBUGCHECK(SESSION3_INITIALIZATION_FAILED);
741
742 /* Setup bugcheck messages */
743 KiInitializeBugCheck();
744
745 /* Initialize the executive at phase 0 */
746 if (!ExInitSystem()) KEBUGCHECK(PHASE0_INITIALIZATION_FAILED);
747
748 /* Break into the Debugger if requested */
749 if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
750
751 /* Set system ranges */
752 SharedUserData->Reserved1 = (ULONG_PTR)MmHighestUserAddress;
753 SharedUserData->Reserved3 = (ULONG_PTR)MmSystemRangeStart;
754
755 /* Make a copy of the NLS Tables */
756 ExpInitNls(LoaderBlock);
757
758 /* Initialize the Handle Table */
759 ExpInitializeHandleTables();
760
761 #if DBG
762 /* On checked builds, allocate the system call count table */
763 KeServiceDescriptorTable[0].Count =
764 ExAllocatePoolWithTag(NonPagedPool,
765 KiServiceLimit * sizeof(ULONG),
766 TAG('C', 'a', 'l', 'l'));
767
768 /* Use it for the shadow table too */
769 KeServiceDescriptorTableShadow[0].Count = KeServiceDescriptorTable[0].Count;
770
771 /* Make sure allocation succeeded */
772 if (KeServiceDescriptorTable[0].Count)
773 {
774 /* Zero the call counts to 0 */
775 RtlZeroMemory(KeServiceDescriptorTable[0].Count,
776 KiServiceLimit * sizeof(ULONG));
777 }
778 #endif
779
780 /* Create the Basic Object Manager Types to allow new Object Types */
781 if (!ObInit()) KEBUGCHECK(OBJECT_INITIALIZATION_FAILED);
782
783 /* Load basic Security for other Managers */
784 if (!SeInit()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
785
786 /* Set up Region Maps, Sections and the Paging File */
787 MmInit2();
788
789 /* Initialize the boot video. */
790 InbvDisplayInitialize();
791
792 /* Initialize the Process Manager */
793 if (!PsInitSystem()) KEBUGCHECK(PROCESS_INITIALIZATION_FAILED);
794
795 /* Initialize the User-Mode Debugging Subsystem */
796 DbgkInitialize();
797
798 /* Calculate the tick count multiplier */
799 ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement);
800 SharedUserData->TickCountMultiplier = ExpTickCountMultiplier;
801
802 /* Set the OS Version */
803 SharedUserData->NtMajorVersion = NtMajorVersion;
804 SharedUserData->NtMinorVersion = NtMinorVersion;
805
806 /* Set the machine type */
807 #if defined(_X86_)
808 SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_I386;
809 SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_I386;
810 #elif defined(_PPC_) // <3 Arty
811 SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_POWERPC;
812 SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_POWERPC;
813 #elif
814 #error "Unsupported ReactOS Target"
815 #endif
816 }
817
818 VOID
819 NTAPI
820 ExPhase2Init(PVOID Context)
821 {
822 LARGE_INTEGER Timeout;
823 HANDLE ProcessHandle;
824 HANDLE ThreadHandle;
825 NTSTATUS Status;
826 TIME_FIELDS TimeFields;
827 LARGE_INTEGER SystemBootTime, UniversalBootTime;
828
829 /* Set to phase 1 */
830 ExpInitializationPhase = 1;
831
832 /* Set us at maximum priority */
833 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY);
834
835 /* Do Phase 1 HAL Initialization */
836 HalInitSystem(1, KeLoaderBlock);
837
838 /* Check if GUI Boot is enabled */
839 if (strstr(KeLoaderBlock->LoadOptions, "NOGUIBOOT")) NoGuiBoot = TRUE;
840
841 /* Display the boot screen image if not disabled */
842 if (!ExpInTextModeSetup) InbvDisplayInitialize2(NoGuiBoot);
843 if (!NoGuiBoot) InbvDisplayBootLogo();
844
845 /* Clear the screen to blue and display the boot notice and debug status */
846 if (NoGuiBoot) ExpDisplayNotice();
847 KdInitSystem(2, KeLoaderBlock);
848
849 /* Initialize Power Subsystem in Phase 0 */
850 PoInit(0, AcpiTableDetected);
851
852 /* Query the clock */
853 if (HalQueryRealTimeClock(&TimeFields))
854 {
855 /* Convert to time fields */
856 RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
857 UniversalBootTime = SystemBootTime;
858
859 #if 0 // FIXME: Won't work until we can read registry data here
860 /* FIXME: This assumes that the RTC is not already in GMT */
861 ExpTimeZoneBias.QuadPart = Int32x32To64(ExpLastTimeZoneBias * 60,
862 10000000);
863
864 /* Set the boot time-zone bias */
865 SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
866 SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
867 SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
868
869 /* Convert the boot time to local time, and set it */
870 UniversalBootTime.QuadPart = SystemBootTime.QuadPart +
871 ExpTimeZoneBias.QuadPart;
872 #endif
873 KiSetSystemTime(&UniversalBootTime);
874
875 /* Remember this as the boot time */
876 KeBootTime = UniversalBootTime;
877 }
878
879 /* The clock is ready now (FIXME: HACK FOR OLD HAL) */
880 KiClockSetupComplete = TRUE;
881
882 /* Initialize all processors */
883 HalAllProcessorsStarted();
884
885 /* Call OB initialization again */
886 if (!ObInit()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED);
887
888 /* Initialize Basic System Objects and Worker Threads */
889 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 1, 0, 0, 0);
890
891 /* Initialize the later stages of the kernel */
892 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 2, 0, 0, 0);
893
894 /* Call KD Providers at Phase 1 */
895 if (!KdInitSystem(ExpInitializationPhase, KeLoaderBlock))
896 {
897 /* Failed, bugcheck */
898 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 3, 0, 0, 0);
899 }
900
901 /* Create SystemRoot Link */
902 Status = ExpCreateSystemRootLink(KeLoaderBlock);
903 if (!NT_SUCCESS(Status))
904 {
905 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 0, 0, 0);
906 }
907
908 /* Create NLS section */
909 ExpInitNls(KeLoaderBlock);
910
911 /* Initialize Cache Views */
912 CcInitializeCacheManager();
913
914 /* Initialize the Registry */
915 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED);
916
917 /* Update timezone information */
918 ExRefreshTimeZoneInformation(&SystemBootTime);
919
920 /* Initialize the File System Runtime Library */
921 FsRtlInitSystem();
922
923 /* Report all resources used by HAL */
924 HalReportResourceUsage();
925
926 /* Initialize LPC */
927 LpcpInitSystem();
928
929 /* Enter the kernel debugger before starting up the boot drivers */
930 if (KdDebuggerEnabled && KdpEarlyBreak) DbgBreakPoint();
931
932 /* Initialize the I/O Subsystem */
933 if (!IoInitSystem(KeLoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED);
934
935 /* Unmap Low memory, and initialize the MPW and Balancer Thread */
936 MmInit3();
937 #if DBG
938 extern ULONG Guard;
939 #endif
940 ASSERT(Guard == 0xCACA1234);
941
942 /* Initialize VDM support */
943 KeI386VdmInitialize();
944
945 /* Initialize Power Subsystem in Phase 1*/
946 PoInit(1, AcpiTableDetected);
947
948 /* Initialize the Process Manager at Phase 1 */
949 if (!PsInitSystem()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
950
951 /* Launch initial process */
952 Status = ExpLoadInitialProcess(&ProcessHandle, &ThreadHandle);
953
954 /* Wait 5 seconds for it to initialize */
955 Timeout.QuadPart = Int32x32To64(5, -10000000);
956 Status = ZwWaitForSingleObject(ProcessHandle, FALSE, &Timeout);
957 if (!NoGuiBoot) InbvFinalizeBootLogo();
958 if (Status == STATUS_SUCCESS)
959 {
960 /* Bugcheck the system if SMSS couldn't initialize */
961 KeBugCheck(SESSION5_INITIALIZATION_FAILED);
962 }
963 else
964 {
965 /* Close process handles */
966 ZwClose(ThreadHandle);
967 ZwClose(ProcessHandle);
968
969 /* FIXME: We should free the initial process' memory!*/
970
971 /* Increase init phase */
972 ExpInitializationPhase += 1;
973
974 /* Jump into zero page thread */
975 MmZeroPageThreadMain(NULL);
976 }
977 }
978 /* EOF */