1 /* $Id: rtl.c,v 1.16 2003/07/10 20:34:50 royce Exp $
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
);
97 RtlImageRvaToSection (
98 PIMAGE_NT_HEADERS NtHeader
,
103 PIMAGE_SECTION_HEADER Section
;
107 Count
= NtHeader
->FileHeader
.NumberOfSections
;
108 Section
= (PIMAGE_SECTION_HEADER
)((ULONG
)&NtHeader
->OptionalHeader
+
109 NtHeader
->FileHeader
.SizeOfOptionalHeader
);
112 Va
= Section
->VirtualAddress
;
114 (Rva
< Va
+ Section
->SizeOfRawData
))
128 PIMAGE_NT_HEADERS NtHeader
,
131 PIMAGE_SECTION_HEADER
*SectionHeader
134 PIMAGE_SECTION_HEADER Section
= NULL
;
137 Section
= *SectionHeader
;
139 if (Section
== NULL
||
140 Rva
< Section
->VirtualAddress
||
141 Rva
>= Section
->VirtualAddress
+ Section
->SizeOfRawData
)
143 Section
= RtlImageRvaToSection (NtHeader
, BaseAddress
, Rva
);
148 *SectionHeader
= Section
;
151 return (ULONG
)(BaseAddress
+
153 Section
->PointerToRawData
-
154 Section
->VirtualAddress
);
157 #define RVA(m, b) ((ULONG)b + m)
163 LdrGetProcedureAddress (IN PVOID BaseAddress
,
164 IN PANSI_STRING Name
,
166 OUT PVOID
*ProcedureAddress
)
168 PIMAGE_EXPORT_DIRECTORY ExportDir
;
174 /* get the pointer to the export directory */
175 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
176 RtlImageDirectoryEntryToData (BaseAddress
, TRUE
,
177 IMAGE_DIRECTORY_ENTRY_EXPORT
, &i
);
179 if (!ExportDir
|| !i
|| !ProcedureAddress
)
181 return(STATUS_INVALID_PARAMETER
);
184 AddressPtr
= (PULONG
)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
185 if (Name
&& Name
->Length
)
191 (PUSHORT
)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
192 NamePtr
= (PULONG
)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
194 minn
= 0; maxn
= ExportDir
->NumberOfNames
;
200 mid
= (minn
+ maxn
) / 2;
201 res
= _strnicmp(Name
->Buffer
, (PCH
)RVA(BaseAddress
, NamePtr
[mid
]),
206 (PVOID
)RVA(BaseAddress
, AddressPtr
[OrdinalPtr
[mid
]]);
207 return(STATUS_SUCCESS
);
219 for (i
= 0; i
< ExportDir
->NumberOfNames
; i
++, NamePtr
++, OrdinalPtr
++)
221 if (!_strnicmp(Name
->Buffer
,
222 (char*)(BaseAddress
+ *NamePtr
), Name
->Length
))
225 (PVOID
)((ULONG
)BaseAddress
+
226 (ULONG
)AddressPtr
[*OrdinalPtr
]);
227 return STATUS_SUCCESS
;
230 CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
235 Ordinal
&= 0x0000FFFF;
236 if (Ordinal
- ExportDir
->Base
< ExportDir
->NumberOfFunctions
)
239 (PVOID
)((ULONG
)BaseAddress
+
240 (ULONG
)AddressPtr
[Ordinal
- ExportDir
->Base
]);
241 return STATUS_SUCCESS
;
243 CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n",
247 return STATUS_PROCEDURE_NOT_FOUND
;