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
);
34 static const char *debugstr_cp_guid(REFIID riid
)
37 if(IsEqualGUID(riid, &x)) \
40 X(IID_IPropertyNotifySink
);
41 X(DIID_HTMLDocumentEvents
);
42 X(DIID_HTMLDocumentEvents2
);
43 X(DIID_HTMLTableEvents
);
44 X(DIID_HTMLTextContainerEvents
);
48 return debugstr_guid(riid
);
51 static inline ConnectionPoint
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
53 return CONTAINING_RECORD(iface
, ConnectionPoint
, IConnectionPoint_iface
);
56 static HRESULT WINAPI
ConnectionPoint_QueryInterface(IConnectionPoint
*iface
,
57 REFIID riid
, LPVOID
*ppv
)
59 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
63 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
64 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
65 *ppv
= &This
->IConnectionPoint_iface
;
66 }else if(IsEqualGUID(&IID_IConnectionPoint
, riid
)) {
67 TRACE("(%p)->(IID_IConnectionPoint %p)\n", This
, ppv
);
68 *ppv
= &This
->IConnectionPoint_iface
;
72 IUnknown_AddRef((IUnknown
*)*ppv
);
76 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
80 static ULONG WINAPI
ConnectionPoint_AddRef(IConnectionPoint
*iface
)
82 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
83 return IConnectionPointContainer_AddRef(&This
->container
->IConnectionPointContainer_iface
);
86 static ULONG WINAPI
ConnectionPoint_Release(IConnectionPoint
*iface
)
88 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
89 return IConnectionPointContainer_Release(&This
->container
->IConnectionPointContainer_iface
);
92 static HRESULT WINAPI
ConnectionPoint_GetConnectionInterface(IConnectionPoint
*iface
, IID
*pIID
)
94 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
96 TRACE("(%p)->(%p)\n", This
, pIID
);
105 static HRESULT WINAPI
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint
*iface
,
106 IConnectionPointContainer
**ppCPC
)
108 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
110 TRACE("(%p)->(%p)\n", This
, ppCPC
);
115 *ppCPC
= &This
->container
->IConnectionPointContainer_iface
;
116 IConnectionPointContainer_AddRef(*ppCPC
);
120 static HRESULT WINAPI
ConnectionPoint_Advise(IConnectionPoint
*iface
, IUnknown
*pUnkSink
,
123 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
128 TRACE("(%p)->(%p %p)\n", This
, pUnkSink
, pdwCookie
);
130 hres
= IUnknown_QueryInterface(pUnkSink
, This
->iid
, (void**)&sink
);
131 if(FAILED(hres
) && !IsEqualGUID(&IID_IPropertyNotifySink
, This
->iid
))
132 hres
= IUnknown_QueryInterface(pUnkSink
, &IID_IDispatch
, (void**)&sink
);
134 return CONNECT_E_CANNOTCONNECT
;
137 for(i
=0; i
<This
->sinks_size
; i
++) {
138 if(!This
->sinks
[i
].unk
)
142 if(i
== This
->sinks_size
)
143 This
->sinks
= heap_realloc(This
->sinks
,(++This
->sinks_size
)*sizeof(*This
->sinks
));
145 This
->sinks
= heap_alloc(sizeof(*This
->sinks
));
146 This
->sinks_size
= 1;
150 This
->sinks
[i
].unk
= sink
;
154 if(!i
&& This
->data
&& This
->data
->on_advise
)
155 This
->data
->on_advise(This
->container
->outer
, This
->data
);
160 static HRESULT WINAPI
ConnectionPoint_Unadvise(IConnectionPoint
*iface
, DWORD dwCookie
)
162 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
163 TRACE("(%p)->(%d)\n", This
, dwCookie
);
165 if(!dwCookie
|| dwCookie
> This
->sinks_size
|| !This
->sinks
[dwCookie
-1].unk
)
166 return CONNECT_E_NOCONNECTION
;
168 IUnknown_Release(This
->sinks
[dwCookie
-1].unk
);
169 This
->sinks
[dwCookie
-1].unk
= NULL
;
174 static HRESULT WINAPI
ConnectionPoint_EnumConnections(IConnectionPoint
*iface
,
175 IEnumConnections
**ppEnum
)
177 ConnectionPoint
*This
= impl_from_IConnectionPoint(iface
);
178 FIXME("(%p)->(%p)\n", This
, ppEnum
);
182 static const IConnectionPointVtbl ConnectionPointVtbl
=
184 ConnectionPoint_QueryInterface
,
185 ConnectionPoint_AddRef
,
186 ConnectionPoint_Release
,
187 ConnectionPoint_GetConnectionInterface
,
188 ConnectionPoint_GetConnectionPointContainer
,
189 ConnectionPoint_Advise
,
190 ConnectionPoint_Unadvise
,
191 ConnectionPoint_EnumConnections
194 static void ConnectionPoint_Init(ConnectionPoint
*cp
, ConnectionPointContainer
*container
, REFIID riid
, cp_static_data_t
*data
)
196 cp
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointVtbl
;
197 cp
->container
= container
;
204 static void ConnectionPoint_Destroy(ConnectionPoint
*This
)
208 for(i
=0; i
<This
->sinks_size
; i
++) {
209 if(This
->sinks
[i
].unk
)
210 IUnknown_Release(This
->sinks
[i
].unk
);
213 heap_free(This
->sinks
);
216 static ConnectionPoint
*get_cp(ConnectionPointContainer
*container
, REFIID riid
, BOOL do_create
)
218 const cpc_entry_t
*iter
;
221 for(iter
= container
->cp_entries
; iter
->riid
; iter
++) {
222 if(IsEqualGUID(iter
->riid
, riid
))
227 idx
= iter
- container
->cp_entries
;
229 if(!container
->cps
) {
235 container
->cps
= heap_alloc((iter
- container
->cp_entries
) * sizeof(*container
->cps
));
239 for(i
=0; container
->cp_entries
[i
].riid
; i
++)
240 ConnectionPoint_Init(container
->cps
+i
, container
, container
->cp_entries
[i
].riid
, container
->cp_entries
[i
].desc
);
243 return container
->cps
+idx
;
246 void call_property_onchanged(ConnectionPointContainer
*container
, DISPID dispid
)
251 cp
= get_cp(container
, &IID_IPropertyNotifySink
, FALSE
);
255 for(i
=0; i
<cp
->sinks_size
; i
++) {
256 if(cp
->sinks
[i
].propnotif
)
257 IPropertyNotifySink_OnChanged(cp
->sinks
[i
].propnotif
, dispid
);
261 static inline ConnectionPointContainer
*impl_from_IConnectionPointContainer(IConnectionPointContainer
*iface
)
263 return CONTAINING_RECORD(iface
, ConnectionPointContainer
, IConnectionPointContainer_iface
);
266 static HRESULT WINAPI
ConnectionPointContainer_QueryInterface(IConnectionPointContainer
*iface
,
267 REFIID riid
, void **ppv
)
269 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
270 return IUnknown_QueryInterface(This
->outer
, riid
, ppv
);
273 static ULONG WINAPI
ConnectionPointContainer_AddRef(IConnectionPointContainer
*iface
)
275 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
276 return IUnknown_AddRef(This
->outer
);
279 static ULONG WINAPI
ConnectionPointContainer_Release(IConnectionPointContainer
*iface
)
281 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
282 return IUnknown_Release(This
->outer
);
285 static HRESULT WINAPI
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer
*iface
,
286 IEnumConnectionPoints
**ppEnum
)
288 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
289 FIXME("(%p)->(%p)\n", This
, ppEnum
);
293 static HRESULT WINAPI
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer
*iface
,
294 REFIID riid
, IConnectionPoint
**ppCP
)
296 ConnectionPointContainer
*This
= impl_from_IConnectionPointContainer(iface
);
299 TRACE("(%p)->(%s %p)\n", This
, debugstr_cp_guid(riid
), ppCP
);
301 if(This
->forward_container
)
302 return IConnectionPointContainer_FindConnectionPoint(&This
->forward_container
->IConnectionPointContainer_iface
,
305 cp
= get_cp(This
, riid
, TRUE
);
307 FIXME("unsupported riid %s\n", debugstr_cp_guid(riid
));
309 return CONNECT_E_NOCONNECTION
;
312 *ppCP
= &cp
->IConnectionPoint_iface
;
313 IConnectionPoint_AddRef(*ppCP
);
317 static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl
= {
318 ConnectionPointContainer_QueryInterface
,
319 ConnectionPointContainer_AddRef
,
320 ConnectionPointContainer_Release
,
321 ConnectionPointContainer_EnumConnectionPoints
,
322 ConnectionPointContainer_FindConnectionPoint
325 void ConnectionPointContainer_Init(ConnectionPointContainer
*This
, IUnknown
*outer
, const cpc_entry_t
*cp_entries
)
327 This
->IConnectionPointContainer_iface
.lpVtbl
= &ConnectionPointContainerVtbl
;
328 This
->cp_entries
= cp_entries
;
331 This
->forward_container
= NULL
;
334 void ConnectionPointContainer_Destroy(ConnectionPointContainer
*This
)
341 for(i
=0; This
->cp_entries
[i
].riid
; i
++)
342 ConnectionPoint_Destroy(This
->cps
+i
);
343 heap_free(This
->cps
);