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