Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #79187 Add MemoryMappedFile.CreateFromFile(SafeFileHandle) overload #83134

Merged
merged 18 commits into from
Mar 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public partial class MemoryMappedFile : System.IDisposable
internal MemoryMappedFile() { }
public Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle { get { throw null; } }
public static System.IO.MemoryMappedFiles.MemoryMappedFile CreateFromFile(System.IO.FileStream fileStream, string? mapName, long capacity, System.IO.MemoryMappedFiles.MemoryMappedFileAccess access, System.IO.HandleInheritability inheritability, bool leaveOpen) { throw null; }
public static System.IO.MemoryMappedFiles.MemoryMappedFile CreateFromFile(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, string? mapName, long capacity, System.IO.MemoryMappedFiles.MemoryMappedFileAccess access, System.IO.HandleInheritability inheritability, bool leaveOpen) { throw null; }
public static System.IO.MemoryMappedFiles.MemoryMappedFile CreateFromFile(string path) { throw null; }
public static System.IO.MemoryMappedFiles.MemoryMappedFile CreateFromFile(string path, System.IO.FileMode mode) { throw null; }
public static System.IO.MemoryMappedFiles.MemoryMappedFile CreateFromFile(string path, System.IO.FileMode mode, string? mapName) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,7 @@ public static MemoryMappedFile CreateFromFile(string path, FileMode mode, string
MemoryMappedFileAccess access)
{
ArgumentNullException.ThrowIfNull(path);

if (mapName != null && mapName.Length == 0)
{
throw new ArgumentException(SR.Argument_MapNameEmptyString);
}

if (capacity < 0)
{
throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_PositiveOrDefaultCapacityRequired);
}

if (access < MemoryMappedFileAccess.ReadWrite ||
access > MemoryMappedFileAccess.ReadWriteExecute)
{
throw new ArgumentOutOfRangeException(nameof(access));
}
ValidateCreateFile(mapName, capacity, access);

if (mode == FileMode.Append)
{
Expand All @@ -132,10 +117,6 @@ public static MemoryMappedFile CreateFromFile(string path, FileMode mode, string
{
throw new ArgumentException(SR.Argument_NewMMFTruncateModeNotAllowed, nameof(mode));
}
if (access == MemoryMappedFileAccess.Write)
{
throw new ArgumentException(SR.Argument_NewMMFWriteAccessNotAllowed, nameof(access));
}

bool existed = mode switch
{
Expand Down Expand Up @@ -186,37 +167,84 @@ public static MemoryMappedFile CreateFromFile(string path, FileMode mode, string
return new MemoryMappedFile(handle, fileHandle, false);
}

public static MemoryMappedFile CreateFromFile(FileStream fileStream, string? mapName, long capacity,
/// <summary>
/// Creates a memory-mapped file from an existing file using a <see cref="SafeFileHandle"/>,
/// and the specified access mode, name, inheritability, and capacity.
/// </summary>
/// <param name="fileHandle">The <see cref="SafeFileHandle"/> to the existing file. Caller is
/// responsible for disposing <paramref name="fileHandle"/> when <paramref name="leaveOpen"/> is <see langword="true" /> (otherwise,
/// automatically disposed by the <see cref="MemoryMappedFile"/>). </param>
/// <param name="mapName">A name to assign to the memory-mapped file, or <see langword="null" /> for a
/// <see cref="MemoryMappedFile"/> that you do not intend to share across processes.</param>
/// <param name="capacity">The maximum size, in bytes, to allocate to the memory-mapped file.
/// Specify 0 to set the capacity to the size of the file.</param>
/// <param name="access">One of the enumeration values that specifies the type of access allowed
/// to the memory-mapped file.
/// <para>This parameter can't be set to <see cref="MemoryMappedFileAccess.Write"/></para></param>
/// <param name="inheritability">One of the enumeration values that specifies whether a handle
/// to the memory-mapped file can be inherited by a child process. The default is <see cref="HandleInheritability.None"/>.</param>
/// <param name="leaveOpen">A value that indicates whether to close the source file handle when
/// the <see cref="MemoryMappedFile"/> is disposed.</param>
/// <returns>A memory-mapped file that has the specified characteristics.</returns>
/// <exception cref="ArgumentException">
/// <para><paramref name="mapName"/> is <see langword="null" /> or an empty string.</para>
/// <para>-or-</para>
/// <para><paramref name="capacity"/> and the length of the file are zero.</para>
/// <para>-or-</para>
/// <para><paramref name="access"/> is set to <see cref="MemoryMappedFileAccess.Write"/>, which is not allowed.</para>
/// <para>-or-</para>
/// <para><paramref name="access"/> is set to <see cref="MemoryMappedFileAccess.Read"/> and <paramref name="capacity"/> is larger than the length of the file.</para>
/// </exception>
/// <exception cref="ArgumentNullException"><paramref name="fileHandle"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <para><paramref name="capacity"/> is less than zero.</para>
/// <para>-or-</para>
/// <para><paramref name="capacity"/> is less than the file size.</para>
/// <para>-or-</para>
/// <para><paramref name="access"/> is not a valid <see cref="MemoryMappedFileAccess"/> enumeration value.</para>
/// <para>-or-</para>
/// <para><paramref name="inheritability"/> is not a valid <see cref="HandleInheritability"/> enumeration value.</para>
/// </exception>
public static MemoryMappedFile CreateFromFile(SafeFileHandle fileHandle, string? mapName, long capacity,
MemoryMappedFileAccess access,
HandleInheritability inheritability, bool leaveOpen)
{
ArgumentNullException.ThrowIfNull(fileStream);
ArgumentNullException.ThrowIfNull(fileHandle);
ValidateCreateFile(mapName, capacity, access);

if (mapName != null && mapName.Length == 0)
long fileSize = RandomAccess.GetLength(fileHandle);
if (capacity == 0 && fileSize == 0)
{
throw new ArgumentException(SR.Argument_MapNameEmptyString);
throw new ArgumentException(SR.Argument_EmptyFile);
}

if (capacity < 0)
if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable)
{
throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_PositiveOrDefaultCapacityRequired);
throw new ArgumentOutOfRangeException(nameof(inheritability));
}

long fileSize = fileStream.Length;
if (capacity == 0 && fileSize == 0)
if (capacity == DefaultSize)
{
throw new ArgumentException(SR.Argument_EmptyFile);
capacity = fileSize;
}

if (access < MemoryMappedFileAccess.ReadWrite ||
access > MemoryMappedFileAccess.ReadWriteExecute)
{
throw new ArgumentOutOfRangeException(nameof(access));
}
SafeMemoryMappedFileHandle handle = CreateCore(fileHandle, mapName, inheritability,
access, MemoryMappedFileOptions.None, capacity, fileSize);

if (access == MemoryMappedFileAccess.Write)
return new MemoryMappedFile(handle, fileHandle, leaveOpen);
}

public static MemoryMappedFile CreateFromFile(FileStream fileStream, string? mapName, long capacity,
MemoryMappedFileAccess access,
HandleInheritability inheritability, bool leaveOpen)
{
ArgumentNullException.ThrowIfNull(fileStream);
ValidateCreateFile(mapName, capacity, access);

long fileSize = fileStream.Length;
if (capacity == 0 && fileSize == 0)
{
throw new ArgumentException(SR.Argument_NewMMFWriteAccessNotAllowed, nameof(access));
throw new ArgumentException(SR.Argument_EmptyFile);
}

if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable)
Expand Down Expand Up @@ -483,5 +511,29 @@ private static void CleanupFile(SafeFileHandle fileHandle, bool existed, string
File.Delete(path);
}
}

private static void ValidateCreateFile(string? mapName, long capacity, MemoryMappedFileAccess access)
{
if (mapName != null && mapName.Length == 0)
{
throw new ArgumentException(SR.Argument_MapNameEmptyString);
}

if (capacity < 0)
{
throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_PositiveOrDefaultCapacityRequired);
}

if (access < MemoryMappedFileAccess.ReadWrite ||
access > MemoryMappedFileAccess.ReadWriteExecute)
{
throw new ArgumentOutOfRangeException(nameof(access));
}

if (access == MemoryMappedFileAccess.Write)
{
throw new ArgumentException(SR.Argument_NewMMFWriteAccessNotAllowed, nameof(access));
}
}
}
}
Loading