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)
27 IN PLOADER_PARAMETER_BLOCK LoaderBlock
30 typedef struct _INIT_BUFFER
32 WCHAR DebugBuffer
[256];
33 CHAR VersionBuffer
[256];
34 CHAR BootlogHeader
[256];
35 CHAR VersionNumber
[24];
36 RTL_USER_PROCESS_INFORMATION ProcessInfo
;
37 WCHAR RegistryBuffer
[256];
38 } INIT_BUFFER
, *PINIT_BUFFER
;
40 /* DATA **********************************************************************/
43 ULONG NtMajorVersion
= VER_PRODUCTMAJORVERSION
;
44 ULONG NtMinorVersion
= VER_PRODUCTMINORVERSION
;
45 #if DBG /* Checked Build */
46 ULONG NtBuildNumber
= VER_PRODUCTBUILD
| 0xC0000000;
47 #else /* Free Build */
48 ULONG NtBuildNumber
= VER_PRODUCTBUILD
;
52 ULONG NtGlobalFlag
= 0;
56 ULONG CmNtSpBuildNumber
;
58 ULONG CmNtCSDReleaseType
;
59 UNICODE_STRING CmVersionString
;
60 UNICODE_STRING CmCSDVersionString
;
62 CHAR NtBuildLab
[] = KERNEL_VERSION_BUILD_STR
"."
63 REACTOS_COMPILER_NAME
"_" REACTOS_COMPILER_VERSION
;
65 /* Init flags and settings */
66 ULONG ExpInitializationPhase
;
67 BOOLEAN ExpInTextModeSetup
;
68 BOOLEAN IoRemoteBootClient
;
69 ULONG InitSafeBootMode
;
70 BOOLEAN InitIsWinPEMode
, InitWinPEModeType
;
73 UNICODE_STRING NtSystemRoot
;
75 /* NT Initial User Application */
76 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
77 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
79 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
81 /* Boot NLS information */
82 PVOID ExpNlsTableBase
;
83 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
84 ULONG ExpUnicodeCaseTableDataOffset
;
85 NLSTABLEINFO ExpNlsTableInfo
;
86 SIZE_T ExpNlsTableSize
;
87 PVOID ExpNlsSectionPointer
;
89 /* CMOS Timer Sanity */
90 BOOLEAN ExCmosClockIsSane
= TRUE
;
91 BOOLEAN ExpRealTimeIsUniversal
;
93 /* FUNCTIONS ****************************************************************/
98 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
100 UNICODE_STRING LinkName
;
101 OBJECT_ATTRIBUTES ObjectAttributes
;
104 ANSI_STRING AnsiName
;
106 ANSI_STRING TargetString
;
107 UNICODE_STRING TargetName
;
109 /* Initialize the ArcName tree */
110 RtlInitUnicodeString(&LinkName
, L
"\\ArcName");
111 InitializeObjectAttributes(&ObjectAttributes
,
113 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
115 SePublicDefaultUnrestrictedSd
);
118 Status
= NtCreateDirectoryObject(&LinkHandle
,
119 DIRECTORY_ALL_ACCESS
,
121 if (!NT_SUCCESS(Status
))
124 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
127 /* Close the LinkHandle */
130 /* Initialize the Device tree */
131 RtlInitUnicodeString(&LinkName
, L
"\\Device");
132 InitializeObjectAttributes(&ObjectAttributes
,
134 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
136 SePublicDefaultUnrestrictedSd
);
139 Status
= NtCreateDirectoryObject(&LinkHandle
,
140 DIRECTORY_ALL_ACCESS
,
142 if (!NT_SUCCESS(Status
))
145 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
148 /* Close the LinkHandle */
149 ObCloseHandle(LinkHandle
, KernelMode
);
151 /* Create the system root symlink name */
152 RtlInitAnsiString(&AnsiName
, "\\SystemRoot");
153 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &AnsiName
, TRUE
);
154 if (!NT_SUCCESS(Status
))
157 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
160 /* Initialize the attributes for the link */
161 InitializeObjectAttributes(&ObjectAttributes
,
163 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
165 SePublicDefaultUnrestrictedSd
);
167 /* Build the ARC name */
170 LoaderBlock
->ArcBootDeviceName
,
171 LoaderBlock
->NtBootPathName
);
172 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
174 /* Convert it to Unicode */
175 RtlInitString(&TargetString
, Buffer
);
176 Status
= RtlAnsiStringToUnicodeString(&TargetName
,
179 if (!NT_SUCCESS(Status
))
181 /* We failed, bugcheck */
182 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
186 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
187 SYMBOLIC_LINK_ALL_ACCESS
,
191 /* Free the strings */
192 RtlFreeUnicodeString(&LinkName
);
193 RtlFreeUnicodeString(&TargetName
);
195 /* Check if creating the link failed */
196 if (!NT_SUCCESS(Status
))
199 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
202 /* Close the handle and return success */
203 ObCloseHandle(LinkHandle
, KernelMode
);
204 return STATUS_SUCCESS
;
210 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
212 LARGE_INTEGER SectionSize
;
215 PVOID SectionBase
= NULL
;
217 LARGE_INTEGER SectionOffset
= {{0, 0}};
218 PLIST_ENTRY ListHead
, NextEntry
;
219 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
220 ULONG NlsTablesEncountered
= 0;
221 SIZE_T NlsTableSizes
[3] = {0, 0, 0}; /* 3 NLS tables */
223 /* Check if this is boot-time phase 0 initialization */
224 if (!ExpInitializationPhase
)
226 /* Loop the memory descriptors */
227 ListHead
= &LoaderBlock
->MemoryDescriptorListHead
;
228 NextEntry
= ListHead
->Flink
;
229 while (NextEntry
!= ListHead
)
231 /* Get the current block */
232 MdBlock
= CONTAINING_RECORD(NextEntry
,
233 MEMORY_ALLOCATION_DESCRIPTOR
,
236 /* Check if this is an NLS block */
237 if (MdBlock
->MemoryType
== LoaderNlsData
)
239 /* Increase the table size */
240 ExpNlsTableSize
+= MdBlock
->PageCount
* PAGE_SIZE
;
242 /* FreeLdr-specific */
243 NlsTableSizes
[NlsTablesEncountered
] = MdBlock
->PageCount
* PAGE_SIZE
;
244 NlsTablesEncountered
++;
245 ASSERT(NlsTablesEncountered
< 4);
248 /* Go to the next block */
249 NextEntry
= MdBlock
->ListEntry
.Flink
;
252 /* Allocate the a new buffer since loader memory will be freed */
253 ExpNlsTableBase
= ExAllocatePoolWithTag(NonPagedPool
,
256 if (!ExpNlsTableBase
) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
258 /* Copy the codepage data in its new location. */
259 if (NlsTablesEncountered
== 1)
261 /* Ntldr-way boot process */
262 RtlCopyMemory(ExpNlsTableBase
,
263 LoaderBlock
->NlsData
->AnsiCodePageData
,
269 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
270 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
272 RtlCopyMemory(ExpNlsTableBase
,
273 LoaderBlock
->NlsData
->AnsiCodePageData
,
276 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0]),
277 LoaderBlock
->NlsData
->OemCodePageData
,
280 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0] +
282 LoaderBlock
->NlsData
->UnicodeCodePageData
,
287 /* Initialize and reset the NLS TAbles */
288 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
289 ExpAnsiCodePageDataOffset
),
290 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
291 ExpOemCodePageDataOffset
),
292 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
293 ExpUnicodeCaseTableDataOffset
),
295 RtlResetRtlTranslations(&ExpNlsTableInfo
);
299 /* Set the section size */
300 SectionSize
.QuadPart
= ExpNlsTableSize
;
302 /* Create the NLS Section */
303 Status
= ZwCreateSection(&NlsSection
,
310 if (!NT_SUCCESS(Status
))
313 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
316 /* Get a pointer to the section */
317 Status
= ObReferenceObjectByHandle(NlsSection
,
321 &ExpNlsSectionPointer
,
323 ObCloseHandle(NlsSection
, KernelMode
);
324 if (!NT_SUCCESS(Status
))
327 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
330 /* Map the NLS Section in system space */
331 Status
= MmMapViewInSystemSpace(ExpNlsSectionPointer
,
334 if (!NT_SUCCESS(Status
))
337 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
340 /* Copy the codepage data in its new location. */
341 ASSERT(SectionBase
>= MmSystemRangeStart
);
342 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
344 /* Free the previously allocated buffer and set the new location */
345 ExFreePoolWithTag(ExpNlsTableBase
, TAG_RTLI
);
346 ExpNlsTableBase
= SectionBase
;
348 /* Initialize the NLS Tables */
349 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
350 ExpAnsiCodePageDataOffset
),
351 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
352 ExpOemCodePageDataOffset
),
353 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
354 ExpUnicodeCaseTableDataOffset
),
356 RtlResetRtlTranslations(&ExpNlsTableInfo
);
358 /* Reset the base to 0 */
361 /* Map the section in the system process */
362 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
363 PsGetCurrentProcess(),
372 if (!NT_SUCCESS(Status
))
375 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
378 /* Copy the table into the system process and set this as the base */
379 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
380 ExpNlsTableBase
= SectionBase
;
386 ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer
,
387 OUT PRTL_USER_PROCESS_PARAMETERS
*ProcessParameters
,
388 OUT PCHAR
*ProcessEnvironment
)
393 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
394 UNICODE_STRING SmssName
, Environment
, SystemDriveString
, DebugString
;
395 PVOID EnvironmentPtr
= NULL
;
396 PRTL_USER_PROCESS_INFORMATION ProcessInformation
;
397 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= NULL
;
399 NullString
.Length
= sizeof(WCHAR
);
401 /* Use the initial buffer, after the strings */
402 ProcessInformation
= &InitBuffer
->ProcessInfo
;
404 /* Allocate memory for the process parameters */
405 Size
= sizeof(*ProcessParams
) + ((MAX_WIN32_PATH
* 6) * sizeof(WCHAR
));
406 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
407 (PVOID
*)&ProcessParams
,
410 MEM_RESERVE
| MEM_COMMIT
,
412 if (!NT_SUCCESS(Status
))
414 /* Failed, display error */
415 _snwprintf(InitBuffer
->DebugBuffer
,
416 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
417 L
"INIT: Unable to allocate Process Parameters. 0x%lx",
419 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
420 ZwDisplayString(&DebugString
);
422 /* Bugcheck the system */
423 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
426 /* Setup the basic header, and give the process the low 1MB to itself */
427 ProcessParams
->Length
= (ULONG
)Size
;
428 ProcessParams
->MaximumLength
= (ULONG
)Size
;
429 ProcessParams
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
430 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
432 /* Allocate a page for the environment */
434 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
438 MEM_RESERVE
| MEM_COMMIT
,
440 if (!NT_SUCCESS(Status
))
442 /* Failed, display error */
443 _snwprintf(InitBuffer
->DebugBuffer
,
444 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
445 L
"INIT: Unable to allocate Process Environment. 0x%lx",
447 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
448 ZwDisplayString(&DebugString
);
450 /* Bugcheck the system */
451 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
454 /* Write the pointer */
455 ProcessParams
->Environment
= EnvironmentPtr
;
457 /* Make a buffer for the DOS path */
458 p
= (PWSTR
)(ProcessParams
+ 1);
459 ProcessParams
->CurrentDirectory
.DosPath
.Buffer
= p
;
460 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
= MAX_WIN32_PATH
*
463 /* Copy the DOS path */
464 RtlCopyUnicodeString(&ProcessParams
->CurrentDirectory
.DosPath
,
467 /* Make a buffer for the DLL Path */
468 p
= (PWSTR
)((PCHAR
)ProcessParams
->CurrentDirectory
.DosPath
.Buffer
+
469 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
);
470 ProcessParams
->DllPath
.Buffer
= p
;
471 ProcessParams
->DllPath
.MaximumLength
= MAX_WIN32_PATH
* sizeof(WCHAR
);
473 /* Copy the DLL path and append the system32 directory */
474 RtlCopyUnicodeString(&ProcessParams
->DllPath
,
475 &ProcessParams
->CurrentDirectory
.DosPath
);
476 RtlAppendUnicodeToString(&ProcessParams
->DllPath
, L
"\\System32");
478 /* Make a buffer for the image name */
479 p
= (PWSTR
)((PCHAR
)ProcessParams
->DllPath
.Buffer
+
480 ProcessParams
->DllPath
.MaximumLength
);
481 ProcessParams
->ImagePathName
.Buffer
= p
;
482 ProcessParams
->ImagePathName
.MaximumLength
= MAX_WIN32_PATH
* sizeof(WCHAR
);
484 /* Make sure the buffer is a valid string which within the given length */
485 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
486 ((NtInitialUserProcessBufferLength
!= MAXULONG
) &&
487 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
488 (NtInitialUserProcessBufferLength
>
489 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
491 /* Invalid initial process string, bugcheck */
492 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
,
493 STATUS_INVALID_PARAMETER
,
494 NtInitialUserProcessBufferType
,
495 NtInitialUserProcessBufferLength
,
496 sizeof(NtInitialUserProcessBuffer
));
499 /* Cut out anything after a space */
500 p
= NtInitialUserProcessBuffer
;
501 while ((*p
) && (*p
!= L
' ')) p
++;
503 /* Set the image path length */
504 ProcessParams
->ImagePathName
.Length
=
505 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
507 /* Copy the actual buffer */
508 RtlCopyMemory(ProcessParams
->ImagePathName
.Buffer
,
509 NtInitialUserProcessBuffer
,
510 ProcessParams
->ImagePathName
.Length
);
512 /* Null-terminate it */
513 ProcessParams
->ImagePathName
.Buffer
[ProcessParams
->ImagePathName
.Length
/
514 sizeof(WCHAR
)] = UNICODE_NULL
;
516 /* Make a buffer for the command line */
517 p
= (PWSTR
)((PCHAR
)ProcessParams
->ImagePathName
.Buffer
+
518 ProcessParams
->ImagePathName
.MaximumLength
);
519 ProcessParams
->CommandLine
.Buffer
= p
;
520 ProcessParams
->CommandLine
.MaximumLength
= MAX_WIN32_PATH
* sizeof(WCHAR
);
522 /* Add the image name to the command line */
523 RtlAppendUnicodeToString(&ProcessParams
->CommandLine
,
524 NtInitialUserProcessBuffer
);
526 /* Create the environment string */
527 RtlInitEmptyUnicodeString(&Environment
,
528 ProcessParams
->Environment
,
531 /* Append the DLL path to it */
532 RtlAppendUnicodeToString(&Environment
, L
"Path=");
533 RtlAppendUnicodeStringToString(&Environment
, &ProcessParams
->DllPath
);
534 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
536 /* Create the system drive string */
537 SystemDriveString
= NtSystemRoot
;
538 SystemDriveString
.Length
= 2 * sizeof(WCHAR
);
540 /* Append it to the environment */
541 RtlAppendUnicodeToString(&Environment
, L
"SystemDrive=");
542 RtlAppendUnicodeStringToString(&Environment
, &SystemDriveString
);
543 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
545 /* Append the system root to the environment */
546 RtlAppendUnicodeToString(&Environment
, L
"SystemRoot=");
547 RtlAppendUnicodeStringToString(&Environment
, &NtSystemRoot
);
548 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
550 /* Prepare the prefetcher */
551 //CcPfBeginBootPhase(150);
553 /* Create SMSS process */
554 SmssName
= ProcessParams
->ImagePathName
;
555 Status
= RtlCreateUserProcess(&SmssName
,
556 OBJ_CASE_INSENSITIVE
,
557 RtlDeNormalizeProcessParams(ProcessParams
),
565 if (!NT_SUCCESS(Status
))
567 /* Failed, display error */
568 _snwprintf(InitBuffer
->DebugBuffer
,
569 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
570 L
"INIT: Unable to create Session Manager. 0x%lx",
572 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
573 ZwDisplayString(&DebugString
);
575 /* Bugcheck the system */
576 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
579 /* Resume the thread */
580 Status
= ZwResumeThread(ProcessInformation
->ThreadHandle
, NULL
);
581 if (!NT_SUCCESS(Status
))
583 /* Failed, display error */
584 _snwprintf(InitBuffer
->DebugBuffer
,
585 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
586 L
"INIT: Unable to resume Session Manager. 0x%lx",
588 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
589 ZwDisplayString(&DebugString
);
591 /* Bugcheck the system */
592 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
596 *ProcessParameters
= ProcessParams
;
597 *ProcessEnvironment
= EnvironmentPtr
;
603 ExComputeTickCountMultiplier(IN ULONG ClockIncrement
)
605 ULONG MsRemainder
= 0, MsIncrement
;
606 ULONG IncrementRemainder
;
609 /* Count the number of milliseconds for each clock interrupt */
610 MsIncrement
= ClockIncrement
/ (10 * 1000);
612 /* Count the remainder from the division above, with 24-bit precision */
613 IncrementRemainder
= ClockIncrement
- (MsIncrement
* (10 * 1000));
614 for (i
= 0; i
< 24; i
++)
616 /* Shift the remainders */
618 IncrementRemainder
<<= 1;
620 /* Check if we've went past 1 ms */
621 if (IncrementRemainder
>= (10 * 1000))
623 /* Increase the remainder by one, and substract from increment */
624 IncrementRemainder
-= (10 * 1000);
629 /* Return the increment */
630 return (MsIncrement
<< 24) | MsRemainder
;
636 ExpInitSystemPhase0(VOID
)
638 /* Initialize EXRESOURCE Support */
639 ExpResourceInitialization();
641 /* Initialize the environment lock */
642 ExInitializeFastMutex(&ExpEnvironmentLock
);
644 /* Initialize the lookaside lists and locks */
645 ExpInitLookasideLists();
647 /* Initialize the Firmware Table resource and listhead */
648 InitializeListHead(&ExpFirmwareTableProviderListHead
);
649 ExInitializeResourceLite(&ExpFirmwareTableResource
);
651 /* Set the suite mask to maximum and return */
652 ExSuiteMask
= 0xFFFFFFFF;
659 ExpInitSystemPhase1(VOID
)
661 /* Initialize worker threads */
662 ExpInitializeWorkerThreads();
664 /* Initialize pushlocks */
665 ExpInitializePushLocks();
667 /* Initialize events and event pairs */
668 if (ExpInitializeEventImplementation() == FALSE
)
670 DPRINT1("Executive: Event initialization failed\n");
673 if (ExpInitializeEventPairImplementation() == FALSE
)
675 DPRINT1("Executive: Event Pair initialization failed\n");
679 /* Initialize mutants */
680 if (ExpInitializeMutantImplementation() == FALSE
)
682 DPRINT1("Executive: Mutant initialization failed\n");
686 /* Initialize callbacks */
687 if (ExpInitializeCallbacks() == FALSE
)
689 DPRINT1("Executive: Callback initialization failed\n");
693 /* Initialize semaphores */
694 if (ExpInitializeSemaphoreImplementation() == FALSE
)
696 DPRINT1("Executive: Semaphore initialization failed\n");
700 /* Initialize timers */
701 if (ExpInitializeTimerImplementation() == FALSE
)
703 DPRINT1("Executive: Timer initialization failed\n");
707 /* Initialize profiling */
708 if (ExpInitializeProfileImplementation() == FALSE
)
710 DPRINT1("Executive: Profile initialization failed\n");
714 /* Initialize UUIDs */
715 if (ExpUuidInitialization() == FALSE
)
717 DPRINT1("Executive: Uuid initialization failed\n");
721 /* Initialize keyed events */
722 if (ExpInitializeKeyedEventImplementation() == FALSE
)
724 DPRINT1("Executive: Keyed event initialization failed\n");
728 /* Initialize Win32K */
729 if (ExpWin32kInit() == FALSE
)
731 DPRINT1("Executive: Win32 initialization failed\n");
742 /* Check the initialization phase */
743 switch (ExpInitializationPhase
)
748 return ExpInitSystemPhase0();
753 return ExpInitSystemPhase1();
757 /* Don't know any other phase! Bugcheck! */
758 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
766 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
768 PLOADER_PARAMETER_EXTENSION Extension
;
770 /* Get the loader extension */
771 Extension
= LoaderBlock
->Extension
;
773 /* Validate the size (Windows 2003 loader doesn't provide more) */
774 if (Extension
->Size
< LOADER_PARAMETER_EXTENSION_MIN_SIZE
) return FALSE
;
776 /* Don't validate upper versions */
777 if (Extension
->MajorVersion
> VER_PRODUCTMAJORVERSION
) return TRUE
;
779 /* Fail if this is NT 4 */
780 if (Extension
->MajorVersion
< VER_PRODUCTMAJORVERSION
) return FALSE
;
782 /* Fail if this is XP */
783 if (Extension
->MinorVersion
< VER_PRODUCTMINORVERSION
) return FALSE
;
785 /* This is 2003 or newer, approve it */
792 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
795 PLIST_ENTRY NextEntry
;
798 PLDR_DATA_TABLE_ENTRY LdrEntry
;
799 CHAR NameBuffer
[256];
803 /* Loop the driver list */
804 NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
805 while (NextEntry
!= &LoaderBlock
->LoadOrderListHead
)
807 /* Skip the first two images */
811 LdrEntry
= CONTAINING_RECORD(NextEntry
,
812 LDR_DATA_TABLE_ENTRY
,
814 if (LdrEntry
->FullDllName
.Buffer
[0] == L
'\\')
816 /* We have a name, read its data */
817 Name
= LdrEntry
->FullDllName
.Buffer
;
818 Length
= LdrEntry
->FullDllName
.Length
/ sizeof(WCHAR
);
820 /* Check if our buffer can hold it */
821 if (sizeof(NameBuffer
) < Length
+ sizeof(ANSI_NULL
))
824 Status
= STATUS_BUFFER_OVERFLOW
;
832 /* Copy the character */
833 NameBuffer
[Count
++] = (CHAR
)*Name
++;
834 } while (Count
< Length
);
837 NameBuffer
[Count
] = ANSI_NULL
;
838 Status
= STATUS_SUCCESS
;
843 /* Safely print the string into our buffer */
844 Status
= RtlStringCbPrintfA(NameBuffer
,
846 "%S\\System32\\Drivers\\%wZ",
847 &SharedUserData
->NtSystemRoot
[2],
848 &LdrEntry
->BaseDllName
);
851 /* Check if the buffer was ok */
852 if (NT_SUCCESS(Status
))
854 /* Initialize the STRING for the debugger */
855 RtlInitString(&SymbolString
, NameBuffer
);
857 /* Load the symbols */
858 DbgLoadImageSymbols(&SymbolString
,
860 (ULONG_PTR
)PsGetCurrentProcessId());
864 /* Go to the next entry */
866 NextEntry
= NextEntry
->Flink
;
873 ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
874 IN ULONG_PTR PagesToDestroy
,
875 IN TYPE_OF_MEMORY MemoryType
)
877 PLIST_ENTRY ListEntry
;
878 PMEMORY_ALLOCATION_DESCRIPTOR MemDescriptor
;
880 DPRINT1("Burn RAM amount: %lu pages\n", PagesToDestroy
);
882 /* Loop the memory descriptors, beginning at the end */
883 for (ListEntry
= LoaderBlock
->MemoryDescriptorListHead
.Blink
;
884 ListEntry
!= &LoaderBlock
->MemoryDescriptorListHead
;
885 ListEntry
= ListEntry
->Blink
)
887 /* Get the memory descriptor structure */
888 MemDescriptor
= CONTAINING_RECORD(ListEntry
,
889 MEMORY_ALLOCATION_DESCRIPTOR
,
892 /* Is memory free there or is it temporary? */
893 if (MemDescriptor
->MemoryType
== LoaderFree
||
894 MemDescriptor
->MemoryType
== LoaderFirmwareTemporary
)
896 /* Check if the descriptor has more pages than we want */
897 if (MemDescriptor
->PageCount
> PagesToDestroy
)
899 /* Change block's page count, ntoskrnl doesn't care much */
900 MemDescriptor
->PageCount
-= PagesToDestroy
;
905 /* Change block type */
906 MemDescriptor
->MemoryType
= MemoryType
;
907 PagesToDestroy
-= MemDescriptor
->PageCount
;
909 /* Check if we are done */
910 if (PagesToDestroy
== 0) break;
919 ExpInitializeExecutive(IN ULONG Cpu
,
920 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
922 PNLS_DATA_BLOCK NlsData
;
924 ANSI_STRING AnsiPath
;
926 PCHAR CommandLine
, PerfMem
;
928 PLDR_DATA_TABLE_ENTRY NtosEntry
;
929 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
930 ANSI_STRING CSDString
;
931 size_t Remaining
= 0;
933 CHAR VersionBuffer
[65];
935 /* Validate Loader */
936 if (!ExpIsLoaderValid(LoaderBlock
))
938 /* Invalid loader version */
939 KeBugCheckEx(MISMATCHED_HAL
,
941 LoaderBlock
->Extension
->Size
,
942 LoaderBlock
->Extension
->MajorVersion
,
943 LoaderBlock
->Extension
->MinorVersion
);
946 /* Initialize PRCB pool lookaside pointers */
947 ExInitPoolLookasidePointers();
949 /* Check if this is an application CPU */
952 /* Then simply initialize it with HAL */
953 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
955 /* Initialization failed */
956 KeBugCheck(HAL_INITIALIZATION_FAILED
);
963 /* Assume no text-mode or remote boot */
964 ExpInTextModeSetup
= FALSE
;
965 IoRemoteBootClient
= FALSE
;
967 /* Check if we have a setup loader block */
968 if (LoaderBlock
->SetupLdrBlock
)
970 /* Check if this is text-mode setup */
971 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_TEXT_MODE
)
972 ExpInTextModeSetup
= TRUE
;
974 /* Check if this is network boot */
975 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_REMOTE_BOOT
)
978 IoRemoteBootClient
= TRUE
;
980 /* Make sure we're actually booting off the network */
981 ASSERT(!_memicmp(LoaderBlock
->ArcBootDeviceName
, "net(0)", 6));
986 ExpInitializationPhase
= 0;
988 /* Get boot command line */
989 CommandLine
= LoaderBlock
->LoadOptions
;
992 /* Upcase it for comparison and check if we're in performance mode */
993 _strupr(CommandLine
);
994 PerfMem
= strstr(CommandLine
, "PERFMEM");
997 /* Check if the user gave a number of bytes to use */
998 PerfMem
= strstr(PerfMem
, "=");
1001 /* Read the number of pages we'll use */
1002 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
1006 DPRINT1("BBT performance mode not yet supported."
1007 "/PERFMEM option ignored.\n");
1012 /* Check if we're burning memory */
1013 PerfMem
= strstr(CommandLine
, "BURNMEMORY");
1016 /* Check if the user gave a number of bytes to use */
1017 PerfMem
= strstr(PerfMem
, "=");
1020 /* Read the number of pages we'll use */
1021 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
1022 if (PerfMemUsed
) ExBurnMemory(LoaderBlock
, PerfMemUsed
, LoaderBad
);
1027 /* Setup NLS Base and offsets */
1028 NlsData
= LoaderBlock
->NlsData
;
1029 ExpNlsTableBase
= NlsData
->AnsiCodePageData
;
1030 ExpAnsiCodePageDataOffset
= 0;
1031 ExpOemCodePageDataOffset
= (ULONG
)((ULONG_PTR
)NlsData
->OemCodePageData
-
1032 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
1033 ExpUnicodeCaseTableDataOffset
= (ULONG
)((ULONG_PTR
)NlsData
->UnicodeCodePageData
-
1034 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
1036 /* Initialize the NLS Tables */
1037 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1038 ExpAnsiCodePageDataOffset
),
1039 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1040 ExpOemCodePageDataOffset
),
1041 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1042 ExpUnicodeCaseTableDataOffset
),
1044 RtlResetRtlTranslations(&ExpNlsTableInfo
);
1046 /* Now initialize the HAL */
1047 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
1049 /* HAL failed to initialize, bugcheck */
1050 KeBugCheck(HAL_INITIALIZATION_FAILED
);
1053 /* Make sure interrupts are active now */
1056 /* Clear the crypto exponent */
1057 SharedUserData
->CryptoExponent
= 0;
1059 /* Set global flags for the checked build */
1061 NtGlobalFlag
|= FLG_ENABLE_CLOSE_EXCEPTIONS
|
1062 FLG_ENABLE_KDEBUG_SYMBOL_LOAD
;
1065 /* Setup NT System Root Path */
1066 sprintf(Buffer
, "C:%s", LoaderBlock
->NtBootPathName
);
1068 /* Convert to ANSI_STRING and null-terminate it */
1069 RtlInitString(&AnsiPath
, Buffer
);
1070 Buffer
[--AnsiPath
.Length
] = ANSI_NULL
;
1072 /* Get the string from KUSER_SHARED_DATA's buffer */
1073 RtlInitEmptyUnicodeString(&NtSystemRoot
,
1074 SharedUserData
->NtSystemRoot
,
1075 sizeof(SharedUserData
->NtSystemRoot
));
1077 /* Now fill it in */
1078 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &AnsiPath
, FALSE
);
1079 if (!NT_SUCCESS(Status
)) KeBugCheck(SESSION3_INITIALIZATION_FAILED
);
1081 /* Setup bugcheck messages */
1082 KiInitializeBugCheck();
1084 /* Setup initial system settings */
1085 CmGetSystemControlValues(LoaderBlock
->RegistryBase
, CmControlVector
);
1087 /* Set the Service Pack Number and add it to the CSD Version number if needed */
1088 CmNtSpBuildNumber
= VER_PRODUCTBUILD_QFE
;
1089 if (((CmNtCSDVersion
& 0xFFFF0000) == 0) && (CmNtCSDReleaseType
== 1))
1091 CmNtCSDVersion
|= (VER_PRODUCTBUILD_QFE
<< 16);
1094 /* Add loaded CmNtGlobalFlag value */
1095 NtGlobalFlag
|= CmNtGlobalFlag
;
1097 /* Initialize the executive at phase 0 */
1098 if (!ExInitSystem()) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1100 /* Initialize the memory manager at phase 0 */
1101 if (!MmArmInitSystem(0, LoaderBlock
)) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1103 /* Load boot symbols */
1104 ExpLoadBootSymbols(LoaderBlock
);
1106 /* Check if we should break after symbol load */
1107 if (KdBreakAfterSymbolLoad
) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
1109 /* Check if this loader is compatible with NT 5.2 */
1110 if (LoaderBlock
->Extension
->Size
>= sizeof(LOADER_PARAMETER_EXTENSION
))
1112 /* Setup headless terminal settings */
1113 HeadlessInit(LoaderBlock
);
1116 /* Set system ranges */
1118 SharedUserData
->Reserved1
= MM_HIGHEST_USER_ADDRESS_WOW64
;
1119 SharedUserData
->Reserved3
= MM_SYSTEM_RANGE_START_WOW64
;
1121 SharedUserData
->Reserved1
= (ULONG_PTR
)MmHighestUserAddress
;
1122 SharedUserData
->Reserved3
= (ULONG_PTR
)MmSystemRangeStart
;
1125 /* Make a copy of the NLS Tables */
1126 ExpInitNls(LoaderBlock
);
1128 /* Get the kernel's load entry */
1129 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1130 LDR_DATA_TABLE_ENTRY
,
1133 /* Check if this is a service pack */
1134 if (CmNtCSDVersion
& 0xFFFF)
1136 /* Get the service pack string */
1137 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1140 WINDOWS_NT_CSD_STRING
,
1142 if (NT_SUCCESS(Status
))
1144 /* Setup the string */
1145 RtlInitAnsiString(&CSDString
, (PCHAR
)MsgEntry
->Text
);
1147 /* Remove trailing newline */
1148 while ((CSDString
.Length
> 0) &&
1149 ((CSDString
.Buffer
[CSDString
.Length
- 1] == '\r') ||
1150 (CSDString
.Buffer
[CSDString
.Length
- 1] == '\n')))
1152 /* Skip the trailing character */
1156 /* Fill the buffer with version information */
1157 Status
= RtlStringCbPrintfA(Buffer
,
1161 (CmNtCSDVersion
& 0xFF00) >> 8,
1162 (CmNtCSDVersion
& 0xFF) ?
1163 'A' + (CmNtCSDVersion
& 0xFF) - 1 :
1168 /* Build default string */
1169 Status
= RtlStringCbPrintfA(Buffer
,
1175 /* Check for success */
1176 if (!NT_SUCCESS(Status
))
1179 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1184 /* Then this is a beta */
1185 Status
= RtlStringCbCopyExA(Buffer
,
1187 VER_PRODUCTBETA_STR
,
1191 if (!NT_SUCCESS(Status
))
1194 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1198 CmCSDVersionString
.MaximumLength
= sizeof(Buffer
) - (USHORT
)Remaining
;
1201 /* Check if we have an RC number */
1202 if ((CmNtCSDVersion
& 0xFFFF0000) && (CmNtCSDReleaseType
== 1))
1204 /* Check if we have no version data yet */
1208 Remaining
= sizeof(Buffer
);
1213 /* Add comma and space */
1214 Status
= RtlStringCbCatExA(Buffer
,
1220 if (!NT_SUCCESS(Status
))
1223 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1227 /* Add the version format string */
1228 Status
= RtlStringCbPrintfA(RcEnd
,
1231 (CmNtCSDVersion
& 0xFFFF0000) >> 16);
1232 if (!NT_SUCCESS(Status
))
1235 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1239 /* Now setup the final string */
1240 RtlInitAnsiString(&CSDString
, Buffer
);
1241 Status
= RtlAnsiStringToUnicodeString(&CmCSDVersionString
,
1244 if (!NT_SUCCESS(Status
))
1247 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1250 /* Add our version */
1251 Status
= RtlStringCbPrintfA(VersionBuffer
,
1252 sizeof(VersionBuffer
),
1254 VER_PRODUCTMAJORVERSION
,
1255 VER_PRODUCTMINORVERSION
);
1256 if (!NT_SUCCESS(Status
))
1259 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1262 /* Build the final version string */
1263 RtlCreateUnicodeStringFromAsciiz(&CmVersionString
, VersionBuffer
);
1265 /* Check if the user wants a kernel stack trace database */
1266 if (NtGlobalFlag
& FLG_KERNEL_STACK_TRACE_DB
)
1269 DPRINT1("Kernel-mode stack trace support not yet present."
1270 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
1273 /* Check if he wanted exception logging */
1274 if (NtGlobalFlag
& FLG_ENABLE_EXCEPTION_LOGGING
)
1277 DPRINT1("Kernel-mode exception logging support not yet present."
1278 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
1281 /* Initialize the Handle Table */
1282 ExpInitializeHandleTables();
1285 /* On checked builds, allocate the system call count table */
1286 KeServiceDescriptorTable
[0].Count
=
1287 ExAllocatePoolWithTag(NonPagedPool
,
1288 KiServiceLimit
* sizeof(ULONG
),
1291 /* Use it for the shadow table too */
1292 KeServiceDescriptorTableShadow
[0].Count
= KeServiceDescriptorTable
[0].Count
;
1294 /* Make sure allocation succeeded */
1295 if (KeServiceDescriptorTable
[0].Count
)
1297 /* Zero the call counts to 0 */
1298 RtlZeroMemory(KeServiceDescriptorTable
[0].Count
,
1299 KiServiceLimit
* sizeof(ULONG
));
1303 /* Create the Basic Object Manager Types to allow new Object Types */
1304 if (!ObInitSystem()) KeBugCheck(OBJECT_INITIALIZATION_FAILED
);
1306 /* Load basic Security for other Managers */
1307 if (!SeInitSystem()) KeBugCheck(SECURITY_INITIALIZATION_FAILED
);
1309 /* Initialize the Process Manager */
1310 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS_INITIALIZATION_FAILED
);
1312 /* Initialize the PnP Manager */
1313 if (!PpInitSystem()) KeBugCheck(PP0_INITIALIZATION_FAILED
);
1315 /* Initialize the User-Mode Debugging Subsystem */
1318 /* Calculate the tick count multiplier */
1319 ExpTickCountMultiplier
= ExComputeTickCountMultiplier(KeMaximumIncrement
);
1320 SharedUserData
->TickCountMultiplier
= ExpTickCountMultiplier
;
1322 /* Set the OS Version */
1323 SharedUserData
->NtMajorVersion
= NtMajorVersion
;
1324 SharedUserData
->NtMinorVersion
= NtMinorVersion
;
1326 /* Set the machine type */
1327 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_NATIVE
;
1328 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_NATIVE
;
1333 MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
1338 Phase1InitializationDiscard(IN PVOID Context
)
1340 PLOADER_PARAMETER_BLOCK LoaderBlock
= Context
;
1341 NTSTATUS Status
, MsgStatus
;
1342 TIME_FIELDS TimeFields
;
1343 LARGE_INTEGER SystemBootTime
, UniversalBootTime
, OldTime
, Timeout
;
1344 BOOLEAN SosEnabled
, NoGuiBoot
, ResetBias
= FALSE
, AlternateShell
= FALSE
;
1345 PLDR_DATA_TABLE_ENTRY NtosEntry
;
1346 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
1347 PCHAR CommandLine
, Y2KHackRequired
, SafeBoot
, Environment
;
1348 PCHAR StringBuffer
, EndBuffer
, BeginBuffer
, MpString
= "";
1349 PINIT_BUFFER InitBuffer
;
1350 ANSI_STRING TempString
;
1351 ULONG LastTzBias
, Length
, YearHack
= 0, Disposition
, MessageCode
= 0;
1354 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
1355 KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo
;
1356 UNICODE_STRING KeyName
;
1357 OBJECT_ATTRIBUTES ObjectAttributes
;
1358 HANDLE KeyHandle
, OptionHandle
;
1359 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
1361 /* Allocate the initialization buffer */
1362 InitBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1363 sizeof(INIT_BUFFER
),
1368 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 8, 0, 0);
1371 /* Set to phase 1 */
1372 ExpInitializationPhase
= 1;
1374 /* Set us at maximum priority */
1375 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY
);
1377 /* Do Phase 1 HAL Initialization */
1378 if (!HalInitSystem(1, LoaderBlock
)) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1380 /* Get the command line and upcase it */
1381 CommandLine
= (LoaderBlock
->LoadOptions
? _strupr(LoaderBlock
->LoadOptions
) : NULL
);
1383 /* Check if GUI Boot is enabled */
1384 NoGuiBoot
= (CommandLine
&& strstr(CommandLine
, "NOGUIBOOT") != NULL
);
1386 /* Get the SOS setting */
1387 SosEnabled
= (CommandLine
&& strstr(CommandLine
, "SOS") != NULL
);
1389 /* Setup the boot driver */
1390 InbvEnableBootDriver(!NoGuiBoot
);
1391 InbvDriverInitialize(LoaderBlock
, IDB_MAX_RESOURCE
);
1393 /* Check if GUI boot is enabled */
1396 /* It is, display the boot logo and enable printing strings */
1397 InbvEnableDisplayString(SosEnabled
);
1398 DisplayBootBitmap(SosEnabled
);
1402 /* Release display ownership if not using GUI boot */
1403 InbvNotifyDisplayOwnershipLost(NULL
);
1405 /* Don't allow boot-time strings */
1406 InbvEnableDisplayString(FALSE
);
1409 /* Check if this is LiveCD (WinPE) mode */
1410 if (CommandLine
&& strstr(CommandLine
, "MININT") != NULL
)
1412 /* Setup WinPE Settings */
1413 InitIsWinPEMode
= TRUE
;
1414 InitWinPEModeType
|= (strstr(CommandLine
, "INRAM") != NULL
) ? 0x80000000 : 0x00000001;
1417 /* Get the kernel's load entry */
1418 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1419 LDR_DATA_TABLE_ENTRY
,
1422 /* Find the banner message */
1423 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1429 /* Setup defaults and check if we have a version string */
1430 StringBuffer
= InitBuffer
->VersionBuffer
;
1431 BeginBuffer
= StringBuffer
;
1432 EndBuffer
= StringBuffer
;
1433 Remaining
= sizeof(InitBuffer
->VersionBuffer
);
1434 if (CmCSDVersionString
.Length
)
1436 /* Print the version string */
1437 Status
= RtlStringCbPrintfExA(StringBuffer
,
1443 &CmCSDVersionString
);
1444 if (!NT_SUCCESS(Status
))
1447 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1453 *EndBuffer
= ANSI_NULL
; /* Null-terminate the string */
1456 /* Skip over the null-terminator to start a new string */
1460 /* Build the version number */
1461 StringBuffer
= InitBuffer
->VersionNumber
;
1462 Status
= RtlStringCbPrintfA(StringBuffer
,
1463 sizeof(InitBuffer
->VersionNumber
),
1465 VER_PRODUCTMAJORVERSION
,
1466 VER_PRODUCTMINORVERSION
);
1467 if (!NT_SUCCESS(Status
))
1470 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1473 /* Check if we had found a banner message */
1474 if (NT_SUCCESS(MsgStatus
))
1476 /* Create the banner message */
1477 /* ReactOS specific: Report ReactOS version, NtBuildLab information and reported NT kernel version */
1478 Status
= RtlStringCbPrintfA(EndBuffer
,
1480 (PCHAR
)MsgEntry
->Text
,
1484 NtBuildNumber
& 0xFFFF,
1486 if (!NT_SUCCESS(Status
))
1489 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1494 /* Use hard-coded banner message */
1495 Status
= RtlStringCbCopyA(EndBuffer
, Remaining
, "REACTOS (R)\r\n");
1496 if (!NT_SUCCESS(Status
))
1499 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1503 /* Display the version string on-screen */
1504 InbvDisplayString(EndBuffer
);
1506 /* Initialize Power Subsystem in Phase 0 */
1507 if (!PoInitSystem(0)) KeBugCheck(INTERNAL_POWER_ERROR
);
1509 /* Check for Y2K hack */
1510 Y2KHackRequired
= CommandLine
? strstr(CommandLine
, "YEAR") : NULL
;
1511 if (Y2KHackRequired
) Y2KHackRequired
= strstr(Y2KHackRequired
, "=");
1512 if (Y2KHackRequired
) YearHack
= atol(Y2KHackRequired
+ 1);
1514 /* Query the clock */
1515 if ((ExCmosClockIsSane
) && (HalQueryRealTimeClock(&TimeFields
)))
1517 /* Check if we're using the Y2K hack */
1518 if (Y2KHackRequired
) TimeFields
.Year
= (CSHORT
)YearHack
;
1520 /* Convert to time fields */
1521 RtlTimeFieldsToTime(&TimeFields
, &SystemBootTime
);
1522 UniversalBootTime
= SystemBootTime
;
1524 /* Check if real time is GMT */
1525 if (!ExpRealTimeIsUniversal
)
1527 /* Check if we don't have a valid bias */
1528 if (ExpLastTimeZoneBias
== MAXULONG
)
1532 ExpLastTimeZoneBias
= ExpAltTimeZoneBias
;
1535 /* Calculate the bias in seconds */
1536 ExpTimeZoneBias
.QuadPart
= Int32x32To64(ExpLastTimeZoneBias
* 60,
1539 /* Set the boot time-zone bias */
1540 SharedUserData
->TimeZoneBias
.High2Time
= ExpTimeZoneBias
.HighPart
;
1541 SharedUserData
->TimeZoneBias
.LowPart
= ExpTimeZoneBias
.LowPart
;
1542 SharedUserData
->TimeZoneBias
.High1Time
= ExpTimeZoneBias
.HighPart
;
1544 /* Convert the boot time to local time, and set it */
1545 UniversalBootTime
.QuadPart
= SystemBootTime
.QuadPart
+
1546 ExpTimeZoneBias
.QuadPart
;
1549 /* Update the system time */
1550 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1552 /* Do system callback */
1553 PoNotifySystemTimeSet();
1555 /* Remember this as the boot time */
1556 KeBootTime
= UniversalBootTime
;
1560 /* Initialize all processors */
1561 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1564 /* HACK: We should use RtlFindMessage and not only fallback to this */
1565 MpString
= "MultiProcessor Kernel\r\n";
1568 /* Setup the "MP" String */
1569 RtlInitAnsiString(&TempString
, MpString
);
1571 /* Make sure to remove the \r\n if we actually have a string */
1572 while ((TempString
.Length
> 0) &&
1573 ((TempString
.Buffer
[TempString
.Length
- 1] == '\r') ||
1574 (TempString
.Buffer
[TempString
.Length
- 1] == '\n')))
1576 /* Skip the trailing character */
1577 TempString
.Length
--;
1580 /* Get the information string from our resource file */
1581 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1584 KeNumberProcessors
> 1 ?
1585 WINDOWS_NT_INFO_STRING_PLURAL
:
1586 WINDOWS_NT_INFO_STRING
,
1589 /* Get total RAM size, in MiB */
1590 /* Round size up. Assumed to better match actual physical RAM size */
1591 Size
= ALIGN_UP_BY(MmNumberOfPhysicalPages
* PAGE_SIZE
, 1024 * 1024) / (1024 * 1024);
1593 /* Create the string */
1594 StringBuffer
= InitBuffer
->VersionBuffer
;
1595 Status
= RtlStringCbPrintfA(StringBuffer
,
1596 sizeof(InitBuffer
->VersionBuffer
),
1597 NT_SUCCESS(MsgStatus
) ?
1598 (PCHAR
)MsgEntry
->Text
:
1599 "%u System Processor [%Iu MB Memory] %Z\r\n",
1603 if (!NT_SUCCESS(Status
))
1606 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
1609 /* Display RAM and CPU count */
1610 InbvDisplayString(StringBuffer
);
1612 /* Update the progress bar */
1613 InbvUpdateProgressBar(5);
1615 /* Call OB initialization again */
1616 if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED
);
1618 /* Initialize Basic System Objects and Worker Threads */
1619 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 1, 0);
1621 /* Initialize the later stages of the kernel */
1622 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 2, 0);
1624 /* Call KD Providers at Phase 1 */
1625 if (!KdInitSystem(ExpInitializationPhase
, KeLoaderBlock
))
1627 /* Failed, bugcheck */
1628 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 3, 0);
1631 /* Initialize the SRM in Phase 1 */
1632 if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED
);
1634 /* Update the progress bar */
1635 InbvUpdateProgressBar(10);
1637 /* Create SystemRoot Link */
1638 Status
= ExpCreateSystemRootLink(LoaderBlock
);
1639 if (!NT_SUCCESS(Status
))
1641 /* Failed to create the system root link */
1642 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1645 /* Set up Region Maps, Sections and the Paging File */
1646 if (!MmInitSystem(1, LoaderBlock
)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED
);
1648 /* Create NLS section */
1649 ExpInitNls(LoaderBlock
);
1651 /* Initialize Cache Views */
1652 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED
);
1654 /* Initialize the Registry */
1655 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
1657 /* Initialize Prefetcher */
1658 CcPfInitializePrefetcher();
1660 /* Update progress bar */
1661 InbvUpdateProgressBar(15);
1663 /* Update timezone information */
1664 LastTzBias
= ExpLastTimeZoneBias
;
1665 ExRefreshTimeZoneInformation(&SystemBootTime
);
1667 /* Check if we're resetting timezone data */
1670 /* Convert the local time to system time */
1671 ExLocalTimeToSystemTime(&SystemBootTime
, &UniversalBootTime
);
1672 KeBootTime
= UniversalBootTime
;
1675 /* Set the new time */
1676 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1680 /* Check if the timezone switched and update the time */
1681 if (LastTzBias
!= ExpLastTimeZoneBias
) ZwSetSystemTime(NULL
, NULL
);
1684 /* Initialize the File System Runtime Library */
1685 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED
);
1687 /* Initialize range lists */
1688 RtlInitializeRangeListPackage();
1690 /* Report all resources used by HAL */
1691 HalReportResourceUsage();
1693 /* Call the debugger DLL */
1694 KdDebuggerInitialize1(LoaderBlock
);
1696 /* Setup PnP Manager in phase 1 */
1697 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED
);
1699 /* Update progress bar */
1700 InbvUpdateProgressBar(20);
1702 /* Initialize LPC */
1703 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED
);
1705 /* Make sure we have a command line */
1708 /* Check if this is a safe mode boot */
1709 SafeBoot
= strstr(CommandLine
, "SAFEBOOT:");
1712 /* Check what kind of boot this is */
1714 if (!strncmp(SafeBoot
, "MINIMAL", 7))
1717 InitSafeBootMode
= 1;
1719 MessageCode
= BOOTING_IN_SAFEMODE_MINIMAL
;
1721 else if (!strncmp(SafeBoot
, "NETWORK", 7))
1723 /* With Networking */
1724 InitSafeBootMode
= 2;
1726 MessageCode
= BOOTING_IN_SAFEMODE_NETWORK
;
1728 else if (!strncmp(SafeBoot
, "DSREPAIR", 8))
1730 /* Domain Server Repair */
1731 InitSafeBootMode
= 3;
1733 MessageCode
= BOOTING_IN_SAFEMODE_DSREPAIR
;
1739 InitSafeBootMode
= 0;
1742 /* Check if there's any settings left */
1745 /* Check if an alternate shell was requested */
1746 if (!strncmp(SafeBoot
, "(ALTERNATESHELL)", 16))
1748 /* Remember this for later */
1749 AlternateShell
= TRUE
;
1753 /* Find the message to print out */
1754 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1759 if (NT_SUCCESS(Status
))
1762 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1767 /* Make sure we have a command line */
1770 /* Check if bootlogging is enabled */
1771 if (strstr(CommandLine
, "BOOTLOG"))
1773 /* Find the message to print out */
1774 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1779 if (NT_SUCCESS(Status
))
1782 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1785 /* Setup boot logging */
1786 //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader);
1790 /* Setup the Executive in Phase 2 */
1791 //ExInitSystemPhase2();
1793 /* Update progress bar */
1794 InbvUpdateProgressBar(25);
1796 /* No KD Time Slip is pending */
1797 KdpTimeSlipPending
= 0;
1799 /* Initialize in-place execution support */
1800 XIPInit(LoaderBlock
);
1802 /* Set maximum update to 75% */
1803 InbvSetProgressBarSubset(25, 75);
1805 /* Initialize the I/O Subsystem */
1806 if (!IoInitSystem(LoaderBlock
)) KeBugCheck(IO1_INITIALIZATION_FAILED
);
1808 /* Set maximum update to 100% */
1809 InbvSetProgressBarSubset(0, 100);
1811 /* Are we in safe mode? */
1812 if (InitSafeBootMode
)
1814 /* Open the safe boot key */
1815 RtlInitUnicodeString(&KeyName
,
1816 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1817 L
"\\CONTROL\\SAFEBOOT");
1818 InitializeObjectAttributes(&ObjectAttributes
,
1820 OBJ_CASE_INSENSITIVE
,
1823 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1824 if (NT_SUCCESS(Status
))
1826 /* First check if we have an alternate shell */
1829 /* Make sure that the registry has one setup */
1830 RtlInitUnicodeString(&KeyName
, L
"AlternateShell");
1831 Status
= NtQueryValueKey(KeyHandle
,
1833 KeyValuePartialInformation
,
1835 sizeof(KeyPartialInfo
),
1837 if (!(NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_OVERFLOW
))
1839 AlternateShell
= FALSE
;
1843 /* Create the option key */
1844 RtlInitUnicodeString(&KeyName
, L
"Option");
1845 InitializeObjectAttributes(&ObjectAttributes
,
1847 OBJ_CASE_INSENSITIVE
,
1850 Status
= ZwCreateKey(&OptionHandle
,
1855 REG_OPTION_VOLATILE
,
1859 /* Check if the key create worked */
1860 if (NT_SUCCESS(Status
))
1862 /* Write the safe boot type */
1863 RtlInitUnicodeString(&KeyName
, L
"OptionValue");
1864 NtSetValueKey(OptionHandle
,
1869 sizeof(InitSafeBootMode
));
1871 /* Check if we have to use an alternate shell */
1874 /* Remember this for later */
1876 RtlInitUnicodeString(&KeyName
, L
"UseAlternateShell");
1877 NtSetValueKey(OptionHandle
,
1882 sizeof(Disposition
));
1885 /* Close the options key handle */
1886 NtClose(OptionHandle
);
1891 /* Are we in Win PE mode? */
1892 if (InitIsWinPEMode
)
1894 /* Open the safe control key */
1895 RtlInitUnicodeString(&KeyName
,
1896 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1898 InitializeObjectAttributes(&ObjectAttributes
,
1900 OBJ_CASE_INSENSITIVE
,
1903 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1904 if (!NT_SUCCESS(Status
))
1907 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1910 /* Create the MiniNT key */
1911 RtlInitUnicodeString(&KeyName
, L
"MiniNT");
1912 InitializeObjectAttributes(&ObjectAttributes
,
1914 OBJ_CASE_INSENSITIVE
,
1917 Status
= ZwCreateKey(&OptionHandle
,
1922 REG_OPTION_VOLATILE
,
1924 if (!NT_SUCCESS(Status
))
1927 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1930 /* Close the handles */
1932 NtClose(OptionHandle
);
1935 /* FIXME: This doesn't do anything for now */
1936 MmArmInitSystem(2, LoaderBlock
);
1938 /* Update progress bar */
1939 InbvUpdateProgressBar(80);
1941 /* Initialize VDM support */
1942 #if defined(_M_IX86)
1943 KeI386VdmInitialize();
1946 /* Initialize Power Subsystem in Phase 1*/
1947 if (!PoInitSystem(1)) KeBugCheck(INTERNAL_POWER_ERROR
);
1949 /* Update progress bar */
1950 InbvUpdateProgressBar(90);
1952 /* Initialize the Process Manager at Phase 1 */
1953 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1955 /* Make sure nobody touches the loader block again */
1956 if (LoaderBlock
== KeLoaderBlock
) KeLoaderBlock
= NULL
;
1957 MmFreeLoaderBlock(LoaderBlock
);
1958 LoaderBlock
= Context
= NULL
;
1960 /* Initialize the SRM in phase 1 */
1961 if (!SeRmInitPhase1()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1963 /* Update progress bar */
1964 InbvUpdateProgressBar(100);
1966 /* Clear the screen */
1967 if (InbvBootDriverInstalled
) FinalizeBootLogo();
1969 /* Allow strings to be displayed */
1970 InbvEnableDisplayString(TRUE
);
1972 /* Launch initial process */
1973 DPRINT("Free non-cache pages: %lx\n", MmAvailablePages
+ MiMemoryConsumers
[MC_CACHE
].PagesUsed
);
1974 ProcessInfo
= &InitBuffer
->ProcessInfo
;
1975 ExpLoadInitialProcess(InitBuffer
, &ProcessParameters
, &Environment
);
1977 /* Wait 5 seconds for initial process to initialize */
1978 Timeout
.QuadPart
= Int32x32To64(5, -10000000);
1979 Status
= ZwWaitForSingleObject(ProcessInfo
->ProcessHandle
, FALSE
, &Timeout
);
1980 if (Status
== STATUS_SUCCESS
)
1982 /* Failed, display error */
1983 DPRINT1("INIT: Session Manager terminated.\n");
1985 /* Bugcheck the system if SMSS couldn't initialize */
1986 KeBugCheck(SESSION5_INITIALIZATION_FAILED
);
1989 /* Close process handles */
1990 ZwClose(ProcessInfo
->ThreadHandle
);
1991 ZwClose(ProcessInfo
->ProcessHandle
);
1993 /* Free the initial process environment */
1995 ZwFreeVirtualMemory(NtCurrentProcess(),
1996 (PVOID
*)&Environment
,
2000 /* Free the initial process parameters */
2002 ZwFreeVirtualMemory(NtCurrentProcess(),
2003 (PVOID
*)&ProcessParameters
,
2007 /* Increase init phase */
2008 ExpInitializationPhase
++;
2010 /* Free the boot buffer */
2011 ExFreePoolWithTag(InitBuffer
, TAG_INIT
);
2012 DPRINT("Free non-cache pages: %lx\n", MmAvailablePages
+ MiMemoryConsumers
[MC_CACHE
].PagesUsed
);
2017 Phase1Initialization(IN PVOID Context
)
2019 /* Do the .INIT part of Phase 1 which we can free later */
2020 Phase1InitializationDiscard(Context
);
2022 /* Jump into zero page thread */