widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / urlmon / bindctx.c
blob406232467c3898aa23f1aa1fa89c2b463bc8291e
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[] = L"_BSCB_Holder_";
28 extern IID IID_IBindStatusCallbackHolder;
30 typedef struct {
31 IBindStatusCallbackEx IBindStatusCallbackEx_iface;
32 IInternetBindInfo IInternetBindInfo_iface;
33 IServiceProvider IServiceProvider_iface;
34 IHttpNegotiate2 IHttpNegotiate2_iface;
35 IAuthenticate IAuthenticate_iface;
37 LONG ref;
39 IBindStatusCallback *callback;
40 IServiceProvider *serv_prov;
41 } BindStatusCallback;
43 static void *get_callback_iface(BindStatusCallback *This, REFIID riid)
45 void *ret;
46 HRESULT hres;
48 hres = IBindStatusCallback_QueryInterface(This->callback, riid, &ret);
49 if(FAILED(hres) && This->serv_prov)
50 hres = IServiceProvider_QueryService(This->serv_prov, riid, riid, &ret);
52 return SUCCEEDED(hres) ? ret : NULL;
55 static IBindStatusCallback *bsch_from_bctx(IBindCtx *bctx)
57 IBindStatusCallback *bsc;
58 IUnknown *unk;
59 HRESULT hres;
61 hres = IBindCtx_GetObjectParam(bctx, bscb_holderW, &unk);
62 if(FAILED(hres))
63 return NULL;
65 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc);
66 IUnknown_Release(unk);
67 return SUCCEEDED(hres) ? bsc : NULL;
70 IBindStatusCallback *bsc_from_bctx(IBindCtx *bctx)
72 BindStatusCallback *holder;
73 IBindStatusCallback *bsc;
74 HRESULT hres;
76 bsc = bsch_from_bctx(bctx);
77 if(!bsc)
78 return NULL;
80 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
81 if(FAILED(hres))
82 return bsc;
84 if(holder->callback) {
85 IBindStatusCallback_Release(bsc);
86 bsc = holder->callback;
87 IBindStatusCallback_AddRef(bsc);
90 IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface);
91 return bsc;
94 static inline BindStatusCallback *impl_from_IBindStatusCallbackEx(IBindStatusCallbackEx *iface)
96 return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallbackEx_iface);
99 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallbackEx *iface,
100 REFIID riid, void **ppv)
102 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
104 *ppv = NULL;
106 if(IsEqualGUID(&IID_IUnknown, riid)) {
107 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
108 *ppv = &This->IBindStatusCallbackEx_iface;
109 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
110 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
111 *ppv = &This->IBindStatusCallbackEx_iface;
112 }else if(IsEqualGUID(&IID_IBindStatusCallbackEx, riid)) {
113 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
114 *ppv = &This->IBindStatusCallbackEx_iface;
115 }else if(IsEqualGUID(&IID_IBindStatusCallbackHolder, riid)) {
116 TRACE("(%p)->(IID_IBindStatusCallbackHolder, %p)\n", This, ppv);
117 *ppv = This;
118 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
119 TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
120 *ppv = &This->IServiceProvider_iface;
121 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
122 TRACE("(%p)->(IID_IHttpNegotiate, %p)\n", This, ppv);
123 *ppv = &This->IHttpNegotiate2_iface;
124 }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
125 TRACE("(%p)->(IID_IHttpNegotiate2, %p)\n", This, ppv);
126 *ppv = &This->IHttpNegotiate2_iface;
127 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
128 TRACE("(%p)->(IID_IAuthenticate, %p)\n", This, ppv);
129 *ppv = &This->IAuthenticate_iface;
130 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
131 TRACE("(%p)->(IID_IInternetBindInfo, %p)\n", This, ppv);
132 *ppv = &This->IInternetBindInfo_iface;
135 if(*ppv) {
136 IUnknown_AddRef((IUnknown*)*ppv);
137 return S_OK;
140 TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
141 return E_NOINTERFACE;
144 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallbackEx *iface)
146 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
147 LONG ref = InterlockedIncrement(&This->ref);
149 TRACE("(%p) ref = %d\n", This, ref);
151 return ref;
154 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallbackEx *iface)
156 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
157 LONG ref = InterlockedDecrement(&This->ref);
159 TRACE("(%p) ref = %d\n", This, ref);
161 if(!ref) {
162 if(This->serv_prov)
163 IServiceProvider_Release(This->serv_prov);
164 IBindStatusCallback_Release(This->callback);
165 heap_free(This);
168 return ref;
171 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallbackEx *iface,
172 DWORD dwReserved, IBinding *pbind)
174 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
176 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
178 return IBindStatusCallback_OnStartBinding(This->callback, 0xff, pbind);
181 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallbackEx *iface, LONG *pnPriority)
183 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
185 TRACE("(%p)->(%p)\n", This, pnPriority);
187 return IBindStatusCallback_GetPriority(This->callback, pnPriority);
190 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallbackEx *iface, DWORD reserved)
192 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
194 TRACE("(%p)->(%d)\n", This, reserved);
196 return IBindStatusCallback_OnLowResource(This->callback, reserved);
199 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallbackEx *iface, ULONG ulProgress,
200 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
202 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
204 TRACE("%p)->(%u %u %s %s)\n", This, ulProgress, ulProgressMax, debugstr_bindstatus(ulStatusCode),
205 debugstr_w(szStatusText));
207 return IBindStatusCallback_OnProgress(This->callback, ulProgress,
208 ulProgressMax, ulStatusCode, szStatusText);
211 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallbackEx *iface,
212 HRESULT hresult, LPCWSTR szError)
214 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
216 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
218 return IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
221 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallbackEx *iface,
222 DWORD *grfBINDF, BINDINFO *pbindinfo)
224 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
225 IBindStatusCallbackEx *bscex;
226 HRESULT hres;
228 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
230 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex);
231 if(SUCCEEDED(hres)) {
232 DWORD bindf2 = 0, reserv = 0;
234 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, &bindf2, &reserv);
235 IBindStatusCallbackEx_Release(bscex);
236 }else {
237 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
240 return hres;
243 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallbackEx *iface,
244 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
246 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
248 TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
250 return IBindStatusCallback_OnDataAvailable(This->callback, grfBSCF, dwSize, pformatetc, pstgmed);
253 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallbackEx *iface,
254 REFIID riid, IUnknown *punk)
256 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
258 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
260 return IBindStatusCallback_OnObjectAvailable(This->callback, riid, punk);
263 static HRESULT WINAPI BindStatusCallback_GetBindInfoEx(IBindStatusCallbackEx *iface, DWORD *grfBINDF,
264 BINDINFO *pbindinfo, DWORD *grfBINDF2, DWORD *pdwReserved)
266 BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
267 IBindStatusCallbackEx *bscex;
268 HRESULT hres;
270 TRACE("(%p)->(%p %p %p %p)\n", This, grfBINDF, pbindinfo, grfBINDF2, pdwReserved);
272 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IBindStatusCallbackEx, (void**)&bscex);
273 if(SUCCEEDED(hres)) {
274 hres = IBindStatusCallbackEx_GetBindInfoEx(bscex, grfBINDF, pbindinfo, grfBINDF2, pdwReserved);
275 IBindStatusCallbackEx_Release(bscex);
276 }else {
277 hres = IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
280 return hres;
283 static const IBindStatusCallbackExVtbl BindStatusCallbackExVtbl = {
284 BindStatusCallback_QueryInterface,
285 BindStatusCallback_AddRef,
286 BindStatusCallback_Release,
287 BindStatusCallback_OnStartBinding,
288 BindStatusCallback_GetPriority,
289 BindStatusCallback_OnLowResource,
290 BindStatusCallback_OnProgress,
291 BindStatusCallback_OnStopBinding,
292 BindStatusCallback_GetBindInfo,
293 BindStatusCallback_OnDataAvailable,
294 BindStatusCallback_OnObjectAvailable,
295 BindStatusCallback_GetBindInfoEx
298 static inline BindStatusCallback *impl_from_IServiceProvider(IServiceProvider *iface)
300 return CONTAINING_RECORD(iface, BindStatusCallback, IServiceProvider_iface);
303 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
304 REFIID riid, void **ppv)
306 BindStatusCallback *This = impl_from_IServiceProvider(iface);
307 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
310 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
312 BindStatusCallback *This = impl_from_IServiceProvider(iface);
313 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
316 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
318 BindStatusCallback *This = impl_from_IServiceProvider(iface);
319 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
322 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
323 REFGUID guidService, REFIID riid, void **ppv)
325 BindStatusCallback *This = impl_from_IServiceProvider(iface);
326 HRESULT hres;
328 if(IsEqualGUID(&IID_IHttpNegotiate, guidService)) {
329 TRACE("(%p)->(IID_IHttpNegotiate %s %p)\n", This, debugstr_guid(riid), ppv);
330 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
333 if(IsEqualGUID(&IID_IHttpNegotiate2, guidService)) {
334 TRACE("(%p)->(IID_IHttpNegotiate2 %s %p)\n", This, debugstr_guid(riid), ppv);
335 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
338 if(IsEqualGUID(&IID_IAuthenticate, guidService)) {
339 TRACE("(%p)->(IID_IAuthenticate %s %p)\n", This, debugstr_guid(riid), ppv);
340 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
343 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
345 hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv);
346 if(SUCCEEDED(hres))
347 return S_OK;
349 if(This->serv_prov) {
350 hres = IServiceProvider_QueryService(This->serv_prov, guidService, riid, ppv);
351 if(SUCCEEDED(hres))
352 return S_OK;
355 return E_NOINTERFACE;
358 static const IServiceProviderVtbl BSCServiceProviderVtbl = {
359 BSCServiceProvider_QueryInterface,
360 BSCServiceProvider_AddRef,
361 BSCServiceProvider_Release,
362 BSCServiceProvider_QueryService
365 static inline BindStatusCallback *impl_from_IHttpNegotiate2(IHttpNegotiate2 *iface)
367 return CONTAINING_RECORD(iface, BindStatusCallback, IHttpNegotiate2_iface);
370 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
371 REFIID riid, void **ppv)
373 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
374 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
377 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate2 *iface)
379 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
380 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
383 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate2 *iface)
385 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
386 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
389 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
390 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
392 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
393 IHttpNegotiate *http_negotiate;
394 HRESULT hres = S_OK;
396 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved,
397 pszAdditionalHeaders);
399 *pszAdditionalHeaders = NULL;
401 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
402 if(http_negotiate) {
403 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, szURL, szHeaders,
404 dwReserved, pszAdditionalHeaders);
405 IHttpNegotiate_Release(http_negotiate);
408 return hres;
411 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
412 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders,
413 LPWSTR *pszAdditionalRequestHeaders)
415 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
416 LPWSTR additional_headers = NULL;
417 IHttpNegotiate *http_negotiate;
418 HRESULT hres = S_OK;
420 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
421 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
423 http_negotiate = get_callback_iface(This, &IID_IHttpNegotiate);
424 if(http_negotiate) {
425 hres = IHttpNegotiate_OnResponse(http_negotiate, dwResponseCode, szResponseHeaders,
426 szRequestHeaders, &additional_headers);
427 IHttpNegotiate_Release(http_negotiate);
430 if(pszAdditionalRequestHeaders)
431 *pszAdditionalRequestHeaders = additional_headers;
432 else
433 CoTaskMemFree(additional_headers);
435 return hres;
438 static HRESULT WINAPI BSCHttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
439 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
441 BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
442 IHttpNegotiate2 *http_negotiate2;
443 HRESULT hres = E_FAIL;
445 TRACE("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved);
447 http_negotiate2 = get_callback_iface(This, &IID_IHttpNegotiate2);
448 if(http_negotiate2) {
449 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, pbSecurityId,
450 pcbSecurityId, dwReserved);
451 IHttpNegotiate2_Release(http_negotiate2);
454 return hres;
457 static const IHttpNegotiate2Vtbl BSCHttpNegotiateVtbl = {
458 BSCHttpNegotiate_QueryInterface,
459 BSCHttpNegotiate_AddRef,
460 BSCHttpNegotiate_Release,
461 BSCHttpNegotiate_BeginningTransaction,
462 BSCHttpNegotiate_OnResponse,
463 BSCHttpNegotiate_GetRootSecurityId
466 static inline BindStatusCallback *impl_from_IAuthenticate(IAuthenticate *iface)
468 return CONTAINING_RECORD(iface, BindStatusCallback, IAuthenticate_iface);
471 static HRESULT WINAPI BSCAuthenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
473 BindStatusCallback *This = impl_from_IAuthenticate(iface);
474 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
477 static ULONG WINAPI BSCAuthenticate_AddRef(IAuthenticate *iface)
479 BindStatusCallback *This = impl_from_IAuthenticate(iface);
480 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
483 static ULONG WINAPI BSCAuthenticate_Release(IAuthenticate *iface)
485 BindStatusCallback *This = impl_from_IAuthenticate(iface);
486 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
489 static HRESULT WINAPI BSCAuthenticate_Authenticate(IAuthenticate *iface,
490 HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword)
492 BindStatusCallback *This = impl_from_IAuthenticate(iface);
493 FIXME("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword);
494 return E_NOTIMPL;
497 static const IAuthenticateVtbl BSCAuthenticateVtbl = {
498 BSCAuthenticate_QueryInterface,
499 BSCAuthenticate_AddRef,
500 BSCAuthenticate_Release,
501 BSCAuthenticate_Authenticate
504 static inline BindStatusCallback *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
506 return CONTAINING_RECORD(iface, BindStatusCallback, IInternetBindInfo_iface);
509 static HRESULT WINAPI BSCInternetBindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
511 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
512 return IBindStatusCallbackEx_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
515 static ULONG WINAPI BSCInternetBindInfo_AddRef(IInternetBindInfo *iface)
517 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
518 return IBindStatusCallbackEx_AddRef(&This->IBindStatusCallbackEx_iface);
521 static ULONG WINAPI BSCInternetBindInfo_Release(IInternetBindInfo *iface)
523 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
524 return IBindStatusCallbackEx_Release(&This->IBindStatusCallbackEx_iface);
527 static HRESULT WINAPI BSCInternetBindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *bindf, BINDINFO *bindinfo)
529 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
530 FIXME("(%p)->(%p %p)\n", This, bindf, bindinfo);
531 return E_NOTIMPL;
534 static HRESULT WINAPI BSCInternetBindInfo_GetBindString(IInternetBindInfo *iface, ULONG string_type,
535 WCHAR **strs, ULONG cnt, ULONG *fetched)
537 BindStatusCallback *This = impl_from_IInternetBindInfo(iface);
538 IInternetBindInfo *bind_info;
539 HRESULT hres;
541 TRACE("(%p)->(%d %p %d %p)\n", This, string_type, strs, cnt, fetched);
543 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IInternetBindInfo, (void**)&bind_info);
544 if(FAILED(hres))
545 return hres;
547 hres = IInternetBindInfo_GetBindString(bind_info, string_type, strs, cnt, fetched);
549 IInternetBindInfo_Release(bind_info);
550 return hres;
553 static IInternetBindInfoVtbl BSCInternetBindInfoVtbl = {
554 BSCInternetBindInfo_QueryInterface,
555 BSCInternetBindInfo_AddRef,
556 BSCInternetBindInfo_Release,
557 BSCInternetBindInfo_GetBindInfo,
558 BSCInternetBindInfo_GetBindString
561 static void set_callback(BindStatusCallback *This, IBindStatusCallback *bsc)
563 IServiceProvider *serv_prov;
564 HRESULT hres;
566 if(This->callback)
567 IBindStatusCallback_Release(This->callback);
568 if(This->serv_prov)
569 IServiceProvider_Release(This->serv_prov);
571 IBindStatusCallback_AddRef(bsc);
572 This->callback = bsc;
574 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&serv_prov);
575 This->serv_prov = hres == S_OK ? serv_prov : NULL;
578 HRESULT wrap_callback(IBindStatusCallback *bsc, IBindStatusCallback **ret_iface)
580 BindStatusCallback *ret;
582 ret = heap_alloc_zero(sizeof(BindStatusCallback));
583 if(!ret)
584 return E_OUTOFMEMORY;
586 ret->IBindStatusCallbackEx_iface.lpVtbl = &BindStatusCallbackExVtbl;
587 ret->IInternetBindInfo_iface.lpVtbl = &BSCInternetBindInfoVtbl;
588 ret->IServiceProvider_iface.lpVtbl = &BSCServiceProviderVtbl;
589 ret->IHttpNegotiate2_iface.lpVtbl = &BSCHttpNegotiateVtbl;
590 ret->IAuthenticate_iface.lpVtbl = &BSCAuthenticateVtbl;
592 ret->ref = 1;
593 set_callback(ret, bsc);
595 *ret_iface = (IBindStatusCallback*)&ret->IBindStatusCallbackEx_iface;
596 return S_OK;
599 /***********************************************************************
600 * RegisterBindStatusCallback (urlmon.@)
602 * Register a bind status callback.
604 * PARAMS
605 * pbc [I] Binding context
606 * pbsc [I] Callback to register
607 * ppbscPrevious [O] Destination for previous callback
608 * dwReserved [I] Reserved, must be 0.
610 * RETURNS
611 * Success: S_OK.
612 * Failure: E_INVALIDARG, if any argument is invalid, or
613 * E_OUTOFMEMORY if memory allocation fails.
615 HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc,
616 IBindStatusCallback **ppbscPrevious, DWORD dwReserved)
618 BindStatusCallback *holder;
619 IBindStatusCallback *bsc, *prev = NULL;
620 HRESULT hres;
622 TRACE("(%p %p %p %x)\n", pbc, pbsc, ppbscPrevious, dwReserved);
624 if (!pbc || !pbsc)
625 return E_INVALIDARG;
627 bsc = bsch_from_bctx(pbc);
628 if(bsc) {
629 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
630 if(SUCCEEDED(hres)) {
631 if(ppbscPrevious) {
632 IBindStatusCallback_AddRef(holder->callback);
633 *ppbscPrevious = holder->callback;
636 set_callback(holder, pbsc);
638 IBindStatusCallback_Release(bsc);
639 IBindStatusCallbackEx_Release(&holder->IBindStatusCallbackEx_iface);
640 return S_OK;
641 }else {
642 prev = bsc;
645 IBindCtx_RevokeObjectParam(pbc, bscb_holderW);
648 hres = wrap_callback(pbsc, &bsc);
649 if(SUCCEEDED(hres)) {
650 hres = IBindCtx_RegisterObjectParam(pbc, bscb_holderW, (IUnknown*)bsc);
651 IBindStatusCallback_Release(bsc);
653 if(FAILED(hres)) {
654 if(prev)
655 IBindStatusCallback_Release(prev);
656 return hres;
659 if(ppbscPrevious)
660 *ppbscPrevious = prev;
661 return S_OK;
664 /***********************************************************************
665 * RevokeBindStatusCallback (URLMON.@)
667 * Unregister a bind status callback.
669 * pbc [I] Binding context
670 * pbsc [I] Callback to unregister
672 * RETURNS
673 * Success: S_OK.
674 * Failure: E_INVALIDARG, if any argument is invalid
676 HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc)
678 IBindStatusCallback *callback;
680 TRACE("(%p %p)\n", pbc, pbsc);
682 if (!pbc || !pbsc)
683 return E_INVALIDARG;
685 callback = bsc_from_bctx(pbc);
686 if(!callback)
687 return S_OK;
689 if(callback == pbsc)
690 IBindCtx_RevokeObjectParam(pbc, bscb_holderW);
692 IBindStatusCallback_Release(callback);
693 return S_OK;
696 typedef struct {
697 IBindCtx IBindCtx_iface;
699 LONG ref;
701 IBindCtx *bindctx;
702 } AsyncBindCtx;
704 static inline AsyncBindCtx *impl_from_IBindCtx(IBindCtx *iface)
706 return CONTAINING_RECORD(iface, AsyncBindCtx, IBindCtx_iface);
709 static HRESULT WINAPI AsyncBindCtx_QueryInterface(IBindCtx *iface, REFIID riid, void **ppv)
711 AsyncBindCtx *This = impl_from_IBindCtx(iface);
713 *ppv = NULL;
715 if(IsEqualGUID(riid, &IID_IUnknown)) {
716 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
717 *ppv = &This->IBindCtx_iface;
718 }else if(IsEqualGUID(riid, &IID_IBindCtx)) {
719 TRACE("(%p)->(IID_IBindCtx %p)\n", This, ppv);
720 *ppv = &This->IBindCtx_iface;
721 }else if(IsEqualGUID(riid, &IID_IAsyncBindCtx)) {
722 TRACE("(%p)->(IID_IAsyncBindCtx %p)\n", This, ppv);
723 *ppv = &This->IBindCtx_iface;
726 if(*ppv) {
727 IUnknown_AddRef((IUnknown*)*ppv);
728 return S_OK;
731 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
732 return E_NOINTERFACE;
735 static ULONG WINAPI AsyncBindCtx_AddRef(IBindCtx *iface)
737 AsyncBindCtx *This = impl_from_IBindCtx(iface);
738 LONG ref = InterlockedIncrement(&This->ref);
740 TRACE("(%p) ref=%d\n", This, ref);
742 return ref;
745 static ULONG WINAPI AsyncBindCtx_Release(IBindCtx *iface)
747 AsyncBindCtx *This = impl_from_IBindCtx(iface);
748 LONG ref = InterlockedDecrement(&This->ref);
750 TRACE("(%p) ref=%d\n", This, ref);
752 if(!ref) {
753 IBindCtx_Release(This->bindctx);
754 heap_free(This);
757 return ref;
760 static HRESULT WINAPI AsyncBindCtx_RegisterObjectBound(IBindCtx *iface, IUnknown *punk)
762 AsyncBindCtx *This = impl_from_IBindCtx(iface);
764 TRACE("(%p)->(%p)\n", This, punk);
766 return IBindCtx_RegisterObjectBound(This->bindctx, punk);
769 static HRESULT WINAPI AsyncBindCtx_RevokeObjectBound(IBindCtx *iface, IUnknown *punk)
771 AsyncBindCtx *This = impl_from_IBindCtx(iface);
773 TRACE("(%p %p)\n", This, punk);
775 return IBindCtx_RevokeObjectBound(This->bindctx, punk);
778 static HRESULT WINAPI AsyncBindCtx_ReleaseBoundObjects(IBindCtx *iface)
780 AsyncBindCtx *This = impl_from_IBindCtx(iface);
782 TRACE("(%p)\n", This);
784 return IBindCtx_ReleaseBoundObjects(This->bindctx);
787 static HRESULT WINAPI AsyncBindCtx_SetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
789 AsyncBindCtx *This = impl_from_IBindCtx(iface);
791 TRACE("(%p)->(%p)\n", This, pbindopts);
793 return IBindCtx_SetBindOptions(This->bindctx, pbindopts);
796 static HRESULT WINAPI AsyncBindCtx_GetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
798 AsyncBindCtx *This = impl_from_IBindCtx(iface);
800 TRACE("(%p)->(%p)\n", This, pbindopts);
802 return IBindCtx_GetBindOptions(This->bindctx, pbindopts);
805 static HRESULT WINAPI AsyncBindCtx_GetRunningObjectTable(IBindCtx *iface, IRunningObjectTable **pprot)
807 AsyncBindCtx *This = impl_from_IBindCtx(iface);
809 TRACE("(%p)->(%p)\n", This, pprot);
811 return IBindCtx_GetRunningObjectTable(This->bindctx, pprot);
814 static HRESULT WINAPI AsyncBindCtx_RegisterObjectParam(IBindCtx *iface, LPOLESTR pszkey, IUnknown *punk)
816 AsyncBindCtx *This = impl_from_IBindCtx(iface);
818 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
820 return IBindCtx_RegisterObjectParam(This->bindctx, pszkey, punk);
823 static HRESULT WINAPI AsyncBindCtx_GetObjectParam(IBindCtx* iface, LPOLESTR pszkey, IUnknown **punk)
825 AsyncBindCtx *This = impl_from_IBindCtx(iface);
827 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
829 return IBindCtx_GetObjectParam(This->bindctx, pszkey, punk);
832 static HRESULT WINAPI AsyncBindCtx_RevokeObjectParam(IBindCtx *iface, LPOLESTR pszkey)
834 AsyncBindCtx *This = impl_from_IBindCtx(iface);
836 TRACE("(%p)->(%s)\n", This, debugstr_w(pszkey));
838 return IBindCtx_RevokeObjectParam(This->bindctx, pszkey);
841 static HRESULT WINAPI AsyncBindCtx_EnumObjectParam(IBindCtx *iface, IEnumString **pszkey)
843 AsyncBindCtx *This = impl_from_IBindCtx(iface);
845 TRACE("(%p)->(%p)\n", This, pszkey);
847 return IBindCtx_EnumObjectParam(This->bindctx, pszkey);
850 static const IBindCtxVtbl AsyncBindCtxVtbl =
852 AsyncBindCtx_QueryInterface,
853 AsyncBindCtx_AddRef,
854 AsyncBindCtx_Release,
855 AsyncBindCtx_RegisterObjectBound,
856 AsyncBindCtx_RevokeObjectBound,
857 AsyncBindCtx_ReleaseBoundObjects,
858 AsyncBindCtx_SetBindOptions,
859 AsyncBindCtx_GetBindOptions,
860 AsyncBindCtx_GetRunningObjectTable,
861 AsyncBindCtx_RegisterObjectParam,
862 AsyncBindCtx_GetObjectParam,
863 AsyncBindCtx_EnumObjectParam,
864 AsyncBindCtx_RevokeObjectParam
867 static HRESULT init_bindctx(IBindCtx *bindctx, DWORD options,
868 IBindStatusCallback *callback, IEnumFORMATETC *format)
870 BIND_OPTS bindopts;
871 HRESULT hres;
873 if(options)
874 FIXME("not supported options %08x\n", options);
875 if(format)
876 FIXME("format is not supported\n");
878 bindopts.cbStruct = sizeof(BIND_OPTS);
879 bindopts.grfFlags = BIND_MAYBOTHERUSER;
880 bindopts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
881 bindopts.dwTickCountDeadline = 0;
883 hres = IBindCtx_SetBindOptions(bindctx, &bindopts);
884 if(FAILED(hres))
885 return hres;
887 if(callback) {
888 hres = RegisterBindStatusCallback(bindctx, callback, NULL, 0);
889 if(FAILED(hres))
890 return hres;
893 return S_OK;
896 /***********************************************************************
897 * CreateAsyncBindCtx (urlmon.@)
899 HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback,
900 IEnumFORMATETC *format, IBindCtx **pbind)
902 IBindCtx *bindctx;
903 HRESULT hres;
905 TRACE("(%08x %p %p %p)\n", reserved, callback, format, pbind);
907 if(!pbind || !callback)
908 return E_INVALIDARG;
910 hres = CreateBindCtx(0, &bindctx);
911 if(FAILED(hres))
912 return hres;
914 hres = init_bindctx(bindctx, 0, callback, format);
915 if(FAILED(hres)) {
916 IBindCtx_Release(bindctx);
917 return hres;
920 *pbind = bindctx;
921 return S_OK;
924 /***********************************************************************
925 * CreateAsyncBindCtxEx (urlmon.@)
927 * Create an asynchronous bind context.
929 HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options,
930 IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx** pbind,
931 DWORD reserved)
933 AsyncBindCtx *ret;
934 IBindCtx *bindctx;
935 HRESULT hres;
937 TRACE("(%p %08x %p %p %p %d)\n", ibind, options, callback, format, pbind, reserved);
939 if(!pbind)
940 return E_INVALIDARG;
942 if(reserved)
943 WARN("reserved=%d\n", reserved);
945 if(ibind) {
946 IBindCtx_AddRef(ibind);
947 bindctx = ibind;
948 }else {
949 hres = CreateBindCtx(0, &bindctx);
950 if(FAILED(hres))
951 return hres;
954 ret = heap_alloc(sizeof(AsyncBindCtx));
956 ret->IBindCtx_iface.lpVtbl = &AsyncBindCtxVtbl;
957 ret->ref = 1;
958 ret->bindctx = bindctx;
960 hres = init_bindctx(&ret->IBindCtx_iface, options, callback, format);
961 if(FAILED(hres)) {
962 IBindCtx_Release(&ret->IBindCtx_iface);
963 return hres;
966 *pbind = &ret->IBindCtx_iface;
967 return S_OK;