diff options
Diffstat (limited to 'externals/breakpad/src/tools/windows/converter_exe/wininet_client.cc')
-rw-r--r-- | externals/breakpad/src/tools/windows/converter_exe/wininet_client.cc | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/externals/breakpad/src/tools/windows/converter_exe/wininet_client.cc b/externals/breakpad/src/tools/windows/converter_exe/wininet_client.cc new file mode 100644 index 0000000000..571ab86c66 --- /dev/null +++ b/externals/breakpad/src/tools/windows/converter_exe/wininet_client.cc @@ -0,0 +1,282 @@ +// Copyright 2019 Google LLC +// +// 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 LLC 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. + +#ifdef HAVE_CONFIG_H +#include <config.h> // Must come first +#endif + +#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 |