Convert to unix line endings.
[wincetools.git] / loader / ntdll_virtual.c
index 6c19b0f..3940785 100644 (file)
-/* From wine1.2-1.1.42/dlls/ntdll/virtual.c  */\r
-\r
-/*\r
- * Win32 virtual memory functions\r
- *\r
- * Copyright 1997, 2002 Alexandre Julliard\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
-#include <windows.h>\r
-#include <assert.h>\r
-\r
-#include "wine.h"\r
-\r
-/* File view */\r
-typedef struct file_view\r
-{\r
-    void         *base;        /* Base address */\r
-    size_t        size;        /* Size in bytes */\r
-    HANDLE        mapping;     /* Handle to the file mapping */\r
-    unsigned int  protect;     /* Protection for all pages at allocation time */\r
-} FILE_VIEW;\r
-\r
-\r
-# define page_mask  0xfff\r
-# define page_shift 12\r
-# define page_size  0x1000\r
-\r
-\r
-#define ROUND_SIZE(addr,size) \\r
-  (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)\r
-\r
-\r
-static size_t get_mask( ULONG zero_bits )\r
-{\r
-  if (!zero_bits) return 0xffff;  /* allocations are aligned to 64K by default */\r
-  if (zero_bits < page_shift) zero_bits = page_shift;\r
-  return (1 << zero_bits) - 1;\r
-}\r
-\r
-\r
-static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot )\r
-{\r
-  switch(protect & 0xff)\r
-    {\r
-    case PAGE_READONLY:\r
-      *vprot = VPROT_READ;\r
-      break;\r
-    case PAGE_READWRITE:\r
-      *vprot = VPROT_READ | VPROT_WRITE;\r
-      break;\r
-    case PAGE_WRITECOPY:\r
-      *vprot = VPROT_READ | VPROT_WRITECOPY;\r
-      break;\r
-    case PAGE_EXECUTE:\r
-      *vprot = VPROT_EXEC;\r
-      break;\r
-    case PAGE_EXECUTE_READ:\r
-      *vprot = VPROT_EXEC | VPROT_READ;\r
-      break;\r
-    case PAGE_EXECUTE_READWRITE:\r
-      *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITE;\r
-      break;\r
-    case PAGE_EXECUTE_WRITECOPY:\r
-      *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITECOPY;\r
-      break;\r
-    case PAGE_NOACCESS:\r
-      *vprot = 0;\r
-      break;\r
-    default:\r
-      return STATUS_INVALID_PARAMETER;\r
-    }\r
-  if (protect & PAGE_GUARD) *vprot |= VPROT_GUARD;\r
-  if (protect & PAGE_NOCACHE) *vprot |= VPROT_NOCACHE;\r
-  return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static void delete_view( struct file_view *view ) /* [in] View */\r
-{\r
-  VirtualFree (view->base, view->size, MEM_RELEASE);\r
-  // if (view->mapping) NtClose( view->mapping );\r
-  free (view);\r
-}\r
-\r
-\r
-static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, size_t mask,\r
-                          int top_down, unsigned int vprot )\r
-{\r
-  int prot = get_prot_flags (vprot);\r
-  struct file_view *view;\r
-  void *ptr;\r
-  void *new_ptr;\r
-\r
-  view = malloc (sizeof (struct file_view));\r
-  if (!view)\r
-    return STATUS_NO_MEMORY;\r
-  \r
-  // FIXME: Only with NOACCESS does Windows CE prefer the high mem area\r
-  // even for smaller areas.\r
-  ptr = VirtualAlloc(base, size < (2* 1024*1024) ? 2*1024*1024 : size, MEM_RESERVE, PAGE_NOACCESS /*prot*/);\r
-  if (!ptr)\r
-    {\r
-      free (view);\r
-      return GetLastError();\r
-    }\r
-  /* We have to zero map the whole thing.  */\r
-  new_ptr = VirtualAlloc (ptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
-  if (new_ptr != ptr)\r
-    {\r
-      free (view);\r
-      return GetLastError();\r
-    }\r
-  view->base = ptr;\r
-  view->size = size;\r
-  view->protect = vprot;\r
-  view->mapping = 0;\r
-  *view_ret = view;\r
-  return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS map_file_into_view( struct file_view *view, HANDLE fhandle, size_t start, size_t size,\r
-                                    off_t offset, unsigned int vprot, BOOL removable )\r
-{\r
-  void *ptr;\r
-  int prot = get_prot_flags (vprot);\r
-  BOOL shared_write = (vprot & VPROT_WRITE) != 0;\r
-\r
-  assert( start < view->size );\r
-  assert( start + size <= view->size );\r
-\r
-#if 0\r
-  /* only try mmap if media is not removable (or if we require write access) */\r
-  if (!removable || shared_write)\r
-    {\r
-      int flags = MAP_FIXED | (shared_write ? MAP_SHARED : MAP_PRIVATE);\r
-\r
-      if (mmap( (char *)view->base + start, size, prot, flags, fd, offset ) != (void *)-1)\r
-       goto done;\r
-\r
-      /* mmap() failed; if this is because the file offset is not    */\r
-      /* page-aligned (EINVAL), or because the underlying filesystem */\r
-      /* does not support mmap() (ENOEXEC,ENODEV), we do it by hand. */\r
-      if ((errno != ENOEXEC) && (errno != EINVAL) && (errno != ENODEV)) return FILE_GetNtStatus();\r
-      if (shared_write)  /* we cannot fake shared write mappings */\r
-        {\r
-         if (errno == EINVAL) return STATUS_INVALID_PARAMETER;\r
-         ERR( "shared writable mmap not supported, broken filesystem?\n" );\r
-         return STATUS_NOT_SUPPORTED;\r
-        }\r
-    }\r
-#endif\r
-\r
-#if 0\r
-  /* Already done by map_view.  */\r
-  /* Reserve the memory with an anonymous mmap */\r
-  ptr = VirtualAlloc ((char *)view->base + start, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
-  if (ptr == (void *)-1) return GetLastError();\r
-#else\r
-  ptr = (char *)view->base + start;\r
-#endif\r
-\r
-  /* Now read in the file */\r
-  pread( fhandle, ptr, size, offset );\r
-  //  if (prot != (PROT_READ|PROT_WRITE)) mprotect( ptr, size, prot );  /* Set the right protection */\r
-  //done:\r
-  //  memset( view->prot + (start >> page_shift), vprot, ROUND_SIZE(start,size) >> page_shift );\r
-  return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS map_image (HANDLE hmapping, HANDLE hfile, HANDLE hmap, char *base, SIZE_T total_size, SIZE_T mask,\r
-                          SIZE_T header_size, int shared_fd, HANDLE dup_mapping, PVOID *addr_ptr)\r
-{\r
-    IMAGE_DOS_HEADER *dos;\r
-    IMAGE_NT_HEADERS *nt;\r
-    IMAGE_SECTION_HEADER *sec;\r
-    IMAGE_DATA_DIRECTORY *imports;\r
-    NTSTATUS status = STATUS_CONFLICTING_ADDRESSES;\r
-    int i;\r
-    off_t pos;\r
-    DWORD fsize;\r
-    struct file_view *view = NULL;\r
-    char *ptr, *header_end;\r
-    INT_PTR delta = 0;\r
-\r
-\r
-    /* zero-map the whole range */\r
-\r
-    if (base >= (char *)0x110000)  /* make sure the DOS area remains free */\r
-      status = map_view( &view, base, total_size, mask, FALSE,\r
-                        VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY | VPROT_IMAGE );\r
-\r
-    if (status != STATUS_SUCCESS)\r
-      status = map_view( &view, NULL, total_size, mask, FALSE,\r
-                        VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY | VPROT_IMAGE );\r
-\r
-    if (status != STATUS_SUCCESS) goto error;\r
-\r
-    ptr = view->base;\r
-    TRACE( "mapped PE file at %p-%p\n", ptr, ptr + total_size );\r
-\r
-    /* map the header */\r
-    \r
-    fsize = GetFileSize (hfile, NULL);\r
-    if (fsize == INVALID_FILE_SIZE)\r
-      {\r
-       status = GetLastError();\r
-       goto error;\r
-      }\r
-    status = STATUS_INVALID_IMAGE_FORMAT;  /* generic error */\r
-    header_size = min( header_size, fsize );\r
-    if (map_file_into_view( view, hfile, 0, header_size, 0, VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,\r
-                            !dup_mapping ) != STATUS_SUCCESS) goto error;\r
-    dos = (IMAGE_DOS_HEADER *)ptr;\r
-    nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew);\r
-    header_end = ptr + ROUND_SIZE( 0, header_size );\r
-    memset( ptr + header_size, 0, header_end - (ptr + header_size) );\r
-    if ((char *)(nt + 1) > header_end) goto error;\r
-    sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);\r
-    if ((char *)(sec + nt->FileHeader.NumberOfSections) > header_end) goto error;\r
-\r
-    imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;\r
-    if (!imports->Size || !imports->VirtualAddress) imports = NULL;\r
-\r
-    /* check the architecture */\r
-\r
-    if (nt->FileHeader.Machine != IMAGE_FILE_MACHINE_ARM\r
-       && nt->FileHeader.Machine != IMAGE_FILE_MACHINE_THUMB)\r
-       {\r
-         TRACE("Trying to load PE image for unsupported architecture (");\r
-         switch (nt->FileHeader.Machine)\r
-           {\r
-           case IMAGE_FILE_MACHINE_UNKNOWN: TRACE("Unknown"); break;\r
-           case IMAGE_FILE_MACHINE_I386:    TRACE("I386"); break;\r
-           case IMAGE_FILE_MACHINE_R3000:   TRACE("R3000"); break;\r
-           case IMAGE_FILE_MACHINE_R4000:   TRACE("R4000"); break;\r
-           case IMAGE_FILE_MACHINE_R10000:  TRACE("R10000"); break;\r
-           case IMAGE_FILE_MACHINE_ALPHA:   TRACE("Alpha"); break;\r
-           case IMAGE_FILE_MACHINE_POWERPC: TRACE("PowerPC"); break;\r
-           case IMAGE_FILE_MACHINE_IA64:    TRACE("IA-64"); break;\r
-           case IMAGE_FILE_MACHINE_ALPHA64: TRACE("Alpha-64"); break;\r
-           case IMAGE_FILE_MACHINE_ARM:     TRACE("ARM"); break;\r
-           default: TRACE("Unknown-%04x", nt->FileHeader.Machine); break;\r
-           }\r
-         TRACE(")\n");\r
-         goto error;\r
-       }\r
-    \r
-    /* check for non page-aligned binary */\r
-\r
-    if (nt->OptionalHeader.SectionAlignment <= page_mask)\r
-      {\r
-        /* unaligned sections, this happens for native subsystem binaries */\r
-        /* in that case Windows simply maps in the whole file */\r
-\r
-        if (map_file_into_view( view, hfile, 0, total_size, 0, VPROT_COMMITTED | VPROT_READ,\r
-                                !dup_mapping ) != STATUS_SUCCESS) goto error;\r
-\r
-        /* check that all sections are loaded at the right offset */\r
-        if (nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) goto error;\r
-        for (i = 0; i < nt->FileHeader.NumberOfSections; i++)\r
-         {\r
-            if (sec[i].VirtualAddress != sec[i].PointerToRawData)\r
-             goto error;  /* Windows refuses to load in that case too */\r
-         }\r
-#if 0\r
-        /* set the image protections */\r
-        VIRTUAL_SetProt( view, ptr, total_size,\r
-                         VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY | VPROT_EXEC );\r
-#endif\r
-\r
-#if 0\r
-        /* no relocations are performed on non page-aligned binaries */\r
-        goto done;\r
-#else\r
-       goto reloc;\r
-#endif\r
-      }\r
-\r
-\r
-    /* map all the sections */\r
-\r
-    for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)\r
-      {\r
-        static const SIZE_T sector_align = 0x1ff;\r
-        SIZE_T map_size, file_start, file_size, end;\r
-\r
-        if (!sec->Misc.VirtualSize)\r
-         map_size = ROUND_SIZE( 0, sec->SizeOfRawData );\r
-        else\r
-         map_size = ROUND_SIZE( 0, sec->Misc.VirtualSize );\r
-\r
-        /* file positions are rounded to sector boundaries regardless of OptionalHeader.FileAlignment */\r
-        file_start = sec->PointerToRawData & ~sector_align;\r
-        file_size = (sec->SizeOfRawData + (sec->PointerToRawData & sector_align) + sector_align) & ~sector_align;\r
-        if (file_size > map_size) file_size = map_size;\r
-\r
-        /* a few sanity checks */\r
-        end = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, map_size );\r
-        if (sec->VirtualAddress > total_size || end > total_size || end < sec->VirtualAddress)\r
-         {\r
-            ERR ( "Section %.8s too large (%x+%lx/%lx)\n",\r
-                 sec->Name, sec->VirtualAddress, map_size, total_size );\r
-            goto error;\r
-         }\r
-\r
-        if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) &&\r
-            (sec->Characteristics & IMAGE_SCN_MEM_WRITE))\r
-         {\r
-            TRACE( "mapping shared section %.8s at %p off %x (%x) size %lx (%lx) flags %x\n",\r
-                  sec->Name, ptr + sec->VirtualAddress,\r
-                  sec->PointerToRawData, (int)pos, file_size, map_size,\r
-                  sec->Characteristics );\r
-            if (map_file_into_view( view, hfile, sec->VirtualAddress, map_size, pos,\r
-                                    VPROT_COMMITTED | VPROT_READ | VPROT_WRITE,\r
-                                    FALSE ) != STATUS_SUCCESS)\r
-             {\r
-                ERR ( "Could not map shared section %.8s\n", sec->Name );\r
-                goto error;\r
-             }\r
-\r
-            /* check if the import directory falls inside this section */\r
-            if (imports && imports->VirtualAddress >= sec->VirtualAddress &&\r
-                imports->VirtualAddress < sec->VirtualAddress + map_size)\r
-             {\r
-                UINT_PTR base = imports->VirtualAddress & ~page_mask;\r
-                UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size );\r
-                if (end > sec->VirtualAddress + map_size) end = sec->VirtualAddress + map_size;\r
-                if (end > base)\r
-                 map_file_into_view( view, hfile, base, end - base,\r
-                                     pos + (base - sec->VirtualAddress),\r
-                                     VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,\r
-                                     FALSE );\r
-             }\r
-            pos += map_size;\r
-            continue;\r
-         }\r
-\r
-        ERR( "mapping section %.8s at %p off %x size %x virt %x flags %x\n",\r
-            sec->Name, ptr + sec->VirtualAddress,\r
-            sec->PointerToRawData, sec->SizeOfRawData,\r
-            sec->Misc.VirtualSize, sec->Characteristics );\r
-       \r
-        if (!sec->PointerToRawData || !file_size) continue;\r
-\r
-        /* Note: if the section is not aligned properly map_file_into_view will magically\r
-         *       fall back to read(), so we don't need to check anything here.\r
-         */\r
-        end = file_start + file_size;\r
-        if (sec->PointerToRawData >= fsize ||\r
-            end > ((fsize + sector_align) & ~sector_align) ||\r
-            end < file_start ||\r
-            map_file_into_view( view, hfile, sec->VirtualAddress, file_size, file_start,\r
-                                VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,\r
-                                !dup_mapping ) != STATUS_SUCCESS)\r
-         {\r
-            ERR( "Could not map section %.8s, file probably truncated\n", sec->Name );\r
-            goto error;\r
-         }\r
-\r
-        if (file_size & page_mask)\r
-         {\r
-            end = ROUND_SIZE( 0, file_size );\r
-            if (end > map_size) end = map_size;\r
-            TRACE("clearing %p - %p\n",\r
-                 ptr + sec->VirtualAddress + file_size,\r
-                 ptr + sec->VirtualAddress + end );\r
-            memset( ptr + sec->VirtualAddress + file_size, 0, end - file_size );\r
-         }\r
-      }\r
-\r
- reloc:\r
-    /* perform base relocation, if necessary */\r
-\r
-    if (ptr != base)\r
-      // &&\r
-      //        ((nt->FileHeader.Characteristics & IMAGE_FILE_DLL) ||\r
-      //        !NtCurrentTeb()->Peb->ImageBaseAddress) )\r
-      {\r
-        IMAGE_BASE_RELOCATION *rel, *end;\r
-        const IMAGE_DATA_DIRECTORY *relocs;\r
-\r
-        if (nt->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)\r
-         {\r
-            TRACE( "Need to relocate module from %p to %p, but there are no relocation records\n",\r
-                  base, ptr );\r
-            status = STATUS_CONFLICTING_ADDRESSES;\r
-            goto error;\r
-         }\r
-\r
-        TRACE( "relocating from %p-%p to %p-%p\n",\r
-              base, base + total_size, ptr, ptr + total_size );\r
-\r
-        relocs = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
-        rel = (IMAGE_BASE_RELOCATION *)(ptr + relocs->VirtualAddress);\r
-        end = (IMAGE_BASE_RELOCATION *)(ptr + relocs->VirtualAddress + relocs->Size);\r
-        delta = ptr - base;\r
-\r
-        while (rel < end - 1 && rel->SizeOfBlock)\r
-         {\r
-            if (rel->VirtualAddress >= total_size)\r
-             {\r
-                TRACE( "invalid address %p in relocation %p\n", ptr + rel->VirtualAddress, rel );\r
-                status = STATUS_ACCESS_VIOLATION;\r
-                goto error;\r
-             }\r
-            rel = MyLdrProcessRelocationBlock( ptr + rel->VirtualAddress,\r
-                                              (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),\r
-                                              (USHORT *)(rel + 1), delta );\r
-            if (!rel) goto error;\r
-         }\r
-      }\r
-#if 0\r
-    /* set the image protections */\r
-    VIRTUAL_SetProt( view, ptr, ROUND_SIZE( 0, header_size ), VPROT_COMMITTED | VPROT_READ );\r
-\r
-    sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);\r
-    for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)\r
-      {\r
-        SIZE_T size;\r
-        BYTE vprot = VPROT_COMMITTED;\r
-\r
-        if (sec->Misc.VirtualSize)\r
-         size = ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );\r
-        else\r
-         size = ROUND_SIZE( sec->VirtualAddress, sec->SizeOfRawData );\r
-\r
-        if (sec->Characteristics & IMAGE_SCN_MEM_READ)    vprot |= VPROT_READ;\r
-        if (sec->Characteristics & IMAGE_SCN_MEM_WRITE)   vprot |= VPROT_READ|VPROT_WRITECOPY;\r
-        if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC;\r
-\r
-        /* Dumb game crack lets the AOEP point into a data section. Adjust. */\r
-        if ((nt->OptionalHeader.AddressOfEntryPoint >= sec->VirtualAddress) &&\r
-            (nt->OptionalHeader.AddressOfEntryPoint < sec->VirtualAddress + size))\r
-         vprot |= VPROT_EXEC;\r
-\r
-        VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );\r
-      }\r
-#endif\r
-\r
-    // done:\r
-    *addr_ptr = ptr;\r
-#ifdef VALGRIND_LOAD_PDB_DEBUGINFO\r
-    VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta);\r
-#endif\r
-    if (ptr != base) return STATUS_IMAGE_NOT_AT_BASE;\r
-    return STATUS_SUCCESS;\r
-\r
- error:\r
-    if (view) delete_view( view );\r
-    return status;\r
-}\r
-\r
-\r
-NTSTATUS MyNtCreateSection (HANDLE *handle, ACCESS_MASK access,\r
-                           /* const OBJECT_ATTRIBUTES *attr */ void *attr,\r
-                           const LARGE_INTEGER *size, ULONG protect,\r
-                           ULONG sec_flags, HANDLE file)\r
-{\r
-    NTSTATUS ret;\r
-    unsigned int vprot;\r
-    \r
-    if ((ret = get_vprot_flags( protect, &vprot ))) return ret;\r
-\r
-    assert (attr == NULL);\r
-\r
-    if (!(sec_flags & SEC_RESERVE)) vprot |= VPROT_COMMITTED;\r
-    if (sec_flags & SEC_NOCACHE) vprot |= VPROT_NOCACHE;\r
-    if (sec_flags & SEC_IMAGE) vprot |= VPROT_IMAGE;\r
-\r
-    ret = SERVER_create_mapping (access, attr, file, size ? size->QuadPart : 0,\r
-                                vprot, handle);\r
-\r
-    return ret;\r
-}\r
-\r
-\r
-NTSTATUS MyNtMapViewOfSection (HANDLE handle, HANDLE process, PVOID *addr_ptr, ULONG zero_bits,\r
-                              SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr,\r
-                              SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect)\r
-{\r
-  NTSTATUS res;\r
-  mem_size_t full_size;\r
-  ACCESS_MASK access;\r
-  SIZE_T size, mask = get_mask( zero_bits );\r
-  unsigned int map_vprot;\r
-  //  unsigned int vprot;\r
-  void *base;\r
-  //  struct file_view *view;\r
-  DWORD header_size;\r
-  HANDLE fhandle;\r
-  HANDLE mhandle;\r
-  LARGE_INTEGER offset;\r
-\r
-  offset.QuadPart = offset_ptr ? offset_ptr->QuadPart : 0;\r
-\r
-  TRACE("handle=%p process=%p addr=%p off=%x%08x size=%lx access=%x\n",\r
-       handle, process, *addr_ptr, offset.u.HighPart, offset.u.LowPart, *size_ptr, protect );\r
-\r
-  /* Check parameters */\r
-\r
-  if ((offset.u.LowPart & mask) || (*addr_ptr && ((UINT_PTR)*addr_ptr & mask)))\r
-    return STATUS_INVALID_PARAMETER;\r
-\r
-  switch(protect)\r
-    {\r
-    case PAGE_NOACCESS:\r
-      access = 0;\r
-      break;\r
-    case PAGE_READWRITE:\r
-    case PAGE_EXECUTE_READWRITE:\r
-      access = SECTION_MAP_WRITE;\r
-      break;\r
-    case PAGE_READONLY:\r
-    case PAGE_WRITECOPY:\r
-    case PAGE_EXECUTE:\r
-    case PAGE_EXECUTE_READ:\r
-    case PAGE_EXECUTE_WRITECOPY:\r
-      access = SECTION_MAP_READ;\r
-      break;\r
-    default:\r
-      return STATUS_INVALID_PARAMETER;\r
-    }\r
-\r
-  res = SERVER_get_mapping_info (handle, access, &map_vprot, &base, &full_size, &header_size, &fhandle, &mhandle);\r
-  if (res) return res;\r
-\r
-  if (map_vprot & VPROT_IMAGE)\r
-    {\r
-      size = full_size;\r
-      if (size != full_size)  /* truncated */\r
-        {\r
-         TRACE( "Modules larger than 4Gb not supported\n");\r
-         res = STATUS_INVALID_PARAMETER;\r
-         goto done;\r
-        }\r
-      res = map_image( handle, fhandle, mhandle, base, size, mask, header_size,\r
-                      -1, INVALID_HANDLE_VALUE, addr_ptr );\r
-      if (res >= 0) *size_ptr = size;\r
-      return res;\r
-    }\r
-\r
-  assert (!"Not supported");\r
-#if 0\r
-  res = STATUS_INVALID_PARAMETER;\r
-  if (offset.QuadPart >= full_size) goto done;\r
-  if (*size_ptr)\r
-    {\r
-      if (*size_ptr > full_size - offset.QuadPart) goto done;\r
-      size = ROUND_SIZE( offset.u.LowPart, *size_ptr );\r
-      if (size < *size_ptr) goto done;  /* wrap-around */\r
-    }\r
-  else\r
-    {\r
-      size = full_size - offset.QuadPart;\r
-      if (size != full_size - offset.QuadPart)  /* truncated */\r
-        {\r
-         WARN( "Files larger than 4Gb (%s) not supported on this platform\n",\r
-               wine_dbgstr_longlong(full_size) );\r
-         goto done;\r
-        }\r
-    }\r
-\r
-  /* Reserve a properly aligned area */\r
-\r
-  server_enter_uninterrupted_section( &csVirtual, &sigset );\r
-\r
-  get_vprot_flags( protect, &vprot );\r
-  vprot |= (map_vprot & VPROT_COMMITTED);\r
-  res = map_view( &view, *addr_ptr, size, mask, FALSE, vprot );\r
-  if (res)\r
-    {\r
-      server_leave_uninterrupted_section( &csVirtual, &sigset );\r
-      goto done;\r
-    }\r
-\r
-  /* Map the file */\r
-\r
-  TRACE("handle=%p size=%lx offset=%x%08x\n",\r
-       handle, size, offset.u.HighPart, offset.u.LowPart );\r
-\r
-  res = map_file_into_view( view, unix_handle, 0, size, offset.QuadPart, vprot, !dup_mapping );\r
-  if (res == STATUS_SUCCESS)\r
-    {\r
-      *addr_ptr = view->base;\r
-      *size_ptr = size;\r
-      view->mapping = dup_mapping;\r
-      dup_mapping = 0;  /* don't close it */\r
-    }\r
-  else\r
-    {\r
-      ERR( "map_file_into_view %p %lx %x%08x failed\n",\r
-          view->base, size, offset.u.HighPart, offset.u.LowPart );\r
-      delete_view( view );\r
-    }\r
-  \r
-  server_leave_uninterrupted_section( &csVirtual, &sigset );\r
-#endif\r
-\r
- done:\r
-  return res;\r
-\r
-  //  *addr_ptr = MapViewOfFile (handle, \r
-  //                        protect == PAGE_READONLY ? FILE_MAP_READ : FILE_MAP_WRITE,\r
-  //                        offset_ptr ? offset_ptr->HighPart : 0,\r
-  //                        offset_ptr ? offset_ptr->LowPart : 0,\r
-  //                        size_ptr ? size_ptr->LowPart : 0);\r
-  //  if (*addr_ptr == NULL)\r
-  //    return GetLastError ();\r
-  //\r
-  //  return STATUS_SUCCESS;\r
-}\r
+/* From wine1.2-1.1.42/dlls/ntdll/virtual.c  */
+
+/*
+ * Win32 virtual memory functions
+ *
+ * Copyright 1997, 2002 Alexandre Julliard
+ * 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 <windows.h>
+#include <assert.h>
+
+#include "wine.h"
+
+/* File view */
+typedef struct file_view
+{
+    void         *base;        /* Base address */
+    size_t        size;        /* Size in bytes */
+    HANDLE        mapping;     /* Handle to the file mapping */
+    unsigned int  protect;     /* Protection for all pages at allocation time */
+} FILE_VIEW;
+
+
+# define page_mask  0xfff
+# define page_shift 12
+# define page_size  0x1000
+
+
+#define ROUND_SIZE(addr,size) \
+  (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
+
+
+static size_t get_mask( ULONG zero_bits )
+{
+  if (!zero_bits) return 0xffff;  /* allocations are aligned to 64K by default */
+  if (zero_bits < page_shift) zero_bits = page_shift;
+  return (1 << zero_bits) - 1;
+}
+
+
+static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot )
+{
+  switch(protect & 0xff)
+    {
+    case PAGE_READONLY:
+      *vprot = VPROT_READ;
+      break;
+    case PAGE_READWRITE:
+      *vprot = VPROT_READ | VPROT_WRITE;
+      break;
+    case PAGE_WRITECOPY:
+      *vprot = VPROT_READ | VPROT_WRITECOPY;
+      break;
+    case PAGE_EXECUTE:
+      *vprot = VPROT_EXEC;
+      break;
+    case PAGE_EXECUTE_READ:
+      *vprot = VPROT_EXEC | VPROT_READ;
+      break;
+    case PAGE_EXECUTE_READWRITE:
+      *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITE;
+      break;
+    case PAGE_EXECUTE_WRITECOPY:
+      *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITECOPY;
+      break;
+    case PAGE_NOACCESS:
+      *vprot = 0;
+      break;
+    default:
+      return STATUS_INVALID_PARAMETER;
+    }
+  if (protect & PAGE_GUARD) *vprot |= VPROT_GUARD;
+  if (protect & PAGE_NOCACHE) *vprot |= VPROT_NOCACHE;
+  return STATUS_SUCCESS;
+}
+
+
+static void delete_view( struct file_view *view ) /* [in] View */
+{
+  VirtualFree (view->base, view->size, MEM_RELEASE);
+  // if (view->mapping) NtClose( view->mapping );
+  free (view);
+}
+
+
+static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, size_t mask,
+                          int top_down, unsigned int vprot )
+{
+  int prot = get_prot_flags (vprot);
+  struct file_view *view;
+  void *ptr;
+  void *new_ptr;
+
+  view = malloc (sizeof (struct file_view));
+  if (!view)
+    return STATUS_NO_MEMORY;
+  
+  // FIXME: Only with NOACCESS does Windows CE prefer the high mem area
+  // even for smaller areas.
+  ptr = VirtualAlloc(base, size < (2* 1024*1024) ? 2*1024*1024 : size, MEM_RESERVE, PAGE_NOACCESS /*prot*/);
+  if (!ptr)
+    {
+      free (view);
+      return GetLastError();
+    }
+  /* We have to zero map the whole thing.  */
+  new_ptr = VirtualAlloc (ptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+  if (new_ptr != ptr)
+    {
+      free (view);
+      return GetLastError();
+    }
+  view->base = ptr;
+  view->size = size;
+  view->protect = vprot;
+  view->mapping = 0;
+  *view_ret = view;
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS map_file_into_view( struct file_view *view, HANDLE fhandle, size_t start, size_t size,
+                                    off_t offset, unsigned int vprot, BOOL removable )
+{
+  void *ptr;
+  int prot = get_prot_flags (vprot);
+  BOOL shared_write = (vprot & VPROT_WRITE) != 0;
+
+  assert( start < view->size );
+  assert( start + size <= view->size );
+
+#if 0
+  /* only try mmap if media is not removable (or if we require write access) */
+  if (!removable || shared_write)
+    {
+      int flags = MAP_FIXED | (shared_write ? MAP_SHARED : MAP_PRIVATE);
+
+      if (mmap( (char *)view->base + start, size, prot, flags, fd, offset ) != (void *)-1)
+       goto done;
+
+      /* mmap() failed; if this is because the file offset is not    */
+      /* page-aligned (EINVAL), or because the underlying filesystem */
+      /* does not support mmap() (ENOEXEC,ENODEV), we do it by hand. */
+      if ((errno != ENOEXEC) && (errno != EINVAL) && (errno != ENODEV)) return FILE_GetNtStatus();
+      if (shared_write)  /* we cannot fake shared write mappings */
+        {
+         if (errno == EINVAL) return STATUS_INVALID_PARAMETER;
+         ERR( "shared writable mmap not supported, broken filesystem?\n" );
+         return STATUS_NOT_SUPPORTED;
+        }
+    }
+#endif
+
+#if 0
+  /* Already done by map_view.  */
+  /* Reserve the memory with an anonymous mmap */
+  ptr = VirtualAlloc ((char *)view->base + start, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+  if (ptr == (void *)-1) return GetLastError();
+#else
+  ptr = (char *)view->base + start;
+#endif
+
+  /* Now read in the file */
+  pread( fhandle, ptr, size, offset );
+  //  if (prot != (PROT_READ|PROT_WRITE)) mprotect( ptr, size, prot );  /* Set the right protection */
+  //done:
+  //  memset( view->prot + (start >> page_shift), vprot, ROUND_SIZE(start,size) >> page_shift );
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS map_image (HANDLE hmapping, HANDLE hfile, HANDLE hmap, char *base, SIZE_T total_size, SIZE_T mask,
+                          SIZE_T header_size, int shared_fd, HANDLE dup_mapping, PVOID *addr_ptr)
+{
+    IMAGE_DOS_HEADER *dos;
+    IMAGE_NT_HEADERS *nt;
+    IMAGE_SECTION_HEADER *sec;
+    IMAGE_DATA_DIRECTORY *imports;
+    NTSTATUS status = STATUS_CONFLICTING_ADDRESSES;
+    int i;
+    off_t pos;
+    DWORD fsize;
+    struct file_view *view = NULL;
+    char *ptr, *header_end;
+    INT_PTR delta = 0;
+
+
+    /* zero-map the whole range */
+
+    if (base >= (char *)0x110000)  /* make sure the DOS area remains free */
+      status = map_view( &view, base, total_size, mask, FALSE,
+                        VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY | VPROT_IMAGE );
+
+    if (status != STATUS_SUCCESS)
+      status = map_view( &view, NULL, total_size, mask, FALSE,
+                        VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY | VPROT_IMAGE );
+
+    if (status != STATUS_SUCCESS) goto error;
+
+    ptr = view->base;
+    TRACE( "mapped PE file at %p-%p\n", ptr, ptr + total_size );
+
+    /* map the header */
+    
+    fsize = GetFileSize (hfile, NULL);
+    if (fsize == INVALID_FILE_SIZE)
+      {
+       status = GetLastError();
+       goto error;
+      }
+    status = STATUS_INVALID_IMAGE_FORMAT;  /* generic error */
+    header_size = min( header_size, fsize );
+    if (map_file_into_view( view, hfile, 0, header_size, 0, VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
+                            !dup_mapping ) != STATUS_SUCCESS) goto error;
+    dos = (IMAGE_DOS_HEADER *)ptr;
+    nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew);
+    header_end = ptr + ROUND_SIZE( 0, header_size );
+    memset( ptr + header_size, 0, header_end - (ptr + header_size) );
+    if ((char *)(nt + 1) > header_end) goto error;
+    sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
+    if ((char *)(sec + nt->FileHeader.NumberOfSections) > header_end) goto error;
+
+    imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;
+    if (!imports->Size || !imports->VirtualAddress) imports = NULL;
+
+    /* check the architecture */
+
+    if (nt->FileHeader.Machine != IMAGE_FILE_MACHINE_ARM
+       && nt->FileHeader.Machine != IMAGE_FILE_MACHINE_THUMB)
+       {
+         TRACE("Trying to load PE image for unsupported architecture (");
+         switch (nt->FileHeader.Machine)
+           {
+           case IMAGE_FILE_MACHINE_UNKNOWN: TRACE("Unknown"); break;
+           case IMAGE_FILE_MACHINE_I386:    TRACE("I386"); break;
+           case IMAGE_FILE_MACHINE_R3000:   TRACE("R3000"); break;
+           case IMAGE_FILE_MACHINE_R4000:   TRACE("R4000"); break;
+           case IMAGE_FILE_MACHINE_R10000:  TRACE("R10000"); break;
+           case IMAGE_FILE_MACHINE_ALPHA:   TRACE("Alpha"); break;
+           case IMAGE_FILE_MACHINE_POWERPC: TRACE("PowerPC"); break;
+           case IMAGE_FILE_MACHINE_IA64:    TRACE("IA-64"); break;
+           case IMAGE_FILE_MACHINE_ALPHA64: TRACE("Alpha-64"); break;
+           case IMAGE_FILE_MACHINE_ARM:     TRACE("ARM"); break;
+           default: TRACE("Unknown-%04x", nt->FileHeader.Machine); break;
+           }
+         TRACE(")\n");
+         goto error;
+       }
+    
+    /* check for non page-aligned binary */
+
+    if (nt->OptionalHeader.SectionAlignment <= page_mask)
+      {
+        /* unaligned sections, this happens for native subsystem binaries */
+        /* in that case Windows simply maps in the whole file */
+
+        if (map_file_into_view( view, hfile, 0, total_size, 0, VPROT_COMMITTED | VPROT_READ,
+                                !dup_mapping ) != STATUS_SUCCESS) goto error;
+
+        /* check that all sections are loaded at the right offset */
+        if (nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) goto error;
+        for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
+         {
+            if (sec[i].VirtualAddress != sec[i].PointerToRawData)
+             goto error;  /* Windows refuses to load in that case too */
+         }
+#if 0
+        /* set the image protections */
+        VIRTUAL_SetProt( view, ptr, total_size,
+                         VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY | VPROT_EXEC );
+#endif
+
+#if 0
+        /* no relocations are performed on non page-aligned binaries */
+        goto done;
+#else
+       goto reloc;
+#endif
+      }
+
+
+    /* map all the sections */
+
+    for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
+      {
+        static const SIZE_T sector_align = 0x1ff;
+        SIZE_T map_size, file_start, file_size, end;
+
+        if (!sec->Misc.VirtualSize)
+         map_size = ROUND_SIZE( 0, sec->SizeOfRawData );
+        else
+         map_size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
+
+        /* file positions are rounded to sector boundaries regardless of OptionalHeader.FileAlignment */
+        file_start = sec->PointerToRawData & ~sector_align;
+        file_size = (sec->SizeOfRawData + (sec->PointerToRawData & sector_align) + sector_align) & ~sector_align;
+        if (file_size > map_size) file_size = map_size;
+
+        /* a few sanity checks */
+        end = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, map_size );
+        if (sec->VirtualAddress > total_size || end > total_size || end < sec->VirtualAddress)
+         {
+            ERR ( "Section %.8s too large (%x+%lx/%lx)\n",
+                 sec->Name, sec->VirtualAddress, map_size, total_size );
+            goto error;
+         }
+
+        if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) &&
+            (sec->Characteristics & IMAGE_SCN_MEM_WRITE))
+         {
+            TRACE( "mapping shared section %.8s at %p off %x (%x) size %lx (%lx) flags %x\n",
+                  sec->Name, ptr + sec->VirtualAddress,
+                  sec->PointerToRawData, (int)pos, file_size, map_size,
+                  sec->Characteristics );
+            if (map_file_into_view( view, hfile, sec->VirtualAddress, map_size, pos,
+                                    VPROT_COMMITTED | VPROT_READ | VPROT_WRITE,
+                                    FALSE ) != STATUS_SUCCESS)
+             {
+                ERR ( "Could not map shared section %.8s\n", sec->Name );
+                goto error;
+             }
+
+            /* check if the import directory falls inside this section */
+            if (imports && imports->VirtualAddress >= sec->VirtualAddress &&
+                imports->VirtualAddress < sec->VirtualAddress + map_size)
+             {
+                UINT_PTR base = imports->VirtualAddress & ~page_mask;
+                UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size );
+                if (end > sec->VirtualAddress + map_size) end = sec->VirtualAddress + map_size;
+                if (end > base)
+                 map_file_into_view( view, hfile, base, end - base,
+                                     pos + (base - sec->VirtualAddress),
+                                     VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
+                                     FALSE );
+             }
+            pos += map_size;
+            continue;
+         }
+
+        ERR( "mapping section %.8s at %p off %x size %x virt %x flags %x\n",
+            sec->Name, ptr + sec->VirtualAddress,
+            sec->PointerToRawData, sec->SizeOfRawData,
+            sec->Misc.VirtualSize, sec->Characteristics );
+       
+        if (!sec->PointerToRawData || !file_size) continue;
+
+        /* Note: if the section is not aligned properly map_file_into_view will magically
+         *       fall back to read(), so we don't need to check anything here.
+         */
+        end = file_start + file_size;
+        if (sec->PointerToRawData >= fsize ||
+            end > ((fsize + sector_align) & ~sector_align) ||
+            end < file_start ||
+            map_file_into_view( view, hfile, sec->VirtualAddress, file_size, file_start,
+                                VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
+                                !dup_mapping ) != STATUS_SUCCESS)
+         {
+            ERR( "Could not map section %.8s, file probably truncated\n", sec->Name );
+            goto error;
+         }
+
+        if (file_size & page_mask)
+         {
+            end = ROUND_SIZE( 0, file_size );
+            if (end > map_size) end = map_size;
+            TRACE("clearing %p - %p\n",
+                 ptr + sec->VirtualAddress + file_size,
+                 ptr + sec->VirtualAddress + end );
+            memset( ptr + sec->VirtualAddress + file_size, 0, end - file_size );
+         }
+      }
+
+ reloc:
+    /* perform base relocation, if necessary */
+
+    if (ptr != base)
+      // &&
+      //        ((nt->FileHeader.Characteristics & IMAGE_FILE_DLL) ||
+      //        !NtCurrentTeb()->Peb->ImageBaseAddress) )
+      {
+        IMAGE_BASE_RELOCATION *rel, *end;
+        const IMAGE_DATA_DIRECTORY *relocs;
+
+        if (nt->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+         {
+            TRACE( "Need to relocate module from %p to %p, but there are no relocation records\n",
+                  base, ptr );
+            status = STATUS_CONFLICTING_ADDRESSES;
+            goto error;
+         }
+
+        TRACE( "relocating from %p-%p to %p-%p\n",
+              base, base + total_size, ptr, ptr + total_size );
+
+        relocs = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+        rel = (IMAGE_BASE_RELOCATION *)(ptr + relocs->VirtualAddress);
+        end = (IMAGE_BASE_RELOCATION *)(ptr + relocs->VirtualAddress + relocs->Size);
+        delta = ptr - base;
+
+        while (rel < end - 1 && rel->SizeOfBlock)
+         {
+            if (rel->VirtualAddress >= total_size)
+             {
+                TRACE( "invalid address %p in relocation %p\n", ptr + rel->VirtualAddress, rel );
+                status = STATUS_ACCESS_VIOLATION;
+                goto error;
+             }
+            rel = MyLdrProcessRelocationBlock( ptr + rel->VirtualAddress,
+                                              (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
+                                              (USHORT *)(rel + 1), delta );
+            if (!rel) goto error;
+         }
+      }
+#if 0
+    /* set the image protections */
+    VIRTUAL_SetProt( view, ptr, ROUND_SIZE( 0, header_size ), VPROT_COMMITTED | VPROT_READ );
+
+    sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
+    for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
+      {
+        SIZE_T size;
+        BYTE vprot = VPROT_COMMITTED;
+
+        if (sec->Misc.VirtualSize)
+         size = ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
+        else
+         size = ROUND_SIZE( sec->VirtualAddress, sec->SizeOfRawData );
+
+        if (sec->Characteristics & IMAGE_SCN_MEM_READ)    vprot |= VPROT_READ;
+        if (sec->Characteristics & IMAGE_SCN_MEM_WRITE)   vprot |= VPROT_READ|VPROT_WRITECOPY;
+        if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC;
+
+        /* Dumb game crack lets the AOEP point into a data section. Adjust. */
+        if ((nt->OptionalHeader.AddressOfEntryPoint >= sec->VirtualAddress) &&
+            (nt->OptionalHeader.AddressOfEntryPoint < sec->VirtualAddress + size))
+         vprot |= VPROT_EXEC;
+
+        VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );
+      }
+#endif
+
+    // done:
+    *addr_ptr = ptr;
+#ifdef VALGRIND_LOAD_PDB_DEBUGINFO
+    VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta);
+#endif
+    if (ptr != base) return STATUS_IMAGE_NOT_AT_BASE;
+    return STATUS_SUCCESS;
+
+ error:
+    if (view) delete_view( view );
+    return status;
+}
+
+
+NTSTATUS MyNtCreateSection (HANDLE *handle, ACCESS_MASK access,
+                           /* const OBJECT_ATTRIBUTES *attr */ void *attr,
+                           const LARGE_INTEGER *size, ULONG protect,
+                           ULONG sec_flags, HANDLE file)
+{
+    NTSTATUS ret;
+    unsigned int vprot;
+    
+    if ((ret = get_vprot_flags( protect, &vprot ))) return ret;
+
+    assert (attr == NULL);
+
+    if (!(sec_flags & SEC_RESERVE)) vprot |= VPROT_COMMITTED;
+    if (sec_flags & SEC_NOCACHE) vprot |= VPROT_NOCACHE;
+    if (sec_flags & SEC_IMAGE) vprot |= VPROT_IMAGE;
+
+    ret = SERVER_create_mapping (access, attr, file, size ? size->QuadPart : 0,
+                                vprot, handle);
+
+    return ret;
+}
+
+
+NTSTATUS MyNtMapViewOfSection (HANDLE handle, HANDLE process, PVOID *addr_ptr, ULONG zero_bits,
+                              SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr,
+                              SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect)
+{
+  NTSTATUS res;
+  mem_size_t full_size;
+  ACCESS_MASK access;
+  SIZE_T size, mask = get_mask( zero_bits );
+  unsigned int map_vprot;
+  //  unsigned int vprot;
+  void *base;
+  //  struct file_view *view;
+  DWORD header_size;
+  HANDLE fhandle;
+  HANDLE mhandle;
+  LARGE_INTEGER offset;
+
+  offset.QuadPart = offset_ptr ? offset_ptr->QuadPart : 0;
+
+  TRACE("handle=%p process=%p addr=%p off=%x%08x size=%lx access=%x\n",
+       handle, process, *addr_ptr, offset.u.HighPart, offset.u.LowPart, *size_ptr, protect );
+
+  /* Check parameters */
+
+  if ((offset.u.LowPart & mask) || (*addr_ptr && ((UINT_PTR)*addr_ptr & mask)))
+    return STATUS_INVALID_PARAMETER;
+
+  switch(protect)
+    {
+    case PAGE_NOACCESS:
+      access = 0;
+      break;
+    case PAGE_READWRITE:
+    case PAGE_EXECUTE_READWRITE:
+      access = SECTION_MAP_WRITE;
+      break;
+    case PAGE_READONLY:
+    case PAGE_WRITECOPY:
+    case PAGE_EXECUTE:
+    case PAGE_EXECUTE_READ:
+    case PAGE_EXECUTE_WRITECOPY:
+      access = SECTION_MAP_READ;
+      break;
+    default:
+      return STATUS_INVALID_PARAMETER;
+    }
+
+  res = SERVER_get_mapping_info (handle, access, &map_vprot, &base, &full_size, &header_size, &fhandle, &mhandle);
+  if (res) return res;
+
+  if (map_vprot & VPROT_IMAGE)
+    {
+      size = full_size;
+      if (size != full_size)  /* truncated */
+        {
+         TRACE( "Modules larger than 4Gb not supported\n");
+         res = STATUS_INVALID_PARAMETER;
+         goto done;
+        }
+      res = map_image( handle, fhandle, mhandle, base, size, mask, header_size,
+                      -1, INVALID_HANDLE_VALUE, addr_ptr );
+      if (res >= 0) *size_ptr = size;
+      return res;
+    }
+
+  assert (!"Not supported");
+#if 0
+  res = STATUS_INVALID_PARAMETER;
+  if (offset.QuadPart >= full_size) goto done;
+  if (*size_ptr)
+    {
+      if (*size_ptr > full_size - offset.QuadPart) goto done;
+      size = ROUND_SIZE( offset.u.LowPart, *size_ptr );
+      if (size < *size_ptr) goto done;  /* wrap-around */
+    }
+  else
+    {
+      size = full_size - offset.QuadPart;
+      if (size != full_size - offset.QuadPart)  /* truncated */
+        {
+         WARN( "Files larger than 4Gb (%s) not supported on this platform\n",
+               wine_dbgstr_longlong(full_size) );
+         goto done;
+        }
+    }
+
+  /* Reserve a properly aligned area */
+
+  server_enter_uninterrupted_section( &csVirtual, &sigset );
+
+  get_vprot_flags( protect, &vprot );
+  vprot |= (map_vprot & VPROT_COMMITTED);
+  res = map_view( &view, *addr_ptr, size, mask, FALSE, vprot );
+  if (res)
+    {
+      server_leave_uninterrupted_section( &csVirtual, &sigset );
+      goto done;
+    }
+
+  /* Map the file */
+
+  TRACE("handle=%p size=%lx offset=%x%08x\n",
+       handle, size, offset.u.HighPart, offset.u.LowPart );
+
+  res = map_file_into_view( view, unix_handle, 0, size, offset.QuadPart, vprot, !dup_mapping );
+  if (res == STATUS_SUCCESS)
+    {
+      *addr_ptr = view->base;
+      *size_ptr = size;
+      view->mapping = dup_mapping;
+      dup_mapping = 0;  /* don't close it */
+    }
+  else
+    {
+      ERR( "map_file_into_view %p %lx %x%08x failed\n",
+          view->base, size, offset.u.HighPart, offset.u.LowPart );
+      delete_view( view );
+    }
+  
+  server_leave_uninterrupted_section( &csVirtual, &sigset );
+#endif
+
+ done:
+  return res;
+
+  //  *addr_ptr = MapViewOfFile (handle, 
+  //                        protect == PAGE_READONLY ? FILE_MAP_READ : FILE_MAP_WRITE,
+  //                        offset_ptr ? offset_ptr->HighPart : 0,
+  //                        offset_ptr ? offset_ptr->LowPart : 0,
+  //                        size_ptr ? size_ptr->LowPart : 0);
+  //  if (*addr_ptr == NULL)
+  //    return GetLastError ();
+  //
+  //  return STATUS_SUCCESS;
+}