*/
#include "urlmon_main.h"
-#include "wininet.h"
-
-#define NO_SHLWAPI_REG
-#include "shlwapi.h"
-
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
typedef struct {
Protocol base;
return ret;
}
-static inline BOOL set_security_flag(HttpProtocol *This, DWORD new_flag)
+static inline BOOL set_security_flag(HttpProtocol *This, DWORD flags)
{
- DWORD flags, size = sizeof(flags);
BOOL res;
- res = InternetQueryOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size);
- if(res) {
- flags |= new_flag;
- res = InternetSetOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, size);
- }
+ res = InternetSetOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
if(!res)
- ERR("Failed to set security flag(s): %x\n", new_flag);
+ ERR("Failed to set security flags: %x\n", flags);
return res;
}
case ERROR_INTERNET_SEC_CERT_CN_INVALID:
case ERROR_INTERNET_INVALID_CA:
case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
+ case ERROR_INTERNET_SEC_INVALID_CERT:
+ case ERROR_INTERNET_SEC_CERT_ERRORS:
+ case ERROR_INTERNET_SEC_CERT_REV_FAILED:
+ case ERROR_INTERNET_SEC_CERT_NO_REV:
+ case ERROR_INTERNET_SEC_CERT_REVOKED:
return INET_E_INVALID_CERTIFICATE;
case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
IWindowForBindingUI *wfb_ui;
IHttpSecurity *http_security;
BOOL security_problem;
+ DWORD dlg_flags;
+ HWND hwnd;
+ DWORD res;
HRESULT hres;
+ TRACE("(%p %u)\n", This, error);
+
switch(error) {
case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
case ERROR_INTERNET_SEC_CERT_CN_INVALID:
case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
- case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
case ERROR_INTERNET_INVALID_CA:
case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
+ case ERROR_INTERNET_SEC_INVALID_CERT:
+ case ERROR_INTERNET_SEC_CERT_ERRORS:
+ case ERROR_INTERNET_SEC_CERT_REV_FAILED:
+ case ERROR_INTERNET_SEC_CERT_NO_REV:
+ case ERROR_INTERNET_SEC_CERT_REVOKED:
+ case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
security_problem = TRUE;
break;
default:
hres = IHttpSecurity_OnSecurityProblem(http_security, error);
IHttpSecurity_Release(http_security);
+ TRACE("OnSecurityProblem returned %08x\n", hres);
+
if(hres != S_FALSE)
{
BOOL res = FALSE;
}
}
- hres = IServiceProvider_QueryService(serv_prov, &IID_IWindowForBindingUI, &IID_IWindowForBindingUI,
- (void**)&wfb_ui);
- if(SUCCEEDED(hres)) {
- HWND hwnd;
- const IID *iid_reason;
-
- if(security_problem)
- iid_reason = &IID_IHttpSecurity;
- else if(error == ERROR_INTERNET_INCORRECT_PASSWORD)
- iid_reason = &IID_IAuthenticate;
- else
- iid_reason = &IID_IWindowForBindingUI;
-
- hres = IWindowForBindingUI_GetWindow(wfb_ui, iid_reason, &hwnd);
- if(SUCCEEDED(hres) && hwnd)
- {
- DWORD res;
-
- res = InternetErrorDlg(hwnd, This->base.request, error,
- FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
- NULL);
-
- if(res == ERROR_INTERNET_FORCE_RETRY || res == ERROR_SUCCESS)
- hres = RPC_E_RETRY;
+ switch(error) {
+ case ERROR_INTERNET_SEC_CERT_REV_FAILED:
+ if(hres != S_FALSE) {
+ /* Silently ignore the error. We will get more detailed error from wininet anyway. */
+ set_security_flag(This, SECURITY_FLAG_IGNORE_REVOCATION);
+ hres = RPC_E_RETRY;
+ break;
+ }
+ /* fallthrough */
+ default:
+ hres = IServiceProvider_QueryService(serv_prov, &IID_IWindowForBindingUI, &IID_IWindowForBindingUI, (void**)&wfb_ui);
+ if(SUCCEEDED(hres)) {
+ const IID *iid_reason;
+
+ if(security_problem)
+ iid_reason = &IID_IHttpSecurity;
+ else if(error == ERROR_INTERNET_INCORRECT_PASSWORD)
+ iid_reason = &IID_IAuthenticate;
else
- hres = E_FAIL;
+ iid_reason = &IID_IWindowForBindingUI;
+
+ hres = IWindowForBindingUI_GetWindow(wfb_ui, iid_reason, &hwnd);
+ IWindowForBindingUI_Release(wfb_ui);
}
- IWindowForBindingUI_Release(wfb_ui);
- }
- IServiceProvider_Release(serv_prov);
+ if(FAILED(hres)) hwnd = NULL;
- if(hres == RPC_E_RETRY)
- return hres;
+ dlg_flags = FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA;
+ if(This->base.bindf & BINDF_NO_UI)
+ dlg_flags |= FLAGS_ERROR_UI_FLAGS_NO_UI;
+
+ res = InternetErrorDlg(hwnd, This->base.request, error, dlg_flags, NULL);
+ hres = res == ERROR_INTERNET_FORCE_RETRY || res == ERROR_SUCCESS ? RPC_E_RETRY : internet_error_to_hres(error);
+ }
- return internet_error_to_hres(error);
+ IServiceProvider_Release(serv_prov);
+ return hres;
}
static ULONG send_http_request(HttpProtocol *This)
HINTERNET internet_session, IInternetBindInfo *bind_info)
{
HttpProtocol *This = impl_from_Protocol(prot);
- LPWSTR addl_header = NULL, post_cookie = NULL;
+ WCHAR *addl_header = NULL, *post_cookie = NULL, *rootdoc_url = NULL;
IServiceProvider *service_provider = NULL;
IHttpNegotiate2 *http_negotiate2 = NULL;
BSTR url, host, user, pass, path;
LPOLESTR accept_mimes[257];
const WCHAR **accept_types;
BYTE security_id[512];
- DWORD len, port;
+ DWORD len, port, flags;
ULONG num, error;
BOOL res, b;
HRESULT hres;
return INET_E_CANNOT_CONNECT;
}
+ num = 0;
+ hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_ROOTDOC_URL, &rootdoc_url, 1, &num);
+ if(hres == S_OK && num) {
+ FIXME("Use root doc URL %s\n", debugstr_w(rootdoc_url));
+ CoTaskMemFree(rootdoc_url);
+ }
+
num = sizeof(accept_mimes)/sizeof(accept_mimes[0])-1;
hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_ACCEPT_MIMES, accept_mimes, num, &num);
if(hres == INET_E_USE_DEFAULT_SETTING) {
}
}
+ flags = INTERNET_ERROR_MASK_COMBINED_SEC_CERT;
+ res = InternetSetOptionW(This->base.request, INTERNET_OPTION_ERROR_MASK, &flags, sizeof(flags));
+ if(!res)
+ WARN("InternetSetOption(INTERNET_OPTION_ERROR_MASK) failed: %u\n", GetLastError());
+
b = TRUE;
res = InternetSetOptionW(This->base.request, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b));
if(!res)
- WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError());
+ WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %u\n", GetLastError());
do {
error = send_http_request(This);
- if(error == ERROR_IO_PENDING || error == ERROR_SUCCESS)
+ switch(error) {
+ case ERROR_IO_PENDING:
return S_OK;
-
- hres = handle_http_error(This, error);
-
+ case ERROR_SUCCESS:
+ /*
+ * If sending response ended synchronously, it means that we have the whole data
+ * available locally (most likely in cache).
+ */
+ return protocol_syncbinding(&This->base);
+ default:
+ hres = handle_http_error(This, error);
+ }
} while(hres == RPC_E_RETRY);
WARN("HttpSendRequest failed: %d\n", error);
This->http_negotiate = NULL;
}
- if(This->full_header) {
- heap_free(This->full_header);
- This->full_header = NULL;
- }
+ heap_free(This->full_header);
+ This->full_header = NULL;
}
static void HttpProtocol_on_error(Protocol *prot, DWORD error)
}
if(*ppv) {
- IInternetProtocol_AddRef(iface);
+ IInternetProtocolEx_AddRef(iface);
return S_OK;
}