Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenconnpt.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
1.7.6.1
|