使用 RpcServerInqCallAttributes 检索 clientPID

Posted

技术标签:

【中文标题】使用 RpcServerInqCallAttributes 检索 clientPID【英文标题】:Retrieve clientPID using RpcServerInqCallAttributes 【发布时间】:2018-01-14 08:50:45 【问题描述】:

我需要在使用 ncalrpc 协议的 RPC 回调中检索客户端进程 ID。 MSDN 建议使用带有 RPC_CALL_ATTRIBUTES_V2 结构的 RpcServerInqCallAttributes。文档说进程ID作为句柄返回

https://msdn.microsoft.com/en-us/library/windows/desktop/aa378501(v=vs.85).aspx

我无法理解。它是指向一个具有进程 ID 的 DWORD 还是一个进程句柄,我可以在其中使用 GetProcessId API 获取 PID?

同样在这两种情况下,谁关闭句柄或删除分配给 DWORD 的内存?

【问题讨论】:

这正是PID 原样。您可以将其转换为DWORD。真的在 Windows 中PID 是句柄。查找例如CLIENT_ID 或说PsLookupProcessByProcessId 等等。这只是win32 层将HANDLE PID 转换为DWORD 【参考方案1】:

考虑到 MSDN 多次特意说它是一个 PID 并且该值可以在客户端进程终止后重新使用,我会说它被定义为 HANDLE 是错误的,它在事实上一个PID值。既然这样就不需要释放了,只要让整个 RPC_CALL_ATTRIBUTES_V2 结构超出范围即可。

【讨论】:

【参考方案2】:

ClientPID 是调用客户端的进程 ID。

它指向一个 DWORD 吗?

没有

是进程句柄吗?

没有

我可以使用 GetProcessId API 获取 PID 吗?

没有。这是 pid 值本身。您可以进行类型转换以用于OpenProcess 调用 - (ULONG)(ULONG_PTR)RpcCallAttributes.ClientPID

谁关闭句柄或删除分配给 DWORD 的内存?

它不能被关闭(这个句柄永远不需要被关闭)或释放(这不是一个指针)

进程和线程 id - 实际上是特殊句柄表 (PspCidTable.) 中的句柄,它本机表示为句柄。本机 (ntdll) api 和内核模式 api 始终使用进程和线程 ID 作为句柄。寻找CLIENT_ID

typedef struct _CLIENT_ID 
   HANDLE UniqueProcess;
   HANDLE UniqueThread;
  CLIENT_ID;

这个活动在不同的原生api中使用,例如ZwOpenProcess 所有内核模式 api 都使用它作为句柄,例如 - PsLookupProcessByProcessId

简单的win32层将HANDLE UniqueProcess;截断为DWORD UniqueProcess

因此,如果您想在 win32 调用 OpenProcess 中使用 RPC_CALL_ATTRIBUTES_V2 结构中的 ClientPID - 您只需将其转换为 DWORD。例如:

RPC_CALL_ATTRIBUTES_V2_W RpcCallAttributes = 
    RPC_CALL_ATTRIBUTES_VERSION, RPC_QUERY_CLIENT_PID
;
if (RPC_S_OK == RpcServerInqCallAttributes(0, &RpcCallAttributes))

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 
        (ULONG)(ULONG_PTR)RpcCallAttributes.ClientPID);

如果使用原生 api - 不需要类型转换。例如

RPC_CALL_ATTRIBUTES_V2_W RpcCallAttributes = 
    RPC_CALL_ATTRIBUTES_VERSION, RPC_QUERY_CLIENT_PID
;
if (RPC_S_OK == RpcServerInqCallAttributes(0, &RpcCallAttributes))

    HANDLE hProcess;
    static OBJECT_ATTRIBUTES zoa =  sizeof(zoa) ;
    CLIENT_ID cid =  RpcCallAttributes.ClientPID ;
    ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &zoa, &cid );

【讨论】:

【参考方案3】:

https://docs.microsoft.com/en-us/windows/desktop/api/rpcasync/ns-rpcasync-tagrpc_call_attributes_v2_a

客户端 ID

包含调用客户端的进程 ID 的句柄。这个领域 仅支持 ncalrpc 协议序列,并且已填充 仅当在 Flags 参数中指定 RPC_QUERY_CLIENT_PID 时。

我发现这是 PID,而不是 HANDLE。那就是:

HANDLE hproc = (HANDLE)ClientPID.ClientPID;
NtQueryProcessInformation ( hproc ...) 

失败,但是

cpid = (DWORD)(DWORD_PTR)ClientPID.ClientPID;
hcproc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, cpid);

成功了。

所以 MSDN 是对的:它表示为 HANDLE,但需要将其强制转换为 DWORD PID 以便在后续调用中使用。

【讨论】:

以上是关于使用 RpcServerInqCallAttributes 检索 clientPID的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)