// THIS FILE IS PART OF Vanara PROJECT
// THE Vanara PROJECT IS AN OPENSOURCE LIBRARY LICENSED UNDER THE MIT License.
// COPYRIGHT (C) dahall. ALL RIGHTS RESERVED.
// GITHUB: https://github.com/dahall/Vanara
using Microsoft.Win32.SafeHandles;
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Vanara.PInvoke
{
/// Signals that a structure or class holds a handle to a synchronization object.
public interface IGraphicsObjectHandle : IUserHandle { }
/// Signals that a structure or class holds a HANDLE.
public interface IHandle
{
/// Returns the value of the handle field.
/// An IntPtr representing the value of the handle field.
IntPtr DangerousGetHandle();
}
/// Signals that a structure or class holds a handle to a synchronization object.
public interface IKernelHandle : IHandle { }
/// Signals that a structure or class holds a handle to a synchronization object.
public interface IUserHandle : IHandle { }
/// Provides a handle to a Windows cursor.
[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")]
public struct HCURSOR : IGraphicsObjectHandle
{
private readonly IntPtr handle;
/// Initializes a new instance of the struct.
/// An object that represents the pre-existing handle to use.
public HCURSOR(IntPtr preexistingHandle) => handle = preexistingHandle;
/// Returns an invalid handle by instantiating a object with .
public static HCURSOR NULL => new HCURSOR(IntPtr.Zero);
/// Gets a value indicating whether this instance is a null handle.
public bool IsNull => handle == IntPtr.Zero;
/// Performs an explicit conversion from to .
/// The handle.
/// The result of the conversion.
public static explicit operator IntPtr(HCURSOR h) => h.handle;
/// Performs an implicit conversion from to .
/// The pointer to a handle.
/// The result of the conversion.
public static implicit operator HCURSOR(IntPtr h) => new HCURSOR(h);
/// Implements the operator !=.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator !=(HCURSOR h1, HCURSOR h2) => !(h1 == h2);
/// Implements the operator ==.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator ==(HCURSOR h1, HCURSOR h2) => h1.Equals(h2);
///
public override bool Equals(object obj) => obj is HCURSOR h && handle == h.handle;
///
public override int GetHashCode() => handle.GetHashCode();
///
public IntPtr DangerousGetHandle() => handle;
}
/// Provides a handle to a module or library instance.
[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")]
public struct HINSTANCE : IKernelHandle
{
private readonly IntPtr handle;
/// Initializes a new instance of the struct.
/// An object that represents the pre-existing handle to use.
public HINSTANCE(IntPtr preexistingHandle) => handle = preexistingHandle;
/// Returns an invalid handle by instantiating a object with .
public static HINSTANCE NULL => new HINSTANCE(IntPtr.Zero);
/// Gets a value indicating whether this instance is a null handle.
public bool IsNull => handle == IntPtr.Zero;
/// Performs an explicit conversion from to .
/// The handle.
/// The result of the conversion.
public static explicit operator IntPtr(HINSTANCE h) => h.handle;
/// Performs an implicit conversion from to .
/// The pointer to a handle.
/// The result of the conversion.
public static implicit operator HINSTANCE(IntPtr h) => new HINSTANCE(h);
/// Implements the operator !=.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator !=(HINSTANCE h1, HINSTANCE h2) => !(h1 == h2);
/// Implements the operator ==.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator ==(HINSTANCE h1, HINSTANCE h2) => h1.Equals(h2);
///
public override bool Equals(object obj) => obj is HINSTANCE h && handle == h.handle;
///
public override int GetHashCode() => handle.GetHashCode();
///
public IntPtr DangerousGetHandle() => handle;
}
/// Provides a handle to a window or dialog.
[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")]
public struct HWND : IUserHandle
{
private readonly IntPtr handle;
/// Initializes a new instance of the struct.
/// An object that represents the pre-existing handle to use.
public HWND(IntPtr preexistingHandle) => handle = preexistingHandle;
///
/// Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost window, the window loses its
/// topmost status and is placed at the bottom of all other windows.
///
public static HWND HWND_BOTTOM = new IntPtr(1);
/// Use as parent in CreateWindow or CreateWindowEx call to indicate a message-only window.
public static HWND HWND_MESSAGE = new IntPtr(-3);
///
/// Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window
/// is already a non-topmost window.
///
public static HWND HWND_NOTOPMOST = new IntPtr(-2);
/// Places the window at the top of the Z order.
public static HWND HWND_TOP = new IntPtr(0);
/// Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.
public static HWND HWND_TOPMOST = new IntPtr(-1);
/// Returns an invalid handle by instantiating a object with .
public static HWND NULL => new HWND(IntPtr.Zero);
/// Gets a value indicating whether this instance is a null handle.
public bool IsNull => handle == IntPtr.Zero;
/// Performs an explicit conversion from to .
/// The handle.
/// The result of the conversion.
public static explicit operator IntPtr(HWND h) => h.handle;
/// Performs an implicit conversion from to .
/// The pointer to a handle.
/// The result of the conversion.
public static implicit operator HWND(IntPtr h) => new HWND(h);
/// Implements the operator !=.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator !=(HWND h1, HWND h2) => !(h1 == h2);
/// Implements the operator ==.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator ==(HWND h1, HWND h2) => h1.Equals(h2);
///
public override bool Equals(object obj) => obj is HWND h && handle == h.handle;
///
public override int GetHashCode() => handle.GetHashCode();
///
public IntPtr DangerousGetHandle() => handle;
}
/// 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 !=.
/// 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, 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 == h2);
/// 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;
/// 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)
{
if (other is null) return false;
if (ReferenceEquals(this, other)) return true;
return 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)
{
switch (obj)
{
case IHandle ih: return handle.Equals(ih.DangerousGetHandle());
case SafeHandle sh: return handle.Equals(sh.DangerousGetHandle());
case IntPtr p: return handle.Equals(p);
default: return 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;
}
}
}