finished applying @implemented and @unimplemented comments and remove the comments...
[reactos.git] / reactos / ntoskrnl / ldr / rtl.c
1 /* $Id: rtl.c,v 1.17 2003/07/11 01:23:15 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 PIMAGE_SECTION_HEADER
93 STDCALL
94 RtlImageRvaToSection (
95 PIMAGE_NT_HEADERS NtHeader,
96 PVOID BaseAddress,
97 ULONG Rva
98 )
99 {
100 PIMAGE_SECTION_HEADER Section;
101 ULONG Va;
102 ULONG Count;
103
104 Count = NtHeader->FileHeader.NumberOfSections;
105 Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader +
106 NtHeader->FileHeader.SizeOfOptionalHeader);
107 while (Count)
108 {
109 Va = Section->VirtualAddress;
110 if ((Va <= Rva) &&
111 (Rva < Va + Section->SizeOfRawData))
112 return Section;
113 Section++;
114 }
115 return NULL;
116 }
117
118
119 ULONG
120 STDCALL
121 RtlImageRvaToVa (
122 PIMAGE_NT_HEADERS NtHeader,
123 PVOID BaseAddress,
124 ULONG Rva,
125 PIMAGE_SECTION_HEADER *SectionHeader
126 )
127 {
128 PIMAGE_SECTION_HEADER Section = NULL;
129
130 if (SectionHeader)
131 Section = *SectionHeader;
132
133 if (Section == NULL ||
134 Rva < Section->VirtualAddress ||
135 Rva >= Section->VirtualAddress + Section->SizeOfRawData)
136 {
137 Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva);
138 if (Section == NULL)
139 return 0;
140
141 if (SectionHeader)
142 *SectionHeader = Section;
143 }
144
145 return (ULONG)(BaseAddress +
146 Rva +
147 Section->PointerToRawData -
148 Section->VirtualAddress);
149 }
150
151 #define RVA(m, b) ((ULONG)b + m)
152
153 NTSTATUS STDCALL
154 LdrGetProcedureAddress (IN PVOID BaseAddress,
155 IN PANSI_STRING Name,
156 IN ULONG Ordinal,
157 OUT PVOID *ProcedureAddress)
158 {
159 PIMAGE_EXPORT_DIRECTORY ExportDir;
160 PUSHORT OrdinalPtr;
161 PULONG NamePtr;
162 PULONG AddressPtr;
163 ULONG i = 0;
164
165 /* get the pointer to the export directory */
166 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
167 RtlImageDirectoryEntryToData (BaseAddress, TRUE,
168 IMAGE_DIRECTORY_ENTRY_EXPORT, &i);
169
170 if (!ExportDir || !i || !ProcedureAddress)
171 {
172 return(STATUS_INVALID_PARAMETER);
173 }
174
175 AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
176 if (Name && Name->Length)
177 {
178 ULONG minn, maxn;
179
180 /* by name */
181 OrdinalPtr =
182 (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
183 NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
184
185 minn = 0; maxn = ExportDir->NumberOfNames;
186 while (minn <= maxn)
187 {
188 ULONG mid;
189 LONG res;
190
191 mid = (minn + maxn) / 2;
192 res = _strnicmp(Name->Buffer, (PCH)RVA(BaseAddress, NamePtr[mid]),
193 Name->Length);
194 if (res == 0)
195 {
196 *ProcedureAddress =
197 (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]);
198 return(STATUS_SUCCESS);
199 }
200 else if (res > 0)
201 {
202 maxn = mid - 1;
203 }
204 else
205 {
206 minn = mid + 1;
207 }
208 }
209
210 for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
211 {
212 if (!_strnicmp(Name->Buffer,
213 (char*)(BaseAddress + *NamePtr), Name->Length))
214 {
215 *ProcedureAddress =
216 (PVOID)((ULONG)BaseAddress +
217 (ULONG)AddressPtr[*OrdinalPtr]);
218 return STATUS_SUCCESS;
219 }
220 }
221 CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
222 }
223 else
224 {
225 /* by ordinal */
226 Ordinal &= 0x0000FFFF;
227 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
228 {
229 *ProcedureAddress =
230 (PVOID)((ULONG)BaseAddress +
231 (ULONG)AddressPtr[Ordinal - ExportDir->Base]);
232 return STATUS_SUCCESS;
233 }
234 CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n",
235 Ordinal);
236 }
237
238 return STATUS_PROCEDURE_NOT_FOUND;
239 }
240
241 /* EOF */