urlmon: Optimize registering urlmon protocols.
[wine/hacks.git] / dlls / urlmon / bindctx.c
blob328254c3bb6efef818a90190d924d1a92ffa7c3e
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;
41 IHttpNegotiate *http_negotiate;
42 BOOL init_http_negotiate;
43 IHttpNegotiate2 *http_negotiate2;
44 BOOL init_http_negotiate2;
45 IAuthenticate *authenticate;
46 BOOL init_authenticate;
47 } BindStatusCallback;
49 #define STATUSCLB(x) ((IBindStatusCallback*) &(x)->lpBindStatusCallbackVtbl)
50 #define SERVPROV(x) ((IServiceProvider*) &(x)->lpServiceProviderVtbl)
51 #define HTTPNEG2(x) ((IHttpNegotiate2*) &(x)->lpHttpNegotiate2Vtbl)
52 #define AUTHENTICATE(x) ((IAuthenticate*) &(x)->lpAuthenticateVtbl)
54 #define STATUSCLB_THIS(iface) DEFINE_THIS(BindStatusCallback, BindStatusCallback, iface)
56 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
57 REFIID riid, void **ppv)
59 BindStatusCallback *This = STATUSCLB_THIS(iface);
61 *ppv = NULL;
63 if(IsEqualGUID(&IID_IUnknown, riid)) {
64 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
65 *ppv = STATUSCLB(This);
66 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
67 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
68 *ppv = STATUSCLB(This);
69 }else if(IsEqualGUID(&IID_IBindStatusCallbackHolder, riid)) {
70 TRACE("(%p)->(IID_IBindStatusCallbackHolder, %p)\n", This, ppv);
71 *ppv = This;
72 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
73 TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
74 *ppv = SERVPROV(This);
75 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
76 TRACE("(%p)->(IID_IHttpNegotiate, %p)\n", This, ppv);
77 *ppv = HTTPNEG2(This);
78 }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
79 TRACE("(%p)->(IID_IHttpNegotiate2, %p)\n", This, ppv);
80 *ppv = HTTPNEG2(This);
81 }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
82 TRACE("(%p)->(IID_IAuthenticate, %p)\n", This, ppv);
83 *ppv = AUTHENTICATE(This);
86 if(*ppv) {
87 IBindStatusCallback_AddRef((IUnknown*)*ppv);
88 return S_OK;
91 TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
92 return E_NOINTERFACE;
95 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
97 BindStatusCallback *This = STATUSCLB_THIS(iface);
98 LONG ref = InterlockedIncrement(&This->ref);
100 TRACE("(%p) ref = %d\n", This, ref);
102 return ref;
105 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
107 BindStatusCallback *This = STATUSCLB_THIS(iface);
108 LONG ref = InterlockedDecrement(&This->ref);
110 TRACE("(%p) ref = %d\n", This, ref);
112 if(!ref) {
113 if(This->serv_prov)
114 IServiceProvider_Release(This->serv_prov);
115 if(This->http_negotiate)
116 IHttpNegotiate_Release(This->http_negotiate);
117 if(This->http_negotiate2)
118 IHttpNegotiate2_Release(This->http_negotiate2);
119 if(This->authenticate)
120 IAuthenticate_Release(This->authenticate);
121 IBindStatusCallback_Release(This->callback);
122 heap_free(This);
125 return ref;
128 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
129 DWORD dwReserved, IBinding *pbind)
131 BindStatusCallback *This = STATUSCLB_THIS(iface);
133 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
135 return IBindStatusCallback_OnStartBinding(This->callback, 0xff, pbind);
138 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
140 BindStatusCallback *This = STATUSCLB_THIS(iface);
142 TRACE("(%p)->(%p)\n", This, pnPriority);
144 return IBindStatusCallback_GetPriority(This->callback, pnPriority);
147 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
149 BindStatusCallback *This = STATUSCLB_THIS(iface);
151 TRACE("(%p)->(%d)\n", This, reserved);
153 return IBindStatusCallback_OnLowResource(This->callback, reserved);
156 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
157 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
159 BindStatusCallback *This = STATUSCLB_THIS(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(IBindStatusCallback *iface,
169 HRESULT hresult, LPCWSTR szError)
171 BindStatusCallback *This = STATUSCLB_THIS(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(IBindStatusCallback *iface,
179 DWORD *grfBINDF, BINDINFO *pbindinfo)
181 BindStatusCallback *This = STATUSCLB_THIS(iface);
183 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
185 return IBindStatusCallback_GetBindInfo(This->callback, grfBINDF, pbindinfo);
188 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
189 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
191 BindStatusCallback *This = STATUSCLB_THIS(iface);
193 TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
195 return IBindStatusCallback_OnDataAvailable(This->callback, grfBSCF, dwSize, pformatetc, pstgmed);
198 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
199 REFIID riid, IUnknown *punk)
201 BindStatusCallback *This = STATUSCLB_THIS(iface);
203 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
205 return IBindStatusCallback_OnObjectAvailable(This->callback, riid, punk);
208 #undef STATUSCLB_THIS
210 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
211 BindStatusCallback_QueryInterface,
212 BindStatusCallback_AddRef,
213 BindStatusCallback_Release,
214 BindStatusCallback_OnStartBinding,
215 BindStatusCallback_GetPriority,
216 BindStatusCallback_OnLowResource,
217 BindStatusCallback_OnProgress,
218 BindStatusCallback_OnStopBinding,
219 BindStatusCallback_GetBindInfo,
220 BindStatusCallback_OnDataAvailable,
221 BindStatusCallback_OnObjectAvailable
224 #define SERVPROV_THIS(iface) DEFINE_THIS(BindStatusCallback, ServiceProvider, iface)
226 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
227 REFIID riid, void **ppv)
229 BindStatusCallback *This = SERVPROV_THIS(iface);
230 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
233 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
235 BindStatusCallback *This = SERVPROV_THIS(iface);
236 return IBindStatusCallback_AddRef(STATUSCLB(This));
239 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
241 BindStatusCallback *This = SERVPROV_THIS(iface);
242 return IBindStatusCallback_Release(STATUSCLB(This));
245 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
246 REFGUID guidService, REFIID riid, void **ppv)
248 BindStatusCallback *This = SERVPROV_THIS(iface);
249 HRESULT hres;
251 if(IsEqualGUID(&IID_IHttpNegotiate, guidService)) {
252 TRACE("(%p)->(IID_IHttpNegotiate %s %p)\n", This, debugstr_guid(riid), ppv);
254 if(!This->init_http_negotiate) {
255 This->init_http_negotiate = TRUE;
256 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IHttpNegotiate,
257 (void**)&This->http_negotiate);
258 if(FAILED(hres) && This->serv_prov)
259 IServiceProvider_QueryService(This->serv_prov, &IID_IHttpNegotiate,
260 &IID_IHttpNegotiate, (void**)&This->http_negotiate);
263 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
266 if(IsEqualGUID(&IID_IHttpNegotiate2, guidService)) {
267 TRACE("(%p)->(IID_IHttpNegotiate2 %s %p)\n", This, debugstr_guid(riid), ppv);
269 if(!This->init_http_negotiate2) {
270 This->init_http_negotiate2 = TRUE;
271 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IHttpNegotiate2,
272 (void**)&This->http_negotiate2);
273 if(FAILED(hres) && This->serv_prov)
274 IServiceProvider_QueryService(This->serv_prov, &IID_IHttpNegotiate2,
275 &IID_IHttpNegotiate2, (void**)&This->http_negotiate2);
278 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
281 if(IsEqualGUID(&IID_IAuthenticate, guidService)) {
282 TRACE("(%p)->(IID_IAuthenticate %s %p)\n", This, debugstr_guid(riid), ppv);
284 if(!This->init_authenticate) {
285 This->init_authenticate = TRUE;
286 hres = IBindStatusCallback_QueryInterface(This->callback, &IID_IAuthenticate,
287 (void**)&This->authenticate);
288 if(FAILED(hres) && This->serv_prov)
289 IServiceProvider_QueryService(This->serv_prov, &IID_IAuthenticate,
290 &IID_IAuthenticate, (void**)&This->authenticate);
293 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
296 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
298 hres = IBindStatusCallback_QueryInterface(This->callback, riid, ppv);
299 if(SUCCEEDED(hres))
300 return S_OK;
302 if(This->serv_prov) {
303 hres = IServiceProvider_QueryService(This->serv_prov, guidService, riid, ppv);
304 if(SUCCEEDED(hres))
305 return S_OK;
308 return E_NOINTERFACE;
311 #undef SERVPROV_THIS
313 static const IServiceProviderVtbl BSCServiceProviderVtbl = {
314 BSCServiceProvider_QueryInterface,
315 BSCServiceProvider_AddRef,
316 BSCServiceProvider_Release,
317 BSCServiceProvider_QueryService
320 #define HTTPNEG2_THIS(iface) DEFINE_THIS(BindStatusCallback, HttpNegotiate2, iface)
322 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
323 REFIID riid, void **ppv)
325 BindStatusCallback *This = HTTPNEG2_THIS(iface);
326 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
329 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate2 *iface)
331 BindStatusCallback *This = HTTPNEG2_THIS(iface);
332 return IBindStatusCallback_AddRef(STATUSCLB(This));
335 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate2 *iface)
337 BindStatusCallback *This = HTTPNEG2_THIS(iface);
338 return IBindStatusCallback_Release(STATUSCLB(This));
341 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
342 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
344 BindStatusCallback *This = HTTPNEG2_THIS(iface);
346 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved,
347 pszAdditionalHeaders);
349 *pszAdditionalHeaders = NULL;
351 if(!This->http_negotiate)
352 return S_OK;
354 return IHttpNegotiate_BeginningTransaction(This->http_negotiate, szURL, szHeaders,
355 dwReserved, pszAdditionalHeaders);
358 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
359 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders,
360 LPWSTR *pszAdditionalRequestHeaders)
362 BindStatusCallback *This = HTTPNEG2_THIS(iface);
363 LPWSTR additional_headers = NULL;
364 HRESULT hres = S_OK;
366 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
367 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
369 if(This->http_negotiate)
370 hres = IHttpNegotiate_OnResponse(This->http_negotiate, dwResponseCode, szResponseHeaders,
371 szRequestHeaders, &additional_headers);
373 if(pszAdditionalRequestHeaders)
374 *pszAdditionalRequestHeaders = additional_headers;
375 else if(additional_headers)
376 CoTaskMemFree(additional_headers);
378 return hres;
381 static HRESULT WINAPI BSCHttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
382 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
384 BindStatusCallback *This = HTTPNEG2_THIS(iface);
386 TRACE("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved);
388 if(!This->http_negotiate2)
389 return E_FAIL;
391 return IHttpNegotiate2_GetRootSecurityId(This->http_negotiate2, pbSecurityId,
392 pcbSecurityId, dwReserved);
395 #undef HTTPNEG2_THIS
397 static const IHttpNegotiate2Vtbl BSCHttpNegotiateVtbl = {
398 BSCHttpNegotiate_QueryInterface,
399 BSCHttpNegotiate_AddRef,
400 BSCHttpNegotiate_Release,
401 BSCHttpNegotiate_BeginningTransaction,
402 BSCHttpNegotiate_OnResponse,
403 BSCHttpNegotiate_GetRootSecurityId
406 #define AUTHENTICATE_THIS(iface) DEFINE_THIS(BindStatusCallback, Authenticate, iface)
408 static HRESULT WINAPI BSCAuthenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
410 BindStatusCallback *This = AUTHENTICATE_THIS(iface);
411 return IBindStatusCallback_QueryInterface(AUTHENTICATE(This), riid, ppv);
414 static ULONG WINAPI BSCAuthenticate_AddRef(IAuthenticate *iface)
416 BindStatusCallback *This = AUTHENTICATE_THIS(iface);
417 return IBindStatusCallback_AddRef(STATUSCLB(This));
420 static ULONG WINAPI BSCAuthenticate_Release(IAuthenticate *iface)
422 BindStatusCallback *This = AUTHENTICATE_THIS(iface);
423 return IBindStatusCallback_Release(STATUSCLB(This));
426 static HRESULT WINAPI BSCAuthenticate_Authenticate(IAuthenticate *iface,
427 HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword)
429 BindStatusCallback *This = AUTHENTICATE_THIS(iface);
430 FIXME("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword);
431 return E_NOTIMPL;
434 #undef AUTHENTICATE_THIS
436 static const IAuthenticateVtbl BSCAuthenticateVtbl = {
437 BSCAuthenticate_QueryInterface,
438 BSCAuthenticate_AddRef,
439 BSCAuthenticate_Release,
440 BSCAuthenticate_Authenticate
443 static IBindStatusCallback *create_bsc(IBindStatusCallback *bsc)
445 BindStatusCallback *ret = heap_alloc_zero(sizeof(BindStatusCallback));
447 ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
448 ret->lpServiceProviderVtbl = &BSCServiceProviderVtbl;
449 ret->lpHttpNegotiate2Vtbl = &BSCHttpNegotiateVtbl;
450 ret->lpAuthenticateVtbl = &BSCAuthenticateVtbl;
452 ret->ref = 1;
454 IBindStatusCallback_AddRef(bsc);
455 ret->callback = bsc;
457 IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&ret->serv_prov);
459 return STATUSCLB(ret);
462 /***********************************************************************
463 * RegisterBindStatusCallback (urlmon.@)
465 * Register a bind status callback.
467 * PARAMS
468 * pbc [I] Binding context
469 * pbsc [I] Callback to register
470 * ppbscPrevious [O] Destination for previous callback
471 * dwReserved [I] Reserved, must be 0.
473 * RETURNS
474 * Success: S_OK.
475 * Failure: E_INVALIDARG, if any argument is invalid, or
476 * E_OUTOFMEMORY if memory allocation fails.
478 HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc,
479 IBindStatusCallback **ppbscPrevious, DWORD dwReserved)
481 BindStatusCallback *holder;
482 IBindStatusCallback *bsc, *prev = NULL;
483 IUnknown *unk;
484 HRESULT hres;
486 TRACE("(%p %p %p %x)\n", pbc, pbsc, ppbscPrevious, dwReserved);
488 if (!pbc || !pbsc)
489 return E_INVALIDARG;
491 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
492 if(SUCCEEDED(hres)) {
493 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc);
494 if(SUCCEEDED(hres)) {
495 hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
496 if(SUCCEEDED(hres)) {
497 prev = holder->callback;
498 IBindStatusCallback_AddRef(prev);
499 IBindStatusCallback_Release(bsc);
500 IBindStatusCallback_Release(STATUSCLB(holder));
501 }else {
502 prev = bsc;
506 IUnknown_Release(unk);
507 IBindCtx_RevokeObjectParam(pbc, BSCBHolder);
510 bsc = create_bsc(pbsc);
511 hres = IBindCtx_RegisterObjectParam(pbc, BSCBHolder, (IUnknown*)bsc);
512 IBindStatusCallback_Release(bsc);
513 if(FAILED(hres)) {
514 IBindStatusCallback_Release(prev);
515 return hres;
518 if(ppbscPrevious)
519 *ppbscPrevious = prev;
520 return S_OK;
523 /***********************************************************************
524 * RevokeBindStatusCallback (URLMON.@)
526 * Unregister a bind status callback.
528 * pbc [I] Binding context
529 * pbsc [I] Callback to unregister
531 * RETURNS
532 * Success: S_OK.
533 * Failure: E_INVALIDARG, if any argument is invalid
535 HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc)
537 BindStatusCallback *holder;
538 IBindStatusCallback *callback;
539 IUnknown *unk;
540 BOOL dorevoke = FALSE;
541 HRESULT hres;
543 TRACE("(%p %p)\n", pbc, pbsc);
545 if (!pbc || !pbsc)
546 return E_INVALIDARG;
548 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
549 if(FAILED(hres))
550 return S_OK;
552 hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&callback);
553 IUnknown_Release(unk);
554 if(FAILED(hres))
555 return S_OK;
557 hres = IBindStatusCallback_QueryInterface(callback, &IID_IBindStatusCallbackHolder, (void**)&holder);
558 if(SUCCEEDED(hres)) {
559 if(pbsc == holder->callback)
560 dorevoke = TRUE;
561 IBindStatusCallback_Release(STATUSCLB(holder));
562 }else if(pbsc == callback) {
563 dorevoke = TRUE;
565 IBindStatusCallback_Release(callback);
567 if(dorevoke)
568 IBindCtx_RevokeObjectParam(pbc, BSCBHolder);
570 return S_OK;
573 typedef struct {
574 const IBindCtxVtbl *lpBindCtxVtbl;
576 LONG ref;
578 IBindCtx *bindctx;
579 } AsyncBindCtx;
581 #define BINDCTX(x) ((IBindCtx*) &(x)->lpBindCtxVtbl)
583 #define BINDCTX_THIS(iface) DEFINE_THIS(AsyncBindCtx, BindCtx, iface)
585 static HRESULT WINAPI AsyncBindCtx_QueryInterface(IBindCtx *iface, REFIID riid, void **ppv)
587 AsyncBindCtx *This = BINDCTX_THIS(iface);
589 *ppv = NULL;
591 if(IsEqualGUID(riid, &IID_IUnknown)) {
592 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
593 *ppv = BINDCTX(This);
594 }else if(IsEqualGUID(riid, &IID_IBindCtx)) {
595 TRACE("(%p)->(IID_IBindCtx %p)\n", This, ppv);
596 *ppv = BINDCTX(This);
597 }else if(IsEqualGUID(riid, &IID_IAsyncBindCtx)) {
598 TRACE("(%p)->(IID_IAsyncBindCtx %p)\n", This, ppv);
599 *ppv = BINDCTX(This);
602 if(*ppv) {
603 IUnknown_AddRef((IUnknown*)*ppv);
604 return S_OK;
607 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
608 return E_NOINTERFACE;
611 static ULONG WINAPI AsyncBindCtx_AddRef(IBindCtx *iface)
613 AsyncBindCtx *This = BINDCTX_THIS(iface);
614 LONG ref = InterlockedIncrement(&This->ref);
616 TRACE("(%p) ref=%d\n", This, ref);
618 return ref;
621 static ULONG WINAPI AsyncBindCtx_Release(IBindCtx *iface)
623 AsyncBindCtx *This = BINDCTX_THIS(iface);
624 LONG ref = InterlockedDecrement(&This->ref);
626 TRACE("(%p) ref=%d\n", This, ref);
628 if(!ref) {
629 IBindCtx_Release(This->bindctx);
630 heap_free(This);
633 return ref;
636 static HRESULT WINAPI AsyncBindCtx_RegisterObjectBound(IBindCtx *iface, IUnknown *punk)
638 AsyncBindCtx *This = BINDCTX_THIS(iface);
640 TRACE("(%p)->(%p)\n", This, punk);
642 return IBindCtx_RegisterObjectBound(This->bindctx, punk);
645 static HRESULT WINAPI AsyncBindCtx_RevokeObjectBound(IBindCtx *iface, IUnknown *punk)
647 AsyncBindCtx *This = BINDCTX_THIS(iface);
649 TRACE("(%p %p)\n", This, punk);
651 return IBindCtx_RevokeObjectBound(This->bindctx, punk);
654 static HRESULT WINAPI AsyncBindCtx_ReleaseBoundObjects(IBindCtx *iface)
656 AsyncBindCtx *This = BINDCTX_THIS(iface);
658 TRACE("(%p)\n", This);
660 return IBindCtx_ReleaseBoundObjects(This->bindctx);
663 static HRESULT WINAPI AsyncBindCtx_SetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
665 AsyncBindCtx *This = BINDCTX_THIS(iface);
667 TRACE("(%p)->(%p)\n", This, pbindopts);
669 return IBindCtx_SetBindOptions(This->bindctx, pbindopts);
672 static HRESULT WINAPI AsyncBindCtx_GetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
674 AsyncBindCtx *This = BINDCTX_THIS(iface);
676 TRACE("(%p)->(%p)\n", This, pbindopts);
678 return IBindCtx_GetBindOptions(This->bindctx, pbindopts);
681 static HRESULT WINAPI AsyncBindCtx_GetRunningObjectTable(IBindCtx *iface, IRunningObjectTable **pprot)
683 AsyncBindCtx *This = BINDCTX_THIS(iface);
685 TRACE("(%p)->(%p)\n", This, pprot);
687 return IBindCtx_GetRunningObjectTable(This->bindctx, pprot);
690 static HRESULT WINAPI AsyncBindCtx_RegisterObjectParam(IBindCtx *iface, LPOLESTR pszkey, IUnknown *punk)
692 AsyncBindCtx *This = BINDCTX_THIS(iface);
694 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
696 return IBindCtx_RegisterObjectParam(This->bindctx, pszkey, punk);
699 static HRESULT WINAPI AsyncBindCtx_GetObjectParam(IBindCtx* iface, LPOLESTR pszkey, IUnknown **punk)
701 AsyncBindCtx *This = BINDCTX_THIS(iface);
703 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
705 return IBindCtx_GetObjectParam(This->bindctx, pszkey, punk);
708 static HRESULT WINAPI AsyncBindCtx_RevokeObjectParam(IBindCtx *iface, LPOLESTR pszkey)
710 AsyncBindCtx *This = BINDCTX_THIS(iface);
712 TRACE("(%p)->(%s)\n", This, debugstr_w(pszkey));
714 return IBindCtx_RevokeObjectParam(This->bindctx, pszkey);
717 static HRESULT WINAPI AsyncBindCtx_EnumObjectParam(IBindCtx *iface, IEnumString **pszkey)
719 AsyncBindCtx *This = BINDCTX_THIS(iface);
721 TRACE("(%p)->(%p)\n", This, pszkey);
723 return IBindCtx_EnumObjectParam(This->bindctx, pszkey);
726 #undef BINDCTX_THIS
728 static const IBindCtxVtbl AsyncBindCtxVtbl =
730 AsyncBindCtx_QueryInterface,
731 AsyncBindCtx_AddRef,
732 AsyncBindCtx_Release,
733 AsyncBindCtx_RegisterObjectBound,
734 AsyncBindCtx_RevokeObjectBound,
735 AsyncBindCtx_ReleaseBoundObjects,
736 AsyncBindCtx_SetBindOptions,
737 AsyncBindCtx_GetBindOptions,
738 AsyncBindCtx_GetRunningObjectTable,
739 AsyncBindCtx_RegisterObjectParam,
740 AsyncBindCtx_GetObjectParam,
741 AsyncBindCtx_EnumObjectParam,
742 AsyncBindCtx_RevokeObjectParam
745 static HRESULT init_bindctx(IBindCtx *bindctx, DWORD options,
746 IBindStatusCallback *callback, IEnumFORMATETC *format)
748 BIND_OPTS bindopts;
749 HRESULT hres;
751 if(options)
752 FIXME("not supported options %08x\n", options);
753 if(format)
754 FIXME("format is not supported\n");
756 bindopts.cbStruct = sizeof(BIND_OPTS);
757 bindopts.grfFlags = BIND_MAYBOTHERUSER;
758 bindopts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
759 bindopts.dwTickCountDeadline = 0;
761 hres = IBindCtx_SetBindOptions(bindctx, &bindopts);
762 if(FAILED(hres))
763 return hres;
765 if(callback) {
766 hres = RegisterBindStatusCallback(bindctx, callback, NULL, 0);
767 if(FAILED(hres))
768 return hres;
771 return S_OK;
774 /***********************************************************************
775 * CreateAsyncBindCtx (urlmon.@)
777 HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback,
778 IEnumFORMATETC *format, IBindCtx **pbind)
780 IBindCtx *bindctx;
781 HRESULT hres;
783 TRACE("(%08x %p %p %p)\n", reserved, callback, format, pbind);
785 if(!pbind || !callback)
786 return E_INVALIDARG;
788 hres = CreateBindCtx(0, &bindctx);
789 if(FAILED(hres))
790 return hres;
792 hres = init_bindctx(bindctx, 0, callback, format);
793 if(FAILED(hres)) {
794 IBindCtx_Release(bindctx);
795 return hres;
798 *pbind = bindctx;
799 return S_OK;
802 /***********************************************************************
803 * CreateAsyncBindCtxEx (urlmon.@)
805 * Create an asynchronous bind context.
807 HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options,
808 IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx** pbind,
809 DWORD reserved)
811 AsyncBindCtx *ret;
812 IBindCtx *bindctx;
813 HRESULT hres;
815 TRACE("(%p %08x %p %p %p %d)\n", ibind, options, callback, format, pbind, reserved);
817 if(!pbind)
818 return E_INVALIDARG;
820 if(reserved)
821 WARN("reserved=%d\n", reserved);
823 if(ibind) {
824 IBindCtx_AddRef(ibind);
825 bindctx = ibind;
826 }else {
827 hres = CreateBindCtx(0, &bindctx);
828 if(FAILED(hres))
829 return hres;
832 ret = heap_alloc(sizeof(AsyncBindCtx));
834 ret->lpBindCtxVtbl = &AsyncBindCtxVtbl;
835 ret->ref = 1;
836 ret->bindctx = bindctx;
838 hres = init_bindctx(BINDCTX(ret), options, callback, format);
839 if(FAILED(hres)) {
840 IBindCtx_Release(BINDCTX(ret));
841 return hres;
844 *pbind = BINDCTX(ret);
845 return S_OK;