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