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