mirror of https://github.com/tongzx/nt5src
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
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);
|
|
}
|