3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #define DbgPrint printf
27 extern PVOID KernelBase
;
28 extern PVOID KernelMemory
;
32 LdrPEGetExportByName(PVOID BaseAddress
,
36 /* FUNCTIONS *****************************************************************/
40 LdrGetModuleObject(PCHAR ModuleName
)
44 for (i
= 0; i
< LoaderBlock
.ModsCount
; i
++)
46 if (strstr(_strupr((PCHAR
)reactos_modules
[i
].String
), _strupr(ModuleName
)))
48 return &reactos_modules
[i
];
57 LdrPEFixupForward(IN PCHAR ForwardName
)
61 PLOADER_MODULE ModuleObject
;
63 strcpy(NameBuffer
, ForwardName
);
64 p
= strchr(NameBuffer
, '.');
65 if (p
== NULL
) return NULL
;
68 ModuleObject
= LdrGetModuleObject(NameBuffer
);
71 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
75 return LdrPEGetExportByName((PVOID
)ModuleObject
->ModStart
, (PUCHAR
)(p
+ 1), 0xffff);
80 LdrPEGetExportByName(PVOID BaseAddress
,
84 PIMAGE_EXPORT_DIRECTORY ExportDir
;
91 LONG minn
, maxn
, mid
, res
;
94 /* HAL and NTOS use a virtual address, switch it to physical mode */
95 if ((ULONG_PTR
)BaseAddress
& 0x80000000)
97 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- KSEG0_BASE
+ (ULONG
)KernelMemory
);
100 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
101 RtlImageDirectoryEntryToData(BaseAddress
,
103 IMAGE_DIRECTORY_ENTRY_EXPORT
,
107 DbgPrint("LdrPEGetExportByName(): no export directory!\n");
111 /* The symbol names may be missing entirely */
112 if (!ExportDir
->AddressOfNames
)
114 DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
119 * Get header pointers
121 ExNames
= (PULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
122 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
123 ExFunctions
= (PULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
126 * Check the hint first
128 if (Hint
< ExportDir
->NumberOfNames
)
130 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
131 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
133 Ordinal
= ExOrdinals
[Hint
];
134 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
135 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
136 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
138 Function
= LdrPEFixupForward((PCHAR
)Function
);
139 if (Function
== NULL
)
141 DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function
);
146 if (Function
!= NULL
) return Function
;
154 maxn
= ExportDir
->NumberOfNames
- 1;
157 mid
= (minn
+ maxn
) / 2;
159 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
160 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
163 Ordinal
= ExOrdinals
[mid
];
164 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
165 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
166 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
168 Function
= LdrPEFixupForward((PCHAR
)Function
);
169 if (Function
== NULL
)
171 DbgPrint("1: failed to find %s\n", Function
);
175 if (Function
!= NULL
)
190 /* Fall back on unsorted */
192 maxn
= ExportDir
->NumberOfNames
- 1;
195 ExName
= RVA(BaseAddress
, ExNames
[minn
]);
196 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
199 Ordinal
= ExOrdinals
[minn
];
200 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
201 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
202 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
204 Function
= LdrPEFixupForward((PCHAR
)Function
);
205 if (Function
== NULL
)
207 DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
211 if (Function
!= NULL
)
215 DbgPrint("Failed to get function %s\n", SymbolName
);
220 DbgPrint("2: failed to find %s\n",SymbolName
);
226 LdrPEProcessImportDirectoryEntry(PVOID DriverBase
,
227 PLOADER_MODULE LoaderModule
,
228 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
230 PVOID
* ImportAddressList
;
231 PULONG FunctionNameList
;
233 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
235 return STATUS_UNSUCCESSFUL
;
238 /* Get the import address list. */
239 ImportAddressList
= (PVOID
*)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
241 /* Get the list of functions to import. */
242 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
244 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->OriginalFirstThunk
);
248 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
251 /* Walk through function list and fixup addresses. */
252 while (*FunctionNameList
!= 0L)
254 if ((*FunctionNameList
) & 0x80000000)
256 DbgPrint("Failed to import ordinal from %s\n", LoaderModule
->String
);
257 return STATUS_UNSUCCESSFUL
;
261 IMAGE_IMPORT_BY_NAME
*pe_name
;
262 pe_name
= RVA(DriverBase
, *FunctionNameList
);
263 *ImportAddressList
= LdrPEGetExportByName((PVOID
)LoaderModule
->ModStart
, pe_name
->Name
, pe_name
->Hint
);
265 /* Fixup the address to be virtual */
266 *ImportAddressList
= (PVOID
)(ULONG_PTR
)*ImportAddressList
+ (ULONG_PTR
)KernelBase
- (ULONG_PTR
)KernelMemory
;
269 //DbgPrint("Looked for: %s and found: %x\n", pe_name->Name, *ImportAddressList);
270 if ((*ImportAddressList
) == NULL
)
272 DbgPrint("Failed to import %s from %s\n", pe_name
->Name
, LoaderModule
->String
);
273 return STATUS_UNSUCCESSFUL
;
279 return STATUS_SUCCESS
;
282 extern BOOLEAN
FrLdrLoadDriver(PCHAR szFileName
, INT nPos
);
286 LdrPEGetOrLoadModule(IN PCHAR ModuleName
,
287 IN PCHAR ImportedName
,
288 IN PLOADER_MODULE
* ImportedModule
)
290 NTSTATUS Status
= STATUS_SUCCESS
;
292 *ImportedModule
= LdrGetModuleObject(ImportedName
);
293 if (*ImportedModule
== NULL
)
296 * For now, we only support import-loading the HAL.
297 * Later, FrLdrLoadDriver should be made to share the same
298 * code, and we'll just call it instead.
300 FrLdrLoadDriver(ImportedName
, 0);
302 /* Return the new module */
303 *ImportedModule
= LdrGetModuleObject(ImportedName
);
304 if (*ImportedModule
== NULL
)
306 DbgPrint("Error loading import: %s\n", ImportedName
);
307 return STATUS_UNSUCCESSFUL
;
316 LdrPEFixupImports(IN PVOID DllBase
,
319 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
322 PLOADER_MODULE ImportedModule
;
325 /* Process each import module */
326 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
327 RtlImageDirectoryEntryToData(DllBase
,
329 IMAGE_DIRECTORY_ENTRY_IMPORT
,
331 while (ImportModuleDirectory
&& ImportModuleDirectory
->Name
)
333 /* Check to make sure that import lib is kernel */
334 ImportedName
= (PCHAR
) DllBase
+ ImportModuleDirectory
->Name
;
335 //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
337 Status
= LdrPEGetOrLoadModule(DllName
, ImportedName
, &ImportedModule
);
338 if (!NT_SUCCESS(Status
)) return Status
;
340 Status
= LdrPEProcessImportDirectoryEntry(DllBase
, ImportedModule
, ImportModuleDirectory
);
341 if (!NT_SUCCESS(Status
)) return Status
;
343 //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
344 ImportModuleDirectory
++;
347 return STATUS_SUCCESS
;