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");
28 const UNICODE_STRING LdrpDotLocal
= RTL_CONSTANT_STRING(L
".Local");
30 BOOLEAN LdrpInLdrInit
;
31 LONG LdrpProcessInitialized
;
32 BOOLEAN LdrpLoaderLockInit
;
33 BOOLEAN LdrpLdrDatabaseIsSetup
;
34 BOOLEAN LdrpShutdownInProgress
;
35 HANDLE LdrpShutdownThreadId
;
37 BOOLEAN LdrpDllValidation
;
39 PLDR_DATA_TABLE_ENTRY LdrpImageEntry
;
40 PUNICODE_STRING LdrpTopLevelDllBeingLoaded
;
41 WCHAR StringBuffer
[156];
42 extern PTEB LdrpTopLevelDllBeingLoadedTeb
; // defined in rtlsupp.c!
43 PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer
;
44 PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry
;
46 static NTSTATUS (WINAPI
*Kernel32ProcessInitPostImportFunction
)(VOID
);
47 static BOOL (WINAPI
*Kernel32BaseQueryModuleData
)(IN LPSTR ModuleName
, IN LPSTR Unk1
, IN PVOID Unk2
, IN PVOID Unk3
, IN PVOID Unk4
);
50 RTL_BITMAP TlsExpansionBitMap
;
52 BOOLEAN LdrpImageHasTls
;
53 LIST_ENTRY LdrpTlsList
;
54 ULONG LdrpNumberOfTlsEntries
;
55 ULONG LdrpNumberOfProcessors
;
57 extern LARGE_INTEGER RtlpTimeout
;
58 BOOLEAN RtlpTimeoutDisable
;
60 LIST_ENTRY LdrpHashTable
[LDR_HASH_TABLE_ENTRIES
];
61 LIST_ENTRY LdrpDllNotificationList
;
62 HANDLE LdrpKnownDllObjectDirectory
;
63 UNICODE_STRING LdrpKnownDllPath
;
64 WCHAR LdrpKnownDllPathBuffer
[128];
65 UNICODE_STRING LdrpDefaultPath
;
69 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug
;
70 RTL_CRITICAL_SECTION LdrpLoaderLock
=
79 RTL_CRITICAL_SECTION FastPebLock
;
83 ULONG LdrpFatalHardErrorCount
;
84 ULONG LdrpActiveUnloadCount
;
86 //extern LIST_ENTRY RtlCriticalSectionList;
88 VOID NTAPI
RtlpInitializeVectoredExceptionHandling(VOID
);
89 VOID NTAPI
RtlpInitDeferedCriticalSection(VOID
);
90 VOID NTAPI
RtlInitializeHeapManager(VOID
);
92 ULONG RtlpDisableHeapLookaside
; // TODO: Move to heap.c
93 ULONG RtlpShutdownProcessFlags
; // TODO: Use it
95 NTSTATUS
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
, PVOID ImageBase
);
96 void actctx_init(void);
97 extern BOOLEAN RtlpUse16ByteSLists
;
100 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
102 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E
105 /* FUNCTIONS *****************************************************************/
112 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey
,
114 OUT PHANDLE NewKeyHandle
)
116 PHANDLE RootKeyLocation
;
118 UNICODE_STRING SubKeyString
;
119 OBJECT_ATTRIBUTES ObjectAttributes
;
123 /* Check which root key to open */
125 RootKeyLocation
= &Wow64ExecOptionsKey
;
127 RootKeyLocation
= &ImageExecOptionsKey
;
129 /* Get the current key */
130 RootKey
= *RootKeyLocation
;
132 /* Setup the object attributes */
133 InitializeObjectAttributes(&ObjectAttributes
,
135 &Wow64OptionsString
: &ImageExecOptionsString
,
136 OBJ_CASE_INSENSITIVE
,
140 /* Open the root key */
141 Status
= ZwOpenKey(&RootKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
142 if (NT_SUCCESS(Status
))
144 /* Write the key handle */
145 if (InterlockedCompareExchangePointer(RootKeyLocation
, RootKey
, NULL
) != NULL
)
147 /* Someone already opened it, use it instead */
149 RootKey
= *RootKeyLocation
;
152 /* Extract the name */
153 SubKeyString
= *SubKey
;
154 p1
= (PWCHAR
)((ULONG_PTR
)SubKeyString
.Buffer
+ SubKeyString
.Length
);
155 while (SubKeyString
.Length
)
157 if (p1
[-1] == L
'\\') break;
159 SubKeyString
.Length
-= sizeof(*p1
);
161 SubKeyString
.Buffer
= p1
;
162 SubKeyString
.Length
= SubKey
->Length
- SubKeyString
.Length
;
164 /* Setup the object attributes */
165 InitializeObjectAttributes(&ObjectAttributes
,
167 OBJ_CASE_INSENSITIVE
,
171 /* Open the setting key */
172 Status
= ZwOpenKey((PHANDLE
)NewKeyHandle
, GENERIC_READ
, &ObjectAttributes
);
175 /* Return to caller */
184 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle
,
189 OUT PULONG ReturnedLength OPTIONAL
)
192 UNICODE_STRING ValueNameString
, IntegerString
;
193 ULONG KeyInfoSize
, ResultSize
;
194 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)&KeyInfo
;
195 BOOLEAN FreeHeap
= FALSE
;
198 /* Build a string for the value name */
199 Status
= RtlInitUnicodeStringEx(&ValueNameString
, ValueName
);
200 if (!NT_SUCCESS(Status
)) return Status
;
202 /* Query the value */
203 Status
= ZwQueryValueKey(KeyHandle
,
205 KeyValuePartialInformation
,
209 if (Status
== STATUS_BUFFER_OVERFLOW
)
211 /* Our local buffer wasn't enough, allocate one */
212 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
213 KeyValueInformation
->DataLength
;
214 KeyValueInformation
= RtlAllocateHeap(RtlGetProcessHeap(),
217 if (KeyValueInformation
!= NULL
)
220 Status
= ZwQueryValueKey(KeyHandle
,
222 KeyValuePartialInformation
,
230 /* Give up this time */
231 Status
= STATUS_NO_MEMORY
;
235 /* Check for success */
236 if (NT_SUCCESS(Status
))
238 /* Handle binary data */
239 if (KeyValueInformation
->Type
== REG_BINARY
)
242 if ((Buffer
) && (KeyValueInformation
->DataLength
<= BufferSize
))
244 /* Copy into buffer */
245 RtlMoveMemory(Buffer
,
246 &KeyValueInformation
->Data
,
247 KeyValueInformation
->DataLength
);
251 Status
= STATUS_BUFFER_OVERFLOW
;
254 /* Copy the result length */
255 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
257 else if (KeyValueInformation
->Type
== REG_DWORD
)
259 /* Check for valid type */
260 if (KeyValueInformation
->Type
!= Type
)
263 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
269 (BufferSize
== sizeof(ULONG
)) &&
270 (KeyValueInformation
->DataLength
<= BufferSize
))
272 /* Copy into buffer */
273 RtlMoveMemory(Buffer
,
274 &KeyValueInformation
->Data
,
275 KeyValueInformation
->DataLength
);
279 Status
= STATUS_BUFFER_OVERFLOW
;
282 /* Copy the result length */
283 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
286 else if (KeyValueInformation
->Type
!= REG_SZ
)
288 /* We got something weird */
289 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
293 /* String, check what you requested */
294 if (Type
== REG_DWORD
)
297 if (BufferSize
!= sizeof(ULONG
))
301 Status
= STATUS_INFO_LENGTH_MISMATCH
;
305 /* OK, we know what you want... */
306 IntegerString
.Buffer
= (PWSTR
)KeyValueInformation
->Data
;
307 IntegerString
.Length
= (USHORT
)KeyValueInformation
->DataLength
-
309 IntegerString
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
310 Status
= RtlUnicodeStringToInteger(&IntegerString
, 0, (PULONG
)Buffer
);
316 if (KeyValueInformation
->DataLength
> BufferSize
)
319 Status
= STATUS_BUFFER_OVERFLOW
;
324 BufferSize
= KeyValueInformation
->DataLength
;
327 /* Copy the string */
328 RtlMoveMemory(Buffer
, &KeyValueInformation
->Data
, BufferSize
);
331 /* Copy the result length */
332 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
336 /* Check if buffer was in heap */
337 if (FreeHeap
) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation
);
348 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey
,
353 OUT PULONG ReturnedLength OPTIONAL
,
359 /* Open a handle to the key */
360 Status
= LdrOpenImageFileOptionsKey(SubKey
, Wow64
, &KeyHandle
);
362 /* Check for success */
363 if (NT_SUCCESS(Status
))
366 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
377 /* Return to caller */
386 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey
,
391 OUT PULONG ReturnedLength OPTIONAL
)
393 /* Call the newer function */
394 return LdrQueryImageFileExecutionOptionsEx(SubKey
,
405 LdrpEnsureLoaderLockIsHeld(VOID
)
412 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress
, ULONG SizeOfImage
)
414 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir
;
418 /* Check NT header first */
419 if (!RtlImageNtHeader(BaseAddress
)) return NULL
;
421 /* Get the pointer to the config directory */
422 ConfigDir
= RtlImageDirectoryEntryToData(BaseAddress
,
424 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
427 /* Check for sanity */
429 (DirSize
!= 64 && ConfigDir
->Size
!= DirSize
) ||
430 (ConfigDir
->Size
< 0x48))
433 /* Now get the cookie */
434 Cookie
= (PVOID
)ConfigDir
->SecurityCookie
;
436 /* Check this cookie */
437 if ((PCHAR
)Cookie
<= (PCHAR
)BaseAddress
||
438 (PCHAR
)Cookie
>= (PCHAR
)BaseAddress
+ SizeOfImage
)
443 /* Return validated security cookie */
449 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry
)
452 LARGE_INTEGER Counter
;
455 /* Fetch address of the cookie */
456 Cookie
= LdrpFetchAddressOfSecurityCookie(LdrEntry
->DllBase
, LdrEntry
->SizeOfImage
);
460 /* Check if it's a default one */
461 if ((*Cookie
== DEFAULT_SECURITY_COOKIE
) ||
464 /* Make up a cookie from a bunch of values which may uniquely represent
465 current moment of time, environment, etc */
466 NtQueryPerformanceCounter(&Counter
, NULL
);
468 NewCookie
= Counter
.LowPart
^ Counter
.HighPart
;
469 NewCookie
^= (ULONG_PTR
)NtCurrentTeb()->ClientId
.UniqueProcess
;
470 NewCookie
^= (ULONG_PTR
)NtCurrentTeb()->ClientId
.UniqueThread
;
472 /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */
473 while (SharedUserData
->SystemTime
.High1Time
!= SharedUserData
->SystemTime
.High2Time
)
478 /* Calculate the milliseconds value and xor it to the cookie */
479 NewCookie
^= Int64ShrlMod32(UInt32x32To64(SharedUserData
->TickCountMultiplier
, SharedUserData
->TickCount
.LowPart
), 24) +
480 (SharedUserData
->TickCountMultiplier
* (SharedUserData
->TickCount
.High1Time
<< 8));
482 /* Make the cookie 16bit if necessary */
483 if (*Cookie
== 0xBB40) NewCookie
&= 0xFFFF;
485 /* If the result is 0 or the same as we got, just subtract one from the existing value
487 if ((NewCookie
== 0) || (NewCookie
== *Cookie
))
489 NewCookie
= *Cookie
- 1;
492 /* Set the new cookie value */
502 LdrpInitializeThread(IN PCONTEXT Context
)
504 PPEB Peb
= NtCurrentPeb();
505 PLDR_DATA_TABLE_ENTRY LdrEntry
;
506 PLIST_ENTRY NextEntry
, ListHead
;
507 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
511 DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n",
512 &LdrpImageEntry
->BaseDllName
,
513 NtCurrentTeb()->RealClientId
.UniqueProcess
,
514 NtCurrentTeb()->RealClientId
.UniqueThread
);
516 /* Allocate an Activation Context Stack */
517 DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer
);
518 Status
= RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer
);
519 if (!NT_SUCCESS(Status
))
521 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
524 /* Make sure we are not shutting down */
525 if (LdrpShutdownInProgress
) return;
530 /* Start at the beginning */
531 ListHead
= &Peb
->Ldr
->InMemoryOrderModuleList
;
532 NextEntry
= ListHead
->Flink
;
533 while (NextEntry
!= ListHead
)
535 /* Get the current entry */
536 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InMemoryOrderLinks
);
538 /* Make sure it's not ourselves */
539 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
541 /* Check if we should call */
542 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
))
544 /* Get the entrypoint */
545 EntryPoint
= LdrEntry
->EntryPoint
;
547 /* Check if we are ready to call it */
549 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
550 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
552 /* Set up the Act Ctx */
553 ActCtx
.Size
= sizeof(ActCtx
);
555 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
557 /* Activate the ActCtx */
558 RtlActivateActivationContextUnsafeFast(&ActCtx
,
559 LdrEntry
->EntryPointActivationContext
);
563 /* Check if it has TLS */
564 if (LdrEntry
->TlsIndex
)
566 /* Make sure we're not shutting down */
567 if (!LdrpShutdownInProgress
)
570 LdrpCallTlsInitializers(LdrEntry
, DLL_THREAD_ATTACH
);
574 /* Make sure we're not shutting down */
575 if (!LdrpShutdownInProgress
)
577 /* Call the Entrypoint */
578 DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n",
579 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
,
580 NtCurrentTeb()->RealClientId
.UniqueProcess
,
581 NtCurrentTeb()->RealClientId
.UniqueThread
);
582 LdrpCallInitRoutine(LdrEntry
->EntryPoint
,
588 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
590 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_ATTACH) for %wZ\n",
591 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
595 /* Deactivate the ActCtx */
596 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
602 NextEntry
= NextEntry
->Flink
;
606 if (LdrpImageHasTls
&& !LdrpShutdownInProgress
)
608 /* Set up the Act Ctx */
609 ActCtx
.Size
= sizeof(ActCtx
);
611 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
613 /* Activate the ActCtx */
614 RtlActivateActivationContextUnsafeFast(&ActCtx
,
615 LdrpImageEntry
->EntryPointActivationContext
);
619 /* Do TLS callbacks */
620 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_THREAD_ATTACH
);
622 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
628 /* Deactivate the ActCtx */
629 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
632 DPRINT("LdrpInitializeThread() done\n");
637 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL
)
639 PLDR_DATA_TABLE_ENTRY LocalArray
[16];
640 PLIST_ENTRY ListHead
;
641 PLIST_ENTRY NextEntry
;
642 PLDR_DATA_TABLE_ENTRY LdrEntry
, *LdrRootEntry
, OldInitializer
;
646 NTSTATUS Status
= STATUS_SUCCESS
;
647 PPEB Peb
= NtCurrentPeb();
648 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
649 ULONG BreakOnDllLoad
;
653 DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
654 &LdrpImageEntry
->BaseDllName
,
655 NtCurrentTeb()->RealClientId
.UniqueProcess
,
656 NtCurrentTeb()->RealClientId
.UniqueThread
);
658 /* Check the Loader Lock */
659 LdrpEnsureLoaderLockIsHeld();
661 /* Get the number of entries to call */
662 if ((Count
= LdrpClearLoadInProgress()))
664 /* Check if we can use our local buffer */
667 /* Allocate space for all the entries */
668 LdrRootEntry
= RtlAllocateHeap(LdrpHeap
,
670 Count
* sizeof(*LdrRootEntry
));
671 if (!LdrRootEntry
) return STATUS_NO_MEMORY
;
675 /* Use our local array */
676 LdrRootEntry
= LocalArray
;
685 /* Show debug message */
688 DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
689 NtCurrentTeb()->RealClientId
.UniqueThread
,
690 NtCurrentTeb()->RealClientId
.UniqueProcess
,
691 &Peb
->ProcessParameters
->ImagePathName
);
695 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
696 NextEntry
= ListHead
->Flink
;
698 while (NextEntry
!= ListHead
)
700 /* Get the Data Entry */
701 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
703 /* Check if we have a Root Entry */
707 if (!(LdrEntry
->Flags
& LDRP_ENTRY_PROCESSED
))
709 /* Setup the Cookie for the DLL */
710 LdrpInitSecurityCookie(LdrEntry
);
712 /* Check for valid entrypoint */
713 if (LdrEntry
->EntryPoint
)
717 LdrRootEntry
[i
] = LdrEntry
;
719 /* Display debug message */
722 DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
723 NtCurrentTeb()->RealClientId
.UniqueThread
,
724 NtCurrentTeb()->RealClientId
.UniqueProcess
,
725 &LdrEntry
->FullDllName
,
726 LdrEntry
->EntryPoint
);
734 LdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
735 NextEntry
= NextEntry
->Flink
;
738 Status
= STATUS_SUCCESS
;
740 /* If we got a context, then we have to call Kernel32 for TS support */
743 /* Check if we have one */
744 if (Kernel32ProcessInitPostImportFunction
)
747 Status
= Kernel32ProcessInitPostImportFunction();
748 if (!NT_SUCCESS(Status
))
750 DPRINT1("LDR: LdrpRunInitializeRoutines - Failed running kernel32 post-import function, Status=0x%08lx\n", Status
);
754 Kernel32ProcessInitPostImportFunction
= NULL
;
757 /* No root entry? return */
761 /* Set the TLD TEB */
762 OldTldTeb
= LdrpTopLevelDllBeingLoadedTeb
;
763 LdrpTopLevelDllBeingLoadedTeb
= NtCurrentTeb();
770 LdrEntry
= LdrRootEntry
[i
];
772 /* FIXME: Verify NX Compat */
774 /* Move to next entry */
777 /* Get its entrypoint */
778 EntryPoint
= LdrEntry
->EntryPoint
;
780 /* Are we being debugged? */
782 if (Peb
->BeingDebugged
|| Peb
->ReadImageFileExecOptions
)
784 /* Check if we should break on load */
785 Status
= LdrQueryImageFileExecutionOptions(&LdrEntry
->BaseDllName
,
791 if (!NT_SUCCESS(Status
)) BreakOnDllLoad
= 0;
793 /* Reset status back to STATUS_SUCCESS */
794 Status
= STATUS_SUCCESS
;
800 /* Check if we should show a message */
803 DPRINT1("LDR: %wZ loaded.", &LdrEntry
->BaseDllName
);
804 DPRINT1(" - About to call init routine at %p\n", EntryPoint
);
807 /* Break in debugger */
811 /* Make sure we have an entrypoint */
814 /* Save the old Dll Initializer and write the current one */
815 OldInitializer
= LdrpCurrentDllInitializer
;
816 LdrpCurrentDllInitializer
= LdrEntry
;
818 /* Set up the Act Ctx */
819 ActCtx
.Size
= sizeof(ActCtx
);
821 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
823 /* Activate the ActCtx */
824 RtlActivateActivationContextUnsafeFast(&ActCtx
,
825 LdrEntry
->EntryPointActivationContext
);
829 /* Check if it has TLS */
830 if (LdrEntry
->TlsIndex
&& Context
)
833 LdrpCallTlsInitializers(LdrEntry
, DLL_PROCESS_ATTACH
);
836 /* Call the Entrypoint */
839 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
840 &LdrEntry
->BaseDllName
, EntryPoint
);
842 DllStatus
= LdrpCallInitRoutine(EntryPoint
,
847 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
850 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_ATTACH) for %wZ\n",
851 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
855 /* Deactivate the ActCtx */
856 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
858 /* Save the Current DLL Initializer */
859 LdrpCurrentDllInitializer
= OldInitializer
;
861 /* Mark the entry as processed */
862 LdrEntry
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
;
864 /* Fail if DLL init failed */
867 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
868 &LdrEntry
->BaseDllName
, EntryPoint
);
870 Status
= STATUS_DLL_INIT_FAILED
;
877 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
878 NextEntry
= NextEntry
->Flink
;
879 while (NextEntry
!= ListHead
)
881 /* Get the Data Entry */
882 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
884 /* FIXME: Verify NX Compat */
885 // LdrpCheckNXCompatibility()
888 NextEntry
= NextEntry
->Flink
;
892 if (LdrpImageHasTls
&& Context
)
894 /* Set up the Act Ctx */
895 ActCtx
.Size
= sizeof(ActCtx
);
897 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
899 /* Activate the ActCtx */
900 RtlActivateActivationContextUnsafeFast(&ActCtx
,
901 LdrpImageEntry
->EntryPointActivationContext
);
905 /* Do TLS callbacks */
906 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_PROCESS_ATTACH
);
908 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
914 /* Deactivate the ActCtx */
915 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
919 /* Restore old TEB */
920 LdrpTopLevelDllBeingLoadedTeb
= OldTldTeb
;
922 /* Check if the array is in the heap */
923 if (LdrRootEntry
!= LocalArray
)
926 RtlFreeHeap(LdrpHeap
, 0, LdrRootEntry
);
929 /* Return to caller */
930 DPRINT("LdrpRunInitializeRoutines() done\n");
939 LdrShutdownProcess(VOID
)
941 PPEB Peb
= NtCurrentPeb();
942 PLDR_DATA_TABLE_ENTRY LdrEntry
;
943 PLIST_ENTRY NextEntry
, ListHead
;
944 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
947 DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry
->BaseDllName
);
948 if (LdrpShutdownInProgress
) return STATUS_SUCCESS
;
950 /* Tell the Shim Engine */
953 VOID(NTAPI
*SE_ProcessDying
)();
954 SE_ProcessDying
= RtlDecodeSystemPointer(g_pfnSE_ProcessDying
);
964 /* Set the shutdown variables */
965 LdrpShutdownThreadId
= NtCurrentTeb()->RealClientId
.UniqueThread
;
966 LdrpShutdownInProgress
= TRUE
;
968 /* Enter the Loader Lock */
969 RtlEnterCriticalSection(&LdrpLoaderLock
);
971 /* Cleanup trace logging data (Etw) */
972 if (SharedUserData
->TraceLogging
)
975 DPRINT1("We don't support Etw yet.\n");
978 /* Start at the end */
979 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
980 NextEntry
= ListHead
->Blink
;
981 while (NextEntry
!= ListHead
)
983 /* Get the current entry */
984 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
985 NextEntry
= NextEntry
->Blink
;
987 /* Make sure it's not ourselves */
988 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
990 /* Get the entrypoint */
991 EntryPoint
= LdrEntry
->EntryPoint
;
993 /* Check if we are ready to call it */
995 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
998 /* Set up the Act Ctx */
999 ActCtx
.Size
= sizeof(ActCtx
);
1001 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1003 /* Activate the ActCtx */
1004 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1005 LdrEntry
->EntryPointActivationContext
);
1009 /* Check if it has TLS */
1010 if (LdrEntry
->TlsIndex
)
1013 LdrpCallTlsInitializers(LdrEntry
, DLL_PROCESS_DETACH
);
1016 /* Call the Entrypoint */
1017 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1018 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1019 LdrpCallInitRoutine(EntryPoint
,
1024 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1026 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_DETACH) for %wZ\n",
1027 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
1031 /* Deactivate the ActCtx */
1032 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1038 if (LdrpImageHasTls
)
1040 /* Set up the Act Ctx */
1041 ActCtx
.Size
= sizeof(ActCtx
);
1043 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1045 /* Activate the ActCtx */
1046 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1047 LdrpImageEntry
->EntryPointActivationContext
);
1051 /* Do TLS callbacks */
1052 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_PROCESS_DETACH
);
1054 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1060 /* Deactivate the ActCtx */
1061 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1064 /* FIXME: Do Heap detection and Etw final shutdown */
1066 /* Release the lock */
1067 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1068 DPRINT("LdrpShutdownProcess() done\n");
1070 return STATUS_SUCCESS
;
1078 LdrShutdownThread(VOID
)
1080 PPEB Peb
= NtCurrentPeb();
1081 PTEB Teb
= NtCurrentTeb();
1082 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1083 PLIST_ENTRY NextEntry
, ListHead
;
1084 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
1087 DPRINT("LdrShutdownThread() called for %wZ\n",
1088 &LdrpImageEntry
->BaseDllName
);
1090 /* Cleanup trace logging data (Etw) */
1091 if (SharedUserData
->TraceLogging
)
1094 DPRINT1("We don't support Etw yet.\n");
1097 /* Get the Ldr Lock */
1098 RtlEnterCriticalSection(&LdrpLoaderLock
);
1100 /* Start at the end */
1101 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
1102 NextEntry
= ListHead
->Blink
;
1103 while (NextEntry
!= ListHead
)
1105 /* Get the current entry */
1106 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
1107 NextEntry
= NextEntry
->Blink
;
1109 /* Make sure it's not ourselves */
1110 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
1112 /* Check if we should call */
1113 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
1114 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
1115 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
1117 /* Get the entrypoint */
1118 EntryPoint
= LdrEntry
->EntryPoint
;
1120 /* Check if we are ready to call it */
1123 /* Set up the Act Ctx */
1124 ActCtx
.Size
= sizeof(ActCtx
);
1126 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1128 /* Activate the ActCtx */
1129 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1130 LdrEntry
->EntryPointActivationContext
);
1134 /* Check if it has TLS */
1135 if (LdrEntry
->TlsIndex
)
1137 /* Make sure we're not shutting down */
1138 if (!LdrpShutdownInProgress
)
1141 LdrpCallTlsInitializers(LdrEntry
, DLL_THREAD_DETACH
);
1145 /* Make sure we're not shutting down */
1146 if (!LdrpShutdownInProgress
)
1148 /* Call the Entrypoint */
1149 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1150 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1151 LdrpCallInitRoutine(EntryPoint
,
1157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1159 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_DETACH) for %wZ\n",
1160 _SEH2_GetExceptionCode(), &LdrEntry
->BaseDllName
);
1164 /* Deactivate the ActCtx */
1165 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1172 if (LdrpImageHasTls
)
1174 /* Set up the Act Ctx */
1175 ActCtx
.Size
= sizeof(ActCtx
);
1177 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1179 /* Activate the ActCtx */
1180 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1181 LdrpImageEntry
->EntryPointActivationContext
);
1185 /* Do TLS callbacks */
1186 LdrpCallTlsInitializers(LdrpImageEntry
, DLL_THREAD_DETACH
);
1188 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1194 /* Deactivate the ActCtx */
1195 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1200 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1202 /* Check for expansion slots */
1203 if (Teb
->TlsExpansionSlots
)
1205 /* Free expansion slots */
1206 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->TlsExpansionSlots
);
1209 /* Check for FLS Data */
1212 /* Mimic BaseRundownFls */
1213 ULONG n
, FlsHighIndex
;
1214 PRTL_FLS_DATA pFlsData
;
1215 PFLS_CALLBACK_FUNCTION lpCallback
;
1217 pFlsData
= Teb
->FlsData
;
1219 RtlAcquirePebLock();
1220 FlsHighIndex
= NtCurrentPeb()->FlsHighIndex
;
1221 RemoveEntryList(&pFlsData
->ListEntry
);
1222 RtlReleasePebLock();
1224 for (n
= 1; n
<= FlsHighIndex
; ++n
)
1226 lpCallback
= NtCurrentPeb()->FlsCallback
[n
];
1227 if (lpCallback
&& pFlsData
->Data
[n
])
1229 lpCallback(pFlsData
->Data
[n
]);
1233 RtlFreeHeap(RtlGetProcessHeap(), 0, pFlsData
);
1234 Teb
->FlsData
= NULL
;
1237 /* Check for Fiber data */
1238 if (Teb
->HasFiberData
)
1240 /* Free Fiber data*/
1241 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->NtTib
.FiberData
);
1242 Teb
->NtTib
.FiberData
= NULL
;
1245 /* Free the activation context stack */
1246 RtlFreeThreadActivationContextStack();
1247 DPRINT("LdrShutdownThread() done\n");
1249 return STATUS_SUCCESS
;
1254 LdrpInitializeTls(VOID
)
1256 PLIST_ENTRY NextEntry
, ListHead
;
1257 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1258 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1259 PLDRP_TLS_DATA TlsData
;
1262 /* Initialize the TLS List */
1263 InitializeListHead(&LdrpTlsList
);
1265 /* Loop all the modules */
1266 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1267 NextEntry
= ListHead
->Flink
;
1268 while (ListHead
!= NextEntry
)
1271 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1272 NextEntry
= NextEntry
->Flink
;
1274 /* Get the TLS directory */
1275 TlsDirectory
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
1277 IMAGE_DIRECTORY_ENTRY_TLS
,
1280 /* Check if we have a directory */
1281 if (!TlsDirectory
) continue;
1283 /* Check if the image has TLS */
1284 if (!LdrpImageHasTls
) LdrpImageHasTls
= TRUE
;
1286 /* Show debug message */
1289 DPRINT1("LDR: Tls Found in %wZ at %p\n",
1290 &LdrEntry
->BaseDllName
,
1294 /* Allocate an entry */
1295 TlsData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA
));
1296 if (!TlsData
) return STATUS_NO_MEMORY
;
1298 /* Lock the DLL and mark it for TLS Usage */
1299 LdrEntry
->LoadCount
= -1;
1300 LdrEntry
->TlsIndex
= -1;
1302 /* Save the cached TLS data */
1303 TlsData
->TlsDirectory
= *TlsDirectory
;
1304 InsertTailList(&LdrpTlsList
, &TlsData
->TlsLinks
);
1306 /* Update the index */
1307 *(PLONG
)TlsData
->TlsDirectory
.AddressOfIndex
= LdrpNumberOfTlsEntries
;
1308 TlsData
->TlsDirectory
.Characteristics
= LdrpNumberOfTlsEntries
++;
1311 /* Done setting up TLS, allocate entries */
1312 return LdrpAllocateTls();
1317 LdrpAllocateTls(VOID
)
1319 PTEB Teb
= NtCurrentTeb();
1320 PLIST_ENTRY NextEntry
, ListHead
;
1321 PLDRP_TLS_DATA TlsData
;
1325 /* Check if we have any entries */
1326 if (!LdrpNumberOfTlsEntries
)
1327 return STATUS_SUCCESS
;
1329 /* Allocate the vector array */
1330 TlsVector
= RtlAllocateHeap(RtlGetProcessHeap(),
1332 LdrpNumberOfTlsEntries
* sizeof(PVOID
));
1333 if (!TlsVector
) return STATUS_NO_MEMORY
;
1334 Teb
->ThreadLocalStoragePointer
= TlsVector
;
1336 /* Loop the TLS Array */
1337 ListHead
= &LdrpTlsList
;
1338 NextEntry
= ListHead
->Flink
;
1339 while (NextEntry
!= ListHead
)
1342 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1343 NextEntry
= NextEntry
->Flink
;
1345 /* Allocate this vector */
1346 TlsDataSize
= TlsData
->TlsDirectory
.EndAddressOfRawData
-
1347 TlsData
->TlsDirectory
.StartAddressOfRawData
;
1348 TlsVector
[TlsData
->TlsDirectory
.Characteristics
] = RtlAllocateHeap(RtlGetProcessHeap(),
1351 if (!TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1354 return STATUS_NO_MEMORY
;
1357 /* Show debug message */
1360 DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
1362 TlsData
->TlsDirectory
.Characteristics
,
1363 &TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1364 TlsData
->TlsDirectory
.StartAddressOfRawData
,
1365 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1369 RtlCopyMemory(TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1370 (PVOID
)TlsData
->TlsDirectory
.StartAddressOfRawData
,
1375 return STATUS_SUCCESS
;
1382 PLIST_ENTRY ListHead
, NextEntry
;
1383 PLDRP_TLS_DATA TlsData
;
1385 PTEB Teb
= NtCurrentTeb();
1387 /* Get a pointer to the vector array */
1388 TlsVector
= Teb
->ThreadLocalStoragePointer
;
1389 if (!TlsVector
) return;
1391 /* Loop through it */
1392 ListHead
= &LdrpTlsList
;
1393 NextEntry
= ListHead
->Flink
;
1394 while (NextEntry
!= ListHead
)
1396 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1397 NextEntry
= NextEntry
->Flink
;
1399 /* Free each entry */
1400 if (TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1402 RtlFreeHeap(RtlGetProcessHeap(),
1404 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1408 /* Free the array itself */
1409 RtlFreeHeap(RtlGetProcessHeap(),
1416 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName
, PPEB Peb
, PHANDLE OptionsKey
)
1420 ULONG ExecuteOptions
, MinimumStackCommit
= 0, GlobalFlag
;
1422 /* Return error if we were not provided a pointer where to save the options key handle */
1423 if (!OptionsKey
) return STATUS_INVALID_HANDLE
;
1425 /* Zero initialize the options key pointer */
1428 /* Open the options key */
1429 Status
= LdrOpenImageFileOptionsKey(ImagePathName
, 0, &KeyHandle
);
1431 /* Save it if it was opened successfully */
1432 if (NT_SUCCESS(Status
))
1433 *OptionsKey
= KeyHandle
;
1437 /* There are image specific options, read them starting with NXCOMPAT */
1438 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1442 sizeof(ExecuteOptions
),
1445 if (NT_SUCCESS(Status
))
1447 /* TODO: Set execution options for the process */
1449 if (ExecuteOptions == 0)
1453 ZwSetInformationProcess(NtCurrentProcess(),
1454 ProcessExecuteFlags,
1460 /* Check if this image uses large pages */
1461 if (Peb
->ImageUsesLargePages
)
1463 /* TODO: If it does, open large page key */
1467 /* Get various option values */
1468 LdrQueryImageFileKeyOption(KeyHandle
,
1469 L
"DisableHeapLookaside",
1471 &RtlpDisableHeapLookaside
,
1472 sizeof(RtlpDisableHeapLookaside
),
1475 LdrQueryImageFileKeyOption(KeyHandle
,
1478 &RtlpShutdownProcessFlags
,
1479 sizeof(RtlpShutdownProcessFlags
),
1482 LdrQueryImageFileKeyOption(KeyHandle
,
1483 L
"MinimumStackCommitInBytes",
1485 &MinimumStackCommit
,
1486 sizeof(MinimumStackCommit
),
1489 /* Update PEB's minimum stack commit if it's lower */
1490 if (Peb
->MinimumStackCommit
< MinimumStackCommit
)
1491 Peb
->MinimumStackCommit
= MinimumStackCommit
;
1493 /* Set the global flag */
1494 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1501 if (NT_SUCCESS(Status
))
1502 Peb
->NtGlobalFlag
= GlobalFlag
;
1506 /* Call AVRF if necessary */
1507 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1509 Status
= LdrpInitializeApplicationVerifierPackage(KeyHandle
, Peb
, TRUE
, FALSE
);
1510 if (!NT_SUCCESS(Status
))
1512 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1518 /* There are no image-specific options, so perform global initialization */
1519 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1521 /* Initialize app verifier package */
1522 Status
= LdrpInitializeApplicationVerifierPackage(KeyHandle
, Peb
, TRUE
, FALSE
);
1523 if (!NT_SUCCESS(Status
))
1525 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1530 return STATUS_SUCCESS
;
1535 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
)
1542 LdrpInitializeProcessCompat(PVOID
* pOldShimData
)
1544 static const GUID
* GuidOrder
[] = { &COMPAT_GUID_WIN10
, &COMPAT_GUID_WIN81
, &COMPAT_GUID_WIN8
,
1545 &COMPAT_GUID_WIN7
, &COMPAT_GUID_VISTA
};
1546 static const DWORD GuidVersions
[] = { WINVER_WIN10
, WINVER_WIN81
, WINVER_WIN8
, WINVER_WIN7
, WINVER_VISTA
};
1548 ULONG Buffer
[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
)) / sizeof(ULONG
)];
1549 ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
* ContextCompatInfo
;
1550 SIZE_T SizeRequired
;
1553 ReactOS_ShimData
* pShimData
= *pOldShimData
;
1555 C_ASSERT(RTL_NUMBER_OF(GuidOrder
) == RTL_NUMBER_OF(GuidVersions
));
1559 if (pShimData
->dwMagic
!= REACTOS_SHIMDATA_MAGIC
||
1560 pShimData
->dwSize
!= sizeof(ReactOS_ShimData
))
1562 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData
->dwMagic
, pShimData
->dwSize
);
1565 if (pShimData
->dwRosProcessCompatVersion
)
1567 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData
->dwRosProcessCompatVersion
);
1572 SizeRequired
= sizeof(Buffer
);
1573 Status
= RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
,
1576 CompatibilityInformationInActivationContext
,
1581 if (!NT_SUCCESS(Status
))
1583 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status
);
1587 ContextCompatInfo
= (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
*)Buffer
;
1588 /* No Compatibility elements present, bail out */
1589 if (ContextCompatInfo
->ElementCount
== 0)
1592 /* Search for known GUID's, starting from newest to oldest. */
1593 for (cur
= 0; cur
< RTL_NUMBER_OF(GuidOrder
); ++cur
)
1595 for (n
= 0; n
< ContextCompatInfo
->ElementCount
; ++n
)
1597 if (ContextCompatInfo
->Elements
[n
].Type
== ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
&&
1598 RtlCompareMemory(&ContextCompatInfo
->Elements
[n
].Id
, GuidOrder
[cur
], sizeof(GUID
)) == sizeof(GUID
))
1600 /* If this process did not need shim data before, allocate and store it */
1601 if (pShimData
== NULL
)
1603 PPEB Peb
= NtCurrentPeb();
1605 ASSERT(Peb
->pShimData
== NULL
);
1606 pShimData
= RtlAllocateHeap(Peb
->ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(*pShimData
));
1610 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData
));
1614 pShimData
->dwSize
= sizeof(*pShimData
);
1615 pShimData
->dwMagic
= REACTOS_SHIMDATA_MAGIC
;
1617 Peb
->pShimData
= pShimData
;
1618 *pOldShimData
= pShimData
;
1621 /* Store the highest found version, and bail out. */
1622 pShimData
->dwRosProcessCompatVersion
= GuidVersions
[cur
];
1623 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", GuidVersions
[cur
]);
1632 LdrpInitializeDotLocalSupport(PRTL_USER_PROCESS_PARAMETERS ProcessParameters
)
1634 UNICODE_STRING ImagePathName
= ProcessParameters
->ImagePathName
;
1635 WCHAR LocalBuffer
[MAX_PATH
];
1636 UNICODE_STRING DotLocal
;
1640 RequiredSize
= ImagePathName
.Length
+ LdrpDotLocal
.Length
+ sizeof(UNICODE_NULL
);
1641 if (RequiredSize
<= sizeof(LocalBuffer
))
1643 RtlInitEmptyUnicodeString(&DotLocal
, LocalBuffer
, sizeof(LocalBuffer
));
1645 else if (RequiredSize
<= UNICODE_STRING_MAX_BYTES
)
1647 DotLocal
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, RequiredSize
);
1648 DotLocal
.Length
= 0;
1649 DotLocal
.MaximumLength
= RequiredSize
;
1650 if (!DotLocal
.Buffer
)
1651 DPRINT1("LDR: Failed to allocate memory for .local check\n");
1655 DotLocal
.Buffer
= NULL
;
1656 DotLocal
.Length
= 0;
1657 DotLocal
.MaximumLength
= 0;
1658 DPRINT1("LDR: String too big for .local check\n");
1661 if (DotLocal
.Buffer
)
1663 Status
= RtlAppendUnicodeStringToString(&DotLocal
, &ImagePathName
);
1664 ASSERT(NT_SUCCESS(Status
));
1665 if (NT_SUCCESS(Status
))
1667 Status
= RtlAppendUnicodeStringToString(&DotLocal
, &LdrpDotLocal
);
1668 ASSERT(NT_SUCCESS(Status
));
1671 if (NT_SUCCESS(Status
))
1673 if (RtlDoesFileExists_UStr(&DotLocal
))
1675 ProcessParameters
->Flags
|= RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH
;
1680 DPRINT1("LDR: Failed to append: 0x%lx\n", Status
);
1683 if (DotLocal
.Buffer
!= LocalBuffer
)
1685 RtlFreeHeap(RtlGetProcessHeap(), 0, DotLocal
.Buffer
);
1693 LdrpInitializeProcess(IN PCONTEXT Context
,
1694 IN PVOID SystemArgument1
)
1696 RTL_HEAP_PARAMETERS HeapParameters
;
1697 ULONG ComSectionSize
;
1698 ANSI_STRING BaseProcessInitPostImportName
= RTL_CONSTANT_STRING("BaseProcessInitPostImport");
1699 ANSI_STRING BaseQueryModuleDataName
= RTL_CONSTANT_STRING("BaseQueryModuleData");
1701 OBJECT_ATTRIBUTES ObjectAttributes
;
1702 //UNICODE_STRING LocalFileName, FullImageName;
1703 HANDLE SymLinkHandle
;
1704 //ULONG DebugHeapOnly;
1705 UNICODE_STRING CommandLine
, NtSystemRoot
, ImagePathName
, FullPath
, ImageFileName
, KnownDllString
;
1706 PPEB Peb
= NtCurrentPeb();
1707 BOOLEAN IsDotNetImage
= FALSE
;
1708 BOOLEAN FreeCurDir
= FALSE
;
1710 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1711 //LPWSTR ImagePathBuffer;
1713 UNICODE_STRING CurrentDirectory
;
1716 PIMAGE_NT_HEADERS NtHeader
;
1717 LPWSTR NtDllName
= NULL
;
1718 NTSTATUS Status
, ImportStatus
;
1719 NLSTABLEINFO NlsTable
;
1720 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig
;
1721 PTEB Teb
= NtCurrentTeb();
1722 PLIST_ENTRY ListHead
;
1723 PLIST_ENTRY NextEntry
;
1726 ULONG DebugProcessHeapOnly
= 0;
1727 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
1729 ULONG ExecuteOptions
= 0;
1732 /* Set a NULL SEH Filter */
1733 RtlSetUnhandledExceptionFilter(NULL
);
1735 /* Get the image path */
1736 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
1738 /* Check if it's not normalized */
1739 if (!(Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
))
1742 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
1745 /* Create a unicode string for the Image Path */
1746 ImagePathName
.Length
= Peb
->ProcessParameters
->ImagePathName
.Length
;
1747 ImagePathName
.MaximumLength
= ImagePathName
.Length
+ sizeof(WCHAR
);
1748 ImagePathName
.Buffer
= ImagePath
;
1750 /* Get the NT Headers */
1751 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
1753 /* Get the execution options */
1754 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &OptionsKey
);
1756 /* Check if this is a .NET executable */
1757 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1759 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
1762 /* Remember this for later */
1763 IsDotNetImage
= TRUE
;
1766 /* Save the NTDLL Base address */
1767 NtDllBase
= SystemArgument1
;
1769 /* If this is a Native Image */
1770 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
1772 /* Then do DLL Validation */
1773 LdrpDllValidation
= TRUE
;
1776 /* Save the old Shim Data */
1777 OldShimData
= Peb
->pShimData
;
1779 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */
1780 //Peb->pShimData = NULL;
1782 /* Save the number of processors and CS Timeout */
1783 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
1784 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
1786 /* Normalize the parameters */
1787 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
1788 if (ProcessParameters
)
1790 /* Save the Image and Command Line Names */
1791 ImageFileName
= ProcessParameters
->ImagePathName
;
1792 CommandLine
= ProcessParameters
->CommandLine
;
1796 /* It failed, initialize empty strings */
1797 RtlInitUnicodeString(&ImageFileName
, NULL
);
1798 RtlInitUnicodeString(&CommandLine
, NULL
);
1801 /* Initialize NLS data */
1802 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1803 Peb
->OemCodePageData
,
1804 Peb
->UnicodeCaseTableData
,
1807 /* Reset NLS Translations */
1808 RtlResetRtlTranslations(&NlsTable
);
1810 /* Get the Image Config Directory */
1811 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1813 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1816 /* Setup the Heap Parameters */
1817 RtlZeroMemory(&HeapParameters
, sizeof(HeapParameters
));
1818 HeapFlags
= HEAP_GROWABLE
;
1819 HeapParameters
.Length
= sizeof(HeapParameters
);
1821 /* Check if we have Configuration Data */
1822 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1824 /* FIXME: Custom heap settings and misc. */
1825 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1828 /* Check for custom affinity mask */
1829 if (Peb
->ImageProcessAffinityMask
)
1832 Status
= NtSetInformationProcess(NtCurrentProcess(),
1833 ProcessAffinityMask
,
1834 &Peb
->ImageProcessAffinityMask
,
1835 sizeof(Peb
->ImageProcessAffinityMask
));
1838 /* Check if verbose debugging (ShowSnaps) was requested */
1839 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1841 /* Start verbose debugging messages right now if they were requested */
1844 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1845 Teb
->ClientId
.UniqueProcess
,
1849 /* If the timeout is too long */
1850 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1852 /* Then disable CS Timeout */
1853 RtlpTimeoutDisable
= TRUE
;
1856 /* Initialize Critical Section Data */
1857 RtlpInitDeferedCriticalSection();
1859 /* Initialize VEH Call lists */
1860 RtlpInitializeVectoredExceptionHandling();
1862 /* Set TLS/FLS Bitmap data */
1863 Peb
->FlsBitmap
= &FlsBitMap
;
1864 Peb
->TlsBitmap
= &TlsBitMap
;
1865 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1867 /* Initialize FLS Bitmap */
1868 RtlInitializeBitMap(&FlsBitMap
,
1870 FLS_MAXIMUM_AVAILABLE
);
1871 RtlSetBit(&FlsBitMap
, 0);
1872 InitializeListHead(&Peb
->FlsListHead
);
1874 /* Initialize TLS Bitmap */
1875 RtlInitializeBitMap(&TlsBitMap
,
1877 TLS_MINIMUM_AVAILABLE
);
1878 RtlSetBit(&TlsBitMap
, 0);
1879 RtlInitializeBitMap(&TlsExpansionBitMap
,
1880 Peb
->TlsExpansionBitmapBits
,
1881 TLS_EXPANSION_SLOTS
);
1882 RtlSetBit(&TlsExpansionBitMap
, 0);
1884 /* Initialize the Hash Table */
1885 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1887 InitializeListHead(&LdrpHashTable
[i
]);
1890 /* Initialize the Loader Lock */
1891 // FIXME: What's the point of initing it manually, if two lines lower
1892 // a call to RtlInitializeCriticalSection() is being made anyway?
1893 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1894 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1895 RtlInitializeCriticalSection(&LdrpLoaderLock
);
1896 LdrpLoaderLockInit
= TRUE
;
1898 /* Check if User Stack Trace Database support was requested */
1899 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1901 DPRINT1("We don't support user stack trace databases yet\n");
1904 /* Setup Fast PEB Lock */
1905 RtlInitializeCriticalSection(&FastPebLock
);
1906 Peb
->FastPebLock
= &FastPebLock
;
1907 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1908 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1910 /* Setup Callout Lock and Notification list */
1911 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1912 InitializeListHead(&LdrpDllNotificationList
);
1914 /* For old executables, use 16-byte aligned heap */
1915 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1916 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1918 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1921 /* Setup the Heap */
1922 RtlInitializeHeapManager();
1923 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1925 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1926 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1930 if (!Peb
->ProcessHeap
)
1932 DPRINT1("Failed to create process heap\n");
1933 return STATUS_NO_MEMORY
;
1936 /* Allocate an Activation Context Stack */
1937 Status
= RtlAllocateActivationContextStack(&Teb
->ActivationContextStackPointer
);
1938 if (!NT_SUCCESS(Status
)) return Status
;
1940 RtlZeroMemory(&HeapParameters
, sizeof(HeapParameters
));
1941 HeapFlags
= HEAP_GROWABLE
| HEAP_CLASS_1
;
1942 HeapParameters
.Length
= sizeof(HeapParameters
);
1943 LdrpHeap
= RtlCreateHeap(HeapFlags
, 0, 0x10000, 0x6000, 0, &HeapParameters
);
1946 DPRINT1("Failed to create loader private heap\n");
1947 return STATUS_NO_MEMORY
;
1950 /* Check for Debug Heap */
1953 /* Query the setting */
1954 Status
= LdrQueryImageFileKeyOption(OptionsKey
,
1955 L
"DebugProcessHeapOnly",
1957 &DebugProcessHeapOnly
,
1961 if (NT_SUCCESS(Status
))
1963 /* Reset DPH if requested */
1964 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1966 RtlpDphGlobalFlags
&= ~DPH_FLAG_DLL_NOTIFY
;
1967 RtlpPageHeapEnabled
= FALSE
;
1972 /* Build the NTDLL Path */
1973 FullPath
.Buffer
= StringBuffer
;
1974 FullPath
.Length
= 0;
1975 FullPath
.MaximumLength
= sizeof(StringBuffer
);
1976 RtlInitUnicodeString(&NtSystemRoot
, SharedUserData
->NtSystemRoot
);
1977 RtlAppendUnicodeStringToString(&FullPath
, &NtSystemRoot
);
1978 RtlAppendUnicodeToString(&FullPath
, L
"\\System32\\");
1980 /* Open the Known DLLs directory */
1981 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1982 InitializeObjectAttributes(&ObjectAttributes
,
1984 OBJ_CASE_INSENSITIVE
,
1987 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
1988 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
1991 /* Check if it exists */
1992 if (NT_SUCCESS(Status
))
1994 /* Open the Known DLLs Path */
1995 RtlInitUnicodeString(&KnownDllString
, L
"KnownDllPath");
1996 InitializeObjectAttributes(&ObjectAttributes
,
1998 OBJ_CASE_INSENSITIVE
,
1999 LdrpKnownDllObjectDirectory
,
2001 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
2002 SYMBOLIC_LINK_QUERY
,
2004 if (NT_SUCCESS(Status
))
2006 /* Query the path */
2007 LdrpKnownDllPath
.Length
= 0;
2008 LdrpKnownDllPath
.MaximumLength
= sizeof(LdrpKnownDllPathBuffer
);
2009 LdrpKnownDllPath
.Buffer
= LdrpKnownDllPathBuffer
;
2010 Status
= ZwQuerySymbolicLinkObject(SymLinkHandle
, &LdrpKnownDllPath
, NULL
);
2011 NtClose(SymLinkHandle
);
2012 if (!NT_SUCCESS(Status
))
2014 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
2020 /* Check if we failed */
2021 if (!NT_SUCCESS(Status
))
2023 /* Assume System32 */
2024 LdrpKnownDllObjectDirectory
= NULL
;
2025 RtlInitUnicodeString(&LdrpKnownDllPath
, StringBuffer
);
2026 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
2029 /* If we have process parameters, get the default path and current path */
2030 if (ProcessParameters
)
2032 /* Check if we have a Dll Path */
2033 if (ProcessParameters
->DllPath
.Length
)
2036 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
2040 /* We need a valid path */
2041 DPRINT1("No valid DllPath was given!\n");
2042 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
2045 /* Set the current directory */
2046 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
2048 /* Check if it's empty or invalid */
2049 if ((!CurrentDirectory
.Buffer
) ||
2050 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
2051 (!CurrentDirectory
.Length
))
2053 /* Allocate space for the buffer */
2054 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
2057 sizeof(UNICODE_NULL
));
2058 if (!CurrentDirectory
.Buffer
)
2060 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
2064 /* Copy the drive of the system root */
2065 RtlMoveMemory(CurrentDirectory
.Buffer
,
2066 SharedUserData
->NtSystemRoot
,
2068 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
2069 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
2070 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
2073 DPRINT("Using dynamically allocd curdir\n");
2077 /* Use the local buffer */
2078 DPRINT("Using local system root\n");
2082 /* Setup Loader Data */
2084 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
2085 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
2086 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
2087 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
2088 PebLdr
.Initialized
= TRUE
;
2090 /* Allocate a data entry for the Image */
2091 LdrpImageEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
2094 LdrpImageEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(LdrpImageEntry
->DllBase
);
2095 LdrpImageEntry
->LoadCount
= -1;
2096 LdrpImageEntry
->EntryPointActivationContext
= 0;
2097 LdrpImageEntry
->FullDllName
= ImageFileName
;
2100 LdrpImageEntry
->Flags
= LDRP_COR_IMAGE
;
2102 LdrpImageEntry
->Flags
= 0;
2104 /* Check if the name is empty */
2105 if (!ImageFileName
.Buffer
[0])
2107 /* Use the same Base name */
2108 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
2112 /* Find the last slash */
2113 Current
= ImageFileName
.Buffer
;
2116 if (*Current
++ == '\\')
2119 NtDllName
= Current
;
2123 /* Did we find anything? */
2126 /* Use the same Base name */
2127 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
2131 /* Setup the name */
2132 LdrpImageEntry
->BaseDllName
.Length
= (USHORT
)((ULONG_PTR
)ImageFileName
.Buffer
+ ImageFileName
.Length
- (ULONG_PTR
)NtDllName
);
2133 LdrpImageEntry
->BaseDllName
.MaximumLength
= LdrpImageEntry
->BaseDllName
.Length
+ sizeof(WCHAR
);
2134 LdrpImageEntry
->BaseDllName
.Buffer
= (PWSTR
)((ULONG_PTR
)ImageFileName
.Buffer
+
2135 (ImageFileName
.Length
- LdrpImageEntry
->BaseDllName
.Length
));
2139 /* Processing done, insert it */
2140 LdrpInsertMemoryTableEntry(LdrpImageEntry
);
2141 LdrpImageEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
2143 /* Now add an entry for NTDLL */
2144 NtLdrEntry
= LdrpAllocateDataTableEntry(SystemArgument1
);
2145 NtLdrEntry
->Flags
= LDRP_IMAGE_DLL
;
2146 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
2147 NtLdrEntry
->LoadCount
= -1;
2148 NtLdrEntry
->EntryPointActivationContext
= 0;
2150 NtLdrEntry
->FullDllName
.Length
= FullPath
.Length
;
2151 NtLdrEntry
->FullDllName
.MaximumLength
= FullPath
.MaximumLength
;
2152 NtLdrEntry
->FullDllName
.Buffer
= StringBuffer
;
2153 RtlAppendUnicodeStringToString(&NtLdrEntry
->FullDllName
, &NtDllString
);
2155 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
2156 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
2157 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
2159 /* Processing done, insert it */
2160 LdrpNtDllDataTableEntry
= NtLdrEntry
;
2161 LdrpInsertMemoryTableEntry(NtLdrEntry
);
2163 /* Let the world know */
2166 DPRINT1("LDR: NEW PROCESS\n");
2167 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry
->FullDllName
, &LdrpImageEntry
->BaseDllName
);
2168 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory
);
2169 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath
);
2172 /* Link the Init Order List */
2173 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
2174 &LdrpNtDllDataTableEntry
->InInitializationOrderLinks
);
2176 /* Initialize Wine's active context implementation for the current process */
2179 /* ReactOS specific */
2180 LdrpInitializeProcessCompat(&OldShimData
);
2182 /* Set the current directory */
2183 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
2184 if (!NT_SUCCESS(Status
))
2186 /* We failed, check if we should free it */
2187 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2189 /* Set it to the NT Root */
2190 CurrentDirectory
= NtSystemRoot
;
2191 RtlSetCurrentDirectory_U(&CurrentDirectory
);
2195 /* We're done with it, free it */
2196 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2199 /* Check if we should look for a .local file */
2200 if (ProcessParameters
&& !(ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
))
2202 LdrpInitializeDotLocalSupport(ProcessParameters
);
2205 /* Check if the Application Verifier was enabled */
2206 if (Peb
->NtGlobalFlag
& FLG_APPLICATION_VERIFIER
)
2208 Status
= AVrfInitializeVerifier();
2209 if (!NT_SUCCESS(Status
))
2211 DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status
);
2220 DPRINT1("We don't support .NET applications yet\n");
2223 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
||
2224 NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_CUI
)
2226 PVOID Kernel32BaseAddress
;
2227 PVOID FunctionAddress
;
2229 Status
= LdrLoadDll(NULL
, NULL
, &Kernel32String
, &Kernel32BaseAddress
);
2231 if (!NT_SUCCESS(Status
))
2234 DPRINT1("LDR: Unable to load %wZ, Status=0x%08lx\n", &Kernel32String
, Status
);
2238 Status
= LdrGetProcedureAddress(Kernel32BaseAddress
,
2239 &BaseProcessInitPostImportName
,
2243 if (!NT_SUCCESS(Status
))
2246 DPRINT1("LDR: Unable to find post-import process init function, Status=0x%08lx\n", &Kernel32String
, Status
);
2249 Kernel32ProcessInitPostImportFunction
= FunctionAddress
;
2251 Status
= LdrGetProcedureAddress(Kernel32BaseAddress
,
2252 &BaseQueryModuleDataName
,
2256 if (!NT_SUCCESS(Status
))
2259 DPRINT1("LDR: Unable to find BaseQueryModuleData, Status=0x%08lx\n", &Kernel32String
, Status
);
2262 Kernel32BaseQueryModuleData
= FunctionAddress
;
2265 /* Walk the IAT and load all the DLLs */
2266 ImportStatus
= LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
2268 /* Check if relocation is needed */
2269 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
2271 DPRINT1("LDR: Performing EXE relocation\n");
2273 /* Change the protection to prepare for relocation */
2274 ViewBase
= Peb
->ImageBaseAddress
;
2275 Status
= LdrpSetProtection(ViewBase
, FALSE
);
2276 if (!NT_SUCCESS(Status
)) return Status
;
2278 /* Do the relocation */
2279 Status
= LdrRelocateImageWithBias(ViewBase
,
2283 STATUS_CONFLICTING_ADDRESSES
,
2284 STATUS_INVALID_IMAGE_FORMAT
);
2285 if (!NT_SUCCESS(Status
))
2287 DPRINT1("LdrRelocateImageWithBias() failed\n");
2291 /* Check if a start context was provided */
2294 DPRINT1("WARNING: Relocated EXE Context");
2295 UNIMPLEMENTED
; // We should support this
2296 return STATUS_INVALID_IMAGE_FORMAT
;
2299 /* Restore the protection */
2300 Status
= LdrpSetProtection(ViewBase
, TRUE
);
2301 if (!NT_SUCCESS(Status
)) return Status
;
2305 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
2306 NextEntry
= ListHead
->Flink
;
2307 while (ListHead
!= NextEntry
)
2309 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2310 NtLdrEntry
->LoadCount
= -1;
2311 NextEntry
= NextEntry
->Flink
;
2314 /* Phase 0 is done */
2315 LdrpLdrDatabaseIsSetup
= TRUE
;
2317 /* Check whether all static imports were properly loaded and return here */
2318 if (!NT_SUCCESS(ImportStatus
)) return ImportStatus
;
2320 /* Initialize TLS */
2321 Status
= LdrpInitializeTls();
2322 if (!NT_SUCCESS(Status
))
2324 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2329 /* FIXME Mark the DLL Ranges for Stack Traces later */
2331 /* Notify the debugger now */
2332 if (Peb
->BeingDebugged
)
2337 /* Update show snaps again */
2338 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
2341 /* Validate the Image for MP Usage */
2342 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
2344 /* Check NX Options */
2345 if (SharedUserData
->NXSupportPolicy
== 1)
2347 ExecuteOptions
= 0xD;
2349 else if (!SharedUserData
->NXSupportPolicy
)
2351 ExecuteOptions
= 0xA;
2355 ZwSetInformationProcess(NtCurrentProcess(),
2356 ProcessExecuteFlags
,
2360 // FIXME: Should be done by Application Compatibility features,
2361 // by reading the registry, etc...
2362 // For now, this is the old code from ntdll!RtlGetVersion().
2363 RtlInitEmptyUnicodeString(&Peb
->CSDVersion
, NULL
, 0);
2364 if (((Peb
->OSCSDVersion
>> 8) & 0xFF) != 0)
2366 WCHAR szCSDVersion
[128];
2368 ULONG Length
= ARRAYSIZE(szCSDVersion
) - 1;
2369 i
= _snwprintf(szCSDVersion
, Length
,
2371 ((Peb
->OSCSDVersion
>> 8) & 0xFF));
2374 /* Null-terminate if it was overflowed */
2375 szCSDVersion
[Length
] = UNICODE_NULL
;
2378 Length
*= sizeof(WCHAR
);
2379 Peb
->CSDVersion
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
2381 Length
+ sizeof(UNICODE_NULL
));
2382 if (Peb
->CSDVersion
.Buffer
)
2384 Peb
->CSDVersion
.Length
= Length
;
2385 Peb
->CSDVersion
.MaximumLength
= Length
+ sizeof(UNICODE_NULL
);
2387 RtlCopyMemory(Peb
->CSDVersion
.Buffer
,
2389 Peb
->CSDVersion
.MaximumLength
);
2390 Peb
->CSDVersion
.Buffer
[Peb
->CSDVersion
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2394 /* Check if we had Shim Data */
2397 /* Load the Shim Engine */
2398 Peb
->AppCompatInfo
= NULL
;
2399 LdrpLoadShimEngine(OldShimData
, &ImagePathName
, OldShimData
);
2403 /* Check for Application Compatibility Goo */
2404 //LdrQueryApplicationCompatibilityGoo(hKey);
2405 DPRINT("Querying app compat hacks is missing!\n");
2409 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2410 * incompatible images.
2413 /* Now call the Init Routines */
2414 Status
= LdrpRunInitializeRoutines(Context
);
2415 if (!NT_SUCCESS(Status
))
2417 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2422 /* Notify Shim Engine */
2425 VOID(NTAPI
*SE_InstallAfterInit
)(PUNICODE_STRING
, PVOID
);
2426 SE_InstallAfterInit
= RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit
);
2427 SE_InstallAfterInit(&ImagePathName
, OldShimData
);
2430 /* Check if we have a user-defined Post Process Routine */
2431 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
2434 Peb
->PostProcessInitRoutine();
2437 /* Close the key if we have one opened */
2438 if (OptionsKey
) NtClose(OptionsKey
);
2446 LdrpInitFailure(NTSTATUS Status
)
2449 PPEB Peb
= NtCurrentPeb();
2451 /* Print a debug message */
2452 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2453 &Peb
->ProcessParameters
->ImagePathName
, Status
);
2455 /* Raise a hard error */
2456 if (!LdrpFatalHardErrorCount
)
2458 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
2464 LdrpInit(PCONTEXT Context
,
2465 PVOID SystemArgument1
,
2466 PVOID SystemArgument2
)
2468 LARGE_INTEGER Timeout
;
2469 PTEB Teb
= NtCurrentTeb();
2470 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
2471 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
2472 PPEB Peb
= NtCurrentPeb();
2474 DPRINT("LdrpInit() %p/%p\n",
2475 NtCurrentTeb()->RealClientId
.UniqueProcess
,
2476 NtCurrentTeb()->RealClientId
.UniqueThread
);
2479 /* Set the SList header usage */
2480 RtlpUse16ByteSLists
= SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE128
];
2483 /* Check if we have a deallocation stack */
2484 if (!Teb
->DeallocationStack
)
2486 /* We don't, set one */
2487 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
2488 Teb
->NtTib
.StackLimit
,
2489 MemoryBasicInformation
,
2491 sizeof(MEMORY_BASIC_INFORMATION
),
2493 if (!NT_SUCCESS(Status
))
2496 LdrpInitFailure(Status
);
2497 RtlRaiseStatus(Status
);
2502 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
2505 /* Now check if the process is already being initialized */
2506 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
2510 /* Set the timeout to 30 milliseconds */
2511 Timeout
.QuadPart
= Int32x32To64(30, -10000);
2513 /* Make sure the status hasn't changed */
2514 while (LdrpProcessInitialized
== 1)
2517 ZwDelayExecution(FALSE
, &Timeout
);
2521 /* Check if we have already setup LDR data */
2524 /* Setup the Loader Lock */
2525 Peb
->LoaderLock
= &LdrpLoaderLock
;
2527 /* Let other code know we're initializing */
2528 LdrpInLdrInit
= TRUE
;
2530 /* Protect with SEH */
2533 /* Initialize the Process */
2534 LoaderStatus
= LdrpInitializeProcess(Context
,
2537 /* Check for success and if MinimumStackCommit was requested */
2538 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
2540 /* Enforce the limit */
2541 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2545 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2547 /* Fail with the SEH error */
2548 LoaderStatus
= _SEH2_GetExceptionCode();
2552 /* We're not initializing anymore */
2553 LdrpInLdrInit
= FALSE
;
2555 /* Check if init worked */
2556 if (NT_SUCCESS(LoaderStatus
))
2558 /* Set the process as Initialized */
2559 _InterlockedIncrement(&LdrpProcessInitialized
);
2564 /* Loader data is there... is this a fork() ? */
2565 if(Peb
->InheritedAddressSpace
)
2567 /* Handle the fork() */
2568 //LoaderStatus = LdrpForkProcess();
2569 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
2574 /* This is a new thread initializing */
2575 LdrpInitializeThread(Context
);
2579 /* All done, test alert the thread */
2583 if (!NT_SUCCESS(LoaderStatus
))
2586 LdrpInitFailure(LoaderStatus
);
2587 RtlRaiseStatus(LoaderStatus
);