{"id":2613,"date":"2023-02-07T22:36:42","date_gmt":"2023-02-08T03:36:42","guid":{"rendered":"https:\/\/badecho.com\/?p=2613"},"modified":"2023-02-28T12:08:55","modified_gmt":"2023-02-28T17:08:55","slug":"safehandles-in-structs","status":"publish","type":"post","link":"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/","title":{"rendered":"Using SafeHandles in Structs via Stateful Marshalling"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2023\/02\/StatefulMarshalling.png\" alt=\"Using SafeHandles in Structs via Stateful Marshalling\" class=\"wp-image-2614\" width=\"856\" height=\"448\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2023\/02\/StatefulMarshalling.png 856w, https:\/\/badecho.com\/wp-content\/uploads\/2023\/02\/StatefulMarshalling-300x157.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2023\/02\/StatefulMarshalling-768x402.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2023\/02\/StatefulMarshalling-480x251.png 480w\" sizes=\"(max-width: 856px) 100vw, 856px\" \/><\/figure><\/div>\n\n\n\n<p><a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.runtime.interopservices.safehandle?view=net-7.0\" target=\"_blank\" rel=\"noreferrer noopener\">SafeHandles<\/a> provide reliable and secure means of managing the lifetime of unmanaged resources. It&#8217;s commonly recommended to use <code>SafeHandle<\/code> instead of <code>IntPtr<\/code> whenever we need to acquire and deal with unmanaged system handles.<\/p>\n\n\n\n<p>The .NET runtime makes this recommendation easy to follow, as the <code>SafeHandle<\/code> class is integrated with platform invoke, allowing for the correct type of <code>SafeHandle<\/code> to be used interchangeably with <code>IntPtr<\/code> as parameters in P\/Invoke method signatures.<\/p>\n\n\n\n<p>Unmanaged handles aren&#8217;t only used as method parameters, however, as they are also present as members of the many kinds of C-style structs that unmanaged functions accept as parameters. Unfortunately, with structs, the use of <code>SafeHandle<\/code> is <em>not<\/em> interchangeable with <code>IntPtr<\/code>.<\/p>\n\n\n\n<p>This means that we&#8217;re still stuck using dangerous <code>IntPtr<\/code> handles when dealing with structs. However, with <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/standard\/native-interop\/pinvoke-source-generation\" target=\"_blank\" rel=\"noreferrer noopener\">.NET 7&#8217;s introduction of source generation for platform invokes<\/a>, we now have a way to safely make use of <code>SafeHandle<\/code> types in our structs. This article will demonstrate how.<\/p>\n\n\n\n<h2>A Sample Handle<\/h2>\n\n\n\n<p>We&#8217;re going to take a look at an example <code>SafeHandle<\/code> and its current limitations, and then look at how we can overcome them as far structs are concerned.<\/p>\n\n\n\n<p>One kind of unmanaged resource we encounter frequently is a handle to a window. It is created when a window is created, and it is used to interact with said window throughout its lifetime.<\/p>\n\n\n\n<h6><a href=\"https:\/\/github.com\/BadEcho\/core\/blob\/master\/src\/Common\/Interop\/WindowHandle.cs\" target=\"_blank\" rel=\"noreferrer noopener\">WindowHandle.cs<\/a><\/h6>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary&gt;\n\/\/\/ Provides a level-0 type for window handles.\n\/\/\/ &lt;\/summary&gt;\n\/\/\/ &lt;suppressions&gt;\n\/\/\/ ReSharper disable UnusedMember.Local\n\/\/\/ &lt;\/suppressions&gt;\npublic sealed class WindowHandle : SafeHandle\n{\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Initializes a new instance of the &lt;see cref=&quot;WindowHandle&quot;\/&gt; class.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=&quot;handle&quot;&gt;The handle to the window.&lt;\/param&gt;\n    \/\/\/ &lt;param name=&quot;ownsHandle&quot;&gt;\n    \/\/\/ Value indicating if this safe handle is responsible for releasing the provided handle.\n    \/\/\/ &lt;\/param&gt;\n    public WindowHandle(IntPtr handle, bool ownsHandle)\n        : this(ownsHandle)\n    {\n        SetHandle(handle);\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Initializes a new instance of the &lt;see cref=&quot;WindowHandle&quot;\/&gt; class.\n    \/\/\/ &lt;\/summary&gt;\n    public WindowHandle()\n        : this(true)\n    { }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Initializes a new instance of the &lt;see cref=&quot;WindowHandle&quot;\/&gt; class.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=&quot;ownsHandle&quot;&gt;\n    \/\/\/ Value indicating if this safe handle is responsible for releasing the provided handle.\n    \/\/\/ &lt;\/param&gt;\n    private WindowHandle(bool ownsHandle)\n        : base(IntPtr.Zero, ownsHandle)\n    { }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets a default invalid instance of the &lt;see cref=&quot;WindowHandle&quot;\/&gt; class.\n    \/\/\/ &lt;\/summary&gt;\n    public static WindowHandle InvalidHandle\n        =&gt; new(false);\n\n    \/\/\/ &lt;inheritdoc\/&gt;\n    public override bool IsInvalid\n        =&gt; handle == IntPtr.Zero;\n    \n    \/\/\/ &lt;inheritdoc\/&gt;\n    protected override bool ReleaseHandle()\n        =&gt; User32.DestroyWindow(handle);\n}\n<\/pre>\n\n\n<p>The <a href=\"https:\/\/github.com\/BadEcho\/core\/blob\/master\/src\/Common\/Interop\/WindowHandle.cs\" target=\"_blank\" rel=\"noreferrer noopener\"><code>WindowHandle<\/code><\/a> class provides <code>SafeHandle<\/code>-like functoinality for unmanaged window handles. <\/p>\n\n\n\n<p>It&#8217;ll be initialized via the default constructor by P\/Invoke whenever it&#8217;s used as a return value for a function that normally returns a window handle.<\/p>\n\n\n\n<h6>P\/Invoke Function Returning WindowHandle<\/h6>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n[LibraryImport(LIBRARY_NAME, \n               EntryPoint = &quot;CreateWindowExW&quot;, \n               StringMarshalling = StringMarshalling.Utf16, \n               SetLastError = true)]\npublic static unsafe partial WindowHandle CreateWindowEx(int dwExStyle,\n                                                         string lpClassName,\n                                                         string lpWindowName,\n                                                         int style,\n                                                         int x,\n                                                         int y,\n                                                         int width,\n                                                         int height,\n                                                         IntPtr hWndParent,\n                                                         IntPtr hMenu,\n                                                         IntPtr hInstance,\n                                                         void* lpParam);\n<\/pre>\n\n\n<p>Normally, the signature for  <code><a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/api\/winuser\/nf-winuser-createwindowexw\" target=\"_blank\" rel=\"noreferrer noopener\">CreateWindowEx<\/a><\/code> would be written to return an <code>IntPtr<\/code> handle to the window. But, as you can see, we can easily swap that with our custom <code>SafeHandle<\/code> and it all works like magic.<\/p>\n\n\n\n<p>Our custom <code>SafeHandle<\/code> can also be used as a parameter for methods that expect a window handle and are normally written to accept an <code>IntPtr<\/code>.<\/p>\n\n\n\n<h6>P\/Invoke Function Accepting WindowHandle as Parameter<\/h6>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n[LibraryImport(LIBRARY_NAME, SetLastError = true)]\n[return: MarshalAs(UnmanagedType.Bool)]\npublic static partial bool GetWindowRect(WindowHandle hWnd, out RECT lpRect);\n<\/pre>\n\n\n<p>And everything works just perfectly, with the added security and reliability that using a <code>SafeHandle<\/code> grants us.<\/p>\n\n\n\n<p>Unfortunately, that&#8217;s where the magic just about stops.<\/p>\n\n\n\n<h2>Structs and SafeHandles Don&#8217;t Mix Well<\/h2>\n\n\n\n<p>If we continue to expand our repertoire of window-related P\/Invoke functions, we&#8217;ll eventually run into some methods expecting window handles to be provided as members of a C-style struct.<\/p>\n\n\n\n<p>An example is the <a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/api\/shellapi\/nf-shellapi-shell_notifyiconw\" target=\"_blank\" rel=\"noreferrer noopener\"><code>Shell_NotifyIcon<\/code><\/a> function, used to register an icon with the taskbar&#8217;s status area. This function accepts a <code><a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/api\/shellapi\/ns-shellapi-notifyicondataw\" target=\"_blank\" rel=\"noreferrer noopener\">NOTIFYICONDATA<\/a><\/code> struct as one of its parameters, which has a member that gets set to the handle of the window meant to receive taskbar notifications.<\/p>\n\n\n\n<p>If we try to define this structure so that it uses a <code>WindowHandle<\/code>, we will run into problems.<\/p>\n\n\n\n<h6>A Problematic NOTIFYICONDATA<\/h6>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary&gt;\n\/\/\/ Represents information that the system needs to display notifications in the notification area.\n\/\/\/ &lt;\/summary&gt;\n[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\ninternal unsafe struct NOTIFYICONDATAW\n{\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ A handle to the window that receives notifications associated with an icon i\n    \/\/\/ n the notification area.\n    \/\/\/ &lt;\/summary&gt;\n    public WindowHandle hWnd;\n\n    \/\/ Insert the rest of the members..\n}\n<\/pre>\n\n\n<p>The presence of a <code>WindowHandle<\/code> in this struct will immediately result in compile-time errors similar to the following if we try to use the struct as a parameter to <code>Shell_NotifyIcon<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>SYSLIB10: The type 'BadEcho.Interop.NOTIFYICONDATAW' is not supported by source-generated P\/Invokes.\nThe generated source will not handle marshalling of parameter 'lpData'.<\/code><\/pre>\n\n\n\n<p>This is an error you&#8217;d get when using the new source generator system \u00e0 la the <code>LibraryImportAttribute<\/code>. If you&#8217;re using the older <code>DllImportAttribute<\/code>, then your program may compile, however it isn&#8217;t going to work at runtime.<\/p>\n\n\n\n<p>So what can we do? Well, let&#8217;s start with the more obvious, less-than-perfect, workaround.<\/p>\n\n\n\n<h2>The Bad Way: Getting a Handle Out of a SafeHandle<\/h2>\n\n\n\n<p>We can revert our struct definition to use <code>IntPtr<\/code> instead of our <code>WindowHandle<\/code>. This will resolve the compile-time errors.<\/p>\n\n\n\n<p>All we need to do then is squeeze the <code>SafeHandle<\/code>&#8216;s internal handle out from it, and use that when populating the struct&#8217;s members.<\/p>\n\n\n\n<h6>A Dangerous Squeeze<\/h6>\n\n\n<pre class=\"brush: csharp; highlight: [7]; title: ; notranslate\" title=\"\">\nvar iconData = new NOTIFYICONDATAW\n               {\n                   cbSize = (uint) sizeof(NOTIFYICONDATAW),\n                   uCallbackMessage = (uint) _TrayEvent,\n                   uFlags = NotifyIconFlags.Message | NotifyIconFlags.Guid,\n                   guidItem = _id,\n                   hWnd = windowHandle.DangerousGetHandle()\n                   \/\/ Everything else...\n               };\n\nShell32.Shell_NotifyIcon(NotifyIconMessage.Add, ref iconData);\n<\/pre>\n\n\n<p>Getting the internal handle out from the <code>SafeHandle<\/code> requires the calling of <code><a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.runtime.interopservices.safehandle.dangerousgethandle?view=net-7.0\" target=\"_blank\" rel=\"noreferrer noopener\">DangerousGetHandle<\/a><\/code>, a method with an appropriately ominous name.<\/p>\n\n\n\n<p>There are numerous articles out there which go into why using this method is, for lack of a better word, &#8220;dangerous&#8221;. It opens ourselves up to runtime errors due to stale handles, as well as potential security issues via handle recycling security attacks.<\/p>\n\n\n\n<p>To use this method safely, we need to use the <code><a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.runtime.interopservices.safehandle.dangerousaddref?view=net-7.0\" target=\"_blank\" rel=\"noreferrer noopener\">DangerousAddRef<\/a><\/code> and <code><a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.runtime.interopservices.safehandle.dangerousrelease?view=net-7.0\" target=\"_blank\" rel=\"noreferrer noopener\">DangerousRelease<\/a><\/code> methods &#8212; and the best place to use these is right in the middle of the whole marshalling procedure, somewhere that&#8217;s been out of reach to us until .NET 7&#8217;s release.<\/p>\n\n\n\n<p>This leads us to the better way to &#8220;handle&#8221; our <code>SafeHandle<\/code>-in-structs conundrum: by implementing a custom stateful marshaller for this struct.<\/p>\n\n\n\n<h2>The Good Way: A Stateful Marshaller<\/h2>\n\n\n\n<p>We&#8217;re going to leverage some of .NET 7&#8217;s new P\/Invoke source generation technology so that we can keep our <code>WindowHandle<\/code>, and a few other <code>SafeHandle<\/code> instances that we require, where we want them in the call to <code>Shell_NotifyIcon<\/code>.<\/p>\n\n\n\n<p>A <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/standard\/native-interop\/custom-marshalling-source-generation\" target=\"_blank\" rel=\"noreferrer noopener\">custom marshaller<\/a> allows for fine-grained control over how a type is marshalled (transformed when crossing between managed and native code). <\/p>\n\n\n\n<p>Most (this is a bit of an assumption) marshallers are &#8216;stateless&#8217;, meaning they are static classes that maintain no state regarding the object being marshalled. You can <a href=\"https:\/\/github.com\/BadEcho\/core\/blob\/master\/src\/Common\/Interop\/WindowClassMarshaller.cs\" target=\"_blank\" rel=\"noreferrer noopener\">see an example of one here<\/a>.<\/p>\n\n\n\n<h3>Custom Marshaller Components<\/h3>\n\n\n\n<p>We&#8217;ll be making a marshaller that keeps track of the object and its constituent parts during the marshalling process. Maintaining state is required so that we can correctly update the reference counters on our <code>SafeHandle<\/code> instances. <\/p>\n\n\n\n<p>Custom marshalling requires the following components:<\/p>\n\n\n\n<ul><li>A managed data type<\/li><li>An unmanaged data type<\/li><li>The custom marshaller type<\/li><\/ul>\n\n\n\n<p>When we&#8217;re done, we&#8217;ll be able to define a P\/Invoke signature that receives the managed data class in place of the C-style struct, and it will all work fabulously.<\/p>\n\n\n\n<h3>The Managed Data Type<\/h3>\n\n\n\n<p>The managed data type will be the class our consuming code will be directly creating and interacting with when calling our P\/Invoke function. Consuming code will never interact with the unmanaged data type.<\/p>\n\n\n\n<p>Despite how we are referring to it, the &#8220;unmanaged&#8221; data type, defined using C# code, will be managed code itself. Our managed data type will differ from the &#8220;unmanaged&#8221; type in that it will contain all the member types not supported by source-generated P\/Invokes, such as our <code>WindowHandle<\/code>.<\/p>\n\n\n\n<p>Also, while the managed type could (and, in practice, sometimes is) defined as a struct, I tend to define them as classes; this is because, being purely managed representations of the data, I find it more appropriate to define them as how one defines the majority of types which don&#8217;t require value type semantics in a .NET assembly: as classes with properties.<\/p>\n\n\n\n<h6><a href=\"https:\/\/github.com\/BadEcho\/core\/blob\/master\/src\/Common\/Interop\/NotifyIconData.cs\" target=\"_blank\" rel=\"noreferrer noopener\">NotifyIconData.cs<\/a><\/h6>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary&gt;\n\/\/\/ Provides information that the system needs to display notifications in the\n\/\/\/ notification area.\n\/\/\/ &lt;\/summary&gt;\n[NativeMarshalling(typeof(NotifyIconDataMarshaller))]\ninternal sealed class NotifyIconData\n{\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Initializes a new instance of the &lt;see cref=&quot;NotifyIconData&quot;\/&gt; class.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=&quot;window&quot;&gt;\n    \/\/\/ A handle to the window that receives notifications associated with an icon in the\n    \/\/\/ notification area.\n    \/\/\/ &lt;\/param&gt;\n    \/\/\/ &lt;param name=&quot;id&quot;&gt;The unique identifier of the taskbar icon.&lt;\/param&gt;\n    \/\/\/ &lt;param name=&quot;flags&quot;&gt;\n    \/\/\/ Flags that either indicate which of the other members of the structure contain valid\n    \/\/\/ data or provide additional information to the tooltip as to how it should display.\n    \/\/\/ &lt;\/param&gt;\n    public NotifyIconData(WindowHandle window, Guid id, NotifyIconFlags flags)\n    {\n        Require.NotNull(window, nameof(window));\n\n        Window = window;\n        Id = id;\n        \/\/ It is implied that the Guid identifier member is valid given our constructor's\n        \/\/ parameters.\n        Flags = flags | NotifyIconFlags.Guid;\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets a handle to the window that receives notifications associated with an icon\n    \/\/\/ in the notification area.\n    \/\/\/ &lt;\/summary&gt;\n    public WindowHandle Window\n    { get; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets the unique identifier of the taskbar icon.\n    \/\/\/ &lt;\/summary&gt;\n    public Guid Id\n    { get; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets flags that either indicate which of the other members of the structure contain\n    \/\/\/ valid data or provide additional information to the tooltip as to how it should display.\n    \/\/\/ &lt;\/summary&gt;\n    public NotifyIconFlags Flags\n    { get; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets an application-defined message identifier.\n    \/\/\/ &lt;\/summary&gt;\n    public uint CallbackMessage\n    { get; set; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets a handle to the icon to be added, modified, or deleted.\n    \/\/\/ &lt;\/summary&gt;\n    public IconHandle? Icon\n    { get; set; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets the state of the icon.\n    \/\/\/ &lt;\/summary&gt;\n    public uint State\n    { get; set; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets a value that specifies which bits of the &lt;see cref=&quot;State&quot;\/&gt; member\n    \/\/\/ are retrieved or modified.\n    \/\/\/ &lt;\/summary&gt;\n    public uint StateMask\n    { get; set; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets either the timeout value, in milliseconds, for the notification, or a\n    \/\/\/ specification of which version of the Shell notification icon interface should be used.\n    \/\/\/ &lt;\/summary&gt;\n    public uint TimeoutOrVersion\n    { get; set; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets Flags that can be set to modify the behavior and appearance of a\n    \/\/\/ balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    public NotifyIconInfoFlags InfoFlags\n    { get; set; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets A handle to a customized notification icon that should be used independently\n    \/\/\/ of the notification area icon.\n    \/\/\/ &lt;\/summary&gt;\n    public IconHandle? BalloonIcon\n    { get; set; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets a string that specifies the text for a standard tooltip.\n    \/\/\/ &lt;\/summary&gt;\n    public string? Tip\n    { get; set; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets a string that specifies the text to display in a balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    public string? Info\n    { get; set; }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets a string that specifies a title for a balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    public string? InfoTitle\n    { get; set; }\n}\n<\/pre>\n\n\n<p>We see above the managed data representation of the <code>NOTIFYICONDATA<\/code> struct; it is a pretty typical looking POCO.<\/p>\n\n\n\n<p>One thing a bit out of the ordinary is the <code><a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.runtime.interopservices.marshalling.nativemarshallingattribute?view=net-7.0\" target=\"_blank\" rel=\"noreferrer noopener\">NativeMarshallingAttribute<\/a><\/code> at the top of the class. The presence of this attribute will cause the specified marshaller to be automatically used when this managed type is present in a P\/Invoke signature.<\/p>\n\n\n\n<p>The marshaller type specified, <code>NotifyIconDataMarshaller<\/code>, is our custom marshaller which we&#8217;ll be defining later.<\/p>\n\n\n\n<h3>The Unmanaged Data Type<\/h3>\n\n\n\n<p>The next step is to define the unmanaged data type. As was mentioned earlier, this &#8220;unmanaged&#8221; data type&#8217;s code will be as managed as everything else we&#8217;re writing.<\/p>\n\n\n\n<p>What will make it &#8220;unmanaged&#8221; is that it will be a C-style struct that contains only member types supported by source-generated P\/Invokes.<\/p>\n\n\n\n<p>That means every member must be a built-in value type. So, no <code>SafeHandle<\/code> types are allowed here; instead, <code>IntPtr<\/code> must be used for handles. Delegate types will need to be replaced with function pointers, strings will need to be replaced with <code>ushort<\/code> or <code>byte<\/code> pointers, etc.<\/p>\n\n\n\n<p>Proper struct authoring is outside the scope of this article; suffice it to say: the unmanaged data type will be the struct we would&#8217;ve been directly feeding to the P\/Invoke function if we weren&#8217;t planning on doing any custom marshalling.<\/p>\n\n\n\n<h6>NOTIFYICONDATAW Struct<\/h6>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary&gt;\n\/\/\/ Represents information that the system needs to display notifications in the notification area.\n\/\/\/ &lt;\/summary&gt;\n[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\ninternal struct NOTIFYICONDATAW\n{\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ The size of this structure in bytes.\n    \/\/\/ &lt;\/summary&gt;\n    public uint cbSize;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ A handle to the window that receives notifications associated with an icon in\n    \/\/\/ the notification area.\n    \/\/\/ &lt;\/summary&gt;\n    public IntPtr hWnd;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ The application-defined identifier of the taskbar icon.\n    \/\/\/ &lt;\/summary&gt;\n    public uint uID;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Flags that either indicate which of the other members of the structure contain valid data\n    \/\/\/ or provide additional information to the tooltip as to how it should display.\n    \/\/\/ &lt;\/summary&gt;\n    public NotifyIconFlags uFlags;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ An application-defined message identifier.\n    \/\/\/ &lt;\/summary&gt;\n    public uint uCallbackMessage;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ A handle to the icon to be added, modified, or deleted.\n    \/\/\/ &lt;\/summary&gt;\n    public IntPtr hIcon;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ A null-terminated string that specifies the text for a standard tooltip.\n    \/\/\/ &lt;\/summary&gt;\n    public fixed char szTip[128];\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ The state of the icon.\n    \/\/\/ &lt;\/summary&gt;\n    public uint dwState;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ A value that specifies which bits of the &lt;see cref=&quot;dwState&quot;\/&gt; member are retrieved\n    \/\/\/ or modified.\n    \/\/\/ &lt;\/summary&gt;\n    public uint dwStateMask;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ A null-terminated string that specifies the text to display in a balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    public fixed char szInfo[256];\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Either the timeout value, in milliseconds, for the notification, or a specification of which\n    \/\/\/ version of the Shell notification icon interface should be used.\n    \/\/\/ &lt;\/summary&gt;\n    public uint uTimeoutOrVersion;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ A null-terminated string that specifies the title for a balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    public fixed char szInfoTitle[64];\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Flags that can be set to modify the behavior and appearance of a balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    public NotifyIconInfoFlags dwInfoFlags;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ A registered &lt;see cref=&quot;GUID&quot;\/&gt; that identifies the icon. This is the preferred way to\n    \/\/\/ identify an icon in modern OS versions.\n    \/\/\/ &lt;\/summary&gt;\n    public GUID guidItem;\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ A handle to a customized notification icon that should be used independently of the\n    \/\/\/ notification area icon.\n    \/\/\/ &lt;\/summary&gt;\n    public IntPtr hBalloonIcon;\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets a string that specifies the text for a standard tooltip.\n    \/\/\/ &lt;\/summary&gt;\n    public ReadOnlySpan&lt;char&gt; Tip\n    {\n        get =&gt; SzTip.SliceAtFirstNull();\n        set =&gt; value.CopyToAndTerminate(SzTip);\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets a string that specifies the text to display in a balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    public ReadOnlySpan&lt;char&gt; Info\n    {\n        get =&gt; SzInfo.SliceAtFirstNull();\n        set =&gt; value.CopyToAndTerminate(SzInfo);\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets or sets a string that specifies a title for a balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    public ReadOnlySpan&lt;char&gt; InfoTitle\n    {\n        get =&gt; SzInfoTitle.SliceAtFirstNull();\n        set =&gt; value.CopyToAndTerminate(SzInfoTitle);\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets a null-terminated string that specifies the text for a standard tooltip.\n    \/\/\/ &lt;\/summary&gt;\n    private Span&lt;char&gt; SzTip\n    {\n        get\n        {\n            fixed (char* c = szTip)\n            {\n                return new Span&lt;char&gt;(c, 128);\n            }\n        }\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets a null-terminated string that specifies the text to display in a balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    private Span&lt;char&gt; SzInfo\n    {\n        get\n        {\n            fixed (char* c = szInfo)\n            {\n                return new Span&lt;char&gt;(c, 256);\n            }\n        }\n    }\n\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Gets a null-terminated string that specifies a title for a balloon notification.\n    \/\/\/ &lt;\/summary&gt;\n    private Span&lt;char&gt; SzInfoTitle\n    {\n        get\n        {\n            fixed (char* c = szInfoTitle)\n            {\n                return new Span&lt;char&gt;(c, 64);\n            }\n        }\n    }\n}\n<\/pre>\n\n\n<p>The only other thing to add here is that it is common practice to include the unmanaged data type as a nested type inside the custom marshaller (which we will be covering next). This discourages its use outside of the marshaller.<\/p>\n\n\n\n<p>Now, let&#8217;s write that marshaller!<\/p>\n\n\n\n<h3>Our Custom Stateful Marshaller<\/h3>\n\n\n\n<p>On to the main show. We will be writing a custom stateful marshaller that will marshal notification area information containing a number of custom <code>SafeHandle<\/code> types.<\/p>\n\n\n\n<p>Most of the time, a custom marshaller will be stateless and consist only of a static class with a few required static methods.<\/p>\n\n\n\n<p>For a stateful marshaller, we need a static class (which will be referenced by the <code>NativeMarshallingAttribute<\/code> adorning our managed data type) and then, inside of that, an inner struct that will hold state information and provide the marshalling methods.<\/p>\n\n\n\n<h6><a href=\"https:\/\/github.com\/BadEcho\/core\/blob\/master\/src\/Common\/Interop\/NotifyIconDataMarshaller.cs\" target=\"_blank\" rel=\"noreferrer noopener\">NotifyIconDataMarshaller.cs<\/a><\/h6>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary&gt;\n\/\/\/ Provides a custom marshaller for notification area information.\n\/\/\/ &lt;\/summary&gt;\n[CustomMarshaller(\n    typeof(NotifyIconData), MarshalMode.ManagedToUnmanagedRef, typeof(ManagedToUnmanagedRef))]\ninternal static unsafe class NotifyIconDataMarshaller\n{\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Represents a stateful marshaller for notification area information.\n    \/\/\/ &lt;\/summary&gt;\n    public ref struct ManagedToUnmanagedRef\n    {\n        private NOTIFYICONDATAW _unmanaged;\n        private WindowHandle _windowHandle;\n        private IconHandle? _iconHandle;\n        private IconHandle? _balloonIconHandle;\n        private bool _windowHandleAddRefd;\n        private bool _iconHandleAddRefd;\n        private bool _balloonIconHandleAddRefd;\n        private IntPtr _originalWindowHandleValue;\n        private IntPtr _originalIconHandleValue;\n        private IntPtr _originalBalloonIconHandleValue;\n\n        \/\/\/ &lt;summary&gt;\n        \/\/\/ Converts a managed &lt;see cref=&quot;NotifyIconData&quot;\/&gt; instance to its unmanaged counterpart,\n        \/\/\/ loading the result into the marshaller.\n        \/\/\/ &lt;\/summary&gt;\n        \/\/\/ &lt;param name=&quot;iconData&quot;&gt;A managed instance of notification area information.&lt;\/param&gt;\n        public void FromManaged(NotifyIconData iconData)\n        {\n            Require.NotNull(iconData, nameof(iconData));\n\n            _windowHandleAddRefd = false;\n            _iconHandleAddRefd = false;\n            _balloonIconHandleAddRefd = false;\n\n            _windowHandle = iconData.Window;\n            _iconHandle = iconData.Icon;\n            _balloonIconHandle = iconData.BalloonIcon;\n\n            _unmanaged.cbSize = (uint) sizeof(NOTIFYICONDATAW);\n            _windowHandle.DangerousAddRef(ref _windowHandleAddRefd);\n            _unmanaged.hWnd = _originalWindowHandleValue = _windowHandle.DangerousGetHandle();\n            _unmanaged.guidItem = GuidMarshaller.ConvertToUnmanaged(iconData.Id);\n            _unmanaged.uFlags = iconData.Flags;\n            _unmanaged.uCallbackMessage = iconData.CallbackMessage;\n\n            if (_iconHandle != null)\n            {\n                _iconHandle.DangerousAddRef(ref _iconHandleAddRefd);\n                _unmanaged.hIcon = _originalIconHandleValue = _iconHandle.DangerousGetHandle();\n            }\n\n            _unmanaged.dwState = iconData.State;\n            _unmanaged.dwStateMask = iconData.StateMask;\n            _unmanaged.uTimeoutOrVersion = iconData.TimeoutOrVersion;\n            _unmanaged.dwInfoFlags = iconData.InfoFlags;\n\n            if (_balloonIconHandle != null)\n            {\n                _balloonIconHandle.DangerousAddRef(ref _balloonIconHandleAddRefd);\n                _unmanaged.hBalloonIcon \n                    = _originalBalloonIconHandleValue = _balloonIconHandle.DangerousGetHandle();\n            }\n\n            _unmanaged.Tip = iconData.Tip;\n            _unmanaged.Info = iconData.Info;\n            _unmanaged.InfoTitle = iconData.InfoTitle;\n        }\n\n        \/\/\/ &lt;summary&gt;\n        \/\/\/ Provides the unmanaged notification area information currently loaded into the\n        \/\/\/ marshaller.\n        \/\/\/ &lt;\/summary&gt;\n        \/\/\/ &lt;returns&gt;The converted &lt;see cref=&quot;NOTIFYICONDATAW&quot;\/&gt; value.&lt;\/returns&gt;\n        public NOTIFYICONDATAW ToUnmanaged()\n            =&gt; _unmanaged;\n\n        \/\/\/ &lt;summary&gt;\n        \/\/\/ Loads the provided unmanaged notification area information into the\n        \/\/\/ marshaller.\n        \/\/\/ &lt;\/summary&gt;\n        \/\/\/ &lt;param name=&quot;unmanaged&quot;&gt;The unmanaged instance of notification area information.&lt;\/param&gt;\n        public void FromUnmanaged(NOTIFYICONDATAW unmanaged)\n            =&gt; _unmanaged = unmanaged;\n\n        \/\/\/ &lt;summary&gt;\n        \/\/\/ Converts the unmanaged &lt;see cref=&quot;NOTIFYICONDATAW&quot;\/&gt; instance currently loaded into\n        \/\/\/ the marshaller into its managed counterpart, returning the result.\n        \/\/\/ &lt;\/summary&gt;\n        \/\/\/ &lt;returns&gt;The converted &lt;see cref=&quot;NotifyIconData&quot;\/&gt; instance.&lt;\/returns&gt;\n        \/\/\/ &lt;exception cref=&quot;NotSupportedException&quot;&gt;\n        \/\/\/ A handle originating from a &lt;see cref=&quot;SafeHandle&quot;\/&gt; was changed.\n        \/\/\/ &lt;\/exception&gt;\n        public NotifyIconData ToManaged()\n        {\n            \/\/ SafeHandle fields must match the underlying handle value during marshalling.\n            \/\/ They cannot change.\n            if (_unmanaged.hWnd != _originalWindowHandleValue)\n                throw new NotSupportedException(Strings.HandleCannotChangeDuringMarshalling);\n\n            if (_unmanaged.hIcon != _originalIconHandleValue)\n                throw new NotSupportedException(Strings.HandleCannotChangeDuringMarshalling);\n\n            if (_unmanaged.hBalloonIcon != _originalBalloonIconHandleValue)\n                throw new NotSupportedException(Strings.HandleCannotChangeDuringMarshalling);\n\n            Guid managedId = GuidMarshaller.ConvertToManaged(_unmanaged.guidItem);\n            \n            return new NotifyIconData(_windowHandle, managedId, _unmanaged.uFlags)\n                   {\n                       CallbackMessage = _unmanaged.uCallbackMessage,\n                       Icon = _iconHandle,\n                       State = _unmanaged.dwState,\n                       StateMask = _unmanaged.dwStateMask,\n                       TimeoutOrVersion = _unmanaged.uTimeoutOrVersion,\n                       InfoFlags = _unmanaged.dwInfoFlags,\n                       BalloonIcon = _balloonIconHandle,\n                       Tip = new string(_unmanaged.Tip),\n                       Info = new string(_unmanaged.Info),\n                       InfoTitle = new string(_unmanaged.InfoTitle)\n                   };\n        }\n\n        \/\/\/ &lt;summary&gt;\n        \/\/\/ Releases all resources in use by the marshaller.\n        \/\/\/ &lt;\/summary&gt;\n        public void Free()\n        {\n            if (_windowHandleAddRefd)\n                _windowHandle.DangerousRelease();\n\n            if (_iconHandle != null &amp;&amp; _iconHandleAddRefd)\n                _iconHandle.DangerousRelease();\n\n            if (_balloonIconHandle != null &amp;&amp; _balloonIconHandleAddRefd)\n                _balloonIconHandle.DangerousRelease();\n        }\n    }\n}\n<\/pre>\n\n\n<p>During managed-to-unmanaged conversion in the <code>FromManaged<\/code> method, we call <code>DangerousAddRef<\/code> on all the provided <code>SafeHandle<\/code> instances and store the <code>bool<\/code> value indicating whether or not the reference counter was successfully incremented.<\/p>\n\n\n\n<p>After that, we call <code>DangerousGetHandle<\/code> for each <code>SafeHandle<\/code> present and store the resulting system handles both in our marshalling struct as well as the <code>NOTIFYICONDATAW<\/code> struct which we&#8217;re populating. <\/p>\n\n\n\n<p>We keep a backup of the original handles in order to see if their values have changed at all when the <code>ToManaged<\/code> method executes; something which we cannot support given that they originated from <code>SafeHandle<\/code> types.<\/p>\n\n\n\n<p>Finally, in the <code>Free<\/code> method, we make good on our attempt to keep our <code>SafeHandle<\/code> instances &#8220;safe&#8221; and call the <code>DangerousRelease<\/code> method for each handle whose reference counter was previously incremented.<\/p>\n\n\n\n<h2>SafeHandles and Structs Living in Harmony<\/h2>\n\n\n\n<p>We&#8217;re done! Our P\/Invoke signature for <code>Shell_NotifyIcon<\/code> should now be error-free.<\/p>\n\n\n\n<h6>Shell_NotifyIcon P\/Invoke Signature<\/h6>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary&gt;\n\/\/\/ Sends a message to the taskbar's status area.\n\/\/\/ &lt;\/summary&gt;\n\/\/\/ &lt;param name=&quot;dwMessage&quot;&gt;A value that specifies the action to be taken by this function.&lt;\/param&gt;\n\/\/\/ &lt;param name=&quot;lpData&quot;&gt;\n\/\/\/ A &lt;see cref=&quot;NotifyIconData&quot;\/&gt; instance containing notification area information.\n\/\/\/ &lt;\/param&gt;\n\/\/\/ &lt;returns&gt;True if successful; otherwise, false.&lt;\/returns&gt;\n[LibraryImport(LIBRARY_NAME, EntryPoint = &quot;Shell_NotifyIconW&quot;)]\n[return: MarshalAs(UnmanagedType.Bool)]\npublic static partial bool Shell_NotifyIcon(NotifyIconMessage dwMessage, ref NotifyIconData lpData);\n<\/pre>\n\n\n<p>Let&#8217;s try it out. The following code was tested and executed successfully.<\/p>\n\n\n\n<h6>Shell_NotifyIcon Usage with SafeHandles<\/h6>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nvar iconData\n    = new NotifyIconData(windowHandle,\n                         _id,\n                         NotifyIconFlags.Message | NotifyIconFlags.Icon | NotifyIconFlags.Tip)\n      {\n          CallbackMessage = (uint) _TrayEvent,\n          Icon = iconHandle,\n          Tip = _tip\n      };\n\nShell32.Shell_NotifyIcon(NotifyIconMessage.Add, ref iconData);\n<\/pre>\n\n\n<p>Mission accomplished! We can all rest easier at night with our <code>SafeHandle<\/code> instances now being able to be passed into those pesky P\/Invoke methods requiring C-style structs. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>SafeHandles provide reliable and secure means of managing the lifetime of unmanaged resources. It&#8217;s commonly recommended to use SafeHandle instead [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[10],"tags":[41,42,78,79],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v14.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\r\n<title>Using SafeHandles in Structs via Stateful Marshalling - omni&#039;s hackpad<\/title>\r\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\r\n<link rel=\"canonical\" href=\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/\" \/>\r\n<meta property=\"og:locale\" content=\"en_US\" \/>\r\n<meta property=\"og:type\" content=\"article\" \/>\r\n<meta property=\"og:title\" content=\"Using SafeHandles in Structs via Stateful Marshalling - omni&#039;s hackpad\" \/>\r\n<meta property=\"og:description\" content=\"SafeHandles provide reliable and secure means of managing the lifetime of unmanaged resources. It&#8217;s commonly recommended to use SafeHandle instead [&hellip;]\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/\" \/>\r\n<meta property=\"og:site_name\" content=\"omni&#039;s hackpad\" \/>\r\n<meta property=\"article:published_time\" content=\"2023-02-08T03:36:42+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2023-02-28T17:08:55+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/badecho.com\/wp-content\/uploads\/2023\/02\/StatefulMarshalling.png\" \/>\r\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\r\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/badecho.com\/#website\",\"url\":\"https:\/\/badecho.com\/\",\"name\":\"omni&#039;s hackpad\",\"description\":\"Game Code Disassembly. Omnified Modification. Madness.\",\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/badecho.com\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/badecho.com\/wp-content\/uploads\/2023\/02\/StatefulMarshalling.png\",\"width\":856,\"height\":448,\"caption\":\"Using SafeHandles in Structs via Stateful Marshalling\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/#webpage\",\"url\":\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/\",\"name\":\"Using SafeHandles in Structs via Stateful Marshalling - omni&#039;s hackpad\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/#primaryimage\"},\"datePublished\":\"2023-02-08T03:36:42+00:00\",\"dateModified\":\"2023-02-28T17:08:55+00:00\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/\"]}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/#webpage\"},\"author\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"headline\":\"Using SafeHandles in Structs via Stateful Marshalling\",\"datePublished\":\"2023-02-08T03:36:42+00:00\",\"dateModified\":\"2023-02-28T17:08:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/#webpage\"},\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"image\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/#primaryimage\"},\"keywords\":\".NET,C#,P\/Invoke,SafeHandle\",\"articleSection\":\"General Dev\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/badecho.com\/index.php\/2023\/02\/07\/safehandles-in-structs\/#respond\"]}]},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\",\"name\":\"Matt Weber\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/badecho.com\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/7e345ac2708b3a41c7bd70a4a0440d41?s=96&d=mm&r=g\",\"caption\":\"Matt Weber\"},\"logo\":{\"@id\":\"https:\/\/badecho.com\/#personlogo\"}}]}<\/script>\r\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/2613"}],"collection":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/comments?post=2613"}],"version-history":[{"count":38,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/2613\/revisions"}],"predecessor-version":[{"id":2662,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/2613\/revisions\/2662"}],"wp:attachment":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/media?parent=2613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/categories?post=2613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/tags?post=2613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}