mirror of https://github.com/dahall/Vanara.git
Refactored base handle structures into templates
parent
660215dc19
commit
677081358a
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,229 @@
|
|||
<#@ template debug="false" hostspecific="false" language="C#" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
<#@ import namespace="System.Text" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<# var classes = new List<(string name, string inheritance, string summaryText)> {
|
||||
( "HACCEL", "IUserHandle", "Provides a handle to an accelerator table." ),
|
||||
( "HANDLE", "IHandle", "Provides a generic handle." ),
|
||||
( "HBITMAP", "IGraphicsObjectHandle", "Provides a handle to a bitmap." ),
|
||||
( "HBRUSH", "IGraphicsObjectHandle", "Provides a handle to drawing brush." ),
|
||||
( "HCOLORSPACE", "IGraphicsObjectHandle", "Provides a handle to a color space." ),
|
||||
( "HCURSOR", "IGraphicsObjectHandle", "Provides a handle to cursor." ),
|
||||
( "HDC", "IHandle", "Provides a handle to a graphic device context." ),
|
||||
( "HDESK", "IKernelHandle", "Provides a handle to a desktop." ),
|
||||
( "HDPA", "IKernelHandle", "Provides a handle to a DPA." ),
|
||||
( "HDROP", "IShellHandle", "Provides a handle to a Windows drop operation." ),
|
||||
( "HDSA", "IKernelHandle", "Provides a handle to a DSA." ),
|
||||
( "HDWP", "IUserHandle", "Provides a handle to a deferred windows position." ),
|
||||
( "HENHMETAFILE", "IHandle", "Provides a handle to an enhanced metafile." ),
|
||||
( "HEVENT", "ISyncHandle", "Provides a handle to a sync event." ),
|
||||
( "HFILE", "ISyncHandle", "Provides a handle to a file." ),
|
||||
( "HFONT", "IGraphicsObjectHandle", "Provides a handle to a font." ),
|
||||
( "HGDIOBJ", "IGraphicsObjectHandle", "Provides a handle to a graphic device object." ), // implicit ops from other handles
|
||||
( "HICON", "IUserHandle", "Provides a handle to an icon." ),
|
||||
( "HIMAGELIST", "IShellHandle", "Provides a handle to a Windows image list." ),
|
||||
( "HINSTANCE", "IKernelHandle", "Provides a handle to a module or library instance." ),
|
||||
( "HKEY", "IKernelHandle", "Provides a handle to a Windows registry key." ),
|
||||
( "HMENU", "IUserHandle", "Provides a handle to a menu." ),
|
||||
( "HMETAFILE", "IHandle", "Provides a handle to a metafile." ),
|
||||
( "HMONITOR", "IKernelHandle", "Provides a handle to a monitor." ),
|
||||
( "HPALETTE", "IGraphicsObjectHandle", "Provides a handle to a palette." ),
|
||||
( "HPEN", "IGraphicsObjectHandle", "Provides a handle to a drawing pen." ),
|
||||
( "HPROCESS", "ISyncHandle", "Provides a handle to a process." ), // implicit Process
|
||||
( "HPROPSHEET", "IUserHandle", "Provides a handle to a Windows property sheet." ),
|
||||
( "HPROPSHEETPAGE", "IUserHandle", "Provides a handle to a property sheet page." ),
|
||||
( "HRGN", "IGraphicsObjectHandle", "Provides a handle to a drawing region." ),
|
||||
( "HSECTION", "IHandle", "Provides a handle to a file mapping object." ),
|
||||
( "HTASK", "IHandle", "Provides a handle to a blocking task." ),
|
||||
( "HTHEME", "IHandle", "Provides a handle to a Windows theme." ),
|
||||
( "HTHREAD", "ISyncHandle", "Provides a handle to a thread." ),
|
||||
( "HTHUMBNAIL", "IShellHandle", "Provides a handle to a Windows thumbnail." ),
|
||||
( "HTOKEN", "IKernelHandle", "Provides a handle to an access token." ),
|
||||
( "HWINSTA", "IKernelHandle", "Provides a handle to a windows station." ),
|
||||
( "HWND", "IUserHandle", "Provides a handle to a window or dialog." ), // constants
|
||||
( "PACE", "ISecurityObject", "Provides a pointer to an access control entry." ),
|
||||
( "PACL", "ISecurityObject", "Provides a handle to an access control list." ),
|
||||
( "PSECURITY_DESCRIPTOR", "ISecurityObject", "Provides a handle to a security descriptor." ),
|
||||
( "PSID", "ISecurityObject", "Provides a handle to a security identifier." ),
|
||||
}; #>
|
||||
<# var casts = new Dictionary<string, (string, string, string)> {
|
||||
{ "HANDLE", ("HANDLE", "SafeHandle", "h.DangerousGetHandle()" ) },
|
||||
{ "HKEY", ("HKEY", "SafeRegistryHandle", "h.DangerousGetHandle()" ) },
|
||||
{ "HPROCESS", ("HPROCESS", "Process", "h.Handle" ) },
|
||||
}; #>
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Vanara.PInvoke;
|
||||
|
||||
<# foreach (var (name, inheritance, summaryText) in classes) { #>
|
||||
/// <summary><#= summaryText #></summary>
|
||||
[StructLayout(LayoutKind.Sequential), DebuggerDisplay("{handle}")]
|
||||
public struct <#= name #> : <#= inheritance #>
|
||||
{
|
||||
private readonly IntPtr handle;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="<#= name #>"/> struct.</summary>
|
||||
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||
public <#= name #>(IntPtr preexistingHandle) => handle = preexistingHandle;
|
||||
|
||||
/// <summary>Returns an invalid handle by instantiating a <see cref="<#= name #>"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
||||
public static <#= name #> NULL => new(IntPtr.Zero);
|
||||
|
||||
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
||||
public bool IsNull => handle == IntPtr.Zero;
|
||||
|
||||
<# if (name == "HFILE") { #>
|
||||
/// <summary>Represents an invalid handle.</summary>
|
||||
public static readonly HFILE INVALID_HANDLE_VALUE = new IntPtr(-1);
|
||||
|
||||
/// <summary>Gets a value indicating whether this instance is an invalid handle (INVALID_HANDLE_VALUE).</summary>
|
||||
public bool IsInvalid => handle == INVALID_HANDLE_VALUE;
|
||||
|
||||
/// <summary>Performs an implicit conversion from <see cref="SafeFileHandle"/> to <see cref="HFILE"/>.</summary>
|
||||
/// <param name="h">The pointer to a handle.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator HFILE(SafeFileHandle h) => new(h?.DangerousGetHandle() ?? IntPtr.Zero);
|
||||
|
||||
<# } #>
|
||||
<# if (name == "HWND") { #>
|
||||
/// <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>
|
||||
/// Used by <c>SendMessage</c> and <c>PostMessage</c> to send a message to all top-level windows in the system, including disabled or
|
||||
/// invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.
|
||||
/// </summary>
|
||||
public static HWND HWND_BROADCAST = new IntPtr(0xffff);
|
||||
|
||||
/// <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);
|
||||
|
||||
<# } #>
|
||||
<# if (name == "HKEY") { #>
|
||||
/// <summary>
|
||||
/// Registry entries subordinate to this key define types (or classes) of documents and the properties associated with those types.
|
||||
/// Shell and COM applications use the information stored under this key.
|
||||
/// </summary>
|
||||
public static readonly HKEY HKEY_CLASSES_ROOT = new(new IntPtr(unchecked((int)0x80000000)));
|
||||
|
||||
/// <summary>
|
||||
/// Contains information about the current hardware profile of the local computer system. The information under HKEY_CURRENT_CONFIG
|
||||
/// describes only the differences between the current hardware configuration and the standard configuration. Information about the
|
||||
/// standard hardware configuration is stored under the Software and System keys of HKEY_LOCAL_MACHINE.
|
||||
/// </summary>
|
||||
public static readonly HKEY HKEY_CURRENT_CONFIG = new(new IntPtr(unchecked((int)0x80000005)));
|
||||
|
||||
/// <summary>
|
||||
/// Registry entries subordinate to this key define the preferences of the current user. These preferences include the settings of
|
||||
/// environment variables, data about program groups, colors, printers, network connections, and application preferences. This key
|
||||
/// makes it easier to establish the current user's settings; the key maps to the current user's branch in HKEY_USERS. In
|
||||
/// HKEY_CURRENT_USER, software vendors store the current user-specific preferences to be used within their applications. Microsoft,
|
||||
/// for example, creates the HKEY_CURRENT_USER\Software\Microsoft key for its applications to use, with each application creating its
|
||||
/// own subkey under the Microsoft key.
|
||||
/// </summary>
|
||||
public static readonly HKEY HKEY_CURRENT_USER = new(new IntPtr(unchecked((int)0x80000001)));
|
||||
|
||||
/// <summary></summary>
|
||||
public static readonly HKEY HKEY_DYN_DATA = new(new IntPtr(unchecked((int)0x80000006)));
|
||||
|
||||
/// <summary>
|
||||
/// Registry entries subordinate to this key define the physical state of the computer, including data about the bus type, system
|
||||
/// memory, and installed hardware and software. It contains subkeys that hold current configuration data, including Plug and Play
|
||||
/// information (the Enum branch, which includes a complete list of all hardware that has ever been on the system), network logon
|
||||
/// preferences, network security information, software-related information (such as server names and the location of the server),
|
||||
/// and other system information.
|
||||
/// </summary>
|
||||
public static readonly HKEY HKEY_LOCAL_MACHINE = new(new IntPtr(unchecked((int)0x80000002)));
|
||||
|
||||
/// <summary>
|
||||
/// Registry entries subordinate to this key allow you to access performance data. The data is not actually stored in the registry;
|
||||
/// the registry functions cause the system to collect the data from its source.
|
||||
/// </summary>
|
||||
public static readonly HKEY HKEY_PERFORMANCE_DATA = new(new IntPtr(unchecked((int)0x80000004)));
|
||||
|
||||
/// <summary>
|
||||
/// Registry entries subordinate to this key define the default user configuration for new users on the local computer and the user
|
||||
/// configuration for the current user.
|
||||
/// </summary>
|
||||
public static readonly HKEY HKEY_USERS = new(new IntPtr(unchecked((int)0x80000003)));
|
||||
|
||||
<# } #>
|
||||
/// <summary>Performs an explicit conversion from <see cref="<#= name #>"/> to <see cref="IntPtr"/>.</summary>
|
||||
/// <param name="h">The handle.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static explicit operator IntPtr(<#= name #> h) => h.handle;
|
||||
|
||||
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="<#= name #>"/>.</summary>
|
||||
/// <param name="h">The pointer to a handle.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator <#= name #>(IntPtr h) => new(h);
|
||||
|
||||
<# if (casts.TryGetValue(name, out var value)) { #>
|
||||
/// <summary>Performs an implicit conversion from <see cref="<#= value.Item1 #>"/> to <see cref="<#= value.Item2 #>"/>.</summary>
|
||||
/// <param name="h">The pointer to a handle.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator <#= value.Item1 #>(<#= value.Item2 #> h) => new(<#= value.Item3 #>);
|
||||
|
||||
<# } #>
|
||||
<# if (name == "HGDIOBJ") { foreach (var res in classes.Where(r => r.name != "HGDIOBJ" && r.inheritance == "IGraphicsObjectHandle")) {#>
|
||||
/// <summary>Performs an implicit conversion from <see cref="<#= res.name #>"/> to <see cref="HGDIOBJ"/>.</summary>
|
||||
/// <param name="h">The pointer to a handle.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator HGDIOBJ(<#= res.name #> h) => new((IntPtr)h);
|
||||
|
||||
<# } } #>
|
||||
<# if (name != "HGDIOBJ" && inheritance == "IGraphicsObjectHandle") { #>
|
||||
/// <summary>Performs an implicit conversion from <see cref="HGDIOBJ"/> to <see cref="<#= name #>"/>.</summary>
|
||||
/// <param name="h">The pointer to a GDI handle.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator <#= name #>(HGDIOBJ h) => new((IntPtr)h);
|
||||
|
||||
<# } #>
|
||||
/// <summary>Implements the operator ! which returns <see langword="true"/> if the handle is invalid.</summary>
|
||||
/// <param name="hMem">The <see cref="<#= name #>"/> instance.</param>
|
||||
/// <returns>The result of the operator.</returns>
|
||||
public static bool operator !(<#= name #> hMem) => hMem.IsNull;
|
||||
|
||||
/// <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 !=(<#= name #> h1, <#= name #> 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 ==(<#= name #> h1, <#= name #> h2) => h1.Equals(h2);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj) => obj is <#= name #> h && handle == h.handle;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode() => handle.GetHashCode();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IntPtr DangerousGetHandle() => handle;
|
||||
}
|
||||
|
||||
<# } #>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,124 @@
|
|||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Vanara.PInvoke
|
||||
{
|
||||
/// <summary>Base class for all native handles.</summary>
|
||||
/// <seealso cref="SafeHandleZeroOrMinusOneIsInvalid"/>
|
||||
/// <seealso cref="IEquatable{T}"/>
|
||||
/// <seealso cref="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 ! which returns <see langword="true"/> if the handle is invalid.</summary>
|
||||
/// <param name="hMem">The <see cref="SafeHANDLE"/> instance.</param>
|
||||
/// <returns>The result of the operator.</returns>
|
||||
public static bool operator !(SafeHANDLE hMem) => hMem.IsInvalid;
|
||||
|
||||
/// <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, 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, 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?.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) => ReferenceEquals(this, other) || other is not null && handle == other.handle && IsClosed == other.IsClosed;
|
||||
|
||||
/// <summary>Determines whether the specified <see cref="object"/>, is equal to this instance.</summary>
|
||||
/// <param name="obj">The <see cref="object"/> to compare with this instance.</param>
|
||||
/// <returns><c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
|
||||
public override bool Equals(object obj) => obj switch
|
||||
{
|
||||
IHandle ih => handle.Equals(ih.DangerousGetHandle()),
|
||||
SafeHandle sh => handle.Equals(sh.DangerousGetHandle()),
|
||||
IntPtr p => handle.Equals(p),
|
||||
_ => 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;
|
||||
}
|
||||
|
||||
void X()
|
||||
{
|
||||
var classes = new System.Collections.Generic.List<(string name, string inheritance, string summaryText)> {
|
||||
( "LPSTR", "LPTSTR", "LPWSTR" ),
|
||||
};
|
||||
|
||||
var casts = new System.Collections.Generic.Dictionary<string, (string, string)> {
|
||||
{ "HANDLE", ("HANDLE", "SafeHandle" ) },
|
||||
{ "HPROCESS", ("Process", "SafeHandle" ) },
|
||||
};
|
||||
|
||||
foreach (var (name, inheritance, summaryText) in classes)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,10 +28,33 @@ CharacterSet, CM_DEVCAP, CM_FILE, CM_INSTALL_STATE, CM_REMOVAL_POLICY, CM_RESOUR
|
|||
</PackageReleaseNotes>
|
||||
<PackageReadmeFile>pkgreadme.md</PackageReadmeFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Handles\HANDLE.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>HANDLE.tt</DependentUpon>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\Vanara.Core.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) Or $(TargetFramework.StartsWith('netcore')) Or $(TargetFramework.StartsWith('net5.0')) Or $(TargetFramework.StartsWith('net6.0')) ">
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Handles\HANDLE.tt">
|
||||
<Generator>TextTemplatingFileGenerator</Generator>
|
||||
<LastGenOutput>HANDLE.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Handles\HANDLE.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>HANDLE.tt</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue