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