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)
10 /* INCLUDES *****************************************************************/
13 #include <compat_undoc.h>
14 #include <compatguid_undoc.h>
20 /* GLOBALS *******************************************************************/
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");
29 BOOLEAN LdrpInLdrInit
;
30 LONG LdrpProcessInitialized
;
31 BOOLEAN LdrpLoaderLockInit
;
32 BOOLEAN LdrpLdrDatabaseIsSetup
;
33 BOOLEAN LdrpShutdownInProgress
;
34 HANDLE LdrpShutdownThreadId
;
36 BOOLEAN LdrpDllValidation
;
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
;
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
);
49 RTL_BITMAP TlsExpansionBitMap
;
51 BOOLEAN LdrpImageHasTls
;
52 LIST_ENTRY LdrpTlsList
;
53 ULONG LdrpNumberOfTlsEntries
;
54 ULONG LdrpNumberOfProcessors
;
56 extern LARGE_INTEGER RtlpTimeout
;
57 BOOLEAN RtlpTimeoutDisable
;
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
;
68 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug
;
69 RTL_CRITICAL_SECTION LdrpLoaderLock
=
78 RTL_CRITICAL_SECTION FastPebLock
;
82 ULONG LdrpFatalHardErrorCount
;
83 ULONG LdrpActiveUnloadCount
;
85 //extern LIST_ENTRY RtlCriticalSectionList;
87 VOID NTAPI
RtlpInitializeVectoredExceptionHandling(VOID
);
88 VOID NTAPI
RtlpInitDeferedCriticalSection(VOID
);
89 VOID NTAPI
RtlInitializeHeapManager(VOID
);
91 ULONG RtlpDisableHeapLookaside
; // TODO: Move to heap.c
92 ULONG RtlpShutdownProcessFlags
; // TODO: Use it
94 NTSTATUS
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
, PVOID ImageBase
);
95 void actctx_init(void);
96 extern BOOLEAN RtlpUse16ByteSLists
;
99 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
101 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E
104 /* FUNCTIONS *****************************************************************/
111 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey
,
113 OUT PHANDLE NewKeyHandle
)
115 PHANDLE RootKeyLocation
;
117 UNICODE_STRING SubKeyString
;
118 OBJECT_ATTRIBUTES ObjectAttributes
;
122 /* Check which root key to open */
124 RootKeyLocation
= &Wow64ExecOptionsKey
;
126 RootKeyLocation
= &ImageExecOptionsKey
;
128 /* Get the current key */
129 RootKey
= *RootKeyLocation
;
131 /* Setup the object attributes */
132 InitializeObjectAttributes(&ObjectAttributes
,
134 &Wow64OptionsString
: &ImageExecOptionsString
,
135 OBJ_CASE_INSENSITIVE
,
139 /* Open the root key */
140 Status
= ZwOpenKey(&RootKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
141 if (NT_SUCCESS(Status
))
143 /* Write the key handle */
144 if (InterlockedCompareExchangePointer(RootKeyLocation
, RootKey
, NULL
) != NULL
)
146 /* Someone already opened it, use it instead */
148 RootKey
= *RootKeyLocation
;
151 /* Extract the name */
152 SubKeyString
= *SubKey
;
153 p1
= (PWCHAR
)((ULONG_PTR
)SubKeyString
.Buffer
+ SubKeyString
.Length
);
154 while (SubKeyString
.Length
)
156 if (p1
[-1] == L
'\\') break;
158 SubKeyString
.Length
-= sizeof(*p1
);
160 SubKeyString
.Buffer
= p1
;
161 SubKeyString
.Length
= SubKey
->Length
- SubKeyString
.Length
;
163 /* Setup the object attributes */
164 InitializeObjectAttributes(&ObjectAttributes
,
166 OBJ_CASE_INSENSITIVE
,
170 /* Open the setting key */
171 Status
= ZwOpenKey((PHANDLE
)NewKeyHandle
, GENERIC_READ
, &ObjectAttributes
);
174 /* Return to caller */
183 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle
,
188 OUT PULONG ReturnedLength OPTIONAL
)
191 UNICODE_STRING ValueNameString
, IntegerString
;
192 ULONG KeyInfoSize
, ResultSize
;
193 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)&KeyInfo
;
194 BOOLEAN FreeHeap
= FALSE
;
197 /* Build a string for the value name */
198 Status
= RtlInitUnicodeStringEx(&ValueNameString
, ValueName
);
199 if (!NT_SUCCESS(Status
)) return Status
;
201 /* Query the value */
202 Status
= ZwQueryValueKey(KeyHandle
,
204 KeyValuePartialInformation
,
208 if (Status
== STATUS_BUFFER_OVERFLOW
)
210 /* Our local buffer wasn't enough, allocate one */
211 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
212 KeyValueInformation
->DataLength
;
213 KeyValueInformation
= RtlAllocateHeap(RtlGetProcessHeap(),
216 if (KeyValueInformation
!= NULL
)
219 Status
= ZwQueryValueKey(KeyHandle
,
221 KeyValuePartialInformation
,
229 /* Give up this time */
230 Status
= STATUS_NO_MEMORY
;
234 /* Check for success */
235 if (NT_SUCCESS(Status
))
237 /* Handle binary data */
238 if (KeyValueInformation
->Type
== REG_BINARY
)
241 if ((Buffer
) && (KeyValueInformation
->DataLength
<= BufferSize
))
243 /* Copy into buffer */
244 RtlMoveMemory(Buffer
,
245 &KeyValueInformation
->Data
,
246 KeyValueInformation
->DataLength
);
250 Status
= STATUS_BUFFER_OVERFLOW
;
253 /* Copy the result length */
254 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
256 else if (KeyValueInformation
->Type
== REG_DWORD
)
258 /* Check for valid type */
259 if (KeyValueInformation
->Type
!= Type
)
262 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
268 (BufferSize
== sizeof(ULONG
)) &&
269 (KeyValueInformation
->DataLength
<= BufferSize
))
271 /* Copy into buffer */
272 RtlMoveMemory(Buffer
,
273 &KeyValueInformation
->Data
,
274 KeyValueInformation
->DataLength
);
278 Status
= STATUS_BUFFER_OVERFLOW
;
281 /* Copy the result length */
282 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
285 else if (KeyValueInformation
->Type
!= REG_SZ
)
287 /* We got something weird */
288 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
292 /* String, check what you requested */
293 if (Type
== REG_DWORD
)
296 if (BufferSize
!= sizeof(ULONG
))
300 Status
= STATUS_INFO_LENGTH_MISMATCH
;
304 /* OK, we know what you want... */
305 IntegerString
.Buffer
= (PWSTR
)KeyValueInformation
->Data
;
306 IntegerString
.Length
= (USHORT
)KeyValueInformation
->DataLength
-
308 IntegerString
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
309 Status
= RtlUnicodeStringToInteger(&IntegerString
, 0, (PULONG
)Buffer
);
315 if (KeyValueInformation
->DataLength
> BufferSize
)
318 Status
= STATUS_BUFFER_OVERFLOW
;
323 BufferSize
= KeyValueInformation
->DataLength
;
326 /* Copy the string */
327 RtlMoveMemory(Buffer
, &KeyValueInformation
->Data
, BufferSize
);
330 /* Copy the result length */
331 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
335 /* Check if buffer was in heap */
336 if (FreeHeap
) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation
);
347 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey
,
352 OUT PULONG ReturnedLength OPTIONAL
,
358 /* Open a handle to the key */
359 Status
= LdrOpenImageFileOptionsKey(SubKey
, Wow64
, &KeyHandle
);
361 /* Check for success */
362 if (NT_SUCCESS(Status
))
365 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
376 /* Return to caller */
385 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey
,
390 OUT PULONG ReturnedLength OPTIONAL
)
392 /* Call the newer function */
393 return LdrQueryImageFileExecutionOptionsEx(SubKey
,
404 LdrpEnsureLoaderLockIsHeld(VOID
)
411 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress
, ULONG SizeOfImage
)
413 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir
;
417 /* Check NT header first */
418 if (!RtlImageNtHeader(BaseAddress
)) return NULL
;
420 /* Get the pointer to the config directory */
421 ConfigDir
= RtlImageDirectoryEntryToData(BaseAddress
,
423 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
426 /* Check for sanity */
428 (DirSize
!= 64 && ConfigDir
->Size
!= DirSize
) ||
429 (ConfigDir
->Size
< 0x48))
432 /* Now get the cookie */
433 Cookie
= (PVOID
)ConfigDir
->SecurityCookie
;
435 /* Check this cookie */
436 if ((PCHAR
)Cookie
<= (PCHAR
)BaseAddress
||
437 (PCHAR
)Cookie
>= (PCHAR
)BaseAddress
+ SizeOfImage
)
442 /* Return validated security cookie */
448 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry
)
451 LARGE_INTEGER Counter
;
454 /* Fetch address of the cookie */
455 Cookie
= LdrpFetchAddressOfSecurityCookie(LdrEntry
->DllBase
, LdrEntry
->SizeOfImage
);
459 /* Check if it's a default one */
460 if ((*Cookie
== DEFAULT_SECURITY_COOKIE
) ||
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
);
467 NewCookie
= Counter
.LowPart
^ Counter
.HighPart
;
468 NewCookie
^= (ULONG_PTR
)NtCurrentTeb()->ClientId
.UniqueProcess
;
469 NewCookie
^= (ULONG_PTR
)NtCurrentTeb()->ClientId
.UniqueThread
;
471 /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */
472 while (SharedUserData
->SystemTime
.High1Time
!= SharedUserData
->SystemTime
.High2Time
)
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));
481 /* Make the cookie 16bit if necessary */
482 if (*Cookie
== 0xBB40) NewCookie
&= 0xFFFF;
484 /* If the result is 0 or the same as we got, just subtract one from the existing value
486 if ((NewCookie
== 0) || (NewCookie
== *Cookie
))
488 NewCookie
= *Cookie
- 1;
491 /* Set the new cookie value */
501 LdrpInitializeThread(IN PCONTEXT Context
)
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
;
510 DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n",
511 &LdrpImageEntry
->BaseDllName
,
512 NtCurrentTeb()->RealClientId
.UniqueProcess
,
513 NtCurrentTeb()->RealClientId
.UniqueThread
);
515 /* Allocate an Activation Context Stack */
516 DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer
);
517 Status
= RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer
);
518 if (!NT_SUCCESS(Status
))
520 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
523 /* Make sure we are not shutting down */
524 if (LdrpShutdownInProgress
) return;
529 /* Start at the beginning */
530 ListHead
= &Peb
->Ldr
->InMemoryOrderModuleList
;
531 NextEntry
= ListHead
->Flink
;
532 while (NextEntry
!= ListHead
)
534 /* Get the current entry */
535 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InMemoryOrderLinks
);
537 /* Make sure it's not ourselves */
538 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
540 /* Check if we should call */
541 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
))
543 /* Get the entrypoint */
544 EntryPoint
= LdrEntry
->EntryPoint
;
546 /* Check if we are ready to call it */
548 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
549 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
551 /* Set up the Act Ctx */
552 ActCtx
.Size
= sizeof(ActCtx
);
554 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
556 /* Activate the ActCtx */
557 RtlActivateActivationContextUnsafeFast(&ActCtx
,
558 LdrEntry
->EntryPointActivationContext
);
562 /* Check if it has TLS */
563 if (LdrEntry
->TlsIndex
)
565 /* Make sure we're not shutting down */
566 if (!LdrpShutdownInProgress
)
569 LdrpCallTlsInitializers(LdrEntry
, DLL_THREAD_ATTACH
);
573 /* Make sure we're not shutting down */
574 if (!LdrpShutdownInProgress
)
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
,
587 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
589 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_ATTACH) for %wZ\n",
590 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
594 /* Deactivate the ActCtx */
595 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
601 NextEntry
= NextEntry
->Flink
;
605 if (LdrpImageHasTls
&& !LdrpShutdownInProgress
)
607 /* Set up the Act Ctx */
608 ActCtx
.Size
= sizeof(ActCtx
);
610 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
612 /* Activate the ActCtx */
613 RtlActivateActivationContextUnsafeFast(&ActCtx
,
614 LdrpImageEntry
->EntryPointActivationContext
);
618 /* Do TLS callbacks */
619 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_THREAD_ATTACH
);
621 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
627 /* Deactivate the ActCtx */
628 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
631 DPRINT("LdrpInitializeThread() done\n");
636 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL
)
638 PLDR_DATA_TABLE_ENTRY LocalArray
[16];
639 PLIST_ENTRY ListHead
;
640 PLIST_ENTRY NextEntry
;
641 PLDR_DATA_TABLE_ENTRY LdrEntry
, *LdrRootEntry
, OldInitializer
;
645 NTSTATUS Status
= STATUS_SUCCESS
;
646 PPEB Peb
= NtCurrentPeb();
647 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
648 ULONG BreakOnDllLoad
;
652 DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
653 &LdrpImageEntry
->BaseDllName
,
654 NtCurrentTeb()->RealClientId
.UniqueProcess
,
655 NtCurrentTeb()->RealClientId
.UniqueThread
);
657 /* Check the Loader Lock */
658 LdrpEnsureLoaderLockIsHeld();
660 /* Get the number of entries to call */
661 if ((Count
= LdrpClearLoadInProgress()))
663 /* Check if we can use our local buffer */
666 /* Allocate space for all the entries */
667 LdrRootEntry
= RtlAllocateHeap(LdrpHeap
,
669 Count
* sizeof(*LdrRootEntry
));
670 if (!LdrRootEntry
) return STATUS_NO_MEMORY
;
674 /* Use our local array */
675 LdrRootEntry
= LocalArray
;
684 /* Show debug message */
687 DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
688 NtCurrentTeb()->RealClientId
.UniqueThread
,
689 NtCurrentTeb()->RealClientId
.UniqueProcess
,
690 &Peb
->ProcessParameters
->ImagePathName
);
694 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
695 NextEntry
= ListHead
->Flink
;
697 while (NextEntry
!= ListHead
)
699 /* Get the Data Entry */
700 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
702 /* Check if we have a Root Entry */
706 if (!(LdrEntry
->Flags
& LDRP_ENTRY_PROCESSED
))
708 /* Setup the Cookie for the DLL */
709 LdrpInitSecurityCookie(LdrEntry
);
711 /* Check for valid entrypoint */
712 if (LdrEntry
->EntryPoint
)
716 LdrRootEntry
[i
] = LdrEntry
;
718 /* Display debug message */
721 DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
722 NtCurrentTeb()->RealClientId
.UniqueThread
,
723 NtCurrentTeb()->RealClientId
.UniqueProcess
,
724 &LdrEntry
->FullDllName
,
725 LdrEntry
->EntryPoint
);
733 LdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
734 NextEntry
= NextEntry
->Flink
;
737 Status
= STATUS_SUCCESS
;
739 /* If we got a context, then we have to call Kernel32 for TS support */
742 /* Check if we have one */
743 if (Kernel32ProcessInitPostImportFunction
)
746 Status
= Kernel32ProcessInitPostImportFunction();
747 if (!NT_SUCCESS(Status
))
749 DPRINT1("LDR: LdrpRunInitializeRoutines - Failed running kernel32 post-import function, Status=0x%08lx\n", Status
);
753 Kernel32ProcessInitPostImportFunction
= NULL
;
756 /* No root entry? return */
760 /* Set the TLD TEB */
761 OldTldTeb
= LdrpTopLevelDllBeingLoadedTeb
;
762 LdrpTopLevelDllBeingLoadedTeb
= NtCurrentTeb();
769 LdrEntry
= LdrRootEntry
[i
];
771 /* FIXME: Verify NX Compat */
773 /* Move to next entry */
776 /* Get its entrypoint */
777 EntryPoint
= LdrEntry
->EntryPoint
;
779 /* Are we being debugged? */
781 if (Peb
->BeingDebugged
|| Peb
->ReadImageFileExecOptions
)
783 /* Check if we should break on load */
784 Status
= LdrQueryImageFileExecutionOptions(&LdrEntry
->BaseDllName
,
790 if (!NT_SUCCESS(Status
)) BreakOnDllLoad
= 0;
792 /* Reset status back to STATUS_SUCCESS */
793 Status
= STATUS_SUCCESS
;
799 /* Check if we should show a message */
802 DPRINT1("LDR: %wZ loaded.", &LdrEntry
->BaseDllName
);
803 DPRINT1(" - About to call init routine at %p\n", EntryPoint
);
806 /* Break in debugger */
810 /* Make sure we have an entrypoint */
813 /* Save the old Dll Initializer and write the current one */
814 OldInitializer
= LdrpCurrentDllInitializer
;
815 LdrpCurrentDllInitializer
= LdrEntry
;
817 /* Set up the Act Ctx */
818 ActCtx
.Size
= sizeof(ActCtx
);
820 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
822 /* Activate the ActCtx */
823 RtlActivateActivationContextUnsafeFast(&ActCtx
,
824 LdrEntry
->EntryPointActivationContext
);
828 /* Check if it has TLS */
829 if (LdrEntry
->TlsIndex
&& Context
)
832 LdrpCallTlsInitializers(LdrEntry
, DLL_PROCESS_ATTACH
);
835 /* Call the Entrypoint */
838 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
839 &LdrEntry
->BaseDllName
, EntryPoint
);
841 DllStatus
= LdrpCallInitRoutine(EntryPoint
,
846 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
849 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_ATTACH) for %wZ\n",
850 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
854 /* Deactivate the ActCtx */
855 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
857 /* Save the Current DLL Initializer */
858 LdrpCurrentDllInitializer
= OldInitializer
;
860 /* Mark the entry as processed */
861 LdrEntry
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
;
863 /* Fail if DLL init failed */
866 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
867 &LdrEntry
->BaseDllName
, EntryPoint
);
869 Status
= STATUS_DLL_INIT_FAILED
;
876 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
877 NextEntry
= NextEntry
->Flink
;
878 while (NextEntry
!= ListHead
)
880 /* Get the Data Entry */
881 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
883 /* FIXME: Verify NX Compat */
884 // LdrpCheckNXCompatibility()
887 NextEntry
= NextEntry
->Flink
;
891 if (LdrpImageHasTls
&& Context
)
893 /* Set up the Act Ctx */
894 ActCtx
.Size
= sizeof(ActCtx
);
896 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
898 /* Activate the ActCtx */
899 RtlActivateActivationContextUnsafeFast(&ActCtx
,
900 LdrpImageEntry
->EntryPointActivationContext
);
904 /* Do TLS callbacks */
905 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_PROCESS_ATTACH
);
907 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
913 /* Deactivate the ActCtx */
914 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
918 /* Restore old TEB */
919 LdrpTopLevelDllBeingLoadedTeb
= OldTldTeb
;
921 /* Check if the array is in the heap */
922 if (LdrRootEntry
!= LocalArray
)
925 RtlFreeHeap(LdrpHeap
, 0, LdrRootEntry
);
928 /* Return to caller */
929 DPRINT("LdrpRunInitializeRoutines() done\n");
938 LdrShutdownProcess(VOID
)
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
;
946 DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry
->BaseDllName
);
947 if (LdrpShutdownInProgress
) return STATUS_SUCCESS
;
949 /* Tell the Shim Engine */
952 VOID(NTAPI
*SE_ProcessDying
)();
953 SE_ProcessDying
= RtlDecodeSystemPointer(g_pfnSE_ProcessDying
);
963 /* Set the shutdown variables */
964 LdrpShutdownThreadId
= NtCurrentTeb()->RealClientId
.UniqueThread
;
965 LdrpShutdownInProgress
= TRUE
;
967 /* Enter the Loader Lock */
968 RtlEnterCriticalSection(&LdrpLoaderLock
);
970 /* Cleanup trace logging data (Etw) */
971 if (SharedUserData
->TraceLogging
)
974 DPRINT1("We don't support Etw yet.\n");
977 /* Start at the end */
978 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
979 NextEntry
= ListHead
->Blink
;
980 while (NextEntry
!= ListHead
)
982 /* Get the current entry */
983 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
984 NextEntry
= NextEntry
->Blink
;
986 /* Make sure it's not ourselves */
987 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
989 /* Get the entrypoint */
990 EntryPoint
= LdrEntry
->EntryPoint
;
992 /* Check if we are ready to call it */
994 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
997 /* Set up the Act Ctx */
998 ActCtx
.Size
= sizeof(ActCtx
);
1000 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1002 /* Activate the ActCtx */
1003 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1004 LdrEntry
->EntryPointActivationContext
);
1008 /* Check if it has TLS */
1009 if (LdrEntry
->TlsIndex
)
1012 LdrpCallTlsInitializers(LdrEntry
, DLL_PROCESS_DETACH
);
1015 /* Call the Entrypoint */
1016 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1017 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1018 LdrpCallInitRoutine(EntryPoint
,
1023 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1025 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_DETACH) for %wZ\n",
1026 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
1030 /* Deactivate the ActCtx */
1031 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1037 if (LdrpImageHasTls
)
1039 /* Set up the Act Ctx */
1040 ActCtx
.Size
= sizeof(ActCtx
);
1042 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1044 /* Activate the ActCtx */
1045 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1046 LdrpImageEntry
->EntryPointActivationContext
);
1050 /* Do TLS callbacks */
1051 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_PROCESS_DETACH
);
1053 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1059 /* Deactivate the ActCtx */
1060 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1063 /* FIXME: Do Heap detection and Etw final shutdown */
1065 /* Release the lock */
1066 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1067 DPRINT("LdrpShutdownProcess() done\n");
1069 return STATUS_SUCCESS
;
1077 LdrShutdownThread(VOID
)
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
;
1086 DPRINT("LdrShutdownThread() called for %wZ\n",
1087 &LdrpImageEntry
->BaseDllName
);
1089 /* Cleanup trace logging data (Etw) */
1090 if (SharedUserData
->TraceLogging
)
1093 DPRINT1("We don't support Etw yet.\n");
1096 /* Get the Ldr Lock */
1097 RtlEnterCriticalSection(&LdrpLoaderLock
);
1099 /* Start at the end */
1100 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
1101 NextEntry
= ListHead
->Blink
;
1102 while (NextEntry
!= ListHead
)
1104 /* Get the current entry */
1105 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
1106 NextEntry
= NextEntry
->Blink
;
1108 /* Make sure it's not ourselves */
1109 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
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
))
1116 /* Get the entrypoint */
1117 EntryPoint
= LdrEntry
->EntryPoint
;
1119 /* Check if we are ready to call it */
1122 /* Set up the Act Ctx */
1123 ActCtx
.Size
= sizeof(ActCtx
);
1125 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1127 /* Activate the ActCtx */
1128 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1129 LdrEntry
->EntryPointActivationContext
);
1133 /* Check if it has TLS */
1134 if (LdrEntry
->TlsIndex
)
1136 /* Make sure we're not shutting down */
1137 if (!LdrpShutdownInProgress
)
1140 LdrpCallTlsInitializers(LdrEntry
, DLL_THREAD_DETACH
);
1144 /* Make sure we're not shutting down */
1145 if (!LdrpShutdownInProgress
)
1147 /* Call the Entrypoint */
1148 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1149 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1150 LdrpCallInitRoutine(EntryPoint
,
1156 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1158 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_DETACH) for %wZ\n",
1159 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
1163 /* Deactivate the ActCtx */
1164 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1171 if (LdrpImageHasTls
)
1173 /* Set up the Act Ctx */
1174 ActCtx
.Size
= sizeof(ActCtx
);
1176 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1178 /* Activate the ActCtx */
1179 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1180 LdrpImageEntry
->EntryPointActivationContext
);
1184 /* Do TLS callbacks */
1185 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_THREAD_DETACH
);
1187 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1193 /* Deactivate the ActCtx */
1194 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1199 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1201 /* Check for expansion slots */
1202 if (Teb
->TlsExpansionSlots
)
1204 /* Free expansion slots */
1205 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->TlsExpansionSlots
);
1208 /* Check for FLS Data */
1211 /* Mimic BaseRundownFls */
1212 ULONG n
, FlsHighIndex
;
1213 PRTL_FLS_DATA pFlsData
;
1214 PFLS_CALLBACK_FUNCTION lpCallback
;
1216 pFlsData
= Teb
->FlsData
;
1218 RtlAcquirePebLock();
1219 FlsHighIndex
= NtCurrentPeb()->FlsHighIndex
;
1220 RemoveEntryList(&pFlsData
->ListEntry
);
1221 RtlReleasePebLock();
1223 for (n
= 1; n
<= FlsHighIndex
; ++n
)
1225 lpCallback
= NtCurrentPeb()->FlsCallback
[n
];
1226 if (lpCallback
&& pFlsData
->Data
[n
])
1228 lpCallback(pFlsData
->Data
[n
]);
1232 RtlFreeHeap(RtlGetProcessHeap(), 0, pFlsData
);
1233 Teb
->FlsData
= NULL
;
1236 /* Check for Fiber data */
1237 if (Teb
->HasFiberData
)
1239 /* Free Fiber data*/
1240 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->NtTib
.FiberData
);
1241 Teb
->NtTib
.FiberData
= NULL
;
1244 /* Free the activation context stack */
1245 RtlFreeThreadActivationContextStack();
1246 DPRINT("LdrShutdownThread() done\n");
1248 return STATUS_SUCCESS
;
1253 LdrpInitializeTls(VOID
)
1255 PLIST_ENTRY NextEntry
, ListHead
;
1256 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1257 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1258 PLDRP_TLS_DATA TlsData
;
1261 /* Initialize the TLS List */
1262 InitializeListHead(&LdrpTlsList
);
1264 /* Loop all the modules */
1265 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1266 NextEntry
= ListHead
->Flink
;
1267 while (ListHead
!= NextEntry
)
1270 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1271 NextEntry
= NextEntry
->Flink
;
1273 /* Get the TLS directory */
1274 TlsDirectory
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
1276 IMAGE_DIRECTORY_ENTRY_TLS
,
1279 /* Check if we have a directory */
1280 if (!TlsDirectory
) continue;
1282 /* Check if the image has TLS */
1283 if (!LdrpImageHasTls
) LdrpImageHasTls
= TRUE
;
1285 /* Show debug message */
1288 DPRINT1("LDR: Tls Found in %wZ at %p\n",
1289 &LdrEntry
->BaseDllName
,
1293 /* Allocate an entry */
1294 TlsData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA
));
1295 if (!TlsData
) return STATUS_NO_MEMORY
;
1297 /* Lock the DLL and mark it for TLS Usage */
1298 LdrEntry
->LoadCount
= -1;
1299 LdrEntry
->TlsIndex
= -1;
1301 /* Save the cached TLS data */
1302 TlsData
->TlsDirectory
= *TlsDirectory
;
1303 InsertTailList(&LdrpTlsList
, &TlsData
->TlsLinks
);
1305 /* Update the index */
1306 *(PLONG
)TlsData
->TlsDirectory
.AddressOfIndex
= LdrpNumberOfTlsEntries
;
1307 TlsData
->TlsDirectory
.Characteristics
= LdrpNumberOfTlsEntries
++;
1310 /* Done setting up TLS, allocate entries */
1311 return LdrpAllocateTls();
1316 LdrpAllocateTls(VOID
)
1318 PTEB Teb
= NtCurrentTeb();
1319 PLIST_ENTRY NextEntry
, ListHead
;
1320 PLDRP_TLS_DATA TlsData
;
1324 /* Check if we have any entries */
1325 if (!LdrpNumberOfTlsEntries
)
1326 return STATUS_SUCCESS
;
1328 /* Allocate the vector array */
1329 TlsVector
= RtlAllocateHeap(RtlGetProcessHeap(),
1331 LdrpNumberOfTlsEntries
* sizeof(PVOID
));
1332 if (!TlsVector
) return STATUS_NO_MEMORY
;
1333 Teb
->ThreadLocalStoragePointer
= TlsVector
;
1335 /* Loop the TLS Array */
1336 ListHead
= &LdrpTlsList
;
1337 NextEntry
= ListHead
->Flink
;
1338 while (NextEntry
!= ListHead
)
1341 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1342 NextEntry
= NextEntry
->Flink
;
1344 /* Allocate this vector */
1345 TlsDataSize
= TlsData
->TlsDirectory
.EndAddressOfRawData
-
1346 TlsData
->TlsDirectory
.StartAddressOfRawData
;
1347 TlsVector
[TlsData
->TlsDirectory
.Characteristics
] = RtlAllocateHeap(RtlGetProcessHeap(),
1350 if (!TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1353 return STATUS_NO_MEMORY
;
1356 /* Show debug message */
1359 DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
1361 TlsData
->TlsDirectory
.Characteristics
,
1362 &TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1363 TlsData
->TlsDirectory
.StartAddressOfRawData
,
1364 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1368 RtlCopyMemory(TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1369 (PVOID
)TlsData
->TlsDirectory
.StartAddressOfRawData
,
1374 return STATUS_SUCCESS
;
1381 PLIST_ENTRY ListHead
, NextEntry
;
1382 PLDRP_TLS_DATA TlsData
;
1384 PTEB Teb
= NtCurrentTeb();
1386 /* Get a pointer to the vector array */
1387 TlsVector
= Teb
->ThreadLocalStoragePointer
;
1388 if (!TlsVector
) return;
1390 /* Loop through it */
1391 ListHead
= &LdrpTlsList
;
1392 NextEntry
= ListHead
->Flink
;
1393 while (NextEntry
!= ListHead
)
1395 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1396 NextEntry
= NextEntry
->Flink
;
1398 /* Free each entry */
1399 if (TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1401 RtlFreeHeap(RtlGetProcessHeap(),
1403 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1407 /* Free the array itself */
1408 RtlFreeHeap(RtlGetProcessHeap(),
1415 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName
, PPEB Peb
, PHANDLE OptionsKey
)
1419 ULONG ExecuteOptions
, MinimumStackCommit
= 0, GlobalFlag
;
1421 /* Return error if we were not provided a pointer where to save the options key handle */
1422 if (!OptionsKey
) return STATUS_INVALID_HANDLE
;
1424 /* Zero initialize the options key pointer */
1427 /* Open the options key */
1428 Status
= LdrOpenImageFileOptionsKey(ImagePathName
, 0, &KeyHandle
);
1430 /* Save it if it was opened successfully */
1431 if (NT_SUCCESS(Status
))
1432 *OptionsKey
= KeyHandle
;
1436 /* There are image specific options, read them starting with NXCOMPAT */
1437 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1441 sizeof(ExecuteOptions
),
1444 if (NT_SUCCESS(Status
))
1446 /* TODO: Set execution options for the process */
1448 if (ExecuteOptions == 0)
1452 ZwSetInformationProcess(NtCurrentProcess(),
1453 ProcessExecuteFlags,
1459 /* Check if this image uses large pages */
1460 if (Peb
->ImageUsesLargePages
)
1462 /* TODO: If it does, open large page key */
1466 /* Get various option values */
1467 LdrQueryImageFileKeyOption(KeyHandle
,
1468 L
"DisableHeapLookaside",
1470 &RtlpDisableHeapLookaside
,
1471 sizeof(RtlpDisableHeapLookaside
),
1474 LdrQueryImageFileKeyOption(KeyHandle
,
1477 &RtlpShutdownProcessFlags
,
1478 sizeof(RtlpShutdownProcessFlags
),
1481 LdrQueryImageFileKeyOption(KeyHandle
,
1482 L
"MinimumStackCommitInBytes",
1484 &MinimumStackCommit
,
1485 sizeof(MinimumStackCommit
),
1488 /* Update PEB's minimum stack commit if it's lower */
1489 if (Peb
->MinimumStackCommit
< MinimumStackCommit
)
1490 Peb
->MinimumStackCommit
= MinimumStackCommit
;
1492 /* Set the global flag */
1493 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1500 if (NT_SUCCESS(Status
))
1501 Peb
->NtGlobalFlag
= GlobalFlag
;
1505 /* Call AVRF if necessary */
1506 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1508 Status
= LdrpInitializeApplicationVerifierPackage(KeyHandle
, Peb
, TRUE
, FALSE
);
1509 if (!NT_SUCCESS(Status
))
1511 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1517 /* There are no image-specific options, so perform global initialization */
1518 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1520 /* Initialize app verifier package */
1521 Status
= LdrpInitializeApplicationVerifierPackage(KeyHandle
, Peb
, TRUE
, FALSE
);
1522 if (!NT_SUCCESS(Status
))
1524 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1529 return STATUS_SUCCESS
;
1534 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
)
1541 LdrpInitializeProcessCompat(PVOID
* pOldShimData
)
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
};
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
;
1552 ReactOS_ShimData
* pShimData
= *pOldShimData
;
1554 C_ASSERT(RTL_NUMBER_OF(GuidOrder
) == RTL_NUMBER_OF(GuidVersions
));
1558 if (pShimData
->dwMagic
!= REACTOS_SHIMDATA_MAGIC
||
1559 pShimData
->dwSize
!= sizeof(ReactOS_ShimData
))
1561 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData
->dwMagic
, pShimData
->dwSize
);
1564 if (pShimData
->dwRosProcessCompatVersion
)
1566 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData
->dwRosProcessCompatVersion
);
1571 SizeRequired
= sizeof(Buffer
);
1572 Status
= RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
,
1575 CompatibilityInformationInActivationContext
,
1580 if (!NT_SUCCESS(Status
))
1582 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status
);
1586 ContextCompatInfo
= (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
*)Buffer
;
1587 /* No Compatibility elements present, bail out */
1588 if (ContextCompatInfo
->ElementCount
== 0)
1591 /* Search for known GUID's, starting from newest to oldest. */
1592 for (cur
= 0; cur
< RTL_NUMBER_OF(GuidOrder
); ++cur
)
1594 for (n
= 0; n
< ContextCompatInfo
->ElementCount
; ++n
)
1596 if (ContextCompatInfo
->Elements
[n
].Type
== ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
&&
1597 RtlCompareMemory(&ContextCompatInfo
->Elements
[n
].Id
, GuidOrder
[cur
], sizeof(GUID
)) == sizeof(GUID
))
1599 /* If this process did not need shim data before, allocate and store it */
1600 if (pShimData
== NULL
)
1602 PPEB Peb
= NtCurrentPeb();
1604 ASSERT(Peb
->pShimData
== NULL
);
1605 pShimData
= RtlAllocateHeap(Peb
->ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(*pShimData
));
1609 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData
));
1613 pShimData
->dwSize
= sizeof(*pShimData
);
1614 pShimData
->dwMagic
= REACTOS_SHIMDATA_MAGIC
;
1616 Peb
->pShimData
= pShimData
;
1617 *pOldShimData
= pShimData
;
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
]);
1632 LdrpInitializeProcess(IN PCONTEXT Context
,
1633 IN PVOID SystemArgument1
)
1635 RTL_HEAP_PARAMETERS HeapParameters
;
1636 ULONG ComSectionSize
;
1637 ANSI_STRING BaseProcessInitPostImportName
= RTL_CONSTANT_STRING("BaseProcessInitPostImport");
1638 ANSI_STRING BaseQueryModuleDataName
= RTL_CONSTANT_STRING("BaseQueryModuleData");
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
;
1649 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1650 //LPWSTR ImagePathBuffer;
1652 UNICODE_STRING CurrentDirectory
;
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
;
1665 ULONG DebugProcessHeapOnly
= 0;
1666 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
1668 ULONG ExecuteOptions
= 0;
1671 /* Set a NULL SEH Filter */
1672 RtlSetUnhandledExceptionFilter(NULL
);
1674 /* Get the image path */
1675 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
1677 /* Check if it's not normalized */
1678 if (!(Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
))
1681 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
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
;
1689 /* Get the NT Headers */
1690 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
1692 /* Get the execution options */
1693 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &OptionsKey
);
1695 /* Check if this is a .NET executable */
1696 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1698 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
1701 /* Remember this for later */
1702 IsDotNetImage
= TRUE
;
1705 /* Save the NTDLL Base address */
1706 NtDllBase
= SystemArgument1
;
1708 /* If this is a Native Image */
1709 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
1711 /* Then do DLL Validation */
1712 LdrpDllValidation
= TRUE
;
1715 /* Save the old Shim Data */
1716 OldShimData
= Peb
->pShimData
;
1718 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */
1719 //Peb->pShimData = NULL;
1721 /* Save the number of processors and CS Timeout */
1722 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
1723 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
1725 /* Normalize the parameters */
1726 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
1727 if (ProcessParameters
)
1729 /* Save the Image and Command Line Names */
1730 ImageFileName
= ProcessParameters
->ImagePathName
;
1731 CommandLine
= ProcessParameters
->CommandLine
;
1735 /* It failed, initialize empty strings */
1736 RtlInitUnicodeString(&ImageFileName
, NULL
);
1737 RtlInitUnicodeString(&CommandLine
, NULL
);
1740 /* Initialize NLS data */
1741 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1742 Peb
->OemCodePageData
,
1743 Peb
->UnicodeCaseTableData
,
1746 /* Reset NLS Translations */
1747 RtlResetRtlTranslations(&NlsTable
);
1749 /* Get the Image Config Directory */
1750 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1752 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1755 /* Setup the Heap Parameters */
1756 RtlZeroMemory(&HeapParameters
, sizeof(HeapParameters
));
1757 HeapFlags
= HEAP_GROWABLE
;
1758 HeapParameters
.Length
= sizeof(HeapParameters
);
1760 /* Check if we have Configuration Data */
1761 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1763 /* FIXME: Custom heap settings and misc. */
1764 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1767 /* Check for custom affinity mask */
1768 if (Peb
->ImageProcessAffinityMask
)
1771 Status
= NtSetInformationProcess(NtCurrentProcess(),
1772 ProcessAffinityMask
,
1773 &Peb
->ImageProcessAffinityMask
,
1774 sizeof(Peb
->ImageProcessAffinityMask
));
1777 /* Check if verbose debugging (ShowSnaps) was requested */
1778 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1780 /* Start verbose debugging messages right now if they were requested */
1783 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1784 Teb
->ClientId
.UniqueProcess
,
1788 /* If the timeout is too long */
1789 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1791 /* Then disable CS Timeout */
1792 RtlpTimeoutDisable
= TRUE
;
1795 /* Initialize Critical Section Data */
1796 RtlpInitDeferedCriticalSection();
1798 /* Initialize VEH Call lists */
1799 RtlpInitializeVectoredExceptionHandling();
1801 /* Set TLS/FLS Bitmap data */
1802 Peb
->FlsBitmap
= &FlsBitMap
;
1803 Peb
->TlsBitmap
= &TlsBitMap
;
1804 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1806 /* Initialize FLS Bitmap */
1807 RtlInitializeBitMap(&FlsBitMap
,
1809 FLS_MAXIMUM_AVAILABLE
);
1810 RtlSetBit(&FlsBitMap
, 0);
1811 InitializeListHead(&Peb
->FlsListHead
);
1813 /* Initialize TLS Bitmap */
1814 RtlInitializeBitMap(&TlsBitMap
,
1816 TLS_MINIMUM_AVAILABLE
);
1817 RtlSetBit(&TlsBitMap
, 0);
1818 RtlInitializeBitMap(&TlsExpansionBitMap
,
1819 Peb
->TlsExpansionBitmapBits
,
1820 TLS_EXPANSION_SLOTS
);
1821 RtlSetBit(&TlsExpansionBitMap
, 0);
1823 /* Initialize the Hash Table */
1824 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1826 InitializeListHead(&LdrpHashTable
[i
]);
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
;
1837 /* Check if User Stack Trace Database support was requested */
1838 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1840 DPRINT1("We don't support user stack trace databases yet\n");
1843 /* Setup Fast PEB Lock */
1844 RtlInitializeCriticalSection(&FastPebLock
);
1845 Peb
->FastPebLock
= &FastPebLock
;
1846 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1847 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1849 /* Setup Callout Lock and Notification list */
1850 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1851 InitializeListHead(&LdrpDllNotificationList
);
1853 /* For old executables, use 16-byte aligned heap */
1854 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1855 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1857 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1860 /* Setup the Heap */
1861 RtlInitializeHeapManager();
1862 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1864 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1865 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1869 if (!Peb
->ProcessHeap
)
1871 DPRINT1("Failed to create process heap\n");
1872 return STATUS_NO_MEMORY
;
1875 /* Allocate an Activation Context Stack */
1876 Status
= RtlAllocateActivationContextStack(&Teb
->ActivationContextStackPointer
);
1877 if (!NT_SUCCESS(Status
)) return Status
;
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
);
1885 DPRINT1("Failed to create loader private heap\n");
1886 return STATUS_NO_MEMORY
;
1889 /* Check for Debug Heap */
1892 /* Query the setting */
1893 Status
= LdrQueryImageFileKeyOption(OptionsKey
,
1894 L
"DebugProcessHeapOnly",
1896 &DebugProcessHeapOnly
,
1900 if (NT_SUCCESS(Status
))
1902 /* Reset DPH if requested */
1903 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1905 RtlpDphGlobalFlags
&= ~DPH_FLAG_DLL_NOTIFY
;
1906 RtlpPageHeapEnabled
= FALSE
;
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\\");
1919 /* Open the Known DLLs directory */
1920 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1921 InitializeObjectAttributes(&ObjectAttributes
,
1923 OBJ_CASE_INSENSITIVE
,
1926 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
1927 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
1930 /* Check if it exists */
1931 if (NT_SUCCESS(Status
))
1933 /* Open the Known DLLs Path */
1934 RtlInitUnicodeString(&KnownDllString
, L
"KnownDllPath");
1935 InitializeObjectAttributes(&ObjectAttributes
,
1937 OBJ_CASE_INSENSITIVE
,
1938 LdrpKnownDllObjectDirectory
,
1940 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
1941 SYMBOLIC_LINK_QUERY
,
1943 if (NT_SUCCESS(Status
))
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
))
1953 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
1959 /* Check if we failed */
1960 if (!NT_SUCCESS(Status
))
1962 /* Assume System32 */
1963 LdrpKnownDllObjectDirectory
= NULL
;
1964 RtlInitUnicodeString(&LdrpKnownDllPath
, StringBuffer
);
1965 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
1968 /* If we have process parameters, get the default path and current path */
1969 if (ProcessParameters
)
1971 /* Check if we have a Dll Path */
1972 if (ProcessParameters
->DllPath
.Length
)
1975 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
1979 /* We need a valid path */
1980 DPRINT1("No valid DllPath was given!\n");
1981 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
1984 /* Set the current directory */
1985 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
1987 /* Check if it's empty or invalid */
1988 if ((!CurrentDirectory
.Buffer
) ||
1989 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
1990 (!CurrentDirectory
.Length
))
1992 /* Allocate space for the buffer */
1993 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
1996 sizeof(UNICODE_NULL
));
1997 if (!CurrentDirectory
.Buffer
)
1999 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
2003 /* Copy the drive of the system root */
2004 RtlMoveMemory(CurrentDirectory
.Buffer
,
2005 SharedUserData
->NtSystemRoot
,
2007 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
2008 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
2009 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
2012 DPRINT("Using dynamically allocd curdir\n");
2016 /* Use the local buffer */
2017 DPRINT("Using local system root\n");
2021 /* Setup Loader Data */
2023 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
2024 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
2025 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
2026 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
2027 PebLdr
.Initialized
= TRUE
;
2029 /* Allocate a data entry for the Image */
2030 LdrpImageEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
2033 LdrpImageEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(LdrpImageEntry
->DllBase
);
2034 LdrpImageEntry
->LoadCount
= -1;
2035 LdrpImageEntry
->EntryPointActivationContext
= 0;
2036 LdrpImageEntry
->FullDllName
= ImageFileName
;
2039 LdrpImageEntry
->Flags
= LDRP_COR_IMAGE
;
2041 LdrpImageEntry
->Flags
= 0;
2043 /* Check if the name is empty */
2044 if (!ImageFileName
.Buffer
[0])
2046 /* Use the same Base name */
2047 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
2051 /* Find the last slash */
2052 Current
= ImageFileName
.Buffer
;
2055 if (*Current
++ == '\\')
2058 NtDllName
= Current
;
2062 /* Did we find anything? */
2065 /* Use the same Base name */
2066 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
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
));
2078 /* Processing done, insert it */
2079 LdrpInsertMemoryTableEntry(LdrpImageEntry
);
2080 LdrpImageEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
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;
2089 NtLdrEntry
->FullDllName
.Length
= FullPath
.Length
;
2090 NtLdrEntry
->FullDllName
.MaximumLength
= FullPath
.MaximumLength
;
2091 NtLdrEntry
->FullDllName
.Buffer
= StringBuffer
;
2092 RtlAppendUnicodeStringToString(&NtLdrEntry
->FullDllName
, &NtDllString
);
2094 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
2095 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
2096 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
2098 /* Processing done, insert it */
2099 LdrpNtDllDataTableEntry
= NtLdrEntry
;
2100 LdrpInsertMemoryTableEntry(NtLdrEntry
);
2102 /* Let the world know */
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
);
2111 /* Link the Init Order List */
2112 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
2113 &LdrpNtDllDataTableEntry
->InInitializationOrderLinks
);
2115 /* Initialize Wine's active context implementation for the current process */
2118 /* ReactOS specific */
2119 LdrpInitializeProcessCompat(&OldShimData
);
2121 /* Set the current directory */
2122 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
2123 if (!NT_SUCCESS(Status
))
2125 /* We failed, check if we should free it */
2126 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2128 /* Set it to the NT Root */
2129 CurrentDirectory
= NtSystemRoot
;
2130 RtlSetCurrentDirectory_U(&CurrentDirectory
);
2134 /* We're done with it, free it */
2135 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2138 /* Check if we should look for a .local file */
2139 if (ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
)
2142 DPRINT1("We don't support .local overrides yet\n");
2145 /* Check if the Application Verifier was enabled */
2146 if (Peb
->NtGlobalFlag
& FLG_APPLICATION_VERIFIER
)
2148 Status
= AVrfInitializeVerifier();
2149 if (!NT_SUCCESS(Status
))
2151 DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status
);
2160 DPRINT1("We don't support .NET applications yet\n");
2163 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
||
2164 NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_CUI
)
2166 PVOID Kernel32BaseAddress
;
2167 PVOID FunctionAddress
;
2169 Status
= LdrLoadDll(NULL
, NULL
, &Kernel32String
, &Kernel32BaseAddress
);
2171 if (!NT_SUCCESS(Status
))
2174 DPRINT1("LDR: Unable to load %wZ, Status=0x%08lx\n", &Kernel32String
, Status
);
2178 Status
= LdrGetProcedureAddress(Kernel32BaseAddress
,
2179 &BaseProcessInitPostImportName
,
2183 if (!NT_SUCCESS(Status
))
2186 DPRINT1("LDR: Unable to find post-import process init function, Status=0x%08lx\n", &Kernel32String
, Status
);
2189 Kernel32ProcessInitPostImportFunction
= FunctionAddress
;
2191 Status
= LdrGetProcedureAddress(Kernel32BaseAddress
,
2192 &BaseQueryModuleDataName
,
2196 if (!NT_SUCCESS(Status
))
2199 DPRINT1("LDR: Unable to find BaseQueryModuleData, Status=0x%08lx\n", &Kernel32String
, Status
);
2202 Kernel32BaseQueryModuleData
= FunctionAddress
;
2205 /* Walk the IAT and load all the DLLs */
2206 ImportStatus
= LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
2208 /* Check if relocation is needed */
2209 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
2211 DPRINT1("LDR: Performing EXE relocation\n");
2213 /* Change the protection to prepare for relocation */
2214 ViewBase
= Peb
->ImageBaseAddress
;
2215 Status
= LdrpSetProtection(ViewBase
, FALSE
);
2216 if (!NT_SUCCESS(Status
)) return Status
;
2218 /* Do the relocation */
2219 Status
= LdrRelocateImageWithBias(ViewBase
,
2223 STATUS_CONFLICTING_ADDRESSES
,
2224 STATUS_INVALID_IMAGE_FORMAT
);
2225 if (!NT_SUCCESS(Status
))
2227 DPRINT1("LdrRelocateImageWithBias() failed\n");
2231 /* Check if a start context was provided */
2234 DPRINT1("WARNING: Relocated EXE Context");
2235 UNIMPLEMENTED
; // We should support this
2236 return STATUS_INVALID_IMAGE_FORMAT
;
2239 /* Restore the protection */
2240 Status
= LdrpSetProtection(ViewBase
, TRUE
);
2241 if (!NT_SUCCESS(Status
)) return Status
;
2245 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
2246 NextEntry
= ListHead
->Flink
;
2247 while (ListHead
!= NextEntry
)
2249 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2250 NtLdrEntry
->LoadCount
= -1;
2251 NextEntry
= NextEntry
->Flink
;
2254 /* Phase 0 is done */
2255 LdrpLdrDatabaseIsSetup
= TRUE
;
2257 /* Check whether all static imports were properly loaded and return here */
2258 if (!NT_SUCCESS(ImportStatus
)) return ImportStatus
;
2260 /* Initialize TLS */
2261 Status
= LdrpInitializeTls();
2262 if (!NT_SUCCESS(Status
))
2264 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2269 /* FIXME Mark the DLL Ranges for Stack Traces later */
2271 /* Notify the debugger now */
2272 if (Peb
->BeingDebugged
)
2277 /* Update show snaps again */
2278 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
2281 /* Validate the Image for MP Usage */
2282 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
2284 /* Check NX Options */
2285 if (SharedUserData
->NXSupportPolicy
== 1)
2287 ExecuteOptions
= 0xD;
2289 else if (!SharedUserData
->NXSupportPolicy
)
2291 ExecuteOptions
= 0xA;
2295 ZwSetInformationProcess(NtCurrentProcess(),
2296 ProcessExecuteFlags
,
2300 // FIXME: Should be done by Application Compatibility features,
2301 // by reading the registry, etc...
2302 // For now, this is the old code from ntdll!RtlGetVersion().
2303 RtlInitEmptyUnicodeString(&Peb
->CSDVersion
, NULL
, 0);
2304 if (((Peb
->OSCSDVersion
>> 8) & 0xFF) != 0)
2306 WCHAR szCSDVersion
[128];
2308 ULONG Length
= ARRAYSIZE(szCSDVersion
) - 1;
2309 i
= _snwprintf(szCSDVersion
, Length
,
2311 ((Peb
->OSCSDVersion
>> 8) & 0xFF));
2314 /* Null-terminate if it was overflowed */
2315 szCSDVersion
[Length
] = UNICODE_NULL
;
2318 Length
*= sizeof(WCHAR
);
2319 Peb
->CSDVersion
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
2321 Length
+ sizeof(UNICODE_NULL
));
2322 if (Peb
->CSDVersion
.Buffer
)
2324 Peb
->CSDVersion
.Length
= Length
;
2325 Peb
->CSDVersion
.MaximumLength
= Length
+ sizeof(UNICODE_NULL
);
2327 RtlCopyMemory(Peb
->CSDVersion
.Buffer
,
2329 Peb
->CSDVersion
.MaximumLength
);
2330 Peb
->CSDVersion
.Buffer
[Peb
->CSDVersion
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2334 /* Check if we had Shim Data */
2337 /* Load the Shim Engine */
2338 Peb
->AppCompatInfo
= NULL
;
2339 LdrpLoadShimEngine(OldShimData
, &ImagePathName
, OldShimData
);
2343 /* Check for Application Compatibility Goo */
2344 //LdrQueryApplicationCompatibilityGoo(hKey);
2345 DPRINT("Querying app compat hacks is missing!\n");
2349 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2350 * incompatible images.
2353 /* Now call the Init Routines */
2354 Status
= LdrpRunInitializeRoutines(Context
);
2355 if (!NT_SUCCESS(Status
))
2357 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2362 /* Notify Shim Engine */
2365 VOID(NTAPI
*SE_InstallAfterInit
)(PUNICODE_STRING
, PVOID
);
2366 SE_InstallAfterInit
= RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit
);
2367 SE_InstallAfterInit(&ImagePathName
, OldShimData
);
2370 /* Check if we have a user-defined Post Process Routine */
2371 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
2374 Peb
->PostProcessInitRoutine();
2377 /* Close the key if we have one opened */
2378 if (OptionsKey
) NtClose(OptionsKey
);
2386 LdrpInitFailure(NTSTATUS Status
)
2389 PPEB Peb
= NtCurrentPeb();
2391 /* Print a debug message */
2392 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2393 &Peb
->ProcessParameters
->ImagePathName
, Status
);
2395 /* Raise a hard error */
2396 if (!LdrpFatalHardErrorCount
)
2398 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
2404 LdrpInit(PCONTEXT Context
,
2405 PVOID SystemArgument1
,
2406 PVOID SystemArgument2
)
2408 LARGE_INTEGER Timeout
;
2409 PTEB Teb
= NtCurrentTeb();
2410 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
2411 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
2412 PPEB Peb
= NtCurrentPeb();
2414 DPRINT("LdrpInit() %p/%p\n",
2415 NtCurrentTeb()->RealClientId
.UniqueProcess
,
2416 NtCurrentTeb()->RealClientId
.UniqueThread
);
2419 /* Set the SList header usage */
2420 RtlpUse16ByteSLists
= SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE128
];
2423 /* Check if we have a deallocation stack */
2424 if (!Teb
->DeallocationStack
)
2426 /* We don't, set one */
2427 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
2428 Teb
->NtTib
.StackLimit
,
2429 MemoryBasicInformation
,
2431 sizeof(MEMORY_BASIC_INFORMATION
),
2433 if (!NT_SUCCESS(Status
))
2436 LdrpInitFailure(Status
);
2437 RtlRaiseStatus(Status
);
2442 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
2445 /* Now check if the process is already being initialized */
2446 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
2450 /* Set the timeout to 30 milliseconds */
2451 Timeout
.QuadPart
= Int32x32To64(30, -10000);
2453 /* Make sure the status hasn't changed */
2454 while (LdrpProcessInitialized
== 1)
2457 ZwDelayExecution(FALSE
, &Timeout
);
2461 /* Check if we have already setup LDR data */
2464 /* Setup the Loader Lock */
2465 Peb
->LoaderLock
= &LdrpLoaderLock
;
2467 /* Let other code know we're initializing */
2468 LdrpInLdrInit
= TRUE
;
2470 /* Protect with SEH */
2473 /* Initialize the Process */
2474 LoaderStatus
= LdrpInitializeProcess(Context
,
2477 /* Check for success and if MinimumStackCommit was requested */
2478 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
2480 /* Enforce the limit */
2481 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2485 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2487 /* Fail with the SEH error */
2488 LoaderStatus
= _SEH2_GetExceptionCode();
2492 /* We're not initializing anymore */
2493 LdrpInLdrInit
= FALSE
;
2495 /* Check if init worked */
2496 if (NT_SUCCESS(LoaderStatus
))
2498 /* Set the process as Initialized */
2499 _InterlockedIncrement(&LdrpProcessInitialized
);
2504 /* Loader data is there... is this a fork() ? */
2505 if(Peb
->InheritedAddressSpace
)
2507 /* Handle the fork() */
2508 //LoaderStatus = LdrpForkProcess();
2509 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
2514 /* This is a new thread initializing */
2515 LdrpInitializeThread(Context
);
2519 /* All done, test alert the thread */
2523 if (!NT_SUCCESS(LoaderStatus
))
2526 LdrpInitFailure(LoaderStatus
);
2527 RtlRaiseStatus(LoaderStatus
);