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 ******************************************************************/
21 IN PLOADER_PARAMETER_BLOCK LoaderBlock
24 typedef struct _INIT_BUFFER
26 WCHAR DebugBuffer
[256];
27 CHAR VersionBuffer
[256];
28 CHAR BootlogHeader
[256];
29 CHAR VersionNumber
[24];
30 RTL_USER_PROCESS_INFORMATION ProcessInfo
;
31 WCHAR RegistryBuffer
[256];
32 } INIT_BUFFER
, *PINIT_BUFFER
;
34 /* DATA **********************************************************************/
37 ULONG NtMajorVersion
= VER_PRODUCTMAJORVERSION
;
38 ULONG NtMinorVersion
= VER_PRODUCTMINORVERSION
;
40 ULONG NtBuildNumber
= VER_PRODUCTBUILD
| 0xC0000000;
42 ULONG NtBuildNumber
= VER_PRODUCTBUILD
;
46 ULONG NtGlobalFlag
= 0;
50 ULONG CmNtSpBuildNumber
;
52 ULONG CmNtCSDReleaseType
;
53 UNICODE_STRING CmVersionString
;
54 UNICODE_STRING CmCSDVersionString
;
55 CHAR NtBuildLab
[] = KERNEL_VERSION_BUILD_STR
;
57 /* Init flags and settings */
58 ULONG ExpInitializationPhase
;
59 BOOLEAN ExpInTextModeSetup
;
60 BOOLEAN IoRemoteBootClient
;
61 ULONG InitSafeBootMode
;
62 BOOLEAN InitIsWinPEMode
, InitWinPEModeType
;
65 UNICODE_STRING NtSystemRoot
;
67 /* NT Initial User Application */
68 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
69 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
71 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
73 /* Boot NLS information */
74 PVOID ExpNlsTableBase
;
75 ULONG ExpAnsiCodePageDataOffset
, ExpOemCodePageDataOffset
;
76 ULONG ExpUnicodeCaseTableDataOffset
;
77 NLSTABLEINFO ExpNlsTableInfo
;
78 SIZE_T ExpNlsTableSize
;
79 PVOID ExpNlsSectionPointer
;
81 /* CMOS Timer Sanity */
82 BOOLEAN ExCmosClockIsSane
= TRUE
;
83 BOOLEAN ExpRealTimeIsUniversal
;
85 /* FUNCTIONS ****************************************************************/
90 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
92 UNICODE_STRING LinkName
;
93 OBJECT_ATTRIBUTES ObjectAttributes
;
98 ANSI_STRING TargetString
;
99 UNICODE_STRING TargetName
;
101 /* Initialize the ArcName tree */
102 RtlInitUnicodeString(&LinkName
, L
"\\ArcName");
103 InitializeObjectAttributes(&ObjectAttributes
,
105 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
107 SePublicDefaultUnrestrictedSd
);
110 Status
= NtCreateDirectoryObject(&LinkHandle
,
111 DIRECTORY_ALL_ACCESS
,
113 if (!NT_SUCCESS(Status
))
116 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
119 /* Close the LinkHandle */
122 /* Initialize the Device tree */
123 RtlInitUnicodeString(&LinkName
, L
"\\Device");
124 InitializeObjectAttributes(&ObjectAttributes
,
126 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
128 SePublicDefaultUnrestrictedSd
);
131 Status
= NtCreateDirectoryObject(&LinkHandle
,
132 DIRECTORY_ALL_ACCESS
,
134 if (!NT_SUCCESS(Status
))
137 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
140 /* Close the LinkHandle */
141 ObCloseHandle(LinkHandle
, KernelMode
);
143 /* Create the system root symlink name */
144 RtlInitAnsiString(&AnsiName
, "\\SystemRoot");
145 Status
= RtlAnsiStringToUnicodeString(&LinkName
, &AnsiName
, TRUE
);
146 if (!NT_SUCCESS(Status
))
149 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
152 /* Initialize the attributes for the link */
153 InitializeObjectAttributes(&ObjectAttributes
,
155 OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
157 SePublicDefaultUnrestrictedSd
);
159 /* Build the ARC name */
162 LoaderBlock
->ArcBootDeviceName
,
163 LoaderBlock
->NtBootPathName
);
164 Buffer
[strlen(Buffer
) - 1] = ANSI_NULL
;
166 /* Convert it to Unicode */
167 RtlInitString(&TargetString
, Buffer
);
168 Status
= RtlAnsiStringToUnicodeString(&TargetName
,
171 if (!NT_SUCCESS(Status
))
173 /* We failed, bugcheck */
174 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
178 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
179 SYMBOLIC_LINK_ALL_ACCESS
,
183 /* Free the strings */
184 RtlFreeUnicodeString(&LinkName
);
185 RtlFreeUnicodeString(&TargetName
);
187 /* Check if creating the link failed */
188 if (!NT_SUCCESS(Status
))
191 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
194 /* Close the handle and return success */
195 ObCloseHandle(LinkHandle
, KernelMode
);
196 return STATUS_SUCCESS
;
202 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
204 LARGE_INTEGER SectionSize
;
207 PVOID SectionBase
= NULL
;
209 LARGE_INTEGER SectionOffset
= {{0, 0}};
210 PLIST_ENTRY ListHead
, NextEntry
;
211 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
212 ULONG NlsTablesEncountered
= 0;
213 ULONG NlsTableSizes
[3]; /* 3 NLS tables */
215 /* Check if this is boot-time phase 0 initialization */
216 if (!ExpInitializationPhase
)
218 /* Loop the memory descriptors */
219 ListHead
= &LoaderBlock
->MemoryDescriptorListHead
;
220 NextEntry
= ListHead
->Flink
;
221 while (NextEntry
!= ListHead
)
223 /* Get the current block */
224 MdBlock
= CONTAINING_RECORD(NextEntry
,
225 MEMORY_ALLOCATION_DESCRIPTOR
,
228 /* Check if this is an NLS block */
229 if (MdBlock
->MemoryType
== LoaderNlsData
)
231 /* Increase the table size */
232 ExpNlsTableSize
+= MdBlock
->PageCount
* PAGE_SIZE
;
234 /* FreeLdr-specific */
235 NlsTableSizes
[NlsTablesEncountered
] = MdBlock
->PageCount
* PAGE_SIZE
;
236 NlsTablesEncountered
++;
237 ASSERT(NlsTablesEncountered
< 4);
240 /* Go to the next block */
241 NextEntry
= MdBlock
->ListEntry
.Flink
;
244 /* Allocate the a new buffer since loader memory will be freed */
245 ExpNlsTableBase
= ExAllocatePoolWithTag(NonPagedPool
,
248 if (!ExpNlsTableBase
) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
250 /* Copy the codepage data in its new location. */
251 if (NlsTablesEncountered
== 1)
253 /* Ntldr-way boot process */
254 RtlCopyMemory(ExpNlsTableBase
,
255 LoaderBlock
->NlsData
->AnsiCodePageData
,
261 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
262 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
264 RtlCopyMemory(ExpNlsTableBase
,
265 LoaderBlock
->NlsData
->AnsiCodePageData
,
268 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0]),
269 LoaderBlock
->NlsData
->OemCodePageData
,
272 RtlCopyMemory((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+ NlsTableSizes
[0] +
274 LoaderBlock
->NlsData
->UnicodeCodePageData
,
279 /* Initialize and reset the NLS TAbles */
280 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
281 ExpAnsiCodePageDataOffset
),
282 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
283 ExpOemCodePageDataOffset
),
284 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
285 ExpUnicodeCaseTableDataOffset
),
287 RtlResetRtlTranslations(&ExpNlsTableInfo
);
291 /* Set the section size */
292 SectionSize
.QuadPart
= ExpNlsTableSize
;
294 /* Create the NLS Section */
295 Status
= ZwCreateSection(&NlsSection
,
302 if (!NT_SUCCESS(Status
))
305 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
308 /* Get a pointer to the section */
309 Status
= ObReferenceObjectByHandle(NlsSection
,
313 &ExpNlsSectionPointer
,
315 ObCloseHandle(NlsSection
, KernelMode
);
316 if (!NT_SUCCESS(Status
))
319 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
322 /* Map the NLS Section in system space */
323 Status
= MmMapViewInSystemSpace(ExpNlsSectionPointer
,
326 if (!NT_SUCCESS(Status
))
329 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
332 /* Copy the codepage data in its new location. */
333 ASSERT(SectionBase
> MmSystemRangeStart
);
334 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
336 /* Free the previously allocated buffer and set the new location */
337 ExFreePoolWithTag(ExpNlsTableBase
, TAG_RTLI
);
338 ExpNlsTableBase
= SectionBase
;
340 /* Initialize the NLS Tables */
341 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
342 ExpAnsiCodePageDataOffset
),
343 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
344 ExpOemCodePageDataOffset
),
345 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
346 ExpUnicodeCaseTableDataOffset
),
348 RtlResetRtlTranslations(&ExpNlsTableInfo
);
350 /* Reset the base to 0 */
353 /* Map the section in the system process */
354 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
355 PsGetCurrentProcess(),
364 if (!NT_SUCCESS(Status
))
367 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
370 /* Copy the table into the system process and set this as the base */
371 RtlCopyMemory(SectionBase
, ExpNlsTableBase
, ExpNlsTableSize
);
372 ExpNlsTableBase
= SectionBase
;
378 ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer
,
379 OUT PRTL_USER_PROCESS_PARAMETERS
*ProcessParameters
,
380 OUT PCHAR
*ProcessEnvironment
)
385 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
386 UNICODE_STRING SmssName
, Environment
, SystemDriveString
, DebugString
;
387 PVOID EnvironmentPtr
= NULL
;
388 PRTL_USER_PROCESS_INFORMATION ProcessInformation
;
389 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= NULL
;
391 NullString
.Length
= sizeof(WCHAR
);
393 /* Use the initial buffer, after the strings */
394 ProcessInformation
= &InitBuffer
->ProcessInfo
;
396 /* Allocate memory for the process parameters */
397 Size
= sizeof(*ProcessParams
) + ((MAX_PATH
* 6) * sizeof(WCHAR
));
398 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
399 (PVOID
*)&ProcessParams
,
404 if (!NT_SUCCESS(Status
))
406 /* Failed, display error */
407 p
= InitBuffer
->DebugBuffer
;
410 L
"INIT: Unable to allocate Process Parameters. 0x%lx",
412 RtlInitUnicodeString(&DebugString
, p
);
413 ZwDisplayString(&DebugString
);
415 /* Bugcheck the system */
416 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
419 /* Setup the basic header, and give the process the low 1MB to itself */
420 ProcessParams
->Length
= Size
;
421 ProcessParams
->MaximumLength
= Size
;
422 ProcessParams
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
423 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
425 /* Allocate a page for the environment */
427 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
433 if (!NT_SUCCESS(Status
))
435 /* Failed, display error */
436 p
= InitBuffer
->DebugBuffer
;
439 L
"INIT: Unable to allocate Process Environment. 0x%lx",
441 RtlInitUnicodeString(&DebugString
, p
);
442 ZwDisplayString(&DebugString
);
444 /* Bugcheck the system */
445 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
448 /* Write the pointer */
449 ProcessParams
->Environment
= EnvironmentPtr
;
451 /* Make a buffer for the DOS path */
452 p
= (PWSTR
)(ProcessParams
+ 1);
453 ProcessParams
->CurrentDirectory
.DosPath
.Buffer
= p
;
454 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
= MAX_PATH
*
457 /* Copy the DOS path */
458 RtlCopyUnicodeString(&ProcessParams
->CurrentDirectory
.DosPath
,
461 /* Make a buffer for the DLL Path */
462 p
= (PWSTR
)((PCHAR
)ProcessParams
->CurrentDirectory
.DosPath
.Buffer
+
463 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
);
464 ProcessParams
->DllPath
.Buffer
= p
;
465 ProcessParams
->DllPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
467 /* Copy the DLL path and append the system32 directory */
468 RtlCopyUnicodeString(&ProcessParams
->DllPath
,
469 &ProcessParams
->CurrentDirectory
.DosPath
);
470 RtlAppendUnicodeToString(&ProcessParams
->DllPath
, L
"\\System32");
472 /* Make a buffer for the image name */
473 p
= (PWSTR
)((PCHAR
)ProcessParams
->DllPath
.Buffer
+
474 ProcessParams
->DllPath
.MaximumLength
);
475 ProcessParams
->ImagePathName
.Buffer
= p
;
476 ProcessParams
->ImagePathName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
478 /* Make sure the buffer is a valid string which within the given length */
479 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
480 ((NtInitialUserProcessBufferLength
!= MAXULONG
) &&
481 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
482 (NtInitialUserProcessBufferLength
>
483 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
485 /* Invalid initial process string, bugcheck */
486 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED
,
487 STATUS_INVALID_PARAMETER
,
488 NtInitialUserProcessBufferType
,
489 NtInitialUserProcessBufferLength
,
490 sizeof(NtInitialUserProcessBuffer
));
493 /* Cut out anything after a space */
494 p
= NtInitialUserProcessBuffer
;
495 while ((*p
) && (*p
!= L
' ')) p
++;
497 /* Set the image path length */
498 ProcessParams
->ImagePathName
.Length
=
499 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
501 /* Copy the actual buffer */
502 RtlCopyMemory(ProcessParams
->ImagePathName
.Buffer
,
503 NtInitialUserProcessBuffer
,
504 ProcessParams
->ImagePathName
.Length
);
506 /* Null-terminate it */
507 ProcessParams
->ImagePathName
.Buffer
[ProcessParams
->ImagePathName
.Length
/
508 sizeof(WCHAR
)] = UNICODE_NULL
;
510 /* Make a buffer for the command line */
511 p
= (PWSTR
)((PCHAR
)ProcessParams
->ImagePathName
.Buffer
+
512 ProcessParams
->ImagePathName
.MaximumLength
);
513 ProcessParams
->CommandLine
.Buffer
= p
;
514 ProcessParams
->CommandLine
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
516 /* Add the image name to the command line */
517 RtlAppendUnicodeToString(&ProcessParams
->CommandLine
,
518 NtInitialUserProcessBuffer
);
520 /* Create the environment string */
521 RtlInitEmptyUnicodeString(&Environment
,
522 ProcessParams
->Environment
,
525 /* Append the DLL path to it */
526 RtlAppendUnicodeToString(&Environment
, L
"Path=" );
527 RtlAppendUnicodeStringToString(&Environment
, &ProcessParams
->DllPath
);
528 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
530 /* Create the system drive string */
531 SystemDriveString
= NtSystemRoot
;
532 SystemDriveString
.Length
= 2 * sizeof(WCHAR
);
534 /* Append it to the environment */
535 RtlAppendUnicodeToString(&Environment
, L
"SystemDrive=");
536 RtlAppendUnicodeStringToString(&Environment
, &SystemDriveString
);
537 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
539 /* Append the system root to the environment */
540 RtlAppendUnicodeToString(&Environment
, L
"SystemRoot=");
541 RtlAppendUnicodeStringToString(&Environment
, &NtSystemRoot
);
542 RtlAppendUnicodeStringToString(&Environment
, &NullString
);
544 /* Prepare the prefetcher */
545 //CcPfBeginBootPhase(150);
547 /* Create SMSS process */
548 SmssName
= ProcessParams
->ImagePathName
;
549 Status
= RtlCreateUserProcess(&SmssName
,
550 OBJ_CASE_INSENSITIVE
,
551 RtlDeNormalizeProcessParams(ProcessParams
),
559 if (!NT_SUCCESS(Status
))
561 /* Failed, display error */
562 p
= InitBuffer
->DebugBuffer
;
565 L
"INIT: Unable to create Session Manager. 0x%lx",
567 RtlInitUnicodeString(&DebugString
, p
);
568 ZwDisplayString(&DebugString
);
570 /* Bugcheck the system */
571 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
574 /* Resume the thread */
575 Status
= ZwResumeThread(ProcessInformation
->ThreadHandle
, NULL
);
576 if (!NT_SUCCESS(Status
))
578 /* Failed, display error */
579 p
= InitBuffer
->DebugBuffer
;
582 L
"INIT: Unable to resume Session Manager. 0x%lx",
584 RtlInitUnicodeString(&DebugString
, p
);
585 ZwDisplayString(&DebugString
);
587 /* Bugcheck the system */
588 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
592 *ProcessParameters
= ProcessParams
;
593 *ProcessEnvironment
= EnvironmentPtr
;
599 ExComputeTickCountMultiplier(IN ULONG ClockIncrement
)
601 ULONG MsRemainder
= 0, MsIncrement
;
602 ULONG IncrementRemainder
;
605 /* Count the number of milliseconds for each clock interrupt */
606 MsIncrement
= ClockIncrement
/ (10 * 1000);
608 /* Count the remainder from the division above, with 24-bit precision */
609 IncrementRemainder
= ClockIncrement
- (MsIncrement
* (10 * 1000));
610 for (i
= 0; i
< 24; i
++)
612 /* Shift the remainders */
614 IncrementRemainder
<<= 1;
616 /* Check if we've went past 1 ms */
617 if (IncrementRemainder
>= (10 * 1000))
619 /* Increase the remainder by one, and substract from increment */
620 IncrementRemainder
-= (10 * 1000);
625 /* Return the increment */
626 return (MsIncrement
<< 24) | MsRemainder
;
632 ExpInitSystemPhase0(VOID
)
634 /* Initialize EXRESOURCE Support */
635 ExpResourceInitialization();
637 /* Initialize the environment lock */
638 ExInitializeFastMutex(&ExpEnvironmentLock
);
640 /* Initialize the lookaside lists and locks */
641 ExpInitLookasideLists();
643 /* Initialize the Firmware Table resource and listhead */
644 InitializeListHead(&ExpFirmwareTableProviderListHead
);
645 ExInitializeResourceLite(&ExpFirmwareTableResource
);
647 /* Set the suite mask to maximum and return */
648 ExSuiteMask
= 0xFFFFFFFF;
655 ExpInitSystemPhase1(VOID
)
657 /* Initialize worker threads */
658 ExpInitializeWorkerThreads();
660 /* Initialize pushlocks */
661 ExpInitializePushLocks();
663 /* Initialize events and event pairs */
664 ExpInitializeEventImplementation();
665 ExpInitializeEventPairImplementation();
667 /* Initialize callbacks */
668 ExpInitializeCallbacks();
670 /* Initialize mutants */
671 ExpInitializeMutantImplementation();
673 /* Initialize semaphores */
674 ExpInitializeSemaphoreImplementation();
676 /* Initialize timers */
677 ExpInitializeTimerImplementation();
679 /* Initialize profiling */
680 ExpInitializeProfileImplementation();
682 /* Initialize UUIDs */
685 /* Initialize Win32K */
695 /* Check the initialization phase */
696 switch (ExpInitializationPhase
)
701 return ExpInitSystemPhase0();
706 return ExpInitSystemPhase1();
710 /* Don't know any other phase! Bugcheck! */
711 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
719 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
721 PLOADER_PARAMETER_EXTENSION Extension
;
723 /* Get the loader extension */
724 Extension
= LoaderBlock
->Extension
;
726 /* Validate the size (larger structures are OK, we'll just ignore them) */
727 if (Extension
->Size
< sizeof(LOADER_PARAMETER_EXTENSION
)) return FALSE
;
729 /* Don't validate upper versions */
730 if (Extension
->MajorVersion
> VER_PRODUCTMAJORVERSION
) return TRUE
;
732 /* Fail if this is NT 4 */
733 if (Extension
->MajorVersion
< VER_PRODUCTMAJORVERSION
) return FALSE
;
735 /* Fail if this is XP */
736 if (Extension
->MinorVersion
< VER_PRODUCTMINORVERSION
) return FALSE
;
738 /* This is 2003 or newer, approve it */
745 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
748 PLIST_ENTRY NextEntry
;
751 PLDR_DATA_TABLE_ENTRY LdrEntry
;
752 BOOLEAN OverFlow
= FALSE
;
753 CHAR NameBuffer
[256];
756 /* Loop the driver list */
757 NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
758 while (NextEntry
!= &LoaderBlock
->LoadOrderListHead
)
760 /* Skip the first two images */
764 LdrEntry
= CONTAINING_RECORD(NextEntry
,
765 LDR_DATA_TABLE_ENTRY
,
767 if (LdrEntry
->FullDllName
.Buffer
[0] == L
'\\')
769 /* We have a name, read its data */
770 Name
= LdrEntry
->FullDllName
.Buffer
;
771 Length
= LdrEntry
->FullDllName
.Length
/ sizeof(WCHAR
);
773 /* Check if our buffer can hold it */
774 if (sizeof(NameBuffer
) < Length
+ sizeof(ANSI_NULL
))
785 /* Copy the character */
786 NameBuffer
[Count
++] = (CHAR
)*Name
++;
787 } while (Count
< Length
);
790 NameBuffer
[Count
] = ANSI_NULL
;
795 /* This should be a driver, check if it fits */
796 if (sizeof(NameBuffer
) <
797 (sizeof("\\System32\\Drivers\\") +
798 NtSystemRoot
.Length
/ sizeof(WCHAR
) - sizeof(UNICODE_NULL
) +
799 LdrEntry
->BaseDllName
.Length
/ sizeof(WCHAR
) +
802 /* Buffer too small */
808 /* Otherwise build the name. HACKED for GCC :( */
810 "%S\\System32\\Drivers\\%S",
811 &SharedUserData
->NtSystemRoot
[2],
812 LdrEntry
->BaseDllName
.Buffer
);
816 /* Check if the buffer was ok */
819 /* Initialize the STRING for the debugger */
820 RtlInitString(&SymbolString
, NameBuffer
);
822 /* Load the symbols */
823 DbgLoadImageSymbols(&SymbolString
,
825 (ULONG_PTR
)ZwCurrentProcess());
829 /* Go to the next entry */
831 NextEntry
= NextEntry
->Flink
;
838 ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
839 IN ULONG PagesToDestroy
,
840 IN TYPE_OF_MEMORY MemoryType
)
842 PLIST_ENTRY ListEntry
;
843 PMEMORY_ALLOCATION_DESCRIPTOR MemDescriptor
;
845 DPRINT1("Burn RAM amount: %d pages\n", PagesToDestroy
);
847 /* Loop the memory descriptors, beginning at the end */
848 for (ListEntry
= LoaderBlock
->MemoryDescriptorListHead
.Blink
;
849 ListEntry
!= &LoaderBlock
->MemoryDescriptorListHead
;
850 ListEntry
= ListEntry
->Blink
)
852 /* Get the memory descriptor structure */
853 MemDescriptor
= CONTAINING_RECORD(ListEntry
,
854 MEMORY_ALLOCATION_DESCRIPTOR
,
857 /* Is memory free there or is it temporary? */
858 if (MemDescriptor
->MemoryType
== LoaderFree
||
859 MemDescriptor
->MemoryType
== LoaderFirmwareTemporary
)
861 /* Check if the descriptor has more pages than we want */
862 if (MemDescriptor
->PageCount
> PagesToDestroy
)
864 /* Change block's page count, ntoskrnl doesn't care much */
865 MemDescriptor
->PageCount
-= PagesToDestroy
;
870 /* Change block type */
871 MemDescriptor
->MemoryType
= MemoryType
;
872 PagesToDestroy
-= MemDescriptor
->PageCount
;
874 /* Check if we are done */
875 if (PagesToDestroy
== 0) break;
884 ExpInitializeExecutive(IN ULONG Cpu
,
885 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
887 PNLS_DATA_BLOCK NlsData
;
889 ANSI_STRING AnsiPath
;
891 PCHAR CommandLine
, PerfMem
;
893 PLDR_DATA_TABLE_ENTRY NtosEntry
;
894 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
895 ANSI_STRING CsdString
;
896 size_t Remaining
= 0;
898 CHAR VersionBuffer
[65];
900 /* Validate Loader */
901 if (!ExpIsLoaderValid(LoaderBlock
))
903 /* Invalid loader version */
904 KeBugCheckEx(MISMATCHED_HAL
,
906 LoaderBlock
->Extension
->Size
,
907 LoaderBlock
->Extension
->MajorVersion
,
908 LoaderBlock
->Extension
->MinorVersion
);
911 /* Initialize PRCB pool lookaside pointers */
912 ExInitPoolLookasidePointers();
914 /* Check if this is an application CPU */
917 /* Then simply initialize it with HAL */
918 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
920 /* Initialization failed */
921 KeBugCheck(HAL_INITIALIZATION_FAILED
);
928 /* Assume no text-mode or remote boot */
929 ExpInTextModeSetup
= FALSE
;
930 IoRemoteBootClient
= FALSE
;
932 /* Check if we have a setup loader block */
933 if (LoaderBlock
->SetupLdrBlock
)
935 /* Check if this is text-mode setup */
936 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_TEXT_MODE
) ExpInTextModeSetup
= TRUE
;
938 /* Check if this is network boot */
939 if (LoaderBlock
->SetupLdrBlock
->Flags
& SETUPLDR_REMOTE_BOOT
)
942 IoRemoteBootClient
= TRUE
;
944 /* Make sure we're actually booting off the network */
945 ASSERT(!_memicmp(LoaderBlock
->ArcBootDeviceName
, "net(0)", 6));
950 ExpInitializationPhase
= 0;
952 /* Get boot command line */
953 CommandLine
= LoaderBlock
->LoadOptions
;
956 /* Upcase it for comparison and check if we're in performance mode */
957 _strupr(CommandLine
);
958 PerfMem
= strstr(CommandLine
, "PERFMEM");
961 /* Check if the user gave a number of bytes to use */
962 PerfMem
= strstr(PerfMem
, "=");
965 /* Read the number of pages we'll use */
966 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
970 DPRINT1("BBT performance mode not yet supported."
971 "/PERFMEM option ignored.\n");
976 /* Check if we're burning memory */
977 PerfMem
= strstr(CommandLine
, "BURNMEMORY");
980 /* Check if the user gave a number of bytes to use */
981 PerfMem
= strstr(PerfMem
, "=");
984 /* Read the number of pages we'll use */
985 PerfMemUsed
= atol(PerfMem
+ 1) * (1024 * 1024 / PAGE_SIZE
);
986 if (PerfMemUsed
) ExBurnMemory(LoaderBlock
, PerfMemUsed
, LoaderBad
);
991 /* Setup NLS Base and offsets */
992 NlsData
= LoaderBlock
->NlsData
;
993 ExpNlsTableBase
= NlsData
->AnsiCodePageData
;
994 ExpAnsiCodePageDataOffset
= 0;
995 ExpOemCodePageDataOffset
= ((ULONG_PTR
)NlsData
->OemCodePageData
-
996 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
997 ExpUnicodeCaseTableDataOffset
= ((ULONG_PTR
)NlsData
->UnicodeCodePageData
-
998 (ULONG_PTR
)NlsData
->AnsiCodePageData
);
1000 /* Initialize the NLS Tables */
1001 RtlInitNlsTables((PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1002 ExpAnsiCodePageDataOffset
),
1003 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1004 ExpOemCodePageDataOffset
),
1005 (PVOID
)((ULONG_PTR
)ExpNlsTableBase
+
1006 ExpUnicodeCaseTableDataOffset
),
1008 RtlResetRtlTranslations(&ExpNlsTableInfo
);
1010 /* Now initialize the HAL */
1011 if (!HalInitSystem(ExpInitializationPhase
, LoaderBlock
))
1013 /* HAL failed to initialize, bugcheck */
1014 KeBugCheck(HAL_INITIALIZATION_FAILED
);
1017 /* Make sure interrupts are active now */
1020 /* Clear the crypto exponent */
1021 SharedUserData
->CryptoExponent
= 0;
1023 /* Set global flags for the checked build */
1025 NtGlobalFlag
|= FLG_ENABLE_CLOSE_EXCEPTIONS
|
1026 FLG_ENABLE_KDEBUG_SYMBOL_LOAD
;
1029 /* Setup NT System Root Path */
1030 sprintf(Buffer
, "C:%s", LoaderBlock
->NtBootPathName
);
1032 /* Convert to ANSI_STRING and null-terminate it */
1033 RtlInitString(&AnsiPath
, Buffer
);
1034 Buffer
[--AnsiPath
.Length
] = ANSI_NULL
;
1036 /* Get the string from KUSER_SHARED_DATA's buffer */
1037 RtlInitEmptyUnicodeString(&NtSystemRoot
,
1038 SharedUserData
->NtSystemRoot
,
1039 sizeof(SharedUserData
->NtSystemRoot
));
1041 /* Now fill it in */
1042 Status
= RtlAnsiStringToUnicodeString(&NtSystemRoot
, &AnsiPath
, FALSE
);
1043 if (!NT_SUCCESS(Status
)) KeBugCheck(SESSION3_INITIALIZATION_FAILED
);
1045 /* Setup bugcheck messages */
1046 KiInitializeBugCheck();
1048 /* Setup initial system settings */
1049 CmGetSystemControlValues(LoaderBlock
->RegistryBase
, CmControlVector
);
1051 /* Load static defaults for Service Pack 1 and add our SVN revision */
1052 CmNtCSDVersion
= 0x100 | (KERNEL_VERSION_BUILD_HEX
<< 16);
1053 CmNtCSDReleaseType
= 0;
1055 /* Set Service Pack data for Service Pack 1 */
1056 CmNtSpBuildNumber
= 1830;
1057 if (!(CmNtCSDVersion
& 0xFFFF0000))
1059 /* Check the release type */
1060 if (CmNtCSDReleaseType
== 1) CmNtSpBuildNumber
|= 1830 << 16;
1063 /* Add loaded CmNtGlobalFlag value */
1064 NtGlobalFlag
|= CmNtGlobalFlag
;
1066 /* Initialize the executive at phase 0 */
1067 if (!ExInitSystem()) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1069 /* Initialize the memory manager at phase 0 */
1070 if (!MmArmInitSystem(0, LoaderBlock
)) KeBugCheck(PHASE0_INITIALIZATION_FAILED
);
1072 /* Load boot symbols */
1073 ExpLoadBootSymbols(LoaderBlock
);
1075 /* Check if we should break after symbol load */
1076 if (KdBreakAfterSymbolLoad
) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
1078 /* Check if this loader is compatible with NT 5.2 */
1079 if (LoaderBlock
->Extension
->Size
>= sizeof(LOADER_PARAMETER_EXTENSION
))
1081 /* Setup headless terminal settings */
1082 HeadlessInit(LoaderBlock
);
1085 /* Set system ranges */
1086 SharedUserData
->Reserved1
= (ULONG_PTR
)MmHighestUserAddress
;
1087 SharedUserData
->Reserved3
= (ULONG_PTR
)MmSystemRangeStart
;
1089 /* Make a copy of the NLS Tables */
1090 ExpInitNls(LoaderBlock
);
1092 /* Get the kernel's load entry */
1093 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1094 LDR_DATA_TABLE_ENTRY
,
1097 /* Check if this is a service pack */
1098 if (CmNtCSDVersion
& 0xFFFF)
1100 /* Get the service pack string */
1101 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1104 WINDOWS_NT_CSD_STRING
,
1106 if (NT_SUCCESS(Status
))
1108 /* Setup the string */
1109 RtlInitAnsiString(&CsdString
, (PCHAR
)MsgEntry
->Text
);
1111 /* Remove trailing newline */
1112 while ((CsdString
.Length
> 0) &&
1113 ((CsdString
.Buffer
[CsdString
.Length
- 1] == '\r') ||
1114 (CsdString
.Buffer
[CsdString
.Length
- 1] == '\n')))
1116 /* Skip the trailing character */
1120 /* Fill the buffer with version information */
1121 Status
= RtlStringCbPrintfA(Buffer
,
1125 (CmNtCSDVersion
& 0xFF00) >> 8,
1126 (CmNtCSDVersion
& 0xFF) ?
1127 'A' + (CmNtCSDVersion
& 0xFF) - 1 :
1132 /* Build default string */
1133 Status
= RtlStringCbPrintfA(Buffer
,
1139 /* Check for success */
1140 if (!NT_SUCCESS(Status
))
1143 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1148 /* Then this is a beta */
1149 Status
= RtlStringCbCopyExA(Buffer
,
1151 VER_PRODUCTBETA_STR
,
1155 if (!NT_SUCCESS(Status
))
1158 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1162 CmCSDVersionString
.MaximumLength
= sizeof(Buffer
) - (USHORT
)Remaining
;
1165 /* Check if we have an RC number */
1166 if (CmNtCSDVersion
& 0xFFFF0000)
1168 /* Check if we have no version data yet */
1172 Remaining
= sizeof(Buffer
);
1177 /* Add comma and space */
1178 Status
= RtlStringCbCatExA(Buffer
,
1184 if (!NT_SUCCESS(Status
))
1187 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1191 /* Add the version format string */
1192 Status
= RtlStringCbPrintfA(RcEnd
,
1195 (CmNtCSDVersion
& 0xFFFF0000) >> 16);
1196 if (!NT_SUCCESS(Status
))
1199 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1203 /* Now setup the final string */
1204 RtlInitAnsiString(&CsdString
, Buffer
);
1205 Status
= RtlAnsiStringToUnicodeString(&CmCSDVersionString
,
1208 if (!NT_SUCCESS(Status
))
1211 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1214 /* Add our version */
1215 Status
= RtlStringCbPrintfA(VersionBuffer
,
1216 sizeof(VersionBuffer
),
1218 VER_PRODUCTMAJORVERSION
,
1219 VER_PRODUCTMINORVERSION
);
1220 if (!NT_SUCCESS(Status
))
1223 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1226 /* Build the final version string */
1227 RtlCreateUnicodeStringFromAsciiz(&CmVersionString
, VersionBuffer
);
1229 /* Check if the user wants a kernel stack trace database */
1230 if (NtGlobalFlag
& FLG_KERNEL_STACK_TRACE_DB
)
1233 DPRINT1("Kernel-mode stack trace support not yet present."
1234 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
1237 /* Check if he wanted exception logging */
1238 if (NtGlobalFlag
& FLG_ENABLE_EXCEPTION_LOGGING
)
1241 DPRINT1("Kernel-mode exception logging support not yet present."
1242 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
1245 /* Initialize the Handle Table */
1246 ExpInitializeHandleTables();
1249 /* On checked builds, allocate the system call count table */
1250 KeServiceDescriptorTable
[0].Count
=
1251 ExAllocatePoolWithTag(NonPagedPool
,
1252 KiServiceLimit
* sizeof(ULONG
),
1255 /* Use it for the shadow table too */
1256 KeServiceDescriptorTableShadow
[0].Count
= KeServiceDescriptorTable
[0].Count
;
1258 /* Make sure allocation succeeded */
1259 if (KeServiceDescriptorTable
[0].Count
)
1261 /* Zero the call counts to 0 */
1262 RtlZeroMemory(KeServiceDescriptorTable
[0].Count
,
1263 KiServiceLimit
* sizeof(ULONG
));
1267 /* Create the Basic Object Manager Types to allow new Object Types */
1268 if (!ObInitSystem()) KeBugCheck(OBJECT_INITIALIZATION_FAILED
);
1270 /* Load basic Security for other Managers */
1271 if (!SeInitSystem()) KeBugCheck(SECURITY_INITIALIZATION_FAILED
);
1273 /* Initialize the Process Manager */
1274 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS_INITIALIZATION_FAILED
);
1276 /* Initialize the PnP Manager */
1277 if (!PpInitSystem()) KeBugCheck(PP0_INITIALIZATION_FAILED
);
1279 /* Initialize the User-Mode Debugging Subsystem */
1282 /* Calculate the tick count multiplier */
1283 ExpTickCountMultiplier
= ExComputeTickCountMultiplier(KeMaximumIncrement
);
1284 SharedUserData
->TickCountMultiplier
= ExpTickCountMultiplier
;
1286 /* Set the OS Version */
1287 SharedUserData
->NtMajorVersion
= NtMajorVersion
;
1288 SharedUserData
->NtMinorVersion
= NtMinorVersion
;
1290 /* Set the machine type */
1291 SharedUserData
->ImageNumberLow
= IMAGE_FILE_MACHINE_NATIVE
;
1292 SharedUserData
->ImageNumberHigh
= IMAGE_FILE_MACHINE_NATIVE
;
1298 Phase1InitializationDiscard(IN PVOID Context
)
1300 PLOADER_PARAMETER_BLOCK LoaderBlock
= Context
;
1301 NTSTATUS Status
, MsgStatus
;
1302 TIME_FIELDS TimeFields
;
1303 LARGE_INTEGER SystemBootTime
, UniversalBootTime
, OldTime
, Timeout
;
1304 BOOLEAN SosEnabled
, NoGuiBoot
, ResetBias
= FALSE
, AlternateShell
= FALSE
;
1305 PLDR_DATA_TABLE_ENTRY NtosEntry
;
1306 PMESSAGE_RESOURCE_ENTRY MsgEntry
;
1307 PCHAR CommandLine
, Y2KHackRequired
, SafeBoot
, Environment
;
1308 PCHAR StringBuffer
, EndBuffer
, BeginBuffer
, MpString
= "";
1309 PINIT_BUFFER InitBuffer
;
1310 ANSI_STRING TempString
;
1311 ULONG LastTzBias
, Length
, YearHack
= 0, Disposition
, MessageCode
= 0;
1314 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
1315 KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo
;
1316 UNICODE_STRING KeyName
, DebugString
;
1317 OBJECT_ATTRIBUTES ObjectAttributes
;
1318 HANDLE KeyHandle
, OptionHandle
;
1319 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
1321 /* Allocate the initialization buffer */
1322 InitBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1323 sizeof(INIT_BUFFER
),
1328 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 8, 0, 0);
1331 /* Set to phase 1 */
1332 ExpInitializationPhase
= 1;
1334 /* Set us at maximum priority */
1335 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY
);
1337 /* Do Phase 1 HAL Initialization */
1338 if (!HalInitSystem(1, LoaderBlock
)) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1340 /* Get the command line and upcase it */
1341 CommandLine
= _strupr(LoaderBlock
->LoadOptions
);
1343 /* Check if GUI Boot is enabled */
1344 NoGuiBoot
= (strstr(CommandLine
, "NOGUIBOOT")) ? TRUE
: FALSE
;
1346 /* Get the SOS setting */
1347 SosEnabled
= strstr(CommandLine
, "SOS") ? TRUE
: FALSE
;
1349 /* Setup the boot driver */
1350 InbvEnableBootDriver(!NoGuiBoot
);
1351 InbvDriverInitialize(LoaderBlock
, 18);
1353 /* Check if GUI boot is enabled */
1356 /* It is, display the boot logo and enable printing strings */
1357 InbvEnableDisplayString(SosEnabled
);
1358 DisplayBootBitmap(SosEnabled
);
1362 /* Release display ownership if not using GUI boot */
1363 InbvNotifyDisplayOwnershipLost(NULL
);
1365 /* Don't allow boot-time strings */
1366 InbvEnableDisplayString(FALSE
);
1369 /* Check if this is LiveCD (WinPE) mode */
1370 if (strstr(CommandLine
, "MININT"))
1372 /* Setup WinPE Settings */
1373 InitIsWinPEMode
= TRUE
;
1374 InitWinPEModeType
|= (strstr(CommandLine
, "INRAM")) ? 0x80000000 : 1;
1377 /* Get the kernel's load entry */
1378 NtosEntry
= CONTAINING_RECORD(LoaderBlock
->LoadOrderListHead
.Flink
,
1379 LDR_DATA_TABLE_ENTRY
,
1382 /* Find the banner message */
1383 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1389 /* Setup defaults and check if we have a version string */
1390 StringBuffer
= InitBuffer
->VersionBuffer
;
1391 BeginBuffer
= StringBuffer
;
1392 EndBuffer
= StringBuffer
;
1393 Remaining
= sizeof(InitBuffer
->VersionBuffer
);
1394 if (CmCSDVersionString
.Length
)
1396 /* Print the version string */
1397 Status
= RtlStringCbPrintfExA(StringBuffer
,
1403 &CmCSDVersionString
);
1404 if (!NT_SUCCESS(Status
))
1407 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1413 *EndBuffer
= ANSI_NULL
; /* Null-terminate the string */
1416 /* Skip over the null-terminator to start a new string */
1420 /* Build the version number */
1421 StringBuffer
= InitBuffer
->VersionNumber
;
1422 Status
= RtlStringCbPrintfA(StringBuffer
,
1423 sizeof(InitBuffer
->VersionNumber
),
1425 VER_PRODUCTMAJORVERSION
,
1426 VER_PRODUCTMINORVERSION
);
1427 if (!NT_SUCCESS(Status
))
1430 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1433 /* Check if we had found a banner message */
1434 if (NT_SUCCESS(MsgStatus
))
1436 /* Create the banner message */
1437 Status
= RtlStringCbPrintfA(EndBuffer
,
1439 (PCHAR
)MsgEntry
->Text
,
1441 NtBuildNumber
& 0xFFFF,
1443 if (!NT_SUCCESS(Status
))
1446 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1451 /* Use hard-coded banner message */
1452 Status
= RtlStringCbCopyA(EndBuffer
, Remaining
, "REACTOS (R)\n");
1453 if (!NT_SUCCESS(Status
))
1456 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
1460 /* Display the version string on-screen */
1461 InbvDisplayString(EndBuffer
);
1463 /* Initialize Power Subsystem in Phase 0 */
1464 if (!PoInitSystem(0)) KeBugCheck(INTERNAL_POWER_ERROR
);
1466 /* Check for Y2K hack */
1467 Y2KHackRequired
= strstr(CommandLine
, "YEAR");
1468 if (Y2KHackRequired
) Y2KHackRequired
= strstr(Y2KHackRequired
, "=");
1469 if (Y2KHackRequired
) YearHack
= atol(Y2KHackRequired
+ 1);
1471 /* Query the clock */
1472 if ((ExCmosClockIsSane
) && (HalQueryRealTimeClock(&TimeFields
)))
1474 /* Check if we're using the Y2K hack */
1475 if (Y2KHackRequired
) TimeFields
.Year
= (CSHORT
)YearHack
;
1477 /* Convert to time fields */
1478 RtlTimeFieldsToTime(&TimeFields
, &SystemBootTime
);
1479 UniversalBootTime
= SystemBootTime
;
1481 /* Check if real time is GMT */
1482 if (!ExpRealTimeIsUniversal
)
1484 /* Check if we don't have a valid bias */
1485 if (ExpLastTimeZoneBias
== MAXULONG
)
1489 ExpLastTimeZoneBias
= ExpAltTimeZoneBias
;
1492 /* Calculate the bias in seconds */
1493 ExpTimeZoneBias
.QuadPart
= Int32x32To64(ExpLastTimeZoneBias
* 60,
1496 /* Set the boot time-zone bias */
1497 SharedUserData
->TimeZoneBias
.High2Time
= ExpTimeZoneBias
.HighPart
;
1498 SharedUserData
->TimeZoneBias
.LowPart
= ExpTimeZoneBias
.LowPart
;
1499 SharedUserData
->TimeZoneBias
.High1Time
= ExpTimeZoneBias
.HighPart
;
1501 /* Convert the boot time to local time, and set it */
1502 UniversalBootTime
.QuadPart
= SystemBootTime
.QuadPart
+
1503 ExpTimeZoneBias
.QuadPart
;
1506 /* Update the system time */
1507 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1509 /* Do system callback */
1510 PoNotifySystemTimeSet();
1512 /* Remember this as the boot time */
1513 KeBootTime
= UniversalBootTime
;
1517 /* Initialize all processors */
1518 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED
);
1521 /* HACK: We should use RtlFindMessage and not only fallback to this */
1522 MpString
= "MultiProcessor Kernel\r\n";
1525 /* Setup the "MP" String */
1526 RtlInitAnsiString(&TempString
, MpString
);
1528 /* Make sure to remove the \r\n if we actually have a string */
1529 while ((TempString
.Length
> 0) &&
1530 ((TempString
.Buffer
[TempString
.Length
- 1] == '\r') ||
1531 (TempString
.Buffer
[TempString
.Length
- 1] == '\n')))
1533 /* Skip the trailing character */
1534 TempString
.Length
--;
1537 /* Get the information string from our resource file */
1538 MsgStatus
= RtlFindMessage(NtosEntry
->DllBase
,
1541 KeNumberProcessors
> 1 ?
1542 WINDOWS_NT_INFO_STRING_PLURAL
:
1543 WINDOWS_NT_INFO_STRING
,
1546 /* Get total RAM size */
1547 Size
= MmNumberOfPhysicalPages
* PAGE_SIZE
/ 1024 / 1024;
1549 /* Create the string */
1550 StringBuffer
= InitBuffer
->VersionBuffer
;
1551 Status
= RtlStringCbPrintfA(StringBuffer
,
1552 sizeof(InitBuffer
->VersionBuffer
),
1553 NT_SUCCESS(MsgStatus
) ?
1554 (PCHAR
)MsgEntry
->Text
:
1555 "%u System Processor [%u MB Memory] %Z\n",
1559 if (!NT_SUCCESS(Status
))
1562 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
1565 /* Display RAM and CPU count */
1566 InbvDisplayString(StringBuffer
);
1568 /* Update the progress bar */
1569 InbvUpdateProgressBar(5);
1571 /* Call OB initialization again */
1572 if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED
);
1574 /* Initialize Basic System Objects and Worker Threads */
1575 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 1, 0);
1577 /* Initialize the later stages of the kernel */
1578 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 2, 0);
1580 /* Call KD Providers at Phase 1 */
1581 if (!KdInitSystem(ExpInitializationPhase
, KeLoaderBlock
))
1583 /* Failed, bugcheck */
1584 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, 0, 0, 3, 0);
1587 /* Initialize the SRM in Phase 1 */
1588 if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED
);
1590 /* Update the progress bar */
1591 InbvUpdateProgressBar(10);
1593 /* Create SystemRoot Link */
1594 Status
= ExpCreateSystemRootLink(LoaderBlock
);
1595 if (!NT_SUCCESS(Status
))
1597 /* Failed to create the system root link */
1598 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1601 /* Set up Region Maps, Sections and the Paging File */
1602 if (!MmInitSystem(1, LoaderBlock
)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED
);
1604 /* Create NLS section */
1605 ExpInitNls(LoaderBlock
);
1607 /* Initialize Cache Views */
1608 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED
);
1610 /* Initialize the Registry */
1611 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
1613 /* Initialize Prefetcher */
1614 CcPfInitializePrefetcher();
1616 /* Update progress bar */
1617 InbvUpdateProgressBar(15);
1619 /* Update timezone information */
1620 LastTzBias
= ExpLastTimeZoneBias
;
1621 ExRefreshTimeZoneInformation(&SystemBootTime
);
1623 /* Check if we're resetting timezone data */
1626 /* Convert the local time to system time */
1627 ExLocalTimeToSystemTime(&SystemBootTime
, &UniversalBootTime
);
1628 KeBootTime
= UniversalBootTime
;
1631 /* Set the new time */
1632 KeSetSystemTime(&UniversalBootTime
, &OldTime
, FALSE
, NULL
);
1636 /* Check if the timezone switched and update the time */
1637 if (LastTzBias
!= ExpLastTimeZoneBias
) ZwSetSystemTime(NULL
, NULL
);
1640 /* Initialize the File System Runtime Library */
1641 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED
);
1643 /* Initialize range lists */
1644 RtlInitializeRangeListPackage();
1646 /* Report all resources used by HAL */
1647 HalReportResourceUsage();
1649 /* Call the debugger DLL */
1650 KdDebuggerInitialize1(LoaderBlock
);
1652 /* Setup PnP Manager in phase 1 */
1653 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED
);
1655 /* Update progress bar */
1656 InbvUpdateProgressBar(20);
1658 /* Initialize LPC */
1659 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED
);
1661 /* Make sure we have a command line */
1664 /* Check if this is a safe mode boot */
1665 SafeBoot
= strstr(CommandLine
, "SAFEBOOT:");
1668 /* Check what kind of boot this is */
1670 if (!strncmp(SafeBoot
, "MINIMAL", 7))
1673 InitSafeBootMode
= 1;
1675 MessageCode
= BOOTING_IN_SAFEMODE_MINIMAL
;
1677 else if (!strncmp(SafeBoot
, "NETWORK", 7))
1679 /* With Networking */
1680 InitSafeBootMode
= 2;
1682 MessageCode
= BOOTING_IN_SAFEMODE_NETWORK
;
1684 else if (!strncmp(SafeBoot
, "DSREPAIR", 8))
1686 /* Domain Server Repair */
1687 InitSafeBootMode
= 3;
1689 MessageCode
= BOOTING_IN_SAFEMODE_DSREPAIR
;
1695 InitSafeBootMode
= 0;
1698 /* Check if there's any settings left */
1701 /* Check if an alternate shell was requested */
1702 if (!strncmp(SafeBoot
, "(ALTERNATESHELL)", 16))
1704 /* Remember this for later */
1705 AlternateShell
= TRUE
;
1709 /* Find the message to print out */
1710 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1715 if (NT_SUCCESS(Status
))
1718 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1723 /* Make sure we have a command line */
1726 /* Check if bootlogging is enabled */
1727 if (strstr(CommandLine
, "BOOTLOG"))
1729 /* Find the message to print out */
1730 Status
= RtlFindMessage(NtosEntry
->DllBase
,
1735 if (NT_SUCCESS(Status
))
1738 InbvDisplayString((PCHAR
)MsgEntry
->Text
);
1741 /* Setup boot logging */
1742 //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader);
1746 /* Setup the Executive in Phase 2 */
1747 //ExInitSystemPhase2();
1749 /* Update progress bar */
1750 InbvUpdateProgressBar(25);
1753 /* No KD Time Slip is pending */
1754 KdpTimeSlipPending
= 0;
1757 /* Initialize in-place execution support */
1758 XIPInit(LoaderBlock
);
1760 /* Set maximum update to 75% */
1761 InbvSetProgressBarSubset(25, 75);
1763 /* Initialize the I/O Subsystem */
1764 if (!IoInitSystem(LoaderBlock
)) KeBugCheck(IO1_INITIALIZATION_FAILED
);
1766 /* Set maximum update to 100% */
1767 InbvSetProgressBarSubset(0, 100);
1769 /* Are we in safe mode? */
1770 if (InitSafeBootMode
)
1772 /* Open the safe boot key */
1773 RtlInitUnicodeString(&KeyName
,
1774 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1775 L
"\\CONTROL\\SAFEBOOT");
1776 InitializeObjectAttributes(&ObjectAttributes
,
1778 OBJ_CASE_INSENSITIVE
,
1781 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1782 if (NT_SUCCESS(Status
))
1784 /* First check if we have an alternate shell */
1787 /* Make sure that the registry has one setup */
1788 RtlInitUnicodeString(&KeyName
, L
"AlternateShell");
1789 Status
= NtQueryValueKey(KeyHandle
,
1791 KeyValuePartialInformation
,
1793 sizeof(KeyPartialInfo
),
1795 if (!NT_SUCCESS(Status
)) AlternateShell
= FALSE
;
1798 /* Create the option key */
1799 RtlInitUnicodeString(&KeyName
, L
"Option");
1800 InitializeObjectAttributes(&ObjectAttributes
,
1802 OBJ_CASE_INSENSITIVE
,
1805 Status
= ZwCreateKey(&OptionHandle
,
1810 REG_OPTION_VOLATILE
,
1814 /* Check if the key create worked */
1815 if (NT_SUCCESS(Status
))
1817 /* Write the safe boot type */
1818 RtlInitUnicodeString(&KeyName
, L
"OptionValue");
1819 NtSetValueKey(OptionHandle
,
1824 sizeof(InitSafeBootMode
));
1826 /* Check if we have to use an alternate shell */
1829 /* Remember this for later */
1831 RtlInitUnicodeString(&KeyName
, L
"UseAlternateShell");
1832 NtSetValueKey(OptionHandle
,
1837 sizeof(Disposition
));
1840 /* Close the options key handle */
1841 NtClose(OptionHandle
);
1846 /* Are we in Win PE mode? */
1847 if (InitIsWinPEMode
)
1849 /* Open the safe control key */
1850 RtlInitUnicodeString(&KeyName
,
1851 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1853 InitializeObjectAttributes(&ObjectAttributes
,
1855 OBJ_CASE_INSENSITIVE
,
1858 Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
1859 if (!NT_SUCCESS(Status
))
1862 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1865 /* Create the MiniNT key */
1866 RtlInitUnicodeString(&KeyName
, L
"MiniNT");
1867 InitializeObjectAttributes(&ObjectAttributes
,
1869 OBJ_CASE_INSENSITIVE
,
1872 Status
= ZwCreateKey(&OptionHandle
,
1877 REG_OPTION_VOLATILE
,
1879 if (!NT_SUCCESS(Status
))
1882 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 6, 0, 0);
1885 /* Close the handles */
1887 NtClose(OptionHandle
);
1890 /* FIXME: This doesn't do anything for now */
1891 MmArmInitSystem(2, LoaderBlock
);
1893 /* Update progress bar */
1894 InbvUpdateProgressBar(80);
1896 /* Initialize VDM support */
1897 #if defined(_M_IX86)
1898 KeI386VdmInitialize();
1901 /* Initialize Power Subsystem in Phase 1*/
1902 if (!PoInitSystem(1)) KeBugCheck(INTERNAL_POWER_ERROR
);
1904 /* Initialize the Process Manager at Phase 1 */
1905 if (!PsInitSystem(LoaderBlock
)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED
);
1907 /* Update progress bar */
1908 InbvUpdateProgressBar(85);
1910 /* Make sure nobody touches the loader block again */
1911 if (LoaderBlock
== KeLoaderBlock
) KeLoaderBlock
= NULL
;
1912 LoaderBlock
= Context
= NULL
;
1914 /* Update progress bar */
1915 InbvUpdateProgressBar(90);
1917 /* Launch initial process */
1918 DPRINT1("Free non-cache pages: %lx\n", MmAvailablePages
+ MiMemoryConsumers
[MC_CACHE
].PagesUsed
);
1919 ProcessInfo
= &InitBuffer
->ProcessInfo
;
1920 ExpLoadInitialProcess(InitBuffer
, &ProcessParameters
, &Environment
);
1922 /* Update progress bar */
1923 InbvUpdateProgressBar(100);
1925 /* Allow strings to be displayed */
1926 InbvEnableDisplayString(TRUE
);
1928 /* Wait 5 seconds for it to initialize */
1929 Timeout
.QuadPart
= Int32x32To64(5, -10000000);
1930 Status
= ZwWaitForSingleObject(ProcessInfo
->ProcessHandle
, FALSE
, &Timeout
);
1931 if (InbvBootDriverInstalled
) FinalizeBootLogo();
1932 if (Status
== STATUS_SUCCESS
)
1934 /* Failed, display error */
1935 RtlInitUnicodeString(&DebugString
, L
"INIT: Session Manager terminated.");
1936 ZwDisplayString(&DebugString
);
1938 /* Bugcheck the system if SMSS couldn't initialize */
1939 KeBugCheck(SESSION5_INITIALIZATION_FAILED
);
1942 /* Close process handles */
1943 ZwClose(ProcessInfo
->ThreadHandle
);
1944 ZwClose(ProcessInfo
->ProcessHandle
);
1946 /* Free the initial process environment */
1948 ZwFreeVirtualMemory(NtCurrentProcess(),
1949 (PVOID
*)&Environment
,
1953 /* Free the initial process parameters */
1955 ZwFreeVirtualMemory(NtCurrentProcess(),
1956 (PVOID
*)&ProcessParameters
,
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 */