mshtml: Pass DispatchEx pointer instead of outer IUnknown to DispatchEx's vtbl functions.
[wine] / dlls / urlmon / ftp.c
1 /*
2  * Copyright 2005-2009 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 "urlmon_main.h"
20
21 #define NO_SHLWAPI_REG
22 #include "shlwapi.h"
23
24 #include "wine/debug.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
27
28 typedef struct {
29     Protocol base;
30
31     IInternetProtocolEx IInternetProtocolEx_iface;
32     IInternetPriority   IInternetPriority_iface;
33     IWinInetHttpInfo    IWinInetHttpInfo_iface;
34
35     LONG ref;
36 } FtpProtocol;
37
38 static inline FtpProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
39 {
40     return CONTAINING_RECORD(iface, FtpProtocol, IInternetProtocolEx_iface);
41 }
42
43 static inline FtpProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
44 {
45     return CONTAINING_RECORD(iface, FtpProtocol, IInternetPriority_iface);
46 }
47 static inline FtpProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
48
49 {
50     return CONTAINING_RECORD(iface, FtpProtocol, IWinInetHttpInfo_iface);
51 }
52
53 #define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(FtpProtocol, base, iface)
54
55 static HRESULT FtpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags,
56         HINTERNET internet_session, IInternetBindInfo *bind_info)
57 {
58     FtpProtocol *This = ASYNCPROTOCOL_THIS(prot);
59     BSTR url;
60     HRESULT hres;
61
62     hres = IUri_GetAbsoluteUri(uri, &url);
63     if(FAILED(hres))
64         return hres;
65
66     This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0,
67             request_flags|INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_PASSIVE,
68             (DWORD_PTR)&This->base);
69     SysFreeString(url);
70     if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {
71         WARN("InternetOpenUrl failed: %d\n", GetLastError());
72         return INET_E_RESOURCE_NOT_FOUND;
73     }
74
75     return S_OK;
76 }
77
78 static HRESULT FtpProtocol_end_request(Protocol *prot)
79 {
80     return E_NOTIMPL;
81 }
82
83 static HRESULT FtpProtocol_start_downloading(Protocol *prot)
84 {
85     FtpProtocol *This = ASYNCPROTOCOL_THIS(prot);
86     DWORD size;
87     BOOL res;
88
89     res = FtpGetFileSize(This->base.request, &size);
90     if(res)
91         This->base.content_length = size;
92     else
93         WARN("FtpGetFileSize failed: %d\n", GetLastError());
94
95     return S_OK;
96 }
97
98 static void FtpProtocol_close_connection(Protocol *prot)
99 {
100 }
101
102 #undef ASYNCPROTOCOL_THIS
103
104 static const ProtocolVtbl AsyncProtocolVtbl = {
105     FtpProtocol_open_request,
106     FtpProtocol_end_request,
107     FtpProtocol_start_downloading,
108     FtpProtocol_close_connection
109 };
110
111 static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
112 {
113     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
114
115     *ppv = NULL;
116     if(IsEqualGUID(&IID_IUnknown, riid)) {
117         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
118         *ppv = &This->IInternetProtocolEx_iface;
119     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
120         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
121         *ppv = &This->IInternetProtocolEx_iface;
122     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
123         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
124         *ppv = &This->IInternetProtocolEx_iface;
125     }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
126         TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
127         *ppv = &This->IInternetProtocolEx_iface;
128     }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
129         TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
130         *ppv = &This->IInternetPriority_iface;
131     }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
132         TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
133         *ppv = &This->IWinInetHttpInfo_iface;
134     }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
135         TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv);
136         *ppv = &This->IWinInetHttpInfo_iface;
137     }
138
139     if(*ppv) {
140         IInternetProtocol_AddRef(iface);
141         return S_OK;
142     }
143
144     WARN("not supported interface %s\n", debugstr_guid(riid));
145     return E_NOINTERFACE;
146 }
147
148 static ULONG WINAPI FtpProtocol_AddRef(IInternetProtocolEx *iface)
149 {
150     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
151     LONG ref = InterlockedIncrement(&This->ref);
152     TRACE("(%p) ref=%d\n", This, ref);
153     return ref;
154 }
155
156 static ULONG WINAPI FtpProtocol_Release(IInternetProtocolEx *iface)
157 {
158     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
159     LONG ref = InterlockedDecrement(&This->ref);
160
161     TRACE("(%p) ref=%d\n", This, ref);
162
163     if(!ref) {
164         protocol_close_connection(&This->base);
165         heap_free(This);
166
167         URLMON_UnlockModule();
168     }
169
170     return ref;
171 }
172
173 static HRESULT WINAPI FtpProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
174         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
175         DWORD grfPI, HANDLE_PTR dwReserved)
176 {
177     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
178     IUri *uri;
179     HRESULT hres;
180
181     TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
182           pOIBindInfo, grfPI, dwReserved);
183
184     hres = CreateUri(szUrl, 0, 0, &uri);
185     if(FAILED(hres))
186         return hres;
187
188     hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
189             pOIBindInfo, grfPI, (HANDLE*)dwReserved);
190
191     IUri_Release(uri);
192     return hres;
193 }
194
195 static HRESULT WINAPI FtpProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
196 {
197     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
198
199     TRACE("(%p)->(%p)\n", This, pProtocolData);
200
201     return protocol_continue(&This->base, pProtocolData);
202 }
203
204 static HRESULT WINAPI FtpProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
205         DWORD dwOptions)
206 {
207     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
208
209     TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
210
211     return protocol_abort(&This->base, hrReason);
212 }
213
214 static HRESULT WINAPI FtpProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
215 {
216     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
217
218     TRACE("(%p)->(%08x)\n", This, dwOptions);
219
220     protocol_close_connection(&This->base);
221     return S_OK;
222 }
223
224 static HRESULT WINAPI FtpProtocol_Suspend(IInternetProtocolEx *iface)
225 {
226     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
227     FIXME("(%p)\n", This);
228     return E_NOTIMPL;
229 }
230
231 static HRESULT WINAPI FtpProtocol_Resume(IInternetProtocolEx *iface)
232 {
233     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
234     FIXME("(%p)\n", This);
235     return E_NOTIMPL;
236 }
237
238 static HRESULT WINAPI FtpProtocol_Read(IInternetProtocolEx *iface, void *pv,
239         ULONG cb, ULONG *pcbRead)
240 {
241     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
242
243     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
244
245     return protocol_read(&This->base, pv, cb, pcbRead);
246 }
247
248 static HRESULT WINAPI FtpProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
249         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
250 {
251     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
252     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
253     return E_NOTIMPL;
254 }
255
256 static HRESULT WINAPI FtpProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
257 {
258     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
259
260     TRACE("(%p)->(%08x)\n", This, dwOptions);
261
262     return protocol_lock_request(&This->base);
263 }
264
265 static HRESULT WINAPI FtpProtocol_UnlockRequest(IInternetProtocolEx *iface)
266 {
267     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
268
269     TRACE("(%p)\n", This);
270
271     return protocol_unlock_request(&This->base);
272 }
273
274 static HRESULT WINAPI FtpProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
275         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
276         DWORD grfPI, HANDLE *dwReserved)
277 {
278     FtpProtocol *This = impl_from_IInternetProtocolEx(iface);
279     DWORD scheme = 0;
280     HRESULT hres;
281
282     TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink,
283             pOIBindInfo, grfPI, dwReserved);
284
285     hres = IUri_GetScheme(pUri, &scheme);
286     if(FAILED(hres))
287         return hres;
288     if(scheme != URL_SCHEME_FTP)
289         return MK_E_SYNTAX;
290
291     return protocol_start(&This->base, (IInternetProtocol*)&This->IInternetProtocolEx_iface, pUri,
292                           pOIProtSink, pOIBindInfo);
293 }
294
295 static const IInternetProtocolExVtbl FtpProtocolVtbl = {
296     FtpProtocol_QueryInterface,
297     FtpProtocol_AddRef,
298     FtpProtocol_Release,
299     FtpProtocol_Start,
300     FtpProtocol_Continue,
301     FtpProtocol_Abort,
302     FtpProtocol_Terminate,
303     FtpProtocol_Suspend,
304     FtpProtocol_Resume,
305     FtpProtocol_Read,
306     FtpProtocol_Seek,
307     FtpProtocol_LockRequest,
308     FtpProtocol_UnlockRequest,
309     FtpProtocol_StartEx
310 };
311
312 static HRESULT WINAPI FtpPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv)
313 {
314     FtpProtocol *This = impl_from_IInternetPriority(iface);
315     return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
316 }
317
318 static ULONG WINAPI FtpPriority_AddRef(IInternetPriority *iface)
319 {
320     FtpProtocol *This = impl_from_IInternetPriority(iface);
321     return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
322 }
323
324 static ULONG WINAPI FtpPriority_Release(IInternetPriority *iface)
325 {
326     FtpProtocol *This = impl_from_IInternetPriority(iface);
327     return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
328 }
329
330 static HRESULT WINAPI FtpPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
331 {
332     FtpProtocol *This = impl_from_IInternetPriority(iface);
333
334     TRACE("(%p)->(%d)\n", This, nPriority);
335
336     This->base.priority = nPriority;
337     return S_OK;
338 }
339
340 static HRESULT WINAPI FtpPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
341 {
342     FtpProtocol *This = impl_from_IInternetPriority(iface);
343
344     TRACE("(%p)->(%p)\n", This, pnPriority);
345
346     *pnPriority = This->base.priority;
347     return S_OK;
348 }
349
350 static const IInternetPriorityVtbl FtpPriorityVtbl = {
351     FtpPriority_QueryInterface,
352     FtpPriority_AddRef,
353     FtpPriority_Release,
354     FtpPriority_SetPriority,
355     FtpPriority_GetPriority
356 };
357
358 static HRESULT WINAPI HttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
359 {
360     FtpProtocol *This = impl_from_IWinInetHttpInfo(iface);
361     return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
362 }
363
364 static ULONG WINAPI HttpInfo_AddRef(IWinInetHttpInfo *iface)
365 {
366     FtpProtocol *This = impl_from_IWinInetHttpInfo(iface);
367     return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
368 }
369
370 static ULONG WINAPI HttpInfo_Release(IWinInetHttpInfo *iface)
371 {
372     FtpProtocol *This = impl_from_IWinInetHttpInfo(iface);
373     return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
374 }
375
376 static HRESULT WINAPI HttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
377         void *pBuffer, DWORD *pcbBuffer)
378 {
379     FtpProtocol *This = impl_from_IWinInetHttpInfo(iface);
380     FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
381     return E_NOTIMPL;
382 }
383
384 static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
385         void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
386 {
387     FtpProtocol *This = impl_from_IWinInetHttpInfo(iface);
388     FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
389     return E_NOTIMPL;
390 }
391
392 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
393     HttpInfo_QueryInterface,
394     HttpInfo_AddRef,
395     HttpInfo_Release,
396     HttpInfo_QueryOption,
397     HttpInfo_QueryInfo
398 };
399
400 HRESULT FtpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
401 {
402     FtpProtocol *ret;
403
404     TRACE("(%p %p)\n", pUnkOuter, ppobj);
405
406     URLMON_LockModule();
407
408     ret = heap_alloc_zero(sizeof(FtpProtocol));
409
410     ret->base.vtbl = &AsyncProtocolVtbl;
411     ret->IInternetProtocolEx_iface.lpVtbl = &FtpProtocolVtbl;
412     ret->IInternetPriority_iface.lpVtbl   = &FtpPriorityVtbl;
413     ret->IWinInetHttpInfo_iface.lpVtbl    = &WinInetHttpInfoVtbl;
414     ret->ref = 1;
415
416     *ppobj = &ret->IInternetProtocolEx_iface;
417
418     return S_OK;
419 }