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