using System; using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; namespace Vanara.InteropServices { /// A that takes a delegate in the constructor that closes the supplied handle. /// public class GenericSafeHandle : SafeHandleZeroOrMinusOneIsInvalid { /// Initializes a new instance of the class. protected GenericSafeHandle() : base(true) { } /// Initializes a new instance of the class. /// The pre-existing handle to use. /// to reliably release the handle during the finalization phase; to prevent reliable release (not recommended). protected GenericSafeHandle(IntPtr ptr, bool ownsHandle) : base(ownsHandle) => SetHandle(ptr); /// Initializes a new instance of the class. /// The delegate method for closing the handle. public GenericSafeHandle(Func closeMethod) : this(IntPtr.Zero, closeMethod, true) { } /// Initializes a new instance of the class. /// The pre-existing handle to use. /// The delegate method for closing the handle. /// to reliably release the handle during the finalization phase; to prevent reliable release (not recommended). /// closeMethod public GenericSafeHandle(IntPtr ptr, Func closeMethod, bool ownsHandle = true) : base(ownsHandle) { SetHandle(ptr); CloseMethod = closeMethod ?? throw new ArgumentNullException(nameof(closeMethod)); } /// Gets or sets the close method. /// The close method. protected virtual Func CloseMethod { get; } /// When overridden in a derived class, executes the code required to free the handle. /// /// true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a /// releaseHandleFailed MDA Managed Debugging Assistant. /// protected override bool ReleaseHandle() { var ret = CloseMethod?.Invoke(handle) ?? true; SetHandle(IntPtr.Zero); return ret; } } }