tangxu
2024-12-29 72e75456f8b30ec5b6f355539d9c883b0f810d21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
// 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
{
    /// <summary>Signals that a structure or class holds a handle to a synchronization object.</summary>
    public interface IGraphicsObjectHandle : IUserHandle { }
 
    /// <summary>Signals that a structure or class holds a HANDLE.</summary>
    public interface IHandle
    {
        /// <summary>Returns the value of the handle field.</summary>
        /// <returns>An IntPtr representing the value of the handle field.</returns>
        IntPtr DangerousGetHandle();
    }
 
    /// <summary>Signals that a structure or class holds a handle to a synchronization object.</summary>
    public interface IKernelHandle : IHandle { }
 
    /// <summary>Signals that a structure or class holds a handle to a synchronization object.</summary>
    public interface IUserHandle : IHandle { }
 
    /// <summary>Provides a handle to a Windows cursor.</summary>
    [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")]
    public struct HCURSOR : IGraphicsObjectHandle
    {
        private readonly IntPtr handle;
 
        /// <summary>Initializes a new instance of the <see cref="HCURSOR"/> struct.</summary>
        /// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
        public HCURSOR(IntPtr preexistingHandle) => handle = preexistingHandle;
 
        /// <summary>Returns an invalid handle by instantiating a <see cref="HCURSOR"/> object with <see cref="IntPtr.Zero"/>.</summary>
        public static HCURSOR NULL => new HCURSOR(IntPtr.Zero);
 
        /// <summary>Gets a value indicating whether this instance is a null handle.</summary>
        public bool IsNull => handle == IntPtr.Zero;
 
        /// <summary>Performs an explicit conversion from <see cref="HCURSOR"/> to <see cref="IntPtr"/>.</summary>
        /// <param name="h">The handle.</param>
        /// <returns>The result of the conversion.</returns>
        public static explicit operator IntPtr(HCURSOR h) => h.handle;
 
        /// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HCURSOR"/>.</summary>
        /// <param name="h">The pointer to a handle.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator HCURSOR(IntPtr h) => new HCURSOR(h);
 
        /// <summary>Implements the operator !=.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(HCURSOR h1, HCURSOR h2) => !(h1 == h2);
 
        /// <summary>Implements the operator ==.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(HCURSOR h1, HCURSOR h2) => h1.Equals(h2);
 
        /// <inheritdoc/>
        public override bool Equals(object obj) => obj is HCURSOR h && handle == h.handle;
 
        /// <inheritdoc/>
        public override int GetHashCode() => handle.GetHashCode();
 
        /// <inheritdoc/>
        public IntPtr DangerousGetHandle() => handle;
    }
 
    /// <summary>Provides a handle to a module or library instance.</summary>
    [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")]
    public struct HINSTANCE : IKernelHandle
    {
        private readonly IntPtr handle;
 
        /// <summary>Initializes a new instance of the <see cref="HINSTANCE"/> struct.</summary>
        /// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
        public HINSTANCE(IntPtr preexistingHandle) => handle = preexistingHandle;
 
        /// <summary>Returns an invalid handle by instantiating a <see cref="HINSTANCE"/> object with <see cref="IntPtr.Zero"/>.</summary>
        public static HINSTANCE NULL => new HINSTANCE(IntPtr.Zero);
 
        /// <summary>Gets a value indicating whether this instance is a null handle.</summary>
        public bool IsNull => handle == IntPtr.Zero;
 
        /// <summary>Performs an explicit conversion from <see cref="HINSTANCE"/> to <see cref="IntPtr"/>.</summary>
        /// <param name="h">The handle.</param>
        /// <returns>The result of the conversion.</returns>
        public static explicit operator IntPtr(HINSTANCE h) => h.handle;
 
        /// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HINSTANCE"/>.</summary>
        /// <param name="h">The pointer to a handle.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator HINSTANCE(IntPtr h) => new HINSTANCE(h);
 
        /// <summary>Implements the operator !=.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(HINSTANCE h1, HINSTANCE h2) => !(h1 == h2);
 
        /// <summary>Implements the operator ==.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(HINSTANCE h1, HINSTANCE h2) => h1.Equals(h2);
 
        /// <inheritdoc/>
        public override bool Equals(object obj) => obj is HINSTANCE h && handle == h.handle;
 
        /// <inheritdoc/>
        public override int GetHashCode() => handle.GetHashCode();
 
        /// <inheritdoc/>
        public IntPtr DangerousGetHandle() => handle;
    }
 
    /// <summary>Provides a handle to a window or dialog.</summary>
    [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")]
    public struct HWND : IUserHandle
    {
        private readonly IntPtr handle;
 
        /// <summary>Initializes a new instance of the <see cref="HWND"/> struct.</summary>
        /// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
        public HWND(IntPtr preexistingHandle) => handle = preexistingHandle;
 
        /// <summary>
        /// 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.
        /// </summary>
        public static HWND HWND_BOTTOM = new IntPtr(1);
 
        /// <summary>Use as parent in CreateWindow or CreateWindowEx call to indicate a message-only window.</summary>
        public static HWND HWND_MESSAGE = new IntPtr(-3);
 
        /// <summary>
        /// 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.
        /// </summary>
        public static HWND HWND_NOTOPMOST = new IntPtr(-2);
 
        /// <summary>Places the window at the top of the Z order.</summary>
        public static HWND HWND_TOP = new IntPtr(0);
 
        /// <summary>Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.</summary>
        public static HWND HWND_TOPMOST = new IntPtr(-1);
 
        /// <summary>Returns an invalid handle by instantiating a <see cref="HWND"/> object with <see cref="IntPtr.Zero"/>.</summary>
        public static HWND NULL => new HWND(IntPtr.Zero);
 
        /// <summary>Gets a value indicating whether this instance is a null handle.</summary>
        public bool IsNull => handle == IntPtr.Zero;
 
        /// <summary>Performs an explicit conversion from <see cref="HWND"/> to <see cref="IntPtr"/>.</summary>
        /// <param name="h">The handle.</param>
        /// <returns>The result of the conversion.</returns>
        public static explicit operator IntPtr(HWND h) => h.handle;
 
        /// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HWND"/>.</summary>
        /// <param name="h">The pointer to a handle.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator HWND(IntPtr h) => new HWND(h);
 
        /// <summary>Implements the operator !=.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(HWND h1, HWND h2) => !(h1 == h2);
 
        /// <summary>Implements the operator ==.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(HWND h1, HWND h2) => h1.Equals(h2);
 
        /// <inheritdoc/>
        public override bool Equals(object obj) => obj is HWND h && handle == h.handle;
 
        /// <inheritdoc/>
        public override int GetHashCode() => handle.GetHashCode();
 
        /// <inheritdoc/>
        public IntPtr DangerousGetHandle() => handle;
    }
 
    /// <summary>Base class for all native handles.</summary>
    /// <seealso cref="Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid"/>
    /// <seealso cref="System.IEquatable{T}"/>
    /// <seealso cref="Vanara.PInvoke.IHandle"/>
    [DebuggerDisplay("{handle}")]
    public abstract class SafeHANDLE : SafeHandleZeroOrMinusOneIsInvalid, IEquatable<SafeHANDLE>, IHandle
    {
        /// <summary>Initializes a new instance of the <see cref="SafeHANDLE"/> class.</summary>
        public SafeHANDLE() : base(true)
        {
        }
 
        /// <summary>Initializes a new instance of the <see cref="SafeHANDLE"/> class and assigns an existing handle.</summary>
        /// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
        /// <param name="ownsHandle">
        /// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
        /// </param>
        protected SafeHANDLE(IntPtr preexistingHandle, bool ownsHandle = true) : base(ownsHandle) => SetHandle(preexistingHandle);
 
        /// <summary>Gets a value indicating whether this instance is null.</summary>
        /// <value><c>true</c> if this instance is null; otherwise, <c>false</c>.</value>
        public bool IsNull => handle == IntPtr.Zero;
 
        /// <summary>Implements the operator !=.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(SafeHANDLE h1, IHandle h2) => !(h1 == h2);
 
        /// <summary>Implements the operator ==.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(SafeHANDLE h1, IHandle h2) => h1?.Equals(h2) ?? h2 is null;
 
        /// <summary>Implements the operator !=.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(SafeHANDLE h1, IntPtr h2) => !(h1 == h2);
 
        /// <summary>Implements the operator ==.</summary>
        /// <param name="h1">The first handle.</param>
        /// <param name="h2">The second handle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(SafeHANDLE h1, IntPtr h2) => h1?.Equals(h2) ?? false;
 
        /// <summary>Determines whether the specified <see cref="SafeHANDLE"/>, is equal to this instance.</summary>
        /// <param name="other">The <see cref="SafeHANDLE"/> to compare with this instance.</param>
        /// <returns><c>true</c> if the specified <see cref="SafeHANDLE"/> is equal to this instance; otherwise, <c>false</c>.</returns>
        public bool Equals(SafeHANDLE? other)
        {
            if (other is null) return false;
            if (ReferenceEquals(this, other)) return true;
            return handle == other.handle && IsClosed == other.IsClosed;
        }
 
        /// <summary>Determines whether the specified <see cref="System.Object"/>, is equal to this instance.</summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
        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);
            }
        }
 
        /// <summary>Returns a hash code for this instance.</summary>
        /// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
        public override int GetHashCode() => base.GetHashCode();
 
        /// <summary>Releases the ownership of the underlying handle and returns the current handle.</summary>
        /// <returns>The value of the current handle.</returns>
        public IntPtr ReleaseOwnership()
        {
            var ret = handle;
            SetHandleAsInvalid();
            return ret;
        }
 
        /// <summary>
        /// Internal method that actually releases the handle. This is called by <see cref="ReleaseHandle"/> for valid handles and afterwards
        /// zeros the handle.
        /// </summary>
        /// <returns><c>true</c> to indicate successful release of the handle; <c>false</c> otherwise.</returns>
        protected abstract bool InternalReleaseHandle();
 
        /// <inheritdoc/>
        [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
        protected override bool ReleaseHandle()
        {
            if (IsInvalid) return true;
            if (!InternalReleaseHandle()) return false;
            handle = IntPtr.Zero;
            return true;
        }
    }
}