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 ******************************************************************/
15 //#include <ntoskrnl/cm/newcm.h>
16 #include "ntoskrnl/cm/cm.h"
18 /* DATA **********************************************************************/
20 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
23 ULONG NtMajorVersion
= 5;
24 ULONG NtMinorVersion
= 0;
25 ULONG NtOSCSDVersion
= BUILD_OSCSDVERSION(4, 0);
26 ULONG NtBuildNumber
= KERNEL_VERSION_BUILD
;
30 /* Init flags and settings */
31 ULONG ExpInitializationPhase
;
32 BOOLEAN ExpInTextModeSetup
;
33 BOOLEAN IoRemoteBootClient
;
34 ULONG InitSafeBootMode
;
35 BOOLEAN InitIsWinPEMode
, InitWinPEModeType
;
38 UNICODE_STRING NtSystemRoot
;
40 /* NT Initial User Application */
41 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
42 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
44 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
46 /* Boot NLS information */
47 PVOID ExpNlsTableBase
;
48 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
49 ULONG ExpUnicodeCaseTableDataOffset
;
50 NLSTABLEINFO ExpNlsTableInfo
;
51 ULONG ExpNlsTableSize
;
52 PVOID ExpNlsSectionPointer
;
54 /* CMOS Timer Sanity */
55 BOOLEAN ExCmosClockIsSane
= TRUE
;
57 /* FUNCTIONS ****************************************************************/
61 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
63 UNICODE_STRING LinkName
;
64 OBJECT_ATTRIBUTES ObjectAttributes
;
69 ANSI_STRING TargetString
;
70 UNICODE_STRING TargetName
;
72 /* Initialize the ArcName tree */
73 RtlInitUnicodeString(&LinkName
, L
"\\ArcName");
74 InitializeObjectAttributes(&ObjectAttributes
,
76 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
78 SePublicDefaultUnrestrictedSd
);
81 Status
= NtCreateDirectoryObject(&LinkHandle
,
84 if (!NT_SUCCESS(Status
))
87 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
90 /* Close the LinkHandle */
93 /* Initialize the Device tree */
94 RtlInitUnicodeString(&LinkName
, L
"\\Device");
95 InitializeObjectAttributes(&ObjectAttributes
,
97 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
99 SePublicDefaultUnrestrictedSd
);
102 Status
= NtCreateDirectoryObject(&LinkHandle
,
103 DIRECTORY_ALL_ACCESS
,
105 if (!NT_SUCCESS(Status
))
108 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
111 /* Close the LinkHandle */
112 ObCloseHandle(LinkHandle
, KernelMode
);
114 /* Create the system root symlink name */
115 RtlInitAnsiString(&AnsiName
, "\\SystemRoot");
116 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &AnsiName
, TRUE
);
117 if (!NT_SUCCESS(Status
))
120 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
123 /* Initialize the attributes for the link */
124 InitializeObjectAttributes(&ObjectAttributes
,
126 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
128 SePublicDefaultUnrestrictedSd
);
130 /* Build the ARC name */
133 LoaderBlock
->ArcBootDeviceName
,
134 LoaderBlock
->NtBootPathName
);
135 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
137 /* Convert it to Unicode */
138 RtlInitString(&TargetString
, Buffer
);
139 Status
= RtlAnsiStringToUnicodeString(&TargetName
,
142 if (!NT_SUCCESS(Status
))
144 /* We failed, bugcheck */
145 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
149 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
150 SYMBOLIC_LINK_ALL_ACCESS
,
154 /* Free the strings */
155 RtlFreeUnicodeString(&LinkName
);
156 RtlFreeUnicodeString(&TargetName
);
158 /* Check if creating the link failed */
159 if (!NT_SUCCESS(Status
))
162 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
165 /* Close the handle and return success */
166 ObCloseHandle(LinkHandle
, KernelMode
);
167 return STATUS_SUCCESS
;
172 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
174 LARGE_INTEGER SectionSize
;
177 PVOID SectionBase
= NULL
;
179 LARGE_INTEGER SectionOffset
= {{0}};
180 PLIST_ENTRY ListHead
, NextEntry
;
181 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
183 /* Check if this is boot-time phase 0 initialization */
184 if (!ExpInitializationPhase
)
186 /* Loop the memory descriptors */
187 ListHead
= &LoaderBlock
->MemoryDescriptorListHead
;
188 NextEntry
= ListHead
->Flink
;
189 while (NextEntry
!= ListHead
)
191 /* Get the current block */
192 MdBlock
= CONTAINING_RECORD(NextEntry
,
193 MEMORY_ALLOCATION_DESCRIPTOR
,
196 /* Check if this is an NLS block */
197 if (MdBlock
->MemoryType
== LoaderNlsData
)
199 /* Increase the table size */
200 ExpNlsTableSize
+= MdBlock
->PageCount
* PAGE_SIZE
;
203 /* Go to the next block */
204 NextEntry
= MdBlock
->ListEntry
.Flink
;
208 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
209 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
211 ExpNlsTableSize
+= 2 * PAGE_SIZE
; // BIAS FOR FREELDR. HACK!
213 /* Allocate the a new buffer since loader memory will be freed */
214 ExpNlsTableBase
= ExAllocatePoolWithTag(NonPagedPool
,
216 TAG('R', 't', 'l', 'i'));
217 if (!ExpNlsTableBase
) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
219 /* Copy the codepage data in its new location. */
220 RtlCopyMemory(ExpNlsTableBase
,
221 LoaderBlock
->NlsData
->AnsiCodePageData
,
224 /* Initialize and reset the NLS TAbles */
225 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
226 ExpAnsiCodePageDataOffset
),
227 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
228 ExpOemCodePageDataOffset
),
229 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
230 ExpUnicodeCaseTableDataOffset
),
232 RtlResetRtlTranslations(&ExpNlsTableInfo
);
236 /* Set the section size */
237 SectionSize
.QuadPart
= ExpNlsTableSize
;
239 /* Create the NLS Section */
240 Status
= ZwCreateSection(&NlsSection
,
247 if (!NT_SUCCESS(Status
))
250 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
253 /* Get a pointer to the section */
254 Status
= ObReferenceObjectByHandle(NlsSection
,
258 &ExpNlsSectionPointer
,
261 if (!NT_SUCCESS(Status
))
264 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
267 /* Map the NLS Section in system space */
268 Status
= MmMapViewInSystemSpace(ExpNlsSectionPointer
,
271 if (!NT_SUCCESS(Status
))
274 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
277 /* Copy the codepage data in its new location. */
278 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
280 /* Free the previously allocated buffer and set the new location */
281 ExFreePool(ExpNlsTableBase
);
282 ExpNlsTableBase
= SectionBase
;
284 /* Initialize the NLS Tables */
285 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
286 ExpAnsiCodePageDataOffset
),
287 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
288 ExpOemCodePageDataOffset
),
289 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
290 ExpUnicodeCaseTableDataOffset
),
292 RtlResetRtlTranslations(&ExpNlsTableInfo
);
294 /* Reset the base to 0 */
297 /* Map the section in the system process */
298 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
299 PsGetCurrentProcess(),
308 if (!NT_SUCCESS(Status
))
311 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
314 /* Copy the table into the system process and set this as the base */
315 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
316 ExpNlsTableBase
= SectionBase
;
321 ExpLoadInitialProcess(IN OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation
)
323 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
327 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
328 UNICODE_STRING SmssName
, Environment
, SystemDriveString
;
329 PVOID EnvironmentPtr
= NULL
;
331 /* Allocate memory for the process parameters */
332 Size
= sizeof(RTL_USER_PROCESS_PARAMETERS
) +
333 ((MAX_PATH
* 6) * sizeof(WCHAR
));
334 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
335 (PVOID
)&ProcessParameters
,
340 if (!NT_SUCCESS(Status
))
343 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
346 /* Setup the basic header, and give the process the low 1MB to itself */
347 ProcessParameters
->Length
= Size
;
348 ProcessParameters
->MaximumLength
= Size
;
349 ProcessParameters
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
350 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
352 /* Allocate a page for the environment */
354 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
360 if (!NT_SUCCESS(Status
))
363 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
366 /* Write the pointer */
367 ProcessParameters
->Environment
= EnvironmentPtr
;
369 /* Make a buffer for the DOS path */
370 p
= (PWSTR
)(ProcessParameters
+ 1);
371 ProcessParameters
->CurrentDirectory
.DosPath
.Buffer
= p
;
373 CurrentDirectory
.DosPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
375 /* Copy the DOS path */
376 RtlCopyUnicodeString(&ProcessParameters
->CurrentDirectory
.DosPath
,
379 /* Make a buffer for the DLL Path */
380 p
= (PWSTR
)((PCHAR
)ProcessParameters
->CurrentDirectory
.DosPath
.Buffer
+
381 ProcessParameters
->CurrentDirectory
.DosPath
.MaximumLength
);
382 ProcessParameters
->DllPath
.Buffer
= p
;
383 ProcessParameters
->DllPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
385 /* Copy the DLL path and append the system32 directory */
386 RtlCopyUnicodeString(&ProcessParameters
->DllPath
,
387 &ProcessParameters
->CurrentDirectory
.DosPath
);
388 RtlAppendUnicodeToString(&ProcessParameters
->DllPath
, L
"\\System32");
390 /* Make a buffer for the image name */
391 p
= (PWSTR
)((PCHAR
)ProcessParameters
->DllPath
.Buffer
+
392 ProcessParameters
->DllPath
.MaximumLength
);
393 ProcessParameters
->ImagePathName
.Buffer
= p
;
394 ProcessParameters
->ImagePathName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
396 /* Make sure the buffer is a valid string which within the given length */
397 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
398 ((NtInitialUserProcessBufferLength
!= -1) &&
399 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
400 (NtInitialUserProcessBufferLength
>
401 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
403 /* Invalid initial process string, bugcheck */
404 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
,
405 (ULONG_PTR
)STATUS_INVALID_PARAMETER
,
406 NtInitialUserProcessBufferType
,
407 NtInitialUserProcessBufferLength
,
408 sizeof(NtInitialUserProcessBuffer
));
411 /* Cut out anything after a space */
412 p
= NtInitialUserProcessBuffer
;
413 while (*p
&& *p
!= L
' ') p
++;
415 /* Set the image path length */
416 ProcessParameters
->ImagePathName
.Length
=
417 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
419 /* Copy the actual buffer */
420 RtlCopyMemory(ProcessParameters
->ImagePathName
.Buffer
,
421 NtInitialUserProcessBuffer
,
422 ProcessParameters
->ImagePathName
.Length
);
424 /* Null-terminate it */
426 ImagePathName
.Buffer
[ProcessParameters
->ImagePathName
.Length
/
427 sizeof(WCHAR
)] = UNICODE_NULL
;
429 /* Make a buffer for the command line */
430 p
= (PWSTR
)((PCHAR
)ProcessParameters
->ImagePathName
.Buffer
+
431 ProcessParameters
->ImagePathName
.MaximumLength
);
432 ProcessParameters
->CommandLine
.Buffer
= p
;
433 ProcessParameters
->CommandLine
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
435 /* Add the image name to the command line */
436 RtlAppendUnicodeToString(&ProcessParameters
->CommandLine
,
437 NtInitialUserProcessBuffer
);
439 /* Create the environment string */
440 RtlInitEmptyUnicodeString(&Environment
,
441 ProcessParameters
->Environment
,
444 /* Append the DLL path to it */
445 RtlAppendUnicodeToString(&Environment
, L
"Path=" );
446 RtlAppendUnicodeStringToString(&Environment
, &ProcessParameters
->DllPath
);
447 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
449 /* Create the system drive string */
450 SystemDriveString
= NtSystemRoot
;
451 SystemDriveString
.Length
= 2 * sizeof(WCHAR
);
453 /* Append it to the environment */
454 RtlAppendUnicodeToString(&Environment
, L
"SystemDrive=");
455 RtlAppendUnicodeStringToString(&Environment
, &SystemDriveString
);
456 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
458 /* Append the system root to the environment */
459 RtlAppendUnicodeToString(&Environment
, L
"SystemRoot=");
460 RtlAppendUnicodeStringToString(&Environment
, &NtSystemRoot
);
461 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
463 /* Create SMSS process */
464 SmssName
= ProcessParameters
->ImagePathName
;
465 Status
= RtlCreateUserProcess(&SmssName
,
466 OBJ_CASE_INSENSITIVE
,
467 RtlDeNormalizeProcessParams(
476 if (!NT_SUCCESS(Status
))
479 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
482 /* Resume the thread */
483 Status
= ZwResumeThread(ProcessInformation
->ThreadHandle
, NULL
);
484 if (!NT_SUCCESS(Status
))
487 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
491 return STATUS_SUCCESS
;
496 ExComputeTickCountMultiplier(IN ULONG ClockIncrement
)
498 ULONG MsRemainder
= 0, MsIncrement
;
499 ULONG IncrementRemainder
;
502 /* Count the number of milliseconds for each clock interrupt */
503 MsIncrement
= ClockIncrement
/ (10 * 1000);
505 /* Count the remainder from the division above, with 24-bit precision */
506 IncrementRemainder
= ClockIncrement
- (MsIncrement
* (10 * 1000));
507 for (i
= 0; i
< 24; i
++)
509 /* Shift the remainders */
511 IncrementRemainder
<<= 1;
513 /* Check if we've went past 1 ms */
514 if (IncrementRemainder
>= (10 * 1000))
516 /* Increase the remainder by one, and substract from increment */
517 IncrementRemainder
-= (10 * 1000);
522 /* Return the increment */
523 return (MsIncrement
<< 24) | MsRemainder
;
528 ExpInitSystemPhase0(VOID
)
530 /* Initialize EXRESOURCE Support */
531 ExpResourceInitialization();
533 /* Initialize the environment lock */
534 ExInitializeFastMutex(&ExpEnvironmentLock
);
536 /* Initialize the lookaside lists and locks */
537 ExpInitLookasideLists();
539 /* Initialize the Firmware Table resource and listhead */
540 InitializeListHead(&ExpFirmwareTableProviderListHead
);
541 ExInitializeResourceLite(&ExpFirmwareTableResource
);
543 /* Set the suite mask to maximum and return */
544 ExSuiteMask
= 0xFFFFFFFF;
550 ExpInitSystemPhase1(VOID
)
552 /* Initialize worker threads */
553 ExpInitializeWorkerThreads();
555 /* Initialize pushlocks */
556 ExpInitializePushLocks();
558 /* Initialize events and event pairs */
559 ExpInitializeEventImplementation();
560 ExpInitializeEventPairImplementation();
562 /* Initialize callbacks */
563 ExpInitializeCallbacks();
565 /* Initialize mutants */
566 ExpInitializeMutantImplementation();
568 /* Initialize semaphores */
569 ExpInitializeSemaphoreImplementation();
571 /* Initialize timers */
572 ExpInitializeTimerImplementation();
574 /* Initialize profiling */
575 ExpInitializeProfileImplementation();
577 /* Initialize UUIDs */
580 /* Initialize Win32K */
589 /* Check the initialization phase */
590 switch (ExpInitializationPhase
)
595 return ExpInitSystemPhase0();
600 return ExpInitSystemPhase1();
604 /* Don't know any other phase! Bugcheck! */
605 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
612 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
614 PLOADER_PARAMETER_EXTENSION Extension
;
616 /* Get the loader extension */
617 Extension
= LoaderBlock
->Extension
;
619 /* Validate the size (larger structures are OK, we'll just ignore them) */
620 if (Extension
->Size
< sizeof(LOADER_PARAMETER_EXTENSION
)) return FALSE
;
622 /* Don't validate upper versions */
623 if (Extension
->MajorVersion
> 5) return TRUE
;
625 /* Fail if this is NT 4 */
626 if (Extension
->MajorVersion
< 5) return FALSE
;
628 /* Fail if this is XP */
629 if (Extension
->MinorVersion
< 2) return FALSE
;
631 /* This is 2003 or newer, approve it */
637 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
640 PLIST_ENTRY NextEntry
;
643 PLDR_DATA_TABLE_ENTRY LdrEntry
;
644 BOOLEAN OverFlow
= FALSE
;
645 CHAR NameBuffer
[256];
646 ANSI_STRING SymbolString
;
648 /* Loop the driver list */
649 NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
650 while (NextEntry
!= &LoaderBlock
->LoadOrderListHead
)
652 /* Skip the first two images */
656 LdrEntry
= CONTAINING_RECORD(NextEntry
,
657 LDR_DATA_TABLE_ENTRY
,
659 if (LdrEntry
->FullDllName
.Buffer
[0] == L
'\\')
661 /* We have a name, read its data */
662 Name
= LdrEntry
->FullDllName
.Buffer
;
663 Length
= LdrEntry
->FullDllName
.Length
/ sizeof(WCHAR
);
665 /* Check if our buffer can hold it */
666 if (sizeof(NameBuffer
) < Length
+ sizeof(ANSI_NULL
))
674 for (Count
= 0; Count
< Length
; Count
++, Name
++)
676 /* Copy the character */
677 NameBuffer
[Count
] = (CHAR
)*Name
;
681 NameBuffer
[Count
] = ANSI_NULL
;
686 /* This should be a driver, check if it fits */
687 if (sizeof(NameBuffer
) <
688 (sizeof("\\System32\\Drivers\\") +
689 NtSystemRoot
.Length
/ sizeof(WCHAR
) - sizeof(UNICODE_NULL
) +
690 LdrEntry
->BaseDllName
.Length
/ sizeof(WCHAR
) +
693 /* Buffer too small */
698 /* Otherwise build the name. HACKED for GCC :( */
700 "%c\\System32\\Drivers\\%S",
701 SharedUserData
->NtSystemRoot
[2],
702 LdrEntry
->BaseDllName
.Buffer
);
706 /* Check if the buffer was ok */
709 /* Initialize the ANSI_STRING for the debugger */
710 RtlInitString(&SymbolString
, NameBuffer
);
712 /* Load the symbols */
713 DbgLoadImageSymbols(&SymbolString
,
719 /* Go to the next entry */
721 NextEntry
= NextEntry
->Flink
;
724 /* Check if we should break after symbol load */
725 if (KdBreakAfterSymbolLoad
) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
730 ExpInitializeExecutive(IN ULONG Cpu
,
731 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
733 PNLS_DATA_BLOCK NlsData
;
735 ANSI_STRING AnsiPath
;
737 PCHAR CommandLine
, PerfMem
;
740 /* Validate Loader */
741 if (!ExpIsLoaderValid(LoaderBlock
))
743 /* Invalid loader version */
744 KeBugCheckEx(MISMATCHED_HAL
,
746 LoaderBlock
->Extension
->Size
,
747 LoaderBlock
->Extension
->MajorVersion
,
748 LoaderBlock
->Extension
->MinorVersion
);
751 /* Initialize PRCB pool lookaside pointers */
752 ExInitPoolLookasidePointers();
754 /* Check if this is an application CPU */
757 /* Then simply initialize it with HAL */
758 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
760 /* Initialization failed */
761 KeBugCheck(HAL_INITIALIZATION_FAILED
);
768 /* Assume no text-mode or remote boot */
769 ExpInTextModeSetup
= FALSE
;
770 IoRemoteBootClient
= FALSE
;
772 /* Check if we have a setup loader block */
773 if (LoaderBlock
->SetupLdrBlock
)
775 /* Check if this is text-mode setup */
776 if (LoaderBlock
->SetupLdrBlock
->Flags
& 1) ExpInTextModeSetup
= TRUE
;
778 /* Check if this is network boot */
779 if (LoaderBlock
->SetupLdrBlock
->Flags
& 2)
782 IoRemoteBootClient
= TRUE
;
784 /* Make sure we're actually booting off the network */
785 ASSERT(!_memicmp(LoaderBlock
->ArcBootDeviceName
, "net(0)", 6));
790 ExpInitializationPhase
= 0;
792 /* Get boot command line */
793 CommandLine
= LoaderBlock
->LoadOptions
;
796 /* Upcase it for comparison and check if we're in performance mode */
797 _strupr(CommandLine
);
798 PerfMem
= strstr(CommandLine
, "PERFMEM");
801 /* Check if the user gave a number of bytes to use */
802 PerfMem
= strstr(PerfMem
, "=");
805 /* Read the number of pages we'll use */
806 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
810 DPRINT1("BBT performance mode not yet supported."
811 "/PERFMEM option ignored.\n");
816 /* Check if we're burning memory */
817 PerfMem
= strstr(CommandLine
, "BURNMEMORY");
820 /* Check if the user gave a number of bytes to use */
821 PerfMem
= strstr(PerfMem
, "=");
824 /* Read the number of pages we'll use */
825 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
829 DPRINT1("Burnable memory support not yet present."
830 "/BURNMEM option ignored.\n");
836 /* Setup NLS Base and offsets */
837 NlsData
= LoaderBlock
->NlsData
;
838 ExpNlsTableBase
= NlsData
->AnsiCodePageData
;
839 ExpAnsiCodePageDataOffset
= 0;
840 ExpOemCodePageDataOffset
= ((ULONG_PTR
)NlsData
->OemCodePageData
-
841 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
842 ExpUnicodeCaseTableDataOffset
= ((ULONG_PTR
)NlsData
->UnicodeCodePageData
-
843 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
845 /* Initialize the NLS Tables */
846 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
847 ExpAnsiCodePageDataOffset
),
848 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
849 ExpOemCodePageDataOffset
),
850 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
851 ExpUnicodeCaseTableDataOffset
),
853 RtlResetRtlTranslations(&ExpNlsTableInfo
);
855 /* Now initialize the HAL */
856 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
858 /* HAL failed to initialize, bugcheck */
859 KeBugCheck(HAL_INITIALIZATION_FAILED
);
862 /* Make sure interrupts are active now */
865 /* Clear the crypto exponent */
866 SharedUserData
->CryptoExponent
= 0;
868 /* Set global flags for the checked build */
870 NtGlobalFlag
|= FLG_ENABLE_CLOSE_EXCEPTIONS
|
871 FLG_ENABLE_KDEBUG_SYMBOL_LOAD
;
874 /* Setup NT System Root Path */
875 sprintf(Buffer
, "C:%s", LoaderBlock
->NtBootPathName
);
877 /* Convert to ANSI_STRING and null-terminate it */
878 RtlInitString(&AnsiPath
, Buffer
);
879 Buffer
[--AnsiPath
.Length
] = ANSI_NULL
;
881 /* Get the string from KUSER_SHARED_DATA's buffer */
882 RtlInitEmptyUnicodeString(&NtSystemRoot
,
883 SharedUserData
->NtSystemRoot
,
884 sizeof(SharedUserData
->NtSystemRoot
));
887 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &AnsiPath
, FALSE
);
888 if (!NT_SUCCESS(Status
)) KEBUGCHECK(SESSION3_INITIALIZATION_FAILED
);
890 /* Setup bugcheck messages */
891 KiInitializeBugCheck();
893 /* Setup initial system settings (FIXME: Needs Cm Rewrite) */
894 CmGetSystemControlValues(LoaderBlock
->RegistryBase
, CmControlVector
);
896 /* Initialize the executive at phase 0 */
897 if (!ExInitSystem()) KEBUGCHECK(PHASE0_INITIALIZATION_FAILED
);
899 /* Load boot symbols */
900 ExpLoadBootSymbols(LoaderBlock
);
902 /* Set system ranges */
903 SharedUserData
->Reserved1
= (ULONG_PTR
)MmHighestUserAddress
;
904 SharedUserData
->Reserved3
= (ULONG_PTR
)MmSystemRangeStart
;
906 /* Make a copy of the NLS Tables */
907 ExpInitNls(LoaderBlock
);
909 /* Check if the user wants a kernel stack trace database */
910 if (NtGlobalFlag
& FLG_KERNEL_STACK_TRACE_DB
)
913 DPRINT1("Kernel-mode stack trace support not yet present."
914 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
917 /* Check if he wanted exception logging */
918 if (NtGlobalFlag
& FLG_ENABLE_EXCEPTION_LOGGING
)
921 DPRINT1("Kernel-mode exception logging support not yet present."
922 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
925 /* Initialize the Handle Table */
926 ExpInitializeHandleTables();
929 /* On checked builds, allocate the system call count table */
930 KeServiceDescriptorTable
[0].Count
=
931 ExAllocatePoolWithTag(NonPagedPool
,
932 KiServiceLimit
* sizeof(ULONG
),
933 TAG('C', 'a', 'l', 'l'));
935 /* Use it for the shadow table too */
936 KeServiceDescriptorTableShadow
[0].Count
= KeServiceDescriptorTable
[0].Count
;
938 /* Make sure allocation succeeded */
939 if (KeServiceDescriptorTable
[0].Count
)
941 /* Zero the call counts to 0 */
942 RtlZeroMemory(KeServiceDescriptorTable
[0].Count
,
943 KiServiceLimit
* sizeof(ULONG
));
947 /* Create the Basic Object Manager Types to allow new Object Types */
948 if (!ObInit()) KEBUGCHECK(OBJECT_INITIALIZATION_FAILED
);
950 /* Load basic Security for other Managers */
951 if (!SeInit()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED
);
953 /* Initialize the Process Manager */
954 if (!PsInitSystem(LoaderBlock
)) KEBUGCHECK(PROCESS_INITIALIZATION_FAILED
);
956 /* Initialize the PnP Manager */
957 if (!PpInitSystem()) KEBUGCHECK(PP0_INITIALIZATION_FAILED
);
959 /* Initialize the User-Mode Debugging Subsystem */
962 /* Calculate the tick count multiplier */
963 ExpTickCountMultiplier
= ExComputeTickCountMultiplier(KeMaximumIncrement
);
964 SharedUserData
->TickCountMultiplier
= ExpTickCountMultiplier
;
966 /* Set the OS Version */
967 SharedUserData
->NtMajorVersion
= NtMajorVersion
;
968 SharedUserData
->NtMinorVersion
= NtMinorVersion
;
970 /* Set the machine type */
972 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_I386
;
973 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_I386
;
974 #elif defined(_PPC_) // <3 Arty
975 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_POWERPC
;
976 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_POWERPC
;
978 #error "Unsupported ReactOS Target"
984 Phase1InitializationDiscard(PVOID Context
)
986 PLOADER_PARAMETER_BLOCK LoaderBlock
= Context
;
987 PCHAR CommandLine
, Y2KHackRequired
;
988 LARGE_INTEGER Timeout
;
990 TIME_FIELDS TimeFields
;
991 LARGE_INTEGER SystemBootTime
, UniversalBootTime
, OldTime
;
992 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
993 BOOLEAN SosEnabled
, NoGuiBoot
;
996 /* Allocate initial process information */
997 ProcessInfo
= ExAllocatePoolWithTag(NonPagedPool
,
998 sizeof(RTL_USER_PROCESS_INFORMATION
),
999 TAG('I', 'n', 'i', 't'));
1003 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 8, 0, 0);
1006 /* Set to phase 1 */
1007 ExpInitializationPhase
= 1;
1009 /* Set us at maximum priority */
1010 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY
);
1012 /* Do Phase 1 HAL Initialization */
1013 if (!HalInitSystem(1, LoaderBlock
)) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1015 /* Get the command line and upcase it */
1016 CommandLine
= _strupr(LoaderBlock
->LoadOptions
);
1018 /* Check if GUI Boot is enabled */
1019 NoGuiBoot
= (strstr(CommandLine
, "NOGUIBOOT")) ? TRUE
: FALSE
;
1021 /* Get the SOS setting */
1022 SosEnabled
= strstr(CommandLine
, "SOS") ? TRUE
: FALSE
;
1024 /* Setup the boot driver */
1025 InbvEnableBootDriver(!NoGuiBoot
);
1026 InbvDriverInitialize(LoaderBlock
, 18);
1028 /* Check if GUI boot is enabled */
1031 /* It is, display the boot logo and enable printing strings */
1032 InbvEnableDisplayString(SosEnabled
);
1033 DisplayBootBitmap(SosEnabled
);
1037 /* Release display ownership if not using GUI boot */
1038 InbvNotifyDisplayOwnershipLost(NULL
);
1040 /* Don't allow boot-time strings */
1041 InbvEnableDisplayString(FALSE
);
1044 /* Check if this is LiveCD (WinPE) mode */
1045 if (strstr(CommandLine
, "MININT"))
1047 /* Setup WinPE Settings */
1048 InitIsWinPEMode
= TRUE
;
1049 InitWinPEModeType
|= (strstr(CommandLine
, "INRAM")) ? 0x80000000 : 1;
1052 /* FIXME: Print product name, version, and build */
1054 /* Initialize Power Subsystem in Phase 0 */
1055 if (!PoInitSystem(0, AcpiTableDetected
)) KeBugCheck(INTERNAL_POWER_ERROR
);
1057 /* Check for Y2K hack */
1058 Y2KHackRequired
= strstr(CommandLine
, "YEAR");
1059 if (Y2KHackRequired
) Y2KHackRequired
= strstr(Y2KHackRequired
, "=");
1060 if (Y2KHackRequired
) YearHack
= atol(Y2KHackRequired
+ 1);
1062 /* Query the clock */
1063 if ((ExCmosClockIsSane
) && (HalQueryRealTimeClock(&TimeFields
)))
1065 /* Check if we're using the Y2K hack */
1066 if (Y2KHackRequired
) TimeFields
.Year
= (CSHORT
)YearHack
;
1068 /* Convert to time fields */
1069 RtlTimeFieldsToTime(&TimeFields
, &SystemBootTime
);
1070 UniversalBootTime
= SystemBootTime
;
1072 #if 0 // FIXME: Won't work until we can read registry data here
1073 /* FIXME: This assumes that the RTC is not already in GMT */
1074 ExpTimeZoneBias
.QuadPart
= Int32x32To64(ExpLastTimeZoneBias
* 60,
1077 /* Set the boot time-zone bias */
1078 SharedUserData
->TimeZoneBias
.High2Time
= ExpTimeZoneBias
.HighPart
;
1079 SharedUserData
->TimeZoneBias
.LowPart
= ExpTimeZoneBias
.LowPart
;
1080 SharedUserData
->TimeZoneBias
.High1Time
= ExpTimeZoneBias
.HighPart
;
1082 /* Convert the boot time to local time, and set it */
1083 UniversalBootTime
.QuadPart
= SystemBootTime
.QuadPart
+
1084 ExpTimeZoneBias
.QuadPart
;
1087 /* Update the system time */
1088 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1090 /* Remember this as the boot time */
1091 KeBootTime
= UniversalBootTime
;
1095 /* Initialize all processors */
1096 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1098 /* FIXME: Print CPU and Memory */
1100 /* Update the progress bar */
1101 InbvUpdateProgressBar(5);
1103 /* Call OB initialization again */
1104 if (!ObInit()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED
);
1106 /* Initialize Basic System Objects and Worker Threads */
1107 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 1, 0);
1109 /* Initialize the later stages of the kernel */
1110 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 2, 0);
1112 /* Call KD Providers at Phase 1 */
1113 if (!KdInitSystem(ExpInitializationPhase
, KeLoaderBlock
))
1115 /* Failed, bugcheck */
1116 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 3, 0);
1119 /* Initialize the SRM in Phase 1 */
1120 if (!SeInit()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED
);
1122 /* Update the progress bar */
1123 InbvUpdateProgressBar(10);
1125 /* Create SystemRoot Link */
1126 Status
= ExpCreateSystemRootLink(LoaderBlock
);
1127 if (!NT_SUCCESS(Status
))
1129 /* Failed to create the system root link */
1130 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1133 /* Set up Region Maps, Sections and the Paging File */
1134 if (!MmInitSystem(1, LoaderBlock
)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED
);
1136 /* Create NLS section */
1137 ExpInitNls(KeLoaderBlock
);
1139 /* Initialize Cache Views */
1140 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED
);
1142 /* Initialize the Registry */
1143 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
1145 /* Update progress bar */
1146 InbvUpdateProgressBar(15);
1148 /* Update timezone information */
1149 ExRefreshTimeZoneInformation(&SystemBootTime
);
1151 /* Initialize the File System Runtime Library */
1152 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED
);
1154 /* Report all resources used by HAL */
1155 HalReportResourceUsage();
1157 /* Call the debugger DLL once we have KD64 6.0 support */
1158 //KdDebuggerInitialize1(LoaderBlock);
1160 /* Setup PnP Manager in phase 1 */
1161 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED
);
1163 /* Update progress bar */
1164 InbvUpdateProgressBar(20);
1166 /* Initialize LPC */
1167 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED
);
1169 /* Initialize the I/O Subsystem */
1170 if (!IoInitSystem(KeLoaderBlock
)) KeBugCheck(IO1_INITIALIZATION_FAILED
);
1172 /* Unmap Low memory, and initialize the MPW and Balancer Thread */
1173 MmInitSystem(2, LoaderBlock
);
1175 /* Update progress bar */
1176 InbvUpdateProgressBar(80);
1178 /* Initialize VDM support */
1179 KeI386VdmInitialize();
1181 /* Initialize Power Subsystem in Phase 1*/
1182 if (!PoInitSystem(1, AcpiTableDetected
)) KeBugCheck(INTERNAL_POWER_ERROR
);
1184 /* Initialize the Process Manager at Phase 1 */
1185 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1187 /* Update progress bar */
1188 InbvUpdateProgressBar(85);
1190 /* Make sure nobody touches the loader block again */
1191 if (LoaderBlock
== KeLoaderBlock
) KeLoaderBlock
= NULL
;
1192 LoaderBlock
= Context
= NULL
;
1194 /* Update progress bar */
1195 InbvUpdateProgressBar(90);
1197 /* Launch initial process */
1198 Status
= ExpLoadInitialProcess(ProcessInfo
);
1200 /* Update progress bar */
1201 InbvUpdateProgressBar(100);
1203 /* Allow strings to be displayed */
1204 InbvEnableDisplayString(TRUE
);
1206 /* Wait 5 seconds for it to initialize */
1207 Timeout
.QuadPart
= Int32x32To64(5, -10000000);
1208 Status
= ZwWaitForSingleObject(ProcessInfo
->ProcessHandle
, FALSE
, &Timeout
);
1209 if (InbvBootDriverInstalled
) FinalizeBootLogo();
1211 if (Status
== STATUS_SUCCESS
)
1213 /* Bugcheck the system if SMSS couldn't initialize */
1214 KeBugCheck(SESSION5_INITIALIZATION_FAILED
);
1217 /* Close process handles */
1218 ZwClose(ProcessInfo
->ThreadHandle
);
1219 ZwClose(ProcessInfo
->ProcessHandle
);
1221 /* FIXME: We should free the initial process' memory!*/
1223 /* Increase init phase */
1224 ExpInitializationPhase
+= 1;
1226 /* Free the process information */
1227 ExFreePool(ProcessInfo
);
1232 Phase1Initialization(IN PVOID Context
)
1234 /* Do the .INIT part of Phase 1 which we can free later */
1235 Phase1InitializationDiscard(Context
);
1237 /* Jump into zero page thread */
1238 MmZeroPageThreadMain(NULL
);