IRpcStubBuffer::Invoke

HRESULT IRpcStubBuffer::Invoke(pMessage, pChannel)

Invoke the pMessage->iMethod'th method in the server object interface instance to which this interface stub is currently connected. The RPC runtime infrastructure (the channel) calls this method on the appropriate interface stub upon receipt of an incoming request from some remote client. See the discussion above regarding how interface stubs implicitly know the IID which they are servicing.

On entry, the members of pMessage are set as follows:

Member Name

Value on entry to Invoke()

reserved members

Indeterminate. These members are neither to be read nor to be changed by the stub.

pvBuffer

Points to a buffer which contains the marshaled incoming arguments. In the case that there are no such arguments (for example, cbBuffer == 0), pvBuffer may be NULL, but will not necessarily be so.

cbBuffer

The size in bytes of the memory buffer to which pvBuffer points. If pvBuffer is NULL, then cbBuffer will be zero (but the converse is not necessarily true, as was mentioned in pvBuffer).

iMethod

The zero-based method number in the interface which is being invoked

dataRepresentation

If NDR transfer syntax is being used, then this indicates the byte order, etc., according to which the data in pvBuffer has been marshaled.

rpcFlags

Indeterminate. Neither to be read nor to be changed by the stub.


The stub is to do the following:

Errors may of course occur at various places in this process.13. Such errors will cause the stub to return an error from Invoke() rather than NOERROR. In cases where such an error code is returned, it is the stub's responsibility to have cleaned up any data and other resources allocated by the unmarshaling and marshaling processes or returned as out values from the server object. However, the stub is not responsible for invoking FreeBuffer() to free the actual marshaling buffer (for example, it is illegal for the stub to do so); rather, on error return from Invoke() the caller of Invoke() will ignore pvBuffer, and will also free it if non-NULL. Having made that general statement as to the exit conditions of Invoke(), let us examine its operation in greater detail.

If the stub cannot deal with the indicated dataRepresentation, it is to return RPC_E_SERVER_INVALIDDATAREP. If it understands the data representation, the stub is to then unmarshal the arguments from the buffer provided in pMessage->pvBuffer, the size of which is passed in pMessage->cbBuffer. If the argument data cannot be completely unmarshaled, the server is to free any partially unmarshaled data, then return RPC_E_SERVER_CANTUNMARSHALDATA from Invoke().

If the data is successfully completely unmarshaled, then the interface stub is to invoke the designated method in the designated interface on the server object. Notice that the incoming pvBuffer memory buffer is at this time still valid, and that therefore the stub may if it wishes and if appropriate for the argument and data representations in question pass to the server object pointers which point directly into this buffer. The memory allocation and data copying that is thus avoided can at times be a significant performance optimization.

Once the invocation of the server object returns, the stub is to marshal the return value and out parameters returned from the server back to the client. It does so irrespective of whether the server object invocation returned an error or success code; that is, the stub marshals back to the client whatever the server object returned.14. The stub gets a reply buffer into which to do this marshaling by calling pChannel->GetBuffer(), passing in the pMessage structure that it received in Invoke(). Before calling GetBuffer(), the stub is to set the cbBuffer member to the size that it requires for the to-be-allocated reply buffer. Zero is explicitly a legal value for cbBuffer, and the stub must always call GetBuffer() (more precisely, to be clear about the error case: the stub must always call GetBuffer() if the server object method has actually been invoked)15. to allocate a reply buffer, even if the stub itself does not require one (such as would be the case if for a void-returning function with no out parameters). The stub must also set dataRepresentation as appropriate for the standard by which it intends to marshal the returning values (or would marshal them if there were some).16. Aside from cbBuffer, dataRepresentation and possibly the contents of the bytes inside the memory buffer, on entry to GetBuffer() no other data accessible from pMessage may be different than they were on entry to Invoke().

Before it allocates a reply buffer, the call to GetBuffer() has the side effect of freeing the memory buffer to which pvBuffer presently points. Thus, the act by the interface stub of allocating a reply buffer for the return values necessarily terminates access by the stub to the incoming marshaled arguments.

If GetBuffer() successfully allocates a reply buffer (see GetBuffer() for a description of how the stub determines this), then the stub is to marshal the return value and returned-out parameters into the buffer according to the rules of the transfer syntax. Once this is complete, the stub is to set the cbBuffer member to the number of bytes it actually marshaled (if it marshaled nothing, then it must explicitly set this to zero ((but see also GetBuffer())), and then return NOERROR from Invoke().

If an error occurs during the unmarshaling of the incoming arguments or the marshaling of the return values, then the interface stub is responsible for correctly freeing any resources consumed by the marshaled data. See in particular CoReleaseMarshalData(). See also the discussion of this topic in IRpcChannelBuffer::SendRecieve().

Argument

Type

Description

pMessage

RPCOLEMESSAGE *

Channel-allocated message structure.

pChannel

IRpcChannelBuffer *

The channel to use for buffer management, and so forth.

return value

HRESULT

S_OK, RPC_E_SERVER_INVALIDDATAREP, RPC_E_SERVER_CANTUNMARSHALDATA, RPC_E_SERVER_CANTMARSHALDATA