Create this branch to work on loading of different Kernel-Debugger DLL providers...
[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 /* 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] = {0, 0, 0}; /* 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 | 0x1,
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 _snwprintf(InitBuffer->DebugBuffer,
409 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR),
410 L"INIT: Unable to allocate Process Parameters. 0x%lx",
411 Status);
412 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer);
413 ZwDisplayString(&DebugString);
414
415 /* Bugcheck the system */
416 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED, Status, 0, 0, 0);
417 }
418
419 /* Setup the basic header, and give the process the low 1MB to itself */
420 ProcessParams->Length = (ULONG)Size;
421 ProcessParams->MaximumLength = (ULONG)Size;
422 ProcessParams->Flags = RTL_USER_PROCESS_PARAMETERS_NORMALIZED |
423 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
424
425 /* Allocate a page for the environment */
426 Size = PAGE_SIZE;
427 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
428 &EnvironmentPtr,
429 0,
430 &Size,
431 MEM_RESERVE | MEM_COMMIT,
432 PAGE_READWRITE);
433 if (!NT_SUCCESS(Status))
434 {
435 /* Failed, display error */
436 _snwprintf(InitBuffer->DebugBuffer,
437 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR),
438 L"INIT: Unable to allocate Process Environment. 0x%lx",
439 Status);
440 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer);
441 ZwDisplayString(&DebugString);
442
443 /* Bugcheck the system */
444 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
445 }
446
447 /* Write the pointer */
448 ProcessParams->Environment = EnvironmentPtr;
449
450 /* Make a buffer for the DOS path */
451 p = (PWSTR)(ProcessParams + 1);
452 ProcessParams->CurrentDirectory.DosPath.Buffer = p;
453 ProcessParams->CurrentDirectory.DosPath.MaximumLength = MAX_PATH *
454 sizeof(WCHAR);
455
456 /* Copy the DOS path */
457 RtlCopyUnicodeString(&ProcessParams->CurrentDirectory.DosPath,
458 &NtSystemRoot);
459
460 /* Make a buffer for the DLL Path */
461 p = (PWSTR)((PCHAR)ProcessParams->CurrentDirectory.DosPath.Buffer +
462 ProcessParams->CurrentDirectory.DosPath.MaximumLength);
463 ProcessParams->DllPath.Buffer = p;
464 ProcessParams->DllPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
465
466 /* Copy the DLL path and append the system32 directory */
467 RtlCopyUnicodeString(&ProcessParams->DllPath,
468 &ProcessParams->CurrentDirectory.DosPath);
469 RtlAppendUnicodeToString(&ProcessParams->DllPath, L"\\System32");
470
471 /* Make a buffer for the image name */
472 p = (PWSTR)((PCHAR)ProcessParams->DllPath.Buffer +
473 ProcessParams->DllPath.MaximumLength);
474 ProcessParams->ImagePathName.Buffer = p;
475 ProcessParams->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
476
477 /* Make sure the buffer is a valid string which within the given length */
478 if ((NtInitialUserProcessBufferType != REG_SZ) ||
479 ((NtInitialUserProcessBufferLength != MAXULONG) &&
480 ((NtInitialUserProcessBufferLength < sizeof(WCHAR)) ||
481 (NtInitialUserProcessBufferLength >
482 sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR)))))
483 {
484 /* Invalid initial process string, bugcheck */
485 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED,
486 STATUS_INVALID_PARAMETER,
487 NtInitialUserProcessBufferType,
488 NtInitialUserProcessBufferLength,
489 sizeof(NtInitialUserProcessBuffer));
490 }
491
492 /* Cut out anything after a space */
493 p = NtInitialUserProcessBuffer;
494 while ((*p) && (*p != L' ')) p++;
495
496 /* Set the image path length */
497 ProcessParams->ImagePathName.Length =
498 (USHORT)((PCHAR)p - (PCHAR)NtInitialUserProcessBuffer);
499
500 /* Copy the actual buffer */
501 RtlCopyMemory(ProcessParams->ImagePathName.Buffer,
502 NtInitialUserProcessBuffer,
503 ProcessParams->ImagePathName.Length);
504
505 /* Null-terminate it */
506 ProcessParams->ImagePathName.Buffer[ProcessParams->ImagePathName.Length /
507 sizeof(WCHAR)] = UNICODE_NULL;
508
509 /* Make a buffer for the command line */
510 p = (PWSTR)((PCHAR)ProcessParams->ImagePathName.Buffer +
511 ProcessParams->ImagePathName.MaximumLength);
512 ProcessParams->CommandLine.Buffer = p;
513 ProcessParams->CommandLine.MaximumLength = MAX_PATH * sizeof(WCHAR);
514
515 /* Add the image name to the command line */
516 RtlAppendUnicodeToString(&ProcessParams->CommandLine,
517 NtInitialUserProcessBuffer);
518
519 /* Create the environment string */
520 RtlInitEmptyUnicodeString(&Environment,
521 ProcessParams->Environment,
522 (USHORT)Size);
523
524 /* Append the DLL path to it */
525 RtlAppendUnicodeToString(&Environment, L"Path=" );
526 RtlAppendUnicodeStringToString(&Environment, &ProcessParams->DllPath);
527 RtlAppendUnicodeStringToString(&Environment, &NullString);
528
529 /* Create the system drive string */
530 SystemDriveString = NtSystemRoot;
531 SystemDriveString.Length = 2 * sizeof(WCHAR);
532
533 /* Append it to the environment */
534 RtlAppendUnicodeToString(&Environment, L"SystemDrive=");
535 RtlAppendUnicodeStringToString(&Environment, &SystemDriveString);
536 RtlAppendUnicodeStringToString(&Environment, &NullString);
537
538 /* Append the system root to the environment */
539 RtlAppendUnicodeToString(&Environment, L"SystemRoot=");
540 RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
541 RtlAppendUnicodeStringToString(&Environment, &NullString);
542
543 /* Prepare the prefetcher */
544 //CcPfBeginBootPhase(150);
545
546 /* Create SMSS process */
547 SmssName = ProcessParams->ImagePathName;
548 Status = RtlCreateUserProcess(&SmssName,
549 OBJ_CASE_INSENSITIVE,
550 RtlDeNormalizeProcessParams(ProcessParams),
551 NULL,
552 NULL,
553 NULL,
554 FALSE,
555 NULL,
556 NULL,
557 ProcessInformation);
558 if (!NT_SUCCESS(Status))
559 {
560 /* Failed, display error */
561 _snwprintf(InitBuffer->DebugBuffer,
562 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR),
563 L"INIT: Unable to create Session Manager. 0x%lx",
564 Status);
565 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer);
566 ZwDisplayString(&DebugString);
567
568 /* Bugcheck the system */
569 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED, Status, 0, 0, 0);
570 }
571
572 /* Resume the thread */
573 Status = ZwResumeThread(ProcessInformation->ThreadHandle, NULL);
574 if (!NT_SUCCESS(Status))
575 {
576 /* Failed, display error */
577 _snwprintf(InitBuffer->DebugBuffer,
578 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR),
579 L"INIT: Unable to resume Session Manager. 0x%lx",
580 Status);
581 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer);
582 ZwDisplayString(&DebugString);
583
584 /* Bugcheck the system */
585 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
586 }
587
588 /* Return success */
589 *ProcessParameters = ProcessParams;
590 *ProcessEnvironment = EnvironmentPtr;
591 }
592
593 ULONG
594 NTAPI
595 INIT_FUNCTION
596 ExComputeTickCountMultiplier(IN ULONG ClockIncrement)
597 {
598 ULONG MsRemainder = 0, MsIncrement;
599 ULONG IncrementRemainder;
600 ULONG i;
601
602 /* Count the number of milliseconds for each clock interrupt */
603 MsIncrement = ClockIncrement / (10 * 1000);
604
605 /* Count the remainder from the division above, with 24-bit precision */
606 IncrementRemainder = ClockIncrement - (MsIncrement * (10 * 1000));
607 for (i= 0; i < 24; i++)
608 {
609 /* Shift the remainders */
610 MsRemainder <<= 1;
611 IncrementRemainder <<= 1;
612
613 /* Check if we've went past 1 ms */
614 if (IncrementRemainder >= (10 * 1000))
615 {
616 /* Increase the remainder by one, and substract from increment */
617 IncrementRemainder -= (10 * 1000);
618 MsRemainder |= 1;
619 }
620 }
621
622 /* Return the increment */
623 return (MsIncrement << 24) | MsRemainder;
624 }
625
626 BOOLEAN
627 NTAPI
628 INIT_FUNCTION
629 ExpInitSystemPhase0(VOID)
630 {
631 /* Initialize EXRESOURCE Support */
632 ExpResourceInitialization();
633
634 /* Initialize the environment lock */
635 ExInitializeFastMutex(&ExpEnvironmentLock);
636
637 /* Initialize the lookaside lists and locks */
638 ExpInitLookasideLists();
639
640 /* Initialize the Firmware Table resource and listhead */
641 InitializeListHead(&ExpFirmwareTableProviderListHead);
642 ExInitializeResourceLite(&ExpFirmwareTableResource);
643
644 /* Set the suite mask to maximum and return */
645 ExSuiteMask = 0xFFFFFFFF;
646 return TRUE;
647 }
648
649 BOOLEAN
650 NTAPI
651 INIT_FUNCTION
652 ExpInitSystemPhase1(VOID)
653 {
654 /* Initialize worker threads */
655 ExpInitializeWorkerThreads();
656
657 /* Initialize pushlocks */
658 ExpInitializePushLocks();
659
660 /* Initialize events and event pairs */
661 if (ExpInitializeEventImplementation() == FALSE)
662 {
663 DPRINT1("Executive: Event initialization failed\n");
664 return FALSE;
665 }
666 if (ExpInitializeEventPairImplementation() == FALSE)
667 {
668 DPRINT1("Executive: Event Pair initialization failed\n");
669 return FALSE;
670 }
671
672 /* Initialize mutants */
673 if (ExpInitializeMutantImplementation() == FALSE)
674 {
675 DPRINT1("Executive: Mutant initialization failed\n");
676 return FALSE;
677 }
678
679 /* Initialize callbacks */
680 if (ExpInitializeCallbacks() == FALSE)
681 {
682 DPRINT1("Executive: Callback initialization failed\n");
683 return FALSE;
684 }
685
686 /* Initialize semaphores */
687 if (ExpInitializeSemaphoreImplementation() == FALSE)
688 {
689 DPRINT1("Executive: Semaphore initialization failed\n");
690 return FALSE;
691 }
692
693 /* Initialize timers */
694 if (ExpInitializeTimerImplementation() == FALSE)
695 {
696 DPRINT1("Executive: Timer initialization failed\n");
697 return FALSE;
698 }
699
700 /* Initialize profiling */
701 if (ExpInitializeProfileImplementation() == FALSE)
702 {
703 DPRINT1("Executive: Profile initialization failed\n");
704 return FALSE;
705 }
706
707 /* Initialize UUIDs */
708 ExpInitUuids();
709
710 /* Initialize keyed events */
711 if (ExpInitializeKeyedEventImplementation() == FALSE)
712 {
713 DPRINT1("Executive: Keyed event initialization failed\n");
714 return FALSE;
715 }
716
717 /* Initialize Win32K */
718 if (ExpWin32kInit() == FALSE)
719 {
720 DPRINT1("Executive: Win32 initialization failed\n");
721 return FALSE;
722 }
723 return TRUE;
724 }
725
726 BOOLEAN
727 NTAPI
728 INIT_FUNCTION
729 ExInitSystem(VOID)
730 {
731 /* Check the initialization phase */
732 switch (ExpInitializationPhase)
733 {
734 case 0:
735
736 /* Do Phase 0 */
737 return ExpInitSystemPhase0();
738
739 case 1:
740
741 /* Do Phase 1 */
742 return ExpInitSystemPhase1();
743
744 default:
745
746 /* Don't know any other phase! Bugcheck! */
747 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL);
748 return FALSE;
749 }
750 }
751
752 BOOLEAN
753 NTAPI
754 INIT_FUNCTION
755 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
756 {
757 PLOADER_PARAMETER_EXTENSION Extension;
758
759 /* Get the loader extension */
760 Extension = LoaderBlock->Extension;
761
762 /* Validate the size (larger structures are OK, we'll just ignore them) */
763 if (Extension->Size < sizeof(LOADER_PARAMETER_EXTENSION)) return FALSE;
764
765 /* Don't validate upper versions */
766 if (Extension->MajorVersion > VER_PRODUCTMAJORVERSION) return TRUE;
767
768 /* Fail if this is NT 4 */
769 if (Extension->MajorVersion < VER_PRODUCTMAJORVERSION) return FALSE;
770
771 /* Fail if this is XP */
772 if (Extension->MinorVersion < VER_PRODUCTMINORVERSION) return FALSE;
773
774 /* This is 2003 or newer, approve it */
775 return TRUE;
776 }
777
778 VOID
779 NTAPI
780 INIT_FUNCTION
781 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
782 {
783 ULONG i = 0;
784 PLIST_ENTRY NextEntry;
785 ULONG Count, Length;
786 PWCHAR Name;
787 PLDR_DATA_TABLE_ENTRY LdrEntry;
788 CHAR NameBuffer[256];
789 STRING SymbolString;
790 NTSTATUS Status;
791
792 /* Loop the driver list */
793 NextEntry = LoaderBlock->LoadOrderListHead.Flink;
794 while (NextEntry != &LoaderBlock->LoadOrderListHead)
795 {
796 /* Skip the first two images */
797 if (i >= 2)
798 {
799 /* Get the entry */
800 LdrEntry = CONTAINING_RECORD(NextEntry,
801 LDR_DATA_TABLE_ENTRY,
802 InLoadOrderLinks);
803 if (LdrEntry->FullDllName.Buffer[0] == L'\\')
804 {
805 /* We have a name, read its data */
806 Name = LdrEntry->FullDllName.Buffer;
807 Length = LdrEntry->FullDllName.Length / sizeof(WCHAR);
808
809 /* Check if our buffer can hold it */
810 if (sizeof(NameBuffer) < Length + sizeof(ANSI_NULL))
811 {
812 /* It's too long */
813 Status = STATUS_BUFFER_OVERFLOW;
814 }
815 else
816 {
817 /* Copy the name */
818 Count = 0;
819 do
820 {
821 /* Copy the character */
822 NameBuffer[Count++] = (CHAR)*Name++;
823 } while (Count < Length);
824
825 /* Null-terminate */
826 NameBuffer[Count] = ANSI_NULL;
827 Status = STATUS_SUCCESS;
828 }
829 }
830 else
831 {
832 /* Safely print the string into our buffer */
833 Status = RtlStringCbPrintfA(NameBuffer,
834 sizeof(NameBuffer),
835 "%S\\System32\\Drivers\\%wZ",
836 &SharedUserData->NtSystemRoot[2],
837 &LdrEntry->BaseDllName);
838 }
839
840 /* Check if the buffer was ok */
841 if (NT_SUCCESS(Status))
842 {
843 /* Initialize the STRING for the debugger */
844 RtlInitString(&SymbolString, NameBuffer);
845
846 /* Load the symbols */
847 DbgLoadImageSymbols(&SymbolString,
848 LdrEntry->DllBase,
849 (ULONG_PTR)ZwCurrentProcess());
850 }
851 }
852
853 /* Go to the next entry */
854 i++;
855 NextEntry = NextEntry->Flink;
856 }
857 }
858
859 VOID
860 NTAPI
861 INIT_FUNCTION
862 ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
863 IN ULONG_PTR PagesToDestroy,
864 IN TYPE_OF_MEMORY MemoryType)
865 {
866 PLIST_ENTRY ListEntry;
867 PMEMORY_ALLOCATION_DESCRIPTOR MemDescriptor;
868
869 DPRINT1("Burn RAM amount: %d pages\n", PagesToDestroy);
870
871 /* Loop the memory descriptors, beginning at the end */
872 for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Blink;
873 ListEntry != &LoaderBlock->MemoryDescriptorListHead;
874 ListEntry = ListEntry->Blink)
875 {
876 /* Get the memory descriptor structure */
877 MemDescriptor = CONTAINING_RECORD(ListEntry,
878 MEMORY_ALLOCATION_DESCRIPTOR,
879 ListEntry);
880
881 /* Is memory free there or is it temporary? */
882 if (MemDescriptor->MemoryType == LoaderFree ||
883 MemDescriptor->MemoryType == LoaderFirmwareTemporary)
884 {
885 /* Check if the descriptor has more pages than we want */
886 if (MemDescriptor->PageCount > PagesToDestroy)
887 {
888 /* Change block's page count, ntoskrnl doesn't care much */
889 MemDescriptor->PageCount -= PagesToDestroy;
890 break;
891 }
892 else
893 {
894 /* Change block type */
895 MemDescriptor->MemoryType = MemoryType;
896 PagesToDestroy -= MemDescriptor->PageCount;
897
898 /* Check if we are done */
899 if (PagesToDestroy == 0) break;
900 }
901 }
902 }
903 }
904
905 VOID
906 NTAPI
907 INIT_FUNCTION
908 ExpInitializeExecutive(IN ULONG Cpu,
909 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
910 {
911 PNLS_DATA_BLOCK NlsData;
912 CHAR Buffer[256];
913 ANSI_STRING AnsiPath;
914 NTSTATUS Status;
915 PCHAR CommandLine, PerfMem;
916 ULONG PerfMemUsed;
917 PLDR_DATA_TABLE_ENTRY NtosEntry;
918 PMESSAGE_RESOURCE_ENTRY MsgEntry;
919 ANSI_STRING CsdString;
920 size_t Remaining = 0;
921 PCHAR RcEnd = NULL;
922 CHAR VersionBuffer [65];
923
924 /* Validate Loader */
925 if (!ExpIsLoaderValid(LoaderBlock))
926 {
927 /* Invalid loader version */
928 KeBugCheckEx(MISMATCHED_HAL,
929 3,
930 LoaderBlock->Extension->Size,
931 LoaderBlock->Extension->MajorVersion,
932 LoaderBlock->Extension->MinorVersion);
933 }
934
935 /* Initialize PRCB pool lookaside pointers */
936 ExInitPoolLookasidePointers();
937
938 /* Check if this is an application CPU */
939 if (Cpu)
940 {
941 /* Then simply initialize it with HAL */
942 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
943 {
944 /* Initialization failed */
945 KeBugCheck(HAL_INITIALIZATION_FAILED);
946 }
947
948 /* We're done */
949 return;
950 }
951
952 /* Assume no text-mode or remote boot */
953 ExpInTextModeSetup = FALSE;
954 IoRemoteBootClient = FALSE;
955
956 /* Check if we have a setup loader block */
957 if (LoaderBlock->SetupLdrBlock)
958 {
959 /* Check if this is text-mode setup */
960 if (LoaderBlock->SetupLdrBlock->Flags & SETUPLDR_TEXT_MODE) ExpInTextModeSetup = TRUE;
961
962 /* Check if this is network boot */
963 if (LoaderBlock->SetupLdrBlock->Flags & SETUPLDR_REMOTE_BOOT)
964 {
965 /* Set variable */
966 IoRemoteBootClient = TRUE;
967
968 /* Make sure we're actually booting off the network */
969 ASSERT(!_memicmp(LoaderBlock->ArcBootDeviceName, "net(0)", 6));
970 }
971 }
972
973 /* Set phase to 0 */
974 ExpInitializationPhase = 0;
975
976 /* Get boot command line */
977 CommandLine = LoaderBlock->LoadOptions;
978 if (CommandLine)
979 {
980 /* Upcase it for comparison and check if we're in performance mode */
981 _strupr(CommandLine);
982 PerfMem = strstr(CommandLine, "PERFMEM");
983 if (PerfMem)
984 {
985 /* Check if the user gave a number of bytes to use */
986 PerfMem = strstr(PerfMem, "=");
987 if (PerfMem)
988 {
989 /* Read the number of pages we'll use */
990 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
991 if (PerfMem)
992 {
993 /* FIXME: TODO */
994 DPRINT1("BBT performance mode not yet supported."
995 "/PERFMEM option ignored.\n");
996 }
997 }
998 }
999
1000 /* Check if we're burning memory */
1001 PerfMem = strstr(CommandLine, "BURNMEMORY");
1002 if (PerfMem)
1003 {
1004 /* Check if the user gave a number of bytes to use */
1005 PerfMem = strstr(PerfMem, "=");
1006 if (PerfMem)
1007 {
1008 /* Read the number of pages we'll use */
1009 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
1010 if (PerfMemUsed) ExBurnMemory(LoaderBlock, PerfMemUsed, LoaderBad);
1011 }
1012 }
1013 }
1014
1015 /* Setup NLS Base and offsets */
1016 NlsData = LoaderBlock->NlsData;
1017 ExpNlsTableBase = NlsData->AnsiCodePageData;
1018 ExpAnsiCodePageDataOffset = 0;
1019 ExpOemCodePageDataOffset = (ULONG)((ULONG_PTR)NlsData->OemCodePageData -
1020 (ULONG_PTR)NlsData->AnsiCodePageData);
1021 ExpUnicodeCaseTableDataOffset = (ULONG)((ULONG_PTR)NlsData->UnicodeCodePageData -
1022 (ULONG_PTR)NlsData->AnsiCodePageData);
1023
1024 /* Initialize the NLS Tables */
1025 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
1026 ExpAnsiCodePageDataOffset),
1027 (PVOID)((ULONG_PTR)ExpNlsTableBase +
1028 ExpOemCodePageDataOffset),
1029 (PVOID)((ULONG_PTR)ExpNlsTableBase +
1030 ExpUnicodeCaseTableDataOffset),
1031 &ExpNlsTableInfo);
1032 RtlResetRtlTranslations(&ExpNlsTableInfo);
1033
1034 /* Now initialize the HAL */
1035 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
1036 {
1037 /* HAL failed to initialize, bugcheck */
1038 KeBugCheck(HAL_INITIALIZATION_FAILED);
1039 }
1040
1041 /* Make sure interrupts are active now */
1042 _enable();
1043
1044 /* Clear the crypto exponent */
1045 SharedUserData->CryptoExponent = 0;
1046
1047 /* Set global flags for the checked build */
1048 #if DBG
1049 NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS |
1050 FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
1051 #endif
1052
1053 /* Setup NT System Root Path */
1054 sprintf(Buffer, "C:%s", LoaderBlock->NtBootPathName);
1055
1056 /* Convert to ANSI_STRING and null-terminate it */
1057 RtlInitString(&AnsiPath, Buffer);
1058 Buffer[--AnsiPath.Length] = ANSI_NULL;
1059
1060 /* Get the string from KUSER_SHARED_DATA's buffer */
1061 RtlInitEmptyUnicodeString(&NtSystemRoot,
1062 SharedUserData->NtSystemRoot,
1063 sizeof(SharedUserData->NtSystemRoot));
1064
1065 /* Now fill it in */
1066 Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
1067 if (!NT_SUCCESS(Status)) KeBugCheck(SESSION3_INITIALIZATION_FAILED);
1068
1069 /* Setup bugcheck messages */
1070 KiInitializeBugCheck();
1071
1072 /* Setup initial system settings */
1073 CmGetSystemControlValues(LoaderBlock->RegistryBase, CmControlVector);
1074
1075 /* Load static defaults for Service Pack 1 and add our SVN revision */
1076 /* Format of CSD : SPMajor - SPMinor */
1077 CmNtCSDVersion = 0x100 | (KERNEL_VERSION_BUILD_HEX << 16);
1078 CmNtCSDReleaseType = 0;
1079
1080 /* Set Service Pack data for Service Pack 1 */
1081 CmNtSpBuildNumber = VER_PRODUCTBUILD_QFE;
1082 if (!(CmNtCSDVersion & 0xFFFF0000))
1083 {
1084 /* Check the release type */
1085 if (CmNtCSDReleaseType == 1) CmNtSpBuildNumber |= 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)
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 "r%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 = _strupr(LoaderBlock->LoadOptions);
1376
1377 /* Check if GUI Boot is enabled */
1378 NoGuiBoot = (strstr(CommandLine, "NOGUIBOOT")) ? TRUE: FALSE;
1379
1380 /* Get the SOS setting */
1381 SosEnabled = strstr(CommandLine, "SOS") ? TRUE: FALSE;
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 (strstr(CommandLine, "MININT"))
1405 {
1406 /* Setup WinPE Settings */
1407 InitIsWinPEMode = TRUE;
1408 InitWinPEModeType |= (strstr(CommandLine, "INRAM")) ? 0x80000000 : 1;
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 Status = RtlStringCbPrintfA(EndBuffer,
1472 Remaining,
1473 (PCHAR)MsgEntry->Text,
1474 StringBuffer,
1475 NtBuildNumber & 0xFFFF,
1476 BeginBuffer);
1477 if (!NT_SUCCESS(Status))
1478 {
1479 /* Bugcheck */
1480 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1481 }
1482 }
1483 else
1484 {
1485 /* Use hard-coded banner message */
1486 Status = RtlStringCbCopyA(EndBuffer, Remaining, "REACTOS (R)\n");
1487 if (!NT_SUCCESS(Status))
1488 {
1489 /* Bugcheck */
1490 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0);
1491 }
1492 }
1493
1494 /* Display the version string on-screen */
1495 InbvDisplayString(EndBuffer);
1496
1497 /* Initialize Power Subsystem in Phase 0 */
1498 if (!PoInitSystem(0)) KeBugCheck(INTERNAL_POWER_ERROR);
1499
1500 /* Check for Y2K hack */
1501 Y2KHackRequired = strstr(CommandLine, "YEAR");
1502 if (Y2KHackRequired) Y2KHackRequired = strstr(Y2KHackRequired, "=");
1503 if (Y2KHackRequired) YearHack = atol(Y2KHackRequired + 1);
1504
1505 /* Query the clock */
1506 if ((ExCmosClockIsSane) && (HalQueryRealTimeClock(&TimeFields)))
1507 {
1508 /* Check if we're using the Y2K hack */
1509 if (Y2KHackRequired) TimeFields.Year = (CSHORT)YearHack;
1510
1511 /* Convert to time fields */
1512 RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
1513 UniversalBootTime = SystemBootTime;
1514
1515 /* Check if real time is GMT */
1516 if (!ExpRealTimeIsUniversal)
1517 {
1518 /* Check if we don't have a valid bias */
1519 if (ExpLastTimeZoneBias == MAXULONG)
1520 {
1521 /* Reset */
1522 ResetBias = TRUE;
1523 ExpLastTimeZoneBias = ExpAltTimeZoneBias;
1524 }
1525
1526 /* Calculate the bias in seconds */
1527 ExpTimeZoneBias.QuadPart = Int32x32To64(ExpLastTimeZoneBias * 60,
1528 10000000);
1529
1530 /* Set the boot time-zone bias */
1531 SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
1532 SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
1533 SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
1534
1535 /* Convert the boot time to local time, and set it */
1536 UniversalBootTime.QuadPart = SystemBootTime.QuadPart +
1537 ExpTimeZoneBias.QuadPart;
1538 }
1539
1540 /* Update the system time */
1541 KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL);
1542
1543 /* Do system callback */
1544 PoNotifySystemTimeSet();
1545
1546 /* Remember this as the boot time */
1547 KeBootTime = UniversalBootTime;
1548 KeBootTimeBias = 0;
1549 }
1550
1551 /* Initialize all processors */
1552 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED);
1553
1554 #ifdef CONFIG_SMP
1555 /* HACK: We should use RtlFindMessage and not only fallback to this */
1556 MpString = "MultiProcessor Kernel\r\n";
1557 #endif
1558
1559 /* Setup the "MP" String */
1560 RtlInitAnsiString(&TempString, MpString);
1561
1562 /* Make sure to remove the \r\n if we actually have a string */
1563 while ((TempString.Length > 0) &&
1564 ((TempString.Buffer[TempString.Length - 1] == '\r') ||
1565 (TempString.Buffer[TempString.Length - 1] == '\n')))
1566 {
1567 /* Skip the trailing character */
1568 TempString.Length--;
1569 }
1570
1571 /* Get the information string from our resource file */
1572 MsgStatus = RtlFindMessage(NtosEntry->DllBase,
1573 11,
1574 0,
1575 KeNumberProcessors > 1 ?
1576 WINDOWS_NT_INFO_STRING_PLURAL :
1577 WINDOWS_NT_INFO_STRING,
1578 &MsgEntry);
1579
1580 /* Get total RAM size */
1581 Size = MmNumberOfPhysicalPages * PAGE_SIZE / 1024 / 1024;
1582
1583 /* Create the string */
1584 StringBuffer = InitBuffer->VersionBuffer;
1585 Status = RtlStringCbPrintfA(StringBuffer,
1586 sizeof(InitBuffer->VersionBuffer),
1587 NT_SUCCESS(MsgStatus) ?
1588 (PCHAR)MsgEntry->Text :
1589 "%u System Processor [%u MB Memory] %Z\n",
1590 KeNumberProcessors,
1591 Size,
1592 &TempString);
1593 if (!NT_SUCCESS(Status))
1594 {
1595 /* Bugcheck */
1596 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 4, 0, 0);
1597 }
1598
1599 /* Display RAM and CPU count */
1600 InbvDisplayString(StringBuffer);
1601
1602 /* Update the progress bar */
1603 InbvUpdateProgressBar(5);
1604
1605 /* Call OB initialization again */
1606 if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED);
1607
1608 /* Initialize Basic System Objects and Worker Threads */
1609 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 1, 0);
1610
1611 /* Initialize the later stages of the kernel */
1612 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 2, 0);
1613
1614 /* Call KD Providers at Phase 1 */
1615 if (!KdInitSystem(ExpInitializationPhase, KeLoaderBlock))
1616 {
1617 /* Failed, bugcheck */
1618 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 3, 0);
1619 }
1620
1621 /* Initialize the SRM in Phase 1 */
1622 if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED);
1623
1624 /* Update the progress bar */
1625 InbvUpdateProgressBar(10);
1626
1627 /* Create SystemRoot Link */
1628 Status = ExpCreateSystemRootLink(LoaderBlock);
1629 if (!NT_SUCCESS(Status))
1630 {
1631 /* Failed to create the system root link */
1632 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 0, 0, 0);
1633 }
1634
1635 /* Set up Region Maps, Sections and the Paging File */
1636 if (!MmInitSystem(1, LoaderBlock)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED);
1637
1638 /* Create NLS section */
1639 ExpInitNls(LoaderBlock);
1640
1641 /* Initialize Cache Views */
1642 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED);
1643
1644 /* Initialize the Registry */
1645 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED);
1646
1647 /* Initialize Prefetcher */
1648 CcPfInitializePrefetcher();
1649
1650 /* Update progress bar */
1651 InbvUpdateProgressBar(15);
1652
1653 /* Update timezone information */
1654 LastTzBias = ExpLastTimeZoneBias;
1655 ExRefreshTimeZoneInformation(&SystemBootTime);
1656
1657 /* Check if we're resetting timezone data */
1658 if (ResetBias)
1659 {
1660 /* Convert the local time to system time */
1661 ExLocalTimeToSystemTime(&SystemBootTime, &UniversalBootTime);
1662 KeBootTime = UniversalBootTime;
1663 KeBootTimeBias = 0;
1664
1665 /* Set the new time */
1666 KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL);
1667 }
1668 else
1669 {
1670 /* Check if the timezone switched and update the time */
1671 if (LastTzBias != ExpLastTimeZoneBias) ZwSetSystemTime(NULL, NULL);
1672 }
1673
1674 /* Initialize the File System Runtime Library */
1675 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED);
1676
1677 /* Initialize range lists */
1678 RtlInitializeRangeListPackage();
1679
1680 /* Report all resources used by HAL */
1681 HalReportResourceUsage();
1682
1683 /* Call the debugger DLL */
1684 KdDebuggerInitialize1(LoaderBlock);
1685
1686 /* Setup PnP Manager in phase 1 */
1687 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED);
1688
1689 /* Update progress bar */
1690 InbvUpdateProgressBar(20);
1691
1692 /* Initialize LPC */
1693 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED);
1694
1695 /* Make sure we have a command line */
1696 if (CommandLine)
1697 {
1698 /* Check if this is a safe mode boot */
1699 SafeBoot = strstr(CommandLine, "SAFEBOOT:");
1700 if (SafeBoot)
1701 {
1702 /* Check what kind of boot this is */
1703 SafeBoot += 9;
1704 if (!strncmp(SafeBoot, "MINIMAL", 7))
1705 {
1706 /* Minimal mode */
1707 InitSafeBootMode = 1;
1708 SafeBoot += 7;
1709 MessageCode = BOOTING_IN_SAFEMODE_MINIMAL;
1710 }
1711 else if (!strncmp(SafeBoot, "NETWORK", 7))
1712 {
1713 /* With Networking */
1714 InitSafeBootMode = 2;
1715 SafeBoot += 7;
1716 MessageCode = BOOTING_IN_SAFEMODE_NETWORK;
1717 }
1718 else if (!strncmp(SafeBoot, "DSREPAIR", 8))
1719 {
1720 /* Domain Server Repair */
1721 InitSafeBootMode = 3;
1722 SafeBoot += 8;
1723 MessageCode = BOOTING_IN_SAFEMODE_DSREPAIR;
1724
1725 }
1726 else
1727 {
1728 /* Invalid */
1729 InitSafeBootMode = 0;
1730 }
1731
1732 /* Check if there's any settings left */
1733 if (*SafeBoot)
1734 {
1735 /* Check if an alternate shell was requested */
1736 if (!strncmp(SafeBoot, "(ALTERNATESHELL)", 16))
1737 {
1738 /* Remember this for later */
1739 AlternateShell = TRUE;
1740 }
1741 }
1742
1743 /* Find the message to print out */
1744 Status = RtlFindMessage(NtosEntry->DllBase,
1745 11,
1746 0,
1747 MessageCode,
1748 &MsgEntry);
1749 if (NT_SUCCESS(Status))
1750 {
1751 /* Display it */
1752 InbvDisplayString((PCHAR)MsgEntry->Text);
1753 }
1754 }
1755 }
1756
1757 /* Make sure we have a command line */
1758 if (CommandLine)
1759 {
1760 /* Check if bootlogging is enabled */
1761 if (strstr(CommandLine, "BOOTLOG"))
1762 {
1763 /* Find the message to print out */
1764 Status = RtlFindMessage(NtosEntry->DllBase,
1765 11,
1766 0,
1767 BOOTLOG_ENABLED,
1768 &MsgEntry);
1769 if (NT_SUCCESS(Status))
1770 {
1771 /* Display it */
1772 InbvDisplayString((PCHAR)MsgEntry->Text);
1773 }
1774
1775 /* Setup boot logging */
1776 //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader);
1777 }
1778 }
1779
1780 /* Setup the Executive in Phase 2 */
1781 //ExInitSystemPhase2();
1782
1783 /* Update progress bar */
1784 InbvUpdateProgressBar(25);
1785
1786 #ifdef _WINKD_
1787 /* No KD Time Slip is pending */
1788 KdpTimeSlipPending = 0;
1789 #endif
1790
1791 /* Initialize in-place execution support */
1792 XIPInit(LoaderBlock);
1793
1794 /* Set maximum update to 75% */
1795 InbvSetProgressBarSubset(25, 75);
1796
1797 /* Initialize the I/O Subsystem */
1798 if (!IoInitSystem(LoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED);
1799
1800 /* Set maximum update to 100% */
1801 InbvSetProgressBarSubset(0, 100);
1802
1803 /* Are we in safe mode? */
1804 if (InitSafeBootMode)
1805 {
1806 /* Open the safe boot key */
1807 RtlInitUnicodeString(&KeyName,
1808 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1809 L"\\CONTROL\\SAFEBOOT");
1810 InitializeObjectAttributes(&ObjectAttributes,
1811 &KeyName,
1812 OBJ_CASE_INSENSITIVE,
1813 NULL,
1814 NULL);
1815 Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
1816 if (NT_SUCCESS(Status))
1817 {
1818 /* First check if we have an alternate shell */
1819 if (AlternateShell)
1820 {
1821 /* Make sure that the registry has one setup */
1822 RtlInitUnicodeString(&KeyName, L"AlternateShell");
1823 Status = NtQueryValueKey(KeyHandle,
1824 &KeyName,
1825 KeyValuePartialInformation,
1826 &KeyPartialInfo,
1827 sizeof(KeyPartialInfo),
1828 &Length);
1829 if (!(NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW))
1830 {
1831 AlternateShell = FALSE;
1832 }
1833 }
1834
1835 /* Create the option key */
1836 RtlInitUnicodeString(&KeyName, L"Option");
1837 InitializeObjectAttributes(&ObjectAttributes,
1838 &KeyName,
1839 OBJ_CASE_INSENSITIVE,
1840 KeyHandle,
1841 NULL);
1842 Status = ZwCreateKey(&OptionHandle,
1843 KEY_ALL_ACCESS,
1844 &ObjectAttributes,
1845 0,
1846 NULL,
1847 REG_OPTION_VOLATILE,
1848 &Disposition);
1849 NtClose(KeyHandle);
1850
1851 /* Check if the key create worked */
1852 if (NT_SUCCESS(Status))
1853 {
1854 /* Write the safe boot type */
1855 RtlInitUnicodeString(&KeyName, L"OptionValue");
1856 NtSetValueKey(OptionHandle,
1857 &KeyName,
1858 0,
1859 REG_DWORD,
1860 &InitSafeBootMode,
1861 sizeof(InitSafeBootMode));
1862
1863 /* Check if we have to use an alternate shell */
1864 if (AlternateShell)
1865 {
1866 /* Remember this for later */
1867 Disposition = TRUE;
1868 RtlInitUnicodeString(&KeyName, L"UseAlternateShell");
1869 NtSetValueKey(OptionHandle,
1870 &KeyName,
1871 0,
1872 REG_DWORD,
1873 &Disposition,
1874 sizeof(Disposition));
1875 }
1876
1877 /* Close the options key handle */
1878 NtClose(OptionHandle);
1879 }
1880 }
1881 }
1882
1883 /* Are we in Win PE mode? */
1884 if (InitIsWinPEMode)
1885 {
1886 /* Open the safe control key */
1887 RtlInitUnicodeString(&KeyName,
1888 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"
1889 L"\\CONTROL");
1890 InitializeObjectAttributes(&ObjectAttributes,
1891 &KeyName,
1892 OBJ_CASE_INSENSITIVE,
1893 NULL,
1894 NULL);
1895 Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
1896 if (!NT_SUCCESS(Status))
1897 {
1898 /* Bugcheck */
1899 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 6, 0, 0);
1900 }
1901
1902 /* Create the MiniNT key */
1903 RtlInitUnicodeString(&KeyName, L"MiniNT");
1904 InitializeObjectAttributes(&ObjectAttributes,
1905 &KeyName,
1906 OBJ_CASE_INSENSITIVE,
1907 KeyHandle,
1908 NULL);
1909 Status = ZwCreateKey(&OptionHandle,
1910 KEY_ALL_ACCESS,
1911 &ObjectAttributes,
1912 0,
1913 NULL,
1914 REG_OPTION_VOLATILE,
1915 &Disposition);
1916 if (!NT_SUCCESS(Status))
1917 {
1918 /* Bugcheck */
1919 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 6, 0, 0);
1920 }
1921
1922 /* Close the handles */
1923 NtClose(KeyHandle);
1924 NtClose(OptionHandle);
1925 }
1926
1927 /* FIXME: This doesn't do anything for now */
1928 MmArmInitSystem(2, LoaderBlock);
1929
1930 /* Update progress bar */
1931 InbvUpdateProgressBar(80);
1932
1933 /* Initialize VDM support */
1934 #if defined(_M_IX86)
1935 KeI386VdmInitialize();
1936 #endif
1937
1938 /* Initialize Power Subsystem in Phase 1*/
1939 if (!PoInitSystem(1)) KeBugCheck(INTERNAL_POWER_ERROR);
1940
1941 /* Update progress bar */
1942 InbvUpdateProgressBar(90);
1943
1944 /* Initialize the Process Manager at Phase 1 */
1945 if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
1946
1947 /* Make sure nobody touches the loader block again */
1948 if (LoaderBlock == KeLoaderBlock) KeLoaderBlock = NULL;
1949 MmFreeLoaderBlock(LoaderBlock);
1950 LoaderBlock = Context = NULL;
1951
1952 /* Update progress bar */
1953 InbvUpdateProgressBar(100);
1954
1955 /* Allow strings to be displayed */
1956 InbvEnableDisplayString(TRUE);
1957
1958 /* Launch initial process */
1959 DPRINT1("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed);
1960 ProcessInfo = &InitBuffer->ProcessInfo;
1961 ExpLoadInitialProcess(InitBuffer, &ProcessParameters, &Environment);
1962
1963 /* Wait 5 seconds for initial process to initialize */
1964 Timeout.QuadPart = Int32x32To64(5, -10000000);
1965 Status = ZwWaitForSingleObject(ProcessInfo->ProcessHandle, FALSE, &Timeout);
1966 if (Status == STATUS_SUCCESS)
1967 {
1968 /* Failed, display error */
1969 DPRINT1("INIT: Session Manager terminated.\n");
1970
1971 /* Bugcheck the system if SMSS couldn't initialize */
1972 KeBugCheck(SESSION5_INITIALIZATION_FAILED);
1973 }
1974
1975 /* Close process handles */
1976 ZwClose(ProcessInfo->ThreadHandle);
1977 ZwClose(ProcessInfo->ProcessHandle);
1978
1979 /* Free the initial process environment */
1980 Size = 0;
1981 ZwFreeVirtualMemory(NtCurrentProcess(),
1982 (PVOID*)&Environment,
1983 &Size,
1984 MEM_RELEASE);
1985
1986 /* Free the initial process parameters */
1987 Size = 0;
1988 ZwFreeVirtualMemory(NtCurrentProcess(),
1989 (PVOID*)&ProcessParameters,
1990 &Size,
1991 MEM_RELEASE);
1992
1993 /* Clean the screen */
1994 if (InbvBootDriverInstalled) FinalizeBootLogo();
1995
1996 /* Increase init phase */
1997 ExpInitializationPhase++;
1998
1999 /* Free the boot buffer */
2000 ExFreePoolWithTag(InitBuffer, TAG_INIT);
2001 DPRINT1("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed);
2002 }
2003
2004 VOID
2005 NTAPI
2006 Phase1Initialization(IN PVOID Context)
2007 {
2008 /* Do the .INIT part of Phase 1 which we can free later */
2009 Phase1InitializationDiscard(Context);
2010
2011 /* Jump into zero page thread */
2012 MmZeroPageThread();
2013 }