using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security; using Vanara.Extensions; namespace Vanara.PInvoke { public static partial class NetApi32 { /// /// The NetApiBufferAllocate function allocates memory from the heap. Use this function only when compatibility with the /// NetApiBufferFree function is required. Otherwise, use the memory management functions. /// /// Number of bytes to be allocated. /// Receives a pointer to the allocated buffer. /// /// If the function succeeds, the return value is NERR_Success. /// If the function fails, the return value is a system error code. For a list of error codes, see System Error Codes. /// /// /// No special group membership is required to successfully execute the ApiBuffer functions. /// For more information, see Network Management Function Buffers and Network Management Function Buffer Lengths. /// Examples /// The following code sample demonstrates how to use the network management ApiBuffer functions. /// /// The sample first calls the NetApiBufferAllocate function to allocate memory and then the NetApiBufferSize function to /// retrieve the size of the allocated memory. Following this, the sample calls NetApiBufferReallocate to change the size of the /// memory allocation. Finally, the sample calls NetApiBufferFree to free the memory. In each case, the sample prints a message /// indicating success or failure. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/lmapibuf/nf-lmapibuf-netapibufferallocate NET_API_STATUS NET_API_FUNCTION // NetApiBufferAllocate( DWORD ByteCount, LPVOID *Buffer ); [DllImport(Lib.NetApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("lmapibuf.h", MSDNShortId = "9ff1e3eb-9417-469f-a8c0-cdcda3cd9583")] public static extern Win32Error NetApiBufferAllocate(uint ByteCount, out SafeNetApiBuffer Buffer); /// /// The NetApiBufferFree function frees the memory that the NetApiBufferAllocate function allocates. Applications should also call /// NetApiBufferFree to free the memory that other network management functions use internally to return information. /// /// /// A pointer to a buffer returned previously by another network management function or memory allocated by calling the /// NetApiBufferAllocate function. /// /// /// If the function succeeds, the return value is NERR_Success. If the function fails, the return value is a system error code. /// [DllImport(Lib.NetApi32, ExactSpelling = true), SuppressUnmanagedCodeSecurity] [PInvokeData("lm.h", MSDNShortId = "aa370304")] public static extern Win32Error NetApiBufferFree(IntPtr pBuf); /// /// The NetApiBufferReallocate function changes the size of a buffer allocated by a previous call to the NetApiBufferAllocate function. /// /// Pointer to the buffer returned by a call to the NetApiBufferAllocate function. /// Specifies the new size of the buffer, in bytes. /// Receives the pointer to the reallocated buffer. /// /// If the function succeeds, the return value is NERR_Success. /// If the function fails, the return value is a system error code. For a list of error codes, see System Error Codes. /// /// /// No special group membership is required to successfully execute the ApiBuffer functions. /// For a code sample that demonstrates how to use the network management ApiBuffer functions, see NetApiBufferAllocate. /// // https://docs.microsoft.com/en-us/windows/desktop/api/lmapibuf/nf-lmapibuf-netapibufferreallocate NET_API_STATUS NET_API_FUNCTION // NetApiBufferReallocate( _Frees_ptr_opt_ LPVOID OldBuffer, DWORD NewByteCount, LPVOID *NewBuffer ); [DllImport(Lib.NetApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("lmapibuf.h", MSDNShortId = "61153de0-33d3-4c83-a8aa-a7179252328c")] public static extern Win32Error NetApiBufferReallocate(IntPtr OldBuffer, uint NewByteCount, out IntPtr NewBuffer); /// /// The NetApiBufferSize function returns the size, in bytes, of a buffer allocated by a call to the NetApiBufferAllocate function. /// /// Pointer to a buffer returned by the NetApiBufferAllocate function. /// Receives the size of the buffer, in bytes. /// /// If the function succeeds, the return value is NERR_Success. /// If the function fails, the return value is a system error code. For a list of error codes, see System Error Codes. /// /// /// No special group membership is required to successfully execute the ApiBuffer functions. /// For a code sample that demonstrates how to use the network management ApiBuffer functions, see NetApiBufferAllocate. /// // https://docs.microsoft.com/en-us/windows/desktop/api/lmapibuf/nf-lmapibuf-netapibuffersize NET_API_STATUS NET_API_FUNCTION // NetApiBufferSize( LPVOID Buffer, LPDWORD ByteCount ); [DllImport(Lib.NetApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("lmapibuf.h", MSDNShortId = "0c28feeb-00a3-4ad5-b85f-96326515fae2")] public static extern Win32Error NetApiBufferSize(IntPtr Buffer, out uint ByteCount); /// Provides a to a buffer that releases a created handle at disposal using NetApiBufferFree. public class SafeNetApiBuffer : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeNetApiBuffer(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeNetApiBuffer() : base() { } /// /// Gets or sets the size of the buffer in bytes. When setting, this reallocates the existing buffer and does not guarantee that /// the currently allocated memory will be untouched or destroyed. /// /// The size of the allocated memory in bytes. public uint Size { get { var err = NetApiBufferSize(handle, out var sz); return err.Succeeded ? sz : throw err.GetException(); } set { NetApiBufferReallocate(handle, value, out var h).ThrowIfFailed(); SetHandle(h); } } /// Allocates memory for a new . /// The size of the buffer in bytes. /// A new instance of with the requested number of bytes allocated. public static SafeNetApiBuffer Allocate(uint size) { NetApiBufferAllocate(size, out var b).ThrowIfFailed(); return b; } /// Extracts a list of structures. /// The type of the structure. /// The count of structures in the list. /// The list of structures. public IEnumerable ToIEnum(int count) => handle.ToIEnum(count); /// public override string ToString() => Extensions.StringHelper.GetString(handle); /// Extracts a list of strings. Used by . /// The number of elements in the list. /// The list of strings. public IEnumerable ToStringEnum(int count) => handle.ToStringEnum(count); /// Returns an extracted structure from this buffer. /// The structure type to extract. /// Extracted structure or default(T) if the buffer is invalid. public T ToStructure() where T : struct => IsInvalid ? default : handle.ToStructure(); /// protected override bool InternalReleaseHandle() => NetApiBufferFree(handle) == 0; } /// A custom marshaler for functions using NetApiBuffer so that managed strings can be used. /// internal class NetApiBufferUnicodeStringMarshaler : ICustomMarshaler { public static ICustomMarshaler GetInstance(string cookie) => new NetApiBufferUnicodeStringMarshaler(); public void CleanUpManagedData(object ManagedObj) { } public void CleanUpNativeData(IntPtr pNativeData) { } public int GetNativeDataSize() => 0; public IntPtr MarshalManagedToNative(object ManagedObj) => throw new NotImplementedException(); public object MarshalNativeToManaged(IntPtr pNativeData) { if (pNativeData == IntPtr.Zero) return null; var s = StringHelper.GetString(pNativeData, CharSet.Unicode); NetApiBufferFree(pNativeData); return s; } } } }