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;
234 DPRINT("LdrLoadDll(Name \"%wZ\" BaseAddress %x)\n",
237 /* adjust the full dll name */
238 LdrAdjustDllName (&AdjustedName,
241 DPRINT("AdjustedName: %wZ\n", &AdjustedName);
244 * Test if dll is already loaded.
246 if (LdrFindEntryForName(&AdjustedName, &Module) == STATUS_SUCCESS)
248 DPRINT("DLL %wZ already loaded.\n", &AdjustedName);
249 if (Module->LoadCount != -1)
251 *BaseAddress = Module->BaseAddress;
252 return STATUS_SUCCESS;
254 DPRINT("Loading \"%wZ\"\n", Name);
256 if (SearchPath == NULL)
258 SearchPath = SearchPathBuffer;
259 wcscpy (SearchPathBuffer, SharedUserData->NtSystemRoot);
260 wcscat (SearchPathBuffer, L"\\system32;");
261 wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
262 wcscat (SearchPathBuffer, L";.");
265 DPRINT("SearchPath %S\n", SearchPath);
267 if (RtlDosSearchPath_U (SearchPath,
273 return STATUS_DLL_NOT_FOUND;
275 DPRINT("FullDosName %S\n", FullDosName);
277 RtlFreeUnicodeString (&AdjustedName);
279 if (!RtlDosPathNameToNtPathName_U (FullDosName,
283 return STATUS_DLL_NOT_FOUND;
285 DPRINT("FullNtFileName %wZ\n", &FullNtFileName);
287 InitializeObjectAttributes(&FileObjectAttributes,
293 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName);
295 Status = ZwOpenFile(&FileHandle,
297 &FileObjectAttributes,
301 if (!NT_SUCCESS(Status))
303 DbgPrint("Dll open of %wZ failed: Status = 0x%08x\n",
304 &FullNtFileName, Status);
305 RtlFreeUnicodeString (&FullNtFileName);
308 RtlFreeUnicodeString (&FullNtFileName);
310 Status = ZwReadFile(FileHandle,
319 if (!NT_SUCCESS(Status))
321 DPRINT("Dll header read failed: Status = 0x%08x\n", Status);
326 * Overlay DOS and NT headers structures to the
327 * buffer with DLL's header raw data.
329 DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
330 NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew);
332 * Check it is a PE image file.
334 if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
335 || (DosHeader->e_lfanew == 0L)
336 || (*(PULONG)(NTHeaders) != IMAGE_PE_MAGIC))
338 DPRINT("NTDLL format invalid\n");
341 return STATUS_UNSUCCESSFUL;
344 ImageBase = (PVOID) NTHeaders->OptionalHeader.ImageBase;
345 ImageSize = NTHeaders->OptionalHeader.SizeOfImage;
347 DPRINT("ImageBase 0x%08x\n", ImageBase);
350 * Create a section for dll.
352 Status = ZwCreateSection(&SectionHandle,
357 SEC_COMMIT | SEC_IMAGE,
359 if (!NT_SUCCESS(Status))
361 DPRINT("NTDLL create section failed: Status = 0x%08x\n", Status);
367 * Map the dll into the process.
371 Status = ZwMapViewOfSection(SectionHandle,
381 if (!NT_SUCCESS(Status))
383 DbgPrint("NTDLL.LDR: map view of section failed (Status %x)\n", Status);
389 /* relocate dll and fixup import table */
390 if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) ==
394 (PDLLMAIN_FUNC) LdrPEStartup(ImageBase, SectionHandle, &Module,
396 if (Entrypoint == NULL)
398 return(STATUS_UNSUCCESSFUL);
404 LdrpLoadUserModuleSymbols(Module);
409 if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) ==
412 if (Module->EntryPoint != 0)
414 Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
416 DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
417 if (FALSE == Entrypoint(Module->BaseAddress,
421 /* Do this as a DPRINT1 for now, until clean up and fail implemented */
422 DPRINT1("NTDLL.LDR: DLL \"%wZ\" failed to initialize\n",
423 &Module->BaseDllName);
424 /* FIXME: should clean up and fail */
428 DPRINT("NTDLL.LDR: DLL \"%wZ\" initialized successfully\n",
429 &Module->BaseDllName);
434 DPRINT("NTDLL.LDR: Entrypoint is NULL for \"%wZ\"\n",
435 &Module->BaseDllName);
439 *BaseAddress = Module->BaseAddress;
440 return STATUS_SUCCESS;
444 /***************************************************************************
446 * LdrFindEntryForAddress
460 LdrFindEntryForAddress(PVOID Address,
463 PLIST_ENTRY ModuleListHead;
465 PLDR_MODULE ModulePtr;
467 DPRINT("NTDLL.LdrFindEntryForAddress(Address %p)\n", Address);
469 if (NtCurrentPeb()->Ldr == NULL)
470 return(STATUS_NO_MORE_ENTRIES);
472 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
473 Entry = ModuleListHead->Flink;
474 if (Entry == ModuleListHead)
475 return(STATUS_NO_MORE_ENTRIES);
477 while (Entry != ModuleListHead)
479 ModulePtr = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
481 DPRINT("Scanning %wZ at %p\n", &ModulePtr->BaseDllName, ModulePtr->BaseAddress);
483 if ((Address >= ModulePtr->BaseAddress) &&
484 (Address <= (ModulePtr->BaseAddress + ModulePtr->SizeOfImage)))
487 return(STATUS_SUCCESS);
490 Entry = Entry->Flink;
493 DPRINT("Failed to find module entry.\n");
495 return(STATUS_NO_MORE_ENTRIES);
499 /***************************************************************************
501 * LdrFindEntryForName
515 LdrFindEntryForName(PUNICODE_STRING Name,
518 PLIST_ENTRY ModuleListHead;
520 PLDR_MODULE ModulePtr;
521 BOOLEAN ContainsPath;
524 DPRINT("NTDLL.LdrFindEntryForName(Name %wZ)\n", Name);
526 if (NtCurrentPeb()->Ldr == NULL)
527 return(STATUS_NO_MORE_ENTRIES);
529 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
530 Entry = ModuleListHead->Flink;
531 if (Entry == ModuleListHead)
532 return(STATUS_NO_MORE_ENTRIES);
534 // NULL is the current process
537 *Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
538 return(STATUS_SUCCESS);
541 ContainsPath = (2 <= Name->Length && L':' == Name->Buffer[1]);
542 for (i = 0; ! ContainsPath && i < Name->Length; i++)
544 ContainsPath = L'\\' == Name->Buffer[i] ||
545 L'/' == Name->Buffer[i];
547 while (Entry != ModuleListHead)
549 ModulePtr = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
551 DPRINT("Scanning %wZ %wZ\n", &ModulePtr->BaseDllName, Name);
553 if ((! ContainsPath &&
554 0 == RtlCompareUnicodeString(&ModulePtr->BaseDllName, Name, TRUE)) ||
556 0 == RtlCompareUnicodeString(&ModulePtr->FullDllName, Name, TRUE)))
559 return(STATUS_SUCCESS);
562 Entry = Entry->Flink;
565 DPRINT("Failed to find dll %wZ\n", Name);
567 return(STATUS_NO_MORE_ENTRIES);
570 /**********************************************************************
586 LdrFixupForward(PCHAR ForwardName)
588 CHAR NameBuffer[128];
589 UNICODE_STRING DllName;
590 UNICODE_STRING FunctionName;
595 strcpy(NameBuffer, ForwardName);
596 p = strchr(NameBuffer, '.');
601 DPRINT("Dll: %s Function: %s\n", NameBuffer, p+1);
602 RtlCreateUnicodeStringFromAsciiz (&DllName,
605 Status = LdrGetDllHandle (0, 0, &DllName, &BaseAddress);
606 if (!NT_SUCCESS(Status))
608 Status = LdrLoadDll(NULL,
612 if (!NT_SUCCESS(Status))
614 DbgPrint("LdrFixupForward: failed to load %wZ\n", &DllName);
615 RtlFreeUnicodeString (&DllName);
620 RtlFreeUnicodeString (&DllName);
621 DPRINT("BaseAddress: %p\n", BaseAddress);
623 return LdrGetExportByName(BaseAddress, p+1, -1);
630 /**********************************************************************
632 * LdrGetExportByOrdinal
646 LdrGetExportByOrdinal (
651 PIMAGE_EXPORT_DIRECTORY ExportDir;
652 PDWORD * ExFunctions;
655 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
656 RtlImageDirectoryEntryToData (BaseAddress,
658 IMAGE_DIRECTORY_ENTRY_EXPORT,
662 ExOrdinals = (USHORT *)
665 ExportDir->AddressOfNameOrdinals
667 ExFunctions = (PDWORD *)
670 ExportDir->AddressOfFunctions
673 "LdrGetExportByOrdinal(Ordinal %d) = %x\n",
675 RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
677 return(RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] ));
681 /**********************************************************************
694 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
695 * both with NumberOfNames entries.
699 LdrGetExportByName(PVOID BaseAddress,
703 PIMAGE_EXPORT_DIRECTORY ExportDir;
704 PDWORD * ExFunctions;
714 DPRINT("LdrGetExportByName %x %s %hu\n", BaseAddress, SymbolName, Hint);
716 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
717 RtlImageDirectoryEntryToData(BaseAddress,
719 IMAGE_DIRECTORY_ENTRY_EXPORT,
721 if (ExportDir == NULL)
723 DbgPrint("LdrGetExportByName(): no export directory!\n");
728 //The symbol names may be missing entirely
729 if (ExportDir->AddressOfNames == 0)
731 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
736 * Get header pointers
738 ExNames = (PDWORD *)RVA(BaseAddress,
739 ExportDir->AddressOfNames);
740 ExOrdinals = (USHORT *)RVA(BaseAddress,
741 ExportDir->AddressOfNameOrdinals);
742 ExFunctions = (PDWORD *)RVA(BaseAddress,
743 ExportDir->AddressOfFunctions);
746 * Check the hint first
748 if (Hint < ExportDir->NumberOfNames)
750 ExName = RVA(BaseAddress, ExNames[Hint]);
751 if (strcmp(ExName, SymbolName) == 0)
753 Ordinal = ExOrdinals[Hint];
754 Function = RVA(BaseAddress, ExFunctions[Ordinal]);
755 if (((ULONG)Function >= (ULONG)ExportDir) &&
756 ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
758 DPRINT("Forward: %s\n", (PCHAR)Function);
759 Function = LdrFixupForward((PCHAR)Function);
761 if (Function != NULL)
767 * Try a binary search first
770 maxn = ExportDir->NumberOfNames;
776 mid = (minn + maxn) / 2;
778 ExName = RVA(BaseAddress, ExNames[mid]);
779 res = strcmp(ExName, SymbolName);
782 Ordinal = ExOrdinals[mid];
783 Function = RVA(BaseAddress, ExFunctions[Ordinal]);
784 if (((ULONG)Function >= (ULONG)ExportDir) &&
785 ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
787 DPRINT("Forward: %s\n", (PCHAR)Function);
788 Function = LdrFixupForward((PCHAR)Function);
790 if (Function != NULL)
793 else if (minn == maxn)
795 DPRINT("LdrGetExportByName(): binary search failed\n");
809 * Fall back on a linear search
811 DPRINT("LdrGetExportByName(): Falling back on a linear search of export table\n");
812 for (i = 0; i < ExportDir->NumberOfNames; i++)
814 ExName = RVA(BaseAddress, ExNames[i]);
815 if (strcmp(ExName,SymbolName) == 0)
817 Ordinal = ExOrdinals[i];
818 Function = RVA(BaseAddress, ExFunctions[Ordinal]);
819 DPRINT("%x %x %x\n", Function, ExportDir, ExportDir + ExportDirSize);
820 if (((ULONG)Function >= (ULONG)ExportDir) &&
821 ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
823 DPRINT("Forward: %s\n", (PCHAR)Function);
824 Function = LdrFixupForward((PCHAR)Function);
829 DbgPrint("LdrGetExportByName(): failed to find %s\n",SymbolName);
834 /**********************************************************************
836 * LdrPerformRelocations
839 * Relocate a DLL's memory image.
850 static NTSTATUS LdrPerformRelocations (PIMAGE_NT_HEADERS NTHeaders,
853 USHORT NumberOfEntries;
859 PRELOCATION_DIRECTORY RelocationDir;
860 PRELOCATION_ENTRY RelocationBlock;
862 PIMAGE_DATA_DIRECTORY RelocationDDir;
866 PIMAGE_SECTION_HEADER Sections;
871 (PIMAGE_SECTION_HEADER)((PVOID)NTHeaders + sizeof(IMAGE_NT_HEADERS));
873 for (i = 0; i < NTHeaders->FileHeader.NumberOfSections; i++)
875 if (!(Sections[i].Characteristics & IMAGE_SECTION_NOLOAD))
879 (ULONG)(Sections[i].VirtualAddress + Sections[i].Misc.VirtualSize);
880 MaxExtend = max(MaxExtend, Extend);
885 &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
886 RelocationRVA = RelocationDDir->VirtualAddress;
891 (PRELOCATION_DIRECTORY)((PCHAR)ImageBase + RelocationRVA);
893 while (RelocationDir->SizeOfBlock)
895 if (RelocationDir->VirtualAddress > MaxExtend)
897 RelocationRVA += RelocationDir->SizeOfBlock;
899 (PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA);
903 Delta32 = (ULONG)(ImageBase - NTHeaders->OptionalHeader.ImageBase);
905 (PRELOCATION_ENTRY) (RelocationRVA + ImageBase +
906 sizeof (RELOCATION_DIRECTORY));
908 RelocationDir->SizeOfBlock - sizeof (RELOCATION_DIRECTORY);
909 NumberOfEntries = NumberOfEntries / sizeof (RELOCATION_ENTRY);
911 Status = NtProtectVirtualMemory(NtCurrentProcess(),
913 RelocationDir->VirtualAddress,
917 if (!NT_SUCCESS(Status))
919 DPRINT1("Failed to unprotect relocation target.\n");
923 if (RelocationDir->VirtualAddress + PAGE_SIZE < MaxExtend)
925 Status = NtProtectVirtualMemory(NtCurrentProcess(),
927 RelocationDir->VirtualAddress + PAGE_SIZE,
931 if (!NT_SUCCESS(Status))
933 DPRINT1("Failed to unprotect relocation target (2).\n");
934 NtProtectVirtualMemory(NtCurrentProcess(),
936 RelocationDir->VirtualAddress,
944 for (i = 0; i < NumberOfEntries; i++)
946 Offset = (RelocationBlock[i].TypeOffset & 0xfff);
947 Offset += (ULONG)(RelocationDir->VirtualAddress + ImageBase);
950 * What kind of relocations should we perform
951 * for the current entry?
953 switch (RelocationBlock[i].TypeOffset >> 12)
955 case TYPE_RELOC_ABSOLUTE:
958 case TYPE_RELOC_HIGH:
959 pValue16 = (PUSHORT)Offset;
960 *pValue16 += Delta32 >> 16;
964 pValue16 = (PUSHORT)Offset;
965 *pValue16 += Delta32 & 0xffff;
968 case TYPE_RELOC_HIGHLOW:
969 pValue32 = (PULONG)Offset;
970 *pValue32 += Delta32;
973 case TYPE_RELOC_HIGHADJ:
974 /* FIXME: do the highadjust fixup */
975 DPRINT("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n");
976 return(STATUS_UNSUCCESSFUL);
979 DPRINT("unexpected fixup type\n");
980 return STATUS_UNSUCCESSFUL;
984 Status = NtProtectVirtualMemory(NtCurrentProcess(),
986 RelocationDir->VirtualAddress,
990 if (!NT_SUCCESS(Status))
992 DPRINT1("Failed to protect relocation target.\n");
996 if (RelocationDir->VirtualAddress + PAGE_SIZE < MaxExtend)
998 Status = NtProtectVirtualMemory(NtCurrentProcess(),
1000 RelocationDir->VirtualAddress + PAGE_SIZE,
1004 if (!NT_SUCCESS(Status))
1006 DPRINT1("Failed to protect relocation target2.\n");
1011 RelocationRVA += RelocationDir->SizeOfBlock;
1013 (PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA);
1016 return STATUS_SUCCESS;
1020 /**********************************************************************
1025 * Compute the entry point for every symbol the DLL imports
1026 * from other modules.
1037 static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
1040 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1046 DPRINT("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders,
1050 * Process each import module.
1052 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)(
1053 ImageBase + NTHeaders->OptionalHeader
1054 .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1056 DPRINT("ImportModuleDirectory %x\n", ImportModuleDirectory);
1058 while (ImportModuleDirectory->dwRVAModuleName)
1060 PVOID * ImportAddressList;
1061 PULONG FunctionNameList;
1062 UNICODE_STRING DllName;
1068 DPRINT("ImportModule->Directory->dwRVAModuleName %s\n",
1069 (PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName));
1071 RtlCreateUnicodeStringFromAsciiz (&DllName,
1072 (PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName));
1074 Status = LdrGetDllHandle (0, 0, &DllName, &BaseAddress);
1075 if (!NT_SUCCESS(Status))
1077 Status = LdrLoadDll(NULL,
1081 RtlFreeUnicodeString (&DllName);
1082 if (!NT_SUCCESS(Status))
1084 DbgPrint("LdrFixupImports:failed to load %s\n"
1086 + ImportModuleDirectory->dwRVAModuleName));
1093 * Get the import address list.
1095 ImportAddressList = (PVOID *)(ImageBase
1096 + ImportModuleDirectory->dwRVAFunctionAddressList);
1099 * Get the list of functions to import.
1101 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1103 FunctionNameList = (PULONG) (
1105 + ImportModuleDirectory->dwRVAFunctionNameList
1112 + ImportModuleDirectory->dwRVAFunctionAddressList);
1116 * Get the size of IAT.
1119 while (FunctionNameList[IATSize] != 0L)
1125 * Unprotect the region we are about to write into.
1127 IATBase = (PVOID)ImportAddressList;
1128 Status = NtProtectVirtualMemory(NtCurrentProcess(),
1130 IATSize * sizeof(PVOID*),
1133 if (!NT_SUCCESS(Status))
1135 DbgPrint("LDR: Failed to unprotect IAT.\n");
1140 * Walk through function list and fixup addresses.
1142 while (*FunctionNameList != 0L)
1144 if ((*FunctionNameList) & 0x80000000)
1146 Ordinal = (*FunctionNameList) & 0x7fffffff;
1147 *ImportAddressList =
1148 LdrGetExportByOrdinal(BaseAddress,
1153 pName = (DWORD) (ImageBase + *FunctionNameList + 2);
1154 pHint = *(PWORD)(ImageBase + *FunctionNameList);
1156 *ImportAddressList =
1157 LdrGetExportByName(BaseAddress, (PUCHAR)pName, pHint);
1158 if ((*ImportAddressList) == NULL)
1160 DbgPrint("Failed to import %s\n", pName);
1161 return STATUS_UNSUCCESSFUL;
1164 ImportAddressList++;
1169 * Protect the region we are about to write into.
1171 Status = NtProtectVirtualMemory(NtCurrentProcess(),
1173 IATSize * sizeof(PVOID*),
1176 if (!NT_SUCCESS(Status))
1178 DbgPrint("LDR: Failed to protect IAT.\n");
1182 ImportModuleDirectory++;
1184 return STATUS_SUCCESS;
1188 /**********************************************************************
1193 * 1. Map the DLL's sections into memory.
1194 * 2. Relocate, if needed the DLL.
1195 * 3. Fixup any imported symbol.
1196 * 4. Compute the DLL's entry point.
1200 * Address at which the DLL's image
1204 * Handle of the section that contains
1208 * NULL on error; otherwise the entry point
1209 * to call for initializing the DLL.
1216 PEPFUNC LdrPEStartup (PVOID ImageBase,
1217 HANDLE SectionHandle,
1218 PLDR_MODULE* Module,
1222 PEPFUNC EntryPoint = NULL;
1223 PIMAGE_DOS_HEADER DosHeader;
1224 PIMAGE_NT_HEADERS NTHeaders;
1226 DPRINT("LdrPEStartup(ImageBase %x SectionHandle %x)\n",
1227 ImageBase, (ULONG)SectionHandle);
1230 * Overlay DOS and WNT headers structures
1231 * to the DLL's image.
1233 DosHeader = (PIMAGE_DOS_HEADER) ImageBase;
1234 NTHeaders = (PIMAGE_NT_HEADERS) (ImageBase + DosHeader->e_lfanew);
1237 * If the base address is different from the
1238 * one the DLL is actually loaded, perform any
1241 if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
1243 DbgPrint("LDR: Performing relocations\n");
1244 Status = LdrPerformRelocations(NTHeaders, ImageBase);
1245 if (!NT_SUCCESS(Status))
1247 DbgPrint("LdrPerformRelocations() failed\n");
1254 *Module = LdrAddModuleEntry(ImageBase, NTHeaders, FullDosName);
1258 * If the DLL's imports symbols from other
1259 * modules, fixup the imported calls entry points.
1261 if (NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1262 .VirtualAddress != 0)
1264 DPRINT("About to fixup imports\n");
1265 Status = LdrFixupImports(NTHeaders, ImageBase);
1266 if (!NT_SUCCESS(Status))
1268 DbgPrint("LdrFixupImports() failed\n");
1271 DPRINT("Fixup done\n");
1275 * Compute the DLL's entry point's address.
1277 DPRINT("ImageBase = %x\n",(ULONG)ImageBase);
1278 DPRINT("AddressOfEntryPoint = %x\n",(ULONG)NTHeaders->OptionalHeader.AddressOfEntryPoint);
1279 if (NTHeaders->OptionalHeader.AddressOfEntryPoint != 0)
1281 EntryPoint = (PEPFUNC) (ImageBase
1282 + NTHeaders->OptionalHeader.AddressOfEntryPoint);
1284 DPRINT("LdrPEStartup() = %x\n",EntryPoint);
1290 LdrUnloadDll (IN PVOID BaseAddress)
1292 PIMAGE_NT_HEADERS NtHeaders;
1293 PDLLMAIN_FUNC Entrypoint;
1294 PLIST_ENTRY ModuleListHead;
1299 if (BaseAddress == NULL)
1300 return STATUS_SUCCESS;
1302 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1303 Entry = ModuleListHead->Flink;
1305 while (Entry != ModuleListHead)
1307 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
1308 if (Module->BaseAddress == BaseAddress)
1310 if (Module->LoadCount == -1)
1312 /* never unload this dll */
1313 return STATUS_SUCCESS;
1315 else if (Module->LoadCount > 1)
1317 Module->LoadCount--;
1318 return STATUS_SUCCESS;
1321 NtHeaders = RtlImageNtHeader (Module->BaseAddress);
1322 if ((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) == IMAGE_FILE_DLL)
1324 if (Module->EntryPoint != 0)
1326 Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
1327 DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
1328 Entrypoint(Module->BaseAddress,
1334 DPRINT("NTDLL.LDR: Entrypoint is NULL for \n");
1337 Status = ZwUnmapViewOfSection (NtCurrentProcess (),
1338 Module->BaseAddress);
1339 ZwClose (Module->SectionHandle);
1341 /* remove the module entry from the list */
1342 RtlFreeUnicodeString (&Module->FullDllName);
1343 RtlFreeUnicodeString (&Module->BaseDllName);
1344 RemoveEntryList (Entry);
1345 RtlFreeHeap (RtlGetProcessHeap (), 0, Module);
1350 Entry = Entry->Flink;
1353 DPRINT("NTDLL.LDR: Dll not found\n")
1355 return STATUS_UNSUCCESSFUL;
1358 #if 0 /*MOVED_TO_FILE_RES_C*/
1361 LdrFindResource_U(PVOID BaseAddress,
1362 PLDR_RESOURCE_INFO ResourceInfo,
1364 PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry)
1366 PIMAGE_RESOURCE_DIRECTORY ResDir;
1367 PIMAGE_RESOURCE_DIRECTORY ResBase;
1368 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
1369 NTSTATUS Status = STATUS_SUCCESS;
1375 DPRINT ("LdrFindResource_U()\n");
1377 /* Get the pointer to the resource directory */
1378 ResDir = (PIMAGE_RESOURCE_DIRECTORY)
1379 RtlImageDirectoryEntryToData (BaseAddress,
1381 IMAGE_DIRECTORY_ENTRY_RESOURCE,
1385 return STATUS_RESOURCE_DATA_NOT_FOUND;
1388 DPRINT("ResourceDirectory: %x\n", (ULONG)ResDir);
1392 /* Let's go into resource tree */
1393 for (i = 0; i < Level; i++)
1395 DPRINT("ResDir: %x\n", (ULONG)ResDir);
1396 Id = ((PULONG)ResourceInfo)[i];
1397 EntryCount = ResDir->NumberOfNamedEntries;
1398 ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
1399 DPRINT("ResEntry %x\n", (ULONG)ResEntry);
1400 if (Id & 0xFFFF0000)
1402 /* Resource name is a unicode string */
1403 for (; EntryCount--; ResEntry++)
1405 /* Scan entries for equal name */
1406 if (ResEntry->Name & 0x80000000)
1408 ws = (PWCHAR)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
1409 if (!wcsncmp((PWCHAR)Id, ws + 1, *ws ) &&
1410 wcslen((PWCHAR)Id) == (int)*ws )
1419 /* We use ID number instead of string */
1420 ResEntry += EntryCount;
1421 EntryCount = ResDir->NumberOfIdEntries;
1422 for (; EntryCount--; ResEntry++)
1424 /* Scan entries for equal name */
1425 if (ResEntry->Name == Id)
1427 DPRINT("ID entry found %x\n", Id);
1432 DPRINT("Error %lu\n", i);
1437 return STATUS_RESOURCE_TYPE_NOT_FOUND;
1440 return STATUS_RESOURCE_NAME_NOT_FOUND;
1443 if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries)
1445 /* Use the first available language */
1446 ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
1449 return STATUS_RESOURCE_LANG_NOT_FOUND;
1452 return STATUS_RESOURCE_DATA_NOT_FOUND;
1455 return STATUS_INVALID_PARAMETER;
1458 ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
1459 (ResEntry->OffsetToData & 0x7FFFFFFF));
1461 DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir);
1463 if (ResourceDataEntry)
1465 *ResourceDataEntry = (PVOID)ResDir;
1473 LdrAccessResource(IN PVOID BaseAddress,
1474 IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
1475 OUT PVOID *Resource OPTIONAL,
1476 OUT PULONG Size OPTIONAL)
1478 PIMAGE_SECTION_HEADER Section;
1479 PIMAGE_NT_HEADERS NtHeader;
1486 Data = (ULONG)RtlImageDirectoryEntryToData (BaseAddress,
1488 IMAGE_DIRECTORY_ENTRY_RESOURCE,
1491 return STATUS_RESOURCE_DATA_NOT_FOUND;
1493 if ((ULONG)BaseAddress & 1)
1495 /* loaded as ordinary file */
1496 NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL));
1497 Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
1498 Section = RtlImageRvaToSection (NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
1499 if (Section == NULL)
1501 return STATUS_RESOURCE_DATA_NOT_FOUND;
1504 if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData)
1506 SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress;
1507 SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL);
1508 Offset = SectionRva - SectionVa + Data - Section->VirtualAddress;
1514 *Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + (ULONG)BaseAddress);
1519 *Size = ResourceDataEntry->Size;
1522 return STATUS_SUCCESS;
1525 #endif /*MOVED_TO_FILE_RES_C*/
1528 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress)
1530 PLIST_ENTRY ModuleListHead;
1535 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %x)\n", BaseAddress);
1537 Status = STATUS_DLL_NOT_FOUND;
1538 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1539 Entry = ModuleListHead->Flink;
1540 while (Entry != ModuleListHead) {
1541 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
1543 DPRINT("BaseDllName %wZ BaseAddress %x\n", &Module->BaseDllName, Module->BaseAddress);
1545 if (Module->BaseAddress == BaseAddress) {
1546 if (Module->TlsIndex == 0) {
1547 Module->Flags |= 0x00040000;
1548 Status = STATUS_SUCCESS;
1552 Entry = Entry->Flink;
1557 #if 0 /*MOVED_TO_FILE_RES_C*/
1560 LdrFindResourceDirectory_U (IN PVOID BaseAddress,
1565 PIMAGE_RESOURCE_DIRECTORY ResDir;
1566 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
1569 NTSTATUS Status = STATUS_SUCCESS;
1572 /* Get the pointer to the resource directory */
1573 ResDir = (PIMAGE_RESOURCE_DIRECTORY)
1574 RtlImageDirectoryEntryToData (BaseAddress,
1576 IMAGE_DIRECTORY_ENTRY_RESOURCE,
1580 return STATUS_RESOURCE_DATA_NOT_FOUND;
1583 /* Let's go into resource tree */
1584 for (i = 0; i < level; i++, name++)
1586 EntryCount = ResDir->NumberOfNamedEntries;
1587 ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
1588 if ((ULONG)(*name) & 0xFFFF0000)
1590 /* Resource name is a unicode string */
1591 for (; EntryCount--; ResEntry++)
1593 /* Scan entries for equal name */
1594 if (ResEntry->Name & 0x80000000)
1596 ws = (WCHAR*)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
1597 if (!wcsncmp( *name, ws + 1, *ws ) && wcslen( *name ) == (int)*ws )
1606 /* We use ID number instead of string */
1607 ResEntry += EntryCount;
1608 EntryCount = ResDir->NumberOfIdEntries;
1609 for (; EntryCount--; ResEntry++)
1611 /* Scan entries for equal name */
1612 if (ResEntry->Name == (ULONG)(*name))
1620 return STATUS_RESOURCE_TYPE_NOT_FOUND;
1623 return STATUS_RESOURCE_NAME_NOT_FOUND;
1626 Status = STATUS_RESOURCE_LANG_NOT_FOUND;
1627 /* Just use first language entry */
1628 if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries)
1630 ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
1636 return STATUS_RESOURCE_DATA_NOT_FOUND;
1639 return STATUS_INVALID_PARAMETER;
1642 ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResDir + ResEntry->OffsetToData);
1647 *addr = (PVOID)ResDir;
1653 #endif /*MOVED_TO_FILE_RES_C*/
1657 LdrGetDllHandle(IN ULONG Unknown1,
1659 IN PUNICODE_STRING DllName,
1660 OUT PVOID* BaseAddress)
1662 UNICODE_STRING FullDllName;
1663 PLIST_ENTRY ModuleListHead;
1667 DPRINT("LdrGetDllHandle (Unknown1 %x Unknown2 %x DllName %wZ BaseAddress %p)\n",
1668 Unknown1, Unknown2, DllName, BaseAddress);
1670 /* NULL is the current executable */
1671 if (DllName == NULL) {
1672 *BaseAddress = NtCurrentPeb()->ImageBaseAddress;
1673 DPRINT("BaseAddress %x\n", *BaseAddress);
1674 return STATUS_SUCCESS;
1676 LdrAdjustDllName(&FullDllName, DllName, TRUE);
1678 DPRINT("FullDllName %wZ\n", &FullDllName);
1680 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1681 Entry = ModuleListHead->Flink;
1682 while (Entry != ModuleListHead) {
1683 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
1685 DPRINT("EntryPoint %x\n", Module->EntryPoint);
1686 DPRINT("Comparing %wZ and %wZ\n", &Module->BaseDllName, &FullDllName);
1688 if (!RtlCompareUnicodeString(&Module->BaseDllName, &FullDllName, TRUE)) {
1689 RtlFreeUnicodeString(&FullDllName);
1690 *BaseAddress = Module->BaseAddress;
1691 DPRINT("BaseAddress %x\n", *BaseAddress);
1692 return STATUS_SUCCESS;
1694 Entry = Entry->Flink;
1697 DPRINT("Failed to find dll %wZ\n", &FullDllName);
1699 RtlFreeUnicodeString(&FullDllName);
1700 *BaseAddress = NULL;
1701 return STATUS_DLL_NOT_FOUND;
1706 LdrGetProcedureAddress (IN PVOID BaseAddress,
1707 IN PANSI_STRING Name,
1709 OUT PVOID *ProcedureAddress)
1711 PIMAGE_EXPORT_DIRECTORY ExportDir;
1717 DPRINT("LdrGetProcedureAddress (BaseAddress %x Name %Z Ordinal %lu ProcedureAddress %x)\n",
1718 BaseAddress, Name, Ordinal, ProcedureAddress);
1720 /* Get the pointer to the export directory */
1721 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1722 RtlImageDirectoryEntryToData (BaseAddress,
1724 IMAGE_DIRECTORY_ENTRY_EXPORT,
1727 DPRINT("ExportDir %x i %lu\n", ExportDir, i);
1729 if (!ExportDir || !i || !ProcedureAddress)
1731 return STATUS_INVALID_PARAMETER;
1734 AddressPtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfFunctions);
1735 if (Name && Name->Length)
1738 OrdinalPtr = (PUSHORT)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNameOrdinals);
1739 NamePtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNames);
1740 for( i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
1742 if (!_strnicmp(Name->Buffer, (char*)(BaseAddress + *NamePtr), Name->Length))
1744 *ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[*OrdinalPtr]);
1745 return STATUS_SUCCESS;
1748 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
1753 Ordinal &= 0x0000FFFF;
1754 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
1756 *ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[Ordinal - ExportDir->Base]);
1757 return STATUS_SUCCESS;
1759 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal);
1762 return STATUS_PROCEDURE_NOT_FOUND;
1767 LdrShutdownProcess (VOID)
1769 PLIST_ENTRY ModuleListHead;
1773 DPRINT("LdrShutdownProcess() called\n");
1775 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
1777 ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
1778 Entry = ModuleListHead->Blink;
1780 while (Entry != ModuleListHead)
1782 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InInitializationOrderModuleList);
1784 DPRINT(" Unloading %wZ\n",
1785 &Module->BaseDllName);
1786 // PJS: only detach from static dlls, they should FreeLibrary() any dlls that
1787 // they loaded dynamically, and when the last reference is gone, that lib will
1789 if (Module->EntryPoint != 0 && Module->LoadCount == -1)
1791 PDLLMAIN_FUNC Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
1793 DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
1794 Entrypoint (Module->BaseAddress,
1799 Entry = Entry->Blink;
1802 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1804 DPRINT("LdrShutdownProcess() done\n");
1806 return STATUS_SUCCESS;
1811 LdrShutdownThread (VOID)
1813 PLIST_ENTRY ModuleListHead;
1817 DPRINT("LdrShutdownThread() called\n");
1819 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
1821 ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
1822 Entry = ModuleListHead->Blink;
1824 while (Entry != ModuleListHead)
1826 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InInitializationOrderModuleList);
1828 DPRINT(" Unloading %wZ\n",
1829 &Module->BaseDllName);
1831 if (Module->EntryPoint != 0)
1833 PDLLMAIN_FUNC Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
1835 DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
1836 Entrypoint (Module->BaseAddress,
1841 Entry = Entry->Blink;
1844 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1846 DPRINT("LdrShutdownThread() done\n");
1848 return STATUS_SUCCESS;
1852 /***************************************************************************
1854 * LdrQueryProcessModuleInformation
1867 LdrQueryProcessModuleInformation(IN PMODULE_INFORMATION ModuleInformation OPTIONAL,
1868 IN ULONG Size OPTIONAL,
1869 OUT PULONG ReturnedSize)
1872 PLIST_ENTRY ModuleListHead;
1875 PMODULE_ENTRY ModulePtr = NULL;
1876 NTSTATUS Status = STATUS_SUCCESS;
1877 ULONG UsedSize = sizeof(ULONG);
1878 ANSI_STRING AnsiString;
1881 DPRINT("LdrQueryProcessModuleInformation() called\n");
1883 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
1885 if (ModuleInformation == NULL || Size == 0)
1887 Status = STATUS_INFO_LENGTH_MISMATCH;
1891 ModuleInformation->ModuleCount = 0;
1892 ModulePtr = &ModuleInformation->ModuleEntry[0];
1893 Status = STATUS_SUCCESS;
1896 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1897 Entry = ModuleListHead->Flink;
1899 while (Entry != ModuleListHead)
1901 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
1903 DPRINT(" Module %wZ\n",
1904 &Module->FullDllName);
1906 if (UsedSize > Size)
1908 Status = STATUS_INFO_LENGTH_MISMATCH;
1910 else if (ModuleInformation != NULL)
1912 ModulePtr->Unknown0 = 0; // FIXME: ??
1913 ModulePtr->Unknown1 = 0; // FIXME: ??
1914 ModulePtr->BaseAddress = Module->BaseAddress;
1915 ModulePtr->SizeOfImage = Module->SizeOfImage;
1916 ModulePtr->Flags = Module->Flags;
1917 ModulePtr->Unknown2 = 0; // FIXME: load order index ??
1918 ModulePtr->Unknown3 = 0; // FIXME: ??
1919 ModulePtr->LoadCount = Module->LoadCount;
1921 AnsiString.Length = 0;
1922 AnsiString.MaximumLength = 256;
1923 AnsiString.Buffer = ModulePtr->ModuleName;
1924 RtlUnicodeStringToAnsiString(&AnsiString,
1925 &Module->FullDllName,
1927 p = strrchr(ModulePtr->ModuleName, '\\');
1929 ModulePtr->PathLength = p - ModulePtr->ModuleName + 1;
1931 ModulePtr->PathLength = 0;
1934 ModuleInformation->ModuleCount++;
1936 UsedSize += sizeof(MODULE_ENTRY);
1938 Entry = Entry->Flink;
1941 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1943 if (ReturnedSize != 0)
1944 *ReturnedSize = UsedSize;
1946 DPRINT("LdrQueryProcessModuleInformation() done\n");