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);
88 RtlImageRvaToSection (
89 PIMAGE_NT_HEADERS NtHeader,
94 PIMAGE_SECTION_HEADER Section;
98 Count = NtHeader->FileHeader.NumberOfSections;
99 Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader +
100 NtHeader->FileHeader.SizeOfOptionalHeader);
103 Va = Section->VirtualAddress;
105 (Rva < Va + Section->SizeOfRawData))
116 PIMAGE_NT_HEADERS NtHeader,
119 PIMAGE_SECTION_HEADER *SectionHeader
122 PIMAGE_SECTION_HEADER Section = NULL;
125 Section = *SectionHeader;
127 if (Section == NULL ||
128 Rva < Section->VirtualAddress ||
129 Rva >= Section->VirtualAddress + Section->SizeOfRawData)
131 Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva);
136 *SectionHeader = Section;
139 return (ULONG)(BaseAddress +
141 Section->PointerToRawData -
142 Section->VirtualAddress);
145 #define RVA(m, b) ((ULONG)b + m)
148 LdrGetProcedureAddress (IN PVOID BaseAddress,
149 IN PANSI_STRING Name,
151 OUT PVOID *ProcedureAddress)
153 PIMAGE_EXPORT_DIRECTORY ExportDir;
159 /* get the pointer to the export directory */
160 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
161 RtlImageDirectoryEntryToData (BaseAddress, TRUE,
162 IMAGE_DIRECTORY_ENTRY_EXPORT, &i);
164 if (!ExportDir || !i || !ProcedureAddress)
166 return(STATUS_INVALID_PARAMETER);
169 AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
170 if (Name && Name->Length)
176 (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
177 NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
179 minn = 0; maxn = ExportDir->NumberOfNames;
185 mid = (minn + maxn) / 2;
186 res = _strnicmp(Name->Buffer, (PCH)RVA(BaseAddress, NamePtr[mid]),
191 (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]);
192 return(STATUS_SUCCESS);
204 for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
206 if (!_strnicmp(Name->Buffer,
207 (char*)(BaseAddress + *NamePtr), Name->Length))
210 (PVOID)((ULONG)BaseAddress +
211 (ULONG)AddressPtr[*OrdinalPtr]);
212 return STATUS_SUCCESS;
215 CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
220 Ordinal &= 0x0000FFFF;
221 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
224 (PVOID)((ULONG)BaseAddress +
225 (ULONG)AddressPtr[Ordinal - ExportDir->Base]);
226 return STATUS_SUCCESS;
228 CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n",
232 return STATUS_PROCEDURE_NOT_FOUND;