749 lines
17 KiB
C
749 lines
17 KiB
C
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Copyright (c) 1993 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
misc.c
|
|
|
|
Abstract :
|
|
|
|
Contains miscelaneous helper routines.
|
|
|
|
Author :
|
|
|
|
David Kays dkays December 1993.
|
|
|
|
Revision History :
|
|
|
|
---------------------------------------------------------------------*/
|
|
|
|
#include "ndrp.h"
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg( "NDR20_2" )
|
|
#endif
|
|
|
|
uchar *
|
|
NdrpMemoryIncrement(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar * pMemory,
|
|
PFORMAT_STRING pFormat
|
|
)
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Returns a memory pointer incremeted past a complex data type. This routine
|
|
is also overloaded to compute the size of a complex data type by passing
|
|
a 0 memory pointer.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to the stub message.
|
|
pMemory - Pointer to the complex type, or 0 if a size is being computed.
|
|
pFormat - Format string description.
|
|
|
|
Return :
|
|
|
|
A memory pointer incremented past the complex type. If a 0 memory pointer
|
|
was passed in then the returned value is the size of the complex type.
|
|
|
|
--*/
|
|
{
|
|
long Elements;
|
|
long ElementSize;
|
|
|
|
switch ( *pFormat )
|
|
{
|
|
//
|
|
// Structs
|
|
//
|
|
case FC_STRUCT :
|
|
case FC_PSTRUCT :
|
|
case FC_HARD_STRUCT :
|
|
pMemory += *((ushort *)(pFormat + 2));
|
|
break;
|
|
|
|
case FC_CSTRUCT :
|
|
case FC_CVSTRUCT :
|
|
pMemory += *((ushort *)(pFormat + 2));
|
|
|
|
// Get conformant array or string description.
|
|
pFormat += 4;
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
// Get the memory pointer past the conformant array.
|
|
pMemory = NdrpMemoryIncrement( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
break;
|
|
|
|
case FC_BOGUS_STRUCT :
|
|
pMemory += *((ushort *)(pFormat + 2));
|
|
|
|
pFormat += 4;
|
|
|
|
// Check for a conformant array or string in the struct.
|
|
if ( *((signed short *)pFormat) )
|
|
{
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
// Get the memory pointer past the conformant array.
|
|
pMemory = NdrpMemoryIncrement( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// Unions
|
|
//
|
|
case FC_ENCAPSULATED_UNION :
|
|
pMemory += HIGH_NIBBLE(pFormat[1]);
|
|
pMemory += *((ushort *)(pFormat + 2));
|
|
break;
|
|
|
|
case FC_NON_ENCAPSULATED_UNION :
|
|
// Go to the size/arm description.
|
|
pFormat += 6;
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
pMemory += *((ushort *)pFormat);
|
|
break;
|
|
|
|
//
|
|
// Arrays
|
|
//
|
|
case FC_SMFARRAY :
|
|
case FC_SMVARRAY :
|
|
pMemory += *((ushort *)(pFormat + 2));
|
|
break;
|
|
|
|
case FC_LGFARRAY :
|
|
case FC_LGVARRAY :
|
|
pMemory += *((ulong UNALIGNED *)(pFormat + 2));
|
|
break;
|
|
|
|
case FC_CARRAY:
|
|
case FC_CVARRAY:
|
|
pMemory += *((ushort *)(pFormat + 2)) *
|
|
NdrpComputeConformance( pStubMsg,
|
|
pMemory,
|
|
pFormat);
|
|
break;
|
|
|
|
case FC_BOGUS_ARRAY :
|
|
{
|
|
PARRAY_INFO pArrayInfo = pStubMsg->pArrayInfo;
|
|
|
|
if ( *((long UNALIGNED *)(pFormat + 4)) == 0xffffffff )
|
|
Elements = *((ushort *)(pFormat + 2));
|
|
else
|
|
{
|
|
if ( pArrayInfo &&
|
|
pArrayInfo->MaxCountArray &&
|
|
(pArrayInfo->MaxCountArray ==
|
|
pArrayInfo->BufferConformanceMark) )
|
|
{
|
|
Elements = pArrayInfo->MaxCountArray[pArrayInfo->Dimension];
|
|
}
|
|
else
|
|
{
|
|
Elements = NdrpComputeConformance( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
}
|
|
}
|
|
|
|
// Go to the array element's description.
|
|
pFormat += 12;
|
|
|
|
//
|
|
// Get the size of one element.
|
|
//
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_ENUM16 :
|
|
ElementSize = sizeof(int);
|
|
break;
|
|
|
|
case FC_RP :
|
|
case FC_UP :
|
|
case FC_FP :
|
|
case FC_OP :
|
|
ElementSize = PTR_MEM_SIZE;
|
|
break;
|
|
|
|
case FC_EMBEDDED_COMPLEX :
|
|
//
|
|
// It's some complicated thingy.
|
|
//
|
|
pFormat += 2;
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
if ( (*pFormat == FC_TRANSMIT_AS) ||
|
|
(*pFormat == FC_REPRESENT_AS) ||
|
|
(*pFormat == FC_USER_MARSHAL) )
|
|
{
|
|
//
|
|
// Get the presented type size.
|
|
//
|
|
ElementSize = *((ushort *)(pFormat + 4));
|
|
}
|
|
else
|
|
{
|
|
if ( pArrayInfo )
|
|
pArrayInfo->Dimension++;
|
|
|
|
ElementSize = NdrpMemoryIncrement( pStubMsg,
|
|
pMemory,
|
|
pFormat ) - pMemory;
|
|
|
|
if ( pArrayInfo )
|
|
pArrayInfo->Dimension--;
|
|
}
|
|
break;
|
|
|
|
default :
|
|
if ( IS_SIMPLE_TYPE(*pFormat) )
|
|
{
|
|
ElementSize = SIMPLE_TYPE_MEMSIZE(*pFormat);
|
|
break;
|
|
}
|
|
|
|
NDR_ASSERT(0,"NdrpMemoryIncrement : bad format char");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return 0;
|
|
}
|
|
|
|
pMemory += Elements * ElementSize;
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// String arrays (a.k.a. non-conformant strings).
|
|
//
|
|
case FC_CSTRING :
|
|
case FC_BSTRING :
|
|
case FC_WSTRING :
|
|
pMemory +=
|
|
*((ushort *)(pFormat + 2)) *
|
|
((*pFormat == FC_WSTRING) ? sizeof(wchar_t) : sizeof(char));
|
|
break;
|
|
|
|
case FC_SSTRING :
|
|
pMemory += pFormat[1] * *((ushort *)(pFormat + 2));
|
|
break;
|
|
|
|
//
|
|
// Sized conformant strings.
|
|
//
|
|
case FC_C_CSTRING:
|
|
case FC_C_BSTRING:
|
|
case FC_C_WSTRING:
|
|
{
|
|
PARRAY_INFO pArrayInfo = pStubMsg->pArrayInfo;
|
|
|
|
NDR_ASSERT(pFormat[1] == FC_STRING_SIZED,
|
|
"NdrpMemoryIncrement : called for non-sized string");
|
|
|
|
if ( pArrayInfo &&
|
|
pArrayInfo->MaxCountArray &&
|
|
(pArrayInfo->MaxCountArray ==
|
|
pArrayInfo->BufferConformanceMark) )
|
|
{
|
|
Elements = pArrayInfo->MaxCountArray[pArrayInfo->Dimension];
|
|
}
|
|
else
|
|
{
|
|
Elements = NdrpComputeConformance( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
}
|
|
|
|
pMemory += Elements *
|
|
( (*pFormat == FC_C_WSTRING) ?
|
|
sizeof(wchar_t) :
|
|
sizeof(char) );
|
|
}
|
|
break;
|
|
|
|
case FC_C_SSTRING:
|
|
{
|
|
PARRAY_INFO pArrayInfo = pStubMsg->pArrayInfo;
|
|
|
|
if ( pArrayInfo &&
|
|
pArrayInfo->MaxCountArray &&
|
|
(pArrayInfo->MaxCountArray ==
|
|
pArrayInfo->BufferConformanceMark) )
|
|
{
|
|
Elements = pArrayInfo->MaxCountArray[pArrayInfo->Dimension];
|
|
}
|
|
else
|
|
{
|
|
Elements = NdrpComputeConformance( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
}
|
|
|
|
pMemory += Elements * pFormat[1];
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Transmit as, represent as, user marshal
|
|
//
|
|
case FC_TRANSMIT_AS :
|
|
case FC_REPRESENT_AS :
|
|
case FC_USER_MARSHAL :
|
|
// Get the presented type size.
|
|
pMemory += *((ushort *)(pFormat + 4));
|
|
break;
|
|
|
|
case FC_BYTE_COUNT_POINTER:
|
|
//
|
|
// Should only hit this case when called from NdrSrvOutInit().
|
|
// In this case it's the total byte count allocation size we're
|
|
// looking for.
|
|
//
|
|
pMemory += NdrpComputeConformance( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
break;
|
|
|
|
case FC_IP :
|
|
pMemory += sizeof( void * );
|
|
break;
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrpMemoryIncrement : bad format char");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return 0;
|
|
}
|
|
|
|
return pMemory;
|
|
}
|
|
|
|
long
|
|
NdrpArrayDimensions(
|
|
PFORMAT_STRING pFormat,
|
|
BOOL fIgnoreStringArrays
|
|
)
|
|
/*++
|
|
|
|
Routine description :
|
|
|
|
This routine determines the number of dimensions in a complex array, which
|
|
is the only array type which is allowed to have multiple dimensions other
|
|
than an array of multiple fixed dimensions.
|
|
|
|
Arguments :
|
|
|
|
pFormat - Complex array's format string description.
|
|
fIgnoreStringArrays - TRUE if a string array should not be counted as
|
|
a dimension, FALSE if it should.
|
|
|
|
Return :
|
|
|
|
The number of dimensions in the array.
|
|
|
|
--*/
|
|
{
|
|
long Dimensions;
|
|
|
|
//
|
|
// Only a complex array can have multiple dimensions.
|
|
//
|
|
if ( *pFormat != FC_BOGUS_ARRAY )
|
|
return 1;
|
|
|
|
Dimensions = 1;
|
|
|
|
pFormat += 12;
|
|
|
|
for ( ; *pFormat == FC_EMBEDDED_COMPLEX; )
|
|
{
|
|
pFormat += 2;
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
//
|
|
// Search for a fixed, complex, or string array.
|
|
//
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_SMFARRAY :
|
|
pFormat += 4;
|
|
break;
|
|
|
|
case FC_LGFARRAY :
|
|
pFormat += 6;
|
|
break;
|
|
|
|
case FC_BOGUS_ARRAY :
|
|
pFormat += 12;
|
|
break;
|
|
|
|
case FC_CSTRING :
|
|
case FC_BSTRING :
|
|
case FC_WSTRING :
|
|
case FC_SSTRING :
|
|
case FC_C_CSTRING :
|
|
case FC_C_BSTRING :
|
|
case FC_C_WSTRING :
|
|
case FC_C_SSTRING :
|
|
//
|
|
// Can't have any more dimensions after a string array.
|
|
//
|
|
return fIgnoreStringArrays ? Dimensions : Dimensions + 1;
|
|
|
|
default :
|
|
return Dimensions;
|
|
}
|
|
|
|
Dimensions++;
|
|
}
|
|
|
|
//
|
|
// Get here if you have only one dimension.
|
|
//
|
|
return Dimensions;
|
|
}
|
|
|
|
long
|
|
NdrpArrayElements(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar * pMemory,
|
|
PFORMAT_STRING pFormat
|
|
)
|
|
/*++
|
|
|
|
Routine description :
|
|
|
|
This routine determines the number of elements (allocation size) in an
|
|
array. Used to handle multidimensional arrays.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - The stub message.
|
|
pMemory - The array.
|
|
pFormat - Array's format string description.
|
|
|
|
Return :
|
|
|
|
The number of elements in the array.
|
|
|
|
--*/
|
|
{
|
|
long TotalSize;
|
|
long ElementSize;
|
|
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_SMFARRAY :
|
|
TotalSize = (long) *((ushort *)(pFormat + 2));
|
|
pFormat += 4;
|
|
break;
|
|
|
|
case FC_LGFARRAY :
|
|
TotalSize = *((long UNALIGNED *)(pFormat + 2));
|
|
pFormat += 6;
|
|
break;
|
|
|
|
case FC_SMVARRAY :
|
|
return (long) *((ushort *)(pFormat + 4));
|
|
|
|
case FC_LGVARRAY :
|
|
return *((long UNALIGNED *)(pFormat + 6));
|
|
|
|
case FC_BOGUS_ARRAY :
|
|
if ( *((long *)(pFormat + 4)) == 0xffffffff )
|
|
return (long) *((ushort *)(pFormat + 2));
|
|
|
|
// else fall through
|
|
|
|
case FC_CARRAY :
|
|
case FC_CVARRAY :
|
|
return NdrpComputeConformance( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrpArrayElements : bad format char");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// We get here for a non-complex fixed array.
|
|
//
|
|
// Since a fixed array's format string description does not
|
|
// contain the number of elements in the array, we have to compute
|
|
// it by computing the array's element size and dividing this into
|
|
// the total array size.
|
|
//
|
|
// A fixed array's child can only be a nice struct, another
|
|
// fixed array, a pointer, or a simple type.
|
|
//
|
|
|
|
//
|
|
// Skip pointer layout if one is present.
|
|
//
|
|
if ( *pFormat == FC_PP )
|
|
pFormat = NdrpSkipPointerLayout( pFormat );
|
|
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_EMBEDDED_COMPLEX :
|
|
pFormat += 2;
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
//
|
|
// We must be at FC_STRUCT, FC_PSTRUCT, FC_SMFARRAY, or FC_LGFARRAY.
|
|
// All these have the total size as a short at 2 bytes past the
|
|
// beginning of the description except for large fixed array.
|
|
//
|
|
if ( *pFormat != FC_LGFARRAY )
|
|
ElementSize = (long) *((ushort *)(pFormat + 2));
|
|
else
|
|
ElementSize = *((long UNALIGNED *)(pFormat + 2));
|
|
|
|
break;
|
|
|
|
//
|
|
// Simple type (enum16 not possible).
|
|
//
|
|
default :
|
|
ElementSize = SIMPLE_TYPE_MEMSIZE( *pFormat );
|
|
break;
|
|
}
|
|
|
|
return TotalSize / ElementSize;
|
|
}
|
|
|
|
void
|
|
NdrpArrayVariance(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar * pMemory,
|
|
PFORMAT_STRING pFormat,
|
|
long * pOffset,
|
|
long * pLength
|
|
)
|
|
/*++
|
|
|
|
Routine description :
|
|
|
|
This routine determines the offset and length values for an array.
|
|
Used to handle multidimensional arrays.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - The stub message.
|
|
pMemory - The array.
|
|
pFormat - Array's format string description.
|
|
pOffset - Returned offset value.
|
|
pLength - Returned length value.
|
|
|
|
Return :
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_SMFARRAY :
|
|
case FC_LGFARRAY :
|
|
case FC_CARRAY :
|
|
*pOffset = 0;
|
|
*pLength = NdrpArrayElements( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
break;
|
|
|
|
case FC_BOGUS_ARRAY :
|
|
if ( *((long *)(pFormat + 8)) == 0xffffffff )
|
|
{
|
|
*pOffset = 0;
|
|
*pLength = NdrpArrayElements( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
return;
|
|
}
|
|
|
|
// else fall through
|
|
|
|
case FC_CVARRAY :
|
|
case FC_SMVARRAY :
|
|
case FC_LGVARRAY :
|
|
NdrpComputeVariance( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
|
|
*pOffset = (long) pStubMsg->Offset;
|
|
*pLength = (long) pStubMsg->ActualCount;
|
|
break;
|
|
|
|
default :
|
|
NDR_ASSERT(0,"NdrpArrayVariance : bad format char");
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return;
|
|
}
|
|
}
|
|
|
|
PFORMAT_STRING
|
|
NdrpSkipPointerLayout(
|
|
PFORMAT_STRING pFormat
|
|
)
|
|
/*--
|
|
|
|
RoutineDescription :
|
|
|
|
Skips a pointer layout format string description.
|
|
|
|
Arguments :
|
|
|
|
pFormat - Format string pointer layout description. Must currently
|
|
point to the FC_PP beginning the pointer layout.
|
|
|
|
Return :
|
|
|
|
Format string pointer past the pointer layout.
|
|
|
|
--*/
|
|
{
|
|
long Pointers;
|
|
|
|
NDR_ASSERT( *pFormat == FC_PP,
|
|
"NdrpSkipPointerLayout : format string not at FC_PP" );
|
|
|
|
// Skip FC_PP and FC_PAD.
|
|
pFormat += 2;
|
|
|
|
for (;;)
|
|
{
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_END :
|
|
return pFormat + 1;
|
|
|
|
case FC_NO_REPEAT :
|
|
pFormat += 10;
|
|
break;
|
|
|
|
case FC_FIXED_REPEAT :
|
|
pFormat += 2;
|
|
// fall through...
|
|
|
|
case FC_VARIABLE_REPEAT :
|
|
pFormat += 6;
|
|
|
|
Pointers = *((ushort *)pFormat)++;
|
|
|
|
pFormat += Pointers * 8;
|
|
break;
|
|
|
|
default :
|
|
NDR_ASSERT( 0, "NdrpSkipPointerLayout : bad format char" );
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
long
|
|
NdrpStringStructLen(
|
|
uchar * pMemory,
|
|
long ElementSize
|
|
)
|
|
/*--
|
|
|
|
RoutineDescription :
|
|
|
|
Determines a stringable struct's length.
|
|
|
|
Arguments :
|
|
|
|
pMemory - Pointer to stringable struct.
|
|
ElementSize - Number of bytes of each string element.
|
|
|
|
Return :
|
|
|
|
Length of string.
|
|
|
|
--*/
|
|
{
|
|
long Length;
|
|
uchar Buffer[256];
|
|
|
|
// Note : String struct element size is limited to 256 bytes.
|
|
|
|
MIDL_memset( Buffer, 0, 256 );
|
|
|
|
for ( Length = 0; ; Length++ )
|
|
{
|
|
#if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
|
|
if ( _fmemcmp( pMemory, Buffer, (uint) ElementSize ) == 0 )
|
|
#else
|
|
if ( memcmp( pMemory, Buffer, ElementSize ) == 0 )
|
|
#endif
|
|
break;
|
|
|
|
pMemory += ElementSize;
|
|
}
|
|
|
|
return Length;
|
|
}
|
|
|
|
void
|
|
NdrpCheckBound(
|
|
ulong Bound,
|
|
int Type
|
|
)
|
|
{
|
|
ulong Mask;
|
|
|
|
switch ( Type )
|
|
{
|
|
case FC_ULONG :
|
|
//
|
|
// We use a mask here which will raise an exception for counts
|
|
// of 2GB or more since this is the max NT allocation size.
|
|
//
|
|
Mask = 0x80000000UL;
|
|
break;
|
|
case FC_LONG :
|
|
Mask = 0x80000000UL;
|
|
break;
|
|
case FC_USHORT :
|
|
Mask = 0xffff0000UL;
|
|
break;
|
|
case FC_SHORT :
|
|
Mask = 0xffff8000UL;
|
|
break;
|
|
case FC_USMALL :
|
|
Mask = 0xffffff00UL;
|
|
break;
|
|
case FC_SMALL :
|
|
Mask = 0xffffff80UL;
|
|
break;
|
|
case 0 :
|
|
//
|
|
// For variance which requires calling an auxilary expression
|
|
// evaluation routine a type is not emitted in the format string.
|
|
// We have to just give up.
|
|
//
|
|
return;
|
|
default :
|
|
NDR_ASSERT( 0, "NdrpCheckBound : bad type" );
|
|
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
|
return;
|
|
}
|
|
|
|
if ( Bound & Mask )
|
|
RpcRaiseException( RPC_X_INVALID_BOUND );
|
|
}
|
|
|