msxml3: Basic support for startElement()/endElement().
[wine/multimedia.git] / dlls / mshtml / conpoint.c
blobca45524c33f0e6b1defbdc2c218e45af79ccf4b7
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 void call_property_onchanged(ConnectionPoint *This, DISPID dispid)
53 DWORD i;
55 for(i=0; i<This->sinks_size; i++) {
56 if(This->sinks[i].propnotif)
57 IPropertyNotifySink_OnChanged(This->sinks[i].propnotif, dispid);
61 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
63 return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
66 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
67 REFIID riid, LPVOID *ppv)
69 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
71 *ppv = NULL;
73 if(IsEqualGUID(&IID_IUnknown, riid)) {
74 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
75 *ppv = &This->IConnectionPoint_iface;
76 }else if(IsEqualGUID(&IID_IConnectionPoint, riid)) {
77 TRACE("(%p)->(IID_IConnectionPoint %p)\n", This, ppv);
78 *ppv = &This->IConnectionPoint_iface;
81 if(*ppv) {
82 IUnknown_AddRef((IUnknown*)*ppv);
83 return S_OK;
86 WARN("Unsupported interface %s\n", debugstr_guid(riid));
87 return E_NOINTERFACE;
90 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
92 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
93 return IConnectionPointContainer_AddRef(&This->container->IConnectionPointContainer_iface);
96 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
98 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
99 return IConnectionPointContainer_Release(&This->container->IConnectionPointContainer_iface);
102 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID)
104 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
106 TRACE("(%p)->(%p)\n", This, pIID);
108 if(!pIID)
109 return E_POINTER;
111 *pIID = *This->iid;
112 return S_OK;
115 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
116 IConnectionPointContainer **ppCPC)
118 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
120 TRACE("(%p)->(%p)\n", This, ppCPC);
122 if(!ppCPC)
123 return E_POINTER;
125 *ppCPC = &This->container->IConnectionPointContainer_iface;
126 IConnectionPointContainer_AddRef(*ppCPC);
127 return S_OK;
130 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
131 DWORD *pdwCookie)
133 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
134 IUnknown *sink;
135 DWORD i;
136 HRESULT hres;
138 TRACE("(%p)->(%p %p)\n", This, pUnkSink, pdwCookie);
140 hres = IUnknown_QueryInterface(pUnkSink, This->iid, (void**)&sink);
141 if(FAILED(hres) && !IsEqualGUID(&IID_IPropertyNotifySink, This->iid))
142 hres = IUnknown_QueryInterface(pUnkSink, &IID_IDispatch, (void**)&sink);
143 if(FAILED(hres))
144 return CONNECT_E_CANNOTCONNECT;
146 if(This->sinks) {
147 for(i=0; i<This->sinks_size; i++) {
148 if(!This->sinks[i].unk)
149 break;
152 if(i == This->sinks_size)
153 This->sinks = heap_realloc(This->sinks,(++This->sinks_size)*sizeof(*This->sinks));
154 }else {
155 This->sinks = heap_alloc(sizeof(*This->sinks));
156 This->sinks_size = 1;
157 i = 0;
160 This->sinks[i].unk = sink;
161 *pdwCookie = i+1;
163 if(!i && This->data && This->data->on_advise)
164 This->data->on_advise(This->container->outer, This->data);
166 return S_OK;
169 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
171 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
172 TRACE("(%p)->(%d)\n", This, dwCookie);
174 if(!dwCookie || dwCookie > This->sinks_size || !This->sinks[dwCookie-1].unk)
175 return CONNECT_E_NOCONNECTION;
177 IUnknown_Release(This->sinks[dwCookie-1].unk);
178 This->sinks[dwCookie-1].unk = NULL;
180 return S_OK;
183 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
184 IEnumConnections **ppEnum)
186 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
187 FIXME("(%p)->(%p)\n", This, ppEnum);
188 return E_NOTIMPL;
191 static const IConnectionPointVtbl ConnectionPointVtbl =
193 ConnectionPoint_QueryInterface,
194 ConnectionPoint_AddRef,
195 ConnectionPoint_Release,
196 ConnectionPoint_GetConnectionInterface,
197 ConnectionPoint_GetConnectionPointContainer,
198 ConnectionPoint_Advise,
199 ConnectionPoint_Unadvise,
200 ConnectionPoint_EnumConnections
203 void ConnectionPoint_Init(ConnectionPoint *cp, ConnectionPointContainer *container, REFIID riid, cp_static_data_t *data)
205 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
206 cp->container = container;
207 cp->sinks = NULL;
208 cp->sinks_size = 0;
209 cp->iid = riid;
210 cp->data = data;
212 cp->next = container->cp_list;
213 container->cp_list = cp;
216 static void ConnectionPoint_Destroy(ConnectionPoint *This)
218 DWORD i;
220 for(i=0; i<This->sinks_size; i++) {
221 if(This->sinks[i].unk)
222 IUnknown_Release(This->sinks[i].unk);
225 heap_free(This->sinks);
228 static inline ConnectionPointContainer *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
230 return CONTAINING_RECORD(iface, ConnectionPointContainer, IConnectionPointContainer_iface);
233 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
234 REFIID riid, void **ppv)
236 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
237 return IUnknown_QueryInterface(This->outer, riid, ppv);
240 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
242 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
243 return IUnknown_AddRef(This->outer);
246 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
248 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
249 return IUnknown_Release(This->outer);
252 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
253 IEnumConnectionPoints **ppEnum)
255 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
256 FIXME("(%p)->(%p)\n", This, ppEnum);
257 return E_NOTIMPL;
260 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
261 REFIID riid, IConnectionPoint **ppCP)
263 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
264 ConnectionPoint *iter;
266 TRACE("(%p)->(%s %p)\n", This, debugstr_cp_guid(riid), ppCP);
268 if(This->forward_container)
269 return IConnectionPointContainer_FindConnectionPoint(&This->forward_container->IConnectionPointContainer_iface,
270 riid, ppCP);
272 *ppCP = NULL;
274 for(iter = This->cp_list; iter; iter = iter->next) {
275 if(IsEqualGUID(iter->iid, riid))
276 *ppCP = &iter->IConnectionPoint_iface;
279 if(*ppCP) {
280 IConnectionPoint_AddRef(*ppCP);
281 return S_OK;
284 FIXME("unsupported riid %s\n", debugstr_cp_guid(riid));
285 return CONNECT_E_NOCONNECTION;
288 static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl = {
289 ConnectionPointContainer_QueryInterface,
290 ConnectionPointContainer_AddRef,
291 ConnectionPointContainer_Release,
292 ConnectionPointContainer_EnumConnectionPoints,
293 ConnectionPointContainer_FindConnectionPoint
296 void ConnectionPointContainer_Init(ConnectionPointContainer *This, IUnknown *outer)
298 This->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
299 This->cp_list = NULL;
300 This->outer = outer;
303 void ConnectionPointContainer_Destroy(ConnectionPointContainer *This)
305 ConnectionPoint *iter = This->cp_list;
307 while(iter) {
308 ConnectionPoint_Destroy(iter);
309 iter = iter->next;