Jacek Caban : mshtml: Properly support COM aggregation in about and res protocol handlers.

Alexandre Julliard julliard at winehq.org
Tue May 15 16:25:22 CDT 2018


Module: wine
Branch: master
Commit: b952590f93e1bbf2b76188b7c5e6ae9ad23bb541
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=b952590f93e1bbf2b76188b7c5e6ae9ad23bb541

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue May 15 15:27:27 2018 +0200

mshtml: Properly support COM aggregation in about and res protocol handlers.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mshtml/main.c     |   2 +
 dlls/mshtml/protocol.c | 146 ++++++++++++++++++++++++-------------------------
 2 files changed, 72 insertions(+), 76 deletions(-)

diff --git a/dlls/mshtml/main.c b/dlls/mshtml/main.c
index 0227ccc..9b2f199 100644
--- a/dlls/mshtml/main.c
+++ b/dlls/mshtml/main.c
@@ -571,6 +571,8 @@ const char *debugstr_mshtml_guid(const GUID *iid)
     X(IID_IHTMLPrivateWindow);
     X(IID_IHtmlLoadOptions);
     X(IID_IInternetHostSecurityManager);
+    X(IID_IInternetProtocol);
+    X(IID_IInternetProtocolRoot);
     X(IID_IManagedObject);
     X(IID_IMarshal);
     X(IID_IMonikerProp);
diff --git a/dlls/mshtml/protocol.c b/dlls/mshtml/protocol.c
index bdb83ce..d385f16 100644
--- a/dlls/mshtml/protocol.c
+++ b/dlls/mshtml/protocol.c
@@ -35,6 +35,7 @@
 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
 
 typedef struct {
+    IUnknown          IUnknown_inner;
     IInternetProtocol IInternetProtocol_iface;
 
     LONG ref;
@@ -43,7 +44,7 @@ typedef struct {
     ULONG data_len;
     ULONG cur;
 
-    IUnknown *pUnkOuter;
+    IUnknown *outer;
 } InternetProtocol;
 
 /********************************************************************
@@ -144,54 +145,50 @@ static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
     return S_OK;
 }
 
+static inline InternetProtocol *impl_from_IUnknown(IUnknown *iface)
+{
+    return CONTAINING_RECORD(iface, InternetProtocol, IUnknown_inner);
+}
+
 static inline InternetProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
 {
     return CONTAINING_RECORD(iface, InternetProtocol, IInternetProtocol_iface);
 }
 
-static HRESULT WINAPI InternetProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
+static HRESULT WINAPI Protocol_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
 {
-    InternetProtocol *This = impl_from_IInternetProtocol(iface);
+    InternetProtocol *This = impl_from_IUnknown(iface);
 
-    *ppv = NULL;
+    TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
 
     if(IsEqualGUID(&IID_IUnknown, riid)) {
-        TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
-        if(This->pUnkOuter)
-            return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
-        *ppv = &This->IInternetProtocol_iface;
+        *ppv = &This->IUnknown_inner;
     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
-        TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", iface, ppv);
         *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
-        TRACE("(%p)->(IID_IInternetProtocol %p)\n", iface, ppv);
         *ppv = &This->IInternetProtocol_iface;
-    }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
-        FIXME("IServiceProvider is not implemented\n");
-        return E_NOINTERFACE;
-    }
-
-    if(!*ppv) {
-        TRACE("unknown interface %s\n", debugstr_guid(riid));
+    }else {
+        if(IsEqualGUID(&IID_IServiceProvider, riid))
+            FIXME("IServiceProvider is not implemented\n");
+        *ppv = NULL;
         return E_NOINTERFACE;
     }
 
-    IInternetProtocol_AddRef(iface);
+    IUnknown_AddRef((IUnknown*)*ppv);
     return S_OK;
 }
 
-static ULONG WINAPI InternetProtocol_AddRef(IInternetProtocol *iface)
+static ULONG WINAPI Protocol_AddRef(IUnknown *iface)
 {
-    InternetProtocol *This = impl_from_IInternetProtocol(iface);
+    InternetProtocol *This = impl_from_IUnknown(iface);
     ULONG ref = InterlockedIncrement(&This->ref);
     TRACE("(%p) ref=%d\n", iface, ref);
-    return This->pUnkOuter ? IUnknown_AddRef(This->pUnkOuter) : ref;
+    return ref;
 }
 
-static ULONG WINAPI InternetProtocol_Release(IInternetProtocol *iface)
+static ULONG WINAPI Protocol_Release(IUnknown *iface)
 {
-    InternetProtocol *This = impl_from_IInternetProtocol(iface);
-    IUnknown *pUnkOuter = This->pUnkOuter;
+    InternetProtocol *This = impl_from_IUnknown(iface);
     ULONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%x\n", iface, ref);
@@ -201,7 +198,31 @@ static ULONG WINAPI InternetProtocol_Release(IInternetProtocol *iface)
         heap_free(This);
     }
 
-    return pUnkOuter ? IUnknown_Release(pUnkOuter) : ref;
+    return ref;
+}
+
+static const IUnknownVtbl ProtocolUnkVtbl = {
+    Protocol_QueryInterface,
+    Protocol_AddRef,
+    Protocol_Release
+};
+
+static HRESULT WINAPI InternetProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
+{
+    InternetProtocol *This = impl_from_IInternetProtocol(iface);
+    return IUnknown_QueryInterface(This->outer, riid, ppv);
+}
+
+static ULONG WINAPI InternetProtocol_AddRef(IInternetProtocol *iface)
+{
+    InternetProtocol *This = impl_from_IInternetProtocol(iface);
+    return IUnknown_AddRef(This->outer);
+}
+
+static ULONG WINAPI InternetProtocol_Release(IInternetProtocol *iface)
+{
+    InternetProtocol *This = impl_from_IInternetProtocol(iface);
+    return IUnknown_Release(This->outer);
 }
 
 static HRESULT WINAPI InternetProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData)
@@ -286,6 +307,28 @@ static HRESULT WINAPI InternetProtocol_UnlockRequest(IInternetProtocol *iface)
     return S_OK;
 }
 
+static HRESULT create_protocol_instance(const IInternetProtocolVtbl *protocol_vtbl,
+                                        IUnknown *outer, REFIID riid, void **ppv)
+{
+    InternetProtocol *protocol;
+    HRESULT hres;
+
+    if(outer && !IsEqualGUID(&IID_IUnknown, riid)) {
+        *ppv = NULL;
+        return E_INVALIDARG;
+    }
+
+    protocol = heap_alloc_zero(sizeof(InternetProtocol));
+    protocol->IUnknown_inner.lpVtbl = &ProtocolUnkVtbl;
+    protocol->IInternetProtocol_iface.lpVtbl = protocol_vtbl;
+    protocol->outer = outer ? outer : &protocol->IUnknown_inner;
+    protocol->ref = 1;
+
+    hres = IUnknown_QueryInterface(&protocol->IUnknown_inner, riid, ppv);
+    IUnknown_Release(&protocol->IUnknown_inner);
+    return hres;
+}
+
 /********************************************************************
  * about protocol implementation
  */
@@ -380,34 +423,9 @@ static const IInternetProtocolVtbl AboutProtocolVtbl = {
 static HRESULT WINAPI AboutProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
         REFIID riid, void **ppv)
 {
-    InternetProtocol *ret;
-    HRESULT hres = S_OK;
-
     TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
 
-    ret = heap_alloc(sizeof(InternetProtocol));
-    ret->IInternetProtocol_iface.lpVtbl = &AboutProtocolVtbl;
-    ret->ref = 0;
-
-    ret->data = NULL;
-    ret->data_len = 0;
-    ret->cur = 0;
-    ret->pUnkOuter = pUnkOuter;
-
-    if(pUnkOuter) {
-        ret->ref = 1;
-        if(IsEqualGUID(&IID_IUnknown, riid))
-            *ppv = &ret->IInternetProtocol_iface;
-        else
-            hres = E_INVALIDARG;
-    }else {
-        hres = IInternetProtocol_QueryInterface(&ret->IInternetProtocol_iface, riid, ppv);
-    }
-
-    if(FAILED(hres))
-        heap_free(ret);
-
-    return hres;
+    return create_protocol_instance(&AboutProtocolVtbl, pUnkOuter, riid, ppv);
 }
 
 static HRESULT WINAPI AboutProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
@@ -654,33 +672,9 @@ static const IInternetProtocolVtbl ResProtocolVtbl = {
 static HRESULT WINAPI ResProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
         REFIID riid, void **ppv)
 {
-    InternetProtocol *ret;
-    HRESULT hres = S_OK;
-
     TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
 
-    ret = heap_alloc(sizeof(InternetProtocol));
-    ret->IInternetProtocol_iface.lpVtbl = &ResProtocolVtbl;
-    ret->ref = 0;
-    ret->data = NULL;
-    ret->data_len = 0;
-    ret->cur = 0;
-    ret->pUnkOuter = pUnkOuter;
-
-    if(pUnkOuter) {
-        ret->ref = 1;
-        if(IsEqualGUID(&IID_IUnknown, riid))
-            *ppv = &ret->IInternetProtocol_iface;
-        else
-            hres = E_FAIL;
-    }else {
-        hres = IInternetProtocol_QueryInterface(&ret->IInternetProtocol_iface, riid, ppv);
-    }
-
-    if(FAILED(hres))
-        heap_free(ret);
-
-    return hres;
+    return create_protocol_instance(&ResProtocolVtbl, pUnkOuter, riid, ppv);
 }
 
 static HRESULT WINAPI ResProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,




More information about the wine-cvs mailing list