ReactOS  0.4.12-dev-918-g6c6e7b8
loader.c
Go to the documentation of this file.
1 /*
2  * FreeLoader
3  * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4  * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net>
5  *
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.
10  *
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.
15  *
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.
19  */
20 #define _NTSYSTEM_
21 #include <freeldr.h>
22 
23 #include <debug.h>
24 
25 #define DbgPrint printf
26 
27 extern PVOID KernelBase;
28 extern PVOID KernelMemory;
29 
30 PVOID
31 NTAPI
33  PUCHAR SymbolName,
34  USHORT Hint);
35 
36 /* FUNCTIONS *****************************************************************/
37 
38 PLOADER_MODULE
39 NTAPI
41 {
42  ULONG i;
43 
44  for (i = 0; i < LoaderBlock.ModsCount; i++)
45  {
46  if (strstr(_strupr((PCHAR)reactos_modules[i].String), _strupr(ModuleName)))
47  {
48  return &reactos_modules[i];
49  }
50  }
51 
52  return NULL;
53 }
54 
55 PVOID
56 NTAPI
58 {
59  CHAR NameBuffer[128];
60  PCHAR p;
61  PLOADER_MODULE ModuleObject;
62 
63  strcpy(NameBuffer, ForwardName);
64  p = strchr(NameBuffer, '.');
65  if (p == NULL) return NULL;
66  *p = 0;
67 
68  ModuleObject = LdrGetModuleObject(NameBuffer);
69  if (!ModuleObject)
70  {
71  DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
72  return NULL;
73  }
74 
75  return LdrPEGetExportByName((PVOID)ModuleObject->ModStart, (PUCHAR)(p + 1), 0xffff);
76 }
77 
78 PVOID
79 NTAPI
81  PUCHAR SymbolName,
82  USHORT Hint)
83 {
84  PIMAGE_EXPORT_DIRECTORY ExportDir;
85  PULONG * ExFunctions;
86  PULONG * ExNames;
87  USHORT * ExOrdinals;
88  PVOID ExName;
89  ULONG Ordinal;
91  LONG minn, maxn, mid, res;
92  ULONG ExportDirSize;
93 
94  /* HAL and NTOS use a virtual address, switch it to physical mode */
95  if ((ULONG_PTR)BaseAddress & 0x80000000)
96  {
98  }
99 
100  ExportDir = (PIMAGE_EXPORT_DIRECTORY)
102  TRUE,
104  &ExportDirSize);
105  if (!ExportDir)
106  {
107  DbgPrint("LdrPEGetExportByName(): no export directory!\n");
108  return NULL;
109  }
110 
111  /* The symbol names may be missing entirely */
112  if (!ExportDir->AddressOfNames)
113  {
114  DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
115  return NULL;
116  }
117 
118  /*
119  * Get header pointers
120  */
121  ExNames = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfNames);
122  ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
123  ExFunctions = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions);
124 
125  /*
126  * Check the hint first
127  */
128  if (Hint < ExportDir->NumberOfNames)
129  {
130  ExName = RVA(BaseAddress, ExNames[Hint]);
131  if (strcmp(ExName, (PCHAR)SymbolName) == 0)
132  {
133  Ordinal = ExOrdinals[Hint];
134  Function = RVA(BaseAddress, ExFunctions[Ordinal]);
135  if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
136  (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
137  {
139  if (Function == NULL)
140  {
141  DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function);
142  }
143  return Function;
144  }
145 
146  if (Function != NULL) return Function;
147  }
148  }
149 
150  /*
151  * Binary search
152  */
153  minn = 0;
154  maxn = ExportDir->NumberOfNames - 1;
155  while (minn <= maxn)
156  {
157  mid = (minn + maxn) / 2;
158 
159  ExName = RVA(BaseAddress, ExNames[mid]);
160  res = strcmp(ExName, (PCHAR)SymbolName);
161  if (res == 0)
162  {
163  Ordinal = ExOrdinals[mid];
164  Function = RVA(BaseAddress, ExFunctions[Ordinal]);
165  if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
166  (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
167  {
169  if (Function == NULL)
170  {
171  DbgPrint("1: failed to find %s\n", Function);
172  }
173  return Function;
174  }
175  if (Function != NULL)
176  {
177  return Function;
178  }
179  }
180  else if (res > 0)
181  {
182  maxn = mid - 1;
183  }
184  else
185  {
186  minn = mid + 1;
187  }
188  }
189 
190  /* Fall back on unsorted */
191  minn = 0;
192  maxn = ExportDir->NumberOfNames - 1;
193  while (minn <= maxn)
194  {
195  ExName = RVA(BaseAddress, ExNames[minn]);
196  res = strcmp(ExName, (PCHAR)SymbolName);
197  if (res == 0)
198  {
199  Ordinal = ExOrdinals[minn];
200  Function = RVA(BaseAddress, ExFunctions[Ordinal]);
201  if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
202  (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
203  {
205  if (Function == NULL)
206  {
207  DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName);
208  }
209  return Function;
210  }
211  if (Function != NULL)
212  {
213  return Function;
214  }
215  DbgPrint("Failed to get function %s\n", SymbolName);
216  }
217  minn++;
218  }
219 
220  DbgPrint("2: failed to find %s\n",SymbolName);
221  return (PVOID)NULL;
222 }
223 
224 NTSTATUS
225 NTAPI
227  PLOADER_MODULE LoaderModule,
228  PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
229 {
230  PVOID* ImportAddressList;
231  PULONG FunctionNameList;
232 
233  if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
234  {
235  return STATUS_UNSUCCESSFUL;
236  }
237 
238  /* Get the import address list. */
239  ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
240 
241  /* Get the list of functions to import. */
242  if (ImportModuleDirectory->OriginalFirstThunk != 0)
243  {
244  FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk);
245  }
246  else
247  {
248  FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
249  }
250 
251  /* Walk through function list and fixup addresses. */
252  while (*FunctionNameList != 0L)
253  {
254  if ((*FunctionNameList) & 0x80000000)
255  {
256  DbgPrint("Failed to import ordinal from %s\n", LoaderModule->String);
257  return STATUS_UNSUCCESSFUL;
258  }
259  else
260  {
261  IMAGE_IMPORT_BY_NAME *pe_name;
262  pe_name = RVA(DriverBase, *FunctionNameList);
263  *ImportAddressList = LdrPEGetExportByName((PVOID)LoaderModule->ModStart, pe_name->Name, pe_name->Hint);
264 
265  /* Fixup the address to be virtual */
266  *ImportAddressList = (PVOID)(ULONG_PTR)*ImportAddressList + (ULONG_PTR)KernelBase - (ULONG_PTR)KernelMemory;
267 
268 
269  //DbgPrint("Looked for: %s and found: %x\n", pe_name->Name, *ImportAddressList);
270  if ((*ImportAddressList) == NULL)
271  {
272  DbgPrint("Failed to import %s from %s\n", pe_name->Name, LoaderModule->String);
273  return STATUS_UNSUCCESSFUL;
274  }
275  }
276  ImportAddressList++;
277  FunctionNameList++;
278  }
279  return STATUS_SUCCESS;
280 }
281 
282 extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos);
283 
284 NTSTATUS
285 NTAPI
287  IN PCHAR ImportedName,
288  IN PLOADER_MODULE* ImportedModule)
289 {
291 
292  *ImportedModule = LdrGetModuleObject(ImportedName);
293  if (*ImportedModule == NULL)
294  {
295  /*
296  * For now, we only support import-loading the HAL.
297  * Later, FrLdrLoadDriver should be made to share the same
298  * code, and we'll just call it instead.
299  */
300  FrLdrLoadDriver(ImportedName, 0);
301 
302  /* Return the new module */
303  *ImportedModule = LdrGetModuleObject(ImportedName);
304  if (*ImportedModule == NULL)
305  {
306  DbgPrint("Error loading import: %s\n", ImportedName);
307  return STATUS_UNSUCCESSFUL;
308  }
309  }
310 
311  return Status;
312 }
313 
314 NTSTATUS
315 NTAPI
317  IN PCHAR DllName)
318 {
319  PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
320  PCHAR ImportedName;
322  PLOADER_MODULE ImportedModule;
323  ULONG Size;
324 
325  /* Process each import module */
326  ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
328  TRUE,
330  &Size);
331  while (ImportModuleDirectory && ImportModuleDirectory->Name)
332  {
333  /* Check to make sure that import lib is kernel */
334  ImportedName = (PCHAR) DllBase + ImportModuleDirectory->Name;
335  //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
336 
337  Status = LdrPEGetOrLoadModule(DllName, ImportedName, &ImportedModule);
338  if (!NT_SUCCESS(Status)) return Status;
339 
340  Status = LdrPEProcessImportDirectoryEntry(DllBase, ImportedModule, ImportModuleDirectory);
341  if (!NT_SUCCESS(Status)) return Status;
342 
343  //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
344  ImportModuleDirectory++;
345  }
346 
347  return STATUS_SUCCESS;
348 }
signed char * PCHAR
Definition: retypes.h:7
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
#define DbgPrint
Definition: loader.c:25
static PULONG
Definition: loader.c:62
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
struct _IMAGE_IMPORT_DESCRIPTOR * PIMAGE_IMPORT_DESCRIPTOR
static WCHAR String[]
Definition: stringtable.c:55
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1252
static PVOID
Definition: loader.c:61
BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos)
int32_t INT
Definition: typedefs.h:56
DWORD AddressOfNameOrdinals
Definition: compat.h:155
uint32_t ULONG_PTR
Definition: typedefs.h:63
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
static LPOVERLAPPED_COMPLETION_ROUTINE Function
Definition: sync.c:684
#define KSEG0_BASE
Definition: ketypes.h:273
long LONG
Definition: pedump.c:60
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static const OBJECT_ATTRIBUTES const LARGE_INTEGER ULONG
Definition: loader.c:57
#define PCHAR
Definition: match.c:90
PVOID NTAPI LdrPEFixupForward(IN PCHAR ForwardName)
Definition: loader.c:57
PLOADER_MODULE NTAPI LdrGetModuleObject(PCHAR ModuleName)
Definition: loader.c:40
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
NTSTATUS NTAPI LdrPEProcessImportDirectoryEntry(PVOID DriverBase, PLOADER_MODULE LoaderModule, PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
Definition: loader.c:226
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS NTAPI LdrPEGetOrLoadModule(IN PCHAR ModuleName, IN PCHAR ImportedName, IN PLOADER_MODULE *ImportedModule)
Definition: loader.c:286
static ULONG ULONG_PTR *static ULONG_PTR
Definition: loader.c:70
PVOID KernelBase
Definition: mboot.c:69
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
static const WCHAR L[]
Definition: oid.c:1250
#define RtlImageDirectoryEntryToData
Definition: compat.h:460
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define IMAGE_DIRECTORY_ENTRY_EXPORT
Definition: compat.h:140
Status
Definition: gdiplustypes.h:24
#define RVA(m, b)
Definition: freeldr.h:24
PVOID KernelMemory
Definition: mboot.c:33
_CRTIMP char *__cdecl _strupr(_Inout_z_ char *_String)
unsigned short USHORT
Definition: pedump.c:61
unsigned int * PULONG
Definition: retypes.h:1
struct _IMAGE_EXPORT_DIRECTORY * PIMAGE_EXPORT_DIRECTORY
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: pedump.c:260
GLuint res
Definition: glext.h:9613
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
GLfloat GLfloat p
Definition: glext.h:8902
NTSTATUS NTAPI LdrPEFixupImports(IN PVOID DllBase, IN PCHAR DllName)
Definition: loader.c:316
return STATUS_SUCCESS
Definition: btrfs.c:2725
PVOID NTAPI LdrPEGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hint)
Definition: loader.c:80