home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / BOCOLE.PAK / BCONNPNT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  21.9 KB  |  759 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.8  $
  6. //
  7. //  Bolero helper for Connection Points  
  8. //
  9. //    BEventClass is the base implementation for Connection Point.  
  10. //    BEventClass deals with sinks collection and with Advise and   
  11. //    Unadvise member functions.                                    
  12. //    BEventClass keeps also a collection of void pointers which are
  13. //    those resulted from QueryInterface on sinks. Control implementors 
  14. //    can ask for this list.                                      
  15. //----------------------------------------------------------------------------
  16. #ifndef _BCONNPNT_H
  17. #include "BConnPnt.h"
  18. #endif
  19.  
  20.  
  21. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  22. // //\\//\\//\\//\\//\\//\\//\\//\\\  \\
  23. // // //\\//\\//\\//\\//\\//\\\\  \\  \\
  24. // // //  BEventHandler class \\  \\  \\
  25.  
  26. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  27. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  28. //      BEventHandler::BEventHandler costructor
  29. //
  30. //      Parameters:
  31. //        REFIID        interface IID for the specific Connection Point,
  32. //                      used by QueryInterface on Advise()
  33. //        LPUNKNOWN     pointer back to the ConnectionPointContainer.
  34. //                      IUnknown is used here becouse of possible aggregation
  35. //        UINT          default size for the two arrays of sinks
  36. //
  37. BEventHandler::BEventHandler (REFIID iid, LPUNKNOWN pCPC, UINT size) :
  38.                                 EventIID (iid),   cRef (0)
  39. {
  40.   // allocate sink list
  41.   pSinkList = new BSinkList (size);
  42.   if (pSinkList) {
  43.     pSinkList->AddRef();
  44.     // save ConnectionPointContainer
  45.     // don't AddRef since this guy owns us
  46.     pBackToCPC = pCPC;
  47.   }
  48. }
  49.  
  50.  
  51. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  52. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  53. //      BEventHandler::~BEventHandler destructor
  54. //
  55. BEventHandler::~BEventHandler()
  56. {
  57.   if (pSinkList)
  58.     pSinkList->Release();
  59.  
  60.   //if (pBackToCPC)
  61.   //  pBackToCPC->Release();
  62. }
  63.  
  64. //\\// IUnknown methods \\//\\
  65.  
  66. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  67. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  68. //      BEventHandler::AddRef
  69. //
  70. //      Purpose:
  71. //        Increment the reference count of "this"
  72. //
  73. //      Return Value:
  74. //        ULONG         new RefCount value
  75. //
  76. ULONG _IFUNC BEventHandler::AddRef ()
  77. {
  78.   return ++cRef;
  79. }
  80.  
  81. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  82. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  83. //      BEventHandler::Release
  84. //
  85. //      Purpose:
  86. //        Decrement the reference count of "this". Delete the object if
  87. //        RefCount is 0
  88. //
  89. //      Return Value:
  90. //        ULONG         new RefCount value
  91. //
  92. ULONG _IFUNC BEventHandler::Release ()
  93. {
  94.   DWORD tempRef = --cRef;
  95.  
  96.   if (!cRef)
  97.     delete this;
  98.  
  99.   return tempRef;
  100. }
  101.  
  102.  
  103. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  104. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  105. //      BEventHandler::QueryInterface
  106. //
  107. //      Purpose:
  108. //        Return all visible interfaces from this object
  109. //
  110. //      Return Value:
  111. //        HRESULT
  112. //
  113. HRESULT _IFUNC BEventHandler::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  114. {
  115.   HRESULT hr = NOERROR;
  116.   *ppv = NULL;
  117.  
  118.   // interfaces
  119.   if (SUCCEEDED(hr = IBEventClass_QueryInterface (this, iid, ppv))) {
  120.   }
  121.   else if (SUCCEEDED (hr = IConnectionPoint_QueryInterface (this, iid, ppv))) {
  122.   }
  123.   else if (SUCCEEDED (hr = pSinkList->QueryInterface (iid, ppv))) {
  124.   }
  125.   else if (iid == IID_IUnknown) {
  126.      (BEventHandler *)*ppv = this;
  127.      AddRef();
  128.      return NOERROR;
  129.   }
  130.  
  131.   return hr;
  132. }
  133.  
  134. //\\// IBEventClass methods \\//\\
  135.  
  136.  
  137. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  138. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  139. //      BEventHandler::GetSinkList
  140. //
  141. //      Purpose:
  142. //        Return the list of sinks which contains the cached interface
  143. //        for event firing. Called from the main Control object to
  144. //        satisfy a request on GetSinkListForIID()
  145. //
  146. //      Parameters:
  147. //        IBSinkList**      a pointer where to return the list
  148. //
  149. //      Return Value:
  150. //        HRESULT
  151. //
  152. HRESULT _IFUNC BEventHandler::GetSinkList (IBSinkList** ppSinkList)
  153. {
  154.   HRESULT hr = NOERROR;
  155.  
  156.   if (ppSinkList) {
  157.     *ppSinkList = pSinkList;
  158.     pSinkList->AddRef(); //\\//\\
  159.   }
  160.   else
  161.     hr = ResultFromScode (E_INVALIDARG);
  162.  
  163.   return hr;
  164. }
  165.  
  166. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  167. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  168. // BEventHandler::FreezeEvents
  169. //
  170. //    Purpose:
  171. //        Called in response to FreezeEvents (IOleControl) this function sets
  172. //        a flag so that NextSink or GetSinkAt will fail and no events can
  173. //         be fired
  174. //
  175. HRESULT _IFUNC BEventHandler::FreezeEvents (bool fFreeze)
  176. {
  177.     if (pSinkList)  {
  178.         pSinkList->SetFreeze (fFreeze);
  179.     return NOERROR;
  180.     }
  181.   else 
  182.     return ResultFromScode (E_UNEXPECTED);
  183. }    
  184.  
  185.  
  186. //\\// IConnectionPoint methods \\//\\
  187.  
  188.  
  189. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  190. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  191. //      BEventHandler::GetConnectionInterface
  192. //
  193. //      Purpose:
  194. //        Answer what IID is supported from this specific IConnectionPoint
  195. //
  196. //      Parameters:
  197. //        IID FAR*      point to where the IID is returned
  198. //
  199. //      Return Value:
  200. //        HRESULT
  201. //
  202. HRESULT _IFUNC BEventHandler::GetConnectionInterface (IID FAR* iid)
  203. {
  204.   if (iid) {
  205.     *iid = EventIID;
  206.     return NOERROR;
  207.   }
  208.   else
  209.     return ResultFromScode (E_INVALIDARG);
  210. }
  211.  
  212.  
  213. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  214. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  215. //      BEventHandler::GetConnectionPointContainer
  216. //
  217. //      Purpose:
  218. //        Here we have a pointer back to the ConnectionPointContainer, in case
  219. //        user does not want to keep a couple of pointer but want to navigate
  220. //        through interfaces
  221. //
  222. //      Parameters:
  223. //        LPCONNECTIONPOINTCONTAINER FAR*   point to where CPC is stored (passed back)
  224. //
  225. //      Return Value:
  226. //        HRESULT
  227. //
  228. HRESULT _IFUNC BEventHandler::GetConnectionPointContainer (LPCONNECTIONPOINTCONTAINER FAR* ppCPC)
  229. {
  230.   if (ppCPC)
  231.     // this is because of aggregation! The object which is aggregating us could
  232.     // have a different connection point container
  233.     return pBackToCPC->QueryInterface (IID_IConnectionPointContainer, (LPVOID FAR*)ppCPC);
  234.   else
  235.     return ResultFromScode (E_INVALIDARG);
  236. }
  237.  
  238.  
  239. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  240. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  241. //      BEventHandler::Advise
  242. //
  243. //      Purpose:
  244. //        This is the main function for ConnectionPoint. With this function
  245. //        a client of this control can connect event handler (sinks)
  246. //
  247. //      Parameters:
  248. //        LPUNKNOWN           the sink passed in. We QueryInterface this
  249. //                  object to see if it really implemente the interface
  250. //                  we want to talk with. If so we cache that interface
  251. //                  pointer
  252. //        DWORD FAR*          user refers to this specific location in the ConnectionPoint
  253. //                  with a DWORD we return here. This "cookie" will be used
  254. //                  later to disconnect the sink
  255. //
  256. //      Return Value:
  257. //        HRESULT
  258. //
  259. HRESULT _IFUNC BEventHandler::Advise (LPUNKNOWN pUnkSink, DWORD FAR* pdwCookie)
  260. {
  261.   HRESULT hr = NOERROR;
  262.  
  263.   if (pUnkSink && pdwCookie) { // check if values passed in are valid
  264.     int nInsPos;
  265.     for (nInsPos=0; nInsPos < pSinkList->Size() && (*pSinkList)[nInsPos]; nInsPos++); // get insert position
  266.  
  267.     *pdwCookie = 0;
  268.  
  269.     if (nInsPos < pSinkList->Size() || pSinkList->Expand()) {
  270.       LPUNKNOWN pObj; // passed to QueryInterface
  271.  
  272.       if (SUCCEEDED(hr = pUnkSink->QueryInterface(EventIID, (LPVOID FAR*)&pObj))) {
  273.         pSinkList->SetSinkAt (pUnkSink, pObj, nInsPos); // pass interfaces pointer to the list object
  274.         *pdwCookie = nInsPos + 1; // cookie will be position into the array + 1 (0 is error)
  275.       }
  276.     }
  277.     else
  278.       hr = ResultFromScode(E_OUTOFMEMORY);
  279.   }
  280.   else
  281.     hr = ResultFromScode(E_INVALIDARG);
  282.  
  283.   return hr;
  284. }
  285.  
  286.  
  287. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  288. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  289. //      BEventHandler::Unadvise
  290. //
  291. //      Purpose:
  292. //        Disconnect a previous connected (Advise) sink
  293. //
  294. //      Parameters:
  295. //        DWORD         this is the cookie value to get the sink (sort of sink ID)
  296. //
  297. //      Return Value:
  298. //        HRESULT
  299. //
  300. HRESULT _IFUNC BEventHandler::Unadvise (DWORD dwCookie)
  301. {
  302.   HRESULT hr = NOERROR;
  303.  
  304.   if (--dwCookie > pSinkList->Size() || !(*pSinkList)[dwCookie])
  305.     hr = ResultFromScode (E_INVALIDARG);
  306.   else
  307.     pSinkList->DeleteSinkAt (dwCookie); // inform the list to release interfaces
  308.  
  309.   return hr;
  310. }
  311.  
  312.  
  313. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  314. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  315. //      BEventHandler::EnumConnections
  316. //
  317. //      Purpose:
  318. //        return an Enumeration of connections
  319. //
  320. //      Parameters:
  321. //        LPENUMCONNECTIONS FAR*    point to where the list of connection is stored
  322. //
  323. //      Return Value:
  324. //        HRESULT
  325. //
  326. HRESULT _IFUNC BEventHandler::EnumConnections (LPENUMCONNECTIONS FAR* ppEnum)
  327. {
  328.   *ppEnum = (LPENUMCONNECTIONS)pSinkList;
  329.   (*ppEnum)->AddRef(); //\\//\\
  330.   return NOERROR;
  331. }
  332.  
  333. //\\//\\//\\//\\//\\//\\//\\//\\\\
  334. // //\\//\\//\\//\\//\\//\\//\\ \\
  335. // // //\\//\\//\\//\\//\\\\ \\ \\
  336. // // //  BSinkList class \\ \\ \\
  337.  
  338. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  339. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  340. //
  341. //      BSinkList::BSinkList constructor
  342. //
  343. //      Parameters:
  344. //        UINT        default size for arrays in this object
  345. //
  346. BEventHandler::BSinkList::BSinkList (UINT size):
  347.                         nCurrPos (0),
  348.                         nSize (size),
  349.                         cRef (0),
  350.                                                 fFreeze (false)
  351. {
  352.   pUnkList = (LPUNKNOWN FAR*) new char[sizeof(LPUNKNOWN) * nSize];
  353.   pDirectList = (LPVOID FAR*) new char[sizeof(LPVOID) * nSize];
  354.  
  355.   memset (pUnkList, 0, sizeof(LPUNKNOWN) * nSize);
  356.   memset (pDirectList, 0, sizeof(LPVOID) * nSize);
  357. }
  358.  
  359.  
  360. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  361. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  362. //      BSinkList::~BSinkList destructor
  363. //
  364. BEventHandler::BSinkList::~BSinkList()
  365. {
  366.   for (int i = 0; i < nSize; i++) {
  367.     if (pUnkList[i]) {
  368.       pUnkList[i]->Release();
  369.       ((IUnknown*)(pDirectList[i]))->Release();
  370.     }
  371.   }
  372.  
  373.   delete [] pUnkList;
  374.   delete [] pDirectList;
  375. }
  376.  
  377. //\\// IUnknown \\//\\
  378.  
  379. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  380. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  381. //      BEventHandler::AddRef
  382. //
  383. //      Purpose:
  384. //        Increment the reference count of "this"
  385. //
  386. //      Return Value:
  387. //        ULONG         new RefCount value
  388. //
  389. ULONG _IFUNC BEventHandler::BSinkList::AddRef ()
  390. {
  391.   return ++cRef;
  392. }
  393.  
  394. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  395. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  396. //      BEventHandler::Release
  397. //
  398. //      Purpose:
  399. //        Decrement the reference count of "this". Delete the object if
  400. //        RefCount is 0
  401. //
  402. //      Return Value:
  403. //        ULONG         new RefCount value
  404. //
  405. ULONG _IFUNC BEventHandler::BSinkList::Release ()
  406. {
  407.   DWORD tempRef = --cRef;
  408.  
  409.   if (!cRef)
  410.     delete this;
  411.  
  412.   return tempRef;
  413. }
  414.  
  415. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  416. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  417. //      BEventHandler::QueryInterface
  418. //
  419. //      Purpose:
  420. //        Return all visible interfaces from this object
  421. //
  422. //      Return Value:
  423. //        HRESULT
  424. //
  425. HRESULT _IFUNC BEventHandler::BSinkList::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  426. {
  427.   HRESULT hr = NOERROR;
  428.   *ppv = NULL;
  429.  
  430.   if (SUCCEEDED(hr = IBSinkList_QueryInterface (this, iid, ppv))) {
  431.   }
  432.   else if (SUCCEEDED (hr = IEnumConnections_QueryInterface (this, iid, ppv))) {
  433.   }
  434.   else if (iid == IID_IUnknown) {
  435.      (BSinkList *)*ppv = this;
  436.      AddRef();
  437.      return NOERROR;
  438.   }
  439.   return hr;
  440. }
  441.  
  442. //\\// IBSinkList methods \\//\\
  443.  
  444. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  445. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  446. //      BSinkList::NextSink
  447. //
  448. //      Purpose:
  449. //        Answer the next sink object. Gives you the illusion to work
  450. //        on a linked list.
  451. //
  452. //      Parameters:
  453. //        LPVOID FAR*           point to where the next sink will be returned
  454. //
  455. //      Return Value:
  456. //        HRESULT
  457. //
  458. HRESULT _IFUNC BEventHandler::BSinkList::NextSink (LPVOID FAR* ppObj)
  459. {
  460.   HRESULT hr = ResultFromScode (E_FAIL);
  461.  
  462.     if (!fFreeze)  {
  463.       if (ppObj) {
  464.         // loop until you get an element
  465.         *ppObj = NULL;
  466.         while (nCurrPos < nSize) {
  467.           if (pDirectList[nCurrPos]) {
  468.             ((LPUNKNOWN)(pDirectList[nCurrPos]))->AddRef(); //\\//\\
  469.             *ppObj = pDirectList[nCurrPos];
  470.             hr = S_OK;
  471.             nCurrPos++;
  472.             break;
  473.           }
  474.           nCurrPos++;
  475.         }
  476.       }
  477.       else
  478.         hr = ResultFromScode (E_INVALIDARG);
  479.     }
  480.  
  481.   return hr;
  482. }
  483.  
  484.  
  485. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  486. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  487. //      BSinkList::GetSinkAt
  488. //
  489. //      Purpose:
  490. //        Answer the sink object at a specific position.
  491. //
  492. //      Parameters:
  493. //        int               psition into the array
  494. //        LPVOID FAR*           point to where the next sink will be returned
  495. //
  496. //      Return Value:
  497. //        HRESULT
  498. //
  499. HRESULT _IFUNC BEventHandler::BSinkList::GetSinkAt (int nPos, LPVOID FAR* ppObj)
  500. {
  501.   HRESULT hr = ResultFromScode (E_FAIL);
  502.  
  503.     if (!fFreeze)  {
  504.       if (ppObj) {
  505.         *ppObj = NULL;
  506.           if (nPos < nSize && pDirectList[nPos]) {
  507.             ((LPUNKNOWN)(pDirectList[nPos]))->AddRef(); //\\//\\
  508.             *ppObj = pDirectList[nPos];
  509.             hr = S_OK;
  510.           }
  511.       }
  512.     }
  513.  
  514.     return hr;
  515. }
  516.  
  517. //\\// IEnumConnections methods \\//\\
  518.  
  519. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  520. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  521. //      BSinkList::Next
  522. //
  523. //      Purpose:
  524. //        return as many elements as required by the first parameter
  525. //
  526. //      Parameters:
  527. //        ULONG           number of elements required
  528. //        LPCONNECTDATA       array of pointers where to store those elements
  529. //        ULONG FAR*            number of element really copied
  530. //
  531. //      Return Value:
  532. //        HRESULT
  533. //
  534. HRESULT _IFUNC BEventHandler::BSinkList::Next (ULONG cConnection,
  535.                             LPCONNECTDATA rgcd,
  536.                             ULONG FAR* lpcFetched)
  537. {
  538.   HRESULT hr = S_OK;
  539.  
  540.   // check rgpcd (for fun);
  541.   // lpcFetched can only be NULL if one element is request (cConnections = 1)
  542.   if (rgcd == NULL || (lpcFetched == NULL && cConnection != 1))
  543.     hr = ResultFromScode (E_INVALIDARG);
  544.   else {
  545.     int nNumEl = 0;
  546.  
  547.     // copy elements
  548.     while (cConnection && nCurrPos < nSize) {
  549.       if (pUnkList[nCurrPos]) { // see if a connection point is there
  550.         pUnkList[nCurrPos]->AddRef(); //\\//\\
  551.         rgcd[nNumEl].pUnk = pUnkList[nCurrPos]; // copy it
  552.         rgcd[nNumEl].dwCookie = nCurrPos; // copy it
  553.  
  554.         cConnection--; nNumEl++;
  555.       }
  556.       nCurrPos++;
  557.     }
  558.  
  559.     // save number of elements copied
  560.     if (lpcFetched != NULL) *lpcFetched = nNumEl;
  561.     // if copied less elements than required return FALSE
  562.     if (cConnection) hr = ResultFromScode (S_FALSE);
  563.   }
  564.  
  565.   return hr;
  566. }
  567.  
  568.  
  569. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  570. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  571. //      BSinkList::Skip
  572. //
  573. //      Purpose:
  574. //        skip a given number of elements
  575. //
  576. //      Parameters:
  577. //        ULONG       number of elements to skip
  578. //
  579. //      Return Value:
  580. //        HRESULT     S_FLASE if we could not skip so many elements
  581. //                S_OK otherwise
  582. //
  583. HRESULT _IFUNC BEventHandler::BSinkList::Skip (ULONG cConnections)
  584. {
  585.   HRESULT hr = S_OK;
  586.  
  587.   // find out how many elements to skip
  588.   for ( ; cConnections && nCurrPos < nSize; nCurrPos++)
  589.     if (pUnkList[nCurrPos]) // see if a connection point is there
  590.       cConnections--;
  591.  
  592.   if (cConnections) hr = ResultFromScode (S_FALSE);
  593.  
  594.   return hr;
  595. }
  596.  
  597.  
  598. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  599. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  600. //      BSinkList::Reset
  601. //
  602. //      Purpose:
  603. //        reset the internal position of this list
  604. //
  605. //      Return Value:
  606. //        HRESULT
  607. //
  608. HRESULT _IFUNC BEventHandler::BSinkList::Reset ()
  609. {
  610.   nCurrPos = 0;
  611.   return S_OK;
  612. }
  613.  
  614.  
  615. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  616. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  617. //      BSinkList::Clone
  618. //
  619. //      Purpose:
  620. //        give back a copy of this enumeration
  621. //
  622. //      Parameters:
  623. //        LPENUMCONNECTIONS FAR*    points to where to copy the enumeration
  624. //
  625. //      Return Value:
  626. //        HRESULT
  627. //
  628. HRESULT _IFUNC BEventHandler::BSinkList::Clone (LPENUMCONNECTIONS FAR* ppecn)
  629. {
  630.   HRESULT hr = S_OK;
  631.  
  632.   // check ppecn
  633.   if (ppecn == NULL)      hr = ResultFromScode (E_INVALIDARG);
  634.  
  635.   *ppecn = (LPENUMCONNECTIONS) new BSinkList (this);
  636.  
  637.   // check ppecn for out of memory
  638.   if (ppecn == NULL)      hr = ResultFromScode (E_OUTOFMEMORY);
  639.  
  640.   (*ppecn)->AddRef(); // user must release it
  641.  
  642.   return hr;
  643. }
  644.  
  645.  
  646. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  647. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  648. //      BSinkList::SetSinkAt
  649. //
  650. //      Purpose:
  651. //        save the two interface pointers. AddRef the IUnknown one since we keep it
  652. //
  653. //      Parameters:
  654. //        LPUNKNOWN           sink passed by clients
  655. //        LPVOID        interface obtained by QueryInterface on the previous IUnknown
  656. //        int             position into the array
  657. //
  658. //      Return Value:
  659. //        HRESULT
  660. //
  661. void BEventHandler::BSinkList::SetSinkAt (IUnknown* pU, LPVOID pObj, int nPos)
  662. {
  663.   pU->AddRef(); //\\//\\
  664.   pUnkList[nPos] = pU;
  665.   pDirectList[nPos] = pObj; // already AddRef'd by QueryInterface
  666.   return;
  667. }
  668.  
  669.  
  670. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  671. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  672. //      BSinkList::DeleteSinkAt
  673. //
  674. //      Purpose:
  675. //        release pointers to interfaces at the specific position
  676. //
  677. //      Parameters:
  678. //        int           position to delete
  679. //
  680. //      Return Value:
  681. //        HRESULT
  682. //
  683. void BEventHandler::BSinkList::DeleteSinkAt (int nPos)
  684. {
  685.   pUnkList[nPos]->Release();
  686.   pUnkList[nPos] = NULL;
  687.  
  688.   ((IUnknown*)(pDirectList[nPos]))->Release();
  689.   pDirectList[nPos] = NULL;
  690.   return;
  691. }
  692.  
  693.  
  694. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  695. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  696. //      BSinkList::Expand
  697. //
  698. //      Purpose:
  699. //        makes more room for new elements
  700. //
  701. //      Parameters:
  702. //        none
  703. //
  704. //      Return Value:
  705. //        int           1 if succesfull, 0 otherwise
  706. //
  707. int BEventHandler::BSinkList::Expand ()
  708. {
  709.   int newSize = nSize + nSize/2; // new dimension
  710.   // allocate
  711.   LPUNKNOWN FAR* pNewUnkList = (LPUNKNOWN FAR*) new char[sizeof(LPUNKNOWN) * newSize];
  712.   LPVOID FAR* pNewIntList = (LPVOID FAR*) new char[sizeof(LPVOID) * newSize];
  713.  
  714.   if (pNewUnkList && pNewIntList) {
  715.     // copy existing values
  716.     memcpy (pNewUnkList, pUnkList, sizeof(LPUNKNOWN) * nSize);
  717.     delete [] pUnkList; // delete old array
  718.     pUnkList = pNewUnkList;
  719.     memset (pUnkList + nSize, 0, sizeof(LPUNKNOWN) * nSize);
  720.  
  721.     memcpy (pNewIntList, pDirectList, sizeof(LPVOID) * nSize);
  722.     delete [] pDirectList; // delete old array
  723.     pDirectList = pNewIntList;
  724.     memset (pDirectList + nSize, 0, sizeof(LPVOID) * nSize);
  725.  
  726.     nSize = newSize;
  727.     return 1;
  728.   }
  729.   else
  730.     return 0;
  731. }
  732.  
  733.  
  734. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  735. ////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  736. //      BSinkList::BSinkList copy constructor
  737. //
  738. //
  739. BEventHandler::BSinkList::BSinkList (BSinkList* pList) :
  740.                         nCurrPos (pList->nCurrPos),
  741.                         nSize (pList->nSize),
  742.                         cRef(0)
  743. {
  744.   // allocate
  745.   LPUNKNOWN FAR* pUnkList = (LPUNKNOWN FAR*) new char[sizeof(LPUNKNOWN) * nSize];
  746.   LPVOID FAR* pDirectList = (LPVOID FAR*) new char[sizeof(LPVOID) * nSize];
  747.  
  748.   for (int i = 0; i < nSize; i++) {
  749.     // must copy and AddRef all elements
  750.     pUnkList[i] = pList->pUnkList[i];
  751.     if (pUnkList[i]) pUnkList[i]->AddRef();
  752.  
  753.     pDirectList[i] = pList->pDirectList[i];
  754.     if (pDirectList[i]) ((LPUNKNOWN)(pDirectList[i]))->AddRef();
  755.   }
  756. }
  757.  
  758.  
  759.