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

3388 lines
98 KiB

  1. /*---------------------------------------------------------------------------
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name:
  4. procndr.hxx
  5. Abstract:
  6. Contains routines for the generation of the new NDR format strings for
  7. the code generation procedure class.
  8. Notes:
  9. History:
  10. DKays Oct-1993 Created.
  11. ----------------------------------------------------------------------------*/
  12. #include "becls.hxx"
  13. #pragma hdrstop
  14. #include "szbuffer.h"
  15. #include "walkctxt.hxx"
  16. #include <malloc.h>
  17. extern CMD_ARG * pCommand;
  18. void
  19. CG_PROC::GenNdrFormat( CCB * pCCB )
  20. /*++
  21. Routine Description :
  22. Interpreted procedure format string descriptions.
  23. Arguments :
  24. pCCB - pointer to the code control block
  25. --*/
  26. {
  27. CG_ITERATOR Iterator;
  28. CG_PARAM * pParam;
  29. FORMAT_STRING * pProcFormatString;
  30. CG_NDR * pOldCGNodeContext;
  31. short ParamNum;
  32. long ServerBufferSize;
  33. long ClientBufferSize;
  34. long BufSize;
  35. BOOL fServerMustSize;
  36. BOOL fClientMustSize;
  37. INTERPRETER_OPT_FLAGS InterpreterOptFlags;
  38. MIDL_ASSERT( !pCommand->IsNDR64Run() );
  39. // make sure that call-as proc targets get processed when necessary.
  40. CG_PROC * pCallAs = GetCallAsCG();
  41. if (pCallAs)
  42. pCallAs->GenNdrFormat(pCCB);
  43. SetupFormatStrings(pCCB);
  44. if ( ! (GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2) )
  45. {
  46. // Generate -Os or -Oi format string.
  47. GenNdrFormatV1( pCCB );
  48. UnsetupFormatStrings(pCCB);
  49. return;
  50. }
  51. if ( GetFormatStringOffset() != -1 )
  52. {
  53. UnsetupFormatStrings(pCCB);
  54. return;
  55. }
  56. pCCB->SetInObjectInterface( IsObject() );
  57. pOldCGNodeContext = pCCB->SetCGNodeContext( this );
  58. //
  59. // If this procedure uses an explicit handle then set the
  60. // NdrBindDescriptionOffset to 0 so that it will not try to output it's
  61. // description when given the GenNdrParamOffLine method in the loop below.
  62. // It's description must be part of the procedure description.
  63. //
  64. if ( GetHandleUsage() == HU_EXPLICIT )
  65. {
  66. CG_HANDLE * pHandle = GetHandleClassPtr();
  67. pHandle->SetNdrBindDescriptionOffset( 0 );
  68. if ( pHandle->GetCGID() == ID_CG_CONTEXT_HDL )
  69. {
  70. // The context handle directs the call.
  71. ((CG_CONTEXT_HANDLE *)pHandle)->SetCannotBeNull();
  72. }
  73. }
  74. GetMembers( Iterator );
  75. ParamNum = 0;
  76. ServerBufferSize = 0;
  77. ClientBufferSize = 0;
  78. fServerMustSize = FALSE;
  79. fClientMustSize = FALSE;
  80. pCCB->SetInterpreterOutSize( 0 );
  81. //
  82. // Generate the offline portion of the format string for all of the params.
  83. //
  84. while( ITERATOR_GETNEXT( Iterator, pParam ) )
  85. {
  86. CG_NDR * pChild;
  87. CG_NDR * pOldPlaceholder;
  88. pChild = (CG_NDR *) pParam->GetChild();
  89. // Ignore the following type of arguments that don't go on wire:
  90. // - async handles
  91. // - primitive handles
  92. //
  93. if ( pChild->GetCGID() == ID_CG_PRIMITIVE_HDL || ( (CG_PARAM*) pParam)->IsAsyncHandleParam() )
  94. continue;
  95. pParam->SetParamNumber( ParamNum++ );
  96. pCCB->SetCurrentParam( (CG_PARAM *) pParam );
  97. pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
  98. pChild->GenNdrParamOffline( pCCB );
  99. // A procedure's buffer size does not depend on pipe arguments
  100. if (pChild->IsPipeOrPipeReference())
  101. {
  102. if (pChild->GetChild()->HasAFixedBufferSize())
  103. pParam->SetInterpreterMustSize(FALSE);
  104. else
  105. // There must be a union in there somewhere
  106. pParam->SetInterpreterMustSize(TRUE);
  107. }
  108. else
  109. {
  110. BufSize = pChild->FixedBufferSize( pCCB );
  111. if ( BufSize != -1 )
  112. {
  113. //
  114. // If either the client's or server's fixed buffer size gets too
  115. // big then we force the parameter to be sized.
  116. //
  117. if ( (pParam->IsParamIn() &&
  118. ((ClientBufferSize + BufSize) >= 65356)) ||
  119. (pParam->IsParamOut() &&
  120. ((ServerBufferSize + BufSize) >= 65356)) )
  121. {
  122. fClientMustSize = TRUE;
  123. fServerMustSize = TRUE;
  124. }
  125. else
  126. {
  127. pParam->SetInterpreterMustSize( FALSE );
  128. if ( pParam->IsParamIn() )
  129. ClientBufferSize += BufSize;
  130. if ( pParam->IsParamOut() )
  131. ServerBufferSize += BufSize;
  132. }
  133. }
  134. else
  135. {
  136. if ( pParam->IsParamIn() )
  137. fClientMustSize = TRUE;
  138. if ( pParam->IsParamOut() )
  139. fServerMustSize = TRUE;
  140. }
  141. }
  142. pCCB->SetCurrentParam( 0 );
  143. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  144. }
  145. //
  146. // Generate the format string for the return type if needed.
  147. //
  148. if ( GetReturnType() )
  149. {
  150. CG_NDR * pChild;
  151. CG_NDR * pOldPlaceholder;
  152. GetReturnType()->SetParamNumber( ParamNum++ );
  153. pChild = (CG_NDR *) GetReturnType()->GetChild();
  154. pCCB->SetCurrentParam( GetReturnType() );
  155. pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetReturnType() );
  156. pChild->GenNdrParamOffline( pCCB );
  157. BufSize = pChild->FixedBufferSize( pCCB );
  158. if ( BufSize != -1 )
  159. {
  160. if ( (ServerBufferSize + BufSize) >= 65536 )
  161. {
  162. fServerMustSize = TRUE;
  163. }
  164. else
  165. {
  166. ServerBufferSize += BufSize;
  167. GetReturnType()->SetInterpreterMustSize( FALSE );
  168. }
  169. }
  170. else
  171. fServerMustSize = TRUE;
  172. pCCB->SetCurrentParam( 0 );
  173. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  174. }
  175. pCCB->SetCurrentParam( 0 );
  176. pProcFormatString = pCCB->GetProcFormatString();
  177. SetFormatStringOffset( pProcFormatString->GetCurrentOffset() );
  178. //
  179. // Generate procedure description stuff for the interpreter if needed.
  180. //
  181. if ( (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER)
  182. || HasAPicklingAttribute() )
  183. {
  184. GenNdrFormatProcInfo( pCCB );
  185. // Client side constant buffer size.
  186. pProcFormatString->PushShort( ClientBufferSize );
  187. // Server side constant buffer size.
  188. pProcFormatString->PushShort( ServerBufferSize );
  189. }
  190. InterpreterOptFlags.ServerMustSize = (unsigned char) fServerMustSize;
  191. InterpreterOptFlags.ClientMustSize = (unsigned char) fClientMustSize;
  192. InterpreterOptFlags.HasReturn = (unsigned char) (GetReturnType() != 0 ? 1 : 0);
  193. InterpreterOptFlags.HasPipes = (unsigned char) HasPipes();
  194. InterpreterOptFlags.Unused = (unsigned char) 0;
  195. InterpreterOptFlags.HasAsyncUuid = (unsigned char) HasAsyncUUID();
  196. InterpreterOptFlags.HasAsyncHandle = (unsigned char) HasAsyncHandle();
  197. InterpreterOptFlags.HasExtensions = (unsigned char)
  198. ( HasDeny()
  199. || HasNotify()
  200. || HasNotifyFlag()
  201. || HasComplexReturnType() );
  202. short floatmask = 0;
  203. if ( pCommand->Is64BitEnv() )
  204. {
  205. floatmask = GetFloatArgMask( pCCB );
  206. InterpreterOptFlags.HasExtensions = (unsigned char)
  207. InterpreterOptFlags.HasExtensions || (0 != floatmask);
  208. }
  209. // New procedure flags.
  210. pProcFormatString->PushOi2ProcFlagsByte( *((char *)&InterpreterOptFlags) );
  211. // Number of parameters.
  212. pProcFormatString->PushByte( ParamNum );
  213. if ( InterpreterOptFlags.HasExtensions )
  214. {
  215. // Extensions layout:
  216. // size<1>
  217. // flags<1>
  218. // client correlation cache size hint<2>
  219. // server correlation cache size hint<2>
  220. // notify routine index<2>
  221. //
  222. INTERPRETER_OPT_FLAGS2 InterpreterOptFlags2;
  223. InterpreterOptFlags2.Unused = 0;
  224. InterpreterOptFlags2.HasNewCorrDesc = ( unsigned char )HasDeny();
  225. if ( InterpreterOptFlags2.HasNewCorrDesc )
  226. {
  227. InterpreterOptFlags2.ClientCorrCheck = ( unsigned char )HasClientCorr();
  228. InterpreterOptFlags2.ServerCorrCheck = ( unsigned char )HasServerCorr();
  229. }
  230. else
  231. {
  232. InterpreterOptFlags2.ClientCorrCheck = 0;
  233. InterpreterOptFlags2.ServerCorrCheck = 0;
  234. }
  235. InterpreterOptFlags2.HasNotify = ( unsigned char )HasNotify();
  236. InterpreterOptFlags2.HasNotify2 = ( unsigned char )HasNotifyFlag();
  237. InterpreterOptFlags2.HasComplexReturn = ( unsigned char )HasComplexReturnType();
  238. if ( pCommand->Is64BitEnv() )
  239. {
  240. pProcFormatString->PushByte( sizeof(NDR_PROC_HEADER_EXTS64) );
  241. }
  242. else
  243. {
  244. pProcFormatString->PushByte( sizeof(NDR_PROC_HEADER_EXTS) );
  245. }
  246. pProcFormatString->PushExtProcFlagsByte( *((char *)&InterpreterOptFlags2) );
  247. node_proc* pProcThis = (node_proc*) GetType();
  248. pProcFormatString->PushShort( short( pProcThis->GetClientCorrelationCount() ) ); // client
  249. pProcFormatString->PushShort( short( pProcThis->GetServerCorrelationCount() ) ); //server
  250. #ifdef PRINT_METRICS
  251. printf (
  252. "Client hint is %16d, Server hint is %16d, for %s\n",
  253. pProcThis->GetClientCorrelationCount(),
  254. pProcThis->GetServerCorrelationCount(),
  255. pProcThis->GetSymName()
  256. );
  257. #endif
  258. if( HasNotify() || HasNotifyFlag() )
  259. GetNotifyTableOffset( pCCB );
  260. pProcFormatString->PushShort( (short)uNotifyTableOffset ); // notify index
  261. if ( pCommand->Is64BitEnv() )
  262. {
  263. pProcFormatString->PushShort( floatmask );
  264. }
  265. }
  266. SetFormatStringParamStart( pProcFormatString->GetCurrentOffset() );
  267. pCCB->SetInterpreterOutSize( 0 );
  268. ITERATOR_INIT( Iterator );
  269. //
  270. // Now generate the param info at the end of the format string.
  271. //
  272. while( ITERATOR_GETNEXT( Iterator, pParam ) )
  273. {
  274. CG_NDR * pChild;
  275. CG_NDR * pOldPlaceholder;
  276. if (pParam->IsAsyncHandleParam())
  277. continue;
  278. pChild = (CG_NDR *) pParam->GetChild();
  279. if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
  280. pChild = (CG_NDR *) pChild->GetChild();
  281. pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
  282. pChild->GenNdrParamDescription( pCCB );
  283. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  284. }
  285. if ( GetReturnType() )
  286. {
  287. CG_NDR * pChild;
  288. CG_NDR * pOldPlaceholder;
  289. pChild = (CG_NDR *) GetReturnType()->GetChild();
  290. if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
  291. pChild = (CG_NDR *) pChild->GetChild();
  292. pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetReturnType() );
  293. pChild->GenNdrParamDescription( pCCB );
  294. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  295. }
  296. pCCB->SetCGNodeContext( pOldCGNodeContext );
  297. pCCB->SetInObjectInterface( FALSE );
  298. SetFormatStringEndOffset( pProcFormatString->GetCurrentOffset() );
  299. // save delta, in case the routine is optimized
  300. short usParamStartDelta = (short) ( GetFormatStringParamStart() -
  301. GetFormatStringOffset() );
  302. pProcFormatString->OptimizeFragment( this );
  303. // Set param start!!!
  304. SetFormatStringParamStart( GetFormatStringOffset() + usParamStartDelta );
  305. //
  306. // For interpreted procs we add some comments to the procedure format
  307. // strings to make the stubs easier to read.
  308. //
  309. if ( ! (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER) )
  310. return;
  311. char * pComment;
  312. long FormatOffset;
  313. short Bytes;
  314. Bytes = short(32 + strlen( GetSymName() ) );
  315. pComment = new char[Bytes];
  316. sprintf( pComment, "\n\t/* Procedure %s */\n\n", GetSymName() );
  317. pProcFormatString->AddComment( GetFormatStringOffset(), pComment );
  318. GetMembers( Iterator );
  319. FormatOffset = GetFormatStringParamStart();
  320. while( ITERATOR_GETNEXT( Iterator, pParam ) )
  321. {
  322. if ( pParam->GetCGID() == ID_CG_PRIMITIVE_HDL || pParam->IsAsyncHandleParam() )
  323. continue;
  324. Bytes = short( 32 + strlen( pParam->GetSymName() ) );
  325. pComment = new char[Bytes];
  326. sprintf( pComment,
  327. "\n\t/* Parameter %s */\n\n",
  328. pParam->GetSymName() );
  329. pProcFormatString->AddComment( FormatOffset, pComment );
  330. FormatOffset += 6;
  331. }
  332. if ( GetReturnType() )
  333. {
  334. pProcFormatString->AddComment(
  335. FormatOffset, "\n\t/* Return value */\n\n" );
  336. }
  337. UnsetupFormatStrings(pCCB);
  338. }
  339. void
  340. CG_PROC::GenNdrFormatProcInfo( CCB * pCCB )
  341. /*++
  342. The layout is:
  343. handle type<1>
  344. Oi and pickling flags <1>
  345. [ rpc flags<4> ]
  346. proc num <2>
  347. stack size<2>
  348. [ explicit handle description <> ]
  349. [ notify table offset<2> ]
  350. --*/
  351. {
  352. FORMAT_STRING * pProcFormatString;
  353. SetupFormatStrings(pCCB);
  354. pProcFormatString = pCCB->GetProcFormatString();
  355. if ( IsObject() )
  356. {
  357. pProcFormatString->PushFormatChar( FC_AUTO_HANDLE );
  358. }
  359. else
  360. {
  361. if ( pCCB->IsInCallback() )
  362. {
  363. pProcFormatString->PushFormatChar( FC_CALLBACK_HANDLE );
  364. }
  365. else
  366. {
  367. if ( GetHandleUsage() == HU_IMPLICIT )
  368. {
  369. //
  370. // Implicit handle type.
  371. //
  372. if ( IsAutoHandle() )
  373. pProcFormatString->PushFormatChar( FC_AUTO_HANDLE );
  374. if ( IsPrimitiveHandle() )
  375. pProcFormatString->PushFormatChar( FC_BIND_PRIMITIVE );
  376. if ( IsGenericHandle() )
  377. {
  378. pProcFormatString->PushFormatChar( FC_BIND_GENERIC );
  379. // implicit generic handle needs to be registered.
  380. pCCB->RegisterGenericHandleType(
  381. GetHandleClassPtr()->GetHandleType() );
  382. }
  383. }
  384. else
  385. pProcFormatString->PushByte( 0 );
  386. }
  387. }
  388. unsigned char OiFlags = 0;
  389. // Indicate if there is a need to init the full ptr or rpcss packages.
  390. if ( HasFullPtr() )
  391. OiFlags |= Oi_FULL_PTR_USED;
  392. if ( MustInvokeRpcSSAllocate() )
  393. OiFlags |= Oi_RPCSS_ALLOC_USED;
  394. if ( IsObject() )
  395. {
  396. OiFlags |= Oi_OBJECT_PROC;
  397. if ( !ReturnsHRESULT() )
  398. OiFlags |= Oi_IGNORE_OBJECT_EXCEPTION_HANDLING;
  399. if ( (GetOptimizationFlags() & OPTIMIZE_INTERPRETER) &&
  400. (GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2) )
  401. OiFlags |= Oi_OBJ_USE_V2_INTERPRETER;
  402. }
  403. OiFlags |= Oi_HAS_RPCFLAGS;
  404. if ( GetCGID() == ID_CG_ENCODE_PROC )
  405. {
  406. if ( HasEncode() )
  407. OiFlags |= ENCODE_IS_USED;
  408. if ( HasDecode() )
  409. OiFlags |= DECODE_IS_USED;
  410. // The Oi_USE_NEW_INIT_ROUTINES and PICKLING_HAS_COMM_OR_FAULT flags
  411. // are overloaded. In -Oicf mode, the new routines are always used
  412. // and the bit specifics comm/fault options (which overriden also).
  413. // In pre-Oicf comm/fault is not supported.
  414. if ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 )
  415. {
  416. if ( HasStatuses() )
  417. OiFlags |= PICKLING_HAS_COMM_OR_FAULT;
  418. }
  419. else
  420. {
  421. OiFlags |= Oi_USE_NEW_INIT_ROUTINES;
  422. }
  423. }
  424. else
  425. {
  426. // Always do this.
  427. OiFlags |= Oi_USE_NEW_INIT_ROUTINES;
  428. if ( HasStatuses() )
  429. OiFlags |= Oi_HAS_COMM_OR_FAULT;
  430. }
  431. pProcFormatString->PushOldProcFlagsByte( OiFlags );
  432. pProcFormatString->PushLong( (long) TranslateOpBitsIntoUnsignedInt() );
  433. // Proc num.
  434. pProcFormatString->PushShort( (short) GetProcNum() );
  435. long Size = GetTotalStackSize( pCCB );
  436. //
  437. // Use a push ushort offset or size method which outputs a #ifdef for
  438. // the various platforms, for which stack offsets are often different.
  439. //
  440. pProcFormatString->PushUShortStackOffsetOrSize( Size );
  441. //
  442. // Output explicit handle description.
  443. //
  444. if ( GetHandleUsage() == HU_EXPLICIT && !IsObject() )
  445. {
  446. CG_NDR * pOldPlaceholder;
  447. CG_HANDLE * pHandle;
  448. pHandle = GetHandleClassPtr();
  449. pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetHandleUsagePtr() );
  450. pHandle->GenNdrHandleFormat( pCCB );
  451. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  452. //
  453. // Patch up a pointer to context handle's offset<2> field.
  454. //
  455. if ( pHandle->GetCGID() == ID_CG_CONTEXT_HDL )
  456. {
  457. CG_NDR * pNdr;
  458. CG_NDR * pPointer;
  459. // Get the handle param's first child node.
  460. pNdr = (CG_NDR *) GetHandleUsagePtr()->GetChild();
  461. pPointer = 0;
  462. while ( pNdr->IsPointer() )
  463. {
  464. pPointer = pNdr;
  465. pNdr = (CG_NDR *) GetChild();
  466. }
  467. if ( pPointer )
  468. {
  469. long OffsetField;
  470. OffsetField = pPointer->GetFormatStringOffset() + 2;
  471. pCCB->GetFormatString()->PushShortOffset(
  472. pHandle->GetFormatStringOffset() - OffsetField,
  473. OffsetField );
  474. }
  475. }
  476. }
  477. UnsetupFormatStrings(pCCB);
  478. }
  479. //
  480. // ##########################################################################
  481. // ----- Interpreted client stub generation. -----###########################
  482. // ##########################################################################
  483. //
  484. void
  485. CG_PROC::GenNdrSingleClientCall( CCB * pCCB )
  486. /*++
  487. Routine Description :
  488. This is the top level routine for generating code for the single NDR call
  489. case on the client side.
  490. Arguments :
  491. pCCB - pointer to the code control block
  492. --*/
  493. {
  494. ISTREAM * pStream;
  495. CG_ITERATOR Iterator;
  496. expr_node * pFinalExpr;
  497. CG_PARAM * pLastParam;
  498. bool fIsErrorStatus = false;
  499. pStream = pCCB->GetStream();
  500. // Generate the format string.
  501. if ( pCommand->IsNDRRun() )
  502. {
  503. GenNdrFormat( pCCB );
  504. }
  505. else
  506. {
  507. pCCB->GetNdr64Format()->Generate( this );
  508. }
  509. if ( GetReturnType() || HasComplexReturnType() )
  510. {
  511. if ( HasAsyncHandle() )
  512. {
  513. if ( !HasComplexReturnType()
  514. && GetReturnType()->GetChild()->GetCGID() != ID_CG_CONTEXT_HDL )
  515. {
  516. fIsErrorStatus = GetReturnType()->GetChild()->GetCGID() == ID_CG_ERROR_STATUS_T;
  517. }
  518. if ( fIsErrorStatus || GetCGID() == ID_CG_OBJECT_PROC )
  519. {
  520. pStream->Write( "CLIENT_CALL_RETURN " RETURN_VALUE_VAR_NAME );
  521. pStream->Write( " = {0};" );
  522. pStream->NewLine( 2 );
  523. }
  524. }
  525. else
  526. {
  527. if ( HasComplexReturnType() )
  528. {
  529. ( (node_proc *) GetType() )
  530. ->GetReturnType()->PrintType(PRT_DECL, pStream);
  531. }
  532. else
  533. pStream->Write( "CLIENT_CALL_RETURN " );
  534. pStream->Write( RETURN_VALUE_VAR_NAME );
  535. pStream->Write( ';' );
  536. pStream->NewLine( 2 );
  537. }
  538. }
  539. GetMembers(Iterator);
  540. pLastParam = 0;
  541. while ( ITERATOR_GETNEXT( Iterator, pLastParam ) )
  542. ;
  543. // If we have a complex return type the "last parameter" is actually the
  544. // return value so we need the one before that.
  545. if ( pLastParam && HasComplexReturnType() )
  546. {
  547. CG_PARAM *pPrevLastParam = NULL;
  548. ITERATOR_INIT( Iterator );
  549. while ( ITERATOR_GETNEXT( Iterator, pPrevLastParam ) )
  550. if ( pPrevLastParam->GetSibling() == pLastParam )
  551. break;
  552. pLastParam = pPrevLastParam;
  553. }
  554. // Now emit code for x86 or ia64.
  555. if ( pCommand->Is64BitEnv() )
  556. {
  557. // Emit code for IA64 platform
  558. pFinalExpr = GenCoreNdrSingleClientCall( pCCB, PROC_PLATFORM_IA64) ;
  559. }
  560. else
  561. {
  562. // x86
  563. pFinalExpr = GenCoreNdrSingleClientCall( pCCB, PROC_PLATFORM_X86 );
  564. }
  565. pFinalExpr->PrintCall( pStream, 0, 0 );
  566. pStream->NewLine();
  567. if ( GetReturnType() || HasComplexReturnType() )
  568. {
  569. if ( HasAsyncHandle() )
  570. {
  571. if ( !fIsErrorStatus && GetCGID() != ID_CG_OBJECT_PROC )
  572. {
  573. return;
  574. }
  575. }
  576. pStream->Write("return ");
  577. //
  578. // Complex return types
  579. //
  580. if ( HasComplexReturnType() )
  581. {
  582. pStream->Write( RETURN_VALUE_VAR_NAME ";" );
  583. pStream->NewLine();
  584. return;
  585. }
  586. CG_NDR* pNdr = (CG_NDR *) GetReturnType()->GetChild();
  587. node_skl* pType = GetReturnType()->GetType();
  588. //
  589. // Base type return value.
  590. //
  591. if ( pNdr->IsSimpleType() )
  592. {
  593. switch ( ((CG_BASETYPE *)pNdr)->GetFormatChar() )
  594. {
  595. case FC_FLOAT :
  596. pType->PrintType( PRT_CAST_TO_TYPE, pStream );
  597. pStream->Write( RETURN_VALUE_VAR_NAME ".Float;" );
  598. break;
  599. case FC_DOUBLE :
  600. pType->PrintType( PRT_CAST_TO_TYPE, pStream );
  601. pStream->Write( RETURN_VALUE_VAR_NAME ".Double;" );
  602. break;
  603. default :
  604. pType->PrintType( PRT_CAST_TO_TYPE, pStream );
  605. pStream->Write( RETURN_VALUE_VAR_NAME ".Simple;" );
  606. break;
  607. }
  608. pStream->NewLine();
  609. return;
  610. }
  611. //
  612. // A by-value struct or union.
  613. //
  614. if ( pNdr->IsStruct() || pNdr->IsUnion() )
  615. {
  616. expr_node * pExpr;
  617. pExpr = new expr_variable( RETURN_VALUE_VAR_NAME ".Pointer" );
  618. pExpr = MakeDerefExpressionOfCastPtrToType( pType, pExpr );
  619. pExpr->Print( pStream );
  620. pStream->Write( ';' );
  621. pStream->NewLine();
  622. return;
  623. }
  624. //
  625. // Otherwise pointer or array.
  626. //
  627. pType->PrintType( PRT_CAST_TO_TYPE, pStream );
  628. pStream->Write( RETURN_VALUE_VAR_NAME ".Pointer;" );
  629. pStream->NewLine();
  630. }
  631. }
  632. //
  633. // ##########################################################################
  634. // ----- Interpreted server stub generation. -----###########################
  635. // ##########################################################################
  636. //
  637. void
  638. CG_PROC::GenNdrSingleServerCall( CCB * pCCB )
  639. /*++
  640. Routine Description :
  641. This is the top level routine for generating code for the single NDR call
  642. case on the server side. It actually ends up being 3 calls.
  643. Arguments :
  644. pCCB - pointer to the code control block
  645. --*/
  646. {
  647. ISTREAM * pStream;
  648. // CG_PARAM * pParam;
  649. expr_proc_call * pCallExpr;
  650. char FormatStringExpr[80];
  651. //
  652. // On the server side we just use the format string that was generated
  653. // during client stub generation if such generation occured.
  654. //
  655. if ( pCommand->IsNDRRun() )
  656. {
  657. if ( GetFormatStringOffset() == -1 )
  658. GenNdrFormat( pCCB );
  659. }
  660. else
  661. {
  662. pCCB->GetNdr64Format()->Generate( this );
  663. }
  664. pCCB->SetCGNodeContext( this );
  665. pStream = pCCB->GetStream();
  666. //
  667. // Output the server stub locals. There are two locals : the stub
  668. // descriptor and the param struct.
  669. //
  670. GenNdrInterpretedServerLocals( pCCB );
  671. pStream->NewLine();
  672. //
  673. // Make the single unmarshall call.
  674. //
  675. pCallExpr = new expr_proc_call( S_NDR_UNMARSHALL_RTN_NAME );
  676. // Rpc message.
  677. pCallExpr->SetParam( new expr_param(
  678. new expr_variable( PRPC_MESSAGE_VAR_NAME ) ) );
  679. // Stub message.
  680. pCallExpr->SetParam( new expr_param(
  681. new expr_u_address (
  682. new expr_variable( STUB_MESSAGE_VAR_NAME ) ) ) );
  683. // Stub descriptor.
  684. pCallExpr->SetParam( new expr_param(
  685. new expr_u_address (
  686. new expr_variable(
  687. pCCB->GetInterfaceCG()->GetStubDescName() ) ) ) );
  688. sprintf( FormatStringExpr,
  689. "&%s[%d]",
  690. PROC_FORMAT_STRING_STRING_FIELD,
  691. GetFormatStringOffset() );
  692. // Format string pointer.
  693. pCallExpr->SetParam( new expr_param(
  694. new expr_variable( FormatStringExpr ) ) );
  695. // Parameter structure pointer.
  696. if ( ! IsNullCall() )
  697. {
  698. pCallExpr->SetParam( new expr_param(
  699. new expr_u_address (
  700. new expr_variable( "ParamStruct" ) ) ) );
  701. }
  702. else
  703. {
  704. pCallExpr->SetParam( new expr_param(
  705. new expr_variable( "0" ) ) );
  706. }
  707. // Print the unmarshall call.
  708. pCallExpr->PrintCall( pCCB->GetStream(),
  709. 0,
  710. 0 );
  711. pStream->NewLine();
  712. //
  713. // Now make the call to the manager.
  714. //
  715. GenNdrInterpretedManagerCall( pCCB );
  716. //
  717. // Make the single marshall call.
  718. //
  719. pCallExpr = new expr_proc_call( S_NDR_MARSHALL_RTN_NAME );
  720. // Stub message.
  721. pCallExpr->SetParam( new expr_param(
  722. new expr_u_address (
  723. new expr_variable( STUB_MESSAGE_VAR_NAME ) ) ) );
  724. // Format string pointer.
  725. pCallExpr->SetParam( new expr_param(
  726. new expr_variable( FormatStringExpr ) ) );
  727. pStream->NewLine( 2 );
  728. // Print the marshall routine call.
  729. pCallExpr->PrintCall( pCCB->GetStream(),
  730. 0,
  731. 0 );
  732. }
  733. void
  734. CG_PROC::GenNdrInterpretedServerLocals( CCB * pCCB )
  735. /*++
  736. Routine Description :
  737. This routine outputs the two local variables for an interpreted server
  738. stub. The two locals are the stub message and the param struct.
  739. Arguments :
  740. pCCB - pointer to the code control block
  741. --*/
  742. {
  743. ISTREAM * pStream;
  744. pStream = pCCB->GetStream();
  745. // Stub message local.
  746. pStream->Write( STUB_MESSAGE_TYPE_NAME " " STUB_MESSAGE_VAR_NAME ";" );
  747. pStream->NewLine();
  748. // Generate the param struct for non-null calls only.
  749. if ( ! IsNullCall() )
  750. {
  751. GenNdrInterpreterParamStruct( pCCB );
  752. pStream->Write( PARAM_STRUCT_TYPE_NAME " ParamStruct;" );
  753. pStream->NewLine();
  754. }
  755. }
  756. void
  757. CG_PROC::GenNdrInterpreterParamStruct(
  758. CCB * pCCB)
  759. {
  760. BOOL f64 = pCommand->Is64BitEnv();
  761. if ( f64)
  762. GenNdrInterpreterParamStruct64( pCCB);
  763. else
  764. GenNdrInterpreterParamStruct32( pCCB );
  765. }
  766. void
  767. CG_PROC::GenNdrInterpreterParamStruct64( CCB * pCCB )
  768. {
  769. CG_ITERATOR Iterator;
  770. ISTREAM * pStream;
  771. CG_PARAM * pParam;
  772. CG_PARAM * pParamPrev;
  773. CG_RETURN * pReturn;
  774. CG_NDR * pNdr;
  775. long PadNumber;
  776. char Buffer[80];
  777. long PrevEndOffset;
  778. pStream = pCCB->GetStream();
  779. // Register size is 8 for 64b platform.
  780. pStream->Write( "#pragma pack(8)" );
  781. pStream->NewLine();
  782. pStream->Write( PARAM_STRUCT_TYPE_NAME );
  783. pStream->IndentInc();
  784. pStream->NewLine();
  785. pStream->Write( '{' );
  786. pStream->NewLine();
  787. PadNumber = 0;
  788. GetMembers( Iterator );
  789. if ( IsObject() )
  790. {
  791. pCCB->GetInterfaceCG()->GetThisDeclarator()->PrintType(
  792. PRT_PARAM_OR_ID_DECLARATION,
  793. pStream,
  794. (node_skl *)0 );
  795. PrevEndOffset = 8;
  796. }
  797. else
  798. PrevEndOffset = 0;
  799. pParamPrev = 0;
  800. while( ITERATOR_GETNEXT( Iterator, pParam ) )
  801. {
  802. pNdr = (CG_NDR *) pParam->GetChild();
  803. if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
  804. pNdr = (CG_NDR *) pNdr->GetChild();
  805. // IA64 does not align every big struct to 16b boundary.
  806. // Only __int128 etc. would be aligned to 16 (and objects embedding it).
  807. // OPTIMIZE: The code below is correct, as GetStackOffset with PrevEndOffset
  808. // is a check for alignment of 16, but pParam->GetMemAlign() would be better.
  809. if ( (pParam->GetStackSize() > 8) && PrevEndOffset > 0 )
  810. {
  811. long CurrentIA64Offset;
  812. if ( pParamPrev )
  813. {
  814. PrevEndOffset = pParamPrev->GetStackOffset( pCCB, I386_STACK_SIZING )
  815. + pParamPrev->GetStackSize();
  816. if ( PrevEndOffset & 7 )
  817. PrevEndOffset += 8 - (PrevEndOffset & 7);
  818. }
  819. // The additional pad for 16b aligned objects can only be
  820. // a full register as the prev param is already padded.
  821. CurrentIA64Offset = pParam->GetStackOffset( pCCB, I386_STACK_SIZING );
  822. if ( CurrentIA64Offset - PrevEndOffset )
  823. {
  824. sprintf( Buffer, "char Pad%d[8];", PadNumber++ );
  825. pStream->Write( Buffer );
  826. pStream->NewLine();
  827. }
  828. }
  829. //
  830. // For reasons lost to the ages if we have a pointer to a
  831. // context handle then it's type gets munged from TYPE* to
  832. // NDR_SCONTEXT. This is fine except that it causes type
  833. // mismatch errors in the server stub. Special case it here.
  834. //
  835. bool print = true;
  836. if ( pNdr->IsPointer() )
  837. {
  838. CG_CONTEXT_HANDLE *pHandle = dynamic_cast<CG_CONTEXT_HANDLE *>
  839. ( pNdr->GetChild() );
  840. if ( pHandle )
  841. {
  842. pStream->WriteFormat(
  843. "%s *%s;",
  844. pHandle->GetHandleType()->GetSymName(),
  845. pParam->GetSymName());
  846. pStream->NewLine();
  847. print = false;
  848. }
  849. }
  850. // Print the field declaration.
  851. if (print)
  852. {
  853. pParam->GetResource()->GetType()->PrintType(
  854. PRT_PARAM_OR_ID_DECLARATION,
  855. pStream,
  856. (node_skl *)0 );
  857. }
  858. //
  859. // Generate some padding if needed.
  860. //
  861. if ( pParam->GetStackSize() & 7 )
  862. {
  863. long Pad = 8 - (pParam->GetStackSize() & 7);
  864. sprintf( Buffer, "char Pad%d[%d];", PadNumber++, Pad );
  865. pStream->Write( Buffer );
  866. pStream->NewLine();
  867. }
  868. pParamPrev = pParam;
  869. } // while params
  870. // Add the return type if one is present.
  871. if ( ( pReturn = GetReturnType() ) != 0 )
  872. {
  873. pReturn->GetResource()->GetType()->PrintType(
  874. PRT_PARAM_OR_ID_DECLARATION,
  875. pStream,
  876. (node_skl *)0 );
  877. // Possibly we could add a padding after the return type member
  878. // but it would not be used anyway.
  879. }
  880. pStream->Write( "};" );
  881. pStream->IndentDec();
  882. pStream->NewLine();
  883. pStream->Write( "#pragma pack()" );
  884. pStream->NewLine();
  885. }
  886. void
  887. CG_PROC::GenNdrInterpreterParamStruct32( CCB * pCCB )
  888. {
  889. CG_ITERATOR Iterator;
  890. ISTREAM * pStream;
  891. CG_PARAM * pParam;
  892. CG_PARAM * pParamPrev;
  893. CG_RETURN * pReturn;
  894. CG_NDR * pNdr;
  895. long Pad;
  896. long PadNumber;
  897. char Buffer[80];
  898. pStream = pCCB->GetStream();
  899. pStream->Write( "#pragma pack(4)" );
  900. pStream->NewLine();
  901. pStream->Write( PARAM_STRUCT_TYPE_NAME );
  902. pStream->IndentInc();
  903. pStream->NewLine();
  904. pStream->Write( '{' );
  905. pStream->NewLine();
  906. PadNumber = 0;
  907. GetMembers( Iterator );
  908. if ( IsObject() )
  909. {
  910. pCCB->GetInterfaceCG()->GetThisDeclarator()->PrintType(
  911. PRT_PARAM_OR_ID_DECLARATION,
  912. pStream,
  913. (node_skl *)0 );
  914. }
  915. pParamPrev = 0;
  916. while( ITERATOR_GETNEXT( Iterator, pParam ) )
  917. {
  918. pNdr = (CG_NDR *) pParam->GetChild();
  919. if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
  920. pNdr = (CG_NDR *) pNdr->GetChild();
  921. //
  922. // For reasons lost to the ages if we have a pointer to a
  923. // context handle then it's type gets munged from TYPE* to
  924. // NDR_SCONTEXT. This is fine except that it causes type
  925. // mismatch errors in the server stub. Special case it here.
  926. //
  927. bool print = true;
  928. if ( pNdr->IsPointer() )
  929. {
  930. CG_CONTEXT_HANDLE *pHandle = dynamic_cast<CG_CONTEXT_HANDLE *>
  931. ( pNdr->GetChild() );
  932. if ( pHandle )
  933. {
  934. pStream->WriteFormat(
  935. "%s *%s;",
  936. pHandle->GetHandleType()->GetSymName(),
  937. pParam->GetSymName());
  938. pStream->NewLine();
  939. print = false;
  940. }
  941. }
  942. // Print the field declaration.
  943. if (print)
  944. {
  945. pParam->GetResource()->GetType()->PrintType(
  946. PRT_PARAM_OR_ID_DECLARATION,
  947. pStream,
  948. (node_skl *)0 );
  949. }
  950. //
  951. // Generate some padding if needed.
  952. //
  953. if ( pParam->GetStackSize() & 3 )
  954. {
  955. Pad = 4 - (pParam->GetStackSize() & 3);
  956. sprintf( Buffer, "char Pad%d[%d];", PadNumber++, Pad );
  957. pStream->Write( Buffer );
  958. pStream->NewLine();
  959. }
  960. pParamPrev = pParam;
  961. } // while params
  962. // Add the return type if one is present.
  963. if ( ( pReturn = GetReturnType() ) != 0 )
  964. {
  965. pReturn->GetResource()->GetType()->PrintType(
  966. PRT_PARAM_OR_ID_DECLARATION,
  967. pStream,
  968. (node_skl *)0 );
  969. }
  970. pStream->Write( "};" );
  971. pStream->IndentDec();
  972. pStream->NewLine();
  973. pStream->Write( "#pragma pack()" );
  974. pStream->NewLine();
  975. }
  976. void
  977. CG_PROC::GenNdrInterpretedManagerCall( CCB * pCCB )
  978. /*++
  979. Routine Description :
  980. This routine outputs the call to the manager for interpreted stubs.
  981. Arguments :
  982. pCCB - pointer to the code control block
  983. --*/
  984. {
  985. CG_ITERATOR Iterator;
  986. CG_PARAM * pParam;
  987. // CG_RETURN * pReturn;
  988. expr_proc_call * pCall;
  989. expr_node * pExpr;
  990. if ( GetCallAsName() )
  991. {
  992. pCall = new expr_proc_call( GenMangledCallAsName( pCCB ) );
  993. }
  994. else
  995. pCall = new expr_proc_call( GetType()->GetSymName() );
  996. GetMembers( Iterator );
  997. while( ITERATOR_GETNEXT( Iterator, pParam ) )
  998. {
  999. CG_NDR * pNdr;
  1000. char * pName;
  1001. expr_node * pExpr;
  1002. pNdr = (CG_NDR *) pParam->GetChild();
  1003. pName = new char[80];
  1004. strcpy( pName, "pParamStruct->" );
  1005. strcat( pName, pParam->GetResource()->GetResourceName() );
  1006. pExpr = new expr_variable( pName );
  1007. pCall->SetParam( new expr_param ( pExpr ) );
  1008. }
  1009. //
  1010. // epv stuff
  1011. //
  1012. expr_node * pExprTemp;
  1013. if( pCCB->IsMEpV() && (GetCGID() != ID_CG_CALLBACK_PROC) )
  1014. {
  1015. unsigned short M, m;
  1016. CSzBuffer Buffer;
  1017. char * pTemp;
  1018. pCCB->GetVersion( &M, &m );
  1019. Buffer.Set("((");
  1020. Buffer.Append(pCCB->GetInterfaceName());
  1021. Buffer.Append(pCCB->GenMangledName());
  1022. Buffer.Append("_");
  1023. Buffer.Append(pCCB->IsOldNames() ? "SERVER_EPV" : "epv_t");
  1024. Buffer.Append(" *)(");
  1025. Buffer.Append(PRPC_MESSAGE_MANAGER_EPV_NAME);
  1026. Buffer.Append("))");
  1027. pTemp = new char [ strlen( Buffer ) + 1 ];
  1028. strcpy( pTemp, Buffer );
  1029. pExprTemp = new expr_variable( pTemp );//this has the rhs expr for the
  1030. // manager epv call. Sneaky !
  1031. pCall = (expr_proc_call *)new expr_pointsto( pExprTemp, pCall );
  1032. }
  1033. //
  1034. // end epv stuff
  1035. //
  1036. // async methods don't have return values
  1037. if ( GetReturnType() && !HasAsyncHandle() )
  1038. {
  1039. CG_NDR * pC = (CG_NDR *) GetReturnType()->GetChild();
  1040. if( pC->GetCGID() == ID_CG_CONTEXT_HDL )
  1041. {
  1042. expr_proc_call * pProc = new expr_proc_call( "NDRSContextValue" );
  1043. pProc->SetParam( new expr_param(
  1044. new expr_variable(
  1045. "pParamStruct->" RETURN_VALUE_VAR_NAME ) ) );
  1046. // cast the proc call to this type.
  1047. pExpr = MakeDerefExpressionOfCastPtrToType(
  1048. GetReturnType()->GetType(),
  1049. pProc );
  1050. pExpr = new expr_assign (pExpr, pCall );
  1051. }
  1052. else
  1053. {
  1054. pExpr = new expr_assign(
  1055. new expr_variable(
  1056. "pParamStruct->" RETURN_VALUE_VAR_NAME ),
  1057. pCall );
  1058. }
  1059. }
  1060. else
  1061. pExpr = pCall;
  1062. pCCB->GetStream()->NewLine();
  1063. pExpr->PrintCall( pCCB->GetStream(), 0, 0 );
  1064. pCCB->GetStream()->NewLine();
  1065. }
  1066. void
  1067. CG_PROC::GenNdrThunkInterpretedServerStub( CCB * pCCB )
  1068. {
  1069. ISTREAM * pStream;
  1070. pStream = pCCB->GetStream();
  1071. pStream->NewLine();
  1072. if ( pCCB->GetInterfaceCG()->GetCGID() == ID_CG_INHERITED_OBJECT_INTERFACE )
  1073. pStream->Write( "static " );
  1074. pStream->Write( "void __RPC_API" );
  1075. pStream->NewLine();
  1076. pStream->Write( pCCB->GetInterfaceName() );
  1077. pStream->Write( '_' );
  1078. pStream->Write( GetType()->GetSymName() );
  1079. // if ( IsObject() )
  1080. pStream->Write( "_Thunk" );
  1081. pStream->Write( '(' );
  1082. pStream->IndentInc();
  1083. pStream->NewLine();
  1084. pStream->Write( PSTUB_MESSAGE_TYPE_NAME " " PSTUB_MESSAGE_PAR_NAME " )" );
  1085. pStream->IndentDec();
  1086. pStream->NewLine();
  1087. pStream->Write( '{' );
  1088. pStream->IndentInc();
  1089. pStream->NewLine();
  1090. GenNdrInterpreterParamStruct( pCCB );
  1091. pStream->Write( PARAM_STRUCT_TYPE_NAME " * pParamStruct;" );
  1092. pStream->NewLine( 2 );
  1093. pStream->Write( "pParamStruct = (" PARAM_STRUCT_TYPE_NAME " *) " );
  1094. pStream->Write( PSTUB_MESSAGE_PAR_NAME "->StackTop;" );
  1095. pStream->NewLine();
  1096. GenNdrInterpretedManagerCall( pCCB );
  1097. pStream->IndentDec();
  1098. pStream->NewLine();
  1099. pStream->Write( '}' );
  1100. pStream->NewLine();
  1101. }
  1102. void
  1103. CG_PROC::GenNdrOldInterpretedServerStub( CCB * pCCB )
  1104. {
  1105. #ifdef TEMPORARY_OI_SERVER_STUBS
  1106. // This code is being generated temporarily to enable easier debugging
  1107. // of server side -Oi stubs. Normally server side stubs do not exist. And
  1108. // the server side runtime calls the Server side interpreter directly. This
  1109. // causes debugging problems if we want to breakpoint on a method on an
  1110. // interface. Therefore till we get the system converted to -Oi and the
  1111. // stress stabilizes, we will emit a server side procedure which will
  1112. // enable breakpointing per interface proc.
  1113. // This emits just the server side prolog for -Oi.
  1114. S_GenProlog( pCCB );
  1115. // Emit the call to NdrStubCall or NdrServerCall.
  1116. PNAME pProcName = IsObject() ? S_OBJECT_NDR_CALL_RTN_NAME :
  1117. S_NDR_CALL_RTN_NAME;
  1118. expr_proc_call * pProc = new expr_proc_call( pProcName );
  1119. ITERATOR ParamList;
  1120. expr_node * pParam;
  1121. // Set the parameters.
  1122. pCCB->GetListOfParamResources( ParamList );
  1123. while( ITERATOR_GETNEXT( ParamList, pParam ) )
  1124. {
  1125. pProc->SetParam( pParam );
  1126. }
  1127. // Emit the call to the interpreter.
  1128. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  1129. Out_IndentDec( pCCB );
  1130. Out_ProcClosingBrace( pCCB );
  1131. #else TEMPORARY_OI_SERVER_STUBS
  1132. //
  1133. // Generate the function header.
  1134. //
  1135. S_GenProlog( pCCB );
  1136. //
  1137. // Do the single call code generation. This includes the
  1138. // declarations of the three server locals : the stub message, the
  1139. // return variable if needed, and the parameter structure.
  1140. //
  1141. GenNdrSingleServerCall( pCCB );
  1142. // Generate end stuff.
  1143. Out_IndentDec( pCCB );
  1144. Out_ProcClosingBrace( pCCB );
  1145. #endif // TEMPORARY_OI_SERVER_STUBS
  1146. }
  1147. //
  1148. // Param format string generation.
  1149. //
  1150. void
  1151. CG_PARAM::GenNdrFormat( CCB * pCCB )
  1152. /*++
  1153. Routine Description :
  1154. Calls the parameter's child node to generate it's format string.
  1155. Arguments :
  1156. pCCB - pointer to the code control block
  1157. --*/
  1158. {
  1159. MIDL_ASSERT( !pCommand->IsNDR64Run() );
  1160. if ( GetFormatStringOffset() != -1 )
  1161. return;
  1162. // The invisible fault/comm status param added by means of acf definition
  1163. // doesn't go on wire, so it has no format string representation.
  1164. if ( IsExtraStatusParam() )
  1165. return;
  1166. // [async_handle] This parameter is the invisible xxx_AsyncHandle and does not go
  1167. // on the wire, so it has no format representation.
  1168. if ( IsAsyncHandleParam() )
  1169. return;
  1170. //
  1171. // Call the param child to generate it's format string.
  1172. //
  1173. ((CG_NDR *)GetChild())->GenNdrFormat( pCCB );
  1174. //
  1175. // Set the param node's format string offset equal to the child.
  1176. //
  1177. SetFormatStringOffset( ((CG_NDR *)GetChild())->GetFormatStringOffset() );
  1178. }
  1179. //
  1180. // Individual NDR routine calls output.
  1181. //
  1182. void
  1183. CG_PARAM::GenNdrMarshallCall( CCB * pCCB )
  1184. /*++
  1185. Routine Description :
  1186. Outputs a parameter's ndr marshall routine call.
  1187. Arguments :
  1188. pCCB - pointer to the code control block
  1189. --*/
  1190. {
  1191. ISTREAM * pStream;
  1192. CG_NDR * pChild;
  1193. FORMAT_STRING * pFormatString;
  1194. PNAME pParamName;
  1195. ID_CG ParamId;
  1196. long NameIndex;
  1197. long FormatOffset;
  1198. BOOL fTakeAddress;
  1199. BOOL fDereference;
  1200. unsigned short WireAlign;
  1201. // BUG BUG, this needs to be cleaned up for NDR64
  1202. MIDL_ASSERT( !pCommand->IsNDR64Run() );
  1203. pStream = pCCB->GetStream();
  1204. pChild = (CG_NDR *)GetChild();
  1205. ParamId = pChild->GetCGID();
  1206. pParamName = GetResource()->GetResourceName();
  1207. if ( IsParamPartialIgnore() &&
  1208. ( pCCB->GetCodeGenSide() == CGSIDE_CLIENT ) )
  1209. {
  1210. Out_PartialIgnoreClientMarshall( pCCB, pParamName );
  1211. return;
  1212. }
  1213. if ( (ParamId == ID_CG_PRIMITIVE_HDL) ||
  1214. ((ParamId == ID_CG_PTR) &&
  1215. (((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_PRIMITIVE_HDL)) )
  1216. return;
  1217. //
  1218. // For a generic handle, get the handle data type and then continue.
  1219. //
  1220. if ( ParamId == ID_CG_GENERIC_HDL )
  1221. {
  1222. pChild = (CG_NDR *)pChild->GetChild();
  1223. ParamId = pChild->GetCGID();
  1224. }
  1225. //
  1226. // Since a ref pointer is not shipped, we must use it's child to figure
  1227. // out the alignment action and next alignment state.
  1228. //
  1229. if ( pChild->IsPointer() &&
  1230. ( !pChild->IsInterfacePointer() ) &&
  1231. (pChild->GetCGID() != ID_CG_STRING_PTR) &&
  1232. (pChild->GetCGID() != ID_CG_STRUCT_STRING_PTR) &&
  1233. (pChild->GetCGID() != ID_CG_SIZE_STRING_PTR) &&
  1234. (pChild->GetCGID() != ID_CG_SIZE_PTR) &&
  1235. (pChild->GetCGID() != ID_CG_SIZE_LENGTH_PTR) &&
  1236. (((CG_POINTER *)pChild)->GetPtrType() == PTR_REF) )
  1237. {
  1238. CG_NDR * pPtrChild = (CG_NDR *) pChild->GetChild();
  1239. if ( ! pChild->IsPipeOrPipeReference() )
  1240. {
  1241. WireAlign = pPtrChild->GetWireAlignment();
  1242. }
  1243. }
  1244. else
  1245. {
  1246. // We shouldn't do that for pipe and object pipe args
  1247. if ( ! pChild->IsPipeOrPipeReference() )
  1248. {
  1249. WireAlign = pChild->GetWireAlignment();
  1250. }
  1251. }
  1252. // For context handles, generate an optimized code for the client side and
  1253. // also an optimize code for common context handles at the server side but
  1254. // except that for new context handle flavors the call is slightly different.
  1255. if ( (ParamId == ID_CG_CONTEXT_HDL) ||
  1256. ((ParamId == ID_CG_PTR) &&
  1257. (((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_CONTEXT_HDL)) )
  1258. {
  1259. if ( pCCB->GetCodeGenSide() == CGSIDE_CLIENT )
  1260. {
  1261. Out_CContextHandleMarshall( pCCB,
  1262. pParamName,
  1263. (ParamId == ID_CG_PTR) );
  1264. }
  1265. else
  1266. {
  1267. CG_CONTEXT_HANDLE * pContextHandle;
  1268. pContextHandle = (ParamId == ID_CG_PTR) ?
  1269. (CG_CONTEXT_HANDLE *) pChild->GetChild() :
  1270. (CG_CONTEXT_HANDLE *) pChild;
  1271. pCCB->RegisterContextHandleType( pContextHandle->GetHandleType() );
  1272. if ( pContextHandle->HasNewContextFlavor() )
  1273. {
  1274. Out_SContextHandleNewMarshall( pCCB,
  1275. pParamName,
  1276. pContextHandle->GetRundownRtnName(),
  1277. pContextHandle->GetFormatStringOffset() );
  1278. }
  1279. else
  1280. {
  1281. Out_SContextHandleMarshall( pCCB,
  1282. pParamName,
  1283. pContextHandle->GetRundownRtnName() );
  1284. }
  1285. }
  1286. return;
  1287. }
  1288. if ( pChild->GetCGID() == ID_CG_ENUM || pChild->GetCGID() == ID_CG_INT3264 )
  1289. {
  1290. expr_proc_call * pCall;
  1291. FORMAT_CHARACTER fc;
  1292. expr_node * pExpr;
  1293. if ( pChild->GetCGID() == ID_CG_ENUM )
  1294. fc = ((CG_ENUM *)pChild)->GetFormatChar();
  1295. else
  1296. fc = ((CG_BASETYPE *)pChild)->GetSignedFormatChar();
  1297. pCall = new expr_proc_call( "NdrSimpleTypeMarshall" );
  1298. pExpr = new expr_u_address (
  1299. new expr_variable( STUB_MESSAGE_VAR_NAME ) );
  1300. pExpr = MakeExpressionOfCastToTypeName(PSTUB_MESSAGE_TYPE_NAME , pExpr);
  1301. pCall->SetParam( new expr_param( pExpr ) );
  1302. pExpr = new expr_u_address ( new expr_variable( pParamName ) );
  1303. pExpr = MakeCastExprPtrToUChar( pExpr );
  1304. pCall->SetParam( new expr_param( pExpr ) );
  1305. // Don't emit names like FC_ENUM16 or FC_INT3264 as constants are not public.
  1306. pCall->SetParam( new expr_param(
  1307. new expr_constant( (long)fc ) ) );
  1308. pStream->NewLine();
  1309. pCall->PrintCall( pStream, 0, 0 );
  1310. return;
  1311. }
  1312. if ( pChild->IsSimpleType() )
  1313. {
  1314. pStream->NewLine();
  1315. OutputNdrAlignment( pCCB, WireAlign );
  1316. //
  1317. // Now make the assignment expression and increment with cast, like :
  1318. //
  1319. // *((<type> *)_StubMsg.Buffer)++ = <var>;
  1320. //
  1321. expr_node * pExpr;
  1322. expr_variable * pBufVar;
  1323. expr_variable * pVar;
  1324. pBufVar = new expr_variable( STUB_MSG_BUFFER_VAR_NAME );
  1325. pVar = new expr_variable( pParamName );
  1326. pExpr = MakeExpressionOfCastPtrToType( pChild->GetType(), pBufVar );
  1327. pExpr = new expr_post_incr( pExpr );
  1328. pExpr = new expr_u_deref( pExpr );
  1329. pExpr = new expr_assign( pExpr, pVar );
  1330. pExpr->Print( pStream );
  1331. pStream->Write( ';' );
  1332. pStream->NewLine();
  1333. return;
  1334. }
  1335. if ( pChild->IsPointerToBaseType() &&
  1336. (((CG_POINTER *)pChild)->GetPtrType() == PTR_REF) &&
  1337. (((CG_NDR *)pChild->GetChild())->GetCGID() != ID_CG_ENUM) &&
  1338. (((CG_NDR *)pChild->GetChild())->GetCGID() != ID_CG_INT3264) )
  1339. {
  1340. CG_POINTER * pPointer;
  1341. CG_NDR * pBasetype;
  1342. expr_node * pExpr;
  1343. expr_variable * pBufVar;
  1344. expr_variable * pVar;
  1345. pPointer = (CG_POINTER *) pChild;
  1346. pBasetype = (CG_NDR *) pPointer->GetChild();
  1347. if ( pBasetype->GetCGID() == ID_CG_GENERIC_HDL )
  1348. pBasetype = (CG_NDR *) pBasetype->GetChild();
  1349. pBufVar = new expr_variable( STUB_MSG_BUFFER_VAR_NAME );
  1350. pVar = new expr_variable( pParamName );
  1351. pStream->NewLine();
  1352. OutputNdrAlignment( pCCB, WireAlign );
  1353. //
  1354. // Now make the assignment expression and increment with cast, like :
  1355. //
  1356. // *((<type>)_StubMsg.Buffer)++ = *<var>;
  1357. //
  1358. pExpr = MakeExpressionOfCastPtrToType( pBasetype->GetType(), pBufVar );
  1359. pExpr = new expr_post_incr( pExpr );
  1360. pExpr = new expr_u_deref( pExpr );
  1361. pExpr = new expr_assign( pExpr, new expr_u_deref(pVar) );
  1362. pExpr->Print( pStream );
  1363. pStream->Write( ';' );
  1364. pStream->NewLine();
  1365. return;
  1366. }
  1367. GenNdrTopLevelAttributeSupport( pCCB );
  1368. pFormatString = pCCB->GetFormatString();
  1369. FormatOffset = pChild->GetFormatStringOffset();
  1370. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1371. //
  1372. // If the param is a by-value struct or union then set the fTakeAddress
  1373. // flag.
  1374. //
  1375. fTakeAddress = pChild->IsStruct() || pChild->IsUnion()
  1376. || pChild->IsXmitRepOrUserMarshal();
  1377. //
  1378. // If the param is an array and we're in the server stub then we
  1379. // must dereference it.
  1380. //
  1381. fDereference = (pCCB->GetCodeGenSide() == CGSIDE_SERVER) &&
  1382. pChild->IsArray();
  1383. //
  1384. // If the param is an omitted cs_tag param, the marshalling code takes
  1385. // care of handling the call to the tag routine to get the actual value.
  1386. // Also, since we don't have the parameter on the stack we don't have a
  1387. // name to pass to Marshall so just pass "0" (NULL)
  1388. //
  1389. if ( IsOmittedParam() )
  1390. {
  1391. PNAME pNewName = (PNAME) alloca( sizeof("0 /* */")
  1392. + strlen(pParamName) );
  1393. strcpy( pNewName, "0 /* ");
  1394. strcat( pNewName, pParamName );
  1395. strcat( pNewName, " */");
  1396. pParamName = pNewName;
  1397. fTakeAddress = FALSE; // Probably don't need these but be safe
  1398. fDereference = FALSE;
  1399. }
  1400. //
  1401. // For ref pointers with no funky attributes, we optimize by calling
  1402. // the pointee's routine directly.
  1403. //
  1404. if ( pChild->IsPointer() && ((CG_POINTER *)pChild)->IsBasicRefPointer() )
  1405. {
  1406. CG_POINTER * pPointer;
  1407. pPointer = (CG_POINTER *) pChild;
  1408. switch ( pPointer->GetCGID() )
  1409. {
  1410. case ID_CG_STRING_PTR :
  1411. if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
  1412. break;
  1413. FormatOffset = pPointer->GetFormatStringOffset() + 2;
  1414. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1415. break;
  1416. case ID_CG_SIZE_STRING_PTR :
  1417. if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
  1418. break;
  1419. FormatOffset = pPointer->GetPointeeFormatStringOffset();
  1420. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1421. break;
  1422. case ID_CG_STRUCT_STRING_PTR :
  1423. break;
  1424. default :
  1425. FormatOffset = pPointer->GetPointeeFormatStringOffset();
  1426. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1427. break;
  1428. }
  1429. }
  1430. Out_NdrMarshallCall( pCCB,
  1431. pNdrRoutineNames[NameIndex],
  1432. pParamName,
  1433. FormatOffset,
  1434. fTakeAddress,
  1435. fDereference );
  1436. }
  1437. void
  1438. CG_PARAM::GenNdrUnmarshallCall( CCB * pCCB )
  1439. /*++
  1440. Routine Description :
  1441. Outputs a parameter's ndr unmarshall routine call.
  1442. Arguments :
  1443. pCCB - pointer to the code control block
  1444. --*/
  1445. {
  1446. // BUG BUG, this needs to be cleaned up for NDR64
  1447. MIDL_ASSERT( !pCommand->IsNDR64Run() );
  1448. ISTREAM * pStream;
  1449. CG_NDR * pChild;
  1450. FORMAT_STRING * pFormatString;
  1451. PNAME pParamName;
  1452. ID_CG ParamId;
  1453. long NameIndex;
  1454. long FormatOffset;
  1455. BOOL fMustAllocFlag = FALSE;
  1456. BOOL fTakeAddress = TRUE;
  1457. unsigned short WireAlign;
  1458. pStream = pCCB->GetStream();
  1459. pChild = (CG_NDR *)GetChild();
  1460. ParamId = pChild->GetCGID();
  1461. pParamName = GetResource()->GetResourceName();
  1462. if ( IsParamPartialIgnore() &&
  1463. ( pCCB->GetCodeGenSide() == CGSIDE_SERVER ) )
  1464. {
  1465. Out_PartialIgnoreServerUnmarshall( pCCB, pParamName );
  1466. return;
  1467. }
  1468. if ( (ParamId == ID_CG_PRIMITIVE_HDL) ||
  1469. ((ParamId == ID_CG_PTR) &&
  1470. (((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_PRIMITIVE_HDL)) )
  1471. return;
  1472. //
  1473. // For a generic handle, get the handle data type and then continue.
  1474. //
  1475. if ( ParamId == ID_CG_GENERIC_HDL )
  1476. {
  1477. pChild = (CG_NDR *)pChild->GetChild();
  1478. ParamId = pChild->GetCGID();
  1479. }
  1480. BOOL IsOutOnly;
  1481. IsOutOnly = ! IsParamIn() || (GetCGID() == ID_CG_RETURN);
  1482. //
  1483. // Since a ref pointer is not shipped, we must use it's child to figure
  1484. // out the alignment action and next alignment state.
  1485. //
  1486. if ( pChild->IsPointer() &&
  1487. (!pChild->IsInterfacePointer()) &&
  1488. (pChild->GetCGID() != ID_CG_STRING_PTR) &&
  1489. (pChild->GetCGID() != ID_CG_STRUCT_STRING_PTR) &&
  1490. (pChild->GetCGID() != ID_CG_SIZE_STRING_PTR) &&
  1491. (pChild->GetCGID() != ID_CG_SIZE_PTR) &&
  1492. (pChild->GetCGID() != ID_CG_SIZE_LENGTH_PTR) &&
  1493. (((CG_POINTER *)pChild)->GetPtrType() == PTR_REF) )
  1494. {
  1495. CG_NDR * pPtrChild = (CG_NDR *) pChild->GetChild();
  1496. if ( ! (IsExtraStatusParam() || pChild->IsPipeOrPipeReference()) )
  1497. {
  1498. WireAlign = pPtrChild->GetWireAlignment();
  1499. }
  1500. }
  1501. else
  1502. {
  1503. // We should not do that for pipe or object pipe args
  1504. // However, we do not support -Os pipes as yet.
  1505. if ( ! pChild->IsPipeOrPipeReference() )
  1506. {
  1507. WireAlign = pChild->GetWireAlignment();
  1508. }
  1509. }
  1510. // For context handles, generate an optimized code for the client side and
  1511. // also an optimize code for common context handles at the server side but
  1512. // except that for new context handle flavors the call is slightly different.
  1513. if ( (ParamId == ID_CG_CONTEXT_HDL) ||
  1514. ( (ParamId == ID_CG_PTR) &&
  1515. (((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_CONTEXT_HDL) ) )
  1516. {
  1517. if ( pCCB->GetCodeGenSide() == CGSIDE_CLIENT )
  1518. {
  1519. BOOL Initialize;
  1520. Initialize = IsOutOnly && (ParamId == ID_CG_PTR);
  1521. Out_CContextHandleUnmarshall( pCCB,
  1522. pParamName,
  1523. Initialize,
  1524. GetCGID() == ID_CG_RETURN );
  1525. }
  1526. else
  1527. {
  1528. CG_CONTEXT_HANDLE * pContextHandle;
  1529. pContextHandle = (ParamId == ID_CG_PTR) ?
  1530. (CG_CONTEXT_HANDLE *) pChild->GetChild() :
  1531. (CG_CONTEXT_HANDLE *) pChild;
  1532. if ( pContextHandle->HasNewContextFlavor() ||
  1533. pCommand->GetNdrVersionControl().IsNdr50orLaterRequired() )
  1534. {
  1535. Out_SContextHandleNewUnmarshall( pCCB,
  1536. pParamName,
  1537. IsOutOnly,
  1538. pContextHandle->GetFormatStringOffset() );
  1539. }
  1540. else
  1541. {
  1542. Out_SContextHandleUnmarshall( pCCB,
  1543. pParamName,
  1544. IsOutOnly );
  1545. }
  1546. }
  1547. return;
  1548. }
  1549. if ( pChild->GetCGID() == ID_CG_ENUM || pChild->GetCGID() == ID_CG_INT3264 )
  1550. {
  1551. expr_proc_call * pCall;
  1552. FORMAT_CHARACTER fc;
  1553. expr_node * pExpr;
  1554. if ( pChild->GetCGID() == ID_CG_ENUM )
  1555. fc = ((CG_ENUM *)pChild)->GetFormatChar();
  1556. else
  1557. fc = ((CG_BASETYPE *)pChild)->GetSignedFormatChar();
  1558. pCall = new expr_proc_call( "NdrSimpleTypeUnmarshall" );
  1559. pExpr = new expr_u_address(new expr_variable(STUB_MESSAGE_VAR_NAME));
  1560. pExpr = MakeExpressionOfCastToTypeName(PSTUB_MESSAGE_TYPE_NAME , pExpr);
  1561. pCall->SetParam( new expr_param( pExpr ) );
  1562. pExpr = new expr_u_address ( new expr_variable( pParamName ) );
  1563. pExpr = MakeCastExprPtrToUChar( pExpr );
  1564. pCall->SetParam( new expr_param( pExpr ) );
  1565. pCall->SetParam( new expr_param(
  1566. new expr_constant( (long)fc ) ) );
  1567. pStream->NewLine();
  1568. pCall->PrintCall( pStream, 0, 0 );
  1569. return;
  1570. }
  1571. if ( pChild->IsSimpleType() )
  1572. {
  1573. pStream->NewLine();
  1574. OutputNdrAlignment( pCCB, WireAlign );
  1575. Out_CheckUnMarshallPastBufferEnd( pCCB, pChild->GetWireSize() );
  1576. pStream->NewLine();
  1577. //
  1578. // Now make the assignment expression and increment with cast, like :
  1579. //
  1580. // <var> = *((<type> *)_StubMsg.Buffer)++;
  1581. //
  1582. expr_node * pExpr;
  1583. expr_variable * pBufVar;
  1584. expr_variable * pVar;
  1585. pBufVar = new expr_variable( STUB_MSG_BUFFER_VAR_NAME );
  1586. pVar = new expr_variable( pParamName );
  1587. pExpr = MakeExpressionOfCastPtrToType( pChild->GetType(), pBufVar );
  1588. pExpr = new expr_post_incr( pExpr );
  1589. pExpr = new expr_u_deref( pExpr );
  1590. pExpr = new expr_assign( pVar, pExpr );
  1591. pExpr->Print( pStream );
  1592. pStream->Write( ';' );
  1593. pStream->NewLine();
  1594. return;
  1595. }
  1596. if ( pChild->IsPointerToBaseType() &&
  1597. (((CG_POINTER *)pChild)->GetPtrType() == PTR_REF) &&
  1598. (((CG_NDR *)pChild->GetChild())->GetCGID() != ID_CG_ENUM) &&
  1599. (((CG_NDR *)pChild->GetChild())->GetCGID() != ID_CG_INT3264) )
  1600. {
  1601. CG_POINTER * pPointer;
  1602. CG_NDR * pBasetype;
  1603. expr_node * pExpr;
  1604. expr_variable * pBufVar;
  1605. expr_variable * pVar;
  1606. pStream->NewLine();
  1607. pPointer = (CG_POINTER *) pChild;
  1608. pBasetype = (CG_NDR *) pPointer->GetChild();
  1609. if ( pBasetype->GetCGID() == ID_CG_GENERIC_HDL )
  1610. pBasetype = (CG_NDR *) pBasetype->GetChild();
  1611. pBufVar = new expr_variable( STUB_MSG_BUFFER_VAR_NAME );
  1612. pVar = new expr_variable( pParamName );
  1613. if ( IsExtraStatusParam() )
  1614. {
  1615. // For the extra (invisible) fault/comm status parameter, that
  1616. // does *not* go on the wire, we need to generate an assignment
  1617. // when unmarshaling on the client (the arg can only be [out]).
  1618. // The value to be assigned is error_status_ok, which maps to 0.
  1619. pExpr = new expr_constant( (long)0 );
  1620. pExpr = new expr_assign( new expr_u_deref( pVar ),
  1621. pExpr );
  1622. pExpr->Print( pStream );
  1623. pStream->Write( ';' );
  1624. pStream->NewLine();
  1625. }
  1626. else
  1627. {
  1628. // For other types generate unmarshaling assignment.
  1629. OutputNdrAlignment( pCCB, WireAlign );
  1630. //
  1631. // Now make the assignment of the pointer to the current buffer
  1632. // pointer (server) or copy the incomming referent's value (client)
  1633. // and increment the buffer pointer.
  1634. //
  1635. pExpr = MakeExpressionOfCastPtrToType( pBasetype->GetType(), pBufVar );
  1636. if ( pCCB->GetCodeGenSide() == CGSIDE_SERVER )
  1637. {
  1638. pExpr = new expr_assign( pVar, pExpr );
  1639. }
  1640. else
  1641. {
  1642. pExpr = new expr_post_incr( pExpr );
  1643. pExpr = new expr_assign(
  1644. new expr_u_deref( pVar ),
  1645. new expr_u_deref( pExpr ) );
  1646. }
  1647. pExpr->Print( pStream );
  1648. pStream->Write( ';' );
  1649. pStream->NewLine();
  1650. if ( pCCB->GetCodeGenSide() == CGSIDE_SERVER )
  1651. {
  1652. pStream->Write( STUB_MSG_BUFFER_VAR_NAME " += " );
  1653. pExpr = new expr_sizeof( pBasetype->GetType() );
  1654. // pExpr = new expr_b_arithmetic( OP_PLUS, pBufVar, pExpr );
  1655. // pExpr = new expr_assign( pBufVar, pExpr );
  1656. pExpr->Print( pStream );
  1657. pStream->Write( ";" );
  1658. pStream->NewLine();
  1659. }
  1660. }
  1661. return;
  1662. }
  1663. if ( pChild->GetCGID() == ID_CG_BC_PTR )
  1664. GenNdrTopLevelAttributeSupport( pCCB );
  1665. pFormatString = pCCB->GetFormatString();
  1666. //
  1667. // If this is a by-value structure or union then use the mangled
  1668. // local pointer variable to the same type.
  1669. //
  1670. if ( pChild->IsStruct() || pChild->IsUnion() ||
  1671. pChild->IsXmitRepOrUserMarshal() )
  1672. {
  1673. if ( !( pCCB->GetCodeGenSide() == CGSIDE_CLIENT && IsParamIn() ) )
  1674. {
  1675. char * pName = new char[strlen(pParamName) + 10];
  1676. strcpy( pName, LOCAL_NAME_POINTER_MANGLE );
  1677. strcat( pName, pParamName );
  1678. pParamName = pName;
  1679. }
  1680. //
  1681. // If this is a regular structure or an encapsulated struct (union)
  1682. // being returned, then zero it out.
  1683. //
  1684. if( (GetCGID() == ID_CG_RETURN) &&
  1685. (pChild->IsStruct() || pChild->IsUnion()) )
  1686. {
  1687. Out_MemsetToZero( pCCB,
  1688. new expr_variable( pParamName, 0 ),
  1689. new expr_sizeof( pChild->GetType() ) );
  1690. }
  1691. }
  1692. FormatOffset = pChild->GetFormatStringOffset();
  1693. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1694. //
  1695. // For ref pointers with no funky attributes, we optimize by calling
  1696. // the pointee's routine directly.
  1697. //
  1698. if ( pChild->IsPointer() && ((CG_POINTER *)pChild)->IsBasicRefPointer() )
  1699. {
  1700. CG_POINTER * pPointer;
  1701. pPointer = (CG_POINTER *) pChild;
  1702. switch ( pPointer->GetCGID() )
  1703. {
  1704. case ID_CG_STRING_PTR :
  1705. if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
  1706. break;
  1707. FormatOffset = pPointer->GetFormatStringOffset() + 2;
  1708. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1709. break;
  1710. case ID_CG_SIZE_STRING_PTR :
  1711. if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
  1712. break;
  1713. FormatOffset = pPointer->GetPointeeFormatStringOffset();
  1714. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1715. break;
  1716. case ID_CG_STRUCT_STRING_PTR :
  1717. break;
  1718. default :
  1719. FormatOffset = pPointer->GetPointeeFormatStringOffset();
  1720. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1721. break;
  1722. }
  1723. }
  1724. //
  1725. // If the param is an omitted cs_tag param, the marshalling code takes
  1726. // care of handling the call to the tag routine to get the actual value.
  1727. // Also, since we don't have the parameter on the stack we don't have a
  1728. // name to pass to Unmarshall so just pass "0" (NULL)
  1729. //
  1730. if ( IsOmittedParam() )
  1731. {
  1732. PNAME pNewName = (PNAME) alloca( sizeof("0 /* */")
  1733. + strlen(pParamName) );
  1734. strcpy( pNewName, "0 /* ");
  1735. strcat( pNewName, pParamName );
  1736. strcat( pNewName, " */");
  1737. pParamName = pNewName;
  1738. fTakeAddress = FALSE;
  1739. }
  1740. Out_NdrUnmarshallCall( pCCB,
  1741. pNdrRoutineNames[NameIndex],
  1742. pParamName,
  1743. FormatOffset,
  1744. fTakeAddress,
  1745. fMustAllocFlag );
  1746. }
  1747. void
  1748. CG_PARAM::GenNdrBufferSizeCall( CCB * pCCB )
  1749. /*++
  1750. Routine Description :
  1751. Outputs a parameter's ndr buffer sizing routine call.
  1752. Arguments :
  1753. pCCB - pointer to the code control block
  1754. --*/
  1755. {
  1756. // BUG BUG, this needs to be cleaned up for NDR64
  1757. MIDL_ASSERT( !pCommand->IsNDR64Run() );
  1758. CG_NDR * pChild;
  1759. FORMAT_STRING * pFormatString;
  1760. PNAME pParamName;
  1761. ID_CG ParamId;
  1762. long NameIndex;
  1763. long FormatOffset;
  1764. BOOL fTakeAddress;
  1765. BOOL fDereference;
  1766. pChild = (CG_NDR *)GetChild();
  1767. ParamId = pChild->GetCGID();
  1768. pParamName = GetResource()->GetResourceName();
  1769. if ( IsParamPartialIgnore() &&
  1770. ( pCCB->GetCodeGenSide() == CGSIDE_CLIENT ) )
  1771. {
  1772. Out_PartialIgnoreClientBufferSize( pCCB, pParamName );
  1773. return;
  1774. }
  1775. //
  1776. // Primitive handle contributes no size.
  1777. //
  1778. if ( (ParamId == ID_CG_PRIMITIVE_HDL) ||
  1779. ((ParamId == ID_CG_PTR) &&
  1780. (((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_PRIMITIVE_HDL)) )
  1781. return;
  1782. //
  1783. // For a generic handle, get the handle data type and then continue.
  1784. //
  1785. if ( ParamId == ID_CG_GENERIC_HDL )
  1786. {
  1787. pChild = (CG_NDR *)pChild->GetChild();
  1788. ParamId = pChild->GetCGID();
  1789. }
  1790. if ( ParamId == ID_CG_CONTEXT_HDL ||
  1791. ((ParamId == ID_CG_PTR) &&
  1792. (((CG_NDR *)pChild->GetChild())->GetCGID() == ID_CG_CONTEXT_HDL)) )
  1793. {
  1794. ISTREAM * pStream = pCCB->GetStream();
  1795. pStream->WriteOnNewLine( STUB_MSG_LENGTH_VAR_NAME " += 20;" );
  1796. pStream->NewLine();
  1797. return;
  1798. }
  1799. if ( pChild->IsSimpleType() )
  1800. {
  1801. ISTREAM * pStream = pCCB->GetStream();
  1802. pStream->WriteOnNewLine( STUB_MSG_LENGTH_VAR_NAME " += 16;" );
  1803. pStream->NewLine();
  1804. return;
  1805. }
  1806. if ( pChild->IsPointerToBaseType() )
  1807. {
  1808. ISTREAM * pStream = pCCB->GetStream();
  1809. pStream->WriteOnNewLine( STUB_MSG_LENGTH_VAR_NAME " += 24;" );
  1810. pStream->NewLine();
  1811. return;
  1812. }
  1813. GenNdrTopLevelAttributeSupport( pCCB );
  1814. pFormatString = pCCB->GetFormatString();
  1815. FormatOffset = pChild->GetFormatStringOffset();
  1816. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1817. //
  1818. // If the param is a by-value struct or union then set the fTakeAddress
  1819. // flag.
  1820. //
  1821. fTakeAddress = pChild->IsStruct() || pChild->IsUnion()
  1822. || pChild->IsXmitRepOrUserMarshal();
  1823. //
  1824. // If the param is an array and we're in the server stub then we
  1825. // must dereference it.
  1826. //
  1827. fDereference = (pCCB->GetCodeGenSide() == CGSIDE_SERVER) &&
  1828. pChild->IsArray();
  1829. //
  1830. // For ref pointers with no funky attributes, we optimize by calling
  1831. // the pointee's routine directly.
  1832. //
  1833. if ( pChild->IsPointer() && ((CG_POINTER *)pChild)->IsBasicRefPointer() )
  1834. {
  1835. CG_POINTER * pPointer;
  1836. pPointer = (CG_POINTER *) pChild;
  1837. switch ( pPointer->GetCGID() )
  1838. {
  1839. case ID_CG_STRING_PTR :
  1840. if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
  1841. break;
  1842. FormatOffset = pPointer->GetFormatStringOffset() + 2;
  1843. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1844. break;
  1845. case ID_CG_SIZE_STRING_PTR :
  1846. if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
  1847. break;
  1848. FormatOffset = pPointer->GetPointeeFormatStringOffset();
  1849. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1850. break;
  1851. case ID_CG_STRUCT_STRING_PTR :
  1852. break;
  1853. default :
  1854. if ( ID_CG_CS_TAG == pPointer->GetChild()->GetCGID() )
  1855. {
  1856. ParamId = ID_CG_CS_TAG;
  1857. break;
  1858. }
  1859. FormatOffset = pPointer->GetPointeeFormatStringOffset();
  1860. NameIndex = (long) pFormatString->GetFormatChar( FormatOffset );
  1861. break;
  1862. }
  1863. }
  1864. if ( ID_CG_CS_TAG == ParamId )
  1865. {
  1866. ISTREAM * pStream = pCCB->GetStream();
  1867. pStream->WriteOnNewLine( STUB_MSG_LENGTH_VAR_NAME " += 4; /* " );
  1868. pStream->Write( pParamName );
  1869. pStream->Write( " */" );
  1870. pStream->NewLine();
  1871. return;
  1872. }
  1873. Out_NdrBufferSizeCall( pCCB,
  1874. pNdrRoutineNames[NameIndex],
  1875. pParamName,
  1876. FormatOffset,
  1877. fTakeAddress,
  1878. fDereference,
  1879. FALSE ); // _StubMsg
  1880. }
  1881. void
  1882. GenDontCallFreeInstAssign(
  1883. CCB * pCCB,
  1884. int SetupValue
  1885. )
  1886. /*++
  1887. a helper routine for GenNdrFreeCall.
  1888. Generates an assignment that sets or resets StubMsg.fDontCallFreeInst.
  1889. --*/
  1890. {
  1891. ISTREAM * pStream = pCCB->GetStream();
  1892. pStream->NewLine();
  1893. pStream->Write( STUB_MESSAGE_VAR_NAME );
  1894. pStream->Write( ".fDontCallFreeInst = " );
  1895. pStream->Write( SetupValue ? "1;"
  1896. : "0;" );
  1897. }
  1898. void
  1899. CG_PARAM::GenNdrFreeCall( CCB * pCCB )
  1900. /*++
  1901. Routine Description :
  1902. Outputs a parameter's ndr free routine call.
  1903. Arguments :
  1904. pCCB - pointer to the code control block
  1905. --*/
  1906. {
  1907. // BUG BUG, this needs to be cleaned up for NDR64
  1908. MIDL_ASSERT( !pCommand->IsNDR64Run() );
  1909. CG_PROC * pProc;
  1910. CG_NDR * pChild;
  1911. FORMAT_STRING * pFormatString;
  1912. PNAME pParamName;
  1913. long Index;
  1914. BOOL fTakeAddress;
  1915. BOOL fDereference;
  1916. pProc = (CG_PROC *) pCCB->GetCGNodeContext();
  1917. //
  1918. // If the proc uses RpcSs then don't emit any freeing code.
  1919. //
  1920. if ( pProc->MustInvokeRpcSSAllocate() )
  1921. return;
  1922. pChild = (CG_NDR *) GetChild();
  1923. if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
  1924. pChild = (CG_NDR *) pChild->GetChild();
  1925. //
  1926. // Check if we need to make a call to an NDR freeing routine for this data.
  1927. //
  1928. if ( pChild->ShouldFreeOffline() ||
  1929. IsParamPartialIgnore() )
  1930. {
  1931. if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
  1932. pChild = (CG_NDR *) pChild->GetChild();
  1933. GenNdrTopLevelAttributeSupport( pCCB );
  1934. pFormatString = pCCB->GetFormatString();
  1935. Index = (long) pFormatString->GetFormatChar(
  1936. pChild->GetFormatStringOffset() );
  1937. pParamName = GetResource()->GetResourceName();
  1938. //
  1939. // If the param is a by-value struct or union then set the fTakeAddress
  1940. // flag.
  1941. //
  1942. fTakeAddress = pChild->IsStruct() || pChild->IsUnion()
  1943. || pChild->IsXmitRepOrUserMarshal();
  1944. fDereference = FALSE;
  1945. if ( GetDontCallFreeInst() )
  1946. GenDontCallFreeInstAssign( pCCB, 1 );
  1947. Out_NdrFreeCall( pCCB,
  1948. pNdrRoutineNames[Index],
  1949. pParamName,
  1950. pChild->GetFormatStringOffset(),
  1951. fTakeAddress,
  1952. fDereference );
  1953. if ( GetDontCallFreeInst() )
  1954. GenDontCallFreeInstAssign( pCCB, 0 );
  1955. }
  1956. //
  1957. // Now generate any needed inline freeing.
  1958. //
  1959. pChild->GenFreeInline( pCCB );
  1960. }
  1961. void
  1962. CG_PARAM::GenNdrTopLevelAttributeSupport(
  1963. CCB * pCCB,
  1964. BOOL fForClearOut )
  1965. /*++
  1966. Routine Description :
  1967. Outputs the assignment(s) to the stub message MaxCount, ActualCount,
  1968. and/or Offset fields, for support of top level conformant and/or
  1969. varying arrays, attributed pointers, and non-encapsulated unions for
  1970. mixed model stubs.
  1971. Arguments :
  1972. pCCB - pointer to the code control block
  1973. --*/
  1974. {
  1975. CG_NDR * pChild;
  1976. ISTREAM * pStream = pCCB->GetStream();
  1977. expr_node * pExpr;
  1978. expr_node * pSizeOrSwitchIsExpr;
  1979. expr_node * pFirstIsExpr;
  1980. expr_node * pLengthIsExpr;
  1981. ID_CG ParamId;
  1982. pChild = (CG_NDR *)GetChild();
  1983. ParamId = pChild->GetCGID();
  1984. // Skip over pointers and generic handles.
  1985. while ( ParamId == ID_CG_PTR || ParamId == ID_CG_GENERIC_HDL )
  1986. {
  1987. pChild = (CG_NDR *) pChild->GetChild();
  1988. ParamId = pChild->GetCGID();
  1989. }
  1990. //
  1991. // Multidimensional conformant/varying arrays and sized pointers of
  1992. // sized pointers need some special handling.
  1993. //
  1994. if ( (pChild->IsArray() && ((CG_ARRAY *)pChild)->IsMultiConfOrVar()) ||
  1995. (pChild->IsPointer() && ((CG_POINTER *)pChild)->IsMultiSize()) )
  1996. {
  1997. CSzBuffer Buffer;
  1998. pStream->NewLine();
  1999. /*
  2000. if ( (ParamId == ID_CG_CONF_ARRAY) ||
  2001. (ParamId == ID_CG_CONF_VAR_ARRAY) ||
  2002. (ParamId == ID_CG_SIZE_PTR) ||
  2003. (ParamId == ID_CG_SIZE_LENGTH_PTR) )
  2004. */
  2005. {
  2006. Buffer.Set(pChild->IsArray() ? "(unsigned long) " : "");
  2007. Buffer.Append("_maxcount_");
  2008. Buffer.Append(GetType()->GetSymName());
  2009. if ( pChild->IsPointer() )
  2010. pExpr = new expr_variable(
  2011. STUB_MESSAGE_VAR_NAME ".SizePtrCountArray" );
  2012. else
  2013. pExpr = new expr_variable(
  2014. STUB_MESSAGE_VAR_NAME ".MaxCount" );
  2015. pExpr = new expr_assign( pExpr, new expr_variable( Buffer ) );
  2016. pExpr->Print( pStream );
  2017. pStream->Write( ';' );
  2018. pStream->NewLine();
  2019. }
  2020. /*
  2021. if ( (ParamId == ID_CG_CONF_VAR_ARRAY) ||
  2022. (ParamId == ID_CG_VAR_ARRAY) ||
  2023. (ParamId == ID_CG_SIZE_LENGTH_PTR) )
  2024. */
  2025. {
  2026. Buffer.Set(pChild->IsArray() ? "(unsigned long) " : "");
  2027. Buffer.Append("_offset_");
  2028. Buffer.Append(GetType()->GetSymName());
  2029. if ( pChild->IsPointer() )
  2030. pExpr = new expr_variable(
  2031. STUB_MESSAGE_VAR_NAME ".SizePtrOffsetArray" );
  2032. else
  2033. pExpr = new expr_variable(
  2034. STUB_MESSAGE_VAR_NAME ".Offset" );
  2035. pExpr = new expr_assign( pExpr, new expr_variable( Buffer ) );
  2036. pExpr->Print( pStream );
  2037. pStream->Write( ';' );
  2038. pStream->NewLine();
  2039. Buffer.Set(pChild->IsArray() ? "(unsigned long) " : "");
  2040. Buffer.Append("_length_");
  2041. Buffer.Append(GetType()->GetSymName());
  2042. if ( pChild->IsPointer() )
  2043. pExpr = new expr_variable(
  2044. STUB_MESSAGE_VAR_NAME ".SizePtrLengthArray" );
  2045. else
  2046. pExpr = new expr_variable(
  2047. STUB_MESSAGE_VAR_NAME ".ActualCount" );
  2048. pExpr = new expr_assign( pExpr, new expr_variable( Buffer ) );
  2049. pExpr->Print( pStream );
  2050. pStream->Write( ';' );
  2051. pStream->NewLine();
  2052. }
  2053. return;
  2054. }
  2055. //
  2056. // We check here if the parameter is a top level attributed array or
  2057. // pointer, a non-encapsulated union or a pointer to a non-encapsulated
  2058. // union. If it isn't, then return.
  2059. //
  2060. switch ( ParamId )
  2061. {
  2062. case ID_CG_CONF_ARRAY :
  2063. case ID_CG_CONF_VAR_ARRAY :
  2064. case ID_CG_VAR_ARRAY :
  2065. case ID_CG_CONF_STRING_ARRAY :
  2066. case ID_CG_SIZE_PTR :
  2067. case ID_CG_SIZE_LENGTH_PTR :
  2068. case ID_CG_SIZE_STRING_PTR :
  2069. case ID_CG_UNION :
  2070. break;
  2071. case ID_CG_BC_PTR :
  2072. if ( pCCB->GetCodeGenSide() == CGSIDE_SERVER )
  2073. return;
  2074. {
  2075. ISTREAM * pStream = pCCB->GetStream();
  2076. expr_node *pExpr, *pSizeExpr;
  2077. CG_BYTE_COUNT_POINTER * pByteCount;
  2078. pByteCount = (CG_BYTE_COUNT_POINTER *) pChild;
  2079. pSizeExpr = MakeExpressionOfCastToTypeName( "unsigned long",
  2080. new expr_variable(
  2081. pByteCount->GetByteCountParam()->GetSymName() ) );
  2082. pExpr = new expr_assign(
  2083. new expr_variable( STUB_MESSAGE_VAR_NAME ".MaxCount" ),
  2084. pSizeExpr );
  2085. pStream->NewLine();
  2086. pExpr->Print( pStream );
  2087. pStream->Write( ';' );
  2088. pStream->NewLine();
  2089. }
  2090. return;
  2091. case ID_CG_IIDIS_INTERFACE_PTR:
  2092. {
  2093. CG_IIDIS_INTERFACE_POINTER * pIfPointer;
  2094. ISTREAM * pStream = pCCB->GetStream();
  2095. pIfPointer = (CG_IIDIS_INTERFACE_POINTER *) pChild;
  2096. if ( ! pIfPointer->GetIIDExpr() )
  2097. return;
  2098. pStream->NewLine();
  2099. if ( pCommand->Is64BitEnv() )
  2100. {
  2101. // _StubMsg.MaxCount = (ULONG_PTR) ( riid );
  2102. pStream->Write( STUB_MESSAGE_VAR_NAME
  2103. ".MaxCount = (ULONG_PTR) ( " );
  2104. }
  2105. else
  2106. {
  2107. // _StubMsg.MaxCount = (unsigned long) ( riid );
  2108. pStream->Write( STUB_MESSAGE_VAR_NAME
  2109. ".MaxCount = (unsigned long) ( " );
  2110. }
  2111. pIfPointer->GetIIDExpr()->Print( pStream );
  2112. pStream->Write( " );" );
  2113. pStream->NewLine();
  2114. }
  2115. return;
  2116. default :
  2117. return;
  2118. }
  2119. pCCB->GetStream()->NewLine();
  2120. switch ( pChild->GetCGID() )
  2121. {
  2122. case ID_CG_CONF_ARRAY :
  2123. pSizeOrSwitchIsExpr =
  2124. ((CG_CONFORMANT_ARRAY *)pChild)->GetSizeIsExpr();
  2125. pFirstIsExpr = NULL;
  2126. pLengthIsExpr = NULL;
  2127. break;
  2128. case ID_CG_CONF_VAR_ARRAY :
  2129. pSizeOrSwitchIsExpr =
  2130. ((CG_CONFORMANT_VARYING_ARRAY *)pChild)->GetSizeIsExpr();
  2131. pFirstIsExpr =
  2132. ((CG_CONFORMANT_VARYING_ARRAY *)pChild)->GetFirstIsExpr();
  2133. pLengthIsExpr =
  2134. ((CG_CONFORMANT_VARYING_ARRAY *)pChild)->GetLengthIsExpr();
  2135. break;
  2136. case ID_CG_VAR_ARRAY :
  2137. pSizeOrSwitchIsExpr = NULL;
  2138. pFirstIsExpr =
  2139. ((CG_VARYING_ARRAY *)pChild)->GetFirstIsExpr();
  2140. pLengthIsExpr =
  2141. ((CG_VARYING_ARRAY *)pChild)->GetLengthIsExpr();
  2142. break;
  2143. case ID_CG_CONF_STRING_ARRAY :
  2144. pSizeOrSwitchIsExpr =
  2145. ((CG_CONFORMANT_STRING_ARRAY *)pChild)->GetSizeIsExpr();
  2146. pFirstIsExpr = NULL;
  2147. pLengthIsExpr = NULL;
  2148. break;
  2149. case ID_CG_SIZE_PTR :
  2150. pSizeOrSwitchIsExpr =
  2151. ((CG_SIZE_POINTER *)pChild)->GetSizeIsExpr();
  2152. pFirstIsExpr = NULL;
  2153. pLengthIsExpr = NULL;
  2154. break;
  2155. case ID_CG_SIZE_LENGTH_PTR :
  2156. pSizeOrSwitchIsExpr =
  2157. ((CG_SIZE_LENGTH_POINTER *)pChild)->GetSizeIsExpr();
  2158. pFirstIsExpr =
  2159. ((CG_SIZE_LENGTH_POINTER *)pChild)->GetFirstIsExpr();
  2160. pLengthIsExpr =
  2161. ((CG_SIZE_LENGTH_POINTER *)pChild)->GetLengthIsExpr();
  2162. break;
  2163. case ID_CG_SIZE_STRING_PTR :
  2164. pSizeOrSwitchIsExpr =
  2165. ((CG_SIZE_STRING_POINTER *)pChild)->GetSizeIsExpr();
  2166. pFirstIsExpr = NULL;
  2167. pLengthIsExpr = NULL;
  2168. break;
  2169. case ID_CG_UNION :
  2170. case ID_CG_PTR :
  2171. pSizeOrSwitchIsExpr = GetSwitchExpr();
  2172. pFirstIsExpr = NULL;
  2173. pLengthIsExpr = NULL;
  2174. break;
  2175. }
  2176. if ( pSizeOrSwitchIsExpr )
  2177. {
  2178. pSizeOrSwitchIsExpr = MakeAttrExprWithNullPtrChecks(
  2179. pSizeOrSwitchIsExpr );
  2180. pSizeOrSwitchIsExpr = MakeExpressionOfCastToTypeName( "unsigned long",
  2181. pSizeOrSwitchIsExpr );
  2182. pExpr = new expr_assign(
  2183. new expr_variable( STUB_MESSAGE_VAR_NAME ".MaxCount" ),
  2184. pSizeOrSwitchIsExpr );
  2185. pExpr->Print( pStream );
  2186. pStream->Write( ';' );
  2187. pStream->NewLine();
  2188. }
  2189. if ( pFirstIsExpr )
  2190. {
  2191. //
  2192. // For NdrClearOutParams we ignore the first_is() & length_is()
  2193. // attributes in case these are [out] and therefore unitialized.
  2194. //
  2195. if ( fForClearOut )
  2196. {
  2197. pStream->Write( STUB_MESSAGE_VAR_NAME ".Offset = 0;" );
  2198. pStream->NewLine();
  2199. }
  2200. else
  2201. {
  2202. pFirstIsExpr = MakeAttrExprWithNullPtrChecks( pFirstIsExpr );
  2203. pFirstIsExpr = MakeExpressionOfCastToTypeName( "unsigned long",
  2204. pFirstIsExpr );
  2205. pExpr = new expr_assign(
  2206. new expr_variable( STUB_MESSAGE_VAR_NAME ".Offset" ),
  2207. pFirstIsExpr );
  2208. pExpr->Print( pStream );
  2209. pStream->Write( ';' );
  2210. pStream->NewLine();
  2211. }
  2212. //
  2213. // Create a LengthIsExpr if one does not already exist.
  2214. //
  2215. if ( ! pLengthIsExpr )
  2216. {
  2217. expr_node * pSize;
  2218. if ( pChild->IsPointer() )
  2219. {
  2220. // Size/length pointer.
  2221. pSize = ((CG_SIZE_LENGTH_POINTER *)pChild)->GetSizeIsExpr();
  2222. }
  2223. else
  2224. {
  2225. // Conformant varying or varying array.
  2226. pSize = ((CG_ARRAY *)pChild)->GetSizeIsExpr();
  2227. }
  2228. pLengthIsExpr =
  2229. new expr_b_arithmetic( OP_MINUS,
  2230. pSize,
  2231. pFirstIsExpr );
  2232. }
  2233. }
  2234. if ( pLengthIsExpr )
  2235. {
  2236. //
  2237. // For NdrClearOutParams we ignore the first_is() & length_is()
  2238. // attributes in case these are [out] and therefore unitialized.
  2239. //
  2240. if ( fForClearOut )
  2241. {
  2242. pStream->Write( STUB_MESSAGE_VAR_NAME ".ActualCount" " = (unsigned long) " );
  2243. pStream->Write( STUB_MESSAGE_VAR_NAME ".MaxCount;" );
  2244. pStream->NewLine();
  2245. }
  2246. else
  2247. {
  2248. pLengthIsExpr = MakeAttrExprWithNullPtrChecks( pLengthIsExpr );
  2249. pLengthIsExpr = MakeExpressionOfCastToTypeName( "unsigned long",
  2250. pLengthIsExpr );
  2251. pExpr = new expr_assign(
  2252. new expr_variable(STUB_MESSAGE_VAR_NAME ".ActualCount"),
  2253. pLengthIsExpr );
  2254. pExpr->Print( pStream );
  2255. pStream->Write( ";" );
  2256. pStream->NewLine();
  2257. }
  2258. }
  2259. }
  2260. expr_node *
  2261. CG_PROC::GenCoreNdrSingleClientCall(
  2262. CCB * pCCB,
  2263. PROC_CALL_PLATFORM Platform )
  2264. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2265. Routine Description:
  2266. Creates the real expression for the ndr single client call.
  2267. Arguments:
  2268. Platform - x86, IA64, alpha, etc.
  2269. An explicit enum type is used to indicate platform.
  2270. Return Value:
  2271. None.
  2272. Notes:
  2273. On risc machines, the compiler passes the parameters in registers,
  2274. therefore the client stub is passed the parameters in registers. The
  2275. interpreter needs arguments on the stack. In order to force a spill of the
  2276. parameters from the registers to the stack, we need to pass addr all the
  2277. parameters to NdrClientCall.
  2278. stub_proc( p1, p2, p3 )
  2279. {
  2280. ...
  2281. NdrClientCall( STUB_DESC *,
  2282. FORMAT_STRING *,
  2283. &p1,
  2284. &p2,
  2285. &p3 );
  2286. ...
  2287. }
  2288. On Alpha the varargs is simply weird. The code generated needs to be
  2289. stub_proc( p1, p2, p3 )
  2290. {
  2291. ...
  2292. NdrClientCall( STUB_DESC *,
  2293. FORMAT_STRING *,
  2294. vlist.a0 );
  2295. ...
  2296. }
  2297. ----------------------------------------------------------------------------*/
  2298. {
  2299. char FormatStringExpr[80];
  2300. expr_proc_call * pCallExpr;
  2301. expr_node * pExpr;
  2302. CG_PARAM * pParam;
  2303. PNAME pFormatName;
  2304. OPTIM_OPTION OptimOptions;
  2305. OptimOptions = GetOptimizationFlags();
  2306. //
  2307. // Now construct the expression for the Ndr call.
  2308. //
  2309. if ( HasAsyncUUID() )
  2310. {
  2311. if ( pCommand->NeedsNDR64Run() )
  2312. pCallExpr = new expr_proc_call( C_NDR64_CALL_RTN_NAME_DCOM_ASYNC );
  2313. else
  2314. pCallExpr = new expr_proc_call( C_NDR_CALL_RTN_NAME_DCOM_ASYNC );
  2315. }
  2316. else if ( HasAsyncHandle() )
  2317. {
  2318. if ( pCommand->NeedsNDR64Run() )
  2319. pCallExpr = new expr_proc_call( C_NDR64_CALL_RTN_NAME_ASYNC );
  2320. else
  2321. pCallExpr = new expr_proc_call( C_NDR_CALL_RTN_NAME_ASYNC );
  2322. }
  2323. else
  2324. {
  2325. if ( pCommand->NeedsNDR64Run() )
  2326. pCallExpr = new expr_proc_call ( C_NDR64_CALL_RTN_NAME );
  2327. else
  2328. {
  2329. if ( OptimOptions & OPTIMIZE_INTERPRETER_V2 )
  2330. pCallExpr = new expr_proc_call( C_NDR_CALL_RTN_NAME_V2 );
  2331. else
  2332. pCallExpr = new expr_proc_call( C_NDR_CALL_RTN_NAME );
  2333. }
  2334. }
  2335. if ( ! pCommand->NeedsNDR64Run() )
  2336. {
  2337. //
  2338. // Stub Descriptor
  2339. //
  2340. pExpr = new expr_variable( pCCB->GetInterfaceCG()->GetStubDescName() );
  2341. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  2342. pExpr = MakeExpressionOfCastToTypeName(PSTUB_DESC_STRUCT_TYPE_NAME, pExpr);
  2343. pCallExpr->SetParam( new expr_param( pExpr ) );
  2344. sprintf( FormatStringExpr,
  2345. "(PFORMAT_STRING) &%s[%d]",
  2346. PROC_FORMAT_STRING_STRING_FIELD,
  2347. GetFormatStringOffset() );
  2348. pFormatName = new char [strlen( FormatStringExpr) + 1];
  2349. strcpy( pFormatName, FormatStringExpr );
  2350. pCallExpr->SetParam( new expr_param(
  2351. new expr_variable( pFormatName ) ) );
  2352. }
  2353. else
  2354. {
  2355. pExpr = new expr_variable ( pCCB->GetInterfaceCG()->GetProxyInfoName() );
  2356. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  2357. pExpr = MakeExpressionOfCastToTypeName(PMIDL_PROXY_INFO_TYPE_NAME, pExpr);
  2358. pCallExpr->SetParam( new expr_param( pExpr ) );
  2359. pExpr = new expr_constant( (long) ProcNum );
  2360. pCallExpr->SetParam ( new expr_param ( pExpr ) );
  2361. if ( HasComplexReturnType() && !HasAsyncHandle() )
  2362. {
  2363. pExpr = new expr_variable( RETURN_VALUE_VAR_NAME );
  2364. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  2365. }
  2366. else
  2367. {
  2368. pExpr = new expr_constant( (long) 0 );
  2369. }
  2370. pCallExpr->SetParam ( new expr_param ( pExpr ) );
  2371. }
  2372. // If this is an object interface the first param is an implicit
  2373. // this param.
  2374. if( IsObject() )
  2375. {
  2376. pExpr = new expr_variable("This");
  2377. if( PROC_PLATFORM_IA64 != Platform )
  2378. {
  2379. pExpr = new expr_u_address( pExpr );
  2380. }
  2381. pExpr = MakeCastExprPtrToUChar( pExpr );
  2382. pCallExpr->SetParam( new expr_param( pExpr ) );
  2383. }
  2384. /************************************************************************
  2385. If this is a risc platform, then
  2386. if there are actual parameters,
  2387. take the address of each of them
  2388. else
  2389. if it is not an object interface,
  2390. push a 0
  2391. else
  2392. do nothing. since we have already pushed &this.
  2393. else // if this is not a risc platform
  2394. if there are actual parameters
  2395. take address of first.
  2396. else
  2397. if it is non object procedure,
  2398. push a 0,
  2399. else
  2400. do nothing since for an object proc we have already pushed &this.
  2401. ************************************************************************/
  2402. if ( PROC_PLATFORM_IA64 == Platform )
  2403. {
  2404. ITERATOR I;
  2405. if ( GetMembers(I))
  2406. {
  2407. while (ITERATOR_GETNEXT(I, pParam))
  2408. {
  2409. // Don't include cs_tag params when there is a tag routine
  2410. if ( GetCSTagRoutine() && pParam->IsSomeCSTag() )
  2411. continue;
  2412. // Don't push the fake parameter that was added for complex
  2413. // return types
  2414. if ( HasComplexReturnType() && NULL == pParam->GetSibling() )
  2415. continue;
  2416. pExpr = new expr_variable(
  2417. pParam->GetResource()->GetResourceName());
  2418. pCallExpr->SetParam(new expr_param(pExpr));
  2419. }
  2420. }
  2421. else if ( !IsObject() )
  2422. {
  2423. pExpr = new expr_constant( 0L );
  2424. pCallExpr->SetParam( new expr_param( pExpr ) );
  2425. }
  2426. }
  2427. else if( !IsObject() )
  2428. {
  2429. pParam = (CG_PARAM *) GetChild();
  2430. // Make sure that this is not a cs_tag parameter that is being
  2431. // omitted because there is a tag routine,
  2432. if ( GetCSTagRoutine() )
  2433. {
  2434. while ( pParam && pParam->IsSomeCSTag() )
  2435. pParam = (CG_PARAM *) pParam->GetSibling();
  2436. }
  2437. if( pParam )
  2438. {
  2439. pExpr = new expr_u_address (
  2440. new expr_variable(
  2441. pParam->GetResource()->GetResourceName()));
  2442. pExpr = MakeCastExprPtrToUChar( pExpr );
  2443. pCallExpr->SetParam( new expr_param( pExpr ) );
  2444. }
  2445. else
  2446. {
  2447. pExpr = new expr_constant( 0L );
  2448. pExpr = MakeCastExprPtrToUChar( pExpr );
  2449. pCallExpr->SetParam( new expr_param( pExpr ) );
  2450. }
  2451. }
  2452. // Assign the return value if one exists.
  2453. expr_node * pFinalExpr;
  2454. if ( GetReturnType() && !HasComplexReturnType() )
  2455. {
  2456. if ( HasAsyncHandle() )
  2457. {
  2458. bool fIsErrorStatus = false;
  2459. if ( GetReturnType()->GetChild()->GetCGID() != ID_CG_CONTEXT_HDL )
  2460. {
  2461. fIsErrorStatus = GetReturnType()->GetChild()->GetType()->GetBasicType()->NodeKind() == NODE_E_STATUS_T;
  2462. }
  2463. if ( fIsErrorStatus || GetCGID() == ID_CG_OBJECT_PROC )
  2464. {
  2465. pFinalExpr = new expr_assign(
  2466. new expr_variable( RETURN_VALUE_VAR_NAME ),
  2467. pCallExpr );
  2468. }
  2469. else
  2470. {
  2471. pFinalExpr = pCallExpr;
  2472. }
  2473. }
  2474. else
  2475. {
  2476. pFinalExpr = new expr_assign(
  2477. new expr_variable( RETURN_VALUE_VAR_NAME ),
  2478. pCallExpr );
  2479. }
  2480. }
  2481. else
  2482. pFinalExpr = pCallExpr;
  2483. return pFinalExpr;
  2484. }
  2485. void CG_PROC::SetupFormatStrings( CCB * pCCB )
  2486. {
  2487. if (!cRefSaved++)
  2488. {
  2489. if(!pSavedProcFormatString)
  2490. {
  2491. pSavedProcFormatString = pCCB->GetProcFormatString();
  2492. pSavedFormatString = pCCB->GetFormatString();
  2493. }
  2494. }
  2495. }
  2496. void CG_PROC::UnsetupFormatStrings(CCB * pCCB )
  2497. {
  2498. if (cRefSaved)
  2499. cRefSaved--;
  2500. if (!cRefSaved)
  2501. {
  2502. pCCB->SetProcFormatString(pSavedProcFormatString);
  2503. pCCB->SetFormatString(pSavedFormatString);
  2504. }
  2505. }
  2506. // --------------------------------------------------
  2507. // Routine used for generation of NT 3.5 and NT 3.51
  2508. // procedure format strings.
  2509. // --------------------------------------------------
  2510. void
  2511. CG_PROC::GenNdrFormatV1( CCB * pCCB )
  2512. /*++
  2513. Routine Description :
  2514. Generates the procedure format strings usable on NT 3.5 and
  2515. NT 3.51 systems.
  2516. Arguments :
  2517. pCCB - pointer to the code control block
  2518. --*/
  2519. {
  2520. CG_ITERATOR Iterator;
  2521. CG_PARAM * pParam;
  2522. FORMAT_STRING * pProcFormatString;
  2523. CG_NDR * pOldCGNodeContext;
  2524. short ParamNum;
  2525. SetupFormatStrings(pCCB);
  2526. if ( GetFormatStringOffset() != -1 )
  2527. {
  2528. UnsetupFormatStrings(pCCB);
  2529. return;
  2530. }
  2531. pCCB->SetInObjectInterface( IsObject() );
  2532. pOldCGNodeContext = pCCB->SetCGNodeContext( this );
  2533. //
  2534. // If this procedure uses an explicit handle then set the
  2535. // NdrBindDescriptionOffset to 0 so that it will not try to output it's
  2536. // description when given the GenNdrParamOffLine method in the loop below.
  2537. // It's description must be part of the procedure description.
  2538. //
  2539. if ( GetHandleUsage() == HU_EXPLICIT )
  2540. {
  2541. CG_HANDLE * pHandle = GetHandleClassPtr();
  2542. pHandle->SetNdrBindDescriptionOffset( 0 );
  2543. if ( pHandle->GetCGID() == ID_CG_CONTEXT_HDL )
  2544. {
  2545. // The context handle directs the call.
  2546. ((CG_CONTEXT_HANDLE *)pHandle)->SetCannotBeNull();
  2547. }
  2548. }
  2549. GetMembers( Iterator );
  2550. ParamNum = 0;
  2551. //
  2552. // Generate the offline portion of the format string for all of the params.
  2553. //
  2554. while( ITERATOR_GETNEXT( Iterator, pParam ) )
  2555. {
  2556. CG_NDR * pChild;
  2557. CG_NDR * pOldPlaceholder;
  2558. if (pParam->IsAsyncHandleParam())
  2559. continue;
  2560. pParam->SetParamNumber( ParamNum++ );
  2561. pChild = (CG_NDR *) pParam->GetChild();
  2562. pCCB->SetCurrentParam( (CG_PARAM *) pParam );
  2563. pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
  2564. pChild->GenNdrParamOffline( pCCB );
  2565. pCCB->SetCurrentParam( 0 );
  2566. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  2567. }
  2568. //
  2569. // Generate the format string for the return type if needed.
  2570. //
  2571. if ( GetReturnType() )
  2572. {
  2573. CG_NDR * pChild;
  2574. CG_NDR * pOldPlaceholder;
  2575. GetReturnType()->SetParamNumber( ParamNum );
  2576. pChild = (CG_NDR *) GetReturnType()->GetChild();
  2577. pCCB->SetCurrentParam( GetReturnType() );
  2578. pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetReturnType() );
  2579. pChild->GenNdrParamOffline( pCCB );
  2580. pCCB->SetCurrentParam( 0 );
  2581. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  2582. }
  2583. pProcFormatString = pCCB->GetProcFormatString();
  2584. SetFormatStringOffset( pProcFormatString->GetCurrentOffset() );
  2585. //
  2586. // Generate procedure description stuff for the interpreter if needed.
  2587. //
  2588. if ( (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER)
  2589. || HasAPicklingAttribute() )
  2590. GenNdrFormatProcInfo( pCCB );
  2591. ITERATOR_INIT( Iterator );
  2592. SetFormatStringParamStart( pProcFormatString->GetCurrentOffset() );
  2593. //
  2594. // Now generate the param info at the end of the format string.
  2595. //
  2596. while( ITERATOR_GETNEXT( Iterator, pParam ) )
  2597. {
  2598. CG_NDR * pChild;
  2599. CG_NDR * pOldPlaceholder;
  2600. if ( pParam->IsExtraStatusParam() || pParam->IsAsyncHandleParam() )
  2601. continue;
  2602. pChild = (CG_NDR *) pParam->GetChild();
  2603. if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
  2604. pChild = (CG_NDR *) pChild->GetChild();
  2605. //
  2606. // Ouput the param directional attribute.
  2607. //
  2608. if ( ! pParam->IsParamOut() )
  2609. {
  2610. if ( pParam->GetDontCallFreeInst() )
  2611. pProcFormatString->PushFormatChar( FC_IN_PARAM_NO_FREE_INST );
  2612. else
  2613. if ( pChild->IsSimpleType() ||
  2614. pChild->GetCGID() == ID_CG_PRIMITIVE_HDL )
  2615. pProcFormatString->PushFormatChar( FC_IN_PARAM_BASETYPE );
  2616. else
  2617. pProcFormatString->PushFormatChar( FC_IN_PARAM );
  2618. }
  2619. else
  2620. {
  2621. if ( pParam->IsParamPartialIgnore() )
  2622. {
  2623. pProcFormatString->PushFormatChar( FC_PARTIAL_IGNORE_PARAM );
  2624. }
  2625. else
  2626. {
  2627. if ( ! pParam->IsParamIn() )
  2628. pProcFormatString->PushFormatChar( FC_OUT_PARAM );
  2629. if ( pParam->IsParamIn() && pParam->IsParamOut() )
  2630. pProcFormatString->PushFormatChar( FC_IN_OUT_PARAM );
  2631. }
  2632. }
  2633. pOldPlaceholder = pCCB->SetLastPlaceholderClass( pParam );
  2634. pChild->GenNdrParamDescriptionOld( pCCB );
  2635. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  2636. }
  2637. if ( GetReturnType() )
  2638. {
  2639. CG_NDR * pChild;
  2640. CG_NDR * pOldPlaceholder;
  2641. pChild = (CG_NDR *) GetReturnType()->GetChild();
  2642. if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
  2643. pChild = (CG_NDR *) pChild->GetChild();
  2644. if ( pChild->IsSimpleType() )
  2645. pProcFormatString->PushFormatChar( FC_RETURN_PARAM_BASETYPE );
  2646. else
  2647. pProcFormatString->PushFormatChar( FC_RETURN_PARAM );
  2648. pOldPlaceholder = pCCB->SetLastPlaceholderClass( GetReturnType() );
  2649. pChild->GenNdrParamDescriptionOld( pCCB );
  2650. pCCB->SetLastPlaceholderClass( pOldPlaceholder );
  2651. }
  2652. else
  2653. {
  2654. pProcFormatString->PushFormatChar( FC_END );
  2655. pProcFormatString->PushFormatChar( FC_PAD );
  2656. }
  2657. pCCB->SetCGNodeContext( pOldCGNodeContext );
  2658. pCCB->SetInObjectInterface( FALSE );
  2659. SetFormatStringEndOffset( pProcFormatString->GetCurrentOffset() );
  2660. // save delta, in case the routine is optimized
  2661. short usParamStartDelta = (short) ( GetFormatStringParamStart() -
  2662. GetFormatStringOffset() );
  2663. pProcFormatString->OptimizeFragment( this );
  2664. // Set param start!!!
  2665. SetFormatStringParamStart( GetFormatStringOffset() + usParamStartDelta );
  2666. UnsetupFormatStrings(pCCB);
  2667. }