#pragma once
#include <windows.h>
#include <MsHTML.h>
#include <atlcomcli.h>
#include <oleacc.h>
#include <Tlhelp32.h>
#include <WtsApi32.h>
#pragma comment(lib,"Wtsapi32.lib")
#include <string>
#include <vector>
#include <codecvt>
typedef struct _window_info
{
HWND h;
std::wstring process;
std::wstring title;
std::wstring class_name;
int pid;
int x;
int y;
int width;
int height;
}window_info, * pwindow_info;
typedef struct _ie_window_info_
{
std::wstring type;
std::wstring name;
std::wstring value;
}ie_window_info, * pie_window_info;
namespace _ie_control
{
bool initialize();
void release();
const wchar_t* get_wchar(HWND h, wchar_t* str, int size);
std::wstring string_to_wstring(std::string str);
std::string wstring_to_string(std::wstring wstr);
std::vector<window_info> get_iexplore_process();
HWND get_ie_window_handle(HWND h);
std::wstring get_ie_url(HWND h);
bool is_ie_window(HWND h);
IHTMLDocument2* get_ie_doc_interface_ex(HWND h);
std::vector<std::wstring> get_ie_password(IHTMLDocument2* doc);
ie_window_info get_ie_control_information_by_point(IHTMLDocument2* doc, unsigned int x, unsigned int y);
bool get_ie_source_code(IHTMLDocument2* doc, wchar_t* source, unsigned int size);
std::vector<ie_window_info> enum_ie_window_control(IHTMLDocument2* doc);
bool set_ie_control_text(IHTMLDocument2* doc, std::wstring type, std::wstring name, std::wstring value);
bool submit_form(IHTMLDocument2* doc);
}
#include "ie_control.h"
static std::vector<int> get_process_id(std::wstring session_name, std::wstring application_name)
{
std::vector<int> result;
DWORD dwCount = 0;
PWTS_PROCESS_INFOW pi = { 0 };
DWORD dwSize = 0;
wchar_t username[128] = { 0 };
SID_NAME_USE nameuse = SidTypeUser;
if (WTSEnumerateProcessesW(NULL, 0, 1, &pi, &dwCount))
{
for (DWORD i = 0; i < dwCount; i++)
{
dwSize = 128;
memset(username, 0, sizeof(wchar_t) * 128);
if (LookupAccountSidW(NULL, pi[i].pUserSid, username, &dwSize, NULL, &dwSize, &nameuse))
{
if (session_name == std::wstring{ username }
&& application_name == std::wstring{ pi[i].pProcessName })
{
result.push_back(pi[i].ProcessId);
}
}
}
WTSFreeMemory(pi);
}
return result;
}
static std::wstring get_process_name_by_id(int id)
{
std::wstring ret;
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (h == INVALID_HANDLE_VALUE) return ret;
PROCESSENTRY32W pro{ 0 };
pro.dwSize = sizeof(pro);
if (Process32FirstW(h, &pro))
{
do
{
if (pro.th32ProcessID == id)
ret = pro.szExeFile;
} while (Process32NextW(h, &pro));
}
CloseHandle(h);
return ret;
}
static bool __stdcall enum_window_callback(HWND h, LPARAM l)
{
std::vector<window_info>* windows = (std::vector<window_info>*)l;
if (GetWindowLongA(h, GWL_STYLE) & WS_VISIBLE)
{
DWORD pid = 0;
GetWindowThreadProcessId(h, &pid);
wchar_t title[0x50]{ 0 };
_ie_control::get_wchar(h, title, 0x50);
wchar_t class_name[0x50]{ 0 };
GetClassNameW(h, class_name, 0x50);
RECT r{ 0 };
GetWindowRect(h, &r);
window_info info{ 0 };
info.h = h;
info.process = get_process_name_by_id(pid);
info.title = title;
info.class_name = class_name;
info.pid = pid;
info.x = r.left;
info.y = r.top;
info.width = r.right - r.left;
info.height = r.bottom - r.top;
windows->push_back(info);
}
return true;
}
static bool __stdcall enum_subwindow_callback(HWND h, LPARAM l)
{
std::vector<window_info>* windows = (std::vector<window_info>*)l;
if (GetWindowLongA(h, GWL_STYLE) & WS_VISIBLE)
{
wchar_t class_name[0x50]{ 0 };
GetClassNameW(h, class_name, 0x50);
wchar_t title[0x50]{ 0 };
_ie_control::get_wchar(h, title, 0x50);
RECT r{ 0 };
GetWindowRect(h, &r);
window_info info{ 0 };
info.h = h;
info.class_name = class_name;
info.title = title;
info.x = r.left;
info.y = r.top;
info.width = r.right - r.left;
info.height = r.bottom - r.top;
windows->push_back(info);
EnumChildWindows(h, (WNDENUMPROC)enum_subwindow_callback, (LPARAM)windows);
}
return true;
}
namespace _ie_control
{
bool initialize()
{
return CoInitialize(NULL) == S_OK;
}
void release()
{
CoUninitialize();
}
const wchar_t* get_wchar(HWND h, wchar_t* str, int size)
{
SendMessageW(h, WM_GETTEXT, size, (LPARAM)str);
return str;
}
std::wstring string_to_wstring(std::string str)
{
using convert_typeX = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_typeX, wchar_t> converterX;
return converterX.from_bytes(str);
}
std::string wstring_to_string(std::wstring wstr)
{
using convert_typeX = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_typeX, wchar_t> converterX;
return converterX.to_bytes(wstr);
}
std::vector<window_info> get_iexplore_process()
{
std::vector<window_info> windows;
EnumWindows((WNDENUMPROC)enum_window_callback, (LPARAM)&windows);
std::vector<window_info> ret;
for (const auto& it : windows)
if (it.process == L"iexplore.exe" && it.class_name == L"IEFrame")
ret.push_back(it);
return ret;
}
HWND get_ie_window_handle(HWND h)
{
std::vector<window_info> all_controls;
if (EnumChildWindows(h, (WNDENUMPROC)enum_subwindow_callback, (LPARAM)&all_controls))
for (const auto& it : all_controls)
if (it.class_name == L"Internet Explorer_Server")
return it.h;
return 0;
}
std::wstring get_ie_url(HWND h)
{
std::vector<window_info> ie_windows;
if (EnumChildWindows(h, (WNDENUMPROC)enum_subwindow_callback, (LPARAM)&ie_windows))
for (const auto& it : ie_windows)
if (it.title.find(L"http") != std::string::npos)
return it.title;
return L"";
}
bool is_ie_window(HWND h)
{
if (h == NULL) return false;
wchar_t class_name[0x50]{ 0 };
int ret = GetClassNameW(h, class_name, 0x50);
if (ret == 0) return false;
return std::wstring{ L"Internet Explorer_Server" } == class_name;
}
IHTMLDocument2* get_ie_doc_interface_ex(HWND h)
{
IHTMLDocument2* ret = nullptr;
if (is_ie_window(h) == false) return ret;
static HINSTANCE oleacc_module = LoadLibraryW(L"OLEACC.DLL");
if (oleacc_module == nullptr) return ret;
static LPFNOBJECTFROMLRESULT pf_ObjectFromLresult = (LPFNOBJECTFROMLRESULT)GetProcAddress(oleacc_module, "ObjectFromLresult");
if (pf_ObjectFromLresult == nullptr) return ret;
LRESULT res;
SendMessageTimeoutW(h, RegisterWindowMessageW(L"WM_HTML_GETOBJECT"), 0, 0, SMTO_ABORTIFHUNG, 1000, (DWORD_PTR*)&res);
CComPtr<IHTMLDocument> doc = NULL;
HRESULT hr = pf_ObjectFromLresult(res, IID_IHTMLDocument, 0, (void**)&doc);
if (FAILED(hr)) return ret;
CComPtr<IDispatch> disp;
CComQIPtr<IHTMLWindow2> win;
doc->get_Script(&disp);
win = disp;
if (win) win->get_document(&ret);
return ret;
}
std::vector<std::wstring> get_ie_password(IHTMLDocument2* doc)
{
std::vector<std::wstring> passwords;
CComPtr<IHTMLElementCollection> form_coll;
long len_form = 0;
if (doc == nullptr) return passwords;
if (FAILED(doc->get_forms(&form_coll))) return passwords;
if (FAILED(form_coll->get_length(&len_form))) return passwords;
VARIANT v_index, v_id;
CComPtr<IDispatch> disp;
for (long i = 0; i < len_form; i++)
{
V_VT(&v_id) = VT_I4;
V_I4(&v_id) = i;
V_VT(&v_index) = VT_I4;
V_I4(&v_index) = 0;
if (SUCCEEDED(form_coll->item(v_id, v_index, &disp.p)))
{
CComPtr<IHTMLFormElement> form_item;
if (SUCCEEDED(disp->QueryInterface(IID_IHTMLFormElement, (void**)&form_item.p)))
{
long len_item = 0;
if (SUCCEEDED(form_item->get_length(&len_item)))
{
for (long j = 0; j < len_item; j++)
{
V_VT(&v_id) = VT_I4;
V_I4(&v_id) = j;
V_VT(&v_index) = VT_I4;
V_I4(&v_index) = 0;
CComPtr<IHTMLInputTextElement> input;
if (SUCCEEDED(form_item->item(v_id, v_index, &disp.p)))
{
if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputTextElement, (void**)&input.p)))
{
CComBSTR c_type;
HRESULT hr = input->get_type(&c_type);
if (SUCCEEDED(hr)
&& c_type
&& c_type.Length()
&& c_type.ToLower() == S_OK
&& std::wstring{ c_type } == std::wstring{ L"password" })
{
CComBSTR c_value;
hr = input->get_value(&c_value);
if (SUCCEEDED(hr) && c_value && c_value.Length())
{
passwords.push_back(std::wstring(c_value.m_str));
}
}
}
}
}
}
}
}
}
return passwords;
}
ie_window_info get_ie_control_information_by_point(IHTMLDocument2* doc, unsigned int x, unsigned int y)
{
ie_window_info ret;
if (doc == nullptr) return ret;
CComPtr<IHTMLElement> element;
HRESULT hr = doc->elementFromPoint(x, y, &element);
if (FAILED(hr)) return ret;
CComPtr<IHTMLInputTextElement> input_element;
hr = element->QueryInterface(IID_IHTMLInputTextElement, (void**)&input_element.p);
if (FAILED(hr)) return ret;
CComBSTR c_type;
hr = input_element->get_type(&c_type);
if (SUCCEEDED(hr) && c_type)
ret.type = c_type.m_str;
CComBSTR c_value;
hr = input_element->get_value(&c_value);
if (SUCCEEDED(hr) && c_value)
ret.value = c_value.m_str;
CComBSTR c_name;
hr = input_element->get_name(&c_name);
if (SUCCEEDED(hr) && c_name)
ret.name = c_name.m_str;
return ret;
}
bool get_ie_source_code(IHTMLDocument2* doc, wchar_t* source, unsigned int size)
{
if (doc == nullptr) return false;
if (source == nullptr) return false;
if (size <= 0) return false;
CComPtr<IHTMLElementCollection> all_coll;
HRESULT hr = doc->get_all(&all_coll);
if (FAILED(hr)) return false;
long length = 0;
hr = all_coll->get_length(&length);
if (FAILED(hr)) return false;
for (long i = 0; i < length; i++)
{
VARIANT v_index, v_name;
v_name.vt = v_index.vt = VT_I4;
v_name.lVal = v_index.lVal = i;
CComPtr<IDispatch> disp;
hr = all_coll->item(v_name, v_index, &disp);
if (SUCCEEDED(hr))
{
CComPtr<IHTMLElement> element;
hr = disp->QueryInterface(IID_IHTMLElement, (void**)&element);
if (SUCCEEDED(hr))
{
CComBSTR c_name;
hr = element->get_tagName(&c_name);
if (SUCCEEDED(hr) && c_name && c_name.Length())
{
if (SUCCEEDED(c_name.ToLower()) && c_name.m_str == std::wstring{ L"html" })
{
CComBSTR content;
hr = element->get_outerHTML(&content);
if (SUCCEEDED(hr) && content)
{
unsigned int len = content.Length();
if (len < size)
{
memcpy(source, content.m_str, len);
return true;
}
}
}
}
}
}
}
return false;
}
std::vector<ie_window_info> enum_ie_window_control(IHTMLDocument2* doc)
{
std::vector<ie_window_info> ret;
CComPtr<IHTMLElementCollection> form_coll;
long len_form = 0;
if (doc == nullptr) return ret;
if (FAILED(doc->get_forms(&form_coll))) return ret;
if (FAILED(form_coll->get_length(&len_form))) return ret;
VARIANT v_index, v_id;
CComPtr<IDispatch> disp;
for (long i = 0; i < len_form; i++)
{
V_VT(&v_id) = VT_I4;
V_I4(&v_id) = i;
V_VT(&v_index) = VT_I4;
V_I4(&v_index) = 0;
if (SUCCEEDED(form_coll->item(v_id, v_index, &disp.p)))
{
CComPtr<IHTMLFormElement> form_item;
if (SUCCEEDED(disp->QueryInterface(IID_IHTMLFormElement, (void**)&form_item.p)))
{
long len_item = 0;
if (SUCCEEDED(form_item->get_length(&len_item)))
{
for (long j = 0; j < len_item; j++)
{
V_VT(&v_id) = VT_I4;
V_I4(&v_id) = j;
V_VT(&v_index) = VT_I4;
V_I4(&v_index) = 0;
CComPtr<IHTMLInputTextElement> input;
CComPtr<IHTMLInputButtonElement> button;
if (SUCCEEDED(form_item->item(v_id, v_index, &disp.p)))
{
if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputTextElement, (void**)&input.p)))
{
ie_window_info info;
CComBSTR c_type;
HRESULT hr = input->get_type(&c_type);
if (SUCCEEDED(hr) && c_type)
info.type = c_type.m_str;
CComBSTR c_value;
hr = input->get_value(&c_value);
if (SUCCEEDED(hr) && c_value)
info.value = c_value.m_str;
CComBSTR c_name;
hr = input->get_name(&c_name);
if (SUCCEEDED(hr) && c_name)
info.name = c_name.m_str;
ret.push_back(info);
}
else if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputButtonElement, (void**)&button.p)))
{
ie_window_info info;
CComBSTR c_type;
HRESULT hr = button->get_type(&c_type);
if (SUCCEEDED(hr) && c_type)
info.type = c_type.m_str;
CComBSTR c_value;
hr = button->get_value(&c_value);
if (SUCCEEDED(hr) && c_value)
info.value = c_value.m_str;
CComBSTR c_name;
hr = button->get_name(&c_name);
if (SUCCEEDED(hr) && c_name)
info.name = c_name.m_str;
ret.push_back(info);
}
}
}
}
}
}
}
return ret;
}
bool set_ie_control_text(IHTMLDocument2* doc, std::wstring type, std::wstring name, std::wstring value)
{
CComPtr<IHTMLElementCollection> form_coll;
long len_form = 0;
if (doc == nullptr) return false;
if (FAILED(doc->get_forms(&form_coll))) return false;
if (FAILED(form_coll->get_length(&len_form))) return false;
VARIANT v_index, v_id;
CComPtr<IDispatch> disp;
bool ret = false;
for (long i = 0; i < len_form; i++)
{
V_VT(&v_id) = VT_I4;
V_I4(&v_id) = i;
V_VT(&v_index) = VT_I4;
V_I4(&v_index) = 0;
if (SUCCEEDED(form_coll->item(v_id, v_index, &disp.p)))
{
CComPtr<IHTMLFormElement> form_item;
if (SUCCEEDED(disp->QueryInterface(IID_IHTMLFormElement, (void**)&form_item.p)))
{
long len_item = 0;
if (SUCCEEDED(form_item->get_length(&len_item)))
{
for (long j = 0; j < len_item; j++)
{
V_VT(&v_id) = VT_I4;
V_I4(&v_id) = j;
V_VT(&v_index) = VT_I4;
V_I4(&v_index) = 0;
CComPtr<IHTMLInputTextElement> input;
if (SUCCEEDED(form_item->item(v_id, v_index, &disp.p)))
{
if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputTextElement, (void**)&input.p)))
{
CComBSTR c_type;
input->get_type(&c_type);
CComBSTR c_name;
input->get_name(&c_name);
if (c_type && c_name && c_type.m_str == type && c_name.m_str == name)
{
CComBSTR c_value = value.c_str();
HRESULT hr = input->put_value(c_value);
ret = SUCCEEDED(hr);
}
}
}
}
}
}
}
}
return ret;
}
bool submit_form(IHTMLDocument2* doc)
{
CComPtr<IHTMLElementCollection> form_coll;
long len_form = 0;
if (doc == nullptr) return false;
if (FAILED(doc->get_forms(&form_coll))) return false;
if (FAILED(form_coll->get_length(&len_form))) return false;
bool ret = false;
VARIANT v_index, v_id;
CComPtr<IDispatch> disp;
for (long i = 0; i < len_form; i++)
{
V_VT(&v_id) = VT_I4;
V_I4(&v_id) = i;
V_VT(&v_index) = VT_I4;
V_I4(&v_index) = 0;
if (SUCCEEDED(form_coll->item(v_id, v_index, &disp.p)))
{
CComPtr<IHTMLFormElement> form_item;
if (SUCCEEDED(disp->QueryInterface(IID_IHTMLFormElement, (void**)&form_item.p)))
{
bool has_text = false;
bool has_password = false;
bool has_button = false;
long len_item = 0;
if (SUCCEEDED(form_item->get_length(&len_item)))
{
for (long j = 0; j < len_item; j++)
{
V_VT(&v_id) = VT_I4;
V_I4(&v_id) = j;
V_VT(&v_index) = VT_I4;
V_I4(&v_index) = 0;
CComPtr<IHTMLInputTextElement> input;
CComPtr<IHTMLInputButtonElement> button;
if (SUCCEEDED(form_item->item(v_id, v_index, &disp.p)))
{
if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputTextElement, (void**)&input.p)))
{
CComBSTR c_type;
HRESULT hr = input->get_type(&c_type);
if (SUCCEEDED(hr) && c_type && SUCCEEDED(c_type.ToLower()))
{
if (c_type.m_str == std::wstring{ L"text" }) has_text = true;
else if (c_type.m_str == std::wstring{ L"password" }) has_password = true;
}
}
else if (SUCCEEDED(disp->QueryInterface(IID_IHTMLInputButtonElement, (void**)&button.p)))
{
CComBSTR c_type;
HRESULT hr = button->get_type(&c_type);
if (SUCCEEDED(hr) && c_type && SUCCEEDED(c_type.ToLower()))
if (c_type.m_str == std::wstring{ L"submit" }) has_button = true;
}
}
}
}
if (has_text && has_password && has_button)
{
form_item->submit();
ret = true;
}
}
}
}
return ret;
}
}