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 NTAPI
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);
90 extern BOOLEAN RtlpUse16ByteSLists
;
93 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
95 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E
98 /* FUNCTIONS *****************************************************************/
105 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey
,
107 OUT PHANDLE NewKeyHandle
)
109 PHANDLE RootKeyLocation
;
111 UNICODE_STRING SubKeyString
;
112 OBJECT_ATTRIBUTES ObjectAttributes
;
116 /* Check which root key to open */
118 RootKeyLocation
= &Wow64ExecOptionsKey
;
120 RootKeyLocation
= &ImageExecOptionsKey
;
122 /* Get the current key */
123 RootKey
= *RootKeyLocation
;
125 /* Setup the object attributes */
126 InitializeObjectAttributes(&ObjectAttributes
,
128 &Wow64OptionsString
: &ImageExecOptionsString
,
129 OBJ_CASE_INSENSITIVE
,
133 /* Open the root key */
134 Status
= ZwOpenKey(&RootKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
135 if (NT_SUCCESS(Status
))
137 /* Write the key handle */
138 if (_InterlockedCompareExchange((LONG
*)RootKeyLocation
, (LONG
)RootKey
, 0) != 0)
140 /* Someone already opened it, use it instead */
142 RootKey
= *RootKeyLocation
;
145 /* Extract the name */
146 SubKeyString
= *SubKey
;
147 p1
= (PWCHAR
)((ULONG_PTR
)SubKeyString
.Buffer
+ SubKeyString
.Length
);
148 while (SubKeyString
.Length
)
150 if (p1
[-1] == L
'\\') break;
152 SubKeyString
.Length
-= sizeof(*p1
);
154 SubKeyString
.Buffer
= p1
;
155 SubKeyString
.Length
= SubKey
->Length
- SubKeyString
.Length
;
157 /* Setup the object attributes */
158 InitializeObjectAttributes(&ObjectAttributes
,
160 OBJ_CASE_INSENSITIVE
,
164 /* Open the setting key */
165 Status
= ZwOpenKey((PHANDLE
)NewKeyHandle
, GENERIC_READ
, &ObjectAttributes
);
168 /* Return to caller */
177 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle
,
182 OUT PULONG ReturnedLength OPTIONAL
)
185 UNICODE_STRING ValueNameString
, IntegerString
;
186 ULONG KeyInfoSize
, ResultSize
;
187 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)&KeyInfo
;
188 BOOLEAN FreeHeap
= FALSE
;
191 /* Build a string for the value name */
192 Status
= RtlInitUnicodeStringEx(&ValueNameString
, ValueName
);
193 if (!NT_SUCCESS(Status
)) return Status
;
195 /* Query the value */
196 Status
= ZwQueryValueKey(KeyHandle
,
198 KeyValuePartialInformation
,
202 if (Status
== STATUS_BUFFER_OVERFLOW
)
204 /* Our local buffer wasn't enough, allocate one */
205 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
206 KeyValueInformation
->DataLength
;
207 KeyValueInformation
= RtlAllocateHeap(RtlGetProcessHeap(),
210 if (KeyValueInformation
!= NULL
)
213 Status
= ZwQueryValueKey(KeyHandle
,
215 KeyValuePartialInformation
,
223 /* Give up this time */
224 Status
= STATUS_NO_MEMORY
;
228 /* Check for success */
229 if (NT_SUCCESS(Status
))
231 /* Handle binary data */
232 if (KeyValueInformation
->Type
== REG_BINARY
)
235 if ((Buffer
) && (KeyValueInformation
->DataLength
<= BufferSize
))
237 /* Copy into buffer */
238 RtlMoveMemory(Buffer
,
239 &KeyValueInformation
->Data
,
240 KeyValueInformation
->DataLength
);
244 Status
= STATUS_BUFFER_OVERFLOW
;
247 /* Copy the result length */
248 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
250 else if (KeyValueInformation
->Type
== REG_DWORD
)
252 /* Check for valid type */
253 if (KeyValueInformation
->Type
!= Type
)
256 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
262 (BufferSize
== sizeof(ULONG
)) &&
263 (KeyValueInformation
->DataLength
<= BufferSize
))
265 /* Copy into buffer */
266 RtlMoveMemory(Buffer
,
267 &KeyValueInformation
->Data
,
268 KeyValueInformation
->DataLength
);
272 Status
= STATUS_BUFFER_OVERFLOW
;
275 /* Copy the result length */
276 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
279 else if (KeyValueInformation
->Type
!= REG_SZ
)
281 /* We got something weird */
282 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
286 /* String, check what you requested */
287 if (Type
== REG_DWORD
)
290 if (BufferSize
!= sizeof(ULONG
))
294 Status
= STATUS_INFO_LENGTH_MISMATCH
;
298 /* OK, we know what you want... */
299 IntegerString
.Buffer
= (PWSTR
)KeyValueInformation
->Data
;
300 IntegerString
.Length
= (USHORT
)KeyValueInformation
->DataLength
-
302 IntegerString
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
303 Status
= RtlUnicodeStringToInteger(&IntegerString
, 0, (PULONG
)Buffer
);
309 if (KeyValueInformation
->DataLength
> BufferSize
)
312 Status
= STATUS_BUFFER_OVERFLOW
;
317 BufferSize
= KeyValueInformation
->DataLength
;
320 /* Copy the string */
321 RtlMoveMemory(Buffer
, &KeyValueInformation
->Data
, BufferSize
);
324 /* Copy the result length */
325 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
329 /* Check if buffer was in heap */
330 if (FreeHeap
) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation
);
341 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey
,
346 OUT PULONG ReturnedLength OPTIONAL
,
352 /* Open a handle to the key */
353 Status
= LdrOpenImageFileOptionsKey(SubKey
, Wow64
, &KeyHandle
);
355 /* Check for success */
356 if (NT_SUCCESS(Status
))
359 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
370 /* Return to caller */
379 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey
,
384 OUT PULONG ReturnedLength OPTIONAL
)
386 /* Call the newer function */
387 return LdrQueryImageFileExecutionOptionsEx(SubKey
,
398 LdrpEnsureLoaderLockIsHeld(VOID
)
405 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress
, ULONG SizeOfImage
)
407 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir
;
411 /* Check NT header first */
412 if (!RtlImageNtHeader(BaseAddress
)) return NULL
;
414 /* Get the pointer to the config directory */
415 ConfigDir
= RtlImageDirectoryEntryToData(BaseAddress
,
417 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
420 /* Check for sanity */
422 (DirSize
!= 64 && ConfigDir
->Size
!= DirSize
) ||
423 (ConfigDir
->Size
< 0x48))
426 /* Now get the cookie */
427 Cookie
= (PVOID
)ConfigDir
->SecurityCookie
;
429 /* Check this cookie */
430 if ((PCHAR
)Cookie
<= (PCHAR
)BaseAddress
||
431 (PCHAR
)Cookie
>= (PCHAR
)BaseAddress
+ SizeOfImage
)
436 /* Return validated security cookie */
442 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry
)
445 LARGE_INTEGER Counter
;
448 /* Fetch address of the cookie */
449 Cookie
= LdrpFetchAddressOfSecurityCookie(LdrEntry
->DllBase
, LdrEntry
->SizeOfImage
);
453 /* Check if it's a default one */
454 if ((*Cookie
== DEFAULT_SECURITY_COOKIE
) ||
457 /* Make up a cookie from a bunch of values which may uniquely represent
458 current moment of time, environment, etc */
459 NtQueryPerformanceCounter(&Counter
, NULL
);
461 NewCookie
= Counter
.LowPart
^ Counter
.HighPart
;
462 NewCookie
^= (ULONG
)NtCurrentTeb()->ClientId
.UniqueProcess
;
463 NewCookie
^= (ULONG
)NtCurrentTeb()->ClientId
.UniqueThread
;
465 /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */
466 while (SharedUserData
->SystemTime
.High1Time
!= SharedUserData
->SystemTime
.High2Time
)
471 /* Calculate the milliseconds value and xor it to the cookie */
472 NewCookie
^= Int64ShrlMod32(UInt32x32To64(SharedUserData
->TickCountMultiplier
, SharedUserData
->TickCount
.LowPart
), 24) +
473 (SharedUserData
->TickCountMultiplier
* (SharedUserData
->TickCount
.High1Time
<< 8));
475 /* Make the cookie 16bit if necessary */
476 if (*Cookie
== 0xBB40) NewCookie
&= 0xFFFF;
478 /* If the result is 0 or the same as we got, just subtract one from the existing value
480 if ((NewCookie
== 0) || (NewCookie
== *Cookie
))
482 NewCookie
= *Cookie
- 1;
485 /* Set the new cookie value */
495 LdrpInitializeThread(IN PCONTEXT Context
)
497 PPEB Peb
= NtCurrentPeb();
498 PLDR_DATA_TABLE_ENTRY LdrEntry
;
499 PLIST_ENTRY NextEntry
, ListHead
;
500 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
504 DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n",
505 &LdrpImageEntry
->BaseDllName
,
506 NtCurrentTeb()->RealClientId
.UniqueProcess
,
507 NtCurrentTeb()->RealClientId
.UniqueThread
);
509 /* Allocate an Activation Context Stack */
510 DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer
);
511 Status
= RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer
);
512 if (!NT_SUCCESS(Status
))
514 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
517 /* Make sure we are not shutting down */
518 if (LdrpShutdownInProgress
) return;
523 /* Start at the beginning */
524 ListHead
= &Peb
->Ldr
->InMemoryOrderModuleList
;
525 NextEntry
= ListHead
->Flink
;
526 while (NextEntry
!= ListHead
)
528 /* Get the current entry */
529 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InMemoryOrderLinks
);
531 /* Make sure it's not ourselves */
532 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
534 /* Check if we should call */
535 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
))
537 /* Get the entrypoint */
538 EntryPoint
= LdrEntry
->EntryPoint
;
540 /* Check if we are ready to call it */
542 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
543 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
545 /* Set up the Act Ctx */
546 ActCtx
.Size
= sizeof(ActCtx
);
548 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
550 /* Activate the ActCtx */
551 RtlActivateActivationContextUnsafeFast(&ActCtx
,
552 LdrEntry
->EntryPointActivationContext
);
554 /* Check if it has TLS */
555 if (LdrEntry
->TlsIndex
)
557 /* Make sure we're not shutting down */
558 if (!LdrpShutdownInProgress
)
561 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_THREAD_ATTACH
);
565 /* Make sure we're not shutting down */
566 if (!LdrpShutdownInProgress
)
568 /* Call the Entrypoint */
569 DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n",
570 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
,
571 NtCurrentTeb()->RealClientId
.UniqueProcess
,
572 NtCurrentTeb()->RealClientId
.UniqueThread
);
573 LdrpCallInitRoutine(LdrEntry
->EntryPoint
,
579 /* Deactivate the ActCtx */
580 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
586 NextEntry
= NextEntry
->Flink
;
590 if (LdrpImageHasTls
&& !LdrpShutdownInProgress
)
592 /* Set up the Act Ctx */
593 ActCtx
.Size
= sizeof(ActCtx
);
595 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
597 /* Activate the ActCtx */
598 RtlActivateActivationContextUnsafeFast(&ActCtx
,
599 LdrpImageEntry
->EntryPointActivationContext
);
601 /* Do TLS callbacks */
602 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_THREAD_ATTACH
);
604 /* Deactivate the ActCtx */
605 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
608 DPRINT("LdrpInitializeThread() done\n");
613 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL
)
615 PLDR_DATA_TABLE_ENTRY LocalArray
[16];
616 PLIST_ENTRY ListHead
;
617 PLIST_ENTRY NextEntry
;
618 PLDR_DATA_TABLE_ENTRY LdrEntry
, *LdrRootEntry
, OldInitializer
;
622 NTSTATUS Status
= STATUS_SUCCESS
;
623 PPEB Peb
= NtCurrentPeb();
624 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
625 ULONG BreakOnDllLoad
;
629 DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
630 &LdrpImageEntry
->BaseDllName
,
631 NtCurrentTeb()->RealClientId
.UniqueProcess
,
632 NtCurrentTeb()->RealClientId
.UniqueThread
);
634 /* Check the Loader Lock */
635 LdrpEnsureLoaderLockIsHeld();
637 /* Get the number of entries to call */
638 if ((Count
= LdrpClearLoadInProgress()))
640 /* Check if we can use our local buffer */
643 /* Allocate space for all the entries */
644 LdrRootEntry
= RtlAllocateHeap(RtlGetProcessHeap(),
646 Count
* sizeof(*LdrRootEntry
));
647 if (!LdrRootEntry
) return STATUS_NO_MEMORY
;
651 /* Use our local array */
652 LdrRootEntry
= LocalArray
;
661 /* Show debug message */
664 DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
665 NtCurrentTeb()->RealClientId
.UniqueThread
,
666 NtCurrentTeb()->RealClientId
.UniqueProcess
,
667 &Peb
->ProcessParameters
->ImagePathName
);
671 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
672 NextEntry
= ListHead
->Flink
;
674 while (NextEntry
!= ListHead
)
676 /* Get the Data Entry */
677 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
679 /* Check if we have a Root Entry */
683 if (!(LdrEntry
->Flags
& LDRP_ENTRY_PROCESSED
))
685 /* Setup the Cookie for the DLL */
686 LdrpInitSecurityCookie(LdrEntry
);
688 /* Check for valid entrypoint */
689 if (LdrEntry
->EntryPoint
)
693 LdrRootEntry
[i
] = LdrEntry
;
695 /* Display debug message */
698 DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
699 NtCurrentTeb()->RealClientId
.UniqueThread
,
700 NtCurrentTeb()->RealClientId
.UniqueProcess
,
701 &LdrEntry
->FullDllName
,
702 LdrEntry
->EntryPoint
);
710 LdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
711 NextEntry
= NextEntry
->Flink
;
714 /* If we got a context, then we have to call Kernel32 for TS support */
717 /* Check if we have one */
718 //if (Kernel32ProcessInitPostImportfunction)
721 //Kernel32ProcessInitPostImportfunction();
725 //Kernel32ProcessInitPostImportfunction = NULL;
729 /* No root entry? return */
730 if (!LdrRootEntry
) return STATUS_SUCCESS
;
732 /* Set the TLD TEB */
733 OldTldTeb
= LdrpTopLevelDllBeingLoadedTeb
;
734 LdrpTopLevelDllBeingLoadedTeb
= NtCurrentTeb();
741 LdrEntry
= LdrRootEntry
[i
];
743 /* FIXME: Verify NX Compat */
745 /* Move to next entry */
748 /* Get its entrypoint */
749 EntryPoint
= LdrEntry
->EntryPoint
;
751 /* Are we being debugged? */
753 if (Peb
->BeingDebugged
|| Peb
->ReadImageFileExecOptions
)
755 /* Check if we should break on load */
756 Status
= LdrQueryImageFileExecutionOptions(&LdrEntry
->BaseDllName
,
762 if (!NT_SUCCESS(Status
)) BreakOnDllLoad
= 0;
764 /* Reset status back to STATUS_SUCCESS */
765 Status
= STATUS_SUCCESS
;
771 /* Check if we should show a message */
774 DPRINT1("LDR: %wZ loaded.", &LdrEntry
->BaseDllName
);
775 DPRINT1(" - About to call init routine at %p\n", EntryPoint
);
778 /* Break in debugger */
782 /* Make sure we have an entrypoint */
785 /* Save the old Dll Initializer and write the current one */
786 OldInitializer
= LdrpCurrentDllInitializer
;
787 LdrpCurrentDllInitializer
= LdrEntry
;
789 /* Set up the Act Ctx */
790 ActCtx
.Size
= sizeof(ActCtx
);
792 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
794 /* Activate the ActCtx */
795 RtlActivateActivationContextUnsafeFast(&ActCtx
,
796 LdrEntry
->EntryPointActivationContext
);
798 /* Check if it has TLS */
799 if (LdrEntry
->TlsIndex
&& Context
)
802 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_PROCESS_ATTACH
);
805 /* Call the Entrypoint */
808 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
809 &LdrEntry
->BaseDllName
, EntryPoint
);
811 DllStatus
= LdrpCallInitRoutine(EntryPoint
,
816 /* Deactivate the ActCtx */
817 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
819 /* Save the Current DLL Initializer */
820 LdrpCurrentDllInitializer
= OldInitializer
;
822 /* Mark the entry as processed */
823 LdrEntry
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
;
825 /* Fail if DLL init failed */
828 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
829 &LdrEntry
->BaseDllName
, EntryPoint
);
831 Status
= STATUS_DLL_INIT_FAILED
;
838 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
839 NextEntry
= NextEntry
->Flink
;
840 while (NextEntry
!= ListHead
)
842 /* Get the Data Entry */
843 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
845 /* FIXME: Verify NX Compat */
846 // LdrpCheckNXCompatibility()
849 NextEntry
= NextEntry
->Flink
;
853 if (LdrpImageHasTls
&& Context
)
855 /* Set up the Act Ctx */
856 ActCtx
.Size
= sizeof(ActCtx
);
858 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
860 /* Activate the ActCtx */
861 RtlActivateActivationContextUnsafeFast(&ActCtx
,
862 LdrpImageEntry
->EntryPointActivationContext
);
864 /* Do TLS callbacks */
865 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_PROCESS_ATTACH
);
867 /* Deactivate the ActCtx */
868 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
872 /* Restore old TEB */
873 LdrpTopLevelDllBeingLoadedTeb
= OldTldTeb
;
875 /* Check if the array is in the heap */
876 if (LdrRootEntry
!= LocalArray
)
879 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry
);
882 /* Return to caller */
883 DPRINT("LdrpRunInitializeRoutines() done\n");
892 LdrShutdownProcess(VOID
)
894 PPEB Peb
= NtCurrentPeb();
895 PLDR_DATA_TABLE_ENTRY LdrEntry
;
896 PLIST_ENTRY NextEntry
, ListHead
;
897 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
900 DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry
->BaseDllName
);
901 if (LdrpShutdownInProgress
) return STATUS_SUCCESS
;
903 /* Tell the Shim Engine */
906 VOID(NTAPI
*SE_ProcessDying
)();
907 SE_ProcessDying
= RtlDecodeSystemPointer(g_pfnSE_ProcessDying
);
917 /* Set the shutdown variables */
918 LdrpShutdownThreadId
= NtCurrentTeb()->RealClientId
.UniqueThread
;
919 LdrpShutdownInProgress
= TRUE
;
921 /* Enter the Loader Lock */
922 RtlEnterCriticalSection(&LdrpLoaderLock
);
924 /* Cleanup trace logging data (Etw) */
925 if (SharedUserData
->TraceLogging
)
928 DPRINT1("We don't support Etw yet.\n");
931 /* Start at the end */
932 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
933 NextEntry
= ListHead
->Blink
;
934 while (NextEntry
!= ListHead
)
936 /* Get the current entry */
937 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
938 NextEntry
= NextEntry
->Blink
;
940 /* Make sure it's not ourselves */
941 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
943 /* Get the entrypoint */
944 EntryPoint
= LdrEntry
->EntryPoint
;
946 /* Check if we are ready to call it */
948 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
951 /* Set up the Act Ctx */
952 ActCtx
.Size
= sizeof(ActCtx
);
954 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
956 /* Activate the ActCtx */
957 RtlActivateActivationContextUnsafeFast(&ActCtx
,
958 LdrEntry
->EntryPointActivationContext
);
960 /* Check if it has TLS */
961 if (LdrEntry
->TlsIndex
)
964 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_PROCESS_DETACH
);
967 /* Call the Entrypoint */
968 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
969 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
970 LdrpCallInitRoutine(EntryPoint
,
975 /* Deactivate the ActCtx */
976 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
984 /* Set up the Act Ctx */
985 ActCtx
.Size
= sizeof(ActCtx
);
987 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
989 /* Activate the ActCtx */
990 RtlActivateActivationContextUnsafeFast(&ActCtx
,
991 LdrpImageEntry
->EntryPointActivationContext
);
993 /* Do TLS callbacks */
994 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_PROCESS_DETACH
);
996 /* Deactivate the ActCtx */
997 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1000 /* FIXME: Do Heap detection and Etw final shutdown */
1002 /* Release the lock */
1003 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1004 DPRINT("LdrpShutdownProcess() done\n");
1006 return STATUS_SUCCESS
;
1014 LdrShutdownThread(VOID
)
1016 PPEB Peb
= NtCurrentPeb();
1017 PTEB Teb
= NtCurrentTeb();
1018 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1019 PLIST_ENTRY NextEntry
, ListHead
;
1020 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
1023 DPRINT("LdrShutdownThread() called for %wZ\n",
1024 &LdrpImageEntry
->BaseDllName
);
1026 /* Cleanup trace logging data (Etw) */
1027 if (SharedUserData
->TraceLogging
)
1030 DPRINT1("We don't support Etw yet.\n");
1033 /* Get the Ldr Lock */
1034 RtlEnterCriticalSection(&LdrpLoaderLock
);
1036 /* Start at the end */
1037 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
1038 NextEntry
= ListHead
->Blink
;
1039 while (NextEntry
!= ListHead
)
1041 /* Get the current entry */
1042 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
1043 NextEntry
= NextEntry
->Blink
;
1045 /* Make sure it's not ourselves */
1046 if (Peb
->ImageBaseAddress
!= LdrEntry
->DllBase
)
1048 /* Check if we should call */
1049 if (!(LdrEntry
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
1050 (LdrEntry
->Flags
& LDRP_PROCESS_ATTACH_CALLED
) &&
1051 (LdrEntry
->Flags
& LDRP_IMAGE_DLL
))
1053 /* Get the entrypoint */
1054 EntryPoint
= LdrEntry
->EntryPoint
;
1056 /* Check if we are ready to call it */
1059 /* Set up the Act Ctx */
1060 ActCtx
.Size
= sizeof(ActCtx
);
1062 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1064 /* Activate the ActCtx */
1065 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1066 LdrEntry
->EntryPointActivationContext
);
1068 /* Check if it has TLS */
1069 if (LdrEntry
->TlsIndex
)
1071 /* Make sure we're not shutting down */
1072 if (!LdrpShutdownInProgress
)
1075 LdrpCallTlsInitializers(LdrEntry
->DllBase
, DLL_THREAD_DETACH
);
1079 /* Make sure we're not shutting down */
1080 if (!LdrpShutdownInProgress
)
1082 /* Call the Entrypoint */
1083 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1084 &LdrEntry
->BaseDllName
, LdrEntry
->EntryPoint
);
1085 LdrpCallInitRoutine(EntryPoint
,
1091 /* Deactivate the ActCtx */
1092 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1099 if (LdrpImageHasTls
)
1101 /* Set up the Act Ctx */
1102 ActCtx
.Size
= sizeof(ActCtx
);
1104 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
1106 /* Activate the ActCtx */
1107 RtlActivateActivationContextUnsafeFast(&ActCtx
,
1108 LdrpImageEntry
->EntryPointActivationContext
);
1110 /* Do TLS callbacks */
1111 LdrpCallTlsInitializers(Peb
->ImageBaseAddress
, DLL_THREAD_DETACH
);
1113 /* Deactivate the ActCtx */
1114 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
1119 RtlLeaveCriticalSection(&LdrpLoaderLock
);
1121 /* Check for expansion slots */
1122 if (Teb
->TlsExpansionSlots
)
1124 /* Free expansion slots */
1125 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->TlsExpansionSlots
);
1128 /* Check for FLS Data */
1132 DPRINT1("We don't support FLS Data yet\n");
1135 /* Check for Fiber data */
1136 if (Teb
->HasFiberData
)
1138 /* Free Fiber data*/
1139 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb
->NtTib
.FiberData
);
1140 Teb
->NtTib
.FiberData
= NULL
;
1143 /* Free the activation context stack */
1144 RtlFreeThreadActivationContextStack();
1145 DPRINT("LdrShutdownThread() done\n");
1147 return STATUS_SUCCESS
;
1152 LdrpInitializeTls(VOID
)
1154 PLIST_ENTRY NextEntry
, ListHead
;
1155 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1156 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1157 PLDRP_TLS_DATA TlsData
;
1160 /* Initialize the TLS List */
1161 InitializeListHead(&LdrpTlsList
);
1163 /* Loop all the modules */
1164 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1165 NextEntry
= ListHead
->Flink
;
1166 while (ListHead
!= NextEntry
)
1169 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1170 NextEntry
= NextEntry
->Flink
;
1172 /* Get the TLS directory */
1173 TlsDirectory
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
1175 IMAGE_DIRECTORY_ENTRY_TLS
,
1178 /* Check if we have a directory */
1179 if (!TlsDirectory
) continue;
1181 /* Check if the image has TLS */
1182 if (!LdrpImageHasTls
) LdrpImageHasTls
= TRUE
;
1184 /* Show debug message */
1187 DPRINT1("LDR: Tls Found in %wZ at %p\n",
1188 &LdrEntry
->BaseDllName
,
1192 /* Allocate an entry */
1193 TlsData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA
));
1194 if (!TlsData
) return STATUS_NO_MEMORY
;
1196 /* Lock the DLL and mark it for TLS Usage */
1197 LdrEntry
->LoadCount
= -1;
1198 LdrEntry
->TlsIndex
= -1;
1200 /* Save the cached TLS data */
1201 TlsData
->TlsDirectory
= *TlsDirectory
;
1202 InsertTailList(&LdrpTlsList
, &TlsData
->TlsLinks
);
1204 /* Update the index */
1205 *(PLONG
)TlsData
->TlsDirectory
.AddressOfIndex
= LdrpNumberOfTlsEntries
;
1206 TlsData
->TlsDirectory
.Characteristics
= LdrpNumberOfTlsEntries
++;
1209 /* Done setting up TLS, allocate entries */
1210 return LdrpAllocateTls();
1215 LdrpAllocateTls(VOID
)
1217 PTEB Teb
= NtCurrentTeb();
1218 PLIST_ENTRY NextEntry
, ListHead
;
1219 PLDRP_TLS_DATA TlsData
;
1223 /* Check if we have any entries */
1224 if (!LdrpNumberOfTlsEntries
)
1225 return STATUS_SUCCESS
;
1227 /* Allocate the vector array */
1228 TlsVector
= RtlAllocateHeap(RtlGetProcessHeap(),
1230 LdrpNumberOfTlsEntries
* sizeof(PVOID
));
1231 if (!TlsVector
) return STATUS_NO_MEMORY
;
1232 Teb
->ThreadLocalStoragePointer
= TlsVector
;
1234 /* Loop the TLS Array */
1235 ListHead
= &LdrpTlsList
;
1236 NextEntry
= ListHead
->Flink
;
1237 while (NextEntry
!= ListHead
)
1240 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1241 NextEntry
= NextEntry
->Flink
;
1243 /* Allocate this vector */
1244 TlsDataSize
= TlsData
->TlsDirectory
.EndAddressOfRawData
-
1245 TlsData
->TlsDirectory
.StartAddressOfRawData
;
1246 TlsVector
[TlsData
->TlsDirectory
.Characteristics
] = RtlAllocateHeap(RtlGetProcessHeap(),
1249 if (!TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1252 return STATUS_NO_MEMORY
;
1255 /* Show debug message */
1258 DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
1260 TlsData
->TlsDirectory
.Characteristics
,
1261 &TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1262 TlsData
->TlsDirectory
.StartAddressOfRawData
,
1263 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1267 RtlCopyMemory(TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
1268 (PVOID
)TlsData
->TlsDirectory
.StartAddressOfRawData
,
1273 return STATUS_SUCCESS
;
1280 PLIST_ENTRY ListHead
, NextEntry
;
1281 PLDRP_TLS_DATA TlsData
;
1283 PTEB Teb
= NtCurrentTeb();
1285 /* Get a pointer to the vector array */
1286 TlsVector
= Teb
->ThreadLocalStoragePointer
;
1287 if (!TlsVector
) return;
1289 /* Loop through it */
1290 ListHead
= &LdrpTlsList
;
1291 NextEntry
= ListHead
->Flink
;
1292 while (NextEntry
!= ListHead
)
1294 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
1295 NextEntry
= NextEntry
->Flink
;
1297 /* Free each entry */
1298 if (TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
1300 RtlFreeHeap(RtlGetProcessHeap(),
1302 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
1306 /* Free the array itself */
1307 RtlFreeHeap(RtlGetProcessHeap(),
1314 LdrpInitializeApplicationVerifierPackage(PUNICODE_STRING ImagePathName
, PPEB Peb
, BOOLEAN SystemWide
, BOOLEAN ReadAdvancedOptions
)
1316 /* If global flags request DPH, perform some additional actions */
1317 if (Peb
->NtGlobalFlag
& FLG_HEAP_PAGE_ALLOCS
)
1319 // TODO: Read advanced DPH flags from the registry if requested
1320 if (ReadAdvancedOptions
)
1325 /* Enable page heap */
1326 RtlpPageHeapEnabled
= TRUE
;
1329 return STATUS_SUCCESS
;
1334 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName
, PPEB Peb
, PHANDLE OptionsKey
)
1338 ULONG ExecuteOptions
, MinimumStackCommit
= 0, GlobalFlag
;
1340 /* Return error if we were not provided a pointer where to save the options key handle */
1341 if (!OptionsKey
) return STATUS_INVALID_HANDLE
;
1343 /* Zero initialize the options key pointer */
1346 /* Open the options key */
1347 Status
= LdrOpenImageFileOptionsKey(ImagePathName
, 0, &KeyHandle
);
1349 /* Save it if it was opened successfully */
1350 if (NT_SUCCESS(Status
))
1351 *OptionsKey
= KeyHandle
;
1355 /* There are image specific options, read them starting with NXCOMPAT */
1356 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1360 sizeof(ExecuteOptions
),
1363 if (NT_SUCCESS(Status
))
1365 /* TODO: Set execution options for the process */
1367 if (ExecuteOptions == 0)
1371 ZwSetInformationProcess(NtCurrentProcess(),
1372 ProcessExecuteFlags,
1378 /* Check if this image uses large pages */
1379 if (Peb
->ImageUsesLargePages
)
1381 /* TODO: If it does, open large page key */
1385 /* Get various option values */
1386 LdrQueryImageFileKeyOption(KeyHandle
,
1387 L
"DisableHeapLookaside",
1389 &RtlpDisableHeapLookaside
,
1390 sizeof(RtlpDisableHeapLookaside
),
1393 LdrQueryImageFileKeyOption(KeyHandle
,
1396 &RtlpShutdownProcessFlags
,
1397 sizeof(RtlpShutdownProcessFlags
),
1400 LdrQueryImageFileKeyOption(KeyHandle
,
1401 L
"MinimumStackCommitInBytes",
1403 &MinimumStackCommit
,
1404 sizeof(MinimumStackCommit
),
1407 /* Update PEB's minimum stack commit if it's lower */
1408 if (Peb
->MinimumStackCommit
< MinimumStackCommit
)
1409 Peb
->MinimumStackCommit
= MinimumStackCommit
;
1411 /* Set the global flag */
1412 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
1419 if (NT_SUCCESS(Status
))
1420 Peb
->NtGlobalFlag
= GlobalFlag
;
1424 /* Call AVRF if necessary */
1425 if (Peb
->NtGlobalFlag
& (FLG_POOL_ENABLE_TAIL_CHECK
| FLG_HEAP_PAGE_ALLOCS
))
1427 Status
= LdrpInitializeApplicationVerifierPackage(ImagePathName
, Peb
, TRUE
, FALSE
);
1428 if (!NT_SUCCESS(Status
))
1430 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1436 /* There are no image-specific options, so perform global initialization */
1437 if (Peb
->NtGlobalFlag
& (FLG_POOL_ENABLE_TAIL_CHECK
| FLG_HEAP_PAGE_ALLOCS
))
1439 /* Initialize app verifier package */
1440 Status
= LdrpInitializeApplicationVerifierPackage(ImagePathName
, Peb
, TRUE
, FALSE
);
1441 if (!NT_SUCCESS(Status
))
1443 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status
);
1448 return STATUS_SUCCESS
;
1453 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
)
1460 LdrpInitializeProcess(IN PCONTEXT Context
,
1461 IN PVOID SystemArgument1
)
1463 RTL_HEAP_PARAMETERS HeapParameters
;
1464 ULONG ComSectionSize
;
1465 //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData");
1467 OBJECT_ATTRIBUTES ObjectAttributes
;
1468 //UNICODE_STRING LocalFileName, FullImageName;
1469 HANDLE SymLinkHandle
;
1470 //ULONG DebugHeapOnly;
1471 UNICODE_STRING CommandLine
, NtSystemRoot
, ImagePathName
, FullPath
, ImageFileName
, KnownDllString
;
1472 PPEB Peb
= NtCurrentPeb();
1473 BOOLEAN IsDotNetImage
= FALSE
;
1474 BOOLEAN FreeCurDir
= FALSE
;
1476 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1477 //LPWSTR ImagePathBuffer;
1479 UNICODE_STRING CurrentDirectory
;
1482 PIMAGE_NT_HEADERS NtHeader
;
1483 LPWSTR NtDllName
= NULL
;
1484 NTSTATUS Status
, ImportStatus
;
1485 NLSTABLEINFO NlsTable
;
1486 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig
;
1487 PTEB Teb
= NtCurrentTeb();
1488 PLIST_ENTRY ListHead
;
1489 PLIST_ENTRY NextEntry
;
1492 ULONG DebugProcessHeapOnly
= 0;
1493 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
1495 ULONG ExecuteOptions
= 0;
1498 /* Set a NULL SEH Filter */
1499 RtlSetUnhandledExceptionFilter(NULL
);
1501 /* Get the image path */
1502 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
1504 /* Check if it's not normalized */
1505 if (!(Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
))
1508 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
1511 /* Create a unicode string for the Image Path */
1512 ImagePathName
.Length
= Peb
->ProcessParameters
->ImagePathName
.Length
;
1513 ImagePathName
.MaximumLength
= ImagePathName
.Length
+ sizeof(WCHAR
);
1514 ImagePathName
.Buffer
= ImagePath
;
1516 /* Get the NT Headers */
1517 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
1519 /* Get the execution options */
1520 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &OptionsKey
);
1522 /* Check if this is a .NET executable */
1523 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1525 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
1528 /* Remember this for later */
1529 IsDotNetImage
= TRUE
;
1532 /* Save the NTDLL Base address */
1533 NtDllBase
= SystemArgument1
;
1535 /* If this is a Native Image */
1536 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
1538 /* Then do DLL Validation */
1539 LdrpDllValidation
= TRUE
;
1542 /* Save the old Shim Data */
1543 OldShimData
= Peb
->pShimData
;
1546 Peb
->pShimData
= NULL
;
1548 /* Save the number of processors and CS Timeout */
1549 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
1550 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
1552 /* Normalize the parameters */
1553 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
1554 if (ProcessParameters
)
1556 /* Save the Image and Command Line Names */
1557 ImageFileName
= ProcessParameters
->ImagePathName
;
1558 CommandLine
= ProcessParameters
->CommandLine
;
1562 /* It failed, initialize empty strings */
1563 RtlInitUnicodeString(&ImageFileName
, NULL
);
1564 RtlInitUnicodeString(&CommandLine
, NULL
);
1567 /* Initialize NLS data */
1568 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1569 Peb
->OemCodePageData
,
1570 Peb
->UnicodeCaseTableData
,
1573 /* Reset NLS Translations */
1574 RtlResetRtlTranslations(&NlsTable
);
1576 /* Get the Image Config Directory */
1577 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1579 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1582 /* Setup the Heap Parameters */
1583 RtlZeroMemory(&HeapParameters
, sizeof(RTL_HEAP_PARAMETERS
));
1584 HeapFlags
= HEAP_GROWABLE
;
1585 HeapParameters
.Length
= sizeof(RTL_HEAP_PARAMETERS
);
1587 /* Check if we have Configuration Data */
1588 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1590 /* FIXME: Custom heap settings and misc. */
1591 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1594 /* Check for custom affinity mask */
1595 if (Peb
->ImageProcessAffinityMask
)
1598 Status
= NtSetInformationProcess(NtCurrentProcess(),
1599 ProcessAffinityMask
,
1600 &Peb
->ImageProcessAffinityMask
,
1601 sizeof(Peb
->ImageProcessAffinityMask
));
1604 /* Check if verbose debugging (ShowSnaps) was requested */
1605 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1607 /* Start verbose debugging messages right now if they were requested */
1610 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1611 Teb
->ClientId
.UniqueProcess
,
1615 /* If the timeout is too long */
1616 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1618 /* Then disable CS Timeout */
1619 RtlpTimeoutDisable
= TRUE
;
1622 /* Initialize Critical Section Data */
1623 RtlpInitDeferedCriticalSection();
1625 /* Initialize VEH Call lists */
1626 RtlpInitializeVectoredExceptionHandling();
1628 /* Set TLS/FLS Bitmap data */
1629 Peb
->FlsBitmap
= &FlsBitMap
;
1630 Peb
->TlsBitmap
= &TlsBitMap
;
1631 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1633 /* Initialize FLS Bitmap */
1634 RtlInitializeBitMap(&FlsBitMap
,
1636 FLS_MAXIMUM_AVAILABLE
);
1637 RtlSetBit(&FlsBitMap
, 0);
1639 /* Initialize TLS Bitmap */
1640 RtlInitializeBitMap(&TlsBitMap
,
1642 TLS_MINIMUM_AVAILABLE
);
1643 RtlSetBit(&TlsBitMap
, 0);
1644 RtlInitializeBitMap(&TlsExpansionBitMap
,
1645 Peb
->TlsExpansionBitmapBits
,
1646 TLS_EXPANSION_SLOTS
);
1647 RtlSetBit(&TlsExpansionBitMap
, 0);
1649 /* Initialize the Hash Table */
1650 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1652 InitializeListHead(&LdrpHashTable
[i
]);
1655 /* Initialize the Loader Lock */
1656 // FIXME: What's the point of initing it manually, if two lines lower
1657 // a call to RtlInitializeCriticalSection() is being made anyway?
1658 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1659 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1660 RtlInitializeCriticalSection(&LdrpLoaderLock
);
1661 LdrpLoaderLockInit
= TRUE
;
1663 /* Check if User Stack Trace Database support was requested */
1664 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1666 DPRINT1("We don't support user stack trace databases yet\n");
1669 /* Setup Fast PEB Lock */
1670 RtlInitializeCriticalSection(&FastPebLock
);
1671 Peb
->FastPebLock
= &FastPebLock
;
1672 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1673 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1675 /* Setup Callout Lock and Notification list */
1676 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1677 InitializeListHead(&LdrpDllNotificationList
);
1679 /* For old executables, use 16-byte aligned heap */
1680 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1681 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1683 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1686 /* Setup the Heap */
1687 RtlInitializeHeapManager();
1688 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1690 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1691 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1695 if (!Peb
->ProcessHeap
)
1697 DPRINT1("Failed to create process heap\n");
1698 return STATUS_NO_MEMORY
;
1701 /* Allocate an Activation Context Stack */
1702 Status
= RtlAllocateActivationContextStack(&Teb
->ActivationContextStackPointer
);
1703 if (!NT_SUCCESS(Status
)) return Status
;
1705 // FIXME: Loader private heap is missing
1706 //DPRINT1("Loader private heap is missing\n");
1708 /* Check for Debug Heap */
1711 /* Query the setting */
1712 Status
= LdrQueryImageFileKeyOption(OptionsKey
,
1713 L
"DebugProcessHeapOnly",
1715 &DebugProcessHeapOnly
,
1719 if (NT_SUCCESS(Status
))
1721 /* Reset DPH if requested */
1722 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1724 RtlpDphGlobalFlags
&= ~DPH_FLAG_DLL_NOTIFY
;
1725 RtlpPageHeapEnabled
= FALSE
;
1730 /* Build the NTDLL Path */
1731 FullPath
.Buffer
= StringBuffer
;
1732 FullPath
.Length
= 0;
1733 FullPath
.MaximumLength
= sizeof(StringBuffer
);
1734 RtlInitUnicodeString(&NtSystemRoot
, SharedUserData
->NtSystemRoot
);
1735 RtlAppendUnicodeStringToString(&FullPath
, &NtSystemRoot
);
1736 RtlAppendUnicodeToString(&FullPath
, L
"\\System32\\");
1738 /* Open the Known DLLs directory */
1739 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1740 InitializeObjectAttributes(&ObjectAttributes
,
1742 OBJ_CASE_INSENSITIVE
,
1745 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
1746 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
1749 /* Check if it exists */
1750 if (NT_SUCCESS(Status
))
1752 /* Open the Known DLLs Path */
1753 RtlInitUnicodeString(&KnownDllString
, L
"KnownDllPath");
1754 InitializeObjectAttributes(&ObjectAttributes
,
1756 OBJ_CASE_INSENSITIVE
,
1757 LdrpKnownDllObjectDirectory
,
1759 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
1760 SYMBOLIC_LINK_QUERY
,
1762 if (NT_SUCCESS(Status
))
1764 /* Query the path */
1765 LdrpKnownDllPath
.Length
= 0;
1766 LdrpKnownDllPath
.MaximumLength
= sizeof(LdrpKnownDllPathBuffer
);
1767 LdrpKnownDllPath
.Buffer
= LdrpKnownDllPathBuffer
;
1768 Status
= ZwQuerySymbolicLinkObject(SymLinkHandle
, &LdrpKnownDllPath
, NULL
);
1769 NtClose(SymLinkHandle
);
1770 if (!NT_SUCCESS(Status
))
1772 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
1778 /* Check if we failed */
1779 if (!NT_SUCCESS(Status
))
1781 /* Assume System32 */
1782 LdrpKnownDllObjectDirectory
= NULL
;
1783 RtlInitUnicodeString(&LdrpKnownDllPath
, StringBuffer
);
1784 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
1787 /* If we have process parameters, get the default path and current path */
1788 if (ProcessParameters
)
1790 /* Check if we have a Dll Path */
1791 if (ProcessParameters
->DllPath
.Length
)
1794 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
1798 /* We need a valid path */
1799 DPRINT1("No valid DllPath was given!\n");
1800 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
1803 /* Set the current directory */
1804 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
1806 /* Check if it's empty or invalid */
1807 if ((!CurrentDirectory
.Buffer
) ||
1808 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
1809 (!CurrentDirectory
.Length
))
1811 /* Allocate space for the buffer */
1812 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
1815 sizeof(UNICODE_NULL
));
1816 if (!CurrentDirectory
.Buffer
)
1818 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
1822 /* Copy the drive of the system root */
1823 RtlMoveMemory(CurrentDirectory
.Buffer
,
1824 SharedUserData
->NtSystemRoot
,
1826 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
1827 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
1828 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
1831 DPRINT("Using dynamically allocd curdir\n");
1835 /* Use the local buffer */
1836 DPRINT("Using local system root\n");
1840 /* Setup Loader Data */
1842 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
1843 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
1844 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
1845 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
1846 PebLdr
.Initialized
= TRUE
;
1848 /* Allocate a data entry for the Image */
1849 LdrpImageEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
1852 LdrpImageEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(LdrpImageEntry
->DllBase
);
1853 LdrpImageEntry
->LoadCount
= -1;
1854 LdrpImageEntry
->EntryPointActivationContext
= 0;
1855 LdrpImageEntry
->FullDllName
= ImageFileName
;
1858 LdrpImageEntry
->Flags
= LDRP_COR_IMAGE
;
1860 LdrpImageEntry
->Flags
= 0;
1862 /* Check if the name is empty */
1863 if (!ImageFileName
.Buffer
[0])
1865 /* Use the same Base name */
1866 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
1870 /* Find the last slash */
1871 Current
= ImageFileName
.Buffer
;
1874 if (*Current
++ == '\\')
1877 NtDllName
= Current
;
1881 /* Did we find anything? */
1884 /* Use the same Base name */
1885 LdrpImageEntry
->BaseDllName
= LdrpImageEntry
->FullDllName
;
1889 /* Setup the name */
1890 LdrpImageEntry
->BaseDllName
.Length
= (USHORT
)((ULONG_PTR
)ImageFileName
.Buffer
+ ImageFileName
.Length
- (ULONG_PTR
)NtDllName
);
1891 LdrpImageEntry
->BaseDllName
.MaximumLength
= LdrpImageEntry
->BaseDllName
.Length
+ sizeof(WCHAR
);
1892 LdrpImageEntry
->BaseDllName
.Buffer
= (PWSTR
)((ULONG_PTR
)ImageFileName
.Buffer
+
1893 (ImageFileName
.Length
- LdrpImageEntry
->BaseDllName
.Length
));
1897 /* Processing done, insert it */
1898 LdrpInsertMemoryTableEntry(LdrpImageEntry
);
1899 LdrpImageEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
1901 /* Now add an entry for NTDLL */
1902 NtLdrEntry
= LdrpAllocateDataTableEntry(SystemArgument1
);
1903 NtLdrEntry
->Flags
= LDRP_IMAGE_DLL
;
1904 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
1905 NtLdrEntry
->LoadCount
= -1;
1906 NtLdrEntry
->EntryPointActivationContext
= 0;
1908 NtLdrEntry
->FullDllName
.Length
= FullPath
.Length
;
1909 NtLdrEntry
->FullDllName
.MaximumLength
= FullPath
.MaximumLength
;
1910 NtLdrEntry
->FullDllName
.Buffer
= StringBuffer
;
1911 RtlAppendUnicodeStringToString(&NtLdrEntry
->FullDllName
, &NtDllString
);
1913 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
1914 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
1915 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
1917 /* Processing done, insert it */
1918 LdrpNtDllDataTableEntry
= NtLdrEntry
;
1919 LdrpInsertMemoryTableEntry(NtLdrEntry
);
1921 /* Let the world know */
1924 DPRINT1("LDR: NEW PROCESS\n");
1925 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry
->FullDllName
, &LdrpImageEntry
->BaseDllName
);
1926 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory
);
1927 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath
);
1930 /* Link the Init Order List */
1931 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
1932 &LdrpNtDllDataTableEntry
->InInitializationOrderLinks
);
1934 /* Initialize Wine's active context implementation for the current process */
1937 /* Set the current directory */
1938 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
1939 if (!NT_SUCCESS(Status
))
1941 /* We failed, check if we should free it */
1942 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
1944 /* Set it to the NT Root */
1945 CurrentDirectory
= NtSystemRoot
;
1946 RtlSetCurrentDirectory_U(&CurrentDirectory
);
1950 /* We're done with it, free it */
1951 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
1954 /* Check if we should look for a .local file */
1955 if (ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
)
1958 DPRINT1("We don't support .local overrides yet\n");
1961 /* Check if the Application Verifier was enabled */
1962 if (Peb
->NtGlobalFlag
& FLG_POOL_ENABLE_TAIL_CHECK
)
1965 DPRINT1("We don't support Application Verifier yet\n");
1971 DPRINT1("We don't support .NET applications yet\n");
1974 /* FIXME: Load support for Terminal Services */
1975 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
)
1977 /* Load kernel32 and call BasePostImportInit... */
1978 DPRINT("Unimplemented codepath!\n");
1981 /* Walk the IAT and load all the DLLs */
1982 ImportStatus
= LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
1984 /* Check if relocation is needed */
1985 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
1987 DPRINT1("LDR: Performing EXE relocation\n");
1989 /* Change the protection to prepare for relocation */
1990 ViewBase
= Peb
->ImageBaseAddress
;
1991 Status
= LdrpSetProtection(ViewBase
, FALSE
);
1992 if (!NT_SUCCESS(Status
)) return Status
;
1994 /* Do the relocation */
1995 Status
= LdrRelocateImageWithBias(ViewBase
,
1999 STATUS_CONFLICTING_ADDRESSES
,
2000 STATUS_INVALID_IMAGE_FORMAT
);
2001 if (!NT_SUCCESS(Status
))
2003 DPRINT1("LdrRelocateImageWithBias() failed\n");
2007 /* Check if a start context was provided */
2010 DPRINT1("WARNING: Relocated EXE Context");
2011 UNIMPLEMENTED
; // We should support this
2012 return STATUS_INVALID_IMAGE_FORMAT
;
2015 /* Restore the protection */
2016 Status
= LdrpSetProtection(ViewBase
, TRUE
);
2017 if (!NT_SUCCESS(Status
)) return Status
;
2021 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
2022 NextEntry
= ListHead
->Flink
;
2023 while (ListHead
!= NextEntry
)
2025 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2026 NtLdrEntry
->LoadCount
= -1;
2027 NextEntry
= NextEntry
->Flink
;
2030 /* Phase 0 is done */
2031 LdrpLdrDatabaseIsSetup
= TRUE
;
2033 /* Check whether all static imports were properly loaded and return here */
2034 if (!NT_SUCCESS(ImportStatus
)) return ImportStatus
;
2036 /* Initialize TLS */
2037 Status
= LdrpInitializeTls();
2038 if (!NT_SUCCESS(Status
))
2040 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2045 /* FIXME Mark the DLL Ranges for Stack Traces later */
2047 /* Notify the debugger now */
2048 if (Peb
->BeingDebugged
)
2053 /* Update show snaps again */
2054 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
2057 /* Validate the Image for MP Usage */
2058 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
2060 /* Check NX Options */
2061 if (SharedUserData
->NXSupportPolicy
== 1)
2063 ExecuteOptions
= 0xD;
2065 else if (!SharedUserData
->NXSupportPolicy
)
2067 ExecuteOptions
= 0xA;
2071 ZwSetInformationProcess(NtCurrentProcess(),
2072 ProcessExecuteFlags
,
2076 // FIXME: Should be done by Application Compatibility features,
2077 // by reading the registry, etc...
2078 // For now, this is the old code from ntdll!RtlGetVersion().
2079 RtlInitEmptyUnicodeString(&Peb
->CSDVersion
, NULL
, 0);
2080 if (((Peb
->OSCSDVersion
>> 8) & 0xFF) != 0)
2082 WCHAR szCSDVersion
[128];
2084 ULONG Length
= ARRAYSIZE(szCSDVersion
) - 1;
2085 i
= _snwprintf(szCSDVersion
, Length
,
2087 ((Peb
->OSCSDVersion
>> 8) & 0xFF));
2090 /* Null-terminate if it was overflowed */
2091 szCSDVersion
[Length
] = UNICODE_NULL
;
2094 Length
*= sizeof(WCHAR
);
2095 Peb
->CSDVersion
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
2097 Length
+ sizeof(UNICODE_NULL
));
2098 if (Peb
->CSDVersion
.Buffer
)
2100 Peb
->CSDVersion
.Length
= Length
;
2101 Peb
->CSDVersion
.MaximumLength
= Length
+ sizeof(UNICODE_NULL
);
2103 RtlCopyMemory(Peb
->CSDVersion
.Buffer
,
2105 Peb
->CSDVersion
.MaximumLength
);
2106 Peb
->CSDVersion
.Buffer
[Peb
->CSDVersion
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2110 /* Check if we had Shim Data */
2113 /* Load the Shim Engine */
2114 Peb
->AppCompatInfo
= NULL
;
2115 LdrpLoadShimEngine(OldShimData
, &ImagePathName
, OldShimData
);
2119 /* Check for Application Compatibility Goo */
2120 //LdrQueryApplicationCompatibilityGoo(hKey);
2121 DPRINT("Querying app compat hacks is missing!\n");
2125 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2126 * incompatible images.
2129 /* Now call the Init Routines */
2130 Status
= LdrpRunInitializeRoutines(Context
);
2131 if (!NT_SUCCESS(Status
))
2133 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2138 /* Notify Shim Engine */
2141 VOID(NTAPI
*SE_InstallAfterInit
)(PUNICODE_STRING
, PVOID
);
2142 SE_InstallAfterInit
= RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit
);
2143 SE_InstallAfterInit(&ImagePathName
, OldShimData
);
2146 /* Check if we have a user-defined Post Process Routine */
2147 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
2150 Peb
->PostProcessInitRoutine();
2153 /* Close the key if we have one opened */
2154 if (OptionsKey
) NtClose(OptionsKey
);
2162 LdrpInitFailure(NTSTATUS Status
)
2165 PPEB Peb
= NtCurrentPeb();
2167 /* Print a debug message */
2168 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2169 &Peb
->ProcessParameters
->ImagePathName
, Status
);
2171 /* Raise a hard error */
2172 if (!LdrpFatalHardErrorCount
)
2174 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
2180 LdrpInit(PCONTEXT Context
,
2181 PVOID SystemArgument1
,
2182 PVOID SystemArgument2
)
2184 LARGE_INTEGER Timeout
;
2185 PTEB Teb
= NtCurrentTeb();
2186 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
2187 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
2188 PPEB Peb
= NtCurrentPeb();
2190 DPRINT("LdrpInit() %p/%p\n",
2191 NtCurrentTeb()->RealClientId
.UniqueProcess
,
2192 NtCurrentTeb()->RealClientId
.UniqueThread
);
2195 /* Set the SList header usage */
2196 RtlpUse16ByteSLists
= SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE128
];
2199 /* Check if we have a deallocation stack */
2200 if (!Teb
->DeallocationStack
)
2202 /* We don't, set one */
2203 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
2204 Teb
->NtTib
.StackLimit
,
2205 MemoryBasicInformation
,
2207 sizeof(MEMORY_BASIC_INFORMATION
),
2209 if (!NT_SUCCESS(Status
))
2212 LdrpInitFailure(Status
);
2213 RtlRaiseStatus(Status
);
2218 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
2221 /* Now check if the process is already being initialized */
2222 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
2226 /* Set the timeout to 30 milliseconds */
2227 Timeout
.QuadPart
= Int32x32To64(30, -10000);
2229 /* Make sure the status hasn't changed */
2230 while (LdrpProcessInitialized
== 1)
2233 ZwDelayExecution(FALSE
, &Timeout
);
2237 /* Check if we have already setup LDR data */
2240 /* Setup the Loader Lock */
2241 Peb
->LoaderLock
= &LdrpLoaderLock
;
2243 /* Let other code know we're initializing */
2244 LdrpInLdrInit
= TRUE
;
2246 /* Protect with SEH */
2249 /* Initialize the Process */
2250 LoaderStatus
= LdrpInitializeProcess(Context
,
2253 /* Check for success and if MinimumStackCommit was requested */
2254 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
2256 /* Enforce the limit */
2257 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2263 /* Fail with the SEH error */
2264 LoaderStatus
= _SEH2_GetExceptionCode();
2268 /* We're not initializing anymore */
2269 LdrpInLdrInit
= FALSE
;
2271 /* Check if init worked */
2272 if (NT_SUCCESS(LoaderStatus
))
2274 /* Set the process as Initialized */
2275 _InterlockedIncrement(&LdrpProcessInitialized
);
2280 /* Loader data is there... is this a fork() ? */
2281 if(Peb
->InheritedAddressSpace
)
2283 /* Handle the fork() */
2284 //LoaderStatus = LdrpForkProcess();
2285 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
2290 /* This is a new thread initializing */
2291 LdrpInitializeThread(Context
);
2295 /* All done, test alert the thread */
2299 if (!NT_SUCCESS(LoaderStatus
))
2302 LdrpInitFailure(LoaderStatus
);
2303 RtlRaiseStatus(LoaderStatus
);