Virtu/Library/SafeFileHandle.cs

98 lines
3.5 KiB
C#
Raw Normal View History

using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.AccessControl;
using Microsoft.Win32.SafeHandles;
namespace Jellyfish.Library
{
[SecurityCritical]
public sealed class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public SafeFileHandle() :
base(ownsHandle: true)
{
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public SafeFileHandle(IntPtr existingHandle, bool ownsHandle) :
base(ownsHandle)
{
SetHandle(existingHandle);
}
[SecurityCritical]
public static SafeFileHandle CreateFile(string fileName, FileAccess fileAccess, FileShare fileShare, FileMode fileMode, GeneralSecurity fileSecurity)
{
if (fileMode == FileMode.Append)
{
throw new NotImplementedException();
}
bool inheritable = ((fileShare & FileShare.Inheritable) != 0);
fileShare &= ~FileShare.Inheritable;
return CreateFile(fileName, (uint)fileAccess, (uint)fileShare, (uint)fileMode, 0x0, fileSecurity, inheritable);
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SecurityCritical]
protected override bool ReleaseHandle()
{
return NativeMethods.CloseHandle(handle);
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public GeneralSecurity GetAccessControl()
{
return new GeneralSecurity(false, ResourceType.FileObject, this);
}
public void SetAccessControl(GeneralSecurity fileSecurity)
{
if (fileSecurity == null)
{
throw new ArgumentNullException("fileSecurity");
}
fileSecurity.Persist(this);
}
[SecurityCritical]
private static SafeFileHandle CreateFile(string fileName, uint fileAccess, uint fileShare, uint fileMode, uint fileOptions, GeneralSecurity fileSecurity,
bool inheritable = false)
{
var file = new SafeFileHandle();
GeneralSecurity.GetSecurityAttributes(fileSecurity, securityAttributes =>
{
file = NativeMethods.CreateFile(fileName, fileAccess, fileShare, securityAttributes, fileMode, fileOptions, IntPtr.Zero);
if (file.IsInvalid)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
}, inheritable);
return file;
}
[SecurityCritical]
[SuppressUnmanagedCodeSecurity]
private static class NativeMethods
{
[DllImport("kernel32.dll", SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, SecurityAttributes lpSecurityAttributes,
uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
}
}
}