ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

connpt.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of a generic ConnectionPoint object.
00003  *
00004  * Copyright 2000 Huw D M Davies for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  *
00020  * NOTES:
00021  * See one exported function here is CreateConnectionPoint, see
00022  * comments just above that function for information.
00023  */
00024 
00025 #include <assert.h>
00026 #include <stdarg.h>
00027 #include <string.h>
00028 
00029 #define COBJMACROS
00030 
00031 #include "winerror.h"
00032 #include "windef.h"
00033 #include "winbase.h"
00034 #include "wingdi.h"
00035 #include "winuser.h"
00036 #include "ole2.h"
00037 #include "olectl.h"
00038 #include "connpt.h"
00039 
00040 #include "wine/debug.h"
00041 
00042 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00043 
00044 #define MAXSINKS 10
00045 
00046 /************************************************************************
00047  * Implementation of IConnectionPoint
00048  */
00049 typedef struct ConnectionPointImpl {
00050 
00051   const IConnectionPointVtbl *lpvtbl;
00052 
00053   /* IUnknown of our main object*/
00054   IUnknown *Obj;
00055 
00056   /* Reference count */
00057   LONG ref;
00058 
00059   /* IID of sink interface */
00060   IID iid;
00061 
00062   /* Array of sink IUnknowns */
00063   IUnknown **sinks;
00064   DWORD maxSinks;
00065 
00066   DWORD nSinks;
00067 } ConnectionPointImpl;
00068 
00069 static const IConnectionPointVtbl ConnectionPointImpl_VTable;
00070 
00071 
00072 /************************************************************************
00073  * Implementation of IEnumConnections
00074  */
00075 typedef struct EnumConnectionsImpl {
00076 
00077   const IEnumConnectionsVtbl *lpvtbl;
00078 
00079   LONG ref;
00080 
00081   /* IUnknown of ConnectionPoint, used for ref counting */
00082   IUnknown *pUnk;
00083 
00084   /* Connection Data */
00085   CONNECTDATA *pCD;
00086   DWORD nConns;
00087 
00088   /* Next connection to enumerate from */
00089   DWORD nCur;
00090 
00091 } EnumConnectionsImpl;
00092 
00093 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
00094                               DWORD nSinks,
00095                               CONNECTDATA *pCD);
00096 
00097 
00098 /************************************************************************
00099  * ConnectionPointImpl_Construct
00100  */
00101 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
00102                               REFIID riid)
00103 {
00104   ConnectionPointImpl *Obj;
00105 
00106   Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
00107   Obj->lpvtbl = &ConnectionPointImpl_VTable;
00108   Obj->Obj = pUnk;
00109   Obj->ref = 1;
00110   Obj->iid =  *riid;
00111   Obj->maxSinks = MAXSINKS;
00112   Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00113              sizeof(IUnknown*) * MAXSINKS);
00114   Obj->nSinks = 0;
00115   return Obj;
00116 }
00117 
00118 /************************************************************************
00119  * ConnectionPointImpl_Destroy
00120  */
00121 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
00122 {
00123   DWORD i;
00124   for(i = 0; i < Obj->maxSinks; i++) {
00125     if(Obj->sinks[i]) {
00126       IUnknown_Release(Obj->sinks[i]);
00127       Obj->sinks[i] = NULL;
00128     }
00129   }
00130   HeapFree(GetProcessHeap(), 0, Obj->sinks);
00131   HeapFree(GetProcessHeap(), 0, Obj);
00132   return;
00133 }
00134 
00135 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
00136 /************************************************************************
00137  * ConnectionPointImpl_QueryInterface (IUnknown)
00138  *
00139  * See Windows documentation for more details on IUnknown methods.
00140  */
00141 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
00142   IConnectionPoint*  iface,
00143   REFIID  riid,
00144   void**  ppvObject)
00145 {
00146   ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
00147   TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
00148 
00149   /*
00150    * Perform a sanity check on the parameters.
00151    */
00152   if ( (This==0) || (ppvObject==0) )
00153     return E_INVALIDARG;
00154 
00155   /*
00156    * Initialize the return parameter.
00157    */
00158   *ppvObject = 0;
00159 
00160   /*
00161    * Compare the riid with the interface IDs implemented by this object.
00162    */
00163   if (IsEqualIID(&IID_IUnknown, riid))
00164     *ppvObject = This;
00165   else if (IsEqualIID(&IID_IConnectionPoint, riid))
00166     *ppvObject = This;
00167 
00168   /*
00169    * Check that we obtained an interface.
00170    */
00171   if ((*ppvObject)==0)
00172   {
00173     FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
00174     return E_NOINTERFACE;
00175   }
00176 
00177   /*
00178    * Query Interface always increases the reference count by one when it is
00179    * successful
00180    */
00181   ConnectionPointImpl_AddRef((IConnectionPoint*)This);
00182 
00183   return S_OK;
00184 }
00185 
00186 
00187 /************************************************************************
00188  * ConnectionPointImpl_AddRef (IUnknown)
00189  *
00190  * See Windows documentation for more details on IUnknown methods.
00191  */
00192 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
00193 {
00194   ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
00195   ULONG refCount = InterlockedIncrement(&This->ref);
00196 
00197   TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
00198 
00199   return refCount;
00200 }
00201 
00202 /************************************************************************
00203  * ConnectionPointImpl_Release (IUnknown)
00204  *
00205  * See Windows documentation for more details on IUnknown methods.
00206  */
00207 static ULONG WINAPI ConnectionPointImpl_Release(
00208       IConnectionPoint* iface)
00209 {
00210   ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
00211   ULONG refCount = InterlockedDecrement(&This->ref);
00212 
00213   TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
00214 
00215   /*
00216    * If the reference count goes down to 0, perform suicide.
00217    */
00218   if (!refCount) ConnectionPointImpl_Destroy(This);
00219 
00220   return refCount;
00221 }
00222 
00223 /************************************************************************
00224  * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
00225  *
00226  */
00227 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
00228                            IConnectionPoint *iface,
00229                            IID              *piid)
00230 {
00231   ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
00232   TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
00233   *piid = This->iid;
00234   return S_OK;
00235 }
00236 
00237 /************************************************************************
00238  * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
00239  *
00240  */
00241 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
00242                       IConnectionPoint           *iface,
00243                       IConnectionPointContainer  **ppCPC)
00244 {
00245   ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
00246   TRACE("(%p)->(%p)\n", This, ppCPC);
00247 
00248   return IUnknown_QueryInterface(This->Obj,
00249                  &IID_IConnectionPointContainer,
00250                  (LPVOID)ppCPC);
00251 }
00252 
00253 /************************************************************************
00254  * ConnectionPointImpl_Advise (IConnectionPoint)
00255  *
00256  */
00257 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
00258                          IUnknown *lpUnk,
00259                          DWORD *pdwCookie)
00260 {
00261   DWORD i;
00262   ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
00263   IUnknown *lpSink;
00264   TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
00265 
00266   *pdwCookie = 0;
00267   if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
00268     return CONNECT_E_CANNOTCONNECT;
00269 
00270   for(i = 0; i < This->maxSinks; i++) {
00271     if(This->sinks[i] == NULL)
00272       break;
00273   }
00274   if(i == This->maxSinks) {
00275     This->maxSinks += MAXSINKS;
00276     This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
00277                   This->maxSinks * sizeof(IUnknown *));
00278   }
00279   This->sinks[i] = lpSink;
00280   This->nSinks++;
00281   *pdwCookie = i + 1;
00282   return S_OK;
00283 }
00284 
00285 
00286 /************************************************************************
00287  * ConnectionPointImpl_Unadvise (IConnectionPoint)
00288  *
00289  */
00290 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
00291                            DWORD dwCookie)
00292 {
00293   ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
00294   TRACE("(%p)->(%d)\n", This, dwCookie);
00295 
00296   if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
00297 
00298   if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
00299 
00300   IUnknown_Release(This->sinks[dwCookie-1]);
00301   This->sinks[dwCookie-1] = NULL;
00302   This->nSinks--;
00303   return S_OK;
00304 }
00305 
00306 /************************************************************************
00307  * ConnectionPointImpl_EnumConnections (IConnectionPoint)
00308  *
00309  */
00310 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
00311                             IConnectionPoint *iface,
00312                             LPENUMCONNECTIONS *ppEnum)
00313 {
00314   ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
00315   CONNECTDATA *pCD;
00316   DWORD i, nextslot;
00317   EnumConnectionsImpl *EnumObj;
00318   HRESULT hr;
00319 
00320   TRACE("(%p)->(%p)\n", This, ppEnum);
00321 
00322   *ppEnum = NULL;
00323 
00324   if(This->nSinks == 0) return OLE_E_NOCONNECTION;
00325 
00326   pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
00327 
00328   for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
00329     if(This->sinks[i] != NULL) {
00330       pCD[nextslot].pUnk = This->sinks[i];
00331       pCD[nextslot].dwCookie = i + 1;
00332       nextslot++;
00333     }
00334   }
00335   assert(nextslot == This->nSinks);
00336 
00337   /* Bump the ref count of this object up by one.  It gets Released in
00338      IEnumConnections_Release */
00339   IUnknown_AddRef((IUnknown*)This);
00340 
00341   EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
00342   hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
00343                   &IID_IEnumConnections, (LPVOID)ppEnum);
00344   IEnumConnections_Release((IEnumConnections*)EnumObj);
00345 
00346   HeapFree(GetProcessHeap(), 0, pCD);
00347   return hr;
00348 }
00349 
00350 static const IConnectionPointVtbl ConnectionPointImpl_VTable =
00351 {
00352   ConnectionPointImpl_QueryInterface,
00353   ConnectionPointImpl_AddRef,
00354   ConnectionPointImpl_Release,
00355   ConnectionPointImpl_GetConnectionInterface,
00356   ConnectionPointImpl_GetConnectionPointContainer,
00357   ConnectionPointImpl_Advise,
00358   ConnectionPointImpl_Unadvise,
00359   ConnectionPointImpl_EnumConnections
00360 };
00361 
00362 
00363 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
00364 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
00365 
00366 /************************************************************************
00367  * EnumConnectionsImpl_Construct
00368  */
00369 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
00370                               DWORD nSinks,
00371                               CONNECTDATA *pCD)
00372 {
00373   EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
00374   DWORD i;
00375 
00376   Obj->lpvtbl = &EnumConnectionsImpl_VTable;
00377   Obj->ref = 1;
00378   Obj->pUnk = pUnk;
00379   Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
00380   Obj->nConns = nSinks;
00381   Obj->nCur = 0;
00382 
00383   for(i = 0; i < nSinks; i++) {
00384     Obj->pCD[i] = pCD[i];
00385     IUnknown_AddRef(Obj->pCD[i].pUnk);
00386   }
00387   return Obj;
00388 }
00389 
00390 /************************************************************************
00391  * EnumConnectionsImpl_Destroy
00392  */
00393 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
00394 {
00395   DWORD i;
00396 
00397   for(i = 0; i < Obj->nConns; i++)
00398     IUnknown_Release(Obj->pCD[i].pUnk);
00399 
00400   HeapFree(GetProcessHeap(), 0, Obj->pCD);
00401   HeapFree(GetProcessHeap(), 0, Obj);
00402   return;
00403 }
00404 
00405 /************************************************************************
00406  * EnumConnectionsImpl_QueryInterface (IUnknown)
00407  *
00408  * See Windows documentation for more details on IUnknown methods.
00409  */
00410 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
00411   IEnumConnections*  iface,
00412   REFIID  riid,
00413   void**  ppvObject)
00414 {
00415   ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
00416   TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
00417 
00418   /*
00419    * Perform a sanity check on the parameters.
00420    */
00421   if ( (This==0) || (ppvObject==0) )
00422     return E_INVALIDARG;
00423 
00424   /*
00425    * Initialize the return parameter.
00426    */
00427   *ppvObject = 0;
00428 
00429   /*
00430    * Compare the riid with the interface IDs implemented by this object.
00431    */
00432   if (IsEqualIID(&IID_IUnknown, riid))
00433     *ppvObject = This;
00434   else if (IsEqualIID(&IID_IEnumConnections, riid))
00435     *ppvObject = This;
00436 
00437   /*
00438    * Check that we obtained an interface.
00439    */
00440   if ((*ppvObject)==0)
00441   {
00442     FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
00443     return E_NOINTERFACE;
00444   }
00445 
00446   /*
00447    * Query Interface always increases the reference count by one when it is
00448    * successful
00449    */
00450   EnumConnectionsImpl_AddRef((IEnumConnections*)This);
00451 
00452   return S_OK;
00453 }
00454 
00455 
00456 /************************************************************************
00457  * EnumConnectionsImpl_AddRef (IUnknown)
00458  *
00459  * See Windows documentation for more details on IUnknown methods.
00460  */
00461 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
00462 {
00463   EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
00464   ULONG refCount = InterlockedIncrement(&This->ref);
00465 
00466   TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
00467 
00468   IUnknown_AddRef(This->pUnk);
00469   return refCount;
00470 }
00471 
00472 /************************************************************************
00473  * EnumConnectionsImpl_Release (IUnknown)
00474  *
00475  * See Windows documentation for more details on IUnknown methods.
00476  */
00477 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
00478 {
00479   EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
00480   ULONG refCount = InterlockedDecrement(&This->ref);
00481 
00482   TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
00483 
00484   IUnknown_Release(This->pUnk);
00485 
00486   /*
00487    * If the reference count goes down to 0, perform suicide.
00488    */
00489   if (!refCount) EnumConnectionsImpl_Destroy(This);
00490 
00491   return refCount;
00492 }
00493 
00494 /************************************************************************
00495  * EnumConnectionsImpl_Next (IEnumConnections)
00496  *
00497  */
00498 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
00499                            ULONG cConn, LPCONNECTDATA pCD,
00500                            ULONG *pEnum)
00501 {
00502   EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
00503   DWORD nRet = 0;
00504   TRACE("(%p)->(%d, %p, %p)\n", This, cConn, pCD, pEnum);
00505 
00506   if(pEnum == NULL) {
00507     if(cConn != 1)
00508       return E_POINTER;
00509   } else
00510     *pEnum = 0;
00511 
00512   if(This->nCur >= This->nConns)
00513     return S_FALSE;
00514 
00515   while(This->nCur < This->nConns && cConn) {
00516     *pCD++ = This->pCD[This->nCur];
00517     IUnknown_AddRef(This->pCD[This->nCur].pUnk);
00518     This->nCur++;
00519     cConn--;
00520     nRet++;
00521   }
00522 
00523   if(pEnum)
00524     *pEnum = nRet;
00525 
00526   return S_OK;
00527 }
00528 
00529 
00530 /************************************************************************
00531  * EnumConnectionsImpl_Skip (IEnumConnections)
00532  *
00533  */
00534 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
00535                            ULONG cSkip)
00536 {
00537   EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
00538   TRACE("(%p)->(%d)\n", This, cSkip);
00539 
00540   if(This->nCur + cSkip >= This->nConns)
00541     return S_FALSE;
00542 
00543   This->nCur += cSkip;
00544 
00545   return S_OK;
00546 }
00547 
00548 
00549 /************************************************************************
00550  * EnumConnectionsImpl_Reset (IEnumConnections)
00551  *
00552  */
00553 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
00554 {
00555   EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
00556   TRACE("(%p)\n", This);
00557 
00558   This->nCur = 0;
00559 
00560   return S_OK;
00561 }
00562 
00563 
00564 /************************************************************************
00565  * EnumConnectionsImpl_Clone (IEnumConnections)
00566  *
00567  */
00568 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
00569                         LPENUMCONNECTIONS *ppEnum)
00570 {
00571   EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
00572   EnumConnectionsImpl *newObj;
00573   TRACE("(%p)->(%p)\n", This, ppEnum);
00574 
00575   newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
00576   newObj->nCur = This->nCur;
00577   *ppEnum = (LPENUMCONNECTIONS)newObj;
00578   IUnknown_AddRef(This->pUnk);
00579   return S_OK;
00580 }
00581 
00582 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
00583 {
00584   EnumConnectionsImpl_QueryInterface,
00585   EnumConnectionsImpl_AddRef,
00586   EnumConnectionsImpl_Release,
00587   EnumConnectionsImpl_Next,
00588   EnumConnectionsImpl_Skip,
00589   EnumConnectionsImpl_Reset,
00590   EnumConnectionsImpl_Clone
00591 };
00592 
00593 /************************************************************************
00594  *
00595  *  The exported function to create the connection point.
00596  *  NB not a windows API
00597  *
00598  * PARAMS
00599  * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
00600  *           Needed to access IConnectionPointContainer.
00601  *
00602  * riid [in] IID of sink interface that this ConnectionPoint manages
00603  *
00604  * pCP [out] returns IConnectionPoint
00605  *
00606  */
00607 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
00608                   IConnectionPoint **pCP)
00609 {
00610   ConnectionPointImpl *Obj;
00611   HRESULT hr;
00612 
00613   Obj = ConnectionPointImpl_Construct(pUnk, riid);
00614   if(!Obj) return E_OUTOFMEMORY;
00615 
00616   hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
00617                        &IID_IConnectionPoint, (LPVOID)pCP);
00618   IConnectionPoint_Release((IConnectionPoint *)Obj);
00619   return hr;
00620 }

Generated on Fri May 25 2012 04:23:49 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.