diff --git a/dlls/mshtml/binding.h b/dlls/mshtml/binding.h
index 3a4e06b8b1..f5b85e94b3 100644
--- a/dlls/mshtml/binding.h
+++ b/dlls/mshtml/binding.h
@@ -69,10 +69,11 @@ typedef struct {
typedef struct BSCallbackVtbl BSCallbackVtbl;
struct BSCallback {
- IBindStatusCallback IBindStatusCallback_iface;
- IServiceProvider IServiceProvider_iface;
- IHttpNegotiate2 IHttpNegotiate2_iface;
- IInternetBindInfo IInternetBindInfo_iface;
+ IBindStatusCallback IBindStatusCallback_iface;
+ IServiceProvider IServiceProvider_iface;
+ IHttpNegotiate2 IHttpNegotiate2_iface;
+ IInternetBindInfo IInternetBindInfo_iface;
+ IBindCallbackRedirect IBindCallbackRedirect_iface;
const BSCallbackVtbl *vtbl;
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c
index cfa37531e8..d036364484 100644
--- a/dlls/mshtml/navigate.c
+++ b/dlls/mshtml/navigate.c
@@ -248,6 +248,9 @@ static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *ifa
}else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
*ppv = &This->IInternetBindInfo_iface;
+ }else if(IsEqualGUID(&IID_IBindCallbackRedirect, riid)) {
+ TRACE("(%p)->(IID_IBindCallbackRedirect %p)\n", This, ppv);
+ *ppv = &This->IBindCallbackRedirect_iface;
}
if(*ppv) {
@@ -561,6 +564,63 @@ static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
InternetBindInfo_GetBindString
};
+static inline BSCallback *impl_from_IBindCallbackRedirect(IBindCallbackRedirect *iface)
+{
+ return CONTAINING_RECORD(iface, BSCallback, IBindCallbackRedirect_iface);
+}
+
+static HRESULT WINAPI BindCallbackRedirect_QueryInterface(IBindCallbackRedirect *iface, REFIID riid, void **ppv)
+{
+ BSCallback *This = impl_from_IBindCallbackRedirect(iface);
+ return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
+}
+
+static ULONG WINAPI BindCallbackRedirect_AddRef(IBindCallbackRedirect *iface)
+{
+ BSCallback *This = impl_from_IBindCallbackRedirect(iface);
+ return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
+}
+
+static ULONG WINAPI BindCallbackRedirect_Release(IBindCallbackRedirect *iface)
+{
+ BSCallback *This = impl_from_IBindCallbackRedirect(iface);
+ return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
+}
+
+static HRESULT WINAPI BindCallbackRedirect_Redirect(IBindCallbackRedirect *iface, const WCHAR *url, VARIANT_BOOL *vbCancel)
+{
+ BSCallback *This = impl_from_IBindCallbackRedirect(iface);
+ HTMLDocumentObj *doc_obj;
+ BOOL cancel = FALSE;
+ BSTR frame_name = NULL;
+ HRESULT hres = S_OK;
+
+ TRACE("(%p)->(%s %p)\n", This, debugstr_w(url), vbCancel);
+
+ if(This->window && This->window->base.outer_window && (doc_obj = This->window->base.outer_window->doc_obj)
+ && doc_obj->doc_object_service) {
+ if(This->window->base.outer_window != doc_obj->basedoc.window) {
+ hres = IHTMLWindow2_get_name(&This->window->base.IHTMLWindow2_iface, &frame_name);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ hres = IDocObjectService_FireBeforeNavigate2(doc_obj->doc_object_service, NULL, url, 0x40,
+ frame_name, NULL, 0, NULL, TRUE, &cancel);
+ SysFreeString(frame_name);
+ }
+
+ *vbCancel = cancel ? VARIANT_TRUE : VARIANT_FALSE;
+ return hres;
+}
+
+static const IBindCallbackRedirectVtbl BindCallbackRedirectVtbl = {
+ BindCallbackRedirect_QueryInterface,
+ BindCallbackRedirect_AddRef,
+ BindCallbackRedirect_Release,
+ BindCallbackRedirect_Redirect
+};
+
static inline BSCallback *impl_from_IServiceProvider(IServiceProvider *iface)
{
return CONTAINING_RECORD(iface, BSCallback, IServiceProvider_iface);
@@ -610,6 +670,7 @@ void init_bscallback(BSCallback *This, const BSCallbackVtbl *vtbl, IMoniker *mon
This->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
This->IHttpNegotiate2_iface.lpVtbl = &HttpNegotiate2Vtbl;
This->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
+ This->IBindCallbackRedirect_iface.lpVtbl = &BindCallbackRedirectVtbl;
This->vtbl = vtbl;
This->ref = 1;
This->bindf = bindf;
diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c
index dafc109c84..6964f6ed07 100644
--- a/dlls/mshtml/tests/htmldoc.c
+++ b/dlls/mshtml/tests/htmldoc.c
@@ -1469,6 +1469,8 @@ static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMon
REFIID riid, void **ppv)
{
IBindStatusCallback *callback = NULL;
+ IBindCallbackRedirect *redirect_callback;
+ IServiceProvider *service_provider;
BINDINFO bindinfo;
DWORD bindf;
HRESULT hres;
@@ -1511,6 +1513,15 @@ static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMon
ok(bindinfo.pUnk == NULL, "bindinfo.pUnk=%p\n", bindinfo.pUnk);
ok(bindinfo.dwReserved == 0, "bindinfo.dwReserved=%d\n", bindinfo.dwReserved);
+ hres = IBindStatusCallback_QueryInterface(callback, &IID_IServiceProvider, (void**)&service_provider);
+ ok(hres == S_OK, "Could not get IServiceProvider iface: %08x\n", hres);
+
+ hres = IServiceProvider_QueryService(service_provider, &IID_IBindCallbackRedirect, &IID_IBindCallbackRedirect, (void**)&redirect_callback);
+ ok(hres == S_OK, "QueryService(IID_IBindCallbackRedirect) returned %08x\n", hres);
+
+ IBindCallbackRedirect_Release(redirect_callback);
+ IServiceProvider_Release(service_provider);
+
hres = IBindStatusCallback_OnStartBinding(callback, 0, &Binding);
ok(hres == S_OK, "OnStartBinding failed: %08x\n", hres);