using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Security; using Vanara.Extensions; using Vanara.PInvoke; namespace Vanara.InteropServices { /// Unmanaged memory methods for COM. /// public sealed class CoTaskMemoryMethods : IMemoryMethods { /// Static instance to methods. public static IMemoryMethods Instance { get; } = new CoTaskMemoryMethods(); /// Gets a handle to a memory allocation of the specified size. /// The size, in bytes, of memory to allocate. /// A memory handle. public IntPtr AllocMem(int size) => Marshal.AllocCoTaskMem(size); /// Gets the Ansi allocation method. /// The secure string. /// A memory handle. public IntPtr AllocSecureStringAnsi(SecureString secureString) => Marshal.SecureStringToCoTaskMemAnsi(secureString); /// Gets the Unicode allocation method. /// The secure string. /// A memory handle. public IntPtr AllocSecureStringUni(SecureString secureString) => Marshal.SecureStringToCoTaskMemUnicode(secureString); /// Gets the Ansi string allocation method. /// The value. /// A memory handle. public IntPtr AllocStringAnsi(string value) => Marshal.StringToCoTaskMemAnsi(value); /// Gets the Unicode string allocation method. /// The value. /// A memory handle. public IntPtr AllocStringUni(string value) => Marshal.StringToCoTaskMemUni(value); /// Frees the memory associated with a handle. /// A memory handle. public void FreeMem(IntPtr hMem) => Marshal.FreeCoTaskMem(hMem); /// Gets the Ansi free method. /// A memory handle. public void FreeSecureStringAnsi(IntPtr hMem) => Marshal.ZeroFreeCoTaskMemAnsi(hMem); /// Gets the Unicode free method. /// A memory handle. public void FreeSecureStringUni(IntPtr hMem) => Marshal.ZeroFreeCoTaskMemUnicode(hMem); /// Locks the memory of a specified handle and gets a pointer to it. /// A memory handle. /// A pointer to the locked memory. public IntPtr LockMem(IntPtr hMem) => hMem; /// Gets the reallocation method. /// A memory handle. /// The size, in bytes, of memory to allocate. /// A memory handle. public IntPtr ReAllocMem(IntPtr hMem, int size) => Marshal.ReAllocCoTaskMem(hMem, size); /// Unlocks the memory of a specified handle. /// A memory handle. public void UnlockMem(IntPtr hMem) { } } /// A for memory allocated via COM. /// public class SafeCoTaskMemHandle : SafeMemoryHandleExt { /// Initializes a new instance of the class. /// The handle. /// The size of memory allocated to the handle, in bytes. /// if set to true if this class is responsible for freeing the memory on disposal. public SafeCoTaskMemHandle(IntPtr handle, SizeT size, bool ownsHandle = true) : base(handle, size, ownsHandle) { } /// Initializes a new instance of the class. /// The size of memory to allocate, in bytes. /// size - The value of this argument must be non-negative public SafeCoTaskMemHandle(SizeT size) : base(size) { } /// /// Allocates from unmanaged memory to represent an array of pointers and marshals the unmanaged pointers (IntPtr) to the native /// array equivalent. /// /// Array of unmanaged pointers /// SafeCoTaskMemHandle object to an native (unmanaged) array of pointers public SafeCoTaskMemHandle(byte[] bytes) : base(bytes) { } /// /// Allocates from unmanaged memory to represent an array of pointers and marshals the unmanaged pointers (IntPtr) to the native /// array equivalent. /// /// Array of unmanaged pointers /// SafeCoTaskMemHandle object to an native (unmanaged) array of pointers public SafeCoTaskMemHandle(IntPtr[] values) : base(values) { } /// Allocates from unmanaged memory to represent a Unicode string (WSTR) and marshal this to a native PWSTR. /// The string value. /// SafeCoTaskMemHandle object to an native (unmanaged) Unicode string public SafeCoTaskMemHandle(string s) : base(s) { } /// Initializes a new instance of the class. [ExcludeFromCodeCoverage] internal SafeCoTaskMemHandle() : base(0) { } /// Represents a NULL memory pointer. public static SafeCoTaskMemHandle Null => new SafeCoTaskMemHandle(IntPtr.Zero, 0, false); /// /// Allocates from unmanaged memory to represent a structure with a variable length array at the end and marshal these structure /// elements. It is the callers responsibility to marshal what precedes the trailing array into the unmanaged memory. ONLY /// structures with attribute StructLayout of LayoutKind.Sequential are supported. /// /// Type of the trailing array of structures /// Collection of structure objects /// /// Number of items in . Setting this value to -1 will cause the method to get the count by iterating /// through . /// /// Number of bytes preceding the trailing array of structures /// object to an native (unmanaged) structure with a trail array of structures public static SafeCoTaskMemHandle CreateFromList(IEnumerable values, int count = -1, int prefixBytes = 0) => new SafeCoTaskMemHandle(InteropExtensions.MarshalToPtr(values, mm.AllocMem, out int s, prefixBytes), s); /// Allocates from unmanaged memory sufficient memory to hold an array of strings. /// The list of strings. /// The packing type for the strings. /// The character set to use for the strings. /// Number of bytes preceding the trailing strings. /// /// object to an native (unmanaged) array of strings stored using the /// model and the character set defined by . /// public static SafeCoTaskMemHandle CreateFromStringList(IEnumerable values, StringListPackMethod packing = StringListPackMethod.Concatenated, CharSet charSet = CharSet.Auto, int prefixBytes = 0) => new SafeCoTaskMemHandle(InteropExtensions.MarshalToPtr(values, packing, mm.AllocMem, out int s, charSet, prefixBytes), s); /// Allocates from unmanaged memory sufficient memory to hold an object of type T. /// Native type /// The value. /// object to an native (unmanaged) memory block the size of T. public static SafeCoTaskMemHandle CreateFromStructure(in T value = default) => new SafeCoTaskMemHandle(InteropExtensions.MarshalToPtr(value, mm.AllocMem, out int s), s); /// Converts an to a where it owns the reference. /// The . /// The result of the conversion. public static implicit operator SafeCoTaskMemHandle(IntPtr ptr) => new SafeCoTaskMemHandle(ptr, 0, true); } }