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 extern 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 RtlpInitDeferredCriticalSection(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 /* Convert the default CS timeout from milliseconds to 100ns units */ 1898 if (VALID_CONFIG_FIELD(CriticalSectionDefaultTimeout) && LoadConfig->CriticalSectionDefaultTimeout) 1899 RtlpTimeout.QuadPart = Int32x32To64(LoadConfig->CriticalSectionDefaultTimeout, -10000); 1900 1901 if (VALID_CONFIG_FIELD(DeCommitFreeBlockThreshold) && LoadConfig->DeCommitFreeBlockThreshold) 1902 HeapParameters.DeCommitFreeBlockThreshold = LoadConfig->DeCommitFreeBlockThreshold; 1903 1904 if (VALID_CONFIG_FIELD(DeCommitTotalFreeThreshold) && LoadConfig->DeCommitTotalFreeThreshold) 1905 HeapParameters.DeCommitTotalFreeThreshold = LoadConfig->DeCommitTotalFreeThreshold; 1906 1907 if (VALID_CONFIG_FIELD(MaximumAllocationSize) && LoadConfig->MaximumAllocationSize) 1908 HeapParameters.MaximumAllocationSize = LoadConfig->MaximumAllocationSize; 1909 1910 if (VALID_CONFIG_FIELD(VirtualMemoryThreshold) && LoadConfig->VirtualMemoryThreshold) 1911 HeapParameters.VirtualMemoryThreshold = LoadConfig->VirtualMemoryThreshold; 1912 1913 if (VALID_CONFIG_FIELD(ProcessHeapFlags) && LoadConfig->ProcessHeapFlags) 1914 HeapFlags = LoadConfig->ProcessHeapFlags; 1915 } 1916 #undef VALID_CONFIG_FIELD 1917 1918 /* Check for custom affinity mask */ 1919 if (Peb->ImageProcessAffinityMask) 1920 { 1921 /* Set it */ 1922 Status = NtSetInformationProcess(NtCurrentProcess(), 1923 ProcessAffinityMask, 1924 &Peb->ImageProcessAffinityMask, 1925 sizeof(Peb->ImageProcessAffinityMask)); 1926 } 1927 1928 /* Check if verbose debugging (ShowSnaps) was requested */ 1929 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; 1930 1931 /* Start verbose debugging messages right now if they were requested */ 1932 if (ShowSnaps) 1933 { 1934 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n", 1935 Teb->ClientId.UniqueProcess, 1936 &CommandLine); 1937 } 1938 1939 /* If the CS timeout is longer than 1 hour, disable it */ 1940 if (RtlpTimeout.QuadPart < Int32x32To64(3600, -10000000)) 1941 RtlpTimeoutDisable = TRUE; 1942 1943 /* Initialize Critical Section Data */ 1944 RtlpInitDeferredCriticalSection(); 1945 1946 /* Initialize VEH Call lists */ 1947 RtlpInitializeVectoredExceptionHandling(); 1948 1949 /* Set TLS/FLS Bitmap data */ 1950 Peb->FlsBitmap = &FlsBitMap; 1951 Peb->TlsBitmap = &TlsBitMap; 1952 Peb->TlsExpansionBitmap = &TlsExpansionBitMap; 1953 1954 /* Initialize FLS Bitmap */ 1955 RtlInitializeBitMap(&FlsBitMap, 1956 Peb->FlsBitmapBits, 1957 FLS_MAXIMUM_AVAILABLE); 1958 RtlSetBit(&FlsBitMap, 0); 1959 InitializeListHead(&Peb->FlsListHead); 1960 1961 /* Initialize TLS Bitmap */ 1962 RtlInitializeBitMap(&TlsBitMap, 1963 Peb->TlsBitmapBits, 1964 TLS_MINIMUM_AVAILABLE); 1965 RtlSetBit(&TlsBitMap, 0); 1966 RtlInitializeBitMap(&TlsExpansionBitMap, 1967 Peb->TlsExpansionBitmapBits, 1968 TLS_EXPANSION_SLOTS); 1969 RtlSetBit(&TlsExpansionBitMap, 0); 1970 1971 /* Initialize the Hash Table */ 1972 for (i = 0; i < LDR_HASH_TABLE_ENTRIES; i++) 1973 { 1974 InitializeListHead(&LdrpHashTable[i]); 1975 } 1976 1977 /* Initialize the Loader Lock */ 1978 // FIXME: What's the point of initing it manually, if two lines lower 1979 // a call to RtlInitializeCriticalSection() is being made anyway? 1980 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList); 1981 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock; 1982 RtlInitializeCriticalSection(&LdrpLoaderLock); 1983 LdrpLoaderLockInit = TRUE; 1984 1985 /* Check if User Stack Trace Database support was requested */ 1986 if (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB) 1987 { 1988 DPRINT1("We don't support user stack trace databases yet\n"); 1989 } 1990 1991 /* Setup Fast PEB Lock */ 1992 RtlInitializeCriticalSection(&FastPebLock); 1993 Peb->FastPebLock = &FastPebLock; 1994 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection; 1995 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection; 1996 1997 /* Setup Callout Lock and Notification list */ 1998 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock); 1999 InitializeListHead(&LdrpDllNotificationList); 2000 2001 /* For old executables, use 16-byte aligned heap */ 2002 if ((NtHeader->OptionalHeader.MajorSubsystemVersion <= 3) && 2003 (NtHeader->OptionalHeader.MinorSubsystemVersion < 51)) 2004 { 2005 HeapFlags |= HEAP_CREATE_ALIGN_16; 2006 } 2007 2008 /* Setup the Heap */ 2009 RtlInitializeHeapManager(); 2010 Peb->ProcessHeap = RtlCreateHeap(HeapFlags, 2011 NULL, 2012 NtHeader->OptionalHeader.SizeOfHeapReserve, 2013 NtHeader->OptionalHeader.SizeOfHeapCommit, 2014 NULL, 2015 &HeapParameters); 2016 2017 if (!Peb->ProcessHeap) 2018 { 2019 DPRINT1("Failed to create process heap\n"); 2020 return STATUS_NO_MEMORY; 2021 } 2022 2023 /* Allocate an Activation Context Stack */ 2024 Status = RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer); 2025 if (!NT_SUCCESS(Status)) return Status; 2026 2027 RtlZeroMemory(&HeapParameters, sizeof(HeapParameters)); 2028 HeapFlags = HEAP_GROWABLE | HEAP_CLASS_1; 2029 HeapParameters.Length = sizeof(HeapParameters); 2030 LdrpHeap = RtlCreateHeap(HeapFlags, 0, 0x10000, 0x6000, 0, &HeapParameters); 2031 if (!LdrpHeap) 2032 { 2033 DPRINT1("Failed to create loader private heap\n"); 2034 return STATUS_NO_MEMORY; 2035 } 2036 2037 /* Check for Debug Heap */ 2038 if (OptionsKey) 2039 { 2040 /* Query the setting */ 2041 Status = LdrQueryImageFileKeyOption(OptionsKey, 2042 L"DebugProcessHeapOnly", 2043 REG_DWORD, 2044 &DebugProcessHeapOnly, 2045 sizeof(ULONG), 2046 NULL); 2047 2048 if (NT_SUCCESS(Status)) 2049 { 2050 /* Reset DPH if requested */ 2051 if (RtlpPageHeapEnabled && DebugProcessHeapOnly) 2052 { 2053 RtlpDphGlobalFlags &= ~DPH_FLAG_DLL_NOTIFY; 2054 RtlpPageHeapEnabled = FALSE; 2055 } 2056 } 2057 } 2058 2059 /* Build the NTDLL Path */ 2060 FullPath.Buffer = StringBuffer; 2061 FullPath.Length = 0; 2062 FullPath.MaximumLength = sizeof(StringBuffer); 2063 RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot); 2064 RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot); 2065 RtlAppendUnicodeToString(&FullPath, L"\\System32\\"); 2066 2067 /* Open the Known DLLs directory */ 2068 RtlInitUnicodeString(&KnownDllString, L"\\KnownDlls"); 2069 InitializeObjectAttributes(&ObjectAttributes, 2070 &KnownDllString, 2071 OBJ_CASE_INSENSITIVE, 2072 NULL, 2073 NULL); 2074 Status = ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory, 2075 DIRECTORY_QUERY | DIRECTORY_TRAVERSE, 2076 &ObjectAttributes); 2077 2078 /* Check if it exists */ 2079 if (NT_SUCCESS(Status)) 2080 { 2081 /* Open the Known DLLs Path */ 2082 RtlInitUnicodeString(&KnownDllString, L"KnownDllPath"); 2083 InitializeObjectAttributes(&ObjectAttributes, 2084 &KnownDllString, 2085 OBJ_CASE_INSENSITIVE, 2086 LdrpKnownDllObjectDirectory, 2087 NULL); 2088 Status = NtOpenSymbolicLinkObject(&SymLinkHandle, 2089 SYMBOLIC_LINK_QUERY, 2090 &ObjectAttributes); 2091 if (NT_SUCCESS(Status)) 2092 { 2093 /* Query the path */ 2094 LdrpKnownDllPath.Length = 0; 2095 LdrpKnownDllPath.MaximumLength = sizeof(LdrpKnownDllPathBuffer); 2096 LdrpKnownDllPath.Buffer = LdrpKnownDllPathBuffer; 2097 Status = ZwQuerySymbolicLinkObject(SymLinkHandle, &LdrpKnownDllPath, NULL); 2098 NtClose(SymLinkHandle); 2099 if (!NT_SUCCESS(Status)) 2100 { 2101 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status); 2102 return Status; 2103 } 2104 } 2105 } 2106 2107 /* Check if we failed */ 2108 if (!NT_SUCCESS(Status)) 2109 { 2110 /* Assume System32 */ 2111 LdrpKnownDllObjectDirectory = NULL; 2112 RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer); 2113 LdrpKnownDllPath.Length -= sizeof(WCHAR); 2114 } 2115 2116 /* If we have process parameters, get the default path and current path */ 2117 if (ProcessParameters) 2118 { 2119 /* Check if we have a Dll Path */ 2120 if (ProcessParameters->DllPath.Length) 2121 { 2122 /* Get the path */ 2123 LdrpDefaultPath = *(PUNICODE_STRING)&ProcessParameters->DllPath; 2124 } 2125 else 2126 { 2127 /* We need a valid path */ 2128 DPRINT1("No valid DllPath was given!\n"); 2129 LdrpInitFailure(STATUS_INVALID_PARAMETER); 2130 } 2131 2132 /* Set the current directory */ 2133 CurrentDirectory = ProcessParameters->CurrentDirectory.DosPath; 2134 2135 /* Check if it's empty or invalid */ 2136 if ((!CurrentDirectory.Buffer) || 2137 (CurrentDirectory.Buffer[0] == UNICODE_NULL) || 2138 (!CurrentDirectory.Length)) 2139 { 2140 /* Allocate space for the buffer */ 2141 CurrentDirectory.Buffer = RtlAllocateHeap(Peb->ProcessHeap, 2142 0, 2143 3 * sizeof(WCHAR) + 2144 sizeof(UNICODE_NULL)); 2145 if (!CurrentDirectory.Buffer) 2146 { 2147 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n"); 2148 // FIXME: And what? 2149 } 2150 2151 /* Copy the drive of the system root */ 2152 RtlMoveMemory(CurrentDirectory.Buffer, 2153 SharedUserData->NtSystemRoot, 2154 3 * sizeof(WCHAR)); 2155 CurrentDirectory.Buffer[3] = UNICODE_NULL; 2156 CurrentDirectory.Length = 3 * sizeof(WCHAR); 2157 CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR); 2158 2159 FreeCurDir = TRUE; 2160 DPRINT("Using dynamically allocd curdir\n"); 2161 } 2162 else 2163 { 2164 /* Use the local buffer */ 2165 DPRINT("Using local system root\n"); 2166 } 2167 } 2168 2169 /* Setup Loader Data */ 2170 Peb->Ldr = &PebLdr; 2171 InitializeListHead(&PebLdr.InLoadOrderModuleList); 2172 InitializeListHead(&PebLdr.InMemoryOrderModuleList); 2173 InitializeListHead(&PebLdr.InInitializationOrderModuleList); 2174 PebLdr.Length = sizeof(PEB_LDR_DATA); 2175 PebLdr.Initialized = TRUE; 2176 2177 /* Allocate a data entry for the Image */ 2178 LdrpImageEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress); 2179 2180 /* Set it up */ 2181 LdrpImageEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrpImageEntry->DllBase); 2182 LdrpImageEntry->LoadCount = -1; 2183 LdrpImageEntry->EntryPointActivationContext = 0; 2184 LdrpImageEntry->FullDllName = ImageFileName; 2185 2186 if (IsDotNetImage) 2187 LdrpImageEntry->Flags = LDRP_COR_IMAGE; 2188 else 2189 LdrpImageEntry->Flags = 0; 2190 2191 /* Check if the name is empty */ 2192 if (!ImageFileName.Buffer[0]) 2193 { 2194 /* Use the same Base name */ 2195 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName; 2196 } 2197 else 2198 { 2199 /* Find the last slash */ 2200 Current = ImageFileName.Buffer; 2201 while (*Current) 2202 { 2203 if (*Current++ == '\\') 2204 { 2205 /* Set this path */ 2206 NtDllName = Current; 2207 } 2208 } 2209 2210 /* Did we find anything? */ 2211 if (!NtDllName) 2212 { 2213 /* Use the same Base name */ 2214 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName; 2215 } 2216 else 2217 { 2218 /* Setup the name */ 2219 LdrpImageEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName); 2220 LdrpImageEntry->BaseDllName.MaximumLength = LdrpImageEntry->BaseDllName.Length + sizeof(WCHAR); 2221 LdrpImageEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer + 2222 (ImageFileName.Length - LdrpImageEntry->BaseDllName.Length)); 2223 } 2224 } 2225 2226 /* Processing done, insert it */ 2227 LdrpInsertMemoryTableEntry(LdrpImageEntry); 2228 LdrpImageEntry->Flags |= LDRP_ENTRY_PROCESSED; 2229 2230 /* Now add an entry for NTDLL */ 2231 NtLdrEntry = LdrpAllocateDataTableEntry(SystemArgument1); 2232 NtLdrEntry->Flags = LDRP_IMAGE_DLL; 2233 NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase); 2234 NtLdrEntry->LoadCount = -1; 2235 NtLdrEntry->EntryPointActivationContext = 0; 2236 2237 NtLdrEntry->FullDllName.Length = FullPath.Length; 2238 NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength; 2239 NtLdrEntry->FullDllName.Buffer = StringBuffer; 2240 RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &NtDllString); 2241 2242 NtLdrEntry->BaseDllName.Length = NtDllString.Length; 2243 NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength; 2244 NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer; 2245 2246 /* Processing done, insert it */ 2247 LdrpNtDllDataTableEntry = NtLdrEntry; 2248 LdrpInsertMemoryTableEntry(NtLdrEntry); 2249 2250 /* Let the world know */ 2251 if (ShowSnaps) 2252 { 2253 DPRINT1("LDR: NEW PROCESS\n"); 2254 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry->FullDllName, &LdrpImageEntry->BaseDllName); 2255 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory); 2256 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath); 2257 } 2258 2259 /* Link the Init Order List */ 2260 InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList, 2261 &LdrpNtDllDataTableEntry->InInitializationOrderLinks); 2262 2263 /* Initialize Wine's active context implementation for the current process */ 2264 actctx_init(&OldShimData); 2265 2266 /* Set the current directory */ 2267 Status = RtlSetCurrentDirectory_U(&CurrentDirectory); 2268 if (!NT_SUCCESS(Status)) 2269 { 2270 /* We failed, check if we should free it */ 2271 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory); 2272 2273 /* Set it to the NT Root */ 2274 CurrentDirectory = NtSystemRoot; 2275 RtlSetCurrentDirectory_U(&CurrentDirectory); 2276 } 2277 else 2278 { 2279 /* We're done with it, free it */ 2280 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory); 2281 } 2282 2283 /* Check if we should look for a .local file */ 2284 if (ProcessParameters && !(ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH)) 2285 { 2286 LdrpInitializeDotLocalSupport(ProcessParameters); 2287 } 2288 2289 /* Check if the Application Verifier was enabled */ 2290 if (Peb->NtGlobalFlag & FLG_APPLICATION_VERIFIER) 2291 { 2292 Status = AVrfInitializeVerifier(); 2293 if (!NT_SUCCESS(Status)) 2294 { 2295 DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status); 2296 return Status; 2297 } 2298 2299 } 2300 2301 if (IsDotNetImage) 2302 { 2303 /* FIXME */ 2304 DPRINT1("We don't support .NET applications yet\n"); 2305 } 2306 2307 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI || 2308 NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) 2309 { 2310 PVOID Kernel32BaseAddress; 2311 PVOID FunctionAddress; 2312 2313 Status = LdrLoadDll(NULL, NULL, &Kernel32String, &Kernel32BaseAddress); 2314 2315 if (!NT_SUCCESS(Status)) 2316 { 2317 if (ShowSnaps) 2318 DPRINT1("LDR: Unable to load %wZ, Status=0x%08lx\n", &Kernel32String, Status); 2319 return Status; 2320 } 2321 2322 Status = LdrGetProcedureAddress(Kernel32BaseAddress, 2323 &BaseProcessInitPostImportName, 2324 0, 2325 &FunctionAddress); 2326 2327 if (!NT_SUCCESS(Status)) 2328 { 2329 if (ShowSnaps) 2330 DPRINT1("LDR: Unable to find post-import process init function, Status=0x%08lx\n", &Kernel32String, Status); 2331 return Status; 2332 } 2333 Kernel32ProcessInitPostImportFunction = FunctionAddress; 2334 2335 Status = LdrGetProcedureAddress(Kernel32BaseAddress, 2336 &BaseQueryModuleDataName, 2337 0, 2338 &FunctionAddress); 2339 2340 if (!NT_SUCCESS(Status)) 2341 { 2342 if (ShowSnaps) 2343 DPRINT1("LDR: Unable to find BaseQueryModuleData, Status=0x%08lx\n", &Kernel32String, Status); 2344 return Status; 2345 } 2346 Kernel32BaseQueryModuleData = FunctionAddress; 2347 } 2348 2349 /* Walk the IAT and load all the DLLs */ 2350 ImportStatus = LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry); 2351 2352 /* Check if relocation is needed */ 2353 if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase) 2354 { 2355 DPRINT1("LDR: Performing EXE relocation\n"); 2356 2357 /* Change the protection to prepare for relocation */ 2358 ViewBase = Peb->ImageBaseAddress; 2359 Status = LdrpSetProtection(ViewBase, FALSE); 2360 if (!NT_SUCCESS(Status)) return Status; 2361 2362 /* Do the relocation */ 2363 Status = LdrRelocateImageWithBias(ViewBase, 2364 0LL, 2365 NULL, 2366 STATUS_SUCCESS, 2367 STATUS_CONFLICTING_ADDRESSES, 2368 STATUS_INVALID_IMAGE_FORMAT); 2369 if (!NT_SUCCESS(Status)) 2370 { 2371 DPRINT1("LdrRelocateImageWithBias() failed\n"); 2372 return Status; 2373 } 2374 2375 /* Check if a start context was provided */ 2376 if (Context) 2377 { 2378 DPRINT1("WARNING: Relocated EXE Context"); 2379 UNIMPLEMENTED; // We should support this 2380 return STATUS_INVALID_IMAGE_FORMAT; 2381 } 2382 2383 /* Restore the protection */ 2384 Status = LdrpSetProtection(ViewBase, TRUE); 2385 if (!NT_SUCCESS(Status)) return Status; 2386 } 2387 2388 /* Lock the DLLs */ 2389 ListHead = &Peb->Ldr->InLoadOrderModuleList; 2390 NextEntry = ListHead->Flink; 2391 while (ListHead != NextEntry) 2392 { 2393 NtLdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 2394 NtLdrEntry->LoadCount = -1; 2395 NextEntry = NextEntry->Flink; 2396 } 2397 2398 /* Phase 0 is done */ 2399 LdrpLdrDatabaseIsSetup = TRUE; 2400 2401 /* Check whether all static imports were properly loaded and return here */ 2402 if (!NT_SUCCESS(ImportStatus)) return ImportStatus; 2403 2404 /* Initialize TLS */ 2405 Status = LdrpInitializeTls(); 2406 if (!NT_SUCCESS(Status)) 2407 { 2408 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n", 2409 Status); 2410 return Status; 2411 } 2412 2413 /* FIXME Mark the DLL Ranges for Stack Traces later */ 2414 2415 /* Notify the debugger now */ 2416 if (Peb->BeingDebugged) 2417 { 2418 /* Break */ 2419 DbgBreakPoint(); 2420 2421 /* Update show snaps again */ 2422 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; 2423 } 2424 2425 /* Validate the Image for MP Usage */ 2426 if (LdrpNumberOfProcessors > 1) LdrpValidateImageForMp(LdrpImageEntry); 2427 2428 /* Check NX options and set them */ 2429 if (SharedUserData->NXSupportPolicy == NX_SUPPORT_POLICY_ALWAYSON) 2430 { 2431 ExecuteOptions = MEM_EXECUTE_OPTION_DISABLE | 2432 MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION | 2433 MEM_EXECUTE_OPTION_PERMANENT; 2434 } 2435 else if (SharedUserData->NXSupportPolicy == NX_SUPPORT_POLICY_ALWAYSOFF) 2436 { 2437 ExecuteOptions = MEM_EXECUTE_OPTION_ENABLE | MEM_EXECUTE_OPTION_PERMANENT; 2438 } 2439 Status = NtSetInformationProcess(NtCurrentProcess(), 2440 ProcessExecuteFlags, 2441 &ExecuteOptions, 2442 sizeof(ExecuteOptions)); 2443 if (!NT_SUCCESS(Status)) 2444 { 2445 DPRINT1("LDR: Could not set process execute flags 0x%x; status %x\n", 2446 ExecuteOptions, Status); 2447 } 2448 2449 // FIXME: Should be done by Application Compatibility features, 2450 // by reading the registry, etc... 2451 // For now, this is the old code from ntdll!RtlGetVersion(). 2452 RtlInitEmptyUnicodeString(&Peb->CSDVersion, NULL, 0); 2453 if (((Peb->OSCSDVersion >> 8) & 0xFF) != 0) 2454 { 2455 WCHAR szCSDVersion[128]; 2456 LONG i; 2457 USHORT Length = (USHORT)ARRAYSIZE(szCSDVersion) - 1; 2458 i = _snwprintf(szCSDVersion, Length, 2459 L"Service Pack %d", 2460 ((Peb->OSCSDVersion >> 8) & 0xFF)); 2461 if (i < 0) 2462 { 2463 /* Null-terminate if it was overflowed */ 2464 szCSDVersion[Length] = UNICODE_NULL; 2465 } 2466 2467 Length *= sizeof(WCHAR); 2468 Peb->CSDVersion.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 2469 0, 2470 Length + sizeof(UNICODE_NULL)); 2471 if (Peb->CSDVersion.Buffer) 2472 { 2473 Peb->CSDVersion.Length = Length; 2474 Peb->CSDVersion.MaximumLength = Length + sizeof(UNICODE_NULL); 2475 2476 RtlCopyMemory(Peb->CSDVersion.Buffer, 2477 szCSDVersion, 2478 Peb->CSDVersion.MaximumLength); 2479 Peb->CSDVersion.Buffer[Peb->CSDVersion.Length / sizeof(WCHAR)] = UNICODE_NULL; 2480 } 2481 } 2482 2483 /* Check if we had Shim Data */ 2484 if (OldShimData) 2485 { 2486 /* Load the Shim Engine */ 2487 Peb->AppCompatInfo = NULL; 2488 LdrpLoadShimEngine(OldShimData, &ImagePathName, OldShimData); 2489 } 2490 else 2491 { 2492 /* Check for Application Compatibility Goo */ 2493 //LdrQueryApplicationCompatibilityGoo(hKey); 2494 DPRINT("Querying app compat hacks is missing!\n"); 2495 } 2496 2497 /* 2498 * FIXME: Check for special images, SecuROM, SafeDisc and other NX- 2499 * incompatible images. 2500 */ 2501 2502 /* Now call the Init Routines */ 2503 Status = LdrpRunInitializeRoutines(Context); 2504 if (!NT_SUCCESS(Status)) 2505 { 2506 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n", 2507 Status); 2508 return Status; 2509 } 2510 2511 /* Notify Shim Engine */ 2512 if (g_ShimsEnabled) 2513 { 2514 VOID(NTAPI *SE_InstallAfterInit)(PUNICODE_STRING, PVOID); 2515 SE_InstallAfterInit = RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit); 2516 SE_InstallAfterInit(&ImagePathName, OldShimData); 2517 } 2518 2519 /* Check if we have a user-defined Post Process Routine */ 2520 if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine) 2521 { 2522 /* Call it */ 2523 Peb->PostProcessInitRoutine(); 2524 } 2525 2526 /* Close the key if we have one opened */ 2527 if (OptionsKey) NtClose(OptionsKey); 2528 2529 /* Return status */ 2530 return Status; 2531 } 2532 2533 VOID 2534 NTAPI 2535 LdrpInitFailure(NTSTATUS Status) 2536 { 2537 ULONG Response; 2538 PPEB Peb = NtCurrentPeb(); 2539 2540 /* Print a debug message */ 2541 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n", 2542 &Peb->ProcessParameters->ImagePathName, Status); 2543 2544 /* Raise a hard error */ 2545 if (!LdrpFatalHardErrorCount) 2546 { 2547 ZwRaiseHardError(STATUS_APP_INIT_FAILURE, 1, 0, (PULONG_PTR)&Status, OptionOk, &Response); 2548 } 2549 } 2550 2551 VOID 2552 NTAPI 2553 LdrpInit(PCONTEXT Context, 2554 PVOID SystemArgument1, 2555 PVOID SystemArgument2) 2556 { 2557 LARGE_INTEGER Timeout; 2558 PTEB Teb = NtCurrentTeb(); 2559 NTSTATUS Status, LoaderStatus = STATUS_SUCCESS; 2560 MEMORY_BASIC_INFORMATION MemoryBasicInfo; 2561 PPEB Peb = NtCurrentPeb(); 2562 2563 DPRINT("LdrpInit() %p/%p\n", 2564 NtCurrentTeb()->RealClientId.UniqueProcess, 2565 NtCurrentTeb()->RealClientId.UniqueThread); 2566 2567 #ifdef _WIN64 2568 /* Set the SList header usage */ 2569 RtlpUse16ByteSLists = SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE128]; 2570 #endif /* _WIN64 */ 2571 2572 /* Check if we have a deallocation stack */ 2573 if (!Teb->DeallocationStack) 2574 { 2575 /* We don't, set one */ 2576 Status = NtQueryVirtualMemory(NtCurrentProcess(), 2577 Teb->NtTib.StackLimit, 2578 MemoryBasicInformation, 2579 &MemoryBasicInfo, 2580 sizeof(MEMORY_BASIC_INFORMATION), 2581 NULL); 2582 if (!NT_SUCCESS(Status)) 2583 { 2584 /* Fail */ 2585 LdrpInitFailure(Status); 2586 RtlRaiseStatus(Status); 2587 return; 2588 } 2589 2590 /* Set the stack */ 2591 Teb->DeallocationStack = MemoryBasicInfo.AllocationBase; 2592 } 2593 2594 /* Now check if the process is already being initialized */ 2595 while (_InterlockedCompareExchange(&LdrpProcessInitialized, 2596 1, 2597 0) == 1) 2598 { 2599 /* Set the timeout to 30 milliseconds */ 2600 Timeout.QuadPart = Int32x32To64(30, -10000); 2601 2602 /* Make sure the status hasn't changed */ 2603 while (LdrpProcessInitialized == 1) 2604 { 2605 /* Do the wait */ 2606 ZwDelayExecution(FALSE, &Timeout); 2607 } 2608 } 2609 2610 /* Check if we have already setup LDR data */ 2611 if (!Peb->Ldr) 2612 { 2613 /* Setup the Loader Lock */ 2614 Peb->LoaderLock = &LdrpLoaderLock; 2615 2616 /* Let other code know we're initializing */ 2617 LdrpInLdrInit = TRUE; 2618 2619 /* Protect with SEH */ 2620 _SEH2_TRY 2621 { 2622 /* Initialize the Process */ 2623 LoaderStatus = LdrpInitializeProcess(Context, 2624 SystemArgument1); 2625 2626 /* Check for success and if MinimumStackCommit was requested */ 2627 if (NT_SUCCESS(LoaderStatus) && Peb->MinimumStackCommit) 2628 { 2629 /* Enforce the limit */ 2630 //LdrpTouchThreadStack(Peb->MinimumStackCommit); 2631 UNIMPLEMENTED; 2632 } 2633 } 2634 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2635 { 2636 /* Fail with the SEH error */ 2637 LoaderStatus = _SEH2_GetExceptionCode(); 2638 } 2639 _SEH2_END; 2640 2641 /* We're not initializing anymore */ 2642 LdrpInLdrInit = FALSE; 2643 2644 /* Check if init worked */ 2645 if (NT_SUCCESS(LoaderStatus)) 2646 { 2647 /* Set the process as Initialized */ 2648 _InterlockedIncrement(&LdrpProcessInitialized); 2649 } 2650 } 2651 else 2652 { 2653 /* Loader data is there... is this a fork() ? */ 2654 if(Peb->InheritedAddressSpace) 2655 { 2656 /* Handle the fork() */ 2657 //LoaderStatus = LdrpForkProcess(); 2658 LoaderStatus = STATUS_NOT_IMPLEMENTED; 2659 UNIMPLEMENTED; 2660 } 2661 else 2662 { 2663 /* This is a new thread initializing */ 2664 LdrpInitializeThread(Context); 2665 } 2666 } 2667 2668 /* All done, test alert the thread */ 2669 NtTestAlert(); 2670 2671 /* Return */ 2672 if (!NT_SUCCESS(LoaderStatus)) 2673 { 2674 /* Fail */ 2675 LdrpInitFailure(LoaderStatus); 2676 RtlRaiseStatus(LoaderStatus); 2677 } 2678 } 2679 2680 /* EOF */ 2681