diff --git a/PInvoke/Shared/Handles/HANDLE.cs b/PInvoke/Shared/Handles/HANDLE.cs index 73d47b8e..8835f97b 100644 --- a/PInvoke/Shared/Handles/HANDLE.cs +++ b/PInvoke/Shared/Handles/HANDLE.cs @@ -1,10 +1,11 @@ using Microsoft.Win32.SafeHandles; +using System.ComponentModel; using System.Diagnostics; namespace Vanara.PInvoke; /// Provides a handle to an accelerator table. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HACCEL : IUserHandle { private readonly IntPtr handle; @@ -57,7 +58,7 @@ public readonly struct HACCEL : IUserHandle } /// Provides a generic handle. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HANDLE : IHandle { private readonly IntPtr handle; @@ -115,7 +116,7 @@ public readonly struct HANDLE : IHandle } /// Provides a handle to a bitmap. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HBITMAP : IGraphicsObjectHandle { private readonly IntPtr handle; @@ -173,7 +174,7 @@ public readonly struct HBITMAP : IGraphicsObjectHandle } /// Provides a handle to drawing brush. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HBRUSH : IGraphicsObjectHandle { private readonly IntPtr handle; @@ -231,7 +232,7 @@ public readonly struct HBRUSH : IGraphicsObjectHandle } /// Provides a handle to a color space. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HCOLORSPACE : IGraphicsObjectHandle { private readonly IntPtr handle; @@ -289,7 +290,7 @@ public readonly struct HCOLORSPACE : IGraphicsObjectHandle } /// Provides a handle to cursor. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HCURSOR : IGraphicsObjectHandle { private readonly IntPtr handle; @@ -347,7 +348,7 @@ public readonly struct HCURSOR : IGraphicsObjectHandle } /// Provides a handle to a graphic device context. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HDC : IHandle { private readonly IntPtr handle; @@ -400,7 +401,7 @@ public readonly struct HDC : IHandle } /// Provides a handle to a desktop. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HDESK : IKernelHandle { private readonly IntPtr handle; @@ -453,7 +454,7 @@ public readonly struct HDESK : IKernelHandle } /// Provides a handle to a DPA. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HDPA : IKernelHandle { private readonly IntPtr handle; @@ -506,7 +507,7 @@ public readonly struct HDPA : IKernelHandle } /// Provides a handle to a Windows drop operation. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HDROP : IShellHandle { private readonly IntPtr handle; @@ -559,7 +560,7 @@ public readonly struct HDROP : IShellHandle } /// Provides a handle to a DSA. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HDSA : IKernelHandle { private readonly IntPtr handle; @@ -612,7 +613,7 @@ public readonly struct HDSA : IKernelHandle } /// Provides a handle to a deferred windows position. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HDWP : IUserHandle { private readonly IntPtr handle; @@ -665,7 +666,7 @@ public readonly struct HDWP : IUserHandle } /// Provides a handle to an enhanced metafile. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HENHMETAFILE : IHandle { private readonly IntPtr handle; @@ -718,7 +719,7 @@ public readonly struct HENHMETAFILE : IHandle } /// Provides a handle to a sync event. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HEVENT : ISyncHandle { private readonly IntPtr handle; @@ -771,7 +772,7 @@ public readonly struct HEVENT : ISyncHandle } /// Provides a handle to a file. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HFILE : ISyncHandle { private readonly IntPtr handle; @@ -835,7 +836,7 @@ public readonly struct HFILE : ISyncHandle } /// Provides a handle to a font. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HFONT : IGraphicsObjectHandle { private readonly IntPtr handle; @@ -893,7 +894,7 @@ public readonly struct HFONT : IGraphicsObjectHandle } /// Provides a handle to a graphic device object. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HGDIOBJ : IGraphicsObjectHandle { private readonly IntPtr handle; @@ -986,7 +987,7 @@ public readonly struct HGDIOBJ : IGraphicsObjectHandle } /// Provides a handle to an icon. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HICON : IUserHandle { private readonly IntPtr handle; @@ -1039,7 +1040,7 @@ public readonly struct HICON : IUserHandle } /// Provides a handle to a Windows image list. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HIMAGELIST : IShellHandle { private readonly IntPtr handle; @@ -1092,7 +1093,7 @@ public readonly struct HIMAGELIST : IShellHandle } /// Provides a handle to a module or library instance. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HINSTANCE : IKernelHandle { private readonly IntPtr handle; @@ -1145,7 +1146,7 @@ public readonly struct HINSTANCE : IKernelHandle } /// Provides a handle to a Windows registry key. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HKEY : IKernelHandle { private readonly IntPtr handle; @@ -1250,7 +1251,7 @@ public readonly struct HKEY : IKernelHandle } /// Provides a handle to a menu. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HMENU : IUserHandle { private readonly IntPtr handle; @@ -1303,7 +1304,7 @@ public readonly struct HMENU : IUserHandle } /// Provides a handle to a metafile. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HMETAFILE : IHandle { private readonly IntPtr handle; @@ -1356,7 +1357,7 @@ public readonly struct HMETAFILE : IHandle } /// Provides a handle to a monitor. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HMONITOR : IKernelHandle { private readonly IntPtr handle; @@ -1409,7 +1410,7 @@ public readonly struct HMONITOR : IKernelHandle } /// Provides a handle to a palette. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HPALETTE : IGraphicsObjectHandle { private readonly IntPtr handle; @@ -1467,7 +1468,7 @@ public readonly struct HPALETTE : IGraphicsObjectHandle } /// Provides a handle to a drawing pen. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HPEN : IGraphicsObjectHandle { private readonly IntPtr handle; @@ -1525,7 +1526,7 @@ public readonly struct HPEN : IGraphicsObjectHandle } /// Provides a handle to a process. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HPROCESS : ISyncHandle { private readonly IntPtr handle; @@ -1583,7 +1584,7 @@ public readonly struct HPROCESS : ISyncHandle } /// Provides a handle to a Windows property sheet. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HPROPSHEET : IUserHandle { private readonly IntPtr handle; @@ -1636,7 +1637,7 @@ public readonly struct HPROPSHEET : IUserHandle } /// Provides a handle to a property sheet page. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HPROPSHEETPAGE : IUserHandle { private readonly IntPtr handle; @@ -1689,7 +1690,7 @@ public readonly struct HPROPSHEETPAGE : IUserHandle } /// Provides a handle to a drawing region. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HRGN : IGraphicsObjectHandle { private readonly IntPtr handle; @@ -1747,7 +1748,7 @@ public readonly struct HRGN : IGraphicsObjectHandle } /// Provides a handle to a file mapping object. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HSECTION : IHandle { private readonly IntPtr handle; @@ -1800,7 +1801,7 @@ public readonly struct HSECTION : IHandle } /// Provides a handle to a blocking task. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HTASK : IHandle { private readonly IntPtr handle; @@ -1853,7 +1854,7 @@ public readonly struct HTASK : IHandle } /// Provides a handle to a Windows theme. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HTHEME : IHandle { private readonly IntPtr handle; @@ -1906,7 +1907,7 @@ public readonly struct HTHEME : IHandle } /// Provides a handle to a thread. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HTHREAD : ISyncHandle { private readonly IntPtr handle; @@ -1959,7 +1960,7 @@ public readonly struct HTHREAD : ISyncHandle } /// Provides a handle to a Windows thumbnail. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HTHUMBNAIL : IShellHandle { private readonly IntPtr handle; @@ -2012,7 +2013,7 @@ public readonly struct HTHUMBNAIL : IShellHandle } /// Provides a handle to an access token. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HTOKEN : IKernelHandle { private readonly IntPtr handle; @@ -2065,7 +2066,7 @@ public readonly struct HTOKEN : IKernelHandle } /// Provides a handle to a windows station. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HWINSTA : IKernelHandle { private readonly IntPtr handle; @@ -2118,7 +2119,7 @@ public readonly struct HWINSTA : IKernelHandle } /// Provides a handle to a window or dialog. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct HWND : IUserHandle { private readonly IntPtr handle; @@ -2198,7 +2199,7 @@ public readonly struct HWND : IUserHandle } /// Provides a pointer to an access control entry. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct PACE : ISecurityObject { private readonly IntPtr handle; @@ -2251,7 +2252,7 @@ public readonly struct PACE : ISecurityObject } /// Provides a handle to an access control list. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct PACL : ISecurityObject { private readonly IntPtr handle; @@ -2304,7 +2305,7 @@ public readonly struct PACL : ISecurityObject } /// Provides a handle to a security descriptor. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct PSECURITY_DESCRIPTOR : ISecurityObject { private readonly IntPtr handle; @@ -2357,7 +2358,7 @@ public readonly struct PSECURITY_DESCRIPTOR : ISecurityObject } /// Provides a handle to a security identifier. -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct PSID : ISecurityObject { private readonly IntPtr handle; diff --git a/PInvoke/Shared/Handles/HANDLE.tt b/PInvoke/Shared/Handles/HANDLE.tt index fc6e728e..c7ac7ccb 100644 --- a/PInvoke/Shared/Handles/HANDLE.tt +++ b/PInvoke/Shared/Handles/HANDLE.tt @@ -54,13 +54,14 @@ { "HPROCESS", ("HPROCESS", "Process", "h.Handle" ) }, }; #> using Microsoft.Win32.SafeHandles; +using System.ComponentModel; using System.Diagnostics; namespace Vanara.PInvoke; <# foreach (var (name, inheritance, summaryText) in classes) { #> /// <#= summaryText #> -[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")] +[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}"), TypeConverter(typeof(HANDLEConverter))] public readonly struct <#= name #> : <#= inheritance #> { private readonly IntPtr handle; diff --git a/PInvoke/Shared/Handles/HANDLEConverter.cs b/PInvoke/Shared/Handles/HANDLEConverter.cs new file mode 100644 index 00000000..0eb150e9 --- /dev/null +++ b/PInvoke/Shared/Handles/HANDLEConverter.cs @@ -0,0 +1,41 @@ +using System.ComponentModel; +using System.Globalization; +using Vanara.Extensions.Reflection; + +namespace Vanara.PInvoke; + +/// Converts a handle to a string or an integer and vice versa. The string representation is the handle value as an integer. +/// +public class HANDLEConverter : TypeConverter +{ + /// + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) => sourceType == typeof(string) || sourceType == typeof(int) || + sourceType == typeof(int) || sourceType.InheritsFrom() || base.CanConvertFrom(context, sourceType); + + /// + public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) => value switch + { + null => IntPtr.Zero, + string s => s.ToLower(culture).Trim() == "null" ? IntPtr.Zero : new IntPtr(long.Parse(s)), + int i => new IntPtr(i), + IHandle h => h.DangerousGetHandle(), + _ => base.ConvertFrom(context, culture, value) + }; + + /// + public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) + { + value ??= HANDLE.NULL; + if (destinationType == typeof(string)) + { + if (value is IHandle h) + return SVal(h.DangerousGetHandle().ToInt64()); + if (value is IConvertible c) + return SVal(c.ToInt64(culture)); + try { return SVal(((IntPtr)value).ToInt64()); } catch { } + } + return base.ConvertTo(context, culture, value, destinationType); + + static string SVal(long v) => v == 0 ? "NULL" : v.ToString(); + } +} \ No newline at end of file