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

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

Version: ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ 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 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 

~ [ 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.