Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

3388 lines
98 KiB

/*---------------------------------------------------------------------------
Copyright (c) 1993-2000 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"
#include <malloc.h>
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;
MIDL_ASSERT( !pCommand->IsNDR64Run() );
// 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) )
{
// Generate -Os or -Oi format string.
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 )
{
CG_HANDLE * pHandle = GetHandleClassPtr();
pHandle->SetNdrBindDescriptionOffset( 0 );
if ( pHandle->GetCGID() == ID_CG_CONTEXT_HDL )
{
// The context handle directs the call.
((CG_CONTEXT_HANDLE *)pHandle)->SetCannotBeNull();
}
}
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();
// Ignore the following type of arguments that don't go on wire:
// - async handles
// - primitive handles
//
if ( pChild->GetCGID() == ID_CG_PRIMITIVE_HDL || ( (CG_PARAM*) pParam)->IsAsyncHandleParam() )
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 );
}
InterpreterOptFlags.ServerMustSize = (unsigned char) fServerMustSize;
InterpreterOptFlags.ClientMustSize = (unsigned char) fClientMustSize;
InterpreterOptFlags.HasReturn = (unsigned char) (GetReturnType() != 0 ? 1 : 0);
InterpreterOptFlags.HasPipes = (unsigned char) HasPipes();
InterpreterOptFlags.Unused = (unsigned char) 0;
InterpreterOptFlags.HasAsyncUuid = (unsigned char) HasAsyncUUID();
InterpreterOptFlags.HasAsyncHandle = (unsigned char) HasAsyncHandle();
InterpreterOptFlags.HasExtensions = (unsigned char)
( HasDeny()
|| HasNotify()
|| HasNotifyFlag()
|| HasComplexReturnType() );
short floatmask = 0;
if ( pCommand->Is64BitEnv() )
{
floatmask = GetFloatArgMask( pCCB );
InterpreterOptFlags.HasExtensions = (unsigned char)
InterpreterOptFlags.HasExtensions || (0 != floatmask);
}
// New procedure flags.
pProcFormatString->PushOi2ProcFlagsByte( *((char *)&InterpreterOptFlags) );
// Number of parameters.
pProcFormatString->PushByte( ParamNum );
if ( InterpreterOptFlags.HasExtensions )
{
// Extensions layout:
// size<1>
// flags<1>
// client correlation cache size hint<2>
// server correlation cache size hint<2>
// notify routine index<2>
//
INTERPRETER_OPT_FLAGS2 InterpreterOptFlags2;
InterpreterOptFlags2.Unused = 0;
InterpreterOptFlags2.HasNewCorrDesc = ( unsigned char )HasDeny();
if ( InterpreterOptFlags2.HasNewCorrDesc )
{
InterpreterOptFlags2.ClientCorrCheck = ( unsigned char )HasClientCorr();
InterpreterOptFlags2.ServerCorrCheck = ( unsigned char )HasServerCorr();
}
else
{
InterpreterOptFlags2.ClientCorrCheck = 0;
InterpreterOptFlags2.ServerCorrCheck = 0;
}
InterpreterOptFlags2.HasNotify = ( unsigned char )HasNotify();
InterpreterOptFlags2.HasNotify2 = ( unsigned char )HasNotifyFlag();
InterpreterOptFlags2.HasComplexReturn = ( unsigned char )HasComplexReturnType();
if ( pCommand->Is64BitEnv() )
{
pProcFormatString->PushByte( sizeof(NDR_PROC_HEADER_EXTS64) );
}
else
{
pProcFormatString->PushByte( sizeof(NDR_PROC_HEADER_EXTS) );
}
pProcFormatString->PushExtProcFlagsByte( *((char *)&InterpreterOptFlags2) );
node_proc* pProcThis = (node_proc*) GetType();
pProcFormatString->PushShort( short( pProcThis->GetClientCorrelationCount() ) ); // client
pProcFormatString->PushShort( short( pProcThis->GetServerCorrelationCount() ) ); //server
#ifdef PRINT_METRICS
printf (
"Client hint is %16d, Server hint is %16d, for %s\n",
pProcThis->GetClientCorrelationCount(),
pProcThis->GetServerCorrelationCount(),
pProcThis->GetSymName()
);
#endif
if( HasNotify() || HasNotifyFlag() )
GetNotifyTableOffset( pCCB );
pProcFormatString->PushShort( (short)uNotifyTableOffset ); // notify index
if ( pCommand->Is64BitEnv() )
{
pProcFormatString->PushShort( floatmask );
}
}
SetFormatStringParamStart( pProcFormatString->GetCurrentOffset() );
pCCB->SetInterpreterOutSize( 0 );
ITERATOR_INIT( Iterator );
//
// Now generate the param info at the end of the format string.
//
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
CG_NDR * pChild;
CG_NDR * pOldPlaceholder;
if (pParam->IsAsyncHandleParam())
continue;
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() );
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;
long FormatOffset;
short Bytes;
Bytes = short(32 + strlen( GetSymName() ) );
pComment = new char[Bytes];
sprintf( pComment, "\n\t/* Procedure %s */\n\n", GetSymName() );
pProcFormatString->AddComment( GetFormatStringOffset(), pComment );
GetMembers( Iterator );
FormatOffset = GetFormatStringParamStart();
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
if ( pParam->GetCGID() == ID_CG_PRIMITIVE_HDL || pParam->IsAsyncHandleParam() )
continue;
Bytes = short( 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 <> ]
[ notify table offset<2> ]
--*/
{
FORMAT_STRING * pProcFormatString;
SetupFormatStrings(pCCB);
pProcFormatString = pCCB->GetProcFormatString();
if ( IsObject() )
{
pProcFormatString->PushFormatChar( FC_AUTO_HANDLE );
}
else
{
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 );
}
}
unsigned char OiFlags = 0;
// Indicate if there is a need to init the full ptr or rpcss packages.
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;
}
OiFlags |= Oi_HAS_RPCFLAGS;
if ( GetCGID() == ID_CG_ENCODE_PROC )
{
if ( HasEncode() )
OiFlags |= ENCODE_IS_USED;
if ( HasDecode() )
OiFlags |= DECODE_IS_USED;
// The Oi_USE_NEW_INIT_ROUTINES and PICKLING_HAS_COMM_OR_FAULT flags
// are overloaded. In -Oicf mode, the new routines are always used
// and the bit specifics comm/fault options (which overriden also).
// In pre-Oicf comm/fault is not supported.
if ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 )
{
if ( HasStatuses() )
OiFlags |= PICKLING_HAS_COMM_OR_FAULT;
}
else
{
OiFlags |= Oi_USE_NEW_INIT_ROUTINES;
}
}
else
{
// Always do this.
OiFlags |= Oi_USE_NEW_INIT_ROUTINES;
if ( HasStatuses() )
OiFlags |= Oi_HAS_COMM_OR_FAULT;
}
pProcFormatString->PushOldProcFlagsByte( OiFlags );
pProcFormatString->PushLong( (long) TranslateOpBitsIntoUnsignedInt() );
// Proc num.
pProcFormatString->PushShort( (short) GetProcNum() );
long Size = GetTotalStackSize( pCCB );
//
// Use a push ushort offset or size method which outputs a #ifdef for
// the various platforms, for which stack offsets are often different.
//
pProcFormatString->PushUShortStackOffsetOrSize( Size );
//
// Output explicit handle description.
//
if ( GetHandleUsage() == HU_EXPLICIT && !IsObject() )
{
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()->PushShortOffset(
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;
bool fIsErrorStatus = false;
pStream = pCCB->GetStream();
// Generate the format string.
if ( pCommand->IsNDRRun() )
{
GenNdrFormat( pCCB );
}
else
{
pCCB->GetNdr64Format()->Generate( this );
}
if ( GetReturnType() || HasComplexReturnType() )
{
if ( HasAsyncHandle() )
{
if ( !HasComplexReturnType()
&& GetReturnType()->GetChild()->GetCGID() != ID_CG_CONTEXT_HDL )
{
fIsErrorStatus = GetReturnType()->GetChild()->GetCGID() == ID_CG_ERROR_STATUS_T;
}
if ( fIsErrorStatus || GetCGID() == ID_CG_OBJECT_PROC )
{
pStream->Write( "CLIENT_CALL_RETURN " RETURN_VALUE_VAR_NAME );
pStream->Write( " = {0};" );
pStream->NewLine( 2 );
}
}
else
{
if ( HasComplexReturnType() )
{
( (node_proc *) GetType() )
->GetReturnType()->PrintType(PRT_DECL, pStream);
}
else
pStream->Write( "CLIENT_CALL_RETURN " );
pStream->Write( RETURN_VALUE_VAR_NAME );
pStream->Write( ';' );
pStream->NewLine( 2 );
}
}
GetMembers(Iterator);
pLastParam = 0;
while ( ITERATOR_GETNEXT( Iterator, pLastParam ) )
;
// If we have a complex return type the "last parameter" is actually the
// return value so we need the one before that.
if ( pLastParam && HasComplexReturnType() )
{
CG_PARAM *pPrevLastParam = NULL;
ITERATOR_INIT( Iterator );
while ( ITERATOR_GETNEXT( Iterator, pPrevLastParam ) )
if ( pPrevLastParam->GetSibling() == pLastParam )
break;
pLastParam = pPrevLastParam;
}
// Now emit code for x86 or ia64.
if ( pCommand->Is64BitEnv() )
{
// Emit code for IA64 platform
pFinalExpr = GenCoreNdrSingleClientCall( pCCB, PROC_PLATFORM_IA64) ;
}
else
{
// x86
pFinalExpr = GenCoreNdrSingleClientCall( pCCB, PROC_PLATFORM_X86 );
}
pFinalExpr->PrintCall( pStream, 0, 0 );
pStream->NewLine();
if ( GetReturnType() || HasComplexReturnType() )
{
if ( HasAsyncHandle() )
{
if ( !fIsErrorStatus && GetCGID() != ID_CG_OBJECT_PROC )
{
return;
}
}
pStream->Write("return ");
//
// Complex return types
//
if ( HasComplexReturnType() )
{
pStream->Write( RETURN_VALUE_VAR_NAME ";" );
pStream->NewLine();
return;
}
CG_NDR* pNdr = (CG_NDR *) GetReturnType()->GetChild();
node_skl* pType = GetReturnType()->GetType();
//
// Base type return value.
//
if ( pNdr->IsSimpleType() )
{
switch ( ((CG_BASETYPE *)pNdr)->GetFormatChar() )
{
case FC_FLOAT :
pType->PrintType( PRT_CAST_TO_TYPE, pStream );
pStream->Write( RETURN_VALUE_VAR_NAME ".Float;" );
break;
case FC_DOUBLE :
pType->PrintType( PRT_CAST_TO_TYPE, pStream );
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 ( pCommand->IsNDRRun() )
{
if ( GetFormatStringOffset() == -1 )
GenNdrFormat( pCCB );
}
else
{
pCCB->GetNdr64Format()->Generate( this );
}
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 f64 = pCommand->Is64BitEnv();
if ( f64)
GenNdrInterpreterParamStruct64( pCCB);
else
GenNdrInterpreterParamStruct32( pCCB );
}
void
CG_PROC::GenNdrInterpreterParamStruct64( CCB * pCCB )
{
CG_ITERATOR Iterator;
ISTREAM * pStream;
CG_PARAM * pParam;
CG_PARAM * pParamPrev;
CG_RETURN * pReturn;
CG_NDR * pNdr;
long PadNumber;
char Buffer[80];
long PrevEndOffset;
pStream = pCCB->GetStream();
// Register size is 8 for 64b platform.
pStream->Write( "#pragma pack(8)" );
pStream->NewLine();
pStream->Write( PARAM_STRUCT_TYPE_NAME );
pStream->IndentInc();
pStream->NewLine();
pStream->Write( '{' );
pStream->NewLine();
PadNumber = 0;
GetMembers( Iterator );
if ( IsObject() )
{
pCCB->GetInterfaceCG()->GetThisDeclarator()->PrintType(
PRT_PARAM_OR_ID_DECLARATION,
pStream,
(node_skl *)0 );
PrevEndOffset = 8;
}
else
PrevEndOffset = 0;
pParamPrev = 0;
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
pNdr = (CG_NDR *) pParam->GetChild();
if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
pNdr = (CG_NDR *) pNdr->GetChild();
// IA64 does not align every big struct to 16b boundary.
// Only __int128 etc. would be aligned to 16 (and objects embedding it).
// OPTIMIZE: The code below is correct, as GetStackOffset with PrevEndOffset
// is a check for alignment of 16, but pParam->GetMemAlign() would be better.
if ( (pParam->GetStackSize() > 8) && PrevEndOffset > 0 )
{
long CurrentIA64Offset;
if ( pParamPrev )
{
PrevEndOffset = pParamPrev->GetStackOffset( pCCB, I386_STACK_SIZING )
+ pParamPrev->GetStackSize();
if ( PrevEndOffset & 7 )
PrevEndOffset += 8 - (PrevEndOffset & 7);
}
// The additional pad for 16b aligned objects can only be
// a full register as the prev param is already padded.
CurrentIA64Offset = pParam->GetStackOffset( pCCB, I386_STACK_SIZING );
if ( CurrentIA64Offset - PrevEndOffset )
{
sprintf( Buffer, "char Pad%d[8];", PadNumber++ );
pStream->Write( Buffer );
pStream->NewLine();
}
}
//
// For reasons lost to the ages if we have a pointer to a
// context handle then it's type gets munged from TYPE* to
// NDR_SCONTEXT. This is fine except that it causes type
// mismatch errors in the server stub. Special case it here.
//
bool print = true;
if ( pNdr->IsPointer() )
{
CG_CONTEXT_HANDLE *pHandle = dynamic_cast<CG_CONTEXT_HANDLE *>
( pNdr->GetChild() );
if ( pHandle )
{
pStream->WriteFormat(
"%s *%s;",
pHandle->GetHandleType()->GetSymName(),
pParam->GetSymName());
pStream->NewLine();
print = false;
}
}
// Print the field declaration.
if (print)
{
pParam->GetResource()->GetType()->PrintType(
PRT_PARAM_OR_ID_DECLARATION,
pStream,
(node_skl *)0 );
}
//
// Generate some padding if needed.
//
if ( pParam->GetStackSize() & 7 )
{
long Pad = 8 - (pParam->GetStackSize() & 7);
sprintf( Buffer, "char Pad%d[%d];", PadNumber++, Pad );
pStream->Write( Buffer );
pStream->NewLine();
}
pParamPrev = pParam;
} // while params
// Add the return type if one is present.
if ( ( pReturn = GetReturnType() ) != 0 )
{
pReturn->GetResource()->GetType()->PrintType(
PRT_PARAM_OR_ID_DECLARATION,
pStream,
(node_skl *)0 );
// Possibly we could add a padding after the return type member
// but it would not be used anyway.
}
pStream->Write( "};" );
pStream->IndentDec();
pStream->NewLine();
pStream->Write( "#pragma pack()" );
pStream->NewLine();
}
void
CG_PROC::GenNdrInterpreterParamStruct32( CCB * pCCB )
{
CG_ITERATOR Iterator;
ISTREAM * pStream;
CG_PARAM * pParam;
CG_PARAM * pParamPrev;
CG_RETURN * pReturn;
CG_NDR * pNdr;
long Pad;
long PadNumber;
char Buffer[80];
pStream = pCCB->GetStream();
pStream->Write( "#pragma pack(4)" );
pStream->NewLine();
pStream->Write( PARAM_STRUCT_TYPE_NAME );
pStream->IndentInc();
pStream->NewLine();
pStream->Write( '{' );
pStream->NewLine();
PadNumber = 0;
GetMembers( Iterator );
if ( IsObject() )
{
pCCB->GetInterfaceCG()->GetThisDeclarator()->PrintType(
PRT_PARAM_OR_ID_DECLARATION,
pStream,
(node_skl *)0 );
}
pParamPrev = 0;
while( ITERATOR_GETNEXT( Iterator, pParam ) )
{
pNdr = (CG_NDR *) pParam->GetChild();
if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
pNdr = (CG_NDR *) pNdr->GetChild();
//
// For reasons lost to the ages if we have a pointer to a
// context handle then it's type gets munged from TYPE* to
// NDR_SCONTEXT. This is fine except that it causes type
// mismatch errors in the server stub. Special case it here.
//
bool print = true;
if ( pNdr->IsPointer() )
{
CG_CONTEXT_HANDLE *pHandle = dynamic_cast<CG_CONTEXT_HANDLE *>
( pNdr->GetChild() );
if ( pHandle )
{
pStream->WriteFormat(
"%s *%s;",
pHandle->GetHandleType()->GetSymName(),
pParam->GetSymName());
pStream->NewLine();
print = false;
}
}
// Print the field declaration.
if (print)
{
pParam->GetResource()->GetType()->PrintType(
PRT_PARAM_OR_ID_DECLARATION,
pStream,
(node_skl *)0 );
}
//
// Generate some padding if needed.
//
if ( pParam->GetStackSize() & 3 )
{
Pad = 4 - (pParam->GetStackSize() & 3);
sprintf( Buffer, "char Pad%d[%d];", PadNumber++, Pad );
pStream->Write( Buffer );
pStream->NewLine();
}
pParamPrev = pParam;
} // while params
// Add the return type if one is present.
if ( ( pReturn = GetReturnType() ) != 0 )
{
pReturn->GetResource()->GetType()->PrintType(
PRT_PARAM_OR_ID_DECLARATION,
pStream,
(node_skl *)0 );
}
pStream->Write( "};" );
pStream->IndentDec();
pStream->NewLine();
pStream->Write( "#pragma pack()" );
pStream->NewLine();
}
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("))");
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
//
// async methods don't have return values
if ( GetReturnType() && !HasAsyncHandle() )
{
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
--*/
{
MIDL_ASSERT( !pCommand->IsNDR64Run() );
if ( GetFormatStringOffset() != -1 )
return;
// The invisible fault/comm status param added by means of acf definition
// doesn't go on wire, so it has no format string representation.
if ( IsExtraStatusParam() )
return;
// [async_handle] This parameter is the invisible xxx_AsyncHandle and does not go
// on the wire, so it has no format representation.
if ( IsAsyncHandleParam() )
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;
unsigned short WireAlign;
// BUG BUG, this needs to be cleaned up for NDR64
MIDL_ASSERT( !pCommand->IsNDR64Run() );
pStream = pCCB->GetStream();
pChild = (CG_NDR *)GetChild();
ParamId = pChild->GetCGID();
pParamName = GetResource()->GetResourceName();
if ( IsParamPartialIgnore() &&
( pCCB->GetCodeGenSide() == CGSIDE_CLIENT ) )
{
Out_PartialIgnoreClientMarshall( pCCB, pParamName );
return;
}
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->IsInterfacePointer() ) &&
(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();
if ( ! pChild->IsPipeOrPipeReference() )
{
WireAlign = pPtrChild->GetWireAlignment();
}
}
else
{
// We shouldn't do that for pipe and object pipe args
if ( ! pChild->IsPipeOrPipeReference() )
{
WireAlign = pChild->GetWireAlignment();
}
}
// For context handles, generate an optimized code for the client side and
// also an optimize code for common context handles at the server side but
// except that for new context handle flavors the call is slightly different.
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() );
if ( pContextHandle->HasNewContextFlavor() )
{
Out_SContextHandleNewMarshall( pCCB,
pParamName,
pContextHandle->GetRundownRtnName(),
pContextHandle->GetFormatStringOffset() );
}
else
{
Out_SContextHandleMarshall( pCCB,
pParamName,
pContextHandle->GetRundownRtnName() );
}
}
return;
}
if ( pChild->GetCGID() == ID_CG_ENUM || pChild->GetCGID() == ID_CG_INT3264 )
{
expr_proc_call * pCall;
FORMAT_CHARACTER fc;
expr_node * pExpr;
if ( pChild->GetCGID() == ID_CG_ENUM )
fc = ((CG_ENUM *)pChild)->GetFormatChar();
else
fc = ((CG_BASETYPE *)pChild)->GetSignedFormatChar();
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 ) );
// Don't emit names like FC_ENUM16 or FC_INT3264 as constants are not public.
pCall->SetParam( new expr_param(
new expr_constant( (long)fc ) ) );
pStream->NewLine();
pCall->PrintCall( pStream, 0, 0 );
return;
}
if ( pChild->IsSimpleType() )
{
pStream->NewLine();
OutputNdrAlignment( pCCB, WireAlign );
//
// 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_NDR *)pChild->GetChild())->GetCGID() != ID_CG_INT3264) )
{
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();
OutputNdrAlignment( pCCB, WireAlign );
//
// 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();
//
// If the param is an omitted cs_tag param, the marshalling code takes
// care of handling the call to the tag routine to get the actual value.
// Also, since we don't have the parameter on the stack we don't have a
// name to pass to Marshall so just pass "0" (NULL)
//
if ( IsOmittedParam() )
{
PNAME pNewName = (PNAME) alloca( sizeof("0 /* */")
+ strlen(pParamName) );
strcpy( pNewName, "0 /* ");
strcat( pNewName, pParamName );
strcat( pNewName, " */");
pParamName = pNewName;
fTakeAddress = FALSE; // Probably don't need these but be safe
fDereference = FALSE;
}
//
// 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
--*/
{
// BUG BUG, this needs to be cleaned up for NDR64
MIDL_ASSERT( !pCommand->IsNDR64Run() );
ISTREAM * pStream;
CG_NDR * pChild;
FORMAT_STRING * pFormatString;
PNAME pParamName;
ID_CG ParamId;
long NameIndex;
long FormatOffset;
BOOL fMustAllocFlag = FALSE;
BOOL fTakeAddress = TRUE;
unsigned short WireAlign;
pStream = pCCB->GetStream();
pChild = (CG_NDR *)GetChild();
ParamId = pChild->GetCGID();
pParamName = GetResource()->GetResourceName();
if ( IsParamPartialIgnore() &&
( pCCB->GetCodeGenSide() == CGSIDE_SERVER ) )
{
Out_PartialIgnoreServerUnmarshall( pCCB, pParamName );
return;
}
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->IsInterfacePointer()) &&
(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();
if ( ! (IsExtraStatusParam() || pChild->IsPipeOrPipeReference()) )
{
WireAlign = pPtrChild->GetWireAlignment();
}
}
else
{
// We should not do that for pipe or object pipe args
// However, we do not support -Os pipes as yet.
if ( ! pChild->IsPipeOrPipeReference() )
{
WireAlign = pChild->GetWireAlignment();
}
}
// For context handles, generate an optimized code for the client side and
// also an optimize code for common context handles at the server side but
// except that for new context handle flavors the call is slightly different.
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
{
CG_CONTEXT_HANDLE * pContextHandle;
pContextHandle = (ParamId == ID_CG_PTR) ?
(CG_CONTEXT_HANDLE *) pChild->GetChild() :
(CG_CONTEXT_HANDLE *) pChild;
if ( pContextHandle->HasNewContextFlavor() ||
pCommand->GetNdrVersionControl().IsNdr50orLaterRequired() )
{
Out_SContextHandleNewUnmarshall( pCCB,
pParamName,
IsOutOnly,
pContextHandle->GetFormatStringOffset() );
}
else
{
Out_SContextHandleUnmarshall( pCCB,
pParamName,
IsOutOnly );
}
}
return;
}
if ( pChild->GetCGID() == ID_CG_ENUM || pChild->GetCGID() == ID_CG_INT3264 )
{
expr_proc_call * pCall;
FORMAT_CHARACTER fc;
expr_node * pExpr;
if ( pChild->GetCGID() == ID_CG_ENUM )
fc = ((CG_ENUM *)pChild)->GetFormatChar();
else
fc = ((CG_BASETYPE *)pChild)->GetSignedFormatChar();
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( (long)fc ) ) );
pStream->NewLine();
pCall->PrintCall( pStream, 0, 0 );
return;
}
if ( pChild->IsSimpleType() )
{
pStream->NewLine();
OutputNdrAlignment( pCCB, WireAlign );
Out_CheckUnMarshallPastBufferEnd( pCCB, pChild->GetWireSize() );
pStream->NewLine();
//
// 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_NDR *)pChild->GetChild())->GetCGID() != ID_CG_INT3264) )
{
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 );
if ( IsExtraStatusParam() )
{
// For the extra (invisible) fault/comm status parameter, that
// does *not* go on the wire, we need to generate an assignment
// when unmarshaling on the client (the arg can only be [out]).
// The value to be assigned is error_status_ok, which maps to 0.
pExpr = new expr_constant( (long)0 );
pExpr = new expr_assign( new expr_u_deref( pVar ),
pExpr );
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
}
else
{
// For other types generate unmarshaling assignment.
OutputNdrAlignment( pCCB, WireAlign );
//
// 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() )
{
if ( !( pCCB->GetCodeGenSide() == CGSIDE_CLIENT && IsParamIn() ) )
{
char * 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;
}
}
//
// If the param is an omitted cs_tag param, the marshalling code takes
// care of handling the call to the tag routine to get the actual value.
// Also, since we don't have the parameter on the stack we don't have a
// name to pass to Unmarshall so just pass "0" (NULL)
//
if ( IsOmittedParam() )
{
PNAME pNewName = (PNAME) alloca( sizeof("0 /* */")
+ strlen(pParamName) );
strcpy( pNewName, "0 /* ");
strcat( pNewName, pParamName );
strcat( pNewName, " */");
pParamName = pNewName;
fTakeAddress = FALSE;
}
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
--*/
{
// BUG BUG, this needs to be cleaned up for NDR64
MIDL_ASSERT( !pCommand->IsNDR64Run() );
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();
pParamName = GetResource()->GetResourceName();
if ( IsParamPartialIgnore() &&
( pCCB->GetCodeGenSide() == CGSIDE_CLIENT ) )
{
Out_PartialIgnoreClientBufferSize( pCCB, pParamName );
return;
}
//
// 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->WriteOnNewLine( STUB_MSG_LENGTH_VAR_NAME " += 20;" );
pStream->NewLine();
return;
}
if ( pChild->IsSimpleType() )
{
ISTREAM * pStream = pCCB->GetStream();
pStream->WriteOnNewLine( STUB_MSG_LENGTH_VAR_NAME " += 16;" );
pStream->NewLine();
return;
}
if ( pChild->IsPointerToBaseType() )
{
ISTREAM * pStream = pCCB->GetStream();
pStream->WriteOnNewLine( STUB_MSG_LENGTH_VAR_NAME " += 24;" );
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 :
if ( ID_CG_CS_TAG == pPointer->GetChild()->GetCGID() )
{
ParamId = ID_CG_CS_TAG;
break;
}
FormatOffset = pPointer->GetPointeeFormatStringOffset();
NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
break;
}
}
if ( ID_CG_CS_TAG == ParamId )
{
ISTREAM * pStream = pCCB->GetStream();
pStream->WriteOnNewLine( STUB_MSG_LENGTH_VAR_NAME " += 4; /* " );
pStream->Write( pParamName );
pStream->Write( " */" );
pStream->NewLine();
return;
}
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
--*/
{
// BUG BUG, this needs to be cleaned up for NDR64
MIDL_ASSERT( !pCommand->IsNDR64Run() );
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() ||
IsParamPartialIgnore() )
{
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());
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());
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());
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, *pSizeExpr;
CG_BYTE_COUNT_POINTER * pByteCount;
pByteCount = (CG_BYTE_COUNT_POINTER *) pChild;
pSizeExpr = MakeExpressionOfCastToTypeName( "unsigned long",
new expr_variable(
pByteCount->GetByteCountParam()->GetSymName() ) );
pExpr = new expr_assign(
new expr_variable( STUB_MESSAGE_VAR_NAME ".MaxCount" ),
pSizeExpr );
pStream->NewLine();
pExpr->Print( pStream );
pStream->Write( ';' );
pStream->NewLine();
}
return;
case ID_CG_IIDIS_INTERFACE_PTR:
{
CG_IIDIS_INTERFACE_POINTER * pIfPointer;
ISTREAM * pStream = pCCB->GetStream();
pIfPointer = (CG_IIDIS_INTERFACE_POINTER *) pChild;
if ( ! pIfPointer->GetIIDExpr() )
return;
pStream->NewLine();
if ( pCommand->Is64BitEnv() )
{
// _StubMsg.MaxCount = (ULONG_PTR) ( riid );
pStream->Write( STUB_MESSAGE_VAR_NAME
".MaxCount = (ULONG_PTR) ( " );
}
else
{
// _StubMsg.MaxCount = (unsigned long) ( riid );
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 );
pSizeOrSwitchIsExpr = MakeExpressionOfCastToTypeName( "unsigned long",
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 );
pFirstIsExpr = MakeExpressionOfCastToTypeName( "unsigned long",
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" " = (unsigned long) " );
pStream->Write( STUB_MESSAGE_VAR_NAME ".MaxCount;" );
pStream->NewLine();
}
else
{
pLengthIsExpr = MakeAttrExprWithNullPtrChecks( pLengthIsExpr );
pLengthIsExpr = MakeExpressionOfCastToTypeName( "unsigned long",
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,
PROC_CALL_PLATFORM Platform )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Creates the real expression for the ndr single client call.
Arguments:
Platform - x86, IA64, alpha, etc.
An explicit enum type is used to indicate platform.
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 ( HasAsyncUUID() )
{
if ( pCommand->NeedsNDR64Run() )
pCallExpr = new expr_proc_call( C_NDR64_CALL_RTN_NAME_DCOM_ASYNC );
else
pCallExpr = new expr_proc_call( C_NDR_CALL_RTN_NAME_DCOM_ASYNC );
}
else if ( HasAsyncHandle() )
{
if ( pCommand->NeedsNDR64Run() )
pCallExpr = new expr_proc_call( C_NDR64_CALL_RTN_NAME_ASYNC );
else
pCallExpr = new expr_proc_call( C_NDR_CALL_RTN_NAME_ASYNC );
}
else
{
if ( pCommand->NeedsNDR64Run() )
pCallExpr = new expr_proc_call ( C_NDR64_CALL_RTN_NAME );
else
{
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 );
}
}
if ( ! pCommand->NeedsNDR64Run() )
{
//
// 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 ) ) );
}
else
{
pExpr = new expr_variable ( pCCB->GetInterfaceCG()->GetProxyInfoName() );
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
pExpr = MakeExpressionOfCastToTypeName(PMIDL_PROXY_INFO_TYPE_NAME, pExpr);
pCallExpr->SetParam( new expr_param( pExpr ) );
pExpr = new expr_constant( (long) ProcNum );
pCallExpr->SetParam ( new expr_param ( pExpr ) );
if ( HasComplexReturnType() && !HasAsyncHandle() )
{
pExpr = new expr_variable( RETURN_VALUE_VAR_NAME );
pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
}
else
{
pExpr = new expr_constant( (long) 0 );
}
pCallExpr->SetParam ( new expr_param ( pExpr ) );
}
// If this is an object interface the first param is an implicit
// this param.
if( IsObject() )
{
pExpr = new expr_variable("This");
if( PROC_PLATFORM_IA64 != Platform )
{
pExpr = new expr_u_address( pExpr );
}
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 ( PROC_PLATFORM_IA64 == Platform )
{
ITERATOR I;
if ( GetMembers(I))
{
while (ITERATOR_GETNEXT(I, pParam))
{
// Don't include cs_tag params when there is a tag routine
if ( GetCSTagRoutine() && pParam->IsSomeCSTag() )
continue;
// Don't push the fake parameter that was added for complex
// return types
if ( HasComplexReturnType() && NULL == pParam->GetSibling() )
continue;
pExpr = new expr_variable(
pParam->GetResource()->GetResourceName());
pCallExpr->SetParam(new expr_param(pExpr));
}
}
else if ( !IsObject() )
{
pExpr = new expr_constant( 0L );
pCallExpr->SetParam( new expr_param( pExpr ) );
}
}
else if( !IsObject() )
{
pParam = (CG_PARAM *) GetChild();
// Make sure that this is not a cs_tag parameter that is being
// omitted because there is a tag routine,
if ( GetCSTagRoutine() )
{
while ( pParam && pParam->IsSomeCSTag() )
pParam = (CG_PARAM *) pParam->GetSibling();
}
if( pParam )
{
pExpr = new expr_u_address (
new expr_variable(
pParam->GetResource()->GetResourceName()));
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() && !HasComplexReturnType() )
{
if ( HasAsyncHandle() )
{
bool fIsErrorStatus = false;
if ( GetReturnType()->GetChild()->GetCGID() != ID_CG_CONTEXT_HDL )
{
fIsErrorStatus = GetReturnType()->GetChild()->GetType()->GetBasicType()->NodeKind() == NODE_E_STATUS_T;
}
if ( fIsErrorStatus || GetCGID() == ID_CG_OBJECT_PROC )
{
pFinalExpr = new expr_assign(
new expr_variable( RETURN_VALUE_VAR_NAME ),
pCallExpr );
}
else
{
pFinalExpr = pCallExpr;
}
}
else
{
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();
}
}
}
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 )
{
CG_HANDLE * pHandle = GetHandleClassPtr();
pHandle->SetNdrBindDescriptionOffset( 0 );
if ( pHandle->GetCGID() == ID_CG_CONTEXT_HDL )
{
// The context handle directs the call.
((CG_CONTEXT_HANDLE *)pHandle)->SetCannotBeNull();
}
}
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;
if (pParam->IsAsyncHandleParam())
continue;
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;
if ( pParam->IsExtraStatusParam() || pParam->IsAsyncHandleParam() )
continue;
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->IsParamPartialIgnore() )
{
pProcFormatString->PushFormatChar( FC_PARTIAL_IGNORE_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() );
pProcFormatString->OptimizeFragment( this );
// Set param start!!!
SetFormatStringParamStart( GetFormatStringOffset() + usParamStartDelta );
UnsetupFormatStrings(pCCB);
}