X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;ds=sidebyside;f=mayu.cpp;h=91653b86894a4ce31fb7232eb768a39de7c3a4a0;hb=HEAD;hp=1476585a457b9f8e50d9e57553b53836612ed995;hpb=40f19a87d0fe4275f1fa31773076a2063b231e3e;p=yamy%2Fyamy.git diff --git a/mayu.cpp b/mayu.cpp index 1476585..91653b8 100644 --- a/mayu.cpp +++ b/mayu.cpp @@ -64,16 +64,20 @@ class Mayu #endif // LOG_TO_FILE HMENU m_hMenuTaskTray; /// tasktray menu +#ifdef _WIN64 + HANDLE m_hMutexYamyd; STARTUPINFO m_si; PROCESS_INFORMATION m_pi; +#endif // _WIN64 HANDLE m_mutex; -#ifdef USE_MAILSLOT HANDLE m_hNotifyMailslot; /// mailslot to receive notify HANDLE m_hNotifyEvent; /// event on receive notify OVERLAPPED m_olNotify; /// BYTE m_notifyBuf[NOTIFY_MESSAGE_SIZE]; -#endif // USE_MAILSLOT - bool m_isConsoleConnected; + static const DWORD SESSION_LOCKED = 1<<0; + static const DWORD SESSION_DISCONNECTED = 1<<1; + static const DWORD SESSION_END_QUERIED = 1<<2; + DWORD m_sessionState; int m_escapeNlsKeys; FixScancodeMap m_fixScancodeMap; @@ -88,11 +92,15 @@ class Mayu enum { WM_APP_taskTrayNotify = WM_APP + 101, /// WM_APP_msgStreamNotify = WM_APP + 102, /// + WM_APP_escapeNLSKeysFailed = WM_APP + 121, /// ID_TaskTrayIcon = 1, /// }; + enum { + YAMY_TIMER_ESCAPE_NLS_KEYS = 0, /// + }; + private: -#ifdef USE_MAILSLOT static VOID CALLBACK mailslotProc(DWORD i_code, DWORD i_len, LPOVERLAPPED i_ol) { Mayu *pThis; @@ -120,7 +128,6 @@ private: &m_olNotify, Mayu::mailslotProc); return result; } -#endif // USE_MAILSLOT /// register class for tasktray ATOM Register_tasktray() { @@ -217,14 +224,27 @@ private: break; } + case Notify::Type_threadAttach: { + NotifyThreadAttach *n = (NotifyThreadAttach *)cd->lpData; + m_engine.threadAttachNotify(n->m_threadId); + break; + } + case Notify::Type_threadDetach: { NotifyThreadDetach *n = (NotifyThreadDetach *)cd->lpData; m_engine.threadDetachNotify(n->m_threadId); break; } - case Notify::Type_command: { - NotifyCommand *n = (NotifyCommand *)cd->lpData; + case Notify::Type_command64: { + NotifyCommand64 *n = (NotifyCommand64 *)cd->lpData; + m_engine.commandNotify(n->m_hwnd, n->m_message, + n->m_wParam, n->m_lParam); + break; + } + + case Notify::Type_command32: { + NotifyCommand32 *n = (NotifyCommand32 *)cd->lpData; m_engine.commandNotify(n->m_hwnd, n->m_message, n->m_wParam, n->m_lParam); break; @@ -272,8 +292,9 @@ private: case WM_CREATE: This = reinterpret_cast( reinterpret_cast(i_lParam)->lpCreateParams); + This->m_fixScancodeMap.init(i_hwnd, WM_APP_escapeNLSKeysFailed); if (This->m_escapeNlsKeys) { - This->m_fixScancodeMap.fix(); + This->m_fixScancodeMap.escape(true); } #ifdef MAYU64 SetWindowLongPtr(i_hwnd, 0, (LONG_PTR)This); @@ -290,6 +311,12 @@ private: return This->notifyHandler(cd); } case WM_QUERYENDSESSION: + if (!This->m_sessionState) { + if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(false); + } + } + This->m_sessionState |= Mayu::SESSION_END_QUERIED; This->m_engine.prepairQuit(); PostQuitMessage(0); return TRUE; @@ -310,36 +337,45 @@ private: # define WTS_SESSION_LOCK 0x7 # define WTS_SESSION_UNLOCK 0x8 #endif -/* - order of WTS_* messages: - screen lock -> screen unlock - change of user -> logon by same user - (1)WTS_SESSION_LOCK ... restore Scancode Map - (2)WTS_SESSION_UNLOCK ... re-fix Scancode Map - - change of user -> logon by another user -> change of user -> logon by previous user - (1)WTS_SESSION_LOCK ... restore Scancode Map - (2)WTS_CONSOLE_CONNECT ... mark disconnection(m_isConsoleConnected=false) - (3)WTS_SESSION_UNLOCK ... (re-fix Scancode Map is not effective here!) - (4)WTS_CONSOLE_DISCONNECT ... re-fix Scancode Map -*/ + /* + restore NLS keys when any bits of m_sessionState is on + and + escape NLS keys when all bits of m_sessionState cleared + */ case WTS_CONSOLE_CONNECT: - if (This->m_isConsoleConnected == false) { - This->m_isConsoleConnected = true; - if (This->m_escapeNlsKeys) { - This->m_fixScancodeMap.fix(); + This->m_sessionState &= ~Mayu::SESSION_DISCONNECTED; + if (!This->m_sessionState) { + if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(true); } } m = "WTS_CONSOLE_CONNECT"; break; case WTS_CONSOLE_DISCONNECT: - This->m_isConsoleConnected = false; + if (!This->m_sessionState) { + if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(false); + } + } + This->m_sessionState |= Mayu::SESSION_DISCONNECTED; m = "WTS_CONSOLE_DISCONNECT"; break; case WTS_REMOTE_CONNECT: + This->m_sessionState &= ~Mayu::SESSION_DISCONNECTED; + if (!This->m_sessionState) { + if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(true); + } + } m = "WTS_REMOTE_CONNECT"; break; case WTS_REMOTE_DISCONNECT: + if (!This->m_sessionState) { + if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(false); + } + } + This->m_sessionState |= Mayu::SESSION_DISCONNECTED; m = "WTS_REMOTE_DISCONNECT"; break; case WTS_SESSION_LOGON: @@ -349,16 +385,20 @@ private: m = "WTS_SESSION_LOGOFF"; break; case WTS_SESSION_LOCK: { - if (This->m_escapeNlsKeys) { - This->m_fixScancodeMap.restore(); + if (!This->m_sessionState) { + if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(false); + } } + This->m_sessionState |= Mayu::SESSION_LOCKED; m = "WTS_SESSION_LOCK"; break; } case WTS_SESSION_UNLOCK: { - if (This->m_isConsoleConnected == true) { - if (This->m_escapeNlsKeys) { - This->m_fixScancodeMap.fix(); + This->m_sessionState &= ~Mayu::SESSION_LOCKED; + if (!This->m_sessionState) { + if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(true); } } m = "WTS_SESSION_UNLOCK"; @@ -448,6 +488,32 @@ private: return 0; } + case WM_APP_escapeNLSKeysFailed: + if (i_lParam) { + int ret; + + This->m_log << _T("escape NLS keys done code=") << i_wParam << std::endl; + switch (i_wParam) { + case YAMY_SUCCESS: + case YAMY_ERROR_RETRY_INJECTION_SUCCESS: + // escape NLS keys success + break; + case YAMY_ERROR_TIMEOUT_INJECTION: + ret = This->errorDialogWithCode(IDS_escapeNlsKeysRetry, i_wParam, MB_RETRYCANCEL | MB_ICONSTOP); + if (ret == IDRETRY) { + This->m_fixScancodeMap.escape(true); + } + break; + default: + This->errorDialogWithCode(IDS_escapeNlsKeysFailed, i_wParam, MB_OK); + break; + } + } else { + This->m_log << _T("restore NLS keys done with code=") << i_wParam << std::endl; + } + return 0; + break; + case WM_COMMAND: { int notify_code = HIWORD(i_wParam); int id = LOWORD(i_wParam); @@ -543,6 +609,11 @@ private: } case ID_MENUITEM_disable: This->m_engine.enable(!This->m_engine.getIsEnabled()); + if (This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(true); + } else { + This->m_fixScancodeMap.escape(false); + } This->showTasktrayIcon(); break; case ID_MENUITEM_quit: @@ -629,8 +700,10 @@ private: wtsUnRegisterSessionNotification(i_hwnd); This->m_usingSN = false; } - if (This->m_escapeNlsKeys) { - This->m_fixScancodeMap.restore(); + if (!This->m_sessionState) { + if (This->m_escapeNlsKeys && This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(false); + } } return 0; @@ -648,6 +721,11 @@ private: switch (static_cast(i_wParam)) { case MayuIPCCommand_Enable: This->m_engine.enable(!!i_lParam); + if (This->m_engine.getIsEnabled()) { + This->m_fixScancodeMap.escape(true); + } else { + This->m_fixScancodeMap.escape(false); + } This->showTasktrayIcon(); if (i_lParam) { Acquire a(&This->m_log, 1); @@ -776,7 +854,17 @@ private: } } - bool enableToWriteByUser(HANDLE hdl) + int errorDialogWithCode(UINT ids, int code, UINT style = MB_OK | MB_ICONSTOP) + { + _TCHAR title[1024]; + _TCHAR text[1024]; + + _sntprintf_s(title, NUMBER_OF(title), _TRUNCATE, loadString(IDS_mayu).c_str()); + _sntprintf_s(text, NUMBER_OF(text), _TRUNCATE, loadString(ids).c_str(), code); + return MessageBox((HWND)NULL, text, title, style); + } + + int enableToWriteByUser(HANDLE hdl) { TCHAR userName[GANA_MAX_ATOM_LENGTH]; DWORD userNameSize = NUMBER_OF(userName); @@ -798,46 +886,49 @@ private: DWORD newAceIndex = 0; BOOL ret; + int err = 0; ret = GetUserName(userName, &userNameSize); if (ret == FALSE) { - return false; + err = YAMY_ERROR_ON_GET_USERNAME; + goto exit; } // get buffer size for pSid (and pDomain) ret = LookupAccountName(NULL, userName, pSid, &sidSize, pDomain, &domainSize, &sidType); if (ret != FALSE || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { // above call should fail by ERROR_INSUFFICIENT_BUFFER - return false; + err = YAMY_ERROR_ON_GET_LOGONUSERNAME; + goto exit; } pSid = reinterpret_cast(LocalAlloc(LPTR, sidSize)); pDomain = reinterpret_cast(LocalAlloc(LPTR, domainSize * sizeof(TCHAR))); if (pSid == NULL || pDomain == NULL) { - LocalFree(pSid); - LocalFree(pDomain); - return false; + err = YAMY_ERROR_NO_MEMORY; + goto exit; } // get SID (and Domain) for logoned user ret = LookupAccountName(NULL, userName, pSid, &sidSize, pDomain, &domainSize, &sidType); if (ret == FALSE) { // LookupAccountName() should success in this time - LocalFree(pSid); - LocalFree(pDomain); - return false; + err = YAMY_ERROR_ON_GET_LOGONUSERNAME; + goto exit; } // get DACL for hdl ret = GetSecurityInfo(hdl, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOrigDacl, NULL, &pSd); if (ret != ERROR_SUCCESS) { - return false; + err = YAMY_ERROR_ON_GET_SECURITYINFO; + goto exit; } // get size for original DACL ret = GetAclInformation(pOrigDacl, &aclInfo, sizeof(aclInfo), AclSizeInformation); if (ret == FALSE) { - return false; + err = YAMY_ERROR_ON_GET_DACL; + goto exit; } // compute size for new DACL @@ -846,15 +937,15 @@ private: // allocate memory for new DACL pNewDacl = reinterpret_cast(LocalAlloc(LPTR, newDaclSize)); if (pNewDacl == NULL) { - LocalFree(pSid); - LocalFree(pDomain); - return false; + err = YAMY_ERROR_NO_MEMORY; + goto exit; } // initialize new DACL ret = InitializeAcl(pNewDacl, newDaclSize, ACL_REVISION); if (ret == FALSE) { - return false; + err = YAMY_ERROR_ON_INITIALIZE_ACL; + goto exit; } // copy original DACL to new DACL @@ -863,7 +954,8 @@ private: ret = GetAce(pOrigDacl, aceIndex, &pAce); if (ret == FALSE) { - return false; + err = YAMY_ERROR_ON_GET_ACE; + goto exit; } if ((reinterpret_cast(pAce))->Header.AceFlags & INHERITED_ACE) { @@ -876,7 +968,8 @@ private: ret = AddAce(pNewDacl, ACL_REVISION, MAXDWORD, pAce, (reinterpret_cast(pAce))->AceSize); if (ret == FALSE) { - return false; + err = YAMY_ERROR_ON_ADD_ACE; + goto exit; } newAceIndex++; @@ -884,7 +977,8 @@ private: ret = AddAccessAllowedAce(pNewDacl, ACL_REVISION, GENERIC_ALL, pSid); if (ret == FALSE) { - return false; + err = YAMY_ERROR_ON_ADD_ALLOWED_ACE; + goto exit; } // copy the rest of inherited ACEs @@ -893,27 +987,29 @@ private: ret = GetAce(pOrigDacl, aceIndex, &pAce); if (ret == FALSE) { - return false; + err = YAMY_ERROR_ON_GET_ACE; + goto exit; } ret = AddAce(pNewDacl, ACL_REVISION, MAXDWORD, pAce, (reinterpret_cast(pAce))->AceSize); if (ret == FALSE) { - return false; + err = YAMY_ERROR_ON_ADD_ACE; + goto exit; } } ret = SetSecurityInfo(hdl, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL); if (ret != ERROR_SUCCESS) { - DWORD err = GetLastError(); - return false; + err = YAMY_ERROR_ON_SET_SECURITYINFO; } +exit: LocalFree(pSd); LocalFree(pSid); LocalFree(pDomain); LocalFree(pNewDacl); - return true; + return err; } public: @@ -929,21 +1025,25 @@ public: m_log(WM_APP_msgStreamNotify), m_setting(NULL), m_isSettingDialogOpened(false), - m_isConsoleConnected(true), + m_sessionState(0), m_engine(m_log) { Registry reg(MAYU_REGISTRY_ROOT); reg.read(_T("escapeNLSKeys"), &m_escapeNlsKeys, 0); -#ifdef USE_MAILSLOT m_hNotifyMailslot = CreateMailslot(NOTIFY_MAILSLOT_NAME, 0, MAILSLOT_WAIT_FOREVER, (SECURITY_ATTRIBUTES *)NULL); ASSERT(m_hNotifyMailslot != INVALID_HANDLE_VALUE); - enableToWriteByUser(m_hNotifyMailslot); + int err; + if (checkWindowsVersion(6, 0) != FALSE) { // enableToWriteByUser() is available only Vista or later + err = enableToWriteByUser(m_hNotifyMailslot); + if (err) { + errorDialogWithCode(IDS_cannotPermitStandardUser, err); + } + } m_hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); ASSERT(m_hNotifyEvent); m_olNotify.Offset = 0; m_olNotify.OffsetHigh = 0; m_olNotify.hEvent = m_hNotifyEvent; -#endif // USE_MAILSLOT time(&m_startTime); CHECK_TRUE( Register_focus() ); @@ -969,10 +1069,7 @@ public: CHECK_TRUE( m_hwndTaskTray ); // set window handle of tasktray to hooks -#ifndef USE_MAILSLOT - g_hookData->m_hwndTaskTray = reinterpret_cast(m_hwndTaskTray); -#endif // !USE_MAILSLOT - CHECK_FALSE( installMessageHook() ); + CHECK_FALSE( installMessageHook(reinterpret_cast(m_hwndTaskTray)) ); m_usingSN = wtsRegisterSessionNotification(m_hwndTaskTray, NOTIFY_FOR_THIS_SESSION); @@ -995,7 +1092,7 @@ public: m_hwndVersion = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_version), NULL, dlgVersion_dlgProc, - (LPARAM)m_engine.getMayudVersion().c_str()); + (LPARAM)_T("")); CHECK_TRUE( m_hwndVersion ); // attach log @@ -1031,7 +1128,7 @@ public: tstring tip = loadString(IDS_mayu); tcslcpy(m_ni.szTip, tip.c_str(), NUMBER_OF(m_ni.szTip)); if (m_canUseTasktrayBaloon) { - m_ni.cbSize = sizeof(m_ni); + m_ni.cbSize = NOTIFYICONDATA_V3_SIZE; m_ni.uFlags |= NIF_INFO; } else m_ni.cbSize = NOTIFYICONDATA_V1_SIZE; @@ -1044,41 +1141,65 @@ public: // set initial lock state notifyLockState(); - BOOL result; - +#ifdef _WIN64 ZeroMemory(&m_pi,sizeof(m_pi)); ZeroMemory(&m_si,sizeof(m_si)); m_si.cb=sizeof(m_si); -#ifdef _WIN64 - result = CreateProcess(_T("yamyd32"), _T("yamyd32"), NULL, NULL, FALSE, + + // create mutex to block yamyd + m_hMutexYamyd = CreateMutex((SECURITY_ATTRIBUTES *)NULL, TRUE, MUTEX_YAMYD_BLOCKER); + + tstring yamydPath; + _TCHAR exePath[GANA_MAX_PATH]; + _TCHAR exeDrive[GANA_MAX_PATH]; + _TCHAR exeDir[GANA_MAX_PATH]; + + GetModuleFileName(NULL, exePath, GANA_MAX_PATH); + _tsplitpath_s(exePath, exeDrive, GANA_MAX_PATH, exeDir, GANA_MAX_PATH, NULL, 0, NULL, 0); + yamydPath = exeDrive; + yamydPath += exeDir; + yamydPath += _T("yamyd32"); + + BOOL result = CreateProcess(yamydPath.c_str(), NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, 0, NULL, &m_si, &m_pi); if (result == FALSE) { TCHAR buf[1024]; TCHAR text[1024]; TCHAR title[1024]; + m_pi.hProcess = NULL; LoadString(GetModuleHandle(NULL), IDS_cannotInvoke, text, sizeof(text)/sizeof(text[0])); LoadString(GetModuleHandle(NULL), IDS_mayu, title, sizeof(title)/sizeof(title[0])); _stprintf_s(buf, sizeof(buf)/sizeof(buf[0]), text, _T("yamyd32"), GetLastError()); - MessageBox((HWND)NULL, buf, title, MB_OK | MB_ICONSTOP); + MessageBox((HWND)NULL, buf, title, MB_OK | MB_ICONSTOP); } else { CloseHandle(m_pi.hThread); - CloseHandle(m_pi.hProcess); } #endif // _WIN64 } /// ~Mayu() { -#ifdef USE_MAILSLOT + // stop notify from mayu.dll + g_hookData->m_hwndTaskTray = NULL; + CHECK_FALSE( uninstallMessageHook() ); + +#ifdef _WIN64 + ReleaseMutex(m_hMutexYamyd); + if (m_pi.hProcess) { + WaitForSingleObject(m_pi.hProcess, 5000); + CloseHandle(m_pi.hProcess); + } + CloseHandle(m_hMutexYamyd); +#endif // _WIN64 + CancelIo(m_hNotifyMailslot); SleepEx(0, TRUE); CloseHandle(m_hNotifyMailslot); CloseHandle(m_hNotifyEvent); -#endif // USE_MAILSLOT ReleaseMutex(m_mutex); WaitForSingleObject(m_mutex, INFINITE); // first, detach log from edit control to avoid deadlock @@ -1087,11 +1208,6 @@ public: m_logFile.close(); #endif // LOG_TO_FILE - // stop notify from mayu.dll - g_hookData->m_hwndTaskTray = NULL; - CHECK_FALSE( uninstallMessageHook() ); - PostMessage(HWND_BROADCAST, WM_NULL, 0, 0); - // destroy windows CHECK_TRUE( DestroyWindow(m_hwndVersion) ); CHECK_TRUE( DestroyWindow(m_hwndInvestigate) ); @@ -1109,6 +1225,11 @@ public: // stop keyboard handler thread m_engine.stop(); + if (!(m_sessionState & SESSION_END_QUERIED)) { + DWORD_PTR result; + SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, 0, 3000, &result); + } + // remove setting; delete m_setting; } @@ -1118,7 +1239,6 @@ public: showBanner(false); load(); -#ifdef USE_MAILSLOT mailslotHandler(0, 0); while (1) { HANDLE handles[] = { m_hNotifyEvent }; @@ -1155,20 +1275,6 @@ public: break; } } -#else // !USE_MAILSLOT - MSG msg; - while (0 < GetMessage(&msg, NULL, 0, 0)) { - if (IsDialogMessage(m_hwndLog, &msg)) - continue; - if (IsDialogMessage(m_hwndInvestigate, &msg)) - continue; - if (IsDialogMessage(m_hwndVersion, &msg)) - continue; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return msg.wParam; -#endif // !USE_MAILSLOT } };