Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenloader.c
Go to the documentation of this file.
00001 /* 00002 * FreeLoader 00003 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com> 00004 * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License along 00017 * with this program; if not, write to the Free Software Foundation, Inc., 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00019 */ 00020 #define _NTSYSTEM_ 00021 #include <freeldr.h> 00022 00023 #define NDEBUG 00024 #include <debug.h> 00025 00026 #define DbgPrint printf 00027 00028 extern PVOID KernelBase; 00029 extern PVOID KernelMemory; 00030 00031 PVOID 00032 NTAPI 00033 LdrPEGetExportByName(PVOID BaseAddress, 00034 PUCHAR SymbolName, 00035 USHORT Hint); 00036 00037 /* FUNCTIONS *****************************************************************/ 00038 00039 PLOADER_MODULE 00040 NTAPI 00041 LdrGetModuleObject(PCHAR ModuleName) 00042 { 00043 ULONG i; 00044 00045 for (i = 0; i < LoaderBlock.ModsCount; i++) 00046 { 00047 if (strstr(_strupr((PCHAR)reactos_modules[i].String), _strupr(ModuleName))) 00048 { 00049 return &reactos_modules[i]; 00050 } 00051 } 00052 00053 return NULL; 00054 } 00055 00056 PVOID 00057 NTAPI 00058 LdrPEFixupForward(IN PCHAR ForwardName) 00059 { 00060 CHAR NameBuffer[128]; 00061 PCHAR p; 00062 PLOADER_MODULE ModuleObject; 00063 00064 strcpy(NameBuffer, ForwardName); 00065 p = strchr(NameBuffer, '.'); 00066 if (p == NULL) return NULL; 00067 *p = 0; 00068 00069 ModuleObject = LdrGetModuleObject(NameBuffer); 00070 if (!ModuleObject) 00071 { 00072 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer); 00073 return NULL; 00074 } 00075 00076 return LdrPEGetExportByName((PVOID)ModuleObject->ModStart, (PUCHAR)(p + 1), 0xffff); 00077 } 00078 00079 PVOID 00080 NTAPI 00081 LdrPEGetExportByName(PVOID BaseAddress, 00082 PUCHAR SymbolName, 00083 USHORT Hint) 00084 { 00085 PIMAGE_EXPORT_DIRECTORY ExportDir; 00086 PULONG * ExFunctions; 00087 PULONG * ExNames; 00088 USHORT * ExOrdinals; 00089 PVOID ExName; 00090 ULONG Ordinal; 00091 PVOID Function; 00092 LONG minn, maxn, mid, res; 00093 ULONG ExportDirSize; 00094 00095 /* HAL and NTOS use a virtual address, switch it to physical mode */ 00096 if ((ULONG_PTR)BaseAddress & 0x80000000) 00097 { 00098 BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - KSEG0_BASE + (ULONG)KernelMemory); 00099 } 00100 00101 ExportDir = (PIMAGE_EXPORT_DIRECTORY) 00102 RtlImageDirectoryEntryToData(BaseAddress, 00103 TRUE, 00104 IMAGE_DIRECTORY_ENTRY_EXPORT, 00105 &ExportDirSize); 00106 if (!ExportDir) 00107 { 00108 DbgPrint("LdrPEGetExportByName(): no export directory!\n"); 00109 return NULL; 00110 } 00111 00112 /* The symbol names may be missing entirely */ 00113 if (!ExportDir->AddressOfNames) 00114 { 00115 DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n"); 00116 return NULL; 00117 } 00118 00119 /* 00120 * Get header pointers 00121 */ 00122 ExNames = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfNames); 00123 ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals); 00124 ExFunctions = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions); 00125 00126 /* 00127 * Check the hint first 00128 */ 00129 if (Hint < ExportDir->NumberOfNames) 00130 { 00131 ExName = RVA(BaseAddress, ExNames[Hint]); 00132 if (strcmp(ExName, (PCHAR)SymbolName) == 0) 00133 { 00134 Ordinal = ExOrdinals[Hint]; 00135 Function = RVA(BaseAddress, ExFunctions[Ordinal]); 00136 if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && 00137 (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) 00138 { 00139 Function = LdrPEFixupForward((PCHAR)Function); 00140 if (Function == NULL) 00141 { 00142 DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function); 00143 } 00144 return Function; 00145 } 00146 00147 if (Function != NULL) return Function; 00148 } 00149 } 00150 00151 /* 00152 * Binary search 00153 */ 00154 minn = 0; 00155 maxn = ExportDir->NumberOfNames - 1; 00156 while (minn <= maxn) 00157 { 00158 mid = (minn + maxn) / 2; 00159 00160 ExName = RVA(BaseAddress, ExNames[mid]); 00161 res = strcmp(ExName, (PCHAR)SymbolName); 00162 if (res == 0) 00163 { 00164 Ordinal = ExOrdinals[mid]; 00165 Function = RVA(BaseAddress, ExFunctions[Ordinal]); 00166 if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && 00167 (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) 00168 { 00169 Function = LdrPEFixupForward((PCHAR)Function); 00170 if (Function == NULL) 00171 { 00172 DbgPrint("1: failed to find %s\n", Function); 00173 } 00174 return Function; 00175 } 00176 if (Function != NULL) 00177 { 00178 return Function; 00179 } 00180 } 00181 else if (res > 0) 00182 { 00183 maxn = mid - 1; 00184 } 00185 else 00186 { 00187 minn = mid + 1; 00188 } 00189 } 00190 00191 /* Fall back on unsorted */ 00192 minn = 0; 00193 maxn = ExportDir->NumberOfNames - 1; 00194 while (minn <= maxn) 00195 { 00196 ExName = RVA(BaseAddress, ExNames[minn]); 00197 res = strcmp(ExName, (PCHAR)SymbolName); 00198 if (res == 0) 00199 { 00200 Ordinal = ExOrdinals[minn]; 00201 Function = RVA(BaseAddress, ExFunctions[Ordinal]); 00202 if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && 00203 (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) 00204 { 00205 Function = LdrPEFixupForward((PCHAR)Function); 00206 if (Function == NULL) 00207 { 00208 DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName); 00209 } 00210 return Function; 00211 } 00212 if (Function != NULL) 00213 { 00214 return Function; 00215 } 00216 DbgPrint("Failed to get function %s\n", SymbolName); 00217 } 00218 minn++; 00219 } 00220 00221 DbgPrint("2: failed to find %s\n",SymbolName); 00222 return (PVOID)NULL; 00223 } 00224 00225 NTSTATUS 00226 NTAPI 00227 LdrPEProcessImportDirectoryEntry(PVOID DriverBase, 00228 PLOADER_MODULE LoaderModule, 00229 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory) 00230 { 00231 PVOID* ImportAddressList; 00232 PULONG FunctionNameList; 00233 00234 if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0) 00235 { 00236 return STATUS_UNSUCCESSFUL; 00237 } 00238 00239 /* Get the import address list. */ 00240 ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk); 00241 00242 /* Get the list of functions to import. */ 00243 if (ImportModuleDirectory->OriginalFirstThunk != 0) 00244 { 00245 FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk); 00246 } 00247 else 00248 { 00249 FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk); 00250 } 00251 00252 /* Walk through function list and fixup addresses. */ 00253 while (*FunctionNameList != 0L) 00254 { 00255 if ((*FunctionNameList) & 0x80000000) 00256 { 00257 DbgPrint("Failed to import ordinal from %s\n", LoaderModule->String); 00258 return STATUS_UNSUCCESSFUL; 00259 } 00260 else 00261 { 00262 IMAGE_IMPORT_BY_NAME *pe_name; 00263 pe_name = RVA(DriverBase, *FunctionNameList); 00264 *ImportAddressList = LdrPEGetExportByName((PVOID)LoaderModule->ModStart, pe_name->Name, pe_name->Hint); 00265 00266 /* Fixup the address to be virtual */ 00267 *ImportAddressList = (PVOID)(ULONG_PTR)*ImportAddressList + (ULONG_PTR)KernelBase - (ULONG_PTR)KernelMemory; 00268 00269 00270 //DbgPrint("Looked for: %s and found: %x\n", pe_name->Name, *ImportAddressList); 00271 if ((*ImportAddressList) == NULL) 00272 { 00273 DbgPrint("Failed to import %s from %s\n", pe_name->Name, LoaderModule->String); 00274 return STATUS_UNSUCCESSFUL; 00275 } 00276 } 00277 ImportAddressList++; 00278 FunctionNameList++; 00279 } 00280 return STATUS_SUCCESS; 00281 } 00282 00283 extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos); 00284 00285 NTSTATUS 00286 NTAPI 00287 LdrPEGetOrLoadModule(IN PCHAR ModuleName, 00288 IN PCHAR ImportedName, 00289 IN PLOADER_MODULE* ImportedModule) 00290 { 00291 NTSTATUS Status = STATUS_SUCCESS; 00292 00293 *ImportedModule = LdrGetModuleObject(ImportedName); 00294 if (*ImportedModule == NULL) 00295 { 00296 /* 00297 * For now, we only support import-loading the HAL. 00298 * Later, FrLdrLoadDriver should be made to share the same 00299 * code, and we'll just call it instead. 00300 */ 00301 FrLdrLoadDriver(ImportedName, 0); 00302 00303 /* Return the new module */ 00304 *ImportedModule = LdrGetModuleObject(ImportedName); 00305 if (*ImportedModule == NULL) 00306 { 00307 DbgPrint("Error loading import: %s\n", ImportedName); 00308 return STATUS_UNSUCCESSFUL; 00309 } 00310 } 00311 00312 return Status; 00313 } 00314 00315 NTSTATUS 00316 NTAPI 00317 LdrPEFixupImports(IN PVOID DllBase, 00318 IN PCHAR DllName) 00319 { 00320 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory; 00321 PCHAR ImportedName; 00322 NTSTATUS Status; 00323 PLOADER_MODULE ImportedModule; 00324 ULONG Size; 00325 00326 /* Process each import module */ 00327 ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR) 00328 RtlImageDirectoryEntryToData(DllBase, 00329 TRUE, 00330 IMAGE_DIRECTORY_ENTRY_IMPORT, 00331 &Size); 00332 while (ImportModuleDirectory && ImportModuleDirectory->Name) 00333 { 00334 /* Check to make sure that import lib is kernel */ 00335 ImportedName = (PCHAR) DllBase + ImportModuleDirectory->Name; 00336 //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName); 00337 00338 Status = LdrPEGetOrLoadModule(DllName, ImportedName, &ImportedModule); 00339 if (!NT_SUCCESS(Status)) return Status; 00340 00341 Status = LdrPEProcessImportDirectoryEntry(DllBase, ImportedModule, ImportModuleDirectory); 00342 if (!NT_SUCCESS(Status)) return Status; 00343 00344 //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName); 00345 ImportModuleDirectory++; 00346 } 00347 00348 return STATUS_SUCCESS; 00349 } Generated on Sat May 26 2012 04:17:51 for ReactOS by
1.7.6.1
|