An updated attempt at the mmap override patch that I previously sent. This 
version properly uses a signed type for the mmap wrapper (as off_t/off64_t are 
signed types), fixes a few things with the munmap wrapper relating to 
truncated and sliced file_views, and implements a mremap wrapper for Linux.

There's some debugging stuff left in the mremap wrapper since I have yet to 
catch anything that uses it, particularly using ERR instead of TRACE and an 
explicit abort() call so it isn't missed. There's also a %lld formatter in the 
mmap wrapper that will be fixed later.

I'd be interested to hear how well it does or doesn't work, as well as any 
comments or critiques on the code.
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 62a9b0e..959af57 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -71,6 +71,7 @@ extern HANDLE thread_init(void);
 extern void actctx_init(void);
 extern void virtual_init(void);
 extern void virtual_init_threading(void);
+extern void virtual_init_mmap(void);
 extern void fill_cpu_info(void);
 extern void heap_set_debug_flags( HANDLE handle );
 
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 56eca23..5bdbb4a 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -297,6 +297,7 @@ HANDLE thread_init(void)
 
     fill_cpu_info();
 
+    virtual_init_mmap();
     return exe_file;
 }
 
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 0913b71..9319d9f 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -159,6 +159,13 @@ static void *preload_reserve_end;
 static int use_locks;
 static int force_exec_prot;  /* whether to force PROT_EXEC on all PROT_READ mmaps */
 
+static void *virtual_mmap_wrapper( void *addr, size_t size, int prot, int flags, int fd, LONGLONG offset );
+static int virtual_munmap_wrapper( void *addr, size_t size );
+static void *virtual_mremap_wrapper( void *addr, size_t old_len, size_t new_len, int flags, ... );
+static void *(*sys_mmap)( void *addr, size_t size, int prot, int flags, int fd, LONGLONG offset );
+static int (*sys_munmap)( void *addr, size_t size );
+static void *(*sys_mremap)( void *addr, size_t old_len, size_t new_len, int flags, ... );
+
 
 /***********************************************************************
  *           VIRTUAL_GetProtStr
@@ -370,7 +377,7 @@ static void add_reserved_area( void *addr, size_t size )
     {
         /* unmap the part of the area that is below the limit */
         assert( (char *)addr + size > (char *)user_space_limit );
-        munmap( addr, (char *)user_space_limit - (char *)addr );
+        sys_munmap( addr, (char *)user_space_limit - (char *)addr );
         size -= (char *)user_space_limit - (char *)addr;
         addr = user_space_limit;
     }
@@ -398,11 +405,11 @@ static void remove_reserved_area( void *addr, size_t size )
     {
         if ((char *)view->base >= (char *)addr + size)
         {
-            munmap( addr, size );
+            sys_munmap( addr, size );
             break;
         }
         if ((char *)view->base + view->size <= (char *)addr) continue;
-        if (view->base > addr) munmap( addr, (char *)view->base - (char *)addr );
+        if (view->base > addr) sys_munmap( addr, (char *)view->base - (char *)addr );
         if ((char *)view->base + view->size > (char *)addr + size) break;
         size = (char *)addr + size - ((char *)view->base + view->size);
         addr = (char *)view->base + view->size;
@@ -427,14 +434,18 @@ static inline int is_beyond_limit( const void *addr, size_t size, const void *li
  * Unmap an area, or simply replace it by an empty mapping if it is
  * in a reserved area. The csVirtual section must be held by caller.
  */
-static inline void unmap_area( void *addr, size_t size )
+static inline int unmap_area( void *addr, size_t size )
 {
+    int ret = 0;
+
     if (wine_mmap_is_in_reserved_area( addr, size ))
         wine_anon_mmap( addr, size, PROT_NONE, MAP_NORESERVE | MAP_FIXED );
     else if (is_beyond_limit( addr, size, user_space_limit ))
         add_reserved_area( addr, size );
     else
-        munmap( addr, size );
+        ret = sys_munmap( addr, size );
+
+    return ret;
 }
 
 
@@ -704,12 +715,12 @@ static inline void *unmap_extra_space( void *ptr, size_t total_size, size_t want
     if ((ULONG_PTR)ptr & mask)
     {
         size_t extra = mask + 1 - ((ULONG_PTR)ptr & mask);
-        munmap( ptr, extra );
+        sys_munmap( ptr, extra );
         ptr = (char *)ptr + extra;
         total_size -= extra;
     }
     if (total_size > wanted_size)
-        munmap( (char *)ptr + wanted_size, total_size - wanted_size );
+        sys_munmap( (char *)ptr + wanted_size, total_size - wanted_size );
     return ptr;
 }
 
@@ -795,7 +806,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
             {
                 /* We couldn't get the address we wanted */
                 if (is_beyond_limit( ptr, size, user_space_limit )) add_reserved_area( ptr, size );
-                else munmap( ptr, size );
+                else sys_munmap( ptr, size );
                 return STATUS_CONFLICTING_ADDRESSES;
             }
             break;
@@ -850,6 +861,281 @@ done:
 
 
 /***********************************************************************
+ *           virtual_mmap_wrapper
+ */
+static void *virtual_mmap_wrapper( void *addr, size_t size, int prot, int flags, int fd, LONGLONG offset )
+{
+    void *ptr = (void *)-1;
+    struct alloc_area alloc;
+    sigset_t sigset;
+
+    TRACE("%p, %lu, 0x%x, 0x%x, %d, %lld\n", addr, (ULONG_PTR)size, prot, flags, fd, offset);
+
+    if (!virtual_heap || (flags & MAP_FIXED))
+        return sys_mmap( addr, size, prot, flags, fd, offset );
+
+    size = ROUND_SIZE( addr, size );
+
+    server_enter_uninterrupted_section( &csVirtual, &sigset );
+
+    /* Try address first, if requested */
+    if (addr != NULL)
+    {
+        addr = ROUND_ADDR( addr, page_mask );
+        switch (wine_mmap_is_in_reserved_area( addr, size ))
+        {
+        case -1: /* partially in a reserved area */
+            break;
+        case 0:  /* not in a reserved area, do a normal allocation */
+            ptr = sys_mmap( addr, size, prot, flags, fd, offset );
+            if (ptr == (void *)-1 && errno == ENOMEM) break;
+            goto done;
+        default:
+        case 1:  /* in a reserved area, make sure the address is available */
+            if (!find_view_range( addr, size ))
+            {
+                /* replace the reserved area by our mapping */
+                ptr = sys_mmap( addr, size, prot, flags | MAP_FIXED, fd, offset );
+                goto done;
+            }
+            break;
+        }
+    }
+
+    alloc.size = size;
+    alloc.mask = page_mask;
+    alloc.top_down = 1;
+    alloc.limit = address_space_limit;
+    if (wine_mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, 1 ))
+        ptr = sys_mmap( alloc.result, size, prot, flags | MAP_FIXED, fd, offset );
+    else
+        ptr = sys_mmap( NULL, size, prot, flags, fd, offset );
+
+done:
+    if (ptr != (void *)-1)
+    {
+        struct file_view *view;
+        WORD vprot = VPROT_COMMITTED | VPROT_SYSTEM | VPROT_NOEXEC;
+
+        if (prot != PROT_NONE)
+        {
+            if (prot & PROT_READ) vprot |= VPROT_READ;
+            if (prot & PROT_WRITE) vprot |= VPROT_WRITE;
+            if (prot & PROT_EXEC) vprot |= VPROT_EXEC;
+        }
+        if (!create_view( &view, ptr, size, vprot ))
+            TRACE( "returning %p-%p\n", ptr, (char *)ptr + size );
+        else
+        {
+            unmap_area( ptr, size );
+            WARN( "Failed to create view for %p, %lu, 0x%04x\n",
+                  ptr, (ULONG_PTR)size, vprot );
+            ptr = (void *)-1;
+            errno = ENOMEM;
+        }
+    }
+    server_leave_uninterrupted_section( &csVirtual, &sigset );
+    return ptr;
+}
+
+
+/***********************************************************************
+ *           virtual_munmap_wrapper
+ */
+static int virtual_munmap_wrapper( void *addr, size_t size )
+{
+    struct file_view *view, *next, *new_view;
+    sigset_t sigset;
+    size_t new_size;
+    char *end;
+    int ret;
+
+    size = ROUND_SIZE( addr, size );
+    addr = ROUND_ADDR( addr, page_mask );
+    end = (char *)addr + size;
+
+    TRACE( "%p-%p (%lu)\n", addr, end, (ULONG_PTR)size );
+    server_enter_uninterrupted_section( &csVirtual, &sigset );
+
+    ret = unmap_area( addr, size );
+    if (ret != 0)
+        goto done;
+
+    LIST_FOR_EACH_ENTRY_SAFE( view, next, &views_list, struct file_view, entry )
+    {
+        if ((char *)view->base >= end) break;
+        if ((char *)view->base + view->size <= (char *)addr) continue;
+
+        if (!(view->protect & VPROT_SYSTEM))
+            FIXME( "unmapping range %p-%p but view %p-%p is not system\n",
+                  addr, (char *)addr + size, view->base, (char *)view->base + size );
+
+        if ((char *)view->base >= (char *)addr)
+        {
+            if ((char *)view->base + view->size <= end)
+            {
+                /* view is entirely within the unmapped space, remove it */
+                TRACE( "deleting view %p-%p\n",
+                       view->base, (char *)view->base + view->size );
+                delete_view( view );
+                continue;
+            }
+            /* move the base to contain the remaining part of the view */
+            TRACE( "rebasing view %p-%p to %p\n",
+                   view->base, (char *)view->base + view->size, end );
+            view->size -= (char *)end - (char *)view->base;
+            memmove( &view->prot[0],
+                     &view->prot[((char *)end - (char *)view->base) >> page_shift],
+                     view->size >> page_shift );
+            view->base = end;
+            break;
+        }
+        if ((char *)view->base + view->size <= end)
+        {
+            /* truncate the view */
+            TRACE( "truncating view %p-%p to %p\n",
+                   view->base, (char *)view->base + view->size, addr );
+            view->size = (char *)addr - (char *)view->base;
+            continue;
+        }
+
+        /* Slice the view by truncating the existing one and creating a new tail */
+        TRACE( "slicing view %p-%p between %p-%p\n",
+               view->base, (char *)view->base + view->size, addr, end );
+
+        new_size = (char *)view->base + view->size - end;
+        view->size = (char *)addr - (char *)view->base;
+
+        /* Temporarily force VPROT_NOEXEC to avoid a potential mprotect call */
+        if (!create_view( &new_view, end, new_size, view->protect|VPROT_NOEXEC ))
+        {
+            memcpy( &new_view->prot[0],
+                    &view->prot[(end - (char *)view->base) >> page_shift],
+                    new_size >> page_shift );
+            if (!(view->protect & VPROT_NOEXEC))
+                new_view->protect &= ~VPROT_NOEXEC;
+        }
+        break;
+    }
+
+done:
+    server_leave_uninterrupted_section( &csVirtual, &sigset );
+    return ret;
+}
+
+static void *virtual_mremap_wrapper( void *addr, size_t old_len, size_t new_len, int flags, ...)
+{
+    struct file_view *view;
+    void *ptr = (void *)-1;
+    sigset_t sigset;
+    char *old_end;
+
+    ERR( "%p, %lu, %lu, 0x%x, ...\n", addr, (ULONG_PTR)old_len, (ULONG_PTR)new_len, flags );
+
+    if ((flags & MREMAP_FIXED))
+    {
+        va_list args;
+
+        va_start( args, flags );
+        ptr = va_arg( args, void* );
+        va_end( args );
+
+        if ((ptr=sys_mremap( addr, old_len, new_len, flags, ptr )) != (void *)-1)
+            virtual_munmap_wrapper( addr, old_len );
+        return ptr;
+    }
+
+    if ((flags & ~MREMAP_MAYMOVE) != 0)
+    {
+        errno = EINVAL;
+        return (void *)-1;
+    }
+
+    old_len = ROUND_SIZE( addr, old_len );
+    new_len = ROUND_SIZE( addr, new_len );
+    addr    = ROUND_ADDR( addr, page_mask );
+    old_end = (char *)addr + old_len;
+
+    /* If the new mapping is smaller than the old, just unmap the end */
+    if (new_len <= old_len)
+    {
+        if (new_len < old_len)
+        {
+            /* Shouldn't error... */
+            if (virtual_munmap_wrapper( (char *)addr + new_len, old_len - new_len ) != 0)
+                return (void *)-1;
+        }
+        return addr;
+    }
+
+    server_enter_uninterrupted_section( &csVirtual, &sigset );
+
+    /* Make sure the new area does not wrap */
+    if ((char *)addr + new_len < (char *)addr)
+    {
+        /* Try to extend the view */
+        switch (wine_mmap_is_in_reserved_area( addr, new_len ))
+        {
+        case -1: /* partially in a reserved area */
+            break;
+        case 0:  /* not in a reserved area, do a normal remap */
+            ptr = sys_mremap( addr, old_len, new_len, 0 );
+            break;
+        default:
+        case 1:  /* in a reserved area, make sure the address is available */
+            if (!find_view_range( old_end, new_len-old_len ))
+                ptr = sys_mremap( addr, old_len, new_len, 0 );
+            break;
+        }
+    }
+
+    if (ptr != (void *)-1)
+    {
+        /* FIXME: What protections to give the new mappings? */
+        WORD vprot = VPROT_COMMITTED | VPROT_SYSTEM | VPROT_NOEXEC;
+        create_view( &view, old_end, new_len-old_len, vprot );
+    }
+    else if ((flags & MREMAP_MAYMOVE))
+    {
+        struct alloc_area alloc;
+
+        /* Couldn't modify existing view; find a new area */
+        alloc.size = new_len;
+        alloc.mask = page_mask;
+        alloc.top_down = 1;
+        alloc.limit = address_space_limit;
+        if (!wine_mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, 1 ))
+        {
+            errno = ENOMEM;
+            goto done;
+        }
+
+        ptr = sys_mremap( addr, old_len, new_len, MREMAP_MAYMOVE|MREMAP_FIXED, alloc.result );
+        if (ptr != (void *)-1)
+        {
+            /* FIXME: What protections to give the new mappings? */
+            WORD vprot = VPROT_COMMITTED | VPROT_SYSTEM | VPROT_NOEXEC;
+            create_view( &view, ptr, new_len, vprot );
+
+            virtual_munmap_wrapper( addr, old_len );
+        }
+        else
+        {
+            WARN( "Failed to remap %p-%p to %p-%p\n",
+                   addr, (char *)addr + old_len,
+                   alloc.result, (char *)alloc.result + new_len );
+        }
+    }
+
+done:
+    server_leave_uninterrupted_section( &csVirtual, &sigset );
+    ERR( "return %p;\n", ptr );
+    abort();
+    return ptr;
+}
+
+
+/***********************************************************************
  *           map_file_into_view
  *
  * Wrapper for mmap() to map a file into a view, falling back to read if mmap fails.
@@ -877,7 +1163,7 @@ static NTSTATUS map_file_into_view( struct file_view *view, int fd, size_t start
     {
         int flags = MAP_FIXED | (shared_write ? MAP_SHARED : MAP_PRIVATE);
 
-        if (mmap( (char *)view->base + start, size, prot, flags, fd, offset ) != (void *)-1)
+        if (sys_mmap( (char *)view->base + start, size, prot, flags, fd, offset ) != (void *)-1)
             goto done;
 
         if ((errno == EPERM) && (prot & PROT_EXEC))
@@ -994,7 +1280,7 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot
         addr = wine_anon_mmap( low_64k, dosmem_size - 0x10000, unix_prot, 0 );
         if (addr != low_64k)
         {
-            if (addr != (void *)-1) munmap( addr, dosmem_size - 0x10000 );
+            if (addr != (void *)-1) sys_munmap( addr, dosmem_size - 0x10000 );
             return map_view( view, NULL, dosmem_size, 0xffff, 0, vprot );
         }
     }
@@ -1015,7 +1301,7 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot
         }
         else
         {
-            if (addr != (void *)-1) munmap( addr, 0x10000 - page_size );
+            if (addr != (void *)-1) sys_munmap( addr, 0x10000 - page_size );
             addr = low_64k;
             TRACE( "failed to map low 64K range\n" );
         }
@@ -1415,6 +1701,15 @@ void virtual_init(void)
         }
     }
 
+    assert(wine_mmap != NULL && wine_mmap != virtual_mmap_wrapper);
+    assert(wine_munmap != NULL && wine_munmap != virtual_munmap_wrapper);
+#ifdef __linux__
+    assert(wine_mremap != NULL && wine_mremap != virtual_mremap_wrapper);
+#endif
+    sys_mmap = wine_mmap;
+    sys_munmap = wine_munmap;
+    sys_mremap = wine_mremap;
+
     /* try to find space in a reserved area for the virtual heap */
     if (!wine_mmap_enum_reserved_areas( alloc_virtual_heap, &heap_base, 1 ))
         heap_base = wine_anon_mmap( NULL, VIRTUAL_HEAP_SIZE, PROT_READ|PROT_WRITE, 0 );
@@ -1441,6 +1736,17 @@ void virtual_init_threading(void)
 
 
 /***********************************************************************
+ *           virtual_init_mmap
+ */
+void virtual_init_mmap(void)
+{
+    wine_mmap = virtual_mmap_wrapper;
+    wine_munmap = virtual_munmap_wrapper;
+    wine_mremap = virtual_mremap_wrapper;
+}
+
+
+/***********************************************************************
  *           virtual_get_system_info
  */
 void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info )
diff --git a/include/wine/library.h b/include/wine/library.h
index 242bb69..b0d5903 100644
--- a/include/wine/library.h
+++ b/include/wine/library.h
@@ -75,6 +75,9 @@ extern int wine_call_on_stack( int (*func)(void *), void *arg, void *stack );
 
 /* memory mappings */
 
+extern void *(*wine_mmap)( void *addr, size_t size, int prot, int flags, int fd, LONGLONG offset );
+extern int (*wine_munmap)( void *addr, size_t size );
+extern void *(*wine_mremap)( void *addr, size_t old_len, size_t new_len, int flags, ... );
 extern void *wine_anon_mmap( void *start, size_t size, int prot, int flags );
 extern void wine_mmap_add_reserved_area( void *addr, size_t size );
 extern void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap );
diff --git a/libs/wine/mmap.c b/libs/wine/mmap.c
index 0e02d16..a22f40e 100644
--- a/libs/wine/mmap.c
+++ b/libs/wine/mmap.c
@@ -43,6 +43,10 @@
 
 #ifdef HAVE_MMAP
 
+void *(*wine_mmap)( void *addr, size_t size, int prot, int flags, int fd, LONGLONG offset );
+int (*wine_munmap)( void *addr, size_t size );
+void *(*wine_mremap)( void *addr, size_t old_len, size_t new_len, int flags, ... );
+
 struct reserved_area
 {
     struct list entry;
@@ -140,12 +144,12 @@ static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
 
         /* Perform the mapping with MAP_FIXED set.  This is safe
            now, as none of the pages is currently in use. */
-        result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
+        result = wine_mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
         if ( result == addr )
             _exit(0);
 
         if ( result != (void *) -1 ) /* This should never happen ... */
-            munmap( result, len );
+            wine_munmap( result, len );
 
        _exit(1);
     }
@@ -174,7 +178,7 @@ static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
 
     if (!vm_allocate(mach_task_self(),&result,len,0))
     {
-        if (mmap( (void *)result, len, prot, flags | MAP_FIXED, fildes, off ) != MAP_FAILED)
+        if (wine_mmap( (void *)result, len, prot, flags | MAP_FIXED, fildes, off ) != MAP_FAILED)
             return 1;
         vm_deallocate(mach_task_self(),result,len);
     }
@@ -213,7 +217,7 @@ void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
             return start;
 #endif
     }
-    return mmap( start, size, prot, flags, get_fdzero(), 0 );
+    return wine_mmap( start, size, prot, flags, get_fdzero(), 0 );
 }
 
 
@@ -232,8 +236,8 @@ static inline int mmap_reserve( void *addr, size_t size )
 #elif defined(__APPLE__)
     return try_mmap_fixed( addr, size, PROT_NONE, flags, get_fdzero(), 0 );
 #endif
-    ptr = mmap( addr, size, PROT_NONE, flags, get_fdzero(), 0 );
-    if (ptr != addr && ptr != (void *)-1)  munmap( ptr, size );
+    ptr = wine_mmap( addr, size, PROT_NONE, flags, get_fdzero(), 0 );
+    if (ptr != addr && ptr != (void *)-1) wine_munmap( ptr, size );
     return (ptr == addr);
 }
 
@@ -259,8 +263,9 @@ static inline void reserve_area( void *addr, void *end )
             if (mincore( (caddr_t)addr + i, pagesize, &vec ) != -1) break;
 
         i &= ~granularity_mask;
-        if (i && mmap( addr, i, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
-                       get_fdzero(), 0 ) != (void *)-1)
+        if (i && wine_mmap( addr, i, PROT_NONE,
+                            MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+                            get_fdzero(), 0 ) != (void *)-1)
             wine_mmap_add_reserved_area( addr, i );
 
         i += granularity_mask + 1;
@@ -324,7 +329,7 @@ static inline void reserve_dos_area(void)
     ptr = wine_anon_mmap( (void *)page_size, dos_area_size - page_size, PROT_NONE, MAP_NORESERVE );
     if (ptr != (void *)page_size)
     {
-        if (ptr != (void *)-1) munmap( ptr, dos_area_size - page_size );
+        if (ptr != (void *)-1) wine_munmap( ptr, dos_area_size - page_size );
         return;
     }
     /* now add first page with MAP_FIXED */
@@ -493,7 +498,7 @@ void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap )
                 if ((char *)area->base + area->size > (char *)addr + size)
                 {
                     /* range overlaps beginning of area only -> shrink area */
-                    if (unmap) munmap( area->base, (char *)addr + size - (char *)area->base );
+                    if (unmap) wine_munmap( area->base, (char *)addr + size - (char *)area->base );
                     area->size -= (char *)addr + size - (char *)area->base;
                     area->base = (char *)addr + size;
                     break;
@@ -502,7 +507,7 @@ void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap )
                 {
                     /* range contains the whole area -> remove area completely */
                     ptr = list_next( &reserved_areas, ptr );
-                    if (unmap) munmap( area->base, area->size );
+                    if (unmap) wine_munmap( area->base, area->size );
                     list_remove( &area->entry );
                     free( area );
                     continue;
@@ -522,13 +527,13 @@ void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap )
                     }
                     else size = (char *)area->base + area->size - (char *)addr;
                     area->size = (char *)addr - (char *)area->base;
-                    if (unmap) munmap( addr, size );
+                    if (unmap) wine_munmap( addr, size );
                     break;
                 }
                 else
                 {
                     /* range overlaps end of area only -> shrink area */
-                    if (unmap) munmap( addr, (char *)area->base + area->size - (char *)addr );
+                    if (unmap) wine_munmap( addr, (char *)area->base + area->size - (char *)addr );
                     area->size = (char *)addr - (char *)area->base;
                 }
             }
diff --git a/libs/wine/wine.map b/libs/wine/wine.map
index 2159fac..73e2ca1 100644
--- a/libs/wine/wine.map
+++ b/libs/wine/wine.map
@@ -105,10 +105,13 @@ WINE_1.0
     wine_ldt_is_system;
     wine_ldt_realloc_entries;
     wine_ldt_set_entry;
+    wine_mmap;
     wine_mmap_add_reserved_area;
     wine_mmap_enum_reserved_areas;
     wine_mmap_is_in_reserved_area;
     wine_mmap_remove_reserved_area;
+    wine_mremap;
+    wine_munmap;
     wine_pthread_get_functions;
     wine_pthread_set_functions;
     wine_set_fs;
diff --git a/loader/main.c b/loader/main.c
index 8434d81..88f0adc 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -24,9 +24,6 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#ifdef HAVE_SYS_MMAN_H
-# include <sys/mman.h>
-#endif
 #ifdef HAVE_SYS_RESOURCE_H
 # include <sys/resource.h>
 #endif
@@ -139,7 +136,7 @@ static void check_vmsplit( void *stack )
     if (stack < (void *)0x80000000)
     {
         /* if the stack is below 0x80000000, assume we can safely try a munmap there */
-        if (munmap( (void *)0x80000000, 1 ) == -1 && errno == EINVAL)
+        if (wine_munmap( (void *)0x80000000, 1 ) == -1 && errno == EINVAL)
             fprintf( stderr,
                      "Warning: memory above 0x80000000 doesn't seem to be accessible.\n"
                      "Wine requires a 3G/1G user/kernel memory split to work properly.\n" );
@@ -196,6 +193,88 @@ static int pre_exec(void)
 #endif
 
 
+/***********************************************************************
+ * overrides for mmap, mmap64, munmap
+ */
+/* Because off_t can change size depending on _FILE_OFFSET_BITS=64 being set,
+ * we can't rely on it here. In most cases, the default off_t type follows the
+ * same pattern as long (4 bytes on 32-bit, 8 on 64).
+ * On FreeBSD, however, off_t is always a 64-bit type.
+ */
+#if defined(__FreeBSD__)
+typedef off_t offset_t;
+#else
+typedef long offset_t;
+#endif
+
+void *mmap( void *addr, size_t size, int prot, int flags, int fd, offset_t offset )
+{
+    return wine_mmap( addr, size, prot, flags, fd, offset );
+}
+
+void *mmap64( void *addr, size_t size, int prot, int flags, int fd, off64_t offset )
+{
+    return wine_mmap( addr, size, prot, flags, fd, offset );
+}
+
+int munmap( void *addr, size_t size )
+{
+    return wine_munmap( addr, size );
+}
+
+#ifdef __linux__
+/* Linux also has a mremap function, which allows changing the size and address
+ * of a particular mapping */
+void *mremap( void *addr, size_t old_len, size_t new_len, int flags, ... )
+{
+    if((flags & 2)) /* MREMAP_FIXED */
+    {
+        void *extra;
+        va_list args;
+
+        va_start(args, flags);
+        extra = va_arg(args, void*);
+        va_end(args);
+
+        return wine_mremap(addr, old_len, new_len, flags, extra);
+    }
+    return wine_mremap(addr, old_len, new_len, flags);
+}
+#endif
+
+/**********************************************************************
+ *           init_mmap_functions
+ */
+static void init_mmap_functions(void)
+{
+    if (sizeof(offset_t) == sizeof(LONGLONG))
+        wine_mmap = wine_dlsym( RTLD_NEXT, "mmap", NULL, 0 );
+    else
+        wine_mmap = wine_dlsym( RTLD_NEXT, "mmap64", NULL, 0 );
+    wine_munmap = wine_dlsym( RTLD_NEXT, "munmap", NULL, 0 );
+
+    if (wine_mmap == NULL)
+    {
+        fprintf( stderr, "Could not find mmap function\n" );
+        exit(1);
+    }
+    if (wine_munmap == NULL)
+    {
+        fprintf( stderr, "Could not find munmap function\n" );
+        exit(1);
+    }
+
+#ifdef __linux__
+    wine_mremap = wine_dlsym( RTLD_NEXT, "mremap", NULL, 0 );
+    if (wine_mremap == NULL)
+    {
+        fprintf( stderr, "Could not find mremap function\n" );
+        exit(1);
+    }
+#endif
+}
+
+
 /**********************************************************************
  *           main
  */
@@ -204,6 +283,8 @@ int main( int argc, char *argv[] )
     char error[1024];
     int i;
 
+    init_mmap_functions();
+
     if (!getenv( "WINELOADERNOEXEC" ))  /* first time around */
     {
         static char noexec[] = "WINELOADERNOEXEC=1";


Reply via email to