When a program needs to communic开发者_Go百科ate using Microsoft RPC developers typically write a IDL definition for all methods, for example:
error_status_t rpcMyInterfaceGetFile( [in] const GUID fileId, [out] BYTE_PIPE filePipe );
which is compiled by MIDL compiler and produces a wrapper function:
/* [fault_status][comm_status] */ error_status_t rpcMyInterfacerGetFile(
/* [in] */ handle_t IDL_handle,
/* [in] */ const GUID fileId,
/* [out] */ BYTE_PIPE filePipe)
{
CLIENT_CALL_RETURN _RetVal;
_RetVal = NdrClientCall2(
( PMIDL_STUB_DESC )&IMyInterfaceRpc_StubDesc,
(PFORMAT_STRING) &MyInterfaceRpc__MIDL_ProcFormatString.Format[SomeNumberHere],
( unsigned char * )&IDL_handle);
return ( error_status_t )_RetVal.Simple;
}
Here the call is forwarded to NdrClientCall2()
RPC runtime function that is declared to have ...
as the third parameter and does actual job. MyInterfaceRpc__MIDL_ProcFormatString
is just a sequence of hardcoded bytes generated by MIDL, so the second parameter is a start of a subsection in that array declared in the same .c file as the wrapper function and having static storage duration.
How do the parameters (fileId
and filePipe
) get passed into NdrClientCall2()
? I don't see them being passed. How do they happen to get from the wrapper to NdrClientCall2()
?
Well, not quite sure but reading between the lines in the MSDN doc (which says that the last argument is Pointer to the client-side calling stack) it sounds like the NdrClientCall2
function can take the STUB_DESC structure, figure out what the argument types and sizes are, extract them from the stack, do the work of calling the remote interface and then write the results back into the proper locations on the stack (for OUT parameters).
Without looking too deep into it, it seems to me that by passing the address of the first argument on the stack (&IDL_handle) the implementation of NdrClientCall2 can see the subsequent arguments that are also on the stack. The second argument to NdrClientCall2 indicates the number and size of the varargs.
精彩评论