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.

749 lines
18 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. stcls.cxx
  5. Abstract:
  6. Implementation of offline methods for the structure code generation
  7. classes.
  8. Notes:
  9. History:
  10. Oct-1993 DKays Created.
  11. ----------------------------------------------------------------------------*/
  12. #include "becls.hxx"
  13. #pragma hdrstop
  14. CG_ARRAY *
  15. CG_CONFORMANT_STRUCT::GetConformantArray()
  16. /*++
  17. Routine Description :
  18. Gets the conformant (varying/string) class pointer for a conformant
  19. structure.
  20. Arguments :
  21. None.
  22. --*/
  23. {
  24. CG_NDR * pConf;
  25. if ( ! pConfFld )
  26. return 0;
  27. pConf = (CG_NDR *) pConfFld->GetChild();
  28. for (;;)
  29. {
  30. if ( pConf->GetCGID() == ID_CG_CONF_ARRAY ||
  31. pConf->GetCGID() == ID_CG_CONF_VAR_ARRAY ||
  32. pConf->GetCGID() == ID_CG_CONF_STRING_ARRAY )
  33. break;
  34. if ( pConf->IsXmitRepOrUserMarshal() )
  35. {
  36. pConf = (CG_NDR *)pConf->GetChild();
  37. continue;
  38. }
  39. // else
  40. pConf = (CG_NDR *)
  41. ((CG_CONFORMANT_STRUCT *)pConf)->GetConformantField();
  42. pConf = (CG_NDR *) pConf->GetChild();
  43. }
  44. return (CG_ARRAY *) pConf;
  45. }
  46. BOOL
  47. CG_COMPLEX_STRUCT::WarnAboutEmbeddedComplexStruct()
  48. /*
  49. The only reason we have this method is to help with an engine bug.
  50. The bug is that for complex structs (FC_BOGUS_STRUCT code) that have an
  51. embedded conformant struct, the engine marshals incorrect wire format.
  52. Hence this method checks if the complex struct has an open array at the end,
  53. and if so, checks if the last member is another type of struct.
  54. */
  55. {
  56. BOOL HasIt = FALSE;
  57. if ( GetConformantArray() )
  58. {
  59. //
  60. // Get the last field.
  61. //
  62. CG_ITERATOR Iterator;
  63. CG_FIELD * pField;
  64. CG_NDR * pNdr;
  65. GetMembers( Iterator );
  66. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  67. ;
  68. pNdr = (CG_NDR *) pField->GetChild();
  69. if ( pNdr->IsStruct() )
  70. {
  71. HasIt = TRUE;
  72. char * pSymName, * pEmbeddedName, * pNameContext;
  73. pSymName = GetSymName() ? GetSymName() : "?";
  74. pEmbeddedName = pNdr->GetSymName() ? pNdr->GetSymName() : "?";
  75. size_t len = strlen( pSymName ) + strlen( pEmbeddedName ) + 20;
  76. pNameContext = new char[ len ];
  77. strcpy( pNameContext, pSymName );
  78. strcat( pNameContext, " embedding " );
  79. strcat( pNameContext, pEmbeddedName );
  80. if ( !pCommand->Is64BitEnv() )
  81. RpcError(NULL, 0, EMBEDDED_OPEN_STRUCT, pNameContext );
  82. }
  83. }
  84. return HasIt;
  85. }
  86. CG_FIELD *
  87. CG_STRUCT::GetFinalField()
  88. {
  89. CG_ITERATOR Iterator;
  90. CG_FIELD * pField;
  91. CG_NDR * pNdr;
  92. GetMembers( Iterator );
  93. //
  94. // Get the last field.
  95. //
  96. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  97. ;
  98. pNdr = (CG_NDR *) pField->GetChild();
  99. if ( pNdr->IsStruct() )
  100. pField = ((CG_STRUCT *)pNdr)->GetFinalField();
  101. return pField;
  102. }
  103. CG_FIELD *
  104. CG_STRUCT::GetArrayField( CG_ARRAY * pArray )
  105. {
  106. CG_ITERATOR Iterator;
  107. CG_FIELD * pField;
  108. CG_NDR * pNdr;
  109. GetMembers( Iterator );
  110. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  111. {
  112. pNdr = (CG_NDR *) pField->GetChild();
  113. if ( pNdr == pArray )
  114. return pField;
  115. //
  116. // Search inside of other structs only.
  117. //
  118. if ( pNdr->IsStruct() )
  119. {
  120. if ( (pField = ((CG_STRUCT *)pNdr)->GetArrayField(pArray)) != 0 )
  121. return pField;
  122. }
  123. }
  124. // Didn't find it.
  125. return 0;
  126. }
  127. BOOL
  128. CG_STRUCT::IsHardStruct()
  129. {
  130. // REVIEW: The previous comment implied that we we're going to do something
  131. // else "after the PPC update". Is this still relevant?
  132. // -- MikeW 16-Jul-99
  133. return FALSE;
  134. }
  135. BOOL
  136. CG_STRUCT::IsHardStructOld()
  137. {
  138. CG_ITERATOR Iterator;
  139. CG_FIELD * pField;
  140. CG_FIELD * pPrevField;
  141. //
  142. // Cannot have a conformant array of any kind.
  143. //
  144. if ( (GetCGID() == ID_CG_CONF_STRUCT) ||
  145. (GetCGID() == ID_CG_CONF_VAR_STRUCT) )
  146. return FALSE;
  147. //
  148. // Cannot have pointers.
  149. //
  150. if ( HasPointer() )
  151. return FALSE;
  152. //
  153. // Can't have more than one enum16.
  154. //
  155. if ( GetNumberOfEnum16s() > 1 )
  156. return FALSE;
  157. //
  158. // Can't have padding in the middle of the struct that differs in
  159. // memory and on the wire.
  160. //
  161. GetMembers( Iterator );
  162. pPrevField = 0;
  163. //
  164. // Get the last field.
  165. //
  166. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  167. {
  168. if ( pField->GetSibling() )
  169. pPrevField = pField;
  170. }
  171. //
  172. // Check if the last field in the struct has a different memory and wire
  173. // offset. However, if there is a single union as the last field then
  174. // we have to check the second to last fields's mem and wire offsets
  175. // instead since a union's field's wire offsets are not accurate.
  176. //
  177. if ( pField->GetChild()->IsUnion() && pPrevField )
  178. pField = pPrevField;
  179. // This is complex.
  180. if ( pField->GetMemOffset() != pField->GetWireOffset() )
  181. return FALSE;
  182. //
  183. // Can have at most one union as the last field only.
  184. //
  185. switch ( GetNumberOfUnions() )
  186. {
  187. case 0 :
  188. break;
  189. case 1 :
  190. //
  191. // The last field must be the union.
  192. //
  193. if ( ! GetFinalField()->GetChild()->IsUnion() )
  194. return FALSE;
  195. else
  196. return TRUE;
  197. break;
  198. default :
  199. return FALSE;
  200. }
  201. //
  202. // Now check again if we have just one enum16.
  203. //
  204. if ( GetNumberOfEnum16s() == 1 )
  205. return TRUE;
  206. //
  207. // Check for end padding, which is ok for a hard struct.
  208. //
  209. if ( GetMemorySize() > GetWireSize() )
  210. return TRUE;
  211. //
  212. // It must be a nice struct.
  213. //
  214. return FALSE;
  215. }
  216. BOOL
  217. CG_STRUCT::HasAFixedBufferSize()
  218. {
  219. CG_ITERATOR Iterator;
  220. CG_FIELD * pField;
  221. GetMembers( Iterator );
  222. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  223. {
  224. if ( !pField->HasAFixedBufferSize() )
  225. return FALSE;
  226. }
  227. return TRUE;
  228. }
  229. BOOL
  230. CG_STRUCT::IsComplexStruct()
  231. {
  232. CG_ITERATOR Iterator;
  233. CG_FIELD * pField;
  234. CG_NDR * pNdr;
  235. BOOL IsConformant;
  236. IsConformant = (GetCGID() == ID_CG_CONF_STRUCT) ||
  237. (GetCGID() == ID_CG_CONF_VAR_STRUCT);
  238. switch ( GetNumberOfEnum16s() )
  239. {
  240. case 0 :
  241. break;
  242. case 1 :
  243. if ( HasPointer() || IsConformant )
  244. return TRUE;
  245. break;
  246. default :
  247. return TRUE;
  248. }
  249. switch ( GetNumberOfUnions() )
  250. {
  251. case 0 :
  252. break;
  253. case 1 :
  254. if ( ! GetFinalField()->GetChild()->IsUnion() ||
  255. HasPointer() ||
  256. IsConformant )
  257. return TRUE;
  258. break;
  259. default :
  260. return TRUE;
  261. }
  262. if ( (GetMemorySize() > GetWireSize()) && (HasPointer() || IsConformant) )
  263. return TRUE;
  264. GetMembers( Iterator );
  265. //
  266. // Check if there are any embedded structs or arrays which are
  267. // complex.
  268. // On 64b platforms any pointer makes it complex as well.
  269. //
  270. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  271. {
  272. pNdr = (CG_NDR *) pField->GetChild();
  273. if ( pNdr->IsArray() && ((CG_ARRAY *)pNdr)->IsComplex() )
  274. return TRUE;
  275. if ( pNdr->IsStruct() && ((CG_STRUCT *)pNdr)->IsComplexStruct() )
  276. return TRUE;
  277. // struct fields with [range] on them make the struct complex.
  278. if ( pNdr->GetRangeAttribute() )
  279. return TRUE;
  280. //if ( pNdr->IsPointer() && pCommand->Is64BitEnv() )
  281. // return TRUE;
  282. if ( ( pField->GetWireOffset() != pField->GetMemOffset() ) ||
  283. ( pField->GetWireSize() != pField->GetMemorySize() ) )
  284. return TRUE;
  285. }
  286. return IsHardStructOld();
  287. }
  288. bool
  289. CG_STRUCT::IsHomogeneous(FORMAT_CHARACTER format)
  290. {
  291. CG_ITERATOR Iterator;
  292. CG_FIELD *pField;
  293. GetMembers( Iterator );
  294. while ( ITERATOR_GETNEXT( Iterator, pField ))
  295. {
  296. CG_NDR *pChild = (CG_NDR *) pField->GetChild();
  297. if ( !pChild->IsHomogeneous( format ) )
  298. return false;
  299. }
  300. return true;
  301. }
  302. long
  303. CG_STRUCT::GetNumberOfPointers()
  304. {
  305. CG_ITERATOR Iterator;
  306. CG_FIELD * pField;
  307. CG_NDR * pMember;
  308. long Count;
  309. Count = 0;
  310. GetMembers(Iterator);
  311. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  312. {
  313. pMember = (CG_NDR *) pField->GetChild();
  314. if ( pMember->IsPointer() &&
  315. !pMember->IsInterfacePointer() )
  316. Count++;
  317. if ( pMember->IsStruct() )
  318. Count += ((CG_STRUCT *)pMember)->GetNumberOfPointers();
  319. }
  320. return Count;
  321. }
  322. long
  323. CG_STRUCT::GetNumberOfEnum16s()
  324. {
  325. CG_ITERATOR Iterator;
  326. CG_FIELD * pField;
  327. CG_NDR * pNdr;
  328. long Count;
  329. long Weight;
  330. Count = 0;
  331. GetMembers(Iterator);
  332. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  333. {
  334. pNdr = (CG_NDR *) pField->GetChild();
  335. //
  336. // If an array contains a enum16 we count it as 100 enum16s, since
  337. // this routine is only interested in small enum16 counts.
  338. //
  339. if ( pNdr->IsArray() )
  340. {
  341. pNdr = (CG_NDR *) pNdr->GetChild();
  342. while ( pNdr->IsArray() )
  343. pNdr = (CG_NDR *) pNdr->GetChild();
  344. Weight = 100;
  345. }
  346. else
  347. Weight = 1;
  348. if ( pNdr->IsSimpleType() &&
  349. (((CG_BASETYPE *)pNdr)->GetFormatChar() == FC_ENUM16) )
  350. Count += Weight;
  351. if ( pNdr->IsStruct() )
  352. Count += Weight * ((CG_STRUCT *)pNdr)->GetNumberOfEnum16s();
  353. }
  354. return Count;
  355. }
  356. long
  357. CG_STRUCT::GetNumberOfUnions()
  358. {
  359. CG_ITERATOR Iterator;
  360. CG_FIELD * pField;
  361. CG_NDR * pNdr;
  362. long Count;
  363. long Weight;
  364. Count = 0;
  365. GetMembers(Iterator);
  366. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  367. {
  368. pNdr = (CG_NDR *) pField->GetChild();
  369. //
  370. // If an array contains a union we count it as 100 unions, since
  371. // this routine is only interested in small union counts.
  372. //
  373. if ( pNdr->IsArray() )
  374. {
  375. pNdr = (CG_NDR *) pNdr->GetChild();
  376. while ( pNdr->IsArray() )
  377. pNdr = (CG_NDR *) pNdr->GetChild();
  378. Weight = 100;
  379. }
  380. else
  381. Weight = 1;
  382. if ( (pNdr->GetCGID() == ID_CG_UNION) ||
  383. (pNdr->GetCGID() == ID_CG_ENCAP_STRUCT) )
  384. Count += Weight;
  385. if ( pNdr->IsStruct() )
  386. Count += Weight * ((CG_STRUCT *)pNdr)->GetNumberOfUnions();
  387. }
  388. return Count;
  389. }
  390. long
  391. CG_STRUCT::GetEnum16Offset()
  392. {
  393. CG_ITERATOR Iterator;
  394. CG_FIELD * pField;
  395. CG_NDR * pNdr;
  396. MIDL_ASSERT( GetNumberOfEnum16s() == 1 );
  397. GetMembers( Iterator );
  398. //
  399. // Search for the enum.
  400. //
  401. while ( ITERATOR_GETNEXT( Iterator, pField ) )
  402. {
  403. pNdr = (CG_NDR *) pField->GetChild();
  404. if ( pNdr->IsSimpleType() &&
  405. (((CG_BASETYPE *)pNdr)->GetFormatChar() == FC_ENUM16) )
  406. return pField->GetMemOffset();
  407. if ( pNdr->IsStruct() &&
  408. (((CG_STRUCT *)pNdr)->GetNumberOfEnum16s() == 1) )
  409. return pField->GetMemOffset() +
  410. ((CG_STRUCT *)pNdr)->GetEnum16Offset();
  411. }
  412. // Never get here.
  413. return 0;
  414. }
  415. void
  416. CloneForUnrolling(
  417. CG_NDR * pParent,
  418. CG_NDR * pNdr )
  419. /*
  420. This routine will clone pNdr and overwrite the original child at
  421. the parent if needed.
  422. It is assumed the parent has been cloned, too.
  423. */
  424. {
  425. CG_POINTER * pNewPointer;
  426. pNewPointer = 0;
  427. if ( pNdr->IsPointer() )
  428. {
  429. switch ( pNdr->GetCGID() )
  430. {
  431. case ID_CG_PTR :
  432. pNewPointer = new CG_POINTER(
  433. (CG_POINTER *) pNdr );
  434. break;
  435. case ID_CG_BC_PTR :
  436. pNewPointer = new CG_BYTE_COUNT_POINTER(
  437. (CG_BYTE_COUNT_POINTER *) pNdr );
  438. break;
  439. case ID_CG_STRING_PTR :
  440. case ID_CG_STRUCT_STRING_PTR :
  441. pNewPointer = new CG_STRING_POINTER(
  442. (CG_STRING_POINTER *) pNdr );
  443. break;
  444. case ID_CG_SIZE_PTR :
  445. pNewPointer = new CG_SIZE_POINTER(
  446. (CG_SIZE_POINTER *) pNdr );
  447. break;
  448. case ID_CG_LENGTH_PTR :
  449. pNewPointer = new CG_LENGTH_POINTER(
  450. (CG_LENGTH_POINTER *) pNdr );
  451. break;
  452. case ID_CG_SIZE_LENGTH_PTR :
  453. pNewPointer = new CG_SIZE_LENGTH_POINTER(
  454. (CG_SIZE_LENGTH_POINTER *) pNdr );
  455. break;
  456. case ID_CG_SIZE_STRING_PTR :
  457. pNewPointer = new CG_SIZE_STRING_POINTER(
  458. (CG_SIZE_STRING_POINTER *) pNdr );
  459. break;
  460. case ID_CG_INTERFACE_PTR :
  461. pNewPointer = new CG_INTERFACE_POINTER(
  462. (CG_INTERFACE_POINTER *) pNdr );
  463. break;
  464. case ID_CG_IIDIS_INTERFACE_PTR :
  465. pNewPointer = new CG_IIDIS_INTERFACE_POINTER(
  466. (CG_IIDIS_INTERFACE_POINTER *) pNdr );
  467. break;
  468. default :
  469. break;
  470. }
  471. if ( pNewPointer )
  472. {
  473. //
  474. // We have to re-set the new pointer's format string offset and
  475. // pointee format string offset to -1 so that we get a new
  476. // description!!!
  477. //
  478. if ( pNewPointer )
  479. pNewPointer->SetFormatStringOffset( -1 );
  480. pNewPointer->SetPointeeFormatStringOffset( -1 );
  481. pParent->SetChild( pNewPointer );
  482. if ( pNdr->GetChild() )
  483. CloneForUnrolling( pNewPointer, (CG_NDR*) pNdr->GetChild() );
  484. }
  485. }
  486. }
  487. void
  488. CG_STRUCT::Unroll()
  489. {
  490. ITERATOR Iterator;
  491. CG_FIELD * pPrevField;
  492. CG_FIELD * pField;
  493. CG_NDR * pNdr;
  494. CG_STRUCT * pStruct;
  495. GetMembers( Iterator );
  496. pPrevField = 0;
  497. while ( ITERATOR_GETNEXT(Iterator,pField) )
  498. {
  499. pNdr = (CG_NDR *) pField->GetChild();
  500. if ( pNdr->IsStruct() && ((CG_STRUCT *)pNdr)->HasSizedPointer() )
  501. pStruct = (CG_STRUCT *) pNdr;
  502. else
  503. {
  504. pPrevField = pField;
  505. continue;
  506. }
  507. //
  508. // First force the embeded struct to unroll if needed.
  509. //
  510. pStruct->Unroll();
  511. ITERATOR IteratorEmbeded;
  512. CG_FIELD * pFieldNew;
  513. CG_FIELD * pFieldEmbeded;
  514. CG_FIELD * pFieldList;
  515. long MemOffsetStart;
  516. long WireOffsetStart;
  517. pStruct->GetMembers( IteratorEmbeded );
  518. MemOffsetStart = pField->GetMemOffset();
  519. WireOffsetStart = pField->GetWireOffset();
  520. // Get previous field node.
  521. pFieldList = pPrevField;
  522. // Remove current struct field node from the list.
  523. if ( pFieldList )
  524. pFieldList->SetSibling( pField->GetSibling() );
  525. else
  526. this->SetChild( pField->GetSibling() );
  527. // To be safe.
  528. pField->SetSibling( 0 );
  529. while ( ITERATOR_GETNEXT(IteratorEmbeded,pFieldEmbeded) )
  530. {
  531. pFieldNew = (CG_FIELD *) pFieldEmbeded->Clone();
  532. pNdr = (CG_NDR *) pFieldEmbeded->GetChild();
  533. CloneForUnrolling( pFieldNew, pNdr );
  534. //
  535. // Set the new field's memory and wire offset.
  536. //
  537. pFieldNew->SetMemOffset( pFieldEmbeded->GetMemOffset() +
  538. MemOffsetStart );
  539. pFieldNew->SetWireOffset( pFieldEmbeded->GetWireOffset() +
  540. WireOffsetStart );
  541. //
  542. // Now add the imbeded struct's field name to the PrintPrefix of
  543. // the new unrolled field. We ask the imbeded struct's field
  544. // for it's name.
  545. //
  546. pFieldNew->AddPrintPrefix( pField->GetType()->GetSymName() );
  547. if ( pFieldList )
  548. {
  549. pFieldNew->SetSibling( pFieldList->GetSibling() );
  550. pFieldList->SetSibling( pFieldNew );
  551. }
  552. else
  553. {
  554. pFieldNew->SetSibling( this->GetChild() );
  555. this->SetChild( pFieldNew );
  556. }
  557. pFieldList = pFieldNew;
  558. }
  559. //
  560. // Set pPrevField equal to the last field node that we entered into
  561. // the list. The outermost Iterator only knows about fields that
  562. // started in the struct's field list, so the last field node we
  563. // added will have a sibling equal to the next field node we'll get
  564. // from the outer iterator.
  565. //
  566. pPrevField = pFieldNew;
  567. }
  568. }
  569. BOOL
  570. CG_STRUCT::HasSizedPointer()
  571. {
  572. CG_ITERATOR Iterator;
  573. CG_FIELD * pField;
  574. CG_NDR * pNdr;
  575. GetMembers( Iterator );
  576. while ( ITERATOR_GETNEXT(Iterator,pField) )
  577. {
  578. pNdr = (CG_NDR *) pField->GetChild();
  579. if ( pNdr->IsStruct() && ((CG_STRUCT *)pNdr)->HasSizedPointer() )
  580. return TRUE;
  581. if ( (pNdr->GetCGID() == ID_CG_SIZE_PTR) ||
  582. (pNdr->GetCGID() == ID_CG_SIZE_LENGTH_PTR) ||
  583. (pNdr->GetCGID() == ID_CG_SIZE_STRING_PTR) )
  584. return TRUE;
  585. }
  586. return FALSE;
  587. }
  588. BOOL
  589. CG_ENCAPSULATED_STRUCT::ShouldFreeOffline()
  590. {
  591. CG_UNION * pUnion;
  592. pUnion = (CG_UNION *) GetChild()->GetSibling()->GetChild();
  593. return pUnion->HasPointer();
  594. }