OSDN Git Service

invoke yamy{64,32} and yamyd32 from same directory of yamy.exe instead of current...
[yamy/yamy.git] / mayu.cpp
index 12e2fb9..f83f19e 100644 (file)
--- a/mayu.cpp
+++ b/mayu.cpp
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// 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