@implemented and @unimplemented comments for ntoskrnl/ldr/*.c
[reactos.git] / reactos / ntoskrnl / ldr / rtl.c
1 /* $Id: rtl.c,v 1.16 2003/07/10 20:34:50 royce Exp $
2 *
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)
9 */
10
11 /* INCLUDES *****************************************************************/
12
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>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* FUNCTIONS ****************************************************************/
24
25
26 /*
27 * @implemented
28 */
29 PIMAGE_NT_HEADERS STDCALL
30 RtlImageNtHeader (IN PVOID BaseAddress)
31 {
32 PIMAGE_DOS_HEADER DosHeader;
33 PIMAGE_NT_HEADERS NTHeaders;
34
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))
40 {
41 return(NULL);
42 }
43 return(NTHeaders);
44 }
45
46
47 /*
48 * @implemented
49 */
50 PVOID STDCALL
51 RtlImageDirectoryEntryToData (IN PVOID BaseAddress,
52 IN BOOLEAN ImageLoaded,
53 IN ULONG Directory,
54 OUT PULONG Size)
55 {
56 PIMAGE_NT_HEADERS NtHeader;
57 PIMAGE_SECTION_HEADER SectionHeader;
58 ULONG Va;
59 ULONG Count;
60
61 NtHeader = RtlImageNtHeader (BaseAddress);
62 if (NtHeader == NULL)
63 return NULL;
64
65 if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
66 return NULL;
67
68 Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
69 if (Va == 0)
70 return NULL;
71
72 if (Size)
73 *Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size;
74
75 if (ImageLoaded)
76 return (PVOID)(BaseAddress + Va);
77
78 /* image mapped as ordinary file, we must find raw pointer */
79 SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1);
80 Count = NtHeader->FileHeader.NumberOfSections;
81 while (Count--)
82 {
83 if (SectionHeader->VirtualAddress == Va)
84 return (PVOID)(BaseAddress + SectionHeader->PointerToRawData);
85 SectionHeader++;
86 }
87
88 return NULL;
89 }
90
91
92 /*
93 * @implemented
94 */
95 PIMAGE_SECTION_HEADER
96 STDCALL
97 RtlImageRvaToSection (
98 PIMAGE_NT_HEADERS NtHeader,
99 PVOID BaseAddress,
100 ULONG Rva
101 )
102 {
103 PIMAGE_SECTION_HEADER Section;
104 ULONG Va;
105 ULONG Count;
106
107 Count = NtHeader->FileHeader.NumberOfSections;
108 Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader +
109 NtHeader->FileHeader.SizeOfOptionalHeader);
110 while (Count)
111 {
112 Va = Section->VirtualAddress;
113 if ((Va <= Rva) &&
114 (Rva < Va + Section->SizeOfRawData))
115 return Section;
116 Section++;
117 }
118 return NULL;
119 }
120
121
122 /*
123 * @implemented
124 */
125 ULONG
126 STDCALL
127 RtlImageRvaToVa (
128 PIMAGE_NT_HEADERS NtHeader,
129 PVOID BaseAddress,
130 ULONG Rva,
131 PIMAGE_SECTION_HEADER *SectionHeader
132 )
133 {
134 PIMAGE_SECTION_HEADER Section = NULL;
135
136 if (SectionHeader)
137 Section = *SectionHeader;
138
139 if (Section == NULL ||
140 Rva < Section->VirtualAddress ||
141 Rva >= Section->VirtualAddress + Section->SizeOfRawData)
142 {
143 Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva);
144 if (Section == NULL)
145 return 0;
146
147 if (SectionHeader)
148 *SectionHeader = Section;
149 }
150
151 return (ULONG)(BaseAddress +
152 Rva +
153 Section->PointerToRawData -
154 Section->VirtualAddress);
155 }
156
157 #define RVA(m, b) ((ULONG)b + m)
158
159 /*
160 * @implemented
161 */
162 NTSTATUS STDCALL
163 LdrGetProcedureAddress (IN PVOID BaseAddress,
164 IN PANSI_STRING Name,
165 IN ULONG Ordinal,
166 OUT PVOID *ProcedureAddress)
167 {
168 PIMAGE_EXPORT_DIRECTORY ExportDir;
169 PUSHORT OrdinalPtr;
170 PULONG NamePtr;
171 PULONG AddressPtr;
172 ULONG i = 0;
173
174 /* get the pointer to the export directory */
175 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
176 RtlImageDirectoryEntryToData (BaseAddress, TRUE,
177 IMAGE_DIRECTORY_ENTRY_EXPORT, &i);
178
179 if (!ExportDir || !i || !ProcedureAddress)
180 {
181 return(STATUS_INVALID_PARAMETER);
182 }
183
184 AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
185 if (Name && Name->Length)
186 {
187 ULONG minn, maxn;
188
189 /* by name */
190 OrdinalPtr =
191 (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
192 NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
193
194 minn = 0; maxn = ExportDir->NumberOfNames;
195 while (minn <= maxn)
196 {
197 ULONG mid;
198 LONG res;
199
200 mid = (minn + maxn) / 2;
201 res = _strnicmp(Name->Buffer, (PCH)RVA(BaseAddress, NamePtr[mid]),
202 Name->Length);
203 if (res == 0)
204 {
205 *ProcedureAddress =
206 (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]);
207 return(STATUS_SUCCESS);
208 }
209 else if (res > 0)
210 {
211 maxn = mid - 1;
212 }
213 else
214 {
215 minn = mid + 1;
216 }
217 }
218
219 for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
220 {
221 if (!_strnicmp(Name->Buffer,
222 (char*)(BaseAddress + *NamePtr), Name->Length))
223 {
224 *ProcedureAddress =
225 (PVOID)((ULONG)BaseAddress +
226 (ULONG)AddressPtr[*OrdinalPtr]);
227 return STATUS_SUCCESS;
228 }
229 }
230 CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
231 }
232 else
233 {
234 /* by ordinal */
235 Ordinal &= 0x0000FFFF;
236 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
237 {
238 *ProcedureAddress =
239 (PVOID)((ULONG)BaseAddress +
240 (ULONG)AddressPtr[Ordinal - ExportDir->Base]);
241 return STATUS_SUCCESS;
242 }
243 CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n",
244 Ordinal);
245 }
246
247 return STATUS_PROCEDURE_NOT_FOUND;
248 }
249
250 /* EOF */