1 /* $Id: utils.c,v 1.59 2003/01/31 21:49:11 hbirr Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: lib/ntdll/ldr/utils.c
6 * PURPOSE: Process startup for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
13 * - Fix calling of entry points
14 * - Handle loading flags correctly
18 /* INCLUDES *****************************************************************/
20 #include <reactos/config.h>
21 #include <ddk/ntddk.h>
25 #include <ntdll/ldr.h>
26 #include <ntos/minmax.h>
29 #ifdef DBG_NTDLL_LDR_UTILS
32 #include <ntdll/ntdll.h>
34 /* PROTOTYPES ****************************************************************/
36 static NTSTATUS
LdrFindEntryForName(PUNICODE_STRING Name
, PLDR_MODULE
*Module
);
37 static PVOID
LdrFixupForward(PCHAR ForwardName
);
38 static PVOID
LdrGetExportByName(PVOID BaseAddress
, PUCHAR SymbolName
, USHORT Hint
);
41 /* FUNCTIONS *****************************************************************/
47 LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule
)
61 /***************************************************************************
66 * Adjusts the name of a dll to a fully qualified name.
69 * FullDllName: Pointer to caller supplied storage for the fully
71 * DllName: Pointer to the dll name.
72 * BaseName: TRUE: Only the file name is passed to FullDllName
73 * FALSE: The full path is preserved in FullDllName
81 * A given path is not affected by the adjustment, but the file
85 * ntdll.xyz --> ntdll.xyz
89 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
90 PUNICODE_STRING DllName
,
93 WCHAR Buffer
[MAX_PATH
];
98 Length
= DllName
->Length
/ sizeof(WCHAR
);
100 if (BaseName
== TRUE
)
102 /* get the base dll name */
103 Pointer
= DllName
->Buffer
+ Length
;
110 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
113 Length
= Extension
- Pointer
;
114 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
115 Buffer
[Length
] = L
'\0';
119 /* get the full dll name */
120 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
121 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
124 /* Build the DLL's absolute name */
125 Extension
= wcsrchr (Buffer
, L
'.');
126 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
128 /* with extension - remove dot if it's the last character */
129 if (Buffer
[Length
- 1] == L
'.')
135 /* name without extension - assume that it is .dll */
136 memmove (Buffer
+ Length
, L
".dll", 10);
139 RtlCreateUnicodeString(FullDllName
, Buffer
);
143 LdrAddModuleEntry(PVOID ImageBase
, PIMAGE_NT_HEADERS NTHeaders
,
147 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_MODULE
));
149 Module
->BaseAddress
= (PVOID
)ImageBase
;
150 Module
->EntryPoint
= NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
151 if (Module
->EntryPoint
!= 0)
152 Module
->EntryPoint
+= (ULONG
)Module
->BaseAddress
;
153 Module
->SizeOfImage
= NTHeaders
->OptionalHeader
.SizeOfImage
;
154 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
156 /* loading while app is running */
157 Module
->LoadCount
= 1;
160 * loading while app is initializing
161 * dll must not be unloaded
163 Module
->LoadCount
= -1;
166 Module
->TlsIndex
= 0;
167 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
168 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
170 RtlCreateUnicodeString (&Module
->FullDllName
,
172 RtlCreateUnicodeString (&Module
->BaseDllName
,
173 wcsrchr(FullDosName
, L
'\\') + 1);
174 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
176 /* FIXME: aquire loader lock */
177 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
178 &Module
->InLoadOrderModuleList
);
179 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
180 &Module
->InInitializationOrderModuleList
);
181 /* FIXME: release loader lock */
186 /***************************************************************************
203 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
205 IN PUNICODE_STRING Name
,
206 OUT PVOID
*BaseAddress OPTIONAL
)
208 WCHAR SearchPathBuffer
[MAX_PATH
];
209 WCHAR FullDosName
[MAX_PATH
];
210 UNICODE_STRING AdjustedName
;
211 UNICODE_STRING FullNtFileName
;
212 OBJECT_ATTRIBUTES FileObjectAttributes
;
213 char BlockBuffer
[1024];
214 PIMAGE_DOS_HEADER DosHeader
;
216 PIMAGE_NT_HEADERS NTHeaders
;
218 ULONG InitialViewSize
;
221 HANDLE SectionHandle
;
222 PDLLMAIN_FUNC Entrypoint
= NULL
;
227 *BaseAddress
= NtCurrentPeb()->ImageBaseAddress
;
228 return STATUS_SUCCESS
;
233 DPRINT("LdrLoadDll(Name \"%wZ\" BaseAddress %x)\n",
236 /* adjust the full dll name */
237 LdrAdjustDllName (&AdjustedName
,
240 DPRINT("AdjustedName: %wZ\n", &AdjustedName
);
243 * Test if dll is already loaded.
245 if (LdrFindEntryForName(&AdjustedName
, &Module
) == STATUS_SUCCESS
)
247 DPRINT("DLL %wZ already loaded.\n", &AdjustedName
);
248 if (Module
->LoadCount
!= -1)
250 *BaseAddress
= Module
->BaseAddress
;
251 return STATUS_SUCCESS
;
253 DPRINT("Loading \"%wZ\"\n", Name
);
255 if (SearchPath
== NULL
)
257 SearchPath
= SearchPathBuffer
;
258 wcscpy (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
259 wcscat (SearchPathBuffer
, L
"\\system32;");
260 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
261 wcscat (SearchPathBuffer
, L
";.");
264 DPRINT("SearchPath %S\n", SearchPath
);
266 if (RtlDosSearchPath_U (SearchPath
,
272 return STATUS_DLL_NOT_FOUND
;
274 DPRINT("FullDosName %S\n", FullDosName
);
276 RtlFreeUnicodeString (&AdjustedName
);
278 if (!RtlDosPathNameToNtPathName_U (FullDosName
,
282 return STATUS_DLL_NOT_FOUND
;
284 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
286 InitializeObjectAttributes(&FileObjectAttributes
,
292 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
294 Status
= ZwOpenFile(&FileHandle
,
296 &FileObjectAttributes
,
300 if (!NT_SUCCESS(Status
))
302 DbgPrint("Dll open of %wZ failed: Status = 0x%08x\n",
303 &FullNtFileName
, Status
);
304 RtlFreeUnicodeString (&FullNtFileName
);
307 RtlFreeUnicodeString (&FullNtFileName
);
309 Status
= ZwReadFile(FileHandle
,
318 if (!NT_SUCCESS(Status
))
320 DPRINT("Dll header read failed: Status = 0x%08x\n", Status
);
325 * Overlay DOS and NT headers structures to the
326 * buffer with DLL's header raw data.
328 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
329 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
331 * Check it is a PE image file.
333 if ((DosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
334 || (DosHeader
->e_lfanew
== 0L)
335 || (*(PULONG
)(NTHeaders
) != IMAGE_PE_MAGIC
))
337 DPRINT("NTDLL format invalid\n");
340 return STATUS_UNSUCCESSFUL
;
343 ImageBase
= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
;
344 ImageSize
= NTHeaders
->OptionalHeader
.SizeOfImage
;
346 DPRINT("ImageBase 0x%08x\n", ImageBase
);
349 * Create a section for dll.
351 Status
= ZwCreateSection(&SectionHandle
,
356 SEC_COMMIT
| SEC_IMAGE
,
358 if (!NT_SUCCESS(Status
))
360 DPRINT("NTDLL create section failed: Status = 0x%08x\n", Status
);
366 * Map the dll into the process.
370 Status
= ZwMapViewOfSection(SectionHandle
,
380 if (!NT_SUCCESS(Status
))
382 DbgPrint("NTDLL.LDR: map view of section failed (Status %x)\n", Status
);
388 /* relocate dll and fixup import table */
389 if ((NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
) ==
393 (PDLLMAIN_FUNC
) LdrPEStartup(ImageBase
, SectionHandle
, &Module
,
395 if (Entrypoint
== NULL
)
397 return(STATUS_UNSUCCESSFUL
);
403 LdrpLoadUserModuleSymbols(Module
);
408 if ((NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
) ==
411 if (Module
->EntryPoint
!= 0)
413 Entrypoint
= (PDLLMAIN_FUNC
)Module
->EntryPoint
;
415 DPRINT("Calling entry point at 0x%08x\n", Entrypoint
);
416 if (FALSE
== Entrypoint(Module
->BaseAddress
,
420 DPRINT("NTDLL.LDR: DLL \"%wZ\" failed to initialize\n",
421 &Module
->BaseDllName
);
422 /* FIXME: should clean up and fail */
426 DPRINT("NTDLL.LDR: DLL \"%wZ\" initialized successfully\n",
427 &Module
->BaseDllName
);
432 DPRINT("NTDLL.LDR: Entrypoint is NULL for \"%wZ\"\n",
433 &Module
->BaseDllName
);
437 *BaseAddress
= Module
->BaseAddress
;
438 return STATUS_SUCCESS
;
442 /***************************************************************************
444 * LdrFindEntryForAddress
458 LdrFindEntryForAddress(PVOID Address
,
461 PLIST_ENTRY ModuleListHead
;
463 PLDR_MODULE ModulePtr
;
465 DPRINT("NTDLL.LdrFindEntryForAddress(Address %p)\n", Address
);
467 if (NtCurrentPeb()->Ldr
== NULL
)
468 return(STATUS_NO_MORE_ENTRIES
);
470 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
471 Entry
= ModuleListHead
->Flink
;
472 if (Entry
== ModuleListHead
)
473 return(STATUS_NO_MORE_ENTRIES
);
475 while (Entry
!= ModuleListHead
)
477 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InLoadOrderModuleList
);
479 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->BaseAddress
);
481 if ((Address
>= ModulePtr
->BaseAddress
) &&
482 (Address
<= (ModulePtr
->BaseAddress
+ ModulePtr
->SizeOfImage
)))
485 return(STATUS_SUCCESS
);
488 Entry
= Entry
->Flink
;
491 DPRINT("Failed to find module entry.\n");
493 return(STATUS_NO_MORE_ENTRIES
);
497 /***************************************************************************
499 * LdrFindEntryForName
513 LdrFindEntryForName(PUNICODE_STRING Name
,
516 PLIST_ENTRY ModuleListHead
;
518 PLDR_MODULE ModulePtr
;
520 DPRINT("NTDLL.LdrFindEntryForName(Name %wZ)\n", Name
);
522 if (NtCurrentPeb()->Ldr
== NULL
)
523 return(STATUS_NO_MORE_ENTRIES
);
525 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
526 Entry
= ModuleListHead
->Flink
;
527 if (Entry
== ModuleListHead
)
528 return(STATUS_NO_MORE_ENTRIES
);
530 // NULL is the current process
533 *Module
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InLoadOrderModuleList
);
534 return(STATUS_SUCCESS
);
537 while (Entry
!= ModuleListHead
)
539 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InLoadOrderModuleList
);
541 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, Name
);
543 if (RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, Name
, TRUE
) == 0)
546 return(STATUS_SUCCESS
);
549 Entry
= Entry
->Flink
;
552 DPRINT("Failed to find dll %wZ\n", Name
);
554 return(STATUS_NO_MORE_ENTRIES
);
557 /**********************************************************************
573 LdrFixupForward(PCHAR ForwardName
)
575 CHAR NameBuffer
[128];
576 UNICODE_STRING DllName
;
577 UNICODE_STRING FunctionName
;
582 strcpy(NameBuffer
, ForwardName
);
583 p
= strchr(NameBuffer
, '.');
588 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
589 RtlCreateUnicodeStringFromAsciiz (&DllName
,
592 Status
= LdrGetDllHandle (0, 0, &DllName
, &BaseAddress
);
593 if (!NT_SUCCESS(Status
))
595 Status
= LdrLoadDll(NULL
,
599 if (!NT_SUCCESS(Status
))
601 DbgPrint("LdrFixupForward: failed to load %wZ\n", &DllName
);
602 RtlFreeUnicodeString (&DllName
);
607 RtlFreeUnicodeString (&DllName
);
608 DPRINT("BaseAddress: %p\n", BaseAddress
);
610 return LdrGetExportByName(BaseAddress
, p
+1, -1);
617 /**********************************************************************
619 * LdrGetExportByOrdinal
633 LdrGetExportByOrdinal (
638 PIMAGE_EXPORT_DIRECTORY ExportDir
;
639 PDWORD
* ExFunctions
;
642 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
643 RtlImageDirectoryEntryToData (BaseAddress
,
645 IMAGE_DIRECTORY_ENTRY_EXPORT
,
649 ExOrdinals
= (USHORT
*)
652 ExportDir
->AddressOfNameOrdinals
654 ExFunctions
= (PDWORD
*)
657 ExportDir
->AddressOfFunctions
660 "LdrGetExportByOrdinal(Ordinal %d) = %x\n",
662 ExFunctions
[ExOrdinals
[Ordinal
- ExportDir
->Base
]]
664 return(ExFunctions
[ExOrdinals
[Ordinal
- ExportDir
->Base
]]);
668 /**********************************************************************
684 LdrGetExportByName(PVOID BaseAddress
,
688 PIMAGE_EXPORT_DIRECTORY ExportDir
;
689 PDWORD
* ExFunctions
;
699 DPRINT("LdrGetExportByName %x %s %hu\n", BaseAddress
, SymbolName
, Hint
);
701 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
702 RtlImageDirectoryEntryToData(BaseAddress
,
704 IMAGE_DIRECTORY_ENTRY_EXPORT
,
706 if (ExportDir
== NULL
)
708 DbgPrint("LdrGetExportByName(): no export directory!\n");
713 * Get header pointers
715 ExNames
= (PDWORD
*)RVA(BaseAddress
,
716 ExportDir
->AddressOfNames
);
717 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
718 ExportDir
->AddressOfNameOrdinals
);
719 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
720 ExportDir
->AddressOfFunctions
);
723 * Check the hint first
725 if (Hint
< ExportDir
->NumberOfFunctions
)
727 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
728 if (strcmp(ExName
, SymbolName
) == 0)
730 Ordinal
= ExOrdinals
[Hint
];
731 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
732 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
733 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
735 DPRINT("Forward: %s\n", (PCHAR
)Function
);
736 Function
= LdrFixupForward((PCHAR
)Function
);
738 if (Function
!= NULL
)
744 * Try a binary search first
747 maxn
= ExportDir
->NumberOfFunctions
;
753 mid
= (minn
+ maxn
) / 2;
755 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
756 res
= strcmp(ExName
, SymbolName
);
759 Ordinal
= ExOrdinals
[mid
];
760 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
761 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
762 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
764 DPRINT("Forward: %s\n", (PCHAR
)Function
);
765 Function
= LdrFixupForward((PCHAR
)Function
);
767 if (Function
!= NULL
)
770 else if (minn
== maxn
)
772 DPRINT("LdrGetExportByName(): binary search failed\n");
786 * Fall back on a linear search
788 DPRINT("LdrGetExportByName(): Falling back on a linear search of export table\n");
789 for (i
= 0; i
< ExportDir
->NumberOfFunctions
; i
++)
791 ExName
= RVA(BaseAddress
, ExNames
[i
]);
792 if (strcmp(ExName
,SymbolName
) == 0)
794 Ordinal
= ExOrdinals
[i
];
795 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
796 DPRINT("%x %x %x\n", Function
, ExportDir
, ExportDir
+ ExportDirSize
);
797 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
798 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
800 DPRINT("Forward: %s\n", (PCHAR
)Function
);
801 Function
= LdrFixupForward((PCHAR
)Function
);
806 DbgPrint("LdrGetExportByName(): failed to find %s\n",SymbolName
);
811 /**********************************************************************
813 * LdrPerformRelocations
816 * Relocate a DLL's memory image.
827 static NTSTATUS
LdrPerformRelocations (PIMAGE_NT_HEADERS NTHeaders
,
830 USHORT NumberOfEntries
;
836 PRELOCATION_DIRECTORY RelocationDir
;
837 PRELOCATION_ENTRY RelocationBlock
;
839 PIMAGE_DATA_DIRECTORY RelocationDDir
;
842 PIMAGE_SECTION_HEADER Sections
;
847 (PIMAGE_SECTION_HEADER
)((PVOID
)NTHeaders
+ sizeof(IMAGE_NT_HEADERS
));
849 for (i
= 0; i
< NTHeaders
->FileHeader
.NumberOfSections
; i
++)
851 if (!(Sections
[i
].Characteristics
& IMAGE_SECTION_NOLOAD
))
855 (ULONG
)(Sections
[i
].VirtualAddress
+ Sections
[i
].Misc
.VirtualSize
);
856 MaxExtend
= max(MaxExtend
, Extend
);
861 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
862 RelocationRVA
= RelocationDDir
->VirtualAddress
;
867 (PRELOCATION_DIRECTORY
)((PCHAR
)ImageBase
+ RelocationRVA
);
869 while (RelocationDir
->SizeOfBlock
)
871 if (RelocationDir
->VirtualAddress
> MaxExtend
)
873 RelocationRVA
+= RelocationDir
->SizeOfBlock
;
875 (PRELOCATION_DIRECTORY
) (ImageBase
+ RelocationRVA
);
879 Delta32
= (ULONG
)(ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
);
881 (PRELOCATION_ENTRY
) (RelocationRVA
+ ImageBase
+
882 sizeof (RELOCATION_DIRECTORY
));
884 RelocationDir
->SizeOfBlock
- sizeof (RELOCATION_DIRECTORY
);
885 NumberOfEntries
= NumberOfEntries
/ sizeof (RELOCATION_ENTRY
);
887 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
889 RelocationDir
->VirtualAddress
,
893 if (!NT_SUCCESS(Status
))
895 DPRINT1("Failed to unprotect relocation target.\n");
899 for (i
= 0; i
< NumberOfEntries
; i
++)
901 Offset
= (RelocationBlock
[i
].TypeOffset
& 0xfff);
902 Offset
+= (ULONG
)(RelocationDir
->VirtualAddress
+ ImageBase
);
905 * What kind of relocations should we perform
906 * for the current entry?
908 switch (RelocationBlock
[i
].TypeOffset
>> 12)
910 case TYPE_RELOC_ABSOLUTE
:
913 case TYPE_RELOC_HIGH
:
914 pValue16
= (PUSHORT
)Offset
;
915 *pValue16
+= Delta32
>> 16;
919 pValue16
= (PUSHORT
)Offset
;
920 *pValue16
+= Delta32
& 0xffff;
923 case TYPE_RELOC_HIGHLOW
:
924 pValue32
= (PULONG
)Offset
;
925 *pValue32
+= Delta32
;
928 case TYPE_RELOC_HIGHADJ
:
929 /* FIXME: do the highadjust fixup */
930 DPRINT("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n");
931 return(STATUS_UNSUCCESSFUL
);
934 DPRINT("unexpected fixup type\n");
935 return STATUS_UNSUCCESSFUL
;
939 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
941 RelocationDir
->VirtualAddress
,
945 if (!NT_SUCCESS(Status
))
947 DPRINT1("Failed to protect relocation target.\n");
951 RelocationRVA
+= RelocationDir
->SizeOfBlock
;
953 (PRELOCATION_DIRECTORY
) (ImageBase
+ RelocationRVA
);
956 return STATUS_SUCCESS
;
960 /**********************************************************************
965 * Compute the entry point for every symbol the DLL imports
966 * from other modules.
977 static NTSTATUS
LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders
,
980 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
986 DPRINT("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders
,
990 * Process each import module.
992 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)(
993 ImageBase
+ NTHeaders
->OptionalHeader
994 .DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
996 DPRINT("ImportModuleDirectory %x\n", ImportModuleDirectory
);
998 while (ImportModuleDirectory
->dwRVAModuleName
)
1000 PVOID
* ImportAddressList
;
1001 PULONG FunctionNameList
;
1002 UNICODE_STRING DllName
;
1008 DPRINT("ImportModule->Directory->dwRVAModuleName %s\n",
1009 (PCHAR
)(ImageBase
+ ImportModuleDirectory
->dwRVAModuleName
));
1011 RtlCreateUnicodeStringFromAsciiz (&DllName
,
1012 (PCHAR
)(ImageBase
+ ImportModuleDirectory
->dwRVAModuleName
));
1014 Status
= LdrGetDllHandle (0, 0, &DllName
, &BaseAddress
);
1015 if (!NT_SUCCESS(Status
))
1017 Status
= LdrLoadDll(NULL
,
1021 RtlFreeUnicodeString (&DllName
);
1022 if (!NT_SUCCESS(Status
))
1024 DbgPrint("LdrFixupImports:failed to load %s\n"
1026 + ImportModuleDirectory
->dwRVAModuleName
));
1033 * Get the import address list.
1035 ImportAddressList
= (PVOID
*)(NTHeaders
->OptionalHeader
.ImageBase
1036 + ImportModuleDirectory
->dwRVAFunctionAddressList
);
1039 * Get the list of functions to import.
1041 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1043 FunctionNameList
= (PULONG
) (
1045 + ImportModuleDirectory
->dwRVAFunctionNameList
1052 + ImportModuleDirectory
->dwRVAFunctionAddressList
);
1056 * Get the size of IAT.
1059 while (FunctionNameList
[IATSize
] != 0L)
1065 * Unprotect the region we are about to write into.
1067 IATBase
= (PVOID
)ImportAddressList
;
1068 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1070 IATSize
* sizeof(PVOID
*),
1073 if (!NT_SUCCESS(Status
))
1075 DbgPrint("LDR: Failed to unprotect IAT.\n");
1080 * Walk through function list and fixup addresses.
1082 while (*FunctionNameList
!= 0L)
1084 if ((*FunctionNameList
) & 0x80000000)
1086 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1087 *ImportAddressList
=
1088 LdrGetExportByOrdinal(BaseAddress
,
1093 pName
= (DWORD
) (ImageBase
+ *FunctionNameList
+ 2);
1094 pHint
= *(PWORD
)(ImageBase
+ *FunctionNameList
);
1096 *ImportAddressList
=
1097 LdrGetExportByName(BaseAddress
, (PUCHAR
)pName
, pHint
);
1098 if ((*ImportAddressList
) == NULL
)
1100 DbgPrint("Failed to import %s\n", pName
);
1101 return STATUS_UNSUCCESSFUL
;
1104 ImportAddressList
++;
1109 * Protect the region we are about to write into.
1111 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1113 IATSize
* sizeof(PVOID
*),
1116 if (!NT_SUCCESS(Status
))
1118 DbgPrint("LDR: Failed to protect IAT.\n");
1122 ImportModuleDirectory
++;
1124 return STATUS_SUCCESS
;
1128 /**********************************************************************
1133 * 1. Map the DLL's sections into memory.
1134 * 2. Relocate, if needed the DLL.
1135 * 3. Fixup any imported symbol.
1136 * 4. Compute the DLL's entry point.
1140 * Address at which the DLL's image
1144 * Handle of the section that contains
1148 * NULL on error; otherwise the entry point
1149 * to call for initializing the DLL.
1156 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
1157 HANDLE SectionHandle
,
1158 PLDR_MODULE
* Module
,
1162 PEPFUNC EntryPoint
= NULL
;
1163 PIMAGE_DOS_HEADER DosHeader
;
1164 PIMAGE_NT_HEADERS NTHeaders
;
1166 DPRINT("LdrPEStartup(ImageBase %x SectionHandle %x)\n",
1167 ImageBase
, (ULONG
)SectionHandle
);
1170 * Overlay DOS and WNT headers structures
1171 * to the DLL's image.
1173 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
1174 NTHeaders
= (PIMAGE_NT_HEADERS
) (ImageBase
+ DosHeader
->e_lfanew
);
1177 * If the base address is different from the
1178 * one the DLL is actually loaded, perform any
1181 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1183 DbgPrint("LDR: Performing relocations\n");
1184 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
1185 if (!NT_SUCCESS(Status
))
1187 DbgPrint("LdrPerformRelocations() failed\n");
1194 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
1198 * If the DLL's imports symbols from other
1199 * modules, fixup the imported calls entry points.
1201 if (NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1202 .VirtualAddress
!= 0)
1204 DPRINT("About to fixup imports\n");
1205 Status
= LdrFixupImports(NTHeaders
, ImageBase
);
1206 if (!NT_SUCCESS(Status
))
1208 DbgPrint("LdrFixupImports() failed\n");
1211 DPRINT("Fixup done\n");
1215 * Compute the DLL's entry point's address.
1217 DPRINT("ImageBase = %x\n",(ULONG
)ImageBase
);
1218 DPRINT("AddressOfEntryPoint = %x\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1219 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
1221 EntryPoint
= (PEPFUNC
) (ImageBase
1222 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1224 DPRINT("LdrPEStartup() = %x\n",EntryPoint
);
1230 LdrUnloadDll (IN PVOID BaseAddress
)
1232 PIMAGE_NT_HEADERS NtHeaders
;
1233 PDLLMAIN_FUNC Entrypoint
;
1234 PLIST_ENTRY ModuleListHead
;
1239 if (BaseAddress
== NULL
)
1240 return STATUS_SUCCESS
;
1242 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1243 Entry
= ModuleListHead
->Flink
;
1245 while (Entry
!= ModuleListHead
)
1247 Module
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InLoadOrderModuleList
);
1248 if (Module
->BaseAddress
== BaseAddress
)
1250 if (Module
->LoadCount
== -1)
1252 /* never unload this dll */
1253 return STATUS_SUCCESS
;
1255 else if (Module
->LoadCount
> 1)
1257 Module
->LoadCount
--;
1258 return STATUS_SUCCESS
;
1261 NtHeaders
= RtlImageNtHeader (Module
->BaseAddress
);
1262 if ((NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
) == IMAGE_FILE_DLL
)
1264 if (Module
->EntryPoint
!= 0)
1266 Entrypoint
= (PDLLMAIN_FUNC
)Module
->EntryPoint
;
1267 DPRINT("Calling entry point at 0x%08x\n", Entrypoint
);
1268 Entrypoint(Module
->BaseAddress
,
1274 DPRINT("NTDLL.LDR: Entrypoint is NULL for \n");
1277 Status
= ZwUnmapViewOfSection (NtCurrentProcess (),
1278 Module
->BaseAddress
);
1279 ZwClose (Module
->SectionHandle
);
1281 /* remove the module entry from the list */
1282 RtlFreeUnicodeString (&Module
->FullDllName
);
1283 RtlFreeUnicodeString (&Module
->BaseDllName
);
1284 RemoveEntryList (Entry
);
1285 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
1290 Entry
= Entry
->Flink
;
1293 DPRINT("NTDLL.LDR: Dll not found\n")
1295 return STATUS_UNSUCCESSFUL
;
1298 #if 0 /*MOVED_TO_FILE_RES_C*/
1301 LdrFindResource_U(PVOID BaseAddress
,
1302 PLDR_RESOURCE_INFO ResourceInfo
,
1304 PIMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
)
1306 PIMAGE_RESOURCE_DIRECTORY ResDir
;
1307 PIMAGE_RESOURCE_DIRECTORY ResBase
;
1308 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry
;
1309 NTSTATUS Status
= STATUS_SUCCESS
;
1315 DPRINT ("LdrFindResource_U()\n");
1317 /* Get the pointer to the resource directory */
1318 ResDir
= (PIMAGE_RESOURCE_DIRECTORY
)
1319 RtlImageDirectoryEntryToData (BaseAddress
,
1321 IMAGE_DIRECTORY_ENTRY_RESOURCE
,
1325 return STATUS_RESOURCE_DATA_NOT_FOUND
;
1328 DPRINT("ResourceDirectory: %x\n", (ULONG
)ResDir
);
1332 /* Let's go into resource tree */
1333 for (i
= 0; i
< Level
; i
++)
1335 DPRINT("ResDir: %x\n", (ULONG
)ResDir
);
1336 Id
= ((PULONG
)ResourceInfo
)[i
];
1337 EntryCount
= ResDir
->NumberOfNamedEntries
;
1338 ResEntry
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(ResDir
+ 1);
1339 DPRINT("ResEntry %x\n", (ULONG
)ResEntry
);
1340 if (Id
& 0xFFFF0000)
1342 /* Resource name is a unicode string */
1343 for (; EntryCount
--; ResEntry
++)
1345 /* Scan entries for equal name */
1346 if (ResEntry
->Name
& 0x80000000)
1348 ws
= (PWCHAR
)((ULONG
)ResDir
+ (ResEntry
->Name
& 0x7FFFFFFF));
1349 if (!wcsncmp((PWCHAR
)Id
, ws
+ 1, *ws
) &&
1350 wcslen((PWCHAR
)Id
) == (int)*ws
)
1359 /* We use ID number instead of string */
1360 ResEntry
+= EntryCount
;
1361 EntryCount
= ResDir
->NumberOfIdEntries
;
1362 for (; EntryCount
--; ResEntry
++)
1364 /* Scan entries for equal name */
1365 if (ResEntry
->Name
== Id
)
1367 DPRINT("ID entry found %x\n", Id
);
1372 DPRINT("Error %lu\n", i
);
1377 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
1380 return STATUS_RESOURCE_NAME_NOT_FOUND
;
1383 if (ResDir
->NumberOfNamedEntries
|| ResDir
->NumberOfIdEntries
)
1385 /* Use the first available language */
1386 ResEntry
= (IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(ResDir
+ 1);
1389 return STATUS_RESOURCE_LANG_NOT_FOUND
;
1392 return STATUS_RESOURCE_DATA_NOT_FOUND
;
1395 return STATUS_INVALID_PARAMETER
;
1398 ResDir
= (PIMAGE_RESOURCE_DIRECTORY
)((ULONG
)ResBase
+
1399 (ResEntry
->OffsetToData
& 0x7FFFFFFF));
1401 DPRINT("ResourceDataEntry: %x\n", (ULONG
)ResDir
);
1403 if (ResourceDataEntry
)
1405 *ResourceDataEntry
= (PVOID
)ResDir
;
1413 LdrAccessResource(IN PVOID BaseAddress
,
1414 IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry
,
1415 OUT PVOID
*Resource OPTIONAL
,
1416 OUT PULONG Size OPTIONAL
)
1418 PIMAGE_SECTION_HEADER Section
;
1419 PIMAGE_NT_HEADERS NtHeader
;
1426 Data
= (ULONG
)RtlImageDirectoryEntryToData (BaseAddress
,
1428 IMAGE_DIRECTORY_ENTRY_RESOURCE
,
1431 return STATUS_RESOURCE_DATA_NOT_FOUND
;
1433 if ((ULONG
)BaseAddress
& 1)
1435 /* loaded as ordinary file */
1436 NtHeader
= RtlImageNtHeader((PVOID
)((ULONG
)BaseAddress
& ~1UL));
1437 Offset
= (ULONG
)BaseAddress
- Data
+ NtHeader
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
1438 Section
= RtlImageRvaToSection (NtHeader
, BaseAddress
, NtHeader
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
);
1439 if (Section
== NULL
)
1441 return STATUS_RESOURCE_DATA_NOT_FOUND
;
1444 if (Section
->Misc
.VirtualSize
< ResourceDataEntry
->OffsetToData
)
1446 SectionRva
= RtlImageRvaToSection (NtHeader
, BaseAddress
, ResourceDataEntry
->OffsetToData
)->VirtualAddress
;
1447 SectionVa
= RtlImageRvaToVa(NtHeader
, BaseAddress
, SectionRva
, NULL
);
1448 Offset
= SectionRva
- SectionVa
+ Data
- Section
->VirtualAddress
;
1454 *Resource
= (PVOID
)(ResourceDataEntry
->OffsetToData
- Offset
+ (ULONG
)BaseAddress
);
1459 *Size
= ResourceDataEntry
->Size
;
1462 return STATUS_SUCCESS
;
1465 #endif /*MOVED_TO_FILE_RES_C*/
1468 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
1470 PLIST_ENTRY ModuleListHead
;
1475 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %x)\n", BaseAddress
);
1477 Status
= STATUS_DLL_NOT_FOUND
;
1478 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1479 Entry
= ModuleListHead
->Flink
;
1480 while (Entry
!= ModuleListHead
) {
1481 Module
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InLoadOrderModuleList
);
1483 DPRINT("BaseDllName %wZ BaseAddress %x\n", &Module
->BaseDllName
, Module
->BaseAddress
);
1485 if (Module
->BaseAddress
== BaseAddress
) {
1486 if (Module
->TlsIndex
== 0) {
1487 Module
->Flags
|= 0x00040000;
1488 Status
= STATUS_SUCCESS
;
1492 Entry
= Entry
->Flink
;
1497 #if 0 /*MOVED_TO_FILE_RES_C*/
1500 LdrFindResourceDirectory_U (IN PVOID BaseAddress
,
1505 PIMAGE_RESOURCE_DIRECTORY ResDir
;
1506 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry
;
1509 NTSTATUS Status
= STATUS_SUCCESS
;
1512 /* Get the pointer to the resource directory */
1513 ResDir
= (PIMAGE_RESOURCE_DIRECTORY
)
1514 RtlImageDirectoryEntryToData (BaseAddress
,
1516 IMAGE_DIRECTORY_ENTRY_RESOURCE
,
1520 return STATUS_RESOURCE_DATA_NOT_FOUND
;
1523 /* Let's go into resource tree */
1524 for (i
= 0; i
< level
; i
++, name
++)
1526 EntryCount
= ResDir
->NumberOfNamedEntries
;
1527 ResEntry
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(ResDir
+ 1);
1528 if ((ULONG
)(*name
) & 0xFFFF0000)
1530 /* Resource name is a unicode string */
1531 for (; EntryCount
--; ResEntry
++)
1533 /* Scan entries for equal name */
1534 if (ResEntry
->Name
& 0x80000000)
1536 ws
= (WCHAR
*)((ULONG
)ResDir
+ (ResEntry
->Name
& 0x7FFFFFFF));
1537 if (!wcsncmp( *name
, ws
+ 1, *ws
) && wcslen( *name
) == (int)*ws
)
1546 /* We use ID number instead of string */
1547 ResEntry
+= EntryCount
;
1548 EntryCount
= ResDir
->NumberOfIdEntries
;
1549 for (; EntryCount
--; ResEntry
++)
1551 /* Scan entries for equal name */
1552 if (ResEntry
->Name
== (ULONG
)(*name
))
1560 return STATUS_RESOURCE_TYPE_NOT_FOUND
;
1563 return STATUS_RESOURCE_NAME_NOT_FOUND
;
1566 Status
= STATUS_RESOURCE_LANG_NOT_FOUND
;
1567 /* Just use first language entry */
1568 if (ResDir
->NumberOfNamedEntries
|| ResDir
->NumberOfIdEntries
)
1570 ResEntry
= (IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(ResDir
+ 1);
1576 return STATUS_RESOURCE_DATA_NOT_FOUND
;
1579 return STATUS_INVALID_PARAMETER
;
1582 ResDir
= (PIMAGE_RESOURCE_DIRECTORY
)((ULONG
)ResDir
+ ResEntry
->OffsetToData
);
1587 *addr
= (PVOID
)ResDir
;
1593 #endif /*MOVED_TO_FILE_RES_C*/
1597 LdrGetDllHandle(IN ULONG Unknown1
,
1599 IN PUNICODE_STRING DllName
,
1600 OUT PVOID
* BaseAddress
)
1602 UNICODE_STRING FullDllName
;
1603 PLIST_ENTRY ModuleListHead
;
1607 DPRINT("LdrGetDllHandle (Unknown1 %x Unknown2 %x DllName %wZ BaseAddress %p)\n",
1608 Unknown1
, Unknown2
, DllName
, BaseAddress
);
1610 /* NULL is the current executable */
1611 if (DllName
== NULL
) {
1612 *BaseAddress
= NtCurrentPeb()->ImageBaseAddress
;
1613 DPRINT("BaseAddress %x\n", *BaseAddress
);
1614 return STATUS_SUCCESS
;
1616 LdrAdjustDllName(&FullDllName
, DllName
, TRUE
);
1618 DPRINT("FullDllName %wZ\n", &FullDllName
);
1620 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1621 Entry
= ModuleListHead
->Flink
;
1622 while (Entry
!= ModuleListHead
) {
1623 Module
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InLoadOrderModuleList
);
1625 DPRINT("EntryPoint %x\n", Module
->EntryPoint
);
1626 DPRINT("Comparing %wZ and %wZ\n", &Module
->BaseDllName
, &FullDllName
);
1628 if (!RtlCompareUnicodeString(&Module
->BaseDllName
, &FullDllName
, TRUE
)) {
1629 RtlFreeUnicodeString(&FullDllName
);
1630 *BaseAddress
= Module
->BaseAddress
;
1631 DPRINT("BaseAddress %x\n", *BaseAddress
);
1632 return STATUS_SUCCESS
;
1634 Entry
= Entry
->Flink
;
1637 DPRINT("Failed to find dll %wZ\n", &FullDllName
);
1639 RtlFreeUnicodeString(&FullDllName
);
1640 *BaseAddress
= NULL
;
1641 return STATUS_DLL_NOT_FOUND
;
1646 LdrGetProcedureAddress (IN PVOID BaseAddress
,
1647 IN PANSI_STRING Name
,
1649 OUT PVOID
*ProcedureAddress
)
1651 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1657 DPRINT("LdrGetProcedureAddress (BaseAddress %x Name %Z Ordinal %lu ProcedureAddress %x)\n",
1658 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
1660 /* Get the pointer to the export directory */
1661 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1662 RtlImageDirectoryEntryToData (BaseAddress
,
1664 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1667 DPRINT("ExportDir %x i %lu\n", ExportDir
, i
);
1669 if (!ExportDir
|| !i
|| !ProcedureAddress
)
1671 return STATUS_INVALID_PARAMETER
;
1674 AddressPtr
= (PULONG
)((ULONG
)BaseAddress
+ (ULONG
)ExportDir
->AddressOfFunctions
);
1675 if (Name
&& Name
->Length
)
1678 OrdinalPtr
= (PUSHORT
)((ULONG
)BaseAddress
+ (ULONG
)ExportDir
->AddressOfNameOrdinals
);
1679 NamePtr
= (PULONG
)((ULONG
)BaseAddress
+ (ULONG
)ExportDir
->AddressOfNames
);
1680 for( i
= 0; i
< ExportDir
->NumberOfNames
; i
++, NamePtr
++, OrdinalPtr
++)
1682 if (!_strnicmp(Name
->Buffer
, (char*)(BaseAddress
+ *NamePtr
), Name
->Length
))
1684 *ProcedureAddress
= (PVOID
)((ULONG
)BaseAddress
+ (ULONG
)AddressPtr
[*OrdinalPtr
]);
1685 return STATUS_SUCCESS
;
1688 DbgPrint("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
1693 Ordinal
&= 0x0000FFFF;
1694 if (Ordinal
- ExportDir
->Base
< ExportDir
->NumberOfFunctions
)
1696 *ProcedureAddress
= (PVOID
)((ULONG
)BaseAddress
+ (ULONG
)AddressPtr
[Ordinal
- ExportDir
->Base
]);
1697 return STATUS_SUCCESS
;
1699 DbgPrint("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal
);
1702 return STATUS_PROCEDURE_NOT_FOUND
;
1707 LdrShutdownProcess (VOID
)
1709 PLIST_ENTRY ModuleListHead
;
1713 DPRINT("LdrShutdownProcess() called\n");
1715 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
1717 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
1718 Entry
= ModuleListHead
->Blink
;
1720 while (Entry
!= ModuleListHead
)
1722 Module
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InInitializationOrderModuleList
);
1724 DPRINT(" Unloading %wZ\n",
1725 &Module
->BaseDllName
);
1726 // PJS: only detach from static dlls, they should FreeLibrary() any dlls that
1727 // they loaded dynamically, and when the last reference is gone, that lib will
1729 if (Module
->EntryPoint
!= 0 && Module
->LoadCount
== -1)
1731 PDLLMAIN_FUNC Entrypoint
= (PDLLMAIN_FUNC
)Module
->EntryPoint
;
1733 DPRINT("Calling entry point at 0x%08x\n", Entrypoint
);
1734 Entrypoint (Module
->BaseAddress
,
1739 Entry
= Entry
->Blink
;
1742 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
1744 DPRINT("LdrShutdownProcess() done\n");
1746 return STATUS_SUCCESS
;
1751 LdrShutdownThread (VOID
)
1753 PLIST_ENTRY ModuleListHead
;
1757 DPRINT("LdrShutdownThread() called\n");
1759 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
1761 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
1762 Entry
= ModuleListHead
->Blink
;
1764 while (Entry
!= ModuleListHead
)
1766 Module
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InInitializationOrderModuleList
);
1768 DPRINT(" Unloading %wZ\n",
1769 &Module
->BaseDllName
);
1771 if (Module
->EntryPoint
!= 0)
1773 PDLLMAIN_FUNC Entrypoint
= (PDLLMAIN_FUNC
)Module
->EntryPoint
;
1775 DPRINT("Calling entry point at 0x%08x\n", Entrypoint
);
1776 Entrypoint (Module
->BaseAddress
,
1781 Entry
= Entry
->Blink
;
1784 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
1786 DPRINT("LdrShutdownThread() done\n");
1788 return STATUS_SUCCESS
;
1792 /***************************************************************************
1794 * LdrQueryProcessModuleInformation
1807 LdrQueryProcessModuleInformation(IN PMODULE_INFORMATION ModuleInformation OPTIONAL
,
1808 IN ULONG Size OPTIONAL
,
1809 OUT PULONG ReturnedSize
)
1812 PLIST_ENTRY ModuleListHead
;
1815 PMODULE_ENTRY ModulePtr
= NULL
;
1816 NTSTATUS Status
= STATUS_SUCCESS
;
1817 ULONG UsedSize
= sizeof(ULONG
);
1818 ANSI_STRING AnsiString
;
1821 DPRINT("LdrQueryProcessModuleInformation() called\n");
1823 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
1825 if (ModuleInformation
== NULL
|| Size
== 0)
1827 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1831 ModuleInformation
->ModuleCount
= 0;
1832 ModulePtr
= &ModuleInformation
->ModuleEntry
[0];
1833 Status
= STATUS_SUCCESS
;
1836 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1837 Entry
= ModuleListHead
->Flink
;
1839 while (Entry
!= ModuleListHead
)
1841 Module
= CONTAINING_RECORD(Entry
, LDR_MODULE
, InLoadOrderModuleList
);
1843 DPRINT(" Module %wZ\n",
1844 &Module
->FullDllName
);
1846 if (UsedSize
> Size
)
1848 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1850 else if (ModuleInformation
!= NULL
)
1852 ModulePtr
->Unknown0
= 0; // FIXME: ??
1853 ModulePtr
->Unknown1
= 0; // FIXME: ??
1854 ModulePtr
->BaseAddress
= Module
->BaseAddress
;
1855 ModulePtr
->SizeOfImage
= Module
->SizeOfImage
;
1856 ModulePtr
->Flags
= Module
->Flags
;
1857 ModulePtr
->Unknown2
= 0; // FIXME: load order index ??
1858 ModulePtr
->Unknown3
= 0; // FIXME: ??
1859 ModulePtr
->LoadCount
= Module
->LoadCount
;
1861 AnsiString
.Length
= 0;
1862 AnsiString
.MaximumLength
= 256;
1863 AnsiString
.Buffer
= ModulePtr
->ModuleName
;
1864 RtlUnicodeStringToAnsiString(&AnsiString
,
1865 &Module
->FullDllName
,
1867 p
= strrchr(ModulePtr
->ModuleName
, '\\');
1869 ModulePtr
->PathLength
= p
- ModulePtr
->ModuleName
+ 1;
1871 ModulePtr
->PathLength
= 0;
1874 ModuleInformation
->ModuleCount
++;
1876 UsedSize
+= sizeof(MODULE_ENTRY
);
1878 Entry
= Entry
->Flink
;
1881 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
1883 if (ReturnedSize
!= 0)
1884 *ReturnedSize
= UsedSize
;
1886 DPRINT("LdrQueryProcessModuleInformation() done\n");