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.

767 lines
20 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1997 Microsoft Corporation. All Rights Reserved.
  5. Component: Component Collection
  6. File: Compcol.h
  7. Owner: DmitryR
  8. This is the Component Collection header file.
  9. Component collection replaces: (used in:)
  10. COleVar, COleVarList (HitObj, Session, Application)
  11. CObjectCover (HitObj, Server, Session)
  12. VariantLink HasTable (Session, Application)
  13. ===================================================================*/
  14. #ifndef COMPCOL_H
  15. #define COMPCOL_H
  16. /*===================================================================
  17. Special OLE stuff
  18. ===================================================================*/
  19. #include "gip.h"
  20. /*===================================================================
  21. Misc declarations
  22. ===================================================================*/
  23. #include "hashing.h"
  24. #include "idhash.h"
  25. #include "dbllink.h"
  26. #include "util.h"
  27. #include "viperint.h"
  28. #include "memcls.h"
  29. // Forward declarations
  30. class CHitObj;
  31. class CAppln;
  32. class CSession;
  33. class CScriptingContext;
  34. // Component Types
  35. #define CompType DWORD
  36. #define ctUnknown 0x00000000 // (Used as UnInitialized state)
  37. #define ctTagged 0x00000001 // Created by <OBJECT ...> tag
  38. #define ctProperty 0x00000002 // Created with Session("xxx") =
  39. #define ctUnnamed 0x00000004 // Created with Server.CreateObject()
  40. // Scope levels
  41. #define CompScope DWORD
  42. #define csUnknown 0x00000000
  43. #define csAppln 0x00000001
  44. #define csSession 0x00000002
  45. #define csPage 0x00000004
  46. // COM threading models
  47. #define CompModel DWORD
  48. #define cmUnknown 0x00000000
  49. #define cmSingle 0x00000001
  50. #define cmApartment 0x00000002
  51. #define cmFree 0x00000004
  52. #define cmBoth 0x00000008
  53. /*===================================================================
  54. Utility Functions Prototypes
  55. ===================================================================*/
  56. HRESULT CompModelFromCLSID
  57. (
  58. const CLSID &ClsId,
  59. CompModel *pcmModel = NULL,
  60. BOOL *pfInProc = NULL
  61. );
  62. BOOL FIsIntrinsic(IDispatch *pdisp);
  63. inline BOOL FIsIntrinsic(VARIANT *pVar)
  64. {
  65. if (V_VT(pVar) != VT_DISPATCH)
  66. return FALSE;
  67. return FIsIntrinsic(V_DISPATCH(pVar));
  68. }
  69. /*===================================================================
  70. OnPageInfo struct used to cache ids of OnStartPage()/OnEndPage()
  71. ===================================================================*/
  72. #define ONPAGEINFO_ONSTARTPAGE 0
  73. #define ONPAGEINFO_ONENDPAGE 1
  74. #define ONPAGE_METHODS_MAX ONPAGEINFO_ONENDPAGE+1
  75. struct COnPageInfo
  76. {
  77. DISPID m_rgDispIds[ONPAGE_METHODS_MAX];
  78. BOOL FHasAnyMethod() const;
  79. };
  80. inline BOOL COnPageInfo::FHasAnyMethod() const
  81. {
  82. #if (ONPAGE_METHODS_MAX == 2)
  83. // fast implementation for the real case
  84. return
  85. (
  86. m_rgDispIds[0] != DISPID_UNKNOWN ||
  87. m_rgDispIds[1] != DISPID_UNKNOWN
  88. );
  89. #else
  90. for (int i = 0; i < ONPAGE_METHODS_MAX; i++)
  91. {
  92. if (m_rgDispIds[i] != DISPID_UNKNOWN)
  93. return TRUE;
  94. }
  95. return FALSE;
  96. #endif
  97. }
  98. /*===================================================================
  99. Component object stores information about a single object
  100. Each component object belongs to a component collection
  101. Component objects are linked into a list, also
  102. tagged objects are hashed by name, and
  103. properties are hashed by name, and
  104. all instantiated objects are hashed by IUnknown*
  105. ===================================================================*/
  106. class CComponentObject : public CLinkElem
  107. {
  108. friend class CComponentCollection;
  109. friend class CPageComponentManager;
  110. friend class CComponentIterator;
  111. private:
  112. // properties
  113. CompScope m_csScope : 4; // Scope
  114. CompType m_ctType : 4; // Component Object Type
  115. CompModel m_cmModel : 4; // Threading behavior (from Registry)
  116. DWORD m_fAgile : 1; // Agile?
  117. // flag to indicate if OnPageInfo was queried
  118. DWORD m_fOnPageInfoCached : 1;
  119. // flag: on-start-page done, waiting to do on-end-page
  120. DWORD m_fOnPageStarted : 1;
  121. // flag to avoid multiple unsuccessful attempts to instantiate
  122. DWORD m_fFailedToInstantiate : 1;
  123. // flag to mark instantiated (or tried to inst.) tagged objects
  124. DWORD m_fInstantiatedTagged : 1;
  125. // flag to mark the object in pointer cache
  126. DWORD m_fInPtrCache : 1;
  127. // variant filled with value?
  128. DWORD m_fVariant : 1;
  129. // name was allocated (longer than the default buffer)?
  130. DWORD m_fNameAllocated : 1;
  131. // pointers to object and type info
  132. IDispatch *m_pDisp; // Dispatch interface pointer
  133. IUnknown *m_pUnknown; // IUnknown interface pointer
  134. union
  135. {
  136. CLSID m_ClsId; // Class id (for tagged and unnamed)
  137. VARIANT m_Variant; // Variant (for properties)
  138. };
  139. // For objects that use OLE cookie API
  140. DWORD m_dwGIPCookie;
  141. // cached OnPageInfo
  142. COnPageInfo m_OnPageInfo;
  143. // pointer to connect objects into link list
  144. CComponentObject *m_pCompNext; // Next object in the link list.
  145. CComponentObject *m_pCompPrev; // Prev object in the link list.
  146. // buffer for names that fit in (36 bytes = 17 unicode chars + '\0')
  147. BYTE m_rgbNameBuffer[36];
  148. private:
  149. // constructor is private! (not for outside use)
  150. CComponentObject
  151. (
  152. CompScope csScope,
  153. CompType ctType,
  154. CompModel cmModel
  155. );
  156. ~CComponentObject();
  157. // Initializes CLinkElem portion
  158. HRESULT Init(LPWSTR pwszName, DWORD cbName);
  159. // Releases all interface pointers (used by clear)
  160. HRESULT ReleaseAll();
  161. // Clears out data (releases all) leaving link alone
  162. HRESULT Clear();
  163. // Create instance if not there already
  164. HRESULT Instantiate(CHitObj *pHitObj);
  165. HRESULT TryInstantiate(CHitObj *pHitObj);
  166. // Set value from variant
  167. HRESULT SetPropertyValue(VARIANT *);
  168. // Convert Object to be GIP cookie
  169. HRESULT ConvertToGIPCookie();
  170. // Get and cache the ids for OnStart methods
  171. HRESULT GetOnPageInfo();
  172. public:
  173. // functions to get the COM object (internally resolve cookies)
  174. HRESULT GetAddRefdIDispatch(IDispatch **ppdisp);
  175. HRESULT GetAddRefdIUnknown(IUnknown **ppunk);
  176. HRESULT GetVariant(VARIANT *pVar); // not for GIP cookies
  177. // Check if the unnamed page level object object
  178. // can be removed without waiting till the end of request
  179. inline BOOL FEarlyReleaseAllowed() const;
  180. // public inlines to access the object's properties
  181. // these are the only methods available from outside
  182. inline LPWSTR GetName();
  183. inline CompScope GetScope() const;
  184. inline CompType GetType() const;
  185. inline CompModel GetModel() const;
  186. inline BOOL FAgile() const;
  187. // Retrieve the cached ids
  188. inline const COnPageInfo *GetCachedOnPageInfo() const;
  189. public:
  190. #ifdef DBG
  191. void AssertValid() const;
  192. #else
  193. void AssertValid() const {}
  194. #endif
  195. // Cache on per-class basis
  196. ACACHE_INCLASS_DEFINITIONS()
  197. };
  198. inline LPWSTR CComponentObject::GetName()
  199. {
  200. return (LPWSTR)m_pKey;
  201. }
  202. inline CompScope CComponentObject::GetScope() const
  203. {
  204. return m_csScope;
  205. }
  206. inline CompType CComponentObject::GetType() const
  207. {
  208. return m_ctType;
  209. }
  210. inline CompType CComponentObject::GetModel() const
  211. {
  212. return m_cmModel;
  213. }
  214. inline BOOL CComponentObject::FAgile() const
  215. {
  216. return m_fAgile;
  217. }
  218. inline const COnPageInfo *CComponentObject::GetCachedOnPageInfo() const
  219. {
  220. return m_fOnPageInfoCached ? &m_OnPageInfo : NULL;
  221. }
  222. inline BOOL CComponentObject::FEarlyReleaseAllowed() const
  223. {
  224. return (!m_fOnPageStarted && // no need to do on-end-page
  225. !m_fInPtrCache && // no need to search by pointer
  226. m_csScope == csPage && // page scoped
  227. m_ctType == ctUnnamed); // created with Server.CreateObject()
  228. }
  229. /*===================================================================
  230. Component collection is a manager of various types of component
  231. objects:
  232. 1) Tagged objects (<OBJECT...>) (instantiated or not)
  233. 2) Session("xxx") and Application("xxx") properties
  234. 3) Unnamed objects (Server.CreateObject())
  235. It hashes added objects as needed (some by name, IUnkn *, etc.)
  236. The idea is to isolate the above issues from outside as much
  237. as possible.
  238. Component collections exist under session, application, hitobj
  239. ===================================================================*/
  240. class CComponentCollection
  241. {
  242. friend class CPageComponentManager;
  243. friend class CComponentIterator;
  244. friend class CVariantsIterator;
  245. private:
  246. CompScope m_csScope : 4; // scope (page, session, appln)
  247. DWORD m_fUseTaggedArray : 1; // remember tagged objects array?
  248. DWORD m_fUsePropArray : 1; // remember properties array?
  249. DWORD m_fHasComProperties : 1; // any property VARIANTs that could be objects
  250. // hash table (by name) of tagged objects
  251. CHashTableStr m_htTaggedObjects;
  252. // hash table (by name) of properties (4)
  253. CHashTableStr m_htProperties;
  254. // hash table (by IUnknown *) of all instances
  255. CIdHashTable m_htidIUnknownPtrs;
  256. // Pointer to the component objects link list
  257. CComponentObject *m_pCompFirst; // First object in link list.
  258. // Array of pointers to static objects to speed lookup by index
  259. CPtrArray m_rgpvTaggedObjects;
  260. // Array of pointers to properties to speed lookup by index
  261. CPtrArray m_rgpvProperties;
  262. // Various object counts in the collection
  263. USHORT m_cAllTagged; // all tagged objects
  264. USHORT m_cInstTagged; // instanciated tagged objects
  265. USHORT m_cProperties; // all properties
  266. USHORT m_cUnnamed; // number of unnamed objects
  267. // Add/remove object to the component objects link list
  268. HRESULT AddComponentToList(CComponentObject *pObj);
  269. HRESULT RemoveComponentFromList(CComponentObject *pObj);
  270. // Add named object to the proper hash table by name
  271. HRESULT AddComponentToNameHash
  272. (
  273. CComponentObject *pObj,
  274. LPWSTR pwszName,
  275. DWORD cbName
  276. );
  277. // Add named object to the IUnkown * hash table
  278. HRESULT AddComponentToPtrHash(CComponentObject *pObj);
  279. // Find by name (for tagged)
  280. HRESULT FindComponentObjectByName
  281. (
  282. LPWSTR pwszName,
  283. DWORD cbName,
  284. CComponentObject **ppObj
  285. );
  286. // Find by name (for properties)
  287. HRESULT FindComponentPropertyByName
  288. (
  289. LPWSTR pwszName,
  290. DWORD cbName,
  291. CComponentObject **ppObj
  292. );
  293. // Find by IUnknown*
  294. HRESULT FindComponentByIUnknownPtr
  295. (
  296. IUnknown *pUnk,
  297. CComponentObject **ppObj
  298. );
  299. // Fill in the arrays for access by index for the first time
  300. HRESULT StartUsingTaggedObjectsArray();
  301. HRESULT StartUsingPropertiesArray();
  302. public:
  303. // Add various kinds of objects to the collection
  304. // They are also used by
  305. // CPageComponentManager AddScoped...()
  306. HRESULT AddTagged
  307. (
  308. LPWSTR pwszName,
  309. const CLSID &clsid,
  310. CompModel cmModel
  311. );
  312. HRESULT AddProperty
  313. (
  314. LPWSTR pwszName,
  315. VARIANT *pVariant,
  316. CComponentObject **ppObj = NULL
  317. );
  318. HRESULT AddUnnamed
  319. (
  320. const CLSID &clsid,
  321. CompModel cmModel,
  322. CComponentObject **ppObj
  323. );
  324. HRESULT GetTagged
  325. (
  326. LPWSTR pwszName,
  327. CComponentObject **ppObj
  328. );
  329. HRESULT GetProperty
  330. (
  331. LPWSTR pwszName,
  332. CComponentObject **ppObj
  333. );
  334. HRESULT GetNameByIndex
  335. (
  336. CompType ctType,
  337. int index,
  338. LPWSTR *ppwszName
  339. );
  340. HRESULT RemoveComponent(CComponentObject *pObj);
  341. HRESULT RemoveProperty(LPWSTR pwszName);
  342. HRESULT RemoveAllProperties();
  343. CComponentCollection();
  344. ~CComponentCollection();
  345. HRESULT Init(CompScope csScope);
  346. HRESULT UnInit();
  347. BOOL FHasStateInfo() const; // TRUE when state-full
  348. BOOL FHasObjects() const; // TRUE when contains objects
  349. DWORD GetPropertyCount() const;
  350. DWORD GetTaggedObjectCount() const;
  351. public:
  352. #ifdef DBG
  353. void AssertValid() const;
  354. #else
  355. void AssertValid() const {}
  356. #endif
  357. // Cache on per-class basis
  358. ACACHE_INCLASS_DEFINITIONS()
  359. };
  360. inline BOOL CComponentCollection::FHasStateInfo() const
  361. {
  362. return ((m_cAllTagged + m_cProperties + m_cUnnamed) > 0);
  363. }
  364. inline BOOL CComponentCollection::FHasObjects() const
  365. {
  366. return (m_cInstTagged > 0 || m_cUnnamed > 0 ||
  367. (m_cProperties > 0 && m_fHasComProperties));
  368. }
  369. inline DWORD CComponentCollection::GetPropertyCount() const
  370. {
  371. return m_cProperties;
  372. }
  373. inline DWORD CComponentCollection::GetTaggedObjectCount() const
  374. {
  375. return m_cAllTagged;
  376. }
  377. inline HRESULT CComponentCollection::AddComponentToList
  378. (
  379. CComponentObject *pObj
  380. )
  381. {
  382. pObj->m_pCompNext = m_pCompFirst;
  383. pObj->m_pCompPrev = NULL;
  384. if (m_pCompFirst)
  385. m_pCompFirst->m_pCompPrev = pObj;
  386. m_pCompFirst = pObj;
  387. return S_OK;
  388. }
  389. inline HRESULT CComponentCollection::RemoveComponentFromList
  390. (
  391. CComponentObject *pObj
  392. )
  393. {
  394. if (pObj->m_pCompPrev)
  395. pObj->m_pCompPrev->m_pCompNext = pObj->m_pCompNext;
  396. if (pObj->m_pCompNext)
  397. pObj->m_pCompNext->m_pCompPrev = pObj->m_pCompPrev;
  398. if (m_pCompFirst == pObj)
  399. m_pCompFirst = pObj->m_pCompNext;
  400. pObj->m_pCompPrev = pObj->m_pCompNext = NULL;
  401. return S_OK;
  402. }
  403. /*===================================================================
  404. A page object controls calls to OnStartPage(), OnEndPage().
  405. Page objects are used by CPageComponentManager
  406. They are hashed using IDispatch * to avoid multiple OnStartPage()
  407. calls for the same object.
  408. ===================================================================*/
  409. class CPageObject
  410. {
  411. friend class CPageComponentManager;
  412. private:
  413. IDispatch *m_pDisp; // Dispatch interface pointer
  414. COnPageInfo m_OnPageInfo; // cached OnPageInfo
  415. DWORD m_fStartPageCalled : 1;
  416. DWORD m_fEndPageCalled : 1;
  417. private: // the only access is using CPageComponentManager
  418. CPageObject();
  419. ~CPageObject();
  420. HRESULT Init(IDispatch *pDisp, const COnPageInfo &OnPageInfo);
  421. // Invoke OnStartPage or OnEndPage
  422. HRESULT InvokeMethod
  423. (
  424. DWORD iMethod,
  425. CScriptingContext *pContext,
  426. CHitObj *pHitObj
  427. );
  428. HRESULT TryInvokeMethod // used by InvokeMethod
  429. ( // inside TRY CATCH
  430. DISPID DispId,
  431. BOOL fOnStart,
  432. IDispatch *pDispContext,
  433. CHitObj *pHitObj
  434. );
  435. public:
  436. #ifdef DBG
  437. void AssertValid() const;
  438. #else
  439. void AssertValid() const {}
  440. #endif
  441. // Cache on per-class basis
  442. ACACHE_INCLASS_DEFINITIONS()
  443. };
  444. /*===================================================================
  445. Page component manager provides access to component collections
  446. for page, session, application level.
  447. It is associated with a HitObj.
  448. It also takes care of covering (OnStartPage(), OnEndPage()).
  449. ===================================================================*/
  450. class CPageComponentManager
  451. {
  452. private:
  453. // hashtable of page objects hashed by IDispatch *
  454. CIdHashTable m_htidPageObjects;
  455. // hit object (this page)
  456. CHitObj *m_pHitObj;
  457. // hash table iterator callbacks
  458. static IteratorCallbackCode DeletePageObjectCB(void *pvObj, void *, void *);
  459. static IteratorCallbackCode OnEndPageObjectCB(void *pvObj, void *pvHitObj, void *pvhr);
  460. private:
  461. // collections related to page, session and application
  462. HRESULT GetPageCollection(CComponentCollection **ppCollection);
  463. HRESULT GetSessionCollection(CComponentCollection **ppCollection);
  464. HRESULT GetApplnCollection(CComponentCollection **ppCollection);
  465. HRESULT GetCollectionByScope
  466. (
  467. CompScope csScope,
  468. CComponentCollection **ppCollection
  469. );
  470. // find objectc in any of the related collections
  471. // (internal private method)
  472. HRESULT FindScopedComponentByName
  473. (
  474. CompScope csScope,
  475. LPWSTR pwszName,
  476. DWORD cbName,
  477. BOOL fProperty,
  478. CComponentObject **ppObj,
  479. CComponentCollection **ppCollection = NULL
  480. );
  481. static HRESULT __stdcall InstantiateObjectFromMTA
  482. (
  483. void *pvObj,
  484. void *pvHitObj
  485. );
  486. public:
  487. CPageComponentManager();
  488. ~CPageComponentManager();
  489. HRESULT Init(CHitObj *pHitObj);
  490. // OnStartPage processing for an object that need it
  491. // (OnEndPage is done for all objects at the end of page)
  492. HRESULT OnStartPage
  493. (
  494. CComponentObject *pCompObj,
  495. CScriptingContext *pContext,
  496. const COnPageInfo *pOnPageInfo,
  497. BOOL *pfStarted
  498. );
  499. // request OnEndPage() for all objects that need it
  500. // (OnStartPage() is done on demand on per-object basis)
  501. HRESULT OnEndPageAllObjects();
  502. // Add various kinds of objects. Objects get added to the
  503. // right collection depending on scope argument
  504. HRESULT AddScopedTagged
  505. (
  506. CompScope csScope,
  507. LPWSTR pwszName,
  508. const CLSID &clsid,
  509. CompModel cmModel
  510. );
  511. HRESULT AddScopedProperty
  512. (
  513. CompScope csScope,
  514. LPWSTR pwszName,
  515. VARIANT *pVariant,
  516. CComponentObject **ppObj = NULL
  517. );
  518. // Server.CreateObject
  519. HRESULT AddScopedUnnamedInstantiated
  520. (
  521. CompScope csScope,
  522. const CLSID &clsid,
  523. CompModel cmModel,
  524. COnPageInfo *pOnPageInfo,
  525. CComponentObject **ppObj
  526. );
  527. // Get component object (tagged) by name.
  528. // Scope could be csUnknown
  529. HRESULT GetScopedObjectInstantiated
  530. (
  531. CompScope csScope,
  532. LPWSTR pwszName,
  533. DWORD cbName,
  534. CComponentObject **ppObj,
  535. BOOL *pfNewInstance
  536. );
  537. // Get component property by name. Scope could be csUnknown
  538. HRESULT GetScopedProperty
  539. (
  540. CompScope csScope,
  541. LPWSTR pwszName,
  542. CComponentObject **ppObj
  543. );
  544. // Find component by IUnknown * (or IDispatch *).
  545. HRESULT FindAnyScopeComponentByIUnknown
  546. (
  547. IUnknown *pUnk,
  548. CComponentObject **ppObj
  549. );
  550. HRESULT FindAnyScopeComponentByIDispatch
  551. (
  552. IDispatch *pDisp,
  553. CComponentObject **ppObj
  554. );
  555. // The same - but static - gets context from Viper
  556. static HRESULT FindComponentWithoutContext
  557. (
  558. IDispatch *pDisp,
  559. CComponentObject **ppObj
  560. );
  561. // Remove component -- the early release logic
  562. HRESULT RemoveComponent(CComponentObject *pObj);
  563. public:
  564. #ifdef DBG
  565. void AssertValid() const;
  566. #else
  567. void AssertValid() const {}
  568. #endif
  569. // Cache on per-class basis
  570. ACACHE_INCLASS_DEFINITIONS()
  571. };
  572. // Component iterator is used to go through component names
  573. // all the HitObj - reletated object across collections
  574. // Needed for scripting
  575. class CComponentIterator
  576. {
  577. private:
  578. CHitObj *m_pHitObj;
  579. DWORD m_fInited : 1;
  580. DWORD m_fFinished : 1;
  581. CompScope m_csLastScope : 4;
  582. CComponentObject *m_pLastObj;
  583. public:
  584. CComponentIterator(CHitObj *pHitObj = NULL);
  585. ~CComponentIterator();
  586. HRESULT Init(CHitObj *pHitObj);
  587. LPWSTR WStrNextComponentName();
  588. };
  589. // Variant Iterator is used to go through Property or Tagged object
  590. // names in a component collection. Needed for scripting
  591. class CVariantsIterator : public IEnumVARIANT
  592. {
  593. public:
  594. CVariantsIterator(CAppln *, DWORD);
  595. CVariantsIterator(CSession *, DWORD);
  596. ~CVariantsIterator();
  597. HRESULT Init();
  598. // The Big Three
  599. STDMETHODIMP QueryInterface(const GUID &, void **);
  600. STDMETHODIMP_(ULONG) AddRef();
  601. STDMETHODIMP_(ULONG) Release();
  602. // standard methods for iterators
  603. STDMETHODIMP Clone(IEnumVARIANT **ppEnumReturn);
  604. STDMETHODIMP Next(unsigned long cElements, VARIANT *rgVariant, unsigned long *pcElementsFetched);
  605. STDMETHODIMP Skip(unsigned long cElements);
  606. STDMETHODIMP Reset();
  607. private:
  608. ULONG m_cRefs; // reference count
  609. CComponentCollection *m_pCompColl; // collection we are iterating over
  610. DWORD m_dwIndex; // current position for iteration
  611. CAppln *m_pAppln; // application (to clone iterator and Lock())
  612. CSession *m_pSession; // session (to clone iterator)
  613. DWORD m_ctColType; // type of collection
  614. // Cache on per-class basis
  615. ACACHE_INCLASS_DEFINITIONS()
  616. };
  617. #endif // COMPCOL_H