Tuesday, 15 May 2012

P/Invoke DhcpEnumServers from C#

As the first part of our DHCP management API series the following shows the sample code for enumerating authorised DHCP servers in the Active Directory domain.

This method runs on the machine where the code is running (not any DHCP server) therefore the caller machine must be connected to Active Directory.

/// <summary>
/// The DhcpEnumServers function returns an enumerated list of DHCP servers found in the directory service
/// </summary>
/// <remarks>http://msdn.microsoft.com/en-us/library/windows/desktop/aa813375(v=vs.85).aspx</remarks>
[DllImport("dhcpsapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
protected static extern uint DhcpEnumServers(
    uint Flags,
    IntPtr IdInfo,
    out IntPtr Servers,
    IntPtr CallbackFn,
    IntPtr CallbackData
);


 
/// <summary>
/// Returns an enumerated list of DHCP servers found in the Active Directory service
/// </summary>
public static List<String> GetAuthorisedServerNames()
{
    List<String> Servers = new List<String>();
    IntPtr EnumInfo;
    uint ReturnValue = DhcpEnumServers(0, IntPtr.Zero, out EnumInfo, IntPtr.Zero, IntPtr.Zero);
    TestReturnValue(ReturnValue);
    DHCP_SERVER_INFO_ARRAY ServerInfoArray = (DHCP_SERVER_INFO_ARRAY)Marshal.PtrToStructure(EnumInfo, typeof(DHCP_SERVER_INFO_ARRAY));
    int ArraySize = (int)ServerInfoArray.NumElements;
    IntPtr ServersArray = ServerInfoArray.Servers;
    IntPtr CurrentPointer = ServersArray;
    for (int i = 0; i < ArraySize; i++)
    {
        DHCPDS_SERVER CurrentServer = new DHCPDS_SERVER();
        Marshal.PtrToStructure(CurrentPointer, CurrentServer);
        Marshal.DestroyStructure(CurrentPointer, typeof(DHCPDS_SERVER));
        CurrentPointer = (IntPtr)((int)CurrentPointer + Marshal.SizeOf(CurrentServer));
        Servers.Add(CurrentServer.ServerName);
    }
    Marshal.FreeCoTaskMem(ServersArray);
    DhcpRpcFreeMemory(EnumInfo);
    Servers.Sort();
    return Servers;
}


/// <summary>
/// The DHCPDS_SERVERS structure defines a list of DHCP servers in the context of directory services.
/// </summary>
/// <remarks>http://msdn.microsoft.com/en-us/library/windows/desktop/aa813374(v=vs.85).aspx</remarks>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class DHCP_SERVER_INFO_ARRAY
{

    /// <summary>
    /// Reserved. This value should be 0.
    /// </summary>
    public uint Flags;

    /// <summary>
    /// Specifies the number of elements in Servers.
    /// </summary>
    public uint NumElements;

    /// <summary>
    /// Pointer to an array of DHCPDS_SERVER structures that contain information on individual DHCP servers.
    /// </summary>
    public IntPtr Servers;

}


/// <summary>
/// The DHCPDS_SERVER structure defines information on a DHCP server in the context of directory services.
/// </summary>
/// <remarks>http://msdn.microsoft.com/en-us/library/windows/desktop/aa813373(v=vs.85).aspx</remarks>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class DHCPDS_SERVER
{

    /// <summary>
    /// Reserved. This value should be set to 0.
    /// </summary>
    public uint Version;

    /// <summary>
    /// Unicode string that contains the unique name of the DHCP server.
    /// </summary>
    public String ServerName;

    /// <summary>
    /// Specifies the IP address of the DHCP server as an unsigned 32-bit integer.
    /// </summary>
    public uint ServerAddress;

    /// <summary>
    /// Specifies a set of bit flags that describe active directory settings for the DHCP server.
    /// </summary>
    public uint Flags;

    /// <summary>
    /// Reserved. This value should be set to 0.
    /// </summary>
    public uint State;

    /// <summary>
    /// Unicode string that contains the active directory path to the DHCP server.
    /// </summary>
    public String DsLocation;

    /// <summary>
    /// Reserved. This value should be set to 0.
    /// </summary>
    public uint DsLocType;

}


No comments:

Post a Comment