Removed memory leaks
[reactos.git] / reactos / ntoskrnl / ldr / loader.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ldr/loader.c
5 * PURPOSE: Loaders for PE executables
6 * PROGRAMMERS: Jean Michault
7 * Rex Jolliff (rex@lvcablemodem.com)
8 * UPDATE HISTORY:
9 * DW 22/05/98 Created
10 * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
11 * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
12 * RJJ 10/12/98 Rolled in David's code to load COFF drivers
13 * JM 14/12/98 Built initail PE user module loader
14 */
15
16 /* INCLUDES *****************************************************************/
17
18 #include <internal/i386/segment.h>
19 #include <internal/kernel.h>
20 #include <internal/linkage.h>
21 #include <internal/module.h>
22 #include <internal/ob.h>
23 #include <internal/string.h>
24 #include <internal/symbol.h>
25
26 #include <ddk/ntddk.h>
27
28 #define NDEBUG
29 #include <internal/debug.h>
30
31 /* MACROS ********************************************************************/
32
33 /* GLOBALS *******************************************************************/
34
35 POBJECT_TYPE ObModuleType = NULL;
36
37 /* FORWARD DECLARATIONS ******************************************************/
38
39 NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename);
40 NTSTATUS LdrProcessDriver(PVOID ModuleLoadBase);
41
42 /* PE Driver load support */
43 static NTSTATUS LdrPEProcessDriver(PVOID ModuleLoadBase);
44 static unsigned int LdrGetKernelSymbolAddr(char *Name);
45
46 /* COFF Driver load support */
47 static NTSTATUS LdrCOFFProcessDriver(PVOID ModuleLoadBase);
48 static BOOLEAN LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex);
49 static BOOLEAN LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
50 static BOOLEAN LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
51 static void LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name);
52 static unsigned int LdrCOFFGetSymbolValue(module *Module, unsigned int Idx);
53 static unsigned int LdrCOFFGetSymbolValueByName(module *Module, char *SymbolName, unsigned int Idx);
54
55 /* Image loader forward delcarations */
56 static NTSTATUS LdrProcessMZImage(HANDLE ProcessHandle, HANDLE ModuleHandle, HANDLE FileHandle);
57 static NTSTATUS LdrProcessPEImage(HANDLE ProcessHandle, HANDLE ModuleHandle, HANDLE FileHandle);
58 static NTSTATUS LdrProcessBinImage(HANDLE ProcessHandle, HANDLE ModuleHandle, HANDLE FileHandle);
59
60 /* FUNCTIONS *****************************************************************/
61
62 VOID LdrInitModuleManagement(VOID)
63 {
64 ANSI_STRING AnsiString;
65
66 /* Register the process object type */
67 ObModuleType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
68 ObModuleType->TotalObjects = 0;
69 ObModuleType->TotalHandles = 0;
70 ObModuleType->MaxObjects = ULONG_MAX;
71 ObModuleType->MaxHandles = ULONG_MAX;
72 ObModuleType->PagedPoolCharge = 0;
73 ObModuleType->NonpagedPoolCharge = sizeof(MODULE);
74 ObModuleType->Dump = NULL;
75 ObModuleType->Open = NULL;
76 ObModuleType->Close = NULL;
77 ObModuleType->Delete = NULL;
78 ObModuleType->Parse = NULL;
79 ObModuleType->Security = NULL;
80 ObModuleType->QueryName = NULL;
81 ObModuleType->OkayToClose = NULL;
82 RtlInitAnsiString(&AnsiString, "Module");
83 RtlAnsiStringToUnicodeString(&ObModuleType->TypeName, &AnsiString, TRUE);
84 }
85
86 /*
87 * load the auto config drivers.
88 */
89 VOID LdrLoadAutoConfigDrivers(VOID)
90 {
91 NTSTATUS Status;
92 ANSI_STRING AnsiDriverName;
93 UNICODE_STRING DriverName;
94
95 RtlInitAnsiString(&AnsiDriverName,"\\??\\C:\\reactos\\system\\drivers\\keyboard.o");
96 RtlAnsiStringToUnicodeString(&DriverName, &AnsiDriverName, TRUE);
97 Status = LdrLoadDriver(&DriverName);
98 RtlFreeUnicodeString(&DriverName);
99 if (!NT_SUCCESS(Status))
100 {
101 DbgPrint("driver load failed, status;%d(%x)\n", Status, Status);
102 DbgPrintErrorMessage(Status);
103 }
104 RtlInitAnsiString(&AnsiDriverName,"\\??\\C:\\reactos\\system\\drivers\\blues.o");
105 RtlAnsiStringToUnicodeString(&DriverName, &AnsiDriverName, TRUE);
106 Status = LdrLoadDriver(&DriverName);
107 RtlFreeUnicodeString(&DriverName);
108 if (!NT_SUCCESS(Status))
109 {
110 DbgPrint("driver load failed, status;%d(%x)\n", Status, Status);
111 DbgPrintErrorMessage(Status);
112 }
113
114 }
115
116 /*
117 * FUNCTION: Loads a kernel driver
118 * ARGUMENTS:
119 * FileName = Driver to load
120 * RETURNS: Status
121 */
122
123 NTSTATUS
124 LdrLoadDriver(PUNICODE_STRING Filename)
125 {
126 PVOID ModuleLoadBase;
127 NTSTATUS Status;
128 HANDLE FileHandle;
129 OBJECT_ATTRIBUTES FileObjectAttributes;
130 FILE_STANDARD_INFORMATION FileStdInfo;
131
132 DbgPrint("Loading Driver %W...\n", Filename);
133
134 /* Open the Driver */
135 InitializeObjectAttributes(&FileObjectAttributes,
136 Filename,
137 0,
138 NULL,
139 NULL);
140 CHECKPOINT;
141 Status = ZwOpenFile(&FileHandle,
142 FILE_ALL_ACCESS,
143 &FileObjectAttributes,
144 NULL, 0, 0);
145 CHECKPOINT;
146 if (!NT_SUCCESS(Status))
147 {
148 return Status;
149 }
150 CHECKPOINT;
151
152 /* Get the size of the file */
153 Status = ZwQueryInformationFile(FileHandle,
154 NULL,
155 &FileStdInfo,
156 sizeof(FileStdInfo),
157 FileStandardInformation);
158 if (!NT_SUCCESS(Status))
159 {
160 return Status;
161 }
162 CHECKPOINT;
163
164 /* Allocate nonpageable memory for driver */
165 ModuleLoadBase = ExAllocatePool(NonPagedPool,
166 GET_LARGE_INTEGER_LOW_PART(FileStdInfo.EndOfFile));
167 if (ModuleLoadBase == NULL)
168 {
169 return STATUS_INSUFFICIENT_RESOURCES;
170 }
171 CHECKPOINT;
172
173 /* Load driver into memory chunk */
174 Status = ZwReadFile(FileHandle,
175 0, 0, 0, 0,
176 ModuleLoadBase,
177 GET_LARGE_INTEGER_LOW_PART(FileStdInfo.EndOfFile),
178 0, 0);
179 if (!NT_SUCCESS(Status))
180 {
181 ExFreePool(ModuleLoadBase);
182 return Status;
183 }
184 CHECKPOINT;
185
186 ZwClose(FileHandle);
187
188 Status = LdrProcessDriver(ModuleLoadBase);
189
190 /* Cleanup */
191 ExFreePool(ModuleLoadBase);
192
193 return STATUS_SUCCESS;
194 }
195
196 NTSTATUS
197 LdrProcessDriver(PVOID ModuleLoadBase)
198 {
199 PIMAGE_DOS_HEADER PEDosHeader;
200
201 /* If MZ header exists */
202 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
203 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
204 {
205 return LdrPEProcessDriver(ModuleLoadBase);
206 }
207 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC)
208 {
209 return STATUS_NOT_IMPLEMENTED;
210 }
211 else /* Assume COFF format and load */
212 {
213 return LdrCOFFProcessDriver(ModuleLoadBase);
214 }
215 }
216
217 NTSTATUS
218 LdrPEProcessDriver(PVOID ModuleLoadBase)
219 {
220 unsigned int DriverSize, Idx;
221 long int RelocDelta, NumRelocs;
222 DWORD CurrentSize;
223 PVOID DriverBase, CurrentBase, EntryPoint;
224 PULONG PEMagic;
225 PIMAGE_DOS_HEADER PEDosHeader;
226 PIMAGE_FILE_HEADER PEFileHeader;
227 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
228 PIMAGE_SECTION_HEADER PESectionHeaders;
229 PRELOCATION_DIRECTORY RelocDir;
230 PRELOCATION_ENTRY RelocEntry;
231 PMODULE Library;
232 PVOID *ImportAddressList;
233 PULONG FunctionNameList;
234 PCHAR pName, SymbolNameBuf;
235 PWORD pHint;
236
237 /* FIXME: this could be used to load kernel DLLs also, however */
238 /* the image headers should be preserved in such a case */
239
240 DPRINT("Processing PE Driver at module base:%08lx\n", ModuleLoadBase);
241
242 /* Get header pointers */
243 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
244 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
245 PEDosHeader->e_lfanew);
246 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
247 PEDosHeader->e_lfanew + sizeof(ULONG));
248 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
249 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
250 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
251 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
252 sizeof(IMAGE_OPTIONAL_HEADER));
253 CHECKPOINT;
254
255 /* Check file magic numbers */
256 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
257 {
258 DPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
259 return STATUS_UNSUCCESSFUL;
260 }
261 if (PEDosHeader->e_lfanew == 0)
262 {
263 DPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
264 return STATUS_UNSUCCESSFUL;
265 }
266 if (*PEMagic != IMAGE_PE_MAGIC)
267 {
268 DPRINT("Incorrect PE magic: %08x\n", *PEMagic);
269 return STATUS_UNSUCCESSFUL;
270 }
271 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
272 {
273 DPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
274 return STATUS_UNSUCCESSFUL;
275 }
276 CHECKPOINT;
277
278 /* FIXME: if image is fixed-address load, then fail */
279
280 /* FIXME: check/verify OS version number */
281
282 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
283 PEOptionalHeader->Magic,
284 PEOptionalHeader->MajorLinkerVersion,
285 PEOptionalHeader->MinorLinkerVersion);
286 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
287 CHECKPOINT;
288
289 /* Determine the size of the module */
290 DPRINT("Sections: (section align:%08lx)\n",
291 PEOptionalHeader->SectionAlignment);
292 DriverSize = PESectionHeaders[0].PointerToRawData;
293 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
294 {
295 DPRINT("Name:%-8.8s VA:%08lx RawSz:%6d Offs:%08lx CHAR:%08lx OfsA: %08lx\n",
296 PESectionHeaders[Idx].Name,
297 PESectionHeaders[Idx].VirtualAddress,
298 PESectionHeaders[Idx].SizeOfRawData,
299 PESectionHeaders[Idx].PointerToRawData,
300 PESectionHeaders[Idx].Characteristics,
301 DriverSize);
302 DriverSize += ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
303 PEOptionalHeader->SectionAlignment);
304 }
305 DPRINT("DriverSize computed by using section headers: %d(%08lx)\n",
306 DriverSize,
307 DriverSize);
308
309 /* Allocate a virtual section for the module */
310 DriverBase = MmAllocateSection(DriverSize);
311 if (DriverBase == 0)
312 {
313 DbgPrint("Failed to allocate a virtual section for driver\n");
314 return STATUS_INSUFFICIENT_RESOURCES;
315 }
316 CHECKPOINT;
317
318 /* Copy image sections into virtual section */
319 memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData);
320 CurrentBase = (PVOID) ((DWORD)DriverBase + PESectionHeaders[0].PointerToRawData);
321 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
322 {
323 /* Copy current section into current offset of virtual section */
324 if (PESectionHeaders[Idx].Characteristics &
325 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
326 {
327 memcpy(CurrentBase,
328 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
329 PESectionHeaders[Idx].SizeOfRawData);
330 }
331 else
332 {
333 memset(CurrentBase, '\0', PESectionHeaders[Idx].SizeOfRawData);
334 }
335 CurrentSize += ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
336 PEOptionalHeader->SectionAlignment);
337 CurrentBase = (PVOID)((DWORD)CurrentBase +
338 ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
339 PEOptionalHeader->SectionAlignment));
340 }
341
342 /* Perform relocation fixups */
343 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
344 RelocDir = (PRELOCATION_DIRECTORY) ((DWORD)ModuleLoadBase +
345 PEOptionalHeader->DataDirectory[
346 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
347 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
348 DriverBase,
349 PEOptionalHeader->ImageBase,
350 RelocDelta);
351 while (RelocDir->SizeOfBlock != 0)
352 {
353 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
354 sizeof(WORD);
355 DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
356 RelocDir,
357 RelocDir->VirtualAddress,
358 NumRelocs);
359 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
360 sizeof(RELOCATION_DIRECTORY));
361 for (Idx = 0; Idx < NumRelocs; Idx++)
362 {
363 DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
364 DriverBase + RelocDir->VirtualAddress +
365 (RelocEntry[Idx].TypeOffset & 0x0fff),
366 (RelocEntry[Idx].TypeOffset >> 12) & 0xf,
367 (RelocEntry[Idx].TypeOffset >> 12) & 0xf ? "HIGHLOW" : "ABS",
368 *(PDWORD)((DWORD) DriverBase + RelocDir->VirtualAddress +
369 (RelocEntry[Idx].TypeOffset & 0x0fff)),
370 (*(PDWORD)((DWORD) DriverBase + RelocDir->VirtualAddress +
371 (RelocEntry[Idx].TypeOffset & 0x0fff))) + RelocDelta);
372 if (((RelocEntry[Idx].TypeOffset >> 12) & 0xf) == 3)
373 {
374 (*(PDWORD)((DWORD) DriverBase + RelocDir->VirtualAddress +
375 (RelocEntry[Idx].TypeOffset & 0x0fff))) += RelocDelta;
376 }
377 else if (((RelocEntry[Idx].TypeOffset >> 12) & 0xf) != 0)
378 {
379 DPRINT("Unknown relocation type %x\n",
380 (RelocEntry[Idx].TypeOffset >> 12) & 0xf);
381 return STATUS_UNSUCCESSFUL;
382 }
383 }
384 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
385 RelocDir->SizeOfBlock);
386 }
387
388 /* Perform import fixups */
389 if (PEOptionalHeader->DataDirectory[
390 IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
391 {
392 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
393
394 SymbolNameBuf = ExAllocatePool(NonPagedPool, 512);
395
396 /* Process each import module */
397 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
398 ((DWORD)ModuleLoadBase + PEOptionalHeader->
399 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
400 while (ImportModuleDirectory->dwRVAModuleName)
401 {
402 /* FIXME: handle kernel mode DLLs */
403
404 /* Check to make sure that import lib is kernel */
405 Library = NULL;
406 pName = (PCHAR) ModuleLoadBase +
407 ImportModuleDirectory->dwRVAModuleName;
408 DPRINT("Import module: %s\n", pName);
409 if (strcmp(pName, "ntoskrnl.exe") &&
410 strcmp(pName, "HAL.dll"))
411 {
412 DPRINT("Kernel mode DLLs are currently unsupported\n");
413 }
414
415 /* Get the import address list */
416 ImportAddressList = (PVOID *) ((DWORD)ModuleLoadBase +
417 ImportModuleDirectory->dwRVAFunctionAddressList);
418
419 /* Get the list of functions to import */
420 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
421 {
422 FunctionNameList = (PULONG) ((DWORD)ModuleLoadBase +
423 ImportModuleDirectory->dwRVAFunctionNameList);
424 }
425 else
426 {
427 FunctionNameList = (PULONG) ((DWORD)ModuleLoadBase +
428 ImportModuleDirectory->dwRVAFunctionAddressList);
429 }
430
431 /* Walk through function list and fixup addresses */
432 while(*FunctionNameList != 0L)
433 {
434 if ((*FunctionNameList) & 0x80000000) // hint
435 {
436 DPRINT(" Hint: %08lx\n", *FunctionNameList);
437 if (Library == NULL)
438 {
439 DPRINT("Hints for kernel symbols are not handled.\n");
440 *ImportAddressList = 0;
441 }
442 }
443 else // hint-name
444 {
445 pName = (PCHAR)((DWORD)ModuleLoadBase +
446 *FunctionNameList + 2);
447 pHint = (PWORD)((DWORD)ModuleLoadBase + *FunctionNameList);
448 DPRINT(" Hint:%04x Name:%s\n", pHint, pName);
449
450 /* Get address for symbol */
451 if (Library == NULL)
452 {
453 *SymbolNameBuf = '_';
454 strcpy(SymbolNameBuf + 1, pName);
455 *ImportAddressList = (PVOID) LdrGetKernelSymbolAddr(SymbolNameBuf); if (*ImportAddressList == 0L)
456 {
457 DPRINT("Unresolved kernel symbol: %s\n", pName);
458 }
459 }
460 }
461 ImportAddressList++;
462 FunctionNameList++;
463 }
464 ImportModuleDirectory++;
465 }
466
467 ExFreePool(SymbolNameBuf);
468 }
469
470 /* Compute address of entry point */
471 EntryPoint = (PVOID) ((DWORD)DriverBase + PEOptionalHeader->AddressOfEntryPoint);
472
473 return InitializeLoadedDriver(EntryPoint);
474 }
475
476 NTSTATUS
477 LdrCOFFProcessDriver(PVOID ModuleLoadBase)
478 {
479 BOOLEAN FoundEntry;
480 char SymbolName[255];
481 int i;
482 ULONG EntryOffset;
483 FILHDR *FileHeader;
484 AOUTHDR *AOUTHeader;
485 module *Module;
486 PDRIVER_INITIALIZE EntryRoutine;
487
488 /* Get header pointers */
489 FileHeader = ModuleLoadBase;
490 AOUTHeader = ModuleLoadBase + FILHSZ;
491 CHECKPOINT;
492
493 /* Check COFF magic value */
494 if (I386BADMAG(*FileHeader))
495 {
496 DbgPrint("Module has bad magic value (%x)\n",
497 FileHeader->f_magic);
498 return STATUS_UNSUCCESSFUL;
499 }
500 CHECKPOINT;
501
502 /* Allocate and initialize a module definition structure */
503 Module = (module *) ExAllocatePool(NonPagedPool, sizeof(module));
504 if (Module == NULL)
505 {
506 return STATUS_INSUFFICIENT_RESOURCES;
507 }
508 Module->sym_list = (SYMENT *)(ModuleLoadBase + FileHeader->f_symptr);
509 Module->str_tab = (char *)(ModuleLoadBase + FileHeader->f_symptr +
510 FileHeader->f_nsyms * SYMESZ);
511 Module->scn_list = (SCNHDR *)(ModuleLoadBase + FILHSZ +
512 FileHeader->f_opthdr);
513 Module->size = 0;
514 Module->raw_data_off = (ULONG) ModuleLoadBase;
515 Module->nsyms = FileHeader->f_nsyms;
516 CHECKPOINT;
517
518 /* Determine the length of the module */
519 for (i = 0; i < FileHeader->f_nscns; i++)
520 {
521 DPRINT("Section name: %.8s\n", Module->scn_list[i].s_name);
522 DPRINT("size %x vaddr %x size %x\n",
523 Module->size,
524 Module->scn_list[i].s_vaddr,
525 Module->scn_list[i].s_size);
526 if (Module->scn_list[i].s_flags & STYP_TEXT)
527 {
528 Module->text_base = Module->scn_list[i].s_vaddr;
529 }
530 if (Module->scn_list[i].s_flags & STYP_DATA)
531 {
532 Module->data_base = Module->scn_list[i].s_vaddr;
533 }
534 if (Module->scn_list[i].s_flags & STYP_BSS)
535 {
536 Module->bss_base = Module->scn_list[i].s_vaddr;
537 }
538 if (Module->size <
539 (Module->scn_list[i].s_vaddr + Module->scn_list[i].s_size))
540 {
541 Module->size = Module->size + Module->scn_list[i].s_vaddr +
542 Module->scn_list[i].s_size;
543 }
544 }
545 CHECKPOINT;
546
547 /* Allocate a section for the module */
548 Module->base = (unsigned int) MmAllocateSection(Module->size);
549 if (Module->base == 0)
550 {
551 DbgPrint("Failed to alloc section for module\n");
552 ExFreePool(Module);
553 return STATUS_INSUFFICIENT_RESOURCES;
554 }
555 CHECKPOINT;
556
557 /* Adjust section vaddrs for allocated area */
558 Module->data_base = Module->data_base + Module->base;
559 Module->text_base = Module->text_base + Module->base;
560 Module->bss_base = Module->bss_base + Module->base;
561
562 /* Relocate module and fixup imports */
563 for (i = 0; i < FileHeader->f_nscns; i++)
564 {
565 if (Module->scn_list[i].s_flags & STYP_TEXT ||
566 Module->scn_list[i].s_flags & STYP_DATA)
567 {
568 memcpy((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
569 (PVOID)(ModuleLoadBase + Module->scn_list[i].s_scnptr),
570 Module->scn_list[i].s_size);
571 if (!LdrCOFFDoRelocations(Module, i))
572 {
573 DPRINT("Relocation failed for section %s\n",
574 Module->scn_list[i].s_name);
575
576 /* FIXME: unallocate all sections here */
577
578 ExFreePool(Module);
579
580 return STATUS_UNSUCCESSFUL;
581 }
582 }
583 if (Module->scn_list[i].s_flags & STYP_BSS)
584 {
585 memset((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
586 0,
587 Module->scn_list[i].s_size);
588 }
589 }
590
591 DbgPrint("Module base: %x\n", Module->base);
592
593 /* Find the entry point */
594 EntryOffset = 0L;
595 FoundEntry = FALSE;
596 for (i = 0; i < FileHeader->f_nsyms; i++)
597 {
598 LdrCOFFGetSymbolName(Module, i, SymbolName);
599 if (!strcmp(SymbolName, "_DriverEntry"))
600 {
601 EntryOffset = Module->sym_list[i].e_value;
602 FoundEntry = TRUE;
603 DPRINT("Found entry at %x\n", EntryOffset);
604 }
605 }
606 if (!FoundEntry)
607 {
608 DbgPrint("No module entry point defined\n");
609 ExFreePool(Module);
610
611 /* FIXME: unallocate all sections here */
612
613 return STATUS_UNSUCCESSFUL;
614 }
615
616 /* Get the address of the module initalization routine */
617 EntryRoutine = (PDRIVER_INITIALIZE)(Module->base + EntryOffset);
618
619 /* Cleanup */
620 ExFreePool(Module);
621
622 return InitializeLoadedDriver(EntryRoutine);
623 }
624
625 /* LdrCOFFDoRelocations
626 * FUNCTION: Do the relocations for a module section
627 * ARGUMENTS:
628 * Module = Pointer to the module
629 * SectionIndex = Index of the section to be relocated
630 * RETURNS: Success or failure
631 */
632
633 static BOOLEAN
634 LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex)
635 {
636 SCNHDR *Section = &Module->scn_list[SectionIndex];
637 RELOC *Relocation = (RELOC *)(Module->raw_data_off + Section->s_relptr);
638 int j;
639
640 DPRINT("SectionIndex %d Name %.8s Relocs %d\n",
641 SectionIndex,
642 Module->scn_list[SectionIndex].s_name,
643 Section->s_nreloc);
644
645 for (j = 0; j < Section->s_nreloc; j++)
646 {
647 DPRINT("vaddr %x symndex %x",
648 Relocation->r_vaddr,
649 Relocation->r_symndx);
650
651 switch (Relocation->r_type)
652 {
653 case RELOC_ADDR32:
654 if (!LdrCOFFDoAddr32Reloc(Module, Section, Relocation))
655 {
656 return FALSE;
657 }
658 break;
659
660 case RELOC_REL32:
661 if (!LdrCOFFDoReloc32Reloc(Module, Section, Relocation))
662 {
663 return FALSE;
664 }
665 break;
666
667 default:
668 DPRINT("%.8s: Unknown relocation type %x at %d in module\n",
669 Module->scn_list[SectionIndex].s_name,
670 Relocation->r_type,
671 j);
672 return FALSE;
673 }
674 Relocation++;
675 }
676 DPRINT("%.8s: relocations done\n", Module->scn_list[SectionIndex].s_name);
677
678 return TRUE;
679 }
680
681 /*
682 * FUNCTION: Performs a addr32 relocation on a loaded module
683 * ARGUMENTS:
684 * mod = module to perform the relocation on
685 * scn = Section to perform the relocation in
686 * reloc = Pointer to a data structure describing the relocation
687 * RETURNS: Success or failure
688 * NOTE: This fixes up a relocation needed when changing the base address of a
689 * module
690 */
691
692 static BOOLEAN
693 LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
694 {
695 unsigned int Value;
696 unsigned int *Location;
697
698 Value = LdrCOFFGetSymbolValue(Module, Relocation->r_symndx);
699 Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
700 DPRINT("ADDR32 loc %x value %x *loc %x\n", Location, Value, *Location);
701 *Location = (*Location) + Module->base;
702
703 return TRUE;
704 }
705
706 /*
707 * FUNCTION: Performs a reloc32 relocation on a loaded module
708 * ARGUMENTS:
709 * mod = module to perform the relocation on
710 * scn = Section to perform the relocation in
711 * reloc = Pointer to a data structure describing the relocation
712 * RETURNS: Success or failure
713 * NOTE: This fixes up an undefined reference to a kernel function in a module
714 */
715
716 static BOOLEAN
717 LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
718 {
719 char Name[255];
720 unsigned int Value;
721 unsigned int *Location;
722
723 memset(Name, 0, 255);
724 LdrCOFFGetSymbolName(Module, Relocation->r_symndx, Name);
725 Value = (unsigned int) LdrGetKernelSymbolAddr(Name);
726 if (Value == 0L)
727 {
728 Value = LdrCOFFGetSymbolValueByName(Module, Name, Relocation->r_symndx);
729 if (Value == 0L)
730 {
731 DbgPrint("Undefined symbol %s in module\n", Name);
732 return FALSE;
733 }
734 Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
735 // (*Location) = (*Location) + Value + Module->base - Section->s_vaddr;
736 (*Location) = (*Location);
737 DPRINT("Module->base %x Section->s_vaddr %x\n",
738 Module->base,
739 Section->s_vaddr);
740 }
741 else
742 {
743 DPRINT("REL32 value %x name %s\n", Value, Name);
744 Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
745 DPRINT("old %x ", *Location);
746 DPRINT("Module->base %x Section->s_vaddr %x\n",
747 Module->base,
748 Section->s_vaddr);
749 (*Location) = (*Location) + Value - Module->base + Section->s_vaddr;
750 DPRINT("new %x\n", *Location);
751 }
752
753 return TRUE;
754 }
755
756 /*
757 * FUNCTION: Get the name of a symbol from a loaded module by ordinal
758 * ARGUMENTS:
759 * mod = module
760 * i = index of symbol
761 * name (OUT) = pointer to a string where the symbol name will be
762 * stored
763 */
764
765 static void
766 LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name)
767 {
768 if (Module->sym_list[Idx].e.e_name[0] != 0)
769 {
770 strncpy(Name, Module->sym_list[Idx].e.e_name, 8);
771 Name[8] = '\0';
772 }
773 else
774 {
775 strcpy(Name, &Module->str_tab[Module->sym_list[Idx].e.e.e_offset]);
776 }
777 }
778
779 /*
780 * FUNCTION: Get the value of a module defined symbol
781 * ARGUMENTS:
782 * mod = module
783 * i = index of symbol
784 * RETURNS: The value of the symbol
785 * NOTE: This fixes up references to known sections
786 */
787
788 static unsigned int
789 LdrCOFFGetSymbolValue(module *Module, unsigned int Idx)
790 {
791 char Name[255];
792
793 LdrCOFFGetSymbolName(Module, Idx, Name);
794 DPRINT("name %s ", Name);
795
796 /* Check if the symbol is a section we have relocated */
797 if (strcmp(Name, ".text") == 0)
798 {
799 return Module->text_base;
800 }
801 if (strcmp(Name, ".data") == 0)
802 {
803 return Module->data_base;
804 }
805 if (strcmp(Name, ".bss") == 0)
806 {
807 return Module->bss_base;
808 }
809
810 return Module->sym_list[Idx].e_value;
811 }
812
813 /*
814 * FUNCTION: Get the address of a kernel symbol
815 * ARGUMENTS:
816 * name = symbol name
817 * RETURNS: The address of the symbol on success
818 * NULL on failure
819 */
820
821 static unsigned int
822 LdrGetKernelSymbolAddr(char *Name)
823 {
824 int i = 0;
825
826 while (symbol_table[i].name != NULL)
827 {
828 if (strcmp(symbol_table[i].name, Name) == 0)
829 {
830 return symbol_table[i].value;
831 }
832 i++;
833 }
834
835 return 0L;
836 }
837
838 static unsigned int
839 LdrCOFFGetSymbolValueByName(module *Module,
840 char *SymbolName,
841 unsigned int Idx)
842 {
843 unsigned int i;
844 char Name[255];
845
846 DPRINT("LdrCOFFGetSymbolValueByName(sname %s, idx %x)\n", SymbolName, Idx);
847
848 for (i = 0; i < Module->nsyms; i++)
849 {
850 LdrCOFFGetSymbolName(Module, i, Name);
851 DPRINT("Scanning %s Value %x\n", Name, Module->sym_list[i].e_value);
852 if (strcmp(Name, SymbolName) == 0)
853 {
854 DPRINT("Returning %x\n", Module->sym_list[i].e_value);
855 return Module->sym_list[i].e_value;
856 }
857 }
858
859 return 0L;
860 }
861
862 NTSTATUS LdrLoadLibrary(HANDLE ProcessHandle,
863 PHANDLE ModuleHandle,
864 PCHAR Name)
865 {
866 #if 0
867 NTSTATUS Status;
868 ANSI_STRING afilename;
869 UNICODE_STRING ufilename,umodName;
870 PMODULE *Library, *Module;
871 OBJECT_ATTRIBUTES attr;
872 PWSTR Ignored;
873 char name2[512];
874
875 /* FIXME: this is broke */
876 /* FIXME: check for module already loaded */
877 /* FIXME: otherwise load module */
878 /* FIXME: we need to fix how modules are loaded so that they can
879 be shared... :( */
880
881 /* If module is already loaded, get a reference and return it */
882 strcpy(name2, "\\modules\\");
883 strcat(name2, Name);
884 RtlInitAnsiString(&afilename, name2);
885 RtlAnsiStringToUnicodeString(&umodName, &afilename, TRUE);
886 InitializeObjectAttributes(&attr, &umodName, 0, NULL, NULL);
887 Status = ObOpenObjectByName(&attr, (PVOID *) &Library, &Ignored);
888 DPRINT("LoadLibrary : Status=%x,pLibrary=%x\n",Status, Library);
889 if (!NT_SUCCESS(Status) || Library == NULL)
890 {
891 strcpy(name2, "\\??\\C:\\reactos\\system\\");
892 strcat(name2, name);
893 RtlInitAnsiString(&afilename, name2);
894 RtlAnsiStringToUnicodeString(&ufilename, &afilename, TRUE);
895 DPRINT("LoadLibrary,load %s\n", name2);
896 Library = LdrLoadImage(&ufilename);
897 /* FIXME: execute start code ? */
898 Module = ObGenericCreateObject(NULL, PROCESS_ALL_ACCESS, &attr, ObModuleType);
899 if (Module)
900 {
901 memcpy(Module, Library, PMODULE);
902 }
903 else
904 {
905 DbgPrint("library object not created\n");
906 }
907 RtlFreeUnicodeString(&ufilename);
908 Status = ObOpenObjectByName(&attr, (PVOID *)&Library, &Ignored);
909 }
910 else
911 {
912 DPRINT("Library already loaded\n");
913 *Module = Library
914 }
915 RtlFreeUnicodeString(&umodName);
916
917 return STATUS_SUCCESS;
918 #endif
919 UNIMPLEMENTED;
920 }
921
922 /* LdrLoadImage
923 * FUNCTION:
924 * Loads a module into the specified process
925 * ARGUMENTS:
926 * HANDLE ProcessHandle handle of the process to load the module into
927 * PHANDLE ModuleHandle handle of the loaded module
928 * PUNICODE_STRING Filename name of the module to load
929 * RETURNS:
930 * NTSTATUS
931 */
932
933 NTSTATUS
934 LdrLoadImage(HANDLE ProcessHandle,
935 PHANDLE ModuleHandle,
936 PUNICODE_STRING Filename)
937 {
938 char BlockBuffer[1024];
939 NTSTATUS Status;
940 OBJECT_ATTRIBUTES FileObjectAttributes;
941 HANDLE FileHandle;
942 PMODULE Module;
943 PIMAGE_DOS_HEADER PEDosHeader;
944
945 /* FIXME: should DLLs be named sections? */
946
947 /* Open the image file */
948 InitializeObjectAttributes(&FileObjectAttributes,
949 Filename,
950 0,
951 NULL,
952 NULL);
953 Status = ZwOpenFile(&FileHandle, 0, &FileObjectAttributes, NULL, 0, 0);
954 if (!NT_SUCCESS(Status))
955 {
956 return Status;
957 }
958
959 /* Build a module structure for the image */
960 Module = ObGenericCreateObject(ModuleHandle,
961 PROCESS_ALL_ACCESS,
962 NULL,
963 ObModuleType);
964 if (Module == NULL)
965 {
966 ZwClose(FileHandle);
967 return Status;
968 }
969
970 /* Read first block of image to determine type */
971 Status = ZwReadFile(FileHandle, 0, 0, 0, 0, BlockBuffer, 1024, 0, 0);
972 if (!NT_SUCCESS(Status))
973 {
974 ObDereferenceObject(*ModuleHandle);
975 *ModuleHandle = NULL;
976 ZwClose(FileHandle);
977
978 return Status;
979 }
980
981 /* If MZ header exists */
982 PEDosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
983 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC &&
984 PEDosHeader->e_lfanew != 0L &&
985 *(PULONG)((PUCHAR)BlockBuffer + PEDosHeader->e_lfanew) == IMAGE_PE_MAGIC)
986 {
987 Status = LdrProcessPEImage(ProcessHandle,
988 ModuleHandle,
989 FileHandle);
990 }
991 else if (PEDosHeader->e_magic == 0x54AD)
992 {
993 Status = LdrProcessMZImage(ProcessHandle,
994 ModuleHandle,
995 FileHandle);
996 }
997 else /* Assume bin format and load */
998 {
999 Status = LdrProcessBinImage(ProcessHandle,
1000 ModuleHandle,
1001 FileHandle);
1002 }
1003 /* FIXME: {else} could check for a.out, ELF, COFF, etc. images here... */
1004
1005 /* FIXME: should we unconditionally dereference the module handle here? */
1006 if (!NT_SUCCESS(Status))
1007 {
1008 ObDereferenceObject(*ModuleHandle);
1009 *ModuleHandle = NULL;
1010 }
1011 ZwClose(FileHandle);
1012
1013 return Status;
1014 }
1015
1016 static NTSTATUS
1017 LdrProcessMZImage(HANDLE ProcessHandle,
1018 HANDLE ModuleHandle,
1019 HANDLE FileHandle)
1020 {
1021
1022 /* FIXME: map VDM into low memory */
1023 /* FIXME: Build/Load image sections */
1024
1025 return STATUS_NOT_IMPLEMENTED;
1026 }
1027
1028 static NTSTATUS
1029 LdrProcessPEImage(HANDLE ProcessHandle,
1030 HANDLE ModuleHandle,
1031 HANDLE FileHandle)
1032 {
1033 int i;
1034 NTSTATUS Status;
1035 PVOID BaseSection;
1036 PIMAGE_DOS_HEADER DosHeader;
1037 PIMAGE_NT_HEADERS NTHeaders;
1038 PMODULE Module;
1039 LARGE_INTEGER SectionOffset;
1040 HANDLE SectionHandle;
1041
1042 /* Allocate memory for headers */
1043 Module = HEADER_TO_BODY(ModuleHandle);
1044 if (Module == NULL)
1045 {
1046 return STATUS_UNSUCCESSFUL;
1047 }
1048 DosHeader = (PIMAGE_DOS_HEADER)ExAllocatePool(NonPagedPool,
1049 sizeof(IMAGE_DOS_HEADER) +
1050 sizeof(IMAGE_NT_HEADERS));
1051 if (DosHeader == NULL)
1052 {
1053 return STATUS_UNSUCCESSFUL;
1054 }
1055 NTHeaders = (PIMAGE_NT_HEADERS)((PUCHAR) DosHeader + sizeof(IMAGE_DOS_HEADER));
1056
1057 /* Read the headers into memory */
1058 memset(Module, '\0', sizeof(PMODULE));
1059 Status = ZwReadFile(FileHandle,
1060 NULL, NULL, NULL, NULL,
1061 DosHeader,
1062 sizeof(IMAGE_DOS_HEADER),
1063 0, 0);
1064 if (!NT_SUCCESS(Status))
1065 {
1066 ExFreePool(DosHeader);
1067 return Status;
1068 }
1069 SET_LARGE_INTEGER_HIGH_PART(SectionOffset, 0);
1070 SET_LARGE_INTEGER_LOW_PART(SectionOffset, DosHeader->e_lfanew);
1071 Status = ZwReadFile(FileHandle,
1072 NULL, NULL, NULL, NULL,
1073 NTHeaders,
1074 sizeof(IMAGE_NT_HEADERS),
1075 &SectionOffset,
1076 0);
1077 if (!NT_SUCCESS(Status))
1078 {
1079 ExFreePool(DosHeader);
1080 return Status;
1081 }
1082
1083 /* Create the section for the code */
1084 Status = ZwCreateSection(&SectionHandle,
1085 SECTION_ALL_ACCESS,
1086 NULL,
1087 NULL,
1088 PAGE_READWRITE,
1089 MEM_COMMIT,
1090 FileHandle);
1091 if (!NT_SUCCESS(Status))
1092 {
1093 return Status;
1094 }
1095
1096 /* Map the Image into the process */
1097 Module->Flags = MODULE_FLAG_PE;
1098 Module->Base = (PVOID) NTHeaders->OptionalHeader.ImageBase;
1099 Module->Size = NTHeaders->OptionalHeader.SizeOfImage;
1100 Status = ZwMapViewOfSection(SectionHandle,
1101 ProcessHandle,
1102 &Module->Base,
1103 0,
1104 Module->Size,
1105 NULL,
1106 &Module->Size,
1107 0,
1108 MEM_COMMIT,
1109 PAGE_READWRITE);
1110 if (!NT_SUCCESS(Status))
1111 {
1112 /* FIXME: destroy the section here */
1113 ExFreePool(DosHeader);
1114 return Status;
1115 }
1116
1117 /* FIXME: create stack and other BSS sections */
1118 /* FIXME: if actual load address is different from ImageBase, then reloc */
1119 /* FIXME: do import fixups/load required libraries */
1120
1121 #if 0
1122 /* Load headers into virtual memory */
1123 Status = ZwReadFile(FileHandle,
1124 NULL, NULL, NULL, NULL,
1125 Module->Base,
1126 NTHeaders->OptionalHeader.SizeOfHeaders,
1127 0, 0);
1128 if (!NT_SUCCESS(Status))
1129 {
1130 ZwFreeVirtualMemory(ProcessHandle,
1131 Module->Base,
1132 0,
1133 MEM_RELEASE);
1134 ExFreePool(DosHeader);
1135 return Status;
1136 }
1137
1138 /* Adjust module pointers into virtual memory */
1139 DosHeader = (PIMAGE_DOS_HEADER) Module->Base;
1140 NTHeaders = (PIMAGE_NT_HEADERS) ((PUCHAR)Module->Base +
1141 DosHeader->e_lfanew);
1142 Module->Image.PE.FileHeader = (PIMAGE_FILE_HEADER) ((PUCHAR)NTHeaders +
1143 sizeof(DWORD));
1144 Module->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
1145 ((PUCHAR)Module->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
1146 Module->Image.PE.SectionList = (PCOFF_SECTION_HEADER) ((PUCHAR)NTHeaders +
1147 sizeof(IMAGE_NT_HEADERS));
1148
1149 /* Build Image Sections */
1150 /* FIXME: should probably use image directory to load sections. */
1151 for (i = 0; i < Module->Image.PE.FileHeader->NumberOfSections; i++)
1152 {
1153 DPRINT("section %d\n", i);
1154 BaseSection = (PVOID)((PCHAR) Module->Base +
1155 Module->Image.PE.SectionList[i].s_vaddr);
1156
1157 /* Load code and initialized data sections from disk */
1158 if ((Module->Image.PE.SectionList[i].s_flags & STYP_TEXT) ||
1159 (Module->Image.PE.SectionList[i].s_flags & STYP_DATA))
1160 {
1161 SET_LARGE_INTEGER_HIGH_PART(SectionOffset, 0);
1162 SET_LARGE_INTEGER_LOW_PART(SectionOffset,
1163 Module->Image.PE.SectionList[i].s_scnptr);
1164
1165 /* FIXME: should probably map sections into sections */
1166 Status = ZwReadFile(FileHandle,
1167 NULL, NULL, NULL, NULL,
1168 Module->Base + Module->Image.PE.SectionList[i].s_vaddr,
1169 min(Module->Image.PE.SectionList[i].s_size,
1170 Module->Image.PE.SectionList[i].s_paddr),
1171 &SectionOffset, 0);
1172 if (!NT_SUCCESS(Status))
1173 {
1174 ZwFreeVirtualMemory(ProcessHandle,
1175 Module->Base,
1176 0,
1177 MEM_RELEASE);
1178 ExFreePool(DosHeader);
1179 return Status;
1180 }
1181 }
1182 else if (Module->Image.PE.SectionList[i].s_flags & STYP_BSS)
1183 {
1184 memset((PVOID)(Module->Base +
1185 Module->Image.PE.SectionList[i].s_vaddr),
1186 0,
1187 Module->Image.PE.SectionList[i].s_size);
1188 }
1189 }
1190
1191 /* Resolve Import Library references */
1192 if (Module->Image.PE.OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1193 {
1194 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1195
1196 /* Process each import module */
1197 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1198 ((PUCHAR)Module->Base + Module->Image.PE.OptionalHeader->
1199 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1200 while (ImportModuleDirectory->dwRVAModuleName)
1201 {
1202 PMODULE Library;
1203 PVOID *LibraryExports;
1204 PVOID *ImportAddressList; // was pImpAddr
1205 PULONG FunctionNameList;
1206 DWORD pName;
1207 PWORD pHint;
1208
1209 /* Load the library module into the process */
1210 /* FIXME: this should take a UNICODE string */
1211 Status = LdrLoadLibrary(ProcessHandle,
1212 &Library,
1213 (PCHAR)(Module->Base +
1214 ImportModuleDirectory->dwRVAModuleName));
1215 if (!NT_SUCCESS(Status))
1216 {
1217 /* FIXME: Dereference all loaded modules */
1218 ZwFreeVirtualMemory(ProcessHandle,
1219 Module->Base,
1220 0,
1221 MEM_RELEASE);
1222 ExFreePool(DosHeader);
1223
1224 return Status;
1225 }
1226
1227 /* Get the address of the export list for the library */
1228 LibraryExports = (PVOID *)(Library->Base +
1229 Library->Image.PE.OptionalHeader->
1230 DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress +
1231 sizeof(IMAGE_EXPORT_DIRECTORY));
1232
1233 /* Get the import address list */
1234 ImportAddressList = (PVOID *)
1235 ((PCHAR)Module->Image.PE.OptionalHeader->ImageBase +
1236 ImportModuleDirectory->dwRVAFunctionAddressList);
1237
1238 /* Get the list of functions to import */
1239 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1240 {
1241 FunctionNameList = (PULONG) ((PCHAR)Module->Base +
1242 ImportModuleDirectory->dwRVAFunctionNameList);
1243 }
1244 else
1245 {
1246 FunctionNameList = (PULONG) ((PCHAR)Module->Base +
1247 ImportModuleDirectory->dwRVAFunctionAddressList);
1248 }
1249
1250 /* Walk through function list and fixup addresses */
1251 while(*FunctionNameList != 0L)
1252 {
1253 if ((*FunctionNameList) & 0x80000000) // hint
1254 {
1255 *ImportAddressList = LibraryExports[(*FunctionNameList) & 0x7fffffff];
1256 }
1257 else // hint-name
1258 {
1259 pName = (DWORD)((PCHAR)Module->Base + *FunctionNameList + 2);
1260 pHint = (PWORD)((PCHAR)Module->Base + *FunctionNameList);
1261
1262 /* FIXME: verify name */
1263
1264 *ImportAddressList = LibraryExports[*pHint];
1265 }
1266
1267 /* FIXME: verify value of hint */
1268
1269 ImportAddressList++;
1270 FunctionNameList++;
1271 }
1272 ImportModuleDirectory++;
1273 }
1274 }
1275
1276 /* Do fixups */
1277 if (Module->Base != (PVOID)Module->Image.PE.OptionalHeader->ImageBase)
1278 {
1279 USHORT NumberOfEntries;
1280 PUSHORT pValue16;
1281 ULONG RelocationRVA;
1282 ULONG Delta32, Offset;
1283 PULONG pValue32;
1284 PRELOCATION_DIRECTORY RelocationDir;
1285 PRELOCATION_ENTRY RelocationBlock;
1286
1287 RelocationRVA = NTHeaders->OptionalHeader.DataDirectory[
1288 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
1289 if (RelocationRVA)
1290 {
1291 RelocationDir = (PRELOCATION_DIRECTORY)
1292 ((PCHAR)Module->Base + RelocationRVA);
1293 while (RelocationDir->SizeOfBlock)
1294 {
1295 Delta32 = (unsigned long)(Module->Base - NTHeaders->OptionalHeader.ImageBase);
1296 RelocationBlock = (PRELOCATION_ENTRY)
1297 (RelocationRVA + Module->Base + sizeof(RELOCATION_DIRECTORY));
1298 NumberOfEntries =
1299 (RelocationDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1300 sizeof(RELOCATION_ENTRY);
1301 for (i = 0; i < NumberOfEntries; i++)
1302 {
1303 Offset = (RelocationBlock[i].TypeOffset & 0xfff) + RelocationDir->VirtualAddress;
1304 switch (RelocationBlock[i].TypeOffset >> 12)
1305 {
1306 case TYPE_RELOC_ABSOLUTE:
1307 break;
1308
1309 case TYPE_RELOC_HIGH:
1310 pValue16 = (PUSHORT) (Module->Base + Offset);
1311 *pValue16 += Delta32 >> 16;
1312 break;
1313
1314 case TYPE_RELOC_LOW:
1315 pValue16 = (PUSHORT)(Module->Base + Offset);
1316 *pValue16 += Delta32 & 0xffff;
1317 break;
1318
1319 case TYPE_RELOC_HIGHLOW:
1320 pValue32 = (PULONG) (Module->Base + Offset);
1321 *pValue32 += Delta32;
1322 break;
1323
1324 case TYPE_RELOC_HIGHADJ:
1325 /* FIXME: do the highadjust fixup */
1326 DbgPrint("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n");
1327 // break;
1328
1329 default:
1330 DbgPrint("unexpected fixup type\n");
1331
1332 /* FIXME: Dereference all loaded modules */
1333
1334 ZwFreeVirtualMemory(ProcessHandle,
1335 Module->Base,
1336 0,
1337 MEM_RELEASE);
1338 ExFreePool(DosHeader);
1339 return STATUS_UNSUCCESSFUL;
1340 }
1341 }
1342 RelocationRVA += RelocationDir->SizeOfBlock;
1343 RelocationDir = (PRELOCATION_DIRECTORY)((PCHAR)Module->Base +
1344 RelocationRVA);
1345 }
1346 }
1347 }
1348 #endif
1349
1350 /* FIXME: Create the stack for the process */
1351 /* FIXME: Setup the context for the initial thread */
1352 /* FIXME: Create the initial thread */
1353
1354 // fail: ZwFreeVirtualMemory(ProcessHandle, Module->ImageBase, 0, MEM_RELEASE);
1355 ExFreePool(DosHeader);
1356
1357 return STATUS_NOT_IMPLEMENTED;
1358 }
1359
1360 NTSTATUS
1361 LdrProcessBinImage(HANDLE ProcessHandle,
1362 HANDLE ModuleHandle,
1363 HANDLE FileHandle)
1364 {
1365 NTSTATUS Status;
1366 FILE_STANDARD_INFORMATION FileStdInfo;
1367 ULONG SectionSize;
1368 HANDLE ThreadHandle;
1369 CONTEXT Context;
1370 HANDLE SectionHandle;
1371 PVOID BaseAddress;
1372
1373 /* FIXME: should set module pointers */
1374
1375 /* Get the size of the file for the section */
1376 Status = ZwQueryInformationFile(FileHandle,
1377 NULL,
1378 &FileStdInfo,
1379 sizeof(FileStdInfo),
1380 FileStandardInformation);
1381 if (!NT_SUCCESS(Status))
1382 {
1383 return Status;
1384 }
1385
1386 /* Create the section for the code */
1387 Status = ZwCreateSection(&SectionHandle,
1388 SECTION_ALL_ACCESS,
1389 NULL,
1390 NULL,
1391 PAGE_READWRITE,
1392 MEM_COMMIT,
1393 FileHandle);
1394 if (!NT_SUCCESS(Status))
1395 {
1396 return Status;
1397 }
1398
1399 /* Map a view of the section into the desired process */
1400 BaseAddress = (PVOID)0x10000;
1401 SectionSize = GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize);
1402 Status = ZwMapViewOfSection(SectionHandle,
1403 ProcessHandle,
1404 &BaseAddress,
1405 0,
1406 SectionSize,
1407 NULL,
1408 &SectionSize,
1409 0,
1410 MEM_COMMIT,
1411 PAGE_READWRITE);
1412 if (!NT_SUCCESS(Status))
1413 {
1414 /* FIXME: destroy the section here */
1415 return Status;
1416 }
1417
1418 /* Setup the context for the initial thread */
1419 memset(&Context,0,sizeof(CONTEXT));
1420 Context.SegSs = USER_DS;
1421 Context.Esp = 0x2000;
1422 Context.EFlags = 0x202;
1423 Context.SegCs = USER_CS;
1424 Context.Eip = 0x10000;
1425 Context.SegDs = USER_DS;
1426 Context.SegEs = USER_DS;
1427 Context.SegFs = USER_DS;
1428 Context.SegGs = USER_DS;
1429
1430 /* Create the stack for the process */
1431 BaseAddress = (PVOID) 0x1000;
1432 SectionSize = 0x1000;
1433 Status = ZwAllocateVirtualMemory(ProcessHandle,
1434 &BaseAddress,
1435 0,
1436 &SectionSize,
1437 MEM_COMMIT,
1438 PAGE_READWRITE);
1439 if (!NT_SUCCESS(Status))
1440 {
1441 /* FIXME: unmap the section here */
1442 /* FIXME: destroy the section here */
1443
1444 return Status;
1445 }
1446
1447 /* Create the initial thread */
1448 Status = ZwCreateThread(&ThreadHandle,
1449 THREAD_ALL_ACCESS,
1450 NULL,
1451 ProcessHandle,
1452 NULL,
1453 &Context,
1454 NULL,
1455 FALSE);
1456 if (!NT_SUCCESS(Status))
1457 {
1458 /* FIXME: destroy the stack memory block here */
1459 /* FIXME: unmap the section here */
1460 /* FIXME: destroy the section here */
1461 return Status;
1462 }
1463
1464 return STATUS_SUCCESS;
1465 }
1466
1467