ReactOS  0.4.15-dev-506-ga3ec01c
connpt.c
Go to the documentation of this file.
1 /*
2  * Implementation of a generic ConnectionPoint object.
3  *
4  * Copyright 2000 Huw D M Davies for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * NOTES:
21  * See one exported function here is CreateConnectionPoint, see
22  * comments just above that function for information.
23  */
24 
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
28 
29 #define COBJMACROS
30 
31 #include "winerror.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "wingdi.h"
35 #include "winuser.h"
36 #include "ole2.h"
37 #include "olectl.h"
38 #include "connpt.h"
39 
40 #include "wine/debug.h"
41 
43 
44 #define MAXSINKS 10
45 
46 /************************************************************************
47  * Implementation of IConnectionPoint
48  */
49 typedef struct ConnectionPointImpl {
50 
52 
53  /* IUnknown of our main object*/
55 
56  /* Reference count */
58 
59  /* IID of sink interface */
61 
62  /* Array of sink IUnknowns */
65 
68 
69 /************************************************************************
70  * Implementation of IEnumConnections
71  */
72 typedef struct EnumConnectionsImpl {
73 
75 
77 
78  /* IUnknown of ConnectionPoint, used for ref counting */
80 
81  /* Connection Data */
82  CONNECTDATA *pCD;
84 
85  /* Next connection to enumerate from */
87 
89 
91  DWORD nSinks,
92  CONNECTDATA *pCD);
93 
95 {
96  return CONTAINING_RECORD(iface, ConnectionPointImpl, IConnectionPoint_iface);
97 }
98 
100 {
101  return CONTAINING_RECORD(iface, EnumConnectionsImpl, IEnumConnections_iface);
102 }
103 
104 /************************************************************************
105  * ConnectionPointImpl_Destroy
106  */
108 {
109  DWORD i;
110  for(i = 0; i < Obj->maxSinks; i++) {
111  if(Obj->sinks[i]) {
112  IUnknown_Release(Obj->sinks[i]);
113  Obj->sinks[i] = NULL;
114  }
115  }
116  HeapFree(GetProcessHeap(), 0, Obj->sinks);
117  HeapFree(GetProcessHeap(), 0, Obj);
118  return;
119 }
120 
121 /************************************************************************
122  * ConnectionPointImpl_QueryInterface (IUnknown)
123  *
124  * See Windows documentation for more details on IUnknown methods.
125  */
127  IConnectionPoint* iface,
128  REFIID riid,
129  void** ppvObject)
130 {
132  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
133 
134  /*
135  * Perform a sanity check on the parameters.
136  */
137  if (!ppvObject)
138  return E_INVALIDARG;
139 
140  /*
141  * Initialize the return parameter.
142  */
143  *ppvObject = 0;
144 
145 
147  *ppvObject = iface;
148 
149  /*
150  * Check that we obtained an interface.
151  */
152  if ((*ppvObject)==0)
153  {
154  FIXME("() : asking for unsupported interface %s\n", debugstr_guid(riid));
155  return E_NOINTERFACE;
156  }
157 
158  IUnknown_AddRef((IUnknown*)*ppvObject);
159 
160  return S_OK;
161 }
162 
163 
164 /************************************************************************
165  * ConnectionPointImpl_AddRef (IUnknown)
166  *
167  * See Windows documentation for more details on IUnknown methods.
168  */
170 {
172  ULONG refCount = InterlockedIncrement(&This->ref);
173 
174  TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
175 
176  return refCount;
177 }
178 
179 /************************************************************************
180  * ConnectionPointImpl_Release (IUnknown)
181  *
182  * See Windows documentation for more details on IUnknown methods.
183  */
185  IConnectionPoint* iface)
186 {
188  ULONG refCount = InterlockedDecrement(&This->ref);
189 
190  TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
191 
192  /*
193  * If the reference count goes down to 0, perform suicide.
194  */
195  if (!refCount) ConnectionPointImpl_Destroy(This);
196 
197  return refCount;
198 }
199 
200 /************************************************************************
201  * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
202  *
203  */
205  IConnectionPoint *iface,
206  IID *piid)
207 {
209  TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
210  *piid = This->iid;
211  return S_OK;
212 }
213 
214 /************************************************************************
215  * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
216  *
217  */
219  IConnectionPoint *iface,
221 {
223  TRACE("(%p)->(%p)\n", This, ppCPC);
224 
225  return IUnknown_QueryInterface(This->Obj, &IID_IConnectionPointContainer, (void**)ppCPC);
226 }
227 
228 /************************************************************************
229  * ConnectionPointImpl_Advise (IConnectionPoint)
230  *
231  */
233  IUnknown *lpUnk,
234  DWORD *pdwCookie)
235 {
236  DWORD i;
238  IUnknown *lpSink;
239  TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
240 
241  *pdwCookie = 0;
242  if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (void**)&lpSink)))
244 
245  for(i = 0; i < This->maxSinks; i++) {
246  if(This->sinks[i] == NULL)
247  break;
248  }
249  if(i == This->maxSinks) {
250  This->maxSinks += MAXSINKS;
252  This->maxSinks * sizeof(IUnknown *));
253  }
254  This->sinks[i] = lpSink;
255  This->nSinks++;
256  *pdwCookie = i + 1;
257  return S_OK;
258 }
259 
260 
261 /************************************************************************
262  * ConnectionPointImpl_Unadvise (IConnectionPoint)
263  *
264  */
266  DWORD dwCookie)
267 {
269  TRACE("(%p)->(%d)\n", This, dwCookie);
270 
271  if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
272 
273  if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
274 
275  IUnknown_Release(This->sinks[dwCookie-1]);
276  This->sinks[dwCookie-1] = NULL;
277  This->nSinks--;
278  return S_OK;
279 }
280 
281 /************************************************************************
282  * ConnectionPointImpl_EnumConnections (IConnectionPoint)
283  *
284  */
286  IConnectionPoint *iface,
287  LPENUMCONNECTIONS *ppEnum)
288 {
290  CONNECTDATA *pCD;
291  DWORD i, nextslot;
292  EnumConnectionsImpl *EnumObj;
293  HRESULT hr;
294 
295  TRACE("(%p)->(%p)\n", This, ppEnum);
296 
297  *ppEnum = NULL;
298 
299  if(This->nSinks == 0) return OLE_E_NOCONNECTION;
300 
301  pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
302 
303  for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
304  if(This->sinks[i] != NULL) {
305  pCD[nextslot].pUnk = This->sinks[i];
306  pCD[nextslot].dwCookie = i + 1;
307  nextslot++;
308  }
309  }
310  assert(nextslot == This->nSinks);
311 
312  /* Bump the ref count of this object up by one. It gets Released in
313  IEnumConnections_Release */
314  IConnectionPoint_AddRef(iface);
315 
316  EnumObj = EnumConnectionsImpl_Construct((IUnknown*)iface, This->nSinks, pCD);
317  hr = IEnumConnections_QueryInterface(&EnumObj->IEnumConnections_iface,
318  &IID_IEnumConnections, (void**)ppEnum);
319  IEnumConnections_Release(&EnumObj->IEnumConnections_iface);
320 
321  HeapFree(GetProcessHeap(), 0, pCD);
322  return hr;
323 }
324 
325 static const IConnectionPointVtbl ConnectionPointImpl_VTable =
326 {
335 };
336 
337 
338 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
339 
340 /************************************************************************
341  * EnumConnectionsImpl_Construct
342  */
344  DWORD nSinks,
345  CONNECTDATA *pCD)
346 {
348  DWORD i;
349 
350  Obj->IEnumConnections_iface.lpVtbl = &EnumConnectionsImpl_VTable;
351  Obj->ref = 1;
352  Obj->pUnk = pUnk;
353  Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
354  Obj->nConns = nSinks;
355  Obj->nCur = 0;
356 
357  for(i = 0; i < nSinks; i++) {
358  Obj->pCD[i] = pCD[i];
359  IUnknown_AddRef(Obj->pCD[i].pUnk);
360  }
361  return Obj;
362 }
363 
364 /************************************************************************
365  * EnumConnectionsImpl_Destroy
366  */
368 {
369  DWORD i;
370 
371  for(i = 0; i < Obj->nConns; i++)
372  IUnknown_Release(Obj->pCD[i].pUnk);
373 
374  HeapFree(GetProcessHeap(), 0, Obj->pCD);
375  HeapFree(GetProcessHeap(), 0, Obj);
376  return;
377 }
378 
379 /************************************************************************
380  * EnumConnectionsImpl_QueryInterface (IUnknown)
381  *
382  * See Windows documentation for more details on IUnknown methods.
383  */
385  IEnumConnections* iface,
386  REFIID riid,
387  void** ppvObject)
388 {
390  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
391 
392  /*
393  * Perform a sanity check on the parameters.
394  */
395  if (!ppvObject)
396  return E_INVALIDARG;
397 
398  /*
399  * Initialize the return parameter.
400  */
401  *ppvObject = 0;
402 
404  *ppvObject = iface;
405 
406  /*
407  * Check that we obtained an interface.
408  */
409  if ((*ppvObject)==0)
410  {
411  FIXME("() : asking for unsupported interface %s\n", debugstr_guid(riid));
412  return E_NOINTERFACE;
413  }
414 
415  IUnknown_AddRef((IUnknown*)*ppvObject);
416 
417  return S_OK;
418 }
419 
420 
421 /************************************************************************
422  * EnumConnectionsImpl_AddRef (IUnknown)
423  *
424  * See Windows documentation for more details on IUnknown methods.
425  */
427 {
429  ULONG refCount = InterlockedIncrement(&This->ref);
430 
431  TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
432 
433  IUnknown_AddRef(This->pUnk);
434  return refCount;
435 }
436 
437 /************************************************************************
438  * EnumConnectionsImpl_Release (IUnknown)
439  *
440  * See Windows documentation for more details on IUnknown methods.
441  */
443 {
445  ULONG refCount = InterlockedDecrement(&This->ref);
446 
447  TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
448 
449  IUnknown_Release(This->pUnk);
450 
451  /*
452  * If the reference count goes down to 0, perform suicide.
453  */
454  if (!refCount) EnumConnectionsImpl_Destroy(This);
455 
456  return refCount;
457 }
458 
459 /************************************************************************
460  * EnumConnectionsImpl_Next (IEnumConnections)
461  *
462  */
464  ULONG cConn, LPCONNECTDATA pCD,
465  ULONG *pEnum)
466 {
468  DWORD nRet = 0;
469  TRACE("(%p)->(%d, %p, %p)\n", This, cConn, pCD, pEnum);
470 
471  if(pEnum == NULL) {
472  if(cConn != 1)
473  return E_POINTER;
474  } else
475  *pEnum = 0;
476 
477  if(This->nCur >= This->nConns)
478  return S_FALSE;
479 
480  while(This->nCur < This->nConns && cConn) {
481  *pCD++ = This->pCD[This->nCur];
482  IUnknown_AddRef(This->pCD[This->nCur].pUnk);
483  This->nCur++;
484  cConn--;
485  nRet++;
486  }
487 
488  if(pEnum)
489  *pEnum = nRet;
490 
491  return S_OK;
492 }
493 
494 
495 /************************************************************************
496  * EnumConnectionsImpl_Skip (IEnumConnections)
497  *
498  */
500  ULONG cSkip)
501 {
503  TRACE("(%p)->(%d)\n", This, cSkip);
504 
505  if(This->nCur + cSkip >= This->nConns)
506  return S_FALSE;
507 
508  This->nCur += cSkip;
509 
510  return S_OK;
511 }
512 
513 
514 /************************************************************************
515  * EnumConnectionsImpl_Reset (IEnumConnections)
516  *
517  */
519 {
521  TRACE("(%p)\n", This);
522 
523  This->nCur = 0;
524 
525  return S_OK;
526 }
527 
528 
529 /************************************************************************
530  * EnumConnectionsImpl_Clone (IEnumConnections)
531  *
532  */
534  LPENUMCONNECTIONS *ppEnum)
535 {
537  EnumConnectionsImpl *newObj;
538  TRACE("(%p)->(%p)\n", This, ppEnum);
539 
540  newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
541  newObj->nCur = This->nCur;
542  *ppEnum = &newObj->IEnumConnections_iface;
543  IUnknown_AddRef(This->pUnk);
544  return S_OK;
545 }
546 
547 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
548 {
556 };
557 
558 /************************************************************************
559  *
560  * The exported function to create the connection point.
561  * NB not a windows API
562  *
563  * PARAMS
564  * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
565  * Needed to access IConnectionPointContainer.
566  *
567  * riid [in] IID of sink interface that this ConnectionPoint manages
568  *
569  * pCP [out] returns IConnectionPoint
570  *
571  */
573  IConnectionPoint **pCP)
574 {
576 
577  TRACE("(%p %s %p)\n", pUnk, debugstr_guid(riid), pCP);
578 
579  *pCP = NULL;
580  Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
581  if (!Obj)
582  return E_OUTOFMEMORY;
583 
584  Obj->IConnectionPoint_iface.lpVtbl = &ConnectionPointImpl_VTable;
585  Obj->Obj = pUnk;
586  Obj->ref = 1;
587  Obj->iid = *riid;
588  Obj->maxSinks = MAXSINKS;
590  Obj->nSinks = 0;
591 
592  *pCP = &Obj->IConnectionPoint_iface;
593  return S_OK;
594 }
static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
Definition: connpt.c:265
static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections *iface)
Definition: connpt.c:426
#define REFIID
Definition: guiddef.h:118
#define E_NOINTERFACE
Definition: winerror.h:2364
static ConnectionPointImpl * impl_from_IConnectionPoint(IConnectionPoint *iface)
Definition: connpt.c:94
HRESULT hr
Definition: shlfolder.c:183
#define CONNECT_E_CANNOTCONNECT
Definition: olectl.h:253
static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections *iface, LPENUMCONNECTIONS *ppEnum)
Definition: connpt.c:533
static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(IConnectionPoint *iface, IConnectionPointContainer **ppCPC)
Definition: connpt.c:218
REFIID riid
Definition: precomp.h:44
#define CONNECT_E_NOCONNECTION
Definition: olectl.h:251
IUnknown * pUnk
Definition: connpt.c:79
Obj()
Definition: swap_test.cpp:67
#define MAXSINKS
Definition: connpt.c:44
const GUID IID_IConnectionPointContainer
#define assert(x)
Definition: debug.h:53
const GUID IID_IEnumConnections
#define OLE_E_NOCONNECTION
Definition: winerror.h:2618
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
IConnectionPoint IConnectionPoint_iface
Definition: connpt.c:51
static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(IConnectionPoint *iface, IID *piid)
Definition: connpt.c:204
long LONG
Definition: pedump.c:60
#define FIXME(fmt,...)
Definition: debug.h:111
#define S_FALSE
Definition: winerror.h:2357
struct EnumConnectionsImpl EnumConnectionsImpl
#define E_INVALIDARG
Definition: ddrawi.h:101
IEnumConnections IEnumConnections_iface
Definition: connpt.c:74
smooth NULL
Definition: ftsmooth.c:416
static EnumConnectionsImpl * EnumConnectionsImpl_Construct(IUnknown *pUnk, DWORD nSinks, CONNECTDATA *pCD)
Definition: connpt.c:343
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections *iface, ULONG cSkip)
Definition: connpt.c:499
static ULONG WINAPI ConnectionPointImpl_Release(IConnectionPoint *iface)
Definition: connpt.c:184
static HRESULT WINAPI ConnectionPointImpl_QueryInterface(IConnectionPoint *iface, REFIID riid, void **ppvObject)
Definition: connpt.c:126
struct ConnectionPointImpl ConnectionPointImpl
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:404
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
LONG HRESULT
Definition: typedefs.h:78
const GUID IID_IUnknown
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
static EnumConnectionsImpl * impl_from_IEnumConnections(IEnumConnections *iface)
Definition: connpt.c:99
WINE_DEFAULT_DEBUG_CHANNEL(ole)
static const IConnectionPointVtbl ConnectionPointImpl_VTable
Definition: connpt.c:325
#define InterlockedDecrement
Definition: armddk.h:52
static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
Definition: connpt.c:107
REFIID LPVOID * ppvObject
Definition: precomp.h:44
static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint *iface)
Definition: connpt.c:169
IUnknown ** sinks
Definition: connpt.c:63
IUnknown * Obj
Definition: connpt.c:54
static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections *iface, ULONG cConn, LPCONNECTDATA pCD, ULONG *pEnum)
Definition: connpt.c:463
static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface, IUnknown *lpUnk, DWORD *pdwCookie)
Definition: connpt.c:232
const GUID IID_IConnectionPoint
#define S_OK
Definition: intsafe.h:59
#define InterlockedIncrement
Definition: armddk.h:53
#define HeapReAlloc
Definition: compat.h:402
static HRESULT WINAPI ConnectionPointImpl_EnumConnections(IConnectionPoint *iface, LPENUMCONNECTIONS *ppEnum)
Definition: connpt.c:285
static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections *iface)
Definition: connpt.c:518
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid, IConnectionPoint **pCP)
Definition: connpt.c:572
CONNECTDATA * pCD
Definition: connpt.c:82
static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable
Definition: connpt.c:338
unsigned int ULONG
Definition: retypes.h:1
#define E_POINTER
Definition: winerror.h:2365
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections *iface)
Definition: connpt.c:442
#define HeapFree(x, y, z)
Definition: compat.h:403
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(IEnumConnections *iface, REFIID riid, void **ppvObject)
Definition: connpt.c:384
static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
Definition: connpt.c:367