/*--------------------------------------------------------------------------- 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 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 ( 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 ( 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 : // // *(( *)_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( 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 : // // *(()_StubMsg.Buffer)++ = *; // 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 : // // = *(( *)_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); }