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 VOID 1541 NTAPI 1542 LdrpInitializeProcessCompat(PVOID pProcessActctx, PVOID* pOldShimData) 1543 { 1544 static const struct 1545 { 1546 const GUID* Guid; 1547 const DWORD Version; 1548 } KnownCompatGuids[] = { 1549 { &COMPAT_GUID_WIN10, _WIN32_WINNT_WIN10 }, 1550 { &COMPAT_GUID_WIN81, _WIN32_WINNT_WINBLUE }, 1551 { &COMPAT_GUID_WIN8, _WIN32_WINNT_WIN8 }, 1552 { &COMPAT_GUID_WIN7, _WIN32_WINNT_WIN7 }, 1553 { &COMPAT_GUID_VISTA, _WIN32_WINNT_VISTA }, 1554 }; 1555 1556 ULONG Buffer[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION)) / sizeof(ULONG)]; 1557 ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION* ContextCompatInfo; 1558 SIZE_T SizeRequired; 1559 NTSTATUS Status; 1560 DWORD n, cur; 1561 ReactOS_ShimData* pShimData = *pOldShimData; 1562 1563 if (pShimData) 1564 { 1565 if (pShimData->dwMagic != REACTOS_SHIMDATA_MAGIC || 1566 pShimData->dwSize != sizeof(ReactOS_ShimData)) 1567 { 1568 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData->dwMagic, pShimData->dwSize); 1569 return; 1570 } 1571 if (pShimData->dwRosProcessCompatVersion) 1572 { 1573 if (pShimData->dwRosProcessCompatVersion == REACTOS_COMPATVERSION_IGNOREMANIFEST) 1574 { 1575 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion set to ignore manifest\n"); 1576 } 1577 else 1578 { 1579 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData->dwRosProcessCompatVersion); 1580 } 1581 return; 1582 } 1583 } 1584 1585 SizeRequired = sizeof(Buffer); 1586 Status = RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF, 1587 pProcessActctx, 1588 NULL, 1589 CompatibilityInformationInActivationContext, 1590 Buffer, 1591 sizeof(Buffer), 1592 &SizeRequired); 1593 1594 if (!NT_SUCCESS(Status)) 1595 { 1596 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status); 1597 return; 1598 } 1599 1600 ContextCompatInfo = (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*)Buffer; 1601 /* No Compatibility elements present, bail out */ 1602 if (ContextCompatInfo->ElementCount == 0) 1603 return; 1604 1605 /* Search for known GUID's, starting from newest to oldest. */ 1606 for (cur = 0; cur < RTL_NUMBER_OF(KnownCompatGuids); ++cur) 1607 { 1608 for (n = 0; n < ContextCompatInfo->ElementCount; ++n) 1609 { 1610 if (ContextCompatInfo->Elements[n].Type == ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS && 1611 RtlCompareMemory(&ContextCompatInfo->Elements[n].Id, KnownCompatGuids[cur].Guid, sizeof(GUID)) == sizeof(GUID)) 1612 { 1613 /* If this process did not need shim data before, allocate and store it */ 1614 if (pShimData == NULL) 1615 { 1616 PPEB Peb = NtCurrentPeb(); 1617 1618 ASSERT(Peb->pShimData == NULL); 1619 pShimData = RtlAllocateHeap(Peb->ProcessHeap, HEAP_ZERO_MEMORY, sizeof(*pShimData)); 1620 1621 if (!pShimData) 1622 { 1623 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData)); 1624 return; 1625 } 1626 1627 pShimData->dwSize = sizeof(*pShimData); 1628 pShimData->dwMagic = REACTOS_SHIMDATA_MAGIC; 1629 1630 Peb->pShimData = pShimData; 1631 *pOldShimData = pShimData; 1632 } 1633 1634 /* Store the highest found version, and bail out. */ 1635 pShimData->dwRosProcessCompatVersion = KnownCompatGuids[cur].Version; 1636 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", KnownCompatGuids[cur].Version); 1637 return; 1638 } 1639 } 1640 } 1641 } 1642 1643 VOID 1644 NTAPI 1645 LdrpInitializeDotLocalSupport(PRTL_USER_PROCESS_PARAMETERS ProcessParameters) 1646 { 1647 UNICODE_STRING ImagePathName = ProcessParameters->ImagePathName; 1648 WCHAR LocalBuffer[MAX_PATH]; 1649 UNICODE_STRING DotLocal; 1650 NTSTATUS Status; 1651 ULONG RequiredSize; 1652 1653 RequiredSize = ImagePathName.Length + LdrpDotLocal.Length + sizeof(UNICODE_NULL); 1654 if (RequiredSize <= sizeof(LocalBuffer)) 1655 { 1656 RtlInitEmptyUnicodeString(&DotLocal, LocalBuffer, sizeof(LocalBuffer)); 1657 } 1658 else if (RequiredSize <= UNICODE_STRING_MAX_BYTES) 1659 { 1660 DotLocal.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, RequiredSize); 1661 DotLocal.Length = 0; 1662 DotLocal.MaximumLength = RequiredSize; 1663 if (!DotLocal.Buffer) 1664 DPRINT1("LDR: Failed to allocate memory for .local check\n"); 1665 } 1666 else 1667 { 1668 DotLocal.Buffer = NULL; 1669 DotLocal.Length = 0; 1670 DotLocal.MaximumLength = 0; 1671 DPRINT1("LDR: String too big for .local check\n"); 1672 } 1673 1674 if (DotLocal.Buffer) 1675 { 1676 Status = RtlAppendUnicodeStringToString(&DotLocal, &ImagePathName); 1677 ASSERT(NT_SUCCESS(Status)); 1678 if (NT_SUCCESS(Status)) 1679 { 1680 Status = RtlAppendUnicodeStringToString(&DotLocal, &LdrpDotLocal); 1681 ASSERT(NT_SUCCESS(Status)); 1682 } 1683 1684 if (NT_SUCCESS(Status)) 1685 { 1686 if (RtlDoesFileExists_UStr(&DotLocal)) 1687 { 1688 ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH; 1689 } 1690 } 1691 else 1692 { 1693 DPRINT1("LDR: Failed to append: 0x%lx\n", Status); 1694 } 1695 1696 if (DotLocal.Buffer != LocalBuffer) 1697 { 1698 RtlFreeHeap(RtlGetProcessHeap(), 0, DotLocal.Buffer); 1699 } 1700 } 1701 } 1702 1703 1704 NTSTATUS 1705 NTAPI 1706 LdrpInitializeProcess(IN PCONTEXT Context, 1707 IN PVOID SystemArgument1) 1708 { 1709 RTL_HEAP_PARAMETERS HeapParameters; 1710 ULONG ComSectionSize; 1711 ANSI_STRING BaseProcessInitPostImportName = RTL_CONSTANT_STRING("BaseProcessInitPostImport"); 1712 ANSI_STRING BaseQueryModuleDataName = RTL_CONSTANT_STRING("BaseQueryModuleData"); 1713 PVOID OldShimData; 1714 OBJECT_ATTRIBUTES ObjectAttributes; 1715 //UNICODE_STRING LocalFileName, FullImageName; 1716 HANDLE SymLinkHandle; 1717 //ULONG DebugHeapOnly; 1718 UNICODE_STRING CommandLine, NtSystemRoot, ImagePathName, FullPath, ImageFileName, KnownDllString; 1719 PPEB Peb = NtCurrentPeb(); 1720 BOOLEAN IsDotNetImage = FALSE; 1721 BOOLEAN FreeCurDir = FALSE; 1722 //HANDLE CompatKey; 1723 PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 1724 //LPWSTR ImagePathBuffer; 1725 ULONG ConfigSize; 1726 UNICODE_STRING CurrentDirectory; 1727 HANDLE OptionsKey; 1728 ULONG HeapFlags; 1729 PIMAGE_NT_HEADERS NtHeader; 1730 LPWSTR NtDllName = NULL; 1731 NTSTATUS Status, ImportStatus; 1732 NLSTABLEINFO NlsTable; 1733 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig; 1734 PTEB Teb = NtCurrentTeb(); 1735 PLIST_ENTRY ListHead; 1736 PLIST_ENTRY NextEntry; 1737 ULONG i; 1738 PWSTR ImagePath; 1739 ULONG DebugProcessHeapOnly = 0; 1740 PLDR_DATA_TABLE_ENTRY NtLdrEntry; 1741 PWCHAR Current; 1742 ULONG ExecuteOptions = 0; 1743 PVOID ViewBase; 1744 1745 /* Set a NULL SEH Filter */ 1746 RtlSetUnhandledExceptionFilter(NULL); 1747 1748 /* Get the image path */ 1749 ImagePath = Peb->ProcessParameters->ImagePathName.Buffer; 1750 1751 /* Check if it's not normalized */ 1752 if (!(Peb->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED)) 1753 { 1754 /* Normalize it*/ 1755 ImagePath = (PWSTR)((ULONG_PTR)ImagePath + (ULONG_PTR)Peb->ProcessParameters); 1756 } 1757 1758 /* Create a unicode string for the Image Path */ 1759 ImagePathName.Length = Peb->ProcessParameters->ImagePathName.Length; 1760 ImagePathName.MaximumLength = ImagePathName.Length + sizeof(WCHAR); 1761 ImagePathName.Buffer = ImagePath; 1762 1763 /* Get the NT Headers */ 1764 NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress); 1765 1766 /* Get the execution options */ 1767 Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &OptionsKey); 1768 1769 /* Check if this is a .NET executable */ 1770 if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress, 1771 TRUE, 1772 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, 1773 &ComSectionSize)) 1774 { 1775 /* Remember this for later */ 1776 IsDotNetImage = TRUE; 1777 } 1778 1779 /* Save the NTDLL Base address */ 1780 NtDllBase = SystemArgument1; 1781 1782 /* If this is a Native Image */ 1783 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE) 1784 { 1785 /* Then do DLL Validation */ 1786 LdrpDllValidation = TRUE; 1787 } 1788 1789 /* Save the old Shim Data */ 1790 OldShimData = Peb->pShimData; 1791 1792 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */ 1793 //Peb->pShimData = NULL; 1794 1795 /* Save the number of processors and CS Timeout */ 1796 LdrpNumberOfProcessors = Peb->NumberOfProcessors; 1797 RtlpTimeout = Peb->CriticalSectionTimeout; 1798 1799 /* Normalize the parameters */ 1800 ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters); 1801 if (ProcessParameters) 1802 { 1803 /* Save the Image and Command Line Names */ 1804 ImageFileName = ProcessParameters->ImagePathName; 1805 CommandLine = ProcessParameters->CommandLine; 1806 } 1807 else 1808 { 1809 /* It failed, initialize empty strings */ 1810 RtlInitUnicodeString(&ImageFileName, NULL); 1811 RtlInitUnicodeString(&CommandLine, NULL); 1812 } 1813 1814 /* Initialize NLS data */ 1815 RtlInitNlsTables(Peb->AnsiCodePageData, 1816 Peb->OemCodePageData, 1817 Peb->UnicodeCaseTableData, 1818 &NlsTable); 1819 1820 /* Reset NLS Translations */ 1821 RtlResetRtlTranslations(&NlsTable); 1822 1823 /* Get the Image Config Directory */ 1824 LoadConfig = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress, 1825 TRUE, 1826 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, 1827 &ConfigSize); 1828 1829 /* Setup the Heap Parameters */ 1830 RtlZeroMemory(&HeapParameters, sizeof(HeapParameters)); 1831 HeapFlags = HEAP_GROWABLE; 1832 HeapParameters.Length = sizeof(HeapParameters); 1833 1834 /* Check if we have Configuration Data */ 1835 if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY))) 1836 { 1837 /* FIXME: Custom heap settings and misc. */ 1838 DPRINT1("We don't support LOAD_CONFIG data yet\n"); 1839 } 1840 1841 /* Check for custom affinity mask */ 1842 if (Peb->ImageProcessAffinityMask) 1843 { 1844 /* Set it */ 1845 Status = NtSetInformationProcess(NtCurrentProcess(), 1846 ProcessAffinityMask, 1847 &Peb->ImageProcessAffinityMask, 1848 sizeof(Peb->ImageProcessAffinityMask)); 1849 } 1850 1851 /* Check if verbose debugging (ShowSnaps) was requested */ 1852 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; 1853 1854 /* Start verbose debugging messages right now if they were requested */ 1855 if (ShowSnaps) 1856 { 1857 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n", 1858 Teb->ClientId.UniqueProcess, 1859 &CommandLine); 1860 } 1861 1862 /* If the timeout is too long */ 1863 if (RtlpTimeout.QuadPart < Int32x32To64(3600, -10000000)) 1864 { 1865 /* Then disable CS Timeout */ 1866 RtlpTimeoutDisable = TRUE; 1867 } 1868 1869 /* Initialize Critical Section Data */ 1870 RtlpInitDeferedCriticalSection(); 1871 1872 /* Initialize VEH Call lists */ 1873 RtlpInitializeVectoredExceptionHandling(); 1874 1875 /* Set TLS/FLS Bitmap data */ 1876 Peb->FlsBitmap = &FlsBitMap; 1877 Peb->TlsBitmap = &TlsBitMap; 1878 Peb->TlsExpansionBitmap = &TlsExpansionBitMap; 1879 1880 /* Initialize FLS Bitmap */ 1881 RtlInitializeBitMap(&FlsBitMap, 1882 Peb->FlsBitmapBits, 1883 FLS_MAXIMUM_AVAILABLE); 1884 RtlSetBit(&FlsBitMap, 0); 1885 InitializeListHead(&Peb->FlsListHead); 1886 1887 /* Initialize TLS Bitmap */ 1888 RtlInitializeBitMap(&TlsBitMap, 1889 Peb->TlsBitmapBits, 1890 TLS_MINIMUM_AVAILABLE); 1891 RtlSetBit(&TlsBitMap, 0); 1892 RtlInitializeBitMap(&TlsExpansionBitMap, 1893 Peb->TlsExpansionBitmapBits, 1894 TLS_EXPANSION_SLOTS); 1895 RtlSetBit(&TlsExpansionBitMap, 0); 1896 1897 /* Initialize the Hash Table */ 1898 for (i = 0; i < LDR_HASH_TABLE_ENTRIES; i++) 1899 { 1900 InitializeListHead(&LdrpHashTable[i]); 1901 } 1902 1903 /* Initialize the Loader Lock */ 1904 // FIXME: What's the point of initing it manually, if two lines lower 1905 // a call to RtlInitializeCriticalSection() is being made anyway? 1906 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList); 1907 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock; 1908 RtlInitializeCriticalSection(&LdrpLoaderLock); 1909 LdrpLoaderLockInit = TRUE; 1910 1911 /* Check if User Stack Trace Database support was requested */ 1912 if (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB) 1913 { 1914 DPRINT1("We don't support user stack trace databases yet\n"); 1915 } 1916 1917 /* Setup Fast PEB Lock */ 1918 RtlInitializeCriticalSection(&FastPebLock); 1919 Peb->FastPebLock = &FastPebLock; 1920 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection; 1921 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection; 1922 1923 /* Setup Callout Lock and Notification list */ 1924 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock); 1925 InitializeListHead(&LdrpDllNotificationList); 1926 1927 /* For old executables, use 16-byte aligned heap */ 1928 if ((NtHeader->OptionalHeader.MajorSubsystemVersion <= 3) && 1929 (NtHeader->OptionalHeader.MinorSubsystemVersion < 51)) 1930 { 1931 HeapFlags |= HEAP_CREATE_ALIGN_16; 1932 } 1933 1934 /* Setup the Heap */ 1935 RtlInitializeHeapManager(); 1936 Peb->ProcessHeap = RtlCreateHeap(HeapFlags, 1937 NULL, 1938 NtHeader->OptionalHeader.SizeOfHeapReserve, 1939 NtHeader->OptionalHeader.SizeOfHeapCommit, 1940 NULL, 1941 &HeapParameters); 1942 1943 if (!Peb->ProcessHeap) 1944 { 1945 DPRINT1("Failed to create process heap\n"); 1946 return STATUS_NO_MEMORY; 1947 } 1948 1949 /* Allocate an Activation Context Stack */ 1950 Status = RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer); 1951 if (!NT_SUCCESS(Status)) return Status; 1952 1953 RtlZeroMemory(&HeapParameters, sizeof(HeapParameters)); 1954 HeapFlags = HEAP_GROWABLE | HEAP_CLASS_1; 1955 HeapParameters.Length = sizeof(HeapParameters); 1956 LdrpHeap = RtlCreateHeap(HeapFlags, 0, 0x10000, 0x6000, 0, &HeapParameters); 1957 if (!LdrpHeap) 1958 { 1959 DPRINT1("Failed to create loader private heap\n"); 1960 return STATUS_NO_MEMORY; 1961 } 1962 1963 /* Check for Debug Heap */ 1964 if (OptionsKey) 1965 { 1966 /* Query the setting */ 1967 Status = LdrQueryImageFileKeyOption(OptionsKey, 1968 L"DebugProcessHeapOnly", 1969 REG_DWORD, 1970 &DebugProcessHeapOnly, 1971 sizeof(ULONG), 1972 NULL); 1973 1974 if (NT_SUCCESS(Status)) 1975 { 1976 /* Reset DPH if requested */ 1977 if (RtlpPageHeapEnabled && DebugProcessHeapOnly) 1978 { 1979 RtlpDphGlobalFlags &= ~DPH_FLAG_DLL_NOTIFY; 1980 RtlpPageHeapEnabled = FALSE; 1981 } 1982 } 1983 } 1984 1985 /* Build the NTDLL Path */ 1986 FullPath.Buffer = StringBuffer; 1987 FullPath.Length = 0; 1988 FullPath.MaximumLength = sizeof(StringBuffer); 1989 RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot); 1990 RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot); 1991 RtlAppendUnicodeToString(&FullPath, L"\\System32\\"); 1992 1993 /* Open the Known DLLs directory */ 1994 RtlInitUnicodeString(&KnownDllString, L"\\KnownDlls"); 1995 InitializeObjectAttributes(&ObjectAttributes, 1996 &KnownDllString, 1997 OBJ_CASE_INSENSITIVE, 1998 NULL, 1999 NULL); 2000 Status = ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory, 2001 DIRECTORY_QUERY | DIRECTORY_TRAVERSE, 2002 &ObjectAttributes); 2003 2004 /* Check if it exists */ 2005 if (NT_SUCCESS(Status)) 2006 { 2007 /* Open the Known DLLs Path */ 2008 RtlInitUnicodeString(&KnownDllString, L"KnownDllPath"); 2009 InitializeObjectAttributes(&ObjectAttributes, 2010 &KnownDllString, 2011 OBJ_CASE_INSENSITIVE, 2012 LdrpKnownDllObjectDirectory, 2013 NULL); 2014 Status = NtOpenSymbolicLinkObject(&SymLinkHandle, 2015 SYMBOLIC_LINK_QUERY, 2016 &ObjectAttributes); 2017 if (NT_SUCCESS(Status)) 2018 { 2019 /* Query the path */ 2020 LdrpKnownDllPath.Length = 0; 2021 LdrpKnownDllPath.MaximumLength = sizeof(LdrpKnownDllPathBuffer); 2022 LdrpKnownDllPath.Buffer = LdrpKnownDllPathBuffer; 2023 Status = ZwQuerySymbolicLinkObject(SymLinkHandle, &LdrpKnownDllPath, NULL); 2024 NtClose(SymLinkHandle); 2025 if (!NT_SUCCESS(Status)) 2026 { 2027 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status); 2028 return Status; 2029 } 2030 } 2031 } 2032 2033 /* Check if we failed */ 2034 if (!NT_SUCCESS(Status)) 2035 { 2036 /* Assume System32 */ 2037 LdrpKnownDllObjectDirectory = NULL; 2038 RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer); 2039 LdrpKnownDllPath.Length -= sizeof(WCHAR); 2040 } 2041 2042 /* If we have process parameters, get the default path and current path */ 2043 if (ProcessParameters) 2044 { 2045 /* Check if we have a Dll Path */ 2046 if (ProcessParameters->DllPath.Length) 2047 { 2048 /* Get the path */ 2049 LdrpDefaultPath = *(PUNICODE_STRING)&ProcessParameters->DllPath; 2050 } 2051 else 2052 { 2053 /* We need a valid path */ 2054 DPRINT1("No valid DllPath was given!\n"); 2055 LdrpInitFailure(STATUS_INVALID_PARAMETER); 2056 } 2057 2058 /* Set the current directory */ 2059 CurrentDirectory = ProcessParameters->CurrentDirectory.DosPath; 2060 2061 /* Check if it's empty or invalid */ 2062 if ((!CurrentDirectory.Buffer) || 2063 (CurrentDirectory.Buffer[0] == UNICODE_NULL) || 2064 (!CurrentDirectory.Length)) 2065 { 2066 /* Allocate space for the buffer */ 2067 CurrentDirectory.Buffer = RtlAllocateHeap(Peb->ProcessHeap, 2068 0, 2069 3 * sizeof(WCHAR) + 2070 sizeof(UNICODE_NULL)); 2071 if (!CurrentDirectory.Buffer) 2072 { 2073 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n"); 2074 // FIXME: And what? 2075 } 2076 2077 /* Copy the drive of the system root */ 2078 RtlMoveMemory(CurrentDirectory.Buffer, 2079 SharedUserData->NtSystemRoot, 2080 3 * sizeof(WCHAR)); 2081 CurrentDirectory.Buffer[3] = UNICODE_NULL; 2082 CurrentDirectory.Length = 3 * sizeof(WCHAR); 2083 CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR); 2084 2085 FreeCurDir = TRUE; 2086 DPRINT("Using dynamically allocd curdir\n"); 2087 } 2088 else 2089 { 2090 /* Use the local buffer */ 2091 DPRINT("Using local system root\n"); 2092 } 2093 } 2094 2095 /* Setup Loader Data */ 2096 Peb->Ldr = &PebLdr; 2097 InitializeListHead(&PebLdr.InLoadOrderModuleList); 2098 InitializeListHead(&PebLdr.InMemoryOrderModuleList); 2099 InitializeListHead(&PebLdr.InInitializationOrderModuleList); 2100 PebLdr.Length = sizeof(PEB_LDR_DATA); 2101 PebLdr.Initialized = TRUE; 2102 2103 /* Allocate a data entry for the Image */ 2104 LdrpImageEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress); 2105 2106 /* Set it up */ 2107 LdrpImageEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrpImageEntry->DllBase); 2108 LdrpImageEntry->LoadCount = -1; 2109 LdrpImageEntry->EntryPointActivationContext = 0; 2110 LdrpImageEntry->FullDllName = ImageFileName; 2111 2112 if (IsDotNetImage) 2113 LdrpImageEntry->Flags = LDRP_COR_IMAGE; 2114 else 2115 LdrpImageEntry->Flags = 0; 2116 2117 /* Check if the name is empty */ 2118 if (!ImageFileName.Buffer[0]) 2119 { 2120 /* Use the same Base name */ 2121 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName; 2122 } 2123 else 2124 { 2125 /* Find the last slash */ 2126 Current = ImageFileName.Buffer; 2127 while (*Current) 2128 { 2129 if (*Current++ == '\\') 2130 { 2131 /* Set this path */ 2132 NtDllName = Current; 2133 } 2134 } 2135 2136 /* Did we find anything? */ 2137 if (!NtDllName) 2138 { 2139 /* Use the same Base name */ 2140 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName; 2141 } 2142 else 2143 { 2144 /* Setup the name */ 2145 LdrpImageEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName); 2146 LdrpImageEntry->BaseDllName.MaximumLength = LdrpImageEntry->BaseDllName.Length + sizeof(WCHAR); 2147 LdrpImageEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer + 2148 (ImageFileName.Length - LdrpImageEntry->BaseDllName.Length)); 2149 } 2150 } 2151 2152 /* Processing done, insert it */ 2153 LdrpInsertMemoryTableEntry(LdrpImageEntry); 2154 LdrpImageEntry->Flags |= LDRP_ENTRY_PROCESSED; 2155 2156 /* Now add an entry for NTDLL */ 2157 NtLdrEntry = LdrpAllocateDataTableEntry(SystemArgument1); 2158 NtLdrEntry->Flags = LDRP_IMAGE_DLL; 2159 NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase); 2160 NtLdrEntry->LoadCount = -1; 2161 NtLdrEntry->EntryPointActivationContext = 0; 2162 2163 NtLdrEntry->FullDllName.Length = FullPath.Length; 2164 NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength; 2165 NtLdrEntry->FullDllName.Buffer = StringBuffer; 2166 RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &NtDllString); 2167 2168 NtLdrEntry->BaseDllName.Length = NtDllString.Length; 2169 NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength; 2170 NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer; 2171 2172 /* Processing done, insert it */ 2173 LdrpNtDllDataTableEntry = NtLdrEntry; 2174 LdrpInsertMemoryTableEntry(NtLdrEntry); 2175 2176 /* Let the world know */ 2177 if (ShowSnaps) 2178 { 2179 DPRINT1("LDR: NEW PROCESS\n"); 2180 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry->FullDllName, &LdrpImageEntry->BaseDllName); 2181 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory); 2182 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath); 2183 } 2184 2185 /* Link the Init Order List */ 2186 InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList, 2187 &LdrpNtDllDataTableEntry->InInitializationOrderLinks); 2188 2189 /* Initialize Wine's active context implementation for the current process */ 2190 actctx_init(&OldShimData); 2191 2192 /* Set the current directory */ 2193 Status = RtlSetCurrentDirectory_U(&CurrentDirectory); 2194 if (!NT_SUCCESS(Status)) 2195 { 2196 /* We failed, check if we should free it */ 2197 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory); 2198 2199 /* Set it to the NT Root */ 2200 CurrentDirectory = NtSystemRoot; 2201 RtlSetCurrentDirectory_U(&CurrentDirectory); 2202 } 2203 else 2204 { 2205 /* We're done with it, free it */ 2206 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory); 2207 } 2208 2209 /* Check if we should look for a .local file */ 2210 if (ProcessParameters && !(ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH)) 2211 { 2212 LdrpInitializeDotLocalSupport(ProcessParameters); 2213 } 2214 2215 /* Check if the Application Verifier was enabled */ 2216 if (Peb->NtGlobalFlag & FLG_APPLICATION_VERIFIER) 2217 { 2218 Status = AVrfInitializeVerifier(); 2219 if (!NT_SUCCESS(Status)) 2220 { 2221 DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status); 2222 return Status; 2223 } 2224 2225 } 2226 2227 if (IsDotNetImage) 2228 { 2229 /* FIXME */ 2230 DPRINT1("We don't support .NET applications yet\n"); 2231 } 2232 2233 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI || 2234 NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) 2235 { 2236 PVOID Kernel32BaseAddress; 2237 PVOID FunctionAddress; 2238 2239 Status = LdrLoadDll(NULL, NULL, &Kernel32String, &Kernel32BaseAddress); 2240 2241 if (!NT_SUCCESS(Status)) 2242 { 2243 if (ShowSnaps) 2244 DPRINT1("LDR: Unable to load %wZ, Status=0x%08lx\n", &Kernel32String, Status); 2245 return Status; 2246 } 2247 2248 Status = LdrGetProcedureAddress(Kernel32BaseAddress, 2249 &BaseProcessInitPostImportName, 2250 0, 2251 &FunctionAddress); 2252 2253 if (!NT_SUCCESS(Status)) 2254 { 2255 if (ShowSnaps) 2256 DPRINT1("LDR: Unable to find post-import process init function, Status=0x%08lx\n", &Kernel32String, Status); 2257 return Status; 2258 } 2259 Kernel32ProcessInitPostImportFunction = FunctionAddress; 2260 2261 Status = LdrGetProcedureAddress(Kernel32BaseAddress, 2262 &BaseQueryModuleDataName, 2263 0, 2264 &FunctionAddress); 2265 2266 if (!NT_SUCCESS(Status)) 2267 { 2268 if (ShowSnaps) 2269 DPRINT1("LDR: Unable to find BaseQueryModuleData, Status=0x%08lx\n", &Kernel32String, Status); 2270 return Status; 2271 } 2272 Kernel32BaseQueryModuleData = FunctionAddress; 2273 } 2274 2275 /* Walk the IAT and load all the DLLs */ 2276 ImportStatus = LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry); 2277 2278 /* Check if relocation is needed */ 2279 if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase) 2280 { 2281 DPRINT1("LDR: Performing EXE relocation\n"); 2282 2283 /* Change the protection to prepare for relocation */ 2284 ViewBase = Peb->ImageBaseAddress; 2285 Status = LdrpSetProtection(ViewBase, FALSE); 2286 if (!NT_SUCCESS(Status)) return Status; 2287 2288 /* Do the relocation */ 2289 Status = LdrRelocateImageWithBias(ViewBase, 2290 0LL, 2291 NULL, 2292 STATUS_SUCCESS, 2293 STATUS_CONFLICTING_ADDRESSES, 2294 STATUS_INVALID_IMAGE_FORMAT); 2295 if (!NT_SUCCESS(Status)) 2296 { 2297 DPRINT1("LdrRelocateImageWithBias() failed\n"); 2298 return Status; 2299 } 2300 2301 /* Check if a start context was provided */ 2302 if (Context) 2303 { 2304 DPRINT1("WARNING: Relocated EXE Context"); 2305 UNIMPLEMENTED; // We should support this 2306 return STATUS_INVALID_IMAGE_FORMAT; 2307 } 2308 2309 /* Restore the protection */ 2310 Status = LdrpSetProtection(ViewBase, TRUE); 2311 if (!NT_SUCCESS(Status)) return Status; 2312 } 2313 2314 /* Lock the DLLs */ 2315 ListHead = &Peb->Ldr->InLoadOrderModuleList; 2316 NextEntry = ListHead->Flink; 2317 while (ListHead != NextEntry) 2318 { 2319 NtLdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 2320 NtLdrEntry->LoadCount = -1; 2321 NextEntry = NextEntry->Flink; 2322 } 2323 2324 /* Phase 0 is done */ 2325 LdrpLdrDatabaseIsSetup = TRUE; 2326 2327 /* Check whether all static imports were properly loaded and return here */ 2328 if (!NT_SUCCESS(ImportStatus)) return ImportStatus; 2329 2330 /* Initialize TLS */ 2331 Status = LdrpInitializeTls(); 2332 if (!NT_SUCCESS(Status)) 2333 { 2334 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n", 2335 Status); 2336 return Status; 2337 } 2338 2339 /* FIXME Mark the DLL Ranges for Stack Traces later */ 2340 2341 /* Notify the debugger now */ 2342 if (Peb->BeingDebugged) 2343 { 2344 /* Break */ 2345 DbgBreakPoint(); 2346 2347 /* Update show snaps again */ 2348 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; 2349 } 2350 2351 /* Validate the Image for MP Usage */ 2352 if (LdrpNumberOfProcessors > 1) LdrpValidateImageForMp(LdrpImageEntry); 2353 2354 /* Check NX Options */ 2355 if (SharedUserData->NXSupportPolicy == 1) 2356 { 2357 ExecuteOptions = 0xD; 2358 } 2359 else if (!SharedUserData->NXSupportPolicy) 2360 { 2361 ExecuteOptions = 0xA; 2362 } 2363 2364 /* Let Mm know */ 2365 ZwSetInformationProcess(NtCurrentProcess(), 2366 ProcessExecuteFlags, 2367 &ExecuteOptions, 2368 sizeof(ULONG)); 2369 2370 // FIXME: Should be done by Application Compatibility features, 2371 // by reading the registry, etc... 2372 // For now, this is the old code from ntdll!RtlGetVersion(). 2373 RtlInitEmptyUnicodeString(&Peb->CSDVersion, NULL, 0); 2374 if (((Peb->OSCSDVersion >> 8) & 0xFF) != 0) 2375 { 2376 WCHAR szCSDVersion[128]; 2377 LONG i; 2378 USHORT Length = (USHORT)ARRAYSIZE(szCSDVersion) - 1; 2379 i = _snwprintf(szCSDVersion, Length, 2380 L"Service Pack %d", 2381 ((Peb->OSCSDVersion >> 8) & 0xFF)); 2382 if (i < 0) 2383 { 2384 /* Null-terminate if it was overflowed */ 2385 szCSDVersion[Length] = UNICODE_NULL; 2386 } 2387 2388 Length *= sizeof(WCHAR); 2389 Peb->CSDVersion.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 2390 0, 2391 Length + sizeof(UNICODE_NULL)); 2392 if (Peb->CSDVersion.Buffer) 2393 { 2394 Peb->CSDVersion.Length = Length; 2395 Peb->CSDVersion.MaximumLength = Length + sizeof(UNICODE_NULL); 2396 2397 RtlCopyMemory(Peb->CSDVersion.Buffer, 2398 szCSDVersion, 2399 Peb->CSDVersion.MaximumLength); 2400 Peb->CSDVersion.Buffer[Peb->CSDVersion.Length / sizeof(WCHAR)] = UNICODE_NULL; 2401 } 2402 } 2403 2404 /* Check if we had Shim Data */ 2405 if (OldShimData) 2406 { 2407 /* Load the Shim Engine */ 2408 Peb->AppCompatInfo = NULL; 2409 LdrpLoadShimEngine(OldShimData, &ImagePathName, OldShimData); 2410 } 2411 else 2412 { 2413 /* Check for Application Compatibility Goo */ 2414 //LdrQueryApplicationCompatibilityGoo(hKey); 2415 DPRINT("Querying app compat hacks is missing!\n"); 2416 } 2417 2418 /* 2419 * FIXME: Check for special images, SecuROM, SafeDisc and other NX- 2420 * incompatible images. 2421 */ 2422 2423 /* Now call the Init Routines */ 2424 Status = LdrpRunInitializeRoutines(Context); 2425 if (!NT_SUCCESS(Status)) 2426 { 2427 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n", 2428 Status); 2429 return Status; 2430 } 2431 2432 /* Notify Shim Engine */ 2433 if (g_ShimsEnabled) 2434 { 2435 VOID(NTAPI *SE_InstallAfterInit)(PUNICODE_STRING, PVOID); 2436 SE_InstallAfterInit = RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit); 2437 SE_InstallAfterInit(&ImagePathName, OldShimData); 2438 } 2439 2440 /* Check if we have a user-defined Post Process Routine */ 2441 if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine) 2442 { 2443 /* Call it */ 2444 Peb->PostProcessInitRoutine(); 2445 } 2446 2447 /* Close the key if we have one opened */ 2448 if (OptionsKey) NtClose(OptionsKey); 2449 2450 /* Return status */ 2451 return Status; 2452 } 2453 2454 VOID 2455 NTAPI 2456 LdrpInitFailure(NTSTATUS Status) 2457 { 2458 ULONG Response; 2459 PPEB Peb = NtCurrentPeb(); 2460 2461 /* Print a debug message */ 2462 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n", 2463 &Peb->ProcessParameters->ImagePathName, Status); 2464 2465 /* Raise a hard error */ 2466 if (!LdrpFatalHardErrorCount) 2467 { 2468 ZwRaiseHardError(STATUS_APP_INIT_FAILURE, 1, 0, (PULONG_PTR)&Status, OptionOk, &Response); 2469 } 2470 } 2471 2472 VOID 2473 NTAPI 2474 LdrpInit(PCONTEXT Context, 2475 PVOID SystemArgument1, 2476 PVOID SystemArgument2) 2477 { 2478 LARGE_INTEGER Timeout; 2479 PTEB Teb = NtCurrentTeb(); 2480 NTSTATUS Status, LoaderStatus = STATUS_SUCCESS; 2481 MEMORY_BASIC_INFORMATION MemoryBasicInfo; 2482 PPEB Peb = NtCurrentPeb(); 2483 2484 DPRINT("LdrpInit() %p/%p\n", 2485 NtCurrentTeb()->RealClientId.UniqueProcess, 2486 NtCurrentTeb()->RealClientId.UniqueThread); 2487 2488 #ifdef _WIN64 2489 /* Set the SList header usage */ 2490 RtlpUse16ByteSLists = SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE128]; 2491 #endif /* _WIN64 */ 2492 2493 /* Check if we have a deallocation stack */ 2494 if (!Teb->DeallocationStack) 2495 { 2496 /* We don't, set one */ 2497 Status = NtQueryVirtualMemory(NtCurrentProcess(), 2498 Teb->NtTib.StackLimit, 2499 MemoryBasicInformation, 2500 &MemoryBasicInfo, 2501 sizeof(MEMORY_BASIC_INFORMATION), 2502 NULL); 2503 if (!NT_SUCCESS(Status)) 2504 { 2505 /* Fail */ 2506 LdrpInitFailure(Status); 2507 RtlRaiseStatus(Status); 2508 return; 2509 } 2510 2511 /* Set the stack */ 2512 Teb->DeallocationStack = MemoryBasicInfo.AllocationBase; 2513 } 2514 2515 /* Now check if the process is already being initialized */ 2516 while (_InterlockedCompareExchange(&LdrpProcessInitialized, 2517 1, 2518 0) == 1) 2519 { 2520 /* Set the timeout to 30 milliseconds */ 2521 Timeout.QuadPart = Int32x32To64(30, -10000); 2522 2523 /* Make sure the status hasn't changed */ 2524 while (LdrpProcessInitialized == 1) 2525 { 2526 /* Do the wait */ 2527 ZwDelayExecution(FALSE, &Timeout); 2528 } 2529 } 2530 2531 /* Check if we have already setup LDR data */ 2532 if (!Peb->Ldr) 2533 { 2534 /* Setup the Loader Lock */ 2535 Peb->LoaderLock = &LdrpLoaderLock; 2536 2537 /* Let other code know we're initializing */ 2538 LdrpInLdrInit = TRUE; 2539 2540 /* Protect with SEH */ 2541 _SEH2_TRY 2542 { 2543 /* Initialize the Process */ 2544 LoaderStatus = LdrpInitializeProcess(Context, 2545 SystemArgument1); 2546 2547 /* Check for success and if MinimumStackCommit was requested */ 2548 if (NT_SUCCESS(LoaderStatus) && Peb->MinimumStackCommit) 2549 { 2550 /* Enforce the limit */ 2551 //LdrpTouchThreadStack(Peb->MinimumStackCommit); 2552 UNIMPLEMENTED; 2553 } 2554 } 2555 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2556 { 2557 /* Fail with the SEH error */ 2558 LoaderStatus = _SEH2_GetExceptionCode(); 2559 } 2560 _SEH2_END; 2561 2562 /* We're not initializing anymore */ 2563 LdrpInLdrInit = FALSE; 2564 2565 /* Check if init worked */ 2566 if (NT_SUCCESS(LoaderStatus)) 2567 { 2568 /* Set the process as Initialized */ 2569 _InterlockedIncrement(&LdrpProcessInitialized); 2570 } 2571 } 2572 else 2573 { 2574 /* Loader data is there... is this a fork() ? */ 2575 if(Peb->InheritedAddressSpace) 2576 { 2577 /* Handle the fork() */ 2578 //LoaderStatus = LdrpForkProcess(); 2579 LoaderStatus = STATUS_NOT_IMPLEMENTED; 2580 UNIMPLEMENTED; 2581 } 2582 else 2583 { 2584 /* This is a new thread initializing */ 2585 LdrpInitializeThread(Context); 2586 } 2587 } 2588 2589 /* All done, test alert the thread */ 2590 NtTestAlert(); 2591 2592 /* Return */ 2593 if (!NT_SUCCESS(LoaderStatus)) 2594 { 2595 /* Fail */ 2596 LdrpInitFailure(LoaderStatus); 2597 RtlRaiseStatus(LoaderStatus); 2598 } 2599 } 2600 2601 /* EOF */ 2602