urlmon: Use existing callback holder in RegisterBindStatusCallback if already exists.

This commit is contained in:
Jacek Caban 2010-10-06 21:36:03 +02:00 committed by Alexandre Julliard
parent 1db24bedfc
commit 428c1bbac6
1 changed files with 40 additions and 14 deletions

View File

@ -460,9 +460,30 @@ static const IAuthenticateVtbl BSCAuthenticateVtbl = {
BSCAuthenticate_Authenticate BSCAuthenticate_Authenticate
}; };
static IBindStatusCallback *create_bsc(IBindStatusCallback *bsc) static void set_callback(BindStatusCallback *This, IBindStatusCallback *bsc)
{ {
BindStatusCallback *ret = heap_alloc_zero(sizeof(BindStatusCallback)); IServiceProvider *serv_prov;
HRESULT hres;
if(This->callback)
IBindStatusCallback_Release(This->callback);
if(This->serv_prov)
IServiceProvider_Release(This->serv_prov);
IBindStatusCallback_AddRef(bsc);
This->callback = bsc;
hres = IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&serv_prov);
This->serv_prov = hres == S_OK ? serv_prov : NULL;
}
static HRESULT wrap_callback(IBindStatusCallback *bsc, IBindStatusCallback **ret_iface)
{
BindStatusCallback *ret;
ret = heap_alloc_zero(sizeof(BindStatusCallback));
if(!ret)
return E_OUTOFMEMORY;
ret->lpBindStatusCallbackExVtbl = &BindStatusCallbackExVtbl; ret->lpBindStatusCallbackExVtbl = &BindStatusCallbackExVtbl;
ret->lpServiceProviderVtbl = &BSCServiceProviderVtbl; ret->lpServiceProviderVtbl = &BSCServiceProviderVtbl;
@ -470,13 +491,10 @@ static IBindStatusCallback *create_bsc(IBindStatusCallback *bsc)
ret->lpAuthenticateVtbl = &BSCAuthenticateVtbl; ret->lpAuthenticateVtbl = &BSCAuthenticateVtbl;
ret->ref = 1; ret->ref = 1;
set_callback(ret, bsc);
IBindStatusCallback_AddRef(bsc); *ret_iface = STATUSCLB(ret);
ret->callback = bsc; return S_OK;
IBindStatusCallback_QueryInterface(bsc, &IID_IServiceProvider, (void**)&ret->serv_prov);
return STATUSCLB(ret);
} }
/*********************************************************************** /***********************************************************************
@ -511,25 +529,33 @@ HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pb
hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk); hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc); hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&bsc);
IUnknown_Release(unk);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder); hres = IBindStatusCallback_QueryInterface(bsc, &IID_IBindStatusCallbackHolder, (void**)&holder);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
prev = holder->callback; if(ppbscPrevious) {
IBindStatusCallback_AddRef(prev); IBindStatusCallback_AddRef(holder->callback);
*ppbscPrevious = holder->callback;
}
set_callback(holder, pbsc);
IBindStatusCallback_Release(bsc); IBindStatusCallback_Release(bsc);
IBindStatusCallback_Release(STATUSCLB(holder)); IBindStatusCallback_Release(STATUSCLB(holder));
return S_OK;
}else { }else {
prev = bsc; prev = bsc;
} }
} }
IUnknown_Release(unk);
IBindCtx_RevokeObjectParam(pbc, BSCBHolder); IBindCtx_RevokeObjectParam(pbc, BSCBHolder);
} }
bsc = create_bsc(pbsc); hres = wrap_callback(pbsc, &bsc);
if(SUCCEEDED(hres)) {
hres = IBindCtx_RegisterObjectParam(pbc, BSCBHolder, (IUnknown*)bsc); hres = IBindCtx_RegisterObjectParam(pbc, BSCBHolder, (IUnknown*)bsc);
IBindStatusCallback_Release(bsc); IBindStatusCallback_Release(bsc);
}
if(FAILED(hres)) { if(FAILED(hres)) {
if(prev) if(prev)
IBindStatusCallback_Release(prev); IBindStatusCallback_Release(prev);