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