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 ****************************************************************/
26 PIMAGE_NT_HEADERS STDCALL
27 RtlImageNtHeader (IN PVOID BaseAddress)
29 PIMAGE_DOS_HEADER DosHeader;
30 PIMAGE_NT_HEADERS NTHeaders;
32 DosHeader = (PIMAGE_DOS_HEADER)BaseAddress;
33 NTHeaders = (PIMAGE_NT_HEADERS)(BaseAddress + DosHeader->e_lfanew);
34 if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
35 || (DosHeader->e_lfanew == 0L)
36 || (*(PULONG) NTHeaders != IMAGE_PE_MAGIC))
45 RtlImageDirectoryEntryToData (IN PVOID BaseAddress,
46 IN BOOLEAN ImageLoaded,
50 PIMAGE_NT_HEADERS NtHeader;
51 PIMAGE_SECTION_HEADER SectionHeader;
55 NtHeader = RtlImageNtHeader (BaseAddress);
59 if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
62 Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
67 *Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size;
70 return (PVOID)(BaseAddress + Va);
72 /* image mapped as ordinary file, we must find raw pointer */
73 SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1);
74 Count = NtHeader->FileHeader.NumberOfSections;
77 if (SectionHeader->VirtualAddress == Va)
78 return (PVOID)(BaseAddress + SectionHeader->PointerToRawData);
89 RtlImageRvaToSection (
90 PIMAGE_NT_HEADERS NtHeader,
95 PIMAGE_SECTION_HEADER Section;
99 Count = NtHeader->FileHeader.NumberOfSections;
100 Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader +
101 NtHeader->FileHeader.SizeOfOptionalHeader);
104 Va = Section->VirtualAddress;
106 (Rva < Va + Section->SizeOfRawData))
117 PIMAGE_NT_HEADERS NtHeader,
120 PIMAGE_SECTION_HEADER *SectionHeader
123 PIMAGE_SECTION_HEADER Section = NULL;
126 Section = *SectionHeader;
128 if (Section == NULL ||
129 Rva < Section->VirtualAddress ||
130 Rva >= Section->VirtualAddress + Section->SizeOfRawData)
132 Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva);
137 *SectionHeader = Section;
140 return (ULONG)(BaseAddress +
142 Section->PointerToRawData -
143 Section->VirtualAddress);
146 #define RVA(m, b) ((ULONG)b + m)
149 LdrGetProcedureAddress (IN PVOID BaseAddress,
150 IN PANSI_STRING Name,
152 OUT PVOID *ProcedureAddress)
154 PIMAGE_EXPORT_DIRECTORY ExportDir;
160 /* get the pointer to the export directory */
161 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
162 RtlImageDirectoryEntryToData (BaseAddress, TRUE,
163 IMAGE_DIRECTORY_ENTRY_EXPORT, &i);
165 if (!ExportDir || !i || !ProcedureAddress)
167 return(STATUS_INVALID_PARAMETER);
170 AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
171 if (Name && Name->Length)
177 (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
178 NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
180 minn = 0; maxn = ExportDir->NumberOfNames;
186 mid = (minn + maxn) / 2;
187 res = _strnicmp(Name->Buffer, (PCH)RVA(BaseAddress, NamePtr[mid]),
192 (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]);
193 return(STATUS_SUCCESS);
205 for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
207 if (!_strnicmp(Name->Buffer,
208 (char*)(BaseAddress + *NamePtr), Name->Length))
211 (PVOID)((ULONG)BaseAddress +
212 (ULONG)AddressPtr[*OrdinalPtr]);
213 return STATUS_SUCCESS;
216 CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
221 Ordinal &= 0x0000FFFF;
222 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
225 (PVOID)((ULONG)BaseAddress +
226 (ULONG)AddressPtr[Ordinal - ExportDir->Base]);
227 return STATUS_SUCCESS;
229 CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n",
233 return STATUS_PROCEDURE_NOT_FOUND;
236 #endif /* LIBCAPTIVE */