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)
10 /* INCLUDES ******************************************************************/
14 #include <internal/debug.h>
16 /* DATA **********************************************************************/
19 extern BOOLEAN KiClockSetupComplete
;
21 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
24 ULONG NtMajorVersion
= 5;
25 ULONG NtMinorVersion
= 0;
26 ULONG NtOSCSDVersion
= BUILD_OSCSDVERSION(4, 0);
27 ULONG NtBuildNumber
= KERNEL_VERSION_BUILD
;
31 /* Init flags and settings */
32 ULONG ExpInitializationPhase
;
33 BOOLEAN ExpInTextModeSetup
;
34 BOOLEAN IoRemoteBootClient
;
35 ULONG InitSafeBootMode
;
37 BOOLEAN NoGuiBoot
= FALSE
;
40 UNICODE_STRING NtSystemRoot
;
42 /* NT Initial User Application */
43 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
44 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
46 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
48 /* Boot NLS information */
49 PVOID ExpNlsTableBase
;
50 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
51 ULONG ExpUnicodeCaseTableDataOffset
;
52 NLSTABLEINFO ExpNlsTableInfo
;
53 ULONG ExpNlsTableSize
;
54 PVOID ExpNlsSectionPointer
;
56 /* FUNCTIONS ****************************************************************/
60 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
62 UNICODE_STRING LinkName
;
63 OBJECT_ATTRIBUTES ObjectAttributes
;
68 ANSI_STRING TargetString
;
69 UNICODE_STRING TargetName
;
71 /* Initialize the ArcName tree */
72 RtlInitUnicodeString(&LinkName
, L
"\\ArcName");
73 InitializeObjectAttributes(&ObjectAttributes
,
75 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
77 SePublicDefaultUnrestrictedSd
);
80 Status
= NtCreateDirectoryObject(&LinkHandle
,
83 if (!NT_SUCCESS(Status
))
85 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
88 /* Close the LinkHandle */
91 /* Initialize the Device tree */
92 RtlInitUnicodeString(&LinkName
, L
"\\Device");
93 InitializeObjectAttributes(&ObjectAttributes
,
95 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
97 SePublicDefaultUnrestrictedSd
);
100 Status
= NtCreateDirectoryObject(&LinkHandle
,
101 DIRECTORY_ALL_ACCESS
,
103 if (!NT_SUCCESS(Status
))
105 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
108 /* Close the LinkHandle */
109 ObCloseHandle(LinkHandle
, KernelMode
);
111 /* Create the system root symlink name */
112 RtlInitAnsiString(&AnsiName
, "\\SystemRoot");
113 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &AnsiName
, TRUE
);
114 if (!NT_SUCCESS(Status
))
116 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
119 /* Initialize the attributes for the link */
120 InitializeObjectAttributes(&ObjectAttributes
,
122 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
124 SePublicDefaultUnrestrictedSd
);
126 /* Build the ARC name */
129 LoaderBlock
->ArcBootDeviceName
,
130 LoaderBlock
->NtBootPathName
);
131 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
133 /* Convert it to Unicode */
134 RtlInitString(&TargetString
, Buffer
);
135 Status
= RtlAnsiStringToUnicodeString(&TargetName
,
138 if (!NT_SUCCESS(Status
))
140 /* We failed, bugcheck */
141 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
145 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
146 SYMBOLIC_LINK_ALL_ACCESS
,
150 /* Free the strings */
151 RtlFreeUnicodeString(&LinkName
);
152 RtlFreeUnicodeString(&TargetName
);
154 /* Check if creating the link failed */
155 if (!NT_SUCCESS(Status
))
157 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
160 /* Close the handle and return success */
161 ObCloseHandle(LinkHandle
, KernelMode
);
162 return STATUS_SUCCESS
;
167 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
169 LARGE_INTEGER SectionSize
;
172 PVOID SectionBase
= NULL
;
174 LARGE_INTEGER SectionOffset
= {{0}};
175 PLIST_ENTRY ListHead
, NextEntry
;
176 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
178 /* Check if this is boot-time phase 0 initialization */
179 if (!ExpInitializationPhase
)
181 /* Loop the memory descriptors */
182 ListHead
= &LoaderBlock
->MemoryDescriptorListHead
;
183 NextEntry
= ListHead
->Flink
;
184 while (NextEntry
!= ListHead
)
186 /* Get the current block */
187 MdBlock
= CONTAINING_RECORD(NextEntry
,
188 MEMORY_ALLOCATION_DESCRIPTOR
,
191 /* Check if this is an NLS block */
192 if (MdBlock
->MemoryType
== LoaderNlsData
)
194 /* Increase the table size */
195 ExpNlsTableSize
+= MdBlock
->PageCount
* PAGE_SIZE
;
198 /* Go to the next block */
199 NextEntry
= MdBlock
->ListEntry
.Flink
;
203 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
204 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
206 ExpNlsTableSize
+= 2 * PAGE_SIZE
; // BIAS FOR FREELDR. HACK!
208 /* Allocate the a new buffer since loader memory will be freed */
209 ExpNlsTableBase
= ExAllocatePoolWithTag(NonPagedPool
,
211 TAG('R', 't', 'l', 'i'));
212 if (!ExpNlsTableBase
) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
214 /* Copy the codepage data in its new location. */
215 RtlCopyMemory(ExpNlsTableBase
,
216 LoaderBlock
->NlsData
->AnsiCodePageData
,
219 /* Initialize and reset the NLS TAbles */
220 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
221 ExpAnsiCodePageDataOffset
),
222 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
223 ExpOemCodePageDataOffset
),
224 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
225 ExpUnicodeCaseTableDataOffset
),
227 RtlResetRtlTranslations(&ExpNlsTableInfo
);
231 /* Set the section size */
232 SectionSize
.QuadPart
= ExpNlsTableSize
;
234 /* Create the NLS Section */
235 Status
= ZwCreateSection(&NlsSection
,
242 if (!NT_SUCCESS(Status
))
245 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
248 /* Get a pointer to the section */
249 Status
= ObReferenceObjectByHandle(NlsSection
,
253 &ExpNlsSectionPointer
,
256 if (!NT_SUCCESS(Status
))
259 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
262 /* Map the NLS Section in system space */
263 Status
= MmMapViewInSystemSpace(ExpNlsSectionPointer
,
266 if (!NT_SUCCESS(Status
))
269 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
272 /* Copy the codepage data in its new location. */
273 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
275 /* Free the previously allocated buffer and set the new location */
276 ExFreePool(ExpNlsTableBase
);
277 ExpNlsTableBase
= SectionBase
;
279 /* Initialize the NLS Tables */
280 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
281 ExpAnsiCodePageDataOffset
),
282 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
283 ExpOemCodePageDataOffset
),
284 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
285 ExpUnicodeCaseTableDataOffset
),
287 RtlResetRtlTranslations(&ExpNlsTableInfo
);
289 /* Reset the base to 0 */
292 /* Map the section in the system process */
293 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
294 PsGetCurrentProcess(),
303 if (!NT_SUCCESS(Status
))
306 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
309 /* Copy the table into the system process and set this as the base */
310 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
311 ExpNlsTableBase
= SectionBase
;
316 ExpDisplayNotice(VOID
)
320 if (ExpInTextModeSetup
)
323 "\n\n\n ReactOS " KERNEL_VERSION_STR
" Setup \n");
325 " \xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD");
331 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
332 KERNEL_VERSION_BUILD_STR
")\n");
333 HalDisplayString(RES_STR_LEGAL_COPYRIGHT
);
334 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
335 "Public License, and you\n");
336 HalDisplayString("are welcome to change it and/or distribute copies of it "
338 HalDisplayString("conditions. There is absolutely no warranty for "
341 /* Display number of Processors */
343 "Found %x system processor(s). [%lu MB Memory]\n",
344 (int)KeNumberProcessors
,
345 (MmFreeLdrMemHigher
+ 1088)/ 1024);
346 HalDisplayString(str
);
352 ExpLoadInitialProcess(IN PHANDLE ProcessHandle
,
353 IN PHANDLE ThreadHandle
)
355 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
358 RTL_USER_PROCESS_INFORMATION ProcessInformation
;
360 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
361 UNICODE_STRING SmssName
, Environment
, SystemDriveString
;
362 PVOID EnvironmentPtr
= NULL
;
364 /* Allocate memory for the process parameters */
365 Size
= sizeof(RTL_USER_PROCESS_PARAMETERS
) +
366 ((MAX_PATH
* 6) * sizeof(WCHAR
));
367 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
368 (PVOID
)&ProcessParameters
,
373 if (!NT_SUCCESS(Status
))
376 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
379 /* Setup the basic header, and give the process the low 1MB to itself */
380 ProcessParameters
->Length
= Size
;
381 ProcessParameters
->MaximumLength
= Size
;
382 ProcessParameters
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
383 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
385 /* Allocate a page for the environment */
387 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
393 if (!NT_SUCCESS(Status
))
396 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
399 /* Write the pointer */
400 ProcessParameters
->Environment
= EnvironmentPtr
;
402 /* Make a buffer for the DOS path */
403 p
= (PWSTR
)(ProcessParameters
+ 1);
404 ProcessParameters
->CurrentDirectory
.DosPath
.Buffer
= p
;
406 CurrentDirectory
.DosPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
408 /* Copy the DOS path */
409 RtlCopyUnicodeString(&ProcessParameters
->CurrentDirectory
.DosPath
,
412 /* Make a buffer for the DLL Path */
413 p
= (PWSTR
)((PCHAR
)ProcessParameters
->CurrentDirectory
.DosPath
.Buffer
+
414 ProcessParameters
->CurrentDirectory
.DosPath
.MaximumLength
);
415 ProcessParameters
->DllPath
.Buffer
= p
;
416 ProcessParameters
->DllPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
418 /* Copy the DLL path and append the system32 directory */
419 RtlCopyUnicodeString(&ProcessParameters
->DllPath
,
420 &ProcessParameters
->CurrentDirectory
.DosPath
);
421 RtlAppendUnicodeToString(&ProcessParameters
->DllPath
, L
"\\System32");
423 /* Make a buffer for the image name */
424 p
= (PWSTR
)((PCHAR
)ProcessParameters
->DllPath
.Buffer
+
425 ProcessParameters
->DllPath
.MaximumLength
);
426 ProcessParameters
->ImagePathName
.Buffer
= p
;
427 ProcessParameters
->ImagePathName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
429 /* Make sure the buffer is a valid string which within the given length */
430 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
431 ((NtInitialUserProcessBufferLength
!= -1) &&
432 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
433 (NtInitialUserProcessBufferLength
>
434 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
436 /* Invalid initial process string, bugcheck */
437 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
,
438 (ULONG_PTR
)STATUS_INVALID_PARAMETER
,
439 NtInitialUserProcessBufferType
,
440 NtInitialUserProcessBufferLength
,
441 sizeof(NtInitialUserProcessBuffer
));
444 /* Cut out anything after a space */
445 p
= NtInitialUserProcessBuffer
;
446 while (*p
&& *p
!= L
' ') p
++;
448 /* Set the image path length */
449 ProcessParameters
->ImagePathName
.Length
=
450 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
452 /* Copy the actual buffer */
453 RtlCopyMemory(ProcessParameters
->ImagePathName
.Buffer
,
454 NtInitialUserProcessBuffer
,
455 ProcessParameters
->ImagePathName
.Length
);
457 /* Null-terminate it */
459 ImagePathName
.Buffer
[ProcessParameters
->ImagePathName
.Length
/
460 sizeof(WCHAR
)] = UNICODE_NULL
;
462 /* Make a buffer for the command line */
463 p
= (PWSTR
)((PCHAR
)ProcessParameters
->ImagePathName
.Buffer
+
464 ProcessParameters
->ImagePathName
.MaximumLength
);
465 ProcessParameters
->CommandLine
.Buffer
= p
;
466 ProcessParameters
->CommandLine
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
468 /* Add the image name to the command line */
469 RtlAppendUnicodeToString(&ProcessParameters
->CommandLine
,
470 NtInitialUserProcessBuffer
);
472 /* Create the environment string */
473 RtlInitEmptyUnicodeString(&Environment
,
474 ProcessParameters
->Environment
,
477 /* Append the DLL path to it */
478 RtlAppendUnicodeToString(&Environment
, L
"Path=" );
479 RtlAppendUnicodeStringToString(&Environment
, &ProcessParameters
->DllPath
);
480 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
482 /* Create the system drive string */
483 SystemDriveString
= NtSystemRoot
;
484 SystemDriveString
.Length
= 2 * sizeof(WCHAR
);
486 /* Append it to the environment */
487 RtlAppendUnicodeToString(&Environment
, L
"SystemDrive=");
488 RtlAppendUnicodeStringToString(&Environment
, &SystemDriveString
);
489 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
491 /* Append the system root to the environment */
492 RtlAppendUnicodeToString(&Environment
, L
"SystemRoot=");
493 RtlAppendUnicodeStringToString(&Environment
, &NtSystemRoot
);
494 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
496 /* Create SMSS process */
497 SmssName
= ProcessParameters
->ImagePathName
;
498 Status
= RtlCreateUserProcess(&SmssName
,
499 OBJ_CASE_INSENSITIVE
,
500 RtlDeNormalizeProcessParams(
508 &ProcessInformation
);
509 if (!NT_SUCCESS(Status
))
512 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
515 /* Resume the thread */
516 Status
= ZwResumeThread(ProcessInformation
.ThreadHandle
, NULL
);
517 if (!NT_SUCCESS(Status
))
520 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
524 *ProcessHandle
= ProcessInformation
.ProcessHandle
;
525 *ThreadHandle
= ProcessInformation
.ThreadHandle
;
526 return STATUS_SUCCESS
;
531 ExComputeTickCountMultiplier(IN ULONG ClockIncrement
)
533 ULONG MsRemainder
= 0, MsIncrement
;
534 ULONG IncrementRemainder
;
537 /* Count the number of milliseconds for each clock interrupt */
538 MsIncrement
= ClockIncrement
/ (10 * 1000);
540 /* Count the remainder from the division above, with 24-bit precision */
541 IncrementRemainder
= ClockIncrement
- (MsIncrement
* (10 * 1000));
542 for (i
= 0; i
< 24; i
++)
544 /* Shift the remainders */
546 IncrementRemainder
<<= 1;
548 /* Check if we've went past 1 ms */
549 if (IncrementRemainder
>= (10 * 1000))
551 /* Increase the remainder by one, and substract from increment */
552 IncrementRemainder
-= (10 * 1000);
557 /* Return the increment */
558 return (MsIncrement
<< 24) | MsRemainder
;
563 ExpInitSystemPhase0(VOID
)
565 /* Initialize EXRESOURCE Support */
566 ExpResourceInitialization();
568 /* Initialize the environment lock */
569 ExInitializeFastMutex(&ExpEnvironmentLock
);
571 /* Initialize the lookaside lists and locks */
572 ExpInitLookasideLists();
574 /* Initialize the Firmware Table resource and listhead */
575 InitializeListHead(&ExpFirmwareTableProviderListHead
);
576 ExInitializeResourceLite(&ExpFirmwareTableResource
);
578 /* Set the suite mask to maximum and return */
579 ExSuiteMask
= 0xFFFFFFFF;
585 ExpInitSystemPhase1(VOID
)
587 /* Initialize worker threads */
588 ExpInitializeWorkerThreads();
590 /* Initialize pushlocks */
591 ExpInitializePushLocks();
593 /* Initialize events and event pairs */
594 ExpInitializeEventImplementation();
595 ExpInitializeEventPairImplementation();
597 /* Initialize callbacks */
598 ExpInitializeCallbacks();
600 /* Initialize mutants */
601 ExpInitializeMutantImplementation();
603 /* Initialize semaphores */
604 ExpInitializeSemaphoreImplementation();
606 /* Initialize timers */
607 ExpInitializeTimerImplementation();
609 /* Initialize profiling */
610 ExpInitializeProfileImplementation();
612 /* Initialize UUIDs */
615 /* Initialize Win32K */
624 /* Check the initialization phase */
625 switch (ExpInitializationPhase
)
630 return ExpInitSystemPhase0();
635 return ExpInitSystemPhase1();
639 /* Don't know any other phase! Bugcheck! */
640 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
647 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
649 PLOADER_PARAMETER_EXTENSION Extension
;
651 /* Get the loader extension */
652 Extension
= LoaderBlock
->Extension
;
654 /* Validate the size (larger structures are OK, we'll just ignore them) */
655 if (Extension
->Size
< sizeof(LOADER_PARAMETER_EXTENSION
)) return FALSE
;
657 /* Don't validate upper versions */
658 if (Extension
->MajorVersion
> 5) return TRUE
;
660 /* Fail if this is NT 4 */
661 if (Extension
->MajorVersion
< 5) return FALSE
;
663 /* Fail if this is XP */
664 if (Extension
->MinorVersion
< 2) return FALSE
;
666 /* This is 2003 or newer, approve it */
672 ExpInitializeExecutive(IN ULONG Cpu
,
673 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
675 PNLS_DATA_BLOCK NlsData
;
677 ANSI_STRING AnsiPath
;
680 /* Validate Loader */
681 if (!ExpIsLoaderValid(LoaderBlock
))
683 /* Invalid loader version */
684 KeBugCheckEx(MISMATCHED_HAL
,
686 LoaderBlock
->Extension
->Size
,
687 LoaderBlock
->Extension
->MajorVersion
,
688 LoaderBlock
->Extension
->MinorVersion
);
691 /* Initialize PRCB pool lookaside pointers */
692 ExInitPoolLookasidePointers();
694 /* Check if this is an application CPU */
697 /* Then simply initialize it with HAL */
698 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
700 /* Initialization failed */
701 KeBugCheck(HAL_INITIALIZATION_FAILED
);
708 /* Assume no text-mode or remote boot */
709 ExpInTextModeSetup
= FALSE
;
710 IoRemoteBootClient
= FALSE
;
712 /* Check if we have a setup loader block */
713 if (LoaderBlock
->SetupLdrBlock
)
715 /* Check if this is text-mode setup */
716 if (LoaderBlock
->SetupLdrBlock
->Flags
& 1) ExpInTextModeSetup
= TRUE
;
718 /* Check if this is network boot */
719 if (LoaderBlock
->SetupLdrBlock
->Flags
& 2)
722 IoRemoteBootClient
= TRUE
;
724 /* Make sure we're actually booting off the network */
725 ASSERT(!_memicmp(LoaderBlock
->ArcBootDeviceName
, "net(0)", 6));
730 ExpInitializationPhase
= 0;
732 /* Setup NLS Base and offsets */
733 NlsData
= LoaderBlock
->NlsData
;
734 ExpNlsTableBase
= NlsData
->AnsiCodePageData
;
735 ExpAnsiCodePageDataOffset
= 0;
736 ExpOemCodePageDataOffset
= ((ULONG_PTR
)NlsData
->OemCodePageData
-
737 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
738 ExpUnicodeCaseTableDataOffset
= ((ULONG_PTR
)NlsData
->UnicodeCodePageData
-
739 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
741 /* Initialize the NLS Tables */
742 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
743 ExpAnsiCodePageDataOffset
),
744 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
745 ExpOemCodePageDataOffset
),
746 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
747 ExpUnicodeCaseTableDataOffset
),
749 RtlResetRtlTranslations(&ExpNlsTableInfo
);
751 /* Now initialize the HAL */
752 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
754 /* HAL failed to initialize, bugcheck */
755 KeBugCheck(HAL_INITIALIZATION_FAILED
);
758 /* Make sure interrupts are active now */
761 /* Clear the crypto exponent */
762 SharedUserData
->CryptoExponent
= 0;
764 /* Set global flags for the checked build */
766 NtGlobalFlag
|= FLG_ENABLE_CLOSE_EXCEPTIONS
|
767 FLG_ENABLE_KDEBUG_SYMBOL_LOAD
;
770 /* Setup NT System Root Path */
771 sprintf(Buffer
, "C:%s", LoaderBlock
->NtBootPathName
);
773 /* Convert to ANSI_STRING and null-terminate it */
774 RtlInitString(&AnsiPath
, Buffer
);
775 Buffer
[--AnsiPath
.Length
] = ANSI_NULL
;
777 /* Get the string from KUSER_SHARED_DATA's buffer */
778 RtlInitEmptyUnicodeString(&NtSystemRoot
,
779 SharedUserData
->NtSystemRoot
,
780 sizeof(SharedUserData
->NtSystemRoot
));
783 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &AnsiPath
, FALSE
);
784 if (!NT_SUCCESS(Status
)) KEBUGCHECK(SESSION3_INITIALIZATION_FAILED
);
786 /* Setup bugcheck messages */
787 KiInitializeBugCheck();
789 /* Initialize the executive at phase 0 */
790 if (!ExInitSystem()) KEBUGCHECK(PHASE0_INITIALIZATION_FAILED
);
792 /* Break into the Debugger if requested */
793 if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
795 /* Set system ranges */
796 SharedUserData
->Reserved1
= (ULONG_PTR
)MmHighestUserAddress
;
797 SharedUserData
->Reserved3
= (ULONG_PTR
)MmSystemRangeStart
;
799 /* Make a copy of the NLS Tables */
800 ExpInitNls(LoaderBlock
);
802 /* Initialize the Handle Table */
803 ExpInitializeHandleTables();
806 /* On checked builds, allocate the system call count table */
807 KeServiceDescriptorTable
[0].Count
=
808 ExAllocatePoolWithTag(NonPagedPool
,
809 KiServiceLimit
* sizeof(ULONG
),
810 TAG('C', 'a', 'l', 'l'));
812 /* Use it for the shadow table too */
813 KeServiceDescriptorTableShadow
[0].Count
= KeServiceDescriptorTable
[0].Count
;
815 /* Make sure allocation succeeded */
816 if (KeServiceDescriptorTable
[0].Count
)
818 /* Zero the call counts to 0 */
819 RtlZeroMemory(KeServiceDescriptorTable
[0].Count
,
820 KiServiceLimit
* sizeof(ULONG
));
824 /* Create the Basic Object Manager Types to allow new Object Types */
825 if (!ObInit()) KEBUGCHECK(OBJECT_INITIALIZATION_FAILED
);
827 /* Load basic Security for other Managers */
828 if (!SeInit()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED
);
830 /* Set up Region Maps, Sections and the Paging File */
833 /* Initialize the boot video. */
834 InbvDisplayInitialize();
836 /* Initialize the Process Manager */
837 if (!PsInitSystem()) KEBUGCHECK(PROCESS_INITIALIZATION_FAILED
);
839 /* Initialize the User-Mode Debugging Subsystem */
842 /* Calculate the tick count multiplier */
843 ExpTickCountMultiplier
= ExComputeTickCountMultiplier(KeMaximumIncrement
);
844 SharedUserData
->TickCountMultiplier
= ExpTickCountMultiplier
;
846 /* Set the OS Version */
847 SharedUserData
->NtMajorVersion
= NtMajorVersion
;
848 SharedUserData
->NtMinorVersion
= NtMinorVersion
;
850 /* Set the machine type */
852 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_I386
;
853 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_I386
;
854 #elif defined(_PPC_) // <3 Arty
855 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_POWERPC
;
856 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_POWERPC
;
858 #error "Unsupported ReactOS Target"
864 ExPhase2Init(PVOID Context
)
866 LARGE_INTEGER Timeout
;
867 HANDLE ProcessHandle
;
870 TIME_FIELDS TimeFields
;
871 LARGE_INTEGER SystemBootTime
, UniversalBootTime
;
874 ExpInitializationPhase
= 1;
876 /* Set us at maximum priority */
877 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY
);
879 /* Do Phase 1 HAL Initialization */
880 HalInitSystem(1, KeLoaderBlock
);
882 /* Check if GUI Boot is enabled */
883 if (strstr(KeLoaderBlock
->LoadOptions
, "NOGUIBOOT")) NoGuiBoot
= TRUE
;
885 /* Display the boot screen image if not disabled */
886 if (!ExpInTextModeSetup
) InbvDisplayInitialize2(NoGuiBoot
);
887 if (!NoGuiBoot
) InbvDisplayBootLogo();
889 /* Clear the screen to blue and display the boot notice and debug status */
890 if (NoGuiBoot
) ExpDisplayNotice();
891 KdInitSystem(2, KeLoaderBlock
);
893 /* Initialize Power Subsystem in Phase 0 */
894 PoInit(0, AcpiTableDetected
);
896 /* Query the clock */
897 if (HalQueryRealTimeClock(&TimeFields
))
899 /* Convert to time fields */
900 RtlTimeFieldsToTime(&TimeFields
, &SystemBootTime
);
901 UniversalBootTime
= SystemBootTime
;
903 #if 0 // FIXME: Won't work until we can read registry data here
904 /* FIXME: This assumes that the RTC is not already in GMT */
905 ExpTimeZoneBias
.QuadPart
= Int32x32To64(ExpLastTimeZoneBias
* 60,
908 /* Set the boot time-zone bias */
909 SharedUserData
->TimeZoneBias
.High2Time
= ExpTimeZoneBias
.HighPart
;
910 SharedUserData
->TimeZoneBias
.LowPart
= ExpTimeZoneBias
.LowPart
;
911 SharedUserData
->TimeZoneBias
.High1Time
= ExpTimeZoneBias
.HighPart
;
913 /* Convert the boot time to local time, and set it */
914 UniversalBootTime
.QuadPart
= SystemBootTime
.QuadPart
+
915 ExpTimeZoneBias
.QuadPart
;
917 KiSetSystemTime(&UniversalBootTime
);
919 /* Remember this as the boot time */
920 KeBootTime
= UniversalBootTime
;
923 /* The clock is ready now (FIXME: HACK FOR OLD HAL) */
924 KiClockSetupComplete
= TRUE
;
926 /* Initialize all processors */
927 HalAllProcessorsStarted();
929 /* Call OB initialization again */
930 if (!ObInit()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED
);
932 /* Initialize Basic System Objects and Worker Threads */
933 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 1, 0, 0, 0);
935 /* Initialize the later stages of the kernel */
936 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 2, 0, 0, 0);
938 /* Call KD Providers at Phase 1 */
939 if (!KdInitSystem(ExpInitializationPhase
, KeLoaderBlock
))
941 /* Failed, bugcheck */
942 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 3, 0, 0, 0);
945 /* Create SystemRoot Link */
946 Status
= ExpCreateSystemRootLink(KeLoaderBlock
);
947 if (!NT_SUCCESS(Status
))
949 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
952 /* Create NLS section */
953 ExpInitNls(KeLoaderBlock
);
955 /* Initialize Cache Views */
956 CcInitializeCacheManager();
958 /* Initialize the Registry */
959 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
961 /* Update timezone information */
962 ExRefreshTimeZoneInformation(&SystemBootTime
);
964 /* Initialize the File System Runtime Library */
967 /* Report all resources used by HAL */
968 HalReportResourceUsage();
973 /* Enter the kernel debugger before starting up the boot drivers */
974 if (KdDebuggerEnabled
&& KdpEarlyBreak
) DbgBreakPoint();
976 /* Initialize the I/O Subsystem */
977 if (!IoInitSystem(KeLoaderBlock
)) KeBugCheck(IO1_INITIALIZATION_FAILED
);
979 /* Unmap Low memory, and initialize the MPW and Balancer Thread */
984 ASSERT(Guard
== 0xCACA1234);
986 /* Initialize VDM support */
987 KeI386VdmInitialize();
989 /* Initialize Power Subsystem in Phase 1*/
990 PoInit(1, AcpiTableDetected
);
992 /* Initialize the Process Manager at Phase 1 */
993 if (!PsInitSystem()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
995 /* Launch initial process */
996 Status
= ExpLoadInitialProcess(&ProcessHandle
, &ThreadHandle
);
998 /* Wait 5 seconds for it to initialize */
999 Timeout
.QuadPart
= Int32x32To64(5, -10000000);
1000 Status
= ZwWaitForSingleObject(ProcessHandle
, FALSE
, &Timeout
);
1001 if (!NoGuiBoot
) InbvFinalizeBootLogo();
1002 if (Status
== STATUS_SUCCESS
)
1004 /* Bugcheck the system if SMSS couldn't initialize */
1005 KeBugCheck(SESSION5_INITIALIZATION_FAILED
);
1008 /* Close process handles */
1009 ZwClose(ThreadHandle
);
1010 ZwClose(ProcessHandle
);
1012 /* FIXME: We should free the initial process' memory!*/
1014 /* Increase init phase */
1015 ExpInitializationPhase
+= 1;
1017 /* Jump into zero page thread */
1018 MmZeroPageThreadMain(NULL
);