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