OSDN Git Service

use boost_1_56_0 and build by VS2013
[yamy/yamy.git] / mayu.cpp
index 836bf46..91653b8 100644 (file)
--- a/mayu.cpp
+++ b/mayu.cpp
@@ -64,16 +64,20 @@ class Mayu
 #endif // LOG_TO_FILE\r
 \r
        HMENU m_hMenuTaskTray;                  /// tasktray menu\r
+#ifdef _WIN64\r
+       HANDLE m_hMutexYamyd;\r
        STARTUPINFO m_si;\r
        PROCESS_INFORMATION m_pi;\r
+#endif // _WIN64\r
        HANDLE m_mutex;\r
-#ifdef USE_MAILSLOT\r
        HANDLE m_hNotifyMailslot;                       /// mailslot to receive notify\r
        HANDLE m_hNotifyEvent;                  /// event on receive notify\r
        OVERLAPPED m_olNotify;                  ///\r
        BYTE m_notifyBuf[NOTIFY_MESSAGE_SIZE];\r
-#endif // USE_MAILSLOT\r
-       bool m_isConsoleConnected;\r
+       static const DWORD SESSION_LOCKED = 1<<0;\r
+       static const DWORD SESSION_DISCONNECTED = 1<<1;\r
+       static const DWORD SESSION_END_QUERIED = 1<<2;\r
+       DWORD m_sessionState;\r
        int m_escapeNlsKeys;\r
        FixScancodeMap m_fixScancodeMap;\r
 \r
@@ -88,11 +92,15 @@ class Mayu
        enum {\r
                WM_APP_taskTrayNotify = WM_APP + 101,   ///\r
                WM_APP_msgStreamNotify = WM_APP + 102,  ///\r
+               WM_APP_escapeNLSKeysFailed = WM_APP + 121,      ///\r
                ID_TaskTrayIcon = 1,                    ///\r
        };\r
 \r
+       enum {\r
+               YAMY_TIMER_ESCAPE_NLS_KEYS = 0, ///\r
+       };\r
+\r
 private:\r
-#ifdef USE_MAILSLOT\r
        static VOID CALLBACK mailslotProc(DWORD i_code, DWORD i_len, LPOVERLAPPED i_ol) {\r
                Mayu *pThis;\r
 \r
@@ -120,7 +128,6 @@ private:
                                                        &m_olNotify, Mayu::mailslotProc);\r
                return result;\r
        }\r
-#endif // USE_MAILSLOT\r
 \r
        /// register class for tasktray\r
        ATOM Register_tasktray() {\r
@@ -217,14 +224,27 @@ private:
                        break;\r
                }\r
 \r
+               case Notify::Type_threadAttach: {\r
+                       NotifyThreadAttach *n = (NotifyThreadAttach *)cd->lpData;\r
+                       m_engine.threadAttachNotify(n->m_threadId);\r
+                       break;\r
+               }\r
+\r
                case Notify::Type_threadDetach: {\r
                        NotifyThreadDetach *n = (NotifyThreadDetach *)cd->lpData;\r
                        m_engine.threadDetachNotify(n->m_threadId);\r
                        break;\r
                }\r
 \r
-               case Notify::Type_command: {\r
-                       NotifyCommand *n = (NotifyCommand *)cd->lpData;\r
+               case Notify::Type_command64: {\r
+                       NotifyCommand64 *n = (NotifyCommand64 *)cd->lpData;\r
+                       m_engine.commandNotify(n->m_hwnd, n->m_message,\r
+                                                                  n->m_wParam, n->m_lParam);\r
+                       break;\r
+               }\r
+\r
+               case Notify::Type_command32: {\r
+                       NotifyCommand32 *n = (NotifyCommand32 *)cd->lpData;\r
                        m_engine.commandNotify(n->m_hwnd, n->m_message,\r
                                                                   n->m_wParam, n->m_lParam);\r
                        break;\r
@@ -272,12 +292,9 @@ private:
                        case WM_CREATE:\r
                                This = reinterpret_cast<Mayu *>(\r
                                                   reinterpret_cast<CREATESTRUCT *>(i_lParam)->lpCreateParams);\r
+                               This->m_fixScancodeMap.init(i_hwnd, WM_APP_escapeNLSKeysFailed);\r
                                if (This->m_escapeNlsKeys) {\r
-                                       int err;\r
-                                       err = This->m_fixScancodeMap.fix();\r
-                                       if (err) {\r
-                                               This->errorDialogWithCode(IDS_escapeNlsKeysFailed, err);\r
-                                       }\r
+                                       This->m_fixScancodeMap.escape(true);\r
                                }\r
 #ifdef MAYU64\r
                                SetWindowLongPtr(i_hwnd, 0, (LONG_PTR)This);\r
@@ -294,6 +311,12 @@ private:
                                return This->notifyHandler(cd);\r
                        }\r
                        case WM_QUERYENDSESSION:\r
+                               if (!This->m_sessionState) {\r
+                                       if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) {\r
+                                               This->m_fixScancodeMap.escape(false);\r
+                                       }\r
+                               }\r
+                               This->m_sessionState |= Mayu::SESSION_END_QUERIED;\r
                                This->m_engine.prepairQuit();\r
                                PostQuitMessage(0);\r
                                return TRUE;\r
@@ -314,41 +337,45 @@ private:
 #  define WTS_SESSION_LOCK                   0x7\r
 #  define WTS_SESSION_UNLOCK                 0x8\r
 #endif\r
-/*\r
-       order of WTS_* messages:\r
-       <case1>screen lock -> screen unlock\r
-       <case2>change of user -> logon by same user\r
-               (1)WTS_SESSION_LOCK                     ... restore Scancode Map\r
-               (2)WTS_SESSION_UNLOCK           ... re-fix Scancode Map\r
-\r
-       <case3>change of user -> logon by another user -> change of user -> logon by previous user\r
-               (1)WTS_SESSION_LOCK                     ... restore Scancode Map\r
-               (2)WTS_CONSOLE_CONNECT          ... mark disconnection(m_isConsoleConnected=false)\r
-               (3)WTS_SESSION_UNLOCK           ... (re-fix Scancode Map is not effective here!)\r
-               (4)WTS_CONSOLE_DISCONNECT       ... re-fix Scancode Map\r
-*/\r
+                               /*\r
+                                       restore NLS keys when any bits of m_sessionState is on\r
+                                       and\r
+                                       escape NLS keys when all bits of m_sessionState cleared\r
+                               */\r
                                case WTS_CONSOLE_CONNECT:\r
-                                       if (This->m_isConsoleConnected == false) {\r
-                                               This->m_isConsoleConnected = true;\r
-                                               if (This->m_escapeNlsKeys) {\r
-                                                       int ret;\r
-                                                       \r
-                                                       ret = This->m_fixScancodeMap.fix();\r
-                                                       if (ret) {\r
-                                                               This->m_log << _T("escape NLS keys failed: ") << ret << std::endl;\r
-                                                       }\r
+                                       This->m_sessionState &= ~Mayu::SESSION_DISCONNECTED;\r
+                                       if (!This->m_sessionState) {\r
+                                               if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) {\r
+                                                       This->m_fixScancodeMap.escape(true);\r
                                                }\r
                                        }\r
                                        m = "WTS_CONSOLE_CONNECT";\r
                                        break;\r
                                case WTS_CONSOLE_DISCONNECT:\r
-                                       This->m_isConsoleConnected = false;\r
+                                       if (!This->m_sessionState) {\r
+                                               if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) {\r
+                                                       This->m_fixScancodeMap.escape(false);\r
+                                               }\r
+                                       }\r
+                                       This->m_sessionState |= Mayu::SESSION_DISCONNECTED;\r
                                        m = "WTS_CONSOLE_DISCONNECT";\r
                                        break;\r
                                case WTS_REMOTE_CONNECT:\r
+                                       This->m_sessionState &= ~Mayu::SESSION_DISCONNECTED;\r
+                                       if (!This->m_sessionState) {\r
+                                               if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) {\r
+                                                       This->m_fixScancodeMap.escape(true);\r
+                                               }\r
+                                       }\r
                                        m = "WTS_REMOTE_CONNECT";\r
                                        break;\r
                                case WTS_REMOTE_DISCONNECT:\r
+                                       if (!This->m_sessionState) {\r
+                                               if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) {\r
+                                                       This->m_fixScancodeMap.escape(false);\r
+                                               }\r
+                                       }\r
+                                       This->m_sessionState |= Mayu::SESSION_DISCONNECTED;\r
                                        m = "WTS_REMOTE_DISCONNECT";\r
                                        break;\r
                                case WTS_SESSION_LOGON:\r
@@ -358,26 +385,20 @@ private:
                                        m = "WTS_SESSION_LOGOFF";\r
                                        break;\r
                                case WTS_SESSION_LOCK: {\r
-                                       if (This->m_escapeNlsKeys) {\r
-                                               int ret;\r
-\r
-                                               ret = This->m_fixScancodeMap.restore();\r
-                                               if (ret) {\r
-                                                       This->m_log << _T("restore NLS keys failed: ") << ret << std::endl;\r
+                                       if (!This->m_sessionState) {\r
+                                               if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) {\r
+                                                       This->m_fixScancodeMap.escape(false);\r
                                                }\r
                                        }\r
+                                       This->m_sessionState |= Mayu::SESSION_LOCKED;\r
                                        m = "WTS_SESSION_LOCK";\r
                                        break;\r
                           }\r
                                case WTS_SESSION_UNLOCK: {\r
-                                       if (This->m_isConsoleConnected == true) {\r
-                                               if (This->m_escapeNlsKeys) {\r
-                                                       int ret;\r
-\r
-                                                       ret = This->m_fixScancodeMap.fix();\r
-                                                       if (ret) {\r
-                                                               This->m_log << _T("escape NLS keys failed: ") << ret << std::endl;\r
-                                                       }\r
+                                       This->m_sessionState &= ~Mayu::SESSION_LOCKED;\r
+                                       if (!This->m_sessionState) {\r
+                                               if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) {\r
+                                                       This->m_fixScancodeMap.escape(true);\r
                                                }\r
                                        }\r
                                        m = "WTS_SESSION_UNLOCK";\r
@@ -467,6 +488,32 @@ private:
                                return 0;\r
                        }\r
 \r
+                       case WM_APP_escapeNLSKeysFailed:\r
+                               if (i_lParam) {\r
+                                       int ret;\r
+\r
+                                       This->m_log << _T("escape NLS keys done code=") << i_wParam << std::endl;\r
+                                       switch (i_wParam) {\r
+                                       case YAMY_SUCCESS:\r
+                                       case YAMY_ERROR_RETRY_INJECTION_SUCCESS:\r
+                                               // escape NLS keys success\r
+                                               break;\r
+                                       case YAMY_ERROR_TIMEOUT_INJECTION:\r
+                                               ret = This->errorDialogWithCode(IDS_escapeNlsKeysRetry, i_wParam, MB_RETRYCANCEL | MB_ICONSTOP);\r
+                                               if (ret == IDRETRY) {\r
+                                                       This->m_fixScancodeMap.escape(true);\r
+                                               }\r
+                                               break;\r
+                                       default:\r
+                                               This->errorDialogWithCode(IDS_escapeNlsKeysFailed, i_wParam, MB_OK);\r
+                                               break;\r
+                                       }\r
+                               } else {\r
+                                       This->m_log << _T("restore NLS keys done with code=") << i_wParam << std::endl;\r
+                               }\r
+                               return 0;\r
+                               break;\r
+\r
                        case WM_COMMAND: {\r
                                int notify_code = HIWORD(i_wParam);\r
                                int id = LOWORD(i_wParam);\r
@@ -562,6 +609,11 @@ private:
                                        }\r
                                        case ID_MENUITEM_disable:\r
                                                This->m_engine.enable(!This->m_engine.getIsEnabled());\r
+                                               if (This->m_engine.getIsEnabled()) {\r
+                                                       This->m_fixScancodeMap.escape(true);\r
+                                               } else {\r
+                                                       This->m_fixScancodeMap.escape(false);\r
+                                               }\r
                                                This->showTasktrayIcon();\r
                                                break;\r
                                        case ID_MENUITEM_quit:\r
@@ -648,11 +700,9 @@ private:
                                        wtsUnRegisterSessionNotification(i_hwnd);\r
                                        This->m_usingSN = false;\r
                                }\r
-                               if (This->m_escapeNlsKeys) {\r
-                                       int err;\r
-                                       err = This->m_fixScancodeMap.restore();\r
-                                       if (err) {\r
-                                               This->errorDialogWithCode(IDS_escapeNlsKeysFailed, err);\r
+                               if (!This->m_sessionState) {\r
+                                       if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) {\r
+                                               This->m_fixScancodeMap.escape(false);\r
                                        }\r
                                }\r
                                return 0;\r
@@ -671,6 +721,11 @@ private:
                                        switch (static_cast<MayuIPCCommand>(i_wParam)) {\r
                                        case MayuIPCCommand_Enable:\r
                                                This->m_engine.enable(!!i_lParam);\r
+                                               if (This->m_engine.getIsEnabled()) {\r
+                                                       This->m_fixScancodeMap.escape(true);\r
+                                               } else {\r
+                                                       This->m_fixScancodeMap.escape(false);\r
+                                               }\r
                                                This->showTasktrayIcon();\r
                                                if (i_lParam) {\r
                                                        Acquire a(&This->m_log, 1);\r
@@ -799,15 +854,14 @@ private:
                }\r
        }\r
 \r
-       bool errorDialogWithCode(UINT ids, int code)\r
+       int errorDialogWithCode(UINT ids, int code, UINT style = MB_OK | MB_ICONSTOP)\r
        {\r
                _TCHAR title[1024];\r
                _TCHAR text[1024];\r
 \r
                _sntprintf_s(title, NUMBER_OF(title), _TRUNCATE, loadString(IDS_mayu).c_str());\r
                _sntprintf_s(text, NUMBER_OF(text), _TRUNCATE, loadString(ids).c_str(), code);\r
-               MessageBox((HWND)NULL, text, title, MB_OK | MB_ICONSTOP);\r
-               return true;\r
+               return MessageBox((HWND)NULL, text, title, style);\r
        }\r
 \r
        int enableToWriteByUser(HANDLE hdl)\r
@@ -836,7 +890,7 @@ private:
 \r
                ret = GetUserName(userName, &userNameSize);\r
                if (ret == FALSE) {\r
-                       err = 1;\r
+                       err = YAMY_ERROR_ON_GET_USERNAME;\r
                        goto exit;\r
                }\r
 \r
@@ -844,14 +898,14 @@ private:
                ret = LookupAccountName(NULL, userName, pSid, &sidSize, pDomain, &domainSize, &sidType);\r
                if (ret != FALSE || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {\r
                        // above call should fail by ERROR_INSUFFICIENT_BUFFER\r
-                       err = 2;\r
+                       err = YAMY_ERROR_ON_GET_LOGONUSERNAME;\r
                        goto exit;\r
                }\r
 \r
                pSid = reinterpret_cast<PSID>(LocalAlloc(LPTR, sidSize));\r
                pDomain = reinterpret_cast<TCHAR*>(LocalAlloc(LPTR, domainSize * sizeof(TCHAR)));\r
                if (pSid == NULL || pDomain == NULL) {\r
-                       err = 3;\r
+                       err = YAMY_ERROR_NO_MEMORY;\r
                        goto exit;\r
                }\r
 \r
@@ -859,21 +913,21 @@ private:
                ret = LookupAccountName(NULL, userName, pSid, &sidSize, pDomain, &domainSize, &sidType);\r
                if (ret == FALSE) {\r
                        // LookupAccountName() should success in this time\r
-                       err = 4;\r
+                       err = YAMY_ERROR_ON_GET_LOGONUSERNAME;\r
                        goto exit;\r
                }\r
 \r
                // get DACL for hdl\r
                ret = GetSecurityInfo(hdl, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOrigDacl, NULL, &pSd);\r
                if (ret != ERROR_SUCCESS) {\r
-                       err = 5;\r
+                       err = YAMY_ERROR_ON_GET_SECURITYINFO;\r
                        goto exit;\r
                }\r
 \r
                // get size for original DACL\r
                ret = GetAclInformation(pOrigDacl, &aclInfo, sizeof(aclInfo), AclSizeInformation);\r
                if (ret == FALSE) {\r
-                       err = 6;\r
+                       err = YAMY_ERROR_ON_GET_DACL;\r
                        goto exit;\r
                }\r
 \r
@@ -883,14 +937,14 @@ private:
                // allocate memory for new DACL\r
                pNewDacl = reinterpret_cast<PACL>(LocalAlloc(LPTR, newDaclSize));\r
                if (pNewDacl == NULL) {\r
-                       err = 7;\r
+                       err = YAMY_ERROR_NO_MEMORY;\r
                        goto exit;\r
                }\r
 \r
                // initialize new DACL\r
                ret = InitializeAcl(pNewDacl, newDaclSize, ACL_REVISION);\r
                if (ret == FALSE) {\r
-                       err = 8;\r
+                       err = YAMY_ERROR_ON_INITIALIZE_ACL;\r
                        goto exit;\r
                }\r
 \r
@@ -900,7 +954,7 @@ private:
 \r
                        ret = GetAce(pOrigDacl, aceIndex, &pAce);\r
                        if (ret == FALSE) {\r
-                               err = 9;\r
+                               err = YAMY_ERROR_ON_GET_ACE;\r
                                goto exit;\r
                        }\r
 \r
@@ -914,7 +968,7 @@ private:
 \r
                        ret = AddAce(pNewDacl, ACL_REVISION, MAXDWORD, pAce, (reinterpret_cast<PACE_HEADER>(pAce))->AceSize);\r
                        if (ret == FALSE) {\r
-                               err = 10;\r
+                               err = YAMY_ERROR_ON_ADD_ACE;\r
                                goto exit;\r
                        }\r
 \r
@@ -923,7 +977,7 @@ private:
 \r
                ret = AddAccessAllowedAce(pNewDacl, ACL_REVISION, GENERIC_ALL, pSid);\r
                if (ret == FALSE) {\r
-                       err = 11;\r
+                       err = YAMY_ERROR_ON_ADD_ALLOWED_ACE;\r
                        goto exit;\r
                }\r
 \r
@@ -933,20 +987,20 @@ private:
 \r
                        ret = GetAce(pOrigDacl, aceIndex, &pAce);\r
                        if (ret == FALSE) {\r
-                               err = 12;\r
+                               err = YAMY_ERROR_ON_GET_ACE;\r
                                goto exit;\r
                        }\r
 \r
                        ret = AddAce(pNewDacl, ACL_REVISION, MAXDWORD, pAce, (reinterpret_cast<PACE_HEADER>(pAce))->AceSize);\r
                        if (ret == FALSE) {\r
-                               err = 13;\r
+                               err = YAMY_ERROR_ON_ADD_ACE;\r
                                goto exit;\r
                        }\r
                }\r
 \r
                ret = SetSecurityInfo(hdl, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL);\r
                if (ret != ERROR_SUCCESS) {\r
-                       err = 14;\r
+                       err = YAMY_ERROR_ON_SET_SECURITYINFO;\r
                }\r
 \r
 exit:\r
@@ -971,11 +1025,10 @@ public:
                        m_log(WM_APP_msgStreamNotify),\r
                        m_setting(NULL),\r
                        m_isSettingDialogOpened(false),\r
-                       m_isConsoleConnected(true),\r
+                       m_sessionState(0),\r
                        m_engine(m_log) {\r
                Registry reg(MAYU_REGISTRY_ROOT);\r
                reg.read(_T("escapeNLSKeys"), &m_escapeNlsKeys, 0);\r
-#ifdef USE_MAILSLOT\r
                m_hNotifyMailslot = CreateMailslot(NOTIFY_MAILSLOT_NAME, 0, MAILSLOT_WAIT_FOREVER, (SECURITY_ATTRIBUTES *)NULL);\r
                ASSERT(m_hNotifyMailslot != INVALID_HANDLE_VALUE);\r
                int err;\r
@@ -991,7 +1044,6 @@ public:
                m_olNotify.Offset = 0;\r
                m_olNotify.OffsetHigh = 0;\r
                m_olNotify.hEvent = m_hNotifyEvent;\r
-#endif // USE_MAILSLOT\r
                time(&m_startTime);\r
 \r
                CHECK_TRUE( Register_focus() );\r
@@ -1017,10 +1069,7 @@ public:
                CHECK_TRUE( m_hwndTaskTray );\r
 \r
                // set window handle of tasktray to hooks\r
-#ifndef USE_MAILSLOT\r
-               g_hookData->m_hwndTaskTray = reinterpret_cast<DWORD>(m_hwndTaskTray);\r
-#endif // !USE_MAILSLOT\r
-               CHECK_FALSE( installMessageHook() );\r
+               CHECK_FALSE( installMessageHook(reinterpret_cast<DWORD>(m_hwndTaskTray)) );\r
                m_usingSN = wtsRegisterSessionNotification(m_hwndTaskTray,\r
                                        NOTIFY_FOR_THIS_SESSION);\r
 \r
@@ -1043,7 +1092,7 @@ public:
                m_hwndVersion =\r
                        CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_version),\r
                                                          NULL, dlgVersion_dlgProc,\r
-                                                         (LPARAM)m_engine.getMayudVersion().c_str());\r
+                                                         (LPARAM)_T(""));\r
                CHECK_TRUE( m_hwndVersion );\r
 \r
                // attach log\r
@@ -1079,7 +1128,7 @@ public:
                tstring tip = loadString(IDS_mayu);\r
                tcslcpy(m_ni.szTip, tip.c_str(), NUMBER_OF(m_ni.szTip));\r
                if (m_canUseTasktrayBaloon) {\r
-                       m_ni.cbSize = sizeof(m_ni);\r
+                       m_ni.cbSize = NOTIFYICONDATA_V3_SIZE;\r
                        m_ni.uFlags |= NIF_INFO;\r
                } else\r
                        m_ni.cbSize = NOTIFYICONDATA_V1_SIZE;\r
@@ -1092,19 +1141,33 @@ public:
                // set initial lock state\r
                notifyLockState();\r
 \r
-               BOOL result;\r
-\r
+#ifdef _WIN64\r
                ZeroMemory(&m_pi,sizeof(m_pi));\r
                ZeroMemory(&m_si,sizeof(m_si));\r
                m_si.cb=sizeof(m_si);\r
-#ifdef _WIN64\r
-               result = CreateProcess(_T("yamyd32"), _T("yamyd32"), NULL, NULL, FALSE,\r
+\r
+               // create mutex to block yamyd\r
+               m_hMutexYamyd = CreateMutex((SECURITY_ATTRIBUTES *)NULL, TRUE, MUTEX_YAMYD_BLOCKER);\r
+\r
+               tstring yamydPath;\r
+               _TCHAR exePath[GANA_MAX_PATH];\r
+               _TCHAR exeDrive[GANA_MAX_PATH];\r
+               _TCHAR exeDir[GANA_MAX_PATH];\r
+\r
+               GetModuleFileName(NULL, exePath, GANA_MAX_PATH);\r
+               _tsplitpath_s(exePath, exeDrive, GANA_MAX_PATH, exeDir, GANA_MAX_PATH, NULL, 0, NULL, 0);\r
+               yamydPath = exeDrive;\r
+               yamydPath += exeDir;\r
+               yamydPath += _T("yamyd32");\r
+\r
+               BOOL result = CreateProcess(yamydPath.c_str(), NULL, NULL, NULL, FALSE,\r
                                                           NORMAL_PRIORITY_CLASS, 0, NULL, &m_si, &m_pi);\r
                if (result == FALSE) {\r
                        TCHAR buf[1024];\r
                        TCHAR text[1024];\r
                        TCHAR title[1024];\r
 \r
+                       m_pi.hProcess = NULL;\r
                        LoadString(GetModuleHandle(NULL), IDS_cannotInvoke,\r
                                           text, sizeof(text)/sizeof(text[0]));\r
                        LoadString(GetModuleHandle(NULL), IDS_mayu,\r
@@ -1114,19 +1177,29 @@ public:
                        MessageBox((HWND)NULL, buf, title, MB_OK | MB_ICONSTOP);\r
                } else {\r
                        CloseHandle(m_pi.hThread);\r
-                       CloseHandle(m_pi.hProcess);\r
                }\r
 #endif // _WIN64\r
        }\r
 \r
        ///\r
        ~Mayu() {\r
-#ifdef USE_MAILSLOT\r
+               // stop notify from mayu.dll\r
+               g_hookData->m_hwndTaskTray = NULL;\r
+               CHECK_FALSE( uninstallMessageHook() );\r
+\r
+#ifdef _WIN64\r
+               ReleaseMutex(m_hMutexYamyd);\r
+               if (m_pi.hProcess) {\r
+                       WaitForSingleObject(m_pi.hProcess, 5000);\r
+                       CloseHandle(m_pi.hProcess);\r
+               }\r
+               CloseHandle(m_hMutexYamyd);\r
+#endif // _WIN64\r
+\r
                CancelIo(m_hNotifyMailslot);\r
                SleepEx(0, TRUE);\r
                CloseHandle(m_hNotifyMailslot);\r
                CloseHandle(m_hNotifyEvent);\r
-#endif // USE_MAILSLOT\r
                ReleaseMutex(m_mutex);\r
                WaitForSingleObject(m_mutex, INFINITE);\r
                // first, detach log from edit control to avoid deadlock\r
@@ -1135,11 +1208,6 @@ public:
                m_logFile.close();\r
 #endif // LOG_TO_FILE\r
 \r
-               // stop notify from mayu.dll\r
-               g_hookData->m_hwndTaskTray = NULL;\r
-               CHECK_FALSE( uninstallMessageHook() );\r
-               PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);\r
-\r
                // destroy windows\r
                CHECK_TRUE( DestroyWindow(m_hwndVersion) );\r
                CHECK_TRUE( DestroyWindow(m_hwndInvestigate) );\r
@@ -1157,6 +1225,11 @@ public:
                // stop keyboard handler thread\r
                m_engine.stop();\r
 \r
+               if (!(m_sessionState & SESSION_END_QUERIED)) {\r
+                       DWORD_PTR result;\r
+                       SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, 0, 3000, &result);\r
+               }\r
+\r
                // remove setting;\r
                delete m_setting;\r
        }\r
@@ -1166,7 +1239,6 @@ public:
                showBanner(false);\r
                load();\r
 \r
-#ifdef USE_MAILSLOT\r
                mailslotHandler(0, 0);\r
                while (1) {\r
                        HANDLE handles[] = { m_hNotifyEvent };\r
@@ -1203,20 +1275,6 @@ public:
                                break;\r
                        }\r
                }\r
-#else // !USE_MAILSLOT\r
-               MSG msg;\r
-               while (0 < GetMessage(&msg, NULL, 0, 0)) {\r
-                       if (IsDialogMessage(m_hwndLog, &msg))\r
-                               continue;\r
-                       if (IsDialogMessage(m_hwndInvestigate, &msg))\r
-                               continue;\r
-                       if (IsDialogMessage(m_hwndVersion, &msg))\r
-                               continue;\r
-                       TranslateMessage(&msg);\r
-                       DispatchMessage(&msg);\r
-               }\r
-               return msg.wParam;\r
-#endif // !USE_MAILSLOT\r
        }\r
 };\r
 \r