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
;
58 LIST_ENTRY LdrpHashTable
[LDR_HASH_TABLE_ENTRIES
];
59 LIST_ENTRY LdrpDllNotificationList
;
60 HANDLE LdrpKnownDllObjectDirectory
;
61 UNICODE_STRING LdrpKnownDllPath
;
62 WCHAR LdrpKnownDllPathBuffer
[128];
63 UNICODE_STRING LdrpDefaultPath
;
67 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug
;
68 RTL_CRITICAL_SECTION LdrpLoaderLock
=
77 RTL_CRITICAL_SECTION FastPebLock
;
81 ULONG LdrpFatalHardErrorCount
;
82 ULONG LdrpActiveUnloadCount
;
84 //extern LIST_ENTRY RtlCriticalSectionList;
86 VOID NTAPI
RtlpInitializeVectoredExceptionHandling(VOID
);
87 VOID NTAPI
RtlpInitDeferedCriticalSection(VOID
);
88 VOID NTAPI
RtlInitializeHeapManager(VOID
);
90 ULONG RtlpDisableHeapLookaside
; // TODO: Move to heap.c
91 ULONG RtlpShutdownProcessFlags
; // TODO: Use it
93 NTSTATUS
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
, PVOID ImageBase
);
94 void actctx_init(void);
95 extern BOOLEAN RtlpUse16ByteSLists
;
98 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
100 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E
103 /* FUNCTIONS *****************************************************************/
110 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey
,
112 OUT PHANDLE NewKeyHandle
)
114 PHANDLE RootKeyLocation
;
116 UNICODE_STRING SubKeyString
;
117 OBJECT_ATTRIBUTES ObjectAttributes
;
121 /* Check which root key to open */
123 RootKeyLocation
= &Wow64ExecOptionsKey
;
125 RootKeyLocation
= &ImageExecOptionsKey
;
127 /* Get the current key */
128 RootKey
= *RootKeyLocation
;
130 /* Setup the object attributes */
131 InitializeObjectAttributes(&ObjectAttributes
,
133 &Wow64OptionsString
: &ImageExecOptionsString
,
134 OBJ_CASE_INSENSITIVE
,
138 /* Open the root key */
139 Status
= ZwOpenKey(&RootKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
140 if (NT_SUCCESS(Status
))
142 /* Write the key handle */
143 if (InterlockedCompareExchangePointer(RootKeyLocation
, RootKey
, NULL
) != NULL
)
145 /* Someone already opened it, use it instead */
147 RootKey
= *RootKeyLocation
;
150 /* Extract the name */
151 SubKeyString
= *SubKey
;
152 p1
= (PWCHAR
)((ULONG_PTR
)SubKeyString
.Buffer
+ SubKeyString
.Length
);
153 while (SubKeyString
.Length
)
155 if (p1
[-1] == L
'\\') break;
157 SubKeyString
.Length
-= sizeof(*p1
);
159 SubKeyString
.Buffer
= p1
;
160 SubKeyString
.Length
= SubKey
->Length
- SubKeyString
.Length
;
162 /* Setup the object attributes */
163 InitializeObjectAttributes(&ObjectAttributes
,
165 OBJ_CASE_INSENSITIVE
,
169 /* Open the setting key */
170 Status
= ZwOpenKey((PHANDLE
)NewKeyHandle
, GENERIC_READ
, &ObjectAttributes
);
173 /* Return to caller */
182 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle
,
187 OUT PULONG ReturnedLength OPTIONAL
)
190 UNICODE_STRING ValueNameString
, IntegerString
;
191 ULONG KeyInfoSize
, ResultSize
;
192 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)&KeyInfo
;
193 BOOLEAN FreeHeap
= FALSE
;
196 /* Build a string for the value name */
197 Status
= RtlInitUnicodeStringEx(&ValueNameString
, ValueName
);
198 if (!NT_SUCCESS(Status
)) return Status
;
200 /* Query the value */
201 Status
= ZwQueryValueKey(KeyHandle
,
203 KeyValuePartialInformation
,
207 if (Status
== STATUS_BUFFER_OVERFLOW
)
209 /* Our local buffer wasn't enough, allocate one */
210 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
211 KeyValueInformation
->DataLength
;
212 KeyValueInformation
= RtlAllocateHeap(RtlGetProcessHeap(),
215 if (KeyValueInformation
!= NULL
)
218 Status
= ZwQueryValueKey(KeyHandle
,
220 KeyValuePartialInformation
,
228 /* Give up this time */
229 Status
= STATUS_NO_MEMORY
;
233 /* Check for success */
234 if (NT_SUCCESS(Status
))
236 /* Handle binary data */
237 if (KeyValueInformation
->Type
== REG_BINARY
)
240 if ((Buffer
) && (KeyValueInformation
->DataLength
<= BufferSize
))
242 /* Copy into buffer */
243 RtlMoveMemory(Buffer
,
244 &KeyValueInformation
->Data
,
245 KeyValueInformation
->DataLength
);
249 Status
= STATUS_BUFFER_OVERFLOW
;
252 /* Copy the result length */
253 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
255 else if (KeyValueInformation
->Type
== REG_DWORD
)
257 /* Check for valid type */
258 if (KeyValueInformation
->Type
!= Type
)
261 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
267 (BufferSize
== sizeof(ULONG
)) &&
268 (KeyValueInformation
->DataLength
<= BufferSize
))
270 /* Copy into buffer */
271 RtlMoveMemory(Buffer
,
272 &KeyValueInformation
->Data
,
273 KeyValueInformation
->DataLength
);
277 Status
= STATUS_BUFFER_OVERFLOW
;
280 /* Copy the result length */
281 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
284 else if (KeyValueInformation
->Type
!= REG_SZ
)
286 /* We got something weird */
287 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
291 /* String, check what you requested */
292 if (Type
== REG_DWORD
)
295 if (BufferSize
!= sizeof(ULONG
))
299 Status
= STATUS_INFO_LENGTH_MISMATCH
;
303 /* OK, we know what you want... */
304 IntegerString
.Buffer
= (PWSTR
)KeyValueInformation
->Data
;
305 IntegerString
.Length
= (USHORT
)KeyValueInformation
->DataLength
-
307 IntegerString
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
308 Status
= RtlUnicodeStringToInteger(&IntegerString
, 0, (PULONG
)Buffer
);
314 if (KeyValueInformation
->DataLength
> BufferSize
)
317 Status
= STATUS_BUFFER_OVERFLOW
;
322 BufferSize
= KeyValueInformation
->DataLength
;
325 /* Copy the string */
326 RtlMoveMemory(Buffer
, &KeyValueInformation
->Data
, BufferSize
);
329 /* Copy the result length */
330 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
334 /* Check if buffer was in heap */
335 if (FreeHeap
) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation
);
346 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey
,
351 OUT PULONG ReturnedLength OPTIONAL
,
357 /* Open a handle to the key */
358 Status
= LdrOpenImageFileOptionsKey(SubKey
, Wow64
, &KeyHandle
);
360 /* Check for success */
361 if (NT_SUCCESS(Status
))
364 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
375 /* Return to caller */
384 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey
,
389 OUT PULONG ReturnedLength OPTIONAL
)
391 /* Call the newer function */
392 return LdrQueryImageFileExecutionOptionsEx(SubKey
,
403 LdrpEnsureLoaderLockIsHeld(VOID
)
410 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress
, ULONG SizeOfImage
)
412 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir
;
416 /* Check NT header first */
417 if (!RtlImageNtHeader(BaseAddress
)) return NULL
;
419 /* Get the pointer to the config directory */
420 ConfigDir
= RtlImageDirectoryEntryToData(BaseAddress
,
422 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
425 /* Check for sanity */
427 (DirSize
!= 64 && ConfigDir
->Size
!= DirSize
) ||
428 (ConfigDir
->Size
< 0x48))
431 /* Now get the cookie */
432 Cookie
= (PVOID
)ConfigDir
->SecurityCookie
;
434 /* Check this cookie */
435 if ((PCHAR
)Cookie
<= (PCHAR
)BaseAddress
||
436 (PCHAR
)Cookie
>= (PCHAR
)BaseAddress
+ SizeOfImage
)
441 /* Return validated security cookie */
447 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry
)
450 LARGE_INTEGER Counter
;
453 /* Fetch address of the cookie */
454 Cookie
= LdrpFetchAddressOfSecurityCookie(LdrEntry
->DllBase
, LdrEntry
->SizeOfImage
);
458 /* Check if it's a default one */
459 if ((*Cookie
== DEFAULT_SECURITY_COOKIE
) ||
462 /* Make up a cookie from a bunch of values which may uniquely represent
463 current moment of time, environment, etc */
464 NtQueryPerformanceCounter(&Counter
, NULL
);
466 NewCookie
= Counter
.LowPart
^ Counter
.HighPart
;
467 NewCookie
^= (ULONG_PTR
)NtCurrentTeb()->ClientId
.UniqueProcess
;
468 NewCookie
^= (ULONG_PTR
)NtCurrentTeb()->ClientId
.UniqueThread
;
470 /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */
471 while (SharedUserData
->SystemTime
.High1Time
!= SharedUserData
->SystemTime
.High2Time
)
476 /* Calculate the milliseconds value and xor it to the cookie */
477 NewCookie
^= Int64ShrlMod32(UInt32x32To64(SharedUserData
->TickCountMultiplier
, SharedUserData
->TickCount
.LowPart
), 24) +
478 (SharedUserData
->TickCountMultiplier
* (SharedUserData
->TickCount
.High1Time
<< 8));
480 /* Make the cookie 16bit if necessary */
481 if (*Cookie
== 0xBB40) NewCookie
&= 0xFFFF;
483 /* If the result is 0 or the same as we got, just subtract one from the existing value
485 if ((NewCookie
== 0) || (NewCookie
== *Cookie
))
487 NewCookie
= *Cookie
- 1;
490 /* Set the new cookie value */
500 LdrpInitializeThread(IN PCONTEXT Context
)
502 PPEB Peb
= NtCurrentPeb();
503 PLDR_DATA_TABLE_ENTRY LdrEntry
;
504 PLIST_ENTRY NextEntry
, ListHead
;
505 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
509 DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n",
510 &LdrpImageEntry
->BaseDllName
,
511 NtCurrentTeb()->RealClientId
.UniqueProcess
,
512 NtCurrentTeb()->RealClientId
.UniqueThread
);
514 /* Allocate an Activation Context Stack */
515 DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer
);
516 Status
= RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer
);
517 if (!NT_SUCCESS(Status
))
519 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
522 /* Make sure we are not shutting down */
523 if (LdrpShutdownInProgress
) return;
528 /* Start at the beginning */
529 ListHead
= &Peb
->Ldr
->InMemoryOrderModuleList
;
530 NextEntry
= ListHead
->Flink
;
531 while (NextEntry
!= ListHead
)
533 /* Get the current entry */
534 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InMemoryOrderLinks
);
536 /* Make sure it's not ourselves */
537 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
539 /* Check if we should call */
540 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
))
542 /* Get the entrypoint */
543 EntryPoint
= LdrEntry
->EntryPoint
;
545 /* Check if we are ready to call it */
547 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
548 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
550 /* Set up the Act Ctx */
551 ActCtx
.Size
= sizeof(ActCtx
);
553 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
555 /* Activate the ActCtx */
556 RtlActivateActivationContextUnsafeFast(&ActCtx
,
557 LdrEntry
->EntryPointActivationContext
);
561 /* Check if it has TLS */
562 if (LdrEntry
->TlsIndex
)
564 /* Make sure we're not shutting down */
565 if (!LdrpShutdownInProgress
)
568 LdrpCallTlsInitializers(LdrEntry
, DLL_THREAD_ATTACH
);
572 /* Make sure we're not shutting down */
573 if (!LdrpShutdownInProgress
)
575 /* Call the Entrypoint */
576 DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n",
577 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
,
578 NtCurrentTeb()->RealClientId
.UniqueProcess
,
579 NtCurrentTeb()->RealClientId
.UniqueThread
);
580 LdrpCallInitRoutine(LdrEntry
->EntryPoint
,
586 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
588 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_ATTACH) for %wZ\n",
589 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
593 /* Deactivate the ActCtx */
594 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
600 NextEntry
= NextEntry
->Flink
;
604 if (LdrpImageHasTls
&& !LdrpShutdownInProgress
)
606 /* Set up the Act Ctx */
607 ActCtx
.Size
= sizeof(ActCtx
);
609 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
611 /* Activate the ActCtx */
612 RtlActivateActivationContextUnsafeFast(&ActCtx
,
613 LdrpImageEntry
->EntryPointActivationContext
);
617 /* Do TLS callbacks */
618 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_THREAD_ATTACH
);
620 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
626 /* Deactivate the ActCtx */
627 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
630 DPRINT("LdrpInitializeThread() done\n");
635 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL
)
637 PLDR_DATA_TABLE_ENTRY LocalArray
[16];
638 PLIST_ENTRY ListHead
;
639 PLIST_ENTRY NextEntry
;
640 PLDR_DATA_TABLE_ENTRY LdrEntry
, *LdrRootEntry
, OldInitializer
;
644 NTSTATUS Status
= STATUS_SUCCESS
;
645 PPEB Peb
= NtCurrentPeb();
646 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
647 ULONG BreakOnDllLoad
;
651 DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
652 &LdrpImageEntry
->BaseDllName
,
653 NtCurrentTeb()->RealClientId
.UniqueProcess
,
654 NtCurrentTeb()->RealClientId
.UniqueThread
);
656 /* Check the Loader Lock */
657 LdrpEnsureLoaderLockIsHeld();
659 /* Get the number of entries to call */
660 if ((Count
= LdrpClearLoadInProgress()))
662 /* Check if we can use our local buffer */
665 /* Allocate space for all the entries */
666 LdrRootEntry
= RtlAllocateHeap(RtlGetProcessHeap(),
668 Count
* sizeof(*LdrRootEntry
));
669 if (!LdrRootEntry
) return STATUS_NO_MEMORY
;
673 /* Use our local array */
674 LdrRootEntry
= LocalArray
;
683 /* Show debug message */
686 DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
687 NtCurrentTeb()->RealClientId
.UniqueThread
,
688 NtCurrentTeb()->RealClientId
.UniqueProcess
,
689 &Peb
->ProcessParameters
->ImagePathName
);
693 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
694 NextEntry
= ListHead
->Flink
;
696 while (NextEntry
!= ListHead
)
698 /* Get the Data Entry */
699 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
701 /* Check if we have a Root Entry */
705 if (!(LdrEntry
->Flags
& LDRP_ENTRY_PROCESSED
))
707 /* Setup the Cookie for the DLL */
708 LdrpInitSecurityCookie(LdrEntry
);
710 /* Check for valid entrypoint */
711 if (LdrEntry
->EntryPoint
)
715 LdrRootEntry
[i
] = LdrEntry
;
717 /* Display debug message */
720 DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
721 NtCurrentTeb()->RealClientId
.UniqueThread
,
722 NtCurrentTeb()->RealClientId
.UniqueProcess
,
723 &LdrEntry
->FullDllName
,
724 LdrEntry
->EntryPoint
);
732 LdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
733 NextEntry
= NextEntry
->Flink
;
736 Status
= STATUS_SUCCESS
;
738 /* If we got a context, then we have to call Kernel32 for TS support */
741 /* Check if we have one */
742 if (Kernel32ProcessInitPostImportFunction
)
745 Status
= Kernel32ProcessInitPostImportFunction();
746 if (!NT_SUCCESS(Status
))
748 DPRINT1("LDR: LdrpRunInitializeRoutines - Failed running kernel32 post-import function, Status=0x%08lx\n", Status
);
752 Kernel32ProcessInitPostImportFunction
= NULL
;
755 /* No root entry? return */
759 /* Set the TLD TEB */
760 OldTldTeb
= LdrpTopLevelDllBeingLoadedTeb
;
761 LdrpTopLevelDllBeingLoadedTeb
= NtCurrentTeb();
768 LdrEntry
= LdrRootEntry
[i
];
770 /* FIXME: Verify NX Compat */
772 /* Move to next entry */
775 /* Get its entrypoint */
776 EntryPoint
= LdrEntry
->EntryPoint
;
778 /* Are we being debugged? */
780 if (Peb
->BeingDebugged
|| Peb
->ReadImageFileExecOptions
)
782 /* Check if we should break on load */
783 Status
= LdrQueryImageFileExecutionOptions(&LdrEntry
->BaseDllName
,
789 if (!NT_SUCCESS(Status
)) BreakOnDllLoad
= 0;
791 /* Reset status back to STATUS_SUCCESS */
792 Status
= STATUS_SUCCESS
;
798 /* Check if we should show a message */
801 DPRINT1("LDR: %wZ loaded.", &LdrEntry
->BaseDllName
);
802 DPRINT1(" - About to call init routine at %p\n", EntryPoint
);
805 /* Break in debugger */
809 /* Make sure we have an entrypoint */
812 /* Save the old Dll Initializer and write the current one */
813 OldInitializer
= LdrpCurrentDllInitializer
;
814 LdrpCurrentDllInitializer
= LdrEntry
;
816 /* Set up the Act Ctx */
817 ActCtx
.Size
= sizeof(ActCtx
);
819 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
821 /* Activate the ActCtx */
822 RtlActivateActivationContextUnsafeFast(&ActCtx
,
823 LdrEntry
->EntryPointActivationContext
);
827 /* Check if it has TLS */
828 if (LdrEntry
->TlsIndex
&& Context
)
831 LdrpCallTlsInitializers(LdrEntry
, DLL_PROCESS_ATTACH
);
834 /* Call the Entrypoint */
837 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
838 &LdrEntry
->BaseDllName
, EntryPoint
);
840 DllStatus
= LdrpCallInitRoutine(EntryPoint
,
845 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
848 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_ATTACH) for %wZ\n",
849 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
853 /* Deactivate the ActCtx */
854 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
856 /* Save the Current DLL Initializer */
857 LdrpCurrentDllInitializer
= OldInitializer
;
859 /* Mark the entry as processed */
860 LdrEntry
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
;
862 /* Fail if DLL init failed */
865 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
866 &LdrEntry
->BaseDllName
, EntryPoint
);
868 Status
= STATUS_DLL_INIT_FAILED
;
875 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
876 NextEntry
= NextEntry
->Flink
;
877 while (NextEntry
!= ListHead
)
879 /* Get the Data Entry */
880 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
882 /* FIXME: Verify NX Compat */
883 // LdrpCheckNXCompatibility()
886 NextEntry
= NextEntry
->Flink
;
890 if (LdrpImageHasTls
&& Context
)
892 /* Set up the Act Ctx */
893 ActCtx
.Size
= sizeof(ActCtx
);
895 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
897 /* Activate the ActCtx */
898 RtlActivateActivationContextUnsafeFast(&ActCtx
,
899 LdrpImageEntry
->EntryPointActivationContext
);
903 /* Do TLS callbacks */
904 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_PROCESS_ATTACH
);
906 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
912 /* Deactivate the ActCtx */
913 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
917 /* Restore old TEB */
918 LdrpTopLevelDllBeingLoadedTeb
= OldTldTeb
;
920 /* Check if the array is in the heap */
921 if (LdrRootEntry
!= LocalArray
)
924 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry
);
927 /* Return to caller */
928 DPRINT("LdrpRunInitializeRoutines() done\n");
937 LdrShutdownProcess(VOID
)
939 PPEB Peb
= NtCurrentPeb();
940 PLDR_DATA_TABLE_ENTRY LdrEntry
;
941 PLIST_ENTRY NextEntry
, ListHead
;
942 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
945 DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry
->BaseDllName
);
946 if (LdrpShutdownInProgress
) return STATUS_SUCCESS
;
948 /* Tell the Shim Engine */
951 VOID(NTAPI
*SE_ProcessDying
)();
952 SE_ProcessDying
= RtlDecodeSystemPointer(g_pfnSE_ProcessDying
);
962 /* Set the shutdown variables */
963 LdrpShutdownThreadId
= NtCurrentTeb()->RealClientId
.UniqueThread
;
964 LdrpShutdownInProgress
= TRUE
;
966 /* Enter the Loader Lock */
967 RtlEnterCriticalSection(&LdrpLoaderLock
);
969 /* Cleanup trace logging data (Etw) */
970 if (SharedUserData
->TraceLogging
)
973 DPRINT1("We don't support Etw yet.\n");
976 /* Start at the end */
977 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
978 NextEntry
= ListHead
->Blink
;
979 while (NextEntry
!= ListHead
)
981 /* Get the current entry */
982 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
983 NextEntry
= NextEntry
->Blink
;
985 /* Make sure it's not ourselves */
986 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
988 /* Get the entrypoint */
989 EntryPoint
= LdrEntry
->EntryPoint
;
991 /* Check if we are ready to call it */
993 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
996 /* Set up the Act Ctx */
997 ActCtx
.Size
= sizeof(ActCtx
);
999 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1001 /* Activate the ActCtx */
1002 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1003 LdrEntry
->EntryPointActivationContext
);
1007 /* Check if it has TLS */
1008 if (LdrEntry
->TlsIndex
)
1011 LdrpCallTlsInitializers(LdrEntry
, DLL_PROCESS_DETACH
);
1014 /* Call the Entrypoint */
1015 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1016 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1017 LdrpCallInitRoutine(EntryPoint
,
1022 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1024 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_DETACH) for %wZ\n",
1025 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
1029 /* Deactivate the ActCtx */
1030 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1036 if (LdrpImageHasTls
)
1038 /* Set up the Act Ctx */
1039 ActCtx
.Size
= sizeof(ActCtx
);
1041 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1043 /* Activate the ActCtx */
1044 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1045 LdrpImageEntry
->EntryPointActivationContext
);
1049 /* Do TLS callbacks */
1050 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_PROCESS_DETACH
);
1052 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1058 /* Deactivate the ActCtx */
1059 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1062 /* FIXME: Do Heap detection and Etw final shutdown */
1064 /* Release the lock */
1065 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1066 DPRINT("LdrpShutdownProcess() done\n");
1068 return STATUS_SUCCESS
;
1076 LdrShutdownThread(VOID
)
1078 PPEB Peb
= NtCurrentPeb();
1079 PTEB Teb
= NtCurrentTeb();
1080 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1081 PLIST_ENTRY NextEntry
, ListHead
;
1082 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
1085 DPRINT("LdrShutdownThread() called for %wZ\n",
1086 &LdrpImageEntry
->BaseDllName
);
1088 /* Cleanup trace logging data (Etw) */
1089 if (SharedUserData
->TraceLogging
)
1092 DPRINT1("We don't support Etw yet.\n");
1095 /* Get the Ldr Lock */
1096 RtlEnterCriticalSection(&LdrpLoaderLock
);
1098 /* Start at the end */
1099 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
1100 NextEntry
= ListHead
->Blink
;
1101 while (NextEntry
!= ListHead
)
1103 /* Get the current entry */
1104 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
1105 NextEntry
= NextEntry
->Blink
;
1107 /* Make sure it's not ourselves */
1108 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
1110 /* Check if we should call */
1111 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
1112 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
1113 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
1115 /* Get the entrypoint */
1116 EntryPoint
= LdrEntry
->EntryPoint
;
1118 /* Check if we are ready to call it */
1121 /* Set up the Act Ctx */
1122 ActCtx
.Size
= sizeof(ActCtx
);
1124 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1126 /* Activate the ActCtx */
1127 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1128 LdrEntry
->EntryPointActivationContext
);
1132 /* Check if it has TLS */
1133 if (LdrEntry
->TlsIndex
)
1135 /* Make sure we're not shutting down */
1136 if (!LdrpShutdownInProgress
)
1139 LdrpCallTlsInitializers(LdrEntry
, DLL_THREAD_DETACH
);
1143 /* Make sure we're not shutting down */
1144 if (!LdrpShutdownInProgress
)
1146 /* Call the Entrypoint */
1147 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1148 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1149 LdrpCallInitRoutine(EntryPoint
,
1155 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1157 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_DETACH) for %wZ\n",
1158 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
1162 /* Deactivate the ActCtx */
1163 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1170 if (LdrpImageHasTls
)
1172 /* Set up the Act Ctx */
1173 ActCtx
.Size
= sizeof(ActCtx
);
1175 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1177 /* Activate the ActCtx */
1178 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1179 LdrpImageEntry
->EntryPointActivationContext
);
1183 /* Do TLS callbacks */
1184 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_THREAD_DETACH
);
1186 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1192 /* Deactivate the ActCtx */
1193 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1198 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1200 /* Check for expansion slots */
1201 if (Teb
->TlsExpansionSlots
)
1203 /* Free expansion slots */
1204 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->TlsExpansionSlots
);
1207 /* Check for FLS Data */
1211 DPRINT1("We don't support FLS Data yet\n");
1214 /* Check for Fiber data */
1215 if (Teb
->HasFiberData
)
1217 /* Free Fiber data*/
1218 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->NtTib
.FiberData
);
1219 Teb
->NtTib
.FiberData
= NULL
;
1222 /* Free the activation context stack */
1223 RtlFreeThreadActivationContextStack();
1224 DPRINT("LdrShutdownThread() done\n");
1226 return STATUS_SUCCESS
;
1231 LdrpInitializeTls(VOID
)
1233 PLIST_ENTRY NextEntry
, ListHead
;
1234 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1235 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1236 PLDRP_TLS_DATA TlsData
;
1239 /* Initialize the TLS List */
1240 InitializeListHead(&LdrpTlsList
);
1242 /* Loop all the modules */
1243 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1244 NextEntry
= ListHead
->Flink
;
1245 while (ListHead
!= NextEntry
)
1248 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1249 NextEntry
= NextEntry
->Flink
;
1251 /* Get the TLS directory */
1252 TlsDirectory
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
1254 IMAGE_DIRECTORY_ENTRY_TLS
,
1257 /* Check if we have a directory */
1258 if (!TlsDirectory
) continue;
1260 /* Check if the image has TLS */
1261 if (!LdrpImageHasTls
) LdrpImageHasTls
= TRUE
;
1263 /* Show debug message */
1266 DPRINT1("LDR: Tls Found in %wZ at %p\n",
1267 &LdrEntry
->BaseDllName
,
1271 /* Allocate an entry */
1272 TlsData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA
));
1273 if (!TlsData
) return STATUS_NO_MEMORY
;
1275 /* Lock the DLL and mark it for TLS Usage */
1276 LdrEntry
->LoadCount
= -1;
1277 LdrEntry
->TlsIndex
= -1;
1279 /* Save the cached TLS data */
1280 TlsData
->TlsDirectory
= *TlsDirectory
;
1281 InsertTailList(&LdrpTlsList
, &TlsData
->TlsLinks
);
1283 /* Update the index */
1284 *(PLONG
)TlsData
->TlsDirectory
.AddressOfIndex
= LdrpNumberOfTlsEntries
;
1285 TlsData
->TlsDirectory
.Characteristics
= LdrpNumberOfTlsEntries
++;
1288 /* Done setting up TLS, allocate entries */
1289 return LdrpAllocateTls();
1294 LdrpAllocateTls(VOID
)
1296 PTEB Teb
= NtCurrentTeb();
1297 PLIST_ENTRY NextEntry
, ListHead
;
1298 PLDRP_TLS_DATA TlsData
;
1302 /* Check if we have any entries */
1303 if (!LdrpNumberOfTlsEntries
)
1304 return STATUS_SUCCESS
;
1306 /* Allocate the vector array */
1307 TlsVector
= RtlAllocateHeap(RtlGetProcessHeap(),
1309 LdrpNumberOfTlsEntries
* sizeof(PVOID
));
1310 if (!TlsVector
) return STATUS_NO_MEMORY
;
1311 Teb
->ThreadLocalStoragePointer
= TlsVector
;
1313 /* Loop the TLS Array */
1314 ListHead
= &LdrpTlsList
;
1315 NextEntry
= ListHead
->Flink
;
1316 while (NextEntry
!= ListHead
)
1319 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1320 NextEntry
= NextEntry
->Flink
;
1322 /* Allocate this vector */
1323 TlsDataSize
= TlsData
->TlsDirectory
.EndAddressOfRawData
-
1324 TlsData
->TlsDirectory
.StartAddressOfRawData
;
1325 TlsVector
[TlsData
->TlsDirectory
.Characteristics
] = RtlAllocateHeap(RtlGetProcessHeap(),
1328 if (!TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1331 return STATUS_NO_MEMORY
;
1334 /* Show debug message */
1337 DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
1339 TlsData
->TlsDirectory
.Characteristics
,
1340 &TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1341 TlsData
->TlsDirectory
.StartAddressOfRawData
,
1342 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1346 RtlCopyMemory(TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1347 (PVOID
)TlsData
->TlsDirectory
.StartAddressOfRawData
,
1352 return STATUS_SUCCESS
;
1359 PLIST_ENTRY ListHead
, NextEntry
;
1360 PLDRP_TLS_DATA TlsData
;
1362 PTEB Teb
= NtCurrentTeb();
1364 /* Get a pointer to the vector array */
1365 TlsVector
= Teb
->ThreadLocalStoragePointer
;
1366 if (!TlsVector
) return;
1368 /* Loop through it */
1369 ListHead
= &LdrpTlsList
;
1370 NextEntry
= ListHead
->Flink
;
1371 while (NextEntry
!= ListHead
)
1373 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1374 NextEntry
= NextEntry
->Flink
;
1376 /* Free each entry */
1377 if (TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1379 RtlFreeHeap(RtlGetProcessHeap(),
1381 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1385 /* Free the array itself */
1386 RtlFreeHeap(RtlGetProcessHeap(),
1393 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName
, PPEB Peb
, PHANDLE OptionsKey
)
1397 ULONG ExecuteOptions
, MinimumStackCommit
= 0, GlobalFlag
;
1399 /* Return error if we were not provided a pointer where to save the options key handle */
1400 if (!OptionsKey
) return STATUS_INVALID_HANDLE
;
1402 /* Zero initialize the options key pointer */
1405 /* Open the options key */
1406 Status
= LdrOpenImageFileOptionsKey(ImagePathName
, 0, &KeyHandle
);
1408 /* Save it if it was opened successfully */
1409 if (NT_SUCCESS(Status
))
1410 *OptionsKey
= KeyHandle
;
1414 /* There are image specific options, read them starting with NXCOMPAT */
1415 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1419 sizeof(ExecuteOptions
),
1422 if (NT_SUCCESS(Status
))
1424 /* TODO: Set execution options for the process */
1426 if (ExecuteOptions == 0)
1430 ZwSetInformationProcess(NtCurrentProcess(),
1431 ProcessExecuteFlags,
1437 /* Check if this image uses large pages */
1438 if (Peb
->ImageUsesLargePages
)
1440 /* TODO: If it does, open large page key */
1444 /* Get various option values */
1445 LdrQueryImageFileKeyOption(KeyHandle
,
1446 L
"DisableHeapLookaside",
1448 &RtlpDisableHeapLookaside
,
1449 sizeof(RtlpDisableHeapLookaside
),
1452 LdrQueryImageFileKeyOption(KeyHandle
,
1455 &RtlpShutdownProcessFlags
,
1456 sizeof(RtlpShutdownProcessFlags
),
1459 LdrQueryImageFileKeyOption(KeyHandle
,
1460 L
"MinimumStackCommitInBytes",
1462 &MinimumStackCommit
,
1463 sizeof(MinimumStackCommit
),
1466 /* Update PEB's minimum stack commit if it's lower */
1467 if (Peb
->MinimumStackCommit
< MinimumStackCommit
)
1468 Peb
->MinimumStackCommit
= MinimumStackCommit
;
1470 /* Set the global flag */
1471 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1478 if (NT_SUCCESS(Status
))
1479 Peb
->NtGlobalFlag
= GlobalFlag
;
1483 /* Call AVRF if necessary */
1484 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1486 Status
= LdrpInitializeApplicationVerifierPackage(KeyHandle
, Peb
, TRUE
, FALSE
);
1487 if (!NT_SUCCESS(Status
))
1489 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1495 /* There are no image-specific options, so perform global initialization */
1496 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1498 /* Initialize app verifier package */
1499 Status
= LdrpInitializeApplicationVerifierPackage(KeyHandle
, Peb
, TRUE
, FALSE
);
1500 if (!NT_SUCCESS(Status
))
1502 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1507 return STATUS_SUCCESS
;
1512 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
)
1519 LdrpInitializeProcessCompat(PVOID
* pOldShimData
)
1521 static const GUID
* GuidOrder
[] = { &COMPAT_GUID_WIN10
, &COMPAT_GUID_WIN81
, &COMPAT_GUID_WIN8
,
1522 &COMPAT_GUID_WIN7
, &COMPAT_GUID_VISTA
};
1523 static const DWORD GuidVersions
[] = { WINVER_WIN10
, WINVER_WIN81
, WINVER_WIN8
, WINVER_WIN7
, WINVER_VISTA
};
1525 ULONG Buffer
[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
)) / sizeof(ULONG
)];
1526 ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
* ContextCompatInfo
;
1527 SIZE_T SizeRequired
;
1530 ReactOS_ShimData
* pShimData
= *pOldShimData
;
1532 C_ASSERT(RTL_NUMBER_OF(GuidOrder
) == RTL_NUMBER_OF(GuidVersions
));
1536 if (pShimData
->dwMagic
!= REACTOS_SHIMDATA_MAGIC
||
1537 pShimData
->dwSize
!= sizeof(ReactOS_ShimData
))
1539 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData
->dwMagic
, pShimData
->dwSize
);
1542 if (pShimData
->dwRosProcessCompatVersion
)
1544 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData
->dwRosProcessCompatVersion
);
1549 SizeRequired
= sizeof(Buffer
);
1550 Status
= RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
,
1553 CompatibilityInformationInActivationContext
,
1558 if (!NT_SUCCESS(Status
))
1560 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status
);
1564 ContextCompatInfo
= (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
*)Buffer
;
1565 /* No Compatibility elements present, bail out */
1566 if (ContextCompatInfo
->ElementCount
== 0)
1569 /* Search for known GUID's, starting from newest to oldest. */
1570 for (cur
= 0; cur
< RTL_NUMBER_OF(GuidOrder
); ++cur
)
1572 for (n
= 0; n
< ContextCompatInfo
->ElementCount
; ++n
)
1574 if (ContextCompatInfo
->Elements
[n
].Type
== ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
&&
1575 RtlCompareMemory(&ContextCompatInfo
->Elements
[n
].Id
, GuidOrder
[cur
], sizeof(GUID
)) == sizeof(GUID
))
1577 /* If this process did not need shim data before, allocate and store it */
1578 if (pShimData
== NULL
)
1580 PPEB Peb
= NtCurrentPeb();
1582 ASSERT(Peb
->pShimData
== NULL
);
1583 pShimData
= RtlAllocateHeap(Peb
->ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(*pShimData
));
1587 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData
));
1591 pShimData
->dwSize
= sizeof(*pShimData
);
1592 pShimData
->dwMagic
= REACTOS_SHIMDATA_MAGIC
;
1594 Peb
->pShimData
= pShimData
;
1595 *pOldShimData
= pShimData
;
1598 /* Store the highest found version, and bail out. */
1599 pShimData
->dwRosProcessCompatVersion
= GuidVersions
[cur
];
1600 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", GuidVersions
[cur
]);
1610 LdrpInitializeProcess(IN PCONTEXT Context
,
1611 IN PVOID SystemArgument1
)
1613 RTL_HEAP_PARAMETERS HeapParameters
;
1614 ULONG ComSectionSize
;
1615 ANSI_STRING BaseProcessInitPostImportName
= RTL_CONSTANT_STRING("BaseProcessInitPostImport");
1616 ANSI_STRING BaseQueryModuleDataName
= RTL_CONSTANT_STRING("BaseQueryModuleData");
1618 OBJECT_ATTRIBUTES ObjectAttributes
;
1619 //UNICODE_STRING LocalFileName, FullImageName;
1620 HANDLE SymLinkHandle
;
1621 //ULONG DebugHeapOnly;
1622 UNICODE_STRING CommandLine
, NtSystemRoot
, ImagePathName
, FullPath
, ImageFileName
, KnownDllString
;
1623 PPEB Peb
= NtCurrentPeb();
1624 BOOLEAN IsDotNetImage
= FALSE
;
1625 BOOLEAN FreeCurDir
= FALSE
;
1627 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1628 //LPWSTR ImagePathBuffer;
1630 UNICODE_STRING CurrentDirectory
;
1633 PIMAGE_NT_HEADERS NtHeader
;
1634 LPWSTR NtDllName
= NULL
;
1635 NTSTATUS Status
, ImportStatus
;
1636 NLSTABLEINFO NlsTable
;
1637 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig
;
1638 PTEB Teb
= NtCurrentTeb();
1639 PLIST_ENTRY ListHead
;
1640 PLIST_ENTRY NextEntry
;
1643 ULONG DebugProcessHeapOnly
= 0;
1644 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
1646 ULONG ExecuteOptions
= 0;
1649 /* Set a NULL SEH Filter */
1650 RtlSetUnhandledExceptionFilter(NULL
);
1652 /* Get the image path */
1653 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
1655 /* Check if it's not normalized */
1656 if (!(Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
))
1659 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
1662 /* Create a unicode string for the Image Path */
1663 ImagePathName
.Length
= Peb
->ProcessParameters
->ImagePathName
.Length
;
1664 ImagePathName
.MaximumLength
= ImagePathName
.Length
+ sizeof(WCHAR
);
1665 ImagePathName
.Buffer
= ImagePath
;
1667 /* Get the NT Headers */
1668 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
1670 /* Get the execution options */
1671 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &OptionsKey
);
1673 /* Check if this is a .NET executable */
1674 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1676 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
1679 /* Remember this for later */
1680 IsDotNetImage
= TRUE
;
1683 /* Save the NTDLL Base address */
1684 NtDllBase
= SystemArgument1
;
1686 /* If this is a Native Image */
1687 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
1689 /* Then do DLL Validation */
1690 LdrpDllValidation
= TRUE
;
1693 /* Save the old Shim Data */
1694 OldShimData
= Peb
->pShimData
;
1696 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */
1697 //Peb->pShimData = NULL;
1699 /* Save the number of processors and CS Timeout */
1700 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
1701 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
1703 /* Normalize the parameters */
1704 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
1705 if (ProcessParameters
)
1707 /* Save the Image and Command Line Names */
1708 ImageFileName
= ProcessParameters
->ImagePathName
;
1709 CommandLine
= ProcessParameters
->CommandLine
;
1713 /* It failed, initialize empty strings */
1714 RtlInitUnicodeString(&ImageFileName
, NULL
);
1715 RtlInitUnicodeString(&CommandLine
, NULL
);
1718 /* Initialize NLS data */
1719 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1720 Peb
->OemCodePageData
,
1721 Peb
->UnicodeCaseTableData
,
1724 /* Reset NLS Translations */
1725 RtlResetRtlTranslations(&NlsTable
);
1727 /* Get the Image Config Directory */
1728 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1730 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1733 /* Setup the Heap Parameters */
1734 RtlZeroMemory(&HeapParameters
, sizeof(RTL_HEAP_PARAMETERS
));
1735 HeapFlags
= HEAP_GROWABLE
;
1736 HeapParameters
.Length
= sizeof(RTL_HEAP_PARAMETERS
);
1738 /* Check if we have Configuration Data */
1739 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1741 /* FIXME: Custom heap settings and misc. */
1742 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1745 /* Check for custom affinity mask */
1746 if (Peb
->ImageProcessAffinityMask
)
1749 Status
= NtSetInformationProcess(NtCurrentProcess(),
1750 ProcessAffinityMask
,
1751 &Peb
->ImageProcessAffinityMask
,
1752 sizeof(Peb
->ImageProcessAffinityMask
));
1755 /* Check if verbose debugging (ShowSnaps) was requested */
1756 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1758 /* Start verbose debugging messages right now if they were requested */
1761 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1762 Teb
->ClientId
.UniqueProcess
,
1766 /* If the timeout is too long */
1767 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1769 /* Then disable CS Timeout */
1770 RtlpTimeoutDisable
= TRUE
;
1773 /* Initialize Critical Section Data */
1774 RtlpInitDeferedCriticalSection();
1776 /* Initialize VEH Call lists */
1777 RtlpInitializeVectoredExceptionHandling();
1779 /* Set TLS/FLS Bitmap data */
1780 Peb
->FlsBitmap
= &FlsBitMap
;
1781 Peb
->TlsBitmap
= &TlsBitMap
;
1782 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1784 /* Initialize FLS Bitmap */
1785 RtlInitializeBitMap(&FlsBitMap
,
1787 FLS_MAXIMUM_AVAILABLE
);
1788 RtlSetBit(&FlsBitMap
, 0);
1790 /* Initialize TLS Bitmap */
1791 RtlInitializeBitMap(&TlsBitMap
,
1793 TLS_MINIMUM_AVAILABLE
);
1794 RtlSetBit(&TlsBitMap
, 0);
1795 RtlInitializeBitMap(&TlsExpansionBitMap
,
1796 Peb
->TlsExpansionBitmapBits
,
1797 TLS_EXPANSION_SLOTS
);
1798 RtlSetBit(&TlsExpansionBitMap
, 0);
1800 /* Initialize the Hash Table */
1801 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1803 InitializeListHead(&LdrpHashTable
[i
]);
1806 /* Initialize the Loader Lock */
1807 // FIXME: What's the point of initing it manually, if two lines lower
1808 // a call to RtlInitializeCriticalSection() is being made anyway?
1809 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1810 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1811 RtlInitializeCriticalSection(&LdrpLoaderLock
);
1812 LdrpLoaderLockInit
= TRUE
;
1814 /* Check if User Stack Trace Database support was requested */
1815 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1817 DPRINT1("We don't support user stack trace databases yet\n");
1820 /* Setup Fast PEB Lock */
1821 RtlInitializeCriticalSection(&FastPebLock
);
1822 Peb
->FastPebLock
= &FastPebLock
;
1823 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1824 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1826 /* Setup Callout Lock and Notification list */
1827 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1828 InitializeListHead(&LdrpDllNotificationList
);
1830 /* For old executables, use 16-byte aligned heap */
1831 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1832 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1834 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1837 /* Setup the Heap */
1838 RtlInitializeHeapManager();
1839 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1841 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1842 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1846 if (!Peb
->ProcessHeap
)
1848 DPRINT1("Failed to create process heap\n");
1849 return STATUS_NO_MEMORY
;
1852 /* Allocate an Activation Context Stack */
1853 Status
= RtlAllocateActivationContextStack(&Teb
->ActivationContextStackPointer
);
1854 if (!NT_SUCCESS(Status
)) return Status
;
1856 // FIXME: Loader private heap is missing
1857 //DPRINT1("Loader private heap is missing\n");
1859 /* Check for Debug Heap */
1862 /* Query the setting */
1863 Status
= LdrQueryImageFileKeyOption(OptionsKey
,
1864 L
"DebugProcessHeapOnly",
1866 &DebugProcessHeapOnly
,
1870 if (NT_SUCCESS(Status
))
1872 /* Reset DPH if requested */
1873 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1875 RtlpDphGlobalFlags
&= ~DPH_FLAG_DLL_NOTIFY
;
1876 RtlpPageHeapEnabled
= FALSE
;
1881 /* Build the NTDLL Path */
1882 FullPath
.Buffer
= StringBuffer
;
1883 FullPath
.Length
= 0;
1884 FullPath
.MaximumLength
= sizeof(StringBuffer
);
1885 RtlInitUnicodeString(&NtSystemRoot
, SharedUserData
->NtSystemRoot
);
1886 RtlAppendUnicodeStringToString(&FullPath
, &NtSystemRoot
);
1887 RtlAppendUnicodeToString(&FullPath
, L
"\\System32\\");
1889 /* Open the Known DLLs directory */
1890 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1891 InitializeObjectAttributes(&ObjectAttributes
,
1893 OBJ_CASE_INSENSITIVE
,
1896 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
1897 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
1900 /* Check if it exists */
1901 if (NT_SUCCESS(Status
))
1903 /* Open the Known DLLs Path */
1904 RtlInitUnicodeString(&KnownDllString
, L
"KnownDllPath");
1905 InitializeObjectAttributes(&ObjectAttributes
,
1907 OBJ_CASE_INSENSITIVE
,
1908 LdrpKnownDllObjectDirectory
,
1910 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
1911 SYMBOLIC_LINK_QUERY
,
1913 if (NT_SUCCESS(Status
))
1915 /* Query the path */
1916 LdrpKnownDllPath
.Length
= 0;
1917 LdrpKnownDllPath
.MaximumLength
= sizeof(LdrpKnownDllPathBuffer
);
1918 LdrpKnownDllPath
.Buffer
= LdrpKnownDllPathBuffer
;
1919 Status
= ZwQuerySymbolicLinkObject(SymLinkHandle
, &LdrpKnownDllPath
, NULL
);
1920 NtClose(SymLinkHandle
);
1921 if (!NT_SUCCESS(Status
))
1923 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
1929 /* Check if we failed */
1930 if (!NT_SUCCESS(Status
))
1932 /* Assume System32 */
1933 LdrpKnownDllObjectDirectory
= NULL
;
1934 RtlInitUnicodeString(&LdrpKnownDllPath
, StringBuffer
);
1935 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
1938 /* If we have process parameters, get the default path and current path */
1939 if (ProcessParameters
)
1941 /* Check if we have a Dll Path */
1942 if (ProcessParameters
->DllPath
.Length
)
1945 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
1949 /* We need a valid path */
1950 DPRINT1("No valid DllPath was given!\n");
1951 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
1954 /* Set the current directory */
1955 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
1957 /* Check if it's empty or invalid */
1958 if ((!CurrentDirectory
.Buffer
) ||
1959 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
1960 (!CurrentDirectory
.Length
))
1962 /* Allocate space for the buffer */
1963 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
1966 sizeof(UNICODE_NULL
));
1967 if (!CurrentDirectory
.Buffer
)
1969 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
1973 /* Copy the drive of the system root */
1974 RtlMoveMemory(CurrentDirectory
.Buffer
,
1975 SharedUserData
->NtSystemRoot
,
1977 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
1978 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
1979 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
1982 DPRINT("Using dynamically allocd curdir\n");
1986 /* Use the local buffer */
1987 DPRINT("Using local system root\n");
1991 /* Setup Loader Data */
1993 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
1994 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
1995 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
1996 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
1997 PebLdr
.Initialized
= TRUE
;
1999 /* Allocate a data entry for the Image */
2000 LdrpImageEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
2003 LdrpImageEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(LdrpImageEntry
->DllBase
);
2004 LdrpImageEntry
->LoadCount
= -1;
2005 LdrpImageEntry
->EntryPointActivationContext
= 0;
2006 LdrpImageEntry
->FullDllName
= ImageFileName
;
2009 LdrpImageEntry
->Flags
= LDRP_COR_IMAGE
;
2011 LdrpImageEntry
->Flags
= 0;
2013 /* Check if the name is empty */
2014 if (!ImageFileName
.Buffer
[0])
2016 /* Use the same Base name */
2017 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
2021 /* Find the last slash */
2022 Current
= ImageFileName
.Buffer
;
2025 if (*Current
++ == '\\')
2028 NtDllName
= Current
;
2032 /* Did we find anything? */
2035 /* Use the same Base name */
2036 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
2040 /* Setup the name */
2041 LdrpImageEntry
->BaseDllName
.Length
= (USHORT
)((ULONG_PTR
)ImageFileName
.Buffer
+ ImageFileName
.Length
- (ULONG_PTR
)NtDllName
);
2042 LdrpImageEntry
->BaseDllName
.MaximumLength
= LdrpImageEntry
->BaseDllName
.Length
+ sizeof(WCHAR
);
2043 LdrpImageEntry
->BaseDllName
.Buffer
= (PWSTR
)((ULONG_PTR
)ImageFileName
.Buffer
+
2044 (ImageFileName
.Length
- LdrpImageEntry
->BaseDllName
.Length
));
2048 /* Processing done, insert it */
2049 LdrpInsertMemoryTableEntry(LdrpImageEntry
);
2050 LdrpImageEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
2052 /* Now add an entry for NTDLL */
2053 NtLdrEntry
= LdrpAllocateDataTableEntry(SystemArgument1
);
2054 NtLdrEntry
->Flags
= LDRP_IMAGE_DLL
;
2055 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
2056 NtLdrEntry
->LoadCount
= -1;
2057 NtLdrEntry
->EntryPointActivationContext
= 0;
2059 NtLdrEntry
->FullDllName
.Length
= FullPath
.Length
;
2060 NtLdrEntry
->FullDllName
.MaximumLength
= FullPath
.MaximumLength
;
2061 NtLdrEntry
->FullDllName
.Buffer
= StringBuffer
;
2062 RtlAppendUnicodeStringToString(&NtLdrEntry
->FullDllName
, &NtDllString
);
2064 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
2065 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
2066 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
2068 /* Processing done, insert it */
2069 LdrpNtDllDataTableEntry
= NtLdrEntry
;
2070 LdrpInsertMemoryTableEntry(NtLdrEntry
);
2072 /* Let the world know */
2075 DPRINT1("LDR: NEW PROCESS\n");
2076 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry
->FullDllName
, &LdrpImageEntry
->BaseDllName
);
2077 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory
);
2078 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath
);
2081 /* Link the Init Order List */
2082 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
2083 &LdrpNtDllDataTableEntry
->InInitializationOrderLinks
);
2085 /* Initialize Wine's active context implementation for the current process */
2088 /* ReactOS specific */
2089 LdrpInitializeProcessCompat(&OldShimData
);
2091 /* Set the current directory */
2092 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
2093 if (!NT_SUCCESS(Status
))
2095 /* We failed, check if we should free it */
2096 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2098 /* Set it to the NT Root */
2099 CurrentDirectory
= NtSystemRoot
;
2100 RtlSetCurrentDirectory_U(&CurrentDirectory
);
2104 /* We're done with it, free it */
2105 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2108 /* Check if we should look for a .local file */
2109 if (ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
)
2112 DPRINT1("We don't support .local overrides yet\n");
2115 /* Check if the Application Verifier was enabled */
2116 if (Peb
->NtGlobalFlag
& FLG_APPLICATION_VERIFIER
)
2118 Status
= AVrfInitializeVerifier();
2119 if (!NT_SUCCESS(Status
))
2121 DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status
);
2130 DPRINT1("We don't support .NET applications yet\n");
2133 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
||
2134 NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_CUI
)
2136 PVOID Kernel32BaseAddress
;
2137 PVOID FunctionAddress
;
2139 Status
= LdrLoadDll(NULL
, NULL
, &Kernel32String
, &Kernel32BaseAddress
);
2141 if (!NT_SUCCESS(Status
))
2144 DPRINT1("LDR: Unable to load %wZ, Status=0x%08lx\n", &Kernel32String
, Status
);
2148 Status
= LdrGetProcedureAddress(Kernel32BaseAddress
,
2149 &BaseProcessInitPostImportName
,
2153 if (!NT_SUCCESS(Status
))
2156 DPRINT1("LDR: Unable to find post-import process init function, Status=0x%08lx\n", &Kernel32String
, Status
);
2159 Kernel32ProcessInitPostImportFunction
= FunctionAddress
;
2161 Status
= LdrGetProcedureAddress(Kernel32BaseAddress
,
2162 &BaseQueryModuleDataName
,
2166 if (!NT_SUCCESS(Status
))
2169 DPRINT1("LDR: Unable to find BaseQueryModuleData, Status=0x%08lx\n", &Kernel32String
, Status
);
2172 Kernel32BaseQueryModuleData
= FunctionAddress
;
2175 /* Walk the IAT and load all the DLLs */
2176 ImportStatus
= LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
2178 /* Check if relocation is needed */
2179 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
2181 DPRINT1("LDR: Performing EXE relocation\n");
2183 /* Change the protection to prepare for relocation */
2184 ViewBase
= Peb
->ImageBaseAddress
;
2185 Status
= LdrpSetProtection(ViewBase
, FALSE
);
2186 if (!NT_SUCCESS(Status
)) return Status
;
2188 /* Do the relocation */
2189 Status
= LdrRelocateImageWithBias(ViewBase
,
2193 STATUS_CONFLICTING_ADDRESSES
,
2194 STATUS_INVALID_IMAGE_FORMAT
);
2195 if (!NT_SUCCESS(Status
))
2197 DPRINT1("LdrRelocateImageWithBias() failed\n");
2201 /* Check if a start context was provided */
2204 DPRINT1("WARNING: Relocated EXE Context");
2205 UNIMPLEMENTED
; // We should support this
2206 return STATUS_INVALID_IMAGE_FORMAT
;
2209 /* Restore the protection */
2210 Status
= LdrpSetProtection(ViewBase
, TRUE
);
2211 if (!NT_SUCCESS(Status
)) return Status
;
2215 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
2216 NextEntry
= ListHead
->Flink
;
2217 while (ListHead
!= NextEntry
)
2219 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2220 NtLdrEntry
->LoadCount
= -1;
2221 NextEntry
= NextEntry
->Flink
;
2224 /* Phase 0 is done */
2225 LdrpLdrDatabaseIsSetup
= TRUE
;
2227 /* Check whether all static imports were properly loaded and return here */
2228 if (!NT_SUCCESS(ImportStatus
)) return ImportStatus
;
2230 /* Initialize TLS */
2231 Status
= LdrpInitializeTls();
2232 if (!NT_SUCCESS(Status
))
2234 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2239 /* FIXME Mark the DLL Ranges for Stack Traces later */
2241 /* Notify the debugger now */
2242 if (Peb
->BeingDebugged
)
2247 /* Update show snaps again */
2248 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
2251 /* Validate the Image for MP Usage */
2252 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
2254 /* Check NX Options */
2255 if (SharedUserData
->NXSupportPolicy
== 1)
2257 ExecuteOptions
= 0xD;
2259 else if (!SharedUserData
->NXSupportPolicy
)
2261 ExecuteOptions
= 0xA;
2265 ZwSetInformationProcess(NtCurrentProcess(),
2266 ProcessExecuteFlags
,
2270 // FIXME: Should be done by Application Compatibility features,
2271 // by reading the registry, etc...
2272 // For now, this is the old code from ntdll!RtlGetVersion().
2273 RtlInitEmptyUnicodeString(&Peb
->CSDVersion
, NULL
, 0);
2274 if (((Peb
->OSCSDVersion
>> 8) & 0xFF) != 0)
2276 WCHAR szCSDVersion
[128];
2278 ULONG Length
= ARRAYSIZE(szCSDVersion
) - 1;
2279 i
= _snwprintf(szCSDVersion
, Length
,
2281 ((Peb
->OSCSDVersion
>> 8) & 0xFF));
2284 /* Null-terminate if it was overflowed */
2285 szCSDVersion
[Length
] = UNICODE_NULL
;
2288 Length
*= sizeof(WCHAR
);
2289 Peb
->CSDVersion
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
2291 Length
+ sizeof(UNICODE_NULL
));
2292 if (Peb
->CSDVersion
.Buffer
)
2294 Peb
->CSDVersion
.Length
= Length
;
2295 Peb
->CSDVersion
.MaximumLength
= Length
+ sizeof(UNICODE_NULL
);
2297 RtlCopyMemory(Peb
->CSDVersion
.Buffer
,
2299 Peb
->CSDVersion
.MaximumLength
);
2300 Peb
->CSDVersion
.Buffer
[Peb
->CSDVersion
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2304 /* Check if we had Shim Data */
2307 /* Load the Shim Engine */
2308 Peb
->AppCompatInfo
= NULL
;
2309 LdrpLoadShimEngine(OldShimData
, &ImagePathName
, OldShimData
);
2313 /* Check for Application Compatibility Goo */
2314 //LdrQueryApplicationCompatibilityGoo(hKey);
2315 DPRINT("Querying app compat hacks is missing!\n");
2319 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2320 * incompatible images.
2323 /* Now call the Init Routines */
2324 Status
= LdrpRunInitializeRoutines(Context
);
2325 if (!NT_SUCCESS(Status
))
2327 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2332 /* Notify Shim Engine */
2335 VOID(NTAPI
*SE_InstallAfterInit
)(PUNICODE_STRING
, PVOID
);
2336 SE_InstallAfterInit
= RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit
);
2337 SE_InstallAfterInit(&ImagePathName
, OldShimData
);
2340 /* Check if we have a user-defined Post Process Routine */
2341 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
2344 Peb
->PostProcessInitRoutine();
2347 /* Close the key if we have one opened */
2348 if (OptionsKey
) NtClose(OptionsKey
);
2356 LdrpInitFailure(NTSTATUS Status
)
2359 PPEB Peb
= NtCurrentPeb();
2361 /* Print a debug message */
2362 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2363 &Peb
->ProcessParameters
->ImagePathName
, Status
);
2365 /* Raise a hard error */
2366 if (!LdrpFatalHardErrorCount
)
2368 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
2374 LdrpInit(PCONTEXT Context
,
2375 PVOID SystemArgument1
,
2376 PVOID SystemArgument2
)
2378 LARGE_INTEGER Timeout
;
2379 PTEB Teb
= NtCurrentTeb();
2380 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
2381 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
2382 PPEB Peb
= NtCurrentPeb();
2384 DPRINT("LdrpInit() %p/%p\n",
2385 NtCurrentTeb()->RealClientId
.UniqueProcess
,
2386 NtCurrentTeb()->RealClientId
.UniqueThread
);
2389 /* Set the SList header usage */
2390 RtlpUse16ByteSLists
= SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE128
];
2393 /* Check if we have a deallocation stack */
2394 if (!Teb
->DeallocationStack
)
2396 /* We don't, set one */
2397 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
2398 Teb
->NtTib
.StackLimit
,
2399 MemoryBasicInformation
,
2401 sizeof(MEMORY_BASIC_INFORMATION
),
2403 if (!NT_SUCCESS(Status
))
2406 LdrpInitFailure(Status
);
2407 RtlRaiseStatus(Status
);
2412 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
2415 /* Now check if the process is already being initialized */
2416 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
2420 /* Set the timeout to 30 milliseconds */
2421 Timeout
.QuadPart
= Int32x32To64(30, -10000);
2423 /* Make sure the status hasn't changed */
2424 while (LdrpProcessInitialized
== 1)
2427 ZwDelayExecution(FALSE
, &Timeout
);
2431 /* Check if we have already setup LDR data */
2434 /* Setup the Loader Lock */
2435 Peb
->LoaderLock
= &LdrpLoaderLock
;
2437 /* Let other code know we're initializing */
2438 LdrpInLdrInit
= TRUE
;
2440 /* Protect with SEH */
2443 /* Initialize the Process */
2444 LoaderStatus
= LdrpInitializeProcess(Context
,
2447 /* Check for success and if MinimumStackCommit was requested */
2448 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
2450 /* Enforce the limit */
2451 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2455 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2457 /* Fail with the SEH error */
2458 LoaderStatus
= _SEH2_GetExceptionCode();
2462 /* We're not initializing anymore */
2463 LdrpInLdrInit
= FALSE
;
2465 /* Check if init worked */
2466 if (NT_SUCCESS(LoaderStatus
))
2468 /* Set the process as Initialized */
2469 _InterlockedIncrement(&LdrpProcessInitialized
);
2474 /* Loader data is there... is this a fork() ? */
2475 if(Peb
->InheritedAddressSpace
)
2477 /* Handle the fork() */
2478 //LoaderStatus = LdrpForkProcess();
2479 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
2484 /* This is a new thread initializing */
2485 LdrpInitializeThread(Context
);
2489 /* All done, test alert the thread */
2493 if (!NT_SUCCESS(LoaderStatus
))
2496 LdrpInitFailure(LoaderStatus
);
2497 RtlRaiseStatus(LoaderStatus
);