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