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