1 /*
2 * Copyright 2007-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 void (*task_proc_t)(BindProtocol*,task_header_t*);
25
26 struct _task_header_t {
27 task_proc_t proc;
28 task_header_t *next;
29 };
30
31 #define BUFFER_SIZE 2048
32 #define MIME_TEST_SIZE 255
33
34 #define WM_MK_CONTINUE (WM_USER+101)
35 #define WM_MK_RELEASE (WM_USER+102)
36
37 static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
38 {
39 switch(msg) {
40 case WM_MK_CONTINUE: {
41 BindProtocol *This = (BindProtocol*)lParam;
42 task_header_t *task;
43
44 while(1) {
45 EnterCriticalSection(&This->section);
46
47 task = This->task_queue_head;
48 if(task) {
49 This->task_queue_head = task->next;
50 if(!This->task_queue_head)
51 This->task_queue_tail = NULL;
52 }
53
54 LeaveCriticalSection(&This->section);
55
56 if(!task)
57 break;
58
59 This->continue_call++;
60 task->proc(This, task);
61 This->continue_call--;
62 }
63
64 IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
65 return 0;
66 }
67 case WM_MK_RELEASE: {
68 tls_data_t *data = get_tls_data();
69
70 if(!--data->notif_hwnd_cnt) {
71 DestroyWindow(hwnd);
72 data->notif_hwnd = NULL;
73 }
74 }
75 }
76
77 return DefWindowProcW(hwnd, msg, wParam, lParam);
78 }
79
80 HWND get_notif_hwnd(void)
81 {
82 static ATOM wnd_class = 0;
83 tls_data_t *tls_data;
84
85 static const WCHAR wszURLMonikerNotificationWindow[] =
86 {'U','R','L',' ','M','o','n','i','k','e','r',' ',
87 'N','o','t','i','f','i','c','a','t','i','o','n',' ','W','i','n','d','o','w',0};
88
89 tls_data = get_tls_data();
90 if(!tls_data)
91 return NULL;
92
93 if(tls_data->notif_hwnd_cnt) {
94 tls_data->notif_hwnd_cnt++;
95 return tls_data->notif_hwnd;
96 }
97
98 if(!wnd_class) {
99 static WNDCLASSEXW wndclass = {
100 sizeof(wndclass), 0,
101 notif_wnd_proc, 0, 0,
102 NULL, NULL, NULL, NULL, NULL,
103 wszURLMonikerNotificationWindow,
104 NULL
105 };
106
107 wndclass.hInstance = hProxyDll;
108
109 wnd_class = RegisterClassExW(&wndclass);
110 if (!wnd_class && GetLastError() == ERROR_CLASS_ALREADY_EXISTS)
111 wnd_class = 1;
112 }
113
114 tls_data->notif_hwnd = CreateWindowExW(0, wszURLMonikerNotificationWindow,
115 wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
116 NULL, hProxyDll, NULL);
117 if(tls_data->notif_hwnd)
118 tls_data->notif_hwnd_cnt++;
119
120 TRACE("hwnd = %p\n", tls_data->notif_hwnd);
121
122 return tls_data->notif_hwnd;
123 }
124
125 void release_notif_hwnd(HWND hwnd)
126 {
127 tls_data_t *data = get_tls_data();
128
129 if(!data)
130 return;
131
132 if(data->notif_hwnd != hwnd) {
133 PostMessageW(data->notif_hwnd, WM_MK_RELEASE, 0, 0);
134 return;
135 }
136
137 if(!--data->notif_hwnd_cnt) {
138 DestroyWindow(data->notif_hwnd);
139 data->notif_hwnd = NULL;
140 }
141 }
142
143 static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
144 {
145 BOOL do_post = FALSE;
146
147 task->proc = proc;
148 task->next = NULL;
149
150 EnterCriticalSection(&This->section);
151
152 if(This->task_queue_tail) {
153 This->task_queue_tail->next = task;
154 This->task_queue_tail = task;
155 }else {
156 This->task_queue_tail = This->task_queue_head = task;
157 do_post = !This->continue_call;
158 }
159
160 LeaveCriticalSection(&This->section);
161
162 if(do_post) {
163 IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
164 PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
165 }
166 }
167
168 static inline BOOL do_direct_notif(BindProtocol *This)
169 {
170 return !(This->pi & PI_APARTMENTTHREADED) || (This->apartment_thread == GetCurrentThreadId() && !This->continue_call);
171 }
172
173 static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter)
174 {
175 PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
176 HRESULT hres;
177
178 hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&This->protocol_sink_handler);
179 if(FAILED(hres)) {
180 This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
181 return hres;
182 }
183
184 IInternetProtocol_AddRef(mime_filter);
185 This->protocol_handler = mime_filter;
186
187 filter_data.pProtocol = &This->default_protocol_handler.IInternetProtocol_iface;
188 hres = IInternetProtocol_Start(mime_filter, This->mime, &This->default_protocol_handler.IInternetProtocolSink_iface,
189 &This->IInternetBindInfo_iface, PI_FILTER_MODE|PI_FORCE_ASYNC,
190 (HANDLE_PTR)&filter_data);
191 if(FAILED(hres)) {
192 IInternetProtocolSink_Release(This->protocol_sink_handler);
193 IInternetProtocol_Release(This->protocol_handler);
194 This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
195 This->protocol_handler = &This->default_protocol_handler.IInternetProtocol_iface;
196 return hres;
197 }
198
199 /* NOTE: IE9 calls it on the new protocol_sink. It doesn't make sense to is seems to be a bug there. */
200 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
201
202 return S_OK;
203 }
204
205 static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified)
206 {
207 IInternetProtocol *mime_filter;
208 HRESULT hres;
209
210 heap_free(This->mime);
211 This->mime = heap_strdupW(mime);
212
213 if(This->protocol_handler==&This->default_protocol_handler.IInternetProtocol_iface
214 && (mime_filter = get_mime_filter(mime))) {
215 TRACE("Got mime filter for %s\n", debugstr_w(mime));
216
217 hres = handle_mime_filter(This, mime_filter);
218 IInternetProtocol_Release(mime_filter);
219 if(FAILED(hres))
220 FIXME("MIME filter failed: %08x\n", hres);
221 }
222
223 if(This->reported_mime || verified || !(This->pi & PI_MIMEVERIFICATION)) {
224 This->reported_mime = TRUE;
225 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
226 }
227 }
228
229 static inline BindProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
230 {
231 return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolEx_iface);
232 }
233
234 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
235 {
236 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
237
238 *ppv = NULL;
239 if(IsEqualGUID(&IID_IUnknown, riid)) {
240 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
241 *ppv = &This->IInternetProtocolEx_iface;
242 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
243 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
244 *ppv = &This->IInternetProtocolEx_iface;
245 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
246 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
247 *ppv = &This->IInternetProtocolEx_iface;
248 }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
249 TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
250 *ppv = &This->IInternetProtocolEx_iface;
251 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
252 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
253 *ppv = &This->IInternetBindInfo_iface;
254 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
255 TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
256 *ppv = &This->IInternetPriority_iface;
257 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
258 FIXME("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
259 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
260 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
261 *ppv = &This->IServiceProvider_iface;
262 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
263 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
264 *ppv = &This->IInternetProtocolSink_iface;
265 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
266 TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
267
268 if(This->protocol) {
269 IWinInetInfo *inet_info;
270 HRESULT hres;
271
272 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info);
273 if(SUCCEEDED(hres)) {
274 *ppv = &This->IWinInetHttpInfo_iface;
275 IWinInetInfo_Release(inet_info);
276 }
277 }
278 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
279 TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv);
280
281 if(This->protocol) {
282 IWinInetHttpInfo *http_info;
283 HRESULT hres;
284
285 hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
286 if(SUCCEEDED(hres)) {
287 *ppv = &This->IWinInetHttpInfo_iface;
288 IWinInetHttpInfo_Release(http_info);
289 }
290 }
291 }else {
292 WARN("not supported interface %s\n", debugstr_guid(riid));
293 }
294
295 if(!*ppv)
296 return E_NOINTERFACE;
297
298 IUnknown_AddRef((IUnknown*)*ppv);
299 return S_OK;
300 }
301
302 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
303 {
304 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
305 LONG ref = InterlockedIncrement(&This->ref);
306 TRACE("(%p) ref=%d\n", This, ref);
307 return ref;
308 }
309
310 static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
311 {
312 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
313 LONG ref = InterlockedDecrement(&This->ref);
314
315 TRACE("(%p) ref=%d\n", This, ref);
316
317 if(!ref) {
318 if(This->wininet_info)
319 IWinInetInfo_Release(This->wininet_info);
320 if(This->wininet_http_info)
321 IWinInetHttpInfo_Release(This->wininet_http_info);
322 if(This->protocol)
323 IInternetProtocol_Release(This->protocol);
324 if(This->bind_info)
325 IInternetBindInfo_Release(This->bind_info);
326 if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface)
327 IInternetProtocol_Release(This->protocol_handler);
328 if(This->protocol_sink_handler &&
329 This->protocol_sink_handler != &This->default_protocol_handler.IInternetProtocolSink_iface)
330 IInternetProtocolSink_Release(This->protocol_sink_handler);
331 if(This->uri)
332 IUri_Release(This->uri);
333 SysFreeString(This->display_uri);
334
335 set_binding_sink(This, NULL, NULL);
336
337 if(This->notif_hwnd)
338 release_notif_hwnd(This->notif_hwnd);
339 This->section.DebugInfo->Spare[0] = 0;
340 DeleteCriticalSection(&This->section);
341
342 heap_free(This->mime);
343 heap_free(This);
344
345 URLMON_UnlockModule();
346 }
347
348 return ref;
349 }
350
351 static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
352 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
353 DWORD grfPI, HANDLE_PTR dwReserved)
354 {
355 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
356 IUri *uri;
357 HRESULT hres;
358
359 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
360 pOIBindInfo, grfPI, dwReserved);
361
362 hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
363 if(FAILED(hres))
364 return hres;
365
366 hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
367 pOIBindInfo, grfPI, (HANDLE*)dwReserved);
368
369 IUri_Release(uri);
370 return hres;
371 }
372
373 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
374 {
375 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
376
377 TRACE("(%p)->(%p)\n", This, pProtocolData);
378
379 return IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
380 }
381
382 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
383 DWORD dwOptions)
384 {
385 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
386
387 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
388
389 return IInternetProtocol_Abort(This->protocol_handler, hrReason, dwOptions);
390 }
391
392 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
393 {
394 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
395
396 TRACE("(%p)->(%08x)\n", This, dwOptions);
397
398 return IInternetProtocol_Terminate(This->protocol_handler, dwOptions);
399 }
400
401 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocolEx *iface)
402 {
403 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
404 FIXME("(%p)\n", This);
405 return E_NOTIMPL;
406 }
407
408 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
409 {
410 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
411 FIXME("(%p)\n", This);
412 return E_NOTIMPL;
413 }
414
415 static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
416 ULONG cb, ULONG *pcbRead)
417 {
418 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
419
420 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
421
422 if(pcbRead)
423 *pcbRead = 0;
424 return IInternetProtocol_Read(This->protocol_handler, pv, cb, pcbRead);
425 }
426
427 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
428 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
429 {
430 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
431 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
432 return E_NOTIMPL;
433 }
434
435 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
436 {
437 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
438
439 TRACE("(%p)->(%08x)\n", This, dwOptions);
440
441 return IInternetProtocol_LockRequest(This->protocol_handler, dwOptions);
442 }
443
444 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocolEx *iface)
445 {
446 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
447
448 TRACE("(%p)\n", This);
449
450 return IInternetProtocol_UnlockRequest(This->protocol_handler);
451 }
452
453 static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
454 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
455 DWORD grfPI, HANDLE *dwReserved)
456 {
457 BindProtocol *This = impl_from_IInternetProtocolEx(iface);
458 IInternetProtocol *protocol = NULL;
459 IInternetProtocolEx *protocolex;
460 IInternetPriority *priority;
461 IServiceProvider *service_provider;
462 BOOL urlmon_protocol = FALSE;
463 CLSID clsid = IID_NULL;
464 LPOLESTR clsid_str;
465 HRESULT hres;
466
467 TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
468
469 if(!pUri || !pOIProtSink || !pOIBindInfo)
470 return E_INVALIDARG;
471
472 This->pi = grfPI;
473
474 IUri_AddRef(pUri);
475 This->uri = pUri;
476
477 hres = IInternetProtocolSink_QueryInterface(pOIProtSink, &IID_IServiceProvider,
478 (void**)&service_provider);
479 if(SUCCEEDED(hres)) {
480 /* FIXME: What's protocol CLSID here? */
481 IServiceProvider_QueryService(service_provider, &IID_IInternetProtocol,
482 &IID_IInternetProtocol, (void**)&protocol);
483 IServiceProvider_Release(service_provider);
484 }
485
486 if(!protocol) {
487 IClassFactory *cf;
488 IUnknown *unk;
489
490 hres = get_protocol_handler(pUri, &clsid, &urlmon_protocol, &cf);
491 if(FAILED(hres))
492 return hres;
493
494 if(This->from_urlmon) {
495 hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol);
496 IClassFactory_Release(cf);
497 if(FAILED(hres))
498 return hres;
499 }else {
500 hres = IClassFactory_CreateInstance(cf, (IUnknown*)&This->IInternetBindInfo_iface,
501 &IID_IUnknown, (void**)&unk);
502 IClassFactory_Release(cf);
503 if(FAILED(hres))
504 return hres;
505
506 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol);
507 IUnknown_Release(unk);
508 if(FAILED(hres))
509 return hres;
510 }
511 }
512
513 StringFromCLSID(&clsid, &clsid_str);
514 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str);
515 CoTaskMemFree(clsid_str);
516
517 This->protocol = protocol;
518
519 if(urlmon_protocol) {
520 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
521 IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&This->wininet_http_info);
522 }
523
524 set_binding_sink(This, pOIProtSink, pOIBindInfo);
525
526 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
527 if(SUCCEEDED(hres)) {
528 IInternetPriority_SetPriority(priority, This->priority);
529 IInternetPriority_Release(priority);
530 }
531
532 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
533 if(SUCCEEDED(hres)) {
534 hres = IInternetProtocolEx_StartEx(protocolex, pUri, &This->IInternetProtocolSink_iface,
535 &This->IInternetBindInfo_iface, 0, NULL);
536 IInternetProtocolEx_Release(protocolex);
537 }else {
538 hres = IUri_GetDisplayUri(pUri, &This->display_uri);
539 if(FAILED(hres))
540 return hres;
541
542 hres = IInternetProtocol_Start(protocol, This->display_uri, &This->IInternetProtocolSink_iface,
543 &This->IInternetBindInfo_iface, 0, 0);
544 }
545
546 return hres;
547 }
548
549 void set_binding_sink(BindProtocol *This, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
550 {
551 IInternetProtocolSink *prev_sink;
552 IServiceProvider *service_provider = NULL;
553
554 if(sink)
555 IInternetProtocolSink_AddRef(sink);
556 prev_sink = InterlockedExchangePointer((void**)&This->protocol_sink, sink);
557 if(prev_sink)
558 IInternetProtocolSink_Release(prev_sink);
559
560 if(sink)
561 IInternetProtocolSink_QueryInterface(sink, &IID_IServiceProvider, (void**)&service_provider);
562 service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
563 if(service_provider)
564 IServiceProvider_Release(service_provider);
565
566 if(bind_info)
567 IInternetBindInfo_AddRef(bind_info);
568 bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
569 if(bind_info)
570 IInternetBindInfo_Release(bind_info);
571 }
572
573 static const IInternetProtocolExVtbl BindProtocolVtbl = {
574 BindProtocol_QueryInterface,
575 BindProtocol_AddRef,
576 BindProtocol_Release,
577 BindProtocol_Start,
578 BindProtocol_Continue,
579 BindProtocol_Abort,
580 BindProtocol_Terminate,
581 BindProtocol_Suspend,
582 BindProtocol_Resume,
583 BindProtocol_Read,
584 BindProtocol_Seek,
585 BindProtocol_LockRequest,
586 BindProtocol_UnlockRequest,
587 BindProtocol_StartEx
588 };
589
590 static inline BindProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
591 {
592 return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocol_iface);
593 }
594
595 static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
596 {
597 BindProtocol *This = impl_from_IInternetProtocol(iface);
598
599 *ppv = NULL;
600 if(IsEqualGUID(&IID_IUnknown, riid)) {
601 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
602 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
603 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
604 TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
605 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
606 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
607 TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
608 *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
609 }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
610 TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
611 *ppv = &This->default_protocol_handler.IInternetProtocolSink_iface;
612 }
613
614 if(*ppv) {
615 IInternetProtocol_AddRef(iface);
616 return S_OK;
617 }
618
619 WARN("not supported interface %s\n", debugstr_guid(riid));
620 return E_NOINTERFACE;
621 }
622
623 static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface)
624 {
625 BindProtocol *This = impl_from_IInternetProtocol(iface);
626 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
627 }
628
629 static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface)
630 {
631 BindProtocol *This = impl_from_IInternetProtocol(iface);
632 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
633 }
634
635 static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR szUrl,
636 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
637 DWORD grfPI, HANDLE_PTR dwReserved)
638 {
639 ERR("Should not be called\n");
640 return E_NOTIMPL;
641 }
642
643 static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
644 {
645 BindProtocol *This = impl_from_IInternetProtocol(iface);
646 HRESULT hres;
647
648 TRACE("(%p)->(%p)\n", This, pProtocolData);
649
650 hres = IInternetProtocol_Continue(This->protocol, pProtocolData);
651
652 heap_free(pProtocolData);
653 return hres;
654 }
655
656 static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocol *iface, HRESULT hrReason,
657 DWORD dwOptions)
658 {
659 BindProtocol *This = impl_from_IInternetProtocol(iface);
660
661 TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
662
663 if(This->protocol && !This->reported_result)
664 return IInternetProtocol_Abort(This->protocol, hrReason, dwOptions);
665
666 return S_OK;
667 }
668
669 static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD dwOptions)
670 {
671 BindProtocol *This = impl_from_IInternetProtocol(iface);
672
673 TRACE("(%p)->(%08x)\n", This, dwOptions);
674
675 if(!This->reported_result)
676 return E_FAIL;
677
678 IInternetProtocol_Terminate(This->protocol, 0);
679
680 set_binding_sink(This, NULL, NULL);
681
682 if(This->bind_info) {
683 IInternetBindInfo_Release(This->bind_info);
684 This->bind_info = NULL;
685 }
686
687 return S_OK;
688 }
689
690 static HRESULT WINAPI ProtocolHandler_Suspend(IInternetProtocol *iface)
691 {
692 BindProtocol *This = impl_from_IInternetProtocol(iface);
693 FIXME("(%p)\n", This);
694 return E_NOTIMPL;
695 }
696
697 static HRESULT WINAPI ProtocolHandler_Resume(IInternetProtocol *iface)
698 {
699 BindProtocol *This = impl_from_IInternetProtocol(iface);
700 FIXME("(%p)\n", This);
701 return E_NOTIMPL;
702 }
703
704 static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv,
705 ULONG cb, ULONG *pcbRead)
706 {
707 BindProtocol *This = impl_from_IInternetProtocol(iface);
708 ULONG read = 0;
709 HRESULT hres = S_OK;
710
711 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
712
713 if(This->buf_size) {
714 read = min(cb, This->buf_size);
715 memcpy(pv, This->buf, read);
716
717 if(read == This->buf_size) {
718 heap_free(This->buf);
719 This->buf = NULL;
720 }else {
721 memmove(This->buf, This->buf+cb, This->buf_size-cb);
722 }
723
724 This->buf_size -= read;
725 }
726
727 if(read < cb) {
728 ULONG cread = 0;
729
730 hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread);
731 read += cread;
732 }
733
734 *pcbRead = read;
735 return hres;
736 }
737
738 static HRESULT WINAPI ProtocolHandler_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
739 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
740 {
741 BindProtocol *This = impl_from_IInternetProtocol(iface);
742 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
743 return E_NOTIMPL;
744 }
745
746 static HRESULT WINAPI ProtocolHandler_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
747 {
748 BindProtocol *This = impl_from_IInternetProtocol(iface);
749
750 TRACE("(%p)->(%08x)\n", This, dwOptions);
751
752 return IInternetProtocol_LockRequest(This->protocol, dwOptions);
753 }
754
755 static HRESULT WINAPI ProtocolHandler_UnlockRequest(IInternetProtocol *iface)
756 {
757 BindProtocol *This = impl_from_IInternetProtocol(iface);
758
759 TRACE("(%p)\n", This);
760
761 return IInternetProtocol_UnlockRequest(This->protocol);
762 }
763
764 static const IInternetProtocolVtbl InternetProtocolHandlerVtbl = {
765 ProtocolHandler_QueryInterface,
766 ProtocolHandler_AddRef,
767 ProtocolHandler_Release,
768 ProtocolHandler_Start,
769 ProtocolHandler_Continue,
770 ProtocolHandler_Abort,
771 ProtocolHandler_Terminate,
772 ProtocolHandler_Suspend,
773 ProtocolHandler_Resume,
774 ProtocolHandler_Read,
775 ProtocolHandler_Seek,
776 ProtocolHandler_LockRequest,
777 ProtocolHandler_UnlockRequest
778 };
779
780 static inline BindProtocol *impl_from_IInternetProtocolSinkHandler(IInternetProtocolSink *iface)
781 {
782 return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocolSink_iface);
783 }
784
785 static HRESULT WINAPI ProtocolSinkHandler_QueryInterface(IInternetProtocolSink *iface,
786 REFIID riid, void **ppvObject)
787 {
788 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
789 return IInternetProtocol_QueryInterface(&This->default_protocol_handler.IInternetProtocol_iface,
790 riid, ppvObject);
791 }
792
793 static ULONG WINAPI ProtocolSinkHandler_AddRef(IInternetProtocolSink *iface)
794 {
795 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
796 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
797 }
798
799 static ULONG WINAPI ProtocolSinkHandler_Release(IInternetProtocolSink *iface)
800 {
801 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
802 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
803 }
804
805 static HRESULT WINAPI ProtocolSinkHandler_Switch(IInternetProtocolSink *iface,
806 PROTOCOLDATA *pProtocolData)
807 {
808 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
809
810 TRACE("(%p)->(%p)\n", This, pProtocolData);
811
812 if(!This->protocol_sink) {
813 IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
814 return S_OK;
815 }
816
817 return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
818 }
819
820 static HRESULT WINAPI ProtocolSinkHandler_ReportProgress(IInternetProtocolSink *iface,
821 ULONG status_code, LPCWSTR status_text)
822 {
823 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
824
825 TRACE("(%p)->(%u %s)\n", This, status_code, debugstr_w(status_text));
826
827 if(!This->protocol_sink)
828 return S_OK;
829
830 switch(status_code) {
831 case BINDSTATUS_FINDINGRESOURCE:
832 case BINDSTATUS_CONNECTING:
833 case BINDSTATUS_REDIRECTING:
834 case BINDSTATUS_SENDINGREQUEST:
835 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
836 case BINDSTATUS_DIRECTBIND:
837 case BINDSTATUS_ACCEPTRANGES:
838 case BINDSTATUS_DECODING:
839 IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
840 break;
841
842 case BINDSTATUS_BEGINDOWNLOADDATA:
843 IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
844 break;
845
846 case BINDSTATUS_MIMETYPEAVAILABLE:
847 mime_available(This, status_text, FALSE);
848 break;
849
850 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
851 mime_available(This, status_text, TRUE);
852 break;
853
854 default:
855 FIXME("unsupported ulStatusCode %u\n", status_code);
856 }
857
858 return S_OK;
859 }
860
861 static HRESULT WINAPI ProtocolSinkHandler_ReportData(IInternetProtocolSink *iface,
862 DWORD bscf, ULONG progress, ULONG progress_max)
863 {
864 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
865
866 TRACE("(%p)->(%x %u %u)\n", This, bscf, progress, progress_max);
867
868 This->bscf = bscf;
869 This->progress = progress;
870 This->progress_max = progress_max;
871
872 if(!This->protocol_sink)
873 return S_OK;
874
875 if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
876 BYTE buf[BUFFER_SIZE];
877 DWORD read = 0;
878 LPWSTR mime;
879 HRESULT hres;
880
881 do {
882 read = 0;
883 hres = IInternetProtocol_Read(This->protocol, buf,
884 sizeof(buf)-This->buf_size, &read);
885 if(FAILED(hres) && hres != E_PENDING)
886 return hres;
887
888 if(!This->buf) {
889 This->buf = heap_alloc(BUFFER_SIZE);
890 if(!This->buf)
891 return E_OUTOFMEMORY;
892 }else if(read + This->buf_size > BUFFER_SIZE) {
893 BYTE *tmp;
894
895 tmp = heap_realloc(This->buf, read+This->buf_size);
896 if(!tmp)
897 return E_OUTOFMEMORY;
898 This->buf = tmp;
899 }
900
901 memcpy(This->buf+This->buf_size, buf, read);
902 This->buf_size += read;
903 }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
904
905 if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
906 return S_OK;
907
908 bscf = BSCF_FIRSTDATANOTIFICATION;
909 if(hres == S_FALSE)
910 bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
911
912 if(!This->reported_mime) {
913 BSTR raw_uri;
914
915 hres = IUri_GetRawUri(This->uri, &raw_uri);
916 if(FAILED(hres))
917 return hres;
918
919 hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
920 This->mime, 0, &mime, 0);
921 SysFreeString(raw_uri);
922 if(FAILED(hres))
923 return hres;
924
925 heap_free(This->mime);
926 This->mime = heap_strdupW(mime);
927 CoTaskMemFree(mime);
928 This->reported_mime = TRUE;
929 if(This->protocol_sink)
930 IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, This->mime);
931 }
932 }
933
934 if(!This->protocol_sink)
935 return S_OK;
936
937 return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
938 }
939
940 static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *iface,
941 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
942 {
943 BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
944
945 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
946
947 if(This->protocol_sink)
948 return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
949 return S_OK;
950 }
951
952 static const IInternetProtocolSinkVtbl InternetProtocolSinkHandlerVtbl = {
953 ProtocolSinkHandler_QueryInterface,
954 ProtocolSinkHandler_AddRef,
955 ProtocolSinkHandler_Release,
956 ProtocolSinkHandler_Switch,
957 ProtocolSinkHandler_ReportProgress,
958 ProtocolSinkHandler_ReportData,
959 ProtocolSinkHandler_ReportResult
960 };
961
962 static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
963 {
964 return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
965 }
966
967 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
968 REFIID riid, void **ppv)
969 {
970 BindProtocol *This = impl_from_IInternetBindInfo(iface);
971 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
972 }
973
974 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
975 {
976 BindProtocol *This = impl_from_IInternetBindInfo(iface);
977 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
978 }
979
980 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
981 {
982 BindProtocol *This = impl_from_IInternetBindInfo(iface);
983 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
984 }
985
986 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
987 DWORD *grfBINDF, BINDINFO *pbindinfo)
988 {
989 BindProtocol *This = impl_from_IInternetBindInfo(iface);
990 HRESULT hres;
991
992 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
993
994 hres = IInternetBindInfo_GetBindInfo(This->bind_info, grfBINDF, pbindinfo);
995 if(FAILED(hres)) {
996 WARN("GetBindInfo failed: %08x\n", hres);
997 return hres;
998 }
999
1000 *grfBINDF |= BINDF_FROMURLMON;
1001 return hres;
1002 }
1003
1004 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
1005 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1006 {
1007 BindProtocol *This = impl_from_IInternetBindInfo(iface);
1008
1009 TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
1010
1011 return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
1012 }
1013
1014 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
1015 BindInfo_QueryInterface,
1016 BindInfo_AddRef,
1017 BindInfo_Release,
1018 BindInfo_GetBindInfo,
1019 BindInfo_GetBindString
1020 };
1021
1022 static inline BindProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
1023 {
1024 return CONTAINING_RECORD(iface, BindProtocol, IInternetPriority_iface);
1025 }
1026
1027 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1028 REFIID riid, void **ppv)
1029 {
1030 BindProtocol *This = impl_from_IInternetPriority(iface);
1031 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1032 }
1033
1034 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1035 {
1036 BindProtocol *This = impl_from_IInternetPriority(iface);
1037 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1038 }
1039
1040 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1041 {
1042 BindProtocol *This = impl_from_IInternetPriority(iface);
1043 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1044 }
1045
1046 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1047 {
1048 BindProtocol *This = impl_from_IInternetPriority(iface);
1049
1050 TRACE("(%p)->(%d)\n", This, nPriority);
1051
1052 This->priority = nPriority;
1053 return S_OK;
1054 }
1055
1056 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1057 {
1058 BindProtocol *This = impl_from_IInternetPriority(iface);
1059
1060 TRACE("(%p)->(%p)\n", This, pnPriority);
1061
1062 *pnPriority = This->priority;
1063 return S_OK;
1064 }
1065
1066 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1067 InternetPriority_QueryInterface,
1068 InternetPriority_AddRef,
1069 InternetPriority_Release,
1070 InternetPriority_SetPriority,
1071 InternetPriority_GetPriority
1072
1073 };
1074
1075 static inline BindProtocol *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
1076 {
1077 return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolSink_iface);
1078 }
1079
1080 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
1081 REFIID riid, void **ppv)
1082 {
1083 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1084 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1085 }
1086
1087 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
1088 {
1089 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1090 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1091 }
1092
1093 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
1094 {
1095 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1096 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1097 }
1098
1099 typedef struct {
1100 task_header_t header;
1101 PROTOCOLDATA *data;
1102 } switch_task_t;
1103
1104 static void switch_proc(BindProtocol *bind, task_header_t *t)
1105 {
1106 switch_task_t *task = (switch_task_t*)t;
1107
1108 IInternetProtocol_Continue(bind->protocol_handler, task->data);
1109
1110 heap_free(task);
1111 }
1112
1113 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
1114 PROTOCOLDATA *pProtocolData)
1115 {
1116 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1117 PROTOCOLDATA *data;
1118
1119 TRACE("(%p)->(%p)\n", This, pProtocolData);
1120
1121 TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState,
1122 pProtocolData->pData, pProtocolData->cbData);
1123
1124 data = heap_alloc(sizeof(PROTOCOLDATA));
1125 if(!data)
1126 return E_OUTOFMEMORY;
1127 memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
1128
1129 if((This->pi&PI_APARTMENTTHREADED && pProtocolData->grfFlags&PI_FORCE_ASYNC)
1130 || !do_direct_notif(This)) {
1131 switch_task_t *task;
1132
1133 task = heap_alloc(sizeof(switch_task_t));
1134 if(!task)
1135 return E_OUTOFMEMORY;
1136
1137 task->data = data;
1138
1139 push_task(This, &task->header, switch_proc);
1140 return S_OK;
1141 }
1142
1143 return IInternetProtocolSink_Switch(This->protocol_sink_handler, data);
1144 }
1145
1146 typedef struct {
1147 task_header_t header;
1148
1149 ULONG status_code;
1150 LPWSTR status_text;
1151 } on_progress_task_t;
1152
1153 static void on_progress_proc(BindProtocol *This, task_header_t *t)
1154 {
1155 on_progress_task_t *task = (on_progress_task_t*)t;
1156
1157 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, task->status_code, task->status_text);
1158
1159 heap_free(task->status_text);
1160 heap_free(task);
1161 }
1162
1163 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
1164 ULONG ulStatusCode, LPCWSTR szStatusText)
1165 {
1166 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1167
1168 TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
1169
1170 if(do_direct_notif(This)) {
1171 IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, ulStatusCode, szStatusText);
1172 }else {
1173 on_progress_task_t *task;
1174
1175 task = heap_alloc(sizeof(on_progress_task_t));
1176
1177 task->status_code = ulStatusCode;
1178 task->status_text = heap_strdupW(szStatusText);
1179
1180 push_task(This, &task->header, on_progress_proc);
1181 }
1182
1183 return S_OK;
1184 }
1185
1186 typedef struct {
1187 task_header_t header;
1188 DWORD bscf;
1189 ULONG progress;
1190 ULONG progress_max;
1191 } report_data_task_t;
1192
1193 static void report_data_proc(BindProtocol *This, task_header_t *t)
1194 {
1195 report_data_task_t *task = (report_data_task_t*)t;
1196
1197 IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1198 task->bscf, task->progress, task->progress_max);
1199
1200 heap_free(task);
1201 }
1202
1203 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
1204 DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
1205 {
1206 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1207
1208 TRACE("(%p)->(%x %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
1209
1210 if(!This->protocol_sink)
1211 return S_OK;
1212
1213 if(!do_direct_notif(This)) {
1214 report_data_task_t *task;
1215
1216 task = heap_alloc(sizeof(report_data_task_t));
1217 if(!task)
1218 return E_OUTOFMEMORY;
1219
1220 task->bscf = grfBSCF;
1221 task->progress = ulProgress;
1222 task->progress_max = ulProgressMax;
1223
1224 push_task(This, &task->header, report_data_proc);
1225 return S_OK;
1226 }
1227
1228 return IInternetProtocolSink_ReportData(This->protocol_sink_handler,
1229 grfBSCF, ulProgress, ulProgressMax);
1230 }
1231
1232 typedef struct {
1233 task_header_t header;
1234
1235 HRESULT hres;
1236 DWORD err;
1237 LPWSTR str;
1238 } report_result_task_t;
1239
1240 static void report_result_proc(BindProtocol *This, task_header_t *t)
1241 {
1242 report_result_task_t *task = (report_result_task_t*)t;
1243
1244 IInternetProtocolSink_ReportResult(This->protocol_sink_handler, task->hres, task->err, task->str);
1245
1246 heap_free(task->str);
1247 heap_free(task);
1248 }
1249
1250 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
1251 HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
1252 {
1253 BindProtocol *This = impl_from_IInternetProtocolSink(iface);
1254
1255 TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
1256
1257 if(!This->protocol_sink)
1258 return E_FAIL;
1259 This->reported_result = TRUE;
1260
1261 if(!do_direct_notif(This)) {
1262 report_result_task_t *task;
1263
1264 task = heap_alloc(sizeof(report_result_task_t));
1265 if(!task)
1266 return E_OUTOFMEMORY;
1267
1268 task->hres = hrResult;
1269 task->err = dwError;
1270 task->str = heap_strdupW(szResult);
1271
1272 push_task(This, &task->header, report_result_proc);
1273 return S_OK;
1274 }
1275
1276 return IInternetProtocolSink_ReportResult(This->protocol_sink_handler, hrResult, dwError, szResult);
1277 }
1278
1279 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
1280 BPInternetProtocolSink_QueryInterface,
1281 BPInternetProtocolSink_AddRef,
1282 BPInternetProtocolSink_Release,
1283 BPInternetProtocolSink_Switch,
1284 BPInternetProtocolSink_ReportProgress,
1285 BPInternetProtocolSink_ReportData,
1286 BPInternetProtocolSink_ReportResult
1287 };
1288
1289 static inline BindProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
1290 {
1291 return CONTAINING_RECORD(iface, BindProtocol, IWinInetHttpInfo_iface);
1292 }
1293
1294 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
1295 {
1296 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1297 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1298 }
1299
1300 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
1301 {
1302 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1303 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1304 }
1305
1306 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
1307 {
1308 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1309 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1310 }
1311
1312 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
1313 void *pBuffer, DWORD *pcbBuffer)
1314 {
1315 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1316 FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
1317 return E_NOTIMPL;
1318 }
1319
1320 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
1321 void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
1322 {
1323 BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
1324 FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
1325 return E_NOTIMPL;
1326 }
1327
1328 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
1329 WinInetHttpInfo_QueryInterface,
1330 WinInetHttpInfo_AddRef,
1331 WinInetHttpInfo_Release,
1332 WinInetHttpInfo_QueryOption,
1333 WinInetHttpInfo_QueryInfo
1334 };
1335
1336 static inline BindProtocol *impl_from_IServiceProvider(IServiceProvider *iface)
1337 {
1338 return CONTAINING_RECORD(iface, BindProtocol, IServiceProvider_iface);
1339 }
1340
1341 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
1342 REFIID riid, void **ppv)
1343 {
1344 BindProtocol *This = impl_from_IServiceProvider(iface);
1345 return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
1346 }
1347
1348 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
1349 {
1350 BindProtocol *This = impl_from_IServiceProvider(iface);
1351 return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1352 }
1353
1354 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
1355 {
1356 BindProtocol *This = impl_from_IServiceProvider(iface);
1357 return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
1358 }
1359
1360 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
1361 REFGUID guidService, REFIID riid, void **ppv)
1362 {
1363 BindProtocol *This = impl_from_IServiceProvider(iface);
1364
1365 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1366
1367 if(!This->service_provider)
1368 return E_NOINTERFACE;
1369
1370 return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
1371 }
1372
1373 static const IServiceProviderVtbl ServiceProviderVtbl = {
1374 BPServiceProvider_QueryInterface,
1375 BPServiceProvider_AddRef,
1376 BPServiceProvider_Release,
1377 BPServiceProvider_QueryService
1378 };
1379
1380 HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol)
1381 {
1382 BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
1383
1384 ret->IInternetProtocolEx_iface.lpVtbl = &BindProtocolVtbl;
1385 ret->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
1386 ret->IInternetPriority_iface.lpVtbl = &InternetPriorityVtbl;
1387 ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
1388 ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
1389 ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl;
1390
1391 ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
1392 ret->default_protocol_handler.IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkHandlerVtbl;
1393
1394 ret->ref = 1;
1395 ret->from_urlmon = from_urlmon;
1396 ret->apartment_thread = GetCurrentThreadId();
1397 ret->notif_hwnd = get_notif_hwnd();
1398 ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface;
1399 ret->protocol_sink_handler = &ret->default_protocol_handler.IInternetProtocolSink_iface;
1400 InitializeCriticalSection(&ret->section);
1401 ret->section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BindProtocol.section");
1402
1403 URLMON_LockModule();
1404
1405 *protocol = ret;
1406 return S_OK;
1407 }
1408
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.