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