Contract semantics of ncalrpc ClientPID / RPC_CALL_ATTRIBUTES_V3 sender attribution

Adam Togstad 0 Reputation points
2026-10-01T19:17:09.2966667+00:00

I am trying to understand the documented contract for sender-process attribution

on local Microsoft RPC (ncalrpc).

This is a correctness/security-boundary question, not a request for undocumented

implementation details.

For a single ncalrpc call, when a server calls RpcServerInqCallAttributes and

requests the client process identifier / related V3 client identifier fields:

  1. At what point is the client process identity actually captured? Is the value captured synchronously while the calling client thread is still executing on the sender side before the RPC request is enqueued/transferred, or is it derived later by the server/RPC runtime after delivery?
  2. Is the reported ClientPID bound to the specific RPC call/message, or can it represent connection/binding-level state?
  3. Does the value always identify the actual process that invoked that specific RPC call? In particular, how do impersonation, forwarding, proxies, duplicated binding handles, connection reuse, and other delegation scenarios affect ClientPID?
  4. RPC_CALL_ATTRIBUTES declares ClientPID using a HANDLE-typed field, but the documentation describes it as a process identifier. Is ClientPID contractually only a scalar PID, or does the RPC runtime retain any process-object/reference-grade sender identity internally for the call?
  5. For RPC_CALL_ATTRIBUTES_V3 ClientIdentifier, what is the documented identity, lifetime, and scope of that value? Specifically:
    • is it per call?
    • is it generated/captured on the sender side?
    • can it be used to distinguish process occurrences across process exit and PID reuse?
    • is it intended to represent the actual sending process occurrence, or only another form of identifier/security metadata?
  6. Is there any supported/documented ncalrpc or ALPC-facing Win32/RPC API that provides the server with a retained or otherwise non-reassignable reference to the exact sending process occurrence for a specific message?

I am specifically trying to distinguish:

where the server queries the identity

from:

where Windows originally captured and bound that identity to the call.

A scalar PID obtained after delivery is not sufficient for my use case, even if

I separately retain a process HANDLE. I need to know whether the RPC/ALPC stack

itself contractually captures the exact sender occurrence before enqueue and

binds that capture to the individual call.

I am only interested in supported/documented behavior. Undocumented Nt*/ALPC

internals are not sufficient.

Relevant API:

RpcServerInqCallAttributes

RPC_CALL_ATTRIBUTES_V2 / V3

ncalrpc

Windows for business | Windows Server | Networking | Other
0 comments No comments

2 answers

Sort by: Most helpful
  1. Daphne Huynh (WICLOUD CORPORATION) 1,570 Reputation points Microsoft External Staff Moderator
    2026-10-02T07:42:25.1033333+00:00

    Welcome to Microsoft Q&A!

    Thank you for the additional clarification and for explaining the design in more detail.

    Based on your description, I understand that your design does not rely on ClientPID as a process-object reference and does not perform a subsequent OpenProcess(ClientPID) lookup. Instead, a trusted launcher retains the original process handle returned by CreateProcess, and ClientPID is used only as evidence of call origin by comparing it with GetProcessId(H).

    From the publicly available Microsoft documentation, ClientPID is described in call-specific terms:

    • RPC_CALL_ATTRIBUTES_V2_A (rpcasync.h) states that ClientPID contains the process ID of the calling client and is populated when RPC_QUERY_CLIENT_PID is specified. It is supported only for the ncalrpc protocol sequence.
    • I_RpcBindingInqLocalClientPID function (rpcdcep.h) states that it returns the process ID of the client that issued the call.
    • The same API may return RPC_S_NO_CALL_ACTIVE when there is no active RPC call on the current thread.
    • RpcServerInqCallAttributesA function (rpcasync.h) obtains client security context attributes and is used in the context of a server routine or a specific asynchronous RPC call.

    Taken together, this documentation supports the interpretation that, for an active ncalrpc call, ClientPID refers to the process ID of the immediate RPC client that issued that call.

    That said, it is important to recognize the limits of what is explicitly documented. The available documentation does not describe:

    • When the PID is captured internally by the RPC runtime.
    • Whether the runtime retains any underlying process-object reference.
    • How attribution behaves in scenarios involving proxying, forwarding, or other implementation-specific mechanisms.
    • Whether Microsoft defines a comparison such as ClientPID == GetProcessId(H) as a supported security boundary.

    For that reason, while the documented wording ("calling client" and "client that issued the call") is consistent with your interpretation, the published documentation does not provide a formal guarantee beyond that statement.

    Therefore, based on the currently available Microsoft documentation, the most supportable conclusion is:

    For an active ncalrpc call, ClientPID is documented as the process ID of the immediate client process that issued that RPC call.

    However, the documentation does not elevate ClientPID itself into a non-reassignable process reference, nor does it explicitly define broader security-boundary guarantees around that value. In the design you described, the retained process handle H remains the component that provides process-occurrence continuity.

    Regarding escalation, Microsoft Q&A contributors are limited to information that is publicly documented and do not have a direct mechanism to obtain official confirmation from the Windows RPC product team. If your scenario requires a formal product-backed statement regarding the contractual semantics of ClientPID, the appropriate path would be to engage Microsoft Support, where the question may be reviewed through the relevant engineering channels.

    I hope this helps clarify both what can reasonably be concluded from the published documentation and where the current documentation leaves room for interpretation.

    References:

    I_RpcBindingInqLocalClientPID function (rpcdcep.h) - Win32 apps | Microsoft Learn

    RPC_CALL_ATTRIBUTES_V2_A (rpcasync.h) - Win32 apps | Microsoft Learn

    RpcServerInqCallAttributesA function (rpcasync.h) - Win32 apps | Microsoft Learn

    Client Impersonation (RPC) - Win32 apps | Microsoft Learn

    I_RpcBindingInqLocalPID | Microsoft Learn

    Rpcdcep.h header - Win32 apps | Microsoft Learn

    Remote Procedure Call (RPC) - Win32 apps | Microsoft Learn

    The Client Application - Win32 apps | Microsoft Learn

    If you find it useful, please click Accept Answer.

    Thank you for choosing Microsoft Q&A.

    Was this answer helpful?

    0 comments No comments

  2. Steven Nguyen (WICLOUD CORPORATION) 415 Reputation points Microsoft External Staff Moderator
    2026-10-02T02:01:48.4533333+00:00

    Hi Adam Togstad

    I reviewed the public Microsoft documentation for RpcServerInqCallAttributes, RPC_CALL_ATTRIBUTES_V2, ClientPID, and RPC client impersonation.

    The documented contract confirms that:

    • RpcServerInqCallAttributes allows an RPC server to obtain client security context attributes.
    • RPC_CALL_ATTRIBUTES_V2 adds support for client process IDs.
    • When RPC_QUERY_CLIENT_PID is requested, ClientPID contains the process ID of the calling client.
    • Retrieving ClientPID is supported only for the ncalrpc protocol sequence.
    • Microsoft explicitly documents that ClientPID uniquely identifies the process only until that process terminates, after which the PID can be reused by a new process.

    References:

    However, the public documentation reviewed does not define:

    1. When or where the PID is captured.
    2. Whether the PID is captured before enqueue or delivery.
    3. Whether the underlying identity is bound to an individual RPC message, call, connection, or binding.
    4. Whether RPC retains a process-object reference internally.
    5. Attribution behavior for proxies, forwarding, impersonation, duplicated binding handles, or connection reuse.
    6. A guarantee that the value identifies a non-reassignable process occurrence.
    7. The lifetime, uniqueness, generation point, or process-occurrence semantics of the referenced V3 ClientIdentifier.

    Therefore, based only on the documented public contract, ClientPID should be treated as a process ID value, not as a documented retained process-object reference. Microsoft explicitly documents that the PID can be reused after the original process terminates.

    This means that the available documentation does not establish the security guarantee required by your design: a non-reassignable reference, captured before enqueue and bound to the exact sending process occurrence for an individual RPC call.

    RPC client impersonation is the documented mechanism for performing authorization under the client's security context. It may be appropriate when the requirement is to authorize the client security principal. However, the public impersonation documentation does not define it as proof of the exact physical process occurrence that sent a particular RPC message.

    Reference:

    Accordingly, the requested exact sender-occurrence guarantee cannot be confirmed from the public documentation reviewed. An authoritative confirmation from the Windows RPC product owner would be required before treating this behavior as a supported security boundary.I reviewed the public Microsoft documentation for RpcServerInqCallAttributes, RPC_CALL_ATTRIBUTES_V2, ClientPID, and RPC client impersonation.

    The documented contract confirms that:

    • RpcServerInqCallAttributes allows an RPC server to obtain client security context attributes.
    • RPC_CALL_ATTRIBUTES_V2 adds support for client process IDs.
    • When RPC_QUERY_CLIENT_PID is requested, ClientPID contains the process ID of the calling client.
    • Retrieving ClientPID is supported only for the ncalrpc protocol sequence.
    • Microsoft explicitly documents that ClientPID uniquely identifies the process only until that process terminates, after which the PID can be reused by a new process.

    References:

    However, the public documentation reviewed does not define:

    1. When or where the PID is captured.
    2. Whether the PID is captured before enqueue or delivery.
    3. Whether the underlying identity is bound to an individual RPC message, call, connection, or binding.
    4. Whether RPC retains a process-object reference internally.
    5. Attribution behavior for proxies, forwarding, impersonation, duplicated binding handles, or connection reuse.
    6. A guarantee that the value identifies a non-reassignable process occurrence.
    7. The lifetime, uniqueness, generation point, or process-occurrence semantics of the referenced V3 ClientIdentifier.

    Therefore, based only on the documented public contract, ClientPID should be treated as a process ID value, not as a documented retained process-object reference. Microsoft explicitly documents that the PID can be reused after the original process terminates.

    This means that the available documentation does not establish the security guarantee required by your design: a non-reassignable reference, captured before enqueue and bound to the exact sending process occurrence for an individual RPC call.

    RPC client impersonation is the documented mechanism for performing authorization under the client's security context. It may be appropriate when the requirement is to authorize the client security principal. However, the public impersonation documentation does not define it as proof of the exact physical process occurrence that sent a particular RPC message.

    Reference:

    Accordingly, the requested exact sender-occurrence guarantee cannot be confirmed from the public documentation reviewed. An authoritative confirmation from the Windows RPC product owner would be required before treating this behavior as a supported security boundary.

    Please note that the information above is limited to behavior explicitly documented in publicly available Microsoft documentation. Where a specific behavior or guarantee is not documented, I cannot make assumptions about internal RPC/ALPC implementation details.

    If this helps clarify the architectural boundaries and resolves your design inquiry, please consider hitting "Accept Answer" so other users facing this scenario can easily find the solution!

    Thank you.

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.