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.

771 lines
21 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. // requests are executing in the MTA?
  132. DWORD m_fMTAConfigured : 1;
  133. // pointers to object and type info
  134. IDispatch *m_pDisp; // Dispatch interface pointer
  135. IUnknown *m_pUnknown; // IUnknown interface pointer
  136. union
  137. {
  138. CLSID m_ClsId; // Class id (for tagged and unnamed)
  139. VARIANT m_Variant; // Variant (for properties)
  140. };
  141. // For objects that use OLE cookie API
  142. DWORD m_dwGIPCookie;
  143. // cached OnPageInfo
  144. COnPageInfo m_OnPageInfo;
  145. // pointer to connect objects into link list
  146. CComponentObject *m_pCompNext; // Next object in the link list.
  147. CComponentObject *m_pCompPrev; // Prev object in the link list.
  148. // buffer for names that fit in (36 bytes = 17 unicode chars + '\0')
  149. BYTE m_rgbNameBuffer[36];
  150. private:
  151. // constructor is private! (not for outside use)
  152. CComponentObject
  153. (
  154. CompScope csScope,
  155. CompType ctType,
  156. CompModel cmModel
  157. );
  158. ~CComponentObject();
  159. // Initializes CLinkElem portion
  160. HRESULT Init(LPWSTR pwszName, DWORD cbName, BOOL fMTAConfigured);
  161. // Releases all interface pointers (used by clear)
  162. HRESULT ReleaseAll();
  163. // Clears out data (releases all) leaving link alone
  164. HRESULT Clear();
  165. // Create instance if not there already
  166. HRESULT Instantiate(CHitObj *pHitObj);
  167. HRESULT TryInstantiate(CHitObj *pHitObj);
  168. // Set value from variant
  169. HRESULT SetPropertyValue(VARIANT *);
  170. // Convert Object to be GIP cookie
  171. HRESULT ConvertToGIPCookie();
  172. // Get and cache the ids for OnStart methods
  173. HRESULT GetOnPageInfo();
  174. public:
  175. // functions to get the COM object (internally resolve cookies)
  176. HRESULT GetAddRefdIDispatch(IDispatch **ppdisp);
  177. HRESULT GetAddRefdIUnknown(IUnknown **ppunk);
  178. HRESULT GetVariant(VARIANT *pVar); // not for GIP cookies
  179. // Check if the unnamed page level object object
  180. // can be removed without waiting till the end of request
  181. inline BOOL FEarlyReleaseAllowed() const;
  182. // public inlines to access the object's properties
  183. // these are the only methods available from outside
  184. inline LPWSTR GetName();
  185. inline CompScope GetScope() const;
  186. inline CompType GetType() const;
  187. inline CompModel GetModel() const;
  188. inline BOOL FAgile() const;
  189. // Retrieve the cached ids
  190. inline const COnPageInfo *GetCachedOnPageInfo() const;
  191. public:
  192. #ifdef DBG
  193. void AssertValid() const;
  194. #else
  195. void AssertValid() const {}
  196. #endif
  197. // Cache on per-class basis
  198. ACACHE_INCLASS_DEFINITIONS()
  199. };
  200. inline LPWSTR CComponentObject::GetName()
  201. {
  202. return (LPWSTR)m_pKey;
  203. }
  204. inline CompScope CComponentObject::GetScope() const
  205. {
  206. return m_csScope;
  207. }
  208. inline CompType CComponentObject::GetType() const
  209. {
  210. return m_ctType;
  211. }
  212. inline CompType CComponentObject::GetModel() const
  213. {
  214. return m_cmModel;
  215. }
  216. inline BOOL CComponentObject::FAgile() const
  217. {
  218. return m_fAgile;
  219. }
  220. inline const COnPageInfo *CComponentObject::GetCachedOnPageInfo() const
  221. {
  222. return m_fOnPageInfoCached ? &m_OnPageInfo : NULL;
  223. }
  224. inline BOOL CComponentObject::FEarlyReleaseAllowed() const
  225. {
  226. return (!m_fOnPageStarted && // no need to do on-end-page
  227. !m_fInPtrCache && // no need to search by pointer
  228. m_csScope == csPage && // page scoped
  229. m_ctType == ctUnnamed); // created with Server.CreateObject()
  230. }
  231. /*===================================================================
  232. Component collection is a manager of various types of component
  233. objects:
  234. 1) Tagged objects (<OBJECT...>) (instantiated or not)
  235. 2) Session("xxx") and Application("xxx") properties
  236. 3) Unnamed objects (Server.CreateObject())
  237. It hashes added objects as needed (some by name, IUnkn *, etc.)
  238. The idea is to isolate the above issues from outside as much
  239. as possible.
  240. Component collections exist under session, application, hitobj
  241. ===================================================================*/
  242. class CComponentCollection
  243. {
  244. friend class CPageComponentManager;
  245. friend class CComponentIterator;
  246. friend class CVariantsIterator;
  247. private:
  248. CompScope m_csScope : 4; // scope (page, session, appln)
  249. DWORD m_fUseTaggedArray : 1; // remember tagged objects array?
  250. DWORD m_fUsePropArray : 1; // remember properties array?
  251. DWORD m_fHasComProperties : 1; // any property VARIANTs that could be objects
  252. DWORD m_fMTAConfigured : 1; // application is running in MTA
  253. // hash table (by name) of tagged objects
  254. CHashTableStr m_htTaggedObjects;
  255. // hash table (by name) of properties (4)
  256. CHashTableStr m_htProperties;
  257. // hash table (by IUnknown *) of all instances
  258. CIdHashTable m_htidIUnknownPtrs;
  259. // Pointer to the component objects link list
  260. CComponentObject *m_pCompFirst; // First object in link list.
  261. // Array of pointers to static objects to speed lookup by index
  262. CPtrArray m_rgpvTaggedObjects;
  263. // Array of pointers to properties to speed lookup by index
  264. CPtrArray m_rgpvProperties;
  265. // Various object counts in the collection
  266. USHORT m_cAllTagged; // all tagged objects
  267. USHORT m_cInstTagged; // instanciated tagged objects
  268. USHORT m_cProperties; // all properties
  269. USHORT m_cUnnamed; // number of unnamed objects
  270. // Add/remove object to the component objects link list
  271. HRESULT AddComponentToList(CComponentObject *pObj);
  272. HRESULT RemoveComponentFromList(CComponentObject *pObj);
  273. // Add named object to the proper hash table by name
  274. HRESULT AddComponentToNameHash
  275. (
  276. CComponentObject *pObj,
  277. LPWSTR pwszName,
  278. DWORD cbName
  279. );
  280. // Add named object to the IUnkown * hash table
  281. HRESULT AddComponentToPtrHash(CComponentObject *pObj);
  282. // Find by name (for tagged)
  283. HRESULT FindComponentObjectByName
  284. (
  285. LPWSTR pwszName,
  286. DWORD cbName,
  287. CComponentObject **ppObj
  288. );
  289. // Find by name (for properties)
  290. HRESULT FindComponentPropertyByName
  291. (
  292. LPWSTR pwszName,
  293. DWORD cbName,
  294. CComponentObject **ppObj
  295. );
  296. // Find by IUnknown*
  297. HRESULT FindComponentByIUnknownPtr
  298. (
  299. IUnknown *pUnk,
  300. CComponentObject **ppObj
  301. );
  302. // Fill in the arrays for access by index for the first time
  303. HRESULT StartUsingTaggedObjectsArray();
  304. HRESULT StartUsingPropertiesArray();
  305. public:
  306. // Add various kinds of objects to the collection
  307. // They are also used by
  308. // CPageComponentManager AddScoped...()
  309. HRESULT AddTagged
  310. (
  311. LPWSTR pwszName,
  312. const CLSID &clsid,
  313. CompModel cmModel
  314. );
  315. HRESULT AddProperty
  316. (
  317. LPWSTR pwszName,
  318. VARIANT *pVariant,
  319. CComponentObject **ppObj = NULL
  320. );
  321. HRESULT AddUnnamed
  322. (
  323. const CLSID &clsid,
  324. CompModel cmModel,
  325. CComponentObject **ppObj
  326. );
  327. HRESULT GetTagged
  328. (
  329. LPWSTR pwszName,
  330. CComponentObject **ppObj
  331. );
  332. HRESULT GetProperty
  333. (
  334. LPWSTR pwszName,
  335. CComponentObject **ppObj
  336. );
  337. HRESULT GetNameByIndex
  338. (
  339. CompType ctType,
  340. int index,
  341. LPWSTR *ppwszName
  342. );
  343. HRESULT RemoveComponent(CComponentObject *pObj);
  344. HRESULT RemoveProperty(LPWSTR pwszName);
  345. HRESULT RemoveAllProperties();
  346. CComponentCollection();
  347. ~CComponentCollection();
  348. HRESULT Init(CompScope csScope, BOOL fMTAConfigured);
  349. HRESULT UnInit();
  350. BOOL FHasStateInfo() const; // TRUE when state-full
  351. BOOL FHasObjects() const; // TRUE when contains objects
  352. DWORD GetPropertyCount() const;
  353. DWORD GetTaggedObjectCount() const;
  354. public:
  355. #ifdef DBG
  356. void AssertValid() const;
  357. #else
  358. void AssertValid() const {}
  359. #endif
  360. // Cache on per-class basis
  361. ACACHE_INCLASS_DEFINITIONS()
  362. };
  363. inline BOOL CComponentCollection::FHasStateInfo() const
  364. {
  365. return ((m_cAllTagged + m_cProperties + m_cUnnamed) > 0);
  366. }
  367. inline BOOL CComponentCollection::FHasObjects() const
  368. {
  369. return (m_cInstTagged > 0 || m_cUnnamed > 0 ||
  370. (m_cProperties > 0 && m_fHasComProperties));
  371. }
  372. inline DWORD CComponentCollection::GetPropertyCount() const
  373. {
  374. return m_cProperties;
  375. }
  376. inline DWORD CComponentCollection::GetTaggedObjectCount() const
  377. {
  378. return m_cAllTagged;
  379. }
  380. inline HRESULT CComponentCollection::AddComponentToList
  381. (
  382. CComponentObject *pObj
  383. )
  384. {
  385. pObj->m_pCompNext = m_pCompFirst;
  386. pObj->m_pCompPrev = NULL;
  387. if (m_pCompFirst)
  388. m_pCompFirst->m_pCompPrev = pObj;
  389. m_pCompFirst = pObj;
  390. return S_OK;
  391. }
  392. inline HRESULT CComponentCollection::RemoveComponentFromList
  393. (
  394. CComponentObject *pObj
  395. )
  396. {
  397. if (pObj->m_pCompPrev)
  398. pObj->m_pCompPrev->m_pCompNext = pObj->m_pCompNext;
  399. if (pObj->m_pCompNext)
  400. pObj->m_pCompNext->m_pCompPrev = pObj->m_pCompPrev;
  401. if (m_pCompFirst == pObj)
  402. m_pCompFirst = pObj->m_pCompNext;
  403. pObj->m_pCompPrev = pObj->m_pCompNext = NULL;
  404. return S_OK;
  405. }
  406. /*===================================================================
  407. A page object controls calls to OnStartPage(), OnEndPage().
  408. Page objects are used by CPageComponentManager
  409. They are hashed using IDispatch * to avoid multiple OnStartPage()
  410. calls for the same object.
  411. ===================================================================*/
  412. class CPageObject
  413. {
  414. friend class CPageComponentManager;
  415. private:
  416. IDispatch *m_pDisp; // Dispatch interface pointer
  417. COnPageInfo m_OnPageInfo; // cached OnPageInfo
  418. DWORD m_fStartPageCalled : 1;
  419. DWORD m_fEndPageCalled : 1;
  420. private: // the only access is using CPageComponentManager
  421. CPageObject();
  422. ~CPageObject();
  423. HRESULT Init(IDispatch *pDisp, const COnPageInfo &OnPageInfo);
  424. // Invoke OnStartPage or OnEndPage
  425. HRESULT InvokeMethod
  426. (
  427. DWORD iMethod,
  428. CScriptingContext *pContext,
  429. CHitObj *pHitObj
  430. );
  431. HRESULT TryInvokeMethod // used by InvokeMethod
  432. ( // inside TRY CATCH
  433. DISPID DispId,
  434. BOOL fOnStart,
  435. IDispatch *pDispContext,
  436. CHitObj *pHitObj
  437. );
  438. public:
  439. #ifdef DBG
  440. void AssertValid() const;
  441. #else
  442. void AssertValid() const {}
  443. #endif
  444. // Cache on per-class basis
  445. ACACHE_INCLASS_DEFINITIONS()
  446. };
  447. /*===================================================================
  448. Page component manager provides access to component collections
  449. for page, session, application level.
  450. It is associated with a HitObj.
  451. It also takes care of covering (OnStartPage(), OnEndPage()).
  452. ===================================================================*/
  453. class CPageComponentManager
  454. {
  455. private:
  456. // hashtable of page objects hashed by IDispatch *
  457. CIdHashTable m_htidPageObjects;
  458. // hit object (this page)
  459. CHitObj *m_pHitObj;
  460. // hash table iterator callbacks
  461. static IteratorCallbackCode DeletePageObjectCB(void *pvObj, void *, void *);
  462. static IteratorCallbackCode OnEndPageObjectCB(void *pvObj, void *pvHitObj, void *pvhr);
  463. private:
  464. // collections related to page, session and application
  465. HRESULT GetPageCollection(CComponentCollection **ppCollection);
  466. HRESULT GetSessionCollection(CComponentCollection **ppCollection);
  467. HRESULT GetApplnCollection(CComponentCollection **ppCollection);
  468. HRESULT GetCollectionByScope
  469. (
  470. CompScope csScope,
  471. CComponentCollection **ppCollection
  472. );
  473. // find objectc in any of the related collections
  474. // (internal private method)
  475. HRESULT FindScopedComponentByName
  476. (
  477. CompScope csScope,
  478. LPWSTR pwszName,
  479. DWORD cbName,
  480. BOOL fProperty,
  481. CComponentObject **ppObj,
  482. CComponentCollection **ppCollection = NULL
  483. );
  484. static HRESULT __stdcall InstantiateObjectFromMTA
  485. (
  486. void *pvObj,
  487. void *pvHitObj
  488. );
  489. public:
  490. CPageComponentManager();
  491. ~CPageComponentManager();
  492. HRESULT Init(CHitObj *pHitObj);
  493. // OnStartPage processing for an object that need it
  494. // (OnEndPage is done for all objects at the end of page)
  495. HRESULT OnStartPage
  496. (
  497. CComponentObject *pCompObj,
  498. CScriptingContext *pContext,
  499. const COnPageInfo *pOnPageInfo,
  500. BOOL *pfStarted
  501. );
  502. // request OnEndPage() for all objects that need it
  503. // (OnStartPage() is done on demand on per-object basis)
  504. HRESULT OnEndPageAllObjects();
  505. // Add various kinds of objects. Objects get added to the
  506. // right collection depending on scope argument
  507. HRESULT AddScopedTagged
  508. (
  509. CompScope csScope,
  510. LPWSTR pwszName,
  511. const CLSID &clsid,
  512. CompModel cmModel
  513. );
  514. HRESULT AddScopedProperty
  515. (
  516. CompScope csScope,
  517. LPWSTR pwszName,
  518. VARIANT *pVariant,
  519. CComponentObject **ppObj = NULL
  520. );
  521. // Server.CreateObject
  522. HRESULT AddScopedUnnamedInstantiated
  523. (
  524. CompScope csScope,
  525. const CLSID &clsid,
  526. CompModel cmModel,
  527. COnPageInfo *pOnPageInfo,
  528. CComponentObject **ppObj
  529. );
  530. // Get component object (tagged) by name.
  531. // Scope could be csUnknown
  532. HRESULT GetScopedObjectInstantiated
  533. (
  534. CompScope csScope,
  535. LPWSTR pwszName,
  536. DWORD cbName,
  537. CComponentObject **ppObj,
  538. BOOL *pfNewInstance
  539. );
  540. // Get component property by name. Scope could be csUnknown
  541. HRESULT GetScopedProperty
  542. (
  543. CompScope csScope,
  544. LPWSTR pwszName,
  545. CComponentObject **ppObj
  546. );
  547. // Find component by IUnknown * (or IDispatch *).
  548. HRESULT FindAnyScopeComponentByIUnknown
  549. (
  550. IUnknown *pUnk,
  551. CComponentObject **ppObj
  552. );
  553. HRESULT FindAnyScopeComponentByIDispatch
  554. (
  555. IDispatch *pDisp,
  556. CComponentObject **ppObj
  557. );
  558. // The same - but static - gets context from Viper
  559. static HRESULT FindComponentWithoutContext
  560. (
  561. IDispatch *pDisp,
  562. CComponentObject **ppObj
  563. );
  564. // Remove component -- the early release logic
  565. HRESULT RemoveComponent(CComponentObject *pObj);
  566. public:
  567. #ifdef DBG
  568. void AssertValid() const;
  569. #else
  570. void AssertValid() const {}
  571. #endif
  572. // Cache on per-class basis
  573. ACACHE_INCLASS_DEFINITIONS()
  574. };
  575. // Component iterator is used to go through component names
  576. // all the HitObj - reletated object across collections
  577. // Needed for scripting
  578. class CComponentIterator
  579. {
  580. private:
  581. CHitObj *m_pHitObj;
  582. DWORD m_fInited : 1;
  583. DWORD m_fFinished : 1;
  584. CompScope m_csLastScope : 4;
  585. CComponentObject *m_pLastObj;
  586. public:
  587. CComponentIterator(CHitObj *pHitObj = NULL);
  588. ~CComponentIterator();
  589. HRESULT Init(CHitObj *pHitObj);
  590. LPWSTR WStrNextComponentName();
  591. };
  592. // Variant Iterator is used to go through Property or Tagged object
  593. // names in a component collection. Needed for scripting
  594. class CVariantsIterator : public IEnumVARIANT
  595. {
  596. public:
  597. CVariantsIterator(CAppln *, DWORD);
  598. CVariantsIterator(CSession *, DWORD);
  599. ~CVariantsIterator();
  600. HRESULT Init();
  601. // The Big Three
  602. STDMETHODIMP QueryInterface(const GUID &, void **);
  603. STDMETHODIMP_(ULONG) AddRef();
  604. STDMETHODIMP_(ULONG) Release();
  605. // standard methods for iterators
  606. STDMETHODIMP Clone(IEnumVARIANT **ppEnumReturn);
  607. STDMETHODIMP Next(unsigned long cElements, VARIANT *rgVariant, unsigned long *pcElementsFetched);
  608. STDMETHODIMP Skip(unsigned long cElements);
  609. STDMETHODIMP Reset();
  610. private:
  611. ULONG m_cRefs; // reference count
  612. CComponentCollection *m_pCompColl; // collection we are iterating over
  613. DWORD m_dwIndex; // current position for iteration
  614. CAppln *m_pAppln; // application (to clone iterator and Lock())
  615. CSession *m_pSession; // session (to clone iterator)
  616. DWORD m_ctColType; // type of collection
  617. // Cache on per-class basis
  618. ACACHE_INCLASS_DEFINITIONS()
  619. };
  620. #endif // COMPCOL_H