xref: /reactos/ntoskrnl/ex/init.c (revision d1b3115a)
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 */
24 CODE_SEG("INIT")
25 BOOLEAN
26 NTAPI
27 MmArmInitSystem(
28     IN ULONG Phase,
29     IN PLOADER_PARAMETER_BLOCK LoaderBlock
30 );
31 
32 typedef 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 */
45 ULONG NtMajorVersion = VER_PRODUCTMAJORVERSION;
46 ULONG NtMinorVersion = VER_PRODUCTMINORVERSION;
47 #if DBG /* Checked Build */
48 ULONG NtBuildNumber = VER_PRODUCTBUILD | 0xC0000000;
49 #else   /* Free Build */
50 ULONG NtBuildNumber = VER_PRODUCTBUILD;
51 #endif
52 
53 /* NT System Info */
54 ULONG NtGlobalFlag = 0;
55 ULONG ExSuiteMask;
56 
57 /* Cm Version Info */
58 ULONG CmNtSpBuildNumber;
59 ULONG CmNtCSDVersion;
60 ULONG CmNtCSDReleaseType;
61 UNICODE_STRING CmVersionString;
62 UNICODE_STRING CmCSDVersionString;
63 
64 CHAR NtBuildLab[] = KERNEL_VERSION_BUILD_STR "."
65                     REACTOS_COMPILER_NAME "_" REACTOS_COMPILER_VERSION;
66 
67 /* Init flags and settings */
68 ULONG ExpInitializationPhase;
69 BOOLEAN ExpInTextModeSetup;
70 BOOLEAN IoRemoteBootClient;
71 ULONG InitSafeBootMode;
72 BOOLEAN InitIsWinPEMode, InitWinPEModeType;
73 BOOLEAN SosEnabled; // Used by driver.c!IopDisplayLoadingMessage()
74 
75 /* NT Boot Path */
76 UNICODE_STRING NtSystemRoot;
77 
78 /* NT Initial User Application */
79 WCHAR NtInitialUserProcessBuffer[128] = L"\\SystemRoot\\System32\\smss.exe";
80 ULONG NtInitialUserProcessBufferLength = sizeof(NtInitialUserProcessBuffer) -
81                                          sizeof(WCHAR);
82 ULONG NtInitialUserProcessBufferType = REG_SZ;
83 
84 /* Boot NLS information */
85 PVOID ExpNlsTableBase;
86 ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
87 ULONG ExpUnicodeCaseTableDataOffset;
88 NLSTABLEINFO ExpNlsTableInfo;
89 SIZE_T ExpNlsTableSize;
90 PVOID ExpNlsSectionPointer;
91 
92 /* CMOS Timer Sanity */
93 BOOLEAN ExCmosClockIsSane = TRUE;
94 BOOLEAN ExpRealTimeIsUniversal;
95 
96 /* FUNCTIONS ****************************************************************/
97 
98 CODE_SEG("INIT")
99 NTSTATUS
100 NTAPI
ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)101 ExpCreateSystemRootLink(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 
210 CODE_SEG("INIT")
211 VOID
212 NTAPI
ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)213 ExpInitNls(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 
386 CODE_SEG("INIT")
387 VOID
388 NTAPI
ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer,OUT PRTL_USER_PROCESS_PARAMETERS * ProcessParameters,OUT PCHAR * ProcessEnvironment)389 ExpLoadInitialProcess(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 
603 CODE_SEG("INIT")
604 ULONG
605 NTAPI
ExComputeTickCountMultiplier(IN ULONG ClockIncrement)606 ExComputeTickCountMultiplier(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 
636 CODE_SEG("INIT")
637 BOOLEAN
638 NTAPI
ExpInitSystemPhase0(VOID)639 ExpInitSystemPhase0(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 
660 CODE_SEG("INIT")
661 BOOLEAN
662 NTAPI
ExpInitSystemPhase1(VOID)663 ExpInitSystemPhase1(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 
741 CODE_SEG("INIT")
742 BOOLEAN
743 NTAPI
ExInitSystem(VOID)744 ExInitSystem(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 
767 CODE_SEG("INIT")
768 BOOLEAN
769 NTAPI
ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock)770 ExpIsLoaderValid(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 
793 CODE_SEG("INIT")
794 VOID
795 NTAPI
ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock)796 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
797 {
798     ULONG i = 0;
799     PLIST_ENTRY NextEntry;
800     ULONG Count, Length;
801     PWCHAR Name;
802     PLDR_DATA_TABLE_ENTRY LdrEntry;
803     CHAR NameBuffer[256];
804     STRING SymbolString;
805     NTSTATUS Status;
806 
807     /* Loop the driver list */
808     NextEntry = LoaderBlock->LoadOrderListHead.Flink;
809     while (NextEntry != &LoaderBlock->LoadOrderListHead)
810     {
811         /* Skip the first two images */
812         if (i >= 2)
813         {
814             /* Get the entry */
815             LdrEntry = CONTAINING_RECORD(NextEntry,
816                                          LDR_DATA_TABLE_ENTRY,
817                                          InLoadOrderLinks);
818             if (LdrEntry->FullDllName.Buffer[0] == L'\\')
819             {
820                 /* We have a name, read its data */
821                 Name = LdrEntry->FullDllName.Buffer;
822                 Length = LdrEntry->FullDllName.Length / sizeof(WCHAR);
823 
824                 /* Check if our buffer can hold it */
825                 if (sizeof(NameBuffer) < Length + sizeof(ANSI_NULL))
826                 {
827                     /* It's too long */
828                     Status = STATUS_BUFFER_OVERFLOW;
829                 }
830                 else
831                 {
832                     /* Copy the name */
833                     Count = 0;
834                     do
835                     {
836                         /* Copy the character */
837                         NameBuffer[Count++] = (CHAR)*Name++;
838                     } while (Count < Length);
839 
840                     /* Null-terminate */
841                     NameBuffer[Count] = ANSI_NULL;
842                     Status = STATUS_SUCCESS;
843                 }
844             }
845             else
846             {
847                 /* Safely print the string into our buffer */
848                 Status = RtlStringCbPrintfA(NameBuffer,
849                                             sizeof(NameBuffer),
850                                             "%S\\System32\\Drivers\\%wZ",
851                                             &SharedUserData->NtSystemRoot[2],
852                                             &LdrEntry->BaseDllName);
853             }
854 
855             /* Check if the buffer was ok */
856             if (NT_SUCCESS(Status))
857             {
858                 /* Initialize the STRING for the debugger */
859                 RtlInitString(&SymbolString, NameBuffer);
860 
861                 /* Load the symbols */
862                 DbgLoadImageSymbols(&SymbolString,
863                                     LdrEntry->DllBase,
864                                     (ULONG_PTR)PsGetCurrentProcessId());
865             }
866         }
867 
868         /* Go to the next entry */
869         i++;
870         NextEntry = NextEntry->Flink;
871     }
872 }
873 
874 CODE_SEG("INIT")
875 VOID
876 NTAPI
ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock,IN ULONG_PTR PagesToDestroy,IN TYPE_OF_MEMORY MemoryType)877 ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
878              IN ULONG_PTR PagesToDestroy,
879              IN TYPE_OF_MEMORY MemoryType)
880 {
881     PLIST_ENTRY ListEntry;
882     PMEMORY_ALLOCATION_DESCRIPTOR MemDescriptor;
883 
884     DPRINT1("Burn RAM amount: %lu pages\n", PagesToDestroy);
885 
886     /* Loop the memory descriptors, beginning at the end */
887     for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Blink;
888          ListEntry != &LoaderBlock->MemoryDescriptorListHead;
889          ListEntry = ListEntry->Blink)
890     {
891         /* Get the memory descriptor structure */
892         MemDescriptor = CONTAINING_RECORD(ListEntry,
893                                           MEMORY_ALLOCATION_DESCRIPTOR,
894                                           ListEntry);
895 
896         /* Is memory free there or is it temporary? */
897         if (MemDescriptor->MemoryType == LoaderFree ||
898             MemDescriptor->MemoryType == LoaderFirmwareTemporary)
899         {
900             /* Check if the descriptor has more pages than we want */
901             if (MemDescriptor->PageCount > PagesToDestroy)
902             {
903                 /* Change block's page count, ntoskrnl doesn't care much */
904                 MemDescriptor->PageCount -= PagesToDestroy;
905                 break;
906             }
907             else
908             {
909                 /* Change block type */
910                 MemDescriptor->MemoryType = MemoryType;
911                 PagesToDestroy -= MemDescriptor->PageCount;
912 
913                 /* Check if we are done */
914                 if (PagesToDestroy == 0) break;
915             }
916         }
917     }
918 }
919 
920 CODE_SEG("INIT")
921 VOID
922 NTAPI
ExpInitializeExecutive(IN ULONG Cpu,IN PLOADER_PARAMETER_BLOCK LoaderBlock)923 ExpInitializeExecutive(IN ULONG Cpu,
924                        IN PLOADER_PARAMETER_BLOCK LoaderBlock)
925 {
926     PNLS_DATA_BLOCK NlsData;
927     CHAR Buffer[256];
928     ANSI_STRING AnsiPath;
929     NTSTATUS Status;
930     PCHAR CommandLine, PerfMem;
931     ULONG PerfMemUsed;
932     PLDR_DATA_TABLE_ENTRY NtosEntry;
933     PMESSAGE_RESOURCE_ENTRY MsgEntry;
934     ANSI_STRING CSDString;
935     size_t Remaining = 0;
936     PCHAR RcEnd = NULL;
937     CHAR VersionBuffer[65];
938 
939     /* Validate Loader */
940     if (!ExpIsLoaderValid(LoaderBlock))
941     {
942         /* Invalid loader version */
943         KeBugCheckEx(MISMATCHED_HAL,
944                      3,
945                      LoaderBlock->Extension->Size,
946                      LoaderBlock->Extension->MajorVersion,
947                      LoaderBlock->Extension->MinorVersion);
948     }
949 
950     /* Initialize PRCB pool lookaside pointers */
951     ExInitPoolLookasidePointers();
952 
953     /* Check if this is an application CPU */
954     if (Cpu)
955     {
956         /* Then simply initialize it with HAL */
957         if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
958         {
959             /* Initialization failed */
960             KeBugCheck(HAL_INITIALIZATION_FAILED);
961         }
962 
963         /* We're done */
964         return;
965     }
966 
967     /* Assume no text-mode or remote boot */
968     ExpInTextModeSetup = FALSE;
969     IoRemoteBootClient = FALSE;
970 
971     /* Check if we have a setup loader block */
972     if (LoaderBlock->SetupLdrBlock)
973     {
974         /* Check if this is text-mode setup */
975         if (LoaderBlock->SetupLdrBlock->Flags & SETUPLDR_TEXT_MODE)
976             ExpInTextModeSetup = TRUE;
977 
978         /* Check if this is network boot */
979         if (LoaderBlock->SetupLdrBlock->Flags & SETUPLDR_REMOTE_BOOT)
980         {
981             /* Set variable */
982             IoRemoteBootClient = TRUE;
983 
984             /* Make sure we're actually booting off the network */
985             ASSERT(!_memicmp(LoaderBlock->ArcBootDeviceName, "net(0)", 6));
986         }
987     }
988 
989     /* Set phase to 0 */
990     ExpInitializationPhase = 0;
991 
992     /* Get boot command line */
993     CommandLine = LoaderBlock->LoadOptions;
994     if (CommandLine)
995     {
996         /* Upcase it for comparison and check if we're in performance mode */
997         _strupr(CommandLine);
998         PerfMem = strstr(CommandLine, "PERFMEM");
999         if (PerfMem)
1000         {
1001             /* Check if the user gave a number of bytes to use */
1002             PerfMem = strstr(PerfMem, "=");
1003             if (PerfMem)
1004             {
1005                 /* Read the number of pages we'll use */
1006                 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
1007                 if (PerfMemUsed)
1008                 {
1009                     /* FIXME: TODO */
1010                     DPRINT1("BBT performance mode not yet supported."
1011                             "/PERFMEM option ignored.\n");
1012                 }
1013             }
1014         }
1015 
1016         /* Check if we're burning memory */
1017         PerfMem = strstr(CommandLine, "BURNMEMORY");
1018         if (PerfMem)
1019         {
1020             /* Check if the user gave a number of bytes to use */
1021             PerfMem = strstr(PerfMem, "=");
1022             if (PerfMem)
1023             {
1024                 /* Read the number of pages we'll use */
1025                 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
1026                 if (PerfMemUsed) ExBurnMemory(LoaderBlock, PerfMemUsed, LoaderBad);
1027             }
1028         }
1029     }
1030 
1031     /* Setup NLS Base and offsets */
1032     NlsData = LoaderBlock->NlsData;
1033     ExpNlsTableBase = NlsData->AnsiCodePageData;
1034     ExpAnsiCodePageDataOffset = 0;
1035     ExpOemCodePageDataOffset = (ULONG)((ULONG_PTR)NlsData->OemCodePageData -
1036                                        (ULONG_PTR)NlsData->AnsiCodePageData);
1037     ExpUnicodeCaseTableDataOffset = (ULONG)((ULONG_PTR)NlsData->UnicodeCodePageData -
1038                                             (ULONG_PTR)NlsData->AnsiCodePageData);
1039 
1040     /* Initialize the NLS Tables */
1041     RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
1042                              ExpAnsiCodePageDataOffset),
1043                      (PVOID)((ULONG_PTR)ExpNlsTableBase +
1044                              ExpOemCodePageDataOffset),
1045                      (PVOID)((ULONG_PTR)ExpNlsTableBase +
1046                              ExpUnicodeCaseTableDataOffset),
1047                      &ExpNlsTableInfo);
1048     RtlResetRtlTranslations(&ExpNlsTableInfo);
1049 
1050     /* Now initialize the HAL */
1051     if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
1052     {
1053         /* HAL failed to initialize, bugcheck */
1054         KeBugCheck(HAL_INITIALIZATION_FAILED);
1055     }
1056 
1057     /* Make sure interrupts are active now */
1058     _enable();
1059 
1060     /* Clear the crypto exponent */
1061     SharedUserData->CryptoExponent = 0;
1062 
1063     /* Set global flags for the checked build */
1064 #if DBG
1065     NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS |
1066                     FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
1067 #endif
1068 
1069     /* Setup NT System Root Path */
1070     sprintf(Buffer, "C:%s", LoaderBlock->NtBootPathName);
1071 
1072     /* Convert to ANSI_STRING and null-terminate it */
1073     RtlInitString(&AnsiPath, Buffer);
1074     Buffer[--AnsiPath.Length] = ANSI_NULL;
1075 
1076     /* Get the string from KUSER_SHARED_DATA's buffer */
1077     RtlInitEmptyUnicodeString(&NtSystemRoot,
1078                               SharedUserData->NtSystemRoot,
1079                               sizeof(SharedUserData->NtSystemRoot));
1080 
1081     /* Now fill it in */
1082     Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
1083     if (!NT_SUCCESS(Status)) KeBugCheck(SESSION3_INITIALIZATION_FAILED);
1084 
1085     /* Setup bugcheck messages */
1086     KiInitializeBugCheck();
1087 
1088     /* Setup initial system settings */
1089     CmGetSystemControlValues(LoaderBlock->RegistryBase, CmControlVector);
1090 
1091     /* Set the Service Pack Number and add it to the CSD Version number if needed */
1092     CmNtSpBuildNumber = VER_PRODUCTBUILD_QFE;
1093     if (((CmNtCSDVersion & 0xFFFF0000) == 0) && (CmNtCSDReleaseType == 1))
1094     {
1095         CmNtCSDVersion |= (VER_PRODUCTBUILD_QFE << 16);
1096     }
1097 
1098     /* Add loaded CmNtGlobalFlag value */
1099     NtGlobalFlag |= CmNtGlobalFlag;
1100 
1101     /* Initialize the executive at phase 0 */
1102     if (!ExInitSystem()) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
1103 
1104     /* Initialize the memory manager at phase 0 */
1105     if (!MmArmInitSystem(0, LoaderBlock)) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
1106 
1107     /* Load boot symbols */
1108     ExpLoadBootSymbols(LoaderBlock);
1109 
1110     /* Check if we should break after symbol load */
1111     if (KdBreakAfterSymbolLoad) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
1112 
1113     /* Check if this loader is compatible with NT 5.2 */
1114     if (LoaderBlock->Extension->Size >= sizeof(LOADER_PARAMETER_EXTENSION))
1115     {
1116         /* Setup headless terminal settings */
1117         HeadlessInit(LoaderBlock);
1118     }
1119 
1120     /* Set system ranges */
1121 #ifdef _M_AMD64
1122     SharedUserData->Reserved1 = MM_HIGHEST_USER_ADDRESS_WOW64;
1123     SharedUserData->Reserved3 = MM_SYSTEM_RANGE_START_WOW64;
1124 #else
1125     SharedUserData->Reserved1 = (ULONG_PTR)MmHighestUserAddress;
1126     SharedUserData->Reserved3 = (ULONG_PTR)MmSystemRangeStart;
1127 #endif
1128 
1129     /* Make a copy of the NLS Tables */
1130     ExpInitNls(LoaderBlock);
1131 
1132     /* Get the kernel's load entry */
1133     NtosEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
1134                                   LDR_DATA_TABLE_ENTRY,
1135                                   InLoadOrderLinks);
1136 
1137     /* Check if this is a service pack */
1138     if (CmNtCSDVersion & 0xFFFF)
1139     {
1140         /* Get the service pack string */
1141         Status = RtlFindMessage(NtosEntry->DllBase,
1142                                 11,
1143                                 0,
1144                                 WINDOWS_NT_CSD_STRING,
1145                                 &MsgEntry);
1146         if (NT_SUCCESS(Status))
1147         {
1148             /* Setup the string */
1149             RtlInitAnsiString(&CSDString, (PCHAR)MsgEntry->Text);
1150 
1151             /* Remove trailing newline */
1152             while ((CSDString.Length > 0) &&
1153                    ((CSDString.Buffer[CSDString.Length - 1] == '\r') ||
1154                     (CSDString.Buffer[CSDString.Length - 1] == '\n')))
1155             {
1156                 /* Skip the trailing character */
1157                 CSDString.Length--;
1158             }
1159 
1160             /* Fill the buffer with version information */
1161             Status = RtlStringCbPrintfA(Buffer,
1162                                         sizeof(Buffer),
1163                                         "%Z %u%c",
1164                                         &CSDString,
1165                                         (CmNtCSDVersion & 0xFF00) >> 8,
1166                                         (CmNtCSDVersion & 0xFF) ?
1167                                         'A' + (CmNtCSDVersion & 0xFF) - 1 :
1168                                         ANSI_NULL);
1169         }
1170         else
1171         {
1172             /* Build default string */
1173             Status = RtlStringCbPrintfA(Buffer,
1174                                         sizeof(Buffer),
1175                                         "CSD %04x",
1176                                         CmNtCSDVersion);
1177         }
1178 
1179         /* Check for success */
1180         if (!NT_SUCCESS(Status))
1181         {
1182             /* Fail */
1183             KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1184         }
1185     }
1186     else
1187     {
1188         /* Then this is a beta */
1189         Status = RtlStringCbCopyExA(Buffer,
1190                                     sizeof(Buffer),
1191                                     VER_PRODUCTBETA_STR,
1192                                     NULL,
1193                                     &Remaining,
1194                                     0);
1195         if (!NT_SUCCESS(Status))
1196         {
1197             /* Fail */
1198             KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1199         }
1200 
1201         /* Update length */
1202         CmCSDVersionString.MaximumLength = sizeof(Buffer) - (USHORT)Remaining;
1203     }
1204 
1205     /* Check if we have an RC number */
1206     if ((CmNtCSDVersion & 0xFFFF0000) && (CmNtCSDReleaseType == 1))
1207     {
1208         /* Check if we have no version data yet */
1209         if (!(*Buffer))
1210         {
1211             /* Set defaults */
1212             Remaining = sizeof(Buffer);
1213             RcEnd = Buffer;
1214         }
1215         else
1216         {
1217             /* Add comma and space */
1218             Status = RtlStringCbCatExA(Buffer,
1219                                        sizeof(Buffer),
1220                                        ", ",
1221                                        &RcEnd,
1222                                        &Remaining,
1223                                        0);
1224             if (!NT_SUCCESS(Status))
1225             {
1226                 /* Fail */
1227                 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1228             }
1229         }
1230 
1231         /* Add the version format string */
1232         Status = RtlStringCbPrintfA(RcEnd,
1233                                     Remaining,
1234                                     "v.%u",
1235                                     (CmNtCSDVersion & 0xFFFF0000) >> 16);
1236         if (!NT_SUCCESS(Status))
1237         {
1238             /* Fail */
1239             KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1240         }
1241     }
1242 
1243     /* Now setup the final string */
1244     RtlInitAnsiString(&CSDString, Buffer);
1245     Status = RtlAnsiStringToUnicodeString(&CmCSDVersionString,
1246                                           &CSDString,
1247                                           TRUE);
1248     if (!NT_SUCCESS(Status))
1249     {
1250         /* Fail */
1251         KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1252     }
1253 
1254     /* Add our version */
1255     Status = RtlStringCbPrintfA(VersionBuffer,
1256                                 sizeof(VersionBuffer),
1257                                 "%u.%u",
1258                                 VER_PRODUCTMAJORVERSION,
1259                                 VER_PRODUCTMINORVERSION);
1260     if (!NT_SUCCESS(Status))
1261     {
1262         /* Fail */
1263         KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0);
1264     }
1265 
1266     /* Build the final version string */
1267     RtlCreateUnicodeStringFromAsciiz(&CmVersionString, VersionBuffer);
1268 
1269     /* Check if the user wants a kernel stack trace database */
1270     if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB)
1271     {
1272         /* FIXME: TODO */
1273         DPRINT1("Kernel-mode stack trace support not yet present."
1274                 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
1275     }
1276 
1277     /* Check if he wanted exception logging */
1278     if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING)
1279     {
1280         /* FIXME: TODO */
1281         DPRINT1("Kernel-mode exception logging support not yet present."
1282                 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
1283     }
1284 
1285     /* Initialize the Handle Table */
1286     ExpInitializeHandleTables();
1287 
1288 #if DBG
1289     /* On checked builds, allocate the system call count table */
1290     KeServiceDescriptorTable[0].Count =
1291         ExAllocatePoolWithTag(NonPagedPool,
1292                               KiServiceLimit * sizeof(ULONG),
1293                               'llaC');
1294 
1295     /* Use it for the shadow table too */
1296     KeServiceDescriptorTableShadow[0].Count = KeServiceDescriptorTable[0].Count;
1297 
1298     /* Make sure allocation succeeded */
1299     if (KeServiceDescriptorTable[0].Count)
1300     {
1301         /* Zero the call counts to 0 */
1302         RtlZeroMemory(KeServiceDescriptorTable[0].Count,
1303                       KiServiceLimit * sizeof(ULONG));
1304     }
1305 #endif
1306 
1307     /* Create the Basic Object Manager Types to allow new Object Types */
1308     if (!ObInitSystem()) KeBugCheck(OBJECT_INITIALIZATION_FAILED);
1309 
1310     /* Load basic Security for other Managers */
1311     if (!SeInitSystem()) KeBugCheck(SECURITY_INITIALIZATION_FAILED);
1312 
1313     /* Initialize the Process Manager */
1314     if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS_INITIALIZATION_FAILED);
1315 
1316     /* Initialize the PnP Manager */
1317     if (!PpInitSystem()) KeBugCheck(PP0_INITIALIZATION_FAILED);
1318 
1319     /* Initialize the User-Mode Debugging Subsystem */
1320     DbgkInitialize();
1321 
1322     /* Calculate the tick count multiplier */
1323     ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement);
1324     SharedUserData->TickCountMultiplier = ExpTickCountMultiplier;
1325 
1326     /* Set the OS Version */
1327     SharedUserData->NtMajorVersion = NtMajorVersion;
1328     SharedUserData->NtMinorVersion = NtMinorVersion;
1329 
1330     /* Set the machine type */
1331     SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_NATIVE;
1332     SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_NATIVE;
1333 }
1334 
1335 VOID
1336 NTAPI
1337 MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock);
1338 
1339 CODE_SEG("INIT")
1340 VOID
1341 NTAPI
Phase1InitializationDiscard(IN PVOID Context)1342 Phase1InitializationDiscard(IN PVOID Context)
1343 {
1344     PLOADER_PARAMETER_BLOCK LoaderBlock = Context;
1345     NTSTATUS Status, MsgStatus;
1346     TIME_FIELDS TimeFields;
1347     LARGE_INTEGER SystemBootTime, UniversalBootTime, OldTime, Timeout;
1348     BOOLEAN NoGuiBoot, ResetBias = FALSE, AlternateShell = FALSE;
1349     PLDR_DATA_TABLE_ENTRY NtosEntry;
1350     PMESSAGE_RESOURCE_ENTRY MsgEntry;
1351     PCHAR CommandLine, Y2KHackRequired, SafeBoot, Environment;
1352     PCHAR StringBuffer, EndBuffer, BeginBuffer, MpString = "";
1353     PINIT_BUFFER InitBuffer;
1354     ANSI_STRING TempString;
1355     ULONG LastTzBias, Length, YearHack = 0, Disposition, MessageCode = 0;
1356     SIZE_T Size;
1357     size_t Remaining;
1358     PRTL_USER_PROCESS_INFORMATION ProcessInfo;
1359     KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo;
1360     UNICODE_STRING KeyName;
1361     OBJECT_ATTRIBUTES ObjectAttributes;
1362     HANDLE KeyHandle, OptionHandle;
1363     PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
1364 
1365     /* Allocate the initialization buffer */
1366     InitBuffer = ExAllocatePoolWithTag(NonPagedPool,
1367                                        sizeof(INIT_BUFFER),
1368                                        TAG_INIT);
1369     if (!InitBuffer)
1370     {
1371         /* Bugcheck */
1372         KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 8, 0, 0);
1373     }
1374 
1375     /* Set to phase 1 */
1376     ExpInitializationPhase = 1;
1377 
1378     /* Set us at maximum priority */
1379     KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY);
1380 
1381     /* Do Phase 1 HAL Initialization */
1382     if (!HalInitSystem(1, LoaderBlock)) KeBugCheck(HAL1_INITIALIZATION_FAILED);
1383 
1384     /* Get the command line and upcase it */
1385     CommandLine = (LoaderBlock->LoadOptions ? _strupr(LoaderBlock->LoadOptions) : NULL);
1386 
1387     /* Check if GUI Boot is enabled */
1388     NoGuiBoot = (CommandLine && strstr(CommandLine, "NOGUIBOOT") != NULL);
1389 
1390     /* Get the SOS setting */
1391     SosEnabled = (CommandLine && strstr(CommandLine, "SOS") != NULL);
1392 
1393     /* Setup the boot video driver */
1394     InbvEnableBootDriver(!NoGuiBoot);
1395     InbvDriverInitialize(LoaderBlock, IDB_MAX_RESOURCES);
1396 
1397     /* Check if GUI boot is enabled */
1398     if (!NoGuiBoot)
1399     {
1400         /* It is, display the boot logo and enable printing strings */
1401         InbvEnableDisplayString(SosEnabled);
1402         DisplayBootBitmap(SosEnabled);
1403     }
1404     else
1405     {
1406         /* Release display ownership if not using GUI boot */
1407         InbvNotifyDisplayOwnershipLost(NULL);
1408 
1409         /* Don't allow boot-time strings */
1410         InbvEnableDisplayString(FALSE);
1411     }
1412 
1413     /* Check if this is LiveCD (WinPE) mode */
1414     if (CommandLine && strstr(CommandLine, "MININT") != NULL)
1415     {
1416         /* Setup WinPE Settings */
1417         InitIsWinPEMode = TRUE;
1418         InitWinPEModeType |= (strstr(CommandLine, "INRAM") != NULL) ? 0x80000000 : 0x00000001;
1419     }
1420 
1421     /* Get the kernel's load entry */
1422     NtosEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
1423                                   LDR_DATA_TABLE_ENTRY,
1424                                   InLoadOrderLinks);
1425 
1426     /* Find the banner message */
1427     MsgStatus = RtlFindMessage(NtosEntry->DllBase,
1428                                11,
1429                                0,
1430                                WINDOWS_NT_BANNER,
1431                                &MsgEntry);
1432 
1433     /* Setup defaults and check if we have a version string */
1434     StringBuffer = InitBuffer->VersionBuffer;
1435     BeginBuffer = StringBuffer;
1436     EndBuffer = StringBuffer;
1437     Remaining = sizeof(InitBuffer->VersionBuffer);
1438     if (CmCSDVersionString.Length)
1439     {
1440         /* Print the version string */
1441         Status = RtlStringCbPrintfExA(StringBuffer,
1442                                       Remaining,
1443                                       &EndBuffer,
1444                                       &Remaining,
1445                                       0,
1446                                       ": %wZ",
1447                                       &CmCSDVersionString);
1448         if (!NT_SUCCESS(Status))
1449         {
1450             /* Bugcheck */
1451             KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1452         }
1453     }
1454     else
1455     {
1456         /* No version */
1457         *EndBuffer = ANSI_NULL; /* Null-terminate the string */
1458     }
1459 
1460     /* Skip over the null-terminator to start a new string */
1461     ++EndBuffer;
1462     --Remaining;
1463 
1464     /* Build the version number */
1465     StringBuffer = InitBuffer->VersionNumber;
1466     Status = RtlStringCbPrintfA(StringBuffer,
1467                                 sizeof(InitBuffer->VersionNumber),
1468                                 "%u.%u",
1469                                 VER_PRODUCTMAJORVERSION,
1470                                 VER_PRODUCTMINORVERSION);
1471     if (!NT_SUCCESS(Status))
1472     {
1473         /* Bugcheck */
1474         KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1475     }
1476 
1477     /* Check if we had found a banner message */
1478     if (NT_SUCCESS(MsgStatus))
1479     {
1480         /* Create the banner message */
1481         /* ReactOS specific: Report ReactOS version, NtBuildLab information and reported NT kernel version */
1482         Status = RtlStringCbPrintfA(EndBuffer,
1483                                     Remaining,
1484                                     (PCHAR)MsgEntry->Text,
1485                                     KERNEL_VERSION_STR,
1486                                     NtBuildLab,
1487                                     StringBuffer,
1488                                     NtBuildNumber & 0xFFFF,
1489                                     BeginBuffer);
1490         if (!NT_SUCCESS(Status))
1491         {
1492             /* Bugcheck */
1493             KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1494         }
1495     }
1496     else
1497     {
1498         /* Use hard-coded banner message */
1499         Status = RtlStringCbCopyA(EndBuffer, Remaining, "REACTOS (R)\r\n");
1500         if (!NT_SUCCESS(Status))
1501         {
1502             /* Bugcheck */
1503             KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1504         }
1505     }
1506 
1507     /* Display the version string on-screen */
1508     InbvDisplayString(EndBuffer);
1509 
1510     /* Initialize Power Subsystem in Phase 0 */
1511     if (!PoInitSystem(0)) KeBugCheck(INTERNAL_POWER_ERROR);
1512 
1513     /* Check for Y2K hack */
1514     Y2KHackRequired = CommandLine ? strstr(CommandLine, "YEAR") : NULL;
1515     if (Y2KHackRequired) Y2KHackRequired = strstr(Y2KHackRequired, "=");
1516     if (Y2KHackRequired) YearHack = atol(Y2KHackRequired + 1);
1517 
1518     /* Query the clock */
1519     if ((ExCmosClockIsSane) && (HalQueryRealTimeClock(&TimeFields)))
1520     {
1521         /* Check if we're using the Y2K hack */
1522         if (Y2KHackRequired) TimeFields.Year = (CSHORT)YearHack;
1523 
1524         /* Convert to time fields */
1525         RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
1526         UniversalBootTime = SystemBootTime;
1527 
1528         /* Check if real time is GMT */
1529         if (!ExpRealTimeIsUniversal)
1530         {
1531             /* Check if we don't have a valid bias */
1532             if (ExpLastTimeZoneBias == MAXULONG)
1533             {
1534                 /* Reset */
1535                 ResetBias = TRUE;
1536                 ExpLastTimeZoneBias = ExpAltTimeZoneBias;
1537             }
1538 
1539             /* Calculate the bias in seconds */
1540             ExpTimeZoneBias.QuadPart = Int32x32To64(ExpLastTimeZoneBias * 60,
1541                                                     10000000);
1542 
1543             /* Set the boot time-zone bias */
1544             SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
1545             SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
1546             SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
1547 
1548             /* Convert the boot time to local time, and set it */
1549             UniversalBootTime.QuadPart = SystemBootTime.QuadPart +
1550                                          ExpTimeZoneBias.QuadPart;
1551         }
1552 
1553         /* Update the system time and notify the system */
1554         KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL);
1555         PoNotifySystemTimeSet();
1556 
1557         /* Remember this as the boot time */
1558         KeBootTime = UniversalBootTime;
1559         KeBootTimeBias = 0;
1560     }
1561 
1562 #ifdef CONFIG_SMP
1563     /* Start Application Processors */
1564     KeStartAllProcessors();
1565 #endif
1566 
1567     /* Initialize all processors */
1568     if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED);
1569 
1570 #ifdef CONFIG_SMP
1571     /* HACK: We should use RtlFindMessage and not only fallback to this */
1572     MpString = "MultiProcessor Kernel\r\n";
1573 #endif
1574 
1575     /* Setup the "MP" String */
1576     RtlInitAnsiString(&TempString, MpString);
1577 
1578     /* Make sure to remove the \r\n if we actually have a string */
1579     while ((TempString.Length > 0) &&
1580            ((TempString.Buffer[TempString.Length - 1] == '\r') ||
1581             (TempString.Buffer[TempString.Length - 1] == '\n')))
1582     {
1583         /* Skip the trailing character */
1584         TempString.Length--;
1585     }
1586 
1587     /* Get the information string from our resource file */
1588     MsgStatus = RtlFindMessage(NtosEntry->DllBase,
1589                                11,
1590                                0,
1591                                KeNumberProcessors > 1 ?
1592                                WINDOWS_NT_INFO_STRING_PLURAL :
1593                                WINDOWS_NT_INFO_STRING,
1594                                &MsgEntry);
1595 
1596     /* Get total RAM size, in MiB */
1597     /* Round size up. Assumed to better match actual physical RAM size */
1598     Size = ALIGN_UP_BY(MmNumberOfPhysicalPages * PAGE_SIZE, 1024 * 1024) / (1024 * 1024);
1599 
1600     /* Create the string */
1601     StringBuffer = InitBuffer->VersionBuffer;
1602     Status = RtlStringCbPrintfA(StringBuffer,
1603                                 sizeof(InitBuffer->VersionBuffer),
1604                                 NT_SUCCESS(MsgStatus) ?
1605                                 (PCHAR)MsgEntry->Text :
1606                                 "%u System Processor [%Iu MB Memory] %Z\r\n",
1607                                 KeNumberProcessors,
1608                                 Size,
1609                                 &TempString);
1610     if (!NT_SUCCESS(Status))
1611     {
1612         /* Bugcheck */
1613         KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 4, 0, 0);
1614     }
1615 
1616     /* Display RAM and CPU count */
1617     InbvDisplayString(StringBuffer);
1618 
1619     /* Update the progress bar */
1620     InbvUpdateProgressBar(5);
1621 
1622     /* Call OB initialization again */
1623     if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED);
1624 
1625     /* Initialize Basic System Objects and Worker Threads */
1626     if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 1, 0);
1627 
1628     /* Initialize the later stages of the kernel */
1629     if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 2, 0);
1630 
1631     /* Call KD Providers at Phase 1 */
1632     if (!KdInitSystem(ExpInitializationPhase, KeLoaderBlock))
1633     {
1634         /* Failed, bugcheck */
1635         KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 3, 0);
1636     }
1637 
1638     /* Initialize the SRM in Phase 1 */
1639     if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED);
1640 
1641     /* Update the progress bar */
1642     InbvUpdateProgressBar(10);
1643 
1644     /* Create SystemRoot Link */
1645     Status = ExpCreateSystemRootLink(LoaderBlock);
1646     if (!NT_SUCCESS(Status))
1647     {
1648         /* Failed to create the system root link */
1649         KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 0, 0, 0);
1650     }
1651 
1652     /* Set up Region Maps, Sections and the Paging File */
1653     if (!MmInitSystem(1, LoaderBlock)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED);
1654 
1655     /* Create NLS section */
1656     ExpInitNls(LoaderBlock);
1657 
1658     /* Initialize Cache Views */
1659     if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED);
1660 
1661     /* Initialize the Registry */
1662     if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED);
1663 
1664     /* Initialize Prefetcher */
1665     CcPfInitializePrefetcher();
1666 
1667     /* Update progress bar */
1668     InbvUpdateProgressBar(15);
1669 
1670     /* Update timezone information */
1671     LastTzBias = ExpLastTimeZoneBias;
1672     ExRefreshTimeZoneInformation(&SystemBootTime);
1673 
1674     /* Check if we're resetting timezone data */
1675     if (ResetBias)
1676     {
1677         /* Convert the local time to system time */
1678         ExLocalTimeToSystemTime(&SystemBootTime, &UniversalBootTime);
1679         KeBootTime = UniversalBootTime;
1680         KeBootTimeBias = 0;
1681 
1682         /* Set the new time */
1683         KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL);
1684     }
1685     else
1686     {
1687         /* Check if the timezone switched and update the time */
1688         if (LastTzBias != ExpLastTimeZoneBias)
1689             ZwSetSystemTime(NULL, NULL);
1690     }
1691 
1692     /* Initialize the File System Runtime Library */
1693     if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED);
1694 
1695     /* Initialize range lists */
1696     RtlInitializeRangeListPackage();
1697 
1698     /* Report all resources used by HAL */
1699     HalReportResourceUsage();
1700 
1701     /* Call the debugger DLL */
1702     KdDebuggerInitialize1(LoaderBlock);
1703 
1704     /* Setup PnP Manager in phase 1 */
1705     if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED);
1706 
1707     /* Update progress bar */
1708     InbvUpdateProgressBar(20);
1709 
1710     /* Initialize LPC */
1711     if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED);
1712 
1713     /* Make sure we have a command line */
1714     if (CommandLine)
1715     {
1716         /* Check if this is a safe mode boot */
1717         SafeBoot = strstr(CommandLine, "SAFEBOOT:");
1718         if (SafeBoot)
1719         {
1720             /* Check what kind of boot this is */
1721             SafeBoot += 9;
1722             if (!strncmp(SafeBoot, "MINIMAL", 7))
1723             {
1724                 /* Minimal mode */
1725                 InitSafeBootMode = 1;
1726                 SafeBoot += 7;
1727                 MessageCode = BOOTING_IN_SAFEMODE_MINIMAL;
1728             }
1729             else if (!strncmp(SafeBoot, "NETWORK", 7))
1730             {
1731                 /* With Networking */
1732                 InitSafeBootMode = 2;
1733                 SafeBoot += 7;
1734                 MessageCode = BOOTING_IN_SAFEMODE_NETWORK;
1735             }
1736             else if (!strncmp(SafeBoot, "DSREPAIR", 8))
1737             {
1738                 /* Domain Server Repair */
1739                 InitSafeBootMode = 3;
1740                 SafeBoot += 8;
1741                 MessageCode = BOOTING_IN_SAFEMODE_DSREPAIR;
1742 
1743             }
1744             else
1745             {
1746                 /* Invalid */
1747                 InitSafeBootMode = 0;
1748             }
1749 
1750             /* Check if there's any settings left */
1751             if (*SafeBoot)
1752             {
1753                 /* Check if an alternate shell was requested */
1754                 if (!strncmp(SafeBoot, "(ALTERNATESHELL)", 16))
1755                 {
1756                     /* Remember this for later */
1757                     AlternateShell = TRUE;
1758                 }
1759             }
1760 
1761             /* Find the message to print out */
1762             Status = RtlFindMessage(NtosEntry->DllBase,
1763                                     11,
1764                                     0,
1765                                     MessageCode,
1766                                     &MsgEntry);
1767             if (NT_SUCCESS(Status))
1768             {
1769                 /* Display it */
1770                 InbvDisplayString((PCHAR)MsgEntry->Text);
1771             }
1772         }
1773     }
1774 
1775     /* Make sure we have a command line */
1776     if (CommandLine)
1777     {
1778         /* Check if bootlogging is enabled */
1779         if (strstr(CommandLine, "BOOTLOG"))
1780         {
1781             /* Find the message to print out */
1782             Status = RtlFindMessage(NtosEntry->DllBase,
1783                                     11,
1784                                     0,
1785                                     BOOTLOG_ENABLED,
1786                                     &MsgEntry);
1787             if (NT_SUCCESS(Status))
1788             {
1789                 /* Display it */
1790                 InbvDisplayString((PCHAR)MsgEntry->Text);
1791             }
1792 
1793             /* Setup boot logging */
1794             //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader);
1795         }
1796     }
1797 
1798     /* Setup the Executive in Phase 2 */
1799     //ExInitSystemPhase2();
1800 
1801     /* Update progress bar */
1802     InbvUpdateProgressBar(25);
1803 
1804     /* No KD Time Slip is pending */
1805     KdpTimeSlipPending = 0;
1806 
1807     /* Initialize in-place execution support */
1808     XIPInit(LoaderBlock);
1809 
1810     /* Set maximum update to 75% */
1811     InbvSetProgressBarSubset(25, 75);
1812 
1813     /* Initialize the I/O Subsystem */
1814     if (!IoInitSystem(LoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED);
1815 
1816     /* Set maximum update to 100% */
1817     InbvSetProgressBarSubset(0, 100);
1818 
1819     /* Are we in safe mode? */
1820     if (InitSafeBootMode)
1821     {
1822         /* Open the safe boot key */
1823         RtlInitUnicodeString(&KeyName,
1824                              L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1825                              L"\\CONTROL\\SAFEBOOT");
1826         InitializeObjectAttributes(&ObjectAttributes,
1827                                    &KeyName,
1828                                    OBJ_CASE_INSENSITIVE,
1829                                    NULL,
1830                                    NULL);
1831         Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
1832         if (NT_SUCCESS(Status))
1833         {
1834             /* First check if we have an alternate shell */
1835             if (AlternateShell)
1836             {
1837                 /* Make sure that the registry has one setup */
1838                 RtlInitUnicodeString(&KeyName, L"AlternateShell");
1839                 Status = NtQueryValueKey(KeyHandle,
1840                                          &KeyName,
1841                                          KeyValuePartialInformation,
1842                                          &KeyPartialInfo,
1843                                          sizeof(KeyPartialInfo),
1844                                          &Length);
1845                 if (!(NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW))
1846                 {
1847                     AlternateShell = FALSE;
1848                 }
1849             }
1850 
1851             /* Create the option key */
1852             RtlInitUnicodeString(&KeyName, L"Option");
1853             InitializeObjectAttributes(&ObjectAttributes,
1854                                        &KeyName,
1855                                        OBJ_CASE_INSENSITIVE,
1856                                        KeyHandle,
1857                                        NULL);
1858             Status = ZwCreateKey(&OptionHandle,
1859                                  KEY_ALL_ACCESS,
1860                                  &ObjectAttributes,
1861                                  0,
1862                                  NULL,
1863                                  REG_OPTION_VOLATILE,
1864                                  &Disposition);
1865             NtClose(KeyHandle);
1866 
1867             /* Check if the key create worked */
1868             if (NT_SUCCESS(Status))
1869             {
1870                 /* Write the safe boot type */
1871                 RtlInitUnicodeString(&KeyName, L"OptionValue");
1872                 NtSetValueKey(OptionHandle,
1873                               &KeyName,
1874                               0,
1875                               REG_DWORD,
1876                               &InitSafeBootMode,
1877                               sizeof(InitSafeBootMode));
1878 
1879                 /* Check if we have to use an alternate shell */
1880                 if (AlternateShell)
1881                 {
1882                     /* Remember this for later */
1883                     Disposition = TRUE;
1884                     RtlInitUnicodeString(&KeyName, L"UseAlternateShell");
1885                     NtSetValueKey(OptionHandle,
1886                                   &KeyName,
1887                                   0,
1888                                   REG_DWORD,
1889                                   &Disposition,
1890                                   sizeof(Disposition));
1891                 }
1892 
1893                 /* Close the options key handle */
1894                 NtClose(OptionHandle);
1895             }
1896         }
1897     }
1898 
1899     /* Are we in Win PE mode? */
1900     if (InitIsWinPEMode)
1901     {
1902         /* Open the safe control key */
1903         RtlInitUnicodeString(&KeyName,
1904                              L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1905                              L"\\CONTROL");
1906         InitializeObjectAttributes(&ObjectAttributes,
1907                                    &KeyName,
1908                                    OBJ_CASE_INSENSITIVE,
1909                                    NULL,
1910                                    NULL);
1911         Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
1912         if (!NT_SUCCESS(Status))
1913         {
1914             /* Bugcheck */
1915             KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 6, 0, 0);
1916         }
1917 
1918         /* Create the MiniNT key */
1919         RtlInitUnicodeString(&KeyName, L"MiniNT");
1920         InitializeObjectAttributes(&ObjectAttributes,
1921                                    &KeyName,
1922                                    OBJ_CASE_INSENSITIVE,
1923                                    KeyHandle,
1924                                    NULL);
1925         Status = ZwCreateKey(&OptionHandle,
1926                              KEY_ALL_ACCESS,
1927                              &ObjectAttributes,
1928                              0,
1929                              NULL,
1930                              REG_OPTION_VOLATILE,
1931                              &Disposition);
1932         if (!NT_SUCCESS(Status))
1933         {
1934             /* Bugcheck */
1935             KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 6, 0, 0);
1936         }
1937 
1938         /* Close the handles */
1939         NtClose(KeyHandle);
1940         NtClose(OptionHandle);
1941     }
1942 
1943     /* FIXME: This doesn't do anything for now */
1944     MmArmInitSystem(2, LoaderBlock);
1945 
1946     /* Update progress bar */
1947     InbvUpdateProgressBar(80);
1948 
1949     /* Initialize VDM support */
1950 #if defined(_M_IX86)
1951     KeI386VdmInitialize();
1952 #endif
1953 
1954     /* Initialize Power Subsystem in Phase 1*/
1955     if (!PoInitSystem(1)) KeBugCheck(INTERNAL_POWER_ERROR);
1956 
1957     /* Update progress bar */
1958     InbvUpdateProgressBar(90);
1959 
1960     /* Initialize the Process Manager at Phase 1 */
1961     if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
1962 
1963     /* Make sure nobody touches the loader block again */
1964     if (LoaderBlock == KeLoaderBlock) KeLoaderBlock = NULL;
1965     MmFreeLoaderBlock(LoaderBlock);
1966     LoaderBlock = Context = NULL;
1967 
1968     /* Initialize the SRM in phase 1 */
1969     if (!SeRmInitPhase1()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
1970 
1971     /* Update progress bar */
1972     InbvUpdateProgressBar(100);
1973 
1974     /* Clear the screen */
1975     if (InbvBootDriverInstalled) FinalizeBootLogo();
1976 
1977     /* Allow strings to be displayed */
1978     InbvEnableDisplayString(TRUE);
1979 
1980     /* Launch initial process */
1981     ProcessInfo = &InitBuffer->ProcessInfo;
1982     ExpLoadInitialProcess(InitBuffer, &ProcessParameters, &Environment);
1983 
1984     /* Wait 5 seconds for initial process to initialize */
1985     Timeout.QuadPart = Int32x32To64(5, -10000000);
1986     Status = ZwWaitForSingleObject(ProcessInfo->ProcessHandle, FALSE, &Timeout);
1987     if (Status == STATUS_SUCCESS)
1988     {
1989         /* Failed, display error */
1990         DPRINT1("INIT: Session Manager terminated.\n");
1991 
1992         /* Bugcheck the system if SMSS couldn't initialize */
1993         KeBugCheck(SESSION5_INITIALIZATION_FAILED);
1994     }
1995 
1996     /* Close process handles */
1997     ZwClose(ProcessInfo->ThreadHandle);
1998     ZwClose(ProcessInfo->ProcessHandle);
1999 
2000     /* Free the initial process environment */
2001     Size = 0;
2002     ZwFreeVirtualMemory(NtCurrentProcess(),
2003                         (PVOID*)&Environment,
2004                         &Size,
2005                         MEM_RELEASE);
2006 
2007     /* Free the initial process parameters */
2008     Size = 0;
2009     ZwFreeVirtualMemory(NtCurrentProcess(),
2010                         (PVOID*)&ProcessParameters,
2011                         &Size,
2012                         MEM_RELEASE);
2013 
2014     /* Increase init phase */
2015     ExpInitializationPhase++;
2016 
2017     /* Free the boot buffer */
2018     ExFreePoolWithTag(InitBuffer, TAG_INIT);
2019 }
2020 
2021 VOID
2022 NTAPI
Phase1Initialization(IN PVOID Context)2023 Phase1Initialization(IN PVOID Context)
2024 {
2025     /* Do the .INIT part of Phase 1 which we can free later */
2026     Phase1InitializationDiscard(Context);
2027 
2028     /* Jump into zero page thread */
2029     MmZeroPageThread();
2030 }
2031