NT4/private/rpc/ndr20/endian.c
2020-09-30 17:12:29 +02:00

3029 lines
76 KiB
C
Raw Permalink 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 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;
}