include: Be consistent in naming regarding MSF's block.
[wine.git] / dlls / mshtml / conpoint.c
blob95043e7cec6776848faf3a2dd416ca0dfe935ff2
1 /*
2 * Copyright 2006 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
28 #include "wine/debug.h"
30 #include "mshtml_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
34 typedef struct {
35 IEnumConnections IEnumConnections_iface;
37 LONG ref;
39 unsigned iter;
40 ConnectionPoint *cp;
41 } EnumConnections;
43 static inline EnumConnections *impl_from_IEnumConnections(IEnumConnections *iface)
45 return CONTAINING_RECORD(iface, EnumConnections, IEnumConnections_iface);
48 static HRESULT WINAPI EnumConnections_QueryInterface(IEnumConnections *iface, REFIID riid, void **ppv)
50 EnumConnections *This = impl_from_IEnumConnections(iface);
52 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
54 if(IsEqualGUID(riid, &IID_IUnknown)) {
55 *ppv = &This->IEnumConnections_iface;
56 }else if(IsEqualGUID(riid, &IID_IEnumConnections)) {
57 *ppv = &This->IEnumConnections_iface;
58 }else {
59 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
60 *ppv = NULL;
61 return E_NOINTERFACE;
64 IUnknown_AddRef((IUnknown*)*ppv);
65 return S_OK;
68 static ULONG WINAPI EnumConnections_AddRef(IEnumConnections *iface)
70 EnumConnections *This = impl_from_IEnumConnections(iface);
71 ULONG ref = InterlockedIncrement(&This->ref);
73 TRACE("(%p) ref=%ld\n", This, ref);
75 return ref;
78 static ULONG WINAPI EnumConnections_Release(IEnumConnections *iface)
80 EnumConnections *This = impl_from_IEnumConnections(iface);
81 ULONG ref = InterlockedDecrement(&This->ref);
83 TRACE("(%p) ref=%ld\n", This, ref);
85 if(!ref) {
86 IConnectionPoint_Release(&This->cp->IConnectionPoint_iface);
87 free(This);
90 return ref;
93 static HRESULT WINAPI EnumConnections_Next(IEnumConnections *iface, ULONG cConnections, CONNECTDATA *rgcd, ULONG *pcFetched)
95 EnumConnections *This = impl_from_IEnumConnections(iface);
96 ULONG fetched = 0;
98 TRACE("(%p)->(%ld %p %p)\n", This, cConnections, rgcd, pcFetched);
100 while(fetched < cConnections && This->iter < This->cp->sinks_size) {
101 if(!This->cp->sinks[This->iter].unk) {
102 This->iter++;
103 continue;
106 rgcd[fetched].pUnk = This->cp->sinks[This->iter].unk;
107 rgcd[fetched].dwCookie = ++This->iter;
108 IUnknown_AddRef(rgcd[fetched].pUnk);
109 fetched++;
112 if(pcFetched)
113 *pcFetched = fetched;
114 return fetched == cConnections ? S_OK : S_FALSE;
117 static HRESULT WINAPI EnumConnections_Skip(IEnumConnections *iface, ULONG cConnections)
119 EnumConnections *This = impl_from_IEnumConnections(iface);
120 FIXME("(%p)->(%ld)\n", This, cConnections);
121 return E_NOTIMPL;
124 static HRESULT WINAPI EnumConnections_Reset(IEnumConnections *iface)
126 EnumConnections *This = impl_from_IEnumConnections(iface);
127 FIXME("(%p)\n", This);
128 return E_NOTIMPL;
131 static HRESULT WINAPI EnumConnections_Clone(IEnumConnections *iface, IEnumConnections **ppEnum)
133 EnumConnections *This = impl_from_IEnumConnections(iface);
134 FIXME("(%p)->(%p)\n", This, ppEnum);
135 return E_NOTIMPL;
138 static const IEnumConnectionsVtbl EnumConnectionsVtbl = {
139 EnumConnections_QueryInterface,
140 EnumConnections_AddRef,
141 EnumConnections_Release,
142 EnumConnections_Next,
143 EnumConnections_Skip,
144 EnumConnections_Reset,
145 EnumConnections_Clone
148 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
150 return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
153 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
154 REFIID riid, LPVOID *ppv)
156 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
158 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
160 if(IsEqualGUID(&IID_IUnknown, riid)) {
161 *ppv = &This->IConnectionPoint_iface;
162 }else if(IsEqualGUID(&IID_IConnectionPoint, riid)) {
163 *ppv = &This->IConnectionPoint_iface;
164 }else {
165 *ppv = NULL;
166 WARN("Unsupported interface %s\n", debugstr_mshtml_guid(riid));
167 return E_NOINTERFACE;
170 IUnknown_AddRef((IUnknown*)*ppv);
171 return S_OK;
174 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
176 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
177 return IConnectionPointContainer_AddRef(&This->container->IConnectionPointContainer_iface);
180 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
182 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
183 return IConnectionPointContainer_Release(&This->container->IConnectionPointContainer_iface);
186 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID)
188 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
190 TRACE("(%p)->(%p)\n", This, pIID);
192 if(!pIID)
193 return E_POINTER;
195 *pIID = *This->iid;
196 return S_OK;
199 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
200 IConnectionPointContainer **ppCPC)
202 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
204 TRACE("(%p)->(%p)\n", This, ppCPC);
206 if(!ppCPC)
207 return E_POINTER;
209 *ppCPC = &This->container->IConnectionPointContainer_iface;
210 IConnectionPointContainer_AddRef(*ppCPC);
211 return S_OK;
214 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
215 DWORD *pdwCookie)
217 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
218 IUnknown *sink;
219 void *new_sinks;
220 DWORD i;
221 HRESULT hres;
223 TRACE("(%p)->(%p %p)\n", This, pUnkSink, pdwCookie);
225 hres = IUnknown_QueryInterface(pUnkSink, This->iid, (void**)&sink);
226 if(FAILED(hres) && !IsEqualGUID(&IID_IPropertyNotifySink, This->iid))
227 hres = IUnknown_QueryInterface(pUnkSink, &IID_IDispatch, (void**)&sink);
228 if(FAILED(hres))
229 return CONNECT_E_CANNOTCONNECT;
231 for(i = 0; i < This->sinks_size; i++) {
232 if(!This->sinks[i].unk)
233 break;
236 if(i == This->sinks_size) {
237 new_sinks = realloc(This->sinks, (This->sinks_size + 1) * sizeof(*This->sinks));
238 if(!new_sinks) {
239 IUnknown_Release(sink);
240 return E_OUTOFMEMORY;
242 This->sinks = new_sinks;
243 This->sinks_size++;
246 This->sinks[i].unk = sink;
247 if(pdwCookie)
248 *pdwCookie = i+1;
250 if(!i && This->data && This->data->on_advise)
251 This->data->on_advise(This->container->outer, This->data);
253 return S_OK;
256 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
258 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
259 TRACE("(%p)->(%ld)\n", This, dwCookie);
261 if(!dwCookie || dwCookie > This->sinks_size || !This->sinks[dwCookie-1].unk)
262 return CONNECT_E_NOCONNECTION;
264 IUnknown_Release(This->sinks[dwCookie-1].unk);
265 This->sinks[dwCookie-1].unk = NULL;
267 return S_OK;
270 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
271 IEnumConnections **ppEnum)
273 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
274 EnumConnections *ret;
276 TRACE("(%p)->(%p)\n", This, ppEnum);
278 ret = malloc(sizeof(*ret));
279 if(!ret)
280 return E_OUTOFMEMORY;
282 ret->IEnumConnections_iface.lpVtbl = &EnumConnectionsVtbl;
283 ret->ref = 1;
284 ret->iter = 0;
286 IConnectionPoint_AddRef(&This->IConnectionPoint_iface);
287 ret->cp = This;
289 *ppEnum = &ret->IEnumConnections_iface;
290 return S_OK;
293 static const IConnectionPointVtbl ConnectionPointVtbl =
295 ConnectionPoint_QueryInterface,
296 ConnectionPoint_AddRef,
297 ConnectionPoint_Release,
298 ConnectionPoint_GetConnectionInterface,
299 ConnectionPoint_GetConnectionPointContainer,
300 ConnectionPoint_Advise,
301 ConnectionPoint_Unadvise,
302 ConnectionPoint_EnumConnections
305 static void ConnectionPoint_Init(ConnectionPoint *cp, ConnectionPointContainer *container, REFIID riid, cp_static_data_t *data)
307 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
308 cp->container = container;
309 cp->sinks = NULL;
310 cp->sinks_size = 0;
311 cp->iid = riid;
312 cp->data = data;
315 static void ConnectionPoint_Destroy(ConnectionPoint *This)
317 DWORD i;
319 for(i=0; i<This->sinks_size; i++) {
320 if(This->sinks[i].unk)
321 IUnknown_Release(This->sinks[i].unk);
324 free(This->sinks);
327 static ConnectionPoint *get_cp(ConnectionPointContainer *container, REFIID riid, BOOL do_create)
329 const cpc_entry_t *iter;
330 unsigned idx, i;
332 for(iter = container->cp_entries; iter->riid; iter++) {
333 if(IsEqualGUID(iter->riid, riid))
334 break;
336 if(!iter->riid)
337 return NULL;
338 idx = iter - container->cp_entries;
340 if(!container->cps) {
341 if(!do_create)
342 return NULL;
344 while(iter->riid)
345 iter++;
346 container->cps = malloc((iter - container->cp_entries) * sizeof(*container->cps));
347 if(!container->cps)
348 return NULL;
350 for(i=0; container->cp_entries[i].riid; i++)
351 ConnectionPoint_Init(container->cps+i, container, container->cp_entries[i].riid, container->cp_entries[i].desc);
354 return container->cps+idx;
357 void call_property_onchanged(ConnectionPointContainer *container, DISPID dispid)
359 ConnectionPoint *cp;
360 DWORD i;
362 cp = get_cp(container, &IID_IPropertyNotifySink, FALSE);
363 if(!cp)
364 return;
366 for(i=0; i<cp->sinks_size; i++) {
367 if(cp->sinks[i].propnotif)
368 IPropertyNotifySink_OnChanged(cp->sinks[i].propnotif, dispid);
372 static inline ConnectionPointContainer *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
374 return CONTAINING_RECORD(iface, ConnectionPointContainer, IConnectionPointContainer_iface);
377 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
378 REFIID riid, void **ppv)
380 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
381 return IUnknown_QueryInterface(This->outer, riid, ppv);
384 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
386 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
387 return IUnknown_AddRef(This->outer);
390 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
392 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
393 return IUnknown_Release(This->outer);
396 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
397 IEnumConnectionPoints **ppEnum)
399 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
400 FIXME("(%p)->(%p)\n", This, ppEnum);
401 return E_NOTIMPL;
404 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
405 REFIID riid, IConnectionPoint **ppCP)
407 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
408 ConnectionPoint *cp;
410 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppCP);
412 if(This->forward_container)
413 return IConnectionPointContainer_FindConnectionPoint(&This->forward_container->IConnectionPointContainer_iface,
414 riid, ppCP);
416 cp = get_cp(This, riid, TRUE);
417 if(!cp) {
418 FIXME("unsupported riid %s\n", debugstr_mshtml_guid(riid));
419 *ppCP = NULL;
420 return CONNECT_E_NOCONNECTION;
423 *ppCP = &cp->IConnectionPoint_iface;
424 IConnectionPoint_AddRef(*ppCP);
425 return S_OK;
428 static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl = {
429 ConnectionPointContainer_QueryInterface,
430 ConnectionPointContainer_AddRef,
431 ConnectionPointContainer_Release,
432 ConnectionPointContainer_EnumConnectionPoints,
433 ConnectionPointContainer_FindConnectionPoint
436 void ConnectionPointContainer_Init(ConnectionPointContainer *This, IUnknown *outer, const cpc_entry_t *cp_entries)
438 This->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
439 This->cp_entries = cp_entries;
440 This->cps = NULL;
441 This->outer = outer;
442 This->forward_container = NULL;
445 void ConnectionPointContainer_Destroy(ConnectionPointContainer *This)
447 unsigned i;
449 if(!This->cps)
450 return;
452 for(i=0; This->cp_entries[i].riid; i++)
453 ConnectionPoint_Destroy(This->cps+i);
454 free(This->cps);