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