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.

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