Add proxy authentication dialog.
[wine/testsucceed.git] / dlls / oleaut32 / connpt.c
blob5cc49c579841e39e1236e2e0b1942127d9062c3b
1 /*
2 * Implementation of a generic ConnectionPoint object.
4 * Copyright 2000 Huw D M Davies for CodeWeavers
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * NOTES:
21 * See one exported function here is CreateConnectionPoint, see
22 * comments just above that function for information.
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
29 #define COBJMACROS
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"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ole);
44 #define MAXSINKS 10
46 /************************************************************************
47 * Implementation of IConnectionPoint
49 typedef struct ConnectionPointImpl {
51 IConnectionPointVtbl *lpvtbl;
53 /* IUnknown of our main object*/
54 IUnknown *Obj;
56 /* Reference count */
57 DWORD ref;
59 /* IID of sink interface */
60 IID iid;
62 /* Array of sink IUnknowns */
63 IUnknown **sinks;
64 DWORD maxSinks;
66 DWORD nSinks;
67 } ConnectionPointImpl;
69 static IConnectionPointVtbl ConnectionPointImpl_VTable;
72 /************************************************************************
73 * Implementation of IEnumConnections
75 typedef struct EnumConnectionsImpl {
77 IEnumConnectionsVtbl *lpvtbl;
79 DWORD ref;
81 /* IUnknown of ConnectionPoint, used for ref counting */
82 IUnknown *pUnk;
84 /* Connection Data */
85 CONNECTDATA *pCD;
86 DWORD nConns;
88 /* Next connection to enumerate from */
89 DWORD nCur;
91 } EnumConnectionsImpl;
93 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
94 DWORD nSinks,
95 CONNECTDATA *pCD);
98 /************************************************************************
99 * ConnectionPointImpl_Construct
101 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
102 REFIID riid)
104 ConnectionPointImpl *Obj;
106 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
107 Obj->lpvtbl = &ConnectionPointImpl_VTable;
108 Obj->Obj = pUnk;
109 Obj->ref = 1;
110 Obj->iid = *riid;
111 Obj->maxSinks = MAXSINKS;
112 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
113 sizeof(IUnknown*) * MAXSINKS);
114 Obj->nSinks = 0;
115 return Obj;
118 /************************************************************************
119 * ConnectionPointImpl_Destroy
121 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
123 DWORD i;
124 for(i = 0; i < Obj->maxSinks; i++) {
125 if(Obj->sinks[i]) {
126 IUnknown_Release(Obj->sinks[i]);
127 Obj->sinks[i] = NULL;
130 HeapFree(GetProcessHeap(), 0, Obj->sinks);
131 HeapFree(GetProcessHeap(), 0, Obj);
132 return;
135 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
136 /************************************************************************
137 * ConnectionPointImpl_QueryInterface (IUnknown)
139 * See Windows documentation for more details on IUnknown methods.
141 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
142 IConnectionPoint* iface,
143 REFIID riid,
144 void** ppvObject)
146 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
147 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
150 * Perform a sanity check on the parameters.
152 if ( (This==0) || (ppvObject==0) )
153 return E_INVALIDARG;
156 * Initialize the return parameter.
158 *ppvObject = 0;
161 * Compare the riid with the interface IDs implemented by this object.
163 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
165 *ppvObject = (IConnectionPoint*)This;
167 else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0)
169 *ppvObject = (IConnectionPoint*)This;
173 * Check that we obtained an interface.
175 if ((*ppvObject)==0)
177 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
178 return E_NOINTERFACE;
182 * Query Interface always increases the reference count by one when it is
183 * successful
185 ConnectionPointImpl_AddRef((IConnectionPoint*)This);
187 return S_OK;
191 /************************************************************************
192 * ConnectionPointImpl_AddRef (IUnknown)
194 * See Windows documentation for more details on IUnknown methods.
196 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
198 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
199 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
200 return InterlockedIncrement(&This->ref);
203 /************************************************************************
204 * ConnectionPointImpl_Release (IUnknown)
206 * See Windows documentation for more details on IUnknown methods.
208 static ULONG WINAPI ConnectionPointImpl_Release(
209 IConnectionPoint* iface)
211 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
212 ULONG ref;
213 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
216 * Decrease the reference count on this object.
218 ref = InterlockedDecrement(&This->ref);
221 * If the reference count goes down to 0, perform suicide.
223 if (ref == 0) ConnectionPointImpl_Destroy(This);
225 return ref;
228 /************************************************************************
229 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
232 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
233 IConnectionPoint *iface,
234 IID *piid)
236 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
237 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
238 *piid = This->iid;
239 return S_OK;
242 /************************************************************************
243 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
246 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
247 IConnectionPoint *iface,
248 IConnectionPointContainer **ppCPC)
250 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
251 TRACE("(%p)->(%p)\n", This, ppCPC);
253 return IUnknown_QueryInterface(This->Obj,
254 &IID_IConnectionPointContainer,
255 (LPVOID)ppCPC);
258 /************************************************************************
259 * ConnectionPointImpl_Advise (IConnectionPoint)
262 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
263 IUnknown *lpUnk,
264 DWORD *pdwCookie)
266 DWORD i;
267 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
268 IUnknown *lpSink;
269 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
271 *pdwCookie = 0;
272 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
273 return CONNECT_E_CANNOTCONNECT;
275 for(i = 0; i < This->maxSinks; i++) {
276 if(This->sinks[i] == NULL)
277 break;
279 if(i == This->maxSinks) {
280 This->maxSinks += MAXSINKS;
281 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
282 This->maxSinks * sizeof(IUnknown *));
284 This->sinks[i] = lpSink;
285 This->nSinks++;
286 *pdwCookie = i + 1;
287 return S_OK;
291 /************************************************************************
292 * ConnectionPointImpl_Unadvise (IConnectionPoint)
295 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
296 DWORD dwCookie)
298 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
299 TRACE("(%p)->(%ld)\n", This, dwCookie);
301 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
303 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
305 IUnknown_Release(This->sinks[dwCookie-1]);
306 This->sinks[dwCookie-1] = NULL;
307 This->nSinks--;
308 return S_OK;
311 /************************************************************************
312 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
315 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
316 IConnectionPoint *iface,
317 LPENUMCONNECTIONS *ppEnum)
319 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
320 CONNECTDATA *pCD;
321 DWORD i, nextslot;
322 EnumConnectionsImpl *EnumObj;
323 HRESULT hr;
325 TRACE("(%p)->(%p)\n", This, ppEnum);
327 *ppEnum = NULL;
329 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
331 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
333 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
334 if(This->sinks[i] != NULL) {
335 pCD[nextslot].pUnk = This->sinks[i];
336 pCD[nextslot].dwCookie = i + 1;
337 nextslot++;
340 assert(nextslot == This->nSinks);
342 /* Bump the ref count of this object up by one. It gets Released in
343 IEnumConnections_Release */
344 IUnknown_AddRef((IUnknown*)This);
346 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
347 hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
348 &IID_IEnumConnections, (LPVOID)ppEnum);
349 IEnumConnections_Release((IEnumConnections*)EnumObj);
351 HeapFree(GetProcessHeap(), 0, pCD);
352 return hr;
355 static IConnectionPointVtbl ConnectionPointImpl_VTable =
357 ConnectionPointImpl_QueryInterface,
358 ConnectionPointImpl_AddRef,
359 ConnectionPointImpl_Release,
360 ConnectionPointImpl_GetConnectionInterface,
361 ConnectionPointImpl_GetConnectionPointContainer,
362 ConnectionPointImpl_Advise,
363 ConnectionPointImpl_Unadvise,
364 ConnectionPointImpl_EnumConnections
368 static IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
369 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
371 /************************************************************************
372 * EnumConnectionsImpl_Construct
374 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
375 DWORD nSinks,
376 CONNECTDATA *pCD)
378 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
379 DWORD i;
381 Obj->lpvtbl = &EnumConnectionsImpl_VTable;
382 Obj->ref = 1;
383 Obj->pUnk = pUnk;
384 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
385 Obj->nConns = nSinks;
386 Obj->nCur = 0;
388 for(i = 0; i < nSinks; i++) {
389 Obj->pCD[i] = pCD[i];
390 IUnknown_AddRef(Obj->pCD[i].pUnk);
392 return Obj;
395 /************************************************************************
396 * EnumConnectionsImpl_Destroy
398 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
400 DWORD i;
402 for(i = 0; i < Obj->nConns; i++)
403 IUnknown_Release(Obj->pCD[i].pUnk);
405 HeapFree(GetProcessHeap(), 0, Obj->pCD);
406 HeapFree(GetProcessHeap(), 0, Obj);
407 return;
410 /************************************************************************
411 * EnumConnectionsImpl_QueryInterface (IUnknown)
413 * See Windows documentation for more details on IUnknown methods.
415 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
416 IEnumConnections* iface,
417 REFIID riid,
418 void** ppvObject)
420 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
421 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
424 * Perform a sanity check on the parameters.
426 if ( (This==0) || (ppvObject==0) )
427 return E_INVALIDARG;
430 * Initialize the return parameter.
432 *ppvObject = 0;
435 * Compare the riid with the interface IDs implemented by this object.
437 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
439 *ppvObject = (IEnumConnections*)This;
441 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
443 *ppvObject = (IEnumConnections*)This;
447 * Check that we obtained an interface.
449 if ((*ppvObject)==0)
451 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
452 return E_NOINTERFACE;
456 * Query Interface always increases the reference count by one when it is
457 * successful
459 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
461 return S_OK;
465 /************************************************************************
466 * EnumConnectionsImpl_AddRef (IUnknown)
468 * See Windows documentation for more details on IUnknown methods.
470 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
472 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
473 ULONG ref;
474 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
475 ref = InterlockedIncrement(&This->ref);
476 IUnknown_AddRef(This->pUnk);
477 return ref;
480 /************************************************************************
481 * EnumConnectionsImpl_Release (IUnknown)
483 * See Windows documentation for more details on IUnknown methods.
485 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
487 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
488 ULONG ref;
489 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
491 IUnknown_Release(This->pUnk);
494 * Decrease the reference count on this object.
496 ref = InterlockedDecrement(&This->ref);
499 * If the reference count goes down to 0, perform suicide.
501 if (ref == 0) EnumConnectionsImpl_Destroy(This);
503 return ref;
506 /************************************************************************
507 * EnumConnectionsImpl_Next (IEnumConnections)
510 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
511 ULONG cConn, LPCONNECTDATA pCD,
512 ULONG *pEnum)
514 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
515 DWORD nRet = 0;
516 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
518 if(pEnum == NULL) {
519 if(cConn != 1)
520 return E_POINTER;
521 } else
522 *pEnum = 0;
524 if(This->nCur >= This->nConns)
525 return S_FALSE;
527 while(This->nCur < This->nConns && cConn) {
528 *pCD++ = This->pCD[This->nCur];
529 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
530 This->nCur++;
531 cConn--;
532 nRet++;
535 if(pEnum)
536 *pEnum = nRet;
538 return S_OK;
542 /************************************************************************
543 * EnumConnectionsImpl_Skip (IEnumConnections)
546 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
547 ULONG cSkip)
549 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
550 TRACE("(%p)->(%ld)\n", This, cSkip);
552 if(This->nCur + cSkip >= This->nConns)
553 return S_FALSE;
555 This->nCur += cSkip;
557 return S_OK;
561 /************************************************************************
562 * EnumConnectionsImpl_Reset (IEnumConnections)
565 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
567 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
568 TRACE("(%p)\n", This);
570 This->nCur = 0;
572 return S_OK;
576 /************************************************************************
577 * EnumConnectionsImpl_Clone (IEnumConnections)
580 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
581 LPENUMCONNECTIONS *ppEnum)
583 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
584 EnumConnectionsImpl *newObj;
585 TRACE("(%p)->(%p)\n", This, ppEnum);
587 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
588 newObj->nCur = This->nCur;
589 *ppEnum = (LPENUMCONNECTIONS)newObj;
590 IUnknown_AddRef(This->pUnk);
591 return S_OK;
594 static IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
596 EnumConnectionsImpl_QueryInterface,
597 EnumConnectionsImpl_AddRef,
598 EnumConnectionsImpl_Release,
599 EnumConnectionsImpl_Next,
600 EnumConnectionsImpl_Skip,
601 EnumConnectionsImpl_Reset,
602 EnumConnectionsImpl_Clone
605 /************************************************************************
607 * The exported function to create the connection point.
608 * NB not a windows API
610 * PARAMS
611 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
612 * Needed to access IConnectionPointContainer.
614 * riid [in] IID of sink interface that this ConnectionPoint manages
616 * pCP [out] returns IConnectionPoint
619 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
620 IConnectionPoint **pCP)
622 ConnectionPointImpl *Obj;
623 HRESULT hr;
625 Obj = ConnectionPointImpl_Construct(pUnk, riid);
626 if(!Obj) return E_OUTOFMEMORY;
628 hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
629 &IID_IConnectionPoint, (LPVOID)pCP);
630 IConnectionPoint_Release((IConnectionPoint *)Obj);
631 return hr;