From 52ca8cd3ce40f11dd846739da6c017db0430e1c1 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 2 Apr 2008 20:40:27 +0200 Subject: [PATCH] winedevice: Apply relocations to the driver in cases where the loader doesn't do it. --- programs/winedevice/device.c | 51 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c index 5e9c322f562..d48017af335 100644 --- a/programs/winedevice/device.c +++ b/programs/winedevice/device.c @@ -18,6 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "config.h" +#include "wine/port.h" + #include #include "ntstatus.h" @@ -58,6 +61,52 @@ static LDR_MODULE *find_ldr_module( HMODULE module ) return NULL; } +/* load the driver module file */ +static HMODULE load_driver_module( const WCHAR *name ) +{ + const IMAGE_NT_HEADERS *nt; + size_t page_size = getpagesize(); + int delta; + HMODULE module = LoadLibraryW( name ); + + if (!module) return NULL; + nt = RtlImageNtHeader( module ); + + if (!(delta = (char *)module - (char *)nt->OptionalHeader.ImageBase)) return module; + + /* the loader does not apply relocations to non page-aligned binaries or executables, + * we have to do it ourselves */ + + if (nt->OptionalHeader.SectionAlignment < page_size || + !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) + { + ULONG size; + DWORD old; + IMAGE_BASE_RELOCATION *rel, *end; + + if ((rel = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size ))) + { + WINE_TRACE( "%s: relocating from %p to %p\n", + wine_dbgstr_w(name), (char *)module - delta, module ); + end = (IMAGE_BASE_RELOCATION *)((char *)rel + size); + while (rel < end && rel->SizeOfBlock) + { + void *page = (char *)module + rel->VirtualAddress; + VirtualProtect( page, page_size, PAGE_EXECUTE_READWRITE, &old ); + rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT), + (USHORT *)(rel + 1), delta ); + if (old != PAGE_EXECUTE_READWRITE) VirtualProtect( page, page_size, old, NULL ); + if (!rel) goto error; + } + } + } + return module; + +error: + FreeLibrary( module ); + return NULL; +} + /* call the driver init entry point */ static NTSTATUS init_driver( HMODULE module, UNICODE_STRING *keyname ) { @@ -146,7 +195,7 @@ static BOOL load_driver(void) WINE_TRACE( "loading driver %s\n", wine_dbgstr_w(str) ); - module = LoadLibraryW( str ); + module = load_driver_module( str ); HeapFree( GetProcessHeap(), 0, path ); if (!module) return FALSE; -- 2.11.4.GIT