1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 #define APSTUDIO_INVOKED
8 #include "compiler_specific_func.h"
9 #include "dlginvestigate.h"
11 #include "dlgsetting.h"
12 #include "dlgversion.h"
14 #include "errormessage.h"
21 #include "msgstream.h"
22 #include "multithread.h"
26 #include "windowstool.h"
35 #define ID_MENUITEM_reloadBegin _APS_NEXT_COMMAND_VALUE
38 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45 HWND m_hwndTaskTray; /// tasktray window
46 HWND m_hwndLog; /// log dialog
47 HWND m_hwndInvestigate; /// investigate dialog
48 HWND m_hwndVersion; /// version dialog
50 UINT m_WM_TaskbarRestart; /** window message sent when
52 UINT m_WM_MayuIPC; /** IPC message sent from
54 NOTIFYICONDATA m_ni; /// taskbar icon data
55 HICON m_tasktrayIcon[2]; /// taskbar icon
56 bool m_canUseTasktrayBaloon; ///
58 tomsgstream m_log; /** log stream (output to log
64 HMENU m_hMenuTaskTray; /// tasktray menu
66 PROCESS_INFORMATION m_pi;
69 HANDLE m_hNotifyMailslot; /// mailslot to receive notify
70 HANDLE m_hNotifyEvent; /// event on receive notify
71 OVERLAPPED m_olNotify; ///
72 BYTE m_notifyBuf[NOTIFY_MESSAGE_SIZE];
73 #endif // USE_MAILSLOT
75 Setting *m_setting; /// current setting
76 bool m_isSettingDialogOpened; /// is setting dialog opened ?
78 Engine m_engine; /// engine
80 bool m_usingSN; /// using WTSRegisterSessionNotification() ?
81 time_t m_startTime; /// mayu started at ...
85 WM_APP_taskTrayNotify = WM_APP + 101, ///
86 WM_APP_msgStreamNotify = WM_APP + 102, ///
87 ID_TaskTrayIcon = 1, ///
92 static VOID CALLBACK mailslotProc(DWORD i_code, DWORD i_len, LPOVERLAPPED i_ol)
96 pThis = reinterpret_cast<Mayu*>(CONTAINING_RECORD(i_ol, Mayu, m_olNotify));
97 pThis->mailslotHandler(i_code, i_len);
101 BOOL mailslotHandler(DWORD i_code, DWORD i_len)
109 cd.dwData = reinterpret_cast<Notify *>(m_notifyBuf)->m_type;
111 cd.lpData = m_notifyBuf;
115 memset(m_notifyBuf, 0, sizeof(m_notifyBuf));
116 result = ReadFileEx(m_hNotifyMailslot, m_notifyBuf, sizeof(m_notifyBuf),
117 &m_olNotify, Mayu::mailslotProc);
120 #endif // USE_MAILSLOT
122 /// register class for tasktray
123 ATOM Register_tasktray()
127 wc.lpfnWndProc = tasktray_wndProc;
129 wc.cbWndExtra = sizeof(Mayu *);
130 wc.hInstance = g_hInst;
133 wc.hbrBackground = NULL;
134 wc.lpszMenuName = NULL;
135 wc.lpszClassName = _T("mayuTasktray");
136 return RegisterClass(&wc);
140 BOOL notifyHandler(COPYDATASTRUCT *cd)
144 case Notify::Type_setFocus:
145 case Notify::Type_name:
147 NotifySetFocus *n = (NotifySetFocus *)cd->lpData;
148 n->m_className[NUMBER_OF(n->m_className) - 1] = _T('\0');
149 n->m_titleName[NUMBER_OF(n->m_titleName) - 1] = _T('\0');
151 if (n->m_type == Notify::Type_setFocus)
152 m_engine.setFocus(reinterpret_cast<HWND>(n->m_hwnd), n->m_threadId,
153 n->m_className, n->m_titleName, false);
156 Acquire a(&m_log, 1);
157 m_log << _T("HWND:\t") << std::hex
159 << std::dec << std::endl;
160 m_log << _T("THREADID:") << static_cast<int>(n->m_threadId)
163 Acquire a(&m_log, (n->m_type == Notify::Type_name) ? 0 : 1);
164 m_log << _T("CLASS:\t") << n->m_className << std::endl;
165 m_log << _T("TITLE:\t") << n->m_titleName << std::endl;
168 HWND hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), &isMDI);
172 getChildWindowRect(hwnd, &rc);
173 m_log << _T("MDI Window Position/Size: (")
174 << rc.left << _T(", ") << rc.top << _T(") / (")
175 << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")
177 hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), NULL);
180 GetWindowRect(hwnd, &rc);
181 m_log << _T("Toplevel Window Position/Size: (")
182 << rc.left << _T(", ") << rc.top << _T(") / (")
183 << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")
186 SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);
187 m_log << _T("Desktop Window Position/Size: (")
188 << rc.left << _T(", ") << rc.top << _T(") / (")
189 << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")
196 case Notify::Type_lockState:
198 NotifyLockState *n = (NotifyLockState *)cd->lpData;
199 m_engine.setLockState(n->m_isNumLockToggled,
200 n->m_isCapsLockToggled,
201 n->m_isScrollLockToggled,
202 n->m_isKanaLockToggled,
203 n->m_isImeLockToggled,
204 n->m_isImeCompToggled);
206 Acquire a(&m_log, 0);
207 if (n->m_isKanaLockToggled) {
208 m_log << _T("Notify::Type_lockState Kana on : ");
210 m_log << _T("Notify::Type_lockState Kana off : ");
212 m_log << n->m_debugParam << ", "
213 << g_hookData->m_correctKanaLockHandling << std::endl;
218 case Notify::Type_sync:
220 m_engine.syncNotify();
224 case Notify::Type_threadDetach:
226 NotifyThreadDetach *n = (NotifyThreadDetach *)cd->lpData;
227 m_engine.threadDetachNotify(n->m_threadId);
231 case Notify::Type_command:
233 NotifyCommand *n = (NotifyCommand *)cd->lpData;
234 m_engine.commandNotify(n->m_hwnd, n->m_message,
235 n->m_wParam, n->m_lParam);
239 case Notify::Type_show:
241 NotifyShow *n = (NotifyShow *)cd->lpData;
244 case NotifyShow::Show_Maximized:
245 m_engine.setShow(true, false, n->m_isMDI);
247 case NotifyShow::Show_Minimized:
248 m_engine.setShow(false, true, n->m_isMDI);
250 case NotifyShow::Show_Normal:
252 m_engine.setShow(false, false, n->m_isMDI);
258 case Notify::Type_log:
260 Acquire a(&m_log, 1);
261 NotifyLog *n = (NotifyLog *)cd->lpData;
262 m_log << _T("hook log: ") << n->m_msg << std::endl;
269 /// window procedure for tasktray
270 static LRESULT CALLBACK
271 tasktray_wndProc(HWND i_hwnd, UINT i_message,
272 WPARAM i_wParam, LPARAM i_lParam)
275 Mayu *This = reinterpret_cast<Mayu *>(GetWindowLongPtr(i_hwnd, 0));
277 Mayu *This = reinterpret_cast<Mayu *>(GetWindowLong(i_hwnd, 0));
284 This = reinterpret_cast<Mayu *>(
285 reinterpret_cast<CREATESTRUCT *>(i_lParam)->lpCreateParams);
287 SetWindowLongPtr(i_hwnd, 0, (LONG_PTR)This);
289 SetWindowLong(i_hwnd, 0, (long)This);
299 cd = reinterpret_cast<COPYDATASTRUCT *>(i_lParam);
300 return This->notifyHandler(cd);
302 case WM_QUERYENDSESSION:
303 This->m_engine.prepairQuit();
307 #ifndef WM_WTSSESSION_CHANGE // WinUser.h
308 # define WM_WTSSESSION_CHANGE 0x02B1
310 case WM_WTSSESSION_CHANGE:
315 #ifndef WTS_CONSOLE_CONNECT // WinUser.h
316 # define WTS_CONSOLE_CONNECT 0x1
317 # define WTS_CONSOLE_DISCONNECT 0x2
318 # define WTS_REMOTE_CONNECT 0x3
319 # define WTS_REMOTE_DISCONNECT 0x4
320 # define WTS_SESSION_LOGON 0x5
321 # define WTS_SESSION_LOGOFF 0x6
322 # define WTS_SESSION_LOCK 0x7
323 # define WTS_SESSION_UNLOCK 0x8
325 case WTS_CONSOLE_CONNECT:
326 m = "WTS_CONSOLE_CONNECT";
327 if (!This->m_engine.resume()) {
328 This->m_engine.prepairQuit();
332 case WTS_CONSOLE_DISCONNECT:
333 m = "WTS_CONSOLE_DISCONNECT";
334 This->m_engine.pause();
336 case WTS_REMOTE_CONNECT: m = "WTS_REMOTE_CONNECT"; break;
337 case WTS_REMOTE_DISCONNECT: m = "WTS_REMOTE_DISCONNECT"; break;
338 case WTS_SESSION_LOGON: m = "WTS_SESSION_LOGON"; break;
339 case WTS_SESSION_LOGOFF: m = "WTS_SESSION_LOGOFF"; break;
340 case WTS_SESSION_LOCK: m = "WTS_SESSION_LOCK"; break;
341 case WTS_SESSION_UNLOCK: m = "WTS_SESSION_UNLOCK"; break;
342 //case WTS_SESSION_REMOTE_CONTROL: m = "WTS_SESSION_REMOTE_CONTROL"; break;
344 This->m_log << _T("WM_WTSESSION_CHANGE(")
345 << i_wParam << ", " << i_lParam << "): "
349 case WM_APP_msgStreamNotify:
351 tomsgstream::StreamBuf *log =
352 reinterpret_cast<tomsgstream::StreamBuf *>(i_lParam);
353 const tstring &str = log->acquireString();
355 This->m_logFile << str << std::flush;
356 #endif // LOG_TO_FILE
357 editInsertTextAtLast(GetDlgItem(This->m_hwndLog, IDC_EDIT_log),
359 log->releaseString();
363 case WM_APP_taskTrayNotify:
365 if (i_wParam == ID_TaskTrayIcon)
371 CHECK_TRUE( GetCursorPos(&p) );
372 SetForegroundWindow(i_hwnd);
373 HMENU hMenuSub = GetSubMenu(This->m_hMenuTaskTray, 0);
374 if (This->m_engine.getIsEnabled())
375 CheckMenuItem(hMenuSub, ID_MENUITEM_disable,
376 MF_UNCHECKED | MF_BYCOMMAND);
378 CheckMenuItem(hMenuSub, ID_MENUITEM_disable,
379 MF_CHECKED | MF_BYCOMMAND);
380 CHECK_TRUE( SetMenuDefaultItem(hMenuSub,
381 ID_MENUITEM_investigate, FALSE) );
383 // create reload menu
384 HMENU hMenuSubSub = GetSubMenu(hMenuSub, 1);
385 Registry reg(MAYU_REGISTRY_ROOT);
387 reg.read(_T(".mayuIndex"), &mayuIndex, 0);
388 while (DeleteMenu(hMenuSubSub, 0, MF_BYPOSITION))
390 tregex getName(_T("^([^;]*);"));
391 for (int index = 0; ; index ++)
394 _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);
396 if (!reg.read(buf, &dot_mayu))
399 if (boost::regex_search(dot_mayu, what, getName))
402 std::memset(&mii, 0, sizeof(mii));
403 mii.cbSize = sizeof(mii);
404 mii.fMask = MIIM_ID | MIIM_STATE | MIIM_TYPE;
405 mii.fType = MFT_STRING;
407 MFS_ENABLED | ((mayuIndex == index) ? MFS_CHECKED : 0);
408 mii.wID = ID_MENUITEM_reloadBegin + index;
409 tstringi name(what.str(1));
410 mii.dwTypeData = const_cast<_TCHAR *>(name.c_str());
411 mii.cch = name.size();
413 InsertMenuItem(hMenuSubSub, index, TRUE, &mii);
418 TrackPopupMenu(hMenuSub, TPM_LEFTALIGN,
419 p.x, p.y, 0, i_hwnd, NULL);
420 // TrackPopupMenu may fail (ERROR_POPUP_ALREADY_ACTIVE)
424 case WM_LBUTTONDBLCLK:
425 SendMessage(i_hwnd, WM_COMMAND,
426 MAKELONG(ID_MENUITEM_investigate, 0), 0);
434 int notify_code = HIWORD(i_wParam);
435 int id = LOWORD(i_wParam);
436 if (notify_code == 0) // menu
440 if (ID_MENUITEM_reloadBegin <= id)
442 Registry reg(MAYU_REGISTRY_ROOT);
443 reg.write(_T(".mayuIndex"), id - ID_MENUITEM_reloadBegin);
447 case ID_MENUITEM_reload:
450 case ID_MENUITEM_investigate:
452 ShowWindow(This->m_hwndLog, SW_SHOW);
453 ShowWindow(This->m_hwndInvestigate, SW_SHOW);
456 GetWindowRect(This->m_hwndInvestigate, &rc1);
457 GetWindowRect(This->m_hwndLog, &rc2);
459 MoveWindow(This->m_hwndLog, rc1.left, rc1.bottom,
460 rcWidth(&rc1), rcHeight(&rc2), TRUE);
462 SetForegroundWindow(This->m_hwndLog);
463 SetForegroundWindow(This->m_hwndInvestigate);
466 case ID_MENUITEM_setting:
467 if (!This->m_isSettingDialogOpened)
469 This->m_isSettingDialogOpened = true;
470 if (DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_setting),
471 NULL, dlgSetting_dlgProc))
473 This->m_isSettingDialogOpened = false;
476 case ID_MENUITEM_log:
477 ShowWindow(This->m_hwndLog, SW_SHOW);
478 SetForegroundWindow(This->m_hwndLog);
480 case ID_MENUITEM_check:
484 ret = GetKeyboardState(keys);
487 This->m_log << _T("Check Keystate Failed(%d)")
488 << GetLastError() << std::endl;
492 This->m_log << _T("Check Keystate: ") << std::endl;
493 for (int i = 0; i < 0xff; i++)
496 asyncKey = GetAsyncKeyState(i);
497 This->m_log << std::hex;
498 if (asyncKey & 0x8000)
500 This->m_log << _T(" ") << VK2TCHAR[i]
501 << _T("(0x") << i << _T("): pressed!")
504 if (i == 0x14 || // VK_CAPTITAL
505 i == 0x15 || // VK_KANA
506 i == 0x19 || // VK_KANJI
507 i == 0x90 || // VK_NUMLOCK
508 i == 0x91 // VK_SCROLL
513 This->m_log << _T(" ") << VK2TCHAR[i]
514 << _T("(0x") << i << _T("): locked!")
518 This->m_log << std::dec;
520 This->m_log << std::endl;
524 case ID_MENUITEM_version:
525 ShowWindow(This->m_hwndVersion, SW_SHOW);
526 SetForegroundWindow(This->m_hwndVersion);
528 case ID_MENUITEM_help:
530 _TCHAR buf[GANA_MAX_PATH];
531 CHECK_TRUE( GetModuleFileName(g_hInst, buf, NUMBER_OF(buf)) );
532 tstringi helpFilename = pathRemoveFileSpec(buf);
533 helpFilename += _T("\\");
534 helpFilename += loadString(IDS_helpFilename);
535 ShellExecute(NULL, _T("open"), helpFilename.c_str(),
536 NULL, NULL, SW_SHOWNORMAL);
539 case ID_MENUITEM_disable:
540 This->m_engine.enable(!This->m_engine.getIsEnabled());
541 This->showTasktrayIcon();
543 case ID_MENUITEM_quit:
544 This->m_engine.prepairQuit();
551 case WM_APP_engineNotify:
555 case EngineNotify_shellExecute:
556 This->m_engine.shellExecute();
558 case EngineNotify_loadSetting:
561 case EngineNotify_helpMessage:
562 This->showHelpMessage(false);
564 This->showHelpMessage(true);
566 case EngineNotify_showDlg:
568 // show investigate/log window
569 int sw = (i_lParam & ~MayuDialogType_mask);
571 switch (static_cast<MayuDialogType>(
572 i_lParam & MayuDialogType_mask))
574 case MayuDialogType_investigate:
575 hwnd = This->m_hwndInvestigate;
577 case MayuDialogType_log:
578 hwnd = This->m_hwndLog;
583 ShowWindow(hwnd, sw);
587 case SW_SHOWMAXIMIZED:
591 SetForegroundWindow(hwnd);
597 case EngineNotify_setForegroundWindow:
598 // FIXME: completely useless. why ?
599 setForegroundWindow(reinterpret_cast<HWND>(i_lParam));
601 Acquire a(&This->m_log, 1);
602 This->m_log << _T("setForegroundWindow(0x")
603 << std::hex << i_lParam << std::dec << _T(")")
607 case EngineNotify_clearLog:
608 SendMessage(This->m_hwndLog, WM_COMMAND,
609 MAKELONG(IDC_BUTTON_clearLog, 0), 0);
617 case WM_APP_dlglogNotify:
621 case DlgLogNotify_logCleared:
622 This->showBanner(true);
633 wtsUnRegisterSessionNotification(i_hwnd);
634 This->m_usingSN = false;
639 if (i_message == This->m_WM_TaskbarRestart)
641 if (This->showTasktrayIcon(true))
643 Acquire a(&This->m_log, 0);
644 This->m_log << _T("Tasktray icon is updated.") << std::endl;
648 Acquire a(&This->m_log, 1);
649 This->m_log << _T("Tasktray icon already exists.") << std::endl;
653 else if (i_message == This->m_WM_MayuIPC)
655 switch (static_cast<MayuIPCCommand>(i_wParam))
657 case MayuIPCCommand_Enable:
658 This->m_engine.enable(!!i_lParam);
659 This->showTasktrayIcon();
662 Acquire a(&This->m_log, 1);
663 This->m_log << _T("Enabled by another application.")
668 Acquire a(&This->m_log, 1);
669 This->m_log << _T("Disabled by another application.")
676 return DefWindowProc(i_hwnd, i_message, i_wParam, i_lParam);
682 Setting *newSetting = new Setting;
685 for (int i = 1; i < __argc; ++ i)
687 if (__targv[i][0] == _T('-') && __targv[i][1] == _T('D'))
688 newSetting->m_symbols.insert(__targv[i] + 2);
691 if (!SettingLoader(&m_log, &m_log).load(newSetting))
693 ShowWindow(m_hwndLog, SW_SHOW);
694 SetForegroundWindow(m_hwndLog);
696 Acquire a(&m_log, 0);
697 m_log << _T("error: failed to load.") << std::endl;
700 m_log << _T("successfully loaded.") << std::endl;
701 while (!m_engine.setSetting(newSetting))
704 m_setting = newSetting;
707 // show message (a baloon from the task tray icon)
708 void showHelpMessage(bool i_doesShow = true)
710 if (m_canUseTasktrayBaloon)
714 tstring helpMessage, helpTitle;
715 m_engine.getHelpMessages(&helpMessage, &helpTitle);
716 tcslcpy(m_ni.szInfo, helpMessage.c_str(), NUMBER_OF(m_ni.szInfo));
717 tcslcpy(m_ni.szInfoTitle, helpTitle.c_str(),
718 NUMBER_OF(m_ni.szInfoTitle));
719 m_ni.dwInfoFlags = NIIF_INFO;
722 m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');
723 CHECK_TRUE( Shell_NotifyIcon(NIM_MODIFY, &m_ni) );
727 // change the task tray icon
728 bool showTasktrayIcon(bool i_doesAdd = false)
730 m_ni.hIcon = m_tasktrayIcon[m_engine.getIsEnabled() ? 1 : 0];
731 m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');
733 // http://support.microsoft.com/kb/418138/JA/
735 for (; !Shell_NotifyIcon(NIM_ADD, &m_ni) && 0 < guard; -- guard) {
736 if (Shell_NotifyIcon(NIM_MODIFY, &m_ni)) {
743 return !!Shell_NotifyIcon(NIM_MODIFY, &m_ni);
747 void showBanner(bool i_isCleared)
752 _TCHAR starttimebuf[1024];
753 _TCHAR timebuf[1024];
756 #pragma message("\t\t****\tAfter std::ostream() is called, ")
757 #pragma message("\t\t****\tstrftime(... \"%%#c\" ...) fails.")
758 #pragma message("\t\t****\tWhy ? Bug of Borland C++ 5.5.1 ? ")
759 #pragma message("\t\t****\t - nayuta")
760 _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%Y/%m/%d %H:%M:%S"),
762 _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%Y/%m/%d %H:%M:%S"),
763 localtime(&m_startTime));
765 _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%#c"), localtime(&now));
766 _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%#c"),
767 localtime(&m_startTime));
770 Acquire a(&m_log, 0);
771 m_log << _T("------------------------------------------------------------") << std::endl;
772 m_log << loadString(IDS_mayu) << _T(" ") _T(VERSION);
774 m_log << _T(" (DEBUG)");
777 m_log << _T(" (UNICODE)");
780 m_log << _T(" built by ")
781 << _T(LOGNAME) << _T("@") << toLower(_T(COMPUTERNAME))
782 << _T(" (") << _T(__DATE__) << _T(" ")
783 << _T(__TIME__) << _T(", ")
784 << getCompilerVersionString() << _T(")") << std::endl;
785 _TCHAR modulebuf[1024];
786 CHECK_TRUE( GetModuleFileName(g_hInst, modulebuf,
787 NUMBER_OF(modulebuf)) );
788 m_log << _T("started at ") << starttimebuf << std::endl;
789 m_log << modulebuf << std::endl;
790 m_log << _T("------------------------------------------------------------") << std::endl;
793 m_log << _T("log was cleared at ") << timebuf << std::endl;
795 m_log << _T("log begins at ") << timebuf << std::endl;
802 : m_hwndTaskTray(NULL),
805 m_WM_TaskbarRestart(RegisterWindowMessage(_T("TaskbarCreated"))),
806 m_WM_MayuIPC(RegisterWindowMessage(WM_MayuIPC_NAME)),
807 m_canUseTasktrayBaloon(
808 PACKVERSION(5, 0) <= getDllVersion(_T("shlwapi.dll"))),
809 m_log(WM_APP_msgStreamNotify),
811 m_isSettingDialogOpened(false),
815 m_hNotifyMailslot = CreateMailslot(NOTIFY_MAILSLOT_NAME, 0, MAILSLOT_WAIT_FOREVER, (SECURITY_ATTRIBUTES *)NULL);
816 ASSERT(m_hNotifyMailslot != INVALID_HANDLE_VALUE);
817 m_hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
818 ASSERT(m_hNotifyEvent);
819 m_olNotify.Offset = 0;
820 m_olNotify.OffsetHigh = 0;
821 m_olNotify.hEvent = m_hNotifyEvent;
822 #endif // USE_MAILSLOT
825 CHECK_TRUE( Register_focus() );
826 CHECK_TRUE( Register_target() );
827 CHECK_TRUE( Register_tasktray() );
831 HomeDirectories pathes;
832 getHomeDirectories(&pathes);
833 for (HomeDirectories::iterator i = pathes.begin(); i != pathes.end(); ++ i)
834 if (SetCurrentDirectory(i->c_str()))
838 // create windows, dialogs
839 tstringi title = loadString(IDS_mayu);
840 m_hwndTaskTray = CreateWindow(_T("mayuTasktray"), title.c_str(),
842 CW_USEDEFAULT, CW_USEDEFAULT,
843 CW_USEDEFAULT, CW_USEDEFAULT,
844 NULL, NULL, g_hInst, this);
845 CHECK_TRUE( m_hwndTaskTray );
847 // set window handle of tasktray to hooks
849 g_hookData->m_hwndTaskTray = reinterpret_cast<DWORD>(m_hwndTaskTray);
850 #endif // !USE_MAILSLOT
851 CHECK_FALSE( installHooks(Engine::keyboardDetour, &m_engine) );
852 m_usingSN = wtsRegisterSessionNotification(m_hwndTaskTray,
853 NOTIFY_FOR_THIS_SESSION);
857 dld.m_hwndTaskTray = m_hwndTaskTray;
859 CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_log), NULL,
860 dlgLog_dlgProc, (LPARAM)&dld);
861 CHECK_TRUE( m_hwndLog );
863 DlgInvestigateData did;
864 did.m_engine = &m_engine;
865 did.m_hwndLog = m_hwndLog;
867 CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_investigate), NULL,
868 dlgInvestigate_dlgProc, (LPARAM)&did);
869 CHECK_TRUE( m_hwndInvestigate );
872 CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_version),
873 NULL, dlgVersion_dlgProc,
874 (LPARAM)m_engine.getMayudVersion().c_str());
875 CHECK_TRUE( m_hwndVersion );
880 _TCHAR exePath[GANA_MAX_PATH];
881 _TCHAR exeDrive[GANA_MAX_PATH];
882 _TCHAR exeDir[GANA_MAX_PATH];
883 GetModuleFileName(NULL, exePath, GANA_MAX_PATH);
884 _tsplitpath_s(exePath, exeDrive, GANA_MAX_PATH, exeDir, GANA_MAX_PATH, NULL, 0, NULL, 0);
887 path += _T("mayu.log");
888 m_logFile.open(path.c_str(), std::ios::app);
889 m_logFile.imbue(std::locale("japanese"));
890 #endif // LOG_TO_FILE
891 SendMessage(GetDlgItem(m_hwndLog, IDC_EDIT_log), EM_SETLIMITTEXT, 0, 0);
892 m_log.attach(m_hwndTaskTray);
894 // start keyboard handler thread
895 m_engine.setAssociatedWndow(m_hwndTaskTray);
898 // show tasktray icon
899 m_tasktrayIcon[0] = loadSmallIcon(IDI_ICON_mayu_disabled);
900 m_tasktrayIcon[1] = loadSmallIcon(IDI_ICON_mayu);
901 std::memset(&m_ni, 0, sizeof(m_ni));
902 m_ni.uID = ID_TaskTrayIcon;
903 m_ni.hWnd = m_hwndTaskTray;
904 m_ni.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
905 m_ni.hIcon = m_tasktrayIcon[1];
906 m_ni.uCallbackMessage = WM_APP_taskTrayNotify;
907 tstring tip = loadString(IDS_mayu);
908 tcslcpy(m_ni.szTip, tip.c_str(), NUMBER_OF(m_ni.szTip));
909 if (m_canUseTasktrayBaloon)
911 m_ni.cbSize = sizeof(m_ni);
912 m_ni.uFlags |= NIF_INFO;
915 m_ni.cbSize = NOTIFYICONDATA_V1_SIZE;
916 showTasktrayIcon(true);
919 m_hMenuTaskTray = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU_tasktray));
920 ASSERT(m_hMenuTaskTray);
922 // set initial lock state
927 ZeroMemory(&m_pi,sizeof(m_pi));
928 ZeroMemory(&m_si,sizeof(m_si));
929 m_si.cb=sizeof(m_si);
931 result = CreateProcess(_T("yamyd32"), _T("yamyd32"), NULL, NULL, FALSE,
932 NORMAL_PRIORITY_CLASS, 0, NULL, &m_si, &m_pi);
939 LoadString(GetModuleHandle(NULL), IDS_cannotInvoke,
940 text, sizeof(text)/sizeof(text[0]));
941 LoadString(GetModuleHandle(NULL), IDS_mayu,
942 title, sizeof(title)/sizeof(title[0]));
943 _stprintf_s(buf, sizeof(buf)/sizeof(buf[0]),
944 text, _T("yamyd32"), GetLastError());
945 MessageBox((HWND)NULL, buf, title, MB_OK | MB_ICONSTOP);
949 CloseHandle(m_pi.hThread);
950 CloseHandle(m_pi.hProcess);
958 ReleaseMutex(m_mutex);
959 WaitForSingleObject(m_mutex, INFINITE);
960 // first, detach log from edit control to avoid deadlock
964 #endif // LOG_TO_FILE
966 // stop notify from mayu.dll
967 g_hookData->m_hwndTaskTray = NULL;
968 CHECK_FALSE( uninstallHooks() );
969 PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);
972 CHECK_TRUE( DestroyWindow(m_hwndVersion) );
973 CHECK_TRUE( DestroyWindow(m_hwndInvestigate) );
974 CHECK_TRUE( DestroyWindow(m_hwndLog) );
975 CHECK_TRUE( DestroyWindow(m_hwndTaskTray) );
978 DestroyMenu(m_hMenuTaskTray);
980 // delete tasktray icon
981 CHECK_TRUE( Shell_NotifyIcon(NIM_DELETE, &m_ni) );
982 CHECK_TRUE( DestroyIcon(m_tasktrayIcon[1]) );
983 CHECK_TRUE( DestroyIcon(m_tasktrayIcon[0]) );
985 // stop keyboard handler thread
992 CloseHandle(m_hNotifyEvent);
993 CloseHandle(m_hNotifyMailslot);
994 #endif // USE_MAILSLOT
1004 mailslotHandler(0, 0);
1007 HANDLE handles[] = { m_hNotifyEvent };
1009 switch (ret = MsgWaitForMultipleObjectsEx(NUMBER_OF(handles), &handles[0],
1010 INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE))
1012 case WAIT_OBJECT_0: // m_hNotifyEvent
1015 case WAIT_OBJECT_0 + NUMBER_OF(handles):
1018 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0)
1020 if (msg.message == WM_QUIT)
1024 if (IsDialogMessage(m_hwndLog, &msg))
1026 if (IsDialogMessage(m_hwndInvestigate, &msg))
1028 if (IsDialogMessage(m_hwndVersion, &msg))
1030 TranslateMessage(&msg);
1031 DispatchMessage(&msg);
1037 case WAIT_IO_COMPLETION:
1045 #else // !USE_MAILSLOT
1047 while (0 < GetMessage(&msg, NULL, 0, 0))
1049 if (IsDialogMessage(m_hwndLog, &msg))
1051 if (IsDialogMessage(m_hwndInvestigate, &msg))
1053 if (IsDialogMessage(m_hwndVersion, &msg))
1055 TranslateMessage(&msg);
1056 DispatchMessage(&msg);
1059 #endif // !USE_MAILSLOT
1064 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1068 /// convert registry
1069 void convertRegistry()
1071 Registry reg(MAYU_REGISTRY_ROOT);
1073 bool doesAdd = false;
1075 if (reg.read(_T(".mayu"), &dot_mayu))
1077 reg.write(_T(".mayu0"), _T(";") + dot_mayu + _T(";"));
1078 reg.remove(_T(".mayu"));
1082 else if (!reg.read(_T(".mayu0"), &dot_mayu))
1084 reg.write(_T(".mayu0"), loadString(IDS_readFromHomeDirectory) + _T(";;"));
1090 Registry commonreg(HKEY_LOCAL_MACHINE, _T("Software\\GANAware\\mayu"));
1091 tstringi dir, layout;
1092 if (commonreg.read(_T("dir"), &dir) &&
1093 commonreg.read(_T("layout"), &layout))
1095 tstringi tmp = _T(";") + dir + _T("\\dot.mayu");
1096 if (layout == _T("109"))
1098 reg.write(_T(".mayu1"), loadString(IDS_109Emacs) + tmp
1099 + _T(";-DUSE109") _T(";-DUSEdefault"));
1100 reg.write(_T(".mayu2"), loadString(IDS_104on109Emacs) + tmp
1101 + _T(";-DUSE109") _T(";-DUSEdefault") _T(";-DUSE104on109"));
1102 reg.write(_T(".mayu3"), loadString(IDS_109) + tmp
1104 reg.write(_T(".mayu4"), loadString(IDS_104on109) + tmp
1105 + _T(";-DUSE109") _T(";-DUSE104on109"));
1109 reg.write(_T(".mayu1"), loadString(IDS_104Emacs) + tmp
1110 + _T(";-DUSE104") _T(";-DUSEdefault"));
1111 reg.write(_T(".mayu2"), loadString(IDS_109on104Emacs) + tmp
1112 + _T(";-DUSE104") _T(";-DUSEdefault") _T(";-DUSE109on104"));
1113 reg.write(_T(".mayu3"), loadString(IDS_104) + tmp
1115 reg.write(_T(".mayu4"), loadString(IDS_109on104) + tmp
1116 + _T(";-DUSE104") _T(";-DUSE109on104"));
1118 reg.write(_T(".mayuIndex"), index);
1125 int WINAPI _tWinMain(HINSTANCE i_hInstance, HINSTANCE /* i_hPrevInstance */,
1126 LPTSTR /* i_lpszCmdLine */, int /* i_nCmdShow */)
1128 g_hInst = i_hInstance;
1131 CHECK_TRUE( _tsetlocale(LC_ALL, _T("")) );
1135 InitCommonControls();
1137 INITCOMMONCONTROLSEX icc;
1138 icc.dwSize = sizeof(icc);
1139 icc.dwICC = ICC_LISTVIEW_CLASSES;
1140 CHECK_TRUE( InitCommonControlsEx(&icc) );
1143 // convert old registry to new registry
1148 // is another mayu running ?
1149 HANDLE mutex = CreateMutex((SECURITY_ATTRIBUTES *)NULL, TRUE,
1150 MUTEX_MAYU_EXCLUSIVE_RUNNING);
1151 if (GetLastError() == ERROR_ALREADY_EXISTS)
1153 // another mayu already running
1154 tstring text = loadString(IDS_mayuAlreadyExists);
1155 tstring title = loadString(IDS_mayu);
1157 UINT WM_TaskbarRestart = RegisterWindowMessage(_T("TaskbarCreated"));
1158 PostMessage(reinterpret_cast<HWND>(g_hookData->m_hwndTaskTray),
1159 WM_TaskbarRestart, 0, 0);
1161 MessageBox((HWND)NULL, text.c_str(), title.c_str(), MB_OK | MB_ICONSTOP);
1165 // check remote desktop
1167 if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId) ||
1168 wtsGetActiveConsoleSessionId() != sessionId)
1170 tstring text = loadString(IDS_executedInRemoteDesktop);
1171 tstring title = loadString(IDS_mayu);
1172 MessageBox((HWND)NULL, text.c_str(), title.c_str(), MB_OK | MB_ICONSTOP);
1178 Mayu(mutex).messageLoop();
1180 catch (ErrorMessage &i_e)
1182 tstring title = loadString(IDS_mayu);
1183 MessageBox((HWND)NULL, i_e.getMessage().c_str(), title.c_str(),
1184 MB_OK | MB_ICONSTOP);
1187 CHECK_TRUE( CloseHandle(mutex) );