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;
}
}
}