Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3690 lines
87 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. {
  387. }
  388. #ifdef DBG
  389. /*===================================================================
  390. CComponentObject::AssertValid
  391. Test to make sure that this is currently correctly formed
  392. and assert if it is not.
  393. Returns:
  394. ===================================================================*/
  395. void CComponentObject::AssertValid() const
  396. {
  397. Assert(m_ctType != ctUnknown);
  398. }
  399. #endif
  400. /*===================================================================
  401. CComponentObject::~CComponentObject
  402. CComponentObject destructor
  403. Releases interface pointers
  404. Parameters:
  405. Returns:
  406. ===================================================================*/
  407. CComponentObject::~CComponentObject()
  408. {
  409. // Release all interface pointers
  410. Clear();
  411. // Name used in hash (from CLinkElem)
  412. if (m_fNameAllocated)
  413. {
  414. Assert(m_pKey);
  415. free(m_pKey);
  416. }
  417. }
  418. /*===================================================================
  419. CComponentObject::Init
  420. Initialize CLinkElem portion with the object name
  421. Needed to implement string hash
  422. Parameters:
  423. LPWSTR pwszName object name
  424. DWORD cbName name length in bytes
  425. Returns:
  426. HRESULT
  427. ===================================================================*/
  428. HRESULT CComponentObject::Init
  429. (
  430. LPWSTR pwszName,
  431. DWORD cbName
  432. )
  433. {
  434. Assert(pwszName);
  435. Assert(*pwszName != L'\0');
  436. Assert(cbName == (wcslen(pwszName) * sizeof(WCHAR)));
  437. // required buffer length
  438. DWORD cbBuffer = cbName + sizeof(WCHAR);
  439. WCHAR *pwszNameBuffer = (WCHAR *)m_rgbNameBuffer;
  440. if (cbBuffer > sizeof(m_rgbNameBuffer))
  441. {
  442. // the name doesn't fit into the member buffer -> allocate
  443. pwszNameBuffer = (WCHAR *)malloc(cbBuffer);
  444. if (!pwszNameBuffer)
  445. return E_OUTOFMEMORY;
  446. m_fNameAllocated = TRUE;
  447. }
  448. memcpy(pwszNameBuffer, pwszName, cbBuffer);
  449. // init link with name as the key (length excludes null term)
  450. return CLinkElem::Init(pwszNameBuffer, cbName);
  451. }
  452. /*===================================================================
  453. CComponentObject::ReleaseAll
  454. Releases all interface pointers
  455. Parameters:
  456. Returns:
  457. HRESULT
  458. ===================================================================*/
  459. HRESULT CComponentObject::ReleaseAll()
  460. {
  461. // Release all other present interface pointers
  462. if (m_pDisp)
  463. {
  464. m_pDisp->Release();
  465. m_pDisp = NULL;
  466. }
  467. if (m_pUnknown)
  468. {
  469. m_pUnknown->Release();
  470. m_pUnknown = NULL;
  471. }
  472. // Variant
  473. if (m_fVariant)
  474. {
  475. VariantClear(&m_Variant);
  476. m_fVariant = FALSE;
  477. }
  478. if (m_dwGIPCookie != NULL_GIP_COOKIE)
  479. {
  480. g_GIPAPI.Revoke(m_dwGIPCookie);
  481. m_dwGIPCookie = NULL_GIP_COOKIE;
  482. }
  483. return S_OK;
  484. }
  485. /*===================================================================
  486. CComponentObject::Clear
  487. Clears out data leaving link alone
  488. Parameters:
  489. Returns:
  490. HRESULT
  491. ===================================================================*/
  492. HRESULT CComponentObject::Clear()
  493. {
  494. // Release all pointers
  495. TRY
  496. ReleaseAll();
  497. CATCH(nExcept)
  498. Assert(FALSE);
  499. m_pDisp = NULL;
  500. m_pUnknown = NULL;
  501. m_fVariant = FALSE;
  502. m_dwGIPCookie = NULL_GIP_COOKIE;
  503. END_TRY
  504. // Invalidate cached OnPageInfo
  505. m_fOnPageInfoCached = FALSE;
  506. m_fOnPageStarted = FALSE;
  507. // Mark it as unknown
  508. m_csScope = csUnknown;
  509. m_ctType = ctUnknown;
  510. m_cmModel = cmUnknown;
  511. m_fAgile = FALSE;
  512. return S_OK;
  513. }
  514. /*===================================================================
  515. CComponentObject::Instantiate
  516. Create object instance if it's not there already
  517. Calls TryInstantiate() from within TRY CATCH
  518. Parameters:
  519. CHitObj *pHitObj Hit object for error reporting
  520. Returns:
  521. HRESULT
  522. ===================================================================*/
  523. HRESULT CComponentObject::Instantiate
  524. (
  525. CHitObj *pHitObj
  526. )
  527. {
  528. HRESULT hr = S_OK;
  529. if (Glob(fExceptionCatchEnable))
  530. {
  531. TRY
  532. hr = TryInstantiate(pHitObj);
  533. CATCH(nExcept)
  534. HandleErrorMissingFilename(IDE_SCRIPT_OBJ_INSTANTIATE_FAILED,
  535. pHitObj,
  536. TRUE,
  537. GetName(),
  538. nExcept);
  539. hr = nExcept;
  540. END_TRY
  541. }
  542. else
  543. {
  544. hr = TryInstantiate(pHitObj);
  545. }
  546. if (FAILED(hr))
  547. {
  548. // Something failed -- need to clean-up
  549. ReleaseAll();
  550. // mark as "failed to instantiate"
  551. m_fFailedToInstantiate = TRUE;
  552. }
  553. return hr;
  554. }
  555. /*===================================================================
  556. CComponentObject::TryInstantiate
  557. Create object instance if it's not there already
  558. Called by Instantiate() from within TRY CATCH
  559. Parameters:
  560. CHitObj *pHitObj Hit object for error reporting
  561. Returns:
  562. HRESULT
  563. ===================================================================*/
  564. HRESULT CComponentObject::TryInstantiate
  565. (
  566. CHitObj *pHitObj
  567. )
  568. {
  569. // Check if the object already exist
  570. if (m_pUnknown)
  571. return S_OK;
  572. if (m_fFailedToInstantiate)
  573. return E_FAIL; // already tried once
  574. if (m_cmModel == cmUnknown && m_ClsId != CLSID_NULL)
  575. {
  576. CompModel cmModel; // needed because m_cmModel is a bit fld
  577. HRESULT hr = CompModelFromCLSID(m_ClsId, &cmModel);
  578. if (FAILED(hr))
  579. return hr;
  580. m_cmModel = cmModel;
  581. }
  582. HRESULT hr = ViperCreateInstance
  583. (
  584. m_ClsId,
  585. IID_IUnknown,
  586. (void **)&m_pUnknown
  587. );
  588. // If we failed because we incorrectly cached the clsid
  589. // (could happen for tagged objects) try to get updated
  590. // cls id and retry
  591. if (m_ctType == ctTagged && FAILED(hr))
  592. {
  593. if (g_TypelibCache.UpdateMappedCLSID(&m_ClsId) == S_OK)
  594. {
  595. hr = ViperCreateInstance
  596. (
  597. m_ClsId,
  598. IID_IUnknown,
  599. (void **)&m_pUnknown
  600. );
  601. }
  602. }
  603. if (SUCCEEDED(hr))
  604. {
  605. if (Glob(fTrackThreadingModel) && m_cmModel == cmBoth)
  606. m_fAgile = TRUE;
  607. else
  608. m_fAgile = ViperCoObjectAggregatesFTM(m_pUnknown);
  609. hr = m_pUnknown->QueryInterface
  610. (
  611. IID_IDispatch,
  612. (void **)&m_pDisp
  613. );
  614. }
  615. // Check if application level object that
  616. // restricts threading -> use Global Interface Cookie
  617. if (SUCCEEDED(hr)
  618. && (m_csScope == csAppln || m_csScope == csSession)
  619. && !m_fAgile)
  620. {
  621. return ConvertToGIPCookie();
  622. }
  623. if (SUCCEEDED(hr) && !m_fOnPageInfoCached)
  624. {
  625. // don't really care if the following fails
  626. GetOnPageInfo();
  627. }
  628. return hr;
  629. }
  630. /*===================================================================
  631. CComponentObject::SetPropertyValue
  632. Sets value from a Variant
  633. Checks agility and possible deadlocks
  634. Does GIP conversion
  635. Parameters:
  636. VARIANT *pVariant [in] Value to set
  637. Returns:
  638. HRESULT
  639. ===================================================================*/
  640. HRESULT CComponentObject::SetPropertyValue
  641. (
  642. VARIANT *pVariant
  643. )
  644. {
  645. Assert(m_ctType == ctProperty);
  646. HRESULT hr = S_OK;
  647. // Copy the variant value
  648. VariantInit(&m_Variant);
  649. m_fVariant = TRUE;
  650. hr = VariantCopyInd(&m_Variant, pVariant);
  651. if (FAILED(hr))
  652. return hr;
  653. // Get IDispatch pointer
  654. if (V_VT(&m_Variant) == VT_DISPATCH)
  655. {
  656. m_pDisp = V_DISPATCH(&m_Variant);
  657. }
  658. else
  659. {
  660. m_pDisp = NULL;
  661. }
  662. if (!m_pDisp)
  663. {
  664. m_fAgile = TRUE; // not VT_DISPATCH VARIANTs are agile
  665. return S_OK;
  666. }
  667. m_pDisp->AddRef();
  668. // Query (and cache) OnPageInfo inside TRY CATCH
  669. if (Glob(fExceptionCatchEnable))
  670. {
  671. TRY
  672. hr = GetOnPageInfo();
  673. CATCH(nExcept)
  674. hr = E_UNEXPECTED;
  675. END_TRY
  676. }
  677. else
  678. {
  679. hr = GetOnPageInfo();
  680. }
  681. // Don't really care if failed
  682. hr = S_OK;
  683. // Check if the assigned object is agile
  684. m_fAgile = ViperCoObjectAggregatesFTM(m_pDisp);
  685. if (Glob(fTrackThreadingModel) && !m_fAgile)
  686. {
  687. // doesn't mean it really isn't. could be one of
  688. // our objects marked as 'both'
  689. CComponentObject *pObjCopyOf = NULL;
  690. hr = CPageComponentManager::FindComponentWithoutContext
  691. (
  692. m_pDisp,
  693. &pObjCopyOf
  694. );
  695. if (hr == S_OK)
  696. {
  697. m_fAgile = pObjCopyOf->FAgile();
  698. }
  699. // end of getting of agile flag from the original object
  700. hr = S_OK; // even if object was not found
  701. }
  702. // Decide whether to use GIP and if invalid assignment
  703. // Applies only to non-agile application objects
  704. if (!m_fAgile && (m_csScope == csAppln || m_csScope == csSession))
  705. {
  706. if (!ViperCoObjectIsaProxy(m_pDisp) && (m_csScope == csAppln)) // deadlocking?
  707. {
  708. m_pDisp->Release();
  709. m_pDisp = NULL;
  710. VariantClear(&m_Variant);
  711. hr = RPC_E_WRONG_THREAD; // to tell the caller the error
  712. }
  713. else
  714. {
  715. // use GIP
  716. hr = ConvertToGIPCookie();
  717. }
  718. }
  719. return hr;
  720. }
  721. /*===================================================================
  722. CComponentObject::ConvertToGIPCookie
  723. Convert Object to be GIP cookie. Release all pointers
  724. Parameters:
  725. Returns:
  726. HRESULT
  727. ===================================================================*/
  728. HRESULT CComponentObject::ConvertToGIPCookie()
  729. {
  730. Assert(m_pDisp); // has to have dispatch pointer
  731. if (!FIsWinNT())
  732. {
  733. // No GIPs on Win95
  734. // On Win95 everything is on the same thread
  735. // -> it is ok for the objects stay as pointers
  736. return S_OK;
  737. }
  738. DWORD dwCookie = NULL_GIP_COOKIE;
  739. HRESULT hr = g_GIPAPI.Register(m_pDisp, IID_IDispatch, &dwCookie);
  740. if (SUCCEEDED(hr))
  741. {
  742. Assert(dwCookie != NULL_GIP_COOKIE);
  743. // Release all pointeres
  744. ReleaseAll();
  745. // Store the cookie instead
  746. m_dwGIPCookie = dwCookie;
  747. }
  748. return hr;
  749. }
  750. /*===================================================================
  751. CComponentObject::GetOnPageInfo
  752. Query dispatch ids for OnStartPage and OnEndPage
  753. Calls static QueryOnPageInfo
  754. Parameters:
  755. Returns:
  756. HRESULT
  757. ===================================================================*/
  758. HRESULT CComponentObject::GetOnPageInfo()
  759. {
  760. Assert(m_pDisp);
  761. HRESULT hr = QueryOnPageInfo(m_pDisp, &m_OnPageInfo);
  762. if (SUCCEEDED(hr))
  763. m_fOnPageInfoCached = TRUE;
  764. return hr;
  765. }
  766. /*===================================================================
  767. CComponentObject::GetAddRefdIDispatch
  768. Get AddRef()'d Dispatch *
  769. Handles the Global Interface Ole Cookies
  770. Parameters:
  771. Dispatch **ppdisp output
  772. Returns:
  773. HRESULT
  774. ===================================================================*/
  775. HRESULT CComponentObject::GetAddRefdIDispatch
  776. (
  777. IDispatch **ppdisp
  778. )
  779. {
  780. Assert(ppdisp);
  781. if (m_pDisp)
  782. {
  783. *ppdisp = m_pDisp;
  784. (*ppdisp)->AddRef();
  785. return S_OK;
  786. }
  787. // try to restore from cookie
  788. if (m_dwGIPCookie != NULL_GIP_COOKIE)
  789. {
  790. // Even if IUnknown * needs to be returned,
  791. // Ask for IDispatch *, because IDispatch * is the one
  792. // that was put in by CoGetInterfaceFromGlobal()
  793. HRESULT hr = g_GIPAPI.Get
  794. (
  795. m_dwGIPCookie,
  796. IID_IDispatch,
  797. (void **)ppdisp
  798. );
  799. if (SUCCEEDED(hr))
  800. return S_OK;
  801. }
  802. *ppdisp = NULL;
  803. return E_NOINTERFACE;
  804. }
  805. /*===================================================================
  806. CComponentObject::GetAddRefdIUnknown
  807. Get AddRef()'d IUnknown *
  808. Handles the Global Interface Ole Cookies
  809. Parameters:
  810. IUnknown **ppunk output
  811. Returns:
  812. HRESULT
  813. ===================================================================*/
  814. HRESULT CComponentObject::GetAddRefdIUnknown
  815. (
  816. IUnknown **ppunk
  817. )
  818. {
  819. Assert(ppunk);
  820. if (m_pUnknown)
  821. {
  822. *ppunk = m_pUnknown;
  823. (*ppunk)->AddRef();
  824. return S_OK;
  825. }
  826. // Use IDispatch (from cookie)
  827. IDispatch *pDisp = NULL;
  828. if (SUCCEEDED(GetAddRefdIDispatch(&pDisp)))
  829. {
  830. *ppunk = pDisp; // IDispatch implements IUnknown
  831. return S_OK;
  832. }
  833. *ppunk = NULL;
  834. return E_NOINTERFACE;
  835. }
  836. /*===================================================================
  837. CComponentObject::GetVariant
  838. Get object's values as variant
  839. Handles the Global Interface Ole Cookies
  840. Parameters:
  841. VARIANT *pVar [out] Variant filled in with object value
  842. Returns:
  843. HRESULT
  844. ===================================================================*/
  845. HRESULT CComponentObject::GetVariant
  846. (
  847. VARIANT *pVar
  848. )
  849. {
  850. HRESULT hr = S_OK;
  851. VariantInit(pVar); // default variant empty
  852. if (m_fVariant)
  853. {
  854. // already has variant
  855. hr = VariantCopyInd(pVar, &m_Variant);
  856. }
  857. else if (m_pDisp)
  858. {
  859. // create variant from IDispatch*
  860. m_pDisp->AddRef();
  861. V_VT(pVar) = VT_DISPATCH;
  862. V_DISPATCH(pVar) = m_pDisp;
  863. }
  864. else if (m_dwGIPCookie != NULL_GIP_COOKIE)
  865. {
  866. // create variant from cookie
  867. IDispatch *pDisp = NULL;
  868. hr = g_GIPAPI.Get(m_dwGIPCookie, IID_IDispatch, (void **)&pDisp);
  869. if (SUCCEEDED(hr))
  870. {
  871. V_VT(pVar) = VT_DISPATCH;
  872. V_DISPATCH(pVar) = pDisp;
  873. }
  874. }
  875. else
  876. {
  877. // nowhere to get the VARIANT value from
  878. hr = E_POINTER;
  879. }
  880. return hr;
  881. }
  882. /*===================================================================
  883. C P a g e O b j e c t
  884. ===================================================================*/
  885. /*===================================================================
  886. CPageObject::CPageObject
  887. CPageObject constructor
  888. Parameters:
  889. Returns:
  890. ===================================================================*/
  891. CPageObject::CPageObject()
  892. : m_pDisp(NULL),
  893. m_fStartPageCalled(FALSE), m_fEndPageCalled(FALSE)
  894. {
  895. }
  896. #ifdef DBG
  897. /*===================================================================
  898. CPageObject::AssertValid
  899. Test to make sure that this is currently correctly formed
  900. and assert if it is not.
  901. Returns:
  902. ===================================================================*/
  903. void CPageObject::AssertValid() const
  904. {
  905. Assert(m_pDisp);
  906. }
  907. #endif
  908. /*===================================================================
  909. CPageObject::~CPageObject
  910. CPageObject destructor
  911. Parameters:
  912. Returns:
  913. ===================================================================*/
  914. CPageObject::~CPageObject()
  915. {
  916. // Release interface pointer
  917. if (m_pDisp)
  918. {
  919. m_pDisp->Release();
  920. m_pDisp = NULL;
  921. }
  922. }
  923. /*===================================================================
  924. CPageObject::Init
  925. Initialize CLinkElem portion with the IDispatch pointer
  926. Needed to implement string hash
  927. Parameters:
  928. IDispatch *pDisp dispatch pointer (AddRef()ed)
  929. COnPageInfo *pOnPageInfo OnStartPage, OnEndPage Ids
  930. Returns:
  931. HRESULT
  932. ===================================================================*/
  933. HRESULT CPageObject::Init
  934. (
  935. IDispatch *pDisp,
  936. const COnPageInfo &OnPageInfo
  937. )
  938. {
  939. Assert(pDisp);
  940. m_pDisp = pDisp;
  941. m_OnPageInfo = OnPageInfo;
  942. m_fStartPageCalled = FALSE;
  943. m_fEndPageCalled = FALSE;
  944. return S_OK;
  945. }
  946. /*===================================================================
  947. CPageObject::InvokeMethod
  948. Invokes OnPageStart() or OnPageEnd()
  949. Parameters:
  950. DWORD iMethod which method
  951. CScriptingContext *pContext scripting context (for OnStart)
  952. CHitObj *pHitObj HitObj for errors
  953. Returns:
  954. HRESULT
  955. ===================================================================*/
  956. HRESULT CPageObject::InvokeMethod
  957. (
  958. DWORD iMethod,
  959. CScriptingContext *pContext,
  960. CHitObj *pHitObj
  961. )
  962. {
  963. BOOL fOnStart = (iMethod == ONPAGEINFO_ONSTARTPAGE);
  964. // check if method exists
  965. if (m_OnPageInfo.m_rgDispIds[iMethod] == DISPID_UNKNOWN)
  966. return S_OK;
  967. // two OnStart in a row - BAD
  968. Assert(!(fOnStart && m_fStartPageCalled));
  969. // two OnEnd in a row - BAD
  970. Assert(!(!fOnStart && m_fEndPageCalled));
  971. Assert(m_pDisp);
  972. HRESULT hr = S_OK;
  973. if (Glob(fExceptionCatchEnable))
  974. {
  975. // Call method inside TRY CATCH
  976. TRY
  977. hr = TryInvokeMethod
  978. (
  979. m_OnPageInfo.m_rgDispIds[iMethod],
  980. fOnStart,
  981. pContext,
  982. pHitObj
  983. );
  984. CATCH(nExcept)
  985. if (fOnStart)
  986. ExceptionId
  987. (
  988. IID_IObjectCover,
  989. IDE_COVER,
  990. IDE_COVER_ON_START_PAGE_GPF
  991. );
  992. else
  993. HandleErrorMissingFilename
  994. (
  995. IDE_COVER_ON_END_PAGE_GPF,
  996. pHitObj
  997. );
  998. hr = E_UNEXPECTED;
  999. END_TRY
  1000. }
  1001. else
  1002. {
  1003. // don't CATCH
  1004. hr = TryInvokeMethod
  1005. (
  1006. m_OnPageInfo.m_rgDispIds[iMethod],
  1007. fOnStart,
  1008. pContext,
  1009. pHitObj
  1010. );
  1011. }
  1012. if (fOnStart)
  1013. m_fStartPageCalled = TRUE;
  1014. else
  1015. m_fEndPageCalled = TRUE;
  1016. return hr;
  1017. }
  1018. /*===================================================================
  1019. CPageObject::TryInvokeMethod
  1020. Invokes OnPageStart() or OnPageEnd()
  1021. Parameters:
  1022. DISPID DispId method's DISPID
  1023. BOOL fOnStart TRUE if invoking OnStart
  1024. IDispatch *pDispContext scripting context (for OnStart)
  1025. CHitObj *pHitObj HitObj for errors
  1026. Returns:
  1027. HRESULT
  1028. ===================================================================*/
  1029. HRESULT CPageObject::TryInvokeMethod
  1030. (
  1031. DISPID DispId,
  1032. BOOL fOnStart,
  1033. IDispatch *pDispContext,
  1034. CHitObj *pHitObj
  1035. )
  1036. {
  1037. EXCEPINFO ExcepInfo;
  1038. DISPPARAMS DispParams;
  1039. VARIANT varResult;
  1040. VARIANT varParam;
  1041. UINT nArgErr;
  1042. memset(&DispParams, 0, sizeof(DISPPARAMS));
  1043. memset(&ExcepInfo, 0, sizeof(EXCEPINFO));
  1044. if (fOnStart)
  1045. {
  1046. VariantInit(&varParam);
  1047. V_VT(&varParam) = VT_DISPATCH;
  1048. V_DISPATCH(&varParam) = pDispContext;
  1049. DispParams.rgvarg = &varParam;
  1050. DispParams.cArgs = 1;
  1051. }
  1052. VariantInit(&varResult);
  1053. // Invoke it
  1054. HRESULT hr = m_pDisp->Invoke
  1055. (
  1056. DispId, // Call method
  1057. IID_NULL, // REFIID - Reserved, must be NULL
  1058. NULL, // Locale id
  1059. DISPATCH_METHOD, // Calling a method, not a property
  1060. &DispParams, // pass arguments
  1061. &varResult, // return value
  1062. &ExcepInfo, // exeption info on failure
  1063. &nArgErr
  1064. );
  1065. // Ignore errors indicating that this method doesnt exist.
  1066. if (FAILED(hr))
  1067. {
  1068. if (hr == E_NOINTERFACE ||
  1069. hr == DISP_E_MEMBERNOTFOUND ||
  1070. hr == DISP_E_UNKNOWNNAME)
  1071. {
  1072. // the above errors really aren't
  1073. hr = S_OK;
  1074. }
  1075. }
  1076. /*
  1077. * NOTE: The OnStartPage method is always called while the
  1078. * script is running, so we use ExceptionId and let the
  1079. * scripting engine report the error. OnEndPage is always
  1080. * called after the engine is gone, so we use HandleError.
  1081. */
  1082. if (FAILED(hr))
  1083. {
  1084. if (ExcepInfo.bstrSource && ExcepInfo.bstrDescription)
  1085. {
  1086. // User supplied error
  1087. Exception
  1088. (
  1089. IID_IObjectCover,
  1090. ExcepInfo.bstrSource,
  1091. ExcepInfo.bstrDescription
  1092. );
  1093. }
  1094. else if (fOnStart)
  1095. {
  1096. // Standard on-start error
  1097. ExceptionId
  1098. (
  1099. IID_IObjectCover,
  1100. IDE_COVER,
  1101. IDE_COVER_ON_START_PAGE_FAILED,
  1102. hr
  1103. );
  1104. }
  1105. else
  1106. {
  1107. // Standard on-end error
  1108. HandleErrorMissingFilename
  1109. (
  1110. IDE_COVER_ON_END_PAGE_FAILED,
  1111. pHitObj
  1112. );
  1113. }
  1114. }
  1115. return hr;
  1116. }
  1117. /*===================================================================
  1118. C C o m p o n e n t C o l l e c t i o n
  1119. ===================================================================*/
  1120. /*===================================================================
  1121. CComponentCollection::CComponentCollection
  1122. CComponentCollection constructor
  1123. Parameters:
  1124. Returns:
  1125. ===================================================================*/
  1126. CComponentCollection::CComponentCollection()
  1127. :
  1128. m_csScope(csUnknown),
  1129. m_fUseTaggedArray(FALSE), m_fUsePropArray(FALSE),
  1130. m_fHasComProperties(FALSE),
  1131. m_cAllTagged(0), m_cInstTagged(0),
  1132. m_cProperties(0), m_cUnnamed(0),
  1133. m_pCompFirst(NULL)
  1134. {
  1135. }
  1136. #ifdef DBG
  1137. /*===================================================================
  1138. CComponentCollection::AssertValid
  1139. Test to make sure that this is currently correctly formed
  1140. and assert if it is not.
  1141. Returns:
  1142. ===================================================================*/
  1143. void CComponentCollection::AssertValid() const
  1144. {
  1145. Assert(m_csScope != csUnknown);
  1146. m_htTaggedObjects.AssertValid();
  1147. m_htTaggedObjects.AssertValid();
  1148. m_htidIUnknownPtrs.AssertValid();
  1149. }
  1150. #endif
  1151. /*===================================================================
  1152. CComponentCollection::~CComponentCollection
  1153. CComponentCollection destructor
  1154. Deletes all the objects
  1155. Parameters:
  1156. Returns:
  1157. ===================================================================*/
  1158. CComponentCollection::~CComponentCollection()
  1159. {
  1160. UnInit();
  1161. }
  1162. /*===================================================================
  1163. CComponentCollection::Init
  1164. Sets collection scope
  1165. Initializes hash tables
  1166. Parameters:
  1167. Returns:
  1168. HRESULT
  1169. ===================================================================*/
  1170. HRESULT CComponentCollection::Init
  1171. (
  1172. CompScope scScope
  1173. )
  1174. {
  1175. HRESULT hr = S_OK;
  1176. m_csScope = scScope;
  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);
  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)
  2414. {
  2415. // For applicatin scoped objects, instantiate from MTA
  2416. hr = CallMTACallback
  2417. (
  2418. CPageComponentManager::InstantiateObjectFromMTA,
  2419. pObj,
  2420. m_pHitObj
  2421. );
  2422. }
  2423. else
  2424. {
  2425. hr = pObj->Instantiate(m_pHitObj);
  2426. }
  2427. if (SUCCEEDED(hr))
  2428. {
  2429. // keep count
  2430. pCollection->m_cInstTagged++;
  2431. // add to pointer cash
  2432. pCollection->AddComponentToPtrHash(pObj);
  2433. // return flag
  2434. *pfNewInstance = TRUE;
  2435. }
  2436. // Flag as instantiated even if failed
  2437. pObj->m_fInstantiatedTagged = TRUE;
  2438. }
  2439. // Remove the lock kept while instantiating appln level object
  2440. if (fApplnLocked)
  2441. m_pHitObj->PAppln()->UnLock();
  2442. // Return if [instantiation] failed
  2443. if (FAILED(hr))
  2444. {
  2445. *ppObj = NULL;
  2446. return hr;
  2447. }
  2448. // Add as page object when needed
  2449. if (pObj->m_csScope != csAppln
  2450. && (pObj->m_pDisp || (pObj->m_dwGIPCookie != NULL_GIP_COOKIE))
  2451. && m_pHitObj && m_pHitObj->FIsBrowserRequest())
  2452. {
  2453. BOOL fStarted;
  2454. OnStartPage // don't care if failed
  2455. (
  2456. pObj,
  2457. m_pHitObj->PScriptingContextGet(),
  2458. pObj->GetCachedOnPageInfo(),
  2459. &fStarted
  2460. );
  2461. }
  2462. return hr;
  2463. }
  2464. /*===================================================================
  2465. CPageComponentManager::InstantiateObjectFromMTA
  2466. Static callback called by CallMTACallback() to
  2467. instantiate aplication scoped objects
  2468. Parameters:
  2469. void *pvObj ComponentObject
  2470. void *pvHitObj HitObj
  2471. Returns:
  2472. HRESULT
  2473. ===================================================================*/
  2474. HRESULT __stdcall CPageComponentManager::InstantiateObjectFromMTA
  2475. (
  2476. void *pvObj,
  2477. void *pvHitObj
  2478. )
  2479. {
  2480. Assert(pvHitObj);
  2481. Assert(pvObj);
  2482. CHitObj *pHitObj = (CHitObj *)pvHitObj;
  2483. CComponentObject *pObj = (CComponentObject *)pvObj;
  2484. return pObj->Instantiate(pHitObj);
  2485. }
  2486. /*===================================================================
  2487. CPageComponentManager::GetScopedProperty
  2488. Find property component by name.
  2489. Also does OnStartPage (adds created pDisp as CPageObject)
  2490. Parameters:
  2491. CompScope csScope Scope (could not be csUnknown)
  2492. LPWSTR pwszName Object name
  2493. CComponentObject **ppObj Object found
  2494. Returns:
  2495. HRESULT
  2496. ===================================================================*/
  2497. HRESULT CPageComponentManager::GetScopedProperty
  2498. (
  2499. CompScope csScope,
  2500. LPWSTR pwszName,
  2501. CComponentObject **ppObj
  2502. )
  2503. {
  2504. HRESULT hr;
  2505. hr = FindScopedComponentByName
  2506. (
  2507. csScope,
  2508. pwszName,
  2509. CbWStr(pwszName),
  2510. TRUE,
  2511. ppObj
  2512. );
  2513. if (FAILED(hr))
  2514. return hr;
  2515. CComponentObject *pObj = *ppObj;
  2516. if (!pObj) // not failed, but not found either
  2517. return TYPE_E_ELEMENTNOTFOUND;
  2518. // Add as page object if IDispatch * is there
  2519. // as VT_DISPATCH property
  2520. if (pObj->m_csScope != csAppln
  2521. && (pObj->m_pDisp || (pObj->m_dwGIPCookie != NULL_GIP_COOKIE))
  2522. && m_pHitObj && m_pHitObj->FIsBrowserRequest())
  2523. {
  2524. BOOL fStarted;
  2525. hr = OnStartPage
  2526. (
  2527. pObj,
  2528. m_pHitObj->PScriptingContextGet(),
  2529. pObj->GetCachedOnPageInfo(),
  2530. &fStarted
  2531. );
  2532. }
  2533. return hr;
  2534. }
  2535. /*===================================================================
  2536. CPageComponentManager::FindAnyScopeComponentByIUnknown
  2537. Find component by its IUnknown *.
  2538. Parameters:
  2539. IUnknown *pUnk find by this pointer
  2540. CComponentObject **ppObj found object
  2541. Returns:
  2542. HRESULT
  2543. (S_FALSE if no error - not found)
  2544. ===================================================================*/
  2545. HRESULT CPageComponentManager::FindAnyScopeComponentByIUnknown
  2546. (
  2547. IUnknown *pUnk,
  2548. CComponentObject **ppObj
  2549. )
  2550. {
  2551. int cTry = 0;
  2552. *ppObj = NULL;
  2553. while (*ppObj == NULL && cTry < 3)
  2554. {
  2555. HRESULT hr = S_OK;
  2556. CComponentCollection *pCollection = NULL;
  2557. switch (++cTry)
  2558. {
  2559. case 1: // page first
  2560. hr = GetPageCollection(&pCollection);
  2561. break;
  2562. case 2: // session
  2563. hr = GetSessionCollection(&pCollection);
  2564. break;
  2565. case 3: // application
  2566. hr = GetApplnCollection(&pCollection);
  2567. break;
  2568. }
  2569. if (FAILED(hr) || !pCollection)
  2570. continue; // couldn't get the collection
  2571. // find the object
  2572. hr = pCollection->FindComponentByIUnknownPtr(pUnk, ppObj);
  2573. if (hr != S_OK)
  2574. *ppObj = NULL;
  2575. }
  2576. return (*ppObj ? S_OK : S_FALSE);
  2577. }
  2578. /*===================================================================
  2579. CPageComponentManager::FindAnyScopeComponentByIDispatch
  2580. Find component by its IDispatch *.
  2581. Uses FindAnyScopeComponentByIUnknown.
  2582. Parameters:
  2583. IDispatch *pDisp find by this pointer
  2584. CComponentObject **ppObj found object
  2585. Returns:
  2586. HRESULT
  2587. (S_FALSE if no error - not found)
  2588. ===================================================================*/
  2589. HRESULT CPageComponentManager::FindAnyScopeComponentByIDispatch
  2590. (
  2591. IDispatch *pDisp,
  2592. CComponentObject **ppObj
  2593. )
  2594. {
  2595. IUnknown *pUnk = NULL;
  2596. HRESULT hr = pDisp->QueryInterface(IID_IUnknown, (void **)&pUnk);
  2597. if (SUCCEEDED(hr) && !pUnk)
  2598. hr = E_FAIL;
  2599. if (FAILED(hr))
  2600. {
  2601. *ppObj = NULL;
  2602. return hr;
  2603. }
  2604. return FindAnyScopeComponentByIUnknown(pUnk, ppObj);
  2605. }
  2606. /*===================================================================
  2607. CPageComponentManager::FindComponentWithoutContext
  2608. The same as FindAnyScopeComponentByIDispatch -
  2609. but static - gets context from Viper
  2610. Uses FindAnyScopeComponentByIUnknown.
  2611. Parameters:
  2612. IDispatch *pDisp find by this pointer
  2613. CComponentObject **ppObj found object
  2614. Returns:
  2615. HRESULT
  2616. (S_FALSE if no error - not found)
  2617. ===================================================================*/
  2618. HRESULT CPageComponentManager::FindComponentWithoutContext
  2619. (
  2620. IDispatch *pDisp,
  2621. CComponentObject **ppObj
  2622. )
  2623. {
  2624. // Get HitObj from Viper Context
  2625. CHitObj *pHitObj = NULL;
  2626. ViperGetHitObjFromContext(&pHitObj);
  2627. if (!pHitObj)
  2628. return E_FAIL;
  2629. // Get page component manager
  2630. CPageComponentManager *pPCM = pHitObj->PPageComponentManager();
  2631. if (!pPCM)
  2632. return E_FAIL;
  2633. // Call the page component manager to find the object
  2634. return pPCM->FindAnyScopeComponentByIUnknown(pDisp, ppObj);
  2635. }
  2636. /*===================================================================
  2637. CPageComponentManager::RemoveComponent
  2638. Remove component -- the early release logic
  2639. Parameters:
  2640. IDispatch *pDisp find by this pointer
  2641. CComponentObject **ppObj found object
  2642. Returns:
  2643. HRESULT
  2644. ===================================================================*/
  2645. HRESULT CPageComponentManager::RemoveComponent
  2646. (
  2647. CComponentObject *pObj
  2648. )
  2649. {
  2650. Assert(pObj);
  2651. CComponentCollection *pCollection;
  2652. HRESULT hr = GetCollectionByScope(pObj->m_csScope, &pCollection);
  2653. if (FAILED(hr))
  2654. return hr;
  2655. return pCollection->RemoveComponent(pObj);
  2656. }
  2657. /*===================================================================
  2658. C C o m p o n e n t I t e r a t o r
  2659. ===================================================================*/
  2660. /*===================================================================
  2661. CComponentIterator::CComponentIterator
  2662. CComponentIterator constructor
  2663. Parameters:
  2664. CHitObj *pHitObj page to init with (optional)
  2665. Returns:
  2666. ===================================================================*/
  2667. CComponentIterator::CComponentIterator(CHitObj *pHitObj)
  2668. : m_fInited(FALSE), m_fFinished(FALSE), m_pHitObj(NULL),
  2669. m_pLastObj(NULL), m_csLastScope(csUnknown)
  2670. {
  2671. if (pHitObj)
  2672. Init(pHitObj);
  2673. }
  2674. /*===================================================================
  2675. CComponentIterator::~CComponentIterator
  2676. CComponentIterator destructor
  2677. Parameters:
  2678. Returns:
  2679. ===================================================================*/
  2680. CComponentIterator::~CComponentIterator()
  2681. {
  2682. }
  2683. /*===================================================================
  2684. CComponentIterator::Init
  2685. Start iterating
  2686. Parameters:
  2687. CHitObj *pHitObj page
  2688. Returns:
  2689. HRESULT
  2690. ===================================================================*/
  2691. HRESULT CComponentIterator::Init
  2692. (
  2693. CHitObj *pHitObj
  2694. )
  2695. {
  2696. Assert(pHitObj);
  2697. pHitObj->AssertValid();
  2698. m_pHitObj = pHitObj;
  2699. m_fInited = TRUE;
  2700. m_fFinished = FALSE;
  2701. m_pLastObj = NULL;
  2702. m_csLastScope = csUnknown;
  2703. return S_OK;
  2704. }
  2705. /*===================================================================
  2706. CComponentIterator::WStrNextComponentName
  2707. The iteration function
  2708. Parameters:
  2709. Returns:
  2710. Next component name or NULL if done
  2711. ===================================================================*/
  2712. LPWSTR CComponentIterator::WStrNextComponentName()
  2713. {
  2714. Assert(m_fInited);
  2715. if (m_fFinished)
  2716. return NULL;
  2717. Assert(m_pHitObj);
  2718. CompScope csScope = m_csLastScope;
  2719. CComponentObject *pObj = m_pLastObj ?
  2720. static_cast<CComponentObject *>(m_pLastObj->m_pNext) : NULL;
  2721. while (!m_fFinished)
  2722. {
  2723. // try the current scope
  2724. if (pObj)
  2725. {
  2726. Assert(pObj->m_ctType == ctTagged);
  2727. Assert(pObj->GetName());
  2728. m_pLastObj = pObj;
  2729. m_csLastScope = csScope;
  2730. return pObj->GetName();
  2731. }
  2732. // couldn't find in the current scope - try next scope
  2733. CComponentCollection *pCol = NULL;
  2734. switch (csScope)
  2735. {
  2736. case csUnknown:
  2737. csScope = csPage;
  2738. m_pHitObj->GetPageComponentCollection(&pCol);
  2739. break;
  2740. case csPage:
  2741. csScope = csSession;
  2742. m_pHitObj->GetSessionComponentCollection(&pCol);
  2743. break;
  2744. case csSession:
  2745. csScope = csAppln;
  2746. m_pHitObj->GetApplnComponentCollection(&pCol);
  2747. break;
  2748. case csAppln:
  2749. default:
  2750. csScope = csUnknown;
  2751. m_fFinished = TRUE;
  2752. break;
  2753. }
  2754. // start at the beginning of the new collection
  2755. if (pCol)
  2756. pObj = static_cast<CComponentObject *>(pCol->m_htTaggedObjects.Head());
  2757. }
  2758. // finished
  2759. return NULL;
  2760. }
  2761. /*===================================================================
  2762. C V a r i a n t s I t e r a t o r
  2763. ===================================================================*/
  2764. /*===================================================================
  2765. CVariantsIterator::CVariantsIterator
  2766. CVariantsIterator constructor by application
  2767. Parameters:
  2768. CAppln *pAppln collection to init with
  2769. DWORD ctCollType type of components to list iteration
  2770. Returns:
  2771. ===================================================================*/
  2772. CVariantsIterator::CVariantsIterator
  2773. (
  2774. CAppln *pAppln,
  2775. DWORD ctColType
  2776. )
  2777. : m_pCompColl(NULL), m_pAppln(NULL), m_pSession(NULL)
  2778. {
  2779. Assert(pAppln);
  2780. pAppln->AddRef();
  2781. m_cRefs = 1;
  2782. m_pCompColl = pAppln->PCompCol();
  2783. m_pAppln = pAppln;
  2784. m_ctColType = ctColType;
  2785. m_dwIndex = 0;
  2786. }
  2787. /*===================================================================
  2788. CVariantsIterator::CVariantsIterator
  2789. CVariantsIterator constructor by session
  2790. Parameters:
  2791. CSession *pSession collection to init with
  2792. DWORD ctCollType type of components to list iteration
  2793. Returns:
  2794. ===================================================================*/
  2795. CVariantsIterator::CVariantsIterator
  2796. (
  2797. CSession *pSession,
  2798. DWORD ctColType
  2799. )
  2800. : m_pCompColl(NULL), m_pAppln(NULL), m_pSession(NULL)
  2801. {
  2802. Assert(pSession);
  2803. pSession->AddRef();
  2804. m_cRefs = 1;
  2805. m_pCompColl = pSession->PCompCol();
  2806. m_ctColType = ctColType;
  2807. m_pSession = pSession;
  2808. m_dwIndex = 0;
  2809. }
  2810. /*===================================================================
  2811. CVariantsIterator::~CVariantsIterator
  2812. CVariantsIterator destructor
  2813. Parameters:
  2814. Returns:
  2815. ===================================================================*/
  2816. CVariantsIterator::~CVariantsIterator()
  2817. {
  2818. if (m_pSession)
  2819. m_pSession->Release();
  2820. if (m_pAppln)
  2821. m_pAppln->Release();
  2822. }
  2823. /*===================================================================
  2824. CVariantsIterator::QueryInterface
  2825. CVariantsIterator QI
  2826. Parameters:
  2827. GUID& iid
  2828. VOID ** ppvObj
  2829. Returns: HRESULT
  2830. ===================================================================*/
  2831. STDMETHODIMP CVariantsIterator::QueryInterface
  2832. (
  2833. const GUID &iid,
  2834. void **ppvObj
  2835. )
  2836. {
  2837. if (iid == IID_IUnknown || iid == IID_IEnumVARIANT)
  2838. {
  2839. AddRef();
  2840. *ppvObj = this;
  2841. return S_OK;
  2842. }
  2843. *ppvObj = NULL;
  2844. return E_NOINTERFACE;
  2845. }
  2846. /*===================================================================
  2847. CVariantsIterator::AddRef
  2848. CVariantsIterator AddRef
  2849. Parameters:
  2850. Returns: ULONG
  2851. ===================================================================*/
  2852. STDMETHODIMP_(ULONG) CVariantsIterator::AddRef()
  2853. {
  2854. return ++m_cRefs;
  2855. }
  2856. /*===================================================================
  2857. CVariantsIterator::Release
  2858. CVariantsIterator Release
  2859. Parameters:
  2860. Returns:
  2861. ===================================================================*/
  2862. STDMETHODIMP_(ULONG) CVariantsIterator::Release()
  2863. {
  2864. if (--m_cRefs > 0)
  2865. return m_cRefs;
  2866. delete this;
  2867. return 0;
  2868. }
  2869. /*===================================================================
  2870. CVariantsIterator::Clone
  2871. CVariantsIterator Clone
  2872. Parameters:
  2873. Returns:
  2874. ===================================================================*/
  2875. STDMETHODIMP CVariantsIterator::Clone
  2876. (
  2877. IEnumVARIANT **ppEnumReturn
  2878. )
  2879. {
  2880. CVariantsIterator *pNewIterator = NULL;
  2881. if (m_pSession)
  2882. {
  2883. pNewIterator = new CVariantsIterator(m_pSession, m_ctColType);
  2884. }
  2885. else if (m_pAppln)
  2886. {
  2887. pNewIterator = new CVariantsIterator(m_pAppln, m_ctColType);
  2888. }
  2889. else
  2890. {
  2891. Assert(FALSE); // better be either Appln or Session
  2892. return E_FAIL;
  2893. }
  2894. if (pNewIterator == NULL)
  2895. return E_OUTOFMEMORY;
  2896. // new iterator should point to same location as this.
  2897. pNewIterator->m_dwIndex = m_dwIndex;
  2898. *ppEnumReturn = pNewIterator;
  2899. return S_OK;
  2900. }
  2901. /*===================================================================
  2902. CVariantsIterator::Next
  2903. CVariantsIterator Next
  2904. Parameters:
  2905. Returns:
  2906. ===================================================================*/
  2907. STDMETHODIMP CVariantsIterator::Next
  2908. (
  2909. unsigned long cElementsRequested,
  2910. VARIANT *rgVariant,
  2911. unsigned long *pcElementsFetched
  2912. )
  2913. {
  2914. // give a valid pointer value to 'pcElementsFetched'
  2915. unsigned long cElementsFetched;
  2916. if (pcElementsFetched == NULL)
  2917. pcElementsFetched = &cElementsFetched;
  2918. if (cElementsRequested == 0)
  2919. {
  2920. if (pcElementsFetched)
  2921. *pcElementsFetched = 0;
  2922. return S_OK;
  2923. }
  2924. DWORD cMax = 0;
  2925. if (m_ctColType == ctTagged)
  2926. {
  2927. cMax = m_pCompColl ? m_pCompColl->m_cAllTagged : 0;
  2928. }
  2929. else if (m_ctColType == ctProperty)
  2930. {
  2931. cMax = m_pCompColl ? m_pCompColl->m_cProperties : 0;
  2932. }
  2933. else
  2934. {
  2935. // Should always be either tagged object or property
  2936. Assert(FALSE);
  2937. return E_FAIL;
  2938. }
  2939. // Loop through the collection until either we reach the end or
  2940. // cElements becomes zero
  2941. //
  2942. unsigned long cElements = cElementsRequested;
  2943. *pcElementsFetched = 0;
  2944. while (cElements > 0 && m_dwIndex < cMax)
  2945. {
  2946. LPWSTR pwszName = NULL;
  2947. if (m_pAppln)
  2948. m_pAppln->Lock();
  2949. m_pCompColl->GetNameByIndex(m_ctColType, ++m_dwIndex, &pwszName);
  2950. if (!pwszName) {
  2951. if (m_pAppln)
  2952. m_pAppln->UnLock();
  2953. continue;
  2954. }
  2955. BSTR bstrT = SysAllocString(pwszName);
  2956. if (m_pAppln)
  2957. m_pAppln->UnLock();
  2958. if (!bstrT)
  2959. return E_OUTOFMEMORY;
  2960. V_VT(rgVariant) = VT_BSTR;
  2961. V_BSTR(rgVariant) = bstrT;
  2962. ++rgVariant;
  2963. --cElements;
  2964. ++(*pcElementsFetched);
  2965. }
  2966. // initialize the remaining variants
  2967. while (cElements-- > 0)
  2968. VariantInit(rgVariant++);
  2969. return (*pcElementsFetched == cElementsRequested)? S_OK : S_FALSE;
  2970. }
  2971. /*===================================================================
  2972. CVariantsIterator::Skip
  2973. CVariantsIterator Skip
  2974. Parameters:
  2975. Returns:
  2976. ===================================================================*/
  2977. STDMETHODIMP CVariantsIterator::Skip
  2978. (
  2979. unsigned long cElements
  2980. )
  2981. {
  2982. /* Adjust the index by cElements or
  2983. * until we hit the max element
  2984. */
  2985. DWORD cMax = 0;
  2986. // We iterate over different arrays depending on the collection type
  2987. if (m_ctColType == ctTagged)
  2988. {
  2989. cMax = m_pCompColl ? m_pCompColl->m_cAllTagged : 0;
  2990. }
  2991. else if (m_ctColType == ctProperty)
  2992. {
  2993. cMax = m_pCompColl ? m_pCompColl->m_cProperties : 0;
  2994. }
  2995. else
  2996. {
  2997. // Should always be either tagged object or property
  2998. Assert(FALSE);
  2999. return E_FAIL;
  3000. }
  3001. m_dwIndex += cElements;
  3002. return (m_dwIndex < cMax)? S_OK : S_FALSE;
  3003. }
  3004. /*===================================================================
  3005. CVariantsIterator::Reset
  3006. CVariantsIterator Reset
  3007. Parameters:
  3008. Returns:
  3009. ===================================================================*/
  3010. STDMETHODIMP CVariantsIterator::Reset()
  3011. {
  3012. m_dwIndex = 0;
  3013. return NO_ERROR;
  3014. }