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>
22 IN PLOADER_PARAMETER_BLOCK LoaderBlock
25 typedef struct _INIT_BUFFER
27 WCHAR DebugBuffer
[256];
28 CHAR VersionBuffer
[256];
29 CHAR BootlogHeader
[256];
30 CHAR VersionNumber
[24];
31 RTL_USER_PROCESS_INFORMATION ProcessInfo
;
32 WCHAR RegistryBuffer
[256];
33 } INIT_BUFFER
, *PINIT_BUFFER
;
35 /* DATA **********************************************************************/
38 ULONG NtMajorVersion
= VER_PRODUCTMAJORVERSION
;
39 ULONG NtMinorVersion
= VER_PRODUCTMINORVERSION
;
41 ULONG NtBuildNumber
= VER_PRODUCTBUILD
| 0xC0000000;
43 ULONG NtBuildNumber
= VER_PRODUCTBUILD
;
47 ULONG NtGlobalFlag
= 0;
51 ULONG CmNtSpBuildNumber
;
53 ULONG CmNtCSDReleaseType
;
54 UNICODE_STRING CmVersionString
;
55 UNICODE_STRING CmCSDVersionString
;
56 CHAR NtBuildLab
[] = KERNEL_VERSION_BUILD_STR
;
58 /* Init flags and settings */
59 ULONG ExpInitializationPhase
;
60 BOOLEAN ExpInTextModeSetup
;
61 BOOLEAN IoRemoteBootClient
;
62 ULONG InitSafeBootMode
;
63 BOOLEAN InitIsWinPEMode
, InitWinPEModeType
;
66 UNICODE_STRING NtSystemRoot
;
68 /* NT Initial User Application */
69 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
70 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
72 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
74 /* Boot NLS information */
75 PVOID ExpNlsTableBase
;
76 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
77 ULONG ExpUnicodeCaseTableDataOffset
;
78 NLSTABLEINFO ExpNlsTableInfo
;
79 SIZE_T ExpNlsTableSize
;
80 PVOID ExpNlsSectionPointer
;
82 /* CMOS Timer Sanity */
83 BOOLEAN ExCmosClockIsSane
= TRUE
;
84 BOOLEAN ExpRealTimeIsUniversal
;
86 /* FUNCTIONS ****************************************************************/
91 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
93 UNICODE_STRING LinkName
;
94 OBJECT_ATTRIBUTES ObjectAttributes
;
99 ANSI_STRING TargetString
;
100 UNICODE_STRING TargetName
;
102 /* Initialize the ArcName tree */
103 RtlInitUnicodeString(&LinkName
, L
"\\ArcName");
104 InitializeObjectAttributes(&ObjectAttributes
,
106 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
108 SePublicDefaultUnrestrictedSd
);
111 Status
= NtCreateDirectoryObject(&LinkHandle
,
112 DIRECTORY_ALL_ACCESS
,
114 if (!NT_SUCCESS(Status
))
117 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
120 /* Close the LinkHandle */
123 /* Initialize the Device tree */
124 RtlInitUnicodeString(&LinkName
, L
"\\Device");
125 InitializeObjectAttributes(&ObjectAttributes
,
127 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
129 SePublicDefaultUnrestrictedSd
);
132 Status
= NtCreateDirectoryObject(&LinkHandle
,
133 DIRECTORY_ALL_ACCESS
,
135 if (!NT_SUCCESS(Status
))
138 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
141 /* Close the LinkHandle */
142 ObCloseHandle(LinkHandle
, KernelMode
);
144 /* Create the system root symlink name */
145 RtlInitAnsiString(&AnsiName
, "\\SystemRoot");
146 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &AnsiName
, TRUE
);
147 if (!NT_SUCCESS(Status
))
150 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
153 /* Initialize the attributes for the link */
154 InitializeObjectAttributes(&ObjectAttributes
,
156 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
158 SePublicDefaultUnrestrictedSd
);
160 /* Build the ARC name */
163 LoaderBlock
->ArcBootDeviceName
,
164 LoaderBlock
->NtBootPathName
);
165 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
167 /* Convert it to Unicode */
168 RtlInitString(&TargetString
, Buffer
);
169 Status
= RtlAnsiStringToUnicodeString(&TargetName
,
172 if (!NT_SUCCESS(Status
))
174 /* We failed, bugcheck */
175 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
179 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
180 SYMBOLIC_LINK_ALL_ACCESS
,
184 /* Free the strings */
185 RtlFreeUnicodeString(&LinkName
);
186 RtlFreeUnicodeString(&TargetName
);
188 /* Check if creating the link failed */
189 if (!NT_SUCCESS(Status
))
192 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
195 /* Close the handle and return success */
196 ObCloseHandle(LinkHandle
, KernelMode
);
197 return STATUS_SUCCESS
;
203 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
205 LARGE_INTEGER SectionSize
;
208 PVOID SectionBase
= NULL
;
210 LARGE_INTEGER SectionOffset
= {{0, 0}};
211 PLIST_ENTRY ListHead
, NextEntry
;
212 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
213 ULONG NlsTablesEncountered
= 0;
214 SIZE_T NlsTableSizes
[3]; /* 3 NLS tables */
216 /* Check if this is boot-time phase 0 initialization */
217 if (!ExpInitializationPhase
)
219 /* Loop the memory descriptors */
220 ListHead
= &LoaderBlock
->MemoryDescriptorListHead
;
221 NextEntry
= ListHead
->Flink
;
222 while (NextEntry
!= ListHead
)
224 /* Get the current block */
225 MdBlock
= CONTAINING_RECORD(NextEntry
,
226 MEMORY_ALLOCATION_DESCRIPTOR
,
229 /* Check if this is an NLS block */
230 if (MdBlock
->MemoryType
== LoaderNlsData
)
232 /* Increase the table size */
233 ExpNlsTableSize
+= MdBlock
->PageCount
* PAGE_SIZE
;
235 /* FreeLdr-specific */
236 NlsTableSizes
[NlsTablesEncountered
] = MdBlock
->PageCount
* PAGE_SIZE
;
237 NlsTablesEncountered
++;
238 ASSERT(NlsTablesEncountered
< 4);
241 /* Go to the next block */
242 NextEntry
= MdBlock
->ListEntry
.Flink
;
245 /* Allocate the a new buffer since loader memory will be freed */
246 ExpNlsTableBase
= ExAllocatePoolWithTag(NonPagedPool
,
249 if (!ExpNlsTableBase
) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
251 /* Copy the codepage data in its new location. */
252 if (NlsTablesEncountered
== 1)
254 /* Ntldr-way boot process */
255 RtlCopyMemory(ExpNlsTableBase
,
256 LoaderBlock
->NlsData
->AnsiCodePageData
,
262 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
263 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
265 RtlCopyMemory(ExpNlsTableBase
,
266 LoaderBlock
->NlsData
->AnsiCodePageData
,
269 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0]),
270 LoaderBlock
->NlsData
->OemCodePageData
,
273 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0] +
275 LoaderBlock
->NlsData
->UnicodeCodePageData
,
280 /* Initialize and reset the NLS TAbles */
281 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
282 ExpAnsiCodePageDataOffset
),
283 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
284 ExpOemCodePageDataOffset
),
285 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
286 ExpUnicodeCaseTableDataOffset
),
288 RtlResetRtlTranslations(&ExpNlsTableInfo
);
292 /* Set the section size */
293 SectionSize
.QuadPart
= ExpNlsTableSize
;
295 /* Create the NLS Section */
296 Status
= ZwCreateSection(&NlsSection
,
303 if (!NT_SUCCESS(Status
))
306 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
309 /* Get a pointer to the section */
310 Status
= ObReferenceObjectByHandle(NlsSection
,
314 &ExpNlsSectionPointer
,
316 ObCloseHandle(NlsSection
, KernelMode
);
317 if (!NT_SUCCESS(Status
))
320 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
323 /* Map the NLS Section in system space */
324 Status
= MmMapViewInSystemSpace(ExpNlsSectionPointer
,
327 if (!NT_SUCCESS(Status
))
330 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
333 /* Copy the codepage data in its new location. */
334 ASSERT(SectionBase
>= MmSystemRangeStart
);
335 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
337 /* Free the previously allocated buffer and set the new location */
338 ExFreePoolWithTag(ExpNlsTableBase
, TAG_RTLI
);
339 ExpNlsTableBase
= SectionBase
;
341 /* Initialize the NLS Tables */
342 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
343 ExpAnsiCodePageDataOffset
),
344 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
345 ExpOemCodePageDataOffset
),
346 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
347 ExpUnicodeCaseTableDataOffset
),
349 RtlResetRtlTranslations(&ExpNlsTableInfo
);
351 /* Reset the base to 0 */
354 /* Map the section in the system process */
355 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
356 PsGetCurrentProcess(),
365 if (!NT_SUCCESS(Status
))
368 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
371 /* Copy the table into the system process and set this as the base */
372 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
373 ExpNlsTableBase
= SectionBase
;
379 ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer
,
380 OUT PRTL_USER_PROCESS_PARAMETERS
*ProcessParameters
,
381 OUT PCHAR
*ProcessEnvironment
)
386 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
387 UNICODE_STRING SmssName
, Environment
, SystemDriveString
, DebugString
;
388 PVOID EnvironmentPtr
= NULL
;
389 PRTL_USER_PROCESS_INFORMATION ProcessInformation
;
390 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= NULL
;
392 NullString
.Length
= sizeof(WCHAR
);
394 /* Use the initial buffer, after the strings */
395 ProcessInformation
= &InitBuffer
->ProcessInfo
;
397 /* Allocate memory for the process parameters */
398 Size
= sizeof(*ProcessParams
) + ((MAX_PATH
* 6) * sizeof(WCHAR
));
399 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
400 (PVOID
*)&ProcessParams
,
403 MEM_RESERVE
| MEM_COMMIT
,
405 if (!NT_SUCCESS(Status
))
407 /* Failed, display error */
408 p
= InitBuffer
->DebugBuffer
;
411 L
"INIT: Unable to allocate Process Parameters. 0x%lx",
413 RtlInitUnicodeString(&DebugString
, p
);
414 ZwDisplayString(&DebugString
);
416 /* Bugcheck the system */
417 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
420 /* Setup the basic header, and give the process the low 1MB to itself */
421 ProcessParams
->Length
= (ULONG
)Size
;
422 ProcessParams
->MaximumLength
= (ULONG
)Size
;
423 ProcessParams
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
424 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
426 /* Allocate a page for the environment */
428 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
432 MEM_RESERVE
| MEM_COMMIT
,
434 if (!NT_SUCCESS(Status
))
436 /* Failed, display error */
437 p
= InitBuffer
->DebugBuffer
;
440 L
"INIT: Unable to allocate Process Environment. 0x%lx",
442 RtlInitUnicodeString(&DebugString
, p
);
443 ZwDisplayString(&DebugString
);
445 /* Bugcheck the system */
446 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
449 /* Write the pointer */
450 ProcessParams
->Environment
= EnvironmentPtr
;
452 /* Make a buffer for the DOS path */
453 p
= (PWSTR
)(ProcessParams
+ 1);
454 ProcessParams
->CurrentDirectory
.DosPath
.Buffer
= p
;
455 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
= MAX_PATH
*
458 /* Copy the DOS path */
459 RtlCopyUnicodeString(&ProcessParams
->CurrentDirectory
.DosPath
,
462 /* Make a buffer for the DLL Path */
463 p
= (PWSTR
)((PCHAR
)ProcessParams
->CurrentDirectory
.DosPath
.Buffer
+
464 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
);
465 ProcessParams
->DllPath
.Buffer
= p
;
466 ProcessParams
->DllPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
468 /* Copy the DLL path and append the system32 directory */
469 RtlCopyUnicodeString(&ProcessParams
->DllPath
,
470 &ProcessParams
->CurrentDirectory
.DosPath
);
471 RtlAppendUnicodeToString(&ProcessParams
->DllPath
, L
"\\System32");
473 /* Make a buffer for the image name */
474 p
= (PWSTR
)((PCHAR
)ProcessParams
->DllPath
.Buffer
+
475 ProcessParams
->DllPath
.MaximumLength
);
476 ProcessParams
->ImagePathName
.Buffer
= p
;
477 ProcessParams
->ImagePathName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
479 /* Make sure the buffer is a valid string which within the given length */
480 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
481 ((NtInitialUserProcessBufferLength
!= MAXULONG
) &&
482 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
483 (NtInitialUserProcessBufferLength
>
484 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
486 /* Invalid initial process string, bugcheck */
487 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
,
488 STATUS_INVALID_PARAMETER
,
489 NtInitialUserProcessBufferType
,
490 NtInitialUserProcessBufferLength
,
491 sizeof(NtInitialUserProcessBuffer
));
494 /* Cut out anything after a space */
495 p
= NtInitialUserProcessBuffer
;
496 while ((*p
) && (*p
!= L
' ')) p
++;
498 /* Set the image path length */
499 ProcessParams
->ImagePathName
.Length
=
500 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
502 /* Copy the actual buffer */
503 RtlCopyMemory(ProcessParams
->ImagePathName
.Buffer
,
504 NtInitialUserProcessBuffer
,
505 ProcessParams
->ImagePathName
.Length
);
507 /* Null-terminate it */
508 ProcessParams
->ImagePathName
.Buffer
[ProcessParams
->ImagePathName
.Length
/
509 sizeof(WCHAR
)] = UNICODE_NULL
;
511 /* Make a buffer for the command line */
512 p
= (PWSTR
)((PCHAR
)ProcessParams
->ImagePathName
.Buffer
+
513 ProcessParams
->ImagePathName
.MaximumLength
);
514 ProcessParams
->CommandLine
.Buffer
= p
;
515 ProcessParams
->CommandLine
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
517 /* Add the image name to the command line */
518 RtlAppendUnicodeToString(&ProcessParams
->CommandLine
,
519 NtInitialUserProcessBuffer
);
521 /* Create the environment string */
522 RtlInitEmptyUnicodeString(&Environment
,
523 ProcessParams
->Environment
,
526 /* Append the DLL path to it */
527 RtlAppendUnicodeToString(&Environment
, L
"Path=" );
528 RtlAppendUnicodeStringToString(&Environment
, &ProcessParams
->DllPath
);
529 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
531 /* Create the system drive string */
532 SystemDriveString
= NtSystemRoot
;
533 SystemDriveString
.Length
= 2 * sizeof(WCHAR
);
535 /* Append it to the environment */
536 RtlAppendUnicodeToString(&Environment
, L
"SystemDrive=");
537 RtlAppendUnicodeStringToString(&Environment
, &SystemDriveString
);
538 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
540 /* Append the system root to the environment */
541 RtlAppendUnicodeToString(&Environment
, L
"SystemRoot=");
542 RtlAppendUnicodeStringToString(&Environment
, &NtSystemRoot
);
543 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
545 /* Prepare the prefetcher */
546 //CcPfBeginBootPhase(150);
548 /* Create SMSS process */
549 SmssName
= ProcessParams
->ImagePathName
;
550 Status
= RtlCreateUserProcess(&SmssName
,
551 OBJ_CASE_INSENSITIVE
,
552 RtlDeNormalizeProcessParams(ProcessParams
),
560 if (!NT_SUCCESS(Status
))
562 /* Failed, display error */
563 p
= InitBuffer
->DebugBuffer
;
566 L
"INIT: Unable to create Session Manager. 0x%lx",
568 RtlInitUnicodeString(&DebugString
, p
);
569 ZwDisplayString(&DebugString
);
571 /* Bugcheck the system */
572 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
575 /* Resume the thread */
576 Status
= ZwResumeThread(ProcessInformation
->ThreadHandle
, NULL
);
577 if (!NT_SUCCESS(Status
))
579 /* Failed, display error */
580 p
= InitBuffer
->DebugBuffer
;
583 L
"INIT: Unable to resume Session Manager. 0x%lx",
585 RtlInitUnicodeString(&DebugString
, p
);
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 ExpInitializeEventImplementation();
666 ExpInitializeEventPairImplementation();
668 /* Initialize callbacks */
669 ExpInitializeCallbacks();
671 /* Initialize mutants */
672 ExpInitializeMutantImplementation();
674 /* Initialize semaphores */
675 ExpInitializeSemaphoreImplementation();
677 /* Initialize timers */
678 ExpInitializeTimerImplementation();
680 /* Initialize profiling */
681 ExpInitializeProfileImplementation();
683 /* Initialize UUIDs */
686 /* Initialize Win32K */
696 /* Check the initialization phase */
697 switch (ExpInitializationPhase
)
702 return ExpInitSystemPhase0();
707 return ExpInitSystemPhase1();
711 /* Don't know any other phase! Bugcheck! */
712 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
720 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
722 PLOADER_PARAMETER_EXTENSION Extension
;
724 /* Get the loader extension */
725 Extension
= LoaderBlock
->Extension
;
727 /* Validate the size (larger structures are OK, we'll just ignore them) */
728 if (Extension
->Size
< sizeof(LOADER_PARAMETER_EXTENSION
)) return FALSE
;
730 /* Don't validate upper versions */
731 if (Extension
->MajorVersion
> VER_PRODUCTMAJORVERSION
) return TRUE
;
733 /* Fail if this is NT 4 */
734 if (Extension
->MajorVersion
< VER_PRODUCTMAJORVERSION
) return FALSE
;
736 /* Fail if this is XP */
737 if (Extension
->MinorVersion
< VER_PRODUCTMINORVERSION
) return FALSE
;
739 /* This is 2003 or newer, approve it */
746 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
749 PLIST_ENTRY NextEntry
;
752 PLDR_DATA_TABLE_ENTRY LdrEntry
;
753 CHAR NameBuffer
[256];
757 /* Loop the driver list */
758 NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
759 while (NextEntry
!= &LoaderBlock
->LoadOrderListHead
)
761 /* Skip the first two images */
765 LdrEntry
= CONTAINING_RECORD(NextEntry
,
766 LDR_DATA_TABLE_ENTRY
,
768 if (LdrEntry
->FullDllName
.Buffer
[0] == L
'\\')
770 /* We have a name, read its data */
771 Name
= LdrEntry
->FullDllName
.Buffer
;
772 Length
= LdrEntry
->FullDllName
.Length
/ sizeof(WCHAR
);
774 /* Check if our buffer can hold it */
775 if (sizeof(NameBuffer
) < Length
+ sizeof(ANSI_NULL
))
778 Status
= STATUS_BUFFER_OVERFLOW
;
786 /* Copy the character */
787 NameBuffer
[Count
++] = (CHAR
)*Name
++;
788 } while (Count
< Length
);
791 NameBuffer
[Count
] = ANSI_NULL
;
792 Status
= STATUS_SUCCESS
;
797 /* Safely print the string into our buffer */
798 Status
= RtlStringCbPrintfA(NameBuffer
,
800 "%S\\System32\\Drivers\\%wZ",
801 &SharedUserData
->NtSystemRoot
[2],
802 &LdrEntry
->BaseDllName
);
805 /* Check if the buffer was ok */
806 if (NT_SUCCESS(Status
))
808 /* Initialize the STRING for the debugger */
809 RtlInitString(&SymbolString
, NameBuffer
);
811 /* Load the symbols */
812 DbgLoadImageSymbols(&SymbolString
,
814 (ULONG_PTR
)ZwCurrentProcess());
818 /* Go to the next entry */
820 NextEntry
= NextEntry
->Flink
;
827 ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
828 IN ULONG_PTR PagesToDestroy
,
829 IN TYPE_OF_MEMORY MemoryType
)
831 PLIST_ENTRY ListEntry
;
832 PMEMORY_ALLOCATION_DESCRIPTOR MemDescriptor
;
834 DPRINT1("Burn RAM amount: %d pages\n", PagesToDestroy
);
836 /* Loop the memory descriptors, beginning at the end */
837 for (ListEntry
= LoaderBlock
->MemoryDescriptorListHead
.Blink
;
838 ListEntry
!= &LoaderBlock
->MemoryDescriptorListHead
;
839 ListEntry
= ListEntry
->Blink
)
841 /* Get the memory descriptor structure */
842 MemDescriptor
= CONTAINING_RECORD(ListEntry
,
843 MEMORY_ALLOCATION_DESCRIPTOR
,
846 /* Is memory free there or is it temporary? */
847 if (MemDescriptor
->MemoryType
== LoaderFree
||
848 MemDescriptor
->MemoryType
== LoaderFirmwareTemporary
)
850 /* Check if the descriptor has more pages than we want */
851 if (MemDescriptor
->PageCount
> PagesToDestroy
)
853 /* Change block's page count, ntoskrnl doesn't care much */
854 MemDescriptor
->PageCount
-= PagesToDestroy
;
859 /* Change block type */
860 MemDescriptor
->MemoryType
= MemoryType
;
861 PagesToDestroy
-= MemDescriptor
->PageCount
;
863 /* Check if we are done */
864 if (PagesToDestroy
== 0) break;
873 ExpInitializeExecutive(IN ULONG Cpu
,
874 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
876 PNLS_DATA_BLOCK NlsData
;
878 ANSI_STRING AnsiPath
;
880 PCHAR CommandLine
, PerfMem
;
882 PLDR_DATA_TABLE_ENTRY NtosEntry
;
883 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
884 ANSI_STRING CsdString
;
885 size_t Remaining
= 0;
887 CHAR VersionBuffer
[65];
889 /* Validate Loader */
890 if (!ExpIsLoaderValid(LoaderBlock
))
892 /* Invalid loader version */
893 KeBugCheckEx(MISMATCHED_HAL
,
895 LoaderBlock
->Extension
->Size
,
896 LoaderBlock
->Extension
->MajorVersion
,
897 LoaderBlock
->Extension
->MinorVersion
);
900 /* Initialize PRCB pool lookaside pointers */
901 ExInitPoolLookasidePointers();
903 /* Check if this is an application CPU */
906 /* Then simply initialize it with HAL */
907 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
909 /* Initialization failed */
910 KeBugCheck(HAL_INITIALIZATION_FAILED
);
917 /* Assume no text-mode or remote boot */
918 ExpInTextModeSetup
= FALSE
;
919 IoRemoteBootClient
= FALSE
;
921 /* Check if we have a setup loader block */
922 if (LoaderBlock
->SetupLdrBlock
)
924 /* Check if this is text-mode setup */
925 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_TEXT_MODE
) ExpInTextModeSetup
= TRUE
;
927 /* Check if this is network boot */
928 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_REMOTE_BOOT
)
931 IoRemoteBootClient
= TRUE
;
933 /* Make sure we're actually booting off the network */
934 ASSERT(!_memicmp(LoaderBlock
->ArcBootDeviceName
, "net(0)", 6));
939 ExpInitializationPhase
= 0;
941 /* Get boot command line */
942 CommandLine
= LoaderBlock
->LoadOptions
;
945 /* Upcase it for comparison and check if we're in performance mode */
946 _strupr(CommandLine
);
947 PerfMem
= strstr(CommandLine
, "PERFMEM");
950 /* Check if the user gave a number of bytes to use */
951 PerfMem
= strstr(PerfMem
, "=");
954 /* Read the number of pages we'll use */
955 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
959 DPRINT1("BBT performance mode not yet supported."
960 "/PERFMEM option ignored.\n");
965 /* Check if we're burning memory */
966 PerfMem
= strstr(CommandLine
, "BURNMEMORY");
969 /* Check if the user gave a number of bytes to use */
970 PerfMem
= strstr(PerfMem
, "=");
973 /* Read the number of pages we'll use */
974 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
975 if (PerfMemUsed
) ExBurnMemory(LoaderBlock
, PerfMemUsed
, LoaderBad
);
980 /* Setup NLS Base and offsets */
981 NlsData
= LoaderBlock
->NlsData
;
982 ExpNlsTableBase
= NlsData
->AnsiCodePageData
;
983 ExpAnsiCodePageDataOffset
= 0;
984 ExpOemCodePageDataOffset
= (ULONG
)((ULONG_PTR
)NlsData
->OemCodePageData
-
985 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
986 ExpUnicodeCaseTableDataOffset
= (ULONG
)((ULONG_PTR
)NlsData
->UnicodeCodePageData
-
987 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
989 /* Initialize the NLS Tables */
990 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
991 ExpAnsiCodePageDataOffset
),
992 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
993 ExpOemCodePageDataOffset
),
994 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
995 ExpUnicodeCaseTableDataOffset
),
997 RtlResetRtlTranslations(&ExpNlsTableInfo
);
999 /* Now initialize the HAL */
1000 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
1002 /* HAL failed to initialize, bugcheck */
1003 KeBugCheck(HAL_INITIALIZATION_FAILED
);
1006 /* Make sure interrupts are active now */
1009 /* Clear the crypto exponent */
1010 SharedUserData
->CryptoExponent
= 0;
1012 /* Set global flags for the checked build */
1014 NtGlobalFlag
|= FLG_ENABLE_CLOSE_EXCEPTIONS
|
1015 FLG_ENABLE_KDEBUG_SYMBOL_LOAD
;
1018 /* Setup NT System Root Path */
1019 sprintf(Buffer
, "C:%s", LoaderBlock
->NtBootPathName
);
1021 /* Convert to ANSI_STRING and null-terminate it */
1022 RtlInitString(&AnsiPath
, Buffer
);
1023 Buffer
[--AnsiPath
.Length
] = ANSI_NULL
;
1025 /* Get the string from KUSER_SHARED_DATA's buffer */
1026 RtlInitEmptyUnicodeString(&NtSystemRoot
,
1027 SharedUserData
->NtSystemRoot
,
1028 sizeof(SharedUserData
->NtSystemRoot
));
1030 /* Now fill it in */
1031 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &AnsiPath
, FALSE
);
1032 if (!NT_SUCCESS(Status
)) KeBugCheck(SESSION3_INITIALIZATION_FAILED
);
1034 /* Setup bugcheck messages */
1035 KiInitializeBugCheck();
1037 /* Setup initial system settings */
1038 CmGetSystemControlValues(LoaderBlock
->RegistryBase
, CmControlVector
);
1040 /* Load static defaults for Service Pack 1 and add our SVN revision */
1041 CmNtCSDVersion
= 0x100 | (KERNEL_VERSION_BUILD_HEX
<< 16);
1042 CmNtCSDReleaseType
= 0;
1044 /* Set Service Pack data for Service Pack 1 */
1045 CmNtSpBuildNumber
= 1830;
1046 if (!(CmNtCSDVersion
& 0xFFFF0000))
1048 /* Check the release type */
1049 if (CmNtCSDReleaseType
== 1) CmNtSpBuildNumber
|= 1830 << 16;
1052 /* Add loaded CmNtGlobalFlag value */
1053 NtGlobalFlag
|= CmNtGlobalFlag
;
1055 /* Initialize the executive at phase 0 */
1056 if (!ExInitSystem()) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1058 /* Initialize the memory manager at phase 0 */
1059 if (!MmArmInitSystem(0, LoaderBlock
)) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1061 /* Load boot symbols */
1062 ExpLoadBootSymbols(LoaderBlock
);
1064 /* Check if we should break after symbol load */
1065 if (KdBreakAfterSymbolLoad
) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
1067 /* Check if this loader is compatible with NT 5.2 */
1068 if (LoaderBlock
->Extension
->Size
>= sizeof(LOADER_PARAMETER_EXTENSION
))
1070 /* Setup headless terminal settings */
1071 HeadlessInit(LoaderBlock
);
1074 /* Set system ranges */
1076 SharedUserData
->Reserved1
= MM_HIGHEST_USER_ADDRESS_WOW64
;
1077 SharedUserData
->Reserved3
= MM_SYSTEM_RANGE_START_WOW64
;
1079 SharedUserData
->Reserved1
= (ULONG_PTR
)MmHighestUserAddress
;
1080 SharedUserData
->Reserved3
= (ULONG_PTR
)MmSystemRangeStart
;
1083 /* Make a copy of the NLS Tables */
1084 ExpInitNls(LoaderBlock
);
1086 /* Get the kernel's load entry */
1087 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1088 LDR_DATA_TABLE_ENTRY
,
1091 /* Check if this is a service pack */
1092 if (CmNtCSDVersion
& 0xFFFF)
1094 /* Get the service pack string */
1095 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1098 WINDOWS_NT_CSD_STRING
,
1100 if (NT_SUCCESS(Status
))
1102 /* Setup the string */
1103 RtlInitAnsiString(&CsdString
, (PCHAR
)MsgEntry
->Text
);
1105 /* Remove trailing newline */
1106 while ((CsdString
.Length
> 0) &&
1107 ((CsdString
.Buffer
[CsdString
.Length
- 1] == '\r') ||
1108 (CsdString
.Buffer
[CsdString
.Length
- 1] == '\n')))
1110 /* Skip the trailing character */
1114 /* Fill the buffer with version information */
1115 Status
= RtlStringCbPrintfA(Buffer
,
1119 (CmNtCSDVersion
& 0xFF00) >> 8,
1120 (CmNtCSDVersion
& 0xFF) ?
1121 'A' + (CmNtCSDVersion
& 0xFF) - 1 :
1126 /* Build default string */
1127 Status
= RtlStringCbPrintfA(Buffer
,
1133 /* Check for success */
1134 if (!NT_SUCCESS(Status
))
1137 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1142 /* Then this is a beta */
1143 Status
= RtlStringCbCopyExA(Buffer
,
1145 VER_PRODUCTBETA_STR
,
1149 if (!NT_SUCCESS(Status
))
1152 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1156 CmCSDVersionString
.MaximumLength
= sizeof(Buffer
) - (USHORT
)Remaining
;
1159 /* Check if we have an RC number */
1160 if (CmNtCSDVersion
& 0xFFFF0000)
1162 /* Check if we have no version data yet */
1166 Remaining
= sizeof(Buffer
);
1171 /* Add comma and space */
1172 Status
= RtlStringCbCatExA(Buffer
,
1178 if (!NT_SUCCESS(Status
))
1181 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1185 /* Add the version format string */
1186 Status
= RtlStringCbPrintfA(RcEnd
,
1189 (CmNtCSDVersion
& 0xFFFF0000) >> 16);
1190 if (!NT_SUCCESS(Status
))
1193 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1197 /* Now setup the final string */
1198 RtlInitAnsiString(&CsdString
, Buffer
);
1199 Status
= RtlAnsiStringToUnicodeString(&CmCSDVersionString
,
1202 if (!NT_SUCCESS(Status
))
1205 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1208 /* Add our version */
1209 Status
= RtlStringCbPrintfA(VersionBuffer
,
1210 sizeof(VersionBuffer
),
1212 VER_PRODUCTMAJORVERSION
,
1213 VER_PRODUCTMINORVERSION
);
1214 if (!NT_SUCCESS(Status
))
1217 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1220 /* Build the final version string */
1221 RtlCreateUnicodeStringFromAsciiz(&CmVersionString
, VersionBuffer
);
1223 /* Check if the user wants a kernel stack trace database */
1224 if (NtGlobalFlag
& FLG_KERNEL_STACK_TRACE_DB
)
1227 DPRINT1("Kernel-mode stack trace support not yet present."
1228 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
1231 /* Check if he wanted exception logging */
1232 if (NtGlobalFlag
& FLG_ENABLE_EXCEPTION_LOGGING
)
1235 DPRINT1("Kernel-mode exception logging support not yet present."
1236 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
1239 /* Initialize the Handle Table */
1240 ExpInitializeHandleTables();
1243 /* On checked builds, allocate the system call count table */
1244 KeServiceDescriptorTable
[0].Count
=
1245 ExAllocatePoolWithTag(NonPagedPool
,
1246 KiServiceLimit
* sizeof(ULONG
),
1249 /* Use it for the shadow table too */
1250 KeServiceDescriptorTableShadow
[0].Count
= KeServiceDescriptorTable
[0].Count
;
1252 /* Make sure allocation succeeded */
1253 if (KeServiceDescriptorTable
[0].Count
)
1255 /* Zero the call counts to 0 */
1256 RtlZeroMemory(KeServiceDescriptorTable
[0].Count
,
1257 KiServiceLimit
* sizeof(ULONG
));
1261 /* Create the Basic Object Manager Types to allow new Object Types */
1262 if (!ObInitSystem()) KeBugCheck(OBJECT_INITIALIZATION_FAILED
);
1264 /* Load basic Security for other Managers */
1265 if (!SeInitSystem()) KeBugCheck(SECURITY_INITIALIZATION_FAILED
);
1267 /* Initialize the Process Manager */
1268 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS_INITIALIZATION_FAILED
);
1270 /* Initialize the PnP Manager */
1271 if (!PpInitSystem()) KeBugCheck(PP0_INITIALIZATION_FAILED
);
1273 /* Initialize the User-Mode Debugging Subsystem */
1276 /* Calculate the tick count multiplier */
1277 ExpTickCountMultiplier
= ExComputeTickCountMultiplier(KeMaximumIncrement
);
1278 SharedUserData
->TickCountMultiplier
= ExpTickCountMultiplier
;
1280 /* Set the OS Version */
1281 SharedUserData
->NtMajorVersion
= NtMajorVersion
;
1282 SharedUserData
->NtMinorVersion
= NtMinorVersion
;
1284 /* Set the machine type */
1285 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_NATIVE
;
1286 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_NATIVE
;
1291 MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
1296 Phase1InitializationDiscard(IN PVOID Context
)
1298 PLOADER_PARAMETER_BLOCK LoaderBlock
= Context
;
1299 NTSTATUS Status
, MsgStatus
;
1300 TIME_FIELDS TimeFields
;
1301 LARGE_INTEGER SystemBootTime
, UniversalBootTime
, OldTime
, Timeout
;
1302 BOOLEAN SosEnabled
, NoGuiBoot
, ResetBias
= FALSE
, AlternateShell
= FALSE
;
1303 PLDR_DATA_TABLE_ENTRY NtosEntry
;
1304 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
1305 PCHAR CommandLine
, Y2KHackRequired
, SafeBoot
, Environment
;
1306 PCHAR StringBuffer
, EndBuffer
, BeginBuffer
, MpString
= "";
1307 PINIT_BUFFER InitBuffer
;
1308 ANSI_STRING TempString
;
1309 ULONG LastTzBias
, Length
, YearHack
= 0, Disposition
, MessageCode
= 0;
1312 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
1313 KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo
;
1314 UNICODE_STRING KeyName
;
1315 OBJECT_ATTRIBUTES ObjectAttributes
;
1316 HANDLE KeyHandle
, OptionHandle
;
1317 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
1319 /* Allocate the initialization buffer */
1320 InitBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1321 sizeof(INIT_BUFFER
),
1326 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 8, 0, 0);
1329 /* Set to phase 1 */
1330 ExpInitializationPhase
= 1;
1332 /* Set us at maximum priority */
1333 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY
);
1335 /* Do Phase 1 HAL Initialization */
1336 if (!HalInitSystem(1, LoaderBlock
)) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1338 /* Get the command line and upcase it */
1339 CommandLine
= _strupr(LoaderBlock
->LoadOptions
);
1341 /* Check if GUI Boot is enabled */
1342 NoGuiBoot
= (strstr(CommandLine
, "NOGUIBOOT")) ? TRUE
: FALSE
;
1344 /* Get the SOS setting */
1345 SosEnabled
= strstr(CommandLine
, "SOS") ? TRUE
: FALSE
;
1347 /* Setup the boot driver */
1348 InbvEnableBootDriver(!NoGuiBoot
);
1349 InbvDriverInitialize(LoaderBlock
, 18);
1351 /* Check if GUI boot is enabled */
1354 /* It is, display the boot logo and enable printing strings */
1355 InbvEnableDisplayString(SosEnabled
);
1356 DisplayBootBitmap(SosEnabled
);
1360 /* Release display ownership if not using GUI boot */
1361 InbvNotifyDisplayOwnershipLost(NULL
);
1363 /* Don't allow boot-time strings */
1364 InbvEnableDisplayString(FALSE
);
1367 /* Check if this is LiveCD (WinPE) mode */
1368 if (strstr(CommandLine
, "MININT"))
1370 /* Setup WinPE Settings */
1371 InitIsWinPEMode
= TRUE
;
1372 InitWinPEModeType
|= (strstr(CommandLine
, "INRAM")) ? 0x80000000 : 1;
1375 /* Get the kernel's load entry */
1376 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1377 LDR_DATA_TABLE_ENTRY
,
1380 /* Find the banner message */
1381 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1387 /* Setup defaults and check if we have a version string */
1388 StringBuffer
= InitBuffer
->VersionBuffer
;
1389 BeginBuffer
= StringBuffer
;
1390 EndBuffer
= StringBuffer
;
1391 Remaining
= sizeof(InitBuffer
->VersionBuffer
);
1392 if (CmCSDVersionString
.Length
)
1394 /* Print the version string */
1395 Status
= RtlStringCbPrintfExA(StringBuffer
,
1401 &CmCSDVersionString
);
1402 if (!NT_SUCCESS(Status
))
1405 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1411 *EndBuffer
= ANSI_NULL
; /* Null-terminate the string */
1414 /* Skip over the null-terminator to start a new string */
1418 /* Build the version number */
1419 StringBuffer
= InitBuffer
->VersionNumber
;
1420 Status
= RtlStringCbPrintfA(StringBuffer
,
1421 sizeof(InitBuffer
->VersionNumber
),
1423 VER_PRODUCTMAJORVERSION
,
1424 VER_PRODUCTMINORVERSION
);
1425 if (!NT_SUCCESS(Status
))
1428 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1431 /* Check if we had found a banner message */
1432 if (NT_SUCCESS(MsgStatus
))
1434 /* Create the banner message */
1435 Status
= RtlStringCbPrintfA(EndBuffer
,
1437 (PCHAR
)MsgEntry
->Text
,
1439 NtBuildNumber
& 0xFFFF,
1441 if (!NT_SUCCESS(Status
))
1444 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1449 /* Use hard-coded banner message */
1450 Status
= RtlStringCbCopyA(EndBuffer
, Remaining
, "REACTOS (R)\n");
1451 if (!NT_SUCCESS(Status
))
1454 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1458 /* Display the version string on-screen */
1459 InbvDisplayString(EndBuffer
);
1461 /* Initialize Power Subsystem in Phase 0 */
1462 if (!PoInitSystem(0)) KeBugCheck(INTERNAL_POWER_ERROR
);
1464 /* Check for Y2K hack */
1465 Y2KHackRequired
= strstr(CommandLine
, "YEAR");
1466 if (Y2KHackRequired
) Y2KHackRequired
= strstr(Y2KHackRequired
, "=");
1467 if (Y2KHackRequired
) YearHack
= atol(Y2KHackRequired
+ 1);
1469 /* Query the clock */
1470 if ((ExCmosClockIsSane
) && (HalQueryRealTimeClock(&TimeFields
)))
1472 /* Check if we're using the Y2K hack */
1473 if (Y2KHackRequired
) TimeFields
.Year
= (CSHORT
)YearHack
;
1475 /* Convert to time fields */
1476 RtlTimeFieldsToTime(&TimeFields
, &SystemBootTime
);
1477 UniversalBootTime
= SystemBootTime
;
1479 /* Check if real time is GMT */
1480 if (!ExpRealTimeIsUniversal
)
1482 /* Check if we don't have a valid bias */
1483 if (ExpLastTimeZoneBias
== MAXULONG
)
1487 ExpLastTimeZoneBias
= ExpAltTimeZoneBias
;
1490 /* Calculate the bias in seconds */
1491 ExpTimeZoneBias
.QuadPart
= Int32x32To64(ExpLastTimeZoneBias
* 60,
1494 /* Set the boot time-zone bias */
1495 SharedUserData
->TimeZoneBias
.High2Time
= ExpTimeZoneBias
.HighPart
;
1496 SharedUserData
->TimeZoneBias
.LowPart
= ExpTimeZoneBias
.LowPart
;
1497 SharedUserData
->TimeZoneBias
.High1Time
= ExpTimeZoneBias
.HighPart
;
1499 /* Convert the boot time to local time, and set it */
1500 UniversalBootTime
.QuadPart
= SystemBootTime
.QuadPart
+
1501 ExpTimeZoneBias
.QuadPart
;
1504 /* Update the system time */
1505 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1507 /* Do system callback */
1508 PoNotifySystemTimeSet();
1510 /* Remember this as the boot time */
1511 KeBootTime
= UniversalBootTime
;
1515 /* Initialize all processors */
1516 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1519 /* HACK: We should use RtlFindMessage and not only fallback to this */
1520 MpString
= "MultiProcessor Kernel\r\n";
1523 /* Setup the "MP" String */
1524 RtlInitAnsiString(&TempString
, MpString
);
1526 /* Make sure to remove the \r\n if we actually have a string */
1527 while ((TempString
.Length
> 0) &&
1528 ((TempString
.Buffer
[TempString
.Length
- 1] == '\r') ||
1529 (TempString
.Buffer
[TempString
.Length
- 1] == '\n')))
1531 /* Skip the trailing character */
1532 TempString
.Length
--;
1535 /* Get the information string from our resource file */
1536 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1539 KeNumberProcessors
> 1 ?
1540 WINDOWS_NT_INFO_STRING_PLURAL
:
1541 WINDOWS_NT_INFO_STRING
,
1544 /* Get total RAM size */
1545 Size
= MmNumberOfPhysicalPages
* PAGE_SIZE
/ 1024 / 1024;
1547 /* Create the string */
1548 StringBuffer
= InitBuffer
->VersionBuffer
;
1549 Status
= RtlStringCbPrintfA(StringBuffer
,
1550 sizeof(InitBuffer
->VersionBuffer
),
1551 NT_SUCCESS(MsgStatus
) ?
1552 (PCHAR
)MsgEntry
->Text
:
1553 "%u System Processor [%u MB Memory] %Z\n",
1557 if (!NT_SUCCESS(Status
))
1560 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
1563 /* Display RAM and CPU count */
1564 InbvDisplayString(StringBuffer
);
1566 /* Update the progress bar */
1567 InbvUpdateProgressBar(5);
1569 /* Call OB initialization again */
1570 if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED
);
1572 /* Initialize Basic System Objects and Worker Threads */
1573 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 1, 0);
1575 /* Initialize the later stages of the kernel */
1576 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 2, 0);
1578 /* Call KD Providers at Phase 1 */
1579 if (!KdInitSystem(ExpInitializationPhase
, KeLoaderBlock
))
1581 /* Failed, bugcheck */
1582 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 3, 0);
1585 /* Initialize the SRM in Phase 1 */
1586 if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED
);
1588 /* Update the progress bar */
1589 InbvUpdateProgressBar(10);
1591 /* Create SystemRoot Link */
1592 Status
= ExpCreateSystemRootLink(LoaderBlock
);
1593 if (!NT_SUCCESS(Status
))
1595 /* Failed to create the system root link */
1596 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1599 /* Set up Region Maps, Sections and the Paging File */
1600 if (!MmInitSystem(1, LoaderBlock
)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED
);
1602 /* Create NLS section */
1603 ExpInitNls(LoaderBlock
);
1605 /* Initialize Cache Views */
1606 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED
);
1608 /* Initialize the Registry */
1609 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
1611 /* Initialize Prefetcher */
1612 CcPfInitializePrefetcher();
1614 /* Update progress bar */
1615 InbvUpdateProgressBar(15);
1617 /* Update timezone information */
1618 LastTzBias
= ExpLastTimeZoneBias
;
1619 ExRefreshTimeZoneInformation(&SystemBootTime
);
1621 /* Check if we're resetting timezone data */
1624 /* Convert the local time to system time */
1625 ExLocalTimeToSystemTime(&SystemBootTime
, &UniversalBootTime
);
1626 KeBootTime
= UniversalBootTime
;
1629 /* Set the new time */
1630 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1634 /* Check if the timezone switched and update the time */
1635 if (LastTzBias
!= ExpLastTimeZoneBias
) ZwSetSystemTime(NULL
, NULL
);
1638 /* Initialize the File System Runtime Library */
1639 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED
);
1641 /* Initialize range lists */
1642 RtlInitializeRangeListPackage();
1644 /* Report all resources used by HAL */
1645 HalReportResourceUsage();
1647 /* Call the debugger DLL */
1648 KdDebuggerInitialize1(LoaderBlock
);
1650 /* Setup PnP Manager in phase 1 */
1651 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED
);
1653 /* Update progress bar */
1654 InbvUpdateProgressBar(20);
1656 /* Initialize LPC */
1657 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED
);
1659 /* Make sure we have a command line */
1662 /* Check if this is a safe mode boot */
1663 SafeBoot
= strstr(CommandLine
, "SAFEBOOT:");
1666 /* Check what kind of boot this is */
1668 if (!strncmp(SafeBoot
, "MINIMAL", 7))
1671 InitSafeBootMode
= 1;
1673 MessageCode
= BOOTING_IN_SAFEMODE_MINIMAL
;
1675 else if (!strncmp(SafeBoot
, "NETWORK", 7))
1677 /* With Networking */
1678 InitSafeBootMode
= 2;
1680 MessageCode
= BOOTING_IN_SAFEMODE_NETWORK
;
1682 else if (!strncmp(SafeBoot
, "DSREPAIR", 8))
1684 /* Domain Server Repair */
1685 InitSafeBootMode
= 3;
1687 MessageCode
= BOOTING_IN_SAFEMODE_DSREPAIR
;
1693 InitSafeBootMode
= 0;
1696 /* Check if there's any settings left */
1699 /* Check if an alternate shell was requested */
1700 if (!strncmp(SafeBoot
, "(ALTERNATESHELL)", 16))
1702 /* Remember this for later */
1703 AlternateShell
= TRUE
;
1707 /* Find the message to print out */
1708 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1713 if (NT_SUCCESS(Status
))
1716 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1721 /* Make sure we have a command line */
1724 /* Check if bootlogging is enabled */
1725 if (strstr(CommandLine
, "BOOTLOG"))
1727 /* Find the message to print out */
1728 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1733 if (NT_SUCCESS(Status
))
1736 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1739 /* Setup boot logging */
1740 //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader);
1744 /* Setup the Executive in Phase 2 */
1745 //ExInitSystemPhase2();
1747 /* Update progress bar */
1748 InbvUpdateProgressBar(25);
1751 /* No KD Time Slip is pending */
1752 KdpTimeSlipPending
= 0;
1755 /* Initialize in-place execution support */
1756 XIPInit(LoaderBlock
);
1758 /* Set maximum update to 75% */
1759 InbvSetProgressBarSubset(25, 75);
1761 /* Initialize the I/O Subsystem */
1762 if (!IoInitSystem(LoaderBlock
)) KeBugCheck(IO1_INITIALIZATION_FAILED
);
1764 /* Set maximum update to 100% */
1765 InbvSetProgressBarSubset(0, 100);
1767 /* Are we in safe mode? */
1768 if (InitSafeBootMode
)
1770 /* Open the safe boot key */
1771 RtlInitUnicodeString(&KeyName
,
1772 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1773 L
"\\CONTROL\\SAFEBOOT");
1774 InitializeObjectAttributes(&ObjectAttributes
,
1776 OBJ_CASE_INSENSITIVE
,
1779 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1780 if (NT_SUCCESS(Status
))
1782 /* First check if we have an alternate shell */
1785 /* Make sure that the registry has one setup */
1786 RtlInitUnicodeString(&KeyName
, L
"AlternateShell");
1787 Status
= NtQueryValueKey(KeyHandle
,
1789 KeyValuePartialInformation
,
1791 sizeof(KeyPartialInfo
),
1793 if (!(NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_OVERFLOW
))
1795 AlternateShell
= FALSE
;
1799 /* Create the option key */
1800 RtlInitUnicodeString(&KeyName
, L
"Option");
1801 InitializeObjectAttributes(&ObjectAttributes
,
1803 OBJ_CASE_INSENSITIVE
,
1806 Status
= ZwCreateKey(&OptionHandle
,
1811 REG_OPTION_VOLATILE
,
1815 /* Check if the key create worked */
1816 if (NT_SUCCESS(Status
))
1818 /* Write the safe boot type */
1819 RtlInitUnicodeString(&KeyName
, L
"OptionValue");
1820 NtSetValueKey(OptionHandle
,
1825 sizeof(InitSafeBootMode
));
1827 /* Check if we have to use an alternate shell */
1830 /* Remember this for later */
1832 RtlInitUnicodeString(&KeyName
, L
"UseAlternateShell");
1833 NtSetValueKey(OptionHandle
,
1838 sizeof(Disposition
));
1841 /* Close the options key handle */
1842 NtClose(OptionHandle
);
1847 /* Are we in Win PE mode? */
1848 if (InitIsWinPEMode
)
1850 /* Open the safe control key */
1851 RtlInitUnicodeString(&KeyName
,
1852 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1854 InitializeObjectAttributes(&ObjectAttributes
,
1856 OBJ_CASE_INSENSITIVE
,
1859 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1860 if (!NT_SUCCESS(Status
))
1863 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1866 /* Create the MiniNT key */
1867 RtlInitUnicodeString(&KeyName
, L
"MiniNT");
1868 InitializeObjectAttributes(&ObjectAttributes
,
1870 OBJ_CASE_INSENSITIVE
,
1873 Status
= ZwCreateKey(&OptionHandle
,
1878 REG_OPTION_VOLATILE
,
1880 if (!NT_SUCCESS(Status
))
1883 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1886 /* Close the handles */
1888 NtClose(OptionHandle
);
1891 /* FIXME: This doesn't do anything for now */
1892 MmArmInitSystem(2, LoaderBlock
);
1894 /* Update progress bar */
1895 InbvUpdateProgressBar(80);
1897 /* Initialize VDM support */
1898 #if defined(_M_IX86)
1899 KeI386VdmInitialize();
1902 /* Initialize Power Subsystem in Phase 1*/
1903 if (!PoInitSystem(1)) KeBugCheck(INTERNAL_POWER_ERROR
);
1905 /* Update progress bar */
1906 InbvUpdateProgressBar(90);
1908 /* Initialize the Process Manager at Phase 1 */
1909 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1911 /* Make sure nobody touches the loader block again */
1912 if (LoaderBlock
== KeLoaderBlock
) KeLoaderBlock
= NULL
;
1913 MmFreeLoaderBlock(LoaderBlock
);
1914 LoaderBlock
= Context
= NULL
;
1916 /* Update progress bar */
1917 InbvUpdateProgressBar(100);
1919 /* Allow strings to be displayed */
1920 InbvEnableDisplayString(TRUE
);
1922 /* Launch initial process */
1923 DPRINT1("Free non-cache pages: %lx\n", MmAvailablePages
+ MiMemoryConsumers
[MC_CACHE
].PagesUsed
);
1924 ProcessInfo
= &InitBuffer
->ProcessInfo
;
1925 ExpLoadInitialProcess(InitBuffer
, &ProcessParameters
, &Environment
);
1927 /* Wait 5 seconds for initial process to initialize */
1928 Timeout
.QuadPart
= Int32x32To64(5, -10000000);
1929 Status
= ZwWaitForSingleObject(ProcessInfo
->ProcessHandle
, FALSE
, &Timeout
);
1930 if (Status
== STATUS_SUCCESS
)
1932 /* Failed, display error */
1933 DPRINT1("INIT: Session Manager terminated.\n");
1935 /* Bugcheck the system if SMSS couldn't initialize */
1936 KeBugCheck(SESSION5_INITIALIZATION_FAILED
);
1939 /* Close process handles */
1940 ZwClose(ProcessInfo
->ThreadHandle
);
1941 ZwClose(ProcessInfo
->ProcessHandle
);
1943 /* Free the initial process environment */
1945 ZwFreeVirtualMemory(NtCurrentProcess(),
1946 (PVOID
*)&Environment
,
1950 /* Free the initial process parameters */
1952 ZwFreeVirtualMemory(NtCurrentProcess(),
1953 (PVOID
*)&ProcessParameters
,
1957 /* Clean the screen */
1958 if (InbvBootDriverInstalled
) FinalizeBootLogo();
1960 /* Increase init phase */
1961 ExpInitializationPhase
++;
1963 /* Free the boot buffer */
1964 ExFreePoolWithTag(InitBuffer
, TAG_INIT
);
1965 DPRINT1("Free non-cache pages: %lx\n", MmAvailablePages
+ MiMemoryConsumers
[MC_CACHE
].PagesUsed
);
1970 Phase1Initialization(IN PVOID Context
)
1972 /* Do the .INIT part of Phase 1 which we can free later */
1973 Phase1InitializationDiscard(Context
);
1975 /* Jump into zero page thread */