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.

699 lines
25 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. CopyTo.cxx
  5. Abstract:
  6. cloning routines
  7. Notes:
  8. Author:
  9. NishadM Sep-29-1997 Created.
  10. Notes:
  11. ----------------------------------------------------------------------------*/
  12. // unreferenced inline/local function has been removed
  13. #pragma warning ( disable : 4514 )
  14. // includes
  15. #include "nodeskl.hxx"
  16. #include "attrnode.hxx"
  17. #include "acfattr.hxx"
  18. #include "idict.hxx"
  19. // externs
  20. extern SymTable* pBaseSymTbl;
  21. // constants
  22. const char* const szAsyncIntfPrefix = "Async";
  23. const unsigned int uAsyncIntfPrefixLen = 5;
  24. const char* const szFinishProcPrefix = "Finish_";
  25. const unsigned int uFinishProcPrefixLen = 7;
  26. const char* const szBeginProcPrefix = "Begin_";
  27. const unsigned int uBeginProcPrefixLen = 6;
  28. // forwards
  29. extern IDICT* pInterfaceDict;
  30. void
  31. FixupCallAs (
  32. node_call_as*,
  33. ITERATOR&
  34. );
  35. node_interface*
  36. DuplicateNodeInterface (
  37. node_interface* pIntfSrc,
  38. const char* const szPrefix,
  39. unsigned short uPrefixLen
  40. );
  41. node_proc*
  42. DuplicateNodeProc (
  43. node_proc* pProcSrc,
  44. const char* const szPrefix,
  45. unsigned uPrefixLen,
  46. unsigned long uInterfaceKey,
  47. ITERATOR& Itr
  48. );
  49. node_param*
  50. DuplicateNodeParam (
  51. node_param* pParamSrc,
  52. node_proc* pProc
  53. );
  54. node_skl*
  55. FindInOnlyParamInExpr (
  56. expr_node* pExpr
  57. );
  58. node_skl*
  59. GetInOnlyParamPairedWithOut (
  60. MEM_ITER& MemParamList
  61. );
  62. void
  63. FixupBeginProcExpr (
  64. expr_node* pExpr
  65. );
  66. void
  67. FixupFinishProcExpr (
  68. expr_node* pExpr
  69. );
  70. void
  71. TraverseParamsAndExprs (
  72. MEM_ITER& MemParamList,
  73. void (*CallFunc)( expr_node* )
  74. );
  75. // routines
  76. /****************************************************************************
  77. CloneIFAndSplitMethods:
  78. Given an interface, copy it and split the methods for async. e.g.
  79. method IFoo::Foo becomes AsyncIFoo::Begin_Bar and AsyncIFoo::Finish_Bar.
  80. ****************************************************************************/
  81. node_interface*
  82. CloneIFAndSplitMethods (
  83. node_interface* pSrc
  84. )
  85. {
  86. node_interface* pAsyncIntf = DuplicateNodeInterface (
  87. pSrc,
  88. szAsyncIntfPrefix,
  89. uAsyncIntfPrefixLen
  90. ) ;
  91. if ( pAsyncIntf )
  92. {
  93. // for [call_as] fixups
  94. ITERATOR BeginProcList;
  95. ITERATOR FinishProcList;
  96. // each IFoo::Bar() becomes,
  97. named_node* pNodeProcItr = 0;
  98. named_node* pPrevSibling = 0;
  99. MEM_ITER MemList( pSrc );
  100. while ( ( pNodeProcItr = MemList.GetNext() ) != 0 )
  101. {
  102. if ( pNodeProcItr->NodeKind() == NODE_PROC )
  103. {
  104. // AsyncIFoo::Begin_Bar()
  105. node_proc* pProcBegin = DuplicateNodeProc (
  106. (node_proc*)pNodeProcItr,
  107. szBeginProcPrefix,
  108. uBeginProcPrefixLen,
  109. CurrentIntfKey,
  110. BeginProcList
  111. );
  112. pProcBegin->SetIsBeginProc();
  113. if ( pPrevSibling )
  114. {
  115. pPrevSibling->SetSibling( pProcBegin );
  116. }
  117. else
  118. {
  119. pAsyncIntf->SetFirstMember( pProcBegin );
  120. }
  121. // AsyncIFoo::Finish_Bar()
  122. node_proc* pProcFinish = DuplicateNodeProc (
  123. (node_proc*)pNodeProcItr,
  124. szFinishProcPrefix,
  125. uFinishProcPrefixLen,
  126. CurrentIntfKey,
  127. FinishProcList
  128. );
  129. pProcFinish->SetIsFinishProc();
  130. pProcFinish->SetBeginProc( pProcBegin );
  131. pProcBegin->SetSibling( pProcFinish );
  132. pPrevSibling = pProcFinish;
  133. // AsyncIFoo::Begin_Bar() gets all [in] params of IFoo::Bar() &
  134. // AsyncIFoo::Finish_Bar() gets all [out] params IFoo::Bar().
  135. MEM_ITER MemParamList( (node_proc*)pNodeProcItr );
  136. named_node* pNodeParamItr = 0;
  137. MemParamList.Init();
  138. while ( ( pNodeParamItr = (node_param *) MemParamList.GetNext() ) != 0 )
  139. {
  140. // if parameter has [in] or, does not have either [in] or [out] attributes
  141. // assume [in] by default
  142. if ( pNodeParamItr->FInSummary( ATTR_IN ) ||
  143. !( pNodeParamItr->FInSummary( ATTR_IN ) || pNodeParamItr->FInSummary( ATTR_OUT ) ) )
  144. {
  145. ( (node_param*) pNodeParamItr )->SetAsyncBeginSibling (
  146. DuplicateNodeParam( (node_param*)pNodeParamItr, pProcBegin )
  147. );
  148. }
  149. if ( pNodeParamItr->FInSummary( ATTR_OUT )
  150. // || ( (node_param *) pNodeParamItr )->IsTaggedForAsyncFinishParamList()
  151. )
  152. {
  153. ( (node_param*) pNodeParamItr )->SetAsyncFinishSibling (
  154. DuplicateNodeParam( (node_param*)pNodeParamItr, pProcFinish )
  155. );
  156. }
  157. }
  158. // fix up expr in Begin_* and Finish_*
  159. MEM_ITER BeginProcParamList( pProcBegin );
  160. TraverseParamsAndExprs( BeginProcParamList, FixupBeginProcExpr );
  161. MEM_ITER FinishProcParamList( pProcFinish );
  162. TraverseParamsAndExprs( FinishProcParamList, FixupFinishProcExpr );
  163. }
  164. }
  165. // [call_as] fixups
  166. // [call_as(Baz)] IFoo::Bar() becomes,
  167. // [call_as(Begin_Baz)] AsyncIFoo::Begin_Bar()
  168. // [call_as(Finish_Baz)] AsyncIFoo::Finish_Bar()
  169. MEM_ITER AsyncMemList( pAsyncIntf );
  170. AsyncMemList.Init();
  171. while ( ( pNodeProcItr = AsyncMemList.GetNext() ) != 0 )
  172. {
  173. node_call_as* pCallAs = ( node_call_as* )pNodeProcItr->GetAttribute( ATTR_CALL_AS );
  174. if ( pCallAs )
  175. {
  176. FixupCallAs( pCallAs, BeginProcList );
  177. pNodeProcItr = AsyncMemList.GetNext();
  178. // if Begin_* has [call_as] Finish_* has it too.
  179. pCallAs = ( node_call_as* )pNodeProcItr->GetAttribute( ATTR_CALL_AS );
  180. FixupCallAs( pCallAs, FinishProcList );
  181. }
  182. }
  183. }
  184. return pAsyncIntf;
  185. }
  186. /****************************************************************************
  187. DuplicateNodeInterface:
  188. Duplicate an interface changing it's name from IFoo to AsyncIFoo and
  189. changing the [async_uuid] attribute to [uuid]
  190. ****************************************************************************/
  191. node_interface*
  192. DuplicateNodeInterface (
  193. node_interface* pIntfSrc,
  194. const char* const szPrefix,
  195. unsigned short uPrefixLen
  196. )
  197. {
  198. node_interface* pIntfDup = new node_interface;
  199. if ( pIntfDup )
  200. {
  201. *pIntfDup = *pIntfSrc;
  202. // new named_node get a new copy of the attributes
  203. pIntfDup->CopyAttributes( pIntfSrc );
  204. // members will be added later
  205. pIntfDup->SetFirstMember( 0 );
  206. // async interface inherits from base interface's async clone
  207. node_interface* pSrcBase = pIntfSrc->GetMyBaseInterface();
  208. if ( pSrcBase && pSrcBase->GetAsyncInterface() )
  209. {
  210. pIntfDup->SetMyBaseInterfaceReference (
  211. new node_interface_reference(
  212. pSrcBase->GetAsyncInterface()
  213. )
  214. );
  215. }
  216. // [async_uuid] becomes [uuid]
  217. node_guid* pAsyncGuid = (node_guid*) pIntfSrc->GetAttribute( ATTR_ASYNCUUID );
  218. char* szGuid = new char[strlen(pAsyncGuid->GetGuidString())+1];
  219. strcpy( szGuid, pAsyncGuid->GetGuidString() );
  220. pIntfDup->RemoveAttribute( ATTR_GUID );
  221. pIntfDup->RemoveAttribute( ATTR_ASYNCUUID );
  222. pIntfDup->SetAttribute( new node_guid( szGuid, ATTR_GUID ) );
  223. // IFoo becomes AsyncIFoo
  224. char* szName = new char[strlen(pIntfSrc->GetSymName())+uPrefixLen+1];
  225. strcpy( szName, szPrefix );
  226. strcat( szName, pIntfSrc->GetSymName() );
  227. pIntfDup->SetSymName( szName );
  228. // AsyncIFoo added to the list of interfaces
  229. pIntfDup->SetSibling( pIntfSrc->GetSibling() );
  230. pIntfSrc->SetSibling( pIntfDup );
  231. CurrentIntfKey = (unsigned short) pInterfaceDict->AddElement( pIntfDup );
  232. SymKey SKey( pIntfDup->GetSymName(), NAME_DEF );
  233. named_node* pFound = pBaseSymTbl->SymSearch( SKey );
  234. if ( pFound )
  235. {
  236. pFound->SetChild( pIntfDup );
  237. }
  238. }
  239. return pIntfDup;
  240. }
  241. /****************************************************************************
  242. DuplicateNodeProc
  243. Duplicate a node_proc and prefix it's name with the given string.
  244. Only the procedure node is duplicated, parameters are not set.
  245. ****************************************************************************/
  246. node_proc*
  247. DuplicateNodeProc (
  248. node_proc* pProcSrc,
  249. const char* const szPrefix,
  250. unsigned uPrefixLen,
  251. unsigned long uInterfaceKey,
  252. ITERATOR& Itr
  253. )
  254. {
  255. node_proc* pProcDup = new node_proc( short( 0 ), true );
  256. // pProcSrc->CopyTo( pProcDup );
  257. *pProcDup = *pProcSrc;
  258. pProcDup->SetSibling( 0 );
  259. pProcDup->SetClientCorrelationCount();
  260. pProcDup->SetServerCorrelationCount();
  261. // new named_node get a new copy of the attributes
  262. pProcDup->CopyAttributes( pProcSrc );
  263. // members will be added later
  264. pProcDup->SetFirstMember( 0 );
  265. pProcDup->SetInterfaceKey( uInterfaceKey );
  266. char* szName = new char[strlen(pProcSrc->GetSymName())+uPrefixLen+1];
  267. strcpy( szName, szPrefix );
  268. strcat( szName, pProcSrc->GetSymName() );
  269. pProcDup->SetSymName( szName );
  270. ITERATOR_INSERT( Itr, pProcDup );
  271. return pProcDup;
  272. }
  273. /****************************************************************************
  274. DuplicateNodeParam:
  275. Duplicate the given parameter and attach it to the given procedure.
  276. ****************************************************************************/
  277. node_param*
  278. DuplicateNodeParam (
  279. node_param* pParamSrc,
  280. node_proc* pProc
  281. )
  282. {
  283. node_param* pParamDup = new node_param;
  284. // pParamSrc->CopyTo( pParamDup );
  285. *pParamDup = *pParamSrc;
  286. pParamDup->SetSibling( 0 );
  287. // new named_node get a new copy of the attributes
  288. pParamDup->CopyAttributes( pParamSrc );
  289. pProc->AddLastMember( pParamDup );
  290. return pParamDup;
  291. }
  292. /****************************************************************************
  293. FixupCallAs:
  294. When an async interface is created from a sync one the duplicated
  295. interface still points to stuff in the original interface. Fix up [call_as]
  296. procs to point to the split procedures instead.
  297. ****************************************************************************/
  298. void
  299. FixupCallAs( node_call_as* pCallAs, ITERATOR& ProcList )
  300. {
  301. char* szProcName = pCallAs->GetCallAsName();
  302. node_proc* pProcItr = 0;
  303. ITERATOR_INIT( ProcList );
  304. while ( ITERATOR_GETNEXT( ProcList, pProcItr ) )
  305. {
  306. // advance past Begin_ or Finish_
  307. char* szProcItrName = pProcItr->GetSymName();
  308. szProcItrName = strchr( szProcItrName, '_' );
  309. szProcItrName++;
  310. // semantic errors will be caught in node_proc::SemanticAnalysis()
  311. if ( !strcmp( szProcItrName, szProcName ) )
  312. {
  313. pCallAs->SetCallAsName( pProcItr->GetSymName() );
  314. pCallAs->SetCallAsType( pProcItr );
  315. break;
  316. }
  317. }
  318. }
  319. /****************************************************************************
  320. FindInOnlyParamInExpr:
  321. Search an expression for an in-only parameter.
  322. ****************************************************************************/
  323. node_skl*
  324. FindInOnlyParamInExpr (
  325. expr_node* pExpr
  326. )
  327. {
  328. node_skl* pRet = 0;
  329. if ( pExpr )
  330. {
  331. if ( pExpr->IsAVariable() )
  332. {
  333. if ( !pExpr->GetType()->FInSummary( ATTR_OUT ) )
  334. pRet = pExpr->GetType();
  335. }
  336. else
  337. {
  338. pRet = FindInOnlyParamInExpr( pExpr->GetLeft() );
  339. if ( !pRet )
  340. {
  341. pRet = FindInOnlyParamInExpr( pExpr->GetRight() );
  342. }
  343. }
  344. }
  345. return pRet;
  346. }
  347. /****************************************************************************
  348. GetUnknownExpression:
  349. Determine if a given expression is a non-simple with in parameters.
  350. An expression is simple if it is NULL, a constant, or a single variable.
  351. An expression is also simple if it is of the form "var+1", "var-1",
  352. "var*2", "var/2", or "*var" (these are simple because they can be
  353. expressed by directly in the correlation descriptor).
  354. If the expression is non-simple with in parameters, non-0 is returned,
  355. else 0 is returned.
  356. ****************************************************************************/
  357. bool
  358. IsSimpleExpression(
  359. expr_node* pExpr
  360. )
  361. {
  362. if ( ! pExpr || pExpr->IsAVariable() || pExpr->IsConstant() )
  363. {
  364. return true;
  365. }
  366. expr_node* pExprLHS = pExpr->GetLeft();
  367. expr_node* pExprRHS = pExpr->GetRight();
  368. switch ( pExpr->GetOperator() )
  369. {
  370. case OP_SLASH:
  371. case OP_STAR:
  372. if ( pExprLHS->IsAVariable() &&
  373. pExprRHS->IsConstant() &&
  374. ((expr_constant *)pExprRHS)->GetValue() == 2 )
  375. {
  376. return true;
  377. }
  378. break;
  379. case OP_PLUS :
  380. case OP_MINUS :
  381. if ( pExprLHS->IsAVariable() &&
  382. pExprRHS->IsConstant() &&
  383. ((expr_constant *)pExprRHS)->GetValue() == 1 )
  384. {
  385. return true;
  386. }
  387. break;
  388. case OP_UNARY_INDIRECTION :
  389. if ( pExprLHS->IsAVariable() )
  390. {
  391. return true;
  392. }
  393. break;
  394. default:
  395. break;
  396. }
  397. return false;
  398. }
  399. /****************************************************************************
  400. GetInOnlyParamPairedWithOut:
  401. Determine if any of the expression in the given parameter list mixes
  402. in and out parameters in non-simple ways. Return non-0 if the do and 0
  403. if they don't.
  404. ****************************************************************************/
  405. node_skl*
  406. GetInOnlyParamPairedWithOut (
  407. MEM_ITER& MemParamList
  408. )
  409. {
  410. named_node* pNodeParamItr = 0;
  411. node_skl* pNode = 0;
  412. MemParamList.Init();
  413. while ( ( pNodeParamItr = (node_param *) MemParamList.GetNext() ) != 0 )
  414. {
  415. if ( !pNodeParamItr->GetAttribute( ATTR_OUT ) )
  416. {
  417. continue;
  418. }
  419. node_base_attr* pAttr;
  420. ATTRLIST AList = pNodeParamItr->GetAttributeList(AList);
  421. ATTR_T lastAttrID = ATTR_NONE;
  422. int nAttrInstance = 0;
  423. bool bFirstInstanceWasNull = false;
  424. bool bHasInParam = false;
  425. for ( pAttr = AList.GetFirst(); NULL != pAttr && 0 == pNode; pAttr = pAttr->GetNext() )
  426. {
  427. ATTR_T thisAttrID = pAttr->GetAttrID();
  428. if ( thisAttrID == lastAttrID )
  429. ++nAttrInstance;
  430. else
  431. nAttrInstance = 1;
  432. lastAttrID = thisAttrID;
  433. switch ( thisAttrID )
  434. {
  435. case ATTR_SIZE:
  436. case ATTR_LENGTH:
  437. case ATTR_SWITCH_IS:
  438. case ATTR_IID_IS:
  439. case ATTR_FIRST:
  440. case ATTR_LAST:
  441. case ATTR_MAX:
  442. case ATTR_MIN:
  443. {
  444. if ( 1 == nAttrInstance )
  445. {
  446. bFirstInstanceWasNull = ( NULL == pAttr->GetExpr() );
  447. bHasInParam = false;
  448. }
  449. // Don't allow any dimensions after one with an in param
  450. if ( bHasInParam )
  451. {
  452. pNode = (node_skl *) -1;
  453. break;
  454. }
  455. if ( FindInOnlyParamInExpr( pAttr->GetExpr() ) )
  456. {
  457. if ( ! IsSimpleExpression( pAttr->GetExpr() )
  458. || ( nAttrInstance > 2 )
  459. || ( nAttrInstance == 2 && ! bFirstInstanceWasNull ) )
  460. {
  461. pNode = (node_skl *) -1;
  462. break;
  463. }
  464. bHasInParam = true;
  465. }
  466. break;
  467. }
  468. case ATTR_BYTE_COUNT:
  469. {
  470. pNode = ( ( node_byte_count* ) pAttr )->GetByteCountParam();
  471. if ( pNode->FInSummary( ATTR_OUT ) )
  472. {
  473. pNode = 0;
  474. }
  475. break;
  476. }
  477. default:
  478. // Only need to worry about attributes with parameter
  479. // expressions
  480. break;
  481. }
  482. }
  483. if ( pNode )
  484. {
  485. // Do this to have an error message context.
  486. pNode = pNodeParamItr;
  487. break;
  488. }
  489. }
  490. return pNode;
  491. }
  492. /****************************************************************************
  493. FixupFinishProcExpr:
  494. When an async interface is created from a sync one the duplicated
  495. interface still points to stuff in the original interface. Fix up
  496. parameters in a Finish method to point to the duplicated parameters
  497. in the async interface instead of the original sync interface.
  498. ****************************************************************************/
  499. void
  500. FixupFinishProcExpr (
  501. expr_node* pExpr
  502. )
  503. {
  504. if ( pExpr )
  505. {
  506. // If we don't have a type then that means we have a reference to a
  507. // variable that doesn't exist. The dangling reference will be caught
  508. // and reported in FIELD_ATTR_INFO::Validate
  509. if ( NULL == pExpr->GetType() )
  510. {
  511. return;
  512. }
  513. if ( pExpr->GetType()->NodeKind() == NODE_PARAM )
  514. {
  515. node_param* pParam = (node_param*)pExpr->GetType();
  516. if ( pParam->GetAsyncFinishSibling() )
  517. {
  518. pExpr->SetType( pParam->GetAsyncFinishSibling() );
  519. }
  520. else
  521. {
  522. pExpr->SetType( pParam->GetAsyncBeginSibling() );
  523. pParam->GetAsyncBeginSibling()->SaveForAsyncFinish();
  524. }
  525. }
  526. FixupFinishProcExpr( pExpr->GetLeft() );
  527. FixupFinishProcExpr( pExpr->GetRight() );
  528. // FixupFinishProcExpr( pExpr->GetRelational() );
  529. }
  530. }
  531. /****************************************************************************
  532. FixupFinishProcExpr:
  533. When an async interface is created from a sync one the duplicated
  534. interface still points to stuff in the original interface. Fix up
  535. parameters in a Begin method to point to the duplicated parameters
  536. in the async interface instead of the original sync interface.
  537. ****************************************************************************/
  538. void
  539. FixupBeginProcExpr (
  540. expr_node* pExpr
  541. )
  542. {
  543. if ( pExpr )
  544. {
  545. // If we don't have a type then that means we have a reference to a
  546. // variable that doesn't exist. The dangling reference will be caught
  547. // and reported in FIELD_ATTR_INFO::Validate
  548. if ( NULL == pExpr->GetType() )
  549. {
  550. return;
  551. }
  552. if ( pExpr->GetType()->NodeKind() == NODE_PARAM )
  553. {
  554. node_param* pParam = (node_param*)pExpr->GetType();
  555. pExpr->SetType( pParam->GetAsyncBeginSibling() );
  556. }
  557. FixupBeginProcExpr( pExpr->GetLeft() );
  558. FixupBeginProcExpr( pExpr->GetRight() );
  559. // FixupExpr( pExpr->GetRelational() );
  560. }
  561. }
  562. /****************************************************************************
  563. FixupFinishProcExpr:
  564. When an async interface is created from a sync one the duplicated
  565. interface still points to stuff in the original interface. This routine
  566. traverses the parameters and fixes up the pointers to point to the
  567. proper stuff in the duplicated interface instead.
  568. This routine is quite specific to the needs of async and is not meant as
  569. a general purpose parameter traversing function.
  570. ****************************************************************************/
  571. void
  572. TraverseParamsAndExprs (
  573. MEM_ITER& MemParamList,
  574. void (*CallFunc)( expr_node* )
  575. )
  576. {
  577. node_param* pNodeParamItr = 0;
  578. MemParamList.Init();
  579. while ( ( pNodeParamItr = ( node_param *) MemParamList.GetNext() ) != 0 )
  580. {
  581. node_base_attr* pAttr;
  582. ATTRLIST AList = pNodeParamItr->GetAttributeList(AList);
  583. for ( pAttr = AList.GetFirst(); NULL != pAttr; pAttr = pAttr->GetNext() )
  584. {
  585. switch ( pAttr->GetAttrID() )
  586. {
  587. case ATTR_SIZE:
  588. case ATTR_LENGTH:
  589. case ATTR_SWITCH_IS:
  590. case ATTR_IID_IS:
  591. case ATTR_FIRST:
  592. case ATTR_LAST:
  593. case ATTR_MAX:
  594. case ATTR_MIN:
  595. {
  596. CallFunc( pAttr->GetExpr() );
  597. break;
  598. }
  599. case ATTR_BYTE_COUNT:
  600. {
  601. node_param* pParam = ( ( node_byte_count* ) pAttr )->GetByteCountParam();
  602. if ( FixupBeginProcExpr == CallFunc )
  603. {
  604. ( ( node_byte_count* ) pAttr )->SetByteCountParam( pParam->GetAsyncBeginSibling() );
  605. }
  606. else
  607. {
  608. if ( pParam->GetAsyncFinishSibling() )
  609. {
  610. ( ( node_byte_count* ) pAttr )->SetByteCountParam( pParam->GetAsyncFinishSibling() );
  611. }
  612. else
  613. {
  614. ( ( node_byte_count* ) pAttr )->SetByteCountParam( pParam->GetAsyncBeginSibling() );
  615. pParam->GetAsyncBeginSibling()->SaveForAsyncFinish();
  616. }
  617. }
  618. }
  619. default:
  620. // Only need to worry about attributes with parameter
  621. // expressions
  622. break;
  623. }
  624. }
  625. }
  626. }