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