shell32: Return empty list instead of NULL.
[wine.git] / dlls / mshtml / conpoint.c
blob691a8c99ef53bad010d2d462bfb28fbdb11de3af
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 if(pdwCookie)
162 *pdwCookie = i+1;
164 if(!i && This->data && This->data->on_advise)
165 This->data->on_advise(This->container->outer, This->data);
167 return S_OK;
170 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
172 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
173 TRACE("(%p)->(%d)\n", This, dwCookie);
175 if(!dwCookie || dwCookie > This->sinks_size || !This->sinks[dwCookie-1].unk)
176 return CONNECT_E_NOCONNECTION;
178 IUnknown_Release(This->sinks[dwCookie-1].unk);
179 This->sinks[dwCookie-1].unk = NULL;
181 return S_OK;
184 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
185 IEnumConnections **ppEnum)
187 ConnectionPoint *This = impl_from_IConnectionPoint(iface);
188 FIXME("(%p)->(%p)\n", This, ppEnum);
189 return E_NOTIMPL;
192 static const IConnectionPointVtbl ConnectionPointVtbl =
194 ConnectionPoint_QueryInterface,
195 ConnectionPoint_AddRef,
196 ConnectionPoint_Release,
197 ConnectionPoint_GetConnectionInterface,
198 ConnectionPoint_GetConnectionPointContainer,
199 ConnectionPoint_Advise,
200 ConnectionPoint_Unadvise,
201 ConnectionPoint_EnumConnections
204 void ConnectionPoint_Init(ConnectionPoint *cp, ConnectionPointContainer *container, REFIID riid, cp_static_data_t *data)
206 cp->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
207 cp->container = container;
208 cp->sinks = NULL;
209 cp->sinks_size = 0;
210 cp->iid = riid;
211 cp->data = data;
213 cp->next = container->cp_list;
214 container->cp_list = cp;
217 static void ConnectionPoint_Destroy(ConnectionPoint *This)
219 DWORD i;
221 for(i=0; i<This->sinks_size; i++) {
222 if(This->sinks[i].unk)
223 IUnknown_Release(This->sinks[i].unk);
226 heap_free(This->sinks);
229 static inline ConnectionPointContainer *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
231 return CONTAINING_RECORD(iface, ConnectionPointContainer, IConnectionPointContainer_iface);
234 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
235 REFIID riid, void **ppv)
237 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
238 return IUnknown_QueryInterface(This->outer, riid, ppv);
241 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
243 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
244 return IUnknown_AddRef(This->outer);
247 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
249 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
250 return IUnknown_Release(This->outer);
253 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
254 IEnumConnectionPoints **ppEnum)
256 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
257 FIXME("(%p)->(%p)\n", This, ppEnum);
258 return E_NOTIMPL;
261 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
262 REFIID riid, IConnectionPoint **ppCP)
264 ConnectionPointContainer *This = impl_from_IConnectionPointContainer(iface);
265 ConnectionPoint *iter;
267 TRACE("(%p)->(%s %p)\n", This, debugstr_cp_guid(riid), ppCP);
269 if(This->forward_container)
270 return IConnectionPointContainer_FindConnectionPoint(&This->forward_container->IConnectionPointContainer_iface,
271 riid, ppCP);
273 *ppCP = NULL;
275 for(iter = This->cp_list; iter; iter = iter->next) {
276 if(IsEqualGUID(iter->iid, riid))
277 *ppCP = &iter->IConnectionPoint_iface;
280 if(*ppCP) {
281 IConnectionPoint_AddRef(*ppCP);
282 return S_OK;
285 FIXME("unsupported riid %s\n", debugstr_cp_guid(riid));
286 return CONNECT_E_NOCONNECTION;
289 static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl = {
290 ConnectionPointContainer_QueryInterface,
291 ConnectionPointContainer_AddRef,
292 ConnectionPointContainer_Release,
293 ConnectionPointContainer_EnumConnectionPoints,
294 ConnectionPointContainer_FindConnectionPoint
297 void ConnectionPointContainer_Init(ConnectionPointContainer *This, IUnknown *outer)
299 This->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
300 This->cp_list = NULL;
301 This->outer = outer;
304 void ConnectionPointContainer_Destroy(ConnectionPointContainer *This)
306 ConnectionPoint *iter = This->cp_list;
308 while(iter) {
309 ConnectionPoint_Destroy(iter);
310 iter = iter->next;