RPCOLEMESSAGE and Related Structures

Common to several of the methods in IRpcChannelBuffer is a data structure of type RPCOLEMESSAGE. This structure is defined as is show below. The structure is to be packed so that there are no holes in its memory layout.


typedef struct RPCOLEMESSAGE {
   void *            reserved1;
   RPCOLEDATAREP      dataRepresentation;   // in NDR transfer syntax: info about endianness, etc.
   void    *            pvBuffer;            // memory buffer used for marshalling
   ULONG            cbBuffer;            // size of the marshalling buffer
   ULONG            iMethod;            // the method number being invoked
   void *            reserved2[5];
   ULONG            rpcFlags;
   } on the ultimate destination computer MESSAGE;8.

The most significant member of this structure is pvBuffer. It is through the memory buffer to which pvBuffer points that marshaled method arguments are transferred. cbBuffer is used to indicate the size of the buffer. iMethod is indicates a particular method number within the interface being invoked. The IID of that interface is identified through other means: on the client side as a parameter to GetBuffer(), and on the server side as part of the internal state of each interface stub.

At all times all reserved values in this structure are to be initialized to zero by non-RPC-infrastructure parties (such as parties other than the channel / RPC runtime implementor) who allocate RPCOLEMESSAGE structures. However, the RPC channel (more generally, the RPC runtime infrastructure) is free to modify these reserved fields. Therefore, once initialized, the reserved fields must be ignored by the initializing code; they cannot be relied on to remain as zero. Further, there are very carefully specified rules as to what values in these structures may or may not be modified at various times and by which parties. In almost all cases, aside from actually reading and writing data from the marshaling buffer, which is done by proxies and stubs, only the channel may change these fields. See the individual method descriptions for details.

Readers familiar with the connection-oriented DCE protocol may notice that the transfer syntax used for marshaling the arguments, the particular set of rules and conventions according to which data is marshaled, is not explicitly called out. Architecturally speaking, it is only the interface proxy for a given interface and its corresponding interface stub that cares at all about what set of marshaling rules is in fact used. However, in the general case these interface proxies and stubs may be installed on different computers with a network in the middle, be written by different development organizations on different operating systems, and so forth. Accordingly, in cases where the author of an interface proxy for a given IID cannot guarantee that all copies of the corresponding interface stub are in fact always revised and updated in synchrony with his interface proxy, a well-defined convention should be used for the transfer syntax. Indeed, formal transfer syntax standards exist for this purpose. The one most commonly used is known as Network Data Representation (NDR), originally developed by Apollo Corporation and subsequently enhanced and adopted by the Open Software Foundation as part of their Distributed Computing Environment (DCE). The Windows NT operating system also uses NDR in its RPC implementation. Unless very good reasons exist to do otherwise, programmers are encouraged to use the NDR transfer syntax.

When NDR transfer syntax is used (and whether it is in use or not is implicitly known by the proxy or stub), the member dataRepresentation provides further information about the rules by which data in the buffer is marshaled. NDR is a multi-canonical standard, meaning that rather than adopting one standard for things like byte-order, character set, and so forth, multiple standards (a fixed set of them) are accommodated. Specifically, this is accommodated by a reader-make-right policy: the writer / marshaler of the data is free to write the data in any of the supported variations and the reader / unmarshaler is expected to be able to read any of them. The particular data type in use is conveyed in an RPCOLEDATAREP structure, which is defined as follows. Note that this structure, too, is packed; the size of the entire structure is exactly four bytes. The actual layout of the structure in all cases always corresponds to the data representation value as defined in the DCE standard; the particular structure shown here is equivalent to that layout in Microsoft's and other common compilers.


typedef RPCOLEDATAREP {
   UINT      uCharacterRep    : 4;      // least signficant nibble of first byte
   UINT      uByteOrder      : 4;      // most signficant nibble of first byte
   BYTE      uFloatRep;
   BYTE      uReserved;
   BYTE      uReserved2;
   } RPCOLEDATAREP;

The values which may legally be found in these fields are as shown in this table. Further information on the interpretation of this field can be found in the NDR Transfer Syntax standards documentation.

Field Name

Meaning of Field

Value in field

Interpretation

uCharacterRep

determines interpretation of single-byte-character valued and single-byte-string valued entities

0

1

ASCII

EBCDIC

uByteOrder

integer and floating point byte order

0

1

Big-endian (Motorola)

Little-endian (Intel)

uFloatRep

representation of floating point numbers

0

1

2

3

IEEE

VAX

Cray

IBM


Table. Interpretation of dataPresentation