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);
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);
This->pi = grfPI;
+ if(This->uri) {
+ SysFreeString(This->display_uri);
+ IUri_Release(This->uri);
+ }
IUri_AddRef(pUri);
This->uri = pUri;
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;
}
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)
{
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;
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;
}
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);
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);