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