Implemented the ntdll virtual memory functions, and made the kernel
functions use them.

diff --git a/dlls/kernel/kernel32.spec b/dlls/kernel/kernel32.spec
index c688d8e..a556b9a 100644
--- a/dlls/kernel/kernel32.spec
+++ b/dlls/kernel/kernel32.spec
@@ -940,7 +940,7 @@
 @ stdcall SwitchToThread() SwitchToThread
 @ forward TryEnterCriticalSection ntdll.RtlTryEnterCriticalSection
 @ stdcall VirtualAllocEx(long ptr long long long) VirtualAllocEx
-@ stub VirtualFreeEx
+@ stdcall VirtualFreeEx(long ptr long long) VirtualFreeEx
 @ stub WriteFileGather
 
 #Win98 and higher
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index e32a216..b52124e 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -111,6 +111,7 @@
 	signal_powerpc.c \
 	signal_sparc.c \
 	sync.c \
+	virtual.c \
 	time.c \
 	wcstring.c
 
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index 321bbe8..7367503 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -293,17 +293,16 @@
     size = (size + COMMIT_MASK) & ~COMMIT_MASK;
     if (size > subheap->size) size = subheap->size;
     if (size <= subheap->commitSize) return TRUE;
-    if (!VirtualAlloc( (char *)subheap + subheap->commitSize,
-                       size - subheap->commitSize, MEM_COMMIT,
-                       PAGE_EXECUTE_READWRITE))
+    size -= subheap->commitSize;
+    if (NtAllocateVirtualMemory( GetCurrentProcess(), &ptr, (char *)subheap + subheap->commitSize,
+                                 &size, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
     {
         WARN("Could not commit %08lx bytes at %08lx for heap %08lx\n",
-                 size - subheap->commitSize,
-                 (DWORD)((char *)subheap + subheap->commitSize),
+                 size, (DWORD)((char *)subheap + subheap->commitSize),
                  (DWORD)subheap->heap );
         return FALSE;
     }
-    subheap->commitSize = size;
+    subheap->commitSize += size;
     return TRUE;
 }
 
@@ -315,20 +314,23 @@
  */
 static inline BOOL HEAP_Decommit( SUBHEAP *subheap, void *ptr )
 {
+    void *addr;
+    ULONG decommit_size;
+
     DWORD size = (DWORD)((char *)ptr - (char *)subheap);
     /* round to next block and add one full block */
     size = ((size + COMMIT_MASK) & ~COMMIT_MASK) + COMMIT_MASK + 1;
     if (size >= subheap->commitSize) return TRUE;
-    if (!VirtualFree( (char *)subheap + size,
-                      subheap->commitSize - size, MEM_DECOMMIT ))
+    decommit_size = subheap->commitSize - size;
+    addr = (char *)subheap + size;
+
+    if (NtFreeVirtualMemory( GetCurrentProcess(), &addr, &decommit_size, MEM_DECOMMIT ))
     {
-        WARN("Could not decommit %08lx bytes at %08lx for heap %08lx\n",
-                 subheap->commitSize - size,
-                 (DWORD)((char *)subheap + size),
-                 (DWORD)subheap->heap );
+        WARN("Could not decommit %08lx bytes at %08lx for heap %p\n",
+                 decommit_size, (DWORD)((char *)subheap + size), subheap->heap );
         return FALSE;
     }
-    subheap->commitSize = size;
+    subheap->commitSize -= decommit_size;
     return TRUE;
 }
 
@@ -472,7 +474,7 @@
 static BOOL HEAP_InitSubHeap( HEAP *heap, LPVOID address, DWORD flags,
                                 DWORD commitSize, DWORD totalSize )
 {
-    SUBHEAP *subheap = (SUBHEAP *)address;
+    SUBHEAP *subheap;
     FREE_LIST_ENTRY *pEntry;
     int i;
 
@@ -480,15 +482,16 @@
 
     if (flags & HEAP_SHARED)
         commitSize = totalSize;  /* always commit everything in a shared heap */
-    if (!VirtualAlloc(address, commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
+    if (NtAllocateVirtualMemory( GetCurrentProcess(), &address, address,
+                                 &commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
     {
-        WARN("Could not commit %08lx bytes for sub-heap %08lx\n",
-                   commitSize, (DWORD)address );
+        WARN("Could not commit %08lx bytes for sub-heap %p\n", commitSize, address );
         return FALSE;
     }
 
     /* Fill the sub-heap structure */
 
+    subheap = (SUBHEAP *)address;
     subheap->heap       = heap;
     subheap->size       = totalSize;
     subheap->commitSize = commitSize;
@@ -560,10 +563,10 @@
     if (!address)
     {
         /* allocate the memory block */
-        if (!(address = VirtualAlloc( NULL, totalSize, MEM_RESERVE, PAGE_EXECUTE_READWRITE )))
+        if (NtAllocateVirtualMemory( GetCurrentProcess(), &address, NULL, &totalSize,
+                                     MEM_RESERVE, PAGE_EXECUTE_READWRITE ))
         {
-            WARN("Could not VirtualAlloc %08lx bytes\n",
-                 totalSize );
+            WARN("Could not allocate %08lx bytes\n", totalSize );
             return NULL;
         }
     }
@@ -573,7 +576,8 @@
     if (!HEAP_InitSubHeap( heap ? heap : (HEAP *)address,
                            address, flags, commitSize, totalSize ))
     {
-        if (!base) VirtualFree( address, 0, MEM_RELEASE );
+        ULONG size = 0;
+        if (!base) NtFreeVirtualMemory( GetCurrentProcess(), &address, &size, MEM_RELEASE );
         return NULL;
     }
 
@@ -988,7 +992,9 @@
     while (subheap)
     {
         SUBHEAP *next = subheap->next;
-        VirtualFree( subheap, 0, MEM_RELEASE );
+        ULONG size = 0;
+        void *addr = subheap;
+        NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE );
         subheap = next;
     }
     return 0;
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index aec0229..f000929 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -418,41 +418,6 @@
  */
 
 /******************************************************************************
- *  NtCreateSection	[NTDLL.@]
- *  ZwCreateSection	[NTDLL.@]
- */
-NTSTATUS WINAPI NtCreateSection(
-	OUT PHANDLE SectionHandle,
-	IN ACCESS_MASK DesiredAccess,
-	IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
-	IN PLARGE_INTEGER MaximumSize OPTIONAL,
-	IN ULONG SectionPageProtection OPTIONAL,
-	IN ULONG AllocationAttributes,
-	IN HANDLE FileHandle OPTIONAL)
-{
-	FIXME("(%p,0x%08lx,%p,%p,0x%08lx,0x%08lx,0x%08x) stub\n",
-	SectionHandle,DesiredAccess, ObjectAttributes,
-	MaximumSize,SectionPageProtection,AllocationAttributes,FileHandle);
-	dump_ObjectAttributes(ObjectAttributes);
-	return 0;
-}
-
-/******************************************************************************
- *  NtOpenSection	[NTDLL.@]
- *  ZwOpenSection	[NTDLL.@]
- */
-NTSTATUS WINAPI NtOpenSection(
-	PHANDLE SectionHandle,
-	ACCESS_MASK DesiredAccess,
-	POBJECT_ATTRIBUTES ObjectAttributes)
-{
-	FIXME("(%p,0x%08lx,%p),stub!\n",
-	SectionHandle,DesiredAccess,ObjectAttributes);
-	dump_ObjectAttributes(ObjectAttributes);
-	return 0;
-}
-
-/******************************************************************************
  *  NtQuerySection	[NTDLL.@]
  */
 NTSTATUS WINAPI NtQuerySection(
@@ -467,44 +432,6 @@
 	return 0;
 }
 
-/******************************************************************************
- * NtMapViewOfSection	[NTDLL.@]
- * ZwMapViewOfSection	[NTDLL.@]
- * FUNCTION: Maps a view of a section into the virtual address space of a process
- *
- * ARGUMENTS:
- *  SectionHandle	Handle of the section
- *  ProcessHandle	Handle of the process
- *  BaseAddress		Desired base address (or NULL) on entry
- *			Actual base address of the view on exit
- *  ZeroBits		Number of high order address bits that must be zero
- *  CommitSize		Size in bytes of the initially committed section of the view
- *  SectionOffset	Offset in bytes from the beginning of the section to the beginning of the view
- *  ViewSize		Desired length of map (or zero to map all) on entry
- 			Actual length mapped on exit
- *  InheritDisposition	Specified how the view is to be shared with
- *			child processes
- *  AllocateType	Type of allocation for the pages
- *  Protect		Protection for the committed region of the view
- */
-NTSTATUS WINAPI NtMapViewOfSection(
-	HANDLE SectionHandle,
-	HANDLE ProcessHandle,
-	PVOID* BaseAddress,
-	ULONG ZeroBits,
-	ULONG CommitSize,
-	PLARGE_INTEGER SectionOffset,
-	PULONG ViewSize,
-	SECTION_INHERIT InheritDisposition,
-	ULONG AllocationType,
-	ULONG Protect)
-{
-	FIXME("(0x%08x,0x%08x,%p,0x%08lx,0x%08lx,%p,%p,0x%08x,0x%08lx,0x%08lx) stub\n",
-	SectionHandle,ProcessHandle,BaseAddress,ZeroBits,CommitSize,SectionOffset,
-	ViewSize,InheritDisposition,AllocationType,Protect);
-	return 0;
-}
-
 /*
  *	ports
  */
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index fdc0ffa..75df84c 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -63,7 +63,7 @@
 @ stub NtAlertThread
 @ stdcall NtAllocateLocallyUniqueId(ptr) NtAllocateLocallyUniqueId
 @ stdcall NtAllocateUuids(ptr ptr ptr) NtAllocateUuids
-@ stub NtAllocateVirtualMemory
+@ stdcall NtAllocateVirtualMemory(long ptr ptr ptr long long) NtAllocateVirtualMemory
 @ stub NtCallbackReturn
 @ stub NtCancelIoFile
 @ stub NtCancelTimer
@@ -86,7 +86,7 @@
 @ stdcall NtCreatePort(long long long long long) NtCreatePort
 @ stub NtCreateProcess
 @ stub NtCreateProfile
-@ stdcall NtCreateSection(long long long long long long long) NtCreateSection
+@ stdcall NtCreateSection(ptr long ptr ptr long long long) NtCreateSection
 @ stdcall NtCreateSemaphore(ptr long ptr long long) NtCreateSemaphore
 @ stdcall NtCreateSymbolicLinkObject(ptr long ptr ptr) NtCreateSymbolicLinkObject
 @ stub NtCreateThread
@@ -108,9 +108,9 @@
 @ stub NtFlushBuffersFile
 @ stub NtFlushInstructionCache
 @ stdcall NtFlushKey(long) NtFlushKey
-@ stub NtFlushVirtualMemory
+@ stdcall NtFlushVirtualMemory(long ptr ptr long) NtFlushVirtualMemory
 @ stub NtFlushWriteBuffer
-@ stub NtFreeVirtualMemory
+@ stdcall NtFreeVirtualMemory(long ptr ptr long) NtFreeVirtualMemory
 @ stdcall NtFsControlFile(long long long long long long long long long long) NtFsControlFile
 @ stub NtGetContextThread
 @ stub NtGetPlugPlayEvent
@@ -122,9 +122,9 @@
 @ stub NtLoadDriver
 @ stdcall NtLoadKey(ptr ptr) NtLoadKey
 @ stub NtLockFile
-@ stub NtLockVirtualMemory
+@ stdcall NtLockVirtualMemory(long ptr ptr long) NtLockVirtualMemory
 @ stub NtMakeTemporaryObject
-@ stdcall NtMapViewOfSection(long long long long long long long long long long) NtMapViewOfSection
+@ stdcall NtMapViewOfSection(long long ptr long long ptr ptr long long long) NtMapViewOfSection
 @ stub NtNotifyChangeDirectoryFile
 @ stdcall NtNotifyChangeKey(long long ptr ptr ptr long long ptr long long) NtNotifyChangeKey
 @ stdcall NtOpenDirectoryObject(long long long) NtOpenDirectoryObject
@@ -137,7 +137,7 @@
 @ stub NtOpenObjectAuditAlarm
 @ stub NtOpenProcess
 @ stdcall NtOpenProcessToken(long long long) NtOpenProcessToken
-@ stdcall NtOpenSection(long long long) NtOpenSection
+@ stdcall NtOpenSection(ptr long ptr) NtOpenSection
 @ stdcall NtOpenSemaphore(long long ptr) NtOpenSemaphore
 @ stdcall NtOpenSymbolicLinkObject (long long long) NtOpenSymbolicLinkObject
 @ stub NtOpenThread
@@ -147,7 +147,7 @@
 @ stub NtPrivilegeCheck
 @ stub NtPrivilegeObjectAuditAlarm
 @ stub NtPrivilegedServiceAuditAlarm
-@ stub NtProtectVirtualMemory
+@ stdcall NtProtectVirtualMemory(long ptr ptr long ptr) NtProtectVirtualMemory
 @ stdcall NtPulseEvent(long ptr) NtPulseEvent
 @ stub NtQueryAttributesFile
 @ stub NtQueryDefaultLocale
@@ -176,7 +176,7 @@
 @ stub NtQueryTimer
 @ stdcall NtQueryTimerResolution(long long long) NtQueryTimerResolution
 @ stdcall NtQueryValueKey(long long long long long long) NtQueryValueKey
-@ stub NtQueryVirtualMemory
+@ stdcall NtQueryVirtualMemory(long ptr long ptr long ptr) NtQueryVirtualMemory
 @ stdcall NtQueryVolumeInformationFile(long ptr ptr long long) NtQueryVolumeInformationFile
 @ stdcall NtRaiseException(ptr ptr long) NtRaiseException
 @ stub NtRaiseHardError
@@ -241,8 +241,8 @@
 @ stub NtUnloadDriver
 @ stdcall NtUnloadKey(long) NtUnloadKey
 @ stub NtUnlockFile
-@ stub NtUnlockVirtualMemory
-@ stub NtUnmapViewOfSection
+@ stdcall NtUnlockVirtualMemory(long ptr ptr long) NtUnlockVirtualMemory
+@ stdcall NtUnmapViewOfSection(long ptr) NtUnmapViewOfSection
 @ stub NtVdmControl
 @ stub NtW32Call
 @ stub NtWaitForMultipleObjects
@@ -581,7 +581,7 @@
 @ stub ZwAlertThread
 @ stub ZwAllocateLocallyUniqueId
 @ stub ZwAllocateUuids
-@ stub ZwAllocateVirtualMemory
+@ stdcall ZwAllocateVirtualMemory(long ptr ptr ptr long long) NtAllocateVirtualMemory
 @ stub ZwCallbackReturn
 @ stub ZwCancelIoFile
 @ stub ZwCancelTimer
@@ -604,7 +604,7 @@
 @ stdcall ZwCreatePort(long long long long long) NtCreatePort
 @ stub ZwCreateProcess
 @ stub ZwCreateProfile
-@ stdcall ZwCreateSection(long long long long long long long) NtCreateSection
+@ stdcall ZwCreateSection(ptr long ptr ptr long long long) NtCreateSection
 @ stub ZwCreateSemaphore
 @ stub ZwCreateSymbolicLinkObject
 @ stub ZwCreateThread
@@ -625,9 +625,9 @@
 @ stub ZwFlushBuffersFile
 @ stub ZwFlushInstructionCache
 @ stdcall ZwFlushKey(long) NtFlushKey
-@ stub ZwFlushVirtualMemory
+@ stdcall ZwFlushVirtualMemory(long ptr ptr long) NtFlushVirtualMemory
 @ stub ZwFlushWriteBuffer
-@ stub ZwFreeVirtualMemory
+@ stdcall ZwFreeVirtualMemory(long ptr ptr long) NtFreeVirtualMemory
 @ stdcall ZwFsControlFile(long long long long long long long long long long) NtFsControlFile
 @ stub ZwGetContextThread
 @ stub ZwGetPlugPlayEvent
@@ -639,9 +639,9 @@
 @ stub ZwLoadDriver
 @ stdcall ZwLoadKey(ptr ptr) NtLoadKey
 @ stub ZwLockFile
-@ stub ZwLockVirtualMemory
+@ stdcall ZwLockVirtualMemory(long ptr ptr long) NtLockVirtualMemory
 @ stub ZwMakeTemporaryObject
-@ stdcall ZwMapViewOfSection(long long long long long long long long long long) NtMapViewOfSection
+@ stdcall ZwMapViewOfSection(long long ptr long long ptr ptr long long long) NtMapViewOfSection
 @ stub ZwNotifyChangeDirectoryFile
 @ stdcall ZwNotifyChangeKey(long long ptr ptr ptr long long ptr long long) NtNotifyChangeKey
 @ stdcall ZwOpenDirectoryObject(long long long) NtOpenDirectoryObject
@@ -654,7 +654,7 @@
 @ stub ZwOpenObjectAuditAlarm
 @ stub ZwOpenProcess
 @ stdcall ZwOpenProcessToken(long long long) NtOpenProcessToken
-@ stdcall ZwOpenSection(long long long) NtOpenSection
+@ stdcall ZwOpenSection(ptr long ptr) NtOpenSection
 @ stub ZwOpenSemaphore
 @ stub ZwOpenSymbolicLinkObject
 @ stub ZwOpenThread
@@ -664,7 +664,7 @@
 @ stub ZwPrivilegeCheck
 @ stub ZwPrivilegeObjectAuditAlarm
 @ stub ZwPrivilegedServiceAuditAlarm
-@ stub ZwProtectVirtualMemory
+@ stdcall ZwProtectVirtualMemory(long ptr ptr long ptr) NtProtectVirtualMemory
 @ stub ZwPulseEvent
 @ stub ZwQueryAttributesFile
 @ stub ZwQueryDefaultLocale
@@ -693,7 +693,7 @@
 @ stub ZwQueryTimer
 @ stub ZwQueryTimerResolution
 @ stdcall ZwQueryValueKey(long ptr long ptr long ptr) NtQueryValueKey
-@ stub ZwQueryVirtualMemory
+@ stdcall ZwQueryVirtualMemory(long ptr long ptr long ptr) NtQueryVirtualMemory
 @ stdcall ZwQueryVolumeInformationFile(long ptr ptr long long) NtQueryVolumeInformationFile
 @ stub ZwRaiseException
 @ stub ZwRaiseHardError
@@ -756,8 +756,8 @@
 @ stub ZwUnloadDriver
 @ stdcall ZwUnloadKey(long) NtUnloadKey
 @ stub ZwUnlockFile
-@ stub ZwUnlockVirtualMemory
-@ stub ZwUnmapViewOfSection
+@ stdcall ZwUnlockVirtualMemory(long ptr ptr long) NtUnlockVirtualMemory
+@ stdcall ZwUnmapViewOfSection(long ptr) NtUnmapViewOfSection
 @ stub ZwVdmControl
 @ stub ZwW32Call
 @ stub ZwWaitForMultipleObjects
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
new file mode 100644
index 0000000..15fd396
--- /dev/null
+++ b/dlls/ntdll/virtual.c
@@ -0,0 +1,1535 @@
+/*
+ * Win32 virtual memory functions
+ *
+ * Copyright 1997, 2002 Alexandre Julliard
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <errno.h>
+#ifdef HAVE_SYS_ERRNO_H
+#include <sys/errno.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include "winternl.h"
+#include "global.h"
+#include "wine/library.h"
+#include "wine/server.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(virtual);
+WINE_DECLARE_DEBUG_CHANNEL(module);
+
+#ifndef MS_SYNC
+#define MS_SYNC 0
+#endif
+
+/* File view */
+typedef struct _FV
+{
+    struct _FV   *next;        /* Next view */
+    struct _FV   *prev;        /* Prev view */
+    void         *base;        /* Base address */
+    UINT          size;        /* Size in bytes */
+    UINT          flags;       /* Allocation flags */
+    HANDLE        mapping;     /* Handle to the file mapping */
+    HANDLERPROC   handlerProc; /* Fault handler */
+    LPVOID        handlerArg;  /* Fault handler argument */
+    BYTE          protect;     /* Protection for all pages at allocation time */
+    BYTE          prot[1];     /* Protection byte for each page */
+} FILE_VIEW;
+
+/* Per-view flags */
+#define VFLAG_SYSTEM     0x01
+#define VFLAG_VALLOC     0x02  /* allocated by VirtualAlloc */
+
+/* Conversion from VPROT_* to Win32 flags */
+static const BYTE VIRTUAL_Win32Flags[16] =
+{
+    PAGE_NOACCESS,              /* 0 */
+    PAGE_READONLY,              /* READ */
+    PAGE_READWRITE,             /* WRITE */
+    PAGE_READWRITE,             /* READ | WRITE */
+    PAGE_EXECUTE,               /* EXEC */
+    PAGE_EXECUTE_READ,          /* READ | EXEC */
+    PAGE_EXECUTE_READWRITE,     /* WRITE | EXEC */
+    PAGE_EXECUTE_READWRITE,     /* READ | WRITE | EXEC */
+    PAGE_WRITECOPY,             /* WRITECOPY */
+    PAGE_WRITECOPY,             /* READ | WRITECOPY */
+    PAGE_WRITECOPY,             /* WRITE | WRITECOPY */
+    PAGE_WRITECOPY,             /* READ | WRITE | WRITECOPY */
+    PAGE_EXECUTE_WRITECOPY,     /* EXEC | WRITECOPY */
+    PAGE_EXECUTE_WRITECOPY,     /* READ | EXEC | WRITECOPY */
+    PAGE_EXECUTE_WRITECOPY,     /* WRITE | EXEC | WRITECOPY */
+    PAGE_EXECUTE_WRITECOPY      /* READ | WRITE | EXEC | WRITECOPY */
+};
+
+
+static FILE_VIEW *VIRTUAL_FirstView;
+static CRITICAL_SECTION csVirtual = CRITICAL_SECTION_INIT("csVirtual");
+
+#ifdef __i386__
+/* These are always the same on an i386, and it will be faster this way */
+# define page_mask  0xfff
+# define page_shift 12
+# define page_size  0x1000
+#else
+static UINT page_shift;
+static UINT page_mask;
+static UINT page_size;
+#endif  /* __i386__ */
+#define granularity_mask 0xffff  /* Allocation granularity (usually 64k) */
+
+#define ADDRESS_SPACE_LIMIT  ((void *)0xc0000000)  /* top of the user address space */
+
+#define ROUND_ADDR(addr,mask) \
+   ((void *)((UINT_PTR)(addr) & ~(mask)))
+
+#define ROUND_SIZE(addr,size) \
+   (((UINT)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
+
+#define VIRTUAL_DEBUG_DUMP_VIEW(view) \
+   if (!TRACE_ON(virtual)); else VIRTUAL_DumpView(view)
+
+static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size, DWORD offset_low,
+                            DWORD offset_high, int prot, int flags, BOOL *removable );
+
+
+/***********************************************************************
+ *           VIRTUAL_GetProtStr
+ */
+static const char *VIRTUAL_GetProtStr( BYTE prot )
+{
+    static char buffer[6];
+    buffer[0] = (prot & VPROT_COMMITTED) ? 'c' : '-';
+    buffer[1] = (prot & VPROT_GUARD) ? 'g' : '-';
+    buffer[2] = (prot & VPROT_READ) ? 'r' : '-';
+    buffer[3] = (prot & VPROT_WRITE) ?
+                    ((prot & VPROT_WRITECOPY) ? 'w' : 'W') : '-';
+    buffer[4] = (prot & VPROT_EXEC) ? 'x' : '-';
+    buffer[5] = 0;
+    return buffer;
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_DumpView
+ */
+static void VIRTUAL_DumpView( FILE_VIEW *view )
+{
+    UINT i, count;
+    char *addr = view->base;
+    BYTE prot = view->prot[0];
+
+    DPRINTF( "View: %p - %p", addr, addr + view->size - 1 );
+    if (view->flags & VFLAG_SYSTEM)
+        DPRINTF( " (system)\n" );
+    else if (view->flags & VFLAG_VALLOC)
+        DPRINTF( " (valloc)\n" );
+    else if (view->mapping)
+        DPRINTF( " %d\n", view->mapping );
+    else
+        DPRINTF( " (anonymous)\n");
+
+    for (count = i = 1; i < view->size >> page_shift; i++, count++)
+    {
+        if (view->prot[i] == prot) continue;
+        DPRINTF( "      %p - %p %s\n",
+                 addr, addr + (count << page_shift) - 1, VIRTUAL_GetProtStr(prot) );
+        addr += (count << page_shift);
+        prot = view->prot[i];
+        count = 0;
+    }
+    if (count)
+        DPRINTF( "      %p - %p %s\n",
+                 addr, addr + (count << page_shift) - 1, VIRTUAL_GetProtStr(prot) );
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_Dump
+ */
+void VIRTUAL_Dump(void)
+{
+    FILE_VIEW *view;
+    DPRINTF( "\nDump of all virtual memory views:\n\n" );
+    RtlEnterCriticalSection(&csVirtual);
+    view = VIRTUAL_FirstView;
+    while (view)
+    {
+        VIRTUAL_DumpView( view );
+        view = view->next;
+    }
+    RtlLeaveCriticalSection(&csVirtual);
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_FindView
+ *
+ * Find the view containing a given address.
+ *
+ * RETURNS
+ *	View: Success
+ *	NULL: Failure
+ */
+static FILE_VIEW *VIRTUAL_FindView( const void *addr ) /* [in] Address */
+{
+    FILE_VIEW *view;
+
+    RtlEnterCriticalSection(&csVirtual);
+    view = VIRTUAL_FirstView;
+    while (view)
+    {
+        if (view->base > addr)
+        {
+            view = NULL;
+            break;
+        }
+        if ((char*)view->base + view->size > (char*)addr) break;
+        view = view->next;
+    }
+    RtlLeaveCriticalSection(&csVirtual);
+    return view;
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_CreateView
+ *
+ * Create a new view and add it in the linked list.
+ */
+static FILE_VIEW *VIRTUAL_CreateView( void *base, UINT size, UINT flags,
+                                      BYTE vprot, HANDLE mapping )
+{
+    FILE_VIEW *view, *prev;
+
+    /* Create the view structure */
+
+    assert( !((unsigned int)base & page_mask) );
+    assert( !(size & page_mask) );
+    size >>= page_shift;
+    if (!(view = (FILE_VIEW *)malloc( sizeof(*view) + size - 1 ))) return NULL;
+    view->base    = base;
+    view->size    = size << page_shift;
+    view->flags   = flags;
+    view->mapping = mapping;
+    view->protect = vprot;
+    view->handlerProc = NULL;
+    memset( view->prot, vprot, size );
+
+    /* Duplicate the mapping handle */
+
+    if (view->mapping &&
+        NtDuplicateObject( GetCurrentProcess(), view->mapping,
+                           GetCurrentProcess(), &view->mapping,
+                           0, 0, DUPLICATE_SAME_ACCESS ))
+    {
+        free( view );
+        return NULL;
+    }
+
+    /* Insert it in the linked list */
+
+    RtlEnterCriticalSection(&csVirtual);
+    if (!VIRTUAL_FirstView || (VIRTUAL_FirstView->base > base))
+    {
+        view->next = VIRTUAL_FirstView;
+        view->prev = NULL;
+        if (view->next) view->next->prev = view;
+        VIRTUAL_FirstView = view;
+    }
+    else
+    {
+        prev = VIRTUAL_FirstView;
+        while (prev->next && (prev->next->base < base)) prev = prev->next;
+        view->next = prev->next;
+        view->prev = prev;
+        if (view->next) view->next->prev = view;
+        prev->next  = view;
+    }
+    RtlLeaveCriticalSection(&csVirtual);
+    VIRTUAL_DEBUG_DUMP_VIEW( view );
+    return view;
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_DeleteView
+ * Deletes a view.
+ *
+ * RETURNS
+ *	None
+ */
+static void VIRTUAL_DeleteView( FILE_VIEW *view ) /* [in] View */
+{
+    if (!(view->flags & VFLAG_SYSTEM))
+        munmap( (void *)view->base, view->size );
+    RtlEnterCriticalSection(&csVirtual);
+    if (view->next) view->next->prev = view->prev;
+    if (view->prev) view->prev->next = view->next;
+    else VIRTUAL_FirstView = view->next;
+    RtlLeaveCriticalSection(&csVirtual);
+    if (view->mapping) NtClose( view->mapping );
+    free( view );
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_GetUnixProt
+ *
+ * Convert page protections to protection for mmap/mprotect.
+ */
+static int VIRTUAL_GetUnixProt( BYTE vprot )
+{
+    int prot = 0;
+    if ((vprot & VPROT_COMMITTED) && !(vprot & VPROT_GUARD))
+    {
+        if (vprot & VPROT_READ) prot |= PROT_READ;
+        if (vprot & VPROT_WRITE) prot |= PROT_WRITE;
+        if (vprot & VPROT_WRITECOPY) prot |= PROT_WRITE;
+        if (vprot & VPROT_EXEC) prot |= PROT_EXEC;
+    }
+    return prot;
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_GetWin32Prot
+ *
+ * Convert page protections to Win32 flags.
+ *
+ * RETURNS
+ *	None
+ */
+static void VIRTUAL_GetWin32Prot(
+            BYTE vprot,     /* [in] Page protection flags */
+            DWORD *protect, /* [out] Location to store Win32 protection flags */
+            DWORD *state )  /* [out] Location to store mem state flag */
+{
+    if (protect) {
+        *protect = VIRTUAL_Win32Flags[vprot & 0x0f];
+/*    	if (vprot & VPROT_GUARD) *protect |= PAGE_GUARD;*/
+        if (vprot & VPROT_NOCACHE) *protect |= PAGE_NOCACHE;
+
+        if (vprot & VPROT_GUARD) *protect = PAGE_NOACCESS;
+    }
+
+    if (state) *state = (vprot & VPROT_COMMITTED) ? MEM_COMMIT : MEM_RESERVE;
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_GetProt
+ *
+ * Build page protections from Win32 flags.
+ *
+ * RETURNS
+ *	Value of page protection flags
+ */
+static BYTE VIRTUAL_GetProt( DWORD protect )  /* [in] Win32 protection flags */
+{
+    BYTE vprot;
+
+    switch(protect & 0xff)
+    {
+    case PAGE_READONLY:
+        vprot = VPROT_READ;
+        break;
+    case PAGE_READWRITE:
+        vprot = VPROT_READ | VPROT_WRITE;
+        break;
+    case PAGE_WRITECOPY:
+        /* MSDN CreateFileMapping() states that if PAGE_WRITECOPY is given,
+	 * that the hFile must have been opened with GENERIC_READ and
+	 * GENERIC_WRITE access.  This is WRONG as tests show that you
+	 * only need GENERIC_READ access (at least for Win9x,
+	 * FIXME: what about NT?).  Thus, we don't put VPROT_WRITE in
+	 * PAGE_WRITECOPY and PAGE_EXECUTE_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:
+        /* See comment for PAGE_WRITECOPY above */
+        vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITECOPY;
+        break;
+    case PAGE_NOACCESS:
+    default:
+        vprot = 0;
+        break;
+    }
+    if (protect & PAGE_GUARD) vprot |= VPROT_GUARD;
+    if (protect & PAGE_NOCACHE) vprot |= VPROT_NOCACHE;
+    return vprot;
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_SetProt
+ *
+ * Change the protection of a range of pages.
+ *
+ * RETURNS
+ *	TRUE: Success
+ *	FALSE: Failure
+ */
+static BOOL VIRTUAL_SetProt( FILE_VIEW *view, /* [in] Pointer to view */
+                             void *base,      /* [in] Starting address */
+                             UINT size,       /* [in] Size in bytes */
+                             BYTE vprot )     /* [in] Protections to use */
+{
+    TRACE("%p-%p %s\n",
+          base, (char *)base + size - 1, VIRTUAL_GetProtStr( vprot ) );
+
+    if (mprotect( base, size, VIRTUAL_GetUnixProt(vprot) ))
+        return FALSE;  /* FIXME: last error */
+
+    memset( view->prot + (((char *)base - (char *)view->base) >> page_shift),
+            vprot, size >> page_shift );
+    VIRTUAL_DEBUG_DUMP_VIEW( view );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           anon_mmap_aligned
+ *
+ * Create an anonymous mapping aligned to the allocation granularity.
+ */
+static NTSTATUS anon_mmap_aligned( void **addr, unsigned int size, int prot, int flags )
+{
+    void *ptr, *base = *addr;
+    unsigned int view_size = size + (base ? 0 : granularity_mask + 1);
+
+    if ((ptr = wine_anon_mmap( base, view_size, prot, flags )) == (void *)-1)
+    {
+        if (errno == ENOMEM) return STATUS_NO_MEMORY;
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (!base)
+    {
+        /* Release the extra memory while keeping the range
+         * starting on the granularity boundary. */
+        if ((unsigned int)ptr & granularity_mask)
+        {
+            unsigned int extra = granularity_mask + 1 - ((unsigned int)ptr & granularity_mask);
+            munmap( ptr, extra );
+            ptr = (char *)ptr + extra;
+            view_size -= extra;
+        }
+        if (view_size > size)
+            munmap( (char *)ptr + size, view_size - size );
+    }
+    else if (ptr != base)
+    {
+        /* We couldn't get the address we wanted */
+        munmap( ptr, view_size );
+        return STATUS_CONFLICTING_ADDRESSES;
+    }
+    *addr = ptr;
+    return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ *           do_relocations
+ *
+ * Apply the relocations to a mapped PE image
+ */
+static int do_relocations( char *base, const IMAGE_DATA_DIRECTORY *dir,
+                           int delta, DWORD total_size )
+{
+    IMAGE_BASE_RELOCATION *rel;
+
+    TRACE_(module)( "relocating from %p-%p to %p-%p\n",
+                    base - delta, base - delta + total_size, base, base + total_size );
+
+    for (rel = (IMAGE_BASE_RELOCATION *)(base + dir->VirtualAddress);
+         ((char *)rel < base + dir->VirtualAddress + dir->Size) && rel->SizeOfBlock;
+         rel = (IMAGE_BASE_RELOCATION*)((char*)rel + rel->SizeOfBlock) )
+    {
+        char *page = base + rel->VirtualAddress;
+        WORD *TypeOffset = (WORD *)(rel + 1);
+        int i, count = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(*TypeOffset);
+
+        if (!count) continue;
+
+        /* sanity checks */
+        if ((char *)rel + rel->SizeOfBlock > base + dir->VirtualAddress + dir->Size ||
+            page > base + total_size)
+        {
+            ERR_(module)("invalid relocation %p,%lx,%ld at %p,%lx,%lx\n",
+                         rel, rel->VirtualAddress, rel->SizeOfBlock,
+                         base, dir->VirtualAddress, dir->Size );
+            return 0;
+        }
+
+        TRACE_(module)("%ld relocations for page %lx\n", rel->SizeOfBlock, rel->VirtualAddress);
+
+        /* patching in reverse order */
+        for (i = 0 ; i < count; i++)
+        {
+            int offset = TypeOffset[i] & 0xFFF;
+            int type = TypeOffset[i] >> 12;
+            switch(type)
+            {
+            case IMAGE_REL_BASED_ABSOLUTE:
+                break;
+            case IMAGE_REL_BASED_HIGH:
+                *(short*)(page+offset) += HIWORD(delta);
+                break;
+            case IMAGE_REL_BASED_LOW:
+                *(short*)(page+offset) += LOWORD(delta);
+                break;
+            case IMAGE_REL_BASED_HIGHLOW:
+                *(int*)(page+offset) += delta;
+                /* FIXME: if this is an exported address, fire up enhanced logic */
+                break;
+            default:
+                FIXME_(module)("Unknown/unsupported fixup type %d.\n", type);
+                break;
+            }
+        }
+    }
+    return 1;
+}
+
+
+/***********************************************************************
+ *           map_image
+ *
+ * Map an executable (PE format) image into memory.
+ */
+static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, DWORD total_size,
+                           DWORD header_size, int shared_fd, DWORD shared_size,
+                           BOOL removable, PVOID *addr_ptr )
+{
+    IMAGE_DOS_HEADER *dos;
+    IMAGE_NT_HEADERS *nt;
+    IMAGE_SECTION_HEADER *sec;
+    IMAGE_DATA_DIRECTORY *imports;
+    NTSTATUS status = STATUS_INVALID_IMAGE_FORMAT;  /* generic error (FIXME) */
+    int i, pos;
+    FILE_VIEW *view;
+    char *ptr;
+
+    /* zero-map the whole range */
+
+    if (base < (char *)0x110000 ||  /* make sure the DOS area remains free */
+        (ptr = wine_anon_mmap( base, total_size,
+                               PROT_READ | PROT_WRITE | PROT_EXEC, 0 )) == (char *)-1)
+    {
+        ptr = wine_anon_mmap( NULL, total_size,
+                            PROT_READ | PROT_WRITE | PROT_EXEC, 0 );
+        if (ptr == (char *)-1)
+        {
+            ERR_(module)("Not enough memory for module (%ld bytes)\n", total_size);
+            goto error;
+        }
+    }
+    TRACE_(module)( "mapped PE file at %p-%p\n", ptr, ptr + total_size );
+
+    /* map the header */
+
+    if (VIRTUAL_mmap( fd, ptr, header_size, 0, 0, PROT_READ,
+                      MAP_PRIVATE | MAP_FIXED, &removable ) == (char *)-1) goto error;
+    dos = (IMAGE_DOS_HEADER *)ptr;
+    nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew);
+    if ((char *)(nt + 1) > ptr + header_size) goto error;
+
+    sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
+    if ((char *)(sec + nt->FileHeader.NumberOfSections) > ptr + header_size) 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_I386)
+    {
+        MESSAGE("Trying to load PE image for unsupported architecture (");
+        switch (nt->FileHeader.Machine)
+        {
+        case IMAGE_FILE_MACHINE_UNKNOWN: MESSAGE("Unknown"); break;
+        case IMAGE_FILE_MACHINE_I860:    MESSAGE("I860"); break;
+        case IMAGE_FILE_MACHINE_R3000:   MESSAGE("R3000"); break;
+        case IMAGE_FILE_MACHINE_R4000:   MESSAGE("R4000"); break;
+        case IMAGE_FILE_MACHINE_R10000:  MESSAGE("R10000"); break;
+        case IMAGE_FILE_MACHINE_ALPHA:   MESSAGE("Alpha"); break;
+        case IMAGE_FILE_MACHINE_POWERPC: MESSAGE("PowerPC"); break;
+        default: MESSAGE("Unknown-%04x", nt->FileHeader.Machine); break;
+        }
+        MESSAGE(")\n");
+        goto error;
+    }
+
+    /* map all the sections */
+
+    for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
+    {
+        DWORD size;
+
+        /* a few sanity checks */
+        size = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
+        if (sec->VirtualAddress > total_size || size > total_size || size < sec->VirtualAddress)
+        {
+            ERR_(module)( "Section %.8s too large (%lx+%lx/%lx)\n",
+                          sec->Name, sec->VirtualAddress, sec->Misc.VirtualSize, total_size );
+            goto error;
+        }
+
+        if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) &&
+            (sec->Characteristics & IMAGE_SCN_MEM_WRITE))
+        {
+            size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
+            TRACE_(module)( "mapping shared section %.8s at %p off %lx (%x) size %lx (%lx) flags %lx\n",
+                          sec->Name, ptr + sec->VirtualAddress,
+                          sec->PointerToRawData, pos, sec->SizeOfRawData,
+                          size, sec->Characteristics );
+            if (VIRTUAL_mmap( shared_fd, ptr + sec->VirtualAddress, size,
+                              pos, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
+                              MAP_SHARED|MAP_FIXED, NULL ) == (void *)-1)
+            {
+                ERR_(module)( "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 + size)
+            {
+                UINT_PTR base = imports->VirtualAddress & ~page_mask;
+                UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size );
+                if (end > sec->VirtualAddress + size) end = sec->VirtualAddress + size;
+                if (end > base) VIRTUAL_mmap( shared_fd, ptr + base, end - base,
+                                              pos, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
+                                              MAP_PRIVATE|MAP_FIXED, NULL );
+            }
+            pos += size;
+            continue;
+        }
+
+        TRACE_(module)( "mapping section %.8s at %p off %lx size %lx flags %lx\n",
+                        sec->Name, ptr + sec->VirtualAddress,
+                        sec->PointerToRawData, sec->SizeOfRawData,
+                        sec->Characteristics );
+
+        if (sec->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) continue;
+        if (!sec->PointerToRawData || !sec->SizeOfRawData) continue;
+
+        /* Note: if the section is not aligned properly VIRTUAL_mmap will magically
+         *       fall back to read(), so we don't need to check anything here.
+         */
+        if (VIRTUAL_mmap( fd, ptr + sec->VirtualAddress, sec->SizeOfRawData,
+                          sec->PointerToRawData, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
+                          MAP_PRIVATE | MAP_FIXED, &removable ) == (void *)-1)
+        {
+            ERR_(module)( "Could not map section %.8s, file probably truncated\n", sec->Name );
+            goto error;
+        }
+
+        if ((sec->SizeOfRawData < sec->Misc.VirtualSize) && (sec->SizeOfRawData & page_mask))
+        {
+            DWORD end = ROUND_SIZE( 0, sec->SizeOfRawData );
+            if (end > sec->Misc.VirtualSize) end = sec->Misc.VirtualSize;
+            TRACE_(module)("clearing %p - %p\n",
+                           ptr + sec->VirtualAddress + sec->SizeOfRawData,
+                           ptr + sec->VirtualAddress + end );
+            memset( ptr + sec->VirtualAddress + sec->SizeOfRawData, 0,
+                    end - sec->SizeOfRawData );
+        }
+    }
+
+
+    /* perform base relocation, if necessary */
+
+    if (ptr != base)
+    {
+        const IMAGE_DATA_DIRECTORY *relocs;
+
+        relocs = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+        if (!relocs->VirtualAddress || !relocs->Size)
+        {
+            if (nt->OptionalHeader.ImageBase == 0x400000)
+                ERR("Standard load address for a Win32 program (0x00400000) not available - security-patched kernel ?\n");
+            else
+                ERR( "FATAL: Need to relocate module from addr %lx, but there are no relocation records\n",
+                     nt->OptionalHeader.ImageBase );
+            goto error;
+        }
+
+        /* FIXME: If we need to relocate a system DLL (base > 2GB) we should
+         *        really make sure that the *new* base address is also > 2GB.
+         *        Some DLLs really check the MSB of the module handle :-/
+         */
+        if ((nt->OptionalHeader.ImageBase & 0x80000000) && !((DWORD)base & 0x80000000))
+            ERR( "Forced to relocate system DLL (base > 2GB). This is not good.\n" );
+
+        if (!do_relocations( ptr, relocs, ptr - base, total_size ))
+        {
+            goto error;
+        }
+    }
+
+    if (removable) hmapping = 0;  /* don't keep handle open on removable media */
+    if (!(view = VIRTUAL_CreateView( ptr, total_size, 0, VPROT_COMMITTED|VPROT_READ, hmapping )))
+    {
+        status = STATUS_NO_MEMORY;
+        goto error;
+    }
+
+    /* set the image protections */
+
+    sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
+    for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
+    {
+        DWORD size = ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
+        BYTE vprot = VPROT_COMMITTED;
+        if (sec->Characteristics & IMAGE_SCN_MEM_READ)    vprot |= VPROT_READ;
+        if (sec->Characteristics & IMAGE_SCN_MEM_WRITE)   vprot |= VPROT_WRITE|VPROT_WRITECOPY;
+        if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC;
+
+        /* make sure the import directory is writable */
+        if (imports && imports->VirtualAddress >= sec->VirtualAddress &&
+            imports->VirtualAddress < sec->VirtualAddress + size)
+            vprot |= VPROT_READ|VPROT_WRITE|VPROT_WRITECOPY;
+
+        VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );
+    }
+
+    close( fd );
+    *addr_ptr = ptr;
+    return STATUS_SUCCESS;
+
+ error:
+    if (ptr != (char *)-1) munmap( ptr, total_size );
+    close( fd );
+    return status;
+}
+
+
+/***********************************************************************
+ *           is_current_process
+ *
+ * Check whether a process handle is for the current process.
+ */
+static BOOL is_current_process( HANDLE handle )
+{
+    BOOL ret = FALSE;
+
+    if (handle == GetCurrentProcess()) return TRUE;
+    SERVER_START_REQ( get_process_info )
+    {
+        req->handle = handle;
+        if (!wine_server_call( req ))
+            ret = ((DWORD)reply->pid == GetCurrentProcessId());
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_Init
+ */
+#ifndef page_mask
+DECL_GLOBAL_CONSTRUCTOR(VIRTUAL_Init)
+{
+    page_size = getpagesize();
+    page_mask = page_size - 1;
+    /* Make sure we have a power of 2 */
+    assert( !(page_size & page_mask) );
+    page_shift = 0;
+    while ((1 << page_shift) != page_size) page_shift++;
+}
+#endif  /* page_mask */
+
+
+/***********************************************************************
+ *           VIRTUAL_SetFaultHandler
+ */
+BOOL VIRTUAL_SetFaultHandler( LPCVOID addr, HANDLERPROC proc, LPVOID arg )
+{
+    FILE_VIEW *view;
+
+    if (!(view = VIRTUAL_FindView( addr ))) return FALSE;
+    view->handlerProc = proc;
+    view->handlerArg  = arg;
+    return TRUE;
+}
+
+/***********************************************************************
+ *           VIRTUAL_HandleFault
+ */
+DWORD VIRTUAL_HandleFault( LPCVOID addr )
+{
+    FILE_VIEW *view = VIRTUAL_FindView( addr );
+    DWORD ret = EXCEPTION_ACCESS_VIOLATION;
+
+    if (view)
+    {
+        if (view->handlerProc)
+        {
+            if (view->handlerProc(view->handlerArg, addr)) ret = 0;  /* handled */
+        }
+        else
+        {
+            BYTE vprot = view->prot[((char *)addr - (char *)view->base) >> page_shift];
+            void *page = (void *)((UINT_PTR)addr & ~page_mask);
+            char *stack = (char *)NtCurrentTeb()->stack_base + SIGNAL_STACK_SIZE + page_mask + 1;
+            if (vprot & VPROT_GUARD)
+            {
+                VIRTUAL_SetProt( view, page, page_mask + 1, vprot & ~VPROT_GUARD );
+                ret = STATUS_GUARD_PAGE_VIOLATION;
+            }
+            /* is it inside the stack guard pages? */
+            if (((char *)addr >= stack) && ((char *)addr < stack + 2*(page_mask+1)))
+                ret = STATUS_STACK_OVERFLOW;
+        }
+    }
+    return ret;
+}
+
+
+
+/***********************************************************************
+ *           unaligned_mmap
+ *
+ * Linux kernels before 2.4.x can support non page-aligned offsets, as
+ * long as the offset is aligned to the filesystem block size. This is
+ * a big performance gain so we want to take advantage of it.
+ *
+ * However, when we use 64-bit file support this doesn't work because
+ * glibc rejects unaligned offsets. Also glibc 2.1.3 mmap64 is broken
+ * in that it rounds unaligned offsets down to a page boundary. For
+ * these reasons we do a direct system call here.
+ */
+static void *unaligned_mmap( void *addr, size_t length, unsigned int prot,
+                             unsigned int flags, int fd, unsigned int offset_low,
+                             unsigned int offset_high )
+{
+#if defined(linux) && defined(__i386__) && defined(__GNUC__)
+    if (!offset_high && (offset_low & page_mask))
+    {
+        int ret;
+
+        struct
+        {
+            void        *addr;
+            unsigned int length;
+            unsigned int prot;
+            unsigned int flags;
+            unsigned int fd;
+            unsigned int offset;
+        } args;
+
+        args.addr   = addr;
+        args.length = length;
+        args.prot   = prot;
+        args.flags  = flags;
+        args.fd     = fd;
+        args.offset = offset_low;
+
+        __asm__ __volatile__("push %%ebx\n\t"
+                             "movl %2,%%ebx\n\t"
+                             "int $0x80\n\t"
+                             "popl %%ebx"
+                             : "=a" (ret)
+                             : "0" (90), /* SYS_mmap */
+                               "g" (&args) );
+        if (ret < 0 && ret > -4096)
+        {
+            errno = -ret;
+            ret = -1;
+        }
+        return (void *)ret;
+    }
+#endif
+    return mmap( addr, length, prot, flags, fd, ((off_t)offset_high << 32) | offset_low );
+}
+
+
+/***********************************************************************
+ *           VIRTUAL_mmap
+ *
+ * Wrapper for mmap() that handles anonymous mappings portably,
+ * and falls back to read if mmap of a file fails.
+ */
+static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size,
+                            DWORD offset_low, DWORD offset_high,
+                            int prot, int flags, BOOL *removable )
+{
+    int pos;
+    LPVOID ret;
+    off_t offset;
+    BOOL is_shared_write = FALSE;
+
+    if (fd == -1) return wine_anon_mmap( start, size, prot, flags );
+
+    if (prot & PROT_WRITE)
+    {
+#ifdef MAP_SHARED
+        if (flags & MAP_SHARED) is_shared_write = TRUE;
+#endif
+#ifdef MAP_PRIVATE
+        if (!(flags & MAP_PRIVATE)) is_shared_write = TRUE;
+#endif
+    }
+
+    if (removable && *removable)
+    {
+        /* if on removable media, try using read instead of mmap */
+        if (!is_shared_write) goto fake_mmap;
+        *removable = FALSE;
+    }
+
+    if ((ret = unaligned_mmap( start, size, prot, flags, fd,
+                               offset_low, offset_high )) != (LPVOID)-1) return ret;
+
+    /* 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 ret;
+    if (is_shared_write) return ret;  /* we cannot fake shared write mappings */
+
+ fake_mmap:
+    /* Reserve the memory with an anonymous mmap */
+    ret = wine_anon_mmap( start, size, PROT_READ | PROT_WRITE, flags );
+    if (ret == (LPVOID)-1) return ret;
+    /* Now read in the file */
+    offset = ((off_t)offset_high << 32) | offset_low;
+    if ((pos = lseek( fd, offset, SEEK_SET )) == -1)
+    {
+        munmap( ret, size );
+        return (LPVOID)-1;
+    }
+    read( fd, ret, size );
+    lseek( fd, pos, SEEK_SET );  /* Restore the file pointer */
+    mprotect( ret, size, prot );  /* Set the right protection */
+    return ret;
+}
+
+
+/***********************************************************************
+ *             NtAllocateVirtualMemory   (NTDLL.@)
+ *             ZwAllocateVirtualMemory   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, PVOID addr,
+                                         ULONG *size_ptr, ULONG type, ULONG protect )
+{
+    FILE_VIEW *view;
+    void *base;
+    BYTE vprot;
+    DWORD size = *size_ptr;
+
+    if (!is_current_process( process ))
+    {
+        ERR("Unsupported on other process\n");
+        return STATUS_ACCESS_DENIED;
+    }
+
+    TRACE("%p %08lx %lx %08lx\n", addr, size, type, protect );
+
+    /* Round parameters to a page boundary */
+
+    if (size > 0x7fc00000) return STATUS_WORKING_SET_LIMIT_RANGE; /* 2Gb - 4Mb */
+
+    if (addr)
+    {
+        if (type & MEM_RESERVE) /* Round down to 64k boundary */
+            base = ROUND_ADDR( addr, granularity_mask );
+        else
+            base = ROUND_ADDR( addr, page_mask );
+        size = (((UINT_PTR)addr + size + page_mask) & ~page_mask) - (UINT_PTR)base;
+
+        /* disallow low 64k, wrap-around and kernel space */
+        if (((char *)base <= (char *)granularity_mask) ||
+            ((char *)base + size < (char *)base) ||
+            ((char *)base + size > (char *)ADDRESS_SPACE_LIMIT))
+            return STATUS_INVALID_PARAMETER;
+    }
+    else
+    {
+        base = NULL;
+        size = (size + page_mask) & ~page_mask;
+    }
+
+    if (type & MEM_TOP_DOWN) {
+        /* FIXME: MEM_TOP_DOWN allocates the largest possible address.
+         *  	  Is there _ANY_ way to do it with UNIX mmap()?
+         */
+        WARN("MEM_TOP_DOWN ignored\n");
+        type &= ~MEM_TOP_DOWN;
+    }
+
+    /* Compute the alloc type flags */
+
+    if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_SYSTEM)) ||
+        (type & ~(MEM_COMMIT | MEM_RESERVE | MEM_SYSTEM)))
+    {
+        ERR("called with wrong alloc type flags (%08lx) !\n", type);
+        return STATUS_INVALID_PARAMETER;
+    }
+    if (type & (MEM_COMMIT | MEM_SYSTEM))
+        vprot = VIRTUAL_GetProt( protect ) | VPROT_COMMITTED;
+    else vprot = 0;
+
+    /* Reserve the memory */
+
+    if ((type & MEM_RESERVE) || !base)
+    {
+        if (type & MEM_SYSTEM)
+        {
+            if (!(view = VIRTUAL_CreateView( base, size, VFLAG_VALLOC | VFLAG_SYSTEM, vprot, 0 )))
+                return STATUS_NO_MEMORY;
+        }
+        else
+        {
+            NTSTATUS res = anon_mmap_aligned( &base, size, VIRTUAL_GetUnixProt( vprot ), 0 );
+            if (res) return res;
+
+            if (!(view = VIRTUAL_CreateView( base, size, VFLAG_VALLOC, vprot, 0 )))
+            {
+                munmap( base, size );
+                return STATUS_NO_MEMORY;
+            }
+        }
+    }
+    else
+    {
+        /* Commit the pages */
+
+        if (!(view = VIRTUAL_FindView( base )) ||
+            ((char *)base + size > (char *)view->base + view->size)) return STATUS_NOT_MAPPED_VIEW;
+
+        if (!VIRTUAL_SetProt( view, base, size, vprot )) return STATUS_ACCESS_DENIED;
+    }
+
+    *ret = base;
+    *size_ptr = size;
+    return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ *             NtFreeVirtualMemory   (NTDLL.@)
+ *             ZwFreeVirtualMemory   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, ULONG *size_ptr, ULONG type )
+{
+    FILE_VIEW *view;
+    char *base;
+    LPVOID addr = *addr_ptr;
+    DWORD size = *size_ptr;
+
+    if (!is_current_process( process ))
+    {
+        ERR("Unsupported on other process\n");
+        return STATUS_ACCESS_DENIED;
+    }
+
+    TRACE("%p %08lx %lx\n", addr, size, type );
+
+    /* Fix the parameters */
+
+    size = ROUND_SIZE( addr, size );
+    base = ROUND_ADDR( addr, page_mask );
+
+    if (!(view = VIRTUAL_FindView( base )) ||
+        (base + size > (char *)view->base + view->size) ||
+        !(view->flags & VFLAG_VALLOC))
+        return STATUS_INVALID_PARAMETER;
+
+    /* Check the type */
+
+    if (type & MEM_SYSTEM)
+    {
+        view->flags |= VFLAG_SYSTEM;
+        type &= ~MEM_SYSTEM;
+    }
+
+    if ((type != MEM_DECOMMIT) && (type != MEM_RELEASE))
+    {
+        ERR("called with wrong free type flags (%08lx) !\n", type);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Free the pages */
+
+    if (type == MEM_RELEASE)
+    {
+        if (size || (base != view->base)) return STATUS_INVALID_PARAMETER;
+        VIRTUAL_DeleteView( view );
+    }
+    else
+    {
+        /* Decommit the pages by remapping zero-pages instead */
+
+        if (wine_anon_mmap( (LPVOID)base, size, VIRTUAL_GetUnixProt(0), MAP_FIXED ) != (LPVOID)base)
+            ERR( "Could not remap pages, expect trouble\n" );
+        if (!VIRTUAL_SetProt( view, base, size, 0 )) return STATUS_ACCESS_DENIED;  /* FIXME */
+    }
+
+    *addr_ptr = base;
+    *size_ptr = size;
+    return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ *             NtProtectVirtualMemory   (NTDLL.@)
+ *             ZwProtectVirtualMemory   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, ULONG *size_ptr,
+                                        ULONG new_prot, ULONG *old_prot )
+{
+    FILE_VIEW *view;
+    char *base;
+    UINT i;
+    BYTE vprot, *p;
+    DWORD prot, size = *size_ptr;
+    LPVOID addr = *addr_ptr;
+
+    if (!is_current_process( process ))
+    {
+        ERR("Unsupported on other process\n");
+        return STATUS_ACCESS_DENIED;
+    }
+
+    TRACE("%p %08lx %08lx\n", addr, size, new_prot );
+
+    /* Fix the parameters */
+
+    size = ROUND_SIZE( addr, size );
+    base = ROUND_ADDR( addr, page_mask );
+
+    if (!(view = VIRTUAL_FindView( base )) ||
+        (base + size > (char *)view->base + view->size))
+        return STATUS_INVALID_PARAMETER;
+
+    /* Make sure all the pages are committed */
+
+    p = view->prot + ((base - (char *)view->base) >> page_shift);
+    VIRTUAL_GetWin32Prot( *p, &prot, NULL );
+    for (i = size >> page_shift; i; i--, p++)
+    {
+        if (!(*p & VPROT_COMMITTED)) return STATUS_INVALID_PARAMETER;
+    }
+
+    if (old_prot) *old_prot = prot;
+    vprot = VIRTUAL_GetProt( new_prot ) | VPROT_COMMITTED;
+    if (!VIRTUAL_SetProt( view, base, size, vprot )) return STATUS_ACCESS_DENIED;
+
+    *addr_ptr = base;
+    *size_ptr = size;
+    return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ *             NtQueryVirtualMemory   (NTDLL.@)
+ *             ZwQueryVirtualMemory   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
+                                      MEMORY_INFORMATION_CLASS info_class, PVOID buffer,
+                                      ULONG len, ULONG *res_len )
+{
+    FILE_VIEW *view;
+    char *base, *alloc_base = 0;
+    UINT size = 0;
+    MEMORY_BASIC_INFORMATION *info = buffer;
+
+    if (info_class != MemoryBasicInformation) return STATUS_INVALID_INFO_CLASS;
+    if (addr >= ADDRESS_SPACE_LIMIT) return STATUS_WORKING_SET_LIMIT_RANGE;  /* FIXME */
+
+    if (!is_current_process( process ))
+    {
+        ERR("Unsupported on other process\n");
+        return STATUS_ACCESS_DENIED;
+    }
+
+    base = ROUND_ADDR( addr, page_mask );
+
+    /* Find the view containing the address */
+
+    RtlEnterCriticalSection(&csVirtual);
+    view = VIRTUAL_FirstView;
+    for (;;)
+    {
+        if (!view)
+        {
+            size = (char *)ADDRESS_SPACE_LIMIT - alloc_base;
+            break;
+        }
+        if ((char *)view->base > base)
+        {
+            size = (char *)view->base - alloc_base;
+            view = NULL;
+            break;
+        }
+        if ((char *)view->base + view->size > base)
+        {
+            alloc_base = view->base;
+            size = view->size;
+            break;
+        }
+        alloc_base = (char *)view->base + view->size;
+        view = view->next;
+    }
+    RtlLeaveCriticalSection(&csVirtual);
+
+    /* Fill the info structure */
+
+    if (!view)
+    {
+        info->State             = MEM_FREE;
+        info->Protect           = 0;
+        info->AllocationProtect = 0;
+        info->Type              = 0;
+    }
+    else
+    {
+        BYTE vprot = view->prot[(base - alloc_base) >> page_shift];
+        VIRTUAL_GetWin32Prot( vprot, &info->Protect, &info->State );
+        for (size = base - alloc_base; size < view->size; size += page_mask+1)
+            if (view->prot[size >> page_shift] != vprot) break;
+        info->AllocationProtect = view->protect;
+        info->Type              = MEM_PRIVATE;  /* FIXME */
+    }
+
+    info->BaseAddress    = (LPVOID)base;
+    info->AllocationBase = (LPVOID)alloc_base;
+    info->RegionSize     = size - (base - alloc_base);
+    *res_len = sizeof(*info);
+    return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ *             NtLockVirtualMemory   (NTDLL.@)
+ *             ZwLockVirtualMemory   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtLockVirtualMemory( HANDLE process, PVOID *addr, ULONG *size, ULONG unknown )
+{
+    if (!is_current_process( process ))
+    {
+        ERR("Unsupported on other process\n");
+        return STATUS_ACCESS_DENIED;
+    }
+    return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ *             NtUnlockVirtualMemory   (NTDLL.@)
+ *             ZwUnlockVirtualMemory   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtUnlockVirtualMemory( HANDLE process, PVOID *addr, ULONG *size, ULONG unknown )
+{
+    if (!is_current_process( process ))
+    {
+        ERR("Unsupported on other process\n");
+        return STATUS_ACCESS_DENIED;
+    }
+    return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ *             NtCreateSection   (NTDLL.@)
+ *             ZwCreateSection   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtCreateSection( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
+                                 const LARGE_INTEGER *size, ULONG protect,
+                                 ULONG sec_flags, HANDLE file )
+{
+    NTSTATUS ret;
+    BYTE vprot;
+    DWORD len = attr->ObjectName ? attr->ObjectName->Length : 0;
+
+    /* Check parameters */
+
+    if (len > MAX_PATH*sizeof(WCHAR)) return STATUS_NAME_TOO_LONG;
+
+    vprot = VIRTUAL_GetProt( protect );
+    if (sec_flags & SEC_RESERVE)
+    {
+        if (file) return STATUS_INVALID_PARAMETER;
+    }
+    else vprot |= VPROT_COMMITTED;
+    if (sec_flags & SEC_NOCACHE) vprot |= VPROT_NOCACHE;
+    if (sec_flags & SEC_IMAGE) vprot |= VPROT_IMAGE;
+
+    /* Create the server object */
+
+    SERVER_START_REQ( create_mapping )
+    {
+        req->file_handle = file;
+        req->size_high   = size ? size->s.HighPart : 0;
+        req->size_low    = size ? size->s.LowPart : 0;
+        req->protect     = vprot;
+        req->access      = access;
+        req->inherit     = (attr->Attributes & OBJ_INHERIT) != 0;
+        if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
+        ret = wine_server_call( req );
+        *handle = reply->handle;
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/***********************************************************************
+ *             NtOpenSection   (NTDLL.@)
+ *             ZwOpenSection   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtOpenSection( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
+{
+    NTSTATUS ret;
+    DWORD len = attr->ObjectName->Length;
+
+    if (len > MAX_PATH*sizeof(WCHAR)) return STATUS_NAME_TOO_LONG;
+
+    SERVER_START_REQ( open_mapping )
+    {
+        req->access  = access;
+        req->inherit = (attr->Attributes & OBJ_INHERIT) != 0;
+        wine_server_add_data( req, attr->ObjectName->Buffer, len );
+        if (!(ret = wine_server_call( req ))) *handle = reply->handle;
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/***********************************************************************
+ *             NtMapViewOfSection   (NTDLL.@)
+ *             ZwMapViewOfSection   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_ptr, ULONG zero_bits,
+                                    ULONG commit_size, const LARGE_INTEGER *offset, ULONG *size_ptr,
+                                    SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect )
+{
+    FILE_VIEW *view;
+    NTSTATUS res;
+    UINT size = 0;
+    int flags = MAP_PRIVATE;
+    int unix_handle = -1;
+    int prot;
+    void *base, *ptr = (void *)-1, *ret;
+    DWORD size_low, size_high, header_size, shared_size;
+    HANDLE shared_file;
+    BOOL removable;
+
+    if (!is_current_process( process ))
+    {
+        ERR("Unsupported on other process\n");
+        return STATUS_ACCESS_DENIED;
+    }
+
+    TRACE("handle=%x addr=%p off=%lx%08lx size=%x access=%lx\n",
+          handle, *addr_ptr, offset->s.HighPart, offset->s.LowPart, size, protect );
+
+    /* Check parameters */
+
+    if ((offset->s.LowPart & granularity_mask) ||
+        (*addr_ptr && ((UINT_PTR)*addr_ptr & granularity_mask)))
+        return STATUS_INVALID_PARAMETER;
+
+    SERVER_START_REQ( get_mapping_info )
+    {
+        req->handle = handle;
+        res = wine_server_call( req );
+        prot        = reply->protect;
+        base        = reply->base;
+        size_low    = reply->size_low;
+        size_high   = reply->size_high;
+        header_size = reply->header_size;
+        shared_file = reply->shared_file;
+        shared_size = reply->shared_size;
+        removable   = (reply->drive_type == DRIVE_REMOVABLE ||
+                       reply->drive_type == DRIVE_CDROM);
+    }
+    SERVER_END_REQ;
+    if (res) goto error;
+
+    if ((res = wine_server_handle_to_fd( handle, 0, &unix_handle, NULL, NULL ))) goto error;
+
+    if (prot & VPROT_IMAGE)
+    {
+        int shared_fd = -1;
+
+        if (shared_file)
+        {
+            if ((res = wine_server_handle_to_fd( shared_file, GENERIC_READ, &shared_fd,
+                                                 NULL, NULL ))) goto error;
+            NtClose( shared_file );  /* we no longer need it */
+        }
+        res = map_image( handle, unix_handle, base, size_low, header_size,
+                         shared_fd, shared_size, removable, addr_ptr );
+        if (shared_fd != -1) close( shared_fd );
+        if (!res) *size_ptr = size_low;
+        return res;
+    }
+
+
+    if (size_high)
+        ERR("Sizes larger than 4Gb not supported\n");
+
+    if ((offset->s.LowPart >= size_low) ||
+        (*size_ptr > size_low - offset->s.LowPart))
+    {
+        res = STATUS_INVALID_PARAMETER;
+        goto error;
+    }
+    if (*size_ptr) size = ROUND_SIZE( offset->s.LowPart, *size_ptr );
+    else size = size_low - offset->s.LowPart;
+
+    switch(protect)
+    {
+    case PAGE_NOACCESS:
+        break;
+    case PAGE_READWRITE:
+    case PAGE_EXECUTE_READWRITE:
+        if (!(prot & VPROT_WRITE))
+        {
+            res = STATUS_INVALID_PARAMETER;
+            goto error;
+        }
+        flags = MAP_SHARED;
+        /* fall through */
+    case PAGE_READONLY:
+    case PAGE_WRITECOPY:
+    case PAGE_EXECUTE:
+    case PAGE_EXECUTE_READ:
+    case PAGE_EXECUTE_WRITECOPY:
+        if (prot & VPROT_READ) break;
+        /* fall through */
+    default:
+        res = STATUS_INVALID_PARAMETER;
+        goto error;
+    }
+
+    /* FIXME: If a mapping is created with SEC_RESERVE and a process,
+     * which has a view of this mapping commits some pages, they will
+     * appear commited in all other processes, which have the same
+     * view created. Since we don`t support this yet, we create the
+     * whole mapping commited.
+     */
+    prot |= VPROT_COMMITTED;
+
+    /* Reserve a properly aligned area */
+
+    if ((res = anon_mmap_aligned( addr_ptr, size, PROT_NONE, 0 ))) goto error;
+    ptr = *addr_ptr;
+
+    /* Map the file */
+
+    TRACE("handle=%x size=%x offset=%lx\n", handle, size, offset->s.LowPart );
+
+    ret = VIRTUAL_mmap( unix_handle, ptr, size, offset->s.LowPart, offset->s.HighPart,
+                        VIRTUAL_GetUnixProt( prot ), flags | MAP_FIXED, &removable );
+    if (ret != ptr)
+    {
+        ERR( "VIRTUAL_mmap %p %x %lx%08lx failed\n",
+             ptr, size, offset->s.HighPart, offset->s.LowPart );
+        res = STATUS_NO_MEMORY;  /* FIXME */
+        goto error;
+    }
+    if (removable) handle = 0;  /* don't keep handle open on removable media */
+
+    if (!(view = VIRTUAL_CreateView( ptr, size, 0, prot, handle )))
+    {
+        res = STATUS_NO_MEMORY;
+        goto error;
+    }
+    if (unix_handle != -1) close( unix_handle );
+    *size_ptr = size;
+    return STATUS_SUCCESS;
+
+error:
+    if (unix_handle != -1) close( unix_handle );
+    if (ptr != (void *)-1) munmap( ptr, size );
+    return res;
+}
+
+
+/***********************************************************************
+ *             NtUnmapViewOfSection   (NTDLL.@)
+ *             ZwUnmapViewOfSection   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr )
+{
+    FILE_VIEW *view;
+    void *base = ROUND_ADDR( addr, page_mask );
+
+    if (!is_current_process( process ))
+    {
+        ERR("Unsupported on other process\n");
+        return STATUS_ACCESS_DENIED;
+    }
+    if (!(view = VIRTUAL_FindView( base )) || (base != view->base)) return STATUS_INVALID_PARAMETER;
+    VIRTUAL_DeleteView( view );
+    return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
+ *             NtFlushVirtualMemory   (NTDLL.@)
+ *             ZwFlushVirtualMemory   (NTDLL.@)
+ */
+NTSTATUS WINAPI NtFlushVirtualMemory( HANDLE process, LPCVOID *addr_ptr,
+                                      ULONG *size_ptr, ULONG unknown )
+{
+    FILE_VIEW *view;
+    void *addr = ROUND_ADDR( *addr_ptr, page_mask );
+
+    if (!is_current_process( process ))
+    {
+        ERR("Unsupported on other process\n");
+        return STATUS_ACCESS_DENIED;
+    }
+    if (!(view = VIRTUAL_FindView( addr ))) return STATUS_INVALID_PARAMETER;
+    if (!*size_ptr) *size_ptr = view->size;
+    *addr_ptr = addr;
+    if (!msync( addr, *size_ptr, MS_SYNC )) return STATUS_SUCCESS;
+    return STATUS_NOT_MAPPED_DATA;
+}
diff --git a/include/winbase.h b/include/winbase.h
index f65e7f3..5d290af 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1500,10 +1500,11 @@
 #define     VerifyVersionInfo WINELIB_NAME_AW(VerifyVersionInfo)
 LPVOID      WINAPI VirtualAlloc(LPVOID,DWORD,DWORD,DWORD);
 LPVOID      WINAPI VirtualAllocEx(HANDLE,LPVOID,DWORD,DWORD,DWORD);
-BOOL      WINAPI VirtualFree(LPVOID,DWORD,DWORD);
-BOOL      WINAPI VirtualLock(LPVOID,DWORD);
-BOOL      WINAPI VirtualProtect(LPVOID,DWORD,DWORD,LPDWORD);
-BOOL      WINAPI VirtualProtectEx(HANDLE,LPVOID,DWORD,DWORD,LPDWORD);
+BOOL        WINAPI VirtualFree(LPVOID,DWORD,DWORD);
+BOOL        WINAPI VirtualFreeEx(HANDLE,LPVOID,DWORD,DWORD);
+BOOL        WINAPI VirtualLock(LPVOID,DWORD);
+BOOL        WINAPI VirtualProtect(LPVOID,DWORD,DWORD,LPDWORD);
+BOOL        WINAPI VirtualProtectEx(HANDLE,LPVOID,DWORD,DWORD,LPDWORD);
 DWORD       WINAPI VirtualQuery(LPCVOID,LPMEMORY_BASIC_INFORMATION,DWORD);
 DWORD       WINAPI VirtualQueryEx(HANDLE,LPCVOID,LPMEMORY_BASIC_INFORMATION,DWORD);
 BOOL      WINAPI VirtualUnlock(LPVOID,DWORD);
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index c5d991a..0b7c4fd 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1418,6 +1418,7 @@
     int          size_high;
     int          size_low;
     int          protect;
+    unsigned int access;
     int          inherit;
     obj_handle_t file_handle;
     /* VARARG(name,unicode_str); */
@@ -3209,6 +3210,6 @@
     struct get_window_properties_reply get_window_properties_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 81
+#define SERVER_PROTOCOL_VERSION 82
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/include/winnt.h b/include/winnt.h
index 89bc850..5a1cd1a 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -3185,6 +3185,13 @@
 #define THREAD_BASE_PRIORITY_MIN   -2
 #define THREAD_BASE_PRIORITY_IDLE  -15
 
+#define SECTION_QUERY              0x0001
+#define SECTION_MAP_WRITE          0x0002
+#define SECTION_MAP_READ           0x0004
+#define SECTION_MAP_EXECUTE        0x0008
+#define SECTION_EXTEND_SIZE        0x0010
+#define SECTION_ALL_ACCESS         (STANDARD_RIGHTS_REQUIRED|0x01f)
+
 #define FILE_READ_DATA            0x0001    /* file & pipe */
 #define FILE_LIST_DIRECTORY       0x0001    /* directory */
 #define FILE_WRITE_DATA           0x0002    /* file & pipe */
diff --git a/include/winternl.h b/include/winternl.h
index 3568a36..41279a4 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -259,6 +259,11 @@
     WinStationInformation = 8
 } WINSTATIONINFOCLASS;
 
+typedef enum
+{
+    MemoryBasicInformation = 0
+} MEMORY_INFORMATION_CLASS;
+
 /***********************************************************************
  * IA64 specific types and data structures
  */
@@ -753,11 +758,13 @@
 
 NTSTATUS  WINAPI NtAccessCheck(PSECURITY_DESCRIPTOR,HANDLE,ACCESS_MASK,PGENERIC_MAPPING,PPRIVILEGE_SET,PULONG,PULONG,PBOOLEAN);
 NTSTATUS  WINAPI NtAdjustPrivilegesToken(HANDLE,BOOLEAN,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
+NTSTATUS  WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,PVOID,ULONG*,ULONG,ULONG);
 NTSTATUS  WINAPI NtClearEvent(HANDLE);
 NTSTATUS  WINAPI NtClose(HANDLE);
 NTSTATUS  WINAPI NtCreateEvent(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES *,BOOLEAN,BOOLEAN);
 NTSTATUS  WINAPI NtCreateFile(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
 NTSTATUS  WINAPI NtCreateKey(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,const UNICODE_STRING*,ULONG,PULONG);
+NTSTATUS  WINAPI NtCreateSection(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const LARGE_INTEGER*,ULONG,ULONG,HANDLE);
 NTSTATUS  WINAPI NtCreateSemaphore(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,ULONG);
 NTSTATUS  WINAPI NtDeleteKey(HANDLE);
 NTSTATUS  WINAPI NtDeleteValueKey(HANDLE,const UNICODE_STRING *);
@@ -766,13 +773,19 @@
 NTSTATUS  WINAPI NtEnumerateKey(HANDLE,ULONG,KEY_INFORMATION_CLASS,void *,DWORD,DWORD *);
 NTSTATUS  WINAPI NtEnumerateValueKey(HANDLE,ULONG,KEY_VALUE_INFORMATION_CLASS,PVOID,ULONG,PULONG);
 NTSTATUS  WINAPI NtFlushKey(HANDLE);
+NTSTATUS  WINAPI NtFlushVirtualMemory(HANDLE,LPCVOID*,ULONG*,ULONG);
+NTSTATUS  WINAPI NtFreeVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG);
 NTSTATUS  WINAPI NtLoadKey(const OBJECT_ATTRIBUTES *,const OBJECT_ATTRIBUTES *);
+NTSTATUS  WINAPI NtLockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG);
+NTSTATUS  WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,ULONG,const LARGE_INTEGER*,ULONG*,SECTION_INHERIT,ULONG,ULONG);
 NTSTATUS  WINAPI NtNotifyChangeKey(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN);
 NTSTATUS  WINAPI NtOpenEvent(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES *);
 NTSTATUS  WINAPI NtOpenFile(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,ULONG,ULONG);
 NTSTATUS  WINAPI NtOpenKey(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES *);
 NTSTATUS  WINAPI NtOpenProcessToken(HANDLE,DWORD,HANDLE *);
+NTSTATUS  WINAPI NtOpenSection(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*);
 NTSTATUS  WINAPI NtOpenThreadToken(HANDLE,DWORD,BOOLEAN,HANDLE *);
+NTSTATUS  WINAPI NtProtectVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG,ULONG*);
 NTSTATUS  WINAPI NtPulseEvent(HANDLE,PULONG);
 NTSTATUS  WINAPI NtQueryInformationProcess(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
 NTSTATUS  WINAPI NtQueryInformationThread(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
@@ -783,6 +796,7 @@
 NTSTATUS  WINAPI NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS,PVOID,ULONG,PULONG);
 NTSTATUS  WINAPI NtQuerySystemTime(PLARGE_INTEGER);
 NTSTATUS  WINAPI NtQueryValueKey(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *);
+NTSTATUS  WINAPI NtQueryVirtualMemory(HANDLE,LPCVOID,MEMORY_INFORMATION_CLASS,PVOID,ULONG,ULONG*);
 void      WINAPI NtRaiseException(PEXCEPTION_RECORD,PCONTEXT,BOOL);
 NTSTATUS  WINAPI NtReadFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,PLARGE_INTEGER,PULONG);
 NTSTATUS  WINAPI NtReleaseSemaphore(HANDLE,ULONG,PULONG);
@@ -797,6 +811,8 @@
 NTSTATUS  WINAPI NtTerminateProcess(HANDLE,LONG);
 NTSTATUS  WINAPI NtTerminateThread(HANDLE,LONG);
 NTSTATUS  WINAPI NtUnloadKey(HANDLE);
+NTSTATUS  WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG);
+NTSTATUS  WINAPI NtUnmapViewOfSection(HANDLE,PVOID);
 NTSTATUS  WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,PLARGE_INTEGER);
 
 void      WINAPI RtlAcquirePebLock(void);
diff --git a/memory/virtual.c b/memory/virtual.c
index ab01a1e..32f6c5d 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -21,110 +21,25 @@
 #include "config.h"
 #include "wine/port.h"
 
-#include <assert.h>
-#include <errno.h>
-#ifdef HAVE_SYS_ERRNO_H
-#include <sys/errno.h>
-#endif
 #include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
+
 #include "winnls.h"
 #include "winbase.h"
-#include "wine/exception.h"
-#include "wine/unicode.h"
-#include "wine/library.h"
+#include "winternl.h"
 #include "winerror.h"
-#include "file.h"
-#include "global.h"
-#include "wine/server.h"
+#include "wine/exception.h"
 #include "msvcrt/excpt.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(virtual);
-WINE_DECLARE_DEBUG_CHANNEL(module);
 
-#ifndef MS_SYNC
-#define MS_SYNC 0
-#endif
-
-/* File view */
-typedef struct _FV
-{
-    struct _FV   *next;        /* Next view */
-    struct _FV   *prev;        /* Prev view */
-    void         *base;        /* Base address */
-    UINT          size;        /* Size in bytes */
-    UINT          flags;       /* Allocation flags */
-    HANDLE        mapping;     /* Handle to the file mapping */
-    HANDLERPROC   handlerProc; /* Fault handler */
-    LPVOID        handlerArg;  /* Fault handler argument */
-    BYTE          protect;     /* Protection for all pages at allocation time */
-    BYTE          prot[1];     /* Protection byte for each page */
-} FILE_VIEW;
-
-/* Per-view flags */
-#define VFLAG_SYSTEM     0x01
-#define VFLAG_VALLOC     0x02  /* allocated by VirtualAlloc */
-
-/* Conversion from VPROT_* to Win32 flags */
-static const BYTE VIRTUAL_Win32Flags[16] =
-{
-    PAGE_NOACCESS,              /* 0 */
-    PAGE_READONLY,              /* READ */
-    PAGE_READWRITE,             /* WRITE */
-    PAGE_READWRITE,             /* READ | WRITE */
-    PAGE_EXECUTE,               /* EXEC */
-    PAGE_EXECUTE_READ,          /* READ | EXEC */
-    PAGE_EXECUTE_READWRITE,     /* WRITE | EXEC */
-    PAGE_EXECUTE_READWRITE,     /* READ | WRITE | EXEC */
-    PAGE_WRITECOPY,             /* WRITECOPY */
-    PAGE_WRITECOPY,             /* READ | WRITECOPY */
-    PAGE_WRITECOPY,             /* WRITE | WRITECOPY */
-    PAGE_WRITECOPY,             /* READ | WRITE | WRITECOPY */
-    PAGE_EXECUTE_WRITECOPY,     /* EXEC | WRITECOPY */
-    PAGE_EXECUTE_WRITECOPY,     /* READ | EXEC | WRITECOPY */
-    PAGE_EXECUTE_WRITECOPY,     /* WRITE | EXEC | WRITECOPY */
-    PAGE_EXECUTE_WRITECOPY      /* READ | WRITE | EXEC | WRITECOPY */
-};
-
-
-static FILE_VIEW *VIRTUAL_FirstView;
-static CRITICAL_SECTION csVirtual = CRITICAL_SECTION_INIT("csVirtual");
-
-#ifdef __i386__
-/* These are always the same on an i386, and it will be faster this way */
-# define page_mask  0xfff
-# define page_shift 12
-# define page_size  0x1000
-#else
-static UINT page_shift;
-static UINT page_mask;
-static UINT page_size;
-#endif  /* __i386__ */
-#define granularity_mask 0xffff  /* Allocation granularity (usually 64k) */
-
-#define ADDRESS_SPACE_LIMIT  ((void *)0xc0000000)  /* top of the user address space */
-
-#define ROUND_ADDR(addr,mask) \
-   ((void *)((UINT_PTR)(addr) & ~(mask)))
-
-#define ROUND_SIZE(addr,size) \
-   (((UINT)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
-
-#define VIRTUAL_DEBUG_DUMP_VIEW(view) \
-   if (!TRACE_ON(virtual)); else VIRTUAL_DumpView(view)
-
-static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size, DWORD offset_low,
-                            DWORD offset_high, int prot, int flags, BOOL *removable );
+static unsigned int page_size;
 
 /* filter for page-fault exceptions */
 static WINE_EXCEPTION_FILTER(page_fault)
@@ -134,841 +49,6 @@
     return EXCEPTION_CONTINUE_SEARCH;
 }
 
-/***********************************************************************
- *           VIRTUAL_GetProtStr
- */
-static const char *VIRTUAL_GetProtStr( BYTE prot )
-{
-    static char buffer[6];
-    buffer[0] = (prot & VPROT_COMMITTED) ? 'c' : '-';
-    buffer[1] = (prot & VPROT_GUARD) ? 'g' : '-';
-    buffer[2] = (prot & VPROT_READ) ? 'r' : '-';
-    buffer[3] = (prot & VPROT_WRITE) ?
-                    ((prot & VPROT_WRITECOPY) ? 'w' : 'W') : '-';
-    buffer[4] = (prot & VPROT_EXEC) ? 'x' : '-';
-    buffer[5] = 0;
-    return buffer;
-}
-
-
-/***********************************************************************
- *           VIRTUAL_DumpView
- */
-static void VIRTUAL_DumpView( FILE_VIEW *view )
-{
-    UINT i, count;
-    char *addr = view->base;
-    BYTE prot = view->prot[0];
-
-    DPRINTF( "View: %p - %p", addr, addr + view->size - 1 );
-    if (view->flags & VFLAG_SYSTEM)
-        DPRINTF( " (system)\n" );
-    else if (view->flags & VFLAG_VALLOC)
-        DPRINTF( " (valloc)\n" );
-    else if (view->mapping)
-        DPRINTF( " %d\n", view->mapping );
-    else
-        DPRINTF( " (anonymous)\n");
-
-    for (count = i = 1; i < view->size >> page_shift; i++, count++)
-    {
-        if (view->prot[i] == prot) continue;
-        DPRINTF( "      %p - %p %s\n",
-                 addr, addr + (count << page_shift) - 1, VIRTUAL_GetProtStr(prot) );
-        addr += (count << page_shift);
-        prot = view->prot[i];
-        count = 0;
-    }
-    if (count)
-        DPRINTF( "      %p - %p %s\n",
-                 addr, addr + (count << page_shift) - 1, VIRTUAL_GetProtStr(prot) );
-}
-
-
-/***********************************************************************
- *           VIRTUAL_Dump
- */
-void VIRTUAL_Dump(void)
-{
-    FILE_VIEW *view;
-    DPRINTF( "\nDump of all virtual memory views:\n\n" );
-    EnterCriticalSection(&csVirtual);
-    view = VIRTUAL_FirstView;
-    while (view)
-    {
-        VIRTUAL_DumpView( view );
-        view = view->next;
-    }
-    LeaveCriticalSection(&csVirtual);
-}
-
-
-/***********************************************************************
- *           VIRTUAL_FindView
- *
- * Find the view containing a given address.
- *
- * RETURNS
- *	View: Success
- *	NULL: Failure
- */
-static FILE_VIEW *VIRTUAL_FindView( const void *addr ) /* [in] Address */
-{
-    FILE_VIEW *view;
-
-    EnterCriticalSection(&csVirtual);
-    view = VIRTUAL_FirstView;
-    while (view)
-    {
-        if (view->base > addr)
-        {
-            view = NULL;
-            break;
-        }
-        if ((char*)view->base + view->size > (char*)addr) break;
-        view = view->next;
-    }
-    LeaveCriticalSection(&csVirtual);
-    return view;
-}
-
-
-/***********************************************************************
- *           VIRTUAL_CreateView
- *
- * Create a new view and add it in the linked list.
- */
-static FILE_VIEW *VIRTUAL_CreateView( void *base, UINT size, UINT flags,
-                                      BYTE vprot, HANDLE mapping )
-{
-    FILE_VIEW *view, *prev;
-
-    /* Create the view structure */
-
-    assert( !((unsigned int)base & page_mask) );
-    assert( !(size & page_mask) );
-    size >>= page_shift;
-    if (!(view = (FILE_VIEW *)malloc( sizeof(*view) + size - 1 ))) return NULL;
-    view->base    = base;
-    view->size    = size << page_shift;
-    view->flags   = flags;
-    view->mapping = mapping;
-    view->protect = vprot;
-    view->handlerProc = NULL;
-    memset( view->prot, vprot, size );
-
-    /* Duplicate the mapping handle */
-
-    if (view->mapping &&
-        !DuplicateHandle( GetCurrentProcess(), view->mapping,
-                          GetCurrentProcess(), &view->mapping,
-                          0, FALSE, DUPLICATE_SAME_ACCESS ))
-    {
-        free( view );
-        return NULL;
-    }
-
-    /* Insert it in the linked list */
-
-    EnterCriticalSection(&csVirtual);
-    if (!VIRTUAL_FirstView || (VIRTUAL_FirstView->base > base))
-    {
-        view->next = VIRTUAL_FirstView;
-        view->prev = NULL;
-        if (view->next) view->next->prev = view;
-        VIRTUAL_FirstView = view;
-    }
-    else
-    {
-        prev = VIRTUAL_FirstView;
-        while (prev->next && (prev->next->base < base)) prev = prev->next;
-        view->next = prev->next;
-        view->prev = prev;
-        if (view->next) view->next->prev = view;
-        prev->next  = view;
-    }
-    LeaveCriticalSection(&csVirtual);
-    VIRTUAL_DEBUG_DUMP_VIEW( view );
-    return view;
-}
-
-
-/***********************************************************************
- *           VIRTUAL_DeleteView
- * Deletes a view.
- *
- * RETURNS
- *	None
- */
-static void VIRTUAL_DeleteView(
-            FILE_VIEW *view /* [in] View */
-) {
-    if (!(view->flags & VFLAG_SYSTEM))
-        munmap( (void *)view->base, view->size );
-    EnterCriticalSection(&csVirtual);
-    if (view->next) view->next->prev = view->prev;
-    if (view->prev) view->prev->next = view->next;
-    else VIRTUAL_FirstView = view->next;
-    LeaveCriticalSection(&csVirtual);
-    if (view->mapping) NtClose( view->mapping );
-    free( view );
-}
-
-
-/***********************************************************************
- *           VIRTUAL_GetUnixProt
- *
- * Convert page protections to protection for mmap/mprotect.
- */
-static int VIRTUAL_GetUnixProt( BYTE vprot )
-{
-    int prot = 0;
-    if ((vprot & VPROT_COMMITTED) && !(vprot & VPROT_GUARD))
-    {
-        if (vprot & VPROT_READ) prot |= PROT_READ;
-        if (vprot & VPROT_WRITE) prot |= PROT_WRITE;
-        if (vprot & VPROT_WRITECOPY) prot |= PROT_WRITE;
-        if (vprot & VPROT_EXEC) prot |= PROT_EXEC;
-    }
-    return prot;
-}
-
-
-/***********************************************************************
- *           VIRTUAL_GetWin32Prot
- *
- * Convert page protections to Win32 flags.
- *
- * RETURNS
- *	None
- */
-static void VIRTUAL_GetWin32Prot(
-            BYTE vprot,     /* [in] Page protection flags */
-            DWORD *protect, /* [out] Location to store Win32 protection flags */
-            DWORD *state    /* [out] Location to store mem state flag */
-) {
-    if (protect) {
-    	*protect = VIRTUAL_Win32Flags[vprot & 0x0f];
-/*    	if (vprot & VPROT_GUARD) *protect |= PAGE_GUARD;*/
-    	if (vprot & VPROT_NOCACHE) *protect |= PAGE_NOCACHE;
-
-    	if (vprot & VPROT_GUARD) *protect = PAGE_NOACCESS;
-    }
-
-    if (state) *state = (vprot & VPROT_COMMITTED) ? MEM_COMMIT : MEM_RESERVE;
-}
-
-
-/***********************************************************************
- *           VIRTUAL_GetProt
- *
- * Build page protections from Win32 flags.
- *
- * RETURNS
- *	Value of page protection flags
- */
-static BYTE VIRTUAL_GetProt(
-            DWORD protect  /* [in] Win32 protection flags */
-) {
-    BYTE vprot;
-
-    switch(protect & 0xff)
-    {
-    case PAGE_READONLY:
-        vprot = VPROT_READ;
-        break;
-    case PAGE_READWRITE:
-        vprot = VPROT_READ | VPROT_WRITE;
-        break;
-    case PAGE_WRITECOPY:
-        /* MSDN CreateFileMapping() states that if PAGE_WRITECOPY is given,
-	 * that the hFile must have been opened with GENERIC_READ and
-	 * GENERIC_WRITE access.  This is WRONG as tests show that you
-	 * only need GENERIC_READ access (at least for Win9x,
-	 * FIXME: what about NT?).  Thus, we don't put VPROT_WRITE in
-	 * PAGE_WRITECOPY and PAGE_EXECUTE_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:
-        /* See comment for PAGE_WRITECOPY above */
-        vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITECOPY;
-        break;
-    case PAGE_NOACCESS:
-    default:
-        vprot = 0;
-        break;
-    }
-    if (protect & PAGE_GUARD) vprot |= VPROT_GUARD;
-    if (protect & PAGE_NOCACHE) vprot |= VPROT_NOCACHE;
-    return vprot;
-}
-
-
-/***********************************************************************
- *           VIRTUAL_SetProt
- *
- * Change the protection of a range of pages.
- *
- * RETURNS
- *	TRUE: Success
- *	FALSE: Failure
- */
-static BOOL VIRTUAL_SetProt( FILE_VIEW *view, /* [in] Pointer to view */
-                             void *base,      /* [in] Starting address */
-                             UINT size,       /* [in] Size in bytes */
-                             BYTE vprot )     /* [in] Protections to use */
-{
-    TRACE("%p-%p %s\n",
-          base, (char *)base + size - 1, VIRTUAL_GetProtStr( vprot ) );
-
-    if (mprotect( base, size, VIRTUAL_GetUnixProt(vprot) ))
-        return FALSE;  /* FIXME: last error */
-
-    memset( view->prot + (((char *)base - (char *)view->base) >> page_shift),
-            vprot, size >> page_shift );
-    VIRTUAL_DEBUG_DUMP_VIEW( view );
-    return TRUE;
-}
-
-
-/***********************************************************************
- *           anon_mmap_aligned
- *
- * Create an anonymous mapping aligned to the allocation granularity.
- */
-static void *anon_mmap_aligned( void *base, unsigned int size, int prot, int flags )
-{
-    void *ptr;
-    unsigned int view_size = size + (base ? 0 : granularity_mask + 1);
-
-    if ((ptr = wine_anon_mmap( base, view_size, prot, flags )) == (void *)-1)
-    {
-        /* KB: Q125713, 25-SEP-1995, "Common File Mapping Problems and
-	 * Platform Differences":
-	 * Windows NT: ERROR_INVALID_PARAMETER
-	 * Windows 95: ERROR_INVALID_ADDRESS.
-	 */
-        if (errno == ENOMEM) SetLastError( ERROR_OUTOFMEMORY );
-        else
-        {
-            if (GetVersion() & 0x80000000)  /* win95 */
-                SetLastError( ERROR_INVALID_ADDRESS );
-            else
-                SetLastError( ERROR_INVALID_PARAMETER );
-        }
-        return ptr;
-    }
-
-    if (!base)
-    {
-        /* Release the extra memory while keeping the range
-         * starting on the granularity boundary. */
-        if ((unsigned int)ptr & granularity_mask)
-        {
-            unsigned int extra = granularity_mask + 1 - ((unsigned int)ptr & granularity_mask);
-            munmap( ptr, extra );
-            ptr = (char *)ptr + extra;
-            view_size -= extra;
-        }
-        if (view_size > size)
-            munmap( (char *)ptr + size, view_size - size );
-    }
-    else if (ptr != base)
-    {
-        /* We couldn't get the address we wanted */
-        munmap( ptr, view_size );
-        SetLastError( ERROR_INVALID_ADDRESS );
-        ptr = (void *)-1;
-    }
-    return ptr;
-}
-
-
-/***********************************************************************
- *           do_relocations
- *
- * Apply the relocations to a mapped PE image
- */
-static int do_relocations( char *base, const IMAGE_DATA_DIRECTORY *dir,
-                           int delta, DWORD total_size )
-{
-    IMAGE_BASE_RELOCATION *rel;
-
-    TRACE_(module)( "relocating from %p-%p to %p-%p\n",
-                    base - delta, base - delta + total_size, base, base + total_size );
-
-    for (rel = (IMAGE_BASE_RELOCATION *)(base + dir->VirtualAddress);
-         ((char *)rel < base + dir->VirtualAddress + dir->Size) && rel->SizeOfBlock;
-         rel = (IMAGE_BASE_RELOCATION*)((char*)rel + rel->SizeOfBlock) )
-    {
-        char *page = base + rel->VirtualAddress;
-        WORD *TypeOffset = (WORD *)(rel + 1);
-        int i, count = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(*TypeOffset);
-
-        if (!count) continue;
-
-        /* sanity checks */
-        if ((char *)rel + rel->SizeOfBlock > base + dir->VirtualAddress + dir->Size ||
-            page > base + total_size)
-        {
-            ERR_(module)("invalid relocation %p,%lx,%ld at %p,%lx,%lx\n",
-                         rel, rel->VirtualAddress, rel->SizeOfBlock,
-                         base, dir->VirtualAddress, dir->Size );
-            return 0;
-        }
-
-        TRACE_(module)("%ld relocations for page %lx\n", rel->SizeOfBlock, rel->VirtualAddress);
-
-        /* patching in reverse order */
-        for (i = 0 ; i < count; i++)
-        {
-            int offset = TypeOffset[i] & 0xFFF;
-            int type = TypeOffset[i] >> 12;
-            switch(type)
-            {
-            case IMAGE_REL_BASED_ABSOLUTE:
-                break;
-            case IMAGE_REL_BASED_HIGH:
-                *(short*)(page+offset) += HIWORD(delta);
-                break;
-            case IMAGE_REL_BASED_LOW:
-                *(short*)(page+offset) += LOWORD(delta);
-                break;
-            case IMAGE_REL_BASED_HIGHLOW:
-                *(int*)(page+offset) += delta;
-                /* FIXME: if this is an exported address, fire up enhanced logic */
-                break;
-            default:
-                FIXME_(module)("Unknown/unsupported fixup type %d.\n", type);
-                break;
-            }
-        }
-    }
-    return 1;
-}
-
-
-/***********************************************************************
- *           map_image
- *
- * Map an executable (PE format) image into memory.
- */
-static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size,
-                         DWORD header_size, HANDLE shared_file, DWORD shared_size,
-                         BOOL removable )
-{
-    IMAGE_DOS_HEADER *dos;
-    IMAGE_NT_HEADERS *nt;
-    IMAGE_SECTION_HEADER *sec;
-    IMAGE_DATA_DIRECTORY *imports;
-    int i, pos;
-    DWORD err = GetLastError();
-    FILE_VIEW *view;
-    char *ptr;
-    int shared_fd = -1;
-
-    SetLastError( ERROR_BAD_EXE_FORMAT );  /* generic error */
-
-    /* zero-map the whole range */
-
-    if (base < (char *)0x110000 ||  /* make sure the DOS area remains free */
-        (ptr = wine_anon_mmap( base, total_size,
-                               PROT_READ | PROT_WRITE | PROT_EXEC, 0 )) == (char *)-1)
-    {
-        ptr = wine_anon_mmap( NULL, total_size,
-                            PROT_READ | PROT_WRITE | PROT_EXEC, 0 );
-        if (ptr == (char *)-1)
-        {
-            ERR_(module)("Not enough memory for module (%ld bytes)\n", total_size);
-            goto error;
-        }
-    }
-    TRACE_(module)( "mapped PE file at %p-%p\n", ptr, ptr + total_size );
-
-    /* map the header */
-
-    if (VIRTUAL_mmap( fd, ptr, header_size, 0, 0, PROT_READ,
-                      MAP_PRIVATE | MAP_FIXED, &removable ) == (char *)-1) goto error;
-    dos = (IMAGE_DOS_HEADER *)ptr;
-    nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew);
-    if ((char *)(nt + 1) > ptr + header_size) goto error;
-
-    sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
-    if ((char *)(sec + nt->FileHeader.NumberOfSections) > ptr + header_size) 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_I386)
-    {
-        MESSAGE("Trying to load PE image for unsupported architecture (");
-        switch (nt->FileHeader.Machine)
-        {
-        case IMAGE_FILE_MACHINE_UNKNOWN: MESSAGE("Unknown"); break;
-        case IMAGE_FILE_MACHINE_I860:    MESSAGE("I860"); break;
-        case IMAGE_FILE_MACHINE_R3000:   MESSAGE("R3000"); break;
-        case IMAGE_FILE_MACHINE_R4000:   MESSAGE("R4000"); break;
-        case IMAGE_FILE_MACHINE_R10000:  MESSAGE("R10000"); break;
-        case IMAGE_FILE_MACHINE_ALPHA:   MESSAGE("Alpha"); break;
-        case IMAGE_FILE_MACHINE_POWERPC: MESSAGE("PowerPC"); break;
-        default: MESSAGE("Unknown-%04x", nt->FileHeader.Machine); break;
-        }
-        MESSAGE(")\n");
-        goto error;
-    }
-
-    /* retrieve the shared sections file */
-
-    if (shared_size)
-    {
-        if ((shared_fd = FILE_GetUnixHandle( shared_file, GENERIC_READ )) == -1) goto error;
-        CloseHandle( shared_file );  /* we no longer need it */
-        shared_file = 0;
-    }
-
-    /* map all the sections */
-
-    for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
-    {
-        DWORD size;
-
-        /* a few sanity checks */
-        size = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
-        if (sec->VirtualAddress > total_size || size > total_size || size < sec->VirtualAddress)
-        {
-            ERR_(module)( "Section %.8s too large (%lx+%lx/%lx)\n",
-                          sec->Name, sec->VirtualAddress, sec->Misc.VirtualSize, total_size );
-            goto error;
-        }
-
-        if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) &&
-            (sec->Characteristics & IMAGE_SCN_MEM_WRITE))
-        {
-            size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
-            TRACE_(module)( "mapping shared section %.8s at %p off %lx (%x) size %lx (%lx) flags %lx\n",
-                          sec->Name, ptr + sec->VirtualAddress,
-                          sec->PointerToRawData, pos, sec->SizeOfRawData,
-                          size, sec->Characteristics );
-            if (VIRTUAL_mmap( shared_fd, ptr + sec->VirtualAddress, size,
-                              pos, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
-                              MAP_SHARED|MAP_FIXED, NULL ) == (void *)-1)
-            {
-                ERR_(module)( "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 + size)
-            {
-                UINT_PTR base = imports->VirtualAddress & ~page_mask;
-                UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size );
-                if (end > sec->VirtualAddress + size) end = sec->VirtualAddress + size;
-                if (end > base) VIRTUAL_mmap( shared_fd, ptr + base, end - base,
-                                              pos, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
-                                              MAP_PRIVATE|MAP_FIXED, NULL );
-            }
-            pos += size;
-            continue;
-        }
-
-        TRACE_(module)( "mapping section %.8s at %p off %lx size %lx flags %lx\n",
-                        sec->Name, ptr + sec->VirtualAddress,
-                        sec->PointerToRawData, sec->SizeOfRawData,
-                        sec->Characteristics );
-
-        if (sec->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) continue;
-        if (!sec->PointerToRawData || !sec->SizeOfRawData) continue;
-
-        /* Note: if the section is not aligned properly VIRTUAL_mmap will magically
-         *       fall back to read(), so we don't need to check anything here.
-         */
-        if (VIRTUAL_mmap( fd, ptr + sec->VirtualAddress, sec->SizeOfRawData,
-                          sec->PointerToRawData, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
-                          MAP_PRIVATE | MAP_FIXED, &removable ) == (void *)-1)
-        {
-            ERR_(module)( "Could not map section %.8s, file probably truncated\n", sec->Name );
-            goto error;
-        }
-
-        if ((sec->SizeOfRawData < sec->Misc.VirtualSize) && (sec->SizeOfRawData & page_mask))
-        {
-            DWORD end = ROUND_SIZE( 0, sec->SizeOfRawData );
-            if (end > sec->Misc.VirtualSize) end = sec->Misc.VirtualSize;
-            TRACE_(module)("clearing %p - %p\n",
-                           ptr + sec->VirtualAddress + sec->SizeOfRawData,
-                           ptr + sec->VirtualAddress + end );
-            memset( ptr + sec->VirtualAddress + sec->SizeOfRawData, 0,
-                    end - sec->SizeOfRawData );
-        }
-    }
-
-
-    /* perform base relocation, if necessary */
-
-    if (ptr != base)
-    {
-        const IMAGE_DATA_DIRECTORY *relocs;
-
-        relocs = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
-        if (!relocs->VirtualAddress || !relocs->Size)
-        {
-            if (nt->OptionalHeader.ImageBase == 0x400000)
-                ERR("Standard load address for a Win32 program (0x00400000) not available - security-patched kernel ?\n");
-            else
-                ERR( "FATAL: Need to relocate module from addr %lx, but there are no relocation records\n",
-                     nt->OptionalHeader.ImageBase );
-            SetLastError( ERROR_BAD_EXE_FORMAT );
-            goto error;
-        }
-
-        /* FIXME: If we need to relocate a system DLL (base > 2GB) we should
-         *        really make sure that the *new* base address is also > 2GB.
-         *        Some DLLs really check the MSB of the module handle :-/
-         */
-        if ((nt->OptionalHeader.ImageBase & 0x80000000) && !((DWORD)base & 0x80000000))
-            ERR( "Forced to relocate system DLL (base > 2GB). This is not good.\n" );
-
-        if (!do_relocations( ptr, relocs, ptr - base, total_size ))
-        {
-            SetLastError( ERROR_BAD_EXE_FORMAT );
-            goto error;
-        }
-    }
-
-    if (removable) hmapping = 0;  /* don't keep handle open on removable media */
-    if (!(view = VIRTUAL_CreateView( ptr, total_size, 0, VPROT_COMMITTED|VPROT_READ, hmapping )))
-    {
-        SetLastError( ERROR_OUTOFMEMORY );
-        goto error;
-    }
-
-    /* set the image protections */
-
-    sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
-    for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
-    {
-        DWORD size = ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
-        BYTE vprot = VPROT_COMMITTED;
-        if (sec->Characteristics & IMAGE_SCN_MEM_READ)    vprot |= VPROT_READ;
-        if (sec->Characteristics & IMAGE_SCN_MEM_WRITE)   vprot |= VPROT_WRITE|VPROT_WRITECOPY;
-        if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC;
-
-        /* make sure the import directory is writable */
-        if (imports && imports->VirtualAddress >= sec->VirtualAddress &&
-            imports->VirtualAddress < sec->VirtualAddress + size)
-            vprot |= VPROT_READ|VPROT_WRITE|VPROT_WRITECOPY;
-
-        VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );
-    }
-
-    SetLastError( err );  /* restore last error */
-    close( fd );
-    if (shared_fd != -1) close( shared_fd );
-    return ptr;
-
- error:
-    if (ptr != (char *)-1) munmap( ptr, total_size );
-    close( fd );
-    if (shared_fd != -1) close( shared_fd );
-    if (shared_file) CloseHandle( shared_file );
-    return NULL;
-}
-
-
-/***********************************************************************
- *           VIRTUAL_Init
- */
-#ifndef page_mask
-DECL_GLOBAL_CONSTRUCTOR(VIRTUAL_Init)
-{
-    page_size = getpagesize();
-    page_mask = page_size - 1;
-    /* Make sure we have a power of 2 */
-    assert( !(page_size & page_mask) );
-    page_shift = 0;
-    while ((1 << page_shift) != page_size) page_shift++;
-}
-#endif  /* page_mask */
-
-
-/***********************************************************************
- *           VIRTUAL_SetFaultHandler
- */
-BOOL VIRTUAL_SetFaultHandler( LPCVOID addr, HANDLERPROC proc, LPVOID arg )
-{
-    FILE_VIEW *view;
-
-    if (!(view = VIRTUAL_FindView( addr ))) return FALSE;
-    view->handlerProc = proc;
-    view->handlerArg  = arg;
-    return TRUE;
-}
-
-/***********************************************************************
- *           VIRTUAL_HandleFault
- */
-DWORD VIRTUAL_HandleFault( LPCVOID addr )
-{
-    FILE_VIEW *view = VIRTUAL_FindView( addr );
-    DWORD ret = EXCEPTION_ACCESS_VIOLATION;
-
-    if (view)
-    {
-        if (view->handlerProc)
-        {
-            if (view->handlerProc(view->handlerArg, addr)) ret = 0;  /* handled */
-        }
-        else
-        {
-            BYTE vprot = view->prot[((char *)addr - (char *)view->base) >> page_shift];
-            void *page = (void *)((UINT_PTR)addr & ~page_mask);
-            char *stack = (char *)NtCurrentTeb()->stack_base + SIGNAL_STACK_SIZE + page_mask + 1;
-            if (vprot & VPROT_GUARD)
-            {
-                VIRTUAL_SetProt( view, page, page_mask + 1, vprot & ~VPROT_GUARD );
-                ret = STATUS_GUARD_PAGE_VIOLATION;
-            }
-            /* is it inside the stack guard pages? */
-            if (((char *)addr >= stack) && ((char *)addr < stack + 2*(page_mask+1)))
-                ret = STATUS_STACK_OVERFLOW;
-        }
-    }
-    return ret;
-}
-
-
-
-/***********************************************************************
- *           unaligned_mmap
- *
- * Linux kernels before 2.4.x can support non page-aligned offsets, as
- * long as the offset is aligned to the filesystem block size. This is
- * a big performance gain so we want to take advantage of it.
- *
- * However, when we use 64-bit file support this doesn't work because
- * glibc rejects unaligned offsets. Also glibc 2.1.3 mmap64 is broken
- * in that it rounds unaligned offsets down to a page boundary. For
- * these reasons we do a direct system call here.
- */
-static void *unaligned_mmap( void *addr, size_t length, unsigned int prot,
-                             unsigned int flags, int fd, unsigned int offset_low,
-                             unsigned int offset_high )
-{
-#if defined(linux) && defined(__i386__) && defined(__GNUC__)
-    if (!offset_high && (offset_low & page_mask))
-    {
-        int ret;
-
-        struct
-        {
-            void        *addr;
-            unsigned int length;
-            unsigned int prot;
-            unsigned int flags;
-            unsigned int fd;
-            unsigned int offset;
-        } args;
-
-        args.addr   = addr;
-        args.length = length;
-        args.prot   = prot;
-        args.flags  = flags;
-        args.fd     = fd;
-        args.offset = offset_low;
-
-        __asm__ __volatile__("push %%ebx\n\t"
-                             "movl %2,%%ebx\n\t"
-                             "int $0x80\n\t"
-                             "popl %%ebx"
-                             : "=a" (ret)
-                             : "0" (90), /* SYS_mmap */
-                               "g" (&args) );
-        if (ret < 0 && ret > -4096)
-        {
-            errno = -ret;
-            ret = -1;
-        }
-        return (void *)ret;
-    }
-#endif
-    return mmap( addr, length, prot, flags, fd, ((off_t)offset_high << 32) | offset_low );
-}
-
-
-/***********************************************************************
- *           VIRTUAL_mmap
- *
- * Wrapper for mmap() that handles anonymous mappings portably,
- * and falls back to read if mmap of a file fails.
- */
-static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size,
-                            DWORD offset_low, DWORD offset_high,
-                            int prot, int flags, BOOL *removable )
-{
-    int pos;
-    LPVOID ret;
-    off_t offset;
-    BOOL is_shared_write = FALSE;
-
-    if (fd == -1) return wine_anon_mmap( start, size, prot, flags );
-
-    if (prot & PROT_WRITE)
-    {
-#ifdef MAP_SHARED
-        if (flags & MAP_SHARED) is_shared_write = TRUE;
-#endif
-#ifdef MAP_PRIVATE
-        if (!(flags & MAP_PRIVATE)) is_shared_write = TRUE;
-#endif
-    }
-
-    if (removable && *removable)
-    {
-        /* if on removable media, try using read instead of mmap */
-        if (!is_shared_write) goto fake_mmap;
-        *removable = FALSE;
-    }
-
-    if ((ret = unaligned_mmap( start, size, prot, flags, fd,
-                               offset_low, offset_high )) != (LPVOID)-1) return ret;
-
-    /* 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 ret;
-    if (is_shared_write) return ret;  /* we cannot fake shared write mappings */
-
- fake_mmap:
-    /* Reserve the memory with an anonymous mmap */
-    ret = wine_anon_mmap( start, size, PROT_READ | PROT_WRITE, flags );
-    if (ret == (LPVOID)-1) return ret;
-    /* Now read in the file */
-    offset = ((off_t)offset_high << 32) | offset_low;
-    if ((pos = lseek( fd, offset, SEEK_SET )) == -1)
-    {
-        munmap( ret, size );
-        return (LPVOID)-1;
-    }
-    read( fd, ret, size );
-    lseek( fd, pos, SEEK_SET );  /* Restore the file pointer */
-    mprotect( ret, size, prot );  /* Set the right protection */
-    return ret;
-}
-
 
 /***********************************************************************
  *             VirtualAlloc   (KERNEL32.@)
@@ -984,98 +64,7 @@
               DWORD type,   /* [in] Type of allocation */
               DWORD protect)/* [in] Type of access protection */
 {
-    FILE_VIEW *view;
-    char *ptr, *base;
-    BYTE vprot;
-
-    TRACE("%p %08lx %lx %08lx\n", addr, size, type, protect );
-
-    /* Round parameters to a page boundary */
-
-    if (size > 0x7fc00000)  /* 2Gb - 4Mb */
-    {
-        SetLastError( ERROR_OUTOFMEMORY );
-        return NULL;
-    }
-    if (addr)
-    {
-        if (type & MEM_RESERVE) /* Round down to 64k boundary */
-            base = ROUND_ADDR( addr, granularity_mask );
-        else
-            base = ROUND_ADDR( addr, page_mask );
-        size = (((UINT_PTR)addr + size + page_mask) & ~page_mask) - (UINT_PTR)base;
-
-        /* disallow low 64k, wrap-around and kernel space */
-        if ((base <= (char *)granularity_mask) ||
-            (base + size < base) ||
-            (base + size > (char *)ADDRESS_SPACE_LIMIT))
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return NULL;
-        }
-    }
-    else
-    {
-        base = 0;
-        size = (size + page_mask) & ~page_mask;
-    }
-
-    if (type & MEM_TOP_DOWN) {
-    	/* FIXME: MEM_TOP_DOWN allocates the largest possible address.
-	 *  	  Is there _ANY_ way to do it with UNIX mmap()?
-	 */
-    	WARN("MEM_TOP_DOWN ignored\n");
-    	type &= ~MEM_TOP_DOWN;
-    }
-    /* Compute the alloc type flags */
-
-    if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_SYSTEM)) ||
-        (type & ~(MEM_COMMIT | MEM_RESERVE | MEM_SYSTEM)))
-    {
-	ERR("called with wrong alloc type flags (%08lx) !\n", type);
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return NULL;
-    }
-    if (type & (MEM_COMMIT | MEM_SYSTEM))
-        vprot = VIRTUAL_GetProt( protect ) | VPROT_COMMITTED;
-    else vprot = 0;
-
-    /* Reserve the memory */
-
-    if ((type & MEM_RESERVE) || !base)
-    {
-        if (type & MEM_SYSTEM)
-        {
-            if (!(view = VIRTUAL_CreateView( base, size, VFLAG_VALLOC | VFLAG_SYSTEM, vprot, 0 )))
-            {
-                SetLastError( ERROR_OUTOFMEMORY );
-                return NULL;
-            }
-            return (LPVOID)base;
-        }
-        ptr = anon_mmap_aligned( base, size, VIRTUAL_GetUnixProt( vprot ), 0 );
-        if (ptr == (void *)-1) return NULL;
-
-        if (!(view = VIRTUAL_CreateView( ptr, size, VFLAG_VALLOC, vprot, 0 )))
-        {
-            munmap( ptr, size );
-            SetLastError( ERROR_OUTOFMEMORY );
-            return NULL;
-        }
-        return ptr;
-    }
-
-    /* Commit the pages */
-
-    if (!(view = VIRTUAL_FindView( base )) ||
-        (base + size > (char *)view->base + view->size))
-    {
-        SetLastError( ERROR_INVALID_ADDRESS );
-        return NULL;
-    }
-
-    if (!VIRTUAL_SetProt( view, base, size, vprot )) return NULL;
-    return (LPVOID)base;
+    return VirtualAllocEx( GetCurrentProcess(), addr, size, type, protect );
 }
 
 
@@ -1086,15 +75,20 @@
  */
 LPVOID WINAPI VirtualAllocEx(
               HANDLE hProcess, /* [in] Handle of process to do mem operation */
-              LPVOID addr,  /* [in] Address of region to reserve or commit */
-              DWORD size,   /* [in] Size of region */
-              DWORD type,   /* [in] Type of allocation */
-              DWORD protect /* [in] Type of access protection */
-) {
-    if (MapProcessHandle( hProcess ) == GetCurrentProcessId())
-        return VirtualAlloc( addr, size, type, protect );
-    ERR("Unsupported on other process\n");
-    return NULL;
+              LPVOID addr,     /* [in] Address of region to reserve or commit */
+              DWORD size,      /* [in] Size of region */
+              DWORD type,      /* [in] Type of allocation */
+              DWORD protect )  /* [in] Type of access protection */
+{
+    LPVOID ret;
+    NTSTATUS status;
+
+    if ((status = NtAllocateVirtualMemory( hProcess, &ret, addr, &size, type, protect )))
+    {
+        SetLastError( RtlNtStatusToDosError(status) );
+        ret = NULL;
+    }
+    return ret;
 }
 
 
@@ -1111,57 +105,23 @@
               DWORD size,  /* [in] Size of region */
               DWORD type   /* [in] Type of operation */
 ) {
-    FILE_VIEW *view;
-    char *base;
+    return VirtualFreeEx( GetCurrentProcess(), addr, size, type );
+}
 
-    TRACE("%p %08lx %lx\n", addr, size, type );
 
-    /* Fix the parameters */
-
-    size = ROUND_SIZE( addr, size );
-    base = ROUND_ADDR( addr, page_mask );
-
-    if (!(view = VIRTUAL_FindView( base )) ||
-        (base + size > (char *)view->base + view->size) ||
-        !(view->flags & VFLAG_VALLOC))
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return FALSE;
-    }
-
-    /* Check the type */
-
-    if (type & MEM_SYSTEM)
-    {
-        view->flags |= VFLAG_SYSTEM;
-        type &= ~MEM_SYSTEM;
-    }
-
-    if ((type != MEM_DECOMMIT) && (type != MEM_RELEASE))
-    {
-	ERR("called with wrong free type flags (%08lx) !\n", type);
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return FALSE;
-    }
-
-    /* Free the pages */
-
-    if (type == MEM_RELEASE)
-    {
-        if (size || (base != view->base))
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return FALSE;
-        }
-        VIRTUAL_DeleteView( view );
-        return TRUE;
-    }
-
-    /* Decommit the pages by remapping zero-pages instead */
-
-    if (wine_anon_mmap( (LPVOID)base, size, VIRTUAL_GetUnixProt(0), MAP_FIXED ) != (LPVOID)base)
-        ERR( "Could not remap pages, expect trouble\n" );
-    return VIRTUAL_SetProt( view, base, size, 0 );
+/***********************************************************************
+ *             VirtualFreeEx   (KERNEL32.@)
+ * Release or decommits a region of pages in virtual address space.
+ *
+ * RETURNS
+ *	TRUE: Success
+ *	FALSE: Failure
+ */
+BOOL WINAPI VirtualFreeEx( HANDLE process, LPVOID addr, DWORD size, DWORD type )
+{
+    NTSTATUS status = NtFreeVirtualMemory( process, &addr, &size, type );
+    if (status) SetLastError( RtlNtStatusToDosError(status) );
+    return !status;
 }
 
 
@@ -1176,11 +136,12 @@
  *	TRUE: Success
  *	FALSE: Failure
  */
-BOOL WINAPI VirtualLock(
-              LPVOID addr, /* [in] Address of first byte of range to lock */
-              DWORD size   /* [in] Number of bytes in range to lock */
-) {
-    return TRUE;
+BOOL WINAPI VirtualLock( LPVOID addr, /* [in] Address of first byte of range to lock */
+                         DWORD size ) /* [in] Number of bytes in range to lock */
+{
+    NTSTATUS status = NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
+    if (status) SetLastError( RtlNtStatusToDosError(status) );
+    return !status;
 }
 
 
@@ -1195,11 +156,12 @@
  *	TRUE: Success
  *	FALSE: Failure
  */
-BOOL WINAPI VirtualUnlock(
-              LPVOID addr, /* [in] Address of first byte of range */
-              DWORD size   /* [in] Number of bytes in range */
-) {
-    return TRUE;
+BOOL WINAPI VirtualUnlock( LPVOID addr, /* [in] Address of first byte of range */
+                           DWORD size ) /* [in] Number of bytes in range */
+{
+    NTSTATUS status = NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
+    if (status) SetLastError( RtlNtStatusToDosError(status) );
+    return !status;
 }
 
 
@@ -1217,42 +179,7 @@
               DWORD new_prot,  /* [in] Desired access protection */
               LPDWORD old_prot /* [out] Address of variable to get old protection */
 ) {
-    FILE_VIEW *view;
-    char *base;
-    UINT i;
-    BYTE vprot, *p;
-    DWORD prot;
-
-    TRACE("%p %08lx %08lx\n", addr, size, new_prot );
-
-    /* Fix the parameters */
-
-    size = ROUND_SIZE( addr, size );
-    base = ROUND_ADDR( addr, page_mask );
-
-    if (!(view = VIRTUAL_FindView( base )) ||
-        (base + size > (char *)view->base + view->size))
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return FALSE;
-    }
-
-    /* Make sure all the pages are committed */
-
-    p = view->prot + ((base - (char *)view->base) >> page_shift);
-    VIRTUAL_GetWin32Prot( *p, &prot, NULL );
-    for (i = size >> page_shift; i; i--, p++)
-    {
-        if (!(*p & VPROT_COMMITTED))
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return FALSE;
-        }
-    }
-
-    if (old_prot) *old_prot = prot;
-    vprot = VIRTUAL_GetProt( new_prot ) | VPROT_COMMITTED;
-    return VIRTUAL_SetProt( view, base, size, vprot );
+    return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
 }
 
 
@@ -1266,16 +193,15 @@
  *	FALSE: Failure
  */
 BOOL WINAPI VirtualProtectEx(
-              HANDLE handle, /* [in]  Handle of process */
+              HANDLE process,  /* [in]  Handle of process */
               LPVOID addr,     /* [in]  Address of region of committed pages */
               DWORD size,      /* [in]  Size of region */
               DWORD new_prot,  /* [in]  Desired access protection */
               LPDWORD old_prot /* [out] Address of variable to get old protection */ )
 {
-    if (MapProcessHandle( handle ) == GetCurrentProcessId())
-        return VirtualProtect( addr, size, new_prot, old_prot );
-    ERR("Unsupported on other process\n");
-    return FALSE;
+    NTSTATUS status = NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot );
+    if (status) SetLastError( RtlNtStatusToDosError(status) );
+    return !status;
 }
 
 
@@ -1292,65 +218,7 @@
              LPMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
              DWORD len                        /* [in]  Size of buffer */
 ) {
-    FILE_VIEW *view;
-    char *base, *alloc_base = 0;
-    UINT size = 0;
-
-    if (addr >= ADDRESS_SPACE_LIMIT) return 0;
-
-    base = ROUND_ADDR( addr, page_mask );
-
-    /* Find the view containing the address */
-
-    EnterCriticalSection(&csVirtual);
-    view = VIRTUAL_FirstView;
-    for (;;)
-    {
-        if (!view)
-        {
-            size = (char *)ADDRESS_SPACE_LIMIT - alloc_base;
-            break;
-        }
-        if ((char *)view->base > base)
-        {
-            size = (char *)view->base - alloc_base;
-            view = NULL;
-            break;
-        }
-        if ((char *)view->base + view->size > base)
-        {
-            alloc_base = view->base;
-            size = view->size;
-            break;
-        }
-        alloc_base = (char *)view->base + view->size;
-        view = view->next;
-    }
-    LeaveCriticalSection(&csVirtual);
-
-    /* Fill the info structure */
-
-    if (!view)
-    {
-        info->State             = MEM_FREE;
-        info->Protect           = 0;
-        info->AllocationProtect = 0;
-        info->Type              = 0;
-    }
-    else
-    {
-        BYTE vprot = view->prot[(base - alloc_base) >> page_shift];
-        VIRTUAL_GetWin32Prot( vprot, &info->Protect, &info->State );
-        for (size = base - alloc_base; size < view->size; size += page_mask+1)
-            if (view->prot[size >> page_shift] != vprot) break;
-        info->AllocationProtect = view->protect;
-        info->Type              = MEM_PRIVATE;  /* FIXME */
-    }
-
-    info->BaseAddress    = (LPVOID)base;
-    info->AllocationBase = (LPVOID)alloc_base;
-    info->RegionSize     = size - (base - alloc_base);
-    return sizeof(*info);
+    return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
 }
 
 
@@ -1363,15 +231,277 @@
  *	Number of bytes returned in information buffer
  */
 DWORD WINAPI VirtualQueryEx(
-             HANDLE handle,                 /* [in] Handle of process */
+             HANDLE process,                  /* [in] Handle of process */
              LPCVOID addr,                    /* [in] Address of region */
              LPMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
              DWORD len                        /* [in] Size of buffer */ )
 {
-    if (MapProcessHandle( handle ) == GetCurrentProcessId())
-        return VirtualQuery( addr, info, len );
-    ERR("Unsupported on other process\n");
-    return 0;
+    DWORD ret;
+    NTSTATUS status;
+
+    if ((status = NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
+    {
+        SetLastError( RtlNtStatusToDosError(status) );
+        ret = 0;
+    }
+    return ret;
+}
+
+
+/***********************************************************************
+ *             CreateFileMappingA   (KERNEL32.@)
+ * Creates a named or unnamed file-mapping object for the specified file
+ *
+ * RETURNS
+ *	Handle: Success
+ *	0: Mapping object does not exist
+ *	NULL: Failure
+ */
+HANDLE WINAPI CreateFileMappingA(
+                HANDLE hFile,   /* [in] Handle of file to map */
+                SECURITY_ATTRIBUTES *sa, /* [in] Optional security attributes*/
+                DWORD protect,   /* [in] Protection for mapping object */
+                DWORD size_high, /* [in] High-order 32 bits of object size */
+                DWORD size_low,  /* [in] Low-order 32 bits of object size */
+                LPCSTR name      /* [in] Name of file-mapping object */ )
+{
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return CreateFileMappingW( hFile, sa, protect, size_high, size_low, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
+    {
+        SetLastError( ERROR_FILENAME_EXCED_RANGE );
+        return 0;
+    }
+    return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
+}
+
+
+/***********************************************************************
+ *             CreateFileMappingW   (KERNEL32.@)
+ * See CreateFileMappingA
+ */
+HANDLE WINAPI CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES sa,
+                                  DWORD protect, DWORD size_high,
+                                  DWORD size_low, LPCWSTR name )
+{
+    static const int sec_flags = SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE;
+
+    HANDLE ret;
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING nameW;
+    NTSTATUS status;
+    DWORD access, sec_type;
+    LARGE_INTEGER size;
+
+    attr.Length                   = sizeof(attr);
+    attr.RootDirectory            = 0;
+    attr.ObjectName               = NULL;
+    attr.Attributes               = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0;
+    attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    if (name)
+    {
+        RtlInitUnicodeString( &nameW, name );
+        attr.ObjectName = &nameW;
+    }
+
+    sec_type = protect & sec_flags;
+    protect &= ~sec_flags;
+    if (!sec_type) sec_type = SEC_COMMIT;
+
+    switch(protect)
+    {
+    case 0:
+    case PAGE_READONLY:
+    case PAGE_WRITECOPY:
+        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
+        break;
+    case PAGE_READWRITE:
+        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE;
+        break;
+    default:
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return 0;
+    }
+
+    if (hFile == INVALID_HANDLE_VALUE)
+    {
+        hFile = 0;
+        if (!size_low && !size_high)
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return 0;
+        }
+    }
+
+    size.s.LowPart  = size_low;
+    size.s.HighPart = size_high;
+
+    status = NtCreateSection( &ret, access, &attr, &size, protect, sec_type, hFile );
+    SetLastError( RtlNtStatusToDosError(status) );
+    return ret;
+}
+
+
+/***********************************************************************
+ *             OpenFileMappingA   (KERNEL32.@)
+ * Opens a named file-mapping object.
+ *
+ * RETURNS
+ *	Handle: Success
+ *	NULL: Failure
+ */
+HANDLE WINAPI OpenFileMappingA(
+                DWORD access,   /* [in] Access mode */
+                BOOL inherit, /* [in] Inherit flag */
+                LPCSTR name )   /* [in] Name of file-mapping object */
+{
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return OpenFileMappingW( access, inherit, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
+    {
+        SetLastError( ERROR_FILENAME_EXCED_RANGE );
+        return 0;
+    }
+    return OpenFileMappingW( access, inherit, buffer );
+}
+
+
+/***********************************************************************
+ *             OpenFileMappingW   (KERNEL32.@)
+ * See OpenFileMappingA
+ */
+HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
+{
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING nameW;
+    HANDLE ret;
+    NTSTATUS status;
+
+    if (!name)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return 0;
+    }
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.ObjectName = &nameW;
+    attr.Attributes = inherit ? OBJ_INHERIT : 0;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+    RtlInitUnicodeString( &nameW, name );
+
+    if (access == FILE_MAP_COPY) access = FILE_MAP_READ;
+
+    if ((status = NtOpenSection( &ret, access, &attr )))
+    {
+        SetLastError( RtlNtStatusToDosError(status) );
+        ret = 0;
+    }
+    return ret;
+}
+
+
+/***********************************************************************
+ *             MapViewOfFile   (KERNEL32.@)
+ * Maps a view of a file into the address space
+ *
+ * RETURNS
+ *	Starting address of mapped view
+ *	NULL: Failure
+ */
+LPVOID WINAPI MapViewOfFile(
+              HANDLE mapping,  /* [in] File-mapping object to map */
+              DWORD access,      /* [in] Access mode */
+              DWORD offset_high, /* [in] High-order 32 bits of file offset */
+              DWORD offset_low,  /* [in] Low-order 32 bits of file offset */
+              DWORD count        /* [in] Number of bytes to map */
+) {
+    return MapViewOfFileEx( mapping, access, offset_high,
+                            offset_low, count, NULL );
+}
+
+
+/***********************************************************************
+ *             MapViewOfFileEx   (KERNEL32.@)
+ * Maps a view of a file into the address space
+ *
+ * RETURNS
+ *	Starting address of mapped view
+ *	NULL: Failure
+ */
+LPVOID WINAPI MapViewOfFileEx(
+              HANDLE handle,   /* [in] File-mapping object to map */
+              DWORD access,      /* [in] Access mode */
+              DWORD offset_high, /* [in] High-order 32 bits of file offset */
+              DWORD offset_low,  /* [in] Low-order 32 bits of file offset */
+              DWORD count,       /* [in] Number of bytes to map */
+              LPVOID addr        /* [in] Suggested starting address for mapped view */
+) {
+    NTSTATUS status;
+    LARGE_INTEGER offset;
+    ULONG protect;
+
+    offset.s.LowPart  = offset_low;
+    offset.s.HighPart = offset_high;
+
+    if (access & FILE_MAP_WRITE) protect = PAGE_READWRITE;
+    else if (access & FILE_MAP_READ) protect = PAGE_READONLY;
+    else if (access & FILE_MAP_COPY) protect = PAGE_WRITECOPY;
+    else protect = PAGE_NOACCESS;
+
+    if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
+                                      &count, ViewShare, 0, protect )))
+    {
+        SetLastError( RtlNtStatusToDosError(status) );
+        addr = NULL;
+    }
+    return addr;
+}
+
+
+/***********************************************************************
+ *             UnmapViewOfFile   (KERNEL32.@)
+ * Unmaps a mapped view of a file.
+ *
+ * NOTES
+ *	Should addr be an LPCVOID?
+ *
+ * RETURNS
+ *	TRUE: Success
+ *	FALSE: Failure
+ */
+BOOL WINAPI UnmapViewOfFile( LPVOID addr ) /* [in] Address where mapped view begins */
+{
+    NTSTATUS status = NtUnmapViewOfSection( GetCurrentProcess(), addr );
+    if (status) SetLastError( RtlNtStatusToDosError(status) );
+    return !status;
+}
+
+
+/***********************************************************************
+ *             FlushViewOfFile   (KERNEL32.@)
+ * Writes to the disk a byte range within a mapped view of a file
+ *
+ * RETURNS
+ *	TRUE: Success
+ *	FALSE: Failure
+ */
+BOOL WINAPI FlushViewOfFile( LPCVOID base,  /* [in] Start address of byte range to flush */
+                             DWORD size )   /* [in] Number of bytes in range */
+{
+    NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
+    if (status)
+    {
+        if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
+        else SetLastError( RtlNtStatusToDosError(status) );
+    }
+    return !status;
 }
 
 
@@ -1387,6 +517,7 @@
               UINT size )  /* [in] Size of block */
 {
     if (!size) return FALSE;  /* handle 0 size case w/o reference */
+    if (!page_size) page_size = getpagesize();
     __TRY
     {
         volatile const char *p = ptr;
@@ -1420,6 +551,7 @@
               UINT size ) /* [in] Size of block in bytes */
 {
     if (!size) return FALSE;  /* handle 0 size case w/o reference */
+    if (!page_size) page_size = getpagesize();
     __TRY
     {
         volatile char *p = ptr;
@@ -1518,350 +650,3 @@
     __ENDTRY
     return FALSE;
 }
-
-
-/***********************************************************************
- *             CreateFileMappingA   (KERNEL32.@)
- * Creates a named or unnamed file-mapping object for the specified file
- *
- * RETURNS
- *	Handle: Success
- *	0: Mapping object does not exist
- *	NULL: Failure
- */
-HANDLE WINAPI CreateFileMappingA(
-                HANDLE hFile,   /* [in] Handle of file to map */
-                SECURITY_ATTRIBUTES *sa, /* [in] Optional security attributes*/
-                DWORD protect,   /* [in] Protection for mapping object */
-                DWORD size_high, /* [in] High-order 32 bits of object size */
-                DWORD size_low,  /* [in] Low-order 32 bits of object size */
-                LPCSTR name      /* [in] Name of file-mapping object */ )
-{
-    WCHAR buffer[MAX_PATH];
-
-    if (!name) return CreateFileMappingW( hFile, sa, protect, size_high, size_low, NULL );
-
-    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
-    {
-        SetLastError( ERROR_FILENAME_EXCED_RANGE );
-        return 0;
-    }
-    return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
-}
-
-
-/***********************************************************************
- *             CreateFileMappingW   (KERNEL32.@)
- * See CreateFileMappingA
- */
-HANDLE WINAPI CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES sa,
-                                  DWORD protect, DWORD size_high,
-                                  DWORD size_low, LPCWSTR name )
-{
-    HANDLE ret;
-    BYTE vprot;
-    DWORD len = name ? strlenW(name) : 0;
-
-    /* Check parameters */
-
-    TRACE("(%x,%p,%08lx,%08lx%08lx,%s)\n",
-          hFile, sa, protect, size_high, size_low, debugstr_w(name) );
-
-    if (len > MAX_PATH)
-    {
-        SetLastError( ERROR_FILENAME_EXCED_RANGE );
-        return 0;
-    }
-
-    vprot = VIRTUAL_GetProt( protect );
-    if (protect & SEC_RESERVE)
-    {
-        if (hFile != INVALID_HANDLE_VALUE)
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return 0;
-        }
-    }
-    else vprot |= VPROT_COMMITTED;
-    if (protect & SEC_NOCACHE) vprot |= VPROT_NOCACHE;
-    if (protect & SEC_IMAGE) vprot |= VPROT_IMAGE;
-
-    /* Create the server object */
-
-    if (hFile == INVALID_HANDLE_VALUE) hFile = 0;
-    SERVER_START_REQ( create_mapping )
-    {
-        req->file_handle = hFile;
-        req->size_high   = size_high;
-        req->size_low    = size_low;
-        req->protect     = vprot;
-        req->inherit     = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        wine_server_add_data( req, name, len * sizeof(WCHAR) );
-        SetLastError(0);
-        wine_server_call_err( req );
-        ret = reply->handle;
-    }
-    SERVER_END_REQ;
-    return ret;
-}
-
-
-/***********************************************************************
- *             OpenFileMappingA   (KERNEL32.@)
- * Opens a named file-mapping object.
- *
- * RETURNS
- *	Handle: Success
- *	NULL: Failure
- */
-HANDLE WINAPI OpenFileMappingA(
-                DWORD access,   /* [in] Access mode */
-                BOOL inherit, /* [in] Inherit flag */
-                LPCSTR name )   /* [in] Name of file-mapping object */
-{
-    WCHAR buffer[MAX_PATH];
-
-    if (!name) return OpenFileMappingW( access, inherit, NULL );
-
-    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
-    {
-        SetLastError( ERROR_FILENAME_EXCED_RANGE );
-        return 0;
-    }
-    return OpenFileMappingW( access, inherit, buffer );
-}
-
-
-/***********************************************************************
- *             OpenFileMappingW   (KERNEL32.@)
- * See OpenFileMappingA
- */
-HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
-{
-    HANDLE ret;
-    DWORD len = name ? strlenW(name) : 0;
-    if (len >= MAX_PATH)
-    {
-        SetLastError( ERROR_FILENAME_EXCED_RANGE );
-        return 0;
-    }
-    SERVER_START_REQ( open_mapping )
-    {
-        req->access  = access;
-        req->inherit = inherit;
-        wine_server_add_data( req, name, len * sizeof(WCHAR) );
-        wine_server_call_err( req );
-        ret = reply->handle;
-    }
-    SERVER_END_REQ;
-    return ret;
-}
-
-
-/***********************************************************************
- *             MapViewOfFile   (KERNEL32.@)
- * Maps a view of a file into the address space
- *
- * RETURNS
- *	Starting address of mapped view
- *	NULL: Failure
- */
-LPVOID WINAPI MapViewOfFile(
-              HANDLE mapping,  /* [in] File-mapping object to map */
-              DWORD access,      /* [in] Access mode */
-              DWORD offset_high, /* [in] High-order 32 bits of file offset */
-              DWORD offset_low,  /* [in] Low-order 32 bits of file offset */
-              DWORD count        /* [in] Number of bytes to map */
-) {
-    return MapViewOfFileEx( mapping, access, offset_high,
-                            offset_low, count, NULL );
-}
-
-
-/***********************************************************************
- *             MapViewOfFileEx   (KERNEL32.@)
- * Maps a view of a file into the address space
- *
- * RETURNS
- *	Starting address of mapped view
- *	NULL: Failure
- */
-LPVOID WINAPI MapViewOfFileEx(
-              HANDLE handle,   /* [in] File-mapping object to map */
-              DWORD access,      /* [in] Access mode */
-              DWORD offset_high, /* [in] High-order 32 bits of file offset */
-              DWORD offset_low,  /* [in] Low-order 32 bits of file offset */
-              DWORD count,       /* [in] Number of bytes to map */
-              LPVOID addr        /* [in] Suggested starting address for mapped view */
-) {
-    FILE_VIEW *view;
-    UINT size = 0;
-    int flags = MAP_PRIVATE;
-    int unix_handle = -1;
-    int prot, res;
-    void *base, *ptr = (void *)-1, *ret;
-    DWORD size_low, size_high, header_size, shared_size;
-    HANDLE shared_file;
-    BOOL removable;
-
-    /* Check parameters */
-
-    if ((offset_low & granularity_mask) ||
-        (addr && ((UINT_PTR)addr & granularity_mask)))
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return NULL;
-    }
-
-    SERVER_START_REQ( get_mapping_info )
-    {
-        req->handle = handle;
-        res = wine_server_call_err( req );
-        prot        = reply->protect;
-        base        = reply->base;
-        size_low    = reply->size_low;
-        size_high   = reply->size_high;
-        header_size = reply->header_size;
-        shared_file = reply->shared_file;
-        shared_size = reply->shared_size;
-        removable   = (reply->drive_type == DRIVE_REMOVABLE ||
-                       reply->drive_type == DRIVE_CDROM);
-    }
-    SERVER_END_REQ;
-    if (res) goto error;
-
-    if ((unix_handle = FILE_GetUnixHandle( handle, 0 )) == -1) goto error;
-
-    if (prot & VPROT_IMAGE)
-        return map_image( handle, unix_handle, base, size_low, header_size,
-                          shared_file, shared_size, removable );
-
-
-    if (size_high)
-        ERR("Sizes larger than 4Gb not supported\n");
-
-    if ((offset_low >= size_low) ||
-        (count > size_low - offset_low))
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        goto error;
-    }
-    if (count) size = ROUND_SIZE( offset_low, count );
-    else size = size_low - offset_low;
-
-    switch(access)
-    {
-    case FILE_MAP_ALL_ACCESS:
-    case FILE_MAP_WRITE:
-    case FILE_MAP_WRITE | FILE_MAP_READ:
-        if (!(prot & VPROT_WRITE))
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            goto error;
-        }
-        flags = MAP_SHARED;
-        /* fall through */
-    case FILE_MAP_READ:
-    case FILE_MAP_COPY:
-    case FILE_MAP_COPY | FILE_MAP_READ:
-        if (prot & VPROT_READ) break;
-        /* fall through */
-    default:
-        SetLastError( ERROR_INVALID_PARAMETER );
-        goto error;
-    }
-
-    /* FIXME: If a mapping is created with SEC_RESERVE and a process,
-     * which has a view of this mapping commits some pages, they will
-     * appear commited in all other processes, which have the same
-     * view created. Since we don`t support this yet, we create the
-     * whole mapping commited.
-     */
-    prot |= VPROT_COMMITTED;
-
-    /* Reserve a properly aligned area */
-
-    if ((ptr = anon_mmap_aligned( addr, size, PROT_NONE, 0 )) == (void *)-1) goto error;
-
-    /* Map the file */
-
-    TRACE("handle=%x size=%x offset=%lx\n", handle, size, offset_low );
-
-    ret = VIRTUAL_mmap( unix_handle, ptr, size, offset_low, offset_high,
-                        VIRTUAL_GetUnixProt( prot ), flags | MAP_FIXED, &removable );
-    if (ret != ptr)
-    {
-        ERR( "VIRTUAL_mmap %p %x %lx%08lx failed\n", ptr, size, offset_high, offset_low );
-        goto error;
-    }
-    if (removable) handle = 0;  /* don't keep handle open on removable media */
-
-    if (!(view = VIRTUAL_CreateView( ptr, size, 0, prot, handle )))
-    {
-        SetLastError( ERROR_OUTOFMEMORY );
-        goto error;
-    }
-    if (unix_handle != -1) close( unix_handle );
-    return ptr;
-
-error:
-    if (unix_handle != -1) close( unix_handle );
-    if (ptr != (void *)-1) munmap( ptr, size );
-    return NULL;
-}
-
-
-/***********************************************************************
- *             FlushViewOfFile   (KERNEL32.@)
- * Writes to the disk a byte range within a mapped view of a file
- *
- * RETURNS
- *	TRUE: Success
- *	FALSE: Failure
- */
-BOOL WINAPI FlushViewOfFile(
-              LPCVOID base, /* [in] Start address of byte range to flush */
-              DWORD cbFlush /* [in] Number of bytes in range */
-) {
-    FILE_VIEW *view;
-    void *addr = ROUND_ADDR( base, page_mask );
-
-    TRACE("FlushViewOfFile at %p for %ld bytes\n",
-                     base, cbFlush );
-
-    if (!(view = VIRTUAL_FindView( addr )))
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return FALSE;
-    }
-    if (!cbFlush) cbFlush = view->size;
-    if (!msync( addr, cbFlush, MS_SYNC )) return TRUE;
-    SetLastError( ERROR_INVALID_PARAMETER );
-    return FALSE;
-}
-
-
-/***********************************************************************
- *             UnmapViewOfFile   (KERNEL32.@)
- * Unmaps a mapped view of a file.
- *
- * NOTES
- *	Should addr be an LPCVOID?
- *
- * RETURNS
- *	TRUE: Success
- *	FALSE: Failure
- */
-BOOL WINAPI UnmapViewOfFile(
-              LPVOID addr /* [in] Address where mapped view begins */
-) {
-    FILE_VIEW *view;
-    void *base = ROUND_ADDR( addr, page_mask );
-    if (!(view = VIRTUAL_FindView( base )) || (base != view->base))
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return FALSE;
-    }
-    VIRTUAL_DeleteView( view );
-    return TRUE;
-}
diff --git a/server/mapping.c b/server/mapping.c
index 0c7e4d9..d9e79c6 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -375,9 +375,7 @@
                                req->protect, req->file_handle,
                                get_req_data(), get_req_data_size() )))
     {
-        int access = FILE_MAP_ALL_ACCESS;
-        if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
-        reply->handle = alloc_handle( current->process, obj, access, req->inherit );
+        reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
         release_object( obj );
     }
 }
diff --git a/server/protocol.def b/server/protocol.def
index 9d4f8f3..fd526e6 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1043,6 +1043,7 @@
     int          size_high;     /* mapping size */
     int          size_low;      /* mapping size */
     int          protect;       /* protection flags (see below) */
+    unsigned int access;        /* wanted access rights */
     int          inherit;       /* inherit flag */
     obj_handle_t file_handle;   /* file handle */
     VARARG(name,unicode_str);   /* object name */
diff --git a/server/trace.c b/server/trace.c
index c96863d..864e146 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1213,6 +1213,7 @@
     fprintf( stderr, " size_high=%d,", req->size_high );
     fprintf( stderr, " size_low=%d,", req->size_low );
     fprintf( stderr, " protect=%d,", req->protect );
+    fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " file_handle=%d,", req->file_handle );
     fprintf( stderr, " name=" );