mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3028 lines
76 KiB
3028 lines
76 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Copyright (c) 1993 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
endian.c
|
|
|
|
Abstract :
|
|
|
|
This file contains the routines called by MIDL 2.0 stubs and the
|
|
interpreter to perform endian, floating pointer, and character conversions.
|
|
|
|
Author :
|
|
|
|
David Kays dkays December 1993.
|
|
|
|
Revision History :
|
|
|
|
---------------------------------------------------------------------*/
|
|
|
|
#include "cvt.h"
|
|
#include "ndrp.h"
|
|
#include "interp2.h"
|
|
|
|
//
|
|
// Conversion routine table.
|
|
//
|
|
const
|
|
PCONVERT_ROUTINE ConvertRoutinesTable[] =
|
|
{
|
|
NdrPointerConvert,
|
|
NdrPointerConvert,
|
|
NdrPointerConvert,
|
|
NdrPointerConvert,
|
|
|
|
NdrSimpleStructConvert,
|
|
NdrSimpleStructConvert,
|
|
NdrConformantStructConvert,
|
|
NdrConformantStructConvert,
|
|
NdrConformantStructConvert, // same as FC_CARRAY
|
|
|
|
NdrComplexStructConvert,
|
|
|
|
NdrConformantArrayConvert,
|
|
NdrConformantVaryingArrayConvert,
|
|
NdrFixedArrayConvert,
|
|
NdrFixedArrayConvert,
|
|
NdrVaryingArrayConvert,
|
|
NdrVaryingArrayConvert,
|
|
|
|
NdrComplexArrayConvert,
|
|
|
|
NdrConformantStringConvert,
|
|
NdrConformantStringConvert,
|
|
NdrConformantStringConvert,
|
|
NdrConformantStringConvert,
|
|
|
|
NdrNonConformantStringConvert,
|
|
NdrNonConformantStringConvert,
|
|
NdrNonConformantStringConvert,
|
|
NdrNonConformantStringConvert,
|
|
|
|
NdrEncapsulatedUnionConvert,
|
|
NdrNonEncapsulatedUnionConvert,
|
|
|
|
NdrByteCountPointerConvert,
|
|
|
|
NdrXmitOrRepAsConvert, // transmit as
|
|
NdrXmitOrRepAsConvert, // represent as
|
|
|
|
NdrInterfacePointerConvert,
|
|
|
|
NdrContextHandleConvert,
|
|
|
|
NdrHardStructConvert,
|
|
|
|
NdrXmitOrRepAsConvert, // transmit as ptr
|
|
NdrXmitOrRepAsConvert, // represent as ptr
|
|
|
|
NdrUserMarshalConvert
|
|
|
|
};
|
|
|
|
const
|
|
PCONVERT_ROUTINE * pfnConvertRoutines = &ConvertRoutinesTable[-FC_RP];
|
|
|
|
//
|
|
// Array for ebcdic to ascii conversions. Use ebcdic value as index into
|
|
// array whose corresponding value is the correct ascii value.
|
|
//
|
|
unsigned char EbcdicToAscii[] =
|
|
{
|
|
0x20, 0x01, 0x02, 0x03, 0x3f, 0x09, 0x3f, 0x10,
|
|
0x3f, 0x3f, 0x3f, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
0x10, 0x11, 0x12, 0x13, 0x3f, 0x3f, 0x08, 0x3f,
|
|
0x18, 0x19, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x3f, 0x3f, 0x1c, 0x3f, 0x3f, 0x3f, 0x17, 0x1b,
|
|
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x05, 0x06, 0x07,
|
|
0x00, 0x00, 0x16, 0x00, 0x3f, 0x1e, 0x3f, 0x04,
|
|
0x3f, 0x3f, 0x3f, 0x3f, 0x14, 0x15, 0x00, 0x1a,
|
|
0x20, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x3f, 0x3f, 0x3f, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
|
|
0x26, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x3f, 0x3f, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e,
|
|
0x2d, 0x2f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x3f, 0x3f, 0x3f, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
|
|
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x3f, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
|
|
0x3f, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
|
0x68, 0x69, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x3f, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
|
|
0x71, 0x72, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x3f, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
|
|
0x79, 0x7a, 0x3f, 0x3f, 0x3f, 0x5b, 0x3f, 0x3f,
|
|
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x5d, 0x3f, 0x3f,
|
|
0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
|
0x48, 0x49, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
|
|
0x51, 0x52, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x5c, 0x3f, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
|
0x59, 0x5a, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
|
0x38, 0x39, 0x7c, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f
|
|
};
|
|
|
|
#if defined( DOS ) || defined( WIN )
|
|
#pragma code_seg( "NDR_1" )
|
|
#endif
|
|
|
|
|
|
void RPC_ENTRY
|
|
NdrConvert2(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
long NumberParams )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
This is the new stub and interpreter entry point for endian conversion.
|
|
This routine handles the conversion of all parameters in a procedure.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Format string description of procedure's parameters.
|
|
NumberParams - The number of parameters in the procedure.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBuffer;
|
|
PFORMAT_STRING pFormatComplex;
|
|
PFORMAT_STRING pFormatTypes;
|
|
PPARAM_DESCRIPTION Params;
|
|
int fClientSide;
|
|
long n;
|
|
|
|
//
|
|
// Check if we need to do any converting.
|
|
//
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation & (unsigned long)0X0000FFFF) ==
|
|
NDR_LOCAL_DATA_REPRESENTATION )
|
|
return;
|
|
|
|
// Save the original buffer pointer to restore later.
|
|
pBuffer = pStubMsg->Buffer;
|
|
|
|
// Get the type format string.
|
|
pFormatTypes = pStubMsg->StubDesc->pFormatTypes;
|
|
|
|
fClientSide = pStubMsg->IsClient;
|
|
|
|
Params = (PPARAM_DESCRIPTION) pFormat;
|
|
|
|
for ( n = 0; n < NumberParams; n++ )
|
|
{
|
|
if ( fClientSide )
|
|
{
|
|
if ( ! Params[n].ParamAttr.IsOut )
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if ( ! Params[n].ParamAttr.IsIn )
|
|
continue;
|
|
}
|
|
|
|
if ( Params[n].ParamAttr.IsPipe )
|
|
continue;
|
|
|
|
if ( Params[n].ParamAttr.IsBasetype )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, Params[n].SimpleType.Type );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Complex type or pointer to complex type.
|
|
//
|
|
pFormatComplex = pFormatTypes + Params[n].TypeOffset;
|
|
|
|
(*pfnConvertRoutines[ROUTINE_INDEX(*pFormatComplex)])
|
|
( pStubMsg,
|
|
pFormatComplex,
|
|
FALSE );
|
|
}
|
|
|
|
pStubMsg->Buffer = pBuffer;
|
|
}
|
|
|
|
|
|
void RPC_ENTRY
|
|
NdrConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
This is the stub and interpreter entry point for endian conversion.
|
|
This routine handles the conversion of all parameters in a procedure.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Format string description of procedure's parameters.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBuffer;
|
|
PFORMAT_STRING pFormatComplex;
|
|
PFORMAT_STRING pFormatTypes;
|
|
int fClientSide;
|
|
|
|
//
|
|
// Check if we need to do any converting.
|
|
//
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation & (unsigned long)0X0000FFFF) ==
|
|
NDR_LOCAL_DATA_REPRESENTATION )
|
|
return;
|
|
|
|
// Save the original buffer pointer to restore later.
|
|
pBuffer = pStubMsg->Buffer;
|
|
|
|
// Get the type format string.
|
|
pFormatTypes = pStubMsg->StubDesc->pFormatTypes;
|
|
|
|
fClientSide = pStubMsg->IsClient;
|
|
|
|
for ( ;; )
|
|
{
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_IN_PARAM :
|
|
case FC_IN_PARAM_NO_FREE_INST :
|
|
if ( fClientSide )
|
|
{
|
|
pFormat += 4;
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
|
|
case FC_IN_PARAM_BASETYPE :
|
|
if ( ! fClientSide )
|
|
NdrSimpleTypeConvert( pStubMsg, pFormat[1] );
|
|
|
|
pFormat += 2;
|
|
continue;
|
|
|
|
case FC_IN_OUT_PARAM :
|
|
break;
|
|
|
|
case FC_OUT_PARAM :
|
|
if ( ! fClientSide )
|
|
{
|
|
pFormat += 4;
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
|
|
case FC_RETURN_PARAM :
|
|
if ( ! fClientSide )
|
|
{
|
|
pStubMsg->Buffer = pBuffer;
|
|
return;
|
|
}
|
|
|
|
break;
|
|
|
|
case FC_RETURN_PARAM_BASETYPE :
|
|
if ( fClientSide )
|
|
NdrSimpleTypeConvert( pStubMsg, pFormat[1] );
|
|
|
|
// We're done. Fall through.
|
|
|
|
default :
|
|
pStubMsg->Buffer = pBuffer;
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Complex type or pointer to complex type.
|
|
//
|
|
pFormatComplex = pFormatTypes + *((ushort *)(pFormat + 2));
|
|
|
|
(*pfnConvertRoutines[ROUTINE_INDEX(*pFormatComplex)])
|
|
( pStubMsg,
|
|
pFormatComplex,
|
|
FALSE );
|
|
|
|
if ( *pFormat == FC_RETURN_PARAM )
|
|
{
|
|
pStubMsg->Buffer = pBuffer;
|
|
return;
|
|
}
|
|
|
|
pFormat += 4;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrSimpleTypeConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar FormatChar )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a simple type.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
FormatChar - Simple type format character.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
switch ( FormatChar )
|
|
{
|
|
case FC_CHAR :
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation & NDR_CHAR_REP_MASK) ==
|
|
NDR_EBCDIC_CHAR )
|
|
*(pStubMsg->Buffer) = EbcdicToAscii[*(pStubMsg->Buffer)];
|
|
|
|
pStubMsg->Buffer += 1;
|
|
break;
|
|
|
|
case FC_BYTE :
|
|
case FC_SMALL :
|
|
case FC_USMALL :
|
|
pStubMsg->Buffer++;
|
|
break;
|
|
|
|
case FC_SHORT :
|
|
case FC_USHORT :
|
|
case FC_WCHAR :
|
|
case FC_ENUM16 :
|
|
ALIGN(pStubMsg->Buffer,1);
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation & NDR_INT_REP_MASK) !=
|
|
NDR_LOCAL_ENDIAN )
|
|
{
|
|
ushort temp;
|
|
|
|
temp = (*((ushort *)pStubMsg->Buffer) & MASK_A_) >> 8 |
|
|
(*((ushort *)pStubMsg->Buffer) & MASK__B) << 8 ;
|
|
|
|
*((ushort *)pStubMsg->Buffer) = temp;
|
|
}
|
|
|
|
pStubMsg->Buffer += 2;
|
|
break;
|
|
|
|
case FC_LONG :
|
|
case FC_ULONG :
|
|
case FC_POINTER :
|
|
case FC_ENUM32 :
|
|
case FC_ERROR_STATUS_T:
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation & NDR_INT_REP_MASK) !=
|
|
NDR_LOCAL_ENDIAN )
|
|
{
|
|
ulong temp;
|
|
|
|
//
|
|
// First apply the transformation: ABCD => BADC
|
|
//
|
|
temp = (*((ulong *)pStubMsg->Buffer) & MASK_A_C_) >> 8 |
|
|
(*((ulong *)pStubMsg->Buffer) & MASK__B_D) << 8 ;
|
|
|
|
//
|
|
// Now swap the left and right halves of the target long word
|
|
// achieving full swap: BADC => DCBA
|
|
//
|
|
temp = (temp & MASK_AB__) >> 16 | (temp & MASK___CD) << 16;
|
|
|
|
*((ulong *)pStubMsg->Buffer) = temp;
|
|
}
|
|
|
|
pStubMsg->Buffer += 4;
|
|
break;
|
|
|
|
case FC_HYPER :
|
|
ALIGN(pStubMsg->Buffer,7);
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation & NDR_INT_REP_MASK) !=
|
|
NDR_LOCAL_ENDIAN )
|
|
{
|
|
ulong temp[2];
|
|
|
|
//
|
|
//.. We are doing ABCDEFGH -> HGFEDCBA
|
|
//.. We start with ABCD going as DCBA into second word of Target
|
|
//
|
|
|
|
//
|
|
// First apply the transformation: ABCD => BADC
|
|
//
|
|
temp[0] = (*((ulong *)pStubMsg->Buffer) & MASK_A_C_) >> 8 |
|
|
(*((ulong *)pStubMsg->Buffer) & MASK__B_D) << 8 ;
|
|
|
|
//
|
|
// Now swap the left and right halves of the Target long word
|
|
// achieving full swap: BADC => DCBA
|
|
//
|
|
temp[1] = (temp[0] & MASK_AB__) >> 16 |
|
|
(temp[0] & MASK___CD) << 16 ;
|
|
|
|
//
|
|
//.. What's left is EFGH going into first word at Target
|
|
//
|
|
|
|
//
|
|
// First apply the transformation: EFGH => FEHG
|
|
//
|
|
temp[0] =
|
|
(*((ulong *)(pStubMsg->Buffer + 4)) & MASK_A_C_) >> 8 |
|
|
(*((ulong *)(pStubMsg->Buffer + 4)) & MASK__B_D) << 8 ;
|
|
|
|
//
|
|
// Now swap the left and right halves of the Target long word
|
|
// achieving full swap: FEHG => HGFE
|
|
//
|
|
temp[0] = (temp[0] & MASK_AB__) >> 16 |
|
|
(temp[0] & MASK___CD) << 16 ;
|
|
|
|
//
|
|
// Now copy the new hyper into the buffer.
|
|
//
|
|
*((ulong *)pStubMsg->Buffer) = temp[0];
|
|
*((ulong *)(pStubMsg->Buffer + 4)) = temp[1];
|
|
}
|
|
|
|
pStubMsg->Buffer += 8;
|
|
break;
|
|
|
|
//
|
|
// VAX floating point conversions is the only one supported.
|
|
//
|
|
|
|
case FC_FLOAT :
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation & NDR_FLOAT_INT_MASK)
|
|
!= NDR_LOCAL_ENDIAN_IEEE_REP )
|
|
{
|
|
BOOL fEndianessDone = FALSE;
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation &
|
|
NDR_INT_REP_MASK) != NDR_LOCAL_ENDIAN )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
fEndianessDone = TRUE;
|
|
}
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation &
|
|
NDR_FLOAT_REP_MASK) != NDR_IEEE_FLOAT )
|
|
{
|
|
if ( fEndianessDone )
|
|
pStubMsg->Buffer -= 4;
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation &
|
|
NDR_FLOAT_REP_MASK) == NDR_VAX_FLOAT )
|
|
{
|
|
cvt_vax_f_to_ieee_single( pStubMsg->Buffer,
|
|
0,
|
|
pStubMsg->Buffer );
|
|
pStubMsg->Buffer += 4;
|
|
}
|
|
else
|
|
RpcRaiseException(RPC_X_BAD_STUB_DATA);
|
|
}
|
|
}
|
|
else
|
|
pStubMsg->Buffer += 4;
|
|
|
|
break;
|
|
|
|
case FC_DOUBLE :
|
|
ALIGN(pStubMsg->Buffer,7);
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation & NDR_FLOAT_INT_MASK)
|
|
!= NDR_LOCAL_ENDIAN_IEEE_REP )
|
|
{
|
|
BOOL fEndianessDone = FALSE;
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation &
|
|
NDR_INT_REP_MASK) != NDR_LOCAL_ENDIAN )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_HYPER );
|
|
fEndianessDone = TRUE;
|
|
}
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation &
|
|
NDR_FLOAT_REP_MASK) != NDR_IEEE_FLOAT )
|
|
{
|
|
if ( fEndianessDone )
|
|
pStubMsg->Buffer -= 8;
|
|
|
|
if ( (pStubMsg->RpcMsg->DataRepresentation &
|
|
NDR_FLOAT_REP_MASK) == NDR_VAX_FLOAT )
|
|
{
|
|
cvt_vax_g_to_ieee_double( pStubMsg->Buffer,
|
|
0,
|
|
pStubMsg->Buffer );
|
|
pStubMsg->Buffer += 8;
|
|
}
|
|
else
|
|
RpcRaiseException(RPC_X_BAD_STUB_DATA);
|
|
}
|
|
}
|
|
else
|
|
pStubMsg->Buffer += 8;
|
|
|
|
break;
|
|
|
|
case FC_IGNORE:
|
|
break;
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrSimpleTypeConvert : Bad format type");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrPointerConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a top level pointer and the data it points to.
|
|
Pointers embedded in structures, arrays, or unions call
|
|
NdrpPointerConvert directly.
|
|
|
|
Used for FC_RP, FC_UP, FC_FP, FC_OP.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Pointer's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBufferMark;
|
|
|
|
if ( *pFormat != FC_RP )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
if ( fEmbeddedPointerPass )
|
|
pStubMsg->Buffer += 4;
|
|
else
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
}
|
|
else
|
|
pBufferMark = 0;
|
|
|
|
NdrpPointerConvert( pStubMsg,
|
|
pBufferMark,
|
|
pFormat );
|
|
}
|
|
|
|
|
|
void
|
|
NdrpPointerConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar * pBufferMark,
|
|
PFORMAT_STRING pFormat )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Private routine for converting a pointer and the data it points to.
|
|
This is the entry point for pointers embedded in structures, arrays,
|
|
and unions.
|
|
|
|
Used for FC_RP, FC_UP, FC_FP, FC_OP.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Pointer's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_RP :
|
|
break;
|
|
|
|
case FC_UP :
|
|
case FC_OP :
|
|
if ( ! *((long *)pBufferMark) )
|
|
return;
|
|
|
|
break;
|
|
|
|
case FC_FP :
|
|
//
|
|
// Check if we have already seen this full pointer ref id during
|
|
// endian coversion. If so then we are finished with this pointer.
|
|
//
|
|
//
|
|
if ( NdrFullPointerQueryRefId( pStubMsg->FullPtrXlatTables,
|
|
*((ulong *)pBufferMark),
|
|
FULL_POINTER_CONVERTED,
|
|
0 ) )
|
|
return;
|
|
|
|
break;
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrpPointerConvert : Bad format type");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Pointer to complex type.
|
|
//
|
|
if ( ! SIMPLE_POINTER(pFormat[1]) )
|
|
{
|
|
pFormat += 2;
|
|
|
|
//
|
|
// Get the pointee format string.
|
|
// Cast must be to a signed short since some offsets are negative.
|
|
//
|
|
pFormat += *((signed short *)pFormat);
|
|
}
|
|
else
|
|
{
|
|
switch ( pFormat[2] )
|
|
{
|
|
case FC_C_CSTRING :
|
|
case FC_C_BSTRING :
|
|
case FC_C_WSTRING :
|
|
case FC_C_SSTRING :
|
|
// Get to the string's description.
|
|
pFormat += 2;
|
|
break;
|
|
|
|
default :
|
|
// Else it's a pointer to a simple type.
|
|
NdrSimpleTypeConvert( pStubMsg,
|
|
pFormat[2] );
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now lookup the proper conversion routine.
|
|
//
|
|
(*pfnConvertRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
|
pFormat,
|
|
FALSE );
|
|
}
|
|
|
|
|
|
void
|
|
NdrSimpleStructConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a simple structure.
|
|
|
|
Used for FC_STRUCT and FC_PSTRUCT.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Structure's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBufferMark;
|
|
PFORMAT_STRING pFormatLayout;
|
|
|
|
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
|
|
|
// Remember where the struct starts in the buffer.
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
pFormat += 4;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
pFormatLayout = NdrpSkipPointerLayout( pFormat );
|
|
else
|
|
pFormatLayout = pFormat;
|
|
|
|
//
|
|
// Convert or skip the flat part of the structure.
|
|
//
|
|
NdrpStructConvert( pStubMsg,
|
|
pFormatLayout,
|
|
0,
|
|
fEmbeddedPointerPass );
|
|
|
|
//
|
|
// Convert the pointers. This will do nothing if
|
|
// pStubMsg->IgnoreEmbeddedPointers is TRUE.
|
|
//
|
|
if ( *pFormat == FC_PP )
|
|
{
|
|
pStubMsg->BufferMark = pBufferMark;
|
|
|
|
NdrpEmbeddedPointerConvert( pStubMsg, pFormat );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrConformantStructConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a conformant or conformant varying structure.
|
|
|
|
Used for FC_CSTRUCT, FC_CPSTRUCT and FC_CVSTRUCT.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Structure's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PPRIVATE_CONVERT_ROUTINE pfnConvert;
|
|
uchar * pBufferMark;
|
|
PFORMAT_STRING pFormatArray;
|
|
PFORMAT_STRING pFormatLayout;
|
|
long MaxCount;
|
|
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
//
|
|
// Convert conformance count if needed.
|
|
//
|
|
if ( fEmbeddedPointerPass )
|
|
pStubMsg->Buffer += 4;
|
|
else
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
|
|
// Get the conformance count.
|
|
MaxCount = *((long *)(pStubMsg->Buffer - 4));
|
|
|
|
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
|
|
|
// Remember where the struct starts in the buffer.
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
pFormat += 4;
|
|
|
|
// Get the array description.
|
|
pFormatArray = pFormat + *((signed short *)pFormat);
|
|
|
|
pFormat += 2;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
pFormatLayout = NdrpSkipPointerLayout( pFormat );
|
|
else
|
|
pFormatLayout = pFormat;
|
|
|
|
//
|
|
// Convert or skip the flat part of the structure.
|
|
//
|
|
NdrpStructConvert( pStubMsg,
|
|
pFormatLayout,
|
|
0,
|
|
fEmbeddedPointerPass );
|
|
|
|
switch ( *pFormatArray )
|
|
{
|
|
case FC_CARRAY :
|
|
pfnConvert = NdrpConformantArrayConvert;
|
|
break;
|
|
case FC_CVARRAY :
|
|
pfnConvert = NdrpConformantVaryingArrayConvert;
|
|
break;
|
|
default :
|
|
//
|
|
// Conformant strings, but use the non-conformant string conversion
|
|
// routine since we've already converted the conformant size.
|
|
//
|
|
NdrNonConformantStringConvert( pStubMsg,
|
|
pFormatArray,
|
|
fEmbeddedPointerPass );
|
|
goto CheckPointers;
|
|
}
|
|
|
|
pStubMsg->MaxCount = MaxCount;
|
|
|
|
(*pfnConvert)( pStubMsg,
|
|
pFormatArray,
|
|
fEmbeddedPointerPass );
|
|
|
|
CheckPointers:
|
|
|
|
//
|
|
// Convert the pointers. This will do nothing if
|
|
// pStubMsg->IgnoreEmbeddedPointers is TRUE.
|
|
//
|
|
if ( *pFormat == FC_PP )
|
|
{
|
|
pStubMsg->BufferMark = pBufferMark;
|
|
|
|
NdrpEmbeddedPointerConvert( pStubMsg, pFormat );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrHardStructConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a hard structure.
|
|
|
|
Used for FC_HARD_STRUCT.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Structure's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
pStubMsg->PointerBufferMark
|
|
! NULL indicates embedding in a complex struct.
|
|
NULL indicates top level or embedding in something else
|
|
|
|
So the algoritm here is
|
|
if the hard struct is in a complex struct, then the complex
|
|
struct is issuing two calls, first with FALSE, then with TRUE.
|
|
if the hard struct is NOT in a complex struct then there is only
|
|
one call and the union has to be called explicitely.
|
|
--*/
|
|
{
|
|
uchar * BufferSaved;
|
|
|
|
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
|
|
|
// Remember where the struct starts in the buffer.
|
|
BufferSaved = pStubMsg->Buffer;
|
|
|
|
//
|
|
// Convert or skip the flat part of the structure.
|
|
//
|
|
NdrpStructConvert( pStubMsg,
|
|
pFormat + 16,
|
|
0, // no pointer layout
|
|
fEmbeddedPointerPass );
|
|
|
|
if ( ! pStubMsg->PointerBufferMark )
|
|
{
|
|
//
|
|
// Convert the pointers. This will do nothing if
|
|
// pStubMsg->IgnoreEmbeddedPointers is TRUE.
|
|
//
|
|
// See if we have a union, as the pointer may be only there.
|
|
//
|
|
pFormat += 14;
|
|
if ( *((short *)pFormat) )
|
|
{
|
|
//
|
|
// Set the pointer to the beginning of the union:
|
|
// the copy size is the struct buffer size without the union.
|
|
//
|
|
|
|
pStubMsg->Buffer = BufferSaved + *((short *)&pFormat[-4]);
|
|
|
|
pFormat += *((short *)pFormat);
|
|
|
|
(*pfnConvertRoutines[ ROUTINE_INDEX( *pFormat )])
|
|
( pStubMsg,
|
|
pFormat,
|
|
TRUE ); // convert the pointer only, if any.
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrComplexStructConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a complex structure.
|
|
|
|
Used for FC_BOGUS_STRUCT.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Structure's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBuffer;
|
|
uchar * pBufferMark;
|
|
PFORMAT_STRING pFormatSave;
|
|
PFORMAT_STRING pFormatArray;
|
|
PFORMAT_STRING pFormatPointers;
|
|
uchar Alignment;
|
|
BOOL fComplexEntry;
|
|
|
|
pFormatSave = pFormat;
|
|
|
|
// Remember the beginning of the structure in the buffer.
|
|
pBuffer = pStubMsg->Buffer;
|
|
|
|
Alignment = pFormat[1];
|
|
|
|
pFormat += 4;
|
|
|
|
// Get conformant array description.
|
|
if ( *((ushort *)pFormat) )
|
|
{
|
|
long Dimensions;
|
|
long i;
|
|
|
|
pFormatArray = pFormat + *((signed short *)pFormat);
|
|
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
// Mark the conformance start.
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
Dimensions = NdrpArrayDimensions( pFormatArray, FALSE );
|
|
|
|
if ( ! fEmbeddedPointerPass )
|
|
{
|
|
for ( i = 0; i < Dimensions; i++ )
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
}
|
|
else
|
|
pStubMsg->Buffer += Dimensions * 4;
|
|
}
|
|
else
|
|
{
|
|
pFormatArray = 0;
|
|
pBufferMark = 0;
|
|
}
|
|
|
|
pFormat += 2;
|
|
|
|
// Get pointer layout description.
|
|
if ( *((ushort *)pFormat) )
|
|
pFormatPointers = pFormat + *((ushort *)pFormat);
|
|
else
|
|
pFormatPointers = 0;
|
|
|
|
pFormat += 2;
|
|
|
|
ALIGN(pStubMsg->Buffer,Alignment);
|
|
|
|
//
|
|
// Check if we are not embedded inside of another complex struct or array.
|
|
//
|
|
if ( fComplexEntry = (pStubMsg->PointerBufferMark == 0) )
|
|
{
|
|
//
|
|
// Mark PointerBufferMark with a non-null value so complex array's
|
|
// or struct's which we embed will get fComplexEntry = false.
|
|
//
|
|
pStubMsg->PointerBufferMark = (uchar *) 0xffffffff;
|
|
}
|
|
|
|
//
|
|
// Convert the flat part of the structure.
|
|
//
|
|
NdrpStructConvert( pStubMsg,
|
|
pFormat,
|
|
pFormatPointers,
|
|
fEmbeddedPointerPass );
|
|
|
|
//
|
|
// Convert any conformant array, if present.
|
|
//
|
|
if ( pFormatArray )
|
|
{
|
|
PPRIVATE_CONVERT_ROUTINE pfnConvert;
|
|
uchar fOldIgnore;
|
|
|
|
switch ( *pFormatArray )
|
|
{
|
|
case FC_CARRAY :
|
|
pfnConvert = NdrpConformantArrayConvert;
|
|
break;
|
|
|
|
case FC_CVARRAY :
|
|
pfnConvert = NdrpConformantVaryingArrayConvert;
|
|
break;
|
|
|
|
case FC_BOGUS_ARRAY :
|
|
pfnConvert = NdrpComplexArrayConvert;
|
|
break;
|
|
|
|
// case FC_C_CSTRING :
|
|
// case FC_C_BSTRING :
|
|
// case FC_C_SSTRING :
|
|
// case FC_C_WSTRING :
|
|
|
|
default :
|
|
//
|
|
// Call the non-conformant string routine since we've
|
|
// already handled the conformance count.
|
|
//
|
|
NdrNonConformantStringConvert( pStubMsg,
|
|
pFormatArray,
|
|
fEmbeddedPointerPass );
|
|
goto ComplexConvertPointers;
|
|
}
|
|
|
|
fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
|
|
|
|
//
|
|
// Ignore embedded pointers if fEmbeddedPointerPass is false.
|
|
//
|
|
pStubMsg->IgnoreEmbeddedPointers = ! fEmbeddedPointerPass;
|
|
|
|
// Get the outermost max count for unidimensional arrays.
|
|
pStubMsg->MaxCount = *((ulong *)pBufferMark);
|
|
|
|
// Mark where conformance count(s) are.
|
|
pStubMsg->BufferMark = pBufferMark;
|
|
|
|
(*pfnConvert)( pStubMsg,
|
|
pFormatArray,
|
|
fEmbeddedPointerPass );
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
|
}
|
|
|
|
ComplexConvertPointers:
|
|
|
|
//
|
|
// Now start a conversion pass for embedded pointers for the complex
|
|
// struct if we're not embedded inside of another complex struct or array.
|
|
//
|
|
if ( ! fEmbeddedPointerPass && fComplexEntry )
|
|
{
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pBuffer;
|
|
|
|
NdrComplexStructConvert( pStubMsg,
|
|
pFormatSave,
|
|
TRUE );
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrpStructConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
PFORMAT_STRING pFormatPointers,
|
|
uchar fEmbeddedPointerPass )
|
|
/*++
|
|
|
|
Routine description :
|
|
|
|
Converts any type of structure given a structure layout.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Structure layout format string description.
|
|
pFormatPointers - Pointer layout if the structure is complex,
|
|
otherwise 0.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PFORMAT_STRING pFormatComplex;
|
|
uchar fOldIgnore;
|
|
|
|
fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
|
|
|
|
//
|
|
// We set this to TRUE during our first pass over the structure in which
|
|
// we convert the flat part of the structure and ignore embedded pointers.
|
|
// This will make any embedded ok structs or ok arrays ignore their
|
|
// embedded pointers until the second pass to convert embedded pointers
|
|
// (at which point we'll have the correct buffer pointer to where the
|
|
// pointees are).
|
|
//
|
|
pStubMsg->IgnoreEmbeddedPointers = ! fEmbeddedPointerPass;
|
|
|
|
//
|
|
// Convert the structure member by member.
|
|
//
|
|
for ( ; ; pFormat++ )
|
|
{
|
|
switch ( *pFormat )
|
|
{
|
|
//
|
|
// simple types
|
|
//
|
|
case FC_CHAR :
|
|
case FC_BYTE :
|
|
case FC_SMALL :
|
|
case FC_WCHAR :
|
|
case FC_SHORT :
|
|
case FC_LONG :
|
|
case FC_FLOAT :
|
|
case FC_HYPER :
|
|
case FC_DOUBLE :
|
|
case FC_ENUM16 :
|
|
case FC_ENUM32 :
|
|
if ( fEmbeddedPointerPass )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,SIMPLE_TYPE_ALIGNMENT(*pFormat));
|
|
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE(*pFormat);
|
|
}
|
|
else
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg,
|
|
*pFormat );
|
|
}
|
|
break;
|
|
|
|
case FC_IGNORE :
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
pStubMsg->Buffer += 4;
|
|
break;
|
|
|
|
case FC_POINTER :
|
|
//
|
|
// We can only get an FC_POINTER in a complex struct's layout.
|
|
// Pointers show up as FC_LONG in ok struct's layouts.
|
|
//
|
|
if ( fEmbeddedPointerPass )
|
|
{
|
|
uchar * pBuffer;
|
|
|
|
NDR_ASSERT(pFormatPointers != 0,"Internal error");
|
|
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
pBuffer = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
|
|
NdrpPointerConvert( pStubMsg,
|
|
pBuffer,
|
|
pFormatPointers );
|
|
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pBuffer + 4;
|
|
|
|
pFormatPointers += 4;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg,
|
|
(uchar) FC_LONG );
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Embedded structures
|
|
//
|
|
case FC_EMBEDDED_COMPLEX :
|
|
pFormat += 2;
|
|
|
|
// Get the type's description.
|
|
pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
|
|
|
|
(*pfnConvertRoutines[ROUTINE_INDEX(*pFormatComplex)])
|
|
( pStubMsg,
|
|
pFormatComplex,
|
|
fEmbeddedPointerPass );
|
|
|
|
// Increment the main format string one byte. The loop
|
|
// will increment it one more byte past the offset field.
|
|
pFormat++;
|
|
|
|
break;
|
|
|
|
//
|
|
// Unused for endian conversion.
|
|
//
|
|
case FC_ALIGNM2 :
|
|
case FC_ALIGNM4 :
|
|
case FC_ALIGNM8 :
|
|
break;
|
|
|
|
case FC_STRUCTPAD1 :
|
|
case FC_STRUCTPAD2 :
|
|
case FC_STRUCTPAD3 :
|
|
case FC_STRUCTPAD4 :
|
|
case FC_STRUCTPAD5 :
|
|
case FC_STRUCTPAD6 :
|
|
case FC_STRUCTPAD7 :
|
|
//
|
|
// Only appears at end of struct description, so ignore it.
|
|
//
|
|
break;
|
|
|
|
case FC_PAD :
|
|
break;
|
|
|
|
//
|
|
// Done with layout.
|
|
//
|
|
case FC_END :
|
|
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
|
return;
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrpStructConvert : Bad format type");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrFixedArrayConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a fixed array of any number of dimensions.
|
|
|
|
Used for FC_SMFARRAY and FC_LGFARRAY.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Array's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PFORMAT_STRING pFormatLayout;
|
|
uchar * pBufferMark;
|
|
long Elements;
|
|
uchar fOldIgnore;
|
|
|
|
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
|
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
// Get the number of array elements.
|
|
Elements = NdrpArrayElements( pStubMsg,
|
|
0,
|
|
pFormat );
|
|
|
|
pFormat += (*pFormat == FC_SMFARRAY) ? 4 : 6;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
pFormatLayout = NdrpSkipPointerLayout( pFormat );
|
|
else
|
|
pFormatLayout = pFormat;
|
|
|
|
fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = TRUE;
|
|
|
|
NdrpArrayConvert( pStubMsg,
|
|
pFormatLayout,
|
|
Elements,
|
|
fEmbeddedPointerPass );
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
{
|
|
pStubMsg->BufferMark = pBufferMark;
|
|
|
|
NdrpEmbeddedPointerConvert( pStubMsg, pFormat );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrConformantArrayConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts top level a one dimensional conformant array.
|
|
|
|
Used for FC_CARRAY.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Array's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
if ( fEmbeddedPointerPass )
|
|
pStubMsg->Buffer += 4;
|
|
else
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
|
|
pStubMsg->MaxCount = *((long *)(pStubMsg->Buffer - 4));
|
|
|
|
NdrpConformantArrayConvert( pStubMsg,
|
|
pFormat,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
|
|
|
|
void
|
|
NdrpConformantArrayConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Private routine for converting a one dimensional conformant array.
|
|
This is the entry point for an embedded conformant array.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Array's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PFORMAT_STRING pFormatLayout;
|
|
uchar * pBufferMark;
|
|
long Elements;
|
|
uchar fOldIgnore;
|
|
|
|
Elements = pStubMsg->MaxCount;
|
|
|
|
if ( ! Elements )
|
|
return;
|
|
|
|
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
|
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
pFormat += 8;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
pFormatLayout = NdrpSkipPointerLayout( pFormat );
|
|
else
|
|
pFormatLayout = pFormat;
|
|
|
|
fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = TRUE;
|
|
|
|
NdrpArrayConvert( pStubMsg,
|
|
pFormatLayout,
|
|
Elements,
|
|
fEmbeddedPointerPass );
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
{
|
|
pStubMsg->BufferMark = pBufferMark;
|
|
|
|
pStubMsg->MaxCount = Elements;
|
|
|
|
NdrpEmbeddedPointerConvert( pStubMsg, pFormat );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrConformantVaryingArrayConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a top level one dimensional conformant varying array.
|
|
|
|
Used for FC_CVARRAY.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Array's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
if ( fEmbeddedPointerPass )
|
|
pStubMsg->Buffer += 4;
|
|
else
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
|
|
// We don't care about the max count.
|
|
|
|
NdrpConformantVaryingArrayConvert( pStubMsg,
|
|
pFormat,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
|
|
|
|
void
|
|
NdrpConformantVaryingArrayConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Private routine for converting a one dimensional conformant varying array.
|
|
This is the entry point for converting an embedded conformant varying
|
|
array.
|
|
|
|
Used for FC_CVARRAY.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Array's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PFORMAT_STRING pFormatLayout;
|
|
uchar * pBufferMark;
|
|
long Elements;
|
|
uchar fOldIgnore;
|
|
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
// Convert offset and actual count.
|
|
if ( fEmbeddedPointerPass )
|
|
pStubMsg->Buffer += 8;
|
|
else
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
}
|
|
|
|
Elements = *((long *)(pStubMsg->Buffer - 4));
|
|
|
|
if ( ! Elements )
|
|
return;
|
|
|
|
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
|
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
pFormat += 12;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
pFormatLayout = NdrpSkipPointerLayout( pFormat );
|
|
else
|
|
pFormatLayout = pFormat;
|
|
|
|
fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = TRUE;
|
|
|
|
NdrpArrayConvert( pStubMsg,
|
|
pFormatLayout,
|
|
Elements,
|
|
fEmbeddedPointerPass );
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
{
|
|
pStubMsg->BufferMark = pBufferMark;
|
|
|
|
pStubMsg->MaxCount = Elements;
|
|
|
|
NdrpEmbeddedPointerConvert( pStubMsg, pFormat );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrVaryingArrayConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a top level or embedded varying array.
|
|
|
|
Used for FC_SMVARRAY and FC_LGVARRAY.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Array's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PFORMAT_STRING pFormatLayout;
|
|
uchar * pBufferMark;
|
|
long Elements;
|
|
uchar fOldIgnore;
|
|
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
// Convert offset and actual count.
|
|
if ( fEmbeddedPointerPass )
|
|
pStubMsg->Buffer += 8;
|
|
else
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
}
|
|
|
|
Elements = *((long *)(pStubMsg->Buffer - 4));
|
|
|
|
if ( ! Elements )
|
|
return;
|
|
|
|
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
|
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
pFormat += (*pFormat == FC_SMVARRAY) ? 12 : 16;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
pFormatLayout = NdrpSkipPointerLayout( pFormat );
|
|
else
|
|
pFormatLayout = pFormat;
|
|
|
|
fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = TRUE;
|
|
|
|
NdrpArrayConvert( pStubMsg,
|
|
pFormatLayout,
|
|
Elements,
|
|
fEmbeddedPointerPass );
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
{
|
|
pStubMsg->BufferMark = pBufferMark;
|
|
|
|
pStubMsg->MaxCount = Elements;
|
|
|
|
NdrpEmbeddedPointerConvert( pStubMsg, pFormat );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrComplexArrayConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a top level complex array.
|
|
|
|
Used for FC_BOGUS_STRUCT.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Array's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
long Dimensions;
|
|
long i;
|
|
|
|
if ( ( *((long UNALIGNED *)(pFormat + 4)) != 0xffffffff ) &&
|
|
( pStubMsg->pArrayInfo == 0 ) )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
// Mark where conformance is.
|
|
pStubMsg->BufferMark = pStubMsg->Buffer;
|
|
|
|
Dimensions = NdrpArrayDimensions( pFormat, FALSE );
|
|
|
|
if ( ! fEmbeddedPointerPass )
|
|
{
|
|
for ( i = 0; i < Dimensions; i++ )
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
}
|
|
else
|
|
pStubMsg->Buffer += Dimensions * 4;
|
|
}
|
|
|
|
NdrpComplexArrayConvert( pStubMsg,
|
|
pFormat,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
|
|
|
|
void
|
|
NdrpComplexArrayConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Private routine for converting a complex array. This is the entry
|
|
point for converting an embedded complex array.
|
|
|
|
Used for FC_BOGUS_ARRAY.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Array's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ARRAY_INFO ArrayInfo;
|
|
PARRAY_INFO pArrayInfo;
|
|
PFORMAT_STRING pFormatSave;
|
|
uchar * pBuffer;
|
|
ulong MaxCountSave;
|
|
long Elements;
|
|
long Dimension;
|
|
uchar Alignment;
|
|
BOOL fComplexEntry;
|
|
|
|
//
|
|
// Setup if we are the outer dimension.
|
|
//
|
|
if ( ! pStubMsg->pArrayInfo )
|
|
{
|
|
pStubMsg->pArrayInfo = &ArrayInfo;
|
|
|
|
ArrayInfo.Dimension = 0;
|
|
ArrayInfo.BufferConformanceMark = (unsigned long *)pStubMsg->BufferMark;
|
|
ArrayInfo.BufferVarianceMark = 0;
|
|
}
|
|
|
|
pFormatSave = pFormat;
|
|
|
|
pArrayInfo = pStubMsg->pArrayInfo;
|
|
|
|
Dimension = pArrayInfo->Dimension;
|
|
|
|
// Remember the start of the array in the buffer.
|
|
pBuffer = pStubMsg->Buffer;
|
|
|
|
// Get the array alignment.
|
|
Alignment = pFormat[1];
|
|
|
|
pFormat += 2;
|
|
|
|
// Get number of elements (0 if conformance present).
|
|
Elements = *((ushort *)pFormat)++;
|
|
|
|
//
|
|
// Check for conformance description.
|
|
//
|
|
if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
|
|
{
|
|
Elements = pArrayInfo->BufferConformanceMark[Dimension];
|
|
pStubMsg->MaxCount = Elements;
|
|
}
|
|
|
|
MaxCountSave = pStubMsg->MaxCount;
|
|
|
|
pFormat += 4;
|
|
|
|
//
|
|
// Check for variance description.
|
|
//
|
|
if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
|
|
{
|
|
long TotalDimensions;
|
|
long i;
|
|
|
|
if ( Dimension == 0 )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
pArrayInfo->BufferVarianceMark = (unsigned long *)pStubMsg->Buffer;
|
|
|
|
TotalDimensions = NdrpArrayDimensions( pFormatSave, TRUE );
|
|
|
|
if ( ! fEmbeddedPointerPass )
|
|
{
|
|
//
|
|
// Convert offsets and lengths.
|
|
//
|
|
for ( i = 0; i < TotalDimensions; i++ )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
}
|
|
}
|
|
else
|
|
pStubMsg->Buffer += TotalDimensions * 8;
|
|
}
|
|
|
|
// Overwrite Elements with the actual count.
|
|
Elements = pArrayInfo->BufferVarianceMark[(Dimension * 2) + 1];
|
|
}
|
|
|
|
pFormat += 4;
|
|
|
|
if ( ! Elements )
|
|
goto ComplexArrayConvertEnd;
|
|
|
|
ALIGN(pStubMsg->Buffer,Alignment);
|
|
|
|
//
|
|
// Check if we are not embedded inside of another complex struct or array.
|
|
//
|
|
if ( fComplexEntry = (pStubMsg->PointerBufferMark == 0) )
|
|
{
|
|
//
|
|
// Mark PointerBufferMark with a non-null value so complex array's
|
|
// or struct's which we embed will get fComplexEntry = false.
|
|
//
|
|
pStubMsg->PointerBufferMark = (uchar *) 0xffffffff;
|
|
}
|
|
|
|
NdrpArrayConvert( pStubMsg,
|
|
pFormat,
|
|
Elements,
|
|
fEmbeddedPointerPass );
|
|
|
|
pArrayInfo->Dimension = Dimension;
|
|
|
|
//
|
|
// Now convert pointers in the array members.
|
|
//
|
|
if ( ! fEmbeddedPointerPass && fComplexEntry )
|
|
{
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pBuffer;
|
|
|
|
// Restore BufferMark to handle multiD arrays.
|
|
pStubMsg->BufferMark = (uchar *) ArrayInfo.BufferConformanceMark;
|
|
|
|
// Restore the original max count if we had one.
|
|
pStubMsg->MaxCount = MaxCountSave;
|
|
|
|
NdrpComplexArrayConvert( pStubMsg,
|
|
pFormatSave,
|
|
TRUE );
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
}
|
|
|
|
ComplexArrayConvertEnd:
|
|
|
|
// pArrayInfo must be zero when not valid.
|
|
pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
|
|
}
|
|
|
|
|
|
void
|
|
NdrpArrayConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
long Elements,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Private routine for converting any kind of array.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Array's element format string description.
|
|
Elements - Number of elements in the array.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PCONVERT_ROUTINE pfnConvert;
|
|
uchar * pBufferSave;
|
|
long Dimension;
|
|
long i;
|
|
|
|
// Used for FC_RP only.
|
|
pBufferSave = 0;
|
|
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_EMBEDDED_COMPLEX :
|
|
//
|
|
// Get the complex type description.
|
|
//
|
|
pFormat += 2;
|
|
pFormat += *((signed short UNALIGNED *)pFormat);
|
|
|
|
pfnConvert = pfnConvertRoutines[ROUTINE_INDEX(*pFormat)];
|
|
break;
|
|
|
|
case FC_RP :
|
|
case FC_UP :
|
|
case FC_FP :
|
|
case FC_OP :
|
|
case FC_IP :
|
|
if ( ! fEmbeddedPointerPass )
|
|
return;
|
|
|
|
if ( pStubMsg->PointerBufferMark )
|
|
{
|
|
pBufferSave = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
}
|
|
|
|
pfnConvert = (*pFormat == FC_RP) ?
|
|
(PCONVERT_ROUTINE) NdrpPointerConvert :
|
|
NdrInterfacePointerConvert;
|
|
break;
|
|
|
|
default :
|
|
//
|
|
// Simple type.
|
|
//
|
|
if ( fEmbeddedPointerPass )
|
|
{
|
|
pStubMsg->Buffer += Elements * SIMPLE_TYPE_BUFSIZE(*pFormat);
|
|
return;
|
|
}
|
|
|
|
for ( i = 0; i < Elements; i++ )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg,
|
|
*pFormat );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ( ! IS_ARRAY_OR_STRING(*pFormat) )
|
|
{
|
|
pStubMsg->pArrayInfo = 0;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If we're dealing with a multidimensional fixed array, then pArrayInfo will
|
|
// be NULL. For non-fixed multidimensional arrays it will be valid.
|
|
//
|
|
if ( pStubMsg->pArrayInfo )
|
|
Dimension = pStubMsg->pArrayInfo->Dimension;
|
|
}
|
|
|
|
if ( pfnConvert == (PCONVERT_ROUTINE) NdrpPointerConvert )
|
|
{
|
|
for ( i = 0; i < Elements; i++ )
|
|
{
|
|
NdrpPointerConvert( pStubMsg,
|
|
0,
|
|
pFormat );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0; i < Elements; i++ )
|
|
{
|
|
if ( IS_ARRAY_OR_STRING(*pFormat) && pStubMsg->pArrayInfo )
|
|
pStubMsg->pArrayInfo->Dimension = Dimension + 1;
|
|
|
|
(*pfnConvert)( pStubMsg,
|
|
pFormat,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
}
|
|
|
|
if ( pBufferSave )
|
|
{
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pBufferSave;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrConformantStringConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a top level conformant string.
|
|
|
|
Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
|
|
(NT Beta2 compatability only).
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - String's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// If this is not part of a multidimensional array then we check if we
|
|
// have to convert the max count.
|
|
//
|
|
if ( pStubMsg->pArrayInfo == 0 )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
if ( fEmbeddedPointerPass )
|
|
pStubMsg->Buffer += 4;
|
|
else
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
}
|
|
|
|
NdrNonConformantStringConvert( pStubMsg,
|
|
pFormat,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
|
|
|
|
void
|
|
NdrNonConformantStringConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a non conformant string. This routine is also used to convert
|
|
conformant strings and is also the entry point for an embeded conformant
|
|
string.
|
|
|
|
Used for FC_CSTRING, FC_WSTRING, FC_SSTRING, FC_BSTRING (NT Beta2
|
|
compatability only), FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and
|
|
FC_C_BSTRING (NT Beta2 compatability only).
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - String's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBuffer;
|
|
long Elements;
|
|
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
if ( fEmbeddedPointerPass )
|
|
pStubMsg->Buffer += 8;
|
|
else
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
}
|
|
|
|
Elements = *((long *)(pStubMsg->Buffer - 4));
|
|
|
|
pBuffer = pStubMsg->Buffer;
|
|
|
|
//
|
|
// Convert string. Remember that NdrConformantStringConvert calls this
|
|
// routine too.
|
|
//
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_C_CSTRING :
|
|
case FC_C_BSTRING :
|
|
case FC_CSTRING :
|
|
case FC_BSTRING :
|
|
if ( ((pStubMsg->RpcMsg->DataRepresentation & NDR_CHAR_REP_MASK) ==
|
|
NDR_EBCDIC_CHAR) && ! fEmbeddedPointerPass )
|
|
{
|
|
for ( ; Elements-- > 0; )
|
|
*pBuffer++ = EbcdicToAscii[*pBuffer];
|
|
}
|
|
else
|
|
pBuffer += Elements;
|
|
|
|
break;
|
|
|
|
case FC_C_WSTRING :
|
|
case FC_WSTRING :
|
|
if ( ((pStubMsg->RpcMsg->DataRepresentation & NDR_INT_REP_MASK) !=
|
|
NDR_LOCAL_ENDIAN) && ! fEmbeddedPointerPass )
|
|
{
|
|
for ( ; Elements-- > 0; )
|
|
*((ushort *)pBuffer)++ =
|
|
(*((ushort *)pBuffer) & MASK_A_) >> 8 |
|
|
(*((ushort *)pBuffer) & MASK__B) << 8 ;
|
|
}
|
|
else
|
|
pBuffer += Elements * 2;
|
|
|
|
break;
|
|
|
|
case FC_C_SSTRING :
|
|
case FC_SSTRING :
|
|
// Never anything to convert.
|
|
pBuffer += Elements * pFormat[1];
|
|
break;
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrNonConformantStringConvert : bad format char");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return;
|
|
}
|
|
|
|
pStubMsg->Buffer = pBuffer;
|
|
}
|
|
|
|
|
|
void
|
|
NdrEncapsulatedUnionConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts an encapsulated union.
|
|
|
|
Used for FC_ENCAPSULATED_UNION.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Union's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar SwitchType;
|
|
|
|
SwitchType = LOW_NIBBLE(pFormat[1]);
|
|
|
|
NdrpUnionConvert( pStubMsg,
|
|
pFormat + 4,
|
|
SwitchType,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
|
|
|
|
void
|
|
NdrNonEncapsulatedUnionConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts an non-encapsulated union.
|
|
|
|
Used for FC_NON_ENCAPSULATED_UNION.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Union's format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar SwitchType;
|
|
|
|
SwitchType = pFormat[1];
|
|
|
|
pFormat += 6;
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
pFormat += 2;
|
|
|
|
NdrpUnionConvert( pStubMsg,
|
|
pFormat,
|
|
SwitchType,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
|
|
|
|
void
|
|
NdrpUnionConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar SwitchType,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Private routine for converting a union shared by encapsulated and
|
|
non-encapsulated unions.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Union's format string description.
|
|
SwitchType - Union's format char switch type.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
long SwitchIs;
|
|
long Arms;
|
|
uchar Alignment;
|
|
|
|
//
|
|
// Convert the switch_is().
|
|
//
|
|
if ( fEmbeddedPointerPass )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,SIMPLE_TYPE_ALIGNMENT(SwitchType));
|
|
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE(SwitchType);
|
|
}
|
|
else
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg,
|
|
SwitchType );
|
|
}
|
|
|
|
switch ( SwitchType )
|
|
{
|
|
case FC_SMALL :
|
|
case FC_CHAR :
|
|
SwitchIs = (long) *((char *)(pStubMsg->Buffer - 1));
|
|
break;
|
|
case FC_USMALL :
|
|
SwitchIs = (long) *((uchar *)(pStubMsg->Buffer - 1));
|
|
break;
|
|
case FC_SHORT :
|
|
case FC_ENUM16 :
|
|
SwitchIs = (long) *((short *)(pStubMsg->Buffer - 2));
|
|
break;
|
|
case FC_USHORT :
|
|
case FC_WCHAR :
|
|
SwitchIs = (long) *((ushort *)(pStubMsg->Buffer - 2));
|
|
break;
|
|
case FC_LONG :
|
|
case FC_ULONG :
|
|
case FC_ENUM32 :
|
|
SwitchIs = *((long *)(pStubMsg->Buffer - 4));
|
|
break;
|
|
default :
|
|
NDR_ASSERT(0,"NdrpUnionConvert : bad switch value");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// We're at the union_arms<2> field now, which contains both the
|
|
// Microsoft union aligment value and the number of union arms.
|
|
//
|
|
|
|
//
|
|
// Get the union alignment (0 if this is a DCE union).
|
|
//
|
|
Alignment = (uchar) ( *((ushort *)pFormat) >> 12 );
|
|
|
|
ALIGN(pStubMsg->Buffer,Alignment);
|
|
|
|
//
|
|
// Number of arms is the lower 12 bits.
|
|
//
|
|
Arms = (long) ( *((ushort *)pFormat)++ & 0x0fff);
|
|
|
|
for ( ; Arms; Arms-- )
|
|
{
|
|
if ( *((long UNALIGNED *)pFormat)++ == SwitchIs )
|
|
{
|
|
//
|
|
// Found the right arm, break out.
|
|
//
|
|
break;
|
|
}
|
|
|
|
// Else increment format string.
|
|
pFormat += 2;
|
|
}
|
|
|
|
//
|
|
// Check if we took the default arm and no default arm is specified.
|
|
//
|
|
if ( ! Arms && (*((ushort *)pFormat) == (ushort) 0xffff) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Return if the arm has no description.
|
|
//
|
|
if ( ! *((ushort *)pFormat) )
|
|
return;
|
|
|
|
//
|
|
// Get the arm's description.
|
|
//
|
|
// We need a real solution after beta for simple type arms. This could
|
|
// break if we have a format string larger than about 32K.
|
|
//
|
|
if ( IS_MAGIC_UNION_BYTE(pFormat) )
|
|
{
|
|
// Convert an arm of a simple type
|
|
|
|
#if defined(__RPC_MAC__)
|
|
#define ARM_TYPE_CODE pFormat[1]
|
|
#else
|
|
#define ARM_TYPE_CODE pFormat[0]
|
|
#endif
|
|
|
|
if ( fEmbeddedPointerPass )
|
|
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE( ARM_TYPE_CODE );
|
|
else
|
|
NdrSimpleTypeConvert( pStubMsg, ARM_TYPE_CODE );
|
|
|
|
return;
|
|
}
|
|
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
//
|
|
// We have to do special things for a union arm which is a pointer when
|
|
// we have a union embedded in a complex struct or array.
|
|
//
|
|
if ( IS_BASIC_POINTER(*pFormat) && pStubMsg->PointerBufferMark )
|
|
{
|
|
uchar * pBufferMark;
|
|
|
|
//
|
|
// If we're not in the embedded pointer pass then just convert the
|
|
// pointer value.
|
|
//
|
|
if ( ! fEmbeddedPointerPass )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
|
|
return;
|
|
}
|
|
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
// Align pBufferMark.
|
|
ALIGN(pBufferMark,3);
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
|
|
//
|
|
// We must call the private pointer conversion routine.
|
|
//
|
|
NdrpPointerConvert( pStubMsg,
|
|
pBufferMark,
|
|
pFormat );
|
|
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pBufferMark + 4;
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Union arm of a complex type.
|
|
//
|
|
(*pfnConvertRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
|
pFormat,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
|
|
|
|
void
|
|
NdrByteCountPointerConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a byte count pointer.
|
|
|
|
Used for FC_BYTE_COUNT_POINTER.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Byte count pointer format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
if ( pFormat[1] != FC_PAD )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, pFormat[1] );
|
|
return;
|
|
}
|
|
|
|
pFormat += 6;
|
|
pFormat += *((short *)pFormat);
|
|
|
|
(*pfnConvertRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
|
pFormat,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
|
|
|
|
void
|
|
NdrXmitOrRepAsConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a transmit as or represent as transmited object.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - s format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PFORMAT_STRING pTransFormat;
|
|
|
|
// Transmitted type cannot have pointers in it, as of now,
|
|
// so if this is a embedded pointer pass, just return.
|
|
|
|
if ( fEmbeddedPointerPass )
|
|
return;
|
|
|
|
// Go to the transmitted type and convert it.
|
|
|
|
pFormat += 8;
|
|
pTransFormat = pFormat + *(short *)pFormat;
|
|
|
|
if ( IS_SIMPLE_TYPE( *pTransFormat ) )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, *pTransFormat );
|
|
}
|
|
else
|
|
{
|
|
(*pfnConvertRoutines[ ROUTINE_INDEX( *pTransFormat) ])
|
|
( pStubMsg,
|
|
pTransFormat,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrUserMarshalConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a user_marshal object using the transmissible type description.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - not used
|
|
fEmbeddedPointerPass - not used
|
|
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PFORMAT_STRING pTransFormat;
|
|
|
|
// Go to the transmissible type and convert it.
|
|
|
|
pFormat += 8;
|
|
pTransFormat = pFormat + *(short *)pFormat;
|
|
|
|
if ( IS_SIMPLE_TYPE( *pTransFormat ) )
|
|
{
|
|
if ( fEmbeddedPointerPass )
|
|
return;
|
|
|
|
NdrSimpleTypeConvert( pStubMsg, *pTransFormat );
|
|
}
|
|
else
|
|
{
|
|
// It may have pointers in it.
|
|
|
|
if ( IS_POINTER_TYPE(*pTransFormat) && pStubMsg->PointerBufferMark )
|
|
{
|
|
// Embedded case and the type is a pointer type.
|
|
|
|
if ( fEmbeddedPointerPass )
|
|
{
|
|
uchar * BufferSave = pStubMsg->Buffer;
|
|
|
|
// Get the pointee type and convert it.
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pTransFormat += 2;
|
|
pTransFormat += *(short *)pTransFormat;
|
|
|
|
if ( IS_SIMPLE_TYPE( *pTransFormat ) )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, *pTransFormat );
|
|
}
|
|
else
|
|
{
|
|
// Convert the pointee as if not embedded.
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
(*pfnConvertRoutines[ ROUTINE_INDEX( *pTransFormat) ])
|
|
( pStubMsg,
|
|
pTransFormat,
|
|
FALSE );
|
|
|
|
// Set the pointee marker behind the converted whole.
|
|
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
}
|
|
|
|
// Now step over the original pointer.
|
|
|
|
pStubMsg->Buffer = BufferSave;
|
|
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
pStubMsg->Buffer += 4;
|
|
}
|
|
else
|
|
{
|
|
// Convert the pointer itself only.
|
|
// We can't call ptr convert routine because of the pointee.
|
|
|
|
NdrSimpleTypeConvert( pStubMsg, FC_LONG );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Non embedded pointer type or
|
|
// (embedded or not) a non-pointer or a non-simple type.
|
|
// Just call the appropriate conversion routine.
|
|
|
|
(*pfnConvertRoutines[ ROUTINE_INDEX( *pTransFormat) ])
|
|
( pStubMsg,
|
|
pTransFormat,
|
|
fEmbeddedPointerPass );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
unsigned char __RPC_FAR * RPC_ENTRY
|
|
NdrUserMarshalSimpleTypeConvert(
|
|
unsigned long * pFlags,
|
|
unsigned char * pBuffer,
|
|
unsigned char FormatChar )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts a simple type supplied from a user_marshal unmarshaled routine.
|
|
|
|
Note that this is *not* supposed to be called when the NDR engine walks
|
|
the wire type description to convert.
|
|
|
|
Arguments :
|
|
|
|
pFlags - flags as for user_marshal routines: data rep, context.
|
|
pBuffer - current buffer pointer supplied by the user
|
|
FormatChar - specifies the type
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
MIDL_STUB_MESSAGE StubMsg;
|
|
RPC_MESSAGE RpcMsg;
|
|
|
|
StubMsg.Buffer = pBuffer;
|
|
StubMsg.RpcMsg = & RpcMsg;
|
|
RpcMsg.DataRepresentation = (((USER_MARSHAL_CB *)pFlags)->Flags) >> 16;
|
|
|
|
NdrSimpleTypeConvert( & StubMsg, FormatChar );
|
|
|
|
return ( StubMsg.Buffer );
|
|
}
|
|
|
|
|
|
void
|
|
NdrInterfacePointerConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Converts an interface pointer.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Xmit/Rep as format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBufferSave;
|
|
unsigned long *pLength;
|
|
|
|
// Align for getting the pointer's node id.
|
|
ALIGN( pStubMsg->Buffer, 0x3 );
|
|
|
|
//
|
|
// If we're ignoring embedded pointers then we simply convert the pointer's
|
|
// node id and return. Otherwise, we skip the pointer's node id and
|
|
// continue on to convert the actuall interface pointer.
|
|
//
|
|
if ( ! fEmbeddedPointerPass )
|
|
{
|
|
NdrSimpleTypeConvert( pStubMsg, FC_LONG );
|
|
|
|
if ( pStubMsg->PointerBufferMark != 0 )
|
|
return;
|
|
|
|
pStubMsg->Buffer -= 4;
|
|
}
|
|
|
|
// Skip the pointer's node id, which will already have been converted.
|
|
//
|
|
// Also, we don't have the pointee if the pointer itself is null;
|
|
// An interface pointer behaves like a unique pointer.
|
|
|
|
if ( *((long *)pStubMsg->Buffer)++ == 0 )
|
|
return;
|
|
|
|
//
|
|
// Check if we're handling pointers in a complex struct, and re-set the
|
|
// Buffer pointer if so.
|
|
//
|
|
if ( pStubMsg->PointerBufferMark )
|
|
{
|
|
pBufferSave = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
}
|
|
else
|
|
pBufferSave = 0;
|
|
|
|
//
|
|
// Convert the conformant size and the count field.
|
|
//
|
|
NdrSimpleTypeConvert( pStubMsg, FC_LONG );
|
|
|
|
pLength = (unsigned long *) pStubMsg->Buffer;
|
|
NdrSimpleTypeConvert( pStubMsg, FC_LONG );
|
|
|
|
// Skip over the marshalled interface pointer.
|
|
|
|
pStubMsg->Buffer += *pLength;
|
|
|
|
//
|
|
// Re-set the buffer pointer if needed.
|
|
//
|
|
if ( pBufferSave )
|
|
{
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pBufferSave;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NdrContextHandleConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat,
|
|
uchar fEmbeddedPointerPass )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Conversion routine for context handles, only increments the buffer.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Format string description.
|
|
fEmbeddedPointerPass - TRUE if a pass is being to convert only embedded
|
|
pointers in a struct/array.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
pStubMsg->Buffer += 20;
|
|
}
|
|
|
|
|
|
void
|
|
NdrpEmbeddedPointerConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Private routine for converting an array's or a structure's embedded
|
|
pointers.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Pointer layout format string description.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBufferMark;
|
|
uchar * pBufferPointer;
|
|
uchar * pBufferSave;
|
|
long MaxCountSave;
|
|
|
|
MaxCountSave = pStubMsg->MaxCount;
|
|
|
|
//
|
|
// Return if we're ignoring embedded pointers.
|
|
//
|
|
if ( pStubMsg->IgnoreEmbeddedPointers )
|
|
return;
|
|
|
|
//
|
|
// Check if we're handling pointers in a complex struct, and re-set the
|
|
// Buffer pointer if so.
|
|
//
|
|
if ( pStubMsg->PointerBufferMark )
|
|
{
|
|
pBufferSave = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
}
|
|
else
|
|
pBufferSave = 0;
|
|
|
|
pBufferMark = pStubMsg->BufferMark;
|
|
|
|
//
|
|
// Increment past the FC_PP and pad.
|
|
//
|
|
pFormat += 2;
|
|
|
|
for (;;)
|
|
{
|
|
if ( *pFormat == FC_END )
|
|
{
|
|
if ( pBufferSave )
|
|
{
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pBufferSave;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Check for a repeat pointer.
|
|
if ( *pFormat != FC_NO_REPEAT )
|
|
{
|
|
pStubMsg->MaxCount = MaxCountSave;
|
|
|
|
pFormat = NdrpEmbeddedRepeatPointerConvert( pStubMsg, pFormat );
|
|
|
|
// Continue to the next pointer.
|
|
continue;
|
|
}
|
|
|
|
// Increment to the buffer pointer offset.
|
|
pFormat += 4;
|
|
|
|
pBufferPointer = pBufferMark + *((signed short *)pFormat)++;
|
|
|
|
NdrpPointerConvert( pStubMsg,
|
|
pBufferPointer,
|
|
pFormat );
|
|
|
|
// Increment past the pointer description.
|
|
pFormat += 4;
|
|
}
|
|
}
|
|
|
|
|
|
PFORMAT_STRING
|
|
NdrpEmbeddedRepeatPointerConvert(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
/*--
|
|
|
|
Routine description :
|
|
|
|
Private routine for converting an array's embedded pointers.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Pointer layout format string description.
|
|
|
|
Return :
|
|
|
|
Format string pointer past the array's pointer layout description.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBufPtr;
|
|
uchar * pBufferMark;
|
|
PFORMAT_STRING pFormatSave;
|
|
ulong RepeatCount, RepeatIncrement, Pointers, PointersSave;
|
|
|
|
pBufferMark = pStubMsg->BufferMark;
|
|
|
|
// Get the repeat count.
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_FIXED_REPEAT :
|
|
pFormat += 2;
|
|
|
|
RepeatCount = *((ushort *)pFormat);
|
|
|
|
break;
|
|
|
|
case FC_VARIABLE_REPEAT :
|
|
RepeatCount = pStubMsg->MaxCount;
|
|
|
|
break;
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrpEmbeddedRepeatPointerConvert : bad format");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return 0;
|
|
}
|
|
|
|
pFormat += 2;
|
|
|
|
RepeatIncrement = *((ushort *)pFormat)++;
|
|
|
|
// array_offset is ignored
|
|
pFormat += 2;
|
|
|
|
// Get number of pointers.
|
|
Pointers = *((ushort *)pFormat)++;
|
|
|
|
pFormatSave = pFormat;
|
|
PointersSave = Pointers;
|
|
|
|
for ( ; RepeatCount--;
|
|
pBufferMark += RepeatIncrement )
|
|
{
|
|
pFormat = pFormatSave;
|
|
Pointers = PointersSave;
|
|
|
|
for ( ; Pointers--; )
|
|
{
|
|
pFormat += 2;
|
|
|
|
pBufPtr = pBufferMark + *((signed short *)pFormat)++;
|
|
|
|
NdrpPointerConvert( pStubMsg,
|
|
pBufPtr,
|
|
pFormat );
|
|
|
|
// Increment past the pointer description.
|
|
pFormat += 4;
|
|
}
|
|
}
|
|
|
|
return pFormatSave + PointersSave * 8;
|
|
}
|
|
|
|
|