[URLMON] Sync with Wine Staging 2.16. CORE-13762
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 17 Sep 2017 22:58:01 +0000 (22:58 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 17 Sep 2017 22:58:01 +0000 (22:58 +0000)
5660a9b urlmon: Remove a redundant NULL check before SysFreeString().
acb1f03 urlmon: Support BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS in BindProtocol object.
ccc5ba2 urlmon: Added a helper function for releasing protocol handler.
cded077 urlmon: Release previously set URI in BindProtocol::StartEx.
9e92254 urlmon: Added support for BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS in http protocol handler.

svn path=/trunk/; revision=75902

reactos/dll/win32/urlmon/bindprot.c
reactos/dll/win32/urlmon/http.c
reactos/dll/win32/urlmon/protocol.c
reactos/dll/win32/urlmon/urlmon_main.h
reactos/media/doc/README.WINE

index cc2e759..c65b55f 100644 (file)
@@ -325,6 +325,31 @@ static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
     return ref;
 }
 
+static void release_protocol_handler(BindProtocol *This)
+{
+    if(This->wininet_info) {
+        IWinInetInfo_Release(This->wininet_info);
+        This->wininet_info = NULL;
+    }
+    if(This->wininet_http_info) {
+        IWinInetHttpInfo_Release(This->wininet_http_info);
+        This->wininet_http_info = NULL;
+    }
+    if(This->protocol) {
+        IInternetProtocol_Release(This->protocol);
+        This->protocol = NULL;
+    }
+    if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface) {
+        IInternetProtocol_Release(This->protocol_handler);
+        This->protocol_handler = &This->default_protocol_handler.IInternetProtocol_iface;
+    }
+    if(This->protocol_sink_handler &&
+       This->protocol_sink_handler != &This->default_protocol_handler.IInternetProtocolSink_iface) {
+        IInternetProtocolSink_Release(This->protocol_sink_handler);
+        This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface;
+    }
+}
+
 static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
 {
     BindProtocol *This = impl_from_IInternetProtocolEx(iface);
@@ -333,19 +358,11 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
     TRACE("(%p) ref=%d\n", This, ref);
 
     if(!ref) {
-        if(This->wininet_info)
-            IWinInetInfo_Release(This->wininet_info);
-        if(This->wininet_http_info)
-            IWinInetHttpInfo_Release(This->wininet_http_info);
-        if(This->protocol)
-            IInternetProtocol_Release(This->protocol);
+        release_protocol_handler(This);
+        if(This->redirect_callback)
+            IBindCallbackRedirect_Release(This->redirect_callback);
         if(This->bind_info)
             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->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);
@@ -489,6 +506,10 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
 
     This->pi = grfPI;
 
+    if(This->uri) {
+        SysFreeString(This->display_uri);
+        IUri_Release(This->uri);
+    }
     IUri_AddRef(pUri);
     This->uri = pUri;
 
@@ -707,6 +728,11 @@ static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD
         This->bind_info = NULL;
     }
 
+    if(This->redirect_callback) {
+        IBindCallbackRedirect_Release(This->redirect_callback);
+        This->redirect_callback = NULL;
+    }
+
     IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
     return S_OK;
 }
@@ -969,6 +995,29 @@ static HRESULT WINAPI ProtocolSinkHandler_ReportData(IInternetProtocolSink *ifac
     return IInternetProtocolSink_ReportData(This->protocol_sink, bscf, progress, progress_max);
 }
 
+static HRESULT handle_redirect(BindProtocol *This, const WCHAR *url)
+{
+    HRESULT hres;
+
+    if(This->redirect_callback) {
+        VARIANT_BOOL cancel = VARIANT_FALSE;
+        IBindCallbackRedirect_Redirect(This->redirect_callback, url, &cancel);
+        if(cancel)
+            return INET_E_REDIRECT_FAILED;
+    }
+
+    if(This->protocol_sink) {
+        hres = IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_REDIRECTING, url);
+        if(FAILED(hres))
+            return hres;
+    }
+
+    IInternetProtocol_Terminate(This->protocol, 0); /* should this be done in StartEx? */
+    release_protocol_handler(This);
+
+    return IInternetProtocolEx_Start(&This->IInternetProtocolEx_iface, url, This->protocol_sink, This->bind_info, This->pi, 0);
+}
+
 static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *iface,
         HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
 {
@@ -976,6 +1025,13 @@ static HRESULT WINAPI ProtocolSinkHandler_ReportResult(IInternetProtocolSink *if
 
     TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
 
+    if(hrResult == INET_E_REDIRECT_FAILED) {
+        hrResult = handle_redirect(This, szResult);
+        if(hrResult == S_OK)
+            return S_OK;
+        szResult = NULL;
+    }
+
     if(This->protocol_sink)
         return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
     return S_OK;
@@ -1029,6 +1085,17 @@ static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
         return hres;
     }
 
+    if((pbindinfo->dwOptions & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS) && !This->redirect_callback) {
+        IServiceProvider *service_provider;
+
+        hres = IInternetProtocolSink_QueryInterface(This->protocol_sink, &IID_IServiceProvider, (void**)&service_provider);
+        if(SUCCEEDED(hres)) {
+            hres = IServiceProvider_QueryService(service_provider, &IID_IBindCallbackRedirect, &IID_IBindCallbackRedirect,
+                                                 (void**)&This->redirect_callback);
+            IServiceProvider_Release(service_provider);
+        }
+    }
+
     *grfBINDF |= BINDF_FROMURLMON;
     return hres;
 }
index 24e2340..0b0f8af 100644 (file)
@@ -475,6 +475,18 @@ static HRESULT HttpProtocol_end_request(Protocol *protocol)
     return S_OK;
 }
 
+static BOOL is_redirect_response(DWORD status_code)
+{
+    switch(status_code) {
+    case HTTP_STATUS_REDIRECT:
+    case HTTP_STATUS_MOVED:
+    case HTTP_STATUS_REDIRECT_KEEP_VERB:
+    case HTTP_STATUS_REDIRECT_METHOD:
+        return TRUE;
+    }
+    return FALSE;
+}
+
 static HRESULT HttpProtocol_start_downloading(Protocol *prot)
 {
     HttpProtocol *This = impl_from_Protocol(prot);
@@ -495,7 +507,21 @@ static HRESULT HttpProtocol_start_downloading(Protocol *prot)
     res = HttpQueryInfoW(This->base.request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
             &status_code, &len, NULL);
     if(res) {
-        LPWSTR response_headers = query_http_info(This, HTTP_QUERY_RAW_HEADERS_CRLF);
+        WCHAR *response_headers;
+
+        if((This->base.bind_info.dwOptions & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS) && is_redirect_response(status_code)) {
+            WCHAR *location;
+
+            TRACE("Got redirect with disabled auto redirects\n");
+
+            location = query_http_info(This, HTTP_QUERY_LOCATION);
+            This->base.flags |= FLAG_RESULT_REPORTED | FLAG_LAST_DATA_REPORTED;
+            IInternetProtocolSink_ReportResult(This->base.protocol_sink, INET_E_REDIRECT_FAILED, 0, location);
+            heap_free(location);
+            return INET_E_REDIRECT_FAILED;
+        }
+
+        response_headers = query_http_info(This, HTTP_QUERY_RAW_HEADERS_CRLF);
         if(response_headers) {
             hres = IHttpNegotiate_OnResponse(This->http_negotiate, status_code, response_headers,
                     NULL, NULL);
index 543ae50..50dc17b 100644 (file)
@@ -72,6 +72,8 @@ static HRESULT start_downloading(Protocol *protocol)
 
     hres = protocol->vtbl->start_downloading(protocol);
     if(FAILED(hres)) {
+        if(hres == INET_E_REDIRECT_FAILED)
+            return S_OK;
         protocol_close_connection(protocol);
         report_result(protocol, hres);
         return hres;
@@ -334,6 +336,8 @@ HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, IUri *uri,
         request_flags |= INTERNET_FLAG_NO_CACHE_WRITE;
     if(protocol->bindf & BINDF_NEEDFILE)
         request_flags |= INTERNET_FLAG_NEED_FILE;
+    if(protocol->bind_info.dwOptions & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)
+        request_flags |= INTERNET_FLAG_NO_AUTO_REDIRECT;
 
     hres = protocol->vtbl->open_request(protocol, uri, request_flags, internet_session, bind_info);
     if(FAILED(hres)) {
index 69c6bde..4567952 100644 (file)
@@ -189,11 +189,13 @@ typedef struct {
     LONG ref;
 
     IInternetProtocol *protocol;
+    IWinInetInfo *wininet_info;
+    IWinInetHttpInfo *wininet_http_info;
+
     IInternetBindInfo *bind_info;
     IInternetProtocolSink *protocol_sink;
     IServiceProvider *service_provider;
-    IWinInetInfo *wininet_info;
-    IWinInetHttpInfo *wininet_http_info;
+    IBindCallbackRedirect *redirect_callback;
 
     struct {
         IInternetProtocol IInternetProtocol_iface;
index 72e3e3d..60a0a40 100644 (file)
@@ -188,7 +188,7 @@ reactos/dll/win32/traffic             # Synced to WineStaging-2.9
 reactos/dll/win32/twain_32            # Synced to WineStaging-2.9
 reactos/dll/win32/updspapi            # Synced to WineStaging-2.9
 reactos/dll/win32/url                 # Synced to WineStaging-2.9
-reactos/dll/win32/urlmon              # Synced to WineStaging-2.9
+reactos/dll/win32/urlmon              # Synced to WineStaging-2.16
 reactos/dll/win32/usp10               # Synced to WineStaging-2.9
 reactos/dll/win32/uxtheme             # Forked
 reactos/dll/win32/vbscript            # Synced to WineStaging-2.9