iphlpapi: Set DNS servers in GetAdaptersAddresses when GAA_FLAG_SKIP_DNS_SERVER isn...
[wine] / dlls / urlmon / protocol.c
1 /*
2  * Copyright 2007 Misha Koshelev
3  * Copyright 2009 Jacek Caban for CodeWeavers
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include "urlmon_main.h"
21
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
25
26 /* Flags are needed for, among other things, return HRESULTs from the Read function
27  * to conform to native. For example, Read returns:
28  *
29  * 1. E_PENDING if called before the request has completed,
30  *        (flags = 0)
31  * 2. S_FALSE after all data has been read and S_OK has been reported,
32  *        (flags = FLAG_REQUEST_COMPLETE | FLAG_ALL_DATA_READ | FLAG_RESULT_REPORTED)
33  * 3. INET_E_DATA_NOT_AVAILABLE if InternetQueryDataAvailable fails. The first time
34  *    this occurs, INET_E_DATA_NOT_AVAILABLE will also be reported to the sink,
35  *        (flags = FLAG_REQUEST_COMPLETE)
36  *    but upon subsequent calls to Read no reporting will take place, yet
37  *    InternetQueryDataAvailable will still be called, and, on failure,
38  *    INET_E_DATA_NOT_AVAILABLE will still be returned.
39  *        (flags = FLAG_REQUEST_COMPLETE | FLAG_RESULT_REPORTED)
40  *
41  * FLAG_FIRST_DATA_REPORTED and FLAG_LAST_DATA_REPORTED are needed for proper
42  * ReportData reporting. For example, if OnResponse returns S_OK, Continue will
43  * report BSCF_FIRSTDATANOTIFICATION, and when all data has been read Read will
44  * report BSCF_INTERMEDIATEDATANOTIFICATION|BSCF_LASTDATANOTIFICATION. However,
45  * if OnResponse does not return S_OK, Continue will not report data, and Read
46  * will report BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION when all
47  * data has been read.
48  */
49 #define FLAG_REQUEST_COMPLETE         0x0001
50 #define FLAG_FIRST_CONTINUE_COMPLETE  0x0002
51 #define FLAG_FIRST_DATA_REPORTED      0x0004
52 #define FLAG_ALL_DATA_READ            0x0008
53 #define FLAG_LAST_DATA_REPORTED       0x0010
54 #define FLAG_RESULT_REPORTED          0x0020
55
56 static inline HRESULT report_progress(Protocol *protocol, ULONG status_code, LPCWSTR status_text)
57 {
58     return IInternetProtocolSink_ReportProgress(protocol->protocol_sink, status_code, status_text);
59 }
60
61 static inline HRESULT report_result(Protocol *protocol, HRESULT hres)
62 {
63     if (!(protocol->flags & FLAG_RESULT_REPORTED) && protocol->protocol_sink) {
64         protocol->flags |= FLAG_RESULT_REPORTED;
65         IInternetProtocolSink_ReportResult(protocol->protocol_sink, hres, 0, NULL);
66     }
67
68     return hres;
69 }
70
71 static void report_data(Protocol *protocol)
72 {
73     DWORD bscf;
74
75     if((protocol->flags & FLAG_LAST_DATA_REPORTED) || !protocol->protocol_sink)
76         return;
77
78     if(protocol->flags & FLAG_FIRST_DATA_REPORTED) {
79         bscf = BSCF_INTERMEDIATEDATANOTIFICATION;
80     }else {
81         protocol->flags |= FLAG_FIRST_DATA_REPORTED;
82         bscf = BSCF_FIRSTDATANOTIFICATION;
83     }
84
85     if(protocol->flags & FLAG_ALL_DATA_READ && !(protocol->flags & FLAG_LAST_DATA_REPORTED)) {
86         protocol->flags |= FLAG_LAST_DATA_REPORTED;
87         bscf |= BSCF_LASTDATANOTIFICATION;
88     }
89
90     IInternetProtocolSink_ReportData(protocol->protocol_sink, bscf,
91             protocol->current_position+protocol->available_bytes,
92             protocol->content_length);
93 }
94
95 static void all_data_read(Protocol *protocol)
96 {
97     protocol->flags |= FLAG_ALL_DATA_READ;
98
99     report_data(protocol);
100     report_result(protocol, S_OK);
101 }
102
103 static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar)
104 {
105     PROTOCOLDATA data;
106
107     TRACE("(%p)->(%p)\n", protocol, ar);
108
109     if(!ar->dwResult) {
110         WARN("request failed: %d\n", ar->dwError);
111         return;
112     }
113
114     protocol->flags |= FLAG_REQUEST_COMPLETE;
115
116     if(!protocol->request) {
117         TRACE("setting request handle %p\n", (HINTERNET)ar->dwResult);
118         protocol->request = (HINTERNET)ar->dwResult;
119     }
120
121     /* PROTOCOLDATA same as native */
122     memset(&data, 0, sizeof(data));
123     data.dwState = 0xf1000000;
124     if(protocol->flags & FLAG_FIRST_CONTINUE_COMPLETE)
125         data.pData = (LPVOID)BINDSTATUS_ENDDOWNLOADCOMPONENTS;
126     else
127         data.pData = (LPVOID)BINDSTATUS_DOWNLOADINGDATA;
128
129     if (protocol->bindf & BINDF_FROMURLMON)
130         IInternetProtocolSink_Switch(protocol->protocol_sink, &data);
131     else
132         protocol_continue(protocol, &data);
133 }
134
135 static void WINAPI internet_status_callback(HINTERNET internet, DWORD_PTR context,
136         DWORD internet_status, LPVOID status_info, DWORD status_info_len)
137 {
138     Protocol *protocol = (Protocol*)context;
139
140     switch(internet_status) {
141     case INTERNET_STATUS_RESOLVING_NAME:
142         TRACE("%p INTERNET_STATUS_RESOLVING_NAME\n", protocol);
143         report_progress(protocol, BINDSTATUS_FINDINGRESOURCE, (LPWSTR)status_info);
144         break;
145
146     case INTERNET_STATUS_CONNECTING_TO_SERVER:
147         TRACE("%p INTERNET_STATUS_CONNECTING_TO_SERVER\n", protocol);
148         report_progress(protocol, BINDSTATUS_CONNECTING, (LPWSTR)status_info);
149         break;
150
151     case INTERNET_STATUS_SENDING_REQUEST:
152         TRACE("%p INTERNET_STATUS_SENDING_REQUEST\n", protocol);
153         report_progress(protocol, BINDSTATUS_SENDINGREQUEST, (LPWSTR)status_info);
154         break;
155
156     case INTERNET_STATUS_REDIRECT:
157         TRACE("%p INTERNET_STATUS_REDIRECT\n", protocol);
158         report_progress(protocol, BINDSTATUS_REDIRECTING, (LPWSTR)status_info);
159         break;
160
161     case INTERNET_STATUS_REQUEST_COMPLETE:
162         request_complete(protocol, status_info);
163         break;
164
165     case INTERNET_STATUS_HANDLE_CREATED:
166         TRACE("%p INTERNET_STATUS_HANDLE_CREATED\n", protocol);
167         IInternetProtocol_AddRef(protocol->protocol);
168         break;
169
170     case INTERNET_STATUS_HANDLE_CLOSING:
171         TRACE("%p INTERNET_STATUS_HANDLE_CLOSING\n", protocol);
172
173         if(*(HINTERNET *)status_info == protocol->request) {
174             protocol->request = NULL;
175             if(protocol->protocol_sink) {
176                 IInternetProtocolSink_Release(protocol->protocol_sink);
177                 protocol->protocol_sink = NULL;
178             }
179
180             if(protocol->bind_info.cbSize) {
181                 ReleaseBindInfo(&protocol->bind_info);
182                 memset(&protocol->bind_info, 0, sizeof(protocol->bind_info));
183             }
184         }else if(*(HINTERNET *)status_info == protocol->connection) {
185             protocol->connection = NULL;
186         }
187
188         IInternetProtocol_Release(protocol->protocol);
189         break;
190
191     default:
192         WARN("Unhandled Internet status callback %d\n", internet_status);
193     }
194 }
195
196 static HRESULT write_post_stream(Protocol *protocol)
197 {
198     BYTE buf[0x20000];
199     DWORD written;
200     ULONG size;
201     BOOL res;
202     HRESULT hres;
203
204     protocol->flags &= ~FLAG_REQUEST_COMPLETE;
205
206     while(1) {
207         size = 0;
208         hres = IStream_Read(protocol->post_stream, buf, sizeof(buf), &size);
209         if(FAILED(hres) || !size)
210             break;
211         res = InternetWriteFile(protocol->request, buf, size, &written);
212         if(!res) {
213             FIXME("InternetWriteFile failed: %u\n", GetLastError());
214             hres = E_FAIL;
215             break;
216         }
217     }
218
219     if(SUCCEEDED(hres)) {
220         IStream_Release(protocol->post_stream);
221         protocol->post_stream = NULL;
222
223         hres = protocol->vtbl->end_request(protocol);
224     }
225
226     if(FAILED(hres))
227         return report_result(protocol, hres);
228
229     return S_OK;
230 }
231
232 static HINTERNET create_internet_session(IInternetBindInfo *bind_info)
233 {
234     LPWSTR global_user_agent = NULL;
235     LPOLESTR user_agent = NULL;
236     ULONG size = 0;
237     HINTERNET ret;
238     HRESULT hres;
239
240     hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_USER_AGENT, &user_agent, 1, &size);
241     if(hres != S_OK || !size)
242         global_user_agent = get_useragent();
243
244     ret = InternetOpenW(user_agent ? user_agent : global_user_agent, 0, NULL, NULL, INTERNET_FLAG_ASYNC);
245     heap_free(global_user_agent);
246     CoTaskMemFree(user_agent);
247     if(!ret) {
248         WARN("InternetOpen failed: %d\n", GetLastError());
249         return NULL;
250     }
251
252     InternetSetStatusCallbackW(ret, internet_status_callback);
253     return ret;
254 }
255
256 static HINTERNET internet_session;
257
258 HINTERNET get_internet_session(IInternetBindInfo *bind_info)
259 {
260     HINTERNET new_session;
261
262     if(internet_session)
263         return internet_session;
264
265     if(!bind_info)
266         return NULL;
267
268     new_session = create_internet_session(bind_info);
269     if(new_session && InterlockedCompareExchangePointer((void**)&internet_session, new_session, NULL))
270         InternetCloseHandle(new_session);
271
272     return internet_session;
273 }
274
275 HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, IUri *uri,
276         IInternetProtocolSink *protocol_sink, IInternetBindInfo *bind_info)
277 {
278     DWORD request_flags;
279     HRESULT hres;
280
281     protocol->protocol = prot;
282
283     IInternetProtocolSink_AddRef(protocol_sink);
284     protocol->protocol_sink = protocol_sink;
285
286     memset(&protocol->bind_info, 0, sizeof(protocol->bind_info));
287     protocol->bind_info.cbSize = sizeof(BINDINFO);
288     hres = IInternetBindInfo_GetBindInfo(bind_info, &protocol->bindf, &protocol->bind_info);
289     if(hres != S_OK) {
290         WARN("GetBindInfo failed: %08x\n", hres);
291         return report_result(protocol, hres);
292     }
293
294     if(!(protocol->bindf & BINDF_FROMURLMON))
295         report_progress(protocol, BINDSTATUS_DIRECTBIND, NULL);
296
297     if(!get_internet_session(bind_info))
298         return report_result(protocol, INET_E_NO_SESSION);
299
300     request_flags = INTERNET_FLAG_KEEP_CONNECTION;
301     if(protocol->bindf & BINDF_NOWRITECACHE)
302         request_flags |= INTERNET_FLAG_NO_CACHE_WRITE;
303     if(protocol->bindf & BINDF_NEEDFILE)
304         request_flags |= INTERNET_FLAG_NEED_FILE;
305
306     hres = protocol->vtbl->open_request(protocol, uri, request_flags, internet_session, bind_info);
307     if(FAILED(hres)) {
308         protocol_close_connection(protocol);
309         return report_result(protocol, hres);
310     }
311
312     return S_OK;
313 }
314
315 HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data)
316 {
317     HRESULT hres;
318
319     if (!data) {
320         WARN("Expected pProtocolData to be non-NULL\n");
321         return S_OK;
322     }
323
324     if(!protocol->request) {
325         WARN("Expected request to be non-NULL\n");
326         return S_OK;
327     }
328
329     if(!protocol->protocol_sink) {
330         WARN("Expected IInternetProtocolSink pointer to be non-NULL\n");
331         return S_OK;
332     }
333
334     if(protocol->post_stream)
335         return write_post_stream(protocol);
336
337     if(data->pData == (LPVOID)BINDSTATUS_DOWNLOADINGDATA) {
338         hres = protocol->vtbl->start_downloading(protocol);
339         if(FAILED(hres)) {
340             protocol_close_connection(protocol);
341             report_result(protocol, hres);
342             return S_OK;
343         }
344
345         if(protocol->bindf & BINDF_NEEDFILE) {
346             WCHAR cache_file[MAX_PATH];
347             DWORD buflen = sizeof(cache_file);
348
349             if(InternetQueryOptionW(protocol->request, INTERNET_OPTION_DATAFILE_NAME,
350                     cache_file, &buflen)) {
351                 report_progress(protocol, BINDSTATUS_CACHEFILENAMEAVAILABLE, cache_file);
352             }else {
353                 FIXME("Could not get cache file\n");
354             }
355         }
356
357         protocol->flags |= FLAG_FIRST_CONTINUE_COMPLETE;
358     }
359
360     if(data->pData >= (LPVOID)BINDSTATUS_DOWNLOADINGDATA) {
361         BOOL res;
362
363         /* InternetQueryDataAvailable may immediately fork and perform its asynchronous
364          * read, so clear the flag _before_ calling so it does not incorrectly get cleared
365          * after the status callback is called */
366         protocol->flags &= ~FLAG_REQUEST_COMPLETE;
367         res = InternetQueryDataAvailable(protocol->request, &protocol->available_bytes, 0, 0);
368         if(res) {
369             protocol->flags |= FLAG_REQUEST_COMPLETE;
370             report_data(protocol);
371         }else if(GetLastError() != ERROR_IO_PENDING) {
372             protocol->flags |= FLAG_REQUEST_COMPLETE;
373             WARN("InternetQueryDataAvailable failed: %d\n", GetLastError());
374             report_result(protocol, INET_E_DATA_NOT_AVAILABLE);
375         }
376     }
377
378     return S_OK;
379 }
380
381 HRESULT protocol_read(Protocol *protocol, void *buf, ULONG size, ULONG *read_ret)
382 {
383     ULONG read = 0;
384     BOOL res;
385     HRESULT hres = S_FALSE;
386
387     if(protocol->flags & FLAG_ALL_DATA_READ) {
388         *read_ret = 0;
389         return S_FALSE;
390     }
391
392     if(!(protocol->flags & FLAG_REQUEST_COMPLETE)) {
393         *read_ret = 0;
394         return E_PENDING;
395     }
396
397     while(read < size) {
398         if(protocol->available_bytes) {
399             ULONG len;
400
401             res = InternetReadFile(protocol->request, ((BYTE *)buf)+read,
402                     protocol->available_bytes > size-read ? size-read : protocol->available_bytes, &len);
403             if(!res) {
404                 WARN("InternetReadFile failed: %d\n", GetLastError());
405                 hres = INET_E_DOWNLOAD_FAILURE;
406                 report_result(protocol, hres);
407                 break;
408             }
409
410             if(!len) {
411                 all_data_read(protocol);
412                 break;
413             }
414
415             read += len;
416             protocol->current_position += len;
417             protocol->available_bytes -= len;
418         }else {
419             /* InternetQueryDataAvailable may immediately fork and perform its asynchronous
420              * read, so clear the flag _before_ calling so it does not incorrectly get cleared
421              * after the status callback is called */
422             protocol->flags &= ~FLAG_REQUEST_COMPLETE;
423             res = InternetQueryDataAvailable(protocol->request, &protocol->available_bytes, 0, 0);
424             if(!res) {
425                 if (GetLastError() == ERROR_IO_PENDING) {
426                     hres = E_PENDING;
427                 }else {
428                     WARN("InternetQueryDataAvailable failed: %d\n", GetLastError());
429                     hres = INET_E_DATA_NOT_AVAILABLE;
430                     report_result(protocol, hres);
431                 }
432                 break;
433             }
434
435             if(!protocol->available_bytes) {
436                 all_data_read(protocol);
437                 break;
438             }
439         }
440     }
441
442     *read_ret = read;
443
444     if (hres != E_PENDING)
445         protocol->flags |= FLAG_REQUEST_COMPLETE;
446     if(FAILED(hres))
447         return hres;
448
449     return read ? S_OK : S_FALSE;
450 }
451
452 HRESULT protocol_lock_request(Protocol *protocol)
453 {
454     if (!InternetLockRequestFile(protocol->request, &protocol->lock))
455         WARN("InternetLockRequest failed: %d\n", GetLastError());
456
457     return S_OK;
458 }
459
460 HRESULT protocol_unlock_request(Protocol *protocol)
461 {
462     if(!protocol->lock)
463         return S_OK;
464
465     if(!InternetUnlockRequestFile(protocol->lock))
466         WARN("InternetUnlockRequest failed: %d\n", GetLastError());
467     protocol->lock = 0;
468
469     return S_OK;
470 }
471
472 HRESULT protocol_abort(Protocol *protocol, HRESULT reason)
473 {
474     if(!protocol->protocol_sink)
475         return S_OK;
476
477     if(protocol->flags & FLAG_RESULT_REPORTED)
478         return INET_E_RESULT_DISPATCHED;
479
480     report_result(protocol, reason);
481     return S_OK;
482 }
483
484 void protocol_close_connection(Protocol *protocol)
485 {
486     protocol->vtbl->close_connection(protocol);
487
488     if(protocol->request)
489         InternetCloseHandle(protocol->request);
490
491     if(protocol->connection)
492         InternetCloseHandle(protocol->connection);
493
494     if(protocol->post_stream) {
495         IStream_Release(protocol->post_stream);
496         protocol->post_stream = NULL;
497     }
498
499     protocol->flags = 0;
500 }