先贴出二进制下载地址: http://download.csdn.net/detail/xyzzf/7322277
第一部分: 键盘映射DLL API实现:
#include <Windows.h>
#include <process.h>
#include <type_traits>
typedef WPARAM key_type;
typedef WPARAM value_type;
typedef struct _k2rt_tree_node
{
key_type key; // virtual key code: mapping-key
value_type value; // virtual key code: mapping-value
struct _k2rt_tree_node* child;
struct _k2rt_tree_node* next;
} k2rt_tree_node, *k2rt_tree_node_pointer, k2rt_tree, *k2rt_tree_pointer;
// shared data segment
#pragma data_seg(".shared")
__declspec(dllexport) HHOOK udg_hhook = nullptr;
__declspec(dllexport) HHOOK udg_hhook_launch = nullptr;
__declspec(dllexport) HMODULE udg_target_hmod = nullptr;
__declspec(dllexport) HANDLE udg_target_process = nullptr;
__declspec(dllexport) DWORD udg_target_tid = 0;
__declspec(dllexport) HWND udg_target_hwnd = nullptr;
__declspec(dllexport) k2rt_tree_pointer udg_mapper_list = nullptr;
__declspec(dllexport) bool udg_start_war_require = false;
#pragma data_seg()
#pragma comment(linker,"/section:.shared,RWS")
/*
** @useful macro utils
*/
#define _WriteMemory(_Paddr,_Pval) ::WriteProcessMemory(udg_target_process, _Paddr, _Pval, sizeof(*_Pval), nullptr)
#define _ReadMemory(_Paddr,_Pval) ::ReadProcessMemory(udg_target_process, _Paddr, _Pval, sizeof(*_Pval), nullptr)
#define _IsNotNullptr(ptr) ( (ptr) != nullptr )
#define LIST_PUSHBACK(_List,_Newkey,_Newval,_CreateFunc,_GetNextFunc,_SetNextFunc) do { \
decltype(_List) next = nullptr; \
decltype(_List) next_visitor = _List; \
while( _IsNotNullptr(next_visitor) && _IsNotNullptr(next = _GetNextFunc(next_visitor)) ) \
{ \
next_visitor = next; \
} \
_SetNextFunc(next_visitor, _CreateFunc(_Newkey, _Newval) ); \
} while(false)
/*
** vtree(the same line nodes have same key,graph view:
** ROOT -------- Only a placeholder node
** |
** |
** child(1) ---> child(1).next(1) ... child(1).next(n)
** |
** |
** child(2) ---> child(2).next(1) ... child(2).next(n)
** .
** .
** .
** child(n) ---> child(n).next(1) ... child(n).next(n)
**
*/
#define VTREE_PUSHBACK(_List,_Newkey,_Newval,_CreateFunc,_GetChildFunc,_SetChildFunc,_GetNextFunc,_SetNextFunc,_GetKeyFunc) do { \
decltype(_List) child = nullptr; \
decltype(_List) child_visitor = _List; \
std::remove_const<decltype(_Newkey)>::type tempkey = -1; \
while( ( child_visitor != nullptr ) && ( _Newkey != ( tempkey = _GetKeyFunc(child_visitor) ) ) && \
( ( child = _GetChildFunc(child_visitor) ) != nullptr ) ) \
{ \
child_visitor = child; \
} \
if(_Newkey == tempkey) { \
LIST_PUSHBACK(child_visitor, _Newkey, _Newval, _CreateFunc, _GetNextFunc, _SetNextFunc); \
} else { \
_SetChildFunc(child_visitor, _CreateFunc(_Newkey, _Newval) ); \
} \
} while(false)
/** @declaration
** user interfaces ( used by external )
*/
extern "C" __declspec(dllexport) void k2ud_mapper_initialize(HANDLE hProcess, DWORD tid, HWND hwnd);
extern "C" __declspec(dllexport) void k2ud_mapper_finalize(void);
extern "C" __declspec(dllexport) bool k2ud_mapper_enable_mapping(void);
extern "C" __declspec(dllexport) bool k2ud_mapper_disable_mapping(void);
/*
* params: key: new short-key
* value: original short-key
*/
extern "C" __declspec(dllexport) unsigned int k2ud_mapper_insert_mapping(const key_type key, const value_type value);
extern "C" __declspec(dllexport) void k2ud_mapper_erase_mapping(const key_type key);
extern "C" __declspec(dllexport) void k2ud_mapper_clear_mapping(void);
extern "C" __declspec(dllexport) bool k2ud_launch_war3_quickly(void);
/** @declaration
** runtime interface( used at internal )
*/
static k2rt_tree_node_pointer k2rt_tree_node_create(const key_type key, const value_type value);
static void k2rt_tree_node_free(k2rt_tree_node_pointer);
static void k2rt_tree_list_free(k2rt_tree_node_pointer);
static key_type k2rt_tree_node_get_key(k2rt_tree_node_pointer);
static value_type k2rt_tree_node_get_value(k2rt_tree_node_pointer);
static k2rt_tree_node_pointer k2rt_tree_node_get_child(k2rt_tree_node_pointer);
static k2rt_tree_node_pointer k2rt_tree_node_get_next(k2rt_tree_node_pointer);
static void k2rt_tree_node_set_key(k2rt_tree_node_pointer, const key_type key);
static void k2rt_tree_node_set_value(k2rt_tree_node_pointer, const value_type value);
static void k2rt_tree_node_set_child(k2rt_tree_node_pointer, k2rt_tree_node_pointer child);
static void k2rt_tree_node_set_next(k2rt_tree_node_pointer, k2rt_tree_node_pointer next);
static LRESULT WINAPI k2rt_GetMsgProc(int code, WPARAM wParam, LPARAM lParam);
static LRESULT WINAPI k2rt_KeyboardProc(int code, WPARAM wParam, LPARAM lParam);
/** @implementation
** user interfaces ( used by external )
*/
extern "C" __declspec(dllexport) void k2ud_mapper_initialize(HANDLE process, DWORD tid, HWND hwnd)
{
udg_target_process = process;
udg_target_tid = tid;
udg_target_hwnd = hwnd;
udg_mapper_list = k2rt_tree_node_create(-1, -1); // Just a reserved node
}
extern "C" __declspec(dllexport) void k2ud_mapper_finalize(void)
{ // destory the vtree at remoate process
k2rt_tree_node_pointer ptr = udg_mapper_list;
k2rt_tree_node_pointer freeing = nullptr;
while(ptr != nullptr)
{
freeing = ptr;
ptr = k2rt_tree_node_get_child(ptr);
k2rt_tree_list_free(freeing);
}
udg_mapper_list = nullptr;
udg_target_hwnd = nullptr;
udg_target_tid = 0;
udg_target_process = nullptr;
}
extern "C" __declspec(dllexport) bool k2ud_mapper_enable_mapping(void)
{
if(0 == udg_target_tid)
{
::MessageBox(nullptr, TEXT("The target thread id is unspecified,please call k2ud_mapper_initialize function!"), TEXT("error from key_mapper2.dll::k2ud_mapper_enable_mapping"), MB_OK | MB_ICONEXCLAMATION);
return false;
}
if(nullptr == udg_hhook)
{
udg_hhook = ::SetWindowsHookEx(WH_KEYBOARD, k2rt_KeyboardProc, udg_target_hmod, udg_target_tid);
}
return udg_hhook != nullptr;
}
extern "C" __declspec(dllexport) bool k2ud_mapper_disable_mapping(void)
{
if(udg_hhook != nullptr)
{
if(::UnhookWindowsHookEx(udg_hhook))
{
udg_hhook = nullptr;
return true;
}
DWORD ec = GetLastError();
if(ec == ERROR_INVALID_HANDLE)
{
udg_hhook = nullptr;
return true;
}
}
return false;
}
extern "C" __declspec(dllexport) unsigned int k2ud_mapper_insert_mapping(const key_type key, const value_type value)
{
if(key == value) return 0;
VTREE_PUSHBACK(udg_mapper_list,
key,
value,
k2rt_tree_node_create,
k2rt_tree_node_get_child,
k2rt_tree_node_set_child,
k2rt_tree_node_get_next,
k2rt_tree_node_set_next,
k2rt_tree_node_get_key);
return 1;
}
extern "C" __declspec(dllexport) void k2ud_mapper_erase_mapping(const key_type key)
{
key_type tempkey = 0;
k2rt_tree_pointer child_visitor = udg_mapper_list;
k2rt_tree_node_pointer parent_visitor = child_visitor;
k2rt_tree_node_pointer child = nullptr;
// search
while( (tempkey = k2rt_tree_node_get_key(child_visitor) ) != key
&& ( child = k2rt_tree_node_get_child(child_visitor) ) != nullptr )
{
parent_visitor = child_visitor;
child_visitor = child;
}
// if found, remove it
if(key == tempkey) {
k2rt_tree_node_set_child(parent_visitor, k2rt_tree_node_get_child(child_visitor) );
k2rt_tree_list_free(child_visitor);
}
}
extern "C" __declspec(dllexport) void k2ud_mapper_clear_mapping(void)
{
k2rt_tree_node_pointer ptr = k2rt_tree_node_get_child(udg_mapper_list);
k2rt_tree_node_pointer freeing = nullptr;
while(ptr != nullptr)
{
freeing = ptr;
ptr = k2rt_tree_node_get_child(ptr);
k2rt_tree_list_free(freeing);
}
k2rt_tree_node_set_child(udg_mapper_list, nullptr);
}
/** @implementation
** runtime interfaces ( used by external )
*/
static k2rt_tree_node_pointer k2rt_tree_node_create(const key_type key, const value_type value)
{
if(nullptr == udg_target_process)
{
::MessageBox(nullptr, TEXT("The target process is unspecified, please call k2ud_mapper_initialize function!"), TEXT("error from key_mapper2.dll::k2rt_tree_node_create"), MB_OK | MB_ICONEXCLAMATION);
return nullptr;
}
static unsigned int zero = 0;
k2rt_tree_node_pointer _Pnode = (k2rt_tree_node_pointer)::VirtualAllocEx(udg_target_process,
nullptr,
sizeof(k2rt_tree_node),
MEM_COMMIT,
PAGE_READWRITE);
_WriteMemory(&_Pnode->key, &key);
_WriteMemory(&_Pnode->value, &value);
_WriteMemory(&_Pnode->child, &zero);
_WriteMemory(&_Pnode->next, &zero);
return _Pnode;
}
static void k2rt_tree_node_free(k2rt_tree_node_pointer _Pnode)
{
::VirtualFreeEx(udg_target_process, _Pnode, 0, MEM_RELEASE);
}
static void k2rt_tree_list_free(k2rt_tree_node_pointer _Phead)
{
k2rt_tree_node_pointer ptr = _Phead;
k2rt_tree_node_pointer freeing = nullptr;
while(ptr != nullptr)
{
freeing = ptr;
ptr = k2rt_tree_node_get_next(ptr);
k2rt_tree_node_free(freeing);
}
}
static key_type k2rt_tree_node_get_key(k2rt_tree_node_pointer _Pnode)
{
key_type key = 0;
_ReadMemory(&_Pnode->key, &key);
return key;
}
static key_type k2rt_tree_node_get_value(k2rt_tree_node_pointer _Pnode)
{
value_type value = 0;
_ReadMemory(&_Pnode->value, &value);
return value;
}
static k2rt_tree_node_pointer k2rt_tree_node_get_child(k2rt_tree_node_pointer _Pnode)
{
k2rt_tree_node_pointer child = nullptr;
_ReadMemory(&_Pnode->child, &child);
return child;
}
static k2rt_tree_node_pointer k2rt_tree_node_get_next(k2rt_tree_node_pointer _Pnode)
{
k2rt_tree_node_pointer next = nullptr;
_ReadMemory(&_Pnode->next, &next);
return next;
}
static void k2rt_tree_node_set_key(k2rt_tree_node_pointer _Pnode, const key_type key) // unused currentlly
{
_WriteMemory(&_Pnode->key, &key);
}
static void k2rt_tree_node_set_value(k2rt_tree_node_pointer _Pnode, const value_type value)
{
_WriteMemory(&_Pnode->value, &value);
}
static void k2rt_tree_node_set_child(k2rt_tree_node_pointer _Pnode, k2rt_tree_node_pointer child)
{
_WriteMemory(&_Pnode->child, &child);
}
static void k2rt_tree_node_set_next(k2rt_tree_node_pointer _Pnode, k2rt_tree_node_pointer next)
{
_WriteMemory(&_Pnode->next, &next);
}
typedef union {
LPARAM value;
struct {
unsigned int repeat_count:16; // The value is the number of times the keystroke is repeated as a result of the user's holding down the key.
unsigned int scan_code:8; // The value depends on the OEM.
unsigned int is_extended_key:1; // extended key: F1~F12 or NUMPAD
unsigned int reserved:4;
unsigned int context_code:1; // 1: the ALT key is down, 0:otherwise
unsigned int previous_key_state:1; // 0: up, 1: down
unsigned int transition_state:1; // 0:being pressed, 1: being released
} detail;
} keybd_detail;
static bool k2rt_keybd_post_message(key_type orig_vkey, int message)
{
k2rt_tree_node_pointer visit_child = udg_mapper_list->child;
k2rt_tree_node_pointer visit_next = nullptr;
while(visit_child != nullptr)
{
if(orig_vkey == visit_child->key)
{
visit_next = visit_child;
do {
::PostMessage(udg_target_hwnd, message, visit_next->value, visit_next->key);
visit_next = visit_next->next;
} while(visit_next != nullptr);
return true;
}
visit_child = visit_child->child;
}
return false;
}
static bool k2rt_keybd_imitate_event(key_type orig_vkey, int type = KEYEVENTF_KEYUP)
{
k2rt_tree_node_pointer visit_child = udg_mapper_list->child;
k2rt_tree_node_pointer visit_next = nullptr;
while(visit_child != nullptr)
{
if(orig_vkey == visit_child->key)
{
visit_next = visit_child;
do {
keybd_event(visit_next->value, MapVirtualKey(visit_next->value, 0), type, 0);
//keybd_event(visit_next->value, MapVirtualKey(visit_next->value, 0), type, 0);
visit_next = visit_next->next;
} while(visit_next != nullptr);
//orig_vkey = visit_child->value;
return true;
}
visit_child = visit_child->child;
}
return false;
}
//
//The hook Procedures
/
static bool k2rt_keybd_send_key(key_type key)
{
keybd_event(key, MapVirtualKey(key, 0), 0, 0);
keybd_event(key, MapVirtualKey(key, 0), KEYEVENTF_KEYUP, 0);
return true;
}
extern "C" __declspec(dllexport) bool k2ud_launch_war3_quickly(void)
{
udg_start_war_require = true;
udg_hhook_launch = ::SetWindowsHookEx(WH_GETMESSAGE, k2rt_GetMsgProc, udg_target_hmod, udg_target_tid);
return udg_hhook_launch != nullptr;
}
static unsigned __stdcall launch_war3_quickly_task(void*)
{
k2rt_keybd_send_key('L');
Sleep(1000);
k2rt_keybd_send_key('C');
Sleep(1000);
k2rt_keybd_send_key('C');
Sleep(1000);
k2rt_keybd_send_key('C');
Sleep(1000);
k2rt_keybd_send_key('C');
Sleep(1000);
k2rt_keybd_send_key('C');
Sleep(1000);
k2rt_keybd_send_key('C');
Sleep(1000);
k2rt_keybd_send_key('C');
Sleep(1000);
k2rt_keybd_send_key('C');
return 0;
}
static LRESULT WINAPI k2rt_GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
{
if( code < 0 ) { return 0; }
tagMSG* pmsg = (tagMSG*)lParam;
if(HC_ACTION == code)
{
if(udg_start_war_require)
{
udg_start_war_require = false;
UnhookWindowsHookEx(udg_hhook_launch);
udg_hhook_launch = nullptr;
// start a async task to quickly create a war3 GAME
uintptr_t handle = _beginthreadex(nullptr, 0, launch_war3_quickly_task, nullptr, 0, nullptr);
}
}
return CallNextHookEx(udg_hhook, code, wParam, lParam);
}
static LRESULT WINAPI k2rt_KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if( code < 0 ) { return 0; }
keybd_detail& parser = *reinterpret_cast<keybd_detail*>(&lParam);
if(HC_ACTION == code)
{
switch(parser.detail.transition_state)
{
case 0:
if(k2rt_keybd_imitate_event(wParam, 0)) return TRUE; // catch the target key
break;
case 1:
if(k2rt_keybd_imitate_event(wParam, KEYEVENTF_KEYUP)) return TRUE; // catch the target key
break;
default:;
}
}
return CallNextHookEx(udg_hhook, code, wParam, lParam);
}
static LRESULT WINAPI k2rt_LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if( code < 0 ) { return 0; }
KBDLLHOOKSTRUCT* detail = (KBDLLHOOKSTRUCT*)lParam;
if(HC_ACTION == code)
{
switch(wParam)
{
case WM_KEYDOWN:
//if(k2rt_keybd_imitate_event(detail->vkCode, 0)) return TRUE;
break;
case WM_KEYUP:
//if(k2rt_keybd_imitate_event(detail->vkCode, KEYEVENTF_EXTENDEDKEY)) return TRUE;
break;
default:;
}
}
return CallNextHookEx(udg_hhook, code, wParam, lParam);
}
static LRESULT WINAPI k2rt_MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if( nCode < 0 ) { return 0; }
MOUSEHOOKSTRUCT* detail = (MOUSEHOOKSTRUCT*)lParam;
if(HC_ACTION == nCode)
{
switch(wParam)
{
case WM_MOUSEACTIVATE:
case WM_MOUSEHWHEEL:
case WM_MOUSEWHEEL:
case WM_MOUSEHOVER:
case WM_MOUSEMOVE:
case WM_MOUSELEAVE:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
default:;
}
}
return CallNextHookEx(udg_hhook, nCode, wParam, lParam);
}
static LRESULT WINAPI k2rt_LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if( nCode < 0 ) { return 0; }
MSLLHOOKSTRUCT* detail = (MSLLHOOKSTRUCT*)lParam;
if(HC_ACTION == nCode)
{
switch(wParam)
{
case WM_MOUSEACTIVATE:
case WM_MOUSEHWHEEL:
case WM_MOUSEWHEEL:
case WM_MOUSEHOVER:
case WM_MOUSEMOVE:
case WM_MOUSELEAVE:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
break;
default:;
}
}
return CallNextHookEx(udg_hhook, nCode, wParam, lParam);
}
static LRESULT WINAPI k2rt_ShellProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if( nCode < 0 ) { return 0; }
MSLLHOOKSTRUCT* detail = (MSLLHOOKSTRUCT*)lParam;
switch(nCode)
{
case HSHELL_ACCESSIBILITYSTATE:
break;
case HSHELL_ACTIVATESHELLWINDOW:
break;
case HSHELL_APPCOMMAND:
break;
case HSHELL_GETMINRECT:
break;
case HSHELL_LANGUAGE:
break;
case HSHELL_REDRAW:
break;
case HSHELL_TASKMAN:
break;
case HSHELL_WINDOWACTIVATED:
break;
case HSHELL_WINDOWCREATED:
break;
case HSHELL_WINDOWDESTROYED:
break;
case HSHELL_WINDOWREPLACED:
break;
default:;
}
return CallNextHookEx(udg_hhook, nCode, wParam, lParam);
}
static LRESULT WINAPI k2rt_CallWndProc(int code, WPARAM wParam, LPARAM lParam)
{
if( code < 0 ) { return 0; }
bool is_sent_by_current_thread = wParam;
CWPSTRUCT* detail = (CWPSTRUCT*)lParam;
return CallNextHookEx(udg_hhook, code, wParam, lParam);
}
static LRESULT WINAPI k2rt_CallWndRetProc(int code, WPARAM wParam, LPARAM lParam)
{
if( code < 0 ) { return 0; }
bool is_sent_by_current_thread = wParam;
CWPRETSTRUCT* detail = (CWPRETSTRUCT*)lParam;
return CallNextHookEx(udg_hhook, code, wParam, lParam);
}
static LRESULT WINAPI k2rt_DebugProc(int code, WPARAM wParam, LPARAM lParam)
{
if( code < 0 ) { return 0; }
DEBUGHOOKINFO* detail = (DEBUGHOOKINFO*)lParam;
switch(wParam)
{
case WH_KEYBOARD:
case WH_KEYBOARD_LL:
case WH_GETMESSAGE:
break;
default:;
}
return CallNextHookEx(udg_hhook, code, wParam, lParam);
}
/** @implementation
** the entry of DLL ( used by internal )
*/
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
DWORD thread_id = 0;
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
udg_target_hmod = hModule;
thread_id = GetCurrentThreadId();
break;
case DLL_THREAD_ATTACH:
thread_id = GetCurrentThreadId();
break;
case DLL_THREAD_DETACH:
thread_id = GetCurrentThreadId();
break;
case DLL_PROCESS_DETACH:
thread_id = GetCurrentThreadId();
break;
}
return TRUE;
}