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