using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.PInvoke; using static Vanara.PInvoke.Kernel32; namespace Vanara.InteropServices { /// Unmanaged memory methods for local heap. /// public sealed class LocalMemoryMethods : MemoryMethodsBase { /// Gets a static instance of these methods. public static readonly IMemoryMethods Instance = new LocalMemoryMethods(); /// Gets a handle to a memory allocation of the specified size. /// The size, in bytes, of memory to allocate. /// A memory handle. public override IntPtr AllocMem(int size) => Win32Error.ThrowLastErrorIfNull((IntPtr)LocalAlloc(LMEM.LPTR, size)); /// Frees the memory associated with a handle. /// A memory handle. public override void FreeMem(IntPtr hMem) => LocalFree(hMem); /// Gets the reallocation method. /// A memory handle. /// The size, in bytes, of memory to allocate. /// A memory handle. public override IntPtr ReAllocMem(IntPtr hMem, int size) => Win32Error.ThrowLastErrorIfNull((IntPtr)LocalReAlloc(hMem, size, LMEM.LMEM_FIXED | LMEM.LMEM_ZEROINIT)); } /// 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); } }