public static unsafe 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 from 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; long 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.CheckForAvailableVirtualMemory(nativeSize); // create the view SafeMemoryMappedViewHandle viewHandle = Interop.MapViewOfFile(memMappedFileHandle, (int)MemoryMappedFile.GetFileMapAccess(access), newOffset, new UIntPtr(nativeSize)); if (viewHandle.IsInvalid) { viewHandle.Dispose(); throw Win32Marshal.GetExceptionForLastWin32Error(); } // Query the view for its size and allocation type Interop.Kernel32.MEMORY_BASIC_INFORMATION viewInfo = new Interop.Kernel32.MEMORY_BASIC_INFORMATION(); Interop.Kernel32.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.Kernel32.MemOptions.MEM_RESERVE) != 0) || ((ulong)viewSize < (ulong)nativeSize)) { IntPtr tempHandle = Interop.VirtualAlloc( viewHandle, (UIntPtr)(nativeSize != MemoryMappedFile.DefaultSize ? nativeSize : viewSize), Interop.Kernel32.MemOptions.MEM_COMMIT, MemoryMappedFile.GetPageAccess(access)); int lastError = Marshal.GetLastWin32Error(); if (viewHandle.IsInvalid) { viewHandle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(lastError); } // again query the view for its new size viewInfo = new Interop.Kernel32.MEMORY_BASIC_INFORMATION(); Interop.Kernel32.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 - (ulong)extraMemNeeded); } else { Debug.Assert(viewSize >= (ulong)size, "viewSize < size"); } viewHandle.Initialize((ulong)size + (ulong)extraMemNeeded); return(new MemoryMappedView(viewHandle, extraMemNeeded, size, 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); }
public 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)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 = (size != MemoryMappedFile.DefaultSize) ? (ulong)size + (ulong)extraMemNeeded : 0; if (IntPtr.Size == 4 && nativeSize > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("size", 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 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 Int64 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 = (Int64)(viewSize - extraMemNeeded); } else { Debug.Assert(viewSize >= (ulong)size, "viewSize < size"); } viewHandle.Initialize((ulong)size + extraMemNeeded); return(new MemoryMappedView(viewHandle, (long)extraMemNeeded, size, access)); }
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)); }