Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / IO / MemoryMappedFiles / MemoryMappedFile.cs / 1305376 / MemoryMappedFile.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Class: MemoryMappedFile ** ** Purpose: Managed MemoryMappedFiles. ** ** Date: February 7, 2007 ** ===========================================================*/ using System; using System.Diagnostics; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.AccessControl; using System.Security.Permissions; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; namespace System.IO.MemoryMappedFiles { public class MemoryMappedFile : IDisposable { private SafeMemoryMappedFileHandle _handle; private bool _leaveOpen; private FileStream _fileStream; internal const int DefaultSize = 0; // Private constructors to be used by the factory methods. //// [System.Security.SecurityCritical] 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. } //// // // // [System.Security.SecurityCritical] 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; } // Factory Method Group #1: Opens an existing named memory mapped file. The native OpenFileMapping call // will check the desiredAccessRights against the ACL on the memory mapped file. Note that a memory // mapped file created without an ACL will use a default ACL taken from the primary or impersonation token // of the creator. On my machine, I always get ReadWrite access to it so I never have to use anything but // the first override of this method. Note: having ReadWrite access to the object does not mean that we // have ReadWrite access to the pages mapping the file. The OS will check against the access on the pages // when a view is created. public static MemoryMappedFile OpenExisting(string mapName) { return OpenExisting(mapName, MemoryMappedFileRights.ReadWrite, HandleInheritability.None); } public static MemoryMappedFile OpenExisting(string mapName, MemoryMappedFileRights desiredAccessRights) { return OpenExisting(mapName, desiredAccessRights, HandleInheritability.None); } //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile OpenExisting(string mapName, MemoryMappedFileRights desiredAccessRights, HandleInheritability inheritability) { if (mapName == null) { throw new ArgumentNullException("mapName", SR.GetString(SR.ArgumentNull_MapName)); } if (mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability"); } if (((int)desiredAccessRights & ~((int)(MemoryMappedFileRights.FullControl | MemoryMappedFileRights.AccessSystemSecurity))) != 0) { throw new ArgumentOutOfRangeException("desiredAccessRights"); } SafeMemoryMappedFileHandle handle = OpenCore(mapName, inheritability, (int)desiredAccessRights, false); return new MemoryMappedFile(handle); } // Factory Method Group #2: Creates a new memory mapped file where the content is taken from an existing // file on disk. This file must be opened by a FileStream before given to us. Specifying DefaultSize to // the capacity will make the capacity of the memory mapped file match the size of the file. Specifying // a value larger than the size of the file will enlarge the new file to this size. Note that in such a // case, the capacity (and there for the size of the file) will be rounded up to a multiple of the system // page size. One can use FileStream.SetLength to bring the length back to a desirable size. By default, // the MemoryMappedFile will close the FileStream object when it is disposed. This behavior can be // changed by the leaveOpen boolean argument. public static MemoryMappedFile CreateFromFile(String path) { return CreateFromFile(path, FileMode.Open, null, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public static MemoryMappedFile CreateFromFile(String path, FileMode mode) { return CreateFromFile(path, mode, null, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public static MemoryMappedFile CreateFromFile(String path, FileMode mode, String mapName) { return CreateFromFile(path, mode, mapName, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public static MemoryMappedFile CreateFromFile(String path, FileMode mode, String mapName, Int64 capacity) { return CreateFromFile(path, mode, mapName, capacity, MemoryMappedFileAccess.ReadWrite); } //// // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile CreateFromFile(String path, FileMode mode, String mapName, Int64 capacity, MemoryMappedFileAccess access) { if (path == null) { throw new ArgumentNullException("path"); } if (mapName != null && mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (capacity < 0) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_PositiveOrDefaultCapacityRequired)); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException("access"); } if (mode == FileMode.Append) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFAppendModeNotAllowed), "mode"); } if (access == MemoryMappedFileAccess.Write) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFWriteAccessNotAllowed), "access"); } bool existed = File.Exists(path); FileStream fileStream = new FileStream(path, mode, GetFileStreamFileSystemRights(access), FileShare.None, 0x1000, FileOptions.None); if (capacity == 0 && fileStream.Length == 0) { CleanupFile(fileStream, existed, path); throw new ArgumentException(SR.GetString(SR.Argument_EmptyFile)); } if (access == MemoryMappedFileAccess.Read && capacity > fileStream.Length) { CleanupFile(fileStream, existed, path); throw new ArgumentException(SR.GetString(SR.Argument_ReadAccessWithLargeCapacity)); } if (capacity == DefaultSize) { capacity = fileStream.Length; } // one can always create a small view if they do not want to map an entire file if (fileStream.Length > capacity) { CleanupFile(fileStream, existed, path); throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_CapacityGEFileSizeRequired)); } SafeMemoryMappedFileHandle handle = null; try { handle = CreateCore(fileStream.SafeFileHandle, mapName, HandleInheritability.None, null, access, MemoryMappedFileOptions.None, capacity); } catch { CleanupFile(fileStream, existed, path); throw; } Debug.Assert(handle != null && !handle.IsInvalid); return new MemoryMappedFile(handle, fileStream, false); } //// // // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile CreateFromFile(FileStream fileStream, String mapName, Int64 capacity, MemoryMappedFileAccess access, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability, bool leaveOpen) { if (fileStream == null) { throw new ArgumentNullException("fileStream", SR.GetString(SR.ArgumentNull_FileStream)); } if (mapName != null && mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (capacity < 0) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_PositiveOrDefaultCapacityRequired)); } if (capacity == 0 && fileStream.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_EmptyFile)); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException("access"); } if (access == MemoryMappedFileAccess.Write) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFWriteAccessNotAllowed), "access"); } if (access == MemoryMappedFileAccess.Read && capacity > fileStream.Length) { throw new ArgumentException(SR.GetString(SR.Argument_ReadAccessWithLargeCapacity)); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability"); } // flush any bytes written to the FileStream buffer so that we can see them in our MemoryMappedFile fileStream.Flush(); if (capacity == DefaultSize) { capacity = fileStream.Length; } // one can always create a small view if they do not want to map an entire file if (fileStream.Length > capacity) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_CapacityGEFileSizeRequired)); } SafeMemoryMappedFileHandle handle = CreateCore(fileStream.SafeFileHandle, mapName, inheritability, memoryMappedFileSecurity, access, MemoryMappedFileOptions.None, capacity); return new MemoryMappedFile(handle, fileStream, leaveOpen); } // Factory Method Group #3: Creates a new empty memory mapped file. Such memory mapped files are ideal // for IPC, when mapName != null. public static MemoryMappedFile CreateNew(String mapName, Int64 capacity) { return CreateNew(mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, null, HandleInheritability.None); } public static MemoryMappedFile CreateNew(String mapName, Int64 capacity, MemoryMappedFileAccess access) { return CreateNew(mapName, capacity, access, MemoryMappedFileOptions.None, null, HandleInheritability.None); } //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile CreateNew(String mapName, Int64 capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability) { if (mapName != null && mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_NeedPositiveNumber)); } if (IntPtr.Size == 4 && capacity > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException("access"); } if (access == MemoryMappedFileAccess.Write) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFWriteAccessNotAllowed), "access"); } if (((int)options & ~((int)(MemoryMappedFileOptions.DelayAllocatePages ))) != 0) { throw new ArgumentOutOfRangeException("options"); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability"); } SafeMemoryMappedFileHandle handle = CreateCore(new SafeFileHandle(new IntPtr(-1), true), mapName, inheritability, memoryMappedFileSecurity, access, options, capacity); return new MemoryMappedFile(handle); } // Factory Method Group #4: Creates a new empty memory mapped file or opens an existing // memory mapped file if one exists with the same name. The capacity, options, and // memoryMappedFileSecurity arguments will be ignored in the case of the later. // This is ideal for P2P style IPC. public static MemoryMappedFile CreateOrOpen(String mapName, Int64 capacity) { return CreateOrOpen(mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, null, HandleInheritability.None); } public static MemoryMappedFile CreateOrOpen(String mapName, Int64 capacity, MemoryMappedFileAccess access) { return CreateOrOpen(mapName, capacity, access, MemoryMappedFileOptions.None, null, HandleInheritability.None); } //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile CreateOrOpen(String mapName, Int64 capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability) { if (mapName == null) { throw new ArgumentNullException("mapName", SR.GetString(SR.ArgumentNull_MapName)); } if (mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_NeedPositiveNumber)); } if (IntPtr.Size == 4 && capacity > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException("access"); } if (((int)options & ~((int)(MemoryMappedFileOptions.DelayAllocatePages))) != 0) { throw new ArgumentOutOfRangeException("options"); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability"); } SafeMemoryMappedFileHandle handle; // special case for write access; create will never succeed if (access == MemoryMappedFileAccess.Write) { handle = OpenCore(mapName, inheritability, GetFileMapAccess(access), true); } else { handle = CreateOrOpenCore(new SafeFileHandle(new IntPtr(-1), true), mapName, inheritability, memoryMappedFileSecurity, access, options, capacity); } return new MemoryMappedFile(handle); } // Used by the 2 Create factory method groups. A -1 fileHandle specifies that the // memory mapped file should not be associated with an exsiting file on disk (ie start // out empty). //// // // // // [System.Security.SecurityCritical] private static SafeMemoryMappedFileHandle CreateCore(SafeFileHandle fileHandle, String mapName, HandleInheritability inheritability, MemoryMappedFileSecurity memoryMappedFileSecurity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, Int64 capacity) { SafeMemoryMappedFileHandle handle = null; Object pinningHandle; UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability, memoryMappedFileSecurity, out pinningHandle); // split the long into two ints Int32 capacityLow = (Int32)(capacity & 0x00000000FFFFFFFFL); Int32 capacityHigh = (Int32)(capacity >> 32); try { handle = UnsafeNativeMethods.CreateFileMapping(fileHandle, secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName); Int32 errorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid && errorCode == UnsafeNativeMethods.ERROR_ALREADY_EXISTS) { handle.Dispose(); __Error.WinIOError(errorCode, String.Empty); } else if (handle.IsInvalid) { __Error.WinIOError(errorCode, String.Empty); } } finally { if (pinningHandle != null) { GCHandle pinHandle = (GCHandle)pinningHandle; pinHandle.Free(); } } return handle; } // Used by the OpenExisting factory method group and by CreateOrOpen if access is write. // We'll throw an ArgumentException if the file mapping object didn't exist and the // caller used CreateOrOpen since Create isn't valid with Write access //// // // // // // // // [System.Security.SecurityCritical] private static SafeMemoryMappedFileHandle OpenCore(String mapName, HandleInheritability inheritability, int desiredAccessRights, bool createOrOpen) { SafeMemoryMappedFileHandle handle = UnsafeNativeMethods.OpenFileMapping(desiredAccessRights, (inheritability & HandleInheritability.Inheritable) != 0, mapName); Int32 lastError = Marshal.GetLastWin32Error(); if (handle.IsInvalid) { if (createOrOpen && (lastError == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND)) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFWriteAccessNotAllowed), "access"); } else { __Error.WinIOError(lastError, String.Empty); } } return handle; } // Used by the CreateOrOpen factory method groups. A -1 fileHandle specifies that the // memory mapped file should not be associated with an existing file on disk (ie start // out empty). // // Try to open the file if it exists -- this requires a bit more work. Loop until we can // either create or open a memory mapped file up to a timeout. CreateFileMapping may fail // if the file exists and we have non-null security attributes, in which case we need to // use OpenFileMapping. But, there exists a race condition because the memory mapped file // may have closed inbetween the two calls -- hence the loop. // // This uses similar retry/timeout logic as in performance counter. It increases the wait // time each pass through the loop and times out in approximately 1.4 minutes. If after // retrying, a MMF handle still hasn't been opened, throw an InvalidOperationException. // //// // // // // [System.Security.SecurityCritical] private static SafeMemoryMappedFileHandle CreateOrOpenCore(SafeFileHandle fileHandle, String mapName, HandleInheritability inheritability, MemoryMappedFileSecurity memoryMappedFileSecurity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, Int64 capacity) { Debug.Assert(access != MemoryMappedFileAccess.Write, "Callers requesting write access shouldn't try to create a mmf"); SafeMemoryMappedFileHandle handle = null; Object pinningHandle; UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability, memoryMappedFileSecurity, out pinningHandle); // split the long into two ints Int32 capacityLow = (Int32)(capacity & 0x00000000FFFFFFFFL); Int32 capacityHigh = (Int32)(capacity >> 32); try { int waitRetries = 14; //((2^13)-1)*10ms == approximately 1.4mins int waitSleep = 0; // keep looping until we've exhausted retries or break as soon we we get valid handle while (waitRetries > 0) { // try to create handle = UnsafeNativeMethods.CreateFileMapping(fileHandle, secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName); Int32 createErrorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid) { break; } else { if (createErrorCode != UnsafeNativeMethods.ERROR_ACCESS_DENIED) { __Error.WinIOError(createErrorCode, String.Empty); } // the mapname exists but our ACL is preventing us from opening it with CreateFileMapping. // Let's try to open it with OpenFileMapping. handle.SetHandleAsInvalid(); } // try to open handle = UnsafeNativeMethods.OpenFileMapping(GetFileMapAccess(access), (inheritability & HandleInheritability.Inheritable) != 0, mapName); Int32 openErrorCode = Marshal.GetLastWin32Error(); // valid handle if (!handle.IsInvalid) { break; } // didn't get valid handle; have to retry else { if (openErrorCode != UnsafeNativeMethods.ERROR_FILE_NOT_FOUND) { __Error.WinIOError(openErrorCode, String.Empty); } // increase wait time --waitRetries; if (waitSleep == 0) { waitSleep = 10; } else { System.Threading.Thread.Sleep(waitSleep); waitSleep *= 2; } } } // finished retrying but couldn't create or open if (handle == null || handle.IsInvalid) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_CantCreateFileMapping)); } } finally { if (pinningHandle != null) { GCHandle pinHandle = (GCHandle)pinningHandle; pinHandle.Free(); } } return handle; } // Creates a new view in the form of a stream. public MemoryMappedViewStream CreateViewStream() { return CreateViewStream(0, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public MemoryMappedViewStream CreateViewStream(Int64 offset, Int64 size) { return CreateViewStream(offset, size, MemoryMappedFileAccess.ReadWrite); } //// // // // // // // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] 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); } // Creates a new view in the form of an accessor. Accessors are for random access. public MemoryMappedViewAccessor CreateViewAccessor() { return CreateViewAccessor(0, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public MemoryMappedViewAccessor CreateViewAccessor(Int64 offset, Int64 size) { return CreateViewAccessor(offset, size, MemoryMappedFileAccess.ReadWrite); } //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public MemoryMappedViewAccessor CreateViewAccessor(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 MemoryMappedViewAccessor(view); } //// // // // [System.Security.SecurityCritical] public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } //// // [System.Security.SecurityCritical] protected virtual void Dispose(bool disposing) { try { if (_handle != null && !_handle.IsClosed) { _handle.Dispose(); } } finally { if (_fileStream != null && _leaveOpen == false) { _fileStream.Dispose(); } } } public SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle { //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] get { return _handle; } } //// // [System.Security.SecurityCritical] public MemoryMappedFileSecurity GetAccessControl() { if (_handle.IsClosed) { __Error.FileNotOpen(); } return new MemoryMappedFileSecurity(_handle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] //// // // [System.Security.SecurityCritical] public void SetAccessControl(MemoryMappedFileSecurity memoryMappedFileSecurity) { if (memoryMappedFileSecurity == null) { throw new ArgumentNullException("memoryMappedFileSecurity"); } if (_handle.IsClosed) { __Error.FileNotOpen(); } memoryMappedFileSecurity.PersistHandle(_handle); } // We don't need to expose this now that we have created views that can start at any address. //// // // [System.Security.SecurityCritical] internal static Int32 GetSystemPageAllocationGranularity() { UnsafeNativeMethods.SYSTEM_INFO info = new UnsafeNativeMethods.SYSTEM_INFO(); UnsafeNativeMethods.GetSystemInfo(ref info); return info.dwAllocationGranularity; } // This converts a MemoryMappedFileAccess to it's corresponding native PAGE_XXX value to be used by the // factory methods that construct a new memory mapped file object. MemoryMappedFileAccess.Write is not // valid here since there is no corresponding PAGE_XXX value. internal static Int32 GetPageAccess(MemoryMappedFileAccess access) { if (access == MemoryMappedFileAccess.Read) { return UnsafeNativeMethods.PAGE_READONLY; } else if (access == MemoryMappedFileAccess.ReadWrite) { return UnsafeNativeMethods.PAGE_READWRITE; } else if (access == MemoryMappedFileAccess.CopyOnWrite) { return UnsafeNativeMethods.PAGE_WRITECOPY; } else if (access == MemoryMappedFileAccess.ReadExecute) { return UnsafeNativeMethods.PAGE_EXECUTE_READ; } else if (access == MemoryMappedFileAccess.ReadWriteExecute) { return UnsafeNativeMethods.PAGE_EXECUTE_READWRITE; } // If we reached here, access was invalid. throw new ArgumentOutOfRangeException("access"); } // This converts a MemoryMappedFileAccess to its corresponding native FILE_MAP_XXX value to be used when // creating new views. internal static Int32 GetFileMapAccess(MemoryMappedFileAccess access) { if (access == MemoryMappedFileAccess.Read) { return UnsafeNativeMethods.FILE_MAP_READ; } else if (access == MemoryMappedFileAccess.Write) { return UnsafeNativeMethods.FILE_MAP_WRITE; } else if (access == MemoryMappedFileAccess.ReadWrite) { return UnsafeNativeMethods.FILE_MAP_READ | UnsafeNativeMethods.FILE_MAP_WRITE; } else if (access == MemoryMappedFileAccess.CopyOnWrite) { return UnsafeNativeMethods.FILE_MAP_COPY; } else if (access == MemoryMappedFileAccess.ReadExecute) { return UnsafeNativeMethods.FILE_MAP_EXECUTE | UnsafeNativeMethods.FILE_MAP_READ; } else if (access == MemoryMappedFileAccess.ReadWriteExecute) { return UnsafeNativeMethods.FILE_MAP_EXECUTE | UnsafeNativeMethods.FILE_MAP_READ | UnsafeNativeMethods.FILE_MAP_WRITE; } // If we reached here, access was invalid. throw new ArgumentOutOfRangeException("access"); } // This converts a MemoryMappedFileAccess to a FileSystemRights for use by FileStream private static FileSystemRights GetFileStreamFileSystemRights(MemoryMappedFileAccess access) { switch (access) { case MemoryMappedFileAccess.Read: case MemoryMappedFileAccess.CopyOnWrite: return FileSystemRights.ReadData; case MemoryMappedFileAccess.ReadWrite: return FileSystemRights.ReadData | FileSystemRights.WriteData; case MemoryMappedFileAccess.Write: return FileSystemRights.WriteData; case MemoryMappedFileAccess.ReadExecute: return FileSystemRights.ReadData | FileSystemRights.ExecuteFile; case MemoryMappedFileAccess.ReadWriteExecute: return FileSystemRights.ReadData | FileSystemRights.WriteData | FileSystemRights.ExecuteFile; default: // If we reached here, access was invalid. throw new ArgumentOutOfRangeException("access"); } } // 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"); } // Helper method used to extract the native binary security descriptor from the MemoryMappedFileSecurity // type. If pinningHandle is not null, caller must free it AFTER the call to CreateFile has returned. //// // [System.Security.SecurityCritical] private unsafe static UnsafeNativeMethods.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability, MemoryMappedFileSecurity memoryMappedFileSecurity, out Object pinningHandle) { pinningHandle = null; UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = null; if ((inheritability & HandleInheritability.Inheritable) != 0 || memoryMappedFileSecurity != null) { secAttrs = new UnsafeNativeMethods.SECURITY_ATTRIBUTES(); secAttrs.nLength = (Int32)Marshal.SizeOf(secAttrs); if ((inheritability & HandleInheritability.Inheritable) != 0) { secAttrs.bInheritHandle = 1; } // For ACLs, get the security descriptor from the MemoryMappedFileSecurity. if (memoryMappedFileSecurity != null) { byte[] sd = memoryMappedFileSecurity.GetSecurityDescriptorBinaryForm(); pinningHandle = GCHandle.Alloc(sd, GCHandleType.Pinned); fixed (byte* pSecDescriptor = sd) secAttrs.pSecurityDescriptor = pSecDescriptor; } } return secAttrs; } // clean up: close file handle and delete files we created private static void CleanupFile(FileStream fileStream, bool existed, String path) { fileStream.Close(); if (!existed) { File.Delete(path); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Class: MemoryMappedFile ** ** Purpose: Managed MemoryMappedFiles. ** ** Date: February 7, 2007 ** ===========================================================*/ using System; using System.Diagnostics; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.AccessControl; using System.Security.Permissions; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; namespace System.IO.MemoryMappedFiles { public class MemoryMappedFile : IDisposable { private SafeMemoryMappedFileHandle _handle; private bool _leaveOpen; private FileStream _fileStream; internal const int DefaultSize = 0; // Private constructors to be used by the factory methods. //// // // // // [System.Security.SecurityCritical] 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. } //// // // // [System.Security.SecurityCritical] 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; } // Factory Method Group #1: Opens an existing named memory mapped file. The native OpenFileMapping call // will check the desiredAccessRights against the ACL on the memory mapped file. Note that a memory // mapped file created without an ACL will use a default ACL taken from the primary or impersonation token // of the creator. On my machine, I always get ReadWrite access to it so I never have to use anything but // the first override of this method. Note: having ReadWrite access to the object does not mean that we // have ReadWrite access to the pages mapping the file. The OS will check against the access on the pages // when a view is created. public static MemoryMappedFile OpenExisting(string mapName) { return OpenExisting(mapName, MemoryMappedFileRights.ReadWrite, HandleInheritability.None); } public static MemoryMappedFile OpenExisting(string mapName, MemoryMappedFileRights desiredAccessRights) { return OpenExisting(mapName, desiredAccessRights, HandleInheritability.None); } //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile OpenExisting(string mapName, MemoryMappedFileRights desiredAccessRights, HandleInheritability inheritability) { if (mapName == null) { throw new ArgumentNullException("mapName", SR.GetString(SR.ArgumentNull_MapName)); } if (mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability"); } if (((int)desiredAccessRights & ~((int)(MemoryMappedFileRights.FullControl | MemoryMappedFileRights.AccessSystemSecurity))) != 0) { throw new ArgumentOutOfRangeException("desiredAccessRights"); } SafeMemoryMappedFileHandle handle = OpenCore(mapName, inheritability, (int)desiredAccessRights, false); return new MemoryMappedFile(handle); } // Factory Method Group #2: Creates a new memory mapped file where the content is taken from an existing // file on disk. This file must be opened by a FileStream before given to us. Specifying DefaultSize to // the capacity will make the capacity of the memory mapped file match the size of the file. Specifying // a value larger than the size of the file will enlarge the new file to this size. Note that in such a // case, the capacity (and there for the size of the file) will be rounded up to a multiple of the system // page size. One can use FileStream.SetLength to bring the length back to a desirable size. By default, // the MemoryMappedFile will close the FileStream object when it is disposed. This behavior can be // changed by the leaveOpen boolean argument. public static MemoryMappedFile CreateFromFile(String path) { return CreateFromFile(path, FileMode.Open, null, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public static MemoryMappedFile CreateFromFile(String path, FileMode mode) { return CreateFromFile(path, mode, null, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public static MemoryMappedFile CreateFromFile(String path, FileMode mode, String mapName) { return CreateFromFile(path, mode, mapName, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public static MemoryMappedFile CreateFromFile(String path, FileMode mode, String mapName, Int64 capacity) { return CreateFromFile(path, mode, mapName, capacity, MemoryMappedFileAccess.ReadWrite); } //// // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile CreateFromFile(String path, FileMode mode, String mapName, Int64 capacity, MemoryMappedFileAccess access) { if (path == null) { throw new ArgumentNullException("path"); } if (mapName != null && mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (capacity < 0) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_PositiveOrDefaultCapacityRequired)); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException("access"); } if (mode == FileMode.Append) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFAppendModeNotAllowed), "mode"); } if (access == MemoryMappedFileAccess.Write) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFWriteAccessNotAllowed), "access"); } bool existed = File.Exists(path); FileStream fileStream = new FileStream(path, mode, GetFileStreamFileSystemRights(access), FileShare.None, 0x1000, FileOptions.None); if (capacity == 0 && fileStream.Length == 0) { CleanupFile(fileStream, existed, path); throw new ArgumentException(SR.GetString(SR.Argument_EmptyFile)); } if (access == MemoryMappedFileAccess.Read && capacity > fileStream.Length) { CleanupFile(fileStream, existed, path); throw new ArgumentException(SR.GetString(SR.Argument_ReadAccessWithLargeCapacity)); } if (capacity == DefaultSize) { capacity = fileStream.Length; } // one can always create a small view if they do not want to map an entire file if (fileStream.Length > capacity) { CleanupFile(fileStream, existed, path); throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_CapacityGEFileSizeRequired)); } SafeMemoryMappedFileHandle handle = null; try { handle = CreateCore(fileStream.SafeFileHandle, mapName, HandleInheritability.None, null, access, MemoryMappedFileOptions.None, capacity); } catch { CleanupFile(fileStream, existed, path); throw; } Debug.Assert(handle != null && !handle.IsInvalid); return new MemoryMappedFile(handle, fileStream, false); } //// // // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile CreateFromFile(FileStream fileStream, String mapName, Int64 capacity, MemoryMappedFileAccess access, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability, bool leaveOpen) { if (fileStream == null) { throw new ArgumentNullException("fileStream", SR.GetString(SR.ArgumentNull_FileStream)); } if (mapName != null && mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (capacity < 0) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_PositiveOrDefaultCapacityRequired)); } if (capacity == 0 && fileStream.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_EmptyFile)); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException("access"); } if (access == MemoryMappedFileAccess.Write) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFWriteAccessNotAllowed), "access"); } if (access == MemoryMappedFileAccess.Read && capacity > fileStream.Length) { throw new ArgumentException(SR.GetString(SR.Argument_ReadAccessWithLargeCapacity)); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability"); } // flush any bytes written to the FileStream buffer so that we can see them in our MemoryMappedFile fileStream.Flush(); if (capacity == DefaultSize) { capacity = fileStream.Length; } // one can always create a small view if they do not want to map an entire file if (fileStream.Length > capacity) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_CapacityGEFileSizeRequired)); } SafeMemoryMappedFileHandle handle = CreateCore(fileStream.SafeFileHandle, mapName, inheritability, memoryMappedFileSecurity, access, MemoryMappedFileOptions.None, capacity); return new MemoryMappedFile(handle, fileStream, leaveOpen); } // Factory Method Group #3: Creates a new empty memory mapped file. Such memory mapped files are ideal // for IPC, when mapName != null. public static MemoryMappedFile CreateNew(String mapName, Int64 capacity) { return CreateNew(mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, null, HandleInheritability.None); } public static MemoryMappedFile CreateNew(String mapName, Int64 capacity, MemoryMappedFileAccess access) { return CreateNew(mapName, capacity, access, MemoryMappedFileOptions.None, null, HandleInheritability.None); } //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile CreateNew(String mapName, Int64 capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability) { if (mapName != null && mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_NeedPositiveNumber)); } if (IntPtr.Size == 4 && capacity > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException("access"); } if (access == MemoryMappedFileAccess.Write) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFWriteAccessNotAllowed), "access"); } if (((int)options & ~((int)(MemoryMappedFileOptions.DelayAllocatePages ))) != 0) { throw new ArgumentOutOfRangeException("options"); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability"); } SafeMemoryMappedFileHandle handle = CreateCore(new SafeFileHandle(new IntPtr(-1), true), mapName, inheritability, memoryMappedFileSecurity, access, options, capacity); return new MemoryMappedFile(handle); } // Factory Method Group #4: Creates a new empty memory mapped file or opens an existing // memory mapped file if one exists with the same name. The capacity, options, and // memoryMappedFileSecurity arguments will be ignored in the case of the later. // This is ideal for P2P style IPC. public static MemoryMappedFile CreateOrOpen(String mapName, Int64 capacity) { return CreateOrOpen(mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, null, HandleInheritability.None); } public static MemoryMappedFile CreateOrOpen(String mapName, Int64 capacity, MemoryMappedFileAccess access) { return CreateOrOpen(mapName, capacity, access, MemoryMappedFileOptions.None, null, HandleInheritability.None); } //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static MemoryMappedFile CreateOrOpen(String mapName, Int64 capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability) { if (mapName == null) { throw new ArgumentNullException("mapName", SR.GetString(SR.ArgumentNull_MapName)); } if (mapName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_MapNameEmptyString)); } if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_NeedPositiveNumber)); } if (IntPtr.Size == 4 && capacity > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("capacity", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); } if (access < MemoryMappedFileAccess.ReadWrite || access > MemoryMappedFileAccess.ReadWriteExecute) { throw new ArgumentOutOfRangeException("access"); } if (((int)options & ~((int)(MemoryMappedFileOptions.DelayAllocatePages))) != 0) { throw new ArgumentOutOfRangeException("options"); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability"); } SafeMemoryMappedFileHandle handle; // special case for write access; create will never succeed if (access == MemoryMappedFileAccess.Write) { handle = OpenCore(mapName, inheritability, GetFileMapAccess(access), true); } else { handle = CreateOrOpenCore(new SafeFileHandle(new IntPtr(-1), true), mapName, inheritability, memoryMappedFileSecurity, access, options, capacity); } return new MemoryMappedFile(handle); } // Used by the 2 Create factory method groups. A -1 fileHandle specifies that the // memory mapped file should not be associated with an exsiting file on disk (ie start // out empty). //// // // // // [System.Security.SecurityCritical] private static SafeMemoryMappedFileHandle CreateCore(SafeFileHandle fileHandle, String mapName, HandleInheritability inheritability, MemoryMappedFileSecurity memoryMappedFileSecurity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, Int64 capacity) { SafeMemoryMappedFileHandle handle = null; Object pinningHandle; UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability, memoryMappedFileSecurity, out pinningHandle); // split the long into two ints Int32 capacityLow = (Int32)(capacity & 0x00000000FFFFFFFFL); Int32 capacityHigh = (Int32)(capacity >> 32); try { handle = UnsafeNativeMethods.CreateFileMapping(fileHandle, secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName); Int32 errorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid && errorCode == UnsafeNativeMethods.ERROR_ALREADY_EXISTS) { handle.Dispose(); __Error.WinIOError(errorCode, String.Empty); } else if (handle.IsInvalid) { __Error.WinIOError(errorCode, String.Empty); } } finally { if (pinningHandle != null) { GCHandle pinHandle = (GCHandle)pinningHandle; pinHandle.Free(); } } return handle; } // Used by the OpenExisting factory method group and by CreateOrOpen if access is write. // We'll throw an ArgumentException if the file mapping object didn't exist and the // caller used CreateOrOpen since Create isn't valid with Write access //// // // // // // // // [System.Security.SecurityCritical] private static SafeMemoryMappedFileHandle OpenCore(String mapName, HandleInheritability inheritability, int desiredAccessRights, bool createOrOpen) { SafeMemoryMappedFileHandle handle = UnsafeNativeMethods.OpenFileMapping(desiredAccessRights, (inheritability & HandleInheritability.Inheritable) != 0, mapName); Int32 lastError = Marshal.GetLastWin32Error(); if (handle.IsInvalid) { if (createOrOpen && (lastError == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND)) { throw new ArgumentException(SR.GetString(SR.Argument_NewMMFWriteAccessNotAllowed), "access"); } else { __Error.WinIOError(lastError, String.Empty); } } return handle; } // Used by the CreateOrOpen factory method groups. A -1 fileHandle specifies that the // memory mapped file should not be associated with an existing file on disk (ie start // out empty). // // Try to open the file if it exists -- this requires a bit more work. Loop until we can // either create or open a memory mapped file up to a timeout. CreateFileMapping may fail // if the file exists and we have non-null security attributes, in which case we need to // use OpenFileMapping. But, there exists a race condition because the memory mapped file // may have closed inbetween the two calls -- hence the loop. // // This uses similar retry/timeout logic as in performance counter. It increases the wait // time each pass through the loop and times out in approximately 1.4 minutes. If after // retrying, a MMF handle still hasn't been opened, throw an InvalidOperationException. // //// // // // // [System.Security.SecurityCritical] private static SafeMemoryMappedFileHandle CreateOrOpenCore(SafeFileHandle fileHandle, String mapName, HandleInheritability inheritability, MemoryMappedFileSecurity memoryMappedFileSecurity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, Int64 capacity) { Debug.Assert(access != MemoryMappedFileAccess.Write, "Callers requesting write access shouldn't try to create a mmf"); SafeMemoryMappedFileHandle handle = null; Object pinningHandle; UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability, memoryMappedFileSecurity, out pinningHandle); // split the long into two ints Int32 capacityLow = (Int32)(capacity & 0x00000000FFFFFFFFL); Int32 capacityHigh = (Int32)(capacity >> 32); try { int waitRetries = 14; //((2^13)-1)*10ms == approximately 1.4mins int waitSleep = 0; // keep looping until we've exhausted retries or break as soon we we get valid handle while (waitRetries > 0) { // try to create handle = UnsafeNativeMethods.CreateFileMapping(fileHandle, secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName); Int32 createErrorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid) { break; } else { if (createErrorCode != UnsafeNativeMethods.ERROR_ACCESS_DENIED) { __Error.WinIOError(createErrorCode, String.Empty); } // the mapname exists but our ACL is preventing us from opening it with CreateFileMapping. // Let's try to open it with OpenFileMapping. handle.SetHandleAsInvalid(); } // try to open handle = UnsafeNativeMethods.OpenFileMapping(GetFileMapAccess(access), (inheritability & HandleInheritability.Inheritable) != 0, mapName); Int32 openErrorCode = Marshal.GetLastWin32Error(); // valid handle if (!handle.IsInvalid) { break; } // didn't get valid handle; have to retry else { if (openErrorCode != UnsafeNativeMethods.ERROR_FILE_NOT_FOUND) { __Error.WinIOError(openErrorCode, String.Empty); } // increase wait time --waitRetries; if (waitSleep == 0) { waitSleep = 10; } else { System.Threading.Thread.Sleep(waitSleep); waitSleep *= 2; } } } // finished retrying but couldn't create or open if (handle == null || handle.IsInvalid) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_CantCreateFileMapping)); } } finally { if (pinningHandle != null) { GCHandle pinHandle = (GCHandle)pinningHandle; pinHandle.Free(); } } return handle; } // Creates a new view in the form of a stream. public MemoryMappedViewStream CreateViewStream() { return CreateViewStream(0, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public MemoryMappedViewStream CreateViewStream(Int64 offset, Int64 size) { return CreateViewStream(offset, size, MemoryMappedFileAccess.ReadWrite); } //// // // // // // // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] 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); } // Creates a new view in the form of an accessor. Accessors are for random access. public MemoryMappedViewAccessor CreateViewAccessor() { return CreateViewAccessor(0, DefaultSize, MemoryMappedFileAccess.ReadWrite); } public MemoryMappedViewAccessor CreateViewAccessor(Int64 offset, Int64 size) { return CreateViewAccessor(offset, size, MemoryMappedFileAccess.ReadWrite); } //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public MemoryMappedViewAccessor CreateViewAccessor(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 MemoryMappedViewAccessor(view); } //// // // // [System.Security.SecurityCritical] public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } //// // [System.Security.SecurityCritical] protected virtual void Dispose(bool disposing) { try { if (_handle != null && !_handle.IsClosed) { _handle.Dispose(); } } finally { if (_fileStream != null && _leaveOpen == false) { _fileStream.Dispose(); } } } public SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle { //// // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] get { return _handle; } } //// // [System.Security.SecurityCritical] public MemoryMappedFileSecurity GetAccessControl() { if (_handle.IsClosed) { __Error.FileNotOpen(); } return new MemoryMappedFileSecurity(_handle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] //// // // [System.Security.SecurityCritical] public void SetAccessControl(MemoryMappedFileSecurity memoryMappedFileSecurity) { if (memoryMappedFileSecurity == null) { throw new ArgumentNullException("memoryMappedFileSecurity"); } if (_handle.IsClosed) { __Error.FileNotOpen(); } memoryMappedFileSecurity.PersistHandle(_handle); } // We don't need to expose this now that we have created views that can start at any address. //// // // [System.Security.SecurityCritical] internal static Int32 GetSystemPageAllocationGranularity() { UnsafeNativeMethods.SYSTEM_INFO info = new UnsafeNativeMethods.SYSTEM_INFO(); UnsafeNativeMethods.GetSystemInfo(ref info); return info.dwAllocationGranularity; } // This converts a MemoryMappedFileAccess to it's corresponding native PAGE_XXX value to be used by the // factory methods that construct a new memory mapped file object. MemoryMappedFileAccess.Write is not // valid here since there is no corresponding PAGE_XXX value. internal static Int32 GetPageAccess(MemoryMappedFileAccess access) { if (access == MemoryMappedFileAccess.Read) { return UnsafeNativeMethods.PAGE_READONLY; } else if (access == MemoryMappedFileAccess.ReadWrite) { return UnsafeNativeMethods.PAGE_READWRITE; } else if (access == MemoryMappedFileAccess.CopyOnWrite) { return UnsafeNativeMethods.PAGE_WRITECOPY; } else if (access == MemoryMappedFileAccess.ReadExecute) { return UnsafeNativeMethods.PAGE_EXECUTE_READ; } else if (access == MemoryMappedFileAccess.ReadWriteExecute) { return UnsafeNativeMethods.PAGE_EXECUTE_READWRITE; } // If we reached here, access was invalid. throw new ArgumentOutOfRangeException("access"); } // This converts a MemoryMappedFileAccess to its corresponding native FILE_MAP_XXX value to be used when // creating new views. internal static Int32 GetFileMapAccess(MemoryMappedFileAccess access) { if (access == MemoryMappedFileAccess.Read) { return UnsafeNativeMethods.FILE_MAP_READ; } else if (access == MemoryMappedFileAccess.Write) { return UnsafeNativeMethods.FILE_MAP_WRITE; } else if (access == MemoryMappedFileAccess.ReadWrite) { return UnsafeNativeMethods.FILE_MAP_READ | UnsafeNativeMethods.FILE_MAP_WRITE; } else if (access == MemoryMappedFileAccess.CopyOnWrite) { return UnsafeNativeMethods.FILE_MAP_COPY; } else if (access == MemoryMappedFileAccess.ReadExecute) { return UnsafeNativeMethods.FILE_MAP_EXECUTE | UnsafeNativeMethods.FILE_MAP_READ; } else if (access == MemoryMappedFileAccess.ReadWriteExecute) { return UnsafeNativeMethods.FILE_MAP_EXECUTE | UnsafeNativeMethods.FILE_MAP_READ | UnsafeNativeMethods.FILE_MAP_WRITE; } // If we reached here, access was invalid. throw new ArgumentOutOfRangeException("access"); } // This converts a MemoryMappedFileAccess to a FileSystemRights for use by FileStream private static FileSystemRights GetFileStreamFileSystemRights(MemoryMappedFileAccess access) { switch (access) { case MemoryMappedFileAccess.Read: case MemoryMappedFileAccess.CopyOnWrite: return FileSystemRights.ReadData; case MemoryMappedFileAccess.ReadWrite: return FileSystemRights.ReadData | FileSystemRights.WriteData; case MemoryMappedFileAccess.Write: return FileSystemRights.WriteData; case MemoryMappedFileAccess.ReadExecute: return FileSystemRights.ReadData | FileSystemRights.ExecuteFile; case MemoryMappedFileAccess.ReadWriteExecute: return FileSystemRights.ReadData | FileSystemRights.WriteData | FileSystemRights.ExecuteFile; default: // If we reached here, access was invalid. throw new ArgumentOutOfRangeException("access"); } } // 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"); } // Helper method used to extract the native binary security descriptor from the MemoryMappedFileSecurity // type. If pinningHandle is not null, caller must free it AFTER the call to CreateFile has returned. //// // [System.Security.SecurityCritical] private unsafe static UnsafeNativeMethods.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability, MemoryMappedFileSecurity memoryMappedFileSecurity, out Object pinningHandle) { pinningHandle = null; UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = null; if ((inheritability & HandleInheritability.Inheritable) != 0 || memoryMappedFileSecurity != null) { secAttrs = new UnsafeNativeMethods.SECURITY_ATTRIBUTES(); secAttrs.nLength = (Int32)Marshal.SizeOf(secAttrs); if ((inheritability & HandleInheritability.Inheritable) != 0) { secAttrs.bInheritHandle = 1; } // For ACLs, get the security descriptor from the MemoryMappedFileSecurity. if (memoryMappedFileSecurity != null) { byte[] sd = memoryMappedFileSecurity.GetSecurityDescriptorBinaryForm(); pinningHandle = GCHandle.Alloc(sd, GCHandleType.Pinned); fixed (byte* pSecDescriptor = sd) secAttrs.pSecurityDescriptor = pSecDescriptor; } } return secAttrs; } // clean up: close file handle and delete files we created private static void CleanupFile(FileStream fileStream, bool existed, String path) { fileStream.Close(); if (!existed) { File.Delete(path); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.// // // //
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AutoGeneratedField.cs
- PersonalizableTypeEntry.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- WebPartEditorCancelVerb.cs
- SchemaTypeEmitter.cs
- TextBoxBase.cs
- ColorDialog.cs
- ReflectionPermission.cs
- OpenTypeLayoutCache.cs
- Simplifier.cs
- WebPartAddingEventArgs.cs
- PaperSource.cs
- ColorMatrix.cs
- ListView.cs
- SQlBooleanStorage.cs
- NavigationProperty.cs
- XmlDomTextWriter.cs
- QueryableDataSourceView.cs
- TextTreeTextElementNode.cs
- HMACSHA384.cs
- designeractionbehavior.cs
- OrderedDictionaryStateHelper.cs
- SafeRightsManagementQueryHandle.cs
- FragmentQueryProcessor.cs
- ProfilePropertySettingsCollection.cs
- PagesSection.cs
- RelatedEnd.cs
- ConnectionPoint.cs
- Collection.cs
- FixedSchema.cs
- Point3DAnimationUsingKeyFrames.cs
- WorkflowTraceTransfer.cs
- GeometryDrawing.cs
- DependencyPropertyDescriptor.cs
- ExpressionPrefixAttribute.cs
- X509CertificateValidator.cs
- DisplayMemberTemplateSelector.cs
- RoleManagerModule.cs
- BrowserDefinition.cs
- ObsoleteAttribute.cs
- codemethodreferenceexpression.cs
- SystemDropShadowChrome.cs
- autovalidator.cs
- SiteMapDataSource.cs
- GeneratedContractType.cs
- TargetControlTypeAttribute.cs
- DrawingGroup.cs
- MergeLocalizationDirectives.cs
- DataGridRow.cs
- DocobjHost.cs
- ValueSerializerAttribute.cs
- TextDecorationCollectionConverter.cs
- DiscoveryClientElement.cs
- securitymgrsite.cs
- FreezableOperations.cs
- GeneralTransform.cs
- FocusManager.cs
- ResourceType.cs
- XslNumber.cs
- odbcmetadatafactory.cs
- BamlRecordHelper.cs
- Exceptions.cs
- PowerStatus.cs
- OleDbRowUpdatedEvent.cs
- PointConverter.cs
- ConfigurationSectionHelper.cs
- InstanceOwnerQueryResult.cs
- MobileUserControl.cs
- AbandonedMutexException.cs
- MatrixTransform3D.cs
- InstanceDataCollectionCollection.cs
- SQLInt64Storage.cs
- Membership.cs
- XmlILCommand.cs
- Vector3dCollection.cs
- XmlSerializationGeneratedCode.cs
- DateTimeValueSerializerContext.cs
- COM2ComponentEditor.cs
- OrderablePartitioner.cs
- DirectionalLight.cs
- HelpPage.cs
- Internal.cs
- DataGrid.cs
- ObjectListShowCommandsEventArgs.cs
- ProviderUtil.cs
- JapaneseLunisolarCalendar.cs
- WebPartConnectionsCancelVerb.cs
- _DomainName.cs
- SHA384CryptoServiceProvider.cs
- WebFaultException.cs
- cryptoapiTransform.cs
- EntityKey.cs
- WebBrowserContainer.cs
- ModelPropertyImpl.cs
- TypeToken.cs
- Int16Animation.cs
- WorkflowOperationInvoker.cs
- TimeSpanHelper.cs
- FilterQueryOptionExpression.cs
- TextEndOfLine.cs