Reactos
1/*
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)
7 * Eric Kohl
8 */
9
10/* INCLUDES ******************************************************************/
11
12#include <ntoskrnl.h>
13#include <reactos/buildno.h>
14#include "inbv/logo.h"
15
16#define NDEBUG
17#include <debug.h>
18
19/* This is the size that we can expect from the win 2003 loader */
20#define LOADER_PARAMETER_EXTENSION_MIN_SIZE \
21 RTL_SIZEOF_THROUGH_FIELD(LOADER_PARAMETER_EXTENSION, AcpiTableSize)
22
23/* Temporary hack */
24CODE_SEG("INIT")
25BOOLEAN
26NTAPI
27MmArmInitSystem(
28 IN ULONG Phase,
29 IN PLOADER_PARAMETER_BLOCK LoaderBlock
30);
31
32typedef struct _INIT_BUFFER
33{
34 WCHAR DebugBuffer[256];
35 CHAR VersionBuffer[256];
36 CHAR BootlogHeader[256];
37 CHAR VersionNumber[24];
38 RTL_USER_PROCESS_INFORMATION ProcessInfo;
39 WCHAR RegistryBuffer[256];
40} INIT_BUFFER, *PINIT_BUFFER;
41
42/* DATA **********************************************************************/
43
44/* NT Version Info */
45ULONG NtMajorVersion = VER_PRODUCTMAJORVERSION;
46ULONG NtMinorVersion = VER_PRODUCTMINORVERSION;
47#if DBG /* Checked Build */
48ULONG NtBuildNumber = VER_PRODUCTBUILD | 0xC0000000;
49#else /* Free Build */
50ULONG NtBuildNumber = VER_PRODUCTBUILD;
51#endif
52
53/* NT System Info */
54ULONG NtGlobalFlag = 0;
55ULONG ExSuiteMask;
56
57/* Cm Version Info */
58ULONG CmNtSpBuildNumber;
59ULONG CmNtCSDVersion;
60ULONG CmNtCSDReleaseType;
61UNICODE_STRING CmVersionString;
62UNICODE_STRING CmCSDVersionString;
63
64CHAR NtBuildLab[] = KERNEL_VERSION_BUILD_STR "."
65 REACTOS_COMPILER_NAME "_" REACTOS_COMPILER_VERSION;
66
67/* Init flags and settings */
68ULONG ExpInitializationPhase;
69BOOLEAN ExpInTextModeSetup;
70BOOLEAN IoRemoteBootClient;
71ULONG InitSafeBootMode;
72BOOLEAN InitIsWinPEMode, InitWinPEModeType;
73BOOLEAN SosEnabled; // Used by driver.c!IopDisplayLoadingMessage()
74
75/* NT Boot Path */
76UNICODE_STRING NtSystemRoot;
77
78/* NT Initial User Application */
79WCHAR NtInitialUserProcessBuffer[128] = L"\\SystemRoot\\System32\\smss.exe";
80ULONG NtInitialUserProcessBufferLength = sizeof(NtInitialUserProcessBuffer) -
81 sizeof(WCHAR);
82ULONG NtInitialUserProcessBufferType = REG_SZ;
83
84/* Boot NLS information */
85PVOID ExpNlsTableBase;
86ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
87ULONG ExpUnicodeCaseTableDataOffset;
88NLSTABLEINFO ExpNlsTableInfo;
89SIZE_T ExpNlsTableSize;
90PVOID ExpNlsSectionPointer;
91
92/* CMOS Timer Sanity */
93BOOLEAN ExCmosClockIsSane = TRUE;
94BOOLEAN ExpRealTimeIsUniversal;
95
96/* FUNCTIONS ****************************************************************/
97
98CODE_SEG("INIT")
99NTSTATUS
100NTAPI
101ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
102{
103 UNICODE_STRING LinkName;
104 OBJECT_ATTRIBUTES ObjectAttributes;
105 HANDLE LinkHandle;
106 NTSTATUS Status;
107 ANSI_STRING AnsiName;
108 CHAR Buffer[256];
109 ANSI_STRING TargetString;
110 UNICODE_STRING TargetName;
111
112 /* Initialize the ArcName tree */
113 RtlInitUnicodeString(&LinkName, L"\\ArcName");
114 InitializeObjectAttributes(&ObjectAttributes,
115 &LinkName,
116 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
117 NULL,
118 SePublicDefaultUnrestrictedSd);
119
120 /* Create it */
121 Status = NtCreateDirectoryObject(&LinkHandle,
122 DIRECTORY_ALL_ACCESS,
123 &ObjectAttributes);
124 if (!NT_SUCCESS(Status))
125 {
126 /* Failed */
127 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 1, 0, 0);
128 }
129
130 /* Close the LinkHandle */
131 NtClose(LinkHandle);
132
133 /* Initialize the Device tree */
134 RtlInitUnicodeString(&LinkName, L"\\Device");
135 InitializeObjectAttributes(&ObjectAttributes,
136 &LinkName,
137 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
138 NULL,
139 SePublicDefaultUnrestrictedSd);
140
141 /* Create it */
142 Status = NtCreateDirectoryObject(&LinkHandle,
143 DIRECTORY_ALL_ACCESS,
144 &ObjectAttributes);
145 if (!NT_SUCCESS(Status))
146 {
147 /* Failed */
148 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 2, 0, 0);
149 }
150
151 /* Close the LinkHandle */
152 ObCloseHandle(LinkHandle, KernelMode);
153
154 /* Create the system root symlink name */
155 RtlInitAnsiString(&AnsiName, "\\SystemRoot");
156 Status = RtlAnsiStringToUnicodeString(&LinkName, &AnsiName, TRUE);
157 if (!NT_SUCCESS(Status))
158 {
159 /* Failed */
160 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 3, 0, 0);
161 }
162
163 /* Initialize the attributes for the link */
164 InitializeObjectAttributes(&ObjectAttributes,
165 &LinkName,
166 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
167 NULL,
168 SePublicDefaultUnrestrictedSd);
169
170 /* Build the ARC name */
171 sprintf(Buffer,
172 "\\ArcName\\%s%s",
173 LoaderBlock->ArcBootDeviceName,
174 LoaderBlock->NtBootPathName);
175 Buffer[strlen(Buffer) - 1] = ANSI_NULL;
176
177 /* Convert it to Unicode */
178 RtlInitString(&TargetString, Buffer);
179 Status = RtlAnsiStringToUnicodeString(&TargetName,
180 &TargetString,
181 TRUE);
182 if (!NT_SUCCESS(Status))
183 {
184 /* We failed, bugcheck */
185 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 4, 0, 0);
186 }
187
188 /* Create it */
189 Status = NtCreateSymbolicLinkObject(&LinkHandle,
190 SYMBOLIC_LINK_ALL_ACCESS,
191 &ObjectAttributes,
192 &TargetName);
193
194 /* Free the strings */
195 RtlFreeUnicodeString(&LinkName);
196 RtlFreeUnicodeString(&TargetName);
197
198 /* Check if creating the link failed */
199 if (!NT_SUCCESS(Status))
200 {
201 /* Failed */
202 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 5, 0, 0);
203 }
204
205 /* Close the handle and return success */
206 ObCloseHandle(LinkHandle, KernelMode);
207 return STATUS_SUCCESS;
208}
209
210CODE_SEG("INIT")
211VOID
212NTAPI
213ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
214{
215 LARGE_INTEGER SectionSize;
216 NTSTATUS Status;
217 HANDLE NlsSection;
218 PVOID SectionBase = NULL;
219 SIZE_T ViewSize = 0;
220 LARGE_INTEGER SectionOffset = {{0, 0}};
221 PLIST_ENTRY ListHead, NextEntry;
222 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
223 ULONG NlsTablesEncountered = 0;
224 SIZE_T NlsTableSizes[3] = {0, 0, 0}; /* 3 NLS tables */
225
226 /* Check if this is boot-time phase 0 initialization */
227 if (!ExpInitializationPhase)
228 {
229 /* Loop the memory descriptors */
230 ListHead = &LoaderBlock->MemoryDescriptorListHead;
231 NextEntry = ListHead->Flink;
232 while (NextEntry != ListHead)
233 {
234 /* Get the current block */
235 MdBlock = CONTAINING_RECORD(NextEntry,
236 MEMORY_ALLOCATION_DESCRIPTOR,
237 ListEntry);
238
239 /* Check if this is an NLS block */
240 if (MdBlock->MemoryType == LoaderNlsData)
241 {
242 /* Increase the table size */
243 ExpNlsTableSize += MdBlock->PageCount * PAGE_SIZE;
244
245 /* FreeLdr-specific */
246 NlsTableSizes[NlsTablesEncountered] = MdBlock->PageCount * PAGE_SIZE;
247 NlsTablesEncountered++;
248 ASSERT(NlsTablesEncountered < 4);
249 }
250
251 /* Go to the next block */
252 NextEntry = MdBlock->ListEntry.Flink;
253 }
254
255 /* Allocate the a new buffer since loader memory will be freed */
256 ExpNlsTableBase = ExAllocatePoolWithTag(NonPagedPool,
257 ExpNlsTableSize,
258 TAG_RTLI);
259 if (!ExpNlsTableBase) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
260
261 /* Copy the codepage data in its new location. */
262 if (NlsTablesEncountered == 1)
263 {
264 /* Ntldr-way boot process */
265 RtlCopyMemory(ExpNlsTableBase,
266 LoaderBlock->NlsData->AnsiCodePageData,
267 ExpNlsTableSize);
268 }
269 else
270 {
271 /*
272 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
273 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
274 */
275 RtlCopyMemory(ExpNlsTableBase,
276 LoaderBlock->NlsData->AnsiCodePageData,
277 NlsTableSizes[0]);
278
279 RtlCopyMemory((PVOID)((ULONG_PTR)ExpNlsTableBase + NlsTableSizes[0]),
280 LoaderBlock->NlsData->OemCodePageData,
281 NlsTableSizes[1]);
282
283 RtlCopyMemory((PVOID)((ULONG_PTR)ExpNlsTableBase + NlsTableSizes[0] +
284 NlsTableSizes[1]),
285 LoaderBlock->NlsData->UnicodeCodePageData,
286 NlsTableSizes[2]);
287 /* End of Hack */
288 }
289
290 /* Initialize and reset the NLS TAbles */
291 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
292 ExpAnsiCodePageDataOffset),
293 (PVOID)((ULONG_PTR)ExpNlsTableBase +
294 ExpOemCodePageDataOffset),
295 (PVOID)((ULONG_PTR)ExpNlsTableBase +
296 ExpUnicodeCaseTableDataOffset),
297 &ExpNlsTableInfo);
298 RtlResetRtlTranslations(&ExpNlsTableInfo);
299 return;
300 }
301
302 /* Set the section size */
303 SectionSize.QuadPart = ExpNlsTableSize;
304
305 /* Create the NLS Section */
306 Status = ZwCreateSection(&NlsSection,
307 SECTION_ALL_ACCESS,
308 NULL,
309 &SectionSize,
310 PAGE_READWRITE,
311 SEC_COMMIT | 0x1,
312 NULL);
313 if (!NT_SUCCESS(Status))
314 {
315 /* Failed */
316 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 1, 0, 0);
317 }
318
319 /* Get a pointer to the section */
320 Status = ObReferenceObjectByHandle(NlsSection,
321 SECTION_ALL_ACCESS,
322 MmSectionObjectType,
323 KernelMode,
324 &ExpNlsSectionPointer,
325 NULL);
326 ObCloseHandle(NlsSection, KernelMode);
327 if (!NT_SUCCESS(Status))
328 {
329 /* Failed */
330 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 2, 0, 0);
331 }
332
333 /* Map the NLS Section in system space */
334 Status = MmMapViewInSystemSpace(ExpNlsSectionPointer,
335 &SectionBase,
336 &ExpNlsTableSize);
337 if (!NT_SUCCESS(Status))
338 {
339 /* Failed */
340 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 3, 0, 0);
341 }
342
343 /* Copy the codepage data in its new location. */
344 ASSERT(SectionBase >= MmSystemRangeStart);
345 RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
346
347 /* Free the previously allocated buffer and set the new location */
348 ExFreePoolWithTag(ExpNlsTableBase, TAG_RTLI);
349 ExpNlsTableBase = SectionBase;
350
351 /* Initialize the NLS Tables */
352 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
353 ExpAnsiCodePageDataOffset),
354 (PVOID)((ULONG_PTR)ExpNlsTableBase +
355 ExpOemCodePageDataOffset),
356 (PVOID)((ULONG_PTR)ExpNlsTableBase +
357 ExpUnicodeCaseTableDataOffset),
358 &ExpNlsTableInfo);
359 RtlResetRtlTranslations(&ExpNlsTableInfo);
360
361 /* Reset the base to 0 */
362 SectionBase = NULL;
363
364 /* Map the section in the system process */
365 Status = MmMapViewOfSection(ExpNlsSectionPointer,
366 PsGetCurrentProcess(),
367 &SectionBase,
368 0L,
369 0L,
370 &SectionOffset,
371 &ViewSize,
372 ViewShare,
373 0L,
374 PAGE_READWRITE);
375 if (!NT_SUCCESS(Status))
376 {
377 /* Failed */
378 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 5, 0, 0);
379 }
380
381 /* Copy the table into the system process and set this as the base */
382 RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
383 ExpNlsTableBase = SectionBase;
384}
385
386CODE_SEG("INIT")
387VOID
388NTAPI
389ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer,
390 OUT PRTL_USER_PROCESS_PARAMETERS *ProcessParameters,
391 OUT PCHAR *ProcessEnvironment)
392{
393 NTSTATUS Status;
394 SIZE_T Size;
395 PWSTR p;
396 UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
397 UNICODE_STRING SmssName, Environment, SystemDriveString, DebugString;
398 PVOID EnvironmentPtr = NULL;
399 PRTL_USER_PROCESS_INFORMATION ProcessInformation;
400 PRTL_USER_PROCESS_PARAMETERS ProcessParams = NULL;
401
402 NullString.Length = sizeof(WCHAR);
403
404 /* Use the initial buffer, after the strings */
405 ProcessInformation = &InitBuffer->ProcessInfo;
406
407 /* Allocate memory for the process parameters */
408 Size = sizeof(*ProcessParams) + ((MAX_WIN32_PATH * 6) * sizeof(WCHAR));
409 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
410 (PVOID*)&ProcessParams,
411 0,
412 &Size,
413 MEM_RESERVE | MEM_COMMIT,
414 PAGE_READWRITE);
415 if (!NT_SUCCESS(Status))
416 {
417 /* Failed, display error */
418 _snwprintf(InitBuffer->DebugBuffer,
419 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR),
420 L"INIT: Unable to allocate Process Parameters. 0x%lx",
421 Status);
422 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer);
423 ZwDisplayString(&DebugString);
424
425 /* Bugcheck the system */
426 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED, Status, 0, 0, 0);
427 }
428
429 /* Setup the basic header, and give the process the low 1MB to itself */
430 ProcessParams->Length = (ULONG)Size;
431 ProcessParams->MaximumLength = (ULONG)Size;
432 ProcessParams->Flags = RTL_USER_PROCESS_PARAMETERS_NORMALIZED |
433 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
434
435 /* Allocate a page for the environment */
436 Size = PAGE_SIZE;
437 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
438 &EnvironmentPtr,
439 0,
440 &Size,
441 MEM_RESERVE | MEM_COMMIT,
442 PAGE_READWRITE);
443 if (!NT_SUCCESS(Status))
444 {
445 /* Failed, display error */
446 _snwprintf(InitBuffer->DebugBuffer,
447 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR),
448 L"INIT: Unable to allocate Process Environment. 0x%lx",
449 Status);
450 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer);
451 ZwDisplayString(&DebugString);
452
453 /* Bugcheck the system */
454 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
455 }
456
457 /* Write the pointer */
458 ProcessParams->Environment = EnvironmentPtr;
459
460 /* Make a buffer for the DOS path */
461 p = (PWSTR)(ProcessParams + 1);
462 ProcessParams->CurrentDirectory.DosPath.Buffer = p;
463 ProcessParams->CurrentDirectory.DosPath.MaximumLength = MAX_WIN32_PATH *
464 sizeof(WCHAR);
465
466 /* Copy the DOS path */
467 RtlCopyUnicodeString(&ProcessParams->CurrentDirectory.DosPath,
468 &NtSystemRoot);
469
470 /* Make a buffer for the DLL Path */
471 p = (PWSTR)((PCHAR)ProcessParams->CurrentDirectory.DosPath.Buffer +
472 ProcessParams->CurrentDirectory.DosPath.MaximumLength);
473 ProcessParams->DllPath.Buffer = p;
474 ProcessParams->DllPath.MaximumLength = MAX_WIN32_PATH * sizeof(WCHAR);
475
476 /* Copy the DLL path and append the system32 directory */
477 RtlCopyUnicodeString(&ProcessParams->DllPath,
478 &ProcessParams->CurrentDirectory.DosPath);
479 RtlAppendUnicodeToString(&ProcessParams->DllPath, L"\\System32");
480
481 /* Make a buffer for the image name */
482 p = (PWSTR)((PCHAR)ProcessParams->DllPath.Buffer +
483 ProcessParams->DllPath.MaximumLength);
484 ProcessParams->ImagePathName.Buffer = p;
485 ProcessParams->ImagePathName.MaximumLength = MAX_WIN32_PATH * sizeof(WCHAR);
486
487 /* Make sure the buffer is a valid string which within the given length */
488 if ((NtInitialUserProcessBufferType != REG_SZ) ||
489 ((NtInitialUserProcessBufferLength != MAXULONG) &&
490 ((NtInitialUserProcessBufferLength < sizeof(WCHAR)) ||
491 (NtInitialUserProcessBufferLength >
492 sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR)))))
493 {
494 /* Invalid initial process string, bugcheck */
495 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED,
496 STATUS_INVALID_PARAMETER,
497 NtInitialUserProcessBufferType,
498 NtInitialUserProcessBufferLength,
499 sizeof(NtInitialUserProcessBuffer));
500 }
501
502 /* Cut out anything after a space */
503 p = NtInitialUserProcessBuffer;
504 while ((*p) && (*p != L' ')) p++;
505
506 /* Set the image path length */
507 ProcessParams->ImagePathName.Length =
508 (USHORT)((PCHAR)p - (PCHAR)NtInitialUserProcessBuffer);
509
510 /* Copy the actual buffer */
511 RtlCopyMemory(ProcessParams->ImagePathName.Buffer,
512 NtInitialUserProcessBuffer,
513 ProcessParams->ImagePathName.Length);
514
515 /* Null-terminate it */
516 ProcessParams->ImagePathName.Buffer[ProcessParams->ImagePathName.Length /
517 sizeof(WCHAR)] = UNICODE_NULL;
518
519 /* Make a buffer for the command line */
520 p = (PWSTR)((PCHAR)ProcessParams->ImagePathName.Buffer +
521 ProcessParams->ImagePathName.MaximumLength);
522 ProcessParams->CommandLine.Buffer = p;
523 ProcessParams->CommandLine.MaximumLength = MAX_WIN32_PATH * sizeof(WCHAR);
524
525 /* Add the image name to the command line */
526 RtlAppendUnicodeToString(&ProcessParams->CommandLine,
527 NtInitialUserProcessBuffer);
528
529 /* Create the environment string */
530 RtlInitEmptyUnicodeString(&Environment,
531 ProcessParams->Environment,
532 (USHORT)Size);
533
534 /* Append the DLL path to it */
535 RtlAppendUnicodeToString(&Environment, L"Path=");
536 RtlAppendUnicodeStringToString(&Environment, &ProcessParams->DllPath);
537 RtlAppendUnicodeStringToString(&Environment, &NullString);
538
539 /* Create the system drive string */
540 SystemDriveString = NtSystemRoot;
541 SystemDriveString.Length = 2 * sizeof(WCHAR);
542
543 /* Append it to the environment */
544 RtlAppendUnicodeToString(&Environment, L"SystemDrive=");
545 RtlAppendUnicodeStringToString(&Environment, &SystemDriveString);
546 RtlAppendUnicodeStringToString(&Environment, &NullString);
547
548 /* Append the system root to the environment */
549 RtlAppendUnicodeToString(&Environment, L"SystemRoot=");
550 RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
551 RtlAppendUnicodeStringToString(&Environment, &NullString);
552
553 /* Prepare the prefetcher */
554 //CcPfBeginBootPhase(150);
555
556 /* Create SMSS process */
557 SmssName = ProcessParams->ImagePathName;
558 Status = RtlCreateUserProcess(&SmssName,
559 OBJ_CASE_INSENSITIVE,
560 RtlDeNormalizeProcessParams(ProcessParams),
561 NULL,
562 NULL,
563 NULL,
564 FALSE,
565 NULL,
566 NULL,
567 ProcessInformation);
568 if (!NT_SUCCESS(Status))
569 {
570 /* Failed, display error */
571 _snwprintf(InitBuffer->DebugBuffer,
572 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR),
573 L"INIT: Unable to create Session Manager. 0x%lx",
574 Status);
575 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer);
576 ZwDisplayString(&DebugString);
577
578 /* Bugcheck the system */
579 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED, Status, 0, 0, 0);
580 }
581
582 /* Resume the thread */
583 Status = ZwResumeThread(ProcessInformation->ThreadHandle, NULL);
584 if (!NT_SUCCESS(Status))
585 {
586 /* Failed, display error */
587 _snwprintf(InitBuffer->DebugBuffer,
588 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR),
589 L"INIT: Unable to resume Session Manager. 0x%lx",
590 Status);
591 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer);
592 ZwDisplayString(&DebugString);
593
594 /* Bugcheck the system */
595 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
596 }
597
598 /* Return success */
599 *ProcessParameters = ProcessParams;
600 *ProcessEnvironment = EnvironmentPtr;
601}
602
603CODE_SEG("INIT")
604ULONG
605NTAPI
606ExComputeTickCountMultiplier(IN ULONG ClockIncrement)
607{
608 ULONG MsRemainder = 0, MsIncrement;
609 ULONG IncrementRemainder;
610 ULONG i;
611
612 /* Count the number of milliseconds for each clock interrupt */
613 MsIncrement = ClockIncrement / (10 * 1000);
614
615 /* Count the remainder from the division above, with 24-bit precision */
616 IncrementRemainder = ClockIncrement - (MsIncrement * (10 * 1000));
617 for (i= 0; i < 24; i++)
618 {
619 /* Shift the remainders */
620 MsRemainder <<= 1;
621 IncrementRemainder <<= 1;
622
623 /* Check if we've went past 1 ms */
624 if (IncrementRemainder >= (10 * 1000))
625 {
626 /* Increase the remainder by one, and substract from increment */
627 IncrementRemainder -= (10 * 1000);
628 MsRemainder |= 1;
629 }
630 }
631
632 /* Return the increment */
633 return (MsIncrement << 24) | MsRemainder;
634}
635
636CODE_SEG("INIT")
637BOOLEAN
638NTAPI
639ExpInitSystemPhase0(VOID)
640{
641 /* Initialize EXRESOURCE Support */
642 ExpResourceInitialization();
643
644 /* Initialize the environment lock */
645 ExInitializeFastMutex(&ExpEnvironmentLock);
646
647 /* Initialize the lookaside lists and locks */
648 ExpInitLookasideLists();
649
650 /* Initialize the Firmware Table resource and listhead */
651 InitializeListHead(&ExpFirmwareTableProviderListHead);
652 ExInitializeResourceLite(&ExpFirmwareTableResource);
653 ExInitializeResourceLite(&ExpTimeRefreshLock);
654
655 /* Set the suite mask to maximum and return */
656 ExSuiteMask = 0xFFFFFFFF;
657 return TRUE;
658}
659
660CODE_SEG("INIT")
661BOOLEAN
662NTAPI
663ExpInitSystemPhase1(VOID)
664{
665 /* Initialize worker threads */
666 ExpInitializeWorkerThreads();
667
668 /* Initialize pushlocks */
669 ExpInitializePushLocks();
670
671 /* Initialize events and event pairs */
672 if (ExpInitializeEventImplementation() == FALSE)
673 {
674 DPRINT1("Executive: Event initialization failed\n");
675 return FALSE;
676 }
677 if (ExpInitializeEventPairImplementation() == FALSE)
678 {
679 DPRINT1("Executive: Event Pair initialization failed\n");
680 return FALSE;
681 }
682
683 /* Initialize mutants */
684 if (ExpInitializeMutantImplementation() == FALSE)
685 {
686 DPRINT1("Executive: Mutant initialization failed\n");
687 return FALSE;
688 }
689
690 /* Initialize callbacks */
691 if (ExpInitializeCallbacks() == FALSE)
692 {
693 DPRINT1("Executive: Callback initialization failed\n");
694 return FALSE;
695 }
696
697 /* Initialize semaphores */
698 if (ExpInitializeSemaphoreImplementation() == FALSE)
699 {
700 DPRINT1("Executive: Semaphore initialization failed\n");
701 return FALSE;
702 }
703
704 /* Initialize timers */
705 if (ExpInitializeTimerImplementation() == FALSE)
706 {
707 DPRINT1("Executive: Timer initialization failed\n");
708 return FALSE;
709 }
710
711 /* Initialize profiling */
712 if (ExpInitializeProfileImplementation() == FALSE)
713 {
714 DPRINT1("Executive: Profile initialization failed\n");
715 return FALSE;
716 }
717
718 /* Initialize UUIDs */
719 if (ExpUuidInitialization() == FALSE)
720 {
721 DPRINT1("Executive: Uuid initialization failed\n");
722 return FALSE;
723 }
724
725 /* Initialize keyed events */
726 if (ExpInitializeKeyedEventImplementation() == FALSE)
727 {
728 DPRINT1("Executive: Keyed event initialization failed\n");
729 return FALSE;
730 }
731
732 /* Initialize Win32K */
733 if (ExpWin32kInit() == FALSE)
734 {
735 DPRINT1("Executive: Win32 initialization failed\n");
736 return FALSE;
737 }
738 return TRUE;
739}
740
741CODE_SEG("INIT")
742BOOLEAN
743NTAPI
744ExInitSystem(VOID)
745{
746 /* Check the initialization phase */
747 switch (ExpInitializationPhase)
748 {
749 case 0:
750
751 /* Do Phase 0 */
752 return ExpInitSystemPhase0();
753
754 case 1:
755
756 /* Do Phase 1 */
757 return ExpInitSystemPhase1();
758
759 default:
760
761 /* Don't know any other phase! Bugcheck! */
762 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL);
763 return FALSE;
764 }
765}
766
767CODE_SEG("INIT")
768BOOLEAN
769NTAPI
770ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
771{
772 PLOADER_PARAMETER_EXTENSION Extension;
773
774 /* Get the loader extension */
775 Extension = LoaderBlock->Extension;
776
777 /* Validate the size (Windows 2003 loader doesn't provide more) */
778 if (Extension->Size < LOADER_PARAMETER_EXTENSION_MIN_SIZE) return FALSE;
779
780 /* Don't validate upper versions */
781 if (Extension->MajorVersion > VER_PRODUCTMAJORVERSION) return TRUE;
782
783 /* Fail if this is NT 4 */
784 if (Extension->MajorVersion < VER_PRODUCTMAJORVERSION) return FALSE;
785
786 /* Fail if this is XP */
787 if (Extension->MinorVersion < VER_PRODUCTMINORVERSION) return FALSE;
788
789 /* This is 2003 or newer, approve it */
790 return TRUE;
791}
792
793static CODE_SEG("INIT")
794VOID
795ExpLoadBootSymbols(
796 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
797{
798 PLIST_ENTRY NextEntry;
799 PLDR_DATA_TABLE_ENTRY LdrEntry;
800 NTSTATUS Status;
801 ULONG i;
802 ULONG Count, Length;
803 PWCHAR Name;
804 STRING ImageName;
805 CHAR NameBuffer[256];
806
807 /* Loop over the boot modules list */
808 for (NextEntry = LoaderBlock->LoadOrderListHead.Flink, i = 0;
809 NextEntry != &LoaderBlock->LoadOrderListHead;
810 NextEntry = NextEntry->Flink, ++i)
811 {
812 /* Skip the first two images: HAL and kernel */
813 if (i < 2)
814 continue;
815
816 /* Get the entry */
817 LdrEntry = CONTAINING_RECORD(NextEntry,
818 LDR_DATA_TABLE_ENTRY,
819 InLoadOrderLinks);
820 if (LdrEntry->FullDllName.Buffer[0] == L'\\')
821 {
822 /* We have a name, read its data */
823 Name = LdrEntry->FullDllName.Buffer;
824 Length = LdrEntry->FullDllName.Length / sizeof(WCHAR);
825
826 /* Check if our buffer can hold it */
827 if (sizeof(NameBuffer) < Length + sizeof(ANSI_NULL))
828 {
829 /* It's too long */
830 Status = STATUS_BUFFER_OVERFLOW;
831 }
832 else
833 {
834 /* Copy the name */
835 Count = 0;
836 do
837 {
838 /* Do cheap Unicode to ANSI conversion */
839 NameBuffer[Count++] = (CHAR)*Name++;
840 } while (Count < Length);
841
842 /* Null-terminate */
843 NameBuffer[Count] = ANSI_NULL;
844 Status = STATUS_SUCCESS;
845 }
846 }
847 else
848 {
849 /* Safely print the string into our buffer */
850 Status = RtlStringCbPrintfA(NameBuffer,
851 sizeof(NameBuffer),
852 "%S\\System32\\Drivers\\%wZ",
853 &SharedUserData->NtSystemRoot[2],
854 &LdrEntry->BaseDllName);
855 }
856
857 /* Check if the buffer is OK */
858 if (NT_SUCCESS(Status))
859 {
860 /* Load the symbols */
861 RtlInitString(&ImageName, NameBuffer);
862 DbgLoadImageSymbols(&ImageName,
863 LdrEntry->DllBase,
864 (ULONG_PTR)PsGetCurrentProcessId());
865 }
866
867#ifdef CONFIG_SMP
868 /* Check that the image is safe to use if we have more than one CPU */
869 if (!MmVerifyImageIsOkForMpUse(LdrEntry->DllBase))
870 {
871 KeBugCheckEx(UP_DRIVER_ON_MP_SYSTEM,
872 (ULONG_PTR)LdrEntry->DllBase,
873 0, 0, 0);
874 }
875#endif // CONFIG_SMP
876 }
877}
878
879CODE_SEG("INIT")
880VOID
881NTAPI
882ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
883 IN ULONG_PTR PagesToDestroy,
884 IN TYPE_OF_MEMORY MemoryType)
885{
886 PLIST_ENTRY ListEntry;
887 PMEMORY_ALLOCATION_DESCRIPTOR MemDescriptor;
888
889 DPRINT1("Burn RAM amount: %lu pages\n", PagesToDestroy);
890
891 /* Loop the memory descriptors, beginning at the end */
892 for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Blink;
893 ListEntry != &LoaderBlock->MemoryDescriptorListHead;
894 ListEntry = ListEntry->Blink)
895 {
896 /* Get the memory descriptor structure */
897 MemDescriptor = CONTAINING_RECORD(ListEntry,
898 MEMORY_ALLOCATION_DESCRIPTOR,
899 ListEntry);
900
901 /* Is memory free there or is it temporary? */
902 if (MemDescriptor->MemoryType == LoaderFree ||
903 MemDescriptor->MemoryType == LoaderFirmwareTemporary)
904 {
905 /* Check if the descriptor has more pages than we want */
906 if (MemDescriptor->PageCount > PagesToDestroy)
907 {
908 /* Change block's page count, ntoskrnl doesn't care much */
909 MemDescriptor->PageCount -= PagesToDestroy;
910 break;
911 }
912 else
913 {
914 /* Change block type */
915 MemDescriptor->MemoryType = MemoryType;
916 PagesToDestroy -= MemDescriptor->PageCount;
917
918 /* Check if we are done */
919 if (PagesToDestroy == 0) break;
920 }
921 }
922 }
923}
924
925CODE_SEG("INIT")
926VOID
927NTAPI
928ExpInitializeExecutive(IN ULONG Cpu,
929 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
930{
931 PNLS_DATA_BLOCK NlsData;
932 CHAR Buffer[256];
933 ANSI_STRING AnsiPath;
934 NTSTATUS Status;
935 PCHAR CommandLine, PerfMem;
936 ULONG PerfMemUsed;
937 PLDR_DATA_TABLE_ENTRY NtosEntry;
938 PMESSAGE_RESOURCE_ENTRY MsgEntry;
939 ANSI_STRING CSDString;
940 size_t Remaining = 0;
941 PCHAR RcEnd = NULL;
942 CHAR VersionBuffer[65];
943
944 /* Validate Loader */
945 if (!ExpIsLoaderValid(LoaderBlock))
946 {
947 /* Invalid loader version */
948 KeBugCheckEx(MISMATCHED_HAL,
949 3,
950 LoaderBlock->Extension->Size,
951 LoaderBlock->Extension->MajorVersion,
952 LoaderBlock->Extension->MinorVersion);
953 }
954
955 /* Initialize PRCB pool lookaside pointers */
956 ExInitPoolLookasidePointers();
957
958 /* Check if this is an application CPU */
959 if (Cpu)
960 {
961 /* Then simply initialize it with HAL */
962 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
963 {
964 /* Initialization failed */
965 KeBugCheck(HAL_INITIALIZATION_FAILED);
966 }
967
968 /* We're done */
969 return;
970 }
971
972 /* Assume no text-mode or remote boot */
973 ExpInTextModeSetup = FALSE;
974 IoRemoteBootClient = FALSE;
975
976 /* Check if we have a setup loader block */
977 if (LoaderBlock->SetupLdrBlock)
978 {
979 /* Check if this is text-mode setup */
980 if (LoaderBlock->SetupLdrBlock->Flags & SETUPLDR_TEXT_MODE)
981 ExpInTextModeSetup = TRUE;
982
983 /* Check if this is network boot */
984 if (LoaderBlock->SetupLdrBlock->Flags & SETUPLDR_REMOTE_BOOT)
985 {
986 /* Set variable */
987 IoRemoteBootClient = TRUE;
988
989 /* Make sure we're actually booting off the network */
990 ASSERT(!_memicmp(LoaderBlock->ArcBootDeviceName, "net(0)", 6));
991 }
992 }
993
994 /* Set phase to 0 */
995 ExpInitializationPhase = 0;
996
997 /* Get boot command line */
998 CommandLine = LoaderBlock->LoadOptions;
999 if (CommandLine)
1000 {
1001 /* Upcase it for comparison and check if we're in performance mode */
1002 _strupr(CommandLine);
1003 PerfMem = strstr(CommandLine, "PERFMEM");
1004 if (PerfMem)
1005 {
1006 /* Check if the user gave a number of bytes to use */
1007 PerfMem = strstr(PerfMem, "=");
1008 if (PerfMem)
1009 {
1010 /* Read the number of pages we'll use */
1011 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
1012 if (PerfMemUsed)
1013 {
1014 /* FIXME: TODO */
1015 DPRINT1("BBT performance mode not yet supported."
1016 "/PERFMEM option ignored.\n");
1017 }
1018 }
1019 }
1020
1021 /* Check if we're burning memory */
1022 PerfMem = strstr(CommandLine, "BURNMEMORY");
1023 if (PerfMem)
1024 {
1025 /* Check if the user gave a number of bytes to use */
1026 PerfMem = strstr(PerfMem, "=");
1027 if (PerfMem)
1028 {
1029 /* Read the number of pages we'll use */
1030 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
1031 if (PerfMemUsed) ExBurnMemory(LoaderBlock, PerfMemUsed, LoaderBad);
1032 }
1033 }
1034 }
1035
1036 /* Setup NLS Base and offsets */
1037 NlsData = LoaderBlock->NlsData;
1038 ExpNlsTableBase = NlsData->AnsiCodePageData;
1039 ExpAnsiCodePageDataOffset = 0;
1040 ExpOemCodePageDataOffset = (ULONG)((ULONG_PTR)NlsData->OemCodePageData -
1041 (ULONG_PTR)NlsData->AnsiCodePageData);
1042 ExpUnicodeCaseTableDataOffset = (ULONG)((ULONG_PTR)NlsData->UnicodeCodePageData -
1043 (ULONG_PTR)NlsData->AnsiCodePageData);
1044
1045 /* Initialize the NLS Tables */
1046 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
1047 ExpAnsiCodePageDataOffset),
1048 (PVOID)((ULONG_PTR)ExpNlsTableBase +
1049 ExpOemCodePageDataOffset),
1050 (PVOID)((ULONG_PTR)ExpNlsTableBase +
1051 ExpUnicodeCaseTableDataOffset),
1052 &ExpNlsTableInfo);
1053 RtlResetRtlTranslations(&ExpNlsTableInfo);
1054
1055 /* Now initialize the HAL */
1056 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
1057 {
1058 /* HAL failed to initialize, bugcheck */
1059 KeBugCheck(HAL_INITIALIZATION_FAILED);
1060 }
1061
1062 /* Make sure interrupts are active now */
1063 _enable();
1064
1065 /* Clear the crypto exponent */
1066 SharedUserData->CryptoExponent = 0;
1067
1068 /* Set global flags for the checked build */
1069#if DBG
1070 NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS |
1071 FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
1072#endif
1073
1074 /* Setup NT System Root Path */
1075 sprintf(Buffer, "C:%s", LoaderBlock->NtBootPathName);
1076
1077 /* Convert to ANSI_STRING and null-terminate it */
1078 RtlInitString(&AnsiPath, Buffer);
1079 Buffer[--AnsiPath.Length] = ANSI_NULL;
1080
1081 /* Get the string from KUSER_SHARED_DATA's buffer */
1082 RtlInitEmptyUnicodeString(&NtSystemRoot,
1083 SharedUserData->NtSystemRoot,
1084 sizeof(SharedUserData->NtSystemRoot));
1085
1086 /* Now fill it in */
1087 Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
1088 if (!NT_SUCCESS(Status)) KeBugCheck(SESSION3_INITIALIZATION_FAILED);
1089
1090 /* Setup bugcheck messages */
1091 KiInitializeBugCheck();
1092
1093 /* Setup initial system settings */
1094 CmGetSystemControlValues(LoaderBlock->RegistryBase, CmControlVector);
1095
1096 /* Set the Service Pack Number and add it to the CSD Version number if needed */
1097 CmNtSpBuildNumber = VER_PRODUCTBUILD_QFE;
1098 if (((CmNtCSDVersion & 0xFFFF0000) == 0) && (CmNtCSDReleaseType == 1))
1099 {
1100 CmNtCSDVersion |= (VER_PRODUCTBUILD_QFE << 16);
1101 }
1102
1103 /* Add loaded CmNtGlobalFlag value */
1104 NtGlobalFlag |= CmNtGlobalFlag;
1105
1106 /* Initialize the executive at phase 0 */
1107 if (!ExInitSystem()) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
1108
1109 /* Initialize the memory manager at phase 0 */
1110 if (!MmArmInitSystem(0, LoaderBlock)) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
1111
1112 /* Load boot symbols */
1113 ExpLoadBootSymbols(LoaderBlock);
1114
1115 /* Check if we should break after symbol load */
1116 if (KdBreakAfterSymbolLoad)
1117 DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
1118
1119 /* Check if this loader is compatible with NT 5.2 */
1120 if (LoaderBlock->Extension->Size >= sizeof(LOADER_PARAMETER_EXTENSION))
1121 {
1122 /* Setup headless terminal settings */
1123 HeadlessInit(LoaderBlock);
1124 }
1125
1126 /* Set system ranges */
1127#ifdef _M_AMD64
1128 SharedUserData->Reserved1 = MM_HIGHEST_USER_ADDRESS_WOW64;
1129 SharedUserData->Reserved3 = MM_SYSTEM_RANGE_START_WOW64;
1130#else
1131 SharedUserData->Reserved1 = (ULONG_PTR)MmHighestUserAddress;
1132 SharedUserData->Reserved3 = (ULONG_PTR)MmSystemRangeStart;
1133#endif
1134
1135 /* Make a copy of the NLS Tables */
1136 ExpInitNls(LoaderBlock);
1137
1138 /* Get the kernel's load entry */
1139 NtosEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
1140 LDR_DATA_TABLE_ENTRY,
1141 InLoadOrderLinks);
1142
1143 /* Check if this is a service pack */
1144 if (CmNtCSDVersion & 0xFFFF)
1145 {
1146 /* Get the service pack string */
1147 Status = RtlFindMessage(NtosEntry->DllBase,
1148 RT_MESSAGETABLE,
1149 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
1150 WINDOWS_NT_CSD_STRING,
1151 &MsgEntry);
1152 if (NT_SUCCESS(Status))
1153 {
1154 /* Setup the string */
1155 RtlInitAnsiString(&CSDString, (PCHAR)MsgEntry->Text);
1156
1157 /* Remove trailing newline */
1158 while ((CSDString.Length > 0) &&
1159 ((CSDString.Buffer[CSDString.Length - 1] == '\r') ||
1160 (CSDString.Buffer[CSDString.Length - 1] == '\n')))
1161 {
1162 /* Skip the trailing character */
1163 CSDString.Length--;
1164 }
1165
1166 /* Fill the buffer with version information */
1167 Status = RtlStringCbPrintfA(Buffer,
1168 sizeof(Buffer),
1169 "%Z %u%c",
1170 &CSDString,
1171 (CmNtCSDVersion & 0xFF00) >> 8,
1172 (CmNtCSDVersion & 0xFF) ?
1173 'A' + (CmNtCSDVersion & 0xFF) - 1 :
1174 ANSI_NULL);
1175 }
1176 else
1177 {
1178 /* Build default string */
1179 Status = RtlStringCbPrintfA(Buffer,
1180 sizeof(Buffer),
1181 "CSD %04x",
1182 CmNtCSDVersion);
1183 }
1184
1185 /* Check for success */
1186 if (!NT_SUCCESS(Status))
1187 {
1188 /* Fail */
1189 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1190 }
1191 }
1192 else
1193 {
1194 /* Then this is a beta */
1195 Status = RtlStringCbCopyExA(Buffer,
1196 sizeof(Buffer),
1197 VER_PRODUCTBETA_STR,
1198 NULL,
1199 &Remaining,
1200 0);
1201 if (!NT_SUCCESS(Status))
1202 {
1203 /* Fail */
1204 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1205 }
1206
1207 /* Update length */
1208 CmCSDVersionString.MaximumLength = sizeof(Buffer) - (USHORT)Remaining;
1209 }
1210
1211 /* Check if we have an RC number */
1212 if ((CmNtCSDVersion & 0xFFFF0000) && (CmNtCSDReleaseType == 1))
1213 {
1214 /* Check if we have no version data yet */
1215 if (!(*Buffer))
1216 {
1217 /* Set defaults */
1218 Remaining = sizeof(Buffer);
1219 RcEnd = Buffer;
1220 }
1221 else
1222 {
1223 /* Add comma and space */
1224 Status = RtlStringCbCatExA(Buffer,
1225 sizeof(Buffer),
1226 ", ",
1227 &RcEnd,
1228 &Remaining,
1229 0);
1230 if (!NT_SUCCESS(Status))
1231 {
1232 /* Fail */
1233 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1234 }
1235 }
1236
1237 /* Add the version format string */
1238 Status = RtlStringCbPrintfA(RcEnd,
1239 Remaining,
1240 "v.%u",
1241 (CmNtCSDVersion & 0xFFFF0000) >> 16);
1242 if (!NT_SUCCESS(Status))
1243 {
1244 /* Fail */
1245 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1246 }
1247 }
1248
1249 /* Now setup the final string */
1250 RtlInitAnsiString(&CSDString, Buffer);
1251 Status = RtlAnsiStringToUnicodeString(&CmCSDVersionString,
1252 &CSDString,
1253 TRUE);
1254 if (!NT_SUCCESS(Status))
1255 {
1256 /* Fail */
1257 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1258 }
1259
1260 /* Add our version */
1261 Status = RtlStringCbPrintfA(VersionBuffer,
1262 sizeof(VersionBuffer),
1263 "%u.%u",
1264 VER_PRODUCTMAJORVERSION,
1265 VER_PRODUCTMINORVERSION);
1266 if (!NT_SUCCESS(Status))
1267 {
1268 /* Fail */
1269 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1270 }
1271
1272 /* Build the final version string */
1273 RtlCreateUnicodeStringFromAsciiz(&CmVersionString, VersionBuffer);
1274
1275 /* Check if the user wants a kernel stack trace database */
1276 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB)
1277 {
1278 /* FIXME: TODO */
1279 DPRINT1("Kernel-mode stack trace support not yet present."
1280 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
1281 }
1282
1283 /* Check if he wanted exception logging */
1284 if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING)
1285 {
1286 /* FIXME: TODO */
1287 DPRINT1("Kernel-mode exception logging support not yet present."
1288 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
1289 }
1290
1291 /* Initialize the Handle Table */
1292 ExpInitializeHandleTables();
1293
1294#if DBG
1295 /* On checked builds, allocate the system call count table */
1296 KeServiceDescriptorTable[0].Count =
1297 ExAllocatePoolWithTag(NonPagedPool,
1298 KiServiceLimit * sizeof(ULONG),
1299 'llaC');
1300
1301 /* Use it for the shadow table too */
1302 KeServiceDescriptorTableShadow[0].Count = KeServiceDescriptorTable[0].Count;
1303
1304 /* Make sure allocation succeeded */
1305 if (KeServiceDescriptorTable[0].Count)
1306 {
1307 /* Zero the call counts to 0 */
1308 RtlZeroMemory(KeServiceDescriptorTable[0].Count,
1309 KiServiceLimit * sizeof(ULONG));
1310 }
1311#endif
1312
1313 /* Create the Basic Object Manager Types to allow new Object Types */
1314 if (!ObInitSystem()) KeBugCheck(OBJECT_INITIALIZATION_FAILED);
1315
1316 /* Load basic Security for other Managers */
1317 if (!SeInitSystem()) KeBugCheck(SECURITY_INITIALIZATION_FAILED);
1318
1319 /* Initialize the Process Manager */
1320 if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS_INITIALIZATION_FAILED);
1321
1322 /* Initialize the PnP Manager */
1323 if (!PpInitSystem()) KeBugCheck(PP0_INITIALIZATION_FAILED);
1324
1325 /* Initialize the User-Mode Debugging Subsystem */
1326 DbgkInitialize();
1327
1328 /* Calculate the tick count multiplier */
1329 ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement);
1330 SharedUserData->TickCountMultiplier = ExpTickCountMultiplier;
1331
1332 /* Set the OS Version */
1333 SharedUserData->NtMajorVersion = NtMajorVersion;
1334 SharedUserData->NtMinorVersion = NtMinorVersion;
1335
1336 /* Set the machine type */
1337 SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_NATIVE;
1338 SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_NATIVE;
1339
1340 /* ReactOS magic */
1341 *(PULONG)(KI_USER_SHARED_DATA + PAGE_SIZE - sizeof(ULONG)) = 0x8eac705;
1342}
1343
1344VOID
1345NTAPI
1346MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock);
1347
1348CODE_SEG("INIT")
1349VOID
1350NTAPI
1351Phase1InitializationDiscard(IN PVOID Context)
1352{
1353 PLOADER_PARAMETER_BLOCK LoaderBlock = Context;
1354 NTSTATUS Status, MsgStatus;
1355 TIME_FIELDS TimeFields;
1356 LARGE_INTEGER SystemBootTime, UniversalBootTime, OldTime, Timeout;
1357 BOOLEAN NoGuiBoot, ResetBias = FALSE, AlternateShell = FALSE;
1358 PLDR_DATA_TABLE_ENTRY NtosEntry;
1359 PMESSAGE_RESOURCE_ENTRY MsgEntry;
1360 PCHAR CommandLine, Y2KHackRequired, SafeBoot, Environment;
1361 PCHAR StringBuffer, EndBuffer, BeginBuffer, MpString = "";
1362 PINIT_BUFFER InitBuffer;
1363 ANSI_STRING TempString;
1364 ULONG LastTzBias, Length, YearHack = 0, Disposition, MessageCode = 0;
1365 SIZE_T Size;
1366 size_t Remaining;
1367 PRTL_USER_PROCESS_INFORMATION ProcessInfo;
1368 KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo;
1369 UNICODE_STRING KeyName;
1370 OBJECT_ATTRIBUTES ObjectAttributes;
1371 HANDLE KeyHandle, OptionHandle;
1372 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
1373
1374 /* Allocate the initialization buffer */
1375 InitBuffer = ExAllocatePoolWithTag(NonPagedPool,
1376 sizeof(INIT_BUFFER),
1377 TAG_INIT);
1378 if (!InitBuffer)
1379 {
1380 /* Bugcheck */
1381 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 8, 0, 0);
1382 }
1383
1384 /* Set to phase 1 */
1385 ExpInitializationPhase = 1;
1386
1387 /* Set us at maximum priority */
1388 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY);
1389
1390 /* Do Phase 1 HAL Initialization */
1391 if (!HalInitSystem(1, LoaderBlock)) KeBugCheck(HAL1_INITIALIZATION_FAILED);
1392
1393 /* Get the command line and upcase it */
1394 CommandLine = (LoaderBlock->LoadOptions ? _strupr(LoaderBlock->LoadOptions) : NULL);
1395
1396 /* Check if GUI Boot is enabled */
1397 NoGuiBoot = (CommandLine && strstr(CommandLine, "NOGUIBOOT") != NULL);
1398
1399 /* Get the SOS setting */
1400 SosEnabled = (CommandLine && strstr(CommandLine, "SOS") != NULL);
1401
1402 /* Setup the boot video driver */
1403 InbvEnableBootDriver(!NoGuiBoot);
1404 InbvDriverInitialize(LoaderBlock, IDB_MAX_RESOURCES);
1405
1406 /* Check if GUI boot is enabled */
1407 if (!NoGuiBoot)
1408 {
1409 /* It is, display the boot logo and enable printing strings */
1410 InbvEnableDisplayString(SosEnabled);
1411 DisplayBootBitmap(SosEnabled);
1412 }
1413 else
1414 {
1415 /* Release display ownership if not using GUI boot */
1416 InbvNotifyDisplayOwnershipLost(NULL);
1417
1418 /* Don't allow boot-time strings */
1419 InbvEnableDisplayString(FALSE);
1420 }
1421
1422 /* Check if this is LiveCD (WinPE) mode */
1423 if (CommandLine && strstr(CommandLine, "MININT") != NULL)
1424 {
1425 /* Setup WinPE Settings */
1426 InitIsWinPEMode = TRUE;
1427 InitWinPEModeType |= (strstr(CommandLine, "INRAM") != NULL) ? 0x80000000 : 0x00000001;
1428 }
1429
1430 /* Get the kernel's load entry */
1431 NtosEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
1432 LDR_DATA_TABLE_ENTRY,
1433 InLoadOrderLinks);
1434
1435 /* Find the banner message */
1436 MsgStatus = RtlFindMessage(NtosEntry->DllBase,
1437 RT_MESSAGETABLE,
1438 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
1439 WINDOWS_NT_BANNER,
1440 &MsgEntry);
1441
1442 /* Setup defaults and check if we have a version string */
1443 StringBuffer = InitBuffer->VersionBuffer;
1444 BeginBuffer = StringBuffer;
1445 EndBuffer = StringBuffer;
1446 Remaining = sizeof(InitBuffer->VersionBuffer);
1447 if (CmCSDVersionString.Length)
1448 {
1449 /* Print the version string */
1450 Status = RtlStringCbPrintfExA(StringBuffer,
1451 Remaining,
1452 &EndBuffer,
1453 &Remaining,
1454 0,
1455 ": %wZ",
1456 &CmCSDVersionString);
1457 if (!NT_SUCCESS(Status))
1458 {
1459 /* Bugcheck */
1460 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1461 }
1462 }
1463 else
1464 {
1465 /* No version */
1466 *EndBuffer = ANSI_NULL; /* Null-terminate the string */
1467 }
1468
1469 /* Skip over the null-terminator to start a new string */
1470 ++EndBuffer;
1471 --Remaining;
1472
1473 /* Build the version number */
1474 StringBuffer = InitBuffer->VersionNumber;
1475 Status = RtlStringCbPrintfA(StringBuffer,
1476 sizeof(InitBuffer->VersionNumber),
1477 "%u.%u",
1478 VER_PRODUCTMAJORVERSION,
1479 VER_PRODUCTMINORVERSION);
1480 if (!NT_SUCCESS(Status))
1481 {
1482 /* Bugcheck */
1483 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1484 }
1485
1486 /* Check if we had found a banner message */
1487 if (NT_SUCCESS(MsgStatus))
1488 {
1489 /* Create the banner message */
1490 /* ReactOS specific: Report ReactOS version, NtBuildLab information and reported NT kernel version */
1491 Status = RtlStringCbPrintfA(EndBuffer,
1492 Remaining,
1493 (PCHAR)MsgEntry->Text,
1494 KERNEL_VERSION_STR,
1495 NtBuildLab,
1496 StringBuffer,
1497 NtBuildNumber & 0xFFFF,
1498 BeginBuffer);
1499 if (!NT_SUCCESS(Status))
1500 {
1501 /* Bugcheck */
1502 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1503 }
1504 }
1505 else
1506 {
1507 /* Use hard-coded banner message */
1508 Status = RtlStringCbCopyA(EndBuffer, Remaining, "REACTOS (R)\r\n");
1509 if (!NT_SUCCESS(Status))
1510 {
1511 /* Bugcheck */
1512 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1513 }
1514 }
1515
1516 /* Display the version string on-screen */
1517 InbvDisplayString(EndBuffer);
1518
1519 /* Initialize Power Subsystem in Phase 0 */
1520 if (!PoInitSystem(0)) KeBugCheck(INTERNAL_POWER_ERROR);
1521
1522 /* Check for Y2K hack */
1523 Y2KHackRequired = CommandLine ? strstr(CommandLine, "YEAR") : NULL;
1524 if (Y2KHackRequired) Y2KHackRequired = strstr(Y2KHackRequired, "=");
1525 if (Y2KHackRequired) YearHack = atol(Y2KHackRequired + 1);
1526
1527 /* Query the clock */
1528 if ((ExCmosClockIsSane) && (HalQueryRealTimeClock(&TimeFields)))
1529 {
1530 /* Check if we're using the Y2K hack */
1531 if (Y2KHackRequired) TimeFields.Year = (CSHORT)YearHack;
1532
1533 /* Convert to time fields */
1534 RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
1535 UniversalBootTime = SystemBootTime;
1536
1537 /* Check if real time is GMT */
1538 if (!ExpRealTimeIsUniversal)
1539 {
1540 /* Check if we don't have a valid bias */
1541 if (ExpLastTimeZoneBias == MAXULONG)
1542 {
1543 /* Reset */
1544 ResetBias = TRUE;
1545 ExpLastTimeZoneBias = ExpAltTimeZoneBias;
1546 }
1547
1548 /* Calculate the bias in seconds */
1549 ExpTimeZoneBias.QuadPart = Int32x32To64(ExpLastTimeZoneBias * 60,
1550 10000000);
1551
1552 /* Set the boot time-zone bias */
1553 SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
1554 SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
1555 SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
1556
1557 /* Convert the boot time to local time, and set it */
1558 UniversalBootTime.QuadPart = SystemBootTime.QuadPart +
1559 ExpTimeZoneBias.QuadPart;
1560 }
1561
1562 /* Update the system time and notify the system */
1563 KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL);
1564 PoNotifySystemTimeSet();
1565
1566 /* Remember this as the boot time */
1567 KeBootTime = UniversalBootTime;
1568 KeBootTimeBias = 0;
1569 }
1570
1571#ifdef CONFIG_SMP
1572 /*
1573 * IMPORTANT NOTE:
1574 * Because ReactOS is a "nice" OS, we do not care _at all_
1575 * about any number of registered/licensed processors:
1576 * no usage of KeRegisteredProcessors nor KeLicensedProcessors.
1577 */
1578 if (CommandLine)
1579 {
1580 PSTR Option;
1581
1582 /* Check for NUMPROC: maximum number of logical processors
1583 * that can be started (including dynamically) at run-time */
1584 Option = strstr(CommandLine, "NUMPROC");
1585 if (Option) Option = strstr(Option, "=");
1586 if (Option) KeNumprocSpecified = atol(Option + 1);
1587
1588 /* Check for BOOTPROC (NT6+ and ReactOS): maximum number
1589 * of logical processors that can be started at boot-time */
1590 Option = strstr(CommandLine, "BOOTPROC");
1591 if (Option) Option = strstr(Option, "=");
1592 if (Option) KeBootprocSpecified = atol(Option + 1);
1593
1594 /* Check for MAXPROC (NT6+ and ReactOS): forces the kernel to report
1595 * as existing the maximum number of processors that can be handled */
1596 if (strstr(CommandLine, "MAXPROC"))
1597 KeMaximumProcessors = MAXIMUM_PROCESSORS;
1598 }
1599
1600 /* Start Application Processors */
1601 KeStartAllProcessors();
1602#endif
1603
1604 /* Initialize all processors */
1605 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED);
1606
1607#ifdef CONFIG_SMP
1608 /* HACK: We should use RtlFindMessage and not only fallback to this */
1609 MpString = "MultiProcessor Kernel\r\n";
1610#endif
1611
1612 /* Setup the "MP" String */
1613 RtlInitAnsiString(&TempString, MpString);
1614
1615 /* Make sure to remove the \r\n if we actually have a string */
1616 while ((TempString.Length > 0) &&
1617 ((TempString.Buffer[TempString.Length - 1] == '\r') ||
1618 (TempString.Buffer[TempString.Length - 1] == '\n')))
1619 {
1620 /* Skip the trailing character */
1621 TempString.Length--;
1622 }
1623
1624 /* Get the information string from our resource file */
1625 MsgStatus = RtlFindMessage(NtosEntry->DllBase,
1626 RT_MESSAGETABLE,
1627 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
1628 KeNumberProcessors > 1 ?
1629 WINDOWS_NT_INFO_STRING_PLURAL :
1630 WINDOWS_NT_INFO_STRING,
1631 &MsgEntry);
1632
1633 /* Get total RAM size, in MiB */
1634 /* Round size up. Assumed to better match actual physical RAM size */
1635 Size = ALIGN_UP_BY(MmNumberOfPhysicalPages * PAGE_SIZE, 1024 * 1024) / (1024 * 1024);
1636
1637 /* Create the string */
1638 StringBuffer = InitBuffer->VersionBuffer;
1639 Status = RtlStringCbPrintfA(StringBuffer,
1640 sizeof(InitBuffer->VersionBuffer),
1641 NT_SUCCESS(MsgStatus) ?
1642 (PCHAR)MsgEntry->Text :
1643 "%u System Processor [%Iu MB Memory] %Z\r\n",
1644 KeNumberProcessors,
1645 Size,
1646 &TempString);
1647 if (!NT_SUCCESS(Status))
1648 {
1649 /* Bugcheck */
1650 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 4, 0, 0);
1651 }
1652
1653 /* Display RAM and CPU count */
1654 InbvDisplayString(StringBuffer);
1655
1656 /* Update the progress bar */
1657 InbvUpdateProgressBar(5);
1658
1659 /* Call OB initialization again */
1660 if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED);
1661
1662 /* Initialize Basic System Objects and Worker Threads */
1663 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 1, 0);
1664
1665 /* Initialize the later stages of the kernel */
1666 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 2, 0);
1667
1668 /* Call KD Providers at Phase 1 */
1669 if (!KdInitSystem(ExpInitializationPhase, KeLoaderBlock))
1670 {
1671 /* Failed, bugcheck */
1672 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 3, 0);
1673 }
1674
1675 /* Initialize the SRM in Phase 1 */
1676 if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED);
1677
1678 /* Update the progress bar */
1679 InbvUpdateProgressBar(10);
1680
1681 /* Create SystemRoot Link */
1682 Status = ExpCreateSystemRootLink(LoaderBlock);
1683 if (!NT_SUCCESS(Status))
1684 {
1685 /* Failed to create the system root link */
1686 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 0, 0, 0);
1687 }
1688
1689 /* Set up Region Maps, Sections and the Paging File */
1690 if (!MmInitSystem(1, LoaderBlock)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED);
1691
1692 /* Create NLS section */
1693 ExpInitNls(LoaderBlock);
1694
1695 /* Initialize Cache Views */
1696 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED);
1697
1698 /* Initialize the Registry */
1699 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED);
1700
1701 /* Initialize Prefetcher */
1702 CcPfInitializePrefetcher();
1703
1704 /* Update progress bar */
1705 InbvUpdateProgressBar(15);
1706
1707 /* Update timezone information */
1708 LastTzBias = ExpLastTimeZoneBias;
1709 ExRefreshTimeZoneInformation(&SystemBootTime);
1710
1711 /* Check if we're resetting timezone data */
1712 if (ResetBias)
1713 {
1714 /* Convert the local time to system time */
1715 ExLocalTimeToSystemTime(&SystemBootTime, &UniversalBootTime);
1716 KeBootTime = UniversalBootTime;
1717 KeBootTimeBias = 0;
1718
1719 /* Set the new time */
1720 KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL);
1721 }
1722 else
1723 {
1724 /* Check if the timezone switched and update the time */
1725 if (LastTzBias != ExpLastTimeZoneBias)
1726 ZwSetSystemTime(NULL, NULL);
1727 }
1728
1729 /* Initialize the File System Runtime Library */
1730 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED);
1731
1732 /* Initialize range lists */
1733 RtlInitializeRangeListPackage();
1734
1735 /* Report all resources used by HAL */
1736 HalReportResourceUsage();
1737
1738 /* Call the debugger DLL */
1739 KdDebuggerInitialize1(LoaderBlock);
1740
1741 /* Setup PnP Manager in phase 1 */
1742 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED);
1743
1744 /* Update progress bar */
1745 InbvUpdateProgressBar(20);
1746
1747 /* Initialize LPC */
1748 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED);
1749
1750 /* Make sure we have a command line */
1751 if (CommandLine)
1752 {
1753 /* Check if this is a safe mode boot */
1754 SafeBoot = strstr(CommandLine, "SAFEBOOT:");
1755 if (SafeBoot)
1756 {
1757 /* Check what kind of boot this is */
1758 SafeBoot += 9;
1759 if (!strncmp(SafeBoot, "MINIMAL", 7))
1760 {
1761 /* Minimal mode */
1762 InitSafeBootMode = 1;
1763 SafeBoot += 7;
1764 MessageCode = BOOTING_IN_SAFEMODE_MINIMAL;
1765 }
1766 else if (!strncmp(SafeBoot, "NETWORK", 7))
1767 {
1768 /* With Networking */
1769 InitSafeBootMode = 2;
1770 SafeBoot += 7;
1771 MessageCode = BOOTING_IN_SAFEMODE_NETWORK;
1772 }
1773 else if (!strncmp(SafeBoot, "DSREPAIR", 8))
1774 {
1775 /* Domain Server Repair */
1776 InitSafeBootMode = 3;
1777 SafeBoot += 8;
1778 MessageCode = BOOTING_IN_SAFEMODE_DSREPAIR;
1779
1780 }
1781 else
1782 {
1783 /* Invalid */
1784 InitSafeBootMode = 0;
1785 }
1786
1787 /* Check if there's any settings left */
1788 if (*SafeBoot)
1789 {
1790 /* Check if an alternate shell was requested */
1791 if (!strncmp(SafeBoot, "(ALTERNATESHELL)", 16))
1792 {
1793 /* Remember this for later */
1794 AlternateShell = TRUE;
1795 }
1796 }
1797
1798 /* Find the message to print out */
1799 Status = RtlFindMessage(NtosEntry->DllBase,
1800 RT_MESSAGETABLE,
1801 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
1802 MessageCode,
1803 &MsgEntry);
1804 if (NT_SUCCESS(Status))
1805 {
1806 /* Display it */
1807 InbvDisplayString((PCSTR)MsgEntry->Text);
1808 }
1809 }
1810 }
1811
1812 /* Make sure we have a command line */
1813 if (CommandLine)
1814 {
1815 /* Check if bootlogging is enabled */
1816 if (strstr(CommandLine, "BOOTLOG"))
1817 {
1818 /* Find the message to print out */
1819 Status = RtlFindMessage(NtosEntry->DllBase,
1820 RT_MESSAGETABLE,
1821 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
1822 BOOTLOG_ENABLED,
1823 &MsgEntry);
1824 if (NT_SUCCESS(Status))
1825 {
1826 /* Display it */
1827 InbvDisplayString((PCSTR)MsgEntry->Text);
1828 }
1829
1830 /* Setup boot logging */
1831 //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader);
1832 }
1833 }
1834
1835 /* Setup the Executive in Phase 2 */
1836 //ExInitSystemPhase2();
1837
1838 /* Update progress bar */
1839 InbvUpdateProgressBar(25);
1840
1841 /* No KD Time Slip is pending */
1842 KdpTimeSlipPending = 0;
1843
1844 /* Initialize in-place execution support */
1845 XIPInit(LoaderBlock);
1846
1847 /* Set maximum update to 75% */
1848 InbvSetProgressBarSubset(25, 75);
1849
1850 /* Initialize the I/O Subsystem */
1851 if (!IoInitSystem(LoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED);
1852
1853 /* Set maximum update to 100% */
1854 InbvSetProgressBarSubset(0, 100);
1855
1856 /* Are we in safe mode? */
1857 if (InitSafeBootMode)
1858 {
1859 /* Open the safe boot key */
1860 RtlInitUnicodeString(&KeyName,
1861 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1862 L"\\CONTROL\\SAFEBOOT");
1863 InitializeObjectAttributes(&ObjectAttributes,
1864 &KeyName,
1865 OBJ_CASE_INSENSITIVE,
1866 NULL,
1867 NULL);
1868 Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
1869 if (NT_SUCCESS(Status))
1870 {
1871 /* First check if we have an alternate shell */
1872 if (AlternateShell)
1873 {
1874 /* Make sure that the registry has one setup */
1875 RtlInitUnicodeString(&KeyName, L"AlternateShell");
1876 Status = NtQueryValueKey(KeyHandle,
1877 &KeyName,
1878 KeyValuePartialInformation,
1879 &KeyPartialInfo,
1880 sizeof(KeyPartialInfo),
1881 &Length);
1882 if (!(NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW))
1883 {
1884 AlternateShell = FALSE;
1885 }
1886 }
1887
1888 /* Create the option key */
1889 RtlInitUnicodeString(&KeyName, L"Option");
1890 InitializeObjectAttributes(&ObjectAttributes,
1891 &KeyName,
1892 OBJ_CASE_INSENSITIVE,
1893 KeyHandle,
1894 NULL);
1895 Status = ZwCreateKey(&OptionHandle,
1896 KEY_ALL_ACCESS,
1897 &ObjectAttributes,
1898 0,
1899 NULL,
1900 REG_OPTION_VOLATILE,
1901 &Disposition);
1902 NtClose(KeyHandle);
1903
1904 /* Check if the key create worked */
1905 if (NT_SUCCESS(Status))
1906 {
1907 /* Write the safe boot type */
1908 RtlInitUnicodeString(&KeyName, L"OptionValue");
1909 NtSetValueKey(OptionHandle,
1910 &KeyName,
1911 0,
1912 REG_DWORD,
1913 &InitSafeBootMode,
1914 sizeof(InitSafeBootMode));
1915
1916 /* Check if we have to use an alternate shell */
1917 if (AlternateShell)
1918 {
1919 /* Remember this for later */
1920 Disposition = TRUE;
1921 RtlInitUnicodeString(&KeyName, L"UseAlternateShell");
1922 NtSetValueKey(OptionHandle,
1923 &KeyName,
1924 0,
1925 REG_DWORD,
1926 &Disposition,
1927 sizeof(Disposition));
1928 }
1929
1930 /* Close the options key handle */
1931 NtClose(OptionHandle);
1932 }
1933 }
1934 }
1935
1936 /* Are we in Win PE mode? */
1937 if (InitIsWinPEMode)
1938 {
1939 /* Open the safe control key */
1940 RtlInitUnicodeString(&KeyName,
1941 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1942 L"\\CONTROL");
1943 InitializeObjectAttributes(&ObjectAttributes,
1944 &KeyName,
1945 OBJ_CASE_INSENSITIVE,
1946 NULL,
1947 NULL);
1948 Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
1949 if (!NT_SUCCESS(Status))
1950 {
1951 /* Bugcheck */
1952 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 6, 0, 0);
1953 }
1954
1955 /* Create the MiniNT key */
1956 RtlInitUnicodeString(&KeyName, L"MiniNT");
1957 InitializeObjectAttributes(&ObjectAttributes,
1958 &KeyName,
1959 OBJ_CASE_INSENSITIVE,
1960 KeyHandle,
1961 NULL);
1962 Status = ZwCreateKey(&OptionHandle,
1963 KEY_ALL_ACCESS,
1964 &ObjectAttributes,
1965 0,
1966 NULL,
1967 REG_OPTION_VOLATILE,
1968 &Disposition);
1969 if (!NT_SUCCESS(Status))
1970 {
1971 /* Bugcheck */
1972 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 6, 0, 0);
1973 }
1974
1975 /* Close the handles */
1976 NtClose(KeyHandle);
1977 NtClose(OptionHandle);
1978 }
1979
1980 /* FIXME: This doesn't do anything for now */
1981 MmArmInitSystem(2, LoaderBlock);
1982
1983 /* Update progress bar */
1984 InbvUpdateProgressBar(80);
1985
1986 /* Initialize VDM support */
1987#if defined(_M_IX86)
1988 KeI386VdmInitialize();
1989#endif
1990
1991 /* Initialize Power Subsystem in Phase 1*/
1992 if (!PoInitSystem(1)) KeBugCheck(INTERNAL_POWER_ERROR);
1993
1994 /* Update progress bar */
1995 InbvUpdateProgressBar(90);
1996
1997 /* Initialize the Process Manager at Phase 1 */
1998 if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
1999
2000 /* Make sure nobody touches the loader block again */
2001 if (LoaderBlock == KeLoaderBlock) KeLoaderBlock = NULL;
2002 MmFreeLoaderBlock(LoaderBlock);
2003 LoaderBlock = Context = NULL;
2004
2005 /* Initialize the SRM in phase 1 */
2006 if (!SeRmInitPhase1()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
2007
2008 /* Update progress bar */
2009 InbvUpdateProgressBar(100);
2010
2011 /* Clear the screen */
2012 if (InbvBootDriverInstalled) FinalizeBootLogo();
2013
2014 /* Allow strings to be displayed */
2015 InbvEnableDisplayString(TRUE);
2016
2017 /* Launch initial process */
2018 ProcessInfo = &InitBuffer->ProcessInfo;
2019 ExpLoadInitialProcess(InitBuffer, &ProcessParameters, &Environment);
2020
2021 /* Wait 5 seconds for initial process to initialize */
2022 Timeout.QuadPart = Int32x32To64(5, -10000000);
2023 Status = ZwWaitForSingleObject(ProcessInfo->ProcessHandle, FALSE, &Timeout);
2024 if (Status == STATUS_SUCCESS)
2025 {
2026 /* Failed, display error */
2027 DPRINT1("INIT: Session Manager terminated.\n");
2028
2029 /* Bugcheck the system if SMSS couldn't initialize */
2030 KeBugCheck(SESSION5_INITIALIZATION_FAILED);
2031 }
2032
2033 /* Close process handles */
2034 ZwClose(ProcessInfo->ThreadHandle);
2035 ZwClose(ProcessInfo->ProcessHandle);
2036
2037 /* Free the initial process environment */
2038 Size = 0;
2039 ZwFreeVirtualMemory(NtCurrentProcess(),
2040 (PVOID*)&Environment,
2041 &Size,
2042 MEM_RELEASE);
2043
2044 /* Free the initial process parameters */
2045 Size = 0;
2046 ZwFreeVirtualMemory(NtCurrentProcess(),
2047 (PVOID*)&ProcessParameters,
2048 &Size,
2049 MEM_RELEASE);
2050
2051 /* Increase init phase */
2052 ExpInitializationPhase++;
2053
2054 /* Free the boot buffer */
2055 ExFreePoolWithTag(InitBuffer, TAG_INIT);
2056}
2057
2058VOID
2059NTAPI
2060Phase1Initialization(IN PVOID Context)
2061{
2062 /* Do the .INIT part of Phase 1 which we can free later */
2063 Phase1InitializationDiscard(Context);
2064
2065 /* Jump into zero page thread */
2066 MmZeroPageThread();
2067}