When a program needs to communicate 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()?