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