DhcpEnumFilterV4(P / Invoke)始终报告ERROR_NO_MORE_ITEMS

时间:2014-11-27 09:04:27

标签: c# pinvoke dhcp

我尝试以编程方式枚举Windows 2012 R2 DHCP服务器上的DHCP过滤器。使用P / Invoke,代码如下:

public const uint ERROR_SUCCESS = 0;
public const uint ERROR_MORE_DATA = 234;
public const uint ERROR_NO_MORE_ITEMS = 259;

public const int MAX_PATTERN_LENGTH = 255;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DHCP_ADDR_PATTERN {
    public bool MatchHWType;
    public byte HWType;
    public bool IsWildCard;
    public byte Length;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_PATTERN_LENGTH)]
    public byte[] Pattern;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DHCP_FILTER_ENUM_INFO {
    public uint NumElements;
    public IntPtr pEnumRecords;
}

public enum DHCP_FILTER_LIST_TYPE : uint { 
    Deny = 0x1,
    Allow = 0x2
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DHCP_FILTER_RECORD {
    public DHCP_ADDR_PATTERN AddrPatt;
    public string Comment;
}


[DllImport("dhcpsapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern uint DhcpEnumFilterV4(string ServerIpAddress,
    ref DHCP_ADDR_PATTERN ResumeHandle, uint PreferredMaximum, 
    DHCP_FILTER_LIST_TYPE ListType, out IntPtr EnumFilterInfo,
    out uint ElementsRead, out uint ElementsTotal);

public static IEnumerable<DHCP_FILTER_RECORD> DhcpEnumFilterV4(
        string serverIpAddress, DHCP_FILTER_LIST_TYPE listType, 
        uint preferredMaximum = 1024) {
    uint cntRead = 0;
    uint cntTotal = 0;
    uint error = ERROR_SUCCESS;
    var hResume = new DHCP_ADDR_PATTERN();
    var data = IntPtr.Zero;
    var size = Marshal.SizeOf(typeof(DHCP_FILTER_RECORD));

    do {
        error = DhcpEnumFilterV4(serverIpAddress, ref hResume,
            preferredMaximum, listType, out data, out cntRead, 
            out cntTotal);
        //
        // PROBLEM OCCURS HERE: 'error' is always 259
        //
        if ((error == ERROR_SUCCESS) || (error == ERROR_MORE_DATA)) {
            var array = data.ToStructure<DHCP_FILTER_ENUM_INFO>();
            for (uint i = 0; i < array.NumElements; ++i) {
                var ptr = new IntPtr((long) array.pEnumRecords + i * size);
                var obj = (DHCP_FILTER_RECORD) Marshal.PtrToStructure(ptr, typeof(DHCP_FILTER_RECORD));
                yield return obj;
            }

            DhcpRpcFreeMemory(array.pEnumRecords);
            DhcpRpcFreeMemory(data);
            data = IntPtr.Zero;

        } else if (error != ERROR_NO_MORE_ITEMS) {
            Debug.Assert(data == IntPtr.Zero);
            throw new Win32Exception((int) error);
        }

    } while (error == ERROR_MORE_DATA);
}

[DllImport("dhcpsapi.dll", SetLastError = true)]
public static extern void DhcpRpcFreeMemory(IntPtr BufferPointer);

整个DHCP API的文档(http://msdn.microsoft.com/en-us/library/windows/desktop/dd897526(v=vs.85).aspx)有点粗略,所以我不能完全确定我是否正在做正确的事。

问题是:我从未收到任何结果,DhcpEnumFilterV4始终返回ERROR_NO_MORE_ITEMS。有什么建议吗?

1 个答案:

答案 0 :(得分:2)

我刚刚在MSDN(http://msdn.microsoft.com/en-us/library/windows/desktop/dd897586(v=vs.85).aspx)中发现了关于DHCP_FILTER_LIST_TYPE的重要用户评论。似乎MSDN中枚举的定义是错误的。以下

typedef enum  { 
    Deny   = 0x1, // This is wrong!
    Allow  = 0x2  // This is wrong!
} DHCP_FILTER_LIST_TYPE;

应该是

typedef enum  { 
    Deny   = 0x0, // This is correct!
    Allow  = 0x1  // This is correct!
} DHCP_FILTER_LIST_TYPE;

使用更新的常量,我的代码可以正常工作。