po: Fix a mistake in Dutch translation.
[wine.git] / dlls / urlmon / bindctx.c
blobb2d2776f58134e15fafef201545d7316d3319d89
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 bscb_holderW[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
28 extern IID IID_IBindStatusCallbackHolder;
30 typedef struct {
31 IBindStatusCallbackEx IBindStatusCallbackEx_iface;
32 IServiceProvider IServiceProvider_iface;
33 IHttpNegotiate2 IHttpNegotiate2_iface;
34 IAuthenticate IAuthenticate_iface;
36 LONG ref;
38 IBindStatusCallback *callback;
39 IServiceProvider *serv_prov;
40 } BindStatusCallback;
42 static void *get_callback_iface(BindStatusCallback *This, REFIID riid)
44 void *ret;
45 HRESULT hres;
47 hres = IBindStatusCallback_QueryInterface(This->callback, riid, (void**)&ret);
48 if(FAILED(hres) && This->serv_prov)
49 hres = IServiceProvider_QueryService(This->serv_prov, riid, riid, &ret);
51 return SUCCEEDED(hres) ? ret : NULL;
54 static IBindStatusCallback *bsch_from_bctx(IBindCtx *bctx)
56 IBindStatusCallback *bsc;
57 IUnknown *unk;
58 HRESULT hres;
60 hres = IBindCtx_GetObjectParam(bctx, bscb_holderW, &unk);
61 if(FAILED(hres))
62 return NULL;
64 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc);
65 IUnknown_Release(unk);
66 return SUCCEEDED(hres) ? bsc : NULL;
69 IBindStatusCallback *bsc_from_bctx(IBindCtx *bctx)
71 BindStatusCallback *holder;
72 IBindStatusCallback *bsc;
73 HRESULT hres;
75 bsc = bsch_from_bctx(bctx);
76 if(!bsc)
77 return NULL;
79 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
80 if(FAILED(hres))
81 return bsc;
83 if(holder->callback) {
84 IBindStatusCallback_Release(bsc);
85 bsc = holder->callback;
86 IBindStatusCallback_AddRef(bsc);
89 IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface);
90 return bsc;
93 static inline BindStatusCallback *impl_from_IBindStatusCallbackEx(IBindStatusCallbackEx *iface)
95 return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallbackEx_iface);
98 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallbackEx *iface,
99 REFIID riid, void **ppv)
101 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
103 *ppv = NULL;
105 if(IsEqualGUID(&IID_IUnknown, riid)) {
106 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
107 *ppv = &This->IBindStatusCallbackEx_iface;
108 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
109 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
110 *ppv = &This->IBindStatusCallbackEx_iface;
111 }else if(IsEqualGUID(&IID_IBindStatusCallbackEx, riid)) {
112 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
113 *ppv = &This->IBindStatusCallbackEx_iface;
114 }else if(IsEqualGUID(&IID_IBindStatusCallbackHolder, riid)) {
115 TRACE("(%p)->(IID_IBindStatusCallbackHolder, %p)\n", This, ppv);
116 *ppv = This;
117 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
118 TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
119 *ppv = &This->IServiceProvider_iface;
120 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
121 TRACE("(%p)->(IID_IHttpNegotiate, %p)\n", This, ppv);
122 *ppv = &This->IHttpNegotiate2_iface;
123 }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
124 TRACE("(%p)->(IID_IHttpNegotiate2, %p)\n", This, ppv);
125 *ppv = &This->IHttpNegotiate2_iface;
126 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
127 TRACE("(%p)->(IID_IAuthenticate, %p)\n", This, ppv);
128 *ppv = &This->IAuthenticate_iface;
131 if(*ppv) {
132 IUnknown_AddRef((IUnknown*)*ppv);
133 return S_OK;
136 TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
137 return E_NOINTERFACE;
140 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallbackEx *iface)
142 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
143 LONG ref = InterlockedIncrement(&This->ref);
145 TRACE("(%p) ref = %d\n", This, ref);
147 return ref;
150 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallbackEx *iface)
152 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
153 LONG ref = InterlockedDecrement(&This->ref);
155 TRACE("(%p) ref = %d\n", This, ref);
157 if(!ref) {
158 if(This->serv_prov)
159 IServiceProvider_Release(This->serv_prov);
160 IBindStatusCallback_Release(This->callback);
161 heap_free(This);
164 return ref;
167 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallbackEx *iface,
168 DWORD dwReserved, IBinding *pbind)
170 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
172 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
174 return IBindStatusCallback_OnStartBinding(This->callback, 0xff, pbind);
177 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallbackEx *iface, LONG *pnPriority)
179 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
181 TRACE("(%p)->(%p)\n", This, pnPriority);
183 return IBindStatusCallback_GetPriority(This->callback, pnPriority);
186 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallbackEx *iface, DWORD reserved)
188 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
190 TRACE("(%p)->(%d)\n", This, reserved);
192 return IBindStatusCallback_OnLowResource(This->callback, reserved);
195 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallbackEx *iface, ULONG ulProgress,
196 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
198 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
200 TRACE("%p)->(%u %u %s %s)\n", This, ulProgress, ulProgressMax, debugstr_bindstatus(ulStatusCode),
201 debugstr_w(szStatusText));
203 return IBindStatusCallback_OnProgress(This->callback, ulProgress,
204 ulProgressMax, ulStatusCode, szStatusText);
207 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallbackEx *iface,
208 HRESULT hresult, LPCWSTR szError)
210 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
212 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
214 return IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
217 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallbackEx *iface,
218 DWORD *grfBINDF, BINDINFO *pbindinfo)
220 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
221 IBindStatusCallbackEx *bscex;
222 HRESULT hres;
224 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
226 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex);
227 if(SUCCEEDED(hres)) {
228 DWORD bindf2 = 0, reserv = 0;
230 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, &bindf2, &reserv);
231 IBindStatusCallbackEx_Release(bscex);
232 }else {
233 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
236 return hres;
239 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallbackEx *iface,
240 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
242 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
244 TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
246 return IBindStatusCallback_OnDataAvailable(This->callback, grfBSCF, dwSize, pformatetc, pstgmed);
249 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallbackEx *iface,
250 REFIID riid, IUnknown *punk)
252 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
254 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
256 return IBindStatusCallback_OnObjectAvailable(This->callback, riid, punk);
259 static HRESULT WINAPI BindStatusCallback_GetBindInfoEx(IBindStatusCallbackEx *iface, DWORD *grfBINDF,
260 BINDINFO *pbindinfo, DWORD *grfBINDF2, DWORD *pdwReserved)
262 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
263 IBindStatusCallbackEx *bscex;
264 HRESULT hres;
266 TRACE("(%p)->(%p %p %p %p)\n", This, grfBINDF, pbindinfo, grfBINDF2, pdwReserved);
268 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex);
269 if(SUCCEEDED(hres)) {
270 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, grfBINDF2, pdwReserved);
271 IBindStatusCallbackEx_Release(bscex);
272 }else {
273 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
276 return hres;
279 static const IBindStatusCallbackExVtbl BindStatusCallbackExVtbl = {
280 BindStatusCallback_QueryInterface,
281 BindStatusCallback_AddRef,
282 BindStatusCallback_Release,
283 BindStatusCallback_OnStartBinding,
284 BindStatusCallback_GetPriority,
285 BindStatusCallback_OnLowResource,
286 BindStatusCallback_OnProgress,
287 BindStatusCallback_OnStopBinding,
288 BindStatusCallback_GetBindInfo,
289 BindStatusCallback_OnDataAvailable,
290 BindStatusCallback_OnObjectAvailable,
291 BindStatusCallback_GetBindInfoEx
294 static inline BindStatusCallback *impl_from_IServiceProvider(IServiceProvider *iface)
296 return CONTAINING_RECORD(iface, BindStatusCallback, IServiceProvider_iface);
299 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
300 REFIID riid, void **ppv)
302 BindStatusCallback *This = impl_from_IServiceProvider(iface);
303 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
306 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
308 BindStatusCallback *This = impl_from_IServiceProvider(iface);
309 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
312 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
314 BindStatusCallback *This = impl_from_IServiceProvider(iface);
315 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
318 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
319 REFGUID guidService, REFIID riid, void **ppv)
321 BindStatusCallback *This = impl_from_IServiceProvider(iface);
322 HRESULT hres;
324 if(IsEqualGUID(&IID_IHttpNegotiate, guidService)) {
325 TRACE("(%p)->(IID_IHttpNegotiate %s %p)\n", This, debugstr_guid(riid), ppv);
326 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
329 if(IsEqualGUID(&IID_IHttpNegotiate2, guidService)) {
330 TRACE("(%p)->(IID_IHttpNegotiate2 %s %p)\n", This, debugstr_guid(riid), ppv);
331 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
334 if(IsEqualGUID(&IID_IAuthenticate, guidService)) {
335 TRACE("(%p)->(IID_IAuthenticate %s %p)\n", This, debugstr_guid(riid), ppv);
336 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
339 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
341 hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv);
342 if(SUCCEEDED(hres))
343 return S_OK;
345 if(This->serv_prov) {
346 hres = IServiceProvider_QueryService(This->serv_prov, guidService, riid, ppv);
347 if(SUCCEEDED(hres))
348 return S_OK;
351 return E_NOINTERFACE;
354 static const IServiceProviderVtbl BSCServiceProviderVtbl = {
355 BSCServiceProvider_QueryInterface,
356 BSCServiceProvider_AddRef,
357 BSCServiceProvider_Release,
358 BSCServiceProvider_QueryService
361 static inline BindStatusCallback *impl_from_IHttpNegotiate2(IHttpNegotiate2 *iface)
363 return CONTAINING_RECORD(iface, BindStatusCallback, IHttpNegotiate2_iface);
366 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
367 REFIID riid, void **ppv)
369 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
370 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
373 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate2 *iface)
375 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
376 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
379 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate2 *iface)
381 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
382 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
385 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
386 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
388 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
389 IHttpNegotiate *http_negotiate;
390 HRESULT hres = S_OK;
392 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved,
393 pszAdditionalHeaders);
395 *pszAdditionalHeaders = NULL;
397 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
398 if(http_negotiate) {
399 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, szURL, szHeaders,
400 dwReserved, pszAdditionalHeaders);
401 IHttpNegotiate_Release(http_negotiate);
404 return hres;
407 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
408 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders,
409 LPWSTR *pszAdditionalRequestHeaders)
411 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
412 LPWSTR additional_headers = NULL;
413 IHttpNegotiate *http_negotiate;
414 HRESULT hres = S_OK;
416 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
417 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
419 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
420 if(http_negotiate) {
421 hres = IHttpNegotiate_OnResponse(http_negotiate, dwResponseCode, szResponseHeaders,
422 szRequestHeaders, &additional_headers);
423 IHttpNegotiate_Release(http_negotiate);
426 if(pszAdditionalRequestHeaders)
427 *pszAdditionalRequestHeaders = additional_headers;
428 else if(additional_headers)
429 CoTaskMemFree(additional_headers);
431 return hres;
434 static HRESULT WINAPI BSCHttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
435 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
437 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
438 IHttpNegotiate2 *http_negotiate2;
439 HRESULT hres = E_FAIL;
441 TRACE("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved);
443 http_negotiate2 = get_callback_iface(This, &IID_IHttpNegotiate2);
444 if(http_negotiate2) {
445 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, pbSecurityId,
446 pcbSecurityId, dwReserved);
447 IHttpNegotiate2_Release(http_negotiate2);
450 return hres;
453 static const IHttpNegotiate2Vtbl BSCHttpNegotiateVtbl = {
454 BSCHttpNegotiate_QueryInterface,
455 BSCHttpNegotiate_AddRef,
456 BSCHttpNegotiate_Release,
457 BSCHttpNegotiate_BeginningTransaction,
458 BSCHttpNegotiate_OnResponse,
459 BSCHttpNegotiate_GetRootSecurityId
462 static inline BindStatusCallback *impl_from_IAuthenticate(IAuthenticate *iface)
464 return CONTAINING_RECORD(iface, BindStatusCallback, IAuthenticate_iface);
467 static HRESULT WINAPI BSCAuthenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
469 BindStatusCallback *This = impl_from_IAuthenticate(iface);
470 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
473 static ULONG WINAPI BSCAuthenticate_AddRef(IAuthenticate *iface)
475 BindStatusCallback *This = impl_from_IAuthenticate(iface);
476 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
479 static ULONG WINAPI BSCAuthenticate_Release(IAuthenticate *iface)
481 BindStatusCallback *This = impl_from_IAuthenticate(iface);
482 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
485 static HRESULT WINAPI BSCAuthenticate_Authenticate(IAuthenticate *iface,
486 HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword)
488 BindStatusCallback *This = impl_from_IAuthenticate(iface);
489 FIXME("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword);
490 return E_NOTIMPL;
493 static const IAuthenticateVtbl BSCAuthenticateVtbl = {
494 BSCAuthenticate_QueryInterface,
495 BSCAuthenticate_AddRef,
496 BSCAuthenticate_Release,
497 BSCAuthenticate_Authenticate
500 static void set_callback(BindStatusCallback *This, IBindStatusCallback *bsc)
502 IServiceProvider *serv_prov;
503 HRESULT hres;
505 if(This->callback)
506 IBindStatusCallback_Release(This->callback);
507 if(This->serv_prov)
508 IServiceProvider_Release(This->serv_prov);
510 IBindStatusCallback_AddRef(bsc);
511 This->callback = bsc;
513 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&serv_prov);
514 This->serv_prov = hres == S_OK ? serv_prov : NULL;
517 HRESULT wrap_callback(IBindStatusCallback *bsc, IBindStatusCallback **ret_iface)
519 BindStatusCallback *ret;
521 ret = heap_alloc_zero(sizeof(BindStatusCallback));
522 if(!ret)
523 return E_OUTOFMEMORY;
525 ret->IBindStatusCallbackEx_iface.lpVtbl = &BindStatusCallbackExVtbl;
526 ret->IServiceProvider_iface.lpVtbl = &BSCServiceProviderVtbl;
527 ret->IHttpNegotiate2_iface.lpVtbl = &BSCHttpNegotiateVtbl;
528 ret->IAuthenticate_iface.lpVtbl = &BSCAuthenticateVtbl;
530 ret->ref = 1;
531 set_callback(ret, bsc);
533 *ret_iface = (IBindStatusCallback*)&ret->IBindStatusCallbackEx_iface;
534 return S_OK;
537 /***********************************************************************
538 * RegisterBindStatusCallback (urlmon.@)
540 * Register a bind status callback.
542 * PARAMS
543 * pbc [I] Binding context
544 * pbsc [I] Callback to register
545 * ppbscPrevious [O] Destination for previous callback
546 * dwReserved [I] Reserved, must be 0.
548 * RETURNS
549 * Success: S_OK.
550 * Failure: E_INVALIDARG, if any argument is invalid, or
551 * E_OUTOFMEMORY if memory allocation fails.
553 HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc,
554 IBindStatusCallback **ppbscPrevious, DWORD dwReserved)
556 BindStatusCallback *holder;
557 IBindStatusCallback *bsc, *prev = NULL;
558 HRESULT hres;
560 TRACE("(%p %p %p %x)\n", pbc, pbsc, ppbscPrevious, dwReserved);
562 if (!pbc || !pbsc)
563 return E_INVALIDARG;
565 bsc = bsch_from_bctx(pbc);
566 if(bsc) {
567 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
568 if(SUCCEEDED(hres)) {
569 if(ppbscPrevious) {
570 IBindStatusCallback_AddRef(holder->callback);
571 *ppbscPrevious = holder->callback;
574 set_callback(holder, pbsc);
576 IBindStatusCallback_Release(bsc);
577 IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface);
578 return S_OK;
579 }else {
580 prev = bsc;
583 IBindCtx_RevokeObjectParam(pbc, bscb_holderW);
586 hres = wrap_callback(pbsc, &bsc);
587 if(SUCCEEDED(hres)) {
588 hres = IBindCtx_RegisterObjectParam(pbc, bscb_holderW, (IUnknown*)bsc);
589 IBindStatusCallback_Release(bsc);
591 if(FAILED(hres)) {
592 if(prev)
593 IBindStatusCallback_Release(prev);
594 return hres;
597 if(ppbscPrevious)
598 *ppbscPrevious = prev;
599 return S_OK;
602 /***********************************************************************
603 * RevokeBindStatusCallback (URLMON.@)
605 * Unregister a bind status callback.
607 * pbc [I] Binding context
608 * pbsc [I] Callback to unregister
610 * RETURNS
611 * Success: S_OK.
612 * Failure: E_INVALIDARG, if any argument is invalid
614 HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc)
616 IBindStatusCallback *callback;
618 TRACE("(%p %p)\n", pbc, pbsc);
620 if (!pbc || !pbsc)
621 return E_INVALIDARG;
623 callback = bsc_from_bctx(pbc);
624 if(!callback)
625 return S_OK;
627 if(callback == pbsc)
628 IBindCtx_RevokeObjectParam(pbc, bscb_holderW);
630 IBindStatusCallback_Release(callback);
631 return S_OK;
634 typedef struct {
635 IBindCtx IBindCtx_iface;
637 LONG ref;
639 IBindCtx *bindctx;
640 } AsyncBindCtx;
642 static inline AsyncBindCtx *impl_from_IBindCtx(IBindCtx *iface)
644 return CONTAINING_RECORD(iface, AsyncBindCtx, IBindCtx_iface);
647 static HRESULT WINAPI AsyncBindCtx_QueryInterface(IBindCtx *iface, REFIID riid, void **ppv)
649 AsyncBindCtx *This = impl_from_IBindCtx(iface);
651 *ppv = NULL;
653 if(IsEqualGUID(riid, &IID_IUnknown)) {
654 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
655 *ppv = &This->IBindCtx_iface;
656 }else if(IsEqualGUID(riid, &IID_IBindCtx)) {
657 TRACE("(%p)->(IID_IBindCtx %p)\n", This, ppv);
658 *ppv = &This->IBindCtx_iface;
659 }else if(IsEqualGUID(riid, &IID_IAsyncBindCtx)) {
660 TRACE("(%p)->(IID_IAsyncBindCtx %p)\n", This, ppv);
661 *ppv = &This->IBindCtx_iface;
664 if(*ppv) {
665 IUnknown_AddRef((IUnknown*)*ppv);
666 return S_OK;
669 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
670 return E_NOINTERFACE;
673 static ULONG WINAPI AsyncBindCtx_AddRef(IBindCtx *iface)
675 AsyncBindCtx *This = impl_from_IBindCtx(iface);
676 LONG ref = InterlockedIncrement(&This->ref);
678 TRACE("(%p) ref=%d\n", This, ref);
680 return ref;
683 static ULONG WINAPI AsyncBindCtx_Release(IBindCtx *iface)
685 AsyncBindCtx *This = impl_from_IBindCtx(iface);
686 LONG ref = InterlockedDecrement(&This->ref);
688 TRACE("(%p) ref=%d\n", This, ref);
690 if(!ref) {
691 IBindCtx_Release(This->bindctx);
692 heap_free(This);
695 return ref;
698 static HRESULT WINAPI AsyncBindCtx_RegisterObjectBound(IBindCtx *iface, IUnknown *punk)
700 AsyncBindCtx *This = impl_from_IBindCtx(iface);
702 TRACE("(%p)->(%p)\n", This, punk);
704 return IBindCtx_RegisterObjectBound(This->bindctx, punk);
707 static HRESULT WINAPI AsyncBindCtx_RevokeObjectBound(IBindCtx *iface, IUnknown *punk)
709 AsyncBindCtx *This = impl_from_IBindCtx(iface);
711 TRACE("(%p %p)\n", This, punk);
713 return IBindCtx_RevokeObjectBound(This->bindctx, punk);
716 static HRESULT WINAPI AsyncBindCtx_ReleaseBoundObjects(IBindCtx *iface)
718 AsyncBindCtx *This = impl_from_IBindCtx(iface);
720 TRACE("(%p)\n", This);
722 return IBindCtx_ReleaseBoundObjects(This->bindctx);
725 static HRESULT WINAPI AsyncBindCtx_SetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
727 AsyncBindCtx *This = impl_from_IBindCtx(iface);
729 TRACE("(%p)->(%p)\n", This, pbindopts);
731 return IBindCtx_SetBindOptions(This->bindctx, pbindopts);
734 static HRESULT WINAPI AsyncBindCtx_GetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
736 AsyncBindCtx *This = impl_from_IBindCtx(iface);
738 TRACE("(%p)->(%p)\n", This, pbindopts);
740 return IBindCtx_GetBindOptions(This->bindctx, pbindopts);
743 static HRESULT WINAPI AsyncBindCtx_GetRunningObjectTable(IBindCtx *iface, IRunningObjectTable **pprot)
745 AsyncBindCtx *This = impl_from_IBindCtx(iface);
747 TRACE("(%p)->(%p)\n", This, pprot);
749 return IBindCtx_GetRunningObjectTable(This->bindctx, pprot);
752 static HRESULT WINAPI AsyncBindCtx_RegisterObjectParam(IBindCtx *iface, LPOLESTR pszkey, IUnknown *punk)
754 AsyncBindCtx *This = impl_from_IBindCtx(iface);
756 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
758 return IBindCtx_RegisterObjectParam(This->bindctx, pszkey, punk);
761 static HRESULT WINAPI AsyncBindCtx_GetObjectParam(IBindCtx* iface, LPOLESTR pszkey, IUnknown **punk)
763 AsyncBindCtx *This = impl_from_IBindCtx(iface);
765 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
767 return IBindCtx_GetObjectParam(This->bindctx, pszkey, punk);
770 static HRESULT WINAPI AsyncBindCtx_RevokeObjectParam(IBindCtx *iface, LPOLESTR pszkey)
772 AsyncBindCtx *This = impl_from_IBindCtx(iface);
774 TRACE("(%p)->(%s)\n", This, debugstr_w(pszkey));
776 return IBindCtx_RevokeObjectParam(This->bindctx, pszkey);
779 static HRESULT WINAPI AsyncBindCtx_EnumObjectParam(IBindCtx *iface, IEnumString **pszkey)
781 AsyncBindCtx *This = impl_from_IBindCtx(iface);
783 TRACE("(%p)->(%p)\n", This, pszkey);
785 return IBindCtx_EnumObjectParam(This->bindctx, pszkey);
788 static const IBindCtxVtbl AsyncBindCtxVtbl =
790 AsyncBindCtx_QueryInterface,
791 AsyncBindCtx_AddRef,
792 AsyncBindCtx_Release,
793 AsyncBindCtx_RegisterObjectBound,
794 AsyncBindCtx_RevokeObjectBound,
795 AsyncBindCtx_ReleaseBoundObjects,
796 AsyncBindCtx_SetBindOptions,
797 AsyncBindCtx_GetBindOptions,
798 AsyncBindCtx_GetRunningObjectTable,
799 AsyncBindCtx_RegisterObjectParam,
800 AsyncBindCtx_GetObjectParam,
801 AsyncBindCtx_EnumObjectParam,
802 AsyncBindCtx_RevokeObjectParam
805 static HRESULT init_bindctx(IBindCtx *bindctx, DWORD options,
806 IBindStatusCallback *callback, IEnumFORMATETC *format)
808 BIND_OPTS bindopts;
809 HRESULT hres;
811 if(options)
812 FIXME("not supported options %08x\n", options);
813 if(format)
814 FIXME("format is not supported\n");
816 bindopts.cbStruct = sizeof(BIND_OPTS);
817 bindopts.grfFlags = BIND_MAYBOTHERUSER;
818 bindopts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
819 bindopts.dwTickCountDeadline = 0;
821 hres = IBindCtx_SetBindOptions(bindctx, &bindopts);
822 if(FAILED(hres))
823 return hres;
825 if(callback) {
826 hres = RegisterBindStatusCallback(bindctx, callback, NULL, 0);
827 if(FAILED(hres))
828 return hres;
831 return S_OK;
834 /***********************************************************************
835 * CreateAsyncBindCtx (urlmon.@)
837 HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback,
838 IEnumFORMATETC *format, IBindCtx **pbind)
840 IBindCtx *bindctx;
841 HRESULT hres;
843 TRACE("(%08x %p %p %p)\n", reserved, callback, format, pbind);
845 if(!pbind || !callback)
846 return E_INVALIDARG;
848 hres = CreateBindCtx(0, &bindctx);
849 if(FAILED(hres))
850 return hres;
852 hres = init_bindctx(bindctx, 0, callback, format);
853 if(FAILED(hres)) {
854 IBindCtx_Release(bindctx);
855 return hres;
858 *pbind = bindctx;
859 return S_OK;
862 /***********************************************************************
863 * CreateAsyncBindCtxEx (urlmon.@)
865 * Create an asynchronous bind context.
867 HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options,
868 IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx** pbind,
869 DWORD reserved)
871 AsyncBindCtx *ret;
872 IBindCtx *bindctx;
873 HRESULT hres;
875 TRACE("(%p %08x %p %p %p %d)\n", ibind, options, callback, format, pbind, reserved);
877 if(!pbind)
878 return E_INVALIDARG;
880 if(reserved)
881 WARN("reserved=%d\n", reserved);
883 if(ibind) {
884 IBindCtx_AddRef(ibind);
885 bindctx = ibind;
886 }else {
887 hres = CreateBindCtx(0, &bindctx);
888 if(FAILED(hres))
889 return hres;
892 ret = heap_alloc(sizeof(AsyncBindCtx));
894 ret->IBindCtx_iface.lpVtbl = &AsyncBindCtxVtbl;
895 ret->ref = 1;
896 ret->bindctx = bindctx;
898 hres = init_bindctx(&ret->IBindCtx_iface, options, callback, format);
899 if(FAILED(hres)) {
900 IBindCtx_Release(&ret->IBindCtx_iface);
901 return hres;
904 *pbind = &ret->IBindCtx_iface;
905 return S_OK;