atl100: Trace ATL version and keep debug channel consistent.
[wine.git] / dlls / mshtml / conpoint.c
blobde501b42bc3d90224d32353d8af75fb5fe740d1d
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 static const char *debugstr_cp_guid(REFIID riid)
36 #define X(x) \
37 if(IsEqualGUID(riid, &x)) \
38 return #x
40 X(IID_IPropertyNotifySink);
41 X(DIID_HTMLDocumentEvents);
42 X(DIID_HTMLDocumentEvents2);
43 X(DIID_HTMLTableEvents);
44 X(DIID_HTMLTextContainerEvents);
46 #undef X
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);
61 *ppv = NULL;
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;
71 if(*ppv) {
72 IUnknown_AddRef((IUnknown*)*ppv);
73 return S_OK;
76 WARN("Unsupported interface %s\n", debugstr_guid(riid));
77 return E_NOINTERFACE;
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);
98 if(!pIID)
99 return E_POINTER;
101 *pIID = *This->iid;
102 return S_OK;
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);
112 if(!ppCPC)
113 return E_POINTER;
115 *ppCPC = &This->container->IConnectionPointContainer_iface;
116 IConnectionPointContainer_AddRef(*ppCPC);
117 return S_OK;
120 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
121 DWORD *pdwCookie)
123 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
124 IUnknown *sink;
125 DWORD i;
126 HRESULT hres;
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);
133 if(FAILED(hres))
134 return CONNECT_E_CANNOTCONNECT;
136 if(This->sinks) {
137 for(i=0; i<This->sinks_size; i++) {
138 if(!This->sinks[i].unk)
139 break;
142 if(i == This->sinks_size)
143 This->sinks = heap_realloc(This->sinks,(++This->sinks_size)*sizeof(*This->sinks));
144 }else {
145 This->sinks = heap_alloc(sizeof(*This->sinks));
146 This->sinks_size = 1;
147 i = 0;
150 This->sinks[i].unk = sink;
151 if(pdwCookie)
152 *pdwCookie = i+1;
154 if(!i && This->data && This->data->on_advise)
155 This->data->on_advise(This->container->outer, This->data);
157 return S_OK;
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;
171 return S_OK;
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);
179 return E_NOTIMPL;
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;
198 cp->sinks = NULL;
199 cp->sinks_size = 0;
200 cp->iid = riid;
201 cp->data = data;
204 static void ConnectionPoint_Destroy(ConnectionPoint *This)
206 DWORD i;
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;
219 unsigned idx, i;
221 for(iter = container->cp_entries; iter->riid; iter++) {
222 if(IsEqualGUID(iter->riid, riid))
223 break;
225 if(!iter->riid)
226 return NULL;
227 idx = iter - container->cp_entries;
229 if(!container->cps) {
230 if(!do_create)
231 return NULL;
233 while(iter->riid)
234 iter++;
235 container->cps = heap_alloc((iter - container->cp_entries) * sizeof(*container->cps));
236 if(!container->cps)
237 return NULL;
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)
248 ConnectionPoint *cp;
249 DWORD i;
251 cp = get_cp(container, &IID_IPropertyNotifySink, FALSE);
252 if(!cp)
253 return;
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);
290 return E_NOTIMPL;
293 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
294 REFIID riid, IConnectionPoint **ppCP)
296 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
297 ConnectionPoint *cp;
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,
303 riid, ppCP);
305 cp = get_cp(This, riid, TRUE);
306 if(!cp) {
307 FIXME("unsupported riid %s\n", debugstr_cp_guid(riid));
308 *ppCP = NULL;
309 return CONNECT_E_NOCONNECTION;
312 *ppCP = &cp->IConnectionPoint_iface;
313 IConnectionPoint_AddRef(*ppCP);
314 return S_OK;
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;
329 This->cps = NULL;
330 This->outer = outer;
331 This->forward_container = NULL;
334 void ConnectionPointContainer_Destroy(ConnectionPointContainer *This)
336 unsigned i;
338 if(!This->cps)
339 return;
341 for(i=0; This->cp_entries[i].riid; i++)
342 ConnectionPoint_Destroy(This->cps+i);
343 heap_free(This->cps);