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 *****************************************************************/
16 /* GLOBALS *******************************************************************/
18 HKEY ImageExecOptionsKey
;
19 HKEY Wow64ExecOptionsKey
;
20 UNICODE_STRING ImageExecOptionsString
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options");
21 UNICODE_STRING Wow64OptionsString
= RTL_CONSTANT_STRING(L
"");
22 UNICODE_STRING NtDllString
= RTL_CONSTANT_STRING(L
"ntdll.dll");
24 BOOLEAN LdrpInLdrInit
;
25 LONG LdrpProcessInitialized
;
26 BOOLEAN LdrpLoaderLockInit
;
27 BOOLEAN LdrpLdrDatabaseIsSetup
;
29 BOOLEAN LdrpDllValidation
;
31 PLDR_DATA_TABLE_ENTRY LdrpImageEntry
;
32 PUNICODE_STRING LdrpTopLevelDllBeingLoaded
;
33 extern PTEB LdrpTopLevelDllBeingLoadedTeb
; // defined in rtlsupp.c!
34 PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer
;
35 PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry
;
38 RTL_BITMAP TlsExpansionBitMap
;
40 BOOLEAN LdrpImageHasTls
;
41 LIST_ENTRY LdrpTlsList
;
42 ULONG LdrpNumberOfTlsEntries
;
43 ULONG LdrpNumberOfProcessors
;
45 LARGE_INTEGER RtlpTimeout
;
46 BOOLEAN RtlpTimeoutDisable
;
47 LIST_ENTRY LdrpHashTable
[LDR_HASH_TABLE_ENTRIES
];
48 LIST_ENTRY LdrpDllNotificationList
;
49 HANDLE LdrpKnownDllObjectDirectory
;
50 UNICODE_STRING LdrpKnownDllPath
;
51 WCHAR LdrpKnownDllPathBuffer
[128];
52 UNICODE_STRING LdrpDefaultPath
;
56 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug
;
57 RTL_CRITICAL_SECTION LdrpLoaderLock
=
66 RTL_CRITICAL_SECTION FastPebLock
;
70 ULONG LdrpFatalHardErrorCount
;
72 //extern LIST_ENTRY RtlCriticalSectionList;
74 VOID
RtlpInitializeVectoredExceptionHandling(VOID
);
75 VOID NTAPI
RtlpInitDeferedCriticalSection(VOID
);
76 VOID
RtlInitializeHeapManager(VOID
);
77 extern BOOLEAN RtlpPageHeapEnabled
;
78 extern ULONG RtlpDphGlobalFlags
;
80 NTSTATUS
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
, PVOID ImageBase
);
82 LdrpInitializeProcess_(PCONTEXT Context
,
83 PVOID SystemArgument1
);
86 /* FUNCTIONS *****************************************************************/
93 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey
,
95 OUT PHKEY NewKeyHandle
)
97 PHKEY RootKeyLocation
;
99 UNICODE_STRING SubKeyString
;
100 OBJECT_ATTRIBUTES ObjectAttributes
;
104 /* Check which root key to open */
106 RootKeyLocation
= &Wow64ExecOptionsKey
;
108 RootKeyLocation
= &ImageExecOptionsKey
;
110 /* Get the current key */
111 RootKey
= *RootKeyLocation
;
113 /* Setup the object attributes */
114 InitializeObjectAttributes(&ObjectAttributes
,
116 &Wow64OptionsString
: &ImageExecOptionsString
,
117 OBJ_CASE_INSENSITIVE
,
121 /* Open the root key */
122 Status
= ZwOpenKey(&RootKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
123 if (NT_SUCCESS(Status
))
125 /* Write the key handle */
126 if (_InterlockedCompareExchange((LONG
*)RootKeyLocation
, (LONG
)RootKey
, 0) != 0)
128 /* Someone already opened it, use it instead */
130 RootKey
= *RootKeyLocation
;
133 /* Extract the name */
134 SubKeyString
= *SubKey
;
135 p1
= (PWCHAR
)((ULONG_PTR
)SubKeyString
.Buffer
+ SubKeyString
.Length
);
136 while (SubKey
->Length
)
138 if (p1
[-1] == L
'\\') break;
140 SubKeyString
.Length
-= sizeof(*p1
);
142 SubKeyString
.Buffer
= p1
;
143 SubKeyString
.Length
= SubKeyString
.MaximumLength
- SubKeyString
.Length
- sizeof(WCHAR
);
145 /* Setup the object attributes */
146 InitializeObjectAttributes(&ObjectAttributes
,
148 OBJ_CASE_INSENSITIVE
,
152 /* Open the setting key */
153 Status
= ZwOpenKey((PHANDLE
)NewKeyHandle
, GENERIC_READ
, &ObjectAttributes
);
156 /* Return to caller */
165 LdrQueryImageFileKeyOption(IN HKEY KeyHandle
,
170 OUT PULONG ReturnedLength OPTIONAL
)
173 UNICODE_STRING ValueNameString
, IntegerString
;
174 ULONG KeyInfoSize
, ResultSize
;
175 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)&KeyInfo
;
176 BOOLEAN FreeHeap
= FALSE
;
179 /* Build a string for the value name */
180 Status
= RtlInitUnicodeStringEx(&ValueNameString
, ValueName
);
181 if (!NT_SUCCESS(Status
)) return Status
;
183 /* Query the value */
184 Status
= NtQueryValueKey(KeyHandle
,
186 KeyValuePartialInformation
,
190 if (Status
== STATUS_BUFFER_OVERFLOW
)
192 /* Our local buffer wasn't enough, allocate one */
193 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
194 KeyValueInformation
->DataLength
;
195 KeyValueInformation
= RtlAllocateHeap(RtlGetProcessHeap(),
200 /* Give up this time */
201 Status
= STATUS_NO_MEMORY
;
205 Status
= NtQueryValueKey(KeyHandle
,
207 KeyValuePartialInformation
,
214 /* Check for success */
215 if (NT_SUCCESS(Status
))
217 /* Handle binary data */
218 if (KeyValueInformation
->Type
== REG_BINARY
)
221 if ((Buffer
) && (KeyValueInformation
->DataLength
<= BufferSize
))
223 /* Copy into buffer */
224 RtlMoveMemory(Buffer
,
225 &KeyValueInformation
->Data
,
226 KeyValueInformation
->DataLength
);
230 Status
= STATUS_BUFFER_OVERFLOW
;
233 /* Copy the result length */
234 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
236 else if (KeyValueInformation
->Type
== REG_DWORD
)
238 /* Check for valid type */
239 if (KeyValueInformation
->Type
!= Type
)
242 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
248 (BufferSize
== sizeof(ULONG
)) &&
249 (KeyValueInformation
->DataLength
<= BufferSize
))
251 /* Copy into buffer */
252 RtlMoveMemory(Buffer
,
253 &KeyValueInformation
->Data
,
254 KeyValueInformation
->DataLength
);
258 Status
= STATUS_BUFFER_OVERFLOW
;
261 /* Copy the result length */
262 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
265 else if (KeyValueInformation
->Type
!= REG_SZ
)
267 /* We got something weird */
268 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
272 /* String, check what you requested */
273 if (Type
== REG_DWORD
)
276 if (BufferSize
!= sizeof(ULONG
))
280 Status
= STATUS_INFO_LENGTH_MISMATCH
;
284 /* OK, we know what you want... */
285 IntegerString
.Buffer
= (PWSTR
)KeyValueInformation
->Data
;
286 IntegerString
.Length
= KeyValueInformation
->DataLength
-
288 IntegerString
.MaximumLength
= KeyValueInformation
->DataLength
;
289 Status
= RtlUnicodeStringToInteger(&IntegerString
, 0, (PULONG
)Buffer
);
295 if (KeyValueInformation
->DataLength
> BufferSize
)
298 Status
= STATUS_BUFFER_OVERFLOW
;
303 BufferSize
= KeyValueInformation
->DataLength
;
306 /* Copy the string */
307 RtlMoveMemory(Buffer
, &KeyValueInformation
->Data
, BufferSize
);
310 /* Copy the result length */
311 if (ReturnedLength
) *ReturnedLength
= KeyValueInformation
->DataLength
;
315 /* Check if buffer was in heap */
316 if (FreeHeap
) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation
);
318 /* Close key and return */
328 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey
,
333 OUT PULONG ReturnedLength OPTIONAL
,
339 /* Open a handle to the key */
340 Status
= LdrOpenImageFileOptionsKey(SubKey
, Wow64
, &KeyHandle
);
342 /* Check for success */
343 if (NT_SUCCESS(Status
))
346 Status
= LdrQueryImageFileKeyOption(KeyHandle
,
357 /* Return to caller */
366 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey
,
371 OUT PULONG ReturnedLength OPTIONAL
)
373 /* Call the newer function */
374 return LdrQueryImageFileExecutionOptionsEx(SubKey
,
385 LdrpEnsureLoaderLockIsHeld()
392 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress
, ULONG SizeOfImage
)
394 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir
;
398 /* Check NT header first */
399 if (!RtlImageNtHeader(BaseAddress
)) return NULL
;
401 /* Get the pointer to the config directory */
402 ConfigDir
= RtlImageDirectoryEntryToData(BaseAddress
,
404 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
407 /* Check for sanity */
409 (DirSize
!= 64 && ConfigDir
->Size
!= DirSize
) ||
410 (ConfigDir
->Size
< 0x48))
413 /* Now get the cookie */
414 Cookie
= (PVOID
)ConfigDir
->SecurityCookie
;
416 /* Check this cookie */
417 if (Cookie
== NULL
||
418 (PCHAR
)Cookie
<= (PCHAR
)BaseAddress
||
419 (PCHAR
)Cookie
>= (PCHAR
)BaseAddress
+ SizeOfImage
)
424 /* Return validated security cookie */
430 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry
)
434 /* Fetch address of the cookie */
435 Cookie
= LdrpFetchAddressOfSecurityCookie(LdrEntry
->DllBase
, LdrEntry
->SizeOfImage
);
448 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL
)
450 PLDR_DATA_TABLE_ENTRY LocalArray
[16];
451 PLIST_ENTRY ListHead
;
452 PLIST_ENTRY NextEntry
;
453 PLDR_DATA_TABLE_ENTRY LdrEntry
, *LdrRootEntry
, OldInitializer
;
457 NTSTATUS Status
= STATUS_SUCCESS
;
458 PPEB Peb
= NtCurrentPeb();
459 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx
;
460 ULONG BreakOnDllLoad
;
464 DPRINT("LdrpRunInitializeRoutines() called for %wZ\n", &LdrpImageEntry
->BaseDllName
);
466 /* Check the Loader Lock */
467 LdrpEnsureLoaderLockIsHeld();
469 /* Get the number of entries to call */
470 if ((Count
= LdrpClearLoadInProgress()))
472 /* Check if we can use our local buffer */
475 /* Allocate space for all the entries */
476 LdrRootEntry
= RtlAllocateHeap(RtlGetProcessHeap(),
478 Count
* sizeof(LdrRootEntry
));
479 if (!LdrRootEntry
) return STATUS_NO_MEMORY
;
483 /* Use our local array */
484 LdrRootEntry
= LocalArray
;
493 /* Show debug message */
496 DPRINT1("[%x,%x] LDR: Real INIT LIST for Process %wZ\n",
497 NtCurrentTeb()->RealClientId
.UniqueThread
,
498 NtCurrentTeb()->RealClientId
.UniqueProcess
,
499 &Peb
->ProcessParameters
->ImagePathName
);
503 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
504 NextEntry
= ListHead
->Flink
;
506 while (NextEntry
!= ListHead
)
508 /* Get the Data Entry */
509 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
511 /* Check if we have a Root Entry */
515 if (!(LdrEntry
->Flags
& LDRP_ENTRY_PROCESSED
))
517 /* Setup the Cookie for the DLL */
518 LdrpInitSecurityCookie(LdrEntry
);
520 /* Check for valid entrypoint */
521 if (LdrEntry
->EntryPoint
)
524 LdrRootEntry
[i
] = LdrEntry
;
526 /* Display debug message */
529 DPRINT1("[%x,%x] LDR: %wZ init routine %p\n",
530 NtCurrentTeb()->RealClientId
.UniqueThread
,
531 NtCurrentTeb()->RealClientId
.UniqueProcess
,
532 &LdrEntry
->FullDllName
,
533 LdrEntry
->EntryPoint
);
541 LdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
542 NextEntry
= NextEntry
->Flink
;
545 /* If we got a context, then we have to call Kernel32 for TS support */
548 /* Check if we have one */
549 //if (Kernel32ProcessInitPostImportfunction)
552 //Kernel32ProcessInitPostImportfunction();
556 //Kernel32ProcessInitPostImportfunction = NULL;
560 /* No root entry? return */
561 if (!LdrRootEntry
) return STATUS_SUCCESS
;
563 /* Set the TLD TEB */
564 OldTldTeb
= LdrpTopLevelDllBeingLoadedTeb
;
565 LdrpTopLevelDllBeingLoadedTeb
= NtCurrentTeb();
572 LdrEntry
= LdrRootEntry
[i
];
574 /* FIXME: Verify NX Compat */
576 /* Move to next entry */
579 /* Get its entrypoint */
580 EntryPoint
= LdrEntry
->EntryPoint
;
582 /* Are we being debugged? */
584 if (Peb
->BeingDebugged
|| Peb
->ReadImageFileExecOptions
)
586 /* Check if we should break on load */
587 Status
= LdrQueryImageFileExecutionOptions(&LdrEntry
->BaseDllName
,
593 if (!NT_SUCCESS(Status
)) BreakOnDllLoad
= 0;
595 /* Reset status back to STATUS_SUCCESS */
596 Status
= STATUS_SUCCESS
;
602 /* Check if we should show a message */
605 DPRINT1("LDR: %wZ loaded.", &LdrEntry
->BaseDllName
);
606 DPRINT1(" - About to call init routine at %p\n", EntryPoint
);
609 /* Break in debugger */
613 /* Make sure we have an entrypoint */
616 /* Save the old Dll Initializer and write the current one */
617 OldInitializer
= LdrpCurrentDllInitializer
;
618 LdrpCurrentDllInitializer
= LdrEntry
;
620 /* Set up the Act Ctx */
621 ActCtx
.Size
= sizeof(ActCtx
);
623 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
625 /* Activate the ActCtx */
626 RtlActivateActivationContextUnsafeFast(&ActCtx
,
627 LdrEntry
->EntryPointActivationContext
);
629 /* Check if it has TLS */
630 if (LdrEntry
->TlsIndex
&& Context
)
633 LdrpTlsCallback(LdrEntry
->DllBase
, DLL_PROCESS_ATTACH
);
636 /* Call the Entrypoint */
639 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
640 &LdrEntry
->BaseDllName
, EntryPoint
);
642 DllStatus
= LdrpCallDllEntry(EntryPoint
,
647 /* Deactivate the ActCtx */
648 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
650 /* Save the Current DLL Initializer */
651 LdrpCurrentDllInitializer
= OldInitializer
;
653 /* Mark the entry as processed */
654 LdrEntry
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
;
656 /* Fail if DLL init failed */
659 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
660 &LdrEntry
->BaseDllName
, EntryPoint
);
662 Status
= STATUS_DLL_INIT_FAILED
;
669 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
670 NextEntry
= NextEntry
->Flink
;
671 while (NextEntry
!= ListHead
)
673 /* Get the Data Entrry */
674 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
676 /* FIXME: Verify NX Compat */
677 // LdrpCheckNXCompatibility()
680 NextEntry
= NextEntry
->Flink
;
684 if (LdrpImageHasTls
&& Context
)
686 /* Set up the Act Ctx */
687 ActCtx
.Size
= sizeof(ActCtx
);
689 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
691 /* Activate the ActCtx */
692 RtlActivateActivationContextUnsafeFast(&ActCtx
,
693 LdrpImageEntry
->EntryPointActivationContext
);
695 /* Do TLS callbacks */
696 LdrpTlsCallback(Peb
->ImageBaseAddress
, DLL_PROCESS_ATTACH
);
698 /* Deactivate the ActCtx */
699 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
703 /* Restore old TEB */
704 LdrpTopLevelDllBeingLoadedTeb
= OldTldTeb
;
706 /* Check if the array is in the heap */
707 if (LdrRootEntry
!= LocalArray
)
710 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry
);
713 /* Return to caller */
714 DPRINT("LdrpRunInitializeRoutines() done\n");
720 LdrpInitializeTls(VOID
)
722 PLIST_ENTRY NextEntry
, ListHead
;
723 PLDR_DATA_TABLE_ENTRY LdrEntry
;
724 PIMAGE_TLS_DIRECTORY TlsDirectory
;
725 PLDRP_TLS_DATA TlsData
;
728 /* Initialize the TLS List */
729 InitializeListHead(&LdrpTlsList
);
731 /* Loop all the modules */
732 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
733 NextEntry
= ListHead
->Flink
;
734 while (ListHead
!= NextEntry
)
737 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
738 NextEntry
= NextEntry
->Flink
;
740 /* Get the TLS directory */
741 TlsDirectory
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
743 IMAGE_DIRECTORY_ENTRY_TLS
,
746 /* Check if we have a directory */
747 if (!TlsDirectory
) continue;
749 /* Check if the image has TLS */
750 if (!LdrpImageHasTls
) LdrpImageHasTls
= TRUE
;
752 /* Show debug message */
755 DPRINT1("LDR: Tls Found in %wZ at %p\n",
756 &LdrEntry
->BaseDllName
,
760 /* Allocate an entry */
761 TlsData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA
));
762 if (!TlsData
) return STATUS_NO_MEMORY
;
764 /* Lock the DLL and mark it for TLS Usage */
765 LdrEntry
->LoadCount
= -1;
766 LdrEntry
->TlsIndex
= -1;
768 /* Save the cached TLS data */
769 TlsData
->TlsDirectory
= *TlsDirectory
;
770 InsertTailList(&LdrpTlsList
, &TlsData
->TlsLinks
);
772 /* Update the index */
773 *(PLONG
)TlsData
->TlsDirectory
.AddressOfIndex
= LdrpNumberOfTlsEntries
;
774 TlsData
->TlsDirectory
.Characteristics
= LdrpNumberOfTlsEntries
++;
777 /* Done setting up TLS, allocate entries */
778 return LdrpAllocateTls();
783 LdrpAllocateTls(VOID
)
785 PTEB Teb
= NtCurrentTeb();
786 PLIST_ENTRY NextEntry
, ListHead
;
787 PLDRP_TLS_DATA TlsData
;
791 /* Check if we have any entries */
792 if (!LdrpNumberOfTlsEntries
)
793 return STATUS_SUCCESS
;
795 /* Allocate the vector array */
796 TlsVector
= RtlAllocateHeap(RtlGetProcessHeap(),
798 LdrpNumberOfTlsEntries
* sizeof(PVOID
));
799 if (!TlsVector
) return STATUS_NO_MEMORY
;
800 Teb
->ThreadLocalStoragePointer
= TlsVector
;
802 /* Loop the TLS Array */
803 ListHead
= &LdrpTlsList
;
804 NextEntry
= ListHead
->Flink
;
805 while (NextEntry
!= ListHead
)
808 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
809 NextEntry
= NextEntry
->Flink
;
811 /* Allocate this vector */
812 TlsDataSize
= TlsData
->TlsDirectory
.EndAddressOfRawData
-
813 TlsData
->TlsDirectory
.StartAddressOfRawData
;
814 TlsVector
[TlsData
->TlsDirectory
.Characteristics
] = RtlAllocateHeap(RtlGetProcessHeap(),
817 if (!TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
820 return STATUS_NO_MEMORY
;
823 /* Show debug message */
826 DPRINT1("LDR: TlsVector %x Index %d = %x copied from %x to %x\n",
828 TlsData
->TlsDirectory
.Characteristics
,
829 &TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
830 TlsData
->TlsDirectory
.StartAddressOfRawData
,
831 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
835 RtlCopyMemory(TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
836 (PVOID
)TlsData
->TlsDirectory
.StartAddressOfRawData
,
841 return STATUS_SUCCESS
;
848 PLIST_ENTRY ListHead
, NextEntry
;
849 PLDRP_TLS_DATA TlsData
;
851 PTEB Teb
= NtCurrentTeb();
853 /* Get a pointer to the vector array */
854 TlsVector
= Teb
->ThreadLocalStoragePointer
;
855 if (!TlsVector
) return;
857 /* Loop through it */
858 ListHead
= &LdrpTlsList
;
859 NextEntry
= ListHead
->Flink
;
860 while (NextEntry
!= ListHead
)
862 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
863 NextEntry
= NextEntry
->Flink
;
865 /* Free each entry */
866 if (TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
868 RtlFreeHeap(RtlGetProcessHeap(),
870 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
874 /* Free the array itself */
875 RtlFreeHeap(RtlGetProcessHeap(),
882 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName
, PPEB Peb
, PULONG Options
)
886 return STATUS_SUCCESS
;
891 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
)
898 LdrpInitializeProcess(IN PCONTEXT Context
,
899 IN PVOID SystemArgument1
)
901 RTL_HEAP_PARAMETERS HeapParameters
;
902 ULONG ComSectionSize
;
903 //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData");
905 OBJECT_ATTRIBUTES ObjectAttributes
;
906 //UNICODE_STRING LocalFileName, FullImageName;
907 HANDLE SymLinkHandle
;
908 //ULONG DebugHeapOnly;
909 UNICODE_STRING CommandLine
, NtSystemRoot
, ImagePathName
, FullPath
, ImageFileName
, KnownDllString
;
910 PPEB Peb
= NtCurrentPeb();
911 BOOLEAN IsDotNetImage
= FALSE
;
912 BOOLEAN FreeCurDir
= FALSE
;
914 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
915 //LPWSTR ImagePathBuffer;
917 UNICODE_STRING CurrentDirectory
;
918 ULONG ExecuteOptions
;
920 PIMAGE_NT_HEADERS NtHeader
;
921 LPWSTR NtDllName
= NULL
;
923 NLSTABLEINFO NlsTable
;
924 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig
;
925 PTEB Teb
= NtCurrentTeb();
926 PLIST_ENTRY ListHead
;
927 PLIST_ENTRY NextEntry
;
930 ULONG DebugProcessHeapOnly
= 0;
931 WCHAR FullNtDllPath
[MAX_PATH
];
932 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
935 /* Set a NULL SEH Filter */
936 RtlSetUnhandledExceptionFilter(NULL
);
938 /* Get the image path */
939 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
941 /* Check if it's normalized */
942 if (Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
)
945 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
948 /* Create a unicode string for the Image Path */
949 ImagePathName
.Length
= Peb
->ProcessParameters
->ImagePathName
.Length
;
950 ImagePathName
.MaximumLength
= ImagePathName
.Length
+ sizeof(WCHAR
);
951 ImagePathName
.Buffer
= ImagePath
;
953 /* Get the NT Headers */
954 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
956 /* Get the execution options */
957 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &ExecuteOptions
);
959 /* Check if this is a .NET executable */
960 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
962 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
965 /* Remeber this for later */
966 IsDotNetImage
= TRUE
;
969 /* Save the NTDLL Base address */
970 NtDllBase
= SystemArgument1
;
972 /* If this is a Native Image */
973 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
975 /* Then do DLL Validation */
976 LdrpDllValidation
= TRUE
;
979 /* Save the old Shim Data */
980 OldShimData
= Peb
->pShimData
;
983 Peb
->pShimData
= NULL
;
985 /* Save the number of processors and CS Timeout */
986 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
987 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
989 /* Normalize the parameters */
990 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
991 ProcessParameters
= Peb
->ProcessParameters
;
992 if (ProcessParameters
)
994 /* Save the Image and Command Line Names */
995 ImageFileName
= ProcessParameters
->ImagePathName
;
996 CommandLine
= ProcessParameters
->CommandLine
;
1000 /* It failed, initialize empty strings */
1001 RtlInitUnicodeString(&ImageFileName
, NULL
);
1002 RtlInitUnicodeString(&CommandLine
, NULL
);
1005 /* Initialize NLS data */
1006 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1007 Peb
->OemCodePageData
,
1008 Peb
->UnicodeCaseTableData
,
1011 /* Reset NLS Translations */
1012 RtlResetRtlTranslations(&NlsTable
);
1014 /* Get the Image Config Directory */
1015 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1017 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1020 /* Setup the Heap Parameters */
1021 RtlZeroMemory(&HeapParameters
, sizeof(RTL_HEAP_PARAMETERS
));
1022 HeapFlags
= HEAP_GROWABLE
;
1023 HeapParameters
.Length
= sizeof(RTL_HEAP_PARAMETERS
);
1025 /* Check if we have Configuration Data */
1026 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1028 /* FIXME: Custom heap settings and misc. */
1029 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1032 /* Check for custom affinity mask */
1033 if (Peb
->ImageProcessAffinityMask
)
1036 Status
= NtSetInformationProcess(NtCurrentProcess(),
1037 ProcessAffinityMask
,
1038 &Peb
->ImageProcessAffinityMask
,
1039 sizeof(Peb
->ImageProcessAffinityMask
));
1042 /* Check if verbose debugging (ShowSnaps) was requested */
1043 ShowSnaps
= TRUE
;//Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
1045 /* Start verbose debugging messages right now if they were requested */
1048 DPRINT1("LDR: PID: 0x%x started - '%wZ'\n",
1049 Teb
->ClientId
.UniqueProcess
,
1053 /* If the timeout is too long */
1054 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1056 /* Then disable CS Timeout */
1057 RtlpTimeoutDisable
= TRUE
;
1060 /* Initialize Critical Section Data */
1061 RtlpInitDeferedCriticalSection();
1063 /* Initialize VEH Call lists */
1064 RtlpInitializeVectoredExceptionHandling();
1066 /* Set TLS/FLS Bitmap data */
1067 Peb
->FlsBitmap
= &FlsBitMap
;
1068 Peb
->TlsBitmap
= &TlsBitMap
;
1069 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1071 /* Initialize FLS Bitmap */
1072 RtlInitializeBitMap(&FlsBitMap
,
1074 FLS_MAXIMUM_AVAILABLE
);
1075 RtlSetBit(&FlsBitMap
, 0);
1077 /* Initialize TLS Bitmap */
1078 RtlInitializeBitMap(&TlsBitMap
,
1080 TLS_MINIMUM_AVAILABLE
);
1081 RtlSetBit(&TlsBitMap
, 0);
1082 RtlInitializeBitMap(&TlsExpansionBitMap
,
1083 Peb
->TlsExpansionBitmapBits
,
1084 TLS_EXPANSION_SLOTS
);
1085 RtlSetBit(&TlsExpansionBitMap
, 0);
1087 /* Initialize the Hash Table */
1088 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1090 InitializeListHead(&LdrpHashTable
[i
]);
1093 /* Initialize the Loader Lock */
1094 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1095 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1097 LdrpLoaderLockInit
= TRUE
;
1099 /* Check if User Stack Trace Database support was requested */
1100 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1102 DPRINT1("We don't support user stack trace databases yet\n");
1105 /* Setup Fast PEB Lock */
1106 RtlInitializeCriticalSection(&FastPebLock
);
1107 Peb
->FastPebLock
= &FastPebLock
;
1108 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1109 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1111 /* Setup Callout Lock and Notification list */
1112 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1113 InitializeListHead(&LdrpDllNotificationList
);
1115 /* For old executables, use 16-byte aligned heap */
1116 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1117 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1119 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1122 /* Setup the Heap */
1123 RtlInitializeHeapManager();
1124 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1126 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1127 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1131 if (!Peb
->ProcessHeap
)
1133 DPRINT1("Failed to create process heap\n");
1134 return STATUS_NO_MEMORY
;
1137 /* Allocate an Activation Context Stack */
1138 Status
= RtlAllocateActivationContextStack((PVOID
*)&Teb
->ActivationContextStackPointer
);
1139 if (!NT_SUCCESS(Status
)) return Status
;
1141 // FIXME: Loader private heap is missing
1142 DPRINT1("Loader private heap is missing\n");
1144 /* Check for Debug Heap */
1145 DPRINT1("Check for a debug heap is missing\n");
1148 /* Query the setting */
1149 Status
= LdrQueryImageFileKeyOption(NULL
,//hKey
1150 L
"DebugProcessHeapOnly",
1152 &DebugProcessHeapOnly
,
1156 if (NT_SUCCESS(Status
))
1158 /* Reset DPH if requested */
1159 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1161 RtlpDphGlobalFlags
&= ~0x40;
1162 RtlpPageHeapEnabled
= FALSE
;
1167 /* Build the NTDLL Path */
1168 FullPath
.Buffer
= FullNtDllPath
;
1169 FullPath
.Length
= 0;
1170 FullPath
.MaximumLength
= sizeof(FullNtDllPath
);
1171 RtlInitUnicodeString(&NtSystemRoot
, SharedUserData
->NtSystemRoot
);
1172 RtlAppendUnicodeStringToString(&FullPath
, &NtSystemRoot
);
1173 RtlAppendUnicodeToString(&FullPath
, L
"\\System32\\");
1175 /* Open the Known DLLs directory */
1176 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1177 InitializeObjectAttributes(&ObjectAttributes
,
1179 OBJ_CASE_INSENSITIVE
,
1182 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
1183 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
1186 /* Check if it exists */
1187 if (!NT_SUCCESS(Status
))
1189 /* It doesn't, so assume System32 */
1190 LdrpKnownDllObjectDirectory
= NULL
;
1191 RtlInitUnicodeString(&LdrpKnownDllPath
, FullPath
.Buffer
);
1192 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
1196 /* Open the Known DLLs Path */
1197 InitializeObjectAttributes(&ObjectAttributes
,
1199 OBJ_CASE_INSENSITIVE
,
1200 LdrpKnownDllObjectDirectory
,
1202 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
1203 SYMBOLIC_LINK_QUERY
,
1205 if (NT_SUCCESS(Status
))
1207 /* Query the path */
1208 LdrpKnownDllPath
.Length
= 0;
1209 LdrpKnownDllPath
.MaximumLength
= sizeof(LdrpKnownDllPathBuffer
);
1210 LdrpKnownDllPath
.Buffer
= LdrpKnownDllPathBuffer
;
1211 Status
= ZwQuerySymbolicLinkObject(SymLinkHandle
, &LdrpKnownDllPath
, NULL
);
1212 NtClose(SymLinkHandle
);
1213 if (!NT_SUCCESS(Status
))
1215 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
1221 /* If we have process parameters, get the default path and current path */
1222 if (ProcessParameters
)
1224 /* Check if we have a Dll Path */
1225 if (ProcessParameters
->DllPath
.Length
)
1228 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
1232 /* We need a valid path */
1233 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
1236 /* Set the current directory */
1237 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
1239 /* Check if it's empty or invalid */
1240 if ((!CurrentDirectory
.Buffer
) ||
1241 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
1242 (!CurrentDirectory
.Length
))
1244 /* Allocate space for the buffer */
1245 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
1248 sizeof(UNICODE_NULL
));
1250 /* Copy the drive of the system root */
1251 RtlMoveMemory(CurrentDirectory
.Buffer
,
1252 SharedUserData
->NtSystemRoot
,
1254 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
1255 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
1256 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
1262 /* Use the local buffer */
1263 CurrentDirectory
.Length
= NtSystemRoot
.Length
;
1264 CurrentDirectory
.Buffer
= NtSystemRoot
.Buffer
;
1268 /* Setup Loader Data */
1270 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
1271 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
1272 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
1273 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
1274 PebLdr
.Initialized
= TRUE
;
1276 /* Allocate a data entry for the Image */
1277 LdrpImageEntry
= NtLdrEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
1280 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
1281 NtLdrEntry
->LoadCount
= -1;
1282 NtLdrEntry
->EntryPointActivationContext
= 0;
1283 NtLdrEntry
->FullDllName
.Length
= ImageFileName
.Length
;
1284 NtLdrEntry
->FullDllName
.Buffer
= ImageFileName
.Buffer
;
1286 NtLdrEntry
->Flags
= LDRP_COR_IMAGE
;
1288 NtLdrEntry
->Flags
= 0;
1290 /* Check if the name is empty */
1291 if (!ImageFileName
.Buffer
[0])
1293 /* Use the same Base name */
1294 NtLdrEntry
->BaseDllName
= NtLdrEntry
->BaseDllName
;
1298 /* Find the last slash */
1299 Current
= ImageFileName
.Buffer
;
1302 if (*Current
++ == '\\')
1305 NtDllName
= Current
;
1309 /* Did we find anything? */
1312 /* Use the same Base name */
1313 NtLdrEntry
->BaseDllName
= NtLdrEntry
->FullDllName
;
1317 /* Setup the name */
1318 NtLdrEntry
->BaseDllName
.Length
= (USHORT
)((ULONG_PTR
)ImageFileName
.Buffer
+ ImageFileName
.Length
- (ULONG_PTR
)NtDllName
);
1319 NtLdrEntry
->BaseDllName
.MaximumLength
= NtLdrEntry
->BaseDllName
.Length
+ sizeof(WCHAR
);
1320 NtLdrEntry
->BaseDllName
.Buffer
= (PWSTR
)((ULONG_PTR
)ImageFileName
.Buffer
+
1321 (ImageFileName
.Length
- NtLdrEntry
->BaseDllName
.Length
));
1325 /* Processing done, insert it */
1326 LdrpInsertMemoryTableEntry(NtLdrEntry
);
1327 NtLdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
1329 /* Now add an entry for NTDLL */
1330 NtLdrEntry
= LdrpAllocateDataTableEntry(SystemArgument1
);
1331 NtLdrEntry
->Flags
= LDRP_IMAGE_DLL
;
1332 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
1333 NtLdrEntry
->LoadCount
= -1;
1334 NtLdrEntry
->EntryPointActivationContext
= 0;
1335 //NtLdrEntry->BaseDllName.Length = NtSystemRoot.Length;
1336 //RtlAppendUnicodeStringToString(&NtSystemRoot, &NtDllString);
1337 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
1338 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
1339 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
1341 // FIXME: Full DLL name?!
1343 /* Processing done, insert it */
1344 LdrpNtDllDataTableEntry
= NtLdrEntry
;
1345 LdrpInsertMemoryTableEntry(NtLdrEntry
);
1347 /* Let the world know */
1350 DPRINT1("LDR: NEW PROCESS\n");
1351 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry
->FullDllName
, &LdrpImageEntry
->BaseDllName
);
1352 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory
);
1353 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath
);
1356 /* Link the Init Order List */
1357 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
1358 &LdrpNtDllDataTableEntry
->InInitializationOrderModuleList
);
1360 /* Set the current directory */
1361 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
1362 if (!NT_SUCCESS(Status
))
1364 /* We failed, check if we should free it */
1365 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
1367 /* Set it to the NT Root */
1368 CurrentDirectory
= NtSystemRoot
;
1369 RtlSetCurrentDirectory_U(&CurrentDirectory
);
1373 /* We're done with it, free it */
1374 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
1377 /* Check if we should look for a .local file */
1378 if (ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
)
1381 DPRINT1("We don't support .local overrides yet\n");
1384 /* Check if the Application Verifier was enabled */
1385 if (Peb
->NtGlobalFlag
& FLG_POOL_ENABLE_TAIL_CHECK
)
1388 DPRINT1("We don't support Application Verifier yet\n");
1394 DPRINT1("We don't support .NET applications yet\n");
1397 /* FIXME: Load support for Terminal Services */
1398 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
)
1400 /* Load kernel32 and call BasePostImportInit... */
1401 DPRINT1("Unimplemented codepath!\n");
1404 /* Walk the IAT and load all the DLLs */
1405 LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
1407 /* Check if relocation is needed */
1408 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
1410 DPRINT("LDR: Performing relocations\n");
1411 Status
= LdrPerformRelocations(NtHeader
, Peb
->ImageBaseAddress
);
1412 if (!NT_SUCCESS(Status
))
1414 DPRINT1("LdrPerformRelocations() failed\n");
1415 return STATUS_INVALID_IMAGE_FORMAT
;
1420 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
1421 NextEntry
= ListHead
->Flink
;
1422 while (ListHead
!= NextEntry
)
1424 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1425 NtLdrEntry
->LoadCount
= -1;
1426 NextEntry
= NextEntry
->Flink
;
1429 /* Phase 0 is done */
1430 LdrpLdrDatabaseIsSetup
= TRUE
;
1432 /* Initialize TLS */
1433 Status
= LdrpInitializeTls();
1434 if (!NT_SUCCESS(Status
))
1436 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
1441 /* FIXME Mark the DLL Ranges for Stack Traces later */
1443 /* Notify the debugger now */
1444 if (Peb
->BeingDebugged
)
1449 /* Update show snaps again */
1450 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1453 /* Validate the Image for MP Usage */
1454 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
1456 /* Check NX Options */
1457 if (SharedUserData
->NXSupportPolicy
== 1)
1459 ExecuteOptions
= 0xD;
1461 else if (!SharedUserData
->NXSupportPolicy
)
1463 ExecuteOptions
= 0xA;
1467 ZwSetInformationProcess(NtCurrentProcess(),
1468 ProcessExecuteFlags
,
1472 /* Check if we had Shim Data */
1475 /* Load the Shim Engine */
1476 Peb
->AppCompatInfo
= NULL
;
1477 //LdrpLoadShimEngine(OldShimData, ImagePathName, OldShimData);
1478 DPRINT1("We do not support shims yet\n");
1482 /* Check for Application Compatibility Goo */
1483 //LdrQueryApplicationCompatibilityGoo(hKey);
1484 DPRINT1("Querying app compat hacks is missing!\n");
1488 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
1489 * incompatible images.
1492 /* Now call the Init Routines */
1493 Status
= LdrpRunInitializeRoutines(Context
);
1494 if (!NT_SUCCESS(Status
))
1496 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
1501 /* FIXME: Unload the Shim Engine if it was loaded */
1503 /* Check if we have a user-defined Post Process Routine */
1504 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
1508 Peb
->PostProcessInitRoutine();
1511 ///* Close the key if we have one opened */
1512 //if (hKey) NtClose(hKey);
1520 LdrpInitFailure(NTSTATUS Status
)
1524 /* Print a debug message */
1525 DPRINT1("LDR: Process initialization failure; NTSTATUS = %08lx\n", Status
);
1527 /* Raise a hard error */
1528 if (!LdrpFatalHardErrorCount
)
1530 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
1536 LdrpInit(PCONTEXT Context
,
1537 PVOID SystemArgument1
,
1538 PVOID SystemArgument2
)
1540 LARGE_INTEGER Timeout
;
1541 PTEB Teb
= NtCurrentTeb();
1542 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
1543 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
1544 PPEB Peb
= NtCurrentPeb();
1546 DPRINT("LdrpInit()\n");
1548 /* Check if we have a deallocation stack */
1549 if (!Teb
->DeallocationStack
)
1551 /* We don't, set one */
1552 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
1553 Teb
->NtTib
.StackLimit
,
1554 MemoryBasicInformation
,
1556 sizeof(MEMORY_BASIC_INFORMATION
),
1558 if (!NT_SUCCESS(Status
))
1561 LdrpInitFailure(Status
);
1562 RtlRaiseStatus(Status
);
1567 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
1570 /* Now check if the process is already being initialized */
1571 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
1575 /* Set the timeout to 30 seconds */
1576 Timeout
.QuadPart
= Int32x32To64(30, -10000);
1578 /* Make sure the status hasn't changed */
1579 while (!LdrpProcessInitialized
)
1582 ZwDelayExecution(FALSE
, &Timeout
);
1586 /* Check if we have already setup LDR data */
1589 /* Setup the Loader Lock */
1590 Peb
->LoaderLock
= &LdrpLoaderLock
;
1592 /* Let other code know we're initializing */
1593 LdrpInLdrInit
= TRUE
;
1595 /* Protect with SEH */
1598 /* Initialize the Process */
1599 LoaderStatus
= LdrpInitializeProcess_(Context
,
1602 /* Check for success and if MinimumStackCommit was requested */
1603 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
1605 /* Enforce the limit */
1606 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
1610 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1612 /* Fail with the SEH error */
1613 LoaderStatus
= _SEH2_GetExceptionCode();
1617 /* We're not initializing anymore */
1618 LdrpInLdrInit
= FALSE
;
1620 /* Check if init worked */
1621 if (NT_SUCCESS(LoaderStatus
))
1623 /* Set the process as Initialized */
1624 _InterlockedIncrement(&LdrpProcessInitialized
);
1629 /* Loader data is there... is this a fork() ? */
1630 if(Peb
->InheritedAddressSpace
)
1632 /* Handle the fork() */
1633 //LoaderStatus = LdrpForkProcess();
1634 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
1639 /* This is a new thread initializing */
1640 LdrpInitializeThread(Context
);
1644 /* All done, test alert the thread */
1648 if (!NT_SUCCESS(LoaderStatus
))
1651 LdrpInitFailure(LoaderStatus
);
1652 RtlRaiseStatus(LoaderStatus
);