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.
 
 
 
 
 
 

2988 lines
75 KiB

/*---------------------------------------------------------------------------
Copyright (c) 1993 Microsoft Corporation
Module Name:
procndr.hxx
Abstract:
Contains routines for the generation of the new NDR format strings for
the code generation procedure class.
Notes:
History:
DKays Oct-1993 Created.
----------------------------------------------------------------------------*/
#include "becls.hxx"
#pragma hdrstop
#include "szbuffer.h"
#include "walkctxt.hxx"
extern CMD_ARG * pCommand;
void
CG_PROC::GenNdrFormat( CCB * pCCB )
/*++
Routine Description :
Interpreted procedure format string descriptions.
Arguments :
pCCB - pointer to the code control block
--*/
{
CG_ITERATOR Iterator;
CG_PARAM * pParam;
FORMAT_STRING * pProcFormatString;
CG_NDR * pOldCGNodeContext;
short ParamNum;
long ServerBufferSize;
long ClientBufferSize;
long BufSize;
BOOL fServerMustSize;
BOOL fClientMustSize;
INTERPRETER_OPT_FLAGS InterpreterOptFlags;
// make sure that call-as proc targets get processed when necessary.
CG_PROC * pCallAs = GetCallAsCG();
if (pCallAs)
pCallAs->GenNdrFormat(pCCB);
SetupFormatStrings(pCCB);
if ( ! (GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2) )
{
GenNdrFormatV1( pCCB );
UnsetupFormatStrings(pCCB);
return;
}
if ( GetFormatStringOffset() != -1 )
{
UnsetupFormatStrings(pCCB);
return;
}
pCCB->SetInObjectInterface( IsObject() );
pOldCGNodeContext = pCCB->SetCGNodeContext( this );
//
// If this procedure uses an explicit handle then set the
// NdrBindDescriptionOffset to 0 so that it will not try to output it's
// description when given the GenNdrParamOffLine method in the loop below.
// It's description must be part of the procedure description.
//
if ( GetHandleUsage() == HU_EXPLICIT )
{
GetHandleClassPtr()->SetNdrBindDescriptionOffset( 0 );
}
GetMembers( Iterator );
ParamNum = 0;
ServerBufferSize = 0;
ClientBufferSize = 0;
fServerMustSize = FALSE;
fClientMustSize = FALSE;
pCCB->SetInterpreterOutSize( 0 );
//
// Generate the offline portion of the format string for all of the params.
//
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
CG_NDR * pChild;
CG_NDR * pOldPlaceholder;
pChild = (CG_NDR *) pParam->GetChild();
//
// Primitive handles are totally ignored.
//
if ( pChild->GetCGID() == ID_CG_PRIMITIVE_HDL )
continue;
pParam->SetParamNumber( ParamNum++ );
pCCB->SetCurrentParam( (CG_PARAM *) pParam );
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
pChild->GenNdrParamOffline( pCCB );
// A procedure's buffer size does not depend on pipe arguments
if (pChild->IsPipeOrPipeReference())
{
if (pChild->GetChild()->HasAFixedBufferSize())
pParam->SetInterpreterMustSize(FALSE);
else
// There must be a union in there somewhere
pParam->SetInterpreterMustSize(TRUE);
}
else
{
BufSize = pChild->FixedBufferSize( pCCB );
if ( BufSize != -1 )
{
//
// If either the client's or server's fixed buffer size gets too
// big then we force the parameter to be sized.
//
if ( (pParam->IsParamIn() &&
((ClientBufferSize + BufSize) >= 65356)) ||
(pParam->IsParamOut() &&
((ServerBufferSize + BufSize) >= 65356)) )
{
fClientMustSize = TRUE;
fServerMustSize = TRUE;
}
else
{
pParam->SetInterpreterMustSize( FALSE );
if ( pParam->IsParamIn() )
ClientBufferSize += BufSize;
if ( pParam->IsParamOut() )
ServerBufferSize += BufSize;
}
}
else
{
if ( pParam->IsParamIn() )
fClientMustSize = TRUE;
if ( pParam->IsParamOut() )
fServerMustSize = TRUE;
}
}
pCCB->SetCurrentParam( 0 );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
}
//
// Generate the format string for the return type if needed.
//
if ( GetReturnType() )
{
CG_NDR * pChild;
CG_NDR * pOldPlaceholder;
GetReturnType()->SetParamNumber( ParamNum++ );
pChild = (CG_NDR *) GetReturnType()->GetChild();
pCCB->SetCurrentParam( GetReturnType() );
pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetReturnType() );
pChild->GenNdrParamOffline( pCCB );
BufSize = pChild->FixedBufferSize( pCCB );
if ( BufSize != -1 )
{
if ( (ServerBufferSize + BufSize) >= 65536 )
{
fServerMustSize = TRUE;
}
else
{
ServerBufferSize += BufSize;
GetReturnType()->SetInterpreterMustSize( FALSE );
}
}
else
fServerMustSize = TRUE;
pCCB->SetCurrentParam( 0 );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
}
pCCB->SetCurrentParam( 0 );
pProcFormatString = pCCB->GetProcFormatString();
SetFormatStringOffset( pProcFormatString->GetCurrentOffset() );
//
// Generate procedure description stuff for the interpreter if needed.
//
if ( (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER)
|| HasAPicklingAttribute() )
{
GenNdrFormatProcInfo( pCCB );
// Client side constant buffer size.
pProcFormatString->PushShort( ClientBufferSize );
// Server side constant buffer size.
pProcFormatString->PushShort( ServerBufferSize );
}
ITERATOR_INIT( Iterator );
InterpreterOptFlags.ServerMustSize = fServerMustSize;
InterpreterOptFlags.ClientMustSize = fClientMustSize;
InterpreterOptFlags.HasReturn = GetReturnType() != 0 ? 1 : 0;
InterpreterOptFlags.HasPipes = HasPipes();
InterpreterOptFlags.Unused = 0;
// New procedure flags.
pProcFormatString->PushByte( *((char *)&InterpreterOptFlags) );
// Number of parameters.
pProcFormatString->PushByte( ParamNum );
SetFormatStringParamStart( pProcFormatString->GetCurrentOffset() );
pCCB->SetInterpreterOutSize( 0 );
//
// Now generate the param info at the end of the format string.
//
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
CG_NDR * pChild;
CG_NDR * pOldPlaceholder;
pChild = (CG_NDR *) pParam->GetChild();
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
pChild = (CG_NDR *) pChild->GetChild();
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
pChild->GenNdrParamDescription( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
}
if ( GetReturnType() )
{
CG_NDR * pChild;
CG_NDR * pOldPlaceholder;
pChild = (CG_NDR *) GetReturnType()->GetChild();
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
pChild = (CG_NDR *) pChild->GetChild();
pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetReturnType() );
pChild->GenNdrParamDescription( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
}
pCCB->SetCGNodeContext( pOldCGNodeContext );
pCCB->SetInObjectInterface( FALSE );
SetFormatStringEndOffset( pProcFormatString->GetCurrentOffset() );
// save delta, in case the routine is optimized
short usParamStartDelta = (short) ( GetFormatStringParamStart() -
GetFormatStringOffset() );
SetFormatStringOffset( pProcFormatString->OptimizeFragment( this ) );
// Set param start!!!
SetFormatStringParamStart( GetFormatStringOffset() + usParamStartDelta );
//
// For interpreted procs we add some comments to the procedure format
// strings to make the stubs easier to read.
//
if ( ! (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER) )
return;
char * pComment;
short FormatOffset;
short Bytes;
Bytes = 32 + strlen( GetSymName() );
pComment = new char[Bytes];
sprintf( pComment, "\n\t/* Procedure %s */\n\n", GetSymName() );
pProcFormatString->AddComment( (short) GetFormatStringOffset(), pComment );
GetMembers( Iterator );
FormatOffset = (short) GetFormatStringParamStart();
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
Bytes = 32 + strlen( pParam->GetSymName() );
pComment = new char[Bytes];
sprintf( pComment,
"\n\t/* Parameter %s */\n\n",
pParam->GetSymName() );
pProcFormatString->AddComment( FormatOffset, pComment );
FormatOffset += 6;
}
if ( GetReturnType() )
{
pProcFormatString->AddComment(
FormatOffset, "\n\t/* Return value */\n\n" );
}
UnsetupFormatStrings(pCCB);
}
void
CG_PROC::GenNdrFormatProcInfo( CCB * pCCB )
/*++
The layout is:
handle type<1>
Oi and pickling flags <1>
[ rpc flags<4> ]
proc num <2>
stack size<2>
[ explicit handle description <> ]
--*/
{
FORMAT_STRING * pProcFormatString;
SetupFormatStrings(pCCB);
pProcFormatString = pCCB->GetProcFormatString();
if ( pCCB->IsInCallback() )
{
pProcFormatString->PushFormatChar( FC_CALLBACK_HANDLE );
}
else
{
if ( GetHandleUsage() == HU_IMPLICIT )
{
//
// Implicit handle type.
//
if ( IsAutoHandle() )
pProcFormatString->PushFormatChar( FC_AUTO_HANDLE );
if ( IsPrimitiveHandle() )
pProcFormatString->PushFormatChar( FC_BIND_PRIMITIVE );
if ( IsGenericHandle() )
{
pProcFormatString->PushFormatChar( FC_BIND_GENERIC );
// implicit generic handle needs to be registered.
pCCB->RegisterGenericHandleType(
GetHandleClassPtr()->GetHandleType() );
}
}
else
pProcFormatString->PushByte( 0 );
}
// Indicate if there is a need to init the full ptr or rpcss packages.
unsigned char OiFlags = 0;
if ( HasFullPtr() )
OiFlags |= Oi_FULL_PTR_USED;
if ( MustInvokeRpcSSAllocate() )
OiFlags |= Oi_RPCSS_ALLOC_USED;
if ( IsObject() )
{
OiFlags |= Oi_OBJECT_PROC;
if ( !ReturnsHRESULT() )
OiFlags |= Oi_IGNORE_OBJECT_EXCEPTION_HANDLING;
if ( (GetOptimizationFlags() & OPTIMIZE_INTERPRETER) &&
(GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2) )
OiFlags |= Oi_OBJ_USE_V2_INTERPRETER;
}
if ( TranslateOpBitsIntoUnsignedInt() )
OiFlags |= Oi_HAS_RPCFLAGS;
if ( GetCGID() == ID_CG_ENCODE_PROC )
{
if ( HasEncode() )
OiFlags |= ENCODE_IS_USED;
if ( HasDecode() )
OiFlags |= DECODE_IS_USED;
}
// Always do this.
OiFlags |= Oi_USE_NEW_INIT_ROUTINES;
if ( HasStatuses() )
OiFlags |= Oi_HAS_COMM_OR_FAULT;
pProcFormatString->PushByte( OiFlags );
// Rpc flags type. Only emitted if it's non-zero.
if ( TranslateOpBitsIntoUnsignedInt() )
pProcFormatString->PushLong( (long) TranslateOpBitsIntoUnsignedInt() );
// Proc num.
pProcFormatString->PushShort( (short) GetProcNum() );
long Size;
long AlphaSize;
long MipsSize;
long PpcSize;
long MacSize;
GetTotalStackSize( pCCB,
&Size,
&AlphaSize,
&MipsSize,
&PpcSize,
&MacSize );
//
// Use the push short stack offset method which outputs a #ifdef for
// Alpha, MIPS, and PPC, for which stack offsets are often different.
//
pProcFormatString->PushShortStackOffset( (short) Size,
(short) AlphaSize,
(short) MipsSize,
(short) PpcSize,
(short) MacSize );
//
// Output explicit handle description.
//
if ( GetHandleUsage() == HU_EXPLICIT )
{
CG_NDR * pOldPlaceholder;
CG_HANDLE * pHandle;
pHandle = GetHandleClassPtr();
pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetHandleUsagePtr() );
pHandle->GenNdrHandleFormat( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
//
// Patch up a pointer to context handle's offset<2> field.
//
if ( pHandle->GetCGID() == ID_CG_CONTEXT_HDL )
{
CG_NDR * pNdr;
CG_NDR * pPointer;
// Get the handle param's first child node.
pNdr = (CG_NDR *) GetHandleUsagePtr()->GetChild();
pPointer = 0;
while ( pNdr->IsPointer() )
{
pPointer = pNdr;
pNdr = (CG_NDR *) GetChild();
}
if ( pPointer )
{
long OffsetField;
OffsetField = pPointer->GetFormatStringOffset() + 2;
pCCB->GetFormatString()->PushShort(
pHandle->GetFormatStringOffset() - OffsetField,
OffsetField );
}
}
}
UnsetupFormatStrings(pCCB);
}
//
// ##########################################################################
// ----- Interpreted client stub generation. -----###########################
// ##########################################################################
//
void
CG_PROC::GenNdrSingleClientCall( CCB * pCCB )
/*++
Routine Description :
This is the top level routine for generating code for the single NDR call
case on the client side.
Arguments :
pCCB - pointer to the code control block
--*/
{
ISTREAM * pStream;
CG_ITERATOR Iterator;
expr_node * pFinalExpr;
CG_PARAM * pLastParam;
expr_node * pExpr;
pStream = pCCB->GetStream();
// Generate the format string.
GenNdrFormat( pCCB );
if ( GetReturnType() )
{
// The delcaration.
pStream->Write( "CLIENT_CALL_RETURN " RETURN_VALUE_VAR_NAME );
pStream->Write( ';' );
pStream->NewLine( 2 );
}
// For alpha, we need to emit a va_list.
pStream->IndentDec();
pStream->NewLine();
pStream->Write( ALPHA_IFDEF );
pStream->IndentInc();
pStream->NewLine();
pStream->Write( VA_LIST_TYPE_NAME" "VLIST_VAR_NAME";" );
// Emit the endif for Alpha.
pStream->IndentDec();
pStream->NewLine();
pStream->Write( "#endif" );
pStream->IndentInc();
pStream->NewLine();
//
// Emit the call into the stub in 2 flavors. One - with strict varags and
// one without. The strict varargs stuff will be emitted for the alpha.
//
GetMembers(Iterator);
pLastParam = 0;
while ( ITERATOR_GETNEXT( Iterator, pLastParam ) )
;
pStream->IndentDec();
pStream->NewLine();
pStream->Write( ALPHA_IFDEF );
pStream->IndentInc();
pStream->NewLine();
//
// Emit "va_start( vlist, last_param_name or 0);
// Do no emit the va_start if we have no parameters.
//
pFinalExpr = new expr_proc_call( VA_START_PROC_NAME );
((expr_proc_call *)pFinalExpr)->SetParam( new expr_param(
new expr_variable( VLIST_VAR_NAME,0)));
if ( pLastParam )
{
pExpr = new expr_variable(
pLastParam->GetResource()->GetResourceName(), 0 );
((expr_proc_call *)pFinalExpr)->SetParam( new expr_param( pExpr ) );
pFinalExpr->PrintCall( pStream, 0, 0 );
}
else if( IsObject() )
{
pExpr = new expr_variable("This");
((expr_proc_call *)pFinalExpr)->SetParam( new expr_param( pExpr ) );
pFinalExpr->PrintCall( pStream, 0, 0 );
}
// Generate alpha specific NdrClientCall.
pStream->NewLine();
pFinalExpr = GenCoreNdrSingleClientCall( pCCB, 2 );
pFinalExpr->PrintCall( pStream, 0, 0 );
// For a risc platform, we need to ensure a spill of every param on the
// stack. For this we generate code that takes the address of every param.
pStream->IndentDec();
pStream->NewLine();
pStream->Write( ELSE_IF_PPC_OR_MIPS );
pStream->NewLine();
pStream->IndentInc();
pStream->NewLine();
// Generate an expression suitable for risc platforms.
pFinalExpr = GenCoreNdrSingleClientCall( pCCB, 1 ); // 1 for RISC PLATFORMS
pFinalExpr->PrintCall( pStream, 0, 0 );
pStream->IndentDec();
pStream->NewLine();
// Now emit code for non-risc platforms.
pStream->Write( "#else" );
pStream->IndentInc();
pStream->NewLine();
pFinalExpr = GenCoreNdrSingleClientCall( pCCB, 0 ); // 0 for NON RISC PLATS.
pFinalExpr->PrintCall( pStream, 0, 0 );
pStream->IndentDec();
pStream->NewLine();
pStream->Write( "#endif" );
pStream->IndentInc();
pStream->NewLine();
if ( GetReturnType() )
{
CG_NDR * pNdr;
node_skl * pType;
pNdr = (CG_NDR *) GetReturnType()->GetChild();
pType = GetReturnType()->GetType();
pStream->Write("return ");
//
// Base type return value.
//
if ( pNdr->IsSimpleType() )
{
switch ( ((CG_BASETYPE *)pNdr)->GetFormatChar() )
{
case FC_HYPER :
pStream->Write( RETURN_VALUE_VAR_NAME ".Hyper;" );
break;
case FC_FLOAT :
pStream->Write( RETURN_VALUE_VAR_NAME ".Float;" );
break;
case FC_DOUBLE :
pStream->Write( RETURN_VALUE_VAR_NAME ".Double;" );
break;
default :
pType->PrintType( PRT_CAST_TO_TYPE, pStream );
pStream->Write( RETURN_VALUE_VAR_NAME ".Simple;" );
break;
}
pStream->NewLine();
return;
}
//
// A by-value struct or union.
//
if ( pNdr->IsStruct() || pNdr->IsUnion() )
{
expr_node * pExpr;
pExpr = new expr_variable( RETURN_VALUE_VAR_NAME ".Pointer" );
pExpr = MakeDerefExpressionOfCastPtrToType( pType, pExpr );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
return;
}
//
// Otherwise pointer or array.
//
pType->PrintType( PRT_CAST_TO_TYPE, pStream );
pStream->Write( RETURN_VALUE_VAR_NAME ".Pointer;" );
pStream->NewLine();
}
}
//
// ##########################################################################
// ----- Interpreted server stub generation. -----###########################
// ##########################################################################
//
void
CG_PROC::GenNdrSingleServerCall( CCB * pCCB )
/*++
Routine Description :
This is the top level routine for generating code for the single NDR call
case on the server side. It actually ends up being 3 calls.
Arguments :
pCCB - pointer to the code control block
--*/
{
ISTREAM * pStream;
// CG_PARAM * pParam;
expr_proc_call * pCallExpr;
char FormatStringExpr[80];
//
// On the server side we just use the format string that was generated
// during client stub generation if such generation occured.
//
if ( GetFormatStringOffset() == -1 )
GenNdrFormat( pCCB );
pCCB->SetCGNodeContext( this );
pStream = pCCB->GetStream();
//
// Output the server stub locals. There are two locals : the stub
// descriptor and the param struct.
//
GenNdrInterpretedServerLocals( pCCB );
pStream->NewLine();
//
// Make the single unmarshall call.
//
pCallExpr = new expr_proc_call( S_NDR_UNMARSHALL_RTN_NAME );
// Rpc message.
pCallExpr->SetParam( new expr_param(
new expr_variable( PRPC_MESSAGE_VAR_NAME ) ) );
// Stub message.
pCallExpr->SetParam( new expr_param(
new expr_u_address (
new expr_variable( STUB_MESSAGE_VAR_NAME ) ) ) );
// Stub descriptor.
pCallExpr->SetParam( new expr_param(
new expr_u_address (
new expr_variable(
pCCB->GetInterfaceCG()->GetStubDescName() ) ) ) );
sprintf( FormatStringExpr,
"&%s[%d]",
PROC_FORMAT_STRING_STRING_FIELD,
GetFormatStringOffset() );
// Format string pointer.
pCallExpr->SetParam( new expr_param(
new expr_variable( FormatStringExpr ) ) );
// Parameter structure pointer.
if ( ! IsNullCall() )
{
pCallExpr->SetParam( new expr_param(
new expr_u_address (
new expr_variable( "ParamStruct" ) ) ) );
}
else
{
pCallExpr->SetParam( new expr_param(
new expr_variable( "0" ) ) );
}
// Print the unmarshall call.
pCallExpr->PrintCall( pCCB->GetStream(),
0,
0 );
pStream->NewLine();
//
// Now make the call to the manager.
//
GenNdrInterpretedManagerCall( pCCB );
//
// Make the single marshall call.
//
pCallExpr = new expr_proc_call( S_NDR_MARSHALL_RTN_NAME );
// Stub message.
pCallExpr->SetParam( new expr_param(
new expr_u_address (
new expr_variable( STUB_MESSAGE_VAR_NAME ) ) ) );
// Format string pointer.
pCallExpr->SetParam( new expr_param(
new expr_variable( FormatStringExpr ) ) );
pStream->NewLine( 2 );
// Print the marshall routine call.
pCallExpr->PrintCall( pCCB->GetStream(),
0,
0 );
}
void
CG_PROC::GenNdrInterpretedServerLocals( CCB * pCCB )
/*++
Routine Description :
This routine outputs the two local variables for an interpreted server
stub. The two locals are the stub message and the param struct.
Arguments :
pCCB - pointer to the code control block
--*/
{
ISTREAM * pStream;
pStream = pCCB->GetStream();
// Stub message local.
pStream->Write( STUB_MESSAGE_TYPE_NAME " " STUB_MESSAGE_VAR_NAME ";" );
pStream->NewLine();
// Generate the param struct for non-null calls only.
if ( ! IsNullCall() )
{
GenNdrInterpreterParamStruct( pCCB );
pStream->Write( PARAM_STRUCT_TYPE_NAME " ParamStruct;" );
pStream->NewLine();
}
}
void
CG_PROC::GenNdrInterpreterParamStruct( CCB * pCCB,
BOOL fForAlpha )
/*++
Routine Description :
Outputs the param struct used in the /Oi server stub.
Arguments :
pCCB - pointer to the code control block
fForAlpha - TRUE if we're emitting an Alpha param struct.
--*/
{
CG_ITERATOR Iterator;
ISTREAM * pStream;
CG_PARAM * pParam;
CG_PARAM * pParamPrev;
CG_RETURN * pReturn;
CG_NDR * pNdr;
long Pad;
long PadPrev;
long PadNumber;
long IntMask;
unsigned short Env;
char Buffer[80];
pStream = pCCB->GetStream();
Env = pCommand->GetEnv();
if ( ! fForAlpha && Env == ENV_WIN32 )
{
pStream->IndentDec();
pStream->NewLine();
pStream->Write( "#ifndef _ALPHA_" );
pStream->IndentInc();
pStream->NewLine();
}
if ( (Env == ENV_DOS) || (Env == ENV_WIN16) )
pStream->Write( "#pragma pack(2)" );
else
pStream->Write( "#pragma pack(4)" );
pStream->NewLine();
pStream->Write( PARAM_STRUCT_TYPE_NAME );
pStream->IndentInc();
pStream->NewLine();
pStream->Write( '{' );
pStream->NewLine();
PadNumber = 0;
IntMask = fForAlpha ?
0x7 : ((Env == ENV_DOS) || (Env == ENV_WIN16)) ? 0x1 : 0x3;
GetMembers( Iterator );
if ( IsObject() )
{
pCCB->GetInterfaceCG()->GetThisDeclarator()->PrintType(
PRT_PARAM_OR_ID_DECLARATION,
pStream,
(node_skl *)0 );
// Padding.
if ( fForAlpha )
{
sprintf( Buffer, "char Pad%d[4];", PadNumber++ );
pStream->Write( Buffer );
pStream->NewLine();
}
}
pParamPrev = 0;
PadPrev = 0;
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
pNdr = (CG_NDR *) pParam->GetChild();
if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
pNdr = (CG_NDR *) pNdr->GetChild();
//
// We have to do some special stuff for MIPS for 8 byte aligned things
// on the stack.
//
if ( (pNdr->GetMemoryAlignment() == 8) && ! fForAlpha &&
(pParamPrev || IsObject()) )
{
long PrevEndOffset;
if ( pParamPrev )
{
PrevEndOffset = pParamPrev->GetStackOffset( pCCB, MIPS_STACK_SIZING );
PrevEndOffset += pParamPrev->GetStackSize();
PrevEndOffset += PadPrev;
}
else
{
//
// If this is the first param, but we're in an object proc,
// then don't forget about the 'this' pointer.
//
PrevEndOffset = 4;
}
if ( PrevEndOffset % 8 )
{
pStream->Write( "#ifdef _MIPS_" );
pStream->NewLine();
sprintf( Buffer, "char Pad%d[4];", PadNumber++ );
pStream->Write( Buffer );
pStream->NewLine();
pStream->Write( "#endif" );
pStream->NewLine();
pStream->Write( "#ifdef _PPC_" );
pStream->NewLine();
sprintf( Buffer, "char Pad%d[4];", PadNumber++ );
pStream->Write( Buffer );
pStream->NewLine();
pStream->Write( "#endif" );
pStream->NewLine();
}
}
// For Mac, the padding has to go before the parameter, not after.
if ( pCommand->IsAnyMac() )
{
Pad = 0;
//
// Generate some padding if needed.
//
if ( pParam->GetStackSize() & IntMask )
{
Pad = (IntMask + 1) - (pParam->GetStackSize() & IntMask);
pStream->NewLine();
sprintf( Buffer, "char Pad%d[%d];", PadNumber++, Pad );
pStream->Write( Buffer );
}
}
// Print the field declaration.
pParam->GetResource()->GetType()->PrintType(
PRT_PARAM_OR_ID_DECLARATION,
pStream,
(node_skl *)0 );
if ( ! pCommand->IsAnyMac() )
{
Pad = 0;
//
// Generate some padding if needed.
//
if ( pParam->GetStackSize() & IntMask )
{
Pad = (IntMask + 1) - (pParam->GetStackSize() & IntMask);
sprintf( Buffer, "char Pad%d[%d];", PadNumber++, Pad );
pStream->Write( Buffer );
pStream->NewLine();
}
}
pParamPrev = pParam;
PadPrev = Pad;
}
// Add the return type if one is present.
if ( pReturn = GetReturnType() )
{
pReturn->GetResource()->GetType()->PrintType(
PRT_PARAM_OR_ID_DECLARATION,
pStream,
(node_skl *)0 );
}
pStream->Write( "};" );
pStream->IndentDec();
pStream->NewLine();
pStream->Write( "#pragma pack()" );
if ( Env == ENV_WIN32 )
pStream->IndentDec();
pStream->NewLine();
if ( ! fForAlpha && Env == ENV_WIN32 )
{
pStream->Write( "#else" );
pStream->IndentInc();
pStream->NewLine();
GenNdrInterpreterParamStruct( pCCB, TRUE );
pStream->Write( "#endif" );
pStream->IndentInc();
pStream->NewLine( 2 );
}
}
void
CG_PROC::GenNdrInterpretedManagerCall( CCB * pCCB )
/*++
Routine Description :
This routine outputs the call to the manager for interpreted stubs.
Arguments :
pCCB - pointer to the code control block
--*/
{
CG_ITERATOR Iterator;
CG_PARAM * pParam;
// CG_RETURN * pReturn;
expr_proc_call * pCall;
expr_node * pExpr;
if ( GetCallAsName() )
{
pCall = new expr_proc_call( GenMangledCallAsName( pCCB ) );
}
else
pCall = new expr_proc_call( GetType()->GetSymName() );
GetMembers( Iterator );
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
CG_NDR * pNdr;
char * pName;
expr_node * pExpr;
pNdr = (CG_NDR *) pParam->GetChild();
pName = new char[80];
strcpy( pName, "pParamStruct->" );
strcat( pName, pParam->GetResource()->GetResourceName() );
pExpr = new expr_variable( pName );
pCall->SetParam( new expr_param ( pExpr ) );
}
//
// epv stuff
//
expr_node * pExprTemp;
if( pCCB->IsMEpV() && (GetCGID() != ID_CG_CALLBACK_PROC) )
{
unsigned short M, m;
CSzBuffer Buffer;
char * pTemp;
pCCB->GetVersion( &M, &m );
Buffer.Set("((");
Buffer.Append(pCCB->GetInterfaceName());
Buffer.Append(pCCB->GenMangledName());
Buffer.Append("_");
Buffer.Append(pCCB->IsOldNames() ? "SERVER_EPV" : "epv_t");
Buffer.Append(" *)(");
Buffer.Append(PRPC_MESSAGE_MANAGER_EPV_NAME);
Buffer.Append("))");
// sprintf( Buffer,
// "((%s%s_%s *)(%s))",
// pCCB->GetInterfaceName(),
// pCCB->GenMangledName(),
// pCCB->IsOldNames() ? "SERVER_EPV" : "epv_t",
// PRPC_MESSAGE_MANAGER_EPV_NAME );
pTemp = new char [ strlen( Buffer ) + 1 ];
strcpy( pTemp, Buffer );
pExprTemp = new expr_variable( pTemp );//this has the rhs expr for the
// manager epv call. Sneaky !
pCall = (expr_proc_call *)new expr_pointsto( pExprTemp, pCall );
}
//
// end epv stuff
//
if ( GetReturnType() )
{
CG_NDR * pC = (CG_NDR *) GetReturnType()->GetChild();
if( pC->GetCGID() == ID_CG_CONTEXT_HDL )
{
expr_proc_call * pProc = new expr_proc_call( "NDRSContextValue" );
pProc->SetParam( new expr_param(
new expr_variable(
"pParamStruct->" RETURN_VALUE_VAR_NAME ) ) );
// cast the proc call to this type.
pExpr = MakeDerefExpressionOfCastPtrToType(
GetReturnType()->GetType(),
pProc );
pExpr = new expr_assign (pExpr, pCall );
}
else
{
pExpr = new expr_assign(
new expr_variable(
"pParamStruct->" RETURN_VALUE_VAR_NAME ),
pCall );
}
}
else
pExpr = pCall;
pCCB->GetStream()->NewLine();
pExpr->PrintCall( pCCB->GetStream(), 0, 0 );
pCCB->GetStream()->NewLine();
}
void
CG_PROC::GenNdrThunkInterpretedServerStub( CCB * pCCB )
{
ISTREAM * pStream;
pStream = pCCB->GetStream();
pStream->NewLine();
if ( pCCB->GetInterfaceCG()->GetCGID() == ID_CG_INHERITED_OBJECT_INTERFACE )
pStream->Write( "static " );
pStream->Write( "void __RPC_API" );
pStream->NewLine();
pStream->Write( pCCB->GetInterfaceName() );
pStream->Write( '_' );
pStream->Write( GetType()->GetSymName() );
// if ( IsObject() )
pStream->Write( "_Thunk" );
pStream->Write( '(' );
pStream->IndentInc();
pStream->NewLine();
pStream->Write( PSTUB_MESSAGE_TYPE_NAME " " PSTUB_MESSAGE_PAR_NAME " )" );
pStream->IndentDec();
pStream->NewLine();
pStream->Write( '{' );
pStream->IndentInc();
pStream->NewLine();
GenNdrInterpreterParamStruct( pCCB );
pStream->Write( PARAM_STRUCT_TYPE_NAME " * pParamStruct;" );
pStream->NewLine( 2 );
pStream->Write( "pParamStruct = (" PARAM_STRUCT_TYPE_NAME " *) " );
pStream->Write( PSTUB_MESSAGE_PAR_NAME "->StackTop;" );
pStream->NewLine();
GenNdrInterpretedManagerCall( pCCB );
pStream->IndentDec();
pStream->NewLine();
pStream->Write( '}' );
pStream->NewLine();
}
void
CG_PROC::GenNdrOldInterpretedServerStub( CCB * pCCB )
{
#ifdef TEMPORARY_OI_SERVER_STUBS
// This code is being generated temporarily to enable easier debugging
// of server side -Oi stubs. Normally server side stubs do not exist. And
// the server side runtime calls the Server side interpreter directly. This
// causes debugging problems if we want to breakpoint on a method on an
// interface. Therefore till we get the system converted to -Oi and the
// stress stabilizes, we will emit a server side procedure which will
// enable breakpointing per interface proc.
// This emits just the server side prolog for -Oi.
S_GenProlog( pCCB );
// Emit the call to NdrStubCall or NdrServerCall.
PNAME pProcName = IsObject() ? S_OBJECT_NDR_CALL_RTN_NAME :
S_NDR_CALL_RTN_NAME;
expr_proc_call * pProc = new expr_proc_call( pProcName );
ITERATOR ParamList;
expr_node * pParam;
// Set the parameters.
pCCB->GetListOfParamResources( ParamList );
while( ITERATOR_GETNEXT( ParamList, pParam ) )
{
pProc->SetParam( pParam );
}
// Emit the call to the interpreter.
pProc->PrintCall( pCCB->GetStream(), 0, 0 );
Out_IndentDec( pCCB );
Out_ProcClosingBrace( pCCB );
#else TEMPORARY_OI_SERVER_STUBS
//
// Generate the function header.
//
S_GenProlog( pCCB );
//
// Do the single call code generation. This includes the
// declarations of the three server locals : the stub message, the
// return variable if needed, and the parameter structure.
//
GenNdrSingleServerCall( pCCB );
// Generate end stuff.
Out_IndentDec( pCCB );
Out_ProcClosingBrace( pCCB );
#endif // TEMPORARY_OI_SERVER_STUBS
}
//
// Param format string generation.
//
void
CG_PARAM::GenNdrFormat( CCB * pCCB )
/*++
Routine Description :
Calls the parameter's child node to generate it's format string.
Arguments :
pCCB - pointer to the code control block
--*/
{
if ( GetFormatStringOffset() != -1 )
return;
//
// Call the param child to generate it's format string.
//
((CG_NDR *)GetChild())->GenNdrFormat( pCCB );
//
// Set the param node's format string offset equal to the child.
//
SetFormatStringOffset( ((CG_NDR *)GetChild())->GetFormatStringOffset() );
}
//
// Individual NDR routine calls output.
//
void
CG_PARAM::GenNdrMarshallCall( CCB * pCCB )
/*++
Routine Description :
Outputs a parameter's ndr marshall routine call.
Arguments :
pCCB - pointer to the code control block
--*/
{
ISTREAM * pStream;
CG_NDR * pChild;
FORMAT_STRING * pFormatString;
PNAME pParamName;
ID_CG ParamId;
long NameIndex;
long FormatOffset;
BOOL fTakeAddress;
BOOL fDereference;
NDR_ALIGN_ACTION AlignAction;
pStream = pCCB->GetStream();
pChild = (CG_NDR *)GetChild();
ParamId = pChild->GetCGID();
pParamName = GetResource()->GetResourceName();
if ( (ParamId == ID_CG_PRIMITIVE_HDL) ||
((ParamId == ID_CG_PTR) &&
(((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_PRIMITIVE_HDL)) )
return;
//
// For a generic handle, get the handle data type and then continue.
//
if ( ParamId == ID_CG_GENERIC_HDL )
{
pChild = (CG_NDR *)pChild->GetChild();
ParamId = pChild->GetCGID();
}
//
// Since a ref pointer is not shipped, we must use it's child to figure
// out the alignment action and next alignment state.
//
if ( pChild->IsPointer() &&
(pChild->GetCGID() != ID_CG_INTERFACE_PTR) &&
(pChild->GetCGID() != ID_CG_STRING_PTR) &&
(pChild->GetCGID() != ID_CG_STRUCT_STRING_PTR) &&
(pChild->GetCGID() != ID_CG_SIZE_STRING_PTR) &&
(pChild->GetCGID() != ID_CG_SIZE_PTR) &&
(pChild->GetCGID() != ID_CG_SIZE_LENGTH_PTR) &&
(((CG_POINTER *)pChild)->GetPtrType() == PTR_REF) )
{
CG_NDR * pPtrChild = (CG_NDR *) pChild->GetChild();
AlignAction = pCCB->NdrAlignmentAction( pPtrChild->GetWireAlignment() );
pPtrChild->SetNextNdrAlignment( pCCB );
}
else
{
AlignAction = pCCB->NdrAlignmentAction( pChild->GetWireAlignment() );
pChild->SetNextNdrAlignment( pCCB );
}
if ( (ParamId == ID_CG_CONTEXT_HDL) ||
((ParamId == ID_CG_PTR) &&
(((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_CONTEXT_HDL)) )
{
if ( pCCB->GetCodeGenSide() == CGSIDE_CLIENT )
{
Out_CContextHandleMarshall( pCCB,
pParamName,
(ParamId == ID_CG_PTR) );
}
else
{
CG_CONTEXT_HANDLE * pContextHandle;
pContextHandle = (ParamId == ID_CG_PTR) ?
(CG_CONTEXT_HANDLE *) pChild->GetChild() :
(CG_CONTEXT_HANDLE *) pChild;
pCCB->RegisterContextHandleType( pContextHandle->GetHandleType() );
Out_SContextHandleMarshall( pCCB,
pParamName,
pContextHandle->GetRundownRtnName() );
}
return;
}
if ( pChild->GetCGID() == ID_CG_ENUM )
{
expr_proc_call * pCall;
long fc;
expr_node * pExpr;
fc = (long) ((CG_ENUM *)pChild)->GetFormatChar();
pCall = new expr_proc_call( "NdrSimpleTypeMarshall" );
pExpr = new expr_u_address (
new expr_variable( STUB_MESSAGE_VAR_NAME ) );
pExpr = MakeExpressionOfCastToTypeName(PSTUB_MESSAGE_TYPE_NAME , pExpr);
pCall->SetParam( new expr_param( pExpr ) );
pExpr = new expr_u_address ( new expr_variable( pParamName ) );
pExpr = MakeCastExprPtrToUChar( pExpr );
pCall->SetParam( new expr_param( pExpr ) );
pCall->SetParam( new expr_param(
new expr_constant( fc ) ) );
pStream->NewLine();
pCall->PrintCall( pStream, 0, 0 );
return;
}
if ( pChild->IsSimpleType() )
{
pStream->NewLine();
OutputNdrAlignmentAction( pCCB, AlignAction );
//
// Now make the assignment expression and increment with cast, like :
//
// *((<type> *)_StubMsg.Buffer)++ = <var>;
//
expr_node * pExpr;
expr_variable * pBufVar;
expr_variable * pVar;
pBufVar = new expr_variable( STUB_MSG_BUFFER_VAR_NAME );
pVar = new expr_variable( pParamName );
pExpr = MakeExpressionOfCastPtrToType( pChild->GetType(), pBufVar );
pExpr = new expr_post_incr( pExpr );
pExpr = new expr_u_deref( pExpr );
pExpr = new expr_assign( pExpr, pVar );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
return;
}
if ( pChild->IsPointerToBaseType() &&
(((CG_POINTER *)pChild)->GetPtrType() == PTR_REF) &&
(((CG_NDR *)pChild->GetChild())->GetCGID() != ID_CG_ENUM) )
{
CG_POINTER * pPointer;
CG_NDR * pBasetype;
expr_node * pExpr;
expr_variable * pBufVar;
expr_variable * pVar;
pPointer = (CG_POINTER *) pChild;
pBasetype = (CG_NDR *) pPointer->GetChild();
if ( pBasetype->GetCGID() == ID_CG_GENERIC_HDL )
pBasetype = (CG_NDR *) pBasetype->GetChild();
pBufVar = new expr_variable( STUB_MSG_BUFFER_VAR_NAME );
pVar = new expr_variable( pParamName );
pStream->NewLine();
OutputNdrAlignmentAction( pCCB, AlignAction );
//
// Now make the assignment expression and increment with cast, like :
//
// *((<type>)_StubMsg.Buffer)++ = *<var>;
//
pExpr = MakeExpressionOfCastPtrToType( pBasetype->GetType(), pBufVar );
pExpr = new expr_post_incr( pExpr );
pExpr = new expr_u_deref( pExpr );
pExpr = new expr_assign( pExpr, new expr_u_deref(pVar) );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
return;
}
GenNdrTopLevelAttributeSupport( pCCB );
pFormatString = pCCB->GetFormatString();
FormatOffset = pChild->GetFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
//
// If the param is a by-value struct or union then set the fTakeAddress
// flag.
//
fTakeAddress = pChild->IsStruct() || pChild->IsUnion()
|| pChild->IsXmitRepOrUserMarshal();
//
// If the param is an array and we're in the server stub then we
// must dereference it.
//
fDereference = (pCCB->GetCodeGenSide() == CGSIDE_SERVER) &&
pChild->IsArray();
//
// For ref pointers with no funky attributes, we optimize by calling
// the pointee's routine directly.
//
if ( pChild->IsPointer() && ((CG_POINTER *)pChild)->IsBasicRefPointer() )
{
CG_POINTER * pPointer;
pPointer = (CG_POINTER *) pChild;
switch ( pPointer->GetCGID() )
{
case ID_CG_STRING_PTR :
if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
break;
FormatOffset = pPointer->GetFormatStringOffset() + 2;
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
case ID_CG_SIZE_STRING_PTR :
if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
break;
FormatOffset = pPointer->GetPointeeFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
case ID_CG_STRUCT_STRING_PTR :
break;
default :
FormatOffset = pPointer->GetPointeeFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
}
}
Out_NdrMarshallCall( pCCB,
pNdrRoutineNames[NameIndex],
pParamName,
FormatOffset,
fTakeAddress,
fDereference );
}
void
CG_PARAM::GenNdrUnmarshallCall( CCB * pCCB )
/*++
Routine Description :
Outputs a parameter's ndr unmarshall routine call.
Arguments :
pCCB - pointer to the code control block
--*/
{
ISTREAM * pStream;
CG_NDR * pChild;
FORMAT_STRING * pFormatString;
PNAME pParamName;
ID_CG ParamId;
long NameIndex;
long FormatOffset;
BOOL fMustAllocFlag = FALSE;
BOOL fTakeAddress = TRUE;
NDR_ALIGN_ACTION AlignAction;
pStream = pCCB->GetStream();
pChild = (CG_NDR *)GetChild();
ParamId = pChild->GetCGID();
pParamName = GetResource()->GetResourceName();
if ( (ParamId == ID_CG_PRIMITIVE_HDL) ||
((ParamId == ID_CG_PTR) &&
(((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_PRIMITIVE_HDL)) )
return;
//
// For a generic handle, get the handle data type and then continue.
//
if ( ParamId == ID_CG_GENERIC_HDL )
{
pChild = (CG_NDR *)pChild->GetChild();
ParamId = pChild->GetCGID();
}
BOOL IsOutOnly;
IsOutOnly = ! IsParamIn() || (GetCGID() == ID_CG_RETURN);
//
// Since a ref pointer is not shipped, we must use it's child to figure
// out the alignment action and next alignment state.
//
if ( pChild->IsPointer() &&
(pChild->GetCGID() != ID_CG_INTERFACE_PTR) &&
(pChild->GetCGID() != ID_CG_STRING_PTR) &&
(pChild->GetCGID() != ID_CG_STRUCT_STRING_PTR) &&
(pChild->GetCGID() != ID_CG_SIZE_STRING_PTR) &&
(pChild->GetCGID() != ID_CG_SIZE_PTR) &&
(pChild->GetCGID() != ID_CG_SIZE_LENGTH_PTR) &&
(((CG_POINTER *)pChild)->GetPtrType() == PTR_REF) )
{
CG_NDR * pPtrChild = (CG_NDR *) pChild->GetChild();
AlignAction = pCCB->NdrAlignmentAction( pPtrChild->GetWireAlignment() );
pPtrChild->SetNextNdrAlignment( pCCB );
}
else
{
AlignAction = pCCB->NdrAlignmentAction( pChild->GetWireAlignment() );
pChild->SetNextNdrAlignment( pCCB );
}
if ( (ParamId == ID_CG_CONTEXT_HDL) ||
( (ParamId == ID_CG_PTR) &&
(((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_CONTEXT_HDL) ) )
{
if ( pCCB->GetCodeGenSide() == CGSIDE_CLIENT )
{
BOOL Initialize;
Initialize = IsOutOnly && (ParamId == ID_CG_PTR);
Out_CContextHandleUnmarshall( pCCB,
pParamName,
Initialize,
GetCGID() == ID_CG_RETURN );
}
else
{
Out_SContextHandleUnmarshall( pCCB,
pParamName,
IsOutOnly );
}
return;
}
if ( pChild->GetCGID() == ID_CG_ENUM )
{
expr_proc_call * pCall;
long fc;
expr_node * pExpr;
fc = (long) ((CG_ENUM *)pChild)->GetFormatChar();
pCall = new expr_proc_call( "NdrSimpleTypeUnmarshall" );
pExpr = new expr_u_address(new expr_variable(STUB_MESSAGE_VAR_NAME));
pExpr = MakeExpressionOfCastToTypeName(PSTUB_MESSAGE_TYPE_NAME , pExpr);
pCall->SetParam( new expr_param( pExpr ) );
pExpr = new expr_u_address ( new expr_variable( pParamName ) );
pExpr = MakeCastExprPtrToUChar( pExpr );
pCall->SetParam( new expr_param( pExpr ) );
pCall->SetParam( new expr_param(
new expr_constant( fc ) ) );
pStream->NewLine();
pCall->PrintCall( pStream, 0, 0 );
return;
}
if ( pChild->IsSimpleType() )
{
pStream->NewLine();
OutputNdrAlignmentAction( pCCB, AlignAction );
//
// Now make the assignment expression and increment with cast, like :
//
// <var> = *((<type> *)_StubMsg.Buffer)++;
//
expr_node * pExpr;
expr_variable * pBufVar;
expr_variable * pVar;
pBufVar = new expr_variable( STUB_MSG_BUFFER_VAR_NAME );
pVar = new expr_variable( pParamName );
pExpr = MakeExpressionOfCastPtrToType( pChild->GetType(), pBufVar );
pExpr = new expr_post_incr( pExpr );
pExpr = new expr_u_deref( pExpr );
pExpr = new expr_assign( pVar, pExpr );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
return;
}
if ( pChild->IsPointerToBaseType() &&
(((CG_POINTER *)pChild)->GetPtrType() == PTR_REF) &&
(((CG_NDR *)pChild->GetChild())->GetCGID() != ID_CG_ENUM) )
{
CG_POINTER * pPointer;
CG_NDR * pBasetype;
expr_node * pExpr;
expr_variable * pBufVar;
expr_variable * pVar;
pStream->NewLine();
pPointer = (CG_POINTER *) pChild;
pBasetype = (CG_NDR *) pPointer->GetChild();
if ( pBasetype->GetCGID() == ID_CG_GENERIC_HDL )
pBasetype = (CG_NDR *) pBasetype->GetChild();
pBufVar = new expr_variable( STUB_MSG_BUFFER_VAR_NAME );
pVar = new expr_variable( pParamName );
OutputNdrAlignmentAction( pCCB, AlignAction );
//
// Now make the assignment of the pointer to the current buffer
// pointer (server) or copy the incomming referent's value (client)
// and increment the buffer pointer.
//
pExpr = MakeExpressionOfCastPtrToType( pBasetype->GetType(), pBufVar );
if ( pCCB->GetCodeGenSide() == CGSIDE_SERVER )
{
pExpr = new expr_assign( pVar, pExpr );
}
else
{
pExpr = new expr_post_incr( pExpr );
pExpr = new expr_assign(
new expr_u_deref( pVar ),
new expr_u_deref( pExpr ) );
}
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
if ( pCCB->GetCodeGenSide() == CGSIDE_SERVER )
{
pStream->Write( STUB_MSG_BUFFER_VAR_NAME " += " );
pExpr = new expr_sizeof( pBasetype->GetType() );
// pExpr = new expr_b_arithmetic( OP_PLUS, pBufVar, pExpr );
// pExpr = new expr_assign( pBufVar, pExpr );
pExpr->Print( pStream );
pStream->Write( ";" );
pStream->NewLine();
}
return;
}
if ( pChild->GetCGID() == ID_CG_BC_PTR )
GenNdrTopLevelAttributeSupport( pCCB );
pFormatString = pCCB->GetFormatString();
//
// If this is a by-value structure or union then use the mangled
// local pointer variable to the same type.
//
if ( pChild->IsStruct() || pChild->IsUnion() ||
pChild->IsXmitRepOrUserMarshal() )
{
char * pName;
pName = new char[strlen(pParamName) + 10];
strcpy( pName, LOCAL_NAME_POINTER_MANGLE );
strcat( pName, pParamName );
pParamName = pName;
//
// If this is a regular structure or an encapsulated struct (union)
// being returned, then zero it out.
//
if( (GetCGID() == ID_CG_RETURN) &&
(pChild->IsStruct() || pChild->IsUnion()) )
{
Out_MemsetToZero( pCCB,
new expr_variable( pParamName, 0 ),
new expr_sizeof( pChild->GetType() ) );
}
}
FormatOffset = pChild->GetFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
//
// For ref pointers with no funky attributes, we optimize by calling
// the pointee's routine directly.
//
if ( pChild->IsPointer() && ((CG_POINTER *)pChild)->IsBasicRefPointer() )
{
CG_POINTER * pPointer;
pPointer = (CG_POINTER *) pChild;
switch ( pPointer->GetCGID() )
{
case ID_CG_STRING_PTR :
if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
break;
FormatOffset = pPointer->GetFormatStringOffset() + 2;
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
case ID_CG_SIZE_STRING_PTR :
if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
break;
FormatOffset = pPointer->GetPointeeFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
case ID_CG_STRUCT_STRING_PTR :
break;
default :
FormatOffset = pPointer->GetPointeeFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
}
}
Out_NdrUnmarshallCall( pCCB,
pNdrRoutineNames[NameIndex],
pParamName,
FormatOffset,
fTakeAddress,
fMustAllocFlag );
}
void
CG_PARAM::GenNdrBufferSizeCall( CCB * pCCB )
/*++
Routine Description :
Outputs a parameter's ndr buffer sizing routine call.
Arguments :
pCCB - pointer to the code control block
--*/
{
CG_NDR * pChild;
FORMAT_STRING * pFormatString;
PNAME pParamName;
ID_CG ParamId;
long NameIndex;
long FormatOffset;
BOOL fTakeAddress;
BOOL fDereference;
pChild = (CG_NDR *)GetChild();
ParamId = pChild->GetCGID();
//
// Primitive handle contributes no size.
//
if ( (ParamId == ID_CG_PRIMITIVE_HDL) ||
((ParamId == ID_CG_PTR) &&
(((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_PRIMITIVE_HDL)) )
return;
//
// For a generic handle, get the handle data type and then continue.
//
if ( ParamId == ID_CG_GENERIC_HDL )
{
pChild = (CG_NDR *)pChild->GetChild();
ParamId = pChild->GetCGID();
}
if ( ParamId == ID_CG_CONTEXT_HDL ||
((ParamId == ID_CG_PTR) &&
(((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_CONTEXT_HDL)) )
{
ISTREAM * pStream = pCCB->GetStream();
pStream->NewLine();
pStream->Write( STUB_MSG_LENGTH_VAR_NAME " += 20;" );
pStream->NewLine();
return;
}
if ( pChild->IsSimpleType() )
{
ISTREAM * pStream = pCCB->GetStream();
pStream->NewLine();
pStream->Write( STUB_MSG_LENGTH_VAR_NAME " += 16;" );
pStream->NewLine();
return;
}
if ( pChild->IsPointerToBaseType() )
{
ISTREAM * pStream = pCCB->GetStream();
pStream->NewLine();
pStream->Write( STUB_MSG_LENGTH_VAR_NAME " += 24;" );
pStream->NewLine();
return;
}
GenNdrTopLevelAttributeSupport( pCCB );
pFormatString = pCCB->GetFormatString();
FormatOffset = pChild->GetFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
pParamName = GetResource()->GetResourceName();
//
// If the param is a by-value struct or union then set the fTakeAddress
// flag.
//
fTakeAddress = pChild->IsStruct() || pChild->IsUnion()
|| pChild->IsXmitRepOrUserMarshal();
//
// If the param is an array and we're in the server stub then we
// must dereference it.
//
fDereference = (pCCB->GetCodeGenSide() == CGSIDE_SERVER) &&
pChild->IsArray();
//
// For ref pointers with no funky attributes, we optimize by calling
// the pointee's routine directly.
//
if ( pChild->IsPointer() && ((CG_POINTER *)pChild)->IsBasicRefPointer() )
{
CG_POINTER * pPointer;
pPointer = (CG_POINTER *) pChild;
switch ( pPointer->GetCGID() )
{
case ID_CG_STRING_PTR :
if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
break;
FormatOffset = pPointer->GetFormatStringOffset() + 2;
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
case ID_CG_SIZE_STRING_PTR :
if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
break;
FormatOffset = pPointer->GetPointeeFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
case ID_CG_STRUCT_STRING_PTR :
break;
default :
FormatOffset = pPointer->GetPointeeFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
}
}
Out_NdrBufferSizeCall( pCCB,
pNdrRoutineNames[NameIndex],
pParamName,
FormatOffset,
fTakeAddress,
fDereference,
FALSE ); // _StubMsg
}
void
GenDontCallFreeInstAssign(
CCB * pCCB,
int SetupValue
)
/*++
a helper routine for GenNdrFreeCall.
Generates an assignment that sets or resets StubMsg.fDontCallFreeInst.
--*/
{
ISTREAM * pStream = pCCB->GetStream();
pStream->NewLine();
pStream->Write( STUB_MESSAGE_VAR_NAME );
pStream->Write( ".fDontCallFreeInst = " );
pStream->Write( SetupValue ? "1;"
: "0;" );
}
void
CG_PARAM::GenNdrFreeCall( CCB * pCCB )
/*++
Routine Description :
Outputs a parameter's ndr free routine call.
Arguments :
pCCB - pointer to the code control block
--*/
{
CG_PROC * pProc;
CG_NDR * pChild;
FORMAT_STRING * pFormatString;
PNAME pParamName;
long Index;
BOOL fTakeAddress;
BOOL fDereference;
pProc = (CG_PROC *) pCCB->GetCGNodeContext();
//
// If the proc uses RpcSs then don't emit any freeing code.
//
if ( pProc->MustInvokeRpcSSAllocate() )
return;
pChild = (CG_NDR *) GetChild();
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
pChild = (CG_NDR *) pChild->GetChild();
//
// Check if we need to make a call to an NDR freeing routine for this data.
//
if ( pChild->ShouldFreeOffline() )
{
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
pChild = (CG_NDR *) pChild->GetChild();
GenNdrTopLevelAttributeSupport( pCCB );
pFormatString = pCCB->GetFormatString();
Index = (long) pFormatString->GetFormatChar(
pChild->GetFormatStringOffset() );
pParamName = GetResource()->GetResourceName();
//
// If the param is a by-value struct or union then set the fTakeAddress
// flag.
//
fTakeAddress = pChild->IsStruct() || pChild->IsUnion()
|| pChild->IsXmitRepOrUserMarshal();
fDereference = FALSE;
if ( GetDontCallFreeInst() )
GenDontCallFreeInstAssign( pCCB, 1 );
Out_NdrFreeCall( pCCB,
pNdrRoutineNames[Index],
pParamName,
pChild->GetFormatStringOffset(),
fTakeAddress,
fDereference );
if ( GetDontCallFreeInst() )
GenDontCallFreeInstAssign( pCCB, 0 );
}
//
// Now generate any needed inline freeing.
//
pChild->GenFreeInline( pCCB );
}
void
CG_PARAM::GenNdrTopLevelAttributeSupport(
CCB * pCCB,
BOOL fForClearOut )
/*++
Routine Description :
Outputs the assignment(s) to the stub message MaxCount, ActualCount,
and/or Offset fields, for support of top level conformant and/or
varying arrays, attributed pointers, and non-encapsulated unions for
mixed model stubs.
Arguments :
pCCB - pointer to the code control block
--*/
{
CG_NDR * pChild;
ISTREAM * pStream = pCCB->GetStream();
expr_node * pExpr;
expr_node * pSizeOrSwitchIsExpr;
expr_node * pFirstIsExpr;
expr_node * pLengthIsExpr;
ID_CG ParamId;
pChild = (CG_NDR *)GetChild();
ParamId = pChild->GetCGID();
// Skip over pointers and generic handles.
while ( (ParamId == ID_CG_PTR) || (ParamId == ID_CG_GENERIC_HDL) )
{
pChild = (CG_NDR *) pChild->GetChild();
ParamId = pChild->GetCGID();
}
//
// Multidimensional conformant/varying arrays and sized pointers of
// sized pointers need some special handling.
//
if ( (pChild->IsArray() && ((CG_ARRAY *)pChild)->IsMultiConfOrVar()) ||
(pChild->IsPointer() && ((CG_POINTER *)pChild)->IsMultiSize()) )
{
CSzBuffer Buffer;
pStream->NewLine();
if ( (ParamId == ID_CG_CONF_ARRAY) ||
(ParamId == ID_CG_CONF_VAR_ARRAY) ||
(ParamId == ID_CG_SIZE_PTR) ||
(ParamId == ID_CG_SIZE_LENGTH_PTR) )
{
Buffer.Set(pChild->IsArray() ? "(unsigned long) " : "");
Buffer.Append("_maxcount_");
Buffer.Append(GetType()->GetSymName());
// sprintf( Buffer,
// "%s_maxcount_%s",
// pChild->IsArray() ? "(unsigned long) " : "",
// GetType()->GetSymName() );
if ( pChild->IsPointer() )
pExpr = new expr_variable(
STUB_MESSAGE_VAR_NAME ".SizePtrCountArray" );
else
pExpr = new expr_variable(
STUB_MESSAGE_VAR_NAME ".MaxCount" );
pExpr = new expr_assign( pExpr, new expr_variable( Buffer ) );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
}
if ( (ParamId == ID_CG_CONF_VAR_ARRAY) ||
(ParamId == ID_CG_VAR_ARRAY) ||
(ParamId == ID_CG_SIZE_LENGTH_PTR) )
{
Buffer.Set(pChild->IsArray() ? "(unsigned long) " : "");
Buffer.Append("_offset_");
Buffer.Append(GetType()->GetSymName());
// sprintf( Buffer,
// "%s_offset_%s",
// pChild->IsArray() ? "(unsigned long) " : "",
// GetType()->GetSymName() );
if ( pChild->IsPointer() )
pExpr = new expr_variable(
STUB_MESSAGE_VAR_NAME ".SizePtrOffsetArray" );
else
pExpr = new expr_variable(
STUB_MESSAGE_VAR_NAME ".Offset" );
pExpr = new expr_assign( pExpr, new expr_variable( Buffer ) );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
Buffer.Set(pChild->IsArray() ? "(unsigned long) " : "");
Buffer.Append("_length_");
Buffer.Append(GetType()->GetSymName());
// sprintf( Buffer,
// "%s_length_%s",
// pChild->IsArray() ? "(unsigned long) " : "",
// GetType()->GetSymName() );
if ( pChild->IsPointer() )
pExpr = new expr_variable(
STUB_MESSAGE_VAR_NAME ".SizePtrLengthArray" );
else
pExpr = new expr_variable(
STUB_MESSAGE_VAR_NAME ".ActualCount" );
pExpr = new expr_assign( pExpr, new expr_variable( Buffer ) );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
}
return;
}
//
// We check here if the parameter is a top level attributed array or
// pointer, a non-encapsulated union or a pointer to a non-encapsulated
// union. If it isn't, then return.
//
switch ( ParamId )
{
case ID_CG_CONF_ARRAY :
case ID_CG_CONF_VAR_ARRAY :
case ID_CG_VAR_ARRAY :
case ID_CG_CONF_STRING_ARRAY :
case ID_CG_SIZE_PTR :
case ID_CG_SIZE_LENGTH_PTR :
case ID_CG_SIZE_STRING_PTR :
case ID_CG_UNION :
break;
case ID_CG_BC_PTR :
if ( pCCB->GetCodeGenSide() == CGSIDE_SERVER )
return;
{
ISTREAM * pStream = pCCB->GetStream();
expr_node * pExpr;
CG_BYTE_COUNT_POINTER * pByteCount;
pByteCount = (CG_BYTE_COUNT_POINTER *) pChild;
pExpr = new expr_assign(
new expr_variable( STUB_MESSAGE_VAR_NAME ".MaxCount" ),
new expr_variable(
pByteCount->GetByteCountParam()->GetSymName() ) );
pStream->NewLine();
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
}
return;
case ID_CG_INTERFACE_PTR :
{
CG_INTERFACE_POINTER * pIfPointer;
ISTREAM * pStream = pCCB->GetStream();
pIfPointer = (CG_INTERFACE_POINTER *) pChild;
if ( ! pIfPointer->GetIIDExpr() )
return;
pStream->NewLine();
pStream->Write( STUB_MESSAGE_VAR_NAME
".MaxCount = (unsigned long) " );
pIfPointer->GetIIDExpr()->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
}
return;
default :
return;
}
pCCB->GetStream()->NewLine();
switch ( pChild->GetCGID() )
{
case ID_CG_CONF_ARRAY :
pSizeOrSwitchIsExpr =
((CG_CONFORMANT_ARRAY *)pChild)->GetSizeIsExpr();
pFirstIsExpr = NULL;
pLengthIsExpr = NULL;
break;
case ID_CG_CONF_VAR_ARRAY :
pSizeOrSwitchIsExpr =
((CG_CONFORMANT_VARYING_ARRAY *)pChild)->GetSizeIsExpr();
pFirstIsExpr =
((CG_CONFORMANT_VARYING_ARRAY *)pChild)->GetFirstIsExpr();
pLengthIsExpr =
((CG_CONFORMANT_VARYING_ARRAY *)pChild)->GetLengthIsExpr();
break;
case ID_CG_VAR_ARRAY :
pSizeOrSwitchIsExpr = NULL;
pFirstIsExpr =
((CG_VARYING_ARRAY *)pChild)->GetFirstIsExpr();
pLengthIsExpr =
((CG_VARYING_ARRAY *)pChild)->GetLengthIsExpr();
break;
case ID_CG_CONF_STRING_ARRAY :
pSizeOrSwitchIsExpr =
((CG_CONFORMANT_STRING_ARRAY *)pChild)->GetSizeIsExpr();
pFirstIsExpr = NULL;
pLengthIsExpr = NULL;
break;
case ID_CG_SIZE_PTR :
pSizeOrSwitchIsExpr =
((CG_SIZE_POINTER *)pChild)->GetSizeIsExpr();
pFirstIsExpr = NULL;
pLengthIsExpr = NULL;
break;
case ID_CG_SIZE_LENGTH_PTR :
pSizeOrSwitchIsExpr =
((CG_SIZE_LENGTH_POINTER *)pChild)->GetSizeIsExpr();
pFirstIsExpr =
((CG_SIZE_LENGTH_POINTER *)pChild)->GetFirstIsExpr();
pLengthIsExpr =
((CG_SIZE_LENGTH_POINTER *)pChild)->GetLengthIsExpr();
break;
case ID_CG_SIZE_STRING_PTR :
pSizeOrSwitchIsExpr =
((CG_SIZE_STRING_POINTER *)pChild)->GetSizeIsExpr();
pFirstIsExpr = NULL;
pLengthIsExpr = NULL;
break;
case ID_CG_UNION :
case ID_CG_PTR :
pSizeOrSwitchIsExpr = GetSwitchExpr();
pFirstIsExpr = NULL;
pLengthIsExpr = NULL;
break;
}
if ( pSizeOrSwitchIsExpr )
{
pSizeOrSwitchIsExpr = MakeAttrExprWithNullPtrChecks(
pSizeOrSwitchIsExpr );
pExpr = new expr_assign(
new expr_variable( STUB_MESSAGE_VAR_NAME ".MaxCount" ),
pSizeOrSwitchIsExpr );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
}
if ( pFirstIsExpr )
{
//
// For NdrClearOutParams we ignore the first_is() & length_is()
// attributes in case these are [out] and therefore unitialized.
//
if ( fForClearOut )
{
pStream->Write( STUB_MESSAGE_VAR_NAME ".Offset = 0;" );
pStream->NewLine();
}
else
{
pFirstIsExpr = MakeAttrExprWithNullPtrChecks( pFirstIsExpr );
pExpr = new expr_assign(
new expr_variable( STUB_MESSAGE_VAR_NAME ".Offset" ),
pFirstIsExpr );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
}
//
// Create a LengthIsExpr if one does not already exist.
//
if ( ! pLengthIsExpr )
{
expr_node * pSize;
if ( pChild->IsPointer() )
{
// Size/length pointer.
pSize = ((CG_SIZE_LENGTH_POINTER *)pChild)->GetSizeIsExpr();
}
else
{
// Conformant varying or varying array.
pSize = ((CG_ARRAY *)pChild)->GetSizeIsExpr();
}
pLengthIsExpr =
new expr_b_arithmetic( OP_MINUS,
pSize,
pFirstIsExpr );
}
}
if ( pLengthIsExpr )
{
//
// For NdrClearOutParams we ignore the first_is() & length_is()
// attributes in case these are [out] and therefore unitialized.
//
if ( fForClearOut )
{
pStream->Write( STUB_MESSAGE_VAR_NAME ".ActualCount" " = " );
pStream->Write( STUB_MESSAGE_VAR_NAME ".MaxCount;" );
pStream->NewLine();
}
else
{
pLengthIsExpr = MakeAttrExprWithNullPtrChecks( pLengthIsExpr );
pExpr = new expr_assign(
new expr_variable(STUB_MESSAGE_VAR_NAME ".ActualCount"),
pLengthIsExpr );
pExpr->Print( pStream );
pStream->Write( ";" );
pStream->NewLine();
}
}
}
expr_node *
CG_PROC::GenCoreNdrSingleClientCall(
CCB * pCCB,
int WhichRisc )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Creates the real expression for the ndr single client call.
Arguments:
WhichRisc - 2 if alpha, 1 if Mips or PPC , 0 otherwise.
Return Value:
None.
Notes:
On risc machines, the compiler passes the parameters in registers,
therefore the client stub is passed the parameters in registers. The
interpreter needs arguments on the stack. In order to force a spill of the
parameters from the registers to the stack, we need to pass addr all the
parameters to NdrClientCall.
stub_proc( p1, p2, p3 )
{
...
NdrClientCall( STUB_DESC *,
FORMAT_STRING *,
&p1,
&p2,
&p3 );
...
}
On Alpha the varargs is simply weird. The code generated needs to be
stub_proc( p1, p2, p3 )
{
...
NdrClientCall( STUB_DESC *,
FORMAT_STRING *,
vlist.a0 );
...
}
----------------------------------------------------------------------------*/
{
char FormatStringExpr[80];
expr_proc_call * pCallExpr;
expr_node * pExpr;
CG_PARAM * pParam;
PNAME pFormatName;
OPTIM_OPTION OptimOptions;
OptimOptions = GetOptimizationFlags();
//
// Now construct the expression for the Ndr call.
//
if ( OptimOptions & OPTIMIZE_INTERPRETER_V2 )
pCallExpr = new expr_proc_call( C_NDR_CALL_RTN_NAME_V2 );
else
pCallExpr = new expr_proc_call( C_NDR_CALL_RTN_NAME );
//
// Stub Descriptor
//
pExpr = new expr_variable( pCCB->GetInterfaceCG()->GetStubDescName() );
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
pExpr = MakeExpressionOfCastToTypeName(PSTUB_DESC_STRUCT_TYPE_NAME, pExpr);
pCallExpr->SetParam( new expr_param( pExpr ) );
sprintf( FormatStringExpr,
"(PFORMAT_STRING) &%s[%d]",
PROC_FORMAT_STRING_STRING_FIELD,
GetFormatStringOffset() );
pFormatName = new char [strlen( FormatStringExpr) + 1];
strcpy( pFormatName, FormatStringExpr );
pCallExpr->SetParam( new expr_param(
new expr_variable( pFormatName ) ) );
if( 2 == WhichRisc )
{
pExpr = new expr_variable( VLIST_A0, 0 );
pCallExpr->SetParam( new expr_param( pExpr ));
}
else
{
// If this is an object interface the first param is an implicit
// this param.
if( IsObject() )
{
pExpr = new expr_u_address(new expr_variable("This"));
pExpr = MakeCastExprPtrToUChar( pExpr );
pCallExpr->SetParam( new expr_param( pExpr ) );
}
/************************************************************************
If this is a risc platform, then
if there are actual parameters,
take the address of each of them
else
if it is not an object interface,
push a 0
else
do nothing. since we have already pushed &this.
else // if this is not a risc platform
if there are actual parameters
take address of first.
else
if it is non object procedure,
push a 0,
else
do nothing since for an object proc we have already pushed &this.
************************************************************************/
if( 1 == WhichRisc )
{
ITERATOR I;
if( GetMembers( I ) )
{
while( ITERATOR_GETNEXT( I, pParam ) )
{
pExpr = new expr_u_address (
new expr_variable(
pParam->GetResource()->GetResourceName()));
pExpr = MakeCastExprPtrToUChar( pExpr );
pCallExpr->SetParam( new expr_param( pExpr ) );
}
}
else if( !IsObject() )
{
pExpr = new expr_constant( 0L );
pExpr = MakeCastExprPtrToUChar( pExpr );
pCallExpr->SetParam( new expr_param( pExpr ) );
}
}
else if( !IsObject() )
{
if( pParam = (CG_PARAM *) GetChild() )
{
pExpr = new expr_u_address (
new expr_variable(
pParam->GetResource()->GetResourceName()));
if ( pCommand->IsAnyMac() )
{
CG_NDR * pNdr;
pNdr = (CG_NDR *) pParam->GetChild();
if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
pNdr = (CG_NDR *) pNdr->GetChild();
if ( pNdr->GetCGID() == ID_CG_BT )
{
FORMAT_CHARACTER Format;
Format = ((CG_BASETYPE *)pNdr)->GetFormatChar( pCCB );
if ( (FC_BYTE <= Format) && (Format <= FC_USMALL) )
{
pExpr = new expr_b_arithmetic(
OP_MINUS,
pExpr,
new expr_constant(3UL) );
}
if ( (FC_WCHAR <= Format) && (Format <= FC_USHORT) )
{
pExpr = new expr_b_arithmetic(
OP_MINUS,
pExpr,
new expr_constant(1UL) );
}
}
}
pExpr = MakeCastExprPtrToUChar( pExpr );
pCallExpr->SetParam( new expr_param( pExpr ) );
}
else
{
pExpr = new expr_constant( 0L );
pExpr = MakeCastExprPtrToUChar( pExpr );
pCallExpr->SetParam( new expr_param( pExpr ) );
}
}
}
// Assign the return value if one exists.
expr_node * pFinalExpr;
if ( GetReturnType() )
{
pFinalExpr = new expr_assign(
new expr_variable( RETURN_VALUE_VAR_NAME ),
pCallExpr );
}
else
pFinalExpr = pCallExpr;
return pFinalExpr;
}
void CG_PROC::SetupFormatStrings( CCB * pCCB )
{
if (!cRefSaved++)
{
if(!pSavedProcFormatString)
{
pSavedProcFormatString = pCCB->GetProcFormatString();
pSavedFormatString = pCCB->GetFormatString();
}
if (IsHookOleLocal())
{
CG_FILE * pFile = pCCB->GetFileCG();
pCCB->SetFormatString( pFile->GetLocalFormatString());
pCCB->SetProcFormatString(pFile->GetLocalProcFormatString());
}
}
}
void CG_PROC::UnsetupFormatStrings(CCB * pCCB )
{
if (cRefSaved)
cRefSaved--;
if (!cRefSaved)
{
pCCB->SetProcFormatString(pSavedProcFormatString);
pCCB->SetFormatString(pSavedFormatString);
}
}
// --------------------------------------------------
// Routine used for generation of NT 3.5 and NT 3.51
// procedure format strings.
// --------------------------------------------------
void
CG_PROC::GenNdrFormatV1( CCB * pCCB )
/*++
Routine Description :
Generates the procedure format strings usable on NT 3.5 and
NT 3.51 systems.
Arguments :
pCCB - pointer to the code control block
--*/
{
CG_ITERATOR Iterator;
CG_PARAM * pParam;
FORMAT_STRING * pProcFormatString;
CG_NDR * pOldCGNodeContext;
short ParamNum;
SetupFormatStrings(pCCB);
if ( GetFormatStringOffset() != -1 )
{
UnsetupFormatStrings(pCCB);
return;
}
pCCB->SetInObjectInterface( IsObject() );
pOldCGNodeContext = pCCB->SetCGNodeContext( this );
//
// If this procedure uses an explicit handle then set the
// NdrBindDescriptionOffset to 0 so that it will not try to output it's
// description when given the GenNdrParamOffLine method in the loop below.
// It's description must be part of the procedure description.
//
if ( GetHandleUsage() == HU_EXPLICIT )
{
GetHandleClassPtr()->SetNdrBindDescriptionOffset( 0 );
}
GetMembers( Iterator );
ParamNum = 0;
//
// Generate the offline portion of the format string for all of the params.
//
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
CG_NDR * pChild;
CG_NDR * pOldPlaceholder;
pParam->SetParamNumber( ParamNum++ );
pChild = (CG_NDR *) pParam->GetChild();
pCCB->SetCurrentParam( (CG_PARAM *) pParam );
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
pChild->GenNdrParamOffline( pCCB );
pCCB->SetCurrentParam( 0 );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
}
//
// Generate the format string for the return type if needed.
//
if ( GetReturnType() )
{
CG_NDR * pChild;
CG_NDR * pOldPlaceholder;
GetReturnType()->SetParamNumber( ParamNum );
pChild = (CG_NDR *) GetReturnType()->GetChild();
pCCB->SetCurrentParam( GetReturnType() );
pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetReturnType() );
pChild->GenNdrParamOffline( pCCB );
pCCB->SetCurrentParam( 0 );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
}
pProcFormatString = pCCB->GetProcFormatString();
SetFormatStringOffset( pProcFormatString->GetCurrentOffset() );
//
// Generate procedure description stuff for the interpreter if needed.
//
if ( (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER)
|| HasAPicklingAttribute() )
GenNdrFormatProcInfo( pCCB );
ITERATOR_INIT( Iterator );
SetFormatStringParamStart( pProcFormatString->GetCurrentOffset() );
//
// Now generate the param info at the end of the format string.
//
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
CG_NDR * pChild;
CG_NDR * pOldPlaceholder;
pChild = (CG_NDR *) pParam->GetChild();
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
pChild = (CG_NDR *) pChild->GetChild();
//
// Ouput the param directional attribute.
//
if ( ! pParam->IsParamOut() )
{
if ( pParam->GetDontCallFreeInst() )
pProcFormatString->PushFormatChar( FC_IN_PARAM_NO_FREE_INST );
else
if ( pChild->IsSimpleType() ||
pChild->GetCGID() == ID_CG_PRIMITIVE_HDL )
pProcFormatString->PushFormatChar( FC_IN_PARAM_BASETYPE );
else
pProcFormatString->PushFormatChar( FC_IN_PARAM );
}
else
{
if ( ! pParam->IsParamIn() )
pProcFormatString->PushFormatChar( FC_OUT_PARAM );
if ( pParam->IsParamIn() && pParam->IsParamOut() )
pProcFormatString->PushFormatChar( FC_IN_OUT_PARAM );
}
pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
pChild->GenNdrParamDescriptionOld( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
}
if ( GetReturnType() )
{
CG_NDR * pChild;
CG_NDR * pOldPlaceholder;
pChild = (CG_NDR *) GetReturnType()->GetChild();
if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
pChild = (CG_NDR *) pChild->GetChild();
if ( pChild->IsSimpleType() )
pProcFormatString->PushFormatChar( FC_RETURN_PARAM_BASETYPE );
else
pProcFormatString->PushFormatChar( FC_RETURN_PARAM );
pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetReturnType() );
pChild->GenNdrParamDescriptionOld( pCCB );
pCCB->SetLastPlaceholderClass( pOldPlaceholder );
}
else
{
pProcFormatString->PushFormatChar( FC_END );
pProcFormatString->PushFormatChar( FC_PAD );
}
pCCB->SetCGNodeContext( pOldCGNodeContext );
pCCB->SetInObjectInterface( FALSE );
SetFormatStringEndOffset( pProcFormatString->GetCurrentOffset() );
// save delta, in case the routine is optimized
short usParamStartDelta = (short) ( GetFormatStringParamStart() -
GetFormatStringOffset() );
SetFormatStringOffset( pProcFormatString->OptimizeFragment( this ) );
// Set param start!!!
SetFormatStringParamStart( GetFormatStringOffset() + usParamStartDelta );
UnsetupFormatStrings(pCCB);
}