DhcpEnumFilterV4 (P/Invoke) 总是报告ERROR_NO_MORE_ITEMS

本文关键字:ERROR 报告 NO ITEMS MORE Invoke DhcpEnumFilterV4 | 更新日期: 2023-09-27 18:32:16

我尝试以编程方式枚举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。有什么建议吗?

DhcpEnumFilterV4 (P/Invoke) 总是报告ERROR_NO_MORE_ITEMS

我偶然发现了一个关于MSDN中DHCP_FILTER_LIST_TYPE的重要用户评论(http://msdn.microsoft.com/en-us/library/windows/desktop/dd897586(v=vs.85).aspx)。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;

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