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