Incremental Serialization

When using the incremental style, you supply three routines to manipulate the buffer when required by the stub. These routines are: Alloc, Read, and Write. The Alloc routine allocates a buffer of the required size. The Write routine writes the data into the buffer, and the Read routine retrieves a buffer that contains marshalled data. A single serialization call can make several calls to these routines.

The incremental style of serialization uses the following routines:

The prototypes for the Alloc, Read, and Write functions that you must provide are shown below:

void __RPC_USER Alloc (
   void *State,          /* application-defined pointer */
   char **pBuffer,       /* returns pointer to allocated buffer */
   unsigned int *pSize); /* inputs requested bytes; outputs 
                         /* pBuffer size */
void __RPC_USER Write (
   void *State,          /* application-defined pointer */
   char *Buffer,         /* buffer with serialized data */
   unsigned int Size);   /* number of bytes to write from Buffer */
void __RPC_USER Read (
   void *State,          /* application-defined pointer */
   char **pBuffer,       /* returned pointer to buffer with data */
   unsigned int *pSize); /* number of bytes to read into pBuffer */
 

The State input argument for all three functions is the application-defined pointer that was associated with the encoding services handle. The application can use this pointer to access the data structure containing application-specific information such as a file handle or stream pointer. Note that the stubs do not modify the State pointer other than to pass it to the Alloc, Read, and Write functions. During encoding, Alloc is called to obtain a buffer into which the data is serialized. Then, Write is called to enable the application to control when and where the serialized data is stored. When decoding, Read is called to return the requested number of bytes of serialized data from wherever the application stored it.

An important feature of the incremental style is that the handle keeps the state pointer for you. This pointer maintains the state and is never touched by the RPC code, except when passing the pointer to Alloc, Write, or Read function. The handle also maintains an internal state that makes it possible to serialize and deserialize several type instances to the same buffer by adding padding as needed for alignment. The MesIncrementalHandleReset function resets a handle to its initial state to enable reading or writing from the beginning of the buffer.

The Alloc and Write functions, along with an application-defined pointer, are associated with an encoding-services handle by a call to the MesEncodeIncrementalHandleCreate function. MesEncodeIncrementalHandleCreate allocates the memory needed for the handle and then initializes it. It has the following prototype:

RPC_STATUS RPC_ENTRY MesEncodeIncrementalHandleCreate (
    void * UserState,        /* application-defined pointer */
    MIDL_ES_ALLOC Alloc,     /* pointer to Alloc function */
    MIDL_ES_WRITE Write,     /* pointer to Write function */
    handle_t *pHandle);      /* receives encoding services handle */
 

The application can call MesDecodeIncrementalHandleCreate to create a decoding handle, MesIncrementalHandleReset to reinitialize the handle, or MesHandleFree to free the handle's memory. The Read function, along with an application-defined parameter, is associated with a decoding handle by a call to the MesDecodeIncrementalHandleCreate routine. The function creates the handle and initializes it. It has the following prototype:

RPC_STATUS RPC_ENTRY MesDecodeIncrementalHandleCreate (
    void * UserState,        /* application-defined pointer */
    MIDL_ES_READ Read,       /* pointer to Read function */
    handle_t Handle);        /* handle to create and initialize */
 

The UserState, Alloc, Write, and Read parameters of MesIncrementalHandleReset can be NULL to indicate no change.

RPC_STATUS RPC_ENTRY MesIncrementalHandleReset (
    handle_t Handle,         /* handle to reinitialize */
    void * UserState,        /* application-defined pointer */
    MIDL_ES_ALLOC Alloc,     /* pointer to Alloc function */
    MIDL_ES_WRITE Write,     /* pointer to Write function */
    MIDL_ES_READ Read,       /* pointer to Read function */
    MIDL_ES_CODE OpCode);    /* operations allowed */

RPC_STATUS RPC_ENTRY MesHandleFree (
    handle_t Handle);            // handle to free