wininet: Use a blank password if none is provided in FTP_Connect.
[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 "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30
31 #include "wine/debug.h"
32
33 #include "mshtml_private.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
36
37 #define CONPOINT(x) ((IConnectionPoint*) &(x)->lpConnectionPointVtbl);
38
39 struct ConnectionPoint {
40     const IConnectionPointVtbl *lpConnectionPointVtbl;
41
42     HTMLDocument *doc;
43
44     union {
45         IUnknown *unk;
46         IDispatch *disp;
47         IPropertyNotifySink *propnotif;
48     } *sinks;
49     DWORD sinks_size;
50
51     IID iid;
52 };
53
54 #define CONPOINT_THIS(iface) DEFINE_THIS(ConnectionPoint, ConnectionPoint, iface)
55
56 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
57                                                      REFIID riid, LPVOID *ppv)
58 {
59     ConnectionPoint *This = CONPOINT_THIS(iface);
60
61     *ppv = NULL;
62
63     if(IsEqualGUID(&IID_IUnknown, riid)) {
64         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
65         *ppv = CONPOINT(This);
66     }else if(IsEqualGUID(&IID_IConnectionPoint, riid)) {
67         TRACE("(%p)->(IID_IConnectionPoint %p)\n", This, ppv);
68         *ppv = CONPOINT(This);
69     }
70
71     if(*ppv) {
72         IUnknown_AddRef((IUnknown*)*ppv);
73         return S_OK;
74     }
75
76     WARN("Unsupported interface %s\n", debugstr_guid(riid));
77     return E_NOINTERFACE;
78 }
79
80 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
81 {
82     ConnectionPoint *This = CONPOINT_THIS(iface);
83     return IHTMLDocument2_AddRef(HTMLDOC(This->doc));
84 }
85
86 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
87 {
88     ConnectionPoint *This = CONPOINT_THIS(iface);
89     return IHTMLDocument2_Release(HTMLDOC(This->doc));
90 }
91
92 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID)
93 {
94     ConnectionPoint *This = CONPOINT_THIS(iface);
95
96     TRACE("(%p)->(%p)\n", This, pIID);
97
98     if(!pIID)
99         return E_POINTER;
100
101     memcpy(pIID, &This->iid, sizeof(IID));
102     return S_OK;
103 }
104
105 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
106         IConnectionPointContainer **ppCPC)
107 {
108     ConnectionPoint *This = CONPOINT_THIS(iface);
109
110     TRACE("(%p)->(%p)\n", This, ppCPC);
111
112     if(!ppCPC)
113         return E_POINTER;
114
115     *ppCPC = CONPTCONT(This->doc);
116     IConnectionPointContainer_AddRef(*ppCPC);
117     return S_OK;
118 }
119
120 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
121                                              DWORD *pdwCookie)
122 {
123     ConnectionPoint *This = CONPOINT_THIS(iface);
124     IUnknown *sink;
125     DWORD i;
126     HRESULT hres;
127
128     TRACE("(%p)->(%p %p)\n", This, pUnkSink, pdwCookie);
129
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;
135     }
136
137     if(This->sinks) {
138         for(i=0; i<This->sinks_size; i++) {
139             if(!This->sinks[i].unk)
140                 break;
141         }
142
143         if(i == This->sinks_size)
144             This->sinks = HeapReAlloc(GetProcessHeap(), 0, This->sinks,
145                     (++This->sinks_size)*sizeof(*This->sinks));
146     }else {
147         This->sinks = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->sinks));
148         This->sinks_size = 1;
149         i = 0;
150     }
151
152     This->sinks[i].unk = sink;
153     *pdwCookie = i+1;
154
155     return S_OK;
156 }
157
158 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
159 {
160     ConnectionPoint *This = CONPOINT_THIS(iface);
161     TRACE("(%p)->(%ld)\n", This, dwCookie);
162
163     if(!dwCookie || dwCookie > This->sinks_size || !This->sinks[dwCookie-1].unk)
164         return CONNECT_E_NOCONNECTION;
165
166     IUnknown_Release(This->sinks[dwCookie-1].unk);
167     This->sinks[dwCookie-1].unk = NULL;
168
169     return S_OK;
170 }
171
172 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
173                                                       IEnumConnections **ppEnum)
174 {
175     ConnectionPoint *This = CONPOINT_THIS(iface);
176     FIXME("(%p)->(%p)\n", This, ppEnum);
177     return E_NOTIMPL;
178 }
179
180 #undef CONPOINT_THIS
181
182 static const IConnectionPointVtbl ConnectionPointVtbl =
183 {
184     ConnectionPoint_QueryInterface,
185     ConnectionPoint_AddRef,
186     ConnectionPoint_Release,
187     ConnectionPoint_GetConnectionInterface,
188     ConnectionPoint_GetConnectionPointContainer,
189     ConnectionPoint_Advise,
190     ConnectionPoint_Unadvise,
191     ConnectionPoint_EnumConnections
192 };
193
194 static void ConnectionPoint_Create(HTMLDocument *doc, REFIID riid, ConnectionPoint **cp)
195 {
196     ConnectionPoint *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ConnectionPoint));
197
198     ret->lpConnectionPointVtbl = &ConnectionPointVtbl;
199     ret->doc = doc;
200     ret->sinks = NULL;
201     ret->sinks_size = 0;
202     memcpy(&ret->iid, riid, sizeof(IID));
203
204     *cp = ret;
205 }
206
207 static void ConnectionPoint_Destroy(ConnectionPoint *This)
208 {
209     int i;
210
211     for(i=0; i<This->sinks_size; i++) {
212         if(This->sinks[i].unk)
213             IUnknown_Release(This->sinks[i].unk);
214     }
215
216     HeapFree(GetProcessHeap(), 0, This->sinks);
217     HeapFree(GetProcessHeap(), 0, This);
218 }
219
220 #define CONPTCONT_THIS(iface) DEFINE_THIS(HTMLDocument, ConnectionPointContainer, iface)
221
222 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
223                                                               REFIID riid, void **ppv)
224 {
225     HTMLDocument *This = CONPTCONT_THIS(iface);
226     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
227 }
228
229 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
230 {
231     HTMLDocument *This = CONPTCONT_THIS(iface);
232     return IHTMLDocument2_AddRef(HTMLDOC(This));
233 }
234
235 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
236 {
237     HTMLDocument *This = CONPTCONT_THIS(iface);
238     return IHTMLDocument2_Release(HTMLDOC(This));
239 }
240
241 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
242         IEnumConnectionPoints **ppEnum)
243 {
244     HTMLDocument *This = CONPTCONT_THIS(iface);
245     FIXME("(%p)->(%p)\n", This, ppEnum);
246     return E_NOTIMPL;
247 }
248
249 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
250         REFIID riid, IConnectionPoint **ppCP)
251 {
252     HTMLDocument *This = CONPTCONT_THIS(iface);
253
254     *ppCP = NULL;
255
256     if(IsEqualGUID(&DIID_HTMLDocumentEvents, riid)) {
257         TRACE("(%p)->(DIID_HTMLDocumentEvents %p)\n", This, ppCP);
258         *ppCP = CONPOINT(This->cp_htmldocevents);
259     }else if(IsEqualGUID(&DIID_HTMLDocumentEvents2, riid)) {
260         TRACE("(%p)->(DIID_HTMLDocumentEvents2 %p)\n", This, ppCP);
261         *ppCP = CONPOINT(This->cp_htmldocevents2);
262     }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
263         TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppCP);
264         *ppCP = CONPOINT(This->cp_propnotif);
265     }
266
267     if(*ppCP) {
268         IConnectionPoint_AddRef(*ppCP);
269         return S_OK;
270     }
271
272     FIXME("(%p)->(%s %p) unsupported riid\n", This, debugstr_guid(riid), ppCP);
273     return CONNECT_E_NOCONNECTION;
274 }
275
276 static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl = {
277     ConnectionPointContainer_QueryInterface,
278     ConnectionPointContainer_AddRef,
279     ConnectionPointContainer_Release,
280     ConnectionPointContainer_EnumConnectionPoints,
281     ConnectionPointContainer_FindConnectionPoint
282 };
283
284 #undef CONPTCONT_THIS
285
286 void HTMLDocument_ConnectionPoints_Init(HTMLDocument *This)
287 {
288     This->lpConnectionPointContainerVtbl = &ConnectionPointContainerVtbl;
289
290     ConnectionPoint_Create(This, &IID_IPropertyNotifySink, &This->cp_propnotif);
291     ConnectionPoint_Create(This, &DIID_HTMLDocumentEvents, &This->cp_htmldocevents);
292     ConnectionPoint_Create(This, &DIID_HTMLDocumentEvents2, &This->cp_htmldocevents2);
293 }
294
295 void HTMLDocument_ConnectionPoints_Destroy(HTMLDocument *This)
296 {
297     ConnectionPoint_Destroy(This->cp_propnotif);
298     ConnectionPoint_Destroy(This->cp_htmldocevents);
299     ConnectionPoint_Destroy(This->cp_htmldocevents2);
300 }