Leaked source code of windows server 2003
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.

1253 lines
34 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. pickle.cxx
  5. Abstract:
  6. Generates stub routines to call the pickle engine.
  7. Notes:
  8. History:
  9. Mar-22-1994 VibhasC Created
  10. ----------------------------------------------------------------------------*/
  11. /****************************************************************************
  12. * include files
  13. ***************************************************************************/
  14. #include "becls.hxx"
  15. #pragma hdrstop
  16. #pragma warning ( disable : 4127 )
  17. #include "szbuffer.h"
  18. /****************************************************************************
  19. * local definitions
  20. ***************************************************************************/
  21. /****************************************************************************
  22. * local data
  23. ***************************************************************************/
  24. /****************************************************************************
  25. * externs
  26. ***************************************************************************/
  27. /****************************************************************************/
  28. CG_STATUS
  29. CG_ENCODE_PROC::GenClientStubV1(
  30. CCB * pCCB )
  31. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  32. Routine Description:
  33. Generate DCE style procedure pickling stub code for the V1 interpreter.
  34. Arguments:
  35. pCCB - The code gen controller block.
  36. Return Value:
  37. CG_OK
  38. Notes:
  39. ----------------------------------------------------------------------------*/
  40. {
  41. ISTREAM * pStream = pCCB->GetStream();
  42. // Register this procedure as a proc-encoding procedure.
  43. pCCB->RegisterEncodeDecodeProc( this );
  44. // Generate the format strings.
  45. MIDL_ASSERT( pCommand->IsNDRRun() );
  46. GenNdrFormat( pCCB );
  47. // Print the prolog of procedure.
  48. Out_ClientProcedureProlog( pCCB, GetType() );
  49. // If there exists a return type, declare a local resource of that
  50. // type.
  51. if( GetReturnType() )
  52. {
  53. node_id *node = MakeIDNode( RETURN_VALUE_VAR_NAME, GetReturnType()->GetType() );
  54. pStream->Write( " " );
  55. node->PrintType(
  56. (PRT_PARAM_WITH_TYPE | PRT_CSTUB_PREFIX),
  57. pStream,
  58. (node_skl *)0 );
  59. pStream->NewLine();
  60. }
  61. //
  62. // The V1 interpreter calls NdrMesProcEncodeDecode and passes the addresses
  63. // of all the parameters that were passed to the stub.
  64. //
  65. GenMesProcEncodeDecodeCall( pCCB, PROC_PLATFORM_V1_INTERPRETER );
  66. GenEpilog( pCCB );
  67. return CG_OK;
  68. }
  69. CG_STATUS
  70. CG_ENCODE_PROC::GenClientStub(
  71. CCB * pCCB )
  72. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  73. Routine Description:
  74. Generate DCE style procedure pickling stub code.
  75. Arguments:
  76. pCCB - The code gen controller block.
  77. Return Value:
  78. CG_OK
  79. Notes:
  80. ----------------------------------------------------------------------------*/
  81. {
  82. if ( ! ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) )
  83. return GenClientStubV1( pCCB );
  84. ISTREAM * pStream = pCCB->GetStream();
  85. // Register this procedure as a proc-encoding procedure.
  86. pCCB->RegisterEncodeDecodeProc( this );
  87. // Generate the format strings.
  88. if ( pCommand->IsNDRRun() )
  89. {
  90. GenNdrFormat( pCCB );
  91. }
  92. else
  93. {
  94. pCCB->GetNdr64Format()->Generate( this );
  95. }
  96. // Print the prolog of procedure.
  97. Out_ClientProcedureProlog( pCCB, GetType() );
  98. // If there exists a return type, declare a local resource of that
  99. // type.
  100. if( GetReturnType() || HasComplexReturnType() )
  101. {
  102. pStream->IndentInc();
  103. if ( HasComplexReturnType() )
  104. {
  105. pStream->NewLine();
  106. ( (node_proc *) GetType() )
  107. ->GetReturnType()->PrintType(PRT_DECL, pStream);
  108. }
  109. else
  110. pStream->WriteOnNewLine( "CLIENT_CALL_RETURN " );
  111. pStream->Write( RETURN_VALUE_VAR_NAME ";" );
  112. pStream->IndentDec();
  113. pStream->NewLine( 2 );
  114. }
  115. // Generate ia64 or x86 code
  116. if ( pCommand->Is64BitEnv() )
  117. {
  118. GenMesProcEncodeDecodeCall( pCCB, PROC_PLATFORM_IA64) ;
  119. }
  120. else
  121. {
  122. GenMesProcEncodeDecodeCall( pCCB, PROC_PLATFORM_X86 );
  123. }
  124. if ( GetReturnType() || HasComplexReturnType() )
  125. {
  126. CG_NDR* pNdr;
  127. node_skl* pType;
  128. if ( GetReturnType() )
  129. {
  130. pNdr = (CG_NDR *) GetReturnType()->GetChild();
  131. pType = GetReturnType()->GetType();
  132. }
  133. pStream->NewLine( 2 );
  134. pStream->Write("return ");
  135. //
  136. // byval structures, unions, floats, doubles
  137. //
  138. if ( HasComplexReturnType() )
  139. {
  140. pStream->Write( RETURN_VALUE_VAR_NAME ";");
  141. }
  142. //
  143. // Base type return value.
  144. //
  145. else if ( pNdr->IsSimpleType() )
  146. {
  147. pType->PrintType( PRT_CAST_TO_TYPE, pStream );
  148. pStream->Write( RETURN_VALUE_VAR_NAME ".Simple;" );
  149. }
  150. //
  151. // old-style byval structs and unions
  152. //
  153. else if ( pNdr->IsStruct() || pNdr->IsUnion() )
  154. {
  155. expr_node * pExpr;
  156. pExpr = new expr_variable( RETURN_VALUE_VAR_NAME ".Pointer" );
  157. pExpr = MakeDerefExpressionOfCastPtrToType( pType, pExpr );
  158. pExpr->Print( pStream );
  159. pStream->Write( ';' );
  160. }
  161. //
  162. // Otherwise pointer or array.
  163. //
  164. else
  165. {
  166. pType->PrintType( PRT_CAST_TO_TYPE, pStream );
  167. pStream->Write( RETURN_VALUE_VAR_NAME ".Pointer;" );
  168. }
  169. }
  170. pStream->IndentDec();
  171. pStream->WriteOnNewLine("}");
  172. return CG_OK;
  173. }
  174. CG_STATUS
  175. CG_ENCODE_PROC::GenMesProcEncodeDecodeCall(
  176. CCB * pCCB,
  177. PROC_CALL_PLATFORM Platform )
  178. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  179. Routine Description:
  180. Generate DCE style procedure pickling stub code.
  181. Arguments:
  182. pCCB - The code gen controller block.
  183. Platform - ia64, etc
  184. Return Value:
  185. CG_OK
  186. Notes:
  187. ----------------------------------------------------------------------------*/
  188. {
  189. expr_proc_call * pProc;
  190. node_skl * pType;
  191. expr_node * pExpr;
  192. CG_ITERATOR I;
  193. CG_PARAM * pCG;
  194. ISTREAM * pStream = pCCB->GetStream();
  195. PNAME pHandleName;
  196. RESOURCE * pReturnResource = 0;
  197. bool fOutputConstantZero = true;
  198. //
  199. // Generate a call to the single encode proc engine call.
  200. if ( pCommand->NeedsNDR64Run() )
  201. pProc = new expr_proc_call( "NdrMesProcEncodeDecode3" );
  202. else if ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 )
  203. pProc = new expr_proc_call( PROC_ENCODE_DECODE_RTN_NAME2 );
  204. else
  205. pProc = new expr_proc_call( PROC_ENCODE_DECODE_RTN_NAME );
  206. // Handle. If the handle is explicit, then it must be a MIDL_ES_HANDLE
  207. if( GetHandleUsage() == HU_EXPLICIT )
  208. {
  209. pHandleName = SearchForBindingParam()->GetName();
  210. pType = MakeIDNodeFromTypeName( pHandleName,
  211. MIDL_ES_HANDLE_TYPE_NAME );
  212. }
  213. else
  214. {
  215. MIDL_ASSERT( pCCB->GetInterfaceCG()->GetImplicitHandle() != 0 );
  216. pType = (node_id *)pCCB->GetInterfaceCG()->GetImplicitHandle()->
  217. GetHandleIDOrParam();
  218. pHandleName = pType->GetSymName();
  219. }
  220. pProc->SetParam( new expr_variable( pHandleName, pType ) );
  221. // ProcEncodeDecode3 needs a proxy info and a proc number. 1 and 2
  222. // need a stub descriptor and a format string
  223. if ( pCommand->NeedsNDR64Run() )
  224. {
  225. long ProcNum = GetProcNum();
  226. pExpr = new expr_variable(pCCB->GetInterfaceCG()->GetProxyInfoName());
  227. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  228. pExpr = MakeExpressionOfCastToTypeName(
  229. PMIDL_PROXY_INFO_TYPE_NAME,
  230. pExpr);
  231. pProc->SetParam( new expr_param( pExpr ) );
  232. pProc->SetParam( new expr_param( new expr_constant( ProcNum ) ) );
  233. if ( HasComplexReturnType() )
  234. {
  235. pExpr = new expr_variable( RETURN_VALUE_VAR_NAME );
  236. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  237. }
  238. else
  239. {
  240. pExpr = new expr_param( new expr_constant( (long) 0 ) );
  241. }
  242. pProc->SetParam( pExpr );
  243. }
  244. else
  245. {
  246. // Stub descriptor.
  247. pExpr = new RESOURCE( pCCB->GetInterfaceCG()->GetStubDescName(),
  248. (node_skl *)0 );
  249. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  250. pExpr = MakeExpressionOfCastToTypeName( PSTUB_DESC_STRUCT_TYPE_NAME,
  251. pExpr );
  252. pProc->SetParam( pExpr );
  253. // Offset into the format string.
  254. pExpr = Make_1_ArrayExpressionFromVarName(
  255. PROC_FORMAT_STRING_STRING_FIELD,
  256. GetFormatStringOffset() );
  257. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  258. pExpr = MakeExpressionOfCastToTypeName(
  259. PFORMAT_STRING_TYPE_NAME,
  260. pExpr );
  261. pProc->SetParam( pExpr );
  262. }
  263. switch ( Platform )
  264. {
  265. case PROC_PLATFORM_V1_INTERPRETER:
  266. {
  267. // Parameters to the engine are the address of each of the parameters to
  268. // this procedure. If there is no parameter AND no return type, push a
  269. // null (0).
  270. if( GetMembers( I ) )
  271. {
  272. fOutputConstantZero = false;
  273. while( ITERATOR_GETNEXT( I, pCG ) )
  274. {
  275. pExpr = new expr_variable( pCG->GetType()->GetSymName(),
  276. pCG->GetType());
  277. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  278. pExpr = MakeCastExprPtrToUChar( pExpr );
  279. pProc->SetParam( pExpr );
  280. }
  281. }
  282. break;
  283. }
  284. case PROC_PLATFORM_IA64:
  285. {
  286. // Parameters to the engine are the actual parameter to this
  287. // this procedure. If there is no parameter AND no return type, push a
  288. // null (0).
  289. if( GetMembers( I ) )
  290. {
  291. fOutputConstantZero = false;
  292. while( ITERATOR_GETNEXT( I, pCG ) )
  293. {
  294. pExpr = new expr_variable( pCG->GetType()->GetSymName(),
  295. pCG->GetType());
  296. pProc->SetParam( pExpr );
  297. }
  298. }
  299. break;
  300. }
  301. default: // PROC_PLATFORM_DEFAULT (i.e. x86)
  302. {
  303. CG_PARAM * pParam = (CG_PARAM *) GetChild();
  304. if (NULL != pParam)
  305. {
  306. fOutputConstantZero = false;
  307. pExpr = new expr_variable( pParam->GetType()->GetSymName(), pParam->GetType() );
  308. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  309. pExpr = MakeCastExprPtrToUChar( pExpr );
  310. pProc->SetParam( pExpr );
  311. }
  312. }
  313. break;
  314. }
  315. //
  316. // If there is a return value, for the V1 interpreter add another
  317. // parameter to the generated procedure expression. For the V2
  318. // interpreter assign the return value from the engine to the local
  319. // return value variable.
  320. //
  321. expr_node *pFinalExpr = pProc;
  322. if( GetReturnType() && !HasComplexReturnType() )
  323. {
  324. if ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 )
  325. {
  326. pFinalExpr = new expr_assign(
  327. new expr_variable( RETURN_VALUE_VAR_NAME ),
  328. pProc );
  329. }
  330. else
  331. {
  332. pReturnResource = new RESOURCE( RETURN_VALUE_VAR_NAME,
  333. GetReturnType()->GetType() );
  334. pExpr = MakeAddressExpressionNoMatterWhat( pReturnResource );
  335. pExpr = MakeCastExprPtrToUChar( pExpr );
  336. pProc->SetParam( pExpr );
  337. }
  338. }
  339. else if (fOutputConstantZero )
  340. {
  341. pProc->SetParam( new expr_constant( 0L ) );
  342. }
  343. // Now print the call out.
  344. pStream->IndentInc();
  345. pStream->NewLine();
  346. pFinalExpr->PrintCall( pStream, 0, 0 );
  347. pStream->NewLine();
  348. pStream->IndentDec();
  349. return CG_OK;
  350. }
  351. CG_STATUS
  352. CG_TYPE_ENCODE_PROC::GenClientStub(
  353. CCB * pCCB )
  354. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  355. Routine Description:
  356. Generate the client side type encoding stub for this proc.
  357. Arguments:
  358. pCCB - The code gen controller block.
  359. Return Value:
  360. CG_OK
  361. Notes:
  362. This proc node hanging under the encode interface node is really a dummy
  363. proc, put in so that the format string generator can have a placeholder
  364. node to look at.
  365. ----------------------------------------------------------------------------*/
  366. {
  367. return ((CG_PARAM *)GetChild())->GenTypeEncodingStub( pCCB );
  368. }
  369. CG_STATUS
  370. CG_PARAM::GenTypeEncodingStub(
  371. CCB * pCCB )
  372. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  373. Routine Description:
  374. Generate the client side type encoding stub for this param.
  375. Arguments:
  376. pCCB - The code gen controller block.
  377. Return Value:
  378. CG_OK
  379. Notes:
  380. This param is really a dummy param, put in so that the format string
  381. generator can have a placeholder node to look at.
  382. ----------------------------------------------------------------------------*/
  383. {
  384. CG_STATUS Status;
  385. CG_NDR * pLast = pCCB->SetLastPlaceholderClass( this );
  386. Status = ((CG_TYPE_ENCODE *)GetChild())->GenTypeEncodingStub( pCCB );
  387. pCCB->SetLastPlaceholderClass( pLast );
  388. return Status;
  389. }
  390. CG_STATUS
  391. CG_TYPE_ENCODE::GenTypeEncodingStub(
  392. CCB * pCCB )
  393. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  394. Routine Description:
  395. Generate the pickling stubs for a given type.
  396. Arguments:
  397. pCCB - A pointer to the code generator control block.
  398. Return Value:
  399. CG_OK
  400. Notes:
  401. Emit the Type_Encode(), Type_Size() and Type_Decode() routines.
  402. If the encode is needed, then sizing is needed too !.
  403. ----------------------------------------------------------------------------*/
  404. {
  405. CG_NDR * pChild = (CG_NDR *)GetChild();
  406. // Generate the ndr format for the types.
  407. if( ! pChild->IsSimpleType() )
  408. {
  409. if ( pCommand->IsNDRRun() )
  410. pChild->GenNdrFormat( pCCB );
  411. else
  412. pCCB->GetNdr64Format()->Generate( pChild );
  413. // Register this type so we can output a table of type offsets later
  414. if ( pCommand->NeedsNDR64Run() )
  415. TypeIndex = pCCB->RegisterPickledType( this );
  416. }
  417. // Check if implicit binding exists.
  418. if( pCCB->GetInterfaceCG()->GetImplicitHandle() )
  419. {
  420. SetHasImplicitHandle();
  421. }
  422. // Create a resource dictionary database.
  423. pCCB->SetResDictDatabase( new RESOURCE_DICT_DATABASE );
  424. pCCB->ClearParamResourceDict();
  425. if ( ! pCCB->HasTypePicklingInfoBeenEmitted() &&
  426. ( pCommand->GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) )
  427. {
  428. Out_TypePicklingInfo( pCCB );
  429. pCCB->SetTypePicklingInfoEmitted();
  430. }
  431. // If the type has [encode] on it, generate the sizing and encode routines.
  432. if( IsEncode() )
  433. {
  434. // Allocate standard resources for type encoding.
  435. AllocateEncodeResources( pCCB );
  436. // Generate the sizing and encode routines.
  437. GenTypeSize( pCCB );
  438. GenTypeEncode( pCCB );
  439. }
  440. pCCB->ClearParamResourceDict();
  441. // If the type has [decode] on it, generate the decode routine.
  442. if( IsDecode() )
  443. {
  444. // Allocate standard resources for type decoding.
  445. AllocateEncodeResources( pCCB );
  446. GenTypeDecode( pCCB );
  447. GenTypeFree( pCCB );
  448. }
  449. return CG_OK;
  450. }
  451. CG_STATUS
  452. CG_TYPE_ENCODE::GenTypeSize(
  453. CCB * pCCB )
  454. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  455. Routine Description:
  456. Generate the type sizing routine for the type.
  457. Arguments:
  458. pCCB - The code gen controller block.
  459. Return Value:
  460. CG_OK
  461. Notes:
  462. ----------------------------------------------------------------------------*/
  463. {
  464. ISTREAM * pStream = pCCB->GetStream();
  465. PNAME pName;
  466. TYPE_ENCODE_INFO * pTEInfo = new TYPE_ENCODE_INFO;
  467. // Generate the standard prototype. This really means emit the proto of
  468. // the proc in the stub file. Remember, a real proc node does not exist
  469. // for this pickling type. So we emit a prototype by hand (so to speak).
  470. // The body of the function is output later,
  471. GenStdMesPrototype( pCCB,
  472. (pName = GetType()->GetSymName()),
  473. TYPE_ALIGN_SIZE_CODE,
  474. HasImplicitHandle()
  475. );
  476. pStream->NewLine();
  477. pStream->Write( '{' );
  478. pStream->IndentInc();
  479. pStream->NewLine();
  480. // The procedure body consists of a single procedure call.
  481. expr_proc_call * pProc = CreateStdMesEngineProc( pCCB, TYPE_ALIGN_SIZE_CODE);
  482. pStream->Write( "return " );
  483. pProc->PrintCall( pStream, 0, 0 );
  484. // Terminate the procedure body.
  485. pStream->IndentDec();
  486. pStream->NewLine();
  487. pStream->Write( '}' );
  488. pStream->NewLine();
  489. // Register the routine with the ccb to enable emitting of prototypes.
  490. pTEInfo->pName = pName;
  491. pTEInfo->Flags = HasImplicitHandle() ? TYPE_ENCODE_WITH_IMPL_HANDLE : TYPE_ENCODE_FLAGS_NONE;
  492. pCCB->RegisterTypeAlignSize( pTEInfo );
  493. return CG_OK;
  494. }
  495. CG_STATUS
  496. CG_TYPE_ENCODE::GenTypeEncode(
  497. CCB * pCCB )
  498. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  499. Routine Description:
  500. Generate the type encoding routine for the type.
  501. Arguments:
  502. pCCB - The code gen controller block.
  503. Return Value:
  504. CG_OK
  505. Notes:
  506. ----------------------------------------------------------------------------*/
  507. {
  508. ISTREAM * pStream = pCCB->GetStream();
  509. PNAME pName;
  510. TYPE_ENCODE_INFO * pTEInfo = new TYPE_ENCODE_INFO;
  511. // Generate the standard prototype. This really means emit the proto of
  512. // the proc in the stub file. The body of the function output later,
  513. GenStdMesPrototype( pCCB,
  514. (pName = GetType()->GetSymName()),
  515. TYPE_ENCODE_CODE,
  516. HasImplicitHandle()
  517. );
  518. pStream->NewLine();
  519. pStream->Write( '{' );
  520. pStream->IndentInc();pStream->NewLine();
  521. // The procedure body consists of a single procedure call.
  522. expr_proc_call * pProc = CreateStdMesEngineProc( pCCB, TYPE_ENCODE_CODE);
  523. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  524. // Terminate the procedure body.
  525. pStream->IndentDec();
  526. pStream->NewLine();
  527. pStream->Write( '}' );
  528. pStream->NewLine();
  529. // Register the routine with the ccb to enable emitting of prototypes.
  530. pTEInfo->pName = pName;
  531. pTEInfo->Flags = HasImplicitHandle() ? TYPE_ENCODE_WITH_IMPL_HANDLE : TYPE_ENCODE_FLAGS_NONE;
  532. pCCB->RegisterTypeEncode( pTEInfo );
  533. return CG_OK;
  534. }
  535. CG_STATUS
  536. CG_TYPE_ENCODE::GenTypeDecode(
  537. CCB * pCCB )
  538. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  539. Routine Description:
  540. Generate the type sizing routine for the type.
  541. Arguments:
  542. pCCB - The code gen controller block.
  543. Return Value:
  544. CG_OK
  545. Notes:
  546. ----------------------------------------------------------------------------*/
  547. {
  548. ISTREAM * pStream = pCCB->GetStream();
  549. PNAME pName;
  550. TYPE_ENCODE_INFO * pTEInfo = new TYPE_ENCODE_INFO;
  551. // Generate the standard prototype. This really means emit the proto of
  552. // the proc in the stub file. The body of the function output later,
  553. GenStdMesPrototype( pCCB,
  554. ( pName = GetType()->GetSymName()),
  555. TYPE_DECODE_CODE,
  556. HasImplicitHandle()
  557. );
  558. pStream->NewLine();
  559. pStream->Write( '{' );
  560. pStream->IndentInc();pStream->NewLine();
  561. // The procedure body consists of a single procedure call.
  562. expr_proc_call * pProc = CreateStdMesEngineProc( pCCB, TYPE_DECODE_CODE);
  563. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  564. // Terminate the procedure body.
  565. pStream->IndentDec();
  566. pStream->NewLine();
  567. pStream->Write( '}' );
  568. pStream->NewLine();
  569. // Register the routine with the ccb to enable emitting of prototypes.
  570. pTEInfo->pName = pName;
  571. pTEInfo->Flags = HasImplicitHandle() ? TYPE_ENCODE_WITH_IMPL_HANDLE : TYPE_ENCODE_FLAGS_NONE;
  572. pCCB->RegisterTypeDecode( pTEInfo );
  573. return CG_OK;
  574. }
  575. CG_STATUS
  576. CG_TYPE_ENCODE::GenTypeFree( CCB* pCCB )
  577. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  578. Routine Description:
  579. Generate the type freeing routine for the type.
  580. Arguments:
  581. pCCB - The code gen controller block.
  582. Return Value:
  583. CG_OK
  584. Notes:
  585. ----------------------------------------------------------------------------*/
  586. {
  587. // Freeing is only allowed under the new intrepreter
  588. if ( ! ( pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER_V2 ) )
  589. return CG_OK;
  590. ISTREAM * pStream = pCCB->GetStream();
  591. PNAME pName;
  592. TYPE_ENCODE_INFO * pTEInfo = new TYPE_ENCODE_INFO;
  593. // Generate the standard prototype. This really means emit the proto of
  594. // the proc in the stub file. The body of the function output later,
  595. if ( ((CG_NDR *)GetChild())->IsSimpleType() )
  596. return CG_OK;
  597. GenStdMesPrototype( pCCB,
  598. ( pName = GetType()->GetSymName()),
  599. TYPE_FREE_CODE,
  600. HasImplicitHandle()
  601. );
  602. pStream->NewLine();
  603. pStream->Write( '{' );
  604. pStream->IndentInc();pStream->NewLine();
  605. // The procedure body consists of a single procedure call.
  606. expr_proc_call * pProc = CreateStdMesEngineProc( pCCB, TYPE_FREE_CODE);
  607. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  608. // Terminate the procedure body.
  609. pStream->IndentDec();
  610. pStream->NewLine();
  611. pStream->Write( '}' );
  612. pStream->NewLine();
  613. // Register the routine with the ccb to enable emitting of prototypes.
  614. pTEInfo->pName = pName;
  615. pTEInfo->Flags = HasImplicitHandle() ? TYPE_ENCODE_WITH_IMPL_HANDLE : TYPE_ENCODE_FLAGS_NONE;
  616. pCCB->RegisterTypeFree( pTEInfo );
  617. return CG_OK;
  618. }
  619. void
  620. CG_TYPE_ENCODE::AllocateEncodeResources(
  621. CCB * pCCB )
  622. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  623. Routine Description:
  624. Allocate predefined resources for type pickling.
  625. Arguments:
  626. pCCB - The code gen controller block.
  627. Return Value:
  628. CG_OK
  629. Notes:
  630. Resources are:
  631. 1. The MIDL_ES_HANDLE if explicit binding.
  632. 2. A pointer to the type.
  633. If there is no explicit binding set the implicit binding resource.
  634. ----------------------------------------------------------------------------*/
  635. {
  636. node_id * pMidlESHandle;
  637. RESOURCE * pBindingResource;
  638. node_id * pType = MakeIDNode( PTYPE_VAR_NAME,GetType());
  639. // If explicit binding, then a parameter of the type MIDL_ES_HANDLE will
  640. // be specified by the user. This must be added to the dictionary of
  641. // parameter resources.
  642. if( !HasImplicitHandle() )
  643. {
  644. pMidlESHandle = MakeIDNodeFromTypeName( MIDL_ES_HANDLE_VAR_NAME,
  645. MIDL_ES_HANDLE_TYPE_NAME
  646. );
  647. pBindingResource = pCCB->AddParamResource(
  648. MIDL_ES_HANDLE_VAR_NAME,
  649. pMidlESHandle
  650. );
  651. }
  652. else
  653. {
  654. PNAME pName;
  655. // If an implicit binding has been specified, a global variable of the
  656. // type MIDL_ES_HANDLE will have been specified by the user. Pick that
  657. // up and use as the binding resource.
  658. MIDL_ASSERT( pCCB->GetInterfaceCG()->GetImplicitHandle() != 0 );
  659. pMidlESHandle =
  660. (node_id *)pCCB->GetInterfaceCG()->
  661. GetImplicitHandle()->
  662. GetHandleIDOrParam();
  663. pName = pMidlESHandle->GetSymName();
  664. pBindingResource = new RESOURCE( pName,
  665. MakeIDNodeFromTypeName(
  666. pName,
  667. MIDL_ES_HANDLE_TYPE_NAME));
  668. }
  669. SetBindingResource( pBindingResource );
  670. // Add a param for the type being pickled.
  671. pCCB->AddParamResource( PTYPE_VAR_NAME, pType );
  672. }
  673. expr_proc_call *
  674. CG_TYPE_ENCODE::CreateStdMesEngineProc(
  675. CCB * pCCB,
  676. int Code )
  677. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  678. Routine Description:
  679. Create a standard proc expression for calls to the engine for encode,
  680. decode, align/size, and free.
  681. Arguments:
  682. pCCB - The code gen controller block.
  683. Code - Which can be any standard encoding services code.
  684. Return Value:
  685. CG_OK
  686. Notes:
  687. If the child is a base type that is being pickled, make direct calls
  688. to the internal apis.
  689. In -Oicf mode the emitted stub looks like the following with Encode
  690. changed to whichever operation [Code] specifies:
  691. void
  692. <typename>_Encode(
  693. <object>)
  694. {
  695. NdrMesTypeEncodeXXX();
  696. }
  697. For pre -Oicf modes the <&type_pickling_info> parameter is omitted.
  698. ----------------------------------------------------------------------------*/
  699. {
  700. expr_node * pExpr;
  701. expr_proc_call * pProc;
  702. PNAME pProcName;
  703. CG_NDR * pChild = (CG_NDR *)GetChild();
  704. CSzBuffer ProcNameBuf;
  705. BOOL fIsBaseType;
  706. bool fNeedPicklingInfoParam = false;
  707. int fNeedsNDR64;
  708. fIsBaseType = pChild->IsSimpleType();
  709. fNeedsNDR64 = pCommand->NeedsNDR64Run();
  710. //
  711. // Figure out what the name of the routine to call is
  712. //
  713. PNAME pNdrMesProcNames[4] =
  714. {
  715. "NdrMesTypeAlignSize",
  716. "NdrMesTypeEncode",
  717. "NdrMesTypeDecode",
  718. "NdrMesTypeFree"
  719. };
  720. if ( fIsBaseType )
  721. {
  722. MIDL_ASSERT( Code != TYPE_FREE_CODE );
  723. ProcNameBuf.Set("NdrMesSimpleType");
  724. ProcNameBuf.Append((Code == TYPE_ALIGN_SIZE_CODE) ? "AlignSize" :
  725. (Code == TYPE_ENCODE_CODE) ? "Encode" : "Decode");
  726. if ( fNeedsNDR64 )
  727. {
  728. ProcNameBuf.Append( "All" );
  729. }
  730. }
  731. else
  732. {
  733. ProcNameBuf.Set( pNdrMesProcNames[Code] );
  734. // -protocol all and ndr64 uses "3" routines.
  735. // -Oicf in straight dce mode uses "2" routines
  736. // otherwise uses unnumbered routines
  737. if ( fNeedsNDR64 )
  738. {
  739. ProcNameBuf.Append( "3" );
  740. fNeedPicklingInfoParam = true;
  741. }
  742. else if ( pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER_V2 )
  743. {
  744. ProcNameBuf.Append( "2" );
  745. fNeedPicklingInfoParam = true;
  746. }
  747. else
  748. {
  749. MIDL_ASSERT( TYPE_FREE_CODE != Code );
  750. }
  751. }
  752. pProcName = new char [strlen( ProcNameBuf ) + 1];
  753. strcpy( pProcName, ProcNameBuf );
  754. //
  755. // Start putting together the proc call
  756. //
  757. pProc = new expr_proc_call( pProcName );
  758. // Set parameters.
  759. // First the encoding handle.
  760. pProc->SetParam( GetBindingResource() );
  761. // Then pickling info structure
  762. if( fNeedPicklingInfoParam )
  763. {
  764. pExpr = new RESOURCE( PICKLING_INFO_STRUCT_NAME,
  765. (node_skl *)0 );
  766. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  767. pExpr = MakeExpressionOfCastToTypeName( PMIDL_TYPE_PICKLING_INFO_NAME,
  768. pExpr );
  769. pProc->SetParam( pExpr );
  770. }
  771. // Next the stub descriptor or the proxy info
  772. if ( !fIsBaseType || fNeedsNDR64 || Code == TYPE_ENCODE_CODE )
  773. {
  774. PNAME StubOrProxy;
  775. if ( fNeedsNDR64 )
  776. StubOrProxy = pCCB->GetInterfaceCG()->GetProxyInfoName();
  777. else
  778. StubOrProxy = pCCB->GetInterfaceCG()->GetStubDescName();
  779. pExpr = new RESOURCE( StubOrProxy,
  780. (node_skl *)0 );
  781. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  782. pProc->SetParam( pExpr );
  783. }
  784. // Next in straight dce, if it's not a simple type, comes the offset into
  785. // the format string of the type
  786. if( !fNeedsNDR64 && !fIsBaseType )
  787. {
  788. // Next parameter is the address of the format string indexed by the
  789. // correct offset i.e &__MIDLFormatString[ ? ].
  790. pExpr = Make_1_ArrayExpressionFromVarName(FORMAT_STRING_STRING_FIELD,
  791. pChild->GetFormatStringOffset());
  792. pExpr = MakeAddressExpressionNoMatterWhat( pExpr );
  793. pExpr = MakeExpressionOfCastToTypeName( PFORMAT_STRING_TYPE_NAME, pExpr );
  794. pProc->SetParam( pExpr );
  795. }
  796. // For -protocol all or ndr64, the table of type offset tables is next
  797. // followed by the index of this type into the tables.
  798. if ( fNeedsNDR64 && !fIsBaseType )
  799. {
  800. pExpr = new RESOURCE( "TypePicklingOffsetTable", NULL );
  801. pProc->SetParam( pExpr );
  802. pExpr = new expr_constant( this->TypeIndex );
  803. pProc->SetParam( pExpr );
  804. }
  805. // Now for everything except simply type AlignSize, we need the object
  806. // itself
  807. if ( ! (fIsBaseType && Code == TYPE_ALIGN_SIZE_CODE) )
  808. {
  809. pExpr = pCCB->GetParamResource( PTYPE_VAR_NAME );
  810. pProc->SetParam( pExpr );
  811. }
  812. // Data size for simple type encoding and decoding
  813. if ( fIsBaseType )
  814. {
  815. switch ( Code )
  816. {
  817. case TYPE_ALIGN_SIZE_CODE:
  818. break;
  819. case TYPE_ENCODE_CODE:
  820. {
  821. pExpr = new expr_constant( (short) pChild->GetMemorySize() );
  822. pProc->SetParam( pExpr );
  823. }
  824. break;
  825. case TYPE_DECODE_CODE:
  826. // We need format char because of conversion.
  827. pExpr = new expr_constant( (short)
  828. ((CG_BASETYPE *)pChild)->GetFormatChar() );
  829. pProc->SetParam( pExpr );
  830. break;
  831. default:
  832. MIDL_ASSERT( FALSE );
  833. break;
  834. }
  835. }
  836. return pProc;
  837. }
  838. void
  839. GenStdMesPrototype(
  840. CCB * pCCB,
  841. PNAME TypeName,
  842. int Code,
  843. BOOL fImplicitHandle )
  844. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  845. Routine Description:
  846. Generate a standard prototype for the type pickle routines.
  847. Arguments:
  848. pCCB - The code gen controller block.
  849. PNAME - Name of the type.
  850. Code - Size / Encode / Decode code.
  851. fImplicitImplicitHandle - TRUE if implicit binding handle used.
  852. Return Value:
  853. Notes:
  854. ----------------------------------------------------------------------------*/
  855. {
  856. CSzBuffer Buffer;
  857. char * p;
  858. switch( Code )
  859. {
  860. case TYPE_ALIGN_SIZE_CODE: p = "AlignSize"; break;
  861. case TYPE_ENCODE_CODE: p = "Encode"; break;
  862. case TYPE_DECODE_CODE: p = "Decode"; break;
  863. case TYPE_FREE_CODE: p = "Free"; break;
  864. default:
  865. MIDL_ASSERT( FALSE );
  866. }
  867. if( fImplicitHandle )
  868. {
  869. Buffer.Set("\n");
  870. Buffer.Append((Code == TYPE_ALIGN_SIZE_CODE) ? "size_t" : "void");
  871. Buffer.Append("\n");
  872. Buffer.Append(TypeName);
  873. Buffer.Append("_");
  874. Buffer.Append(p);
  875. Buffer.Append("(\n ");
  876. Buffer.Append(TypeName);
  877. Buffer.Append(" * ");
  878. Buffer.Append(PTYPE_VAR_NAME);
  879. Buffer.Append(")");
  880. }
  881. else
  882. {
  883. Buffer.Set("\n");
  884. Buffer.Append((Code == TYPE_ALIGN_SIZE_CODE) ? "size_t" : "void");
  885. Buffer.Append("\n");
  886. Buffer.Append(TypeName);
  887. Buffer.Append("_");
  888. Buffer.Append(p);
  889. Buffer.Append("(\n ");
  890. Buffer.Append(MIDL_ES_HANDLE_TYPE_NAME);
  891. Buffer.Append(" ");
  892. Buffer.Append(MIDL_ES_HANDLE_VAR_NAME);
  893. Buffer.Append(",\n ");
  894. Buffer.Append(TypeName);
  895. Buffer.Append(" * ");
  896. Buffer.Append(PTYPE_VAR_NAME);
  897. Buffer.Append(")");
  898. }
  899. pCCB->GetStream()->Write( Buffer );
  900. }