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
);
85 extern BOOLEAN RtlpPageHeapEnabled
;
87 ULONG RtlpDisableHeapLookaside
; // TODO: Move to heap.c
88 ULONG RtlpShutdownProcessFlags
; // TODO: Use it
90 NTSTATUS
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
, PVOID ImageBase
);
91 void actctx_init(void);
92 extern BOOLEAN RtlpUse16ByteSLists
;
95 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
97 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E
100 /* FUNCTIONS *****************************************************************/
107 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey
,
109 OUT PHANDLE NewKeyHandle
)
111 PHANDLE RootKeyLocation
;
113 UNICODE_STRING SubKeyString
;
114 OBJECT_ATTRIBUTES ObjectAttributes
;
118 /* Check which root key to open */
120 RootKeyLocation
= &Wow64ExecOptionsKey
;
122 RootKeyLocation
= &ImageExecOptionsKey
;
124 /* Get the current key */
125 RootKey
= *RootKeyLocation
;
127 /* Setup the object attributes */
128 InitializeObjectAttributes(&ObjectAttributes
,
130 &Wow64OptionsString
: &ImageExecOptionsString
,
131 OBJ_CASE_INSENSITIVE
,
135 /* Open the root key */
136 Status
= ZwOpenKey(&RootKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
137 if (NT_SUCCESS(Status
))
139 /* Write the key handle */
140 if (_InterlockedCompareExchange((LONG
*)RootKeyLocation
, (LONG
)RootKey
, 0) != 0)
142 /* Someone already opened it, use it instead */
144 RootKey
= *RootKeyLocation
;
147 /* Extract the name */
148 SubKeyString
= *SubKey
;
149 p1
= (PWCHAR
)((ULONG_PTR
)SubKeyString
.Buffer
+ SubKeyString
.Length
);
150 while (SubKeyString
.Length
)
152 if (p1
[-1] == L
'\\') break;
154 SubKeyString
.Length
-= sizeof(*p1
);
156 SubKeyString
.Buffer
= p1
;
157 SubKeyString
.Length
= SubKey
->Length
- SubKeyString
.Length
;
159 /* Setup the object attributes */
160 InitializeObjectAttributes(&ObjectAttributes
,
162 OBJ_CASE_INSENSITIVE
,
166 /* Open the setting key */
167 Status
= ZwOpenKey((PHANDLE
)NewKeyHandle
, GENERIC_READ
, &ObjectAttributes
);
170 /* Return to caller */
179 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle
,
184 OUT PULONG ReturnedLength OPTIONAL
)
187 UNICODE_STRING ValueNameString
, IntegerString
;
188 ULONG KeyInfoSize
, ResultSize
;
189 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)&KeyInfo
;
190 BOOLEAN FreeHeap
= FALSE
;
193 /* Build a string for the value name */
194 Status
= RtlInitUnicodeStringEx(&ValueNameString
, ValueName
);
195 if (!NT_SUCCESS(Status
)) return Status
;
197 /* Query the value */
198 Status
= ZwQueryValueKey(KeyHandle
,
200 KeyValuePartialInformation
,
204 if (Status
== STATUS_BUFFER_OVERFLOW
)
206 /* Our local buffer wasn't enough, allocate one */
207 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
208 KeyValueInformation
->DataLength
;
209 KeyValueInformation
= RtlAllocateHeap(RtlGetProcessHeap(),
212 if (KeyValueInformation
!= NULL
)
215 Status
= ZwQueryValueKey(KeyHandle
,
217 KeyValuePartialInformation
,
225 /* Give up this time */
226 Status
= STATUS_NO_MEMORY
;
230 /* Check for success */
231 if (NT_SUCCESS(Status
))
233 /* Handle binary data */
234 if (KeyValueInformation
->Type
== REG_BINARY
)
237 if ((Buffer
) && (KeyValueInformation
->DataLength
<= BufferSize
))
239 /* Copy into buffer */
240 RtlMoveMemory(Buffer
,
241 &KeyValueInformation
->Data
,
242 KeyValueInformation
->DataLength
);
246 Status
= STATUS_BUFFER_OVERFLOW
;
249 /* Copy the result length */
250 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
252 else if (KeyValueInformation
->Type
== REG_DWORD
)
254 /* Check for valid type */
255 if (KeyValueInformation
->Type
!= Type
)
258 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
264 (BufferSize
== sizeof(ULONG
)) &&
265 (KeyValueInformation
->DataLength
<= BufferSize
))
267 /* Copy into buffer */
268 RtlMoveMemory(Buffer
,
269 &KeyValueInformation
->Data
,
270 KeyValueInformation
->DataLength
);
274 Status
= STATUS_BUFFER_OVERFLOW
;
277 /* Copy the result length */
278 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
281 else if (KeyValueInformation
->Type
!= REG_SZ
)
283 /* We got something weird */
284 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
288 /* String, check what you requested */
289 if (Type
== REG_DWORD
)
292 if (BufferSize
!= sizeof(ULONG
))
296 Status
= STATUS_INFO_LENGTH_MISMATCH
;
300 /* OK, we know what you want... */
301 IntegerString
.Buffer
= (PWSTR
)KeyValueInformation
->Data
;
302 IntegerString
.Length
= (USHORT
)KeyValueInformation
->DataLength
-
304 IntegerString
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
305 Status
= RtlUnicodeStringToInteger(&IntegerString
, 0, (PULONG
)Buffer
);
311 if (KeyValueInformation
->DataLength
> BufferSize
)
314 Status
= STATUS_BUFFER_OVERFLOW
;
319 BufferSize
= KeyValueInformation
->DataLength
;
322 /* Copy the string */
323 RtlMoveMemory(Buffer
, &KeyValueInformation
->Data
, BufferSize
);
326 /* Copy the result length */
327 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
331 /* Check if buffer was in heap */
332 if (FreeHeap
) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation
);
343 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey
,
348 OUT PULONG ReturnedLength OPTIONAL
,
354 /* Open a handle to the key */
355 Status
= LdrOpenImageFileOptionsKey(SubKey
, Wow64
, &KeyHandle
);
357 /* Check for success */
358 if (NT_SUCCESS(Status
))
361 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
372 /* Return to caller */
381 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey
,
386 OUT PULONG ReturnedLength OPTIONAL
)
388 /* Call the newer function */
389 return LdrQueryImageFileExecutionOptionsEx(SubKey
,
400 LdrpEnsureLoaderLockIsHeld(VOID
)
407 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress
, ULONG SizeOfImage
)
409 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir
;
413 /* Check NT header first */
414 if (!RtlImageNtHeader(BaseAddress
)) return NULL
;
416 /* Get the pointer to the config directory */
417 ConfigDir
= RtlImageDirectoryEntryToData(BaseAddress
,
419 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
422 /* Check for sanity */
424 (DirSize
!= 64 && ConfigDir
->Size
!= DirSize
) ||
425 (ConfigDir
->Size
< 0x48))
428 /* Now get the cookie */
429 Cookie
= (PVOID
)ConfigDir
->SecurityCookie
;
431 /* Check this cookie */
432 if ((PCHAR
)Cookie
<= (PCHAR
)BaseAddress
||
433 (PCHAR
)Cookie
>= (PCHAR
)BaseAddress
+ SizeOfImage
)
438 /* Return validated security cookie */
444 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry
)
447 LARGE_INTEGER Counter
;
450 /* Fetch address of the cookie */
451 Cookie
= LdrpFetchAddressOfSecurityCookie(LdrEntry
->DllBase
, LdrEntry
->SizeOfImage
);
455 /* Check if it's a default one */
456 if ((*Cookie
== DEFAULT_SECURITY_COOKIE
) ||
459 /* Make up a cookie from a bunch of values which may uniquely represent
460 current moment of time, environment, etc */
461 NtQueryPerformanceCounter(&Counter
, NULL
);
463 NewCookie
= Counter
.LowPart
^ Counter
.HighPart
;
464 NewCookie
^= (ULONG
)NtCurrentTeb()->ClientId
.UniqueProcess
;
465 NewCookie
^= (ULONG
)NtCurrentTeb()->ClientId
.UniqueThread
;
467 /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */
468 while (SharedUserData
->SystemTime
.High1Time
!= SharedUserData
->SystemTime
.High2Time
)
473 /* Calculate the milliseconds value and xor it to the cookie */
474 NewCookie
^= Int64ShrlMod32(UInt32x32To64(SharedUserData
->TickCountMultiplier
, SharedUserData
->TickCount
.LowPart
), 24) +
475 (SharedUserData
->TickCountMultiplier
* (SharedUserData
->TickCount
.High1Time
<< 8));
477 /* Make the cookie 16bit if necessary */
478 if (*Cookie
== 0xBB40) NewCookie
&= 0xFFFF;
480 /* If the result is 0 or the same as we got, just subtract one from the existing value
482 if ((NewCookie
== 0) || (NewCookie
== *Cookie
))
484 NewCookie
= *Cookie
- 1;
487 /* Set the new cookie value */
497 LdrpInitializeThread(IN PCONTEXT Context
)
499 PPEB Peb
= NtCurrentPeb();
500 PLDR_DATA_TABLE_ENTRY LdrEntry
;
501 PLIST_ENTRY NextEntry
, ListHead
;
502 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
506 DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n",
507 &LdrpImageEntry
->BaseDllName
,
508 NtCurrentTeb()->RealClientId
.UniqueProcess
,
509 NtCurrentTeb()->RealClientId
.UniqueThread
);
511 /* Allocate an Activation Context Stack */
512 DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer
);
513 Status
= RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer
);
514 if (!NT_SUCCESS(Status
))
516 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
519 /* Make sure we are not shutting down */
520 if (LdrpShutdownInProgress
) return;
525 /* Start at the beginning */
526 ListHead
= &Peb
->Ldr
->InMemoryOrderModuleList
;
527 NextEntry
= ListHead
->Flink
;
528 while (NextEntry
!= ListHead
)
530 /* Get the current entry */
531 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InMemoryOrderLinks
);
533 /* Make sure it's not ourselves */
534 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
536 /* Check if we should call */
537 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
))
539 /* Get the entrypoint */
540 EntryPoint
= LdrEntry
->EntryPoint
;
542 /* Check if we are ready to call it */
544 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
545 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
547 /* Set up the Act Ctx */
548 ActCtx
.Size
= sizeof(ActCtx
);
550 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
552 /* Activate the ActCtx */
553 RtlActivateActivationContextUnsafeFast(&ActCtx
,
554 LdrEntry
->EntryPointActivationContext
);
556 /* Check if it has TLS */
557 if (LdrEntry
->TlsIndex
)
559 /* Make sure we're not shutting down */
560 if (!LdrpShutdownInProgress
)
563 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_THREAD_ATTACH
);
567 /* Make sure we're not shutting down */
568 if (!LdrpShutdownInProgress
)
570 /* Call the Entrypoint */
571 DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n",
572 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
,
573 NtCurrentTeb()->RealClientId
.UniqueProcess
,
574 NtCurrentTeb()->RealClientId
.UniqueThread
);
575 LdrpCallInitRoutine(LdrEntry
->EntryPoint
,
581 /* Deactivate the ActCtx */
582 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
588 NextEntry
= NextEntry
->Flink
;
592 if (LdrpImageHasTls
&& !LdrpShutdownInProgress
)
594 /* Set up the Act Ctx */
595 ActCtx
.Size
= sizeof(ActCtx
);
597 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
599 /* Activate the ActCtx */
600 RtlActivateActivationContextUnsafeFast(&ActCtx
,
601 LdrpImageEntry
->EntryPointActivationContext
);
603 /* Do TLS callbacks */
604 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_THREAD_ATTACH
);
606 /* Deactivate the ActCtx */
607 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
610 DPRINT("LdrpInitializeThread() done\n");
615 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL
)
617 PLDR_DATA_TABLE_ENTRY LocalArray
[16];
618 PLIST_ENTRY ListHead
;
619 PLIST_ENTRY NextEntry
;
620 PLDR_DATA_TABLE_ENTRY LdrEntry
, *LdrRootEntry
, OldInitializer
;
624 NTSTATUS Status
= STATUS_SUCCESS
;
625 PPEB Peb
= NtCurrentPeb();
626 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
627 ULONG BreakOnDllLoad
;
631 DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
632 &LdrpImageEntry
->BaseDllName
,
633 NtCurrentTeb()->RealClientId
.UniqueProcess
,
634 NtCurrentTeb()->RealClientId
.UniqueThread
);
636 /* Check the Loader Lock */
637 LdrpEnsureLoaderLockIsHeld();
639 /* Get the number of entries to call */
640 if ((Count
= LdrpClearLoadInProgress()))
642 /* Check if we can use our local buffer */
645 /* Allocate space for all the entries */
646 LdrRootEntry
= RtlAllocateHeap(RtlGetProcessHeap(),
648 Count
* sizeof(*LdrRootEntry
));
649 if (!LdrRootEntry
) return STATUS_NO_MEMORY
;
653 /* Use our local array */
654 LdrRootEntry
= LocalArray
;
663 /* Show debug message */
666 DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
667 NtCurrentTeb()->RealClientId
.UniqueThread
,
668 NtCurrentTeb()->RealClientId
.UniqueProcess
,
669 &Peb
->ProcessParameters
->ImagePathName
);
673 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
674 NextEntry
= ListHead
->Flink
;
676 while (NextEntry
!= ListHead
)
678 /* Get the Data Entry */
679 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
681 /* Check if we have a Root Entry */
685 if (!(LdrEntry
->Flags
& LDRP_ENTRY_PROCESSED
))
687 /* Setup the Cookie for the DLL */
688 LdrpInitSecurityCookie(LdrEntry
);
690 /* Check for valid entrypoint */
691 if (LdrEntry
->EntryPoint
)
695 LdrRootEntry
[i
] = LdrEntry
;
697 /* Display debug message */
700 DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
701 NtCurrentTeb()->RealClientId
.UniqueThread
,
702 NtCurrentTeb()->RealClientId
.UniqueProcess
,
703 &LdrEntry
->FullDllName
,
704 LdrEntry
->EntryPoint
);
712 LdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
713 NextEntry
= NextEntry
->Flink
;
716 /* If we got a context, then we have to call Kernel32 for TS support */
719 /* Check if we have one */
720 //if (Kernel32ProcessInitPostImportfunction)
723 //Kernel32ProcessInitPostImportfunction();
727 //Kernel32ProcessInitPostImportfunction = NULL;
731 /* No root entry? return */
732 if (!LdrRootEntry
) return STATUS_SUCCESS
;
734 /* Set the TLD TEB */
735 OldTldTeb
= LdrpTopLevelDllBeingLoadedTeb
;
736 LdrpTopLevelDllBeingLoadedTeb
= NtCurrentTeb();
743 LdrEntry
= LdrRootEntry
[i
];
745 /* FIXME: Verify NX Compat */
747 /* Move to next entry */
750 /* Get its entrypoint */
751 EntryPoint
= LdrEntry
->EntryPoint
;
753 /* Are we being debugged? */
755 if (Peb
->BeingDebugged
|| Peb
->ReadImageFileExecOptions
)
757 /* Check if we should break on load */
758 Status
= LdrQueryImageFileExecutionOptions(&LdrEntry
->BaseDllName
,
764 if (!NT_SUCCESS(Status
)) BreakOnDllLoad
= 0;
766 /* Reset status back to STATUS_SUCCESS */
767 Status
= STATUS_SUCCESS
;
773 /* Check if we should show a message */
776 DPRINT1("LDR: %wZ loaded.", &LdrEntry
->BaseDllName
);
777 DPRINT1(" - About to call init routine at %p\n", EntryPoint
);
780 /* Break in debugger */
784 /* Make sure we have an entrypoint */
787 /* Save the old Dll Initializer and write the current one */
788 OldInitializer
= LdrpCurrentDllInitializer
;
789 LdrpCurrentDllInitializer
= LdrEntry
;
791 /* Set up the Act Ctx */
792 ActCtx
.Size
= sizeof(ActCtx
);
794 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
796 /* Activate the ActCtx */
797 RtlActivateActivationContextUnsafeFast(&ActCtx
,
798 LdrEntry
->EntryPointActivationContext
);
800 /* Check if it has TLS */
801 if (LdrEntry
->TlsIndex
&& Context
)
804 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_PROCESS_ATTACH
);
807 /* Call the Entrypoint */
810 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
811 &LdrEntry
->BaseDllName
, EntryPoint
);
813 DllStatus
= LdrpCallInitRoutine(EntryPoint
,
818 /* Deactivate the ActCtx */
819 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
821 /* Save the Current DLL Initializer */
822 LdrpCurrentDllInitializer
= OldInitializer
;
824 /* Mark the entry as processed */
825 LdrEntry
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
;
827 /* Fail if DLL init failed */
830 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
831 &LdrEntry
->BaseDllName
, EntryPoint
);
833 Status
= STATUS_DLL_INIT_FAILED
;
840 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
841 NextEntry
= NextEntry
->Flink
;
842 while (NextEntry
!= ListHead
)
844 /* Get the Data Entry */
845 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
847 /* FIXME: Verify NX Compat */
848 // LdrpCheckNXCompatibility()
851 NextEntry
= NextEntry
->Flink
;
855 if (LdrpImageHasTls
&& Context
)
857 /* Set up the Act Ctx */
858 ActCtx
.Size
= sizeof(ActCtx
);
860 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
862 /* Activate the ActCtx */
863 RtlActivateActivationContextUnsafeFast(&ActCtx
,
864 LdrpImageEntry
->EntryPointActivationContext
);
866 /* Do TLS callbacks */
867 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_PROCESS_ATTACH
);
869 /* Deactivate the ActCtx */
870 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
874 /* Restore old TEB */
875 LdrpTopLevelDllBeingLoadedTeb
= OldTldTeb
;
877 /* Check if the array is in the heap */
878 if (LdrRootEntry
!= LocalArray
)
881 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry
);
884 /* Return to caller */
885 DPRINT("LdrpRunInitializeRoutines() done\n");
894 LdrShutdownProcess(VOID
)
896 PPEB Peb
= NtCurrentPeb();
897 PLDR_DATA_TABLE_ENTRY LdrEntry
;
898 PLIST_ENTRY NextEntry
, ListHead
;
899 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
902 DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry
->BaseDllName
);
903 if (LdrpShutdownInProgress
) return STATUS_SUCCESS
;
905 /* Tell the Shim Engine */
908 VOID(NTAPI
*SE_ProcessDying
)();
909 SE_ProcessDying
= RtlDecodeSystemPointer(g_pfnSE_ProcessDying
);
919 /* Set the shutdown variables */
920 LdrpShutdownThreadId
= NtCurrentTeb()->RealClientId
.UniqueThread
;
921 LdrpShutdownInProgress
= TRUE
;
923 /* Enter the Loader Lock */
924 RtlEnterCriticalSection(&LdrpLoaderLock
);
926 /* Cleanup trace logging data (Etw) */
927 if (SharedUserData
->TraceLogging
)
930 DPRINT1("We don't support Etw yet.\n");
933 /* Start at the end */
934 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
935 NextEntry
= ListHead
->Blink
;
936 while (NextEntry
!= ListHead
)
938 /* Get the current entry */
939 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
940 NextEntry
= NextEntry
->Blink
;
942 /* Make sure it's not ourselves */
943 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
945 /* Get the entrypoint */
946 EntryPoint
= LdrEntry
->EntryPoint
;
948 /* Check if we are ready to call it */
950 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
953 /* Set up the Act Ctx */
954 ActCtx
.Size
= sizeof(ActCtx
);
956 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
958 /* Activate the ActCtx */
959 RtlActivateActivationContextUnsafeFast(&ActCtx
,
960 LdrEntry
->EntryPointActivationContext
);
962 /* Check if it has TLS */
963 if (LdrEntry
->TlsIndex
)
966 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_PROCESS_DETACH
);
969 /* Call the Entrypoint */
970 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
971 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
972 LdrpCallInitRoutine(EntryPoint
,
977 /* Deactivate the ActCtx */
978 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
986 /* Set up the Act Ctx */
987 ActCtx
.Size
= sizeof(ActCtx
);
989 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
991 /* Activate the ActCtx */
992 RtlActivateActivationContextUnsafeFast(&ActCtx
,
993 LdrpImageEntry
->EntryPointActivationContext
);
995 /* Do TLS callbacks */
996 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_PROCESS_DETACH
);
998 /* Deactivate the ActCtx */
999 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1002 /* FIXME: Do Heap detection and Etw final shutdown */
1004 /* Release the lock */
1005 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1006 DPRINT("LdrpShutdownProcess() done\n");
1008 return STATUS_SUCCESS
;
1016 LdrShutdownThread(VOID
)
1018 PPEB Peb
= NtCurrentPeb();
1019 PTEB Teb
= NtCurrentTeb();
1020 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1021 PLIST_ENTRY NextEntry
, ListHead
;
1022 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
1025 DPRINT("LdrShutdownThread() called for %wZ\n",
1026 &LdrpImageEntry
->BaseDllName
);
1028 /* Cleanup trace logging data (Etw) */
1029 if (SharedUserData
->TraceLogging
)
1032 DPRINT1("We don't support Etw yet.\n");
1035 /* Get the Ldr Lock */
1036 RtlEnterCriticalSection(&LdrpLoaderLock
);
1038 /* Start at the end */
1039 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
1040 NextEntry
= ListHead
->Blink
;
1041 while (NextEntry
!= ListHead
)
1043 /* Get the current entry */
1044 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
1045 NextEntry
= NextEntry
->Blink
;
1047 /* Make sure it's not ourselves */
1048 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
1050 /* Check if we should call */
1051 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
1052 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
1053 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
1055 /* Get the entrypoint */
1056 EntryPoint
= LdrEntry
->EntryPoint
;
1058 /* Check if we are ready to call it */
1061 /* Set up the Act Ctx */
1062 ActCtx
.Size
= sizeof(ActCtx
);
1064 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1066 /* Activate the ActCtx */
1067 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1068 LdrEntry
->EntryPointActivationContext
);
1070 /* Check if it has TLS */
1071 if (LdrEntry
->TlsIndex
)
1073 /* Make sure we're not shutting down */
1074 if (!LdrpShutdownInProgress
)
1077 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_THREAD_DETACH
);
1081 /* Make sure we're not shutting down */
1082 if (!LdrpShutdownInProgress
)
1084 /* Call the Entrypoint */
1085 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1086 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1087 LdrpCallInitRoutine(EntryPoint
,
1093 /* Deactivate the ActCtx */
1094 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1101 if (LdrpImageHasTls
)
1103 /* Set up the Act Ctx */
1104 ActCtx
.Size
= sizeof(ActCtx
);
1106 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1108 /* Activate the ActCtx */
1109 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1110 LdrpImageEntry
->EntryPointActivationContext
);
1112 /* Do TLS callbacks */
1113 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_THREAD_DETACH
);
1115 /* Deactivate the ActCtx */
1116 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1121 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1123 /* Check for expansion slots */
1124 if (Teb
->TlsExpansionSlots
)
1126 /* Free expansion slots */
1127 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->TlsExpansionSlots
);
1130 /* Check for FLS Data */
1134 DPRINT1("We don't support FLS Data yet\n");
1137 /* Check for Fiber data */
1138 if (Teb
->HasFiberData
)
1140 /* Free Fiber data*/
1141 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->NtTib
.FiberData
);
1142 Teb
->NtTib
.FiberData
= NULL
;
1145 /* Free the activation context stack */
1146 RtlFreeThreadActivationContextStack();
1147 DPRINT("LdrShutdownThread() done\n");
1149 return STATUS_SUCCESS
;
1154 LdrpInitializeTls(VOID
)
1156 PLIST_ENTRY NextEntry
, ListHead
;
1157 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1158 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1159 PLDRP_TLS_DATA TlsData
;
1162 /* Initialize the TLS List */
1163 InitializeListHead(&LdrpTlsList
);
1165 /* Loop all the modules */
1166 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1167 NextEntry
= ListHead
->Flink
;
1168 while (ListHead
!= NextEntry
)
1171 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1172 NextEntry
= NextEntry
->Flink
;
1174 /* Get the TLS directory */
1175 TlsDirectory
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
1177 IMAGE_DIRECTORY_ENTRY_TLS
,
1180 /* Check if we have a directory */
1181 if (!TlsDirectory
) continue;
1183 /* Check if the image has TLS */
1184 if (!LdrpImageHasTls
) LdrpImageHasTls
= TRUE
;
1186 /* Show debug message */
1189 DPRINT1("LDR: Tls Found in %wZ at %p\n",
1190 &LdrEntry
->BaseDllName
,
1194 /* Allocate an entry */
1195 TlsData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA
));
1196 if (!TlsData
) return STATUS_NO_MEMORY
;
1198 /* Lock the DLL and mark it for TLS Usage */
1199 LdrEntry
->LoadCount
= -1;
1200 LdrEntry
->TlsIndex
= -1;
1202 /* Save the cached TLS data */
1203 TlsData
->TlsDirectory
= *TlsDirectory
;
1204 InsertTailList(&LdrpTlsList
, &TlsData
->TlsLinks
);
1206 /* Update the index */
1207 *(PLONG
)TlsData
->TlsDirectory
.AddressOfIndex
= LdrpNumberOfTlsEntries
;
1208 TlsData
->TlsDirectory
.Characteristics
= LdrpNumberOfTlsEntries
++;
1211 /* Done setting up TLS, allocate entries */
1212 return LdrpAllocateTls();
1217 LdrpAllocateTls(VOID
)
1219 PTEB Teb
= NtCurrentTeb();
1220 PLIST_ENTRY NextEntry
, ListHead
;
1221 PLDRP_TLS_DATA TlsData
;
1225 /* Check if we have any entries */
1226 if (!LdrpNumberOfTlsEntries
)
1227 return STATUS_SUCCESS
;
1229 /* Allocate the vector array */
1230 TlsVector
= RtlAllocateHeap(RtlGetProcessHeap(),
1232 LdrpNumberOfTlsEntries
* sizeof(PVOID
));
1233 if (!TlsVector
) return STATUS_NO_MEMORY
;
1234 Teb
->ThreadLocalStoragePointer
= TlsVector
;
1236 /* Loop the TLS Array */
1237 ListHead
= &LdrpTlsList
;
1238 NextEntry
= ListHead
->Flink
;
1239 while (NextEntry
!= ListHead
)
1242 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1243 NextEntry
= NextEntry
->Flink
;
1245 /* Allocate this vector */
1246 TlsDataSize
= TlsData
->TlsDirectory
.EndAddressOfRawData
-
1247 TlsData
->TlsDirectory
.StartAddressOfRawData
;
1248 TlsVector
[TlsData
->TlsDirectory
.Characteristics
] = RtlAllocateHeap(RtlGetProcessHeap(),
1251 if (!TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1254 return STATUS_NO_MEMORY
;
1257 /* Show debug message */
1260 DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
1262 TlsData
->TlsDirectory
.Characteristics
,
1263 &TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1264 TlsData
->TlsDirectory
.StartAddressOfRawData
,
1265 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1269 RtlCopyMemory(TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1270 (PVOID
)TlsData
->TlsDirectory
.StartAddressOfRawData
,
1275 return STATUS_SUCCESS
;
1282 PLIST_ENTRY ListHead
, NextEntry
;
1283 PLDRP_TLS_DATA TlsData
;
1285 PTEB Teb
= NtCurrentTeb();
1287 /* Get a pointer to the vector array */
1288 TlsVector
= Teb
->ThreadLocalStoragePointer
;
1289 if (!TlsVector
) return;
1291 /* Loop through it */
1292 ListHead
= &LdrpTlsList
;
1293 NextEntry
= ListHead
->Flink
;
1294 while (NextEntry
!= ListHead
)
1296 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1297 NextEntry
= NextEntry
->Flink
;
1299 /* Free each entry */
1300 if (TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1302 RtlFreeHeap(RtlGetProcessHeap(),
1304 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1308 /* Free the array itself */
1309 RtlFreeHeap(RtlGetProcessHeap(),
1316 LdrpInitializeApplicationVerifierPackage(PUNICODE_STRING ImagePathName
, PPEB Peb
, BOOLEAN SystemWide
, BOOLEAN ReadAdvancedOptions
)
1318 /* If global flags request DPH, perform some additional actions */
1319 if (Peb
->NtGlobalFlag
& FLG_HEAP_PAGE_ALLOCS
)
1321 // TODO: Read advanced DPH flags from the registry if requested
1322 if (ReadAdvancedOptions
)
1327 /* Enable page heap */
1328 RtlpPageHeapEnabled
= TRUE
;
1331 return STATUS_SUCCESS
;
1336 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName
, PPEB Peb
, PHANDLE OptionsKey
)
1340 ULONG ExecuteOptions
, MinimumStackCommit
= 0, GlobalFlag
;
1342 /* Return error if we were not provided a pointer where to save the options key handle */
1343 if (!OptionsKey
) return STATUS_INVALID_HANDLE
;
1345 /* Zero initialize the options key pointer */
1348 /* Open the options key */
1349 Status
= LdrOpenImageFileOptionsKey(ImagePathName
, 0, &KeyHandle
);
1351 /* Save it if it was opened successfully */
1352 if (NT_SUCCESS(Status
))
1353 *OptionsKey
= KeyHandle
;
1357 /* There are image specific options, read them starting with NXCOMPAT */
1358 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1362 sizeof(ExecuteOptions
),
1365 if (NT_SUCCESS(Status
))
1367 /* TODO: Set execution options for the process */
1369 if (ExecuteOptions == 0)
1373 ZwSetInformationProcess(NtCurrentProcess(),
1374 ProcessExecuteFlags,
1380 /* Check if this image uses large pages */
1381 if (Peb
->ImageUsesLargePages
)
1383 /* TODO: If it does, open large page key */
1387 /* Get various option values */
1388 LdrQueryImageFileKeyOption(KeyHandle
,
1389 L
"DisableHeapLookaside",
1391 &RtlpDisableHeapLookaside
,
1392 sizeof(RtlpDisableHeapLookaside
),
1395 LdrQueryImageFileKeyOption(KeyHandle
,
1398 &RtlpShutdownProcessFlags
,
1399 sizeof(RtlpShutdownProcessFlags
),
1402 LdrQueryImageFileKeyOption(KeyHandle
,
1403 L
"MinimumStackCommitInBytes",
1405 &MinimumStackCommit
,
1406 sizeof(MinimumStackCommit
),
1409 /* Update PEB's minimum stack commit if it's lower */
1410 if (Peb
->MinimumStackCommit
< MinimumStackCommit
)
1411 Peb
->MinimumStackCommit
= MinimumStackCommit
;
1413 /* Set the global flag */
1414 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1421 if (NT_SUCCESS(Status
))
1422 Peb
->NtGlobalFlag
= GlobalFlag
;
1426 /* Call AVRF if necessary */
1427 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1429 Status
= LdrpInitializeApplicationVerifierPackage(ImagePathName
, Peb
, TRUE
, FALSE
);
1430 if (!NT_SUCCESS(Status
))
1432 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1438 /* There are no image-specific options, so perform global initialization */
1439 if (Peb
->NtGlobalFlag
& (FLG_APPLICATION_VERIFIER
| FLG_HEAP_PAGE_ALLOCS
))
1441 /* Initialize app verifier package */
1442 Status
= LdrpInitializeApplicationVerifierPackage(ImagePathName
, Peb
, TRUE
, FALSE
);
1443 if (!NT_SUCCESS(Status
))
1445 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1450 return STATUS_SUCCESS
;
1455 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
)
1462 LdrpInitializeProcessCompat(PVOID
* pOldShimData
)
1464 static const GUID
* GuidOrder
[] = { &COMPAT_GUID_WIN10
, &COMPAT_GUID_WIN81
, &COMPAT_GUID_WIN8
,
1465 &COMPAT_GUID_WIN7
, &COMPAT_GUID_VISTA
};
1466 static const DWORD GuidVersions
[] = { WINVER_WIN10
, WINVER_WIN81
, WINVER_WIN8
, WINVER_WIN7
, WINVER_VISTA
};
1468 ULONG Buffer
[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
)) / sizeof(ULONG
)];
1469 ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
* ContextCompatInfo
;
1470 SIZE_T SizeRequired
;
1473 ReactOS_ShimData
* pShimData
= *pOldShimData
;
1475 C_ASSERT(RTL_NUMBER_OF(GuidOrder
) == RTL_NUMBER_OF(GuidVersions
));
1479 if (pShimData
->dwMagic
!= REACTOS_SHIMDATA_MAGIC
||
1480 pShimData
->dwSize
!= sizeof(ReactOS_ShimData
))
1482 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData
->dwMagic
, pShimData
->dwSize
);
1485 if (pShimData
->dwRosProcessCompatVersion
)
1487 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData
->dwRosProcessCompatVersion
);
1492 SizeRequired
= sizeof(Buffer
);
1493 Status
= RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
,
1496 CompatibilityInformationInActivationContext
,
1501 if (!NT_SUCCESS(Status
))
1503 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status
);
1507 ContextCompatInfo
= (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION
*)Buffer
;
1508 /* No Compatibility elements present, bail out */
1509 if (ContextCompatInfo
->ElementCount
== 0)
1512 /* Search for known GUID's, starting from newest to oldest. */
1513 for (cur
= 0; cur
< RTL_NUMBER_OF(GuidOrder
); ++cur
)
1515 for (n
= 0; n
< ContextCompatInfo
->ElementCount
; ++n
)
1517 if (ContextCompatInfo
->Elements
[n
].Type
== ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
&&
1518 RtlCompareMemory(&ContextCompatInfo
->Elements
[n
].Id
, GuidOrder
[cur
], sizeof(GUID
)) == sizeof(GUID
))
1520 /* If this process did not need shim data before, allocate and store it */
1521 if (pShimData
== NULL
)
1523 PPEB Peb
= NtCurrentPeb();
1525 ASSERT(Peb
->pShimData
== NULL
);
1526 pShimData
= RtlAllocateHeap(Peb
->ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(*pShimData
));
1530 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData
));
1534 pShimData
->dwSize
= sizeof(*pShimData
);
1535 pShimData
->dwMagic
= REACTOS_SHIMDATA_MAGIC
;
1537 Peb
->pShimData
= pShimData
;
1538 *pOldShimData
= pShimData
;
1541 /* Store the highest found version, and bail out. */
1542 pShimData
->dwRosProcessCompatVersion
= GuidVersions
[cur
];
1543 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", GuidVersions
[cur
]);
1553 LdrpInitializeProcess(IN PCONTEXT Context
,
1554 IN PVOID SystemArgument1
)
1556 RTL_HEAP_PARAMETERS HeapParameters
;
1557 ULONG ComSectionSize
;
1558 //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData");
1560 OBJECT_ATTRIBUTES ObjectAttributes
;
1561 //UNICODE_STRING LocalFileName, FullImageName;
1562 HANDLE SymLinkHandle
;
1563 //ULONG DebugHeapOnly;
1564 UNICODE_STRING CommandLine
, NtSystemRoot
, ImagePathName
, FullPath
, ImageFileName
, KnownDllString
;
1565 PPEB Peb
= NtCurrentPeb();
1566 BOOLEAN IsDotNetImage
= FALSE
;
1567 BOOLEAN FreeCurDir
= FALSE
;
1569 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1570 //LPWSTR ImagePathBuffer;
1572 UNICODE_STRING CurrentDirectory
;
1575 PIMAGE_NT_HEADERS NtHeader
;
1576 LPWSTR NtDllName
= NULL
;
1577 NTSTATUS Status
, ImportStatus
;
1578 NLSTABLEINFO NlsTable
;
1579 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig
;
1580 PTEB Teb
= NtCurrentTeb();
1581 PLIST_ENTRY ListHead
;
1582 PLIST_ENTRY NextEntry
;
1585 ULONG DebugProcessHeapOnly
= 0;
1586 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
1588 ULONG ExecuteOptions
= 0;
1591 /* Set a NULL SEH Filter */
1592 RtlSetUnhandledExceptionFilter(NULL
);
1594 /* Get the image path */
1595 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
1597 /* Check if it's not normalized */
1598 if (!(Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
))
1601 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
1604 /* Create a unicode string for the Image Path */
1605 ImagePathName
.Length
= Peb
->ProcessParameters
->ImagePathName
.Length
;
1606 ImagePathName
.MaximumLength
= ImagePathName
.Length
+ sizeof(WCHAR
);
1607 ImagePathName
.Buffer
= ImagePath
;
1609 /* Get the NT Headers */
1610 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
1612 /* Get the execution options */
1613 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &OptionsKey
);
1615 /* Check if this is a .NET executable */
1616 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1618 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
1621 /* Remember this for later */
1622 IsDotNetImage
= TRUE
;
1625 /* Save the NTDLL Base address */
1626 NtDllBase
= SystemArgument1
;
1628 /* If this is a Native Image */
1629 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
1631 /* Then do DLL Validation */
1632 LdrpDllValidation
= TRUE
;
1635 /* Save the old Shim Data */
1636 OldShimData
= Peb
->pShimData
;
1638 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */
1639 //Peb->pShimData = NULL;
1641 /* Save the number of processors and CS Timeout */
1642 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
1643 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
1645 /* Normalize the parameters */
1646 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
1647 if (ProcessParameters
)
1649 /* Save the Image and Command Line Names */
1650 ImageFileName
= ProcessParameters
->ImagePathName
;
1651 CommandLine
= ProcessParameters
->CommandLine
;
1655 /* It failed, initialize empty strings */
1656 RtlInitUnicodeString(&ImageFileName
, NULL
);
1657 RtlInitUnicodeString(&CommandLine
, NULL
);
1660 /* Initialize NLS data */
1661 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1662 Peb
->OemCodePageData
,
1663 Peb
->UnicodeCaseTableData
,
1666 /* Reset NLS Translations */
1667 RtlResetRtlTranslations(&NlsTable
);
1669 /* Get the Image Config Directory */
1670 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1672 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1675 /* Setup the Heap Parameters */
1676 RtlZeroMemory(&HeapParameters
, sizeof(RTL_HEAP_PARAMETERS
));
1677 HeapFlags
= HEAP_GROWABLE
;
1678 HeapParameters
.Length
= sizeof(RTL_HEAP_PARAMETERS
);
1680 /* Check if we have Configuration Data */
1681 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1683 /* FIXME: Custom heap settings and misc. */
1684 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1687 /* Check for custom affinity mask */
1688 if (Peb
->ImageProcessAffinityMask
)
1691 Status
= NtSetInformationProcess(NtCurrentProcess(),
1692 ProcessAffinityMask
,
1693 &Peb
->ImageProcessAffinityMask
,
1694 sizeof(Peb
->ImageProcessAffinityMask
));
1697 /* Check if verbose debugging (ShowSnaps) was requested */
1698 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1700 /* Start verbose debugging messages right now if they were requested */
1703 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1704 Teb
->ClientId
.UniqueProcess
,
1708 /* If the timeout is too long */
1709 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1711 /* Then disable CS Timeout */
1712 RtlpTimeoutDisable
= TRUE
;
1715 /* Initialize Critical Section Data */
1716 RtlpInitDeferedCriticalSection();
1718 /* Initialize VEH Call lists */
1719 RtlpInitializeVectoredExceptionHandling();
1721 /* Set TLS/FLS Bitmap data */
1722 Peb
->FlsBitmap
= &FlsBitMap
;
1723 Peb
->TlsBitmap
= &TlsBitMap
;
1724 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1726 /* Initialize FLS Bitmap */
1727 RtlInitializeBitMap(&FlsBitMap
,
1729 FLS_MAXIMUM_AVAILABLE
);
1730 RtlSetBit(&FlsBitMap
, 0);
1732 /* Initialize TLS Bitmap */
1733 RtlInitializeBitMap(&TlsBitMap
,
1735 TLS_MINIMUM_AVAILABLE
);
1736 RtlSetBit(&TlsBitMap
, 0);
1737 RtlInitializeBitMap(&TlsExpansionBitMap
,
1738 Peb
->TlsExpansionBitmapBits
,
1739 TLS_EXPANSION_SLOTS
);
1740 RtlSetBit(&TlsExpansionBitMap
, 0);
1742 /* Initialize the Hash Table */
1743 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1745 InitializeListHead(&LdrpHashTable
[i
]);
1748 /* Initialize the Loader Lock */
1749 // FIXME: What's the point of initing it manually, if two lines lower
1750 // a call to RtlInitializeCriticalSection() is being made anyway?
1751 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1752 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1753 RtlInitializeCriticalSection(&LdrpLoaderLock
);
1754 LdrpLoaderLockInit
= TRUE
;
1756 /* Check if User Stack Trace Database support was requested */
1757 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1759 DPRINT1("We don't support user stack trace databases yet\n");
1762 /* Setup Fast PEB Lock */
1763 RtlInitializeCriticalSection(&FastPebLock
);
1764 Peb
->FastPebLock
= &FastPebLock
;
1765 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1766 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1768 /* Setup Callout Lock and Notification list */
1769 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1770 InitializeListHead(&LdrpDllNotificationList
);
1772 /* For old executables, use 16-byte aligned heap */
1773 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1774 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1776 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1779 /* Setup the Heap */
1780 RtlInitializeHeapManager();
1781 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1783 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1784 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1788 if (!Peb
->ProcessHeap
)
1790 DPRINT1("Failed to create process heap\n");
1791 return STATUS_NO_MEMORY
;
1794 /* Allocate an Activation Context Stack */
1795 Status
= RtlAllocateActivationContextStack(&Teb
->ActivationContextStackPointer
);
1796 if (!NT_SUCCESS(Status
)) return Status
;
1798 // FIXME: Loader private heap is missing
1799 //DPRINT1("Loader private heap is missing\n");
1801 /* Check for Debug Heap */
1804 /* Query the setting */
1805 Status
= LdrQueryImageFileKeyOption(OptionsKey
,
1806 L
"DebugProcessHeapOnly",
1808 &DebugProcessHeapOnly
,
1812 if (NT_SUCCESS(Status
))
1814 /* Reset DPH if requested */
1815 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1817 RtlpDphGlobalFlags
&= ~DPH_FLAG_DLL_NOTIFY
;
1818 RtlpPageHeapEnabled
= FALSE
;
1823 /* Build the NTDLL Path */
1824 FullPath
.Buffer
= StringBuffer
;
1825 FullPath
.Length
= 0;
1826 FullPath
.MaximumLength
= sizeof(StringBuffer
);
1827 RtlInitUnicodeString(&NtSystemRoot
, SharedUserData
->NtSystemRoot
);
1828 RtlAppendUnicodeStringToString(&FullPath
, &NtSystemRoot
);
1829 RtlAppendUnicodeToString(&FullPath
, L
"\\System32\\");
1831 /* Open the Known DLLs directory */
1832 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1833 InitializeObjectAttributes(&ObjectAttributes
,
1835 OBJ_CASE_INSENSITIVE
,
1838 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
1839 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
1842 /* Check if it exists */
1843 if (NT_SUCCESS(Status
))
1845 /* Open the Known DLLs Path */
1846 RtlInitUnicodeString(&KnownDllString
, L
"KnownDllPath");
1847 InitializeObjectAttributes(&ObjectAttributes
,
1849 OBJ_CASE_INSENSITIVE
,
1850 LdrpKnownDllObjectDirectory
,
1852 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
1853 SYMBOLIC_LINK_QUERY
,
1855 if (NT_SUCCESS(Status
))
1857 /* Query the path */
1858 LdrpKnownDllPath
.Length
= 0;
1859 LdrpKnownDllPath
.MaximumLength
= sizeof(LdrpKnownDllPathBuffer
);
1860 LdrpKnownDllPath
.Buffer
= LdrpKnownDllPathBuffer
;
1861 Status
= ZwQuerySymbolicLinkObject(SymLinkHandle
, &LdrpKnownDllPath
, NULL
);
1862 NtClose(SymLinkHandle
);
1863 if (!NT_SUCCESS(Status
))
1865 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
1871 /* Check if we failed */
1872 if (!NT_SUCCESS(Status
))
1874 /* Assume System32 */
1875 LdrpKnownDllObjectDirectory
= NULL
;
1876 RtlInitUnicodeString(&LdrpKnownDllPath
, StringBuffer
);
1877 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
1880 /* If we have process parameters, get the default path and current path */
1881 if (ProcessParameters
)
1883 /* Check if we have a Dll Path */
1884 if (ProcessParameters
->DllPath
.Length
)
1887 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
1891 /* We need a valid path */
1892 DPRINT1("No valid DllPath was given!\n");
1893 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
1896 /* Set the current directory */
1897 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
1899 /* Check if it's empty or invalid */
1900 if ((!CurrentDirectory
.Buffer
) ||
1901 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
1902 (!CurrentDirectory
.Length
))
1904 /* Allocate space for the buffer */
1905 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
1908 sizeof(UNICODE_NULL
));
1909 if (!CurrentDirectory
.Buffer
)
1911 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
1915 /* Copy the drive of the system root */
1916 RtlMoveMemory(CurrentDirectory
.Buffer
,
1917 SharedUserData
->NtSystemRoot
,
1919 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
1920 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
1921 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
1924 DPRINT("Using dynamically allocd curdir\n");
1928 /* Use the local buffer */
1929 DPRINT("Using local system root\n");
1933 /* Setup Loader Data */
1935 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
1936 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
1937 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
1938 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
1939 PebLdr
.Initialized
= TRUE
;
1941 /* Allocate a data entry for the Image */
1942 LdrpImageEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
1945 LdrpImageEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(LdrpImageEntry
->DllBase
);
1946 LdrpImageEntry
->LoadCount
= -1;
1947 LdrpImageEntry
->EntryPointActivationContext
= 0;
1948 LdrpImageEntry
->FullDllName
= ImageFileName
;
1951 LdrpImageEntry
->Flags
= LDRP_COR_IMAGE
;
1953 LdrpImageEntry
->Flags
= 0;
1955 /* Check if the name is empty */
1956 if (!ImageFileName
.Buffer
[0])
1958 /* Use the same Base name */
1959 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
1963 /* Find the last slash */
1964 Current
= ImageFileName
.Buffer
;
1967 if (*Current
++ == '\\')
1970 NtDllName
= Current
;
1974 /* Did we find anything? */
1977 /* Use the same Base name */
1978 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
1982 /* Setup the name */
1983 LdrpImageEntry
->BaseDllName
.Length
= (USHORT
)((ULONG_PTR
)ImageFileName
.Buffer
+ ImageFileName
.Length
- (ULONG_PTR
)NtDllName
);
1984 LdrpImageEntry
->BaseDllName
.MaximumLength
= LdrpImageEntry
->BaseDllName
.Length
+ sizeof(WCHAR
);
1985 LdrpImageEntry
->BaseDllName
.Buffer
= (PWSTR
)((ULONG_PTR
)ImageFileName
.Buffer
+
1986 (ImageFileName
.Length
- LdrpImageEntry
->BaseDllName
.Length
));
1990 /* Processing done, insert it */
1991 LdrpInsertMemoryTableEntry(LdrpImageEntry
);
1992 LdrpImageEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
1994 /* Now add an entry for NTDLL */
1995 NtLdrEntry
= LdrpAllocateDataTableEntry(SystemArgument1
);
1996 NtLdrEntry
->Flags
= LDRP_IMAGE_DLL
;
1997 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
1998 NtLdrEntry
->LoadCount
= -1;
1999 NtLdrEntry
->EntryPointActivationContext
= 0;
2001 NtLdrEntry
->FullDllName
.Length
= FullPath
.Length
;
2002 NtLdrEntry
->FullDllName
.MaximumLength
= FullPath
.MaximumLength
;
2003 NtLdrEntry
->FullDllName
.Buffer
= StringBuffer
;
2004 RtlAppendUnicodeStringToString(&NtLdrEntry
->FullDllName
, &NtDllString
);
2006 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
2007 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
2008 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
2010 /* Processing done, insert it */
2011 LdrpNtDllDataTableEntry
= NtLdrEntry
;
2012 LdrpInsertMemoryTableEntry(NtLdrEntry
);
2014 /* Let the world know */
2017 DPRINT1("LDR: NEW PROCESS\n");
2018 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry
->FullDllName
, &LdrpImageEntry
->BaseDllName
);
2019 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory
);
2020 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath
);
2023 /* Link the Init Order List */
2024 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
2025 &LdrpNtDllDataTableEntry
->InInitializationOrderLinks
);
2027 /* Initialize Wine's active context implementation for the current process */
2030 /* ReactOS specific */
2031 LdrpInitializeProcessCompat(&OldShimData
);
2033 /* Set the current directory */
2034 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
2035 if (!NT_SUCCESS(Status
))
2037 /* We failed, check if we should free it */
2038 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2040 /* Set it to the NT Root */
2041 CurrentDirectory
= NtSystemRoot
;
2042 RtlSetCurrentDirectory_U(&CurrentDirectory
);
2046 /* We're done with it, free it */
2047 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
2050 /* Check if we should look for a .local file */
2051 if (ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
)
2054 DPRINT1("We don't support .local overrides yet\n");
2057 /* Check if the Application Verifier was enabled */
2058 if (Peb
->NtGlobalFlag
& FLG_APPLICATION_VERIFIER
)
2061 DPRINT1("We don't support Application Verifier yet\n");
2067 DPRINT1("We don't support .NET applications yet\n");
2070 /* FIXME: Load support for Terminal Services */
2071 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
)
2073 /* Load kernel32 and call BasePostImportInit... */
2074 DPRINT("Unimplemented codepath!\n");
2077 /* Walk the IAT and load all the DLLs */
2078 ImportStatus
= LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
2080 /* Check if relocation is needed */
2081 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
2083 DPRINT1("LDR: Performing EXE relocation\n");
2085 /* Change the protection to prepare for relocation */
2086 ViewBase
= Peb
->ImageBaseAddress
;
2087 Status
= LdrpSetProtection(ViewBase
, FALSE
);
2088 if (!NT_SUCCESS(Status
)) return Status
;
2090 /* Do the relocation */
2091 Status
= LdrRelocateImageWithBias(ViewBase
,
2095 STATUS_CONFLICTING_ADDRESSES
,
2096 STATUS_INVALID_IMAGE_FORMAT
);
2097 if (!NT_SUCCESS(Status
))
2099 DPRINT1("LdrRelocateImageWithBias() failed\n");
2103 /* Check if a start context was provided */
2106 DPRINT1("WARNING: Relocated EXE Context");
2107 UNIMPLEMENTED
; // We should support this
2108 return STATUS_INVALID_IMAGE_FORMAT
;
2111 /* Restore the protection */
2112 Status
= LdrpSetProtection(ViewBase
, TRUE
);
2113 if (!NT_SUCCESS(Status
)) return Status
;
2117 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
2118 NextEntry
= ListHead
->Flink
;
2119 while (ListHead
!= NextEntry
)
2121 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2122 NtLdrEntry
->LoadCount
= -1;
2123 NextEntry
= NextEntry
->Flink
;
2126 /* Phase 0 is done */
2127 LdrpLdrDatabaseIsSetup
= TRUE
;
2129 /* Check whether all static imports were properly loaded and return here */
2130 if (!NT_SUCCESS(ImportStatus
)) return ImportStatus
;
2132 /* Initialize TLS */
2133 Status
= LdrpInitializeTls();
2134 if (!NT_SUCCESS(Status
))
2136 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2141 /* FIXME Mark the DLL Ranges for Stack Traces later */
2143 /* Notify the debugger now */
2144 if (Peb
->BeingDebugged
)
2149 /* Update show snaps again */
2150 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
2153 /* Validate the Image for MP Usage */
2154 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
2156 /* Check NX Options */
2157 if (SharedUserData
->NXSupportPolicy
== 1)
2159 ExecuteOptions
= 0xD;
2161 else if (!SharedUserData
->NXSupportPolicy
)
2163 ExecuteOptions
= 0xA;
2167 ZwSetInformationProcess(NtCurrentProcess(),
2168 ProcessExecuteFlags
,
2172 // FIXME: Should be done by Application Compatibility features,
2173 // by reading the registry, etc...
2174 // For now, this is the old code from ntdll!RtlGetVersion().
2175 RtlInitEmptyUnicodeString(&Peb
->CSDVersion
, NULL
, 0);
2176 if (((Peb
->OSCSDVersion
>> 8) & 0xFF) != 0)
2178 WCHAR szCSDVersion
[128];
2180 ULONG Length
= ARRAYSIZE(szCSDVersion
) - 1;
2181 i
= _snwprintf(szCSDVersion
, Length
,
2183 ((Peb
->OSCSDVersion
>> 8) & 0xFF));
2186 /* Null-terminate if it was overflowed */
2187 szCSDVersion
[Length
] = UNICODE_NULL
;
2190 Length
*= sizeof(WCHAR
);
2191 Peb
->CSDVersion
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
2193 Length
+ sizeof(UNICODE_NULL
));
2194 if (Peb
->CSDVersion
.Buffer
)
2196 Peb
->CSDVersion
.Length
= Length
;
2197 Peb
->CSDVersion
.MaximumLength
= Length
+ sizeof(UNICODE_NULL
);
2199 RtlCopyMemory(Peb
->CSDVersion
.Buffer
,
2201 Peb
->CSDVersion
.MaximumLength
);
2202 Peb
->CSDVersion
.Buffer
[Peb
->CSDVersion
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2206 /* Check if we had Shim Data */
2209 /* Load the Shim Engine */
2210 Peb
->AppCompatInfo
= NULL
;
2211 LdrpLoadShimEngine(OldShimData
, &ImagePathName
, OldShimData
);
2215 /* Check for Application Compatibility Goo */
2216 //LdrQueryApplicationCompatibilityGoo(hKey);
2217 DPRINT("Querying app compat hacks is missing!\n");
2221 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2222 * incompatible images.
2225 /* Now call the Init Routines */
2226 Status
= LdrpRunInitializeRoutines(Context
);
2227 if (!NT_SUCCESS(Status
))
2229 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2234 /* Notify Shim Engine */
2237 VOID(NTAPI
*SE_InstallAfterInit
)(PUNICODE_STRING
, PVOID
);
2238 SE_InstallAfterInit
= RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit
);
2239 SE_InstallAfterInit(&ImagePathName
, OldShimData
);
2242 /* Check if we have a user-defined Post Process Routine */
2243 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
2246 Peb
->PostProcessInitRoutine();
2249 /* Close the key if we have one opened */
2250 if (OptionsKey
) NtClose(OptionsKey
);
2258 LdrpInitFailure(NTSTATUS Status
)
2261 PPEB Peb
= NtCurrentPeb();
2263 /* Print a debug message */
2264 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2265 &Peb
->ProcessParameters
->ImagePathName
, Status
);
2267 /* Raise a hard error */
2268 if (!LdrpFatalHardErrorCount
)
2270 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
2276 LdrpInit(PCONTEXT Context
,
2277 PVOID SystemArgument1
,
2278 PVOID SystemArgument2
)
2280 LARGE_INTEGER Timeout
;
2281 PTEB Teb
= NtCurrentTeb();
2282 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
2283 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
2284 PPEB Peb
= NtCurrentPeb();
2286 DPRINT("LdrpInit() %p/%p\n",
2287 NtCurrentTeb()->RealClientId
.UniqueProcess
,
2288 NtCurrentTeb()->RealClientId
.UniqueThread
);
2291 /* Set the SList header usage */
2292 RtlpUse16ByteSLists
= SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE128
];
2295 /* Check if we have a deallocation stack */
2296 if (!Teb
->DeallocationStack
)
2298 /* We don't, set one */
2299 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
2300 Teb
->NtTib
.StackLimit
,
2301 MemoryBasicInformation
,
2303 sizeof(MEMORY_BASIC_INFORMATION
),
2305 if (!NT_SUCCESS(Status
))
2308 LdrpInitFailure(Status
);
2309 RtlRaiseStatus(Status
);
2314 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
2317 /* Now check if the process is already being initialized */
2318 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
2322 /* Set the timeout to 30 milliseconds */
2323 Timeout
.QuadPart
= Int32x32To64(30, -10000);
2325 /* Make sure the status hasn't changed */
2326 while (LdrpProcessInitialized
== 1)
2329 ZwDelayExecution(FALSE
, &Timeout
);
2333 /* Check if we have already setup LDR data */
2336 /* Setup the Loader Lock */
2337 Peb
->LoaderLock
= &LdrpLoaderLock
;
2339 /* Let other code know we're initializing */
2340 LdrpInLdrInit
= TRUE
;
2342 /* Protect with SEH */
2345 /* Initialize the Process */
2346 LoaderStatus
= LdrpInitializeProcess(Context
,
2349 /* Check for success and if MinimumStackCommit was requested */
2350 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
2352 /* Enforce the limit */
2353 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2357 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2359 /* Fail with the SEH error */
2360 LoaderStatus
= _SEH2_GetExceptionCode();
2364 /* We're not initializing anymore */
2365 LdrpInLdrInit
= FALSE
;
2367 /* Check if init worked */
2368 if (NT_SUCCESS(LoaderStatus
))
2370 /* Set the process as Initialized */
2371 _InterlockedIncrement(&LdrpProcessInitialized
);
2376 /* Loader data is there... is this a fork() ? */
2377 if(Peb
->InheritedAddressSpace
)
2379 /* Handle the fork() */
2380 //LoaderStatus = LdrpForkProcess();
2381 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
2386 /* This is a new thread initializing */
2387 LdrpInitializeThread(Context
);
2391 /* All done, test alert the thread */
2395 if (!NT_SUCCESS(LoaderStatus
))
2398 LdrpInitFailure(LoaderStatus
);
2399 RtlRaiseStatus(LoaderStatus
);