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 /* GLOBALS *******************************************************************/
36 static HANDLE LdrpKnownDllsDirHandle = NULL;
37 static UNICODE_STRING LdrpKnownDllPath = {0, 0, NULL};
40 /* PROTOTYPES ****************************************************************/
42 static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_MODULE *Module);
43 static PVOID LdrFixupForward(PCHAR ForwardName);
44 static PVOID LdrGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hint);
47 /* FUNCTIONS *****************************************************************/
53 LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule)
70 OBJECT_ATTRIBUTES ObjectAttributes;
71 UNICODE_STRING LinkTarget;
77 DPRINT("LdrpInitLoader() called\n");
79 /* Get handle to the 'KnownDlls' directory */
80 RtlInitUnicodeString(&Name,
82 InitializeObjectAttributes(&ObjectAttributes,
87 Status = NtOpenDirectoryObject(&LdrpKnownDllsDirHandle,
88 DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
90 if (!NT_SUCCESS(Status))
92 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
93 LdrpKnownDllsDirHandle = NULL;
97 /* Allocate target name string */
98 LinkTarget.Length = 0;
99 LinkTarget.MaximumLength = MAX_PATH * sizeof(WCHAR);
100 LinkTarget.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
102 MAX_PATH * sizeof(WCHAR));
103 if (LinkTarget.Buffer == NULL)
105 NtClose(LdrpKnownDllsDirHandle);
106 LdrpKnownDllsDirHandle = NULL;
110 RtlInitUnicodeString(&Name,
112 InitializeObjectAttributes(&ObjectAttributes,
114 OBJ_CASE_INSENSITIVE | OBJ_OPENLINK,
115 LdrpKnownDllsDirHandle,
117 Status = NtOpenSymbolicLinkObject(&LinkHandle,
118 SYMBOLIC_LINK_ALL_ACCESS,
120 if (!NT_SUCCESS(Status))
122 RtlFreeUnicodeString(&LinkTarget);
123 NtClose(LdrpKnownDllsDirHandle);
124 LdrpKnownDllsDirHandle = NULL;
128 Status = NtQuerySymbolicLinkObject(LinkHandle,
132 if (!NT_SUCCESS(Status))
134 RtlFreeUnicodeString(&LinkTarget);
135 NtClose(LdrpKnownDllsDirHandle);
136 LdrpKnownDllsDirHandle = NULL;
139 RtlCreateUnicodeString(&LdrpKnownDllPath,
142 RtlFreeUnicodeString(&LinkTarget);
144 DPRINT("LdrpInitLoader() done\n");
148 /***************************************************************************
153 * Adjusts the name of a dll to a fully qualified name.
156 * FullDllName: Pointer to caller supplied storage for the fully
157 * qualified dll name.
158 * DllName: Pointer to the dll name.
159 * BaseName: TRUE: Only the file name is passed to FullDllName
160 * FALSE: The full path is preserved in FullDllName
168 * A given path is not affected by the adjustment, but the file
170 * ntdll --> ntdll.dll
172 * ntdll.xyz --> ntdll.xyz
176 LdrAdjustDllName (PUNICODE_STRING FullDllName,
177 PUNICODE_STRING DllName,
180 WCHAR Buffer[MAX_PATH];
185 Length = DllName->Length / sizeof(WCHAR);
187 if (BaseName == TRUE)
189 /* get the base dll name */
190 Pointer = DllName->Buffer + Length;
197 while (Pointer >= DllName->Buffer && *Pointer != L'\\' && *Pointer != L'/');
200 Length = Extension - Pointer;
201 memmove (Buffer, Pointer, Length * sizeof(WCHAR));
202 Buffer[Length] = L'\0';
206 /* get the full dll name */
207 memmove (Buffer, DllName->Buffer, DllName->Length);
208 Buffer[DllName->Length / sizeof(WCHAR)] = L'\0';
211 /* Build the DLL's absolute name */
212 Extension = wcsrchr (Buffer, L'.');
213 if ((Extension != NULL) && (*Extension == L'.'))
215 /* with extension - remove dot if it's the last character */
216 if (Buffer[Length - 1] == L'.')
222 /* name without extension - assume that it is .dll */
223 memmove (Buffer + Length, L".dll", 10);
226 RtlCreateUnicodeString(FullDllName, Buffer);
230 LdrAddModuleEntry(PVOID ImageBase,
231 PIMAGE_NT_HEADERS NTHeaders,
235 Module = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_MODULE));
237 memset(Module, 0, sizeof(LDR_MODULE));
238 Module->BaseAddress = (PVOID)ImageBase;
239 Module->EntryPoint = NTHeaders->OptionalHeader.AddressOfEntryPoint;
240 if (Module->EntryPoint != 0)
241 Module->EntryPoint += (ULONG)Module->BaseAddress;
242 Module->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
243 if (NtCurrentPeb()->Ldr->Initialized == TRUE)
245 /* loading while app is running */
246 Module->LoadCount = 1;
249 * loading while app is initializing
250 * dll must not be unloaded
252 Module->LoadCount = -1;
255 Module->TlsIndex = 0;
256 Module->CheckSum = NTHeaders->OptionalHeader.CheckSum;
257 Module->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
259 RtlCreateUnicodeString (&Module->FullDllName,
261 RtlCreateUnicodeString (&Module->BaseDllName,
262 wcsrchr(FullDosName, L'\\') + 1);
263 DPRINT ("BaseDllName %wZ\n", &Module->BaseDllName);
265 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
266 InsertTailList(&NtCurrentPeb()->Ldr->InLoadOrderModuleList,
267 &Module->InLoadOrderModuleList);
268 InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
269 &Module->InInitializationOrderModuleList);
270 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
277 LdrpMapKnownDll(IN PUNICODE_STRING DllName,
278 OUT PUNICODE_STRING FullDosName,
279 OUT PHANDLE SectionHandle)
281 OBJECT_ATTRIBUTES ObjectAttributes;
284 DPRINT("LdrpMapKnownDll() called\n");
286 if (LdrpKnownDllsDirHandle == NULL)
288 DPRINT("Invalid 'KnownDlls' directory\n");
289 return STATUS_UNSUCCESSFUL;
292 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath);
294 InitializeObjectAttributes(&ObjectAttributes,
296 OBJ_CASE_INSENSITIVE,
297 LdrpKnownDllsDirHandle,
299 Status = NtOpenSection(SectionHandle,
300 SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
302 if (!NT_SUCCESS(Status))
304 DPRINT("NtOpenSection() failed for '%wZ' (Status %lx)\n", DllName, Status);
308 FullDosName->Length = LdrpKnownDllPath.Length + DllName->Length + sizeof(WCHAR);
309 FullDosName->MaximumLength = FullDosName->Length + sizeof(WCHAR);
310 FullDosName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
312 FullDosName->MaximumLength);
313 if (FullDosName->Buffer == NULL)
315 FullDosName->Length = 0;
316 FullDosName->MaximumLength = 0;
317 return STATUS_SUCCESS;
320 wcscpy(FullDosName->Buffer, LdrpKnownDllPath.Buffer);
321 wcscat(FullDosName->Buffer, L"\\");
322 wcscat(FullDosName->Buffer, DllName->Buffer);
324 DPRINT("FullDosName '%wZ'\n", FullDosName);
326 DPRINT("LdrpMapKnownDll() done\n");
328 return STATUS_SUCCESS;
333 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
334 IN PUNICODE_STRING DllName,
335 OUT PUNICODE_STRING FullDosName,
336 OUT PHANDLE SectionHandle)
338 WCHAR SearchPathBuffer[MAX_PATH];
339 WCHAR DosName[MAX_PATH];
340 UNICODE_STRING FullNtFileName;
341 OBJECT_ATTRIBUTES FileObjectAttributes;
343 char BlockBuffer [1024];
344 PIMAGE_DOS_HEADER DosHeader;
345 PIMAGE_NT_HEADERS NTHeaders;
350 DPRINT("LdrpMapDllImageFile() called\n");
352 if (SearchPath == NULL)
354 SearchPath = SearchPathBuffer;
355 wcscpy (SearchPathBuffer, SharedUserData->NtSystemRoot);
356 wcscat (SearchPathBuffer, L"\\system32;");
357 wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
358 wcscat (SearchPathBuffer, L";.");
361 DPRINT("SearchPath %S\n", SearchPath);
363 if (RtlDosSearchPath_U (SearchPath,
369 return STATUS_DLL_NOT_FOUND;
371 DPRINT("DosName %S\n", DosName);
373 if (!RtlDosPathNameToNtPathName_U (DosName,
377 return STATUS_DLL_NOT_FOUND;
379 DPRINT("FullNtFileName %wZ\n", &FullNtFileName);
381 InitializeObjectAttributes(&FileObjectAttributes,
387 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName);
389 Status = ZwOpenFile(&FileHandle,
391 &FileObjectAttributes,
395 if (!NT_SUCCESS(Status))
397 DbgPrint("Dll open of %wZ failed: Status = 0x%08x\n",
398 &FullNtFileName, Status);
399 RtlFreeUnicodeString (&FullNtFileName);
402 RtlFreeUnicodeString (&FullNtFileName);
404 Status = ZwReadFile(FileHandle,
413 if (!NT_SUCCESS(Status))
415 DPRINT("Dll header read failed: Status = 0x%08x\n", Status);
420 * Overlay DOS and NT headers structures to the
421 * buffer with DLL's header raw data.
423 DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
424 NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew);
426 * Check it is a PE image file.
428 if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
429 || (DosHeader->e_lfanew == 0L)
430 || (*(PULONG)(NTHeaders) != IMAGE_PE_MAGIC))
432 DPRINT("NTDLL format invalid\n");
435 return STATUS_UNSUCCESSFUL;
438 ImageBase = (PVOID) NTHeaders->OptionalHeader.ImageBase;
439 ImageSize = NTHeaders->OptionalHeader.SizeOfImage;
441 DPRINT("ImageBase 0x%08x\n", ImageBase);
444 * Create a section for dll.
446 Status = ZwCreateSection(SectionHandle,
451 SEC_COMMIT | SEC_IMAGE,
455 if (!NT_SUCCESS(Status))
457 DPRINT("NTDLL create section failed: Status = 0x%08x\n", Status);
461 RtlCreateUnicodeString(FullDosName,
469 /***************************************************************************
487 LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
489 IN PUNICODE_STRING Name,
490 OUT PVOID *BaseAddress OPTIONAL)
492 UNICODE_STRING FullDosName;
493 UNICODE_STRING AdjustedName;
495 PIMAGE_NT_HEADERS NTHeaders;
498 HANDLE SectionHandle;
499 PDLLMAIN_FUNC Entrypoint = NULL;
505 *BaseAddress = NtCurrentPeb()->ImageBaseAddress;
506 return STATUS_SUCCESS;
511 DPRINT("LdrLoadDll(Name \"%wZ\" BaseAddress %x)\n",
514 /* adjust the full dll name */
515 LdrAdjustDllName (&AdjustedName,
518 DPRINT("AdjustedName: %wZ\n", &AdjustedName);
521 * Test if dll is already loaded.
523 if (LdrFindEntryForName(&AdjustedName, &Module) == STATUS_SUCCESS)
525 DPRINT("DLL %wZ already loaded.\n", &AdjustedName);
526 *BaseAddress = Module->BaseAddress;
527 return STATUS_SUCCESS;
529 DPRINT("Loading \"%wZ\"\n", Name);
531 /* Open or create dll image section */
532 Status = LdrpMapKnownDll(&AdjustedName,
535 if (!NT_SUCCESS(Status))
537 Status = LdrpMapDllImageFile(SearchPath,
543 RtlFreeUnicodeString(&AdjustedName);
545 if (!NT_SUCCESS(Status))
547 DPRINT1("Failed to create or open dll section (Status %lx)\n", Status);
552 * Map the dll into the process.
556 Status = NtMapViewOfSection(SectionHandle,
566 if (!NT_SUCCESS(Status))
568 DbgPrint("NTDLL.LDR: map view of section failed (Status %x)\n", Status);
569 RtlFreeUnicodeString(&FullDosName);
570 NtClose(SectionHandle);
574 /* Get and check the NT headers */
575 NTHeaders = RtlImageNtHeader(ImageBase);
576 if (NTHeaders == NULL)
578 DPRINT1("RtlImageNtHeaders() failed\n");
579 RtlFreeUnicodeString(&FullDosName);
580 return STATUS_UNSUCCESSFUL;
583 /* relocate dll and fixup import table */
584 if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) ==
588 (PDLLMAIN_FUNC) LdrPEStartup(ImageBase, SectionHandle, &Module,
590 if (Entrypoint == NULL)
592 RtlFreeUnicodeString(&FullDosName);
593 return(STATUS_UNSUCCESSFUL);
597 RtlFreeUnicodeString(&FullDosName);
601 LdrpLoadUserModuleSymbols(Module);
606 if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) ==
609 if (Module->EntryPoint != 0)
611 Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
613 DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
614 if (FALSE == Entrypoint(Module->BaseAddress,
618 /* Do this as a DPRINT1 for now, until clean up and fail implemented */
619 DPRINT1("NTDLL.LDR: DLL \"%wZ\" failed to initialize\n",
620 &Module->BaseDllName);
621 /* FIXME: should clean up and fail */
625 DPRINT("NTDLL.LDR: DLL \"%wZ\" initialized successfully\n",
626 &Module->BaseDllName);
631 DPRINT("NTDLL.LDR: Entrypoint is NULL for \"%wZ\"\n",
632 &Module->BaseDllName);
636 *BaseAddress = Module->BaseAddress;
637 return STATUS_SUCCESS;
641 /***************************************************************************
643 * LdrFindEntryForAddress
658 LdrFindEntryForAddress(PVOID Address,
661 PLIST_ENTRY ModuleListHead;
663 PLDR_MODULE ModulePtr;
665 DPRINT("NTDLL.LdrFindEntryForAddress(Address %p)\n", Address);
667 if (NtCurrentPeb()->Ldr == NULL)
668 return(STATUS_NO_MORE_ENTRIES);
670 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
671 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
672 Entry = ModuleListHead->Flink;
673 if (Entry == ModuleListHead)
675 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
676 return(STATUS_NO_MORE_ENTRIES);
679 while (Entry != ModuleListHead)
681 ModulePtr = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
683 DPRINT("Scanning %wZ at %p\n", &ModulePtr->BaseDllName, ModulePtr->BaseAddress);
685 if ((Address >= ModulePtr->BaseAddress) &&
686 (Address <= (ModulePtr->BaseAddress + ModulePtr->SizeOfImage)))
689 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
690 return(STATUS_SUCCESS);
693 Entry = Entry->Flink;
696 DPRINT("Failed to find module entry.\n");
698 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
699 return(STATUS_NO_MORE_ENTRIES);
703 /***************************************************************************
705 * LdrFindEntryForName
719 LdrFindEntryForName(PUNICODE_STRING Name,
722 PLIST_ENTRY ModuleListHead;
724 PLDR_MODULE ModulePtr;
725 BOOLEAN ContainsPath;
728 DPRINT("NTDLL.LdrFindEntryForName(Name %wZ)\n", Name);
730 if (NtCurrentPeb()->Ldr == NULL)
731 return(STATUS_NO_MORE_ENTRIES);
733 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
734 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
735 Entry = ModuleListHead->Flink;
736 if (Entry == ModuleListHead)
738 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
739 return(STATUS_NO_MORE_ENTRIES);
742 // NULL is the current process
745 *Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
746 if ((*Module)->LoadCount != -1)
747 (*Module)->LoadCount++;
749 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
750 return(STATUS_SUCCESS);
753 ContainsPath = (Name->Length >= 2 * sizeof(WCHAR) && L':' == Name->Buffer[1]);
754 for (i = 0; ! ContainsPath && i < Name->Length / sizeof(WCHAR); i++)
756 ContainsPath = L'\\' == Name->Buffer[i] ||
757 L'/' == Name->Buffer[i];
759 while (Entry != ModuleListHead)
761 ModulePtr = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
763 DPRINT("Scanning %wZ %wZ\n", &ModulePtr->BaseDllName, Name);
765 if ((! ContainsPath &&
766 0 == RtlCompareUnicodeString(&ModulePtr->BaseDllName, Name, TRUE)) ||
768 0 == RtlCompareUnicodeString(&ModulePtr->FullDllName, Name, TRUE)))
771 if (ModulePtr->LoadCount != -1)
772 ModulePtr->LoadCount++;
773 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
774 return(STATUS_SUCCESS);
777 Entry = Entry->Flink;
780 DPRINT("Failed to find dll %wZ\n", Name);
781 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
782 return(STATUS_NO_MORE_ENTRIES);
785 /**********************************************************************
801 LdrFixupForward(PCHAR ForwardName)
803 CHAR NameBuffer[128];
804 UNICODE_STRING DllName;
809 strcpy(NameBuffer, ForwardName);
810 p = strchr(NameBuffer, '.');
815 DPRINT("Dll: %s Function: %s\n", NameBuffer, p+1);
816 RtlCreateUnicodeStringFromAsciiz (&DllName,
819 Status = LdrGetDllHandle (0, 0, &DllName, &BaseAddress);
820 if (!NT_SUCCESS(Status))
822 Status = LdrLoadDll(NULL,
826 if (!NT_SUCCESS(Status))
828 DbgPrint("LdrFixupForward: failed to load %wZ\n", &DllName);
829 RtlFreeUnicodeString (&DllName);
834 RtlFreeUnicodeString (&DllName);
835 DPRINT("BaseAddress: %p\n", BaseAddress);
837 return LdrGetExportByName(BaseAddress, p+1, -1);
844 /**********************************************************************
846 * LdrGetExportByOrdinal
860 LdrGetExportByOrdinal (
865 PIMAGE_EXPORT_DIRECTORY ExportDir;
866 PDWORD * ExFunctions;
869 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
870 RtlImageDirectoryEntryToData (BaseAddress,
872 IMAGE_DIRECTORY_ENTRY_EXPORT,
876 ExOrdinals = (USHORT *)
879 ExportDir->AddressOfNameOrdinals
881 ExFunctions = (PDWORD *)
884 ExportDir->AddressOfFunctions
887 "LdrGetExportByOrdinal(Ordinal %d) = %x\n",
889 RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
891 return(RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] ));
895 /**********************************************************************
908 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
909 * both with NumberOfNames entries.
913 LdrGetExportByName(PVOID BaseAddress,
917 PIMAGE_EXPORT_DIRECTORY ExportDir;
918 PDWORD * ExFunctions;
928 DPRINT("LdrGetExportByName %x %s %hu\n", BaseAddress, SymbolName, Hint);
930 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
931 RtlImageDirectoryEntryToData(BaseAddress,
933 IMAGE_DIRECTORY_ENTRY_EXPORT,
935 if (ExportDir == NULL)
937 DbgPrint("LdrGetExportByName(): no export directory!\n");
942 //The symbol names may be missing entirely
943 if (ExportDir->AddressOfNames == 0)
945 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
950 * Get header pointers
952 ExNames = (PDWORD *)RVA(BaseAddress,
953 ExportDir->AddressOfNames);
954 ExOrdinals = (USHORT *)RVA(BaseAddress,
955 ExportDir->AddressOfNameOrdinals);
956 ExFunctions = (PDWORD *)RVA(BaseAddress,
957 ExportDir->AddressOfFunctions);
960 * Check the hint first
962 if (Hint < ExportDir->NumberOfNames)
964 ExName = RVA(BaseAddress, ExNames[Hint]);
965 if (strcmp(ExName, SymbolName) == 0)
967 Ordinal = ExOrdinals[Hint];
968 Function = RVA(BaseAddress, ExFunctions[Ordinal]);
969 if (((ULONG)Function >= (ULONG)ExportDir) &&
970 ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
972 DPRINT("Forward: %s\n", (PCHAR)Function);
973 Function = LdrFixupForward((PCHAR)Function);
975 if (Function != NULL)
981 * Try a binary search first
984 maxn = ExportDir->NumberOfNames;
990 mid = (minn + maxn) / 2;
992 ExName = RVA(BaseAddress, ExNames[mid]);
993 res = strcmp(ExName, SymbolName);
996 Ordinal = ExOrdinals[mid];
997 Function = RVA(BaseAddress, ExFunctions[Ordinal]);
998 if (((ULONG)Function >= (ULONG)ExportDir) &&
999 ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
1001 DPRINT("Forward: %s\n", (PCHAR)Function);
1002 Function = LdrFixupForward((PCHAR)Function);
1004 if (Function != NULL)
1007 else if (minn == maxn)
1009 DPRINT("LdrGetExportByName(): binary search failed\n");
1023 * Fall back on a linear search
1025 DPRINT("LdrGetExportByName(): Falling back on a linear search of export table\n");
1026 for (i = 0; i < ExportDir->NumberOfNames; i++)
1028 ExName = RVA(BaseAddress, ExNames[i]);
1029 if (strcmp(ExName,SymbolName) == 0)
1031 Ordinal = ExOrdinals[i];
1032 Function = RVA(BaseAddress, ExFunctions[Ordinal]);
1033 DPRINT("%x %x %x\n", Function, ExportDir, ExportDir + ExportDirSize);
1034 if (((ULONG)Function >= (ULONG)ExportDir) &&
1035 ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
1037 DPRINT("Forward: %s\n", (PCHAR)Function);
1038 Function = LdrFixupForward((PCHAR)Function);
1043 DbgPrint("LdrGetExportByName(): failed to find %s\n",SymbolName);
1048 /**********************************************************************
1050 * LdrPerformRelocations
1053 * Relocate a DLL's memory image.
1064 static NTSTATUS LdrPerformRelocations (PIMAGE_NT_HEADERS NTHeaders,
1067 USHORT NumberOfEntries;
1069 ULONG RelocationRVA;
1073 PRELOCATION_DIRECTORY RelocationDir;
1074 PRELOCATION_ENTRY RelocationBlock;
1076 PIMAGE_DATA_DIRECTORY RelocationDDir;
1080 PIMAGE_SECTION_HEADER Sections;
1083 if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
1085 return STATUS_UNSUCCESSFUL;
1089 (PIMAGE_SECTION_HEADER)((PVOID)NTHeaders + sizeof(IMAGE_NT_HEADERS));
1091 for (i = 0; i < NTHeaders->FileHeader.NumberOfSections; i++)
1093 if (!(Sections[i].Characteristics & IMAGE_SECTION_NOLOAD))
1097 (ULONG)(Sections[i].VirtualAddress + Sections[i].Misc.VirtualSize);
1098 MaxExtend = max(MaxExtend, Extend);
1103 &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
1104 RelocationRVA = RelocationDDir->VirtualAddress;
1109 (PRELOCATION_DIRECTORY)((PCHAR)ImageBase + RelocationRVA);
1111 while (RelocationDir->SizeOfBlock)
1113 if (RelocationDir->VirtualAddress > MaxExtend)
1115 RelocationRVA += RelocationDir->SizeOfBlock;
1117 (PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA);
1121 Delta32 = (ULONG)(ImageBase - NTHeaders->OptionalHeader.ImageBase);
1123 (PRELOCATION_ENTRY) (RelocationRVA + ImageBase +
1124 sizeof (RELOCATION_DIRECTORY));
1126 RelocationDir->SizeOfBlock - sizeof (RELOCATION_DIRECTORY);
1127 NumberOfEntries = NumberOfEntries / sizeof (RELOCATION_ENTRY);
1129 Status = NtProtectVirtualMemory(NtCurrentProcess(),
1131 RelocationDir->VirtualAddress,
1135 if (!NT_SUCCESS(Status))
1137 DPRINT1("Failed to unprotect relocation target.\n");
1141 if (RelocationDir->VirtualAddress + PAGE_SIZE < MaxExtend)
1143 Status = NtProtectVirtualMemory(NtCurrentProcess(),
1145 RelocationDir->VirtualAddress + PAGE_SIZE,
1149 if (!NT_SUCCESS(Status))
1151 DPRINT1("Failed to unprotect relocation target (2).\n");
1152 NtProtectVirtualMemory(NtCurrentProcess(),
1154 RelocationDir->VirtualAddress,
1162 for (i = 0; i < NumberOfEntries; i++)
1164 Offset = (RelocationBlock[i].TypeOffset & 0xfff);
1165 Offset += (ULONG)(RelocationDir->VirtualAddress + ImageBase);
1168 * What kind of relocations should we perform
1169 * for the current entry?
1171 switch (RelocationBlock[i].TypeOffset >> 12)
1173 case TYPE_RELOC_ABSOLUTE:
1176 case TYPE_RELOC_HIGH:
1177 pValue16 = (PUSHORT)Offset;
1178 *pValue16 += Delta32 >> 16;
1181 case TYPE_RELOC_LOW:
1182 pValue16 = (PUSHORT)Offset;
1183 *pValue16 += Delta32 & 0xffff;
1186 case TYPE_RELOC_HIGHLOW:
1187 pValue32 = (PULONG)Offset;
1188 *pValue32 += Delta32;
1191 case TYPE_RELOC_HIGHADJ:
1192 /* FIXME: do the highadjust fixup */
1193 DPRINT("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n");
1194 return(STATUS_UNSUCCESSFUL);
1197 DPRINT("unexpected fixup type\n");
1198 return STATUS_UNSUCCESSFUL;
1202 Status = NtProtectVirtualMemory(NtCurrentProcess(),
1204 RelocationDir->VirtualAddress,
1208 if (!NT_SUCCESS(Status))
1210 DPRINT1("Failed to protect relocation target.\n");
1214 if (RelocationDir->VirtualAddress + PAGE_SIZE < MaxExtend)
1216 Status = NtProtectVirtualMemory(NtCurrentProcess(),
1218 RelocationDir->VirtualAddress + PAGE_SIZE,
1222 if (!NT_SUCCESS(Status))
1224 DPRINT1("Failed to protect relocation target2.\n");
1229 RelocationRVA += RelocationDir->SizeOfBlock;
1231 (PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA);
1234 return STATUS_SUCCESS;
1238 /**********************************************************************
1243 * Compute the entry point for every symbol the DLL imports
1244 * from other modules.
1255 static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
1258 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1264 DPRINT("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders,
1268 * Process each import module.
1270 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)(
1271 ImageBase + NTHeaders->OptionalHeader
1272 .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1274 DPRINT("ImportModuleDirectory %x\n", ImportModuleDirectory);
1276 while (ImportModuleDirectory->dwRVAModuleName)
1278 PVOID * ImportAddressList;
1279 PULONG FunctionNameList;
1280 UNICODE_STRING DllName;
1286 DPRINT("ImportModule->Directory->dwRVAModuleName %s\n",
1287 (PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName));
1289 RtlCreateUnicodeStringFromAsciiz (&DllName,
1290 (PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName));
1292 Status = LdrGetDllHandle (0, 0, &DllName, &BaseAddress);
1293 if (!NT_SUCCESS(Status))
1295 Status = LdrLoadDll(NULL,
1299 RtlFreeUnicodeString (&DllName);
1300 if (!NT_SUCCESS(Status))
1302 DbgPrint("LdrFixupImports:failed to load %s\n"
1304 + ImportModuleDirectory->dwRVAModuleName));
1311 * Get the import address list.
1313 ImportAddressList = (PVOID *)(ImageBase
1314 + ImportModuleDirectory->dwRVAFunctionAddressList);
1317 * Get the list of functions to import.
1319 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1321 FunctionNameList = (PULONG) (
1323 + ImportModuleDirectory->dwRVAFunctionNameList
1330 + ImportModuleDirectory->dwRVAFunctionAddressList);
1334 * Get the size of IAT.
1337 while (FunctionNameList[IATSize] != 0L)
1343 * Unprotect the region we are about to write into.
1345 IATBase = (PVOID)ImportAddressList;
1346 Status = NtProtectVirtualMemory(NtCurrentProcess(),
1348 IATSize * sizeof(PVOID*),
1351 if (!NT_SUCCESS(Status))
1353 DbgPrint("LDR: Failed to unprotect IAT.\n");
1358 * Walk through function list and fixup addresses.
1360 while (*FunctionNameList != 0L)
1362 if ((*FunctionNameList) & 0x80000000)
1364 Ordinal = (*FunctionNameList) & 0x7fffffff;
1365 *ImportAddressList =
1366 LdrGetExportByOrdinal(BaseAddress,
1371 pName = (DWORD) (ImageBase + *FunctionNameList + 2);
1372 pHint = *(PWORD)(ImageBase + *FunctionNameList);
1374 *ImportAddressList =
1375 LdrGetExportByName(BaseAddress, (PUCHAR)pName, pHint);
1376 if ((*ImportAddressList) == NULL)
1378 DbgPrint("Failed to import %s\n", pName);
1379 return STATUS_UNSUCCESSFUL;
1382 ImportAddressList++;
1387 * Protect the region we are about to write into.
1389 Status = NtProtectVirtualMemory(NtCurrentProcess(),
1391 IATSize * sizeof(PVOID*),
1394 if (!NT_SUCCESS(Status))
1396 DbgPrint("LDR: Failed to protect IAT.\n");
1400 ImportModuleDirectory++;
1402 return STATUS_SUCCESS;
1406 /**********************************************************************
1411 * 1. Map the DLL's sections into memory.
1412 * 2. Relocate, if needed the DLL.
1413 * 3. Fixup any imported symbol.
1414 * 4. Compute the DLL's entry point.
1418 * Address at which the DLL's image
1422 * Handle of the section that contains
1426 * NULL on error; otherwise the entry point
1427 * to call for initializing the DLL.
1434 PEPFUNC LdrPEStartup (PVOID ImageBase,
1435 HANDLE SectionHandle,
1436 PLDR_MODULE* Module,
1440 PEPFUNC EntryPoint = NULL;
1441 PIMAGE_DOS_HEADER DosHeader;
1442 PIMAGE_NT_HEADERS NTHeaders;
1444 DPRINT("LdrPEStartup(ImageBase %x SectionHandle %x)\n",
1445 ImageBase, (ULONG)SectionHandle);
1448 * Overlay DOS and WNT headers structures
1449 * to the DLL's image.
1451 DosHeader = (PIMAGE_DOS_HEADER) ImageBase;
1452 NTHeaders = (PIMAGE_NT_HEADERS) (ImageBase + DosHeader->e_lfanew);
1455 * If the base address is different from the
1456 * one the DLL is actually loaded, perform any
1459 if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
1461 DbgPrint("LDR: Performing relocations\n");
1462 Status = LdrPerformRelocations(NTHeaders, ImageBase);
1463 if (!NT_SUCCESS(Status))
1465 DbgPrint("LdrPerformRelocations() failed\n");
1472 *Module = LdrAddModuleEntry(ImageBase, NTHeaders, FullDosName);
1473 (*Module)->SectionHandle = SectionHandle;
1477 * If the DLL's imports symbols from other
1478 * modules, fixup the imported calls entry points.
1480 if (NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1481 .VirtualAddress != 0)
1483 DPRINT("About to fixup imports\n");
1484 Status = LdrFixupImports(NTHeaders, ImageBase);
1485 if (!NT_SUCCESS(Status))
1487 DbgPrint("LdrFixupImports() failed\n");
1490 DPRINT("Fixup done\n");
1494 * Compute the DLL's entry point's address.
1496 DPRINT("ImageBase = %x\n",(ULONG)ImageBase);
1497 DPRINT("AddressOfEntryPoint = %x\n",(ULONG)NTHeaders->OptionalHeader.AddressOfEntryPoint);
1498 if (NTHeaders->OptionalHeader.AddressOfEntryPoint != 0)
1500 EntryPoint = (PEPFUNC) (ImageBase
1501 + NTHeaders->OptionalHeader.AddressOfEntryPoint);
1503 DPRINT("LdrPEStartup() = %x\n",EntryPoint);
1512 LdrUnloadDll (IN PVOID BaseAddress)
1514 PIMAGE_NT_HEADERS NtHeaders;
1515 PDLLMAIN_FUNC Entrypoint;
1516 PLIST_ENTRY ModuleListHead;
1521 if (BaseAddress == NULL)
1522 return STATUS_SUCCESS;
1524 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
1526 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1527 Entry = ModuleListHead->Flink;
1529 while (Entry != ModuleListHead)
1531 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
1532 if (Module->BaseAddress == BaseAddress)
1534 if (Module->LoadCount == -1)
1536 /* never unload this dll */
1537 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1538 return STATUS_SUCCESS;
1540 else if (Module->LoadCount > 1)
1542 Module->LoadCount--;
1543 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1544 return STATUS_SUCCESS;
1547 NtHeaders = RtlImageNtHeader (Module->BaseAddress);
1548 if ((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) == IMAGE_FILE_DLL)
1550 if (Module->EntryPoint != 0)
1552 Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
1553 DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
1554 Entrypoint(Module->BaseAddress,
1560 DPRINT("NTDLL.LDR: Entrypoint is NULL for \n");
1563 Status = ZwUnmapViewOfSection (NtCurrentProcess (),
1564 Module->BaseAddress);
1565 ZwClose (Module->SectionHandle);
1567 /* remove the module entry from the list */
1568 RemoveEntryList (&Module->InLoadOrderModuleList)
1569 RemoveEntryList (&Module->InInitializationOrderModuleList);
1570 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1572 RtlFreeUnicodeString (&Module->FullDllName);
1573 RtlFreeUnicodeString (&Module->BaseDllName);
1575 RtlFreeHeap (RtlGetProcessHeap (), 0, Module);
1580 Entry = Entry->Flink;
1582 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1584 DPRINT("NTDLL.LDR: Dll not found\n")
1586 return STATUS_UNSUCCESSFUL;
1594 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress)
1596 PLIST_ENTRY ModuleListHead;
1601 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %x)\n", BaseAddress);
1603 Status = STATUS_DLL_NOT_FOUND;
1604 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
1605 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1606 Entry = ModuleListHead->Flink;
1607 while (Entry != ModuleListHead) {
1608 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
1610 DPRINT("BaseDllName %wZ BaseAddress %x\n", &Module->BaseDllName, Module->BaseAddress);
1612 if (Module->BaseAddress == BaseAddress) {
1613 if (Module->TlsIndex == 0) {
1614 Module->Flags |= 0x00040000;
1615 Status = STATUS_SUCCESS;
1619 Entry = Entry->Flink;
1621 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1630 LdrGetDllHandle(IN ULONG Unknown1,
1632 IN PUNICODE_STRING DllName,
1633 OUT PVOID* BaseAddress)
1635 UNICODE_STRING FullDllName;
1636 PLIST_ENTRY ModuleListHead;
1640 DPRINT("LdrGetDllHandle (Unknown1 %x Unknown2 %x DllName %wZ BaseAddress %p)\n",
1641 Unknown1, Unknown2, DllName, BaseAddress);
1643 /* NULL is the current executable */
1644 if (DllName == NULL) {
1645 *BaseAddress = NtCurrentPeb()->ImageBaseAddress;
1646 DPRINT("BaseAddress %x\n", *BaseAddress);
1647 return STATUS_SUCCESS;
1649 LdrAdjustDllName(&FullDllName, DllName, TRUE);
1651 DPRINT("FullDllName %wZ\n", &FullDllName);
1653 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
1654 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1655 Entry = ModuleListHead->Flink;
1656 while (Entry != ModuleListHead) {
1657 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
1659 DPRINT("EntryPoint %x\n", Module->EntryPoint);
1660 DPRINT("Comparing %wZ and %wZ\n", &Module->BaseDllName, &FullDllName);
1662 if (!RtlCompareUnicodeString(&Module->BaseDllName, &FullDllName, TRUE)) {
1663 RtlFreeUnicodeString(&FullDllName);
1664 *BaseAddress = Module->BaseAddress;
1665 DPRINT("BaseAddress %x\n", *BaseAddress);
1666 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1667 return STATUS_SUCCESS;
1669 Entry = Entry->Flink;
1672 DPRINT("Failed to find dll %wZ\n", &FullDllName);
1674 RtlFreeUnicodeString(&FullDllName);
1675 *BaseAddress = NULL;
1676 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1677 return STATUS_DLL_NOT_FOUND;
1685 LdrGetProcedureAddress (IN PVOID BaseAddress,
1686 IN PANSI_STRING Name,
1688 OUT PVOID *ProcedureAddress)
1690 PIMAGE_EXPORT_DIRECTORY ExportDir;
1696 DPRINT("LdrGetProcedureAddress (BaseAddress %x Name %Z Ordinal %lu ProcedureAddress %x)\n",
1697 BaseAddress, Name, Ordinal, ProcedureAddress);
1699 /* Get the pointer to the export directory */
1700 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1701 RtlImageDirectoryEntryToData (BaseAddress,
1703 IMAGE_DIRECTORY_ENTRY_EXPORT,
1706 DPRINT("ExportDir %x i %lu\n", ExportDir, i);
1708 if (!ExportDir || !i || !ProcedureAddress)
1710 return STATUS_INVALID_PARAMETER;
1713 AddressPtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfFunctions);
1714 if (Name && Name->Length)
1717 OrdinalPtr = (PUSHORT)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNameOrdinals);
1718 NamePtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNames);
1719 for( i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
1721 if (!_strnicmp(Name->Buffer, (char*)(BaseAddress + *NamePtr), Name->Length))
1723 *ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[*OrdinalPtr]);
1724 return STATUS_SUCCESS;
1727 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
1732 Ordinal &= 0x0000FFFF;
1733 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
1735 *ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[Ordinal - ExportDir->Base]);
1736 return STATUS_SUCCESS;
1738 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal);
1741 return STATUS_PROCEDURE_NOT_FOUND;
1749 LdrShutdownProcess (VOID)
1751 PLIST_ENTRY ModuleListHead;
1755 DPRINT("LdrShutdownProcess() called\n");
1757 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
1759 ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
1760 Entry = ModuleListHead->Blink;
1762 while (Entry != ModuleListHead)
1764 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InInitializationOrderModuleList);
1766 DPRINT(" Unloading %wZ\n",
1767 &Module->BaseDllName);
1768 // PJS: only detach from static dlls, they should FreeLibrary() any dlls that
1769 // they loaded dynamically, and when the last reference is gone, that lib will
1771 if (Module->EntryPoint != 0 && Module->LoadCount == -1)
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("LdrShutdownProcess() done\n");
1788 return STATUS_SUCCESS;
1796 LdrShutdownThread (VOID)
1798 PLIST_ENTRY ModuleListHead;
1802 DPRINT("LdrShutdownThread() called\n");
1804 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
1806 ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
1807 Entry = ModuleListHead->Blink;
1809 while (Entry != ModuleListHead)
1811 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InInitializationOrderModuleList);
1813 DPRINT(" Unloading %wZ\n",
1814 &Module->BaseDllName);
1816 if (Module->EntryPoint != 0)
1818 PDLLMAIN_FUNC Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
1820 DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
1821 Entrypoint (Module->BaseAddress,
1826 Entry = Entry->Blink;
1829 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1831 DPRINT("LdrShutdownThread() done\n");
1833 return STATUS_SUCCESS;
1837 /***************************************************************************
1839 * LdrQueryProcessModuleInformation
1854 LdrQueryProcessModuleInformation(IN PMODULE_INFORMATION ModuleInformation OPTIONAL,
1855 IN ULONG Size OPTIONAL,
1856 OUT PULONG ReturnedSize)
1858 PLIST_ENTRY ModuleListHead;
1861 PMODULE_ENTRY ModulePtr = NULL;
1862 NTSTATUS Status = STATUS_SUCCESS;
1863 ULONG UsedSize = sizeof(ULONG);
1864 ANSI_STRING AnsiString;
1867 DPRINT("LdrQueryProcessModuleInformation() called\n");
1869 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
1871 if (ModuleInformation == NULL || Size == 0)
1873 Status = STATUS_INFO_LENGTH_MISMATCH;
1877 ModuleInformation->ModuleCount = 0;
1878 ModulePtr = &ModuleInformation->ModuleEntry[0];
1879 Status = STATUS_SUCCESS;
1882 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1883 Entry = ModuleListHead->Flink;
1885 while (Entry != ModuleListHead)
1887 Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList);
1889 DPRINT(" Module %wZ\n",
1890 &Module->FullDllName);
1892 if (UsedSize > Size)
1894 Status = STATUS_INFO_LENGTH_MISMATCH;
1896 else if (ModuleInformation != NULL)
1898 ModulePtr->Unknown0 = 0; // FIXME: ??
1899 ModulePtr->Unknown1 = 0; // FIXME: ??
1900 ModulePtr->BaseAddress = Module->BaseAddress;
1901 ModulePtr->SizeOfImage = Module->SizeOfImage;
1902 ModulePtr->Flags = Module->Flags;
1903 ModulePtr->Unknown2 = 0; // FIXME: load order index ??
1904 ModulePtr->Unknown3 = 0; // FIXME: ??
1905 ModulePtr->LoadCount = Module->LoadCount;
1907 AnsiString.Length = 0;
1908 AnsiString.MaximumLength = 256;
1909 AnsiString.Buffer = ModulePtr->ModuleName;
1910 RtlUnicodeStringToAnsiString(&AnsiString,
1911 &Module->FullDllName,
1913 p = strrchr(ModulePtr->ModuleName, '\\');
1915 ModulePtr->PathLength = p - ModulePtr->ModuleName + 1;
1917 ModulePtr->PathLength = 0;
1920 ModuleInformation->ModuleCount++;
1922 UsedSize += sizeof(MODULE_ENTRY);
1924 Entry = Entry->Flink;
1927 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
1929 if (ReturnedSize != 0)
1930 *ReturnedSize = UsedSize;
1932 DPRINT("LdrQueryProcessModuleInformation() done\n");
1939 LdrpCheckImageChecksum (IN PVOID BaseAddress,
1942 PIMAGE_NT_HEADERS Header;
1949 Header = RtlImageNtHeader (BaseAddress);
1953 HeaderSum = Header->OptionalHeader.CheckSum;
1958 Ptr = (PUSHORT) BaseAddress;
1959 for (i = 0; i < ImageSize / sizeof (USHORT); i++)
1962 if (HIWORD(Sum) != 0)
1964 Sum = LOWORD(Sum) + HIWORD(Sum);
1971 Sum += (ULONG)*((PUCHAR)Ptr);
1972 if (HIWORD(Sum) != 0)
1974 Sum = LOWORD(Sum) + HIWORD(Sum);
1978 CalcSum = (USHORT)(LOWORD(Sum) + HIWORD(Sum));
1980 /* Subtract image checksum from calculated checksum. */
1981 /* fix low word of checksum */
1982 if (LOWORD(CalcSum) >= LOWORD(HeaderSum))
1984 CalcSum -= LOWORD(HeaderSum);
1988 CalcSum = ((LOWORD(CalcSum) - LOWORD(HeaderSum)) & 0xFFFF) - 1;
1991 /* fix high word of checksum */
1992 if (LOWORD(CalcSum) >= HIWORD(HeaderSum))
1994 CalcSum -= HIWORD(HeaderSum);
1998 CalcSum = ((LOWORD(CalcSum) - HIWORD(HeaderSum)) & 0xFFFF) - 1;
2001 /* add file length */
2002 CalcSum += ImageSize;
2004 return (BOOLEAN)(CalcSum == HeaderSum);
2008 /***************************************************************************
2010 * LdrVerifyImageMatchesChecksum
2025 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle,
2030 FILE_STANDARD_INFORMATION FileInfo;
2031 IO_STATUS_BLOCK IoStatusBlock;
2032 HANDLE SectionHandle;
2038 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
2040 Status = NtCreateSection (&SectionHandle,
2041 SECTION_MAP_EXECUTE,
2047 if (!NT_SUCCESS(Status))
2049 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status);
2055 Status = NtMapViewOfSection (SectionHandle,
2056 NtCurrentProcess (),
2065 if (!NT_SUCCESS(Status))
2067 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status);
2068 NtClose (SectionHandle);
2072 Status = NtQueryInformationFile (FileHandle,
2075 sizeof (FILE_STANDARD_INFORMATION),
2076 FileStandardInformation);
2077 if (!NT_SUCCESS(Status))
2079 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status);
2080 NtUnmapViewOfSection (NtCurrentProcess (),
2082 NtClose (SectionHandle);
2086 Result = LdrpCheckImageChecksum (BaseAddress,
2087 FileInfo.EndOfFile.u.LowPart);
2088 if (Result == FALSE)
2090 Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
2093 NtUnmapViewOfSection (NtCurrentProcess (),
2096 NtClose (SectionHandle);
2102 /***************************************************************************
2104 * LdrQueryImageFileExecutionOptions
2119 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey,
2120 IN PCWSTR ValueName,
2123 IN ULONG BufferSize,
2124 OUT PULONG ReturnedLength OPTIONAL)
2126 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
2127 OBJECT_ATTRIBUTES ObjectAttributes;
2128 UNICODE_STRING ValueNameString;
2129 UNICODE_STRING ValueString;
2130 UNICODE_STRING KeyName;
2131 WCHAR NameBuffer[256];
2139 L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
2140 Ptr = wcsrchr (SubKey->Buffer, L'\\');
2143 Ptr = SubKey->Buffer;
2149 wcscat (NameBuffer, Ptr);
2150 RtlInitUnicodeString (&KeyName,
2153 InitializeObjectAttributes (&ObjectAttributes,
2155 OBJ_CASE_INSENSITIVE,
2159 Status = NtOpenKey (&KeyHandle,
2162 if (!NT_SUCCESS(Status))
2164 DPRINT1 ("NtOpenKey() failed (Status %lx)\n", Status);
2168 KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 32;
2169 KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(),
2173 RtlInitUnicodeString (&ValueNameString,
2175 Status = NtQueryValueKey (KeyHandle,
2177 KeyValuePartialInformation,
2181 if (Status == STATUS_BUFFER_OVERFLOW)
2183 KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + KeyInfo->DataLength;
2184 RtlFreeHeap (RtlGetProcessHeap(),
2187 KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(),
2190 if (KeyInfo == NULL)
2192 NtClose (KeyHandle);
2196 Status = NtQueryValueKey (KeyHandle,
2198 KeyValuePartialInformation,
2203 NtClose (KeyHandle);
2205 if (!NT_SUCCESS(Status))
2207 if (KeyInfo != NULL)
2209 RtlFreeHeap (RtlGetProcessHeap(),
2216 if (KeyInfo->Type != REG_SZ)
2218 RtlFreeHeap (RtlGetProcessHeap(),
2221 return STATUS_OBJECT_TYPE_MISMATCH;
2224 if (ValueSize == sizeof(ULONG))
2226 if (BufferSize != sizeof(ULONG))
2229 Status = STATUS_INFO_LENGTH_MISMATCH;
2233 ResultSize = sizeof(ULONG);
2234 ValueString.Length = (USHORT)KeyInfo->DataLength - sizeof(WCHAR);
2235 ValueString.MaximumLength = (USHORT)KeyInfo->DataLength;
2236 ValueString.Buffer = (PWSTR)&KeyInfo->Data;
2237 Status = RtlUnicodeStringToInteger (&ValueString,
2244 ResultSize = BufferSize;
2245 if (ResultSize < KeyInfo->DataLength)
2247 Status = STATUS_BUFFER_OVERFLOW;
2251 ResultSize = KeyInfo->DataLength;
2253 RtlCopyMemory (Buffer,
2258 RtlFreeHeap (RtlGetProcessHeap(),
2262 if (ReturnedLength != NULL)
2264 *ReturnedLength = ResultSize;