mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Implemented loader functions for COFF Drivers and BIN apps, and stubs for PE apps
svn path=/trunk/; revision=118
This commit is contained in:
parent
6b8cb5c939
commit
570be7966c
4 changed files with 710 additions and 196 deletions
|
@ -31,5 +31,7 @@ typedef struct
|
|||
|
||||
BOOLEAN process_boot_module(unsigned int start);
|
||||
|
||||
NTSTATUS InitalizeLoadedDriver(PDRIVER_INITIALIZE entry);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3,117 +3,488 @@
|
|||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ldr/loader.c
|
||||
* PURPOSE: Loaders for PE executables
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com)
|
||||
* UPDATE HISTORY:
|
||||
* Created 22/05/98
|
||||
* DW 22/05/98 Created
|
||||
* RJJ 10/12/98 Completed loader function and added hooks for MZ/PE
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <internal/i386/segment.h>
|
||||
#include <internal/kernel.h>
|
||||
#include <internal/linkage.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/module.h>
|
||||
#include <internal/string.h>
|
||||
#include <internal/symbol.h>
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ddk/li.h>
|
||||
|
||||
//#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "pe.h"
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS LdrProcessImage(HANDLE SectionHandle, PVOID BaseAddress)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos_hdr = (PIMAGE_DOS_HEADER)BaseAddress;
|
||||
PIMAGE_NT_HEADERS hdr = (PIMAGE_NT_HEADERS)(BaseAddress
|
||||
+ dos_hdr->e_lfanew);
|
||||
PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)(BaseAddress
|
||||
+ dos_hdr->e_lfanew + sizeof(IMAGE_NT_HEADERS));
|
||||
/* COFF Driver load support **************************************************/
|
||||
static BOOLEAN LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex);
|
||||
static BOOLEAN LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
|
||||
static BOOLEAN LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
|
||||
static void LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name);
|
||||
static unsigned int LdrCOFFGetSymbolValue(module *Module, unsigned int Idx);
|
||||
static unsigned int LdrCOFFGetKernelSymbolAddr(char *Name);
|
||||
static unsigned int LdrCOFFGetSymbolValueByName(module *Module, char *SymbolName, unsigned int Idx);
|
||||
|
||||
// FIXME: Check image signature
|
||||
// FIXME: Check architechture
|
||||
// FIXME: Build/Load image sections
|
||||
// FIXME: resolve imports
|
||||
// FIXME: do fixups
|
||||
static NTSTATUS
|
||||
LdrCOFFProcessDriver(HANDLE FileHandle)
|
||||
{
|
||||
BOOLEAN FoundEntry;
|
||||
char SymbolName[255];
|
||||
int i;
|
||||
NTSTATUS Status;
|
||||
PVOID ModuleLoadBase;
|
||||
ULONG EntryOffset;
|
||||
FILHDR *FileHeader;
|
||||
AOUTHDR *AOUTHeader;
|
||||
module *Module;
|
||||
FILE_STANDARD_INFORMATION FileStdInfo;
|
||||
PDRIVER_INITIALIZE EntryRoutine;
|
||||
|
||||
/* Get the size of the file for the section */
|
||||
Status = ZwQueryInformationFile(FileHandle,
|
||||
NULL,
|
||||
&FileStdInfo,
|
||||
sizeof(FileStdInfo),
|
||||
FileStandardInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
CHECKPOINT;
|
||||
|
||||
/* Allocate nonpageable memory for driver */
|
||||
ModuleLoadBase = ExAllocatePool(NonPagedPool,
|
||||
GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize));
|
||||
if (ModuleLoadBase == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
CHECKPOINT;
|
||||
|
||||
/* Load driver into memory chunk */
|
||||
Status = ZwReadFile(FileHandle,
|
||||
0, 0, 0, 0,
|
||||
ModuleLoadBase,
|
||||
GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize),
|
||||
0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(ModuleLoadBase);
|
||||
return Status;
|
||||
}
|
||||
CHECKPOINT;
|
||||
|
||||
/* Get header pointers */
|
||||
FileHeader = ModuleLoadBase;
|
||||
AOUTHeader = ModuleLoadBase + FILHSZ;
|
||||
CHECKPOINT;
|
||||
|
||||
/* Check COFF magic value */
|
||||
if (I386BADMAG(*FileHeader))
|
||||
{
|
||||
DbgPrint("Module has bad magic value (%x)\n",
|
||||
FileHeader->f_magic);
|
||||
ExFreePool(ModuleLoadBase);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
CHECKPOINT;
|
||||
|
||||
/* Allocate and initialize a module definition structure */
|
||||
Module = (module *) ExAllocatePool(NonPagedPool, sizeof(module));
|
||||
if (Module == NULL)
|
||||
{
|
||||
ExFreePool(ModuleLoadBase);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
Module->sym_list = (SYMENT *)(ModuleLoadBase + FileHeader->f_symptr);
|
||||
Module->str_tab = (char *)(ModuleLoadBase + FileHeader->f_symptr +
|
||||
FileHeader->f_nsyms * SYMESZ);
|
||||
Module->scn_list = (SCNHDR *)(ModuleLoadBase + FILHSZ +
|
||||
FileHeader->f_opthdr);
|
||||
Module->size = 0;
|
||||
Module->raw_data_off = (ULONG) ModuleLoadBase;
|
||||
Module->nsyms = FileHeader->f_nsyms;
|
||||
CHECKPOINT;
|
||||
|
||||
/* Determine the length of the module */
|
||||
for (i = 0; i < FileHeader->f_nscns; i++)
|
||||
{
|
||||
DPRINT("Section name: %.8s\n", Module->scn_list[i].s_name);
|
||||
DPRINT("size %x vaddr %x size %x\n",
|
||||
Module->size,
|
||||
Module->scn_list[i].s_vaddr,
|
||||
Module->scn_list[i].s_size);
|
||||
if (Module->scn_list[i].s_flags & STYP_TEXT)
|
||||
{
|
||||
Module->text_base = Module->scn_list[i].s_vaddr;
|
||||
}
|
||||
if (Module->scn_list[i].s_flags & STYP_DATA)
|
||||
{
|
||||
Module->data_base = Module->scn_list[i].s_vaddr;
|
||||
}
|
||||
if (Module->scn_list[i].s_flags & STYP_BSS)
|
||||
{
|
||||
Module->bss_base = Module->scn_list[i].s_vaddr;
|
||||
}
|
||||
if (Module->size <
|
||||
(Module->scn_list[i].s_vaddr + Module->scn_list[i].s_size))
|
||||
{
|
||||
Module->size = Module->size + Module->scn_list[i].s_vaddr +
|
||||
Module->scn_list[i].s_size;
|
||||
}
|
||||
}
|
||||
CHECKPOINT;
|
||||
|
||||
/* Allocate a section for the module */
|
||||
Module->base = (unsigned int) MmAllocateSection(Module->size);
|
||||
if (Module->base == 0)
|
||||
{
|
||||
DbgPrint("Failed to alloc section for module\n");
|
||||
ExFreePool(Module);
|
||||
ExFreePool(ModuleLoadBase);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
CHECKPOINT;
|
||||
|
||||
/* Adjust section vaddrs for allocated area */
|
||||
Module->data_base = Module->data_base + Module->base;
|
||||
Module->text_base = Module->text_base + Module->base;
|
||||
Module->bss_base = Module->bss_base + Module->base;
|
||||
|
||||
/* Relocate module and fixup imports */
|
||||
for (i = 0; i < FileHeader->f_nscns; i++)
|
||||
{
|
||||
if (Module->scn_list[i].s_flags & STYP_TEXT ||
|
||||
Module->scn_list[i].s_flags & STYP_DATA)
|
||||
{
|
||||
memcpy((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
|
||||
(PVOID)(ModuleLoadBase + Module->scn_list[i].s_scnptr),
|
||||
Module->scn_list[i].s_size);
|
||||
if (!LdrCOFFDoRelocations(Module, i))
|
||||
{
|
||||
DPRINT("Relocation failed for section %s\n",
|
||||
Module->scn_list[i].s_name);
|
||||
ExFreePool(Module);
|
||||
ExFreePool(ModuleLoadBase);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
if (Module->scn_list[i].s_flags & STYP_BSS)
|
||||
{
|
||||
memset((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
|
||||
0,
|
||||
Module->scn_list[i].s_size);
|
||||
}
|
||||
}
|
||||
|
||||
DbgPrint("Module base: %x\n", Module->base);
|
||||
|
||||
/* Find the entry point */
|
||||
EntryOffset = 0L;
|
||||
FoundEntry = FALSE;
|
||||
for (i = 0; i < FileHeader->f_nsyms; i++)
|
||||
{
|
||||
LdrCOFFGetSymbolName(Module, i, SymbolName);
|
||||
if (!strcmp(SymbolName, "_DriverEntry"))
|
||||
{
|
||||
EntryOffset = Module->sym_list[i].e_value;
|
||||
FoundEntry = TRUE;
|
||||
DPRINT("Found entry at %x\n", EntryOffset);
|
||||
}
|
||||
}
|
||||
if (!FoundEntry)
|
||||
{
|
||||
DbgPrint("No module entry point defined\n");
|
||||
ExFreePool(Module);
|
||||
ExFreePool(ModuleLoadBase);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Call the module initalization routine */
|
||||
EntryRoutine = (PDRIVER_INITIALIZE)(Module->base + EntryOffset);
|
||||
|
||||
return InitalizeLoadedDriver(EntryRoutine);
|
||||
}
|
||||
|
||||
NTSTATUS LdrLoadDriver(PUNICODE_STRING FileName)
|
||||
/* LdrCOFFDoRelocations
|
||||
* FUNCTION: Do the relocations for a module section
|
||||
* ARGUMENTS:
|
||||
* Module = Pointer to the module
|
||||
* SectionIndex = Index of the section to be relocated
|
||||
* RETURNS: Success or failure
|
||||
*/
|
||||
|
||||
static BOOLEAN
|
||||
LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex)
|
||||
{
|
||||
SCNHDR *Section = &Module->scn_list[SectionIndex];
|
||||
RELOC *Relocation = (RELOC *)(Module->raw_data_off + Section->s_relptr);
|
||||
int j;
|
||||
|
||||
DPRINT("SectionIndex %d Name %.8s Relocs %d\n",
|
||||
SectionIndex,
|
||||
Module->scn_list[SectionIndex].s_name,
|
||||
Section->s_nreloc);
|
||||
|
||||
for (j = 0; j < Section->s_nreloc; j++)
|
||||
{
|
||||
DbgPrint("vaddr %x ", Relocation->r_vaddr);
|
||||
DbgPrint("symndex %x ", Relocation->r_symndx);
|
||||
|
||||
switch (Relocation->r_type)
|
||||
{
|
||||
case RELOC_ADDR32:
|
||||
if (!LdrCOFFDoAddr32Reloc(Module, Section, Relocation))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case RELOC_REL32:
|
||||
if (!LdrCOFFDoReloc32Reloc(Module, Section, Relocation))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DbgPrint("%.8s: Unknown relocation type %x at %d in module\n",
|
||||
Module->scn_list[SectionIndex].s_name,
|
||||
Relocation->r_type,
|
||||
j);
|
||||
return FALSE;
|
||||
}
|
||||
Relocation++;
|
||||
}
|
||||
DPRINT("%.8s: relocations done\n", Module->scn_list[SectionIndex].s_name);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Loads a PE executable into the kernel
|
||||
* FUNCTION: Performs a addr32 relocation on a loaded module
|
||||
* ARGUMENTS:
|
||||
* mod = module to perform the relocation on
|
||||
* scn = Section to perform the relocation in
|
||||
* reloc = Pointer to a data structure describing the relocation
|
||||
* RETURNS: Success or failure
|
||||
* NOTE: This fixes up a relocation needed when changing the base address of a
|
||||
* module
|
||||
*/
|
||||
|
||||
static BOOLEAN
|
||||
LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
|
||||
{
|
||||
unsigned int Value;
|
||||
unsigned int *Location;
|
||||
|
||||
Value = LdrCOFFGetSymbolValue(Module, Relocation->r_symndx);
|
||||
Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
|
||||
DbgPrint("ADDR32 loc %x value %x *loc %x ", Location, Value, *Location);
|
||||
*Location = (*Location) + Module->base;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Performs a reloc32 relocation on a loaded module
|
||||
* ARGUMENTS:
|
||||
* mod = module to perform the relocation on
|
||||
* scn = Section to perform the relocation in
|
||||
* reloc = Pointer to a data structure describing the relocation
|
||||
* RETURNS: Success or failure
|
||||
* NOTE: This fixes up an undefined reference to a kernel function in a module
|
||||
*/
|
||||
|
||||
static BOOLEAN
|
||||
LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
|
||||
{
|
||||
char Name[255];
|
||||
unsigned int Value;
|
||||
unsigned int *Location;
|
||||
|
||||
memset(Name, 0, 255);
|
||||
LdrCOFFGetSymbolName(Module, Relocation->r_symndx, Name);
|
||||
Value = (unsigned int) LdrCOFFGetKernelSymbolAddr(Name);
|
||||
if (Value == 0L)
|
||||
{
|
||||
Value = LdrCOFFGetSymbolValueByName(Module, Name, Relocation->r_symndx);
|
||||
if (Value == 0L)
|
||||
{
|
||||
DbgPrint("Undefined symbol %s in module\n", Name);
|
||||
return FALSE;
|
||||
}
|
||||
Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
|
||||
// (*Location) = (*Location) + Value + Module->base - Section->s_vaddr;
|
||||
(*Location) = (*Location);
|
||||
DPRINT("Module->base %x Section->s_vaddr %x\n",
|
||||
Module->base,
|
||||
Section->s_vaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("REL32 value %x name %s\n", Value, Name);
|
||||
Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
|
||||
DPRINT("old %x ", *Location);
|
||||
DPRINT("Module->base %x Section->s_vaddr %x\n",
|
||||
Module->base,
|
||||
Section->s_vaddr);
|
||||
(*Location) = (*Location) + Value - Module->base + Section->s_vaddr;
|
||||
DPRINT("new %x\n", *Location);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Get the name of a symbol from a loaded module by ordinal
|
||||
* ARGUMENTS:
|
||||
* mod = module
|
||||
* i = index of symbol
|
||||
* name (OUT) = pointer to a string where the symbol name will be
|
||||
* stored
|
||||
*/
|
||||
|
||||
static void
|
||||
LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name)
|
||||
{
|
||||
if (Module->sym_list[Idx].e.e_name[0] != 0)
|
||||
{
|
||||
strncpy(Name, Module->sym_list[Idx].e.e_name, 8);
|
||||
Name[8] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(Name, &Module->str_tab[Module->sym_list[Idx].e.e.e_offset]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Get the value of a module defined symbol
|
||||
* ARGUMENTS:
|
||||
* mod = module
|
||||
* i = index of symbol
|
||||
* RETURNS: The value of the symbol
|
||||
* NOTE: This fixes up references to known sections
|
||||
*/
|
||||
|
||||
static unsigned int
|
||||
LdrCOFFGetSymbolValue(module *Module, unsigned int Idx)
|
||||
{
|
||||
char Name[255];
|
||||
|
||||
LdrCOFFGetSymbolName(Module, Idx, Name);
|
||||
DbgPrint("name %s ", Name);
|
||||
|
||||
/* Check if the symbol is a section we have relocated */
|
||||
if (strcmp(Name, ".text") == 0)
|
||||
{
|
||||
return Module->text_base;
|
||||
}
|
||||
if (strcmp(Name, ".data") == 0)
|
||||
{
|
||||
return Module->data_base;
|
||||
}
|
||||
if (strcmp(Name, ".bss") == 0)
|
||||
{
|
||||
return Module->bss_base;
|
||||
}
|
||||
|
||||
return Module->sym_list[Idx].e_value;
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Get the address of a kernel symbol
|
||||
* ARGUMENTS:
|
||||
* name = symbol name
|
||||
* RETURNS: The address of the symbol on success
|
||||
* NULL on failure
|
||||
*/
|
||||
|
||||
static unsigned int
|
||||
LdrCOFFGetKernelSymbolAddr(char *Name)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (symbol_table[i].name != NULL)
|
||||
{
|
||||
if (strcmp(symbol_table[i].name, Name) == 0)
|
||||
{
|
||||
return symbol_table[i].value;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0L;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
LdrCOFFGetSymbolValueByName(module *Module,
|
||||
char *SymbolName,
|
||||
unsigned int Idx)
|
||||
{
|
||||
unsigned int i;
|
||||
char Name[255];
|
||||
|
||||
DPRINT("LdrCOFFGetSymbolValueByName(sname %s, idx %x)\n", SymbolName, Idx);
|
||||
|
||||
for (i = 0; i < Module->nsyms; i++)
|
||||
{
|
||||
LdrCOFFGetSymbolName(Module, i, Name);
|
||||
DPRINT("Scanning %s Value %x\n", Name, Module->sym_list[i].e_value);
|
||||
if (strcmp(Name, SymbolName) == 0)
|
||||
{
|
||||
DPRINT("Returning %x\n", Module->sym_list[i].e_value);
|
||||
return Module->sym_list[i].e_value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0L;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
LdrProcessPEDriver(HANDLE FileHandle, PIMAGE_DOS_HEADER DosHeader)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
LdrLoadDriver(PUNICODE_STRING Filename)
|
||||
/*
|
||||
* FUNCTION: Loads a kernel driver
|
||||
* ARGUMENTS:
|
||||
* FileName = Driver to load
|
||||
* RETURNS: Status
|
||||
*/
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE FileHandle;
|
||||
HANDLE SectionHandle;
|
||||
ANSI_STRING AnsiFileName;
|
||||
UNICODE_STRING UnicodeFileName;
|
||||
OBJECT_ATTRIBUTES FileAttributes;
|
||||
PVOID BaseAddress;
|
||||
|
||||
// Open the image file or die
|
||||
RtlInitAnsiString(&AnsiFileName, FileName);
|
||||
RtlAnsiStringToUnicodeString(&UnicodeFileName, &AnsiFileName, TRUE);
|
||||
InitializeObjectAttributes(&FileAttributes,
|
||||
&UnicodeFileName,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
FileHandle = ZwFileOpen(&FileHandle, 0, &FileAttributes, NULL, 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
RtlFreeUnicodeString(&UnicodeFileName);
|
||||
|
||||
// Map the image into a section or die
|
||||
Status = ZwCreateSection(&SectionHandle,
|
||||
SECTION_MAP_READ,
|
||||
NULL,
|
||||
NULL,
|
||||
PAGE_READONLY,
|
||||
SEC_IMAGE,
|
||||
FileHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
// FIXME: get the base address of the section
|
||||
|
||||
ZwCloseFile(FileHandle);
|
||||
|
||||
return LdrProcessImage(SectionHandle, BaseAddress);
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Loads a PE executable into the specified process
|
||||
* ARGUMENTS:
|
||||
* Filename = File to load
|
||||
* ProcessHandle = handle
|
||||
* RETURNS: Status
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
LdrLoadImage(PUNICODE_STRING Filename, HANDLE ProcessHandle)
|
||||
{
|
||||
char BlockBuffer[512];
|
||||
NTSTATUS Status;
|
||||
HANDLE FileHandle;
|
||||
OBJECT_ATTRIBUTES FileObjectAttributes;
|
||||
PIMAGE_DOS_HEADER PEDosHeader;
|
||||
PIMAGE_NT_HEADERS PEHeader;
|
||||
|
||||
HANDLE SectionHandle;
|
||||
PVOID BaseAddress;
|
||||
|
||||
/* Open the image file */
|
||||
/* Open the Driver */
|
||||
InitializeObjectAttributes(&FileObjectAttributes,
|
||||
&Filename,
|
||||
Filename,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwFileOpen(&FileHandle, 0, &FileObjectAttributes, NULL, 0, 0);
|
||||
Status = ZwOpenFile(&FileHandle, 0, &FileObjectAttributes, NULL, 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
|
@ -129,16 +500,145 @@ LdrLoadImage(PUNICODE_STRING Filename, HANDLE ProcessHandle)
|
|||
|
||||
/* If MZ header exists */
|
||||
PEDosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
|
||||
if (PEDosHeader->e_magic == 0x54AD && PEDosHeader->e_lfanew != 0L)
|
||||
{
|
||||
Status = LdrProcessPEDriver(FileHandle, PEDosHeader);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ZwClose(FileHandle);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
if (PEDosHeader->e_magic == 0x54AD)
|
||||
{
|
||||
/* FIXME: if PE header exists */
|
||||
/* FIXME: load PE image */
|
||||
/* FIXME: else */
|
||||
/* FIXME: load MZ image */
|
||||
ZwClose(FileHandle);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
else /* Assume coff format and load */
|
||||
{
|
||||
Status = LdrCOFFProcessDriver(FileHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ZwClose(FileHandle);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
LdrProcessMZImage(HANDLE ProcessHandle,
|
||||
HANDLE FileHandle,
|
||||
PIMAGE_DOS_HEADER DosHeader)
|
||||
{
|
||||
|
||||
/* FIXME: map VDM into low memory */
|
||||
/* FIXME: Build/Load image sections */
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
LdrProcessPEImage(HANDLE ProcessHandle,
|
||||
HANDLE FileHandle,
|
||||
PIMAGE_DOS_HEADER DosHeader)
|
||||
{
|
||||
// PIMAGE_NT_HEADERS PEHeader;
|
||||
// PIMAGE_SECTION_HEADER Sections;
|
||||
|
||||
// FIXME: Check architechture
|
||||
// FIXME: Build/Load image sections
|
||||
// FIXME: do relocations code sections
|
||||
// FIXME: resolve imports
|
||||
// FIXME: do fixups
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Loads a PE executable into the specified process
|
||||
* ARGUMENTS:
|
||||
* Filename = File to load
|
||||
* ProcessHandle = handle
|
||||
* RETURNS: Status
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
LdrLoadImage(PUNICODE_STRING Filename, HANDLE ProcessHandle)
|
||||
{
|
||||
char BlockBuffer[512];
|
||||
NTSTATUS Status;
|
||||
ULONG SectionSize;
|
||||
HANDLE FileHandle;
|
||||
HANDLE ThreadHandle;
|
||||
OBJECT_ATTRIBUTES FileObjectAttributes;
|
||||
PIMAGE_DOS_HEADER PEDosHeader;
|
||||
CONTEXT Context;
|
||||
HANDLE SectionHandle;
|
||||
PVOID BaseAddress;
|
||||
|
||||
/* FIXME: should DLLs be named sections? */
|
||||
|
||||
/* Open the image file */
|
||||
InitializeObjectAttributes(&FileObjectAttributes,
|
||||
Filename,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenFile(&FileHandle, 0, &FileObjectAttributes, NULL, 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Read first block of image to determine type */
|
||||
Status = ZwReadFile(FileHandle, 0, 0, 0, 0, BlockBuffer, 512, 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ZwClose(FileHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* If MZ header exists */
|
||||
PEDosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
|
||||
if (PEDosHeader->e_magic == 0x54AD && PEDosHeader->e_lfanew != 0L)
|
||||
{
|
||||
Status = LdrProcessPEImage(ProcessHandle,
|
||||
FileHandle,
|
||||
PEDosHeader);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else if (PEDosHeader->e_magic == 0x54AD)
|
||||
{
|
||||
Status = LdrProcessMZImage(ProcessHandle,
|
||||
FileHandle,
|
||||
PEDosHeader);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else /* Assume bin format and load */
|
||||
/* FIXME: could check for a.out, ELF, COFF, etc. images here... */
|
||||
{
|
||||
FILE_STANDARD_INFORMATION FileStdInfo;
|
||||
|
||||
/* Get the size of the file for the section */
|
||||
Status = ZwQueryInformationFile(FileHandle,
|
||||
NULL,
|
||||
&FileStdInfo,
|
||||
sizeof(FileStdInfo),
|
||||
FileStandardInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ZwClose(FileHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Create the section for the code */
|
||||
Status = ZwCreateSection(&SectionHandle,
|
||||
SECTION_ALL_ACCESS,
|
||||
NULL,
|
||||
|
@ -152,26 +652,28 @@ LdrLoadImage(PUNICODE_STRING Filename, HANDLE ProcessHandle)
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* Map a view of the section into the desired process */
|
||||
BaseAddress = (PVOID)0x10000;
|
||||
SectionOffset.HighPart = 0;
|
||||
SectionOffset.LowPart = 0;
|
||||
SectionSize = GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize);
|
||||
Status = ZwMapViewOfSection(SectionHandle,
|
||||
ProcessHandle,
|
||||
&BaseAddress,
|
||||
0,
|
||||
SectionSize,
|
||||
NULL,
|
||||
&SectionSize,
|
||||
0,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* FIXME: destroy the section here */
|
||||
|
||||
/* FIXME: get the size of the file */
|
||||
Size = 0x8000;
|
||||
|
||||
ZwMapViewOfSection(SectionHandle,
|
||||
ProcessHandle,
|
||||
&BaseAddress,
|
||||
0,
|
||||
0x8000,
|
||||
&SectionOffset,
|
||||
&Size,
|
||||
0,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Setup the context for the initial thread */
|
||||
memset(&Context,0,sizeof(CONTEXT));
|
||||
|
||||
Context.SegSs = USER_DS;
|
||||
Context.Esp = 0x2000;
|
||||
Context.EFlags = 0x202;
|
||||
|
@ -182,46 +684,43 @@ LdrLoadImage(PUNICODE_STRING Filename, HANDLE ProcessHandle)
|
|||
Context.SegFs = USER_DS;
|
||||
Context.SegGs = USER_DS;
|
||||
|
||||
BaseAddress = 0x1000;
|
||||
StackSize = 0x1000;
|
||||
ZwAllocateVirtualMemory(ProcessHandle,
|
||||
&BaseAddress,
|
||||
0,
|
||||
&StackSize,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
ZwCreateThread(&ThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
ShellHandle,
|
||||
NULL,
|
||||
&Context,
|
||||
NULL,
|
||||
FALSE);
|
||||
/* Create the stack for the process */
|
||||
BaseAddress = (PVOID) 0x1000;
|
||||
SectionSize = 0x1000;
|
||||
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
||||
&BaseAddress,
|
||||
0,
|
||||
&SectionSize,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* FIXME: unmap the section here */
|
||||
/* FIXME: destroy the section here */
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Create the initial thread */
|
||||
Status = ZwCreateThread(&ThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
ProcessHandle,
|
||||
NULL,
|
||||
&Context,
|
||||
NULL,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* FIXME: destroy the stack memory block here */
|
||||
/* FIXME: unmap the section here */
|
||||
/* FIXME: destroy the section here */
|
||||
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
/* FIXME: {else} could check for a.out, ELF, COFF, etc. images here... */
|
||||
|
||||
/* FIXME: should DLLs be named sections? */
|
||||
/* FIXME: get current process and associate with section */
|
||||
|
||||
// Map the image into a section or die
|
||||
Status = ZwCreateSection(&SectionHandle,
|
||||
SECTION_MAP_READ,
|
||||
NULL,
|
||||
NULL,
|
||||
PAGE_READONLY,
|
||||
SEC_IMAGE,
|
||||
FileHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
// FIXME: get the base address of the section
|
||||
|
||||
ZwCloseFile(FileHandle);
|
||||
|
||||
// FIXME: initialize process context for image
|
||||
|
||||
return LdrProcessImage(SectionHandle, BaseAddress);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
|
||||
#ifndef PWORD
|
||||
typedef WORD *PWORD;
|
||||
#endif
|
||||
|
||||
#ifndef PDWORD
|
||||
typedef DWORD *PDWORD;
|
||||
#endif
|
||||
|
||||
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
|
||||
WORD e_magic; // Magic number
|
||||
WORD e_cblp; // Bytes on last page of file
|
||||
|
@ -329,15 +338,15 @@ typedef struct _IMAGE_NORMAL_MENU_ITEM{
|
|||
WCHAR szItemText[1];
|
||||
} IMAGE_NORMAL_MENU_ITEM, *PIMAGE_NORMAL_MENU_ITEM;
|
||||
|
||||
#define GRAYED 0x0001 // GRAYED keyword
|
||||
#define INACTIVE 0x0002 // INACTIVE keyword
|
||||
#define BITMAP 0x0004 // BITMAP keyword
|
||||
#define OWNERDRAW 0x0100 // OWNERDRAW keyword
|
||||
#define CHECKED 0x0008 // CHECKED keyword
|
||||
#define POPUP 0x0010 // used internally
|
||||
#define MENUBARBREAK 0x0020 // MENUBARBREAK keyword
|
||||
#define MENUBREAK 0x0040 // MENUBREAK keyword
|
||||
#define ENDMENU 0x0080 // used internally
|
||||
#define MI_GRAYED 0x0001 // GRAYED keyword
|
||||
#define MI_INACTIVE 0x0002 // INACTIVE keyword
|
||||
#define MI_BITMAP 0x0004 // BITMAP keyword
|
||||
#define MI_OWNERDRAW 0x0100 // OWNERDRAW keyword
|
||||
#define MI_CHECKED 0x0008 // CHECKED keyword
|
||||
#define MI_POPUP 0x0010 // used internally
|
||||
#define MI_MENUBARBREAK 0x0020 // MENUBARBREAK keyword
|
||||
#define MI_MENUBREAK 0x0040 // MENUBREAK keyword
|
||||
#define MI_ENDMENU 0x0080 // used internally
|
||||
|
||||
|
||||
// Dialog Box Resources .................. added by sang cho.
|
||||
|
|
|
@ -1,29 +1,20 @@
|
|||
all: kimage
|
||||
|
||||
CC_OBJECTS = cc/cacheman.o cc/block.o
|
||||
|
||||
CM_OBJECTS = cm/registry.o
|
||||
|
||||
DBG_OBJECTS = dbg/brkpoint.o
|
||||
|
||||
EX_OBJECTS = ex/work.o ex/fmutex.o ex/resource.o ex/time.o ex/interlck.o \
|
||||
ex/callback.o ex/napi.o ex/power.o ex/sysinfo.o ex/locale.o \
|
||||
ex/stamp.o
|
||||
|
||||
#
|
||||
# Defines $(HAL_OBJECTS)
|
||||
#
|
||||
include hal/x86/sources
|
||||
|
||||
NT_OBJECTS = nt/port.o nt/channel.o nt/ntevent.o nt/nttimer.o nt/atom.o \
|
||||
nt/evtpair.o nt/ntsem.o nt/mutant.o nt/misc.o nt/plugplay.o \
|
||||
nt/profile.o
|
||||
|
||||
RTL_OBJECTS = rtl/vsprintf.o rtl/lookas.o rtl/unicode.o rtl/strtok.o \
|
||||
rtl/time.o rtl/unalign.o rtl/mem.o rtl/largeint.o rtl/ctype.o \
|
||||
rtl/list.o rtl/slist.o rtl/interlck.o rtl/return.o \
|
||||
rtl/wstring.o
|
||||
|
||||
KE_OBJECTS = ke/main.o ke/timer.o ke/error.o ke/catch.o ke/exports.o \
|
||||
ke/module.o ke/dpc.o ke/wait.o ke/kqueue.o ke/dispatch.o \
|
||||
ke/sem.o ke/critical.o ke/event.o ke/apc.o ke/bug.o \
|
||||
ke/mutex.o ke/kernel.o ke/ldt.o ke/apchelp.o
|
||||
|
||||
MM_OBJECTS = mm/mm.o mm/freelist.o mm/pool.o mm/virtual.o \
|
||||
mm/mdl.o mm/zone.o mm/special.o mm/paging.o \
|
||||
mm/section.o mm/marea.o mm/ppool.o mm/npool.o
|
||||
|
||||
|
||||
IO_OBJECTS = io/iomgr.o io/create.o io/irp.o io/device.o io/rw.o \
|
||||
io/queue.o io/drvlck.o io/timer.o io/share.o io/errlog.o \
|
||||
io/shutdown.o io/fdisk.o io/cancel.o io/error.o io/arc.o \
|
||||
|
@ -32,26 +23,46 @@ IO_OBJECTS = io/iomgr.o io/create.o io/irp.o io/device.o io/rw.o \
|
|||
io/fs.o io/vpb.o io/buildirp.o io/flush.o io/dir.o io/iocomp.o \
|
||||
io/mailslot.o io/npipe.o io/lock.o io/page.o io/cleanup.o
|
||||
|
||||
KE_OBJECTS = ke/main.o ke/timer.o ke/error.o ke/catch.o ke/exports.o \
|
||||
ke/module.o ke/dpc.o ke/wait.o ke/kqueue.o ke/dispatch.o \
|
||||
ke/sem.o ke/critical.o ke/event.o ke/apc.o ke/bug.o \
|
||||
ke/mutex.o ke/kernel.o ke/ldt.o ke/apchelp.o
|
||||
|
||||
LDR_OBJECTS = ldr/loader.o
|
||||
|
||||
MM_OBJECTS = mm/mm.o mm/freelist.o mm/pool.o mm/virtual.o \
|
||||
mm/mdl.o mm/zone.o mm/special.o mm/paging.o \
|
||||
mm/section.o mm/marea.o mm/ppool.o mm/npool.o
|
||||
|
||||
NT_OBJECTS = nt/port.o nt/channel.o nt/ntevent.o nt/nttimer.o nt/atom.o \
|
||||
nt/evtpair.o nt/ntsem.o nt/mutant.o nt/misc.o nt/plugplay.o \
|
||||
nt/profile.o
|
||||
|
||||
OB_OBJECTS = ob/object.o ob/handle.o ob/namespc.o
|
||||
|
||||
PS_OBJECTS = ps/psmgr.o ps/thread.o ps/process.o ps/idle.o ps/kill.o \
|
||||
ps/tinfo.o
|
||||
|
||||
EX_OBJECTS = ex/work.o ex/fmutex.o ex/resource.o ex/time.o ex/interlck.o \
|
||||
ex/callback.o ex/napi.o ex/power.o ex/sysinfo.o ex/locale.o \
|
||||
ex/stamp.o
|
||||
RTL_OBJECTS = rtl/vsprintf.o rtl/lookas.o rtl/unicode.o rtl/strtok.o \
|
||||
rtl/time.o rtl/unalign.o rtl/mem.o rtl/largeint.o rtl/ctype.o \
|
||||
rtl/list.o rtl/slist.o rtl/interlck.o rtl/return.o \
|
||||
rtl/wstring.o
|
||||
|
||||
SE_OBJECTS = se/semgr.o
|
||||
|
||||
CM_OBJECTS = cm/registry.o
|
||||
|
||||
TST_OBJECTS = tst/test.o tst/sshell.o tst/readline.o
|
||||
|
||||
DBG_OBJECTS = dbg/brkpoint.o
|
||||
objects/cc.o: $(CC_OBJECTS)
|
||||
$(LD) -r $(CC_OBJECTS) -o objects/cc.o
|
||||
|
||||
LDR_OBJECTS = ldr/loader.o
|
||||
objects/cm.o: $(CM_OBJECTS)
|
||||
$(LD) -r $(CM_OBJECTS) -o objects/cm.o
|
||||
|
||||
CC_OBJECTS = cc/cacheman.o cc/block.o
|
||||
objects/dbg.o: $(DBG_OBJECTS)
|
||||
$(LD) -r $(DBG_OBJECTS) -o objects/dbg.o
|
||||
|
||||
objects/ex.o: $(EX_OBJECTS)
|
||||
$(LD) -r $(EX_OBJECTS) -o objects/ex.o
|
||||
|
||||
objects/hal.o: $(HAL_OBJECTS)
|
||||
$(LD) -r $(HAL_OBJECTS) -o objects/hal.o
|
||||
|
@ -59,47 +70,37 @@ objects/hal.o: $(HAL_OBJECTS)
|
|||
objects/io.o: $(IO_OBJECTS)
|
||||
$(LD) -r $(IO_OBJECTS) -o objects/io.o
|
||||
|
||||
objects/ldr.o: $(LDR_OBJECTS)
|
||||
$(LD) -r $(LDR_OBJECTS) -o objects/ldr.o
|
||||
|
||||
objects/ke.o: $(KE_OBJECTS)
|
||||
$(LD) -r $(KE_OBJECTS) -o objects/ke.o
|
||||
|
||||
objects/rtl.o: $(RTL_OBJECTS)
|
||||
$(LD) -r $(RTL_OBJECTS) -o objects/rtl.o
|
||||
|
||||
objects/mm.o: $(MM_OBJECTS)
|
||||
$(LD) -r $(MM_OBJECTS) -o objects/mm.o
|
||||
|
||||
objects/nt.o: $(NT_OBJECTS)
|
||||
$(LD) -r $(NT_OBJECTS) -o objects/nt.o
|
||||
|
||||
objects/ob.o: $(OB_OBJECTS)
|
||||
$(LD) -r $(OB_OBJECTS) -o objects/ob.o
|
||||
|
||||
objects/ps.o: $(PS_OBJECTS)
|
||||
$(LD) -r $(PS_OBJECTS) -o objects/ps.o
|
||||
|
||||
objects/ex.o: $(EX_OBJECTS)
|
||||
$(LD) -r $(EX_OBJECTS) -o objects/ex.o
|
||||
objects/rtl.o: $(RTL_OBJECTS)
|
||||
$(LD) -r $(RTL_OBJECTS) -o objects/rtl.o
|
||||
|
||||
objects/se.o: $(SE_OBJECTS)
|
||||
$(LD) -r $(SE_OBJECTS) -o objects/se.o
|
||||
|
||||
objects/cm.o: $(CM_OBJECTS)
|
||||
$(LD) -r $(CM_OBJECTS) -o objects/cm.o
|
||||
|
||||
objects/tst.o: $(TST_OBJECTS)
|
||||
$(LD) -r $(TST_OBJECTS) -o objects/tst.o
|
||||
|
||||
objects/dbg.o: $(DBG_OBJECTS)
|
||||
$(LD) -r $(DBG_OBJECTS) -o objects/dbg.o
|
||||
|
||||
objects/nt.o: $(NT_OBJECTS)
|
||||
$(LD) -r $(NT_OBJECTS) -o objects/nt.o
|
||||
|
||||
objects/cc.o: $(CC_OBJECTS)
|
||||
$(LD) -r $(CC_OBJECTS) -o objects/cc.o
|
||||
|
||||
OBJECTS = objects/hal.o objects/ke.o objects/rtl.o objects/mm.o \
|
||||
objects/io.o objects/ob.o objects/ps.o objects/ex.o \
|
||||
objects/se.o objects/cm.o objects/tst.o objects/dbg.o\
|
||||
objects/nt.o objects/cc.o
|
||||
|
||||
OBJECTS = objects/cc.o objects/cm.o objects/dbg.o objects/ex.o \
|
||||
objects/hal.o objects/io.o objects/ke.o objects/ldr.o \
|
||||
objects/mm.o objects/nt.o objects/ob.o objects/ps.o objects/rtl.o \
|
||||
objects/se.o objects/tst.o
|
||||
|
||||
utils/export/export$(EXE_POSTFIX): utils/export/export.c
|
||||
$(NATIVE_CC) -g utils/export/export.c -o utils/export/export$(EXE_POSTFIX)
|
||||
|
@ -124,4 +125,7 @@ ex/napi.o: ex/napi.c ../include/ntdll/napi.h
|
|||
|
||||
WITH_DEBUGGING = yes
|
||||
WIN32_LEAN_AND_MEAN = yes
|
||||
|
||||
include ../rules.mak
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue