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 extern PVOID KernelMemory
;
31 LdrPEGetExportByName(PVOID BaseAddress
,
35 /* FUNCTIONS *****************************************************************/
39 LdrGetModuleObject(PCHAR ModuleName
)
43 for (i
= 0; i
< LoaderBlock
.ModsCount
; i
++)
45 if (strstr(_strupr((PCHAR
)reactos_modules
[i
].String
), _strupr(ModuleName
)))
47 return &reactos_modules
[i
];
56 LdrPEFixupForward(IN PCHAR ForwardName
)
60 PLOADER_MODULE ModuleObject
;
62 strcpy(NameBuffer
, ForwardName
);
63 p
= strchr(NameBuffer
, '.');
64 if (p
== NULL
) return NULL
;
67 ModuleObject
= LdrGetModuleObject(NameBuffer
);
70 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
74 return LdrPEGetExportByName((PVOID
)ModuleObject
->ModStart
, (PUCHAR
)(p
+ 1), 0xffff);
79 LdrPEGetExportByName(PVOID BaseAddress
,
83 PIMAGE_EXPORT_DIRECTORY ExportDir
;
90 LONG minn
, maxn
, mid
, res
;
93 /* HAL and NTOS use a virtual address, switch it to physical mode */
94 if ((ULONG_PTR
)BaseAddress
& 0x80000000)
96 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- KSEG0_BASE
+ (ULONG
)KernelMemory
);
99 DbgPrint("Exports: RtlImageDirectoryEntryToData\n");
100 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
101 RtlImageDirectoryEntryToData(BaseAddress
,
103 IMAGE_DIRECTORY_ENTRY_EXPORT
,
105 DbgPrint("RtlImageDirectoryEntryToData done\n");
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 DbgPrint("Forward: %s\n", (PCHAR
)Function
);
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
+ (KSEG0_BASE
- (ULONG_PTR
)KernelMemory
));
270 //DbgPrint("Looked for: %s and found: %p\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 printf("Fixing up %x (%s)\n", DllBase
, DllName
);
328 /* Process each import module */
329 DbgPrint("FixupImports: RtlImageDirectoryEntryToData\n");
330 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
331 RtlImageDirectoryEntryToData(DllBase
,
333 IMAGE_DIRECTORY_ENTRY_IMPORT
,
335 DbgPrint("RtlImageDirectoryEntryToData done\n");
336 while (ImportModuleDirectory
&& ImportModuleDirectory
->Name
)
338 /* Check to make sure that import lib is kernel */
339 ImportedName
= (PCHAR
) DllBase
+ ImportModuleDirectory
->Name
;
340 //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
342 Status
= LdrPEGetOrLoadModule(DllName
, ImportedName
, &ImportedModule
);
343 if (!NT_SUCCESS(Status
)) return Status
;
345 Status
= LdrPEProcessImportDirectoryEntry(DllBase
, ImportedModule
, ImportModuleDirectory
);
346 if (!NT_SUCCESS(Status
)) return Status
;
348 //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
349 ImportModuleDirectory
++;
352 return STATUS_SUCCESS
;