urlmon: Add mime handler layer before data is processed.
diff --git a/dlls/urlmon/Makefile.in b/dlls/urlmon/Makefile.in
index 0953553..7a44794 100644
--- a/dlls/urlmon/Makefile.in
+++ b/dlls/urlmon/Makefile.in
@@ -18,7 +18,6 @@
 	mimefilter.c \
 	mk.c \
 	protocol.c \
-	protproxy.c \
 	sec_mgr.c \
 	session.c \
 	umon.c \
diff --git a/dlls/urlmon/bindprot.c b/dlls/urlmon/bindprot.c
index 0941e25..043ff85 100644
--- a/dlls/urlmon/bindprot.c
+++ b/dlls/urlmon/bindprot.c
@@ -170,44 +170,35 @@
     return !(This->pi & PI_APARTMENTTHREADED) || (This->apartment_thread == GetCurrentThreadId() && !This->continue_call);
 }
 
-static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter, LPCWSTR mime)
+static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_filter)
 {
     PROTOCOLFILTERDATA filter_data = { sizeof(PROTOCOLFILTERDATA), NULL, NULL, NULL, 0 };
-    IInternetProtocolSink *protocol_sink, *old_sink;
-    ProtocolProxy *filter_proxy;
     HRESULT hres;
 
-    hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&protocol_sink);
-    if(FAILED(hres))
-        return hres;
-
-    hres = create_protocol_proxy(&This->default_protocol_handler.IInternetProtocol_iface, This->protocol_sink, &filter_proxy);
+    hres = IInternetProtocol_QueryInterface(mime_filter, &IID_IInternetProtocolSink, (void**)&This->protocol_sink_handler);
     if(FAILED(hres)) {
-        IInternetProtocolSink_Release(protocol_sink);
+        This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
         return hres;
     }
 
-    old_sink = This->protocol_sink;
-    This->protocol_sink = protocol_sink;
-    This->filter_proxy = filter_proxy;
-
     IInternetProtocol_AddRef(mime_filter);
     This->protocol_handler = mime_filter;
 
-    filter_data.pProtocol = &filter_proxy->IInternetProtocol_iface;
-    hres = IInternetProtocol_Start(mime_filter, mime, &filter_proxy->IInternetProtocolSink_iface,
+    filter_data.pProtocol = &This->default_protocol_handler.IInternetProtocol_iface;
+    hres = IInternetProtocol_Start(mime_filter, This->mime, &This->default_protocol_handler.IInternetProtocolSink_iface,
             &This->IInternetBindInfo_iface, PI_FILTER_MODE|PI_FORCE_ASYNC,
             (HANDLE_PTR)&filter_data);
     if(FAILED(hres)) {
-        IInternetProtocolSink_Release(old_sink);
+        IInternetProtocolSink_Release(This->protocol_sink_handler);
+        IInternetProtocol_Release(This->protocol_handler);
+        This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
+        This->protocol_handler = &This->default_protocol_handler.IInternetProtocol_iface;
         return hres;
     }
 
     /* NOTE: IE9 calls it on the new protocol_sink. It doesn't make sense to is seems to be a bug there. */
-    IInternetProtocolSink_ReportProgress(old_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
-    IInternetProtocolSink_Release(old_sink);
+    IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_LOADINGMIMEHANDLER, NULL);
 
-    This->pi &= ~PI_MIMEVERIFICATION; /* FIXME: more tests */
     return S_OK;
 }
 
@@ -217,25 +208,21 @@
     HRESULT hres;
 
     heap_free(This->mime);
-    This->mime = NULL;
+    This->mime = heap_strdupW(mime);
 
-    mime_filter = get_mime_filter(mime);
-    if(mime_filter) {
+    if(This->protocol_handler==&This->default_protocol_handler.IInternetProtocol_iface
+            && (mime_filter = get_mime_filter(mime))) {
         TRACE("Got mime filter for %s\n", debugstr_w(mime));
 
-        hres = handle_mime_filter(This, mime_filter, mime);
+        hres = handle_mime_filter(This, mime_filter);
         IInternetProtocol_Release(mime_filter);
         if(FAILED(hres))
             FIXME("MIME filter failed: %08x\n", hres);
-    }else {
-        This->mime = heap_strdupW(mime);
+    }
 
-        if(verified || !(This->pi & PI_MIMEVERIFICATION)) {
-            This->reported_mime = TRUE;
-
-            if(This->protocol_sink)
-                IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
-        }
+    if(This->reported_mime || verified || !(This->pi & PI_MIMEVERIFICATION)) {
+        This->reported_mime = TRUE;
+        IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
     }
 }
 
@@ -338,8 +325,9 @@
             IInternetBindInfo_Release(This->bind_info);
         if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface)
             IInternetProtocol_Release(This->protocol_handler);
-        if(This->filter_proxy)
-            IInternetProtocol_Release(&This->filter_proxy->IInternetProtocol_iface);
+        if(This->protocol_sink_handler &&
+                This->protocol_sink_handler != &This->default_protocol_handler.IInternetProtocolSink_iface)
+            IInternetProtocolSink_Release(This->protocol_sink_handler);
         if(This->uri)
             IUri_Release(This->uri);
         SysFreeString(This->display_uri);
@@ -606,7 +594,29 @@
 
 static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
 {
-    ERR("should not be called\n");
+    BindProtocol *This = impl_from_IInternetProtocol(iface);
+
+    *ppv = NULL;
+    if(IsEqualGUID(&IID_IUnknown, riid)) {
+        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+        *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
+    }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
+        TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
+        *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
+    }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
+        TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
+        *ppv = &This->default_protocol_handler.IInternetProtocol_iface;
+    }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
+        TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
+        *ppv = &This->default_protocol_handler.IInternetProtocolSink_iface;
+    }
+
+    if(*ppv) {
+        IInternetProtocol_AddRef(iface);
+        return S_OK;
+    }
+
+    WARN("not supported interface %s\n", debugstr_guid(riid));
     return E_NOINTERFACE;
 }
 
@@ -667,11 +677,6 @@
 
     IInternetProtocol_Terminate(This->protocol, 0);
 
-    if(This->filter_proxy) {
-        IInternetProtocol_Release(&This->filter_proxy->IInternetProtocol_iface);
-        This->filter_proxy = NULL;
-    }
-
     set_binding_sink(This, NULL, NULL);
 
     if(This->bind_info) {
@@ -772,6 +777,188 @@
     ProtocolHandler_UnlockRequest
 };
 
+static inline BindProtocol *impl_from_IInternetProtocolSinkHandler(IInternetProtocolSink *iface)
+{
+    return CONTAINING_RECORD(iface, BindProtocol, default_protocol_handler.IInternetProtocolSink_iface);
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_QueryInterface(IInternetProtocolSink *iface,
+        REFIID riid, void **ppvObject)
+{
+    BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+    return IInternetProtocol_QueryInterface(&This->default_protocol_handler.IInternetProtocol_iface,
+            riid, ppvObject);
+}
+
+static ULONG WINAPI ProtocolSinkHandler_AddRef(IInternetProtocolSink *iface)
+{
+    BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+    return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
+}
+
+static ULONG WINAPI ProtocolSinkHandler_Release(IInternetProtocolSink *iface)
+{
+    BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+    return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_Switch(IInternetProtocolSink *iface,
+        PROTOCOLDATA *pProtocolData)
+{
+    BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+
+    TRACE("(%p)->(%p)\n", This, pProtocolData);
+
+    if(!This->protocol_sink) {
+        IInternetProtocol_Continue(This->protocol_handler, pProtocolData);
+        return S_OK;
+    }
+
+    return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_ReportProgress(IInternetProtocolSink *iface,
+        ULONG status_code, LPCWSTR status_text)
+{
+    BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+
+    TRACE("(%p)->(%u %s)\n", This, status_code, debugstr_w(status_text));
+
+    if(!This->protocol_sink)
+        return S_OK;
+
+    switch(status_code) {
+    case BINDSTATUS_FINDINGRESOURCE:
+    case BINDSTATUS_CONNECTING:
+    case BINDSTATUS_REDIRECTING:
+    case BINDSTATUS_SENDINGREQUEST:
+    case BINDSTATUS_CACHEFILENAMEAVAILABLE:
+    case BINDSTATUS_DIRECTBIND:
+    case BINDSTATUS_ACCEPTRANGES:
+    case BINDSTATUS_DECODING:
+        IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
+        break;
+
+    case BINDSTATUS_BEGINDOWNLOADDATA:
+        IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
+        break;
+
+    case BINDSTATUS_MIMETYPEAVAILABLE:
+        mime_available(This, status_text, FALSE);
+        break;
+
+    case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
+        mime_available(This, status_text, TRUE);
+        break;
+
+    default:
+        FIXME("unsupported ulStatusCode %u\n", status_code);
+    }
+
+    return S_OK;
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_ReportData(IInternetProtocolSink *iface,
+        DWORD bscf, ULONG progress, ULONG progress_max)
+{
+    BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+
+    TRACE("(%p)->(%x %u %u)\n", This, bscf, progress, progress_max);
+
+    This->bscf = bscf;
+    This->progress = progress;
+    This->progress_max = progress_max;
+
+    if(!This->protocol_sink)
+        return S_OK;
+
+    if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
+        BYTE buf[BUFFER_SIZE];
+        DWORD read = 0;
+        LPWSTR mime;
+        HRESULT hres;
+
+        do {
+            read = 0;
+            hres = IInternetProtocol_Read(This->protocol, buf,
+                    sizeof(buf)-This->buf_size, &read);
+            if(FAILED(hres) && hres != E_PENDING)
+                return hres;
+
+            if(!This->buf) {
+                This->buf = heap_alloc(BUFFER_SIZE);
+                if(!This->buf)
+                    return E_OUTOFMEMORY;
+            }else if(read + This->buf_size > BUFFER_SIZE) {
+                BYTE *tmp;
+
+                tmp = heap_realloc(This->buf, read+This->buf_size);
+                if(!tmp)
+                    return E_OUTOFMEMORY;
+                This->buf = tmp;
+            }
+
+            memcpy(This->buf+This->buf_size, buf, read);
+            This->buf_size += read;
+        }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
+
+        if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
+            return S_OK;
+
+        bscf = BSCF_FIRSTDATANOTIFICATION;
+        if(hres == S_FALSE)
+            bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
+
+        if(!This->reported_mime) {
+            BSTR raw_uri;
+
+            hres = IUri_GetRawUri(This->uri, &raw_uri);
+            if(FAILED(hres))
+                return hres;
+
+            hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
+                    This->mime, 0, &mime, 0);
+            SysFreeString(raw_uri);
+            if(FAILED(hres))
+                return hres;
+
+            heap_free(This->mime);
+            This->mime = heap_strdupW(mime);
+            CoTaskMemFree(mime);
+            This->reported_mime = TRUE;
+            if(This->protocol_sink)
+                IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, This->mime);
+        }
+    }
+
+    if(!This->protocol_sink)
+        return S_OK;
+
+    return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
+}
+
+static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *iface,
+        HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
+{
+    BindProtocol *This = impl_from_IInternetProtocolSinkHandler(iface);
+
+    TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
+
+    if(This->protocol_sink)
+        return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
+    return S_OK;
+}
+
+static const IInternetProtocolSinkVtbl InternetProtocolSinkHandlerVtbl = {
+    ProtocolSinkHandler_QueryInterface,
+    ProtocolSinkHandler_AddRef,
+    ProtocolSinkHandler_Release,
+    ProtocolSinkHandler_Switch,
+    ProtocolSinkHandler_ReportProgress,
+    ProtocolSinkHandler_ReportData,
+    ProtocolSinkHandler_ReportResult
+};
+
 static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
 {
     return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
@@ -953,44 +1140,7 @@
         return S_OK;
     }
 
-    if(!This->protocol_sink) {
-        IInternetProtocol_Continue(This->protocol_handler, data);
-        return S_OK;
-    }
-
-    return IInternetProtocolSink_Switch(This->protocol_sink, data);
-}
-
-static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
-{
-    switch(status_code) {
-    case BINDSTATUS_FINDINGRESOURCE:
-    case BINDSTATUS_CONNECTING:
-    case BINDSTATUS_REDIRECTING:
-    case BINDSTATUS_SENDINGREQUEST:
-    case BINDSTATUS_CACHEFILENAMEAVAILABLE:
-    case BINDSTATUS_DIRECTBIND:
-    case BINDSTATUS_ACCEPTRANGES:
-        if(This->protocol_sink)
-            IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
-        break;
-
-    case BINDSTATUS_BEGINDOWNLOADDATA:
-        if(This->protocol_sink)
-            IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
-        break;
-
-    case BINDSTATUS_MIMETYPEAVAILABLE:
-        mime_available(This, status_text, FALSE);
-        break;
-
-    case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
-        mime_available(This, status_text, TRUE);
-        break;
-
-    default:
-        FIXME("unsupported ulStatusCode %u\n", status_code);
-    }
+    return IInternetProtocolSink_Switch(This->protocol_sink_handler, data);
 }
 
 typedef struct {
@@ -1004,7 +1154,7 @@
 {
     on_progress_task_t *task = (on_progress_task_t*)t;
 
-    report_progress(This, task->status_code, task->status_text);
+    IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, task->status_code, task->status_text);
 
     heap_free(task->status_text);
     heap_free(task);
@@ -1018,7 +1168,7 @@
     TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
 
     if(do_direct_notif(This)) {
-        report_progress(This, ulStatusCode, szStatusText);
+        IInternetProtocolSink_ReportProgress(This->protocol_sink_handler, ulStatusCode, szStatusText);
     }else {
         on_progress_task_t *task;
 
@@ -1033,76 +1183,6 @@
     return S_OK;
 }
 
-static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG progress_max)
-{
-    This->bscf = bscf;
-    This->progress = progress;
-    This->progress_max = progress_max;
-
-    if(!This->protocol_sink)
-        return S_OK;
-
-    if((This->pi & PI_MIMEVERIFICATION) && !This->reported_mime) {
-        BYTE buf[BUFFER_SIZE];
-        DWORD read = 0;
-        LPWSTR mime;
-        HRESULT hres;
-
-        do {
-            read = 0;
-            hres = IInternetProtocol_Read(This->protocol, buf,
-                    sizeof(buf)-This->buf_size, &read);
-            if(FAILED(hres) && hres != E_PENDING)
-                return hres;
-
-            if(!This->buf) {
-                This->buf = heap_alloc(BUFFER_SIZE);
-                if(!This->buf)
-                    return E_OUTOFMEMORY;
-            }else if(read + This->buf_size > BUFFER_SIZE) {
-                BYTE *tmp;
-
-                tmp = heap_realloc(This->buf, read+This->buf_size);
-                if(!tmp)
-                    return E_OUTOFMEMORY;
-                This->buf = tmp;
-            }
-
-            memcpy(This->buf+This->buf_size, buf, read);
-            This->buf_size += read;
-        }while(This->buf_size < MIME_TEST_SIZE && hres == S_OK);
-
-        if(This->buf_size < MIME_TEST_SIZE && hres != S_FALSE)
-            return S_OK;
-
-        bscf = BSCF_FIRSTDATANOTIFICATION;
-        if(hres == S_FALSE)
-            bscf |= BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
-
-        if(!This->reported_mime) {
-            BSTR raw_uri;
-
-            hres = IUri_GetRawUri(This->uri, &raw_uri);
-            if(FAILED(hres))
-                return hres;
-
-            hres = FindMimeFromData(NULL, raw_uri, This->buf, min(This->buf_size, MIME_TEST_SIZE),
-                    This->mime, 0, &mime, 0);
-            SysFreeString(raw_uri);
-            if(FAILED(hres))
-                return hres;
-
-            mime_available(This, mime, TRUE);
-            CoTaskMemFree(mime);
-        }
-    }
-
-    if(!This->protocol_sink)
-        return S_OK;
-
-    return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
-}
-
 typedef struct {
     task_header_t header;
     DWORD bscf;
@@ -1114,7 +1194,9 @@
 {
     report_data_task_t *task = (report_data_task_t*)t;
 
-    report_data(This, task->bscf, task->progress, task->progress_max);
+    IInternetProtocolSink_ReportData(This->protocol_sink_handler,
+            task->bscf, task->progress, task->progress_max);
+
     heap_free(task);
 }
 
@@ -1123,7 +1205,7 @@
 {
     BindProtocol *This = impl_from_IInternetProtocolSink(iface);
 
-    TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
+    TRACE("(%p)->(%x %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
 
     if(!This->protocol_sink)
         return S_OK;
@@ -1143,7 +1225,8 @@
         return S_OK;
     }
 
-    return report_data(This, grfBSCF, ulProgress, ulProgressMax);
+    return IInternetProtocolSink_ReportData(This->protocol_sink_handler,
+            grfBSCF, ulProgress, ulProgressMax);
 }
 
 typedef struct {
@@ -1158,8 +1241,7 @@
 {
     report_result_task_t *task = (report_result_task_t*)t;
 
-    if(This->protocol_sink)
-        IInternetProtocolSink_ReportResult(This->protocol_sink, task->hres, task->err, task->str);
+    IInternetProtocolSink_ReportResult(This->protocol_sink_handler, task->hres, task->err, task->str);
 
     heap_free(task->str);
     heap_free(task);
@@ -1174,7 +1256,6 @@
 
     if(!This->protocol_sink)
         return E_FAIL;
-
     This->reported_result = TRUE;
 
     if(!do_direct_notif(This)) {
@@ -1192,7 +1273,7 @@
         return S_OK;
     }
 
-    return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
+    return IInternetProtocolSink_ReportResult(This->protocol_sink_handler, hrResult, dwError, szResult);
 }
 
 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
@@ -1308,12 +1389,14 @@
     ret->IWinInetHttpInfo_iface.lpVtbl      = &WinInetHttpInfoVtbl;
 
     ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
+    ret->default_protocol_handler.IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkHandlerVtbl;
 
     ret->ref = 1;
     ret->from_urlmon = from_urlmon;
     ret->apartment_thread = GetCurrentThreadId();
     ret->notif_hwnd = get_notif_hwnd();
     ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface;
+    ret->protocol_sink_handler = &ret->default_protocol_handler.IInternetProtocolSink_iface;
     InitializeCriticalSection(&ret->section);
     ret->section.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BindProtocol.section");
 
diff --git a/dlls/urlmon/protproxy.c b/dlls/urlmon/protproxy.c
deleted file mode 100644
index 06a8586..0000000
--- a/dlls/urlmon/protproxy.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright 2009 Jacek Caban for CodeWeavers
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "urlmon_main.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
-
-static inline ProtocolProxy *impl_from_IInternetProtocol(IInternetProtocol *iface)
-{
-    return CONTAINING_RECORD(iface, ProtocolProxy, IInternetProtocol_iface);
-}
-
-static HRESULT WINAPI ProtocolProxy_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-
-    *ppv = NULL;
-    if(IsEqualGUID(&IID_IUnknown, riid)) {
-        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
-        *ppv = &This->IInternetProtocol_iface;
-    }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
-        TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
-        *ppv = &This->IInternetProtocol_iface;
-    }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
-        TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
-        *ppv = &This->IInternetProtocol_iface;
-    }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
-        TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
-        *ppv = &This->IInternetProtocolSink_iface;
-    }
-
-    if(*ppv) {
-        IInternetProtocol_AddRef(iface);
-        return S_OK;
-    }
-
-    WARN("not supported interface %s\n", debugstr_guid(riid));
-    return E_NOINTERFACE;
-}
-
-static ULONG WINAPI ProtocolProxy_AddRef(IInternetProtocol *iface)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-    LONG ref = InterlockedIncrement(&This->ref);
-    TRACE("(%p) ref=%d\n", This, ref);
-    return ref;
-}
-
-static ULONG WINAPI ProtocolProxy_Release(IInternetProtocol *iface)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-    LONG ref = InterlockedDecrement(&This->ref);
-
-    TRACE("(%p) ref=%d\n", This, ref);
-
-    if(!ref) {
-        if(This->protocol_sink)
-            IInternetProtocolSink_Release(This->protocol_sink);
-        if(This->protocol)
-            IInternetProtocol_Release(This->protocol);
-
-        heap_free(This);
-
-        URLMON_UnlockModule();
-    }
-
-    return ref;
-}
-
-static HRESULT WINAPI ProtocolProxy_Start(IInternetProtocol *iface, LPCWSTR szUrl,
-        IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
-        DWORD grfPI, HANDLE_PTR dwReserved)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-
-    TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
-          pOIBindInfo, grfPI, dwReserved);
-
-    return IInternetProtocol_Start(This->protocol, szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved);
-}
-
-static HRESULT WINAPI ProtocolProxy_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-
-    TRACE("(%p)->(%p)\n", This, pProtocolData);
-
-    return IInternetProtocol_Continue(This->protocol, pProtocolData);
-}
-
-static HRESULT WINAPI ProtocolProxy_Abort(IInternetProtocol *iface, HRESULT hrReason,
-        DWORD dwOptions)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-    FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI ProtocolProxy_Terminate(IInternetProtocol *iface, DWORD dwOptions)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-
-    TRACE("(%p)->(%08x)\n", This, dwOptions);
-
-    return IInternetProtocol_Terminate(This->protocol, dwOptions);
-}
-
-static HRESULT WINAPI ProtocolProxy_Suspend(IInternetProtocol *iface)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-    FIXME("(%p)\n", This);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI ProtocolProxy_Resume(IInternetProtocol *iface)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-    FIXME("(%p)\n", This);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI ProtocolProxy_Read(IInternetProtocol *iface, void *pv,
-        ULONG cb, ULONG *pcbRead)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-
-    TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
-
-    return IInternetProtocol_Read(This->protocol, pv, cb, pcbRead);
-}
-
-static HRESULT WINAPI ProtocolProxy_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
-        DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-    FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI ProtocolProxy_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-
-    TRACE("(%p)->(%08x)\n", This, dwOptions);
-
-    return IInternetProtocol_LockRequest(This->protocol, dwOptions);
-}
-
-static HRESULT WINAPI ProtocolProxy_UnlockRequest(IInternetProtocol *iface)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
-
-    TRACE("(%p)\n", This);
-
-    return IInternetProtocol_UnlockRequest(This->protocol);
-}
-
-static const IInternetProtocolVtbl ProtocolProxyVtbl = {
-    ProtocolProxy_QueryInterface,
-    ProtocolProxy_AddRef,
-    ProtocolProxy_Release,
-    ProtocolProxy_Start,
-    ProtocolProxy_Continue,
-    ProtocolProxy_Abort,
-    ProtocolProxy_Terminate,
-    ProtocolProxy_Suspend,
-    ProtocolProxy_Resume,
-    ProtocolProxy_Read,
-    ProtocolProxy_Seek,
-    ProtocolProxy_LockRequest,
-    ProtocolProxy_UnlockRequest
-};
-
-static inline ProtocolProxy *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
-{
-    return CONTAINING_RECORD(iface, ProtocolProxy, IInternetProtocolSink_iface);
-}
-
-static HRESULT WINAPI ProtocolProxySink_QueryInterface(IInternetProtocolSink *iface,
-        REFIID riid, void **ppv)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
-    return IInternetProtocol_QueryInterface(&This->IInternetProtocol_iface, riid, ppv);
-}
-
-static ULONG WINAPI ProtocolProxySink_AddRef(IInternetProtocolSink *iface)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
-    return IInternetProtocol_AddRef(&This->IInternetProtocol_iface);
-}
-
-static ULONG WINAPI ProtocolProxySink_Release(IInternetProtocolSink *iface)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
-    return IInternetProtocol_Release(&This->IInternetProtocol_iface);
-}
-
-static HRESULT WINAPI ProtocolProxySink_Switch(IInternetProtocolSink *iface,
-        PROTOCOLDATA *pProtocolData)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
-
-    TRACE("(%p)->(%p)\n", This, pProtocolData);
-
-    return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData);
-}
-
-static HRESULT WINAPI ProtocolProxySink_ReportProgress(IInternetProtocolSink *iface,
-        ULONG ulStatusCode, LPCWSTR szStatusText)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
-
-    TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
-
-    switch(ulStatusCode) {
-    case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
-        IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_MIMETYPEAVAILABLE, szStatusText);
-        break;
-    default:
-        IInternetProtocolSink_ReportProgress(This->protocol_sink, ulStatusCode, szStatusText);
-    }
-
-    return S_OK;
-}
-
-static HRESULT WINAPI ProtocolProxySink_ReportData(IInternetProtocolSink *iface,
-        DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
-
-    TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
-
-    return IInternetProtocolSink_ReportData(This->protocol_sink, grfBSCF, ulProgress, ulProgressMax);
-}
-
-static HRESULT WINAPI ProtocolProxySink_ReportResult(IInternetProtocolSink *iface,
-        HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
-{
-    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
-
-    TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
-
-    return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
-}
-
-static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
-    ProtocolProxySink_QueryInterface,
-    ProtocolProxySink_AddRef,
-    ProtocolProxySink_Release,
-    ProtocolProxySink_Switch,
-    ProtocolProxySink_ReportProgress,
-    ProtocolProxySink_ReportData,
-    ProtocolProxySink_ReportResult
-};
-
-HRESULT create_protocol_proxy(IInternetProtocol *protocol, IInternetProtocolSink *protocol_sink, ProtocolProxy **ret)
-{
-    ProtocolProxy *sink;
-
-    sink = heap_alloc(sizeof(ProtocolProxy));
-    if(!sink)
-        return E_OUTOFMEMORY;
-
-    sink->IInternetProtocol_iface.lpVtbl = &ProtocolProxyVtbl;
-    sink->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
-    sink->ref = 1;
-
-    IInternetProtocol_AddRef(protocol);
-    sink->protocol = protocol;
-
-    IInternetProtocolSink_AddRef(protocol_sink);
-    sink->protocol_sink = protocol_sink;
-
-    *ret = sink;
-    return S_OK;
-}
diff --git a/dlls/urlmon/tests/protocol.c b/dlls/urlmon/tests/protocol.c
index 98422fe..90beeb9 100644
--- a/dlls/urlmon/tests/protocol.c
+++ b/dlls/urlmon/tests/protocol.c
@@ -148,7 +148,7 @@
 static HANDLE event_complete, event_complete2, event_continue, event_continue_done;
 static BOOL binding_test;
 static PROTOCOLDATA protocoldata, *pdata, continue_protdata;
-static DWORD prot_read, pi, filter_state, http_post_test, thread_id;
+static DWORD prot_read, filter_state, http_post_test, thread_id;
 static BOOL security_problem, test_async_req, impl_protex;
 static BOOL async_read_pending, mimefilter_test, direct_read, wait_for_switch, emulate_prot, short_read, test_abort;
 static BOOL empty_file;
@@ -1617,7 +1617,7 @@
         CHECK_CALLED(MimeFilter_CreateInstance);
         CHECK_CALLED(MimeFilter_Start);
         CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
-        todo_wine CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
+        CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
     }else {
         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
     }
@@ -2208,8 +2208,6 @@
     IInternetSession *session;
     HRESULT hres;
 
-    static const WCHAR gzipW[] = {'g','z','i','p',0};
-
     hres = pCoInternetGetSession(0, &session, 0);
     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
 
diff --git a/dlls/urlmon/urlmon_main.h b/dlls/urlmon/urlmon_main.h
index be9bc7f..4231307 100644
--- a/dlls/urlmon/urlmon_main.h
+++ b/dlls/urlmon/urlmon_main.h
@@ -155,18 +155,6 @@
 
 void find_domain_name(const WCHAR*,DWORD,INT*) DECLSPEC_HIDDEN;
 
-typedef struct {
-    IInternetProtocol     IInternetProtocol_iface;
-    IInternetProtocolSink IInternetProtocolSink_iface;
-
-    LONG ref;
-
-    IInternetProtocolSink *protocol_sink;
-    IInternetProtocol *protocol;
-} ProtocolProxy;
-
-HRESULT create_protocol_proxy(IInternetProtocol*,IInternetProtocolSink*,ProtocolProxy**) DECLSPEC_HIDDEN;
-
 typedef struct _task_header_t task_header_t;
 
 typedef struct {
@@ -188,8 +176,10 @@
 
     struct {
         IInternetProtocol IInternetProtocol_iface;
+        IInternetProtocolSink IInternetProtocolSink_iface;
     } default_protocol_handler;
     IInternetProtocol *protocol_handler;
+    IInternetProtocolSink *protocol_sink_handler;
 
     LONG priority;
 
@@ -214,7 +204,6 @@
     LPWSTR mime;
     IUri *uri;
     BSTR display_uri;
-    ProtocolProxy *filter_proxy;
 }  BindProtocol;
 
 HRESULT create_binding_protocol(BOOL,BindProtocol**) DECLSPEC_HIDDEN;