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.

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