using Microsoft.Win32.SafeHandles;
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Vanara.PInvoke
{
/// Base class for all native handles.
///
///
///
[DebuggerDisplay("{handle}")]
public abstract class SafeHANDLE : SafeHandleZeroOrMinusOneIsInvalid, IEquatable, IHandle
{
/// Initializes a new instance of the class.
public SafeHANDLE() : base(true)
{
}
/// Initializes a new instance of the class and assigns an existing handle.
/// An object that represents the pre-existing handle to use.
///
/// to reliably release the handle during the finalization phase; otherwise, (not recommended).
///
protected SafeHANDLE(IntPtr preexistingHandle, bool ownsHandle = true) : base(ownsHandle) => SetHandle(preexistingHandle);
/// Gets a value indicating whether this instance is null.
/// true if this instance is null; otherwise, false.
public bool IsNull => handle == IntPtr.Zero;
/// Implements the operator ! which returns if the handle is invalid.
/// The instance.
/// The result of the operator.
public static bool operator !(SafeHANDLE hMem) => hMem.IsInvalid;
/// Implements the operator !=.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator !=(SafeHANDLE h1, IHandle h2) => !(h1 == h2);
/// Implements the operator !=.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator !=(SafeHANDLE h1, IntPtr h2) => !(h1 == h2);
/// Implements the operator ==.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator ==(SafeHANDLE h1, IHandle h2) => h1?.Equals(h2) ?? h2 is null;
/// Implements the operator ==.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator ==(SafeHANDLE h1, IntPtr h2) => h1?.Equals(h2) ?? false;
/// Performs an implicit conversion from to .
/// The safe handle.
/// The result of the conversion.
public static implicit operator HANDLE(SafeHANDLE h) => h.handle;
/// Determines whether the specified , is equal to this instance.
/// The to compare with this instance.
/// true if the specified is equal to this instance; otherwise, false.
public bool Equals(SafeHANDLE other) => ReferenceEquals(this, other) || other is not null && handle == other.handle && IsClosed == other.IsClosed;
/// Determines whether the specified , is equal to this instance.
/// The to compare with this instance.
/// true if the specified is equal to this instance; otherwise, false.
public override bool Equals(object obj) => obj switch
{
IHandle ih => handle.Equals(ih.DangerousGetHandle()),
SafeHandle sh => handle.Equals(sh.DangerousGetHandle()),
IntPtr p => handle.Equals(p),
_ => base.Equals(obj),
};
/// Returns a hash code for this instance.
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
public override int GetHashCode() => base.GetHashCode();
/// Releases the ownership of the underlying handle and returns the current handle.
/// The value of the current handle.
public IntPtr ReleaseOwnership()
{
var ret = handle;
SetHandleAsInvalid();
return ret;
}
///
/// Internal method that actually releases the handle. This is called by for valid handles and afterwards
/// zeros the handle.
///
/// true to indicate successful release of the handle; false otherwise.
protected abstract bool InternalReleaseHandle();
///
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
protected override bool ReleaseHandle()
{
if (IsInvalid) return true;
if (!InternalReleaseHandle()) return false;
handle = IntPtr.Zero;
return true;
}
}
}