1 /* 2 * Copyright 2007 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 <stdio.h> 20 21 #include "urlmon_main.h" 22 #include "wine/debug.h" 23 24 WINE_DEFAULT_DEBUG_CHANNEL(urlmon); 25 26 static WCHAR bscb_holderW[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 }; 27 28 extern IID IID_IBindStatusCallbackHolder; 29 30 typedef struct { 31 IBindStatusCallbackEx IBindStatusCallbackEx_iface; 32 IInternetBindInfo IInternetBindInfo_iface; 33 IServiceProvider IServiceProvider_iface; 34 IHttpNegotiate2 IHttpNegotiate2_iface; 35 IAuthenticate IAuthenticate_iface; 36 37 LONG ref; 38 39 IBindStatusCallback *callback; 40 IServiceProvider *serv_prov; 41 } BindStatusCallback; 42 43 static void *get_callback_iface(BindStatusCallback *This, REFIID riid) 44 { 45 void *ret; 46 HRESULT hres; 47 48 hres = IBindStatusCallback_QueryInterface(This->callback, riid, &ret); 49 if(FAILED(hres) && This->serv_prov) 50 hres = IServiceProvider_QueryService(This->serv_prov, riid, riid, &ret); 51 52 return SUCCEEDED(hres) ? ret : NULL; 53 } 54 55 static IBindStatusCallback *bsch_from_bctx(IBindCtx *bctx) 56 { 57 IBindStatusCallback *bsc; 58 IUnknown *unk; 59 HRESULT hres; 60 61 hres = IBindCtx_GetObjectParam(bctx, bscb_holderW, &unk); 62 if(FAILED(hres)) 63 return NULL; 64 65 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc); 66 IUnknown_Release(unk); 67 return SUCCEEDED(hres) ? bsc : NULL; 68 } 69 70 IBindStatusCallback *bsc_from_bctx(IBindCtx *bctx) 71 { 72 BindStatusCallback *holder; 73 IBindStatusCallback *bsc; 74 HRESULT hres; 75 76 bsc = bsch_from_bctx(bctx); 77 if(!bsc) 78 return NULL; 79 80 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder); 81 if(FAILED(hres)) 82 return bsc; 83 84 if(holder->callback) { 85 IBindStatusCallback_Release(bsc); 86 bsc = holder->callback; 87 IBindStatusCallback_AddRef(bsc); 88 } 89 90 IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface); 91 return bsc; 92 } 93 94 static inline BindStatusCallback *impl_from_IBindStatusCallbackEx(IBindStatusCallbackEx *iface) 95 { 96 return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallbackEx_iface); 97 } 98 99 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallbackEx *iface, 100 REFIID riid, void **ppv) 101 { 102 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 103 104 *ppv = NULL; 105 106 if(IsEqualGUID(&IID_IUnknown, riid)) { 107 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv); 108 *ppv = &This->IBindStatusCallbackEx_iface; 109 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) { 110 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv); 111 *ppv = &This->IBindStatusCallbackEx_iface; 112 }else if(IsEqualGUID(&IID_IBindStatusCallbackEx, riid)) { 113 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv); 114 *ppv = &This->IBindStatusCallbackEx_iface; 115 }else if(IsEqualGUID(&IID_IBindStatusCallbackHolder, riid)) { 116 TRACE("(%p)->(IID_IBindStatusCallbackHolder, %p)\n", This, ppv); 117 *ppv = This; 118 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { 119 TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv); 120 *ppv = &This->IServiceProvider_iface; 121 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) { 122 TRACE("(%p)->(IID_IHttpNegotiate, %p)\n", This, ppv); 123 *ppv = &This->IHttpNegotiate2_iface; 124 }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) { 125 TRACE("(%p)->(IID_IHttpNegotiate2, %p)\n", This, ppv); 126 *ppv = &This->IHttpNegotiate2_iface; 127 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) { 128 TRACE("(%p)->(IID_IAuthenticate, %p)\n", This, ppv); 129 *ppv = &This->IAuthenticate_iface; 130 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) { 131 TRACE("(%p)->(IID_IInternetBindInfo, %p)\n", This, ppv); 132 *ppv = &This->IInternetBindInfo_iface; 133 } 134 135 if(*ppv) { 136 IUnknown_AddRef((IUnknown*)*ppv); 137 return S_OK; 138 } 139 140 TRACE("Unsupported riid = %s\n", debugstr_guid(riid)); 141 return E_NOINTERFACE; 142 } 143 144 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallbackEx *iface) 145 { 146 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 147 LONG ref = InterlockedIncrement(&This->ref); 148 149 TRACE("(%p) ref = %d\n", This, ref); 150 151 return ref; 152 } 153 154 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallbackEx *iface) 155 { 156 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 157 LONG ref = InterlockedDecrement(&This->ref); 158 159 TRACE("(%p) ref = %d\n", This, ref); 160 161 if(!ref) { 162 if(This->serv_prov) 163 IServiceProvider_Release(This->serv_prov); 164 IBindStatusCallback_Release(This->callback); 165 heap_free(This); 166 } 167 168 return ref; 169 } 170 171 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallbackEx *iface, 172 DWORD dwReserved, IBinding *pbind) 173 { 174 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 175 176 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind); 177 178 return IBindStatusCallback_OnStartBinding(This->callback, 0xff, pbind); 179 } 180 181 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallbackEx *iface, LONG *pnPriority) 182 { 183 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 184 185 TRACE("(%p)->(%p)\n", This, pnPriority); 186 187 return IBindStatusCallback_GetPriority(This->callback, pnPriority); 188 } 189 190 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallbackEx *iface, DWORD reserved) 191 { 192 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 193 194 TRACE("(%p)->(%d)\n", This, reserved); 195 196 return IBindStatusCallback_OnLowResource(This->callback, reserved); 197 } 198 199 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallbackEx *iface, ULONG ulProgress, 200 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) 201 { 202 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 203 204 TRACE("%p)->(%u %u %s %s)\n", This, ulProgress, ulProgressMax, debugstr_bindstatus(ulStatusCode), 205 debugstr_w(szStatusText)); 206 207 return IBindStatusCallback_OnProgress(This->callback, ulProgress, 208 ulProgressMax, ulStatusCode, szStatusText); 209 } 210 211 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallbackEx *iface, 212 HRESULT hresult, LPCWSTR szError) 213 { 214 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 215 216 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError)); 217 218 return IBindStatusCallback_OnStopBinding(This->callback, hresult, szError); 219 } 220 221 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallbackEx *iface, 222 DWORD *grfBINDF, BINDINFO *pbindinfo) 223 { 224 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 225 IBindStatusCallbackEx *bscex; 226 HRESULT hres; 227 228 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); 229 230 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex); 231 if(SUCCEEDED(hres)) { 232 DWORD bindf2 = 0, reserv = 0; 233 234 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, &bindf2, &reserv); 235 IBindStatusCallbackEx_Release(bscex); 236 }else { 237 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo); 238 } 239 240 return hres; 241 } 242 243 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallbackEx *iface, 244 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) 245 { 246 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 247 248 TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed); 249 250 return IBindStatusCallback_OnDataAvailable(This->callback, grfBSCF, dwSize, pformatetc, pstgmed); 251 } 252 253 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallbackEx *iface, 254 REFIID riid, IUnknown *punk) 255 { 256 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 257 258 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk); 259 260 return IBindStatusCallback_OnObjectAvailable(This->callback, riid, punk); 261 } 262 263 static HRESULT WINAPI BindStatusCallback_GetBindInfoEx(IBindStatusCallbackEx *iface, DWORD *grfBINDF, 264 BINDINFO *pbindinfo, DWORD *grfBINDF2, DWORD *pdwReserved) 265 { 266 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface); 267 IBindStatusCallbackEx *bscex; 268 HRESULT hres; 269 270 TRACE("(%p)->(%p %p %p %p)\n", This, grfBINDF, pbindinfo, grfBINDF2, pdwReserved); 271 272 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex); 273 if(SUCCEEDED(hres)) { 274 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, grfBINDF2, pdwReserved); 275 IBindStatusCallbackEx_Release(bscex); 276 }else { 277 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo); 278 } 279 280 return hres; 281 } 282 283 static const IBindStatusCallbackExVtbl BindStatusCallbackExVtbl = { 284 BindStatusCallback_QueryInterface, 285 BindStatusCallback_AddRef, 286 BindStatusCallback_Release, 287 BindStatusCallback_OnStartBinding, 288 BindStatusCallback_GetPriority, 289 BindStatusCallback_OnLowResource, 290 BindStatusCallback_OnProgress, 291 BindStatusCallback_OnStopBinding, 292 BindStatusCallback_GetBindInfo, 293 BindStatusCallback_OnDataAvailable, 294 BindStatusCallback_OnObjectAvailable, 295 BindStatusCallback_GetBindInfoEx 296 }; 297 298 static inline BindStatusCallback *impl_from_IServiceProvider(IServiceProvider *iface) 299 { 300 return CONTAINING_RECORD(iface, BindStatusCallback, IServiceProvider_iface); 301 } 302 303 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface, 304 REFIID riid, void **ppv) 305 { 306 BindStatusCallback *This = impl_from_IServiceProvider(iface); 307 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv); 308 } 309 310 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface) 311 { 312 BindStatusCallback *This = impl_from_IServiceProvider(iface); 313 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface); 314 } 315 316 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface) 317 { 318 BindStatusCallback *This = impl_from_IServiceProvider(iface); 319 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface); 320 } 321 322 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface, 323 REFGUID guidService, REFIID riid, void **ppv) 324 { 325 BindStatusCallback *This = impl_from_IServiceProvider(iface); 326 HRESULT hres; 327 328 if(IsEqualGUID(&IID_IHttpNegotiate, guidService)) { 329 TRACE("(%p)->(IID_IHttpNegotiate %s %p)\n", This, debugstr_guid(riid), ppv); 330 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv); 331 } 332 333 if(IsEqualGUID(&IID_IHttpNegotiate2, guidService)) { 334 TRACE("(%p)->(IID_IHttpNegotiate2 %s %p)\n", This, debugstr_guid(riid), ppv); 335 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv); 336 } 337 338 if(IsEqualGUID(&IID_IAuthenticate, guidService)) { 339 TRACE("(%p)->(IID_IAuthenticate %s %p)\n", This, debugstr_guid(riid), ppv); 340 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv); 341 } 342 343 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); 344 345 hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv); 346 if(SUCCEEDED(hres)) 347 return S_OK; 348 349 if(This->serv_prov) { 350 hres = IServiceProvider_QueryService(This->serv_prov, guidService, riid, ppv); 351 if(SUCCEEDED(hres)) 352 return S_OK; 353 } 354 355 return E_NOINTERFACE; 356 } 357 358 static const IServiceProviderVtbl BSCServiceProviderVtbl = { 359 BSCServiceProvider_QueryInterface, 360 BSCServiceProvider_AddRef, 361 BSCServiceProvider_Release, 362 BSCServiceProvider_QueryService 363 }; 364 365 static inline BindStatusCallback *impl_from_IHttpNegotiate2(IHttpNegotiate2 *iface) 366 { 367 return CONTAINING_RECORD(iface, BindStatusCallback, IHttpNegotiate2_iface); 368 } 369 370 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, 371 REFIID riid, void **ppv) 372 { 373 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface); 374 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv); 375 } 376 377 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate2 *iface) 378 { 379 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface); 380 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface); 381 } 382 383 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate2 *iface) 384 { 385 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface); 386 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface); 387 } 388 389 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, 390 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) 391 { 392 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface); 393 IHttpNegotiate *http_negotiate; 394 HRESULT hres = S_OK; 395 396 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved, 397 pszAdditionalHeaders); 398 399 *pszAdditionalHeaders = NULL; 400 401 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate); 402 if(http_negotiate) { 403 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, szURL, szHeaders, 404 dwReserved, pszAdditionalHeaders); 405 IHttpNegotiate_Release(http_negotiate); 406 } 407 408 return hres; 409 } 410 411 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode, 412 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, 413 LPWSTR *pszAdditionalRequestHeaders) 414 { 415 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface); 416 LPWSTR additional_headers = NULL; 417 IHttpNegotiate *http_negotiate; 418 HRESULT hres = S_OK; 419 420 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders), 421 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders); 422 423 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate); 424 if(http_negotiate) { 425 hres = IHttpNegotiate_OnResponse(http_negotiate, dwResponseCode, szResponseHeaders, 426 szRequestHeaders, &additional_headers); 427 IHttpNegotiate_Release(http_negotiate); 428 } 429 430 if(pszAdditionalRequestHeaders) 431 *pszAdditionalRequestHeaders = additional_headers; 432 else 433 CoTaskMemFree(additional_headers); 434 435 return hres; 436 } 437 438 static HRESULT WINAPI BSCHttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface, 439 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved) 440 { 441 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface); 442 IHttpNegotiate2 *http_negotiate2; 443 HRESULT hres = E_FAIL; 444 445 TRACE("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved); 446 447 http_negotiate2 = get_callback_iface(This, &IID_IHttpNegotiate2); 448 if(http_negotiate2) { 449 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, pbSecurityId, 450 pcbSecurityId, dwReserved); 451 IHttpNegotiate2_Release(http_negotiate2); 452 } 453 454 return hres; 455 } 456 457 static const IHttpNegotiate2Vtbl BSCHttpNegotiateVtbl = { 458 BSCHttpNegotiate_QueryInterface, 459 BSCHttpNegotiate_AddRef, 460 BSCHttpNegotiate_Release, 461 BSCHttpNegotiate_BeginningTransaction, 462 BSCHttpNegotiate_OnResponse, 463 BSCHttpNegotiate_GetRootSecurityId 464 }; 465 466 static inline BindStatusCallback *impl_from_IAuthenticate(IAuthenticate *iface) 467 { 468 return CONTAINING_RECORD(iface, BindStatusCallback, IAuthenticate_iface); 469 } 470 471 static HRESULT WINAPI BSCAuthenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv) 472 { 473 BindStatusCallback *This = impl_from_IAuthenticate(iface); 474 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv); 475 } 476 477 static ULONG WINAPI BSCAuthenticate_AddRef(IAuthenticate *iface) 478 { 479 BindStatusCallback *This = impl_from_IAuthenticate(iface); 480 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface); 481 } 482 483 static ULONG WINAPI BSCAuthenticate_Release(IAuthenticate *iface) 484 { 485 BindStatusCallback *This = impl_from_IAuthenticate(iface); 486 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface); 487 } 488 489 static HRESULT WINAPI BSCAuthenticate_Authenticate(IAuthenticate *iface, 490 HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword) 491 { 492 BindStatusCallback *This = impl_from_IAuthenticate(iface); 493 FIXME("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword); 494 return E_NOTIMPL; 495 } 496 497 static const IAuthenticateVtbl BSCAuthenticateVtbl = { 498 BSCAuthenticate_QueryInterface, 499 BSCAuthenticate_AddRef, 500 BSCAuthenticate_Release, 501 BSCAuthenticate_Authenticate 502 }; 503 504 static inline BindStatusCallback *impl_from_IInternetBindInfo(IInternetBindInfo *iface) 505 { 506 return CONTAINING_RECORD(iface, BindStatusCallback, IInternetBindInfo_iface); 507 } 508 509 static HRESULT WINAPI BSCInternetBindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv) 510 { 511 BindStatusCallback *This = impl_from_IInternetBindInfo(iface); 512 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv); 513 } 514 515 static ULONG WINAPI BSCInternetBindInfo_AddRef(IInternetBindInfo *iface) 516 { 517 BindStatusCallback *This = impl_from_IInternetBindInfo(iface); 518 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface); 519 } 520 521 static ULONG WINAPI BSCInternetBindInfo_Release(IInternetBindInfo *iface) 522 { 523 BindStatusCallback *This = impl_from_IInternetBindInfo(iface); 524 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface); 525 } 526 527 static HRESULT WINAPI BSCInternetBindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *bindf, BINDINFO *bindinfo) 528 { 529 BindStatusCallback *This = impl_from_IInternetBindInfo(iface); 530 FIXME("(%p)->(%p %p)\n", This, bindf, bindinfo); 531 return E_NOTIMPL; 532 } 533 534 static HRESULT WINAPI BSCInternetBindInfo_GetBindString(IInternetBindInfo *iface, ULONG string_type, 535 WCHAR **strs, ULONG cnt, ULONG *fetched) 536 { 537 BindStatusCallback *This = impl_from_IInternetBindInfo(iface); 538 IInternetBindInfo *bind_info; 539 HRESULT hres; 540 541 TRACE("(%p)->(%d %p %d %p)\n", This, string_type, strs, cnt, fetched); 542 543 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IInternetBindInfo, (void**)&bind_info); 544 if(FAILED(hres)) 545 return hres; 546 547 hres = IInternetBindInfo_GetBindString(bind_info, string_type, strs, cnt, fetched); 548 549 IInternetBindInfo_Release(bind_info); 550 return hres; 551 } 552 553 static IInternetBindInfoVtbl BSCInternetBindInfoVtbl = { 554 BSCInternetBindInfo_QueryInterface, 555 BSCInternetBindInfo_AddRef, 556 BSCInternetBindInfo_Release, 557 BSCInternetBindInfo_GetBindInfo, 558 BSCInternetBindInfo_GetBindString 559 }; 560 561 static void set_callback(BindStatusCallback *This, IBindStatusCallback *bsc) 562 { 563 IServiceProvider *serv_prov; 564 HRESULT hres; 565 566 if(This->callback) 567 IBindStatusCallback_Release(This->callback); 568 if(This->serv_prov) 569 IServiceProvider_Release(This->serv_prov); 570 571 IBindStatusCallback_AddRef(bsc); 572 This->callback = bsc; 573 574 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&serv_prov); 575 This->serv_prov = hres == S_OK ? serv_prov : NULL; 576 } 577 578 HRESULT wrap_callback(IBindStatusCallback *bsc, IBindStatusCallback **ret_iface) 579 { 580 BindStatusCallback *ret; 581 582 ret = heap_alloc_zero(sizeof(BindStatusCallback)); 583 if(!ret) 584 return E_OUTOFMEMORY; 585 586 ret->IBindStatusCallbackEx_iface.lpVtbl = &BindStatusCallbackExVtbl; 587 ret->IInternetBindInfo_iface.lpVtbl = &BSCInternetBindInfoVtbl; 588 ret->IServiceProvider_iface.lpVtbl = &BSCServiceProviderVtbl; 589 ret->IHttpNegotiate2_iface.lpVtbl = &BSCHttpNegotiateVtbl; 590 ret->IAuthenticate_iface.lpVtbl = &BSCAuthenticateVtbl; 591 592 ret->ref = 1; 593 set_callback(ret, bsc); 594 595 *ret_iface = (IBindStatusCallback*)&ret->IBindStatusCallbackEx_iface; 596 return S_OK; 597 } 598 599 /*********************************************************************** 600 * RegisterBindStatusCallback (urlmon.@) 601 * 602 * Register a bind status callback. 603 * 604 * PARAMS 605 * pbc [I] Binding context 606 * pbsc [I] Callback to register 607 * ppbscPrevious [O] Destination for previous callback 608 * dwReserved [I] Reserved, must be 0. 609 * 610 * RETURNS 611 * Success: S_OK. 612 * Failure: E_INVALIDARG, if any argument is invalid, or 613 * E_OUTOFMEMORY if memory allocation fails. 614 */ 615 HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc, 616 IBindStatusCallback **ppbscPrevious, DWORD dwReserved) 617 { 618 BindStatusCallback *holder; 619 IBindStatusCallback *bsc, *prev = NULL; 620 HRESULT hres; 621 622 TRACE("(%p %p %p %x)\n", pbc, pbsc, ppbscPrevious, dwReserved); 623 624 if (!pbc || !pbsc) 625 return E_INVALIDARG; 626 627 bsc = bsch_from_bctx(pbc); 628 if(bsc) { 629 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder); 630 if(SUCCEEDED(hres)) { 631 if(ppbscPrevious) { 632 IBindStatusCallback_AddRef(holder->callback); 633 *ppbscPrevious = holder->callback; 634 } 635 636 set_callback(holder, pbsc); 637 638 IBindStatusCallback_Release(bsc); 639 IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface); 640 return S_OK; 641 }else { 642 prev = bsc; 643 } 644 645 IBindCtx_RevokeObjectParam(pbc, bscb_holderW); 646 } 647 648 hres = wrap_callback(pbsc, &bsc); 649 if(SUCCEEDED(hres)) { 650 hres = IBindCtx_RegisterObjectParam(pbc, bscb_holderW, (IUnknown*)bsc); 651 IBindStatusCallback_Release(bsc); 652 } 653 if(FAILED(hres)) { 654 if(prev) 655 IBindStatusCallback_Release(prev); 656 return hres; 657 } 658 659 if(ppbscPrevious) 660 *ppbscPrevious = prev; 661 return S_OK; 662 } 663 664 /*********************************************************************** 665 * RevokeBindStatusCallback (URLMON.@) 666 * 667 * Unregister a bind status callback. 668 * 669 * pbc [I] Binding context 670 * pbsc [I] Callback to unregister 671 * 672 * RETURNS 673 * Success: S_OK. 674 * Failure: E_INVALIDARG, if any argument is invalid 675 */ 676 HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc) 677 { 678 IBindStatusCallback *callback; 679 680 TRACE("(%p %p)\n", pbc, pbsc); 681 682 if (!pbc || !pbsc) 683 return E_INVALIDARG; 684 685 callback = bsc_from_bctx(pbc); 686 if(!callback) 687 return S_OK; 688 689 if(callback == pbsc) 690 IBindCtx_RevokeObjectParam(pbc, bscb_holderW); 691 692 IBindStatusCallback_Release(callback); 693 return S_OK; 694 } 695 696 typedef struct { 697 IBindCtx IBindCtx_iface; 698 699 LONG ref; 700 701 IBindCtx *bindctx; 702 } AsyncBindCtx; 703 704 static inline AsyncBindCtx *impl_from_IBindCtx(IBindCtx *iface) 705 { 706 return CONTAINING_RECORD(iface, AsyncBindCtx, IBindCtx_iface); 707 } 708 709 static HRESULT WINAPI AsyncBindCtx_QueryInterface(IBindCtx *iface, REFIID riid, void **ppv) 710 { 711 AsyncBindCtx *This = impl_from_IBindCtx(iface); 712 713 *ppv = NULL; 714 715 if(IsEqualGUID(riid, &IID_IUnknown)) { 716 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 717 *ppv = &This->IBindCtx_iface; 718 }else if(IsEqualGUID(riid, &IID_IBindCtx)) { 719 TRACE("(%p)->(IID_IBindCtx %p)\n", This, ppv); 720 *ppv = &This->IBindCtx_iface; 721 }else if(IsEqualGUID(riid, &IID_IAsyncBindCtx)) { 722 TRACE("(%p)->(IID_IAsyncBindCtx %p)\n", This, ppv); 723 *ppv = &This->IBindCtx_iface; 724 } 725 726 if(*ppv) { 727 IUnknown_AddRef((IUnknown*)*ppv); 728 return S_OK; 729 } 730 731 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 732 return E_NOINTERFACE; 733 } 734 735 static ULONG WINAPI AsyncBindCtx_AddRef(IBindCtx *iface) 736 { 737 AsyncBindCtx *This = impl_from_IBindCtx(iface); 738 LONG ref = InterlockedIncrement(&This->ref); 739 740 TRACE("(%p) ref=%d\n", This, ref); 741 742 return ref; 743 } 744 745 static ULONG WINAPI AsyncBindCtx_Release(IBindCtx *iface) 746 { 747 AsyncBindCtx *This = impl_from_IBindCtx(iface); 748 LONG ref = InterlockedDecrement(&This->ref); 749 750 TRACE("(%p) ref=%d\n", This, ref); 751 752 if(!ref) { 753 IBindCtx_Release(This->bindctx); 754 heap_free(This); 755 } 756 757 return ref; 758 } 759 760 static HRESULT WINAPI AsyncBindCtx_RegisterObjectBound(IBindCtx *iface, IUnknown *punk) 761 { 762 AsyncBindCtx *This = impl_from_IBindCtx(iface); 763 764 TRACE("(%p)->(%p)\n", This, punk); 765 766 return IBindCtx_RegisterObjectBound(This->bindctx, punk); 767 } 768 769 static HRESULT WINAPI AsyncBindCtx_RevokeObjectBound(IBindCtx *iface, IUnknown *punk) 770 { 771 AsyncBindCtx *This = impl_from_IBindCtx(iface); 772 773 TRACE("(%p %p)\n", This, punk); 774 775 return IBindCtx_RevokeObjectBound(This->bindctx, punk); 776 } 777 778 static HRESULT WINAPI AsyncBindCtx_ReleaseBoundObjects(IBindCtx *iface) 779 { 780 AsyncBindCtx *This = impl_from_IBindCtx(iface); 781 782 TRACE("(%p)\n", This); 783 784 return IBindCtx_ReleaseBoundObjects(This->bindctx); 785 } 786 787 static HRESULT WINAPI AsyncBindCtx_SetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts) 788 { 789 AsyncBindCtx *This = impl_from_IBindCtx(iface); 790 791 TRACE("(%p)->(%p)\n", This, pbindopts); 792 793 return IBindCtx_SetBindOptions(This->bindctx, pbindopts); 794 } 795 796 static HRESULT WINAPI AsyncBindCtx_GetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts) 797 { 798 AsyncBindCtx *This = impl_from_IBindCtx(iface); 799 800 TRACE("(%p)->(%p)\n", This, pbindopts); 801 802 return IBindCtx_GetBindOptions(This->bindctx, pbindopts); 803 } 804 805 static HRESULT WINAPI AsyncBindCtx_GetRunningObjectTable(IBindCtx *iface, IRunningObjectTable **pprot) 806 { 807 AsyncBindCtx *This = impl_from_IBindCtx(iface); 808 809 TRACE("(%p)->(%p)\n", This, pprot); 810 811 return IBindCtx_GetRunningObjectTable(This->bindctx, pprot); 812 } 813 814 static HRESULT WINAPI AsyncBindCtx_RegisterObjectParam(IBindCtx *iface, LPOLESTR pszkey, IUnknown *punk) 815 { 816 AsyncBindCtx *This = impl_from_IBindCtx(iface); 817 818 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk); 819 820 return IBindCtx_RegisterObjectParam(This->bindctx, pszkey, punk); 821 } 822 823 static HRESULT WINAPI AsyncBindCtx_GetObjectParam(IBindCtx* iface, LPOLESTR pszkey, IUnknown **punk) 824 { 825 AsyncBindCtx *This = impl_from_IBindCtx(iface); 826 827 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk); 828 829 return IBindCtx_GetObjectParam(This->bindctx, pszkey, punk); 830 } 831 832 static HRESULT WINAPI AsyncBindCtx_RevokeObjectParam(IBindCtx *iface, LPOLESTR pszkey) 833 { 834 AsyncBindCtx *This = impl_from_IBindCtx(iface); 835 836 TRACE("(%p)->(%s)\n", This, debugstr_w(pszkey)); 837 838 return IBindCtx_RevokeObjectParam(This->bindctx, pszkey); 839 } 840 841 static HRESULT WINAPI AsyncBindCtx_EnumObjectParam(IBindCtx *iface, IEnumString **pszkey) 842 { 843 AsyncBindCtx *This = impl_from_IBindCtx(iface); 844 845 TRACE("(%p)->(%p)\n", This, pszkey); 846 847 return IBindCtx_EnumObjectParam(This->bindctx, pszkey); 848 } 849 850 static const IBindCtxVtbl AsyncBindCtxVtbl = 851 { 852 AsyncBindCtx_QueryInterface, 853 AsyncBindCtx_AddRef, 854 AsyncBindCtx_Release, 855 AsyncBindCtx_RegisterObjectBound, 856 AsyncBindCtx_RevokeObjectBound, 857 AsyncBindCtx_ReleaseBoundObjects, 858 AsyncBindCtx_SetBindOptions, 859 AsyncBindCtx_GetBindOptions, 860 AsyncBindCtx_GetRunningObjectTable, 861 AsyncBindCtx_RegisterObjectParam, 862 AsyncBindCtx_GetObjectParam, 863 AsyncBindCtx_EnumObjectParam, 864 AsyncBindCtx_RevokeObjectParam 865 }; 866 867 static HRESULT init_bindctx(IBindCtx *bindctx, DWORD options, 868 IBindStatusCallback *callback, IEnumFORMATETC *format) 869 { 870 BIND_OPTS bindopts; 871 HRESULT hres; 872 873 if(options) 874 FIXME("not supported options %08x\n", options); 875 if(format) 876 FIXME("format is not supported\n"); 877 878 bindopts.cbStruct = sizeof(BIND_OPTS); 879 bindopts.grfFlags = BIND_MAYBOTHERUSER; 880 bindopts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE; 881 bindopts.dwTickCountDeadline = 0; 882 883 hres = IBindCtx_SetBindOptions(bindctx, &bindopts); 884 if(FAILED(hres)) 885 return hres; 886 887 if(callback) { 888 hres = RegisterBindStatusCallback(bindctx, callback, NULL, 0); 889 if(FAILED(hres)) 890 return hres; 891 } 892 893 return S_OK; 894 } 895 896 /*********************************************************************** 897 * CreateAsyncBindCtx (urlmon.@) 898 */ 899 HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback, 900 IEnumFORMATETC *format, IBindCtx **pbind) 901 { 902 IBindCtx *bindctx; 903 HRESULT hres; 904 905 TRACE("(%08x %p %p %p)\n", reserved, callback, format, pbind); 906 907 if(!pbind || !callback) 908 return E_INVALIDARG; 909 910 hres = CreateBindCtx(0, &bindctx); 911 if(FAILED(hres)) 912 return hres; 913 914 hres = init_bindctx(bindctx, 0, callback, format); 915 if(FAILED(hres)) { 916 IBindCtx_Release(bindctx); 917 return hres; 918 } 919 920 *pbind = bindctx; 921 return S_OK; 922 } 923 924 /*********************************************************************** 925 * CreateAsyncBindCtxEx (urlmon.@) 926 * 927 * Create an asynchronous bind context. 928 */ 929 HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options, 930 IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx** pbind, 931 DWORD reserved) 932 { 933 AsyncBindCtx *ret; 934 IBindCtx *bindctx; 935 HRESULT hres; 936 937 TRACE("(%p %08x %p %p %p %d)\n", ibind, options, callback, format, pbind, reserved); 938 939 if(!pbind) 940 return E_INVALIDARG; 941 942 if(reserved) 943 WARN("reserved=%d\n", reserved); 944 945 if(ibind) { 946 IBindCtx_AddRef(ibind); 947 bindctx = ibind; 948 }else { 949 hres = CreateBindCtx(0, &bindctx); 950 if(FAILED(hres)) 951 return hres; 952 } 953 954 ret = heap_alloc(sizeof(AsyncBindCtx)); 955 956 ret->IBindCtx_iface.lpVtbl = &AsyncBindCtxVtbl; 957 ret->ref = 1; 958 ret->bindctx = bindctx; 959 960 hres = init_bindctx(&ret->IBindCtx_iface, options, callback, format); 961 if(FAILED(hres)) { 962 IBindCtx_Release(&ret->IBindCtx_iface); 963 return hres; 964 } 965 966 *pbind = &ret->IBindCtx_iface; 967 return S_OK; 968 } 969