using System.Collections.Generic;
using System.Security;
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() => 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 string.Empty;
try { return StringHelper.GetString(pNativeData, CharSet.Unicode) ?? string.Empty; }
finally { NetApiBufferFree(pNativeData); }
}
}
}