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
28 #include "wine/debug.h"
30 #include "mshtml_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
35 IEnumConnections IEnumConnections_iface
;
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
;
59 WARN("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
64 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
86 IConnectionPoint_Release(&This
->cp
->IConnectionPoint_iface
);
93 static HRESULT WINAPI
EnumConnections_Next(IEnumConnections
*iface
, ULONG cConnections
, CONNECTDATA
*rgcd
, ULONG
*pcFetched
)
95 EnumConnections
*This
= impl_from_IEnumConnections(iface
);
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
) {
106 rgcd
[fetched
].pUnk
= This
->cp
->sinks
[This
->iter
].unk
;
107 rgcd
[fetched
].dwCookie
= ++This
->iter
;
108 IUnknown_AddRef(rgcd
[fetched
].pUnk
);
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
);
124 static HRESULT WINAPI
EnumConnections_Reset(IEnumConnections
*iface
)
126 EnumConnections
*This
= impl_from_IEnumConnections(iface
);
127 FIXME("(%p)\n", This
);
131 static HRESULT WINAPI
EnumConnections_Clone(IEnumConnections
*iface
, IEnumConnections
**ppEnum
)
133 EnumConnections
*This
= impl_from_IEnumConnections(iface
);
134 FIXME("(%p)->(%p)\n", This
, ppEnum
);
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
;
166 WARN("Unsupported interface %s\n", debugstr_mshtml_guid(riid
));
167 return E_NOINTERFACE
;
170 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
209 *ppCPC
= &This
->container
->IConnectionPointContainer_iface
;
210 IConnectionPointContainer_AddRef(*ppCPC
);
214 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*pUnkSink
,
217 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
222 TRACE("(%p)->(%p %p)\n", This
, pUnkSink
, pdwCookie
);
224 hres
= IUnknown_QueryInterface(pUnkSink
, This
->iid
, (void**)&sink
);
225 if(FAILED(hres
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
226 hres
= IUnknown_QueryInterface(pUnkSink
, &IID_IDispatch
, (void**)&sink
);
228 return CONNECT_E_CANNOTCONNECT
;
231 for(i
=0; i
<This
->sinks_size
; i
++) {
232 if(!This
->sinks
[i
].unk
)
236 if(i
== This
->sinks_size
)
237 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
239 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
240 This
->sinks_size
= 1;
244 This
->sinks
[i
].unk
= sink
;
248 if(!i
&& This
->data
&& This
->data
->on_advise
)
249 This
->data
->on_advise(This
->container
->outer
, This
->data
);
254 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD dwCookie
)
256 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
257 TRACE("(%p)->(%ld)\n", This
, dwCookie
);
259 if(!dwCookie
|| dwCookie
> This
->sinks_size
|| !This
->sinks
[dwCookie
-1].unk
)
260 return CONNECT_E_NOCONNECTION
;
262 IUnknown_Release(This
->sinks
[dwCookie
-1].unk
);
263 This
->sinks
[dwCookie
-1].unk
= NULL
;
268 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
269 IEnumConnections
**ppEnum
)
271 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
272 EnumConnections
*ret
;
274 TRACE("(%p)->(%p)\n", This
, ppEnum
);
276 ret
= heap_alloc(sizeof(*ret
));
278 return E_OUTOFMEMORY
;
280 ret
->IEnumConnections_iface
.lpVtbl
= &EnumConnectionsVtbl
;
284 IConnectionPoint_AddRef(&This
->IConnectionPoint_iface
);
287 *ppEnum
= &ret
->IEnumConnections_iface
;
291 static const IConnectionPointVtbl ConnectionPointVtbl
=
293 ConnectionPoint_QueryInterface
,
294 ConnectionPoint_AddRef
,
295 ConnectionPoint_Release
,
296 ConnectionPoint_GetConnectionInterface
,
297 ConnectionPoint_GetConnectionPointContainer
,
298 ConnectionPoint_Advise
,
299 ConnectionPoint_Unadvise
,
300 ConnectionPoint_EnumConnections
303 static void ConnectionPoint_Init(ConnectionPoint
*cp
, ConnectionPointContainer
*container
, REFIID riid
, cp_static_data_t
*data
)
305 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
306 cp
->container
= container
;
313 static void ConnectionPoint_Destroy(ConnectionPoint
*This
)
317 for(i
=0; i
<This
->sinks_size
; i
++) {
318 if(This
->sinks
[i
].unk
)
319 IUnknown_Release(This
->sinks
[i
].unk
);
322 heap_free(This
->sinks
);
325 static ConnectionPoint
*get_cp(ConnectionPointContainer
*container
, REFIID riid
, BOOL do_create
)
327 const cpc_entry_t
*iter
;
330 for(iter
= container
->cp_entries
; iter
->riid
; iter
++) {
331 if(IsEqualGUID(iter
->riid
, riid
))
336 idx
= iter
- container
->cp_entries
;
338 if(!container
->cps
) {
344 container
->cps
= heap_alloc((iter
- container
->cp_entries
) * sizeof(*container
->cps
));
348 for(i
=0; container
->cp_entries
[i
].riid
; i
++)
349 ConnectionPoint_Init(container
->cps
+i
, container
, container
->cp_entries
[i
].riid
, container
->cp_entries
[i
].desc
);
352 return container
->cps
+idx
;
355 void call_property_onchanged(ConnectionPointContainer
*container
, DISPID dispid
)
360 cp
= get_cp(container
, &IID_IPropertyNotifySink
, FALSE
);
364 for(i
=0; i
<cp
->sinks_size
; i
++) {
365 if(cp
->sinks
[i
].propnotif
)
366 IPropertyNotifySink_OnChanged(cp
->sinks
[i
].propnotif
, dispid
);
370 static inline ConnectionPointContainer
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
372 return CONTAINING_RECORD(iface
, ConnectionPointContainer
, IConnectionPointContainer_iface
);
375 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
376 REFIID riid
, void **ppv
)
378 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
379 return IUnknown_QueryInterface(This
->outer
, riid
, ppv
);
382 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
384 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
385 return IUnknown_AddRef(This
->outer
);
388 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
390 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
391 return IUnknown_Release(This
->outer
);
394 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
395 IEnumConnectionPoints
**ppEnum
)
397 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
398 FIXME("(%p)->(%p)\n", This
, ppEnum
);
402 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
403 REFIID riid
, IConnectionPoint
**ppCP
)
405 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
408 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppCP
);
410 if(This
->forward_container
)
411 return IConnectionPointContainer_FindConnectionPoint(&This
->forward_container
->IConnectionPointContainer_iface
,
414 cp
= get_cp(This
, riid
, TRUE
);
416 FIXME("unsupported riid %s\n", debugstr_mshtml_guid(riid
));
418 return CONNECT_E_NOCONNECTION
;
421 *ppCP
= &cp
->IConnectionPoint_iface
;
422 IConnectionPoint_AddRef(*ppCP
);
426 static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl
= {
427 ConnectionPointContainer_QueryInterface
,
428 ConnectionPointContainer_AddRef
,
429 ConnectionPointContainer_Release
,
430 ConnectionPointContainer_EnumConnectionPoints
,
431 ConnectionPointContainer_FindConnectionPoint
434 void ConnectionPointContainer_Init(ConnectionPointContainer
*This
, IUnknown
*outer
, const cpc_entry_t
*cp_entries
)
436 This
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
437 This
->cp_entries
= cp_entries
;
440 This
->forward_container
= NULL
;
443 void ConnectionPointContainer_Destroy(ConnectionPointContainer
*This
)
450 for(i
=0; This
->cp_entries
[i
].riid
; i
++)
451 ConnectionPoint_Destroy(This
->cps
+i
);
452 heap_free(This
->cps
);