1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS NT User-Mode Library 4 * FILE: dll/ntdll/ldr/ldrinit.c 5 * PURPOSE: User-Mode Process/Thread Startup 6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 7 * Aleksey Bragin (aleksey@reactos.org) 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include <ntdll.h> 13 #include <compat_undoc.h> 14 #include <compatguid_undoc.h> 15 16 #define NDEBUG 17 #include <debug.h> 18 19 20 /* GLOBALS *******************************************************************/ 21 22 HANDLE ImageExecOptionsKey; 23 HANDLE Wow64ExecOptionsKey; 24 UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"); 25 UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L""); 26 UNICODE_STRING NtDllString = RTL_CONSTANT_STRING(L"ntdll.dll"); 27 28 BOOLEAN LdrpInLdrInit; 29 LONG LdrpProcessInitialized; 30 BOOLEAN LdrpLoaderLockInit; 31 BOOLEAN LdrpLdrDatabaseIsSetup; 32 BOOLEAN LdrpShutdownInProgress; 33 HANDLE LdrpShutdownThreadId; 34 35 BOOLEAN LdrpDllValidation; 36 37 PLDR_DATA_TABLE_ENTRY LdrpImageEntry; 38 PUNICODE_STRING LdrpTopLevelDllBeingLoaded; 39 WCHAR StringBuffer[156]; 40 extern PTEB LdrpTopLevelDllBeingLoadedTeb; // defined in rtlsupp.c! 41 PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer; 42 PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry; 43 44 RTL_BITMAP TlsBitMap; 45 RTL_BITMAP TlsExpansionBitMap; 46 RTL_BITMAP FlsBitMap; 47 BOOLEAN LdrpImageHasTls; 48 LIST_ENTRY LdrpTlsList; 49 ULONG LdrpNumberOfTlsEntries; 50 ULONG LdrpNumberOfProcessors; 51 PVOID NtDllBase; 52 extern LARGE_INTEGER RtlpTimeout; 53 BOOLEAN RtlpTimeoutDisable; 54 LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES]; 55 LIST_ENTRY LdrpDllNotificationList; 56 HANDLE LdrpKnownDllObjectDirectory; 57 UNICODE_STRING LdrpKnownDllPath; 58 WCHAR LdrpKnownDllPathBuffer[128]; 59 UNICODE_STRING LdrpDefaultPath; 60 61 PEB_LDR_DATA PebLdr; 62 63 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug; 64 RTL_CRITICAL_SECTION LdrpLoaderLock = 65 { 66 &LdrpLoaderLockDebug, 67 -1, 68 0, 69 0, 70 0, 71 0 72 }; 73 RTL_CRITICAL_SECTION FastPebLock; 74 75 BOOLEAN ShowSnaps; 76 77 ULONG LdrpFatalHardErrorCount; 78 ULONG LdrpActiveUnloadCount; 79 80 //extern LIST_ENTRY RtlCriticalSectionList; 81 82 VOID NTAPI RtlpInitializeVectoredExceptionHandling(VOID); 83 VOID NTAPI RtlpInitDeferedCriticalSection(VOID); 84 VOID NTAPI RtlInitializeHeapManager(VOID); 85 86 ULONG RtlpDisableHeapLookaside; // TODO: Move to heap.c 87 ULONG RtlpShutdownProcessFlags; // TODO: Use it 88 89 NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase); 90 void actctx_init(void); 91 extern BOOLEAN RtlpUse16ByteSLists; 92 93 #ifdef _WIN64 94 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll 95 #else 96 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E 97 #endif 98 99 /* FUNCTIONS *****************************************************************/ 100 101 /* 102 * @implemented 103 */ 104 NTSTATUS 105 NTAPI 106 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey, 107 IN BOOLEAN Wow64, 108 OUT PHANDLE NewKeyHandle) 109 { 110 PHANDLE RootKeyLocation; 111 HANDLE RootKey; 112 UNICODE_STRING SubKeyString; 113 OBJECT_ATTRIBUTES ObjectAttributes; 114 NTSTATUS Status; 115 PWCHAR p1; 116 117 /* Check which root key to open */ 118 if (Wow64) 119 RootKeyLocation = &Wow64ExecOptionsKey; 120 else 121 RootKeyLocation = &ImageExecOptionsKey; 122 123 /* Get the current key */ 124 RootKey = *RootKeyLocation; 125 126 /* Setup the object attributes */ 127 InitializeObjectAttributes(&ObjectAttributes, 128 Wow64 ? 129 &Wow64OptionsString : &ImageExecOptionsString, 130 OBJ_CASE_INSENSITIVE, 131 NULL, 132 NULL); 133 134 /* Open the root key */ 135 Status = ZwOpenKey(&RootKey, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); 136 if (NT_SUCCESS(Status)) 137 { 138 /* Write the key handle */ 139 if (InterlockedCompareExchangePointer(RootKeyLocation, RootKey, NULL) != NULL) 140 { 141 /* Someone already opened it, use it instead */ 142 NtClose(RootKey); 143 RootKey = *RootKeyLocation; 144 } 145 146 /* Extract the name */ 147 SubKeyString = *SubKey; 148 p1 = (PWCHAR)((ULONG_PTR)SubKeyString.Buffer + SubKeyString.Length); 149 while (SubKeyString.Length) 150 { 151 if (p1[-1] == L'\\') break; 152 p1--; 153 SubKeyString.Length -= sizeof(*p1); 154 } 155 SubKeyString.Buffer = p1; 156 SubKeyString.Length = SubKey->Length - SubKeyString.Length; 157 158 /* Setup the object attributes */ 159 InitializeObjectAttributes(&ObjectAttributes, 160 &SubKeyString, 161 OBJ_CASE_INSENSITIVE, 162 RootKey, 163 NULL); 164 165 /* Open the setting key */ 166 Status = ZwOpenKey((PHANDLE)NewKeyHandle, GENERIC_READ, &ObjectAttributes); 167 } 168 169 /* Return to caller */ 170 return Status; 171 } 172 173 /* 174 * @implemented 175 */ 176 NTSTATUS 177 NTAPI 178 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle, 179 IN PCWSTR ValueName, 180 IN ULONG Type, 181 OUT PVOID Buffer, 182 IN ULONG BufferSize, 183 OUT PULONG ReturnedLength OPTIONAL) 184 { 185 ULONG KeyInfo[256]; 186 UNICODE_STRING ValueNameString, IntegerString; 187 ULONG KeyInfoSize, ResultSize; 188 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)&KeyInfo; 189 BOOLEAN FreeHeap = FALSE; 190 NTSTATUS Status; 191 192 /* Build a string for the value name */ 193 Status = RtlInitUnicodeStringEx(&ValueNameString, ValueName); 194 if (!NT_SUCCESS(Status)) return Status; 195 196 /* Query the value */ 197 Status = ZwQueryValueKey(KeyHandle, 198 &ValueNameString, 199 KeyValuePartialInformation, 200 KeyValueInformation, 201 sizeof(KeyInfo), 202 &ResultSize); 203 if (Status == STATUS_BUFFER_OVERFLOW) 204 { 205 /* Our local buffer wasn't enough, allocate one */ 206 KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 207 KeyValueInformation->DataLength; 208 KeyValueInformation = RtlAllocateHeap(RtlGetProcessHeap(), 209 0, 210 KeyInfoSize); 211 if (KeyValueInformation != NULL) 212 { 213 /* Try again */ 214 Status = ZwQueryValueKey(KeyHandle, 215 &ValueNameString, 216 KeyValuePartialInformation, 217 KeyValueInformation, 218 KeyInfoSize, 219 &ResultSize); 220 FreeHeap = TRUE; 221 } 222 else 223 { 224 /* Give up this time */ 225 Status = STATUS_NO_MEMORY; 226 } 227 } 228 229 /* Check for success */ 230 if (NT_SUCCESS(Status)) 231 { 232 /* Handle binary data */ 233 if (KeyValueInformation->Type == REG_BINARY) 234 { 235 /* Check validity */ 236 if ((Buffer) && (KeyValueInformation->DataLength <= BufferSize)) 237 { 238 /* Copy into buffer */ 239 RtlMoveMemory(Buffer, 240 &KeyValueInformation->Data, 241 KeyValueInformation->DataLength); 242 } 243 else 244 { 245 Status = STATUS_BUFFER_OVERFLOW; 246 } 247 248 /* Copy the result length */ 249 if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength; 250 } 251 else if (KeyValueInformation->Type == REG_DWORD) 252 { 253 /* Check for valid type */ 254 if (KeyValueInformation->Type != Type) 255 { 256 /* Error */ 257 Status = STATUS_OBJECT_TYPE_MISMATCH; 258 } 259 else 260 { 261 /* Check validity */ 262 if ((Buffer) && 263 (BufferSize == sizeof(ULONG)) && 264 (KeyValueInformation->DataLength <= BufferSize)) 265 { 266 /* Copy into buffer */ 267 RtlMoveMemory(Buffer, 268 &KeyValueInformation->Data, 269 KeyValueInformation->DataLength); 270 } 271 else 272 { 273 Status = STATUS_BUFFER_OVERFLOW; 274 } 275 276 /* Copy the result length */ 277 if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength; 278 } 279 } 280 else if (KeyValueInformation->Type != REG_SZ) 281 { 282 /* We got something weird */ 283 Status = STATUS_OBJECT_TYPE_MISMATCH; 284 } 285 else 286 { 287 /* String, check what you requested */ 288 if (Type == REG_DWORD) 289 { 290 /* Validate */ 291 if (BufferSize != sizeof(ULONG)) 292 { 293 /* Invalid size */ 294 BufferSize = 0; 295 Status = STATUS_INFO_LENGTH_MISMATCH; 296 } 297 else 298 { 299 /* OK, we know what you want... */ 300 IntegerString.Buffer = (PWSTR)KeyValueInformation->Data; 301 IntegerString.Length = (USHORT)KeyValueInformation->DataLength - 302 sizeof(WCHAR); 303 IntegerString.MaximumLength = (USHORT)KeyValueInformation->DataLength; 304 Status = RtlUnicodeStringToInteger(&IntegerString, 0, (PULONG)Buffer); 305 } 306 } 307 else 308 { 309 /* Validate */ 310 if (KeyValueInformation->DataLength > BufferSize) 311 { 312 /* Invalid */ 313 Status = STATUS_BUFFER_OVERFLOW; 314 } 315 else 316 { 317 /* Set the size */ 318 BufferSize = KeyValueInformation->DataLength; 319 } 320 321 /* Copy the string */ 322 RtlMoveMemory(Buffer, &KeyValueInformation->Data, BufferSize); 323 } 324 325 /* Copy the result length */ 326 if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength; 327 } 328 } 329 330 /* Check if buffer was in heap */ 331 if (FreeHeap) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation); 332 333 /* Return status */ 334 return Status; 335 } 336 337 /* 338 * @implemented 339 */ 340 NTSTATUS 341 NTAPI 342 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey, 343 IN PCWSTR ValueName, 344 IN ULONG Type, 345 OUT PVOID Buffer, 346 IN ULONG BufferSize, 347 OUT PULONG ReturnedLength OPTIONAL, 348 IN BOOLEAN Wow64) 349 { 350 NTSTATUS Status; 351 HANDLE KeyHandle; 352 353 /* Open a handle to the key */ 354 Status = LdrOpenImageFileOptionsKey(SubKey, Wow64, &KeyHandle); 355 356 /* Check for success */ 357 if (NT_SUCCESS(Status)) 358 { 359 /* Query the data */ 360 Status = LdrQueryImageFileKeyOption(KeyHandle, 361 ValueName, 362 Type, 363 Buffer, 364 BufferSize, 365 ReturnedLength); 366 367 /* Close the key */ 368 NtClose(KeyHandle); 369 } 370 371 /* Return to caller */ 372 return Status; 373 } 374 375 /* 376 * @implemented 377 */ 378 NTSTATUS 379 NTAPI 380 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey, 381 IN PCWSTR ValueName, 382 IN ULONG Type, 383 OUT PVOID Buffer, 384 IN ULONG BufferSize, 385 OUT PULONG ReturnedLength OPTIONAL) 386 { 387 /* Call the newer function */ 388 return LdrQueryImageFileExecutionOptionsEx(SubKey, 389 ValueName, 390 Type, 391 Buffer, 392 BufferSize, 393 ReturnedLength, 394 FALSE); 395 } 396 397 VOID 398 NTAPI 399 LdrpEnsureLoaderLockIsHeld(VOID) 400 { 401 // Ignored atm 402 } 403 404 PVOID 405 NTAPI 406 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress, ULONG SizeOfImage) 407 { 408 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir; 409 ULONG DirSize; 410 PVOID Cookie = NULL; 411 412 /* Check NT header first */ 413 if (!RtlImageNtHeader(BaseAddress)) return NULL; 414 415 /* Get the pointer to the config directory */ 416 ConfigDir = RtlImageDirectoryEntryToData(BaseAddress, 417 TRUE, 418 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, 419 &DirSize); 420 421 /* Check for sanity */ 422 if (!ConfigDir || 423 (DirSize != 64 && ConfigDir->Size != DirSize) || 424 (ConfigDir->Size < 0x48)) 425 return NULL; 426 427 /* Now get the cookie */ 428 Cookie = (PVOID)ConfigDir->SecurityCookie; 429 430 /* Check this cookie */ 431 if ((PCHAR)Cookie <= (PCHAR)BaseAddress || 432 (PCHAR)Cookie >= (PCHAR)BaseAddress + SizeOfImage) 433 { 434 Cookie = NULL; 435 } 436 437 /* Return validated security cookie */ 438 return Cookie; 439 } 440 441 PVOID 442 NTAPI 443 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry) 444 { 445 PULONG_PTR Cookie; 446 LARGE_INTEGER Counter; 447 ULONG_PTR NewCookie; 448 449 /* Fetch address of the cookie */ 450 Cookie = LdrpFetchAddressOfSecurityCookie(LdrEntry->DllBase, LdrEntry->SizeOfImage); 451 452 if (Cookie) 453 { 454 /* Check if it's a default one */ 455 if ((*Cookie == DEFAULT_SECURITY_COOKIE) || 456 (*Cookie == 0xBB40)) 457 { 458 /* Make up a cookie from a bunch of values which may uniquely represent 459 current moment of time, environment, etc */ 460 NtQueryPerformanceCounter(&Counter, NULL); 461 462 NewCookie = Counter.LowPart ^ Counter.HighPart; 463 NewCookie ^= (ULONG_PTR)NtCurrentTeb()->ClientId.UniqueProcess; 464 NewCookie ^= (ULONG_PTR)NtCurrentTeb()->ClientId.UniqueThread; 465 466 /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */ 467 while (SharedUserData->SystemTime.High1Time != SharedUserData->SystemTime.High2Time) 468 { 469 YieldProcessor(); 470 }; 471 472 /* Calculate the milliseconds value and xor it to the cookie */ 473 NewCookie ^= Int64ShrlMod32(UInt32x32To64(SharedUserData->TickCountMultiplier, SharedUserData->TickCount.LowPart), 24) + 474 (SharedUserData->TickCountMultiplier * (SharedUserData->TickCount.High1Time << 8)); 475 476 /* Make the cookie 16bit if necessary */ 477 if (*Cookie == 0xBB40) NewCookie &= 0xFFFF; 478 479 /* If the result is 0 or the same as we got, just subtract one from the existing value 480 and that's it */ 481 if ((NewCookie == 0) || (NewCookie == *Cookie)) 482 { 483 NewCookie = *Cookie - 1; 484 } 485 486 /* Set the new cookie value */ 487 *Cookie = NewCookie; 488 } 489 } 490 491 return Cookie; 492 } 493 494 VOID 495 NTAPI 496 LdrpInitializeThread(IN PCONTEXT Context) 497 { 498 PPEB Peb = NtCurrentPeb(); 499 PLDR_DATA_TABLE_ENTRY LdrEntry; 500 PLIST_ENTRY NextEntry, ListHead; 501 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; 502 NTSTATUS Status; 503 PVOID EntryPoint; 504 505 DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n", 506 &LdrpImageEntry->BaseDllName, 507 NtCurrentTeb()->RealClientId.UniqueProcess, 508 NtCurrentTeb()->RealClientId.UniqueThread); 509 510 /* Allocate an Activation Context Stack */ 511 DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer); 512 Status = RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer); 513 if (!NT_SUCCESS(Status)) 514 { 515 DPRINT1("Warning: Unable to allocate ActivationContextStack\n"); 516 } 517 518 /* Make sure we are not shutting down */ 519 if (LdrpShutdownInProgress) return; 520 521 /* Allocate TLS */ 522 LdrpAllocateTls(); 523 524 /* Start at the beginning */ 525 ListHead = &Peb->Ldr->InMemoryOrderModuleList; 526 NextEntry = ListHead->Flink; 527 while (NextEntry != ListHead) 528 { 529 /* Get the current entry */ 530 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); 531 532 /* Make sure it's not ourselves */ 533 if (Peb->ImageBaseAddress != LdrEntry->DllBase) 534 { 535 /* Check if we should call */ 536 if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS)) 537 { 538 /* Get the entrypoint */ 539 EntryPoint = LdrEntry->EntryPoint; 540 541 /* Check if we are ready to call it */ 542 if ((EntryPoint) && 543 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) && 544 (LdrEntry->Flags & LDRP_IMAGE_DLL)) 545 { 546 /* Set up the Act Ctx */ 547 ActCtx.Size = sizeof(ActCtx); 548 ActCtx.Format = 1; 549 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 550 551 /* Activate the ActCtx */ 552 RtlActivateActivationContextUnsafeFast(&ActCtx, 553 LdrEntry->EntryPointActivationContext); 554 555 /* Check if it has TLS */ 556 if (LdrEntry->TlsIndex) 557 { 558 /* Make sure we're not shutting down */ 559 if (!LdrpShutdownInProgress) 560 { 561 /* Call TLS */ 562 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_ATTACH); 563 } 564 } 565 566 /* Make sure we're not shutting down */ 567 if (!LdrpShutdownInProgress) 568 { 569 /* Call the Entrypoint */ 570 DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n", 571 &LdrEntry->BaseDllName, LdrEntry->EntryPoint, 572 NtCurrentTeb()->RealClientId.UniqueProcess, 573 NtCurrentTeb()->RealClientId.UniqueThread); 574 LdrpCallInitRoutine(LdrEntry->EntryPoint, 575 LdrEntry->DllBase, 576 DLL_THREAD_ATTACH, 577 NULL); 578 } 579 580 /* Deactivate the ActCtx */ 581 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 582 } 583 } 584 } 585 586 /* Next entry */ 587 NextEntry = NextEntry->Flink; 588 } 589 590 /* Check for TLS */ 591 if (LdrpImageHasTls && !LdrpShutdownInProgress) 592 { 593 /* Set up the Act Ctx */ 594 ActCtx.Size = sizeof(ActCtx); 595 ActCtx.Format = 1; 596 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 597 598 /* Activate the ActCtx */ 599 RtlActivateActivationContextUnsafeFast(&ActCtx, 600 LdrpImageEntry->EntryPointActivationContext); 601 602 /* Do TLS callbacks */ 603 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_ATTACH); 604 605 /* Deactivate the ActCtx */ 606 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 607 } 608 609 DPRINT("LdrpInitializeThread() done\n"); 610 } 611 612 NTSTATUS 613 NTAPI 614 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) 615 { 616 PLDR_DATA_TABLE_ENTRY LocalArray[16]; 617 PLIST_ENTRY ListHead; 618 PLIST_ENTRY NextEntry; 619 PLDR_DATA_TABLE_ENTRY LdrEntry, *LdrRootEntry, OldInitializer; 620 PVOID EntryPoint; 621 ULONG Count, i; 622 //ULONG BreakOnInit; 623 NTSTATUS Status = STATUS_SUCCESS; 624 PPEB Peb = NtCurrentPeb(); 625 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; 626 ULONG BreakOnDllLoad; 627 PTEB OldTldTeb; 628 BOOLEAN DllStatus; 629 630 DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n", 631 &LdrpImageEntry->BaseDllName, 632 NtCurrentTeb()->RealClientId.UniqueProcess, 633 NtCurrentTeb()->RealClientId.UniqueThread); 634 635 /* Check the Loader Lock */ 636 LdrpEnsureLoaderLockIsHeld(); 637 638 /* Get the number of entries to call */ 639 if ((Count = LdrpClearLoadInProgress())) 640 { 641 /* Check if we can use our local buffer */ 642 if (Count > 16) 643 { 644 /* Allocate space for all the entries */ 645 LdrRootEntry = RtlAllocateHeap(RtlGetProcessHeap(), 646 0, 647 Count * sizeof(*LdrRootEntry)); 648 if (!LdrRootEntry) return STATUS_NO_MEMORY; 649 } 650 else 651 { 652 /* Use our local array */ 653 LdrRootEntry = LocalArray; 654 } 655 } 656 else 657 { 658 /* Don't need one */ 659 LdrRootEntry = NULL; 660 } 661 662 /* Show debug message */ 663 if (ShowSnaps) 664 { 665 DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n", 666 NtCurrentTeb()->RealClientId.UniqueThread, 667 NtCurrentTeb()->RealClientId.UniqueProcess, 668 &Peb->ProcessParameters->ImagePathName); 669 } 670 671 /* Loop in order */ 672 ListHead = &Peb->Ldr->InInitializationOrderModuleList; 673 NextEntry = ListHead->Flink; 674 i = 0; 675 while (NextEntry != ListHead) 676 { 677 /* Get the Data Entry */ 678 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); 679 680 /* Check if we have a Root Entry */ 681 if (LdrRootEntry) 682 { 683 /* Check flags */ 684 if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED)) 685 { 686 /* Setup the Cookie for the DLL */ 687 LdrpInitSecurityCookie(LdrEntry); 688 689 /* Check for valid entrypoint */ 690 if (LdrEntry->EntryPoint) 691 { 692 /* Write in array */ 693 ASSERT(i < Count); 694 LdrRootEntry[i] = LdrEntry; 695 696 /* Display debug message */ 697 if (ShowSnaps) 698 { 699 DPRINT1("[%p,%p] LDR: %wZ init routine %p\n", 700 NtCurrentTeb()->RealClientId.UniqueThread, 701 NtCurrentTeb()->RealClientId.UniqueProcess, 702 &LdrEntry->FullDllName, 703 LdrEntry->EntryPoint); 704 } 705 i++; 706 } 707 } 708 } 709 710 /* Set the flag */ 711 LdrEntry->Flags |= LDRP_ENTRY_PROCESSED; 712 NextEntry = NextEntry->Flink; 713 } 714 715 /* If we got a context, then we have to call Kernel32 for TS support */ 716 if (Context) 717 { 718 /* Check if we have one */ 719 //if (Kernel32ProcessInitPostImportfunction) 720 //{ 721 /* Call it */ 722 //Kernel32ProcessInitPostImportfunction(); 723 //} 724 725 /* Clear it */ 726 //Kernel32ProcessInitPostImportfunction = NULL; 727 //UNIMPLEMENTED; 728 } 729 730 /* No root entry? return */ 731 if (!LdrRootEntry) return STATUS_SUCCESS; 732 733 /* Set the TLD TEB */ 734 OldTldTeb = LdrpTopLevelDllBeingLoadedTeb; 735 LdrpTopLevelDllBeingLoadedTeb = NtCurrentTeb(); 736 737 /* Loop */ 738 i = 0; 739 while (i < Count) 740 { 741 /* Get an entry */ 742 LdrEntry = LdrRootEntry[i]; 743 744 /* FIXME: Verify NX Compat */ 745 746 /* Move to next entry */ 747 i++; 748 749 /* Get its entrypoint */ 750 EntryPoint = LdrEntry->EntryPoint; 751 752 /* Are we being debugged? */ 753 BreakOnDllLoad = 0; 754 if (Peb->BeingDebugged || Peb->ReadImageFileExecOptions) 755 { 756 /* Check if we should break on load */ 757 Status = LdrQueryImageFileExecutionOptions(&LdrEntry->BaseDllName, 758 L"BreakOnDllLoad", 759 REG_DWORD, 760 &BreakOnDllLoad, 761 sizeof(ULONG), 762 NULL); 763 if (!NT_SUCCESS(Status)) BreakOnDllLoad = 0; 764 765 /* Reset status back to STATUS_SUCCESS */ 766 Status = STATUS_SUCCESS; 767 } 768 769 /* Break if aksed */ 770 if (BreakOnDllLoad) 771 { 772 /* Check if we should show a message */ 773 if (ShowSnaps) 774 { 775 DPRINT1("LDR: %wZ loaded.", &LdrEntry->BaseDllName); 776 DPRINT1(" - About to call init routine at %p\n", EntryPoint); 777 } 778 779 /* Break in debugger */ 780 DbgBreakPoint(); 781 } 782 783 /* Make sure we have an entrypoint */ 784 if (EntryPoint) 785 { 786 /* Save the old Dll Initializer and write the current one */ 787 OldInitializer = LdrpCurrentDllInitializer; 788 LdrpCurrentDllInitializer = LdrEntry; 789 790 /* Set up the Act Ctx */ 791 ActCtx.Size = sizeof(ActCtx); 792 ActCtx.Format = 1; 793 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 794 795 /* Activate the ActCtx */ 796 RtlActivateActivationContextUnsafeFast(&ActCtx, 797 LdrEntry->EntryPointActivationContext); 798 799 /* Check if it has TLS */ 800 if (LdrEntry->TlsIndex && Context) 801 { 802 /* Call TLS */ 803 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_ATTACH); 804 } 805 806 /* Call the Entrypoint */ 807 if (ShowSnaps) 808 { 809 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n", 810 &LdrEntry->BaseDllName, EntryPoint); 811 } 812 DllStatus = LdrpCallInitRoutine(EntryPoint, 813 LdrEntry->DllBase, 814 DLL_PROCESS_ATTACH, 815 Context); 816 817 /* Deactivate the ActCtx */ 818 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 819 820 /* Save the Current DLL Initializer */ 821 LdrpCurrentDllInitializer = OldInitializer; 822 823 /* Mark the entry as processed */ 824 LdrEntry->Flags |= LDRP_PROCESS_ATTACH_CALLED; 825 826 /* Fail if DLL init failed */ 827 if (!DllStatus) 828 { 829 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n", 830 &LdrEntry->BaseDllName, EntryPoint); 831 832 Status = STATUS_DLL_INIT_FAILED; 833 goto Quickie; 834 } 835 } 836 } 837 838 /* Loop in order */ 839 ListHead = &Peb->Ldr->InInitializationOrderModuleList; 840 NextEntry = NextEntry->Flink; 841 while (NextEntry != ListHead) 842 { 843 /* Get the Data Entry */ 844 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); 845 846 /* FIXME: Verify NX Compat */ 847 // LdrpCheckNXCompatibility() 848 849 /* Next entry */ 850 NextEntry = NextEntry->Flink; 851 } 852 853 /* Check for TLS */ 854 if (LdrpImageHasTls && Context) 855 { 856 /* Set up the Act Ctx */ 857 ActCtx.Size = sizeof(ActCtx); 858 ActCtx.Format = 1; 859 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 860 861 /* Activate the ActCtx */ 862 RtlActivateActivationContextUnsafeFast(&ActCtx, 863 LdrpImageEntry->EntryPointActivationContext); 864 865 /* Do TLS callbacks */ 866 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_ATTACH); 867 868 /* Deactivate the ActCtx */ 869 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 870 } 871 872 Quickie: 873 /* Restore old TEB */ 874 LdrpTopLevelDllBeingLoadedTeb = OldTldTeb; 875 876 /* Check if the array is in the heap */ 877 if (LdrRootEntry != LocalArray) 878 { 879 /* Free the array */ 880 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry); 881 } 882 883 /* Return to caller */ 884 DPRINT("LdrpRunInitializeRoutines() done\n"); 885 return Status; 886 } 887 888 /* 889 * @implemented 890 */ 891 NTSTATUS 892 NTAPI 893 LdrShutdownProcess(VOID) 894 { 895 PPEB Peb = NtCurrentPeb(); 896 PLDR_DATA_TABLE_ENTRY LdrEntry; 897 PLIST_ENTRY NextEntry, ListHead; 898 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; 899 PVOID EntryPoint; 900 901 DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry->BaseDllName); 902 if (LdrpShutdownInProgress) return STATUS_SUCCESS; 903 904 /* Tell the Shim Engine */ 905 if (g_ShimsEnabled) 906 { 907 VOID(NTAPI *SE_ProcessDying)(); 908 SE_ProcessDying = RtlDecodeSystemPointer(g_pfnSE_ProcessDying); 909 SE_ProcessDying(); 910 } 911 912 /* Tell the world */ 913 if (ShowSnaps) 914 { 915 DPRINT1("\n"); 916 } 917 918 /* Set the shutdown variables */ 919 LdrpShutdownThreadId = NtCurrentTeb()->RealClientId.UniqueThread; 920 LdrpShutdownInProgress = TRUE; 921 922 /* Enter the Loader Lock */ 923 RtlEnterCriticalSection(&LdrpLoaderLock); 924 925 /* Cleanup trace logging data (Etw) */ 926 if (SharedUserData->TraceLogging) 927 { 928 /* FIXME */ 929 DPRINT1("We don't support Etw yet.\n"); 930 } 931 932 /* Start at the end */ 933 ListHead = &Peb->Ldr->InInitializationOrderModuleList; 934 NextEntry = ListHead->Blink; 935 while (NextEntry != ListHead) 936 { 937 /* Get the current entry */ 938 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); 939 NextEntry = NextEntry->Blink; 940 941 /* Make sure it's not ourselves */ 942 if (Peb->ImageBaseAddress != LdrEntry->DllBase) 943 { 944 /* Get the entrypoint */ 945 EntryPoint = LdrEntry->EntryPoint; 946 947 /* Check if we are ready to call it */ 948 if (EntryPoint && 949 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) && 950 LdrEntry->Flags) 951 { 952 /* Set up the Act Ctx */ 953 ActCtx.Size = sizeof(ActCtx); 954 ActCtx.Format = 1; 955 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 956 957 /* Activate the ActCtx */ 958 RtlActivateActivationContextUnsafeFast(&ActCtx, 959 LdrEntry->EntryPointActivationContext); 960 961 /* Check if it has TLS */ 962 if (LdrEntry->TlsIndex) 963 { 964 /* Call TLS */ 965 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_DETACH); 966 } 967 968 /* Call the Entrypoint */ 969 DPRINT("%wZ - Calling entry point at %p for thread detaching\n", 970 &LdrEntry->BaseDllName, LdrEntry->EntryPoint); 971 LdrpCallInitRoutine(EntryPoint, 972 LdrEntry->DllBase, 973 DLL_PROCESS_DETACH, 974 (PVOID)1); 975 976 /* Deactivate the ActCtx */ 977 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 978 } 979 } 980 } 981 982 /* Check for TLS */ 983 if (LdrpImageHasTls) 984 { 985 /* Set up the Act Ctx */ 986 ActCtx.Size = sizeof(ActCtx); 987 ActCtx.Format = 1; 988 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 989 990 /* Activate the ActCtx */ 991 RtlActivateActivationContextUnsafeFast(&ActCtx, 992 LdrpImageEntry->EntryPointActivationContext); 993 994 /* Do TLS callbacks */ 995 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_DETACH); 996 997 /* Deactivate the ActCtx */ 998 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 999 } 1000 1001 /* FIXME: Do Heap detection and Etw final shutdown */ 1002 1003 /* Release the lock */ 1004 RtlLeaveCriticalSection(&LdrpLoaderLock); 1005 DPRINT("LdrpShutdownProcess() done\n"); 1006 1007 return STATUS_SUCCESS; 1008 } 1009 1010 /* 1011 * @implemented 1012 */ 1013 NTSTATUS 1014 NTAPI 1015 LdrShutdownThread(VOID) 1016 { 1017 PPEB Peb = NtCurrentPeb(); 1018 PTEB Teb = NtCurrentTeb(); 1019 PLDR_DATA_TABLE_ENTRY LdrEntry; 1020 PLIST_ENTRY NextEntry, ListHead; 1021 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; 1022 PVOID EntryPoint; 1023 1024 DPRINT("LdrShutdownThread() called for %wZ\n", 1025 &LdrpImageEntry->BaseDllName); 1026 1027 /* Cleanup trace logging data (Etw) */ 1028 if (SharedUserData->TraceLogging) 1029 { 1030 /* FIXME */ 1031 DPRINT1("We don't support Etw yet.\n"); 1032 } 1033 1034 /* Get the Ldr Lock */ 1035 RtlEnterCriticalSection(&LdrpLoaderLock); 1036 1037 /* Start at the end */ 1038 ListHead = &Peb->Ldr->InInitializationOrderModuleList; 1039 NextEntry = ListHead->Blink; 1040 while (NextEntry != ListHead) 1041 { 1042 /* Get the current entry */ 1043 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); 1044 NextEntry = NextEntry->Blink; 1045 1046 /* Make sure it's not ourselves */ 1047 if (Peb->ImageBaseAddress != LdrEntry->DllBase) 1048 { 1049 /* Check if we should call */ 1050 if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS) && 1051 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) && 1052 (LdrEntry->Flags & LDRP_IMAGE_DLL)) 1053 { 1054 /* Get the entrypoint */ 1055 EntryPoint = LdrEntry->EntryPoint; 1056 1057 /* Check if we are ready to call it */ 1058 if (EntryPoint) 1059 { 1060 /* Set up the Act Ctx */ 1061 ActCtx.Size = sizeof(ActCtx); 1062 ActCtx.Format = 1; 1063 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 1064 1065 /* Activate the ActCtx */ 1066 RtlActivateActivationContextUnsafeFast(&ActCtx, 1067 LdrEntry->EntryPointActivationContext); 1068 1069 /* Check if it has TLS */ 1070 if (LdrEntry->TlsIndex) 1071 { 1072 /* Make sure we're not shutting down */ 1073 if (!LdrpShutdownInProgress) 1074 { 1075 /* Call TLS */ 1076 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_DETACH); 1077 } 1078 } 1079 1080 /* Make sure we're not shutting down */ 1081 if (!LdrpShutdownInProgress) 1082 { 1083 /* Call the Entrypoint */ 1084 DPRINT("%wZ - Calling entry point at %p for thread detaching\n", 1085 &LdrEntry->BaseDllName, LdrEntry->EntryPoint); 1086 LdrpCallInitRoutine(EntryPoint, 1087 LdrEntry->DllBase, 1088 DLL_THREAD_DETACH, 1089 NULL); 1090 } 1091 1092 /* Deactivate the ActCtx */ 1093 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 1094 } 1095 } 1096 } 1097 } 1098 1099 /* Check for TLS */ 1100 if (LdrpImageHasTls) 1101 { 1102 /* Set up the Act Ctx */ 1103 ActCtx.Size = sizeof(ActCtx); 1104 ActCtx.Format = 1; 1105 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 1106 1107 /* Activate the ActCtx */ 1108 RtlActivateActivationContextUnsafeFast(&ActCtx, 1109 LdrpImageEntry->EntryPointActivationContext); 1110 1111 /* Do TLS callbacks */ 1112 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_DETACH); 1113 1114 /* Deactivate the ActCtx */ 1115 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 1116 } 1117 1118 /* Free TLS */ 1119 LdrpFreeTls(); 1120 RtlLeaveCriticalSection(&LdrpLoaderLock); 1121 1122 /* Check for expansion slots */ 1123 if (Teb->TlsExpansionSlots) 1124 { 1125 /* Free expansion slots */ 1126 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->TlsExpansionSlots); 1127 } 1128 1129 /* Check for FLS Data */ 1130 if (Teb->FlsData) 1131 { 1132 /* FIXME */ 1133 DPRINT1("We don't support FLS Data yet\n"); 1134 } 1135 1136 /* Check for Fiber data */ 1137 if (Teb->HasFiberData) 1138 { 1139 /* Free Fiber data*/ 1140 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->NtTib.FiberData); 1141 Teb->NtTib.FiberData = NULL; 1142 } 1143 1144 /* Free the activation context stack */ 1145 RtlFreeThreadActivationContextStack(); 1146 DPRINT("LdrShutdownThread() done\n"); 1147 1148 return STATUS_SUCCESS; 1149 } 1150 1151 NTSTATUS 1152 NTAPI 1153 LdrpInitializeTls(VOID) 1154 { 1155 PLIST_ENTRY NextEntry, ListHead; 1156 PLDR_DATA_TABLE_ENTRY LdrEntry; 1157 PIMAGE_TLS_DIRECTORY TlsDirectory; 1158 PLDRP_TLS_DATA TlsData; 1159 ULONG Size; 1160 1161 /* Initialize the TLS List */ 1162 InitializeListHead(&LdrpTlsList); 1163 1164 /* Loop all the modules */ 1165 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 1166 NextEntry = ListHead->Flink; 1167 while (ListHead != NextEntry) 1168 { 1169 /* Get the entry */ 1170 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 1171 NextEntry = NextEntry->Flink; 1172 1173 /* Get the TLS directory */ 1174 TlsDirectory = RtlImageDirectoryEntryToData(LdrEntry->DllBase, 1175 TRUE, 1176 IMAGE_DIRECTORY_ENTRY_TLS, 1177 &Size); 1178 1179 /* Check if we have a directory */ 1180 if (!TlsDirectory) continue; 1181 1182 /* Check if the image has TLS */ 1183 if (!LdrpImageHasTls) LdrpImageHasTls = TRUE; 1184 1185 /* Show debug message */ 1186 if (ShowSnaps) 1187 { 1188 DPRINT1("LDR: Tls Found in %wZ at %p\n", 1189 &LdrEntry->BaseDllName, 1190 TlsDirectory); 1191 } 1192 1193 /* Allocate an entry */ 1194 TlsData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA)); 1195 if (!TlsData) return STATUS_NO_MEMORY; 1196 1197 /* Lock the DLL and mark it for TLS Usage */ 1198 LdrEntry->LoadCount = -1; 1199 LdrEntry->TlsIndex = -1; 1200 1201 /* Save the cached TLS data */ 1202 TlsData->TlsDirectory = *TlsDirectory; 1203 InsertTailList(&LdrpTlsList, &TlsData->TlsLinks); 1204 1205 /* Update the index */ 1206 *(PLONG)TlsData->TlsDirectory.AddressOfIndex = LdrpNumberOfTlsEntries; 1207 TlsData->TlsDirectory.Characteristics = LdrpNumberOfTlsEntries++; 1208 } 1209 1210 /* Done setting up TLS, allocate entries */ 1211 return LdrpAllocateTls(); 1212 } 1213 1214 NTSTATUS 1215 NTAPI 1216 LdrpAllocateTls(VOID) 1217 { 1218 PTEB Teb = NtCurrentTeb(); 1219 PLIST_ENTRY NextEntry, ListHead; 1220 PLDRP_TLS_DATA TlsData; 1221 SIZE_T TlsDataSize; 1222 PVOID *TlsVector; 1223 1224 /* Check if we have any entries */ 1225 if (!LdrpNumberOfTlsEntries) 1226 return STATUS_SUCCESS; 1227 1228 /* Allocate the vector array */ 1229 TlsVector = RtlAllocateHeap(RtlGetProcessHeap(), 1230 0, 1231 LdrpNumberOfTlsEntries * sizeof(PVOID)); 1232 if (!TlsVector) return STATUS_NO_MEMORY; 1233 Teb->ThreadLocalStoragePointer = TlsVector; 1234 1235 /* Loop the TLS Array */ 1236 ListHead = &LdrpTlsList; 1237 NextEntry = ListHead->Flink; 1238 while (NextEntry != ListHead) 1239 { 1240 /* Get the entry */ 1241 TlsData = CONTAINING_RECORD(NextEntry, LDRP_TLS_DATA, TlsLinks); 1242 NextEntry = NextEntry->Flink; 1243 1244 /* Allocate this vector */ 1245 TlsDataSize = TlsData->TlsDirectory.EndAddressOfRawData - 1246 TlsData->TlsDirectory.StartAddressOfRawData; 1247 TlsVector[TlsData->TlsDirectory.Characteristics] = RtlAllocateHeap(RtlGetProcessHeap(), 1248 0, 1249 TlsDataSize); 1250 if (!TlsVector[TlsData->TlsDirectory.Characteristics]) 1251 { 1252 /* Out of memory */ 1253 return STATUS_NO_MEMORY; 1254 } 1255 1256 /* Show debug message */ 1257 if (ShowSnaps) 1258 { 1259 DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n", 1260 TlsVector, 1261 TlsData->TlsDirectory.Characteristics, 1262 &TlsVector[TlsData->TlsDirectory.Characteristics], 1263 TlsData->TlsDirectory.StartAddressOfRawData, 1264 TlsVector[TlsData->TlsDirectory.Characteristics]); 1265 } 1266 1267 /* Copy the data */ 1268 RtlCopyMemory(TlsVector[TlsData->TlsDirectory.Characteristics], 1269 (PVOID)TlsData->TlsDirectory.StartAddressOfRawData, 1270 TlsDataSize); 1271 } 1272 1273 /* Done */ 1274 return STATUS_SUCCESS; 1275 } 1276 1277 VOID 1278 NTAPI 1279 LdrpFreeTls(VOID) 1280 { 1281 PLIST_ENTRY ListHead, NextEntry; 1282 PLDRP_TLS_DATA TlsData; 1283 PVOID *TlsVector; 1284 PTEB Teb = NtCurrentTeb(); 1285 1286 /* Get a pointer to the vector array */ 1287 TlsVector = Teb->ThreadLocalStoragePointer; 1288 if (!TlsVector) return; 1289 1290 /* Loop through it */ 1291 ListHead = &LdrpTlsList; 1292 NextEntry = ListHead->Flink; 1293 while (NextEntry != ListHead) 1294 { 1295 TlsData = CONTAINING_RECORD(NextEntry, LDRP_TLS_DATA, TlsLinks); 1296 NextEntry = NextEntry->Flink; 1297 1298 /* Free each entry */ 1299 if (TlsVector[TlsData->TlsDirectory.Characteristics]) 1300 { 1301 RtlFreeHeap(RtlGetProcessHeap(), 1302 0, 1303 TlsVector[TlsData->TlsDirectory.Characteristics]); 1304 } 1305 } 1306 1307 /* Free the array itself */ 1308 RtlFreeHeap(RtlGetProcessHeap(), 1309 0, 1310 TlsVector); 1311 } 1312 1313 NTSTATUS 1314 NTAPI 1315 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHANDLE OptionsKey) 1316 { 1317 NTSTATUS Status; 1318 HANDLE KeyHandle; 1319 ULONG ExecuteOptions, MinimumStackCommit = 0, GlobalFlag; 1320 1321 /* Return error if we were not provided a pointer where to save the options key handle */ 1322 if (!OptionsKey) return STATUS_INVALID_HANDLE; 1323 1324 /* Zero initialize the options key pointer */ 1325 *OptionsKey = NULL; 1326 1327 /* Open the options key */ 1328 Status = LdrOpenImageFileOptionsKey(ImagePathName, 0, &KeyHandle); 1329 1330 /* Save it if it was opened successfully */ 1331 if (NT_SUCCESS(Status)) 1332 *OptionsKey = KeyHandle; 1333 1334 if (KeyHandle) 1335 { 1336 /* There are image specific options, read them starting with NXCOMPAT */ 1337 Status = LdrQueryImageFileKeyOption(KeyHandle, 1338 L"ExecuteOptions", 1339 4, 1340 &ExecuteOptions, 1341 sizeof(ExecuteOptions), 1342 0); 1343 1344 if (NT_SUCCESS(Status)) 1345 { 1346 /* TODO: Set execution options for the process */ 1347 /* 1348 if (ExecuteOptions == 0) 1349 ExecuteOptions = 1; 1350 else 1351 ExecuteOptions = 2; 1352 ZwSetInformationProcess(NtCurrentProcess(), 1353 ProcessExecuteFlags, 1354 &ExecuteOptions, 1355 sizeof(ULONG));*/ 1356 1357 } 1358 1359 /* Check if this image uses large pages */ 1360 if (Peb->ImageUsesLargePages) 1361 { 1362 /* TODO: If it does, open large page key */ 1363 UNIMPLEMENTED; 1364 } 1365 1366 /* Get various option values */ 1367 LdrQueryImageFileKeyOption(KeyHandle, 1368 L"DisableHeapLookaside", 1369 REG_DWORD, 1370 &RtlpDisableHeapLookaside, 1371 sizeof(RtlpDisableHeapLookaside), 1372 NULL); 1373 1374 LdrQueryImageFileKeyOption(KeyHandle, 1375 L"ShutdownFlags", 1376 REG_DWORD, 1377 &RtlpShutdownProcessFlags, 1378 sizeof(RtlpShutdownProcessFlags), 1379 NULL); 1380 1381 LdrQueryImageFileKeyOption(KeyHandle, 1382 L"MinimumStackCommitInBytes", 1383 REG_DWORD, 1384 &MinimumStackCommit, 1385 sizeof(MinimumStackCommit), 1386 NULL); 1387 1388 /* Update PEB's minimum stack commit if it's lower */ 1389 if (Peb->MinimumStackCommit < MinimumStackCommit) 1390 Peb->MinimumStackCommit = MinimumStackCommit; 1391 1392 /* Set the global flag */ 1393 Status = LdrQueryImageFileKeyOption(KeyHandle, 1394 L"GlobalFlag", 1395 REG_DWORD, 1396 &GlobalFlag, 1397 sizeof(GlobalFlag), 1398 NULL); 1399 1400 if (NT_SUCCESS(Status)) 1401 Peb->NtGlobalFlag = GlobalFlag; 1402 else 1403 GlobalFlag = 0; 1404 1405 /* Call AVRF if necessary */ 1406 if (Peb->NtGlobalFlag & (FLG_APPLICATION_VERIFIER | FLG_HEAP_PAGE_ALLOCS)) 1407 { 1408 Status = LdrpInitializeApplicationVerifierPackage(KeyHandle, Peb, TRUE, FALSE); 1409 if (!NT_SUCCESS(Status)) 1410 { 1411 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status); 1412 } 1413 } 1414 } 1415 else 1416 { 1417 /* There are no image-specific options, so perform global initialization */ 1418 if (Peb->NtGlobalFlag & (FLG_APPLICATION_VERIFIER | FLG_HEAP_PAGE_ALLOCS)) 1419 { 1420 /* Initialize app verifier package */ 1421 Status = LdrpInitializeApplicationVerifierPackage(KeyHandle, Peb, TRUE, FALSE); 1422 if (!NT_SUCCESS(Status)) 1423 { 1424 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status); 1425 } 1426 } 1427 } 1428 1429 return STATUS_SUCCESS; 1430 } 1431 1432 VOID 1433 NTAPI 1434 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry) 1435 { 1436 UNIMPLEMENTED; 1437 } 1438 1439 VOID 1440 NTAPI 1441 LdrpInitializeProcessCompat(PVOID* pOldShimData) 1442 { 1443 static const GUID* GuidOrder[] = { &COMPAT_GUID_WIN10, &COMPAT_GUID_WIN81, &COMPAT_GUID_WIN8, 1444 &COMPAT_GUID_WIN7, &COMPAT_GUID_VISTA }; 1445 static const DWORD GuidVersions[] = { WINVER_WIN10, WINVER_WIN81, WINVER_WIN8, WINVER_WIN7, WINVER_VISTA }; 1446 1447 ULONG Buffer[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION)) / sizeof(ULONG)]; 1448 ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION* ContextCompatInfo; 1449 SIZE_T SizeRequired; 1450 NTSTATUS Status; 1451 DWORD n, cur; 1452 ReactOS_ShimData* pShimData = *pOldShimData; 1453 1454 C_ASSERT(RTL_NUMBER_OF(GuidOrder) == RTL_NUMBER_OF(GuidVersions)); 1455 1456 if (pShimData) 1457 { 1458 if (pShimData->dwMagic != REACTOS_SHIMDATA_MAGIC || 1459 pShimData->dwSize != sizeof(ReactOS_ShimData)) 1460 { 1461 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData->dwMagic, pShimData->dwSize); 1462 return; 1463 } 1464 if (pShimData->dwRosProcessCompatVersion) 1465 { 1466 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData->dwRosProcessCompatVersion); 1467 return; 1468 } 1469 } 1470 1471 SizeRequired = sizeof(Buffer); 1472 Status = RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF, 1473 NULL, 1474 NULL, 1475 CompatibilityInformationInActivationContext, 1476 Buffer, 1477 sizeof(Buffer), 1478 &SizeRequired); 1479 1480 if (!NT_SUCCESS(Status)) 1481 { 1482 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status); 1483 return; 1484 } 1485 1486 ContextCompatInfo = (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*)Buffer; 1487 /* No Compatibility elements present, bail out */ 1488 if (ContextCompatInfo->ElementCount == 0) 1489 return; 1490 1491 /* Search for known GUID's, starting from newest to oldest. */ 1492 for (cur = 0; cur < RTL_NUMBER_OF(GuidOrder); ++cur) 1493 { 1494 for (n = 0; n < ContextCompatInfo->ElementCount; ++n) 1495 { 1496 if (ContextCompatInfo->Elements[n].Type == ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS && 1497 RtlCompareMemory(&ContextCompatInfo->Elements[n].Id, GuidOrder[cur], sizeof(GUID)) == sizeof(GUID)) 1498 { 1499 /* If this process did not need shim data before, allocate and store it */ 1500 if (pShimData == NULL) 1501 { 1502 PPEB Peb = NtCurrentPeb(); 1503 1504 ASSERT(Peb->pShimData == NULL); 1505 pShimData = RtlAllocateHeap(Peb->ProcessHeap, HEAP_ZERO_MEMORY, sizeof(*pShimData)); 1506 1507 if (!pShimData) 1508 { 1509 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData)); 1510 return; 1511 } 1512 1513 pShimData->dwSize = sizeof(*pShimData); 1514 pShimData->dwMagic = REACTOS_SHIMDATA_MAGIC; 1515 1516 Peb->pShimData = pShimData; 1517 *pOldShimData = pShimData; 1518 } 1519 1520 /* Store the highest found version, and bail out. */ 1521 pShimData->dwRosProcessCompatVersion = GuidVersions[cur]; 1522 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", GuidVersions[cur]); 1523 return; 1524 } 1525 } 1526 } 1527 } 1528 1529 1530 NTSTATUS 1531 NTAPI 1532 LdrpInitializeProcess(IN PCONTEXT Context, 1533 IN PVOID SystemArgument1) 1534 { 1535 RTL_HEAP_PARAMETERS HeapParameters; 1536 ULONG ComSectionSize; 1537 //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData"); 1538 PVOID OldShimData; 1539 OBJECT_ATTRIBUTES ObjectAttributes; 1540 //UNICODE_STRING LocalFileName, FullImageName; 1541 HANDLE SymLinkHandle; 1542 //ULONG DebugHeapOnly; 1543 UNICODE_STRING CommandLine, NtSystemRoot, ImagePathName, FullPath, ImageFileName, KnownDllString; 1544 PPEB Peb = NtCurrentPeb(); 1545 BOOLEAN IsDotNetImage = FALSE; 1546 BOOLEAN FreeCurDir = FALSE; 1547 //HANDLE CompatKey; 1548 PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 1549 //LPWSTR ImagePathBuffer; 1550 ULONG ConfigSize; 1551 UNICODE_STRING CurrentDirectory; 1552 HANDLE OptionsKey; 1553 ULONG HeapFlags; 1554 PIMAGE_NT_HEADERS NtHeader; 1555 LPWSTR NtDllName = NULL; 1556 NTSTATUS Status, ImportStatus; 1557 NLSTABLEINFO NlsTable; 1558 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig; 1559 PTEB Teb = NtCurrentTeb(); 1560 PLIST_ENTRY ListHead; 1561 PLIST_ENTRY NextEntry; 1562 ULONG i; 1563 PWSTR ImagePath; 1564 ULONG DebugProcessHeapOnly = 0; 1565 PLDR_DATA_TABLE_ENTRY NtLdrEntry; 1566 PWCHAR Current; 1567 ULONG ExecuteOptions = 0; 1568 PVOID ViewBase; 1569 1570 /* Set a NULL SEH Filter */ 1571 RtlSetUnhandledExceptionFilter(NULL); 1572 1573 /* Get the image path */ 1574 ImagePath = Peb->ProcessParameters->ImagePathName.Buffer; 1575 1576 /* Check if it's not normalized */ 1577 if (!(Peb->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED)) 1578 { 1579 /* Normalize it*/ 1580 ImagePath = (PWSTR)((ULONG_PTR)ImagePath + (ULONG_PTR)Peb->ProcessParameters); 1581 } 1582 1583 /* Create a unicode string for the Image Path */ 1584 ImagePathName.Length = Peb->ProcessParameters->ImagePathName.Length; 1585 ImagePathName.MaximumLength = ImagePathName.Length + sizeof(WCHAR); 1586 ImagePathName.Buffer = ImagePath; 1587 1588 /* Get the NT Headers */ 1589 NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress); 1590 1591 /* Get the execution options */ 1592 Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &OptionsKey); 1593 1594 /* Check if this is a .NET executable */ 1595 if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress, 1596 TRUE, 1597 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, 1598 &ComSectionSize)) 1599 { 1600 /* Remember this for later */ 1601 IsDotNetImage = TRUE; 1602 } 1603 1604 /* Save the NTDLL Base address */ 1605 NtDllBase = SystemArgument1; 1606 1607 /* If this is a Native Image */ 1608 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE) 1609 { 1610 /* Then do DLL Validation */ 1611 LdrpDllValidation = TRUE; 1612 } 1613 1614 /* Save the old Shim Data */ 1615 OldShimData = Peb->pShimData; 1616 1617 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */ 1618 //Peb->pShimData = NULL; 1619 1620 /* Save the number of processors and CS Timeout */ 1621 LdrpNumberOfProcessors = Peb->NumberOfProcessors; 1622 RtlpTimeout = Peb->CriticalSectionTimeout; 1623 1624 /* Normalize the parameters */ 1625 ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters); 1626 if (ProcessParameters) 1627 { 1628 /* Save the Image and Command Line Names */ 1629 ImageFileName = ProcessParameters->ImagePathName; 1630 CommandLine = ProcessParameters->CommandLine; 1631 } 1632 else 1633 { 1634 /* It failed, initialize empty strings */ 1635 RtlInitUnicodeString(&ImageFileName, NULL); 1636 RtlInitUnicodeString(&CommandLine, NULL); 1637 } 1638 1639 /* Initialize NLS data */ 1640 RtlInitNlsTables(Peb->AnsiCodePageData, 1641 Peb->OemCodePageData, 1642 Peb->UnicodeCaseTableData, 1643 &NlsTable); 1644 1645 /* Reset NLS Translations */ 1646 RtlResetRtlTranslations(&NlsTable); 1647 1648 /* Get the Image Config Directory */ 1649 LoadConfig = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress, 1650 TRUE, 1651 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, 1652 &ConfigSize); 1653 1654 /* Setup the Heap Parameters */ 1655 RtlZeroMemory(&HeapParameters, sizeof(RTL_HEAP_PARAMETERS)); 1656 HeapFlags = HEAP_GROWABLE; 1657 HeapParameters.Length = sizeof(RTL_HEAP_PARAMETERS); 1658 1659 /* Check if we have Configuration Data */ 1660 if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY))) 1661 { 1662 /* FIXME: Custom heap settings and misc. */ 1663 DPRINT1("We don't support LOAD_CONFIG data yet\n"); 1664 } 1665 1666 /* Check for custom affinity mask */ 1667 if (Peb->ImageProcessAffinityMask) 1668 { 1669 /* Set it */ 1670 Status = NtSetInformationProcess(NtCurrentProcess(), 1671 ProcessAffinityMask, 1672 &Peb->ImageProcessAffinityMask, 1673 sizeof(Peb->ImageProcessAffinityMask)); 1674 } 1675 1676 /* Check if verbose debugging (ShowSnaps) was requested */ 1677 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; 1678 1679 /* Start verbose debugging messages right now if they were requested */ 1680 if (ShowSnaps) 1681 { 1682 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n", 1683 Teb->ClientId.UniqueProcess, 1684 &CommandLine); 1685 } 1686 1687 /* If the timeout is too long */ 1688 if (RtlpTimeout.QuadPart < Int32x32To64(3600, -10000000)) 1689 { 1690 /* Then disable CS Timeout */ 1691 RtlpTimeoutDisable = TRUE; 1692 } 1693 1694 /* Initialize Critical Section Data */ 1695 RtlpInitDeferedCriticalSection(); 1696 1697 /* Initialize VEH Call lists */ 1698 RtlpInitializeVectoredExceptionHandling(); 1699 1700 /* Set TLS/FLS Bitmap data */ 1701 Peb->FlsBitmap = &FlsBitMap; 1702 Peb->TlsBitmap = &TlsBitMap; 1703 Peb->TlsExpansionBitmap = &TlsExpansionBitMap; 1704 1705 /* Initialize FLS Bitmap */ 1706 RtlInitializeBitMap(&FlsBitMap, 1707 Peb->FlsBitmapBits, 1708 FLS_MAXIMUM_AVAILABLE); 1709 RtlSetBit(&FlsBitMap, 0); 1710 1711 /* Initialize TLS Bitmap */ 1712 RtlInitializeBitMap(&TlsBitMap, 1713 Peb->TlsBitmapBits, 1714 TLS_MINIMUM_AVAILABLE); 1715 RtlSetBit(&TlsBitMap, 0); 1716 RtlInitializeBitMap(&TlsExpansionBitMap, 1717 Peb->TlsExpansionBitmapBits, 1718 TLS_EXPANSION_SLOTS); 1719 RtlSetBit(&TlsExpansionBitMap, 0); 1720 1721 /* Initialize the Hash Table */ 1722 for (i = 0; i < LDR_HASH_TABLE_ENTRIES; i++) 1723 { 1724 InitializeListHead(&LdrpHashTable[i]); 1725 } 1726 1727 /* Initialize the Loader Lock */ 1728 // FIXME: What's the point of initing it manually, if two lines lower 1729 // a call to RtlInitializeCriticalSection() is being made anyway? 1730 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList); 1731 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock; 1732 RtlInitializeCriticalSection(&LdrpLoaderLock); 1733 LdrpLoaderLockInit = TRUE; 1734 1735 /* Check if User Stack Trace Database support was requested */ 1736 if (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB) 1737 { 1738 DPRINT1("We don't support user stack trace databases yet\n"); 1739 } 1740 1741 /* Setup Fast PEB Lock */ 1742 RtlInitializeCriticalSection(&FastPebLock); 1743 Peb->FastPebLock = &FastPebLock; 1744 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection; 1745 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection; 1746 1747 /* Setup Callout Lock and Notification list */ 1748 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock); 1749 InitializeListHead(&LdrpDllNotificationList); 1750 1751 /* For old executables, use 16-byte aligned heap */ 1752 if ((NtHeader->OptionalHeader.MajorSubsystemVersion <= 3) && 1753 (NtHeader->OptionalHeader.MinorSubsystemVersion < 51)) 1754 { 1755 HeapFlags |= HEAP_CREATE_ALIGN_16; 1756 } 1757 1758 /* Setup the Heap */ 1759 RtlInitializeHeapManager(); 1760 Peb->ProcessHeap = RtlCreateHeap(HeapFlags, 1761 NULL, 1762 NtHeader->OptionalHeader.SizeOfHeapReserve, 1763 NtHeader->OptionalHeader.SizeOfHeapCommit, 1764 NULL, 1765 &HeapParameters); 1766 1767 if (!Peb->ProcessHeap) 1768 { 1769 DPRINT1("Failed to create process heap\n"); 1770 return STATUS_NO_MEMORY; 1771 } 1772 1773 /* Allocate an Activation Context Stack */ 1774 Status = RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer); 1775 if (!NT_SUCCESS(Status)) return Status; 1776 1777 // FIXME: Loader private heap is missing 1778 //DPRINT1("Loader private heap is missing\n"); 1779 1780 /* Check for Debug Heap */ 1781 if (OptionsKey) 1782 { 1783 /* Query the setting */ 1784 Status = LdrQueryImageFileKeyOption(OptionsKey, 1785 L"DebugProcessHeapOnly", 1786 REG_DWORD, 1787 &DebugProcessHeapOnly, 1788 sizeof(ULONG), 1789 NULL); 1790 1791 if (NT_SUCCESS(Status)) 1792 { 1793 /* Reset DPH if requested */ 1794 if (RtlpPageHeapEnabled && DebugProcessHeapOnly) 1795 { 1796 RtlpDphGlobalFlags &= ~DPH_FLAG_DLL_NOTIFY; 1797 RtlpPageHeapEnabled = FALSE; 1798 } 1799 } 1800 } 1801 1802 /* Build the NTDLL Path */ 1803 FullPath.Buffer = StringBuffer; 1804 FullPath.Length = 0; 1805 FullPath.MaximumLength = sizeof(StringBuffer); 1806 RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot); 1807 RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot); 1808 RtlAppendUnicodeToString(&FullPath, L"\\System32\\"); 1809 1810 /* Open the Known DLLs directory */ 1811 RtlInitUnicodeString(&KnownDllString, L"\\KnownDlls"); 1812 InitializeObjectAttributes(&ObjectAttributes, 1813 &KnownDllString, 1814 OBJ_CASE_INSENSITIVE, 1815 NULL, 1816 NULL); 1817 Status = ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory, 1818 DIRECTORY_QUERY | DIRECTORY_TRAVERSE, 1819 &ObjectAttributes); 1820 1821 /* Check if it exists */ 1822 if (NT_SUCCESS(Status)) 1823 { 1824 /* Open the Known DLLs Path */ 1825 RtlInitUnicodeString(&KnownDllString, L"KnownDllPath"); 1826 InitializeObjectAttributes(&ObjectAttributes, 1827 &KnownDllString, 1828 OBJ_CASE_INSENSITIVE, 1829 LdrpKnownDllObjectDirectory, 1830 NULL); 1831 Status = NtOpenSymbolicLinkObject(&SymLinkHandle, 1832 SYMBOLIC_LINK_QUERY, 1833 &ObjectAttributes); 1834 if (NT_SUCCESS(Status)) 1835 { 1836 /* Query the path */ 1837 LdrpKnownDllPath.Length = 0; 1838 LdrpKnownDllPath.MaximumLength = sizeof(LdrpKnownDllPathBuffer); 1839 LdrpKnownDllPath.Buffer = LdrpKnownDllPathBuffer; 1840 Status = ZwQuerySymbolicLinkObject(SymLinkHandle, &LdrpKnownDllPath, NULL); 1841 NtClose(SymLinkHandle); 1842 if (!NT_SUCCESS(Status)) 1843 { 1844 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status); 1845 return Status; 1846 } 1847 } 1848 } 1849 1850 /* Check if we failed */ 1851 if (!NT_SUCCESS(Status)) 1852 { 1853 /* Assume System32 */ 1854 LdrpKnownDllObjectDirectory = NULL; 1855 RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer); 1856 LdrpKnownDllPath.Length -= sizeof(WCHAR); 1857 } 1858 1859 /* If we have process parameters, get the default path and current path */ 1860 if (ProcessParameters) 1861 { 1862 /* Check if we have a Dll Path */ 1863 if (ProcessParameters->DllPath.Length) 1864 { 1865 /* Get the path */ 1866 LdrpDefaultPath = *(PUNICODE_STRING)&ProcessParameters->DllPath; 1867 } 1868 else 1869 { 1870 /* We need a valid path */ 1871 DPRINT1("No valid DllPath was given!\n"); 1872 LdrpInitFailure(STATUS_INVALID_PARAMETER); 1873 } 1874 1875 /* Set the current directory */ 1876 CurrentDirectory = ProcessParameters->CurrentDirectory.DosPath; 1877 1878 /* Check if it's empty or invalid */ 1879 if ((!CurrentDirectory.Buffer) || 1880 (CurrentDirectory.Buffer[0] == UNICODE_NULL) || 1881 (!CurrentDirectory.Length)) 1882 { 1883 /* Allocate space for the buffer */ 1884 CurrentDirectory.Buffer = RtlAllocateHeap(Peb->ProcessHeap, 1885 0, 1886 3 * sizeof(WCHAR) + 1887 sizeof(UNICODE_NULL)); 1888 if (!CurrentDirectory.Buffer) 1889 { 1890 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n"); 1891 // FIXME: And what? 1892 } 1893 1894 /* Copy the drive of the system root */ 1895 RtlMoveMemory(CurrentDirectory.Buffer, 1896 SharedUserData->NtSystemRoot, 1897 3 * sizeof(WCHAR)); 1898 CurrentDirectory.Buffer[3] = UNICODE_NULL; 1899 CurrentDirectory.Length = 3 * sizeof(WCHAR); 1900 CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR); 1901 1902 FreeCurDir = TRUE; 1903 DPRINT("Using dynamically allocd curdir\n"); 1904 } 1905 else 1906 { 1907 /* Use the local buffer */ 1908 DPRINT("Using local system root\n"); 1909 } 1910 } 1911 1912 /* Setup Loader Data */ 1913 Peb->Ldr = &PebLdr; 1914 InitializeListHead(&PebLdr.InLoadOrderModuleList); 1915 InitializeListHead(&PebLdr.InMemoryOrderModuleList); 1916 InitializeListHead(&PebLdr.InInitializationOrderModuleList); 1917 PebLdr.Length = sizeof(PEB_LDR_DATA); 1918 PebLdr.Initialized = TRUE; 1919 1920 /* Allocate a data entry for the Image */ 1921 LdrpImageEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress); 1922 1923 /* Set it up */ 1924 LdrpImageEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrpImageEntry->DllBase); 1925 LdrpImageEntry->LoadCount = -1; 1926 LdrpImageEntry->EntryPointActivationContext = 0; 1927 LdrpImageEntry->FullDllName = ImageFileName; 1928 1929 if (IsDotNetImage) 1930 LdrpImageEntry->Flags = LDRP_COR_IMAGE; 1931 else 1932 LdrpImageEntry->Flags = 0; 1933 1934 /* Check if the name is empty */ 1935 if (!ImageFileName.Buffer[0]) 1936 { 1937 /* Use the same Base name */ 1938 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName; 1939 } 1940 else 1941 { 1942 /* Find the last slash */ 1943 Current = ImageFileName.Buffer; 1944 while (*Current) 1945 { 1946 if (*Current++ == '\\') 1947 { 1948 /* Set this path */ 1949 NtDllName = Current; 1950 } 1951 } 1952 1953 /* Did we find anything? */ 1954 if (!NtDllName) 1955 { 1956 /* Use the same Base name */ 1957 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName; 1958 } 1959 else 1960 { 1961 /* Setup the name */ 1962 LdrpImageEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName); 1963 LdrpImageEntry->BaseDllName.MaximumLength = LdrpImageEntry->BaseDllName.Length + sizeof(WCHAR); 1964 LdrpImageEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer + 1965 (ImageFileName.Length - LdrpImageEntry->BaseDllName.Length)); 1966 } 1967 } 1968 1969 /* Processing done, insert it */ 1970 LdrpInsertMemoryTableEntry(LdrpImageEntry); 1971 LdrpImageEntry->Flags |= LDRP_ENTRY_PROCESSED; 1972 1973 /* Now add an entry for NTDLL */ 1974 NtLdrEntry = LdrpAllocateDataTableEntry(SystemArgument1); 1975 NtLdrEntry->Flags = LDRP_IMAGE_DLL; 1976 NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase); 1977 NtLdrEntry->LoadCount = -1; 1978 NtLdrEntry->EntryPointActivationContext = 0; 1979 1980 NtLdrEntry->FullDllName.Length = FullPath.Length; 1981 NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength; 1982 NtLdrEntry->FullDllName.Buffer = StringBuffer; 1983 RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &NtDllString); 1984 1985 NtLdrEntry->BaseDllName.Length = NtDllString.Length; 1986 NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength; 1987 NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer; 1988 1989 /* Processing done, insert it */ 1990 LdrpNtDllDataTableEntry = NtLdrEntry; 1991 LdrpInsertMemoryTableEntry(NtLdrEntry); 1992 1993 /* Let the world know */ 1994 if (ShowSnaps) 1995 { 1996 DPRINT1("LDR: NEW PROCESS\n"); 1997 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry->FullDllName, &LdrpImageEntry->BaseDllName); 1998 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory); 1999 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath); 2000 } 2001 2002 /* Link the Init Order List */ 2003 InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList, 2004 &LdrpNtDllDataTableEntry->InInitializationOrderLinks); 2005 2006 /* Initialize Wine's active context implementation for the current process */ 2007 actctx_init(); 2008 2009 /* ReactOS specific */ 2010 LdrpInitializeProcessCompat(&OldShimData); 2011 2012 /* Set the current directory */ 2013 Status = RtlSetCurrentDirectory_U(&CurrentDirectory); 2014 if (!NT_SUCCESS(Status)) 2015 { 2016 /* We failed, check if we should free it */ 2017 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory); 2018 2019 /* Set it to the NT Root */ 2020 CurrentDirectory = NtSystemRoot; 2021 RtlSetCurrentDirectory_U(&CurrentDirectory); 2022 } 2023 else 2024 { 2025 /* We're done with it, free it */ 2026 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory); 2027 } 2028 2029 /* Check if we should look for a .local file */ 2030 if (ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH) 2031 { 2032 /* FIXME */ 2033 DPRINT1("We don't support .local overrides yet\n"); 2034 } 2035 2036 /* Check if the Application Verifier was enabled */ 2037 if (Peb->NtGlobalFlag & FLG_APPLICATION_VERIFIER) 2038 { 2039 Status = AVrfInitializeVerifier(); 2040 if (!NT_SUCCESS(Status)) 2041 { 2042 DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status); 2043 return Status; 2044 } 2045 2046 } 2047 2048 if (IsDotNetImage) 2049 { 2050 /* FIXME */ 2051 DPRINT1("We don't support .NET applications yet\n"); 2052 } 2053 2054 /* FIXME: Load support for Terminal Services */ 2055 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) 2056 { 2057 /* Load kernel32 and call BasePostImportInit... */ 2058 DPRINT("Unimplemented codepath!\n"); 2059 } 2060 2061 /* Walk the IAT and load all the DLLs */ 2062 ImportStatus = LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry); 2063 2064 /* Check if relocation is needed */ 2065 if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase) 2066 { 2067 DPRINT1("LDR: Performing EXE relocation\n"); 2068 2069 /* Change the protection to prepare for relocation */ 2070 ViewBase = Peb->ImageBaseAddress; 2071 Status = LdrpSetProtection(ViewBase, FALSE); 2072 if (!NT_SUCCESS(Status)) return Status; 2073 2074 /* Do the relocation */ 2075 Status = LdrRelocateImageWithBias(ViewBase, 2076 0LL, 2077 NULL, 2078 STATUS_SUCCESS, 2079 STATUS_CONFLICTING_ADDRESSES, 2080 STATUS_INVALID_IMAGE_FORMAT); 2081 if (!NT_SUCCESS(Status)) 2082 { 2083 DPRINT1("LdrRelocateImageWithBias() failed\n"); 2084 return Status; 2085 } 2086 2087 /* Check if a start context was provided */ 2088 if (Context) 2089 { 2090 DPRINT1("WARNING: Relocated EXE Context"); 2091 UNIMPLEMENTED; // We should support this 2092 return STATUS_INVALID_IMAGE_FORMAT; 2093 } 2094 2095 /* Restore the protection */ 2096 Status = LdrpSetProtection(ViewBase, TRUE); 2097 if (!NT_SUCCESS(Status)) return Status; 2098 } 2099 2100 /* Lock the DLLs */ 2101 ListHead = &Peb->Ldr->InLoadOrderModuleList; 2102 NextEntry = ListHead->Flink; 2103 while (ListHead != NextEntry) 2104 { 2105 NtLdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 2106 NtLdrEntry->LoadCount = -1; 2107 NextEntry = NextEntry->Flink; 2108 } 2109 2110 /* Phase 0 is done */ 2111 LdrpLdrDatabaseIsSetup = TRUE; 2112 2113 /* Check whether all static imports were properly loaded and return here */ 2114 if (!NT_SUCCESS(ImportStatus)) return ImportStatus; 2115 2116 /* Initialize TLS */ 2117 Status = LdrpInitializeTls(); 2118 if (!NT_SUCCESS(Status)) 2119 { 2120 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n", 2121 Status); 2122 return Status; 2123 } 2124 2125 /* FIXME Mark the DLL Ranges for Stack Traces later */ 2126 2127 /* Notify the debugger now */ 2128 if (Peb->BeingDebugged) 2129 { 2130 /* Break */ 2131 DbgBreakPoint(); 2132 2133 /* Update show snaps again */ 2134 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; 2135 } 2136 2137 /* Validate the Image for MP Usage */ 2138 if (LdrpNumberOfProcessors > 1) LdrpValidateImageForMp(LdrpImageEntry); 2139 2140 /* Check NX Options */ 2141 if (SharedUserData->NXSupportPolicy == 1) 2142 { 2143 ExecuteOptions = 0xD; 2144 } 2145 else if (!SharedUserData->NXSupportPolicy) 2146 { 2147 ExecuteOptions = 0xA; 2148 } 2149 2150 /* Let Mm know */ 2151 ZwSetInformationProcess(NtCurrentProcess(), 2152 ProcessExecuteFlags, 2153 &ExecuteOptions, 2154 sizeof(ULONG)); 2155 2156 // FIXME: Should be done by Application Compatibility features, 2157 // by reading the registry, etc... 2158 // For now, this is the old code from ntdll!RtlGetVersion(). 2159 RtlInitEmptyUnicodeString(&Peb->CSDVersion, NULL, 0); 2160 if (((Peb->OSCSDVersion >> 8) & 0xFF) != 0) 2161 { 2162 WCHAR szCSDVersion[128]; 2163 LONG i; 2164 ULONG Length = ARRAYSIZE(szCSDVersion) - 1; 2165 i = _snwprintf(szCSDVersion, Length, 2166 L"Service Pack %d", 2167 ((Peb->OSCSDVersion >> 8) & 0xFF)); 2168 if (i < 0) 2169 { 2170 /* Null-terminate if it was overflowed */ 2171 szCSDVersion[Length] = UNICODE_NULL; 2172 } 2173 2174 Length *= sizeof(WCHAR); 2175 Peb->CSDVersion.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 2176 0, 2177 Length + sizeof(UNICODE_NULL)); 2178 if (Peb->CSDVersion.Buffer) 2179 { 2180 Peb->CSDVersion.Length = Length; 2181 Peb->CSDVersion.MaximumLength = Length + sizeof(UNICODE_NULL); 2182 2183 RtlCopyMemory(Peb->CSDVersion.Buffer, 2184 szCSDVersion, 2185 Peb->CSDVersion.MaximumLength); 2186 Peb->CSDVersion.Buffer[Peb->CSDVersion.Length / sizeof(WCHAR)] = UNICODE_NULL; 2187 } 2188 } 2189 2190 /* Check if we had Shim Data */ 2191 if (OldShimData) 2192 { 2193 /* Load the Shim Engine */ 2194 Peb->AppCompatInfo = NULL; 2195 LdrpLoadShimEngine(OldShimData, &ImagePathName, OldShimData); 2196 } 2197 else 2198 { 2199 /* Check for Application Compatibility Goo */ 2200 //LdrQueryApplicationCompatibilityGoo(hKey); 2201 DPRINT("Querying app compat hacks is missing!\n"); 2202 } 2203 2204 /* 2205 * FIXME: Check for special images, SecuROM, SafeDisc and other NX- 2206 * incompatible images. 2207 */ 2208 2209 /* Now call the Init Routines */ 2210 Status = LdrpRunInitializeRoutines(Context); 2211 if (!NT_SUCCESS(Status)) 2212 { 2213 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n", 2214 Status); 2215 return Status; 2216 } 2217 2218 /* Notify Shim Engine */ 2219 if (g_ShimsEnabled) 2220 { 2221 VOID(NTAPI *SE_InstallAfterInit)(PUNICODE_STRING, PVOID); 2222 SE_InstallAfterInit = RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit); 2223 SE_InstallAfterInit(&ImagePathName, OldShimData); 2224 } 2225 2226 /* Check if we have a user-defined Post Process Routine */ 2227 if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine) 2228 { 2229 /* Call it */ 2230 Peb->PostProcessInitRoutine(); 2231 } 2232 2233 /* Close the key if we have one opened */ 2234 if (OptionsKey) NtClose(OptionsKey); 2235 2236 /* Return status */ 2237 return Status; 2238 } 2239 2240 VOID 2241 NTAPI 2242 LdrpInitFailure(NTSTATUS Status) 2243 { 2244 ULONG Response; 2245 PPEB Peb = NtCurrentPeb(); 2246 2247 /* Print a debug message */ 2248 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n", 2249 &Peb->ProcessParameters->ImagePathName, Status); 2250 2251 /* Raise a hard error */ 2252 if (!LdrpFatalHardErrorCount) 2253 { 2254 ZwRaiseHardError(STATUS_APP_INIT_FAILURE, 1, 0, (PULONG_PTR)&Status, OptionOk, &Response); 2255 } 2256 } 2257 2258 VOID 2259 NTAPI 2260 LdrpInit(PCONTEXT Context, 2261 PVOID SystemArgument1, 2262 PVOID SystemArgument2) 2263 { 2264 LARGE_INTEGER Timeout; 2265 PTEB Teb = NtCurrentTeb(); 2266 NTSTATUS Status, LoaderStatus = STATUS_SUCCESS; 2267 MEMORY_BASIC_INFORMATION MemoryBasicInfo; 2268 PPEB Peb = NtCurrentPeb(); 2269 2270 DPRINT("LdrpInit() %p/%p\n", 2271 NtCurrentTeb()->RealClientId.UniqueProcess, 2272 NtCurrentTeb()->RealClientId.UniqueThread); 2273 2274 #ifdef _WIN64 2275 /* Set the SList header usage */ 2276 RtlpUse16ByteSLists = SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE128]; 2277 #endif /* _WIN64 */ 2278 2279 /* Check if we have a deallocation stack */ 2280 if (!Teb->DeallocationStack) 2281 { 2282 /* We don't, set one */ 2283 Status = NtQueryVirtualMemory(NtCurrentProcess(), 2284 Teb->NtTib.StackLimit, 2285 MemoryBasicInformation, 2286 &MemoryBasicInfo, 2287 sizeof(MEMORY_BASIC_INFORMATION), 2288 NULL); 2289 if (!NT_SUCCESS(Status)) 2290 { 2291 /* Fail */ 2292 LdrpInitFailure(Status); 2293 RtlRaiseStatus(Status); 2294 return; 2295 } 2296 2297 /* Set the stack */ 2298 Teb->DeallocationStack = MemoryBasicInfo.AllocationBase; 2299 } 2300 2301 /* Now check if the process is already being initialized */ 2302 while (_InterlockedCompareExchange(&LdrpProcessInitialized, 2303 1, 2304 0) == 1) 2305 { 2306 /* Set the timeout to 30 milliseconds */ 2307 Timeout.QuadPart = Int32x32To64(30, -10000); 2308 2309 /* Make sure the status hasn't changed */ 2310 while (LdrpProcessInitialized == 1) 2311 { 2312 /* Do the wait */ 2313 ZwDelayExecution(FALSE, &Timeout); 2314 } 2315 } 2316 2317 /* Check if we have already setup LDR data */ 2318 if (!Peb->Ldr) 2319 { 2320 /* Setup the Loader Lock */ 2321 Peb->LoaderLock = &LdrpLoaderLock; 2322 2323 /* Let other code know we're initializing */ 2324 LdrpInLdrInit = TRUE; 2325 2326 /* Protect with SEH */ 2327 _SEH2_TRY 2328 { 2329 /* Initialize the Process */ 2330 LoaderStatus = LdrpInitializeProcess(Context, 2331 SystemArgument1); 2332 2333 /* Check for success and if MinimumStackCommit was requested */ 2334 if (NT_SUCCESS(LoaderStatus) && Peb->MinimumStackCommit) 2335 { 2336 /* Enforce the limit */ 2337 //LdrpTouchThreadStack(Peb->MinimumStackCommit); 2338 UNIMPLEMENTED; 2339 } 2340 } 2341 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2342 { 2343 /* Fail with the SEH error */ 2344 LoaderStatus = _SEH2_GetExceptionCode(); 2345 } 2346 _SEH2_END; 2347 2348 /* We're not initializing anymore */ 2349 LdrpInLdrInit = FALSE; 2350 2351 /* Check if init worked */ 2352 if (NT_SUCCESS(LoaderStatus)) 2353 { 2354 /* Set the process as Initialized */ 2355 _InterlockedIncrement(&LdrpProcessInitialized); 2356 } 2357 } 2358 else 2359 { 2360 /* Loader data is there... is this a fork() ? */ 2361 if(Peb->InheritedAddressSpace) 2362 { 2363 /* Handle the fork() */ 2364 //LoaderStatus = LdrpForkProcess(); 2365 LoaderStatus = STATUS_NOT_IMPLEMENTED; 2366 UNIMPLEMENTED; 2367 } 2368 else 2369 { 2370 /* This is a new thread initializing */ 2371 LdrpInitializeThread(Context); 2372 } 2373 } 2374 2375 /* All done, test alert the thread */ 2376 NtTestAlert(); 2377 2378 /* Return */ 2379 if (!NT_SUCCESS(LoaderStatus)) 2380 { 2381 /* Fail */ 2382 LdrpInitFailure(LoaderStatus); 2383 RtlRaiseStatus(LoaderStatus); 2384 } 2385 } 2386 2387 /* EOF */ 2388