oleconn.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFXCTL_CORE3_SEG
  12. #pragma code_seg(AFXCTL_CORE3_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. #define GetConnectionPtr(pTarget, pEntry) \
  20. (LPCONNECTIONPOINT)((char*)pTarget + pEntry->nOffset + \
  21. offsetof(CConnectionPoint, m_xConnPt))
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CConnectionPoint
  24. CConnectionPoint::CConnectionPoint() :
  25. m_pUnkFirstConnection(NULL),
  26. m_pConnections(NULL)
  27. {
  28. }
  29. CConnectionPoint::~CConnectionPoint()
  30. {
  31. POSITION pos = GetStartPosition();
  32. while (pos != NULL)
  33. {
  34. LPUNKNOWN pUnk = GetNextConnection(pos);
  35. ASSERT(pUnk != NULL);
  36. pUnk->Release();
  37. }
  38. if (m_pConnections != NULL)
  39. delete m_pConnections;
  40. }
  41. POSITION CConnectionPoint::GetStartPosition() const
  42. {
  43. ASSERT(m_pConnections == NULL || m_pUnkFirstConnection == NULL);
  44. if (m_pUnkFirstConnection != NULL)
  45. return (POSITION)-1;
  46. if (m_pConnections == NULL || m_pConnections->GetSize() == 0)
  47. return NULL;
  48. return (POSITION)1;
  49. }
  50. LPUNKNOWN CConnectionPoint::GetNextConnection(POSITION& pos) const
  51. {
  52. ASSERT(pos != NULL);
  53. if (pos == (POSITION)-1)
  54. {
  55. ASSERT(m_pUnkFirstConnection != NULL);
  56. ASSERT(m_pConnections == NULL);
  57. pos = NULL;
  58. return m_pUnkFirstConnection;
  59. }
  60. ASSERT(m_pConnections != NULL);
  61. ASSERT((long)pos > 0 && (long)pos <= m_pConnections->GetSize());
  62. int nIndex = (long)pos - 1;
  63. pos = (POSITION)((long)pos + 1);
  64. if ((long)pos > m_pConnections->GetSize())
  65. pos = NULL;
  66. return (LPUNKNOWN)m_pConnections->GetAt(nIndex);
  67. }
  68. const CPtrArray* CConnectionPoint::GetConnections()
  69. {
  70. ASSERT_VALID(this);
  71. if (m_pConnections == NULL)
  72. CreateConnectionArray();
  73. ASSERT(m_pConnections != NULL);
  74. return m_pConnections;
  75. }
  76. void CConnectionPoint::OnAdvise(BOOL)
  77. {
  78. ASSERT_VALID(this);
  79. }
  80. int CConnectionPoint::GetMaxConnections()
  81. {
  82. ASSERT_VALID(this);
  83. // May be overridden by subclass.
  84. return -1;
  85. }
  86. LPCONNECTIONPOINTCONTAINER CConnectionPoint::GetContainer()
  87. {
  88. CCmdTarget* pCmdTarget = (CCmdTarget*)((BYTE*)this - m_nOffset);
  89. #ifdef _DEBUG
  90. pCmdTarget->CCmdTarget::AssertValid();
  91. #endif
  92. LPCONNECTIONPOINTCONTAINER pCPC = NULL;
  93. if (SUCCEEDED((HRESULT)pCmdTarget->ExternalQueryInterface(
  94. &IID_IConnectionPointContainer, (LPVOID*)&pCPC)))
  95. {
  96. ASSERT(pCPC != NULL);
  97. }
  98. return pCPC;
  99. }
  100. void CConnectionPoint::CreateConnectionArray()
  101. {
  102. ASSERT(m_pConnections == NULL);
  103. m_pConnections = new CPtrArray;
  104. if (m_pUnkFirstConnection != NULL)
  105. {
  106. m_pConnections->Add(m_pUnkFirstConnection);
  107. m_pUnkFirstConnection = NULL;
  108. }
  109. ASSERT(m_pConnections != NULL);
  110. ASSERT(m_pUnkFirstConnection == NULL);
  111. }
  112. int CConnectionPoint::GetConnectionCount()
  113. {
  114. if (m_pUnkFirstConnection != NULL)
  115. return 1;
  116. if (m_pConnections == NULL)
  117. return 0;
  118. return m_pConnections->GetSize();
  119. }
  120. LPUNKNOWN CConnectionPoint::QuerySinkInterface(LPUNKNOWN pUnkSink)
  121. {
  122. LPUNKNOWN pUnkReturn = NULL;
  123. pUnkSink->QueryInterface(GetIID(), reinterpret_cast<void**>(&pUnkReturn));
  124. return pUnkReturn;
  125. }
  126. STDMETHODIMP_(ULONG) CConnectionPoint::XConnPt::Release()
  127. {
  128. METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
  129. return (ULONG)pThis->InternalRelease();
  130. }
  131. STDMETHODIMP_(ULONG) CConnectionPoint::XConnPt::AddRef()
  132. {
  133. METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
  134. return (ULONG)pThis->InternalAddRef();
  135. }
  136. STDMETHODIMP CConnectionPoint::XConnPt::QueryInterface(
  137. REFIID iid, LPVOID* ppvObj)
  138. {
  139. METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
  140. ASSERT(AfxIsValidAddress(ppvObj, sizeof(LPVOID), FALSE));
  141. if (IsEqualIID(iid, IID_IUnknown) ||
  142. IsEqualIID(iid, IID_IConnectionPoint))
  143. {
  144. *ppvObj = this;
  145. AddRef();
  146. return S_OK;
  147. }
  148. return E_NOINTERFACE;
  149. }
  150. STDMETHODIMP CConnectionPoint::XConnPt::GetConnectionInterface(IID* pIID)
  151. {
  152. METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
  153. ASSERT(AfxIsValidAddress(pIID, sizeof(IID)));
  154. *pIID = pThis->GetIID();
  155. return S_OK;
  156. }
  157. STDMETHODIMP CConnectionPoint::XConnPt::GetConnectionPointContainer(
  158. IConnectionPointContainer** ppCPC)
  159. {
  160. METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
  161. ASSERT(AfxIsValidAddress(ppCPC, sizeof(LPCONNECTIONPOINT)));
  162. if ((*ppCPC = pThis->GetContainer()) != NULL)
  163. return S_OK;
  164. return E_FAIL;
  165. }
  166. STDMETHODIMP CConnectionPoint::XConnPt::Advise(
  167. LPUNKNOWN pUnkSink, DWORD* pdwCookie)
  168. {
  169. METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
  170. ASSERT(AfxIsValidAddress(pUnkSink, sizeof(IUnknown), FALSE));
  171. ASSERT((pdwCookie == NULL) || AfxIsValidAddress(pdwCookie, sizeof(DWORD)));
  172. if (pUnkSink == NULL)
  173. return E_POINTER;
  174. LPUNKNOWN lpInterface;
  175. int cMaxConn = pThis->GetMaxConnections();
  176. if ((cMaxConn >= 0) && (pThis->GetConnectionCount() == cMaxConn))
  177. {
  178. return CONNECT_E_ADVISELIMIT;
  179. }
  180. if ((lpInterface = pThis->QuerySinkInterface(pUnkSink)) != NULL)
  181. {
  182. if (pThis->m_pUnkFirstConnection == NULL &&
  183. pThis->m_pConnections == NULL)
  184. {
  185. pThis->m_pUnkFirstConnection = lpInterface;
  186. }
  187. else
  188. {
  189. if (pThis->m_pConnections == NULL)
  190. pThis->CreateConnectionArray();
  191. pThis->m_pConnections->Add(lpInterface);
  192. }
  193. pThis->OnAdvise(TRUE);
  194. if (pdwCookie != NULL)
  195. *pdwCookie = (DWORD)lpInterface;
  196. return S_OK;
  197. }
  198. return E_NOINTERFACE;
  199. }
  200. STDMETHODIMP CConnectionPoint::XConnPt::Unadvise(DWORD dwCookie)
  201. {
  202. METHOD_PROLOGUE_EX_(CConnectionPoint, ConnPt)
  203. if (pThis->m_pUnkFirstConnection != NULL)
  204. {
  205. if ((DWORD)pThis->m_pUnkFirstConnection == dwCookie)
  206. {
  207. pThis->m_pUnkFirstConnection->Release();
  208. pThis->m_pUnkFirstConnection = NULL;
  209. pThis->OnAdvise(FALSE);
  210. return S_OK;
  211. }
  212. else
  213. {
  214. return CONNECT_E_NOCONNECTION;
  215. }
  216. }
  217. if (pThis->m_pConnections == NULL)
  218. return CONNECT_E_NOCONNECTION;
  219. LPUNKNOWN pUnkSink;
  220. int cConnections = pThis->m_pConnections->GetSize();
  221. for (int i = 0; i < cConnections; i++)
  222. {
  223. pUnkSink = (LPUNKNOWN)(pThis->m_pConnections->GetAt(i));
  224. if ((DWORD)pUnkSink == dwCookie)
  225. {
  226. pUnkSink->Release();
  227. pThis->m_pConnections->RemoveAt(i);
  228. pThis->OnAdvise(FALSE);
  229. return S_OK;
  230. }
  231. }
  232. return CONNECT_E_NOCONNECTION;
  233. }
  234. /////////////////////////////////////////////////////////////////////////////
  235. // CEnumConnections
  236. class CEnumConnections : public CEnumArray
  237. {
  238. public:
  239. CEnumConnections(const void* pvEnum, UINT nSize);
  240. ~CEnumConnections();
  241. void AddConnection(CONNECTDATA* pConn);
  242. protected:
  243. virtual BOOL OnNext(void* pv);
  244. virtual CEnumArray* OnClone();
  245. UINT m_nMaxSize; // number of items allocated (>= m_nSize)
  246. DECLARE_INTERFACE_MAP()
  247. };
  248. BEGIN_INTERFACE_MAP(CEnumConnections, CEnumArray)
  249. INTERFACE_PART(CEnumConnections, IID_IEnumConnections, EnumVOID)
  250. END_INTERFACE_MAP()
  251. CEnumConnections::CEnumConnections(const void* pvEnum, UINT nSize) :
  252. CEnumArray(sizeof(CONNECTDATA), pvEnum, nSize, TRUE)
  253. {
  254. m_nMaxSize = 0;
  255. }
  256. CEnumConnections::~CEnumConnections()
  257. {
  258. if (m_pClonedFrom == NULL)
  259. {
  260. UINT iCP;
  261. CONNECTDATA* ppCP = (CONNECTDATA*)(VOID *)m_pvEnum;
  262. for (iCP = 0; iCP < m_nSize; iCP++)
  263. RELEASE(ppCP[iCP].pUnk);
  264. }
  265. // destructor will free the actual array (if it was not a clone)
  266. }
  267. BOOL CEnumConnections::OnNext(void* pv)
  268. {
  269. if (!CEnumArray::OnNext(pv))
  270. return FALSE;
  271. // outgoing connection point needs to be AddRef'ed
  272. // (the caller has responsibility to release it)
  273. ((CONNECTDATA*)pv)->pUnk->AddRef();
  274. return TRUE;
  275. }
  276. CEnumArray* CEnumConnections::OnClone()
  277. {
  278. ASSERT_VALID(this);
  279. CEnumConnections* pClone;
  280. pClone = new CEnumConnections(m_pvEnum, m_nSize);
  281. pClone->m_bNeedFree = FALSE;
  282. ASSERT(pClone != NULL);
  283. ASSERT(!pClone->m_bNeedFree); // clones should never free themselves
  284. pClone->m_nCurPos = m_nCurPos;
  285. // finally, return the clone to OLE
  286. ASSERT_VALID(pClone);
  287. return pClone;
  288. }
  289. void CEnumConnections::AddConnection(CONNECTDATA* pConn)
  290. {
  291. ASSERT(m_nSize <= m_nMaxSize);
  292. if (m_nSize == m_nMaxSize)
  293. {
  294. // not enough space for new item -- allocate more
  295. CONNECTDATA* pListNew = new CONNECTDATA[m_nSize+2];
  296. m_nMaxSize += 2;
  297. if (m_nSize > 0)
  298. memcpy(pListNew, m_pvEnum, m_nSize*sizeof(CONNECTDATA));
  299. delete m_pvEnum;
  300. #ifdef _WIN32
  301. m_pvEnum = (BYTE*)pListNew;
  302. #else
  303. m_pvEnum = (char*)pListNew;
  304. #endif
  305. }
  306. // add this item to the list
  307. ASSERT(m_nSize < m_nMaxSize);
  308. ((CONNECTDATA*)m_pvEnum)[m_nSize] = *pConn;
  309. pConn->pUnk->AddRef();
  310. ++m_nSize;
  311. }
  312. STDMETHODIMP CConnectionPoint::XConnPt::EnumConnections(LPENUMCONNECTIONS* ppEnum)
  313. {
  314. METHOD_PROLOGUE_EX(CConnectionPoint, ConnPt)
  315. CEnumConnections* pEnum = NULL;
  316. CONNECTDATA cd;
  317. TRY
  318. {
  319. pEnum = new CEnumConnections(NULL, 0);
  320. if (pThis->m_pUnkFirstConnection != NULL)
  321. {
  322. cd.pUnk = pThis->m_pUnkFirstConnection;
  323. cd.dwCookie = (DWORD)cd.pUnk;
  324. pEnum->AddConnection(&cd);
  325. }
  326. if (pThis->m_pConnections != NULL)
  327. {
  328. int cConnections = pThis->m_pConnections->GetSize();
  329. for (int i = 0; i < cConnections; i++)
  330. {
  331. cd.pUnk = (LPUNKNOWN)(pThis->m_pConnections->GetAt(i));
  332. cd.dwCookie = (DWORD)cd.pUnk;
  333. pEnum->AddConnection(&cd);
  334. }
  335. }
  336. }
  337. CATCH (CException, e)
  338. {
  339. delete pEnum;
  340. pEnum = NULL;
  341. }
  342. END_CATCH
  343. if (pEnum != NULL)
  344. {
  345. // create and return the IEnumConnectionPoints object
  346. *ppEnum = (IEnumConnections*)&pEnum->m_xEnumVOID;
  347. }
  348. else
  349. {
  350. // no connections: return NULL
  351. *ppEnum = NULL;
  352. }
  353. return (pEnum != NULL) ? S_OK : E_OUTOFMEMORY;
  354. }
  355. /////////////////////////////////////////////////////////////////////////////
  356. // CEnumConnPoints
  357. class CEnumConnPoints : public CEnumArray
  358. {
  359. public:
  360. CEnumConnPoints(const void* pvEnum, UINT nSize);
  361. ~CEnumConnPoints();
  362. void AddConnPoint(LPCONNECTIONPOINT pConnPt);
  363. protected:
  364. virtual BOOL OnNext(void* pv);
  365. UINT m_nMaxSize; // number of items allocated (>= m_nSize)
  366. DECLARE_INTERFACE_MAP()
  367. };
  368. BEGIN_INTERFACE_MAP(CEnumConnPoints, CEnumArray)
  369. INTERFACE_PART(CEnumConnPoints, IID_IEnumConnectionPoints, EnumVOID)
  370. END_INTERFACE_MAP()
  371. CEnumConnPoints::CEnumConnPoints(const void* pvEnum, UINT nSize) :
  372. CEnumArray(sizeof(LPCONNECTIONPOINT), pvEnum, nSize, TRUE)
  373. {
  374. m_nMaxSize = 0;
  375. }
  376. CEnumConnPoints::~CEnumConnPoints()
  377. {
  378. if (m_pClonedFrom == NULL)
  379. {
  380. UINT iCP;
  381. LPCONNECTIONPOINT* ppCP =
  382. (LPCONNECTIONPOINT*)(VOID *)m_pvEnum;
  383. for (iCP = 0; iCP < m_nSize; iCP++)
  384. RELEASE(ppCP[iCP]);
  385. }
  386. // destructor will free the actual array (if it was not a clone)
  387. }
  388. BOOL CEnumConnPoints::OnNext(void* pv)
  389. {
  390. if (!CEnumArray::OnNext(pv))
  391. return FALSE;
  392. // outgoing connection point needs to be AddRef'ed
  393. // (the caller has responsibility to release it)
  394. (*(LPCONNECTIONPOINT*)pv)->AddRef();
  395. return TRUE;
  396. }
  397. void CEnumConnPoints::AddConnPoint(LPCONNECTIONPOINT pConnPt)
  398. {
  399. ASSERT(m_nSize <= m_nMaxSize);
  400. if (m_nSize == m_nMaxSize)
  401. {
  402. // not enough space for new item -- allocate more
  403. LPCONNECTIONPOINT* pListNew = new LPCONNECTIONPOINT[m_nSize+2];
  404. m_nMaxSize += 2;
  405. if (m_nSize > 0)
  406. memcpy(pListNew, m_pvEnum, m_nSize*sizeof(LPCONNECTIONPOINT));
  407. delete m_pvEnum;
  408. #ifdef _WIN32
  409. m_pvEnum = (BYTE*)pListNew;
  410. #else
  411. m_pvEnum = (char*)pListNew;
  412. #endif
  413. }
  414. // add this item to the list
  415. ASSERT(m_nSize < m_nMaxSize);
  416. ((LPCONNECTIONPOINT*)m_pvEnum)[m_nSize] = pConnPt;
  417. pConnPt->AddRef();
  418. ++m_nSize;
  419. }
  420. /////////////////////////////////////////////////////////////////////////////
  421. // COleConnPtContainer
  422. class COleConnPtContainer : public IConnectionPointContainer
  423. {
  424. public:
  425. #ifndef _AFX_NO_NESTED_DERIVATION
  426. // required for METHOD_PROLOGUE_EX
  427. size_t m_nOffset;
  428. COleConnPtContainer::COleConnPtContainer()
  429. { m_nOffset = offsetof(CCmdTarget, m_xConnPtContainer); }
  430. #endif
  431. STDMETHOD_(ULONG, AddRef)();
  432. STDMETHOD_(ULONG, Release)();
  433. STDMETHOD(QueryInterface)(REFIID, LPVOID*);
  434. STDMETHOD(EnumConnectionPoints)(LPENUMCONNECTIONPOINTS* ppEnum);
  435. STDMETHOD(FindConnectionPoint)(REFIID iid, LPCONNECTIONPOINT* ppCP);
  436. };
  437. STDMETHODIMP_(ULONG) COleConnPtContainer::AddRef()
  438. {
  439. METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
  440. return (ULONG)pThis->ExternalAddRef();
  441. }
  442. STDMETHODIMP_(ULONG) COleConnPtContainer::Release()
  443. {
  444. METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
  445. return (ULONG)pThis->ExternalRelease();
  446. }
  447. STDMETHODIMP COleConnPtContainer::QueryInterface(
  448. REFIID iid, LPVOID* ppvObj)
  449. {
  450. METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
  451. return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  452. }
  453. STDMETHODIMP COleConnPtContainer::EnumConnectionPoints(
  454. LPENUMCONNECTIONPOINTS* ppEnum)
  455. {
  456. METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
  457. CEnumConnPoints* pEnum = NULL;
  458. TRY
  459. {
  460. pEnum = new CEnumConnPoints(NULL, 0);
  461. // Add connection points that aren't in the connection map
  462. CPtrArray ptrArray;
  463. if (pThis->GetExtraConnectionPoints(&ptrArray))
  464. {
  465. for (int i = 0; i < ptrArray.GetSize(); i++)
  466. pEnum->AddConnPoint((LPCONNECTIONPOINT)ptrArray.GetAt(i));
  467. }
  468. // walk the chain of connection maps
  469. const AFX_CONNECTIONMAP* pMap = pThis->GetConnectionMap();
  470. const AFX_CONNECTIONMAP_ENTRY* pEntry;
  471. while (pMap != NULL)
  472. {
  473. pEntry = pMap->pEntry;
  474. while (pEntry->piid != NULL)
  475. {
  476. pEnum->AddConnPoint(GetConnectionPtr(pThis, pEntry));
  477. ++pEntry;
  478. }
  479. #ifdef _AFXDLL
  480. pMap = (*pMap->pfnGetBaseMap)();
  481. #else
  482. pMap = pMap->pBaseMap;
  483. #endif
  484. }
  485. }
  486. CATCH (CException, e)
  487. {
  488. delete pEnum;
  489. pEnum = NULL;
  490. }
  491. END_CATCH
  492. if (pEnum != NULL)
  493. {
  494. // create and return the IEnumConnectionPoints object
  495. *ppEnum = (IEnumConnectionPoints*)&pEnum->m_xEnumVOID;
  496. }
  497. else
  498. {
  499. // no connection points: return NULL
  500. *ppEnum = NULL;
  501. }
  502. return (pEnum != NULL) ? S_OK : CONNECT_E_NOCONNECTION;
  503. }
  504. STDMETHODIMP COleConnPtContainer::FindConnectionPoint(
  505. REFIID iid, LPCONNECTIONPOINT* ppCP)
  506. {
  507. METHOD_PROLOGUE_EX_(CCmdTarget, ConnPtContainer)
  508. ASSERT(ppCP != NULL);
  509. if ((*ppCP = pThis->GetConnectionHook(iid)) != NULL)
  510. {
  511. (*ppCP)->AddRef();
  512. return S_OK;
  513. }
  514. const AFX_CONNECTIONMAP* pMap = pThis->GetConnectionMap();
  515. const AFX_CONNECTIONMAP_ENTRY* pEntry;
  516. while (pMap != NULL)
  517. {
  518. pEntry = pMap->pEntry;
  519. while (pEntry->piid != NULL)
  520. {
  521. if (IsEqualIID(iid, *(IID*)(pEntry->piid)))
  522. {
  523. *ppCP = GetConnectionPtr(pThis, pEntry);
  524. (*ppCP)->AddRef();
  525. return S_OK;
  526. }
  527. ++pEntry;
  528. }
  529. #ifdef _AFXDLL
  530. pMap = (*pMap->pfnGetBaseMap)();
  531. #else
  532. pMap = pMap->pBaseMap;
  533. #endif
  534. }
  535. return E_NOINTERFACE;
  536. }
  537. /////////////////////////////////////////////////////////////////////////////
  538. // Wiring CCmdTarget to COleConnPtContainer
  539. // enable this object for OLE connections, called from derived class ctor
  540. void CCmdTarget::EnableConnections()
  541. {
  542. ASSERT(GetConnectionMap() != NULL); // must have DECLARE_DISPATCH_MAP
  543. // construct an COleConnPtContainer instance just to get to the vtable
  544. COleConnPtContainer cpc;
  545. // vtable pointer should be already set to same or NULL
  546. ASSERT(m_xConnPtContainer.m_vtbl == NULL||
  547. *(DWORD*)&cpc == m_xConnPtContainer.m_vtbl);
  548. // verify that sizes match
  549. ASSERT(sizeof(m_xConnPtContainer) == sizeof(COleConnPtContainer));
  550. // copy the vtable (and other data) to make sure it is initialized
  551. m_xConnPtContainer.m_vtbl = *(DWORD*)&cpc;
  552. *(COleConnPtContainer*)&m_xConnPtContainer = cpc;
  553. }
  554. /////////////////////////////////////////////////////////////////////////////
  555. // Force any extra compiler-generated code into AFX_INIT_SEG
  556. #ifdef AFX_INIT_SEG
  557. #pragma code_seg(AFX_INIT_SEG)
  558. #endif