IRpcChannelBuffer::SendReceive

HRESULT IRpcChannelBuffer::SendReceive(pMessage, pStatus)

Cause an invocation to be sent across to the server process. The caller will have first obtained access to a transmission packet in which to marshal the arguments by calling IRpcChannelBuffer::GetBuffer(). The same pMessage structure passed as an argument into that function is passed here to the channel a second time.

In the intervening time period, the method arguments will have been marshaled into the buffer pointed to by pMessage->pvBuffer. However, the pvBuffer pointer parameter must on entry to SendReceive() be exactly as it was when returned from GetBuffer(). That is, it must point to the start of the memory buffer. The caller should in addition set pMessage->cbBuffer to the number of bytes actually written into the buffer (zero is explicitly a legal value). No other values accessible from pMessage may be different than they were on exit from GetBuffer().

Upon successful exit from SendReceive(), the incoming buffer pointed to by pvBuffer will have been freed by the channel. In its place will be found a buffer containing the marshaled return values / out parameters from the interface stub: pMessage->pvBuffer points to the new buffer, and pMessage->cbBuffer indicates the size thereof. If there are no such return values, then pMessage->cbBuffer is set to zero, while pMessage->pvBuffer may or may not be NULL.

On error exit from SendReceive(),11. the incoming buffer pointed to by pvBuffer may or may not have been freed. If it has been freed, then on error exit pMessage->pvBuffer is set to NULL and pMessage->cbBuffer is set to zero. If in contrast, pMessage->pvBuffer is on error exit not NULL, then that pointer, the data to which it points, and the value pMessage->cbBuffer will contain exactly as they did on entry; that is, the marshaled arguments will not have been touched. Thus, on error exit from SendReceive(), in no case are any marshaled return values passed back; if a marshaling buffer is in fact returned, then it contains the marshaled arguments as they were on entry.

The exact cases on error exit when the incoming buffer has or has not been freed needs careful attention. There are three cases:

  1. The channel implementation knows with certainty either that all of the incoming data was successfully unmarshaled or that if any errors occurred during unmarshaling that the interface stub correctly cleaned up. In practical terms, this condition is equivalent to the stub manager having actually called IRpcStubBuffer::Invoke() on the appropriate interface stub. In this case, on exit from SendReceive() the incoming arguments will always have been freed.
  2. The channel implementation knows with certainty the situation in case 1 has not occurred. In this case, on exit from SendReceive(), the incoming arguments will never have been freed.
  3. The channel implementation does not know with certainty that either of the above two cases has occurred. In this case, on exit from SendReceive(), the incoming arguments will always have been freed. This is a possible resource leakage (due to, for example, CoReleaseMarshalData() calls that never get made), but it safely avoids freeing resources that should not be freed.
If pMessage->pvBuffer is returned as non-NULL, then the caller is responsible for subsequently freeing it; see FreeBuffer(). A returned non-NULL pMessage->pvBuffer may in general legally be (and will commonly be, the success case) different than the (non-NULL) value on entry; for example, the buffer may be legally be reallocated. Further, between the return from SendReceive() and the subsequent freeing call no data accessible from pMessage may be modified, with the possible exception of the data actually in the memory buffer.

Upon successful exit from SendReceive(), the pMessage->dataRepresentation field will have been modified to contain whatever was returned by the interface stub in field of the same name value on exit to IRpcStubBuffer::Invoke(). This is particularly important when NDR transfer syntax is used, as dataRepresentation indicates critical things (such as byte order) which apply to the marshaled return / out values. Upon error exit from SendReceive(), pMessage->dataRepresentation is undefined.

Argument

Type

Description

pMessage

RPCOLEMESSAGE *

Message structure containing information to transmit to server.

pStatus

ULONG *

May legally be NULL. If non-NULL, then if either (i) an RPC-infrastructure-detected server-object fault (such as a server object bug caused an exception which was caught by the RPC infrastructure), or (ii) an RPC communications failure occurs, then at this location a status code is written which describes what happened. In the two error cases, the errors E_RPCFAULT and E_RPCSTATUS are (respectively) returned (and are always returned when these errors occur, irrespective of the NULL-ness of pStatus).

return value

HRESULT

S_OK, E_RPCFAULT, E_RPCSTATUS