~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/urlmon/bindprot.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.