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