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