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)
10 /* INCLUDES ******************************************************************/
13 #include <reactos/buildno.h>
17 /* This is the size that we can expect from the win 2003 loader */
18 #define LOADER_PARAMETER_EXTENSION_MIN_SIZE \
19 RTL_SIZEOF_THROUGH_FIELD(LOADER_PARAMETER_EXTENSION, AcpiTableSize)
26 IN PLOADER_PARAMETER_BLOCK LoaderBlock
29 typedef struct _INIT_BUFFER
31 WCHAR DebugBuffer
[256];
32 CHAR VersionBuffer
[256];
33 CHAR BootlogHeader
[256];
34 CHAR VersionNumber
[24];
35 RTL_USER_PROCESS_INFORMATION ProcessInfo
;
36 WCHAR RegistryBuffer
[256];
37 } INIT_BUFFER
, *PINIT_BUFFER
;
39 /* DATA **********************************************************************/
42 ULONG NtMajorVersion
= VER_PRODUCTMAJORVERSION
;
43 ULONG NtMinorVersion
= VER_PRODUCTMINORVERSION
;
44 #if DBG /* Checked Build */
45 ULONG NtBuildNumber
= VER_PRODUCTBUILD
| 0xC0000000;
46 #else /* Free Build */
47 ULONG NtBuildNumber
= VER_PRODUCTBUILD
;
51 ULONG NtGlobalFlag
= 0;
55 ULONG CmNtSpBuildNumber
;
57 ULONG CmNtCSDReleaseType
;
58 UNICODE_STRING CmVersionString
;
59 UNICODE_STRING CmCSDVersionString
;
61 CHAR NtBuildLab
[] = KERNEL_VERSION_BUILD_STR
"."
62 REACTOS_COMPILER_NAME
"_" REACTOS_COMPILER_VERSION
;
64 /* Init flags and settings */
65 ULONG ExpInitializationPhase
;
66 BOOLEAN ExpInTextModeSetup
;
67 BOOLEAN IoRemoteBootClient
;
68 ULONG InitSafeBootMode
;
69 BOOLEAN InitIsWinPEMode
, InitWinPEModeType
;
72 UNICODE_STRING NtSystemRoot
;
74 /* NT Initial User Application */
75 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
76 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
78 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
80 /* Boot NLS information */
81 PVOID ExpNlsTableBase
;
82 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
83 ULONG ExpUnicodeCaseTableDataOffset
;
84 NLSTABLEINFO ExpNlsTableInfo
;
85 SIZE_T ExpNlsTableSize
;
86 PVOID ExpNlsSectionPointer
;
88 /* CMOS Timer Sanity */
89 BOOLEAN ExCmosClockIsSane
= TRUE
;
90 BOOLEAN ExpRealTimeIsUniversal
;
92 /* FUNCTIONS ****************************************************************/
97 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
99 UNICODE_STRING LinkName
;
100 OBJECT_ATTRIBUTES ObjectAttributes
;
103 ANSI_STRING AnsiName
;
105 ANSI_STRING TargetString
;
106 UNICODE_STRING TargetName
;
108 /* Initialize the ArcName tree */
109 RtlInitUnicodeString(&LinkName
, L
"\\ArcName");
110 InitializeObjectAttributes(&ObjectAttributes
,
112 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
114 SePublicDefaultUnrestrictedSd
);
117 Status
= NtCreateDirectoryObject(&LinkHandle
,
118 DIRECTORY_ALL_ACCESS
,
120 if (!NT_SUCCESS(Status
))
123 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
126 /* Close the LinkHandle */
129 /* Initialize the Device tree */
130 RtlInitUnicodeString(&LinkName
, L
"\\Device");
131 InitializeObjectAttributes(&ObjectAttributes
,
133 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
135 SePublicDefaultUnrestrictedSd
);
138 Status
= NtCreateDirectoryObject(&LinkHandle
,
139 DIRECTORY_ALL_ACCESS
,
141 if (!NT_SUCCESS(Status
))
144 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
147 /* Close the LinkHandle */
148 ObCloseHandle(LinkHandle
, KernelMode
);
150 /* Create the system root symlink name */
151 RtlInitAnsiString(&AnsiName
, "\\SystemRoot");
152 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &AnsiName
, TRUE
);
153 if (!NT_SUCCESS(Status
))
156 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
159 /* Initialize the attributes for the link */
160 InitializeObjectAttributes(&ObjectAttributes
,
162 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
164 SePublicDefaultUnrestrictedSd
);
166 /* Build the ARC name */
169 LoaderBlock
->ArcBootDeviceName
,
170 LoaderBlock
->NtBootPathName
);
171 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
173 /* Convert it to Unicode */
174 RtlInitString(&TargetString
, Buffer
);
175 Status
= RtlAnsiStringToUnicodeString(&TargetName
,
178 if (!NT_SUCCESS(Status
))
180 /* We failed, bugcheck */
181 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
185 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
186 SYMBOLIC_LINK_ALL_ACCESS
,
190 /* Free the strings */
191 RtlFreeUnicodeString(&LinkName
);
192 RtlFreeUnicodeString(&TargetName
);
194 /* Check if creating the link failed */
195 if (!NT_SUCCESS(Status
))
198 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
201 /* Close the handle and return success */
202 ObCloseHandle(LinkHandle
, KernelMode
);
203 return STATUS_SUCCESS
;
209 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
211 LARGE_INTEGER SectionSize
;
214 PVOID SectionBase
= NULL
;
216 LARGE_INTEGER SectionOffset
= {{0, 0}};
217 PLIST_ENTRY ListHead
, NextEntry
;
218 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
219 ULONG NlsTablesEncountered
= 0;
220 SIZE_T NlsTableSizes
[3] = {0, 0, 0}; /* 3 NLS tables */
222 /* Check if this is boot-time phase 0 initialization */
223 if (!ExpInitializationPhase
)
225 /* Loop the memory descriptors */
226 ListHead
= &LoaderBlock
->MemoryDescriptorListHead
;
227 NextEntry
= ListHead
->Flink
;
228 while (NextEntry
!= ListHead
)
230 /* Get the current block */
231 MdBlock
= CONTAINING_RECORD(NextEntry
,
232 MEMORY_ALLOCATION_DESCRIPTOR
,
235 /* Check if this is an NLS block */
236 if (MdBlock
->MemoryType
== LoaderNlsData
)
238 /* Increase the table size */
239 ExpNlsTableSize
+= MdBlock
->PageCount
* PAGE_SIZE
;
241 /* FreeLdr-specific */
242 NlsTableSizes
[NlsTablesEncountered
] = MdBlock
->PageCount
* PAGE_SIZE
;
243 NlsTablesEncountered
++;
244 ASSERT(NlsTablesEncountered
< 4);
247 /* Go to the next block */
248 NextEntry
= MdBlock
->ListEntry
.Flink
;
251 /* Allocate the a new buffer since loader memory will be freed */
252 ExpNlsTableBase
= ExAllocatePoolWithTag(NonPagedPool
,
255 if (!ExpNlsTableBase
) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
257 /* Copy the codepage data in its new location. */
258 if (NlsTablesEncountered
== 1)
260 /* Ntldr-way boot process */
261 RtlCopyMemory(ExpNlsTableBase
,
262 LoaderBlock
->NlsData
->AnsiCodePageData
,
268 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
269 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
271 RtlCopyMemory(ExpNlsTableBase
,
272 LoaderBlock
->NlsData
->AnsiCodePageData
,
275 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0]),
276 LoaderBlock
->NlsData
->OemCodePageData
,
279 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0] +
281 LoaderBlock
->NlsData
->UnicodeCodePageData
,
286 /* Initialize and reset the NLS TAbles */
287 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
288 ExpAnsiCodePageDataOffset
),
289 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
290 ExpOemCodePageDataOffset
),
291 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
292 ExpUnicodeCaseTableDataOffset
),
294 RtlResetRtlTranslations(&ExpNlsTableInfo
);
298 /* Set the section size */
299 SectionSize
.QuadPart
= ExpNlsTableSize
;
301 /* Create the NLS Section */
302 Status
= ZwCreateSection(&NlsSection
,
309 if (!NT_SUCCESS(Status
))
312 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
315 /* Get a pointer to the section */
316 Status
= ObReferenceObjectByHandle(NlsSection
,
320 &ExpNlsSectionPointer
,
322 ObCloseHandle(NlsSection
, KernelMode
);
323 if (!NT_SUCCESS(Status
))
326 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
329 /* Map the NLS Section in system space */
330 Status
= MmMapViewInSystemSpace(ExpNlsSectionPointer
,
333 if (!NT_SUCCESS(Status
))
336 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
339 /* Copy the codepage data in its new location. */
340 ASSERT(SectionBase
>= MmSystemRangeStart
);
341 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
343 /* Free the previously allocated buffer and set the new location */
344 ExFreePoolWithTag(ExpNlsTableBase
, TAG_RTLI
);
345 ExpNlsTableBase
= SectionBase
;
347 /* Initialize the NLS Tables */
348 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
349 ExpAnsiCodePageDataOffset
),
350 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
351 ExpOemCodePageDataOffset
),
352 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
353 ExpUnicodeCaseTableDataOffset
),
355 RtlResetRtlTranslations(&ExpNlsTableInfo
);
357 /* Reset the base to 0 */
360 /* Map the section in the system process */
361 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
362 PsGetCurrentProcess(),
371 if (!NT_SUCCESS(Status
))
374 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
377 /* Copy the table into the system process and set this as the base */
378 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
379 ExpNlsTableBase
= SectionBase
;
385 ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer
,
386 OUT PRTL_USER_PROCESS_PARAMETERS
*ProcessParameters
,
387 OUT PCHAR
*ProcessEnvironment
)
392 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
393 UNICODE_STRING SmssName
, Environment
, SystemDriveString
, DebugString
;
394 PVOID EnvironmentPtr
= NULL
;
395 PRTL_USER_PROCESS_INFORMATION ProcessInformation
;
396 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= NULL
;
398 NullString
.Length
= sizeof(WCHAR
);
400 /* Use the initial buffer, after the strings */
401 ProcessInformation
= &InitBuffer
->ProcessInfo
;
403 /* Allocate memory for the process parameters */
404 Size
= sizeof(*ProcessParams
) + ((MAX_PATH
* 6) * sizeof(WCHAR
));
405 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
406 (PVOID
*)&ProcessParams
,
409 MEM_RESERVE
| MEM_COMMIT
,
411 if (!NT_SUCCESS(Status
))
413 /* Failed, display error */
414 _snwprintf(InitBuffer
->DebugBuffer
,
415 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
416 L
"INIT: Unable to allocate Process Parameters. 0x%lx",
418 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
419 ZwDisplayString(&DebugString
);
421 /* Bugcheck the system */
422 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
425 /* Setup the basic header, and give the process the low 1MB to itself */
426 ProcessParams
->Length
= (ULONG
)Size
;
427 ProcessParams
->MaximumLength
= (ULONG
)Size
;
428 ProcessParams
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
429 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
431 /* Allocate a page for the environment */
433 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
437 MEM_RESERVE
| MEM_COMMIT
,
439 if (!NT_SUCCESS(Status
))
441 /* Failed, display error */
442 _snwprintf(InitBuffer
->DebugBuffer
,
443 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
444 L
"INIT: Unable to allocate Process Environment. 0x%lx",
446 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
447 ZwDisplayString(&DebugString
);
449 /* Bugcheck the system */
450 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
453 /* Write the pointer */
454 ProcessParams
->Environment
= EnvironmentPtr
;
456 /* Make a buffer for the DOS path */
457 p
= (PWSTR
)(ProcessParams
+ 1);
458 ProcessParams
->CurrentDirectory
.DosPath
.Buffer
= p
;
459 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
= MAX_PATH
*
462 /* Copy the DOS path */
463 RtlCopyUnicodeString(&ProcessParams
->CurrentDirectory
.DosPath
,
466 /* Make a buffer for the DLL Path */
467 p
= (PWSTR
)((PCHAR
)ProcessParams
->CurrentDirectory
.DosPath
.Buffer
+
468 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
);
469 ProcessParams
->DllPath
.Buffer
= p
;
470 ProcessParams
->DllPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
472 /* Copy the DLL path and append the system32 directory */
473 RtlCopyUnicodeString(&ProcessParams
->DllPath
,
474 &ProcessParams
->CurrentDirectory
.DosPath
);
475 RtlAppendUnicodeToString(&ProcessParams
->DllPath
, L
"\\System32");
477 /* Make a buffer for the image name */
478 p
= (PWSTR
)((PCHAR
)ProcessParams
->DllPath
.Buffer
+
479 ProcessParams
->DllPath
.MaximumLength
);
480 ProcessParams
->ImagePathName
.Buffer
= p
;
481 ProcessParams
->ImagePathName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
483 /* Make sure the buffer is a valid string which within the given length */
484 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
485 ((NtInitialUserProcessBufferLength
!= MAXULONG
) &&
486 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
487 (NtInitialUserProcessBufferLength
>
488 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
490 /* Invalid initial process string, bugcheck */
491 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
,
492 STATUS_INVALID_PARAMETER
,
493 NtInitialUserProcessBufferType
,
494 NtInitialUserProcessBufferLength
,
495 sizeof(NtInitialUserProcessBuffer
));
498 /* Cut out anything after a space */
499 p
= NtInitialUserProcessBuffer
;
500 while ((*p
) && (*p
!= L
' ')) p
++;
502 /* Set the image path length */
503 ProcessParams
->ImagePathName
.Length
=
504 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
506 /* Copy the actual buffer */
507 RtlCopyMemory(ProcessParams
->ImagePathName
.Buffer
,
508 NtInitialUserProcessBuffer
,
509 ProcessParams
->ImagePathName
.Length
);
511 /* Null-terminate it */
512 ProcessParams
->ImagePathName
.Buffer
[ProcessParams
->ImagePathName
.Length
/
513 sizeof(WCHAR
)] = UNICODE_NULL
;
515 /* Make a buffer for the command line */
516 p
= (PWSTR
)((PCHAR
)ProcessParams
->ImagePathName
.Buffer
+
517 ProcessParams
->ImagePathName
.MaximumLength
);
518 ProcessParams
->CommandLine
.Buffer
= p
;
519 ProcessParams
->CommandLine
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
521 /* Add the image name to the command line */
522 RtlAppendUnicodeToString(&ProcessParams
->CommandLine
,
523 NtInitialUserProcessBuffer
);
525 /* Create the environment string */
526 RtlInitEmptyUnicodeString(&Environment
,
527 ProcessParams
->Environment
,
530 /* Append the DLL path to it */
531 RtlAppendUnicodeToString(&Environment
, L
"Path=");
532 RtlAppendUnicodeStringToString(&Environment
, &ProcessParams
->DllPath
);
533 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
535 /* Create the system drive string */
536 SystemDriveString
= NtSystemRoot
;
537 SystemDriveString
.Length
= 2 * sizeof(WCHAR
);
539 /* Append it to the environment */
540 RtlAppendUnicodeToString(&Environment
, L
"SystemDrive=");
541 RtlAppendUnicodeStringToString(&Environment
, &SystemDriveString
);
542 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
544 /* Append the system root to the environment */
545 RtlAppendUnicodeToString(&Environment
, L
"SystemRoot=");
546 RtlAppendUnicodeStringToString(&Environment
, &NtSystemRoot
);
547 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
549 /* Prepare the prefetcher */
550 //CcPfBeginBootPhase(150);
552 /* Create SMSS process */
553 SmssName
= ProcessParams
->ImagePathName
;
554 Status
= RtlCreateUserProcess(&SmssName
,
555 OBJ_CASE_INSENSITIVE
,
556 RtlDeNormalizeProcessParams(ProcessParams
),
564 if (!NT_SUCCESS(Status
))
566 /* Failed, display error */
567 _snwprintf(InitBuffer
->DebugBuffer
,
568 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
569 L
"INIT: Unable to create Session Manager. 0x%lx",
571 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
572 ZwDisplayString(&DebugString
);
574 /* Bugcheck the system */
575 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
578 /* Resume the thread */
579 Status
= ZwResumeThread(ProcessInformation
->ThreadHandle
, NULL
);
580 if (!NT_SUCCESS(Status
))
582 /* Failed, display error */
583 _snwprintf(InitBuffer
->DebugBuffer
,
584 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
585 L
"INIT: Unable to resume Session Manager. 0x%lx",
587 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
588 ZwDisplayString(&DebugString
);
590 /* Bugcheck the system */
591 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
595 *ProcessParameters
= ProcessParams
;
596 *ProcessEnvironment
= EnvironmentPtr
;
602 ExComputeTickCountMultiplier(IN ULONG ClockIncrement
)
604 ULONG MsRemainder
= 0, MsIncrement
;
605 ULONG IncrementRemainder
;
608 /* Count the number of milliseconds for each clock interrupt */
609 MsIncrement
= ClockIncrement
/ (10 * 1000);
611 /* Count the remainder from the division above, with 24-bit precision */
612 IncrementRemainder
= ClockIncrement
- (MsIncrement
* (10 * 1000));
613 for (i
= 0; i
< 24; i
++)
615 /* Shift the remainders */
617 IncrementRemainder
<<= 1;
619 /* Check if we've went past 1 ms */
620 if (IncrementRemainder
>= (10 * 1000))
622 /* Increase the remainder by one, and substract from increment */
623 IncrementRemainder
-= (10 * 1000);
628 /* Return the increment */
629 return (MsIncrement
<< 24) | MsRemainder
;
635 ExpInitSystemPhase0(VOID
)
637 /* Initialize EXRESOURCE Support */
638 ExpResourceInitialization();
640 /* Initialize the environment lock */
641 ExInitializeFastMutex(&ExpEnvironmentLock
);
643 /* Initialize the lookaside lists and locks */
644 ExpInitLookasideLists();
646 /* Initialize the Firmware Table resource and listhead */
647 InitializeListHead(&ExpFirmwareTableProviderListHead
);
648 ExInitializeResourceLite(&ExpFirmwareTableResource
);
650 /* Set the suite mask to maximum and return */
651 ExSuiteMask
= 0xFFFFFFFF;
658 ExpInitSystemPhase1(VOID
)
660 /* Initialize worker threads */
661 ExpInitializeWorkerThreads();
663 /* Initialize pushlocks */
664 ExpInitializePushLocks();
666 /* Initialize events and event pairs */
667 if (ExpInitializeEventImplementation() == FALSE
)
669 DPRINT1("Executive: Event initialization failed\n");
672 if (ExpInitializeEventPairImplementation() == FALSE
)
674 DPRINT1("Executive: Event Pair initialization failed\n");
678 /* Initialize mutants */
679 if (ExpInitializeMutantImplementation() == FALSE
)
681 DPRINT1("Executive: Mutant initialization failed\n");
685 /* Initialize callbacks */
686 if (ExpInitializeCallbacks() == FALSE
)
688 DPRINT1("Executive: Callback initialization failed\n");
692 /* Initialize semaphores */
693 if (ExpInitializeSemaphoreImplementation() == FALSE
)
695 DPRINT1("Executive: Semaphore initialization failed\n");
699 /* Initialize timers */
700 if (ExpInitializeTimerImplementation() == FALSE
)
702 DPRINT1("Executive: Timer initialization failed\n");
706 /* Initialize profiling */
707 if (ExpInitializeProfileImplementation() == FALSE
)
709 DPRINT1("Executive: Profile initialization failed\n");
713 /* Initialize UUIDs */
714 if (ExpUuidInitialization() == FALSE
)
716 DPRINT1("Executive: Uuid initialization failed\n");
720 /* Initialize keyed events */
721 if (ExpInitializeKeyedEventImplementation() == FALSE
)
723 DPRINT1("Executive: Keyed event initialization failed\n");
727 /* Initialize Win32K */
728 if (ExpWin32kInit() == FALSE
)
730 DPRINT1("Executive: Win32 initialization failed\n");
741 /* Check the initialization phase */
742 switch (ExpInitializationPhase
)
747 return ExpInitSystemPhase0();
752 return ExpInitSystemPhase1();
756 /* Don't know any other phase! Bugcheck! */
757 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
765 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
767 PLOADER_PARAMETER_EXTENSION Extension
;
769 /* Get the loader extension */
770 Extension
= LoaderBlock
->Extension
;
772 /* Validate the size (Windows 2003 loader doesn't provide more) */
773 if (Extension
->Size
< LOADER_PARAMETER_EXTENSION_MIN_SIZE
) return FALSE
;
775 /* Don't validate upper versions */
776 if (Extension
->MajorVersion
> VER_PRODUCTMAJORVERSION
) return TRUE
;
778 /* Fail if this is NT 4 */
779 if (Extension
->MajorVersion
< VER_PRODUCTMAJORVERSION
) return FALSE
;
781 /* Fail if this is XP */
782 if (Extension
->MinorVersion
< VER_PRODUCTMINORVERSION
) return FALSE
;
784 /* This is 2003 or newer, approve it */
791 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
794 PLIST_ENTRY NextEntry
;
797 PLDR_DATA_TABLE_ENTRY LdrEntry
;
798 CHAR NameBuffer
[256];
802 /* Loop the driver list */
803 NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
804 while (NextEntry
!= &LoaderBlock
->LoadOrderListHead
)
806 /* Skip the first two images */
810 LdrEntry
= CONTAINING_RECORD(NextEntry
,
811 LDR_DATA_TABLE_ENTRY
,
813 if (LdrEntry
->FullDllName
.Buffer
[0] == L
'\\')
815 /* We have a name, read its data */
816 Name
= LdrEntry
->FullDllName
.Buffer
;
817 Length
= LdrEntry
->FullDllName
.Length
/ sizeof(WCHAR
);
819 /* Check if our buffer can hold it */
820 if (sizeof(NameBuffer
) < Length
+ sizeof(ANSI_NULL
))
823 Status
= STATUS_BUFFER_OVERFLOW
;
831 /* Copy the character */
832 NameBuffer
[Count
++] = (CHAR
)*Name
++;
833 } while (Count
< Length
);
836 NameBuffer
[Count
] = ANSI_NULL
;
837 Status
= STATUS_SUCCESS
;
842 /* Safely print the string into our buffer */
843 Status
= RtlStringCbPrintfA(NameBuffer
,
845 "%S\\System32\\Drivers\\%wZ",
846 &SharedUserData
->NtSystemRoot
[2],
847 &LdrEntry
->BaseDllName
);
850 /* Check if the buffer was ok */
851 if (NT_SUCCESS(Status
))
853 /* Initialize the STRING for the debugger */
854 RtlInitString(&SymbolString
, NameBuffer
);
856 /* Load the symbols */
857 DbgLoadImageSymbols(&SymbolString
,
859 (ULONG_PTR
)PsGetCurrentProcessId());
863 /* Go to the next entry */
865 NextEntry
= NextEntry
->Flink
;
872 ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
873 IN ULONG_PTR PagesToDestroy
,
874 IN TYPE_OF_MEMORY MemoryType
)
876 PLIST_ENTRY ListEntry
;
877 PMEMORY_ALLOCATION_DESCRIPTOR MemDescriptor
;
879 DPRINT1("Burn RAM amount: %lu pages\n", PagesToDestroy
);
881 /* Loop the memory descriptors, beginning at the end */
882 for (ListEntry
= LoaderBlock
->MemoryDescriptorListHead
.Blink
;
883 ListEntry
!= &LoaderBlock
->MemoryDescriptorListHead
;
884 ListEntry
= ListEntry
->Blink
)
886 /* Get the memory descriptor structure */
887 MemDescriptor
= CONTAINING_RECORD(ListEntry
,
888 MEMORY_ALLOCATION_DESCRIPTOR
,
891 /* Is memory free there or is it temporary? */
892 if (MemDescriptor
->MemoryType
== LoaderFree
||
893 MemDescriptor
->MemoryType
== LoaderFirmwareTemporary
)
895 /* Check if the descriptor has more pages than we want */
896 if (MemDescriptor
->PageCount
> PagesToDestroy
)
898 /* Change block's page count, ntoskrnl doesn't care much */
899 MemDescriptor
->PageCount
-= PagesToDestroy
;
904 /* Change block type */
905 MemDescriptor
->MemoryType
= MemoryType
;
906 PagesToDestroy
-= MemDescriptor
->PageCount
;
908 /* Check if we are done */
909 if (PagesToDestroy
== 0) break;
918 ExpInitializeExecutive(IN ULONG Cpu
,
919 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
921 PNLS_DATA_BLOCK NlsData
;
923 ANSI_STRING AnsiPath
;
925 PCHAR CommandLine
, PerfMem
;
927 PLDR_DATA_TABLE_ENTRY NtosEntry
;
928 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
929 ANSI_STRING CSDString
;
930 size_t Remaining
= 0;
932 CHAR VersionBuffer
[65];
934 /* Validate Loader */
935 if (!ExpIsLoaderValid(LoaderBlock
))
937 /* Invalid loader version */
938 KeBugCheckEx(MISMATCHED_HAL
,
940 LoaderBlock
->Extension
->Size
,
941 LoaderBlock
->Extension
->MajorVersion
,
942 LoaderBlock
->Extension
->MinorVersion
);
945 /* Initialize PRCB pool lookaside pointers */
946 ExInitPoolLookasidePointers();
948 /* Check if this is an application CPU */
951 /* Then simply initialize it with HAL */
952 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
954 /* Initialization failed */
955 KeBugCheck(HAL_INITIALIZATION_FAILED
);
962 /* Assume no text-mode or remote boot */
963 ExpInTextModeSetup
= FALSE
;
964 IoRemoteBootClient
= FALSE
;
966 /* Check if we have a setup loader block */
967 if (LoaderBlock
->SetupLdrBlock
)
969 /* Check if this is text-mode setup */
970 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_TEXT_MODE
)
971 ExpInTextModeSetup
= TRUE
;
973 /* Check if this is network boot */
974 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_REMOTE_BOOT
)
977 IoRemoteBootClient
= TRUE
;
979 /* Make sure we're actually booting off the network */
980 ASSERT(!_memicmp(LoaderBlock
->ArcBootDeviceName
, "net(0)", 6));
985 ExpInitializationPhase
= 0;
987 /* Get boot command line */
988 CommandLine
= LoaderBlock
->LoadOptions
;
991 /* Upcase it for comparison and check if we're in performance mode */
992 _strupr(CommandLine
);
993 PerfMem
= strstr(CommandLine
, "PERFMEM");
996 /* Check if the user gave a number of bytes to use */
997 PerfMem
= strstr(PerfMem
, "=");
1000 /* Read the number of pages we'll use */
1001 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
1005 DPRINT1("BBT performance mode not yet supported."
1006 "/PERFMEM option ignored.\n");
1011 /* Check if we're burning memory */
1012 PerfMem
= strstr(CommandLine
, "BURNMEMORY");
1015 /* Check if the user gave a number of bytes to use */
1016 PerfMem
= strstr(PerfMem
, "=");
1019 /* Read the number of pages we'll use */
1020 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
1021 if (PerfMemUsed
) ExBurnMemory(LoaderBlock
, PerfMemUsed
, LoaderBad
);
1026 /* Setup NLS Base and offsets */
1027 NlsData
= LoaderBlock
->NlsData
;
1028 ExpNlsTableBase
= NlsData
->AnsiCodePageData
;
1029 ExpAnsiCodePageDataOffset
= 0;
1030 ExpOemCodePageDataOffset
= (ULONG
)((ULONG_PTR
)NlsData
->OemCodePageData
-
1031 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
1032 ExpUnicodeCaseTableDataOffset
= (ULONG
)((ULONG_PTR
)NlsData
->UnicodeCodePageData
-
1033 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
1035 /* Initialize the NLS Tables */
1036 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1037 ExpAnsiCodePageDataOffset
),
1038 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1039 ExpOemCodePageDataOffset
),
1040 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1041 ExpUnicodeCaseTableDataOffset
),
1043 RtlResetRtlTranslations(&ExpNlsTableInfo
);
1045 /* Now initialize the HAL */
1046 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
1048 /* HAL failed to initialize, bugcheck */
1049 KeBugCheck(HAL_INITIALIZATION_FAILED
);
1052 /* Make sure interrupts are active now */
1055 /* Clear the crypto exponent */
1056 SharedUserData
->CryptoExponent
= 0;
1058 /* Set global flags for the checked build */
1060 NtGlobalFlag
|= FLG_ENABLE_CLOSE_EXCEPTIONS
|
1061 FLG_ENABLE_KDEBUG_SYMBOL_LOAD
;
1064 /* Setup NT System Root Path */
1065 sprintf(Buffer
, "C:%s", LoaderBlock
->NtBootPathName
);
1067 /* Convert to ANSI_STRING and null-terminate it */
1068 RtlInitString(&AnsiPath
, Buffer
);
1069 Buffer
[--AnsiPath
.Length
] = ANSI_NULL
;
1071 /* Get the string from KUSER_SHARED_DATA's buffer */
1072 RtlInitEmptyUnicodeString(&NtSystemRoot
,
1073 SharedUserData
->NtSystemRoot
,
1074 sizeof(SharedUserData
->NtSystemRoot
));
1076 /* Now fill it in */
1077 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &AnsiPath
, FALSE
);
1078 if (!NT_SUCCESS(Status
)) KeBugCheck(SESSION3_INITIALIZATION_FAILED
);
1080 /* Setup bugcheck messages */
1081 KiInitializeBugCheck();
1083 /* Setup initial system settings */
1084 CmGetSystemControlValues(LoaderBlock
->RegistryBase
, CmControlVector
);
1086 /* Set the Service Pack Number and add it to the CSD Version number if needed */
1087 CmNtSpBuildNumber
= VER_PRODUCTBUILD_QFE
;
1088 if (((CmNtCSDVersion
& 0xFFFF0000) == 0) && (CmNtCSDReleaseType
== 1))
1090 CmNtCSDVersion
|= (VER_PRODUCTBUILD_QFE
<< 16);
1093 /* Add loaded CmNtGlobalFlag value */
1094 NtGlobalFlag
|= CmNtGlobalFlag
;
1096 /* Initialize the executive at phase 0 */
1097 if (!ExInitSystem()) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1099 /* Initialize the memory manager at phase 0 */
1100 if (!MmArmInitSystem(0, LoaderBlock
)) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1102 /* Load boot symbols */
1103 ExpLoadBootSymbols(LoaderBlock
);
1105 /* Check if we should break after symbol load */
1106 if (KdBreakAfterSymbolLoad
) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
1108 /* Check if this loader is compatible with NT 5.2 */
1109 if (LoaderBlock
->Extension
->Size
>= sizeof(LOADER_PARAMETER_EXTENSION
))
1111 /* Setup headless terminal settings */
1112 HeadlessInit(LoaderBlock
);
1115 /* Set system ranges */
1117 SharedUserData
->Reserved1
= MM_HIGHEST_USER_ADDRESS_WOW64
;
1118 SharedUserData
->Reserved3
= MM_SYSTEM_RANGE_START_WOW64
;
1120 SharedUserData
->Reserved1
= (ULONG_PTR
)MmHighestUserAddress
;
1121 SharedUserData
->Reserved3
= (ULONG_PTR
)MmSystemRangeStart
;
1124 /* Make a copy of the NLS Tables */
1125 ExpInitNls(LoaderBlock
);
1127 /* Get the kernel's load entry */
1128 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1129 LDR_DATA_TABLE_ENTRY
,
1132 /* Check if this is a service pack */
1133 if (CmNtCSDVersion
& 0xFFFF)
1135 /* Get the service pack string */
1136 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1139 WINDOWS_NT_CSD_STRING
,
1141 if (NT_SUCCESS(Status
))
1143 /* Setup the string */
1144 RtlInitAnsiString(&CSDString
, (PCHAR
)MsgEntry
->Text
);
1146 /* Remove trailing newline */
1147 while ((CSDString
.Length
> 0) &&
1148 ((CSDString
.Buffer
[CSDString
.Length
- 1] == '\r') ||
1149 (CSDString
.Buffer
[CSDString
.Length
- 1] == '\n')))
1151 /* Skip the trailing character */
1155 /* Fill the buffer with version information */
1156 Status
= RtlStringCbPrintfA(Buffer
,
1160 (CmNtCSDVersion
& 0xFF00) >> 8,
1161 (CmNtCSDVersion
& 0xFF) ?
1162 'A' + (CmNtCSDVersion
& 0xFF) - 1 :
1167 /* Build default string */
1168 Status
= RtlStringCbPrintfA(Buffer
,
1174 /* Check for success */
1175 if (!NT_SUCCESS(Status
))
1178 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1183 /* Then this is a beta */
1184 Status
= RtlStringCbCopyExA(Buffer
,
1186 VER_PRODUCTBETA_STR
,
1190 if (!NT_SUCCESS(Status
))
1193 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1197 CmCSDVersionString
.MaximumLength
= sizeof(Buffer
) - (USHORT
)Remaining
;
1200 /* Check if we have an RC number */
1201 if ((CmNtCSDVersion
& 0xFFFF0000) && (CmNtCSDReleaseType
== 1))
1203 /* Check if we have no version data yet */
1207 Remaining
= sizeof(Buffer
);
1212 /* Add comma and space */
1213 Status
= RtlStringCbCatExA(Buffer
,
1219 if (!NT_SUCCESS(Status
))
1222 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1226 /* Add the version format string */
1227 Status
= RtlStringCbPrintfA(RcEnd
,
1230 (CmNtCSDVersion
& 0xFFFF0000) >> 16);
1231 if (!NT_SUCCESS(Status
))
1234 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1238 /* Now setup the final string */
1239 RtlInitAnsiString(&CSDString
, Buffer
);
1240 Status
= RtlAnsiStringToUnicodeString(&CmCSDVersionString
,
1243 if (!NT_SUCCESS(Status
))
1246 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1249 /* Add our version */
1250 Status
= RtlStringCbPrintfA(VersionBuffer
,
1251 sizeof(VersionBuffer
),
1253 VER_PRODUCTMAJORVERSION
,
1254 VER_PRODUCTMINORVERSION
);
1255 if (!NT_SUCCESS(Status
))
1258 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1261 /* Build the final version string */
1262 RtlCreateUnicodeStringFromAsciiz(&CmVersionString
, VersionBuffer
);
1264 /* Check if the user wants a kernel stack trace database */
1265 if (NtGlobalFlag
& FLG_KERNEL_STACK_TRACE_DB
)
1268 DPRINT1("Kernel-mode stack trace support not yet present."
1269 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
1272 /* Check if he wanted exception logging */
1273 if (NtGlobalFlag
& FLG_ENABLE_EXCEPTION_LOGGING
)
1276 DPRINT1("Kernel-mode exception logging support not yet present."
1277 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
1280 /* Initialize the Handle Table */
1281 ExpInitializeHandleTables();
1284 /* On checked builds, allocate the system call count table */
1285 KeServiceDescriptorTable
[0].Count
=
1286 ExAllocatePoolWithTag(NonPagedPool
,
1287 KiServiceLimit
* sizeof(ULONG
),
1290 /* Use it for the shadow table too */
1291 KeServiceDescriptorTableShadow
[0].Count
= KeServiceDescriptorTable
[0].Count
;
1293 /* Make sure allocation succeeded */
1294 if (KeServiceDescriptorTable
[0].Count
)
1296 /* Zero the call counts to 0 */
1297 RtlZeroMemory(KeServiceDescriptorTable
[0].Count
,
1298 KiServiceLimit
* sizeof(ULONG
));
1302 /* Create the Basic Object Manager Types to allow new Object Types */
1303 if (!ObInitSystem()) KeBugCheck(OBJECT_INITIALIZATION_FAILED
);
1305 /* Load basic Security for other Managers */
1306 if (!SeInitSystem()) KeBugCheck(SECURITY_INITIALIZATION_FAILED
);
1308 /* Initialize the Process Manager */
1309 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS_INITIALIZATION_FAILED
);
1311 /* Initialize the PnP Manager */
1312 if (!PpInitSystem()) KeBugCheck(PP0_INITIALIZATION_FAILED
);
1314 /* Initialize the User-Mode Debugging Subsystem */
1317 /* Calculate the tick count multiplier */
1318 ExpTickCountMultiplier
= ExComputeTickCountMultiplier(KeMaximumIncrement
);
1319 SharedUserData
->TickCountMultiplier
= ExpTickCountMultiplier
;
1321 /* Set the OS Version */
1322 SharedUserData
->NtMajorVersion
= NtMajorVersion
;
1323 SharedUserData
->NtMinorVersion
= NtMinorVersion
;
1325 /* Set the machine type */
1326 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_NATIVE
;
1327 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_NATIVE
;
1332 MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
1337 Phase1InitializationDiscard(IN PVOID Context
)
1339 PLOADER_PARAMETER_BLOCK LoaderBlock
= Context
;
1340 NTSTATUS Status
, MsgStatus
;
1341 TIME_FIELDS TimeFields
;
1342 LARGE_INTEGER SystemBootTime
, UniversalBootTime
, OldTime
, Timeout
;
1343 BOOLEAN SosEnabled
, NoGuiBoot
, ResetBias
= FALSE
, AlternateShell
= FALSE
;
1344 PLDR_DATA_TABLE_ENTRY NtosEntry
;
1345 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
1346 PCHAR CommandLine
, Y2KHackRequired
, SafeBoot
, Environment
;
1347 PCHAR StringBuffer
, EndBuffer
, BeginBuffer
, MpString
= "";
1348 PINIT_BUFFER InitBuffer
;
1349 ANSI_STRING TempString
;
1350 ULONG LastTzBias
, Length
, YearHack
= 0, Disposition
, MessageCode
= 0;
1353 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
1354 KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo
;
1355 UNICODE_STRING KeyName
;
1356 OBJECT_ATTRIBUTES ObjectAttributes
;
1357 HANDLE KeyHandle
, OptionHandle
;
1358 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
1360 /* Allocate the initialization buffer */
1361 InitBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1362 sizeof(INIT_BUFFER
),
1367 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 8, 0, 0);
1370 /* Set to phase 1 */
1371 ExpInitializationPhase
= 1;
1373 /* Set us at maximum priority */
1374 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY
);
1376 /* Do Phase 1 HAL Initialization */
1377 if (!HalInitSystem(1, LoaderBlock
)) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1379 /* Get the command line and upcase it */
1380 CommandLine
= (LoaderBlock
->LoadOptions
? _strupr(LoaderBlock
->LoadOptions
) : NULL
);
1382 /* Check if GUI Boot is enabled */
1383 NoGuiBoot
= (CommandLine
&& strstr(CommandLine
, "NOGUIBOOT") != NULL
);
1385 /* Get the SOS setting */
1386 SosEnabled
= (CommandLine
&& strstr(CommandLine
, "SOS") != NULL
);
1388 /* Setup the boot driver */
1389 InbvEnableBootDriver(!NoGuiBoot
);
1390 InbvDriverInitialize(LoaderBlock
, IDB_MAX_RESOURCE
);
1392 /* Check if GUI boot is enabled */
1395 /* It is, display the boot logo and enable printing strings */
1396 InbvEnableDisplayString(SosEnabled
);
1397 DisplayBootBitmap(SosEnabled
);
1401 /* Release display ownership if not using GUI boot */
1402 InbvNotifyDisplayOwnershipLost(NULL
);
1404 /* Don't allow boot-time strings */
1405 InbvEnableDisplayString(FALSE
);
1408 /* Check if this is LiveCD (WinPE) mode */
1409 if (CommandLine
&& strstr(CommandLine
, "MININT") != NULL
)
1411 /* Setup WinPE Settings */
1412 InitIsWinPEMode
= TRUE
;
1413 InitWinPEModeType
|= (strstr(CommandLine
, "INRAM") != NULL
) ? 0x80000000 : 0x00000001;
1416 /* Get the kernel's load entry */
1417 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1418 LDR_DATA_TABLE_ENTRY
,
1421 /* Find the banner message */
1422 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1428 /* Setup defaults and check if we have a version string */
1429 StringBuffer
= InitBuffer
->VersionBuffer
;
1430 BeginBuffer
= StringBuffer
;
1431 EndBuffer
= StringBuffer
;
1432 Remaining
= sizeof(InitBuffer
->VersionBuffer
);
1433 if (CmCSDVersionString
.Length
)
1435 /* Print the version string */
1436 Status
= RtlStringCbPrintfExA(StringBuffer
,
1442 &CmCSDVersionString
);
1443 if (!NT_SUCCESS(Status
))
1446 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1452 *EndBuffer
= ANSI_NULL
; /* Null-terminate the string */
1455 /* Skip over the null-terminator to start a new string */
1459 /* Build the version number */
1460 StringBuffer
= InitBuffer
->VersionNumber
;
1461 Status
= RtlStringCbPrintfA(StringBuffer
,
1462 sizeof(InitBuffer
->VersionNumber
),
1464 VER_PRODUCTMAJORVERSION
,
1465 VER_PRODUCTMINORVERSION
);
1466 if (!NT_SUCCESS(Status
))
1469 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1472 /* Check if we had found a banner message */
1473 if (NT_SUCCESS(MsgStatus
))
1475 /* Create the banner message */
1476 /* ReactOS specific: Report ReactOS version, NtBuildLab information and reported NT kernel version */
1477 Status
= RtlStringCbPrintfA(EndBuffer
,
1479 (PCHAR
)MsgEntry
->Text
,
1483 NtBuildNumber
& 0xFFFF,
1485 if (!NT_SUCCESS(Status
))
1488 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1493 /* Use hard-coded banner message */
1494 Status
= RtlStringCbCopyA(EndBuffer
, Remaining
, "REACTOS (R)\r\n");
1495 if (!NT_SUCCESS(Status
))
1498 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1502 /* Display the version string on-screen */
1503 InbvDisplayString(EndBuffer
);
1505 /* Initialize Power Subsystem in Phase 0 */
1506 if (!PoInitSystem(0)) KeBugCheck(INTERNAL_POWER_ERROR
);
1508 /* Check for Y2K hack */
1509 Y2KHackRequired
= CommandLine
? strstr(CommandLine
, "YEAR") : NULL
;
1510 if (Y2KHackRequired
) Y2KHackRequired
= strstr(Y2KHackRequired
, "=");
1511 if (Y2KHackRequired
) YearHack
= atol(Y2KHackRequired
+ 1);
1513 /* Query the clock */
1514 if ((ExCmosClockIsSane
) && (HalQueryRealTimeClock(&TimeFields
)))
1516 /* Check if we're using the Y2K hack */
1517 if (Y2KHackRequired
) TimeFields
.Year
= (CSHORT
)YearHack
;
1519 /* Convert to time fields */
1520 RtlTimeFieldsToTime(&TimeFields
, &SystemBootTime
);
1521 UniversalBootTime
= SystemBootTime
;
1523 /* Check if real time is GMT */
1524 if (!ExpRealTimeIsUniversal
)
1526 /* Check if we don't have a valid bias */
1527 if (ExpLastTimeZoneBias
== MAXULONG
)
1531 ExpLastTimeZoneBias
= ExpAltTimeZoneBias
;
1534 /* Calculate the bias in seconds */
1535 ExpTimeZoneBias
.QuadPart
= Int32x32To64(ExpLastTimeZoneBias
* 60,
1538 /* Set the boot time-zone bias */
1539 SharedUserData
->TimeZoneBias
.High2Time
= ExpTimeZoneBias
.HighPart
;
1540 SharedUserData
->TimeZoneBias
.LowPart
= ExpTimeZoneBias
.LowPart
;
1541 SharedUserData
->TimeZoneBias
.High1Time
= ExpTimeZoneBias
.HighPart
;
1543 /* Convert the boot time to local time, and set it */
1544 UniversalBootTime
.QuadPart
= SystemBootTime
.QuadPart
+
1545 ExpTimeZoneBias
.QuadPart
;
1548 /* Update the system time */
1549 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1551 /* Do system callback */
1552 PoNotifySystemTimeSet();
1554 /* Remember this as the boot time */
1555 KeBootTime
= UniversalBootTime
;
1559 /* Initialize all processors */
1560 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1563 /* HACK: We should use RtlFindMessage and not only fallback to this */
1564 MpString
= "MultiProcessor Kernel\r\n";
1567 /* Setup the "MP" String */
1568 RtlInitAnsiString(&TempString
, MpString
);
1570 /* Make sure to remove the \r\n if we actually have a string */
1571 while ((TempString
.Length
> 0) &&
1572 ((TempString
.Buffer
[TempString
.Length
- 1] == '\r') ||
1573 (TempString
.Buffer
[TempString
.Length
- 1] == '\n')))
1575 /* Skip the trailing character */
1576 TempString
.Length
--;
1579 /* Get the information string from our resource file */
1580 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1583 KeNumberProcessors
> 1 ?
1584 WINDOWS_NT_INFO_STRING_PLURAL
:
1585 WINDOWS_NT_INFO_STRING
,
1588 /* Get total RAM size, in MiB */
1589 /* Round size up. Assumed to better match actual physical RAM size */
1590 Size
= ALIGN_UP_BY(MmNumberOfPhysicalPages
* PAGE_SIZE
, 1024 * 1024) / (1024 * 1024);
1592 /* Create the string */
1593 StringBuffer
= InitBuffer
->VersionBuffer
;
1594 Status
= RtlStringCbPrintfA(StringBuffer
,
1595 sizeof(InitBuffer
->VersionBuffer
),
1596 NT_SUCCESS(MsgStatus
) ?
1597 (PCHAR
)MsgEntry
->Text
:
1598 "%u System Processor [%Iu MB Memory] %Z\r\n",
1602 if (!NT_SUCCESS(Status
))
1605 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
1608 /* Display RAM and CPU count */
1609 InbvDisplayString(StringBuffer
);
1611 /* Update the progress bar */
1612 InbvUpdateProgressBar(5);
1614 /* Call OB initialization again */
1615 if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED
);
1617 /* Initialize Basic System Objects and Worker Threads */
1618 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 1, 0);
1620 /* Initialize the later stages of the kernel */
1621 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 2, 0);
1623 /* Call KD Providers at Phase 1 */
1624 if (!KdInitSystem(ExpInitializationPhase
, KeLoaderBlock
))
1626 /* Failed, bugcheck */
1627 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 3, 0);
1630 /* Initialize the SRM in Phase 1 */
1631 if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED
);
1633 /* Update the progress bar */
1634 InbvUpdateProgressBar(10);
1636 /* Create SystemRoot Link */
1637 Status
= ExpCreateSystemRootLink(LoaderBlock
);
1638 if (!NT_SUCCESS(Status
))
1640 /* Failed to create the system root link */
1641 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1644 /* Set up Region Maps, Sections and the Paging File */
1645 if (!MmInitSystem(1, LoaderBlock
)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED
);
1647 /* Create NLS section */
1648 ExpInitNls(LoaderBlock
);
1650 /* Initialize Cache Views */
1651 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED
);
1653 /* Initialize the Registry */
1654 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
1656 /* Initialize Prefetcher */
1657 CcPfInitializePrefetcher();
1659 /* Update progress bar */
1660 InbvUpdateProgressBar(15);
1662 /* Update timezone information */
1663 LastTzBias
= ExpLastTimeZoneBias
;
1664 ExRefreshTimeZoneInformation(&SystemBootTime
);
1666 /* Check if we're resetting timezone data */
1669 /* Convert the local time to system time */
1670 ExLocalTimeToSystemTime(&SystemBootTime
, &UniversalBootTime
);
1671 KeBootTime
= UniversalBootTime
;
1674 /* Set the new time */
1675 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1679 /* Check if the timezone switched and update the time */
1680 if (LastTzBias
!= ExpLastTimeZoneBias
) ZwSetSystemTime(NULL
, NULL
);
1683 /* Initialize the File System Runtime Library */
1684 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED
);
1686 /* Initialize range lists */
1687 RtlInitializeRangeListPackage();
1689 /* Report all resources used by HAL */
1690 HalReportResourceUsage();
1692 /* Call the debugger DLL */
1693 KdDebuggerInitialize1(LoaderBlock
);
1695 /* Setup PnP Manager in phase 1 */
1696 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED
);
1698 /* Update progress bar */
1699 InbvUpdateProgressBar(20);
1701 /* Initialize LPC */
1702 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED
);
1704 /* Make sure we have a command line */
1707 /* Check if this is a safe mode boot */
1708 SafeBoot
= strstr(CommandLine
, "SAFEBOOT:");
1711 /* Check what kind of boot this is */
1713 if (!strncmp(SafeBoot
, "MINIMAL", 7))
1716 InitSafeBootMode
= 1;
1718 MessageCode
= BOOTING_IN_SAFEMODE_MINIMAL
;
1720 else if (!strncmp(SafeBoot
, "NETWORK", 7))
1722 /* With Networking */
1723 InitSafeBootMode
= 2;
1725 MessageCode
= BOOTING_IN_SAFEMODE_NETWORK
;
1727 else if (!strncmp(SafeBoot
, "DSREPAIR", 8))
1729 /* Domain Server Repair */
1730 InitSafeBootMode
= 3;
1732 MessageCode
= BOOTING_IN_SAFEMODE_DSREPAIR
;
1738 InitSafeBootMode
= 0;
1741 /* Check if there's any settings left */
1744 /* Check if an alternate shell was requested */
1745 if (!strncmp(SafeBoot
, "(ALTERNATESHELL)", 16))
1747 /* Remember this for later */
1748 AlternateShell
= TRUE
;
1752 /* Find the message to print out */
1753 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1758 if (NT_SUCCESS(Status
))
1761 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1766 /* Make sure we have a command line */
1769 /* Check if bootlogging is enabled */
1770 if (strstr(CommandLine
, "BOOTLOG"))
1772 /* Find the message to print out */
1773 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1778 if (NT_SUCCESS(Status
))
1781 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1784 /* Setup boot logging */
1785 //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader);
1789 /* Setup the Executive in Phase 2 */
1790 //ExInitSystemPhase2();
1792 /* Update progress bar */
1793 InbvUpdateProgressBar(25);
1796 /* No KD Time Slip is pending */
1797 KdpTimeSlipPending
= 0;
1800 /* Initialize in-place execution support */
1801 XIPInit(LoaderBlock
);
1803 /* Set maximum update to 75% */
1804 InbvSetProgressBarSubset(25, 75);
1806 /* Initialize the I/O Subsystem */
1807 if (!IoInitSystem(LoaderBlock
)) KeBugCheck(IO1_INITIALIZATION_FAILED
);
1809 /* Set maximum update to 100% */
1810 InbvSetProgressBarSubset(0, 100);
1812 /* Are we in safe mode? */
1813 if (InitSafeBootMode
)
1815 /* Open the safe boot key */
1816 RtlInitUnicodeString(&KeyName
,
1817 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1818 L
"\\CONTROL\\SAFEBOOT");
1819 InitializeObjectAttributes(&ObjectAttributes
,
1821 OBJ_CASE_INSENSITIVE
,
1824 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1825 if (NT_SUCCESS(Status
))
1827 /* First check if we have an alternate shell */
1830 /* Make sure that the registry has one setup */
1831 RtlInitUnicodeString(&KeyName
, L
"AlternateShell");
1832 Status
= NtQueryValueKey(KeyHandle
,
1834 KeyValuePartialInformation
,
1836 sizeof(KeyPartialInfo
),
1838 if (!(NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_OVERFLOW
))
1840 AlternateShell
= FALSE
;
1844 /* Create the option key */
1845 RtlInitUnicodeString(&KeyName
, L
"Option");
1846 InitializeObjectAttributes(&ObjectAttributes
,
1848 OBJ_CASE_INSENSITIVE
,
1851 Status
= ZwCreateKey(&OptionHandle
,
1856 REG_OPTION_VOLATILE
,
1860 /* Check if the key create worked */
1861 if (NT_SUCCESS(Status
))
1863 /* Write the safe boot type */
1864 RtlInitUnicodeString(&KeyName
, L
"OptionValue");
1865 NtSetValueKey(OptionHandle
,
1870 sizeof(InitSafeBootMode
));
1872 /* Check if we have to use an alternate shell */
1875 /* Remember this for later */
1877 RtlInitUnicodeString(&KeyName
, L
"UseAlternateShell");
1878 NtSetValueKey(OptionHandle
,
1883 sizeof(Disposition
));
1886 /* Close the options key handle */
1887 NtClose(OptionHandle
);
1892 /* Are we in Win PE mode? */
1893 if (InitIsWinPEMode
)
1895 /* Open the safe control key */
1896 RtlInitUnicodeString(&KeyName
,
1897 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1899 InitializeObjectAttributes(&ObjectAttributes
,
1901 OBJ_CASE_INSENSITIVE
,
1904 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1905 if (!NT_SUCCESS(Status
))
1908 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1911 /* Create the MiniNT key */
1912 RtlInitUnicodeString(&KeyName
, L
"MiniNT");
1913 InitializeObjectAttributes(&ObjectAttributes
,
1915 OBJ_CASE_INSENSITIVE
,
1918 Status
= ZwCreateKey(&OptionHandle
,
1923 REG_OPTION_VOLATILE
,
1925 if (!NT_SUCCESS(Status
))
1928 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1931 /* Close the handles */
1933 NtClose(OptionHandle
);
1936 /* FIXME: This doesn't do anything for now */
1937 MmArmInitSystem(2, LoaderBlock
);
1939 /* Update progress bar */
1940 InbvUpdateProgressBar(80);
1942 /* Initialize VDM support */
1943 #if defined(_M_IX86)
1944 KeI386VdmInitialize();
1947 /* Initialize Power Subsystem in Phase 1*/
1948 if (!PoInitSystem(1)) KeBugCheck(INTERNAL_POWER_ERROR
);
1950 /* Update progress bar */
1951 InbvUpdateProgressBar(90);
1953 /* Initialize the Process Manager at Phase 1 */
1954 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1956 /* Make sure nobody touches the loader block again */
1957 if (LoaderBlock
== KeLoaderBlock
) KeLoaderBlock
= NULL
;
1958 MmFreeLoaderBlock(LoaderBlock
);
1959 LoaderBlock
= Context
= NULL
;
1961 /* Initialize the SRM in phase 1 */
1962 if (!SeRmInitPhase1()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1964 /* Update progress bar */
1965 InbvUpdateProgressBar(100);
1967 /* Clear the screen */
1968 if (InbvBootDriverInstalled
) FinalizeBootLogo();
1970 /* Allow strings to be displayed */
1971 InbvEnableDisplayString(TRUE
);
1973 /* Launch initial process */
1974 DPRINT("Free non-cache pages: %lx\n", MmAvailablePages
+ MiMemoryConsumers
[MC_CACHE
].PagesUsed
);
1975 ProcessInfo
= &InitBuffer
->ProcessInfo
;
1976 ExpLoadInitialProcess(InitBuffer
, &ProcessParameters
, &Environment
);
1978 /* Wait 5 seconds for initial process to initialize */
1979 Timeout
.QuadPart
= Int32x32To64(5, -10000000);
1980 Status
= ZwWaitForSingleObject(ProcessInfo
->ProcessHandle
, FALSE
, &Timeout
);
1981 if (Status
== STATUS_SUCCESS
)
1983 /* Failed, display error */
1984 DPRINT1("INIT: Session Manager terminated.\n");
1986 /* Bugcheck the system if SMSS couldn't initialize */
1987 KeBugCheck(SESSION5_INITIALIZATION_FAILED
);
1990 /* Close process handles */
1991 ZwClose(ProcessInfo
->ThreadHandle
);
1992 ZwClose(ProcessInfo
->ProcessHandle
);
1994 /* Free the initial process environment */
1996 ZwFreeVirtualMemory(NtCurrentProcess(),
1997 (PVOID
*)&Environment
,
2001 /* Free the initial process parameters */
2003 ZwFreeVirtualMemory(NtCurrentProcess(),
2004 (PVOID
*)&ProcessParameters
,
2008 /* Increase init phase */
2009 ExpInitializationPhase
++;
2011 /* Free the boot buffer */
2012 ExFreePoolWithTag(InitBuffer
, TAG_INIT
);
2013 DPRINT("Free non-cache pages: %lx\n", MmAvailablePages
+ MiMemoryConsumers
[MC_CACHE
].PagesUsed
);
2018 Phase1Initialization(IN PVOID Context
)
2020 /* Do the .INIT part of Phase 1 which we can free later */
2021 Phase1InitializationDiscard(Context
);
2023 /* Jump into zero page thread */