/* Copyright (C) 2010-2012 kaosu (qiupf2000@gmail.com) * This file is part of the Interactive Text Hooker. * Interactive Text Hooker is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ITH.h" #include "host/host.h" #include "host/hookman.h" #include "host/settings.h" #include "CustomFilter.h" #include "profile/Profile.h" #include "ProfileManager.h" HINSTANCE hIns; ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE hInstance, DWORD nCmdShow, RECT *rc); RECT window; extern HWND hMainWnd; // windows.cpp extern bool MonitorFlag; // ProfileManager.cpp extern ProfileManager* pfman; // ProfileManager.cpp extern "C" { BOOL IthInitSystemService(); void IthCloseSystemService(); } CustomFilter* uni_filter; CustomFilter* mb_filter; HookManager* man; Settings* setman; LONG split_time, cyclic_remove, global_filter; LONG process_time, inject_delay, insert_delay, auto_inject, auto_insert, clipboard_flag; std::map setting; void RecordMBChar(WORD mb, PVOID f) { auto filter = (pugi::xml_node*)f; DWORD m = mb; WCHAR buffer[16]; std::swprintf(buffer, L"m%04X", m); filter->append_attribute(buffer) = L"0"; } void RecordUniChar(WORD uni, PVOID f) { auto filter = (pugi::xml_node*)f; DWORD m = uni; WCHAR buffer[16]; std::swprintf(buffer, L"u%04X", m); filter->append_attribute(buffer) = L"0"; std::wstring text = filter->text().get(); text += (wchar_t)m; filter->text().set(text.c_str()); } void SaveSettings() { WINDOWPLACEMENT wndpl; wndpl.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(hMainWnd, &wndpl); setting[L"window_left"] = wndpl.rcNormalPosition.left; setting[L"window_right"] = wndpl.rcNormalPosition.right; setting[L"window_top"] = wndpl.rcNormalPosition.top; setting[L"window_bottom"] = wndpl.rcNormalPosition.bottom; setting[L"split_time"] = split_time; setting[L"process_time"] = process_time; setting[L"inject_delay"] = inject_delay; setting[L"insert_delay"] = insert_delay; setting[L"auto_inject"] = auto_inject; setting[L"auto_insert"] = auto_insert; setting[L"auto_copy"] = clipboard_flag; setting[L"auto_suppress"] = cyclic_remove; setting[L"global_filter"] = global_filter; UniqueHandle hFile(IthCreateFile(L"ITH.xml", GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS)); if (hFile.get() != INVALID_HANDLE_VALUE) { FileWriter fw(hFile.get()); pugi::xml_document doc; auto root = doc.root().append_child(L"ITH_Setting"); for (auto it = setting.begin(); it != setting.end(); ++it) root.append_attribute(it->first.c_str()).set_value(it->second); auto filter = root.append_child(L"SingleCharFilter"); filter.append_child(pugi::xml_node_type::node_pcdata); mb_filter->Traverse(RecordMBChar, &filter); uni_filter->Traverse(RecordUniChar, &filter); doc.save(fw); } } void DefaultSettings() { setting[L"split_time"] = 200; setting[L"process_time"] = 50; setting[L"inject_delay"] = 3000; setting[L"insert_delay"] = 500; setting[L"auto_inject"] = 1; setting[L"auto_insert"] = 1; setting[L"auto_copy"] = 0; setting[L"auto_suppress"] = 0; setting[L"global_filter"] = 0; setting[L"window_left"] = 100; setting[L"window_right"] = 800; setting[L"window_top"] = 100; setting[L"window_bottom"] = 600; } void InitializeSettings() { split_time = setting[L"split_time"]; process_time = setting[L"process_time"]; inject_delay = setting[L"inject_delay"]; insert_delay = setting[L"insert_delay"]; auto_inject = setting[L"auto_inject"]; auto_insert = setting[L"auto_insert"]; clipboard_flag = setting[L"auto_copy"]; cyclic_remove = setting[L"auto_suppress"]; global_filter = setting[L"global_filter"]; window.left = setting[L"window_left"]; window.right = setting[L"window_right"]; window.top = setting[L"window_top"]; window.bottom = setting[L"window_bottom"]; if (auto_inject > 1) auto_inject = 1; if (auto_insert > 1) auto_insert = 1; if (clipboard_flag > 1) clipboard_flag = 1; if (cyclic_remove > 1) cyclic_remove = 1; if (window.right < window.left || window.right - window.left < 600) window.right = window.left + 600; if (window.bottom < window.top || window.bottom - window.top < 200) window.bottom = window.top + 200; } void LoadSettings() { UniqueHandle hFile(IthCreateFile(L"ITH.xml", GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING)); if (hFile.get() != INVALID_HANDLE_VALUE) { DWORD size = GetFileSize(hFile.get(), NULL); std::unique_ptr buffer(new char[size]); ReadFile(hFile.get(), buffer.get(), size, &size, NULL); pugi::xml_document doc; auto result = doc.load_buffer_inplace(buffer.get(), size); if (!result) return; auto root = doc.root().child(L"ITH_Setting"); for (auto attr = root.attributes_begin(); attr != root.attributes_end(); ++attr) { auto it = setting.find(attr->name()); if (it != setting.end()) it->second = std::stoul(attr->value()); } auto filter = root.child(L"SingleCharFilter"); if (filter) { for (auto attr = filter.attributes_begin(); attr != filter.attributes_end(); ++attr) { if (attr->name()[0] == L'm') { DWORD c = std::stoul(attr->name() + 1, NULL, 16); mb_filter->Insert(c & 0xFFFF); } else if (attr->name()[0] == L'u') { DWORD c = std::stoul(attr->name() + 1, NULL, 16); uni_filter->Insert(c & 0xFFFF); } } std::wstring filter_value = filter.text().get(); for (auto it = filter_value.begin(); it != filter_value.end(); ++it) { WCHAR filter_unichar[2] = { *it, L'\0' }; char filter_mbchar[4]; WC_MB(filter_unichar, filter_mbchar, 4); mb_filter->Insert(*(WORD*)filter_mbchar); uni_filter->Insert(*it); } } } } extern LPCWSTR ClassName, ClassNameAdmin; static WCHAR mutex[] = L"ITH_RUNNING"; DWORD FindITH() { HWND hwnd = FindWindow(ClassName, ClassName); if (hwnd == NULL) hwnd = FindWindow(ClassName, ClassNameAdmin); if (hwnd) { ShowWindow(hwnd, SW_SHOWNORMAL); SetForegroundWindow(hwnd); return 0; } return 1; } LONG WINAPI UnhandledExcept(_EXCEPTION_POINTERS *ExceptionInfo) { wchar_t path_name[512]; // fully qualified path name WCHAR code[16]; EXCEPTION_RECORD* rec = ExceptionInfo->ExceptionRecord; std::swprintf(code, L"%08X", rec->ExceptionCode); MEMORY_BASIC_INFORMATION info; if (VirtualQuery(rec->ExceptionAddress, &info, sizeof(info))) { if (GetModuleFileName((HMODULE)info.AllocationBase, path_name, 512)) { LPWSTR name = wcsrchr(path_name, L'\\'); if (name) { DWORD addr = (DWORD)rec->ExceptionAddress; std::swprintf(name, L"%s:%08X", name + 1, addr - (DWORD)info.AllocationBase); MessageBox(NULL, name, code, MB_OK); TerminateProcess(GetCurrentProcess(), 0); } } } std::swprintf(path_name, L"%08X", rec->ExceptionAddress); MessageBox(NULL, path_name, code, MB_OK); TerminateProcess(GetCurrentProcess(), 0); return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { InitCommonControls(); if (!IthInitSystemService()) TerminateProcess(GetCurrentProcess(), 0); CreateMutex(NULL, TRUE, L"ITH_MAIN_RUNNING"); if (Host_Open()) { SetUnhandledExceptionFilter(UnhandledExcept); Host_GetHookManager(&man); Host_GetSettings(&setman); setman->splittingInterval = 200; MonitorFlag = true; pfman = new ProfileManager(); mb_filter = new CustomFilter(); uni_filter = new CustomFilter(); DefaultSettings(); LoadSettings(); InitializeSettings(); setman->splittingInterval = split_time; setman->clipboardFlag = clipboard_flag > 0; hIns = hInstance; MyRegisterClass(hIns); InitInstance(hIns, FALSE, &window); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } //delete mb_filter; //delete uni_filter; delete pfman; MonitorFlag = false; man = NULL; } else { FindITH(); } Host_Close(); IthCloseSystemService(); TerminateProcess(GetCurrentProcess(), 0); }