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.

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