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.

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