OSDN Git Service

use boost_1_56_0 and build by VS2013
[yamy/yamy.git] / hook.cpp
index c1b3197..98b585d 100644 (file)
--- a/hook.cpp
+++ b/hook.cpp
 #define HOOK_RPT0(msg)\r
 #define HOOK_RPT1(msg, arg1)\r
 #define HOOK_RPT2(msg, arg1, arg2)\r
+#define HOOK_RPT3(msg, arg1, arg2, arg3)\r
+#define HOOK_RPT4(msg, arg1, arg2, arg3, arg4)\r
+#define HOOK_RPT5(msg, arg1, arg2, arg3, arg4, arg5)\r
 #else\r
 #define HOOK_RPT0(msg) if (g.m_isLogging) { _RPT0(_CRT_WARN, msg); }\r
 #define HOOK_RPT1(msg, arg1) if (g.m_isLogging) { _RPT1(_CRT_WARN, msg, arg1); }\r
 #define HOOK_RPT2(msg, arg1, arg2) if (g.m_isLogging) { _RPT2(_CRT_WARN, msg, arg1, arg2); }\r
+#define HOOK_RPT3(msg, arg1, arg2, arg3) if (g.m_isLogging) { _RPT3(_CRT_WARN, msg, arg1, arg2, arg3); }\r
+#define HOOK_RPT4(msg, arg1, arg2, arg3, arg4) if (g.m_isLogging) { _RPT4(_CRT_WARN, msg, arg1, arg2, arg3, arg4); }\r
+#define HOOK_RPT5(msg, arg1, arg2, arg3, arg4, arg5) if (g.m_isLogging) { _RPT5(_CRT_WARN, msg, arg1, arg2, arg3, arg4, arg5); }\r
 #endif\r
 \r
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
@@ -65,14 +71,16 @@ struct Globals {
        bool m_isImeLock;                               ///\r
        bool m_isImeCompositioning;                     ///\r
        HHOOK m_hHookMouseProc;                 ///\r
-#ifdef NO_DRIVER\r
        HHOOK m_hHookKeyboardProc;                      ///\r
-       KEYBOARD_DETOUR m_keyboardDetour;\r
+       INPUT_DETOUR m_keyboardDetour;\r
+       INPUT_DETOUR m_mouseDetour;\r
        Engine *m_engine;\r
-#endif // NO_DRIVER\r
        DWORD m_hwndTaskTray;                           ///\r
        HANDLE m_hMailslot;\r
        bool m_isInitialized;\r
+#ifdef HOOK_LOG_TO_FILE\r
+       HANDLE m_logFile;\r
+#endif // HOOK_LOG_TO_FILE\r
 #ifndef NDEBUG\r
        bool m_isLogging;\r
        _TCHAR m_moduleName[GANA_MAX_PATH];\r
@@ -89,26 +97,52 @@ static Globals g;
 static void notifyThreadDetach();\r
 static void notifyShow(NotifyShow::Show i_show, bool i_isMDI);\r
 static void notifyLog(_TCHAR *i_msg);\r
-static bool mapHookData();\r
+static bool mapHookData(bool i_isYamy);\r
 static void unmapHookData();\r
-static bool initialize();\r
+static bool initialize(bool i_isYamy);\r
+static bool notify(void *i_data, size_t i_dataSize);\r
 \r
 \r
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
 // Functions\r
 \r
-bool initialize()\r
+\r
+#ifdef HOOK_LOG_TO_FILE\r
+static void WriteToLog(const char *data)\r
+{\r
+       char buf[1024];\r
+       DWORD count;\r
+\r
+       WideCharToMultiByte(CP_THREAD_ACP, 0, g.m_moduleName, -1, buf, NUMBER_OF(buf), NULL, NULL);\r
+       strcat(buf, ": ");\r
+       strcat(buf, data);\r
+       SetFilePointer(g.m_logFile, 0, NULL, FILE_END);\r
+       WriteFile(g.m_logFile, buf, strlen(buf), &count, NULL);\r
+       FlushFileBuffers(g.m_logFile);\r
+}\r
+#else // !HOOK_LOG_TO_FILE\r
+#define WriteToLog(data)\r
+#endif // !HOOK_LOG_TO_FILE\r
+\r
+bool initialize(bool i_isYamy)\r
 {\r
 #ifndef NDEBUG\r
        _TCHAR path[GANA_MAX_PATH];\r
        GetModuleFileName(NULL, path, GANA_MAX_PATH);\r
        _tsplitpath_s(path, NULL, 0, NULL, 0, g.m_moduleName, GANA_MAX_PATH, NULL, 0);\r
-       if (_tcsncmp(g.m_moduleName, _T("Dbgview"), sizeof(_T("Dbgview"))/sizeof(_TCHAR)) != 0 &&\r
-                       _tcsncmp(g.m_moduleName, _T("windbg"), sizeof(_T("windbg"))/sizeof(_TCHAR)) != 0) {\r
+       if (_tcsnicmp(g.m_moduleName, _T("Dbgview"), sizeof(_T("Dbgview"))/sizeof(_TCHAR)) != 0 &&\r
+                       _tcsnicmp(g.m_moduleName, _T("windbg"), sizeof(_T("windbg"))/sizeof(_TCHAR)) != 0) {\r
                g.m_isLogging = true;\r
        }\r
 #endif // !NDEBUG\r
-#ifdef USE_MAILSLOT\r
+#ifdef HOOK_LOG_TO_FILE\r
+       _TCHAR logFileName[GANA_MAX_PATH];\r
+       GetEnvironmentVariable(_T("USERPROFILE"), logFileName, NUMBER_OF(logFileName));\r
+       _tcsncat(logFileName, _T("\\AppData\\LocalLow\\yamydll.txt"), _tcslen(_T("\\AppData\\LocalLow\\yamydll.log")));\r
+       g.m_logFile = CreateFile(logFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\r
+               OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);\r
+#endif // HOOK_LOG_TO_FILE\r
+       WriteToLog("try to open mailslot\r\n");\r
        g.m_hMailslot =\r
                CreateFile(NOTIFY_MAILSLOT_NAME, GENERIC_WRITE,\r
                                   FILE_SHARE_READ | FILE_SHARE_WRITE,\r
@@ -116,16 +150,23 @@ bool initialize()
                                   FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);\r
        if (g.m_hMailslot == INVALID_HANDLE_VALUE) {\r
                HOOK_RPT2("MAYU: %S create mailslot failed(0x%08x)\r\n", g.m_moduleName, GetLastError());\r
+               WriteToLog("open mailslot NG\r\n");\r
        } else {\r
                HOOK_RPT1("MAYU: %S create mailslot successed\r\n", g.m_moduleName);\r
+               WriteToLog("open mailslot OK\r\n");\r
        }\r
-#endif //USE_MAILSLOT\r
-       if (!mapHookData())\r
+       if (!mapHookData(i_isYamy))\r
                return false;\r
        _tsetlocale(LC_ALL, _T(""));\r
        g.m_WM_MAYU_MESSAGE =\r
                RegisterWindowMessage(addSessionId(WM_MAYU_MESSAGE_NAME).c_str());\r
        g.m_hwndTaskTray = g_hookData->m_hwndTaskTray;\r
+       if (!i_isYamy) {\r
+               NotifyThreadAttach ntd;\r
+               ntd.m_type = Notify::Type_threadAttach;\r
+               ntd.m_threadId = GetCurrentThreadId();\r
+               notify(&ntd, sizeof(ntd));\r
+       }\r
        g.m_isInitialized = true;\r
        return true;\r
 }\r
@@ -148,12 +189,16 @@ BOOL WINAPI DllMain(HINSTANCE i_hInstDLL, DWORD i_fdwReason,
        case DLL_PROCESS_DETACH:\r
                notifyThreadDetach();\r
                unmapHookData();\r
-#ifdef USE_MAILSLOT\r
                if (g.m_hMailslot != INVALID_HANDLE_VALUE) {\r
                        CloseHandle(g.m_hMailslot);\r
                        g.m_hMailslot = INVALID_HANDLE_VALUE;\r
                }\r
-#endif //USE_MAILSLOT\r
+#ifdef HOOK_LOG_TO_FILE\r
+               if (g.m_logFile != INVALID_HANDLE_VALUE) {\r
+                       CloseHandle(g.m_logFile);\r
+                       g.m_logFile = INVALID_HANDLE_VALUE;\r
+               }\r
+#endif // HOOK_LOG_TO_FILE\r
                break;\r
        case DLL_THREAD_DETACH:\r
                notifyThreadDetach();\r
@@ -166,36 +211,27 @@ BOOL WINAPI DllMain(HINSTANCE i_hInstDLL, DWORD i_fdwReason,
 \r
 \r
 /// map hook data\r
-static bool mapHookData()\r
+static bool mapHookData(bool i_isYamy)\r
 {\r
-       g.m_hHookData = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,\r
-                                                                         0, sizeof(HookData),\r
-                                                                         addSessionId(HOOK_DATA_NAME).c_str());\r
-       if (!g.m_hHookData) {\r
-               unmapHookData();\r
-               return false;\r
-       }\r
+       DWORD access = FILE_MAP_READ;\r
 \r
-       g_hookData =\r
-               (HookData *)MapViewOfFile(g.m_hHookData, FILE_MAP_READ | FILE_MAP_WRITE,\r
-                                                                 0, 0, sizeof(HookData));\r
-       if (!g_hookData) {\r
-               unmapHookData();\r
-               return false;\r
+       if (i_isYamy) {\r
+               access |= FILE_MAP_WRITE;\r
+               g.m_hHookData = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,   0, sizeof(HookData), addSessionId(HOOK_DATA_NAME).c_str());\r
+               g.m_hHookDataArch = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,       0, sizeof(HookDataArch), addSessionId(HOOK_DATA_NAME_ARCH).c_str());\r
+       } else {\r
+               g.m_hHookData = OpenFileMapping(access, FALSE, addSessionId(HOOK_DATA_NAME).c_str());\r
+               g.m_hHookDataArch = OpenFileMapping(access, FALSE, addSessionId(HOOK_DATA_NAME_ARCH).c_str());\r
        }\r
 \r
-       g.m_hHookDataArch = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,\r
-                                                                                 0, sizeof(HookDataArch),\r
-                                                                                 addSessionId(HOOK_DATA_NAME_ARCH).c_str());\r
-       if (!g.m_hHookDataArch) {\r
+       if (g.m_hHookData == NULL || g.m_hHookDataArch == NULL) {\r
                unmapHookData();\r
                return false;\r
        }\r
 \r
-       s_hookDataArch =\r
-               (HookDataArch *)MapViewOfFile(g.m_hHookDataArch, FILE_MAP_READ | FILE_MAP_WRITE,\r
-                                                                         0, 0, sizeof(HookDataArch));\r
-       if (!s_hookDataArch) {\r
+       g_hookData = (HookData *)MapViewOfFile(g.m_hHookData, access, 0, 0, sizeof(HookData));\r
+       s_hookDataArch = (HookDataArch *)MapViewOfFile(g.m_hHookDataArch, access, 0, 0, sizeof(HookDataArch));\r
+       if (g_hookData == NULL || s_hookDataArch == NULL) {\r
                unmapHookData();\r
                return false;\r
        }\r
@@ -223,7 +259,7 @@ static void unmapHookData()
 \r
 \r
 /// notify\r
-DllExport bool notify(void *i_data, size_t i_dataSize)\r
+bool notify(void *i_data, size_t i_dataSize)\r
 {\r
        COPYDATASTRUCT cd;\r
 #ifdef MAYU64\r
@@ -232,7 +268,6 @@ DllExport bool notify(void *i_data, size_t i_dataSize)
        DWORD result;\r
 #endif // MAYU64\r
 \r
-#ifdef USE_MAILSLOT\r
        DWORD len;\r
        if (g.m_hMailslot != INVALID_HANDLE_VALUE) {\r
                BOOL ret;\r
@@ -244,20 +279,19 @@ DllExport bool notify(void *i_data, size_t i_dataSize)
                        HOOK_RPT1("MAYU: %S WriteFile to mailslot successed\r\n", g.m_moduleName);\r
                }\r
 #endif // !NDEBUG\r
+       } else {\r
+               cd.dwData = reinterpret_cast<Notify *>(i_data)->m_type;\r
+               cd.cbData = i_dataSize;\r
+               cd.lpData = i_data;\r
+               if (g.m_hwndTaskTray == 0 || cd.dwData == Notify::Type_threadDetach)\r
+                       return false;\r
+               if (!SendMessageTimeout(reinterpret_cast<HWND>(g.m_hwndTaskTray),\r
+                                                               WM_COPYDATA, NULL, reinterpret_cast<LPARAM>(&cd),\r
+                                                               SMTO_ABORTIFHUNG | SMTO_NORMAL, 5000, &result)) {\r
+                       _RPT0(_CRT_WARN, "MAYU: SendMessageTimeout() timeouted\r\n");\r
+                       return false;\r
+               }\r
        }\r
-#else // !USE_MAILSLOT\r
-       cd.dwData = reinterpret_cast<Notify *>(i_data)->m_type;\r
-       cd.cbData = i_dataSize;\r
-       cd.lpData = i_data;\r
-       if (g.m_hwndTaskTray == 0)\r
-               return false;\r
-       if (!SendMessageTimeout(reinterpret_cast<HWND>(g.m_hwndTaskTray),\r
-                                                       WM_COPYDATA, NULL, reinterpret_cast<LPARAM>(&cd),\r
-                                                       SMTO_ABORTIFHUNG | SMTO_NORMAL, 5000, &result)) {\r
-               _RPT0(_CRT_WARN, "MAYU: SendMessageTimeout() timeouted\r\n");\r
-               return false;\r
-       }\r
-#endif // !USE_MAILSLOT\r
        return true;\r
 }\r
 \r
@@ -400,17 +434,20 @@ static void notifyThreadDetach()
 static void notifyCommand(\r
        HWND i_hwnd, UINT i_message, WPARAM i_wParam, LPARAM i_lParam)\r
 {\r
-#ifndef _WIN64\r
        if (g_hookData->m_doesNotifyCommand) {\r
-               NotifyCommand ntc;\r
-               ntc.m_type = Notify::Type_command;\r
+#ifdef _WIN64\r
+               NotifyCommand64 ntc;\r
+               ntc.m_type = Notify::Type_command64;\r
+#else // !_WIN64\r
+               NotifyCommand32 ntc;\r
+               ntc.m_type = Notify::Type_command32;\r
+#endif // !_WIN64\r
                ntc.m_hwnd = i_hwnd;\r
                ntc.m_message = i_message;\r
                ntc.m_wParam = i_wParam;\r
                ntc.m_lParam = i_lParam;\r
                notify(&ntc, sizeof(ntc));\r
        }\r
-#endif\r
 }\r
 \r
 \r
@@ -549,7 +586,7 @@ DllExport void notifyLockState()
 LRESULT CALLBACK getMessageProc(int i_nCode, WPARAM i_wParam, LPARAM i_lParam)\r
 {\r
        if (!g.m_isInitialized)\r
-               initialize();\r
+               initialize(false);\r
 \r
        if (!g_hookData)\r
                return 0;\r
@@ -630,7 +667,7 @@ finally:
 LRESULT CALLBACK callWndProc(int i_nCode, WPARAM i_wParam, LPARAM i_lParam)\r
 {\r
        if (!g.m_isInitialized)\r
-               initialize();\r
+               initialize(false);\r
 \r
        if (!g_hookData)\r
                return 0;\r
@@ -741,58 +778,18 @@ LRESULT CALLBACK callWndProc(int i_nCode, WPARAM i_wParam, LPARAM i_lParam)
 \r
 static LRESULT CALLBACK lowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)\r
 {\r
-       MSLLHOOKSTRUCT *pMsll = (MSLLHOOKSTRUCT*)lParam;\r
-       LONG dx = pMsll->pt.x - g_hookData->m_mousePos.x;\r
-       LONG dy = pMsll->pt.y - g_hookData->m_mousePos.y;\r
-       HWND target = reinterpret_cast<HWND>(g_hookData->m_hwndMouseHookTarget);\r
-\r
        if (!g.m_isInitialized)\r
-               initialize();\r
+               initialize(false);\r
 \r
-       if (!g_hookData || nCode < 0 || wParam != WM_MOUSEMOVE)\r
+       if (!g_hookData || nCode < 0)\r
                goto through;\r
 \r
-       switch (g_hookData->m_mouseHookType) {\r
-       case MouseHookType_Wheel:\r
-               // For this type, g_hookData->m_mouseHookParam means\r
-               // translate rate mouse move to wheel.\r
-               mouse_event(MOUSEEVENTF_WHEEL, 0, 0,\r
-                                       g_hookData->m_mouseHookParam * dy, 0);\r
-               return 1;\r
-               break;\r
-       case MouseHookType_WindowMove: {\r
-               RECT curRect;\r
-\r
-               if (!GetWindowRect(target, &curRect))\r
-                       goto through;\r
-\r
-               // g_hookData->m_mouseHookParam < 0 means\r
-               // target window to move is MDI.\r
-               if (g_hookData->m_mouseHookParam < 0) {\r
-                       HWND parent = GetParent(target);\r
-                       POINT p = {curRect.left, curRect.top};\r
-\r
-                       if (parent == NULL || !ScreenToClient(parent, &p))\r
-                               goto through;\r
-\r
-                       curRect.left = p.x;\r
-                       curRect.top = p.y;\r
+       if (g.m_mouseDetour && g.m_engine) {\r
+               unsigned int result;\r
+               result = g.m_mouseDetour(g.m_engine, wParam, lParam);\r
+               if (result) {\r
+                       return 1;\r
                }\r
-\r
-               SetWindowPos(target, NULL,\r
-                                        curRect.left + dx,\r
-                                        curRect.top + dy,\r
-                                        0, 0,\r
-                                        SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE |\r
-                                        SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);\r
-               g_hookData->m_mousePos = pMsll->pt;\r
-               goto through;\r
-               break;\r
-       }\r
-       case MouseHookType_None:\r
-       default:\r
-               goto through;\r
-               break;\r
        }\r
 \r
 through:\r
@@ -801,20 +798,19 @@ through:
 }\r
 \r
 \r
-#ifdef NO_DRIVER\r
 static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)\r
 {\r
        KBDLLHOOKSTRUCT *pKbll = (KBDLLHOOKSTRUCT*)lParam;\r
 \r
        if (!g.m_isInitialized)\r
-               initialize();\r
+               initialize(false);\r
 \r
        if (!g_hookData || nCode < 0)\r
                goto through;\r
 \r
        if (g.m_keyboardDetour && g.m_engine) {\r
                unsigned int result;\r
-               result = g.m_keyboardDetour(g.m_engine, pKbll);\r
+               result = g.m_keyboardDetour(g.m_engine, wParam, lParam);\r
                if (result) {\r
                        return 1;\r
                }\r
@@ -823,40 +819,29 @@ through:
        return CallNextHookEx(g.m_hHookKeyboardProc,\r
                                                  nCode, wParam, lParam);\r
 }\r
-#endif // NO_DRIVER\r
 \r
 \r
-/// install hooks\r
-DllExport int installHooks(KEYBOARD_DETOUR i_keyboardDetour, Engine *i_engine)\r
+/// install message hook\r
+DllExport int installMessageHook(DWORD i_hwndTaskTray)\r
 {\r
        if (!g.m_isInitialized)\r
-               initialize();\r
+               initialize(true);\r
 \r
+       if (i_hwndTaskTray) {\r
+               g_hookData->m_hwndTaskTray = i_hwndTaskTray;\r
+       }\r
        g.m_hwndTaskTray = g_hookData->m_hwndTaskTray;\r
        s_hookDataArch->m_hHookGetMessage =\r
                SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)getMessageProc,\r
                                                 g.m_hInstDLL, 0);\r
        s_hookDataArch->m_hHookCallWndProc =\r
                SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)callWndProc, g.m_hInstDLL, 0);\r
-       g_hookData->m_mouseHookType = MouseHookType_None;\r
-       if (i_engine != NULL) {\r
-#ifdef NO_DRIVER\r
-               g.m_keyboardDetour = i_keyboardDetour;\r
-               g.m_engine = i_engine;\r
-               g.m_hHookKeyboardProc =\r
-                       SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)lowLevelKeyboardProc,\r
-                                                        g.m_hInstDLL, 0);\r
-#endif // NO_DRIVER\r
-               g.m_hHookMouseProc =\r
-                       SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)lowLevelMouseProc,\r
-                                                        g.m_hInstDLL, 0);\r
-       }\r
        return 0;\r
 }\r
 \r
 \r
-/// uninstall hooks\r
-DllExport int uninstallHooks()\r
+/// uninstall message hook\r
+DllExport int uninstallMessageHook()\r
 {\r
        if (s_hookDataArch->m_hHookGetMessage)\r
                UnhookWindowsHookEx(s_hookDataArch->m_hHookGetMessage);\r
@@ -864,14 +849,49 @@ DllExport int uninstallHooks()
        if (s_hookDataArch->m_hHookCallWndProc)\r
                UnhookWindowsHookEx(s_hookDataArch->m_hHookCallWndProc);\r
        s_hookDataArch->m_hHookCallWndProc = NULL;\r
-       if (g.m_hHookMouseProc)\r
-               UnhookWindowsHookEx(g.m_hHookMouseProc);\r
-       g.m_hHookMouseProc = NULL;\r
-#ifdef NO_DRIVER\r
-       if (g.m_hHookKeyboardProc)\r
-               UnhookWindowsHookEx(g.m_hHookKeyboardProc);\r
-       g.m_hHookKeyboardProc = NULL;\r
-#endif // NO_DRIVER\r
        g.m_hwndTaskTray = 0;\r
        return 0;\r
 }\r
+\r
+\r
+/// install keyboard hook\r
+DllExport int installKeyboardHook(INPUT_DETOUR i_keyboardDetour, Engine *i_engine, bool i_install)\r
+{\r
+       if (i_install) {\r
+               if (!g.m_isInitialized)\r
+                       initialize(true);\r
+\r
+               g.m_keyboardDetour = i_keyboardDetour;\r
+               g.m_engine = i_engine;\r
+               g.m_hHookKeyboardProc =\r
+                       SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)lowLevelKeyboardProc,\r
+                                                        g.m_hInstDLL, 0);\r
+       } else {\r
+               if (g.m_hHookKeyboardProc)\r
+                       UnhookWindowsHookEx(g.m_hHookKeyboardProc);\r
+               g.m_hHookKeyboardProc = NULL;\r
+       }\r
+       return 0;\r
+}\r
+\r
+\r
+/// install mouse hook\r
+DllExport int installMouseHook(INPUT_DETOUR i_mouseDetour, Engine *i_engine, bool i_install)\r
+{\r
+       if (i_install) {\r
+               if (!g.m_isInitialized)\r
+                       initialize(true);\r
+\r
+               g.m_mouseDetour = i_mouseDetour;\r
+               g.m_engine = i_engine;\r
+               g_hookData->m_mouseHookType = MouseHookType_None;\r
+               g.m_hHookMouseProc =\r
+                       SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)lowLevelMouseProc,\r
+                                                        g.m_hInstDLL, 0);\r
+       } else {\r
+               if (g.m_hHookMouseProc)\r
+                       UnhookWindowsHookEx(g.m_hHookMouseProc);\r
+               g.m_hHookMouseProc = NULL;\r
+       }\r
+       return 0;\r
+}\r