Do builtin modules fixups in library/loader.c before calling the
load_dll callback.

diff --git a/library/loader.c b/library/loader.c
index 95922d0..4d202ac 100644
--- a/library/loader.c
+++ b/library/loader.c
@@ -11,13 +11,17 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
-
+#include <unistd.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
 #ifdef HAVE_DL_API
 #include <dlfcn.h>
 #endif
 
-#include "windef.h"
+#include "winnt.h"
 #include "wine/library.h"
+#include "wine/port.h"
 
 #define MAX_DLLS 100
 
@@ -116,6 +120,151 @@
 }
 
 
+/* adjust an array of pointers to make them into RVAs */
+static inline void fixup_rva_ptrs( void *array, void *base, int count )
+{
+    void **ptr = (void **)array;
+    while (count--)
+    {
+        if (*ptr) *ptr = (void *)((char *)*ptr - (char *)base);
+        ptr++;
+    }
+}
+
+
+/* fixup RVAs in the resource directory */
+static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *base )
+{
+    IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
+    int i;
+
+    entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
+    for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++)
+    {
+        void *ptr = root + entry->u2.s.OffsetToDirectory;
+        if (entry->u2.s.DataIsDirectory) fixup_resources( ptr, root, base );
+        else
+        {
+            IMAGE_RESOURCE_DATA_ENTRY *data = ptr;
+            fixup_rva_ptrs( &data->OffsetToData, base, 1 );
+        }
+    }
+}
+
+
+/* map a builtin dll in memory and fixup RVAs */
+static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
+{
+    IMAGE_DATA_DIRECTORY *dir;
+    IMAGE_DOS_HEADER *dos;
+    IMAGE_NT_HEADERS *nt;
+    IMAGE_SECTION_HEADER *sec;
+    BYTE *addr, *code_start, *data_start;
+    size_t page_size = getpagesize();
+    int nb_sections = 2;  /* code + data */
+
+    size_t size = (sizeof(IMAGE_DOS_HEADER)
+                   + sizeof(IMAGE_NT_HEADERS)
+                   + nb_sections * sizeof(IMAGE_SECTION_HEADER));
+
+    assert( size <= page_size );
+
+    if (nt_descr->OptionalHeader.ImageBase)
+    {
+        addr = wine_anon_mmap( (void *)nt_descr->OptionalHeader.ImageBase,
+                               page_size, PROT_READ|PROT_WRITE, MAP_FIXED );
+        if (addr != (BYTE *)nt_descr->OptionalHeader.ImageBase) return NULL;
+    }
+    else
+    {
+        /* this will leak memory; but it should never happen */
+        addr = wine_anon_mmap( NULL, page_size, PROT_READ|PROT_WRITE, 0 );
+        if (addr == (BYTE *)-1) return NULL;
+    }
+
+    dos    = (IMAGE_DOS_HEADER *)addr;
+    nt     = (IMAGE_NT_HEADERS *)(dos + 1);
+    sec    = (IMAGE_SECTION_HEADER *)(nt + 1);
+    code_start = addr + page_size;
+
+    /* HACK! */
+    data_start = code_start + page_size;
+
+    /* Build the DOS and NT headers */
+
+    dos->e_magic  = IMAGE_DOS_SIGNATURE;
+    dos->e_lfanew = sizeof(*dos);
+
+    *nt = *nt_descr;
+
+    nt->FileHeader.NumberOfSections                = nb_sections;
+    nt->OptionalHeader.SizeOfCode                  = data_start - code_start;
+    nt->OptionalHeader.SizeOfInitializedData       = 0;
+    nt->OptionalHeader.SizeOfUninitializedData     = 0;
+    nt->OptionalHeader.ImageBase                   = (DWORD)addr;
+
+    fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
+
+    /* Build the code section */
+
+    strcpy( sec->Name, ".text" );
+    sec->SizeOfRawData = data_start - code_start;
+    sec->Misc.VirtualSize = sec->SizeOfRawData;
+    sec->VirtualAddress   = code_start - addr;
+    sec->PointerToRawData = code_start - addr;
+    sec->Characteristics  = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
+    sec++;
+
+    /* Build the data section */
+
+    strcpy( sec->Name, ".data" );
+    sec->SizeOfRawData = 0;
+    sec->Misc.VirtualSize = sec->SizeOfRawData;
+    sec->VirtualAddress   = data_start - addr;
+    sec->PointerToRawData = data_start - addr;
+    sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
+                             IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
+    sec++;
+
+    /* Build the import directory */
+
+    dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
+    if (dir->Size)
+    {
+        IMAGE_IMPORT_DESCRIPTOR *imports = (void *)dir->VirtualAddress;
+        fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
+        /* we can fixup everything at once since we only have pointers and 0 values */
+        fixup_rva_ptrs( imports, addr, dir->Size / sizeof(void*) );
+    }
+
+    /* Build the resource directory */
+
+    dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
+    if (dir->Size)
+    {
+        void *ptr = (void *)dir->VirtualAddress;
+        fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
+        fixup_resources( ptr, ptr, addr );
+    }
+
+    /* Build the export directory */
+
+    dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
+    if (dir->Size)
+    {
+        IMAGE_EXPORT_DIRECTORY *exports = (void *)dir->VirtualAddress;
+        fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
+        fixup_rva_ptrs( (void *)exports->AddressOfFunctions, addr, exports->NumberOfFunctions );
+        fixup_rva_ptrs( (void *)exports->AddressOfNames, addr, exports->NumberOfNames );
+        fixup_rva_ptrs( &exports->Name, addr, 1 );
+        fixup_rva_ptrs( &exports->AddressOfFunctions, addr, 1 );
+        fixup_rva_ptrs( &exports->AddressOfNames, addr, 1 );
+        fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1 );
+    }
+    return addr;
+}
+
+
 /***********************************************************************
  *           __wine_dll_register
  *
@@ -123,7 +272,7 @@
  */
 void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename )
 {
-    if (load_dll_callback) load_dll_callback( header, filename );
+    if (load_dll_callback) load_dll_callback( map_dll(header), filename );
     else
     {
         if (!(header->FileHeader.Characteristics & IMAGE_FILE_DLL))
@@ -154,10 +303,10 @@
         const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
         if (!nt) continue;
         builtin_dlls[i].nt = NULL;
-        load_dll_callback( nt, builtin_dlls[i].filename );
+        load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
     }
     nb_dlls = 0;
-    if (main_exe) load_dll_callback( main_exe, "" );
+    if (main_exe) load_dll_callback( map_dll(main_exe), "" );
 }
 
 
@@ -182,7 +331,7 @@
         {
             const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
             builtin_dlls[i].nt = NULL;
-            load_dll_callback( nt, builtin_dlls[i].filename );
+            load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
             return (void *)1;
         }
     }