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 *****************************************************************/
18 /* GLOBALS *******************************************************************/
20 HANDLE ImageExecOptionsKey
;
21 HANDLE Wow64ExecOptionsKey
;
22 UNICODE_STRING ImageExecOptionsString
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options");
23 UNICODE_STRING Wow64OptionsString
= RTL_CONSTANT_STRING(L
"");
24 UNICODE_STRING NtDllString
= RTL_CONSTANT_STRING(L
"ntdll.dll");
26 BOOLEAN LdrpInLdrInit
;
27 LONG LdrpProcessInitialized
;
28 BOOLEAN LdrpLoaderLockInit
;
29 BOOLEAN LdrpLdrDatabaseIsSetup
;
30 BOOLEAN LdrpShutdownInProgress
;
31 HANDLE LdrpShutdownThreadId
;
33 BOOLEAN LdrpDllValidation
;
35 PLDR_DATA_TABLE_ENTRY LdrpImageEntry
;
36 PUNICODE_STRING LdrpTopLevelDllBeingLoaded
;
37 WCHAR StringBuffer
[156];
38 extern PTEB LdrpTopLevelDllBeingLoadedTeb
; // defined in rtlsupp.c!
39 PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer
;
40 PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry
;
43 RTL_BITMAP TlsExpansionBitMap
;
45 BOOLEAN LdrpImageHasTls
;
46 LIST_ENTRY LdrpTlsList
;
47 ULONG LdrpNumberOfTlsEntries
;
48 ULONG LdrpNumberOfProcessors
;
50 extern LARGE_INTEGER RtlpTimeout
;
51 BOOLEAN RtlpTimeoutDisable
;
52 LIST_ENTRY LdrpHashTable
[LDR_HASH_TABLE_ENTRIES
];
53 LIST_ENTRY LdrpDllNotificationList
;
54 HANDLE LdrpKnownDllObjectDirectory
;
55 UNICODE_STRING LdrpKnownDllPath
;
56 WCHAR LdrpKnownDllPathBuffer
[128];
57 UNICODE_STRING LdrpDefaultPath
;
61 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug
;
62 RTL_CRITICAL_SECTION LdrpLoaderLock
=
71 RTL_CRITICAL_SECTION FastPebLock
;
75 ULONG LdrpFatalHardErrorCount
;
76 ULONG LdrpActiveUnloadCount
;
78 //extern LIST_ENTRY RtlCriticalSectionList;
80 VOID
RtlpInitializeVectoredExceptionHandling(VOID
);
81 VOID NTAPI
RtlpInitDeferedCriticalSection(VOID
);
82 VOID NTAPI
RtlInitializeHeapManager(VOID
);
83 extern BOOLEAN RtlpPageHeapEnabled
;
85 ULONG RtlpDisableHeapLookaside
; // TODO: Move to heap.c
86 ULONG RtlpShutdownProcessFlags
; // TODO: Use it
88 NTSTATUS
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
, PVOID ImageBase
);
89 void actctx_init(void);
92 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
94 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E
97 /* FUNCTIONS *****************************************************************/
104 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey
,
106 OUT PHANDLE NewKeyHandle
)
108 PHANDLE RootKeyLocation
;
110 UNICODE_STRING SubKeyString
;
111 OBJECT_ATTRIBUTES ObjectAttributes
;
115 /* Check which root key to open */
117 RootKeyLocation
= &Wow64ExecOptionsKey
;
119 RootKeyLocation
= &ImageExecOptionsKey
;
121 /* Get the current key */
122 RootKey
= *RootKeyLocation
;
124 /* Setup the object attributes */
125 InitializeObjectAttributes(&ObjectAttributes
,
127 &Wow64OptionsString
: &ImageExecOptionsString
,
128 OBJ_CASE_INSENSITIVE
,
132 /* Open the root key */
133 Status
= ZwOpenKey(&RootKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
134 if (NT_SUCCESS(Status
))
136 /* Write the key handle */
137 if (_InterlockedCompareExchange((LONG
*)RootKeyLocation
, (LONG
)RootKey
, 0) != 0)
139 /* Someone already opened it, use it instead */
141 RootKey
= *RootKeyLocation
;
144 /* Extract the name */
145 SubKeyString
= *SubKey
;
146 p1
= (PWCHAR
)((ULONG_PTR
)SubKeyString
.Buffer
+ SubKeyString
.Length
);
147 while (SubKeyString
.Length
)
149 if (p1
[-1] == L
'\\') break;
151 SubKeyString
.Length
-= sizeof(*p1
);
153 SubKeyString
.Buffer
= p1
;
154 SubKeyString
.Length
= SubKey
->Length
- SubKeyString
.Length
;
156 /* Setup the object attributes */
157 InitializeObjectAttributes(&ObjectAttributes
,
159 OBJ_CASE_INSENSITIVE
,
163 /* Open the setting key */
164 Status
= ZwOpenKey((PHANDLE
)NewKeyHandle
, GENERIC_READ
, &ObjectAttributes
);
167 /* Return to caller */
176 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle
,
181 OUT PULONG ReturnedLength OPTIONAL
)
184 UNICODE_STRING ValueNameString
, IntegerString
;
185 ULONG KeyInfoSize
, ResultSize
;
186 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)&KeyInfo
;
187 BOOLEAN FreeHeap
= FALSE
;
190 /* Build a string for the value name */
191 Status
= RtlInitUnicodeStringEx(&ValueNameString
, ValueName
);
192 if (!NT_SUCCESS(Status
)) return Status
;
194 /* Query the value */
195 Status
= ZwQueryValueKey(KeyHandle
,
197 KeyValuePartialInformation
,
201 if (Status
== STATUS_BUFFER_OVERFLOW
)
203 /* Our local buffer wasn't enough, allocate one */
204 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
205 KeyValueInformation
->DataLength
;
206 KeyValueInformation
= RtlAllocateHeap(RtlGetProcessHeap(),
209 if (KeyValueInformation
!= NULL
)
212 Status
= ZwQueryValueKey(KeyHandle
,
214 KeyValuePartialInformation
,
222 /* Give up this time */
223 Status
= STATUS_NO_MEMORY
;
227 /* Check for success */
228 if (NT_SUCCESS(Status
))
230 /* Handle binary data */
231 if (KeyValueInformation
->Type
== REG_BINARY
)
234 if ((Buffer
) && (KeyValueInformation
->DataLength
<= BufferSize
))
236 /* Copy into buffer */
237 RtlMoveMemory(Buffer
,
238 &KeyValueInformation
->Data
,
239 KeyValueInformation
->DataLength
);
243 Status
= STATUS_BUFFER_OVERFLOW
;
246 /* Copy the result length */
247 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
249 else if (KeyValueInformation
->Type
== REG_DWORD
)
251 /* Check for valid type */
252 if (KeyValueInformation
->Type
!= Type
)
255 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
261 (BufferSize
== sizeof(ULONG
)) &&
262 (KeyValueInformation
->DataLength
<= BufferSize
))
264 /* Copy into buffer */
265 RtlMoveMemory(Buffer
,
266 &KeyValueInformation
->Data
,
267 KeyValueInformation
->DataLength
);
271 Status
= STATUS_BUFFER_OVERFLOW
;
274 /* Copy the result length */
275 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
278 else if (KeyValueInformation
->Type
!= REG_SZ
)
280 /* We got something weird */
281 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
285 /* String, check what you requested */
286 if (Type
== REG_DWORD
)
289 if (BufferSize
!= sizeof(ULONG
))
293 Status
= STATUS_INFO_LENGTH_MISMATCH
;
297 /* OK, we know what you want... */
298 IntegerString
.Buffer
= (PWSTR
)KeyValueInformation
->Data
;
299 IntegerString
.Length
= (USHORT
)KeyValueInformation
->DataLength
-
301 IntegerString
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
302 Status
= RtlUnicodeStringToInteger(&IntegerString
, 0, (PULONG
)Buffer
);
308 if (KeyValueInformation
->DataLength
> BufferSize
)
311 Status
= STATUS_BUFFER_OVERFLOW
;
316 BufferSize
= KeyValueInformation
->DataLength
;
319 /* Copy the string */
320 RtlMoveMemory(Buffer
, &KeyValueInformation
->Data
, BufferSize
);
323 /* Copy the result length */
324 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
328 /* Check if buffer was in heap */
329 if (FreeHeap
) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation
);
340 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey
,
345 OUT PULONG ReturnedLength OPTIONAL
,
351 /* Open a handle to the key */
352 Status
= LdrOpenImageFileOptionsKey(SubKey
, Wow64
, &KeyHandle
);
354 /* Check for success */
355 if (NT_SUCCESS(Status
))
358 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
369 /* Return to caller */
378 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey
,
383 OUT PULONG ReturnedLength OPTIONAL
)
385 /* Call the newer function */
386 return LdrQueryImageFileExecutionOptionsEx(SubKey
,
397 LdrpEnsureLoaderLockIsHeld()
404 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress
, ULONG SizeOfImage
)
406 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir
;
410 /* Check NT header first */
411 if (!RtlImageNtHeader(BaseAddress
)) return NULL
;
413 /* Get the pointer to the config directory */
414 ConfigDir
= RtlImageDirectoryEntryToData(BaseAddress
,
416 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
419 /* Check for sanity */
421 (DirSize
!= 64 && ConfigDir
->Size
!= DirSize
) ||
422 (ConfigDir
->Size
< 0x48))
425 /* Now get the cookie */
426 Cookie
= (PVOID
)ConfigDir
->SecurityCookie
;
428 /* Check this cookie */
429 if ((PCHAR
)Cookie
<= (PCHAR
)BaseAddress
||
430 (PCHAR
)Cookie
>= (PCHAR
)BaseAddress
+ SizeOfImage
)
435 /* Return validated security cookie */
441 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry
)
444 LARGE_INTEGER Counter
;
447 /* Fetch address of the cookie */
448 Cookie
= LdrpFetchAddressOfSecurityCookie(LdrEntry
->DllBase
, LdrEntry
->SizeOfImage
);
452 /* Check if it's a default one */
453 if ((*Cookie
== DEFAULT_SECURITY_COOKIE
) ||
456 /* Make up a cookie from a bunch of values which may uniquely represent
457 current moment of time, environment, etc */
458 NtQueryPerformanceCounter(&Counter
, NULL
);
460 NewCookie
= Counter
.LowPart
^ Counter
.HighPart
;
461 NewCookie
^= (ULONG
)NtCurrentTeb()->ClientId
.UniqueProcess
;
462 NewCookie
^= (ULONG
)NtCurrentTeb()->ClientId
.UniqueThread
;
464 /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */
465 while (SharedUserData
->SystemTime
.High1Time
!= SharedUserData
->SystemTime
.High2Time
)
470 /* Calculate the milliseconds value and xor it to the cookie */
471 NewCookie
^= Int64ShrlMod32(UInt32x32To64(SharedUserData
->TickCountMultiplier
, SharedUserData
->TickCount
.LowPart
), 24) +
472 (SharedUserData
->TickCountMultiplier
* (SharedUserData
->TickCount
.High1Time
<< 8));
474 /* Make the cookie 16bit if necessary */
475 if (*Cookie
== 0xBB40) NewCookie
&= 0xFFFF;
477 /* If the result is 0 or the same as we got, just subtract one from the existing value
479 if ((NewCookie
== 0) || (NewCookie
== *Cookie
))
481 NewCookie
= *Cookie
- 1;
484 /* Set the new cookie value */
494 LdrpInitializeThread(IN PCONTEXT Context
)
496 PPEB Peb
= NtCurrentPeb();
497 PLDR_DATA_TABLE_ENTRY LdrEntry
;
498 PLIST_ENTRY NextEntry
, ListHead
;
499 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
503 DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n",
504 &LdrpImageEntry
->BaseDllName
,
505 NtCurrentTeb()->RealClientId
.UniqueProcess
,
506 NtCurrentTeb()->RealClientId
.UniqueThread
);
508 /* Allocate an Activation Context Stack */
509 DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer
);
510 Status
= RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer
);
511 if (!NT_SUCCESS(Status
))
513 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
516 /* Make sure we are not shutting down */
517 if (LdrpShutdownInProgress
) return;
522 /* Start at the beginning */
523 ListHead
= &Peb
->Ldr
->InMemoryOrderModuleList
;
524 NextEntry
= ListHead
->Flink
;
525 while (NextEntry
!= ListHead
)
527 /* Get the current entry */
528 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InMemoryOrderModuleList
);
530 /* Make sure it's not ourselves */
531 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
533 /* Check if we should call */
534 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
))
536 /* Get the entrypoint */
537 EntryPoint
= LdrEntry
->EntryPoint
;
539 /* Check if we are ready to call it */
541 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
542 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
544 /* Set up the Act Ctx */
545 ActCtx
.Size
= sizeof(ActCtx
);
547 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
549 /* Activate the ActCtx */
550 RtlActivateActivationContextUnsafeFast(&ActCtx
,
551 LdrEntry
->EntryPointActivationContext
);
553 /* Check if it has TLS */
554 if (LdrEntry
->TlsIndex
)
556 /* Make sure we're not shutting down */
557 if (!LdrpShutdownInProgress
)
560 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_THREAD_ATTACH
);
564 /* Make sure we're not shutting down */
565 if (!LdrpShutdownInProgress
)
567 /* Call the Entrypoint */
568 DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n",
569 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
,
570 NtCurrentTeb()->RealClientId
.UniqueProcess
,
571 NtCurrentTeb()->RealClientId
.UniqueThread
);
572 LdrpCallInitRoutine(LdrEntry
->EntryPoint
,
578 /* Deactivate the ActCtx */
579 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
585 NextEntry
= NextEntry
->Flink
;
589 if (LdrpImageHasTls
&& !LdrpShutdownInProgress
)
591 /* Set up the Act Ctx */
592 ActCtx
.Size
= sizeof(ActCtx
);
594 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
596 /* Activate the ActCtx */
597 RtlActivateActivationContextUnsafeFast(&ActCtx
,
598 LdrpImageEntry
->EntryPointActivationContext
);
600 /* Do TLS callbacks */
601 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_THREAD_ATTACH
);
603 /* Deactivate the ActCtx */
604 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
607 DPRINT("LdrpInitializeThread() done\n");
612 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL
)
614 PLDR_DATA_TABLE_ENTRY LocalArray
[16];
615 PLIST_ENTRY ListHead
;
616 PLIST_ENTRY NextEntry
;
617 PLDR_DATA_TABLE_ENTRY LdrEntry
, *LdrRootEntry
, OldInitializer
;
621 NTSTATUS Status
= STATUS_SUCCESS
;
622 PPEB Peb
= NtCurrentPeb();
623 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
624 ULONG BreakOnDllLoad
;
628 DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
629 &LdrpImageEntry
->BaseDllName
,
630 NtCurrentTeb()->RealClientId
.UniqueProcess
,
631 NtCurrentTeb()->RealClientId
.UniqueThread
);
633 /* Check the Loader Lock */
634 LdrpEnsureLoaderLockIsHeld();
636 /* Get the number of entries to call */
637 if ((Count
= LdrpClearLoadInProgress()))
639 /* Check if we can use our local buffer */
642 /* Allocate space for all the entries */
643 LdrRootEntry
= RtlAllocateHeap(RtlGetProcessHeap(),
645 Count
* sizeof(*LdrRootEntry
));
646 if (!LdrRootEntry
) return STATUS_NO_MEMORY
;
650 /* Use our local array */
651 LdrRootEntry
= LocalArray
;
660 /* Show debug message */
663 DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
664 NtCurrentTeb()->RealClientId
.UniqueThread
,
665 NtCurrentTeb()->RealClientId
.UniqueProcess
,
666 &Peb
->ProcessParameters
->ImagePathName
);
670 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
671 NextEntry
= ListHead
->Flink
;
673 while (NextEntry
!= ListHead
)
675 /* Get the Data Entry */
676 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
678 /* Check if we have a Root Entry */
682 if (!(LdrEntry
->Flags
& LDRP_ENTRY_PROCESSED
))
684 /* Setup the Cookie for the DLL */
685 LdrpInitSecurityCookie(LdrEntry
);
687 /* Check for valid entrypoint */
688 if (LdrEntry
->EntryPoint
)
692 LdrRootEntry
[i
] = LdrEntry
;
694 /* Display debug message */
697 DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
698 NtCurrentTeb()->RealClientId
.UniqueThread
,
699 NtCurrentTeb()->RealClientId
.UniqueProcess
,
700 &LdrEntry
->FullDllName
,
701 LdrEntry
->EntryPoint
);
709 LdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
710 NextEntry
= NextEntry
->Flink
;
713 /* If we got a context, then we have to call Kernel32 for TS support */
716 /* Check if we have one */
717 //if (Kernel32ProcessInitPostImportfunction)
720 //Kernel32ProcessInitPostImportfunction();
724 //Kernel32ProcessInitPostImportfunction = NULL;
728 /* No root entry? return */
729 if (!LdrRootEntry
) return STATUS_SUCCESS
;
731 /* Set the TLD TEB */
732 OldTldTeb
= LdrpTopLevelDllBeingLoadedTeb
;
733 LdrpTopLevelDllBeingLoadedTeb
= NtCurrentTeb();
740 LdrEntry
= LdrRootEntry
[i
];
742 /* FIXME: Verify NX Compat */
744 /* Move to next entry */
747 /* Get its entrypoint */
748 EntryPoint
= LdrEntry
->EntryPoint
;
750 /* Are we being debugged? */
752 if (Peb
->BeingDebugged
|| Peb
->ReadImageFileExecOptions
)
754 /* Check if we should break on load */
755 Status
= LdrQueryImageFileExecutionOptions(&LdrEntry
->BaseDllName
,
761 if (!NT_SUCCESS(Status
)) BreakOnDllLoad
= 0;
763 /* Reset status back to STATUS_SUCCESS */
764 Status
= STATUS_SUCCESS
;
770 /* Check if we should show a message */
773 DPRINT1("LDR: %wZ loaded.", &LdrEntry
->BaseDllName
);
774 DPRINT1(" - About to call init routine at %p\n", EntryPoint
);
777 /* Break in debugger */
781 /* Make sure we have an entrypoint */
784 /* Save the old Dll Initializer and write the current one */
785 OldInitializer
= LdrpCurrentDllInitializer
;
786 LdrpCurrentDllInitializer
= LdrEntry
;
788 /* Set up the Act Ctx */
789 ActCtx
.Size
= sizeof(ActCtx
);
791 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
793 /* Activate the ActCtx */
794 RtlActivateActivationContextUnsafeFast(&ActCtx
,
795 LdrEntry
->EntryPointActivationContext
);
797 /* Check if it has TLS */
798 if (LdrEntry
->TlsIndex
&& Context
)
801 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_PROCESS_ATTACH
);
804 /* Call the Entrypoint */
807 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
808 &LdrEntry
->BaseDllName
, EntryPoint
);
810 DllStatus
= LdrpCallInitRoutine(EntryPoint
,
815 /* Deactivate the ActCtx */
816 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
818 /* Save the Current DLL Initializer */
819 LdrpCurrentDllInitializer
= OldInitializer
;
821 /* Mark the entry as processed */
822 LdrEntry
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
;
824 /* Fail if DLL init failed */
827 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
828 &LdrEntry
->BaseDllName
, EntryPoint
);
830 Status
= STATUS_DLL_INIT_FAILED
;
837 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
838 NextEntry
= NextEntry
->Flink
;
839 while (NextEntry
!= ListHead
)
841 /* Get the Data Entrry */
842 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
844 /* FIXME: Verify NX Compat */
845 // LdrpCheckNXCompatibility()
848 NextEntry
= NextEntry
->Flink
;
852 if (LdrpImageHasTls
&& Context
)
854 /* Set up the Act Ctx */
855 ActCtx
.Size
= sizeof(ActCtx
);
857 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
859 /* Activate the ActCtx */
860 RtlActivateActivationContextUnsafeFast(&ActCtx
,
861 LdrpImageEntry
->EntryPointActivationContext
);
863 /* Do TLS callbacks */
864 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_PROCESS_ATTACH
);
866 /* Deactivate the ActCtx */
867 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
871 /* Restore old TEB */
872 LdrpTopLevelDllBeingLoadedTeb
= OldTldTeb
;
874 /* Check if the array is in the heap */
875 if (LdrRootEntry
!= LocalArray
)
878 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry
);
881 /* Return to caller */
882 DPRINT("LdrpRunInitializeRoutines() done\n");
891 LdrShutdownProcess(VOID
)
893 PPEB Peb
= NtCurrentPeb();
894 PLDR_DATA_TABLE_ENTRY LdrEntry
;
895 PLIST_ENTRY NextEntry
, ListHead
;
896 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
899 DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry
->BaseDllName
);
900 if (LdrpShutdownInProgress
) return STATUS_SUCCESS
;
902 /* Tell the Shim Engine */
914 /* Set the shutdown variables */
915 LdrpShutdownThreadId
= NtCurrentTeb()->RealClientId
.UniqueThread
;
916 LdrpShutdownInProgress
= TRUE
;
918 /* Enter the Loader Lock */
919 RtlEnterCriticalSection(&LdrpLoaderLock
);
921 /* Cleanup trace logging data (Etw) */
922 if (SharedUserData
->TraceLogging
)
925 DPRINT1("We don't support Etw yet.\n");
928 /* Start at the end */
929 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
930 NextEntry
= ListHead
->Blink
;
931 while (NextEntry
!= ListHead
)
933 /* Get the current entry */
934 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
935 NextEntry
= NextEntry
->Blink
;
937 /* Make sure it's not ourselves */
938 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
940 /* Get the entrypoint */
941 EntryPoint
= LdrEntry
->EntryPoint
;
943 /* Check if we are ready to call it */
945 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
948 /* Set up the Act Ctx */
949 ActCtx
.Size
= sizeof(ActCtx
);
951 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
953 /* Activate the ActCtx */
954 RtlActivateActivationContextUnsafeFast(&ActCtx
,
955 LdrEntry
->EntryPointActivationContext
);
957 /* Check if it has TLS */
958 if (LdrEntry
->TlsIndex
)
961 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_PROCESS_DETACH
);
964 /* Call the Entrypoint */
965 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
966 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
967 LdrpCallInitRoutine(EntryPoint
,
972 /* Deactivate the ActCtx */
973 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
981 /* Set up the Act Ctx */
982 ActCtx
.Size
= sizeof(ActCtx
);
984 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
986 /* Activate the ActCtx */
987 RtlActivateActivationContextUnsafeFast(&ActCtx
,
988 LdrpImageEntry
->EntryPointActivationContext
);
990 /* Do TLS callbacks */
991 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_PROCESS_DETACH
);
993 /* Deactivate the ActCtx */
994 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
997 /* FIXME: Do Heap detection and Etw final shutdown */
999 /* Release the lock */
1000 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1001 DPRINT("LdrpShutdownProcess() done\n");
1003 return STATUS_SUCCESS
;
1011 LdrShutdownThread(VOID
)
1013 PPEB Peb
= NtCurrentPeb();
1014 PTEB Teb
= NtCurrentTeb();
1015 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1016 PLIST_ENTRY NextEntry
, ListHead
;
1017 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
1020 DPRINT("LdrShutdownThread() called for %wZ\n",
1021 &LdrpImageEntry
->BaseDllName
);
1023 /* Cleanup trace logging data (Etw) */
1024 if (SharedUserData
->TraceLogging
)
1027 DPRINT1("We don't support Etw yet.\n");
1030 /* Get the Ldr Lock */
1031 RtlEnterCriticalSection(&LdrpLoaderLock
);
1033 /* Start at the end */
1034 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
1035 NextEntry
= ListHead
->Blink
;
1036 while (NextEntry
!= ListHead
)
1038 /* Get the current entry */
1039 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
1040 NextEntry
= NextEntry
->Blink
;
1042 /* Make sure it's not ourselves */
1043 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
1045 /* Check if we should call */
1046 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
1047 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
1048 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
1050 /* Get the entrypoint */
1051 EntryPoint
= LdrEntry
->EntryPoint
;
1053 /* Check if we are ready to call it */
1056 /* Set up the Act Ctx */
1057 ActCtx
.Size
= sizeof(ActCtx
);
1059 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1061 /* Activate the ActCtx */
1062 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1063 LdrEntry
->EntryPointActivationContext
);
1065 /* Check if it has TLS */
1066 if (LdrEntry
->TlsIndex
)
1068 /* Make sure we're not shutting down */
1069 if (!LdrpShutdownInProgress
)
1072 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_THREAD_DETACH
);
1076 /* Make sure we're not shutting down */
1077 if (!LdrpShutdownInProgress
)
1079 /* Call the Entrypoint */
1080 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1081 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1082 LdrpCallInitRoutine(EntryPoint
,
1088 /* Deactivate the ActCtx */
1089 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1096 if (LdrpImageHasTls
)
1098 /* Set up the Act Ctx */
1099 ActCtx
.Size
= sizeof(ActCtx
);
1101 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1103 /* Activate the ActCtx */
1104 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1105 LdrpImageEntry
->EntryPointActivationContext
);
1107 /* Do TLS callbacks */
1108 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_THREAD_DETACH
);
1110 /* Deactivate the ActCtx */
1111 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1116 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1118 /* Check for expansion slots */
1119 if (Teb
->TlsExpansionSlots
)
1121 /* Free expansion slots */
1122 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->TlsExpansionSlots
);
1125 /* Check for FLS Data */
1129 DPRINT1("We don't support FLS Data yet\n");
1132 /* Check for Fiber data */
1133 if (Teb
->HasFiberData
)
1135 /* Free Fiber data*/
1136 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->NtTib
.FiberData
);
1137 Teb
->NtTib
.FiberData
= NULL
;
1140 /* Free the activation context stack */
1141 RtlFreeThreadActivationContextStack();
1142 DPRINT("LdrShutdownThread() done\n");
1144 return STATUS_SUCCESS
;
1149 LdrpInitializeTls(VOID
)
1151 PLIST_ENTRY NextEntry
, ListHead
;
1152 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1153 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1154 PLDRP_TLS_DATA TlsData
;
1157 /* Initialize the TLS List */
1158 InitializeListHead(&LdrpTlsList
);
1160 /* Loop all the modules */
1161 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1162 NextEntry
= ListHead
->Flink
;
1163 while (ListHead
!= NextEntry
)
1166 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1167 NextEntry
= NextEntry
->Flink
;
1169 /* Get the TLS directory */
1170 TlsDirectory
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
1172 IMAGE_DIRECTORY_ENTRY_TLS
,
1175 /* Check if we have a directory */
1176 if (!TlsDirectory
) continue;
1178 /* Check if the image has TLS */
1179 if (!LdrpImageHasTls
) LdrpImageHasTls
= TRUE
;
1181 /* Show debug message */
1184 DPRINT1("LDR: Tls Found in %wZ at %p\n",
1185 &LdrEntry
->BaseDllName
,
1189 /* Allocate an entry */
1190 TlsData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA
));
1191 if (!TlsData
) return STATUS_NO_MEMORY
;
1193 /* Lock the DLL and mark it for TLS Usage */
1194 LdrEntry
->LoadCount
= -1;
1195 LdrEntry
->TlsIndex
= -1;
1197 /* Save the cached TLS data */
1198 TlsData
->TlsDirectory
= *TlsDirectory
;
1199 InsertTailList(&LdrpTlsList
, &TlsData
->TlsLinks
);
1201 /* Update the index */
1202 *(PLONG
)TlsData
->TlsDirectory
.AddressOfIndex
= LdrpNumberOfTlsEntries
;
1203 TlsData
->TlsDirectory
.Characteristics
= LdrpNumberOfTlsEntries
++;
1206 /* Done setting up TLS, allocate entries */
1207 return LdrpAllocateTls();
1212 LdrpAllocateTls(VOID
)
1214 PTEB Teb
= NtCurrentTeb();
1215 PLIST_ENTRY NextEntry
, ListHead
;
1216 PLDRP_TLS_DATA TlsData
;
1220 /* Check if we have any entries */
1221 if (!LdrpNumberOfTlsEntries
)
1222 return STATUS_SUCCESS
;
1224 /* Allocate the vector array */
1225 TlsVector
= RtlAllocateHeap(RtlGetProcessHeap(),
1227 LdrpNumberOfTlsEntries
* sizeof(PVOID
));
1228 if (!TlsVector
) return STATUS_NO_MEMORY
;
1229 Teb
->ThreadLocalStoragePointer
= TlsVector
;
1231 /* Loop the TLS Array */
1232 ListHead
= &LdrpTlsList
;
1233 NextEntry
= ListHead
->Flink
;
1234 while (NextEntry
!= ListHead
)
1237 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1238 NextEntry
= NextEntry
->Flink
;
1240 /* Allocate this vector */
1241 TlsDataSize
= TlsData
->TlsDirectory
.EndAddressOfRawData
-
1242 TlsData
->TlsDirectory
.StartAddressOfRawData
;
1243 TlsVector
[TlsData
->TlsDirectory
.Characteristics
] = RtlAllocateHeap(RtlGetProcessHeap(),
1246 if (!TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1249 return STATUS_NO_MEMORY
;
1252 /* Show debug message */
1255 DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
1257 TlsData
->TlsDirectory
.Characteristics
,
1258 &TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1259 TlsData
->TlsDirectory
.StartAddressOfRawData
,
1260 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1264 RtlCopyMemory(TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1265 (PVOID
)TlsData
->TlsDirectory
.StartAddressOfRawData
,
1270 return STATUS_SUCCESS
;
1277 PLIST_ENTRY ListHead
, NextEntry
;
1278 PLDRP_TLS_DATA TlsData
;
1280 PTEB Teb
= NtCurrentTeb();
1282 /* Get a pointer to the vector array */
1283 TlsVector
= Teb
->ThreadLocalStoragePointer
;
1284 if (!TlsVector
) return;
1286 /* Loop through it */
1287 ListHead
= &LdrpTlsList
;
1288 NextEntry
= ListHead
->Flink
;
1289 while (NextEntry
!= ListHead
)
1291 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1292 NextEntry
= NextEntry
->Flink
;
1294 /* Free each entry */
1295 if (TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1297 RtlFreeHeap(RtlGetProcessHeap(),
1299 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1303 /* Free the array itself */
1304 RtlFreeHeap(RtlGetProcessHeap(),
1311 LdrpInitializeApplicationVerifierPackage(PUNICODE_STRING ImagePathName
, PPEB Peb
, BOOLEAN SystemWide
, BOOLEAN ReadAdvancedOptions
)
1313 /* If global flags request DPH, perform some additional actions */
1314 if (Peb
->NtGlobalFlag
& FLG_HEAP_PAGE_ALLOCS
)
1316 // TODO: Read advanced DPH flags from the registry if requested
1317 if (ReadAdvancedOptions
)
1322 /* Enable page heap */
1323 RtlpPageHeapEnabled
= TRUE
;
1326 return STATUS_SUCCESS
;
1331 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName
, PPEB Peb
, PHANDLE OptionsKey
)
1335 ULONG ExecuteOptions
, MinimumStackCommit
= 0, GlobalFlag
;
1337 /* Return error if we were not provided a pointer where to save the options key handle */
1338 if (!OptionsKey
) return STATUS_INVALID_HANDLE
;
1340 /* Zero initialize the optinos key pointer */
1343 /* Open the options key */
1344 Status
= LdrOpenImageFileOptionsKey(ImagePathName
, 0, &KeyHandle
);
1346 /* Save it if it was opened successfully */
1347 if (NT_SUCCESS(Status
))
1348 *OptionsKey
= KeyHandle
;
1352 /* There are image specific options, read them starting with NXCOMPAT */
1353 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1357 sizeof(ExecuteOptions
),
1360 if (NT_SUCCESS(Status
))
1362 /* TODO: Set execution options for the process */
1364 if (ExecuteOptions == 0)
1368 ZwSetInformationProcess(NtCurrentProcess(),
1369 ProcessExecuteFlags,
1375 /* Check if this image uses large pages */
1376 if (Peb
->ImageUsesLargePages
)
1378 /* TODO: If it does, open large page key */
1382 /* Get various option values */
1383 LdrQueryImageFileKeyOption(KeyHandle
,
1384 L
"DisableHeapLookaside",
1386 &RtlpDisableHeapLookaside
,
1387 sizeof(RtlpDisableHeapLookaside
),
1390 LdrQueryImageFileKeyOption(KeyHandle
,
1393 &RtlpShutdownProcessFlags
,
1394 sizeof(RtlpShutdownProcessFlags
),
1397 LdrQueryImageFileKeyOption(KeyHandle
,
1398 L
"MinimumStackCommitInBytes",
1400 &MinimumStackCommit
,
1401 sizeof(MinimumStackCommit
),
1404 /* Update PEB's minimum stack commit if it's lower */
1405 if (Peb
->MinimumStackCommit
< MinimumStackCommit
)
1406 Peb
->MinimumStackCommit
= MinimumStackCommit
;
1408 /* Set the global flag */
1409 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1416 if (NT_SUCCESS(Status
))
1417 Peb
->NtGlobalFlag
= GlobalFlag
;
1421 /* Call AVRF if necessary */
1422 if (Peb
->NtGlobalFlag
& (FLG_POOL_ENABLE_TAIL_CHECK
| FLG_HEAP_PAGE_ALLOCS
))
1424 Status
= LdrpInitializeApplicationVerifierPackage(ImagePathName
, Peb
, TRUE
, FALSE
);
1425 if (!NT_SUCCESS(Status
))
1427 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1433 /* There are no image-specific options, so perform global initialization */
1434 if (Peb
->NtGlobalFlag
& (FLG_POOL_ENABLE_TAIL_CHECK
| FLG_HEAP_PAGE_ALLOCS
))
1436 /* Initialize app verifier package */
1437 Status
= LdrpInitializeApplicationVerifierPackage(ImagePathName
, Peb
, TRUE
, FALSE
);
1438 if (!NT_SUCCESS(Status
))
1440 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1445 return STATUS_SUCCESS
;
1450 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
)
1457 LdrpInitializeProcess(IN PCONTEXT Context
,
1458 IN PVOID SystemArgument1
)
1460 RTL_HEAP_PARAMETERS HeapParameters
;
1461 ULONG ComSectionSize
;
1462 //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData");
1464 OBJECT_ATTRIBUTES ObjectAttributes
;
1465 //UNICODE_STRING LocalFileName, FullImageName;
1466 HANDLE SymLinkHandle
;
1467 //ULONG DebugHeapOnly;
1468 UNICODE_STRING CommandLine
, NtSystemRoot
, ImagePathName
, FullPath
, ImageFileName
, KnownDllString
;
1469 PPEB Peb
= NtCurrentPeb();
1470 BOOLEAN IsDotNetImage
= FALSE
;
1471 BOOLEAN FreeCurDir
= FALSE
;
1473 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1474 //LPWSTR ImagePathBuffer;
1476 UNICODE_STRING CurrentDirectory
;
1479 PIMAGE_NT_HEADERS NtHeader
;
1480 LPWSTR NtDllName
= NULL
;
1481 NTSTATUS Status
, ImportStatus
;
1482 NLSTABLEINFO NlsTable
;
1483 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig
;
1484 PTEB Teb
= NtCurrentTeb();
1485 PLIST_ENTRY ListHead
;
1486 PLIST_ENTRY NextEntry
;
1489 ULONG DebugProcessHeapOnly
= 0;
1490 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
1492 ULONG ExecuteOptions
= 0;
1495 /* Set a NULL SEH Filter */
1496 RtlSetUnhandledExceptionFilter(NULL
);
1498 /* Get the image path */
1499 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
1501 /* Check if it's not normalized */
1502 if (!(Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
))
1505 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
1508 /* Create a unicode string for the Image Path */
1509 ImagePathName
.Length
= Peb
->ProcessParameters
->ImagePathName
.Length
;
1510 ImagePathName
.MaximumLength
= ImagePathName
.Length
+ sizeof(WCHAR
);
1511 ImagePathName
.Buffer
= ImagePath
;
1513 /* Get the NT Headers */
1514 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
1516 /* Get the execution options */
1517 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &OptionsKey
);
1519 /* Check if this is a .NET executable */
1520 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1522 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
1525 /* Remeber this for later */
1526 IsDotNetImage
= TRUE
;
1529 /* Save the NTDLL Base address */
1530 NtDllBase
= SystemArgument1
;
1532 /* If this is a Native Image */
1533 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
1535 /* Then do DLL Validation */
1536 LdrpDllValidation
= TRUE
;
1539 /* Save the old Shim Data */
1540 OldShimData
= Peb
->pShimData
;
1543 Peb
->pShimData
= NULL
;
1545 /* Save the number of processors and CS Timeout */
1546 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
1547 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
1549 /* Normalize the parameters */
1550 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
1551 if (ProcessParameters
)
1553 /* Save the Image and Command Line Names */
1554 ImageFileName
= ProcessParameters
->ImagePathName
;
1555 CommandLine
= ProcessParameters
->CommandLine
;
1559 /* It failed, initialize empty strings */
1560 RtlInitUnicodeString(&ImageFileName
, NULL
);
1561 RtlInitUnicodeString(&CommandLine
, NULL
);
1564 /* Initialize NLS data */
1565 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1566 Peb
->OemCodePageData
,
1567 Peb
->UnicodeCaseTableData
,
1570 /* Reset NLS Translations */
1571 RtlResetRtlTranslations(&NlsTable
);
1573 /* Get the Image Config Directory */
1574 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1576 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1579 /* Setup the Heap Parameters */
1580 RtlZeroMemory(&HeapParameters
, sizeof(RTL_HEAP_PARAMETERS
));
1581 HeapFlags
= HEAP_GROWABLE
;
1582 HeapParameters
.Length
= sizeof(RTL_HEAP_PARAMETERS
);
1584 /* Check if we have Configuration Data */
1585 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1587 /* FIXME: Custom heap settings and misc. */
1588 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1591 /* Check for custom affinity mask */
1592 if (Peb
->ImageProcessAffinityMask
)
1595 Status
= NtSetInformationProcess(NtCurrentProcess(),
1596 ProcessAffinityMask
,
1597 &Peb
->ImageProcessAffinityMask
,
1598 sizeof(Peb
->ImageProcessAffinityMask
));
1601 /* Check if verbose debugging (ShowSnaps) was requested */
1602 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1604 /* Start verbose debugging messages right now if they were requested */
1607 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1608 Teb
->ClientId
.UniqueProcess
,
1612 /* If the timeout is too long */
1613 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1615 /* Then disable CS Timeout */
1616 RtlpTimeoutDisable
= TRUE
;
1619 /* Initialize Critical Section Data */
1620 RtlpInitDeferedCriticalSection();
1622 /* Initialize VEH Call lists */
1623 RtlpInitializeVectoredExceptionHandling();
1625 /* Set TLS/FLS Bitmap data */
1626 Peb
->FlsBitmap
= &FlsBitMap
;
1627 Peb
->TlsBitmap
= &TlsBitMap
;
1628 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1630 /* Initialize FLS Bitmap */
1631 RtlInitializeBitMap(&FlsBitMap
,
1633 FLS_MAXIMUM_AVAILABLE
);
1634 RtlSetBit(&FlsBitMap
, 0);
1636 /* Initialize TLS Bitmap */
1637 RtlInitializeBitMap(&TlsBitMap
,
1639 TLS_MINIMUM_AVAILABLE
);
1640 RtlSetBit(&TlsBitMap
, 0);
1641 RtlInitializeBitMap(&TlsExpansionBitMap
,
1642 Peb
->TlsExpansionBitmapBits
,
1643 TLS_EXPANSION_SLOTS
);
1644 RtlSetBit(&TlsExpansionBitMap
, 0);
1646 /* Initialize the Hash Table */
1647 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1649 InitializeListHead(&LdrpHashTable
[i
]);
1652 /* Initialize the Loader Lock */
1653 // FIXME: What's the point of initing it manually, if two lines lower
1654 // a call to RtlInitializeCriticalSection() is being made anyway?
1655 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1656 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1657 RtlInitializeCriticalSection(&LdrpLoaderLock
);
1658 LdrpLoaderLockInit
= TRUE
;
1660 /* Check if User Stack Trace Database support was requested */
1661 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1663 DPRINT1("We don't support user stack trace databases yet\n");
1666 /* Setup Fast PEB Lock */
1667 RtlInitializeCriticalSection(&FastPebLock
);
1668 Peb
->FastPebLock
= &FastPebLock
;
1669 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1670 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1672 /* Setup Callout Lock and Notification list */
1673 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1674 InitializeListHead(&LdrpDllNotificationList
);
1676 /* For old executables, use 16-byte aligned heap */
1677 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1678 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1680 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1683 /* Setup the Heap */
1684 RtlInitializeHeapManager();
1685 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1687 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1688 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1692 if (!Peb
->ProcessHeap
)
1694 DPRINT1("Failed to create process heap\n");
1695 return STATUS_NO_MEMORY
;
1698 /* Allocate an Activation Context Stack */
1699 Status
= RtlAllocateActivationContextStack(&Teb
->ActivationContextStackPointer
);
1700 if (!NT_SUCCESS(Status
)) return Status
;
1702 // FIXME: Loader private heap is missing
1703 //DPRINT1("Loader private heap is missing\n");
1705 /* Check for Debug Heap */
1708 /* Query the setting */
1709 Status
= LdrQueryImageFileKeyOption(OptionsKey
,
1710 L
"DebugProcessHeapOnly",
1712 &DebugProcessHeapOnly
,
1716 if (NT_SUCCESS(Status
))
1718 /* Reset DPH if requested */
1719 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1721 RtlpDphGlobalFlags
&= ~DPH_FLAG_DLL_NOTIFY
;
1722 RtlpPageHeapEnabled
= FALSE
;
1727 /* Build the NTDLL Path */
1728 FullPath
.Buffer
= StringBuffer
;
1729 FullPath
.Length
= 0;
1730 FullPath
.MaximumLength
= sizeof(StringBuffer
);
1731 RtlInitUnicodeString(&NtSystemRoot
, SharedUserData
->NtSystemRoot
);
1732 RtlAppendUnicodeStringToString(&FullPath
, &NtSystemRoot
);
1733 RtlAppendUnicodeToString(&FullPath
, L
"\\System32\\");
1735 /* Open the Known DLLs directory */
1736 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1737 InitializeObjectAttributes(&ObjectAttributes
,
1739 OBJ_CASE_INSENSITIVE
,
1742 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
1743 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
1746 /* Check if it exists */
1747 if (NT_SUCCESS(Status
))
1749 /* Open the Known DLLs Path */
1750 RtlInitUnicodeString(&KnownDllString
, L
"KnownDllPath");
1751 InitializeObjectAttributes(&ObjectAttributes
,
1753 OBJ_CASE_INSENSITIVE
,
1754 LdrpKnownDllObjectDirectory
,
1756 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
1757 SYMBOLIC_LINK_QUERY
,
1759 if (NT_SUCCESS(Status
))
1761 /* Query the path */
1762 LdrpKnownDllPath
.Length
= 0;
1763 LdrpKnownDllPath
.MaximumLength
= sizeof(LdrpKnownDllPathBuffer
);
1764 LdrpKnownDllPath
.Buffer
= LdrpKnownDllPathBuffer
;
1765 Status
= ZwQuerySymbolicLinkObject(SymLinkHandle
, &LdrpKnownDllPath
, NULL
);
1766 NtClose(SymLinkHandle
);
1767 if (!NT_SUCCESS(Status
))
1769 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
1775 /* Check if we failed */
1776 if (!NT_SUCCESS(Status
))
1778 /* Assume System32 */
1779 LdrpKnownDllObjectDirectory
= NULL
;
1780 RtlInitUnicodeString(&LdrpKnownDllPath
, StringBuffer
);
1781 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
1784 /* If we have process parameters, get the default path and current path */
1785 if (ProcessParameters
)
1787 /* Check if we have a Dll Path */
1788 if (ProcessParameters
->DllPath
.Length
)
1791 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
1795 /* We need a valid path */
1796 DPRINT1("No valid DllPath was given!\n");
1797 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
1800 /* Set the current directory */
1801 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
1803 /* Check if it's empty or invalid */
1804 if ((!CurrentDirectory
.Buffer
) ||
1805 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
1806 (!CurrentDirectory
.Length
))
1808 /* Allocate space for the buffer */
1809 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
1812 sizeof(UNICODE_NULL
));
1813 if (!CurrentDirectory
.Buffer
)
1815 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
1819 /* Copy the drive of the system root */
1820 RtlMoveMemory(CurrentDirectory
.Buffer
,
1821 SharedUserData
->NtSystemRoot
,
1823 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
1824 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
1825 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
1828 DPRINT("Using dynamically allocd curdir\n");
1832 /* Use the local buffer */
1833 DPRINT("Using local system root\n");
1837 /* Setup Loader Data */
1839 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
1840 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
1841 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
1842 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
1843 PebLdr
.Initialized
= TRUE
;
1845 /* Allocate a data entry for the Image */
1846 LdrpImageEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
1849 LdrpImageEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(LdrpImageEntry
->DllBase
);
1850 LdrpImageEntry
->LoadCount
= -1;
1851 LdrpImageEntry
->EntryPointActivationContext
= 0;
1852 LdrpImageEntry
->FullDllName
= ImageFileName
;
1855 LdrpImageEntry
->Flags
= LDRP_COR_IMAGE
;
1857 LdrpImageEntry
->Flags
= 0;
1859 /* Check if the name is empty */
1860 if (!ImageFileName
.Buffer
[0])
1862 /* Use the same Base name */
1863 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
1867 /* Find the last slash */
1868 Current
= ImageFileName
.Buffer
;
1871 if (*Current
++ == '\\')
1874 NtDllName
= Current
;
1878 /* Did we find anything? */
1881 /* Use the same Base name */
1882 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
1886 /* Setup the name */
1887 LdrpImageEntry
->BaseDllName
.Length
= (USHORT
)((ULONG_PTR
)ImageFileName
.Buffer
+ ImageFileName
.Length
- (ULONG_PTR
)NtDllName
);
1888 LdrpImageEntry
->BaseDllName
.MaximumLength
= LdrpImageEntry
->BaseDllName
.Length
+ sizeof(WCHAR
);
1889 LdrpImageEntry
->BaseDllName
.Buffer
= (PWSTR
)((ULONG_PTR
)ImageFileName
.Buffer
+
1890 (ImageFileName
.Length
- LdrpImageEntry
->BaseDllName
.Length
));
1894 /* Processing done, insert it */
1895 LdrpInsertMemoryTableEntry(LdrpImageEntry
);
1896 LdrpImageEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
1898 /* Now add an entry for NTDLL */
1899 NtLdrEntry
= LdrpAllocateDataTableEntry(SystemArgument1
);
1900 NtLdrEntry
->Flags
= LDRP_IMAGE_DLL
;
1901 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
1902 NtLdrEntry
->LoadCount
= -1;
1903 NtLdrEntry
->EntryPointActivationContext
= 0;
1905 NtLdrEntry
->FullDllName
.Length
= FullPath
.Length
;
1906 NtLdrEntry
->FullDllName
.MaximumLength
= FullPath
.MaximumLength
;
1907 NtLdrEntry
->FullDllName
.Buffer
= StringBuffer
;
1908 RtlAppendUnicodeStringToString(&NtLdrEntry
->FullDllName
, &NtDllString
);
1910 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
1911 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
1912 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
1914 /* Processing done, insert it */
1915 LdrpNtDllDataTableEntry
= NtLdrEntry
;
1916 LdrpInsertMemoryTableEntry(NtLdrEntry
);
1918 /* Let the world know */
1921 DPRINT1("LDR: NEW PROCESS\n");
1922 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry
->FullDllName
, &LdrpImageEntry
->BaseDllName
);
1923 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory
);
1924 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath
);
1927 /* Link the Init Order List */
1928 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
1929 &LdrpNtDllDataTableEntry
->InInitializationOrderModuleList
);
1931 /* Initialize Wine's active context implementation for the current process */
1934 /* Set the current directory */
1935 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
1936 if (!NT_SUCCESS(Status
))
1938 /* We failed, check if we should free it */
1939 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
1941 /* Set it to the NT Root */
1942 CurrentDirectory
= NtSystemRoot
;
1943 RtlSetCurrentDirectory_U(&CurrentDirectory
);
1947 /* We're done with it, free it */
1948 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
1951 /* Check if we should look for a .local file */
1952 if (ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
)
1955 DPRINT1("We don't support .local overrides yet\n");
1958 /* Check if the Application Verifier was enabled */
1959 if (Peb
->NtGlobalFlag
& FLG_POOL_ENABLE_TAIL_CHECK
)
1962 DPRINT1("We don't support Application Verifier yet\n");
1968 DPRINT1("We don't support .NET applications yet\n");
1971 /* FIXME: Load support for Terminal Services */
1972 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
)
1974 /* Load kernel32 and call BasePostImportInit... */
1975 DPRINT("Unimplemented codepath!\n");
1978 /* Walk the IAT and load all the DLLs */
1979 ImportStatus
= LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
1981 /* Check if relocation is needed */
1982 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
1984 DPRINT1("LDR: Performing EXE relocation\n");
1986 /* Change the protection to prepare for relocation */
1987 ViewBase
= Peb
->ImageBaseAddress
;
1988 Status
= LdrpSetProtection(ViewBase
, FALSE
);
1989 if (!NT_SUCCESS(Status
)) return Status
;
1991 /* Do the relocation */
1992 Status
= LdrRelocateImageWithBias(ViewBase
,
1996 STATUS_CONFLICTING_ADDRESSES
,
1997 STATUS_INVALID_IMAGE_FORMAT
);
1998 if (!NT_SUCCESS(Status
))
2000 DPRINT1("LdrRelocateImageWithBias() failed\n");
2004 /* Check if a start context was provided */
2007 DPRINT1("WARNING: Relocated EXE Context");
2008 UNIMPLEMENTED
; // We should support this
2009 return STATUS_INVALID_IMAGE_FORMAT
;
2012 /* Restore the protection */
2013 Status
= LdrpSetProtection(ViewBase
, TRUE
);
2014 if (!NT_SUCCESS(Status
)) return Status
;
2018 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
2019 NextEntry
= ListHead
->Flink
;
2020 while (ListHead
!= NextEntry
)
2022 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2023 NtLdrEntry
->LoadCount
= -1;
2024 NextEntry
= NextEntry
->Flink
;
2027 /* Phase 0 is done */
2028 LdrpLdrDatabaseIsSetup
= TRUE
;
2030 /* Check whether all static imports were properly loaded and return here */
2031 if (!NT_SUCCESS(ImportStatus
)) return ImportStatus
;
2033 /* Initialize TLS */
2034 Status
= LdrpInitializeTls();
2035 if (!NT_SUCCESS(Status
))
2037 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2042 /* FIXME Mark the DLL Ranges for Stack Traces later */
2044 /* Notify the debugger now */
2045 if (Peb
->BeingDebugged
)
2050 /* Update show snaps again */
2051 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
2054 /* Validate the Image for MP Usage */
2055 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
2057 /* Check NX Options */
2058 if (SharedUserData
->NXSupportPolicy
== 1)
2060 ExecuteOptions
= 0xD;
2062 else if (!SharedUserData
->NXSupportPolicy
)
2064 ExecuteOptions
= 0xA;
2068 ZwSetInformationProcess(NtCurrentProcess(),
2069 ProcessExecuteFlags
,
2073 // FIXME: Should be done by Application Compatibility features,
2074 // by reading the registry, etc...
2075 // For now, this is the old code from ntdll!RtlGetVersion().
2076 RtlInitEmptyUnicodeString(&Peb
->CSDVersion
, NULL
, 0);
2077 if (((Peb
->OSCSDVersion
>> 8) & 0xFF) != 0)
2079 WCHAR szCSDVersion
[128];
2081 ULONG Length
= ARRAYSIZE(szCSDVersion
) - 1;
2082 i
= _snwprintf(szCSDVersion
, Length
,
2084 ((Peb
->OSCSDVersion
>> 8) & 0xFF));
2087 /* Null-terminate if it was overflowed */
2088 szCSDVersion
[Length
] = UNICODE_NULL
;
2091 Length
*= sizeof(WCHAR
);
2092 Peb
->CSDVersion
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
2094 Length
+ sizeof(UNICODE_NULL
));
2095 if (Peb
->CSDVersion
.Buffer
)
2097 Peb
->CSDVersion
.Length
= Length
;
2098 Peb
->CSDVersion
.MaximumLength
= Length
+ sizeof(UNICODE_NULL
);
2100 RtlCopyMemory(Peb
->CSDVersion
.Buffer
,
2102 Peb
->CSDVersion
.MaximumLength
);
2103 Peb
->CSDVersion
.Buffer
[Peb
->CSDVersion
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2107 /* Check if we had Shim Data */
2110 /* Load the Shim Engine */
2111 Peb
->AppCompatInfo
= NULL
;
2112 //LdrpLoadShimEngine(OldShimData, ImagePathName, OldShimData);
2113 DPRINT1("We do not support shims yet\n");
2117 /* Check for Application Compatibility Goo */
2118 //LdrQueryApplicationCompatibilityGoo(hKey);
2119 DPRINT("Querying app compat hacks is missing!\n");
2123 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2124 * incompatible images.
2127 /* Now call the Init Routines */
2128 Status
= LdrpRunInitializeRoutines(Context
);
2129 if (!NT_SUCCESS(Status
))
2131 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2136 /* FIXME: Unload the Shim Engine if it was loaded */
2138 /* Check if we have a user-defined Post Process Routine */
2139 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
2142 Peb
->PostProcessInitRoutine();
2145 /* Close the key if we have one opened */
2146 if (OptionsKey
) NtClose(OptionsKey
);
2154 LdrpInitFailure(NTSTATUS Status
)
2157 PPEB Peb
= NtCurrentPeb();
2159 /* Print a debug message */
2160 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2161 &Peb
->ProcessParameters
->ImagePathName
, Status
);
2163 /* Raise a hard error */
2164 if (!LdrpFatalHardErrorCount
)
2166 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
2172 LdrpInit(PCONTEXT Context
,
2173 PVOID SystemArgument1
,
2174 PVOID SystemArgument2
)
2176 LARGE_INTEGER Timeout
;
2177 PTEB Teb
= NtCurrentTeb();
2178 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
2179 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
2180 PPEB Peb
= NtCurrentPeb();
2182 DPRINT("LdrpInit() %p/%p\n",
2183 NtCurrentTeb()->RealClientId
.UniqueProcess
,
2184 NtCurrentTeb()->RealClientId
.UniqueThread
);
2186 /* Check if we have a deallocation stack */
2187 if (!Teb
->DeallocationStack
)
2189 /* We don't, set one */
2190 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
2191 Teb
->NtTib
.StackLimit
,
2192 MemoryBasicInformation
,
2194 sizeof(MEMORY_BASIC_INFORMATION
),
2196 if (!NT_SUCCESS(Status
))
2199 LdrpInitFailure(Status
);
2200 RtlRaiseStatus(Status
);
2205 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
2208 /* Now check if the process is already being initialized */
2209 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
2213 /* Set the timeout to 30 seconds */
2214 Timeout
.QuadPart
= Int32x32To64(30, -10000);
2216 /* Make sure the status hasn't changed */
2217 while (!LdrpProcessInitialized
)
2220 ZwDelayExecution(FALSE
, &Timeout
);
2224 /* Check if we have already setup LDR data */
2227 /* Setup the Loader Lock */
2228 Peb
->LoaderLock
= &LdrpLoaderLock
;
2230 /* Let other code know we're initializing */
2231 LdrpInLdrInit
= TRUE
;
2233 /* Protect with SEH */
2236 /* Initialize the Process */
2237 LoaderStatus
= LdrpInitializeProcess(Context
,
2240 /* Check for success and if MinimumStackCommit was requested */
2241 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
2243 /* Enforce the limit */
2244 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2248 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2250 /* Fail with the SEH error */
2251 LoaderStatus
= _SEH2_GetExceptionCode();
2255 /* We're not initializing anymore */
2256 LdrpInLdrInit
= FALSE
;
2258 /* Check if init worked */
2259 if (NT_SUCCESS(LoaderStatus
))
2261 /* Set the process as Initialized */
2262 _InterlockedIncrement(&LdrpProcessInitialized
);
2267 /* Loader data is there... is this a fork() ? */
2268 if(Peb
->InheritedAddressSpace
)
2270 /* Handle the fork() */
2271 //LoaderStatus = LdrpForkProcess();
2272 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
2277 /* This is a new thread initializing */
2278 LdrpInitializeThread(Context
);
2282 /* All done, test alert the thread */
2286 if (!NT_SUCCESS(LoaderStatus
))
2289 LdrpInitFailure(LoaderStatus
);
2290 RtlRaiseStatus(LoaderStatus
);