#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
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
&m_olNotify, Mayu::mailslotProc);\r
return result;\r
}\r
-#endif // USE_MAILSLOT\r
\r
/// register class for tasktray\r
ATOM Register_tasktray() {\r
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
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
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
# 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
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
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
}\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
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
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
}\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
\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
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
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
// 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
\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
\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
\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
\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
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
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
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
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
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
// 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
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
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
// 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
showBanner(false);\r
load();\r
\r
-#ifdef USE_MAILSLOT\r
mailslotHandler(0, 0);\r
while (1) {\r
HANDLE handles[] = { m_hNotifyEvent };\r
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