internal MemoryMappedViewAccessor(MemoryMappedView view) { Debug.Assert(view != null, "view is null"); _view = view; Initialize(_view.ViewHandle, _view.PointerOffset, _view.Size, MemoryMappedFile.GetFileAccess(_view.Access)); }
public MemoryMappedViewStream CreateViewStream(Int64 offset, Int64 size, MemoryMappedFileAccess access) { if (offset < 0) { throw new ArgumentOutOfRangeException("offset", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNum)); } if (size < 0) { throw new ArgumentOutOfRangeException("size", SR.GetString(SR.ArgumentOutOfRange_PositiveOrDefaultSizeRequired)); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException("access"); } if (IntPtr.Size == 4 && size > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("size", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); } MemoryMappedView view = MemoryMappedView.CreateView(_handle, access, offset, size); return(new MemoryMappedViewStream(view)); }
public MemoryMappedViewAccessor CreateViewAccessor(long offset, long size, MemoryMappedFileAccess access) { if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); } if (size < 0) { throw new ArgumentOutOfRangeException(nameof(size), SR.ArgumentOutOfRange_PositiveOrDefaultSizeRequired); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException(nameof(access)); } if (IntPtr.Size == 4 && size > uint.MaxValue) { throw new ArgumentOutOfRangeException(nameof(size), SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed); } MemoryMappedView view = MemoryMappedView.CreateView(_handle, access, offset, size); return(new MemoryMappedViewAccessor(view)); }
internal MemoryMappedViewStream(MemoryMappedView view) { Debug.Assert(view != null, "view is null"); _view = view; Initialize(_view.ViewHandle, _view.PointerOffset, _view.Size, MemoryMappedFile.GetFileAccess(_view.Access)); }
private void Dispose(bool disposeManagedResources) { if (_view != null) { _view.Dispose(); } _view = null; }
private static unsafe SafeMemoryMappedFileHandle CreateCore( FileStream fileStream, string mapName, HandleInheritability inheritability, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity) { if (mapName != null) { // Named maps are not supported in our Unix implementation. We could support named maps on Linux using // shared memory segments (shmget/shmat/shmdt/shmctl/etc.), but that doesn't work on OSX by default due // to very low default limits on OSX for the size of such objects; it also doesn't support behaviors // like copy-on-write or the ability to control handle inheritability, and reliably cleaning them up // relies on some non-conforming behaviors around shared memory IDs remaining valid even after they've // been marked for deletion (IPC_RMID). We could also support named maps using the current implementation // by not unlinking after creating the backing store, but then the backing stores would remain around // and accessible even after process exit, with no good way to appropriately clean them up. // (File-backed maps may still be used for cross-process communication.) throw CreateNamedMapsNotSupportedException(); } bool ownsFileStream = false; if (fileStream != null) { // This map is backed by a file. Make sure the file's size is increased to be // at least as big as the requested capacity of the map. if (fileStream.Length < capacity) { fileStream.SetLength(capacity); } } else { // This map is backed by memory-only. With files, multiple views over the same map // will end up being able to share data through the same file-based backing store; // for anonymous maps, we need a similar backing store, or else multiple views would logically // each be their own map and wouldn't share any data. To achieve this, we create a backing object // (either memory or on disk, depending on the system) and use its file descriptor as the file handle. // However, we only do this when the permission is more than read-only. We can't change the size // of an object that has read-only permissions, but we also don't need to worry about sharing // views over a read-only, anonymous, memory-backed map, because the data will never change, so all views // will always see zero and can't change that. In that case, we just use the built-in anonymous support of // the map by leaving fileStream as null. Interop.libc.MemoryMappedProtections protections = MemoryMappedView.GetProtections(access, forVerification: false); if ((protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0 && capacity > 0) { ownsFileStream = true; fileStream = CreateSharedBackingObject(protections, capacity); } } return(new SafeMemoryMappedFileHandle(fileStream, ownsFileStream, inheritability, access, options, capacity)); }
private static unsafe SafeMemoryMappedFileHandle CreateCore( FileStream fileStream, string mapName, HandleInheritability inheritability, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity) { if (mapName != null) { // TODO: We currently do not support named maps. We could possibly support // named maps in the future by using shm_open / shm_unlink, as we do for // giving internal names to anonymous maps. Issues to work through will include // dealing with permissions, passing information from the creator of the // map to another opener of it, etc. throw CreateNamedMapsNotSupportedException(); } SafeFileHandle fileHandle = null; if (fileStream != null) { // This map is backed by a file. Make sure the file's size is increased to be // at least as big as the requested capacity of the map. fileHandle = fileStream.SafeFileHandle; if (fileStream.Length < capacity) { fileStream.SetLength(capacity); } } else { // This map is backed by memory-only. With files, multiple views over the same map // will end up being able to share data through the same file-based backing store; // for anonymous maps, we need a similar backing store, or else multiple views would logically // each be their own map and wouldn't share any data. To achieve this, we create a POSIX shared // memory object and use its file descriptor as the file handle. However, we only do this when the // permission is more than read-only. We can't ftruncate to increase the size of a shared memory // object that has read-only permissions, but we also don't need to worry about sharing // views over a read-only, anonymous, memory-backed map, because the data will never change, so all views // will always see zero and can't change that. In that case, we just use the built-in anonymous support of // the map by leaving fileHandle as null. Interop.libc.MemoryMappedProtections protections = MemoryMappedView.GetProtections(access, forVerification: false); if ((protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0 && capacity > 0) { mapName = "/AnonCoreFxMemMap_" + Guid.NewGuid().ToString("N"); // unique name must start with "/" and be < NAME_MAX length fileHandle = CreateNewSharedMemoryObject(mapName, protections, capacity); } } return(new SafeMemoryMappedFileHandle(mapName, fileHandle, inheritability, access, options, capacity)); }
public MemoryMappedViewAccessor CreateViewAccessor(long offset, long size, MemoryMappedFileAccess access = MemoryMappedFileAccess.ReadWrite) { if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "Value must be non-negative"); } if (size < 0) { throw new ArgumentOutOfRangeException("size", "Value must be positive or zero for default size"); } if (IntPtr.Size == 4 && size > ((1024 * 1024 * 1024) * (long)4)) { throw new ArgumentOutOfRangeException("size", "The capacity cannot be greater than the size of the system's logical address space."); } MemoryMappedView memoryMappedView = MemoryMappedView.CreateView(this._handle, access, offset, size); return(new MemoryMappedViewAccessor(memoryMappedView)); }
public MemoryMappedViewStream CreateViewStream(long offset, long size, MemoryMappedFileAccess access) { if (offset < 0L) { throw new ArgumentOutOfRangeException("offset", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum")); } if (size < 0L) { throw new ArgumentOutOfRangeException("size", System.SR.GetString("ArgumentOutOfRange_PositiveOrDefaultSizeRequired")); } if ((access < MemoryMappedFileAccess.ReadWrite) || (access > MemoryMappedFileAccess.ReadWriteExecute)) { throw new ArgumentOutOfRangeException("access"); } if ((IntPtr.Size == 4) && (size > 0xffffffffL)) { throw new ArgumentOutOfRangeException("size", System.SR.GetString("ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed")); } return(new MemoryMappedViewStream(MemoryMappedView.CreateView(this._handle, access, offset, size))); }
internal unsafe MemoryMappedViewStream(MemoryMappedView view) { Debug.Assert(view != null, "view is null"); m_view = view; Initialize(m_view.ViewHandle, m_view.PointerOffset, m_view.Size, MemoryMappedFile.GetFileAccess(m_view.Access)); }
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; }
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); }
public MemoryMappedViewAccessor CreateViewAccessor(long offset, long size, MemoryMappedFileAccess access) { var view = MemoryMappedView.Create(handle, offset, size, access); return(new MemoryMappedViewAccessor(view)); }
public MemoryMappedViewStream CreateViewStream(long offset, long size, MemoryMappedFileAccess access) { var view = MemoryMappedView.Create(handle.DangerousGetHandle(), offset, size, access); return(new MemoryMappedViewStream(view)); }
internal MemoryMappedViewAccessor(MemoryMappedView view) { this.m_view = view; base.Initialize(this.m_view.ViewHandle, this.m_view.PointerOffset, this.m_view.Size, MemoryMappedFile.GetFileAccess(this.m_view.Access)); }
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); }
internal MemoryMappedViewAccessor(MemoryMappedView view) { this.m_view = view; base.Initialize(this.m_view.ViewHandle, this.m_view.PointerOffset, this.m_view.Size, MemoryMappedFile.GetFileAccess(this.m_view.Access)); }
internal MemoryMappedViewAccessor(MemoryMappedView memoryMappedView) { this._view = memoryMappedView; }
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; }