魔獸改建程序源碼(一)

先貼出二進制下載地址:  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;
}



發佈了41 篇原創文章 · 獲贊 35 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章