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