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