using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Security; using Vanara.Extensions; using Vanara.PInvoke; using static Vanara.PInvoke.Kernel32; namespace Vanara.InteropServices { /// Unmanaged memory methods for local heap. /// public sealed class LocalMemoryMethods : IMemoryMethods { /// Gets the allocation method. public Func AllocMem => i => { var o = LocalAlloc(LMEM.LPTR, i); return !o.IsNull ? (IntPtr)o : throw Win32Error.GetLastError().GetException(); }; /// Gets the Ansi allocation method. public Func AllocSecureStringAnsi => s => StringHelper.AllocSecureString(s, CharSet.Ansi, AllocMem); /// Gets the Unicode allocation method. public Func AllocSecureStringUni => s => StringHelper.AllocSecureString(s, CharSet.Unicode, AllocMem); /// Gets the Ansi string allocation method. public Func AllocStringAnsi => s => StringHelper.AllocString(s, CharSet.Ansi, AllocMem); /// Gets the Unicode string allocation method. public Func AllocStringUni => s => StringHelper.AllocString(s, CharSet.Unicode, AllocMem); /// Gets the free method. public Action FreeMem => p => LocalFree(p); /// Gets the Ansi free method. public Action FreeSecureStringAnsi => p => StringHelper.FreeSecureString(p, LocalSize(p), FreeMem); /// Gets the Unicode free method. public Action FreeSecureStringUni => p => StringHelper.FreeSecureString(p, LocalSize(p), FreeMem); /// Gets the reallocation method. public Func ReAllocMem => (p, i) => { var o = LocalReAlloc(p, i, LMEM.LMEM_MOVEABLE); return !o.IsNull ? (IntPtr)o : throw Win32Error.GetLastError().GetException(); }; /// Gets a static instance of these methods. public static readonly IMemoryMethods Instance = new LocalMemoryMethods(); } /// A for memory allocated via LocalAlloc. /// public class SafeLocalHandle : 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 SafeLocalHandle(HLOCAL handle, SizeT size, bool ownsHandle = true) : base((IntPtr)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 SafeLocalHandle(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 /// SafeLocalHandle object to an native (unmanaged) array of pointers public SafeLocalHandle(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 /// SafeLocalHandle object to an native (unmanaged) array of pointers public SafeLocalHandle(IntPtr[] values) : base(values) { } /// Allocates from unmanaged memory to represent a Unicode string (WSTR) and marshal this to a native PWSTR. /// The string value. /// SafeLocalHandle object to an native (unmanaged) Unicode string public SafeLocalHandle(string s) : base(s) { } /// Initializes a new instance of the class. [ExcludeFromCodeCoverage] internal SafeLocalHandle() : base(0) { } /// Represents a NULL memory pointer. public static SafeLocalHandle Null { get; } = new SafeLocalHandle(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 . /// Number of bytes preceding the trailing array of structures /// object to an native (unmanaged) structure with a trail array of structures public static SafeLocalHandle CreateFromList(IEnumerable values, int count = -1, int prefixBytes = 0) => new SafeLocalHandle(InteropExtensions.MarshalToPtr(values, mm.AllocMem, out var 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 SafeLocalHandle CreateFromStringList(IEnumerable values, StringListPackMethod packing = StringListPackMethod.Concatenated, CharSet charSet = CharSet.Auto, int prefixBytes = 0) => new SafeLocalHandle(InteropExtensions.MarshalToPtr(values, packing, mm.AllocMem, out var 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 SafeLocalHandle CreateFromStructure(in T value = default) => new SafeLocalHandle(InteropExtensions.MarshalToPtr(value, mm.AllocMem, out var s), s); /// Converts an to a where it owns the reference. /// The . /// The result of the conversion. public static implicit operator SafeLocalHandle(IntPtr ptr) => new SafeLocalHandle(ptr, 0, true); } }