1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
5 #define APSTUDIO_INVOKED
\r
8 #include "compiler_specific_func.h"
\r
9 #include "dlginvestigate.h"
\r
11 #include "dlgsetting.h"
\r
12 #include "dlgversion.h"
\r
14 #include "errormessage.h"
\r
16 #include "function.h"
\r
19 #include "mayuipc.h"
\r
21 #include "msgstream.h"
\r
22 #include "multithread.h"
\r
23 #include "registry.h"
\r
24 #include "setting.h"
\r
26 #include "windowstool.h"
\r
27 #include "vk2tchar.h"
\r
28 #include <process.h>
\r
30 #include <commctrl.h>
\r
31 #include <wtsapi32.h>
\r
35 #define ID_MENUITEM_reloadBegin _APS_NEXT_COMMAND_VALUE
\r
38 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
45 HWND m_hwndTaskTray; /// tasktray window
\r
46 HWND m_hwndLog; /// log dialog
\r
47 HWND m_hwndInvestigate; /// investigate dialog
\r
48 HWND m_hwndVersion; /// version dialog
\r
50 UINT m_WM_TaskbarRestart; /** window message sent when
\r
52 UINT m_WM_MayuIPC; /** IPC message sent from
\r
53 other applications */
\r
54 NOTIFYICONDATA m_ni; /// taskbar icon data
\r
55 HICON m_tasktrayIcon[2]; /// taskbar icon
\r
56 bool m_canUseTasktrayBaloon; ///
\r
58 tomsgstream m_log; /** log stream (output to log
\r
61 tofstream m_logFile;
\r
62 #endif // LOG_TO_FILE
\r
64 HMENU m_hMenuTaskTray; /// tasktray menu
\r
66 PROCESS_INFORMATION m_pi;
\r
69 HANDLE m_hNotifyMailslot; /// mailslot to receive notify
\r
70 HANDLE m_hNotifyEvent; /// event on receive notify
\r
71 OVERLAPPED m_olNotify; ///
\r
72 BYTE m_notifyBuf[NOTIFY_MESSAGE_SIZE];
\r
73 #endif // USE_MAILSLOT
\r
75 Setting *m_setting; /// current setting
\r
76 bool m_isSettingDialogOpened; /// is setting dialog opened ?
\r
78 Engine m_engine; /// engine
\r
80 bool m_usingSN; /// using WTSRegisterSessionNotification() ?
\r
81 time_t m_startTime; /// mayu started at ...
\r
84 WM_APP_taskTrayNotify = WM_APP + 101, ///
\r
85 WM_APP_msgStreamNotify = WM_APP + 102, ///
\r
86 ID_TaskTrayIcon = 1, ///
\r
91 static VOID CALLBACK mailslotProc(DWORD i_code, DWORD i_len, LPOVERLAPPED i_ol) {
\r
94 pThis = reinterpret_cast<Mayu*>(CONTAINING_RECORD(i_ol, Mayu, m_olNotify));
\r
95 pThis->mailslotHandler(i_code, i_len);
\r
99 BOOL mailslotHandler(DWORD i_code, DWORD i_len) {
\r
105 cd.dwData = reinterpret_cast<Notify *>(m_notifyBuf)->m_type;
\r
107 cd.lpData = m_notifyBuf;
\r
108 notifyHandler(&cd);
\r
111 memset(m_notifyBuf, 0, sizeof(m_notifyBuf));
\r
112 result = ReadFileEx(m_hNotifyMailslot, m_notifyBuf, sizeof(m_notifyBuf),
\r
113 &m_olNotify, Mayu::mailslotProc);
\r
116 #endif // USE_MAILSLOT
\r
118 /// register class for tasktray
\r
119 ATOM Register_tasktray() {
\r
122 wc.lpfnWndProc = tasktray_wndProc;
\r
124 wc.cbWndExtra = sizeof(Mayu *);
\r
125 wc.hInstance = g_hInst;
\r
128 wc.hbrBackground = NULL;
\r
129 wc.lpszMenuName = NULL;
\r
130 wc.lpszClassName = _T("mayuTasktray");
\r
131 return RegisterClass(&wc);
\r
135 BOOL notifyHandler(COPYDATASTRUCT *cd) {
\r
136 switch (cd->dwData) {
\r
137 case Notify::Type_setFocus:
\r
138 case Notify::Type_name: {
\r
139 NotifySetFocus *n = (NotifySetFocus *)cd->lpData;
\r
140 n->m_className[NUMBER_OF(n->m_className) - 1] = _T('\0');
\r
141 n->m_titleName[NUMBER_OF(n->m_titleName) - 1] = _T('\0');
\r
143 if (n->m_type == Notify::Type_setFocus)
\r
144 m_engine.setFocus(reinterpret_cast<HWND>(n->m_hwnd), n->m_threadId,
\r
145 n->m_className, n->m_titleName, false);
\r
148 Acquire a(&m_log, 1);
\r
149 m_log << _T("HWND:\t") << std::hex
\r
151 << std::dec << std::endl;
\r
152 m_log << _T("THREADID:") << static_cast<int>(n->m_threadId)
\r
155 Acquire a(&m_log, (n->m_type == Notify::Type_name) ? 0 : 1);
\r
156 m_log << _T("CLASS:\t") << n->m_className << std::endl;
\r
157 m_log << _T("TITLE:\t") << n->m_titleName << std::endl;
\r
160 HWND hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), &isMDI);
\r
163 getChildWindowRect(hwnd, &rc);
\r
164 m_log << _T("MDI Window Position/Size: (")
\r
165 << rc.left << _T(", ") << rc.top << _T(") / (")
\r
166 << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")
\r
168 hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), NULL);
\r
171 GetWindowRect(hwnd, &rc);
\r
172 m_log << _T("Toplevel Window Position/Size: (")
\r
173 << rc.left << _T(", ") << rc.top << _T(") / (")
\r
174 << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")
\r
177 SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);
\r
178 m_log << _T("Desktop Window Position/Size: (")
\r
179 << rc.left << _T(", ") << rc.top << _T(") / (")
\r
180 << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")
\r
183 m_log << std::endl;
\r
187 case Notify::Type_lockState: {
\r
188 NotifyLockState *n = (NotifyLockState *)cd->lpData;
\r
189 m_engine.setLockState(n->m_isNumLockToggled,
\r
190 n->m_isCapsLockToggled,
\r
191 n->m_isScrollLockToggled,
\r
192 n->m_isKanaLockToggled,
\r
193 n->m_isImeLockToggled,
\r
194 n->m_isImeCompToggled);
\r
196 Acquire a(&m_log, 0);
\r
197 if (n->m_isKanaLockToggled) {
\r
198 m_log << _T("Notify::Type_lockState Kana on : ");
\r
200 m_log << _T("Notify::Type_lockState Kana off : ");
\r
202 m_log << n->m_debugParam << ", "
\r
203 << g_hookData->m_correctKanaLockHandling << std::endl;
\r
208 case Notify::Type_sync: {
\r
209 m_engine.syncNotify();
\r
213 case Notify::Type_threadDetach: {
\r
214 NotifyThreadDetach *n = (NotifyThreadDetach *)cd->lpData;
\r
215 m_engine.threadDetachNotify(n->m_threadId);
\r
219 case Notify::Type_command: {
\r
220 NotifyCommand *n = (NotifyCommand *)cd->lpData;
\r
221 m_engine.commandNotify(n->m_hwnd, n->m_message,
\r
222 n->m_wParam, n->m_lParam);
\r
226 case Notify::Type_show: {
\r
227 NotifyShow *n = (NotifyShow *)cd->lpData;
\r
228 switch (n->m_show) {
\r
229 case NotifyShow::Show_Maximized:
\r
230 m_engine.setShow(true, false, n->m_isMDI);
\r
232 case NotifyShow::Show_Minimized:
\r
233 m_engine.setShow(false, true, n->m_isMDI);
\r
235 case NotifyShow::Show_Normal:
\r
237 m_engine.setShow(false, false, n->m_isMDI);
\r
243 case Notify::Type_log: {
\r
244 Acquire a(&m_log, 1);
\r
245 NotifyLog *n = (NotifyLog *)cd->lpData;
\r
246 m_log << _T("hook log: ") << n->m_msg << std::endl;
\r
253 /// window procedure for tasktray
\r
254 static LRESULT CALLBACK
\r
255 tasktray_wndProc(HWND i_hwnd, UINT i_message,
\r
256 WPARAM i_wParam, LPARAM i_lParam) {
\r
258 Mayu *This = reinterpret_cast<Mayu *>(GetWindowLongPtr(i_hwnd, 0));
\r
260 Mayu *This = reinterpret_cast<Mayu *>(GetWindowLong(i_hwnd, 0));
\r
264 switch (i_message) {
\r
266 This = reinterpret_cast<Mayu *>(
\r
267 reinterpret_cast<CREATESTRUCT *>(i_lParam)->lpCreateParams);
\r
269 SetWindowLongPtr(i_hwnd, 0, (LONG_PTR)This);
\r
271 SetWindowLong(i_hwnd, 0, (long)This);
\r
276 switch (i_message) {
\r
277 case WM_COPYDATA: {
\r
278 COPYDATASTRUCT *cd;
\r
279 cd = reinterpret_cast<COPYDATASTRUCT *>(i_lParam);
\r
280 return This->notifyHandler(cd);
\r
282 case WM_QUERYENDSESSION:
\r
283 This->m_engine.prepairQuit();
\r
284 PostQuitMessage(0);
\r
287 #ifndef WM_WTSSESSION_CHANGE // WinUser.h
\r
288 # define WM_WTSSESSION_CHANGE 0x02B1
\r
290 case WM_WTSSESSION_CHANGE: {
\r
291 const char *m = "";
\r
292 switch (i_wParam) {
\r
293 #ifndef WTS_CONSOLE_CONNECT // WinUser.h
\r
294 # define WTS_CONSOLE_CONNECT 0x1
\r
295 # define WTS_CONSOLE_DISCONNECT 0x2
\r
296 # define WTS_REMOTE_CONNECT 0x3
\r
297 # define WTS_REMOTE_DISCONNECT 0x4
\r
298 # define WTS_SESSION_LOGON 0x5
\r
299 # define WTS_SESSION_LOGOFF 0x6
\r
300 # define WTS_SESSION_LOCK 0x7
\r
301 # define WTS_SESSION_UNLOCK 0x8
\r
303 case WTS_CONSOLE_CONNECT:
\r
304 m = "WTS_CONSOLE_CONNECT";
\r
305 if (!This->m_engine.resume()) {
\r
306 This->m_engine.prepairQuit();
\r
307 PostQuitMessage(0);
\r
310 case WTS_CONSOLE_DISCONNECT:
\r
311 m = "WTS_CONSOLE_DISCONNECT";
\r
312 This->m_engine.pause();
\r
314 case WTS_REMOTE_CONNECT:
\r
315 m = "WTS_REMOTE_CONNECT";
\r
317 case WTS_REMOTE_DISCONNECT:
\r
318 m = "WTS_REMOTE_DISCONNECT";
\r
320 case WTS_SESSION_LOGON:
\r
321 m = "WTS_SESSION_LOGON";
\r
323 case WTS_SESSION_LOGOFF:
\r
324 m = "WTS_SESSION_LOGOFF";
\r
326 case WTS_SESSION_LOCK:
\r
327 m = "WTS_SESSION_LOCK";
\r
329 case WTS_SESSION_UNLOCK:
\r
330 m = "WTS_SESSION_UNLOCK";
\r
332 //case WTS_SESSION_REMOTE_CONTROL: m = "WTS_SESSION_REMOTE_CONTROL"; break;
\r
334 This->m_log << _T("WM_WTSESSION_CHANGE(")
\r
335 << i_wParam << ", " << i_lParam << "): "
\r
339 case WM_APP_msgStreamNotify: {
\r
340 tomsgstream::StreamBuf *log =
\r
341 reinterpret_cast<tomsgstream::StreamBuf *>(i_lParam);
\r
342 const tstring &str = log->acquireString();
\r
344 This->m_logFile << str << std::flush;
\r
345 #endif // LOG_TO_FILE
\r
346 editInsertTextAtLast(GetDlgItem(This->m_hwndLog, IDC_EDIT_log),
\r
348 log->releaseString();
\r
352 case WM_APP_taskTrayNotify: {
\r
353 if (i_wParam == ID_TaskTrayIcon)
\r
354 switch (i_lParam) {
\r
355 case WM_RBUTTONUP: {
\r
357 CHECK_TRUE( GetCursorPos(&p) );
\r
358 SetForegroundWindow(i_hwnd);
\r
359 HMENU hMenuSub = GetSubMenu(This->m_hMenuTaskTray, 0);
\r
360 if (This->m_engine.getIsEnabled())
\r
361 CheckMenuItem(hMenuSub, ID_MENUITEM_disable,
\r
362 MF_UNCHECKED | MF_BYCOMMAND);
\r
364 CheckMenuItem(hMenuSub, ID_MENUITEM_disable,
\r
365 MF_CHECKED | MF_BYCOMMAND);
\r
366 CHECK_TRUE( SetMenuDefaultItem(hMenuSub,
\r
367 ID_MENUITEM_investigate, FALSE) );
\r
369 // create reload menu
\r
370 HMENU hMenuSubSub = GetSubMenu(hMenuSub, 1);
\r
371 Registry reg(MAYU_REGISTRY_ROOT);
\r
373 reg.read(_T(".mayuIndex"), &mayuIndex, 0);
\r
374 while (DeleteMenu(hMenuSubSub, 0, MF_BYPOSITION))
\r
376 tregex getName(_T("^([^;]*);"));
\r
377 for (int index = 0; ; index ++) {
\r
379 _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);
\r
381 if (!reg.read(buf, &dot_mayu))
\r
384 if (boost::regex_search(dot_mayu, what, getName)) {
\r
386 std::memset(&mii, 0, sizeof(mii));
\r
387 mii.cbSize = sizeof(mii);
\r
388 mii.fMask = MIIM_ID | MIIM_STATE | MIIM_TYPE;
\r
389 mii.fType = MFT_STRING;
\r
391 MFS_ENABLED | ((mayuIndex == index) ? MFS_CHECKED : 0);
\r
392 mii.wID = ID_MENUITEM_reloadBegin + index;
\r
393 tstringi name(what.str(1));
\r
394 mii.dwTypeData = const_cast<_TCHAR *>(name.c_str());
\r
395 mii.cch = name.size();
\r
397 InsertMenuItem(hMenuSubSub, index, TRUE, &mii);
\r
402 TrackPopupMenu(hMenuSub, TPM_LEFTALIGN,
\r
403 p.x, p.y, 0, i_hwnd, NULL);
\r
404 // TrackPopupMenu may fail (ERROR_POPUP_ALREADY_ACTIVE)
\r
408 case WM_LBUTTONDBLCLK:
\r
409 SendMessage(i_hwnd, WM_COMMAND,
\r
410 MAKELONG(ID_MENUITEM_investigate, 0), 0);
\r
417 int notify_code = HIWORD(i_wParam);
\r
418 int id = LOWORD(i_wParam);
\r
419 if (notify_code == 0) // menu
\r
422 if (ID_MENUITEM_reloadBegin <= id) {
\r
423 Registry reg(MAYU_REGISTRY_ROOT);
\r
424 reg.write(_T(".mayuIndex"), id - ID_MENUITEM_reloadBegin);
\r
428 case ID_MENUITEM_reload:
\r
431 case ID_MENUITEM_investigate: {
\r
432 ShowWindow(This->m_hwndLog, SW_SHOW);
\r
433 ShowWindow(This->m_hwndInvestigate, SW_SHOW);
\r
436 GetWindowRect(This->m_hwndInvestigate, &rc1);
\r
437 GetWindowRect(This->m_hwndLog, &rc2);
\r
439 MoveWindow(This->m_hwndLog, rc1.left, rc1.bottom,
\r
440 rcWidth(&rc1), rcHeight(&rc2), TRUE);
\r
442 SetForegroundWindow(This->m_hwndLog);
\r
443 SetForegroundWindow(This->m_hwndInvestigate);
\r
446 case ID_MENUITEM_setting:
\r
447 if (!This->m_isSettingDialogOpened) {
\r
448 This->m_isSettingDialogOpened = true;
\r
449 if (DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_setting),
\r
450 NULL, dlgSetting_dlgProc))
\r
452 This->m_isSettingDialogOpened = false;
\r
455 case ID_MENUITEM_log:
\r
456 ShowWindow(This->m_hwndLog, SW_SHOW);
\r
457 SetForegroundWindow(This->m_hwndLog);
\r
459 case ID_MENUITEM_check: {
\r
462 ret = GetKeyboardState(keys);
\r
464 This->m_log << _T("Check Keystate Failed(%d)")
\r
465 << GetLastError() << std::endl;
\r
467 This->m_log << _T("Check Keystate: ") << std::endl;
\r
468 for (int i = 0; i < 0xff; i++) {
\r
470 asyncKey = GetAsyncKeyState(i);
\r
471 This->m_log << std::hex;
\r
472 if (asyncKey & 0x8000) {
\r
473 This->m_log << _T(" ") << VK2TCHAR[i]
\r
474 << _T("(0x") << i << _T("): pressed!")
\r
477 if (i == 0x14 || // VK_CAPTITAL
\r
478 i == 0x15 || // VK_KANA
\r
479 i == 0x19 || // VK_KANJI
\r
480 i == 0x90 || // VK_NUMLOCK
\r
481 i == 0x91 // VK_SCROLL
\r
484 This->m_log << _T(" ") << VK2TCHAR[i]
\r
485 << _T("(0x") << i << _T("): locked!")
\r
489 This->m_log << std::dec;
\r
491 This->m_log << std::endl;
\r
495 case ID_MENUITEM_version:
\r
496 ShowWindow(This->m_hwndVersion, SW_SHOW);
\r
497 SetForegroundWindow(This->m_hwndVersion);
\r
499 case ID_MENUITEM_help: {
\r
500 _TCHAR buf[GANA_MAX_PATH];
\r
501 CHECK_TRUE( GetModuleFileName(g_hInst, buf, NUMBER_OF(buf)) );
\r
502 tstringi helpFilename = pathRemoveFileSpec(buf);
\r
503 helpFilename += _T("\\");
\r
504 helpFilename += loadString(IDS_helpFilename);
\r
505 ShellExecute(NULL, _T("open"), helpFilename.c_str(),
\r
506 NULL, NULL, SW_SHOWNORMAL);
\r
509 case ID_MENUITEM_disable:
\r
510 This->m_engine.enable(!This->m_engine.getIsEnabled());
\r
511 This->showTasktrayIcon();
\r
513 case ID_MENUITEM_quit:
\r
514 This->m_engine.prepairQuit();
\r
515 PostQuitMessage(0);
\r
521 case WM_APP_engineNotify: {
\r
522 switch (i_wParam) {
\r
523 case EngineNotify_shellExecute:
\r
524 This->m_engine.shellExecute();
\r
526 case EngineNotify_loadSetting:
\r
529 case EngineNotify_helpMessage:
\r
530 This->showHelpMessage(false);
\r
532 This->showHelpMessage(true);
\r
534 case EngineNotify_showDlg: {
\r
535 // show investigate/log window
\r
536 int sw = (i_lParam & ~MayuDialogType_mask);
\r
538 switch (static_cast<MayuDialogType>(
\r
539 i_lParam & MayuDialogType_mask)) {
\r
540 case MayuDialogType_investigate:
\r
541 hwnd = This->m_hwndInvestigate;
\r
543 case MayuDialogType_log:
\r
544 hwnd = This->m_hwndLog;
\r
548 ShowWindow(hwnd, sw);
\r
550 case SW_SHOWNORMAL:
\r
551 case SW_SHOWMAXIMIZED:
\r
554 case SW_SHOWDEFAULT:
\r
555 SetForegroundWindow(hwnd);
\r
561 case EngineNotify_setForegroundWindow:
\r
562 // FIXME: completely useless. why ?
\r
563 setForegroundWindow(reinterpret_cast<HWND>(i_lParam));
\r
565 Acquire a(&This->m_log, 1);
\r
566 This->m_log << _T("setForegroundWindow(0x")
\r
567 << std::hex << i_lParam << std::dec << _T(")")
\r
571 case EngineNotify_clearLog:
\r
572 SendMessage(This->m_hwndLog, WM_COMMAND,
\r
573 MAKELONG(IDC_BUTTON_clearLog, 0), 0);
\r
581 case WM_APP_dlglogNotify: {
\r
582 switch (i_wParam) {
\r
583 case DlgLogNotify_logCleared:
\r
584 This->showBanner(true);
\r
593 if (This->m_usingSN) {
\r
594 wtsUnRegisterSessionNotification(i_hwnd);
\r
595 This->m_usingSN = false;
\r
600 if (i_message == This->m_WM_TaskbarRestart) {
\r
601 if (This->showTasktrayIcon(true)) {
\r
602 Acquire a(&This->m_log, 0);
\r
603 This->m_log << _T("Tasktray icon is updated.") << std::endl;
\r
605 Acquire a(&This->m_log, 1);
\r
606 This->m_log << _T("Tasktray icon already exists.") << std::endl;
\r
609 } else if (i_message == This->m_WM_MayuIPC) {
\r
610 switch (static_cast<MayuIPCCommand>(i_wParam)) {
\r
611 case MayuIPCCommand_Enable:
\r
612 This->m_engine.enable(!!i_lParam);
\r
613 This->showTasktrayIcon();
\r
615 Acquire a(&This->m_log, 1);
\r
616 This->m_log << _T("Enabled by another application.")
\r
619 Acquire a(&This->m_log, 1);
\r
620 This->m_log << _T("Disabled by another application.")
\r
627 return DefWindowProc(i_hwnd, i_message, i_wParam, i_lParam);
\r
632 Setting *newSetting = new Setting;
\r
635 for (int i = 1; i < __argc; ++ i) {
\r
636 if (__targv[i][0] == _T('-') && __targv[i][1] == _T('D'))
\r
637 newSetting->m_symbols.insert(__targv[i] + 2);
\r
640 if (!SettingLoader(&m_log, &m_log).load(newSetting)) {
\r
641 ShowWindow(m_hwndLog, SW_SHOW);
\r
642 SetForegroundWindow(m_hwndLog);
\r
644 Acquire a(&m_log, 0);
\r
645 m_log << _T("error: failed to load.") << std::endl;
\r
648 m_log << _T("successfully loaded.") << std::endl;
\r
649 while (!m_engine.setSetting(newSetting))
\r
652 m_setting = newSetting;
\r
655 // show message (a baloon from the task tray icon)
\r
656 void showHelpMessage(bool i_doesShow = true) {
\r
657 if (m_canUseTasktrayBaloon) {
\r
659 tstring helpMessage, helpTitle;
\r
660 m_engine.getHelpMessages(&helpMessage, &helpTitle);
\r
661 tcslcpy(m_ni.szInfo, helpMessage.c_str(), NUMBER_OF(m_ni.szInfo));
\r
662 tcslcpy(m_ni.szInfoTitle, helpTitle.c_str(),
\r
663 NUMBER_OF(m_ni.szInfoTitle));
\r
664 m_ni.dwInfoFlags = NIIF_INFO;
\r
666 m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');
\r
667 CHECK_TRUE( Shell_NotifyIcon(NIM_MODIFY, &m_ni) );
\r
671 // change the task tray icon
\r
672 bool showTasktrayIcon(bool i_doesAdd = false) {
\r
673 m_ni.hIcon = m_tasktrayIcon[m_engine.getIsEnabled() ? 1 : 0];
\r
674 m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');
\r
676 // http://support.microsoft.com/kb/418138/JA/
\r
678 for (; !Shell_NotifyIcon(NIM_ADD, &m_ni) && 0 < guard; -- guard) {
\r
679 if (Shell_NotifyIcon(NIM_MODIFY, &m_ni)) {
\r
682 Sleep(1000); // 1sec
\r
686 return !!Shell_NotifyIcon(NIM_MODIFY, &m_ni);
\r
690 void showBanner(bool i_isCleared) {
\r
694 _TCHAR starttimebuf[1024];
\r
695 _TCHAR timebuf[1024];
\r
697 #ifdef __BORLANDC__
\r
698 #pragma message("\t\t****\tAfter std::ostream() is called, ")
\r
699 #pragma message("\t\t****\tstrftime(... \"%%#c\" ...) fails.")
\r
700 #pragma message("\t\t****\tWhy ? Bug of Borland C++ 5.5.1 ? ")
\r
701 #pragma message("\t\t****\t - nayuta")
\r
702 _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%Y/%m/%d %H:%M:%S"),
\r
704 _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%Y/%m/%d %H:%M:%S"),
\r
705 localtime(&m_startTime));
\r
707 _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%#c"), localtime(&now));
\r
708 _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%#c"),
\r
709 localtime(&m_startTime));
\r
712 Acquire a(&m_log, 0);
\r
713 m_log << _T("------------------------------------------------------------") << std::endl;
\r
714 m_log << loadString(IDS_mayu) << _T(" ") _T(VERSION);
\r
716 m_log << _T(" (DEBUG)");
\r
719 m_log << _T(" (UNICODE)");
\r
721 m_log << std::endl;
\r
722 m_log << _T(" built by ")
\r
723 << _T(LOGNAME) << _T("@") << toLower(_T(COMPUTERNAME))
\r
724 << _T(" (") << _T(__DATE__) << _T(" ")
\r
725 << _T(__TIME__) << _T(", ")
\r
726 << getCompilerVersionString() << _T(")") << std::endl;
\r
727 _TCHAR modulebuf[1024];
\r
728 CHECK_TRUE( GetModuleFileName(g_hInst, modulebuf,
\r
729 NUMBER_OF(modulebuf)) );
\r
730 m_log << _T("started at ") << starttimebuf << std::endl;
\r
731 m_log << modulebuf << std::endl;
\r
732 m_log << _T("------------------------------------------------------------") << std::endl;
\r
735 m_log << _T("log was cleared at ") << timebuf << std::endl;
\r
737 m_log << _T("log begins at ") << timebuf << std::endl;
\r
743 Mayu(HANDLE i_mutex)
\r
744 : m_hwndTaskTray(NULL),
\r
747 m_WM_TaskbarRestart(RegisterWindowMessage(_T("TaskbarCreated"))),
\r
748 m_WM_MayuIPC(RegisterWindowMessage(WM_MayuIPC_NAME)),
\r
749 m_canUseTasktrayBaloon(
\r
750 PACKVERSION(5, 0) <= getDllVersion(_T("shlwapi.dll"))),
\r
751 m_log(WM_APP_msgStreamNotify),
\r
753 m_isSettingDialogOpened(false),
\r
755 #ifdef USE_MAILSLOT
\r
756 m_hNotifyMailslot = CreateMailslot(NOTIFY_MAILSLOT_NAME, 0, MAILSLOT_WAIT_FOREVER, (SECURITY_ATTRIBUTES *)NULL);
\r
757 ASSERT(m_hNotifyMailslot != INVALID_HANDLE_VALUE);
\r
758 m_hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
\r
759 ASSERT(m_hNotifyEvent);
\r
760 m_olNotify.Offset = 0;
\r
761 m_olNotify.OffsetHigh = 0;
\r
762 m_olNotify.hEvent = m_hNotifyEvent;
\r
763 #endif // USE_MAILSLOT
\r
764 time(&m_startTime);
\r
766 CHECK_TRUE( Register_focus() );
\r
767 CHECK_TRUE( Register_target() );
\r
768 CHECK_TRUE( Register_tasktray() );
\r
772 HomeDirectories pathes;
\r
773 getHomeDirectories(&pathes);
\r
774 for (HomeDirectories::iterator i = pathes.begin(); i != pathes.end(); ++ i)
\r
775 if (SetCurrentDirectory(i->c_str()))
\r
779 // create windows, dialogs
\r
780 tstringi title = loadString(IDS_mayu);
\r
781 m_hwndTaskTray = CreateWindow(_T("mayuTasktray"), title.c_str(),
\r
782 WS_OVERLAPPEDWINDOW,
\r
783 CW_USEDEFAULT, CW_USEDEFAULT,
\r
784 CW_USEDEFAULT, CW_USEDEFAULT,
\r
785 NULL, NULL, g_hInst, this);
\r
786 CHECK_TRUE( m_hwndTaskTray );
\r
788 // set window handle of tasktray to hooks
\r
789 #ifndef USE_MAILSLOT
\r
790 g_hookData->m_hwndTaskTray = reinterpret_cast<DWORD>(m_hwndTaskTray);
\r
791 #endif // !USE_MAILSLOT
\r
792 CHECK_FALSE( installHooks(Engine::keyboardDetour, &m_engine) );
\r
793 m_usingSN = wtsRegisterSessionNotification(m_hwndTaskTray,
\r
794 NOTIFY_FOR_THIS_SESSION);
\r
797 dld.m_log = &m_log;
\r
798 dld.m_hwndTaskTray = m_hwndTaskTray;
\r
800 CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_log), NULL,
\r
801 dlgLog_dlgProc, (LPARAM)&dld);
\r
802 CHECK_TRUE( m_hwndLog );
\r
804 DlgInvestigateData did;
\r
805 did.m_engine = &m_engine;
\r
806 did.m_hwndLog = m_hwndLog;
\r
807 m_hwndInvestigate =
\r
808 CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_investigate), NULL,
\r
809 dlgInvestigate_dlgProc, (LPARAM)&did);
\r
810 CHECK_TRUE( m_hwndInvestigate );
\r
813 CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_version),
\r
814 NULL, dlgVersion_dlgProc,
\r
815 (LPARAM)m_engine.getMayudVersion().c_str());
\r
816 CHECK_TRUE( m_hwndVersion );
\r
821 _TCHAR exePath[GANA_MAX_PATH];
\r
822 _TCHAR exeDrive[GANA_MAX_PATH];
\r
823 _TCHAR exeDir[GANA_MAX_PATH];
\r
824 GetModuleFileName(NULL, exePath, GANA_MAX_PATH);
\r
825 _tsplitpath_s(exePath, exeDrive, GANA_MAX_PATH, exeDir, GANA_MAX_PATH, NULL, 0, NULL, 0);
\r
828 path += _T("mayu.log");
\r
829 m_logFile.open(path.c_str(), std::ios::app);
\r
830 m_logFile.imbue(std::locale("japanese"));
\r
831 #endif // LOG_TO_FILE
\r
832 SendMessage(GetDlgItem(m_hwndLog, IDC_EDIT_log), EM_SETLIMITTEXT, 0, 0);
\r
833 m_log.attach(m_hwndTaskTray);
\r
835 // start keyboard handler thread
\r
836 m_engine.setAssociatedWndow(m_hwndTaskTray);
\r
839 // show tasktray icon
\r
840 m_tasktrayIcon[0] = loadSmallIcon(IDI_ICON_mayu_disabled);
\r
841 m_tasktrayIcon[1] = loadSmallIcon(IDI_ICON_mayu);
\r
842 std::memset(&m_ni, 0, sizeof(m_ni));
\r
843 m_ni.uID = ID_TaskTrayIcon;
\r
844 m_ni.hWnd = m_hwndTaskTray;
\r
845 m_ni.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
\r
846 m_ni.hIcon = m_tasktrayIcon[1];
\r
847 m_ni.uCallbackMessage = WM_APP_taskTrayNotify;
\r
848 tstring tip = loadString(IDS_mayu);
\r
849 tcslcpy(m_ni.szTip, tip.c_str(), NUMBER_OF(m_ni.szTip));
\r
850 if (m_canUseTasktrayBaloon) {
\r
851 m_ni.cbSize = sizeof(m_ni);
\r
852 m_ni.uFlags |= NIF_INFO;
\r
854 m_ni.cbSize = NOTIFYICONDATA_V1_SIZE;
\r
855 showTasktrayIcon(true);
\r
858 m_hMenuTaskTray = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU_tasktray));
\r
859 ASSERT(m_hMenuTaskTray);
\r
861 // set initial lock state
\r
866 ZeroMemory(&m_pi,sizeof(m_pi));
\r
867 ZeroMemory(&m_si,sizeof(m_si));
\r
868 m_si.cb=sizeof(m_si);
\r
870 result = CreateProcess(_T("yamyd32"), _T("yamyd32"), NULL, NULL, FALSE,
\r
871 NORMAL_PRIORITY_CLASS, 0, NULL, &m_si, &m_pi);
\r
872 if (result == FALSE) {
\r
877 LoadString(GetModuleHandle(NULL), IDS_cannotInvoke,
\r
878 text, sizeof(text)/sizeof(text[0]));
\r
879 LoadString(GetModuleHandle(NULL), IDS_mayu,
\r
880 title, sizeof(title)/sizeof(title[0]));
\r
881 _stprintf_s(buf, sizeof(buf)/sizeof(buf[0]),
\r
882 text, _T("yamyd32"), GetLastError());
\r
883 MessageBox((HWND)NULL, buf, title, MB_OK | MB_ICONSTOP);
\r
885 CloseHandle(m_pi.hThread);
\r
886 CloseHandle(m_pi.hProcess);
\r
893 ReleaseMutex(m_mutex);
\r
894 WaitForSingleObject(m_mutex, INFINITE);
\r
895 // first, detach log from edit control to avoid deadlock
\r
899 #endif // LOG_TO_FILE
\r
901 // stop notify from mayu.dll
\r
902 g_hookData->m_hwndTaskTray = NULL;
\r
903 CHECK_FALSE( uninstallHooks() );
\r
904 PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);
\r
907 CHECK_TRUE( DestroyWindow(m_hwndVersion) );
\r
908 CHECK_TRUE( DestroyWindow(m_hwndInvestigate) );
\r
909 CHECK_TRUE( DestroyWindow(m_hwndLog) );
\r
910 CHECK_TRUE( DestroyWindow(m_hwndTaskTray) );
\r
913 DestroyMenu(m_hMenuTaskTray);
\r
915 // delete tasktray icon
\r
916 CHECK_TRUE( Shell_NotifyIcon(NIM_DELETE, &m_ni) );
\r
917 CHECK_TRUE( DestroyIcon(m_tasktrayIcon[1]) );
\r
918 CHECK_TRUE( DestroyIcon(m_tasktrayIcon[0]) );
\r
920 // stop keyboard handler thread
\r
926 #ifdef USE_MAILSLOT
\r
927 CloseHandle(m_hNotifyEvent);
\r
928 CloseHandle(m_hNotifyMailslot);
\r
929 #endif // USE_MAILSLOT
\r
933 WPARAM messageLoop() {
\r
937 #ifdef USE_MAILSLOT
\r
938 mailslotHandler(0, 0);
\r
940 HANDLE handles[] = { m_hNotifyEvent };
\r
942 switch (ret = MsgWaitForMultipleObjectsEx(NUMBER_OF(handles), &handles[0],
\r
943 INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE)) {
\r
944 case WAIT_OBJECT_0: // m_hNotifyEvent
\r
947 case WAIT_OBJECT_0 + NUMBER_OF(handles): {
\r
949 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
\r
950 if (msg.message == WM_QUIT) {
\r
953 if (IsDialogMessage(m_hwndLog, &msg))
\r
955 if (IsDialogMessage(m_hwndInvestigate, &msg))
\r
957 if (IsDialogMessage(m_hwndVersion, &msg))
\r
959 TranslateMessage(&msg);
\r
960 DispatchMessage(&msg);
\r
966 case WAIT_IO_COMPLETION:
\r
974 #else // !USE_MAILSLOT
\r
976 while (0 < GetMessage(&msg, NULL, 0, 0)) {
\r
977 if (IsDialogMessage(m_hwndLog, &msg))
\r
979 if (IsDialogMessage(m_hwndInvestigate, &msg))
\r
981 if (IsDialogMessage(m_hwndVersion, &msg))
\r
983 TranslateMessage(&msg);
\r
984 DispatchMessage(&msg);
\r
987 #endif // !USE_MAILSLOT
\r
992 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
996 /// convert registry
\r
997 void convertRegistry()
\r
999 Registry reg(MAYU_REGISTRY_ROOT);
\r
1000 tstringi dot_mayu;
\r
1001 bool doesAdd = false;
\r
1003 if (reg.read(_T(".mayu"), &dot_mayu)) {
\r
1004 reg.write(_T(".mayu0"), _T(";") + dot_mayu + _T(";"));
\r
1005 reg.remove(_T(".mayu"));
\r
1008 } else if (!reg.read(_T(".mayu0"), &dot_mayu)) {
\r
1009 reg.write(_T(".mayu0"), loadString(IDS_readFromHomeDirectory) + _T(";;"));
\r
1014 Registry commonreg(HKEY_LOCAL_MACHINE, _T("Software\\GANAware\\mayu"));
\r
1015 tstringi dir, layout;
\r
1016 if (commonreg.read(_T("dir"), &dir) &&
\r
1017 commonreg.read(_T("layout"), &layout)) {
\r
1018 tstringi tmp = _T(";") + dir + _T("\\dot.mayu");
\r
1019 if (layout == _T("109")) {
\r
1020 reg.write(_T(".mayu1"), loadString(IDS_109Emacs) + tmp
\r
1021 + _T(";-DUSE109") _T(";-DUSEdefault"));
\r
1022 reg.write(_T(".mayu2"), loadString(IDS_104on109Emacs) + tmp
\r
1023 + _T(";-DUSE109") _T(";-DUSEdefault") _T(";-DUSE104on109"));
\r
1024 reg.write(_T(".mayu3"), loadString(IDS_109) + tmp
\r
1025 + _T(";-DUSE109"));
\r
1026 reg.write(_T(".mayu4"), loadString(IDS_104on109) + tmp
\r
1027 + _T(";-DUSE109") _T(";-DUSE104on109"));
\r
1029 reg.write(_T(".mayu1"), loadString(IDS_104Emacs) + tmp
\r
1030 + _T(";-DUSE104") _T(";-DUSEdefault"));
\r
1031 reg.write(_T(".mayu2"), loadString(IDS_109on104Emacs) + tmp
\r
1032 + _T(";-DUSE104") _T(";-DUSEdefault") _T(";-DUSE109on104"));
\r
1033 reg.write(_T(".mayu3"), loadString(IDS_104) + tmp
\r
1034 + _T(";-DUSE104"));
\r
1035 reg.write(_T(".mayu4"), loadString(IDS_109on104) + tmp
\r
1036 + _T(";-DUSE104") _T(";-DUSE109on104"));
\r
1038 reg.write(_T(".mayuIndex"), index);
\r
1045 int WINAPI _tWinMain(HINSTANCE i_hInstance, HINSTANCE /* i_hPrevInstance */,
\r
1046 LPTSTR /* i_lpszCmdLine */, int /* i_nCmdShow */)
\r
1048 g_hInst = i_hInstance;
\r
1051 CHECK_TRUE( _tsetlocale(LC_ALL, _T("")) );
\r
1053 // common controls
\r
1054 #if defined(_WIN95)
\r
1055 InitCommonControls();
\r
1057 INITCOMMONCONTROLSEX icc;
\r
1058 icc.dwSize = sizeof(icc);
\r
1059 icc.dwICC = ICC_LISTVIEW_CLASSES;
\r
1060 CHECK_TRUE( InitCommonControlsEx(&icc) );
\r
1063 // convert old registry to new registry
\r
1065 convertRegistry();
\r
1066 #endif // !USE_INI
\r
1068 // is another mayu running ?
\r
1069 HANDLE mutex = CreateMutex((SECURITY_ATTRIBUTES *)NULL, TRUE,
\r
1070 MUTEX_MAYU_EXCLUSIVE_RUNNING);
\r
1071 if (GetLastError() == ERROR_ALREADY_EXISTS) {
\r
1072 // another mayu already running
\r
1073 tstring text = loadString(IDS_mayuAlreadyExists);
\r
1074 tstring title = loadString(IDS_mayu);
\r
1076 UINT WM_TaskbarRestart = RegisterWindowMessage(_T("TaskbarCreated"));
\r
1077 PostMessage(reinterpret_cast<HWND>(g_hookData->m_hwndTaskTray),
\r
1078 WM_TaskbarRestart, 0, 0);
\r
1080 MessageBox((HWND)NULL, text.c_str(), title.c_str(), MB_OK | MB_ICONSTOP);
\r
1084 // check remote desktop
\r
1086 if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId) ||
\r
1087 wtsGetActiveConsoleSessionId() != sessionId) {
\r
1088 tstring text = loadString(IDS_executedInRemoteDesktop);
\r
1089 tstring title = loadString(IDS_mayu);
\r
1090 MessageBox((HWND)NULL, text.c_str(), title.c_str(), MB_OK | MB_ICONSTOP);
\r
1095 Mayu(mutex).messageLoop();
\r
1096 } catch (ErrorMessage &i_e) {
\r
1097 tstring title = loadString(IDS_mayu);
\r
1098 MessageBox((HWND)NULL, i_e.getMessage().c_str(), title.c_str(),
\r
1099 MB_OK | MB_ICONSTOP);
\r
1102 CHECK_TRUE( CloseHandle(mutex) );
\r