Source code

Revision control

Copy as Markdown

Other Tools

// Copyright 2019 Google Inc. All rights reserved.↩
//↩
// Redistribution and use in source and binary forms, with or without↩
// modification, are permitted provided that the following conditions are↩
// met:↩
//↩
// * Redistributions of source code must retain the above copyright↩
// notice, this list of conditions and the following disclaimer.↩
// * Redistributions in binary form must reproduce the above↩
// copyright notice, this list of conditions and the following disclaimer↩
// in the documentation and/or other materials provided with the↩
// distribution.↩
// * Neither the name of Google Inc. nor the names of its↩
// contributors may be used to endorse or promote products derived from↩
// this software without specific prior written permission.↩
//↩
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS↩
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT↩
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR↩
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT↩
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,↩
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT↩
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,↩
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY↩
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT↩
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE↩
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.↩
#include "tools/windows/converter_exe/wininet_client.h"
#include <assert.h>↩
#include <stdlib.h>↩
#include <windows.h>↩
#include <wininet.h>↩
namespace crash {↩
namespace internal {↩
// This class implements HttpClient based on WinInet APIs.↩
class WinInetClient : public HttpClient {↩
public:↩
virtual ~WinInetClient() {}↩
virtual bool CrackUrl(const TCHAR* url,↩
DWORD flags,↩
TCHAR* scheme,↩
size_t scheme_buffer_length,↩
TCHAR* host,↩
size_t host_buffer_length,↩
TCHAR* uri,↩
size_t uri_buffer_length,↩
int* port) const;↩
virtual bool Open(const TCHAR* user_agent,↩
DWORD access_type,↩
const TCHAR* proxy_name,↩
const TCHAR* proxy_bypass,↩
HttpHandle* session_handle) const;↩
virtual bool Connect(HttpHandle session_handle,↩
const TCHAR* server,↩
int port,↩
HttpHandle* connection_handle) const;↩
virtual bool OpenRequest(HttpHandle connection_handle,↩
const TCHAR* verb,↩
const TCHAR* uri,↩
const TCHAR* version,↩
const TCHAR* referrer,↩
bool is_secure,↩
HttpHandle* request_handle) const;↩
virtual bool SendRequest(HttpHandle request_handle,↩
const TCHAR* headers,↩
DWORD headers_length) const;↩
virtual bool ReceiveResponse(HttpHandle request_handle) const;↩
virtual bool GetHttpStatusCode(HttpHandle request_handle,↩
int* status_code) const;↩
virtual bool GetContentLength(HttpHandle request_handle,↩
DWORD* content_length) const;↩
virtual bool ReadData(HttpHandle request_handle,↩
void* buffer,↩
DWORD buffer_length,↩
DWORD* bytes_read) const;↩
virtual bool Close(HttpHandle handle) const;↩
private:↩
static DWORD MapAccessType(DWORD access_type);↩
static HINTERNET ToHINTERNET(HttpHandle handle);↩
static HttpHandle FromHINTERNET(HINTERNET handle);↩
};↩
bool WinInetClient::CrackUrl(const TCHAR* url,↩
DWORD flags,↩
TCHAR* scheme,↩
size_t scheme_buffer_length,↩
TCHAR* host,↩
size_t host_buffer_length,↩
TCHAR* uri,↩
size_t uri_buffer_length,↩
int* port) const {↩
assert(url);↩
assert(scheme);↩
assert(host);↩
assert(uri);↩
assert(port);↩
URL_COMPONENTS url_comp = {0};↩
url_comp.dwStructSize = sizeof(url_comp);↩
url_comp.lpszScheme = scheme;↩
url_comp.dwSchemeLength = static_cast<DWORD>(scheme_buffer_length);↩
url_comp.lpszHostName = host;↩
url_comp.dwHostNameLength = static_cast<DWORD>(host_buffer_length);↩
url_comp.lpszUrlPath = uri;↩
url_comp.dwUrlPathLength = static_cast<DWORD>(uri_buffer_length);↩
bool result = !!::InternetCrackUrl(url, 0, flags, &url_comp);↩
if (result) {↩
*port = static_cast<int>(url_comp.nPort);↩
}↩
return result;↩
}↩
bool WinInetClient::Open(const TCHAR* user_agent,↩
DWORD access_type,↩
const TCHAR* proxy_name,↩
const TCHAR* proxy_bypass,↩
HttpHandle* session_handle) const {↩
*session_handle = FromHINTERNET(::InternetOpen(user_agent,↩
MapAccessType(access_type),↩
proxy_name,↩
proxy_bypass,↩
0));↩
return !!(*session_handle);↩
}↩
bool WinInetClient::Connect(HttpHandle session_handle,↩
const TCHAR* server,↩
int port,↩
HttpHandle* connection_handle) const {↩
assert(server);↩
// Uses NULL user name and password to connect. Always uses http service.↩
*connection_handle = FromHINTERNET(::InternetConnect(↩
ToHINTERNET(session_handle),↩
server,↩
static_cast<INTERNET_PORT>(port),↩
NULL,↩
NULL,↩
INTERNET_SERVICE_HTTP,↩
0,↩
0));↩
return !!(*connection_handle);↩
}↩
bool WinInetClient::OpenRequest(HttpHandle connection_handle,↩
const TCHAR* verb,↩
const TCHAR* uri,↩
const TCHAR* version,↩
const TCHAR* referrer,↩
bool is_secure,↩
HttpHandle* request_handle) const {↩
assert(connection_handle);↩
assert(verb);↩
assert(uri);↩
*request_handle = FromHINTERNET(::HttpOpenRequest(↩
ToHINTERNET(connection_handle),↩
verb,↩
uri,↩
version,↩
referrer,↩
NULL,↩
is_secure ? INTERNET_FLAG_SECURE : 0,↩
NULL));↩
return !!(*request_handle);↩
}↩
bool WinInetClient::SendRequest(HttpHandle request_handle,↩
const TCHAR* headers,↩
DWORD headers_length) const {↩
assert(request_handle);↩
return !!::HttpSendRequest(ToHINTERNET(request_handle),↩
headers,↩
headers_length,↩
NULL,↩
0);↩
}↩
bool WinInetClient::ReceiveResponse(HttpHandle) const {↩
return true;↩
}↩
bool WinInetClient::GetHttpStatusCode(HttpHandle request_handle,↩
int* status_code) const {↩
assert(request_handle);↩
TCHAR http_status_string[4] = {0};↩
DWORD http_status_string_size = sizeof(http_status_string);↩
if (!::HttpQueryInfo(ToHINTERNET(request_handle),↩
HTTP_QUERY_STATUS_CODE,↩
static_cast<void *>(&http_status_string),↩
&http_status_string_size,↩
0)) {↩
return false;↩
}↩
*status_code = _tcstol(http_status_string, NULL, 10);↩
return true;↩
}↩
bool WinInetClient::GetContentLength(HttpHandle request_handle,↩
DWORD* content_length) const {↩
assert(request_handle);↩
assert(content_length);↩
TCHAR content_length_string[11];↩
DWORD content_length_string_size = sizeof(content_length_string);↩
if (!::HttpQueryInfo(ToHINTERNET(request_handle),↩
HTTP_QUERY_CONTENT_LENGTH,↩
static_cast<void *>(&content_length_string),↩
&content_length_string_size,↩
0)) {↩
*content_length = kUnknownContentLength;↩
} else {↩
*content_length = wcstol(content_length_string, NULL, 10);↩
}↩
return true;↩
}↩
bool WinInetClient::ReadData(HttpHandle request_handle,↩
void* buffer,↩
DWORD buffer_length,↩
DWORD* bytes_read) const {↩
assert(request_handle);↩
assert(buffer);↩
assert(bytes_read);↩
DWORD bytes_read_local = 0;↩
if (!::InternetReadFile(ToHINTERNET(request_handle),↩
buffer,↩
buffer_length,↩
&bytes_read_local)) {↩
return false;↩
}↩
*bytes_read = bytes_read_local;↩
return true;↩
}↩
bool WinInetClient::Close(HttpHandle handle) const {↩
assert(handle);↩
return !!::InternetCloseHandle(ToHINTERNET(handle));↩
}↩
DWORD WinInetClient::MapAccessType(DWORD access_type) {↩
switch (static_cast<AccessType>(access_type)) {↩
case ACCESS_TYPE_PRECONFIG:↩
default:↩
return INTERNET_OPEN_TYPE_PRECONFIG;↩
case ACCESS_TYPE_DIRECT:↩
return INTERNET_OPEN_TYPE_DIRECT;↩
case ACCESS_TYPE_PROXY:↩
return INTERNET_OPEN_TYPE_PROXY;↩
}↩
}↩
HINTERNET WinInetClient::ToHINTERNET(HttpHandle handle) {↩
return static_cast<HINTERNET>(handle);↩
}↩
HttpHandle WinInetClient::FromHINTERNET(HINTERNET handle) {↩
return static_cast<HttpHandle>(handle);↩
}↩
} // namespace internal↩
HttpClient* CreateWinInetClient(const TCHAR*) {↩
return new internal::WinInetClient();↩
}↩
} // namespace crash↩