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
;
45 ULONG NtBuildNumber
= VER_PRODUCTBUILD
| 0xC0000000;
47 ULONG NtBuildNumber
= VER_PRODUCTBUILD
;
51 ULONG NtGlobalFlag
= 0;
55 ULONG CmNtSpBuildNumber
;
57 ULONG CmNtCSDReleaseType
;
58 UNICODE_STRING CmVersionString
;
59 UNICODE_STRING CmCSDVersionString
;
60 CHAR NtBuildLab
[] = KERNEL_VERSION_BUILD_STR
;
62 /* Init flags and settings */
63 ULONG ExpInitializationPhase
;
64 BOOLEAN ExpInTextModeSetup
;
65 BOOLEAN IoRemoteBootClient
;
66 ULONG InitSafeBootMode
;
67 BOOLEAN InitIsWinPEMode
, InitWinPEModeType
;
70 UNICODE_STRING NtSystemRoot
;
72 /* NT Initial User Application */
73 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
74 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
76 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
78 /* Boot NLS information */
79 PVOID ExpNlsTableBase
;
80 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
81 ULONG ExpUnicodeCaseTableDataOffset
;
82 NLSTABLEINFO ExpNlsTableInfo
;
83 SIZE_T ExpNlsTableSize
;
84 PVOID ExpNlsSectionPointer
;
86 /* CMOS Timer Sanity */
87 BOOLEAN ExCmosClockIsSane
= TRUE
;
88 BOOLEAN ExpRealTimeIsUniversal
;
90 /* FUNCTIONS ****************************************************************/
95 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
97 UNICODE_STRING LinkName
;
98 OBJECT_ATTRIBUTES ObjectAttributes
;
101 ANSI_STRING AnsiName
;
103 ANSI_STRING TargetString
;
104 UNICODE_STRING TargetName
;
106 /* Initialize the ArcName tree */
107 RtlInitUnicodeString(&LinkName
, L
"\\ArcName");
108 InitializeObjectAttributes(&ObjectAttributes
,
110 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
112 SePublicDefaultUnrestrictedSd
);
115 Status
= NtCreateDirectoryObject(&LinkHandle
,
116 DIRECTORY_ALL_ACCESS
,
118 if (!NT_SUCCESS(Status
))
121 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
124 /* Close the LinkHandle */
127 /* Initialize the Device tree */
128 RtlInitUnicodeString(&LinkName
, L
"\\Device");
129 InitializeObjectAttributes(&ObjectAttributes
,
131 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
133 SePublicDefaultUnrestrictedSd
);
136 Status
= NtCreateDirectoryObject(&LinkHandle
,
137 DIRECTORY_ALL_ACCESS
,
139 if (!NT_SUCCESS(Status
))
142 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
145 /* Close the LinkHandle */
146 ObCloseHandle(LinkHandle
, KernelMode
);
148 /* Create the system root symlink name */
149 RtlInitAnsiString(&AnsiName
, "\\SystemRoot");
150 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &AnsiName
, TRUE
);
151 if (!NT_SUCCESS(Status
))
154 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
157 /* Initialize the attributes for the link */
158 InitializeObjectAttributes(&ObjectAttributes
,
160 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
162 SePublicDefaultUnrestrictedSd
);
164 /* Build the ARC name */
167 LoaderBlock
->ArcBootDeviceName
,
168 LoaderBlock
->NtBootPathName
);
169 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
171 /* Convert it to Unicode */
172 RtlInitString(&TargetString
, Buffer
);
173 Status
= RtlAnsiStringToUnicodeString(&TargetName
,
176 if (!NT_SUCCESS(Status
))
178 /* We failed, bugcheck */
179 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
183 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
184 SYMBOLIC_LINK_ALL_ACCESS
,
188 /* Free the strings */
189 RtlFreeUnicodeString(&LinkName
);
190 RtlFreeUnicodeString(&TargetName
);
192 /* Check if creating the link failed */
193 if (!NT_SUCCESS(Status
))
196 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
199 /* Close the handle and return success */
200 ObCloseHandle(LinkHandle
, KernelMode
);
201 return STATUS_SUCCESS
;
207 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
209 LARGE_INTEGER SectionSize
;
212 PVOID SectionBase
= NULL
;
214 LARGE_INTEGER SectionOffset
= {{0, 0}};
215 PLIST_ENTRY ListHead
, NextEntry
;
216 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
217 ULONG NlsTablesEncountered
= 0;
218 SIZE_T NlsTableSizes
[3] = {0, 0, 0}; /* 3 NLS tables */
220 /* Check if this is boot-time phase 0 initialization */
221 if (!ExpInitializationPhase
)
223 /* Loop the memory descriptors */
224 ListHead
= &LoaderBlock
->MemoryDescriptorListHead
;
225 NextEntry
= ListHead
->Flink
;
226 while (NextEntry
!= ListHead
)
228 /* Get the current block */
229 MdBlock
= CONTAINING_RECORD(NextEntry
,
230 MEMORY_ALLOCATION_DESCRIPTOR
,
233 /* Check if this is an NLS block */
234 if (MdBlock
->MemoryType
== LoaderNlsData
)
236 /* Increase the table size */
237 ExpNlsTableSize
+= MdBlock
->PageCount
* PAGE_SIZE
;
239 /* FreeLdr-specific */
240 NlsTableSizes
[NlsTablesEncountered
] = MdBlock
->PageCount
* PAGE_SIZE
;
241 NlsTablesEncountered
++;
242 ASSERT(NlsTablesEncountered
< 4);
245 /* Go to the next block */
246 NextEntry
= MdBlock
->ListEntry
.Flink
;
249 /* Allocate the a new buffer since loader memory will be freed */
250 ExpNlsTableBase
= ExAllocatePoolWithTag(NonPagedPool
,
253 if (!ExpNlsTableBase
) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
255 /* Copy the codepage data in its new location. */
256 if (NlsTablesEncountered
== 1)
258 /* Ntldr-way boot process */
259 RtlCopyMemory(ExpNlsTableBase
,
260 LoaderBlock
->NlsData
->AnsiCodePageData
,
266 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
267 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
269 RtlCopyMemory(ExpNlsTableBase
,
270 LoaderBlock
->NlsData
->AnsiCodePageData
,
273 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0]),
274 LoaderBlock
->NlsData
->OemCodePageData
,
277 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0] +
279 LoaderBlock
->NlsData
->UnicodeCodePageData
,
284 /* Initialize and reset the NLS TAbles */
285 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
286 ExpAnsiCodePageDataOffset
),
287 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
288 ExpOemCodePageDataOffset
),
289 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
290 ExpUnicodeCaseTableDataOffset
),
292 RtlResetRtlTranslations(&ExpNlsTableInfo
);
296 /* Set the section size */
297 SectionSize
.QuadPart
= ExpNlsTableSize
;
299 /* Create the NLS Section */
300 Status
= ZwCreateSection(&NlsSection
,
307 if (!NT_SUCCESS(Status
))
310 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
313 /* Get a pointer to the section */
314 Status
= ObReferenceObjectByHandle(NlsSection
,
318 &ExpNlsSectionPointer
,
320 ObCloseHandle(NlsSection
, KernelMode
);
321 if (!NT_SUCCESS(Status
))
324 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
327 /* Map the NLS Section in system space */
328 Status
= MmMapViewInSystemSpace(ExpNlsSectionPointer
,
331 if (!NT_SUCCESS(Status
))
334 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
337 /* Copy the codepage data in its new location. */
338 ASSERT(SectionBase
>= MmSystemRangeStart
);
339 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
341 /* Free the previously allocated buffer and set the new location */
342 ExFreePoolWithTag(ExpNlsTableBase
, TAG_RTLI
);
343 ExpNlsTableBase
= SectionBase
;
345 /* Initialize the NLS Tables */
346 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
347 ExpAnsiCodePageDataOffset
),
348 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
349 ExpOemCodePageDataOffset
),
350 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
351 ExpUnicodeCaseTableDataOffset
),
353 RtlResetRtlTranslations(&ExpNlsTableInfo
);
355 /* Reset the base to 0 */
358 /* Map the section in the system process */
359 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
360 PsGetCurrentProcess(),
369 if (!NT_SUCCESS(Status
))
372 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
375 /* Copy the table into the system process and set this as the base */
376 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
377 ExpNlsTableBase
= SectionBase
;
383 ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer
,
384 OUT PRTL_USER_PROCESS_PARAMETERS
*ProcessParameters
,
385 OUT PCHAR
*ProcessEnvironment
)
390 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
391 UNICODE_STRING SmssName
, Environment
, SystemDriveString
, DebugString
;
392 PVOID EnvironmentPtr
= NULL
;
393 PRTL_USER_PROCESS_INFORMATION ProcessInformation
;
394 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= NULL
;
396 NullString
.Length
= sizeof(WCHAR
);
398 /* Use the initial buffer, after the strings */
399 ProcessInformation
= &InitBuffer
->ProcessInfo
;
401 /* Allocate memory for the process parameters */
402 Size
= sizeof(*ProcessParams
) + ((MAX_PATH
* 6) * sizeof(WCHAR
));
403 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
404 (PVOID
*)&ProcessParams
,
407 MEM_RESERVE
| MEM_COMMIT
,
409 if (!NT_SUCCESS(Status
))
411 /* Failed, display error */
412 _snwprintf(InitBuffer
->DebugBuffer
,
413 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
414 L
"INIT: Unable to allocate Process Parameters. 0x%lx",
416 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
417 ZwDisplayString(&DebugString
);
419 /* Bugcheck the system */
420 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
423 /* Setup the basic header, and give the process the low 1MB to itself */
424 ProcessParams
->Length
= (ULONG
)Size
;
425 ProcessParams
->MaximumLength
= (ULONG
)Size
;
426 ProcessParams
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
427 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
429 /* Allocate a page for the environment */
431 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
435 MEM_RESERVE
| MEM_COMMIT
,
437 if (!NT_SUCCESS(Status
))
439 /* Failed, display error */
440 _snwprintf(InitBuffer
->DebugBuffer
,
441 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
442 L
"INIT: Unable to allocate Process Environment. 0x%lx",
444 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
445 ZwDisplayString(&DebugString
);
447 /* Bugcheck the system */
448 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
451 /* Write the pointer */
452 ProcessParams
->Environment
= EnvironmentPtr
;
454 /* Make a buffer for the DOS path */
455 p
= (PWSTR
)(ProcessParams
+ 1);
456 ProcessParams
->CurrentDirectory
.DosPath
.Buffer
= p
;
457 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
= MAX_PATH
*
460 /* Copy the DOS path */
461 RtlCopyUnicodeString(&ProcessParams
->CurrentDirectory
.DosPath
,
464 /* Make a buffer for the DLL Path */
465 p
= (PWSTR
)((PCHAR
)ProcessParams
->CurrentDirectory
.DosPath
.Buffer
+
466 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
);
467 ProcessParams
->DllPath
.Buffer
= p
;
468 ProcessParams
->DllPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
470 /* Copy the DLL path and append the system32 directory */
471 RtlCopyUnicodeString(&ProcessParams
->DllPath
,
472 &ProcessParams
->CurrentDirectory
.DosPath
);
473 RtlAppendUnicodeToString(&ProcessParams
->DllPath
, L
"\\System32");
475 /* Make a buffer for the image name */
476 p
= (PWSTR
)((PCHAR
)ProcessParams
->DllPath
.Buffer
+
477 ProcessParams
->DllPath
.MaximumLength
);
478 ProcessParams
->ImagePathName
.Buffer
= p
;
479 ProcessParams
->ImagePathName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
481 /* Make sure the buffer is a valid string which within the given length */
482 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
483 ((NtInitialUserProcessBufferLength
!= MAXULONG
) &&
484 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
485 (NtInitialUserProcessBufferLength
>
486 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
488 /* Invalid initial process string, bugcheck */
489 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
,
490 STATUS_INVALID_PARAMETER
,
491 NtInitialUserProcessBufferType
,
492 NtInitialUserProcessBufferLength
,
493 sizeof(NtInitialUserProcessBuffer
));
496 /* Cut out anything after a space */
497 p
= NtInitialUserProcessBuffer
;
498 while ((*p
) && (*p
!= L
' ')) p
++;
500 /* Set the image path length */
501 ProcessParams
->ImagePathName
.Length
=
502 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
504 /* Copy the actual buffer */
505 RtlCopyMemory(ProcessParams
->ImagePathName
.Buffer
,
506 NtInitialUserProcessBuffer
,
507 ProcessParams
->ImagePathName
.Length
);
509 /* Null-terminate it */
510 ProcessParams
->ImagePathName
.Buffer
[ProcessParams
->ImagePathName
.Length
/
511 sizeof(WCHAR
)] = UNICODE_NULL
;
513 /* Make a buffer for the command line */
514 p
= (PWSTR
)((PCHAR
)ProcessParams
->ImagePathName
.Buffer
+
515 ProcessParams
->ImagePathName
.MaximumLength
);
516 ProcessParams
->CommandLine
.Buffer
= p
;
517 ProcessParams
->CommandLine
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
519 /* Add the image name to the command line */
520 RtlAppendUnicodeToString(&ProcessParams
->CommandLine
,
521 NtInitialUserProcessBuffer
);
523 /* Create the environment string */
524 RtlInitEmptyUnicodeString(&Environment
,
525 ProcessParams
->Environment
,
528 /* Append the DLL path to it */
529 RtlAppendUnicodeToString(&Environment
, L
"Path=");
530 RtlAppendUnicodeStringToString(&Environment
, &ProcessParams
->DllPath
);
531 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
533 /* Create the system drive string */
534 SystemDriveString
= NtSystemRoot
;
535 SystemDriveString
.Length
= 2 * sizeof(WCHAR
);
537 /* Append it to the environment */
538 RtlAppendUnicodeToString(&Environment
, L
"SystemDrive=");
539 RtlAppendUnicodeStringToString(&Environment
, &SystemDriveString
);
540 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
542 /* Append the system root to the environment */
543 RtlAppendUnicodeToString(&Environment
, L
"SystemRoot=");
544 RtlAppendUnicodeStringToString(&Environment
, &NtSystemRoot
);
545 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
547 /* Prepare the prefetcher */
548 //CcPfBeginBootPhase(150);
550 /* Create SMSS process */
551 SmssName
= ProcessParams
->ImagePathName
;
552 Status
= RtlCreateUserProcess(&SmssName
,
553 OBJ_CASE_INSENSITIVE
,
554 RtlDeNormalizeProcessParams(ProcessParams
),
562 if (!NT_SUCCESS(Status
))
564 /* Failed, display error */
565 _snwprintf(InitBuffer
->DebugBuffer
,
566 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
567 L
"INIT: Unable to create Session Manager. 0x%lx",
569 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
570 ZwDisplayString(&DebugString
);
572 /* Bugcheck the system */
573 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
576 /* Resume the thread */
577 Status
= ZwResumeThread(ProcessInformation
->ThreadHandle
, NULL
);
578 if (!NT_SUCCESS(Status
))
580 /* Failed, display error */
581 _snwprintf(InitBuffer
->DebugBuffer
,
582 sizeof(InitBuffer
->DebugBuffer
)/sizeof(WCHAR
),
583 L
"INIT: Unable to resume Session Manager. 0x%lx",
585 RtlInitUnicodeString(&DebugString
, InitBuffer
->DebugBuffer
);
586 ZwDisplayString(&DebugString
);
588 /* Bugcheck the system */
589 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
593 *ProcessParameters
= ProcessParams
;
594 *ProcessEnvironment
= EnvironmentPtr
;
600 ExComputeTickCountMultiplier(IN ULONG ClockIncrement
)
602 ULONG MsRemainder
= 0, MsIncrement
;
603 ULONG IncrementRemainder
;
606 /* Count the number of milliseconds for each clock interrupt */
607 MsIncrement
= ClockIncrement
/ (10 * 1000);
609 /* Count the remainder from the division above, with 24-bit precision */
610 IncrementRemainder
= ClockIncrement
- (MsIncrement
* (10 * 1000));
611 for (i
= 0; i
< 24; i
++)
613 /* Shift the remainders */
615 IncrementRemainder
<<= 1;
617 /* Check if we've went past 1 ms */
618 if (IncrementRemainder
>= (10 * 1000))
620 /* Increase the remainder by one, and substract from increment */
621 IncrementRemainder
-= (10 * 1000);
626 /* Return the increment */
627 return (MsIncrement
<< 24) | MsRemainder
;
633 ExpInitSystemPhase0(VOID
)
635 /* Initialize EXRESOURCE Support */
636 ExpResourceInitialization();
638 /* Initialize the environment lock */
639 ExInitializeFastMutex(&ExpEnvironmentLock
);
641 /* Initialize the lookaside lists and locks */
642 ExpInitLookasideLists();
644 /* Initialize the Firmware Table resource and listhead */
645 InitializeListHead(&ExpFirmwareTableProviderListHead
);
646 ExInitializeResourceLite(&ExpFirmwareTableResource
);
648 /* Set the suite mask to maximum and return */
649 ExSuiteMask
= 0xFFFFFFFF;
656 ExpInitSystemPhase1(VOID
)
658 /* Initialize worker threads */
659 ExpInitializeWorkerThreads();
661 /* Initialize pushlocks */
662 ExpInitializePushLocks();
664 /* Initialize events and event pairs */
665 if (ExpInitializeEventImplementation() == FALSE
)
667 DPRINT1("Executive: Event initialization failed\n");
670 if (ExpInitializeEventPairImplementation() == FALSE
)
672 DPRINT1("Executive: Event Pair initialization failed\n");
676 /* Initialize mutants */
677 if (ExpInitializeMutantImplementation() == FALSE
)
679 DPRINT1("Executive: Mutant initialization failed\n");
683 /* Initialize callbacks */
684 if (ExpInitializeCallbacks() == FALSE
)
686 DPRINT1("Executive: Callback initialization failed\n");
690 /* Initialize semaphores */
691 if (ExpInitializeSemaphoreImplementation() == FALSE
)
693 DPRINT1("Executive: Semaphore initialization failed\n");
697 /* Initialize timers */
698 if (ExpInitializeTimerImplementation() == FALSE
)
700 DPRINT1("Executive: Timer initialization failed\n");
704 /* Initialize profiling */
705 if (ExpInitializeProfileImplementation() == FALSE
)
707 DPRINT1("Executive: Profile initialization failed\n");
711 /* Initialize UUIDs */
714 /* Initialize keyed events */
715 if (ExpInitializeKeyedEventImplementation() == FALSE
)
717 DPRINT1("Executive: Keyed event initialization failed\n");
721 /* Initialize Win32K */
722 if (ExpWin32kInit() == FALSE
)
724 DPRINT1("Executive: Win32 initialization failed\n");
735 /* Check the initialization phase */
736 switch (ExpInitializationPhase
)
741 return ExpInitSystemPhase0();
746 return ExpInitSystemPhase1();
750 /* Don't know any other phase! Bugcheck! */
751 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
759 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
761 PLOADER_PARAMETER_EXTENSION Extension
;
763 /* Get the loader extension */
764 Extension
= LoaderBlock
->Extension
;
766 /* Validate the size (Windows 2003 loader doesn't provide more) */
767 if (Extension
->Size
< LOADER_PARAMETER_EXTENSION_MIN_SIZE
) return FALSE
;
769 /* Don't validate upper versions */
770 if (Extension
->MajorVersion
> VER_PRODUCTMAJORVERSION
) return TRUE
;
772 /* Fail if this is NT 4 */
773 if (Extension
->MajorVersion
< VER_PRODUCTMAJORVERSION
) return FALSE
;
775 /* Fail if this is XP */
776 if (Extension
->MinorVersion
< VER_PRODUCTMINORVERSION
) return FALSE
;
778 /* This is 2003 or newer, approve it */
785 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
788 PLIST_ENTRY NextEntry
;
791 PLDR_DATA_TABLE_ENTRY LdrEntry
;
792 CHAR NameBuffer
[256];
796 /* Loop the driver list */
797 NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
798 while (NextEntry
!= &LoaderBlock
->LoadOrderListHead
)
800 /* Skip the first two images */
804 LdrEntry
= CONTAINING_RECORD(NextEntry
,
805 LDR_DATA_TABLE_ENTRY
,
807 if (LdrEntry
->FullDllName
.Buffer
[0] == L
'\\')
809 /* We have a name, read its data */
810 Name
= LdrEntry
->FullDllName
.Buffer
;
811 Length
= LdrEntry
->FullDllName
.Length
/ sizeof(WCHAR
);
813 /* Check if our buffer can hold it */
814 if (sizeof(NameBuffer
) < Length
+ sizeof(ANSI_NULL
))
817 Status
= STATUS_BUFFER_OVERFLOW
;
825 /* Copy the character */
826 NameBuffer
[Count
++] = (CHAR
)*Name
++;
827 } while (Count
< Length
);
830 NameBuffer
[Count
] = ANSI_NULL
;
831 Status
= STATUS_SUCCESS
;
836 /* Safely print the string into our buffer */
837 Status
= RtlStringCbPrintfA(NameBuffer
,
839 "%S\\System32\\Drivers\\%wZ",
840 &SharedUserData
->NtSystemRoot
[2],
841 &LdrEntry
->BaseDllName
);
844 /* Check if the buffer was ok */
845 if (NT_SUCCESS(Status
))
847 /* Initialize the STRING for the debugger */
848 RtlInitString(&SymbolString
, NameBuffer
);
850 /* Load the symbols */
851 DbgLoadImageSymbols(&SymbolString
,
853 (ULONG_PTR
)PsGetCurrentProcessId());
857 /* Go to the next entry */
859 NextEntry
= NextEntry
->Flink
;
866 ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
867 IN ULONG_PTR PagesToDestroy
,
868 IN TYPE_OF_MEMORY MemoryType
)
870 PLIST_ENTRY ListEntry
;
871 PMEMORY_ALLOCATION_DESCRIPTOR MemDescriptor
;
873 DPRINT1("Burn RAM amount: %lu pages\n", PagesToDestroy
);
875 /* Loop the memory descriptors, beginning at the end */
876 for (ListEntry
= LoaderBlock
->MemoryDescriptorListHead
.Blink
;
877 ListEntry
!= &LoaderBlock
->MemoryDescriptorListHead
;
878 ListEntry
= ListEntry
->Blink
)
880 /* Get the memory descriptor structure */
881 MemDescriptor
= CONTAINING_RECORD(ListEntry
,
882 MEMORY_ALLOCATION_DESCRIPTOR
,
885 /* Is memory free there or is it temporary? */
886 if (MemDescriptor
->MemoryType
== LoaderFree
||
887 MemDescriptor
->MemoryType
== LoaderFirmwareTemporary
)
889 /* Check if the descriptor has more pages than we want */
890 if (MemDescriptor
->PageCount
> PagesToDestroy
)
892 /* Change block's page count, ntoskrnl doesn't care much */
893 MemDescriptor
->PageCount
-= PagesToDestroy
;
898 /* Change block type */
899 MemDescriptor
->MemoryType
= MemoryType
;
900 PagesToDestroy
-= MemDescriptor
->PageCount
;
902 /* Check if we are done */
903 if (PagesToDestroy
== 0) break;
912 ExpInitializeExecutive(IN ULONG Cpu
,
913 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
915 PNLS_DATA_BLOCK NlsData
;
917 ANSI_STRING AnsiPath
;
919 PCHAR CommandLine
, PerfMem
;
921 PLDR_DATA_TABLE_ENTRY NtosEntry
;
922 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
923 ANSI_STRING CsdString
;
924 size_t Remaining
= 0;
926 CHAR VersionBuffer
[65];
928 /* Validate Loader */
929 if (!ExpIsLoaderValid(LoaderBlock
))
931 /* Invalid loader version */
932 KeBugCheckEx(MISMATCHED_HAL
,
934 LoaderBlock
->Extension
->Size
,
935 LoaderBlock
->Extension
->MajorVersion
,
936 LoaderBlock
->Extension
->MinorVersion
);
939 /* Initialize PRCB pool lookaside pointers */
940 ExInitPoolLookasidePointers();
942 /* Check if this is an application CPU */
945 /* Then simply initialize it with HAL */
946 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
948 /* Initialization failed */
949 KeBugCheck(HAL_INITIALIZATION_FAILED
);
956 /* Assume no text-mode or remote boot */
957 ExpInTextModeSetup
= FALSE
;
958 IoRemoteBootClient
= FALSE
;
960 /* Check if we have a setup loader block */
961 if (LoaderBlock
->SetupLdrBlock
)
963 /* Check if this is text-mode setup */
964 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_TEXT_MODE
) ExpInTextModeSetup
= TRUE
;
966 /* Check if this is network boot */
967 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_REMOTE_BOOT
)
970 IoRemoteBootClient
= TRUE
;
972 /* Make sure we're actually booting off the network */
973 ASSERT(!_memicmp(LoaderBlock
->ArcBootDeviceName
, "net(0)", 6));
978 ExpInitializationPhase
= 0;
980 /* Get boot command line */
981 CommandLine
= LoaderBlock
->LoadOptions
;
984 /* Upcase it for comparison and check if we're in performance mode */
985 _strupr(CommandLine
);
986 PerfMem
= strstr(CommandLine
, "PERFMEM");
989 /* Check if the user gave a number of bytes to use */
990 PerfMem
= strstr(PerfMem
, "=");
993 /* Read the number of pages we'll use */
994 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
998 DPRINT1("BBT performance mode not yet supported."
999 "/PERFMEM option ignored.\n");
1004 /* Check if we're burning memory */
1005 PerfMem
= strstr(CommandLine
, "BURNMEMORY");
1008 /* Check if the user gave a number of bytes to use */
1009 PerfMem
= strstr(PerfMem
, "=");
1012 /* Read the number of pages we'll use */
1013 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
1014 if (PerfMemUsed
) ExBurnMemory(LoaderBlock
, PerfMemUsed
, LoaderBad
);
1019 /* Setup NLS Base and offsets */
1020 NlsData
= LoaderBlock
->NlsData
;
1021 ExpNlsTableBase
= NlsData
->AnsiCodePageData
;
1022 ExpAnsiCodePageDataOffset
= 0;
1023 ExpOemCodePageDataOffset
= (ULONG
)((ULONG_PTR
)NlsData
->OemCodePageData
-
1024 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
1025 ExpUnicodeCaseTableDataOffset
= (ULONG
)((ULONG_PTR
)NlsData
->UnicodeCodePageData
-
1026 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
1028 /* Initialize the NLS Tables */
1029 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1030 ExpAnsiCodePageDataOffset
),
1031 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1032 ExpOemCodePageDataOffset
),
1033 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1034 ExpUnicodeCaseTableDataOffset
),
1036 RtlResetRtlTranslations(&ExpNlsTableInfo
);
1038 /* Now initialize the HAL */
1039 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
1041 /* HAL failed to initialize, bugcheck */
1042 KeBugCheck(HAL_INITIALIZATION_FAILED
);
1045 /* Make sure interrupts are active now */
1048 /* Clear the crypto exponent */
1049 SharedUserData
->CryptoExponent
= 0;
1051 /* Set global flags for the checked build */
1053 NtGlobalFlag
|= FLG_ENABLE_CLOSE_EXCEPTIONS
|
1054 FLG_ENABLE_KDEBUG_SYMBOL_LOAD
;
1057 /* Setup NT System Root Path */
1058 sprintf(Buffer
, "C:%s", LoaderBlock
->NtBootPathName
);
1060 /* Convert to ANSI_STRING and null-terminate it */
1061 RtlInitString(&AnsiPath
, Buffer
);
1062 Buffer
[--AnsiPath
.Length
] = ANSI_NULL
;
1064 /* Get the string from KUSER_SHARED_DATA's buffer */
1065 RtlInitEmptyUnicodeString(&NtSystemRoot
,
1066 SharedUserData
->NtSystemRoot
,
1067 sizeof(SharedUserData
->NtSystemRoot
));
1069 /* Now fill it in */
1070 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &AnsiPath
, FALSE
);
1071 if (!NT_SUCCESS(Status
)) KeBugCheck(SESSION3_INITIALIZATION_FAILED
);
1073 /* Setup bugcheck messages */
1074 KiInitializeBugCheck();
1076 /* Setup initial system settings */
1077 CmGetSystemControlValues(LoaderBlock
->RegistryBase
, CmControlVector
);
1079 /* Load static defaults for Service Pack 1 and add our SVN revision */
1080 /* Format of CSD : SPMajor - SPMinor */
1081 CmNtCSDVersion
= 0x100 | (KERNEL_VERSION_BUILD_HEX
<< 16);
1082 CmNtCSDReleaseType
= 0;
1084 /* Set Service Pack data for Service Pack 1 */
1085 CmNtSpBuildNumber
= VER_PRODUCTBUILD_QFE
;
1086 if (!(CmNtCSDVersion
& 0xFFFF0000))
1088 /* Check the release type */
1089 if (CmNtCSDReleaseType
== 1) CmNtSpBuildNumber
|= VER_PRODUCTBUILD_QFE
<< 16;
1092 /* Add loaded CmNtGlobalFlag value */
1093 NtGlobalFlag
|= CmNtGlobalFlag
;
1095 /* Initialize the executive at phase 0 */
1096 if (!ExInitSystem()) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1098 /* Initialize the memory manager at phase 0 */
1099 if (!MmArmInitSystem(0, LoaderBlock
)) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1101 /* Load boot symbols */
1102 ExpLoadBootSymbols(LoaderBlock
);
1104 /* Check if we should break after symbol load */
1105 if (KdBreakAfterSymbolLoad
) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
1107 /* Check if this loader is compatible with NT 5.2 */
1108 if (LoaderBlock
->Extension
->Size
>= sizeof(LOADER_PARAMETER_EXTENSION
))
1110 /* Setup headless terminal settings */
1111 HeadlessInit(LoaderBlock
);
1114 /* Set system ranges */
1116 SharedUserData
->Reserved1
= MM_HIGHEST_USER_ADDRESS_WOW64
;
1117 SharedUserData
->Reserved3
= MM_SYSTEM_RANGE_START_WOW64
;
1119 SharedUserData
->Reserved1
= (ULONG_PTR
)MmHighestUserAddress
;
1120 SharedUserData
->Reserved3
= (ULONG_PTR
)MmSystemRangeStart
;
1123 /* Make a copy of the NLS Tables */
1124 ExpInitNls(LoaderBlock
);
1126 /* Get the kernel's load entry */
1127 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1128 LDR_DATA_TABLE_ENTRY
,
1131 /* Check if this is a service pack */
1132 if (CmNtCSDVersion
& 0xFFFF)
1134 /* Get the service pack string */
1135 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1138 WINDOWS_NT_CSD_STRING
,
1140 if (NT_SUCCESS(Status
))
1142 /* Setup the string */
1143 RtlInitAnsiString(&CsdString
, (PCHAR
)MsgEntry
->Text
);
1145 /* Remove trailing newline */
1146 while ((CsdString
.Length
> 0) &&
1147 ((CsdString
.Buffer
[CsdString
.Length
- 1] == '\r') ||
1148 (CsdString
.Buffer
[CsdString
.Length
- 1] == '\n')))
1150 /* Skip the trailing character */
1154 /* Fill the buffer with version information */
1155 Status
= RtlStringCbPrintfA(Buffer
,
1159 (CmNtCSDVersion
& 0xFF00) >> 8,
1160 (CmNtCSDVersion
& 0xFF) ?
1161 'A' + (CmNtCSDVersion
& 0xFF) - 1 :
1166 /* Build default string */
1167 Status
= RtlStringCbPrintfA(Buffer
,
1173 /* Check for success */
1174 if (!NT_SUCCESS(Status
))
1177 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1182 /* Then this is a beta */
1183 Status
= RtlStringCbCopyExA(Buffer
,
1185 VER_PRODUCTBETA_STR
,
1189 if (!NT_SUCCESS(Status
))
1192 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1196 CmCSDVersionString
.MaximumLength
= sizeof(Buffer
) - (USHORT
)Remaining
;
1199 /* Check if we have an RC number */
1200 if (CmNtCSDVersion
& 0xFFFF0000)
1202 /* Check if we have no version data yet */
1206 Remaining
= sizeof(Buffer
);
1211 /* Add comma and space */
1212 Status
= RtlStringCbCatExA(Buffer
,
1218 if (!NT_SUCCESS(Status
))
1221 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1225 /* Add the version format string */
1226 Status
= RtlStringCbPrintfA(RcEnd
,
1229 (CmNtCSDVersion
& 0xFFFF0000) >> 16);
1230 if (!NT_SUCCESS(Status
))
1233 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1237 /* Now setup the final string */
1238 RtlInitAnsiString(&CsdString
, Buffer
);
1239 Status
= RtlAnsiStringToUnicodeString(&CmCSDVersionString
,
1242 if (!NT_SUCCESS(Status
))
1245 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1248 /* Add our version */
1249 Status
= RtlStringCbPrintfA(VersionBuffer
,
1250 sizeof(VersionBuffer
),
1252 VER_PRODUCTMAJORVERSION
,
1253 VER_PRODUCTMINORVERSION
);
1254 if (!NT_SUCCESS(Status
))
1257 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1260 /* Build the final version string */
1261 RtlCreateUnicodeStringFromAsciiz(&CmVersionString
, VersionBuffer
);
1263 /* Check if the user wants a kernel stack trace database */
1264 if (NtGlobalFlag
& FLG_KERNEL_STACK_TRACE_DB
)
1267 DPRINT1("Kernel-mode stack trace support not yet present."
1268 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
1271 /* Check if he wanted exception logging */
1272 if (NtGlobalFlag
& FLG_ENABLE_EXCEPTION_LOGGING
)
1275 DPRINT1("Kernel-mode exception logging support not yet present."
1276 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
1279 /* Initialize the Handle Table */
1280 ExpInitializeHandleTables();
1283 /* On checked builds, allocate the system call count table */
1284 KeServiceDescriptorTable
[0].Count
=
1285 ExAllocatePoolWithTag(NonPagedPool
,
1286 KiServiceLimit
* sizeof(ULONG
),
1289 /* Use it for the shadow table too */
1290 KeServiceDescriptorTableShadow
[0].Count
= KeServiceDescriptorTable
[0].Count
;
1292 /* Make sure allocation succeeded */
1293 if (KeServiceDescriptorTable
[0].Count
)
1295 /* Zero the call counts to 0 */
1296 RtlZeroMemory(KeServiceDescriptorTable
[0].Count
,
1297 KiServiceLimit
* sizeof(ULONG
));
1301 /* Create the Basic Object Manager Types to allow new Object Types */
1302 if (!ObInitSystem()) KeBugCheck(OBJECT_INITIALIZATION_FAILED
);
1304 /* Load basic Security for other Managers */
1305 if (!SeInitSystem()) KeBugCheck(SECURITY_INITIALIZATION_FAILED
);
1307 /* Initialize the Process Manager */
1308 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS_INITIALIZATION_FAILED
);
1310 /* Initialize the PnP Manager */
1311 if (!PpInitSystem()) KeBugCheck(PP0_INITIALIZATION_FAILED
);
1313 /* Initialize the User-Mode Debugging Subsystem */
1316 /* Calculate the tick count multiplier */
1317 ExpTickCountMultiplier
= ExComputeTickCountMultiplier(KeMaximumIncrement
);
1318 SharedUserData
->TickCountMultiplier
= ExpTickCountMultiplier
;
1320 /* Set the OS Version */
1321 SharedUserData
->NtMajorVersion
= NtMajorVersion
;
1322 SharedUserData
->NtMinorVersion
= NtMinorVersion
;
1324 /* Set the machine type */
1325 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_NATIVE
;
1326 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_NATIVE
;
1331 MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
1336 Phase1InitializationDiscard(IN PVOID Context
)
1338 PLOADER_PARAMETER_BLOCK LoaderBlock
= Context
;
1339 NTSTATUS Status
, MsgStatus
;
1340 TIME_FIELDS TimeFields
;
1341 LARGE_INTEGER SystemBootTime
, UniversalBootTime
, OldTime
, Timeout
;
1342 BOOLEAN SosEnabled
, NoGuiBoot
, ResetBias
= FALSE
, AlternateShell
= FALSE
;
1343 PLDR_DATA_TABLE_ENTRY NtosEntry
;
1344 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
1345 PCHAR CommandLine
, Y2KHackRequired
, SafeBoot
, Environment
;
1346 PCHAR StringBuffer
, EndBuffer
, BeginBuffer
, MpString
= "";
1347 PINIT_BUFFER InitBuffer
;
1348 ANSI_STRING TempString
;
1349 ULONG LastTzBias
, Length
, YearHack
= 0, Disposition
, MessageCode
= 0;
1352 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
1353 KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo
;
1354 UNICODE_STRING KeyName
;
1355 OBJECT_ATTRIBUTES ObjectAttributes
;
1356 HANDLE KeyHandle
, OptionHandle
;
1357 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
1359 /* Allocate the initialization buffer */
1360 InitBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1361 sizeof(INIT_BUFFER
),
1366 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 8, 0, 0);
1369 /* Set to phase 1 */
1370 ExpInitializationPhase
= 1;
1372 /* Set us at maximum priority */
1373 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY
);
1375 /* Do Phase 1 HAL Initialization */
1376 if (!HalInitSystem(1, LoaderBlock
)) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1378 /* Get the command line and upcase it */
1379 CommandLine
= _strupr(LoaderBlock
->LoadOptions
);
1381 /* Check if GUI Boot is enabled */
1382 NoGuiBoot
= (strstr(CommandLine
, "NOGUIBOOT")) ? TRUE
: FALSE
;
1384 /* Get the SOS setting */
1385 SosEnabled
= strstr(CommandLine
, "SOS") ? TRUE
: FALSE
;
1387 /* Setup the boot driver */
1388 InbvEnableBootDriver(!NoGuiBoot
);
1389 InbvDriverInitialize(LoaderBlock
, 18);
1391 /* Check if GUI boot is enabled */
1394 /* It is, display the boot logo and enable printing strings */
1395 InbvEnableDisplayString(SosEnabled
);
1396 DisplayBootBitmap(SosEnabled
);
1400 /* Release display ownership if not using GUI boot */
1401 InbvNotifyDisplayOwnershipLost(NULL
);
1403 /* Don't allow boot-time strings */
1404 InbvEnableDisplayString(FALSE
);
1407 /* Check if this is LiveCD (WinPE) mode */
1408 if (strstr(CommandLine
, "MININT"))
1410 /* Setup WinPE Settings */
1411 InitIsWinPEMode
= TRUE
;
1412 InitWinPEModeType
|= (strstr(CommandLine
, "INRAM")) ? 0x80000000 : 1;
1415 /* Get the kernel's load entry */
1416 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1417 LDR_DATA_TABLE_ENTRY
,
1420 /* Find the banner message */
1421 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1427 /* Setup defaults and check if we have a version string */
1428 StringBuffer
= InitBuffer
->VersionBuffer
;
1429 BeginBuffer
= StringBuffer
;
1430 EndBuffer
= StringBuffer
;
1431 Remaining
= sizeof(InitBuffer
->VersionBuffer
);
1432 if (CmCSDVersionString
.Length
)
1434 /* Print the version string */
1435 Status
= RtlStringCbPrintfExA(StringBuffer
,
1441 &CmCSDVersionString
);
1442 if (!NT_SUCCESS(Status
))
1445 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1451 *EndBuffer
= ANSI_NULL
; /* Null-terminate the string */
1454 /* Skip over the null-terminator to start a new string */
1458 /* Build the version number */
1459 StringBuffer
= InitBuffer
->VersionNumber
;
1460 Status
= RtlStringCbPrintfA(StringBuffer
,
1461 sizeof(InitBuffer
->VersionNumber
),
1463 VER_PRODUCTMAJORVERSION
,
1464 VER_PRODUCTMINORVERSION
);
1465 if (!NT_SUCCESS(Status
))
1468 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1471 /* Check if we had found a banner message */
1472 if (NT_SUCCESS(MsgStatus
))
1474 /* Create the banner message */
1475 Status
= RtlStringCbPrintfA(EndBuffer
,
1477 (PCHAR
)MsgEntry
->Text
,
1479 NtBuildNumber
& 0xFFFF,
1481 if (!NT_SUCCESS(Status
))
1484 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1489 /* Use hard-coded banner message */
1490 Status
= RtlStringCbCopyA(EndBuffer
, Remaining
, "REACTOS (R)\r\n");
1491 if (!NT_SUCCESS(Status
))
1494 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1498 /* Display the version string on-screen */
1499 InbvDisplayString(EndBuffer
);
1501 /* Initialize Power Subsystem in Phase 0 */
1502 if (!PoInitSystem(0)) KeBugCheck(INTERNAL_POWER_ERROR
);
1504 /* Check for Y2K hack */
1505 Y2KHackRequired
= strstr(CommandLine
, "YEAR");
1506 if (Y2KHackRequired
) Y2KHackRequired
= strstr(Y2KHackRequired
, "=");
1507 if (Y2KHackRequired
) YearHack
= atol(Y2KHackRequired
+ 1);
1509 /* Query the clock */
1510 if ((ExCmosClockIsSane
) && (HalQueryRealTimeClock(&TimeFields
)))
1512 /* Check if we're using the Y2K hack */
1513 if (Y2KHackRequired
) TimeFields
.Year
= (CSHORT
)YearHack
;
1515 /* Convert to time fields */
1516 RtlTimeFieldsToTime(&TimeFields
, &SystemBootTime
);
1517 UniversalBootTime
= SystemBootTime
;
1519 /* Check if real time is GMT */
1520 if (!ExpRealTimeIsUniversal
)
1522 /* Check if we don't have a valid bias */
1523 if (ExpLastTimeZoneBias
== MAXULONG
)
1527 ExpLastTimeZoneBias
= ExpAltTimeZoneBias
;
1530 /* Calculate the bias in seconds */
1531 ExpTimeZoneBias
.QuadPart
= Int32x32To64(ExpLastTimeZoneBias
* 60,
1534 /* Set the boot time-zone bias */
1535 SharedUserData
->TimeZoneBias
.High2Time
= ExpTimeZoneBias
.HighPart
;
1536 SharedUserData
->TimeZoneBias
.LowPart
= ExpTimeZoneBias
.LowPart
;
1537 SharedUserData
->TimeZoneBias
.High1Time
= ExpTimeZoneBias
.HighPart
;
1539 /* Convert the boot time to local time, and set it */
1540 UniversalBootTime
.QuadPart
= SystemBootTime
.QuadPart
+
1541 ExpTimeZoneBias
.QuadPart
;
1544 /* Update the system time */
1545 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1547 /* Do system callback */
1548 PoNotifySystemTimeSet();
1550 /* Remember this as the boot time */
1551 KeBootTime
= UniversalBootTime
;
1555 /* Initialize all processors */
1556 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1559 /* HACK: We should use RtlFindMessage and not only fallback to this */
1560 MpString
= "MultiProcessor Kernel\r\n";
1563 /* Setup the "MP" String */
1564 RtlInitAnsiString(&TempString
, MpString
);
1566 /* Make sure to remove the \r\n if we actually have a string */
1567 while ((TempString
.Length
> 0) &&
1568 ((TempString
.Buffer
[TempString
.Length
- 1] == '\r') ||
1569 (TempString
.Buffer
[TempString
.Length
- 1] == '\n')))
1571 /* Skip the trailing character */
1572 TempString
.Length
--;
1575 /* Get the information string from our resource file */
1576 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1579 KeNumberProcessors
> 1 ?
1580 WINDOWS_NT_INFO_STRING_PLURAL
:
1581 WINDOWS_NT_INFO_STRING
,
1584 /* Get total RAM size */
1585 Size
= MmNumberOfPhysicalPages
* PAGE_SIZE
/ 1024 / 1024;
1587 /* Create the string */
1588 StringBuffer
= InitBuffer
->VersionBuffer
;
1589 Status
= RtlStringCbPrintfA(StringBuffer
,
1590 sizeof(InitBuffer
->VersionBuffer
),
1591 NT_SUCCESS(MsgStatus
) ?
1592 (PCHAR
)MsgEntry
->Text
:
1593 "%u System Processor [%u MB Memory] %Z\r\n",
1597 if (!NT_SUCCESS(Status
))
1600 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
1603 /* Display RAM and CPU count */
1604 InbvDisplayString(StringBuffer
);
1606 /* Update the progress bar */
1607 InbvUpdateProgressBar(5);
1609 /* Call OB initialization again */
1610 if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED
);
1612 /* Initialize Basic System Objects and Worker Threads */
1613 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 1, 0);
1615 /* Initialize the later stages of the kernel */
1616 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 2, 0);
1618 /* Call KD Providers at Phase 1 */
1619 if (!KdInitSystem(ExpInitializationPhase
, KeLoaderBlock
))
1621 /* Failed, bugcheck */
1622 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 3, 0);
1625 /* Initialize the SRM in Phase 1 */
1626 if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED
);
1628 /* Update the progress bar */
1629 InbvUpdateProgressBar(10);
1631 /* Create SystemRoot Link */
1632 Status
= ExpCreateSystemRootLink(LoaderBlock
);
1633 if (!NT_SUCCESS(Status
))
1635 /* Failed to create the system root link */
1636 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1639 /* Set up Region Maps, Sections and the Paging File */
1640 if (!MmInitSystem(1, LoaderBlock
)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED
);
1642 /* Create NLS section */
1643 ExpInitNls(LoaderBlock
);
1645 /* Initialize Cache Views */
1646 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED
);
1648 /* Initialize the Registry */
1649 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
1651 /* Initialize Prefetcher */
1652 CcPfInitializePrefetcher();
1654 /* Update progress bar */
1655 InbvUpdateProgressBar(15);
1657 /* Update timezone information */
1658 LastTzBias
= ExpLastTimeZoneBias
;
1659 ExRefreshTimeZoneInformation(&SystemBootTime
);
1661 /* Check if we're resetting timezone data */
1664 /* Convert the local time to system time */
1665 ExLocalTimeToSystemTime(&SystemBootTime
, &UniversalBootTime
);
1666 KeBootTime
= UniversalBootTime
;
1669 /* Set the new time */
1670 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1674 /* Check if the timezone switched and update the time */
1675 if (LastTzBias
!= ExpLastTimeZoneBias
) ZwSetSystemTime(NULL
, NULL
);
1678 /* Initialize the File System Runtime Library */
1679 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED
);
1681 /* Initialize range lists */
1682 RtlInitializeRangeListPackage();
1684 /* Report all resources used by HAL */
1685 HalReportResourceUsage();
1687 /* Call the debugger DLL */
1688 KdDebuggerInitialize1(LoaderBlock
);
1690 /* Setup PnP Manager in phase 1 */
1691 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED
);
1693 /* Update progress bar */
1694 InbvUpdateProgressBar(20);
1696 /* Initialize LPC */
1697 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED
);
1699 /* Make sure we have a command line */
1702 /* Check if this is a safe mode boot */
1703 SafeBoot
= strstr(CommandLine
, "SAFEBOOT:");
1706 /* Check what kind of boot this is */
1708 if (!strncmp(SafeBoot
, "MINIMAL", 7))
1711 InitSafeBootMode
= 1;
1713 MessageCode
= BOOTING_IN_SAFEMODE_MINIMAL
;
1715 else if (!strncmp(SafeBoot
, "NETWORK", 7))
1717 /* With Networking */
1718 InitSafeBootMode
= 2;
1720 MessageCode
= BOOTING_IN_SAFEMODE_NETWORK
;
1722 else if (!strncmp(SafeBoot
, "DSREPAIR", 8))
1724 /* Domain Server Repair */
1725 InitSafeBootMode
= 3;
1727 MessageCode
= BOOTING_IN_SAFEMODE_DSREPAIR
;
1733 InitSafeBootMode
= 0;
1736 /* Check if there's any settings left */
1739 /* Check if an alternate shell was requested */
1740 if (!strncmp(SafeBoot
, "(ALTERNATESHELL)", 16))
1742 /* Remember this for later */
1743 AlternateShell
= TRUE
;
1747 /* Find the message to print out */
1748 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1753 if (NT_SUCCESS(Status
))
1756 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1761 /* Make sure we have a command line */
1764 /* Check if bootlogging is enabled */
1765 if (strstr(CommandLine
, "BOOTLOG"))
1767 /* Find the message to print out */
1768 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1773 if (NT_SUCCESS(Status
))
1776 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1779 /* Setup boot logging */
1780 //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader);
1784 /* Setup the Executive in Phase 2 */
1785 //ExInitSystemPhase2();
1787 /* Update progress bar */
1788 InbvUpdateProgressBar(25);
1791 /* No KD Time Slip is pending */
1792 KdpTimeSlipPending
= 0;
1795 /* Initialize in-place execution support */
1796 XIPInit(LoaderBlock
);
1798 /* Set maximum update to 75% */
1799 InbvSetProgressBarSubset(25, 75);
1801 /* Initialize the I/O Subsystem */
1802 if (!IoInitSystem(LoaderBlock
)) KeBugCheck(IO1_INITIALIZATION_FAILED
);
1804 /* Set maximum update to 100% */
1805 InbvSetProgressBarSubset(0, 100);
1807 /* Are we in safe mode? */
1808 if (InitSafeBootMode
)
1810 /* Open the safe boot key */
1811 RtlInitUnicodeString(&KeyName
,
1812 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1813 L
"\\CONTROL\\SAFEBOOT");
1814 InitializeObjectAttributes(&ObjectAttributes
,
1816 OBJ_CASE_INSENSITIVE
,
1819 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1820 if (NT_SUCCESS(Status
))
1822 /* First check if we have an alternate shell */
1825 /* Make sure that the registry has one setup */
1826 RtlInitUnicodeString(&KeyName
, L
"AlternateShell");
1827 Status
= NtQueryValueKey(KeyHandle
,
1829 KeyValuePartialInformation
,
1831 sizeof(KeyPartialInfo
),
1833 if (!(NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_OVERFLOW
))
1835 AlternateShell
= FALSE
;
1839 /* Create the option key */
1840 RtlInitUnicodeString(&KeyName
, L
"Option");
1841 InitializeObjectAttributes(&ObjectAttributes
,
1843 OBJ_CASE_INSENSITIVE
,
1846 Status
= ZwCreateKey(&OptionHandle
,
1851 REG_OPTION_VOLATILE
,
1855 /* Check if the key create worked */
1856 if (NT_SUCCESS(Status
))
1858 /* Write the safe boot type */
1859 RtlInitUnicodeString(&KeyName
, L
"OptionValue");
1860 NtSetValueKey(OptionHandle
,
1865 sizeof(InitSafeBootMode
));
1867 /* Check if we have to use an alternate shell */
1870 /* Remember this for later */
1872 RtlInitUnicodeString(&KeyName
, L
"UseAlternateShell");
1873 NtSetValueKey(OptionHandle
,
1878 sizeof(Disposition
));
1881 /* Close the options key handle */
1882 NtClose(OptionHandle
);
1887 /* Are we in Win PE mode? */
1888 if (InitIsWinPEMode
)
1890 /* Open the safe control key */
1891 RtlInitUnicodeString(&KeyName
,
1892 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1894 InitializeObjectAttributes(&ObjectAttributes
,
1896 OBJ_CASE_INSENSITIVE
,
1899 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1900 if (!NT_SUCCESS(Status
))
1903 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1906 /* Create the MiniNT key */
1907 RtlInitUnicodeString(&KeyName
, L
"MiniNT");
1908 InitializeObjectAttributes(&ObjectAttributes
,
1910 OBJ_CASE_INSENSITIVE
,
1913 Status
= ZwCreateKey(&OptionHandle
,
1918 REG_OPTION_VOLATILE
,
1920 if (!NT_SUCCESS(Status
))
1923 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1926 /* Close the handles */
1928 NtClose(OptionHandle
);
1931 /* FIXME: This doesn't do anything for now */
1932 MmArmInitSystem(2, LoaderBlock
);
1934 /* Update progress bar */
1935 InbvUpdateProgressBar(80);
1937 /* Initialize VDM support */
1938 #if defined(_M_IX86)
1939 KeI386VdmInitialize();
1942 /* Initialize Power Subsystem in Phase 1*/
1943 if (!PoInitSystem(1)) KeBugCheck(INTERNAL_POWER_ERROR
);
1945 /* Update progress bar */
1946 InbvUpdateProgressBar(90);
1948 /* Initialize the Process Manager at Phase 1 */
1949 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1951 /* Make sure nobody touches the loader block again */
1952 if (LoaderBlock
== KeLoaderBlock
) KeLoaderBlock
= NULL
;
1953 MmFreeLoaderBlock(LoaderBlock
);
1954 LoaderBlock
= Context
= NULL
;
1956 /* Update progress bar */
1957 InbvUpdateProgressBar(100);
1959 /* Clear the screen */
1960 if (InbvBootDriverInstalled
) FinalizeBootLogo();
1962 /* Allow strings to be displayed */
1963 InbvEnableDisplayString(TRUE
);
1965 /* Launch initial process */
1966 DPRINT("Free non-cache pages: %lx\n", MmAvailablePages
+ MiMemoryConsumers
[MC_CACHE
].PagesUsed
);
1967 ProcessInfo
= &InitBuffer
->ProcessInfo
;
1968 ExpLoadInitialProcess(InitBuffer
, &ProcessParameters
, &Environment
);
1970 /* Wait 5 seconds for initial process to initialize */
1971 Timeout
.QuadPart
= Int32x32To64(5, -10000000);
1972 Status
= ZwWaitForSingleObject(ProcessInfo
->ProcessHandle
, FALSE
, &Timeout
);
1973 if (Status
== STATUS_SUCCESS
)
1975 /* Failed, display error */
1976 DPRINT1("INIT: Session Manager terminated.\n");
1978 /* Bugcheck the system if SMSS couldn't initialize */
1979 KeBugCheck(SESSION5_INITIALIZATION_FAILED
);
1982 /* Close process handles */
1983 ZwClose(ProcessInfo
->ThreadHandle
);
1984 ZwClose(ProcessInfo
->ProcessHandle
);
1986 /* Free the initial process environment */
1988 ZwFreeVirtualMemory(NtCurrentProcess(),
1989 (PVOID
*)&Environment
,
1993 /* Free the initial process parameters */
1995 ZwFreeVirtualMemory(NtCurrentProcess(),
1996 (PVOID
*)&ProcessParameters
,
2000 /* Increase init phase */
2001 ExpInitializationPhase
++;
2003 /* Free the boot buffer */
2004 ExFreePoolWithTag(InitBuffer
, TAG_INIT
);
2005 DPRINT("Free non-cache pages: %lx\n", MmAvailablePages
+ MiMemoryConsumers
[MC_CACHE
].PagesUsed
);
2010 Phase1Initialization(IN PVOID Context
)
2012 /* Do the .INIT part of Phase 1 which we can free later */
2013 Phase1InitializationDiscard(Context
);
2015 /* Jump into zero page thread */