Sync with trunk r63174.
[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 typedef struct {
22 Protocol base;
23
24 IInternetProtocolEx IInternetProtocolEx_iface;
25 IInternetPriority IInternetPriority_iface;
26 IWinInetHttpInfo IWinInetHttpInfo_iface;
27
28 LONG ref;
29 } FtpProtocol;
30
31 static inline FtpProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
32 {
33 return CONTAINING_RECORD(iface, FtpProtocol, IInternetProtocolEx_iface);
34 }
35
36 static inline FtpProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
37 {
38 return CONTAINING_RECORD(iface, FtpProtocol, IInternetPriority_iface);
39 }
40 static inline FtpProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
41
42 {
43 return CONTAINING_RECORD(iface, FtpProtocol, IWinInetHttpInfo_iface);
44 }
45
46 static inline FtpProtocol *impl_from_Protocol(Protocol *prot)
47 {
48 return CONTAINING_RECORD(prot, FtpProtocol, base);
49 }
50
51 static HRESULT FtpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags,
52 HINTERNET internet_session, IInternetBindInfo *bind_info)
53 {
54 FtpProtocol *This = impl_from_Protocol(prot);
55 BSTR url;
56 HRESULT hres;
57
58 hres = IUri_GetAbsoluteUri(uri, &url);
59 if(FAILED(hres))
60 return hres;
61
62 This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0,
63 request_flags|INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_PASSIVE,
64 (DWORD_PTR)&This->base);
65 SysFreeString(url);
66 if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {
67 WARN("InternetOpenUrl failed: %d\n", GetLastError());
68 return INET_E_RESOURCE_NOT_FOUND;
69 }
70
71 return S_OK;
72 }
73
74 static HRESULT FtpProtocol_end_request(Protocol *prot)
75 {
76 return E_NOTIMPL;
77 }
78
79 static HRESULT FtpProtocol_start_downloading(Protocol *prot)
80 {
81 FtpProtocol *This = impl_from_Protocol(prot);
82 DWORD size;
83 BOOL res;
84
85 res = FtpGetFileSize(This->base.request, &size);
86 if(res)
87 This->base.content_length = size;
88 else
89 WARN("FtpGetFileSize failed: %d\n", GetLastError());
90
91 return S_OK;
92 }
93
94 static void FtpProtocol_close_connection(Protocol *prot)
95 {
96 }
97
98 static void FtpProtocol_on_error(Protocol *prot, DWORD error)
99 {
100 FIXME("(%p) %d - stub\n", prot, error);
101 }
102
103 static const ProtocolVtbl AsyncProtocolVtbl = {
104 FtpProtocol_open_request,
105 FtpProtocol_end_request,
106 FtpProtocol_start_downloading,
107 FtpProtocol_close_connection,
108 FtpProtocol_on_error
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 IInternetProtocolEx_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 TRACE("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
381
382 if(!This->base.request)
383 return E_FAIL;
384
385 if(!InternetQueryOptionW(This->base.request, dwOption, pBuffer, pcbBuffer))
386 return S_FALSE;
387 return S_OK;
388 }
389
390 static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
391 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
392 {
393 FtpProtocol *This = impl_from_IWinInetHttpInfo(iface);
394 TRACE("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
395
396 if(!This->base.request)
397 return E_FAIL;
398
399 if(!HttpQueryInfoW(This->base.request, dwOption, pBuffer, pcbBuffer, pdwFlags))
400 return S_FALSE;
401 return S_OK;
402 }
403
404 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
405 HttpInfo_QueryInterface,
406 HttpInfo_AddRef,
407 HttpInfo_Release,
408 HttpInfo_QueryOption,
409 HttpInfo_QueryInfo
410 };
411
412 HRESULT FtpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
413 {
414 FtpProtocol *ret;
415
416 TRACE("(%p %p)\n", pUnkOuter, ppobj);
417
418 URLMON_LockModule();
419
420 ret = heap_alloc_zero(sizeof(FtpProtocol));
421
422 ret->base.vtbl = &AsyncProtocolVtbl;
423 ret->IInternetProtocolEx_iface.lpVtbl = &FtpProtocolVtbl;
424 ret->IInternetPriority_iface.lpVtbl = &FtpPriorityVtbl;
425 ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl;
426 ret->ref = 1;
427
428 *ppobj = &ret->IInternetProtocolEx_iface;
429
430 return S_OK;
431 }