using System; using System.Diagnostics; using System.Runtime.InteropServices; using Vanara.Extensions; namespace Vanara.InteropServices { /// The StrPtr structure represents a LPTSTR. [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{ptr}, {ToString()}")] public struct StrPtrAuto { 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; } /// 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 StrPtrAuto { 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 override bool Equals(object obj) { switch (obj) { case string s: return s.Equals(StringHelper.GetString(ptr, CharSet.Auto)); case IntPtr p: return ptr.Equals(p); default: return 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"; } /// The StrPtr structure represents a LPWSTR. [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{ptr}, {ToString()}")] public struct StrPtrUni { 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; } /// 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 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 StrPtrUni { 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 override bool Equals(object obj) { switch (obj) { case string s: return s.Equals(StringHelper.GetString(ptr, CharSet.Unicode)); case IntPtr p: return ptr.Equals(p); default: return 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"; } /// The StrPtr structure represents a LPWSTR. [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{ptr}, {ToString()}")] public struct StrPtrAnsi { 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; /// 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; } /// Frees the unmanaged string memory. public void Free() { StringHelper.FreeString(ptr, CharSet.Ansi); ptr = IntPtr.Zero; } /// 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 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 StrPtrAnsi { 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 override bool Equals(object obj) { switch (obj) { case string s: return s.Equals(StringHelper.GetString(ptr, CharSet.Ansi)); case IntPtr p: return ptr.Equals(p); default: return 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.Ansi) ?? "null"; } /// The GuidPtr structure represents a LPGUID. [StructLayout(LayoutKind.Sequential), DebuggerDisplay("{ptr}, {ToString()}")] public struct GuidPtr { 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 ? (Guid?)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); } /// Frees the unmanaged memory. public void Free() { Marshal.FreeCoTaskMem(ptr); ptr = IntPtr.Zero; } /// /// 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 GuidPtr { 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 override bool Equals(object obj) { switch (obj) { case Guid g: return IsNull ? false : g.Equals(Value.Value); case IntPtr p: return ptr.Equals(p); default: return 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(); /// public override string ToString() => Value?.ToString("B") ?? ""; } /// /// 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 { /// /// 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; /// The equivalent of a pointer to a GUID value. public static readonly SafeGuidPtr Null = new SafeGuidPtr(); } }