shlwapi: URL_FILE_USE_PATHURL flag only unescapes file urls in UrlCanonicalize.
[wine] / dlls / mshtml / conpoint.c
1 /*
2  * Copyright 2006 Jacek Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include <stdarg.h>
20
21 #define COBJMACROS
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
27
28 #include "wine/debug.h"
29
30 #include "mshtml_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
33
34 #define CONPOINT(x) ((IConnectionPoint*) &(x)->lpConnectionPointVtbl);
35
36 static const char *debugstr_cp_guid(REFIID riid)
37 {
38 #define X(x) \
39     if(IsEqualGUID(riid, &x)) \
40         return #x
41
42     X(IID_IPropertyNotifySink);
43     X(DIID_HTMLDocumentEvents);
44     X(DIID_HTMLDocumentEvents2);
45     X(DIID_HTMLTableEvents);
46     X(DIID_HTMLTextContainerEvents);
47
48 #undef X
49
50     return debugstr_guid(riid);
51 }
52
53 void call_property_onchanged(ConnectionPoint *This, DISPID dispid)
54 {
55     DWORD i;
56
57     for(i=0; i<This->sinks_size; i++) {
58         if(This->sinks[i].propnotif)
59             IPropertyNotifySink_OnChanged(This->sinks[i].propnotif, dispid);
60     }
61 }
62
63 #define CONPOINT_THIS(iface) DEFINE_THIS(ConnectionPoint, ConnectionPoint, iface)
64
65 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
66                                                      REFIID riid, LPVOID *ppv)
67 {
68     ConnectionPoint *This = CONPOINT_THIS(iface);
69
70     *ppv = NULL;
71
72     if(IsEqualGUID(&IID_IUnknown, riid)) {
73         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
74         *ppv = CONPOINT(This);
75     }else if(IsEqualGUID(&IID_IConnectionPoint, riid)) {
76         TRACE("(%p)->(IID_IConnectionPoint %p)\n", This, ppv);
77         *ppv = CONPOINT(This);
78     }
79
80     if(*ppv) {
81         IUnknown_AddRef((IUnknown*)*ppv);
82         return S_OK;
83     }
84
85     WARN("Unsupported interface %s\n", debugstr_guid(riid));
86     return E_NOINTERFACE;
87 }
88
89 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
90 {
91     ConnectionPoint *This = CONPOINT_THIS(iface);
92     return IConnectionPointContainer_AddRef(CONPTCONT(This->container));
93 }
94
95 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
96 {
97     ConnectionPoint *This = CONPOINT_THIS(iface);
98     return IConnectionPointContainer_Release(CONPTCONT(This->container));
99 }
100
101 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID)
102 {
103     ConnectionPoint *This = CONPOINT_THIS(iface);
104
105     TRACE("(%p)->(%p)\n", This, pIID);
106
107     if(!pIID)
108         return E_POINTER;
109
110     *pIID = *This->iid;
111     return S_OK;
112 }
113
114 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
115         IConnectionPointContainer **ppCPC)
116 {
117     ConnectionPoint *This = CONPOINT_THIS(iface);
118
119     TRACE("(%p)->(%p)\n", This, ppCPC);
120
121     if(!ppCPC)
122         return E_POINTER;
123
124     *ppCPC = CONPTCONT(This->container);
125     IConnectionPointContainer_AddRef(*ppCPC);
126     return S_OK;
127 }
128
129 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
130                                              DWORD *pdwCookie)
131 {
132     ConnectionPoint *This = CONPOINT_THIS(iface);
133     IUnknown *sink;
134     DWORD i;
135     HRESULT hres;
136
137     TRACE("(%p)->(%p %p)\n", This, pUnkSink, pdwCookie);
138
139     hres = IUnknown_QueryInterface(pUnkSink, This->iid, (void**)&sink);
140     if(FAILED(hres) && !IsEqualGUID(&IID_IPropertyNotifySink, This->iid))
141         hres = IUnknown_QueryInterface(pUnkSink, &IID_IDispatch, (void**)&sink);
142     if(FAILED(hres))
143         return CONNECT_E_CANNOTCONNECT;
144
145     if(This->sinks) {
146         for(i=0; i<This->sinks_size; i++) {
147             if(!This->sinks[i].unk)
148                 break;
149         }
150
151         if(i == This->sinks_size)
152             This->sinks = heap_realloc(This->sinks,(++This->sinks_size)*sizeof(*This->sinks));
153     }else {
154         This->sinks = heap_alloc(sizeof(*This->sinks));
155         This->sinks_size = 1;
156         i = 0;
157     }
158
159     This->sinks[i].unk = sink;
160     *pdwCookie = i+1;
161
162     if(!i && This->data && This->data->on_advise)
163         This->data->on_advise(This->container->outer, This->data);
164
165     return S_OK;
166 }
167
168 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
169 {
170     ConnectionPoint *This = CONPOINT_THIS(iface);
171     TRACE("(%p)->(%d)\n", This, dwCookie);
172
173     if(!dwCookie || dwCookie > This->sinks_size || !This->sinks[dwCookie-1].unk)
174         return CONNECT_E_NOCONNECTION;
175
176     IUnknown_Release(This->sinks[dwCookie-1].unk);
177     This->sinks[dwCookie-1].unk = NULL;
178
179     return S_OK;
180 }
181
182 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
183                                                       IEnumConnections **ppEnum)
184 {
185     ConnectionPoint *This = CONPOINT_THIS(iface);
186     FIXME("(%p)->(%p)\n", This, ppEnum);
187     return E_NOTIMPL;
188 }
189
190 #undef CONPOINT_THIS
191
192 static const IConnectionPointVtbl ConnectionPointVtbl =
193 {
194     ConnectionPoint_QueryInterface,
195     ConnectionPoint_AddRef,
196     ConnectionPoint_Release,
197     ConnectionPoint_GetConnectionInterface,
198     ConnectionPoint_GetConnectionPointContainer,
199     ConnectionPoint_Advise,
200     ConnectionPoint_Unadvise,
201     ConnectionPoint_EnumConnections
202 };
203
204 void ConnectionPoint_Init(ConnectionPoint *cp, ConnectionPointContainer *container, REFIID riid, cp_static_data_t *data)
205 {
206     cp->lpConnectionPointVtbl = &ConnectionPointVtbl;
207     cp->container = container;
208     cp->sinks = NULL;
209     cp->sinks_size = 0;
210     cp->iid = riid;
211     cp->next = NULL;
212     cp->data = data;
213
214     cp->next = container->cp_list;
215     container->cp_list = cp;
216 }
217
218 static void ConnectionPoint_Destroy(ConnectionPoint *This)
219 {
220     DWORD i;
221
222     for(i=0; i<This->sinks_size; i++) {
223         if(This->sinks[i].unk)
224             IUnknown_Release(This->sinks[i].unk);
225     }
226
227     heap_free(This->sinks);
228 }
229
230 #define CONPTCONT_THIS(iface) DEFINE_THIS(ConnectionPointContainer, ConnectionPointContainer, iface)
231
232 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
233                                                               REFIID riid, void **ppv)
234 {
235     ConnectionPointContainer *This = CONPTCONT_THIS(iface);
236     return IUnknown_QueryInterface(This->outer, riid, ppv);
237 }
238
239 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
240 {
241     ConnectionPointContainer *This = CONPTCONT_THIS(iface);
242     return IUnknown_AddRef(This->outer);
243 }
244
245 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
246 {
247     ConnectionPointContainer *This = CONPTCONT_THIS(iface);
248     return IUnknown_Release(This->outer);
249 }
250
251 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
252         IEnumConnectionPoints **ppEnum)
253 {
254     ConnectionPointContainer *This = CONPTCONT_THIS(iface);
255     FIXME("(%p)->(%p)\n", This, ppEnum);
256     return E_NOTIMPL;
257 }
258
259 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
260         REFIID riid, IConnectionPoint **ppCP)
261 {
262     ConnectionPointContainer *This = CONPTCONT_THIS(iface);
263     ConnectionPoint *iter;
264
265     TRACE("(%p)->(%s %p)\n", This, debugstr_cp_guid(riid), ppCP);
266
267     if(This->forward_container)
268         return IConnectionPointContainer_FindConnectionPoint(CONPTCONT(This), riid, ppCP);
269
270     *ppCP = NULL;
271
272     for(iter = This->cp_list; iter; iter = iter->next) {
273         if(IsEqualGUID(iter->iid, riid))
274             *ppCP = CONPOINT(iter);
275     }
276
277     if(*ppCP) {
278         IConnectionPoint_AddRef(*ppCP);
279         return S_OK;
280     }
281
282     FIXME("unsupported riid %s\n", debugstr_cp_guid(riid));
283     return CONNECT_E_NOCONNECTION;
284 }
285
286 static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl = {
287     ConnectionPointContainer_QueryInterface,
288     ConnectionPointContainer_AddRef,
289     ConnectionPointContainer_Release,
290     ConnectionPointContainer_EnumConnectionPoints,
291     ConnectionPointContainer_FindConnectionPoint
292 };
293
294 #undef CONPTCONT_THIS
295
296 void ConnectionPointContainer_Init(ConnectionPointContainer *This, IUnknown *outer)
297 {
298     This->lpConnectionPointContainerVtbl = &ConnectionPointContainerVtbl;
299     This->cp_list = NULL;
300     This->outer = outer;
301 }
302
303 void ConnectionPointContainer_Destroy(ConnectionPointContainer *This)
304 {
305     ConnectionPoint *iter = This->cp_list;
306
307     while(iter) {
308         ConnectionPoint_Destroy(iter);
309         iter = iter->next;
310     }
311 }