wininet: Support the Cache-Control max-age directive for setting url cache entry...
[wine/testsucceed.git] / dlls / urlmon / bindctx.c
blob1af7fa7a1294b7383a6f3e1b0825c416535ffb6c
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 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 inline BindStatusCallback *impl_from_IBindStatusCallbackEx(IBindStatusCallbackEx *iface)
56 return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallbackEx_iface);
59 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallbackEx *iface,
60 REFIID riid, void **ppv)
62 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
64 *ppv = NULL;
66 if(IsEqualGUID(&IID_IUnknown, riid)) {
67 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
68 *ppv = &This->IBindStatusCallbackEx_iface;
69 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
70 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
71 *ppv = &This->IBindStatusCallbackEx_iface;
72 }else if(IsEqualGUID(&IID_IBindStatusCallbackEx, riid)) {
73 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
74 *ppv = &This->IBindStatusCallbackEx_iface;
75 }else if(IsEqualGUID(&IID_IBindStatusCallbackHolder, riid)) {
76 TRACE("(%p)->(IID_IBindStatusCallbackHolder, %p)\n", This, ppv);
77 *ppv = This;
78 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
79 TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
80 *ppv = &This->IServiceProvider_iface;
81 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
82 TRACE("(%p)->(IID_IHttpNegotiate, %p)\n", This, ppv);
83 *ppv = &This->IHttpNegotiate2_iface;
84 }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
85 TRACE("(%p)->(IID_IHttpNegotiate2, %p)\n", This, ppv);
86 *ppv = &This->IHttpNegotiate2_iface;
87 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
88 TRACE("(%p)->(IID_IAuthenticate, %p)\n", This, ppv);
89 *ppv = &This->IAuthenticate_iface;
92 if(*ppv) {
93 IBindStatusCallback_AddRef((IUnknown*)*ppv);
94 return S_OK;
97 TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
98 return E_NOINTERFACE;
101 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallbackEx *iface)
103 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
104 LONG ref = InterlockedIncrement(&This->ref);
106 TRACE("(%p) ref = %d\n", This, ref);
108 return ref;
111 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallbackEx *iface)
113 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
114 LONG ref = InterlockedDecrement(&This->ref);
116 TRACE("(%p) ref = %d\n", This, ref);
118 if(!ref) {
119 if(This->serv_prov)
120 IServiceProvider_Release(This->serv_prov);
121 IBindStatusCallback_Release(This->callback);
122 heap_free(This);
125 return ref;
128 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallbackEx *iface,
129 DWORD dwReserved, IBinding *pbind)
131 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
133 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
135 return IBindStatusCallback_OnStartBinding(This->callback, 0xff, pbind);
138 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallbackEx *iface, LONG *pnPriority)
140 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
142 TRACE("(%p)->(%p)\n", This, pnPriority);
144 return IBindStatusCallback_GetPriority(This->callback, pnPriority);
147 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallbackEx *iface, DWORD reserved)
149 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
151 TRACE("(%p)->(%d)\n", This, reserved);
153 return IBindStatusCallback_OnLowResource(This->callback, reserved);
156 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallbackEx *iface, ULONG ulProgress,
157 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
159 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
161 TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
162 debugstr_w(szStatusText));
164 return IBindStatusCallback_OnProgress(This->callback, ulProgress,
165 ulProgressMax, ulStatusCode, szStatusText);
168 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallbackEx *iface,
169 HRESULT hresult, LPCWSTR szError)
171 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
173 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
175 return IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
178 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallbackEx *iface,
179 DWORD *grfBINDF, BINDINFO *pbindinfo)
181 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
182 IBindStatusCallbackEx *bscex;
183 HRESULT hres;
185 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
187 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex);
188 if(SUCCEEDED(hres)) {
189 DWORD bindf2 = 0, reserv = 0;
191 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, &bindf2, &reserv);
192 IBindStatusCallbackEx_Release(bscex);
193 }else {
194 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
197 return hres;
200 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallbackEx *iface,
201 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
203 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
205 TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
207 return IBindStatusCallback_OnDataAvailable(This->callback, grfBSCF, dwSize, pformatetc, pstgmed);
210 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallbackEx *iface,
211 REFIID riid, IUnknown *punk)
213 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
215 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
217 return IBindStatusCallback_OnObjectAvailable(This->callback, riid, punk);
220 static HRESULT WINAPI BindStatusCallback_GetBindInfoEx(IBindStatusCallbackEx *iface, DWORD *grfBINDF,
221 BINDINFO *pbindinfo, DWORD *grfBINDF2, DWORD *pdwReserved)
223 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
224 IBindStatusCallbackEx *bscex;
225 HRESULT hres;
227 TRACE("(%p)->(%p %p %p %p)\n", This, grfBINDF, pbindinfo, grfBINDF2, pdwReserved);
229 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex);
230 if(SUCCEEDED(hres)) {
231 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, grfBINDF2, pdwReserved);
232 IBindStatusCallbackEx_Release(bscex);
233 }else {
234 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
237 return hres;
240 static const IBindStatusCallbackExVtbl BindStatusCallbackExVtbl = {
241 BindStatusCallback_QueryInterface,
242 BindStatusCallback_AddRef,
243 BindStatusCallback_Release,
244 BindStatusCallback_OnStartBinding,
245 BindStatusCallback_GetPriority,
246 BindStatusCallback_OnLowResource,
247 BindStatusCallback_OnProgress,
248 BindStatusCallback_OnStopBinding,
249 BindStatusCallback_GetBindInfo,
250 BindStatusCallback_OnDataAvailable,
251 BindStatusCallback_OnObjectAvailable,
252 BindStatusCallback_GetBindInfoEx
255 static inline BindStatusCallback *impl_from_IServiceProvider(IServiceProvider *iface)
257 return CONTAINING_RECORD(iface, BindStatusCallback, IServiceProvider_iface);
260 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
261 REFIID riid, void **ppv)
263 BindStatusCallback *This = impl_from_IServiceProvider(iface);
264 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
267 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
269 BindStatusCallback *This = impl_from_IServiceProvider(iface);
270 return IBindStatusCallback_AddRef(&This->IBindStatusCallbackEx_iface);
273 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
275 BindStatusCallback *This = impl_from_IServiceProvider(iface);
276 return IBindStatusCallback_Release(&This->IBindStatusCallbackEx_iface);
279 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
280 REFGUID guidService, REFIID riid, void **ppv)
282 BindStatusCallback *This = impl_from_IServiceProvider(iface);
283 HRESULT hres;
285 if(IsEqualGUID(&IID_IHttpNegotiate, guidService)) {
286 TRACE("(%p)->(IID_IHttpNegotiate %s %p)\n", This, debugstr_guid(riid), ppv);
287 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
290 if(IsEqualGUID(&IID_IHttpNegotiate2, guidService)) {
291 TRACE("(%p)->(IID_IHttpNegotiate2 %s %p)\n", This, debugstr_guid(riid), ppv);
292 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
295 if(IsEqualGUID(&IID_IAuthenticate, guidService)) {
296 TRACE("(%p)->(IID_IAuthenticate %s %p)\n", This, debugstr_guid(riid), ppv);
297 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
300 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
302 hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv);
303 if(SUCCEEDED(hres))
304 return S_OK;
306 if(This->serv_prov) {
307 hres = IServiceProvider_QueryService(This->serv_prov, guidService, riid, ppv);
308 if(SUCCEEDED(hres))
309 return S_OK;
312 return E_NOINTERFACE;
315 static const IServiceProviderVtbl BSCServiceProviderVtbl = {
316 BSCServiceProvider_QueryInterface,
317 BSCServiceProvider_AddRef,
318 BSCServiceProvider_Release,
319 BSCServiceProvider_QueryService
322 static inline BindStatusCallback *impl_from_IHttpNegotiate2(IHttpNegotiate2 *iface)
324 return CONTAINING_RECORD(iface, BindStatusCallback, IHttpNegotiate2_iface);
327 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
328 REFIID riid, void **ppv)
330 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
331 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
334 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate2 *iface)
336 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
337 return IBindStatusCallback_AddRef(&This->IBindStatusCallbackEx_iface);
340 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate2 *iface)
342 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
343 return IBindStatusCallback_Release(&This->IBindStatusCallbackEx_iface);
346 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
347 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
349 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
350 IHttpNegotiate *http_negotiate;
351 HRESULT hres = S_OK;
353 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved,
354 pszAdditionalHeaders);
356 *pszAdditionalHeaders = NULL;
358 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
359 if(http_negotiate) {
360 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, szURL, szHeaders,
361 dwReserved, pszAdditionalHeaders);
362 IHttpNegotiate_Release(http_negotiate);
365 return hres;
368 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
369 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders,
370 LPWSTR *pszAdditionalRequestHeaders)
372 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
373 LPWSTR additional_headers = NULL;
374 IHttpNegotiate *http_negotiate;
375 HRESULT hres = S_OK;
377 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
378 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
380 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
381 if(http_negotiate) {
382 hres = IHttpNegotiate_OnResponse(http_negotiate, dwResponseCode, szResponseHeaders,
383 szRequestHeaders, &additional_headers);
384 IHttpNegotiate_Release(http_negotiate);
387 if(pszAdditionalRequestHeaders)
388 *pszAdditionalRequestHeaders = additional_headers;
389 else if(additional_headers)
390 CoTaskMemFree(additional_headers);
392 return hres;
395 static HRESULT WINAPI BSCHttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
396 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
398 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
399 IHttpNegotiate2 *http_negotiate2;
400 HRESULT hres = E_FAIL;
402 TRACE("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved);
404 http_negotiate2 = get_callback_iface(This, &IID_IHttpNegotiate2);
405 if(http_negotiate2) {
406 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, pbSecurityId,
407 pcbSecurityId, dwReserved);
408 IHttpNegotiate2_Release(http_negotiate2);
411 return hres;
414 static const IHttpNegotiate2Vtbl BSCHttpNegotiateVtbl = {
415 BSCHttpNegotiate_QueryInterface,
416 BSCHttpNegotiate_AddRef,
417 BSCHttpNegotiate_Release,
418 BSCHttpNegotiate_BeginningTransaction,
419 BSCHttpNegotiate_OnResponse,
420 BSCHttpNegotiate_GetRootSecurityId
423 static inline BindStatusCallback *impl_from_IAuthenticate(IAuthenticate *iface)
425 return CONTAINING_RECORD(iface, BindStatusCallback, IAuthenticate_iface);
428 static HRESULT WINAPI BSCAuthenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
430 BindStatusCallback *This = impl_from_IAuthenticate(iface);
431 return IBindStatusCallback_QueryInterface(&This->IAuthenticate_iface, riid, ppv);
434 static ULONG WINAPI BSCAuthenticate_AddRef(IAuthenticate *iface)
436 BindStatusCallback *This = impl_from_IAuthenticate(iface);
437 return IBindStatusCallback_AddRef(&This->IBindStatusCallbackEx_iface);
440 static ULONG WINAPI BSCAuthenticate_Release(IAuthenticate *iface)
442 BindStatusCallback *This = impl_from_IAuthenticate(iface);
443 return IBindStatusCallback_Release(&This->IBindStatusCallbackEx_iface);
446 static HRESULT WINAPI BSCAuthenticate_Authenticate(IAuthenticate *iface,
447 HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword)
449 BindStatusCallback *This = impl_from_IAuthenticate(iface);
450 FIXME("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword);
451 return E_NOTIMPL;
454 static const IAuthenticateVtbl BSCAuthenticateVtbl = {
455 BSCAuthenticate_QueryInterface,
456 BSCAuthenticate_AddRef,
457 BSCAuthenticate_Release,
458 BSCAuthenticate_Authenticate
461 static void set_callback(BindStatusCallback *This, IBindStatusCallback *bsc)
463 IServiceProvider *serv_prov;
464 HRESULT hres;
466 if(This->callback)
467 IBindStatusCallback_Release(This->callback);
468 if(This->serv_prov)
469 IServiceProvider_Release(This->serv_prov);
471 IBindStatusCallback_AddRef(bsc);
472 This->callback = bsc;
474 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&serv_prov);
475 This->serv_prov = hres == S_OK ? serv_prov : NULL;
478 HRESULT wrap_callback(IBindStatusCallback *bsc, IBindStatusCallback **ret_iface)
480 BindStatusCallback *ret;
482 ret = heap_alloc_zero(sizeof(BindStatusCallback));
483 if(!ret)
484 return E_OUTOFMEMORY;
486 ret->IBindStatusCallbackEx_iface.lpVtbl = &BindStatusCallbackExVtbl;
487 ret->IServiceProvider_iface.lpVtbl = &BSCServiceProviderVtbl;
488 ret->IHttpNegotiate2_iface.lpVtbl = &BSCHttpNegotiateVtbl;
489 ret->IAuthenticate_iface.lpVtbl = &BSCAuthenticateVtbl;
491 ret->ref = 1;
492 set_callback(ret, bsc);
494 *ret_iface = (IBindStatusCallback*)&ret->IBindStatusCallbackEx_iface;
495 return S_OK;
498 /***********************************************************************
499 * RegisterBindStatusCallback (urlmon.@)
501 * Register a bind status callback.
503 * PARAMS
504 * pbc [I] Binding context
505 * pbsc [I] Callback to register
506 * ppbscPrevious [O] Destination for previous callback
507 * dwReserved [I] Reserved, must be 0.
509 * RETURNS
510 * Success: S_OK.
511 * Failure: E_INVALIDARG, if any argument is invalid, or
512 * E_OUTOFMEMORY if memory allocation fails.
514 HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc,
515 IBindStatusCallback **ppbscPrevious, DWORD dwReserved)
517 BindStatusCallback *holder;
518 IBindStatusCallback *bsc, *prev = NULL;
519 IUnknown *unk;
520 HRESULT hres;
522 TRACE("(%p %p %p %x)\n", pbc, pbsc, ppbscPrevious, dwReserved);
524 if (!pbc || !pbsc)
525 return E_INVALIDARG;
527 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
528 if(SUCCEEDED(hres)) {
529 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc);
530 IUnknown_Release(unk);
531 if(SUCCEEDED(hres)) {
532 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
533 if(SUCCEEDED(hres)) {
534 if(ppbscPrevious) {
535 IBindStatusCallback_AddRef(holder->callback);
536 *ppbscPrevious = holder->callback;
539 set_callback(holder, pbsc);
541 IBindStatusCallback_Release(bsc);
542 IBindStatusCallback_Release(&holder->IBindStatusCallbackEx_iface);
543 return S_OK;
544 }else {
545 prev = bsc;
549 IBindCtx_RevokeObjectParam(pbc, BSCBHolder);
552 hres = wrap_callback(pbsc, &bsc);
553 if(SUCCEEDED(hres)) {
554 hres = IBindCtx_RegisterObjectParam(pbc, BSCBHolder, (IUnknown*)bsc);
555 IBindStatusCallback_Release(bsc);
557 if(FAILED(hres)) {
558 if(prev)
559 IBindStatusCallback_Release(prev);
560 return hres;
563 if(ppbscPrevious)
564 *ppbscPrevious = prev;
565 return S_OK;
568 /***********************************************************************
569 * RevokeBindStatusCallback (URLMON.@)
571 * Unregister a bind status callback.
573 * pbc [I] Binding context
574 * pbsc [I] Callback to unregister
576 * RETURNS
577 * Success: S_OK.
578 * Failure: E_INVALIDARG, if any argument is invalid
580 HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc)
582 BindStatusCallback *holder;
583 IBindStatusCallback *callback;
584 IUnknown *unk;
585 BOOL dorevoke = FALSE;
586 HRESULT hres;
588 TRACE("(%p %p)\n", pbc, pbsc);
590 if (!pbc || !pbsc)
591 return E_INVALIDARG;
593 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
594 if(FAILED(hres))
595 return S_OK;
597 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&callback);
598 IUnknown_Release(unk);
599 if(FAILED(hres))
600 return S_OK;
602 hres = IBindStatusCallback_QueryInterface(callback, &IID_IBindStatusCallbackHolder, (void**)&holder);
603 if(SUCCEEDED(hres)) {
604 if(pbsc == holder->callback)
605 dorevoke = TRUE;
606 IBindStatusCallback_Release(&holder->IBindStatusCallbackEx_iface);
607 }else if(pbsc == callback) {
608 dorevoke = TRUE;
610 IBindStatusCallback_Release(callback);
612 if(dorevoke)
613 IBindCtx_RevokeObjectParam(pbc, BSCBHolder);
615 return S_OK;
618 typedef struct {
619 IBindCtx IBindCtx_iface;
621 LONG ref;
623 IBindCtx *bindctx;
624 } AsyncBindCtx;
626 static inline AsyncBindCtx *impl_from_IBindCtx(IBindCtx *iface)
628 return CONTAINING_RECORD(iface, AsyncBindCtx, IBindCtx_iface);
631 static HRESULT WINAPI AsyncBindCtx_QueryInterface(IBindCtx *iface, REFIID riid, void **ppv)
633 AsyncBindCtx *This = impl_from_IBindCtx(iface);
635 *ppv = NULL;
637 if(IsEqualGUID(riid, &IID_IUnknown)) {
638 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
639 *ppv = &This->IBindCtx_iface;
640 }else if(IsEqualGUID(riid, &IID_IBindCtx)) {
641 TRACE("(%p)->(IID_IBindCtx %p)\n", This, ppv);
642 *ppv = &This->IBindCtx_iface;
643 }else if(IsEqualGUID(riid, &IID_IAsyncBindCtx)) {
644 TRACE("(%p)->(IID_IAsyncBindCtx %p)\n", This, ppv);
645 *ppv = &This->IBindCtx_iface;
648 if(*ppv) {
649 IUnknown_AddRef((IUnknown*)*ppv);
650 return S_OK;
653 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
654 return E_NOINTERFACE;
657 static ULONG WINAPI AsyncBindCtx_AddRef(IBindCtx *iface)
659 AsyncBindCtx *This = impl_from_IBindCtx(iface);
660 LONG ref = InterlockedIncrement(&This->ref);
662 TRACE("(%p) ref=%d\n", This, ref);
664 return ref;
667 static ULONG WINAPI AsyncBindCtx_Release(IBindCtx *iface)
669 AsyncBindCtx *This = impl_from_IBindCtx(iface);
670 LONG ref = InterlockedDecrement(&This->ref);
672 TRACE("(%p) ref=%d\n", This, ref);
674 if(!ref) {
675 IBindCtx_Release(This->bindctx);
676 heap_free(This);
679 return ref;
682 static HRESULT WINAPI AsyncBindCtx_RegisterObjectBound(IBindCtx *iface, IUnknown *punk)
684 AsyncBindCtx *This = impl_from_IBindCtx(iface);
686 TRACE("(%p)->(%p)\n", This, punk);
688 return IBindCtx_RegisterObjectBound(This->bindctx, punk);
691 static HRESULT WINAPI AsyncBindCtx_RevokeObjectBound(IBindCtx *iface, IUnknown *punk)
693 AsyncBindCtx *This = impl_from_IBindCtx(iface);
695 TRACE("(%p %p)\n", This, punk);
697 return IBindCtx_RevokeObjectBound(This->bindctx, punk);
700 static HRESULT WINAPI AsyncBindCtx_ReleaseBoundObjects(IBindCtx *iface)
702 AsyncBindCtx *This = impl_from_IBindCtx(iface);
704 TRACE("(%p)\n", This);
706 return IBindCtx_ReleaseBoundObjects(This->bindctx);
709 static HRESULT WINAPI AsyncBindCtx_SetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
711 AsyncBindCtx *This = impl_from_IBindCtx(iface);
713 TRACE("(%p)->(%p)\n", This, pbindopts);
715 return IBindCtx_SetBindOptions(This->bindctx, pbindopts);
718 static HRESULT WINAPI AsyncBindCtx_GetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
720 AsyncBindCtx *This = impl_from_IBindCtx(iface);
722 TRACE("(%p)->(%p)\n", This, pbindopts);
724 return IBindCtx_GetBindOptions(This->bindctx, pbindopts);
727 static HRESULT WINAPI AsyncBindCtx_GetRunningObjectTable(IBindCtx *iface, IRunningObjectTable **pprot)
729 AsyncBindCtx *This = impl_from_IBindCtx(iface);
731 TRACE("(%p)->(%p)\n", This, pprot);
733 return IBindCtx_GetRunningObjectTable(This->bindctx, pprot);
736 static HRESULT WINAPI AsyncBindCtx_RegisterObjectParam(IBindCtx *iface, LPOLESTR pszkey, IUnknown *punk)
738 AsyncBindCtx *This = impl_from_IBindCtx(iface);
740 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
742 return IBindCtx_RegisterObjectParam(This->bindctx, pszkey, punk);
745 static HRESULT WINAPI AsyncBindCtx_GetObjectParam(IBindCtx* iface, LPOLESTR pszkey, IUnknown **punk)
747 AsyncBindCtx *This = impl_from_IBindCtx(iface);
749 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
751 return IBindCtx_GetObjectParam(This->bindctx, pszkey, punk);
754 static HRESULT WINAPI AsyncBindCtx_RevokeObjectParam(IBindCtx *iface, LPOLESTR pszkey)
756 AsyncBindCtx *This = impl_from_IBindCtx(iface);
758 TRACE("(%p)->(%s)\n", This, debugstr_w(pszkey));
760 return IBindCtx_RevokeObjectParam(This->bindctx, pszkey);
763 static HRESULT WINAPI AsyncBindCtx_EnumObjectParam(IBindCtx *iface, IEnumString **pszkey)
765 AsyncBindCtx *This = impl_from_IBindCtx(iface);
767 TRACE("(%p)->(%p)\n", This, pszkey);
769 return IBindCtx_EnumObjectParam(This->bindctx, pszkey);
772 static const IBindCtxVtbl AsyncBindCtxVtbl =
774 AsyncBindCtx_QueryInterface,
775 AsyncBindCtx_AddRef,
776 AsyncBindCtx_Release,
777 AsyncBindCtx_RegisterObjectBound,
778 AsyncBindCtx_RevokeObjectBound,
779 AsyncBindCtx_ReleaseBoundObjects,
780 AsyncBindCtx_SetBindOptions,
781 AsyncBindCtx_GetBindOptions,
782 AsyncBindCtx_GetRunningObjectTable,
783 AsyncBindCtx_RegisterObjectParam,
784 AsyncBindCtx_GetObjectParam,
785 AsyncBindCtx_EnumObjectParam,
786 AsyncBindCtx_RevokeObjectParam
789 static HRESULT init_bindctx(IBindCtx *bindctx, DWORD options,
790 IBindStatusCallback *callback, IEnumFORMATETC *format)
792 BIND_OPTS bindopts;
793 HRESULT hres;
795 if(options)
796 FIXME("not supported options %08x\n", options);
797 if(format)
798 FIXME("format is not supported\n");
800 bindopts.cbStruct = sizeof(BIND_OPTS);
801 bindopts.grfFlags = BIND_MAYBOTHERUSER;
802 bindopts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
803 bindopts.dwTickCountDeadline = 0;
805 hres = IBindCtx_SetBindOptions(bindctx, &bindopts);
806 if(FAILED(hres))
807 return hres;
809 if(callback) {
810 hres = RegisterBindStatusCallback(bindctx, callback, NULL, 0);
811 if(FAILED(hres))
812 return hres;
815 return S_OK;
818 /***********************************************************************
819 * CreateAsyncBindCtx (urlmon.@)
821 HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback,
822 IEnumFORMATETC *format, IBindCtx **pbind)
824 IBindCtx *bindctx;
825 HRESULT hres;
827 TRACE("(%08x %p %p %p)\n", reserved, callback, format, pbind);
829 if(!pbind || !callback)
830 return E_INVALIDARG;
832 hres = CreateBindCtx(0, &bindctx);
833 if(FAILED(hres))
834 return hres;
836 hres = init_bindctx(bindctx, 0, callback, format);
837 if(FAILED(hres)) {
838 IBindCtx_Release(bindctx);
839 return hres;
842 *pbind = bindctx;
843 return S_OK;
846 /***********************************************************************
847 * CreateAsyncBindCtxEx (urlmon.@)
849 * Create an asynchronous bind context.
851 HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options,
852 IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx** pbind,
853 DWORD reserved)
855 AsyncBindCtx *ret;
856 IBindCtx *bindctx;
857 HRESULT hres;
859 TRACE("(%p %08x %p %p %p %d)\n", ibind, options, callback, format, pbind, reserved);
861 if(!pbind)
862 return E_INVALIDARG;
864 if(reserved)
865 WARN("reserved=%d\n", reserved);
867 if(ibind) {
868 IBindCtx_AddRef(ibind);
869 bindctx = ibind;
870 }else {
871 hres = CreateBindCtx(0, &bindctx);
872 if(FAILED(hres))
873 return hres;
876 ret = heap_alloc(sizeof(AsyncBindCtx));
878 ret->IBindCtx_iface.lpVtbl = &AsyncBindCtxVtbl;
879 ret->ref = 1;
880 ret->bindctx = bindctx;
882 hres = init_bindctx(&ret->IBindCtx_iface, options, callback, format);
883 if(FAILED(hres)) {
884 IBindCtx_Release(&ret->IBindCtx_iface);
885 return hres;
888 *pbind = &ret->IBindCtx_iface;
889 return S_OK;