First version of DLL preloader.
[wincetools.git] / loader / ntdll_virtual.c
index c76193a..5cb643f 100644 (file)
-/* 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 "himemce.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, 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;
-}
+/* 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, 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