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

2957 lines
80 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. procgen.cxx
  5. Abstract:
  6. code generation for procedures.
  7. Notes:
  8. History:
  9. Aug-15-1993 VibhasC Created.
  10. ----------------------------------------------------------------------------*/
  11. /****************************************************************************
  12. * include files
  13. ***************************************************************************/
  14. #include "becls.hxx"
  15. #pragma hdrstop
  16. /****************************************************************************
  17. * externs
  18. ***************************************************************************/
  19. extern CMD_ARG * pCommand;
  20. void GenCorrInit( CCB* );
  21. void GenCorrPassFree( CCB*, char* );
  22. /****************************************************************************/
  23. CG_STATUS
  24. CG_PROC::GenClientStub(
  25. CCB * pCCB )
  26. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  27. Routine Description:
  28. Generate client stub.
  29. Arguments:
  30. pCCB - pointer to code generation control block.
  31. Return Value:
  32. A status of the code generation.
  33. Notes:
  34. Set up local variables, parameters etc.
  35. Perform buffer size and marshalling analysis.
  36. Generate the stub.
  37. The strategy for binding is now different than the old stubs. The actual
  38. binding is performed AFTER the sizing is performed, right at the first
  39. get buffer call. This allows us to combine the message init and the call
  40. to get buffer and binding into one single call to an ndr routine.
  41. Significant code / time savings.
  42. ----------------------------------------------------------------------------*/
  43. {
  44. ANALYSIS_INFO Analysis;
  45. BOOL fHasExceptionHandler = FALSE;
  46. ISTREAM * pStream = pCCB->GetStream();
  47. // [nocode] procs get no client side stub; although they do get a
  48. // server side stub
  49. if ( IsNoCode() )
  50. return CG_OK;
  51. // call_as procs need additional prototypes
  52. if ( pCallAsName )
  53. pCCB->RegisterCallAsRoutine( (node_proc *)GetType() );
  54. //
  55. // Set the CCB code generation side.
  56. //
  57. pCCB->SetCodeGenSide( CGSIDE_CLIENT );
  58. pCCB->SetCodeGenPhase( CGPHASE_MARSHALL );
  59. //
  60. // Change to -Os if needed because of number of param and/or stack size.
  61. //
  62. (void) MustUseSingleEngineCall( pCCB );
  63. pCCB->SetOptimOption( GetOptimizationFlags() );
  64. Analysis.SetCurrentSide( C_SIDE );
  65. Analysis.SetOptimOption( pCCB->GetOptimOption() );
  66. Analysis.SetMode( pCCB->GetMode() );
  67. Analysis.SetRpcSSSwitchSet( (unsigned long)pCCB->IsRpcSSSwitchSet() );
  68. // Declare pre-allocated resources. All params are registered as resources,
  69. // The standard local variables : an rpc message and the stub message are
  70. // also set up local variables.
  71. C_PreAllocateResources( &Analysis );
  72. // Set current phase. Perform buffer size, binding and marshalling analysis.
  73. // The binding analysis usually sets up resources needed for binding.
  74. Analysis.SetCurrentPhase( ANA_PHASE_CLIENT_MARSHALL );
  75. C_BindingAnalysis( &Analysis );
  76. MarshallAnalysis( &Analysis );
  77. // Perform analysis to check if anything needs to be done for ref
  78. // pointer checks. This is especially needed for arrays of ref pointers
  79. // where we need to declare indexes for each array dimension.
  80. RefCheckAnalysis( &Analysis );
  81. // Perform the unmarshalling analysis. This allows the cg nodes to set
  82. // up for unmarshall, figure out local variables needed if any.
  83. Analysis.SetCurrentPhase( ANA_PHASE_CLIENT_UNMARSHALL );
  84. UnMarshallAnalysis( &Analysis );
  85. // Perform the Out Local analysis even on the client side, so the engine
  86. // format string generation will get information if the pointer is
  87. // allocated on stack. One the client side this call will NOT actually
  88. // allocate a resource.
  89. S_OutLocalAnalysis( &Analysis );
  90. // Perform this analysis on the client side so the format string is
  91. // correct for server. It is needed for -Oi RpcSs flag generation.
  92. RpcSsPackageAnalysis( &Analysis );
  93. // Find out which alloc and free routines should be put in the stub
  94. // descriptor.
  95. PNAME AllocRoutineName, FreeRoutineName;
  96. GetCorrectAllocFreeRoutines( pCCB,
  97. FALSE, //client
  98. & AllocRoutineName,
  99. & FreeRoutineName );
  100. // Init the code gen. controller block for a new procedure. The resource
  101. // dictionary data base is handed over to the code generation controller
  102. // for use.
  103. pCCB->InitForNewProc(
  104. GetProcNum(),
  105. (RPC_FLAGS) 0, // rpc flags
  106. AllocRoutineName,
  107. FreeRoutineName,
  108. Analysis.GetResDictDatabase() // resource dict.
  109. );
  110. // If the single engine call is to be used, send message to the ndr
  111. // code generator.
  112. if ( MustUseSingleEngineCall( pCCB ) )
  113. {
  114. if ( IsObject() )
  115. {
  116. //
  117. // Non-call_as object proxies are now stubless.
  118. //
  119. if (((CG_OBJECT_PROC *)this)->IsStublessProxy())
  120. return CG_OK;
  121. ((CG_OBJECT_PROC *)this)->Out_ProxyFunctionPrototype(pCCB,0);
  122. pStream->WriteOnNewLine( "{" );
  123. pStream->NewLine();
  124. }
  125. else
  126. {
  127. // Generate the function header.
  128. Out_ClientProcedureProlog( pCCB, GetType() );
  129. Out_IndentInc( pCCB );
  130. pStream->NewLine();
  131. }
  132. GenNdrSingleClientCall( pCCB );
  133. Out_IndentDec( pCCB );
  134. Out_ProcClosingBrace( pCCB );
  135. // All done.
  136. return CG_OK;
  137. }
  138. pCCB->SetCGNodeContext( this );
  139. MIDL_ASSERT( pCommand->IsNDRRun() || pCommand->IsNDR64Run() );
  140. //
  141. // Always create the format string for the proc.
  142. //
  143. if ( pCommand->IsNDRRun() )
  144. {
  145. GenNdrFormat( pCCB );
  146. }
  147. else
  148. {
  149. pCCB->GetNdr64Format()->Generate( this );
  150. }
  151. // Generate the prolog, the sizing code. Then once the length has been
  152. // calculated, go ahead and perform the binding using our ndr routines.
  153. // The call to the ndr routine returns a buffer pointer ready for
  154. // marshalling.
  155. C_GenProlog( pCCB );
  156. if ( ( fHasExceptionHandler = ( HasStatuses() || IsObject() ) ) == TRUE )
  157. {
  158. Out_RpcTryExcept( pCCB );
  159. }
  160. if ( HasFullPtr() )
  161. Out_FullPointerInit( pCCB );
  162. // Generate the null ref check code.
  163. // For object interfaces we need to generate a call to initialize proxy
  164. // first as we won't be able to walk parameters later for cleanup.
  165. // For raw interfaces we don't ned to move initialization call
  166. // as we don't have the walk problem.
  167. if ( IsObject() )
  168. C_GenBind( pCCB );
  169. if( pCCB->MustCheckRef() )
  170. GenRefChecks( pCCB );
  171. Out_RpcTryFinally( pCCB);
  172. if ( !IsObject() )
  173. C_GenBind( pCCB );
  174. // generate NdrCorrelationInitialize( _StubMsg, _NdrCorrCache, _NdrCorrCacheSize, _NdrCorrFlags );
  175. // normally, /deny causes a switch to /Oicf. This code will be executed when a
  176. // a switch to from /Os to /Oicf is not posible
  177. if ( fHasDeny )
  178. {
  179. GenCorrInit( pCCB );
  180. }
  181. // If the rpc ss package is to be enabled, do so.
  182. // It would need to be enabled explicitely on the client side when
  183. // in non-osf mode, with the attribute on the operation AND
  184. // - the routine is a callback,
  185. // - the routine is not a callback and the interface doesn't
  186. // have the attribute (if it does, we optimized via stub descr.)
  187. if( pCCB->GetMode() && MustInvokeRpcSSAllocate()
  188. &&
  189. ( GetCGID() == ID_CG_CALLBACK_PROC ||
  190. GetCGID() != ID_CG_CALLBACK_PROC &&
  191. ! pCCB->GetInterfaceCG()->IsAllRpcSS())
  192. )
  193. {
  194. Out_RpcSSSetClientToOsf( pCCB );
  195. }
  196. GenSizing( pCCB );
  197. GenMarshall( pCCB );
  198. // Generate the send receive.
  199. C_GenSendReceive( pCCB );
  200. // Before Win2000 Ndr<whatetver>SendReceive didn't set the BufferStart
  201. // and BufferEnd fields. Do it now.
  202. pStream->WriteOnNewLine( "_StubMsg.BufferStart = (unsigned char *) _RpcMessage.Buffer; ");
  203. pStream->WriteOnNewLine( "_StubMsg.BufferEnd = _StubMsg.BufferStart + _RpcMessage.BufferLength;" );
  204. pStream->NewLine();
  205. pCCB->SetCodeGenPhase( CGPHASE_UNMARSHALL );
  206. GenUnMarshall( pCCB );
  207. // generate NdrCorrelationPass( _StubMsg );
  208. // normally, /deny causes a switch to /Oicf. This code will be executed when a
  209. // a switch to from /Os to /Oicf is not posible
  210. if ( fHasDeny )
  211. {
  212. GenCorrPassFree( pCCB, CSTUB_CORR_PASS_RTN_NAME );
  213. }
  214. Out_RpcFinally( pCCB );
  215. if ( fHasDeny )
  216. {
  217. GenCorrPassFree( pCCB, CSTUB_CORR_FREE_RTN_NAME );
  218. }
  219. if ( HasFullPtr() )
  220. Out_FullPointerFree( pCCB );
  221. C_GenFreeBuffer( pCCB );
  222. C_GenUnBind( pCCB );
  223. Out_RpcEndFinally( pCCB );
  224. if( fHasExceptionHandler )
  225. {
  226. if(IsObject())
  227. {
  228. ISTREAM * pStream = pCCB->GetStream();
  229. pStream->NewLine();
  230. pStream->Write('}');
  231. pStream->IndentDec();
  232. pStream->NewLine();
  233. pStream->Write( "RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)" );
  234. pStream->IndentInc();
  235. pStream->NewLine();
  236. pStream->Write( '{' );
  237. }
  238. else
  239. {
  240. Out_RpcExcept( pCCB, "1" );
  241. }
  242. if(ReturnsHRESULT())
  243. {
  244. C_GenClearOutParams( pCCB );
  245. C_GenMapHRESULT( pCCB );
  246. }
  247. else if( HasStatuses() )
  248. {
  249. C_GenMapCommAndFaultStatus( pCCB );
  250. }
  251. else
  252. {
  253. Out_RaiseException( pCCB, "RpcExceptionCode()" );
  254. }
  255. Out_RpcEndExcept( pCCB );
  256. }
  257. // All done, emit the final closed curly and we're done.
  258. GenEpilog( pCCB );
  259. return CG_OK;
  260. }
  261. CG_STATUS
  262. CG_PROC::C_GenMapCommAndFaultStatus(
  263. CCB * pCCB )
  264. {
  265. CG_NDR * pTemp = 0;
  266. CG_NDR * pComm = 0;
  267. CG_NDR * pFault = 0;
  268. CG_NDR * pRT;
  269. int i = 0;
  270. expr_node * pCommExpr;
  271. expr_node * pFaultExpr;
  272. BOOL fReturnHasStatus = FALSE;
  273. ITERATOR I;
  274. GetMembers( I );
  275. if ( (pRT = GetReturnType()) != 0 && (fReturnHasStatus = pRT->HasStatuses() ) == TRUE )
  276. ITERATOR_INSERT( I, pRT );
  277. while( ITERATOR_GETNEXT(I, pTemp ) && (i < 2) )
  278. {
  279. if( pTemp->HasStatuses() )
  280. {
  281. if( pTemp->GetStatuses() == STATUS_COMM )
  282. pComm = pTemp;
  283. if( pTemp->GetStatuses() == STATUS_FAULT )
  284. pFault = pTemp;
  285. if( pTemp->GetStatuses() == STATUS_BOTH )
  286. {
  287. pComm = pFault = pTemp;
  288. break;
  289. }
  290. }
  291. }
  292. if( pComm )
  293. {
  294. if( pComm == pRT )
  295. pCommExpr = MakeAddressExpressionNoMatterWhat( pRT->GetResource() );
  296. else
  297. pCommExpr = pComm->GetResource();
  298. }
  299. else
  300. pCommExpr = new expr_constant(0L);
  301. if( pFault )
  302. {
  303. if( pFault == pRT )
  304. pFaultExpr = MakeAddressExpressionNoMatterWhat(pRT->GetResource());
  305. else
  306. pFaultExpr = pFault->GetResource();
  307. }
  308. else
  309. pFaultExpr = new expr_constant(0L);
  310. Out_CallNdrMapCommAndFaultStatus( pCCB,
  311. MakeAddressExpressionNoMatterWhat(
  312. pCCB->GetStandardResource(
  313. ST_RES_STUB_MESSAGE_VARIABLE)),
  314. GetStatusResource(),
  315. pCommExpr,
  316. pFaultExpr );
  317. return CG_OK;
  318. }
  319. CG_STATUS
  320. CG_PROC::C_GenClearOutParams(
  321. CCB * pCCB )
  322. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  323. Routine Description:
  324. Generate code to clear out params in the case of exceptions.
  325. Arguments:
  326. pCCB - The code gen controller block.
  327. Return Value:
  328. CG_OK
  329. Notes:
  330. Generate a call to a varargs function which will take a stub message, a
  331. format string offset and a list of all output parameters.
  332. ----------------------------------------------------------------------------*/
  333. {
  334. ITERATOR I;
  335. expr_proc_call * pProc;
  336. expr_node * pExpr;
  337. short Count;
  338. CG_PARAM * pParam;
  339. ISTREAM * pStream = pCCB->GetStream();
  340. // The first parameter is the stub message.
  341. Count = GetOutParamList( I );
  342. // For each of the output parameters, call the ndr clear out parameters
  343. // procedure.
  344. ITERATOR_INIT( I );
  345. while( ITERATOR_GETNEXT( I, pParam ) )
  346. {
  347. pParam->GenNdrTopLevelAttributeSupport( pCCB, TRUE );
  348. // Create a call to the procedure.
  349. pProc = new expr_proc_call( C_NDR_CLEAR_OUT_PARAMS_RTN_NAME );
  350. // First param is the address of the stub message.
  351. pExpr = pCCB->GetStandardResource( ST_RES_STUB_MESSAGE_VARIABLE );
  352. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  353. pExpr = MakeExpressionOfCastToTypeName( PSTUB_MESSAGE_TYPE_NAME,
  354. pExpr );
  355. pProc->SetParam( pExpr );
  356. // Second param is the format string offset of the first out parameter.
  357. // Emitted as &__MIDL_FormatString[ ?? ]
  358. pExpr = Make_1_ArrayExpressionFromVarName(
  359. FORMAT_STRING_STRING_FIELD,
  360. ((CG_NDR *)(pParam->GetChild()))->GetFormatStringOffset() );
  361. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  362. pExpr = MakeExpressionOfCastToTypeName(
  363. PFORMAT_STRING_TYPE_NAME,
  364. pExpr);
  365. pProc->SetParam( pExpr );
  366. // The last param is the [out] parameter itself.
  367. pProc->SetParam( MakeCastExprPtrToVoid(pParam->GetResource()) );
  368. pStream->NewLine();
  369. pProc->PrintCall( pStream, 0, 0 );
  370. }
  371. return CG_OK;
  372. }
  373. CG_STATUS
  374. CG_PROC::C_GenMapHRESULT(
  375. CCB * pCCB )
  376. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  377. Routine Description:
  378. Generates code to map exceptions into HRESULT return values.
  379. Arguments:
  380. pCCB - A pointer to the code generation controller block.
  381. Return Value:
  382. CG_OK if all is well
  383. error Otherwise.
  384. Notes:
  385. ----------------------------------------------------------------------------*/
  386. {
  387. ISTREAM *pStream = pCCB->GetStream();
  388. pStream->NewLine();
  389. pStream->Write("_RetVal = NdrProxyErrorHandler(RpcExceptionCode());");
  390. return CG_OK;
  391. }
  392. CG_STATUS
  393. CG_PROC::C_GenProlog(
  394. CCB * pCCB )
  395. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  396. Routine Description:
  397. Generate the procedure prolog for the stub procedure.
  398. Arguments:
  399. pCCB - A pointer to the code generation controller block.
  400. Return Value:
  401. CG_OK if all is well
  402. error Otherwise
  403. Notes:
  404. Increment the stream indentation at the end of the prolog.
  405. Although we register params as param resources, we dont generate the
  406. procedure signature using the PrintType/Decl facility.
  407. ----------------------------------------------------------------------------*/
  408. {
  409. ITERATOR I;
  410. ITERATOR T;
  411. // Output the bare procedure declaration
  412. Out_ClientProcedureProlog( pCCB, GetType() );
  413. // Generate declarations for pre-allocated and analyser-determined locals.
  414. pCCB->GetListOfLocalResources( I );
  415. Out_ClientLocalVariables( pCCB, I );
  416. pCCB->GetListOfTransientResources( T );
  417. Out_ClientLocalVariables( pCCB, T );
  418. // Increment the indentation of the output stream. Reset at epilog time.
  419. Out_IndentInc( pCCB );
  420. //
  421. // This is where we output additional variable declarations to handle
  422. // multidimensional conformant/varying arrays.
  423. //
  424. CG_ITERATOR Iterator;
  425. ISTREAM * pStream;
  426. CG_PARAM * pParam;
  427. CG_NDR * pNdr;
  428. pStream = pCCB->GetStream();
  429. GetMembers( Iterator );
  430. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  431. {
  432. pNdr = (CG_NDR *) pParam->GetChild();
  433. if ( (pNdr->IsArray() && ((CG_ARRAY *)pNdr)->IsMultiConfOrVar()) ||
  434. (pNdr->IsPointer() && ((CG_POINTER *)pNdr)->IsMultiSize()) )
  435. Out_MultiDimVars( pCCB, pParam );
  436. }
  437. Iterator.Init();
  438. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  439. {
  440. pNdr = (CG_NDR *) pParam->GetChild();
  441. if ( (pNdr->IsArray() && ((CG_ARRAY *)pNdr)->IsMultiConfOrVar()) ||
  442. (pNdr->IsPointer() && ((CG_POINTER *)pNdr)->IsMultiSize()) )
  443. Out_MultiDimVarsInit( pCCB, pParam );
  444. }
  445. return CG_OK;
  446. }
  447. CG_STATUS
  448. CG_PROC::C_GenBind(
  449. CCB * pCCB )
  450. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  451. Routine Description:
  452. Generate code to bind to server.
  453. Arguments:
  454. pCCB - A pointer to the code generation controller block.
  455. pAna - A pointer to the analysis information.
  456. Return Value:
  457. CG_OK if all is well
  458. error Otherwise.
  459. Notes:
  460. The binding process is a part of the stub message initialization. The
  461. stub initializing routine takes the actual binding as a parameter. The
  462. binding therefore is done as part of the call to this init routine. This
  463. routine also calls rpc get buffer. This is a change from the erstwhile
  464. stub generation when binding was done first before the size pass. With
  465. this call which takes the length as a parameter which means that now we
  466. will do the sizing pass before the binding pass.
  467. In case of auto handles, the call is a slightly different one.
  468. Also, we need to assign to the local buffer pointer variable only if there
  469. is at least one param that is shipped.
  470. ----------------------------------------------------------------------------*/
  471. {
  472. ITERATOR BindingParamList;
  473. expr_node * pExpr;
  474. expr_node * pExprStubMsg;
  475. BOOL fCallBack = (GetCGID() == ID_CG_CALLBACK_PROC);
  476. //
  477. // collect standard arguments to the init procedure.
  478. //
  479. // The rpc message variable.
  480. pExpr = pCCB->GetStandardResource( ST_RES_RPC_MESSAGE_VARIABLE );
  481. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  482. pExpr = MakeExpressionOfCastToTypeName( PRPC_MESSAGE_TYPE_NAME, pExpr );
  483. ITERATOR_INSERT(
  484. BindingParamList,
  485. pExpr
  486. );
  487. // The stub message variable.
  488. pExpr = pCCB->GetStandardResource( ST_RES_STUB_MESSAGE_VARIABLE);
  489. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  490. pExpr = MakeExpressionOfCastToTypeName( PSTUB_MESSAGE_TYPE_NAME, pExpr );
  491. pExprStubMsg = pExpr;
  492. ITERATOR_INSERT(
  493. BindingParamList,
  494. pExpr
  495. );
  496. // The stub descriptor structure variable. This is not allocated as
  497. // a resource explicitly.
  498. pExpr = new RESOURCE( pCCB->GetInterfaceCG()->GetStubDescName(),
  499. (node_skl *)0 );
  500. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  501. pExpr = MakeExpressionOfCastToTypeName( PSTUB_DESC_STRUCT_TYPE_NAME,
  502. pExpr );
  503. ITERATOR_INSERT( BindingParamList, pExpr );
  504. //
  505. // Proc num.
  506. //
  507. ITERATOR_INSERT( BindingParamList,
  508. new expr_constant( (long) GetProcNum() ) );
  509. // This call doesn't do much nowadays except for generating
  510. // the initialize call and rpc flags assignment and so could
  511. // be eliminated.
  512. Out_HandleInitialize( pCCB,
  513. BindingParamList,
  514. 0,
  515. IsAutoHandle(),
  516. (unsigned short) GetOperationBits()
  517. );
  518. // Generate an explicit binding call depending upon the handle or callback.
  519. if( fCallBack )
  520. {
  521. pExpr = new expr_proc_call( CALLBACK_HANDLE_RTN_NAME );
  522. pExpr = new expr_assign( GetBindingResource(), pExpr );
  523. }
  524. else
  525. {
  526. pExpr = GenBindOrUnBindExpression( pCCB,
  527. TRUE // call to bind.
  528. );
  529. }
  530. // Emit the handle init expression.
  531. if( IsContextHandle() )
  532. {
  533. // Special for context handles:
  534. // The bind expression will contain only the context handle expression,
  535. // and not the assignment to the binding handle variable. This is to
  536. // be done right here. This is because some special code has to be
  537. // generated for context handles for error checking.
  538. // if the context handle param is [in] generate code of the form:
  539. // if( Context_Handle != 0 )
  540. // {
  541. // _Handle = NdrContextBinding( Context_Handle );
  542. // }
  543. // else
  544. // {
  545. // RpcRaiseException( RPC_X_SS_IN_NULL_CONTEXT );
  546. // }
  547. //
  548. // if the context handle is [in, out] then generate code of the form:
  549. // if( Context_Handle != 0 )
  550. // {
  551. // Handle = NdrContextBinding( Context_Handle );
  552. // }
  553. // else
  554. // {
  555. // _Handle = 0;
  556. // }
  557. // Note: The case of [out] context handle will never come here since
  558. // this context handle is not a binding handle, and hence will be
  559. // handled elsewhere.
  560. //
  561. ITERATOR I;
  562. BOOL fIn = (SearchForBindingParam())->IsParamIn();
  563. BOOL fInOut = ((SearchForBindingParam())->IsParamOut()
  564. &&
  565. fIn );
  566. // For now assume we always have error checking on. When we get -error
  567. // none implemented on procs, we can set it based on that.
  568. BOOL fErrorCheckReqd = pCCB->MustCheckRef();
  569. expr_node * pAss;
  570. expr_node * pContextParam = ((CG_NDR *)SearchForBindingParam())->
  571. GenBindOrUnBindExpression(
  572. pCCB, TRUE );
  573. pExpr = pContextParam;
  574. pExpr = MakeExpressionOfCastToTypeName( CTXT_HDL_C_CONTEXT_TYPE_NAME,
  575. pExpr
  576. );
  577. ITERATOR_INSERT( I, pExpr );
  578. pExpr = MakeProcCallOutOfParamExprList( CTXT_HDL_BIND_RTN_NAME,
  579. (node_skl *)0,
  580. I
  581. );
  582. pAss= new expr_assign(GetBindingResource(), pExpr);
  583. if( !fErrorCheckReqd )
  584. {
  585. pCCB->GetStream()->NewLine();
  586. pAss->PrintCall( pCCB->GetStream(), 0, 0 );
  587. pCCB->GetStream()->Write(';');
  588. pCCB->GetStream()->NewLine();
  589. }
  590. else
  591. {
  592. Out_If( pCCB, new expr_relational(OP_NOT_EQUAL,
  593. pContextParam,
  594. new expr_constant(0L) ) );
  595. pCCB->GetStream()->NewLine();
  596. pAss->PrintCall( pCCB->GetStream(), 0, 0 );
  597. pCCB->GetStream()->Write(';');
  598. pCCB->GetStream()->NewLine();
  599. Out_Endif( pCCB );
  600. if( !fInOut )
  601. {
  602. Out_Else( pCCB );
  603. Out_RaiseException( pCCB, "RPC_X_SS_IN_NULL_CONTEXT" );
  604. Out_Endif( pCCB );
  605. }
  606. }
  607. }
  608. else if( pExpr )
  609. {
  610. pCCB->GetStream()->NewLine();
  611. pExpr->PrintCall( pCCB->GetStream(), 0, 0 );
  612. pCCB->GetStream()->Write(';');
  613. pCCB->GetStream()->NewLine();
  614. if ( IsGenericHandle() )
  615. {
  616. // For generic handles generate a check that the handle
  617. // is not null after calling user's bind routine.
  618. Out_If( pCCB, new expr_relational( OP_EQUAL,
  619. GetBindingResource(),
  620. new expr_constant(0L) ) );
  621. Out_RaiseException( pCCB, "RPC_S_INVALID_BINDING" );
  622. Out_Endif( pCCB );
  623. }
  624. }
  625. return CG_OK;
  626. }
  627. CG_STATUS
  628. CG_PROC::C_GenSendReceive(
  629. CCB * pCCB )
  630. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  631. Routine Description:
  632. Generate code to call the rpc runtime sendreceive.
  633. Arguments:
  634. pCCB - A pointer to the code generation controller block.
  635. Return Value:
  636. CG_OK if all is well
  637. error Otherwise.
  638. Notes:
  639. We will always call an ndr routine for the sendreceive call. This
  640. is so that we can unify the buffer length updating in that one call.
  641. The only difference is for Auto handles when we will have to call this
  642. with an additional parameter.
  643. ----------------------------------------------------------------------------*/
  644. {
  645. PNAME pProcName;
  646. expr_proc_call * pProc;
  647. expr_node * pExpr;
  648. expr_node * pStubMsgExpr = pCCB->GetStandardResource(
  649. ST_RES_STUB_MESSAGE_VARIABLE );
  650. ITERATOR ParamsList;
  651. //
  652. // Check if we're targeting the ndr engine.
  653. //
  654. if ( pCCB->GetOptimOption() & OPTIMIZE_SIZE )
  655. {
  656. if ( IsAutoHandle() )
  657. Out_NdrNsSendReceive( pCCB );
  658. else
  659. Out_NdrSendReceive( pCCB );
  660. return CG_OK;
  661. }
  662. // update the param list with a pointer to the stub message.
  663. pStubMsgExpr = MakeAddressExpressionNoMatterWhat( pStubMsgExpr );
  664. ITERATOR_INSERT( ParamsList, pStubMsgExpr );
  665. // In case of auto handles, an additional param is reqd, viz the
  666. // address of the auto handle variable.
  667. if( IsAutoHandle() )
  668. {
  669. pExpr = pCCB->GetStandardResource( ST_RES_AUTO_BH_VARIABLE );
  670. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  671. ITERATOR_INSERT( ParamsList, pExpr );
  672. pProcName = AUTO_SR_NDR_RTN_NAME;
  673. }
  674. else
  675. {
  676. pProcName = NORMAL_SR_NDR_RTN_NAME;
  677. }
  678. ITERATOR_INSERT( ParamsList,
  679. new expr_variable( STUB_MSG_BUFFER_VAR_NAME ) );
  680. // generate the procedure call expression.
  681. pProc = MakeProcCallOutOfParamExprList( pProcName,
  682. (node_skl *)0,
  683. ParamsList
  684. );
  685. pCCB->GetStream()->NewLine();
  686. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  687. return CG_OK;
  688. }
  689. CG_STATUS
  690. CG_PROC::C_GenUnBind(
  691. CCB * pCCB)
  692. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  693. Routine Description:
  694. Generate code to unbind from server.
  695. Arguments:
  696. pCCB - A pointer to the code generation controller block.
  697. Return Value:
  698. CG_OK if all is well
  699. error Otherwise.
  700. Notes:
  701. Dont make unbind calls if not a generic handle.
  702. ----------------------------------------------------------------------------*/
  703. {
  704. if( IsGenericHandle() )
  705. {
  706. ISTREAM * pStream = pCCB->GetStream();
  707. expr_proc_call * pUnBindCall =
  708. (expr_proc_call *)GenBindOrUnBindExpression( pCCB, FALSE );
  709. pStream->NewLine();
  710. Out_If( pCCB, GetBindingResource() );
  711. pStream->NewLine();
  712. pUnBindCall->PrintCall( pStream, 0, 0 );
  713. Out_Endif( pCCB );
  714. }
  715. return CG_OK;
  716. }
  717. CG_STATUS
  718. CG_PROC::C_GenFreeBuffer(
  719. CCB * pCCB)
  720. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  721. Routine Description:
  722. Generate code to call runtime to free the rpc buffer.
  723. Arguments:
  724. pCCB - A pointer to the code generation controller block.
  725. Return Value:
  726. CG_OK if all is well
  727. error Otherwise.
  728. Notes:
  729. The analyser will supply the binding information.
  730. ----------------------------------------------------------------------------*/
  731. {
  732. if ( pCCB->GetOptimOption() & OPTIMIZE_SIZE )
  733. {
  734. Out_NdrFreeBuffer( pCCB );
  735. return CG_OK;
  736. }
  737. Out_NormalFreeBuffer( pCCB );
  738. return CG_OK;
  739. }
  740. CG_STATUS
  741. CG_PROC::GenServerStub(
  742. CCB * pCCB )
  743. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  744. Routine Description:
  745. Generate the server side unmarshalling stub.
  746. Arguments:
  747. pCCB - A pointer to the code generation block.
  748. Return Value:
  749. CG_OK if all is well
  750. error otherwise.
  751. Notes:
  752. ----------------------------------------------------------------------------*/
  753. {
  754. ANALYSIS_INFO Analysis;
  755. DISPATCH_TABLE_FLAGS Dtf;
  756. BOOL fEmitCheckStubData;
  757. // call_as procs need additional prototypes
  758. if ( pCallAsName )
  759. pCCB->RegisterCallAsRoutine( (node_proc *)GetType() );
  760. BOOL fPicklingProcOrType = GetCGID() == ID_CG_ENCODE_PROC ||
  761. GetCGID() == ID_CG_TYPE_ENCODE_PROC;
  762. //
  763. // Set the CCB code generation side.
  764. //
  765. pCCB->SetCodeGenSide( CGSIDE_SERVER );
  766. pCCB->SetCodeGenPhase( CGPHASE_UNMARSHALL );
  767. pCCB->SetOptimOption( GetOptimizationFlags() );
  768. Analysis.SetCurrentSide( S_SIDE );
  769. Analysis.SetOptimOption( pCCB->GetOptimOption() );
  770. // Set the analysis phase to the correct one.
  771. Analysis.SetCurrentPhase( ANA_PHASE_SERVER_UNMARSHALL );
  772. //
  773. // Change to -Os if needed because of number of param and/or stack size.
  774. //
  775. (void) MustUseSingleEngineCall( pCCB );
  776. Analysis.SetOptimOption( pCCB->GetOptimOption() );
  777. Analysis.SetMode( pCCB->GetMode() );
  778. Analysis.SetRpcSSSwitchSet( (unsigned long)pCCB->IsRpcSSSwitchSet() );
  779. // Preallocate param and local resources if needed. We do need at least
  780. // one param resource - the rpc message pointer.
  781. S_PreAllocateResources( &Analysis );
  782. // The unmarshall analysis figures out the local variables needed,
  783. // and their allocation type. This helps the code generator select the
  784. // most optimal instruction. This is performed only for [in] and [in,out]
  785. // params.
  786. UnMarshallAnalysis( &Analysis );
  787. // Perform the initialization analysis for the server side locals if
  788. // allocated for the [out] ONLY parameters.
  789. S_OutLocalAnalysis( &Analysis );
  790. // Perform this analysis so the format string is correct for server.
  791. // It is needed for -Oi RpcSs flag generation.
  792. RpcSsPackageAnalysis( &Analysis );
  793. // Perform InLocalAnalysis to allocate any in params( for now arrays of
  794. // ref pointers only) on the server side stub stack.
  795. InLocalAnalysis( &Analysis );
  796. // Perform the size analysis for the marshalling part of the stub.
  797. Analysis.SetCurrentPhase( ANA_PHASE_SERVER_MARSHALL );
  798. MarshallAnalysis( &Analysis );
  799. // Generate the unmarshalling code. Register this procedure with the
  800. // dispatch table. Copy the resource dictionary from the analysis phase
  801. // to be used during the code gen phase.
  802. char * AllocRoutineName, * FreeRoutineName;
  803. GetCorrectAllocFreeRoutines( pCCB,
  804. TRUE, //client
  805. &AllocRoutineName,
  806. &FreeRoutineName );
  807. pCCB->InitForNewProc(
  808. GetProcNum(), // procedure number
  809. (RPC_FLAGS)0, // flags, datagram etc
  810. (PNAME) AllocRoutineName,
  811. (PNAME) FreeRoutineName,
  812. Analysis.GetResDictDatabase() // copy the resource database
  813. );
  814. if( HasNotify() || HasNotifyFlag() )
  815. GetNotifyTableOffset( pCCB );
  816. // Register the procedure for the dispatch table.
  817. // If this proc is interpreted, then the dispatch table has an
  818. // entry which specifies the NdrServerCall rather than the proc name itself.
  819. if( GetOptimizationFlags() & OPTIMIZE_INTERPRETER )
  820. {
  821. Dtf = DTF_INTERPRETER;
  822. }
  823. else
  824. {
  825. Dtf = DTF_NONE;
  826. }
  827. if ( GetCGID() == ID_CG_ENCODE_PROC )
  828. Dtf = (DISPATCH_TABLE_FLAGS) (Dtf | DTF_PICKLING_PROC);
  829. if ( GetCGID() != ID_CG_TYPE_ENCODE_PROC )
  830. pCCB->GetInterfaceCG()->RegisterProcedure( GetType(), Dtf );
  831. if ( ! fPicklingProcOrType )
  832. {
  833. if ( MustUseSingleEngineCall( pCCB ) )
  834. {
  835. if ( UseOldInterpreterMode( pCCB ) )
  836. {
  837. GenNdrOldInterpretedServerStub( pCCB );
  838. }
  839. if ( NeedsServerThunk( pCCB, CGSIDE_SERVER ) )
  840. {
  841. GenNdrThunkInterpretedServerStub( pCCB );
  842. }
  843. //
  844. // This will only do something for a [callback] proc when we're
  845. // called while generating the client side.
  846. //
  847. MIDL_ASSERT( pCommand->IsNDRRun() || pCommand->IsNDR64Run() );
  848. if ( pCommand->IsNDRRun() )
  849. {
  850. GenNdrFormat( pCCB );
  851. }
  852. else
  853. {
  854. pCCB->GetNdr64Format()->Generate( this );
  855. }
  856. return CG_OK;
  857. }
  858. }
  859. pCCB->SetCGNodeContext( this );
  860. //
  861. // Always create the format string for the proc.
  862. //
  863. if ( pCommand->IsNDRRun() )
  864. {
  865. GenNdrFormat( pCCB );
  866. }
  867. else
  868. {
  869. pCCB->GetNdr64Format()->Generate( this );
  870. }
  871. // Dont generate the stub itself for pickling.
  872. if ( fPicklingProcOrType )
  873. return( CG_OK );
  874. // Generate the server side procedure prolog. This generates only the
  875. // server side proc signature, the locals needed and the stub descriptor
  876. // structure.
  877. // This also generates the call to server initialize routine.
  878. // Note, that it is out of RpcTryFinally, but this is ok as
  879. // we shouldn't attempt to free parameters (they haven't been
  880. // unmarshaled yet.
  881. S_GenProlog( pCCB );
  882. S_GenInitTopLevelStuff( pCCB );
  883. S_GenInitInLocals( pCCB );
  884. // Initialize the local variables allocated on the server side if necessary.
  885. // Also make the initialization call for the server side stub message which
  886. // updates the buffer pointer.
  887. // Generate the unmarshalling code.
  888. Out_RpcTryFinally( pCCB );
  889. // If the user specifies the -error stub_data to check server unmarshall
  890. // errors, we need to enclose the unmarshall in a try except, and in the
  891. // except clause, raise a bad stub data exception.
  892. fEmitCheckStubData = pCCB->IsMustCheckStubDataSpecified() && !IsObject();
  893. if( fEmitCheckStubData )
  894. {
  895. Out_RpcTryExcept( pCCB );
  896. }
  897. if ( HasFullPtr() )
  898. Out_FullPointerInit( pCCB );
  899. // generate NdrCorrelationInitialize( _StubMsg, _NdrCorrCache, _NdrCorrCacheSize, _NdrCorrFlags );
  900. // normally, /deny causes a switch to /Oicf. This code will be executed when a
  901. // a switch to from /Os to /Oicf is not posible
  902. if ( fHasDeny )
  903. {
  904. GenCorrInit( pCCB );
  905. }
  906. GenUnMarshall( pCCB );
  907. // generate NdrCorrelationUninitialize( _StubMsg );
  908. // normally, /deny causes a switch to /Oicf. This code will be executed when a
  909. // a switch to from /Os to /Oicf is not posible
  910. if ( fHasDeny )
  911. {
  912. GenCorrPassFree( pCCB, CSTUB_CORR_PASS_RTN_NAME );
  913. }
  914. // If the check for bad stub data must be made, then generate a
  915. // Rpcexcept() to catch some exceptions here, and re-raise a bad
  916. // stub data exception for them.
  917. // Other exceptions would propagate unchanged.
  918. if( fEmitCheckStubData )
  919. {
  920. Out_CheckUnMarshallPastBufferEnd( pCCB );
  921. Out_RpcExcept( pCCB, "RPC_BAD_STUB_DATA_EXCEPTION_FILTER" );
  922. Out_RaiseException( pCCB, "RPC_X_BAD_STUB_DATA" );
  923. Out_RpcEndExcept( pCCB );
  924. }
  925. S_GenInitOutLocals( pCCB );
  926. // Generate the call to the actual manager procedure.
  927. S_GenCallManager( pCCB );
  928. S_GenInitMarshall( pCCB );
  929. pCCB->SetCodeGenPhase( CGPHASE_MARSHALL );
  930. GenSizing( pCCB );
  931. // Generate the server side marshall initialization.
  932. // Marshall the outs and return value.
  933. GenMarshall( pCCB );
  934. Out_RpcFinally( pCCB );
  935. if ( fHasDeny )
  936. {
  937. GenCorrPassFree( pCCB, CSTUB_CORR_FREE_RTN_NAME );
  938. }
  939. // When notify is used, guard also against an exception in freeing.
  940. if( HasNotify() || HasNotifyFlag() )
  941. {
  942. Out_RpcTryFinally( pCCB );
  943. }
  944. // Free anything that needs freeing.
  945. GenFree( pCCB );
  946. if( MustInvokeRpcSSAllocate())
  947. {
  948. Out_RpcSSDisableAllocate( pCCB );
  949. }
  950. if ( HasFullPtr() )
  951. Out_FullPointerFree( pCCB );
  952. // If this is a notify procedure, generate the call to the notify procedure.
  953. if( HasNotify() || HasNotifyFlag() )
  954. {
  955. Out_RpcFinally( pCCB );
  956. GenNotify( pCCB , HasNotifyFlag() );
  957. Out_RpcEndFinally( pCCB );
  958. }
  959. Out_RpcEndFinally( pCCB );
  960. // For now, just return.
  961. GenEpilog( pCCB );
  962. return CG_OK;
  963. }
  964. CG_STATUS
  965. CG_PROC::S_GenInitMarshall(
  966. CCB * pCCB )
  967. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  968. Routine Description:
  969. Generate the server side marshall init.
  970. Arguments:
  971. pCCB - A pointer to the code generation controller block.
  972. Return Value:
  973. CG_OK if all is well,
  974. error otherwise.
  975. Notes:
  976. ----------------------------------------------------------------------------*/
  977. {
  978. CG_ITERATOR Iterator;
  979. ISTREAM * pStream;
  980. CG_PARAM * pParam;
  981. CG_NDR * pNdr;
  982. //
  983. // We have to fill in the arrays that we use for handling multidimensional
  984. // arrays.
  985. //
  986. pStream = pCCB->GetStream();
  987. GetMembers( Iterator );
  988. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  989. {
  990. pNdr = (CG_NDR *) pParam->GetChild();
  991. if ( (pNdr->IsArray() && ((CG_ARRAY *)pNdr)->IsMultiConfOrVar()) ||
  992. (pNdr->IsPointer() && ((CG_POINTER *)pNdr)->IsMultiSize()) )
  993. Out_MultiDimVarsInit( pCCB, pParam );
  994. }
  995. return CG_OK;
  996. }
  997. CG_STATUS
  998. CG_PROC::S_GenInitOutLocals(
  999. CCB * pCCB )
  1000. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1001. Routine Description:
  1002. Generate the initialization of the local variables.
  1003. Arguments:
  1004. pCCB - A pointer to the code generation controller block.
  1005. Return Value:
  1006. CG_OK if all is well,
  1007. error otherwise.
  1008. Notes:
  1009. This method performs initalization of local variables on the server side.
  1010. Local variables may be declared in the server stub for [out] params, and
  1011. for in parameters which cannot reuse the buffer.
  1012. This method will also perform the stub descriptor structure initialization.
  1013. This method will also perform the server side stub message init.
  1014. ----------------------------------------------------------------------------*/
  1015. {
  1016. CG_ITERATOR Iter;
  1017. CG_PARAM * pParam;
  1018. if( GetMembers( Iter ) )
  1019. {
  1020. while( ITERATOR_GETNEXT( Iter, pParam ) )
  1021. {
  1022. pParam->S_GenInitOutLocals( pCCB );
  1023. }
  1024. }
  1025. //
  1026. // We have to catch initialization of returns of pointers to context
  1027. // handles here.
  1028. //
  1029. if ( GetReturnType() )
  1030. {
  1031. GetReturnType()->S_GenInitOutLocals( pCCB );
  1032. }
  1033. return CG_OK;
  1034. }
  1035. CG_STATUS
  1036. CG_PROC::S_GenCallManager(
  1037. CCB * pCCB )
  1038. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1039. Routine Description:
  1040. Generate a call to the manager routine.
  1041. Arguments:
  1042. pCCB - A pointer to the code generation controller block.
  1043. Return Value:
  1044. CG_OK if all is well
  1045. error otherwise.
  1046. Notes:
  1047. Make a procedure node with all the parameters that need to be passed to
  1048. the manager code. The actual expression that needs to be passed to the
  1049. actual manager code is set up during earlier passes. This is called the
  1050. result expression.
  1051. ----------------------------------------------------------------------------*/
  1052. {
  1053. CG_ITERATOR I;
  1054. PNAME pName;
  1055. expr_proc_call * pProc;
  1056. CG_PARAM * pParam;
  1057. expr_node * pExpr;
  1058. expr_node * pReturnExpr = 0;
  1059. CG_RETURN * pRT;
  1060. char * pSStubPrefix = NULL;
  1061. pSStubPrefix = pCommand->GetUserPrefix( PREFIX_SERVER_MGR );
  1062. if ( GetCallAsName() )
  1063. pName = (PNAME ) GenMangledCallAsName( pCCB );
  1064. else if ( pSStubPrefix )
  1065. {
  1066. pName = new char[ strlen(pSStubPrefix) + strlen(GetType()->GetSymName()) + 1];
  1067. strcpy( pName, pSStubPrefix );
  1068. strcat( pName, GetType()->GetSymName() );
  1069. }
  1070. else
  1071. pName = (PNAME ) GetType()->GetSymName();
  1072. pProc = new expr_proc_call( pName );
  1073. GetMembers( I );
  1074. while( ITERATOR_GETNEXT( I, pParam ) )
  1075. {
  1076. if ( pParam->IsOmittedParam() )
  1077. continue;
  1078. if ( ( pExpr = pParam->GetFinalExpression() ) != 0 )
  1079. {
  1080. CG_NDR * pChild = (CG_NDR *)pParam->GetChild();
  1081. //
  1082. // We have to dereference arrays because of how they are defined
  1083. // in the stub.
  1084. //
  1085. if ( pChild->IsArray() )
  1086. {
  1087. pExpr = new expr_u_deref( pExpr );
  1088. }
  1089. else if( (pChild->GetCGID() == ID_CG_GENERIC_HDL ) &&
  1090. (((CG_NDR *)pChild->GetChild())->IsArray() )
  1091. )
  1092. {
  1093. pExpr = new expr_u_deref( pExpr );
  1094. }
  1095. //
  1096. // Context handle param is handled differently.
  1097. //
  1098. if ( (pChild->GetCGID() == ID_CG_CONTEXT_HDL) ||
  1099. ((pChild->GetCGID() == ID_CG_PTR) &&
  1100. (((CG_NDR *)pChild->GetChild())->GetCGID() ==
  1101. ID_CG_CONTEXT_HDL)) )
  1102. {
  1103. expr_proc_call * pCall;
  1104. pCall = new expr_proc_call( "NDRSContextValue" );
  1105. pCall->SetParam(
  1106. new expr_param(
  1107. new expr_variable(
  1108. pParam->GetResource()->GetResourceName() )) );
  1109. expr_node * pFinal;
  1110. if ( pChild->GetCGID() == ID_CG_CONTEXT_HDL )
  1111. pFinal = new expr_u_deref(pCall);
  1112. else
  1113. pFinal = pCall;
  1114. //
  1115. // Dereference a plain context handle.
  1116. //
  1117. pExpr = new expr_cast( pParam->GetType()->GetChild(),
  1118. pFinal );
  1119. }
  1120. pProc->SetParam( new expr_param( pExpr ) );
  1121. }
  1122. }
  1123. if ( ( pRT = GetReturnType() ) != 0 )
  1124. {
  1125. pReturnExpr = pRT->GetFinalExpression();
  1126. }
  1127. if ( HasNotifyFlag() )
  1128. {
  1129. // Assign TRUE to the notify flag variable.
  1130. expr_node * pNotifyFlag;
  1131. expr_node * pAssignExpr;
  1132. ISTREAM * pStream = pCCB->GetStream();
  1133. pNotifyFlag = new expr_variable( NOTIFY_FLAG_VAR_NAME );
  1134. pAssignExpr = new expr_assign( pNotifyFlag,
  1135. new expr_variable( "TRUE" ) );
  1136. pStream->NewLine();
  1137. pAssignExpr->Print( pStream );
  1138. pStream->Write( ';' );
  1139. pStream->NewLine();
  1140. }
  1141. Out_CallManager( pCCB,
  1142. pProc,
  1143. pReturnExpr,
  1144. (GetCGID() == ID_CG_CALLBACK_PROC)
  1145. );
  1146. return CG_OK;
  1147. }
  1148. CG_STATUS
  1149. CG_PROC::S_GenInitTopLevelStuff(
  1150. CCB * pCCB )
  1151. {
  1152. CG_ITERATOR Iter;
  1153. CG_NDR * pParam;
  1154. if( GetMembers( Iter ) )
  1155. {
  1156. while( ITERATOR_GETNEXT( Iter, pParam ) )
  1157. {
  1158. pParam->S_GenInitTopLevelStuff( pCCB );
  1159. }
  1160. }
  1161. if ( GetReturnType() )
  1162. GetReturnType()->S_GenInitTopLevelStuff( pCCB );
  1163. return CG_OK;
  1164. }
  1165. CG_STATUS
  1166. CG_PROC::S_GenProlog(
  1167. CCB * pCCB )
  1168. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1169. Routine Description:
  1170. Generate the server side stub prolog.
  1171. Arguments:
  1172. pCCB - A pointer to the code generation controller block.
  1173. Return Value:
  1174. CG_OK if all is well
  1175. error Otherwise.
  1176. Notes:
  1177. Print out the signature, locals, the stub descriptor if needed and the
  1178. adjust indent in anticipation of code.
  1179. ----------------------------------------------------------------------------*/
  1180. {
  1181. ITERATOR LocalsList;
  1182. ITERATOR ParamsList;
  1183. ITERATOR TransientList;
  1184. // Collect all the params and locals into lists ready to print.
  1185. pCCB->GetListOfLocalResources( LocalsList );
  1186. pCCB->GetListOfParamResources( ParamsList );
  1187. pCCB->GetListOfTransientResources( TransientList );
  1188. //
  1189. // Print out the procedure signature and the local variables.
  1190. //
  1191. Out_ServerProcedureProlog( pCCB,
  1192. GetType(),
  1193. LocalsList,
  1194. ParamsList,
  1195. TransientList
  1196. );
  1197. //
  1198. // Done for interpretation op. No indent needed either.
  1199. //
  1200. if ( pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER )
  1201. return CG_OK;
  1202. //
  1203. // This is where we output additional variable declarations to handle
  1204. // multidimensional conformant/varying arrays.
  1205. //
  1206. CG_ITERATOR Iterator;
  1207. ISTREAM * pStream;
  1208. CG_PARAM * pParam;
  1209. CG_NDR * pNdr;
  1210. pStream = pCCB->GetStream();
  1211. GetMembers( Iterator );
  1212. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  1213. {
  1214. pNdr = (CG_NDR *) pParam->GetChild();
  1215. if ( (pNdr->IsArray() && ((CG_ARRAY *)pNdr)->IsMultiConfOrVar()) ||
  1216. (pNdr->IsPointer() && ((CG_POINTER *)pNdr)->IsMultiSize()) )
  1217. Out_MultiDimVars( pCCB, pParam );
  1218. }
  1219. pStream->NewLine();
  1220. // Removes warning if we don't use the _Status variable.
  1221. pStream->Write( "((void)(" RPC_STATUS_VAR_NAME "));" );
  1222. pStream->NewLine();
  1223. if ( HasNotifyFlag() )
  1224. {
  1225. // Assign FALSE to the notify flag variable.
  1226. expr_node * pNotifyFlag;
  1227. expr_node * pAssignExpr;
  1228. pNotifyFlag = new expr_variable( NOTIFY_FLAG_VAR_NAME );
  1229. pAssignExpr = new expr_assign( pNotifyFlag,
  1230. new expr_variable( "FALSE" ) );
  1231. pStream->NewLine();
  1232. pAssignExpr->Print( pStream );
  1233. pStream->Write( ';' );
  1234. pStream->NewLine();
  1235. }
  1236. //
  1237. // Call the NdrServerInitialize routine.
  1238. //
  1239. expr_proc_call * pCall;
  1240. pCall = new expr_proc_call( SSTUB_INIT_RTN_NAME );
  1241. pCall->SetParam( new expr_param (
  1242. new expr_variable( PRPC_MESSAGE_VAR_NAME ) ) );
  1243. pCall->SetParam( new expr_param (
  1244. new expr_u_address (
  1245. new expr_variable( STUB_MESSAGE_VAR_NAME ) ) ) );
  1246. pCall->SetParam( new expr_param (
  1247. new expr_u_address (
  1248. new expr_variable(
  1249. pCCB->GetInterfaceCG()->GetStubDescName() ) ) ) );
  1250. pCall->PrintCall( pCCB->GetStream(), 0, 0 );
  1251. pStream->NewLine();
  1252. // if the rpc ss package is to be enabled, do so.
  1253. if( MustInvokeRpcSSAllocate() )
  1254. {
  1255. Out_RpcSSEnableAllocate( pCCB );
  1256. }
  1257. return CG_OK;
  1258. }
  1259. CG_STATUS
  1260. CG_PROC::GenUnMarshall(
  1261. CCB * pCCB )
  1262. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1263. Routine Description:
  1264. Generate the unmarshalling code for the server side stub.
  1265. Arguments:
  1266. pCCB - A pointer to the code generation controller block.
  1267. Return Value:
  1268. CG_OK if all is well,
  1269. error Otherwise.
  1270. Notes:
  1271. The new server stubs will contain an ndr transformation phase which will
  1272. convert, in-situ, any incoming buffer that needs ndr transformations like
  1273. big-little endian conversions, char / float transformations etc.
  1274. Therefore the first thing the server stub does is to tranform the data into
  1275. the correct format and then the rest of the stub can proceed as if the
  1276. data came in little endian format.
  1277. Currently we will use the engine to tranform the data.
  1278. ----------------------------------------------------------------------------*/
  1279. {
  1280. CG_ITERATOR Iterator;
  1281. ITERATOR ParamList;
  1282. CG_RETURN * pRT;
  1283. CGSIDE Side;
  1284. BOOL fReturnNeedsUnMarshall = FALSE;
  1285. long ParamTotal;
  1286. GetMembers( Iterator );
  1287. ParamTotal = ITERATOR_GETCOUNT( Iterator );
  1288. if ( GetReturnType() )
  1289. ParamTotal++;
  1290. pCCB->SetCodeGenPhase( CGPHASE_UNMARSHALL );
  1291. // Generate a call to tranform the data into the proper endianness.
  1292. S_XFormToProperFormat( pCCB );
  1293. // For all [in] params, generate the unmarshalling code.
  1294. if( (Side = pCCB->GetCodeGenSide()) == CGSIDE_CLIENT )
  1295. GetOutParamList( ParamList );
  1296. else
  1297. GetInParamList( ParamList );
  1298. if ( (Side == CGSIDE_CLIENT) && (pRT = GetReturnType()) != 0 )
  1299. fReturnNeedsUnMarshall = TRUE;
  1300. //
  1301. // Output the call to check for and perform endian or other transformations
  1302. // if needed.
  1303. //
  1304. if ( fReturnNeedsUnMarshall || ParamList.GetCount() )
  1305. Out_NdrConvert( pCCB,
  1306. GetFormatStringParamStart(),
  1307. ParamTotal,
  1308. GetOptimizationFlags() );
  1309. if( ITERATOR_GETCOUNT( ParamList ) )
  1310. {
  1311. CG_PARAM * pParam;
  1312. CG_PARAM * pS;
  1313. ITERATOR_INIT( ParamList );
  1314. while( ITERATOR_GETNEXT( ParamList, pParam ) )
  1315. {
  1316. // The extra fault/comm status param doesn't go on wire.
  1317. pS = (CG_PARAM *)ITERATOR_PEEKTHIS( ParamList );
  1318. pParam->GenUnMarshall( pCCB );
  1319. }
  1320. }
  1321. // For the client side, generate the unmarshall call if there is a return
  1322. // value.
  1323. if( fReturnNeedsUnMarshall )
  1324. {
  1325. pRT->GenUnMarshall( pCCB );
  1326. }
  1327. return CG_OK;
  1328. }
  1329. CG_STATUS
  1330. CG_PROC::GenFree(
  1331. CCB * pCCB )
  1332. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1333. Routine Description:
  1334. Generates freeing code.
  1335. Arguments:
  1336. pCCB - A pointer to the code generation controller block.
  1337. Return Value:
  1338. CG_OK if all is well
  1339. error Otherwise.
  1340. Notes:
  1341. ----------------------------------------------------------------------------*/
  1342. {
  1343. CG_ITERATOR ParamList;
  1344. CGSIDE Side;
  1345. CG_RETURN * pRT;
  1346. BOOL fReturnNeedsFree = FALSE;
  1347. if( (Side = pCCB->GetCodeGenSide()) == CGSIDE_CLIENT )
  1348. return CG_OK;
  1349. // Else it's the server side
  1350. GetMembers( ParamList );
  1351. if ( ( pRT = GetReturnType() ) != 0 )
  1352. fReturnNeedsFree = TRUE;
  1353. if( ITERATOR_GETCOUNT( ParamList ) )
  1354. {
  1355. CG_PARAM * pParam;
  1356. ITERATOR_INIT( ParamList );
  1357. while( ITERATOR_GETNEXT( ParamList, pParam ) )
  1358. {
  1359. pParam->GenFree( pCCB );
  1360. }
  1361. }
  1362. //
  1363. // Size the return value on the server side if needed.
  1364. //
  1365. if( fReturnNeedsFree )
  1366. {
  1367. pRT->GenFree( pCCB );
  1368. }
  1369. return CG_OK;
  1370. }
  1371. CG_STATUS
  1372. CG_PROC::GenNotify(
  1373. CCB * pCCB,
  1374. BOOL fHasFlag )
  1375. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1376. Routine Description:
  1377. Generate the notify call for the procedure.
  1378. Arguments:
  1379. pCCB - A pointer to the code generation controller block.
  1380. Return Value:
  1381. Notes:
  1382. We need to generate a call to foo_notify with all parameters, exactly
  1383. the same as the original procedure. The return value is a void.
  1384. ----------------------------------------------------------------------------*/
  1385. {
  1386. ISTREAM * pStream = pCCB->GetStream();
  1387. // Create an expression for the call to the notify procedure. The name
  1388. // of the notify procedure is the procname suffixed by _notify.
  1389. CSzBuffer ProcName;
  1390. ProcName.Set( GetType()->GetSymName() );
  1391. ProcName.Append( (fHasFlag ? NOTIFY_FLAG_SUFFIX
  1392. : NOTIFY_SUFFIX) );
  1393. expr_proc_call ProcExpr( ProcName.GetData(), 0 );
  1394. expr_variable * pVarNode;
  1395. expr_param * pFlagParam;
  1396. if ( fHasFlag )
  1397. {
  1398. pVarNode = new expr_variable( NOTIFY_FLAG_VAR_NAME );
  1399. pFlagParam = new expr_param( pVarNode );
  1400. ProcExpr.SetParam( pFlagParam );
  1401. }
  1402. // The call expression has been made. Emit it.
  1403. pStream->NewLine();
  1404. ProcExpr.PrintCall( pStream, 0, 0 );
  1405. pStream->NewLine();
  1406. // Clean up.
  1407. if ( fHasFlag )
  1408. {
  1409. delete pVarNode;
  1410. delete pFlagParam;
  1411. }
  1412. return CG_OK;
  1413. }
  1414. CG_STATUS
  1415. CG_PROC::GenEpilog(
  1416. CCB * pCCB )
  1417. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1418. Routine Description:
  1419. Generate the server side epilog for the procedure.
  1420. Arguments:
  1421. pCCB - A pointer to the code generation controller block.
  1422. Return Value:
  1423. Notes:
  1424. Decrement the indent back to the initial, and emit the closing brace.
  1425. ----------------------------------------------------------------------------*/
  1426. {
  1427. if( (pCCB->GetCodeGenSide() == CGSIDE_CLIENT) && GetReturnType() )
  1428. {
  1429. expr_node * pExpr = new expr_variable( RETURN_VALUE_VAR_NAME );
  1430. pCCB->GetStream()->NewLine();
  1431. pCCB->GetStream()->Write( "return " );
  1432. pExpr->Print( pCCB->GetStream() );
  1433. pCCB->GetStream()->Write( ';' );
  1434. }
  1435. if ( (pCCB->GetCodeGenSide() == CGSIDE_SERVER) )
  1436. {
  1437. ISTREAM * pStream = pCCB->GetStream();
  1438. pStream->Write( PRPC_MESSAGE_VAR_NAME "->BufferLength = " );
  1439. pStream->NewLine();
  1440. pStream->Spaces( STANDARD_STUB_TAB );
  1441. pStream->Write( "(unsigned int)(" STUB_MESSAGE_VAR_NAME ".Buffer - ");
  1442. pStream->Write( "(unsigned char *)" PRPC_MESSAGE_VAR_NAME "->Buffer);" );
  1443. pStream->NewLine();
  1444. }
  1445. Out_IndentDec( pCCB );
  1446. Out_ProcClosingBrace( pCCB );
  1447. return CG_OK;
  1448. }
  1449. CG_STATUS
  1450. CG_PROC::GenSizing(
  1451. CCB * pCCB )
  1452. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1453. Routine Description:
  1454. Generate sizing code.
  1455. Arguments:
  1456. pCCB - A pointer to the code generation controller block.
  1457. Return Value:
  1458. CG_OK if all is well
  1459. error Otherwise.
  1460. Notes:
  1461. ----------------------------------------------------------------------------*/
  1462. {
  1463. ITERATOR ParamList;
  1464. CGSIDE Side;
  1465. CG_RETURN * pRT;
  1466. BOOL fReturnNeedsSizing = FALSE;
  1467. short ParamCount = 0;
  1468. pCCB->GetStream()->NewLine();
  1469. if( (Side = pCCB->GetCodeGenSide()) == CGSIDE_CLIENT )
  1470. ParamCount = GetInParamList( ParamList );
  1471. else
  1472. ParamCount = GetOutParamList( ParamList );
  1473. if ( (Side == CGSIDE_SERVER) && (pRT = GetReturnType()) != 0 )
  1474. fReturnNeedsSizing = TRUE;
  1475. // On the server side if there are no out params and no returns, dont
  1476. // generate code for sizing and get buffer at all !
  1477. if( (Side == CGSIDE_SERVER) && (ParamCount == 0) && !fReturnNeedsSizing )
  1478. {
  1479. return CG_OK;
  1480. }
  1481. //
  1482. // Analyze all the parameters and compute the constant buffer.
  1483. //
  1484. long ConstantBufferSize = 0;
  1485. if( ITERATOR_GETCOUNT( ParamList ) )
  1486. {
  1487. CG_PARAM * pParam;
  1488. ITERATOR_INIT( ParamList );
  1489. while( ITERATOR_GETNEXT( ParamList, pParam ) )
  1490. {
  1491. long ParamBufferSize = pParam->FixedBufferSize( pCCB );
  1492. pParam->SetFixedBufferSize( ParamBufferSize );
  1493. if (-1 != ParamBufferSize)
  1494. ConstantBufferSize += ParamBufferSize;
  1495. }
  1496. }
  1497. //
  1498. // Size the return value on the server side if needed.
  1499. //
  1500. if( fReturnNeedsSizing )
  1501. {
  1502. long ReturnBufferSize = pRT->FixedBufferSize( pCCB );
  1503. pRT->SetFixedBufferSize( ReturnBufferSize );
  1504. if (-1 != ReturnBufferSize)
  1505. ConstantBufferSize += ReturnBufferSize;
  1506. }
  1507. //
  1508. // Init the length variable to 0.
  1509. //
  1510. Out_Assign( pCCB,
  1511. new expr_variable ( STUB_MSG_LENGTH_VAR_NAME, 0 ),
  1512. new expr_constant( ConstantBufferSize )
  1513. );
  1514. if( ITERATOR_GETCOUNT( ParamList ) )
  1515. {
  1516. CG_PARAM * pParam;
  1517. ITERATOR_INIT( ParamList );
  1518. while( ITERATOR_GETNEXT( ParamList, pParam ) )
  1519. {
  1520. if (pParam->GetFixedBufferSize() == -1)
  1521. pParam->GenSizing( pCCB );
  1522. }
  1523. }
  1524. //
  1525. // Size the return value on the server side if needed.
  1526. //
  1527. if( fReturnNeedsSizing )
  1528. {
  1529. if (pRT->GetFixedBufferSize() == -1)
  1530. pRT->GenSizing( pCCB );
  1531. }
  1532. GenGetBuffer( pCCB );
  1533. return CG_OK;
  1534. }
  1535. CG_STATUS
  1536. CG_PROC::GenGetBuffer(
  1537. CCB * pCCB )
  1538. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1539. Routine Description:
  1540. Get the message buffer.
  1541. Arguments:
  1542. pCCB - A pointer to the code generation controller block.
  1543. Return Value:
  1544. CG_OK if all is well
  1545. error Otherwise.
  1546. Notes:
  1547. ----------------------------------------------------------------------------*/
  1548. {
  1549. if ( IsAutoHandle() && (pCCB->GetCodeGenSide() == CGSIDE_CLIENT) )
  1550. Out_NdrNsGetBuffer( pCCB );
  1551. else
  1552. Out_NdrGetBuffer( pCCB );
  1553. return CG_OK;
  1554. }
  1555. CG_STATUS
  1556. CG_PROC::GenMarshall(
  1557. CCB * pCCB )
  1558. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1559. Routine Description:
  1560. Server side procedure to marshall out params.
  1561. Arguments:
  1562. pCCB - A pointer to the code generation controller block.
  1563. Return Value:
  1564. CG_OK if all is well
  1565. error Otherwise.
  1566. Notes:
  1567. ----------------------------------------------------------------------------*/
  1568. {
  1569. ITERATOR ParamList;
  1570. CGSIDE Side;
  1571. CG_RETURN * pRT;
  1572. BOOL fReturnNeedsMarshall = FALSE;
  1573. pCCB->SetCodeGenPhase( CGPHASE_MARSHALL );
  1574. // Generate a call to tranform the data into the proper endianness.
  1575. S_XFormToProperFormat( pCCB );
  1576. // For all [in] params, generate the unmarshalling code.
  1577. if( (Side = pCCB->GetCodeGenSide()) == CGSIDE_CLIENT )
  1578. GetInParamList( ParamList );
  1579. else
  1580. GetOutParamList( ParamList );
  1581. if ( (Side == CGSIDE_SERVER) && (pRT = GetReturnType()) != 0 )
  1582. fReturnNeedsMarshall = TRUE;
  1583. if( ITERATOR_GETCOUNT( ParamList ) )
  1584. {
  1585. CG_PARAM * pParam;
  1586. CG_PARAM * pS;
  1587. ITERATOR_INIT( ParamList );
  1588. while( ITERATOR_GETNEXT( ParamList, pParam ) )
  1589. {
  1590. // IsExtraParam
  1591. pS = (CG_PARAM *)ITERATOR_PEEKTHIS( ParamList );
  1592. pParam->GenMarshall( pCCB );
  1593. }
  1594. }
  1595. // For the server side, generate the marshall call if there is a return
  1596. // value.
  1597. if( fReturnNeedsMarshall )
  1598. {
  1599. pRT->GenMarshall( pCCB );
  1600. }
  1601. return CG_OK;
  1602. }
  1603. CG_STATUS
  1604. CG_PROC::GenRefChecks(
  1605. CCB * pCCB )
  1606. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1607. Routine Description:
  1608. Generate ref checks for a procedure.
  1609. Arguments:
  1610. pCCB - The code gen block.
  1611. Return Value:
  1612. CG_OK
  1613. Notes:
  1614. ----------------------------------------------------------------------------*/
  1615. {
  1616. CG_ITERATOR ParamList;
  1617. CGSIDE Side;
  1618. // On the client side, perform ref checks for every pointer parameter.
  1619. // On the server side, dont perform any checks at all. If it is a top
  1620. // level ref, the stub allocates the pointee on the stack or in memory.
  1621. // if the allocation fails, the engine will always raise an exception.
  1622. // For embedded pointers, the engine checks anyhow.
  1623. //
  1624. // If the parameter is a cs tag (e.g. [cs_stag]), and the proc has
  1625. // a tag setting routine, the param will be allocated as a local variable
  1626. // so we don't need to check them.
  1627. if( (Side = pCCB->GetCodeGenSide()) == CGSIDE_CLIENT )
  1628. {
  1629. GetMembers( ParamList );
  1630. if( ITERATOR_GETCOUNT( ParamList ) )
  1631. {
  1632. CG_PARAM * pParam;
  1633. ITERATOR_INIT( ParamList );
  1634. while( ITERATOR_GETNEXT( ParamList, pParam ) )
  1635. {
  1636. if( ( pCCB->GetOptimOption() & OPTIMIZE_SIZE )
  1637. && ( NULL == GetCSTagRoutine() || !pParam->IsSomeCSTag() ) )
  1638. {
  1639. pParam->GenRefChecks( pCCB );
  1640. }
  1641. }
  1642. }
  1643. }
  1644. return CG_OK;
  1645. }
  1646. CG_STATUS
  1647. CG_PROC::S_GenInitInLocals(
  1648. CCB * pCCB )
  1649. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1650. Routine Description:
  1651. Generate in local initialization for the procedure.
  1652. Arguments:
  1653. pCCB - The code gen block.
  1654. Return Value:
  1655. CG_OK
  1656. Notes:
  1657. ----------------------------------------------------------------------------*/
  1658. {
  1659. ITERATOR ParamList;
  1660. GetInParamList( ParamList );
  1661. if( ITERATOR_GETCOUNT( ParamList ) )
  1662. {
  1663. CG_PARAM * pParam;
  1664. ITERATOR_INIT( ParamList );
  1665. while( ITERATOR_GETNEXT( ParamList, pParam ) )
  1666. {
  1667. pParam->S_GenInitInLocals( pCCB );
  1668. }
  1669. }
  1670. return CG_OK;
  1671. }
  1672. /***************************************************************************
  1673. * parameter code generation class implementation.
  1674. ***************************************************************************/
  1675. CG_STATUS
  1676. CG_PARAM::S_GenInitInLocals(
  1677. CCB * pCCB )
  1678. {
  1679. pCCB->SetMemoryAllocDone();
  1680. pCCB->ResetRefAllocDone();
  1681. pCCB->SetSourceExpression( GetResource() );
  1682. pCCB->SetLastPlaceholderClass(this);
  1683. ((CG_NDR *)GetChild())->S_GenInitInLocals( pCCB );
  1684. return CG_OK;
  1685. }
  1686. CG_STATUS
  1687. CG_PARAM::S_GenInitOutLocals(
  1688. CCB * pCCB )
  1689. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1690. Routine Description:
  1691. Generate local initialization for the parameters.
  1692. Arguments:
  1693. pCCB - A pointer to the code generation controller block.
  1694. Return Value:
  1695. CG_OK if all is well
  1696. error Otherwise.
  1697. Notes:
  1698. ----------------------------------------------------------------------------*/
  1699. {
  1700. if ( IsParamPartialIgnore() )
  1701. {
  1702. // Evaluate toplevel size_is. Ignore first_is and length_is since
  1703. // the entire data needs to be allocated and cleared.
  1704. GenNdrTopLevelAttributeSupport( pCCB, TRUE );
  1705. char *pParamName = GetResource()->GetResourceName();
  1706. long FormatOffset = dynamic_cast<CG_NDR*>(GetChild())->GetFormatStringOffset();
  1707. Out_PartialIgnoreServerInitialize( pCCB,
  1708. pParamName,
  1709. FormatOffset );
  1710. return CG_OK;
  1711. }
  1712. else if( IsParamOut() && !IsParamIn() )
  1713. {
  1714. pCCB->SetMemoryAllocDone();
  1715. pCCB->ResetRefAllocDone();
  1716. pCCB->SetSourceExpression( GetResource() );
  1717. pCCB->SetLastPlaceholderClass(this);
  1718. ((CG_NDR *)GetChild())->S_GenInitOutLocals( pCCB );
  1719. SetFinalExpression( GetResource() );
  1720. }
  1721. return CG_OK;
  1722. }
  1723. CG_STATUS
  1724. CG_PARAM::S_GenInitTopLevelStuff(
  1725. CCB * pCCB )
  1726. {
  1727. ISTREAM * pStream;
  1728. CG_NDR * pChild;
  1729. ID_CG ChildID;
  1730. pStream = pCCB->GetStream();
  1731. pChild = (CG_NDR *)GetChild();
  1732. ChildID = pChild->GetCGID();
  1733. if ( ChildID == ID_CG_GENERIC_HDL )
  1734. {
  1735. pChild = (CG_NDR *)pChild->GetChild();
  1736. ChildID = pChild->GetCGID();
  1737. }
  1738. //
  1739. // Initialize all [in] pointer and array params, and handle by-value
  1740. // structures and unions.
  1741. //
  1742. if ( pChild->IsArray() || pChild->IsSimpleType() )
  1743. {
  1744. expr_node * pParam;
  1745. expr_node * pExpr;
  1746. pParam = new expr_variable( GetResource()->GetResourceName() );
  1747. pExpr = new expr_assign( pParam,
  1748. new expr_constant( (long) 0 ) );
  1749. pStream->NewLine();
  1750. pExpr->Print( pStream );
  1751. pStream->Write( ';' );
  1752. }
  1753. if ( pChild->IsPointer() )
  1754. {
  1755. // const type* ptr or type* const ptr
  1756. // get initialized as (type*) ptr = 0;
  1757. expr_node* pParam;
  1758. expr_node* pExpr;
  1759. expr_node* pLHS;
  1760. pParam = new expr_variable( GetResource()->GetResourceName() );
  1761. node_skl* pType = GetChild()->GetType();
  1762. if ( pType != 0 && pType->NodeKind() != NODE_INTERFACE_REFERENCE )
  1763. {
  1764. expr_cast* pCast = new expr_cast( pType, pParam );
  1765. pCast->SetEmitModifiers( false );
  1766. pLHS = pCast;
  1767. }
  1768. else
  1769. {
  1770. pLHS = pParam;
  1771. }
  1772. pExpr = new expr_assign( pLHS, new expr_constant( (long) 0 ) );
  1773. pStream->NewLine();
  1774. pExpr->Print( pStream );
  1775. pStream->Write( ';' );
  1776. }
  1777. //
  1778. // If this is a by-value structure or union then we allocate a
  1779. // local which is a pointer to the same type.
  1780. //
  1781. if ( pChild->IsStruct() || pChild->IsUnion() ||
  1782. pChild->IsXmitRepOrUserMarshal() )
  1783. {
  1784. expr_node * pParam;
  1785. expr_node * pPointer;
  1786. expr_node * pExpr;
  1787. char * pPointerName;
  1788. char * pPlainName = GetResource()->GetResourceName();
  1789. pPointerName = new char[strlen( pPlainName ) + 10];
  1790. strcpy( pPointerName, LOCAL_NAME_POINTER_MANGLE);
  1791. strcat( pPointerName, pPlainName);
  1792. pParam = new expr_u_address (
  1793. new expr_variable( pPlainName ) );
  1794. pPointer = new expr_variable( pPointerName );
  1795. pExpr = new expr_assign( pPointer, pParam );
  1796. pStream->NewLine();
  1797. pExpr->Print( pStream );
  1798. pStream->Write( ';' );
  1799. //
  1800. // Memset [in], [in,out] by-value structs & unions in case we catch
  1801. // an exception before we finish unmarshalling them. If they have
  1802. // embedded pointers they must be zeroed before freeing.
  1803. //
  1804. if ( IsParamIn() &&
  1805. (pChild->IsStruct() || pChild->IsUnion()) )
  1806. {
  1807. Out_MemsetToZero( pCCB,
  1808. pPointer,
  1809. new expr_sizeof( pChild->GetType() ) );
  1810. }
  1811. // If there is a transmit_as etc, init the ptr to 0.
  1812. switch( ChildID )
  1813. {
  1814. case ID_CG_TRANSMIT_AS:
  1815. {
  1816. expr_proc_call * pProc = new expr_proc_call( MIDL_MEMSET_RTN_NAME );
  1817. pProc->SetParam( new expr_param( pPointer ) );
  1818. pProc->SetParam( new expr_param( new expr_constant( 0L ) ) );
  1819. pProc->SetParam(
  1820. new expr_param(
  1821. new expr_sizeof(
  1822. ((CG_TRANSMIT_AS *)pChild)->GetPresentedType())));
  1823. pCCB->GetStream()->NewLine();
  1824. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  1825. break;
  1826. }
  1827. case ID_CG_REPRESENT_AS:
  1828. {
  1829. node_skl * pNode = new node_def(
  1830. ((CG_REPRESENT_AS *)pChild)->GetRepAsTypeName() );
  1831. expr_proc_call * pProc = new expr_proc_call( MIDL_MEMSET_RTN_NAME );
  1832. pProc->SetParam( new expr_param( pPointer ) );
  1833. pProc->SetParam( new expr_param( new expr_constant( 0L ) ) );
  1834. pProc->SetParam( new expr_param( new expr_sizeof( pNode ) ) );
  1835. pCCB->GetStream()->NewLine();
  1836. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  1837. break;
  1838. }
  1839. case ID_CG_USER_MARSHAL:
  1840. {
  1841. node_skl * pNode = new node_def(
  1842. ((CG_REPRESENT_AS *)pChild)->GetRepAsTypeName() );
  1843. expr_proc_call * pProc = new expr_proc_call( MIDL_MEMSET_RTN_NAME );
  1844. pProc->SetParam( new expr_param( pPointer ) );
  1845. pProc->SetParam( new expr_param( new expr_constant( 0L ) ) );
  1846. pProc->SetParam( new expr_param( new expr_sizeof( pNode ) ) );
  1847. pCCB->GetStream()->NewLine();
  1848. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  1849. break;
  1850. }
  1851. default:
  1852. break;
  1853. }
  1854. }
  1855. if ( ChildID == ID_CG_PRIMITIVE_HDL )
  1856. {
  1857. pStream->NewLine();
  1858. pStream->Write( GetType()->GetSymName() );
  1859. pStream->Write( " = " PRPC_MESSAGE_VAR_NAME "->Handle;" );
  1860. }
  1861. return CG_OK;
  1862. }
  1863. CG_STATUS
  1864. CG_PARAM::GenMarshall(
  1865. CCB * pCCB )
  1866. {
  1867. CG_STATUS Status;
  1868. CG_NDR * pOldPlaceholder;
  1869. // The fault/comm additional parameter doesn't go on wire.
  1870. if ( IsExtraStatusParam() )
  1871. return CG_OK;
  1872. pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
  1873. GenNdrMarshallCall( pCCB );
  1874. Status = CG_OK;
  1875. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  1876. return CG_OK;
  1877. }
  1878. CG_STATUS
  1879. CG_PARAM::GenUnMarshall(
  1880. CCB * pCCB )
  1881. {
  1882. CG_STATUS Status;
  1883. CG_NDR * pOldPlaceholder;
  1884. CG_NDR * pC = (CG_NDR *)GetChild();
  1885. BOOL fPtrToContext = FALSE;
  1886. expr_node * pFinalExpr = GetResource();
  1887. // The fault/comm additional parameter doesn't go on wire...
  1888. // However, we need to generate an assignment in its place.
  1889. pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
  1890. if ( pC->GetCGID() == ID_CG_CONTEXT_HDL ||
  1891. ( (fPtrToContext = ( pC->GetChild()) != 0 && pC->GetChild()->GetCGID() == ID_CG_CONTEXT_HDL ) ) == TRUE )
  1892. {
  1893. expr_node * pExpr;
  1894. expr_proc_call * pProc = new expr_proc_call( "NDRSContextValue" );
  1895. CG_CONTEXT_HANDLE * pCtxtHandle;
  1896. pProc->SetParam( new expr_param( GetResource() ) );
  1897. if( fPtrToContext )
  1898. {
  1899. pExpr = new expr_u_deref( pProc );
  1900. pCtxtHandle = (CG_CONTEXT_HANDLE *)pC->GetChild();
  1901. }
  1902. else
  1903. {
  1904. pExpr = pProc;
  1905. pCtxtHandle = (CG_CONTEXT_HANDLE *)pC;
  1906. }
  1907. pExpr = new expr_cast( GetType()->GetChild(), pExpr );
  1908. pFinalExpr = pExpr;
  1909. // Register the context handle for a rundown.
  1910. if( pCtxtHandle->GetHandleType()->NodeKind() == NODE_DEF )
  1911. pCCB->RegisterContextHandleType( pCtxtHandle->GetHandleType() );
  1912. }
  1913. GenNdrUnmarshallCall( pCCB );
  1914. SetFinalExpression( pFinalExpr );
  1915. Status = CG_OK;
  1916. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  1917. return Status;
  1918. }
  1919. CG_STATUS
  1920. CG_PARAM::GenSizing(
  1921. CCB * pCCB )
  1922. {
  1923. CG_STATUS Status;
  1924. CG_NDR * pOldPlaceholder;
  1925. // The fault/comm additional parameter doesn't go on wire.
  1926. if ( IsExtraStatusParam() || IsAsyncHandleParam() )
  1927. return CG_OK;
  1928. pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
  1929. GenNdrBufferSizeCall( pCCB );
  1930. Status = CG_OK;
  1931. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  1932. return CG_OK;
  1933. }
  1934. CG_STATUS
  1935. CG_PARAM::GenFree(
  1936. CCB * pCCB )
  1937. {
  1938. CG_NDR * pOldPlaceholder;
  1939. if ( IsExtraStatusParam() )
  1940. return CG_OK;
  1941. pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
  1942. GenNdrFreeCall( pCCB );
  1943. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  1944. return CG_OK;
  1945. }
  1946. CG_STATUS
  1947. CG_PARAM::GenRefChecks(
  1948. CCB * pCCB )
  1949. {
  1950. pCCB->ResetEmbeddingLevel();
  1951. pCCB->ResetIndirectionLevel();
  1952. pCCB->ResetReturnContext();
  1953. pCCB->ResetRefAllocDone();
  1954. pCCB->SetPrefix(0);
  1955. pCCB->SetSourceExpression( GetResource() );
  1956. ((CG_NDR *)GetChild())->GenRefChecks( pCCB );
  1957. return CG_OK;
  1958. }
  1959. /*****************************************************************************
  1960. CG_RETURN procedures.
  1961. *****************************************************************************/
  1962. CG_STATUS
  1963. CG_RETURN::GenMarshall(
  1964. CCB * pCCB )
  1965. {
  1966. CG_NDR * pOldPlaceholder;
  1967. pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
  1968. GenNdrMarshallCall( pCCB );
  1969. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  1970. return CG_OK;
  1971. }
  1972. CG_STATUS
  1973. CG_RETURN::GenSizing(
  1974. CCB * pCCB )
  1975. {
  1976. CG_NDR * pOldPlaceholder;
  1977. pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
  1978. pCCB->SetSourceExpression( GetResource() );
  1979. GenNdrBufferSizeCall( pCCB );
  1980. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  1981. return CG_OK;
  1982. }
  1983. CG_STATUS
  1984. CG_RETURN::GenUnMarshall(
  1985. CCB * pCCB )
  1986. {
  1987. CG_NDR * pOldPlaceholder;
  1988. pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
  1989. ISTREAM * pStream;
  1990. pStream = pCCB->GetStream();
  1991. //
  1992. // Initialize a pointer return type to 0.
  1993. //
  1994. if ( GetChild()->IsPointer() )
  1995. {
  1996. pStream->NewLine();
  1997. pStream->Write( RETURN_VALUE_VAR_NAME );
  1998. pStream->Write( " = 0;" );
  1999. }
  2000. //
  2001. // Initialize a struct or union return value.
  2002. //
  2003. if ( GetChild()->IsStruct() || GetChild()->IsUnion() ||
  2004. ((CG_NDR *)GetChild())->IsXmitRepOrUserMarshal() )
  2005. {
  2006. pStream->NewLine();
  2007. pStream->Write( LOCAL_NAME_POINTER_MANGLE RETURN_VALUE_VAR_NAME );
  2008. pStream->Write( " = " );
  2009. pStream->Write( "(void *) &" RETURN_VALUE_VAR_NAME );
  2010. pStream->Write( ';' );
  2011. }
  2012. GenNdrUnmarshallCall( pCCB );
  2013. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  2014. return CG_OK;
  2015. }
  2016. CG_STATUS
  2017. CG_RETURN::S_GenInitOutLocals(
  2018. CCB * pCCB )
  2019. {
  2020. CG_NDR * pNdr;
  2021. pNdr = (CG_NDR *) GetChild();
  2022. //
  2023. // The only return type we ever have to initialize is a context handle.
  2024. // A pointer to a context handle as a return type is forbidden.
  2025. //
  2026. if ( pNdr->GetCGID() == ID_CG_CONTEXT_HDL )
  2027. {
  2028. pCCB->SetLastPlaceholderClass(this);
  2029. pNdr->S_GenInitOutLocals( pCCB );
  2030. }
  2031. return CG_OK;
  2032. }
  2033. CG_STATUS
  2034. CG_RETURN::S_GenInitTopLevelStuff(
  2035. CCB * pCCB )
  2036. {
  2037. CG_NDR * pChild;
  2038. expr_node * pExpr;
  2039. pChild = (CG_NDR *) GetChild();
  2040. pExpr = new expr_u_address (
  2041. new expr_variable( RETURN_VALUE_VAR_NAME ) );
  2042. if ( pChild->IsStruct() || pChild->IsUnion() )
  2043. {
  2044. Out_MemsetToZero( pCCB,
  2045. pExpr,
  2046. new expr_sizeof( pChild->GetType() ) );
  2047. }
  2048. return CG_OK;
  2049. }
  2050. CG_STATUS
  2051. CG_RETURN::GenFree(
  2052. CCB * pCCB )
  2053. {
  2054. CG_NDR * pOldPlaceholder;
  2055. pOldPlaceholder = pCCB->SetLastPlaceholderClass( this );
  2056. GenNdrFreeCall( pCCB );
  2057. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  2058. return CG_OK;
  2059. }
  2060. expr_node *
  2061. CG_RETURN::GetFinalExpression()
  2062. {
  2063. expr_node * pReturnExpr;
  2064. BOOL fPtrToContext = FALSE;
  2065. CG_NDR * pC = (CG_NDR *)GetChild();
  2066. if( pC->GetCGID() == ID_CG_CONTEXT_HDL ||
  2067. ( (fPtrToContext = ( pC->GetChild()) != 0 &&
  2068. pC->GetChild()->GetCGID() == ID_CG_CONTEXT_HDL ) ) == TRUE )
  2069. {
  2070. expr_node * pExpr;
  2071. expr_proc_call * pProc = new expr_proc_call( "NDRSContextValue" );
  2072. pProc->SetParam( new expr_param( GetResource() ) );
  2073. // cast the proc call to this type.
  2074. pExpr = MakeDerefExpressionOfCastPtrToType( GetType(), pProc );
  2075. pReturnExpr = pExpr;
  2076. }
  2077. else
  2078. pReturnExpr = GetResource();
  2079. return pReturnExpr;
  2080. }
  2081. CG_STATUS
  2082. CG_CALLBACK_PROC::GenClientStub( CCB * pCCB )
  2083. {
  2084. CGSIDE Side = pCCB->GetCodeGenSide();
  2085. pCCB->GetInterfaceCG()->SetDispatchTBLPtrForCallback();
  2086. pCCB->SetInCallback();
  2087. CG_PROC::GenServerStub( pCCB );
  2088. pCCB->ClearInCallback();
  2089. pCCB->GetInterfaceCG()->RestoreDispatchTBLPtr();
  2090. pCCB->SetCodeGenSide( Side );
  2091. return CG_OK;
  2092. }
  2093. CG_STATUS
  2094. CG_CALLBACK_PROC::GenServerStub( CCB * pCCB )
  2095. {
  2096. CGSIDE Side = pCCB->GetCodeGenSide();
  2097. pCCB->GetInterfaceCG()->SetDispatchTBLPtrForCallback();
  2098. pCCB->SetInCallback();
  2099. CG_PROC::GenClientStub( pCCB );
  2100. pCCB->ClearInCallback();
  2101. pCCB->GetInterfaceCG()->RestoreDispatchTBLPtr();
  2102. pCCB->SetCodeGenSide( Side );
  2103. return CG_OK;
  2104. }
  2105. void
  2106. CG_PROC::GetCorrectAllocFreeRoutines(
  2107. CCB * pCCB,
  2108. BOOL fServer,
  2109. char ** ppAllocName,
  2110. char ** ppFreeName )
  2111. /*++
  2112. Finds out correct Alloc and Free routine names, depending on the mode
  2113. (osf vs. msft) and need to enable memory management.
  2114. In object mode:
  2115. use NdrOleAllocate, NdrOleFree
  2116. In ms_ext mode and c-ext:
  2117. unless forced to enable allocate, use MIDL_user_*
  2118. In osf mode:
  2119. client always uses NdrRpcSsClient*
  2120. server use a default allocator or RpcSsAllocate.
  2121. ++*/
  2122. {
  2123. *ppAllocName = (char *) DEFAULT_ALLOC_RTN_NAME; // MIDL_user_allocate
  2124. *ppFreeName = (char *) DEFAULT_FREE_RTN_NAME; // MIDL_user_free
  2125. if ( IsObject() )
  2126. {
  2127. *ppAllocName = (char *) OLE_ALLOC_RTN_NAME; // NdrOleAllocate
  2128. *ppFreeName = (char *) OLE_FREE_RTN_NAME; // NdrOleFree
  2129. }
  2130. else if ( MustInvokeRpcSSAllocate() )
  2131. {
  2132. // This means: msft mode - only when forced to enable
  2133. // osf mode - when there is a need or forced to.
  2134. if ( fServer )
  2135. {
  2136. *ppAllocName = (char *) RPC_SS_SERVER_ALLOCATE_RTN_NAME;
  2137. *ppFreeName = (char *) RPC_SS_SERVER_FREE_RTN_NAME;
  2138. }
  2139. else
  2140. {
  2141. *ppAllocName = (char *) RPC_SM_CLIENT_ALLOCATE_RTN_NAME;
  2142. *ppFreeName = (char *) RPC_SM_CLIENT_FREE_RTN_NAME;
  2143. }
  2144. }
  2145. else
  2146. if ( pCCB->GetMode() == 0 )
  2147. {
  2148. // osf, without having to enable memory manager
  2149. if ( fServer )
  2150. {
  2151. *ppAllocName = (char *) DEFAULT_ALLOC_OSF_RTN_NAME;
  2152. *ppFreeName = (char *) DEFAULT_FREE_OSF_RTN_NAME;
  2153. }
  2154. else
  2155. {
  2156. *ppAllocName = (char *) RPC_SM_CLIENT_ALLOCATE_RTN_NAME;
  2157. *ppFreeName = (char *) RPC_SM_CLIENT_FREE_RTN_NAME;
  2158. }
  2159. }
  2160. }
  2161. void
  2162. GenCorrInit (
  2163. CCB* pCCB
  2164. )
  2165. {
  2166. ISTREAM* pStream = pCCB->GetStream();
  2167. ITERATOR ParamList;
  2168. // _StubMsg
  2169. expr_node* pExpr = pCCB->GetStandardResource( ST_RES_STUB_MESSAGE_VARIABLE );
  2170. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  2171. pExpr = MakeExpressionOfCastToTypeName( PSTUB_MESSAGE_TYPE_NAME, pExpr );
  2172. ITERATOR_INSERT( ParamList, pExpr );
  2173. // _Cache
  2174. pExpr = pCCB->GetLocalResource( NDR_CORR_CACHE_VAR_NAME );
  2175. ITERATOR_INSERT( ParamList, pExpr );
  2176. // _CacheSize
  2177. unsigned long ulSize = NDR_CORR_CACHE_SIZE * sizeof( unsigned long );
  2178. pExpr = new expr_constant( ulSize );
  2179. ITERATOR_INSERT( ParamList, pExpr );
  2180. // _Flags
  2181. pExpr = new expr_constant( unsigned long( 0 ) );
  2182. ITERATOR_INSERT( ParamList, pExpr );
  2183. expr_proc_call* pProcCall = MakeProcCallOutOfParamExprList (
  2184. CSTUB_CORR_INIT_RTN_NAME,
  2185. 0,
  2186. ParamList
  2187. );
  2188. pStream->NewLine();
  2189. pProcCall->PrintCall( pStream, 0, 0 );
  2190. pStream->NewLine();
  2191. }
  2192. void
  2193. GenCorrPassFree (
  2194. CCB* pCCB,
  2195. char* szRtn
  2196. )
  2197. {
  2198. ISTREAM* pStream = pCCB->GetStream();
  2199. expr_node* pExpr = pCCB->GetStandardResource( ST_RES_STUB_MESSAGE_VARIABLE );
  2200. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  2201. pExpr = MakeExpressionOfCastToTypeName( PSTUB_MESSAGE_TYPE_NAME, pExpr );
  2202. ITERATOR ParamList;
  2203. ITERATOR_INSERT( ParamList, pExpr );
  2204. expr_proc_call* pProcCall = MakeProcCallOutOfParamExprList (
  2205. szRtn,
  2206. 0,
  2207. ParamList
  2208. );
  2209. pStream->NewLine();
  2210. pProcCall->PrintCall( pStream, 0, 0 );
  2211. pStream->NewLine();
  2212. }