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
)
1547 const DWORD Version
;
1548 } KnownCompatGuids
[] = {
1549 { &COMPAT_GUID_WIN10
, _WIN32_WINNT_WIN10
},
1550 { &COMPAT_GUID_WIN81
, _WIN32_WINNT_WINBLUE
},
1551 { &COMPAT_GUID_WIN8
, _WIN32_WINNT_WIN8
},
1552 { &COMPAT_GUID_WIN7
, _WIN32_WINNT_WIN7
},
1553 { &COMPAT_GUID_VISTA
, _WIN32_WINNT_VISTA
},
1556 ULONG Buffer
[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
)) / sizeof(ULONG
)];
1557 ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
* ContextCompatInfo
;
1558 SIZE_T SizeRequired
;
1561 ReactOS_ShimData
* pShimData
= *pOldShimData
;
1565 if (pShimData
->dwMagic
!= REACTOS_SHIMDATA_MAGIC
||
1566 pShimData
->dwSize
!= sizeof(ReactOS_ShimData
))
1568 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData
->dwMagic
, pShimData
->dwSize
);
1571 if (pShimData
->dwRosProcessCompatVersion
)
1573 if (pShimData
->dwRosProcessCompatVersion
== REACTOS_COMPATVERSION_IGNOREMANIFEST
)
1575 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion set to ignore manifest\n");
1579 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData
->dwRosProcessCompatVersion
);
1585 SizeRequired
= sizeof(Buffer
);
1586 Status
= RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
,
1589 CompatibilityInformationInActivationContext
,
1594 if (!NT_SUCCESS(Status
))
1596 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status
);
1600 ContextCompatInfo
= (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
*)Buffer
;
1601 /* No Compatibility elements present, bail out */
1602 if (ContextCompatInfo
->ElementCount
== 0)
1605 /* Search for known GUID's, starting from newest to oldest. */
1606 for (cur
= 0; cur
< RTL_NUMBER_OF(KnownCompatGuids
); ++cur
)
1608 for (n
= 0; n
< ContextCompatInfo
->ElementCount
; ++n
)
1610 if (ContextCompatInfo
->Elements
[n
].Type
== ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
&&
1611 RtlCompareMemory(&ContextCompatInfo
->Elements
[n
].Id
, KnownCompatGuids
[cur
].Guid
, sizeof(GUID
)) == sizeof(GUID
))
1613 /* If this process did not need shim data before, allocate and store it */
1614 if (pShimData
== NULL
)
1616 PPEB Peb
= NtCurrentPeb();
1618 ASSERT(Peb
->pShimData
== NULL
);
1619 pShimData
= RtlAllocateHeap(Peb
->ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(*pShimData
));
1623 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData
));
1627 pShimData
->dwSize
= sizeof(*pShimData
);
1628 pShimData
->dwMagic
= REACTOS_SHIMDATA_MAGIC
;
1630 Peb
->pShimData
= pShimData
;
1631 *pOldShimData
= pShimData
;
1634 /* Store the highest found version, and bail out. */
1635 pShimData
->dwRosProcessCompatVersion
= KnownCompatGuids
[cur
].Version
;
1636 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", KnownCompatGuids
[cur
].Version
);
1645 LdrpInitializeDotLocalSupport(PRTL_USER_PROCESS_PARAMETERS ProcessParameters
)
1647 UNICODE_STRING ImagePathName
= ProcessParameters
->ImagePathName
;
1648 WCHAR LocalBuffer
[MAX_PATH
];
1649 UNICODE_STRING DotLocal
;
1653 RequiredSize
= ImagePathName
.Length
+ LdrpDotLocal
.Length
+ sizeof(UNICODE_NULL
);
1654 if (RequiredSize
<= sizeof(LocalBuffer
))
1656 RtlInitEmptyUnicodeString(&DotLocal
, LocalBuffer
, sizeof(LocalBuffer
));
1658 else if (RequiredSize
<= UNICODE_STRING_MAX_BYTES
)
1660 DotLocal
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, RequiredSize
);
1661 DotLocal
.Length
= 0;
1662 DotLocal
.MaximumLength
= RequiredSize
;
1663 if (!DotLocal
.Buffer
)
1664 DPRINT1("LDR: Failed to allocate memory for .local check\n");
1668 DotLocal
.Buffer
= NULL
;
1669 DotLocal
.Length
= 0;
1670 DotLocal
.MaximumLength
= 0;
1671 DPRINT1("LDR: String too big for .local check\n");
1674 if (DotLocal
.Buffer
)
1676 Status
= RtlAppendUnicodeStringToString(&DotLocal
, &ImagePathName
);
1677 ASSERT(NT_SUCCESS(Status
));
1678 if (NT_SUCCESS(Status
))
1680 Status
= RtlAppendUnicodeStringToString(&DotLocal
, &LdrpDotLocal
);
1681 ASSERT(NT_SUCCESS(Status
));
1684 if (NT_SUCCESS(Status
))
1686 if (RtlDoesFileExists_UStr(&DotLocal
))
1688 ProcessParameters
->Flags
|= RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH
;
1693 DPRINT1("LDR: Failed to append: 0x%lx\n", Status
);
1696 if (DotLocal
.Buffer
!= LocalBuffer
)
1698 RtlFreeHeap(RtlGetProcessHeap(), 0, DotLocal
.Buffer
);
1706 LdrpInitializeProcess(IN PCONTEXT Context
,
1707 IN PVOID SystemArgument1
)
1709 RTL_HEAP_PARAMETERS HeapParameters
;
1710 ULONG ComSectionSize
;
1711 ANSI_STRING BaseProcessInitPostImportName
= RTL_CONSTANT_STRING("BaseProcessInitPostImport");
1712 ANSI_STRING BaseQueryModuleDataName
= RTL_CONSTANT_STRING("BaseQueryModuleData");
1714 OBJECT_ATTRIBUTES ObjectAttributes
;
1715 //UNICODE_STRING LocalFileName, FullImageName;
1716 HANDLE SymLinkHandle
;
1717 //ULONG DebugHeapOnly;
1718 UNICODE_STRING CommandLine
, NtSystemRoot
, ImagePathName
, FullPath
, ImageFileName
, KnownDllString
;
1719 PPEB Peb
= NtCurrentPeb();
1720 BOOLEAN IsDotNetImage
= FALSE
;
1721 BOOLEAN FreeCurDir
= FALSE
;
1723 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1724 //LPWSTR ImagePathBuffer;
1726 UNICODE_STRING CurrentDirectory
;
1729 PIMAGE_NT_HEADERS NtHeader
;
1730 LPWSTR NtDllName
= NULL
;
1731 NTSTATUS Status
, ImportStatus
;
1732 NLSTABLEINFO NlsTable
;
1733 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig
;
1734 PTEB Teb
= NtCurrentTeb();
1735 PLIST_ENTRY ListHead
;
1736 PLIST_ENTRY NextEntry
;
1739 ULONG DebugProcessHeapOnly
= 0;
1740 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
1742 ULONG ExecuteOptions
= 0;
1745 /* Set a NULL SEH Filter */
1746 RtlSetUnhandledExceptionFilter(NULL
);
1748 /* Get the image path */
1749 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
1751 /* Check if it's not normalized */
1752 if (!(Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
))
1755 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
1758 /* Create a unicode string for the Image Path */
1759 ImagePathName
.Length
= Peb
->ProcessParameters
->ImagePathName
.Length
;
1760 ImagePathName
.MaximumLength
= ImagePathName
.Length
+ sizeof(WCHAR
);
1761 ImagePathName
.Buffer
= ImagePath
;
1763 /* Get the NT Headers */
1764 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
1766 /* Get the execution options */
1767 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &OptionsKey
);
1769 /* Check if this is a .NET executable */
1770 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1772 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
1775 /* Remember this for later */
1776 IsDotNetImage
= TRUE
;
1779 /* Save the NTDLL Base address */
1780 NtDllBase
= SystemArgument1
;
1782 /* If this is a Native Image */
1783 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
1785 /* Then do DLL Validation */
1786 LdrpDllValidation
= TRUE
;
1789 /* Save the old Shim Data */
1790 OldShimData
= Peb
->pShimData
;
1792 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */
1793 //Peb->pShimData = NULL;
1795 /* Save the number of processors and CS Timeout */
1796 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
1797 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
1799 /* Normalize the parameters */
1800 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
1801 if (ProcessParameters
)
1803 /* Save the Image and Command Line Names */
1804 ImageFileName
= ProcessParameters
->ImagePathName
;
1805 CommandLine
= ProcessParameters
->CommandLine
;
1809 /* It failed, initialize empty strings */
1810 RtlInitUnicodeString(&ImageFileName
, NULL
);
1811 RtlInitUnicodeString(&CommandLine
, NULL
);
1814 /* Initialize NLS data */
1815 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1816 Peb
->OemCodePageData
,
1817 Peb
->UnicodeCaseTableData
,
1820 /* Reset NLS Translations */
1821 RtlResetRtlTranslations(&NlsTable
);
1823 /* Get the Image Config Directory */
1824 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1826 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1829 /* Setup the Heap Parameters */
1830 RtlZeroMemory(&HeapParameters
, sizeof(HeapParameters
));
1831 HeapFlags
= HEAP_GROWABLE
;
1832 HeapParameters
.Length
= sizeof(HeapParameters
);
1834 /* Check if we have Configuration Data */
1835 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1837 /* FIXME: Custom heap settings and misc. */
1838 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1841 /* Check for custom affinity mask */
1842 if (Peb
->ImageProcessAffinityMask
)
1845 Status
= NtSetInformationProcess(NtCurrentProcess(),
1846 ProcessAffinityMask
,
1847 &Peb
->ImageProcessAffinityMask
,
1848 sizeof(Peb
->ImageProcessAffinityMask
));
1851 /* Check if verbose debugging (ShowSnaps) was requested */
1852 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1854 /* Start verbose debugging messages right now if they were requested */
1857 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1858 Teb
->ClientId
.UniqueProcess
,
1862 /* If the timeout is too long */
1863 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1865 /* Then disable CS Timeout */
1866 RtlpTimeoutDisable
= TRUE
;
1869 /* Initialize Critical Section Data */
1870 RtlpInitDeferedCriticalSection();
1872 /* Initialize VEH Call lists */
1873 RtlpInitializeVectoredExceptionHandling();
1875 /* Set TLS/FLS Bitmap data */
1876 Peb
->FlsBitmap
= &FlsBitMap
;
1877 Peb
->TlsBitmap
= &TlsBitMap
;
1878 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1880 /* Initialize FLS Bitmap */
1881 RtlInitializeBitMap(&FlsBitMap
,
1883 FLS_MAXIMUM_AVAILABLE
);
1884 RtlSetBit(&FlsBitMap
, 0);
1885 InitializeListHead(&Peb
->FlsListHead
);
1887 /* Initialize TLS Bitmap */
1888 RtlInitializeBitMap(&TlsBitMap
,
1890 TLS_MINIMUM_AVAILABLE
);
1891 RtlSetBit(&TlsBitMap
, 0);
1892 RtlInitializeBitMap(&TlsExpansionBitMap
,
1893 Peb
->TlsExpansionBitmapBits
,
1894 TLS_EXPANSION_SLOTS
);
1895 RtlSetBit(&TlsExpansionBitMap
, 0);
1897 /* Initialize the Hash Table */
1898 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1900 InitializeListHead(&LdrpHashTable
[i
]);
1903 /* Initialize the Loader Lock */
1904 // FIXME: What's the point of initing it manually, if two lines lower
1905 // a call to RtlInitializeCriticalSection() is being made anyway?
1906 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1907 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1908 RtlInitializeCriticalSection(&LdrpLoaderLock
);
1909 LdrpLoaderLockInit
= TRUE
;
1911 /* Check if User Stack Trace Database support was requested */
1912 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1914 DPRINT1("We don't support user stack trace databases yet\n");
1917 /* Setup Fast PEB Lock */
1918 RtlInitializeCriticalSection(&FastPebLock
);
1919 Peb
->FastPebLock
= &FastPebLock
;
1920 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1921 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1923 /* Setup Callout Lock and Notification list */
1924 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1925 InitializeListHead(&LdrpDllNotificationList
);
1927 /* For old executables, use 16-byte aligned heap */
1928 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1929 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1931 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1934 /* Setup the Heap */
1935 RtlInitializeHeapManager();
1936 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1938 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1939 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1943 if (!Peb
->ProcessHeap
)
1945 DPRINT1("Failed to create process heap\n");
1946 return STATUS_NO_MEMORY
;
1949 /* Allocate an Activation Context Stack */
1950 Status
= RtlAllocateActivationContextStack(&Teb
->ActivationContextStackPointer
);
1951 if (!NT_SUCCESS(Status
)) return Status
;
1953 RtlZeroMemory(&HeapParameters
, sizeof(HeapParameters
));
1954 HeapFlags
= HEAP_GROWABLE
| HEAP_CLASS_1
;
1955 HeapParameters
.Length
= sizeof(HeapParameters
);
1956 LdrpHeap
= RtlCreateHeap(HeapFlags
, 0, 0x10000, 0x6000, 0, &HeapParameters
);
1959 DPRINT1("Failed to create loader private heap\n");
1960 return STATUS_NO_MEMORY
;
1963 /* Check for Debug Heap */
1966 /* Query the setting */
1967 Status
= LdrQueryImageFileKeyOption(OptionsKey
,
1968 L
"DebugProcessHeapOnly",
1970 &DebugProcessHeapOnly
,
1974 if (NT_SUCCESS(Status
))
1976 /* Reset DPH if requested */
1977 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1979 RtlpDphGlobalFlags
&= ~DPH_FLAG_DLL_NOTIFY
;
1980 RtlpPageHeapEnabled
= FALSE
;
1985 /* Build the NTDLL Path */
1986 FullPath
.Buffer
= StringBuffer
;
1987 FullPath
.Length
= 0;
1988 FullPath
.MaximumLength
= sizeof(StringBuffer
);
1989 RtlInitUnicodeString(&NtSystemRoot
, SharedUserData
->NtSystemRoot
);
1990 RtlAppendUnicodeStringToString(&FullPath
, &NtSystemRoot
);
1991 RtlAppendUnicodeToString(&FullPath
, L
"\\System32\\");
1993 /* Open the Known DLLs directory */
1994 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1995 InitializeObjectAttributes(&ObjectAttributes
,
1997 OBJ_CASE_INSENSITIVE
,
2000 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
2001 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
2004 /* Check if it exists */
2005 if (NT_SUCCESS(Status
))
2007 /* Open the Known DLLs Path */
2008 RtlInitUnicodeString(&KnownDllString
, L
"KnownDllPath");
2009 InitializeObjectAttributes(&ObjectAttributes
,
2011 OBJ_CASE_INSENSITIVE
,
2012 LdrpKnownDllObjectDirectory
,
2014 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
2015 SYMBOLIC_LINK_QUERY
,
2017 if (NT_SUCCESS(Status
))
2019 /* Query the path */
2020 LdrpKnownDllPath
.Length
= 0;
2021 LdrpKnownDllPath
.MaximumLength
= sizeof(LdrpKnownDllPathBuffer
);
2022 LdrpKnownDllPath
.Buffer
= LdrpKnownDllPathBuffer
;
2023 Status
= ZwQuerySymbolicLinkObject(SymLinkHandle
, &LdrpKnownDllPath
, NULL
);
2024 NtClose(SymLinkHandle
);
2025 if (!NT_SUCCESS(Status
))
2027 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
2033 /* Check if we failed */
2034 if (!NT_SUCCESS(Status
))
2036 /* Assume System32 */
2037 LdrpKnownDllObjectDirectory
= NULL
;
2038 RtlInitUnicodeString(&LdrpKnownDllPath
, StringBuffer
);
2039 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
2042 /* If we have process parameters, get the default path and current path */
2043 if (ProcessParameters
)
2045 /* Check if we have a Dll Path */
2046 if (ProcessParameters
->DllPath
.Length
)
2049 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
2053 /* We need a valid path */
2054 DPRINT1("No valid DllPath was given!\n");
2055 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
2058 /* Set the current directory */
2059 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
2061 /* Check if it's empty or invalid */
2062 if ((!CurrentDirectory
.Buffer
) ||
2063 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
2064 (!CurrentDirectory
.Length
))
2066 /* Allocate space for the buffer */
2067 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
2070 sizeof(UNICODE_NULL
));
2071 if (!CurrentDirectory
.Buffer
)
2073 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
2077 /* Copy the drive of the system root */
2078 RtlMoveMemory(CurrentDirectory
.Buffer
,
2079 SharedUserData
->NtSystemRoot
,
2081 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
2082 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
2083 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
2086 DPRINT("Using dynamically allocd curdir\n");
2090 /* Use the local buffer */
2091 DPRINT("Using local system root\n");
2095 /* Setup Loader Data */
2097 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
2098 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
2099 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
2100 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
2101 PebLdr
.Initialized
= TRUE
;
2103 /* Allocate a data entry for the Image */
2104 LdrpImageEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
2107 LdrpImageEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(LdrpImageEntry
->DllBase
);
2108 LdrpImageEntry
->LoadCount
= -1;
2109 LdrpImageEntry
->EntryPointActivationContext
= 0;
2110 LdrpImageEntry
->FullDllName
= ImageFileName
;
2113 LdrpImageEntry
->Flags
= LDRP_COR_IMAGE
;
2115 LdrpImageEntry
->Flags
= 0;
2117 /* Check if the name is empty */
2118 if (!ImageFileName
.Buffer
[0])
2120 /* Use the same Base name */
2121 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
2125 /* Find the last slash */
2126 Current
= ImageFileName
.Buffer
;
2129 if (*Current
++ == '\\')
2132 NtDllName
= Current
;
2136 /* Did we find anything? */
2139 /* Use the same Base name */
2140 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
2144 /* Setup the name */
2145 LdrpImageEntry
->BaseDllName
.Length
= (USHORT
)((ULONG_PTR
)ImageFileName
.Buffer
+ ImageFileName
.Length
- (ULONG_PTR
)NtDllName
);
2146 LdrpImageEntry
->BaseDllName
.MaximumLength
= LdrpImageEntry
->BaseDllName
.Length
+ sizeof(WCHAR
);
2147 LdrpImageEntry
->BaseDllName
.Buffer
= (PWSTR
)((ULONG_PTR
)ImageFileName
.Buffer
+
2148 (ImageFileName
.Length
- LdrpImageEntry
->BaseDllName
.Length
));
2152 /* Processing done, insert it */
2153 LdrpInsertMemoryTableEntry(LdrpImageEntry
);
2154 LdrpImageEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
2156 /* Now add an entry for NTDLL */
2157 NtLdrEntry
= LdrpAllocateDataTableEntry(SystemArgument1
);
2158 NtLdrEntry
->Flags
= LDRP_IMAGE_DLL
;
2159 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
2160 NtLdrEntry
->LoadCount
= -1;
2161 NtLdrEntry
->EntryPointActivationContext
= 0;
2163 NtLdrEntry
->FullDllName
.Length
= FullPath
.Length
;
2164 NtLdrEntry
->FullDllName
.MaximumLength
= FullPath
.MaximumLength
;
2165 NtLdrEntry
->FullDllName
.Buffer
= StringBuffer
;
2166 RtlAppendUnicodeStringToString(&NtLdrEntry
->FullDllName
, &NtDllString
);
2168 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
2169 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
2170 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
2172 /* Processing done, insert it */
2173 LdrpNtDllDataTableEntry
= NtLdrEntry
;
2174 LdrpInsertMemoryTableEntry(NtLdrEntry
);
2176 /* Let the world know */
2179 DPRINT1("LDR: NEW PROCESS\n");
2180 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry
->FullDllName
, &LdrpImageEntry
->BaseDllName
);
2181 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory
);
2182 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath
);
2185 /* Link the Init Order List */
2186 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
2187 &LdrpNtDllDataTableEntry
->InInitializationOrderLinks
);
2189 /* Initialize Wine's active context implementation for the current process */
2192 /* ReactOS specific */
2193 LdrpInitializeProcessCompat(&OldShimData
);
2195 /* Set the current directory */
2196 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
2197 if (!NT_SUCCESS(Status
))
2199 /* We failed, check if we should free it */
2200 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2202 /* Set it to the NT Root */
2203 CurrentDirectory
= NtSystemRoot
;
2204 RtlSetCurrentDirectory_U(&CurrentDirectory
);
2208 /* We're done with it, free it */
2209 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2212 /* Check if we should look for a .local file */
2213 if (ProcessParameters
&& !(ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
))
2215 LdrpInitializeDotLocalSupport(ProcessParameters
);
2218 /* Check if the Application Verifier was enabled */
2219 if (Peb
->NtGlobalFlag
& FLG_APPLICATION_VERIFIER
)
2221 Status
= AVrfInitializeVerifier();
2222 if (!NT_SUCCESS(Status
))
2224 DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status
);
2233 DPRINT1("We don't support .NET applications yet\n");
2236 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
||
2237 NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_CUI
)
2239 PVOID Kernel32BaseAddress
;
2240 PVOID FunctionAddress
;
2242 Status
= LdrLoadDll(NULL
, NULL
, &Kernel32String
, &Kernel32BaseAddress
);
2244 if (!NT_SUCCESS(Status
))
2247 DPRINT1("LDR: Unable to load %wZ, Status=0x%08lx\n", &Kernel32String
, Status
);
2251 Status
= LdrGetProcedureAddress(Kernel32BaseAddress
,
2252 &BaseProcessInitPostImportName
,
2256 if (!NT_SUCCESS(Status
))
2259 DPRINT1("LDR: Unable to find post-import process init function, Status=0x%08lx\n", &Kernel32String
, Status
);
2262 Kernel32ProcessInitPostImportFunction
= FunctionAddress
;
2264 Status
= LdrGetProcedureAddress(Kernel32BaseAddress
,
2265 &BaseQueryModuleDataName
,
2269 if (!NT_SUCCESS(Status
))
2272 DPRINT1("LDR: Unable to find BaseQueryModuleData, Status=0x%08lx\n", &Kernel32String
, Status
);
2275 Kernel32BaseQueryModuleData
= FunctionAddress
;
2278 /* Walk the IAT and load all the DLLs */
2279 ImportStatus
= LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
2281 /* Check if relocation is needed */
2282 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
2284 DPRINT1("LDR: Performing EXE relocation\n");
2286 /* Change the protection to prepare for relocation */
2287 ViewBase
= Peb
->ImageBaseAddress
;
2288 Status
= LdrpSetProtection(ViewBase
, FALSE
);
2289 if (!NT_SUCCESS(Status
)) return Status
;
2291 /* Do the relocation */
2292 Status
= LdrRelocateImageWithBias(ViewBase
,
2296 STATUS_CONFLICTING_ADDRESSES
,
2297 STATUS_INVALID_IMAGE_FORMAT
);
2298 if (!NT_SUCCESS(Status
))
2300 DPRINT1("LdrRelocateImageWithBias() failed\n");
2304 /* Check if a start context was provided */
2307 DPRINT1("WARNING: Relocated EXE Context");
2308 UNIMPLEMENTED
; // We should support this
2309 return STATUS_INVALID_IMAGE_FORMAT
;
2312 /* Restore the protection */
2313 Status
= LdrpSetProtection(ViewBase
, TRUE
);
2314 if (!NT_SUCCESS(Status
)) return Status
;
2318 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
2319 NextEntry
= ListHead
->Flink
;
2320 while (ListHead
!= NextEntry
)
2322 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2323 NtLdrEntry
->LoadCount
= -1;
2324 NextEntry
= NextEntry
->Flink
;
2327 /* Phase 0 is done */
2328 LdrpLdrDatabaseIsSetup
= TRUE
;
2330 /* Check whether all static imports were properly loaded and return here */
2331 if (!NT_SUCCESS(ImportStatus
)) return ImportStatus
;
2333 /* Initialize TLS */
2334 Status
= LdrpInitializeTls();
2335 if (!NT_SUCCESS(Status
))
2337 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2342 /* FIXME Mark the DLL Ranges for Stack Traces later */
2344 /* Notify the debugger now */
2345 if (Peb
->BeingDebugged
)
2350 /* Update show snaps again */
2351 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
2354 /* Validate the Image for MP Usage */
2355 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
2357 /* Check NX Options */
2358 if (SharedUserData
->NXSupportPolicy
== 1)
2360 ExecuteOptions
= 0xD;
2362 else if (!SharedUserData
->NXSupportPolicy
)
2364 ExecuteOptions
= 0xA;
2368 ZwSetInformationProcess(NtCurrentProcess(),
2369 ProcessExecuteFlags
,
2373 // FIXME: Should be done by Application Compatibility features,
2374 // by reading the registry, etc...
2375 // For now, this is the old code from ntdll!RtlGetVersion().
2376 RtlInitEmptyUnicodeString(&Peb
->CSDVersion
, NULL
, 0);
2377 if (((Peb
->OSCSDVersion
>> 8) & 0xFF) != 0)
2379 WCHAR szCSDVersion
[128];
2381 USHORT Length
= (USHORT
)ARRAYSIZE(szCSDVersion
) - 1;
2382 i
= _snwprintf(szCSDVersion
, Length
,
2384 ((Peb
->OSCSDVersion
>> 8) & 0xFF));
2387 /* Null-terminate if it was overflowed */
2388 szCSDVersion
[Length
] = UNICODE_NULL
;
2391 Length
*= sizeof(WCHAR
);
2392 Peb
->CSDVersion
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
2394 Length
+ sizeof(UNICODE_NULL
));
2395 if (Peb
->CSDVersion
.Buffer
)
2397 Peb
->CSDVersion
.Length
= Length
;
2398 Peb
->CSDVersion
.MaximumLength
= Length
+ sizeof(UNICODE_NULL
);
2400 RtlCopyMemory(Peb
->CSDVersion
.Buffer
,
2402 Peb
->CSDVersion
.MaximumLength
);
2403 Peb
->CSDVersion
.Buffer
[Peb
->CSDVersion
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2407 /* Check if we had Shim Data */
2410 /* Load the Shim Engine */
2411 Peb
->AppCompatInfo
= NULL
;
2412 LdrpLoadShimEngine(OldShimData
, &ImagePathName
, OldShimData
);
2416 /* Check for Application Compatibility Goo */
2417 //LdrQueryApplicationCompatibilityGoo(hKey);
2418 DPRINT("Querying app compat hacks is missing!\n");
2422 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2423 * incompatible images.
2426 /* Now call the Init Routines */
2427 Status
= LdrpRunInitializeRoutines(Context
);
2428 if (!NT_SUCCESS(Status
))
2430 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2435 /* Notify Shim Engine */
2438 VOID(NTAPI
*SE_InstallAfterInit
)(PUNICODE_STRING
, PVOID
);
2439 SE_InstallAfterInit
= RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit
);
2440 SE_InstallAfterInit(&ImagePathName
, OldShimData
);
2443 /* Check if we have a user-defined Post Process Routine */
2444 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
2447 Peb
->PostProcessInitRoutine();
2450 /* Close the key if we have one opened */
2451 if (OptionsKey
) NtClose(OptionsKey
);
2459 LdrpInitFailure(NTSTATUS Status
)
2462 PPEB Peb
= NtCurrentPeb();
2464 /* Print a debug message */
2465 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2466 &Peb
->ProcessParameters
->ImagePathName
, Status
);
2468 /* Raise a hard error */
2469 if (!LdrpFatalHardErrorCount
)
2471 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
2477 LdrpInit(PCONTEXT Context
,
2478 PVOID SystemArgument1
,
2479 PVOID SystemArgument2
)
2481 LARGE_INTEGER Timeout
;
2482 PTEB Teb
= NtCurrentTeb();
2483 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
2484 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
2485 PPEB Peb
= NtCurrentPeb();
2487 DPRINT("LdrpInit() %p/%p\n",
2488 NtCurrentTeb()->RealClientId
.UniqueProcess
,
2489 NtCurrentTeb()->RealClientId
.UniqueThread
);
2492 /* Set the SList header usage */
2493 RtlpUse16ByteSLists
= SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE128
];
2496 /* Check if we have a deallocation stack */
2497 if (!Teb
->DeallocationStack
)
2499 /* We don't, set one */
2500 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
2501 Teb
->NtTib
.StackLimit
,
2502 MemoryBasicInformation
,
2504 sizeof(MEMORY_BASIC_INFORMATION
),
2506 if (!NT_SUCCESS(Status
))
2509 LdrpInitFailure(Status
);
2510 RtlRaiseStatus(Status
);
2515 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
2518 /* Now check if the process is already being initialized */
2519 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
2523 /* Set the timeout to 30 milliseconds */
2524 Timeout
.QuadPart
= Int32x32To64(30, -10000);
2526 /* Make sure the status hasn't changed */
2527 while (LdrpProcessInitialized
== 1)
2530 ZwDelayExecution(FALSE
, &Timeout
);
2534 /* Check if we have already setup LDR data */
2537 /* Setup the Loader Lock */
2538 Peb
->LoaderLock
= &LdrpLoaderLock
;
2540 /* Let other code know we're initializing */
2541 LdrpInLdrInit
= TRUE
;
2543 /* Protect with SEH */
2546 /* Initialize the Process */
2547 LoaderStatus
= LdrpInitializeProcess(Context
,
2550 /* Check for success and if MinimumStackCommit was requested */
2551 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
2553 /* Enforce the limit */
2554 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2558 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2560 /* Fail with the SEH error */
2561 LoaderStatus
= _SEH2_GetExceptionCode();
2565 /* We're not initializing anymore */
2566 LdrpInLdrInit
= FALSE
;
2568 /* Check if init worked */
2569 if (NT_SUCCESS(LoaderStatus
))
2571 /* Set the process as Initialized */
2572 _InterlockedIncrement(&LdrpProcessInitialized
);
2577 /* Loader data is there... is this a fork() ? */
2578 if(Peb
->InheritedAddressSpace
)
2580 /* Handle the fork() */
2581 //LoaderStatus = LdrpForkProcess();
2582 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
2587 /* This is a new thread initializing */
2588 LdrpInitializeThread(Context
);
2592 /* All done, test alert the thread */
2596 if (!NT_SUCCESS(LoaderStatus
))
2599 LdrpInitFailure(LoaderStatus
);
2600 RtlRaiseStatus(LoaderStatus
);