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