windows.networking.hostname/tests: Add IHostNameFactory::CreateHostName() tests.
[wine.git] / dlls / oleaut32 / connpt.c
blob993f2d9cf08787c6dae4ca351bb2a0a94e1abc7e
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 IConnectionPoint IConnectionPoint_iface;
53 /* IUnknown of our main object*/
54 IUnknown *Obj;
56 /* Reference count */
57 LONG 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 /************************************************************************
70 * Implementation of IEnumConnections
72 typedef struct EnumConnectionsImpl {
74 IEnumConnections IEnumConnections_iface;
76 LONG ref;
78 /* IUnknown of ConnectionPoint, used for ref counting */
79 IUnknown *pUnk;
81 /* Connection Data */
82 CONNECTDATA *pCD;
83 DWORD nConns;
85 /* Next connection to enumerate from */
86 DWORD nCur;
88 } EnumConnectionsImpl;
90 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
91 DWORD nSinks,
92 CONNECTDATA *pCD);
94 static inline ConnectionPointImpl *impl_from_IConnectionPoint(IConnectionPoint *iface)
96 return CONTAINING_RECORD(iface, ConnectionPointImpl, IConnectionPoint_iface);
99 static inline EnumConnectionsImpl *impl_from_IEnumConnections(IEnumConnections *iface)
101 return CONTAINING_RECORD(iface, EnumConnectionsImpl, IEnumConnections_iface);
104 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
106 DWORD i;
107 for(i = 0; i < Obj->maxSinks; i++) {
108 if(Obj->sinks[i]) {
109 IUnknown_Release(Obj->sinks[i]);
110 Obj->sinks[i] = NULL;
113 HeapFree(GetProcessHeap(), 0, Obj->sinks);
114 HeapFree(GetProcessHeap(), 0, Obj);
115 return;
118 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
119 IConnectionPoint* iface,
120 REFIID riid,
121 void** ppvObject)
123 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
124 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
127 * Perform a sanity check on the parameters.
129 if (!ppvObject)
130 return E_INVALIDARG;
133 * Initialize the return parameter.
135 *ppvObject = 0;
138 if (IsEqualIID(&IID_IConnectionPoint, riid) || IsEqualIID(&IID_IUnknown, riid))
139 *ppvObject = iface;
142 * Check that we obtained an interface.
144 if ((*ppvObject)==0)
146 FIXME("() : asking for unsupported interface %s\n", debugstr_guid(riid));
147 return E_NOINTERFACE;
150 IUnknown_AddRef((IUnknown*)*ppvObject);
152 return S_OK;
155 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
157 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
158 ULONG refCount = InterlockedIncrement(&This->ref);
160 TRACE("%p, refcount %lu.\n", iface, refCount);
162 return refCount;
165 static ULONG WINAPI ConnectionPointImpl_Release(
166 IConnectionPoint* iface)
168 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
169 ULONG refCount = InterlockedDecrement(&This->ref);
171 TRACE("%p, refcount %lu.\n", iface, refCount);
173 if (!refCount) ConnectionPointImpl_Destroy(This);
175 return refCount;
178 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
179 IConnectionPoint *iface,
180 IID *piid)
182 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
183 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
184 *piid = This->iid;
185 return S_OK;
188 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
189 IConnectionPoint *iface,
190 IConnectionPointContainer **ppCPC)
192 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
193 TRACE("(%p)->(%p)\n", This, ppCPC);
195 return IUnknown_QueryInterface(This->Obj, &IID_IConnectionPointContainer, (void**)ppCPC);
198 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
199 IUnknown *lpUnk,
200 DWORD *pdwCookie)
202 DWORD i;
203 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
204 IUnknown *lpSink;
205 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
207 *pdwCookie = 0;
208 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (void**)&lpSink)))
209 return CONNECT_E_CANNOTCONNECT;
211 for(i = 0; i < This->maxSinks; i++) {
212 if(This->sinks[i] == NULL)
213 break;
215 if(i == This->maxSinks) {
216 This->maxSinks += MAXSINKS;
217 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
218 This->maxSinks * sizeof(IUnknown *));
220 This->sinks[i] = lpSink;
221 This->nSinks++;
222 *pdwCookie = i + 1;
223 return S_OK;
227 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
229 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
231 TRACE("%p, %#lx.\n", iface, dwCookie);
233 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
235 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
237 IUnknown_Release(This->sinks[dwCookie-1]);
238 This->sinks[dwCookie-1] = NULL;
239 This->nSinks--;
240 return S_OK;
243 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(IConnectionPoint *iface, IEnumConnections **ppEnum)
245 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
246 CONNECTDATA *pCD;
247 DWORD i, nextslot;
248 EnumConnectionsImpl *EnumObj;
249 HRESULT hr;
251 TRACE("(%p)->(%p)\n", This, ppEnum);
253 *ppEnum = NULL;
255 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
257 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
259 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
260 if(This->sinks[i] != NULL) {
261 pCD[nextslot].pUnk = This->sinks[i];
262 pCD[nextslot].dwCookie = i + 1;
263 nextslot++;
266 assert(nextslot == This->nSinks);
268 /* Bump the ref count of this object up by one. It gets Released in
269 IEnumConnections_Release */
270 IConnectionPoint_AddRef(iface);
272 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)iface, This->nSinks, pCD);
273 hr = IEnumConnections_QueryInterface(&EnumObj->IEnumConnections_iface,
274 &IID_IEnumConnections, (void**)ppEnum);
275 IEnumConnections_Release(&EnumObj->IEnumConnections_iface);
277 HeapFree(GetProcessHeap(), 0, pCD);
278 return hr;
281 static const IConnectionPointVtbl ConnectionPointImpl_VTable =
283 ConnectionPointImpl_QueryInterface,
284 ConnectionPointImpl_AddRef,
285 ConnectionPointImpl_Release,
286 ConnectionPointImpl_GetConnectionInterface,
287 ConnectionPointImpl_GetConnectionPointContainer,
288 ConnectionPointImpl_Advise,
289 ConnectionPointImpl_Unadvise,
290 ConnectionPointImpl_EnumConnections
294 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
296 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
297 DWORD nSinks,
298 CONNECTDATA *pCD)
300 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
301 DWORD i;
303 Obj->IEnumConnections_iface.lpVtbl = &EnumConnectionsImpl_VTable;
304 Obj->ref = 1;
305 Obj->pUnk = pUnk;
306 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
307 Obj->nConns = nSinks;
308 Obj->nCur = 0;
310 for(i = 0; i < nSinks; i++) {
311 Obj->pCD[i] = pCD[i];
312 IUnknown_AddRef(Obj->pCD[i].pUnk);
314 return Obj;
317 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
319 DWORD i;
321 for(i = 0; i < Obj->nConns; i++)
322 IUnknown_Release(Obj->pCD[i].pUnk);
324 HeapFree(GetProcessHeap(), 0, Obj->pCD);
325 HeapFree(GetProcessHeap(), 0, Obj);
326 return;
329 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
330 IEnumConnections* iface,
331 REFIID riid,
332 void** ppvObject)
334 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
335 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
338 * Perform a sanity check on the parameters.
340 if (!ppvObject)
341 return E_INVALIDARG;
344 * Initialize the return parameter.
346 *ppvObject = 0;
348 if (IsEqualIID(&IID_IEnumConnections, riid) || IsEqualIID(&IID_IUnknown, riid))
349 *ppvObject = iface;
352 * Check that we obtained an interface.
354 if ((*ppvObject)==0)
356 FIXME("() : asking for unsupported interface %s\n", debugstr_guid(riid));
357 return E_NOINTERFACE;
360 IUnknown_AddRef((IUnknown*)*ppvObject);
362 return S_OK;
365 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
367 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
368 ULONG refCount = InterlockedIncrement(&This->ref);
370 TRACE("%p, refcount %lu.\n", iface, refCount);
372 IUnknown_AddRef(This->pUnk);
373 return refCount;
376 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
378 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
379 ULONG refCount = InterlockedDecrement(&This->ref);
381 TRACE("%p, refcount %lu.\n", iface, refCount);
383 IUnknown_Release(This->pUnk);
385 if (!refCount) EnumConnectionsImpl_Destroy(This);
387 return refCount;
390 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface, ULONG cConn, LPCONNECTDATA pCD, ULONG *pEnum)
392 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
393 DWORD nRet = 0;
395 TRACE("%p, %lu, %p, %p.\n", iface, cConn, pCD, pEnum);
397 if(pEnum == NULL) {
398 if(cConn != 1)
399 return E_POINTER;
400 } else
401 *pEnum = 0;
403 if(This->nCur >= This->nConns)
404 return S_FALSE;
406 while(This->nCur < This->nConns && cConn) {
407 *pCD++ = This->pCD[This->nCur];
408 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
409 This->nCur++;
410 cConn--;
411 nRet++;
414 if(pEnum)
415 *pEnum = nRet;
417 return S_OK;
420 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface, ULONG cSkip)
422 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
424 TRACE("%p, %lu.\n", iface, cSkip);
426 if(This->nCur + cSkip >= This->nConns)
427 return S_FALSE;
429 This->nCur += cSkip;
431 return S_OK;
434 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
436 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
437 TRACE("(%p)\n", This);
439 This->nCur = 0;
441 return S_OK;
444 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface, IEnumConnections **ppEnum)
446 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
447 EnumConnectionsImpl *newObj;
448 TRACE("(%p)->(%p)\n", This, ppEnum);
450 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
451 newObj->nCur = This->nCur;
452 *ppEnum = &newObj->IEnumConnections_iface;
453 IUnknown_AddRef(This->pUnk);
454 return S_OK;
457 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
459 EnumConnectionsImpl_QueryInterface,
460 EnumConnectionsImpl_AddRef,
461 EnumConnectionsImpl_Release,
462 EnumConnectionsImpl_Next,
463 EnumConnectionsImpl_Skip,
464 EnumConnectionsImpl_Reset,
465 EnumConnectionsImpl_Clone
468 /************************************************************************
470 * The exported function to create the connection point.
471 * NB not a windows API
473 * PARAMS
474 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
475 * Needed to access IConnectionPointContainer.
477 * riid [in] IID of sink interface that this ConnectionPoint manages
479 * pCP [out] returns IConnectionPoint
482 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
483 IConnectionPoint **pCP)
485 ConnectionPointImpl *Obj;
487 TRACE("(%p %s %p)\n", pUnk, debugstr_guid(riid), pCP);
489 *pCP = NULL;
490 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
491 if (!Obj)
492 return E_OUTOFMEMORY;
494 Obj->IConnectionPoint_iface.lpVtbl = &ConnectionPointImpl_VTable;
495 Obj->Obj = pUnk;
496 Obj->ref = 1;
497 Obj->iid = *riid;
498 Obj->maxSinks = MAXSINKS;
499 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IUnknown*) * MAXSINKS);
500 Obj->nSinks = 0;
502 *pCP = &Obj->IConnectionPoint_iface;
503 return S_OK;