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.

3691 lines
91 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1997 Microsoft Corporation. All Rights Reserved.
  5. Component: Component Collection
  6. File: Compcol.cpp
  7. Owner: DmitryR
  8. This is the Component Collection source 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. #include "denpre.h"
  15. #pragma hdrstop
  16. #include "Context.h"
  17. #include "MTAcb.h"
  18. #include "Request.h"
  19. #include "Response.h"
  20. #include "Server.h"
  21. #include "tlbcache.h"
  22. #include "memchk.h"
  23. /*===================================================================
  24. Defines for hash table sizes
  25. ===================================================================*/
  26. #define HT_TAGGED_OBJECTS_BUCKETS_MAX 19
  27. #define HT_PROPERTIES_BUCKETS_MAX 17
  28. #define HT_IUNKNOWN_PTRS_BUCKETS_MAX 23
  29. #define HT_PAGE_OBJECTS_BUCKETS_MAX 17
  30. /*===================================================================
  31. Static utility function prototypes
  32. ===================================================================*/
  33. static HRESULT QueryOnPageInfo
  34. (
  35. IDispatch *pDisp,
  36. COnPageInfo *pOnPageInfo
  37. );
  38. static HRESULT CLSIDToMultibyteString
  39. (
  40. CLSID ClsId,
  41. char *psz,
  42. int cch
  43. );
  44. #define REG_MODEL_TEXT_LEN_MAX 20 // big enough for "Apartment"
  45. static CompModel RegStrToCompModel
  46. (
  47. BYTE *pb,
  48. DWORD cb
  49. );
  50. /*===================================================================
  51. Static utility functions code
  52. ===================================================================*/
  53. /*===================================================================
  54. QueryOnPageInfo
  55. Query dispatch ids for OnStartPage and OnEndPage
  56. Parameters:
  57. IDispatch *pDisp Object to query
  58. COnPageInfo *pOnPageInfo Struct to fill in
  59. Returns:
  60. HRESULT
  61. ===================================================================*/
  62. HRESULT QueryOnPageInfo
  63. (
  64. IDispatch *pDisp,
  65. COnPageInfo *pOnPageInfo
  66. )
  67. {
  68. static LPOLESTR BStrEntryPoints[ONPAGE_METHODS_MAX] =
  69. {
  70. L"OnStartPage",
  71. L"OnEndPage"
  72. };
  73. HRESULT hr = S_OK;
  74. for (int i = 0; i < ONPAGE_METHODS_MAX; i++)
  75. {
  76. hr = pDisp->GetIDsOfNames
  77. (
  78. IID_NULL,
  79. &BStrEntryPoints[i],
  80. 1,
  81. LOCALE_SYSTEM_DEFAULT,
  82. &pOnPageInfo->m_rgDispIds[i]
  83. );
  84. if (FAILED(hr))
  85. {
  86. if (hr != DISP_E_UNKNOWNNAME &&
  87. hr != DISP_E_MEMBERNOTFOUND)
  88. {
  89. break;
  90. }
  91. // If UNKNOWNNAME, set dispid to DISPID_UNKNOWN
  92. hr = S_OK;
  93. pOnPageInfo->m_rgDispIds[i] = DISPID_UNKNOWN;
  94. }
  95. }
  96. return hr;
  97. }
  98. /*===================================================================
  99. CLSIDToMultibyteString
  100. Converts CLSID into multibyte string
  101. Used in CompModelFromCLSID
  102. Parameters:
  103. CLSID ClsId (in) CLSID to convert
  104. char *pb put string into this buffer
  105. int cch of this length
  106. Returns:
  107. HRESULT
  108. ===================================================================*/
  109. HRESULT CLSIDToMultibyteString
  110. (
  111. CLSID ClsId,
  112. char *psz,
  113. int cch
  114. )
  115. {
  116. // First convert it to OLECHAR string
  117. OLECHAR *pszWideClassID = NULL; // temp wide string classid
  118. HRESULT hr = StringFromCLSID(ClsId, &pszWideClassID);
  119. if (FAILED(hr))
  120. return hr;
  121. // OLECHAR to MultiByte
  122. BOOL f = WideCharToMultiByte
  123. (
  124. CP_ACP, // code page
  125. 0, // performance and mapping flags
  126. pszWideClassID, // address of wide-character string
  127. -1, // length (-1 == null-terminated)
  128. psz, // address of buffer for new string
  129. cch, // size of buffer for new string
  130. NULL, // address of default for unmappable
  131. // characters; quickest if null
  132. NULL // address of flag set when default
  133. // char. used; quickest if null
  134. );
  135. if (f == FALSE)
  136. hr = E_FAIL;
  137. if (pszWideClassID)
  138. CoTaskMemFree(pszWideClassID);
  139. return hr;
  140. }
  141. /*===================================================================
  142. RegStrToCompModel
  143. Get CompModel value from a registry string
  144. Parameters:
  145. char *pb string as returned from registry
  146. int cb length returned from registry
  147. Returns:
  148. HRESULT
  149. ===================================================================*/
  150. CompModel RegStrToCompModel
  151. (
  152. BYTE *pb,
  153. DWORD cb
  154. )
  155. {
  156. CompModel cmModel = cmSingle; // assume single
  157. if (cb == 5) // 5 include '\0'
  158. {
  159. if (!(_strnicmp((const char*)pb, "Both", cb)))
  160. cmModel = cmBoth;
  161. else if (!(_strnicmp((const char*)pb, "Free", cb)))
  162. cmModel = cmFree;
  163. }
  164. else if (cb == 10) // 10 include '\0'
  165. {
  166. if (!(_strnicmp((const char*)pb, "Apartment", cb)))
  167. cmModel = cmApartment;
  168. }
  169. return cmModel;
  170. }
  171. /*===================================================================
  172. Public utility functions code
  173. ===================================================================*/
  174. /*===================================================================
  175. CompModelFromCLSID
  176. Get object's model and InProc flag by its CLSID from the registry
  177. Parameters:
  178. CLSID &ClsId (in)
  179. CompModel *pcmModel (out) Model (optional)
  180. BOOL *pfInProc (out) InProc flag (optional)
  181. Returns:
  182. CompModel (cmFree, cmBoth, etc.)
  183. ===================================================================*/
  184. HRESULT CompModelFromCLSID
  185. (
  186. const CLSID &ClsId,
  187. CompModel *pcmModel,
  188. BOOL *pfInProc
  189. )
  190. {
  191. if (!Glob(fTrackThreadingModel) && !pfInProc)
  192. {
  193. // ignore registry value for threading model and
  194. // inproc flag is not requested -> take short return
  195. if (pcmModel)
  196. *pcmModel = cmUnknown;
  197. return S_OK;
  198. }
  199. // default returns
  200. CompModel cmModel = cmSingle; // assume single
  201. BOOL fInProc = TRUE; // assume inproc
  202. HRESULT hr = S_OK;
  203. // Convert ClsId to multibyte string
  204. char szClassID[50];
  205. hr = CLSIDToMultibyteString(ClsId, szClassID, sizeof(szClassID));
  206. if (FAILED(hr))
  207. return hr;
  208. /* query the registry; threading model is stored as:
  209. HKEY_CLASSES_ROOT
  210. key: CLSID
  211. key: <object's classid>
  212. key: InprocServer32
  213. name: ThreadingModel data: "Both" | "Apartment"
  214. */
  215. // Navigate the registry to "InprocServer32" key
  216. HKEY hKey1 = NULL; // handle of open reg key
  217. HKEY hKey2 = NULL; // handle of open reg key
  218. HKEY hKey3 = NULL; // handle of open reg key
  219. if (SUCCEEDED(hr))
  220. {
  221. int nRet = RegOpenKeyExA
  222. (
  223. HKEY_CLASSES_ROOT,
  224. "CLSID",
  225. 0,
  226. KEY_READ,
  227. &hKey1
  228. );
  229. if (nRet != ERROR_SUCCESS)
  230. hr = E_FAIL;
  231. }
  232. if (SUCCEEDED(hr))
  233. {
  234. int nRet = RegOpenKeyExA
  235. (
  236. hKey1,
  237. szClassID,
  238. 0,
  239. KEY_READ,
  240. &hKey2
  241. );
  242. if (nRet != ERROR_SUCCESS)
  243. hr = E_FAIL;
  244. }
  245. // Get the stuff from the registry "InprocServer32" key
  246. if (SUCCEEDED(hr))
  247. {
  248. int nRet = RegOpenKeyExA
  249. (
  250. hKey2,
  251. "InprocServer32",
  252. 0,
  253. KEY_READ,
  254. &hKey3
  255. );
  256. if (nRet == ERROR_SUCCESS)
  257. {
  258. DWORD cbData = REG_MODEL_TEXT_LEN_MAX;
  259. BYTE szData[REG_MODEL_TEXT_LEN_MAX];
  260. nRet = RegQueryValueExA
  261. (
  262. hKey3,
  263. "ThreadingModel",
  264. NULL,
  265. NULL,
  266. szData,
  267. &cbData
  268. );
  269. if (nRet == ERROR_SUCCESS)
  270. cmModel = RegStrToCompModel(szData, cbData);
  271. if (cmModel == cmBoth)
  272. {
  273. // Some objects marked as "Both" ASP treats as
  274. // "Apartment". These objects should be marked in
  275. // the registry as "ASPComponentNonAgile"
  276. nRet = RegQueryValueExA
  277. (
  278. hKey3,
  279. "ASPComponentNonAgile",
  280. NULL,
  281. NULL,
  282. szData,
  283. &cbData
  284. );
  285. // If the key is found pretend it's "apartment"
  286. if (nRet == ERROR_SUCCESS)
  287. cmModel = cmApartment;
  288. }
  289. }
  290. else
  291. {
  292. // if there is no InprocServer32 key,
  293. // then it must be a localserver or remote server.
  294. fInProc = FALSE;
  295. }
  296. }
  297. // clean up registry keys
  298. if (hKey3)
  299. RegCloseKey(hKey3);
  300. if (hKey2)
  301. RegCloseKey(hKey2);
  302. if (hKey1)
  303. RegCloseKey(hKey1);
  304. // return values
  305. if (pcmModel)
  306. *pcmModel = Glob(fTrackThreadingModel) ? cmModel : cmUnknown;
  307. if (pfInProc)
  308. *pfInProc = fInProc;
  309. return hr;
  310. }
  311. /*===================================================================
  312. FIsIntrinsic
  313. Checks if the given IDispatch * points to an ASP intrinsic.
  314. Parameters:
  315. pdisp pointer to check
  316. Returns:
  317. TRUE if Intrinsic
  318. ===================================================================*/
  319. BOOL FIsIntrinsic
  320. (
  321. IDispatch *pdisp
  322. )
  323. {
  324. if (!pdisp)
  325. return FALSE; // null dispatch pointer - not an intrinsic
  326. IUnknown *punk = NULL;
  327. if (FAILED(pdisp->QueryInterface(IID_IDenaliIntrinsic, (void **)&punk)))
  328. return FALSE;
  329. Assert(punk);
  330. punk->Release();
  331. return TRUE;
  332. }
  333. /*===================================================================
  334. FIsSimpleVariant
  335. Checks if the given VARIANT is a simple one
  336. Parameters:
  337. pvar variant to check
  338. Returns:
  339. TRUE if [for sure] simple, FALSE if [possibly] not
  340. ===================================================================*/
  341. inline FIsSimpleVariant(VARIANT *pvar)
  342. {
  343. switch (V_VT(pvar))
  344. {
  345. case VT_BSTR:
  346. case VT_I2:
  347. case VT_I4:
  348. case VT_BOOL:
  349. case VT_DATE:
  350. case VT_R4:
  351. case VT_R8:
  352. return TRUE;
  353. }
  354. return FALSE;
  355. }
  356. /*===================================================================
  357. C C o m p o n e n t O b j e c t
  358. ===================================================================*/
  359. /*===================================================================
  360. CComponentObject::CComponentObject
  361. CComponentObject constructor
  362. Parameters:
  363. CompScope scScope Object scope
  364. CompType ctType Object type
  365. CompModel cmModel Object threading model
  366. Returns:
  367. ===================================================================*/
  368. CComponentObject::CComponentObject
  369. (
  370. CompScope scScope,
  371. CompType ctType,
  372. CompModel cmModel
  373. )
  374. :
  375. m_csScope(scScope), m_ctType(ctType), m_cmModel(cmModel),
  376. m_fAgile(FALSE),
  377. m_fOnPageInfoCached(FALSE),
  378. m_fOnPageStarted(FALSE),
  379. m_fFailedToInstantiate(FALSE), m_fInstantiatedTagged(FALSE),
  380. m_fInPtrCache(FALSE),
  381. m_fVariant(FALSE),
  382. m_fNameAllocated(FALSE),
  383. m_dwGIPCookie(NULL_GIP_COOKIE),
  384. m_pDisp(NULL), m_pUnknown(NULL),
  385. m_pCompNext(NULL), m_pCompPrev(NULL),
  386. m_fMTAConfigured(FALSE)
  387. {
  388. }
  389. #ifdef DBG
  390. /*===================================================================
  391. CComponentObject::AssertValid
  392. Test to make sure that this is currently correctly formed
  393. and assert if it is not.
  394. Returns:
  395. ===================================================================*/
  396. void CComponentObject::AssertValid() const
  397. {
  398. Assert(m_ctType != ctUnknown);
  399. }
  400. #endif
  401. /*===================================================================
  402. CComponentObject::~CComponentObject
  403. CComponentObject destructor
  404. Releases interface pointers
  405. Parameters:
  406. Returns:
  407. ===================================================================*/
  408. CComponentObject::~CComponentObject()
  409. {
  410. // Release all interface pointers
  411. Clear();
  412. // Name used in hash (from CLinkElem)
  413. if (m_fNameAllocated)
  414. {
  415. Assert(m_pKey);
  416. free(m_pKey);
  417. }
  418. }
  419. /*===================================================================
  420. CComponentObject::Init
  421. Initialize CLinkElem portion with the object name
  422. Needed to implement string hash
  423. Parameters:
  424. LPWSTR pwszName object name
  425. DWORD cbName name length in bytes
  426. Returns:
  427. HRESULT
  428. ===================================================================*/
  429. HRESULT CComponentObject::Init
  430. (
  431. LPWSTR pwszName,
  432. DWORD cbName,
  433. BOOL fMTAConfigured
  434. )
  435. {
  436. Assert(pwszName);
  437. Assert(*pwszName != L'\0');
  438. Assert(cbName == (wcslen(pwszName) * sizeof(WCHAR)));
  439. m_fMTAConfigured = fMTAConfigured;
  440. // required buffer length
  441. DWORD cbBuffer = cbName + sizeof(WCHAR);
  442. WCHAR *pwszNameBuffer = (WCHAR *)m_rgbNameBuffer;
  443. if (cbBuffer > sizeof(m_rgbNameBuffer))
  444. {
  445. // the name doesn't fit into the member buffer -> allocate
  446. pwszNameBuffer = (WCHAR *)malloc(cbBuffer);
  447. if (!pwszNameBuffer)
  448. return E_OUTOFMEMORY;
  449. m_fNameAllocated = TRUE;
  450. }
  451. memcpy(pwszNameBuffer, pwszName, cbBuffer);
  452. // init link with name as the key (length excludes null term)
  453. return CLinkElem::Init(pwszNameBuffer, cbName);
  454. }
  455. /*===================================================================
  456. CComponentObject::ReleaseAll
  457. Releases all interface pointers
  458. Parameters:
  459. Returns:
  460. HRESULT
  461. ===================================================================*/
  462. HRESULT CComponentObject::ReleaseAll()
  463. {
  464. // Release all other present interface pointers
  465. if (m_pDisp)
  466. {
  467. m_pDisp->Release();
  468. m_pDisp = NULL;
  469. }
  470. if (m_pUnknown)
  471. {
  472. m_pUnknown->Release();
  473. m_pUnknown = NULL;
  474. }
  475. // Variant
  476. if (m_fVariant)
  477. {
  478. VariantClear(&m_Variant);
  479. m_fVariant = FALSE;
  480. }
  481. if (m_dwGIPCookie != NULL_GIP_COOKIE)
  482. {
  483. g_GIPAPI.Revoke(m_dwGIPCookie);
  484. m_dwGIPCookie = NULL_GIP_COOKIE;
  485. }
  486. return S_OK;
  487. }
  488. /*===================================================================
  489. CComponentObject::Clear
  490. Clears out data leaving link alone
  491. Parameters:
  492. Returns:
  493. HRESULT
  494. ===================================================================*/
  495. HRESULT CComponentObject::Clear()
  496. {
  497. // Release all pointers
  498. TRY
  499. ReleaseAll();
  500. CATCH(nExcept)
  501. Assert(FALSE);
  502. m_pDisp = NULL;
  503. m_pUnknown = NULL;
  504. m_fVariant = FALSE;
  505. m_dwGIPCookie = NULL_GIP_COOKIE;
  506. END_TRY
  507. // Invalidate cached OnPageInfo
  508. m_fOnPageInfoCached = FALSE;
  509. m_fOnPageStarted = FALSE;
  510. // Mark it as unknown
  511. m_csScope = csUnknown;
  512. m_ctType = ctUnknown;
  513. m_cmModel = cmUnknown;
  514. m_fAgile = FALSE;
  515. return S_OK;
  516. }
  517. /*===================================================================
  518. CComponentObject::Instantiate
  519. Create object instance if it's not there already
  520. Calls TryInstantiate() from within TRY CATCH
  521. Parameters:
  522. CHitObj *pHitObj Hit object for error reporting
  523. Returns:
  524. HRESULT
  525. ===================================================================*/
  526. HRESULT CComponentObject::Instantiate
  527. (
  528. CHitObj *pHitObj
  529. )
  530. {
  531. HRESULT hr = S_OK;
  532. if (Glob(fExceptionCatchEnable))
  533. {
  534. TRY
  535. hr = TryInstantiate(pHitObj);
  536. CATCH(nExcept)
  537. HandleErrorMissingFilename(IDE_SCRIPT_OBJ_INSTANTIATE_FAILED,
  538. pHitObj,
  539. TRUE,
  540. GetName(),
  541. nExcept);
  542. hr = nExcept;
  543. END_TRY
  544. }
  545. else
  546. {
  547. hr = TryInstantiate(pHitObj);
  548. }
  549. if (FAILED(hr))
  550. {
  551. // Something failed -- need to clean-up
  552. ReleaseAll();
  553. // mark as "failed to instantiate"
  554. m_fFailedToInstantiate = TRUE;
  555. }
  556. return hr;
  557. }
  558. /*===================================================================
  559. CComponentObject::TryInstantiate
  560. Create object instance if it's not there already
  561. Called by Instantiate() from within TRY CATCH
  562. Parameters:
  563. CHitObj *pHitObj Hit object for error reporting
  564. Returns:
  565. HRESULT
  566. ===================================================================*/
  567. HRESULT CComponentObject::TryInstantiate
  568. (
  569. CHitObj *pHitObj
  570. )
  571. {
  572. HRESULT hr = S_OK;
  573. // Check if the object already exist
  574. if (m_pUnknown)
  575. return S_OK;
  576. if (m_fFailedToInstantiate)
  577. return E_FAIL; // already tried once
  578. if (m_cmModel == cmUnknown && m_ClsId != CLSID_NULL)
  579. {
  580. CompModel cmModel; // needed because m_cmModel is a bit fld
  581. hr = CompModelFromCLSID(m_ClsId, &cmModel);
  582. if (FAILED(hr))
  583. return hr;
  584. m_cmModel = cmModel;
  585. }
  586. hr = ViperCreateInstance
  587. (
  588. m_ClsId,
  589. IID_IUnknown,
  590. (void **)&m_pUnknown
  591. );
  592. // If we failed because we incorrectly cached the clsid
  593. // (could happen for tagged objects) try to get updated
  594. // cls id and retry
  595. if (m_ctType == ctTagged && FAILED(hr))
  596. {
  597. if (g_TypelibCache.UpdateMappedCLSID(&m_ClsId) == S_OK)
  598. {
  599. hr = ViperCreateInstance
  600. (
  601. m_ClsId,
  602. IID_IUnknown,
  603. (void **)&m_pUnknown
  604. );
  605. }
  606. }
  607. if (SUCCEEDED(hr))
  608. {
  609. if (Glob(fTrackThreadingModel) && m_cmModel == cmBoth)
  610. m_fAgile = TRUE;
  611. else
  612. m_fAgile = ViperCoObjectAggregatesFTM(m_pUnknown);
  613. hr = m_pUnknown->QueryInterface
  614. (
  615. IID_IDispatch,
  616. (void **)&m_pDisp
  617. );
  618. }
  619. // Check if application level object that
  620. // restricts threading -> use Global Interface Cookie
  621. if (SUCCEEDED(hr)
  622. && (m_csScope == csAppln || m_csScope == csSession)
  623. && !m_fMTAConfigured
  624. && !m_fAgile)
  625. {
  626. return ConvertToGIPCookie();
  627. }
  628. if (SUCCEEDED(hr) && !m_fOnPageInfoCached)
  629. {
  630. // don't really care if the following fails
  631. GetOnPageInfo();
  632. }
  633. return hr;
  634. }
  635. /*===================================================================
  636. CComponentObject::SetPropertyValue
  637. Sets value from a Variant
  638. Checks agility and possible deadlocks
  639. Does GIP conversion
  640. Parameters:
  641. VARIANT *pVariant [in] Value to set
  642. Returns:
  643. HRESULT
  644. ===================================================================*/
  645. HRESULT CComponentObject::SetPropertyValue
  646. (
  647. VARIANT *pVariant
  648. )
  649. {
  650. Assert(m_ctType == ctProperty);
  651. HRESULT hr = S_OK;
  652. // Copy the variant value
  653. VariantInit(&m_Variant);
  654. m_fVariant = TRUE;
  655. hr = VariantCopyInd(&m_Variant, pVariant);
  656. if (FAILED(hr))
  657. return hr;
  658. // Get IDispatch pointer
  659. if (V_VT(&m_Variant) == VT_DISPATCH)
  660. {
  661. m_pDisp = V_DISPATCH(&m_Variant);
  662. }
  663. else
  664. {
  665. m_pDisp = NULL;
  666. }
  667. if (!m_pDisp)
  668. {
  669. m_fAgile = TRUE; // not VT_DISPATCH VARIANTs are agile
  670. return S_OK;
  671. }
  672. m_pDisp->AddRef();
  673. // Query (and cache) OnPageInfo inside TRY CATCH
  674. if (Glob(fExceptionCatchEnable))
  675. {
  676. TRY
  677. hr = GetOnPageInfo();
  678. CATCH(nExcept)
  679. hr = E_UNEXPECTED;
  680. END_TRY
  681. }
  682. else
  683. {
  684. hr = GetOnPageInfo();
  685. }
  686. // Don't really care if failed
  687. hr = S_OK;
  688. // Check if the assigned object is agile
  689. m_fAgile = ViperCoObjectAggregatesFTM(m_pDisp);
  690. if (Glob(fTrackThreadingModel) && !m_fAgile)
  691. {
  692. // doesn't mean it really isn't. could be one of
  693. // our objects marked as 'both'
  694. CComponentObject *pObjCopyOf = NULL;
  695. hr = CPageComponentManager::FindComponentWithoutContext
  696. (
  697. m_pDisp,
  698. &pObjCopyOf
  699. );
  700. if (hr == S_OK)
  701. {
  702. m_fAgile = pObjCopyOf->FAgile();
  703. }
  704. // end of getting of agile flag from the original object
  705. hr = S_OK; // even if object was not found
  706. }
  707. // Decide whether to use GIP and if invalid assignment
  708. // Applies only to non-agile application objects
  709. if (!m_fAgile && !m_fMTAConfigured && (m_csScope == csAppln || m_csScope == csSession))
  710. {
  711. if (!ViperCoObjectIsaProxy(m_pDisp) && (m_csScope == csAppln)) // deadlocking?
  712. {
  713. m_pDisp->Release();
  714. m_pDisp = NULL;
  715. VariantClear(&m_Variant);
  716. hr = RPC_E_WRONG_THREAD; // to tell the caller the error
  717. }
  718. else
  719. {
  720. // use GIP
  721. hr = ConvertToGIPCookie();
  722. }
  723. }
  724. return hr;
  725. }
  726. /*===================================================================
  727. CComponentObject::ConvertToGIPCookie
  728. Convert Object to be GIP cookie. Release all pointers
  729. Parameters:
  730. Returns:
  731. HRESULT
  732. ===================================================================*/
  733. HRESULT CComponentObject::ConvertToGIPCookie()
  734. {
  735. Assert(m_pDisp); // has to have dispatch pointer
  736. DWORD dwCookie = NULL_GIP_COOKIE;
  737. HRESULT hr = g_GIPAPI.Register(m_pDisp, IID_IDispatch, &dwCookie);
  738. if (SUCCEEDED(hr))
  739. {
  740. Assert(dwCookie != NULL_GIP_COOKIE);
  741. // Release all pointeres
  742. ReleaseAll();
  743. // Store the cookie instead
  744. m_dwGIPCookie = dwCookie;
  745. }
  746. return hr;
  747. }
  748. /*===================================================================
  749. CComponentObject::GetOnPageInfo
  750. Query dispatch ids for OnStartPage and OnEndPage
  751. Calls static QueryOnPageInfo
  752. Parameters:
  753. Returns:
  754. HRESULT
  755. ===================================================================*/
  756. HRESULT CComponentObject::GetOnPageInfo()
  757. {
  758. Assert(m_pDisp);
  759. HRESULT hr = QueryOnPageInfo(m_pDisp, &m_OnPageInfo);
  760. if (SUCCEEDED(hr))
  761. m_fOnPageInfoCached = TRUE;
  762. return hr;
  763. }
  764. /*===================================================================
  765. CComponentObject::GetAddRefdIDispatch
  766. Get AddRef()'d Dispatch *
  767. Handles the Global Interface Ole Cookies
  768. Parameters:
  769. Dispatch **ppdisp output
  770. Returns:
  771. HRESULT
  772. ===================================================================*/
  773. HRESULT CComponentObject::GetAddRefdIDispatch
  774. (
  775. IDispatch **ppdisp
  776. )
  777. {
  778. Assert(ppdisp);
  779. if (m_pDisp)
  780. {
  781. *ppdisp = m_pDisp;
  782. (*ppdisp)->AddRef();
  783. return S_OK;
  784. }
  785. // try to restore from cookie
  786. if (m_dwGIPCookie != NULL_GIP_COOKIE)
  787. {
  788. // Even if IUnknown * needs to be returned,
  789. // Ask for IDispatch *, because IDispatch * is the one
  790. // that was put in by CoGetInterfaceFromGlobal()
  791. HRESULT hr = g_GIPAPI.Get
  792. (
  793. m_dwGIPCookie,
  794. IID_IDispatch,
  795. (void **)ppdisp
  796. );
  797. if (SUCCEEDED(hr))
  798. return S_OK;
  799. }
  800. *ppdisp = NULL;
  801. return E_NOINTERFACE;
  802. }
  803. /*===================================================================
  804. CComponentObject::GetAddRefdIUnknown
  805. Get AddRef()'d IUnknown *
  806. Handles the Global Interface Ole Cookies
  807. Parameters:
  808. IUnknown **ppunk output
  809. Returns:
  810. HRESULT
  811. ===================================================================*/
  812. HRESULT CComponentObject::GetAddRefdIUnknown
  813. (
  814. IUnknown **ppunk
  815. )
  816. {
  817. Assert(ppunk);
  818. if (m_pUnknown)
  819. {
  820. *ppunk = m_pUnknown;
  821. (*ppunk)->AddRef();
  822. return S_OK;
  823. }
  824. // Use IDispatch (from cookie)
  825. IDispatch *pDisp = NULL;
  826. if (SUCCEEDED(GetAddRefdIDispatch(&pDisp)))
  827. {
  828. *ppunk = pDisp; // IDispatch implements IUnknown
  829. return S_OK;
  830. }
  831. *ppunk = NULL;
  832. return E_NOINTERFACE;
  833. }
  834. /*===================================================================
  835. CComponentObject::GetVariant
  836. Get object's values as variant
  837. Handles the Global Interface Ole Cookies
  838. Parameters:
  839. VARIANT *pVar [out] Variant filled in with object value
  840. Returns:
  841. HRESULT
  842. ===================================================================*/
  843. HRESULT CComponentObject::GetVariant
  844. (
  845. VARIANT *pVar
  846. )
  847. {
  848. HRESULT hr = S_OK;
  849. VariantInit(pVar); // default variant empty
  850. if (m_fVariant)
  851. {
  852. // already has variant
  853. hr = VariantCopyInd(pVar, &m_Variant);
  854. }
  855. else if (m_pDisp)
  856. {
  857. // create variant from IDispatch*
  858. m_pDisp->AddRef();
  859. V_VT(pVar) = VT_DISPATCH;
  860. V_DISPATCH(pVar) = m_pDisp;
  861. }
  862. else if (m_dwGIPCookie != NULL_GIP_COOKIE)
  863. {
  864. // create variant from cookie
  865. IDispatch *pDisp = NULL;
  866. hr = g_GIPAPI.Get(m_dwGIPCookie, IID_IDispatch, (void **)&pDisp);
  867. if (SUCCEEDED(hr))
  868. {
  869. V_VT(pVar) = VT_DISPATCH;
  870. V_DISPATCH(pVar) = pDisp;
  871. }
  872. }
  873. else
  874. {
  875. // nowhere to get the VARIANT value from
  876. hr = E_POINTER;
  877. }
  878. return hr;
  879. }
  880. /*===================================================================
  881. C P a g e O b j e c t
  882. ===================================================================*/
  883. /*===================================================================
  884. CPageObject::CPageObject
  885. CPageObject constructor
  886. Parameters:
  887. Returns:
  888. ===================================================================*/
  889. CPageObject::CPageObject()
  890. : m_pDisp(NULL),
  891. m_fStartPageCalled(FALSE), m_fEndPageCalled(FALSE)
  892. {
  893. }
  894. #ifdef DBG
  895. /*===================================================================
  896. CPageObject::AssertValid
  897. Test to make sure that this is currently correctly formed
  898. and assert if it is not.
  899. Returns:
  900. ===================================================================*/
  901. void CPageObject::AssertValid() const
  902. {
  903. Assert(m_pDisp);
  904. }
  905. #endif
  906. /*===================================================================
  907. CPageObject::~CPageObject
  908. CPageObject destructor
  909. Parameters:
  910. Returns:
  911. ===================================================================*/
  912. CPageObject::~CPageObject()
  913. {
  914. // Release interface pointer
  915. if (m_pDisp)
  916. {
  917. m_pDisp->Release();
  918. m_pDisp = NULL;
  919. }
  920. }
  921. /*===================================================================
  922. CPageObject::Init
  923. Initialize CLinkElem portion with the IDispatch pointer
  924. Needed to implement string hash
  925. Parameters:
  926. IDispatch *pDisp dispatch pointer (AddRef()ed)
  927. COnPageInfo *pOnPageInfo OnStartPage, OnEndPage Ids
  928. Returns:
  929. HRESULT
  930. ===================================================================*/
  931. HRESULT CPageObject::Init
  932. (
  933. IDispatch *pDisp,
  934. const COnPageInfo &OnPageInfo
  935. )
  936. {
  937. Assert(pDisp);
  938. m_pDisp = pDisp;
  939. m_OnPageInfo = OnPageInfo;
  940. m_fStartPageCalled = FALSE;
  941. m_fEndPageCalled = FALSE;
  942. return S_OK;
  943. }
  944. /*===================================================================
  945. CPageObject::InvokeMethod
  946. Invokes OnPageStart() or OnPageEnd()
  947. Parameters:
  948. DWORD iMethod which method
  949. CScriptingContext *pContext scripting context (for OnStart)
  950. CHitObj *pHitObj HitObj for errors
  951. Returns:
  952. HRESULT
  953. ===================================================================*/
  954. HRESULT CPageObject::InvokeMethod
  955. (
  956. DWORD iMethod,
  957. CScriptingContext *pContext,
  958. CHitObj *pHitObj
  959. )
  960. {
  961. BOOL fOnStart = (iMethod == ONPAGEINFO_ONSTARTPAGE);
  962. // check if method exists
  963. if (m_OnPageInfo.m_rgDispIds[iMethod] == DISPID_UNKNOWN)
  964. return S_OK;
  965. // two OnStart in a row - BAD
  966. Assert(!(fOnStart && m_fStartPageCalled));
  967. // two OnEnd in a row - BAD
  968. Assert(!(!fOnStart && m_fEndPageCalled));
  969. Assert(m_pDisp);
  970. HRESULT hr = S_OK;
  971. if (Glob(fExceptionCatchEnable))
  972. {
  973. // Call method inside TRY CATCH
  974. TRY
  975. hr = TryInvokeMethod
  976. (
  977. m_OnPageInfo.m_rgDispIds[iMethod],
  978. fOnStart,
  979. pContext,
  980. pHitObj
  981. );
  982. CATCH(nExcept)
  983. if (fOnStart)
  984. ExceptionId
  985. (
  986. IID_IObjectCover,
  987. IDE_COVER,
  988. IDE_COVER_ON_START_PAGE_GPF
  989. );
  990. else
  991. HandleErrorMissingFilename
  992. (
  993. IDE_COVER_ON_END_PAGE_GPF,
  994. pHitObj
  995. );
  996. hr = E_UNEXPECTED;
  997. END_TRY
  998. }
  999. else
  1000. {
  1001. // don't CATCH
  1002. hr = TryInvokeMethod
  1003. (
  1004. m_OnPageInfo.m_rgDispIds[iMethod],
  1005. fOnStart,
  1006. pContext,
  1007. pHitObj
  1008. );
  1009. }
  1010. if (fOnStart)
  1011. m_fStartPageCalled = TRUE;
  1012. else
  1013. m_fEndPageCalled = TRUE;
  1014. return hr;
  1015. }
  1016. /*===================================================================
  1017. CPageObject::TryInvokeMethod
  1018. Invokes OnPageStart() or OnPageEnd()
  1019. Parameters:
  1020. DISPID DispId method's DISPID
  1021. BOOL fOnStart TRUE if invoking OnStart
  1022. IDispatch *pDispContext scripting context (for OnStart)
  1023. CHitObj *pHitObj HitObj for errors
  1024. Returns:
  1025. HRESULT
  1026. ===================================================================*/
  1027. HRESULT CPageObject::TryInvokeMethod
  1028. (
  1029. DISPID DispId,
  1030. BOOL fOnStart,
  1031. IDispatch *pDispContext,
  1032. CHitObj *pHitObj
  1033. )
  1034. {
  1035. EXCEPINFO ExcepInfo;
  1036. DISPPARAMS DispParams;
  1037. VARIANT varResult;
  1038. VARIANT varParam;
  1039. UINT nArgErr;
  1040. memset(&DispParams, 0, sizeof(DISPPARAMS));
  1041. memset(&ExcepInfo, 0, sizeof(EXCEPINFO));
  1042. if (fOnStart)
  1043. {
  1044. VariantInit(&varParam);
  1045. V_VT(&varParam) = VT_DISPATCH;
  1046. V_DISPATCH(&varParam) = pDispContext;
  1047. DispParams.rgvarg = &varParam;
  1048. DispParams.cArgs = 1;
  1049. }
  1050. VariantInit(&varResult);
  1051. // Invoke it
  1052. HRESULT hr = m_pDisp->Invoke
  1053. (
  1054. DispId, // Call method
  1055. IID_NULL, // REFIID - Reserved, must be NULL
  1056. NULL, // Locale id
  1057. DISPATCH_METHOD, // Calling a method, not a property
  1058. &DispParams, // pass arguments
  1059. &varResult, // return value
  1060. &ExcepInfo, // exeption info on failure
  1061. &nArgErr
  1062. );
  1063. // Ignore errors indicating that this method doesnt exist.
  1064. if (FAILED(hr))
  1065. {
  1066. if (hr == E_NOINTERFACE ||
  1067. hr == DISP_E_MEMBERNOTFOUND ||
  1068. hr == DISP_E_UNKNOWNNAME)
  1069. {
  1070. // the above errors really aren't
  1071. hr = S_OK;
  1072. }
  1073. }
  1074. /*
  1075. * NOTE: The OnStartPage method is always called while the
  1076. * script is running, so we use ExceptionId and let the
  1077. * scripting engine report the error. OnEndPage is always
  1078. * called after the engine is gone, so we use HandleError.
  1079. */
  1080. if (FAILED(hr))
  1081. {
  1082. if (ExcepInfo.bstrSource && ExcepInfo.bstrDescription)
  1083. {
  1084. // User supplied error
  1085. Exception
  1086. (
  1087. IID_IObjectCover,
  1088. ExcepInfo.bstrSource,
  1089. ExcepInfo.bstrDescription
  1090. );
  1091. }
  1092. else if (fOnStart)
  1093. {
  1094. // Standard on-start error
  1095. ExceptionId
  1096. (
  1097. IID_IObjectCover,
  1098. IDE_COVER,
  1099. IDE_COVER_ON_START_PAGE_FAILED,
  1100. hr
  1101. );
  1102. }
  1103. else
  1104. {
  1105. // Standard on-end error
  1106. HandleErrorMissingFilename
  1107. (
  1108. IDE_COVER_ON_END_PAGE_FAILED,
  1109. pHitObj
  1110. );
  1111. }
  1112. }
  1113. return hr;
  1114. }
  1115. /*===================================================================
  1116. C C o m p o n e n t C o l l e c t i o n
  1117. ===================================================================*/
  1118. /*===================================================================
  1119. CComponentCollection::CComponentCollection
  1120. CComponentCollection constructor
  1121. Parameters:
  1122. Returns:
  1123. ===================================================================*/
  1124. CComponentCollection::CComponentCollection()
  1125. :
  1126. m_csScope(csUnknown),
  1127. m_fUseTaggedArray(FALSE), m_fUsePropArray(FALSE),
  1128. m_fHasComProperties(FALSE),
  1129. m_cAllTagged(0), m_cInstTagged(0),
  1130. m_cProperties(0), m_cUnnamed(0),
  1131. m_pCompFirst(NULL), m_fMTAConfigured(FALSE)
  1132. {
  1133. }
  1134. #ifdef DBG
  1135. /*===================================================================
  1136. CComponentCollection::AssertValid
  1137. Test to make sure that this is currently correctly formed
  1138. and assert if it is not.
  1139. Returns:
  1140. ===================================================================*/
  1141. void CComponentCollection::AssertValid() const
  1142. {
  1143. Assert(m_csScope != csUnknown);
  1144. m_htTaggedObjects.AssertValid();
  1145. m_htTaggedObjects.AssertValid();
  1146. m_htidIUnknownPtrs.AssertValid();
  1147. }
  1148. #endif
  1149. /*===================================================================
  1150. CComponentCollection::~CComponentCollection
  1151. CComponentCollection destructor
  1152. Deletes all the objects
  1153. Parameters:
  1154. Returns:
  1155. ===================================================================*/
  1156. CComponentCollection::~CComponentCollection()
  1157. {
  1158. UnInit();
  1159. }
  1160. /*===================================================================
  1161. CComponentCollection::Init
  1162. Sets collection scope
  1163. Initializes hash tables
  1164. Parameters:
  1165. Returns:
  1166. HRESULT
  1167. ===================================================================*/
  1168. HRESULT CComponentCollection::Init
  1169. (
  1170. CompScope scScope,
  1171. BOOL fMTAConfigured
  1172. )
  1173. {
  1174. HRESULT hr = S_OK;
  1175. m_csScope = scScope;
  1176. m_fMTAConfigured = fMTAConfigured;
  1177. hr = m_htTaggedObjects.Init(HT_TAGGED_OBJECTS_BUCKETS_MAX);
  1178. if (FAILED(hr))
  1179. return hr;
  1180. hr = m_htProperties.Init(HT_PROPERTIES_BUCKETS_MAX);
  1181. if (FAILED(hr))
  1182. return hr;
  1183. hr = m_htidIUnknownPtrs.Init(HT_IUNKNOWN_PTRS_BUCKETS_MAX);
  1184. if (FAILED(hr))
  1185. return hr;
  1186. return S_OK;
  1187. }
  1188. /*===================================================================
  1189. CComponentCollection::UnInit
  1190. Deletes all the objects
  1191. Parameters:
  1192. Returns:
  1193. S_OK
  1194. ===================================================================*/
  1195. HRESULT CComponentCollection::UnInit()
  1196. {
  1197. // clear out pointer arrays
  1198. m_rgpvTaggedObjects.Clear();
  1199. m_rgpvProperties.Clear();
  1200. m_fUseTaggedArray = FALSE;
  1201. m_fUsePropArray = FALSE;
  1202. // clear out name hash tables
  1203. m_htTaggedObjects.UnInit();
  1204. m_htProperties.UnInit();
  1205. // clear out pointers hash table
  1206. m_htidIUnknownPtrs.UnInit();
  1207. // delete all member component objects
  1208. if (m_pCompFirst)
  1209. {
  1210. CComponentObject *pObj = m_pCompFirst;
  1211. while (pObj)
  1212. {
  1213. CComponentObject *pNext = pObj->m_pCompNext;
  1214. delete pObj;
  1215. pObj = pNext;
  1216. }
  1217. m_pCompFirst = NULL;
  1218. }
  1219. // reset the counters
  1220. m_cAllTagged = 0;
  1221. m_cInstTagged = 0;
  1222. m_cProperties = 0;
  1223. m_cUnnamed = 0;
  1224. m_fHasComProperties = FALSE;
  1225. return S_OK;
  1226. }
  1227. /*===================================================================
  1228. CComponentCollection::AddComponentToNameHash
  1229. Adds an object to the proper hash table
  1230. Parameters:
  1231. CComponentObject *pObj object to add
  1232. LPWSTR pwszName object's name (hash)
  1233. DWORD cbName name length in bytes
  1234. Returns:
  1235. HRESULT
  1236. ===================================================================*/
  1237. HRESULT CComponentCollection::AddComponentToNameHash
  1238. (
  1239. CComponentObject *pObj,
  1240. LPWSTR pwszName,
  1241. DWORD cbName
  1242. )
  1243. {
  1244. Assert(pwszName);
  1245. Assert(cbName == (wcslen(pwszName) * sizeof(WCHAR)));
  1246. // determine which hash table
  1247. CHashTableStr *pHashTable;
  1248. if (pObj->m_ctType == ctTagged)
  1249. pHashTable = &m_htTaggedObjects;
  1250. else if (pObj->m_ctType == ctProperty)
  1251. pHashTable = &m_htProperties;
  1252. else
  1253. return S_OK; // nowhere to add, OK
  1254. // Initialize object's CLinkElem
  1255. HRESULT hr = pObj->Init(pwszName, cbName, m_fMTAConfigured);
  1256. if (FAILED(hr))
  1257. return hr;
  1258. // Add to hash table
  1259. CLinkElem *pAddedElem = pHashTable->AddElem(pObj);
  1260. if (!pAddedElem)
  1261. return E_FAIL; // couldn't add
  1262. if (pObj != static_cast<CComponentObject *>(pAddedElem))
  1263. return E_FAIL; // another object with the same name
  1264. // already there
  1265. return S_OK;
  1266. }
  1267. /*===================================================================
  1268. CComponentCollection::AddComponentToPtrHash
  1269. Adds an object to the IUnkown * hash table
  1270. Parameters:
  1271. CComponentObject *pObj object to add
  1272. Returns:
  1273. HRESULT
  1274. ===================================================================*/
  1275. HRESULT CComponentCollection::AddComponentToPtrHash
  1276. (
  1277. CComponentObject *pObj
  1278. )
  1279. {
  1280. // If we don't track the threading model, we don't care
  1281. // to add objects to cache by IUnknown * - no need to look them up
  1282. if (!Glob(fTrackThreadingModel))
  1283. return S_OK;
  1284. void *ptr = pObj->m_pUnknown;
  1285. if (!ptr)
  1286. return S_OK; // uninstatiated
  1287. if (FAILED(m_htidIUnknownPtrs.AddObject((DWORD_PTR)ptr, pObj)))
  1288. return E_FAIL;
  1289. pObj->m_fInPtrCache = TRUE;
  1290. return S_OK;
  1291. }
  1292. /*===================================================================
  1293. ComponentCollection::FindComponentObjectByName
  1294. Find tagged object by name
  1295. Parameters:
  1296. LPWSTR pwszName object's name
  1297. DWORD cbName name length
  1298. CComponentObject **ppObj found object
  1299. Returns:
  1300. HRESULT
  1301. (S_FALSE if no error - not found)
  1302. ===================================================================*/
  1303. HRESULT CComponentCollection::FindComponentObjectByName
  1304. (
  1305. LPWSTR pwszName,
  1306. DWORD cbName,
  1307. CComponentObject **ppObj
  1308. )
  1309. {
  1310. Assert(pwszName);
  1311. Assert(cbName == (wcslen(pwszName) * sizeof(WCHAR)));
  1312. CLinkElem *pElem = m_htTaggedObjects.FindElem(pwszName, cbName);
  1313. if (!pElem)
  1314. {
  1315. *ppObj = NULL;
  1316. return S_FALSE;
  1317. }
  1318. *ppObj = static_cast<CComponentObject *>(pElem);
  1319. return S_OK;
  1320. }
  1321. /*===================================================================
  1322. ComponentCollection::FindComponentPropertyByName
  1323. Find property by name
  1324. Parameters:
  1325. LPWSTR pwszName object's name
  1326. DWORD cbName name length
  1327. CComponentObject **ppObj found object
  1328. Returns:
  1329. HRESULT
  1330. (S_FALSE if no error - not found)
  1331. ===================================================================*/
  1332. HRESULT CComponentCollection::FindComponentPropertyByName
  1333. (
  1334. LPWSTR pwszName,
  1335. DWORD cbName,
  1336. CComponentObject **ppObj
  1337. )
  1338. {
  1339. Assert(pwszName);
  1340. Assert(cbName == (wcslen(pwszName) * sizeof(WCHAR)));
  1341. CLinkElem *pElem = m_htProperties.FindElem(pwszName, cbName);
  1342. if (!pElem)
  1343. {
  1344. *ppObj = NULL;
  1345. return S_FALSE;
  1346. }
  1347. *ppObj = static_cast<CComponentObject *>(pElem);
  1348. return S_OK;
  1349. }
  1350. /*===================================================================
  1351. ComponentCollection::FindComponentByIUnknownPtr
  1352. Find property by IUnknown *
  1353. Parameters:
  1354. IUnknown *pUnk find by this pointer
  1355. CComponentObject **ppObj found object
  1356. Returns:
  1357. HRESULT
  1358. (S_FALSE if no error - not found)
  1359. ===================================================================*/
  1360. HRESULT CComponentCollection::FindComponentByIUnknownPtr
  1361. (
  1362. IUnknown *pUnk,
  1363. CComponentObject **ppObj
  1364. )
  1365. {
  1366. void *pv;
  1367. if (m_htidIUnknownPtrs.FindObject((DWORD_PTR)pUnk, &pv) != S_OK)
  1368. {
  1369. *ppObj = NULL;
  1370. return S_FALSE;
  1371. }
  1372. *ppObj = reinterpret_cast<CComponentObject *>(pv);
  1373. return S_OK;
  1374. }
  1375. /*===================================================================
  1376. CComponentCollection::AddTagged
  1377. Adds a tagged object to the collection. Does not instanciate it yet.
  1378. Parameters:
  1379. LPWSTR pwszName Object name
  1380. CLSID &ClsId Class ID
  1381. CompModel cmModel Object model
  1382. Returns:
  1383. HRESULT
  1384. ===================================================================*/
  1385. HRESULT CComponentCollection::AddTagged
  1386. (
  1387. LPWSTR pwszName,
  1388. const CLSID &ClsId,
  1389. CompModel cmModel
  1390. )
  1391. {
  1392. HRESULT hr = S_OK;
  1393. DWORD cbName = CbWStr(pwszName); // do strlen once
  1394. if (m_htTaggedObjects.FindElem(pwszName, cbName))
  1395. return E_FAIL; // duplicate name
  1396. CComponentObject *pObj = new CComponentObject
  1397. (
  1398. m_csScope,
  1399. ctTagged,
  1400. cmModel
  1401. );
  1402. if (pObj == NULL)
  1403. return E_OUTOFMEMORY;
  1404. pObj->m_ClsId = ClsId;
  1405. hr = AddComponentToList(pObj);
  1406. if (FAILED(hr))
  1407. return hr;
  1408. hr = AddComponentToNameHash(pObj, pwszName, cbName);
  1409. if (FAILED(hr))
  1410. return hr;
  1411. if (m_fUseTaggedArray)
  1412. m_rgpvTaggedObjects.Append(pObj);
  1413. m_cAllTagged++;
  1414. return S_OK;
  1415. }
  1416. /*===================================================================
  1417. CComponentCollection::AddProperty
  1418. Adds a property object to the collection.
  1419. If property with the same name exists, it changes the value
  1420. Parameters:
  1421. LPWSTR pwszName Object name
  1422. VARIANT pVariant Property value
  1423. CComponentObject **ppObj [out] Property object could
  1424. be NULL if not requested
  1425. Returns:
  1426. HRESULT
  1427. ===================================================================*/
  1428. HRESULT CComponentCollection::AddProperty
  1429. (
  1430. LPWSTR pwszName,
  1431. VARIANT *pVariant,
  1432. CComponentObject **ppObj
  1433. )
  1434. {
  1435. if (ppObj)
  1436. *ppObj = NULL;
  1437. HRESULT hr = S_OK;
  1438. CComponentObject *pObj = NULL;
  1439. DWORD cbName = CbWStr(pwszName); // do strlen once
  1440. // Find the existing object first
  1441. CLinkElem *pElem = m_htProperties.FindElem(pwszName, cbName);
  1442. if (pElem)
  1443. {
  1444. // Object already exists - use it
  1445. pObj = static_cast<CComponentObject *>(pElem);
  1446. Assert(pObj->m_ctType == ctProperty);
  1447. // Clear out the object from any data
  1448. hr = pObj->Clear();
  1449. if (FAILED(hr))
  1450. return hr;
  1451. // Reinitialize object
  1452. pObj->m_csScope = m_csScope;
  1453. pObj->m_ctType = ctProperty;
  1454. pObj->m_cmModel = cmUnknown;
  1455. }
  1456. else
  1457. {
  1458. // Create new object
  1459. pObj = new CComponentObject(m_csScope, ctProperty, cmUnknown);
  1460. if (pObj == NULL)
  1461. return E_OUTOFMEMORY;
  1462. // Add the object to the list
  1463. hr = AddComponentToList(pObj);
  1464. if (FAILED(hr))
  1465. return hr;
  1466. // Add the object to the hash
  1467. hr = AddComponentToNameHash(pObj, pwszName, cbName);
  1468. if (FAILED(hr))
  1469. return hr;
  1470. // Add to properties array if needed
  1471. if (m_fUsePropArray)
  1472. m_rgpvProperties.Append(pObj);
  1473. m_cProperties++;
  1474. }
  1475. // Assign value
  1476. hr = pObj->SetPropertyValue(pVariant);
  1477. if (SUCCEEDED(hr))
  1478. {
  1479. // check if simple variant
  1480. if (!FIsSimpleVariant(&pObj->m_Variant))
  1481. m_fHasComProperties = TRUE;
  1482. }
  1483. // Return object ptr if requested
  1484. if (SUCCEEDED(hr))
  1485. {
  1486. if (ppObj)
  1487. *ppObj = pObj;
  1488. }
  1489. return hr;
  1490. }
  1491. /*===================================================================
  1492. CComponentCollection::AddUnnamed
  1493. Add object to be instantiated using Server.CreateObject
  1494. Parameters:
  1495. CLSID &ClsId Class ID
  1496. CompModel cmModel Object model
  1497. CComponentObject **ppObj Object Added
  1498. Returns:
  1499. HRESULT
  1500. ===================================================================*/
  1501. HRESULT CComponentCollection::AddUnnamed
  1502. (
  1503. const CLSID &ClsId,
  1504. CompModel cmModel,
  1505. CComponentObject **ppObj
  1506. )
  1507. {
  1508. HRESULT hr = S_OK;
  1509. if (cmModel == cmUnknown)
  1510. {
  1511. hr = CompModelFromCLSID(ClsId, &cmModel);
  1512. if (FAILED(hr))
  1513. return hr;
  1514. }
  1515. CComponentObject *pObj = new CComponentObject
  1516. (
  1517. m_csScope,
  1518. ctUnnamed,
  1519. cmModel
  1520. );
  1521. if (pObj == NULL)
  1522. return E_OUTOFMEMORY;
  1523. pObj->m_ClsId = ClsId;
  1524. hr = AddComponentToList(pObj);
  1525. if (FAILED(hr))
  1526. return hr;
  1527. *ppObj = pObj;
  1528. m_cUnnamed++;
  1529. return S_OK;
  1530. }
  1531. /*===================================================================
  1532. CComponentCollection::GetTagged
  1533. Finds tagged object by name
  1534. Parameters:
  1535. LPWSTR pwszName Object name
  1536. CComponentObject **ppObj [out] Object Found
  1537. Returns:
  1538. HRESULT
  1539. ===================================================================*/
  1540. HRESULT CComponentCollection::GetTagged
  1541. (
  1542. LPWSTR pwszName,
  1543. CComponentObject **ppObj
  1544. )
  1545. {
  1546. Assert(ppObj);
  1547. *ppObj = NULL;
  1548. CComponentObject *pObj = NULL;
  1549. HRESULT hr = FindComponentObjectByName
  1550. (
  1551. pwszName,
  1552. CbWStr(pwszName),
  1553. &pObj
  1554. );
  1555. if (FAILED(hr))
  1556. return hr;
  1557. if (pObj && pObj->m_ctType != ctTagged)
  1558. pObj = NULL;
  1559. if (pObj)
  1560. *ppObj = pObj;
  1561. else
  1562. hr = TYPE_E_ELEMENTNOTFOUND;
  1563. return hr;
  1564. }
  1565. /*===================================================================
  1566. CComponentCollection::GetProperty
  1567. Finds property object by name
  1568. Parameters:
  1569. LPWSTR pwszName Property name
  1570. CComponentObject **ppObj [out] Object Found
  1571. Returns:
  1572. HRESULT
  1573. ===================================================================*/
  1574. HRESULT CComponentCollection::GetProperty
  1575. (
  1576. LPWSTR pwszName,
  1577. CComponentObject **ppObj
  1578. )
  1579. {
  1580. Assert(ppObj);
  1581. *ppObj = NULL;
  1582. CComponentObject *pObj = NULL;
  1583. HRESULT hr = FindComponentPropertyByName
  1584. (
  1585. pwszName,
  1586. CbWStr(pwszName),
  1587. &pObj
  1588. );
  1589. if (FAILED(hr))
  1590. return hr;
  1591. if (pObj)
  1592. *ppObj = pObj;
  1593. else
  1594. hr = TYPE_E_ELEMENTNOTFOUND;
  1595. return hr;
  1596. }
  1597. /*===================================================================
  1598. CComponentCollection::GetNameByIndex
  1599. Find name of a tagged objects or property by index
  1600. Parameters:
  1601. CompType ctType tagged or property
  1602. int index index (1-based)
  1603. LPWSTR *ppwszName [out] name (NOT allocated)
  1604. Returns:
  1605. HRESULT
  1606. ===================================================================*/
  1607. HRESULT CComponentCollection::GetNameByIndex
  1608. (
  1609. CompType ctType,
  1610. int index,
  1611. LPWSTR *ppwszName
  1612. )
  1613. {
  1614. CPtrArray *pPtrArray;
  1615. if (ctType == ctTagged)
  1616. {
  1617. if (!m_fUseTaggedArray)
  1618. StartUsingTaggedObjectsArray();
  1619. pPtrArray = &m_rgpvTaggedObjects;
  1620. }
  1621. else if (ctType == ctProperty)
  1622. {
  1623. if (!m_fUsePropArray)
  1624. StartUsingPropertiesArray();
  1625. pPtrArray = &m_rgpvProperties;
  1626. }
  1627. else
  1628. {
  1629. Assert(FALSE);
  1630. *ppwszName = NULL;
  1631. return E_FAIL;
  1632. }
  1633. if (index >= 1 && index <= pPtrArray->Count())
  1634. {
  1635. CComponentObject *pObj = (CComponentObject *)pPtrArray->Get(index-1);
  1636. if (pObj)
  1637. {
  1638. Assert(pObj->GetType() == ctType);
  1639. *ppwszName = pObj->GetName();
  1640. if (*ppwszName)
  1641. return S_OK;
  1642. }
  1643. }
  1644. *ppwszName = NULL;
  1645. return E_FAIL;
  1646. }
  1647. /*===================================================================
  1648. CComponentCollection::RemoveComponent
  1649. Remove a known component.
  1650. Slow method for a non-recent objects.
  1651. Parameters:
  1652. CComponentObject *pObj -- object to remove
  1653. Returns:
  1654. HRESULT
  1655. ===================================================================*/
  1656. HRESULT CComponentCollection::RemoveComponent
  1657. (
  1658. CComponentObject *pObj
  1659. )
  1660. {
  1661. Assert(pObj);
  1662. // Remove from by-name hash tables and arrays
  1663. if (pObj->m_ctType == ctTagged)
  1664. {
  1665. // tagged cannot be removed
  1666. Assert(FALSE);
  1667. return E_FAIL;
  1668. }
  1669. else if (pObj->m_ctType == ctProperty)
  1670. {
  1671. // hash table
  1672. if (m_htProperties.DeleteElem(pObj->GetName(), CbWStr(pObj->GetName())))
  1673. {
  1674. m_cProperties--;
  1675. }
  1676. // array
  1677. if (m_fUsePropArray)
  1678. {
  1679. m_rgpvProperties.Remove(pObj);
  1680. }
  1681. }
  1682. else
  1683. {
  1684. Assert(pObj->m_ctType == ctUnnamed);
  1685. m_cUnnamed--;
  1686. }
  1687. // Remove from the 'by pointer hash table'
  1688. if (pObj->m_fInPtrCache)
  1689. {
  1690. void *ptr = pObj->m_pUnknown;
  1691. if (ptr)
  1692. m_htidIUnknownPtrs.RemoveObject((DWORD_PTR)ptr);
  1693. pObj->m_fInPtrCache = FALSE;
  1694. }
  1695. // Remove from the list
  1696. RemoveComponentFromList(pObj);
  1697. // Remove
  1698. delete pObj;
  1699. return S_OK;
  1700. }
  1701. /*===================================================================
  1702. CComponentCollection::RemovePropery
  1703. Remove a property by name.
  1704. Parameters:
  1705. LPWSTR pwszName -- property name
  1706. Returns:
  1707. HRESULT
  1708. ===================================================================*/
  1709. HRESULT CComponentCollection::RemoveProperty
  1710. (
  1711. LPWSTR pwszName
  1712. )
  1713. {
  1714. CComponentObject *pObj = NULL;
  1715. HRESULT hr = FindComponentPropertyByName
  1716. (
  1717. pwszName,
  1718. CbWStr(pwszName),
  1719. &pObj
  1720. );
  1721. if (FAILED(hr))
  1722. return hr;
  1723. if (pObj)
  1724. hr = RemoveComponent(pObj);
  1725. return hr;
  1726. }
  1727. /*===================================================================
  1728. CComponentCollection::RemoveAllProperties
  1729. Remove all properties. Faster than iterating.
  1730. Parameters:
  1731. Returns:
  1732. HRESULT
  1733. ===================================================================*/
  1734. HRESULT CComponentCollection::RemoveAllProperties()
  1735. {
  1736. // Clear out the properties array
  1737. if (m_fUsePropArray)
  1738. {
  1739. m_rgpvProperties.Clear();
  1740. m_fUsePropArray = FALSE;
  1741. }
  1742. // Walk the object list to remove properties
  1743. CComponentObject *pObj = m_pCompFirst;
  1744. while (pObj)
  1745. {
  1746. CComponentObject *pNextObj = pObj->m_pCompNext;
  1747. if (pObj->m_ctType == ctProperty)
  1748. {
  1749. // remove from the hash table
  1750. m_htProperties.DeleteElem(pObj->GetName(), CbWStr(pObj->GetName()));
  1751. // properties are not in the 'by pointer hash table'
  1752. Assert(!pObj->m_fInPtrCache);
  1753. // remove from the list
  1754. RemoveComponentFromList(pObj);
  1755. // remove
  1756. delete pObj;
  1757. }
  1758. pObj = pNextObj;
  1759. }
  1760. m_cProperties = 0;
  1761. m_fHasComProperties = FALSE;
  1762. return S_OK;
  1763. }
  1764. /*===================================================================
  1765. CComponentCollection::StartUsingTaggedObjectsArray
  1766. Fill in the tagged objects array for access by index for the
  1767. first time
  1768. Parameters:
  1769. Returns:
  1770. HRESULT
  1771. ===================================================================*/
  1772. HRESULT CComponentCollection::StartUsingTaggedObjectsArray()
  1773. {
  1774. if (m_fUseTaggedArray)
  1775. return S_OK;
  1776. m_rgpvTaggedObjects.Clear();
  1777. CComponentObject *pObj = m_pCompFirst;
  1778. while (pObj)
  1779. {
  1780. if (pObj->GetType() == ctTagged)
  1781. m_rgpvTaggedObjects.Append(pObj);
  1782. pObj = pObj->m_pCompNext;
  1783. }
  1784. m_fUseTaggedArray = TRUE;
  1785. return S_OK;
  1786. }
  1787. /*===================================================================
  1788. CComponentCollection::StartUsingPropertiesArray
  1789. Fill in the properties array for access by index for the
  1790. first time
  1791. Parameters:
  1792. Returns:
  1793. HRESULT
  1794. ===================================================================*/
  1795. HRESULT CComponentCollection::StartUsingPropertiesArray()
  1796. {
  1797. if (m_fUsePropArray)
  1798. return S_OK;
  1799. m_rgpvProperties.Clear();
  1800. CComponentObject *pObj = m_pCompFirst;
  1801. while (pObj)
  1802. {
  1803. if (pObj->GetType() == ctProperty)
  1804. m_rgpvProperties.Prepend(pObj); // backwards
  1805. pObj = pObj->m_pCompNext;
  1806. }
  1807. m_fUsePropArray = TRUE;
  1808. return S_OK;
  1809. }
  1810. /*===================================================================
  1811. C P a g e C o m p o n e n t M a n a g e r
  1812. ===================================================================*/
  1813. /*===================================================================
  1814. CPageComponentManager::CPageComponentManager
  1815. CPageComponentManager constructor
  1816. Parameters:
  1817. Returns:
  1818. ===================================================================*/
  1819. CPageComponentManager::CPageComponentManager()
  1820. : m_pHitObj(NULL)
  1821. {
  1822. }
  1823. #ifdef DBG
  1824. /*===================================================================
  1825. CPageComponentManager::AssertValid()
  1826. Test to make sure that this is currently correctly formed
  1827. and assert if it is not.
  1828. Returns:
  1829. ===================================================================*/
  1830. void CPageComponentManager::AssertValid() const
  1831. {
  1832. Assert(m_pHitObj);
  1833. m_pHitObj->AssertValid();
  1834. m_htidPageObjects.AssertValid();
  1835. }
  1836. #endif
  1837. /*===================================================================
  1838. CPageComponentManager::~CPageComponentManager
  1839. CPageComponentManager destructor
  1840. Deletes all page objects
  1841. Parameters:
  1842. Returns:
  1843. ===================================================================*/
  1844. CPageComponentManager::~CPageComponentManager()
  1845. {
  1846. // delete all page objects
  1847. m_htidPageObjects.IterateObjects(DeletePageObjectCB);
  1848. }
  1849. /*===================================================================
  1850. CPageComponentManager::DeletePageObjectCB
  1851. Static callback from hash table iterator to delete a CPageObject
  1852. Parameters:
  1853. pvObj CPageObject* to delete passed as void*
  1854. Returns:
  1855. iccContinue
  1856. ===================================================================*/
  1857. IteratorCallbackCode CPageComponentManager::DeletePageObjectCB
  1858. (
  1859. void *pvObj,
  1860. void *,
  1861. void *
  1862. )
  1863. {
  1864. Assert(pvObj);
  1865. CPageObject *pObj = reinterpret_cast<CPageObject *>(pvObj);
  1866. delete pObj;
  1867. return iccContinue;
  1868. }
  1869. /*===================================================================
  1870. CPageComponentManager::Init
  1871. Sets collection scope (to page)
  1872. Initializes hash tables
  1873. Parameters:
  1874. CHitObj *pHitObj this page
  1875. Returns:
  1876. HRESULT
  1877. ===================================================================*/
  1878. HRESULT CPageComponentManager::Init
  1879. (
  1880. CHitObj *pHitObj
  1881. )
  1882. {
  1883. HRESULT hr;
  1884. // Init hash table of Page Objects
  1885. hr = m_htidPageObjects.Init(HT_PAGE_OBJECTS_BUCKETS_MAX);
  1886. if (FAILED(hr))
  1887. return hr;
  1888. // remember pHitObj
  1889. m_pHitObj = pHitObj;
  1890. return S_OK;
  1891. }
  1892. /*===================================================================
  1893. CPageComponentManager::OnStartPage
  1894. Adds new page object. Ignores objects withount page info
  1895. (OnEndPage is done for all objects at the end of page)
  1896. Parameters:
  1897. CComponentObject *pCompObj object to do OnStartPage
  1898. CScriptingContext *pContext arg to OnStart
  1899. COnPageInfo *pOnPageInfo pre-queried ids (optional)
  1900. BOOL *pfStarted returned flag
  1901. Returns:
  1902. HRESULT
  1903. ===================================================================*/
  1904. HRESULT CPageComponentManager::OnStartPage
  1905. (
  1906. CComponentObject *pCompObj,
  1907. CScriptingContext *pContext,
  1908. const COnPageInfo *pOnPageInfo,
  1909. BOOL *pfStarted
  1910. )
  1911. {
  1912. IDispatch *pDisp = pCompObj->m_pDisp;
  1913. HRESULT hr = S_OK;
  1914. if(pDisp == NULL)
  1915. {
  1916. Assert(pCompObj->m_dwGIPCookie != NULL_GIP_COOKIE);
  1917. // try to restore from cookie
  1918. hr = g_GIPAPI.Get
  1919. (
  1920. pCompObj->m_dwGIPCookie,
  1921. IID_IDispatch,
  1922. (void **)&pDisp
  1923. );
  1924. if (FAILED(hr))
  1925. return hr;
  1926. }
  1927. else
  1928. pDisp->AddRef();
  1929. Assert(pDisp);
  1930. Assert(pfStarted);
  1931. *pfStarted = FALSE;
  1932. // check if onpageinfo passed and the methods aren't defined
  1933. if (pOnPageInfo && !pOnPageInfo->FHasAnyMethod())
  1934. {
  1935. pDisp->Release();
  1936. return S_OK;
  1937. }
  1938. // check if already in the PageObject Hash
  1939. if (m_htidPageObjects.FindObject((DWORD_PTR)pDisp) == S_OK)
  1940. {
  1941. pDisp->Release();
  1942. return S_OK;
  1943. }
  1944. COnPageInfo OnPageInfo;
  1945. if (pOnPageInfo)
  1946. {
  1947. OnPageInfo = *pOnPageInfo;
  1948. }
  1949. else
  1950. {
  1951. // dynamically create OnPageInfo if not passed
  1952. if (Glob(fExceptionCatchEnable))
  1953. {
  1954. TRY
  1955. hr = QueryOnPageInfo(pDisp, &OnPageInfo);
  1956. CATCH(nExcept)
  1957. HandleErrorMissingFilename(IDE_SCRIPT_OBJ_ONPAGE_QI_FAILED,
  1958. m_pHitObj,
  1959. TRUE,
  1960. pCompObj->GetName(),
  1961. nExcept);
  1962. hr = nExcept;
  1963. END_TRY
  1964. }
  1965. else
  1966. {
  1967. hr = QueryOnPageInfo(pDisp, &OnPageInfo);
  1968. }
  1969. if (FAILED(hr))
  1970. {
  1971. pDisp->Release();
  1972. return hr;
  1973. }
  1974. // check if any of the methods is defined
  1975. if (!OnPageInfo.FHasAnyMethod())
  1976. {
  1977. pDisp->Release();
  1978. return S_OK;
  1979. }
  1980. }
  1981. // create object
  1982. CPageObject *pPageObj = new CPageObject;
  1983. if (!pPageObj)
  1984. {
  1985. pDisp->Release();
  1986. return E_OUTOFMEMORY;
  1987. }
  1988. // init LinkElem
  1989. hr = pPageObj->Init(pDisp, OnPageInfo); // this eats our previous AddRef()
  1990. if (SUCCEEDED(hr))
  1991. {
  1992. // add to hash table
  1993. hr = m_htidPageObjects.AddObject((DWORD_PTR)pDisp, pPageObj);
  1994. }
  1995. // cleanup if failed
  1996. if (FAILED(hr) && pPageObj)
  1997. {
  1998. pDisp->Release(); // Init failed, so remove our AddRef()
  1999. delete pPageObj;
  2000. return hr;
  2001. }
  2002. *pfStarted = TRUE;
  2003. return pPageObj->InvokeMethod
  2004. (
  2005. ONPAGEINFO_ONSTARTPAGE,
  2006. pContext,
  2007. m_pHitObj
  2008. );
  2009. }
  2010. /*===================================================================
  2011. PageComponentManager::OnEndPageAllObjects
  2012. Does OnEndPage() for all objects that need it
  2013. (OnStartPage() is on demand basis)
  2014. Parameters:
  2015. Returns:
  2016. HRESULT
  2017. ===================================================================*/
  2018. HRESULT CPageComponentManager::OnEndPageAllObjects()
  2019. {
  2020. HRESULT hrGlobal = S_OK;
  2021. m_htidPageObjects.IterateObjects
  2022. (
  2023. OnEndPageObjectCB,
  2024. m_pHitObj,
  2025. &hrGlobal
  2026. );
  2027. return hrGlobal;
  2028. }
  2029. /*===================================================================
  2030. CPageComponentManager::OnEndPageObjectCB
  2031. Static callback from hash table iterator to execute OnEndPage
  2032. for a CPageObject
  2033. Parameters:
  2034. pvObj CPageObject* to delete passed as void*
  2035. Returns:
  2036. iccContinue
  2037. ===================================================================*/
  2038. IteratorCallbackCode CPageComponentManager::OnEndPageObjectCB
  2039. (
  2040. void *pvObj,
  2041. void *pvHitObj,
  2042. void *pvhr
  2043. )
  2044. {
  2045. Assert(pvObj);
  2046. Assert(pvHitObj);
  2047. Assert(pvhr);
  2048. CPageObject *pObj = reinterpret_cast<CPageObject *>(pvObj);
  2049. HRESULT hr = pObj->InvokeMethod
  2050. (
  2051. ONPAGEINFO_ONENDPAGE,
  2052. NULL,
  2053. reinterpret_cast<CHitObj *>(pvHitObj)
  2054. );
  2055. if (FAILED(hr))
  2056. *(reinterpret_cast<HRESULT *>(pvhr)) = hr;
  2057. return iccContinue;
  2058. }
  2059. /*===================================================================
  2060. CPageComponentManager::GetPageCollection
  2061. Queries HitObj for the Page's Component Collection
  2062. Parameters:
  2063. CComponentCollection **ppCollection (out)
  2064. Returns:
  2065. HRESULT
  2066. ===================================================================*/
  2067. HRESULT CPageComponentManager::GetPageCollection
  2068. (
  2069. CComponentCollection **ppCollection
  2070. )
  2071. {
  2072. Assert(m_pHitObj);
  2073. *ppCollection = NULL;
  2074. return m_pHitObj->GetPageComponentCollection(ppCollection);
  2075. }
  2076. /*===================================================================
  2077. CPageComponentManager::GetSessionCollection
  2078. Queries HitObj for the Session's Component Collection
  2079. Parameters:
  2080. CComponentCollection **ppCollection (out)
  2081. Returns:
  2082. HRESULT
  2083. ===================================================================*/
  2084. HRESULT CPageComponentManager::GetSessionCollection
  2085. (
  2086. CComponentCollection **ppCollection
  2087. )
  2088. {
  2089. Assert(m_pHitObj);
  2090. *ppCollection = NULL;
  2091. return m_pHitObj->GetSessionComponentCollection(ppCollection);
  2092. }
  2093. /*===================================================================
  2094. CPageComponentManager::GetApplnCollection
  2095. Queries HitObj for the Application's Component Collection
  2096. Parameters:
  2097. CComponentCollection **ppCollection (out)
  2098. Returns:
  2099. HRESULT
  2100. ===================================================================*/
  2101. HRESULT CPageComponentManager::GetApplnCollection
  2102. (
  2103. CComponentCollection **ppCollection
  2104. )
  2105. {
  2106. Assert(m_pHitObj);
  2107. *ppCollection = NULL;
  2108. return m_pHitObj->GetApplnComponentCollection(ppCollection);
  2109. }
  2110. /*===================================================================
  2111. CPageComponentManager::GetCollectionByScope
  2112. Gets the collection corresponding to the scope
  2113. Parameters:
  2114. CompScope csScope (in) desired scope
  2115. CComponentCollection **ppCollection (out)
  2116. Returns:
  2117. HRESULT
  2118. ===================================================================*/
  2119. HRESULT CPageComponentManager::GetCollectionByScope
  2120. (
  2121. CompScope scScope,
  2122. CComponentCollection **ppCollection
  2123. )
  2124. {
  2125. HRESULT hr = S_OK;
  2126. switch (scScope)
  2127. {
  2128. case csPage:
  2129. hr = GetPageCollection(ppCollection);
  2130. break;
  2131. case csSession:
  2132. hr = GetSessionCollection(ppCollection);
  2133. break;
  2134. case csAppln:
  2135. hr = GetApplnCollection(ppCollection);
  2136. break;
  2137. default:
  2138. hr = E_UNEXPECTED;
  2139. break;
  2140. }
  2141. if (FAILED(hr))
  2142. *ppCollection = NULL;
  2143. else if (*ppCollection == NULL)
  2144. hr = E_POINTER; // to make sure we fail if no collection
  2145. return hr;
  2146. }
  2147. /*===================================================================
  2148. CPageComponentManager::FindScopedComponentByName
  2149. Finds object by name. Searches multiple collections if
  2150. the scope is unknown.
  2151. Internal private method used in GetScoped...()
  2152. Parameters:
  2153. CompScope csScope Scope (could be csUnknown)
  2154. LPWSTR pwszName Object name
  2155. DWORD cbName name length
  2156. BOOL fProperty TRUE = property,
  2157. FALSE = tagged
  2158. CComponentObject **ppObj (out) Object found
  2159. CComponentCollection **ppCollection (out) Collection where found
  2160. (optional)
  2161. Returns:
  2162. HRESULT
  2163. (S_FALSE if no error - not found)
  2164. ===================================================================*/
  2165. HRESULT CPageComponentManager::FindScopedComponentByName
  2166. (
  2167. CompScope csScope,
  2168. LPWSTR pwszName,
  2169. DWORD cbName,
  2170. BOOL fProperty,
  2171. CComponentObject **ppObj,
  2172. CComponentCollection **ppCollection
  2173. )
  2174. {
  2175. int cMaxTry = (csScope == csUnknown) ? 3 : 1;
  2176. int cTry = 0;
  2177. *ppObj = NULL;
  2178. while (*ppObj == NULL && cTry < cMaxTry)
  2179. {
  2180. HRESULT hr = S_OK;
  2181. CComponentCollection *pCollection = NULL;
  2182. switch (++cTry)
  2183. {
  2184. case 1: // page (or explicit scope) first
  2185. if (csScope == csUnknown)
  2186. hr = GetPageCollection(&pCollection);
  2187. else // explicit scope
  2188. hr = GetCollectionByScope(csScope, &pCollection);
  2189. break;
  2190. case 2: // session
  2191. hr = GetSessionCollection(&pCollection);
  2192. break;
  2193. case 3: // application
  2194. hr = GetApplnCollection(&pCollection);
  2195. break;
  2196. }
  2197. if (FAILED(hr) || !pCollection)
  2198. continue; // couldn't get the collection
  2199. Assert(cbName == (wcslen(pwszName) * sizeof(WCHAR)));
  2200. // find the object
  2201. if (fProperty)
  2202. {
  2203. hr = pCollection->FindComponentPropertyByName
  2204. (
  2205. pwszName,
  2206. cbName,
  2207. ppObj
  2208. );
  2209. }
  2210. else
  2211. {
  2212. hr = pCollection->FindComponentObjectByName
  2213. (
  2214. pwszName,
  2215. cbName,
  2216. ppObj
  2217. );
  2218. }
  2219. if (hr != S_OK)
  2220. *ppObj = NULL;
  2221. // remember where found
  2222. if (*ppObj && ppCollection)
  2223. *ppCollection = pCollection;
  2224. }
  2225. return (*ppObj ? S_OK : S_FALSE);
  2226. }
  2227. /*===================================================================
  2228. CPageComponentManager::AddScopedTagged
  2229. Adds a tagged object to the collection. Does not instantiate it yet.
  2230. Parameters:
  2231. CompScope csScope Object scope (which collection)
  2232. LPWSTR pwszName Object name
  2233. CLSID &ClsId Class ID
  2234. CompModel cmModel Object model
  2235. Returns:
  2236. HRESULT
  2237. ===================================================================*/
  2238. HRESULT CPageComponentManager::AddScopedTagged
  2239. (
  2240. CompScope csScope,
  2241. LPWSTR pwszName,
  2242. const CLSID &ClsId,
  2243. CompModel cmModel
  2244. )
  2245. {
  2246. CComponentCollection *pCollection;
  2247. HRESULT hr = GetCollectionByScope(csScope, &pCollection);
  2248. if (FAILED(hr))
  2249. return hr;
  2250. return pCollection->AddTagged(pwszName, ClsId, cmModel);
  2251. }
  2252. /*===================================================================
  2253. CPageComponentManager::AddScopedProperty
  2254. Adds a property object to the collection.
  2255. If property with the same name exists, it changes the value
  2256. Parameters:
  2257. CompScope csScope Object scope (which collection)
  2258. LPWSTR pwszName Object name
  2259. VARIANT pVariant Property value
  2260. CComponentObject **ppObj [out] Property object could
  2261. be NULL if not requested
  2262. Returns:
  2263. HRESULT
  2264. ===================================================================*/
  2265. HRESULT CPageComponentManager::AddScopedProperty
  2266. (
  2267. CompScope csScope,
  2268. LPWSTR pwszName,
  2269. VARIANT *pVariant,
  2270. CComponentObject **ppObj
  2271. )
  2272. {
  2273. CComponentCollection *pCollection;
  2274. HRESULT hr = GetCollectionByScope(csScope, &pCollection);
  2275. if (FAILED(hr))
  2276. {
  2277. if (ppObj)
  2278. *ppObj = NULL;
  2279. return hr;
  2280. }
  2281. return pCollection->AddProperty(pwszName, pVariant, ppObj);
  2282. }
  2283. /*===================================================================
  2284. CPageComponentManager::AddScopedUnnamedInstantiated
  2285. Server.CreateObject
  2286. Also does OnStartPage (adds created pDisp as CPageObject)
  2287. Parameters:
  2288. csScope Object scope (which collection)
  2289. ClsId Class ID
  2290. cmModel Object model
  2291. pOnPageInfo DispIds for OnStartPage/OnEndPage (can be NULL)
  2292. ppObj [out] Object Added
  2293. Returns:
  2294. HRESULT
  2295. ===================================================================*/
  2296. HRESULT CPageComponentManager::AddScopedUnnamedInstantiated
  2297. (
  2298. CompScope csScope,
  2299. const CLSID &ClsId,
  2300. CompModel cmModel,
  2301. COnPageInfo *pOnPageInfo,
  2302. CComponentObject **ppObj
  2303. )
  2304. {
  2305. CComponentCollection *pCollection;
  2306. HRESULT hr = GetCollectionByScope(csScope, &pCollection);
  2307. if (FAILED(hr))
  2308. return hr;
  2309. hr = pCollection->AddUnnamed(ClsId, cmModel, ppObj);
  2310. if (FAILED(hr))
  2311. return hr;
  2312. CComponentObject *pObj = *ppObj;
  2313. // remember passed OnPageInfo
  2314. if (pOnPageInfo)
  2315. {
  2316. pObj->m_OnPageInfo = *pOnPageInfo;
  2317. pObj->m_fOnPageInfoCached = TRUE;
  2318. }
  2319. // create it
  2320. hr = pObj->Instantiate(m_pHitObj);
  2321. if (FAILED(hr))
  2322. return hr;
  2323. // add to pointer cash
  2324. pCollection->AddComponentToPtrHash(pObj);
  2325. // add as page object when needed
  2326. if (csScope == csPage
  2327. && (pObj->m_pDisp || (pObj->m_dwGIPCookie != NULL_GIP_COOKIE))
  2328. && m_pHitObj && m_pHitObj->FIsBrowserRequest())
  2329. {
  2330. BOOL fStarted = FALSE;
  2331. hr = OnStartPage
  2332. (
  2333. pObj,
  2334. m_pHitObj->PScriptingContextGet(),
  2335. pObj->GetCachedOnPageInfo(),
  2336. &fStarted
  2337. );
  2338. if (fStarted)
  2339. pObj->m_fOnPageStarted = TRUE;
  2340. }
  2341. return hr;
  2342. }
  2343. /*===================================================================
  2344. CPageComponentManager::GetScopedObjectInstantiated
  2345. Finds component object (tagged) by name.
  2346. Scope could be csUnknown.
  2347. Instantiates tagged objects.
  2348. Also does OnStartPage (adds created pDisp as CPageObject)
  2349. Parameters:
  2350. CompScope csScope Scope (could be csUnknown)
  2351. LPWSTR pwszName Object name
  2352. DWORD cbName Object name length (in bytes)
  2353. CComponentObject **ppObj Object found
  2354. BOOL *pfNewInstance [out] TRUE if just instantiated
  2355. Returns:
  2356. HRESULT
  2357. ===================================================================*/
  2358. HRESULT CPageComponentManager::GetScopedObjectInstantiated
  2359. (
  2360. CompScope csScope,
  2361. LPWSTR pwszName,
  2362. DWORD cbName,
  2363. CComponentObject **ppObj,
  2364. BOOL *pfNewInstance
  2365. )
  2366. {
  2367. HRESULT hr;
  2368. Assert(pfNewInstance);
  2369. *pfNewInstance = FALSE;
  2370. CComponentCollection *pCollection;
  2371. hr = FindScopedComponentByName
  2372. (
  2373. csScope,
  2374. pwszName,
  2375. cbName,
  2376. FALSE,
  2377. ppObj,
  2378. &pCollection
  2379. );
  2380. if (FAILED(hr))
  2381. return hr;
  2382. CComponentObject *pObj = *ppObj;
  2383. if (!pObj) // not failed, but not found either
  2384. return TYPE_E_ELEMENTNOTFOUND;
  2385. if (pObj->m_ctType != ctTagged)
  2386. return S_OK;
  2387. // For tagged only - instantiate and do OnStartPage()
  2388. // For application level objects instantiation must be
  2389. // done within critical section
  2390. BOOL fApplnLocked = FALSE;
  2391. Assert(m_pHitObj);
  2392. if (!pObj->m_fInstantiatedTagged && // uninstantiated
  2393. pObj->m_csScope == csAppln && // application scope
  2394. m_pHitObj->PAppln()->FFirstRequestRun()) // after GLOBAL.ASA
  2395. {
  2396. // Lock
  2397. m_pHitObj->PAppln()->Lock();
  2398. // check if the object is still uninstantiated
  2399. if (!pObj->m_fInstantiatedTagged)
  2400. {
  2401. // yes, still uninstantiated - keep the lock
  2402. fApplnLocked = TRUE;
  2403. }
  2404. else
  2405. {
  2406. // object instantiated while we waited - don't keep lock
  2407. m_pHitObj->PAppln()->UnLock();
  2408. }
  2409. }
  2410. // Instantiate tagged if needed
  2411. if (!pObj->m_fInstantiatedTagged)
  2412. {
  2413. if ((pObj->m_csScope == csAppln) && !pObj->m_fMTAConfigured)
  2414. {
  2415. // For applicatin scoped objects, instantiate from MTA if we're not
  2416. // already executing on the MTA.
  2417. hr = CallMTACallback
  2418. (
  2419. CPageComponentManager::InstantiateObjectFromMTA,
  2420. pObj,
  2421. m_pHitObj
  2422. );
  2423. }
  2424. else
  2425. {
  2426. hr = pObj->Instantiate(m_pHitObj);
  2427. }
  2428. if (SUCCEEDED(hr))
  2429. {
  2430. // keep count
  2431. pCollection->m_cInstTagged++;
  2432. // add to pointer cash
  2433. pCollection->AddComponentToPtrHash(pObj);
  2434. // return flag
  2435. *pfNewInstance = TRUE;
  2436. }
  2437. // Flag as instantiated even if failed
  2438. pObj->m_fInstantiatedTagged = TRUE;
  2439. }
  2440. // Remove the lock kept while instantiating appln level object
  2441. if (fApplnLocked)
  2442. m_pHitObj->PAppln()->UnLock();
  2443. // Return if [instantiation] failed
  2444. if (FAILED(hr))
  2445. {
  2446. *ppObj = NULL;
  2447. return hr;
  2448. }
  2449. // Add as page object when needed
  2450. if (pObj->m_csScope != csAppln
  2451. && (pObj->m_pDisp || (pObj->m_dwGIPCookie != NULL_GIP_COOKIE))
  2452. && m_pHitObj && m_pHitObj->FIsBrowserRequest())
  2453. {
  2454. BOOL fStarted;
  2455. OnStartPage // don't care if failed
  2456. (
  2457. pObj,
  2458. m_pHitObj->PScriptingContextGet(),
  2459. pObj->GetCachedOnPageInfo(),
  2460. &fStarted
  2461. );
  2462. }
  2463. return hr;
  2464. }
  2465. /*===================================================================
  2466. CPageComponentManager::InstantiateObjectFromMTA
  2467. Static callback called by CallMTACallback() to
  2468. instantiate aplication scoped objects
  2469. Parameters:
  2470. void *pvObj ComponentObject
  2471. void *pvHitObj HitObj
  2472. Returns:
  2473. HRESULT
  2474. ===================================================================*/
  2475. HRESULT __stdcall CPageComponentManager::InstantiateObjectFromMTA
  2476. (
  2477. void *pvObj,
  2478. void *pvHitObj
  2479. )
  2480. {
  2481. Assert(pvHitObj);
  2482. Assert(pvObj);
  2483. CHitObj *pHitObj = (CHitObj *)pvHitObj;
  2484. CComponentObject *pObj = (CComponentObject *)pvObj;
  2485. return pObj->Instantiate(pHitObj);
  2486. }
  2487. /*===================================================================
  2488. CPageComponentManager::GetScopedProperty
  2489. Find property component by name.
  2490. Also does OnStartPage (adds created pDisp as CPageObject)
  2491. Parameters:
  2492. CompScope csScope Scope (could not be csUnknown)
  2493. LPWSTR pwszName Object name
  2494. CComponentObject **ppObj Object found
  2495. Returns:
  2496. HRESULT
  2497. ===================================================================*/
  2498. HRESULT CPageComponentManager::GetScopedProperty
  2499. (
  2500. CompScope csScope,
  2501. LPWSTR pwszName,
  2502. CComponentObject **ppObj
  2503. )
  2504. {
  2505. HRESULT hr;
  2506. hr = FindScopedComponentByName
  2507. (
  2508. csScope,
  2509. pwszName,
  2510. CbWStr(pwszName),
  2511. TRUE,
  2512. ppObj
  2513. );
  2514. if (FAILED(hr))
  2515. return hr;
  2516. CComponentObject *pObj = *ppObj;
  2517. if (!pObj) // not failed, but not found either
  2518. return TYPE_E_ELEMENTNOTFOUND;
  2519. // Add as page object if IDispatch * is there
  2520. // as VT_DISPATCH property
  2521. if (pObj->m_csScope != csAppln
  2522. && (pObj->m_pDisp || (pObj->m_dwGIPCookie != NULL_GIP_COOKIE))
  2523. && m_pHitObj && m_pHitObj->FIsBrowserRequest())
  2524. {
  2525. BOOL fStarted;
  2526. hr = OnStartPage
  2527. (
  2528. pObj,
  2529. m_pHitObj->PScriptingContextGet(),
  2530. pObj->GetCachedOnPageInfo(),
  2531. &fStarted
  2532. );
  2533. }
  2534. return hr;
  2535. }
  2536. /*===================================================================
  2537. CPageComponentManager::FindAnyScopeComponentByIUnknown
  2538. Find component by its IUnknown *.
  2539. Parameters:
  2540. IUnknown *pUnk find by this pointer
  2541. CComponentObject **ppObj found object
  2542. Returns:
  2543. HRESULT
  2544. (S_FALSE if no error - not found)
  2545. ===================================================================*/
  2546. HRESULT CPageComponentManager::FindAnyScopeComponentByIUnknown
  2547. (
  2548. IUnknown *pUnk,
  2549. CComponentObject **ppObj
  2550. )
  2551. {
  2552. int cTry = 0;
  2553. *ppObj = NULL;
  2554. while (*ppObj == NULL && cTry < 3)
  2555. {
  2556. HRESULT hr = S_OK;
  2557. CComponentCollection *pCollection = NULL;
  2558. switch (++cTry)
  2559. {
  2560. case 1: // page first
  2561. hr = GetPageCollection(&pCollection);
  2562. break;
  2563. case 2: // session
  2564. hr = GetSessionCollection(&pCollection);
  2565. break;
  2566. case 3: // application
  2567. hr = GetApplnCollection(&pCollection);
  2568. break;
  2569. }
  2570. if (FAILED(hr) || !pCollection)
  2571. continue; // couldn't get the collection
  2572. // find the object
  2573. hr = pCollection->FindComponentByIUnknownPtr(pUnk, ppObj);
  2574. if (hr != S_OK)
  2575. *ppObj = NULL;
  2576. }
  2577. return (*ppObj ? S_OK : S_FALSE);
  2578. }
  2579. /*===================================================================
  2580. CPageComponentManager::FindAnyScopeComponentByIDispatch
  2581. Find component by its IDispatch *.
  2582. Uses FindAnyScopeComponentByIUnknown.
  2583. Parameters:
  2584. IDispatch *pDisp find by this pointer
  2585. CComponentObject **ppObj found object
  2586. Returns:
  2587. HRESULT
  2588. (S_FALSE if no error - not found)
  2589. ===================================================================*/
  2590. HRESULT CPageComponentManager::FindAnyScopeComponentByIDispatch
  2591. (
  2592. IDispatch *pDisp,
  2593. CComponentObject **ppObj
  2594. )
  2595. {
  2596. IUnknown *pUnk = NULL;
  2597. HRESULT hr = pDisp->QueryInterface(IID_IUnknown, (void **)&pUnk);
  2598. if (SUCCEEDED(hr) && !pUnk)
  2599. hr = E_FAIL;
  2600. if (FAILED(hr))
  2601. {
  2602. *ppObj = NULL;
  2603. return hr;
  2604. }
  2605. return FindAnyScopeComponentByIUnknown(pUnk, ppObj);
  2606. }
  2607. /*===================================================================
  2608. CPageComponentManager::FindComponentWithoutContext
  2609. The same as FindAnyScopeComponentByIDispatch -
  2610. but static - gets context from Viper
  2611. Uses FindAnyScopeComponentByIUnknown.
  2612. Parameters:
  2613. IDispatch *pDisp find by this pointer
  2614. CComponentObject **ppObj found object
  2615. Returns:
  2616. HRESULT
  2617. (S_FALSE if no error - not found)
  2618. ===================================================================*/
  2619. HRESULT CPageComponentManager::FindComponentWithoutContext
  2620. (
  2621. IDispatch *pDisp,
  2622. CComponentObject **ppObj
  2623. )
  2624. {
  2625. // Get HitObj from Viper Context
  2626. CHitObj *pHitObj = NULL;
  2627. ViperGetHitObjFromContext(&pHitObj);
  2628. if (!pHitObj)
  2629. return E_FAIL;
  2630. // Get page component manager
  2631. CPageComponentManager *pPCM = pHitObj->PPageComponentManager();
  2632. if (!pPCM)
  2633. return E_FAIL;
  2634. // Call the page component manager to find the object
  2635. return pPCM->FindAnyScopeComponentByIUnknown(pDisp, ppObj);
  2636. }
  2637. /*===================================================================
  2638. CPageComponentManager::RemoveComponent
  2639. Remove component -- the early release logic
  2640. Parameters:
  2641. IDispatch *pDisp find by this pointer
  2642. CComponentObject **ppObj found object
  2643. Returns:
  2644. HRESULT
  2645. ===================================================================*/
  2646. HRESULT CPageComponentManager::RemoveComponent
  2647. (
  2648. CComponentObject *pObj
  2649. )
  2650. {
  2651. Assert(pObj);
  2652. CComponentCollection *pCollection;
  2653. HRESULT hr = GetCollectionByScope(pObj->m_csScope, &pCollection);
  2654. if (FAILED(hr))
  2655. return hr;
  2656. return pCollection->RemoveComponent(pObj);
  2657. }
  2658. /*===================================================================
  2659. C C o m p o n e n t I t e r a t o r
  2660. ===================================================================*/
  2661. /*===================================================================
  2662. CComponentIterator::CComponentIterator
  2663. CComponentIterator constructor
  2664. Parameters:
  2665. CHitObj *pHitObj page to init with (optional)
  2666. Returns:
  2667. ===================================================================*/
  2668. CComponentIterator::CComponentIterator(CHitObj *pHitObj)
  2669. : m_fInited(FALSE), m_fFinished(FALSE), m_pHitObj(NULL),
  2670. m_pLastObj(NULL), m_csLastScope(csUnknown)
  2671. {
  2672. if (pHitObj)
  2673. Init(pHitObj);
  2674. }
  2675. /*===================================================================
  2676. CComponentIterator::~CComponentIterator
  2677. CComponentIterator destructor
  2678. Parameters:
  2679. Returns:
  2680. ===================================================================*/
  2681. CComponentIterator::~CComponentIterator()
  2682. {
  2683. }
  2684. /*===================================================================
  2685. CComponentIterator::Init
  2686. Start iterating
  2687. Parameters:
  2688. CHitObj *pHitObj page
  2689. Returns:
  2690. HRESULT
  2691. ===================================================================*/
  2692. HRESULT CComponentIterator::Init
  2693. (
  2694. CHitObj *pHitObj
  2695. )
  2696. {
  2697. Assert(pHitObj);
  2698. pHitObj->AssertValid();
  2699. m_pHitObj = pHitObj;
  2700. m_fInited = TRUE;
  2701. m_fFinished = FALSE;
  2702. m_pLastObj = NULL;
  2703. m_csLastScope = csUnknown;
  2704. return S_OK;
  2705. }
  2706. /*===================================================================
  2707. CComponentIterator::WStrNextComponentName
  2708. The iteration function
  2709. Parameters:
  2710. Returns:
  2711. Next component name or NULL if done
  2712. ===================================================================*/
  2713. LPWSTR CComponentIterator::WStrNextComponentName()
  2714. {
  2715. Assert(m_fInited);
  2716. if (m_fFinished)
  2717. return NULL;
  2718. Assert(m_pHitObj);
  2719. CompScope csScope = m_csLastScope;
  2720. CComponentObject *pObj = m_pLastObj ?
  2721. static_cast<CComponentObject *>(m_pLastObj->m_pNext) : NULL;
  2722. while (!m_fFinished)
  2723. {
  2724. // try the current scope
  2725. if (pObj)
  2726. {
  2727. Assert(pObj->m_ctType == ctTagged);
  2728. Assert(pObj->GetName());
  2729. m_pLastObj = pObj;
  2730. m_csLastScope = csScope;
  2731. return pObj->GetName();
  2732. }
  2733. // couldn't find in the current scope - try next scope
  2734. CComponentCollection *pCol = NULL;
  2735. switch (csScope)
  2736. {
  2737. case csUnknown:
  2738. csScope = csPage;
  2739. m_pHitObj->GetPageComponentCollection(&pCol);
  2740. break;
  2741. case csPage:
  2742. csScope = csSession;
  2743. m_pHitObj->GetSessionComponentCollection(&pCol);
  2744. break;
  2745. case csSession:
  2746. csScope = csAppln;
  2747. m_pHitObj->GetApplnComponentCollection(&pCol);
  2748. break;
  2749. case csAppln:
  2750. default:
  2751. csScope = csUnknown;
  2752. m_fFinished = TRUE;
  2753. break;
  2754. }
  2755. // start at the beginning of the new collection
  2756. if (pCol)
  2757. pObj = static_cast<CComponentObject *>(pCol->m_htTaggedObjects.Head());
  2758. }
  2759. // finished
  2760. return NULL;
  2761. }
  2762. /*===================================================================
  2763. C V a r i a n t s I t e r a t o r
  2764. ===================================================================*/
  2765. /*===================================================================
  2766. CVariantsIterator::CVariantsIterator
  2767. CVariantsIterator constructor by application
  2768. Parameters:
  2769. CAppln *pAppln collection to init with
  2770. DWORD ctCollType type of components to list iteration
  2771. Returns:
  2772. ===================================================================*/
  2773. CVariantsIterator::CVariantsIterator
  2774. (
  2775. CAppln *pAppln,
  2776. DWORD ctColType
  2777. )
  2778. : m_pCompColl(NULL), m_pAppln(NULL), m_pSession(NULL)
  2779. {
  2780. Assert(pAppln);
  2781. pAppln->AddRef();
  2782. m_cRefs = 1;
  2783. m_pCompColl = pAppln->PCompCol();
  2784. m_pAppln = pAppln;
  2785. m_ctColType = ctColType;
  2786. m_dwIndex = 0;
  2787. }
  2788. /*===================================================================
  2789. CVariantsIterator::CVariantsIterator
  2790. CVariantsIterator constructor by session
  2791. Parameters:
  2792. CSession *pSession collection to init with
  2793. DWORD ctCollType type of components to list iteration
  2794. Returns:
  2795. ===================================================================*/
  2796. CVariantsIterator::CVariantsIterator
  2797. (
  2798. CSession *pSession,
  2799. DWORD ctColType
  2800. )
  2801. : m_pCompColl(NULL), m_pAppln(NULL), m_pSession(NULL)
  2802. {
  2803. Assert(pSession);
  2804. pSession->AddRef();
  2805. m_cRefs = 1;
  2806. m_pCompColl = pSession->PCompCol();
  2807. m_ctColType = ctColType;
  2808. m_pSession = pSession;
  2809. m_dwIndex = 0;
  2810. }
  2811. /*===================================================================
  2812. CVariantsIterator::~CVariantsIterator
  2813. CVariantsIterator destructor
  2814. Parameters:
  2815. Returns:
  2816. ===================================================================*/
  2817. CVariantsIterator::~CVariantsIterator()
  2818. {
  2819. if (m_pSession)
  2820. m_pSession->Release();
  2821. if (m_pAppln)
  2822. m_pAppln->Release();
  2823. }
  2824. /*===================================================================
  2825. CVariantsIterator::QueryInterface
  2826. CVariantsIterator QI
  2827. Parameters:
  2828. GUID& iid
  2829. VOID ** ppvObj
  2830. Returns: HRESULT
  2831. ===================================================================*/
  2832. STDMETHODIMP CVariantsIterator::QueryInterface
  2833. (
  2834. const GUID &iid,
  2835. void **ppvObj
  2836. )
  2837. {
  2838. if (iid == IID_IUnknown || iid == IID_IEnumVARIANT)
  2839. {
  2840. AddRef();
  2841. *ppvObj = this;
  2842. return S_OK;
  2843. }
  2844. *ppvObj = NULL;
  2845. return E_NOINTERFACE;
  2846. }
  2847. /*===================================================================
  2848. CVariantsIterator::AddRef
  2849. CVariantsIterator AddRef
  2850. Parameters:
  2851. Returns: ULONG
  2852. ===================================================================*/
  2853. STDMETHODIMP_(ULONG) CVariantsIterator::AddRef()
  2854. {
  2855. return ++m_cRefs;
  2856. }
  2857. /*===================================================================
  2858. CVariantsIterator::Release
  2859. CVariantsIterator Release
  2860. Parameters:
  2861. Returns:
  2862. ===================================================================*/
  2863. STDMETHODIMP_(ULONG) CVariantsIterator::Release()
  2864. {
  2865. if (--m_cRefs > 0)
  2866. return m_cRefs;
  2867. delete this;
  2868. return 0;
  2869. }
  2870. /*===================================================================
  2871. CVariantsIterator::Clone
  2872. CVariantsIterator Clone
  2873. Parameters:
  2874. Returns:
  2875. ===================================================================*/
  2876. STDMETHODIMP CVariantsIterator::Clone
  2877. (
  2878. IEnumVARIANT **ppEnumReturn
  2879. )
  2880. {
  2881. CVariantsIterator *pNewIterator = NULL;
  2882. if (m_pSession)
  2883. {
  2884. pNewIterator = new CVariantsIterator(m_pSession, m_ctColType);
  2885. }
  2886. else if (m_pAppln)
  2887. {
  2888. pNewIterator = new CVariantsIterator(m_pAppln, m_ctColType);
  2889. }
  2890. else
  2891. {
  2892. Assert(FALSE); // better be either Appln or Session
  2893. return E_FAIL;
  2894. }
  2895. if (pNewIterator == NULL)
  2896. return E_OUTOFMEMORY;
  2897. // new iterator should point to same location as this.
  2898. pNewIterator->m_dwIndex = m_dwIndex;
  2899. *ppEnumReturn = pNewIterator;
  2900. return S_OK;
  2901. }
  2902. /*===================================================================
  2903. CVariantsIterator::Next
  2904. CVariantsIterator Next
  2905. Parameters:
  2906. Returns:
  2907. ===================================================================*/
  2908. STDMETHODIMP CVariantsIterator::Next
  2909. (
  2910. unsigned long cElementsRequested,
  2911. VARIANT *rgVariant,
  2912. unsigned long *pcElementsFetched
  2913. )
  2914. {
  2915. // give a valid pointer value to 'pcElementsFetched'
  2916. unsigned long cElementsFetched;
  2917. if (pcElementsFetched == NULL)
  2918. pcElementsFetched = &cElementsFetched;
  2919. if (cElementsRequested == 0)
  2920. {
  2921. if (pcElementsFetched)
  2922. *pcElementsFetched = 0;
  2923. return S_OK;
  2924. }
  2925. DWORD cMax = 0;
  2926. if (m_ctColType == ctTagged)
  2927. {
  2928. cMax = m_pCompColl ? m_pCompColl->m_cAllTagged : 0;
  2929. }
  2930. else if (m_ctColType == ctProperty)
  2931. {
  2932. cMax = m_pCompColl ? m_pCompColl->m_cProperties : 0;
  2933. }
  2934. else
  2935. {
  2936. // Should always be either tagged object or property
  2937. Assert(FALSE);
  2938. return E_FAIL;
  2939. }
  2940. // Loop through the collection until either we reach the end or
  2941. // cElements becomes zero
  2942. //
  2943. unsigned long cElements = cElementsRequested;
  2944. *pcElementsFetched = 0;
  2945. while (cElements > 0 && m_dwIndex < cMax)
  2946. {
  2947. LPWSTR pwszName = NULL;
  2948. if (m_pAppln)
  2949. m_pAppln->Lock();
  2950. m_pCompColl->GetNameByIndex(m_ctColType, ++m_dwIndex, &pwszName);
  2951. if (!pwszName) {
  2952. if (m_pAppln)
  2953. m_pAppln->UnLock();
  2954. continue;
  2955. }
  2956. BSTR bstrT = SysAllocString(pwszName);
  2957. if (m_pAppln)
  2958. m_pAppln->UnLock();
  2959. if (!bstrT)
  2960. return E_OUTOFMEMORY;
  2961. V_VT(rgVariant) = VT_BSTR;
  2962. V_BSTR(rgVariant) = bstrT;
  2963. ++rgVariant;
  2964. --cElements;
  2965. ++(*pcElementsFetched);
  2966. }
  2967. // initialize the remaining variants
  2968. while (cElements-- > 0)
  2969. VariantInit(rgVariant++);
  2970. return (*pcElementsFetched == cElementsRequested)? S_OK : S_FALSE;
  2971. }
  2972. /*===================================================================
  2973. CVariantsIterator::Skip
  2974. CVariantsIterator Skip
  2975. Parameters:
  2976. Returns:
  2977. ===================================================================*/
  2978. STDMETHODIMP CVariantsIterator::Skip
  2979. (
  2980. unsigned long cElements
  2981. )
  2982. {
  2983. /* Adjust the index by cElements or
  2984. * until we hit the max element
  2985. */
  2986. DWORD cMax = 0;
  2987. // We iterate over different arrays depending on the collection type
  2988. if (m_ctColType == ctTagged)
  2989. {
  2990. cMax = m_pCompColl ? m_pCompColl->m_cAllTagged : 0;
  2991. }
  2992. else if (m_ctColType == ctProperty)
  2993. {
  2994. cMax = m_pCompColl ? m_pCompColl->m_cProperties : 0;
  2995. }
  2996. else
  2997. {
  2998. // Should always be either tagged object or property
  2999. Assert(FALSE);
  3000. return E_FAIL;
  3001. }
  3002. m_dwIndex += cElements;
  3003. return (m_dwIndex < cMax)? S_OK : S_FALSE;
  3004. }
  3005. /*===================================================================
  3006. CVariantsIterator::Reset
  3007. CVariantsIterator Reset
  3008. Parameters:
  3009. Returns:
  3010. ===================================================================*/
  3011. STDMETHODIMP CVariantsIterator::Reset()
  3012. {
  3013. m_dwIndex = 0;
  3014. return NO_ERROR;
  3015. }