- Get rid of the completely convoluted way that Phase 1 initialization was being...
[reactos.git] / reactos / ntoskrnl / ex / init.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/init.c
5 * PURPOSE: Executive initalization
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
8 * and optimized/cleaned it.
9 * Eric Kohl (ekohl@abo.rhein-zeitung.de)
10 */
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15
16 /* DATA **********************************************************************/
17
18 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
19
20 /* NT Version Info */
21 ULONG NtMajorVersion = 5;
22 ULONG NtMinorVersion = 0;
23 ULONG NtOSCSDVersion = BUILD_OSCSDVERSION(4, 0);
24 ULONG NtBuildNumber = KERNEL_VERSION_BUILD;
25 ULONG NtGlobalFlag;
26 ULONG ExSuiteMask;
27
28 /* Init flags and settings */
29 ULONG ExpInitializationPhase;
30 BOOLEAN ExpInTextModeSetup;
31 BOOLEAN IoRemoteBootClient;
32 ULONG InitSafeBootMode;
33
34 BOOLEAN NoGuiBoot = FALSE;
35
36 /* NT Boot Path */
37 UNICODE_STRING NtSystemRoot;
38
39 /* Boot NLS information */
40 PVOID ExpNlsTableBase;
41 ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
42 ULONG ExpUnicodeCaseTableDataOffset;
43 NLSTABLEINFO ExpNlsTableInfo;
44 ULONG ExpNlsTableSize;
45 PVOID ExpNlsSectionPointer;
46
47 /* FUNCTIONS ****************************************************************/
48
49 VOID
50 NTAPI
51 ExpInitNls(VOID)
52 {
53 LARGE_INTEGER SectionSize;
54 NTSTATUS Status;
55 HANDLE NlsSection;
56 PVOID SectionBase = NULL;
57 ULONG ViewSize = 0;
58 LARGE_INTEGER SectionOffset = {{0}};
59
60 /* Set the section size */
61 SectionSize.QuadPart = ExpNlsTableSize;
62
63 /* Create the NLS Section */
64 Status = ZwCreateSection(&NlsSection,
65 SECTION_ALL_ACCESS,
66 NULL,
67 &SectionSize,
68 PAGE_READWRITE,
69 SEC_COMMIT,
70 NULL);
71 if (!NT_SUCCESS(Status))
72 {
73 /* Failed */
74 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 1, 0, 0);
75 }
76
77 /* Get a pointer to the section */
78 Status = ObReferenceObjectByHandle(NlsSection,
79 SECTION_ALL_ACCESS,
80 MmSectionObjectType,
81 KernelMode,
82 &ExpNlsSectionPointer,
83 NULL);
84 ZwClose(NlsSection);
85 if (!NT_SUCCESS(Status))
86 {
87 /* Failed */
88 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 2, 0, 0);
89 }
90
91 /* Map the NLS Section in system space */
92 Status = MmMapViewInSystemSpace(ExpNlsSectionPointer,
93 &SectionBase,
94 &ExpNlsTableSize);
95 if (!NT_SUCCESS(Status))
96 {
97 /* Failed */
98 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 3, 0, 0);
99 }
100
101 /* Copy the codepage data in its new location. */
102 RtlMoveMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
103
104 /* Free the previously allocated buffer and set the new location */
105 ExFreePool(ExpNlsTableBase);
106 ExpNlsTableBase = SectionBase;
107
108 /* Initialize the NLS Tables */
109 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
110 ExpAnsiCodePageDataOffset),
111 (PVOID)((ULONG_PTR)ExpNlsTableBase +
112 ExpOemCodePageDataOffset),
113 (PVOID)((ULONG_PTR)ExpNlsTableBase +
114 ExpUnicodeCaseTableDataOffset),
115 &ExpNlsTableInfo);
116 RtlResetRtlTranslations(&ExpNlsTableInfo);
117
118 /* Reset the base to 0 */
119 SectionBase = NULL;
120
121 /* Map the section in the system process */
122 Status = MmMapViewOfSection(ExpNlsSectionPointer,
123 PsGetCurrentProcess(),
124 &SectionBase,
125 0L,
126 0L,
127 &SectionOffset,
128 &ViewSize,
129 ViewShare,
130 0L,
131 PAGE_READWRITE);
132 if (!NT_SUCCESS(Status))
133 {
134 /* Failed */
135 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 5, 0, 0);
136 }
137
138 /* Copy the table into the system process and set this as the base */
139 RtlMoveMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
140 ExpNlsTableBase = SectionBase;
141 }
142
143 static
144 VOID
145 INIT_FUNCTION
146 InitSystemSharedUserPage (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
147 {
148 UNICODE_STRING ArcDeviceName;
149 UNICODE_STRING ArcName;
150 UNICODE_STRING BootPath;
151 UNICODE_STRING DriveDeviceName;
152 UNICODE_STRING DriveName;
153 WCHAR DriveNameBuffer[20];
154 PWCHAR ArcNameBuffer;
155 NTSTATUS Status;
156 ULONG Length;
157 OBJECT_ATTRIBUTES ObjectAttributes;
158 HANDLE Handle;
159 ULONG i;
160 BOOLEAN BootDriveFound = FALSE;
161
162 /* Set the Product Type */
163 SharedUserData->NtProductType = NtProductWinNt;
164 SharedUserData->ProductTypeIsValid = TRUE;
165
166 /*
167 * Retrieve the current dos system path
168 * (e.g.: C:\reactos) from the given arc path
169 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
170 * Format: "<arc_name>\<path> [options...]"
171 */
172
173 RtlCreateUnicodeStringFromAsciiz(&BootPath, LoaderBlock->NtBootPathName);
174
175 /* Remove the trailing backslash */
176 BootPath.Length -= sizeof(WCHAR);
177 BootPath.MaximumLength -= sizeof(WCHAR);
178
179 /* Only ARC Name left - Build full ARC Name */
180 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
181 swprintf (ArcNameBuffer, L"\\ArcName\\%S", LoaderBlock->ArcBootDeviceName);
182 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
183
184 /* Allocate ARC Device Name string */
185 ArcDeviceName.Length = 0;
186 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
187 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
188
189 /* Open the Symbolic Link */
190 InitializeObjectAttributes(&ObjectAttributes,
191 &ArcName,
192 OBJ_OPENLINK,
193 NULL,
194 NULL);
195 Status = NtOpenSymbolicLinkObject(&Handle,
196 SYMBOLIC_LINK_ALL_ACCESS,
197 &ObjectAttributes);
198
199 /* Free the String */
200 ExFreePool(ArcName.Buffer);
201
202 /* Check for Success */
203 if (!NT_SUCCESS(Status)) {
204
205 /* Free the Strings */
206 RtlFreeUnicodeString(&BootPath);
207 ExFreePool(ArcDeviceName.Buffer);
208 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", Status);
209 KEBUGCHECK(0);
210 }
211
212 /* Query the Link */
213 Status = NtQuerySymbolicLinkObject(Handle,
214 &ArcDeviceName,
215 &Length);
216 NtClose (Handle);
217
218 /* Check for Success */
219 if (!NT_SUCCESS(Status)) {
220
221 /* Free the Strings */
222 RtlFreeUnicodeString(&BootPath);
223 ExFreePool(ArcDeviceName.Buffer);
224 CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
225 KEBUGCHECK(0);
226 }
227
228 /* Allocate Device Name string */
229 DriveDeviceName.Length = 0;
230 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
231 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
232
233 /* Loop Drives */
234 for (i = 0; i < 26; i++) {
235
236 /* Setup the String */
237 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
238 RtlInitUnicodeString(&DriveName,
239 DriveNameBuffer);
240
241 /* Open the Symbolic Link */
242 InitializeObjectAttributes(&ObjectAttributes,
243 &DriveName,
244 OBJ_OPENLINK,
245 NULL,
246 NULL);
247 Status = NtOpenSymbolicLinkObject(&Handle,
248 SYMBOLIC_LINK_ALL_ACCESS,
249 &ObjectAttributes);
250
251 /* If it failed, skip to the next drive */
252 if (!NT_SUCCESS(Status)) {
253 DPRINT("Failed to open link %wZ\n", &DriveName);
254 continue;
255 }
256
257 /* Query it */
258 Status = NtQuerySymbolicLinkObject(Handle,
259 &DriveDeviceName,
260 &Length);
261
262 /* If it failed, skip to the next drive */
263 if (!NT_SUCCESS(Status)) {
264 DPRINT("Failed to query link %wZ\n", &DriveName);
265 continue;
266 }
267 DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
268
269 /* See if we've found the boot drive */
270 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
271
272 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
273 swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
274 BootDriveFound = TRUE;
275 }
276
277 /* Close this Link */
278 NtClose (Handle);
279 }
280
281 /* Free all the Strings we have in memory */
282 RtlFreeUnicodeString (&BootPath);
283 ExFreePool(DriveDeviceName.Buffer);
284 ExFreePool(ArcDeviceName.Buffer);
285
286 /* Make sure we found the Boot Drive */
287 if (BootDriveFound == FALSE) {
288
289 DbgPrint("No system drive found!\n");
290 KEBUGCHECK (NO_BOOT_DEVICE);
291 }
292 }
293
294 VOID
295 INIT_FUNCTION
296 ExpDisplayNotice(VOID)
297 {
298 CHAR str[50];
299
300 if (ExpInTextModeSetup)
301 {
302 HalDisplayString(
303 "\n\n\n ReactOS " KERNEL_VERSION_STR " Setup \n");
304 HalDisplayString(
305 " \xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD");
306 HalDisplayString(
307 "\xCD\xCD\n");
308 return;
309 }
310
311 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
312 KERNEL_VERSION_BUILD_STR")\n");
313 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
314 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
315 "Public License, and you\n");
316 HalDisplayString("are welcome to change it and/or distribute copies of it "
317 "under certain\n");
318 HalDisplayString("conditions. There is absolutely no warranty for "
319 "ReactOS.\n\n");
320
321 /* Display number of Processors */
322 sprintf(str,
323 "Found %x system processor(s). [%lu MB Memory]\n",
324 (int)KeNumberProcessors,
325 (MmFreeLdrMemHigher + 1088)/ 1024);
326 HalDisplayString(str);
327
328 }
329
330 NTSTATUS
331 NTAPI
332 ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
333 IN PHANDLE ThreadHandle)
334 {
335 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
336 NTSTATUS Status;
337 ULONG Size;
338 RTL_USER_PROCESS_INFORMATION ProcessInformation;
339 PWSTR p;
340 UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
341 UNICODE_STRING SmssName, Environment, SystemDriveString;
342
343 /* Allocate memory for the process parameters */
344 Size = sizeof(RTL_USER_PROCESS_PARAMETERS) +
345 ((MAX_PATH * 4) * sizeof(WCHAR));
346 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
347 (PVOID)&ProcessParameters,
348 0,
349 &Size,
350 MEM_COMMIT,
351 PAGE_READWRITE);
352 if (!NT_SUCCESS(Status))
353 {
354 /* Failed */
355 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED, Status, 0, 0, 0);
356 }
357
358 /* Setup the basic header, and give the process the low 1MB to itself */
359 ProcessParameters->Length = Size;
360 ProcessParameters->MaximumLength = Size;
361 ProcessParameters->Flags = RTL_USER_PROCESS_PARAMETERS_NORMALIZED |
362 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
363
364 /* Allocate a page for the environment */
365 Size = PAGE_SIZE;
366 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
367 (PVOID)&ProcessParameters->Environment,
368 0,
369 &Size,
370 MEM_COMMIT,
371 PAGE_READWRITE
372 );
373 if (!NT_SUCCESS(Status))
374 {
375 /* Failed */
376 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
377 }
378
379 /* Make a buffer for the DOS path */
380 p = (PWSTR)(ProcessParameters + 1);
381 ProcessParameters->CurrentDirectory.DosPath.Buffer = p;
382 ProcessParameters->
383 CurrentDirectory.DosPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
384
385 /* Copy the DOS path */
386 RtlCopyUnicodeString(&ProcessParameters->CurrentDirectory.DosPath,
387 &NtSystemRoot);
388
389 /* Make a buffer for the DLL Path */
390 p = (PWSTR)((PCHAR)ProcessParameters->CurrentDirectory.DosPath.Buffer +
391 ProcessParameters->CurrentDirectory.DosPath.MaximumLength);
392 ProcessParameters->DllPath.Buffer = p;
393 ProcessParameters->DllPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
394
395 /* Copy the DLL path and append the system32 directory */
396 RtlCopyUnicodeString(&ProcessParameters->DllPath,
397 &ProcessParameters->CurrentDirectory.DosPath);
398 RtlAppendUnicodeToString(&ProcessParameters->DllPath, L"\\System32");
399
400 /* Make a buffer for the image name */
401 p = (PWSTR)((PCHAR)ProcessParameters->DllPath.Buffer +
402 ProcessParameters->DllPath.MaximumLength);
403 ProcessParameters->ImagePathName.Buffer = p;
404 ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
405
406 /* Append the system path and session manager name */
407 RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
408 L"\\SystemRoot\\System32");
409 RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
410 L"\\smss.exe");
411
412 /* Create the environment string */
413 RtlInitEmptyUnicodeString(&Environment,
414 ProcessParameters->Environment,
415 Size);
416
417 /* Append the DLL path to it */
418 RtlAppendUnicodeToString(&Environment, L"Path=" );
419 RtlAppendUnicodeStringToString(&Environment, &ProcessParameters->DllPath);
420 RtlAppendUnicodeStringToString(&Environment, &NullString );
421
422 /* Create the system drive string */
423 SystemDriveString = NtSystemRoot;
424 SystemDriveString.Length = 2 * sizeof(WCHAR);
425
426 /* Append it to the environment */
427 RtlAppendUnicodeToString(&Environment, L"SystemDrive=");
428 RtlAppendUnicodeStringToString(&Environment, &SystemDriveString);
429 RtlAppendUnicodeStringToString(&Environment, &NullString);
430
431 /* Append the system root to the environment */
432 RtlAppendUnicodeToString(&Environment, L"SystemRoot=");
433 RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
434 RtlAppendUnicodeStringToString(&Environment, &NullString);
435
436 /* Get and set the command line equal to the image path */
437 ProcessParameters->CommandLine = ProcessParameters->ImagePathName;
438 SmssName = ProcessParameters->ImagePathName;
439
440 /* Create SMSS process */
441 Status = RtlCreateUserProcess(&SmssName,
442 OBJ_CASE_INSENSITIVE,
443 RtlDeNormalizeProcessParams(
444 ProcessParameters),
445 NULL,
446 NULL,
447 NULL,
448 FALSE,
449 NULL,
450 NULL,
451 &ProcessInformation);
452 if (!NT_SUCCESS(Status))
453 {
454 /* Failed */
455 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED, Status, 0, 0, 0);
456 }
457
458 /* Resume the thread */
459 Status = ZwResumeThread(ProcessInformation.ThreadHandle, NULL);
460 if (!NT_SUCCESS(Status))
461 {
462 /* Failed */
463 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
464 }
465
466 /* Return Handles */
467 *ProcessHandle = ProcessInformation.ProcessHandle;
468 *ThreadHandle = ProcessInformation.ThreadHandle;
469 return STATUS_SUCCESS;
470 }
471
472 ULONG
473 NTAPI
474 ExComputeTickCountMultiplier(IN ULONG ClockIncrement)
475 {
476 ULONG MsRemainder = 0, MsIncrement;
477 ULONG IncrementRemainder;
478 ULONG i;
479
480 /* Count the number of milliseconds for each clock interrupt */
481 MsIncrement = ClockIncrement / (10 * 1000);
482
483 /* Count the remainder from the division above, with 24-bit precision */
484 IncrementRemainder = ClockIncrement - (MsIncrement * (10 * 1000));
485 for (i= 0; i < 24; i++)
486 {
487 /* Shift the remainders */
488 MsRemainder <<= 1;
489 IncrementRemainder <<= 1;
490
491 /* Check if we've went past 1 ms */
492 if (IncrementRemainder >= (10 * 1000))
493 {
494 /* Increase the remainder by one, and substract from increment */
495 IncrementRemainder -= (10 * 1000);
496 MsRemainder |= 1;
497 }
498 }
499
500 /* Return the increment */
501 return (MsIncrement << 24) | MsRemainder;
502 }
503
504 BOOLEAN
505 NTAPI
506 ExpInitSystemPhase0(VOID)
507 {
508 /* Initialize EXRESOURCE Support */
509 ExpResourceInitialization();
510
511 /* Initialize the environment lock */
512 ExInitializeFastMutex(&ExpEnvironmentLock);
513
514 /* Initialize the lookaside lists and locks */
515 ExpInitLookasideLists();
516
517 /* Initialize the Firmware Table resource and listhead */
518 InitializeListHead(&ExpFirmwareTableProviderListHead);
519 ExInitializeResourceLite(&ExpFirmwareTableResource);
520
521 /* Set the suite mask to maximum and return */
522 ExSuiteMask = 0xFFFFFFFF;
523 return TRUE;
524 }
525
526 BOOLEAN
527 NTAPI
528 ExpInitSystemPhase1(VOID)
529 {
530 /* Initialize worker threads */
531 ExpInitializeWorkerThreads();
532
533 /* Initialize pushlocks */
534 ExpInitializePushLocks();
535
536 /* Initialize events and event pairs */
537 ExpInitializeEventImplementation();
538 ExpInitializeEventPairImplementation();
539
540 /* Initialize callbacks */
541 ExpInitializeCallbacks();
542
543 /* Initialize mutants */
544 ExpInitializeMutantImplementation();
545
546 /* Initialize semaphores */
547 ExpInitializeSemaphoreImplementation();
548
549 /* Initialize timers */
550 ExpInitializeTimerImplementation();
551
552 /* Initialize profiling */
553 ExpInitializeProfileImplementation();
554
555 /* Initialize UUIDs */
556 ExpInitUuids();
557
558 /* Initialize Win32K */
559 ExpWin32kInit();
560 return TRUE;
561 }
562
563 BOOLEAN
564 NTAPI
565 ExInitSystem(VOID)
566 {
567 /* Check the initialization phase */
568 switch (ExpInitializationPhase)
569 {
570 case 0:
571
572 /* Do Phase 0 */
573 return ExpInitSystemPhase0();
574
575 case 1:
576
577 /* Do Phase 1 */
578 return ExpInitSystemPhase1();
579
580 default:
581
582 /* Don't know any other phase! Bugcheck! */
583 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL);
584 return FALSE;
585 }
586 }
587
588 BOOLEAN
589 NTAPI
590 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
591 {
592 PLOADER_PARAMETER_EXTENSION Extension;
593
594 /* Get the loader extension */
595 Extension = LoaderBlock->Extension;
596
597 /* Validate the size (larger structures are OK, we'll just ignore them) */
598 if (Extension->Size < sizeof(LOADER_PARAMETER_EXTENSION)) return FALSE;
599
600 /* Don't validate upper versions */
601 if (Extension->MajorVersion > 5) return TRUE;
602
603 /* Fail if this is NT 4 */
604 if (Extension->MajorVersion < 5) return FALSE;
605
606 /* Fail if this is XP */
607 if (Extension->MinorVersion < 2) return FALSE;
608
609 /* This is 2003 or newer, aprove it */
610 return TRUE;
611 }
612
613 VOID
614 NTAPI
615 ExpInitializeExecutive(IN ULONG Cpu,
616 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
617 {
618 PNLS_DATA_BLOCK NlsData;
619 CHAR Buffer[256];
620 ANSI_STRING AnsiPath;
621 NTSTATUS Status;
622 PLIST_ENTRY NextEntry, ListHead;
623 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
624
625 /* Validate Loader */
626 if (!ExpIsLoaderValid(LoaderBlock))
627 {
628 /* Invalid loader version */
629 KeBugCheckEx(MISMATCHED_HAL,
630 3,
631 LoaderBlock->Extension->Size,
632 LoaderBlock->Extension->MajorVersion,
633 LoaderBlock->Extension->MinorVersion);
634 }
635
636 /* Initialize PRCB pool lookaside pointers */
637 ExInitPoolLookasidePointers();
638
639 /* Check if this is an application CPU */
640 if (Cpu)
641 {
642 /* Then simply initialize it with HAL */
643 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
644 {
645 /* Initialization failed */
646 KEBUGCHECK(HAL_INITIALIZATION_FAILED);
647 }
648
649 /* We're done */
650 return;
651 }
652
653 /* Assume no text-mode or remote boot */
654 ExpInTextModeSetup = FALSE;
655 IoRemoteBootClient = FALSE;
656
657 /* Check if we have a setup loader block */
658 if (LoaderBlock->SetupLdrBlock)
659 {
660 /* Check if this is text-mode setup */
661 if (LoaderBlock->SetupLdrBlock->Flags & 1) ExpInTextModeSetup = TRUE;
662
663 /* Check if this is network boot */
664 if (LoaderBlock->SetupLdrBlock->Flags & 2)
665 {
666 /* Set variable */
667 IoRemoteBootClient = TRUE;
668
669 /* Make sure we're actually booting off the network */
670 ASSERT(!_memicmp(LoaderBlock->ArcBootDeviceName, "net(0)", 6));
671 }
672 }
673
674 /* Set phase to 0 */
675 ExpInitializationPhase = 0;
676
677 /* Setup NLS Base and offsets */
678 NlsData = LoaderBlock->NlsData;
679 ExpNlsTableBase = NlsData->AnsiCodePageData;
680 ExpAnsiCodePageDataOffset = 0;
681 ExpOemCodePageDataOffset = ((ULONG_PTR)NlsData->OemCodePageData -
682 (ULONG_PTR)NlsData->AnsiCodePageData);
683 ExpUnicodeCaseTableDataOffset = ((ULONG_PTR)NlsData->UnicodeCodePageData -
684 (ULONG_PTR)NlsData->AnsiCodePageData);
685
686 /* Initialize the NLS Tables */
687 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
688 ExpAnsiCodePageDataOffset),
689 (PVOID)((ULONG_PTR)ExpNlsTableBase +
690 ExpOemCodePageDataOffset),
691 (PVOID)((ULONG_PTR)ExpNlsTableBase +
692 ExpUnicodeCaseTableDataOffset),
693 &ExpNlsTableInfo);
694 RtlResetRtlTranslations(&ExpNlsTableInfo);
695
696 /* Now initialize the HAL */
697 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
698 {
699 /* HAL failed to initialize, bugcheck */
700 KeBugCheck(HAL_INITIALIZATION_FAILED);
701 }
702
703 /* Make sure interrupts are active now */
704 _enable();
705
706 /* Clear the crypto exponent */
707 SharedUserData->CryptoExponent = 0;
708
709 /* Set global flags for the checked build */
710 #if DBG
711 NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS |
712 FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
713 #endif
714
715 /* Setup NT System Root Path */
716 sprintf(Buffer, "C:%s", LoaderBlock->NtBootPathName);
717
718 /* Convert to ANSI_STRING and null-terminate it */
719 RtlInitString(&AnsiPath, Buffer );
720 Buffer[--AnsiPath.Length] = UNICODE_NULL;
721
722 /* Get the string from KUSER_SHARED_DATA's buffer */
723 NtSystemRoot.Buffer = SharedUserData->NtSystemRoot;
724 NtSystemRoot.MaximumLength = sizeof(SharedUserData->NtSystemRoot) / sizeof(WCHAR);
725 NtSystemRoot.Length = 0;
726
727 /* Now fill it in */
728 Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
729 if (!NT_SUCCESS(Status)) KEBUGCHECK(SESSION3_INITIALIZATION_FAILED);
730
731 /* Setup bugcheck messages */
732 KiInitializeBugCheck();
733
734 /* Setup system time */
735 KiInitializeSystemClock();
736
737 /* Initialize the executive at phase 0 */
738 if (!ExInitSystem()) KEBUGCHECK(PHASE0_INITIALIZATION_FAILED);
739
740 /* Break into the Debugger if requested */
741 if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
742
743 /* Set system ranges */
744 SharedUserData->Reserved1 = (ULONG_PTR)MmHighestUserAddress;
745 SharedUserData->Reserved3 = (ULONG_PTR)MmSystemRangeStart;
746
747 /* Loop the memory descriptors */
748 ListHead = &LoaderBlock->MemoryDescriptorListHead;
749 NextEntry = ListHead->Flink;
750 while (NextEntry != ListHead)
751 {
752 /* Get the current block */
753 MdBlock = CONTAINING_RECORD(NextEntry,
754 MEMORY_ALLOCATION_DESCRIPTOR,
755 ListEntry);
756
757 /* Check if this is an NLS block */
758 if (MdBlock->MemoryType == LoaderNlsData)
759 {
760 /* Increase the table size */
761 ExpNlsTableSize += MdBlock->PageCount * PAGE_SIZE;
762 }
763
764 /* Go to the next block */
765 NextEntry = MdBlock->ListEntry.Flink;
766 }
767
768 /*
769 * In NT, the memory blocks are contiguous, but in ReactOS they are not,
770 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
771 */
772 ExpNlsTableSize += 2 * PAGE_SIZE; // BIAS FOR FREELDR. HACK!
773
774 /* Allocate the NLS buffer in the pool since loader memory will be freed */
775 ExpNlsTableBase = ExAllocatePoolWithTag(NonPagedPool,
776 ExpNlsTableSize,
777 TAG('R', 't', 'l', 'i'));
778 if (!ExpNlsTableBase) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
779
780 /* Copy the codepage data in its new location. */
781 RtlMoveMemory(ExpNlsTableBase,
782 LoaderBlock->NlsData->AnsiCodePageData,
783 ExpNlsTableSize);
784
785 /* Initialize and reset the NLS TAbles */
786 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
787 ExpAnsiCodePageDataOffset),
788 (PVOID)((ULONG_PTR)ExpNlsTableBase +
789 ExpOemCodePageDataOffset),
790 (PVOID)((ULONG_PTR)ExpNlsTableBase +
791 ExpUnicodeCaseTableDataOffset),
792 &ExpNlsTableInfo);
793 RtlResetRtlTranslations(&ExpNlsTableInfo);
794
795 /* Initialize the Handle Table */
796 ExpInitializeHandleTables();
797
798 #if DBG
799 /* On checked builds, allocate the system call count table */
800 KeServiceDescriptorTable[0].Count =
801 ExAllocatePoolWithTag(NonPagedPool,
802 KiServiceLimit * sizeof(ULONG),
803 TAG('C', 'a', 'l', 'l'));
804
805 /* Use it for the shadow table too */
806 KeServiceDescriptorTableShadow[0].Count = KeServiceDescriptorTable[0].Count;
807
808 /* Make sure allocation succeeded */
809 if (KeServiceDescriptorTable[0].Count)
810 {
811 /* Zero the call counts to 0 */
812 RtlZeroMemory(KeServiceDescriptorTable[0].Count,
813 KiServiceLimit * sizeof(ULONG));
814 }
815 #endif
816
817 /* Create the Basic Object Manager Types to allow new Object Types */
818 if (!ObInit()) KEBUGCHECK(OBJECT_INITIALIZATION_FAILED);
819
820 /* Load basic Security for other Managers */
821 if (!SeInit()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
822
823 /* Set up Region Maps, Sections and the Paging File */
824 MmInit2();
825
826 /* Call OB initialization again */
827 if (!ObInit()) KEBUGCHECK(OBJECT_INITIALIZATION_FAILED);
828
829 /* Initialize the Process Manager */
830 if (!PsInitSystem()) KEBUGCHECK(PROCESS_INITIALIZATION_FAILED);
831
832 /* Calculate the tick count multiplier */
833 ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement);
834 SharedUserData->TickCountMultiplier = ExpTickCountMultiplier;
835
836 /* Set the OS Version */
837 SharedUserData->NtMajorVersion = NtMajorVersion;
838 SharedUserData->NtMinorVersion = NtMinorVersion;
839
840 /* Set the machine type */
841 #if defined(_X86_)
842 SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_I386;
843 SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_I386;
844 #elif defined(_PPC_) // <3 Arty
845 SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_POWERPC;
846 SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_POWERPC;
847 #elif
848 #error "Unsupported ReactOS Target"
849 #endif
850 }
851
852 VOID
853 NTAPI
854 ExPhase2Init(PVOID Context)
855 {
856 LARGE_INTEGER Timeout;
857 HANDLE ProcessHandle;
858 HANDLE ThreadHandle;
859 NTSTATUS Status;
860
861 /* Set to phase 1 */
862 ExpInitializationPhase = 1;
863
864 /* Set us at maximum priority */
865 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY);
866
867 /* Initialize the later stages of the kernel */
868 KeInitSystem();
869
870 /* Initialize all processors */
871 HalAllProcessorsStarted();
872
873 /* Do Phase 1 HAL Initialization */
874 HalInitSystem(1, KeLoaderBlock);
875
876 /* Initialize Basic System Objects and Worker Threads */
877 ExInitSystem();
878
879 /* Call KD Providers at Phase 1 */
880 KdInitSystem(1, KeLoaderBlock);
881
882 /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
883 IoInit();
884
885 /* TBD */
886 PoInit(AcpiTableDetected, KeLoaderBlock);
887
888 /* Initialize the Registry (Hives are NOT yet loaded!) */
889 CmInitializeRegistry();
890
891 /* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
892 MmInit3();
893
894 /* Initialize Cache Views */
895 CcInit();
896
897 /* Initialize File Locking */
898 FsRtlpInitFileLockingImplementation();
899
900 /* Report all resources used by hal */
901 HalReportResourceUsage();
902
903 /* Clear the screen to blue */
904 HalInitSystem(2, KeLoaderBlock);
905
906 /* Check if GUI Boot is enabled */
907 if (strstr(KeLoaderBlock->LoadOptions, "NOGUIBOOT")) NoGuiBoot = TRUE;
908
909 /* Display version number and copyright/warranty message */
910 if (NoGuiBoot) ExpDisplayNotice();
911
912 /* Call KD Providers at Phase 2 */
913 KdInitSystem(2, KeLoaderBlock);
914
915 /* Create NLS section */
916 ExpInitNls();
917
918 /* Initialize LPC */
919 LpcpInitSystem();
920
921 /* Import and Load Registry Hives */
922 CmInitHives(ExpInTextModeSetup);
923
924 /* Initialize VDM support */
925 KeI386VdmInitialize();
926
927 /* Initialize the time zone information from the registry */
928 ExpInitTimeZoneInfo();
929
930 /* Enter the kernel debugger before starting up the boot drivers */
931 if (KdDebuggerEnabled && KdpEarlyBreak)
932 DbgBreakPoint();
933
934 /* Setup Drivers and Root Device Node */
935 IoInit2(FALSE);
936
937 /* Display the boot screen image if not disabled */
938 if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
939
940 /* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
941 IoInit3();
942
943 /* Load the System DLL and its Entrypoints */
944 PsLocateSystemDll();
945
946 /* Initialize shared user page. Set dos system path, dos device map, etc. */
947 InitSystemSharedUserPage(KeLoaderBlock);
948
949 /* Launch initial process */
950 Status = ExpLoadInitialProcess(&ProcessHandle,
951 &ThreadHandle);
952
953 /* Wait 5 seconds for it to initialize */
954 Timeout.QuadPart = Int32x32To64(5, -10000000);
955 Status = ZwWaitForSingleObject(ProcessHandle, FALSE, &Timeout);
956 if (Status == STATUS_SUCCESS)
957 {
958 /* Bugcheck the system if SMSS couldn't initialize */
959 KeBugCheck(SESSION5_INITIALIZATION_FAILED);
960 }
961 else
962 {
963 /* Close process handles */
964 ZwClose(ThreadHandle);
965 ZwClose(ProcessHandle);
966
967 /*
968 * FIXME: FILIP!
969 * Disable the Boot Logo
970 */
971 if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
972
973 /* FIXME: We should free the initial process' memory!*/
974
975 /* Increase init phase */
976 ExpInitializationPhase += 1;
977
978 /* Jump into zero page thread */
979 MmZeroPageThreadMain(NULL);
980 }
981 }
982 /* EOF */