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