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