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