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 *****************************************************************/
15 #include <internal/debug.h>
17 /* FUNCTIONS ****************************************************************/
23 PIMAGE_NT_HEADERS STDCALL
24 RtlImageNtHeader (IN PVOID BaseAddress
)
26 PIMAGE_DOS_HEADER DosHeader
;
27 PIMAGE_NT_HEADERS NTHeaders
;
29 DosHeader
= (PIMAGE_DOS_HEADER
)BaseAddress
;
30 NTHeaders
= (PIMAGE_NT_HEADERS
)((char*)BaseAddress
+ DosHeader
->e_lfanew
);
31 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
32 || (DosHeader
->e_lfanew
== 0L)
33 || (*(PULONG
) NTHeaders
!= IMAGE_NT_SIGNATURE
))
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
)((char*)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
)((char*)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
)((char*)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((char*)BaseAddress
, ExportDir
->AddressOfFunctions
);
170 if (Name
&& Name
->Length
)
176 (PUSHORT
)RVA((char*)BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
177 NamePtr
= (PULONG
)RVA((char*)BaseAddress
, ExportDir
->AddressOfNames
);
179 minn
= 0; maxn
= ExportDir
->NumberOfNames
;
185 mid
= (minn
+ maxn
) / 2;
186 res
= _strnicmp(Name
->Buffer
, (PCH
)RVA((char*)BaseAddress
, NamePtr
[mid
]),
191 (PVOID
)RVA((char*)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*)((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
;