簡體   English   中英

PInvoke 從指針到結構的封送值

[英]PInvoke marshal value from pointer to struct

我想從 Dhcpsapi.dll 中調用方法 DhcpEnumSubnets()。

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

CsWin32 自動生成方法和調用該方法所需的結構。

https://github.com/microsoft/CsWin32

這是我的例子:

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;
}

我被告知要編寫 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 自動生成:

// ------------------------------------------------------------------------------
// <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;
    }
}

2 for 循環的方式對我不起作用,我錯過了什么嗎? 第一個代碼示例對我有用,我不確定這真的是調用此方法的正確方法嗎? 這部分引起了我的困惑:

DHCP_IP_ARRAY info = enumInfo[0]

像數組一樣訪問指針是否有效? 基本上我將值從指針傳遞給結構。 這是否將所有需要的值分配給 sruct? 指針是否僅在index 0中保存一個值? 我想知道這是否可以與 dhcpsapi.dll 的其他方法一起使用,並且index 0會給我所有結果嗎?

根據DhcpEnumSubnets function, EnumInfo是一個指向 DHCP_IP_ARRAY 結構的指針,像數組一樣訪問指針是有效的。
是的,這會將所有需要的值分配給 sruct,指針是否僅在索引 0 中保存一個值取決於DhcpEnumSubnets function。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM