Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1270 lines
28 KiB

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1993 Microsoft Corporation
Module Name:
ptrndr.hxx
Abstract:
Contains routines for the generation of the new NDR format strings for
pointer types, and the new NDR marshalling and unmarshalling calls.
Notes:
History:
DKays Oct-1993 Created.
----------------------------------------------------------------------------*/
#include "becls.hxx"
#pragma hdrstop
static long StringToHex( char * str );
extern CMD_ARG * pCommand;
BOOL
CG_POINTER::IsPointerToBaseType()
{
BOOL fIsPointerToBaseType = FALSE;
CG_NDR * pChild;
if(GetCGID() == ID_CG_PTR)
{
pChild = (CG_NDR *)GetChild();
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
pChild = (CG_NDR *)pChild->GetChild();
if(pChild->IsSimpleType())
fIsPointerToBaseType = TRUE;
}
return fIsPointerToBaseType;
}
BOOL
CG_POINTER::IsPointerToPointer()
{
BOOL fIsPointerToPointer = FALSE;
CG_NDR * pChild;
if(GetCGID() == ID_CG_PTR)
{
pChild = (CG_NDR *)GetChild();
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
pChild = (CG_NDR *)pChild->GetChild();
if (pChild->IsPointer())
fIsPointerToPointer = TRUE;
}
return fIsPointerToPointer;
}
BOOL
CG_POINTER::IsBasicRefPointer()
{
short Attributes;
if ( (GetCGID() == ID_CG_INTERFACE_PTR) ||
(GetCGID() == ID_CG_BC_PTR) ||
(GetCGID() == ID_CG_STRUCT_STRING_PTR) ||
(GetPtrType() != PTR_REF) ||
IsPointerToBaseType() )
return FALSE;
if ( ((GetCGID() == ID_CG_STRING_PTR) ||
(GetCGID() == ID_CG_SIZE_STRING_PTR)) &&
((CG_STRING_POINTER *)this)->IsStringableStruct() )
return FALSE;
Attributes = GetAllocateDetails();
if ( IsPointerToPointer() ||
IS_ALLOCATE(Attributes, ALLOCATE_ALL_NODES) ||
IS_ALLOCATE(Attributes, ALLOCATE_DONT_FREE) )
return FALSE;
return TRUE;
}
BOOL
CG_POINTER::IsMultiSize()
{
if ( (GetCGID() != ID_CG_SIZE_PTR) &&
(GetCGID() != ID_CG_SIZE_LENGTH_PTR) )
return FALSE;
CG_NDR * pChild = (CG_NDR *) GetChild();
if ( (pChild->GetCGID() == ID_CG_SIZE_PTR) ||
(pChild->GetCGID() == ID_CG_SIZE_LENGTH_PTR) ||
(pChild->GetCGID() == ID_CG_SIZE_STRING_PTR) )
return TRUE;
return FALSE;
}
long
CG_POINTER::SizedDimensions()
{
CG_NDR * pNdr;
long Dim;
Dim = 0;
pNdr = this;
for ( ; ; pNdr = (CG_NDR *) pNdr->GetChild(), Dim++ )
{
if ( (pNdr->GetCGID() != ID_CG_SIZE_PTR) &&
(pNdr->GetCGID() != ID_CG_SIZE_LENGTH_PTR) &&
(pNdr->GetCGID() != ID_CG_SIZE_STRING_PTR) )
break;
}
return Dim;
}
long
CG_POINTER::FixedBufferSize( CCB * pCCB )
{
long BufSize;
//
// Must give up on string or sized pointers.
//
if ( GetCGID() != ID_CG_PTR )
return -1;
BufSize = ((CG_NDR *)GetChild())->FixedBufferSize( pCCB );
if ( BufSize == -1 )
return -1;
if ( GetPtrType() != PTR_REF )
BufSize += 8;
return BufSize;
}
BOOL
CG_POINTER::InterpreterAllocatesOnStack(
CCB * pCCB,
CG_PARAM * pMyParam,
long * pAllocationSize )
{
CG_NDR * pNdr;
long OutSize;
if ( ! pMyParam )
return FALSE;
pNdr = (CG_NDR *) GetChild();
if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
pNdr = (CG_NDR *) pNdr->GetChild();
if ( pNdr->GetCGID() == ID_CG_CONTEXT_HDL )
{
//
// These get the "allocated on stack" attribute but a size of 0 since
// they are allocated by calling NDRSContextUnmarshall.
//
*pAllocationSize = 0;
return TRUE;
}
//
// Make sure this pointer is a top level parameter and doesn't have
// any allocate attributes.
//
if ( (pMyParam->GetCGID() == ID_CG_RETURN) ||
(pMyParam->GetChild() != this) ||
IS_ALLOCATE( GetAllocateDetails(), ALLOCATE_ALL_NODES ) ||
IS_ALLOCATE( GetAllocateDetails(), ALLOCATE_DONT_FREE ) )
return FALSE;
OutSize = pCCB->GetInterpreterOutSize();
//
// Watch for [out] only ref to ref pointers as they should be
// handled by NdrOutInit in the new interpreter, not on stack.
//
if ( ! pMyParam->IsParamIn() && IsRef() &&
IsPointerToPointer() && ((CG_POINTER *)pNdr)->IsRef() )
return FALSE;
//
// Look for pointer to pointer, [out] only pointer to base type, or
// pointer to enum16 of any direction.
//
if ( IsPointerToPointer() ||
(IsPointerToBaseType() && ! pMyParam->IsParamIn()) ||
(IsPointerToBaseType() &&
(((CG_BASETYPE *)pNdr)->GetFormatChar() == FC_ENUM16) &&
pMyParam->IsParamIn()) )
{
if ( (OutSize + 8) <= MAX_INTERPRETER_OUT_SIZE )
{
*pAllocationSize = 8;
pCCB->SetInterpreterOutSize( pCCB->GetInterpreterOutSize() + 8 );
return TRUE;
}
}
//
// Finished with [in], [in,out] cases now.
//
if ( pMyParam->IsParamIn() )
return FALSE;
//
// This covers [out] pointers to structs and unions. We don't allow
// any one parameter to eat up too much of the total stack space
// the interpreter has set aside for this optimization.
//
if ( pNdr->GetMemorySize() <= MAX_INTERPRETER_PARAM_OUT_SIZE )
{
OutSize += (pNdr->GetMemorySize() + 7) & ~0x7;
if ( OutSize <= MAX_INTERPRETER_OUT_SIZE )
{
*pAllocationSize = (pNdr->GetMemorySize() + 7) & ~0x7;
pCCB->SetInterpreterOutSize(
pCCB->GetInterpreterOutSize() + *pAllocationSize );
return TRUE;
}
}
return FALSE;
}
void
CG_POINTER::GenNdrPointerType( CCB * pCCB )
/*++
Routine Description :
Generates the first two bytes of a pointer's format string description.
Arguments :
pCCB - pointer to the code control block.
Return:
Returns FALSE if the format string for the pointer type has already been
generated, otherwise returns TRUE.
--*/
{
FORMAT_STRING * pFormatString;
CG_PARAM * pParam;
short Attributes;
unsigned char FormatAttr;
pFormatString = pCCB->GetFormatString();
pParam = pCCB->GetCurrentParam();
//
// Set the pointer type.
//
switch ( GetPtrType() )
{
case PTR_REF :
pFormatString->PushPointerFormatChar(FC_RP);
break;
case PTR_UNIQUE :
//
// Check if this is a unique pointer in an OLE interface, but
// is not the top most pointer.
//
if ( pCCB->IsInObjectInterface() &&
pParam->IsParamOut() &&
pParam->GetChild() != this )
pFormatString->PushPointerFormatChar(FC_OP);
else
pFormatString->PushPointerFormatChar(FC_UP);
break;
case PTR_FULL :
pFormatString->PushPointerFormatChar(FC_FP);
break;
}
//
// Now the attributes.
//
FormatAttr = 0;
Attributes = GetAllocateDetails();
if ( IS_ALLOCATE(Attributes, ALLOCATE_ALL_NODES) )
FormatAttr |= FC_ALLOCATE_ALL_NODES;
if ( IS_ALLOCATE(Attributes, ALLOCATE_DONT_FREE) )
FormatAttr |= FC_DONT_FREE;
if ( GetCGID() == ID_CG_PTR )
{
//
// Check if we are allocated on the stack by the stub. Currently this
// only works for top level pointers.
//
if ( ! ShouldPointerFree() &&
! (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER) )
FormatAttr |= FC_ALLOCED_ON_STACK;
//
// For the interpreter we set the alloced on stack attribute for
// those [out] pointers which we will be able to "allocate" on the
// server interpreter's stack. We also do this for [in,out] double
// pointers.
// The version 1 interpreter simply looks for pointers to context
// handles.
//
if ( pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER )
{
if ( ! (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER_V2) )
{
if ( ((CG_NDR *)GetChild())->GetCGID() == ID_CG_CONTEXT_HDL )
FormatAttr |= FC_ALLOCED_ON_STACK;
}
else
{
long OutSize;
if ( InterpreterAllocatesOnStack( pCCB, pParam, &OutSize ) )
FormatAttr |= FC_ALLOCED_ON_STACK;
}
}
}
//
// Check for a pointer to simple type, non-sized string, or pointer to
// pointer.
//
if ( IsPointerToBaseType() || (GetCGID() == ID_CG_STRING_PTR) )
FormatAttr |= FC_SIMPLE_POINTER;
if ( IsPointerToPointer() )
FormatAttr |= FC_POINTER_DEREF;
pFormatString->PushByte( FormatAttr );
SetFormatAttr( FormatAttr );
}
void
CG_POINTER::GenNdrFormat( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for a pointer to anything.
Arguments :
pCCB - pointer to the code control block.
--*/
{
FORMAT_STRING * pFormatString = pCCB->GetFormatString();
unsigned short StartOffset = pFormatString->GetCurrentOffset();
if ( GetFormatStringOffset() != -1 )
return;
SetFormatStringOffset( StartOffset );
SetFormatStringEndOffset( StartOffset + 4 );
GenNdrFormatAlways( pCCB );
// here, we assume all pointers generate 4 bytes
SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
}
void
CG_POINTER::GenNdrFormatAlways( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for a pointer to anything.
Arguments :
pCCB - pointer to the code control block.
--*/
{
FORMAT_STRING * pFormatString;
long Offset;
pFormatString = pCCB->GetFormatString();
GenNdrPointerType( pCCB );
//
// If it's an unattributed pointer to a simple type then the format
// string is optimized.
//
if ( IsPointerToBaseType() )
{
GenNdrFormatPointee( pCCB );
pFormatString->PushFormatChar( FC_PAD );
return;
}
// Get the current offset.
Offset = pFormatString->GetCurrentOffset();
// Push a short for the offset to be filled in later.
pFormatString->PushShortOffset( 0 );
// Generate the pointee's format string.
GenNdrFormatPointee( pCCB );
// Now fill in the offset field correctly.
pFormatString->PushShort( GetPointeeFormatStringOffset() - Offset,
Offset );
}
void
CG_POINTER::GenNdrParamOffline( CCB * pCCB )
{
GenNdrFormat( pCCB );
}
void
CG_POINTER::GenNdrFormatPointee( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for the pointee of an
unattributed pointer to anything.
Arguments :
pCCB - pointer to the code control block.
--*/
{
CG_NDR * pChild;
pChild = (CG_NDR *)GetChild();
if (pChild->IsProc())
{
assert(pCommand->IsHookOleEnabled());
FORMAT_STRING * pFormatString = pCCB->GetFormatString();
SetPointeeFormatStringOffset(pFormatString->GetCurrentOffset());
pFormatString->PushFormatChar(FC_BLKHOLE);
pFormatString->PushByte( BLKHOLE_FUNCTION ); // flags
pFormatString->PushShort( (short) -1 ); // Reserved
}
else
{
//
// For unattributed pointers (no size or length), this is simply a
// call to the child's GenNdrFormat method.
//
pChild->GenNdrFormat( pCCB );
SetPointeeFormatStringOffset( pChild->GetFormatStringOffset() );
}
}
BOOL
CG_POINTER::ShouldFreeOffline()
{
CG_NDR * pNdr;
//
// The order here is very, very important.
//
if ( IsAllocateDontFree() )
return FALSE;
pNdr = (CG_NDR *) GetChild();
//
// Skip past generic handle nodes.
//
if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
pNdr = (CG_NDR *) pNdr->GetChild();
//
// Check for handles.
//
if ( (pNdr->GetCGID() == ID_CG_CONTEXT_HDL) ||
(pNdr->GetCGID() == ID_CG_PRIMITIVE_HDL) )
return FALSE;
//
// Offline full pointers.
//
if ( GetPtrType() == PTR_FULL )
return TRUE;
switch ( GetCGID() )
{
case ID_CG_PTR :
case ID_CG_SIZE_PTR :
break;
case ID_CG_STRING_PTR :
case ID_CG_STRUCT_STRING_PTR :
return FALSE;
case ID_CG_SIZE_LENGTH_PTR :
case ID_CG_LENGTH_PTR :
case ID_CG_SIZE_STRING_PTR :
case ID_CG_BC_PTR :
return TRUE;
default :
assert(0);
}
if ( pNdr->IsSimpleType() )
return FALSE;
if ( pNdr->IsStruct() )
return ((CG_STRUCT *)pNdr)->ShouldFreeOffline();
return TRUE;
}
void
CG_POINTER::GenFreeInline( CCB * pCCB )
{
CG_PARAM * pParam;
CG_NDR * pNdr;
BOOL fFree;
if ( ShouldFreeOffline() || IsAllocateDontFree() )
return;
//
// We use the buffer for these since they have to be [in] or [in,out].
//
if ( GetCGID() == ID_CG_STRING_PTR )
return;
fFree = FALSE;
pParam = (CG_PARAM *) pCCB->GetLastPlaceholderClass();
pNdr = (CG_NDR *) GetChild();
//
// Skip past generic handle nodes.
//
if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
pNdr = (CG_NDR *) pNdr->GetChild();
//
// Check for handles.
//
if ( (pNdr->GetCGID() == ID_CG_CONTEXT_HDL) ||
(pNdr->GetCGID() == ID_CG_PRIMITIVE_HDL) )
return;
//
// Free a pointer to simple type only if it's a pointer to enum16.
//
if ( pNdr->IsSimpleType() )
fFree = ( (pNdr->GetCGID() == ID_CG_ENUM) &&
! ((CG_ENUM *)pNdr)->IsEnumLong() );
//
// Out only pointer is freed if it wasn't allocated on the server's stack.
// We overwrite any previous freeing descision.
//
if ( ! pParam->IsParamIn() )
fFree = ShouldPointerFree();
if ( fFree )
{
//
// Always check if the pointer is not null before freeing.
//
Out_FreeParamInline( pCCB );
}
}
void CG_SIZE_POINTER::GenNdrFormatPointee( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for the pointee of an
sized pointer to anything.
Since a sized pointer is really the same as a pointer to a conformant
array in Ndr terms, we just create a CG_CONFORMANT_ARRAY class on the
fly and tell it to generate it's code.
Arguments :
pCCB - pointer to the code control block.
--*/
{
CG_CONFORMANT_ARRAY * pConformantArray;
CG_QUALIFIED_POINTER * pOldSizePtr;
if ( GetPointeeFormatStringOffset() != -1 )
return;
if ( IsMultiSize() )
{
CG_NDR * pChild = (CG_NDR *) GetChild();
SetIsInMultiSized( TRUE );
if ( (pChild->GetCGID() == ID_CG_SIZE_PTR) ||
(pChild->GetCGID() == ID_CG_SIZE_LENGTH_PTR) ||
(pChild->GetCGID() == ID_CG_SIZE_STRING_PTR) )
{
((CG_QUALIFIED_POINTER *)pChild)->SetIsInMultiSized( TRUE );
((CG_QUALIFIED_POINTER *)pChild)->SetDimension(GetDimension() + 1);
}
}
pOldSizePtr = pCCB->GetCurrentSizePointer();
pCCB->SetCurrentSizePointer( this );
CG_NDR * pChild = (CG_NDR *) GetChild();
pConformantArray = new CG_CONFORMANT_ARRAY( this );
SetPointee( pConformantArray );
pConformantArray->SetPtrType( PTR_REF );
pConformantArray->SetChild( GetChild() );
pConformantArray->SetIsInMultiDim( IsInMultiSized() );
pConformantArray->SetFormatStringOffset( -1 );
pConformantArray->GenNdrFormat( pCCB );
SetPointeeFormatStringOffset( pConformantArray->GetFormatStringOffset() );
pCCB->SetCurrentSizePointer( pOldSizePtr );
}
void CG_SIZE_LENGTH_POINTER::GenNdrFormatPointee( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for the pointee of a
size-length pointer to anything.
Since a size-length pointer is really the same as a pointer to a conformant
varying array in Ndr terms, we just create a CG_CONFORMANT_VARYING_ARRAY
class on the fly and tell it to generate it's code.
Arguments :
pCCB - pointer to the code control block.
--*/
{
CG_CONFORMANT_VARYING_ARRAY * pConfVaryArray;
CG_QUALIFIED_POINTER * pOldSizePtr;
if ( GetPointeeFormatStringOffset() != -1 )
return;
if ( IsMultiSize() )
{
CG_NDR * pChild = (CG_NDR *) GetChild();
SetIsInMultiSized( TRUE );
if ( (pChild->GetCGID() == ID_CG_SIZE_PTR) ||
(pChild->GetCGID() == ID_CG_SIZE_LENGTH_PTR) ||
(pChild->GetCGID() == ID_CG_SIZE_STRING_PTR) )
{
((CG_QUALIFIED_POINTER *)pChild)->SetIsInMultiSized( TRUE );
((CG_QUALIFIED_POINTER *)pChild)->SetDimension(GetDimension() + 1);
}
}
pOldSizePtr = pCCB->GetCurrentSizePointer();
pCCB->SetCurrentSizePointer( this );
pConfVaryArray = new CG_CONFORMANT_VARYING_ARRAY( this );
SetPointee( pConfVaryArray );
pConfVaryArray->SetPtrType( PTR_REF );
pConfVaryArray->SetChild( GetChild() );
pConfVaryArray->SetIsInMultiDim( IsInMultiSized() );
pConfVaryArray->SetFormatStringOffset( -1 );
pConfVaryArray->GenNdrFormat( pCCB );
SetPointeeFormatStringOffset( pConfVaryArray->GetFormatStringOffset() );
pCCB->SetCurrentSizePointer( pOldSizePtr );
}
// --------------------------------------------------------------------------
// Strings
// --------------------------------------------------------------------------
void
CG_STRING_POINTER::GenNdrFormat( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for a string pointer.
Arguments :
pCCB - pointer to the code control block.
--*/
{
FORMAT_STRING * pFormatString = pCCB->GetFormatString();
unsigned short StartOffset = pFormatString->GetCurrentOffset();
if ( GetFormatStringOffset() != -1 )
return;
SetFormatStringOffset( StartOffset );
SetFormatStringEndOffset( StartOffset + 4 );
GenNdrFormatAlways( pCCB );
// here, we assume all pointers generate 4 bytes
SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
}
void
CG_STRING_POINTER::GenNdrFormatAlways( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for a string pointer.
Arguments :
pCCB - pointer to the code control block.
--*/
{
GenNdrPointerType( pCCB );
if ( IsStringableStruct() )
{
FORMAT_STRING * pFormatString;
long Offset;
pFormatString = pCCB->GetFormatString();
//
// For stringable struct's we must emit the offset to the pointee
// description. Regular string pointers have the actual description
// immediately following.
//
Offset = pFormatString->GetCurrentOffset();
pFormatString->PushShortOffset( 0 );
GenNdrFormatPointee( pCCB );
pFormatString->PushShort( GetPointeeFormatStringOffset() - Offset,
Offset );
return;
}
GenNdrFormatPointee( pCCB );
pCCB->GetFormatString()->PushFormatChar( FC_PAD );
}
void
CG_STRING_POINTER::GenNdrFormatPointee( CCB * pCCB )
/*++
Routine Description :
Generate the format string of the actual string type without the
pointer attributes.
Arguments :
pCCB - pointer to the code control block.
--*/
{
FORMAT_STRING * pFormatString;
pFormatString = pCCB->GetFormatString();
//
// Check for stringable struct.
//
if ( IsStringableStruct() )
{
if ( GetPointeeFormatStringOffset() != -1 )
return;
SetPointeeFormatStringOffset( pFormatString->GetCurrentOffset() );
pFormatString->PushFormatChar( FC_C_SSTRING );
pFormatString->PushByte( ((CG_NDR *)GetChild())->GetWireSize() );
return;
}
//
// Always generate the format string. The description of a non-sized
// string pointer is not shared.
//
switch ( ((CG_BASETYPE *)GetChild())->GetFormatChar() )
{
case FC_CHAR :
case FC_BYTE :
pFormatString->PushFormatChar( FC_C_CSTRING );
break;
case FC_WCHAR :
pFormatString->PushFormatChar( FC_C_WSTRING );
break;
default :
assert(0);
}
}
void
CG_SIZE_STRING_POINTER::GenNdrFormat( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for a sized string pointer.
Arguments :
pCCB - pointer to the code control block.
--*/
{
FORMAT_STRING * pFormatString = pCCB->GetFormatString();
unsigned short StartOffset = pFormatString->GetCurrentOffset();
if ( GetFormatStringOffset() != -1 )
return;
SetFormatStringOffset( StartOffset );
SetFormatStringEndOffset( StartOffset + 4 );
GenNdrFormatAlways( pCCB );
// here, we assume all pointers generate 4 bytes
SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
}
void
CG_SIZE_STRING_POINTER::GenNdrFormatAlways( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for a sized string pointer.
Arguments :
pCCB - pointer to the code control block.
--*/
{
FORMAT_STRING * pFormatString;
long Offset;
pFormatString = pCCB->GetFormatString();
GenNdrPointerType( pCCB );
// Get the current offset.
Offset = pFormatString->GetCurrentOffset();
// Push a short for the offset to be filled in later.
pFormatString->PushShortOffset( 0 );
// Generate the pointee's format string.
GenNdrFormatPointee( pCCB );
// Now fill in the offset field correctly.
pFormatString->PushShort( GetPointeeFormatStringOffset() - Offset,
Offset );
}
void
CG_SIZE_STRING_POINTER::GenNdrFormatPointee( CCB * pCCB )
/*++
Routine Description :
Generate the format string of the actual string type without the
pointer attributes.
Arguments :
pCCB - pointer to the code control block.
--*/
{
FORMAT_STRING * pFormatString;
CG_QUALIFIED_POINTER * pOldSizePtr;
if ( GetPointeeFormatStringOffset() != -1 )
return;
pFormatString = pCCB->GetFormatString();
SetPointeeFormatStringOffset( pFormatString->GetCurrentOffset() );
pOldSizePtr = pCCB->GetCurrentSizePointer();
pCCB->SetCurrentSizePointer( this );
//
// Check for stringable struct.
//
if ( IsStringableStruct() )
{
pFormatString->PushFormatChar( FC_C_SSTRING );
pFormatString->PushByte( ((CG_NDR *)GetChild())->GetWireSize() );
pFormatString->PushFormatChar( FC_STRING_SIZED );
pFormatString->PushFormatChar( FC_PAD );
GenFormatStringConformanceDescription( pCCB, TRUE, IsInMultiSized() );
pCCB->SetCurrentSizePointer( pOldSizePtr );
return;
}
switch ( ((CG_BASETYPE *)GetChild())->GetFormatChar() )
{
case FC_CHAR :
case FC_BYTE :
pFormatString->PushFormatChar( FC_C_CSTRING );
break;
case FC_WCHAR :
pFormatString->PushFormatChar( FC_C_WSTRING );
break;
default :
assert(0);
}
pFormatString->PushFormatChar( FC_STRING_SIZED );
//
// Set the IsPointer parameter to TRUE.
//
GenFormatStringConformanceDescription( pCCB, TRUE, IsInMultiSized() );
pCCB->SetCurrentSizePointer( pOldSizePtr );
}
void
CG_BYTE_COUNT_POINTER::GenNdrFormat( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for a byte count pointer.
Arguments :
pCCB - pointer to the code control block.
--*/
{
CG_ITERATOR Iterator;
FORMAT_STRING * pFormatString;
CG_PROC * pProc;
CG_PARAM * pParam;
CG_NDR * pChild;
if ( GetFormatStringOffset() != -1 )
return;
pFormatString = pCCB->GetFormatString();
pChild = (CG_NDR *) GetChild();
if ( ! pChild->IsSimpleType() )
pChild->GenNdrFormat( pCCB );
SetFormatStringOffset( pFormatString->GetCurrentOffset() );
pFormatString->PushFormatChar( FC_BYTE_COUNT_POINTER );
if ( pChild->IsSimpleType() )
pChild->GenNdrFormat( pCCB );
else
pFormatString->PushFormatChar( FC_PAD );
pProc = (CG_PROC *) pCCB->GetCGNodeContext();
pProc->GetMembers( Iterator );
while ( ITERATOR_GETNEXT( Iterator, pParam ) )
if ( GetByteCountParam() == pParam->GetType() )
break;
assert( ((CG_NDR *)pParam->GetChild())->IsSimpleType() );
CG_BASETYPE * pCount = (CG_BASETYPE *) pParam->GetChild();
unsigned char Type;
Type = (unsigned char) pCount->GetFormatChar();
Type |= FC_TOP_LEVEL_CONFORMANCE;
// Byte count description, just do it here.
pFormatString->PushByte( Type );
pFormatString->PushByte( 0 );
pFormatString->PushShortStackOffset(
(short) pParam->GetStackOffset( pCCB, I386_STACK_SIZING ),
(short) pParam->GetStackOffset( pCCB, ALPHA_STACK_SIZING ),
(short) pParam->GetStackOffset( pCCB, MIPS_STACK_SIZING ),
(short) pParam->GetStackOffset( pCCB, PPC_STACK_SIZING ),
(short) pParam->GetStackOffset( pCCB, MAC_STACK_SIZING ) );
if ( ! pChild->IsSimpleType() )
{
pFormatString->PushShortOffset( pChild->GetFormatStringOffset() -
pFormatString->GetCurrentOffset() );
}
}
void
CG_INTERFACE_POINTER::GenNdrFormat( CCB * pCCB )
/*++
Routine Description :
Generates the format string description for an interface pointer.
Arguments :
pCCB - pointer to the code control block.
--*/
{
FORMAT_STRING * pFormatString;
node_interface * pInterface;
node_guid * pGuid;
char * p1;
char * p2;
char * p3;
char * p4;
char * p5;
if ( GetFormatStringOffset() != -1 )
return;
pFormatString = pCCB->GetFormatString();
SetFormatStringOffset( pFormatString->GetCurrentOffset() );
//
// There are two cases, the constant UUID and the [iid_is] expression.
//
// In the normal case, we will get the 16 byte UUID from the [uuid]
// attribute on the interface node. The 16 byte UUID is written to the
// format string. Note that the UUID in the format string is not aligned
// in memory. The UUID must be copied to a local structure before being
// used.
//
// Get the interface node.
pFormatString->PushFormatChar( FC_IP );
if ( GetIIDExpr() )
{
//
// Interface pointer has [iid_is] applied to it.
//
pFormatString->PushFormatChar( FC_PAD );
GenNdrFormatAttributeDescription( pCCB,
0,
GetIIDExpr(),
TRUE,
FALSE,
FALSE,
FALSE );
return;
}
//
// Else handle a constant iid interface pointer.
//
pInterface = GetTheInterface();
assert( pInterface->NodeKind() == NODE_INTERFACE );
pFormatString->PushFormatChar( FC_CONSTANT_IID );
// Get the [uuid] from the interface node.
pGuid = (node_guid *)pInterface->GetAttribute( ATTR_GUID );
assert( pGuid && "No UUID for interface pointer" );
pGuid->GetStrs( &p1, &p2, &p3, &p4, &p5 );
pFormatString->PushLong( StringToHex( p1 ) );
pFormatString->PushShort( StringToHex( p2 ) );
pFormatString->PushShort( StringToHex( p3 ) );
char Buffer[20];
char String[4];
int i;
strcpy( Buffer, p4 );
strcat( Buffer, p5 );
for ( i = 0; i < 16; i += 2 )
{
String[0] = Buffer[i];
String[1] = Buffer[i+1];
String[2] = '\0';
pFormatString->PushByte( StringToHex( String ) );
}
SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
}
void
CG_INTERFACE_POINTER::GenNdrFormatAlways( CCB * pCCB )
{
long OldOffset;
OldOffset = GetFormatStringOffset();
SetFormatStringOffset( -1 );
GenNdrFormat( pCCB );
SetFormatStringOffset( OldOffset );
}
void
CG_POINTER::SetNextNdrAlignment( CCB * pCCB )
{
if ( GetPtrType() != PTR_REF )
{
pCCB->SetNdrAlignment( NDR_ALWC1 );
return;
}
switch ( GetCGID() )
{
case ID_CG_PTR :
pCCB->NdrAlignmentAction(
((CG_NDR *)GetChild())->GetWireAlignment() );
((CG_NDR *)GetChild())->SetNextNdrAlignment( pCCB );
break;
case ID_CG_SIZE_PTR :
case ID_CG_LENGTH_PTR :
case ID_CG_SIZE_LENGTH_PTR :
pCCB->SetNdrAlignment( NDR_ALWC4 );
pCCB->NdrAlignmentAction(
((CG_NDR *)GetChild())->GetWireAlignment() );
((CG_NDR *)GetChild())->SetNextNdrAlignment( pCCB );
break;
default :
pCCB->SetNdrAlignment( NDR_ALWC1 );
break;
}
}
void
CG_STRING_POINTER::SetNextNdrAlignment( CCB * pCCB )
{
CG_BASETYPE * pChild;
if ( GetPtrType() != PTR_REF )
{
pCCB->SetNdrAlignment( NDR_ALWC1 );
return;
}
if ( ((CG_NDR *)GetChild())->IsSimpleType() )
{
pChild = (CG_BASETYPE *) GetChild();
pCCB->SetNdrAlignment( pChild->GetFormatChar( pCCB ) == FC_WCHAR ?
NDR_ALWC2 : NDR_ALWC1 );
}
else
{
// Stringable struct - just give up.
pCCB->SetNdrAlignment( NDR_ALWC1 );
}
}
static long
StringToHex( char * str )
{
long l;
l = 0;
for ( ; *str ; str++ )
{
l *= 16;
if ( ('0' <= *str) && (*str <= '9') )
{
l += *str - '0';
continue;
}
if ( ('a' <= *str) && (*str <= 'f') )
{
l += 10 + *str - 'a';
continue;
}
if ( ('A' <= *str) && (*str <= 'F') )
{
l += 10 + *str - 'A';
continue;
}
assert(0);
}
return l;
}