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");
28 BOOLEAN LdrpInLdrInit
;
29 LONG LdrpProcessInitialized
;
30 BOOLEAN LdrpLoaderLockInit
;
31 BOOLEAN LdrpLdrDatabaseIsSetup
;
32 BOOLEAN LdrpShutdownInProgress
;
33 HANDLE LdrpShutdownThreadId
;
35 BOOLEAN LdrpDllValidation
;
37 PLDR_DATA_TABLE_ENTRY LdrpImageEntry
;
38 PUNICODE_STRING LdrpTopLevelDllBeingLoaded
;
39 WCHAR StringBuffer
[156];
40 extern PTEB LdrpTopLevelDllBeingLoadedTeb
; // defined in rtlsupp.c!
41 PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer
;
42 PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry
;
45 RTL_BITMAP TlsExpansionBitMap
;
47 BOOLEAN LdrpImageHasTls
;
48 LIST_ENTRY LdrpTlsList
;
49 ULONG LdrpNumberOfTlsEntries
;
50 ULONG LdrpNumberOfProcessors
;
52 extern LARGE_INTEGER RtlpTimeout
;
53 BOOLEAN RtlpTimeoutDisable
;
54 LIST_ENTRY LdrpHashTable
[LDR_HASH_TABLE_ENTRIES
];
55 LIST_ENTRY LdrpDllNotificationList
;
56 HANDLE LdrpKnownDllObjectDirectory
;
57 UNICODE_STRING LdrpKnownDllPath
;
58 WCHAR LdrpKnownDllPathBuffer
[128];
59 UNICODE_STRING LdrpDefaultPath
;
63 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug
;
64 RTL_CRITICAL_SECTION LdrpLoaderLock
=
73 RTL_CRITICAL_SECTION FastPebLock
;
77 ULONG LdrpFatalHardErrorCount
;
78 ULONG LdrpActiveUnloadCount
;
80 //extern LIST_ENTRY RtlCriticalSectionList;
82 VOID NTAPI
RtlpInitializeVectoredExceptionHandling(VOID
);
83 VOID NTAPI
RtlpInitDeferedCriticalSection(VOID
);
84 VOID NTAPI
RtlInitializeHeapManager(VOID
);
86 ULONG RtlpDisableHeapLookaside
; // TODO: Move to heap.c
87 ULONG RtlpShutdownProcessFlags
; // TODO: Use it
89 NTSTATUS
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
, PVOID ImageBase
);
90 void actctx_init(void);
91 extern BOOLEAN RtlpUse16ByteSLists
;
94 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
96 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E
99 /* FUNCTIONS *****************************************************************/
106 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey
,
108 OUT PHANDLE NewKeyHandle
)
110 PHANDLE RootKeyLocation
;
112 UNICODE_STRING SubKeyString
;
113 OBJECT_ATTRIBUTES ObjectAttributes
;
117 /* Check which root key to open */
119 RootKeyLocation
= &Wow64ExecOptionsKey
;
121 RootKeyLocation
= &ImageExecOptionsKey
;
123 /* Get the current key */
124 RootKey
= *RootKeyLocation
;
126 /* Setup the object attributes */
127 InitializeObjectAttributes(&ObjectAttributes
,
129 &Wow64OptionsString
: &ImageExecOptionsString
,
130 OBJ_CASE_INSENSITIVE
,
134 /* Open the root key */
135 Status
= ZwOpenKey(&RootKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
136 if (NT_SUCCESS(Status
))
138 /* Write the key handle */
139 if (_InterlockedCompareExchange((LONG
*)RootKeyLocation
, (LONG
)RootKey
, 0) != 0)
141 /* Someone already opened it, use it instead */
143 RootKey
= *RootKeyLocation
;
146 /* Extract the name */
147 SubKeyString
= *SubKey
;
148 p1
= (PWCHAR
)((ULONG_PTR
)SubKeyString
.Buffer
+ SubKeyString
.Length
);
149 while (SubKeyString
.Length
)
151 if (p1
[-1] == L
'\\') break;
153 SubKeyString
.Length
-= sizeof(*p1
);
155 SubKeyString
.Buffer
= p1
;
156 SubKeyString
.Length
= SubKey
->Length
- SubKeyString
.Length
;
158 /* Setup the object attributes */
159 InitializeObjectAttributes(&ObjectAttributes
,
161 OBJ_CASE_INSENSITIVE
,
165 /* Open the setting key */
166 Status
= ZwOpenKey((PHANDLE
)NewKeyHandle
, GENERIC_READ
, &ObjectAttributes
);
169 /* Return to caller */
178 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle
,
183 OUT PULONG ReturnedLength OPTIONAL
)
186 UNICODE_STRING ValueNameString
, IntegerString
;
187 ULONG KeyInfoSize
, ResultSize
;
188 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)&KeyInfo
;
189 BOOLEAN FreeHeap
= FALSE
;
192 /* Build a string for the value name */
193 Status
= RtlInitUnicodeStringEx(&ValueNameString
, ValueName
);
194 if (!NT_SUCCESS(Status
)) return Status
;
196 /* Query the value */
197 Status
= ZwQueryValueKey(KeyHandle
,
199 KeyValuePartialInformation
,
203 if (Status
== STATUS_BUFFER_OVERFLOW
)
205 /* Our local buffer wasn't enough, allocate one */
206 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
207 KeyValueInformation
->DataLength
;
208 KeyValueInformation
= RtlAllocateHeap(RtlGetProcessHeap(),
211 if (KeyValueInformation
!= NULL
)
214 Status
= ZwQueryValueKey(KeyHandle
,
216 KeyValuePartialInformation
,
224 /* Give up this time */
225 Status
= STATUS_NO_MEMORY
;
229 /* Check for success */
230 if (NT_SUCCESS(Status
))
232 /* Handle binary data */
233 if (KeyValueInformation
->Type
== REG_BINARY
)
236 if ((Buffer
) && (KeyValueInformation
->DataLength
<= BufferSize
))
238 /* Copy into buffer */
239 RtlMoveMemory(Buffer
,
240 &KeyValueInformation
->Data
,
241 KeyValueInformation
->DataLength
);
245 Status
= STATUS_BUFFER_OVERFLOW
;
248 /* Copy the result length */
249 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
251 else if (KeyValueInformation
->Type
== REG_DWORD
)
253 /* Check for valid type */
254 if (KeyValueInformation
->Type
!= Type
)
257 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
263 (BufferSize
== sizeof(ULONG
)) &&
264 (KeyValueInformation
->DataLength
<= BufferSize
))
266 /* Copy into buffer */
267 RtlMoveMemory(Buffer
,
268 &KeyValueInformation
->Data
,
269 KeyValueInformation
->DataLength
);
273 Status
= STATUS_BUFFER_OVERFLOW
;
276 /* Copy the result length */
277 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
280 else if (KeyValueInformation
->Type
!= REG_SZ
)
282 /* We got something weird */
283 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
287 /* String, check what you requested */
288 if (Type
== REG_DWORD
)
291 if (BufferSize
!= sizeof(ULONG
))
295 Status
= STATUS_INFO_LENGTH_MISMATCH
;
299 /* OK, we know what you want... */
300 IntegerString
.Buffer
= (PWSTR
)KeyValueInformation
->Data
;
301 IntegerString
.Length
= (USHORT
)KeyValueInformation
->DataLength
-
303 IntegerString
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
304 Status
= RtlUnicodeStringToInteger(&IntegerString
, 0, (PULONG
)Buffer
);
310 if (KeyValueInformation
->DataLength
> BufferSize
)
313 Status
= STATUS_BUFFER_OVERFLOW
;
318 BufferSize
= KeyValueInformation
->DataLength
;
321 /* Copy the string */
322 RtlMoveMemory(Buffer
, &KeyValueInformation
->Data
, BufferSize
);
325 /* Copy the result length */
326 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
330 /* Check if buffer was in heap */
331 if (FreeHeap
) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation
);
342 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey
,
347 OUT PULONG ReturnedLength OPTIONAL
,
353 /* Open a handle to the key */
354 Status
= LdrOpenImageFileOptionsKey(SubKey
, Wow64
, &KeyHandle
);
356 /* Check for success */
357 if (NT_SUCCESS(Status
))
360 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
371 /* Return to caller */
380 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey
,
385 OUT PULONG ReturnedLength OPTIONAL
)
387 /* Call the newer function */
388 return LdrQueryImageFileExecutionOptionsEx(SubKey
,
399 LdrpEnsureLoaderLockIsHeld(VOID
)
406 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress
, ULONG SizeOfImage
)
408 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir
;
412 /* Check NT header first */
413 if (!RtlImageNtHeader(BaseAddress
)) return NULL
;
415 /* Get the pointer to the config directory */
416 ConfigDir
= RtlImageDirectoryEntryToData(BaseAddress
,
418 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
421 /* Check for sanity */
423 (DirSize
!= 64 && ConfigDir
->Size
!= DirSize
) ||
424 (ConfigDir
->Size
< 0x48))
427 /* Now get the cookie */
428 Cookie
= (PVOID
)ConfigDir
->SecurityCookie
;
430 /* Check this cookie */
431 if ((PCHAR
)Cookie
<= (PCHAR
)BaseAddress
||
432 (PCHAR
)Cookie
>= (PCHAR
)BaseAddress
+ SizeOfImage
)
437 /* Return validated security cookie */
443 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry
)
446 LARGE_INTEGER Counter
;
449 /* Fetch address of the cookie */
450 Cookie
= LdrpFetchAddressOfSecurityCookie(LdrEntry
->DllBase
, LdrEntry
->SizeOfImage
);
454 /* Check if it's a default one */
455 if ((*Cookie
== DEFAULT_SECURITY_COOKIE
) ||
458 /* Make up a cookie from a bunch of values which may uniquely represent
459 current moment of time, environment, etc */
460 NtQueryPerformanceCounter(&Counter
, NULL
);
462 NewCookie
= Counter
.LowPart
^ Counter
.HighPart
;
463 NewCookie
^= (ULONG
)NtCurrentTeb()->ClientId
.UniqueProcess
;
464 NewCookie
^= (ULONG
)NtCurrentTeb()->ClientId
.UniqueThread
;
466 /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */
467 while (SharedUserData
->SystemTime
.High1Time
!= SharedUserData
->SystemTime
.High2Time
)
472 /* Calculate the milliseconds value and xor it to the cookie */
473 NewCookie
^= Int64ShrlMod32(UInt32x32To64(SharedUserData
->TickCountMultiplier
, SharedUserData
->TickCount
.LowPart
), 24) +
474 (SharedUserData
->TickCountMultiplier
* (SharedUserData
->TickCount
.High1Time
<< 8));
476 /* Make the cookie 16bit if necessary */
477 if (*Cookie
== 0xBB40) NewCookie
&= 0xFFFF;
479 /* If the result is 0 or the same as we got, just subtract one from the existing value
481 if ((NewCookie
== 0) || (NewCookie
== *Cookie
))
483 NewCookie
= *Cookie
- 1;
486 /* Set the new cookie value */
496 LdrpInitializeThread(IN PCONTEXT Context
)
498 PPEB Peb
= NtCurrentPeb();
499 PLDR_DATA_TABLE_ENTRY LdrEntry
;
500 PLIST_ENTRY NextEntry
, ListHead
;
501 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
505 DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n",
506 &LdrpImageEntry
->BaseDllName
,
507 NtCurrentTeb()->RealClientId
.UniqueProcess
,
508 NtCurrentTeb()->RealClientId
.UniqueThread
);
510 /* Allocate an Activation Context Stack */
511 DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer
);
512 Status
= RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer
);
513 if (!NT_SUCCESS(Status
))
515 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
518 /* Make sure we are not shutting down */
519 if (LdrpShutdownInProgress
) return;
524 /* Start at the beginning */
525 ListHead
= &Peb
->Ldr
->InMemoryOrderModuleList
;
526 NextEntry
= ListHead
->Flink
;
527 while (NextEntry
!= ListHead
)
529 /* Get the current entry */
530 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InMemoryOrderLinks
);
532 /* Make sure it's not ourselves */
533 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
535 /* Check if we should call */
536 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
))
538 /* Get the entrypoint */
539 EntryPoint
= LdrEntry
->EntryPoint
;
541 /* Check if we are ready to call it */
543 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
544 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
546 /* Set up the Act Ctx */
547 ActCtx
.Size
= sizeof(ActCtx
);
549 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
551 /* Activate the ActCtx */
552 RtlActivateActivationContextUnsafeFast(&ActCtx
,
553 LdrEntry
->EntryPointActivationContext
);
555 /* Check if it has TLS */
556 if (LdrEntry
->TlsIndex
)
558 /* Make sure we're not shutting down */
559 if (!LdrpShutdownInProgress
)
562 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_THREAD_ATTACH
);
566 /* Make sure we're not shutting down */
567 if (!LdrpShutdownInProgress
)
569 /* Call the Entrypoint */
570 DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n",
571 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
,
572 NtCurrentTeb()->RealClientId
.UniqueProcess
,
573 NtCurrentTeb()->RealClientId
.UniqueThread
);
574 LdrpCallInitRoutine(LdrEntry
->EntryPoint
,
580 /* Deactivate the ActCtx */
581 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
587 NextEntry
= NextEntry
->Flink
;
591 if (LdrpImageHasTls
&& !LdrpShutdownInProgress
)
593 /* Set up the Act Ctx */
594 ActCtx
.Size
= sizeof(ActCtx
);
596 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
598 /* Activate the ActCtx */
599 RtlActivateActivationContextUnsafeFast(&ActCtx
,
600 LdrpImageEntry
->EntryPointActivationContext
);
602 /* Do TLS callbacks */
603 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_THREAD_ATTACH
);
605 /* Deactivate the ActCtx */
606 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
609 DPRINT("LdrpInitializeThread() done\n");
614 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL
)
616 PLDR_DATA_TABLE_ENTRY LocalArray
[16];
617 PLIST_ENTRY ListHead
;
618 PLIST_ENTRY NextEntry
;
619 PLDR_DATA_TABLE_ENTRY LdrEntry
, *LdrRootEntry
, OldInitializer
;
623 NTSTATUS Status
= STATUS_SUCCESS
;
624 PPEB Peb
= NtCurrentPeb();
625 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
626 ULONG BreakOnDllLoad
;
630 DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
631 &LdrpImageEntry
->BaseDllName
,
632 NtCurrentTeb()->RealClientId
.UniqueProcess
,
633 NtCurrentTeb()->RealClientId
.UniqueThread
);
635 /* Check the Loader Lock */
636 LdrpEnsureLoaderLockIsHeld();
638 /* Get the number of entries to call */
639 if ((Count
= LdrpClearLoadInProgress()))
641 /* Check if we can use our local buffer */
644 /* Allocate space for all the entries */
645 LdrRootEntry
= RtlAllocateHeap(RtlGetProcessHeap(),
647 Count
* sizeof(*LdrRootEntry
));
648 if (!LdrRootEntry
) return STATUS_NO_MEMORY
;
652 /* Use our local array */
653 LdrRootEntry
= LocalArray
;
662 /* Show debug message */
665 DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
666 NtCurrentTeb()->RealClientId
.UniqueThread
,
667 NtCurrentTeb()->RealClientId
.UniqueProcess
,
668 &Peb
->ProcessParameters
->ImagePathName
);
672 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
673 NextEntry
= ListHead
->Flink
;
675 while (NextEntry
!= ListHead
)
677 /* Get the Data Entry */
678 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
680 /* Check if we have a Root Entry */
684 if (!(LdrEntry
->Flags
& LDRP_ENTRY_PROCESSED
))
686 /* Setup the Cookie for the DLL */
687 LdrpInitSecurityCookie(LdrEntry
);
689 /* Check for valid entrypoint */
690 if (LdrEntry
->EntryPoint
)
694 LdrRootEntry
[i
] = LdrEntry
;
696 /* Display debug message */
699 DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
700 NtCurrentTeb()->RealClientId
.UniqueThread
,
701 NtCurrentTeb()->RealClientId
.UniqueProcess
,
702 &LdrEntry
->FullDllName
,
703 LdrEntry
->EntryPoint
);
711 LdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
712 NextEntry
= NextEntry
->Flink
;
715 /* If we got a context, then we have to call Kernel32 for TS support */
718 /* Check if we have one */
719 //if (Kernel32ProcessInitPostImportfunction)
722 //Kernel32ProcessInitPostImportfunction();
726 //Kernel32ProcessInitPostImportfunction = NULL;
730 /* No root entry? return */
731 if (!LdrRootEntry
) return STATUS_SUCCESS
;
733 /* Set the TLD TEB */
734 OldTldTeb
= LdrpTopLevelDllBeingLoadedTeb
;
735 LdrpTopLevelDllBeingLoadedTeb
= NtCurrentTeb();
742 LdrEntry
= LdrRootEntry
[i
];
744 /* FIXME: Verify NX Compat */
746 /* Move to next entry */
749 /* Get its entrypoint */
750 EntryPoint
= LdrEntry
->EntryPoint
;
752 /* Are we being debugged? */
754 if (Peb
->BeingDebugged
|| Peb
->ReadImageFileExecOptions
)
756 /* Check if we should break on load */
757 Status
= LdrQueryImageFileExecutionOptions(&LdrEntry
->BaseDllName
,
763 if (!NT_SUCCESS(Status
)) BreakOnDllLoad
= 0;
765 /* Reset status back to STATUS_SUCCESS */
766 Status
= STATUS_SUCCESS
;
772 /* Check if we should show a message */
775 DPRINT1("LDR: %wZ loaded.", &LdrEntry
->BaseDllName
);
776 DPRINT1(" - About to call init routine at %p\n", EntryPoint
);
779 /* Break in debugger */
783 /* Make sure we have an entrypoint */
786 /* Save the old Dll Initializer and write the current one */
787 OldInitializer
= LdrpCurrentDllInitializer
;
788 LdrpCurrentDllInitializer
= LdrEntry
;
790 /* Set up the Act Ctx */
791 ActCtx
.Size
= sizeof(ActCtx
);
793 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
795 /* Activate the ActCtx */
796 RtlActivateActivationContextUnsafeFast(&ActCtx
,
797 LdrEntry
->EntryPointActivationContext
);
799 /* Check if it has TLS */
800 if (LdrEntry
->TlsIndex
&& Context
)
803 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_PROCESS_ATTACH
);
806 /* Call the Entrypoint */
809 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
810 &LdrEntry
->BaseDllName
, EntryPoint
);
812 DllStatus
= LdrpCallInitRoutine(EntryPoint
,
817 /* Deactivate the ActCtx */
818 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
820 /* Save the Current DLL Initializer */
821 LdrpCurrentDllInitializer
= OldInitializer
;
823 /* Mark the entry as processed */
824 LdrEntry
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
;
826 /* Fail if DLL init failed */
829 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
830 &LdrEntry
->BaseDllName
, EntryPoint
);
832 Status
= STATUS_DLL_INIT_FAILED
;
839 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
840 NextEntry
= NextEntry
->Flink
;
841 while (NextEntry
!= ListHead
)
843 /* Get the Data Entry */
844 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
846 /* FIXME: Verify NX Compat */
847 // LdrpCheckNXCompatibility()
850 NextEntry
= NextEntry
->Flink
;
854 if (LdrpImageHasTls
&& Context
)
856 /* Set up the Act Ctx */
857 ActCtx
.Size
= sizeof(ActCtx
);
859 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
861 /* Activate the ActCtx */
862 RtlActivateActivationContextUnsafeFast(&ActCtx
,
863 LdrpImageEntry
->EntryPointActivationContext
);
865 /* Do TLS callbacks */
866 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_PROCESS_ATTACH
);
868 /* Deactivate the ActCtx */
869 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
873 /* Restore old TEB */
874 LdrpTopLevelDllBeingLoadedTeb
= OldTldTeb
;
876 /* Check if the array is in the heap */
877 if (LdrRootEntry
!= LocalArray
)
880 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry
);
883 /* Return to caller */
884 DPRINT("LdrpRunInitializeRoutines() done\n");
893 LdrShutdownProcess(VOID
)
895 PPEB Peb
= NtCurrentPeb();
896 PLDR_DATA_TABLE_ENTRY LdrEntry
;
897 PLIST_ENTRY NextEntry
, ListHead
;
898 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
901 DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry
->BaseDllName
);
902 if (LdrpShutdownInProgress
) return STATUS_SUCCESS
;
904 /* Tell the Shim Engine */
907 VOID(NTAPI
*SE_ProcessDying
)();
908 SE_ProcessDying
= RtlDecodeSystemPointer(g_pfnSE_ProcessDying
);
918 /* Set the shutdown variables */
919 LdrpShutdownThreadId
= NtCurrentTeb()->RealClientId
.UniqueThread
;
920 LdrpShutdownInProgress
= TRUE
;
922 /* Enter the Loader Lock */
923 RtlEnterCriticalSection(&LdrpLoaderLock
);
925 /* Cleanup trace logging data (Etw) */
926 if (SharedUserData
->TraceLogging
)
929 DPRINT1("We don't support Etw yet.\n");
932 /* Start at the end */
933 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
934 NextEntry
= ListHead
->Blink
;
935 while (NextEntry
!= ListHead
)
937 /* Get the current entry */
938 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
939 NextEntry
= NextEntry
->Blink
;
941 /* Make sure it's not ourselves */
942 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
944 /* Get the entrypoint */
945 EntryPoint
= LdrEntry
->EntryPoint
;
947 /* Check if we are ready to call it */
949 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
952 /* Set up the Act Ctx */
953 ActCtx
.Size
= sizeof(ActCtx
);
955 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
957 /* Activate the ActCtx */
958 RtlActivateActivationContextUnsafeFast(&ActCtx
,
959 LdrEntry
->EntryPointActivationContext
);
961 /* Check if it has TLS */
962 if (LdrEntry
->TlsIndex
)
965 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_PROCESS_DETACH
);
968 /* Call the Entrypoint */
969 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
970 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
971 LdrpCallInitRoutine(EntryPoint
,
976 /* Deactivate the ActCtx */
977 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
985 /* Set up the Act Ctx */
986 ActCtx
.Size
= sizeof(ActCtx
);
988 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
990 /* Activate the ActCtx */
991 RtlActivateActivationContextUnsafeFast(&ActCtx
,
992 LdrpImageEntry
->EntryPointActivationContext
);
994 /* Do TLS callbacks */
995 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_PROCESS_DETACH
);
997 /* Deactivate the ActCtx */
998 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1001 /* FIXME: Do Heap detection and Etw final shutdown */
1003 /* Release the lock */
1004 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1005 DPRINT("LdrpShutdownProcess() done\n");
1007 return STATUS_SUCCESS
;
1015 LdrShutdownThread(VOID
)
1017 PPEB Peb
= NtCurrentPeb();
1018 PTEB Teb
= NtCurrentTeb();
1019 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1020 PLIST_ENTRY NextEntry
, ListHead
;
1021 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
1024 DPRINT("LdrShutdownThread() called for %wZ\n",
1025 &LdrpImageEntry
->BaseDllName
);
1027 /* Cleanup trace logging data (Etw) */
1028 if (SharedUserData
->TraceLogging
)
1031 DPRINT1("We don't support Etw yet.\n");
1034 /* Get the Ldr Lock */
1035 RtlEnterCriticalSection(&LdrpLoaderLock
);
1037 /* Start at the end */
1038 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
1039 NextEntry
= ListHead
->Blink
;
1040 while (NextEntry
!= ListHead
)
1042 /* Get the current entry */
1043 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
1044 NextEntry
= NextEntry
->Blink
;
1046 /* Make sure it's not ourselves */
1047 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
1049 /* Check if we should call */
1050 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
1051 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
1052 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
1054 /* Get the entrypoint */
1055 EntryPoint
= LdrEntry
->EntryPoint
;
1057 /* Check if we are ready to call it */
1060 /* Set up the Act Ctx */
1061 ActCtx
.Size
= sizeof(ActCtx
);
1063 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1065 /* Activate the ActCtx */
1066 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1067 LdrEntry
->EntryPointActivationContext
);
1069 /* Check if it has TLS */
1070 if (LdrEntry
->TlsIndex
)
1072 /* Make sure we're not shutting down */
1073 if (!LdrpShutdownInProgress
)
1076 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_THREAD_DETACH
);
1080 /* Make sure we're not shutting down */
1081 if (!LdrpShutdownInProgress
)
1083 /* Call the Entrypoint */
1084 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1085 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1086 LdrpCallInitRoutine(EntryPoint
,
1092 /* Deactivate the ActCtx */
1093 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1100 if (LdrpImageHasTls
)
1102 /* Set up the Act Ctx */
1103 ActCtx
.Size
= sizeof(ActCtx
);
1105 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1107 /* Activate the ActCtx */
1108 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1109 LdrpImageEntry
->EntryPointActivationContext
);
1111 /* Do TLS callbacks */
1112 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_THREAD_DETACH
);
1114 /* Deactivate the ActCtx */
1115 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1120 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1122 /* Check for expansion slots */
1123 if (Teb
->TlsExpansionSlots
)
1125 /* Free expansion slots */
1126 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->TlsExpansionSlots
);
1129 /* Check for FLS Data */
1133 DPRINT1("We don't support FLS Data yet\n");
1136 /* Check for Fiber data */
1137 if (Teb
->HasFiberData
)
1139 /* Free Fiber data*/
1140 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->NtTib
.FiberData
);
1141 Teb
->NtTib
.FiberData
= NULL
;
1144 /* Free the activation context stack */
1145 RtlFreeThreadActivationContextStack();
1146 DPRINT("LdrShutdownThread() done\n");
1148 return STATUS_SUCCESS
;
1153 LdrpInitializeTls(VOID
)
1155 PLIST_ENTRY NextEntry
, ListHead
;
1156 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1157 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1158 PLDRP_TLS_DATA TlsData
;
1161 /* Initialize the TLS List */
1162 InitializeListHead(&LdrpTlsList
);
1164 /* Loop all the modules */
1165 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1166 NextEntry
= ListHead
->Flink
;
1167 while (ListHead
!= NextEntry
)
1170 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1171 NextEntry
= NextEntry
->Flink
;
1173 /* Get the TLS directory */
1174 TlsDirectory
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
1176 IMAGE_DIRECTORY_ENTRY_TLS
,
1179 /* Check if we have a directory */
1180 if (!TlsDirectory
) continue;
1182 /* Check if the image has TLS */
1183 if (!LdrpImageHasTls
) LdrpImageHasTls
= TRUE
;
1185 /* Show debug message */
1188 DPRINT1("LDR: Tls Found in %wZ at %p\n",
1189 &LdrEntry
->BaseDllName
,
1193 /* Allocate an entry */
1194 TlsData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA
));
1195 if (!TlsData
) return STATUS_NO_MEMORY
;
1197 /* Lock the DLL and mark it for TLS Usage */
1198 LdrEntry
->LoadCount
= -1;
1199 LdrEntry
->TlsIndex
= -1;
1201 /* Save the cached TLS data */
1202 TlsData
->TlsDirectory
= *TlsDirectory
;
1203 InsertTailList(&LdrpTlsList
, &TlsData
->TlsLinks
);
1205 /* Update the index */
1206 *(PLONG
)TlsData
->TlsDirectory
.AddressOfIndex
= LdrpNumberOfTlsEntries
;
1207 TlsData
->TlsDirectory
.Characteristics
= LdrpNumberOfTlsEntries
++;
1210 /* Done setting up TLS, allocate entries */
1211 return LdrpAllocateTls();
1216 LdrpAllocateTls(VOID
)
1218 PTEB Teb
= NtCurrentTeb();
1219 PLIST_ENTRY NextEntry
, ListHead
;
1220 PLDRP_TLS_DATA TlsData
;
1224 /* Check if we have any entries */
1225 if (!LdrpNumberOfTlsEntries
)
1226 return STATUS_SUCCESS
;
1228 /* Allocate the vector array */
1229 TlsVector
= RtlAllocateHeap(RtlGetProcessHeap(),
1231 LdrpNumberOfTlsEntries
* sizeof(PVOID
));
1232 if (!TlsVector
) return STATUS_NO_MEMORY
;
1233 Teb
->ThreadLocalStoragePointer
= TlsVector
;
1235 /* Loop the TLS Array */
1236 ListHead
= &LdrpTlsList
;
1237 NextEntry
= ListHead
->Flink
;
1238 while (NextEntry
!= ListHead
)
1241 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1242 NextEntry
= NextEntry
->Flink
;
1244 /* Allocate this vector */
1245 TlsDataSize
= TlsData
->TlsDirectory
.EndAddressOfRawData
-
1246 TlsData
->TlsDirectory
.StartAddressOfRawData
;
1247 TlsVector
[TlsData
->TlsDirectory
.Characteristics
] = RtlAllocateHeap(RtlGetProcessHeap(),
1250 if (!TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1253 return STATUS_NO_MEMORY
;
1256 /* Show debug message */
1259 DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
1261 TlsData
->TlsDirectory
.Characteristics
,
1262 &TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1263 TlsData
->TlsDirectory
.StartAddressOfRawData
,
1264 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1268 RtlCopyMemory(TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1269 (PVOID
)TlsData
->TlsDirectory
.StartAddressOfRawData
,
1274 return STATUS_SUCCESS
;
1281 PLIST_ENTRY ListHead
, NextEntry
;
1282 PLDRP_TLS_DATA TlsData
;
1284 PTEB Teb
= NtCurrentTeb();
1286 /* Get a pointer to the vector array */
1287 TlsVector
= Teb
->ThreadLocalStoragePointer
;
1288 if (!TlsVector
) return;
1290 /* Loop through it */
1291 ListHead
= &LdrpTlsList
;
1292 NextEntry
= ListHead
->Flink
;
1293 while (NextEntry
!= ListHead
)
1295 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1296 NextEntry
= NextEntry
->Flink
;
1298 /* Free each entry */
1299 if (TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1301 RtlFreeHeap(RtlGetProcessHeap(),
1303 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1307 /* Free the array itself */
1308 RtlFreeHeap(RtlGetProcessHeap(),
1315 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName
, PPEB Peb
, PHANDLE OptionsKey
)
1319 ULONG ExecuteOptions
, MinimumStackCommit
= 0, GlobalFlag
;
1321 /* Return error if we were not provided a pointer where to save the options key handle */
1322 if (!OptionsKey
) return STATUS_INVALID_HANDLE
;
1324 /* Zero initialize the options key pointer */
1327 /* Open the options key */
1328 Status
= LdrOpenImageFileOptionsKey(ImagePathName
, 0, &KeyHandle
);
1330 /* Save it if it was opened successfully */
1331 if (NT_SUCCESS(Status
))
1332 *OptionsKey
= KeyHandle
;
1336 /* There are image specific options, read them starting with NXCOMPAT */
1337 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1341 sizeof(ExecuteOptions
),
1344 if (NT_SUCCESS(Status
))
1346 /* TODO: Set execution options for the process */
1348 if (ExecuteOptions == 0)
1352 ZwSetInformationProcess(NtCurrentProcess(),
1353 ProcessExecuteFlags,
1359 /* Check if this image uses large pages */
1360 if (Peb
->ImageUsesLargePages
)
1362 /* TODO: If it does, open large page key */
1366 /* Get various option values */
1367 LdrQueryImageFileKeyOption(KeyHandle
,
1368 L
"DisableHeapLookaside",
1370 &RtlpDisableHeapLookaside
,
1371 sizeof(RtlpDisableHeapLookaside
),
1374 LdrQueryImageFileKeyOption(KeyHandle
,
1377 &RtlpShutdownProcessFlags
,
1378 sizeof(RtlpShutdownProcessFlags
),
1381 LdrQueryImageFileKeyOption(KeyHandle
,
1382 L
"MinimumStackCommitInBytes",
1384 &MinimumStackCommit
,
1385 sizeof(MinimumStackCommit
),
1388 /* Update PEB's minimum stack commit if it's lower */
1389 if (Peb
->MinimumStackCommit
< MinimumStackCommit
)
1390 Peb
->MinimumStackCommit
= MinimumStackCommit
;
1392 /* Set the global flag */
1393 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1400 if (NT_SUCCESS(Status
))
1401 Peb
->NtGlobalFlag
= GlobalFlag
;
1405 /* Call AVRF if necessary */
1406 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1408 Status
= LdrpInitializeApplicationVerifierPackage(KeyHandle
, Peb
, TRUE
, FALSE
);
1409 if (!NT_SUCCESS(Status
))
1411 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1417 /* There are no image-specific options, so perform global initialization */
1418 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1420 /* Initialize app verifier package */
1421 Status
= LdrpInitializeApplicationVerifierPackage(KeyHandle
, Peb
, TRUE
, FALSE
);
1422 if (!NT_SUCCESS(Status
))
1424 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1429 return STATUS_SUCCESS
;
1434 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
)
1441 LdrpInitializeProcessCompat(PVOID
* pOldShimData
)
1443 static const GUID
* GuidOrder
[] = { &COMPAT_GUID_WIN10
, &COMPAT_GUID_WIN81
, &COMPAT_GUID_WIN8
,
1444 &COMPAT_GUID_WIN7
, &COMPAT_GUID_VISTA
};
1445 static const DWORD GuidVersions
[] = { WINVER_WIN10
, WINVER_WIN81
, WINVER_WIN8
, WINVER_WIN7
, WINVER_VISTA
};
1447 ULONG Buffer
[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
)) / sizeof(ULONG
)];
1448 ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
* ContextCompatInfo
;
1449 SIZE_T SizeRequired
;
1452 ReactOS_ShimData
* pShimData
= *pOldShimData
;
1454 C_ASSERT(RTL_NUMBER_OF(GuidOrder
) == RTL_NUMBER_OF(GuidVersions
));
1458 if (pShimData
->dwMagic
!= REACTOS_SHIMDATA_MAGIC
||
1459 pShimData
->dwSize
!= sizeof(ReactOS_ShimData
))
1461 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData
->dwMagic
, pShimData
->dwSize
);
1464 if (pShimData
->dwRosProcessCompatVersion
)
1466 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData
->dwRosProcessCompatVersion
);
1471 SizeRequired
= sizeof(Buffer
);
1472 Status
= RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
,
1475 CompatibilityInformationInActivationContext
,
1480 if (!NT_SUCCESS(Status
))
1482 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status
);
1486 ContextCompatInfo
= (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
*)Buffer
;
1487 /* No Compatibility elements present, bail out */
1488 if (ContextCompatInfo
->ElementCount
== 0)
1491 /* Search for known GUID's, starting from newest to oldest. */
1492 for (cur
= 0; cur
< RTL_NUMBER_OF(GuidOrder
); ++cur
)
1494 for (n
= 0; n
< ContextCompatInfo
->ElementCount
; ++n
)
1496 if (ContextCompatInfo
->Elements
[n
].Type
== ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
&&
1497 RtlCompareMemory(&ContextCompatInfo
->Elements
[n
].Id
, GuidOrder
[cur
], sizeof(GUID
)) == sizeof(GUID
))
1499 /* If this process did not need shim data before, allocate and store it */
1500 if (pShimData
== NULL
)
1502 PPEB Peb
= NtCurrentPeb();
1504 ASSERT(Peb
->pShimData
== NULL
);
1505 pShimData
= RtlAllocateHeap(Peb
->ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(*pShimData
));
1509 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData
));
1513 pShimData
->dwSize
= sizeof(*pShimData
);
1514 pShimData
->dwMagic
= REACTOS_SHIMDATA_MAGIC
;
1516 Peb
->pShimData
= pShimData
;
1517 *pOldShimData
= pShimData
;
1520 /* Store the highest found version, and bail out. */
1521 pShimData
->dwRosProcessCompatVersion
= GuidVersions
[cur
];
1522 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", GuidVersions
[cur
]);
1532 LdrpInitializeProcess(IN PCONTEXT Context
,
1533 IN PVOID SystemArgument1
)
1535 RTL_HEAP_PARAMETERS HeapParameters
;
1536 ULONG ComSectionSize
;
1537 //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData");
1539 OBJECT_ATTRIBUTES ObjectAttributes
;
1540 //UNICODE_STRING LocalFileName, FullImageName;
1541 HANDLE SymLinkHandle
;
1542 //ULONG DebugHeapOnly;
1543 UNICODE_STRING CommandLine
, NtSystemRoot
, ImagePathName
, FullPath
, ImageFileName
, KnownDllString
;
1544 PPEB Peb
= NtCurrentPeb();
1545 BOOLEAN IsDotNetImage
= FALSE
;
1546 BOOLEAN FreeCurDir
= FALSE
;
1548 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1549 //LPWSTR ImagePathBuffer;
1551 UNICODE_STRING CurrentDirectory
;
1554 PIMAGE_NT_HEADERS NtHeader
;
1555 LPWSTR NtDllName
= NULL
;
1556 NTSTATUS Status
, ImportStatus
;
1557 NLSTABLEINFO NlsTable
;
1558 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig
;
1559 PTEB Teb
= NtCurrentTeb();
1560 PLIST_ENTRY ListHead
;
1561 PLIST_ENTRY NextEntry
;
1564 ULONG DebugProcessHeapOnly
= 0;
1565 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
1567 ULONG ExecuteOptions
= 0;
1570 /* Set a NULL SEH Filter */
1571 RtlSetUnhandledExceptionFilter(NULL
);
1573 /* Get the image path */
1574 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
1576 /* Check if it's not normalized */
1577 if (!(Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
))
1580 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
1583 /* Create a unicode string for the Image Path */
1584 ImagePathName
.Length
= Peb
->ProcessParameters
->ImagePathName
.Length
;
1585 ImagePathName
.MaximumLength
= ImagePathName
.Length
+ sizeof(WCHAR
);
1586 ImagePathName
.Buffer
= ImagePath
;
1588 /* Get the NT Headers */
1589 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
1591 /* Get the execution options */
1592 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &OptionsKey
);
1594 /* Check if this is a .NET executable */
1595 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1597 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
1600 /* Remember this for later */
1601 IsDotNetImage
= TRUE
;
1604 /* Save the NTDLL Base address */
1605 NtDllBase
= SystemArgument1
;
1607 /* If this is a Native Image */
1608 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
1610 /* Then do DLL Validation */
1611 LdrpDllValidation
= TRUE
;
1614 /* Save the old Shim Data */
1615 OldShimData
= Peb
->pShimData
;
1617 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */
1618 //Peb->pShimData = NULL;
1620 /* Save the number of processors and CS Timeout */
1621 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
1622 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
1624 /* Normalize the parameters */
1625 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
1626 if (ProcessParameters
)
1628 /* Save the Image and Command Line Names */
1629 ImageFileName
= ProcessParameters
->ImagePathName
;
1630 CommandLine
= ProcessParameters
->CommandLine
;
1634 /* It failed, initialize empty strings */
1635 RtlInitUnicodeString(&ImageFileName
, NULL
);
1636 RtlInitUnicodeString(&CommandLine
, NULL
);
1639 /* Initialize NLS data */
1640 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1641 Peb
->OemCodePageData
,
1642 Peb
->UnicodeCaseTableData
,
1645 /* Reset NLS Translations */
1646 RtlResetRtlTranslations(&NlsTable
);
1648 /* Get the Image Config Directory */
1649 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1651 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1654 /* Setup the Heap Parameters */
1655 RtlZeroMemory(&HeapParameters
, sizeof(RTL_HEAP_PARAMETERS
));
1656 HeapFlags
= HEAP_GROWABLE
;
1657 HeapParameters
.Length
= sizeof(RTL_HEAP_PARAMETERS
);
1659 /* Check if we have Configuration Data */
1660 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1662 /* FIXME: Custom heap settings and misc. */
1663 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1666 /* Check for custom affinity mask */
1667 if (Peb
->ImageProcessAffinityMask
)
1670 Status
= NtSetInformationProcess(NtCurrentProcess(),
1671 ProcessAffinityMask
,
1672 &Peb
->ImageProcessAffinityMask
,
1673 sizeof(Peb
->ImageProcessAffinityMask
));
1676 /* Check if verbose debugging (ShowSnaps) was requested */
1677 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1679 /* Start verbose debugging messages right now if they were requested */
1682 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1683 Teb
->ClientId
.UniqueProcess
,
1687 /* If the timeout is too long */
1688 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1690 /* Then disable CS Timeout */
1691 RtlpTimeoutDisable
= TRUE
;
1694 /* Initialize Critical Section Data */
1695 RtlpInitDeferedCriticalSection();
1697 /* Initialize VEH Call lists */
1698 RtlpInitializeVectoredExceptionHandling();
1700 /* Set TLS/FLS Bitmap data */
1701 Peb
->FlsBitmap
= &FlsBitMap
;
1702 Peb
->TlsBitmap
= &TlsBitMap
;
1703 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1705 /* Initialize FLS Bitmap */
1706 RtlInitializeBitMap(&FlsBitMap
,
1708 FLS_MAXIMUM_AVAILABLE
);
1709 RtlSetBit(&FlsBitMap
, 0);
1711 /* Initialize TLS Bitmap */
1712 RtlInitializeBitMap(&TlsBitMap
,
1714 TLS_MINIMUM_AVAILABLE
);
1715 RtlSetBit(&TlsBitMap
, 0);
1716 RtlInitializeBitMap(&TlsExpansionBitMap
,
1717 Peb
->TlsExpansionBitmapBits
,
1718 TLS_EXPANSION_SLOTS
);
1719 RtlSetBit(&TlsExpansionBitMap
, 0);
1721 /* Initialize the Hash Table */
1722 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1724 InitializeListHead(&LdrpHashTable
[i
]);
1727 /* Initialize the Loader Lock */
1728 // FIXME: What's the point of initing it manually, if two lines lower
1729 // a call to RtlInitializeCriticalSection() is being made anyway?
1730 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1731 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1732 RtlInitializeCriticalSection(&LdrpLoaderLock
);
1733 LdrpLoaderLockInit
= TRUE
;
1735 /* Check if User Stack Trace Database support was requested */
1736 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1738 DPRINT1("We don't support user stack trace databases yet\n");
1741 /* Setup Fast PEB Lock */
1742 RtlInitializeCriticalSection(&FastPebLock
);
1743 Peb
->FastPebLock
= &FastPebLock
;
1744 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1745 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1747 /* Setup Callout Lock and Notification list */
1748 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1749 InitializeListHead(&LdrpDllNotificationList
);
1751 /* For old executables, use 16-byte aligned heap */
1752 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1753 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1755 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1758 /* Setup the Heap */
1759 RtlInitializeHeapManager();
1760 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1762 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1763 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1767 if (!Peb
->ProcessHeap
)
1769 DPRINT1("Failed to create process heap\n");
1770 return STATUS_NO_MEMORY
;
1773 /* Allocate an Activation Context Stack */
1774 Status
= RtlAllocateActivationContextStack(&Teb
->ActivationContextStackPointer
);
1775 if (!NT_SUCCESS(Status
)) return Status
;
1777 // FIXME: Loader private heap is missing
1778 //DPRINT1("Loader private heap is missing\n");
1780 /* Check for Debug Heap */
1783 /* Query the setting */
1784 Status
= LdrQueryImageFileKeyOption(OptionsKey
,
1785 L
"DebugProcessHeapOnly",
1787 &DebugProcessHeapOnly
,
1791 if (NT_SUCCESS(Status
))
1793 /* Reset DPH if requested */
1794 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1796 RtlpDphGlobalFlags
&= ~DPH_FLAG_DLL_NOTIFY
;
1797 RtlpPageHeapEnabled
= FALSE
;
1802 /* Build the NTDLL Path */
1803 FullPath
.Buffer
= StringBuffer
;
1804 FullPath
.Length
= 0;
1805 FullPath
.MaximumLength
= sizeof(StringBuffer
);
1806 RtlInitUnicodeString(&NtSystemRoot
, SharedUserData
->NtSystemRoot
);
1807 RtlAppendUnicodeStringToString(&FullPath
, &NtSystemRoot
);
1808 RtlAppendUnicodeToString(&FullPath
, L
"\\System32\\");
1810 /* Open the Known DLLs directory */
1811 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1812 InitializeObjectAttributes(&ObjectAttributes
,
1814 OBJ_CASE_INSENSITIVE
,
1817 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
1818 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
1821 /* Check if it exists */
1822 if (NT_SUCCESS(Status
))
1824 /* Open the Known DLLs Path */
1825 RtlInitUnicodeString(&KnownDllString
, L
"KnownDllPath");
1826 InitializeObjectAttributes(&ObjectAttributes
,
1828 OBJ_CASE_INSENSITIVE
,
1829 LdrpKnownDllObjectDirectory
,
1831 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
1832 SYMBOLIC_LINK_QUERY
,
1834 if (NT_SUCCESS(Status
))
1836 /* Query the path */
1837 LdrpKnownDllPath
.Length
= 0;
1838 LdrpKnownDllPath
.MaximumLength
= sizeof(LdrpKnownDllPathBuffer
);
1839 LdrpKnownDllPath
.Buffer
= LdrpKnownDllPathBuffer
;
1840 Status
= ZwQuerySymbolicLinkObject(SymLinkHandle
, &LdrpKnownDllPath
, NULL
);
1841 NtClose(SymLinkHandle
);
1842 if (!NT_SUCCESS(Status
))
1844 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
1850 /* Check if we failed */
1851 if (!NT_SUCCESS(Status
))
1853 /* Assume System32 */
1854 LdrpKnownDllObjectDirectory
= NULL
;
1855 RtlInitUnicodeString(&LdrpKnownDllPath
, StringBuffer
);
1856 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
1859 /* If we have process parameters, get the default path and current path */
1860 if (ProcessParameters
)
1862 /* Check if we have a Dll Path */
1863 if (ProcessParameters
->DllPath
.Length
)
1866 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
1870 /* We need a valid path */
1871 DPRINT1("No valid DllPath was given!\n");
1872 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
1875 /* Set the current directory */
1876 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
1878 /* Check if it's empty or invalid */
1879 if ((!CurrentDirectory
.Buffer
) ||
1880 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
1881 (!CurrentDirectory
.Length
))
1883 /* Allocate space for the buffer */
1884 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
1887 sizeof(UNICODE_NULL
));
1888 if (!CurrentDirectory
.Buffer
)
1890 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
1894 /* Copy the drive of the system root */
1895 RtlMoveMemory(CurrentDirectory
.Buffer
,
1896 SharedUserData
->NtSystemRoot
,
1898 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
1899 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
1900 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
1903 DPRINT("Using dynamically allocd curdir\n");
1907 /* Use the local buffer */
1908 DPRINT("Using local system root\n");
1912 /* Setup Loader Data */
1914 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
1915 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
1916 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
1917 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
1918 PebLdr
.Initialized
= TRUE
;
1920 /* Allocate a data entry for the Image */
1921 LdrpImageEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
1924 LdrpImageEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(LdrpImageEntry
->DllBase
);
1925 LdrpImageEntry
->LoadCount
= -1;
1926 LdrpImageEntry
->EntryPointActivationContext
= 0;
1927 LdrpImageEntry
->FullDllName
= ImageFileName
;
1930 LdrpImageEntry
->Flags
= LDRP_COR_IMAGE
;
1932 LdrpImageEntry
->Flags
= 0;
1934 /* Check if the name is empty */
1935 if (!ImageFileName
.Buffer
[0])
1937 /* Use the same Base name */
1938 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
1942 /* Find the last slash */
1943 Current
= ImageFileName
.Buffer
;
1946 if (*Current
++ == '\\')
1949 NtDllName
= Current
;
1953 /* Did we find anything? */
1956 /* Use the same Base name */
1957 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
1961 /* Setup the name */
1962 LdrpImageEntry
->BaseDllName
.Length
= (USHORT
)((ULONG_PTR
)ImageFileName
.Buffer
+ ImageFileName
.Length
- (ULONG_PTR
)NtDllName
);
1963 LdrpImageEntry
->BaseDllName
.MaximumLength
= LdrpImageEntry
->BaseDllName
.Length
+ sizeof(WCHAR
);
1964 LdrpImageEntry
->BaseDllName
.Buffer
= (PWSTR
)((ULONG_PTR
)ImageFileName
.Buffer
+
1965 (ImageFileName
.Length
- LdrpImageEntry
->BaseDllName
.Length
));
1969 /* Processing done, insert it */
1970 LdrpInsertMemoryTableEntry(LdrpImageEntry
);
1971 LdrpImageEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
1973 /* Now add an entry for NTDLL */
1974 NtLdrEntry
= LdrpAllocateDataTableEntry(SystemArgument1
);
1975 NtLdrEntry
->Flags
= LDRP_IMAGE_DLL
;
1976 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
1977 NtLdrEntry
->LoadCount
= -1;
1978 NtLdrEntry
->EntryPointActivationContext
= 0;
1980 NtLdrEntry
->FullDllName
.Length
= FullPath
.Length
;
1981 NtLdrEntry
->FullDllName
.MaximumLength
= FullPath
.MaximumLength
;
1982 NtLdrEntry
->FullDllName
.Buffer
= StringBuffer
;
1983 RtlAppendUnicodeStringToString(&NtLdrEntry
->FullDllName
, &NtDllString
);
1985 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
1986 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
1987 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
1989 /* Processing done, insert it */
1990 LdrpNtDllDataTableEntry
= NtLdrEntry
;
1991 LdrpInsertMemoryTableEntry(NtLdrEntry
);
1993 /* Let the world know */
1996 DPRINT1("LDR: NEW PROCESS\n");
1997 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry
->FullDllName
, &LdrpImageEntry
->BaseDllName
);
1998 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory
);
1999 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath
);
2002 /* Link the Init Order List */
2003 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
2004 &LdrpNtDllDataTableEntry
->InInitializationOrderLinks
);
2006 /* Initialize Wine's active context implementation for the current process */
2009 /* ReactOS specific */
2010 LdrpInitializeProcessCompat(&OldShimData
);
2012 /* Set the current directory */
2013 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
2014 if (!NT_SUCCESS(Status
))
2016 /* We failed, check if we should free it */
2017 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2019 /* Set it to the NT Root */
2020 CurrentDirectory
= NtSystemRoot
;
2021 RtlSetCurrentDirectory_U(&CurrentDirectory
);
2025 /* We're done with it, free it */
2026 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2029 /* Check if we should look for a .local file */
2030 if (ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
)
2033 DPRINT1("We don't support .local overrides yet\n");
2036 /* Check if the Application Verifier was enabled */
2037 if (Peb
->NtGlobalFlag
& FLG_APPLICATION_VERIFIER
)
2039 Status
= AVrfInitializeVerifier();
2040 if (!NT_SUCCESS(Status
))
2042 DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status
);
2051 DPRINT1("We don't support .NET applications yet\n");
2054 /* FIXME: Load support for Terminal Services */
2055 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
)
2057 /* Load kernel32 and call BasePostImportInit... */
2058 DPRINT("Unimplemented codepath!\n");
2061 /* Walk the IAT and load all the DLLs */
2062 ImportStatus
= LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
2064 /* Check if relocation is needed */
2065 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
2067 DPRINT1("LDR: Performing EXE relocation\n");
2069 /* Change the protection to prepare for relocation */
2070 ViewBase
= Peb
->ImageBaseAddress
;
2071 Status
= LdrpSetProtection(ViewBase
, FALSE
);
2072 if (!NT_SUCCESS(Status
)) return Status
;
2074 /* Do the relocation */
2075 Status
= LdrRelocateImageWithBias(ViewBase
,
2079 STATUS_CONFLICTING_ADDRESSES
,
2080 STATUS_INVALID_IMAGE_FORMAT
);
2081 if (!NT_SUCCESS(Status
))
2083 DPRINT1("LdrRelocateImageWithBias() failed\n");
2087 /* Check if a start context was provided */
2090 DPRINT1("WARNING: Relocated EXE Context");
2091 UNIMPLEMENTED
; // We should support this
2092 return STATUS_INVALID_IMAGE_FORMAT
;
2095 /* Restore the protection */
2096 Status
= LdrpSetProtection(ViewBase
, TRUE
);
2097 if (!NT_SUCCESS(Status
)) return Status
;
2101 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
2102 NextEntry
= ListHead
->Flink
;
2103 while (ListHead
!= NextEntry
)
2105 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2106 NtLdrEntry
->LoadCount
= -1;
2107 NextEntry
= NextEntry
->Flink
;
2110 /* Phase 0 is done */
2111 LdrpLdrDatabaseIsSetup
= TRUE
;
2113 /* Check whether all static imports were properly loaded and return here */
2114 if (!NT_SUCCESS(ImportStatus
)) return ImportStatus
;
2116 /* Initialize TLS */
2117 Status
= LdrpInitializeTls();
2118 if (!NT_SUCCESS(Status
))
2120 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2125 /* FIXME Mark the DLL Ranges for Stack Traces later */
2127 /* Notify the debugger now */
2128 if (Peb
->BeingDebugged
)
2133 /* Update show snaps again */
2134 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
2137 /* Validate the Image for MP Usage */
2138 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
2140 /* Check NX Options */
2141 if (SharedUserData
->NXSupportPolicy
== 1)
2143 ExecuteOptions
= 0xD;
2145 else if (!SharedUserData
->NXSupportPolicy
)
2147 ExecuteOptions
= 0xA;
2151 ZwSetInformationProcess(NtCurrentProcess(),
2152 ProcessExecuteFlags
,
2156 // FIXME: Should be done by Application Compatibility features,
2157 // by reading the registry, etc...
2158 // For now, this is the old code from ntdll!RtlGetVersion().
2159 RtlInitEmptyUnicodeString(&Peb
->CSDVersion
, NULL
, 0);
2160 if (((Peb
->OSCSDVersion
>> 8) & 0xFF) != 0)
2162 WCHAR szCSDVersion
[128];
2164 ULONG Length
= ARRAYSIZE(szCSDVersion
) - 1;
2165 i
= _snwprintf(szCSDVersion
, Length
,
2167 ((Peb
->OSCSDVersion
>> 8) & 0xFF));
2170 /* Null-terminate if it was overflowed */
2171 szCSDVersion
[Length
] = UNICODE_NULL
;
2174 Length
*= sizeof(WCHAR
);
2175 Peb
->CSDVersion
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
2177 Length
+ sizeof(UNICODE_NULL
));
2178 if (Peb
->CSDVersion
.Buffer
)
2180 Peb
->CSDVersion
.Length
= Length
;
2181 Peb
->CSDVersion
.MaximumLength
= Length
+ sizeof(UNICODE_NULL
);
2183 RtlCopyMemory(Peb
->CSDVersion
.Buffer
,
2185 Peb
->CSDVersion
.MaximumLength
);
2186 Peb
->CSDVersion
.Buffer
[Peb
->CSDVersion
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2190 /* Check if we had Shim Data */
2193 /* Load the Shim Engine */
2194 Peb
->AppCompatInfo
= NULL
;
2195 LdrpLoadShimEngine(OldShimData
, &ImagePathName
, OldShimData
);
2199 /* Check for Application Compatibility Goo */
2200 //LdrQueryApplicationCompatibilityGoo(hKey);
2201 DPRINT("Querying app compat hacks is missing!\n");
2205 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2206 * incompatible images.
2209 /* Now call the Init Routines */
2210 Status
= LdrpRunInitializeRoutines(Context
);
2211 if (!NT_SUCCESS(Status
))
2213 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2218 /* Notify Shim Engine */
2221 VOID(NTAPI
*SE_InstallAfterInit
)(PUNICODE_STRING
, PVOID
);
2222 SE_InstallAfterInit
= RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit
);
2223 SE_InstallAfterInit(&ImagePathName
, OldShimData
);
2226 /* Check if we have a user-defined Post Process Routine */
2227 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
2230 Peb
->PostProcessInitRoutine();
2233 /* Close the key if we have one opened */
2234 if (OptionsKey
) NtClose(OptionsKey
);
2242 LdrpInitFailure(NTSTATUS Status
)
2245 PPEB Peb
= NtCurrentPeb();
2247 /* Print a debug message */
2248 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2249 &Peb
->ProcessParameters
->ImagePathName
, Status
);
2251 /* Raise a hard error */
2252 if (!LdrpFatalHardErrorCount
)
2254 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
2260 LdrpInit(PCONTEXT Context
,
2261 PVOID SystemArgument1
,
2262 PVOID SystemArgument2
)
2264 LARGE_INTEGER Timeout
;
2265 PTEB Teb
= NtCurrentTeb();
2266 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
2267 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
2268 PPEB Peb
= NtCurrentPeb();
2270 DPRINT("LdrpInit() %p/%p\n",
2271 NtCurrentTeb()->RealClientId
.UniqueProcess
,
2272 NtCurrentTeb()->RealClientId
.UniqueThread
);
2275 /* Set the SList header usage */
2276 RtlpUse16ByteSLists
= SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE128
];
2279 /* Check if we have a deallocation stack */
2280 if (!Teb
->DeallocationStack
)
2282 /* We don't, set one */
2283 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
2284 Teb
->NtTib
.StackLimit
,
2285 MemoryBasicInformation
,
2287 sizeof(MEMORY_BASIC_INFORMATION
),
2289 if (!NT_SUCCESS(Status
))
2292 LdrpInitFailure(Status
);
2293 RtlRaiseStatus(Status
);
2298 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
2301 /* Now check if the process is already being initialized */
2302 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
2306 /* Set the timeout to 30 milliseconds */
2307 Timeout
.QuadPart
= Int32x32To64(30, -10000);
2309 /* Make sure the status hasn't changed */
2310 while (LdrpProcessInitialized
== 1)
2313 ZwDelayExecution(FALSE
, &Timeout
);
2317 /* Check if we have already setup LDR data */
2320 /* Setup the Loader Lock */
2321 Peb
->LoaderLock
= &LdrpLoaderLock
;
2323 /* Let other code know we're initializing */
2324 LdrpInLdrInit
= TRUE
;
2326 /* Protect with SEH */
2329 /* Initialize the Process */
2330 LoaderStatus
= LdrpInitializeProcess(Context
,
2333 /* Check for success and if MinimumStackCommit was requested */
2334 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
2336 /* Enforce the limit */
2337 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2341 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2343 /* Fail with the SEH error */
2344 LoaderStatus
= _SEH2_GetExceptionCode();
2348 /* We're not initializing anymore */
2349 LdrpInLdrInit
= FALSE
;
2351 /* Check if init worked */
2352 if (NT_SUCCESS(LoaderStatus
))
2354 /* Set the process as Initialized */
2355 _InterlockedIncrement(&LdrpProcessInitialized
);
2360 /* Loader data is there... is this a fork() ? */
2361 if(Peb
->InheritedAddressSpace
)
2363 /* Handle the fork() */
2364 //LoaderStatus = LdrpForkProcess();
2365 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
2370 /* This is a new thread initializing */
2371 LdrpInitializeThread(Context
);
2375 /* All done, test alert the thread */
2379 if (!NT_SUCCESS(LoaderStatus
))
2382 LdrpInitFailure(LoaderStatus
);
2383 RtlRaiseStatus(LoaderStatus
);