using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using Vanara.Extensions; namespace Vanara.InteropServices { /// The GuidPtr structure represents a LPGUID. [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{ptr}, {ToString()}")] public struct GuidPtr : IEquatable, IEquatable, IEquatable { private IntPtr ptr; /// Initializes a new instance of the struct by allocating memory with . /// The guid value. public GuidPtr(Guid g) => ptr = g.MarshalToPtr(Marshal.AllocCoTaskMem, out _); /// Gets a value indicating whether this instance is equivalent to null pointer or void*. /// true if this instance is null; otherwise, false. public bool IsNull => ptr == IntPtr.Zero; /// Gets the value of the Guid. /// The value pointed to by this pointer. public Guid? Value => IsNull ? null : ptr.ToStructure(); /// Assigns a new Guid value to the pointer. /// The guid value. public void Assign(Guid g) { if (IsNull) ptr = g.MarshalToPtr(Marshal.AllocCoTaskMem, out _); else Marshal.StructureToPtr(g, ptr, true); } /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(Guid? other) => EqualityComparer.Default.Equals(Value, other); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(GuidPtr other) => Equals(other.ptr); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(IntPtr other) => EqualityComparer.Default.Equals(ptr, other); /// public override bool Equals(object obj) => obj switch { null => IsNull, IntPtr p => Equals(p), GuidPtr gp => Equals(gp), Guid g => Equals(g), _ => base.Equals(obj), }; /// Frees the unmanaged memory. public void Free() { Marshal.FreeCoTaskMem(ptr); ptr = IntPtr.Zero; } /// public override int GetHashCode() => ptr.GetHashCode(); /// public override string ToString() => Value?.ToString("B") ?? ""; /// Performs an implicit conversion from to . /// The pointer to a Guid. /// The result of the conversion. public static implicit operator Guid?(GuidPtr g) => g.Value; /// Performs an explicit conversion from to . /// The pointer to a Guid. /// The result of the conversion. public static explicit operator IntPtr(GuidPtr g) => g.ptr; /// Performs an implicit conversion from to . /// The pointer. /// The result of the conversion. public static implicit operator GuidPtr(IntPtr p) => new() { ptr = p }; /// Determines whether two specified instances of are equal. /// The first pointer or handle to compare. /// The second pointer or handle to compare. /// if equals ; otherwise, . public static bool operator ==(GuidPtr left, GuidPtr right) => left.Equals(right); /// Determines whether two specified instances of are not equal. /// The first pointer or handle to compare. /// The second pointer or handle to compare. /// if does not equal ; otherwise, . public static bool operator !=(GuidPtr left, GuidPtr right) => !left.Equals(right); } /// The StrPtr structure represents a LPWSTR. [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{ptr}, {ToString()}")] public struct StrPtrAnsi : IEquatable, IEquatable, IEquatable { private IntPtr ptr; /// Initializes a new instance of the struct. /// The string value. public StrPtrAnsi(string s) => ptr = StringHelper.AllocString(s, CharSet.Ansi); /// Initializes a new instance of the struct. /// Number of characters to reserve in memory. public StrPtrAnsi(uint charLen) => ptr = StringHelper.AllocChars(charLen, CharSet.Ansi); /// Gets a value indicating whether this instance is equivalent to null pointer or void*. /// true if this instance is null; otherwise, false. public bool IsNull => ptr == IntPtr.Zero; /// Indicates whether the specified string is or an empty string (""). /// /// if the value parameter is or an empty string (""); otherwise, . /// public bool IsNullOrEmpty => ptr == IntPtr.Zero || Marshal.ReadByte(ptr) == 0; /// Assigns a new string value to the pointer. /// The string value. public void Assign(string s) => StringHelper.RefreshString(ref ptr, out var _, s, CharSet.Ansi); /// Assigns a new string value to the pointer. /// The string value. /// The character count allocated. /// true if new memory was allocated for the string; false if otherwise. public bool Assign(string s, out uint charsAllocated) => StringHelper.RefreshString(ref ptr, out charsAllocated, s, CharSet.Ansi); /// Assigns an integer to the pointer for uses such as LPSTR_TEXTCALLBACK. /// The value to assign. public void AssignConstant(int value) { Free(); ptr = (IntPtr)value; } /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(IntPtr other) => EqualityComparer.Default.Equals(ptr, other); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(string other) => EqualityComparer.Default.Equals(this, other); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(StrPtrAnsi other) => Equals(other.ptr); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public override bool Equals(object obj) => obj switch { null => IsNull, string s => Equals(s), StrPtrAnsi p => Equals(p), IntPtr p => Equals(p), _ => base.Equals(obj), }; /// Frees the unmanaged string memory. public void Free() { StringHelper.FreeString(ptr, CharSet.Ansi); ptr = IntPtr.Zero; } /// Returns a hash code for this instance. /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. public override int GetHashCode() => ptr.GetHashCode(); /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => StringHelper.GetString(ptr, CharSet.Ansi) ?? "null"; /// Performs an implicit conversion from to . /// The instance. /// The result of the conversion. public static implicit operator string(StrPtrAnsi p) => p.IsNull ? null : p.ToString(); /// Performs an explicit conversion from to *. /// The * reference. /// The resulting * from the conversion. public static unsafe explicit operator sbyte*(StrPtrAnsi p) => (sbyte*)p.ptr; /// Performs an explicit conversion from to . /// The instance. /// The result of the conversion. public static explicit operator IntPtr(StrPtrAnsi p) => p.ptr; /// Performs an implicit conversion from to . /// The pointer. /// The result of the conversion. public static implicit operator StrPtrAnsi(IntPtr p) => new() { ptr = p }; /// Determines whether two specified instances of are equal. /// The first pointer or handle to compare. /// The second pointer or handle to compare. /// if equals ; otherwise, . public static bool operator ==(StrPtrAnsi left, StrPtrAnsi right) => left.Equals(right); /// Determines whether two specified instances of are not equal. /// The first pointer or handle to compare. /// The second pointer or handle to compare. /// if does not equal ; otherwise, . public static bool operator !=(StrPtrAnsi left, StrPtrAnsi right) => !left.Equals(right); } /// The StrPtr structure represents a LPTSTR. [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{ptr}, {ToString()}")] public struct StrPtrAuto : IEquatable, IEquatable, IEquatable { private IntPtr ptr; /// Initializes a new instance of the struct. /// The string value. public StrPtrAuto(string s) => ptr = StringHelper.AllocString(s); /// Initializes a new instance of the struct. /// Number of characters to reserve in memory. public StrPtrAuto(uint charLen) => ptr = StringHelper.AllocChars(charLen); /// Gets a value indicating whether this instance is equivalent to null pointer or void*. /// true if this instance is null; otherwise, false. public bool IsNull => ptr == IntPtr.Zero; /// Assigns a string pointer value to the pointer. /// The string pointer value. public void Assign(IntPtr stringPtr) { Free(); ptr = stringPtr; } /// Assigns a new string value to the pointer. /// The string value. public void Assign(string s) => StringHelper.RefreshString(ref ptr, out var _, s); /// Assigns a new string value to the pointer. /// The string value. /// The character count allocated. /// true if new memory was allocated for the string; false if otherwise. public bool Assign(string s, out uint charsAllocated) => StringHelper.RefreshString(ref ptr, out charsAllocated, s); /// Assigns an integer to the pointer for uses such as LPSTR_TEXTCALLBACK. /// The value to assign. public void AssignConstant(int value) { Free(); ptr = (IntPtr)value; } /// Frees the unmanaged string memory. public void Free() { StringHelper.FreeString(ptr); ptr = IntPtr.Zero; } /// Indicates whether the specified string is or an empty string (""). /// /// if the value parameter is or an empty string (""); otherwise, . /// public bool IsNullOrEmpty => ptr == IntPtr.Zero || StringHelper.GetString(ptr, CharSet.Auto, 1) == string.Empty; /// Performs an implicit conversion from to . /// The instance. /// The result of the conversion. public static implicit operator string(StrPtrAuto p) => p.IsNull ? null : p.ToString(); /// Performs an explicit conversion from to . /// The instance. /// The result of the conversion. public static explicit operator IntPtr(StrPtrAuto p) => p.ptr; /// Performs an implicit conversion from to . /// The pointer. /// The result of the conversion. public static implicit operator StrPtrAuto(IntPtr p) => new() { ptr = p }; /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(IntPtr other) => EqualityComparer.Default.Equals(ptr, other); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(string other) => EqualityComparer.Default.Equals(this, other); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(StrPtrAuto other) => Equals(other.ptr); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public override bool Equals(object obj) => obj switch { null => IsNull, string s => Equals(s), StrPtrAuto p => Equals(p), IntPtr p => Equals(p), _ => base.Equals(obj), }; /// Returns a hash code for this instance. /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. public override int GetHashCode() => ptr.GetHashCode(); /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => StringHelper.GetString(ptr) ?? "null"; /// Determines whether two specified instances of are equal. /// The first pointer or handle to compare. /// The second pointer or handle to compare. /// if equals ; otherwise, . public static bool operator ==(StrPtrAuto left, StrPtrAuto right) => left.Equals(right); /// Determines whether two specified instances of are not equal. /// The first pointer or handle to compare. /// The second pointer or handle to compare. /// if does not equal ; otherwise, . public static bool operator !=(StrPtrAuto left, StrPtrAuto right) => !left.Equals(right); } /// The StrPtr structure represents a LPWSTR. [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{ptr}, {ToString()}")] public struct StrPtrUni : IEquatable, IEquatable, IEquatable { private IntPtr ptr; /// Initializes a new instance of the struct. /// The string value. public StrPtrUni(string s) => ptr = StringHelper.AllocString(s, CharSet.Unicode); /// Initializes a new instance of the struct. /// Number of characters to reserve in memory. public StrPtrUni(uint charLen) => ptr = StringHelper.AllocChars(charLen, CharSet.Unicode); /// Gets a value indicating whether this instance is equivalent to null pointer or void*. /// true if this instance is null; otherwise, false. public bool IsNull => ptr == IntPtr.Zero; /// Assigns a new string value to the pointer. /// The string value. public void Assign(string s) => StringHelper.RefreshString(ref ptr, out var _, s, CharSet.Unicode); /// Assigns a new string value to the pointer. /// The string value. /// The character count allocated. /// true if new memory was allocated for the string; false if otherwise. public bool Assign(string s, out uint charsAllocated) => StringHelper.RefreshString(ref ptr, out charsAllocated, s, CharSet.Unicode); /// Assigns an integer to the pointer for uses such as LPSTR_TEXTCALLBACK. /// The value to assign. public void AssignConstant(int value) { Free(); ptr = (IntPtr)value; } /// Frees the unmanaged string memory. public void Free() { StringHelper.FreeString(ptr, CharSet.Unicode); ptr = IntPtr.Zero; } /// Indicates whether the specified string is or an empty string (""). /// /// if the value parameter is or an empty string (""); otherwise, . /// public bool IsNullOrEmpty => ptr == IntPtr.Zero || Marshal.ReadInt16(ptr) == 0; /// Performs an implicit conversion from to . /// The instance. /// The result of the conversion. public static implicit operator string(StrPtrUni p) => p.IsNull ? null : p.ToString(); /// Performs an explicit conversion from to *. /// The * reference. /// The resulting * from the conversion. public static unsafe explicit operator char*(StrPtrUni p) => (char*)p.ptr; /// Performs an explicit conversion from to . /// The instance. /// The result of the conversion. public static explicit operator IntPtr(StrPtrUni p) => p.ptr; /// Performs an implicit conversion from to . /// The pointer. /// The result of the conversion. public static implicit operator StrPtrUni(IntPtr p) => new() { ptr = p }; /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(IntPtr other) => EqualityComparer.Default.Equals(ptr, other); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(string other) => EqualityComparer.Default.Equals(this, other); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public bool Equals(StrPtrUni other) => Equals(other.ptr); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public override bool Equals(object obj) => obj switch { null => IsNull, string s => Equals(s), StrPtrUni p => Equals(p), IntPtr p => Equals(p), _ => base.Equals(obj), }; /// Returns a hash code for this instance. /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. public override int GetHashCode() => ptr.GetHashCode(); /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => StringHelper.GetString(ptr, CharSet.Unicode) ?? "null"; /// Determines whether two specified instances of are equal. /// The first pointer or handle to compare. /// The second pointer or handle to compare. /// if equals ; otherwise, . public static bool operator ==(StrPtrUni left, StrPtrUni right) => left.Equals(right); /// Determines whether two specified instances of are not equal. /// The first pointer or handle to compare. /// The second pointer or handle to compare. /// if does not equal ; otherwise, . public static bool operator !=(StrPtrUni left, StrPtrUni right) => !left.Equals(right); } /// /// Represents a GUID point, or REFGUID, that will automatically dispose the memory to which it points at the end of scope. /// You must use the value, or the parameter-less constructor to pass the equivalent of . /// public class SafeGuidPtr : SafeMemStruct { /// The equivalent of a pointer to a GUID value. public static readonly SafeGuidPtr Null = new(); /// /// Initializes a new instance of the class. This value is equivalent to a pointer. /// public SafeGuidPtr() : base(IntPtr.Zero, true, 0) { } /// Initializes a new instance of the class. /// The unique identifier to assign to the pointer. public SafeGuidPtr(in Guid guid) : base(guid) { } /// Performs an implicit conversion from to . /// The unique identifier. /// The resulting instance from the conversion. public static implicit operator SafeGuidPtr(Guid? guid) => guid.HasValue ? new SafeGuidPtr(guid.Value) : Null; } }