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 "ntstrsafe.h"
17 typedef struct _INIT_BUFFER
19 WCHAR DebugBuffer
[256];
20 CHAR VersionBuffer
[256];
21 CHAR BootlogHeader
[256];
22 CHAR VersionNumber
[24];
23 RTL_USER_PROCESS_INFORMATION ProcessInfo
;
24 WCHAR RegistryBuffer
[256];
25 } INIT_BUFFER
, *PINIT_BUFFER
;
27 /* DATA **********************************************************************/
30 ULONG NtMajorVersion
= VER_PRODUCTMAJORVERSION
;
31 ULONG NtMinorVersion
= VER_PRODUCTMINORVERSION
;
33 ULONG NtBuildNumber
= VER_PRODUCTBUILD
| 0xC0000000;
35 ULONG NtBuildNumber
= VER_PRODUCTBUILD
;
43 ULONG CmNtSpBuildNumber
;
45 ULONG CmNtCSDReleaseType
;
46 UNICODE_STRING CmVersionString
;
47 UNICODE_STRING CmCSDVersionString
;
48 CHAR NtBuildLab
[] = KERNEL_VERSION_BUILD_STR
;
50 /* Init flags and settings */
51 ULONG ExpInitializationPhase
;
52 BOOLEAN ExpInTextModeSetup
;
53 BOOLEAN IoRemoteBootClient
;
54 ULONG InitSafeBootMode
;
55 BOOLEAN InitIsWinPEMode
, InitWinPEModeType
;
58 UNICODE_STRING NtSystemRoot
;
60 /* NT Initial User Application */
61 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
62 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
64 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
66 /* Boot NLS information */
67 PVOID ExpNlsTableBase
;
68 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
69 ULONG ExpUnicodeCaseTableDataOffset
;
70 NLSTABLEINFO ExpNlsTableInfo
;
71 SIZE_T ExpNlsTableSize
;
72 PVOID ExpNlsSectionPointer
;
74 /* CMOS Timer Sanity */
75 BOOLEAN ExCmosClockIsSane
= TRUE
;
76 BOOLEAN ExpRealTimeIsUniversal
;
78 /* FUNCTIONS ****************************************************************/
82 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
84 UNICODE_STRING LinkName
;
85 OBJECT_ATTRIBUTES ObjectAttributes
;
90 ANSI_STRING TargetString
;
91 UNICODE_STRING TargetName
;
93 /* Initialize the ArcName tree */
94 RtlInitUnicodeString(&LinkName
, L
"\\ArcName");
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
, 1, 0, 0);
111 /* Close the LinkHandle */
114 /* Initialize the Device tree */
115 RtlInitUnicodeString(&LinkName
, L
"\\Device");
116 InitializeObjectAttributes(&ObjectAttributes
,
118 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
120 SePublicDefaultUnrestrictedSd
);
123 Status
= NtCreateDirectoryObject(&LinkHandle
,
124 DIRECTORY_ALL_ACCESS
,
126 if (!NT_SUCCESS(Status
))
129 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
132 /* Close the LinkHandle */
133 ObCloseHandle(LinkHandle
, KernelMode
);
135 /* Create the system root symlink name */
136 RtlInitAnsiString(&AnsiName
, "\\SystemRoot");
137 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &AnsiName
, TRUE
);
138 if (!NT_SUCCESS(Status
))
141 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
144 /* Initialize the attributes for the link */
145 InitializeObjectAttributes(&ObjectAttributes
,
147 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
149 SePublicDefaultUnrestrictedSd
);
151 /* Build the ARC name */
154 LoaderBlock
->ArcBootDeviceName
,
155 LoaderBlock
->NtBootPathName
);
156 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
158 /* Convert it to Unicode */
159 RtlInitString(&TargetString
, Buffer
);
160 Status
= RtlAnsiStringToUnicodeString(&TargetName
,
163 if (!NT_SUCCESS(Status
))
165 /* We failed, bugcheck */
166 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
170 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
171 SYMBOLIC_LINK_ALL_ACCESS
,
175 /* Free the strings */
176 RtlFreeUnicodeString(&LinkName
);
177 RtlFreeUnicodeString(&TargetName
);
179 /* Check if creating the link failed */
180 if (!NT_SUCCESS(Status
))
183 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
186 /* Close the handle and return success */
187 ObCloseHandle(LinkHandle
, KernelMode
);
188 return STATUS_SUCCESS
;
193 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
195 LARGE_INTEGER SectionSize
;
198 PVOID SectionBase
= NULL
;
200 LARGE_INTEGER SectionOffset
= {{0}};
201 PLIST_ENTRY ListHead
, NextEntry
;
202 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
203 ULONG NlsTablesEncountered
= 0;
204 ULONG NlsTableSizes
[3]; /* 3 NLS tables */
206 /* Check if this is boot-time phase 0 initialization */
207 if (!ExpInitializationPhase
)
209 /* Loop the memory descriptors */
210 ListHead
= &LoaderBlock
->MemoryDescriptorListHead
;
211 NextEntry
= ListHead
->Flink
;
212 while (NextEntry
!= ListHead
)
214 /* Get the current block */
215 MdBlock
= CONTAINING_RECORD(NextEntry
,
216 MEMORY_ALLOCATION_DESCRIPTOR
,
219 /* Check if this is an NLS block */
220 if (MdBlock
->MemoryType
== LoaderNlsData
)
222 /* Increase the table size */
223 ExpNlsTableSize
+= MdBlock
->PageCount
* PAGE_SIZE
;
225 /* FreeLdr-specific */
226 NlsTableSizes
[NlsTablesEncountered
] = MdBlock
->PageCount
* PAGE_SIZE
;
227 NlsTablesEncountered
++;
228 ASSERT(NlsTablesEncountered
< 4);
231 /* Go to the next block */
232 NextEntry
= MdBlock
->ListEntry
.Flink
;
235 /* Allocate the a new buffer since loader memory will be freed */
236 ExpNlsTableBase
= ExAllocatePoolWithTag(NonPagedPool
,
238 TAG('R', 't', 'l', 'i'));
239 if (!ExpNlsTableBase
) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
241 /* Copy the codepage data in its new location. */
242 if (NlsTablesEncountered
== 1)
244 /* Ntldr-way boot process */
245 RtlCopyMemory(ExpNlsTableBase
,
246 LoaderBlock
->NlsData
->AnsiCodePageData
,
252 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
253 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
255 RtlCopyMemory(ExpNlsTableBase
,
256 LoaderBlock
->NlsData
->AnsiCodePageData
,
259 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0]),
260 LoaderBlock
->NlsData
->OemCodePageData
,
263 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0] +
265 LoaderBlock
->NlsData
->UnicodeCodePageData
,
270 /* Initialize and reset the NLS TAbles */
271 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
272 ExpAnsiCodePageDataOffset
),
273 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
274 ExpOemCodePageDataOffset
),
275 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
276 ExpUnicodeCaseTableDataOffset
),
278 RtlResetRtlTranslations(&ExpNlsTableInfo
);
282 /* Set the section size */
283 SectionSize
.QuadPart
= ExpNlsTableSize
;
285 /* Create the NLS Section */
286 Status
= ZwCreateSection(&NlsSection
,
293 if (!NT_SUCCESS(Status
))
296 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
299 /* Get a pointer to the section */
300 Status
= ObReferenceObjectByHandle(NlsSection
,
304 &ExpNlsSectionPointer
,
307 if (!NT_SUCCESS(Status
))
310 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
313 /* Map the NLS Section in system space */
314 Status
= MmMapViewInSystemSpace(ExpNlsSectionPointer
,
317 if (!NT_SUCCESS(Status
))
320 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
323 /* Copy the codepage data in its new location. */
324 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
326 /* Free the previously allocated buffer and set the new location */
327 ExFreePoolWithTag(ExpNlsTableBase
, TAG('R', 't', 'l', 'i'));
328 ExpNlsTableBase
= SectionBase
;
330 /* Initialize the NLS Tables */
331 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
332 ExpAnsiCodePageDataOffset
),
333 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
334 ExpOemCodePageDataOffset
),
335 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
336 ExpUnicodeCaseTableDataOffset
),
338 RtlResetRtlTranslations(&ExpNlsTableInfo
);
340 /* Reset the base to 0 */
343 /* Map the section in the system process */
344 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
345 PsGetCurrentProcess(),
354 if (!NT_SUCCESS(Status
))
357 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
360 /* Copy the table into the system process and set this as the base */
361 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
362 ExpNlsTableBase
= SectionBase
;
367 ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer
,
368 OUT PRTL_USER_PROCESS_PARAMETERS
*ProcessParameters
,
369 OUT PCHAR
*ProcessEnvironment
)
374 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
375 UNICODE_STRING SmssName
, Environment
, SystemDriveString
, DebugString
;
376 PVOID EnvironmentPtr
= NULL
;
377 PRTL_USER_PROCESS_INFORMATION ProcessInformation
;
378 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= NULL
;
380 NullString
.Length
= sizeof(WCHAR
);
382 /* Use the initial buffer, after the strings */
383 ProcessInformation
= &InitBuffer
->ProcessInfo
;
385 /* Allocate memory for the process parameters */
386 Size
= sizeof(*ProcessParams
) + ((MAX_PATH
* 6) * sizeof(WCHAR
));
387 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
388 (PVOID
*)&ProcessParams
,
393 if (!NT_SUCCESS(Status
))
395 /* Failed, display error */
396 p
= InitBuffer
->DebugBuffer
;
399 L
"INIT: Unable to allocate Process Parameters. 0x%lx",
401 RtlInitUnicodeString(&DebugString
, p
);
402 ZwDisplayString(&DebugString
);
404 /* Bugcheck the system */
405 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
408 /* Setup the basic header, and give the process the low 1MB to itself */
409 ProcessParams
->Length
= Size
;
410 ProcessParams
->MaximumLength
= Size
;
411 ProcessParams
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
412 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
414 /* Allocate a page for the environment */
416 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
422 if (!NT_SUCCESS(Status
))
424 /* Failed, display error */
425 p
= InitBuffer
->DebugBuffer
;
428 L
"INIT: Unable to allocate Process Environment. 0x%lx",
430 RtlInitUnicodeString(&DebugString
, p
);
431 ZwDisplayString(&DebugString
);
433 /* Bugcheck the system */
434 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
437 /* Write the pointer */
438 ProcessParams
->Environment
= EnvironmentPtr
;
440 /* Make a buffer for the DOS path */
441 p
= (PWSTR
)(ProcessParams
+ 1);
442 ProcessParams
->CurrentDirectory
.DosPath
.Buffer
= p
;
443 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
= MAX_PATH
*
446 /* Copy the DOS path */
447 RtlCopyUnicodeString(&ProcessParams
->CurrentDirectory
.DosPath
,
450 /* Make a buffer for the DLL Path */
451 p
= (PWSTR
)((PCHAR
)ProcessParams
->CurrentDirectory
.DosPath
.Buffer
+
452 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
);
453 ProcessParams
->DllPath
.Buffer
= p
;
454 ProcessParams
->DllPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
456 /* Copy the DLL path and append the system32 directory */
457 RtlCopyUnicodeString(&ProcessParams
->DllPath
,
458 &ProcessParams
->CurrentDirectory
.DosPath
);
459 RtlAppendUnicodeToString(&ProcessParams
->DllPath
, L
"\\System32");
461 /* Make a buffer for the image name */
462 p
= (PWSTR
)((PCHAR
)ProcessParams
->DllPath
.Buffer
+
463 ProcessParams
->DllPath
.MaximumLength
);
464 ProcessParams
->ImagePathName
.Buffer
= p
;
465 ProcessParams
->ImagePathName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
467 /* Make sure the buffer is a valid string which within the given length */
468 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
469 ((NtInitialUserProcessBufferLength
!= -1) &&
470 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
471 (NtInitialUserProcessBufferLength
>
472 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
474 /* Invalid initial process string, bugcheck */
475 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
,
476 STATUS_INVALID_PARAMETER
,
477 NtInitialUserProcessBufferType
,
478 NtInitialUserProcessBufferLength
,
479 sizeof(NtInitialUserProcessBuffer
));
482 /* Cut out anything after a space */
483 p
= NtInitialUserProcessBuffer
;
484 while ((*p
) && (*p
!= L
' ')) p
++;
486 /* Set the image path length */
487 ProcessParams
->ImagePathName
.Length
=
488 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
490 /* Copy the actual buffer */
491 RtlCopyMemory(ProcessParams
->ImagePathName
.Buffer
,
492 NtInitialUserProcessBuffer
,
493 ProcessParams
->ImagePathName
.Length
);
495 /* Null-terminate it */
496 ProcessParams
->ImagePathName
.Buffer
[ProcessParams
->ImagePathName
.Length
/
497 sizeof(WCHAR
)] = UNICODE_NULL
;
499 /* Make a buffer for the command line */
500 p
= (PWSTR
)((PCHAR
)ProcessParams
->ImagePathName
.Buffer
+
501 ProcessParams
->ImagePathName
.MaximumLength
);
502 ProcessParams
->CommandLine
.Buffer
= p
;
503 ProcessParams
->CommandLine
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
505 /* Add the image name to the command line */
506 RtlAppendUnicodeToString(&ProcessParams
->CommandLine
,
507 NtInitialUserProcessBuffer
);
509 /* Create the environment string */
510 RtlInitEmptyUnicodeString(&Environment
,
511 ProcessParams
->Environment
,
514 /* Append the DLL path to it */
515 RtlAppendUnicodeToString(&Environment
, L
"Path=" );
516 RtlAppendUnicodeStringToString(&Environment
, &ProcessParams
->DllPath
);
517 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
519 /* Create the system drive string */
520 SystemDriveString
= NtSystemRoot
;
521 SystemDriveString
.Length
= 2 * sizeof(WCHAR
);
523 /* Append it to the environment */
524 RtlAppendUnicodeToString(&Environment
, L
"SystemDrive=");
525 RtlAppendUnicodeStringToString(&Environment
, &SystemDriveString
);
526 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
528 /* Append the system root to the environment */
529 RtlAppendUnicodeToString(&Environment
, L
"SystemRoot=");
530 RtlAppendUnicodeStringToString(&Environment
, &NtSystemRoot
);
531 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
533 /* Prepare the prefetcher */
534 //CcPfBeginBootPhase(150);
536 /* Create SMSS process */
537 SmssName
= ProcessParams
->ImagePathName
;
538 Status
= RtlCreateUserProcess(&SmssName
,
539 OBJ_CASE_INSENSITIVE
,
540 RtlDeNormalizeProcessParams(ProcessParams
),
548 if (!NT_SUCCESS(Status
))
550 /* Failed, display error */
551 p
= InitBuffer
->DebugBuffer
;
554 L
"INIT: Unable to create Session Manager. 0x%lx",
556 RtlInitUnicodeString(&DebugString
, p
);
557 ZwDisplayString(&DebugString
);
559 /* Bugcheck the system */
560 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
563 /* Resume the thread */
564 Status
= ZwResumeThread(ProcessInformation
->ThreadHandle
, NULL
);
565 if (!NT_SUCCESS(Status
))
567 /* Failed, display error */
568 p
= InitBuffer
->DebugBuffer
;
571 L
"INIT: Unable to resume Session Manager. 0x%lx",
573 RtlInitUnicodeString(&DebugString
, p
);
574 ZwDisplayString(&DebugString
);
576 /* Bugcheck the system */
577 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
581 *ProcessParameters
= ProcessParams
;
582 *ProcessEnvironment
= EnvironmentPtr
;
587 ExComputeTickCountMultiplier(IN ULONG ClockIncrement
)
589 ULONG MsRemainder
= 0, MsIncrement
;
590 ULONG IncrementRemainder
;
593 /* Count the number of milliseconds for each clock interrupt */
594 MsIncrement
= ClockIncrement
/ (10 * 1000);
596 /* Count the remainder from the division above, with 24-bit precision */
597 IncrementRemainder
= ClockIncrement
- (MsIncrement
* (10 * 1000));
598 for (i
= 0; i
< 24; i
++)
600 /* Shift the remainders */
602 IncrementRemainder
<<= 1;
604 /* Check if we've went past 1 ms */
605 if (IncrementRemainder
>= (10 * 1000))
607 /* Increase the remainder by one, and substract from increment */
608 IncrementRemainder
-= (10 * 1000);
613 /* Return the increment */
614 return (MsIncrement
<< 24) | MsRemainder
;
619 ExpInitSystemPhase0(VOID
)
621 /* Initialize EXRESOURCE Support */
622 ExpResourceInitialization();
624 /* Initialize the environment lock */
625 ExInitializeFastMutex(&ExpEnvironmentLock
);
627 /* Initialize the lookaside lists and locks */
628 ExpInitLookasideLists();
630 /* Initialize the Firmware Table resource and listhead */
631 InitializeListHead(&ExpFirmwareTableProviderListHead
);
632 ExInitializeResourceLite(&ExpFirmwareTableResource
);
634 /* Set the suite mask to maximum and return */
635 ExSuiteMask
= 0xFFFFFFFF;
641 ExpInitSystemPhase1(VOID
)
643 /* Initialize worker threads */
644 ExpInitializeWorkerThreads();
646 /* Initialize pushlocks */
647 ExpInitializePushLocks();
649 /* Initialize events and event pairs */
650 ExpInitializeEventImplementation();
651 ExpInitializeEventPairImplementation();
653 /* Initialize callbacks */
654 ExpInitializeCallbacks();
656 /* Initialize mutants */
657 ExpInitializeMutantImplementation();
659 /* Initialize semaphores */
660 ExpInitializeSemaphoreImplementation();
662 /* Initialize timers */
663 ExpInitializeTimerImplementation();
665 /* Initialize profiling */
666 ExpInitializeProfileImplementation();
668 /* Initialize UUIDs */
671 /* Initialize Win32K */
680 /* Check the initialization phase */
681 switch (ExpInitializationPhase
)
686 return ExpInitSystemPhase0();
691 return ExpInitSystemPhase1();
695 /* Don't know any other phase! Bugcheck! */
696 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
703 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
705 PLOADER_PARAMETER_EXTENSION Extension
;
707 /* Get the loader extension */
708 Extension
= LoaderBlock
->Extension
;
710 /* Validate the size (larger structures are OK, we'll just ignore them) */
711 if (Extension
->Size
< sizeof(LOADER_PARAMETER_EXTENSION
)) return FALSE
;
713 /* Don't validate upper versions */
714 if (Extension
->MajorVersion
> VER_PRODUCTMAJORVERSION
) return TRUE
;
716 /* Fail if this is NT 4 */
717 if (Extension
->MajorVersion
< VER_PRODUCTMAJORVERSION
) return FALSE
;
719 /* Fail if this is XP */
720 if (Extension
->MinorVersion
< VER_PRODUCTMINORVERSION
) return FALSE
;
722 /* This is 2003 or newer, approve it */
728 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
731 PLIST_ENTRY NextEntry
;
734 PLDR_DATA_TABLE_ENTRY LdrEntry
;
735 BOOLEAN OverFlow
= FALSE
;
736 CHAR NameBuffer
[256];
737 ANSI_STRING SymbolString
;
739 /* Loop the driver list */
740 NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
741 while (NextEntry
!= &LoaderBlock
->LoadOrderListHead
)
743 /* Skip the first two images */
747 LdrEntry
= CONTAINING_RECORD(NextEntry
,
748 LDR_DATA_TABLE_ENTRY
,
750 if (LdrEntry
->FullDllName
.Buffer
[0] == L
'\\')
752 /* We have a name, read its data */
753 Name
= LdrEntry
->FullDllName
.Buffer
;
754 Length
= LdrEntry
->FullDllName
.Length
/ sizeof(WCHAR
);
756 /* Check if our buffer can hold it */
757 if (sizeof(NameBuffer
) < Length
+ sizeof(ANSI_NULL
))
768 /* Copy the character */
769 NameBuffer
[Count
++] = (CHAR
)*Name
++;
770 } while (Count
< Length
);
773 NameBuffer
[Count
] = ANSI_NULL
;
778 /* This should be a driver, check if it fits */
779 if (sizeof(NameBuffer
) <
780 (sizeof("\\System32\\Drivers\\") +
781 NtSystemRoot
.Length
/ sizeof(WCHAR
) - sizeof(UNICODE_NULL
) +
782 LdrEntry
->BaseDllName
.Length
/ sizeof(WCHAR
) +
785 /* Buffer too small */
791 /* Otherwise build the name. HACKED for GCC :( */
793 "%S\\System32\\Drivers\\%S",
794 &SharedUserData
->NtSystemRoot
[2],
795 LdrEntry
->BaseDllName
.Buffer
);
799 /* Check if the buffer was ok */
802 /* Initialize the ANSI_STRING for the debugger */
803 RtlInitString(&SymbolString
, NameBuffer
);
805 /* Load the symbols */
806 DbgLoadImageSymbols(&SymbolString
,
812 /* Go to the next entry */
814 NextEntry
= NextEntry
->Flink
;
820 ExpInitializeExecutive(IN ULONG Cpu
,
821 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
823 PNLS_DATA_BLOCK NlsData
;
825 ANSI_STRING AnsiPath
;
827 PCHAR CommandLine
, PerfMem
;
829 PLDR_DATA_TABLE_ENTRY NtosEntry
;
830 PRTL_MESSAGE_RESOURCE_ENTRY MsgEntry
;
831 ANSI_STRING CsdString
;
832 SIZE_T Remaining
= 0;
834 CHAR VersionBuffer
[65];
836 /* Validate Loader */
837 if (!ExpIsLoaderValid(LoaderBlock
))
839 /* Invalid loader version */
840 KeBugCheckEx(MISMATCHED_HAL
,
842 LoaderBlock
->Extension
->Size
,
843 LoaderBlock
->Extension
->MajorVersion
,
844 LoaderBlock
->Extension
->MinorVersion
);
847 /* Initialize PRCB pool lookaside pointers */
848 ExInitPoolLookasidePointers();
850 /* Check if this is an application CPU */
853 /* Then simply initialize it with HAL */
854 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
856 /* Initialization failed */
857 KeBugCheck(HAL_INITIALIZATION_FAILED
);
864 /* Assume no text-mode or remote boot */
865 ExpInTextModeSetup
= FALSE
;
866 IoRemoteBootClient
= FALSE
;
868 /* Check if we have a setup loader block */
869 if (LoaderBlock
->SetupLdrBlock
)
871 /* Check if this is text-mode setup */
872 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_TEXT_MODE
) ExpInTextModeSetup
= TRUE
;
874 /* Check if this is network boot */
875 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_REMOTE_BOOT
)
878 IoRemoteBootClient
= TRUE
;
880 /* Make sure we're actually booting off the network */
881 ASSERT(!_memicmp(LoaderBlock
->ArcBootDeviceName
, "net(0)", 6));
886 ExpInitializationPhase
= 0;
888 /* Get boot command line */
889 CommandLine
= LoaderBlock
->LoadOptions
;
892 /* Upcase it for comparison and check if we're in performance mode */
893 _strupr(CommandLine
);
894 PerfMem
= strstr(CommandLine
, "PERFMEM");
897 /* Check if the user gave a number of bytes to use */
898 PerfMem
= strstr(PerfMem
, "=");
901 /* Read the number of pages we'll use */
902 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
906 DPRINT1("BBT performance mode not yet supported."
907 "/PERFMEM option ignored.\n");
912 /* Check if we're burning memory */
913 PerfMem
= strstr(CommandLine
, "BURNMEMORY");
916 /* Check if the user gave a number of bytes to use */
917 PerfMem
= strstr(PerfMem
, "=");
920 /* Read the number of pages we'll use */
921 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
925 DPRINT1("Burnable memory support not yet present."
926 "/BURNMEM option ignored.\n");
932 /* Setup NLS Base and offsets */
933 NlsData
= LoaderBlock
->NlsData
;
934 ExpNlsTableBase
= NlsData
->AnsiCodePageData
;
935 ExpAnsiCodePageDataOffset
= 0;
936 ExpOemCodePageDataOffset
= ((ULONG_PTR
)NlsData
->OemCodePageData
-
937 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
938 ExpUnicodeCaseTableDataOffset
= ((ULONG_PTR
)NlsData
->UnicodeCodePageData
-
939 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
941 /* Initialize the NLS Tables */
942 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
943 ExpAnsiCodePageDataOffset
),
944 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
945 ExpOemCodePageDataOffset
),
946 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
947 ExpUnicodeCaseTableDataOffset
),
949 RtlResetRtlTranslations(&ExpNlsTableInfo
);
951 /* Now initialize the HAL */
952 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
954 /* HAL failed to initialize, bugcheck */
955 KeBugCheck(HAL_INITIALIZATION_FAILED
);
958 /* Make sure interrupts are active now */
961 /* Clear the crypto exponent */
962 SharedUserData
->CryptoExponent
= 0;
964 /* Set global flags for the checked build */
966 NtGlobalFlag
|= FLG_ENABLE_CLOSE_EXCEPTIONS
|
967 FLG_ENABLE_KDEBUG_SYMBOL_LOAD
;
970 /* Setup NT System Root Path */
971 sprintf(Buffer
, "C:%s", LoaderBlock
->NtBootPathName
);
973 /* Convert to ANSI_STRING and null-terminate it */
974 RtlInitString(&AnsiPath
, Buffer
);
975 Buffer
[--AnsiPath
.Length
] = ANSI_NULL
;
977 /* Get the string from KUSER_SHARED_DATA's buffer */
978 RtlInitEmptyUnicodeString(&NtSystemRoot
,
979 SharedUserData
->NtSystemRoot
,
980 sizeof(SharedUserData
->NtSystemRoot
));
983 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &AnsiPath
, FALSE
);
984 if (!NT_SUCCESS(Status
)) KeBugCheck(SESSION3_INITIALIZATION_FAILED
);
986 /* Setup bugcheck messages */
987 KiInitializeBugCheck();
989 /* Setup initial system settings */
990 CmGetSystemControlValues(LoaderBlock
->RegistryBase
, CmControlVector
);
992 /* Load static defaults for Service Pack 1 and add our SVN revision */
993 CmNtCSDVersion
= 0x100 | (KERNEL_VERSION_BUILD_HEX
<< 16);
994 CmNtCSDReleaseType
= 0;
996 /* Set Service Pack data for Service Pack 1 */
997 CmNtSpBuildNumber
= 1830;
998 if (!(CmNtCSDVersion
& 0xFFFF0000))
1000 /* Check the release type */
1001 if (CmNtCSDReleaseType
== 1) CmNtSpBuildNumber
|= 1830 << 16;
1004 /* Initialize the executive at phase 0 */
1005 if (!ExInitSystem()) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1007 /* Initialize the memory manager at phase 0 */
1008 if (!MmInitSystem(0, LoaderBlock
)) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1010 /* Load boot symbols */
1011 ExpLoadBootSymbols(LoaderBlock
);
1013 /* Check if we should break after symbol load */
1014 if (KdBreakAfterSymbolLoad
) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
1016 /* Check if this loader is compatible with NT 5.2 */
1017 if (LoaderBlock
->Extension
->Size
>= sizeof(LOADER_PARAMETER_EXTENSION
))
1019 /* Setup headless terminal settings */
1020 HeadlessInit(LoaderBlock
);
1023 /* Set system ranges */
1024 SharedUserData
->Reserved1
= (ULONG_PTR
)MmHighestUserAddress
;
1025 SharedUserData
->Reserved3
= (ULONG_PTR
)MmSystemRangeStart
;
1027 /* Make a copy of the NLS Tables */
1028 ExpInitNls(LoaderBlock
);
1030 /* Get the kernel's load entry */
1031 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1032 LDR_DATA_TABLE_ENTRY
,
1035 /* Check if this is a service pack */
1036 if (CmNtCSDVersion
& 0xFFFF)
1038 /* Get the service pack string */
1039 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1042 WINDOWS_NT_CSD_STRING
,
1044 if (NT_SUCCESS(Status
))
1046 /* Setup the string */
1047 RtlInitAnsiString(&CsdString
, MsgEntry
->Text
);
1049 /* Remove trailing newline */
1050 while ((CsdString
.Length
> 0) &&
1051 ((CsdString
.Buffer
[CsdString
.Length
- 1] == '\r') ||
1052 (CsdString
.Buffer
[CsdString
.Length
- 1] == '\n')))
1054 /* Skip the trailing character */
1058 /* Fill the buffer with version information */
1059 Status
= RtlStringCbPrintfA(Buffer
,
1063 (CmNtCSDVersion
& 0xFF00) >> 8,
1064 (CmNtCSDVersion
& 0xFF) ?
1065 'A' + (CmNtCSDVersion
& 0xFF) - 1 :
1070 /* Build default string */
1071 Status
= RtlStringCbPrintfA(Buffer
,
1077 /* Check for success */
1078 if (!NT_SUCCESS(Status
))
1081 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1086 /* Then this is a beta */
1087 Status
= RtlStringCbCopyExA(Buffer
,
1089 VER_PRODUCTBETA_STR
,
1093 if (!NT_SUCCESS(Status
))
1096 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1100 CmCSDVersionString
.MaximumLength
= sizeof(Buffer
) - (USHORT
)Remaining
;
1103 /* Check if we have an RC number */
1104 if (CmNtCSDVersion
& 0xFFFF0000)
1106 /* Check if we have no version data yet */
1110 Remaining
= sizeof(Buffer
);
1115 /* Add comma and space */
1116 Status
= RtlStringCbCatExA(Buffer
,
1122 if (!NT_SUCCESS(Status
))
1125 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1129 /* Add the version format string */
1130 Status
= RtlStringCbPrintfA(RcEnd
,
1133 (CmNtCSDVersion
& 0xFFFF0000) >> 16);
1134 if (!NT_SUCCESS(Status
))
1137 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1141 /* Now setup the final string */
1142 RtlInitAnsiString(&CsdString
, Buffer
);
1143 Status
= RtlAnsiStringToUnicodeString(&CmCSDVersionString
,
1146 if (!NT_SUCCESS(Status
))
1149 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1152 /* Add our version */
1153 Status
= RtlStringCbPrintfA(VersionBuffer
,
1154 sizeof(VersionBuffer
),
1156 VER_PRODUCTMAJORVERSION
,
1157 VER_PRODUCTMINORVERSION
);
1158 if (!NT_SUCCESS(Status
))
1161 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1164 /* Build the final version string */
1165 RtlCreateUnicodeStringFromAsciiz(&CmVersionString
, VersionBuffer
);
1167 /* Check if the user wants a kernel stack trace database */
1168 if (NtGlobalFlag
& FLG_KERNEL_STACK_TRACE_DB
)
1171 DPRINT1("Kernel-mode stack trace support not yet present."
1172 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
1175 /* Check if he wanted exception logging */
1176 if (NtGlobalFlag
& FLG_ENABLE_EXCEPTION_LOGGING
)
1179 DPRINT1("Kernel-mode exception logging support not yet present."
1180 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
1183 /* Initialize the Handle Table */
1184 ExpInitializeHandleTables();
1187 /* On checked builds, allocate the system call count table */
1188 KeServiceDescriptorTable
[0].Count
=
1189 ExAllocatePoolWithTag(NonPagedPool
,
1190 KiServiceLimit
* sizeof(ULONG
),
1191 TAG('C', 'a', 'l', 'l'));
1193 /* Use it for the shadow table too */
1194 KeServiceDescriptorTableShadow
[0].Count
= KeServiceDescriptorTable
[0].Count
;
1196 /* Make sure allocation succeeded */
1197 if (KeServiceDescriptorTable
[0].Count
)
1199 /* Zero the call counts to 0 */
1200 RtlZeroMemory(KeServiceDescriptorTable
[0].Count
,
1201 KiServiceLimit
* sizeof(ULONG
));
1205 /* Create the Basic Object Manager Types to allow new Object Types */
1206 if (!ObInitSystem()) KeBugCheck(OBJECT_INITIALIZATION_FAILED
);
1208 /* Load basic Security for other Managers */
1209 if (!SeInitSystem()) KeBugCheck(SECURITY_INITIALIZATION_FAILED
);
1211 /* Initialize the Process Manager */
1212 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS_INITIALIZATION_FAILED
);
1214 /* Initialize the PnP Manager */
1215 if (!PpInitSystem()) KeBugCheck(PP0_INITIALIZATION_FAILED
);
1217 /* Initialize the User-Mode Debugging Subsystem */
1220 /* Calculate the tick count multiplier */
1221 ExpTickCountMultiplier
= ExComputeTickCountMultiplier(KeMaximumIncrement
);
1222 SharedUserData
->TickCountMultiplier
= ExpTickCountMultiplier
;
1224 /* Set the OS Version */
1225 SharedUserData
->NtMajorVersion
= NtMajorVersion
;
1226 SharedUserData
->NtMinorVersion
= NtMinorVersion
;
1228 /* Set the machine type */
1230 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_I386
;
1231 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_I386
;
1232 #elif defined(_PPC_) // <3 Arty
1233 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_POWERPC
;
1234 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_POWERPC
;
1235 #elif defined(_MIPS_)
1236 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_R4000
;
1237 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_R4000
;
1238 #elif defined(_ARM_)
1239 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_ARM
;
1240 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_ARM
;
1241 #elif defined(_AMD64_)
1242 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_AMD64
;
1243 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_AMD64
;
1245 #error "Unsupported ReactOS Target"
1251 Phase1InitializationDiscard(IN PVOID Context
)
1253 PLOADER_PARAMETER_BLOCK LoaderBlock
= Context
;
1254 NTSTATUS Status
, MsgStatus
;
1255 TIME_FIELDS TimeFields
;
1256 LARGE_INTEGER SystemBootTime
, UniversalBootTime
, OldTime
, Timeout
;
1257 BOOLEAN SosEnabled
, NoGuiBoot
, ResetBias
= FALSE
, AlternateShell
= FALSE
;
1258 PLDR_DATA_TABLE_ENTRY NtosEntry
;
1259 PRTL_MESSAGE_RESOURCE_ENTRY MsgEntry
;
1260 PCHAR CommandLine
, Y2KHackRequired
, SafeBoot
, Environment
;
1261 PCHAR StringBuffer
, EndBuffer
, BeginBuffer
, MpString
= "";
1262 PINIT_BUFFER InitBuffer
;
1263 ANSI_STRING TempString
;
1264 ULONG LastTzBias
, Size
, YearHack
= 0, Disposition
, MessageCode
= 0;
1266 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
1267 KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo
;
1268 UNICODE_STRING KeyName
, DebugString
;
1269 OBJECT_ATTRIBUTES ObjectAttributes
;
1270 HANDLE KeyHandle
, OptionHandle
;
1271 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
1273 /* Allocate the initialization buffer */
1274 InitBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1275 sizeof(INIT_BUFFER
),
1276 TAG('I', 'n', 'i', 't'));
1280 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 8, 0, 0);
1283 /* Set to phase 1 */
1284 ExpInitializationPhase
= 1;
1286 /* Set us at maximum priority */
1287 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY
);
1289 /* Do Phase 1 HAL Initialization */
1290 if (!HalInitSystem(1, LoaderBlock
)) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1292 /* Get the command line and upcase it */
1293 CommandLine
= _strupr(LoaderBlock
->LoadOptions
);
1295 /* Check if GUI Boot is enabled */
1296 NoGuiBoot
= (strstr(CommandLine
, "NOGUIBOOT")) ? TRUE
: FALSE
;
1298 /* Get the SOS setting */
1299 SosEnabled
= strstr(CommandLine
, "SOS") ? TRUE
: FALSE
;
1301 /* Setup the boot driver */
1302 InbvEnableBootDriver(!NoGuiBoot
);
1303 InbvDriverInitialize(LoaderBlock
, 18);
1305 /* Check if GUI boot is enabled */
1308 /* It is, display the boot logo and enable printing strings */
1309 InbvEnableDisplayString(SosEnabled
);
1310 DisplayBootBitmap(SosEnabled
);
1314 /* Release display ownership if not using GUI boot */
1315 InbvNotifyDisplayOwnershipLost(NULL
);
1317 /* Don't allow boot-time strings */
1318 InbvEnableDisplayString(FALSE
);
1321 /* Check if this is LiveCD (WinPE) mode */
1322 if (strstr(CommandLine
, "MININT"))
1324 /* Setup WinPE Settings */
1325 InitIsWinPEMode
= TRUE
;
1326 InitWinPEModeType
|= (strstr(CommandLine
, "INRAM")) ? 0x80000000 : 1;
1329 /* Get the kernel's load entry */
1330 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1331 LDR_DATA_TABLE_ENTRY
,
1334 /* Find the banner message */
1335 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1341 /* Setup defaults and check if we have a version string */
1342 StringBuffer
= InitBuffer
->VersionBuffer
;
1343 BeginBuffer
= StringBuffer
;
1344 EndBuffer
= StringBuffer
;
1346 if (CmCSDVersionString
.Length
)
1348 /* Print the version string */
1349 Status
= RtlStringCbPrintfExA(StringBuffer
,
1355 &CmCSDVersionString
);
1356 if (!NT_SUCCESS(Status
))
1359 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1368 /* Null-terminate the string */
1369 *EndBuffer
++ = ANSI_NULL
;
1371 /* Build the version number */
1372 StringBuffer
= InitBuffer
->VersionNumber
;
1373 Status
= RtlStringCbPrintfA(StringBuffer
,
1376 VER_PRODUCTMAJORVERSION
,
1377 VER_PRODUCTMINORVERSION
);
1378 if (!NT_SUCCESS(Status
))
1381 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1384 /* Check if we had found a banner message */
1385 if (NT_SUCCESS(MsgStatus
))
1387 /* Create the banner message */
1388 Status
= RtlStringCbPrintfA(EndBuffer
,
1392 NtBuildNumber
& 0xFFFF,
1394 if (!NT_SUCCESS(Status
))
1397 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1402 /* Use hard-coded banner message */
1403 Status
= RtlStringCbCopyA(EndBuffer
, Length
, "REACTOS (R)\n");
1404 if (!NT_SUCCESS(Status
))
1407 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1411 /* Display the version string on-screen */
1412 InbvDisplayString(EndBuffer
);
1414 /* Initialize Power Subsystem in Phase 0 */
1415 if (!PoInitSystem(0, AcpiTableDetected
)) KeBugCheck(INTERNAL_POWER_ERROR
);
1417 /* Check for Y2K hack */
1418 Y2KHackRequired
= strstr(CommandLine
, "YEAR");
1419 if (Y2KHackRequired
) Y2KHackRequired
= strstr(Y2KHackRequired
, "=");
1420 if (Y2KHackRequired
) YearHack
= atol(Y2KHackRequired
+ 1);
1422 /* Query the clock */
1423 if ((ExCmosClockIsSane
) && (HalQueryRealTimeClock(&TimeFields
)))
1425 /* Check if we're using the Y2K hack */
1426 if (Y2KHackRequired
) TimeFields
.Year
= (CSHORT
)YearHack
;
1428 /* Convert to time fields */
1429 RtlTimeFieldsToTime(&TimeFields
, &SystemBootTime
);
1430 UniversalBootTime
= SystemBootTime
;
1432 /* Check if real time is GMT */
1433 if (!ExpRealTimeIsUniversal
)
1435 /* Check if we don't have a valid bias */
1436 if (ExpLastTimeZoneBias
== -1)
1440 ExpLastTimeZoneBias
= ExpAltTimeZoneBias
;
1443 /* Calculate the bias in seconds */
1444 ExpTimeZoneBias
.QuadPart
= Int32x32To64(ExpLastTimeZoneBias
* 60,
1447 /* Set the boot time-zone bias */
1448 SharedUserData
->TimeZoneBias
.High2Time
= ExpTimeZoneBias
.HighPart
;
1449 SharedUserData
->TimeZoneBias
.LowPart
= ExpTimeZoneBias
.LowPart
;
1450 SharedUserData
->TimeZoneBias
.High1Time
= ExpTimeZoneBias
.HighPart
;
1452 /* Convert the boot time to local time, and set it */
1453 UniversalBootTime
.QuadPart
= SystemBootTime
.QuadPart
+
1454 ExpTimeZoneBias
.QuadPart
;
1457 /* Update the system time */
1458 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1460 /* Do system callback */
1461 PoNotifySystemTimeSet();
1463 /* Remember this as the boot time */
1464 KeBootTime
= UniversalBootTime
;
1468 /* Initialize all processors */
1469 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1472 /* HACK: We should use RtlFindMessage and not only fallback to this */
1473 MpString
= "MultiProcessor Kernel\r\n";
1476 /* Setup the "MP" String */
1477 RtlInitAnsiString(&TempString
, MpString
);
1479 /* Make sure to remove the \r\n if we actually have a string */
1480 while ((TempString
.Length
> 0) &&
1481 ((TempString
.Buffer
[TempString
.Length
- 1] == '\r') ||
1482 (TempString
.Buffer
[TempString
.Length
- 1] == '\n')))
1484 /* Skip the trailing character */
1485 TempString
.Length
--;
1488 /* Get the information string from our resource file */
1489 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1492 KeNumberProcessors
> 1 ?
1493 WINDOWS_NT_INFO_STRING_PLURAL
:
1494 WINDOWS_NT_INFO_STRING
,
1497 /* Get total RAM size */
1498 Size
= MmNumberOfPhysicalPages
* PAGE_SIZE
/ 1024 / 1024;
1500 /* Create the string */
1501 StringBuffer
= InitBuffer
->VersionBuffer
;
1502 Status
= RtlStringCbPrintfA(StringBuffer
,
1504 NT_SUCCESS(MsgStatus
) ?
1506 "%u System Processor [%u MB Memory] %Z\n",
1510 if (!NT_SUCCESS(Status
))
1513 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
1516 /* Display RAM and CPU count */
1517 InbvDisplayString(StringBuffer
);
1519 /* Update the progress bar */
1520 InbvUpdateProgressBar(5);
1522 /* Call OB initialization again */
1523 if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED
);
1525 /* Initialize Basic System Objects and Worker Threads */
1526 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 1, 0);
1528 /* Initialize the later stages of the kernel */
1529 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 2, 0);
1531 /* Call KD Providers at Phase 1 */
1532 if (!KdInitSystem(ExpInitializationPhase
, KeLoaderBlock
))
1534 /* Failed, bugcheck */
1535 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 3, 0);
1538 /* Initialize the SRM in Phase 1 */
1539 if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED
);
1541 /* Update the progress bar */
1542 InbvUpdateProgressBar(10);
1544 /* Create SystemRoot Link */
1545 Status
= ExpCreateSystemRootLink(LoaderBlock
);
1546 if (!NT_SUCCESS(Status
))
1548 /* Failed to create the system root link */
1549 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1552 /* Set up Region Maps, Sections and the Paging File */
1553 if (!MmInitSystem(1, LoaderBlock
)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED
);
1555 /* Create NLS section */
1556 ExpInitNls(KeLoaderBlock
);
1558 /* Initialize Cache Views */
1559 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED
);
1561 /* Initialize the Registry */
1562 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
1564 /* Initialize Prefetcher */
1565 CcPfInitializePrefetcher();
1567 /* Update progress bar */
1568 InbvUpdateProgressBar(15);
1570 /* Update timezone information */
1571 LastTzBias
= ExpLastTimeZoneBias
;
1572 ExRefreshTimeZoneInformation(&SystemBootTime
);
1574 /* Check if we're resetting timezone data */
1577 /* Convert the local time to system time */
1578 ExLocalTimeToSystemTime(&SystemBootTime
, &UniversalBootTime
);
1579 KeBootTime
= UniversalBootTime
;
1582 /* Set the new time */
1583 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1587 /* Check if the timezone switched and update the time */
1588 if (LastTzBias
!= ExpLastTimeZoneBias
) ZwSetSystemTime(NULL
, NULL
);
1591 /* Initialize the File System Runtime Library */
1592 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED
);
1594 /* Initialize range lists */
1595 RtlInitializeRangeListPackage();
1597 /* Report all resources used by HAL */
1598 HalReportResourceUsage();
1600 /* Call the debugger DLL */
1601 KdDebuggerInitialize1(LoaderBlock
);
1603 /* Setup PnP Manager in phase 1 */
1604 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED
);
1606 /* Update progress bar */
1607 InbvUpdateProgressBar(20);
1609 /* Initialize LPC */
1610 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED
);
1612 /* Make sure we have a command line */
1615 /* Check if this is a safe mode boot */
1616 SafeBoot
= strstr(CommandLine
, "SAFEBOOT:");
1619 /* Check what kind of boot this is */
1621 if (!strncmp(SafeBoot
, "MINIMAL", 7))
1624 InitSafeBootMode
= 1;
1626 MessageCode
= BOOTING_IN_SAFEMODE_MINIMAL
;
1628 else if (!strncmp(SafeBoot
, "NETWORK", 7))
1630 /* With Networking */
1631 InitSafeBootMode
= 1;
1633 MessageCode
= BOOTING_IN_SAFEMODE_NETWORK
;
1635 else if (!strncmp(SafeBoot
, "DSREPAIR", 8))
1637 /* Domain Server Repair */
1638 InitSafeBootMode
= 3;
1640 MessageCode
= BOOTING_IN_SAFEMODE_DSREPAIR
;
1646 InitSafeBootMode
= 0;
1649 /* Check if there's any settings left */
1652 /* Check if an alternate shell was requested */
1653 if (!strncmp(SafeBoot
, "(ALTERNATESHELL)", 16))
1655 /* Remember this for later */
1656 AlternateShell
= TRUE
;
1660 /* Find the message to print out */
1661 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1666 if (NT_SUCCESS(Status
))
1669 InbvDisplayString(MsgEntry
->Text
);
1674 /* Make sure we have a command line */
1677 /* Check if bootlogging is enabled */
1678 if (strstr(CommandLine
, "BOOTLOG"))
1680 /* Find the message to print out */
1681 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1686 if (NT_SUCCESS(Status
))
1689 InbvDisplayString(MsgEntry
->Text
);
1692 /* Setup boot logging */
1693 //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader);
1697 /* Setup the Executive in Phase 2 */
1698 //ExInitSystemPhase2();
1700 /* Update progress bar */
1701 InbvUpdateProgressBar(25);
1704 /* No KD Time Slip is pending */
1705 KdpTimeSlipPending
= 0;
1708 /* Initialize in-place execution support */
1709 XIPInit(LoaderBlock
);
1711 /* Set maximum update to 75% */
1712 InbvSetProgressBarSubset(25, 75);
1714 /* Initialize the I/O Subsystem */
1715 if (!IoInitSystem(LoaderBlock
)) KeBugCheck(IO1_INITIALIZATION_FAILED
);
1717 /* Set maximum update to 100% */
1718 InbvSetProgressBarSubset(0, 100);
1720 /* Are we in safe mode? */
1721 if (InitSafeBootMode
)
1723 /* Open the safe boot key */
1724 RtlInitUnicodeString(&KeyName
,
1725 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1726 L
"\\CONTROL\\SAFEBOOT");
1727 InitializeObjectAttributes(&ObjectAttributes
,
1729 OBJ_CASE_INSENSITIVE
,
1732 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1733 if (NT_SUCCESS(Status
))
1735 /* First check if we have an alternate shell */
1738 /* Make sure that the registry has one setup */
1739 RtlInitUnicodeString(&KeyName
, L
"AlternateShell");
1740 Status
= NtQueryValueKey(KeyHandle
,
1742 KeyValuePartialInformation
,
1744 sizeof(KeyPartialInfo
),
1746 if (!NT_SUCCESS(Status
)) AlternateShell
= FALSE
;
1749 /* Create the option key */
1750 RtlInitUnicodeString(&KeyName
, L
"Option");
1751 InitializeObjectAttributes(&ObjectAttributes
,
1753 OBJ_CASE_INSENSITIVE
,
1756 Status
= ZwCreateKey(&OptionHandle
,
1761 REG_OPTION_VOLATILE
,
1765 /* Check if the key create worked */
1766 if (NT_SUCCESS(Status
))
1768 /* Write the safe boot type */
1769 RtlInitUnicodeString(&KeyName
, L
"OptionValue");
1770 NtSetValueKey(OptionHandle
,
1775 sizeof(InitSafeBootMode
));
1777 /* Check if we have to use an alternate shell */
1780 /* Remember this for later */
1782 RtlInitUnicodeString(&KeyName
, L
"UseAlternateShell");
1783 NtSetValueKey(OptionHandle
,
1788 sizeof(Disposition
));
1791 /* Close the options key handle */
1792 NtClose(OptionHandle
);
1797 /* Are we in Win PE mode? */
1798 if (InitIsWinPEMode
)
1800 /* Open the safe control key */
1801 RtlInitUnicodeString(&KeyName
,
1802 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1804 InitializeObjectAttributes(&ObjectAttributes
,
1806 OBJ_CASE_INSENSITIVE
,
1809 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1810 if (!NT_SUCCESS(Status
))
1813 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1816 /* Create the MiniNT key */
1817 RtlInitUnicodeString(&KeyName
, L
"MiniNT");
1818 InitializeObjectAttributes(&ObjectAttributes
,
1820 OBJ_CASE_INSENSITIVE
,
1823 Status
= ZwCreateKey(&OptionHandle
,
1828 REG_OPTION_VOLATILE
,
1830 if (!NT_SUCCESS(Status
))
1833 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1836 /* Close the handles */
1838 NtClose(OptionHandle
);
1841 /* Unmap Low memory, and initialize the MPW and Balancer Thread */
1842 MmInitSystem(2, LoaderBlock
);
1844 /* Update progress bar */
1845 InbvUpdateProgressBar(80);
1847 /* Initialize VDM support */
1849 KeI386VdmInitialize();
1852 /* Initialize Power Subsystem in Phase 1*/
1853 if (!PoInitSystem(1, AcpiTableDetected
)) KeBugCheck(INTERNAL_POWER_ERROR
);
1855 /* Initialize the Process Manager at Phase 1 */
1856 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1858 /* Update progress bar */
1859 InbvUpdateProgressBar(85);
1861 /* Make sure nobody touches the loader block again */
1862 if (LoaderBlock
== KeLoaderBlock
) KeLoaderBlock
= NULL
;
1863 LoaderBlock
= Context
= NULL
;
1865 /* Update progress bar */
1866 InbvUpdateProgressBar(90);
1868 /* Launch initial process */
1869 ProcessInfo
= &InitBuffer
->ProcessInfo
;
1870 ExpLoadInitialProcess(InitBuffer
, &ProcessParameters
, &Environment
);
1872 /* Update progress bar */
1873 InbvUpdateProgressBar(100);
1875 /* Allow strings to be displayed */
1876 InbvEnableDisplayString(TRUE
);
1878 /* Wait 5 seconds for it to initialize */
1879 Timeout
.QuadPart
= Int32x32To64(5, -10000000);
1880 Status
= ZwWaitForSingleObject(ProcessInfo
->ProcessHandle
, FALSE
, &Timeout
);
1881 if (InbvBootDriverInstalled
) FinalizeBootLogo();
1882 if (Status
== STATUS_SUCCESS
)
1884 /* Failed, display error */
1885 RtlInitUnicodeString(&DebugString
, L
"INIT: Session Manager terminated.");
1886 ZwDisplayString(&DebugString
);
1888 /* Bugcheck the system if SMSS couldn't initialize */
1889 KeBugCheck(SESSION5_INITIALIZATION_FAILED
);
1892 /* Close process handles */
1893 ZwClose(ProcessInfo
->ThreadHandle
);
1894 ZwClose(ProcessInfo
->ProcessHandle
);
1896 /* Free the initial process environment */
1898 ZwFreeVirtualMemory(NtCurrentProcess(),
1899 (PVOID
*)&Environment
,
1903 /* Free the initial process parameters */
1905 ZwFreeVirtualMemory(NtCurrentProcess(),
1906 (PVOID
*)&ProcessParameters
,
1910 /* Increase init phase */
1911 ExpInitializationPhase
++;
1913 /* Free the boot buffer */
1914 ExFreePool(InitBuffer
);
1919 Phase1Initialization(IN PVOID Context
)
1921 /* Do the .INIT part of Phase 1 which we can free later */
1922 Phase1InitializationDiscard(Context
);
1924 /* Jump into zero page thread */
1925 MmZeroPageThreadMain(NULL
);