From 51e0becc3210bbd726fb4f42365f10fed97cd42c Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 17 Sep 2017 22:58:01 +0000 Subject: [PATCH] [URLMON] Sync with Wine Staging 2.16. CORE-13762 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 | 89 ++++++++++++++++++++++---- reactos/dll/win32/urlmon/http.c | 28 +++++++- reactos/dll/win32/urlmon/protocol.c | 4 ++ reactos/dll/win32/urlmon/urlmon_main.h | 6 +- reactos/media/doc/README.WINE | 2 +- 5 files changed, 114 insertions(+), 15 deletions(-) diff --git a/reactos/dll/win32/urlmon/bindprot.c b/reactos/dll/win32/urlmon/bindprot.c index cc2e75923f1..c65b55f23d6 100644 --- a/reactos/dll/win32/urlmon/bindprot.c +++ b/reactos/dll/win32/urlmon/bindprot.c @@ -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; } diff --git a/reactos/dll/win32/urlmon/http.c b/reactos/dll/win32/urlmon/http.c index 24e23409daf..0b0f8af1101 100644 --- a/reactos/dll/win32/urlmon/http.c +++ b/reactos/dll/win32/urlmon/http.c @@ -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); diff --git a/reactos/dll/win32/urlmon/protocol.c b/reactos/dll/win32/urlmon/protocol.c index 543ae504b2f..50dc17bb864 100644 --- a/reactos/dll/win32/urlmon/protocol.c +++ b/reactos/dll/win32/urlmon/protocol.c @@ -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)) { diff --git a/reactos/dll/win32/urlmon/urlmon_main.h b/reactos/dll/win32/urlmon/urlmon_main.h index 69c6bde0c2b..45679521a5c 100644 --- a/reactos/dll/win32/urlmon/urlmon_main.h +++ b/reactos/dll/win32/urlmon/urlmon_main.h @@ -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; diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 72e3e3d7dc6..60a0a400e17 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -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