Vanara/PInvoke/NetApi32/LmApiBuf.cs

176 lines
9.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
using Vanara.Extensions;
namespace Vanara.PInvoke
{
public static partial class NetApi32
{
/// <summary>
/// The <c>NetApiBufferAllocate</c> function allocates memory from the heap. Use this function only when compatibility with the
/// NetApiBufferFree function is required. Otherwise, use the memory management functions.
/// </summary>
/// <param name="ByteCount">Number of bytes to be allocated.</param>
/// <param name="Buffer">Receives a pointer to the allocated buffer.</param>
/// <returns>
/// <para>If the function succeeds, the return value is NERR_Success.</para>
/// <para>If the function fails, the return value is a system error code. For a list of error codes, see System Error Codes.</para>
/// </returns>
/// <remarks>
/// <para>No special group membership is required to successfully execute the ApiBuffer functions.</para>
/// <para>For more information, see Network Management Function Buffers and Network Management Function Buffer Lengths.</para>
/// <para>Examples</para>
/// <para>The following code sample demonstrates how to use the network management ApiBuffer functions.</para>
/// <para>
/// The sample first calls the <c>NetApiBufferAllocate</c> 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.
/// </para>
/// </remarks>
// 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);
/// <summary>
/// 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.
/// </summary>
/// <param name="pBuf">
/// A pointer to a buffer returned previously by another network management function or memory allocated by calling the
/// NetApiBufferAllocate function.
/// </param>
/// <returns>
/// If the function succeeds, the return value is NERR_Success. If the function fails, the return value is a system error code.
/// </returns>
[DllImport(Lib.NetApi32, ExactSpelling = true), SuppressUnmanagedCodeSecurity]
[PInvokeData("lm.h", MSDNShortId = "aa370304")]
public static extern Win32Error NetApiBufferFree(IntPtr pBuf);
/// <summary>
/// The <c>NetApiBufferReallocate</c> function changes the size of a buffer allocated by a previous call to the NetApiBufferAllocate function.
/// </summary>
/// <param name="OldBuffer">Pointer to the buffer returned by a call to the NetApiBufferAllocate function.</param>
/// <param name="NewByteCount">Specifies the new size of the buffer, in bytes.</param>
/// <param name="NewBuffer">Receives the pointer to the reallocated buffer.</param>
/// <returns>
/// <para>If the function succeeds, the return value is NERR_Success.</para>
/// <para>If the function fails, the return value is a system error code. For a list of error codes, see System Error Codes.</para>
/// </returns>
/// <remarks>
/// <para>No special group membership is required to successfully execute the ApiBuffer functions.</para>
/// <para>For a code sample that demonstrates how to use the network management ApiBuffer functions, see NetApiBufferAllocate.</para>
/// </remarks>
// 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);
/// <summary>
/// The <c>NetApiBufferSize</c> function returns the size, in bytes, of a buffer allocated by a call to the NetApiBufferAllocate function.
/// </summary>
/// <param name="Buffer">Pointer to a buffer returned by the NetApiBufferAllocate function.</param>
/// <param name="ByteCount">Receives the size of the buffer, in bytes.</param>
/// <returns>
/// <para>If the function succeeds, the return value is NERR_Success.</para>
/// <para>If the function fails, the return value is a system error code. For a list of error codes, see System Error Codes.</para>
/// </returns>
/// <remarks>
/// <para>No special group membership is required to successfully execute the ApiBuffer functions.</para>
/// <para>For a code sample that demonstrates how to use the network management ApiBuffer functions, see NetApiBufferAllocate.</para>
/// </remarks>
// 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);
/// <summary>Provides a <see cref="SafeHandle"/> to a buffer that releases a created handle at disposal using NetApiBufferFree.</summary>
public class SafeNetApiBuffer : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeNetApiBuffer"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeNetApiBuffer(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeNetApiBuffer"/> class.</summary>
private SafeNetApiBuffer() : base() { }
/// <summary>
/// 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.
/// </summary>
/// <value>The size of the allocated memory in bytes.</value>
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); }
}
/// <summary>Allocates memory for a new <see cref="SafeNetApiBuffer"/>.</summary>
/// <param name="size">The size of the buffer in bytes.</param>
/// <returns>A new instance of <see cref="SafeNetApiBuffer"/> with the requested number of bytes allocated.</returns>
public static SafeNetApiBuffer Allocate(uint size)
{
NetApiBufferAllocate(size, out var b).ThrowIfFailed();
return b;
}
/// <summary>Extracts a list of structures.</summary>
/// <typeparam name="T">The type of the structure.</typeparam>
/// <param name="count">The count of structures in the list.</param>
/// <returns>The list of structures.</returns>
public IEnumerable<T> ToIEnum<T>(int count) => handle.ToIEnum<T>(count);
/// <inheritdoc/>
public override string ToString() => Extensions.StringHelper.GetString(handle);
/// <summary>Extracts a list of strings. Used by <see cref="DsAddressToSiteNames"/>.</summary>
/// <param name="count">The number of elements in the list.</param>
/// <returns>The list of strings.</returns>
public IEnumerable<string> ToStringEnum(int count) => handle.ToStringEnum(count);
/// <summary>Returns an extracted structure from this buffer.</summary>
/// <typeparam name="T">The structure type to extract.</typeparam>
/// <returns>Extracted structure or default(T) if the buffer is invalid.</returns>
public T ToStructure<T>() where T : struct => IsInvalid ? default : handle.ToStructure<T>();
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => NetApiBufferFree(handle) == 0;
}
/// <summary>A custom marshaler for functions using NetApiBuffer so that managed strings can be used.</summary>
/// <seealso cref="ICustomMarshaler"/>
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;
}
}
}
}