-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// mayu.cpp
-
-
-#define APSTUDIO_INVOKED
-
-#include "misc.h"
-#include "compiler_specific_func.h"
-#include "dlginvestigate.h"
-#include "dlglog.h"
-#include "dlgsetting.h"
-#include "dlgversion.h"
-#include "engine.h"
-#include "errormessage.h"
-#include "focus.h"
-#include "function.h"
-#include "hook.h"
-#include "mayu.h"
-#include "mayuipc.h"
-#include "mayurc.h"
-#include "msgstream.h"
-#include "multithread.h"
-#include "registry.h"
-#include "setting.h"
-#include "target.h"
-#include "windowstool.h"
-#include "vk2tchar.h"
-#include <process.h>
-#include <time.h>
-#include <commctrl.h>
-#include <wtsapi32.h>
-
-
-///
-#define ID_MENUITEM_reloadBegin _APS_NEXT_COMMAND_VALUE
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Mayu
-
-
-///
-class Mayu
-{
- HWND m_hwndTaskTray; /// tasktray window
- HWND m_hwndLog; /// log dialog
- HWND m_hwndInvestigate; /// investigate dialog
- HWND m_hwndVersion; /// version dialog
-
- UINT m_WM_TaskbarRestart; /** window message sent when
- taskber restarts */
- UINT m_WM_MayuIPC; /** IPC message sent from
- other applications */
- NOTIFYICONDATA m_ni; /// taskbar icon data
- HICON m_tasktrayIcon[2]; /// taskbar icon
- bool m_canUseTasktrayBaloon; ///
-
- tomsgstream m_log; /** log stream (output to log
- dialog's edit) */
-#ifdef LOG_TO_FILE
- tofstream m_logFile;
-#endif // LOG_TO_FILE
-
- HMENU m_hMenuTaskTray; /// tasktray menu
- STARTUPINFO m_si;
- PROCESS_INFORMATION m_pi;
- 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
-
- Setting *m_setting; /// current setting
- bool m_isSettingDialogOpened; /// is setting dialog opened ?
-
- Engine m_engine; /// engine
-
- bool m_usingSN; /// using WTSRegisterSessionNotification() ?
- time_t m_startTime; /// mayu started at ...
-
- enum
- {
- WM_APP_taskTrayNotify = WM_APP + 101, ///
- WM_APP_msgStreamNotify = WM_APP + 102, ///
- ID_TaskTrayIcon = 1, ///
- };
-
-private:
-#ifdef USE_MAILSLOT
- static VOID CALLBACK mailslotProc(DWORD i_code, DWORD i_len, LPOVERLAPPED i_ol)
- {
- Mayu *pThis;
-
- pThis = reinterpret_cast<Mayu*>(CONTAINING_RECORD(i_ol, Mayu, m_olNotify));
- pThis->mailslotHandler(i_code, i_len);
- return;
- }
-
- BOOL mailslotHandler(DWORD i_code, DWORD i_len)
- {
- BOOL result;
-
- if (i_len)
- {
- COPYDATASTRUCT cd;
-
- cd.dwData = reinterpret_cast<Notify *>(m_notifyBuf)->m_type;
- cd.cbData = i_len;
- cd.lpData = m_notifyBuf;
- notifyHandler(&cd);
- }
-
- memset(m_notifyBuf, 0, sizeof(m_notifyBuf));
- result = ReadFileEx(m_hNotifyMailslot, m_notifyBuf, sizeof(m_notifyBuf),
- &m_olNotify, Mayu::mailslotProc);
- return result;
- }
-#endif // USE_MAILSLOT
-
- /// register class for tasktray
- ATOM Register_tasktray()
- {
- WNDCLASS wc;
- wc.style = 0;
- wc.lpfnWndProc = tasktray_wndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = sizeof(Mayu *);
- wc.hInstance = g_hInst;
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- wc.lpszClassName = _T("mayuTasktray");
- return RegisterClass(&wc);
- }
-
- /// notify handler
- BOOL notifyHandler(COPYDATASTRUCT *cd)
- {
- switch (cd->dwData)
- {
- case Notify::Type_setFocus:
- case Notify::Type_name:
- {
- NotifySetFocus *n = (NotifySetFocus *)cd->lpData;
- n->m_className[NUMBER_OF(n->m_className) - 1] = _T('\0');
- n->m_titleName[NUMBER_OF(n->m_titleName) - 1] = _T('\0');
-
- if (n->m_type == Notify::Type_setFocus)
- m_engine.setFocus(reinterpret_cast<HWND>(n->m_hwnd), n->m_threadId,
- n->m_className, n->m_titleName, false);
-
- {
- Acquire a(&m_log, 1);
- m_log << _T("HWND:\t") << std::hex
- << n->m_hwnd
- << std::dec << std::endl;
- m_log << _T("THREADID:") << static_cast<int>(n->m_threadId)
- << std::endl;
- }
- Acquire a(&m_log, (n->m_type == Notify::Type_name) ? 0 : 1);
- m_log << _T("CLASS:\t") << n->m_className << std::endl;
- m_log << _T("TITLE:\t") << n->m_titleName << std::endl;
-
- bool isMDI = true;
- HWND hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), &isMDI);
- RECT rc;
- if (isMDI)
- {
- getChildWindowRect(hwnd, &rc);
- m_log << _T("MDI Window Position/Size: (")
- << rc.left << _T(", ") << rc.top << _T(") / (")
- << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")
- << std::endl;
- hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), NULL);
- }
-
- GetWindowRect(hwnd, &rc);
- m_log << _T("Toplevel Window Position/Size: (")
- << rc.left << _T(", ") << rc.top << _T(") / (")
- << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")
- << std::endl;
-
- SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);
- m_log << _T("Desktop Window Position/Size: (")
- << rc.left << _T(", ") << rc.top << _T(") / (")
- << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")
- << std::endl;
-
- m_log << std::endl;
- break;
- }
-
- case Notify::Type_lockState:
- {
- NotifyLockState *n = (NotifyLockState *)cd->lpData;
- m_engine.setLockState(n->m_isNumLockToggled,
- n->m_isCapsLockToggled,
- n->m_isScrollLockToggled,
- n->m_isKanaLockToggled,
- n->m_isImeLockToggled,
- n->m_isImeCompToggled);
-#if 0
- Acquire a(&m_log, 0);
- if (n->m_isKanaLockToggled) {
- m_log << _T("Notify::Type_lockState Kana on : ");
- } else {
- m_log << _T("Notify::Type_lockState Kana off : ");
- }
- m_log << n->m_debugParam << ", "
- << g_hookData->m_correctKanaLockHandling << std::endl;
-#endif
- break;
- }
-
- case Notify::Type_sync:
- {
- m_engine.syncNotify();
- 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;
- m_engine.commandNotify(n->m_hwnd, n->m_message,
- n->m_wParam, n->m_lParam);
- break;
- }
-
- case Notify::Type_show:
- {
- NotifyShow *n = (NotifyShow *)cd->lpData;
- switch (n->m_show)
- {
- case NotifyShow::Show_Maximized:
- m_engine.setShow(true, false, n->m_isMDI);
- break;
- case NotifyShow::Show_Minimized:
- m_engine.setShow(false, true, n->m_isMDI);
- break;
- case NotifyShow::Show_Normal:
- default:
- m_engine.setShow(false, false, n->m_isMDI);
- break;
- }
- break;
- }
-
- case Notify::Type_log:
- {
- Acquire a(&m_log, 1);
- NotifyLog *n = (NotifyLog *)cd->lpData;
- m_log << _T("hook log: ") << n->m_msg << std::endl;
- break;
- }
- }
- return true;
- }
-
- /// window procedure for tasktray
- static LRESULT CALLBACK
- tasktray_wndProc(HWND i_hwnd, UINT i_message,
- WPARAM i_wParam, LPARAM i_lParam)
- {
-#ifdef MAYU64
- Mayu *This = reinterpret_cast<Mayu *>(GetWindowLongPtr(i_hwnd, 0));
-#else
- Mayu *This = reinterpret_cast<Mayu *>(GetWindowLong(i_hwnd, 0));
-#endif
-
- if (!This)
- switch (i_message)
- {
- case WM_CREATE:
- This = reinterpret_cast<Mayu *>(
- reinterpret_cast<CREATESTRUCT *>(i_lParam)->lpCreateParams);
-#ifdef MAYU64
- SetWindowLongPtr(i_hwnd, 0, (LONG_PTR)This);
-#else
- SetWindowLong(i_hwnd, 0, (long)This);
-#endif
- return 0;
- }
- else
- switch (i_message)
- {
- case WM_COPYDATA:
- {
- COPYDATASTRUCT *cd;
- cd = reinterpret_cast<COPYDATASTRUCT *>(i_lParam);
- return This->notifyHandler(cd);
- }
- case WM_QUERYENDSESSION:
- This->m_engine.prepairQuit();
- PostQuitMessage(0);
- return TRUE;
-
-#ifndef WM_WTSSESSION_CHANGE // WinUser.h
-# define WM_WTSSESSION_CHANGE 0x02B1
-#endif
- case WM_WTSSESSION_CHANGE:
- {
- const char *m = "";
- switch (i_wParam)
- {
-#ifndef WTS_CONSOLE_CONNECT // WinUser.h
-# define WTS_CONSOLE_CONNECT 0x1
-# define WTS_CONSOLE_DISCONNECT 0x2
-# define WTS_REMOTE_CONNECT 0x3
-# define WTS_REMOTE_DISCONNECT 0x4
-# define WTS_SESSION_LOGON 0x5
-# define WTS_SESSION_LOGOFF 0x6
-# define WTS_SESSION_LOCK 0x7
-# define WTS_SESSION_UNLOCK 0x8
-#endif
- case WTS_CONSOLE_CONNECT:
- m = "WTS_CONSOLE_CONNECT";
- if (!This->m_engine.resume()) {
- This->m_engine.prepairQuit();
- PostQuitMessage(0);
- }
- break;
- case WTS_CONSOLE_DISCONNECT:
- m = "WTS_CONSOLE_DISCONNECT";
- This->m_engine.pause();
- break;
- case WTS_REMOTE_CONNECT: m = "WTS_REMOTE_CONNECT"; break;
- case WTS_REMOTE_DISCONNECT: m = "WTS_REMOTE_DISCONNECT"; break;
- case WTS_SESSION_LOGON: m = "WTS_SESSION_LOGON"; break;
- case WTS_SESSION_LOGOFF: m = "WTS_SESSION_LOGOFF"; break;
- case WTS_SESSION_LOCK: m = "WTS_SESSION_LOCK"; break;
- case WTS_SESSION_UNLOCK: m = "WTS_SESSION_UNLOCK"; break;
- //case WTS_SESSION_REMOTE_CONTROL: m = "WTS_SESSION_REMOTE_CONTROL"; break;
- }
- This->m_log << _T("WM_WTSESSION_CHANGE(")
- << i_wParam << ", " << i_lParam << "): "
- << m << std::endl;
- return TRUE;
- }
- case WM_APP_msgStreamNotify:
- {
- tomsgstream::StreamBuf *log =
- reinterpret_cast<tomsgstream::StreamBuf *>(i_lParam);
- const tstring &str = log->acquireString();
-#ifdef LOG_TO_FILE
- This->m_logFile << str << std::flush;
-#endif // LOG_TO_FILE
- editInsertTextAtLast(GetDlgItem(This->m_hwndLog, IDC_EDIT_log),
- str, 65000);
- log->releaseString();
- return 0;
- }
-
- case WM_APP_taskTrayNotify:
- {
- if (i_wParam == ID_TaskTrayIcon)
- switch (i_lParam)
- {
- case WM_RBUTTONUP:
- {
- POINT p;
- CHECK_TRUE( GetCursorPos(&p) );
- SetForegroundWindow(i_hwnd);
- HMENU hMenuSub = GetSubMenu(This->m_hMenuTaskTray, 0);
- if (This->m_engine.getIsEnabled())
- CheckMenuItem(hMenuSub, ID_MENUITEM_disable,
- MF_UNCHECKED | MF_BYCOMMAND);
- else
- CheckMenuItem(hMenuSub, ID_MENUITEM_disable,
- MF_CHECKED | MF_BYCOMMAND);
- CHECK_TRUE( SetMenuDefaultItem(hMenuSub,
- ID_MENUITEM_investigate, FALSE) );
-
- // create reload menu
- HMENU hMenuSubSub = GetSubMenu(hMenuSub, 1);
- Registry reg(MAYU_REGISTRY_ROOT);
- int mayuIndex;
- reg.read(_T(".mayuIndex"), &mayuIndex, 0);
- while (DeleteMenu(hMenuSubSub, 0, MF_BYPOSITION))
- ;
- tregex getName(_T("^([^;]*);"));
- for (int index = 0; ; index ++)
- {
- _TCHAR buf[100];
- _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);
- tstringi dot_mayu;
- if (!reg.read(buf, &dot_mayu))
- break;
- tsmatch what;
- if (boost::regex_search(dot_mayu, what, getName))
- {
- MENUITEMINFO mii;
- std::memset(&mii, 0, sizeof(mii));
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_ID | MIIM_STATE | MIIM_TYPE;
- mii.fType = MFT_STRING;
- mii.fState =
- MFS_ENABLED | ((mayuIndex == index) ? MFS_CHECKED : 0);
- mii.wID = ID_MENUITEM_reloadBegin + index;
- tstringi name(what.str(1));
- mii.dwTypeData = const_cast<_TCHAR *>(name.c_str());
- mii.cch = name.size();
-
- InsertMenuItem(hMenuSubSub, index, TRUE, &mii);
- }
- }
-
- // show popup menu
- TrackPopupMenu(hMenuSub, TPM_LEFTALIGN,
- p.x, p.y, 0, i_hwnd, NULL);
- // TrackPopupMenu may fail (ERROR_POPUP_ALREADY_ACTIVE)
- break;
- }
-
- case WM_LBUTTONDBLCLK:
- SendMessage(i_hwnd, WM_COMMAND,
- MAKELONG(ID_MENUITEM_investigate, 0), 0);
- break;
- }
- return 0;
- }
-
- case WM_COMMAND:
- {
- int notify_code = HIWORD(i_wParam);
- int id = LOWORD(i_wParam);
- if (notify_code == 0) // menu
- switch (id)
- {
- default:
- if (ID_MENUITEM_reloadBegin <= id)
- {
- Registry reg(MAYU_REGISTRY_ROOT);
- reg.write(_T(".mayuIndex"), id - ID_MENUITEM_reloadBegin);
- This->load();
- }
- break;
- case ID_MENUITEM_reload:
- This->load();
- break;
- case ID_MENUITEM_investigate:
- {
- ShowWindow(This->m_hwndLog, SW_SHOW);
- ShowWindow(This->m_hwndInvestigate, SW_SHOW);
-
- RECT rc1, rc2;
- GetWindowRect(This->m_hwndInvestigate, &rc1);
- GetWindowRect(This->m_hwndLog, &rc2);
-
- MoveWindow(This->m_hwndLog, rc1.left, rc1.bottom,
- rcWidth(&rc1), rcHeight(&rc2), TRUE);
-
- SetForegroundWindow(This->m_hwndLog);
- SetForegroundWindow(This->m_hwndInvestigate);
- break;
- }
- case ID_MENUITEM_setting:
- if (!This->m_isSettingDialogOpened)
- {
- This->m_isSettingDialogOpened = true;
- if (DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_setting),
- NULL, dlgSetting_dlgProc))
- This->load();
- This->m_isSettingDialogOpened = false;
- }
- break;
- case ID_MENUITEM_log:
- ShowWindow(This->m_hwndLog, SW_SHOW);
- SetForegroundWindow(This->m_hwndLog);
- break;
- case ID_MENUITEM_check:
- {
- BOOL ret;
- BYTE keys[256];
- ret = GetKeyboardState(keys);
- if (ret == 0)
- {
- This->m_log << _T("Check Keystate Failed(%d)")
- << GetLastError() << std::endl;
- }
- else
- {
- This->m_log << _T("Check Keystate: ") << std::endl;
- for (int i = 0; i < 0xff; i++)
- {
- USHORT asyncKey;
- asyncKey = GetAsyncKeyState(i);
- This->m_log << std::hex;
- if (asyncKey & 0x8000)
- {
- This->m_log << _T(" ") << VK2TCHAR[i]
- << _T("(0x") << i << _T("): pressed!")
- << std::endl;
- }
- if (i == 0x14 || // VK_CAPTITAL
- i == 0x15 || // VK_KANA
- i == 0x19 || // VK_KANJI
- i == 0x90 || // VK_NUMLOCK
- i == 0x91 // VK_SCROLL
- )
- {
- if (keys[i] & 1)
- {
- This->m_log << _T(" ") << VK2TCHAR[i]
- << _T("(0x") << i << _T("): locked!")
- << std::endl;
- }
- }
- This->m_log << std::dec;
- }
- This->m_log << std::endl;
- }
- break;
- }
- case ID_MENUITEM_version:
- ShowWindow(This->m_hwndVersion, SW_SHOW);
- SetForegroundWindow(This->m_hwndVersion);
- break;
- case ID_MENUITEM_help:
- {
- _TCHAR buf[GANA_MAX_PATH];
- CHECK_TRUE( GetModuleFileName(g_hInst, buf, NUMBER_OF(buf)) );
- tstringi helpFilename = pathRemoveFileSpec(buf);
- helpFilename += _T("\\");
- helpFilename += loadString(IDS_helpFilename);
- ShellExecute(NULL, _T("open"), helpFilename.c_str(),
- NULL, NULL, SW_SHOWNORMAL);
- break;
- }
- case ID_MENUITEM_disable:
- This->m_engine.enable(!This->m_engine.getIsEnabled());
- This->showTasktrayIcon();
- break;
- case ID_MENUITEM_quit:
- This->m_engine.prepairQuit();
- PostQuitMessage(0);
- break;
- }
- return 0;
- }
-
- case WM_APP_engineNotify:
- {
- switch (i_wParam)
- {
- case EngineNotify_shellExecute:
- This->m_engine.shellExecute();
- break;
- case EngineNotify_loadSetting:
- This->load();
- break;
- case EngineNotify_helpMessage:
- This->showHelpMessage(false);
- if (i_lParam)
- This->showHelpMessage(true);
- break;
- case EngineNotify_showDlg:
- {
- // show investigate/log window
- int sw = (i_lParam & ~MayuDialogType_mask);
- HWND hwnd = NULL;
- switch (static_cast<MayuDialogType>(
- i_lParam & MayuDialogType_mask))
- {
- case MayuDialogType_investigate:
- hwnd = This->m_hwndInvestigate;
- break;
- case MayuDialogType_log:
- hwnd = This->m_hwndLog;
- break;
- }
- if (hwnd)
- {
- ShowWindow(hwnd, sw);
- switch (sw)
- {
- case SW_SHOWNORMAL:
- case SW_SHOWMAXIMIZED:
- case SW_SHOW:
- case SW_RESTORE:
- case SW_SHOWDEFAULT:
- SetForegroundWindow(hwnd);
- break;
- }
- }
- break;
- }
- case EngineNotify_setForegroundWindow:
- // FIXME: completely useless. why ?
- setForegroundWindow(reinterpret_cast<HWND>(i_lParam));
- {
- Acquire a(&This->m_log, 1);
- This->m_log << _T("setForegroundWindow(0x")
- << std::hex << i_lParam << std::dec << _T(")")
- << std::endl;
- }
- break;
- case EngineNotify_clearLog:
- SendMessage(This->m_hwndLog, WM_COMMAND,
- MAKELONG(IDC_BUTTON_clearLog, 0), 0);
- break;
- default:
- break;
- }
- return 0;
- }
-
- case WM_APP_dlglogNotify:
- {
- switch (i_wParam)
- {
- case DlgLogNotify_logCleared:
- This->showBanner(true);
- break;
- default:
- break;
- }
- return 0;
- }
-
- case WM_DESTROY:
- if (This->m_usingSN)
- {
- wtsUnRegisterSessionNotification(i_hwnd);
- This->m_usingSN = false;
- }
- return 0;
-
- default:
- if (i_message == This->m_WM_TaskbarRestart)
- {
- if (This->showTasktrayIcon(true))
- {
- Acquire a(&This->m_log, 0);
- This->m_log << _T("Tasktray icon is updated.") << std::endl;
- }
- else
- {
- Acquire a(&This->m_log, 1);
- This->m_log << _T("Tasktray icon already exists.") << std::endl;
- }
- return 0;
- }
- else if (i_message == This->m_WM_MayuIPC)
- {
- switch (static_cast<MayuIPCCommand>(i_wParam))
- {
- case MayuIPCCommand_Enable:
- This->m_engine.enable(!!i_lParam);
- This->showTasktrayIcon();
- if (i_lParam)
- {
- Acquire a(&This->m_log, 1);
- This->m_log << _T("Enabled by another application.")
- << std::endl;
- }
- else
- {
- Acquire a(&This->m_log, 1);
- This->m_log << _T("Disabled by another application.")
- << std::endl;
- }
- break;
- }
- }
- }
- return DefWindowProc(i_hwnd, i_message, i_wParam, i_lParam);
- }
-
- /// load setting
- void load()
- {
- Setting *newSetting = new Setting;
-
- // set symbol
- for (int i = 1; i < __argc; ++ i)
- {
- if (__targv[i][0] == _T('-') && __targv[i][1] == _T('D'))
- newSetting->m_symbols.insert(__targv[i] + 2);
- }
-
- if (!SettingLoader(&m_log, &m_log).load(newSetting))
- {
- ShowWindow(m_hwndLog, SW_SHOW);
- SetForegroundWindow(m_hwndLog);
- delete newSetting;
- Acquire a(&m_log, 0);
- m_log << _T("error: failed to load.") << std::endl;
- return;
- }
- m_log << _T("successfully loaded.") << std::endl;
- while (!m_engine.setSetting(newSetting))
- Sleep(1000);
- delete m_setting;
- m_setting = newSetting;
- }
-
- // show message (a baloon from the task tray icon)
- void showHelpMessage(bool i_doesShow = true)
- {
- if (m_canUseTasktrayBaloon)
- {
- if (i_doesShow)
- {
- tstring helpMessage, helpTitle;
- m_engine.getHelpMessages(&helpMessage, &helpTitle);
- tcslcpy(m_ni.szInfo, helpMessage.c_str(), NUMBER_OF(m_ni.szInfo));
- tcslcpy(m_ni.szInfoTitle, helpTitle.c_str(),
- NUMBER_OF(m_ni.szInfoTitle));
- m_ni.dwInfoFlags = NIIF_INFO;
- }
- else
- m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');
- CHECK_TRUE( Shell_NotifyIcon(NIM_MODIFY, &m_ni) );
- }
- }
-
- // change the task tray icon
- bool showTasktrayIcon(bool i_doesAdd = false)
- {
- m_ni.hIcon = m_tasktrayIcon[m_engine.getIsEnabled() ? 1 : 0];
- m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');
- if (i_doesAdd) {
- // http://support.microsoft.com/kb/418138/JA/
- int guard = 60;
- for (; !Shell_NotifyIcon(NIM_ADD, &m_ni) && 0 < guard; -- guard) {
- if (Shell_NotifyIcon(NIM_MODIFY, &m_ni)) {
- return true;
- }
- Sleep(1000); // 1sec
- }
- return 0 < guard;
- } else {
- return !!Shell_NotifyIcon(NIM_MODIFY, &m_ni);
- }
- }
-
- void showBanner(bool i_isCleared)
- {
- time_t now;
- time(&now);
-
- _TCHAR starttimebuf[1024];
- _TCHAR timebuf[1024];
-
-#ifdef __BORLANDC__
-#pragma message("\t\t****\tAfter std::ostream() is called, ")
-#pragma message("\t\t****\tstrftime(... \"%%#c\" ...) fails.")
-#pragma message("\t\t****\tWhy ? Bug of Borland C++ 5.5.1 ? ")
-#pragma message("\t\t****\t - nayuta")
- _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%Y/%m/%d %H:%M:%S"),
- localtime(&now));
- _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%Y/%m/%d %H:%M:%S"),
- localtime(&m_startTime));
-#else
- _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%#c"), localtime(&now));
- _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%#c"),
- localtime(&m_startTime));
-#endif
-
- Acquire a(&m_log, 0);
- m_log << _T("------------------------------------------------------------") << std::endl;
- m_log << loadString(IDS_mayu) << _T(" ") _T(VERSION);
-#ifndef NDEBUG
- m_log << _T(" (DEBUG)");
-#endif
-#ifdef _UNICODE
- m_log << _T(" (UNICODE)");
-#endif
- m_log << std::endl;
- m_log << _T(" built by ")
- << _T(LOGNAME) << _T("@") << toLower(_T(COMPUTERNAME))
- << _T(" (") << _T(__DATE__) << _T(" ")
- << _T(__TIME__) << _T(", ")
- << getCompilerVersionString() << _T(")") << std::endl;
- _TCHAR modulebuf[1024];
- CHECK_TRUE( GetModuleFileName(g_hInst, modulebuf,
- NUMBER_OF(modulebuf)) );
- m_log << _T("started at ") << starttimebuf << std::endl;
- m_log << modulebuf << std::endl;
- m_log << _T("------------------------------------------------------------") << std::endl;
-
- if (i_isCleared) {
- m_log << _T("log was cleared at ") << timebuf << std::endl;
- } else {
- m_log << _T("log begins at ") << timebuf << std::endl;
- }
- }
-
-public:
- ///
- Mayu(HANDLE i_mutex)
- : m_hwndTaskTray(NULL),
- m_mutex(i_mutex),
- m_hwndLog(NULL),
- m_WM_TaskbarRestart(RegisterWindowMessage(_T("TaskbarCreated"))),
- m_WM_MayuIPC(RegisterWindowMessage(WM_MayuIPC_NAME)),
- m_canUseTasktrayBaloon(
- PACKVERSION(5, 0) <= getDllVersion(_T("shlwapi.dll"))),
- m_log(WM_APP_msgStreamNotify),
- m_setting(NULL),
- m_isSettingDialogOpened(false),
- m_engine(m_log)
- {
-#ifdef USE_MAILSLOT
- m_hNotifyMailslot = CreateMailslot(NOTIFY_MAILSLOT_NAME, 0, MAILSLOT_WAIT_FOREVER, (SECURITY_ATTRIBUTES *)NULL);
- ASSERT(m_hNotifyMailslot != INVALID_HANDLE_VALUE);
- 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() );
- CHECK_TRUE( Register_target() );
- CHECK_TRUE( Register_tasktray() );
-
- // change dir
-#if 0
- HomeDirectories pathes;
- getHomeDirectories(&pathes);
- for (HomeDirectories::iterator i = pathes.begin(); i != pathes.end(); ++ i)
- if (SetCurrentDirectory(i->c_str()))
- break;
-#endif
-
- // create windows, dialogs
- tstringi title = loadString(IDS_mayu);
- m_hwndTaskTray = CreateWindow(_T("mayuTasktray"), title.c_str(),
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL, g_hInst, this);
- CHECK_TRUE( m_hwndTaskTray );
-
- // set window handle of tasktray to hooks
-#ifndef USE_MAILSLOT
- g_hookData->m_hwndTaskTray = reinterpret_cast<DWORD>(m_hwndTaskTray);
-#endif // !USE_MAILSLOT
- CHECK_FALSE( installHooks(Engine::keyboardDetour, &m_engine) );
- m_usingSN = wtsRegisterSessionNotification(m_hwndTaskTray,
- NOTIFY_FOR_THIS_SESSION);
-
- DlgLogData dld;
- dld.m_log = &m_log;
- dld.m_hwndTaskTray = m_hwndTaskTray;
- m_hwndLog =
- CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_log), NULL,
- dlgLog_dlgProc, (LPARAM)&dld);
- CHECK_TRUE( m_hwndLog );
-
- DlgInvestigateData did;
- did.m_engine = &m_engine;
- did.m_hwndLog = m_hwndLog;
- m_hwndInvestigate =
- CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_investigate), NULL,
- dlgInvestigate_dlgProc, (LPARAM)&did);
- CHECK_TRUE( m_hwndInvestigate );
-
- m_hwndVersion =
- CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_version),
- NULL, dlgVersion_dlgProc,
- (LPARAM)m_engine.getMayudVersion().c_str());
- CHECK_TRUE( m_hwndVersion );
-
- // attach log
-#ifdef LOG_TO_FILE
- tstring path;
- _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);
- path = exeDrive;
- path += exeDir;
- path += _T("mayu.log");
- m_logFile.open(path.c_str(), std::ios::app);
- m_logFile.imbue(std::locale("japanese"));
-#endif // LOG_TO_FILE
- SendMessage(GetDlgItem(m_hwndLog, IDC_EDIT_log), EM_SETLIMITTEXT, 0, 0);
- m_log.attach(m_hwndTaskTray);
-
- // start keyboard handler thread
- m_engine.setAssociatedWndow(m_hwndTaskTray);
- m_engine.start();
-
- // show tasktray icon
- m_tasktrayIcon[0] = loadSmallIcon(IDI_ICON_mayu_disabled);
- m_tasktrayIcon[1] = loadSmallIcon(IDI_ICON_mayu);
- std::memset(&m_ni, 0, sizeof(m_ni));
- m_ni.uID = ID_TaskTrayIcon;
- m_ni.hWnd = m_hwndTaskTray;
- m_ni.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
- m_ni.hIcon = m_tasktrayIcon[1];
- m_ni.uCallbackMessage = WM_APP_taskTrayNotify;
- 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.uFlags |= NIF_INFO;
- }
- else
- m_ni.cbSize = NOTIFYICONDATA_V1_SIZE;
- showTasktrayIcon(true);
-
- // create menu
- m_hMenuTaskTray = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU_tasktray));
- ASSERT(m_hMenuTaskTray);
-
- // set initial lock state
- notifyLockState();
-
- BOOL result;
-
- 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,
- NORMAL_PRIORITY_CLASS, 0, NULL, &m_si, &m_pi);
- if (result == FALSE)
- {
- TCHAR buf[1024];
- TCHAR text[1024];
- TCHAR title[1024];
-
- 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);
- }
- else
- {
- CloseHandle(m_pi.hThread);
- CloseHandle(m_pi.hProcess);
- }
-#endif // _WIN64
- }
-
- ///
- ~Mayu()
- {
- ReleaseMutex(m_mutex);
- WaitForSingleObject(m_mutex, INFINITE);
- // first, detach log from edit control to avoid deadlock
- m_log.detach();
-#ifdef LOG_TO_FILE
- m_logFile.close();
-#endif // LOG_TO_FILE
-
- // stop notify from mayu.dll
- g_hookData->m_hwndTaskTray = NULL;
- CHECK_FALSE( uninstallHooks() );
- PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);
-
- // destroy windows
- CHECK_TRUE( DestroyWindow(m_hwndVersion) );
- CHECK_TRUE( DestroyWindow(m_hwndInvestigate) );
- CHECK_TRUE( DestroyWindow(m_hwndLog) );
- CHECK_TRUE( DestroyWindow(m_hwndTaskTray) );
-
- // destroy menu
- DestroyMenu(m_hMenuTaskTray);
-
- // delete tasktray icon
- CHECK_TRUE( Shell_NotifyIcon(NIM_DELETE, &m_ni) );
- CHECK_TRUE( DestroyIcon(m_tasktrayIcon[1]) );
- CHECK_TRUE( DestroyIcon(m_tasktrayIcon[0]) );
-
- // stop keyboard handler thread
- m_engine.stop();
-
- // remove setting;
- delete m_setting;
-
-#ifdef USE_MAILSLOT
- CloseHandle(m_hNotifyEvent);
- CloseHandle(m_hNotifyMailslot);
-#endif // USE_MAILSLOT
- }
-
- /// message loop
- WPARAM messageLoop()
- {
- showBanner(false);
- load();
-
-#ifdef USE_MAILSLOT
- mailslotHandler(0, 0);
- while (1)
- {
- HANDLE handles[] = { m_hNotifyEvent };
- DWORD ret;
- switch (ret = MsgWaitForMultipleObjectsEx(NUMBER_OF(handles), &handles[0],
- INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE))
- {
- case WAIT_OBJECT_0: // m_hNotifyEvent
- break;
-
- case WAIT_OBJECT_0 + NUMBER_OF(handles):
- {
- MSG msg;
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0)
- {
- if (msg.message == WM_QUIT)
- {
- return msg.wParam;
- }
- if (IsDialogMessage(m_hwndLog, &msg))
- break;
- if (IsDialogMessage(m_hwndInvestigate, &msg))
- break;
- if (IsDialogMessage(m_hwndVersion, &msg))
- break;
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- break;
- }
- break;
- }
-
- case WAIT_IO_COMPLETION:
- break;
-
- case 0x102:
- default:
- 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
- }
-};
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Functions
-
-
-/// convert registry
-void convertRegistry()
-{
- Registry reg(MAYU_REGISTRY_ROOT);
- tstringi dot_mayu;
- bool doesAdd = false;
- DWORD index;
- if (reg.read(_T(".mayu"), &dot_mayu))
- {
- reg.write(_T(".mayu0"), _T(";") + dot_mayu + _T(";"));
- reg.remove(_T(".mayu"));
- doesAdd = true;
- index = 0;
- }
- else if (!reg.read(_T(".mayu0"), &dot_mayu))
- {
- reg.write(_T(".mayu0"), loadString(IDS_readFromHomeDirectory) + _T(";;"));
- doesAdd = true;
- index = 1;
- }
- if (doesAdd)
- {
- Registry commonreg(HKEY_LOCAL_MACHINE, _T("Software\\GANAware\\mayu"));
- tstringi dir, layout;
- if (commonreg.read(_T("dir"), &dir) &&
- commonreg.read(_T("layout"), &layout))
- {
- tstringi tmp = _T(";") + dir + _T("\\dot.mayu");
- if (layout == _T("109"))
- {
- reg.write(_T(".mayu1"), loadString(IDS_109Emacs) + tmp
- + _T(";-DUSE109") _T(";-DUSEdefault"));
- reg.write(_T(".mayu2"), loadString(IDS_104on109Emacs) + tmp
- + _T(";-DUSE109") _T(";-DUSEdefault") _T(";-DUSE104on109"));
- reg.write(_T(".mayu3"), loadString(IDS_109) + tmp
- + _T(";-DUSE109"));
- reg.write(_T(".mayu4"), loadString(IDS_104on109) + tmp
- + _T(";-DUSE109") _T(";-DUSE104on109"));
- }
- else
- {
- reg.write(_T(".mayu1"), loadString(IDS_104Emacs) + tmp
- + _T(";-DUSE104") _T(";-DUSEdefault"));
- reg.write(_T(".mayu2"), loadString(IDS_109on104Emacs) + tmp
- + _T(";-DUSE104") _T(";-DUSEdefault") _T(";-DUSE109on104"));
- reg.write(_T(".mayu3"), loadString(IDS_104) + tmp
- + _T(";-DUSE104"));
- reg.write(_T(".mayu4"), loadString(IDS_109on104) + tmp
- + _T(";-DUSE104") _T(";-DUSE109on104"));
- }
- reg.write(_T(".mayuIndex"), index);
- }
- }
-}
-
-
-/// main
-int WINAPI _tWinMain(HINSTANCE i_hInstance, HINSTANCE /* i_hPrevInstance */,
- LPTSTR /* i_lpszCmdLine */, int /* i_nCmdShow */)
-{
- g_hInst = i_hInstance;
-
- // set locale
- CHECK_TRUE( _tsetlocale(LC_ALL, _T("")) );
-
- // common controls
-#if defined(_WIN95)
- InitCommonControls();
-#else
- INITCOMMONCONTROLSEX icc;
- icc.dwSize = sizeof(icc);
- icc.dwICC = ICC_LISTVIEW_CLASSES;
- CHECK_TRUE( InitCommonControlsEx(&icc) );
-#endif
-
- // convert old registry to new registry
-#ifndef USE_INI
- convertRegistry();
-#endif // !USE_INI
-
- // is another mayu running ?
- HANDLE mutex = CreateMutex((SECURITY_ATTRIBUTES *)NULL, TRUE,
- MUTEX_MAYU_EXCLUSIVE_RUNNING);
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- {
- // another mayu already running
- tstring text = loadString(IDS_mayuAlreadyExists);
- tstring title = loadString(IDS_mayu);
- if (g_hookData) {
- UINT WM_TaskbarRestart = RegisterWindowMessage(_T("TaskbarCreated"));
- PostMessage(reinterpret_cast<HWND>(g_hookData->m_hwndTaskTray),
- WM_TaskbarRestart, 0, 0);
- }
- MessageBox((HWND)NULL, text.c_str(), title.c_str(), MB_OK | MB_ICONSTOP);
- return 1;
- }
-
- // check remote desktop
- DWORD sessionId;
- if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId) ||
- wtsGetActiveConsoleSessionId() != sessionId)
- {
- tstring text = loadString(IDS_executedInRemoteDesktop);
- tstring title = loadString(IDS_mayu);
- MessageBox((HWND)NULL, text.c_str(), title.c_str(), MB_OK | MB_ICONSTOP);
- return 1;
- }
-
- try
- {
- Mayu(mutex).messageLoop();
- }
- catch (ErrorMessage &i_e)
- {
- tstring title = loadString(IDS_mayu);
- MessageBox((HWND)NULL, i_e.getMessage().c_str(), title.c_str(),
- MB_OK | MB_ICONSTOP);
- }
-
- CHECK_TRUE( CloseHandle(mutex) );
- return 0;
-}
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// mayu.cpp\r
+\r
+\r
+#define APSTUDIO_INVOKED\r
+\r
+#include "misc.h"\r
+#include "compiler_specific_func.h"\r
+#include "dlginvestigate.h"\r
+#include "dlglog.h"\r
+#include "dlgsetting.h"\r
+#include "dlgversion.h"\r
+#include "engine.h"\r
+#include "errormessage.h"\r
+#include "focus.h"\r
+#include "function.h"\r
+#include "hook.h"\r
+#include "mayu.h"\r
+#include "mayuipc.h"\r
+#include "mayurc.h"\r
+#include "msgstream.h"\r
+#include "multithread.h"\r
+#include "registry.h"\r
+#include "setting.h"\r
+#include "target.h"\r
+#include "windowstool.h"\r
+#include "fixscancodemap.h"\r
+#include "vk2tchar.h"\r
+#include <process.h>\r
+#include <time.h>\r
+#include <commctrl.h>\r
+#include <wtsapi32.h>\r
+#include <aclapi.h>\r
+\r
+\r
+///\r
+#define ID_MENUITEM_reloadBegin _APS_NEXT_COMMAND_VALUE\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// Mayu\r
+\r
+\r
+///\r
+class Mayu\r
+{\r
+ HWND m_hwndTaskTray; /// tasktray window\r
+ HWND m_hwndLog; /// log dialog\r
+ HWND m_hwndInvestigate; /// investigate dialog\r
+ HWND m_hwndVersion; /// version dialog\r
+\r
+ UINT m_WM_TaskbarRestart; /** window message sent when\r
+ taskber restarts */\r
+ UINT m_WM_MayuIPC; /** IPC message sent from\r
+ other applications */\r
+ NOTIFYICONDATA m_ni; /// taskbar icon data\r
+ HICON m_tasktrayIcon[2]; /// taskbar icon\r
+ bool m_canUseTasktrayBaloon; ///\r
+\r
+ tomsgstream m_log; /** log stream (output to log\r
+ dialog's edit) */\r
+#ifdef LOG_TO_FILE\r
+ tofstream m_logFile;\r
+#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
+ 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
+ Setting *m_setting; /// current setting\r
+ bool m_isSettingDialogOpened; /// is setting dialog opened ?\r
+\r
+ Engine m_engine; /// engine\r
+\r
+ bool m_usingSN; /// using WTSRegisterSessionNotification() ?\r
+ time_t m_startTime; /// mayu started at ...\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
+ if (i_code == ERROR_SUCCESS) {\r
+ pThis = reinterpret_cast<Mayu*>(CONTAINING_RECORD(i_ol, Mayu, m_olNotify));\r
+ pThis->mailslotHandler(i_code, i_len);\r
+ }\r
+ return;\r
+ }\r
+\r
+ BOOL mailslotHandler(DWORD i_code, DWORD i_len) {\r
+ BOOL result;\r
+\r
+ if (i_len) {\r
+ COPYDATASTRUCT cd;\r
+\r
+ cd.dwData = reinterpret_cast<Notify *>(m_notifyBuf)->m_type;\r
+ cd.cbData = i_len;\r
+ cd.lpData = m_notifyBuf;\r
+ notifyHandler(&cd);\r
+ }\r
+\r
+ memset(m_notifyBuf, 0, sizeof(m_notifyBuf));\r
+ result = ReadFileEx(m_hNotifyMailslot, m_notifyBuf, sizeof(m_notifyBuf),\r
+ &m_olNotify, Mayu::mailslotProc);\r
+ return result;\r
+ }\r
+#endif // USE_MAILSLOT\r
+\r
+ /// register class for tasktray\r
+ ATOM Register_tasktray() {\r
+ WNDCLASS wc;\r
+ wc.style = 0;\r
+ wc.lpfnWndProc = tasktray_wndProc;\r
+ wc.cbClsExtra = 0;\r
+ wc.cbWndExtra = sizeof(Mayu *);\r
+ wc.hInstance = g_hInst;\r
+ wc.hIcon = NULL;\r
+ wc.hCursor = NULL;\r
+ wc.hbrBackground = NULL;\r
+ wc.lpszMenuName = NULL;\r
+ wc.lpszClassName = _T("mayuTasktray");\r
+ return RegisterClass(&wc);\r
+ }\r
+\r
+ /// notify handler\r
+ BOOL notifyHandler(COPYDATASTRUCT *cd) {\r
+ switch (cd->dwData) {\r
+ case Notify::Type_setFocus:\r
+ case Notify::Type_name: {\r
+ NotifySetFocus *n = (NotifySetFocus *)cd->lpData;\r
+ n->m_className[NUMBER_OF(n->m_className) - 1] = _T('\0');\r
+ n->m_titleName[NUMBER_OF(n->m_titleName) - 1] = _T('\0');\r
+\r
+ if (n->m_type == Notify::Type_setFocus)\r
+ m_engine.setFocus(reinterpret_cast<HWND>(n->m_hwnd), n->m_threadId,\r
+ n->m_className, n->m_titleName, false);\r
+\r
+ {\r
+ Acquire a(&m_log, 1);\r
+ m_log << _T("HWND:\t") << std::hex\r
+ << n->m_hwnd\r
+ << std::dec << std::endl;\r
+ m_log << _T("THREADID:") << static_cast<int>(n->m_threadId)\r
+ << std::endl;\r
+ }\r
+ Acquire a(&m_log, (n->m_type == Notify::Type_name) ? 0 : 1);\r
+ m_log << _T("CLASS:\t") << n->m_className << std::endl;\r
+ m_log << _T("TITLE:\t") << n->m_titleName << std::endl;\r
+\r
+ bool isMDI = true;\r
+ HWND hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), &isMDI);\r
+ RECT rc;\r
+ if (isMDI) {\r
+ getChildWindowRect(hwnd, &rc);\r
+ m_log << _T("MDI Window Position/Size: (")\r
+ << rc.left << _T(", ") << rc.top << _T(") / (")\r
+ << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")\r
+ << std::endl;\r
+ hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), NULL);\r
+ }\r
+\r
+ GetWindowRect(hwnd, &rc);\r
+ m_log << _T("Toplevel Window Position/Size: (")\r
+ << rc.left << _T(", ") << rc.top << _T(") / (")\r
+ << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")\r
+ << std::endl;\r
+\r
+ SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);\r
+ m_log << _T("Desktop Window Position/Size: (")\r
+ << rc.left << _T(", ") << rc.top << _T(") / (")\r
+ << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")\r
+ << std::endl;\r
+\r
+ m_log << std::endl;\r
+ break;\r
+ }\r
+\r
+ case Notify::Type_lockState: {\r
+ NotifyLockState *n = (NotifyLockState *)cd->lpData;\r
+ m_engine.setLockState(n->m_isNumLockToggled,\r
+ n->m_isCapsLockToggled,\r
+ n->m_isScrollLockToggled,\r
+ n->m_isKanaLockToggled,\r
+ n->m_isImeLockToggled,\r
+ n->m_isImeCompToggled);\r
+#if 0\r
+ Acquire a(&m_log, 0);\r
+ if (n->m_isKanaLockToggled) {\r
+ m_log << _T("Notify::Type_lockState Kana on : ");\r
+ } else {\r
+ m_log << _T("Notify::Type_lockState Kana off : ");\r
+ }\r
+ m_log << n->m_debugParam << ", "\r
+ << g_hookData->m_correctKanaLockHandling << std::endl;\r
+#endif\r
+ break;\r
+ }\r
+\r
+ case Notify::Type_sync: {\r
+ m_engine.syncNotify();\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
+ m_engine.commandNotify(n->m_hwnd, n->m_message,\r
+ n->m_wParam, n->m_lParam);\r
+ break;\r
+ }\r
+\r
+ case Notify::Type_show: {\r
+ NotifyShow *n = (NotifyShow *)cd->lpData;\r
+ switch (n->m_show) {\r
+ case NotifyShow::Show_Maximized:\r
+ m_engine.setShow(true, false, n->m_isMDI);\r
+ break;\r
+ case NotifyShow::Show_Minimized:\r
+ m_engine.setShow(false, true, n->m_isMDI);\r
+ break;\r
+ case NotifyShow::Show_Normal:\r
+ default:\r
+ m_engine.setShow(false, false, n->m_isMDI);\r
+ break;\r
+ }\r
+ break;\r
+ }\r
+\r
+ case Notify::Type_log: {\r
+ Acquire a(&m_log, 1);\r
+ NotifyLog *n = (NotifyLog *)cd->lpData;\r
+ m_log << _T("hook log: ") << n->m_msg << std::endl;\r
+ break;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /// window procedure for tasktray\r
+ static LRESULT CALLBACK\r
+ tasktray_wndProc(HWND i_hwnd, UINT i_message,\r
+ WPARAM i_wParam, LPARAM i_lParam) {\r
+#ifdef MAYU64\r
+ Mayu *This = reinterpret_cast<Mayu *>(GetWindowLongPtr(i_hwnd, 0));\r
+#else\r
+ Mayu *This = reinterpret_cast<Mayu *>(GetWindowLong(i_hwnd, 0));\r
+#endif\r
+\r
+ if (!This)\r
+ switch (i_message) {\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
+ This->m_fixScancodeMap.escape(true);\r
+ }\r
+#ifdef MAYU64\r
+ SetWindowLongPtr(i_hwnd, 0, (LONG_PTR)This);\r
+#else\r
+ SetWindowLong(i_hwnd, 0, (long)This);\r
+#endif\r
+ return 0;\r
+ }\r
+ else\r
+ switch (i_message) {\r
+ case WM_COPYDATA: {\r
+ COPYDATASTRUCT *cd;\r
+ cd = reinterpret_cast<COPYDATASTRUCT *>(i_lParam);\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
+\r
+#ifndef WM_WTSSESSION_CHANGE // WinUser.h\r
+# define WM_WTSSESSION_CHANGE 0x02B1\r
+#endif\r
+ case WM_WTSSESSION_CHANGE: {\r
+ const char *m = "";\r
+ switch (i_wParam) {\r
+#ifndef WTS_CONSOLE_CONNECT // WinUser.h\r
+# define WTS_CONSOLE_CONNECT 0x1\r
+# define WTS_CONSOLE_DISCONNECT 0x2\r
+# define WTS_REMOTE_CONNECT 0x3\r
+# define WTS_REMOTE_DISCONNECT 0x4\r
+# define WTS_SESSION_LOGON 0x5\r
+# define WTS_SESSION_LOGOFF 0x6\r
+# define WTS_SESSION_LOCK 0x7\r
+# define WTS_SESSION_UNLOCK 0x8\r
+#endif\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
+ 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
+ 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_LOGON";\r
+ break;\r
+ case WTS_SESSION_LOGOFF:\r
+ m = "WTS_SESSION_LOGOFF";\r
+ break;\r
+ case WTS_SESSION_LOCK: {\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
+ 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
+ break;\r
+ }\r
+ //case WTS_SESSION_REMOTE_CONTROL: m = "WTS_SESSION_REMOTE_CONTROL"; break;\r
+ }\r
+ This->m_log << _T("WM_WTSESSION_CHANGE(")\r
+ << i_wParam << ", " << i_lParam << "): "\r
+ << m << std::endl;\r
+ return TRUE;\r
+ }\r
+ case WM_APP_msgStreamNotify: {\r
+ tomsgstream::StreamBuf *log =\r
+ reinterpret_cast<tomsgstream::StreamBuf *>(i_lParam);\r
+ const tstring &str = log->acquireString();\r
+#ifdef LOG_TO_FILE\r
+ This->m_logFile << str << std::flush;\r
+#endif // LOG_TO_FILE\r
+ editInsertTextAtLast(GetDlgItem(This->m_hwndLog, IDC_EDIT_log),\r
+ str, 65000);\r
+ log->releaseString();\r
+ return 0;\r
+ }\r
+\r
+ case WM_APP_taskTrayNotify: {\r
+ if (i_wParam == ID_TaskTrayIcon)\r
+ switch (i_lParam) {\r
+ case WM_RBUTTONUP: {\r
+ POINT p;\r
+ CHECK_TRUE( GetCursorPos(&p) );\r
+ SetForegroundWindow(i_hwnd);\r
+ HMENU hMenuSub = GetSubMenu(This->m_hMenuTaskTray, 0);\r
+ if (This->m_engine.getIsEnabled())\r
+ CheckMenuItem(hMenuSub, ID_MENUITEM_disable,\r
+ MF_UNCHECKED | MF_BYCOMMAND);\r
+ else\r
+ CheckMenuItem(hMenuSub, ID_MENUITEM_disable,\r
+ MF_CHECKED | MF_BYCOMMAND);\r
+ CHECK_TRUE( SetMenuDefaultItem(hMenuSub,\r
+ ID_MENUITEM_investigate, FALSE) );\r
+\r
+ // create reload menu\r
+ HMENU hMenuSubSub = GetSubMenu(hMenuSub, 1);\r
+ Registry reg(MAYU_REGISTRY_ROOT);\r
+ int mayuIndex;\r
+ reg.read(_T(".mayuIndex"), &mayuIndex, 0);\r
+ while (DeleteMenu(hMenuSubSub, 0, MF_BYPOSITION))\r
+ ;\r
+ tregex getName(_T("^([^;]*);"));\r
+ for (int index = 0; ; index ++) {\r
+ _TCHAR buf[100];\r
+ _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);\r
+ tstringi dot_mayu;\r
+ if (!reg.read(buf, &dot_mayu))\r
+ break;\r
+ tsmatch what;\r
+ if (boost::regex_search(dot_mayu, what, getName)) {\r
+ MENUITEMINFO mii;\r
+ std::memset(&mii, 0, sizeof(mii));\r
+ mii.cbSize = sizeof(mii);\r
+ mii.fMask = MIIM_ID | MIIM_STATE | MIIM_TYPE;\r
+ mii.fType = MFT_STRING;\r
+ mii.fState =\r
+ MFS_ENABLED | ((mayuIndex == index) ? MFS_CHECKED : 0);\r
+ mii.wID = ID_MENUITEM_reloadBegin + index;\r
+ tstringi name(what.str(1));\r
+ mii.dwTypeData = const_cast<_TCHAR *>(name.c_str());\r
+ mii.cch = name.size();\r
+\r
+ InsertMenuItem(hMenuSubSub, index, TRUE, &mii);\r
+ }\r
+ }\r
+\r
+ // show popup menu\r
+ TrackPopupMenu(hMenuSub, TPM_LEFTALIGN,\r
+ p.x, p.y, 0, i_hwnd, NULL);\r
+ // TrackPopupMenu may fail (ERROR_POPUP_ALREADY_ACTIVE)\r
+ break;\r
+ }\r
+\r
+ case WM_LBUTTONDBLCLK:\r
+ SendMessage(i_hwnd, WM_COMMAND,\r
+ MAKELONG(ID_MENUITEM_investigate, 0), 0);\r
+ break;\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ case WM_APP_escapeNLSKeysFailed:\r
+ if (i_lParam) {\r
+ This->m_log << _T("escape NLS keys done code=") << i_wParam << std::endl;\r
+ if (i_wParam != YAMY_SUCCESS && i_wParam != YAMY_ERROR_RETRY_INJECTION_SUCCESS) {\r
+ int ret = This->errorDialogWithCode(IDS_escapeNlsKeysFailed, i_wParam, MB_RETRYCANCEL | MB_ICONSTOP);\r
+ if (ret == IDRETRY) {\r
+ This->m_fixScancodeMap.escape(true);\r
+ }\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
+ if (notify_code == 0) // menu\r
+ switch (id) {\r
+ default:\r
+ if (ID_MENUITEM_reloadBegin <= id) {\r
+ Registry reg(MAYU_REGISTRY_ROOT);\r
+ reg.write(_T(".mayuIndex"), id - ID_MENUITEM_reloadBegin);\r
+ This->load();\r
+ }\r
+ break;\r
+ case ID_MENUITEM_reload:\r
+ This->load();\r
+ break;\r
+ case ID_MENUITEM_investigate: {\r
+ ShowWindow(This->m_hwndLog, SW_SHOW);\r
+ ShowWindow(This->m_hwndInvestigate, SW_SHOW);\r
+\r
+ RECT rc1, rc2;\r
+ GetWindowRect(This->m_hwndInvestigate, &rc1);\r
+ GetWindowRect(This->m_hwndLog, &rc2);\r
+\r
+ MoveWindow(This->m_hwndLog, rc1.left, rc1.bottom,\r
+ rcWidth(&rc1), rcHeight(&rc2), TRUE);\r
+\r
+ SetForegroundWindow(This->m_hwndLog);\r
+ SetForegroundWindow(This->m_hwndInvestigate);\r
+ break;\r
+ }\r
+ case ID_MENUITEM_setting:\r
+ if (!This->m_isSettingDialogOpened) {\r
+ This->m_isSettingDialogOpened = true;\r
+ if (DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_setting),\r
+ NULL, dlgSetting_dlgProc))\r
+ This->load();\r
+ This->m_isSettingDialogOpened = false;\r
+ }\r
+ break;\r
+ case ID_MENUITEM_log:\r
+ ShowWindow(This->m_hwndLog, SW_SHOW);\r
+ SetForegroundWindow(This->m_hwndLog);\r
+ break;\r
+ case ID_MENUITEM_check: {\r
+ BOOL ret;\r
+ BYTE keys[256];\r
+ ret = GetKeyboardState(keys);\r
+ if (ret == 0) {\r
+ This->m_log << _T("Check Keystate Failed(%d)")\r
+ << GetLastError() << std::endl;\r
+ } else {\r
+ This->m_log << _T("Check Keystate: ") << std::endl;\r
+ for (int i = 0; i < 0xff; i++) {\r
+ USHORT asyncKey;\r
+ asyncKey = GetAsyncKeyState(i);\r
+ This->m_log << std::hex;\r
+ if (asyncKey & 0x8000) {\r
+ This->m_log << _T(" ") << VK2TCHAR[i]\r
+ << _T("(0x") << i << _T("): pressed!")\r
+ << std::endl;\r
+ }\r
+ if (i == 0x14 || // VK_CAPTITAL\r
+ i == 0x15 || // VK_KANA\r
+ i == 0x19 || // VK_KANJI\r
+ i == 0x90 || // VK_NUMLOCK\r
+ i == 0x91 // VK_SCROLL\r
+ ) {\r
+ if (keys[i] & 1) {\r
+ This->m_log << _T(" ") << VK2TCHAR[i]\r
+ << _T("(0x") << i << _T("): locked!")\r
+ << std::endl;\r
+ }\r
+ }\r
+ This->m_log << std::dec;\r
+ }\r
+ This->m_log << std::endl;\r
+ }\r
+ break;\r
+ }\r
+ case ID_MENUITEM_version:\r
+ ShowWindow(This->m_hwndVersion, SW_SHOW);\r
+ SetForegroundWindow(This->m_hwndVersion);\r
+ break;\r
+ case ID_MENUITEM_help: {\r
+ _TCHAR buf[GANA_MAX_PATH];\r
+ CHECK_TRUE( GetModuleFileName(g_hInst, buf, NUMBER_OF(buf)) );\r
+ tstringi helpFilename = pathRemoveFileSpec(buf);\r
+ helpFilename += _T("\\");\r
+ helpFilename += loadString(IDS_helpFilename);\r
+ ShellExecute(NULL, _T("open"), helpFilename.c_str(),\r
+ NULL, NULL, SW_SHOWNORMAL);\r
+ break;\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
+ This->m_engine.prepairQuit();\r
+ PostQuitMessage(0);\r
+ break;\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ case WM_APP_engineNotify: {\r
+ switch (i_wParam) {\r
+ case EngineNotify_shellExecute:\r
+ This->m_engine.shellExecute();\r
+ break;\r
+ case EngineNotify_loadSetting:\r
+ This->load();\r
+ break;\r
+ case EngineNotify_helpMessage:\r
+ This->showHelpMessage(false);\r
+ if (i_lParam)\r
+ This->showHelpMessage(true);\r
+ break;\r
+ case EngineNotify_showDlg: {\r
+ // show investigate/log window\r
+ int sw = (i_lParam & ~MayuDialogType_mask);\r
+ HWND hwnd = NULL;\r
+ switch (static_cast<MayuDialogType>(\r
+ i_lParam & MayuDialogType_mask)) {\r
+ case MayuDialogType_investigate:\r
+ hwnd = This->m_hwndInvestigate;\r
+ break;\r
+ case MayuDialogType_log:\r
+ hwnd = This->m_hwndLog;\r
+ break;\r
+ }\r
+ if (hwnd) {\r
+ ShowWindow(hwnd, sw);\r
+ switch (sw) {\r
+ case SW_SHOWNORMAL:\r
+ case SW_SHOWMAXIMIZED:\r
+ case SW_SHOW:\r
+ case SW_RESTORE:\r
+ case SW_SHOWDEFAULT:\r
+ SetForegroundWindow(hwnd);\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ case EngineNotify_setForegroundWindow:\r
+ // FIXME: completely useless. why ?\r
+ setForegroundWindow(reinterpret_cast<HWND>(i_lParam));\r
+ {\r
+ Acquire a(&This->m_log, 1);\r
+ This->m_log << _T("setForegroundWindow(0x")\r
+ << std::hex << i_lParam << std::dec << _T(")")\r
+ << std::endl;\r
+ }\r
+ break;\r
+ case EngineNotify_clearLog:\r
+ SendMessage(This->m_hwndLog, WM_COMMAND,\r
+ MAKELONG(IDC_BUTTON_clearLog, 0), 0);\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ case WM_APP_dlglogNotify: {\r
+ switch (i_wParam) {\r
+ case DlgLogNotify_logCleared:\r
+ This->showBanner(true);\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ case WM_DESTROY:\r
+ if (This->m_usingSN) {\r
+ wtsUnRegisterSessionNotification(i_hwnd);\r
+ This->m_usingSN = false;\r
+ }\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
+\r
+ default:\r
+ if (i_message == This->m_WM_TaskbarRestart) {\r
+ if (This->showTasktrayIcon(true)) {\r
+ Acquire a(&This->m_log, 0);\r
+ This->m_log << _T("Tasktray icon is updated.") << std::endl;\r
+ } else {\r
+ Acquire a(&This->m_log, 1);\r
+ This->m_log << _T("Tasktray icon already exists.") << std::endl;\r
+ }\r
+ return 0;\r
+ } else if (i_message == This->m_WM_MayuIPC) {\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
+ This->m_log << _T("Enabled by another application.")\r
+ << std::endl;\r
+ } else {\r
+ Acquire a(&This->m_log, 1);\r
+ This->m_log << _T("Disabled by another application.")\r
+ << std::endl;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ return DefWindowProc(i_hwnd, i_message, i_wParam, i_lParam);\r
+ }\r
+\r
+ /// load setting\r
+ void load() {\r
+ Setting *newSetting = new Setting;\r
+\r
+ // set symbol\r
+ for (int i = 1; i < __argc; ++ i) {\r
+ if (__targv[i][0] == _T('-') && __targv[i][1] == _T('D'))\r
+ newSetting->m_symbols.insert(__targv[i] + 2);\r
+ }\r
+\r
+ if (!SettingLoader(&m_log, &m_log).load(newSetting)) {\r
+ ShowWindow(m_hwndLog, SW_SHOW);\r
+ SetForegroundWindow(m_hwndLog);\r
+ delete newSetting;\r
+ Acquire a(&m_log, 0);\r
+ m_log << _T("error: failed to load.") << std::endl;\r
+ return;\r
+ }\r
+ m_log << _T("successfully loaded.") << std::endl;\r
+ while (!m_engine.setSetting(newSetting))\r
+ Sleep(1000);\r
+ delete m_setting;\r
+ m_setting = newSetting;\r
+ }\r
+\r
+ // show message (a baloon from the task tray icon)\r
+ void showHelpMessage(bool i_doesShow = true) {\r
+ if (m_canUseTasktrayBaloon) {\r
+ if (i_doesShow) {\r
+ tstring helpMessage, helpTitle;\r
+ m_engine.getHelpMessages(&helpMessage, &helpTitle);\r
+ tcslcpy(m_ni.szInfo, helpMessage.c_str(), NUMBER_OF(m_ni.szInfo));\r
+ tcslcpy(m_ni.szInfoTitle, helpTitle.c_str(),\r
+ NUMBER_OF(m_ni.szInfoTitle));\r
+ m_ni.dwInfoFlags = NIIF_INFO;\r
+ } else\r
+ m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');\r
+ CHECK_TRUE( Shell_NotifyIcon(NIM_MODIFY, &m_ni) );\r
+ }\r
+ }\r
+\r
+ // change the task tray icon\r
+ bool showTasktrayIcon(bool i_doesAdd = false) {\r
+ m_ni.hIcon = m_tasktrayIcon[m_engine.getIsEnabled() ? 1 : 0];\r
+ m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');\r
+ if (i_doesAdd) {\r
+ // http://support.microsoft.com/kb/418138/JA/\r
+ int guard = 60;\r
+ for (; !Shell_NotifyIcon(NIM_ADD, &m_ni) && 0 < guard; -- guard) {\r
+ if (Shell_NotifyIcon(NIM_MODIFY, &m_ni)) {\r
+ return true;\r
+ }\r
+ Sleep(1000); // 1sec\r
+ }\r
+ return 0 < guard;\r
+ } else {\r
+ return !!Shell_NotifyIcon(NIM_MODIFY, &m_ni);\r
+ }\r
+ }\r
+\r
+ void showBanner(bool i_isCleared) {\r
+ time_t now;\r
+ time(&now);\r
+\r
+ _TCHAR starttimebuf[1024];\r
+ _TCHAR timebuf[1024];\r
+\r
+#ifdef __BORLANDC__\r
+#pragma message("\t\t****\tAfter std::ostream() is called, ")\r
+#pragma message("\t\t****\tstrftime(... \"%%#c\" ...) fails.")\r
+#pragma message("\t\t****\tWhy ? Bug of Borland C++ 5.5.1 ? ")\r
+#pragma message("\t\t****\t - nayuta")\r
+ _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%Y/%m/%d %H:%M:%S"),\r
+ localtime(&now));\r
+ _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%Y/%m/%d %H:%M:%S"),\r
+ localtime(&m_startTime));\r
+#else\r
+ _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%#c"), localtime(&now));\r
+ _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%#c"),\r
+ localtime(&m_startTime));\r
+#endif\r
+\r
+ Acquire a(&m_log, 0);\r
+ m_log << _T("------------------------------------------------------------") << std::endl;\r
+ m_log << loadString(IDS_mayu) << _T(" ") _T(VERSION);\r
+#ifndef NDEBUG\r
+ m_log << _T(" (DEBUG)");\r
+#endif\r
+#ifdef _UNICODE\r
+ m_log << _T(" (UNICODE)");\r
+#endif\r
+ m_log << std::endl;\r
+ m_log << _T(" built by ")\r
+ << _T(LOGNAME) << _T("@") << toLower(_T(COMPUTERNAME))\r
+ << _T(" (") << _T(__DATE__) << _T(" ")\r
+ << _T(__TIME__) << _T(", ")\r
+ << getCompilerVersionString() << _T(")") << std::endl;\r
+ _TCHAR modulebuf[1024];\r
+ CHECK_TRUE( GetModuleFileName(g_hInst, modulebuf,\r
+ NUMBER_OF(modulebuf)) );\r
+ m_log << _T("started at ") << starttimebuf << std::endl;\r
+ m_log << modulebuf << std::endl;\r
+ m_log << _T("------------------------------------------------------------") << std::endl;\r
+\r
+ if (i_isCleared) {\r
+ m_log << _T("log was cleared at ") << timebuf << std::endl;\r
+ } else {\r
+ m_log << _T("log begins at ") << timebuf << std::endl;\r
+ }\r
+ }\r
+\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
+ return MessageBox((HWND)NULL, text, title, style);\r
+ }\r
+\r
+ int enableToWriteByUser(HANDLE hdl)\r
+ {\r
+ TCHAR userName[GANA_MAX_ATOM_LENGTH];\r
+ DWORD userNameSize = NUMBER_OF(userName);\r
+\r
+ SID_NAME_USE sidType;\r
+ PSID pSid = NULL;\r
+ DWORD sidSize = 0;\r
+ TCHAR *pDomain = NULL;\r
+ DWORD domainSize = 0;\r
+\r
+ PSECURITY_DESCRIPTOR pSd;\r
+ PACL pOrigDacl;\r
+ ACL_SIZE_INFORMATION aclInfo;\r
+\r
+ PACL pNewDacl;\r
+ DWORD newDaclSize;\r
+\r
+ DWORD aceIndex;\r
+ DWORD newAceIndex = 0;\r
+\r
+ BOOL ret;\r
+ int err = 0;\r
+\r
+ ret = GetUserName(userName, &userNameSize);\r
+ if (ret == FALSE) {\r
+ err = YAMY_ERROR_ON_GET_USERNAME;\r
+ goto exit;\r
+ }\r
+\r
+ // get buffer size for pSid (and pDomain)\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 = 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 = YAMY_ERROR_NO_MEMORY;\r
+ goto exit;\r
+ }\r
+\r
+ // get SID (and Domain) for logoned user\r
+ ret = LookupAccountName(NULL, userName, pSid, &sidSize, pDomain, &domainSize, &sidType);\r
+ if (ret == FALSE) {\r
+ // LookupAccountName() should success in this time\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 = 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 = YAMY_ERROR_ON_GET_DACL;\r
+ goto exit;\r
+ }\r
+\r
+ // compute size for new DACL\r
+ newDaclSize = aclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) - sizeof(DWORD);\r
+\r
+ // allocate memory for new DACL\r
+ pNewDacl = reinterpret_cast<PACL>(LocalAlloc(LPTR, newDaclSize));\r
+ if (pNewDacl == NULL) {\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 = YAMY_ERROR_ON_INITIALIZE_ACL;\r
+ goto exit;\r
+ }\r
+\r
+ // copy original DACL to new DACL\r
+ for (aceIndex = 0; aceIndex < aclInfo.AceCount; aceIndex++) {\r
+ LPVOID pAce;\r
+\r
+ ret = GetAce(pOrigDacl, aceIndex, &pAce);\r
+ if (ret == FALSE) {\r
+ err = YAMY_ERROR_ON_GET_ACE;\r
+ goto exit;\r
+ }\r
+\r
+ if ((reinterpret_cast<ACCESS_ALLOWED_ACE*>(pAce))->Header.AceFlags & INHERITED_ACE) {\r
+ break;\r
+ }\r
+\r
+ if (EqualSid(pSid, &(reinterpret_cast<ACCESS_ALLOWED_ACE*>(pAce))->SidStart) != FALSE) {\r
+ continue;\r
+ }\r
+\r
+ ret = AddAce(pNewDacl, ACL_REVISION, MAXDWORD, pAce, (reinterpret_cast<PACE_HEADER>(pAce))->AceSize);\r
+ if (ret == FALSE) {\r
+ err = YAMY_ERROR_ON_ADD_ACE;\r
+ goto exit;\r
+ }\r
+\r
+ newAceIndex++;\r
+ }\r
+\r
+ ret = AddAccessAllowedAce(pNewDacl, ACL_REVISION, GENERIC_ALL, pSid);\r
+ if (ret == FALSE) {\r
+ err = YAMY_ERROR_ON_ADD_ALLOWED_ACE;\r
+ goto exit;\r
+ }\r
+\r
+ // copy the rest of inherited ACEs\r
+ for (; aceIndex < aclInfo.AceCount; aceIndex++) {\r
+ LPVOID pAce;\r
+\r
+ ret = GetAce(pOrigDacl, aceIndex, &pAce);\r
+ if (ret == FALSE) {\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 = 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 = YAMY_ERROR_ON_SET_SECURITYINFO;\r
+ }\r
+\r
+exit:\r
+ LocalFree(pSd);\r
+ LocalFree(pSid);\r
+ LocalFree(pDomain);\r
+ LocalFree(pNewDacl);\r
+\r
+ return err;\r
+ }\r
+\r
+public:\r
+ ///\r
+ Mayu(HANDLE i_mutex)\r
+ : m_hwndTaskTray(NULL),\r
+ m_mutex(i_mutex),\r
+ m_hwndLog(NULL),\r
+ m_WM_TaskbarRestart(RegisterWindowMessage(_T("TaskbarCreated"))),\r
+ m_WM_MayuIPC(RegisterWindowMessage(WM_MayuIPC_NAME)),\r
+ m_canUseTasktrayBaloon(\r
+ PACKVERSION(5, 0) <= getDllVersion(_T("shlwapi.dll"))),\r
+ m_log(WM_APP_msgStreamNotify),\r
+ m_setting(NULL),\r
+ m_isSettingDialogOpened(false),\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
+ if (checkWindowsVersion(6, 0) != FALSE) { // enableToWriteByUser() is available only Vista or later\r
+ err = enableToWriteByUser(m_hNotifyMailslot);\r
+ if (err) {\r
+ errorDialogWithCode(IDS_cannotPermitStandardUser, err);\r
+ }\r
+ }\r
+\r
+ m_hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
+ ASSERT(m_hNotifyEvent);\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( Register_target() );\r
+ CHECK_TRUE( Register_tasktray() );\r
+\r
+ // change dir\r
+#if 0\r
+ HomeDirectories pathes;\r
+ getHomeDirectories(&pathes);\r
+ for (HomeDirectories::iterator i = pathes.begin(); i != pathes.end(); ++ i)\r
+ if (SetCurrentDirectory(i->c_str()))\r
+ break;\r
+#endif\r
+\r
+ // create windows, dialogs\r
+ tstringi title = loadString(IDS_mayu);\r
+ m_hwndTaskTray = CreateWindow(_T("mayuTasktray"), title.c_str(),\r
+ WS_OVERLAPPEDWINDOW,\r
+ CW_USEDEFAULT, CW_USEDEFAULT,\r
+ CW_USEDEFAULT, CW_USEDEFAULT,\r
+ NULL, NULL, g_hInst, this);\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
+ m_usingSN = wtsRegisterSessionNotification(m_hwndTaskTray,\r
+ NOTIFY_FOR_THIS_SESSION);\r
+\r
+ DlgLogData dld;\r
+ dld.m_log = &m_log;\r
+ dld.m_hwndTaskTray = m_hwndTaskTray;\r
+ m_hwndLog =\r
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_log), NULL,\r
+ dlgLog_dlgProc, (LPARAM)&dld);\r
+ CHECK_TRUE( m_hwndLog );\r
+\r
+ DlgInvestigateData did;\r
+ did.m_engine = &m_engine;\r
+ did.m_hwndLog = m_hwndLog;\r
+ m_hwndInvestigate =\r
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_investigate), NULL,\r
+ dlgInvestigate_dlgProc, (LPARAM)&did);\r
+ CHECK_TRUE( m_hwndInvestigate );\r
+\r
+ m_hwndVersion =\r
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_version),\r
+ NULL, dlgVersion_dlgProc,\r
+ (LPARAM)m_engine.getMayudVersion().c_str());\r
+ CHECK_TRUE( m_hwndVersion );\r
+\r
+ // attach log\r
+#ifdef LOG_TO_FILE\r
+ tstring path;\r
+ _TCHAR exePath[GANA_MAX_PATH];\r
+ _TCHAR exeDrive[GANA_MAX_PATH];\r
+ _TCHAR exeDir[GANA_MAX_PATH];\r
+ GetModuleFileName(NULL, exePath, GANA_MAX_PATH);\r
+ _tsplitpath_s(exePath, exeDrive, GANA_MAX_PATH, exeDir, GANA_MAX_PATH, NULL, 0, NULL, 0);\r
+ path = exeDrive;\r
+ path += exeDir;\r
+ path += _T("mayu.log");\r
+ m_logFile.open(path.c_str(), std::ios::app);\r
+ m_logFile.imbue(std::locale("japanese"));\r
+#endif // LOG_TO_FILE\r
+ SendMessage(GetDlgItem(m_hwndLog, IDC_EDIT_log), EM_SETLIMITTEXT, 0, 0);\r
+ m_log.attach(m_hwndTaskTray);\r
+\r
+ // start keyboard handler thread\r
+ m_engine.setAssociatedWndow(m_hwndTaskTray);\r
+ m_engine.start();\r
+\r
+ // show tasktray icon\r
+ m_tasktrayIcon[0] = loadSmallIcon(IDI_ICON_mayu_disabled);\r
+ m_tasktrayIcon[1] = loadSmallIcon(IDI_ICON_mayu);\r
+ std::memset(&m_ni, 0, sizeof(m_ni));\r
+ m_ni.uID = ID_TaskTrayIcon;\r
+ m_ni.hWnd = m_hwndTaskTray;\r
+ m_ni.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;\r
+ m_ni.hIcon = m_tasktrayIcon[1];\r
+ m_ni.uCallbackMessage = WM_APP_taskTrayNotify;\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 = NOTIFYICONDATA_V3_SIZE;\r
+ m_ni.uFlags |= NIF_INFO;\r
+ } else\r
+ m_ni.cbSize = NOTIFYICONDATA_V1_SIZE;\r
+ showTasktrayIcon(true);\r
+\r
+ // create menu\r
+ m_hMenuTaskTray = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU_tasktray));\r
+ ASSERT(m_hMenuTaskTray);\r
+\r
+ // set initial lock state\r
+ notifyLockState();\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
+\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
+ title, sizeof(title)/sizeof(title[0]));\r
+ _stprintf_s(buf, sizeof(buf)/sizeof(buf[0]),\r
+ text, _T("yamyd32"), GetLastError());\r
+ MessageBox((HWND)NULL, buf, title, MB_OK | MB_ICONSTOP);\r
+ } else {\r
+ CloseHandle(m_pi.hThread);\r
+ }\r
+#endif // _WIN64\r
+ }\r
+\r
+ ///\r
+ ~Mayu() {\r
+#ifdef USE_MAILSLOT\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_log.detach();\r
+#ifdef LOG_TO_FILE\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
+\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
+ if (!(m_sessionState & SESSION_END_QUERIED)) {\r
+ DWORD_PTR result;\r
+ SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG, 3000, &result);\r
+ }\r
+\r
+ // destroy windows\r
+ CHECK_TRUE( DestroyWindow(m_hwndVersion) );\r
+ CHECK_TRUE( DestroyWindow(m_hwndInvestigate) );\r
+ CHECK_TRUE( DestroyWindow(m_hwndLog) );\r
+ CHECK_TRUE( DestroyWindow(m_hwndTaskTray) );\r
+\r
+ // destroy menu\r
+ DestroyMenu(m_hMenuTaskTray);\r
+\r
+ // delete tasktray icon\r
+ CHECK_TRUE( Shell_NotifyIcon(NIM_DELETE, &m_ni) );\r
+ CHECK_TRUE( DestroyIcon(m_tasktrayIcon[1]) );\r
+ CHECK_TRUE( DestroyIcon(m_tasktrayIcon[0]) );\r
+\r
+ // stop keyboard handler thread\r
+ m_engine.stop();\r
+\r
+ // remove setting;\r
+ delete m_setting;\r
+ }\r
+\r
+ /// message loop\r
+ WPARAM messageLoop() {\r
+ showBanner(false);\r
+ load();\r
+\r
+#ifdef USE_MAILSLOT\r
+ mailslotHandler(0, 0);\r
+ while (1) {\r
+ HANDLE handles[] = { m_hNotifyEvent };\r
+ DWORD ret;\r
+ switch (ret = MsgWaitForMultipleObjectsEx(NUMBER_OF(handles), &handles[0],\r
+ INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE)) {\r
+ case WAIT_OBJECT_0: // m_hNotifyEvent\r
+ break;\r
+\r
+ case WAIT_OBJECT_0 + NUMBER_OF(handles): {\r
+ MSG msg;\r
+ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {\r
+ if (msg.message == WM_QUIT) {\r
+ return msg.wParam;\r
+ }\r
+ if (IsDialogMessage(m_hwndLog, &msg))\r
+ break;\r
+ if (IsDialogMessage(m_hwndInvestigate, &msg))\r
+ break;\r
+ if (IsDialogMessage(m_hwndVersion, &msg))\r
+ break;\r
+ TranslateMessage(&msg);\r
+ DispatchMessage(&msg);\r
+ break;\r
+ }\r
+ break;\r
+ }\r
+\r
+ case WAIT_IO_COMPLETION:\r
+ break;\r
+\r
+ case 0x102:\r
+ default:\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
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// Functions\r
+\r
+\r
+/// convert registry\r
+void convertRegistry()\r
+{\r
+ Registry reg(MAYU_REGISTRY_ROOT);\r
+ tstringi dot_mayu;\r
+ bool doesAdd = false;\r
+ DWORD index;\r
+ if (reg.read(_T(".mayu"), &dot_mayu)) {\r
+ reg.write(_T(".mayu0"), _T(";") + dot_mayu + _T(";"));\r
+ reg.remove(_T(".mayu"));\r
+ doesAdd = true;\r
+ index = 0;\r
+ } else if (!reg.read(_T(".mayu0"), &dot_mayu)) {\r
+ reg.write(_T(".mayu0"), loadString(IDS_readFromHomeDirectory) + _T(";;"));\r
+ doesAdd = true;\r
+ index = 1;\r
+ }\r
+ if (doesAdd) {\r
+ Registry commonreg(HKEY_LOCAL_MACHINE, _T("Software\\GANAware\\mayu"));\r
+ tstringi dir, layout;\r
+ if (commonreg.read(_T("dir"), &dir) &&\r
+ commonreg.read(_T("layout"), &layout)) {\r
+ tstringi tmp = _T(";") + dir + _T("\\dot.mayu");\r
+ if (layout == _T("109")) {\r
+ reg.write(_T(".mayu1"), loadString(IDS_109Emacs) + tmp\r
+ + _T(";-DUSE109") _T(";-DUSEdefault"));\r
+ reg.write(_T(".mayu2"), loadString(IDS_104on109Emacs) + tmp\r
+ + _T(";-DUSE109") _T(";-DUSEdefault") _T(";-DUSE104on109"));\r
+ reg.write(_T(".mayu3"), loadString(IDS_109) + tmp\r
+ + _T(";-DUSE109"));\r
+ reg.write(_T(".mayu4"), loadString(IDS_104on109) + tmp\r
+ + _T(";-DUSE109") _T(";-DUSE104on109"));\r
+ } else {\r
+ reg.write(_T(".mayu1"), loadString(IDS_104Emacs) + tmp\r
+ + _T(";-DUSE104") _T(";-DUSEdefault"));\r
+ reg.write(_T(".mayu2"), loadString(IDS_109on104Emacs) + tmp\r
+ + _T(";-DUSE104") _T(";-DUSEdefault") _T(";-DUSE109on104"));\r
+ reg.write(_T(".mayu3"), loadString(IDS_104) + tmp\r
+ + _T(";-DUSE104"));\r
+ reg.write(_T(".mayu4"), loadString(IDS_109on104) + tmp\r
+ + _T(";-DUSE104") _T(";-DUSE109on104"));\r
+ }\r
+ reg.write(_T(".mayuIndex"), index);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/// main\r
+int WINAPI _tWinMain(HINSTANCE i_hInstance, HINSTANCE /* i_hPrevInstance */,\r
+ LPTSTR /* i_lpszCmdLine */, int /* i_nCmdShow */)\r
+{\r
+ g_hInst = i_hInstance;\r
+\r
+ // set locale\r
+ CHECK_TRUE( _tsetlocale(LC_ALL, _T("")) );\r
+\r
+ // common controls\r
+#if defined(_WIN95)\r
+ InitCommonControls();\r
+#else\r
+ INITCOMMONCONTROLSEX icc;\r
+ icc.dwSize = sizeof(icc);\r
+ icc.dwICC = ICC_LISTVIEW_CLASSES;\r
+ CHECK_TRUE( InitCommonControlsEx(&icc) );\r
+#endif\r
+\r
+ // convert old registry to new registry\r
+#ifndef USE_INI\r
+ convertRegistry();\r
+#endif // !USE_INI\r
+\r
+ // is another mayu running ?\r
+ HANDLE mutex = CreateMutex((SECURITY_ATTRIBUTES *)NULL, TRUE,\r
+ MUTEX_MAYU_EXCLUSIVE_RUNNING);\r
+ if (GetLastError() == ERROR_ALREADY_EXISTS) {\r
+ // another mayu already running\r
+ tstring text = loadString(IDS_mayuAlreadyExists);\r
+ tstring title = loadString(IDS_mayu);\r
+ if (g_hookData) {\r
+ UINT WM_TaskbarRestart = RegisterWindowMessage(_T("TaskbarCreated"));\r
+ PostMessage(reinterpret_cast<HWND>(g_hookData->m_hwndTaskTray),\r
+ WM_TaskbarRestart, 0, 0);\r
+ }\r
+ MessageBox((HWND)NULL, text.c_str(), title.c_str(), MB_OK | MB_ICONSTOP);\r
+ return 1;\r
+ }\r
+\r
+ try {\r
+ Mayu(mutex).messageLoop();\r
+ } catch (ErrorMessage &i_e) {\r
+ tstring title = loadString(IDS_mayu);\r
+ MessageBox((HWND)NULL, i_e.getMessage().c_str(), title.c_str(),\r
+ MB_OK | MB_ICONSTOP);\r
+ }\r
+\r
+ CHECK_TRUE( CloseHandle(mutex) );\r
+ return 0;\r
+}\r