如何PInvoke RpcMgmtEpEltInqNext?

时间:2014-02-15 23:20:37

标签: c# pinvoke rpc

Stackoverflow和PInvoke.net上的搜索词RpcMgmtEpEltInqNext产生的结果为零,因此值得一提。我一直在MSDN上翻阅并整天查看Win SDK * .h文件,感觉有点偏离我的元素。

我基本上是在尝试使用托管代码查询MSRPC端点映射器。以下是我到目前为止的情况:

[DllImport("Rpcrt4.dll", CharSet = CharSet.Auto)]
public static extern int RpcBindingFromStringBinding(string StringBinding, out IntPtr Binding);

[DllImport("Rpcrt4.dll")]
public static extern int RpcBindingFree(ref IntPtr Binding);

[DllImport("Rpcrt4.dll", CharSet = CharSet.Auto)]
public static extern int RpcMgmtEpEltInqBegin(IntPtr EpBinding,
                                                int InquiryType, // 0x00000000 = RPC_C_EP_ALL_ELTS
                                                int IfId,
                                                int VersOption,
                                                string ObjectUuid,
                                                out IntPtr InquiryContext);

[DllImport("Rpcrt4.dll", CharSet = CharSet.Auto)]
public static extern int RpcMgmtEpEltInqNext(ref IntPtr InquiryContext,
                                                out int IfId,
                                                out IntPtr Binding,
                                                out string ObjectUuid,
                                                out string Annotation);

public static List<int> QueryEPM(string host)
{
    List<int> ports = new List<int>();
    int retCode = 0; // RPC_S_OK                
    IntPtr bindingHandle = IntPtr.Zero;
    IntPtr inquiryContext = IntPtr.Zero;                
    IntPtr elementBindingHandle = IntPtr.Zero;
    int elementIfId = 0;
    string elementUuid = string.Empty;
    string elementAnnotation = string.Empty;

    try
    {                    
        retCode = RpcBindingFromStringBinding("ncacn_ip_tcp:" + host, out bindingHandle);
        if (retCode != 0)
            throw new Exception("RpcBindingFromStringBinding: " + retCode);

        retCode = RpcMgmtEpEltInqBegin(bindingHandle, 0, 0, 0, string.Empty, out inquiryContext);
        if (retCode != 0)
            throw new Exception("RpcMgmtEpEltInqBegin: " + retCode);


        retCode = RpcMgmtEpEltInqNext (ref inquiryContext, out elementIfId, out elementBindingHandle, out elementUuid, out elementAnnotation);
        if (retCode != 0)
            throw new Exception("RpcMgmtEpEltInqNext: " + retCode);
}

以上代码不完整,但它说明了我的观点。代码始终如一地返回:

  

RpcMgmtEpEltIngNext:87

87含义根据here参数不正确。

所以我在这一点上基本上很难过,而且我确定这是因为我非常糟糕的PInvoke代码。

1 个答案:

答案 0 :(得分:1)

p / invoke声明是错误的。它必须是:

[DllImport("Rpcrt4.dll", CharSet = CharSet.Auto)]
public static extern int RpcMgmtEpEltInqNext(
    IntPtr InquiryContext,
    out RPC_IF_ID IfId,
    out IntPtr Binding,
    out Guid ObjectUuid,
    out IntPtr Annotation
);

第一个参数必须按值传递。

您需要翻译RPC_IF_ID结构。这很简单。

public struct RPC_IF_ID
{
    public Guid Uuid;
    public ushort VersMajor;
    public ushort VersMinor;
}

您使用的两个字符串参数错误。它们导致编组人员CoTaskMemFree的返回值调用Annotation。你不希望这样。您需要使用Marshal.PtrToStringAnsi来读取值。

不要忘记根据文档致电RpcBindingFreeRpcStringFree