Add spawnvp to the portability lib.
[wine/testsucceed.git] / dlls / oleaut32 / connpt.c
blobe9415a72b2014d85db977833f0ae9546e9b0cca0
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 <string.h>
27 #include "winerror.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "ole2.h"
32 #include "olectl.h"
33 #include "connpt.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39 #define MAXSINKS 10
41 /************************************************************************
42 * Implementation of IConnectionPoint
44 typedef struct ConnectionPointImpl {
46 ICOM_VTABLE(IConnectionPoint) *lpvtbl;
48 /* IUnknown of our main object*/
49 IUnknown *Obj;
51 /* Reference count */
52 DWORD ref;
54 /* IID of sink interface */
55 IID iid;
57 /* Array of sink IUnknowns */
58 IUnknown **sinks;
59 DWORD maxSinks;
61 DWORD nSinks;
62 } ConnectionPointImpl;
64 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable;
67 /************************************************************************
68 * Implementation of IEnumConnections
70 typedef struct EnumConnectionsImpl {
72 ICOM_VTABLE(IEnumConnections) *lpvtbl;
74 DWORD ref;
76 /* IUnknown of ConnectionPoint, used for ref counting */
77 IUnknown *pUnk;
79 /* Connection Data */
80 CONNECTDATA *pCD;
81 DWORD nConns;
83 /* Next connection to enumerate from */
84 DWORD nCur;
86 } EnumConnectionsImpl;
88 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
89 DWORD nSinks,
90 CONNECTDATA *pCD);
93 /************************************************************************
94 * ConnectionPointImpl_Construct
96 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
97 REFIID riid)
99 ConnectionPointImpl *Obj;
101 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
102 Obj->lpvtbl = &ConnectionPointImpl_VTable;
103 Obj->Obj = pUnk;
104 Obj->ref = 1;
105 Obj->iid = *riid;
106 Obj->maxSinks = MAXSINKS;
107 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
108 sizeof(IUnknown*) * MAXSINKS);
109 Obj->nSinks = 0;
110 return Obj;
113 /************************************************************************
114 * ConnectionPointImpl_Destroy
116 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
118 DWORD i;
119 for(i = 0; i < Obj->maxSinks; i++) {
120 if(Obj->sinks[i]) {
121 IUnknown_Release(Obj->sinks[i]);
122 Obj->sinks[i] = NULL;
125 HeapFree(GetProcessHeap(), 0, Obj->sinks);
126 HeapFree(GetProcessHeap(), 0, Obj);
127 return;
130 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
131 /************************************************************************
132 * ConnectionPointImpl_QueryInterface (IUnknown)
134 * See Windows documentation for more details on IUnknown methods.
136 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
137 IConnectionPoint* iface,
138 REFIID riid,
139 void** ppvObject)
141 ICOM_THIS(ConnectionPointImpl, iface);
142 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
145 * Perform a sanity check on the parameters.
147 if ( (This==0) || (ppvObject==0) )
148 return E_INVALIDARG;
151 * Initialize the return parameter.
153 *ppvObject = 0;
156 * Compare the riid with the interface IDs implemented by this object.
158 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
160 *ppvObject = (IConnectionPoint*)This;
162 else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0)
164 *ppvObject = (IConnectionPoint*)This;
168 * Check that we obtained an interface.
170 if ((*ppvObject)==0)
172 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
173 return E_NOINTERFACE;
177 * Query Interface always increases the reference count by one when it is
178 * successful
180 ConnectionPointImpl_AddRef((IConnectionPoint*)This);
182 return S_OK;
186 /************************************************************************
187 * ConnectionPointImpl_AddRef (IUnknown)
189 * See Windows documentation for more details on IUnknown methods.
191 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
193 ICOM_THIS(ConnectionPointImpl, iface);
194 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
195 This->ref++;
197 return This->ref;
200 /************************************************************************
201 * ConnectionPointImpl_Release (IUnknown)
203 * See Windows documentation for more details on IUnknown methods.
205 static ULONG WINAPI ConnectionPointImpl_Release(
206 IConnectionPoint* iface)
208 ICOM_THIS(ConnectionPointImpl, iface);
209 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
212 * Decrease the reference count on this object.
214 This->ref--;
217 * If the reference count goes down to 0, perform suicide.
219 if (This->ref==0)
221 ConnectionPointImpl_Destroy(This);
223 return 0;
226 return This->ref;
229 /************************************************************************
230 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
233 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
234 IConnectionPoint *iface,
235 IID *piid)
237 ICOM_THIS(ConnectionPointImpl, iface);
238 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
239 *piid = This->iid;
240 return S_OK;
243 /************************************************************************
244 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
247 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
248 IConnectionPoint *iface,
249 IConnectionPointContainer **ppCPC)
251 ICOM_THIS(ConnectionPointImpl, iface);
252 TRACE("(%p)->(%p)\n", This, ppCPC);
254 return IUnknown_QueryInterface(This->Obj,
255 &IID_IConnectionPointContainer,
256 (LPVOID)ppCPC);
259 /************************************************************************
260 * ConnectionPointImpl_Advise (IConnectionPoint)
263 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
264 IUnknown *lpUnk,
265 DWORD *pdwCookie)
267 DWORD i;
268 ICOM_THIS(ConnectionPointImpl, iface);
269 IUnknown *lpSink;
270 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
272 *pdwCookie = 0;
273 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
274 return CONNECT_E_CANNOTCONNECT;
276 for(i = 0; i < This->maxSinks; i++) {
277 if(This->sinks[i] == NULL)
278 break;
280 if(i == This->maxSinks) {
281 This->maxSinks += MAXSINKS;
282 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
283 This->maxSinks * sizeof(IUnknown *));
285 This->sinks[i] = lpSink;
286 This->nSinks++;
287 *pdwCookie = i + 1;
288 return S_OK;
292 /************************************************************************
293 * ConnectionPointImpl_Unadvise (IConnectionPoint)
296 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
297 DWORD dwCookie)
299 ICOM_THIS(ConnectionPointImpl, iface);
300 TRACE("(%p)->(%ld)\n", This, dwCookie);
302 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
304 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
306 IUnknown_Release(This->sinks[dwCookie-1]);
307 This->sinks[dwCookie-1] = NULL;
308 This->nSinks--;
309 return S_OK;
312 /************************************************************************
313 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
316 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
317 IConnectionPoint *iface,
318 LPENUMCONNECTIONS *ppEnum)
320 ICOM_THIS(ConnectionPointImpl, iface);
321 CONNECTDATA *pCD;
322 DWORD i, nextslot;
323 EnumConnectionsImpl *EnumObj;
324 HRESULT hr;
326 TRACE("(%p)->(%p)\n", This, ppEnum);
328 *ppEnum = NULL;
330 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
332 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
334 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
335 if(This->sinks[i] != NULL) {
336 pCD[nextslot].pUnk = This->sinks[i];
337 pCD[nextslot].dwCookie = i + 1;
338 nextslot++;
341 assert(nextslot == This->nSinks);
343 /* Bump the ref count of this object up by one. It gets Released in
344 IEnumConnections_Release */
345 IUnknown_AddRef((IUnknown*)This);
347 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
348 hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
349 &IID_IEnumConnections, (LPVOID)ppEnum);
350 IEnumConnections_Release((IEnumConnections*)EnumObj);
352 HeapFree(GetProcessHeap(), 0, pCD);
353 return hr;
356 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable =
358 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
359 ConnectionPointImpl_QueryInterface,
360 ConnectionPointImpl_AddRef,
361 ConnectionPointImpl_Release,
362 ConnectionPointImpl_GetConnectionInterface,
363 ConnectionPointImpl_GetConnectionPointContainer,
364 ConnectionPointImpl_Advise,
365 ConnectionPointImpl_Unadvise,
366 ConnectionPointImpl_EnumConnections
370 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable;
371 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
373 /************************************************************************
374 * EnumConnectionsImpl_Construct
376 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
377 DWORD nSinks,
378 CONNECTDATA *pCD)
380 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
381 DWORD i;
383 Obj->lpvtbl = &EnumConnectionsImpl_VTable;
384 Obj->ref = 1;
385 Obj->pUnk = pUnk;
386 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
387 Obj->nConns = nSinks;
388 Obj->nCur = 0;
390 for(i = 0; i < nSinks; i++) {
391 Obj->pCD[i] = pCD[i];
392 IUnknown_AddRef(Obj->pCD[i].pUnk);
394 return Obj;
397 /************************************************************************
398 * EnumConnectionsImpl_Destroy
400 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
402 DWORD i;
404 for(i = 0; i < Obj->nConns; i++)
405 IUnknown_Release(Obj->pCD[i].pUnk);
407 HeapFree(GetProcessHeap(), 0, Obj->pCD);
408 HeapFree(GetProcessHeap(), 0, Obj);
409 return;
412 /************************************************************************
413 * EnumConnectionsImpl_QueryInterface (IUnknown)
415 * See Windows documentation for more details on IUnknown methods.
417 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
418 IEnumConnections* iface,
419 REFIID riid,
420 void** ppvObject)
422 ICOM_THIS(ConnectionPointImpl, iface);
423 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
426 * Perform a sanity check on the parameters.
428 if ( (This==0) || (ppvObject==0) )
429 return E_INVALIDARG;
432 * Initialize the return parameter.
434 *ppvObject = 0;
437 * Compare the riid with the interface IDs implemented by this object.
439 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
441 *ppvObject = (IEnumConnections*)This;
443 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
445 *ppvObject = (IEnumConnections*)This;
449 * Check that we obtained an interface.
451 if ((*ppvObject)==0)
453 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
454 return E_NOINTERFACE;
458 * Query Interface always increases the reference count by one when it is
459 * successful
461 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
463 return S_OK;
467 /************************************************************************
468 * EnumConnectionsImpl_AddRef (IUnknown)
470 * See Windows documentation for more details on IUnknown methods.
472 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
474 ICOM_THIS(EnumConnectionsImpl, iface);
475 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
476 This->ref++;
477 IUnknown_AddRef(This->pUnk);
478 return This->ref;
481 /************************************************************************
482 * EnumConnectionsImpl_Release (IUnknown)
484 * See Windows documentation for more details on IUnknown methods.
486 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
488 ICOM_THIS(EnumConnectionsImpl, iface);
489 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
491 IUnknown_Release(This->pUnk);
494 * Decrease the reference count on this object.
496 This->ref--;
499 * If the reference count goes down to 0, perform suicide.
501 if (This->ref==0)
503 EnumConnectionsImpl_Destroy(This);
505 return 0;
508 return This->ref;
511 /************************************************************************
512 * EnumConnectionsImpl_Next (IEnumConnections)
515 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
516 ULONG cConn, LPCONNECTDATA pCD,
517 ULONG *pEnum)
519 ICOM_THIS(EnumConnectionsImpl, iface);
520 DWORD nRet = 0;
521 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
523 if(pEnum == NULL) {
524 if(cConn != 1)
525 return E_POINTER;
526 } else
527 *pEnum = 0;
529 if(This->nCur >= This->nConns)
530 return S_FALSE;
532 while(This->nCur < This->nConns && cConn) {
533 *pCD++ = This->pCD[This->nCur];
534 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
535 This->nCur++;
536 cConn--;
537 nRet++;
540 if(pEnum)
541 *pEnum = nRet;
543 return S_OK;
547 /************************************************************************
548 * EnumConnectionsImpl_Skip (IEnumConnections)
551 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
552 ULONG cSkip)
554 ICOM_THIS(EnumConnectionsImpl, iface);
555 TRACE("(%p)->(%ld)\n", This, cSkip);
557 if(This->nCur + cSkip >= This->nConns)
558 return S_FALSE;
560 This->nCur += cSkip;
562 return S_OK;
566 /************************************************************************
567 * EnumConnectionsImpl_Reset (IEnumConnections)
570 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
572 ICOM_THIS(EnumConnectionsImpl, iface);
573 TRACE("(%p)\n", This);
575 This->nCur = 0;
577 return S_OK;
581 /************************************************************************
582 * EnumConnectionsImpl_Clone (IEnumConnections)
585 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
586 LPENUMCONNECTIONS *ppEnum)
588 ICOM_THIS(EnumConnectionsImpl, iface);
589 EnumConnectionsImpl *newObj;
590 TRACE("(%p)->(%p)\n", This, ppEnum);
592 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
593 newObj->nCur = This->nCur;
594 *ppEnum = (LPENUMCONNECTIONS)newObj;
595 IUnknown_AddRef(This->pUnk);
596 return S_OK;
599 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable =
601 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
602 EnumConnectionsImpl_QueryInterface,
603 EnumConnectionsImpl_AddRef,
604 EnumConnectionsImpl_Release,
605 EnumConnectionsImpl_Next,
606 EnumConnectionsImpl_Skip,
607 EnumConnectionsImpl_Reset,
608 EnumConnectionsImpl_Clone
611 /************************************************************************
613 * The exported function to create the connection point.
614 * NB not a windows API
616 * PARAMS
617 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
618 * Needed to access IConnectionPointContainer.
620 * riid [in] IID of sink interface that this ConnectionPoint manages
622 * pCP [out] returns IConnectionPoint
625 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
626 IConnectionPoint **pCP)
628 ConnectionPointImpl *Obj;
629 HRESULT hr;
631 Obj = ConnectionPointImpl_Construct(pUnk, riid);
632 if(!Obj) return E_OUTOFMEMORY;
634 hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
635 &IID_IConnectionPoint, (LPVOID)pCP);
636 IConnectionPoint_Release((IConnectionPoint *)Obj);
637 return hr;