1 /* $Id: rtl.c,v 1.17 2003/07/11 01:23:15 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
);
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
;