#include "CookieManager.h"
#include <UrlMon.h>
#include <wininet.h>
#include "errorcodes.h"
#include "logging.h"
#include "BrowserCookie.h"
#include "HookProcessor.h"
#include "messages.h"
#include "StringUtilities.h"
#define TICKS_PER_SECOND 10000000
#define UNIX_TIME_OFFSET_SECONDS 11644473600L
namespace webdriver {
struct CookieSendMessageInfo {
HWND window_handle;
unsigned int message;
};
CookieManager::CookieManager(void) {
this->window_handle_ = NULL;
}
CookieManager::~CookieManager(void) {
}
void CookieManager::Initialize(HWND window_handle) {
LOG(TRACE) << "Entering CookieManager::Initialize";
this->window_handle_ = window_handle;
}
bool CookieManager::IsAdvancedCookiesApi() {
FARPROC address = NULL;
HMODULE wininet_handle = ::GetModuleHandle(L"wininet");
if (wininet_handle) {
address = ::GetProcAddress(wininet_handle, "InternetGetCookieEx2");
}
return address != NULL;
}
int CookieManager::SetCookie(const std::string& url,
const BrowserCookie& cookie) {
std::string full_data = url + "|" + cookie.ToString();
WPARAM set_flags = 0;
if (cookie.is_httponly()) {
set_flags = INTERNET_COOKIE_HTTPONLY;
}
HookSettings hook_settings;
hook_settings.hook_procedure_name = "CookieWndProc";
hook_settings.hook_procedure_type = WH_CALLWNDPROC;
hook_settings.window_handle = this->window_handle_;
hook_settings.communication_type = OneWay;
HookProcessor hook;
if (!hook.CanSetWindowsHook(this->window_handle_)) {
LOG(WARN) << "Cannot set cookie because driver and browser are not the "
<< "same bit-ness.";
return EUNHANDLEDERROR;
}
hook.Initialize(hook_settings);
hook.PushData(StringUtilities::ToWString(full_data));
::SendMessage(this->window_handle_, WD_SET_COOKIE, set_flags, NULL);
int status = HookProcessor::GetDataBufferSize();
if (status != 0) {
LOG(WARN) << "Setting cookie encountered error " << status;
return EINVALIDCOOKIEDOMAIN;
}
return WD_SUCCESS;
}
int CookieManager::GetCookies(const std::string& url,
std::vector<BrowserCookie>* all_cookies) {
LOG(TRACE) << "Entering CookieManager::GetCookies";
std::wstring wide_url = StringUtilities::ToWString(url);
CComPtr<IUri> parsed_url;
::CreateUri(wide_url.c_str(), Uri_CREATE_ALLOW_RELATIVE, 0, &parsed_url);
DWORD url_scheme = 0;
parsed_url->GetScheme(&url_scheme);
bool is_secure_url = URL_SCHEME_HTTPS == url_scheme;
HookSettings hook_settings;
hook_settings.hook_procedure_name = "CookieWndProc";
hook_settings.hook_procedure_type = WH_CALLWNDPROC;
hook_settings.window_handle = this->window_handle_;
hook_settings.communication_type = TwoWay;
HookProcessor hook;
if (!hook.CanSetWindowsHook(this->window_handle_)) {
LOG(WARN) << "Cannot get cookies because driver and browser are not the "
<< "same bit-ness.";
return EUNHANDLEDERROR;
}
hook.Initialize(hook_settings);
bool supports_advanced_api = this->IsAdvancedCookiesApi();
if (supports_advanced_api) {
std::wstring raw_cookie_data =
this->SendGetCookieMessage(wide_url,
WD_GET_ALL_COOKIES,
&hook);
std::string all_cookies_list = StringUtilities::ToString(raw_cookie_data);
std::map<std::string, BrowserCookie> cookies;
this->ParseCookieList(all_cookies_list,
is_secure_url,
&cookies);
std::map<std::string, BrowserCookie>::const_iterator cookie_iterator;
for (cookie_iterator = cookies.begin();
cookie_iterator != cookies.end();
++cookie_iterator) {
all_cookies->push_back(cookie_iterator->second);
}
} else {
std::wstring scriptable_cookie_string =
this->SendGetCookieMessage(wide_url,
WD_GET_SCRIPTABLE_COOKIES,
&hook);
std::map<std::string, std::string> scriptable_cookies;
this->ParseCookieString(scriptable_cookie_string, &scriptable_cookies);
std::wstring insecure_cookie_string =
this->SendGetCookieMessage(wide_url,
WD_GET_HTTPONLY_COOKIES,
&hook);
std::map<std::string, std::string> insecure_cookies;
this->ParseCookieString(insecure_cookie_string, &insecure_cookies);
std::wstring secure_cookie_string =
this->SendGetCookieMessage(wide_url,
WD_GET_SECURE_COOKIES,
&hook);
std::map<std::string, std::string> secure_cookies;
this->ParseCookieString(secure_cookie_string, &secure_cookies);
std::wstring file_list =
this->SendGetCookieMessage(wide_url,
WD_GET_COOKIE_CACHE_FILES,
&hook);
std::vector<std::wstring> files;
StringUtilities::Split(file_list, L"|", &files);
std::map<std::string, BrowserCookie> persistent_cookies;
std::vector<std::wstring>::const_iterator file_iterator;
for (file_iterator = files.begin();
file_iterator != files.end();
++file_iterator) {
std::string cookie_file_contents = this->ReadCookieFile(*file_iterator);
this->ParseCookieList(cookie_file_contents,
is_secure_url,
&persistent_cookies);
}
std::map<std::string, std::string>::const_iterator it = secure_cookies.begin();
for (; it != secure_cookies.end(); ++it) {
BrowserCookie browser_cookie;
if (persistent_cookies.find(it->first) != persistent_cookies.end()) {
browser_cookie = persistent_cookies[it->first];
} else {
browser_cookie.set_name(it->first);
browser_cookie.set_value(it->second);
browser_cookie.set_is_httponly(scriptable_cookies.find(it->first) == scriptable_cookies.end());
browser_cookie.set_is_secure(insecure_cookies.find(it->first) == insecure_cookies.end());
}
all_cookies->push_back(browser_cookie);
}
}
return WD_SUCCESS;
}
bool CookieManager::DeleteCookie(const std::string& url,
const BrowserCookie& cookie) {
std::wstring wide_url = StringUtilities::ToWString(url);
CComPtr<IUri> uri_pointer;
::CreateUri(wide_url.c_str(), Uri_CREATE_ALLOW_RELATIVE, 0, &uri_pointer);
CComBSTR host_bstr;
uri_pointer->GetHost(&host_bstr);
std::wstring wide_domain = host_bstr;
CComBSTR path_bstr;
uri_pointer->GetPath(&path_bstr);
std::wstring wide_path = path_bstr;
std::string domain = StringUtilities::ToString(wide_domain);
std::string path = StringUtilities::ToString(wide_path);
BrowserCookie recursive_cookie = cookie.Copy();
recursive_cookie.set_domain(domain);
recursive_cookie.set_path(path);
recursive_cookie.set_value("deleted");
recursive_cookie.set_expiration_time(1000);
return this->RecursivelyDeleteCookie(url, recursive_cookie);
}
bool CookieManager::RecursivelyDeleteCookie(const std::string& url,
const BrowserCookie& cookie) {
BrowserCookie recursive_cookie = cookie.Copy();
recursive_cookie.set_domain("." + cookie.domain());
return this->RecurseCookiePath(url, recursive_cookie);
}
bool CookieManager::RecurseCookiePath(const std::string& url,
const BrowserCookie& cookie) {
size_t number_of_characters = 0;
size_t slash_index = cookie.path().find_last_of('/');
size_t final_index = cookie.path().size() - 1;
if (slash_index == final_index) {
number_of_characters = slash_index;
}
else {
number_of_characters = slash_index + 1;
}
if (slash_index != std::string::npos) {
BrowserCookie path_cookie = cookie.Copy();
path_cookie.set_path(cookie.path().substr(0, number_of_characters));
bool deleted = this->RecurseCookiePath(url, path_cookie);
}
return this->RecurseCookieDomain(url, cookie);
}
bool CookieManager::RecurseCookieDomain(const std::string& url,
const BrowserCookie& cookie) {
int status = this->SetCookie(url, cookie);
size_t dot_index = cookie.domain().find_first_of('.');
if (dot_index == 0) {
BrowserCookie first_dot_cookie = cookie.Copy();
first_dot_cookie.set_domain(cookie.domain().substr(1));
return this->RecurseCookieDomain(url, first_dot_cookie);
} else if (dot_index != std::string::npos) {
BrowserCookie no_dot_cookie = cookie.Copy();
no_dot_cookie.set_domain(cookie.domain().substr(dot_index));
return this->RecurseCookieDomain(url, no_dot_cookie);
}
BrowserCookie no_domain_cookie = cookie.Copy();
no_domain_cookie.set_domain("");
status = this->SetCookie(url, no_domain_cookie);
return status == WD_SUCCESS;
}
std::string CookieManager::ReadCookieFile(const std::wstring& file_name) {
LOG(TRACE) << "Entering CookieManager::ReadCookieFile";
HANDLE file_handle = ::CreateFile(file_name.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
DWORD file_size_high = 0;
DWORD file_size_low = ::GetFileSize(file_handle, &file_size_high);
std::vector<char> file_content(file_size_low + 1);
DWORD bytes_read = 0;
::ReadFile(file_handle, &file_content[0], file_size_low, &bytes_read, NULL);
::CloseHandle(file_handle);
file_content[bytes_read - 1] = '\0';
std::string cookie_file_contents = &file_content[0];
return cookie_file_contents;
}
void CookieManager::ParseCookieList(const std::string& cookie_file_contents,
const bool include_secure_cookies,
std::map<std::string, BrowserCookie>* cookies) {
LOG(TRACE) << "Entering CookieManager::ParseCookieList";
std::vector<std::string> persistent_cookie_strings;
StringUtilities::Split(cookie_file_contents,
"\n*\n",
&persistent_cookie_strings);
std::vector<std::string>::const_iterator cookie_string_iterator;
for (cookie_string_iterator = persistent_cookie_strings.begin();
cookie_string_iterator != persistent_cookie_strings.end();
++cookie_string_iterator) {
BrowserCookie persistent_cookie =
this->ParseSingleCookie(*cookie_string_iterator);
if (include_secure_cookies || !persistent_cookie.is_secure()) {
cookies->insert(
std::pair<std::string, BrowserCookie>(persistent_cookie.name(),
persistent_cookie));
}
}
}
BrowserCookie CookieManager::ParseSingleCookie(const std::string& cookie) {
LOG(TRACE) << "Entering CookieManager::ParsePersistentCookieInfo";
std::vector<std::string> cookie_parts;
StringUtilities::Split(cookie, "\n", &cookie_parts);
BrowserCookie cookie_to_return;
cookie_to_return.set_name(cookie_parts[0]);
cookie_to_return.set_value(cookie_parts[1]);
size_t position = cookie_parts[2].find_first_of("/");
cookie_to_return.set_domain(cookie_parts[2].substr(0, position));
cookie_to_return.set_path(cookie_parts[2].substr(position));
int flags = atoi(cookie_parts[3].c_str());
cookie_to_return.set_is_secure(INTERNET_COOKIE_IS_SECURE == (INTERNET_COOKIE_IS_SECURE & flags));
cookie_to_return.set_is_httponly(INTERNET_COOKIE_HTTPONLY == (INTERNET_COOKIE_HTTPONLY & flags));
if (cookie_parts[4].size() > 0 && cookie_parts[5].size() > 0) {
unsigned long expiry_time_low = strtoul(cookie_parts[4].c_str(), NULL, 10);
unsigned long expiry_time_high = strtoul(cookie_parts[5].c_str(), NULL, 10);
unsigned long long expiration_time = (expiry_time_high * static_cast<long long>(pow(2.0, 32))) + expiry_time_low;
unsigned long cookie_expiration_time = static_cast<unsigned long>((expiration_time / TICKS_PER_SECOND) - UNIX_TIME_OFFSET_SECONDS);
cookie_to_return.set_expiration_time(cookie_expiration_time);
}
return cookie_to_return;
}
void CookieManager::ParseCookieString(const std::wstring& cookie_string,
std::map<std::string, std::string>* cookies) {
LOG(TRACE) << "Entering CookieManager::ParseCookieString";
std::wstring cookie_string_copy = cookie_string;
while (cookie_string_copy.size() > 0) {
size_t cookie_delimiter_pos = cookie_string_copy.find(L"; ");
std::wstring cookie = cookie_string_copy.substr(0, cookie_delimiter_pos);
if (cookie_delimiter_pos == std::wstring::npos) {
cookie_string_copy = L"";
} else {
cookie_string_copy = cookie_string_copy.substr(cookie_delimiter_pos + 2);
}
size_t cookie_separator_pos(cookie.find_first_of(L"="));
std::string cookie_name(StringUtilities::ToString(cookie.substr(0, cookie_separator_pos)));
std::string cookie_value(StringUtilities::ToString(cookie.substr(cookie_separator_pos + 1)));
cookies->insert(std::pair<std::string, std::string>(cookie_name, cookie_value));
}
}
std::wstring CookieManager::SendGetCookieMessage(const std::wstring& url,
const unsigned int message,
HookProcessor* hook) {
LOG(TRACE) << "Entering CookieManager::SendGetCookieMessage";
hook->PushData(url);
CookieSendMessageInfo info;
info.window_handle = this->window_handle_;
info.message = message;
unsigned int thread_id = 0;
HANDLE thread_handle = reinterpret_cast<HANDLE>(_beginthreadex(NULL,
0,
&CookieManager::ThreadProc,
reinterpret_cast<void*>(&info),
0,
&thread_id));
if (thread_handle != NULL) {
::CloseHandle(thread_handle);
} else {
LOGERR(DEBUG) << "Unable to create thread";
}
std::vector<char> buffer(0);
int bytes = hook->PullData(&buffer);
std::wstring cookies = reinterpret_cast<const wchar_t*>(&buffer[0]);
return cookies;
}
unsigned int WINAPI CookieManager::ThreadProc(LPVOID lpParameter) {
LOG(TRACE) << "Entering CookieManager::ThreadProc";
CookieSendMessageInfo* info = reinterpret_cast<CookieSendMessageInfo*>(lpParameter);
DWORD process_id = ::GetCurrentProcessId();
LRESULT result = ::SendMessage(info->window_handle,
info->message,
process_id,
NULL);
return 0;
}
}
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
PWSTR pwszName;
PWSTR pwszValue;
PWSTR pwszDomain;
PWSTR pwszPath;
DWORD dwFlags;
FILETIME ftExpires;
BOOL fExpiresSet;
} INTERNETCOOKIE2;
typedef void* (__stdcall *InternetFreeCookiesProc)(INTERNETCOOKIE2*, DWORD);
typedef DWORD(__stdcall *InternetGetCookieEx2Proc)(PCWSTR, PCWSTR, DWORD, INTERNETCOOKIE2**, PDWORD);
LRESULT CALLBACK CookieWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
CWPSTRUCT* call_window_proc_struct = reinterpret_cast<CWPSTRUCT*>(lParam);
if (WM_COPYDATA == call_window_proc_struct->message) {
COPYDATASTRUCT* data = reinterpret_cast<COPYDATASTRUCT*>(call_window_proc_struct->lParam);
webdriver::HookProcessor::CopyDataToBuffer(data->cbData, data->lpData);
} else if (WD_GET_ALL_COOKIES == call_window_proc_struct->message) {
std::wstring url = webdriver::HookProcessor::CopyWStringFromBuffer();
int driver_process_id = static_cast<int>(call_window_proc_struct->wParam);
CComPtr<IUri> uri_pointer;
HRESULT hr = ::CreateUri(url.c_str(), Uri_CREATE_ALLOW_RELATIVE, 0, &uri_pointer);
DWORD scheme = 0;
uri_pointer->GetScheme(&scheme);
CComBSTR scheme_bstr;
uri_pointer->GetSchemeName(&scheme_bstr);
CComBSTR host_bstr;
uri_pointer->GetHost(&host_bstr);
CComBSTR path_bstr;
uri_pointer->GetPath(&path_bstr);
std::wstring parsed_uri = scheme_bstr;
parsed_uri.append(L"://");
parsed_uri.append(host_bstr);
parsed_uri.append(path_bstr);
InternetGetCookieEx2Proc get_cookie_proc = NULL;
InternetFreeCookiesProc free_cookies_proc = NULL;
HMODULE wininet_handle = ::GetModuleHandle(L"wininet");
if (wininet_handle) {
get_cookie_proc = reinterpret_cast<InternetGetCookieEx2Proc>(::GetProcAddress(wininet_handle, "InternetGetCookieEx2"));
free_cookies_proc = reinterpret_cast<InternetFreeCookiesProc>(::GetProcAddress(wininet_handle, "InternetFreeCookies"));
}
DWORD cookie_count = 0;
INTERNETCOOKIE2* cookie_pointer = NULL;
DWORD success = 1;
if (get_cookie_proc) {
success = get_cookie_proc(parsed_uri.c_str(),
NULL,
INTERNET_COOKIE_NON_SCRIPT,
&cookie_pointer,
&cookie_count);
}
if (success == 0) {
std::wstring all_cookies = L"";
for (DWORD cookie_index = 0; cookie_index < cookie_count; ++cookie_index) {
if (all_cookies.size() > 0) {
all_cookies.append(L"\n*\n");
}
INTERNETCOOKIE2* current_cookie = cookie_pointer + cookie_index;
std::wstring cookie_name = L"";
if (current_cookie->pwszName) {
cookie_name = current_cookie->pwszName;
}
std::wstring cookie_value = L"";
if (current_cookie->pwszValue) {
cookie_value = current_cookie->pwszValue;
}
std::wstring cookie_domain = L"";
if (current_cookie->pwszDomain) {
cookie_domain = current_cookie->pwszDomain;
}
std::wstring cookie_path = L"";
if (current_cookie->pwszPath) {
cookie_path = current_cookie->pwszPath;
}
DWORD flags = current_cookie->dwFlags;
FILETIME expires = current_cookie->ftExpires;
all_cookies.append(cookie_name).append(L"\n");
all_cookies.append(cookie_value).append(L"\n");
all_cookies.append(cookie_domain).append(L"/").append(cookie_path).append(L"\n");
all_cookies.append(std::to_wstring(flags)).append(L"\n");
if (current_cookie->fExpiresSet) {
all_cookies.append(std::to_wstring(expires.dwLowDateTime)).append(L"\n");
all_cookies.append(std::to_wstring(expires.dwHighDateTime)).append(L"\n");
} else {
all_cookies.append(L"\n\n");
}
}
free_cookies_proc(cookie_pointer, cookie_count);
webdriver::HookProcessor::CopyWStringToBuffer(all_cookies);
} else {
webdriver::HookProcessor::SetDataBufferSize(sizeof(wchar_t));
}
webdriver::HookProcessor::WriteBufferToPipe(driver_process_id);
} else if (WD_GET_HTTPONLY_COOKIES == call_window_proc_struct->message ||
WD_GET_SCRIPTABLE_COOKIES == call_window_proc_struct->message ||
WD_GET_SECURE_COOKIES == call_window_proc_struct->message) {
std::wstring url = webdriver::HookProcessor::CopyWStringFromBuffer();
int driver_process_id = static_cast<int>(call_window_proc_struct->wParam);
DWORD get_cookie_flags = 0;
if (WD_GET_HTTPONLY_COOKIES == call_window_proc_struct->message ||
WD_GET_SECURE_COOKIES == call_window_proc_struct->message) {
get_cookie_flags = INTERNET_COOKIE_HTTPONLY;
}
CComPtr<IUri> uri_pointer;
HRESULT hr = ::CreateUri(url.c_str(), Uri_CREATE_ALLOW_RELATIVE, 0, &uri_pointer);
DWORD scheme = 0;
uri_pointer->GetScheme(&scheme);
CComBSTR scheme_bstr;
uri_pointer->GetSchemeName(&scheme_bstr);
CComBSTR host_bstr;
uri_pointer->GetHost(&host_bstr);
CComBSTR path_bstr;
uri_pointer->GetPath(&path_bstr);
std::wstring parsed_uri = L"http";
if ((WD_GET_SECURE_COOKIES == call_window_proc_struct->message ||
WD_GET_SCRIPTABLE_COOKIES == call_window_proc_struct->message) &&
URL_SCHEME_HTTPS == scheme) {
parsed_uri.append(L"s");
}
parsed_uri.append(L"://");
parsed_uri.append(host_bstr);
parsed_uri.append(path_bstr);
DWORD buffer_size = 0;
BOOL success = ::InternetGetCookieEx(parsed_uri.c_str(),
NULL,
NULL,
&buffer_size,
get_cookie_flags,
NULL);
if (success) {
webdriver::HookProcessor::SetDataBufferSize(buffer_size);
::InternetGetCookieEx(parsed_uri.c_str(),
NULL,
reinterpret_cast<LPTSTR>(webdriver::HookProcessor::GetDataBufferAddress()),
&buffer_size,
get_cookie_flags,
NULL);
webdriver::HookProcessor::WriteBufferToPipe(driver_process_id);
} else {
if (ERROR_NO_MORE_ITEMS == ::GetLastError()) {
webdriver::HookProcessor::SetDataBufferSize(sizeof(wchar_t));
webdriver::HookProcessor::WriteBufferToPipe(driver_process_id);
}
}
} else if (WD_GET_COOKIE_CACHE_FILES == call_window_proc_struct->message) {
int driver_process_id = static_cast<int>(call_window_proc_struct->wParam);
std::wstring file_list = L"";
std::wstring url = webdriver::HookProcessor::CopyWStringFromBuffer();
CComPtr<IUri> uri_pointer;
HRESULT hr = ::CreateUri(url.c_str(), Uri_CREATE_ALLOW_RELATIVE, 0, &uri_pointer);
CComBSTR host_bstr;
uri_pointer->GetHost(&host_bstr);
CComBSTR path_bstr;
uri_pointer->GetPath(&path_bstr);
std::wstring parsed_uri = host_bstr;
parsed_uri.append(path_bstr);
HANDLE cache_enum_handle = NULL;
DWORD entry_size = 2048;
LPINTERNET_CACHE_ENTRY_INFO entry = NULL;
std::vector<char> entry_buffer(entry_size);
entry = reinterpret_cast<INTERNET_CACHE_ENTRY_INFO*>(&entry_buffer[0]);
cache_enum_handle = ::FindFirstUrlCacheEntry(L"cookie:",
entry,
&entry_size);
if (cache_enum_handle == NULL &&
ERROR_INSUFFICIENT_BUFFER == ::GetLastError()) {
entry_buffer.resize(entry_size);
entry = reinterpret_cast<INTERNET_CACHE_ENTRY_INFO*>(&entry_buffer[0]);
cache_enum_handle = ::FindFirstUrlCacheEntry(L"cookie:",
entry,
&entry_size);
}
while (cache_enum_handle != NULL) {
if (COOKIE_CACHE_ENTRY == (entry->CacheEntryType & COOKIE_CACHE_ENTRY)) {
std::wstring name = entry->lpszSourceUrlName;
size_t name_separator_pos(name.find_first_of(L"@"));
std::wstring domain = name.substr(name_separator_pos + 1);
if (parsed_uri.find(domain) != std::wstring::npos) {
if (file_list.size() > 0) {
file_list.append(L"|");
}
file_list.append(entry->lpszLocalFileName);
}
}
BOOL success = ::FindNextUrlCacheEntry(cache_enum_handle,
entry,
&entry_size);
if (!success) {
DWORD error = ::GetLastError();
if (ERROR_INSUFFICIENT_BUFFER == error) {
entry_buffer.resize(entry_size);
BOOL other_success = ::FindNextUrlCacheEntry(cache_enum_handle,
entry,
&entry_size);
} else if (ERROR_NO_MORE_ITEMS == error) {
::FindCloseUrlCache(cache_enum_handle);
cache_enum_handle = NULL;
}
}
}
webdriver::HookProcessor::CopyWStringToBuffer(file_list);
webdriver::HookProcessor::WriteBufferToPipe(driver_process_id);
} else if (WD_SET_COOKIE == call_window_proc_struct->message) {
DWORD set_cookie_flags = static_cast<DWORD>(call_window_proc_struct->wParam);
std::wstring cookie_data = webdriver::HookProcessor::CopyWStringFromBuffer();
size_t url_separator_pos = cookie_data.find_first_of(L"|");
std::wstring url = cookie_data.substr(0, url_separator_pos);
std::wstring cookie = cookie_data.substr(url_separator_pos + 1);
CComPtr<IUri> uri_pointer;
HRESULT hr = ::CreateUri(url.c_str(), Uri_CREATE_ALLOW_RELATIVE, 0, &uri_pointer);
CComBSTR scheme_bstr;
uri_pointer->GetSchemeName(&scheme_bstr);
CComBSTR host_bstr;
uri_pointer->GetHost(&host_bstr);
std::wstring parsed_uri = scheme_bstr;
parsed_uri.append(L"://");
parsed_uri.append(host_bstr);
DWORD cookie_set = ::InternetSetCookieEx(parsed_uri.c_str(),
NULL,
cookie.c_str(),
set_cookie_flags,
NULL);
if (cookie_set) {
webdriver::HookProcessor::SetDataBufferSize(0);
} else {
DWORD error = ::GetLastError();
webdriver::HookProcessor::SetDataBufferSize(error);
}
}
return ::CallNextHookEx(NULL, nCode, wParam, lParam);
}
#ifdef __cplusplus
}
#endif