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
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #define DbgPrint printf
29 extern PVOID KernelBase
;
30 extern PVOID KernelMemory
;
34 LdrPEGetExportByName(PVOID BaseAddress
,
38 /* FUNCTIONS *****************************************************************/
42 LdrGetModuleObject(PCHAR ModuleName
)
46 for (i
= 0; i
< LoaderBlock
.ModsCount
; i
++)
48 if (strstr(_strupr((PCHAR
)reactos_modules
[i
].String
), _strupr(ModuleName
)))
50 return &reactos_modules
[i
];
59 LdrPEFixupForward(IN PCHAR ForwardName
)
63 PLOADER_MODULE ModuleObject
;
65 strcpy(NameBuffer
, ForwardName
);
66 p
= strchr(NameBuffer
, '.');
67 if (p
== NULL
) return NULL
;
70 ModuleObject
= LdrGetModuleObject(NameBuffer
);
73 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
77 return LdrPEGetExportByName((PVOID
)ModuleObject
->ModStart
, (PUCHAR
)(p
+ 1), 0xffff);
82 LdrPEGetExportByName(PVOID BaseAddress
,
86 PIMAGE_EXPORT_DIRECTORY ExportDir
;
93 LONG minn
, maxn
, mid
, res
;
96 /* HAL and NTOS use a virtual address, switch it to physical mode */
97 if ((ULONG_PTR
)BaseAddress
& 0x80000000)
99 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- KSEG0_BASE
+ (ULONG
)KernelMemory
);
102 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
103 RtlImageDirectoryEntryToData(BaseAddress
,
105 IMAGE_DIRECTORY_ENTRY_EXPORT
,
109 DbgPrint("LdrPEGetExportByName(): no export directory!\n");
113 /* The symbol names may be missing entirely */
114 if (!ExportDir
->AddressOfNames
)
116 DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
121 * Get header pointers
123 ExNames
= (PULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
124 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
125 ExFunctions
= (PULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
128 * Check the hint first
130 if (Hint
< ExportDir
->NumberOfNames
)
132 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
133 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
135 Ordinal
= ExOrdinals
[Hint
];
136 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
137 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
138 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
140 Function
= LdrPEFixupForward((PCHAR
)Function
);
141 if (Function
== NULL
)
143 DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function
);
148 if (Function
!= NULL
) return Function
;
156 maxn
= ExportDir
->NumberOfNames
- 1;
159 mid
= (minn
+ maxn
) / 2;
161 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
162 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
165 Ordinal
= ExOrdinals
[mid
];
166 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
167 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
168 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
170 Function
= LdrPEFixupForward((PCHAR
)Function
);
171 if (Function
== NULL
)
173 DbgPrint("1: failed to find %s\n", Function
);
177 if (Function
!= NULL
)
192 /* Fall back on unsorted */
194 maxn
= ExportDir
->NumberOfNames
- 1;
197 ExName
= RVA(BaseAddress
, ExNames
[minn
]);
198 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
201 Ordinal
= ExOrdinals
[minn
];
202 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
203 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
204 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
206 Function
= LdrPEFixupForward((PCHAR
)Function
);
207 if (Function
== NULL
)
209 DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
213 if (Function
!= NULL
)
217 DbgPrint("Failed to get function %s\n", SymbolName
);
222 DbgPrint("2: failed to find %s\n",SymbolName
);
228 LdrPEProcessImportDirectoryEntry(PVOID DriverBase
,
229 PLOADER_MODULE LoaderModule
,
230 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
232 PVOID
* ImportAddressList
;
233 PULONG FunctionNameList
;
235 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
237 return STATUS_UNSUCCESSFUL
;
240 /* Get the import address list. */
241 ImportAddressList
= (PVOID
*)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
243 /* Get the list of functions to import. */
244 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
246 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->OriginalFirstThunk
);
250 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
253 /* Walk through function list and fixup addresses. */
254 while (*FunctionNameList
!= 0L)
256 if ((*FunctionNameList
) & 0x80000000)
258 DbgPrint("Failed to import ordinal from %s\n", LoaderModule
->String
);
259 return STATUS_UNSUCCESSFUL
;
263 IMAGE_IMPORT_BY_NAME
*pe_name
;
264 pe_name
= RVA(DriverBase
, *FunctionNameList
);
265 *ImportAddressList
= LdrPEGetExportByName((PVOID
)LoaderModule
->ModStart
, pe_name
->Name
, pe_name
->Hint
);
267 /* Fixup the address to be virtual */
268 *ImportAddressList
= (PVOID
)(ULONG_PTR
)*ImportAddressList
+ (ULONG_PTR
)KernelBase
- (ULONG_PTR
)KernelMemory
;
271 //DbgPrint("Looked for: %s and found: %x\n", pe_name->Name, *ImportAddressList);
272 if ((*ImportAddressList
) == NULL
)
274 DbgPrint("Failed to import %s from %s\n", pe_name
->Name
, LoaderModule
->String
);
275 return STATUS_UNSUCCESSFUL
;
281 return STATUS_SUCCESS
;
284 extern BOOLEAN
FrLdrLoadDriver(PCHAR szFileName
, INT nPos
);
288 LdrPEGetOrLoadModule(IN PCHAR ModuleName
,
289 IN PCHAR ImportedName
,
290 IN PLOADER_MODULE
* ImportedModule
)
292 NTSTATUS Status
= STATUS_SUCCESS
;
294 *ImportedModule
= LdrGetModuleObject(ImportedName
);
295 if (*ImportedModule
== NULL
)
298 * For now, we only support import-loading the HAL.
299 * Later, FrLdrLoadDriver should be made to share the same
300 * code, and we'll just call it instead.
302 FrLdrLoadDriver(ImportedName
, 0);
304 /* Return the new module */
305 *ImportedModule
= LdrGetModuleObject(ImportedName
);
306 if (*ImportedModule
== NULL
)
308 DbgPrint("Error loading import: %s\n", ImportedName
);
309 return STATUS_UNSUCCESSFUL
;
318 LdrPEFixupImports(IN PVOID DllBase
,
321 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
324 PLOADER_MODULE ImportedModule
;
327 /* Process each import module */
328 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
329 RtlImageDirectoryEntryToData(DllBase
,
331 IMAGE_DIRECTORY_ENTRY_IMPORT
,
333 while (ImportModuleDirectory
&& ImportModuleDirectory
->Name
)
335 /* Check to make sure that import lib is kernel */
336 ImportedName
= (PCHAR
) DllBase
+ ImportModuleDirectory
->Name
;
337 //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
339 Status
= LdrPEGetOrLoadModule(DllName
, ImportedName
, &ImportedModule
);
340 if (!NT_SUCCESS(Status
)) return Status
;
342 Status
= LdrPEProcessImportDirectoryEntry(DllBase
, ImportedModule
, ImportModuleDirectory
);
343 if (!NT_SUCCESS(Status
)) return Status
;
345 //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
346 ImportModuleDirectory
++;
349 return STATUS_SUCCESS
;