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