/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Copyright (c) 1993-2000 Microsoft Corporation

Module Name:

    pickle.cxx

Abstract:

    This module contains pickling related ndr library routines.

Notes:

Author:

    Ryszard K. Kott (ryszardk)  Oct 10, 1993

Revision History:

    ryszardk    Mar 17, 1994    Reworked for midl20


------------------------------------------------------------------------*/

#include <ndrp.h>
#include <rpcdcep.h>
#include "ndrtypes.h"
#include <midles.h>
#include <stdarg.h>
#include <malloc.h>
#include "interp2.h"
#include "mulsyntx.h"

#include "picklep.hxx"
#include "util.hxx" // PerformRpcInitialization

extern const MIDL_FORMAT_STRING __MIDLFormatString;

// DCE puts endianness on the low nibble in the pickling header.

#define NDR_LOCAL_ENDIAN_LOW    (NDR_LOCAL_ENDIAN >> 4)

RPC_STATUS
NdrpPerformRpcInitialization (
    void
    )
{
    return PerformRpcInitialization();
}




// =======================================================================
//    Handle validation
// =======================================================================

void
NdrpValidateMesHandle(
    PMIDL_ES_MESSAGE_EX  pMesMsgEx )
{
    RpcTryExcept
        {
        if ( pMesMsgEx == 0  ||  pMesMsgEx->Signature != MIDL_ES_SIGNATURE  ||
             pMesMsgEx->MesMsg.MesVersion != MIDL_ES_VERSION )
            RpcRaiseException( RPC_S_INVALID_ARG );
        }
    RpcExcept( 1 )
        {
        RpcRaiseException( RPC_S_INVALID_ARG );
        }
    RpcEndExcept
}

RPC_STATUS
NdrpValidateMesHandleReturnStatus(
    PMIDL_ES_MESSAGE_EX  pMesMsgEx )
{
    RPC_STATUS  Status = RPC_S_OK;

    RpcTryExcept
        {
        if ( pMesMsgEx == 0  ||  pMesMsgEx->Signature != MIDL_ES_SIGNATURE  ||
             ( pMesMsgEx->MesMsg.MesVersion != MIDL_ES_VERSION &&
               pMesMsgEx->MesMsg.MesVersion != MIDL_NDR64_ES_VERSION ) )
            Status = RPC_S_INVALID_ARG;
        }
    RpcExcept( 1 )
        {
        Status = RPC_S_INVALID_ARG;
        }
    RpcEndExcept

    return Status;
}



// =======================================================================
//    Handle allocation and freeing.
// =======================================================================

RPC_STATUS
NdrpHandleAllocate(
    handle_t *    pHandle )
/*++
    The reason for having this function here is that
    handle_t is a near pointer on win16 (but not on Dos),
    and we still compile the whole rpcndr20 large for that platform.
    So we need near malloc to be within the default segment.
--*/
{
    RPC_STATUS RpcStatus;

    if ( pHandle == NULL )
        return( RPC_S_INVALID_ARG );

    // Rpc mtrt heap allocation initialization (any platform).
    // This is a macro that returns from NdrpHandleAllocate with
    // out of memory error when it fails.
    // It's under an if only to facilitate testing.


    RpcStatus = NdrpPerformRpcInitialization();
    if ( RpcStatus != RPC_S_OK )
        return(RpcStatus);

    // Now allocate.
    // Mes handle includes stubmsg but we need to add rpcmsg to it.

    *pHandle = new char[ sizeof(MIDL_ES_MESSAGE_EX) ];

    if ( *pHandle == NULL )
        return( RPC_S_OUT_OF_MEMORY );
    return( RPC_S_OK );
}

RPC_STATUS  RPC_ENTRY
MesHandleFree( handle_t  Handle )
/*++
    This routine frees a pickling handle.
--*/
{
    if ( Handle)
        {
        delete Handle;
        }
    return( RPC_S_OK );
}

void RPC_ENTRY
I_NdrMesMessageInit(
    PMIDL_ES_MESSAGE_EX pMesMsgEx )
{
    PMIDL_STUB_MESSAGE  pStubMsg = & pMesMsgEx->MesMsg.StubMsg;
    PRPC_MESSAGE        pRpcMsg  = & pMesMsgEx->RpcMsg;

    MIDL_memset( pStubMsg, 0, sizeof(MIDL_STUB_MESSAGE) );
    MIDL_memset( pRpcMsg, 0, sizeof(RPC_MESSAGE) );

    pRpcMsg->DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;

    pStubMsg->RpcMsg   = pRpcMsg;
    pStubMsg->IsClient = 1;

    NdrSetupLowStackMark( pStubMsg );
}


// =======================================================================

RPC_STATUS RPC_ENTRY
MesEncodeIncrementalHandleCreate(
    void     *    UserState,
    MIDL_ES_ALLOC           Alloc,
    MIDL_ES_WRITE           Write,
    handle_t *    pHandle )
/*++
    This routine creates an encoding incremental pickling handle.
--*/
{
    RPC_STATUS Status;

    if ( (Status = NdrpHandleAllocate( pHandle )) == RPC_S_OK )
        {
        ((PMIDL_ES_MESSAGE) *pHandle)->HandleStyle = MES_INCREMENTAL_HANDLE;
        ((PMIDL_ES_MESSAGE) *pHandle)->MesVersion  = MIDL_ES_VERSION;
        ((PMIDL_ES_MESSAGE_EX)*pHandle)->Signature = MIDL_ES_SIGNATURE;

        if ( (Status = MesIncrementalHandleReset( *pHandle,
                                                  UserState,
                                                  Alloc,
                                                  Write,
                                                  0,
                                                  MES_ENCODE )) != RPC_S_OK )
            {
            MesHandleFree( *pHandle );
            *pHandle = NULL;
            }
        }

    return( Status );
}

RPC_STATUS RPC_ENTRY
MesDecodeIncrementalHandleCreate(
    void     *      UserState,
    MIDL_ES_READ    Read,
    handle_t *      pHandle )
/*++
    This routine creates a descoding incrementsl pickling handle.
--*/
{
    RPC_STATUS Status;

    if ( (Status = NdrpHandleAllocate( pHandle )) == RPC_S_OK )
        {
        ((PMIDL_ES_MESSAGE) *pHandle)->HandleStyle = MES_INCREMENTAL_HANDLE;
        ((PMIDL_ES_MESSAGE) *pHandle)->MesVersion  = MIDL_ES_VERSION;
        ((PMIDL_ES_MESSAGE_EX)*pHandle)->Signature = MIDL_ES_SIGNATURE;

        if ( (Status = MesIncrementalHandleReset( *pHandle,
                                                  UserState,
                                                  0,
                                                  0,
                                                  Read,
                                                  MES_DECODE )) != RPC_S_OK )
            {
            MesHandleFree( *pHandle );
            *pHandle = NULL;
            }
        }

    return( Status );
}


RPC_STATUS  RPC_ENTRY
MesIncrementalHandleReset(
    handle_t           Handle,
    void *             UserState,
    MIDL_ES_ALLOC      Alloc,
    MIDL_ES_WRITE      Write,
    MIDL_ES_READ       Read,
    MIDL_ES_CODE       Operation )
/*++
    This routine initializes a pickling handle with supplied arguments.
--*/
{
    RPC_STATUS  Status;

    Status = NdrpValidateMesHandleReturnStatus( (PMIDL_ES_MESSAGE_EX)Handle );
    if ( Status != RPC_S_OK )
        return Status;

    PMIDL_ES_MESSAGE  pMesMsg = (PMIDL_ES_MESSAGE) Handle;

    // we support ndr64 pickling now.
    if ( Handle == NULL  ||
         pMesMsg->HandleStyle != MES_INCREMENTAL_HANDLE  ||
         ( Operation != MES_ENCODE  &&  
           Operation != MES_DECODE  &&
           Operation != MES_ENCODE_NDR64 &&
           Operation != MES_DECODE_NDR64 ) )
        return( RPC_S_INVALID_ARG );

    I_NdrMesMessageInit( (PMIDL_ES_MESSAGE_EX) Handle );

    pMesMsg->Operation  = Operation;
    pMesMsg->HandleFlags = 0;
    pMesMsg->ByteCount = 0;
    if ( Operation == MES_ENCODE_NDR64 ||
         Operation == MES_DECODE_NDR64 )
        {
        pMesMsg->MesVersion  = MIDL_NDR64_ES_VERSION;
        }
    else
        {
        pMesMsg->MesVersion  = MIDL_ES_VERSION;
        }

    if ( UserState )
        pMesMsg->UserState = UserState;
    if ( Alloc )
        pMesMsg->Alloc = Alloc;
    if ( Write )
        pMesMsg->Write = Write;
    if ( Read )
        pMesMsg->Read  = Read;

    if ( ( (Operation == MES_ENCODE || Operation == MES_ENCODE_NDR64 ) &&
             (pMesMsg->Alloc == NULL  ||  pMesMsg->Write == NULL) ) ||
         ( (Operation == MES_DECODE  || Operation == MES_DECODE_NDR64 ) && 
            (pMesMsg->Read == NULL))  )
        return( RPC_S_INVALID_ARG );

    return( RPC_S_OK );
}


RPC_STATUS  RPC_ENTRY
MesEncodeFixedBufferHandleCreate(
    char *            Buffer,
    unsigned long     BufferSize,
    unsigned long *   pEncodedSize,
    handle_t  *       pHandle )
{
    RPC_STATUS Status;

    if( (LONG_PTR)Buffer & 0x7 )
        return( RPC_X_INVALID_BUFFER );

    if ( (Status = NdrpHandleAllocate( pHandle )) == RPC_S_OK )
        {
        ((PMIDL_ES_MESSAGE) *pHandle)->HandleStyle = MES_FIXED_BUFFER_HANDLE;
        ((PMIDL_ES_MESSAGE) *pHandle)->MesVersion  = MIDL_ES_VERSION;
        ((PMIDL_ES_MESSAGE_EX)*pHandle)->Signature = MIDL_ES_SIGNATURE;

        if ( (Status = MesBufferHandleReset( *pHandle,
                                             MES_FIXED_BUFFER_HANDLE,
                                             MES_ENCODE,
                                             & Buffer,
                                             BufferSize,
                                             pEncodedSize )) != RPC_S_OK )
            {
            MesHandleFree( *pHandle );
            *pHandle = NULL;
            }
        }

    return( Status );
}

RPC_STATUS  RPC_ENTRY
MesEncodeDynBufferHandleCreate(
    char             ** pBuffer,
    unsigned long    *  pEncodedSize,
    handle_t         *  pHandle )
{
    RPC_STATUS Status;

    if ( (Status = NdrpHandleAllocate( pHandle )) == RPC_S_OK )
        {
        ((PMIDL_ES_MESSAGE) *pHandle)->HandleStyle = MES_DYNAMIC_BUFFER_HANDLE;
        ((PMIDL_ES_MESSAGE) *pHandle)->MesVersion  = MIDL_ES_VERSION;
        ((PMIDL_ES_MESSAGE_EX)*pHandle)->Signature = MIDL_ES_SIGNATURE;

        if ( (Status = MesBufferHandleReset( *pHandle,
                                             MES_DYNAMIC_BUFFER_HANDLE,
                                             MES_ENCODE,
                                             pBuffer,
                                             0,
                                             pEncodedSize )) != RPC_S_OK )
            {
            MesHandleFree( *pHandle );
            *pHandle = NULL;
            }
        }

    return( Status );
}

RPC_STATUS  RPC_ENTRY
MesDecodeBufferHandleCreate(
    char *          Buffer,
    unsigned long   BufferSize,
    handle_t  *     pHandle )
{
    if ( Buffer == NULL  ||
         BufferSize < MES_CTYPE_HEADER_SIZE + 8 )
        return( RPC_S_INVALID_ARG );

    if( (LONG_PTR)Buffer & 0x7 )
        return( RPC_X_INVALID_BUFFER );

    RPC_STATUS Status;

    if ( (Status = NdrpHandleAllocate( pHandle )) == RPC_S_OK )
        {
        ((PMIDL_ES_MESSAGE) *pHandle)->HandleStyle = MES_FIXED_BUFFER_HANDLE;
        ((PMIDL_ES_MESSAGE) *pHandle)->MesVersion  = MIDL_ES_VERSION;
        ((PMIDL_ES_MESSAGE_EX)*pHandle)->Signature = MIDL_ES_SIGNATURE;

        if ( (Status = MesBufferHandleReset( *pHandle,
                                             MES_FIXED_BUFFER_HANDLE,
                                             MES_DECODE,
                                             & Buffer,
                                             BufferSize,
                                             0            )) != RPC_S_OK )
            {
            MesHandleFree( *pHandle );
            *pHandle = NULL;
            }
        }

    return( Status );
}


// reset a pickling handle. 
RPC_STATUS  RPC_ENTRY
MesBufferHandleReset(
    handle_t            Handle,
    unsigned long       HandleStyle,
    MIDL_ES_CODE        Operation,
    char * *            pBuffer,
    unsigned long       BufferSize,
    unsigned long *     pEncodedSize )
{
    RPC_STATUS  Status;

    Status = NdrpValidateMesHandleReturnStatus( (PMIDL_ES_MESSAGE_EX)Handle );
    if ( Status != RPC_S_OK )
        return Status;

    PMIDL_ES_MESSAGE    pMesMsg = (PMIDL_ES_MESSAGE) Handle;

    if ( Handle == NULL ||  pBuffer == NULL  ||
        ( HandleStyle != MES_FIXED_BUFFER_HANDLE  &&
            HandleStyle != MES_DYNAMIC_BUFFER_HANDLE )  ||
        (HandleStyle == MES_FIXED_BUFFER_HANDLE  &&
            (*pBuffer == NULL  ||  BufferSize < MES_MINIMAL_BUFFER_SIZE)) ||
        (Operation == MES_ENCODE  &&  pEncodedSize == NULL)  ||
        (Operation == MES_DECODE  &&
            (*pBuffer == NULL  ||  BufferSize < MES_MINIMAL_BUFFER_SIZE))
       )
        return( RPC_S_INVALID_ARG );

    if ( (Operation == MES_ENCODE_NDR64  &&  pEncodedSize == NULL)  ||
        (Operation == MES_DECODE_NDR64  &&
            (*pBuffer == NULL  ||  BufferSize < MES_MINIMAL_NDR64_BUFFER_SIZE ) ) )
        return( RPC_S_INVALID_ARG );

    I_NdrMesMessageInit( (PMIDL_ES_MESSAGE_EX) Handle );

    pMesMsg->Operation  = Operation;
    pMesMsg->HandleFlags = 0;
    pMesMsg->HandleStyle = HandleStyle;
    pMesMsg->ByteCount = 0;
    if ( Operation == MES_ENCODE_NDR64 ||
         Operation == MES_DECODE_NDR64 )
        {
        pMesMsg->MesVersion  = MIDL_NDR64_ES_VERSION;
        }
    else
        {
        pMesMsg->MesVersion  = MIDL_ES_VERSION;
        }


    PMIDL_STUB_MESSAGE  pStubMsg = & pMesMsg->StubMsg;
    PRPC_MESSAGE        pRpcMsg  =   pMesMsg->StubMsg.RpcMsg;

    if ( HandleStyle == MES_FIXED_BUFFER_HANDLE)
        {
        pMesMsg->Buffer         = (uchar *)*pBuffer;

        pRpcMsg->BufferLength = BufferSize;
        pRpcMsg->Buffer       = *pBuffer;

        pStubMsg->Buffer      = (uchar *)*pBuffer;
        pStubMsg->BufferStart = (uchar *)*pBuffer;
        pStubMsg->BufferEnd   = (uchar *)*pBuffer + BufferSize;
        }
    if ( HandleStyle == MES_DYNAMIC_BUFFER_HANDLE)
        {
        pMesMsg->pDynBuffer = (uchar **)pBuffer;
        if (Operation == MES_DECODE || Operation == MES_DECODE_NDR64 )
            {
            pMesMsg->Buffer       = (uchar *)*pBuffer;

            pRpcMsg->BufferLength = BufferSize;
            pRpcMsg->Buffer       = *pBuffer;

            pStubMsg->Buffer      = (uchar *)*pBuffer;
            pStubMsg->BufferStart = (uchar *)*pBuffer;
            pStubMsg->BufferEnd   = (uchar *)*pBuffer + BufferSize;
            }
        else
            {
            *pBuffer = NULL;

            pRpcMsg->BufferLength = 0;
            pRpcMsg->Buffer       = 0;

            pStubMsg->Buffer      = 0;
            pStubMsg->BufferStart = 0;
            pStubMsg->BufferEnd   = 0;
            }
        }
    pMesMsg->BufferSize = BufferSize;
    pMesMsg->pEncodedSize = pEncodedSize;

    return( RPC_S_OK );
}


RPC_STATUS  RPC_ENTRY
MesInqProcEncodingId(
    handle_t                Handle,
    PRPC_SYNTAX_IDENTIFIER  pInterfaceId,
    unsigned long *         pProcNumber )
/*++

    The routine returns an informantion about the last proc encoding.
    Called before an encode, it should return RPC_X_INVALID_ES_ACTION.
    Called after an encode, it should return the last encoding info.
    Called before a decode, it should return the same encoding info.
    Called after a decode, it should return the just decoded encode info.

--*/
{
    RPC_STATUS  Status;

    Status = NdrpValidateMesHandleReturnStatus( (PMIDL_ES_MESSAGE_EX)Handle );
    if ( Status != RPC_S_OK )
        return Status;

    PMIDL_ES_MESSAGE  pMesMsg = (PMIDL_ES_MESSAGE) Handle;

    Status  = RPC_X_INVALID_ES_ACTION;

    if ( Handle == NULL  ||  pInterfaceId == NULL  ||  pProcNumber == NULL )
        return( RPC_S_INVALID_ARG );

    RpcTryExcept
        {
        // Note: because we allow to pickle several procs into the same buffer
        // (using the same handle without resetting), the PEEKED bit may be
        // cleared and the info may still be available.
        // On the other hand, the info bit is always set if we unmarshaled
        // a header. So check the info bit first.

        if ( pMesMsg->Operation == MES_DECODE  &&
             ! GET_MES_INFO_AVAILABLE( pMesMsg ) &&
             ! GET_MES_HEADER_PEEKED( pMesMsg ) )
            {
            NdrpProcHeaderUnmarshallAll( pMesMsg );
            SET_MES_HEADER_PEEKED( pMesMsg );
            }
            
        if ( GET_MES_INFO_AVAILABLE( pMesMsg ) )
            {
            RpcpMemoryCopy( pInterfaceId,
                            & pMesMsg->InterfaceId,
                            sizeof( RPC_SYNTAX_IDENTIFIER ) );
            *pProcNumber = pMesMsg->ProcNumber;
            Status =  RPC_S_OK;
            }
        // else Status = RPC_X_INVALID_ES_ACTION;
        }
    RpcExcept(1)
        {
        Status = RpcExceptionCode();
        }
    RpcEndExcept

    return( Status );
}


// =======================================================================
//
//   Private Alloc, Read, Write helper routines
//
// =======================================================================

void
NdrpAllocPicklingBuffer(
    PMIDL_ES_MESSAGE    pMesMsg,
    unsigned int        RequiredLen
    )
{
    unsigned int ActualLen;

    PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;

    // Get the marshalling buffer.

    // alert: assuming the return buffer is aligned at 16 in 64bit platform. 
    // ndr64 buffer needs to be aligned at 16.
    switch ( pMesMsg->HandleStyle )
        {
        case MES_INCREMENTAL_HANDLE:
            // Allocating the pickling buffer.

            ActualLen = RequiredLen;
            (pMesMsg->Alloc)( pMesMsg->UserState,
                              (char * *) & pStubMsg->Buffer,
                              & ActualLen );
            if ( ActualLen < RequiredLen )
                RpcRaiseException( RPC_S_OUT_OF_MEMORY );

            pStubMsg->RpcMsg->BufferLength = ActualLen;
            pStubMsg->RpcMsg->Buffer       = pStubMsg->Buffer;

            pStubMsg->BufferStart = pStubMsg->Buffer;
            pStubMsg->BufferEnd   = pStubMsg->Buffer + ActualLen;
            break;

        case MES_FIXED_BUFFER_HANDLE:
            break;

        case MES_DYNAMIC_BUFFER_HANDLE:
            {
            // We have to return one buffer for multiple encodings,
            // and a cumulative size along with it.
            // So, we check if we have to copy data to a new buffer.

            uchar * pOldBufferToCopy = NULL;

            if ( pMesMsg->ByteCount )
                {
                RequiredLen += pMesMsg->ByteCount;
                pOldBufferToCopy = *pMesMsg->pDynBuffer;
                }

            pStubMsg->Buffer = (uchar *) pStubMsg->pfnAllocate( RequiredLen );
            if ( pStubMsg->Buffer == NULL )
                RpcRaiseException( RPC_S_OUT_OF_MEMORY );

            if ( pOldBufferToCopy )
                {
                RpcpMemoryCopy( pStubMsg->Buffer,
                                pOldBufferToCopy,
                                pMesMsg->ByteCount );

                pStubMsg->pfnFree( pOldBufferToCopy );
                }

            pStubMsg->RpcMsg->BufferLength = RequiredLen;
            pStubMsg->RpcMsg->Buffer       = pStubMsg->Buffer;

            pStubMsg->BufferStart = pStubMsg->Buffer;
            pStubMsg->BufferEnd   = pStubMsg->Buffer + RequiredLen;

            * pMesMsg->pDynBuffer = pStubMsg->Buffer;
            pMesMsg->BufferSize = RequiredLen;

            // We write after the previously written buffer.

            pStubMsg->Buffer += pMesMsg->ByteCount;
            break;
            }
        }

    if( (LONG_PTR)pStubMsg->Buffer & 0x7 )
        RpcRaiseException( RPC_X_INVALID_BUFFER );
}

void
NdrpReadPicklingBuffer(
    PMIDL_ES_MESSAGE    pMesMsg,
    unsigned int        RequiredLen
    )
{
    unsigned int ActualLen;
    PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;

    // Read the marshalling buffer.

    if ( pMesMsg->HandleStyle  == MES_INCREMENTAL_HANDLE )
        {
            // Allocating the pickling buffer.

            ActualLen = RequiredLen;
            (pMesMsg->Read)( pMesMsg->UserState,
                             (char **) & pStubMsg->Buffer,
                             & ActualLen );
            if ( ActualLen < RequiredLen )
                RpcRaiseException( RPC_S_OUT_OF_MEMORY );

            pStubMsg->RpcMsg->BufferLength = ActualLen;
            pStubMsg->RpcMsg->Buffer       = pStubMsg->Buffer;

            pStubMsg->BufferStart = pStubMsg->Buffer;
            pStubMsg->BufferEnd   = pStubMsg->Buffer + ActualLen;
        }

    if( (LONG_PTR)pStubMsg->Buffer & 0x7 )
        RpcRaiseException( RPC_X_INVALID_BUFFER );
}

void
NdrpWritePicklingBuffer(
    PMIDL_ES_MESSAGE    pMesMsg,
    uchar *             pBuffer,
    size_t              WriteLength
    )
{
    PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;

    NDR_ASSERT( ! ((LONG_PTR)pStubMsg->Buffer & 0x7), "Misaligned buffer" );
    NDR_ASSERT( ! (WriteLength & 0x7 ), "Length should be multiple of 8" );

    // Write the marshalling buffer.

    if ( pMesMsg->HandleStyle == MES_INCREMENTAL_HANDLE )
        {
        (pMesMsg->Write)( pMesMsg->UserState,
                          (char * ) pBuffer,
                          WriteLength );
        }
    else
        {
        // We return the cumulative length both for the fixed buffer
        // and for the dynamic buffer style.

        pMesMsg->ByteCount += WriteLength;
        * pMesMsg->pEncodedSize = pMesMsg->ByteCount;
        }
}



// =======================================================================
//
//   One call generic routine pickling.
//
// =======================================================================


void
NdrpProcHeaderMarshall(
    PMIDL_ES_MESSAGE    pMesMsg
    )
{
    PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;

    // Marshall DCE pickle header.

    if( (LONG_PTR)pStubMsg->Buffer & 0x7 )
        RpcRaiseException( RPC_X_INVALID_BUFFER );

    * pStubMsg->Buffer++ = MIDL_ES_VERSION;
    * pStubMsg->Buffer++ = NDR_LOCAL_ENDIAN_LOW;
    *( PSHORT_LV_CAST pStubMsg->Buffer)++ = (short)0xcccc;    // filler

    // Marshall transfer syntax from the stub.

    RpcpMemoryCopy( pStubMsg->Buffer,
                    & ((PRPC_CLIENT_INTERFACE)(pStubMsg->
                          StubDesc->RpcInterfaceInformation))->TransferSyntax,
                    sizeof(RPC_SYNTAX_IDENTIFIER) );

    // We need to remember InterfaceId for inquiries.

    RpcpMemoryCopy( & pMesMsg->InterfaceId,
                    & ((PRPC_CLIENT_INTERFACE)(pStubMsg->
                         StubDesc->RpcInterfaceInformation))->InterfaceId,
                    sizeof(RPC_SYNTAX_IDENTIFIER) );

   // Marshall InterfaceId and ProcNumber from the handle.

    RpcpMemoryCopy( pStubMsg->Buffer + sizeof(RPC_SYNTAX_IDENTIFIER),
                    & pMesMsg->InterfaceId,
                    sizeof(RPC_SYNTAX_IDENTIFIER) + sizeof(long) );

    SET_MES_INFO_AVAILABLE( pMesMsg );

    pStubMsg->Buffer += 2 * sizeof(RPC_SYNTAX_IDENTIFIER) + sizeof(long);

    * pStubMsg->Buffer++ = NDR_LOCAL_ENDIAN_LOW;
    * pStubMsg->Buffer++ = NDR_ASCII_CHAR;
    * pStubMsg->Buffer++ = (char) (NDR_IEEE_FLOAT >> 8);
    * pStubMsg->Buffer++ = 0;   // filler

    // This is non-DCE element as they have just 4 more bytes of filler here.
    // This field is used only when unmarshalling in our incremental style.

    *( PLONG_LV_CAST pStubMsg->Buffer)++ = pStubMsg->BufferLength -
                                                   MES_PROC_HEADER_SIZE;
}

void
NdrpProcHeaderUnmarshall(
    PMIDL_ES_MESSAGE    pMesMsg
    )
{
    unsigned char *         BufferToRestore;
    PMIDL_STUB_MESSAGE      pStubMsg = &pMesMsg->StubMsg;

    if ( GET_MES_HEADER_PEEKED( pMesMsg ) )
        return;

    NdrpReadPicklingBuffer( pMesMsg, MES_PROC_HEADER_SIZE );

    // Unmarshalling the header

    if ( *pStubMsg->Buffer != MIDL_ES_VERSION )
        RpcRaiseException( RPC_X_WRONG_ES_VERSION );

    BufferToRestore = pStubMsg->Buffer + 4;

    if ( pStubMsg->Buffer[1] != NDR_LOCAL_ENDIAN_LOW )
        {
        // The DCE header has the endianness on the low nibble, while
        // our DataRep has it on the high nibble.
        // We need only endianess to convert the proc header.

        byte Endianness = (pStubMsg->Buffer[1] << 4 );

        pStubMsg->RpcMsg->DataRepresentation = Endianness;

        pStubMsg->Buffer += 4;
        NdrSimpleStructConvert( pStubMsg,
                                &__MIDLFormatString.Format[32],
                                FALSE );
        }

    pStubMsg->Buffer = BufferToRestore;

    // Verify the transfer syntax

    if ( NULL != pStubMsg->StubDesc )
        {
        if (0 != RpcpMemoryCompare( 
                        pStubMsg->Buffer,
                        & ((PRPC_CLIENT_INTERFACE)(pStubMsg->
                            StubDesc->RpcInterfaceInformation))->
TransferSyntax,
                        sizeof(RPC_SYNTAX_IDENTIFIER) ) )
            {
            RpcRaiseException( RPC_S_UNSUPPORTED_TRANS_SYN );
            } 
        }

    RpcpMemoryCopy( &((PMIDL_ES_MESSAGE_EX)pMesMsg)->TransferSyntax, 
                      pStubMsg->Buffer,
                      sizeof( RPC_SYNTAX_IDENTIFIER ) );

    pStubMsg->Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);

    // We need to remember the last InterfaceId and ProcNumber for inquiries.

    RpcpMemoryCopy( & pMesMsg->InterfaceId,
                    pStubMsg->Buffer,
                    sizeof(RPC_SYNTAX_IDENTIFIER) + sizeof(long) );

    pStubMsg->Buffer += sizeof(RPC_SYNTAX_IDENTIFIER) + sizeof(long);

    SET_MES_INFO_AVAILABLE( pMesMsg );

    unsigned long AlienDataRepresentation =
                        ( (pStubMsg->Buffer[0] << 4)  |           // endianness
                          pStubMsg->Buffer[1]  |                       // chars
                        ((unsigned long)(pStubMsg->Buffer[2]) << 8) ); // float
    pMesMsg->AlienDataRep = AlienDataRepresentation;
    pMesMsg->IncrDataSize = (size_t) *(unsigned long *)
                                                (pStubMsg->Buffer + 4);
    pStubMsg->Buffer += 8;
}

void
NdrpDataBufferInit(
    PMIDL_ES_MESSAGE    pMesMsg,
    PFORMAT_STRING      pProcFormat
    )
{
    size_t              RequiredLen;
    PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;

    if ( pMesMsg->AlienDataRep != NDR_LOCAL_DATA_REPRESENTATION )
        {
        pStubMsg->RpcMsg->DataRepresentation = pMesMsg->AlienDataRep;
        NdrConvert( pStubMsg, pProcFormat );
        }

    // When incremental, this is the non-DCE buffer size.
    // For non incremental RequiredLen will be ignored.

    RequiredLen = pMesMsg->IncrDataSize;

    NdrpReadPicklingBuffer( pMesMsg, RequiredLen );

    pStubMsg->pfnAllocate = pStubMsg->StubDesc->pfnAllocate;
    pStubMsg->pfnFree     = pStubMsg->StubDesc->pfnFree;
}


void  RPC_VAR_ENTRY
NdrMesProcEncodeDecode(
    handle_t                Handle,
    const MIDL_STUB_DESC *  pStubDesc,
    PFORMAT_STRING          pFormat,
    ...
    )
/*++

Routine description:

    Sizes and marshalls [in] arguments, unmarshalls [out] arguments.
    Includes a routine header.

Arguments:

    Handle      - a pickling handle
    pStubDesc   - a pointer to the stub descriptor,
    pFormat     - a pointer to the format code describing the object type.

Note:

    Please note that all the ... arguments here are pointers.
    We will handle them appropriately to access the original arguments.

    The pickling header for the routine is included in the sizing.

--*/
{
    BOOL                fMoreParams;
    PFORMAT_STRING      pProcFormat;
    void            *   pArg;
    va_list             ArgList;
    unsigned char   *   BufferSaved;
    size_t              WriteLength;

    NdrpValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle );

    PMIDL_ES_MESSAGE    pMesMsg  = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE  pStubMsg = & pMesMsg->StubMsg;

    NDR_ASSERT( *pFormat == FC_BIND_PRIMITIVE  ||  *pFormat == 0,
                "Pickling handle expected" );

    pStubMsg->StubDesc = pStubDesc;
    pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
    pStubMsg->pfnFree     = pStubDesc->pfnFree;

    BOOL fEncodeUsed = (pFormat[1] & ENCODE_IS_USED)  &&
                       pMesMsg->Operation == MES_ENCODE;
    BOOL fDecodeUsed = (pFormat[1] & DECODE_IS_USED)  &&
                       pMesMsg->Operation == MES_DECODE;

    NDR_ASSERT( !( fEncodeUsed && fDecodeUsed ),
                "Both encode & decode at the same time" );

    if ( !fEncodeUsed && !fDecodeUsed )
        RpcRaiseException( RPC_X_INVALID_ES_ACTION );

    pStubMsg->FullPtrXlatTables = ( (pFormat[1]  &  Oi_FULL_PTR_USED)
                                    ?  NdrFullPointerXlatInit( 0, XLAT_CLIENT )
                                    :  0 );

    pFormat += HAS_RPCFLAGS(pFormat[1]) ? 6
                                        : 2;

    // We use the proc number only to support MesInqEncodingId. So, set it for
    // encoding only. When decoding it will get picked up from the header.
    //
    if ( fEncodeUsed )
        pMesMsg->ProcNumber = * (unsigned short *) pFormat;

    pFormat +=4;

    if ( *pFormat == FC_BIND_PRIMITIVE )
        pFormat += 4;

    if ( fEncodeUsed )
        {
        //
        // The sizing walk.
        //

        pStubMsg->BufferLength = MES_PROC_HEADER_SIZE;

        // We will be walking this routine's stack.
        // However, for the engine to be able to calculate conformant arrays
        // and such, top of the original routine's stack has to be available
        // via the stub message.

        INIT_ARG( ArgList, pFormat );
        GET_FIRST_ARG( pArg, ArgList );

        pStubMsg->StackTop = *(uchar * *)pArg;
        pProcFormat = pFormat;
        fMoreParams = TRUE;

        for ( ; fMoreParams ; pProcFormat += 2 )
            {
            switch ( *pProcFormat )
                {
                case FC_OUT_PARAM:
                    break;

                case FC_RETURN_PARAM:
                    fMoreParams = FALSE;
                    break;
                default:
                    fMoreParams = FALSE;
                    break;

                case FC_IN_PARAM_BASETYPE :

                    LENGTH_ALIGN( pStubMsg->BufferLength,
                                SIMPLE_TYPE_ALIGNMENT( pProcFormat[1] ));
                    pStubMsg->BufferLength +=
                                SIMPLE_TYPE_BUFSIZE( pProcFormat[1] );
                    break;

                case FC_IN_PARAM:
                case FC_IN_PARAM_NO_FREE_INST:

                    // Other [in] types than simple or ignore
                    // fall through to [in,out].

                case FC_IN_OUT_PARAM:
                    {
                    uchar *         pOrigArg = *(uchar * *)pArg;
                    PFORMAT_STRING  pTypeFormat;
                    unsigned char   FcType;


                    pProcFormat += 2;
                    pTypeFormat = pStubDesc->pFormatTypes +
                                                *(signed short *) pProcFormat;
                    FcType = *pTypeFormat;

                    if ( ! IS_BY_VALUE( FcType ) )
                        pOrigArg = *(uchar * *)pOrigArg;

                    (*pfnSizeRoutines[ ROUTINE_INDEX( FcType ) ])( pStubMsg,
                                                                   pOrigArg,
                                                                   pTypeFormat );
                    }
                    break;
                }

            GET_NEXT_ARG( pArg, ArgList );
            }   // for

        LENGTH_ALIGN( pStubMsg->BufferLength, 7 );

        size_t  LengthSaved;

        NdrpAllocPicklingBuffer( pMesMsg, pStubMsg->BufferLength );
        BufferSaved = pStubMsg->Buffer;
        LengthSaved = pStubMsg->BufferLength;

        //
        // Marshalling.
        //

        NdrpProcHeaderMarshall( pMesMsg );

        INIT_ARG( ArgList, pFormat );
        GET_FIRST_ARG( pArg, ArgList );

        pProcFormat = pFormat;
        fMoreParams = TRUE;

        for ( ; fMoreParams ; pProcFormat += 2 )
            {
            switch ( *pProcFormat )
                {
                case FC_OUT_PARAM:
                    break;

                case FC_RETURN_PARAM:
                default:
                    fMoreParams = FALSE;
                    break;

                case FC_IN_PARAM_BASETYPE :

                    NdrSimpleTypeMarshall( pStubMsg,
                                           *(uchar * *)pArg,
                                           pProcFormat[1] );
                    break;

                case FC_IN_PARAM:
                case FC_IN_PARAM_NO_FREE_INST:
                case FC_IN_OUT_PARAM:
                    {
                    uchar *         pOrigArg = *(uchar * *)pArg;
                    PFORMAT_STRING  pTypeFormat;
                    unsigned char   FcType;

                    pProcFormat += 2;
                    pTypeFormat = pStubDesc->pFormatTypes +
                                                *(signed short *) pProcFormat;
                    FcType = *pTypeFormat;

                    if ( ! IS_BY_VALUE( FcType ) )
                        pOrigArg = *(uchar * *)pOrigArg;

                    (*pfnMarshallRoutines[ ROUTINE_INDEX( FcType )])( pStubMsg,
                                                                      pOrigArg,
                                                                      pTypeFormat );
                    }
                    break;
                }

            GET_NEXT_ARG( pArg, ArgList );
            }

        // Next encoding (if any) starts at aligned to 8.

        ALIGN( pStubMsg->Buffer, 7 );

        // Now manage the actual size of encoded data.

        WriteLength = (size_t)(pStubMsg->Buffer - BufferSaved);
        * (unsigned long *)
                ( BufferSaved + MES_PROC_HEADER_SIZE - 4) =
                                    WriteLength - MES_PROC_HEADER_SIZE;

        if ( LengthSaved < WriteLength )
            {
            NDR_ASSERT( 0, "NdrMesProcEncodeDecode: encode buffer overflow" );
            RpcRaiseException( RPC_S_INTERNAL_ERROR );
            }

        NdrpWritePicklingBuffer( pMesMsg, BufferSaved, WriteLength );
        }

    if ( fDecodeUsed )
        {
        //
        // Unmarshalling.
        //

        if ( GET_MES_HEADER_PEEKED( pMesMsg ) )
            {
            // This makes it possible to encode/decode several procs one after
            // another with the same pickling handle (using the same buffer).

            CLEAR_MES_HEADER_PEEKED( pMesMsg );
            }
        else
            NdrpProcHeaderUnmarshall( pMesMsg );

        NdrpDataBufferInit( pMesMsg, pFormat );

        INIT_ARG( ArgList, pFormat );
        GET_FIRST_ARG( pArg, ArgList );

        pStubMsg->StackTop = *(uchar * *)pArg;
        pProcFormat = pFormat;
        fMoreParams = TRUE;

        for ( ; fMoreParams ; pProcFormat += 2 )
            {
            switch ( *pProcFormat )
                {
                case FC_IN_PARAM_BASETYPE :
                case FC_IN_PARAM:
                case FC_IN_PARAM_NO_FREE_INST:
                    break;

                default:
                    fMoreParams = FALSE;
                    break;

                case FC_RETURN_PARAM_BASETYPE :

                    NdrSimpleTypeUnmarshall( pStubMsg,
                                             *(uchar * *)pArg,
                                             pProcFormat[1] );
                    fMoreParams = FALSE;
                    break;

                case FC_RETURN_PARAM:
                    fMoreParams = FALSE;

                    // fall through to out params.

                case FC_IN_OUT_PARAM:
                case FC_OUT_PARAM:
                    {
                    uchar *         pOrigArg = *(uchar * *)pArg;
                    PFORMAT_STRING  pTypeFormat;
                    unsigned char   FcType;

                    pProcFormat += 2;
                    pTypeFormat = pStubDesc->pFormatTypes +
                                                *(signed short *) pProcFormat;
                    FcType = *pTypeFormat;

                    if ( IS_STRUCT( FcType )  ||  IS_UNION( FcType)  ||
                         IS_XMIT_AS( FcType ) )
                        {
                        // All these are possible only as a return value.
                        pOrigArg = (uchar *) &pOrigArg;
                        }
                    else
                        pOrigArg = (uchar *)pOrigArg;

                    (*pfnUnmarshallRoutines[ ROUTINE_INDEX( FcType )])(
                        pStubMsg,
                        (uchar * *)pOrigArg,
                        pTypeFormat,
                        FALSE );
                    }
                    break;
                }

            GET_NEXT_ARG( pArg, ArgList );
            }   // for

            // Next decoding (if any) starts at aligned to 8.

            ALIGN( pStubMsg->Buffer, 7 );

        }   // if decode

    NdrFullPointerXlatFree( pStubMsg->FullPtrXlatTables );
}


CLIENT_CALL_RETURN RPC_VAR_ENTRY
NdrMesProcEncodeDecode2(
    handle_t                Handle,
    const MIDL_STUB_DESC *  pStubDescriptor,
    PFORMAT_STRING          pFormat,
    ...
    )
{
    va_list                     ArgList;
    uchar *                     StartofStack;
    PFORMAT_STRING              pFormatParam;
    CLIENT_CALL_RETURN          ReturnValue;
    ulong                       ProcNum;
    uchar *                     pArg;
    void *                      pThis;
    PFORMAT_STRING              pProcFormat = pFormat;
    unsigned char *             BufferSaved;
    size_t                      WriteLength;
    NDR_PROC_CONTEXT            ProcContext;
    PNDR_PROC_HEADER_EXTS       pHeaderExts = 0;

    ReturnValue.Pointer = 0;

    //
    // Get address of argument to this function following pFormat. This
    // is the address of the address of the first argument of the function
    // calling this function.
    //
    INIT_ARG( ArgList, pFormat);

    //
    // Get the address of the stack where the parameters are.
    //
    GET_FIRST_IN_ARG(ArgList);
    StartofStack = (uchar *) GET_STACK_START(ArgList);

    // StartofStack points to the virtual stack at this point.

    NdrpValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle );

    PMIDL_ES_MESSAGE    pMesMsg  = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE  pStubMsg = & pMesMsg->StubMsg;

    NDR_ASSERT( *pFormat == FC_BIND_PRIMITIVE  ||  *pFormat == 0,
                "Pickling handle expected" );

    pStubMsg->StubDesc = pStubDescriptor;
    pStubMsg->pfnAllocate = pStubDescriptor->pfnAllocate;
    pStubMsg->pfnFree     = pStubDescriptor->pfnFree;

    ProcNum = MulNdrpInitializeContextFromProc( XFER_SYNTAX_DCE, pFormat, &ProcContext, StartofStack );

    BOOL fEncodeUsed = ( * ( ( uchar *)&ProcContext.NdrInfo.InterpreterFlags ) & ENCODE_IS_USED )  &&
                       pMesMsg->Operation == MES_ENCODE;
    BOOL fDecodeUsed = ( * ( ( uchar *)&ProcContext.NdrInfo.InterpreterFlags ) & DECODE_IS_USED )  &&
                       pMesMsg->Operation == MES_DECODE;

    NDR_ASSERT( !( fEncodeUsed && fDecodeUsed ),
                "Both encode & decode at the same time" );

    if ( !fEncodeUsed && !fDecodeUsed )
        RpcRaiseException( RPC_X_INVALID_ES_ACTION );

    if ( fEncodeUsed )
    pMesMsg->ProcNumber = ProcNum;


   // Must do this before the sizing pass!
   pStubMsg->StackTop = StartofStack;
   pStubMsg->pContext = &ProcContext;

   RpcTryFinally
        {

        // We don't really need to zeroout here, but code is much more cleaner this way, 
        // and ObjectProc is the first check anyhow.
        NdrpClientInit( pStubMsg, &ReturnValue );
        if (fEncodeUsed)
            {

            //
            // ----------------------------------------------------------------
            // Sizing Pass.
            // ----------------------------------------------------------------
            //

            pStubMsg->BufferLength += MES_PROC_HEADER_SIZE;

            //
            // Skip buffer size pass if possible.
            //
            if ( ProcContext.NdrInfo.pProcDesc->Oi2Flags.ClientMustSize )
                {
                NdrpSizing( pStubMsg, 
                            TRUE );     // IsClient
                }

            LENGTH_ALIGN( pStubMsg->BufferLength, 7 );

            size_t  LengthSaved;

            NdrpAllocPicklingBuffer( pMesMsg, pStubMsg->BufferLength );
            BufferSaved = pStubMsg->Buffer;
            LengthSaved = pStubMsg->BufferLength;

            NdrpProcHeaderMarshall( pMesMsg );

            //
            // ----------------------------------------------------------
            // Marshall Pass.
            // ----------------------------------------------------------
            //

            NdrpClientMarshal( pStubMsg,
                               FALSE ); // IsObject
                           

            // Next encoding (if any) starts at aligned to 8.

            ALIGN( pStubMsg->Buffer, 7 );

            // Now manage the actual size of encoded data.

            WriteLength = (size_t)(pStubMsg->Buffer - BufferSaved);
            * (unsigned long *) ( BufferSaved + MES_PROC_HEADER_SIZE - 4) =
                                    WriteLength - MES_PROC_HEADER_SIZE;

            if ( LengthSaved < WriteLength )
                {
                NDR_ASSERT( 0, "NdrMesProcEncodeDecode: encode buffer overflow" );
                RpcRaiseException( RPC_S_INTERNAL_ERROR );
                }

            NdrpWritePicklingBuffer( pMesMsg, BufferSaved, WriteLength );
            }


        if (fDecodeUsed)
            {
            //
            // ----------------------------------------------------------
            // Unmarshall Pass.
            // ----------------------------------------------------------
            //

            if ( GET_MES_HEADER_PEEKED( pMesMsg ) )
                {
                // This makes it possible to encode/decode several procs one after
                // another with the same pickling handle (using the same buffer).
    
                CLEAR_MES_HEADER_PEEKED( pMesMsg );
                }
            else    
                NdrpProcHeaderUnmarshall( pMesMsg );
       
            NdrpDataBufferInit( pMesMsg, pFormat );

            NdrpClientUnMarshal( pStubMsg,
                             &ReturnValue );

            // Next decoding (if any) starts at aligned to 8.

            ALIGN( pStubMsg->Buffer, 7 );

            } // if decode

        }
    RpcFinally
        {

        NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);

        NdrCorrelationFree( pStubMsg );
        }
   RpcEndFinally

    return ReturnValue;
}


// =======================================================================
//
//   Generic type pickling routines (for non-simple types).
//
// =======================================================================

void
NdrpCommonTypeHeaderSize(
    PMIDL_ES_MESSAGE    pMesMsg
    )
{
    // This check is to prevent a decoding handle from being used
    // for both encoding and sizing of types.

    if ( pMesMsg->Operation != MES_ENCODE )
        RpcRaiseException( RPC_X_INVALID_ES_ACTION );

    if ( ! GET_COMMON_TYPE_HEADER_SIZED( pMesMsg ) )
        {
        pMesMsg->StubMsg.BufferLength += MES_CTYPE_HEADER_SIZE;

        SET_COMMON_TYPE_HEADER_SIZED( pMesMsg );
        }
}


size_t  RPC_ENTRY
NdrMesTypeAlignSize2(
    handle_t                        Handle,
    const MIDL_TYPE_PICKLING_INFO * pxPicklingInfo, 
    const MIDL_STUB_DESC *          pStubDesc,
    PFORMAT_STRING                  pFormat,
    const void *                    pObject
    )
{
    PMIDL_ES_MESSAGE            pMesMsg = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE          pStubMsg = &pMesMsg->StubMsg;
    PMIDL_TYPE_PICKLING_INFOp   pPicklingInfo;

    pPicklingInfo = (PMIDL_TYPE_PICKLING_INFOp) pxPicklingInfo;

    NDR_ASSERT( pPicklingInfo->Flags.Oicf, "Oicf should always be on" )
        
    pStubMsg->fHasExtensions  = 1;

    if ( pPicklingInfo->Flags.HasNewCorrDesc )
        {
        void * pCorrInfo = alloca( NDR_DEFAULT_CORR_CACHE_SIZE );

        NdrCorrelationInitialize( pStubMsg,
                        (unsigned long *) pCorrInfo,
                        NDR_DEFAULT_CORR_CACHE_SIZE,
                        0 /* flags */ );
        }

    return NdrMesTypeAlignSize(Handle, pStubDesc, pFormat, pObject);
}

size_t  RPC_ENTRY
NdrMesTypeAlignSize(
    handle_t                Handle,
    const MIDL_STUB_DESC *  pStubDesc,
    PFORMAT_STRING          pFormat,
    const void *            pObject
    )
/*++

Routine description:

    Calculates the buffer size of the object relative to the current state
    of the pickling handle.

Arguments:

    Handle      - a pickling handle,
    pStubDesc   - a pointer to the stub descriptor,
    pFormat     - a pointer to the format code describing the object type
    pObject     - a pointer to the object being sized.

Returns:

    The size.

Note:

    The pickling header is included in the sizing.

--*/
{
    NdrpValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle );

    PMIDL_STUB_MESSAGE  pStubMsg = &((PMIDL_ES_MESSAGE)Handle)->StubMsg;
    size_t             OldLength = pStubMsg->BufferLength;

    if ( ! pObject )
        RpcRaiseException( RPC_X_NULL_REF_POINTER );

    if( (long)pStubMsg->BufferLength & 0x7 )
        RpcRaiseException( RPC_X_INVALID_BUFFER );

    pStubMsg->StubDesc = pStubDesc;
    pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
    pStubMsg->pfnFree     = pStubDesc->pfnFree;

    // See if we need to size the common type header.

    NdrpCommonTypeHeaderSize( (PMIDL_ES_MESSAGE)Handle );

    // Now the individual type object.

    pStubMsg->BufferLength += MES_HEADER_SIZE;

    if ( IS_POINTER_TYPE(*pFormat) )
        {
        // We have to dereference the pointer once.
        pObject = *(void * *)pObject;
        }

    (*pfnSizeRoutines[ ROUTINE_INDEX(*pFormat) ])
                                        ( pStubMsg,
                                        (uchar *)pObject,
                                        pFormat );

   LENGTH_ALIGN( pStubMsg->BufferLength, 7 );

   return( pStubMsg->BufferLength - OldLength );
}



size_t
NdrpCommonTypeHeaderMarshall(
    PMIDL_ES_MESSAGE    pMesMsg
    )
/*++
    Returns the space used by the common header.
--*/
{
    if ( ! GET_COMMON_TYPE_HEADER_IN( pMesMsg ) )
        {
        PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;

        MIDL_memset( pStubMsg->Buffer, 0xcc, MES_CTYPE_HEADER_SIZE );

        *pStubMsg->Buffer++ = MIDL_ES_VERSION;
        *pStubMsg->Buffer++ = NDR_LOCAL_ENDIAN;
        * PSHORT_CAST pStubMsg->Buffer = MES_CTYPE_HEADER_SIZE;

        pStubMsg->Buffer += MES_CTYPE_HEADER_SIZE - 2;

        SET_COMMON_TYPE_HEADER_IN( pMesMsg );
        return( MES_CTYPE_HEADER_SIZE );
        }

    return( 0 );
}


void  RPC_ENTRY
NdrMesTypeEncode2(
    handle_t                        Handle,
    const MIDL_TYPE_PICKLING_INFO * pxPicklingInfo,
    const MIDL_STUB_DESC *          pStubDesc,
    PFORMAT_STRING                  pFormat,
    const void *                    pObject
    )
{
    PMIDL_ES_MESSAGE            pMesMsg = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE          pStubMsg = &pMesMsg->StubMsg;
    PMIDL_TYPE_PICKLING_INFOp   pPicklingInfo;

    pPicklingInfo = (PMIDL_TYPE_PICKLING_INFOp) pxPicklingInfo;

    NDR_ASSERT( pPicklingInfo->Flags.Oicf, "Oicf should always be on" )

    pStubMsg->fHasExtensions  = 1;

    if ( pPicklingInfo->Flags.HasNewCorrDesc )
        {
        void * pCorrInfo = alloca( NDR_DEFAULT_CORR_CACHE_SIZE );

        NdrCorrelationInitialize( pStubMsg,
                        (unsigned long *) pCorrInfo,
                        NDR_DEFAULT_CORR_CACHE_SIZE,
                        0 /* flags */ );
        }
    RpcTryFinally
        {
        NdrMesTypeEncode(Handle, pStubDesc, pFormat, pObject);
        if ( pStubMsg->pCorrInfo )
            NdrCorrelationPass( pStubMsg );        
        }
    RpcFinally
        {
        // while currently we are not using corrinfo in marshalling pass, we need this 
        // in case we are using corrinfo later (like info for free)
        NdrCorrelationFree( pStubMsg );        
        }
    RpcEndFinally
        
}

void  RPC_ENTRY
NdrMesTypeEncode(
    handle_t                Handle,
    const MIDL_STUB_DESC *  pStubDesc,
    PFORMAT_STRING          pFormat,
    const void *            pObject
    )
/*++

Routine description:

    Encodes the object to the buffer depending on the state of the handle.
    This means: sizing, allocating buffer, marshalling, writing buffer.

Arguments:

    Handle      - a pickling handle
    pStubDesc   - a pointer to the stub descriptor,
    pFormat     - a pointer to the format code describing the object type,
    pObject     - a pointer to the object being sized.

Returns:

    The size.

Note:

    The pickling header is included in the sizing.

--*/
{
    NdrpValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle );

    uchar *             pBufferSaved;
    size_t              RequiredLen, CommonHeaderSize, LengthSaved;

    PMIDL_ES_MESSAGE    pMesMsg = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;

    if ( ! pObject )
        RpcRaiseException( RPC_X_NULL_REF_POINTER );

    if( (LONG_PTR)pStubMsg->Buffer & 0x7 )
        RpcRaiseException( RPC_X_INVALID_BUFFER );

    pStubMsg->StubDesc = pStubDesc;
    pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
    pStubMsg->pfnFree     = pStubDesc->pfnFree;

    // Size and allocate the buffer.
    // The req len includes: (the common header), the header and the data

    // Take the pointer alignment to come up with the right size.

    pStubMsg->BufferLength = 0xf & PtrToUlong( pStubMsg->Buffer );

    RequiredLen = NdrMesTypeAlignSize( Handle,
                                       pStubDesc,
                                       pFormat,
                                       pObject );

    NdrpAllocPicklingBuffer( pMesMsg, RequiredLen );

    pBufferSaved = pStubMsg->Buffer;
    LengthSaved  = RequiredLen;

    // See if we need to marshall the common type header

    CommonHeaderSize = NdrpCommonTypeHeaderMarshall( pMesMsg );

    // Marshall the header and the object.

    // zero out the type header (will contain type buffer length after
    // encoding is done )
    memset( pStubMsg->Buffer, 0, MES_HEADER_SIZE );
    pStubMsg->Buffer += MES_HEADER_SIZE;

    if ( IS_POINTER_TYPE(*pFormat) )
        {
        // We have to dereference the pointer once.
        pObject = *(void * *)pObject;
        }

    (*pfnMarshallRoutines[ ROUTINE_INDEX(*pFormat) ])
                                      ( pStubMsg,
                                        (uchar *)pObject,
                                        pFormat );

    // We adjust the buffer to the next align by 8 and
    // so, we tell the user that we've written out till next mod 8.

    ALIGN( pStubMsg->Buffer, 7 );
    size_t WriteLength = (size_t)(pStubMsg->Buffer - pBufferSaved);

    // We always save the rounded up object length in the type header.

    *(unsigned long *)(pBufferSaved + CommonHeaderSize) =
                     WriteLength - CommonHeaderSize - MES_HEADER_SIZE;

    if ( LengthSaved < WriteLength )
        {
        NDR_ASSERT( 0, "NdrMesTypeEncode: encode buffer overflow" );
        RpcRaiseException( RPC_S_INTERNAL_ERROR );
        }

    NdrpWritePicklingBuffer( pMesMsg, pBufferSaved, WriteLength );
}



void
NdrpCommonTypeHeaderUnmarshall(
    PMIDL_ES_MESSAGE    pMesMsg
    )
{
    if ( pMesMsg->Operation != MES_DECODE )
        RpcRaiseException( RPC_X_INVALID_ES_ACTION );

    if ( ! GET_COMMON_TYPE_HEADER_IN( pMesMsg ) )
        {
        PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;

        NdrpReadPicklingBuffer( pMesMsg, MES_CTYPE_HEADER_SIZE );

        // Check the version number, endianness.

        if ( *pStubMsg->Buffer != MIDL_ES_VERSION )
            RpcRaiseException( RPC_X_WRONG_ES_VERSION );

        if ( pStubMsg->Buffer[1] == NDR_LOCAL_ENDIAN )
            {
            // Read the note about endianess at NdrMesTypeDecode.
            //
            pMesMsg->AlienDataRep = NDR_LOCAL_DATA_REPRESENTATION;
            }
        else
            {
            unsigned char temp = pStubMsg->Buffer[2];
            pStubMsg->Buffer[2] = pStubMsg->Buffer[3];
            pStubMsg->Buffer[3] = temp;

            pMesMsg->AlienDataRep = ( NDR_ASCII_CHAR       |     // chars
                                      pStubMsg->Buffer[1]  |     // endianness
                                      NDR_IEEE_FLOAT );          // float
            }

        pStubMsg->Buffer += MES_CTYPE_HEADER_SIZE;

        SET_COMMON_TYPE_HEADER_IN( pMesMsg );
        }

}

void  RPC_ENTRY
NdrMesTypeDecode2(
    handle_t                        Handle,
    const MIDL_TYPE_PICKLING_INFO * pxPicklingInfo,
    const MIDL_STUB_DESC          * pStubDesc,
    PFORMAT_STRING                  pFormat,
    void                          * pObject
    )
{
    PMIDL_ES_MESSAGE            pMesMsg = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE          pStubMsg = &pMesMsg->StubMsg;
    PMIDL_TYPE_PICKLING_INFOp   pPicklingInfo;

    pPicklingInfo = (PMIDL_TYPE_PICKLING_INFOp) pxPicklingInfo;

    NDR_ASSERT( pPicklingInfo->Flags.Oicf, "Oicf should always be on" )

    pStubMsg->fHasExtensions  = 1;
    RpcTryFinally
        {

    if ( pPicklingInfo->Flags.HasNewCorrDesc )
        {
        void * pCorrInfo = alloca( NDR_DEFAULT_CORR_CACHE_SIZE );

        NdrCorrelationInitialize( pStubMsg,
                        (unsigned long *) pCorrInfo,
                        NDR_DEFAULT_CORR_CACHE_SIZE,
                        0 /* flags */ );
        }

        NdrMesTypeDecode(Handle, pStubDesc, pFormat, pObject);
        if ( pStubMsg->pCorrInfo )
            NdrCorrelationPass( pStubMsg );
        }
    RpcFinally
        {
        NdrCorrelationFree( pStubMsg );
        }
    RpcEndFinally
}

void  RPC_ENTRY
NdrMesTypeDecode(
    handle_t                Handle,
    const MIDL_STUB_DESC *  pStubDesc,
    PFORMAT_STRING          pFormat,
    void                 *  pObject
    )
/*++

Routine description:

    Decodes the object to the buffer depending on the state of the handle.
    This means: reads the header, reads the buffer, unmarshalls.

Arguments:

    Handle      - a pickling handle
    pStubDesc   - a pointer to the stub descriptor,
    pFormat     - a pointer to the format code describing the object type,
    pObject     - a pointer to the object being sized.

Returns:

    The size.

Note:

    Endianness and other conversions when decoding *types*.
    Starting with Mac implementation, types have a conversion that
    takes care of different endianness. ASCII and VAX_FLOAT are still
    assummed for types.
    Common header conveys the endianness information. The handle gets the
    endian info from the common header and so when decoding types, the
    handle is used to check if the conversion is needed.

    We cannot convert the whole buffer at the time of processing the common
    header as the buffer may not be there yet (for incremental handle).

--*/
{
    NdrpValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle );

    size_t              RequiredLen;

    PMIDL_ES_MESSAGE    pMesMsg = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;
    uchar *             BufferSaved;

    if ( ! pObject )
        RpcRaiseException( RPC_X_NULL_REF_POINTER );

    pStubMsg->StubDesc = pStubDesc;
    pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
    pStubMsg->pfnFree     = pStubDesc->pfnFree;

    // See if we need to unmarshall the common type header.

    NdrpCommonTypeHeaderUnmarshall( pMesMsg );

    // Now the individual data object.

    NdrpReadPicklingBuffer( pMesMsg, MES_HEADER_SIZE );

    // Reading the object. Get the length of the buffer first.

    if ( pMesMsg->AlienDataRep != NDR_LOCAL_DATA_REPRESENTATION )
        {
        pStubMsg->RpcMsg->DataRepresentation = pMesMsg->AlienDataRep;

        BufferSaved = pStubMsg->Buffer;
        NdrSimpleTypeConvert( pStubMsg, FC_LONG );
        pStubMsg->Buffer = BufferSaved;
        }

    RequiredLen = (size_t) *(unsigned long *)pStubMsg->Buffer;
    pStubMsg->Buffer += MES_HEADER_SIZE;

    NdrpReadPicklingBuffer( pMesMsg, RequiredLen );

    // Now the conversion of the object, if needed.

    if ( pMesMsg->AlienDataRep != NDR_LOCAL_DATA_REPRESENTATION )
        {
        BufferSaved = pStubMsg->Buffer;
        (*pfnConvertRoutines[ ROUTINE_INDEX( *pFormat) ])
            ( pStubMsg,
              pFormat,
              FALSE );
        pStubMsg->Buffer = BufferSaved;
        }

    // Unmarshalling.

    pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
    pStubMsg->pfnFree     = pStubDesc->pfnFree;

    void * pArg = pObject;

    if ( IS_POINTER_TYPE(*pFormat) )
        {
        // We have to dereference the pointer once.
        //
        pArg = *(void **)pArg;
        }

    (*pfnUnmarshallRoutines[ ROUTINE_INDEX( *pFormat )])
                            ( pStubMsg,
                              (uchar * *)&pArg,
                              pFormat,
                              FALSE );

    if ( IS_POINTER_TYPE(*pFormat) )
        {
        // Don't drop the pointee, if it was allocated.

        *(void **)pObject = pArg;
        }

    // Next decoding needs to start at aligned to 8.

    ALIGN( pStubMsg->Buffer, 7 );
}




void  RPC_ENTRY
NdrMesTypeFree(
    handle_t                Handle,
    const MIDL_STUB_DESC *  pStubDesc,
    PFORMAT_STRING          pFormat,
    void                 *  pObject
    )
/*++

Routine description:

    Free the object.

Arguments:

    Handle      - a pickling handle,
    pStubDesc   - a pointer to the stub descriptor,
    pFormat     - a pointer to the format code describing the object type
    pObject     - a pointer to the object being freed.

Returns:

Note:

    The pickling header is included in the sizing.

--*/
{
    NdrpValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle );

    PMIDL_STUB_MESSAGE  pStubMsg = &((PMIDL_ES_MESSAGE)Handle)->StubMsg;

    if ( ! pObject )
        RpcRaiseException( RPC_X_NULL_REF_POINTER );

    if( (LONG_PTR)pStubMsg->Buffer & 0x7 )
        RpcRaiseException( RPC_X_INVALID_BUFFER );

    pStubMsg->StubDesc = pStubDesc;
    pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
    pStubMsg->pfnFree     = pStubDesc->pfnFree;

    // Now the individual type object.

    if ( IS_POINTER_TYPE(*pFormat) )
        {
        // We have to dereference the pointer once.
        pObject = *(void * *)pObject;
        }

    (*pfnFreeRoutines[ ROUTINE_INDEX(*pFormat) ])
                                        ( pStubMsg,
                                        (uchar *)pObject,
                                        pFormat );
}

void  RPC_ENTRY
NdrMesTypeFree2(
    handle_t                        Handle,
    const MIDL_TYPE_PICKLING_INFO * pxPicklingInfo,
    const MIDL_STUB_DESC          * pStubDesc,
    PFORMAT_STRING                  pFormat,
    void                          * pObject
    )
{
    PMIDL_ES_MESSAGE            pMesMsg = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE          pStubMsg = &pMesMsg->StubMsg;
    PMIDL_TYPE_PICKLING_INFOp   pPicklingInfo;

    pPicklingInfo = (PMIDL_TYPE_PICKLING_INFOp) pxPicklingInfo;

    NDR_ASSERT( pPicklingInfo->Flags.Oicf, "Oicf should always be on" )

    pStubMsg->fHasExtensions  = 1;

    if ( pPicklingInfo->Flags.HasNewCorrDesc )
        {
        void * pCorrInfo = alloca( NDR_DEFAULT_CORR_CACHE_SIZE );

        NdrCorrelationInitialize( pStubMsg,
                        (unsigned long *) pCorrInfo,
                        NDR_DEFAULT_CORR_CACHE_SIZE,
                        0 /* flags */ );
        }

    NdrMesTypeFree(Handle, pStubDesc, pFormat, pObject);
}


// =======================================================================
//
//   Ready to use AlignSize routines for simple types
//
// =======================================================================

size_t  RPC_ENTRY
NdrMesSimpleTypeAlignSize(
    handle_t Handle )
/*++
    Size is always 8 bytes for data and there is no header here per data.
    However, the common header gets included for the first object.
--*/
{
    NdrpValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle );

    PMIDL_STUB_MESSAGE  pStubMsg = &((PMIDL_ES_MESSAGE) Handle)->StubMsg;

    if( (long)( pStubMsg->BufferLength & 0x7 ) )
        RpcRaiseException( RPC_X_INVALID_BUFFER );

    unsigned long OldLength = pStubMsg->BufferLength;

    NdrpCommonTypeHeaderSize( (PMIDL_ES_MESSAGE)Handle );
    pStubMsg->BufferLength += 8;

    return( (size_t)(pStubMsg->BufferLength - OldLength) );
}


// =======================================================================
//
//   Ready to use Encode routines for simple types
//
// =======================================================================

void  RPC_ENTRY
NdrMesSimpleTypeEncode(
    handle_t                Handle,
    const MIDL_STUB_DESC *  pStubDesc,
    const void           *  pData,
    short                   Size )
/*++
    Marshall a simple type entity. There is no header here per data.
    However, the common header gets included for the first object.
--*/
{
    NdrpValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle );

    PMIDL_ES_MESSAGE    pMesMsg = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;
    pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
    pStubMsg->pfnFree     = pStubDesc->pfnFree;
    size_t RequiredLen;

    // Size and allocate the buffer.
    // The req len includes: (the common header) and the data

    // Take the pointer alignment to come up with the right size.

    pStubMsg->BufferLength = 0xf & PtrToUlong( pStubMsg->Buffer );

    RequiredLen = NdrMesSimpleTypeAlignSize( Handle );
    NdrpAllocPicklingBuffer( pMesMsg, RequiredLen );

    // See if we need to marshall the common type header

    uchar *   pBufferSaved = pStubMsg->Buffer;

    NdrpCommonTypeHeaderMarshall( pMesMsg );

    switch ( Size )
        {
        case 1:
            * PCHAR_CAST pStubMsg->Buffer  = * PCHAR_CAST pData;
            break;

        case 2:
            * PSHORT_CAST pStubMsg->Buffer = * PSHORT_CAST pData;
            break;

        case 4:
            * PLONG_CAST pStubMsg->Buffer  = * PLONG_CAST pData;
            break;

        case 8:
            * PHYPER_CAST pStubMsg->Buffer = * PHYPER_CAST pData;
            break;

        default:
            NDR_ASSERT( 0, " Size generation problem" );
        }
    pStubMsg->Buffer += 8;

    NdrpWritePicklingBuffer( pMesMsg, pBufferSaved, RequiredLen );
}



// =======================================================================
//
//   Ready to use Decode routines for simple types
//
// =======================================================================

void  RPC_ENTRY
NdrMesSimpleTypeDecode(
    handle_t Handle,
    void  *  pData,
    short    FormatChar )
/*++
    Does not include the header for the data.
    However, the common header gets included for the first object.

    Note. Endianness and other conversions for decode.
    This has been deemed as not worthy doing in the Daytona time frame.
    However, to be able to add it in future without backward compatibility
    problems, we have the last argument to be the format character as
    opposed to the size.
    This makes it possible to call NdrSimpleTypeConvert, if needed.
--*/
{
    NdrpValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle );

    PMIDL_ES_MESSAGE    pMesMsg = (PMIDL_ES_MESSAGE) Handle;
    PMIDL_STUB_MESSAGE  pStubMsg = &((PMIDL_ES_MESSAGE)Handle)->StubMsg;
    uchar *             BufferSaved;

    // See if we need to unmarshall the common type header.

    NdrpCommonTypeHeaderUnmarshall( (PMIDL_ES_MESSAGE) Handle );

    // Now the data.

    NdrpReadPicklingBuffer( (PMIDL_ES_MESSAGE) Handle, 8);

    if ( pMesMsg->AlienDataRep != NDR_LOCAL_DATA_REPRESENTATION )
        {
        pStubMsg->RpcMsg->DataRepresentation = pMesMsg->AlienDataRep;

        BufferSaved = pStubMsg->Buffer;
        NdrSimpleTypeConvert( pStubMsg, (unsigned char)FormatChar );
        pStubMsg->Buffer = BufferSaved;
        }

    switch ( FormatChar )
        {
        case FC_BYTE:
        case FC_CHAR:
        case FC_SMALL:
        case FC_USMALL:
            * PCHAR_CAST  pData = * PCHAR_CAST pStubMsg->Buffer;
            break;

        case FC_WCHAR:
        case FC_SHORT:
        case FC_USHORT:
        case FC_ENUM16:
            * PSHORT_CAST pData = * PSHORT_CAST pStubMsg->Buffer;
            break;

        case FC_LONG:
        case FC_ULONG:
        case FC_FLOAT:
        case FC_ENUM32:
        case FC_ERROR_STATUS_T:
            * PLONG_CAST  pData = * PLONG_CAST pStubMsg->Buffer;
            break;

        case FC_HYPER:
        case FC_DOUBLE:
            * PHYPER_CAST pData = * PHYPER_CAST pStubMsg->Buffer;
            break;

#if defined(__RPC_WIN64__)
        case FC_INT3264:
            *((INT64 *)pData)  = *((long *) pStubMsg->Buffer);
            break;

        case FC_UINT3264:
            *((UINT64 *)pData) = *((ulong *)pStubMsg->Buffer);
            break;
#endif

        default:
            NDR_ASSERT( 0, " Size generation problem for simple types" );
        }

    pStubMsg->Buffer += 8;
}

void
NdrpProcHeaderMarshallAll(
    PMIDL_ES_MESSAGE    pMesMsg
    )
{
    PMIDL_STUB_MESSAGE  pStubMsg = &pMesMsg->StubMsg;

    // Marshall DCE pickle header.

    if( (LONG_PTR)pStubMsg->Buffer & 0x7 )
        RpcRaiseException( RPC_X_INVALID_BUFFER );

    if ( pMesMsg->Operation == MES_ENCODE )
        * pStubMsg->Buffer++ = MIDL_ES_VERSION;
    else
        * pStubMsg->Buffer++ = MIDL_NDR64_ES_VERSION;
        
    * pStubMsg->Buffer++ = NDR_LOCAL_ENDIAN_LOW;
    *( PSHORT_LV_CAST pStubMsg->Buffer)++ = (short)0xcccc;    // filler

    // Marshall transfer syntax from the stub.

    RpcpMemoryCopy( pStubMsg->Buffer,
                    &( ( PMIDL_ES_MESSAGE_EX)pMesMsg )->TransferSyntax,
                    sizeof(RPC_SYNTAX_IDENTIFIER) );

    // We need to remember InterfaceId for inquiries.

    RpcpMemoryCopy( & pMesMsg->InterfaceId,
                    & ((PRPC_CLIENT_INTERFACE)(pStubMsg->
                         StubDesc->RpcInterfaceInformation))->InterfaceId,
                    sizeof(RPC_SYNTAX_IDENTIFIER) );

   // Marshall InterfaceId and ProcNumber from the handle.

    RpcpMemoryCopy( pStubMsg->Buffer + sizeof(RPC_SYNTAX_IDENTIFIER),
                    & pMesMsg->InterfaceId,
                    sizeof(RPC_SYNTAX_IDENTIFIER) + sizeof(long) );

    SET_MES_INFO_AVAILABLE( pMesMsg );

    pStubMsg->Buffer += 2 * sizeof(RPC_SYNTAX_IDENTIFIER) + sizeof(long);

    * pStubMsg->Buffer++ = NDR_LOCAL_ENDIAN_LOW;
    * pStubMsg->Buffer++ = NDR_ASCII_CHAR;
    * pStubMsg->Buffer++ = (char) (NDR_IEEE_FLOAT >> 8);
    * pStubMsg->Buffer++ = 0;   // filler

    // This is non-DCE element as they have just 4 more bytes of filler here.
    // This field is used only when unmarshalling in our incremental style.

    *( PLONG_LV_CAST pStubMsg->Buffer)++ = pStubMsg->BufferLength -
                                                   MES_PROC_HEADER_SIZE;
}

void
NdrpProcHeaderUnmarshallAll(
    PMIDL_ES_MESSAGE    pMesMsg
    )
{
    unsigned char *         BufferToRestore;
    PMIDL_STUB_MESSAGE      pStubMsg = &pMesMsg->StubMsg;

    if ( GET_MES_HEADER_PEEKED( pMesMsg ) )
        return;

    NdrpReadPicklingBuffer( pMesMsg, MES_PROC_HEADER_SIZE );

    // Unmarshalling the header

    if ( *pStubMsg->Buffer != MIDL_ES_VERSION && 
         *pStubMsg->Buffer != MIDL_NDR64_ES_VERSION)
        RpcRaiseException( RPC_X_WRONG_ES_VERSION );

    BufferToRestore = pStubMsg->Buffer + 4;

    if ( pStubMsg->Buffer[1] != NDR_LOCAL_ENDIAN_LOW )
        {
        // The DCE header has the endianness on the low nibble, while
        // our DataRep has it on the high nibble.
        // We need only endianess to convert the proc header.

        byte Endianness = (pStubMsg->Buffer[1] << 4 );

        pStubMsg->RpcMsg->DataRepresentation = Endianness;

        pStubMsg->Buffer += 4;
        NdrSimpleStructConvert( pStubMsg,
                                &__MIDLFormatString.Format[32],
                                FALSE );
        }

    pStubMsg->Buffer = BufferToRestore;

    // Verify the transfer syntax

    RpcpMemoryCopy( &((PMIDL_ES_MESSAGE_EX)pMesMsg)->TransferSyntax, 
                      pStubMsg->Buffer,
                      sizeof( RPC_SYNTAX_IDENTIFIER ) );

    pStubMsg->Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);

    // We need to remember the last InterfaceId and ProcNumber for inquiries.

    RpcpMemoryCopy( & pMesMsg->InterfaceId,
                    pStubMsg->Buffer,
                    sizeof(RPC_SYNTAX_IDENTIFIER)  );
  
    pStubMsg->Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);

    pMesMsg->ProcNumber = *(ulong *)pStubMsg->Buffer;

    pStubMsg->Buffer += 4;

    SET_MES_INFO_AVAILABLE( pMesMsg );

    unsigned long AlienDataRepresentation =
                        ( (pStubMsg->Buffer[0] << 4)  |           // endianness
                          pStubMsg->Buffer[1]  |                       // chars
                        ((unsigned long)(pStubMsg->Buffer[2]) << 8) ); // float
    pMesMsg->AlienDataRep = AlienDataRepresentation;
    pMesMsg->IncrDataSize = (size_t) *(unsigned long __RPC_FAR *)
                                                (pStubMsg->Buffer + 4);
    pStubMsg->Buffer += 8;
}

extern const MIDL_FORMAT_STRING __MIDLFormatString =
    {
        0,
        {
            
            0x1d,       /* FC_SMFARRAY */
            0x0,        /* 0 */
/*  2 */    0x6, 0x0,   /* 6 */
/*  4 */    0x1,        /* FC_BYTE */
            0x5b,       /* FC_END */
/*  6 */    
            0x15,       /* FC_STRUCT */
            0x3,        /* 3 */
/*  8 */    0x10, 0x0,  /* 16 */
/* 10 */    0x8,        /* FC_LONG */
            0x6,        /* FC_SHORT */
/* 12 */    0x6,        /* FC_SHORT */
            0x3,        /* FC_SMALL */
/* 14 */    0x3,        /* FC_SMALL */
            0x4c,       /* FC_EMBEDDED_COMPLEX */
/* 16 */    0x0,        /* 0 */
            0xef, 0xff, /* Offset= -17 (0) */
            0x5b,       /* FC_END */
/* 20 */    
            0x15,       /* FC_STRUCT */
            0x3,        /* 3 */
/* 22 */    0x14, 0x0,  /* 20 */
/* 24 */    0x4c,       /* FC_EMBEDDED_COMPLEX */
            0x0,        /* 0 */
/* 26 */    0xec, 0xff, /* Offset= -20 (6) */
/* 28 */    0x6,        /* FC_SHORT */
            0x6,        /* FC_SHORT */
/* 30 */    0x5c,       /* FC_PAD */
            0x5b,       /* FC_END */
/* 32 */    
            0x15,       /* FC_STRUCT */
            0x3,        /* 3 */
/* 34 */    0x34, 0x0,  /* 52 */
/* 36 */    0x4c,       /* FC_EMBEDDED_COMPLEX */
            0x0,        /* 0 */
/* 38 */    0xee, 0xff, /* Offset= -18 (20) */
/* 40 */    0x4c,       /* FC_EMBEDDED_COMPLEX */
            0x0,        /* 0 */
/* 42 */    0xea, 0xff, /* Offset= -22 (20) */
/* 44 */    0x8,        /* FC_LONG */
            0x1,        /* FC_BYTE */
/* 46 */    0x1,        /* FC_BYTE */
            0x1,        /* FC_BYTE */
/* 48 */    0x1,        /* FC_BYTE */
            0x38,       /* FC_ALIGNM4 */
/* 50 */    0x8,        /* FC_LONG */
            0x5b,       /* FC_END */

            0x0
        }
    };