Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

901 lines
21 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. if (!rgdispid)
  269. {
  270. hr = E_ADS_BAD_PARAMETER;
  271. }
  272. else
  273. {
  274. //
  275. // Try our list of TypeInfos.
  276. //
  277. pTypeInfo = _pTypeInfoEntry;
  278. while (pTypeInfo) {
  279. hr = DispGetIDsOfNames(((ITypeInfo *)pTypeInfo->ptypeinfo),
  280. rgszNames,
  281. cNames,
  282. rgdispid
  283. );
  284. if (SUCCEEDED(hr)) {
  285. MakeDISPIDs(pTypeInfo->TypeInfoId, rgdispid, cNames);
  286. return hr;
  287. }
  288. pTypeInfo = pTypeInfo->pNext;
  289. }
  290. //
  291. // Try our property cache.
  292. //
  293. if (FAILED(hr) && _pPropertyCache) {
  294. hr = S_OK;
  295. for (DWORD dw = 0; dw < cNames; dw++) {
  296. if (FAILED(_pPropertyCache->locateproperty(rgszNames[dw],
  297. (PDWORD)(rgdispid + dw)))) {
  298. hr = DISP_E_UNKNOWNNAME;
  299. rgdispid[dw] = DISPID_UNKNOWN;
  300. }
  301. }
  302. if (SUCCEEDED(hr)) {
  303. MakeDISPIDs(_dwPropCacheID, rgdispid, cNames);
  304. }
  305. }
  306. }
  307. return hr;
  308. }
  309. STDMETHODIMP
  310. CAggregatorDispMgr::Invoke(
  311. DISPID dispidMember,
  312. REFIID iid,
  313. LCID lcid,
  314. unsigned short wFlags,
  315. DISPPARAMS *pdispparams,
  316. VARIANT *pvarResult,
  317. EXCEPINFO *pexcepinfo,
  318. unsigned int *puArgErr
  319. )
  320. {
  321. //
  322. // Clear the error object before we call invoke.
  323. //
  324. SetErrorInfo(0, NULL);
  325. return TypeInfoInvoke(dispidMember,
  326. iid,
  327. lcid,
  328. wFlags,
  329. pdispparams,
  330. pvarResult,
  331. pexcepinfo,
  332. puArgErr
  333. );
  334. }
  335. //////////////////////////////////////////////////////////////////////////////
  336. //
  337. // Private methods and helper functions:
  338. void *
  339. CAggregatorDispMgr::getInterfacePtr(LONG TypeInfoId)
  340. {
  341. PTYPEINFOENTRY pTypeInfoEntry = FindTypeInfoEntry(TypeInfoId);
  342. return (pTypeInfoEntry ? pTypeInfoEntry->pInterfacePointer : NULL);
  343. }
  344. ITypeInfo *
  345. CAggregatorDispMgr::getTypeInfo(LONG TypeInfoId)
  346. {
  347. PTYPEINFOENTRY pTypeInfoEntry = FindTypeInfoEntry(TypeInfoId);
  348. return (ITypeInfo *)(pTypeInfoEntry ? pTypeInfoEntry->ptypeinfo : NULL);
  349. }
  350. PTYPEINFOENTRY
  351. CAggregatorDispMgr::FindTypeInfoEntry(LONG TypeInfoId)
  352. {
  353. PTYPEINFOENTRY pTypeInfoEntry;
  354. pTypeInfoEntry = _pTypeInfoEntry;
  355. while (pTypeInfoEntry) {
  356. if (pTypeInfoEntry->TypeInfoId == TypeInfoId) {
  357. return pTypeInfoEntry;
  358. }
  359. pTypeInfoEntry = pTypeInfoEntry->pNext;
  360. }
  361. return NULL;
  362. }
  363. PTYPEINFOENTRY
  364. CAggregatorDispMgr::FindTypeInfo(void *pTypeInfo)
  365. {
  366. PTYPEINFOENTRY pTypeInfoEntry;
  367. pTypeInfoEntry = _pTypeInfoEntry;
  368. while (pTypeInfoEntry) {
  369. if (pTypeInfoEntry->ptypeinfo == pTypeInfo) {
  370. return pTypeInfoEntry;
  371. }
  372. pTypeInfoEntry = pTypeInfoEntry->pNext;
  373. }
  374. return NULL;
  375. }
  376. HRESULT
  377. CAggregatorDispMgr::AddTypeInfo(void *ptypeinfo, void *pIntfptr)
  378. {
  379. PTYPEINFOENTRY pTypeInfoEntry = NULL;
  380. HRESULT hr = S_OK;
  381. if (FindTypeInfo(ptypeinfo)) {
  382. return E_FAIL;
  383. }
  384. pTypeInfoEntry = (PTYPEINFOENTRY)LocalAlloc(LPTR,sizeof(TYPEINFOENTRY));
  385. if (!pTypeInfoEntry) {
  386. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  387. }
  388. pTypeInfoEntry->ptypeinfo = ptypeinfo;
  389. pTypeInfoEntry->TypeInfoId = gentypeinfoid();
  390. pTypeInfoEntry->pInterfacePointer = pIntfptr;
  391. pTypeInfoEntry->pNext = _pTypeInfoEntry;
  392. _pTypeInfoEntry = pTypeInfoEntry;
  393. error:
  394. return hr;
  395. }
  396. STDMETHODIMP
  397. CAggregatorDispMgr::TypeInfoInvoke(
  398. DISPID dispidMember,
  399. REFIID iid,
  400. LCID lcid,
  401. unsigned short wFlags,
  402. DISPPARAMS *pdispparams,
  403. VARIANT *pvarResult,
  404. EXCEPINFO *pexcepinfo,
  405. unsigned int *puArgErr
  406. )
  407. {
  408. void *pInterfacePtr = NULL;
  409. DISPID dispid = 0;
  410. DISPID typeinfoid = 0;
  411. ITypeInfo *pTypeInfo = NULL;
  412. HRESULT hr = S_OK;
  413. if (dispidMember <= 0) {
  414. //
  415. // One of the special DISPIDs.
  416. //
  417. // If we have an interface pointer for it, use that.
  418. // If we don't, and we have a base IDispatch pointer,
  419. // pass it to the base pointer's Invoke() method.
  420. // If we don't, and we don't have a base IDispatch pointer,
  421. // return failure.
  422. //
  423. dispid = dispidMember;
  424. switch (dispid) {
  425. case DISPID_VALUE:
  426. if (_pDispidValue) {
  427. pTypeInfo = (ITypeInfo *)_pDispidValue->ptypeinfo;
  428. pInterfacePtr = _pDispidValue->pInterfacePointer;
  429. }
  430. break;
  431. case DISPID_NEWENUM:
  432. if (_pDispidNewEnum) {
  433. pTypeInfo = (ITypeInfo *)_pDispidNewEnum->ptypeinfo;
  434. pInterfacePtr = _pDispidNewEnum->pInterfacePointer;
  435. }
  436. break;
  437. default:
  438. break;
  439. }
  440. if (!pInterfacePtr) {
  441. BAIL_ON_FAILURE(hr = DISP_E_MEMBERNOTFOUND);
  442. }else {
  443. //
  444. // Fill in the special case scenarios here
  445. //
  446. hr = DispInvoke(
  447. pInterfacePtr,
  448. pTypeInfo,
  449. dispid,
  450. wFlags,
  451. pdispparams,
  452. pvarResult,
  453. pexcepinfo,
  454. puArgErr
  455. );
  456. return(hr);
  457. }
  458. } else {
  459. //
  460. // A regular DISPID of ours.
  461. //
  462. typeinfoid = getTypeInfoId(dispidMember);
  463. dispid = getDispId(dispidMember);
  464. if ((_pPropertyCache == NULL) || (typeinfoid != _dwPropCacheID)) {
  465. pInterfacePtr = getInterfacePtr(typeinfoid);
  466. pTypeInfo = getTypeInfo(typeinfoid);
  467. if (!pTypeInfo)
  468. //
  469. // Shouldn't happen.
  470. //
  471. BAIL_ON_FAILURE(hr = DISP_E_MEMBERNOTFOUND);
  472. }
  473. if ((_pPropertyCache == NULL) || (typeinfoid != _dwPropCacheID)) {
  474. //
  475. // A regular interface.
  476. //
  477. hr = DispInvoke(
  478. pInterfacePtr,
  479. pTypeInfo,
  480. dispid,
  481. wFlags,
  482. pdispparams,
  483. pvarResult,
  484. pexcepinfo,
  485. puArgErr
  486. );
  487. }else {
  488. //
  489. // A "dynamic DISPID", for the property cache.
  490. //
  491. hr = DynamicDispidInvoke(
  492. _pPropertyCache,
  493. dispid,
  494. wFlags,
  495. pdispparams,
  496. pvarResult
  497. );
  498. }
  499. }
  500. error:
  501. return hr;
  502. }
  503. HRESULT
  504. DynamicDispidInvoke(
  505. IPropertyCache * pPropertyCache,
  506. DISPID dispid,
  507. unsigned short wFlags,
  508. DISPPARAMS *pdispparams,
  509. VARIANT * pvarResult
  510. )
  511. {
  512. HRESULT hr = S_OK;
  513. if (!pPropertyCache) {
  514. return(E_INVALIDARG);
  515. }
  516. if (wFlags & DISPATCH_PROPERTYGET) {
  517. if (!pvarResult) {
  518. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  519. }
  520. hr = pPropertyCache->getproperty((DWORD)dispid,pvarResult);
  521. if (FAILED(hr)) {
  522. #if 1
  523. // This lets us return S_OK and a VT_EMPTY variant if
  524. // there's no data. #if this out to disable it.
  525. V_VT(pvarResult) = VT_EMPTY;
  526. hr = S_OK;
  527. #else
  528. V_VT(pvarResult) = VT_ERROR;
  529. #endif
  530. }
  531. }else if (wFlags & DISPATCH_PROPERTYPUT) {
  532. if (pdispparams[0].cArgs != 1){
  533. hr = DISP_E_BADPARAMCOUNT;
  534. }
  535. else {
  536. hr = pPropertyCache->putproperty(
  537. (DWORD)dispid,
  538. pdispparams[0].rgvarg[0]
  539. );
  540. }
  541. }else {
  542. hr = E_INVALIDARG;
  543. }
  544. error:
  545. return(hr);
  546. }
  547. HRESULT
  548. CAggregatorDispMgr::MarkAsNewEnum(void *pTypeInfo)
  549. {
  550. PTYPEINFOENTRY pTypeInfoEntry;
  551. if (!pTypeInfo) {
  552. return E_FAIL;
  553. }
  554. if (!(pTypeInfoEntry = FindTypeInfo(pTypeInfo))) {
  555. return E_FAIL;
  556. }
  557. _pDispidNewEnum = pTypeInfoEntry;
  558. return S_OK;
  559. }
  560. HRESULT
  561. CAggregatorDispMgr::MarkAsItem(void *pTypeInfo)
  562. {
  563. PTYPEINFOENTRY pTypeInfoEntry;
  564. if (!pTypeInfo) {
  565. return E_FAIL;
  566. }
  567. if (!(pTypeInfoEntry = FindTypeInfo(pTypeInfo))) {
  568. return E_FAIL;
  569. }
  570. _pDispidValue = pTypeInfoEntry;
  571. return S_OK;
  572. }
  573. LONG
  574. CAggregatorDispMgr::gentypeinfoid()
  575. {
  576. //
  577. // This would mean we've registered 65536 IDispatch methods
  578. // in this object's dispatch manager. We lose.
  579. //
  580. AggregatorDispMgrAssert(_dwTypeInfoId < 0xffff);
  581. return (_dwTypeInfoId++);
  582. }
  583. ITypeInfo *
  584. FindTypeInfo(
  585. PTYPEINFO_TABLE pTypeInfoTable,
  586. REFIID iid
  587. )
  588. {
  589. PTYPEINFO_TABLE pTemp = NULL;
  590. pTemp = pTypeInfoTable;
  591. while (pTemp) {
  592. if (IsEqualIID(iid, pTemp->iid)) {
  593. return pTemp->pTypeInfo;
  594. }
  595. pTemp = pTemp->pNext;
  596. }
  597. return NULL;
  598. }
  599. PTYPEINFO_TABLE
  600. AddTypeInfo(
  601. PTYPEINFO_TABLE pTypeInfoTable,
  602. REFIID iid,
  603. ITypeInfo * pTypeInfo
  604. )
  605. {
  606. PTYPEINFO_TABLE pTemp = NULL;
  607. pTemp = (PTYPEINFO_TABLE)LocalAlloc(LPTR, sizeof(TYPEINFO_TABLE));
  608. if (!pTemp) {
  609. return NULL;
  610. }
  611. memcpy(&pTemp->iid, &iid, sizeof(GUID));
  612. pTemp->pTypeInfo = pTypeInfo;
  613. pTemp->pNext = pTypeInfoTable;
  614. return pTemp;
  615. }
  616. //+------------------------------------------------------------------------
  617. //
  618. // Function: LoadTypeInfo
  619. //
  620. // Synopsis: Loads a typeinfo from a registered typelib.
  621. //
  622. // Arguments: [clsidTL] -- TypeLib GUID
  623. // [clsidTI] -- TypeInfo GUID
  624. // [ppTI] -- Resulting typeInfo
  625. //
  626. // Returns: HRESULT
  627. //
  628. //-------------------------------------------------------------------------
  629. HRESULT
  630. LoadTypeInfo(CLSID clsidTL, CLSID clsidTI, LPTYPEINFO *ppTI)
  631. {
  632. HRESULT hr;
  633. ITypeLib * pTL;
  634. AggregatorDispMgrAssert(ppTI);
  635. *ppTI = NULL;
  636. hr = LoadRegTypeLib(clsidTL, 1, 0, LOCALE_SYSTEM_DEFAULT, &pTL);
  637. if (!SUCCEEDED(hr))
  638. return hr;
  639. hr = pTL->GetTypeInfoOfGuid(clsidTI, ppTI);
  640. pTL->Release();
  641. return hr;
  642. }
  643. HRESULT
  644. CAggregatorDispMgr::LoadTypeInfoEntry(
  645. REFIID libid,
  646. REFIID iid,
  647. void * pIntf,
  648. DISPID SpecialId
  649. )
  650. {
  651. ITypeInfo * pTypeInfo = NULL;
  652. HRESULT hr;
  653. ENTER_TYPEINFO_CRITSECT();
  654. pTypeInfo = ::FindTypeInfo(gpTypeInfoTable, iid);
  655. if (!pTypeInfo) {
  656. LEAVE_TYPEINFO_CRITSECT();
  657. hr = LoadTypeInfo(libid, iid, &pTypeInfo);
  658. BAIL_ON_FAILURE(hr);
  659. ENTER_TYPEINFO_CRITSECT();
  660. gpTypeInfoTable = ::AddTypeInfo(
  661. gpTypeInfoTable,
  662. iid,
  663. pTypeInfo
  664. );
  665. if (!gpTypeInfoTable) {
  666. LEAVE_TYPEINFO_CRITSECT();
  667. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  668. }
  669. //
  670. // Increment the global list of the types of type info's.
  671. //
  672. InterlockedIncrement(&glnTypesOfInfo);
  673. InterlockedIncrement(&glnObjCount);
  674. }
  675. pTypeInfo->AddRef();
  676. hr = AddTypeInfo(pTypeInfo, pIntf);
  677. if (FAILED(hr)) {
  678. LEAVE_TYPEINFO_CRITSECT();
  679. BAIL_ON_FAILURE(hr);
  680. }
  681. //
  682. // We have a ref on the object as add was succesful
  683. //
  684. InterlockedIncrement(&glnObjCount);
  685. LEAVE_TYPEINFO_CRITSECT();
  686. if (SpecialId == -4) {
  687. hr = MarkAsNewEnum(pTypeInfo);
  688. } else if (SpecialId == DISPID_VALUE) {
  689. hr = MarkAsItem(pTypeInfo);
  690. }
  691. return S_OK;
  692. error:
  693. if (pTypeInfo)
  694. pTypeInfo->Release();
  695. return hr;
  696. }
  697. //
  698. // Kept for backwards compatibility.
  699. //
  700. HRESULT
  701. LoadTypeInfoEntry(
  702. CAggregatorDispMgr *pDispMgr,
  703. REFIID libid,
  704. REFIID iid,
  705. void * pIntf,
  706. DISPID SpecialId
  707. )
  708. {
  709. return pDispMgr->LoadTypeInfoEntry(libid, iid, pIntf, SpecialId);
  710. }
  711. void
  712. FreeTypeInfoTable()
  713. {
  714. PTYPEINFO_TABLE pTypeInfoTable = NULL;
  715. PTYPEINFO_TABLE pTemp = NULL;
  716. ITypeInfo * pTypeInfo = NULL;
  717. pTypeInfoTable = gpTypeInfoTable;
  718. while (pTypeInfoTable) {
  719. pTypeInfo = pTypeInfoTable->pTypeInfo;
  720. pTypeInfo->Release();
  721. pTemp = pTypeInfoTable;
  722. pTypeInfoTable = pTypeInfoTable->pNext;
  723. LocalFree(pTemp);
  724. }
  725. gpTypeInfoTable = NULL;
  726. }
  727. BOOL
  728. AggregatorDllCanUnload()
  729. {
  730. BOOL retVal = FALSE;
  731. ENTER_TYPEINFO_CRITSECT();
  732. retVal = (glnTypesOfInfo == 0);
  733. LEAVE_TYPEINFO_CRITSECT();
  734. return retVal;
  735. }