Convert to unix line endings.
[wincetools.git] / loader / ntdll_loader.c
index f5ee763..4d4115d 100644 (file)
-/* From wine1.2-1.1.42/dlls/ntdll/loader.c  */\r
-\r
-/*\r
- * Loader functions\r
- *\r
- * Copyright 1995, 2003 Alexandre Julliard\r
- * Copyright 2002 Dmitry Timoshkov for CodeWeavers\r
- * Copyright 2010 g10 Code GmbH\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA\r
- */\r
-\r
-\r
-\r
-#include <assert.h>\r
-\r
-#undef USE_DLMALLOC\r
-#ifdef USE_DLMALLOC\r
-#include "dlmalloc.h"\r
-#endif\r
-\r
-#include "wine.h"\r
-\r
-/* convert PE image VirtualAddress to Real Address */\r
-static void *get_rva( HMODULE module, DWORD va )\r
-{\r
-  return (void *)((char *)module + va);\r
-}\r
-\r
-\r
-#define USE_HIMEMCE_MAP\r
-#ifdef USE_HIMEMCE_MAP\r
-/* Support for DLL loading.  */\r
-\r
-#include "himemce-map.h"\r
-\r
-static int himemce_map_initialized;\r
-static struct himemce_map *himemce_map;\r
-int himemce_mod_loaded[HIMEMCE_MAP_MAX_MODULES];\r
-\r
-static void\r
-himemce_map_init ()\r
-{\r
-  void *ptr;\r
-  /* Only try once.  */\r
-  if (himemce_map_initialized)\r
-         return;\r
-  himemce_map_initialized = 1;\r
+/* From wine1.2-1.1.42/dlls/ntdll/loader.c  */
+
+/*
+ * Loader functions
+ *
+ * Copyright 1995, 2003 Alexandre Julliard
+ * Copyright 2002 Dmitry Timoshkov for CodeWeavers
+ * Copyright 2010 g10 Code GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+
+#include <assert.h>
+
+#undef USE_DLMALLOC
+#ifdef USE_DLMALLOC
+#include "dlmalloc.h"
+#endif
+
+#include "wine.h"
+
+/* convert PE image VirtualAddress to Real Address */
+static void *get_rva( HMODULE module, DWORD va )
+{
+  return (void *)((char *)module + va);
+}
+
+
+#define USE_HIMEMCE_MAP
+#ifdef USE_HIMEMCE_MAP
+/* Support for DLL loading.  */
+
+#include "himemce-map.h"
+
+static int himemce_map_initialized;
+static struct himemce_map *himemce_map;
+int himemce_mod_loaded[HIMEMCE_MAP_MAX_MODULES];
+
+static void
+himemce_map_init ()
+{
+  void *ptr;
+  /* Only try once.  */
+  if (himemce_map_initialized)
+         return;
+  himemce_map_initialized = 1;
   himemce_map = himemce_map_open ();
   if (! himemce_map)
     {
                TRACE ("can not open himemce map\n");
-        return;\r
-    }\r
-  TRACE ("himemce map found at %p (reserving 0x%x bytes at %p)\n", himemce_map,\r
-         himemce_map->low_start, himemce_map->low_size);\r
-  ptr = VirtualAlloc(himemce_map->low_start, himemce_map->low_size,\r
-           MEM_RESERVE, PAGE_EXECUTE_READWRITE);\r
-  if (! ptr)\r
-  {\r
-         TRACE ("failed to reserve memory: %i\n", GetLastError ());\r
-         himemce_map_close (himemce_map);\r
-         himemce_map = NULL;\r
-      return;\r
-  }\r
-}\r
-\r
-\r
-# define page_mask  0xfff\r
-# define page_shift 12\r
-# define page_size  0x1000\r
-\r
-#define ROUND_SIZE(size) \\r
-  (((SIZE_T)(size) + page_mask) & ~page_mask)\r
-\r
-static SIZE_T\r
-section_size (IMAGE_SECTION_HEADER *sec)\r
-{\r
-  static const SIZE_T sector_align = 0x1ff;\r
-  SIZE_T map_size, file_size, end;\r
-\r
-  if (!sec->Misc.VirtualSize)\r
-    map_size = ROUND_SIZE( sec->SizeOfRawData );\r
-  else\r
-    map_size = ROUND_SIZE( sec->Misc.VirtualSize );\r
-\r
-  file_size = (sec->SizeOfRawData + (sec->PointerToRawData & sector_align) + sector_align) & ~sector_align;\r
-  if (file_size > map_size) file_size = map_size;\r
-  end = ROUND_SIZE( file_size );\r
-  if (end > map_size) end = map_size;\r
-  return end;\r
-}\r
-\r
-\r
-/* Returns the base of the module after loading it, if necessary.\r
-   NULL if not found, -1 if a fatal error occurs.  */\r
-void *\r
-himemce_map_load_dll (const char *name)\r
-{\r
-  struct himemce_module *mod;\r
-  int modidx;\r
-  char *ptr;\r
-  IMAGE_DOS_HEADER *dos;\r
-  IMAGE_NT_HEADERS *nt;\r
-  IMAGE_SECTION_HEADER *sec;\r
-  int sec_cnt;\r
-  int idx;\r
-  const IMAGE_IMPORT_DESCRIPTOR *imports;\r
-  DWORD imports_size;\r
-\r
-  himemce_map_init ();\r
-  if (! himemce_map)\r
-         return NULL;\r
-\r
-  mod = himemce_map_find_module (himemce_map, name);\r
-  if (!mod)\r
-         return NULL;\r
-  modidx = mod - himemce_map->module;\r
-  if (himemce_mod_loaded[modidx])\r
-         return mod->base;\r
-\r
-  /* First map the sections low.  */\r
-  ptr = mod->base;\r
-  dos = (IMAGE_DOS_HEADER *) ptr;\r
-  nt = (IMAGE_NT_HEADERS *) (ptr + dos->e_lfanew);\r
-  sec = (IMAGE_SECTION_HEADER *) ((char*) &nt->OptionalHeader\r
-                                  + nt->FileHeader.SizeOfOptionalHeader);\r
-  sec_cnt = nt->FileHeader.NumberOfSections;\r
-  for (idx = 0; idx < sec_cnt; idx++)\r
-  {\r
-       size_t secsize;\r
-       char *secptr;\r
-\r
-       if (! sec[idx].PointerToLinenumbers)\r
-         continue;\r
-       secsize = section_size (&sec[idx]);\r
-    secptr = VirtualAlloc ((void *) sec[idx].PointerToLinenumbers,\r
-               secsize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
-       if (! secptr)\r
-       {\r
-               TRACE ("could not allocate 0x%x bytes of low memory at %p: %i\n",\r
-                       secsize, sec[idx].PointerToLinenumbers, GetLastError ());\r
-               return (void *) -1;\r
-       }\r
-    memcpy (secptr, ptr + sec[idx].VirtualAddress, secsize);\r
-  }\r
-\r
-  /* To break circles, we claim that we loaded before recursing.  */\r
-  himemce_mod_loaded[modidx]++;\r
-  imports = MyRtlImageDirectoryEntryToData ((HMODULE) ptr, TRUE,\r
-                                            IMAGE_DIRECTORY_ENTRY_IMPORT,\r
-                                            &imports_size);\r
-  if (imports)\r
-  {\r
-       idx = 0;\r
-       while (imports[idx].Name && imports[idx].FirstThunk)\r
-       {\r
-               char *iname = ptr + imports[idx].Name;\r
-               void *ibase;\r
-\r
-               /* Recursion!  */\r
-               ibase = himemce_map_load_dll (iname);\r
-               if (ibase == (void *) -1)\r
-                       return (void *) -1;\r
-               /* Nothing to do if ibase !=0: Successful loading of high DLL.  */\r
-               if (ibase == 0)\r
-               {\r
-                       ibase = LoadLibrary (iname);\r
-                       if (!ibase)\r
-                       {\r
-                               TRACE ("Could not find %s, dependency of %s\n", iname, name);\r
-                               return (void *) -1;\r
-                       }\r
-               }\r
-               idx++;\r
-       }\r
-  }\r
-  return ptr;\r
-}\r
-\r
-\r
-static void *\r
-get_rva_low (char *module, size_t rva)\r
-{\r
-  IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)module;\r
-  IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(module + dos->e_lfanew);\r
-  IMAGE_SECTION_HEADER *sec;\r
-  int sec_cnt;\r
-  int idx;\r
-\r
-  sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeO\\r
-fOptionalHeader);\r
-  sec_cnt = nt->FileHeader.NumberOfSections;\r
-\r
-  for (idx = 0; idx < sec_cnt; idx++)\r
-    {\r
-      if (! sec[idx].PointerToLinenumbers)\r
-        continue;\r
-      if (rva >= sec[idx].VirtualAddress\r
-          && rva < sec[idx].VirtualAddress + section_size (&sec[idx]))\r
-                break;\r
-    }\r
-  if (idx == sec_cnt)\r
-    return (void *)((char *)module + rva);\r
-\r
-  return (void *)((char *)sec[idx].PointerToLinenumbers\r
-                  + (rva - sec[idx].VirtualAddress));\r
-}\r
-\r
-\r
-static FARPROC\r
-find_ordinal_export (void *module, const IMAGE_EXPORT_DIRECTORY *exports,\r
-                     DWORD exp_size, DWORD ordinal, LPCWSTR load_path)\r
-{\r
-  FARPROC proc;\r
-  const DWORD *functions = get_rva (module, exports->AddressOfFunctions);\r
-\r
-  if (ordinal >= exports->NumberOfFunctions)\r
-    {\r
-      TRACE(" ordinal %d out of range!\n", ordinal + exports->Base );\r
-      return NULL;\r
-    }\r
-  if (!functions[ordinal]) return NULL;\r
-\r
-#if 0\r
-  /* if the address falls into the export dir, it's a forward */\r
-  if (((const char *)proc >= (const char *)exports) &&\r
-      ((const char *)proc < (const char *)exports + exp_size))\r
-    return find_forwarded_export( module, (const char *)proc, load_path );\r
-#endif\r
-\r
-  proc = get_rva_low (module, functions[ordinal]);\r
-  return proc;\r
-}\r
-\r
-static FARPROC\r
-find_named_export (void *module, const IMAGE_EXPORT_DIRECTORY *exports,\r
-                   DWORD exp_size, const char *name, int hint, LPCWSTR load_path)\r
-{\r
-  const WORD *ordinals = get_rva (module, exports->AddressOfNameOrdinals);\r
-  const DWORD *names = get_rva (module, exports->AddressOfNames);\r
-  int min = 0, max = exports->NumberOfNames - 1;\r
-\r
-  /* first check the hint */\r
-  if (hint >= 0 && hint <= max)\r
-    {\r
-      char *ename = get_rva( module, names[hint] );\r
-      if (!strcmp( ename, name ))\r
-        return find_ordinal_export( module, exports, exp_size, ordinals[hint], load_path);\r
-    }\r
-\r
-  /* then do a binary search */\r
-  while (min <= max)\r
-    {\r
-      int res, pos = (min + max) / 2;\r
-      char *ename = get_rva( module, names[pos] );\r
-      if (!(res = strcmp( ename, name )))\r
-        return find_ordinal_export( module, exports, exp_size, ordinals[pos], load_path);\r
-      if (res > 0) max = pos - 1;\r
-      else min = pos + 1;\r
-    }\r
-  return NULL;\r
-}\r
-\r
-#endif\r
-\r
-\r
-PIMAGE_NT_HEADERS MyRtlImageNtHeader(HMODULE hModule)\r
-{\r
-    IMAGE_NT_HEADERS *ret;\r
-    IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;\r
-\r
-    ret = NULL;\r
-    if (dos->e_magic == IMAGE_DOS_SIGNATURE)\r
-    {\r
-        ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);\r
-        if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;\r
-    }\r
-    return ret;\r
-}\r
-\r
-\f\r
-/* internal representation of 32bit modules. per process. */\r
-typedef struct _wine_modref\r
-{\r
-    LDR_MODULE            ldr;\r
-    int                   nDeps;\r
-    struct _wine_modref **deps;\r
-} WINE_MODREF;\r
-\r
-/* FIXME: cmp with himemce-map.h */\r
-#define MAX_MODREFS 64\r
-WINE_MODREF *modrefs[MAX_MODREFS];\r
-int nr_modrefs;\r
-\r
-\r
-static WINE_MODREF *current_modref;\r
-\r
-\r
-/* convert from straight ASCII to Unicode without depending on the current codepage */\r
-static void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )\r
-{\r
-  while (len--) *dst++ = (unsigned char)*src++;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- *           RtlImageDirectoryEntryToData   (NTDLL.@)\r
- */\r
-PVOID MyRtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir, ULONG *size )\r
-{\r
-  const IMAGE_NT_HEADERS *nt;\r
-  DWORD addr;\r
-\r
-  if ((ULONG_PTR)module & 1)  /* mapped as data file */\r
-    {\r
-      module = (HMODULE)((ULONG_PTR)module & ~1);\r
-      image = FALSE;\r
-    }\r
-  if (!(nt = MyRtlImageNtHeader( module ))) return NULL;\r
-  if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)\r
-    {\r
-      const IMAGE_NT_HEADERS64 *nt64 = (const IMAGE_NT_HEADERS64 *)nt;\r
-\r
-      if (dir >= nt64->OptionalHeader.NumberOfRvaAndSizes) return NULL;\r
-      if (!(addr = nt64->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;\r
-      *size = nt64->OptionalHeader.DataDirectory[dir].Size;\r
-      if (image || addr < nt64->OptionalHeader.SizeOfHeaders) return (char *)module + addr;\r
-    }\r
-  else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)\r
-    {\r
-      const IMAGE_NT_HEADERS32 *nt32 = (const IMAGE_NT_HEADERS32 *)nt;\r
-\r
-      if (dir >= nt32->OptionalHeader.NumberOfRvaAndSizes) return NULL;\r
-      if (!(addr = nt32->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;\r
-      *size = nt32->OptionalHeader.DataDirectory[dir].Size;\r
-      if (image || addr < nt32->OptionalHeader.SizeOfHeaders) return (char *)module + addr;\r
-    }\r
-  else return NULL;\r
-\r
-#if 0\r
-  /* not mapped as image, need to find the section containing the virtual address */\r
-  return RtlImageRvaToVa( nt, module, addr, NULL );\r
-#else\r
-  return NULL;\r
-#endif\r
-}\r
-\r
-\r
-#define allocate_stub(x,y) (0xdeadbeef)\r
-\r
-/*************************************************************************\r
- *              import_dll\r
- *\r
- * Import the dll specified by the given import descriptor.\r
- * The loader_section must be locked while calling this function.\r
- */\r
-static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path )\r
-{\r
-  NTSTATUS status = STATUS_SUCCESS;\r
-  //  WINE_MODREF *wmImp;\r
-  HMODULE imp_mod;\r
-#ifdef USE_HIMEMCE_MAP\r
-  void *imp_base = 0;\r
-  const IMAGE_EXPORT_DIRECTORY *exports;\r
-  DWORD exp_size;\r
-#endif\r
-  const IMAGE_THUNK_DATA *import_list;\r
-  IMAGE_THUNK_DATA *thunk_list;\r
-  WCHAR buffer[32];\r
-  const char *name = get_rva( module, descr->Name );\r
-  DWORD len = strlen(name);\r
-#if 0\r
-  PVOID protect_base;\r
-  SIZE_T protect_size = 0;\r
-  DWORD protect_old;\r
-#endif\r
-#ifdef USE_DLMALLOC\r
-  int iscoredll = 0;\r
-#endif\r
-\r
-  thunk_list = get_rva( module, (DWORD)descr->FirstThunk );\r
-  if (descr->OriginalFirstThunk)\r
-    import_list = get_rva( module, (DWORD)descr->OriginalFirstThunk );\r
-  else\r
-    import_list = thunk_list;\r
-\r
-  while (len && name[len-1] == ' ') len--;  /* remove trailing spaces */\r
-\r
-#ifdef USE_DLMALLOC\r
-  if (! _stricmp (name, "coredll.dll"))\r
-    iscoredll = 1;\r
-#endif\r
-\r
-#ifdef USE_HIMEMCE_MAP\r
-  imp_base = himemce_map_load_dll (name);\r
-  if (imp_base == (void *) -1)\r
-    status = GetLastError ();\r
-  if (imp_base)\r
-    goto loaded;\r
-#endif\r
-\r
-  if (len * sizeof(WCHAR) < sizeof(buffer))\r
-    {\r
-      ascii_to_unicode( buffer, name, len );\r
-      buffer[len] = 0;\r
-      //      status = load_dll( load_path, buffer, 0, &wmImp );\r
-      imp_mod = LoadLibrary (buffer);\r
-         if (imp_mod == INVALID_HANDLE_VALUE)\r
-           status = GetLastError ();\r
-  }\r
-  else  /* need to allocate a larger buffer */\r
-    {\r
-      WCHAR *ptr = malloc ((len + 1) * sizeof(WCHAR) );\r
-      if (!ptr) return NULL;\r
-      ascii_to_unicode( ptr, name, len );\r
-      ptr[len] = 0;\r
-      // status = load_dll( load_path, ptr, 0, &wmImp );\r
-         imp_mod = LoadLibrary (ptr);\r
-         if (imp_mod == INVALID_HANDLE_VALUE)\r
-           status = GetLastError ();\r
-         free (ptr);\r
-    }\r
-#ifdef USE_HIMEMCE_MAP\r
-loaded:\r
-#endif\r
-  if (status)\r
-    {\r
-      if (status == STATUS_DLL_NOT_FOUND)\r
-       TRACE("Library %s (which is needed by %s) not found\n",\r
-           name, current_modref->ldr.FullDllName);\r
-      else\r
-       TRACE("Loading library %s (which is needed by %s) failed (error %x).\n",\r
-           name, current_modref->ldr.FullDllName, status);\r
-      return NULL;\r
-    }\r
-  \r
-#if 0\r
-  /* unprotect the import address table since it can be located in\r
-   * readonly section */\r
-  while (import_list[protect_size].u1.Ordinal) protect_size++;\r
-  protect_base = thunk_list;\r
-  protect_size *= sizeof(*thunk_list);\r
-  NtProtectVirtualMemory( NtCurrentProcess(), &protect_base,\r
-                         &protect_size, PAGE_WRITECOPY, &protect_old );\r
-#endif\r
-\r
-#ifdef USE_HIMEMCE_MAP\r
- if (imp_base)\r
- {\r
-   exports = MyRtlImageDirectoryEntryToData( imp_base, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );\r
-\r
-  if (!exports)\r
-    {\r
-      /* set all imported function to deadbeef */\r
-      while (import_list->u1.Ordinal)\r
-        {\r
-         if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))\r
-            {\r
-             int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);\r
-             TRACE("No implementation for %s.%d", name, ordinal );\r
-             thunk_list->u1.Function = (PDWORD)(ULONG_PTR)allocate_stub( name, IntToPtr(ordinal) );\r
-            }\r
-         else\r
-            {\r
-             IMAGE_IMPORT_BY_NAME *pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );\r
-             TRACE("No implementation for %s.%s", name, pe_name->Name );\r
-             thunk_list->u1.Function = (PDWORD)(ULONG_PTR)allocate_stub( name, (const char*)pe_name->Name );\r
-            }\r
-         TRACE(" imported from %s, allocating stub %p\n",\r
-              current_modref->ldr.FullDllName,\r
-              (void *)thunk_list->u1.Function );\r
-         import_list++;\r
-         thunk_list++;\r
-        }\r
-      goto done;\r
-    }\r
- }\r
-#endif\r
-\r
-  while (import_list->u1.Ordinal)\r
-    {\r
-      if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))\r
-        {\r
-         int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);\r
-\r
-#ifdef USE_HIMEMCE_MAP\r
-         if (imp_base)\r
-               thunk_list->u1.Function = (PDWORD)(ULONG_PTR)find_ordinal_export( imp_base, exports, exp_size,\r
-                                                                     ordinal - exports->Base, load_path );\r
-         else\r
-#endif\r
-\r
-#ifdef USE_DLMALLOC\r
-         if (iscoredll)\r
-           {\r
-#define COREDLL_MALLOC 1041\r
-#define COREDLL_CALLOC 1346\r
-#define COREDLL_FREE 1018\r
-#define COREDLL_REALLOC 1054\r
-\r
-             if (ordinal == COREDLL_MALLOC)\r
-               thunk_list->u1.Function = (PWORD) dlmalloc;\r
-             else if (ordinal == COREDLL_CALLOC)\r
-               thunk_list->u1.Function = (PWORD) dlcalloc;\r
-             else if (ordinal == COREDLL_FREE)\r
-               thunk_list->u1.Function = (PWORD) dlfree;\r
-             else if (ordinal == COREDLL_REALLOC)\r
-               thunk_list->u1.Function = (PWORD) dlrealloc;\r
-             else\r
-               thunk_list->u1.Function = (PWORD)(ULONG_PTR)GetProcAddress (imp_mod, (void *) (ordinal & 0xffff));\r
-           }\r
-         else\r
-#endif\r
-           thunk_list->u1.Function = (PDWORD)(ULONG_PTR)GetProcAddress (imp_mod, (void *) (ordinal & 0xffff));\r
-\r
-         if (!thunk_list->u1.Function)\r
-            {\r
-             thunk_list->u1.Function = (PDWORD) allocate_stub( name, IntToPtr(ordinal) );\r
-             TRACE("No implementation for %s.%d imported from %s, setting to %p\n",\r
-                   name, ordinal, current_modref->ldr.FullDllName,\r
-                   (void *)thunk_list->u1.Function );\r
-            }\r
-         TRACE("--- Ordinal %s.%d = %p\n", name, ordinal, (void *)thunk_list->u1.Function );\r
-        }\r
-      else  /* import by name */\r
-        {\r
-         IMAGE_IMPORT_BY_NAME *pe_name;\r
-         const char *symname;\r
-         pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );\r
-         symname = (const char*)pe_name->Name;\r
-\r
-#ifdef USE_HIMEMCE_MAP\r
-         if (imp_base)\r
-                 thunk_list->u1.Function = (PDWORD)(ULONG_PTR)find_named_export( imp_base, exports, exp_size,\r
-                                                                         (const char*)pe_name->Name,\r
-                                                                         pe_name->Hint, load_path );\r
-         else\r
-#endif\r
-#ifdef USE_DLMALLOC\r
-         if (iscoredll)\r
-           {\r
-             if (! strcmp (symname, "malloc"))\r
-               thunk_list->u1.Function = (PWORD) dlmalloc;\r
-             else if (! strcmp (symname, "calloc"))\r
-               thunk_list->u1.Function = (PWORD) dlcalloc;\r
-             else if (! strcmp (symname, "free"))\r
-               thunk_list->u1.Function = (PWORD) dlfree;\r
-             else if (! strcmp (symname, "realloc"))\r
-               thunk_list->u1.Function = (PWORD) dlrealloc;\r
-             else\r
-               thunk_list->u1.Function = (PDWORD)(ULONG_PTR)GetProcAddressA (imp_mod, symname);\r
-           }\r
-         else\r
-#endif\r
-           thunk_list->u1.Function = (PDWORD)(ULONG_PTR)GetProcAddressA (imp_mod, symname);\r
-         if (!thunk_list->u1.Function)\r
-            {\r
-             thunk_list->u1.Function = (PDWORD) allocate_stub (name, symname);\r
-             TRACE("No implementation for %s.%s imported from %s, setting to %p\n",\r
-                   name, symname, current_modref->ldr.FullDllName,\r
-                   (void *)thunk_list->u1.Function );\r
-            }\r
-         TRACE("--- %s %s.%d = %p\n",\r
-               symname, name, pe_name->Hint, (void *)thunk_list->u1.Function);\r
-        }\r
-      import_list++;\r
-      thunk_list++;\r
-    }\r
-done:\r
-#if 0\r
-  /* restore old protection of the import address table */\r
-  NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, protect_old, NULL );\r
-  return wmImp;\r
-#endif\r
-  return (void*)1;\r
-}\r
-\r
-\r
-\r
-/****************************************************************\r
- *       fixup_imports\r
- *\r
- * Fixup all imports of a given module.\r
- * The loader_section must be locked while calling this function.\r
- */\r
-static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )\r
-{\r
-  int i, nb_imports;\r
-  const IMAGE_IMPORT_DESCRIPTOR *imports;\r
-  WINE_MODREF *prev;\r
-  DWORD size;\r
-  NTSTATUS status;\r
-  //  ULONG_PTR cookie;\r
-\r
-  if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS;  /* already done */\r
-  wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;\r
-  \r
-  if (!(imports = MyRtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,\r
-                                                 IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))\r
-    return STATUS_SUCCESS;\r
-  \r
-  nb_imports = 0;\r
-  while (imports[nb_imports].Name && imports[nb_imports].FirstThunk) nb_imports++;\r
-  \r
-  if (!nb_imports) return STATUS_SUCCESS;  /* no imports */\r
-  \r
-#if 0\r
-  if (!create_module_activation_context( &wm->ldr ))\r
-    RtlActivateActivationContext( 0, wm->ldr.ActivationContext, &cookie );\r
-#endif\r
-  \r
-#if 0\r
-  /* Allocate module dependency list */\r
-  wm->nDeps = nb_imports;\r
-  wm->deps  = RtlAllocateHeap( GetProcessHeap(), 0, nb_imports*sizeof(WINE_MODREF *) );\r
-#endif\r
-\r
-  /* load the imported modules. They are automatically\r
-   * added to the modref list of the process.\r
-   */\r
-  prev = current_modref;\r
-  current_modref = wm;\r
-  status = STATUS_SUCCESS;\r
-  for (i = 0; i < nb_imports; i++)\r
-    {\r
-      //      if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i], load_path )))\r
-      if (! import_dll( wm->ldr.BaseAddress, &imports[i], load_path ))\r
-       status = STATUS_DLL_NOT_FOUND;\r
-    }\r
-  current_modref = prev;\r
-  //  if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie );\r
-  return status;\r
-}\r
-\r
-\r
-static BOOL is_dll_native_subsystem( HMODULE module, const IMAGE_NT_HEADERS *nt, LPCWSTR filename )\r
-{\r
-       return FALSE;\r
-}\r
-\r
-\r
-/*************************************************************************\r
- *              get_modref\r
- *\r
- * Looks for the referenced HMODULE in the current process\r
- * The loader_section must be locked while calling this function.\r
- */\r
-static WINE_MODREF *get_modref( HMODULE hmod )\r
-{\r
-  int i;\r
-  for (i = 0; i < nr_modrefs; i++)\r
-    if (modrefs[i]->ldr.BaseAddress == hmod)\r
-      return modrefs[i];\r
-  return NULL;\r
-}\r
-\r
-\r
-\r
-static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )\r
-{\r
-    WINE_MODREF *wm;\r
-    const WCHAR *p;\r
-    const IMAGE_NT_HEADERS *nt = MyRtlImageNtHeader(hModule);\r
-#if 0\r
-    PLIST_ENTRY entry, mark;\r
-#endif\r
-\r
-    if (!(wm = malloc (sizeof(*wm)))) return NULL;\r
-\r
-    wm->nDeps    = 0;\r
-    wm->deps     = NULL;\r
-\r
-    wm->ldr.BaseAddress   = hModule;\r
-    wm->ldr.EntryPoint    = NULL;\r
-    wm->ldr.SizeOfImage   = nt->OptionalHeader.SizeOfImage;\r
-    wm->ldr.Flags         = LDR_DONT_RESOLVE_REFS;\r
-    wm->ldr.LoadCount     = 1;\r
-    wm->ldr.TlsIndex      = -1;\r
-    wm->ldr.SectionHandle = NULL;\r
-    wm->ldr.CheckSum      = 0;\r
-    wm->ldr.TimeDateStamp = 0;\r
-    wm->ldr.ActivationContext = 0;\r
-\r
-    wcscpy (wm->ldr.FullDllName, filename);\r
-    if ((p = wcsrchr( wm->ldr.FullDllName, L'\\' ))) p++;\r
-    else p = wm->ldr.FullDllName;\r
-    wcscpy (wm->ldr.BaseDllName, p );\r
-\r
-    if ((nt->FileHeader.Characteristics & IMAGE_FILE_DLL) && !is_dll_native_subsystem( hModule, nt, p ))\r
-    {\r
-        wm->ldr.Flags |= LDR_IMAGE_IS_DLL;\r
-        if (nt->OptionalHeader.AddressOfEntryPoint)\r
-            wm->ldr.EntryPoint = (char *)hModule + nt->OptionalHeader.AddressOfEntryPoint;\r
-    }\r
-\r
-#if 0\r
-    InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,\r
-                   &wm->ldr.InLoadOrderModuleList);\r
-\r
-    /* insert module in MemoryList, sorted in increasing base addresses */\r
-    mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;\r
-    for (entry = mark->Flink; entry != mark; entry = entry->Flink)\r
-    {\r
-        if (CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList)->BaseAddress > wm->ldr.BaseAddress)\r
-            break;\r
-    }\r
-    entry->Blink->Flink = &wm->ldr.InMemoryOrderModuleList;\r
-    wm->ldr.InMemoryOrderModuleList.Blink = entry->Blink;\r
-    wm->ldr.InMemoryOrderModuleList.Flink = entry;\r
-    entry->Blink = &wm->ldr.InMemoryOrderModuleList;\r
-\r
-    /* wait until init is called for inserting into this list */\r
-    wm->ldr.InInitializationOrderModuleList.Flink = NULL;\r
-    wm->ldr.InInitializationOrderModuleList.Blink = NULL;\r
-#endif\r
-\r
-    modrefs[nr_modrefs++] = wm;\r
-\r
-    return wm;\r
-}\r
-\r
-\r
-static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,\r
-                                 DWORD flags, WINE_MODREF** pwm )\r
-{\r
-  void *module;\r
-  HANDLE mapping;\r
-  LARGE_INTEGER size;\r
-  SIZE_T len = 0;\r
-  WINE_MODREF *wm;\r
-  NTSTATUS status;\r
-\r
-  TRACE("Trying native dll %S\n", name);\r
-  \r
-  size.QuadPart = 0;\r
-  status = MyNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,\r
-                             NULL, &size, PAGE_READONLY, SEC_IMAGE, file );\r
-  if (status != STATUS_SUCCESS) return status;\r
-  \r
-  module = NULL;\r
-  status = MyNtMapViewOfSection( mapping, NtCurrentProcess(),\r
-                                &module, 0, 0, &size, &len, ViewShare, 0, PAGE_READONLY );\r
-  CloseHandle( mapping );\r
-  if (status < 0) return status;\r
-  \r
-  /* create the MODREF */\r
-  \r
-  if (!(wm = alloc_module( module, name ))) return STATUS_NO_MEMORY;\r
-  \r
-  /* fixup imports */\r
-  \r
-  if (!(flags & DONT_RESOLVE_DLL_REFERENCES))\r
-    {\r
-#if 1\r
-      return (STATUS_NOT_IMPLEMENTED);\r
-#else\r
-      if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS)\r
-        {\r
-#if 0\r
-         /* the module has only be inserted in the load & memory order lists */\r
-         RemoveEntryList(&wm->ldr.InLoadOrderModuleList);\r
-         RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);\r
-         \r
-         /* FIXME: there are several more dangling references\r
-          * left. Including dlls loaded by this dll before the\r
-          * failed one. Unrolling is rather difficult with the\r
-          * current structure and we can leave them lying\r
-          * around with no problems, so we don't care.\r
-          * As these might reference our wm, we don't free it.\r
-          */\r
-#endif\r
-         return status;\r
-        }\r
-#endif\r
-    }\r
-  \r
-  TRACE( "Loaded %S at %p: native\n", wm->ldr.FullDllName, module );\r
-  \r
-  wm->ldr.LoadCount = 1;\r
-  *pwm = wm;\r
-  return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,\r
-                               WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle )\r
-{\r
-  HMODULE hnd = GetModuleHandle (NULL);\r
-  int len;\r
-  \r
-  assert (handle);\r
-  assert (*size == MAX_PATH);\r
-  \r
-  if (libname[0] == L'/' || libname[0] == L'\\')\r
-    {\r
-      wcscpy (filename, libname);\r
-    }\r
-  else\r
-    {\r
-      len = GetModuleFileName (hnd, filename, MAX_PATH);\r
-      filename[len++] = L'\\';\r
-      wcscpy (&filename[len], libname);\r
-    }\r
-  TRACE( "opening %S\n", filename);\r
-  \r
-  if (handle)\r
-    {\r
-      *handle = CreateFile( filename, GENERIC_READ, FILE_SHARE_READ, NULL,\r
-                           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
-      TRACE ("find_dll_file: 0x%p (0x%x)\n", *handle, GetFileSize (*handle, NULL));\r
-    }\r
-  return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )\r
-{\r
-    WCHAR filename[MAX_PATH];\r
-    ULONG size;\r
-    HANDLE handle = 0;\r
-    NTSTATUS nts;\r
-\r
-    TRACE( "looking for %S in %S\n", libname, load_path ? load_path : L"default path" );\r
-\r
-    *pwm = NULL;\r
-    size = MAX_PATH;\r
-    find_dll_file( load_path, libname, filename, &size, pwm, &handle );\r
-    \r
-    if (!handle)\r
-      nts = STATUS_DLL_NOT_FOUND;\r
-    else\r
-      nts = load_native_dll( load_path, filename, handle, flags, pwm );\r
-    \r
-    if (nts == STATUS_SUCCESS)\r
-      {\r
-        /* Initialize DLL just loaded */\r
-        TRACE("Loaded module %S at %p\n", filename, (*pwm)->ldr.BaseAddress);\r
-        if (handle)\r
-         CloseHandle( handle );\r
-        return nts;\r
-      }\r
-    \r
-    TRACE("Failed to load module %S; status=%x\n", libname, nts);\r
-    if (handle)\r
-      CloseHandle( handle );\r
-    return nts;\r
-}\r
-\r
-\r
-NTSTATUS MyLdrLoadDll(LPCWSTR path_name, DWORD flags,\r
-                     LPCWSTR libname, HMODULE* hModule)\r
-{\r
-  WINE_MODREF *wm;\r
-  NTSTATUS nts;\r
-\r
-  /* Support for dll path removed.  */\r
-  nts = load_dll( path_name, libname, flags, &wm );\r
-\r
-  /* For now.  */\r
-  assert (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS);\r
-#if 0\r
-  if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))\r
-    {\r
-      nts = process_attach( wm, NULL );\r
-      if (nts != STATUS_SUCCESS)\r
-        {\r
-         LdrUnloadDll(wm->ldr.BaseAddress);\r
-         wm = NULL;\r
-        }\r
-    }\r
-#endif\r
-  *hModule = (wm) ? wm->ldr.BaseAddress : NULL;\r
-\r
-  return nts;\r
-}\r
-\r
-\r
-\r
-/***********************************************************************\r
- *           LdrProcessRelocationBlock  (NTDLL.@)\r
- *\r
- * Apply relocations to a given page of a mapped PE image.\r
- */\r
-IMAGE_BASE_RELOCATION * MyLdrProcessRelocationBlock( void *page, UINT count,\r
-                                                    USHORT *relocs, INT_PTR delta )\r
-{\r
-  while (count--)\r
-    {\r
-      USHORT offset = *relocs & 0xfff;\r
-      int type = *relocs >> 12;\r
-      switch(type)\r
-        {\r
-        case IMAGE_REL_BASED_ABSOLUTE:\r
-         break;\r
-#if 1\r
-        case IMAGE_REL_BASED_HIGH:\r
-         *(short *)((char *)page + offset) += HIWORD(delta);\r
-         break;\r
-        case IMAGE_REL_BASED_LOW:\r
-         *(short *)((char *)page + offset) += LOWORD(delta);\r
-         break;\r
-        case IMAGE_REL_BASED_HIGHLOW:\r
-         *(int *)((char *)page + offset) += delta;\r
-         break;\r
-#else\r
-        case IMAGE_REL_BASED_DIR64:\r
-         *(INT_PTR *)((char *)page + offset) += delta;\r
-         break;\r
-#endif\r
-        default:\r
-         TRACE("Unknown/unsupported fixup type %x.\n", type);\r
-         return NULL;\r
-        }\r
-      relocs++;\r
-    }\r
-  return (IMAGE_BASE_RELOCATION *)relocs;  /* return address of next block */\r
-}\r
-\r
-\r
-void MyLdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,\r
-                          ULONG_PTR unknown3, ULONG_PTR unknown4 )\r
-{\r
-  static const WCHAR globalflagW[] = {'G','l','o','b','a','l','F','l','a','g',0};\r
-  NTSTATUS status;\r
-  WINE_MODREF *wm;\r
-  LPCWSTR load_path = NULL;\r
-  PEB *peb = current_peb();\r
-  IMAGE_NT_HEADERS *nt = MyRtlImageNtHeader( peb->ImageBaseAddress );\r
-  void (*_kernel_start) (void *ptr) = kernel_start;\r
-\r
-#if 0\r
-  if (main_exe_file) NtClose( main_exe_file );  /* at this point the main module is created */\r
-#endif\r
-\r
-  /* allocate the modref for the main exe (if not already done) */\r
-  wm = get_modref( peb->ImageBaseAddress );\r
-  assert( wm );\r
-  if (wm->ldr.Flags & LDR_IMAGE_IS_DLL)\r
-    {\r
-      TRACE("%S is a dll, not an executable\n", wm->ldr.FullDllName );\r
-      exit(1);\r
-    }\r
-\r
-  //  peb->ProcessParameters->ImagePathName = wm->ldr.FullDllName;\r
-  //  version_init( wm->ldr.FullDllName );\r
-\r
-  //  LdrQueryImageFileExecutionOptions( &peb->ProcessParameters->ImagePathName, globalflagW,\r
-  //                                REG_DWORD, &peb->NtGlobalFlag, sizeof(peb->NtGlobalFlag), NULL );\r
-\r
-  /* the main exe needs to be the first in the load order list */\r
-  //  RemoveEntryList( &wm->ldr.InLoadOrderModuleList );\r
-  //  InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList );\r
-\r
-  //  if ((status = virtual_alloc_thread_stack( NtCurrentTeb(), 0, 0 )) != STATUS_SUCCESS) goto error;\r
-  //  if ((status = server_init_process_done()) != STATUS_SUCCESS) goto error;\r
-\r
-  //  actctx_init();\r
-  //  load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;\r
-  if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error;\r
-  //  if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error;\r
-  //  if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error;\r
-  //  heap_set_debug_flags( GetProcessHeap() );\r
-\r
-#if 0\r
-  /* FIXME: This may be interesting at some point.  */\r
-  status = wine_call_on_stack( attach_process_dlls, wm, NtCurrentTeb()->Tib.StackBase );\r
-  if (status != STATUS_SUCCESS) goto error;\r
-#endif\r
-\r
-  //  virtual_release_address_space( nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE );\r
-  //  virtual_clear_thread_stack();\r
-  //  wine_switch_to_stack( start_process, kernel_start, NtCurrentTeb()->Tib.StackBase );\r
-  // stack( start_process, kernel_start, NtCurrentTeb()->Tib.StackBase );\r
-  _kernel_start (peb);\r
-\r
- error:\r
-  TRACE( "Main exe initialization for %S failed, status %x\n",\r
-        wm->ldr.FullDllName, status);\r
-        //      peb->ProcessParameters->ImagePathName, status );\r
-  //  NtTerminateProcess( GetCurrentProcess(), status );\r
-  exit (1);\r
-}\r
+        return;
+    }
+  TRACE ("himemce map found at %p (reserving 0x%x bytes at %p)\n", himemce_map,
+         himemce_map->low_start, himemce_map->low_size);
+  ptr = VirtualAlloc(himemce_map->low_start, himemce_map->low_size,
+           MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+  if (! ptr)
+  {
+         TRACE ("failed to reserve memory: %i\n", GetLastError ());
+         himemce_map_close (himemce_map);
+         himemce_map = NULL;
+      return;
+  }
+}
+
+
+# define page_mask  0xfff
+# define page_shift 12
+# define page_size  0x1000
+
+#define ROUND_SIZE(size) \
+  (((SIZE_T)(size) + page_mask) & ~page_mask)
+
+static SIZE_T
+section_size (IMAGE_SECTION_HEADER *sec)
+{
+  static const SIZE_T sector_align = 0x1ff;
+  SIZE_T map_size, file_size, end;
+
+  if (!sec->Misc.VirtualSize)
+    map_size = ROUND_SIZE( sec->SizeOfRawData );
+  else
+    map_size = ROUND_SIZE( sec->Misc.VirtualSize );
+
+  file_size = (sec->SizeOfRawData + (sec->PointerToRawData & sector_align) + sector_align) & ~sector_align;
+  if (file_size > map_size) file_size = map_size;
+  end = ROUND_SIZE( file_size );
+  if (end > map_size) end = map_size;
+  return end;
+}
+
+
+/* Returns the base of the module after loading it, if necessary.
+   NULL if not found, -1 if a fatal error occurs.  */
+void *
+himemce_map_load_dll (const char *name)
+{
+  struct himemce_module *mod;
+  int modidx;
+  char *ptr;
+  IMAGE_DOS_HEADER *dos;
+  IMAGE_NT_HEADERS *nt;
+  IMAGE_SECTION_HEADER *sec;
+  int sec_cnt;
+  int idx;
+  const IMAGE_IMPORT_DESCRIPTOR *imports;
+  DWORD imports_size;
+
+  himemce_map_init ();
+  if (! himemce_map)
+         return NULL;
+
+  mod = himemce_map_find_module (himemce_map, name);
+  if (!mod)
+         return NULL;
+  modidx = mod - himemce_map->module;
+  if (himemce_mod_loaded[modidx])
+         return mod->base;
+
+  /* First map the sections low.  */
+  ptr = mod->base;
+  dos = (IMAGE_DOS_HEADER *) ptr;
+  nt = (IMAGE_NT_HEADERS *) (ptr + dos->e_lfanew);
+  sec = (IMAGE_SECTION_HEADER *) ((char*) &nt->OptionalHeader
+                                  + nt->FileHeader.SizeOfOptionalHeader);
+  sec_cnt = nt->FileHeader.NumberOfSections;
+  for (idx = 0; idx < sec_cnt; idx++)
+  {
+       size_t secsize;
+       char *secptr;
+
+       if (! sec[idx].PointerToLinenumbers)
+         continue;
+       secsize = section_size (&sec[idx]);
+    secptr = VirtualAlloc ((void *) sec[idx].PointerToLinenumbers,
+               secsize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+       if (! secptr)
+       {
+               TRACE ("could not allocate 0x%x bytes of low memory at %p: %i\n",
+                       secsize, sec[idx].PointerToLinenumbers, GetLastError ());
+               return (void *) -1;
+       }
+    memcpy (secptr, ptr + sec[idx].VirtualAddress, secsize);
+  }
+
+  /* To break circles, we claim that we loaded before recursing.  */
+  himemce_mod_loaded[modidx]++;
+  imports = MyRtlImageDirectoryEntryToData ((HMODULE) ptr, TRUE,
+                                            IMAGE_DIRECTORY_ENTRY_IMPORT,
+                                            &imports_size);
+  if (imports)
+  {
+       idx = 0;
+       while (imports[idx].Name && imports[idx].FirstThunk)
+       {
+               char *iname = ptr + imports[idx].Name;
+               void *ibase;
+
+               /* Recursion!  */
+               ibase = himemce_map_load_dll (iname);
+               if (ibase == (void *) -1)
+                       return (void *) -1;
+               /* Nothing to do if ibase !=0: Successful loading of high DLL.  */
+               if (ibase == 0)
+               {
+                       ibase = LoadLibrary (iname);
+                       if (!ibase)
+                       {
+                               TRACE ("Could not find %s, dependency of %s\n", iname, name);
+                               return (void *) -1;
+                       }
+               }
+               idx++;
+       }
+  }
+  return ptr;
+}
+
+
+static void *
+get_rva_low (char *module, size_t rva)
+{
+  IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)module;
+  IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(module + dos->e_lfanew);
+  IMAGE_SECTION_HEADER *sec;
+  int sec_cnt;
+  int idx;
+
+  sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeO\
+fOptionalHeader);
+  sec_cnt = nt->FileHeader.NumberOfSections;
+
+  for (idx = 0; idx < sec_cnt; idx++)
+    {
+      if (! sec[idx].PointerToLinenumbers)
+        continue;
+      if (rva >= sec[idx].VirtualAddress
+          && rva < sec[idx].VirtualAddress + section_size (&sec[idx]))
+                break;
+    }
+  if (idx == sec_cnt)
+    return (void *)((char *)module + rva);
+
+  return (void *)((char *)sec[idx].PointerToLinenumbers
+                  + (rva - sec[idx].VirtualAddress));
+}
+
+
+static FARPROC
+find_ordinal_export (void *module, const IMAGE_EXPORT_DIRECTORY *exports,
+                     DWORD exp_size, DWORD ordinal, LPCWSTR load_path)
+{
+  FARPROC proc;
+  const DWORD *functions = get_rva (module, exports->AddressOfFunctions);
+
+  if (ordinal >= exports->NumberOfFunctions)
+    {
+      TRACE(" ordinal %d out of range!\n", ordinal + exports->Base );
+      return NULL;
+    }
+  if (!functions[ordinal]) return NULL;
+
+#if 0
+  /* if the address falls into the export dir, it's a forward */
+  if (((const char *)proc >= (const char *)exports) &&
+      ((const char *)proc < (const char *)exports + exp_size))
+    return find_forwarded_export( module, (const char *)proc, load_path );
+#endif
+
+  proc = get_rva_low (module, functions[ordinal]);
+  return proc;
+}
+
+static FARPROC
+find_named_export (void *module, const IMAGE_EXPORT_DIRECTORY *exports,
+                   DWORD exp_size, const char *name, int hint, LPCWSTR load_path)
+{
+  const WORD *ordinals = get_rva (module, exports->AddressOfNameOrdinals);
+  const DWORD *names = get_rva (module, exports->AddressOfNames);
+  int min = 0, max = exports->NumberOfNames - 1;
+
+  /* first check the hint */
+  if (hint >= 0 && hint <= max)
+    {
+      char *ename = get_rva( module, names[hint] );
+      if (!strcmp( ename, name ))
+        return find_ordinal_export( module, exports, exp_size, ordinals[hint], load_path);
+    }
+
+  /* then do a binary search */
+  while (min <= max)
+    {
+      int res, pos = (min + max) / 2;
+      char *ename = get_rva( module, names[pos] );
+      if (!(res = strcmp( ename, name )))
+        return find_ordinal_export( module, exports, exp_size, ordinals[pos], load_path);
+      if (res > 0) max = pos - 1;
+      else min = pos + 1;
+    }
+  return NULL;
+}
+
+#endif
+
+
+PIMAGE_NT_HEADERS MyRtlImageNtHeader(HMODULE hModule)
+{
+    IMAGE_NT_HEADERS *ret;
+    IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;
+
+    ret = NULL;
+    if (dos->e_magic == IMAGE_DOS_SIGNATURE)
+    {
+        ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
+        if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
+    }
+    return ret;
+}
+
+\f
+/* internal representation of 32bit modules. per process. */
+typedef struct _wine_modref
+{
+    LDR_MODULE            ldr;
+    int                   nDeps;
+    struct _wine_modref **deps;
+} WINE_MODREF;
+
+/* FIXME: cmp with himemce-map.h */
+#define MAX_MODREFS 64
+WINE_MODREF *modrefs[MAX_MODREFS];
+int nr_modrefs;
+
+
+static WINE_MODREF *current_modref;
+
+
+/* convert from straight ASCII to Unicode without depending on the current codepage */
+static void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
+{
+  while (len--) *dst++ = (unsigned char)*src++;
+}
+
+
+/***********************************************************************
+ *           RtlImageDirectoryEntryToData   (NTDLL.@)
+ */
+PVOID MyRtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir, ULONG *size )
+{
+  const IMAGE_NT_HEADERS *nt;
+  DWORD addr;
+
+  if ((ULONG_PTR)module & 1)  /* mapped as data file */
+    {
+      module = (HMODULE)((ULONG_PTR)module & ~1);
+      image = FALSE;
+    }
+  if (!(nt = MyRtlImageNtHeader( module ))) return NULL;
+  if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+    {
+      const IMAGE_NT_HEADERS64 *nt64 = (const IMAGE_NT_HEADERS64 *)nt;
+
+      if (dir >= nt64->OptionalHeader.NumberOfRvaAndSizes) return NULL;
+      if (!(addr = nt64->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
+      *size = nt64->OptionalHeader.DataDirectory[dir].Size;
+      if (image || addr < nt64->OptionalHeader.SizeOfHeaders) return (char *)module + addr;
+    }
+  else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+    {
+      const IMAGE_NT_HEADERS32 *nt32 = (const IMAGE_NT_HEADERS32 *)nt;
+
+      if (dir >= nt32->OptionalHeader.NumberOfRvaAndSizes) return NULL;
+      if (!(addr = nt32->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
+      *size = nt32->OptionalHeader.DataDirectory[dir].Size;
+      if (image || addr < nt32->OptionalHeader.SizeOfHeaders) return (char *)module + addr;
+    }
+  else return NULL;
+
+#if 0
+  /* not mapped as image, need to find the section containing the virtual address */
+  return RtlImageRvaToVa( nt, module, addr, NULL );
+#else
+  return NULL;
+#endif
+}
+
+
+#define allocate_stub(x,y) (0xdeadbeef)
+
+/*************************************************************************
+ *              import_dll
+ *
+ * Import the dll specified by the given import descriptor.
+ * The loader_section must be locked while calling this function.
+ */
+static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path )
+{
+  NTSTATUS status = STATUS_SUCCESS;
+  //  WINE_MODREF *wmImp;
+  HMODULE imp_mod;
+#ifdef USE_HIMEMCE_MAP
+  void *imp_base = 0;
+  const IMAGE_EXPORT_DIRECTORY *exports;
+  DWORD exp_size;
+#endif
+  const IMAGE_THUNK_DATA *import_list;
+  IMAGE_THUNK_DATA *thunk_list;
+  WCHAR buffer[32];
+  const char *name = get_rva( module, descr->Name );
+  DWORD len = strlen(name);
+#if 0
+  PVOID protect_base;
+  SIZE_T protect_size = 0;
+  DWORD protect_old;
+#endif
+#ifdef USE_DLMALLOC
+  int iscoredll = 0;
+#endif
+
+  thunk_list = get_rva( module, (DWORD)descr->FirstThunk );
+  if (descr->OriginalFirstThunk)
+    import_list = get_rva( module, (DWORD)descr->OriginalFirstThunk );
+  else
+    import_list = thunk_list;
+
+  while (len && name[len-1] == ' ') len--;  /* remove trailing spaces */
+
+#ifdef USE_DLMALLOC
+  if (! _stricmp (name, "coredll.dll"))
+    iscoredll = 1;
+#endif
+
+#ifdef USE_HIMEMCE_MAP
+  imp_base = himemce_map_load_dll (name);
+  if (imp_base == (void *) -1)
+    status = GetLastError ();
+  if (imp_base)
+    goto loaded;
+#endif
+
+  if (len * sizeof(WCHAR) < sizeof(buffer))
+    {
+      ascii_to_unicode( buffer, name, len );
+      buffer[len] = 0;
+      //      status = load_dll( load_path, buffer, 0, &wmImp );
+      imp_mod = LoadLibrary (buffer);
+         if (imp_mod == INVALID_HANDLE_VALUE)
+           status = GetLastError ();
+  }
+  else  /* need to allocate a larger buffer */
+    {
+      WCHAR *ptr = malloc ((len + 1) * sizeof(WCHAR) );
+      if (!ptr) return NULL;
+      ascii_to_unicode( ptr, name, len );
+      ptr[len] = 0;
+      // status = load_dll( load_path, ptr, 0, &wmImp );
+         imp_mod = LoadLibrary (ptr);
+         if (imp_mod == INVALID_HANDLE_VALUE)
+           status = GetLastError ();
+         free (ptr);
+    }
+#ifdef USE_HIMEMCE_MAP
+loaded:
+#endif
+  if (status)
+    {
+      if (status == STATUS_DLL_NOT_FOUND)
+       TRACE("Library %s (which is needed by %s) not found\n",
+           name, current_modref->ldr.FullDllName);
+      else
+       TRACE("Loading library %s (which is needed by %s) failed (error %x).\n",
+           name, current_modref->ldr.FullDllName, status);
+      return NULL;
+    }
+  
+#if 0
+  /* unprotect the import address table since it can be located in
+   * readonly section */
+  while (import_list[protect_size].u1.Ordinal) protect_size++;
+  protect_base = thunk_list;
+  protect_size *= sizeof(*thunk_list);
+  NtProtectVirtualMemory( NtCurrentProcess(), &protect_base,
+                         &protect_size, PAGE_WRITECOPY, &protect_old );
+#endif
+
+#ifdef USE_HIMEMCE_MAP
+ if (imp_base)
+ {
+   exports = MyRtlImageDirectoryEntryToData( imp_base, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
+
+  if (!exports)
+    {
+      /* set all imported function to deadbeef */
+      while (import_list->u1.Ordinal)
+        {
+         if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
+            {
+             int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
+             TRACE("No implementation for %s.%d", name, ordinal );
+             thunk_list->u1.Function = (PDWORD)(ULONG_PTR)allocate_stub( name, IntToPtr(ordinal) );
+            }
+         else
+            {
+             IMAGE_IMPORT_BY_NAME *pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
+             TRACE("No implementation for %s.%s", name, pe_name->Name );
+             thunk_list->u1.Function = (PDWORD)(ULONG_PTR)allocate_stub( name, (const char*)pe_name->Name );
+            }
+         TRACE(" imported from %s, allocating stub %p\n",
+              current_modref->ldr.FullDllName,
+              (void *)thunk_list->u1.Function );
+         import_list++;
+         thunk_list++;
+        }
+      goto done;
+    }
+ }
+#endif
+
+  while (import_list->u1.Ordinal)
+    {
+      if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
+        {
+         int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
+
+#ifdef USE_HIMEMCE_MAP
+         if (imp_base)
+               thunk_list->u1.Function = (PDWORD)(ULONG_PTR)find_ordinal_export( imp_base, exports, exp_size,
+                                                                     ordinal - exports->Base, load_path );
+         else
+#endif
+
+#ifdef USE_DLMALLOC
+         if (iscoredll)
+           {
+#define COREDLL_MALLOC 1041
+#define COREDLL_CALLOC 1346
+#define COREDLL_FREE 1018
+#define COREDLL_REALLOC 1054
+
+             if (ordinal == COREDLL_MALLOC)
+               thunk_list->u1.Function = (PWORD) dlmalloc;
+             else if (ordinal == COREDLL_CALLOC)
+               thunk_list->u1.Function = (PWORD) dlcalloc;
+             else if (ordinal == COREDLL_FREE)
+               thunk_list->u1.Function = (PWORD) dlfree;
+             else if (ordinal == COREDLL_REALLOC)
+               thunk_list->u1.Function = (PWORD) dlrealloc;
+             else
+               thunk_list->u1.Function = (PWORD)(ULONG_PTR)GetProcAddress (imp_mod, (void *) (ordinal & 0xffff));
+           }
+         else
+#endif
+           thunk_list->u1.Function = (PDWORD)(ULONG_PTR)GetProcAddress (imp_mod, (void *) (ordinal & 0xffff));
+
+         if (!thunk_list->u1.Function)
+            {
+             thunk_list->u1.Function = (PDWORD) allocate_stub( name, IntToPtr(ordinal) );
+             TRACE("No implementation for %s.%d imported from %s, setting to %p\n",
+                   name, ordinal, current_modref->ldr.FullDllName,
+                   (void *)thunk_list->u1.Function );
+            }
+         TRACE("--- Ordinal %s.%d = %p\n", name, ordinal, (void *)thunk_list->u1.Function );
+        }
+      else  /* import by name */
+        {
+         IMAGE_IMPORT_BY_NAME *pe_name;
+         const char *symname;
+         pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
+         symname = (const char*)pe_name->Name;
+
+#ifdef USE_HIMEMCE_MAP
+         if (imp_base)
+                 thunk_list->u1.Function = (PDWORD)(ULONG_PTR)find_named_export( imp_base, exports, exp_size,
+                                                                         (const char*)pe_name->Name,
+                                                                         pe_name->Hint, load_path );
+         else
+#endif
+#ifdef USE_DLMALLOC
+         if (iscoredll)
+           {
+             if (! strcmp (symname, "malloc"))
+               thunk_list->u1.Function = (PWORD) dlmalloc;
+             else if (! strcmp (symname, "calloc"))
+               thunk_list->u1.Function = (PWORD) dlcalloc;
+             else if (! strcmp (symname, "free"))
+               thunk_list->u1.Function = (PWORD) dlfree;
+             else if (! strcmp (symname, "realloc"))
+               thunk_list->u1.Function = (PWORD) dlrealloc;
+             else
+               thunk_list->u1.Function = (PDWORD)(ULONG_PTR)GetProcAddressA (imp_mod, symname);
+           }
+         else
+#endif
+           thunk_list->u1.Function = (PDWORD)(ULONG_PTR)GetProcAddressA (imp_mod, symname);
+         if (!thunk_list->u1.Function)
+            {
+             thunk_list->u1.Function = (PDWORD) allocate_stub (name, symname);
+             TRACE("No implementation for %s.%s imported from %s, setting to %p\n",
+                   name, symname, current_modref->ldr.FullDllName,
+                   (void *)thunk_list->u1.Function );
+            }
+         TRACE("--- %s %s.%d = %p\n",
+               symname, name, pe_name->Hint, (void *)thunk_list->u1.Function);
+        }
+      import_list++;
+      thunk_list++;
+    }
+done:
+#if 0
+  /* restore old protection of the import address table */
+  NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, protect_old, NULL );
+  return wmImp;
+#endif
+  return (void*)1;
+}
+
+
+
+/****************************************************************
+ *       fixup_imports
+ *
+ * Fixup all imports of a given module.
+ * The loader_section must be locked while calling this function.
+ */
+static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )
+{
+  int i, nb_imports;
+  const IMAGE_IMPORT_DESCRIPTOR *imports;
+  WINE_MODREF *prev;
+  DWORD size;
+  NTSTATUS status;
+  //  ULONG_PTR cookie;
+
+  if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS;  /* already done */
+  wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
+  
+  if (!(imports = MyRtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
+                                                 IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
+    return STATUS_SUCCESS;
+  
+  nb_imports = 0;
+  while (imports[nb_imports].Name && imports[nb_imports].FirstThunk) nb_imports++;
+  
+  if (!nb_imports) return STATUS_SUCCESS;  /* no imports */
+  
+#if 0
+  if (!create_module_activation_context( &wm->ldr ))
+    RtlActivateActivationContext( 0, wm->ldr.ActivationContext, &cookie );
+#endif
+  
+#if 0
+  /* Allocate module dependency list */
+  wm->nDeps = nb_imports;
+  wm->deps  = RtlAllocateHeap( GetProcessHeap(), 0, nb_imports*sizeof(WINE_MODREF *) );
+#endif
+
+  /* load the imported modules. They are automatically
+   * added to the modref list of the process.
+   */
+  prev = current_modref;
+  current_modref = wm;
+  status = STATUS_SUCCESS;
+  for (i = 0; i < nb_imports; i++)
+    {
+      //      if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i], load_path )))
+      if (! import_dll( wm->ldr.BaseAddress, &imports[i], load_path ))
+       status = STATUS_DLL_NOT_FOUND;
+    }
+  current_modref = prev;
+  //  if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie );
+  return status;
+}
+
+
+static BOOL is_dll_native_subsystem( HMODULE module, const IMAGE_NT_HEADERS *nt, LPCWSTR filename )
+{
+       return FALSE;
+}
+
+
+/*************************************************************************
+ *              get_modref
+ *
+ * Looks for the referenced HMODULE in the current process
+ * The loader_section must be locked while calling this function.
+ */
+static WINE_MODREF *get_modref( HMODULE hmod )
+{
+  int i;
+  for (i = 0; i < nr_modrefs; i++)
+    if (modrefs[i]->ldr.BaseAddress == hmod)
+      return modrefs[i];
+  return NULL;
+}
+
+
+
+static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
+{
+    WINE_MODREF *wm;
+    const WCHAR *p;
+    const IMAGE_NT_HEADERS *nt = MyRtlImageNtHeader(hModule);
+#if 0
+    PLIST_ENTRY entry, mark;
+#endif
+
+    if (!(wm = malloc (sizeof(*wm)))) return NULL;
+
+    wm->nDeps    = 0;
+    wm->deps     = NULL;
+
+    wm->ldr.BaseAddress   = hModule;
+    wm->ldr.EntryPoint    = NULL;
+    wm->ldr.SizeOfImage   = nt->OptionalHeader.SizeOfImage;
+    wm->ldr.Flags         = LDR_DONT_RESOLVE_REFS;
+    wm->ldr.LoadCount     = 1;
+    wm->ldr.TlsIndex      = -1;
+    wm->ldr.SectionHandle = NULL;
+    wm->ldr.CheckSum      = 0;
+    wm->ldr.TimeDateStamp = 0;
+    wm->ldr.ActivationContext = 0;
+
+    wcscpy (wm->ldr.FullDllName, filename);
+    if ((p = wcsrchr( wm->ldr.FullDllName, L'\\' ))) p++;
+    else p = wm->ldr.FullDllName;
+    wcscpy (wm->ldr.BaseDllName, p );
+
+    if ((nt->FileHeader.Characteristics & IMAGE_FILE_DLL) && !is_dll_native_subsystem( hModule, nt, p ))
+    {
+        wm->ldr.Flags |= LDR_IMAGE_IS_DLL;
+        if (nt->OptionalHeader.AddressOfEntryPoint)
+            wm->ldr.EntryPoint = (char *)hModule + nt->OptionalHeader.AddressOfEntryPoint;
+    }
+
+#if 0
+    InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
+                   &wm->ldr.InLoadOrderModuleList);
+
+    /* insert module in MemoryList, sorted in increasing base addresses */
+    mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
+    for (entry = mark->Flink; entry != mark; entry = entry->Flink)
+    {
+        if (CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList)->BaseAddress > wm->ldr.BaseAddress)
+            break;
+    }
+    entry->Blink->Flink = &wm->ldr.InMemoryOrderModuleList;
+    wm->ldr.InMemoryOrderModuleList.Blink = entry->Blink;
+    wm->ldr.InMemoryOrderModuleList.Flink = entry;
+    entry->Blink = &wm->ldr.InMemoryOrderModuleList;
+
+    /* wait until init is called for inserting into this list */
+    wm->ldr.InInitializationOrderModuleList.Flink = NULL;
+    wm->ldr.InInitializationOrderModuleList.Blink = NULL;
+#endif
+
+    modrefs[nr_modrefs++] = wm;
+
+    return wm;
+}
+
+
+static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
+                                 DWORD flags, WINE_MODREF** pwm )
+{
+  void *module;
+  HANDLE mapping;
+  LARGE_INTEGER size;
+  SIZE_T len = 0;
+  WINE_MODREF *wm;
+  NTSTATUS status;
+
+  TRACE("Trying native dll %S\n", name);
+  
+  size.QuadPart = 0;
+  status = MyNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
+                             NULL, &size, PAGE_READONLY, SEC_IMAGE, file );
+  if (status != STATUS_SUCCESS) return status;
+  
+  module = NULL;
+  status = MyNtMapViewOfSection( mapping, NtCurrentProcess(),
+                                &module, 0, 0, &size, &len, ViewShare, 0, PAGE_READONLY );
+  CloseHandle( mapping );
+  if (status < 0) return status;
+  
+  /* create the MODREF */
+  
+  if (!(wm = alloc_module( module, name ))) return STATUS_NO_MEMORY;
+  
+  /* fixup imports */
+  
+  if (!(flags & DONT_RESOLVE_DLL_REFERENCES))
+    {
+#if 1
+      return (STATUS_NOT_IMPLEMENTED);
+#else
+      if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS)
+        {
+#if 0
+         /* the module has only be inserted in the load & memory order lists */
+         RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
+         RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
+         
+         /* FIXME: there are several more dangling references
+          * left. Including dlls loaded by this dll before the
+          * failed one. Unrolling is rather difficult with the
+          * current structure and we can leave them lying
+          * around with no problems, so we don't care.
+          * As these might reference our wm, we don't free it.
+          */
+#endif
+         return status;
+        }
+#endif
+    }
+  
+  TRACE( "Loaded %S at %p: native\n", wm->ldr.FullDllName, module );
+  
+  wm->ldr.LoadCount = 1;
+  *pwm = wm;
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
+                               WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle )
+{
+  HMODULE hnd = GetModuleHandle (NULL);
+  int len;
+  
+  assert (handle);
+  assert (*size == MAX_PATH);
+  
+  if (libname[0] == L'/' || libname[0] == L'\\')
+    {
+      wcscpy (filename, libname);
+    }
+  else
+    {
+      len = GetModuleFileName (hnd, filename, MAX_PATH);
+      filename[len++] = L'\\';
+      wcscpy (&filename[len], libname);
+    }
+  TRACE( "opening %S\n", filename);
+  
+  if (handle)
+    {
+      *handle = CreateFile( filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+                           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+      TRACE ("find_dll_file: 0x%p (0x%x)\n", *handle, GetFileSize (*handle, NULL));
+    }
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
+{
+    WCHAR filename[MAX_PATH];
+    ULONG size;
+    HANDLE handle = 0;
+    NTSTATUS nts;
+
+    TRACE( "looking for %S in %S\n", libname, load_path ? load_path : L"default path" );
+
+    *pwm = NULL;
+    size = MAX_PATH;
+    find_dll_file( load_path, libname, filename, &size, pwm, &handle );
+    
+    if (!handle)
+      nts = STATUS_DLL_NOT_FOUND;
+    else
+      nts = load_native_dll( load_path, filename, handle, flags, pwm );
+    
+    if (nts == STATUS_SUCCESS)
+      {
+        /* Initialize DLL just loaded */
+        TRACE("Loaded module %S at %p\n", filename, (*pwm)->ldr.BaseAddress);
+        if (handle)
+         CloseHandle( handle );
+        return nts;
+      }
+    
+    TRACE("Failed to load module %S; status=%x\n", libname, nts);
+    if (handle)
+      CloseHandle( handle );
+    return nts;
+}
+
+
+NTSTATUS MyLdrLoadDll(LPCWSTR path_name, DWORD flags,
+                     LPCWSTR libname, HMODULE* hModule)
+{
+  WINE_MODREF *wm;
+  NTSTATUS nts;
+
+  /* Support for dll path removed.  */
+  nts = load_dll( path_name, libname, flags, &wm );
+
+  /* For now.  */
+  assert (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS);
+#if 0
+  if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
+    {
+      nts = process_attach( wm, NULL );
+      if (nts != STATUS_SUCCESS)
+        {
+         LdrUnloadDll(wm->ldr.BaseAddress);
+         wm = NULL;
+        }
+    }
+#endif
+  *hModule = (wm) ? wm->ldr.BaseAddress : NULL;
+
+  return nts;
+}
+
+
+
+/***********************************************************************
+ *           LdrProcessRelocationBlock  (NTDLL.@)
+ *
+ * Apply relocations to a given page of a mapped PE image.
+ */
+IMAGE_BASE_RELOCATION * MyLdrProcessRelocationBlock( void *page, UINT count,
+                                                    USHORT *relocs, INT_PTR delta )
+{
+  while (count--)
+    {
+      USHORT offset = *relocs & 0xfff;
+      int type = *relocs >> 12;
+      switch(type)
+        {
+        case IMAGE_REL_BASED_ABSOLUTE:
+         break;
+#if 1
+        case IMAGE_REL_BASED_HIGH:
+         *(short *)((char *)page + offset) += HIWORD(delta);
+         break;
+        case IMAGE_REL_BASED_LOW:
+         *(short *)((char *)page + offset) += LOWORD(delta);
+         break;
+        case IMAGE_REL_BASED_HIGHLOW:
+         *(int *)((char *)page + offset) += delta;
+         break;
+#else
+        case IMAGE_REL_BASED_DIR64:
+         *(INT_PTR *)((char *)page + offset) += delta;
+         break;
+#endif
+        default:
+         TRACE("Unknown/unsupported fixup type %x.\n", type);
+         return NULL;
+        }
+      relocs++;
+    }
+  return (IMAGE_BASE_RELOCATION *)relocs;  /* return address of next block */
+}
+
+
+void MyLdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
+                          ULONG_PTR unknown3, ULONG_PTR unknown4 )
+{
+  static const WCHAR globalflagW[] = {'G','l','o','b','a','l','F','l','a','g',0};
+  NTSTATUS status;
+  WINE_MODREF *wm;
+  LPCWSTR load_path = NULL;
+  PEB *peb = current_peb();
+  IMAGE_NT_HEADERS *nt = MyRtlImageNtHeader( peb->ImageBaseAddress );
+  void (*_kernel_start) (void *ptr) = kernel_start;
+
+#if 0
+  if (main_exe_file) NtClose( main_exe_file );  /* at this point the main module is created */
+#endif
+
+  /* allocate the modref for the main exe (if not already done) */
+  wm = get_modref( peb->ImageBaseAddress );
+  assert( wm );
+  if (wm->ldr.Flags & LDR_IMAGE_IS_DLL)
+    {
+      TRACE("%S is a dll, not an executable\n", wm->ldr.FullDllName );
+      exit(1);
+    }
+
+  //  peb->ProcessParameters->ImagePathName = wm->ldr.FullDllName;
+  //  version_init( wm->ldr.FullDllName );
+
+  //  LdrQueryImageFileExecutionOptions( &peb->ProcessParameters->ImagePathName, globalflagW,
+  //                                REG_DWORD, &peb->NtGlobalFlag, sizeof(peb->NtGlobalFlag), NULL );
+
+  /* the main exe needs to be the first in the load order list */
+  //  RemoveEntryList( &wm->ldr.InLoadOrderModuleList );
+  //  InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList );
+
+  //  if ((status = virtual_alloc_thread_stack( NtCurrentTeb(), 0, 0 )) != STATUS_SUCCESS) goto error;
+  //  if ((status = server_init_process_done()) != STATUS_SUCCESS) goto error;
+
+  //  actctx_init();
+  //  load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
+  if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error;
+  //  if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error;
+  //  if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error;
+  //  heap_set_debug_flags( GetProcessHeap() );
+
+#if 0
+  /* FIXME: This may be interesting at some point.  */
+  status = wine_call_on_stack( attach_process_dlls, wm, NtCurrentTeb()->Tib.StackBase );
+  if (status != STATUS_SUCCESS) goto error;
+#endif
+
+  //  virtual_release_address_space( nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE );
+  //  virtual_clear_thread_stack();
+  //  wine_switch_to_stack( start_process, kernel_start, NtCurrentTeb()->Tib.StackBase );
+  // stack( start_process, kernel_start, NtCurrentTeb()->Tib.StackBase );
+  _kernel_start (peb);
+
+ error:
+  TRACE( "Main exe initialization for %S failed, status %x\n",
+        wm->ldr.FullDllName, status);
+        //      peb->ProcessParameters->ImagePathName, status );
+  //  NtTerminateProcess( GetCurrentProcess(), status );
+  exit (1);
+}