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.
26 #define DbgPrint printf
28 extern PVOID KernelBase
;
29 extern PVOID KernelMemory
;
33 LdrPEGetExportByName(PVOID BaseAddress
,
37 /* FUNCTIONS *****************************************************************/
41 LdrGetModuleObject(PCHAR ModuleName
)
45 for (i
= 0; i
< LoaderBlock
.ModsCount
; i
++)
47 if (strstr(_strupr((PCHAR
)reactos_modules
[i
].String
), _strupr(ModuleName
)))
49 return &reactos_modules
[i
];
58 LdrPEFixupForward(IN PCHAR ForwardName
)
62 PLOADER_MODULE ModuleObject
;
64 strcpy(NameBuffer
, ForwardName
);
65 p
= strchr(NameBuffer
, '.');
66 if (p
== NULL
) return NULL
;
69 ModuleObject
= LdrGetModuleObject(NameBuffer
);
72 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
76 return LdrPEGetExportByName((PVOID
)ModuleObject
->ModStart
, (PUCHAR
)(p
+ 1), 0xffff);
81 LdrPEGetExportByName(PVOID BaseAddress
,
85 PIMAGE_EXPORT_DIRECTORY ExportDir
;
92 LONG minn
, maxn
, mid
, res
;
95 /* HAL and NTOS use a virtual address, switch it to physical mode */
96 if ((ULONG_PTR
)BaseAddress
& 0x80000000)
98 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- KSEG0_BASE
+ (ULONG
)KernelMemory
);
101 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
102 RtlImageDirectoryEntryToData(BaseAddress
,
104 IMAGE_DIRECTORY_ENTRY_EXPORT
,
108 DbgPrint("LdrPEGetExportByName(): no export directory!\n");
112 /* The symbol names may be missing entirely */
113 if (!ExportDir
->AddressOfNames
)
115 DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
120 * Get header pointers
122 ExNames
= (PULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
123 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
124 ExFunctions
= (PULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
127 * Check the hint first
129 if (Hint
< ExportDir
->NumberOfNames
)
131 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
132 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
134 Ordinal
= ExOrdinals
[Hint
];
135 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
136 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
137 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
139 Function
= LdrPEFixupForward((PCHAR
)Function
);
140 if (Function
== NULL
)
142 DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function
);
147 if (Function
!= NULL
) return Function
;
155 maxn
= ExportDir
->NumberOfNames
- 1;
158 mid
= (minn
+ maxn
) / 2;
160 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
161 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
164 Ordinal
= ExOrdinals
[mid
];
165 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
166 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
167 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
169 Function
= LdrPEFixupForward((PCHAR
)Function
);
170 if (Function
== NULL
)
172 DbgPrint("1: failed to find %s\n", Function
);
176 if (Function
!= NULL
)
191 /* Fall back on unsorted */
193 maxn
= ExportDir
->NumberOfNames
- 1;
196 ExName
= RVA(BaseAddress
, ExNames
[minn
]);
197 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
200 Ordinal
= ExOrdinals
[minn
];
201 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
202 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
203 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
205 Function
= LdrPEFixupForward((PCHAR
)Function
);
206 if (Function
== NULL
)
208 DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
212 if (Function
!= NULL
)
216 DbgPrint("Failed to get function %s\n", SymbolName
);
221 DbgPrint("2: failed to find %s\n",SymbolName
);
227 LdrPEProcessImportDirectoryEntry(PVOID DriverBase
,
228 PLOADER_MODULE LoaderModule
,
229 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
231 PVOID
* ImportAddressList
;
232 PULONG FunctionNameList
;
234 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
236 return STATUS_UNSUCCESSFUL
;
239 /* Get the import address list. */
240 ImportAddressList
= (PVOID
*)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
242 /* Get the list of functions to import. */
243 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
245 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->OriginalFirstThunk
);
249 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
252 /* Walk through function list and fixup addresses. */
253 while (*FunctionNameList
!= 0L)
255 if ((*FunctionNameList
) & 0x80000000)
257 DbgPrint("Failed to import ordinal from %s\n", LoaderModule
->String
);
258 return STATUS_UNSUCCESSFUL
;
262 IMAGE_IMPORT_BY_NAME
*pe_name
;
263 pe_name
= RVA(DriverBase
, *FunctionNameList
);
264 *ImportAddressList
= LdrPEGetExportByName((PVOID
)LoaderModule
->ModStart
, pe_name
->Name
, pe_name
->Hint
);
266 /* Fixup the address to be virtual */
267 *ImportAddressList
= (PVOID
)(ULONG_PTR
)*ImportAddressList
+ (ULONG_PTR
)KernelBase
- (ULONG_PTR
)KernelMemory
;
270 //DbgPrint("Looked for: %s and found: %x\n", pe_name->Name, *ImportAddressList);
271 if ((*ImportAddressList
) == NULL
)
273 DbgPrint("Failed to import %s from %s\n", pe_name
->Name
, LoaderModule
->String
);
274 return STATUS_UNSUCCESSFUL
;
280 return STATUS_SUCCESS
;
283 extern BOOLEAN
FrLdrLoadDriver(PCHAR szFileName
, INT nPos
);
287 LdrPEGetOrLoadModule(IN PCHAR ModuleName
,
288 IN PCHAR ImportedName
,
289 IN PLOADER_MODULE
* ImportedModule
)
291 NTSTATUS Status
= STATUS_SUCCESS
;
293 *ImportedModule
= LdrGetModuleObject(ImportedName
);
294 if (*ImportedModule
== NULL
)
297 * For now, we only support import-loading the HAL.
298 * Later, FrLdrLoadDriver should be made to share the same
299 * code, and we'll just call it instead.
301 FrLdrLoadDriver(ImportedName
, 0);
303 /* Return the new module */
304 *ImportedModule
= LdrGetModuleObject(ImportedName
);
305 if (*ImportedModule
== NULL
)
307 DbgPrint("Error loading import: %s\n", ImportedName
);
308 return STATUS_UNSUCCESSFUL
;
317 LdrPEFixupImports(IN PVOID DllBase
,
320 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
323 PLOADER_MODULE ImportedModule
;
326 /* Process each import module */
327 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
328 RtlImageDirectoryEntryToData(DllBase
,
330 IMAGE_DIRECTORY_ENTRY_IMPORT
,
332 while (ImportModuleDirectory
&& ImportModuleDirectory
->Name
)
334 /* Check to make sure that import lib is kernel */
335 ImportedName
= (PCHAR
) DllBase
+ ImportModuleDirectory
->Name
;
336 //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
338 Status
= LdrPEGetOrLoadModule(DllName
, ImportedName
, &ImportedModule
);
339 if (!NT_SUCCESS(Status
)) return Status
;
341 Status
= LdrPEProcessImportDirectoryEntry(DllBase
, ImportedModule
, ImportModuleDirectory
);
342 if (!NT_SUCCESS(Status
)) return Status
;
344 //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
345 ImportModuleDirectory
++;
348 return STATUS_SUCCESS
;