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