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