3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ldr/loader.c
6 * PURPOSE: Loader utilities
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
11 /* INCLUDES *****************************************************************/
13 #include <ddk/ntddk.h>
14 #include <internal/module.h>
15 #include <internal/ntoskrnl.h>
16 #include <internal/ob.h>
17 #include <internal/ps.h>
18 #include <internal/ldr.h>
21 #include <internal/debug.h>
23 /* FUNCTIONS ****************************************************************/
29 PIMAGE_NT_HEADERS STDCALL
30 RtlImageNtHeader (IN PVOID BaseAddress)
32 PIMAGE_DOS_HEADER DosHeader;
33 PIMAGE_NT_HEADERS NTHeaders;
35 DosHeader = (PIMAGE_DOS_HEADER)BaseAddress;
36 NTHeaders = (PIMAGE_NT_HEADERS)(BaseAddress + DosHeader->e_lfanew);
37 if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
38 || (DosHeader->e_lfanew == 0L)
39 || (*(PULONG) NTHeaders != IMAGE_PE_MAGIC))
51 RtlImageDirectoryEntryToData (IN PVOID BaseAddress,
52 IN BOOLEAN ImageLoaded,
56 PIMAGE_NT_HEADERS NtHeader;
57 PIMAGE_SECTION_HEADER SectionHeader;
61 NtHeader = RtlImageNtHeader (BaseAddress);
65 if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
68 Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
73 *Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size;
76 return (PVOID)(BaseAddress + Va);
78 /* image mapped as ordinary file, we must find raw pointer */
79 SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1);
80 Count = NtHeader->FileHeader.NumberOfSections;
83 if (SectionHeader->VirtualAddress == Va)
84 return (PVOID)(BaseAddress + SectionHeader->PointerToRawData);
94 RtlImageRvaToSection (
95 PIMAGE_NT_HEADERS NtHeader,
100 PIMAGE_SECTION_HEADER Section;
104 Count = NtHeader->FileHeader.NumberOfSections;
105 Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader +
106 NtHeader->FileHeader.SizeOfOptionalHeader);
109 Va = Section->VirtualAddress;
111 (Rva < Va + Section->SizeOfRawData))
122 PIMAGE_NT_HEADERS NtHeader,
125 PIMAGE_SECTION_HEADER *SectionHeader
128 PIMAGE_SECTION_HEADER Section = NULL;
131 Section = *SectionHeader;
133 if (Section == NULL ||
134 Rva < Section->VirtualAddress ||
135 Rva >= Section->VirtualAddress + Section->SizeOfRawData)
137 Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva);
142 *SectionHeader = Section;
145 return (ULONG)(BaseAddress +
147 Section->PointerToRawData -
148 Section->VirtualAddress);
151 #define RVA(m, b) ((ULONG)b + m)
154 LdrGetProcedureAddress (IN PVOID BaseAddress,
155 IN PANSI_STRING Name,
157 OUT PVOID *ProcedureAddress)
159 PIMAGE_EXPORT_DIRECTORY ExportDir;
165 /* get the pointer to the export directory */
166 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
167 RtlImageDirectoryEntryToData (BaseAddress, TRUE,
168 IMAGE_DIRECTORY_ENTRY_EXPORT, &i);
170 if (!ExportDir || !i || !ProcedureAddress)
172 return(STATUS_INVALID_PARAMETER);
175 AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
176 if (Name && Name->Length)
182 (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
183 NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
185 minn = 0; maxn = ExportDir->NumberOfNames;
191 mid = (minn + maxn) / 2;
192 res = _strnicmp(Name->Buffer, (PCH)RVA(BaseAddress, NamePtr[mid]),
197 (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]);
198 return(STATUS_SUCCESS);
210 for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
212 if (!_strnicmp(Name->Buffer,
213 (char*)(BaseAddress + *NamePtr), Name->Length))
216 (PVOID)((ULONG)BaseAddress +
217 (ULONG)AddressPtr[*OrdinalPtr]);
218 return STATUS_SUCCESS;
221 CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
226 Ordinal &= 0x0000FFFF;
227 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
230 (PVOID)((ULONG)BaseAddress +
231 (ULONG)AddressPtr[Ordinal - ExportDir->Base]);
232 return STATUS_SUCCESS;
234 CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n",
238 return STATUS_PROCEDURE_NOT_FOUND;