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;
599 /* Check if we should show a message */
602 DPRINT1("LDR: %wZ loaded.", &LdrEntry
->BaseDllName
);
603 DPRINT1(" - About to call init routine at %p\n", EntryPoint
);
606 /* Break in debugger */
610 /* Make sure we have an entrypoint */
613 /* Save the old Dll Initializer and write the current one */
614 OldInitializer
= LdrpCurrentDllInitializer
;
615 LdrpCurrentDllInitializer
= LdrEntry
;
617 /* Set up the Act Ctx */
618 ActCtx
.Size
= sizeof(ActCtx
);
620 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
622 /* Activate the ActCtx */
623 RtlActivateActivationContextUnsafeFast(&ActCtx
,
624 LdrEntry
->EntryPointActivationContext
);
626 /* Check if it has TLS */
627 if (LdrEntry
->TlsIndex
&& Context
)
630 LdrpTlsCallback(LdrEntry
->DllBase
, DLL_PROCESS_ATTACH
);
633 /* Call the Entrypoint */
636 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
637 &LdrEntry
->BaseDllName
, EntryPoint
);
639 DllStatus
= LdrpCallDllEntry(EntryPoint
,
644 /* Deactivate the ActCtx */
645 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
647 /* Save the Current DLL Initializer */
648 LdrpCurrentDllInitializer
= OldInitializer
;
650 /* Mark the entry as processed */
651 LdrEntry
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
;
653 /* Fail if DLL init failed */
656 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
657 &LdrEntry
->BaseDllName
, EntryPoint
);
659 Status
= STATUS_DLL_INIT_FAILED
;
666 ListHead
= &Peb
->Ldr
->InInitializationOrderModuleList
;
667 NextEntry
= NextEntry
->Flink
;
668 while (NextEntry
!= ListHead
)
670 /* Get the Data Entrry */
671 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
673 /* FIXME: Verify NX Compat */
674 // LdrpCheckNXCompatibility()
677 NextEntry
= NextEntry
->Flink
;
681 if (LdrpImageHasTls
&& Context
)
683 /* Set up the Act Ctx */
684 ActCtx
.Size
= sizeof(ActCtx
);
686 RtlZeroMemory(&ActCtx
.Frame
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
688 /* Activate the ActCtx */
689 RtlActivateActivationContextUnsafeFast(&ActCtx
,
690 LdrpImageEntry
->EntryPointActivationContext
);
692 /* Do TLS callbacks */
693 LdrpTlsCallback(Peb
->ImageBaseAddress
, DLL_PROCESS_ATTACH
);
695 /* Deactivate the ActCtx */
696 RtlDeactivateActivationContextUnsafeFast(&ActCtx
);
700 /* Restore old TEB */
701 LdrpTopLevelDllBeingLoadedTeb
= OldTldTeb
;
703 /* Check if the array is in the heap */
704 if (LdrRootEntry
!= LocalArray
)
707 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry
);
710 /* Return to caller */
711 DPRINT("LdrpRunInitializeRoutines() done\n");
717 LdrpInitializeTls(VOID
)
719 PLIST_ENTRY NextEntry
, ListHead
;
720 PLDR_DATA_TABLE_ENTRY LdrEntry
;
721 PIMAGE_TLS_DIRECTORY TlsDirectory
;
722 PLDRP_TLS_DATA TlsData
;
725 /* Initialize the TLS List */
726 InitializeListHead(&LdrpTlsList
);
728 /* Loop all the modules */
729 ListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
730 NextEntry
= ListHead
->Flink
;
731 while (ListHead
!= NextEntry
)
734 LdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
735 NextEntry
= NextEntry
->Flink
;
737 /* Get the TLS directory */
738 TlsDirectory
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
740 IMAGE_DIRECTORY_ENTRY_TLS
,
743 /* Check if we have a directory */
744 if (!TlsDirectory
) continue;
746 /* Check if the image has TLS */
747 if (!LdrpImageHasTls
) LdrpImageHasTls
= TRUE
;
749 /* Show debug message */
752 DPRINT1("LDR: Tls Found in %wZ at %p\n",
753 &LdrEntry
->BaseDllName
,
757 /* Allocate an entry */
758 TlsData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA
));
759 if (!TlsData
) return STATUS_NO_MEMORY
;
761 /* Lock the DLL and mark it for TLS Usage */
762 LdrEntry
->LoadCount
= -1;
763 LdrEntry
->TlsIndex
= -1;
765 /* Save the cached TLS data */
766 TlsData
->TlsDirectory
= *TlsDirectory
;
767 InsertTailList(&LdrpTlsList
, &TlsData
->TlsLinks
);
769 /* Update the index */
770 *(PLONG
)TlsData
->TlsDirectory
.AddressOfIndex
= LdrpNumberOfTlsEntries
;
771 TlsData
->TlsDirectory
.Characteristics
= LdrpNumberOfTlsEntries
++;
774 /* Done setting up TLS, allocate entries */
775 return LdrpAllocateTls();
780 LdrpAllocateTls(VOID
)
782 PTEB Teb
= NtCurrentTeb();
783 PLIST_ENTRY NextEntry
, ListHead
;
784 PLDRP_TLS_DATA TlsData
;
788 /* Check if we have any entries */
789 if (!LdrpNumberOfTlsEntries
)
790 return STATUS_SUCCESS
;
792 /* Allocate the vector array */
793 TlsVector
= RtlAllocateHeap(RtlGetProcessHeap(),
795 LdrpNumberOfTlsEntries
* sizeof(PVOID
));
796 if (!TlsVector
) return STATUS_NO_MEMORY
;
797 Teb
->ThreadLocalStoragePointer
= TlsVector
;
799 /* Loop the TLS Array */
800 ListHead
= &LdrpTlsList
;
801 NextEntry
= ListHead
->Flink
;
802 while (NextEntry
!= ListHead
)
805 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
806 NextEntry
= NextEntry
->Flink
;
808 /* Allocate this vector */
809 TlsDataSize
= TlsData
->TlsDirectory
.EndAddressOfRawData
-
810 TlsData
->TlsDirectory
.StartAddressOfRawData
;
811 TlsVector
[TlsData
->TlsDirectory
.Characteristics
] = RtlAllocateHeap(RtlGetProcessHeap(),
814 if (!TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
817 return STATUS_NO_MEMORY
;
820 /* Show debug message */
823 DPRINT1("LDR: TlsVector %x Index %d = %x copied from %x to %x\n",
825 TlsData
->TlsDirectory
.Characteristics
,
826 &TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
827 TlsData
->TlsDirectory
.StartAddressOfRawData
,
828 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
832 RtlCopyMemory(TlsVector
[TlsData
->TlsDirectory
.Characteristics
],
833 (PVOID
)TlsData
->TlsDirectory
.StartAddressOfRawData
,
838 return STATUS_SUCCESS
;
845 PLIST_ENTRY ListHead
, NextEntry
;
846 PLDRP_TLS_DATA TlsData
;
848 PTEB Teb
= NtCurrentTeb();
850 /* Get a pointer to the vector array */
851 TlsVector
= Teb
->ThreadLocalStoragePointer
;
852 if (!TlsVector
) return;
854 /* Loop through it */
855 ListHead
= &LdrpTlsList
;
856 NextEntry
= ListHead
->Flink
;
857 while (NextEntry
!= ListHead
)
859 TlsData
= CONTAINING_RECORD(NextEntry
, LDRP_TLS_DATA
, TlsLinks
);
860 NextEntry
= NextEntry
->Flink
;
862 /* Free each entry */
863 if (TlsVector
[TlsData
->TlsDirectory
.Characteristics
])
865 RtlFreeHeap(RtlGetProcessHeap(),
867 TlsVector
[TlsData
->TlsDirectory
.Characteristics
]);
871 /* Free the array itself */
872 RtlFreeHeap(RtlGetProcessHeap(),
879 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName
, PPEB Peb
, PULONG Options
)
883 return STATUS_SUCCESS
;
888 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
)
895 LdrpInitializeProcess(IN PCONTEXT Context
,
896 IN PVOID SystemArgument1
)
898 RTL_HEAP_PARAMETERS HeapParameters
;
899 ULONG ComSectionSize
;
900 //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData");
902 OBJECT_ATTRIBUTES ObjectAttributes
;
903 //UNICODE_STRING LocalFileName, FullImageName;
904 HANDLE SymLinkHandle
;
905 //ULONG DebugHeapOnly;
906 UNICODE_STRING CommandLine
, NtSystemRoot
, ImagePathName
, FullPath
, ImageFileName
, KnownDllString
;
907 PPEB Peb
= NtCurrentPeb();
908 BOOLEAN IsDotNetImage
= FALSE
;
909 BOOLEAN FreeCurDir
= FALSE
;
911 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
912 //LPWSTR ImagePathBuffer;
914 UNICODE_STRING CurrentDirectory
;
915 ULONG ExecuteOptions
;
917 PIMAGE_NT_HEADERS NtHeader
;
918 LPWSTR NtDllName
= NULL
;
920 NLSTABLEINFO NlsTable
;
921 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig
;
922 PTEB Teb
= NtCurrentTeb();
923 PLIST_ENTRY ListHead
;
924 PLIST_ENTRY NextEntry
;
927 ULONG DebugProcessHeapOnly
= 0;
928 WCHAR FullNtDllPath
[MAX_PATH
];
929 PLDR_DATA_TABLE_ENTRY NtLdrEntry
;
932 /* Set a NULL SEH Filter */
933 RtlSetUnhandledExceptionFilter(NULL
);
935 /* Get the image path */
936 ImagePath
= Peb
->ProcessParameters
->ImagePathName
.Buffer
;
938 /* Check if it's normalized */
939 if (Peb
->ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_NORMALIZED
)
942 ImagePath
= (PWSTR
)((ULONG_PTR
)ImagePath
+ (ULONG_PTR
)Peb
->ProcessParameters
);
945 /* Create a unicode string for the Image Path */
946 ImagePathName
.Length
= Peb
->ProcessParameters
->ImagePathName
.Length
;
947 ImagePathName
.MaximumLength
= ImagePathName
.Length
+ sizeof(WCHAR
);
948 ImagePathName
.Buffer
= ImagePath
;
950 /* Get the NT Headers */
951 NtHeader
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
953 /* Get the execution options */
954 Status
= LdrpInitializeExecutionOptions(&ImagePathName
, Peb
, &ExecuteOptions
);
956 /* Check if this is a .NET executable */
957 if (RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
959 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
,
962 /* Remeber this for later */
963 IsDotNetImage
= TRUE
;
966 /* Save the NTDLL Base address */
967 NtDllBase
= SystemArgument1
;
969 /* If this is a Native Image */
970 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
)
972 /* Then do DLL Validation */
973 LdrpDllValidation
= TRUE
;
976 /* Save the old Shim Data */
977 OldShimData
= Peb
->pShimData
;
980 Peb
->pShimData
= NULL
;
982 /* Save the number of processors and CS Timeout */
983 LdrpNumberOfProcessors
= Peb
->NumberOfProcessors
;
984 RtlpTimeout
= Peb
->CriticalSectionTimeout
;
986 /* Normalize the parameters */
987 ProcessParameters
= RtlNormalizeProcessParams(Peb
->ProcessParameters
);
988 ProcessParameters
= Peb
->ProcessParameters
;
989 if (ProcessParameters
)
991 /* Save the Image and Command Line Names */
992 ImageFileName
= ProcessParameters
->ImagePathName
;
993 CommandLine
= ProcessParameters
->CommandLine
;
997 /* It failed, initialize empty strings */
998 RtlInitUnicodeString(&ImageFileName
, NULL
);
999 RtlInitUnicodeString(&CommandLine
, NULL
);
1002 /* Initialize NLS data */
1003 RtlInitNlsTables(Peb
->AnsiCodePageData
,
1004 Peb
->OemCodePageData
,
1005 Peb
->UnicodeCaseTableData
,
1008 /* Reset NLS Translations */
1009 RtlResetRtlTranslations(&NlsTable
);
1011 /* Get the Image Config Directory */
1012 LoadConfig
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
1014 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
1017 /* Setup the Heap Parameters */
1018 RtlZeroMemory(&HeapParameters
, sizeof(RTL_HEAP_PARAMETERS
));
1019 HeapFlags
= HEAP_GROWABLE
;
1020 HeapParameters
.Length
= sizeof(RTL_HEAP_PARAMETERS
);
1022 /* Check if we have Configuration Data */
1023 if ((LoadConfig
) && (ConfigSize
== sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
)))
1025 /* FIXME: Custom heap settings and misc. */
1026 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1029 /* Check for custom affinity mask */
1030 if (Peb
->ImageProcessAffinityMask
)
1033 Status
= NtSetInformationProcess(NtCurrentProcess(),
1034 ProcessAffinityMask
,
1035 &Peb
->ImageProcessAffinityMask
,
1036 sizeof(Peb
->ImageProcessAffinityMask
));
1039 /* Check if verbose debugging (ShowSnaps) was requested */
1040 ShowSnaps
= TRUE
;//Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
1042 /* Start verbose debugging messages right now if they were requested */
1045 DPRINT1("LDR: PID: 0x%x started - '%wZ'\n",
1046 Teb
->ClientId
.UniqueProcess
,
1050 /* If the timeout is too long */
1051 if (RtlpTimeout
.QuadPart
< Int32x32To64(3600, -10000000))
1053 /* Then disable CS Timeout */
1054 RtlpTimeoutDisable
= TRUE
;
1057 /* Initialize Critical Section Data */
1058 RtlpInitDeferedCriticalSection();
1060 /* Initialize VEH Call lists */
1061 RtlpInitializeVectoredExceptionHandling();
1063 /* Set TLS/FLS Bitmap data */
1064 Peb
->FlsBitmap
= &FlsBitMap
;
1065 Peb
->TlsBitmap
= &TlsBitMap
;
1066 Peb
->TlsExpansionBitmap
= &TlsExpansionBitMap
;
1068 /* Initialize FLS Bitmap */
1069 RtlInitializeBitMap(&FlsBitMap
,
1071 FLS_MAXIMUM_AVAILABLE
);
1072 RtlSetBit(&FlsBitMap
, 0);
1074 /* Initialize TLS Bitmap */
1075 RtlInitializeBitMap(&TlsBitMap
,
1077 TLS_MINIMUM_AVAILABLE
);
1078 RtlSetBit(&TlsBitMap
, 0);
1079 RtlInitializeBitMap(&TlsExpansionBitMap
,
1080 Peb
->TlsExpansionBitmapBits
,
1081 TLS_EXPANSION_SLOTS
);
1082 RtlSetBit(&TlsExpansionBitMap
, 0);
1084 /* Initialize the Hash Table */
1085 for (i
= 0; i
< LDR_HASH_TABLE_ENTRIES
; i
++)
1087 InitializeListHead(&LdrpHashTable
[i
]);
1090 /* Initialize the Loader Lock */
1091 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1092 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1094 LdrpLoaderLockInit
= TRUE
;
1096 /* Check if User Stack Trace Database support was requested */
1097 if (Peb
->NtGlobalFlag
& FLG_USER_STACK_TRACE_DB
)
1099 DPRINT1("We don't support user stack trace databases yet\n");
1102 /* Setup Fast PEB Lock */
1103 RtlInitializeCriticalSection(&FastPebLock
);
1104 Peb
->FastPebLock
= &FastPebLock
;
1105 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1106 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1108 /* Setup Callout Lock and Notification list */
1109 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1110 InitializeListHead(&LdrpDllNotificationList
);
1112 /* For old executables, use 16-byte aligned heap */
1113 if ((NtHeader
->OptionalHeader
.MajorSubsystemVersion
<= 3) &&
1114 (NtHeader
->OptionalHeader
.MinorSubsystemVersion
< 51))
1116 HeapFlags
|= HEAP_CREATE_ALIGN_16
;
1119 /* Setup the Heap */
1120 RtlInitializeHeapManager();
1121 Peb
->ProcessHeap
= RtlCreateHeap(HeapFlags
,
1123 NtHeader
->OptionalHeader
.SizeOfHeapReserve
,
1124 NtHeader
->OptionalHeader
.SizeOfHeapCommit
,
1128 if (!Peb
->ProcessHeap
)
1130 DPRINT1("Failed to create process heap\n");
1131 return STATUS_NO_MEMORY
;
1134 /* Allocate an Activation Context Stack */
1135 Status
= RtlAllocateActivationContextStack((PVOID
*)&Teb
->ActivationContextStackPointer
);
1136 if (!NT_SUCCESS(Status
)) return Status
;
1138 // FIXME: Loader private heap is missing
1139 DPRINT1("Loader private heap is missing\n");
1141 /* Check for Debug Heap */
1142 DPRINT1("Check for a debug heap is missing\n");
1145 /* Query the setting */
1146 Status
= LdrQueryImageFileKeyOption(NULL
,//hKey
1147 L
"DebugProcessHeapOnly",
1149 &DebugProcessHeapOnly
,
1153 if (NT_SUCCESS(Status
))
1155 /* Reset DPH if requested */
1156 if (RtlpPageHeapEnabled
&& DebugProcessHeapOnly
)
1158 RtlpDphGlobalFlags
&= ~0x40;
1159 RtlpPageHeapEnabled
= FALSE
;
1164 /* Build the NTDLL Path */
1165 FullPath
.Buffer
= FullNtDllPath
;
1166 FullPath
.Length
= 0;
1167 FullPath
.MaximumLength
= sizeof(FullNtDllPath
);
1168 RtlInitUnicodeString(&NtSystemRoot
, SharedUserData
->NtSystemRoot
);
1169 RtlAppendUnicodeStringToString(&FullPath
, &NtSystemRoot
);
1170 RtlAppendUnicodeToString(&FullPath
, L
"\\System32\\");
1172 /* Open the Known DLLs directory */
1173 RtlInitUnicodeString(&KnownDllString
, L
"\\KnownDlls");
1174 InitializeObjectAttributes(&ObjectAttributes
,
1176 OBJ_CASE_INSENSITIVE
,
1179 Status
= ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory
,
1180 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
1183 /* Check if it exists */
1184 if (!NT_SUCCESS(Status
))
1186 /* It doesn't, so assume System32 */
1187 LdrpKnownDllObjectDirectory
= NULL
;
1188 RtlInitUnicodeString(&LdrpKnownDllPath
, FullPath
.Buffer
);
1189 LdrpKnownDllPath
.Length
-= sizeof(WCHAR
);
1193 /* Open the Known DLLs Path */
1194 InitializeObjectAttributes(&ObjectAttributes
,
1196 OBJ_CASE_INSENSITIVE
,
1197 LdrpKnownDllObjectDirectory
,
1199 Status
= NtOpenSymbolicLinkObject(&SymLinkHandle
,
1200 SYMBOLIC_LINK_QUERY
,
1202 if (NT_SUCCESS(Status
))
1204 /* Query the path */
1205 LdrpKnownDllPath
.Length
= 0;
1206 LdrpKnownDllPath
.MaximumLength
= sizeof(LdrpKnownDllPathBuffer
);
1207 LdrpKnownDllPath
.Buffer
= LdrpKnownDllPathBuffer
;
1208 Status
= ZwQuerySymbolicLinkObject(SymLinkHandle
, &LdrpKnownDllPath
, NULL
);
1209 NtClose(SymLinkHandle
);
1210 if (!NT_SUCCESS(Status
))
1212 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status
);
1218 /* If we have process parameters, get the default path and current path */
1219 if (ProcessParameters
)
1221 /* Check if we have a Dll Path */
1222 if (ProcessParameters
->DllPath
.Length
)
1225 LdrpDefaultPath
= *(PUNICODE_STRING
)&ProcessParameters
->DllPath
;
1229 /* We need a valid path */
1230 LdrpInitFailure(STATUS_INVALID_PARAMETER
);
1233 /* Set the current directory */
1234 CurrentDirectory
= ProcessParameters
->CurrentDirectory
.DosPath
;
1236 /* Check if it's empty or invalid */
1237 if ((!CurrentDirectory
.Buffer
) ||
1238 (CurrentDirectory
.Buffer
[0] == UNICODE_NULL
) ||
1239 (!CurrentDirectory
.Length
))
1241 /* Allocate space for the buffer */
1242 CurrentDirectory
.Buffer
= RtlAllocateHeap(Peb
->ProcessHeap
,
1245 sizeof(UNICODE_NULL
));
1247 /* Copy the drive of the system root */
1248 RtlMoveMemory(CurrentDirectory
.Buffer
,
1249 SharedUserData
->NtSystemRoot
,
1251 CurrentDirectory
.Buffer
[3] = UNICODE_NULL
;
1252 CurrentDirectory
.Length
= 3 * sizeof(WCHAR
);
1253 CurrentDirectory
.MaximumLength
= CurrentDirectory
.Length
+ sizeof(WCHAR
);
1259 /* Use the local buffer */
1260 CurrentDirectory
.Length
= NtSystemRoot
.Length
;
1261 CurrentDirectory
.Buffer
= NtSystemRoot
.Buffer
;
1265 /* Setup Loader Data */
1267 InitializeListHead(&PebLdr
.InLoadOrderModuleList
);
1268 InitializeListHead(&PebLdr
.InMemoryOrderModuleList
);
1269 InitializeListHead(&PebLdr
.InInitializationOrderModuleList
);
1270 PebLdr
.Length
= sizeof(PEB_LDR_DATA
);
1271 PebLdr
.Initialized
= TRUE
;
1273 /* Allocate a data entry for the Image */
1274 LdrpImageEntry
= NtLdrEntry
= LdrpAllocateDataTableEntry(Peb
->ImageBaseAddress
);
1277 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
1278 NtLdrEntry
->LoadCount
= -1;
1279 NtLdrEntry
->EntryPointActivationContext
= 0;
1280 NtLdrEntry
->FullDllName
.Length
= ImageFileName
.Length
;
1281 NtLdrEntry
->FullDllName
.Buffer
= ImageFileName
.Buffer
;
1283 NtLdrEntry
->Flags
= LDRP_COR_IMAGE
;
1285 NtLdrEntry
->Flags
= 0;
1287 /* Check if the name is empty */
1288 if (!ImageFileName
.Buffer
[0])
1290 /* Use the same Base name */
1291 NtLdrEntry
->BaseDllName
= NtLdrEntry
->BaseDllName
;
1295 /* Find the last slash */
1296 Current
= ImageFileName
.Buffer
;
1299 if (*Current
++ == '\\')
1302 NtDllName
= Current
;
1306 /* Did we find anything? */
1309 /* Use the same Base name */
1310 NtLdrEntry
->BaseDllName
= NtLdrEntry
->FullDllName
;
1314 /* Setup the name */
1315 NtLdrEntry
->BaseDllName
.Length
= (USHORT
)((ULONG_PTR
)ImageFileName
.Buffer
+ ImageFileName
.Length
- (ULONG_PTR
)NtDllName
);
1316 NtLdrEntry
->BaseDllName
.MaximumLength
= NtLdrEntry
->BaseDllName
.Length
+ sizeof(WCHAR
);
1317 NtLdrEntry
->BaseDllName
.Buffer
= (PWSTR
)((ULONG_PTR
)ImageFileName
.Buffer
+
1318 (ImageFileName
.Length
- NtLdrEntry
->BaseDllName
.Length
));
1322 /* Processing done, insert it */
1323 LdrpInsertMemoryTableEntry(NtLdrEntry
);
1324 NtLdrEntry
->Flags
|= LDRP_ENTRY_PROCESSED
;
1326 /* Now add an entry for NTDLL */
1327 NtLdrEntry
= LdrpAllocateDataTableEntry(SystemArgument1
);
1328 NtLdrEntry
->Flags
= LDRP_IMAGE_DLL
;
1329 NtLdrEntry
->EntryPoint
= LdrpFetchAddressOfEntryPoint(NtLdrEntry
->DllBase
);
1330 NtLdrEntry
->LoadCount
= -1;
1331 NtLdrEntry
->EntryPointActivationContext
= 0;
1332 //NtLdrEntry->BaseDllName.Length = NtSystemRoot.Length;
1333 //RtlAppendUnicodeStringToString(&NtSystemRoot, &NtDllString);
1334 NtLdrEntry
->BaseDllName
.Length
= NtDllString
.Length
;
1335 NtLdrEntry
->BaseDllName
.MaximumLength
= NtDllString
.MaximumLength
;
1336 NtLdrEntry
->BaseDllName
.Buffer
= NtDllString
.Buffer
;
1338 // FIXME: Full DLL name?!
1340 /* Processing done, insert it */
1341 LdrpNtDllDataTableEntry
= NtLdrEntry
;
1342 LdrpInsertMemoryTableEntry(NtLdrEntry
);
1344 /* Let the world know */
1347 DPRINT1("LDR: NEW PROCESS\n");
1348 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry
->FullDllName
, &LdrpImageEntry
->BaseDllName
);
1349 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory
);
1350 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath
);
1353 /* Link the Init Order List */
1354 InsertHeadList(&Peb
->Ldr
->InInitializationOrderModuleList
,
1355 &LdrpNtDllDataTableEntry
->InInitializationOrderModuleList
);
1357 /* Set the current directory */
1358 Status
= RtlSetCurrentDirectory_U(&CurrentDirectory
);
1359 if (!NT_SUCCESS(Status
))
1361 /* We failed, check if we should free it */
1362 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
1364 /* Set it to the NT Root */
1365 CurrentDirectory
= NtSystemRoot
;
1366 RtlSetCurrentDirectory_U(&CurrentDirectory
);
1370 /* We're done with it, free it */
1371 if (FreeCurDir
) RtlFreeUnicodeString(&CurrentDirectory
);
1374 /* Check if we should look for a .local file */
1375 if (ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH
)
1378 DPRINT1("We don't support .local overrides yet\n");
1381 /* Check if the Application Verifier was enabled */
1382 if (Peb
->NtGlobalFlag
& FLG_POOL_ENABLE_TAIL_CHECK
)
1385 DPRINT1("We don't support Application Verifier yet\n");
1391 DPRINT1("We don't support .NET applications yet\n");
1394 /* FIXME: Load support for Terminal Services */
1395 if (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
)
1397 /* Load kernel32 and call BasePostImportInit... */
1398 DPRINT1("Unimplemented codepath!\n");
1401 /* Walk the IAT and load all the DLLs */
1402 LdrpWalkImportDescriptor(LdrpDefaultPath
.Buffer
, LdrpImageEntry
);
1404 /* Check if relocation is needed */
1405 if (Peb
->ImageBaseAddress
!= (PVOID
)NtHeader
->OptionalHeader
.ImageBase
)
1407 DPRINT("LDR: Performing relocations\n");
1408 Status
= LdrPerformRelocations(NtHeader
, Peb
->ImageBaseAddress
);
1409 if (!NT_SUCCESS(Status
))
1411 DPRINT1("LdrPerformRelocations() failed\n");
1412 return STATUS_INVALID_IMAGE_FORMAT
;
1417 ListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
1418 NextEntry
= ListHead
->Flink
;
1419 while (ListHead
!= NextEntry
)
1421 NtLdrEntry
= CONTAINING_RECORD(NextEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1422 NtLdrEntry
->LoadCount
= -1;
1423 NextEntry
= NextEntry
->Flink
;
1426 /* Phase 0 is done */
1427 LdrpLdrDatabaseIsSetup
= TRUE
;
1429 /* Initialize TLS */
1430 Status
= LdrpInitializeTls();
1431 if (!NT_SUCCESS(Status
))
1433 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
1438 /* FIXME Mark the DLL Ranges for Stack Traces later */
1440 /* Notify the debugger now */
1441 if (Peb
->BeingDebugged
)
1446 /* Update show snaps again */
1447 ShowSnaps
= Peb
->NtGlobalFlag
& FLG_SHOW_LDR_SNAPS
;
1450 /* Validate the Image for MP Usage */
1451 if (LdrpNumberOfProcessors
> 1) LdrpValidateImageForMp(LdrpImageEntry
);
1453 /* Check NX Options */
1454 if (SharedUserData
->NXSupportPolicy
== 1)
1456 ExecuteOptions
= 0xD;
1458 else if (!SharedUserData
->NXSupportPolicy
)
1460 ExecuteOptions
= 0xA;
1464 ZwSetInformationProcess(NtCurrentProcess(),
1465 ProcessExecuteFlags
,
1469 /* Check if we had Shim Data */
1472 /* Load the Shim Engine */
1473 Peb
->AppCompatInfo
= NULL
;
1474 //LdrpLoadShimEngine(OldShimData, ImagePathName, OldShimData);
1475 DPRINT1("We do not support shims yet\n");
1479 /* Check for Application Compatibility Goo */
1480 //LdrQueryApplicationCompatibilityGoo(hKey);
1481 DPRINT1("Querying app compat hacks is missing!\n");
1485 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
1486 * incompatible images.
1489 /* Now call the Init Routines */
1490 Status
= LdrpRunInitializeRoutines(Context
);
1491 if (!NT_SUCCESS(Status
))
1493 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
1498 /* FIXME: Unload the Shim Engine if it was loaded */
1500 /* Check if we have a user-defined Post Process Routine */
1501 if (NT_SUCCESS(Status
) && Peb
->PostProcessInitRoutine
)
1505 Peb
->PostProcessInitRoutine();
1508 ///* Close the key if we have one opened */
1509 //if (hKey) NtClose(hKey);
1517 LdrpInitFailure(NTSTATUS Status
)
1521 /* Print a debug message */
1522 DPRINT1("LDR: Process initialization failure; NTSTATUS = %08lx\n", Status
);
1524 /* Raise a hard error */
1525 if (!LdrpFatalHardErrorCount
)
1527 ZwRaiseHardError(STATUS_APP_INIT_FAILURE
, 1, 0, (PULONG_PTR
)&Status
, OptionOk
, &Response
);
1533 LdrpInit(PCONTEXT Context
,
1534 PVOID SystemArgument1
,
1535 PVOID SystemArgument2
)
1537 LARGE_INTEGER Timeout
;
1538 PTEB Teb
= NtCurrentTeb();
1539 NTSTATUS Status
, LoaderStatus
= STATUS_SUCCESS
;
1540 MEMORY_BASIC_INFORMATION MemoryBasicInfo
;
1541 PPEB Peb
= NtCurrentPeb();
1543 DPRINT("LdrpInit()\n");
1545 /* Check if we have a deallocation stack */
1546 if (!Teb
->DeallocationStack
)
1548 /* We don't, set one */
1549 Status
= NtQueryVirtualMemory(NtCurrentProcess(),
1550 Teb
->NtTib
.StackLimit
,
1551 MemoryBasicInformation
,
1553 sizeof(MEMORY_BASIC_INFORMATION
),
1555 if (!NT_SUCCESS(Status
))
1558 LdrpInitFailure(Status
);
1559 RtlRaiseStatus(Status
);
1564 Teb
->DeallocationStack
= MemoryBasicInfo
.AllocationBase
;
1567 /* Now check if the process is already being initialized */
1568 while (_InterlockedCompareExchange(&LdrpProcessInitialized
,
1572 /* Set the timeout to 30 seconds */
1573 Timeout
.QuadPart
= Int32x32To64(30, -10000);
1575 /* Make sure the status hasn't changed */
1576 while (!LdrpProcessInitialized
)
1579 ZwDelayExecution(FALSE
, &Timeout
);
1583 /* Check if we have already setup LDR data */
1586 /* Setup the Loader Lock */
1587 Peb
->LoaderLock
= &LdrpLoaderLock
;
1589 /* Let other code know we're initializing */
1590 LdrpInLdrInit
= TRUE
;
1592 /* Protect with SEH */
1595 /* Initialize the Process */
1596 LoaderStatus
= LdrpInitializeProcess_(Context
,
1599 /* Check for success and if MinimumStackCommit was requested */
1600 if (NT_SUCCESS(LoaderStatus
) && Peb
->MinimumStackCommit
)
1602 /* Enforce the limit */
1603 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
1607 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1609 /* Fail with the SEH error */
1610 LoaderStatus
= _SEH2_GetExceptionCode();
1614 /* We're not initializing anymore */
1615 LdrpInLdrInit
= FALSE
;
1617 /* Check if init worked */
1618 if (NT_SUCCESS(LoaderStatus
))
1620 /* Set the process as Initialized */
1621 _InterlockedIncrement(&LdrpProcessInitialized
);
1626 /* Loader data is there... is this a fork() ? */
1627 if(Peb
->InheritedAddressSpace
)
1629 /* Handle the fork() */
1630 //LoaderStatus = LdrpForkProcess();
1631 LoaderStatus
= STATUS_NOT_IMPLEMENTED
;
1636 /* This is a new thread initializing */
1637 LdrpInitializeThread(Context
);
1641 /* All done, test alert the thread */
1645 if (!NT_SUCCESS(LoaderStatus
))
1648 LdrpInitFailure(LoaderStatus
);
1649 RtlRaiseStatus(LoaderStatus
);