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.

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