MemoryMappedFile support on Windows
[mono.git] / mcs / class / System.Core / System.IO.MemoryMappedFiles / MemoryMappedFile.cs
index 20973c00c6549f335cc00dce8069ff044925efc7..7a3cce164f61e2feffc9b46fcd751d1c75626e91 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_4_0
-
 using System;
 using System.IO;
 using System.Collections.Generic;
 using Microsoft.Win32.SafeHandles;
 using System.Runtime.InteropServices;
 using System;
 using System.IO;
 using System.Collections.Generic;
 using Microsoft.Win32.SafeHandles;
 using System.Runtime.InteropServices;
-
-
-#if !MOBILE
-using Mono.Unix.Native;
-using Mono.Unix;
-#else
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
-#endif
+
 
 namespace System.IO.MemoryMappedFiles
 {
 
 namespace System.IO.MemoryMappedFiles
 {
-#if !MOBILE
        internal static class MemoryMapImpl {
        internal static class MemoryMapImpl {
-               //
-               // Turns the FileMode into the first half of open(2) flags
-               //
-               static OpenFlags ToUnixMode (FileMode mode)
-               {
-                       switch (mode){
-                       case FileMode.CreateNew:
-                               return OpenFlags.O_CREAT | OpenFlags.O_EXCL;
-                               
-                       case FileMode.Create:
-                               return OpenFlags.O_CREAT | OpenFlags.O_TRUNC;
-                               
-                       case FileMode.OpenOrCreate:
-                               return OpenFlags.O_CREAT;
-                               
-                       case FileMode.Truncate:
-                               return OpenFlags.O_TRUNC;
-                               
-                       case FileMode.Append:
-                               return OpenFlags.O_APPEND;
-                       default:
-                       case FileMode.Open:
-                               return 0;
-                       }
-               }
-
-               //
-               // Turns the MemoryMappedFileAccess into the second half of open(2) flags
-               //
-               static OpenFlags ToUnixMode (MemoryMappedFileAccess access)
-               {
-                       switch (access){
-                       case MemoryMappedFileAccess.CopyOnWrite:
-                       case MemoryMappedFileAccess.ReadWriteExecute:
-                       case MemoryMappedFileAccess.ReadWrite:
-                               return OpenFlags.O_RDWR;
-                               
-                       case MemoryMappedFileAccess.Write:
-                               return OpenFlags.O_WRONLY;
-
-                       case MemoryMappedFileAccess.ReadExecute:
-                       case MemoryMappedFileAccess.Read:
-                       default:
-                               return OpenFlags.O_RDONLY;
-                       }
-               }
-
-               static MmapProts ToUnixProts (MemoryMappedFileAccess access)
-               {
-                       switch (access){
-                       case MemoryMappedFileAccess.ReadWrite:
-                               return MmapProts.PROT_WRITE | MmapProts.PROT_READ;
-                               
-                       case MemoryMappedFileAccess.Write:
-                               return MmapProts.PROT_WRITE;
-                               
-                       case MemoryMappedFileAccess.CopyOnWrite:
-                               return MmapProts.PROT_WRITE | MmapProts.PROT_READ;
-                               
-                       case MemoryMappedFileAccess.ReadExecute:
-                               return MmapProts.PROT_EXEC;
-                               
-                       case MemoryMappedFileAccess.ReadWriteExecute:
-                               return MmapProts.PROT_WRITE | MmapProts.PROT_READ | MmapProts.PROT_EXEC;
-                               
-                       case MemoryMappedFileAccess.Read:
-                       default:
-                               return MmapProts.PROT_READ;
-                       }
-               }
-
-               internal static int Open (string path, FileMode mode, ref long capacity, MemoryMappedFileAccess access)
-               {
-                       if (MonoUtil.IsUnix){
-                               Stat buf;
-                               if (Syscall.stat (path, out buf) == -1)
-                                       UnixMarshal.ThrowExceptionForLastError ();
-
-                               if (capacity == 0) {
-                                       // Special files such as FIFOs, sockets, and devices can
-                                       // have a size of 0. Specifying a capacity for these
-                                       // also makes little sense, so don't do the check if the
-                                       // file is one of these.
-                                       if (buf.st_size == 0 &&
-                                               (buf.st_mode & (FilePermissions.S_IFCHR |
-                                                               FilePermissions.S_IFBLK |
-                                                               FilePermissions.S_IFIFO |
-                                                               FilePermissions.S_IFSOCK)) == 0) {
-                                               throw new ArgumentException ("A positive capacity must be specified for a Memory Mapped File backed by an empty file.");
-                                       }
-
-                                       capacity = buf.st_size;
-                               } else if (capacity < buf.st_size) {
-                                       throw new ArgumentException ("The capacity may not be smaller than the file size.");
-                               }
-
-                               int fd = Syscall.open (path, ToUnixMode (mode) | ToUnixMode (access), FilePermissions.DEFFILEMODE);
-
-                               if (fd == -1)
-                                       UnixMarshal.ThrowExceptionForLastError ();
-                               return fd;
-                       }
-
-                       throw new NotImplementedException ();
-               }
-               
-               internal static void CloseFD (int fd) {
-                       Syscall.close (fd);
-               }
-
-               internal static void Flush (int fd) {
-                       if (MonoUtil.IsUnix)
-                               Syscall.fsync (fd);
-                       else
-                               throw new NotImplementedException ("Not implemented on Windows");
-                       
-               }
-
-               static int pagesize;
-
-               internal static unsafe void Map (int file_handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr map_addr, out int offset_diff)
-               {
-                       if (!MonoUtil.IsUnix)
-                               throw new NotImplementedException ("Not implemented on windows.");
-
-                       if (pagesize == 0)
-                               pagesize = Syscall.getpagesize ();
-
-                       Stat buf;
-                       Syscall.fstat (file_handle, out buf);
-                       long fsize = buf.st_size;
-
-                       if (size == 0 || size > fsize)
-                               size = fsize;
-                       
-                       // Align offset
-                       long real_offset = offset & ~(pagesize - 1);
-
-                       offset_diff = (int)(offset - real_offset);
-
-                       // FIXME: Need to determine the unix fd for the file, Handle is only
-                       // equal to it by accident
-                       //
-                       // The new API no longer uses FileStream everywhere, but exposes instead
-                       // the filename (with one exception), we could move this API to use
-                       // file descriptors instead of the FileStream plus its Handle.
-                       //
-                       map_addr = Syscall.mmap (IntPtr.Zero, (ulong) size,
-                                                ToUnixProts (access),
-                                                access == MemoryMappedFileAccess.CopyOnWrite ? MmapFlags.MAP_PRIVATE : MmapFlags.MAP_SHARED,
-                                                file_handle, real_offset);
-
-                       if (map_addr == (IntPtr)(-1))
-                               throw new IOException ("mmap failed for fd#" + file_handle + "(" + offset + ", " + size + ")");
-               }
-
-               internal static bool Unmap (IntPtr map_addr, ulong map_size)
-               {
-                       if (!MonoUtil.IsUnix)
-                               return false;
-                       return Syscall.munmap (map_addr, map_size) == 0;
-               }
-
-               static void ConfigureUnixFD (IntPtr handle, HandleInheritability h)
-               {
-                       // TODO: Mono.Posix is lacking O_CLOEXEC definitions for fcntl.
-               }
-
-
-               [DllImport("kernel32", SetLastError = true)]
-               static extern bool SetHandleInformation (IntPtr hObject, int dwMask, int dwFlags);
-               static void ConfigureWindowsFD (IntPtr handle, HandleInheritability h)
-               {
-                       SetHandleInformation (handle, 1 /* FLAG_INHERIT */, h == HandleInheritability.None ? 0 : 1);
-               }
-               
-               internal static void ConfigureFD (IntPtr handle, HandleInheritability inheritability)
-               {
-                       if (MonoUtil.IsUnix)
-                               ConfigureUnixFD (handle, inheritability);
-                       else
-                               ConfigureWindowsFD (handle, inheritability);
-               }
-
-       }
-#else
-       internal static class MemoryMapImpl {
-               [DllImport ("libc")]
-               static extern int fsync (int fd);
-
-               [DllImport ("libc")]
-               static extern int close (int fd);
-
-               [DllImport ("libc")]
-               static extern int fcntl (int fd, int cmd, int arg0);
-
-               //XXX check if android off_t is 64bits or not. on iOS / darwin it is.
-               [DllImport ("libc")]
-               static extern IntPtr mmap (IntPtr addr, IntPtr len, int prot, int flags, int fd, long offset);
-
-               [DllImport ("libc")]
-               static extern int munmap (IntPtr addr, IntPtr size);
-
-               [DllImport ("libc", SetLastError=true)]
-               static extern int open (string path, int flags, int access);
-
-#if MONODROID
-               [DllImport ("__Internal")]
-               static extern int monodroid_getpagesize ();
-
-               static int getpagesize ()
-               {
-                       return monodroid_getpagesize ();
-               }
-#else
-               [DllImport ("libc")]
-               static extern int getpagesize ();
-#endif
-
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               static extern long mono_filesize_from_path (string str);
+               static extern IntPtr OpenFileInternal (string path, FileMode mode, string mapName, out long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, out int error);
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               static extern long mono_filesize_from_fd (int fd);
-
-               //Values valid on iOS/OSX and android ndk r6
-               const int F_GETFD = 1;
-               const int F_SETFD = 2;
-               const int FD_CLOEXEC = 1;
-               const int DEFFILEMODE = 0x666;
-
-               const int O_RDONLY = 0x0;
-               const int O_WRONLY = 0x1;
-               const int O_RDWR   = 0x2;
-
-               const int PROT_READ  = 0x1;
-               const int PROT_WRITE = 0x2;
-               const int PROT_EXEC  = 0x4;
-
-               const int MAP_PRIVATE = 0x2;
-               const int MAP_SHARED  = 0x1;
+               static extern IntPtr OpenHandleInternal (IntPtr handle, string mapName, out long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, out int error);
 
 
-               const int EINVAL = 22;
-
-#if MONODROID
-               const int O_CREAT = 0x040;
-               const int O_TRUNC = 0x080;
-               const int O_EXCL  = 0x200;
-
-               const int ENAMETOOLONG = 63;
-#else
-               /* MONOTOUCH - usr/include/sys/fcntl.h */
-               const int O_CREAT = 0x0200;
-               const int O_TRUNC = 0x0400;
-               const int O_EXCL  = 0x0800;
-
-               // usr/include/sys/errno.h
-               const int ENAMETOOLONG = 63;
-#endif
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               internal extern static void CloseMapping (IntPtr handle);
 
 
-               static int ToUnixMode (FileMode mode)
-               {
-                       switch (mode) {
-                       case FileMode.CreateNew:
-                               return O_CREAT | O_EXCL;
-                               
-                       case FileMode.Create:
-                               return O_CREAT | O_TRUNC;
-                               
-                       case FileMode.OpenOrCreate:
-                               return O_CREAT;
-                               
-                       case FileMode.Truncate:
-                               return O_TRUNC;
-                       default:
-                       case FileMode.Open:
-                               return 0;
-                       }
-               }
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               internal extern static void Flush (IntPtr file_handle);
 
 
-               //
-               // Turns the MemoryMappedFileAccess into the second half of open(2) flags
-               //
-               static int ToUnixMode (MemoryMappedFileAccess access)
-               {
-                       switch (access) {
-                       case MemoryMappedFileAccess.CopyOnWrite:
-                       case MemoryMappedFileAccess.ReadWriteExecute:
-                       case MemoryMappedFileAccess.ReadWrite:
-                               return O_RDWR;
-                               
-                       case MemoryMappedFileAccess.Write:
-                               return O_WRONLY;
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               internal extern static void ConfigureHandleInheritability (IntPtr handle, HandleInheritability inheritability);
 
 
-                       case MemoryMappedFileAccess.ReadExecute:
-                       case MemoryMappedFileAccess.Read:
-                       default:
-                               return O_RDONLY;
-                       }
-               }
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               internal extern static bool Unmap (IntPtr mmap_handle);
 
 
-               static int ToUnixProts (MemoryMappedFileAccess access)
-               {
-                       switch (access){
-                       case MemoryMappedFileAccess.ReadWrite:
-                               return PROT_WRITE | PROT_READ;
-                               
-                       case MemoryMappedFileAccess.Write:
-                               return PROT_WRITE;
-                               
-                       case MemoryMappedFileAccess.CopyOnWrite:
-                               return PROT_WRITE | PROT_READ;
-                               
-                       case MemoryMappedFileAccess.ReadExecute:
-                               return PROT_EXEC;
-                               
-                       case MemoryMappedFileAccess.ReadWriteExecute:
-                               return PROT_WRITE | PROT_READ | PROT_EXEC;
-                               
-                       case MemoryMappedFileAccess.Read:
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               extern static int MapInternal (IntPtr handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr mmap_handle, out IntPtr base_address);
+
+               internal static void Map (IntPtr handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr mmap_handle, out IntPtr base_address)
+               {
+                       int error = MapInternal (handle, offset, ref size, access, out mmap_handle, out base_address);
+                       if (error != 0)
+                               throw CreateException (error, "<none>");
+               }
+
+               static Exception CreateException (int error, string path) {
+                       switch (error){
+                       case 1:
+                               return new ArgumentException ("A positive capacity must be specified for a Memory Mapped File backed by an empty file.");
+                       case 2:
+                               return new ArgumentOutOfRangeException ("capacity", "The capacity may not be smaller than the file size.");
+                       case 3:
+                               return new FileNotFoundException (path);
+                       case 4:
+                               return new IOException ("The file already exists");
+                       case 5:
+                               return new PathTooLongException ();
+                       case 6:
+                               return new IOException ("Could not open file");
+                       case 7:
+                               return new ArgumentException ("Capacity must be bigger than zero for non-file mappings");
+                       case 8:
+                               return new ArgumentException ("Invalid FileMode value.");
+                       case 9:
+                               return new IOException ("Could not map file");
+                       case 10:
+                               return new UnauthorizedAccessException ("Access to the path is denied.");
+                       case 11:
+                               return new ArgumentOutOfRangeException ("capacity", "The capacity cannot be greater than the size of the system's logical address space.");
                        default:
                        default:
-                               return PROT_READ;
-                       }
-               }
-
-               static void ThrowErrorFromErrno (int errno) 
-               {
-                       switch (errno) {
-                       case EINVAL:            throw new ArgumentException ();
-                       case ENAMETOOLONG:      throw new PathTooLongException ();
-                       default: throw new IOException ("Failed with errno " + errno);
+                               return new IOException ("Failed with unknown error code " + error);
                        }
                }
 
                        }
                }
 
-               internal static int Open (string path, FileMode mode, ref long capacity, MemoryMappedFileAccess access)
+               internal static IntPtr OpenFile (string path, FileMode mode, string mapName, out long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options)
                {
                {
-                       long file_size = mono_filesize_from_path (path);
-                       if (file_size < 0)
-                               throw new FileNotFoundException (path);
-
-                       if (capacity > file_size)
-                               throw new ArgumentException ("capacity");
-
-                       int fd = open (path, ToUnixMode (mode) | ToUnixMode (access), DEFFILEMODE);
-
-                       if (fd == -1)
-                               ThrowErrorFromErrno (Marshal.GetLastWin32Error ());
-                       return fd;
+                       int error = 0;
+                       IntPtr res = OpenFileInternal (path, mode, mapName, out capacity, access, options, out error);
+                       if (error != 0)
+                               throw CreateException (error, path);
+                       return res;
                }
 
                }
 
-               internal static void CloseFD (int fd)
+               internal static IntPtr OpenHandle (IntPtr handle, string mapName, out long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options)
                {
                {
-                       close (fd);
+                       int error = 0;
+                       IntPtr res = OpenHandleInternal (handle, mapName, out capacity, access, options, out error);
+                       if (error != 0)
+                               throw CreateException (error, "<none>");
+                       return res;
                }
                }
-
-               internal static void Flush (int fd)
-               {
-                       fsync (fd);
-               }
-
-               internal static bool Unmap (IntPtr map_addr, ulong map_size)
-               {
-                       return munmap (map_addr, (IntPtr)map_size) == 0;
-               }
-
-               static int pagesize;
-
-               internal static unsafe void Map (int file_handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr map_addr, out int offset_diff)
-               {
-                       if (pagesize == 0)
-                               pagesize = getpagesize ();
-
-                       long fsize = mono_filesize_from_fd (file_handle);
-                       if (fsize < 0)
-                               throw new FileNotFoundException ();
-
-                       if (size == 0 || size > fsize)
-                               size = fsize;
-                       
-                       // Align offset
-                       long real_offset = offset & ~(pagesize - 1);
-
-                       offset_diff = (int)(offset - real_offset);
-
-                       map_addr = mmap (IntPtr.Zero, (IntPtr) size,
-                                                ToUnixProts (access),
-                                                access == MemoryMappedFileAccess.CopyOnWrite ? MAP_PRIVATE : MAP_SHARED,
-                                                file_handle, real_offset);
-
-                       if (map_addr == (IntPtr)(-1))
-                               throw new IOException ("mmap failed for fd#" + file_handle + "(" + offset + ", " + size + ")");
-               }
-
-               internal static void ConfigureFD (IntPtr handle, HandleInheritability inheritability)
-               {
-                       int fd = (int)handle;
-                       int flags = fcntl (fd, F_GETFD, 0);
-                       if (inheritability == HandleInheritability.None)
-                               flags &= ~FD_CLOEXEC;
-                       else
-                               flags |= FD_CLOEXEC;
-                       fcntl (fd, F_SETFD, flags);
-               }
-
        }
        }
-#endif
+
 
        public class MemoryMappedFile : IDisposable {
 
        public class MemoryMappedFile : IDisposable {
-               MemoryMappedFileAccess fileAccess;
-               string name;
-               long fileCapacity;
+               // MemoryMappedFileAccess fileAccess;
+               // string name;
+               // long fileCapacity;
 
                //
                // We allow the use of either the FileStream/keepOpen combo
 
                //
                // We allow the use of either the FileStream/keepOpen combo
@@ -466,7 +127,7 @@ namespace System.IO.MemoryMappedFiles
                //
                FileStream stream;
                bool keepOpen;
                //
                FileStream stream;
                bool keepOpen;
-               int unix_fd;
+               IntPtr handle;
 
                public static MemoryMappedFile CreateFromFile (string path)
                {
 
                public static MemoryMappedFile CreateFromFile (string path)
                {
@@ -475,7 +136,21 @@ namespace System.IO.MemoryMappedFiles
 
                public static MemoryMappedFile CreateFromFile (string path, FileMode mode)
                {
 
                public static MemoryMappedFile CreateFromFile (string path, FileMode mode)
                {
-                       return CreateFromFile (path, mode, null, 0, MemoryMappedFileAccess.ReadWrite);
+                       long capacity = 0;
+                       if (path == null)
+                               throw new ArgumentNullException ("path");
+                       if (path.Length == 0)
+                               throw new ArgumentException ("path");
+                       if (mode == FileMode.Append)
+                               throw new ArgumentException ("mode");
+
+                       IntPtr handle = MemoryMapImpl.OpenFile (path, mode, null, out capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None);
+
+                       return new MemoryMappedFile () {
+                               handle = handle,
+                               // fileAccess = MemoryMappedFileAccess.ReadWrite,
+                               // fileCapacity = capacity
+                       };
                }
 
                public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName)
                }
 
                public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName)
@@ -501,26 +176,46 @@ namespace System.IO.MemoryMappedFiles
                        if (capacity < 0)
                                throw new ArgumentOutOfRangeException ("capacity");
 
                        if (capacity < 0)
                                throw new ArgumentOutOfRangeException ("capacity");
 
-                       int fd = MemoryMapImpl.Open (path, mode, ref capacity, access);
+                       IntPtr handle = MemoryMapImpl.OpenFile (path, mode, mapName, out capacity, access, MemoryMappedFileOptions.None);
                        
                        return new MemoryMappedFile () {
                        
                        return new MemoryMappedFile () {
-                               unix_fd = fd,
-                               fileAccess = access,
-                               name = mapName,
-                               fileCapacity = capacity
+                               handle = handle,
+                               // fileAccess = access,
+                               // name = mapName,
+                               // fileCapacity = capacity
                        };
                }
 
                        };
                }
 
-#if MOBILE
                public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access,
                                                               HandleInheritability inheritability,
                                                               bool leaveOpen)
                public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access,
                                                               HandleInheritability inheritability,
                                                               bool leaveOpen)
-#else
+               {
+                       if (fileStream == null)
+                               throw new ArgumentNullException ("fileStream");
+                       if (mapName != null && mapName.Length == 0)
+                               throw new ArgumentException ("mapName");
+                       if ((!MonoUtil.IsUnix && capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length))
+                               throw new ArgumentException ("capacity");
+
+                       IntPtr handle = MemoryMapImpl.OpenHandle (fileStream.SafeFileHandle.DangerousGetHandle (), mapName, out capacity, access, MemoryMappedFileOptions.None);
+                       
+                       MemoryMapImpl.ConfigureHandleInheritability (handle, inheritability);
+                               
+                       return new MemoryMappedFile () {
+                               handle = handle,
+                               // fileAccess = access,
+                               // name = mapName,
+                               // fileCapacity = capacity,
+
+                               stream = fileStream,
+                               keepOpen = leaveOpen
+                       };
+               }
+
                [MonoLimitation ("memoryMappedFileSecurity is currently ignored")]
                public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access,
                                                               MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability,
                                                               bool leaveOpen)
                [MonoLimitation ("memoryMappedFileSecurity is currently ignored")]
                public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access,
                                                               MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability,
                                                               bool leaveOpen)
-#endif
                {
                        if (fileStream == null)
                                throw new ArgumentNullException ("fileStream");
                {
                        if (fileStream == null)
                                throw new ArgumentNullException ("fileStream");
@@ -529,86 +224,104 @@ namespace System.IO.MemoryMappedFiles
                        if ((!MonoUtil.IsUnix && capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length))
                                throw new ArgumentException ("capacity");
 
                        if ((!MonoUtil.IsUnix && capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length))
                                throw new ArgumentException ("capacity");
 
-                       MemoryMapImpl.ConfigureFD (fileStream.Handle, inheritability);
+                       IntPtr handle = MemoryMapImpl.OpenHandle (fileStream.SafeFileHandle.DangerousGetHandle (), mapName, out capacity, access, MemoryMappedFileOptions.None);
+                       
+                       MemoryMapImpl.ConfigureHandleInheritability (handle, inheritability);
                                
                        return new MemoryMappedFile () {
                                
                        return new MemoryMappedFile () {
+                               handle = handle,
+                               // fileAccess = access,
+                               // name = mapName,
+                               // fileCapacity = capacity,
+
                                stream = fileStream,
                                stream = fileStream,
-                               fileAccess = access,
-                               name = mapName,
-                               fileCapacity = capacity,
                                keepOpen = leaveOpen
                        };
                }
 
                                keepOpen = leaveOpen
                        };
                }
 
-               [MonoLimitation ("CreateNew requires that mapName be a file name on Unix")]
+
+               static MemoryMappedFile CoreShmCreate (string mapName, long capacity, MemoryMappedFileAccess access,
+                                                         MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity,
+                                                         HandleInheritability inheritability, FileMode mode)
+               {
+                       if (mapName != null && mapName.Length == 0)
+                               throw new ArgumentException ("mapName");
+                       if (capacity < 0)
+                               throw new ArgumentOutOfRangeException ("capacity");
+
+                       IntPtr handle = MemoryMapImpl.OpenFile (null, mode, mapName, out capacity, access, options);
+                       
+                       return new MemoryMappedFile () {
+                               handle = handle,
+                               // fileAccess = access,
+                               // name = mapName,
+                               // fileCapacity = capacity
+                       };                      
+               }
+
+               [MonoLimitation ("Named mappings scope is process local")]
                public static MemoryMappedFile CreateNew (string mapName, long capacity)
                {
                public static MemoryMappedFile CreateNew (string mapName, long capacity)
                {
-#if MOBILE
-                       return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, 0);
-#else
-                       return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, null, 0);
-#endif
+                       return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, null, HandleInheritability.None);
                }
 
                }
 
-               [MonoLimitation ("CreateNew requires that mapName be a file name on Unix")]
+               [MonoLimitation ("Named mappings scope is process local")]
                public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access) 
                {
                public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access) 
                {
-#if MOBILE
-                       return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, 0);
-#else
-                       return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, null, 0);
-#endif
+                       return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.None, null, HandleInheritability.None);
                }
 
                }
 
-#if MOBILE
-               public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access,
-                                                         MemoryMappedFileOptions options, 
-                                                         HandleInheritability handleInheritability)
-#else
-               [MonoLimitation ("CreateNew requires that mapName be a file name on Unix; options and memoryMappedFileSecurity are ignored")]
+               [MonoLimitation ("Named mappings scope is process local; options is ignored")]
+               public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, HandleInheritability inheritability)
+               {
+                       return CreateNew (mapName, capacity, access, options, null, inheritability);
+               }
+
+               [MonoLimitation ("Named mappings scope is process local; options and memoryMappedFileSecurity are ignored")]
                public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access,
                                                          MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity,
                                                          HandleInheritability inheritability)
                public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access,
                                                          MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity,
                                                          HandleInheritability inheritability)
-#endif
                {
                {
-                       return CreateFromFile (mapName, FileMode.CreateNew, mapName, capacity, access);
+                       return CoreShmCreate (mapName, capacity, access, options, memoryMappedFileSecurity, inheritability, FileMode.CreateNew);
                }
 
                }
 
-               [MonoLimitation ("CreateOrOpen requires that mapName be a file name on Unix")]
+               [MonoLimitation ("Named mappings scope is process local")]
                public static MemoryMappedFile CreateOrOpen (string mapName, long capacity)
                {
                        return CreateOrOpen (mapName, capacity, MemoryMappedFileAccess.ReadWrite);
                }
 
                public static MemoryMappedFile CreateOrOpen (string mapName, long capacity)
                {
                        return CreateOrOpen (mapName, capacity, MemoryMappedFileAccess.ReadWrite);
                }
 
-               [MonoLimitation ("CreateOrOpen requires that mapName be a file name on Unix")]
+               [MonoLimitation ("Named mappings scope is process local")]
                public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access)
                {
                public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access)
                {
-                       return CreateFromFile (mapName, FileMode.OpenOrCreate, mapName, capacity, access); 
+                       return CreateOrOpen (mapName, capacity, access, MemoryMappedFileOptions.None, null, HandleInheritability.None);
                }
 
                }
 
-               [MonoTODO]
-#if MOBILE
+               [MonoLimitation ("Named mappings scope is process local")]
                public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, HandleInheritability inheritability)
                public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, HandleInheritability inheritability)
-#else
+               {
+                       return CreateOrOpen (mapName, capacity, access, options, null, inheritability);
+               }
+
+               [MonoLimitation ("Named mappings scope is process local")]
                public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability)
                public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability)
-#endif
                {
                {
-                       throw new NotImplementedException ();
+                       return CoreShmCreate (mapName, capacity, access, options, memoryMappedFileSecurity, inheritability, FileMode.OpenOrCreate);
                }
 
                }
 
-               [MonoTODO]
+               [MonoLimitation ("Named mappings scope is process local")]
                public static MemoryMappedFile OpenExisting (string mapName)
                {
                        throw new NotImplementedException ();
                }
 
                public static MemoryMappedFile OpenExisting (string mapName)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoLimitation ("Named mappings scope is process local")]
                public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights)
                {
                        throw new NotImplementedException ();
                }
 
                public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights)
                {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
+               [MonoLimitation ("Named mappings scope is process local")]
                public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights, HandleInheritability inheritability)
                {
                        throw new NotImplementedException ();
                public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights, HandleInheritability inheritability)
                {
                        throw new NotImplementedException ();
@@ -616,7 +329,7 @@ namespace System.IO.MemoryMappedFiles
 
                public MemoryMappedViewStream CreateViewStream ()
                {
 
                public MemoryMappedViewStream CreateViewStream ()
                {
-                       return CreateViewStream (0, 0);
+                       return CreateViewStream (0, 0);//FIXME this is wrong
                }
 
                public MemoryMappedViewStream CreateViewStream (long offset, long size)
                }
 
                public MemoryMappedViewStream CreateViewStream (long offset, long size)
@@ -626,7 +339,8 @@ namespace System.IO.MemoryMappedFiles
 
                public MemoryMappedViewStream CreateViewStream (long offset, long size, MemoryMappedFileAccess access)
                {
 
                public MemoryMappedViewStream CreateViewStream (long offset, long size, MemoryMappedFileAccess access)
                {
-                       return new MemoryMappedViewStream (stream != null ? (int)stream.Handle : unix_fd, offset, size, access);
+                       var view = MemoryMappedView.Create (handle, offset, size, access);
+                       return new MemoryMappedViewStream (view);
                }
 
                public MemoryMappedViewAccessor CreateViewAccessor ()
                }
 
                public MemoryMappedViewAccessor CreateViewAccessor ()
@@ -641,9 +355,8 @@ namespace System.IO.MemoryMappedFiles
 
                public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size, MemoryMappedFileAccess access)
                {
 
                public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size, MemoryMappedFileAccess access)
                {
-                       int file_handle = stream != null ? (int) stream.Handle : unix_fd;
-                       
-                       return new MemoryMappedViewAccessor (file_handle, offset, size, access);
+                       var view = MemoryMappedView.Create (handle, offset, size, access);
+                       return new MemoryMappedViewAccessor (view);
                }
 
                MemoryMappedFile ()
                }
 
                MemoryMappedFile ()
@@ -661,17 +374,15 @@ namespace System.IO.MemoryMappedFiles
                                if (stream != null){
                                        if (keepOpen == false)
                                                stream.Close ();
                                if (stream != null){
                                        if (keepOpen == false)
                                                stream.Close ();
-                                       unix_fd = -1;
                                        stream = null;
                                }
                                        stream = null;
                                }
-                               if (unix_fd != -1) {
-                                       MemoryMapImpl.CloseFD (unix_fd);
-                                       unix_fd = -1;
+                               if (handle != IntPtr.Zero) {
+                                       MemoryMapImpl.CloseMapping (handle);
+                                       handle = IntPtr.Zero;
                                }
                        }
                }
 
                                }
                        }
                }
 
-#if !MOBILE
                [MonoTODO]
                public MemoryMappedFileSecurity GetAccessControl ()
                {
                [MonoTODO]
                public MemoryMappedFileSecurity GetAccessControl ()
                {
@@ -683,7 +394,6 @@ namespace System.IO.MemoryMappedFiles
                {
                        throw new NotImplementedException ();
                }
                {
                        throw new NotImplementedException ();
                }
-#endif
 
                [MonoTODO]
                public SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle {
 
                [MonoTODO]
                public SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle {
@@ -691,7 +401,34 @@ namespace System.IO.MemoryMappedFiles
                                throw new NotImplementedException ();
                        }
                }
                                throw new NotImplementedException ();
                        }
                }
+
+               // This converts a MemoryMappedFileAccess to a FileAccess. MemoryMappedViewStream and
+               // MemoryMappedViewAccessor subclass UnmanagedMemoryStream and UnmanagedMemoryAccessor, which both use
+               // FileAccess to determine whether they are writable and/or readable.
+               internal static FileAccess GetFileAccess (MemoryMappedFileAccess access) {
+
+                       if (access == MemoryMappedFileAccess.Read) {
+                               return FileAccess.Read;
+                       }
+                       if (access == MemoryMappedFileAccess.Write) {
+                               return FileAccess.Write;
+                       }
+                       else if (access == MemoryMappedFileAccess.ReadWrite) {
+                               return FileAccess.ReadWrite;
+                       }
+                       else if (access == MemoryMappedFileAccess.CopyOnWrite) {
+                               return FileAccess.ReadWrite;
+                       }
+                       else if (access == MemoryMappedFileAccess.ReadExecute) {
+                               return FileAccess.Read;
+                       }
+                       else if (access == MemoryMappedFileAccess.ReadWriteExecute) {
+                               return FileAccess.ReadWrite;
+                       }
+
+                       // If we reached here, access was invalid.
+                       throw new ArgumentOutOfRangeException ("access");
+               }
        }
 }
 
        }
 }
 
-#endif