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