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 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include <ntoskrnl.h> 13 #include <reactos/buildno.h> 14 #define NDEBUG 15 #include <debug.h> 16 17 /* This is the size that we can expect from the win 2003 loader */ 18 #define LOADER_PARAMETER_EXTENSION_MIN_SIZE \ 19 RTL_SIZEOF_THROUGH_FIELD(LOADER_PARAMETER_EXTENSION, AcpiTableSize) 20 21 /* Temporary hack */ 22 BOOLEAN 23 NTAPI 24 MmArmInitSystem( 25 IN ULONG Phase, 26 IN PLOADER_PARAMETER_BLOCK LoaderBlock 27 ); 28 29 typedef struct _INIT_BUFFER 30 { 31 WCHAR DebugBuffer[256]; 32 CHAR VersionBuffer[256]; 33 CHAR BootlogHeader[256]; 34 CHAR VersionNumber[24]; 35 RTL_USER_PROCESS_INFORMATION ProcessInfo; 36 WCHAR RegistryBuffer[256]; 37 } INIT_BUFFER, *PINIT_BUFFER; 38 39 /* DATA **********************************************************************/ 40 41 /* NT Version Info */ 42 ULONG NtMajorVersion = VER_PRODUCTMAJORVERSION; 43 ULONG NtMinorVersion = VER_PRODUCTMINORVERSION; 44 #if DBG /* Checked Build */ 45 ULONG NtBuildNumber = VER_PRODUCTBUILD | 0xC0000000; 46 #else /* Free Build */ 47 ULONG NtBuildNumber = VER_PRODUCTBUILD; 48 #endif 49 50 /* NT System Info */ 51 ULONG NtGlobalFlag = 0; 52 ULONG ExSuiteMask; 53 54 /* Cm Version Info */ 55 ULONG CmNtSpBuildNumber; 56 ULONG CmNtCSDVersion; 57 ULONG CmNtCSDReleaseType; 58 UNICODE_STRING CmVersionString; 59 UNICODE_STRING CmCSDVersionString; 60 61 CHAR NtBuildLab[] = KERNEL_VERSION_BUILD_STR "." 62 REACTOS_COMPILER_NAME "_" REACTOS_COMPILER_VERSION; 63 64 /* Init flags and settings */ 65 ULONG ExpInitializationPhase; 66 BOOLEAN ExpInTextModeSetup; 67 BOOLEAN IoRemoteBootClient; 68 ULONG InitSafeBootMode; 69 BOOLEAN InitIsWinPEMode, InitWinPEModeType; 70 71 /* NT Boot Path */ 72 UNICODE_STRING NtSystemRoot; 73 74 /* NT Initial User Application */ 75 WCHAR NtInitialUserProcessBuffer[128] = L"\\SystemRoot\\System32\\smss.exe"; 76 ULONG NtInitialUserProcessBufferLength = sizeof(NtInitialUserProcessBuffer) - 77 sizeof(WCHAR); 78 ULONG NtInitialUserProcessBufferType = REG_SZ; 79 80 /* Boot NLS information */ 81 PVOID ExpNlsTableBase; 82 ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset; 83 ULONG ExpUnicodeCaseTableDataOffset; 84 NLSTABLEINFO ExpNlsTableInfo; 85 SIZE_T ExpNlsTableSize; 86 PVOID ExpNlsSectionPointer; 87 88 /* CMOS Timer Sanity */ 89 BOOLEAN ExCmosClockIsSane = TRUE; 90 BOOLEAN ExpRealTimeIsUniversal; 91 92 /* FUNCTIONS ****************************************************************/ 93 94 NTSTATUS 95 NTAPI 96 INIT_FUNCTION 97 ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 98 { 99 UNICODE_STRING LinkName; 100 OBJECT_ATTRIBUTES ObjectAttributes; 101 HANDLE LinkHandle; 102 NTSTATUS Status; 103 ANSI_STRING AnsiName; 104 CHAR Buffer[256]; 105 ANSI_STRING TargetString; 106 UNICODE_STRING TargetName; 107 108 /* Initialize the ArcName tree */ 109 RtlInitUnicodeString(&LinkName, L"\\ArcName"); 110 InitializeObjectAttributes(&ObjectAttributes, 111 &LinkName, 112 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 113 NULL, 114 SePublicDefaultUnrestrictedSd); 115 116 /* Create it */ 117 Status = NtCreateDirectoryObject(&LinkHandle, 118 DIRECTORY_ALL_ACCESS, 119 &ObjectAttributes); 120 if (!NT_SUCCESS(Status)) 121 { 122 /* Failed */ 123 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 1, 0, 0); 124 } 125 126 /* Close the LinkHandle */ 127 NtClose(LinkHandle); 128 129 /* Initialize the Device tree */ 130 RtlInitUnicodeString(&LinkName, L"\\Device"); 131 InitializeObjectAttributes(&ObjectAttributes, 132 &LinkName, 133 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 134 NULL, 135 SePublicDefaultUnrestrictedSd); 136 137 /* Create it */ 138 Status = NtCreateDirectoryObject(&LinkHandle, 139 DIRECTORY_ALL_ACCESS, 140 &ObjectAttributes); 141 if (!NT_SUCCESS(Status)) 142 { 143 /* Failed */ 144 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 2, 0, 0); 145 } 146 147 /* Close the LinkHandle */ 148 ObCloseHandle(LinkHandle, KernelMode); 149 150 /* Create the system root symlink name */ 151 RtlInitAnsiString(&AnsiName, "\\SystemRoot"); 152 Status = RtlAnsiStringToUnicodeString(&LinkName, &AnsiName, TRUE); 153 if (!NT_SUCCESS(Status)) 154 { 155 /* Failed */ 156 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 3, 0, 0); 157 } 158 159 /* Initialize the attributes for the link */ 160 InitializeObjectAttributes(&ObjectAttributes, 161 &LinkName, 162 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 163 NULL, 164 SePublicDefaultUnrestrictedSd); 165 166 /* Build the ARC name */ 167 sprintf(Buffer, 168 "\\ArcName\\%s%s", 169 LoaderBlock->ArcBootDeviceName, 170 LoaderBlock->NtBootPathName); 171 Buffer[strlen(Buffer) - 1] = ANSI_NULL; 172 173 /* Convert it to Unicode */ 174 RtlInitString(&TargetString, Buffer); 175 Status = RtlAnsiStringToUnicodeString(&TargetName, 176 &TargetString, 177 TRUE); 178 if (!NT_SUCCESS(Status)) 179 { 180 /* We failed, bugcheck */ 181 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 4, 0, 0); 182 } 183 184 /* Create it */ 185 Status = NtCreateSymbolicLinkObject(&LinkHandle, 186 SYMBOLIC_LINK_ALL_ACCESS, 187 &ObjectAttributes, 188 &TargetName); 189 190 /* Free the strings */ 191 RtlFreeUnicodeString(&LinkName); 192 RtlFreeUnicodeString(&TargetName); 193 194 /* Check if creating the link failed */ 195 if (!NT_SUCCESS(Status)) 196 { 197 /* Failed */ 198 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 5, 0, 0); 199 } 200 201 /* Close the handle and return success */ 202 ObCloseHandle(LinkHandle, KernelMode); 203 return STATUS_SUCCESS; 204 } 205 206 VOID 207 NTAPI 208 INIT_FUNCTION 209 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 210 { 211 LARGE_INTEGER SectionSize; 212 NTSTATUS Status; 213 HANDLE NlsSection; 214 PVOID SectionBase = NULL; 215 SIZE_T ViewSize = 0; 216 LARGE_INTEGER SectionOffset = {{0, 0}}; 217 PLIST_ENTRY ListHead, NextEntry; 218 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock; 219 ULONG NlsTablesEncountered = 0; 220 SIZE_T NlsTableSizes[3] = {0, 0, 0}; /* 3 NLS tables */ 221 222 /* Check if this is boot-time phase 0 initialization */ 223 if (!ExpInitializationPhase) 224 { 225 /* Loop the memory descriptors */ 226 ListHead = &LoaderBlock->MemoryDescriptorListHead; 227 NextEntry = ListHead->Flink; 228 while (NextEntry != ListHead) 229 { 230 /* Get the current block */ 231 MdBlock = CONTAINING_RECORD(NextEntry, 232 MEMORY_ALLOCATION_DESCRIPTOR, 233 ListEntry); 234 235 /* Check if this is an NLS block */ 236 if (MdBlock->MemoryType == LoaderNlsData) 237 { 238 /* Increase the table size */ 239 ExpNlsTableSize += MdBlock->PageCount * PAGE_SIZE; 240 241 /* FreeLdr-specific */ 242 NlsTableSizes[NlsTablesEncountered] = MdBlock->PageCount * PAGE_SIZE; 243 NlsTablesEncountered++; 244 ASSERT(NlsTablesEncountered < 4); 245 } 246 247 /* Go to the next block */ 248 NextEntry = MdBlock->ListEntry.Flink; 249 } 250 251 /* Allocate the a new buffer since loader memory will be freed */ 252 ExpNlsTableBase = ExAllocatePoolWithTag(NonPagedPool, 253 ExpNlsTableSize, 254 TAG_RTLI); 255 if (!ExpNlsTableBase) KeBugCheck(PHASE0_INITIALIZATION_FAILED); 256 257 /* Copy the codepage data in its new location. */ 258 if (NlsTablesEncountered == 1) 259 { 260 /* Ntldr-way boot process */ 261 RtlCopyMemory(ExpNlsTableBase, 262 LoaderBlock->NlsData->AnsiCodePageData, 263 ExpNlsTableSize); 264 } 265 else 266 { 267 /* 268 * In NT, the memory blocks are contiguous, but in ReactOS they aren't, 269 * so unless someone fixes FreeLdr, we'll have to use this icky hack. 270 */ 271 RtlCopyMemory(ExpNlsTableBase, 272 LoaderBlock->NlsData->AnsiCodePageData, 273 NlsTableSizes[0]); 274 275 RtlCopyMemory((PVOID)((ULONG_PTR)ExpNlsTableBase + NlsTableSizes[0]), 276 LoaderBlock->NlsData->OemCodePageData, 277 NlsTableSizes[1]); 278 279 RtlCopyMemory((PVOID)((ULONG_PTR)ExpNlsTableBase + NlsTableSizes[0] + 280 NlsTableSizes[1]), 281 LoaderBlock->NlsData->UnicodeCodePageData, 282 NlsTableSizes[2]); 283 /* End of Hack */ 284 } 285 286 /* Initialize and reset the NLS TAbles */ 287 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase + 288 ExpAnsiCodePageDataOffset), 289 (PVOID)((ULONG_PTR)ExpNlsTableBase + 290 ExpOemCodePageDataOffset), 291 (PVOID)((ULONG_PTR)ExpNlsTableBase + 292 ExpUnicodeCaseTableDataOffset), 293 &ExpNlsTableInfo); 294 RtlResetRtlTranslations(&ExpNlsTableInfo); 295 return; 296 } 297 298 /* Set the section size */ 299 SectionSize.QuadPart = ExpNlsTableSize; 300 301 /* Create the NLS Section */ 302 Status = ZwCreateSection(&NlsSection, 303 SECTION_ALL_ACCESS, 304 NULL, 305 &SectionSize, 306 PAGE_READWRITE, 307 SEC_COMMIT | 0x1, 308 NULL); 309 if (!NT_SUCCESS(Status)) 310 { 311 /* Failed */ 312 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 1, 0, 0); 313 } 314 315 /* Get a pointer to the section */ 316 Status = ObReferenceObjectByHandle(NlsSection, 317 SECTION_ALL_ACCESS, 318 MmSectionObjectType, 319 KernelMode, 320 &ExpNlsSectionPointer, 321 NULL); 322 ObCloseHandle(NlsSection, KernelMode); 323 if (!NT_SUCCESS(Status)) 324 { 325 /* Failed */ 326 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 2, 0, 0); 327 } 328 329 /* Map the NLS Section in system space */ 330 Status = MmMapViewInSystemSpace(ExpNlsSectionPointer, 331 &SectionBase, 332 &ExpNlsTableSize); 333 if (!NT_SUCCESS(Status)) 334 { 335 /* Failed */ 336 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 3, 0, 0); 337 } 338 339 /* Copy the codepage data in its new location. */ 340 ASSERT(SectionBase >= MmSystemRangeStart); 341 RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize); 342 343 /* Free the previously allocated buffer and set the new location */ 344 ExFreePoolWithTag(ExpNlsTableBase, TAG_RTLI); 345 ExpNlsTableBase = SectionBase; 346 347 /* Initialize the NLS Tables */ 348 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase + 349 ExpAnsiCodePageDataOffset), 350 (PVOID)((ULONG_PTR)ExpNlsTableBase + 351 ExpOemCodePageDataOffset), 352 (PVOID)((ULONG_PTR)ExpNlsTableBase + 353 ExpUnicodeCaseTableDataOffset), 354 &ExpNlsTableInfo); 355 RtlResetRtlTranslations(&ExpNlsTableInfo); 356 357 /* Reset the base to 0 */ 358 SectionBase = NULL; 359 360 /* Map the section in the system process */ 361 Status = MmMapViewOfSection(ExpNlsSectionPointer, 362 PsGetCurrentProcess(), 363 &SectionBase, 364 0L, 365 0L, 366 &SectionOffset, 367 &ViewSize, 368 ViewShare, 369 0L, 370 PAGE_READWRITE); 371 if (!NT_SUCCESS(Status)) 372 { 373 /* Failed */ 374 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 5, 0, 0); 375 } 376 377 /* Copy the table into the system process and set this as the base */ 378 RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize); 379 ExpNlsTableBase = SectionBase; 380 } 381 382 VOID 383 NTAPI 384 INIT_FUNCTION 385 ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer, 386 OUT PRTL_USER_PROCESS_PARAMETERS *ProcessParameters, 387 OUT PCHAR *ProcessEnvironment) 388 { 389 NTSTATUS Status; 390 SIZE_T Size; 391 PWSTR p; 392 UNICODE_STRING NullString = RTL_CONSTANT_STRING(L""); 393 UNICODE_STRING SmssName, Environment, SystemDriveString, DebugString; 394 PVOID EnvironmentPtr = NULL; 395 PRTL_USER_PROCESS_INFORMATION ProcessInformation; 396 PRTL_USER_PROCESS_PARAMETERS ProcessParams = NULL; 397 398 NullString.Length = sizeof(WCHAR); 399 400 /* Use the initial buffer, after the strings */ 401 ProcessInformation = &InitBuffer->ProcessInfo; 402 403 /* Allocate memory for the process parameters */ 404 Size = sizeof(*ProcessParams) + ((MAX_PATH * 6) * sizeof(WCHAR)); 405 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 406 (PVOID*)&ProcessParams, 407 0, 408 &Size, 409 MEM_RESERVE | MEM_COMMIT, 410 PAGE_READWRITE); 411 if (!NT_SUCCESS(Status)) 412 { 413 /* Failed, display error */ 414 _snwprintf(InitBuffer->DebugBuffer, 415 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR), 416 L"INIT: Unable to allocate Process Parameters. 0x%lx", 417 Status); 418 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer); 419 ZwDisplayString(&DebugString); 420 421 /* Bugcheck the system */ 422 KeBugCheckEx(SESSION1_INITIALIZATION_FAILED, Status, 0, 0, 0); 423 } 424 425 /* Setup the basic header, and give the process the low 1MB to itself */ 426 ProcessParams->Length = (ULONG)Size; 427 ProcessParams->MaximumLength = (ULONG)Size; 428 ProcessParams->Flags = RTL_USER_PROCESS_PARAMETERS_NORMALIZED | 429 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB; 430 431 /* Allocate a page for the environment */ 432 Size = PAGE_SIZE; 433 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 434 &EnvironmentPtr, 435 0, 436 &Size, 437 MEM_RESERVE | MEM_COMMIT, 438 PAGE_READWRITE); 439 if (!NT_SUCCESS(Status)) 440 { 441 /* Failed, display error */ 442 _snwprintf(InitBuffer->DebugBuffer, 443 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR), 444 L"INIT: Unable to allocate Process Environment. 0x%lx", 445 Status); 446 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer); 447 ZwDisplayString(&DebugString); 448 449 /* Bugcheck the system */ 450 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0); 451 } 452 453 /* Write the pointer */ 454 ProcessParams->Environment = EnvironmentPtr; 455 456 /* Make a buffer for the DOS path */ 457 p = (PWSTR)(ProcessParams + 1); 458 ProcessParams->CurrentDirectory.DosPath.Buffer = p; 459 ProcessParams->CurrentDirectory.DosPath.MaximumLength = MAX_PATH * 460 sizeof(WCHAR); 461 462 /* Copy the DOS path */ 463 RtlCopyUnicodeString(&ProcessParams->CurrentDirectory.DosPath, 464 &NtSystemRoot); 465 466 /* Make a buffer for the DLL Path */ 467 p = (PWSTR)((PCHAR)ProcessParams->CurrentDirectory.DosPath.Buffer + 468 ProcessParams->CurrentDirectory.DosPath.MaximumLength); 469 ProcessParams->DllPath.Buffer = p; 470 ProcessParams->DllPath.MaximumLength = MAX_PATH * sizeof(WCHAR); 471 472 /* Copy the DLL path and append the system32 directory */ 473 RtlCopyUnicodeString(&ProcessParams->DllPath, 474 &ProcessParams->CurrentDirectory.DosPath); 475 RtlAppendUnicodeToString(&ProcessParams->DllPath, L"\\System32"); 476 477 /* Make a buffer for the image name */ 478 p = (PWSTR)((PCHAR)ProcessParams->DllPath.Buffer + 479 ProcessParams->DllPath.MaximumLength); 480 ProcessParams->ImagePathName.Buffer = p; 481 ProcessParams->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR); 482 483 /* Make sure the buffer is a valid string which within the given length */ 484 if ((NtInitialUserProcessBufferType != REG_SZ) || 485 ((NtInitialUserProcessBufferLength != MAXULONG) && 486 ((NtInitialUserProcessBufferLength < sizeof(WCHAR)) || 487 (NtInitialUserProcessBufferLength > 488 sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR))))) 489 { 490 /* Invalid initial process string, bugcheck */ 491 KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, 492 STATUS_INVALID_PARAMETER, 493 NtInitialUserProcessBufferType, 494 NtInitialUserProcessBufferLength, 495 sizeof(NtInitialUserProcessBuffer)); 496 } 497 498 /* Cut out anything after a space */ 499 p = NtInitialUserProcessBuffer; 500 while ((*p) && (*p != L' ')) p++; 501 502 /* Set the image path length */ 503 ProcessParams->ImagePathName.Length = 504 (USHORT)((PCHAR)p - (PCHAR)NtInitialUserProcessBuffer); 505 506 /* Copy the actual buffer */ 507 RtlCopyMemory(ProcessParams->ImagePathName.Buffer, 508 NtInitialUserProcessBuffer, 509 ProcessParams->ImagePathName.Length); 510 511 /* Null-terminate it */ 512 ProcessParams->ImagePathName.Buffer[ProcessParams->ImagePathName.Length / 513 sizeof(WCHAR)] = UNICODE_NULL; 514 515 /* Make a buffer for the command line */ 516 p = (PWSTR)((PCHAR)ProcessParams->ImagePathName.Buffer + 517 ProcessParams->ImagePathName.MaximumLength); 518 ProcessParams->CommandLine.Buffer = p; 519 ProcessParams->CommandLine.MaximumLength = MAX_PATH * sizeof(WCHAR); 520 521 /* Add the image name to the command line */ 522 RtlAppendUnicodeToString(&ProcessParams->CommandLine, 523 NtInitialUserProcessBuffer); 524 525 /* Create the environment string */ 526 RtlInitEmptyUnicodeString(&Environment, 527 ProcessParams->Environment, 528 (USHORT)Size); 529 530 /* Append the DLL path to it */ 531 RtlAppendUnicodeToString(&Environment, L"Path="); 532 RtlAppendUnicodeStringToString(&Environment, &ProcessParams->DllPath); 533 RtlAppendUnicodeStringToString(&Environment, &NullString); 534 535 /* Create the system drive string */ 536 SystemDriveString = NtSystemRoot; 537 SystemDriveString.Length = 2 * sizeof(WCHAR); 538 539 /* Append it to the environment */ 540 RtlAppendUnicodeToString(&Environment, L"SystemDrive="); 541 RtlAppendUnicodeStringToString(&Environment, &SystemDriveString); 542 RtlAppendUnicodeStringToString(&Environment, &NullString); 543 544 /* Append the system root to the environment */ 545 RtlAppendUnicodeToString(&Environment, L"SystemRoot="); 546 RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot); 547 RtlAppendUnicodeStringToString(&Environment, &NullString); 548 549 /* Prepare the prefetcher */ 550 //CcPfBeginBootPhase(150); 551 552 /* Create SMSS process */ 553 SmssName = ProcessParams->ImagePathName; 554 Status = RtlCreateUserProcess(&SmssName, 555 OBJ_CASE_INSENSITIVE, 556 RtlDeNormalizeProcessParams(ProcessParams), 557 NULL, 558 NULL, 559 NULL, 560 FALSE, 561 NULL, 562 NULL, 563 ProcessInformation); 564 if (!NT_SUCCESS(Status)) 565 { 566 /* Failed, display error */ 567 _snwprintf(InitBuffer->DebugBuffer, 568 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR), 569 L"INIT: Unable to create Session Manager. 0x%lx", 570 Status); 571 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer); 572 ZwDisplayString(&DebugString); 573 574 /* Bugcheck the system */ 575 KeBugCheckEx(SESSION3_INITIALIZATION_FAILED, Status, 0, 0, 0); 576 } 577 578 /* Resume the thread */ 579 Status = ZwResumeThread(ProcessInformation->ThreadHandle, NULL); 580 if (!NT_SUCCESS(Status)) 581 { 582 /* Failed, display error */ 583 _snwprintf(InitBuffer->DebugBuffer, 584 sizeof(InitBuffer->DebugBuffer)/sizeof(WCHAR), 585 L"INIT: Unable to resume Session Manager. 0x%lx", 586 Status); 587 RtlInitUnicodeString(&DebugString, InitBuffer->DebugBuffer); 588 ZwDisplayString(&DebugString); 589 590 /* Bugcheck the system */ 591 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0); 592 } 593 594 /* Return success */ 595 *ProcessParameters = ProcessParams; 596 *ProcessEnvironment = EnvironmentPtr; 597 } 598 599 ULONG 600 NTAPI 601 INIT_FUNCTION 602 ExComputeTickCountMultiplier(IN ULONG ClockIncrement) 603 { 604 ULONG MsRemainder = 0, MsIncrement; 605 ULONG IncrementRemainder; 606 ULONG i; 607 608 /* Count the number of milliseconds for each clock interrupt */ 609 MsIncrement = ClockIncrement / (10 * 1000); 610 611 /* Count the remainder from the division above, with 24-bit precision */ 612 IncrementRemainder = ClockIncrement - (MsIncrement * (10 * 1000)); 613 for (i= 0; i < 24; i++) 614 { 615 /* Shift the remainders */ 616 MsRemainder <<= 1; 617 IncrementRemainder <<= 1; 618 619 /* Check if we've went past 1 ms */ 620 if (IncrementRemainder >= (10 * 1000)) 621 { 622 /* Increase the remainder by one, and substract from increment */ 623 IncrementRemainder -= (10 * 1000); 624 MsRemainder |= 1; 625 } 626 } 627 628 /* Return the increment */ 629 return (MsIncrement << 24) | MsRemainder; 630 } 631 632 BOOLEAN 633 NTAPI 634 INIT_FUNCTION 635 ExpInitSystemPhase0(VOID) 636 { 637 /* Initialize EXRESOURCE Support */ 638 ExpResourceInitialization(); 639 640 /* Initialize the environment lock */ 641 ExInitializeFastMutex(&ExpEnvironmentLock); 642 643 /* Initialize the lookaside lists and locks */ 644 ExpInitLookasideLists(); 645 646 /* Initialize the Firmware Table resource and listhead */ 647 InitializeListHead(&ExpFirmwareTableProviderListHead); 648 ExInitializeResourceLite(&ExpFirmwareTableResource); 649 650 /* Set the suite mask to maximum and return */ 651 ExSuiteMask = 0xFFFFFFFF; 652 return TRUE; 653 } 654 655 BOOLEAN 656 NTAPI 657 INIT_FUNCTION 658 ExpInitSystemPhase1(VOID) 659 { 660 /* Initialize worker threads */ 661 ExpInitializeWorkerThreads(); 662 663 /* Initialize pushlocks */ 664 ExpInitializePushLocks(); 665 666 /* Initialize events and event pairs */ 667 if (ExpInitializeEventImplementation() == FALSE) 668 { 669 DPRINT1("Executive: Event initialization failed\n"); 670 return FALSE; 671 } 672 if (ExpInitializeEventPairImplementation() == FALSE) 673 { 674 DPRINT1("Executive: Event Pair initialization failed\n"); 675 return FALSE; 676 } 677 678 /* Initialize mutants */ 679 if (ExpInitializeMutantImplementation() == FALSE) 680 { 681 DPRINT1("Executive: Mutant initialization failed\n"); 682 return FALSE; 683 } 684 685 /* Initialize callbacks */ 686 if (ExpInitializeCallbacks() == FALSE) 687 { 688 DPRINT1("Executive: Callback initialization failed\n"); 689 return FALSE; 690 } 691 692 /* Initialize semaphores */ 693 if (ExpInitializeSemaphoreImplementation() == FALSE) 694 { 695 DPRINT1("Executive: Semaphore initialization failed\n"); 696 return FALSE; 697 } 698 699 /* Initialize timers */ 700 if (ExpInitializeTimerImplementation() == FALSE) 701 { 702 DPRINT1("Executive: Timer initialization failed\n"); 703 return FALSE; 704 } 705 706 /* Initialize profiling */ 707 if (ExpInitializeProfileImplementation() == FALSE) 708 { 709 DPRINT1("Executive: Profile initialization failed\n"); 710 return FALSE; 711 } 712 713 /* Initialize UUIDs */ 714 ExpInitUuids(); 715 716 /* Initialize keyed events */ 717 if (ExpInitializeKeyedEventImplementation() == FALSE) 718 { 719 DPRINT1("Executive: Keyed event initialization failed\n"); 720 return FALSE; 721 } 722 723 /* Initialize Win32K */ 724 if (ExpWin32kInit() == FALSE) 725 { 726 DPRINT1("Executive: Win32 initialization failed\n"); 727 return FALSE; 728 } 729 return TRUE; 730 } 731 732 BOOLEAN 733 NTAPI 734 INIT_FUNCTION 735 ExInitSystem(VOID) 736 { 737 /* Check the initialization phase */ 738 switch (ExpInitializationPhase) 739 { 740 case 0: 741 742 /* Do Phase 0 */ 743 return ExpInitSystemPhase0(); 744 745 case 1: 746 747 /* Do Phase 1 */ 748 return ExpInitSystemPhase1(); 749 750 default: 751 752 /* Don't know any other phase! Bugcheck! */ 753 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL); 754 return FALSE; 755 } 756 } 757 758 BOOLEAN 759 NTAPI 760 INIT_FUNCTION 761 ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 762 { 763 PLOADER_PARAMETER_EXTENSION Extension; 764 765 /* Get the loader extension */ 766 Extension = LoaderBlock->Extension; 767 768 /* Validate the size (Windows 2003 loader doesn't provide more) */ 769 if (Extension->Size < LOADER_PARAMETER_EXTENSION_MIN_SIZE) return FALSE; 770 771 /* Don't validate upper versions */ 772 if (Extension->MajorVersion > VER_PRODUCTMAJORVERSION) return TRUE; 773 774 /* Fail if this is NT 4 */ 775 if (Extension->MajorVersion < VER_PRODUCTMAJORVERSION) return FALSE; 776 777 /* Fail if this is XP */ 778 if (Extension->MinorVersion < VER_PRODUCTMINORVERSION) return FALSE; 779 780 /* This is 2003 or newer, approve it */ 781 return TRUE; 782 } 783 784 VOID 785 NTAPI 786 INIT_FUNCTION 787 ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 788 { 789 ULONG i = 0; 790 PLIST_ENTRY NextEntry; 791 ULONG Count, Length; 792 PWCHAR Name; 793 PLDR_DATA_TABLE_ENTRY LdrEntry; 794 CHAR NameBuffer[256]; 795 STRING SymbolString; 796 NTSTATUS Status; 797 798 /* Loop the driver list */ 799 NextEntry = LoaderBlock->LoadOrderListHead.Flink; 800 while (NextEntry != &LoaderBlock->LoadOrderListHead) 801 { 802 /* Skip the first two images */ 803 if (i >= 2) 804 { 805 /* Get the entry */ 806 LdrEntry = CONTAINING_RECORD(NextEntry, 807 LDR_DATA_TABLE_ENTRY, 808 InLoadOrderLinks); 809 if (LdrEntry->FullDllName.Buffer[0] == L'\\') 810 { 811 /* We have a name, read its data */ 812 Name = LdrEntry->FullDllName.Buffer; 813 Length = LdrEntry->FullDllName.Length / sizeof(WCHAR); 814 815 /* Check if our buffer can hold it */ 816 if (sizeof(NameBuffer) < Length + sizeof(ANSI_NULL)) 817 { 818 /* It's too long */ 819 Status = STATUS_BUFFER_OVERFLOW; 820 } 821 else 822 { 823 /* Copy the name */ 824 Count = 0; 825 do 826 { 827 /* Copy the character */ 828 NameBuffer[Count++] = (CHAR)*Name++; 829 } while (Count < Length); 830 831 /* Null-terminate */ 832 NameBuffer[Count] = ANSI_NULL; 833 Status = STATUS_SUCCESS; 834 } 835 } 836 else 837 { 838 /* Safely print the string into our buffer */ 839 Status = RtlStringCbPrintfA(NameBuffer, 840 sizeof(NameBuffer), 841 "%S\\System32\\Drivers\\%wZ", 842 &SharedUserData->NtSystemRoot[2], 843 &LdrEntry->BaseDllName); 844 } 845 846 /* Check if the buffer was ok */ 847 if (NT_SUCCESS(Status)) 848 { 849 /* Initialize the STRING for the debugger */ 850 RtlInitString(&SymbolString, NameBuffer); 851 852 /* Load the symbols */ 853 DbgLoadImageSymbols(&SymbolString, 854 LdrEntry->DllBase, 855 (ULONG_PTR)PsGetCurrentProcessId()); 856 } 857 } 858 859 /* Go to the next entry */ 860 i++; 861 NextEntry = NextEntry->Flink; 862 } 863 } 864 865 VOID 866 NTAPI 867 INIT_FUNCTION 868 ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 869 IN ULONG_PTR PagesToDestroy, 870 IN TYPE_OF_MEMORY MemoryType) 871 { 872 PLIST_ENTRY ListEntry; 873 PMEMORY_ALLOCATION_DESCRIPTOR MemDescriptor; 874 875 DPRINT1("Burn RAM amount: %lu pages\n", PagesToDestroy); 876 877 /* Loop the memory descriptors, beginning at the end */ 878 for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Blink; 879 ListEntry != &LoaderBlock->MemoryDescriptorListHead; 880 ListEntry = ListEntry->Blink) 881 { 882 /* Get the memory descriptor structure */ 883 MemDescriptor = CONTAINING_RECORD(ListEntry, 884 MEMORY_ALLOCATION_DESCRIPTOR, 885 ListEntry); 886 887 /* Is memory free there or is it temporary? */ 888 if (MemDescriptor->MemoryType == LoaderFree || 889 MemDescriptor->MemoryType == LoaderFirmwareTemporary) 890 { 891 /* Check if the descriptor has more pages than we want */ 892 if (MemDescriptor->PageCount > PagesToDestroy) 893 { 894 /* Change block's page count, ntoskrnl doesn't care much */ 895 MemDescriptor->PageCount -= PagesToDestroy; 896 break; 897 } 898 else 899 { 900 /* Change block type */ 901 MemDescriptor->MemoryType = MemoryType; 902 PagesToDestroy -= MemDescriptor->PageCount; 903 904 /* Check if we are done */ 905 if (PagesToDestroy == 0) break; 906 } 907 } 908 } 909 } 910 911 VOID 912 NTAPI 913 INIT_FUNCTION 914 ExpInitializeExecutive(IN ULONG Cpu, 915 IN PLOADER_PARAMETER_BLOCK LoaderBlock) 916 { 917 PNLS_DATA_BLOCK NlsData; 918 CHAR Buffer[256]; 919 ANSI_STRING AnsiPath; 920 NTSTATUS Status; 921 PCHAR CommandLine, PerfMem; 922 ULONG PerfMemUsed; 923 PLDR_DATA_TABLE_ENTRY NtosEntry; 924 PMESSAGE_RESOURCE_ENTRY MsgEntry; 925 ANSI_STRING CSDString; 926 size_t Remaining = 0; 927 PCHAR RcEnd = NULL; 928 CHAR VersionBuffer[65]; 929 930 /* Validate Loader */ 931 if (!ExpIsLoaderValid(LoaderBlock)) 932 { 933 /* Invalid loader version */ 934 KeBugCheckEx(MISMATCHED_HAL, 935 3, 936 LoaderBlock->Extension->Size, 937 LoaderBlock->Extension->MajorVersion, 938 LoaderBlock->Extension->MinorVersion); 939 } 940 941 /* Initialize PRCB pool lookaside pointers */ 942 ExInitPoolLookasidePointers(); 943 944 /* Check if this is an application CPU */ 945 if (Cpu) 946 { 947 /* Then simply initialize it with HAL */ 948 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock)) 949 { 950 /* Initialization failed */ 951 KeBugCheck(HAL_INITIALIZATION_FAILED); 952 } 953 954 /* We're done */ 955 return; 956 } 957 958 /* Assume no text-mode or remote boot */ 959 ExpInTextModeSetup = FALSE; 960 IoRemoteBootClient = FALSE; 961 962 /* Check if we have a setup loader block */ 963 if (LoaderBlock->SetupLdrBlock) 964 { 965 /* Check if this is text-mode setup */ 966 if (LoaderBlock->SetupLdrBlock->Flags & SETUPLDR_TEXT_MODE) 967 ExpInTextModeSetup = TRUE; 968 969 /* Check if this is network boot */ 970 if (LoaderBlock->SetupLdrBlock->Flags & SETUPLDR_REMOTE_BOOT) 971 { 972 /* Set variable */ 973 IoRemoteBootClient = TRUE; 974 975 /* Make sure we're actually booting off the network */ 976 ASSERT(!_memicmp(LoaderBlock->ArcBootDeviceName, "net(0)", 6)); 977 } 978 } 979 980 /* Set phase to 0 */ 981 ExpInitializationPhase = 0; 982 983 /* Get boot command line */ 984 CommandLine = LoaderBlock->LoadOptions; 985 if (CommandLine) 986 { 987 /* Upcase it for comparison and check if we're in performance mode */ 988 _strupr(CommandLine); 989 PerfMem = strstr(CommandLine, "PERFMEM"); 990 if (PerfMem) 991 { 992 /* Check if the user gave a number of bytes to use */ 993 PerfMem = strstr(PerfMem, "="); 994 if (PerfMem) 995 { 996 /* Read the number of pages we'll use */ 997 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE); 998 if (PerfMem) 999 { 1000 /* FIXME: TODO */ 1001 DPRINT1("BBT performance mode not yet supported." 1002 "/PERFMEM option ignored.\n"); 1003 } 1004 } 1005 } 1006 1007 /* Check if we're burning memory */ 1008 PerfMem = strstr(CommandLine, "BURNMEMORY"); 1009 if (PerfMem) 1010 { 1011 /* Check if the user gave a number of bytes to use */ 1012 PerfMem = strstr(PerfMem, "="); 1013 if (PerfMem) 1014 { 1015 /* Read the number of pages we'll use */ 1016 PerfMemUsed = atol(PerfMem + 1) * (1024 * 1024 / PAGE_SIZE); 1017 if (PerfMemUsed) ExBurnMemory(LoaderBlock, PerfMemUsed, LoaderBad); 1018 } 1019 } 1020 } 1021 1022 /* Setup NLS Base and offsets */ 1023 NlsData = LoaderBlock->NlsData; 1024 ExpNlsTableBase = NlsData->AnsiCodePageData; 1025 ExpAnsiCodePageDataOffset = 0; 1026 ExpOemCodePageDataOffset = (ULONG)((ULONG_PTR)NlsData->OemCodePageData - 1027 (ULONG_PTR)NlsData->AnsiCodePageData); 1028 ExpUnicodeCaseTableDataOffset = (ULONG)((ULONG_PTR)NlsData->UnicodeCodePageData - 1029 (ULONG_PTR)NlsData->AnsiCodePageData); 1030 1031 /* Initialize the NLS Tables */ 1032 RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase + 1033 ExpAnsiCodePageDataOffset), 1034 (PVOID)((ULONG_PTR)ExpNlsTableBase + 1035 ExpOemCodePageDataOffset), 1036 (PVOID)((ULONG_PTR)ExpNlsTableBase + 1037 ExpUnicodeCaseTableDataOffset), 1038 &ExpNlsTableInfo); 1039 RtlResetRtlTranslations(&ExpNlsTableInfo); 1040 1041 /* Now initialize the HAL */ 1042 if (!HalInitSystem(ExpInitializationPhase, LoaderBlock)) 1043 { 1044 /* HAL failed to initialize, bugcheck */ 1045 KeBugCheck(HAL_INITIALIZATION_FAILED); 1046 } 1047 1048 /* Make sure interrupts are active now */ 1049 _enable(); 1050 1051 /* Clear the crypto exponent */ 1052 SharedUserData->CryptoExponent = 0; 1053 1054 /* Set global flags for the checked build */ 1055 #if DBG 1056 NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS | 1057 FLG_ENABLE_KDEBUG_SYMBOL_LOAD; 1058 #endif 1059 1060 /* Setup NT System Root Path */ 1061 sprintf(Buffer, "C:%s", LoaderBlock->NtBootPathName); 1062 1063 /* Convert to ANSI_STRING and null-terminate it */ 1064 RtlInitString(&AnsiPath, Buffer); 1065 Buffer[--AnsiPath.Length] = ANSI_NULL; 1066 1067 /* Get the string from KUSER_SHARED_DATA's buffer */ 1068 RtlInitEmptyUnicodeString(&NtSystemRoot, 1069 SharedUserData->NtSystemRoot, 1070 sizeof(SharedUserData->NtSystemRoot)); 1071 1072 /* Now fill it in */ 1073 Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE); 1074 if (!NT_SUCCESS(Status)) KeBugCheck(SESSION3_INITIALIZATION_FAILED); 1075 1076 /* Setup bugcheck messages */ 1077 KiInitializeBugCheck(); 1078 1079 /* Setup initial system settings */ 1080 CmGetSystemControlValues(LoaderBlock->RegistryBase, CmControlVector); 1081 1082 /* Set the Service Pack Number and add it to the CSD Version number if needed */ 1083 CmNtSpBuildNumber = VER_PRODUCTBUILD_QFE; 1084 if (((CmNtCSDVersion & 0xFFFF0000) == 0) && (CmNtCSDReleaseType == 1)) 1085 { 1086 CmNtCSDVersion |= (VER_PRODUCTBUILD_QFE << 16); 1087 } 1088 1089 /* Add loaded CmNtGlobalFlag value */ 1090 NtGlobalFlag |= CmNtGlobalFlag; 1091 1092 /* Initialize the executive at phase 0 */ 1093 if (!ExInitSystem()) KeBugCheck(PHASE0_INITIALIZATION_FAILED); 1094 1095 /* Initialize the memory manager at phase 0 */ 1096 if (!MmArmInitSystem(0, LoaderBlock)) KeBugCheck(PHASE0_INITIALIZATION_FAILED); 1097 1098 /* Load boot symbols */ 1099 ExpLoadBootSymbols(LoaderBlock); 1100 1101 /* Check if we should break after symbol load */ 1102 if (KdBreakAfterSymbolLoad) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); 1103 1104 /* Check if this loader is compatible with NT 5.2 */ 1105 if (LoaderBlock->Extension->Size >= sizeof(LOADER_PARAMETER_EXTENSION)) 1106 { 1107 /* Setup headless terminal settings */ 1108 HeadlessInit(LoaderBlock); 1109 } 1110 1111 /* Set system ranges */ 1112 #ifdef _M_AMD64 1113 SharedUserData->Reserved1 = MM_HIGHEST_USER_ADDRESS_WOW64; 1114 SharedUserData->Reserved3 = MM_SYSTEM_RANGE_START_WOW64; 1115 #else 1116 SharedUserData->Reserved1 = (ULONG_PTR)MmHighestUserAddress; 1117 SharedUserData->Reserved3 = (ULONG_PTR)MmSystemRangeStart; 1118 #endif 1119 1120 /* Make a copy of the NLS Tables */ 1121 ExpInitNls(LoaderBlock); 1122 1123 /* Get the kernel's load entry */ 1124 NtosEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink, 1125 LDR_DATA_TABLE_ENTRY, 1126 InLoadOrderLinks); 1127 1128 /* Check if this is a service pack */ 1129 if (CmNtCSDVersion & 0xFFFF) 1130 { 1131 /* Get the service pack string */ 1132 Status = RtlFindMessage(NtosEntry->DllBase, 1133 11, 1134 0, 1135 WINDOWS_NT_CSD_STRING, 1136 &MsgEntry); 1137 if (NT_SUCCESS(Status)) 1138 { 1139 /* Setup the string */ 1140 RtlInitAnsiString(&CSDString, (PCHAR)MsgEntry->Text); 1141 1142 /* Remove trailing newline */ 1143 while ((CSDString.Length > 0) && 1144 ((CSDString.Buffer[CSDString.Length - 1] == '\r') || 1145 (CSDString.Buffer[CSDString.Length - 1] == '\n'))) 1146 { 1147 /* Skip the trailing character */ 1148 CSDString.Length--; 1149 } 1150 1151 /* Fill the buffer with version information */ 1152 Status = RtlStringCbPrintfA(Buffer, 1153 sizeof(Buffer), 1154 "%Z %u%c", 1155 &CSDString, 1156 (CmNtCSDVersion & 0xFF00) >> 8, 1157 (CmNtCSDVersion & 0xFF) ? 1158 'A' + (CmNtCSDVersion & 0xFF) - 1 : 1159 ANSI_NULL); 1160 } 1161 else 1162 { 1163 /* Build default string */ 1164 Status = RtlStringCbPrintfA(Buffer, 1165 sizeof(Buffer), 1166 "CSD %04x", 1167 CmNtCSDVersion); 1168 } 1169 1170 /* Check for success */ 1171 if (!NT_SUCCESS(Status)) 1172 { 1173 /* Fail */ 1174 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0); 1175 } 1176 } 1177 else 1178 { 1179 /* Then this is a beta */ 1180 Status = RtlStringCbCopyExA(Buffer, 1181 sizeof(Buffer), 1182 VER_PRODUCTBETA_STR, 1183 NULL, 1184 &Remaining, 1185 0); 1186 if (!NT_SUCCESS(Status)) 1187 { 1188 /* Fail */ 1189 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0); 1190 } 1191 1192 /* Update length */ 1193 CmCSDVersionString.MaximumLength = sizeof(Buffer) - (USHORT)Remaining; 1194 } 1195 1196 /* Check if we have an RC number */ 1197 if ((CmNtCSDVersion & 0xFFFF0000) && (CmNtCSDReleaseType == 1)) 1198 { 1199 /* Check if we have no version data yet */ 1200 if (!(*Buffer)) 1201 { 1202 /* Set defaults */ 1203 Remaining = sizeof(Buffer); 1204 RcEnd = Buffer; 1205 } 1206 else 1207 { 1208 /* Add comma and space */ 1209 Status = RtlStringCbCatExA(Buffer, 1210 sizeof(Buffer), 1211 ", ", 1212 &RcEnd, 1213 &Remaining, 1214 0); 1215 if (!NT_SUCCESS(Status)) 1216 { 1217 /* Fail */ 1218 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0); 1219 } 1220 } 1221 1222 /* Add the version format string */ 1223 Status = RtlStringCbPrintfA(RcEnd, 1224 Remaining, 1225 "v.%u", 1226 (CmNtCSDVersion & 0xFFFF0000) >> 16); 1227 if (!NT_SUCCESS(Status)) 1228 { 1229 /* Fail */ 1230 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0); 1231 } 1232 } 1233 1234 /* Now setup the final string */ 1235 RtlInitAnsiString(&CSDString, Buffer); 1236 Status = RtlAnsiStringToUnicodeString(&CmCSDVersionString, 1237 &CSDString, 1238 TRUE); 1239 if (!NT_SUCCESS(Status)) 1240 { 1241 /* Fail */ 1242 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0); 1243 } 1244 1245 /* Add our version */ 1246 Status = RtlStringCbPrintfA(VersionBuffer, 1247 sizeof(VersionBuffer), 1248 "%u.%u", 1249 VER_PRODUCTMAJORVERSION, 1250 VER_PRODUCTMINORVERSION); 1251 if (!NT_SUCCESS(Status)) 1252 { 1253 /* Fail */ 1254 KeBugCheckEx(PHASE0_INITIALIZATION_FAILED, Status, 0, 0, 0); 1255 } 1256 1257 /* Build the final version string */ 1258 RtlCreateUnicodeStringFromAsciiz(&CmVersionString, VersionBuffer); 1259 1260 /* Check if the user wants a kernel stack trace database */ 1261 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) 1262 { 1263 /* FIXME: TODO */ 1264 DPRINT1("Kernel-mode stack trace support not yet present." 1265 "FLG_KERNEL_STACK_TRACE_DB flag ignored.\n"); 1266 } 1267 1268 /* Check if he wanted exception logging */ 1269 if (NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) 1270 { 1271 /* FIXME: TODO */ 1272 DPRINT1("Kernel-mode exception logging support not yet present." 1273 "FLG_ENABLE_EXCEPTION_LOGGING flag ignored.\n"); 1274 } 1275 1276 /* Initialize the Handle Table */ 1277 ExpInitializeHandleTables(); 1278 1279 #if DBG 1280 /* On checked builds, allocate the system call count table */ 1281 KeServiceDescriptorTable[0].Count = 1282 ExAllocatePoolWithTag(NonPagedPool, 1283 KiServiceLimit * sizeof(ULONG), 1284 'llaC'); 1285 1286 /* Use it for the shadow table too */ 1287 KeServiceDescriptorTableShadow[0].Count = KeServiceDescriptorTable[0].Count; 1288 1289 /* Make sure allocation succeeded */ 1290 if (KeServiceDescriptorTable[0].Count) 1291 { 1292 /* Zero the call counts to 0 */ 1293 RtlZeroMemory(KeServiceDescriptorTable[0].Count, 1294 KiServiceLimit * sizeof(ULONG)); 1295 } 1296 #endif 1297 1298 /* Create the Basic Object Manager Types to allow new Object Types */ 1299 if (!ObInitSystem()) KeBugCheck(OBJECT_INITIALIZATION_FAILED); 1300 1301 /* Load basic Security for other Managers */ 1302 if (!SeInitSystem()) KeBugCheck(SECURITY_INITIALIZATION_FAILED); 1303 1304 /* Initialize the Process Manager */ 1305 if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS_INITIALIZATION_FAILED); 1306 1307 /* Initialize the PnP Manager */ 1308 if (!PpInitSystem()) KeBugCheck(PP0_INITIALIZATION_FAILED); 1309 1310 /* Initialize the User-Mode Debugging Subsystem */ 1311 DbgkInitialize(); 1312 1313 /* Calculate the tick count multiplier */ 1314 ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement); 1315 SharedUserData->TickCountMultiplier = ExpTickCountMultiplier; 1316 1317 /* Set the OS Version */ 1318 SharedUserData->NtMajorVersion = NtMajorVersion; 1319 SharedUserData->NtMinorVersion = NtMinorVersion; 1320 1321 /* Set the machine type */ 1322 SharedUserData->ImageNumberLow = IMAGE_FILE_MACHINE_NATIVE; 1323 SharedUserData->ImageNumberHigh = IMAGE_FILE_MACHINE_NATIVE; 1324 } 1325 1326 VOID 1327 NTAPI 1328 MmFreeLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock); 1329 1330 VOID 1331 NTAPI 1332 INIT_FUNCTION 1333 Phase1InitializationDiscard(IN PVOID Context) 1334 { 1335 PLOADER_PARAMETER_BLOCK LoaderBlock = Context; 1336 NTSTATUS Status, MsgStatus; 1337 TIME_FIELDS TimeFields; 1338 LARGE_INTEGER SystemBootTime, UniversalBootTime, OldTime, Timeout; 1339 BOOLEAN SosEnabled, NoGuiBoot, ResetBias = FALSE, AlternateShell = FALSE; 1340 PLDR_DATA_TABLE_ENTRY NtosEntry; 1341 PMESSAGE_RESOURCE_ENTRY MsgEntry; 1342 PCHAR CommandLine, Y2KHackRequired, SafeBoot, Environment; 1343 PCHAR StringBuffer, EndBuffer, BeginBuffer, MpString = ""; 1344 PINIT_BUFFER InitBuffer; 1345 ANSI_STRING TempString; 1346 ULONG LastTzBias, Length, YearHack = 0, Disposition, MessageCode = 0; 1347 SIZE_T Size; 1348 size_t Remaining; 1349 PRTL_USER_PROCESS_INFORMATION ProcessInfo; 1350 KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo; 1351 UNICODE_STRING KeyName; 1352 OBJECT_ATTRIBUTES ObjectAttributes; 1353 HANDLE KeyHandle, OptionHandle; 1354 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL; 1355 1356 /* Allocate the initialization buffer */ 1357 InitBuffer = ExAllocatePoolWithTag(NonPagedPool, 1358 sizeof(INIT_BUFFER), 1359 TAG_INIT); 1360 if (!InitBuffer) 1361 { 1362 /* Bugcheck */ 1363 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 8, 0, 0); 1364 } 1365 1366 /* Set to phase 1 */ 1367 ExpInitializationPhase = 1; 1368 1369 /* Set us at maximum priority */ 1370 KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY); 1371 1372 /* Do Phase 1 HAL Initialization */ 1373 if (!HalInitSystem(1, LoaderBlock)) KeBugCheck(HAL1_INITIALIZATION_FAILED); 1374 1375 /* Get the command line and upcase it */ 1376 CommandLine = (LoaderBlock->LoadOptions ? _strupr(LoaderBlock->LoadOptions) : NULL); 1377 1378 /* Check if GUI Boot is enabled */ 1379 NoGuiBoot = (CommandLine && strstr(CommandLine, "NOGUIBOOT") != NULL); 1380 1381 /* Get the SOS setting */ 1382 SosEnabled = (CommandLine && strstr(CommandLine, "SOS") != NULL); 1383 1384 /* Setup the boot driver */ 1385 InbvEnableBootDriver(!NoGuiBoot); 1386 InbvDriverInitialize(LoaderBlock, IDB_MAX_RESOURCE); 1387 1388 /* Check if GUI boot is enabled */ 1389 if (!NoGuiBoot) 1390 { 1391 /* It is, display the boot logo and enable printing strings */ 1392 InbvEnableDisplayString(SosEnabled); 1393 DisplayBootBitmap(SosEnabled); 1394 } 1395 else 1396 { 1397 /* Release display ownership if not using GUI boot */ 1398 InbvNotifyDisplayOwnershipLost(NULL); 1399 1400 /* Don't allow boot-time strings */ 1401 InbvEnableDisplayString(FALSE); 1402 } 1403 1404 /* Check if this is LiveCD (WinPE) mode */ 1405 if (CommandLine && strstr(CommandLine, "MININT") != NULL) 1406 { 1407 /* Setup WinPE Settings */ 1408 InitIsWinPEMode = TRUE; 1409 InitWinPEModeType |= (strstr(CommandLine, "INRAM") != NULL) ? 0x80000000 : 0x00000001; 1410 } 1411 1412 /* Get the kernel's load entry */ 1413 NtosEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink, 1414 LDR_DATA_TABLE_ENTRY, 1415 InLoadOrderLinks); 1416 1417 /* Find the banner message */ 1418 MsgStatus = RtlFindMessage(NtosEntry->DllBase, 1419 11, 1420 0, 1421 WINDOWS_NT_BANNER, 1422 &MsgEntry); 1423 1424 /* Setup defaults and check if we have a version string */ 1425 StringBuffer = InitBuffer->VersionBuffer; 1426 BeginBuffer = StringBuffer; 1427 EndBuffer = StringBuffer; 1428 Remaining = sizeof(InitBuffer->VersionBuffer); 1429 if (CmCSDVersionString.Length) 1430 { 1431 /* Print the version string */ 1432 Status = RtlStringCbPrintfExA(StringBuffer, 1433 Remaining, 1434 &EndBuffer, 1435 &Remaining, 1436 0, 1437 ": %wZ", 1438 &CmCSDVersionString); 1439 if (!NT_SUCCESS(Status)) 1440 { 1441 /* Bugcheck */ 1442 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0); 1443 } 1444 } 1445 else 1446 { 1447 /* No version */ 1448 *EndBuffer = ANSI_NULL; /* Null-terminate the string */ 1449 } 1450 1451 /* Skip over the null-terminator to start a new string */ 1452 ++EndBuffer; 1453 --Remaining; 1454 1455 /* Build the version number */ 1456 StringBuffer = InitBuffer->VersionNumber; 1457 Status = RtlStringCbPrintfA(StringBuffer, 1458 sizeof(InitBuffer->VersionNumber), 1459 "%u.%u", 1460 VER_PRODUCTMAJORVERSION, 1461 VER_PRODUCTMINORVERSION); 1462 if (!NT_SUCCESS(Status)) 1463 { 1464 /* Bugcheck */ 1465 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0); 1466 } 1467 1468 /* Check if we had found a banner message */ 1469 if (NT_SUCCESS(MsgStatus)) 1470 { 1471 /* Create the banner message */ 1472 /* ReactOS specific: Report ReactOS version, NtBuildLab information and reported NT kernel version */ 1473 Status = RtlStringCbPrintfA(EndBuffer, 1474 Remaining, 1475 (PCHAR)MsgEntry->Text, 1476 KERNEL_VERSION_STR, 1477 NtBuildLab, 1478 StringBuffer, 1479 NtBuildNumber & 0xFFFF, 1480 BeginBuffer); 1481 if (!NT_SUCCESS(Status)) 1482 { 1483 /* Bugcheck */ 1484 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0); 1485 } 1486 } 1487 else 1488 { 1489 /* Use hard-coded banner message */ 1490 Status = RtlStringCbCopyA(EndBuffer, Remaining, "REACTOS (R)\r\n"); 1491 if (!NT_SUCCESS(Status)) 1492 { 1493 /* Bugcheck */ 1494 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 7, 0, 0); 1495 } 1496 } 1497 1498 /* Display the version string on-screen */ 1499 InbvDisplayString(EndBuffer); 1500 1501 /* Initialize Power Subsystem in Phase 0 */ 1502 if (!PoInitSystem(0)) KeBugCheck(INTERNAL_POWER_ERROR); 1503 1504 /* Check for Y2K hack */ 1505 Y2KHackRequired = CommandLine ? strstr(CommandLine, "YEAR") : NULL; 1506 if (Y2KHackRequired) Y2KHackRequired = strstr(Y2KHackRequired, "="); 1507 if (Y2KHackRequired) YearHack = atol(Y2KHackRequired + 1); 1508 1509 /* Query the clock */ 1510 if ((ExCmosClockIsSane) && (HalQueryRealTimeClock(&TimeFields))) 1511 { 1512 /* Check if we're using the Y2K hack */ 1513 if (Y2KHackRequired) TimeFields.Year = (CSHORT)YearHack; 1514 1515 /* Convert to time fields */ 1516 RtlTimeFieldsToTime(&TimeFields, &SystemBootTime); 1517 UniversalBootTime = SystemBootTime; 1518 1519 /* Check if real time is GMT */ 1520 if (!ExpRealTimeIsUniversal) 1521 { 1522 /* Check if we don't have a valid bias */ 1523 if (ExpLastTimeZoneBias == MAXULONG) 1524 { 1525 /* Reset */ 1526 ResetBias = TRUE; 1527 ExpLastTimeZoneBias = ExpAltTimeZoneBias; 1528 } 1529 1530 /* Calculate the bias in seconds */ 1531 ExpTimeZoneBias.QuadPart = Int32x32To64(ExpLastTimeZoneBias * 60, 1532 10000000); 1533 1534 /* Set the boot time-zone bias */ 1535 SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart; 1536 SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart; 1537 SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart; 1538 1539 /* Convert the boot time to local time, and set it */ 1540 UniversalBootTime.QuadPart = SystemBootTime.QuadPart + 1541 ExpTimeZoneBias.QuadPart; 1542 } 1543 1544 /* Update the system time */ 1545 KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL); 1546 1547 /* Do system callback */ 1548 PoNotifySystemTimeSet(); 1549 1550 /* Remember this as the boot time */ 1551 KeBootTime = UniversalBootTime; 1552 KeBootTimeBias = 0; 1553 } 1554 1555 /* Initialize all processors */ 1556 if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED); 1557 1558 #ifdef CONFIG_SMP 1559 /* HACK: We should use RtlFindMessage and not only fallback to this */ 1560 MpString = "MultiProcessor Kernel\r\n"; 1561 #endif 1562 1563 /* Setup the "MP" String */ 1564 RtlInitAnsiString(&TempString, MpString); 1565 1566 /* Make sure to remove the \r\n if we actually have a string */ 1567 while ((TempString.Length > 0) && 1568 ((TempString.Buffer[TempString.Length - 1] == '\r') || 1569 (TempString.Buffer[TempString.Length - 1] == '\n'))) 1570 { 1571 /* Skip the trailing character */ 1572 TempString.Length--; 1573 } 1574 1575 /* Get the information string from our resource file */ 1576 MsgStatus = RtlFindMessage(NtosEntry->DllBase, 1577 11, 1578 0, 1579 KeNumberProcessors > 1 ? 1580 WINDOWS_NT_INFO_STRING_PLURAL : 1581 WINDOWS_NT_INFO_STRING, 1582 &MsgEntry); 1583 1584 /* Get total RAM size, in MiB */ 1585 /* Round size up. Assumed to better match actual physical RAM size */ 1586 Size = ALIGN_UP_BY(MmNumberOfPhysicalPages * PAGE_SIZE, 1024 * 1024) / (1024 * 1024); 1587 1588 /* Create the string */ 1589 StringBuffer = InitBuffer->VersionBuffer; 1590 Status = RtlStringCbPrintfA(StringBuffer, 1591 sizeof(InitBuffer->VersionBuffer), 1592 NT_SUCCESS(MsgStatus) ? 1593 (PCHAR)MsgEntry->Text : 1594 "%u System Processor [%Iu MB Memory] %Z\r\n", 1595 KeNumberProcessors, 1596 Size, 1597 &TempString); 1598 if (!NT_SUCCESS(Status)) 1599 { 1600 /* Bugcheck */ 1601 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 4, 0, 0); 1602 } 1603 1604 /* Display RAM and CPU count */ 1605 InbvDisplayString(StringBuffer); 1606 1607 /* Update the progress bar */ 1608 InbvUpdateProgressBar(5); 1609 1610 /* Call OB initialization again */ 1611 if (!ObInitSystem()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED); 1612 1613 /* Initialize Basic System Objects and Worker Threads */ 1614 if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 1, 0); 1615 1616 /* Initialize the later stages of the kernel */ 1617 if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 2, 0); 1618 1619 /* Call KD Providers at Phase 1 */ 1620 if (!KdInitSystem(ExpInitializationPhase, KeLoaderBlock)) 1621 { 1622 /* Failed, bugcheck */ 1623 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 0, 0, 3, 0); 1624 } 1625 1626 /* Initialize the SRM in Phase 1 */ 1627 if (!SeInitSystem()) KeBugCheck(SECURITY1_INITIALIZATION_FAILED); 1628 1629 /* Update the progress bar */ 1630 InbvUpdateProgressBar(10); 1631 1632 /* Create SystemRoot Link */ 1633 Status = ExpCreateSystemRootLink(LoaderBlock); 1634 if (!NT_SUCCESS(Status)) 1635 { 1636 /* Failed to create the system root link */ 1637 KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 0, 0, 0); 1638 } 1639 1640 /* Set up Region Maps, Sections and the Paging File */ 1641 if (!MmInitSystem(1, LoaderBlock)) KeBugCheck(MEMORY1_INITIALIZATION_FAILED); 1642 1643 /* Create NLS section */ 1644 ExpInitNls(LoaderBlock); 1645 1646 /* Initialize Cache Views */ 1647 if (!CcInitializeCacheManager()) KeBugCheck(CACHE_INITIALIZATION_FAILED); 1648 1649 /* Initialize the Registry */ 1650 if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED); 1651 1652 /* Initialize Prefetcher */ 1653 CcPfInitializePrefetcher(); 1654 1655 /* Update progress bar */ 1656 InbvUpdateProgressBar(15); 1657 1658 /* Update timezone information */ 1659 LastTzBias = ExpLastTimeZoneBias; 1660 ExRefreshTimeZoneInformation(&SystemBootTime); 1661 1662 /* Check if we're resetting timezone data */ 1663 if (ResetBias) 1664 { 1665 /* Convert the local time to system time */ 1666 ExLocalTimeToSystemTime(&SystemBootTime, &UniversalBootTime); 1667 KeBootTime = UniversalBootTime; 1668 KeBootTimeBias = 0; 1669 1670 /* Set the new time */ 1671 KeSetSystemTime(&UniversalBootTime, &OldTime, FALSE, NULL); 1672 } 1673 else 1674 { 1675 /* Check if the timezone switched and update the time */ 1676 if (LastTzBias != ExpLastTimeZoneBias) ZwSetSystemTime(NULL, NULL); 1677 } 1678 1679 /* Initialize the File System Runtime Library */ 1680 if (!FsRtlInitSystem()) KeBugCheck(FILE_INITIALIZATION_FAILED); 1681 1682 /* Initialize range lists */ 1683 RtlInitializeRangeListPackage(); 1684 1685 /* Report all resources used by HAL */ 1686 HalReportResourceUsage(); 1687 1688 /* Call the debugger DLL */ 1689 KdDebuggerInitialize1(LoaderBlock); 1690 1691 /* Setup PnP Manager in phase 1 */ 1692 if (!PpInitSystem()) KeBugCheck(PP1_INITIALIZATION_FAILED); 1693 1694 /* Update progress bar */ 1695 InbvUpdateProgressBar(20); 1696 1697 /* Initialize LPC */ 1698 if (!LpcInitSystem()) KeBugCheck(LPC_INITIALIZATION_FAILED); 1699 1700 /* Make sure we have a command line */ 1701 if (CommandLine) 1702 { 1703 /* Check if this is a safe mode boot */ 1704 SafeBoot = strstr(CommandLine, "SAFEBOOT:"); 1705 if (SafeBoot) 1706 { 1707 /* Check what kind of boot this is */ 1708 SafeBoot += 9; 1709 if (!strncmp(SafeBoot, "MINIMAL", 7)) 1710 { 1711 /* Minimal mode */ 1712 InitSafeBootMode = 1; 1713 SafeBoot += 7; 1714 MessageCode = BOOTING_IN_SAFEMODE_MINIMAL; 1715 } 1716 else if (!strncmp(SafeBoot, "NETWORK", 7)) 1717 { 1718 /* With Networking */ 1719 InitSafeBootMode = 2; 1720 SafeBoot += 7; 1721 MessageCode = BOOTING_IN_SAFEMODE_NETWORK; 1722 } 1723 else if (!strncmp(SafeBoot, "DSREPAIR", 8)) 1724 { 1725 /* Domain Server Repair */ 1726 InitSafeBootMode = 3; 1727 SafeBoot += 8; 1728 MessageCode = BOOTING_IN_SAFEMODE_DSREPAIR; 1729 1730 } 1731 else 1732 { 1733 /* Invalid */ 1734 InitSafeBootMode = 0; 1735 } 1736 1737 /* Check if there's any settings left */ 1738 if (*SafeBoot) 1739 { 1740 /* Check if an alternate shell was requested */ 1741 if (!strncmp(SafeBoot, "(ALTERNATESHELL)", 16)) 1742 { 1743 /* Remember this for later */ 1744 AlternateShell = TRUE; 1745 } 1746 } 1747 1748 /* Find the message to print out */ 1749 Status = RtlFindMessage(NtosEntry->DllBase, 1750 11, 1751 0, 1752 MessageCode, 1753 &MsgEntry); 1754 if (NT_SUCCESS(Status)) 1755 { 1756 /* Display it */ 1757 InbvDisplayString((PCHAR)MsgEntry->Text); 1758 } 1759 } 1760 } 1761 1762 /* Make sure we have a command line */ 1763 if (CommandLine) 1764 { 1765 /* Check if bootlogging is enabled */ 1766 if (strstr(CommandLine, "BOOTLOG")) 1767 { 1768 /* Find the message to print out */ 1769 Status = RtlFindMessage(NtosEntry->DllBase, 1770 11, 1771 0, 1772 BOOTLOG_ENABLED, 1773 &MsgEntry); 1774 if (NT_SUCCESS(Status)) 1775 { 1776 /* Display it */ 1777 InbvDisplayString((PCHAR)MsgEntry->Text); 1778 } 1779 1780 /* Setup boot logging */ 1781 //IopInitializeBootLogging(LoaderBlock, InitBuffer->BootlogHeader); 1782 } 1783 } 1784 1785 /* Setup the Executive in Phase 2 */ 1786 //ExInitSystemPhase2(); 1787 1788 /* Update progress bar */ 1789 InbvUpdateProgressBar(25); 1790 1791 #ifdef _WINKD_ 1792 /* No KD Time Slip is pending */ 1793 KdpTimeSlipPending = 0; 1794 #endif 1795 1796 /* Initialize in-place execution support */ 1797 XIPInit(LoaderBlock); 1798 1799 /* Set maximum update to 75% */ 1800 InbvSetProgressBarSubset(25, 75); 1801 1802 /* Initialize the I/O Subsystem */ 1803 if (!IoInitSystem(LoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED); 1804 1805 /* Set maximum update to 100% */ 1806 InbvSetProgressBarSubset(0, 100); 1807 1808 /* Are we in safe mode? */ 1809 if (InitSafeBootMode) 1810 { 1811 /* Open the safe boot key */ 1812 RtlInitUnicodeString(&KeyName, 1813 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET" 1814 L"\\CONTROL\\SAFEBOOT"); 1815 InitializeObjectAttributes(&ObjectAttributes, 1816 &KeyName, 1817 OBJ_CASE_INSENSITIVE, 1818 NULL, 1819 NULL); 1820 Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); 1821 if (NT_SUCCESS(Status)) 1822 { 1823 /* First check if we have an alternate shell */ 1824 if (AlternateShell) 1825 { 1826 /* Make sure that the registry has one setup */ 1827 RtlInitUnicodeString(&KeyName, L"AlternateShell"); 1828 Status = NtQueryValueKey(KeyHandle, 1829 &KeyName, 1830 KeyValuePartialInformation, 1831 &KeyPartialInfo, 1832 sizeof(KeyPartialInfo), 1833 &Length); 1834 if (!(NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)) 1835 { 1836 AlternateShell = FALSE; 1837 } 1838 } 1839 1840 /* Create the option key */ 1841 RtlInitUnicodeString(&KeyName, L"Option"); 1842 InitializeObjectAttributes(&ObjectAttributes, 1843 &KeyName, 1844 OBJ_CASE_INSENSITIVE, 1845 KeyHandle, 1846 NULL); 1847 Status = ZwCreateKey(&OptionHandle, 1848 KEY_ALL_ACCESS, 1849 &ObjectAttributes, 1850 0, 1851 NULL, 1852 REG_OPTION_VOLATILE, 1853 &Disposition); 1854 NtClose(KeyHandle); 1855 1856 /* Check if the key create worked */ 1857 if (NT_SUCCESS(Status)) 1858 { 1859 /* Write the safe boot type */ 1860 RtlInitUnicodeString(&KeyName, L"OptionValue"); 1861 NtSetValueKey(OptionHandle, 1862 &KeyName, 1863 0, 1864 REG_DWORD, 1865 &InitSafeBootMode, 1866 sizeof(InitSafeBootMode)); 1867 1868 /* Check if we have to use an alternate shell */ 1869 if (AlternateShell) 1870 { 1871 /* Remember this for later */ 1872 Disposition = TRUE; 1873 RtlInitUnicodeString(&KeyName, L"UseAlternateShell"); 1874 NtSetValueKey(OptionHandle, 1875 &KeyName, 1876 0, 1877 REG_DWORD, 1878 &Disposition, 1879 sizeof(Disposition)); 1880 } 1881 1882 /* Close the options key handle */ 1883 NtClose(OptionHandle); 1884 } 1885 } 1886 } 1887 1888 /* Are we in Win PE mode? */ 1889 if (InitIsWinPEMode) 1890 { 1891 /* Open the safe control key */ 1892 RtlInitUnicodeString(&KeyName, 1893 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET" 1894 L"\\CONTROL"); 1895 InitializeObjectAttributes(&ObjectAttributes, 1896 &KeyName, 1897 OBJ_CASE_INSENSITIVE, 1898 NULL, 1899 NULL); 1900 Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); 1901 if (!NT_SUCCESS(Status)) 1902 { 1903 /* Bugcheck */ 1904 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 6, 0, 0); 1905 } 1906 1907 /* Create the MiniNT key */ 1908 RtlInitUnicodeString(&KeyName, L"MiniNT"); 1909 InitializeObjectAttributes(&ObjectAttributes, 1910 &KeyName, 1911 OBJ_CASE_INSENSITIVE, 1912 KeyHandle, 1913 NULL); 1914 Status = ZwCreateKey(&OptionHandle, 1915 KEY_ALL_ACCESS, 1916 &ObjectAttributes, 1917 0, 1918 NULL, 1919 REG_OPTION_VOLATILE, 1920 &Disposition); 1921 if (!NT_SUCCESS(Status)) 1922 { 1923 /* Bugcheck */ 1924 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 6, 0, 0); 1925 } 1926 1927 /* Close the handles */ 1928 NtClose(KeyHandle); 1929 NtClose(OptionHandle); 1930 } 1931 1932 /* FIXME: This doesn't do anything for now */ 1933 MmArmInitSystem(2, LoaderBlock); 1934 1935 /* Update progress bar */ 1936 InbvUpdateProgressBar(80); 1937 1938 /* Initialize VDM support */ 1939 #if defined(_M_IX86) 1940 KeI386VdmInitialize(); 1941 #endif 1942 1943 /* Initialize Power Subsystem in Phase 1*/ 1944 if (!PoInitSystem(1)) KeBugCheck(INTERNAL_POWER_ERROR); 1945 1946 /* Update progress bar */ 1947 InbvUpdateProgressBar(90); 1948 1949 /* Initialize the Process Manager at Phase 1 */ 1950 if (!PsInitSystem(LoaderBlock)) KeBugCheck(PROCESS1_INITIALIZATION_FAILED); 1951 1952 /* Make sure nobody touches the loader block again */ 1953 if (LoaderBlock == KeLoaderBlock) KeLoaderBlock = NULL; 1954 MmFreeLoaderBlock(LoaderBlock); 1955 LoaderBlock = Context = NULL; 1956 1957 /* Initialize the SRM in phase 1 */ 1958 if (!SeRmInitPhase1()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED); 1959 1960 /* Update progress bar */ 1961 InbvUpdateProgressBar(100); 1962 1963 /* Clear the screen */ 1964 if (InbvBootDriverInstalled) FinalizeBootLogo(); 1965 1966 /* Allow strings to be displayed */ 1967 InbvEnableDisplayString(TRUE); 1968 1969 /* Launch initial process */ 1970 DPRINT("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed); 1971 ProcessInfo = &InitBuffer->ProcessInfo; 1972 ExpLoadInitialProcess(InitBuffer, &ProcessParameters, &Environment); 1973 1974 /* Wait 5 seconds for initial process to initialize */ 1975 Timeout.QuadPart = Int32x32To64(5, -10000000); 1976 Status = ZwWaitForSingleObject(ProcessInfo->ProcessHandle, FALSE, &Timeout); 1977 if (Status == STATUS_SUCCESS) 1978 { 1979 /* Failed, display error */ 1980 DPRINT1("INIT: Session Manager terminated.\n"); 1981 1982 /* Bugcheck the system if SMSS couldn't initialize */ 1983 KeBugCheck(SESSION5_INITIALIZATION_FAILED); 1984 } 1985 1986 /* Close process handles */ 1987 ZwClose(ProcessInfo->ThreadHandle); 1988 ZwClose(ProcessInfo->ProcessHandle); 1989 1990 /* Free the initial process environment */ 1991 Size = 0; 1992 ZwFreeVirtualMemory(NtCurrentProcess(), 1993 (PVOID*)&Environment, 1994 &Size, 1995 MEM_RELEASE); 1996 1997 /* Free the initial process parameters */ 1998 Size = 0; 1999 ZwFreeVirtualMemory(NtCurrentProcess(), 2000 (PVOID*)&ProcessParameters, 2001 &Size, 2002 MEM_RELEASE); 2003 2004 /* Increase init phase */ 2005 ExpInitializationPhase++; 2006 2007 /* Free the boot buffer */ 2008 ExFreePoolWithTag(InitBuffer, TAG_INIT); 2009 DPRINT("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed); 2010 } 2011 2012 VOID 2013 NTAPI 2014 Phase1Initialization(IN PVOID Context) 2015 { 2016 /* Do the .INIT part of Phase 1 which we can free later */ 2017 Phase1InitializationDiscard(Context); 2018 2019 /* Jump into zero page thread */ 2020 MmZeroPageThread(); 2021 } 2022