简体   繁体   English

PInvoke 从指针到结构的封送值

[英]PInvoke marshal value from pointer to struct

I want to call the method DhcpEnumSubnets() from the Dhcpsapi.dll.我想从 Dhcpsapi.dll 中调用方法 DhcpEnumSubnets()。

https://docs.microsoft.com/en-us/windows/win32/api/dhcpsapi/nf-dhcpsapi-dhcpenumsubnets https://docs.microsoft.com/en-us/windows/win32/api/dhcpsapi/nf-dhcpsapi-dhcpenumsubnets

CsWin32 autogenerated the method and the structs needed to call the method. CsWin32 自动生成方法和调用该方法所需的结构。

https://github.com/microsoft/CsWin32 https://github.com/microsoft/CsWin32

Here is my example:这是我的例子:

public static unsafe List<string> DhcpEnumSubnets(string serverAddress)
{
    uint resumeHandle = 0;
    uint preferredMaximum = 65536;
    DHCP_IP_ARRAY* enumInfo = null;
    List<string> subnets = new();
    while (PInvoke.DhcpEnumSubnets(serverAddress,
        ref resumeHandle,
        preferredMaximum,
        ref enumInfo,
        out uint elementsRead,
        out uint elementsTotal).IsEqual(DhcpErrorCode.SUCCESS))
    {
        try
        {
            DHCP_IP_ARRAY info = enumInfo[0];
            for (uint j = 0; j < info.NumElements; j++)
            {
                uint nativeSubnetAddress = info.Elements[j];
                var subnetAddress = DhcpHelper.NativeIpAddressToString(nativeSubnetAddress);
                subnets.Add(subnetAddress);
            }
        }
        finally
        {
            DhcpRpcFreeMemory(enumInfo);
        }
    }
    return subnets;
}

I was told to write 2 for loops to produce the full items and then release them appropriate.我被告知要编写 2 个 for 循环来生成完整的项目,然后适当地释放它们。

try
{
    for (uint i = 0; i < elementsRead; i++)
    {
        DHCP_IP_ARRAY info = enumInfo[i];
        for (uint j = 0; j < info.NumElements; j++)
        {
            uint nativeSubnetAddress = info.Elements[j];
            var subnetAddress = DhcpHelper.NativeIpAddressToString(nativeSubnetAddress);
            subnets.Add(subnetAddress);
        }
    }
}
finally
{
    for (uint i = 0; i < elementsRead; i++)
    {
        DhcpRpcFreeMemory(enumInfo[i].Elements);
    }
    DhcpRpcFreeMemory(enumInfo);
}

CsWin32 autogenerated this: CsWin32 自动生成:

// ------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
#pragma warning disable CS1591, CS1573, CS0465, CS0649, CS8019, CS1570, CS1584, CS1658
namespace Microsoft.Windows.Sdk
{
    using global::System;
    using global::System.Diagnostics;
    using global::System.Runtime.CompilerServices;
    using global::System.Runtime.InteropServices;

    /// <content>
    /// Contains extern methods from "DHCPSAPI.dll".
    /// </content>
    internal static partial class PInvoke
    {
        /// <inheritdoc cref = "DhcpEnumSubnets(PCWSTR, uint *, uint, DHCP_IP_ARRAY**, uint *, uint *)"/>
        internal static unsafe uint DhcpEnumSubnets(string ServerIpAddress, ref uint ResumeHandle, uint PreferredMaximum, ref DHCP_IP_ARRAY*EnumInfo, out uint ElementsRead, out uint ElementsTotal)
        {
            fixed (uint *ElementsTotalLocal = &ElementsTotal)
            {
                fixed (uint *ElementsReadLocal = &ElementsRead)
                {
                    fixed (DHCP_IP_ARRAY**EnumInfoLocal = &EnumInfo)
                    {
                        fixed (uint *ResumeHandleLocal = &ResumeHandle)
                        {
                            fixed (char *ServerIpAddressLocal = ServerIpAddress)
                            {
                                uint __result = PInvoke.DhcpEnumSubnets(ServerIpAddressLocal, ResumeHandleLocal, PreferredMaximum, EnumInfoLocal, ElementsReadLocal, ElementsTotalLocal);
                                return __result;
                            }
                        }
                    }
                }
            }
        }

        /// <summary>The DhcpEnumSubnets function returns an enumerated list of subnets defined on the DHCP server.</summary>
        /// <param name = "ServerIpAddress">Unicode string that specifies the IP address or hostname of the DHCP server.</param>
        /// <param name = "ResumeHandle">Pointer to a <a href = "https://docs.microsoft.com/previous-versions/windows/desktop/dhcp/dhcp-server-management-type-definitions">DHCP_RESUME_HANDLE</a> value that identifies the enumeration operation. Initially, this value should be zero, with a successful call returning the handle value used for subsequent enumeration requests. For example, if <i>PreferredMaximum</i> is set to 100, and 200 subnet addresses  are stored on the server, the resume handle can be used after the first 100 subnets are retrieved to obtain the next 100 on a subsequent call, and so forth.</param>
        /// <param name = "PreferredMaximum">Specifies the preferred maximum number of subnet addresses to return. If the number of remaining unenumerated options is less than this value, then that amount will be returned.</param>
        /// <param name = "EnumInfo">Pointer to a <a href = "https://docs.microsoft.com/windows/desktop/api/dhcpsapi/ns-dhcpsapi-dhcp_ip_array">DHCP_IP_ARRAY</a> structure that contains the subnet IDs available on the DHCP server. If no subnets are defined, this value will be null.</param>
        /// <param name = "ElementsRead">Pointer to a <b>DWORD</b> value that specifies the number of subnet addresses returned in <i>EnumInfo</i>.</param>
        /// <param name = "ElementsTotal">Pointer to a <b>DWORD</b> value that specifies the  number of subnets defined on the DHCP server that have not yet been enumerated.</param>
        /// <returns>This function returns <b>ERROR_SUCCESS</b> upon a successful call. If a call is made with the same <i>ResumeHandle</i> value and all items on the server have been enumerated, this method returns <b>ERROR_NO_MORE_ITEMS</b> with <i>ElementsRead</i> and <i>ElementsTotal</i> set to 0. Otherwise, it returns one of the <a href = "/previous-versions/windows/desktop/dhcp/dhcp-server-management-api-error-codes">DHCP Server Management API Error Codes</a>.</returns>
        /// <remarks>
        /// <para><see href = "https://docs.microsoft.com/windows/win32/api//dhcpsapi/nf-dhcpsapi-dhcpenumsubnets">Learn more about this API from docs.microsoft.com</see>.</para>
        /// </remarks>
        [DllImport("DHCPSAPI", ExactSpelling = true)]
        [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
        internal static extern unsafe uint DhcpEnumSubnets(PCWSTR ServerIpAddress, uint *ResumeHandle, uint PreferredMaximum, DHCP_IP_ARRAY**EnumInfo, uint *ElementsRead, uint *ElementsTotal);
    }
}
// ------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
#pragma warning disable CS1591, CS1573, CS0465, CS0649, CS8019, CS1570, CS1584, CS1658
namespace Microsoft.Windows.Sdk
{
    using global::System;
    using global::System.Diagnostics;
    using global::System.Runtime.CompilerServices;
    using global::System.Runtime.InteropServices;

    /// <summary>The DHCP_IP_ARRAY structure defines an array of IP addresses.</summary>
    /// <remarks>
    /// <para><see href = "https://docs.microsoft.com/windows/win32/api//dhcpsapi/ns-dhcpsapi-dhcp_ip_array">Learn more about this API from docs.microsoft.com</see>.</para>
    /// </remarks>
    internal partial struct DHCP_IP_ARRAY
    {
        /// <summary>Specifies the number of IP addresses in <b>Elements</b>.</summary>
        internal uint NumElements;
        /// <summary>Pointer to a list of <a href = "https://docs.microsoft.com/previous-versions/windows/desktop/dhcp/dhcp-server-management-type-definitions">DHCP_IP_ADDRESS</a> values.</summary>
        internal unsafe uint *Elements;
    }
}

The way with the 2 for loops is not working for me, am I missing something? 2 for 循环的方式对我不起作用,我错过了什么吗? The first code sample works for me, I am unsure is this really the right way to call this method?第一个代码示例对我有用,我不确定这真的是调用此方法的正确方法吗? This part is causing my confusion:这部分引起了我的困惑:

DHCP_IP_ARRAY info = enumInfo[0]

Is this valid to access the pointer like an array?像数组一样访问指针是否有效? basically I am passing the value from the pointer to the struct.基本上我将值从指针传递给结构。 Does this assign all needed values to the sruct?这是否将所有需要的值分配给 sruct? Does a pointer only hold one value in the index 0 ?指针是否仅在index 0中保存一个值? I am wondering if this will work with other methods form the dhcpsapi.dll and will the index 0 give me all results?我想知道这是否可以与 dhcpsapi.dll 的其他方法一起使用,并且index 0会给我所有结果吗?

According to DhcpEnumSubnets function, EnumInfo is a pointer to a DHCP_IP_ARRAY structure and it is valid to access the pointer like an array.根据DhcpEnumSubnets function, EnumInfo是一个指向 DHCP_IP_ARRAY 结构的指针,像数组一样访问指针是有效的。
Yes, this assigns all needed values to the sruct and whether a pointer only holds one value in the index 0 or not depends on DhcpEnumSubnets function.是的,这会将所有需要的值分配给 sruct,指针是否仅在索引 0 中保存一个值取决于DhcpEnumSubnets function。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM