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.

904 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: cdispmgr.cxx
  7. //
  8. // Contents: The dispatch manager -- a class to manage
  9. // multiple IDispatch-callable interfaces.
  10. //
  11. // Classes: CAggregatorDispMgr
  12. //
  13. // Functions: None external.
  14. //
  15. // History: ??-???-?? KrishnaG created
  16. // 07-Sep-97 t-blakej Commented, cleaned up, made
  17. // independent of ADSI.
  18. //
  19. // See cdispmgr.hxx for a more thorough description of the dispatch manager.
  20. //
  21. //----------------------------------------------------------------------------
  22. //
  23. // Since this class is useful outside of ADSI, some work has been taken to
  24. // make it not depend on any ADSI-specific code. It needs two ADSI header
  25. // files (cdispmgr.hxx and iprops.hxx), but they only depend on definitions
  26. // from standard system header files.
  27. //
  28. // To accomodate the current building method in ADSI, the precompiled
  29. // header "procs.hxx" is included; this includes all the necessary ADSI
  30. // header files and definitions. But for use outside of ADSI, the few
  31. // necessary header files are explicitly included below; see the comment by
  32. // "#ifndef ADsAssert".
  33. //
  34. // So if not compiling for ADSI, comment the following two lines out.
  35. //
  36. #include "nwcompat.hxx"
  37. #pragma hdrstop
  38. //////////////////////////////////////////////////////////////////////////////
  39. //
  40. // General helper definitions, routines, and inclusions:
  41. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Begin Non-ADSI compile stuff
  42. //
  43. // This macro is defined by the precompiled header file, so the following
  44. // will only be included if not compiling for ADSI.
  45. //
  46. #ifndef ADsAssert
  47. //
  48. // Necessary system headers.
  49. //
  50. #define UNICODE
  51. #define _UNICODE
  52. #define _OLEAUT32_
  53. #define INC_OLE2
  54. #include <windows.h>
  55. #include <stdio.h>
  56. //
  57. // Necessary class definitions used by the dispatch manager.
  58. // Edit these paths if necessary.
  59. //
  60. #endif // ADsAssert
  61. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- End Non-ADSI compile stuff
  62. //
  63. // Error recovery.
  64. //
  65. //
  66. // A simple assert function.
  67. //
  68. #if DBG == 1
  69. //+---------------------------------------------------------------------------
  70. //
  71. // Function: AssertEx
  72. //
  73. // Synopsis: Display assertion information.
  74. //
  75. // Effects: Called when an assertion is hit.
  76. //
  77. // History: Simplified from Win4AssertEx, to make this dispatch manager
  78. // not depend on other files.
  79. //
  80. //----------------------------------------------------------------------------
  81. static void
  82. AggregatorAssertEx(char const *szFile, int iLine, char const *szMessage)
  83. {
  84. static char szAssertCaption[200];
  85. DWORD dwCount = strlen("File: %s line %u, thread id %d");
  86. if (szFile) {
  87. dwCount += strlen(szFile);
  88. }
  89. dwCount += 15; // for the line number and thread id
  90. if (dwCount > 199) {
  91. sprintf(szAssertCaption, "Error, could not get more infomration");
  92. }
  93. else {
  94. sprintf(szAssertCaption, "File: %s line %u, thread id %d",
  95. szFile, iLine, GetCurrentThreadId());
  96. }
  97. if (IDCANCEL == MessageBoxA(
  98. NULL,
  99. (char *) szMessage,
  100. (LPSTR) szAssertCaption,
  101. MB_SETFOREGROUND |
  102. MB_TASKMODAL | MB_ICONEXCLAMATION | MB_OKCANCEL
  103. ))
  104. {
  105. DebugBreak();
  106. }
  107. }
  108. # define AggregatorDispMgrAssert(x) (void)((x) || (AggregatorAssertEx(__FILE__, __LINE__, #x),0))
  109. #else
  110. # define AggregatorAssertEx(f,l,m)
  111. # define AggregatorDispMgrAssert(x)
  112. #endif
  113. //////////////////////////////////////////////////////////////////////////////
  114. //
  115. // Inline routines:
  116. static inline LONG
  117. getDispMgrId(DISPID InputDispId)
  118. {
  119. return (InputDispId & 0x7f000000) >> 24;
  120. }
  121. static inline LONG
  122. getTypeInfoId(DISPID InputDispId)
  123. {
  124. return (InputDispId & 0x00ff0000) >> 16;
  125. }
  126. static inline LONG
  127. getDispId(DISPID InputDispId)
  128. {
  129. return (InputDispId & 0x0000ffff);
  130. }
  131. static inline void
  132. MakeDISPID(LONG TypeInfoId, LONG DispId, DISPID *pResult)
  133. {
  134. if (DispId == DISPID_UNKNOWN)
  135. *pResult = DispId;
  136. else if (TypeInfoId < 0 || TypeInfoId >= 0x100 ||
  137. DispId < 0 || DispId >= 0x10000)
  138. {
  139. //
  140. // Might happen if some object has very large dispid's.
  141. // But we can't handle it if it does.
  142. //
  143. *pResult = DISPID_UNKNOWN;
  144. }
  145. else
  146. *pResult = ((TypeInfoId & 0xff) << 16) | (DispId & 0xffff);
  147. }
  148. static inline void
  149. IncDispMgrIds(DISPID *rgdispid, unsigned int cNames)
  150. {
  151. for (unsigned int i = 0; i < cNames; ++i)
  152. {
  153. if (rgdispid[i] == DISPID_UNKNOWN)
  154. continue;
  155. //
  156. // This is either a stack of DispMgrs >127 high, or
  157. // a programming error. More likely the latter.
  158. //
  159. AggregatorDispMgrAssert(getDispMgrId(rgdispid[i]) < 0x7f);
  160. rgdispid[i] =
  161. (rgdispid[i] & 0x00ffffff) |
  162. (((getDispMgrId(rgdispid[i]) + 1) & 0x7f) << 24);
  163. }
  164. }
  165. static inline void
  166. DecDispMgrIds(DISPID *rgdispid, unsigned int cNames)
  167. {
  168. for (unsigned int i = 0; i < cNames; ++i)
  169. {
  170. //
  171. // It should never be less than zero, and the only place
  172. // this is called from guarantees it is not zero.
  173. //
  174. AggregatorDispMgrAssert(getDispMgrId(rgdispid[i]) > 0);
  175. rgdispid[i] =
  176. (rgdispid[i] & 0x00ffffff) |
  177. (((getDispMgrId(rgdispid[i]) - 1) & 0x7f) << 24);
  178. }
  179. }
  180. static inline void
  181. MakeDISPIDs(LONG TypeInfoId, DISPID *rgdispid, unsigned int cNames)
  182. {
  183. for (unsigned int i = 0; i < cNames; i++)
  184. {
  185. MakeDISPID(TypeInfoId, rgdispid[i], &rgdispid[i]);
  186. }
  187. }
  188. //
  189. // Struct definitions
  190. //
  191. typedef struct _typeinfotable
  192. {
  193. GUID iid;
  194. ITypeInfo * pTypeInfo;
  195. struct _typeinfotable *pNext;
  196. }TYPEINFO_TABLE, *PTYPEINFO_TABLE;
  197. PTYPEINFO_TABLE gpTypeInfoTable = NULL;
  198. CRITICAL_SECTION g_TypeInfoCritSect;
  199. #define ENTER_TYPEINFO_CRITSECT() EnterCriticalSection(&g_TypeInfoCritSect)
  200. #define LEAVE_TYPEINFO_CRITSECT() LeaveCriticalSection(&g_TypeInfoCritSect)
  201. LONG glnObjCount = 0;
  202. LONG glnTypesOfInfo = 0;
  203. //////////////////////////////////////////////////////////////////////////////
  204. //
  205. // Public methods:
  206. CAggregatorDispMgr::CAggregatorDispMgr()
  207. {
  208. _pTypeInfoEntry = NULL;
  209. _pDispidNewEnum = NULL;
  210. _dwTypeInfoId = 0;
  211. _pDispidValue = NULL;
  212. _pPropertyCache = NULL;
  213. _dwPropCacheID = 0;
  214. }
  215. CAggregatorDispMgr::~CAggregatorDispMgr()
  216. {
  217. PTYPEINFOENTRY pTypeInfoEntry = NULL;
  218. PTYPEINFOENTRY pTemp = NULL;
  219. ITypeInfo *pTypeInfo = NULL;
  220. pTypeInfoEntry = _pTypeInfoEntry;
  221. while (pTypeInfoEntry) {
  222. pTemp = pTypeInfoEntry;
  223. pTypeInfo = (ITypeInfo *)pTypeInfoEntry->ptypeinfo;
  224. pTypeInfo->Release();
  225. InterlockedDecrement(&glnObjCount);
  226. pTypeInfoEntry = pTemp->pNext;
  227. LocalFree(pTemp);
  228. }
  229. ENTER_TYPEINFO_CRITSECT();
  230. if (glnObjCount == glnTypesOfInfo) {
  231. //
  232. // We need to clean up the list
  233. //
  234. FreeTypeInfoTable();
  235. glnObjCount = glnTypesOfInfo = 0;
  236. }
  237. LEAVE_TYPEINFO_CRITSECT();
  238. }
  239. void
  240. CAggregatorDispMgr::RegisterPropertyCache(IPropertyCache *pPropertyCache)
  241. {
  242. _pPropertyCache = pPropertyCache;
  243. _dwPropCacheID = gentypeinfoid();
  244. }
  245. STDMETHODIMP
  246. CAggregatorDispMgr::GetTypeInfoCount(unsigned int *pctinfo)
  247. {
  248. return E_NOTIMPL;
  249. }
  250. STDMETHODIMP
  251. CAggregatorDispMgr::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo **pptinfo)
  252. {
  253. return E_NOTIMPL;
  254. }
  255. //
  256. // This works only for single names; if multiple names are
  257. // passed we die big time. This is help us get going using VB's _NewEnum
  258. //
  259. STDMETHODIMP
  260. CAggregatorDispMgr::GetIDsOfNames(
  261. REFIID iid,
  262. LPWSTR *rgszNames,
  263. unsigned int cNames,
  264. LCID lcid,
  265. DISPID *rgdispid
  266. )
  267. {
  268. PTYPEINFOENTRY pTypeInfo = NULL;
  269. HRESULT hr = DISP_E_UNKNOWNNAME;
  270. //
  271. // Try our list of TypeInfos.
  272. //
  273. pTypeInfo = _pTypeInfoEntry;
  274. while (pTypeInfo) {
  275. hr = DispGetIDsOfNames(((ITypeInfo *)pTypeInfo->ptypeinfo),
  276. rgszNames,
  277. cNames,
  278. rgdispid
  279. );
  280. if (SUCCEEDED(hr)) {
  281. MakeDISPIDs(pTypeInfo->TypeInfoId, rgdispid, cNames);
  282. return hr;
  283. }
  284. pTypeInfo = pTypeInfo->pNext;
  285. }
  286. //
  287. // Try our property cache.
  288. //
  289. if (FAILED(hr) && _pPropertyCache) {
  290. hr = S_OK;
  291. for (DWORD dw = 0; dw < cNames; dw++) {
  292. if (FAILED(_pPropertyCache->locateproperty(rgszNames[dw],
  293. (PDWORD)(rgdispid + dw)))) {
  294. hr = DISP_E_UNKNOWNNAME;
  295. rgdispid[dw] = DISPID_UNKNOWN;
  296. }
  297. }
  298. if (SUCCEEDED(hr)) {
  299. MakeDISPIDs(_dwPropCacheID, rgdispid, cNames);
  300. }
  301. }
  302. return hr;
  303. }
  304. STDMETHODIMP
  305. CAggregatorDispMgr::Invoke(
  306. DISPID dispidMember,
  307. REFIID iid,
  308. LCID lcid,
  309. unsigned short wFlags,
  310. DISPPARAMS *pdispparams,
  311. VARIANT *pvarResult,
  312. EXCEPINFO *pexcepinfo,
  313. unsigned int *puArgErr
  314. )
  315. {
  316. //
  317. // Clear the error object before we call invoke.
  318. //
  319. SetErrorInfo(0, NULL);
  320. return TypeInfoInvoke(dispidMember,
  321. iid,
  322. lcid,
  323. wFlags,
  324. pdispparams,
  325. pvarResult,
  326. pexcepinfo,
  327. puArgErr
  328. );
  329. }
  330. //////////////////////////////////////////////////////////////////////////////
  331. //
  332. // Private methods and helper functions:
  333. void *
  334. CAggregatorDispMgr::getInterfacePtr(LONG TypeInfoId)
  335. {
  336. PTYPEINFOENTRY pTypeInfoEntry = FindTypeInfoEntry(TypeInfoId);
  337. return (pTypeInfoEntry ? pTypeInfoEntry->pInterfacePointer : NULL);
  338. }
  339. ITypeInfo *
  340. CAggregatorDispMgr::getTypeInfo(LONG TypeInfoId)
  341. {
  342. PTYPEINFOENTRY pTypeInfoEntry = FindTypeInfoEntry(TypeInfoId);
  343. return (ITypeInfo *)(pTypeInfoEntry ? pTypeInfoEntry->ptypeinfo : NULL);
  344. }
  345. PTYPEINFOENTRY
  346. CAggregatorDispMgr::FindTypeInfoEntry(LONG TypeInfoId)
  347. {
  348. PTYPEINFOENTRY pTypeInfoEntry;
  349. pTypeInfoEntry = _pTypeInfoEntry;
  350. while (pTypeInfoEntry) {
  351. if (pTypeInfoEntry->TypeInfoId == TypeInfoId) {
  352. return pTypeInfoEntry;
  353. }
  354. pTypeInfoEntry = pTypeInfoEntry->pNext;
  355. }
  356. return NULL;
  357. }
  358. PTYPEINFOENTRY
  359. CAggregatorDispMgr::FindTypeInfo(void *pTypeInfo)
  360. {
  361. PTYPEINFOENTRY pTypeInfoEntry;
  362. pTypeInfoEntry = _pTypeInfoEntry;
  363. while (pTypeInfoEntry) {
  364. if (pTypeInfoEntry->ptypeinfo == pTypeInfo) {
  365. return pTypeInfoEntry;
  366. }
  367. pTypeInfoEntry = pTypeInfoEntry->pNext;
  368. }
  369. return NULL;
  370. }
  371. HRESULT
  372. CAggregatorDispMgr::AddTypeInfo(void *ptypeinfo, void *pIntfptr)
  373. {
  374. PTYPEINFOENTRY pTypeInfoEntry = NULL;
  375. HRESULT hr = S_OK;
  376. if (FindTypeInfo(ptypeinfo)) {
  377. return E_FAIL;
  378. }
  379. pTypeInfoEntry = (PTYPEINFOENTRY)LocalAlloc(LPTR,sizeof(TYPEINFOENTRY));
  380. if (!pTypeInfoEntry) {
  381. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  382. }
  383. pTypeInfoEntry->ptypeinfo = ptypeinfo;
  384. pTypeInfoEntry->TypeInfoId = gentypeinfoid();
  385. pTypeInfoEntry->pInterfacePointer = pIntfptr;
  386. pTypeInfoEntry->pNext = _pTypeInfoEntry;
  387. _pTypeInfoEntry = pTypeInfoEntry;
  388. error:
  389. return hr;
  390. }
  391. STDMETHODIMP
  392. CAggregatorDispMgr::TypeInfoInvoke(
  393. DISPID dispidMember,
  394. REFIID iid,
  395. LCID lcid,
  396. unsigned short wFlags,
  397. DISPPARAMS *pdispparams,
  398. VARIANT *pvarResult,
  399. EXCEPINFO *pexcepinfo,
  400. unsigned int *puArgErr
  401. )
  402. {
  403. void *pInterfacePtr = NULL;
  404. DISPID dispid = 0;
  405. DISPID typeinfoid = 0;
  406. ITypeInfo *pTypeInfo = NULL;
  407. HRESULT hr = S_OK;
  408. if (dispidMember <= 0) {
  409. //
  410. // One of the special DISPIDs.
  411. //
  412. // If we have an interface pointer for it, use that.
  413. // If we don't, and we have a base IDispatch pointer,
  414. // pass it to the base pointer's Invoke() method.
  415. // If we don't, and we don't have a base IDispatch pointer,
  416. // return failure.
  417. //
  418. dispid = dispidMember;
  419. switch (dispid) {
  420. case DISPID_VALUE:
  421. if (_pDispidValue) {
  422. pTypeInfo = (ITypeInfo *)_pDispidValue->ptypeinfo;
  423. pInterfacePtr = _pDispidValue->pInterfacePointer;
  424. }
  425. break;
  426. case DISPID_NEWENUM:
  427. if (_pDispidNewEnum) {
  428. pTypeInfo = (ITypeInfo *)_pDispidNewEnum->ptypeinfo;
  429. pInterfacePtr = _pDispidNewEnum->pInterfacePointer;
  430. }
  431. break;
  432. default:
  433. break;
  434. }
  435. if (!pInterfacePtr) {
  436. BAIL_ON_FAILURE(hr = DISP_E_MEMBERNOTFOUND);
  437. }else {
  438. //
  439. // Fill in the special case scenarios here
  440. //
  441. hr = DispInvoke(
  442. pInterfacePtr,
  443. pTypeInfo,
  444. dispid,
  445. wFlags,
  446. pdispparams,
  447. pvarResult,
  448. pexcepinfo,
  449. puArgErr
  450. );
  451. return(hr);
  452. }
  453. } else {
  454. //
  455. // A regular DISPID of ours.
  456. //
  457. typeinfoid = getTypeInfoId(dispidMember);
  458. dispid = getDispId(dispidMember);
  459. if ((_pPropertyCache == NULL) || (typeinfoid != _dwPropCacheID)) {
  460. pInterfacePtr = getInterfacePtr(typeinfoid);
  461. pTypeInfo = getTypeInfo(typeinfoid);
  462. if (!pTypeInfo)
  463. //
  464. // Shouldn't happen.
  465. //
  466. BAIL_ON_FAILURE(hr = DISP_E_MEMBERNOTFOUND);
  467. }
  468. if ((_pPropertyCache == NULL) || (typeinfoid != _dwPropCacheID)) {
  469. //
  470. // A regular interface.
  471. //
  472. hr = DispInvoke(
  473. pInterfacePtr,
  474. pTypeInfo,
  475. dispid,
  476. wFlags,
  477. pdispparams,
  478. pvarResult,
  479. pexcepinfo,
  480. puArgErr
  481. );
  482. }else {
  483. //
  484. // A "dynamic DISPID", for the property cache.
  485. //
  486. hr = DynamicDispidInvoke(
  487. _pPropertyCache,
  488. dispid,
  489. wFlags,
  490. pdispparams,
  491. pvarResult
  492. );
  493. }
  494. }
  495. error:
  496. return hr;
  497. }
  498. HRESULT
  499. DynamicDispidInvoke(
  500. IPropertyCache * pPropertyCache,
  501. DISPID dispid,
  502. unsigned short wFlags,
  503. DISPPARAMS *pdispparams,
  504. VARIANT * pvarResult
  505. )
  506. {
  507. HRESULT hr = S_OK;
  508. if (!pPropertyCache) {
  509. return(E_INVALIDARG);
  510. }
  511. if (wFlags & DISPATCH_PROPERTYGET) {
  512. if (!pvarResult) {
  513. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  514. }
  515. hr = pPropertyCache->getproperty((DWORD)dispid,pvarResult);
  516. if (FAILED(hr)) {
  517. #if 1
  518. // This lets us return S_OK and a VT_EMPTY variant if
  519. // there's no data. #if this out to disable it.
  520. V_VT(pvarResult) = VT_EMPTY;
  521. hr = S_OK;
  522. #else
  523. V_VT(pvarResult) = VT_ERROR;
  524. #endif
  525. }
  526. }else if (wFlags & DISPATCH_PROPERTYPUT) {
  527. //
  528. // ADSI property PUTs only take a single argument
  529. // (even multivalued properties are set with a single
  530. // argument, a VARIANT array). Therefore, if someone
  531. // is trying to get a multiple argument property PUT,
  532. // it's a invalid method call that must be disallowed.
  533. //
  534. if (pdispparams[0].cArgs != 1){
  535. hr = DISP_E_BADPARAMCOUNT;
  536. }
  537. else {
  538. hr = pPropertyCache->putproperty(
  539. (DWORD)dispid,
  540. pdispparams[0].rgvarg[0]
  541. );
  542. }
  543. }else {
  544. hr = E_INVALIDARG;
  545. }
  546. error:
  547. return(hr);
  548. }
  549. HRESULT
  550. CAggregatorDispMgr::MarkAsNewEnum(void *pTypeInfo)
  551. {
  552. PTYPEINFOENTRY pTypeInfoEntry;
  553. if (!pTypeInfo) {
  554. return E_FAIL;
  555. }
  556. if (!(pTypeInfoEntry = FindTypeInfo(pTypeInfo))) {
  557. return E_FAIL;
  558. }
  559. _pDispidNewEnum = pTypeInfoEntry;
  560. return S_OK;
  561. }
  562. HRESULT
  563. CAggregatorDispMgr::MarkAsItem(void *pTypeInfo)
  564. {
  565. PTYPEINFOENTRY pTypeInfoEntry;
  566. if (!pTypeInfo) {
  567. return E_FAIL;
  568. }
  569. if (!(pTypeInfoEntry = FindTypeInfo(pTypeInfo))) {
  570. return E_FAIL;
  571. }
  572. _pDispidValue = pTypeInfoEntry;
  573. return S_OK;
  574. }
  575. LONG
  576. CAggregatorDispMgr::gentypeinfoid()
  577. {
  578. //
  579. // This would mean we've registered 65536 IDispatch methods
  580. // in this object's dispatch manager. We lose.
  581. //
  582. AggregatorDispMgrAssert(_dwTypeInfoId < 0xffff);
  583. return (_dwTypeInfoId++);
  584. }
  585. ITypeInfo *
  586. FindTypeInfo(
  587. PTYPEINFO_TABLE pTypeInfoTable,
  588. REFIID iid
  589. )
  590. {
  591. PTYPEINFO_TABLE pTemp = NULL;
  592. pTemp = pTypeInfoTable;
  593. while (pTemp) {
  594. if (IsEqualIID(iid, pTemp->iid)) {
  595. return pTemp->pTypeInfo;
  596. }
  597. pTemp = pTemp->pNext;
  598. }
  599. return NULL;
  600. }
  601. PTYPEINFO_TABLE
  602. AddTypeInfo(
  603. PTYPEINFO_TABLE pTypeInfoTable,
  604. REFIID iid,
  605. ITypeInfo * pTypeInfo
  606. )
  607. {
  608. PTYPEINFO_TABLE pTemp = NULL;
  609. pTemp = (PTYPEINFO_TABLE)LocalAlloc(LPTR, sizeof(TYPEINFO_TABLE));
  610. if (!pTemp) {
  611. return NULL;
  612. }
  613. memcpy(&pTemp->iid, &iid, sizeof(GUID));
  614. pTemp->pTypeInfo = pTypeInfo;
  615. pTemp->pNext = pTypeInfoTable;
  616. return pTemp;
  617. }
  618. //+------------------------------------------------------------------------
  619. //
  620. // Function: LoadTypeInfo
  621. //
  622. // Synopsis: Loads a typeinfo from a registered typelib.
  623. //
  624. // Arguments: [clsidTL] -- TypeLib GUID
  625. // [clsidTI] -- TypeInfo GUID
  626. // [ppTI] -- Resulting typeInfo
  627. //
  628. // Returns: HRESULT
  629. //
  630. //-------------------------------------------------------------------------
  631. HRESULT
  632. LoadTypeInfo(CLSID clsidTL, CLSID clsidTI, LPTYPEINFO *ppTI)
  633. {
  634. HRESULT hr;
  635. ITypeLib * pTL;
  636. AggregatorDispMgrAssert(ppTI);
  637. *ppTI = NULL;
  638. hr = LoadRegTypeLib(clsidTL, 1, 0, LOCALE_SYSTEM_DEFAULT, &pTL);
  639. if (!SUCCEEDED(hr))
  640. return hr;
  641. hr = pTL->GetTypeInfoOfGuid(clsidTI, ppTI);
  642. pTL->Release();
  643. return hr;
  644. }
  645. HRESULT
  646. CAggregatorDispMgr::LoadTypeInfoEntry(
  647. REFIID libid,
  648. REFIID iid,
  649. void * pIntf,
  650. DISPID SpecialId
  651. )
  652. {
  653. ITypeInfo * pTypeInfo = NULL;
  654. HRESULT hr;
  655. ENTER_TYPEINFO_CRITSECT();
  656. pTypeInfo = ::FindTypeInfo(gpTypeInfoTable, iid);
  657. if (!pTypeInfo) {
  658. LEAVE_TYPEINFO_CRITSECT();
  659. hr = LoadTypeInfo(libid, iid, &pTypeInfo);
  660. BAIL_ON_FAILURE(hr);
  661. ENTER_TYPEINFO_CRITSECT();
  662. gpTypeInfoTable = ::AddTypeInfo(
  663. gpTypeInfoTable,
  664. iid,
  665. pTypeInfo
  666. );
  667. if (!gpTypeInfoTable) {
  668. LEAVE_TYPEINFO_CRITSECT();
  669. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  670. }
  671. //
  672. // Increment the global list of the types of type info's.
  673. //
  674. InterlockedIncrement(&glnTypesOfInfo);
  675. InterlockedIncrement(&glnObjCount);
  676. }
  677. pTypeInfo->AddRef();
  678. hr = AddTypeInfo(pTypeInfo, pIntf);
  679. if (FAILED(hr)) {
  680. LEAVE_TYPEINFO_CRITSECT();
  681. BAIL_ON_FAILURE(hr);
  682. }
  683. //
  684. // We have a ref on the object as add was succesful
  685. //
  686. InterlockedIncrement(&glnObjCount);
  687. LEAVE_TYPEINFO_CRITSECT();
  688. if (SpecialId == -4) {
  689. hr = MarkAsNewEnum(pTypeInfo);
  690. } else if (SpecialId == DISPID_VALUE) {
  691. hr = MarkAsItem(pTypeInfo);
  692. }
  693. return S_OK;
  694. error:
  695. if (pTypeInfo)
  696. pTypeInfo->Release();
  697. return hr;
  698. }
  699. //
  700. // Kept for backwards compatibility.
  701. //
  702. HRESULT
  703. LoadTypeInfoEntry(
  704. CAggregatorDispMgr *pDispMgr,
  705. REFIID libid,
  706. REFIID iid,
  707. void * pIntf,
  708. DISPID SpecialId
  709. )
  710. {
  711. return pDispMgr->LoadTypeInfoEntry(libid, iid, pIntf, SpecialId);
  712. }
  713. void
  714. FreeTypeInfoTable()
  715. {
  716. PTYPEINFO_TABLE pTypeInfoTable = NULL;
  717. PTYPEINFO_TABLE pTemp = NULL;
  718. ITypeInfo * pTypeInfo = NULL;
  719. pTypeInfoTable = gpTypeInfoTable;
  720. while (pTypeInfoTable) {
  721. pTypeInfo = pTypeInfoTable->pTypeInfo;
  722. pTypeInfo->Release();
  723. pTemp = pTypeInfoTable;
  724. pTypeInfoTable = pTypeInfoTable->pNext;
  725. LocalFree(pTemp);
  726. }
  727. gpTypeInfoTable = NULL;
  728. }
  729. BOOL
  730. AggregatorDllCanUnload()
  731. {
  732. BOOL retVal = FALSE;
  733. ENTER_TYPEINFO_CRITSECT();
  734. retVal = (glnObjCount == 0);
  735. LEAVE_TYPEINFO_CRITSECT();
  736. return retVal;
  737. }