private MemoryMappedFile(SafeMemoryMappedFileHandle handle) { Debug.Assert(handle != null && !handle.IsClosed && !handle.IsInvalid, "handle is null, closed, or invalid"); _handle = handle; _leaveOpen = true; // No FileStream to dispose of in this case. }
private static Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle CreateCore(SafeFileHandle fileHandle, string mapName, HandleInheritability inheritability, MemoryMappedFileSecurity memoryMappedFileSecurity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity) { Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle handle = null; object obj2; Microsoft.Win32.UnsafeNativeMethods.SECURITY_ATTRIBUTES lpAttributes = GetSecAttrs(inheritability, memoryMappedFileSecurity, out obj2); int dwMaximumSizeLow = (int)(((ulong)capacity) & 0xffffffffL); int dwMaximumSizeHigh = (int)(capacity >> 0x20); try { handle = Microsoft.Win32.UnsafeNativeMethods.CreateFileMapping(fileHandle, lpAttributes, GetPageAccess(access) | options, dwMaximumSizeHigh, dwMaximumSizeLow, mapName); int errorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid && (errorCode == 0xb7)) { handle.Dispose(); System.IO.__Error.WinIOError(errorCode, string.Empty); return(handle); } if (handle.IsInvalid) { System.IO.__Error.WinIOError(errorCode, string.Empty); } } finally { if (obj2 != null) { ((GCHandle)obj2).Free(); } } return(handle); }
private static FileStream CreateSharedBackingObject( Interop.libc.MemoryMappedProtections protections, long capacity, out string mapName, out SafeMemoryMappedFileHandle.FileStreamSource fileStreamSource) { // The POSIX shared memory object name must begin with '/'. After that we just want something short and unique. mapName = "/" + MemoryMapObjectFilePrefix + Guid.NewGuid().ToString("N"); fileStreamSource = SafeMemoryMappedFileHandle.FileStreamSource.ManufacturedSharedMemory; // Determine the flags to use when creating the shared memory object Interop.libc.OpenFlags flags = (protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0 ? Interop.libc.OpenFlags.O_RDWR : Interop.libc.OpenFlags.O_RDONLY; flags |= Interop.libc.OpenFlags.O_CREAT | Interop.libc.OpenFlags.O_EXCL; // CreateNew // Determine the permissions with which to create the file Interop.libc.Permissions perms = default(Interop.libc.Permissions); if ((protections & Interop.libc.MemoryMappedProtections.PROT_READ) != 0) perms |= Interop.libc.Permissions.S_IRUSR; if ((protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0) perms |= Interop.libc.Permissions.S_IWUSR; if ((protections & Interop.libc.MemoryMappedProtections.PROT_EXEC) != 0) perms |= Interop.libc.Permissions.S_IXUSR; // Create the shared memory object. Then enlarge it to the requested capacity. int fd; Interop.CheckIo(fd = Interop.libc.shm_open(mapName, flags, (int)perms), mapName); SafeFileHandle fileHandle = new SafeFileHandle((IntPtr)fd, ownsHandle: true); // Wrap the handle in a stream and return it. var fs = new FileStream(fileHandle, TranslateProtectionsToFileAccess(protections)); fs.SetLength(capacity); return fs; }
public static MemoryMappedFile CreateFromFile(string path, FileMode mode, string mapName, long capacity, MemoryMappedFileAccess access) { if (path == null) { throw new ArgumentNullException("path"); } if ((mapName != null) && (mapName.Length == 0)) { throw new ArgumentException(System.SR.GetString("Argument_MapNameEmptyString")); } if (capacity < 0L) { throw new ArgumentOutOfRangeException("capacity", System.SR.GetString("ArgumentOutOfRange_PositiveOrDefaultCapacityRequired")); } if ((access < MemoryMappedFileAccess.ReadWrite) || (access > MemoryMappedFileAccess.ReadWriteExecute)) { throw new ArgumentOutOfRangeException("access"); } if (mode == FileMode.Append) { throw new ArgumentException(System.SR.GetString("Argument_NewMMFAppendModeNotAllowed"), "mode"); } if (access == MemoryMappedFileAccess.Write) { throw new ArgumentException(System.SR.GetString("Argument_NewMMFWriteAccessNotAllowed"), "access"); } bool existed = File.Exists(path); FileStream fileStream = new FileStream(path, mode, GetFileStreamFileSystemRights(access), FileShare.None, 0x1000, FileOptions.None); if ((capacity == 0L) && (fileStream.Length == 0L)) { CleanupFile(fileStream, existed, path); throw new ArgumentException(System.SR.GetString("Argument_EmptyFile")); } if ((access == MemoryMappedFileAccess.Read) && (capacity > fileStream.Length)) { CleanupFile(fileStream, existed, path); throw new ArgumentException(System.SR.GetString("Argument_ReadAccessWithLargeCapacity")); } if (capacity == 0L) { capacity = fileStream.Length; } if (fileStream.Length > capacity) { CleanupFile(fileStream, existed, path); throw new ArgumentOutOfRangeException("capacity", System.SR.GetString("ArgumentOutOfRange_CapacityGEFileSizeRequired")); } Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle handle = null; try { handle = CreateCore(fileStream.SafeFileHandle, mapName, HandleInheritability.None, null, access, MemoryMappedFileOptions.None, capacity); } catch { CleanupFile(fileStream, existed, path); throw; } return(new MemoryMappedFile(handle, fileStream, false)); }
private MemoryMappedFile(SafeMemoryMappedFileHandle handle, FileStream fileStream, bool leaveOpen) { Debug.Assert(handle != null && !handle.IsClosed && !handle.IsInvalid, "handle is null, closed, or invalid"); Debug.Assert(fileStream != null, "fileStream is null"); _handle = handle; _fileStream = fileStream; _leaveOpen = leaveOpen; }
public static SafeMemoryMappedViewHandle MapViewOfFile( SafeMemoryMappedFileHandle hFileMappingObject, int desiredAccess, long fileOffset, UIntPtr numberOfBytesToMap) { return Interop.mincore.MapViewOfFileFromApp(hFileMappingObject, desiredAccess, fileOffset, numberOfBytesToMap); }
private MemoryMappedFile(SafeMemoryMappedFileHandle handle) { Debug.Assert(handle != null); Debug.Assert(!handle.IsClosed); Debug.Assert(!handle.IsInvalid); _handle = handle; _leaveOpen = true; // No FileStream to dispose of in this case. }
private MemoryMappedFile(SafeMemoryMappedFileHandle handle, FileStream fileStream, bool leaveOpen) { Debug.Assert(handle != null); Debug.Assert(!handle.IsClosed); Debug.Assert(!handle.IsInvalid); Debug.Assert(fileStream != null); _handle = handle; _fileStream = fileStream; _leaveOpen = leaveOpen; }
public static SafeMemoryMappedViewHandle MapViewOfFile( SafeMemoryMappedFileHandle hFileMappingObject, int desiredAccess, long fileOffset, UIntPtr numberOfBytesToMap) { // split the long into two ints int offsetHigh, offsetLow; SplitLong(fileOffset, out offsetHigh, out offsetLow); return Interop.Kernel32.MapViewOfFile(hFileMappingObject, desiredAccess, offsetHigh, offsetLow, numberOfBytesToMap); }
internal static MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, long offset, long size) { ulong num3; ulong num = (ulong) (offset % ((long) MemoryMappedFile.GetSystemPageAllocationGranularity())); ulong num2 = ((ulong) offset) - num; if (size != 0L) { num3 = ((ulong) size) + num; } else { num3 = 0L; } if ((IntPtr.Size == 4) && (num3 > 0xffffffffL)) { throw new ArgumentOutOfRangeException("size", System.SR.GetString("ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed")); } Microsoft.Win32.UnsafeNativeMethods.MEMORYSTATUSEX lpBuffer = new Microsoft.Win32.UnsafeNativeMethods.MEMORYSTATUSEX(); Microsoft.Win32.UnsafeNativeMethods.GlobalMemoryStatusEx(lpBuffer); ulong ullTotalVirtual = lpBuffer.ullTotalVirtual; if (num3 >= ullTotalVirtual) { throw new IOException(System.SR.GetString("IO_NotEnoughMemory")); } uint dwFileOffsetLow = (uint) (num2 & 0xffffffffL); uint dwFileOffsetHigh = (uint) (num2 >> 0x20); SafeMemoryMappedViewHandle address = Microsoft.Win32.UnsafeNativeMethods.MapViewOfFile(memMappedFileHandle, MemoryMappedFile.GetFileMapAccess(access), dwFileOffsetHigh, dwFileOffsetLow, new UIntPtr(num3)); if (address.IsInvalid) { System.IO.__Error.WinIOError(Marshal.GetLastWin32Error(), string.Empty); } Microsoft.Win32.UnsafeNativeMethods.MEMORY_BASIC_INFORMATION buffer = new Microsoft.Win32.UnsafeNativeMethods.MEMORY_BASIC_INFORMATION(); Microsoft.Win32.UnsafeNativeMethods.VirtualQuery(address, ref buffer, (IntPtr) Marshal.SizeOf(buffer)); ulong regionSize = (ulong) buffer.RegionSize; if ((buffer.State & 0x2000) != 0) { Microsoft.Win32.UnsafeNativeMethods.VirtualAlloc(address, (UIntPtr) regionSize, 0x1000, MemoryMappedFile.GetPageAccess(access)); int errorCode = Marshal.GetLastWin32Error(); if (address.IsInvalid) { System.IO.__Error.WinIOError(errorCode, string.Empty); } } if (size == 0L) { size = (long) (regionSize - num); } address.Initialize(((ulong) size) + num); return new MemoryMappedView(address, (long) num, size, access); }
private static Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle OpenCore(string mapName, HandleInheritability inheritability, int desiredAccessRights, bool createOrOpen) { Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle handle = Microsoft.Win32.UnsafeNativeMethods.OpenFileMapping(desiredAccessRights, (inheritability & HandleInheritability.Inheritable) != HandleInheritability.None, mapName); int errorCode = Marshal.GetLastWin32Error(); if (handle.IsInvalid) { if (createOrOpen && (errorCode == 2)) { throw new ArgumentException(System.SR.GetString("Argument_NewMMFWriteAccessNotAllowed"), "access"); } System.IO.__Error.WinIOError(errorCode, string.Empty); } return(handle); }
private static FileStream CreateSharedBackingObject( Interop.libc.MemoryMappedProtections protections, long capacity, out string mapName, out SafeMemoryMappedFileHandle.FileStreamSource fileHandleSource) { mapName = MemoryMapObjectFilePrefix + Guid.NewGuid().ToString("N") + ".tmp"; fileHandleSource = SafeMemoryMappedFileHandle.FileStreamSource.ManufacturedFile; FileAccess access = (protections & (Interop.libc.MemoryMappedProtections.PROT_READ | Interop.libc.MemoryMappedProtections.PROT_WRITE)) != 0 ? FileAccess.ReadWrite : (protections & (Interop.libc.MemoryMappedProtections.PROT_WRITE)) != 0 ? FileAccess.Write : FileAccess.Read; const int DefaultBufferSize = 0x1000; var fs = new FileStream(Path.Combine(Path.GetTempPath(), mapName), FileMode.CreateNew, TranslateProtectionsToFileAccess(protections), FileShare.ReadWrite, DefaultBufferSize, FileOptions.DeleteOnClose); fs.SetLength(capacity); return fs; }
private MemoryMappedFile(Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle handle, FileStream fileStream, bool leaveOpen) { this._handle = handle; this._fileStream = fileStream; this._leaveOpen = leaveOpen; }
private MemoryMappedFile(Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle handle) { this._handle = handle; this._leaveOpen = true; }
internal static extern SafeMemoryMappedViewHandle MapViewOfFile( SafeMemoryMappedFileHandle hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, UIntPtr dwNumberOfBytesToMap);
internal static extern int GetFileSize(SafeMemoryMappedFileHandle hFile, out int highSize);
internal static int GetFileSize (SafeMemoryMappedFileHandle hFile, out int highSize) { highSize = Int32.MaxValue; return Int32.MaxValue; }
internal unsafe static MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, Int64 offset, Int64 size) { // MapViewOfFile can only create views that start at a multiple of the system memory allocation // granularity. We decided to hide this restriction form the user by creating larger views than the // user requested and hiding the parts that the user did not request. extraMemNeeded is the amount of // extra memory we allocate before the start of the requested view. MapViewOfFile will also round the // capacity of the view to the nearest multiple of the system page size. Once again, we hide this // from the user by preventing them from writing to any memory that they did not request. ulong extraMemNeeded = (ulong)offset % (ulong)MemoryMappedFile.GetSystemPageAllocationGranularity(); // newOffset takes into account the fact that we have some extra memory allocated before the requested view ulong newOffset = (ulong)offset - extraMemNeeded; Debug.Assert(newOffset >= 0, "newOffset = (offset - extraMemNeeded) < 0"); // determine size to pass to MapViewOfFile ulong nativeSize; if (size != MemoryMappedFile.DefaultSize) { nativeSize = (ulong)size + (ulong)extraMemNeeded; } else { nativeSize = 0; } if (IntPtr.Size == 4 && nativeSize > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("size", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); } // if request is >= than total virtual, then MapViewOfFile will fail with meaningless error message // "the parameter is incorrect"; this provides better error message in advance UnsafeNativeMethods.MEMORYSTATUSEX memStatus = new UnsafeNativeMethods.MEMORYSTATUSEX(); bool result = UnsafeNativeMethods.GlobalMemoryStatusEx(ref memStatus); ulong totalVirtual = memStatus.ullTotalVirtual; if (nativeSize >= totalVirtual) { throw new IOException(SR.GetString(SR.IO_NotEnoughMemory)); } // split the Int64 into two ints uint offsetLow = (uint)(newOffset & 0x00000000FFFFFFFFL); uint offsetHigh = (uint)(newOffset >> 32); // create the view SafeMemoryMappedViewHandle viewHandle = UnsafeNativeMethods.MapViewOfFile(memMappedFileHandle, MemoryMappedFile.GetFileMapAccess(access), offsetHigh, offsetLow, new UIntPtr(nativeSize)); if (viewHandle.IsInvalid) { __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty); } // Query the view for its size and allocation type UnsafeNativeMethods.MEMORY_BASIC_INFORMATION viewInfo = new UnsafeNativeMethods.MEMORY_BASIC_INFORMATION(); UnsafeNativeMethods.VirtualQuery(viewHandle, ref viewInfo, (IntPtr)Marshal.SizeOf(viewInfo)); ulong viewSize = (ulong)viewInfo.RegionSize; // Allocate the pages if we were using the MemoryMappedFileOptions.DelayAllocatePages option // OR check if the allocated view size is smaller than the expected native size // If multiple overlapping views are created over the file mapping object, the pages in a given region // could have different attributes(MEM_RESERVE OR MEM_COMMIT) as MapViewOfFile preserves coherence between // views created on a mapping object backed by same file. // In which case, the viewSize will be smaller than nativeSize required and viewState could be MEM_COMMIT // but more pages may need to be committed in the region. // This is because, VirtualQuery function(that internally invokes VirtualQueryEx function) returns the attributes // and size of the region of pages with matching attributes starting from base address. // VirtualQueryEx: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366907(v=vs.85).aspx if (((viewInfo.State & UnsafeNativeMethods.MEM_RESERVE) != 0) || (viewSize < nativeSize)) { ulong allocSize = (nativeSize == 0) ? viewSize : nativeSize; IntPtr tempHandle = UnsafeNativeMethods.VirtualAlloc(viewHandle, (UIntPtr)allocSize, UnsafeNativeMethods.MEM_COMMIT, MemoryMappedFile.GetPageAccess(access)); int lastError = Marshal.GetLastWin32Error(); // The following is commented out for backward compatibility. // Previously releases failed to check for this error so introducing this check // could cause new/different exceptions in existing code paths. // if (tempHandle == IntPtr.Zero) { // __Error.WinIOError(lastError, String.Empty); // } // again query the view for its new size viewInfo = new UnsafeNativeMethods.MEMORY_BASIC_INFORMATION(); UnsafeNativeMethods.VirtualQuery(viewHandle, ref viewInfo, (IntPtr)Marshal.SizeOf(viewInfo)); viewSize = (ulong)viewInfo.RegionSize; } // if the user specified DefaultSize as the size, we need to get the actual size if (size == MemoryMappedFile.DefaultSize) { size = (Int64)(viewSize - extraMemNeeded); } else { Debug.Assert(viewSize >= (ulong)size, "viewSize < size"); } viewHandle.Initialize((ulong)size + extraMemNeeded); MemoryMappedView mmv = new MemoryMappedView(viewHandle, (long)extraMemNeeded, size, access); return mmv; }
private MemoryMappedFile(SafeMemoryMappedFileHandle handle) { this._handle = handle; }
internal static MemoryMappedView CreateView(SafeMemoryMappedFileHandle safeMemoryMappedFileHandle, MemoryMappedFileAccess access, long offset, long size) { // http://msdn.microsoft.com/en-us/library/windows/desktop/aa366548(v=vs.85).aspx UnsafeNativeMethods.SYSTEM_INFO info = new UnsafeNativeMethods.SYSTEM_INFO(); UnsafeNativeMethods.GetSystemInfo(ref info); // To calculate where to start the file mapping, round down the // offset of the data into the memory-mapped file to the nearest multiple of the // system allocation granularity. long fileMapStart = (offset / info.dwAllocationGranularity) * info.dwAllocationGranularity; // How large will the file mapping object be? long mapViewSize = (offset % info.dwAllocationGranularity) + size; // The data of interest is not necessarily at the beginning of the // view, so determine how far into the view to set the pointer. long viewDelta = offset - fileMapStart; SafeMemoryMappedViewHandle safeHandle = UnsafeNativeMethods.MapViewOfFile(safeMemoryMappedFileHandle, access.ToMapViewFileAccess(), (ulong)fileMapStart, new UIntPtr((ulong)mapViewSize)); var lastWin32Error = Marshal.GetLastWin32Error(); if (safeHandle.IsInvalid) { if (lastWin32Error == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND) throw new FileNotFoundException(); throw new System.IO.IOException(UnsafeNativeMethods.GetMessage(lastWin32Error)); } return new MemoryMappedView(safeHandle, viewDelta, size); }
public unsafe static MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, long offset, long size) { // MapViewOfFile can only create views that start at a multiple of the system memory allocation // granularity. We decided to hide this restriction form the user by creating larger views than the // user requested and hiding the parts that the user did not request. extraMemNeeded is the amount of // extra memory we allocate before the start of the requested view. MapViewOfFile will also round the // capacity of the view to the nearest multiple of the system page size. Once again, we hide this // from the user by preventing them from writing to any memory that they did not request. ulong nativeSize, extraMemNeeded, newOffset; ValidateSizeAndOffset( size, offset, GetSystemPageAllocationGranularity(), out nativeSize, out extraMemNeeded, out newOffset); // if request is >= than total virtual, then MapViewOfFile will fail with meaningless error message // "the parameter is incorrect"; this provides better error message in advance Interop.MEMORYSTATUSEX memStatus; memStatus.dwLength = (uint)sizeof(Interop.MEMORYSTATUSEX); Interop.mincore.GlobalMemoryStatusEx(out memStatus); ulong totalVirtual = memStatus.ullTotalVirtual; if (nativeSize >= totalVirtual) { throw new IOException(SR.IO_NotEnoughMemory); } // split the long into two ints int offsetLow = unchecked((int)(newOffset & 0x00000000FFFFFFFFL)); int offsetHigh = unchecked((int)(newOffset >> 32)); // create the view SafeMemoryMappedViewHandle viewHandle = Interop.mincore.MapViewOfFile(memMappedFileHandle, (int)MemoryMappedFile.GetFileMapAccess(access), offsetHigh, offsetLow, new UIntPtr(nativeSize)); if (viewHandle.IsInvalid) { throw Win32Marshal.GetExceptionForLastWin32Error(); } // Query the view for its size and allocation type Interop.MEMORY_BASIC_INFORMATION viewInfo = new Interop.MEMORY_BASIC_INFORMATION(); Interop.mincore.VirtualQuery(viewHandle, ref viewInfo, (UIntPtr)Marshal.SizeOf(viewInfo)); ulong viewSize = (ulong)viewInfo.RegionSize; // Allocate the pages if we were using the MemoryMappedFileOptions.DelayAllocatePages option // OR check if the allocated view size is smaller than the expected native size // If multiple overlapping views are created over the file mapping object, the pages in a given region // could have different attributes(MEM_RESERVE OR MEM_COMMIT) as MapViewOfFile preserves coherence between // views created on a mapping object backed by same file. // In which case, the viewSize will be smaller than nativeSize required and viewState could be MEM_COMMIT // but more pages may need to be committed in the region. // This is because, VirtualQuery function(that internally invokes VirtualQueryEx function) returns the attributes // and size of the region of pages with matching attributes starting from base address. // VirtualQueryEx: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366907(v=vs.85).aspx if (((viewInfo.State & Interop.MEM_RESERVE) != 0) || (viewSize < nativeSize)) { IntPtr tempHandle = Interop.mincore.VirtualAlloc(viewHandle, (UIntPtr)nativeSize, Interop.MEM_COMMIT, MemoryMappedFile.GetPageAccess(access)); int lastError = Marshal.GetLastWin32Error(); if (viewHandle.IsInvalid) { throw Win32Marshal.GetExceptionForWin32Error(lastError); } // again query the view for its new size viewInfo = new Interop.MEMORY_BASIC_INFORMATION(); Interop.mincore.VirtualQuery(viewHandle, ref viewInfo, (UIntPtr)Marshal.SizeOf(viewInfo)); viewSize = (ulong)viewInfo.RegionSize; } // if the user specified DefaultSize as the size, we need to get the actual size if (size == MemoryMappedFile.DefaultSize) { size = (long)(viewSize - extraMemNeeded); } else { Debug.Assert(viewSize >= (ulong)size, "viewSize < size"); } viewHandle.Initialize((ulong)size + extraMemNeeded); return new MemoryMappedView(viewHandle, (long)extraMemNeeded, size, access); }
public unsafe static MemoryMappedView CreateView( SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, long requestedOffset, long requestedSize) { // If the requested size is either the default or if it's larger than the capacity // of the mapped file, reset it to be the capacity set when creating the mapped file. if (requestedSize == MemoryMappedFile.DefaultSize || requestedSize > memMappedFileHandle._capacity) { requestedSize = memMappedFileHandle._capacity; } Debug.Assert(requestedSize > 0); // mmap can only create views that start at a multiple of the page size. As on Windows, // we hide this restriction form the user by creating larger views than the user requested and hiding the parts // that the user did not request. extraMemNeeded is the amount of extra memory we allocate before the start of the // requested view. (mmap may round up the actual length such that it is also page-aligned; we hide that by using // the right size and not extending the size to be page-aligned.) ulong nativeSize, extraMemNeeded, nativeOffset; ValidateSizeAndOffset( requestedSize, requestedOffset, Interop.libc.sysconf(Interop.libc.SysConfNames._SC_PAGESIZE), out nativeSize, out extraMemNeeded, out nativeOffset); bool gotRefOnHandle = false; try { // Determine whether to create the pages as private or as shared; the former is used for copy-on-write. Interop.libc.MemoryMappedFlags flags = (memMappedFileHandle._access == MemoryMappedFileAccess.CopyOnWrite) ? Interop.libc.MemoryMappedFlags.MAP_PRIVATE : Interop.libc.MemoryMappedFlags.MAP_SHARED; // If we have a file handle, get the file descriptor from it. If the handle is null, // we'll use an anonymous backing store for the map. int fd; if (memMappedFileHandle._fileHandle != null) { // Get the file descriptor from the SafeFileHandle memMappedFileHandle._fileHandle.DangerousAddRef(ref gotRefOnHandle); Debug.Assert(gotRefOnHandle); fd = (int)memMappedFileHandle._fileHandle.DangerousGetHandle(); Debug.Assert(fd >= 0); } else { Debug.Assert(!gotRefOnHandle); fd = -1; flags |= Interop.libc.MemoryMappedFlags.MAP_ANONYMOUS; } // Nothing to do for options.DelayAllocatePages, since we're only creating the map // with mmap when creating the view. // Intersect the permissions from the creation of the MMF and the MMV. Interop.libc.MemoryMappedProtections prot = GetProtections(memMappedFileHandle._access); prot &= GetProtections(access); if (prot == 0) { throw new ArgumentOutOfRangeException("access"); } // Create the map IntPtr addr = Interop.libc.mmap( IntPtr.Zero, // don't specify an address; let the system choose one (IntPtr)nativeSize, // specify the rounded-size we computed so as to page align; size + extraMemNeeded prot, flags, fd, // mmap adds a ref count to the fd, so there's no need to dup it. (long)nativeOffset); // specify the rounded-offset we computed so as to page align; offset - extraMemNeeded if ((long)addr < 0) { throw Interop.GetExceptionForIoErrno(Marshal.GetLastWin32Error()); } // Based on the HandleInheritability, try to prevent the memory-mapped region // from being inherited by a forked process if (memMappedFileHandle._inheritability == HandleInheritability.None) { int adviseResult = Interop.libc.madvise(addr, (IntPtr)nativeSize, Interop.libc.MemoryMappedAdvice.MADV_DONTFORK); Debug.Assert(adviseResult == 0); // In release, ignore failures from advise; it's just a hint, anyway. } // Create and return the view handle var viewHandle = new SafeMemoryMappedViewHandle(addr, ownsHandle: true); viewHandle.Initialize(nativeSize); return new MemoryMappedView( viewHandle, (long)extraMemNeeded, // the view points to offset - extraMemNeeded, so we need to shift back by extraMemNeeded requestedSize, // only allow access to the actual size requested access); } finally { if (gotRefOnHandle) { memMappedFileHandle._fileHandle.DangerousRelease(); } } }
private Win32MemoryMappedFile(FileStream fs, SafeMemoryMappedFileHandle handle, ulong size) { Contract.Requires(fs != null && handle != null && !handle.IsInvalid && !handle.IsClosed); m_mapHandle = handle; m_file = fs; m_size = size; // verify that it fits on 32 bit OS... if (IntPtr.Size == 4 && size > uint.MaxValue) { // won't work with 32-bit pointers throw new InvalidOperationException("Memory mapped file size is too big to be opened on a 32-bit system."); } // verifiy that it will fit in the virtual address space of the process var totalVirtual = UnsafeNativeMethods.GetTotalVirtualAddressSpaceSize(); if (size > totalVirtual) { throw new InvalidOperationException("Memory mapped file size is too big to fit in the current process virtual address space"); } SafeMemoryMappedViewHandle view = null; byte* baseAddress = null; try { view = UnsafeNativeMethods.MapViewOfFile(m_mapHandle, UnsafeNativeMethods.FileMapAccess.FileMapRead, 0, 0, new UIntPtr(size)); if (view.IsInvalid) throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); view.Initialize(size); m_viewHandle = view; view.AcquirePointer(ref baseAddress); m_baseAddress = baseAddress; } catch { if (baseAddress != null) view.ReleasePointer(); if (view != null) view.Dispose(); m_file = null; m_viewHandle = null; m_mapHandle = null; m_baseAddress = null; throw; } }
/* [SecurityCritical, DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)] internal static extern SafeMemoryMappedViewHandle MapViewOfFile(SafeMemoryMappedFileHandle handle, int dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumberOfBytesToMap); [SecurityCritical, DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] internal static extern SafeMemoryMappedFileHandle OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName); [SecurityCritical, DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true, ExactSpelling=true)] internal static extern unsafe PerfCounterSetInstanceStruct* PerfCreateInstance([In] SafePerfProviderHandle hProvider, [In] ref Guid CounterSetGuid, [In] string szInstanceName, [In] uint dwInstance); [SecurityCritical, DllImport("advapi32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)] internal static extern unsafe uint PerfDeleteInstance([In] SafePerfProviderHandle hProvider, [In] PerfCounterSetInstanceStruct* InstanceBlock); [SecurityCritical, DllImport("advapi32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)] internal static extern unsafe int PerfSetCounterRefValue([In] SafePerfProviderHandle hProvider, [In] PerfCounterSetInstanceStruct* pInstance, [In] int CounterId, [In] void* lpAddr); [SecurityCritical, DllImport("advapi32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)] internal static extern unsafe uint PerfSetCounterSetInfo([In] SafePerfProviderHandle hProvider, [In, Out] PerfCounterSetInfoStruct* pTemplate, [In] uint dwTemplateSize); [SecurityCritical, DllImport("advapi32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)] internal static extern uint PerfStartProvider([In] ref Guid ProviderGuid, [In] PERFLIBREQUEST ControlCallback, out SafePerfProviderHandle phProvider); [SecurityCritical, DllImport("advapi32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)] internal static extern uint PerfStopProvider([In] IntPtr hProvider); [SecurityCritical, DllImport("kernel32.dll", SetLastError=true)] internal static extern unsafe int ReadFile(SafePipeHandle handle, byte* bytes, int numBytesToRead, IntPtr numBytesRead_mustBeZero, NativeOverlapped* overlapped); [SecurityCritical, DllImport("kernel32.dll", SetLastError=true)] internal static extern unsafe int ReadFile(SafePipeHandle handle, byte* bytes, int numBytesToRead, out int numBytesRead, IntPtr mustBeZero); [return: MarshalAs(UnmanagedType.Bool)] [SecurityCritical, ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), DllImport("advapi32.dll", SetLastError=true)] internal static extern bool RevertToSelf(); */ internal static SafeMemoryMappedViewHandle MapViewOfFile (SafeMemoryMappedFileHandle handle, int dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumberOfBytesToMap) { return null; }
private static Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle CreateOrOpenCore(SafeFileHandle fileHandle, string mapName, HandleInheritability inheritability, MemoryMappedFileSecurity memoryMappedFileSecurity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity) { Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle handle = null; object obj2; Microsoft.Win32.UnsafeNativeMethods.SECURITY_ATTRIBUTES lpAttributes = GetSecAttrs(inheritability, memoryMappedFileSecurity, out obj2); int dwMaximumSizeLow = (int)(((ulong)capacity) & 0xffffffffL); int dwMaximumSizeHigh = (int)(capacity >> 0x20); try { int num3 = 14; int millisecondsTimeout = 0; while (num3 > 0) { handle = Microsoft.Win32.UnsafeNativeMethods.CreateFileMapping(fileHandle, lpAttributes, GetPageAccess(access) | options, dwMaximumSizeHigh, dwMaximumSizeLow, mapName); int errorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid) { break; } if (errorCode != 5) { System.IO.__Error.WinIOError(errorCode, string.Empty); } handle.SetHandleAsInvalid(); handle = Microsoft.Win32.UnsafeNativeMethods.OpenFileMapping(GetFileMapAccess(access), (inheritability & HandleInheritability.Inheritable) != HandleInheritability.None, mapName); int num6 = Marshal.GetLastWin32Error(); if (!handle.IsInvalid) { break; } if (num6 != 2) { System.IO.__Error.WinIOError(num6, string.Empty); } num3--; if (millisecondsTimeout == 0) { millisecondsTimeout = 10; } else { Thread.Sleep(millisecondsTimeout); millisecondsTimeout *= 2; } } if ((handle == null) || handle.IsInvalid) { throw new InvalidOperationException(System.SR.GetString("InvalidOperation_CantCreateFileMapping")); } return(handle); } finally { if (obj2 != null) { ((GCHandle)obj2).Free(); } } return(handle); }
void Dispose(bool disposeManagedResources) { if (this._handle != null && !this._handle.IsClosed) { this._handle.Dispose(); this._handle = null; } }
internal static extern SafeMemoryMappedViewHandle MapViewOfFileFromApp( SafeMemoryMappedFileHandle hFileMappingObject, int DesiredAccess, long FileOffset, UIntPtr NumberOfBytesToMap);
internal static SafeMemoryMappedViewHandle MapViewOfFile(SafeMemoryMappedFileHandle hFileMappingObject, FileMapAccess dwDesiredAccess, ulong ddFileOffset, UIntPtr dwNumberofBytesToMap) { uint hi = (UInt32)(ddFileOffset / UInt32.MaxValue); uint lo = (UInt32)(ddFileOffset % UInt32.MaxValue); return MapViewOfFile(hFileMappingObject, dwDesiredAccess, hi, lo, dwNumberofBytesToMap); }
public unsafe static MemoryMappedView CreateView( SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, long requestedOffset, long requestedSize) { if (requestedOffset > memMappedFileHandle._capacity) { throw new ArgumentOutOfRangeException("offset"); } if (requestedSize > MaxProcessAddressSpace) { throw new IOException(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed); } if (requestedOffset + requestedSize > memMappedFileHandle._capacity) { throw new UnauthorizedAccessException(); } if (memMappedFileHandle.IsClosed) { throw new ObjectDisposedException(typeof(MemoryMappedFile).Name); } if (requestedSize == MemoryMappedFile.DefaultSize) { requestedSize = memMappedFileHandle._capacity - requestedOffset; } // mmap can only create views that start at a multiple of the page size. As on Windows, // we hide this restriction form the user by creating larger views than the user requested and hiding the parts // that the user did not request. extraMemNeeded is the amount of extra memory we allocate before the start of the // requested view. (mmap may round up the actual length such that it is also page-aligned; we hide that by using // the right size and not extending the size to be page-aligned.) ulong nativeSize; long extraMemNeeded, nativeOffset; long pageSize = Interop.Sys.SysConf(Interop.Sys.SysConfName._SC_PAGESIZE); Debug.Assert(pageSize > 0); ValidateSizeAndOffset( requestedSize, requestedOffset, pageSize, out nativeSize, out extraMemNeeded, out nativeOffset); // Determine whether to create the pages as private or as shared; the former is used for copy-on-write. Interop.Sys.MemoryMappedFlags flags = (memMappedFileHandle._access == MemoryMappedFileAccess.CopyOnWrite || access == MemoryMappedFileAccess.CopyOnWrite) ? Interop.Sys.MemoryMappedFlags.MAP_PRIVATE : Interop.Sys.MemoryMappedFlags.MAP_SHARED; // If we have a file handle, get the file descriptor from it. If the handle is null, // we'll use an anonymous backing store for the map. SafeFileHandle fd; if (memMappedFileHandle._fileStream != null) { // Get the file descriptor from the SafeFileHandle fd = memMappedFileHandle._fileStream.SafeFileHandle; Debug.Assert(!fd.IsInvalid); } else { fd = new SafeFileHandle(new IntPtr(-1), false); flags |= Interop.Sys.MemoryMappedFlags.MAP_ANONYMOUS; } // Nothing to do for options.DelayAllocatePages, since we're only creating the map // with mmap when creating the view. // Verify that the requested view permissions don't exceed the map's permissions Interop.Sys.MemoryMappedProtections viewProtForVerification = GetProtections(access, forVerification: true); Interop.Sys.MemoryMappedProtections mapProtForVerification = GetProtections(memMappedFileHandle._access, forVerification: true); if ((viewProtForVerification & mapProtForVerification) != viewProtForVerification) { throw new UnauthorizedAccessException(); } // viewProtections is strictly less than mapProtections, so use viewProtections for actually creating the map. Interop.Sys.MemoryMappedProtections viewProtForCreation = GetProtections(access, forVerification: false); // Create the map IntPtr addr = IntPtr.Zero; if (nativeSize > 0) { addr = Interop.Sys.MMap( IntPtr.Zero, // don't specify an address; let the system choose one nativeSize, // specify the rounded-size we computed so as to page align; size + extraMemNeeded viewProtForCreation, flags, fd, // mmap adds a ref count to the fd, so there's no need to dup it. nativeOffset); // specify the rounded-offset we computed so as to page align; offset - extraMemNeeded } else { // There are some corner cases where the .NET API allows the requested size to be zero, e.g. the caller is // creating a map at the end of the capacity. We can't pass 0 to mmap, as that'll fail with EINVAL, nor can // we create a map that extends beyond the end of the underlying file, as that'll fail on some platforms at the // time of the map's creation. Instead, since there's no data to be read/written, it doesn't actually matter // what backs the view, so we just create an anonymous mapping. addr = Interop.Sys.MMap( IntPtr.Zero, 1, // any length that's greater than zero will suffice viewProtForCreation, flags | Interop.Sys.MemoryMappedFlags.MAP_ANONYMOUS, new SafeFileHandle(new IntPtr(-1), false), // ignore the actual fd even if there was one 0); requestedSize = 0; extraMemNeeded = 0; } if (addr == IntPtr.Zero) // note that shim uses null pointer, not non-null MAP_FAILED sentinel { throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo()); } // Based on the HandleInheritability, try to prevent the memory-mapped region // from being inherited by a forked process if (memMappedFileHandle._inheritability == HandleInheritability.None) { DisableForkingIfPossible(addr, nativeSize); } // Create and return the view handle var viewHandle = new SafeMemoryMappedViewHandle(addr, ownsHandle: true); viewHandle.Initialize((ulong)nativeSize); return new MemoryMappedView( viewHandle, extraMemNeeded, // the view points to offset - extraMemNeeded, so we need to shift back by extraMemNeeded requestedSize, // only allow access to the actual size requested access); }
public static extern SafeMemoryMappedViewHandle MapViewOfFile(SafeMemoryMappedFileHandle handle, FileMapAccess dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumberOfBytesToMap);
internal static SafeMemoryMappedFileHandle CreateFileMapping(SafeFileHandle hFile, SECURITY_ATTRIBUTES lpAttributes, int fProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName) { var handle = new SafeMemoryMappedFileHandle(hFile.DangerousGetHandle (), false); return handle; }
internal unsafe static MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, Int64 offset, Int64 size) { // MapViewOfFile can only create views that start at a multiple of the system memory allocation // granularity. We decided to hide this restriction form the user by creating larger views than the // user requested and hiding the parts that the user did not request. extraMemNeeded is the amount of // extra memory we allocate before the start of the requested view. MapViewOfFile will also round the // capacity of the view to the nearest multiple of the system page size. Once again, we hide this // from the user by preventing them from writing to any memory that they did not request. ulong extraMemNeeded = (ulong)offset % (ulong)MemoryMappedFile.GetSystemPageAllocationGranularity(); // newOffset takes into account the fact that we have some extra memory allocated before the requested view ulong newOffset = (ulong)offset - extraMemNeeded; Debug.Assert(newOffset >= 0, "newOffset = (offset - extraMemNeeded) < 0"); // determine size to pass to MapViewOfFile ulong nativeSize; if (size != MemoryMappedFile.DefaultSize) { nativeSize = (ulong)size + (ulong)extraMemNeeded; } else { nativeSize = 0; } if (IntPtr.Size == 4 && nativeSize > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("size", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); } // if request is >= than total virtual, then MapViewOfFile will fail with meaningless error message // "the parameter is incorrect"; this provides better error message in advance UnsafeNativeMethods.MEMORYSTATUSEX memStatus = new UnsafeNativeMethods.MEMORYSTATUSEX(); bool result = UnsafeNativeMethods.GlobalMemoryStatusEx(memStatus); ulong totalVirtual = memStatus.ullTotalVirtual; if (nativeSize >= totalVirtual) { throw new IOException(SR.GetString(SR.IO_NotEnoughMemory)); } // split the Int64 into two ints uint offsetLow = (uint)(newOffset & 0x00000000FFFFFFFFL); uint offsetHigh = (uint)(newOffset >> 32); // create the view SafeMemoryMappedViewHandle viewHandle = UnsafeNativeMethods.MapViewOfFile(memMappedFileHandle, MemoryMappedFile.GetFileMapAccess(access), offsetHigh, offsetLow, new UIntPtr(nativeSize)); if (viewHandle.IsInvalid) { __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty); } // Query the view for its size and allocation type UnsafeNativeMethods.MEMORY_BASIC_INFORMATION viewInfo = new UnsafeNativeMethods.MEMORY_BASIC_INFORMATION(); UnsafeNativeMethods.VirtualQuery(viewHandle, ref viewInfo, (IntPtr)Marshal.SizeOf(viewInfo)); ulong viewSize = (ulong)viewInfo.RegionSize; // allocate the pages if we were using the MemoryMappedFileOptions.DelayAllocatePages option if ((viewInfo.State & UnsafeNativeMethods.MEM_RESERVE) != 0) { IntPtr tempHandle = UnsafeNativeMethods.VirtualAlloc(viewHandle, (UIntPtr)viewSize, UnsafeNativeMethods.MEM_COMMIT, MemoryMappedFile.GetPageAccess(access)); int lastError = Marshal.GetLastWin32Error(); if (viewHandle.IsInvalid) { __Error.WinIOError(lastError, String.Empty); } } // if the user specified DefaultSize as the size, we need to get the actual size if (size == MemoryMappedFile.DefaultSize) { size = (Int64)(viewSize - extraMemNeeded); } else { Debug.Assert(viewSize >= (ulong)size, "viewSize < size"); } viewHandle.Initialize((ulong)size + extraMemNeeded); MemoryMappedView mmv = new MemoryMappedView(viewHandle, (long)extraMemNeeded, size, access); return mmv; }
public static extern SafeMemoryMappedViewHandle MapViewOfFile( SafeMemoryMappedFileHandle hFileMappingObject, Kernel32.FileMapAccess dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, IntPtr dwNumberOfBytesToMap);