urlmon: Use GetBinfInfoEx in GetBindInfo implementation if possible.
[wine/wine-gecko.git] / dlls / urlmon / bindctx.c
blob1a894825291714e58d206353e51e7f47f850c8dc
1 /*
2 * Copyright 2007 Jacek Caban for CodeWeavers
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.
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.
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
19 #include <stdio.h>
21 #include "urlmon_main.h"
22 #include "wine/debug.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
26 static WCHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
28 extern IID IID_IBindStatusCallbackHolder;
30 typedef struct {
31 const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl;
32 const IServiceProviderVtbl *lpServiceProviderVtbl;
33 const IHttpNegotiate2Vtbl *lpHttpNegotiate2Vtbl;
34 const IAuthenticateVtbl *lpAuthenticateVtbl;
36 LONG ref;
38 IBindStatusCallback *callback;
39 IServiceProvider *serv_prov;
40 } BindStatusCallback;
42 #define STATUSCLB(x) ((IBindStatusCallback*) &(x)->lpBindStatusCallbackVtbl)
43 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
44 #define HTTPNEG2(x) ((IHttpNegotiate2*) &(x)->lpHttpNegotiate2Vtbl)
45 #define AUTHENTICATE(x) ((IAuthenticate*) &(x)->lpAuthenticateVtbl)
47 static void *get_callback_iface(BindStatusCallback *This, REFIID riid)
49 void *ret;
50 HRESULT hres;
52 hres = IBindStatusCallback_QueryInterface(This->callback, riid, (void**)&ret);
53 if(FAILED(hres) && This->serv_prov)
54 hres = IServiceProvider_QueryService(This->serv_prov, riid, riid, &ret);
56 return SUCCEEDED(hres) ? ret : NULL;
59 #define STATUSCLB_THIS(iface) DEFINE_THIS(BindStatusCallback, BindStatusCallback, iface)
61 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
62 REFIID riid, void **ppv)
64 BindStatusCallback *This = STATUSCLB_THIS(iface);
66 *ppv = NULL;
68 if(IsEqualGUID(&IID_IUnknown, riid)) {
69 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
70 *ppv = STATUSCLB(This);
71 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
72 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
73 *ppv = STATUSCLB(This);
74 }else if(IsEqualGUID(&IID_IBindStatusCallbackHolder, riid)) {
75 TRACE("(%p)->(IID_IBindStatusCallbackHolder, %p)\n", This, ppv);
76 *ppv = This;
77 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
78 TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
79 *ppv = SERVPROV(This);
80 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
81 TRACE("(%p)->(IID_IHttpNegotiate, %p)\n", This, ppv);
82 *ppv = HTTPNEG2(This);
83 }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
84 TRACE("(%p)->(IID_IHttpNegotiate2, %p)\n", This, ppv);
85 *ppv = HTTPNEG2(This);
86 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
87 TRACE("(%p)->(IID_IAuthenticate, %p)\n", This, ppv);
88 *ppv = AUTHENTICATE(This);
91 if(*ppv) {
92 IBindStatusCallback_AddRef((IUnknown*)*ppv);
93 return S_OK;
96 TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
97 return E_NOINTERFACE;
100 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
102 BindStatusCallback *This = STATUSCLB_THIS(iface);
103 LONG ref = InterlockedIncrement(&This->ref);
105 TRACE("(%p) ref = %d\n", This, ref);
107 return ref;
110 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
112 BindStatusCallback *This = STATUSCLB_THIS(iface);
113 LONG ref = InterlockedDecrement(&This->ref);
115 TRACE("(%p) ref = %d\n", This, ref);
117 if(!ref) {
118 if(This->serv_prov)
119 IServiceProvider_Release(This->serv_prov);
120 IBindStatusCallback_Release(This->callback);
121 heap_free(This);
124 return ref;
127 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
128 DWORD dwReserved, IBinding *pbind)
130 BindStatusCallback *This = STATUSCLB_THIS(iface);
132 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
134 return IBindStatusCallback_OnStartBinding(This->callback, 0xff, pbind);
137 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
139 BindStatusCallback *This = STATUSCLB_THIS(iface);
141 TRACE("(%p)->(%p)\n", This, pnPriority);
143 return IBindStatusCallback_GetPriority(This->callback, pnPriority);
146 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
148 BindStatusCallback *This = STATUSCLB_THIS(iface);
150 TRACE("(%p)->(%d)\n", This, reserved);
152 return IBindStatusCallback_OnLowResource(This->callback, reserved);
155 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
156 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
158 BindStatusCallback *This = STATUSCLB_THIS(iface);
160 TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
161 debugstr_w(szStatusText));
163 return IBindStatusCallback_OnProgress(This->callback, ulProgress,
164 ulProgressMax, ulStatusCode, szStatusText);
167 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface,
168 HRESULT hresult, LPCWSTR szError)
170 BindStatusCallback *This = STATUSCLB_THIS(iface);
172 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
174 return IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
177 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
178 DWORD *grfBINDF, BINDINFO *pbindinfo)
180 BindStatusCallback *This = STATUSCLB_THIS(iface);
181 IBindStatusCallbackEx *bscex;
182 HRESULT hres;
184 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
186 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex);
187 if(SUCCEEDED(hres)) {
188 DWORD bindf2 = 0, reserv = 0;
190 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, &bindf2, &reserv);
191 IBindStatusCallbackEx_Release(bscex);
192 }else {
193 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
196 return hres;
199 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
200 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
202 BindStatusCallback *This = STATUSCLB_THIS(iface);
204 TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
206 return IBindStatusCallback_OnDataAvailable(This->callback, grfBSCF, dwSize, pformatetc, pstgmed);
209 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
210 REFIID riid, IUnknown *punk)
212 BindStatusCallback *This = STATUSCLB_THIS(iface);
214 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
216 return IBindStatusCallback_OnObjectAvailable(This->callback, riid, punk);
219 #undef STATUSCLB_THIS
221 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
222 BindStatusCallback_QueryInterface,
223 BindStatusCallback_AddRef,
224 BindStatusCallback_Release,
225 BindStatusCallback_OnStartBinding,
226 BindStatusCallback_GetPriority,
227 BindStatusCallback_OnLowResource,
228 BindStatusCallback_OnProgress,
229 BindStatusCallback_OnStopBinding,
230 BindStatusCallback_GetBindInfo,
231 BindStatusCallback_OnDataAvailable,
232 BindStatusCallback_OnObjectAvailable
235 #define SERVPROV_THIS(iface) DEFINE_THIS(BindStatusCallback, ServiceProvider, iface)
237 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
238 REFIID riid, void **ppv)
240 BindStatusCallback *This = SERVPROV_THIS(iface);
241 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
244 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
246 BindStatusCallback *This = SERVPROV_THIS(iface);
247 return IBindStatusCallback_AddRef(STATUSCLB(This));
250 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
252 BindStatusCallback *This = SERVPROV_THIS(iface);
253 return IBindStatusCallback_Release(STATUSCLB(This));
256 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
257 REFGUID guidService, REFIID riid, void **ppv)
259 BindStatusCallback *This = SERVPROV_THIS(iface);
260 HRESULT hres;
262 if(IsEqualGUID(&IID_IHttpNegotiate, guidService)) {
263 TRACE("(%p)->(IID_IHttpNegotiate %s %p)\n", This, debugstr_guid(riid), ppv);
264 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
267 if(IsEqualGUID(&IID_IHttpNegotiate2, guidService)) {
268 TRACE("(%p)->(IID_IHttpNegotiate2 %s %p)\n", This, debugstr_guid(riid), ppv);
269 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
272 if(IsEqualGUID(&IID_IAuthenticate, guidService)) {
273 TRACE("(%p)->(IID_IAuthenticate %s %p)\n", This, debugstr_guid(riid), ppv);
274 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
277 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
279 hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv);
280 if(SUCCEEDED(hres))
281 return S_OK;
283 if(This->serv_prov) {
284 hres = IServiceProvider_QueryService(This->serv_prov, guidService, riid, ppv);
285 if(SUCCEEDED(hres))
286 return S_OK;
289 return E_NOINTERFACE;
292 #undef SERVPROV_THIS
294 static const IServiceProviderVtbl BSCServiceProviderVtbl = {
295 BSCServiceProvider_QueryInterface,
296 BSCServiceProvider_AddRef,
297 BSCServiceProvider_Release,
298 BSCServiceProvider_QueryService
301 #define HTTPNEG2_THIS(iface) DEFINE_THIS(BindStatusCallback, HttpNegotiate2, iface)
303 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
304 REFIID riid, void **ppv)
306 BindStatusCallback *This = HTTPNEG2_THIS(iface);
307 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
310 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate2 *iface)
312 BindStatusCallback *This = HTTPNEG2_THIS(iface);
313 return IBindStatusCallback_AddRef(STATUSCLB(This));
316 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate2 *iface)
318 BindStatusCallback *This = HTTPNEG2_THIS(iface);
319 return IBindStatusCallback_Release(STATUSCLB(This));
322 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
323 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
325 BindStatusCallback *This = HTTPNEG2_THIS(iface);
326 IHttpNegotiate *http_negotiate;
327 HRESULT hres = S_OK;
329 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved,
330 pszAdditionalHeaders);
332 *pszAdditionalHeaders = NULL;
334 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
335 if(http_negotiate) {
336 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, szURL, szHeaders,
337 dwReserved, pszAdditionalHeaders);
338 IHttpNegotiate_Release(http_negotiate);
341 return hres;
344 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
345 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders,
346 LPWSTR *pszAdditionalRequestHeaders)
348 BindStatusCallback *This = HTTPNEG2_THIS(iface);
349 LPWSTR additional_headers = NULL;
350 IHttpNegotiate *http_negotiate;
351 HRESULT hres = S_OK;
353 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
354 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
356 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
357 if(http_negotiate) {
358 hres = IHttpNegotiate_OnResponse(http_negotiate, dwResponseCode, szResponseHeaders,
359 szRequestHeaders, &additional_headers);
360 IHttpNegotiate_Release(http_negotiate);
363 if(pszAdditionalRequestHeaders)
364 *pszAdditionalRequestHeaders = additional_headers;
365 else if(additional_headers)
366 CoTaskMemFree(additional_headers);
368 return hres;
371 static HRESULT WINAPI BSCHttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
372 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
374 BindStatusCallback *This = HTTPNEG2_THIS(iface);
375 IHttpNegotiate2 *http_negotiate2;
376 HRESULT hres = E_FAIL;
378 TRACE("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved);
380 http_negotiate2 = get_callback_iface(This, &IID_IHttpNegotiate2);
381 if(http_negotiate2) {
382 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, pbSecurityId,
383 pcbSecurityId, dwReserved);
384 IHttpNegotiate2_Release(http_negotiate2);
387 return hres;
390 #undef HTTPNEG2_THIS
392 static const IHttpNegotiate2Vtbl BSCHttpNegotiateVtbl = {
393 BSCHttpNegotiate_QueryInterface,
394 BSCHttpNegotiate_AddRef,
395 BSCHttpNegotiate_Release,
396 BSCHttpNegotiate_BeginningTransaction,
397 BSCHttpNegotiate_OnResponse,
398 BSCHttpNegotiate_GetRootSecurityId
401 #define AUTHENTICATE_THIS(iface) DEFINE_THIS(BindStatusCallback, Authenticate, iface)
403 static HRESULT WINAPI BSCAuthenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
405 BindStatusCallback *This = AUTHENTICATE_THIS(iface);
406 return IBindStatusCallback_QueryInterface(AUTHENTICATE(This), riid, ppv);
409 static ULONG WINAPI BSCAuthenticate_AddRef(IAuthenticate *iface)
411 BindStatusCallback *This = AUTHENTICATE_THIS(iface);
412 return IBindStatusCallback_AddRef(STATUSCLB(This));
415 static ULONG WINAPI BSCAuthenticate_Release(IAuthenticate *iface)
417 BindStatusCallback *This = AUTHENTICATE_THIS(iface);
418 return IBindStatusCallback_Release(STATUSCLB(This));
421 static HRESULT WINAPI BSCAuthenticate_Authenticate(IAuthenticate *iface,
422 HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword)
424 BindStatusCallback *This = AUTHENTICATE_THIS(iface);
425 FIXME("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword);
426 return E_NOTIMPL;
429 #undef AUTHENTICATE_THIS
431 static const IAuthenticateVtbl BSCAuthenticateVtbl = {
432 BSCAuthenticate_QueryInterface,
433 BSCAuthenticate_AddRef,
434 BSCAuthenticate_Release,
435 BSCAuthenticate_Authenticate
438 static IBindStatusCallback *create_bsc(IBindStatusCallback *bsc)
440 BindStatusCallback *ret = heap_alloc_zero(sizeof(BindStatusCallback));
442 ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
443 ret->lpServiceProviderVtbl = &BSCServiceProviderVtbl;
444 ret->lpHttpNegotiate2Vtbl = &BSCHttpNegotiateVtbl;
445 ret->lpAuthenticateVtbl = &BSCAuthenticateVtbl;
447 ret->ref = 1;
449 IBindStatusCallback_AddRef(bsc);
450 ret->callback = bsc;
452 IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&ret->serv_prov);
454 return STATUSCLB(ret);
457 /***********************************************************************
458 * RegisterBindStatusCallback (urlmon.@)
460 * Register a bind status callback.
462 * PARAMS
463 * pbc [I] Binding context
464 * pbsc [I] Callback to register
465 * ppbscPrevious [O] Destination for previous callback
466 * dwReserved [I] Reserved, must be 0.
468 * RETURNS
469 * Success: S_OK.
470 * Failure: E_INVALIDARG, if any argument is invalid, or
471 * E_OUTOFMEMORY if memory allocation fails.
473 HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc,
474 IBindStatusCallback **ppbscPrevious, DWORD dwReserved)
476 BindStatusCallback *holder;
477 IBindStatusCallback *bsc, *prev = NULL;
478 IUnknown *unk;
479 HRESULT hres;
481 TRACE("(%p %p %p %x)\n", pbc, pbsc, ppbscPrevious, dwReserved);
483 if (!pbc || !pbsc)
484 return E_INVALIDARG;
486 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
487 if(SUCCEEDED(hres)) {
488 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc);
489 if(SUCCEEDED(hres)) {
490 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
491 if(SUCCEEDED(hres)) {
492 prev = holder->callback;
493 IBindStatusCallback_AddRef(prev);
494 IBindStatusCallback_Release(bsc);
495 IBindStatusCallback_Release(STATUSCLB(holder));
496 }else {
497 prev = bsc;
501 IUnknown_Release(unk);
502 IBindCtx_RevokeObjectParam(pbc, BSCBHolder);
505 bsc = create_bsc(pbsc);
506 hres = IBindCtx_RegisterObjectParam(pbc, BSCBHolder, (IUnknown*)bsc);
507 IBindStatusCallback_Release(bsc);
508 if(FAILED(hres)) {
509 if(prev)
510 IBindStatusCallback_Release(prev);
511 return hres;
514 if(ppbscPrevious)
515 *ppbscPrevious = prev;
516 return S_OK;
519 /***********************************************************************
520 * RevokeBindStatusCallback (URLMON.@)
522 * Unregister a bind status callback.
524 * pbc [I] Binding context
525 * pbsc [I] Callback to unregister
527 * RETURNS
528 * Success: S_OK.
529 * Failure: E_INVALIDARG, if any argument is invalid
531 HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc)
533 BindStatusCallback *holder;
534 IBindStatusCallback *callback;
535 IUnknown *unk;
536 BOOL dorevoke = FALSE;
537 HRESULT hres;
539 TRACE("(%p %p)\n", pbc, pbsc);
541 if (!pbc || !pbsc)
542 return E_INVALIDARG;
544 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
545 if(FAILED(hres))
546 return S_OK;
548 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&callback);
549 IUnknown_Release(unk);
550 if(FAILED(hres))
551 return S_OK;
553 hres = IBindStatusCallback_QueryInterface(callback, &IID_IBindStatusCallbackHolder, (void**)&holder);
554 if(SUCCEEDED(hres)) {
555 if(pbsc == holder->callback)
556 dorevoke = TRUE;
557 IBindStatusCallback_Release(STATUSCLB(holder));
558 }else if(pbsc == callback) {
559 dorevoke = TRUE;
561 IBindStatusCallback_Release(callback);
563 if(dorevoke)
564 IBindCtx_RevokeObjectParam(pbc, BSCBHolder);
566 return S_OK;
569 typedef struct {
570 const IBindCtxVtbl *lpBindCtxVtbl;
572 LONG ref;
574 IBindCtx *bindctx;
575 } AsyncBindCtx;
577 #define BINDCTX(x) ((IBindCtx*) &(x)->lpBindCtxVtbl)
579 #define BINDCTX_THIS(iface) DEFINE_THIS(AsyncBindCtx, BindCtx, iface)
581 static HRESULT WINAPI AsyncBindCtx_QueryInterface(IBindCtx *iface, REFIID riid, void **ppv)
583 AsyncBindCtx *This = BINDCTX_THIS(iface);
585 *ppv = NULL;
587 if(IsEqualGUID(riid, &IID_IUnknown)) {
588 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
589 *ppv = BINDCTX(This);
590 }else if(IsEqualGUID(riid, &IID_IBindCtx)) {
591 TRACE("(%p)->(IID_IBindCtx %p)\n", This, ppv);
592 *ppv = BINDCTX(This);
593 }else if(IsEqualGUID(riid, &IID_IAsyncBindCtx)) {
594 TRACE("(%p)->(IID_IAsyncBindCtx %p)\n", This, ppv);
595 *ppv = BINDCTX(This);
598 if(*ppv) {
599 IUnknown_AddRef((IUnknown*)*ppv);
600 return S_OK;
603 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
604 return E_NOINTERFACE;
607 static ULONG WINAPI AsyncBindCtx_AddRef(IBindCtx *iface)
609 AsyncBindCtx *This = BINDCTX_THIS(iface);
610 LONG ref = InterlockedIncrement(&This->ref);
612 TRACE("(%p) ref=%d\n", This, ref);
614 return ref;
617 static ULONG WINAPI AsyncBindCtx_Release(IBindCtx *iface)
619 AsyncBindCtx *This = BINDCTX_THIS(iface);
620 LONG ref = InterlockedDecrement(&This->ref);
622 TRACE("(%p) ref=%d\n", This, ref);
624 if(!ref) {
625 IBindCtx_Release(This->bindctx);
626 heap_free(This);
629 return ref;
632 static HRESULT WINAPI AsyncBindCtx_RegisterObjectBound(IBindCtx *iface, IUnknown *punk)
634 AsyncBindCtx *This = BINDCTX_THIS(iface);
636 TRACE("(%p)->(%p)\n", This, punk);
638 return IBindCtx_RegisterObjectBound(This->bindctx, punk);
641 static HRESULT WINAPI AsyncBindCtx_RevokeObjectBound(IBindCtx *iface, IUnknown *punk)
643 AsyncBindCtx *This = BINDCTX_THIS(iface);
645 TRACE("(%p %p)\n", This, punk);
647 return IBindCtx_RevokeObjectBound(This->bindctx, punk);
650 static HRESULT WINAPI AsyncBindCtx_ReleaseBoundObjects(IBindCtx *iface)
652 AsyncBindCtx *This = BINDCTX_THIS(iface);
654 TRACE("(%p)\n", This);
656 return IBindCtx_ReleaseBoundObjects(This->bindctx);
659 static HRESULT WINAPI AsyncBindCtx_SetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
661 AsyncBindCtx *This = BINDCTX_THIS(iface);
663 TRACE("(%p)->(%p)\n", This, pbindopts);
665 return IBindCtx_SetBindOptions(This->bindctx, pbindopts);
668 static HRESULT WINAPI AsyncBindCtx_GetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
670 AsyncBindCtx *This = BINDCTX_THIS(iface);
672 TRACE("(%p)->(%p)\n", This, pbindopts);
674 return IBindCtx_GetBindOptions(This->bindctx, pbindopts);
677 static HRESULT WINAPI AsyncBindCtx_GetRunningObjectTable(IBindCtx *iface, IRunningObjectTable **pprot)
679 AsyncBindCtx *This = BINDCTX_THIS(iface);
681 TRACE("(%p)->(%p)\n", This, pprot);
683 return IBindCtx_GetRunningObjectTable(This->bindctx, pprot);
686 static HRESULT WINAPI AsyncBindCtx_RegisterObjectParam(IBindCtx *iface, LPOLESTR pszkey, IUnknown *punk)
688 AsyncBindCtx *This = BINDCTX_THIS(iface);
690 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
692 return IBindCtx_RegisterObjectParam(This->bindctx, pszkey, punk);
695 static HRESULT WINAPI AsyncBindCtx_GetObjectParam(IBindCtx* iface, LPOLESTR pszkey, IUnknown **punk)
697 AsyncBindCtx *This = BINDCTX_THIS(iface);
699 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
701 return IBindCtx_GetObjectParam(This->bindctx, pszkey, punk);
704 static HRESULT WINAPI AsyncBindCtx_RevokeObjectParam(IBindCtx *iface, LPOLESTR pszkey)
706 AsyncBindCtx *This = BINDCTX_THIS(iface);
708 TRACE("(%p)->(%s)\n", This, debugstr_w(pszkey));
710 return IBindCtx_RevokeObjectParam(This->bindctx, pszkey);
713 static HRESULT WINAPI AsyncBindCtx_EnumObjectParam(IBindCtx *iface, IEnumString **pszkey)
715 AsyncBindCtx *This = BINDCTX_THIS(iface);
717 TRACE("(%p)->(%p)\n", This, pszkey);
719 return IBindCtx_EnumObjectParam(This->bindctx, pszkey);
722 #undef BINDCTX_THIS
724 static const IBindCtxVtbl AsyncBindCtxVtbl =
726 AsyncBindCtx_QueryInterface,
727 AsyncBindCtx_AddRef,
728 AsyncBindCtx_Release,
729 AsyncBindCtx_RegisterObjectBound,
730 AsyncBindCtx_RevokeObjectBound,
731 AsyncBindCtx_ReleaseBoundObjects,
732 AsyncBindCtx_SetBindOptions,
733 AsyncBindCtx_GetBindOptions,
734 AsyncBindCtx_GetRunningObjectTable,
735 AsyncBindCtx_RegisterObjectParam,
736 AsyncBindCtx_GetObjectParam,
737 AsyncBindCtx_EnumObjectParam,
738 AsyncBindCtx_RevokeObjectParam
741 static HRESULT init_bindctx(IBindCtx *bindctx, DWORD options,
742 IBindStatusCallback *callback, IEnumFORMATETC *format)
744 BIND_OPTS bindopts;
745 HRESULT hres;
747 if(options)
748 FIXME("not supported options %08x\n", options);
749 if(format)
750 FIXME("format is not supported\n");
752 bindopts.cbStruct = sizeof(BIND_OPTS);
753 bindopts.grfFlags = BIND_MAYBOTHERUSER;
754 bindopts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
755 bindopts.dwTickCountDeadline = 0;
757 hres = IBindCtx_SetBindOptions(bindctx, &bindopts);
758 if(FAILED(hres))
759 return hres;
761 if(callback) {
762 hres = RegisterBindStatusCallback(bindctx, callback, NULL, 0);
763 if(FAILED(hres))
764 return hres;
767 return S_OK;
770 /***********************************************************************
771 * CreateAsyncBindCtx (urlmon.@)
773 HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback,
774 IEnumFORMATETC *format, IBindCtx **pbind)
776 IBindCtx *bindctx;
777 HRESULT hres;
779 TRACE("(%08x %p %p %p)\n", reserved, callback, format, pbind);
781 if(!pbind || !callback)
782 return E_INVALIDARG;
784 hres = CreateBindCtx(0, &bindctx);
785 if(FAILED(hres))
786 return hres;
788 hres = init_bindctx(bindctx, 0, callback, format);
789 if(FAILED(hres)) {
790 IBindCtx_Release(bindctx);
791 return hres;
794 *pbind = bindctx;
795 return S_OK;
798 /***********************************************************************
799 * CreateAsyncBindCtxEx (urlmon.@)
801 * Create an asynchronous bind context.
803 HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options,
804 IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx** pbind,
805 DWORD reserved)
807 AsyncBindCtx *ret;
808 IBindCtx *bindctx;
809 HRESULT hres;
811 TRACE("(%p %08x %p %p %p %d)\n", ibind, options, callback, format, pbind, reserved);
813 if(!pbind)
814 return E_INVALIDARG;
816 if(reserved)
817 WARN("reserved=%d\n", reserved);
819 if(ibind) {
820 IBindCtx_AddRef(ibind);
821 bindctx = ibind;
822 }else {
823 hres = CreateBindCtx(0, &bindctx);
824 if(FAILED(hres))
825 return hres;
828 ret = heap_alloc(sizeof(AsyncBindCtx));
830 ret->lpBindCtxVtbl = &AsyncBindCtxVtbl;
831 ret->ref = 1;
832 ret->bindctx = bindctx;
834 hres = init_bindctx(BINDCTX(ret), options, callback, format);
835 if(FAILED(hres)) {
836 IBindCtx_Release(BINDCTX(ret));
837 return hres;
840 *pbind = BINDCTX(ret);
841 return S_OK;