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