#include "precomp.hxx"
#include "..\..\ndr20\ndrole.h"

void
Ndr64UDTSimpleTypeMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT      pFormat )

{
    ALIGN(pStubMsg->Buffer, NDR64_SIMPLE_TYPE_MEMALIGN(*(PFORMAT_STRING)pFormat));

    pStubMsg->Buffer += NDR64_SIMPLE_TYPE_BUFSIZE(*(PFORMAT_STRING)pFormat);

    LENGTH_ALIGN( pStubMsg->MemorySize,
                  NDR64_SIMPLE_TYPE_MEMALIGN(*(PFORMAT_STRING)pFormat) );

    pStubMsg->MemorySize += NDR64_SIMPLE_TYPE_MEMSIZE(*(PFORMAT_STRING)pFormat);
}

void
Ndr64pRangeMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{
   const NDR64_RANGE_FORMAT * pRangeFormat =
        (const NDR64_RANGE_FORMAT*)pFormat;

   Ndr64UDTSimpleTypeMemorySize( pStubMsg,
                                 (PFORMAT_STRING)&pRangeFormat->RangeType );
}

void
Ndr64pInterfacePointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{

    ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

    CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, (sizeof(NDR64_WIRE_COUNT_TYPE)+sizeof(ulong)) );
    NDR64_UINT32 MaxCount = Ndr64pConvertTo2GB( *(NDR64_WIRE_COUNT_TYPE *) pStubMsg->Buffer );
    pStubMsg->Buffer      += sizeof(NDR64_WIRE_COUNT_TYPE);
    ulong ulCntData       = *(ulong *) pStubMsg->Buffer;
    pStubMsg->Buffer      += sizeof(ulong);

    if ( MaxCount != ulCntData )
        {
        RpcRaiseException( RPC_X_BAD_STUB_DATA );
        return;
        }

    RpcTryFinally
        {

        CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, MaxCount );

        if( (MaxCount > 0) && NDR64_IS_WALKIP(pStubMsg->uFlags) )
        {

            IStream *pStream = (*NdrpCreateStreamOnMemory)(pStubMsg->Buffer, MaxCount);
            if(pStream == 0)
                RpcRaiseException(RPC_S_OUT_OF_MEMORY);

            HRESULT hr = (*pfnCoReleaseMarshalData)(pStream);
            pStream->Release();

            if(FAILED(hr))
                RpcRaiseException(hr);
        }

        }
    RpcFinally
        {

        pStubMsg->Buffer += MaxCount;

        }
    RpcEndFinally
}

__forceinline void
Ndr64pPointerMemorySizeInternal(
    PMIDL_STUB_MESSAGE  pStubMsg,
    NDR64_PTR_WIRE_TYPE *pBufferMark,
    PNDR64_FORMAT       pFormat )

{
    const NDR64_POINTER_FORMAT *pPointerFormat = (NDR64_POINTER_FORMAT*) pFormat;

    PFORMAT_STRING pPointeeFormat = (PFORMAT_STRING)pPointerFormat->Pointee;

    switch ( pPointerFormat->FormatCode )
        {
        case FC64_RP :
            break;

        case FC64_UP :
        case FC64_OP :
            if ( ! *pBufferMark )
                return;
            break;

        case FC64_IP :
            if ( ! *pBufferMark )
                return;

            Ndr64pInterfacePointerMemorySize(pStubMsg,
                                             pPointeeFormat );
            return;

        case FC64_FP :

            if ( Ndr64pFullPointerQueryRefId( pStubMsg,
                                              Ndr64pWirePtrToRefId(*pBufferMark),
                                              FULL_POINTER_MEM_SIZED,
                                              0 ) )
                return;

            break;

        default :
            NDR_ASSERT(0,"Ndr64pPointerMemorySize : bad format char");
            RpcRaiseException( RPC_S_INTERNAL_ERROR );
            return;
        }

    LENGTH_ALIGN( pStubMsg->MemorySize, PTR_MEM_ALIGN );

    if ( NDR64_SIMPLE_POINTER( pPointerFormat->Flags ) )
        {
        ALIGN(pStubMsg->Buffer, NDR64_SIMPLE_TYPE_BUFALIGN( *pPointeeFormat ));
        pStubMsg->Buffer += NDR64_SIMPLE_TYPE_BUFSIZE( *pPointeeFormat );

        LENGTH_ALIGN( pStubMsg->MemorySize,
                      NDR64_SIMPLE_TYPE_MEMALIGN( *pPointeeFormat ) );
        pStubMsg->MemorySize += NDR64_SIMPLE_TYPE_MEMSIZE( *pPointeeFormat );

        return;
        }

    if ( NDR64_POINTER_DEREF( pPointerFormat->Flags ) )
        pStubMsg->MemorySize += PTR_MEM_SIZE;

    SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags );
    NDR64_RESET_EMBEDDED_FLAGS_TO_STANDALONE(pStubMsg->uFlags);

    Ndr64TopLevelTypeMemorySize( pStubMsg,
                                 pPointeeFormat );

    return;
}

void NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT::Dispatch(PMIDL_STUB_MESSAGE pStubMsg)
{
    SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags, uFlags );

    Ndr64pPointerMemorySizeInternal( pStubMsg,
                                     pBufferMark,
                                     pFormat );

}

#if defined(DBG)
void NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT::Print()
{
    DbgPrint("NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT:\n");
    DbgPrint("pNext:                   %p\n", pNext );
    DbgPrint("pFormat:                 %p\n", pFormat );
    DbgPrint("uFlags:                  %u\n", uFlags );
    DbgPrint("pBufferMark:             %p\n", pBufferMark );
}
#endif

void
Ndr64pEnquePointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    NDR64_PTR_WIRE_TYPE *pBufferMark,
    PNDR64_FORMAT       pFormat )
{

    NDR64_POINTER_CONTEXT PointerContext( pStubMsg );

    RpcTryFinally
        {
        if ( !PointerContext.ShouldEnque() )
            {
            Ndr64pPointerMemorySizeInternal( pStubMsg,
                                             pBufferMark,
                                             pFormat );

            }
        else
            {
            NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT*pElement =
                new(PointerContext.GetActiveState())
                    NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT(pStubMsg,
                                                        (PFORMAT_STRING)pFormat,
                                                        pBufferMark );
            PointerContext.Enque( pElement );
            }
        PointerContext.DispatchIfRequired();
        }
    RpcFinally
        {
        PointerContext.EndContext();
        }
    RpcEndFinally

}

void
Ndr64pPointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    NDR64_PTR_WIRE_TYPE *pBufferMark,
    PNDR64_FORMAT       pFormat )
{
    SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags );
    NDR64_RESET_EMBEDDED_FLAGS_TO_STANDALONE(pStubMsg->uFlags);

    if ( !NdrIsLowStack(pStubMsg) )
        {
        Ndr64pPointerMemorySizeInternal(
            pStubMsg,
            pBufferMark,
            pFormat );
        return;
        }

    Ndr64pEnquePointerMemorySize(
        pStubMsg,
        pBufferMark,
        pFormat );

}

__forceinline void
Ndr64TopLevelPointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    NDR64_PTR_WIRE_TYPE * pBufferMark = NULL;

    if ( *(PFORMAT_STRING)pFormat != FC64_RP )
        {
        ALIGN(pStubMsg->Buffer, NDR64_PTR_WIRE_ALIGN );

        pBufferMark = (NDR64_PTR_WIRE_TYPE*)pStubMsg->Buffer;

        pStubMsg->Buffer += sizeof( NDR64_PTR_WIRE_TYPE );
        }
     pStubMsg->MemorySize += PTR_MEM_SIZE;

     Ndr64pPointerMemorySize( pStubMsg,
                             pBufferMark,
                             pFormat );

}

__forceinline void
Ndr64EmbeddedPointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{

    ALIGN(pStubMsg->Buffer, NDR64_PTR_WIRE_ALIGN );
    NDR64_PTR_WIRE_TYPE * pBufferMark = (NDR64_PTR_WIRE_TYPE*)pStubMsg->Buffer;
    pStubMsg->Buffer += sizeof( NDR64_PTR_WIRE_TYPE );
    pStubMsg->MemorySize += PTR_MEM_SIZE;

    if ( pStubMsg->IgnoreEmbeddedPointers )
        return;

    POINTER_MEMSIZE_SWAP_CONTEXT SwapContext( pStubMsg );

    Ndr64pPointerMemorySize( pStubMsg,
                             pBufferMark,
                             pFormat );

}

void
Ndr64SimpleStructMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{
    const NDR64_STRUCTURE_HEADER_FORMAT * const pStructFormat =
        (NDR64_STRUCTURE_HEADER_FORMAT*) pFormat;

    ALIGN( pStubMsg->Buffer, pStructFormat->Alignment );

    uchar *pBufferSave = pStubMsg->Buffer;

    LENGTH_ALIGN( pStubMsg->MemorySize, pStructFormat->Alignment );

    CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + pStructFormat->MemorySize );
    pStubMsg->Buffer += pStructFormat->MemorySize;
    pStubMsg->MemorySize += pStructFormat->MemorySize;

    if ( pStructFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pStructFormat + 1,
                                       0,
                                       pBufferSave );
        }
}

void
Ndr64ConformantStructMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{
    const NDR64_CONF_STRUCTURE_HEADER_FORMAT * const pStructFormat =
        (NDR64_CONF_STRUCTURE_HEADER_FORMAT*) pFormat;

    NDR64_WIRE_COUNT_TYPE MaxCount;

    const NDR64_CONF_ARRAY_HEADER_FORMAT * const pArrayFormat =
        (NDR64_CONF_ARRAY_HEADER_FORMAT *) pStructFormat->ArrayDescription;

    if ( !NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
        {

        ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );
        MaxCount = *((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer);
        pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE);
        }
    else
        {
        MaxCount = *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
        }

    NDR64_UINT32 StructSize =  pStructFormat->MemorySize + Ndr64pMultiplyUpTo2GB( 
                                                    MaxCount , pArrayFormat->ElementSize ) ;

    ALIGN(pStubMsg->Buffer, pStructFormat->Alignment);

    uchar *pBufferSave = pStubMsg->Buffer;

    LENGTH_ALIGN( pStubMsg->MemorySize, pStructFormat->Alignment );

    CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, StructSize );
    pStubMsg->Buffer        += StructSize;
    pStubMsg->MemorySize    += StructSize;

    if ( pStructFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pStructFormat + 1,
                                       (NDR64_UINT32)MaxCount,
                                       pBufferSave );

        }
}

void
Ndr64ComplexStructMemorySize(
    PMIDL_STUB_MESSAGE    pStubMsg,
    PNDR64_FORMAT         pFormat )

{
    const NDR64_BOGUS_STRUCTURE_HEADER_FORMAT *  pStructFormat =
        (NDR64_BOGUS_STRUCTURE_HEADER_FORMAT*) pFormat;
    const NDR64_CONF_BOGUS_STRUCTURE_HEADER_FORMAT * pConfStructFormat =
        (NDR64_CONF_BOGUS_STRUCTURE_HEADER_FORMAT*) pFormat;

    bool fSetPointerBufferMark = !pStubMsg->IgnoreEmbeddedPointers &&
                                 !pStubMsg->PointerBufferMark;

    if ( fSetPointerBufferMark )
        {
        pStubMsg->IgnoreEmbeddedPointers = TRUE;

        uchar * BufferSave = pStubMsg->Buffer;
        ulong MemorySizeSave = pStubMsg->MemorySize;

        Ndr64ComplexStructMemorySize(
            pStubMsg,
            pFormat );

        pStubMsg->PointerBufferMark = pStubMsg->Buffer;
        pStubMsg->PointerLength     = pStubMsg->MemorySize;

        pStubMsg->IgnoreEmbeddedPointers = FALSE;

        pStubMsg->MemorySize = MemorySizeSave;
        pStubMsg->Buffer = BufferSave;
        }

    PFORMAT_STRING  pFormatPointers = (PFORMAT_STRING)pStructFormat->PointerLayout;
    PFORMAT_STRING  pFormatArray = NULL;

    PFORMAT_STRING  pMemberLayout = ( *(PFORMAT_STRING)pFormat == FC64_CONF_BOGUS_STRUCT ||
                                      *(PFORMAT_STRING)pFormat == FC64_FORCED_CONF_BOGUS_STRUCT ) ?
                                    (PFORMAT_STRING)( pConfStructFormat + 1) :
                                    (PFORMAT_STRING)( pStructFormat + 1);

    SAVE_CONTEXT<uchar>  uFlagsSave( pStubMsg->uFlags );
    SAVE_CONTEXT<uchar*> ConformanceMarkSave( pStubMsg->ConformanceMark );

    if ( pStructFormat->Flags.HasConfArray )
        {
        pFormatArray = (PFORMAT_STRING)pConfStructFormat->ConfArrayDescription;

        if ( ! NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
            {

            NDR64_WIRE_COUNT_TYPE ConformanceSize;

            ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

            pStubMsg->ConformanceMark = pStubMsg->Buffer;

            ConformanceSize = pConfStructFormat->Dimensions * sizeof(NDR64_WIRE_COUNT_TYPE);

            CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + ConformanceSize );
            pStubMsg->Buffer += ConformanceSize;

            NDR64_SET_CONF_MARK_VALID( pStubMsg->uFlags );
            }
        }
    else
        {
        pFormatArray = 0;
        }

    ALIGN(pStubMsg->Buffer, pStructFormat->Alignment);

    for ( ; ; )
        {
        switch ( *pMemberLayout )
            {

            case FC64_STRUCT:
                {
                const NDR64_SIMPLE_REGION_FORMAT *pRegion =
                    (NDR64_SIMPLE_REGION_FORMAT*) pMemberLayout;

                ALIGN( pStubMsg->Buffer, pRegion->Alignment );

                CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + pRegion->RegionSize );
                pStubMsg->Buffer        += pRegion->RegionSize;
                pStubMsg->MemorySize    += pRegion->RegionSize;

                pMemberLayout           += sizeof( *pRegion );
                break;
                }

            case FC64_STRUCTPADN :
                {
                const NDR64_MEMPAD_FORMAT *pMemPad = (NDR64_MEMPAD_FORMAT*)pMemberLayout;
                pStubMsg->MemorySize    += pMemPad->MemPad;
                pMemberLayout           += sizeof(*pMemPad);
                break;
                }

            case FC64_POINTER :

                Ndr64EmbeddedPointerMemorySize(
                    pStubMsg,
                    pFormatPointers );

                pFormatPointers += sizeof(NDR64_POINTER_FORMAT);
                pMemberLayout += sizeof(NDR64_SIMPLE_MEMBER_FORMAT);

                break;

            case FC64_EMBEDDED_COMPLEX :
                {
                const NDR64_EMBEDDED_COMPLEX_FORMAT * pEmbeddedFormat =
                    (NDR64_EMBEDDED_COMPLEX_FORMAT*) pMemberLayout;

                Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                             pEmbeddedFormat->Type );

                pMemberLayout += sizeof(*pEmbeddedFormat);

                break;

                }

            case FC64_BUFFER_ALIGN:
                {
                const NDR64_BUFFER_ALIGN_FORMAT *pBufAlign =
                    (NDR64_BUFFER_ALIGN_FORMAT*) pMemberLayout;
                ALIGN( pStubMsg->Buffer, pBufAlign->Alignment );
                pMemberLayout += sizeof( *pBufAlign );
                break;
                }

             case FC64_CHAR :
             case FC64_WCHAR :
             case FC64_INT8:
             case FC64_UINT8:
             case FC64_INT16:
             case FC64_UINT16:
             case FC64_INT32:
             case FC64_UINT32:
             case FC64_INT64:
             case FC64_UINT64:
             case FC64_FLOAT32 :
             case FC64_FLOAT64 :
             case FC64_ERROR_STATUS_T:
                ALIGN(pStubMsg->Buffer, NDR64_SIMPLE_TYPE_BUFALIGN(*pMemberLayout));

                pStubMsg->Buffer += NDR64_SIMPLE_TYPE_BUFSIZE( *pMemberLayout );
                pStubMsg->MemorySize += NDR64_SIMPLE_TYPE_MEMSIZE(*pMemberLayout);

                pMemberLayout += sizeof(NDR64_SIMPLE_MEMBER_FORMAT);
                break;

            case FC64_IGNORE:
                ALIGN(pStubMsg->Buffer, NDR64_PTR_WIRE_ALIGN );
                pStubMsg->Buffer     += sizeof(NDR64_PTR_WIRE_TYPE) ;
                pStubMsg->MemorySize += PTR_MEM_SIZE;

                pMemberLayout += sizeof(NDR64_SIMPLE_MEMBER_FORMAT);
                break;

            case FC64_END :
                goto ComplexMemorySizeEnd;

            default :
                NDR_ASSERT(0,"Ndr64ComplexStructMemorySize : bad format char");
                RpcRaiseException( RPC_S_INTERNAL_ERROR );
                return;
            }
        }

ComplexMemorySizeEnd :

    if ( pFormatArray )
        {
        Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                     pFormatArray );
        }
    else
        {

        ALIGN( pStubMsg->Buffer, pStructFormat->Alignment );
        }

    if ( fSetPointerBufferMark )
        {
        pStubMsg->Buffer            = pStubMsg->PointerBufferMark;
        pStubMsg->MemorySize        = pStubMsg->PointerLength;
        pStubMsg->PointerBufferMark = 0;
        pStubMsg->PointerLength     = 0;
        }
}

void
Ndr64FixedArrayMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{
    const NDR64_FIX_ARRAY_HEADER_FORMAT * pArrayFormat =
        (NDR64_FIX_ARRAY_HEADER_FORMAT*) pFormat;

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment );
    LENGTH_ALIGN( pStubMsg->MemorySize, pArrayFormat->Alignment );

    CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer , pArrayFormat->TotalSize );
    uchar *pBufferStart = pStubMsg->Buffer;

    pStubMsg->Buffer        += pArrayFormat->TotalSize;
    pStubMsg->MemorySize    += pArrayFormat->TotalSize;

    if ( pArrayFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pArrayFormat + 1,
                                       0,
                                       pBufferStart );
        }
}

void
Ndr64ConformantArrayMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{

    const NDR64_CONF_ARRAY_HEADER_FORMAT *pArrayFormat =
        (NDR64_CONF_ARRAY_HEADER_FORMAT*) pFormat;

    NDR64_WIRE_COUNT_TYPE MaxCount;
    if ( !NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
        {
        ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );
        MaxCount = *((NDR64_WIRE_COUNT_TYPE*)pStubMsg->Buffer);
        pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE);
        }
    else
        {
        MaxCount = *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
        }

    NDR64_UINT32 Size = Ndr64pMultiplyUpTo2GB( MaxCount ,
                               pArrayFormat->ElementSize );

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment );
    LENGTH_ALIGN( pStubMsg->MemorySize, pArrayFormat->Alignment );

    CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, Size );
    uchar *pBufferStart     =  pStubMsg->Buffer;
    pStubMsg->Buffer        += Size;
    pStubMsg->MemorySize    += Size;

    if ( pArrayFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pArrayFormat + 1,
                                       (NDR64_UINT32)MaxCount,
                                       pBufferStart );

        }
}

void
Ndr64ConformantVaryingArrayMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{
    const NDR64_CONF_VAR_ARRAY_HEADER_FORMAT * pArrayFormat =
        (NDR64_CONF_VAR_ARRAY_HEADER_FORMAT*) pFormat;

    NDR64_WIRE_COUNT_TYPE MaxCount;
    if ( ! NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
        {

        ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

        MaxCount = *((NDR64_WIRE_COUNT_TYPE*)pStubMsg->Buffer);
        pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE);
        }
    else
        {
        MaxCount = *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
        }

    ALIGN(pStubMsg->Buffer,NDR64_WIRE_COUNT_ALIGN);

    NDR64_WIRE_COUNT_TYPE Offset      = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[0];
    NDR64_WIRE_COUNT_TYPE ActualCount = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[1];
    pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

    NDR64_UINT32 MemorySize  = Ndr64pMultiplyUpTo2GB(MaxCount ,
                                     pArrayFormat->ElementSize );
    NDR64_UINT32 BufferSize  = Ndr64pMultiplyUpTo2GB(ActualCount ,
                                     pArrayFormat->ElementSize );

    if ( (Offset != 0) ||
         (MaxCount < ActualCount) )
        RpcRaiseException( RPC_X_INVALID_BOUND );

    LENGTH_ALIGN( pStubMsg->MemorySize, pArrayFormat->Alignment );
    pStubMsg->MemorySize += MemorySize;

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment);

    CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, BufferSize );
    uchar *pBufferStart =  pStubMsg->Buffer;
    pStubMsg->Buffer    += BufferSize;

    if ( pArrayFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pArrayFormat + 1,
                                       (NDR64_UINT32)ActualCount,
                                       pBufferStart );

        }
}

void
Ndr64VaryingArrayMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{
    const NDR64_VAR_ARRAY_HEADER_FORMAT * pArrayFormat =
        (NDR64_VAR_ARRAY_HEADER_FORMAT*) pFormat;

    ALIGN( pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

    NDR64_WIRE_COUNT_TYPE Offset = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[0];
    NDR64_WIRE_COUNT_TYPE ActualCount = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[1];
    pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

    NDR64_UINT32 BufferSize =
        Ndr64pMultiplyUpTo2GB( ActualCount ,
                            pArrayFormat->ElementSize );

    if ( ( Offset != 0 ) ||
         ( BufferSize > pArrayFormat->TotalSize ) )
        RpcRaiseException( RPC_X_INVALID_BOUND );

    LENGTH_ALIGN( pStubMsg->MemorySize, pArrayFormat->Alignment );

    pStubMsg->MemorySize += pArrayFormat->TotalSize;

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment);

    CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, BufferSize );
    uchar *pBufferStart     =  pStubMsg->Buffer;
    pStubMsg->Buffer        += BufferSize;

    if ( pArrayFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pArrayFormat + 1,
                                       (NDR64_UINT32)ActualCount,
                                       pBufferStart );

        }
}

void
Ndr64ComplexArrayMemorySize(
                           PMIDL_STUB_MESSAGE  pStubMsg,
                           PNDR64_FORMAT       pFormat )

{
    const NDR64_BOGUS_ARRAY_HEADER_FORMAT *pArrayFormat =
    (NDR64_BOGUS_ARRAY_HEADER_FORMAT *) pFormat;

    bool fSetPointerBufferMark = ! pStubMsg->IgnoreEmbeddedPointers &&
                                 ! pStubMsg->PointerBufferMark;
    if ( fSetPointerBufferMark )
        {
        pStubMsg->IgnoreEmbeddedPointers = TRUE;

        ulong MemorySizeSave = pStubMsg->MemorySize;
        uchar* pBufferSave = pStubMsg->Buffer;

        Ndr64ComplexArrayMemorySize(
            pStubMsg,
            pFormat );

        pStubMsg->PointerBufferMark = pStubMsg->Buffer;
        pStubMsg->PointerLength     = pStubMsg->MemorySize;
        pStubMsg->IgnoreEmbeddedPointers = FALSE;

        pStubMsg->MemorySize = MemorySizeSave;
        pStubMsg->Buffer = pBufferSave;
        }

    BOOL                IsFixed = ( pArrayFormat->FormatCode == FC64_FIX_BOGUS_ARRAY ) ||
                                  ( pArrayFormat->FormatCode == FC64_FIX_FORCED_BOGUS_ARRAY );

    PFORMAT_STRING      pElementFormat = (PFORMAT_STRING)pArrayFormat->Element;

    SAVE_CONTEXT<uchar>  uFlagsSave( pStubMsg->uFlags );
    SAVE_CONTEXT<uchar*> ConformanceMarkSave( pStubMsg->ConformanceMark );
    SAVE_CONTEXT<uchar*> VarianceMarkSave( pStubMsg->VarianceMark );

    NDR64_WIRE_COUNT_TYPE Elements = pArrayFormat->NumberElements;
    NDR64_WIRE_COUNT_TYPE Count = Elements;
    NDR64_WIRE_COUNT_TYPE Offset = 0;

    if ( !IsFixed )
        {

        const NDR64_CONF_VAR_BOGUS_ARRAY_HEADER_FORMAT* pConfVarFormat=
        (NDR64_CONF_VAR_BOGUS_ARRAY_HEADER_FORMAT*)pFormat;

        if ( pConfVarFormat->ConfDescription )
            {

            if ( ! NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
                {

                ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN);

                pStubMsg->ConformanceMark = pStubMsg->Buffer;

                pStubMsg->Buffer += pArrayFormat->NumberDims * sizeof(NDR64_WIRE_COUNT_TYPE);

                CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );

                NDR64_SET_CONF_MARK_VALID( pStubMsg->uFlags );

                }

            Elements = *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
            pStubMsg->ConformanceMark += sizeof(NDR64_WIRE_COUNT_TYPE);
            Offset   = 0;
            Count    = Elements;

            }

        if ( pConfVarFormat->VarDescription )
            {

            if ( ! NDR64_IS_VAR_MARK_VALID( pStubMsg->uFlags ) )
                {

                NDR64_UINT32 Dimensions;

                ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN);

                pStubMsg->VarianceMark = pStubMsg->Buffer;

                Dimensions = pArrayFormat->Flags.IsArrayofStrings ?
                             (pArrayFormat->NumberDims - 1) :
                             (pArrayFormat->NumberDims);

                pStubMsg->Buffer += Dimensions * sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

                CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );

                if ( NDR64_IS_ARRAY_OR_STRING( *pElementFormat ) )
                    NDR64_SET_VAR_MARK_VALID( pStubMsg->uFlags );
                }
            else if ( !NDR64_IS_ARRAY_OR_STRING( *pElementFormat ) )
                NDR64_RESET_VAR_MARK_VALID( pStubMsg->uFlags );

            Offset  = ((NDR64_WIRE_COUNT_TYPE*)pStubMsg->VarianceMark)[0];
            Count   = ((NDR64_WIRE_COUNT_TYPE*)pStubMsg->VarianceMark)[1];
            pStubMsg->VarianceMark += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

            if ( Elements < (Offset + Count) )
                RpcRaiseException( RPC_X_INVALID_BOUND );
            }

        }

    NDR64_UINT32        ElementMemorySize =
        Ndr64pMemorySize( pStubMsg,
                          pElementFormat,
                          TRUE );

    pStubMsg->MemorySize+= Ndr64pMultiplyUpTo2GB(Offset ,
                                              ElementMemorySize);

    Ndr64pMultiplyUpTo2GB( Elements ,  ElementMemorySize );
    Ndr64pMultiplyUpTo2GB( Count ,  ElementMemorySize );

    NDR64_WIRE_COUNT_TYPE LeftOverGap = Elements - Count - Offset;

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment);

    for ( ; Count--; )
        {
        Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                     pElementFormat );
        }

    pStubMsg->MemorySize += Ndr64pMultiplyUpTo2GB(LeftOverGap , 
                                               ElementMemorySize );
    if ( fSetPointerBufferMark )
        {
        pStubMsg->Buffer            = pStubMsg->PointerBufferMark;
        pStubMsg->MemorySize        = pStubMsg->PointerLength;
        pStubMsg->PointerBufferMark = 0;
        pStubMsg->PointerLength     = 0;
        }
}

void
Ndr64NonConformantStringMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{
    const NDR64_NON_CONFORMANT_STRING_FORMAT * pStringFormat =
        (NDR64_NON_CONFORMANT_STRING_FORMAT*) pFormat;

    ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

    NDR64_WIRE_COUNT_TYPE Offset      = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[0];
    NDR64_WIRE_COUNT_TYPE ActualCount = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[1];
    pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

    NDR64_UINT32 BufferSize =
        Ndr64pMultiplyUpTo2GB( ActualCount ,
                           pStringFormat->Header.ElementSize );

    if ( pStringFormat->Header.FormatCode == FC64_WCHAR_STRING )
        {

        LENGTH_ALIGN( pStubMsg->MemorySize, 0x1 );
        }

    CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, BufferSize );
    pStubMsg->Buffer        += BufferSize;
    pStubMsg->MemorySize    += pStringFormat->TotalSize;

}

void
Ndr64ConformantStringMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{

    const NDR64_CONFORMANT_STRING_FORMAT * const pStringFormat =
        (NDR64_CONFORMANT_STRING_FORMAT*) pFormat;

    NDR64_WIRE_COUNT_TYPE    MaxCount;
    if ( ! NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
        {
        ALIGN( pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );
        MaxCount =  *((NDR64_WIRE_COUNT_TYPE*)pStubMsg->Buffer);
        pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE);
        }
    else
        {
        MaxCount =  *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
        }

    ALIGN( pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );
    NDR64_WIRE_COUNT_TYPE Offset      = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[0];
    NDR64_WIRE_COUNT_TYPE ActualCount = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[1];
    pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

    NDR64_UINT32 TransmittedSize =
        Ndr64pMultiplyUpTo2GB( ActualCount ,
                            pStringFormat->Header.ElementSize );
    NDR64_UINT32 MemorySize      =
        Ndr64pMultiplyUpTo2GB( MaxCount ,
                            pStringFormat->Header.ElementSize );

    CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, TransmittedSize );

    if ( pStringFormat->Header.FormatCode == FC64_CONF_WCHAR_STRING )
        {

        LENGTH_ALIGN( pStubMsg->MemorySize, 0x1 );
        }

    pStubMsg->Buffer        += TransmittedSize;
    pStubMsg->MemorySize    += MemorySize;
}

void
Ndr64UnionMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )

{
    const NDR64_UNION_ARM_SELECTOR* pArmSelector;

    NDR64_FORMAT_CHAR   SwitchType;
    NDR64_UINT32        MemorySize;

    switch(*(PFORMAT_STRING)pFormat)
    {
    case FC64_NON_ENCAPSULATED_UNION:
        {
        const NDR64_NON_ENCAPSULATED_UNION* pNonEncapUnionFormat =
            (const NDR64_NON_ENCAPSULATED_UNION*) pFormat;

        ALIGN(pStubMsg->Buffer, pNonEncapUnionFormat->Alignment);
        SwitchType      = pNonEncapUnionFormat->SwitchType;
        pArmSelector    = (NDR64_UNION_ARM_SELECTOR*)(pNonEncapUnionFormat + 1);
        MemorySize      = pNonEncapUnionFormat->MemorySize;

        break;
        }
    case FC64_ENCAPSULATED_UNION:
        {
        const NDR64_ENCAPSULATED_UNION* pEncapUnionFormat =
            (const NDR64_ENCAPSULATED_UNION*)pFormat;

        ALIGN(pStubMsg->Buffer, pEncapUnionFormat->Alignment);
        SwitchType      = pEncapUnionFormat->SwitchType;
        pArmSelector    = (NDR64_UNION_ARM_SELECTOR*)(pEncapUnionFormat + 1);
        MemorySize      = pEncapUnionFormat->MemorySize;
        break;
        }

    default:
        NDR_ASSERT("Bad union format\n", 0);
        return;
        }

    EXPR_VALUE SwitchIs =
        Ndr64pSimpleTypeToExprValue( SwitchType,
                                     pStubMsg->Buffer );

    pStubMsg->MemorySize += MemorySize;

    pStubMsg->Buffer     += NDR64_SIMPLE_TYPE_BUFSIZE(SwitchType);

    ALIGN(pStubMsg->Buffer, pArmSelector->Alignment);

    PNDR64_FORMAT pArmFormat =
        Ndr64pFindUnionArm( pStubMsg,
                            pArmSelector,
                            SwitchIs );

    if ( ! pArmFormat )
        return;

    Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                 pArmFormat );

}

void
Ndr64XmitOrRepAsMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat,
    bool bIsEmbedded )

{
    NDR64_TRANSMIT_AS_FORMAT *pTransFormat = ( NDR64_TRANSMIT_AS_FORMAT *) pFormat;
    NDR_ASSERT( pTransFormat->FormatCode == FC64_TRANSMIT_AS || pTransFormat->FormatCode , "invalid format string for user marshal" );

    pStubMsg->MemorySize += pTransFormat->PresentedTypeMemorySize;

    if ( bIsEmbedded )
        {
        Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                     pTransFormat->TransmittedType );
        }
    else
        {
        Ndr64TopLevelTypeMemorySize( pStubMsg,
                                     pTransFormat->TransmittedType );
        }
}

void
Ndr64TopLevelXmitOrRepAsMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    Ndr64XmitOrRepAsMemorySize( pStubMsg,
                                pFormat,
                                false );
}

void
Ndr64EmbeddedXmitOrRepAsMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    Ndr64XmitOrRepAsMemorySize( pStubMsg,
                                pFormat,
                                true );
}

void
NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT::Dispatch(MIDL_STUB_MESSAGE *pStubMsg)
{

    Ndr64TopLevelTypeMemorySize( pStubMsg,
                                 pFormat );

}

#if defined(DBG)
void
NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT::Print()
{
    DbgPrint("NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT\n");
    DbgPrint("pFormat:                 %p\n", pFormat );
}
#endif

void
Ndr64UserMarshallPointeeMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{

    if ( pStubMsg->IgnoreEmbeddedPointers )
        return;

    if ( !pStubMsg->pPointerQueueState ||
         !pStubMsg->pPointerQueueState->GetActiveQueue() )
        {

        POINTER_MEMSIZE_SWAP_CONTEXT SwapContext( pStubMsg );

        Ndr64TopLevelTypeMemorySize(
            pStubMsg,
            pFormat );
        return;
        }

    NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT*pElement =
       new(pStubMsg->pPointerQueueState)
           NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT((PFORMAT_STRING)pFormat );
    pStubMsg->pPointerQueueState->GetActiveQueue()->Enque( pElement );

}

void
Ndr64UserMarshalMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat,
    bool                bIsEmbedded )

{
    NDR64_USER_MARSHAL_FORMAT  *pUserFormat = ( NDR64_USER_MARSHAL_FORMAT *) pFormat;

    pStubMsg->MemorySize += pUserFormat->UserTypeMemorySize;

    ALIGN( pStubMsg->Buffer, pUserFormat->TransmittedTypeWireAlignment );

    if ( pUserFormat->Flags & USER_MARSHAL_POINTER )
        {

        if ( ( pUserFormat->Flags & USER_MARSHAL_UNIQUE )  ||
             (( pUserFormat->Flags & USER_MARSHAL_REF ) && bIsEmbedded) )
            {

            pStubMsg->Buffer += sizeof(NDR64_PTR_WIRE_TYPE);
            }

        Ndr64UserMarshallPointeeMemorySize( pStubMsg,
                                            pUserFormat->TransmittedType );

        return;

        }

    if ( bIsEmbedded )
        {
        Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                     pUserFormat->TransmittedType );
        }
    else
        {
        Ndr64TopLevelTypeMemorySize( pStubMsg,
                                     pUserFormat->TransmittedType );
        }

    return;
}

void
Ndr64TopLevelUserMarshalMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    Ndr64UserMarshalMemorySize( pStubMsg,
                                pFormat,
                                false );
}

void
Ndr64EmbeddedUserMarshalMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    Ndr64UserMarshalMemorySize( pStubMsg,
                                pFormat,
                                true );
}

#define NDR64_BEGIN_TABLE  \
PNDR64_MEM_SIZE_ROUTINE extern const Ndr64MemSizeRoutinesTable[] = \
{

#define NDR64_TABLE_END    \
};

#define NDR64_ZERO_ENTRY   NULL
#define NDR64_UNUSED_TABLE_ENTRY( number, tokenname ) ,NULL
#define NDR64_UNUSED_TABLE_ENTRY_NOSYM( number ) ,NULL

#define NDR64_TABLE_ENTRY( number, tokenname, marshall, embeddedmarshall, unmarshall, embeddedunmarshall, buffersize, embeddedbuffersize, memsize, embeddedmemsize, free, embeddedfree, typeflags ) \
   ,memsize

#define NDR64_SIMPLE_TYPE_TABLE_ENTRY( number, tokenname, buffersize, memorysize) \
   ,Ndr64UDTSimpleTypeMemorySize

#include "tokntbl.h"

C_ASSERT( sizeof(Ndr64MemSizeRoutinesTable)/sizeof(PNDR64_MEM_SIZE_ROUTINE) == 256 );

#undef NDR64_BEGIN_TABLE
#undef NDR64_TABLE_ENTRY

#define NDR64_BEGIN_TABLE  \
PNDR64_MEM_SIZE_ROUTINE extern const Ndr64EmbeddedMemSizeRoutinesTable[] = \
{

#define NDR64_TABLE_ENTRY( number, tokenname, marshall, embeddedmarshall, unmarshall, embeddedunmarshall, buffersize, embeddedbuffersize, memsize, embeddedmemsize, free, embeddedfree, typeflags ) \
   ,embeddedmemsize

#include "tokntbl.h"

C_ASSERT( sizeof(Ndr64EmbeddedMemSizeRoutinesTable)/sizeof(PNDR64_MEM_SIZE_ROUTINE) == 256 );
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Copyright (c) 1993 - 1999 Microsoft Corporation

Module Name :

    memsize.c

Abstract :

    This file contains the routines called by MIDL 2.0 stubs and the
    intepreter for computing the memory size needed to hold a parameter being
    unmarshalled.

Author :

    David Kays  dkays   November 1993.

Revision History :

Note:
    Simple types are not checked for buffer over-run since we are
    only reading from the buffer and not writing from it.  So if
    a buffer overun actually occures, no real damage is done.

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

#include "precomp.hxx"
#include "..\..\ndr20\ndrole.h"


void
Ndr64UDTSimpleTypeMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT      pFormat )

/*++
--*/
{
    ALIGN(pStubMsg->Buffer, NDR64_SIMPLE_TYPE_MEMALIGN(*(PFORMAT_STRING)pFormat));

    pStubMsg->Buffer += NDR64_SIMPLE_TYPE_BUFSIZE(*(PFORMAT_STRING)pFormat);

    LENGTH_ALIGN( pStubMsg->MemorySize,
                  NDR64_SIMPLE_TYPE_MEMALIGN(*(PFORMAT_STRING)pFormat) );

    pStubMsg->MemorySize += NDR64_SIMPLE_TYPE_MEMSIZE(*(PFORMAT_STRING)pFormat);
}



void
Ndr64pRangeMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++
--*/
{
   const NDR64_RANGE_FORMAT * pRangeFormat =
        (const NDR64_RANGE_FORMAT*)pFormat;

   Ndr64UDTSimpleTypeMemorySize( pStubMsg,
                                 (PFORMAT_STRING)&pRangeFormat->RangeType );
}


void
Ndr64pInterfacePointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size needed for an interface pointer.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The current memory size.

    // wire representation of a marshalled interface pointer
    typedef struct tagMInterfacePointer
    {
        ULONG           ulCntData;          // size of data
        [size_is(ulCntData)] BYTE abData[]; // data (OBJREF)
    } MInterfacePointer;

--*/
{

    ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

    // Unmarshal the conformant size and the count field.
    CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, (sizeof(NDR64_WIRE_COUNT_TYPE)+sizeof(ulong)) );
    NDR64_UINT32 MaxCount = Ndr64pConvertTo2GB( *(NDR64_WIRE_COUNT_TYPE *) pStubMsg->Buffer );
    pStubMsg->Buffer      += sizeof(NDR64_WIRE_COUNT_TYPE);
    ulong ulCntData       = *(ulong *) pStubMsg->Buffer;
    pStubMsg->Buffer      += sizeof(ulong);

    if ( MaxCount != ulCntData )
        {
        RpcRaiseException( RPC_X_BAD_STUB_DATA );
        return;
        }

    RpcTryFinally
        {

        CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, MaxCount );

        if( (MaxCount > 0) && NDR64_IS_WALKIP(pStubMsg->uFlags) )
        {

            IStream *pStream = (*NdrpCreateStreamOnMemory)(pStubMsg->Buffer, MaxCount);
            if(pStream == 0)
                RpcRaiseException(RPC_S_OUT_OF_MEMORY);

            HRESULT hr = (*pfnCoReleaseMarshalData)(pStream);
            pStream->Release();

            if(FAILED(hr))
                RpcRaiseException(hr);
        }

        }
    RpcFinally
        {

        pStubMsg->Buffer += MaxCount;

        }
    RpcEndFinally
}


__forceinline void
Ndr64pPointerMemorySizeInternal(
    PMIDL_STUB_MESSAGE  pStubMsg,
    NDR64_PTR_WIRE_TYPE *pBufferMark,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Private routine for computing the memory size required for a pointer to
    anything.  This is the entry point for pointers embedded in structures
    arrays, or unions.

    Used for FC64_RP, FC64_UP, FC64_FP, FC64_OP.

Arguments :

    pStubMsg    - Pointer to stub message.
    pBufferMark - Location in the buffer where a unique or full pointer's id is.
                  Unused for ref pointers.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{
    const NDR64_POINTER_FORMAT *pPointerFormat = (NDR64_POINTER_FORMAT*) pFormat;

    PFORMAT_STRING pPointeeFormat = (PFORMAT_STRING)pPointerFormat->Pointee;

    switch ( pPointerFormat->FormatCode )
        {
        case FC64_RP :
            break;

        case FC64_UP :
        case FC64_OP :
            if ( ! *pBufferMark )
                return;
            break;

        case FC64_IP :
            if ( ! *pBufferMark )
                return;


            Ndr64pInterfacePointerMemorySize(pStubMsg,
                                             pPointeeFormat );
            return;

        case FC64_FP :
            //
            // Check if we've already mem sized this full pointer.
            //
            if ( Ndr64pFullPointerQueryRefId( pStubMsg,
                                              Ndr64pWirePtrToRefId(*pBufferMark),
                                              FULL_POINTER_MEM_SIZED,
                                              0 ) )
                return;

            break;

        default :
            NDR_ASSERT(0,"Ndr64pPointerMemorySize : bad format char");
            RpcRaiseException( RPC_S_INTERNAL_ERROR );
            return;
        }

    //
    // We align all memory pointers on at least a void * boundary.
    //
    LENGTH_ALIGN( pStubMsg->MemorySize, PTR_MEM_ALIGN );

    if ( NDR64_SIMPLE_POINTER( pPointerFormat->Flags ) )
        {
        ALIGN(pStubMsg->Buffer, NDR64_SIMPLE_TYPE_BUFALIGN( *pPointeeFormat ));
        pStubMsg->Buffer += NDR64_SIMPLE_TYPE_BUFSIZE( *pPointeeFormat );

        LENGTH_ALIGN( pStubMsg->MemorySize,
                      NDR64_SIMPLE_TYPE_MEMALIGN( *pPointeeFormat ) );
        pStubMsg->MemorySize += NDR64_SIMPLE_TYPE_MEMSIZE( *pPointeeFormat );

        return;
        }

    // Pointer to complex type.

    if ( NDR64_POINTER_DEREF( pPointerFormat->Flags ) )
        pStubMsg->MemorySize += PTR_MEM_SIZE;

    SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags );
    NDR64_RESET_EMBEDDED_FLAGS_TO_STANDALONE(pStubMsg->uFlags);

    Ndr64TopLevelTypeMemorySize( pStubMsg,
                                 pPointeeFormat );

    return;
}


void NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT::Dispatch(PMIDL_STUB_MESSAGE pStubMsg)
{
    SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags, uFlags );

    Ndr64pPointerMemorySizeInternal( pStubMsg,
                                     pBufferMark,
                                     pFormat );

}

#if defined(DBG)
void NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT::Print()
{
    DbgPrint("NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT:\n");
    DbgPrint("pNext:                   %p\n", pNext );
    DbgPrint("pFormat:                 %p\n", pFormat );
    DbgPrint("uFlags:                  %u\n", uFlags );
    DbgPrint("pBufferMark:             %p\n", pBufferMark );
}
#endif

void
Ndr64pEnquePointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    NDR64_PTR_WIRE_TYPE *pBufferMark,
    PNDR64_FORMAT       pFormat )
{

    NDR64_POINTER_CONTEXT PointerContext( pStubMsg );

    RpcTryFinally
        {
        if ( !PointerContext.ShouldEnque() )
            {
            Ndr64pPointerMemorySizeInternal( pStubMsg,
                                             pBufferMark,
                                             pFormat );

            }
        else
            {
            NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT*pElement =
                new(PointerContext.GetActiveState())
                    NDR64_MEMSIZE_POINTER_QUEUE_ELEMENT(pStubMsg,
                                                        (PFORMAT_STRING)pFormat,
                                                        pBufferMark );
            PointerContext.Enque( pElement );
            }
        PointerContext.DispatchIfRequired();
        }
    RpcFinally
        {
        PointerContext.EndContext();
        }
    RpcEndFinally

}

void
Ndr64pPointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    NDR64_PTR_WIRE_TYPE *pBufferMark,
    PNDR64_FORMAT       pFormat )
{
    SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags );
    NDR64_RESET_EMBEDDED_FLAGS_TO_STANDALONE(pStubMsg->uFlags);

    if ( !NdrIsLowStack(pStubMsg) )
        {
        Ndr64pPointerMemorySizeInternal(
            pStubMsg,
            pBufferMark,
            pFormat );
        return;
        }


    Ndr64pEnquePointerMemorySize(
        pStubMsg,
        pBufferMark,
        pFormat );

}


__forceinline void
Ndr64TopLevelPointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    NDR64_PTR_WIRE_TYPE * pBufferMark = NULL;

    //
    // If this is not a ref pointer then mark where the pointer's id is in
    // the buffer and increment the stub message buffer pointer.
    //
    if ( *(PFORMAT_STRING)pFormat != FC64_RP )
        {
        ALIGN(pStubMsg->Buffer, NDR64_PTR_WIRE_ALIGN );

        pBufferMark = (NDR64_PTR_WIRE_TYPE*)pStubMsg->Buffer;

        pStubMsg->Buffer += sizeof( NDR64_PTR_WIRE_TYPE );
        }
     pStubMsg->MemorySize += PTR_MEM_SIZE;

     Ndr64pPointerMemorySize( pStubMsg,
                             pBufferMark,
                             pFormat );

}


__forceinline void
Ndr64EmbeddedPointerMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{

    ALIGN(pStubMsg->Buffer, NDR64_PTR_WIRE_ALIGN );
    NDR64_PTR_WIRE_TYPE * pBufferMark = (NDR64_PTR_WIRE_TYPE*)pStubMsg->Buffer;
    pStubMsg->Buffer += sizeof( NDR64_PTR_WIRE_TYPE );
    pStubMsg->MemorySize += PTR_MEM_SIZE;

    if ( pStubMsg->IgnoreEmbeddedPointers )
        return;

    POINTER_MEMSIZE_SWAP_CONTEXT SwapContext( pStubMsg );

    Ndr64pPointerMemorySize( pStubMsg,
                             pBufferMark,
                             pFormat );

}


void
Ndr64SimpleStructMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size required for a simple structure.

    Used for FC64_STRUCT and FC64_PSTRUCT.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Structure's format string description.

Return :

    The computed memory size.

--*/
{
    const NDR64_STRUCTURE_HEADER_FORMAT * const pStructFormat =
        (NDR64_STRUCTURE_HEADER_FORMAT*) pFormat;

    ALIGN( pStubMsg->Buffer, pStructFormat->Alignment );

    uchar *pBufferSave = pStubMsg->Buffer;

    LENGTH_ALIGN( pStubMsg->MemorySize, pStructFormat->Alignment );

    CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + pStructFormat->MemorySize );
    pStubMsg->Buffer += pStructFormat->MemorySize;
    pStubMsg->MemorySize += pStructFormat->MemorySize;

    if ( pStructFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pStructFormat + 1,
                                       0,
                                       pBufferSave );
        }
}


void
Ndr64ConformantStructMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size required for a conformant structure.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{
    const NDR64_CONF_STRUCTURE_HEADER_FORMAT * const pStructFormat =
        (NDR64_CONF_STRUCTURE_HEADER_FORMAT*) pFormat;

    NDR64_WIRE_COUNT_TYPE MaxCount;

    const NDR64_CONF_ARRAY_HEADER_FORMAT * const pArrayFormat =
        (NDR64_CONF_ARRAY_HEADER_FORMAT *) pStructFormat->ArrayDescription;

    if ( !NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
        {
        // Align for the conformance count.
        ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );
        MaxCount = *((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer);
        pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE);
        }
    else
        {
        MaxCount = *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
        }

    NDR64_UINT32 StructSize =  pStructFormat->MemorySize + Ndr64pMultiplyUpTo2GB( 
                                                    MaxCount , pArrayFormat->ElementSize ) ;

    // Realign for struct
    ALIGN(pStubMsg->Buffer, pStructFormat->Alignment);

    uchar *pBufferSave = pStubMsg->Buffer;

    LENGTH_ALIGN( pStubMsg->MemorySize, pStructFormat->Alignment );

    CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, StructSize );
    pStubMsg->Buffer        += StructSize;
    pStubMsg->MemorySize    += StructSize;

    if ( pStructFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pStructFormat + 1,
                                       (NDR64_UINT32)MaxCount,
                                       pBufferSave );

        }
}


void
Ndr64ComplexStructMemorySize(
    PMIDL_STUB_MESSAGE    pStubMsg,
    PNDR64_FORMAT         pFormat )
/*++

Routine Description :

    Computes the memory size required for a complex structure.

    Used for FC64_BOGUS_STRUCT.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

Notes:
    This routine can calculate the memory size with or without pointees.
    When calculating size with pointees at the top level, the routine calls
    itself recursively to find out where pointees would be and then remember
    the context using pStubMsg->MemorySize and pStubMsg->PointerBufferMark.

--*/
{
    const NDR64_BOGUS_STRUCTURE_HEADER_FORMAT *  pStructFormat =
        (NDR64_BOGUS_STRUCTURE_HEADER_FORMAT*) pFormat;
    const NDR64_CONF_BOGUS_STRUCTURE_HEADER_FORMAT * pConfStructFormat =
        (NDR64_CONF_BOGUS_STRUCTURE_HEADER_FORMAT*) pFormat;

    bool fSetPointerBufferMark = !pStubMsg->IgnoreEmbeddedPointers &&
                                 !pStubMsg->PointerBufferMark;

    if ( fSetPointerBufferMark )
        {
        pStubMsg->IgnoreEmbeddedPointers = TRUE;

        // This gets clobbered.
        uchar * BufferSave = pStubMsg->Buffer;
        ulong MemorySizeSave = pStubMsg->MemorySize;

        //
        // Get a buffer pointer to where the struct's pointees are.
        //
        Ndr64ComplexStructMemorySize(
            pStubMsg,
            pFormat );


        // Mark where the pointees begin.
        pStubMsg->PointerBufferMark = pStubMsg->Buffer;
        pStubMsg->PointerLength     = pStubMsg->MemorySize;

        pStubMsg->IgnoreEmbeddedPointers = FALSE;

        pStubMsg->MemorySize = MemorySizeSave;
        pStubMsg->Buffer = BufferSave;
        }

    PFORMAT_STRING  pFormatPointers = (PFORMAT_STRING)pStructFormat->PointerLayout;
    PFORMAT_STRING  pFormatArray = NULL;

    PFORMAT_STRING  pMemberLayout = ( *(PFORMAT_STRING)pFormat == FC64_CONF_BOGUS_STRUCT ||
                                      *(PFORMAT_STRING)pFormat == FC64_FORCED_CONF_BOGUS_STRUCT ) ?
                                    (PFORMAT_STRING)( pConfStructFormat + 1) :
                                    (PFORMAT_STRING)( pStructFormat + 1);

    SAVE_CONTEXT<uchar>  uFlagsSave( pStubMsg->uFlags );
    SAVE_CONTEXT<uchar*> ConformanceMarkSave( pStubMsg->ConformanceMark );

    // Get conformant array description.
    if ( pStructFormat->Flags.HasConfArray )
        {
        pFormatArray = (PFORMAT_STRING)pConfStructFormat->ConfArrayDescription;

        if ( ! NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
            {

            NDR64_WIRE_COUNT_TYPE ConformanceSize;

            ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

            // conformance count marker
            pStubMsg->ConformanceMark = pStubMsg->Buffer;

            // Handle multidimensional arrays.
            ConformanceSize = pConfStructFormat->Dimensions * sizeof(NDR64_WIRE_COUNT_TYPE);

            CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + ConformanceSize );
            pStubMsg->Buffer += ConformanceSize;

            NDR64_SET_CONF_MARK_VALID( pStubMsg->uFlags );
            }
        }
    else
        {
        pFormatArray = 0;
        }

    ALIGN(pStubMsg->Buffer, pStructFormat->Alignment);

    for ( ; ; )
        {
        switch ( *pMemberLayout )
            {

            case FC64_STRUCT:
                {
                const NDR64_SIMPLE_REGION_FORMAT *pRegion =
                    (NDR64_SIMPLE_REGION_FORMAT*) pMemberLayout;

                ALIGN( pStubMsg->Buffer, pRegion->Alignment );

                CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + pRegion->RegionSize );
                pStubMsg->Buffer        += pRegion->RegionSize;
                pStubMsg->MemorySize    += pRegion->RegionSize;

                pMemberLayout           += sizeof( *pRegion );
                break;
                }

            case FC64_STRUCTPADN :
                {
                const NDR64_MEMPAD_FORMAT *pMemPad = (NDR64_MEMPAD_FORMAT*)pMemberLayout;
                pStubMsg->MemorySize    += pMemPad->MemPad;
                pMemberLayout           += sizeof(*pMemPad);
                break;
                }

            case FC64_POINTER :

                Ndr64EmbeddedPointerMemorySize(
                    pStubMsg,
                    pFormatPointers );

                pFormatPointers += sizeof(NDR64_POINTER_FORMAT);
                pMemberLayout += sizeof(NDR64_SIMPLE_MEMBER_FORMAT);

                break;

            case FC64_EMBEDDED_COMPLEX :
                {
                const NDR64_EMBEDDED_COMPLEX_FORMAT * pEmbeddedFormat =
                    (NDR64_EMBEDDED_COMPLEX_FORMAT*) pMemberLayout;

                Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                             pEmbeddedFormat->Type );

                pMemberLayout += sizeof(*pEmbeddedFormat);

                break;

                }

            case FC64_BUFFER_ALIGN:
                {
                const NDR64_BUFFER_ALIGN_FORMAT *pBufAlign =
                    (NDR64_BUFFER_ALIGN_FORMAT*) pMemberLayout;
                ALIGN( pStubMsg->Buffer, pBufAlign->Alignment );
                pMemberLayout += sizeof( *pBufAlign );
                break;
                }

             case FC64_CHAR :
             case FC64_WCHAR :
             case FC64_INT8:
             case FC64_UINT8:
             case FC64_INT16:
             case FC64_UINT16:
             case FC64_INT32:
             case FC64_UINT32:
             case FC64_INT64:
             case FC64_UINT64:
             case FC64_FLOAT32 :
             case FC64_FLOAT64 :
             case FC64_ERROR_STATUS_T:
                ALIGN(pStubMsg->Buffer, NDR64_SIMPLE_TYPE_BUFALIGN(*pMemberLayout));

                pStubMsg->Buffer += NDR64_SIMPLE_TYPE_BUFSIZE( *pMemberLayout );
                pStubMsg->MemorySize += NDR64_SIMPLE_TYPE_MEMSIZE(*pMemberLayout);

                pMemberLayout += sizeof(NDR64_SIMPLE_MEMBER_FORMAT);
                break;

            case FC64_IGNORE:
                ALIGN(pStubMsg->Buffer, NDR64_PTR_WIRE_ALIGN );
                pStubMsg->Buffer     += sizeof(NDR64_PTR_WIRE_TYPE) ;
                pStubMsg->MemorySize += PTR_MEM_SIZE;

                pMemberLayout += sizeof(NDR64_SIMPLE_MEMBER_FORMAT);
                break;

            case FC64_END :
                goto ComplexMemorySizeEnd;

            default :
                NDR_ASSERT(0,"Ndr64ComplexStructMemorySize : bad format char");
                RpcRaiseException( RPC_S_INTERNAL_ERROR );
                return;
            }
        }

ComplexMemorySizeEnd :

    if ( pFormatArray )
        {
        Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                     pFormatArray );
        }
    else
        {
        // If the structure doesn't have a conformant array, align it again
        ALIGN( pStubMsg->Buffer, pStructFormat->Alignment );
        }

    if ( fSetPointerBufferMark )
        {
        pStubMsg->Buffer            = pStubMsg->PointerBufferMark;
        pStubMsg->MemorySize        = pStubMsg->PointerLength;
        pStubMsg->PointerBufferMark = 0;
        pStubMsg->PointerLength     = 0;
        }
}


void
Ndr64FixedArrayMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size of a fixed array of any number of dimensions.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{
    const NDR64_FIX_ARRAY_HEADER_FORMAT * pArrayFormat =
        (NDR64_FIX_ARRAY_HEADER_FORMAT*) pFormat;

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment );
    LENGTH_ALIGN( pStubMsg->MemorySize, pArrayFormat->Alignment );

    CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer , pArrayFormat->TotalSize );
    uchar *pBufferStart = pStubMsg->Buffer;

    pStubMsg->Buffer        += pArrayFormat->TotalSize;
    pStubMsg->MemorySize    += pArrayFormat->TotalSize;

    if ( pArrayFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pArrayFormat + 1,
                                       0,
                                       pBufferStart );
        }
}


void
Ndr64ConformantArrayMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size of a top level one dimensional conformant array.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{


    const NDR64_CONF_ARRAY_HEADER_FORMAT *pArrayFormat =
        (NDR64_CONF_ARRAY_HEADER_FORMAT*) pFormat;

    NDR64_WIRE_COUNT_TYPE MaxCount;
    if ( !NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
        {
        ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );
        MaxCount = *((NDR64_WIRE_COUNT_TYPE*)pStubMsg->Buffer);
        pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE);
        }
    else
        {
        MaxCount = *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
        }

    NDR64_UINT32 Size = Ndr64pMultiplyUpTo2GB( MaxCount ,
                               pArrayFormat->ElementSize );

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment );
    LENGTH_ALIGN( pStubMsg->MemorySize, pArrayFormat->Alignment );

    CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, Size );
    uchar *pBufferStart     =  pStubMsg->Buffer;
    pStubMsg->Buffer        += Size;
    pStubMsg->MemorySize    += Size;

    if ( pArrayFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pArrayFormat + 1,
                                       (NDR64_UINT32)MaxCount,
                                       pBufferStart );

        }
}


void
Ndr64ConformantVaryingArrayMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size of a one dimensional top level conformant
    varying array.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{
    const NDR64_CONF_VAR_ARRAY_HEADER_FORMAT * pArrayFormat =
        (NDR64_CONF_VAR_ARRAY_HEADER_FORMAT*) pFormat;

    NDR64_WIRE_COUNT_TYPE MaxCount;
    if ( ! NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
        {
        // Align the buffer for conformance unmarshalling.
        ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

        MaxCount = *((NDR64_WIRE_COUNT_TYPE*)pStubMsg->Buffer);
        pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE);
        }
    else
        {
        MaxCount = *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
        }

    //
    // Get the offset and actual count in case needed for pointer sizing.
    //
    ALIGN(pStubMsg->Buffer,NDR64_WIRE_COUNT_ALIGN);

    NDR64_WIRE_COUNT_TYPE Offset      = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[0];
    NDR64_WIRE_COUNT_TYPE ActualCount = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[1];
    pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

    NDR64_UINT32 MemorySize  = Ndr64pMultiplyUpTo2GB(MaxCount ,
                                     pArrayFormat->ElementSize );
    NDR64_UINT32 BufferSize  = Ndr64pMultiplyUpTo2GB(ActualCount ,
                                     pArrayFormat->ElementSize );

    if ( (Offset != 0) ||
         (MaxCount < ActualCount) )
        RpcRaiseException( RPC_X_INVALID_BOUND );

    //
    // Do the memory size increment now in case the actual count is 0.
    //
    LENGTH_ALIGN( pStubMsg->MemorySize, pArrayFormat->Alignment );
    pStubMsg->MemorySize += MemorySize;

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment);

    CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, BufferSize );
    uchar *pBufferStart =  pStubMsg->Buffer;
    pStubMsg->Buffer    += BufferSize;

    if ( pArrayFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pArrayFormat + 1,
                                       (NDR64_UINT32)ActualCount,
                                       pBufferStart );

        }
}


void
Ndr64VaryingArrayMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size of a top level or embedded varying array.

    Used for FC64_SMVARRAY and FC64_LGVARRAY.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{
    const NDR64_VAR_ARRAY_HEADER_FORMAT * pArrayFormat =
        (NDR64_VAR_ARRAY_HEADER_FORMAT*) pFormat;

    //
    // Get the offset and actual count.
    //

    ALIGN( pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

    NDR64_WIRE_COUNT_TYPE Offset = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[0];
    NDR64_WIRE_COUNT_TYPE ActualCount = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[1];
    pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

    NDR64_UINT32 BufferSize =
        Ndr64pMultiplyUpTo2GB( ActualCount ,
                            pArrayFormat->ElementSize );

    if ( ( Offset != 0 ) ||
         ( BufferSize > pArrayFormat->TotalSize ) )
        RpcRaiseException( RPC_X_INVALID_BOUND );

    LENGTH_ALIGN( pStubMsg->MemorySize, pArrayFormat->Alignment );

    pStubMsg->MemorySize += pArrayFormat->TotalSize;

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment);

    CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, BufferSize );
    uchar *pBufferStart     =  pStubMsg->Buffer;
    pStubMsg->Buffer        += BufferSize;

    if ( pArrayFormat->Flags.HasPointerInfo )
        {

        Ndr64pPointerLayoutMemorySize( pStubMsg,
                                       pArrayFormat + 1,
                                       (NDR64_UINT32)ActualCount,
                                       pBufferStart );

        }
}


void
Ndr64ComplexArrayMemorySize(
                           PMIDL_STUB_MESSAGE  pStubMsg,
                           PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size of a top level complex array.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{
    const NDR64_BOGUS_ARRAY_HEADER_FORMAT *pArrayFormat =
    (NDR64_BOGUS_ARRAY_HEADER_FORMAT *) pFormat;

    bool fSetPointerBufferMark = ! pStubMsg->IgnoreEmbeddedPointers &&
                                 ! pStubMsg->PointerBufferMark;
    if ( fSetPointerBufferMark )
        {
        pStubMsg->IgnoreEmbeddedPointers = TRUE;

        // Save this since it gets clobbered.
        ulong MemorySizeSave = pStubMsg->MemorySize;
        uchar* pBufferSave = pStubMsg->Buffer;

        //
        // Get a buffer pointer to where the array's pointees are.
        //
        Ndr64ComplexArrayMemorySize(
            pStubMsg,
            pFormat );


        // This is where the array pointees start.
        pStubMsg->PointerBufferMark = pStubMsg->Buffer;
        pStubMsg->PointerLength     = pStubMsg->MemorySize;
        pStubMsg->IgnoreEmbeddedPointers = FALSE;

        pStubMsg->MemorySize = MemorySizeSave;
        pStubMsg->Buffer = pBufferSave;
        }

    BOOL                IsFixed = ( pArrayFormat->FormatCode == FC64_FIX_BOGUS_ARRAY ) ||
                                  ( pArrayFormat->FormatCode == FC64_FIX_FORCED_BOGUS_ARRAY );

    PFORMAT_STRING      pElementFormat = (PFORMAT_STRING)pArrayFormat->Element;

    SAVE_CONTEXT<uchar>  uFlagsSave( pStubMsg->uFlags );
    SAVE_CONTEXT<uchar*> ConformanceMarkSave( pStubMsg->ConformanceMark );
    SAVE_CONTEXT<uchar*> VarianceMarkSave( pStubMsg->VarianceMark );

    NDR64_WIRE_COUNT_TYPE Elements = pArrayFormat->NumberElements;
    NDR64_WIRE_COUNT_TYPE Count = Elements;
    NDR64_WIRE_COUNT_TYPE Offset = 0;

    if ( !IsFixed )
        {

        const NDR64_CONF_VAR_BOGUS_ARRAY_HEADER_FORMAT* pConfVarFormat=
        (NDR64_CONF_VAR_BOGUS_ARRAY_HEADER_FORMAT*)pFormat;

        if ( pConfVarFormat->ConfDescription )
            {

            if ( ! NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
                {
                //
                // The outer most array dimension sets the conformance marker.
                //

                ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN);

                pStubMsg->ConformanceMark = pStubMsg->Buffer;

                // Increment past conformance count(s).
                pStubMsg->Buffer += pArrayFormat->NumberDims * sizeof(NDR64_WIRE_COUNT_TYPE);

                CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );

                NDR64_SET_CONF_MARK_VALID( pStubMsg->uFlags );

                }

            Elements = *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
            pStubMsg->ConformanceMark += sizeof(NDR64_WIRE_COUNT_TYPE);
            Offset   = 0;
            Count    = Elements;

            }

        if ( pConfVarFormat->VarDescription )
            {

            if ( ! NDR64_IS_VAR_MARK_VALID( pStubMsg->uFlags ) )
                {

                NDR64_UINT32 Dimensions;

                ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN);

                // Mark where the variance counts are.
                pStubMsg->VarianceMark = pStubMsg->Buffer;

                Dimensions = pArrayFormat->Flags.IsArrayofStrings ?
                             (pArrayFormat->NumberDims - 1) :
                             (pArrayFormat->NumberDims);

                pStubMsg->Buffer += Dimensions * sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

                CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );

                if ( NDR64_IS_ARRAY_OR_STRING( *pElementFormat ) )
                    NDR64_SET_VAR_MARK_VALID( pStubMsg->uFlags );
                }
            else if ( !NDR64_IS_ARRAY_OR_STRING( *pElementFormat ) )
                NDR64_RESET_VAR_MARK_VALID( pStubMsg->uFlags );

            Offset  = ((NDR64_WIRE_COUNT_TYPE*)pStubMsg->VarianceMark)[0];
            Count   = ((NDR64_WIRE_COUNT_TYPE*)pStubMsg->VarianceMark)[1];
            pStubMsg->VarianceMark += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

            if ( Elements < (Offset + Count) )
                RpcRaiseException( RPC_X_INVALID_BOUND );
            }

        }


    NDR64_UINT32        ElementMemorySize =
        Ndr64pMemorySize( pStubMsg,
                          pElementFormat,
                          TRUE );

    pStubMsg->MemorySize+= Ndr64pMultiplyUpTo2GB(Offset ,
                                              ElementMemorySize);

    Ndr64pMultiplyUpTo2GB( Elements ,  ElementMemorySize );
    Ndr64pMultiplyUpTo2GB( Count ,  ElementMemorySize );

    NDR64_WIRE_COUNT_TYPE LeftOverGap = Elements - Count - Offset;

    ALIGN(pStubMsg->Buffer, pArrayFormat->Alignment);

    for ( ; Count--; )
        {
        Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                     pElementFormat );
        }

    pStubMsg->MemorySize += Ndr64pMultiplyUpTo2GB(LeftOverGap , 
                                               ElementMemorySize );
    if ( fSetPointerBufferMark )
        {
        pStubMsg->Buffer            = pStubMsg->PointerBufferMark;
        pStubMsg->MemorySize        = pStubMsg->PointerLength;
        pStubMsg->PointerBufferMark = 0;
        pStubMsg->PointerLength     = 0;
        }
}


void
Ndr64NonConformantStringMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size of a non conformant string.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{
    const NDR64_NON_CONFORMANT_STRING_FORMAT * pStringFormat =
        (NDR64_NON_CONFORMANT_STRING_FORMAT*) pFormat;

    ALIGN(pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );

    NDR64_WIRE_COUNT_TYPE Offset      = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[0];
    NDR64_WIRE_COUNT_TYPE ActualCount = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[1];
    pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

    NDR64_UINT32 BufferSize =
        Ndr64pMultiplyUpTo2GB( ActualCount ,
                           pStringFormat->Header.ElementSize );

    if ( pStringFormat->Header.FormatCode == FC64_WCHAR_STRING )
        {
        // Align memory just in case.
        LENGTH_ALIGN( pStubMsg->MemorySize, 0x1 );
        }

    CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, BufferSize );
    pStubMsg->Buffer        += BufferSize;
    pStubMsg->MemorySize    += pStringFormat->TotalSize;

}


void
Ndr64ConformantStringMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size of a top level conformant string.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{

    const NDR64_CONFORMANT_STRING_FORMAT * const pStringFormat =
        (NDR64_CONFORMANT_STRING_FORMAT*) pFormat;

    NDR64_WIRE_COUNT_TYPE    MaxCount;
    if ( ! NDR64_IS_CONF_MARK_VALID( pStubMsg->uFlags ) )
        {
        ALIGN( pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );
        MaxCount =  *((NDR64_WIRE_COUNT_TYPE*)pStubMsg->Buffer);
        pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE);
        }
    else
        {
        MaxCount =  *(NDR64_WIRE_COUNT_TYPE*)pStubMsg->ConformanceMark;
        }

    ALIGN( pStubMsg->Buffer, NDR64_WIRE_COUNT_ALIGN );
    NDR64_WIRE_COUNT_TYPE Offset      = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[0];
    NDR64_WIRE_COUNT_TYPE ActualCount = ((NDR64_WIRE_COUNT_TYPE *)pStubMsg->Buffer)[1];
    pStubMsg->Buffer += sizeof(NDR64_WIRE_COUNT_TYPE) * 2;

    NDR64_UINT32 TransmittedSize =
        Ndr64pMultiplyUpTo2GB( ActualCount ,
                            pStringFormat->Header.ElementSize );
    NDR64_UINT32 MemorySize      =
        Ndr64pMultiplyUpTo2GB( MaxCount ,
                            pStringFormat->Header.ElementSize );

    CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, TransmittedSize );

    if ( pStringFormat->Header.FormatCode == FC64_CONF_WCHAR_STRING )
        {
        // Align memory just in case.
        LENGTH_ALIGN( pStubMsg->MemorySize, 0x1 );
        }


    pStubMsg->Buffer        += TransmittedSize;
    pStubMsg->MemorySize    += MemorySize;
}


void
Ndr64UnionMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
/*++

Routine Description :

    Computes the memory size of an encapsulated union.

    Used for FC64_ENCAPSULATED_UNION.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size.

--*/
{
    const NDR64_UNION_ARM_SELECTOR* pArmSelector;

    NDR64_FORMAT_CHAR   SwitchType;
    NDR64_UINT32        MemorySize;

    switch(*(PFORMAT_STRING)pFormat)
    {
    case FC64_NON_ENCAPSULATED_UNION:
        {
        const NDR64_NON_ENCAPSULATED_UNION* pNonEncapUnionFormat =
            (const NDR64_NON_ENCAPSULATED_UNION*) pFormat;

        ALIGN(pStubMsg->Buffer, pNonEncapUnionFormat->Alignment);
        SwitchType      = pNonEncapUnionFormat->SwitchType;
        pArmSelector    = (NDR64_UNION_ARM_SELECTOR*)(pNonEncapUnionFormat + 1);
        MemorySize      = pNonEncapUnionFormat->MemorySize;

        break;
        }
    case FC64_ENCAPSULATED_UNION:
        {
        const NDR64_ENCAPSULATED_UNION* pEncapUnionFormat =
            (const NDR64_ENCAPSULATED_UNION*)pFormat;


        ALIGN(pStubMsg->Buffer, pEncapUnionFormat->Alignment);
        SwitchType      = pEncapUnionFormat->SwitchType;
        pArmSelector    = (NDR64_UNION_ARM_SELECTOR*)(pEncapUnionFormat + 1);
        MemorySize      = pEncapUnionFormat->MemorySize;
        break;
        }

    default:
        NDR_ASSERT("Bad union format\n", 0);
        return;
        }

    EXPR_VALUE SwitchIs =
        Ndr64pSimpleTypeToExprValue( SwitchType,
                                     pStubMsg->Buffer );

    pStubMsg->MemorySize += MemorySize;

    pStubMsg->Buffer     += NDR64_SIMPLE_TYPE_BUFSIZE(SwitchType);

    ALIGN(pStubMsg->Buffer, pArmSelector->Alignment);

    PNDR64_FORMAT pArmFormat =
        Ndr64pFindUnionArm( pStubMsg,
                            pArmSelector,
                            SwitchIs );

    if ( ! pArmFormat )
        return;

    Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                 pArmFormat );

}


void
Ndr64XmitOrRepAsMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat,
    bool bIsEmbedded )
/*++

Routine Description :

    Computes the memory size required for the presented type of a
    transmit as or represent as.

    See mrshl.c for the description of the FC layout.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The computed memory size of the presented type object.

--*/
{
    NDR64_TRANSMIT_AS_FORMAT *pTransFormat = ( NDR64_TRANSMIT_AS_FORMAT *) pFormat;
    NDR_ASSERT( pTransFormat->FormatCode == FC64_TRANSMIT_AS || pTransFormat->FormatCode , "invalid format string for user marshal" );

    pStubMsg->MemorySize += pTransFormat->PresentedTypeMemorySize;

    // In NDR64, Xmit/Rep cannot be a pointer or contain a pointer.
    // So we don't need to worry about the pointer queue here.

    if ( bIsEmbedded )
        {
        Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                     pTransFormat->TransmittedType );
        }
    else
        {
        Ndr64TopLevelTypeMemorySize( pStubMsg,
                                     pTransFormat->TransmittedType );
        }
}

void
Ndr64TopLevelXmitOrRepAsMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    Ndr64XmitOrRepAsMemorySize( pStubMsg,
                                pFormat,
                                false );
}

void
Ndr64EmbeddedXmitOrRepAsMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    Ndr64XmitOrRepAsMemorySize( pStubMsg,
                                pFormat,
                                true );
}


void
NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT::Dispatch(MIDL_STUB_MESSAGE *pStubMsg)
{

    Ndr64TopLevelTypeMemorySize( pStubMsg,
                                 pFormat );

}

#if defined(DBG)
void
NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT::Print()
{
    DbgPrint("NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT\n");
    DbgPrint("pFormat:                 %p\n", pFormat );
}
#endif


void
Ndr64UserMarshallPointeeMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{

    if ( pStubMsg->IgnoreEmbeddedPointers )
        return;

    if ( !pStubMsg->pPointerQueueState ||
         !pStubMsg->pPointerQueueState->GetActiveQueue() )
        {

        POINTER_MEMSIZE_SWAP_CONTEXT SwapContext( pStubMsg );

        Ndr64TopLevelTypeMemorySize(
            pStubMsg,
            pFormat );
        return;
        }

    NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT*pElement =
       new(pStubMsg->pPointerQueueState)
           NDR64_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT((PFORMAT_STRING)pFormat );
    pStubMsg->pPointerQueueState->GetActiveQueue()->Enque( pElement );

}


void
Ndr64UserMarshalMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat,
    bool                bIsEmbedded )
/*++

Routine Description :

    Computes the memory size required for a usr_marshal type.
    See mrshl.c for the description of the layouts.

Arguments :

    pStubMsg    - Pointer to stub message.
    pFormat     - Pointer's format string description.

Return :

    The memory size of the usr_marshall object.

--*/
{
    NDR64_USER_MARSHAL_FORMAT  *pUserFormat = ( NDR64_USER_MARSHAL_FORMAT *) pFormat;

    pStubMsg->MemorySize += pUserFormat->UserTypeMemorySize;

    ALIGN( pStubMsg->Buffer, pUserFormat->TransmittedTypeWireAlignment );

    if ( pUserFormat->Flags & USER_MARSHAL_POINTER )
        {

        if ( ( pUserFormat->Flags & USER_MARSHAL_UNIQUE )  ||
             (( pUserFormat->Flags & USER_MARSHAL_REF ) && bIsEmbedded) )
            {
            // it's embedded: unique or ref.
            pStubMsg->Buffer += sizeof(NDR64_PTR_WIRE_TYPE);
            }

        Ndr64UserMarshallPointeeMemorySize( pStubMsg,
                                            pUserFormat->TransmittedType );

        return;

        }

    if ( bIsEmbedded )
        {
        Ndr64EmbeddedTypeMemorySize( pStubMsg,
                                     pUserFormat->TransmittedType );
        }
    else
        {
        Ndr64TopLevelTypeMemorySize( pStubMsg,
                                     pUserFormat->TransmittedType );
        }

    return;
}

void
Ndr64TopLevelUserMarshalMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    Ndr64UserMarshalMemorySize( pStubMsg,
                                pFormat,
                                false );
}

void
Ndr64EmbeddedUserMarshalMemorySize(
    PMIDL_STUB_MESSAGE  pStubMsg,
    PNDR64_FORMAT       pFormat )
{
    Ndr64UserMarshalMemorySize( pStubMsg,
                                pFormat,
                                true );
}

// define the jump table
#define NDR64_BEGIN_TABLE  \
PNDR64_MEM_SIZE_ROUTINE extern const Ndr64MemSizeRoutinesTable[] = \
{

#define NDR64_TABLE_END    \
};

#define NDR64_ZERO_ENTRY   NULL
#define NDR64_UNUSED_TABLE_ENTRY( number, tokenname ) ,NULL
#define NDR64_UNUSED_TABLE_ENTRY_NOSYM( number ) ,NULL

#define NDR64_TABLE_ENTRY( number, tokenname, marshall, embeddedmarshall, unmarshall, embeddedunmarshall, buffersize, embeddedbuffersize, memsize, embeddedmemsize, free, embeddedfree, typeflags ) \
   ,memsize

#define NDR64_SIMPLE_TYPE_TABLE_ENTRY( number, tokenname, buffersize, memorysize) \
   ,Ndr64UDTSimpleTypeMemorySize

#include "tokntbl.h"


C_ASSERT( sizeof(Ndr64MemSizeRoutinesTable)/sizeof(PNDR64_MEM_SIZE_ROUTINE) == 256 );

#undef NDR64_BEGIN_TABLE
#undef NDR64_TABLE_ENTRY

#define NDR64_BEGIN_TABLE  \
PNDR64_MEM_SIZE_ROUTINE extern const Ndr64EmbeddedMemSizeRoutinesTable[] = \
{

#define NDR64_TABLE_ENTRY( number, tokenname, marshall, embeddedmarshall, unmarshall, embeddedunmarshall, buffersize, embeddedbuffersize, memsize, embeddedmemsize, free, embeddedfree, typeflags ) \
   ,embeddedmemsize

#include "tokntbl.h"


C_ASSERT( sizeof(Ndr64EmbeddedMemSizeRoutinesTable)/sizeof(PNDR64_MEM_SIZE_ROUTINE) == 256 );



