windows-nt/Source/XPSP1/NT/com/rpc/ndr20/endian.cxx
2020-09-26 16:20:57 +08:00

3381 lines
90 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1993-2000 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"
#include "attack.h"
void
NdrUDTSimpeTypeConvert(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat,
uchar fEmbeddedPointerPass );
void cvt_ibm_f_to_ieee_single( ULONG *ulFP );
void cvt_ibm_d_to_ieee_double( ULONG *ulFP );
//
// Conversion routine table.
//
const
PCONVERT_ROUTINE ConvertRoutinesTable[] =
{
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
NdrUDTSimpeTypeConvert,
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,
0, // NdrHardStructConvert,
NdrXmitOrRepAsConvert, // transmit as ptr
NdrXmitOrRepAsConvert, // represent as ptr
NdrUserMarshalConvert,
0, // FC_PIPE
0, // FC_BLK_HOLE
NdrpRangeConvert
};
extern const
PCONVERT_ROUTINE * pfnConvertRoutines = ConvertRoutinesTable;
void
NdrUDTSimpeTypeConvert(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat,
uchar fEmbeddedPointerPass )
{
if ( fEmbeddedPointerPass )
{
ALIGN(pStubMsg->Buffer,SIMPLE_TYPE_ALIGNMENT(*pFormat));
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE(*pFormat);
}
else
{
NdrSimpleTypeConvert( pStubMsg,
*pFormat );
}
}
//
// Array for ebcdic to ascii conversions. Use ebcdic value as index into
// array whose corresponding value is the correct ascii value.
// The table below maps from IBM 1047 EBCDIC codeset to ANSI 1252 code page.
//
// Note that due to a disagreement among the code page experts both within Msft
// and between Msft and SAG, I could not determine what the proper mapping
// between these 2 code pages should be.
// The following 2 characters where in dispute:
// 0x15 maps to 0x0a - this is most likely right, as per experts' majority vote
// 0x25 maps to 0x85 - no agreement here at all, except that for back mapping
// it cannot be 0x0a again.
// So, I resolved to use the mapping that worked for SAG.
// Ryszardk, Dec 4, 97
//
extern const
unsigned char EbcdicToAscii[] =
{
0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f,
0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x9d, 0x0a, 0x08, 0x87, // 0x15 -> 0x0a
0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1b, // 0x25 -> 0x85
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e,
0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1,
0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4,
0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae,
0xac, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
0xbd, 0xbe, 0xdd, 0xa8, 0xaf, 0x5d, 0xb4, 0xd7,
0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5,
0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff,
0x5c, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f
};
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.IsPartialIgnore )
{
NdrSimpleTypeConvert( pStubMsg, FC_POINTER );
continue;
}
if ( ! Params[n].ParamAttr.IsIn )
continue;
}
if ( Params[n].ParamAttr.IsPipe )
continue;
if ( Params[n].ParamAttr.IsBasetype )
{
NdrSimpleTypeConvert( pStubMsg, Params[n].SimpleType.Type );
}
else
{
//
// 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_PARTIAL_IGNORE_PARAM:
if ( ! fClientSide )
{
NdrSimpleTypeConvert( pStubMsg, FC_LONG );
pFormat += 4;
continue;
}
// Intentional fallthrough
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 :
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + 1 );
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 :
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + 1 );
pStubMsg->Buffer++;
break;
case FC_SHORT :
case FC_USHORT :
case FC_WCHAR :
case FC_ENUM16 :
ALIGN(pStubMsg->Buffer,1);
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + 2 );
if ( (pStubMsg->RpcMsg->DataRepresentation & NDR_INT_REP_MASK) !=
NDR_LOCAL_ENDIAN )
{
*((ushort *)pStubMsg->Buffer) = RtlUshortByteSwap((*(ushort *)pStubMsg->Buffer));
}
pStubMsg->Buffer += 2;
break;
case FC_LONG :
case FC_ULONG :
#if defined(__RPC_WIN64__)
case FC_INT3264:
case FC_UINT3264:
#endif
case FC_POINTER :
case FC_ENUM32 :
case FC_ERROR_STATUS_T:
ALIGN(pStubMsg->Buffer,3);
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + 4 );
if ( (pStubMsg->RpcMsg->DataRepresentation & NDR_INT_REP_MASK) !=
NDR_LOCAL_ENDIAN )
{
*((ulong *)pStubMsg->Buffer) = RtlUlongByteSwap(*(ulong *)pStubMsg->Buffer);
}
pStubMsg->Buffer += 4;
break;
case FC_HYPER :
ALIGN(pStubMsg->Buffer,7);
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + 8 );
if ( (pStubMsg->RpcMsg->DataRepresentation & NDR_INT_REP_MASK) !=
NDR_LOCAL_ENDIAN )
{
*((MIDL_uhyper *)pStubMsg->Buffer) = RtlUlonglongByteSwap(*(MIDL_uhyper *)pStubMsg->Buffer);
}
pStubMsg->Buffer += 8;
break;
//
// VAX floating point conversions is the only one supported.
//
case FC_FLOAT :
ALIGN(pStubMsg->Buffer,3);
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + 4 );
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 if ( (pStubMsg->RpcMsg->DataRepresentation &
NDR_FLOAT_REP_MASK) == NDR_IBM_FLOAT )
{
cvt_ibm_f_to_ieee_single( (ULONG *)pStubMsg->Buffer ) ;
pStubMsg->Buffer += 4 ;
}
else
RpcRaiseException(RPC_X_BAD_STUB_DATA);
}
}
else
pStubMsg->Buffer += 4;
break;
case FC_DOUBLE :
ALIGN(pStubMsg->Buffer,7);
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + 8 );
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 if ( (pStubMsg->RpcMsg->DataRepresentation &
NDR_FLOAT_REP_MASK) == NDR_IBM_FLOAT )
{
cvt_ibm_d_to_ieee_double( (ULONG *)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
NdrpRangeConvert(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat,
uchar fEmbeddedPointerPass )
/*--
Routine description :
--*/
{
uchar FcType = pFormat[1] & 0x0f;
if ( fEmbeddedPointerPass )
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE( FcType );
else
NdrSimpleTypeConvert( pStubMsg, FcType );
}
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 += PTR_WIRE_SIZE;
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.
--*/
{
uchar uFlagsSave;
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.
//
uFlagsSave = pStubMsg->uFlags;
RESET_CONF_FLAGS_TO_STANDALONE(pStubMsg->uFlags);
(*pfnConvertRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
pFormat,
FALSE );
pStubMsg->uFlags = uFlagsSave;
}
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.
Note that for a top level struct it can only be FALSE.
Return :
None.
Notes.
These pearls of wisdom should be recorded for posterity in the main NDR doc,
but just in case, let's have them here as well.
Pointer layout is generated for all structs with pointers, however it is very
much different for bogus structs.
A conformant struct has a pointer layout that's complete, i.e. includes pointers
from conformant arrays in conformant structs. In other words, pointer layout
propagates up the embedding chain of conf structs.
For bogus structs, the layout has only the pointers from the current level
of the bogus struct, the pointers from emebedded bogus structs are with the
embedded struct and the pointers from the array are with the array.
Now, arrays in conf structs don't have their own pointer layout description.
However, top level arrays do have a pointer layout description as appropriate,
and also conformant arrays from bogus structures do have pointer layout.
So the bottom line is that a bogus struct depends on its conformant structure
or on its conformant array to walk the pointers embedded therein. The only
pointers described within the bogus struct are its member level pointers.
Another look at it is that a conformant struct always has a full description of
all the pointers contained within itself, whether in the flat portion or in the
array, and so a conformant struct embedded in a bogus struct can be treated
like a top level struct as far as walking its embedded pointers.
(Then the outer bogus struct cannot walk its array for embedded pointers as it
would if the embedded struct was another bogus struct.)
So, the rule for the conformant size is simple: whoever picks up the size
should also process the array for the flat part.
For the embedded pointers the situation is somewhat unpleasant for the conf
struct inside a bogus struct but we simplify by walking both levels.
The topmost conf struct has to be walked to see the pointers and the bogus
can be walked as the walk would be an empty operation.
--*/
{
PPRIVATE_CONVERT_ROUTINE pfnConvert;
uchar * pStructStart;
PFORMAT_STRING pFormatArray;
PFORMAT_STRING pFormatLayout;
long MaxCount = 0;
uchar fTopLevelStruct, fTopmostConfStruct;
// We can't use pStubMsg->PointerBufferMark == 0 due to dual way ComplexStruct
// routine is called. One is when embedded, another is a recursion for
// embedded pointer pass.
// Top level means a standalone struct, topmost means topmost conf struct,
// that is topmost may be embedded in a bogus struct.
fTopLevelStruct = ! IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
fTopmostConfStruct = ! IS_TOPMOST_CONF_STRUCT( pStubMsg->uFlags );
if ( fTopLevelStruct )
{
ALIGN(pStubMsg->Buffer,3);
// Remember the conformant size position.
pStubMsg->BufferMark = pStubMsg->Buffer;
//
// Convert conformance count if needed.
//
if ( fEmbeddedPointerPass )
pStubMsg->Buffer += 4;
else
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
// Get the conformance count.
// This is valid because a conf struct would have only a single dim array.
MaxCount = *((long *)(pStubMsg->Buffer - 4));
}
else
{
// This will be used only for the topmost case, set by bogus struct.
MaxCount = *((long *)(pStubMsg->BufferMark));
}
ALIGN(pStubMsg->Buffer,pFormat[1]);
// Remember where the struct starts in the buffer.
pStructStart = 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;
// When walking the struct we can descend into embedded conf structs
// so mark that the top level already happened.
//
SET_EMBED_CONF_STRUCT(pStubMsg->uFlags);
SET_TOPMOST_CONF_STRUCT(pStubMsg->uFlags);
//
// Convert or skip the flat part of the structure.
//
NdrpStructConvert( pStubMsg,
pFormatLayout,
0,
fEmbeddedPointerPass );
// Convert the flat part of the array only if top level, as the array
// description gets propagated up the embeddings.
// See a note about propagating array and pointer descriptions above.
if ( fTopmostConfStruct && !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 );
SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
}
CheckPointers:
// Convert embedded pointers for the whole structure including the array
RESET_EMBED_CONF_STRUCT(pStubMsg->uFlags);
RESET_TOPMOST_CONF_STRUCT(pStubMsg->uFlags);
// Convert pointees if the structure is standalone or if it is
// topmost embedded and pointer pass
if ( fTopLevelStruct // standalone && !fEmbeddedPointerPass
||
fEmbeddedPointerPass && fTopmostConfStruct )
{
// Top level, or topmost within a bogus struct: walk the pointers.
// Convert the pointers. This will do nothing if
// pStubMsg->IgnoreEmbeddedPointers is TRUE.
//
if ( *pFormat == FC_PP )
{
pStubMsg->BufferMark = pStructStart;
NdrpEmbeddedPointerConvert( pStubMsg, pFormat );
}
SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
}
// Restore flags.
if ( ! fTopLevelStruct)
SET_EMBED_CONF_STRUCT(pStubMsg->uFlags);
if ( ! fTopmostConfStruct)
SET_TOPMOST_CONF_STRUCT(pStubMsg->uFlags);
}
#if 0
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.
}
}
}
#endif
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.
Notice a recursive call to this routine at the end.
Hence, the flag can be TRUE or FALSE even for the top level
bogus structures.
Also, for the recursive call pStubMsg->PointerBufferMark is
not 0, even for top level bogus struct.
Return :
None.
Note about the recursive use of this routine:
First pass - flat conversion pass.
Convert flat part of the struct, then convert the array. For the embedded
structs or arrays, go in and convert all of them without walking their
pointers. The embedded conformant arrays should not be walked, only the
top level one.
Second pass - converting the pointees.
It has to increment over the conformant size.
It needs to go through the flat part of any embedded thing as for bogus
the pointer members are described only at their level.
It needs to go through the conf array at the top level only.
--*/
{
uchar * pBufferSave;
uchar * pBufferMark;
PFORMAT_STRING pFormatSave;
PFORMAT_STRING pFormatArray;
PFORMAT_STRING pFormatPointers;
uchar Alignment;
uchar fTopLevelStruct;
// We can't base the fTopLevelStruct flag upon check if
// pStubMsg->PointerBufferMark == 0 due to dual way this routine is called.
// One is when embedded in another struct (or array), another is a recursion
// from the same level for embedded pointer pass.
// Luckily, when embedded in an array, the struct can be bogus but not
// conformant.
fTopLevelStruct = ! IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
pFormatSave = pFormat;
// Remember the beginning of the structure in the buffer.
pBufferSave = pStubMsg->Buffer;
Alignment = pFormat[1];
pFormat += 4;
// Get conformant array description.
if ( *((ushort *)pFormat) )
{
long Dimensions;
long i;
pFormatArray = pFormat + *((signed short *)pFormat);
// Skip conformant size(s) for embedded struct.
if ( fTopLevelStruct )
{
ALIGN(pStubMsg->Buffer,3);
// Mark the conformance start.
pStubMsg->BufferMark = pStubMsg->Buffer;
Dimensions = NdrpArrayDimensions( pStubMsg, pFormatArray, FALSE );
if ( ! fEmbeddedPointerPass )
{
for ( i = 0; i < Dimensions; i++ )
NdrSimpleTypeConvert( pStubMsg, (uchar) FC_LONG );
}
else
{
pStubMsg->Buffer += Dimensions * 4;
}
}
}
else
pFormatArray = 0;
// Position of the conf size(s) - we will pass it to conf struct routine.
pBufferMark = pStubMsg->BufferMark;
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.
//
// Notice that this check depends on PointerBufferMark that gets changed.
// Hence, fComplexEntry will come out FALSE for the top level struct during
// the embedded pointer pass recursive call.
if ( fTopLevelStruct )
{
//
// Mark PointerBufferMark with a non-null value so complex array's
// embeddings work properly.
//
if ( pStubMsg->PointerBufferMark == 0 )
pStubMsg->PointerBufferMark = (uchar *) UlongToPtr( 0xffffffff );
}
//
// Convert the flat part of the structure.
// Or convert pointers of the flat part of the structure.
//
SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
NdrpStructConvert( pStubMsg,
pFormat,
pFormatPointers,
fEmbeddedPointerPass );
//
// Convert any conformant array, if present.
// This converts the array flat on the first pass and the array's pointees
// during the recursive pass.
//
// Convert the array only for a top level bogus struct but not if there was
// an embedded conformant struct as this had been done already.
if ( pFormatArray && fTopLevelStruct &&
! IS_CONF_ARRAY_DONE( pStubMsg->uFlags ) )
{
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 = (uchar) 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:
// Setup for the recursive call.
// 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 ( fTopLevelStruct && ! fEmbeddedPointerPass )
{
RESET_EMBED_CONF_STRUCT(pStubMsg->uFlags);
RESET_CONF_ARRAY_DONE( pStubMsg->uFlags );
// The first pointee.
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
// Starting from the conf size again.
pStubMsg->Buffer = pBufferSave;
NdrComplexStructConvert( pStubMsg,
pFormatSave,
TRUE );
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
pStubMsg->PointerBufferMark = 0;
}
// Restore the flag
if ( fTopLevelStruct )
{
RESET_EMBED_CONF_STRUCT(pStubMsg->uFlags);
RESET_CONF_ARRAY_DONE( pStubMsg->uFlags );
}
else
SET_EMBED_CONF_STRUCT(pStubMsg->uFlags);
}
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.
Does one pass converting flat part or the pointees per fEmbeddedPointerPass.
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.
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 is preserved but does not change anything.
pStubMsg->BufferMark is preserved and passed on for the embedded conf structs.
Return :
None.
--*/
{
PFORMAT_STRING pFormatComplex;
uchar fOldIgnore;
uchar * pBufferMarkSave = pStubMsg->BufferMark;
fOldIgnore = (uchar) pStubMsg->IgnoreEmbeddedPointers;
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 :
#if defined(__RPC_WIN64__)
case FC_INT3264 :
case FC_UINT3264 :
#endif
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 += PTR_WIRE_SIZE;
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;
uchar fEmbedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
NDR_ASSERT(pFormatPointers != 0,"Internal error");
ALIGN(pStubMsg->Buffer,3);
pBuffer = pStubMsg->Buffer;
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
pStubMsg->PointerBufferMark = 0;
RESET_EMBED_CONF_STRUCT(pStubMsg->uFlags);
NdrpPointerConvert( pStubMsg,
pBuffer,
pFormatPointers );
// Restore the flag
if ( fEmbedStruct )
SET_EMBED_CONF_STRUCT(pStubMsg->uFlags);
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
pStubMsg->Buffer = pBuffer + PTR_WIRE_SIZE;
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);
pStubMsg->BufferMark = pBufferMarkSave;
(*pfnConvertRoutines[ROUTINE_INDEX(*pFormatComplex)])
( pStubMsg,
pFormatComplex,
fEmbeddedPointerPass ); // the argument as it came in
// 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 :
break;
case FC_STRUCTPADN :
// FC_STRUCTPADN 0 <unsigned short>
pFormat += 3;
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;
}
}
pStubMsg->BufferMark = pBufferMarkSave;
}
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 = (uchar) 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 = (ulong)pStubMsg->MaxCount;
if ( ! Elements )
return;
ALIGN(pStubMsg->Buffer,pFormat[1]);
pBufferMark = pStubMsg->Buffer;
pFormat += 8;
CORRELATION_DESC_INCREMENT( pFormat );
if ( *pFormat == FC_PP )
pFormatLayout = NdrpSkipPointerLayout( pFormat );
else
pFormatLayout = pFormat;
fOldIgnore = (uchar) 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;
CORRELATION_DESC_INCREMENT( pFormat );
CORRELATION_DESC_INCREMENT( pFormat );
if ( *pFormat == FC_PP )
pFormatLayout = NdrpSkipPointerLayout( pFormat );
else
pFormatLayout = pFormat;
fOldIgnore = (uchar) 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;
CORRELATION_DESC_INCREMENT( pFormat );
if ( *pFormat == FC_PP )
pFormatLayout = NdrpSkipPointerLayout( pFormat );
else
pFormatLayout = pFormat;
fOldIgnore = (uchar) 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( pStubMsg, 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_PTR MaxCountSave;
long Elements;
long Dimension;
uchar Alignment;
//
// 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;
CORRELATION_DESC_INCREMENT( pFormat );
//
// 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( pStubMsg, 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;
CORRELATION_DESC_INCREMENT( pFormat );
if ( Elements )
{
BOOL fComplexEntry;
uchar fIsEmbedStruct = ! IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
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 *) UlongToPtr( 0xffffffff );
SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
}
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;
}
// Restore the entry values of these flags.
if ( fComplexEntry )
{
pStubMsg->PointerBufferMark = 0;
if ( ! fIsEmbedStruct )
RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
}
}
// 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;
uchar * pPointerIdMark = 0;
// 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_IP :
// we don't want to change the behavior of these two
if (! fEmbeddedPointerPass)
return;
// fall through otherwise
case FC_UP :
case FC_FP :
case FC_OP :
pPointerIdMark = pStubMsg->Buffer;
if ( ! fEmbeddedPointerPass )
{
for ( i = 0; i < Elements; i++ )
NdrSimpleTypeConvert(pStubMsg, FC_LONG);
return;
}
if ( pStubMsg->PointerBufferMark )
{
pBufferSave = pStubMsg->Buffer;
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
pStubMsg->PointerBufferMark = 0;
}
pfnConvert = (*pFormat == FC_IP) ? NdrInterfacePointerConvert:
(PCONVERT_ROUTINE) NdrpPointerConvert ;
break;
case FC_RANGE:
if ( fEmbeddedPointerPass )
{
ulong RangeSize = Elements * SIMPLE_TYPE_BUFSIZE( pFormat[1] );
CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, RangeSize );
pStubMsg->Buffer += RangeSize;
return;
}
for ( i = 0; i < Elements; i++ )
{
NdrpRangeConvert( pStubMsg, pFormat, fEmbeddedPointerPass);
}
break;
default :
//
// Simple type.
//
if ( fEmbeddedPointerPass )
{
unsigned long ArrSize = Elements * SIMPLE_TYPE_BUFSIZE(*pFormat);
CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, ArrSize );
pStubMsg->Buffer += ArrSize;
return;
}
// Optimize out an array of bytes
if ( *pFormat == FC_BYTE )
{
CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, Elements );
pStubMsg->Buffer += Elements;
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 )
{
ALIGN( pPointerIdMark, 3);
for ( i = 0; i < Elements; i++, pPointerIdMark += PTR_WIRE_SIZE )
{
NdrpPointerConvert( pStubMsg,
pPointerIdMark,
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 :
CHECK_ULONG_BOUND( Elements );
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + Elements );
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 :
CHECK_ULONG_BOUND( Elements * 2 );
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + 2 * Elements );
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.
CHECK_ULONG_BOUND( Elements * pFormat[1]);
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + Elements * pFormat[1] );
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;
NO_CORRELATION;
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;
CORRELATION_DESC_INCREMENT( pFormat );
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 :
// FC_INT3264 gets mapped to FC_LONG.
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) )
{
RpcRaiseException( RPC_S_INVALID_TAG );
}
//
// 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 ( fEmbeddedPointerPass )
{
ALIGN( pStubMsg->Buffer, SIMPLE_TYPE_ALIGNMENT( pFormat[0] ));
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE( pFormat[0] );
}
else
NdrSimpleTypeConvert( pStubMsg, pFormat[0] );
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 + PTR_WIRE_SIZE;
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;
CORRELATION_DESC_INCREMENT( pFormat );
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
{
uchar uFlagsSave;
uFlagsSave = pStubMsg->uFlags;
RESET_CONF_FLAGS_TO_STANDALONE(pStubMsg->uFlags);
// Convert the pointee as if not embedded.
pStubMsg->PointerBufferMark = 0;
(*pfnConvertRoutines[ ROUTINE_INDEX( *pTransFormat) ])
( pStubMsg,
pTransFormat,
FALSE );
pStubMsg->uFlags = uFlagsSave;
// 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 += PTR_WIRE_SIZE;
}
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_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.
--*/
{
uchar * pBufferSave;
USER_MARSHAL_CB * pUserCB = (USER_MARSHAL_CB *)pFlags;
MIDL_STUB_MESSAGE * pStubMsg = pUserCB->pStubMsg;
if ( pBuffer < pStubMsg->BufferStart ||
pBuffer > pStubMsg->BufferEnd ||
( (*pFlags >> 16) !=
(pStubMsg->RpcMsg->DataRepresentation & (ulong)0x0000FFFF) )
)
RpcRaiseException( RPC_S_INVALID_ARG );
pBufferSave = pStubMsg->Buffer;
pStubMsg->Buffer = pBuffer;
NdrSimpleTypeConvert( pStubMsg, FormatChar );
pBuffer = pStubMsg->Buffer;
pStubMsg->Buffer = pBufferSave;
return ( pBuffer );
}
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 -= PTR_WIRE_SIZE;
}
// 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.
CHECK_EOB_RAISE_IB( pStubMsg->Buffer + *pLength );
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);
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + CONTEXT_HANDLE_WIRE_SIZE );
pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
}
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;
ULONG_PTR 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 = (ulong)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;
}