static HRESULT GopherProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags, HINTERNET internet_session, IInternetBindInfo *bind_info) { GopherProtocol *This = impl_from_Protocol(prot); BSTR url; HRESULT hres; hres = IUri_GetAbsoluteUri(uri, &url); if(FAILED(hres)) return hres; This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0, request_flags, (DWORD_PTR)&This->base); SysFreeString(url); if (!This->base.request && GetLastError() != ERROR_IO_PENDING) { WARN("InternetOpenUrl failed: %d\n", GetLastError()); return INET_E_RESOURCE_NOT_FOUND; } return S_OK; }
static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags, HINTERNET internet_session, IInternetBindInfo *bind_info) { HttpProtocol *This = impl_from_Protocol(prot); 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, flags; ULONG num, error; BOOL res, b; HRESULT hres; static const WCHAR wszBindVerb[BINDVERB_CUSTOM][5] = {{'G','E','T',0}, {'P','O','S','T',0}, {'P','U','T',0}}; hres = IUri_GetPort(uri, &port); if(FAILED(hres)) return hres; hres = IUri_GetHost(uri, &host); if(FAILED(hres)) return hres; hres = IUri_GetUserName(uri, &user); if(SUCCEEDED(hres)) { hres = IUri_GetPassword(uri, &pass); if(SUCCEEDED(hres)) { This->base.connection = InternetConnectW(internet_session, host, port, user, pass, INTERNET_SERVICE_HTTP, This->https ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)&This->base); SysFreeString(pass); } SysFreeString(user); } SysFreeString(host); if(FAILED(hres)) return hres; if(!This->base.connection) { WARN("InternetConnect failed: %d\n", GetLastError()); 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) { static const WCHAR default_accept_mimeW[] = {'*','/','*',0}; static const WCHAR *default_accept_mimes[] = {default_accept_mimeW, NULL}; accept_types = default_accept_mimes; num = 0; }else if(hres == S_OK) { accept_types = (const WCHAR**)accept_mimes; }else { WARN("GetBindString BINDSTRING_ACCEPT_MIMES failed: %08x\n", hres); return INET_E_NO_VALID_MEDIA; } accept_mimes[num] = 0; if(This->https) request_flags |= INTERNET_FLAG_SECURE; hres = IUri_GetPathAndQuery(uri, &path); if(SUCCEEDED(hres)) { This->base.request = HttpOpenRequestW(This->base.connection, This->base.bind_info.dwBindVerb < BINDVERB_CUSTOM ? wszBindVerb[This->base.bind_info.dwBindVerb] : This->base.bind_info.szCustomVerb, path, NULL, NULL, accept_types, request_flags, (DWORD_PTR)&This->base); SysFreeString(path); } while(num--) CoTaskMemFree(accept_mimes[num]); if(FAILED(hres)) return hres; if (!This->base.request) { WARN("HttpOpenRequest failed: %d\n", GetLastError()); return INET_E_RESOURCE_NOT_FOUND; } hres = IInternetProtocolSink_QueryInterface(This->base.protocol_sink, &IID_IServiceProvider, (void **)&service_provider); if (hres != S_OK) { WARN("IInternetProtocolSink_QueryInterface IID_IServiceProvider failed: %08x\n", hres); return hres; } hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate, &IID_IHttpNegotiate, (void **)&This->http_negotiate); if (hres != S_OK) { WARN("IServiceProvider_QueryService IID_IHttpNegotiate failed: %08x\n", hres); IServiceProvider_Release(service_provider); return hres; } hres = IUri_GetAbsoluteUri(uri, &url); if(FAILED(hres)) { IServiceProvider_Release(service_provider); return hres; } hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, url, default_headersW, 0, &addl_header); SysFreeString(url); if(hres != S_OK) { WARN("IHttpNegotiate_BeginningTransaction failed: %08x\n", hres); IServiceProvider_Release(service_provider); return hres; } len = addl_header ? strlenW(addl_header) : 0; This->full_header = heap_alloc(len*sizeof(WCHAR)+sizeof(default_headersW)); if(!This->full_header) { IServiceProvider_Release(service_provider); return E_OUTOFMEMORY; } if(len) memcpy(This->full_header, addl_header, len*sizeof(WCHAR)); CoTaskMemFree(addl_header); memcpy(This->full_header+len, default_headersW, sizeof(default_headersW)); hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2, &IID_IHttpNegotiate2, (void **)&http_negotiate2); IServiceProvider_Release(service_provider); if(hres != S_OK) { WARN("IServiceProvider_QueryService IID_IHttpNegotiate2 failed: %08x\n", hres); /* No goto done as per native */ }else { len = sizeof(security_id)/sizeof(security_id[0]); hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, security_id, &len, 0); IHttpNegotiate2_Release(http_negotiate2); if (hres != S_OK) WARN("IHttpNegotiate2_GetRootSecurityId failed: %08x\n", hres); } /* FIXME: Handle security_id. Native calls undocumented function IsHostInProxyBypassList. */ if(This->base.bind_info.dwBindVerb == BINDVERB_POST) { num = 0; hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_POST_COOKIE, &post_cookie, 1, &num); if(hres == S_OK && num) { if(!InternetSetOptionW(This->base.request, INTERNET_OPTION_SECONDARY_CACHE_KEY, post_cookie, lstrlenW(post_cookie))) WARN("InternetSetOption INTERNET_OPTION_SECONDARY_CACHE_KEY failed: %d\n", GetLastError()); CoTaskMemFree(post_cookie); } } 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: %u\n", GetLastError()); do { error = send_http_request(This); switch(error) { case ERROR_IO_PENDING: return S_OK; 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); return hres; }