- Create KD branch. All debugging support is removed in this branch (no symbols,...
[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 <debug.h>
15 //#include <ntoskrnl/cm/newcm.h>
16 #include "ntoskrnl/cm/cm.h"
17
18 /* DATA **********************************************************************/
19
20 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
21
22 /* NT Version Info */
23 ULONG NtMajorVersion = 5;
24 ULONG NtMinorVersion = 0;
25 ULONG NtOSCSDVersion = BUILD_OSCSDVERSION(4, 0);
26 ULONG NtBuildNumber = KERNEL_VERSION_BUILD;
27 ULONG NtGlobalFlag;
28 ULONG ExSuiteMask;
29
30 /* Init flags and settings */
31 ULONG ExpInitializationPhase;
32 BOOLEAN ExpInTextModeSetup;
33 BOOLEAN IoRemoteBootClient;
34 ULONG InitSafeBootMode;
35 BOOLEAN InitIsWinPEMode, InitWinPEModeType;
36
37 /* NT Boot Path */
38 UNICODE_STRING NtSystemRoot;
39
40 /* NT Initial User Application */
41 WCHAR NtInitialUserProcessBuffer[128] = L"\\SystemRoot\\System32\\smss.exe";
42 ULONG NtInitialUserProcessBufferLength = sizeof(NtInitialUserProcessBuffer) -
43 sizeof(WCHAR);
44 ULONG NtInitialUserProcessBufferType = REG_SZ;
45
46 /* Boot NLS information */
47 PVOID ExpNlsTableBase;
48 ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
49 ULONG ExpUnicodeCaseTableDataOffset;
50 NLSTABLEINFO ExpNlsTableInfo;
51 ULONG ExpNlsTableSize;
52 PVOID ExpNlsSectionPointer;
53
54 /* CMOS Timer Sanity */
55 BOOLEAN ExCmosClockIsSane = TRUE;
56
57 /* FUNCTIONS ****************************************************************/
58
59 NTSTATUS
60 NTAPI
61 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
62 {
63 UNICODE_STRING LinkName;
64 OBJECT_ATTRIBUTES ObjectAttributes;
65 HANDLE LinkHandle;
66 NTSTATUS Status;
67 ANSI_STRING AnsiName;
68 CHAR Buffer[256];
69 ANSI_STRING TargetString;
70 UNICODE_STRING TargetName;
71
72 /* Initialize the ArcName tree */
73 RtlInitUnicodeString(&LinkName, L"\\ArcName");
74 InitializeObjectAttributes(&ObjectAttributes,
75 &LinkName,
76 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
77 NULL,
78 SePublicDefaultUnrestrictedSd);
79
80 /* Create it */
81 Status = NtCreateDirectoryObject(&LinkHandle,
82 DIRECTORY_ALL_ACCESS,
83 &ObjectAttributes);
84 if (!NT_SUCCESS(Status))
85 {
86 /* Failed */
87 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 1, 0, 0);
88 }
89
90 /* Close the LinkHandle */
91 NtClose(LinkHandle);
92
93 /* Initialize the Device tree */
94 RtlInitUnicodeString(&LinkName, L"\\Device");
95 InitializeObjectAttributes(&ObjectAttributes,
96 &LinkName,
97 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
98 NULL,
99 SePublicDefaultUnrestrictedSd);
100
101 /* Create it */
102 Status = NtCreateDirectoryObject(&LinkHandle,
103 DIRECTORY_ALL_ACCESS,
104 &ObjectAttributes);
105 if (!NT_SUCCESS(Status))
106 {
107 /* Failed */
108 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 2, 0, 0);
109 }
110
111 /* Close the LinkHandle */
112 ObCloseHandle(LinkHandle, KernelMode);
113
114 /* Create the system root symlink name */
115 RtlInitAnsiString(&AnsiName, "\\SystemRoot");
116 Status = RtlAnsiStringToUnicodeString(&LinkName, &AnsiName, TRUE);
117 if (!NT_SUCCESS(Status))
118 {
119 /* Failed */
120 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 3, 0, 0);
121 }
122
123 /* Initialize the attributes for the link */
124 InitializeObjectAttributes(&ObjectAttributes,
125 &LinkName,
126 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
127 NULL,
128 SePublicDefaultUnrestrictedSd);
129
130 /* Build the ARC name */
131 sprintf(Buffer,
132 "\\ArcName\\%s%s",
133 LoaderBlock->ArcBootDeviceName,
134 LoaderBlock->NtBootPathName);
135 Buffer[strlen(Buffer) - 1] = ANSI_NULL;
136
137 /* Convert it to Unicode */
138 RtlInitString(&TargetString, Buffer);
139 Status = RtlAnsiStringToUnicodeString(&TargetName,
140 &TargetString,
141 TRUE);
142 if (!NT_SUCCESS(Status))
143 {
144 /* We failed, bugcheck */
145 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 4, 0, 0);
146 }
147
148 /* Create it */
149 Status = NtCreateSymbolicLinkObject(&LinkHandle,
150 SYMBOLIC_LINK_ALL_ACCESS,
151 &ObjectAttributes,
152 &TargetName);
153
154 /* Free the strings */
155 RtlFreeUnicodeString(&LinkName);
156 RtlFreeUnicodeString(&TargetName);
157
158 /* Check if creating the link failed */
159 if (!NT_SUCCESS(Status))
160 {
161 /* Failed */
162 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 5, 0, 0);
163 }
164
165 /* Close the handle and return success */
166 ObCloseHandle(LinkHandle, KernelMode);
167 return STATUS_SUCCESS;
168 }
169
170 VOID
171 NTAPI
172 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
173 {
174 LARGE_INTEGER SectionSize;
175 NTSTATUS Status;
176 HANDLE NlsSection;
177 PVOID SectionBase = NULL;
178 ULONG ViewSize = 0;
179 LARGE_INTEGER SectionOffset = {{0}};
180 PLIST_ENTRY ListHead, NextEntry;
181 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
182
183 /* Check if this is boot-time phase 0 initialization */
184 if (!ExpInitializationPhase)
185 {
186 /* Loop the memory descriptors */
187 ListHead = &LoaderBlock->MemoryDescriptorListHead;
188 NextEntry = ListHead->Flink;
189 while (NextEntry != ListHead)
190 {
191 /* Get the current block */
192 MdBlock = CONTAINING_RECORD(NextEntry,
193 MEMORY_ALLOCATION_DESCRIPTOR,
194 ListEntry);
195
196 /* Check if this is an NLS block */
197 if (MdBlock->MemoryType == LoaderNlsData)
198 {
199 /* Increase the table size */
200 ExpNlsTableSize += MdBlock->PageCount * PAGE_SIZE;
201 }
202
203 /* Go to the next block */
204 NextEntry = MdBlock->ListEntry.Flink;
205 }
206
207 /*
208 * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
209 * so unless someone fixes FreeLdr, we'll have to use this icky hack.
210 */
211 ExpNlsTableSize += 2 * PAGE_SIZE; // BIAS FOR FREELDR. HACK!
212
213 /* Allocate the a new buffer since loader memory will be freed */
214 ExpNlsTableBase = ExAllocatePoolWithTag(NonPagedPool,
215 ExpNlsTableSize,
216 TAG('R', 't', 'l', 'i'));
217 if (!ExpNlsTableBase) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
218
219 /* Copy the codepage data in its new location. */
220 RtlCopyMemory(ExpNlsTableBase,
221 LoaderBlock->NlsData->AnsiCodePageData,
222 ExpNlsTableSize);
223
224 /* Initialize and reset the NLS TAbles */
225 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
226 ExpAnsiCodePageDataOffset),
227 (PVOID)((ULONG_PTR)ExpNlsTableBase +
228 ExpOemCodePageDataOffset),
229 (PVOID)((ULONG_PTR)ExpNlsTableBase +
230 ExpUnicodeCaseTableDataOffset),
231 &ExpNlsTableInfo);
232 RtlResetRtlTranslations(&ExpNlsTableInfo);
233 return;
234 }
235
236 /* Set the section size */
237 SectionSize.QuadPart = ExpNlsTableSize;
238
239 /* Create the NLS Section */
240 Status = ZwCreateSection(&NlsSection,
241 SECTION_ALL_ACCESS,
242 NULL,
243 &SectionSize,
244 PAGE_READWRITE,
245 SEC_COMMIT,
246 NULL);
247 if (!NT_SUCCESS(Status))
248 {
249 /* Failed */
250 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 1, 0, 0);
251 }
252
253 /* Get a pointer to the section */
254 Status = ObReferenceObjectByHandle(NlsSection,
255 SECTION_ALL_ACCESS,
256 MmSectionObjectType,
257 KernelMode,
258 &ExpNlsSectionPointer,
259 NULL);
260 ZwClose(NlsSection);
261 if (!NT_SUCCESS(Status))
262 {
263 /* Failed */
264 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 2, 0, 0);
265 }
266
267 /* Map the NLS Section in system space */
268 Status = MmMapViewInSystemSpace(ExpNlsSectionPointer,
269 &SectionBase,
270 &ExpNlsTableSize);
271 if (!NT_SUCCESS(Status))
272 {
273 /* Failed */
274 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 3, 0, 0);
275 }
276
277 /* Copy the codepage data in its new location. */
278 RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
279
280 /* Free the previously allocated buffer and set the new location */
281 ExFreePool(ExpNlsTableBase);
282 ExpNlsTableBase = SectionBase;
283
284 /* Initialize the NLS Tables */
285 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
286 ExpAnsiCodePageDataOffset),
287 (PVOID)((ULONG_PTR)ExpNlsTableBase +
288 ExpOemCodePageDataOffset),
289 (PVOID)((ULONG_PTR)ExpNlsTableBase +
290 ExpUnicodeCaseTableDataOffset),
291 &ExpNlsTableInfo);
292 RtlResetRtlTranslations(&ExpNlsTableInfo);
293
294 /* Reset the base to 0 */
295 SectionBase = NULL;
296
297 /* Map the section in the system process */
298 Status = MmMapViewOfSection(ExpNlsSectionPointer,
299 PsGetCurrentProcess(),
300 &SectionBase,
301 0L,
302 0L,
303 &SectionOffset,
304 &ViewSize,
305 ViewShare,
306 0L,
307 PAGE_READWRITE);
308 if (!NT_SUCCESS(Status))
309 {
310 /* Failed */
311 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 5, 0, 0);
312 }
313
314 /* Copy the table into the system process and set this as the base */
315 RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
316 ExpNlsTableBase = SectionBase;
317 }
318
319 NTSTATUS
320 NTAPI
321 ExpLoadInitialProcess(IN OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation)
322 {
323 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
324 NTSTATUS Status;
325 ULONG Size;
326 PWSTR p;
327 UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
328 UNICODE_STRING SmssName, Environment, SystemDriveString;
329 PVOID EnvironmentPtr = NULL;
330
331 /* Allocate memory for the process parameters */
332 Size = sizeof(RTL_USER_PROCESS_PARAMETERS) +
333 ((MAX_PATH * 6) * sizeof(WCHAR));
334 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
335 (PVOID)&ProcessParameters,
336 0,
337 &Size,
338 MEM_COMMIT,
339 PAGE_READWRITE);
340 if (!NT_SUCCESS(Status))
341 {
342 /* Failed */
343 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED, Status, 0, 0, 0);
344 }
345
346 /* Setup the basic header, and give the process the low 1MB to itself */
347 ProcessParameters->Length = Size;
348 ProcessParameters->MaximumLength = Size;
349 ProcessParameters->Flags = RTL_USER_PROCESS_PARAMETERS_NORMALIZED |
350 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
351
352 /* Allocate a page for the environment */
353 Size = PAGE_SIZE;
354 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
355 &EnvironmentPtr,
356 0,
357 &Size,
358 MEM_COMMIT,
359 PAGE_READWRITE);
360 if (!NT_SUCCESS(Status))
361 {
362 /* Failed */
363 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
364 }
365
366 /* Write the pointer */
367 ProcessParameters->Environment = EnvironmentPtr;
368
369 /* Make a buffer for the DOS path */
370 p = (PWSTR)(ProcessParameters + 1);
371 ProcessParameters->CurrentDirectory.DosPath.Buffer = p;
372 ProcessParameters->
373 CurrentDirectory.DosPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
374
375 /* Copy the DOS path */
376 RtlCopyUnicodeString(&ProcessParameters->CurrentDirectory.DosPath,
377 &NtSystemRoot);
378
379 /* Make a buffer for the DLL Path */
380 p = (PWSTR)((PCHAR)ProcessParameters->CurrentDirectory.DosPath.Buffer +
381 ProcessParameters->CurrentDirectory.DosPath.MaximumLength);
382 ProcessParameters->DllPath.Buffer = p;
383 ProcessParameters->DllPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
384
385 /* Copy the DLL path and append the system32 directory */
386 RtlCopyUnicodeString(&ProcessParameters->DllPath,
387 &ProcessParameters->CurrentDirectory.DosPath);
388 RtlAppendUnicodeToString(&ProcessParameters->DllPath, L"\\System32");
389
390 /* Make a buffer for the image name */
391 p = (PWSTR)((PCHAR)ProcessParameters->DllPath.Buffer +
392 ProcessParameters->DllPath.MaximumLength);
393 ProcessParameters->ImagePathName.Buffer = p;
394 ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
395
396 /* Make sure the buffer is a valid string which within the given length */
397 if ((NtInitialUserProcessBufferType != REG_SZ) ||
398 ((NtInitialUserProcessBufferLength != -1) &&
399 ((NtInitialUserProcessBufferLength < sizeof(WCHAR)) ||
400 (NtInitialUserProcessBufferLength >
401 sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR)))))
402 {
403 /* Invalid initial process string, bugcheck */
404 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED,
405 (ULONG_PTR)STATUS_INVALID_PARAMETER,
406 NtInitialUserProcessBufferType,
407 NtInitialUserProcessBufferLength,
408 sizeof(NtInitialUserProcessBuffer));
409 }
410
411 /* Cut out anything after a space */
412 p = NtInitialUserProcessBuffer;
413 while (*p && *p != L' ') p++;
414
415 /* Set the image path length */
416 ProcessParameters->ImagePathName.Length =
417 (USHORT)((PCHAR)p - (PCHAR)NtInitialUserProcessBuffer);
418
419 /* Copy the actual buffer */
420 RtlCopyMemory(ProcessParameters->ImagePathName.Buffer,
421 NtInitialUserProcessBuffer,
422 ProcessParameters->ImagePathName.Length);
423
424 /* Null-terminate it */
425 ProcessParameters->
426 ImagePathName.Buffer[ProcessParameters->ImagePathName.Length /
427 sizeof(WCHAR)] = UNICODE_NULL;
428
429 /* Make a buffer for the command line */
430 p = (PWSTR)((PCHAR)ProcessParameters->ImagePathName.Buffer +
431 ProcessParameters->ImagePathName.MaximumLength);
432 ProcessParameters->CommandLine.Buffer = p;
433 ProcessParameters->CommandLine.MaximumLength = MAX_PATH * sizeof(WCHAR);
434
435 /* Add the image name to the command line */
436 RtlAppendUnicodeToString(&ProcessParameters->CommandLine,
437 NtInitialUserProcessBuffer);
438
439 /* Create the environment string */
440 RtlInitEmptyUnicodeString(&Environment,
441 ProcessParameters->Environment,
442 (USHORT)Size);
443
444 /* Append the DLL path to it */
445 RtlAppendUnicodeToString(&Environment, L"Path=" );
446 RtlAppendUnicodeStringToString(&Environment, &ProcessParameters->DllPath);
447 RtlAppendUnicodeStringToString(&Environment, &NullString );
448
449 /* Create the system drive string */
450 SystemDriveString = NtSystemRoot;
451 SystemDriveString.Length = 2 * sizeof(WCHAR);
452
453 /* Append it to the environment */
454 RtlAppendUnicodeToString(&Environment, L"SystemDrive=");
455 RtlAppendUnicodeStringToString(&Environment, &SystemDriveString);
456 RtlAppendUnicodeStringToString(&Environment, &NullString);
457
458 /* Append the system root to the environment */
459 RtlAppendUnicodeToString(&Environment, L"SystemRoot=");
460 RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
461 RtlAppendUnicodeStringToString(&Environment, &NullString);
462
463 /* Create SMSS process */
464 SmssName = ProcessParameters->ImagePathName;
465 Status = RtlCreateUserProcess(&SmssName,
466 OBJ_CASE_INSENSITIVE,
467 RtlDeNormalizeProcessParams(
468 ProcessParameters),
469 NULL,
470 NULL,
471 NULL,
472 FALSE,
473 NULL,
474 NULL,
475 ProcessInformation);
476 if (!NT_SUCCESS(Status))
477 {
478 /* Failed */
479 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED, Status, 0, 0, 0);
480 }
481
482 /* Resume the thread */
483 Status = ZwResumeThread(ProcessInformation->ThreadHandle, NULL);
484 if (!NT_SUCCESS(Status))
485 {
486 /* Failed */
487 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
488 }
489
490 /* Return success */
491 return STATUS_SUCCESS;
492 }
493
494 ULONG
495 NTAPI
496 ExComputeTickCountMultiplier(IN ULONG ClockIncrement)
497 {
498 ULONG MsRemainder = 0, MsIncrement;
499 ULONG IncrementRemainder;
500 ULONG i;
501
502 /* Count the number of milliseconds for each clock interrupt */
503 MsIncrement = ClockIncrement / (10 * 1000);
504
505 /* Count the remainder from the division above, with 24-bit precision */
506 IncrementRemainder = ClockIncrement - (MsIncrement * (10 * 1000));
507 for (i= 0; i < 24; i++)
508 {
509 /* Shift the remainders */
510 MsRemainder <<= 1;
511 IncrementRemainder <<= 1;
512
513 /* Check if we've went past 1 ms */
514 if (IncrementRemainder >= (10 * 1000))
515 {
516 /* Increase the remainder by one, and substract from increment */
517 IncrementRemainder -= (10 * 1000);
518 MsRemainder |= 1;
519 }
520 }
521
522 /* Return the increment */
523 return (MsIncrement << 24) | MsRemainder;
524 }
525
526 BOOLEAN
527 NTAPI
528 ExpInitSystemPhase0(VOID)
529 {
530 /* Initialize EXRESOURCE Support */
531 ExpResourceInitialization();
532
533 /* Initialize the environment lock */
534 ExInitializeFastMutex(&ExpEnvironmentLock);
535
536 /* Initialize the lookaside lists and locks */
537 ExpInitLookasideLists();
538
539 /* Initialize the Firmware Table resource and listhead */
540 InitializeListHead(&ExpFirmwareTableProviderListHead);
541 ExInitializeResourceLite(&ExpFirmwareTableResource);
542
543 /* Set the suite mask to maximum and return */
544 ExSuiteMask = 0xFFFFFFFF;
545 return TRUE;
546 }
547
548 BOOLEAN
549 NTAPI
550 ExpInitSystemPhase1(VOID)
551 {
552 /* Initialize worker threads */
553 ExpInitializeWorkerThreads();
554
555 /* Initialize pushlocks */
556 ExpInitializePushLocks();
557
558 /* Initialize events and event pairs */
559 ExpInitializeEventImplementation();
560 ExpInitializeEventPairImplementation();
561
562 /* Initialize callbacks */
563 ExpInitializeCallbacks();
564
565 /* Initialize mutants */
566 ExpInitializeMutantImplementation();
567
568 /* Initialize semaphores */
569 ExpInitializeSemaphoreImplementation();
570
571 /* Initialize timers */
572 ExpInitializeTimerImplementation();
573
574 /* Initialize profiling */
575 ExpInitializeProfileImplementation();
576
577 /* Initialize UUIDs */
578 ExpInitUuids();
579
580 /* Initialize Win32K */
581 ExpWin32kInit();
582 return TRUE;
583 }
584
585 BOOLEAN
586 NTAPI
587 ExInitSystem(VOID)
588 {
589 /* Check the initialization phase */
590 switch (ExpInitializationPhase)
591 {
592 case 0:
593
594 /* Do Phase 0 */
595 return ExpInitSystemPhase0();
596
597 case 1:
598
599 /* Do Phase 1 */
600 return ExpInitSystemPhase1();
601
602 default:
603
604 /* Don't know any other phase! Bugcheck! */
605 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL);
606 return FALSE;
607 }
608 }
609
610 BOOLEAN
611 NTAPI
612 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
613 {
614 PLOADER_PARAMETER_EXTENSION Extension;
615
616 /* Get the loader extension */
617 Extension = LoaderBlock->Extension;
618
619 /* Validate the size (larger structures are OK, we'll just ignore them) */
620 if (Extension->Size < sizeof(LOADER_PARAMETER_EXTENSION)) return FALSE;
621
622 /* Don't validate upper versions */
623 if (Extension->MajorVersion > 5) return TRUE;
624
625 /* Fail if this is NT 4 */
626 if (Extension->MajorVersion < 5) return FALSE;
627
628 /* Fail if this is XP */
629 if (Extension->MinorVersion < 2) return FALSE;
630
631 /* This is 2003 or newer, approve it */
632 return TRUE;
633 }
634
635 VOID
636 NTAPI
637 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
638 {
639 ULONG i = 0;
640 PLIST_ENTRY NextEntry;
641 ULONG Count, Length;
642 PWCHAR Name;
643 PLDR_DATA_TABLE_ENTRY LdrEntry;
644 BOOLEAN OverFlow = FALSE;
645 CHAR NameBuffer[256];
646 ANSI_STRING SymbolString;
647
648 /* Loop the driver list */
649 NextEntry = LoaderBlock->LoadOrderListHead.Flink;
650 while (NextEntry != &LoaderBlock->LoadOrderListHead)
651 {
652 /* Skip the first two images */
653 if (i >= 2)
654 {
655 /* Get the entry */
656 LdrEntry = CONTAINING_RECORD(NextEntry,
657 LDR_DATA_TABLE_ENTRY,
658 InLoadOrderLinks);
659 if (LdrEntry->FullDllName.Buffer[0] == L'\\')
660 {
661 /* We have a name, read its data */
662 Name = LdrEntry->FullDllName.Buffer;
663 Length = LdrEntry->FullDllName.Length / sizeof(WCHAR);
664
665 /* Check if our buffer can hold it */
666 if (sizeof(NameBuffer) < Length + sizeof(ANSI_NULL))
667 {
668 /* It's too long */
669 OverFlow = TRUE;
670 }
671 else
672 {
673 /* Copy the name */
674 for (Count = 0; Count < Length; Count++, Name++)
675 {
676 /* Copy the character */
677 NameBuffer[Count] = (CHAR)*Name;
678 }
679
680 /* Null-terminate */
681 NameBuffer[Count] = ANSI_NULL;
682 }
683 }
684 else
685 {
686 /* This should be a driver, check if it fits */
687 if (sizeof(NameBuffer) <
688 (sizeof("\\System32\\Drivers\\") +
689 NtSystemRoot.Length / sizeof(WCHAR) - sizeof(UNICODE_NULL) +
690 LdrEntry->BaseDllName.Length / sizeof(WCHAR) +
691 sizeof(ANSI_NULL)))
692 {
693 /* Buffer too small */
694 OverFlow = TRUE;
695 }
696 else
697 {
698 /* Otherwise build the name. HACKED for GCC :( */
699 sprintf(NameBuffer,
700 "%c\\System32\\Drivers\\%S",
701 SharedUserData->NtSystemRoot[2],
702 LdrEntry->BaseDllName.Buffer);
703 }
704 }
705
706 /* Check if the buffer was ok */
707 if (!OverFlow)
708 {
709 /* Initialize the ANSI_STRING for the debugger */
710 RtlInitString(&SymbolString, NameBuffer);
711
712 /* Load the symbols */
713 DbgLoadImageSymbols(&SymbolString,
714 LdrEntry->DllBase,
715 0xFFFFFFFF);
716 }
717 }
718
719 /* Go to the next entry */
720 i++;
721 NextEntry = NextEntry->Flink;
722 }
723
724 /* Check if we should break after symbol load */
725 if (KdBreakAfterSymbolLoad) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
726 }
727
728 VOID
729 NTAPI
730 ExpInitializeExecutive(IN ULONG Cpu,
731 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
732 {
733 PNLS_DATA_BLOCK NlsData;
734 CHAR Buffer[256];
735 ANSI_STRING AnsiPath;
736 NTSTATUS Status;
737 PCHAR CommandLine, PerfMem;
738 ULONG PerfMemUsed;
739
740 /* Validate Loader */
741 if (!ExpIsLoaderValid(LoaderBlock))
742 {
743 /* Invalid loader version */
744 KeBugCheckEx(MISMATCHED_HAL,
745 3,
746 LoaderBlock->Extension->Size,
747 LoaderBlock->Extension->MajorVersion,
748 LoaderBlock->Extension->MinorVersion);
749 }
750
751 /* Initialize PRCB pool lookaside pointers */
752 ExInitPoolLookasidePointers();
753
754 /* Check if this is an application CPU */
755 if (Cpu)
756 {
757 /* Then simply initialize it with HAL */
758 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
759 {
760 /* Initialization failed */
761 KeBugCheck(HAL_INITIALIZATION_FAILED);
762 }
763
764 /* We're done */
765 return;
766 }
767
768 /* Assume no text-mode or remote boot */
769 ExpInTextModeSetup = FALSE;
770 IoRemoteBootClient = FALSE;
771
772 /* Check if we have a setup loader block */
773 if (LoaderBlock->SetupLdrBlock)
774 {
775 /* Check if this is text-mode setup */
776 if (LoaderBlock->SetupLdrBlock->Flags & 1) ExpInTextModeSetup = TRUE;
777
778 /* Check if this is network boot */
779 if (LoaderBlock->SetupLdrBlock->Flags & 2)
780 {
781 /* Set variable */
782 IoRemoteBootClient = TRUE;
783
784 /* Make sure we're actually booting off the network */
785 ASSERT(!_memicmp(LoaderBlock->ArcBootDeviceName, "net(0)", 6));
786 }
787 }
788
789 /* Set phase to 0 */
790 ExpInitializationPhase = 0;
791
792 /* Get boot command line */
793 CommandLine = LoaderBlock->LoadOptions;
794 if (CommandLine)
795 {
796 /* Upcase it for comparison and check if we're in performance mode */
797 _strupr(CommandLine);
798 PerfMem = strstr(CommandLine, "PERFMEM");
799 if (PerfMem)
800 {
801 /* Check if the user gave a number of bytes to use */
802 PerfMem = strstr(PerfMem, "=");
803 if (PerfMem)
804 {
805 /* Read the number of pages we'll use */
806 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
807 if (PerfMem)
808 {
809 /* FIXME: TODO */
810 DPRINT1("BBT performance mode not yet supported."
811 "/PERFMEM option ignored.\n");
812 }
813 }
814 }
815
816 /* Check if we're burning memory */
817 PerfMem = strstr(CommandLine, "BURNMEMORY");
818 if (PerfMem)
819 {
820 /* Check if the user gave a number of bytes to use */
821 PerfMem = strstr(PerfMem, "=");
822 if (PerfMem)
823 {
824 /* Read the number of pages we'll use */
825 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE);
826 if (PerfMem)
827 {
828 /* FIXME: TODO */
829 DPRINT1("Burnable memory support not yet present."
830 "/BURNMEM option ignored.\n");
831 }
832 }
833 }
834 }
835
836 /* Setup NLS Base and offsets */
837 NlsData = LoaderBlock->NlsData;
838 ExpNlsTableBase = NlsData->AnsiCodePageData;
839 ExpAnsiCodePageDataOffset = 0;
840 ExpOemCodePageDataOffset = ((ULONG_PTR)NlsData->OemCodePageData -
841 (ULONG_PTR)NlsData->AnsiCodePageData);
842 ExpUnicodeCaseTableDataOffset = ((ULONG_PTR)NlsData->UnicodeCodePageData -
843 (ULONG_PTR)NlsData->AnsiCodePageData);
844
845 /* Initialize the NLS Tables */
846 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
847 ExpAnsiCodePageDataOffset),
848 (PVOID)((ULONG_PTR)ExpNlsTableBase +
849 ExpOemCodePageDataOffset),
850 (PVOID)((ULONG_PTR)ExpNlsTableBase +
851 ExpUnicodeCaseTableDataOffset),
852 &ExpNlsTableInfo);
853 RtlResetRtlTranslations(&ExpNlsTableInfo);
854
855 /* Now initialize the HAL */
856 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
857 {
858 /* HAL failed to initialize, bugcheck */
859 KeBugCheck(HAL_INITIALIZATION_FAILED);
860 }
861
862 /* Make sure interrupts are active now */
863 _enable();
864
865 /* Clear the crypto exponent */
866 SharedUserData->CryptoExponent = 0;
867
868 /* Set global flags for the checked build */
869 #if DBG
870 NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS |
871 FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
872 #endif
873
874 /* Setup NT System Root Path */
875 sprintf(Buffer, "C:%s", LoaderBlock->NtBootPathName);
876
877 /* Convert to ANSI_STRING and null-terminate it */
878 RtlInitString(&AnsiPath, Buffer );
879 Buffer[--AnsiPath.Length] = ANSI_NULL;
880
881 /* Get the string from KUSER_SHARED_DATA's buffer */
882 RtlInitEmptyUnicodeString(&NtSystemRoot,
883 SharedUserData->NtSystemRoot,
884 sizeof(SharedUserData->NtSystemRoot));
885
886 /* Now fill it in */
887 Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
888 if (!NT_SUCCESS(Status)) KEBUGCHECK(SESSION3_INITIALIZATION_FAILED);
889
890 /* Setup bugcheck messages */
891 KiInitializeBugCheck();
892
893 /* Setup initial system settings (FIXME: Needs Cm Rewrite) */
894 CmGetSystemControlValues(LoaderBlock->RegistryBase, CmControlVector);
895
896 /* Initialize the executive at phase 0 */
897 if (!ExInitSystem()) KEBUGCHECK(PHASE0_INITIALIZATION_FAILED);
898
899 /* Load boot symbols */
900 ExpLoadBootSymbols(LoaderBlock);
901
902 /* Set system ranges */
903 SharedUserData->Reserved1 = (ULONG_PTR)MmHighestUserAddress;
904 SharedUserData->Reserved3 = (ULONG_PTR)MmSystemRangeStart;
905
906 /* Make a copy of the NLS Tables */
907 ExpInitNls(LoaderBlock);
908
909 /* Check if the user wants a kernel stack trace database */
910 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB)
911 {
912 /* FIXME: TODO */
913 DPRINT1("Kernel-mode stack trace support not yet present."
914 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n");
915 }
916
917 /* Check if he wanted exception logging */
918 if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING)
919 {
920 /* FIXME: TODO */
921 DPRINT1("Kernel-mode exception logging support not yet present."
922 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n");
923 }
924
925 /* Initialize the Handle Table */
926 ExpInitializeHandleTables();
927
928 #if DBG
929 /* On checked builds, allocate the system call count table */
930 KeServiceDescriptorTable[0].Count =
931 ExAllocatePoolWithTag(NonPagedPool,
932 KiServiceLimit * sizeof(ULONG),
933 TAG('C', 'a', 'l', 'l'));
934
935 /* Use it for the shadow table too */
936 KeServiceDescriptorTableShadow[0].Count = KeServiceDescriptorTable[0].Count;
937
938 /* Make sure allocation succeeded */
939 if (KeServiceDescriptorTable[0].Count)
940 {
941 /* Zero the call counts to 0 */
942 RtlZeroMemory(KeServiceDescriptorTable[0].Count,
943 KiServiceLimit * sizeof(ULONG));
944 }
945 #endif
946
947 /* Create the Basic Object Manager Types to allow new Object Types */
948 if (!ObInit()) KEBUGCHECK(OBJECT_INITIALIZATION_FAILED);
949
950 /* Load basic Security for other Managers */
951 if (!SeInit()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
952
953 /* Initialize the Process Manager */
954 if (!PsInitSystem(LoaderBlock)) KEBUGCHECK(PROCESS_INITIALIZATION_FAILED);
955
956 /* Initialize the PnP Manager */
957 if (!PpInitSystem()) KEBUGCHECK(PP0_INITIALIZATION_FAILED);
958
959 /* Initialize the User-Mode Debugging Subsystem */
960 DbgkInitialize();
961
962 /* Calculate the tick count multiplier */
963 ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement);
964 SharedUserData->TickCountMultiplier = ExpTickCountMultiplier;
965
966 /* Set the OS Version */
967 SharedUserData->NtMajorVersion = NtMajorVersion;
968 SharedUserData->NtMinorVersion = NtMinorVersion;
969
970 /* Set the machine type */
971 #if defined(_X86_)
972 SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_I386;
973 SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_I386;
974 #elif defined(_PPC_) // <3 Arty
975 SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_POWERPC;
976 SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_POWERPC;
977 #elif
978 #error "Unsupported ReactOS Target"
979 #endif
980 }
981
982 VOID
983 NTAPI
984 Phase1InitializationDiscard(PVOID Context)
985 {
986 PLOADER_PARAMETER_BLOCK LoaderBlock = Context;
987 PCHAR CommandLine, Y2KHackRequired;
988 LARGE_INTEGER Timeout;
989 NTSTATUS Status;
990 TIME_FIELDS TimeFields;
991 LARGE_INTEGER SystemBootTime, UniversalBootTime, OldTime;
992 PRTL_USER_PROCESS_INFORMATION ProcessInfo;
993 BOOLEAN SosEnabled, NoGuiBoot;
994 ULONG YearHack = 0;
995
996 /* Allocate initial process information */
997 ProcessInfo = ExAllocatePoolWithTag(NonPagedPool,
998 sizeof(RTL_USER_PROCESS_INFORMATION),
999 TAG('I', 'n', 'i', 't'));
1000 if (!ProcessInfo)
1001 {
1002 /* Bugcheck */
1003 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 8, 0, 0);
1004 }
1005
1006 /* Set to phase 1 */
1007 ExpInitializationPhase = 1;
1008
1009 /* Set us at maximum priority */
1010 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY);
1011
1012 /* Do Phase 1 HAL Initialization */
1013 if (!HalInitSystem(1, LoaderBlock)) KeBugCheck(HAL1_INITIALIZATION_FAILED);
1014
1015 /* Get the command line and upcase it */
1016 CommandLine = _strupr(LoaderBlock->LoadOptions);
1017
1018 /* Check if GUI Boot is enabled */
1019 NoGuiBoot = (strstr(CommandLine, "NOGUIBOOT")) ? TRUE: FALSE;
1020
1021 /* Get the SOS setting */
1022 SosEnabled = strstr(CommandLine, "SOS") ? TRUE: FALSE;
1023
1024 /* Setup the boot driver */
1025 InbvEnableBootDriver(!NoGuiBoot);
1026 InbvDriverInitialize(LoaderBlock, 18);
1027
1028 /* Check if GUI boot is enabled */
1029 if (!NoGuiBoot)
1030 {
1031 /* It is, display the boot logo and enable printing strings */
1032 InbvEnableDisplayString(SosEnabled);
1033 DisplayBootBitmap(SosEnabled);
1034 }
1035 else
1036 {
1037 /* Release display ownership if not using GUI boot */
1038 InbvNotifyDisplayOwnershipLost(NULL);
1039
1040 /* Don't allow boot-time strings */
1041 InbvEnableDisplayString(FALSE);
1042 }
1043
1044 /* Check if this is LiveCD (WinPE) mode */
1045 if (strstr(CommandLine, "MININT"))
1046 {
1047 /* Setup WinPE Settings */
1048 InitIsWinPEMode = TRUE;
1049 InitWinPEModeType |= (strstr(CommandLine, "INRAM")) ? 0x80000000 : 1;
1050 }
1051
1052 /* FIXME: Print product name, version, and build */
1053
1054 /* Initialize Power Subsystem in Phase 0 */
1055 if (!PoInitSystem(0, AcpiTableDetected)) KeBugCheck(INTERNAL_POWER_ERROR);
1056
1057 /* Check for Y2K hack */
1058 Y2KHackRequired = strstr(CommandLine, "YEAR");
1059 if (Y2KHackRequired) Y2KHackRequired = strstr(Y2KHackRequired, "=");
1060 if (Y2KHackRequired) YearHack = atol(Y2KHackRequired + 1);
1061
1062 /* Query the clock */
1063 if ((ExCmosClockIsSane) && (HalQueryRealTimeClock(&TimeFields)))
1064 {
1065 /* Check if we're using the Y2K hack */
1066 if (Y2KHackRequired) TimeFields.Year = (CSHORT)YearHack;
1067
1068 /* Convert to time fields */
1069 RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
1070 UniversalBootTime = SystemBootTime;
1071
1072 #if 0 // FIXME: Won't work until we can read registry data here
1073 /* FIXME: This assumes that the RTC is not already in GMT */
1074 ExpTimeZoneBias.QuadPart = Int32x32To64(ExpLastTimeZoneBias * 60,
1075 10000000);
1076
1077 /* Set the boot time-zone bias */
1078 SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
1079 SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
1080 SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
1081
1082 /* Convert the boot time to local time, and set it */
1083 UniversalBootTime.QuadPart = SystemBootTime.QuadPart +
1084 ExpTimeZoneBias.QuadPart;
1085 #endif
1086
1087 /* Update the system time */
1088 KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL);
1089
1090 /* Remember this as the boot time */
1091 KeBootTime = UniversalBootTime;
1092 KeBootTimeBias = 0;
1093 }
1094
1095 /* Initialize all processors */
1096 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED);
1097
1098 /* FIXME: Print CPU and Memory */
1099
1100 /* Update the progress bar */
1101 InbvUpdateProgressBar(5);
1102
1103 /* Call OB initialization again */
1104 if (!ObInit()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED);
1105
1106 /* Initialize Basic System Objects and Worker Threads */
1107 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 1, 0);
1108
1109 /* Initialize the later stages of the kernel */
1110 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 2, 0);
1111
1112 /* Call KD Providers at Phase 1 */
1113 if (!KdInitSystem(ExpInitializationPhase, KeLoaderBlock))
1114 {
1115 /* Failed, bugcheck */
1116 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 3, 0);
1117 }
1118
1119 /* Initialize the SRM in Phase 1 */
1120 if (!SeInit()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
1121
1122 /* Update the progress bar */
1123 InbvUpdateProgressBar(10);
1124
1125 /* Create SystemRoot Link */
1126 Status = ExpCreateSystemRootLink(LoaderBlock);
1127 if (!NT_SUCCESS(Status))
1128 {
1129 /* Failed to create the system root link */
1130 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 0, 0, 0);
1131 }
1132
1133 /* Set up Region Maps, Sections and the Paging File */
1134 if (!MmInitSystem(1, LoaderBlock)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED);
1135
1136 /* Create NLS section */
1137 ExpInitNls(KeLoaderBlock);
1138
1139 /* Initialize Cache Views */
1140 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED);
1141
1142 /* Initialize the Registry */
1143 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED);
1144
1145 /* Update progress bar */
1146 InbvUpdateProgressBar(15);
1147
1148 /* Update timezone information */
1149 ExRefreshTimeZoneInformation(&SystemBootTime);
1150
1151 /* Initialize the File System Runtime Library */
1152 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED);
1153
1154 /* Report all resources used by HAL */
1155 HalReportResourceUsage();
1156
1157 /* Call the debugger DLL once we have KD64 6.0 support */
1158 //KdDebuggerInitialize1(LoaderBlock);
1159
1160 /* Setup PnP Manager in phase 1 */
1161 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED);
1162
1163 /* Update progress bar */
1164 InbvUpdateProgressBar(20);
1165
1166 /* Initialize LPC */
1167 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED);
1168
1169 /* Initialize the I/O Subsystem */
1170 if (!IoInitSystem(KeLoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED);
1171
1172 /* Unmap Low memory, and initialize the MPW and Balancer Thread */
1173 MmInitSystem(2, LoaderBlock);
1174
1175 /* Update progress bar */
1176 InbvUpdateProgressBar(80);
1177
1178 /* Initialize VDM support */
1179 KeI386VdmInitialize();
1180
1181 /* Initialize Power Subsystem in Phase 1*/
1182 if (!PoInitSystem(1, AcpiTableDetected)) KeBugCheck(INTERNAL_POWER_ERROR);
1183
1184 /* Initialize the Process Manager at Phase 1 */
1185 if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
1186
1187 /* Update progress bar */
1188 InbvUpdateProgressBar(85);
1189
1190 /* Make sure nobody touches the loader block again */
1191 if (LoaderBlock == KeLoaderBlock) KeLoaderBlock = NULL;
1192 LoaderBlock = Context = NULL;
1193
1194 /* Update progress bar */
1195 InbvUpdateProgressBar(90);
1196
1197 /* Launch initial process */
1198 Status = ExpLoadInitialProcess(ProcessInfo);
1199
1200 /* Update progress bar */
1201 InbvUpdateProgressBar(100);
1202
1203 /* Allow strings to be displayed */
1204 InbvEnableDisplayString(TRUE);
1205
1206 /* Wait 5 seconds for it to initialize */
1207 Timeout.QuadPart = Int32x32To64(5, -10000000);
1208 Status = ZwWaitForSingleObject(ProcessInfo->ProcessHandle, FALSE, &Timeout);
1209 if (InbvBootDriverInstalled) FinalizeBootLogo();
1210
1211 if (Status == STATUS_SUCCESS)
1212 {
1213 /* Bugcheck the system if SMSS couldn't initialize */
1214 KeBugCheck(SESSION5_INITIALIZATION_FAILED);
1215 }
1216
1217 /* Close process handles */
1218 ZwClose(ProcessInfo->ThreadHandle);
1219 ZwClose(ProcessInfo->ProcessHandle);
1220
1221 /* FIXME: We should free the initial process' memory!*/
1222
1223 /* Increase init phase */
1224 ExpInitializationPhase += 1;
1225
1226 /* Free the process information */
1227 ExFreePool(ProcessInfo);
1228 }
1229
1230 VOID
1231 NTAPI
1232 Phase1Initialization(IN PVOID Context)
1233 {
1234 /* Do the .INIT part of Phase 1 which we can free later */
1235 Phase1InitializationDiscard(Context);
1236
1237 /* Jump into zero page thread */
1238 MmZeroPageThreadMain(NULL);
1239 }
1240