ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

loader.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.