OSDN Git Service

change indent rule to hard tab with width 4 to adjust to default setting of VC++...
[yamy/yamy.git] / mayu.cpp
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2 // mayu.cpp\r
3 \r
4 \r
5 #define APSTUDIO_INVOKED\r
6 \r
7 #include "misc.h"\r
8 #include "compiler_specific_func.h"\r
9 #include "dlginvestigate.h"\r
10 #include "dlglog.h"\r
11 #include "dlgsetting.h"\r
12 #include "dlgversion.h"\r
13 #include "engine.h"\r
14 #include "errormessage.h"\r
15 #include "focus.h"\r
16 #include "function.h"\r
17 #include "hook.h"\r
18 #include "mayu.h"\r
19 #include "mayuipc.h"\r
20 #include "mayurc.h"\r
21 #include "msgstream.h"\r
22 #include "multithread.h"\r
23 #include "registry.h"\r
24 #include "setting.h"\r
25 #include "target.h"\r
26 #include "windowstool.h"\r
27 #include "vk2tchar.h"\r
28 #include <process.h>\r
29 #include <time.h>\r
30 #include <commctrl.h>\r
31 #include <wtsapi32.h>\r
32 \r
33 \r
34 ///\r
35 #define ID_MENUITEM_reloadBegin _APS_NEXT_COMMAND_VALUE\r
36 \r
37 \r
38 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
39 // Mayu\r
40 \r
41 \r
42 ///\r
43 class Mayu\r
44 {\r
45         HWND m_hwndTaskTray;                            /// tasktray window\r
46         HWND m_hwndLog;                         /// log dialog\r
47         HWND m_hwndInvestigate;                 /// investigate dialog\r
48         HWND m_hwndVersion;                             /// version dialog\r
49 \r
50         UINT m_WM_TaskbarRestart;                       /** window message sent when\r
51                                                     taskber restarts */\r
52         UINT m_WM_MayuIPC;                              /** IPC message sent from\r
53                                                     other applications */\r
54         NOTIFYICONDATA m_ni;                            /// taskbar icon data\r
55         HICON m_tasktrayIcon[2];                        /// taskbar icon\r
56         bool m_canUseTasktrayBaloon;                    ///\r
57 \r
58         tomsgstream m_log;                              /** log stream (output to log\r
59                                                     dialog's edit) */\r
60 #ifdef LOG_TO_FILE\r
61         tofstream m_logFile;\r
62 #endif // LOG_TO_FILE\r
63 \r
64         HMENU m_hMenuTaskTray;                  /// tasktray menu\r
65         STARTUPINFO m_si;\r
66         PROCESS_INFORMATION m_pi;\r
67         HANDLE m_mutex;\r
68 #ifdef USE_MAILSLOT\r
69         HANDLE m_hNotifyMailslot;                       /// mailslot to receive notify\r
70         HANDLE m_hNotifyEvent;                  /// event on receive notify\r
71         OVERLAPPED m_olNotify;                  ///\r
72         BYTE m_notifyBuf[NOTIFY_MESSAGE_SIZE];\r
73 #endif // USE_MAILSLOT\r
74 \r
75         Setting *m_setting;                             /// current setting\r
76         bool m_isSettingDialogOpened;                   /// is setting dialog opened ?\r
77 \r
78         Engine m_engine;                                /// engine\r
79 \r
80         bool m_usingSN;            /// using WTSRegisterSessionNotification() ?\r
81         time_t m_startTime;                             /// mayu started at ...\r
82 \r
83         enum {\r
84                 WM_APP_taskTrayNotify = WM_APP + 101,   ///\r
85                 WM_APP_msgStreamNotify = WM_APP + 102,  ///\r
86                 ID_TaskTrayIcon = 1,                    ///\r
87         };\r
88 \r
89 private:\r
90 #ifdef USE_MAILSLOT\r
91         static VOID CALLBACK mailslotProc(DWORD i_code, DWORD i_len, LPOVERLAPPED i_ol) {\r
92                 Mayu *pThis;\r
93 \r
94                 pThis = reinterpret_cast<Mayu*>(CONTAINING_RECORD(i_ol, Mayu, m_olNotify));\r
95                 pThis->mailslotHandler(i_code, i_len);\r
96                 return;\r
97         }\r
98 \r
99         BOOL mailslotHandler(DWORD i_code, DWORD i_len) {\r
100                 BOOL result;\r
101 \r
102                 if (i_len) {\r
103                         COPYDATASTRUCT cd;\r
104 \r
105                         cd.dwData = reinterpret_cast<Notify *>(m_notifyBuf)->m_type;\r
106                         cd.cbData = i_len;\r
107                         cd.lpData = m_notifyBuf;\r
108                         notifyHandler(&cd);\r
109                 }\r
110 \r
111                 memset(m_notifyBuf, 0, sizeof(m_notifyBuf));\r
112                 result = ReadFileEx(m_hNotifyMailslot, m_notifyBuf, sizeof(m_notifyBuf),\r
113                                                         &m_olNotify, Mayu::mailslotProc);\r
114                 return result;\r
115         }\r
116 #endif // USE_MAILSLOT\r
117 \r
118         /// register class for tasktray\r
119         ATOM Register_tasktray() {\r
120                 WNDCLASS wc;\r
121                 wc.style         = 0;\r
122                 wc.lpfnWndProc   = tasktray_wndProc;\r
123                 wc.cbClsExtra    = 0;\r
124                 wc.cbWndExtra    = sizeof(Mayu *);\r
125                 wc.hInstance     = g_hInst;\r
126                 wc.hIcon         = NULL;\r
127                 wc.hCursor       = NULL;\r
128                 wc.hbrBackground = NULL;\r
129                 wc.lpszMenuName  = NULL;\r
130                 wc.lpszClassName = _T("mayuTasktray");\r
131                 return RegisterClass(&wc);\r
132         }\r
133 \r
134         /// notify handler\r
135         BOOL notifyHandler(COPYDATASTRUCT *cd) {\r
136                 switch (cd->dwData) {\r
137                 case Notify::Type_setFocus:\r
138                 case Notify::Type_name: {\r
139                         NotifySetFocus *n = (NotifySetFocus *)cd->lpData;\r
140                         n->m_className[NUMBER_OF(n->m_className) - 1] = _T('\0');\r
141                         n->m_titleName[NUMBER_OF(n->m_titleName) - 1] = _T('\0');\r
142 \r
143                         if (n->m_type == Notify::Type_setFocus)\r
144                                 m_engine.setFocus(reinterpret_cast<HWND>(n->m_hwnd), n->m_threadId,\r
145                                                                   n->m_className, n->m_titleName, false);\r
146 \r
147                         {\r
148                                 Acquire a(&m_log, 1);\r
149                                 m_log << _T("HWND:\t") << std::hex\r
150                                 << n->m_hwnd\r
151                                 << std::dec << std::endl;\r
152                                 m_log << _T("THREADID:") << static_cast<int>(n->m_threadId)\r
153                                 << std::endl;\r
154                         }\r
155                         Acquire a(&m_log, (n->m_type == Notify::Type_name) ? 0 : 1);\r
156                         m_log << _T("CLASS:\t") << n->m_className << std::endl;\r
157                         m_log << _T("TITLE:\t") << n->m_titleName << std::endl;\r
158 \r
159                         bool isMDI = true;\r
160                         HWND hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), &isMDI);\r
161                         RECT rc;\r
162                         if (isMDI) {\r
163                                 getChildWindowRect(hwnd, &rc);\r
164                                 m_log << _T("MDI Window Position/Size: (")\r
165                                 << rc.left << _T(", ") << rc.top << _T(") / (")\r
166                                 << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")\r
167                                 << std::endl;\r
168                                 hwnd = getToplevelWindow(reinterpret_cast<HWND>(n->m_hwnd), NULL);\r
169                         }\r
170 \r
171                         GetWindowRect(hwnd, &rc);\r
172                         m_log << _T("Toplevel Window Position/Size: (")\r
173                         << rc.left << _T(", ") << rc.top << _T(") / (")\r
174                         << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")\r
175                         << std::endl;\r
176 \r
177                         SystemParametersInfo(SPI_GETWORKAREA, 0, (void *)&rc, FALSE);\r
178                         m_log << _T("Desktop Window Position/Size: (")\r
179                         << rc.left << _T(", ") << rc.top << _T(") / (")\r
180                         << rcWidth(&rc) << _T("x") << rcHeight(&rc) << _T(")")\r
181                         << std::endl;\r
182 \r
183                         m_log << std::endl;\r
184                         break;\r
185                 }\r
186 \r
187                 case Notify::Type_lockState: {\r
188                         NotifyLockState *n = (NotifyLockState *)cd->lpData;\r
189                         m_engine.setLockState(n->m_isNumLockToggled,\r
190                                                                   n->m_isCapsLockToggled,\r
191                                                                   n->m_isScrollLockToggled,\r
192                                                                   n->m_isKanaLockToggled,\r
193                                                                   n->m_isImeLockToggled,\r
194                                                                   n->m_isImeCompToggled);\r
195 #if 0\r
196                         Acquire a(&m_log, 0);\r
197                         if (n->m_isKanaLockToggled) {\r
198                                 m_log << _T("Notify::Type_lockState Kana on  : ");\r
199                         } else {\r
200                                 m_log << _T("Notify::Type_lockState Kana off : ");\r
201                         }\r
202                         m_log << n->m_debugParam << ", "\r
203                         << g_hookData->m_correctKanaLockHandling << std::endl;\r
204 #endif\r
205                         break;\r
206                 }\r
207 \r
208                 case Notify::Type_sync: {\r
209                         m_engine.syncNotify();\r
210                         break;\r
211                 }\r
212 \r
213                 case Notify::Type_threadDetach: {\r
214                         NotifyThreadDetach *n = (NotifyThreadDetach *)cd->lpData;\r
215                         m_engine.threadDetachNotify(n->m_threadId);\r
216                         break;\r
217                 }\r
218 \r
219                 case Notify::Type_command: {\r
220                         NotifyCommand *n = (NotifyCommand *)cd->lpData;\r
221                         m_engine.commandNotify(n->m_hwnd, n->m_message,\r
222                                                                    n->m_wParam, n->m_lParam);\r
223                         break;\r
224                 }\r
225 \r
226                 case Notify::Type_show: {\r
227                         NotifyShow *n = (NotifyShow *)cd->lpData;\r
228                         switch (n->m_show) {\r
229                         case NotifyShow::Show_Maximized:\r
230                                 m_engine.setShow(true, false, n->m_isMDI);\r
231                                 break;\r
232                         case NotifyShow::Show_Minimized:\r
233                                 m_engine.setShow(false, true, n->m_isMDI);\r
234                                 break;\r
235                         case NotifyShow::Show_Normal:\r
236                         default:\r
237                                 m_engine.setShow(false, false, n->m_isMDI);\r
238                                 break;\r
239                         }\r
240                         break;\r
241                 }\r
242 \r
243                 case Notify::Type_log: {\r
244                         Acquire a(&m_log, 1);\r
245                         NotifyLog *n = (NotifyLog *)cd->lpData;\r
246                         m_log << _T("hook log: ") << n->m_msg << std::endl;\r
247                         break;\r
248                 }\r
249                 }\r
250                 return true;\r
251         }\r
252 \r
253         /// window procedure for tasktray\r
254         static LRESULT CALLBACK\r
255         tasktray_wndProc(HWND i_hwnd, UINT i_message,\r
256                                          WPARAM i_wParam, LPARAM i_lParam) {\r
257 #ifdef MAYU64\r
258                 Mayu *This = reinterpret_cast<Mayu *>(GetWindowLongPtr(i_hwnd, 0));\r
259 #else\r
260                 Mayu *This = reinterpret_cast<Mayu *>(GetWindowLong(i_hwnd, 0));\r
261 #endif\r
262 \r
263                 if (!This)\r
264                         switch (i_message) {\r
265                         case WM_CREATE:\r
266                                 This = reinterpret_cast<Mayu *>(\r
267                                                    reinterpret_cast<CREATESTRUCT *>(i_lParam)->lpCreateParams);\r
268 #ifdef MAYU64\r
269                                 SetWindowLongPtr(i_hwnd, 0, (LONG_PTR)This);\r
270 #else\r
271                                 SetWindowLong(i_hwnd, 0, (long)This);\r
272 #endif\r
273                                 return 0;\r
274                         }\r
275                 else\r
276                         switch (i_message) {\r
277                         case WM_COPYDATA: {\r
278                                 COPYDATASTRUCT *cd;\r
279                                 cd = reinterpret_cast<COPYDATASTRUCT *>(i_lParam);\r
280                                 return This->notifyHandler(cd);\r
281                         }\r
282                         case WM_QUERYENDSESSION:\r
283                                 This->m_engine.prepairQuit();\r
284                                 PostQuitMessage(0);\r
285                                 return TRUE;\r
286 \r
287 #ifndef WM_WTSSESSION_CHANGE                    // WinUser.h\r
288 #  define WM_WTSSESSION_CHANGE            0x02B1\r
289 #endif\r
290                         case WM_WTSSESSION_CHANGE: {\r
291                                 const char *m = "";\r
292                                 switch (i_wParam) {\r
293 #ifndef WTS_CONSOLE_CONNECT                     // WinUser.h\r
294 #  define WTS_CONSOLE_CONNECT                0x1\r
295 #  define WTS_CONSOLE_DISCONNECT             0x2\r
296 #  define WTS_REMOTE_CONNECT                 0x3\r
297 #  define WTS_REMOTE_DISCONNECT              0x4\r
298 #  define WTS_SESSION_LOGON                  0x5\r
299 #  define WTS_SESSION_LOGOFF                 0x6\r
300 #  define WTS_SESSION_LOCK                   0x7\r
301 #  define WTS_SESSION_UNLOCK                 0x8\r
302 #endif\r
303                                 case WTS_CONSOLE_CONNECT:\r
304                                         m = "WTS_CONSOLE_CONNECT";\r
305                                         if (!This->m_engine.resume()) {\r
306                                                 This->m_engine.prepairQuit();\r
307                                                 PostQuitMessage(0);\r
308                                         }\r
309                                         break;\r
310                                 case WTS_CONSOLE_DISCONNECT:\r
311                                         m = "WTS_CONSOLE_DISCONNECT";\r
312                                         This->m_engine.pause();\r
313                                         break;\r
314                                 case WTS_REMOTE_CONNECT:\r
315                                         m = "WTS_REMOTE_CONNECT";\r
316                                         break;\r
317                                 case WTS_REMOTE_DISCONNECT:\r
318                                         m = "WTS_REMOTE_DISCONNECT";\r
319                                         break;\r
320                                 case WTS_SESSION_LOGON:\r
321                                         m = "WTS_SESSION_LOGON";\r
322                                         break;\r
323                                 case WTS_SESSION_LOGOFF:\r
324                                         m = "WTS_SESSION_LOGOFF";\r
325                                         break;\r
326                                 case WTS_SESSION_LOCK:\r
327                                         m = "WTS_SESSION_LOCK";\r
328                                         break;\r
329                                 case WTS_SESSION_UNLOCK:\r
330                                         m = "WTS_SESSION_UNLOCK";\r
331                                         break;\r
332                                         //case WTS_SESSION_REMOTE_CONTROL: m = "WTS_SESSION_REMOTE_CONTROL"; break;\r
333                                 }\r
334                                 This->m_log << _T("WM_WTSESSION_CHANGE(")\r
335                                 << i_wParam << ", " << i_lParam << "): "\r
336                                 << m << std::endl;\r
337                                 return TRUE;\r
338                         }\r
339                         case WM_APP_msgStreamNotify: {\r
340                                 tomsgstream::StreamBuf *log =\r
341                                         reinterpret_cast<tomsgstream::StreamBuf *>(i_lParam);\r
342                                 const tstring &str = log->acquireString();\r
343 #ifdef LOG_TO_FILE\r
344                                 This->m_logFile << str << std::flush;\r
345 #endif // LOG_TO_FILE\r
346                                 editInsertTextAtLast(GetDlgItem(This->m_hwndLog, IDC_EDIT_log),\r
347                                                                          str, 65000);\r
348                                 log->releaseString();\r
349                                 return 0;\r
350                         }\r
351 \r
352                         case WM_APP_taskTrayNotify: {\r
353                                 if (i_wParam == ID_TaskTrayIcon)\r
354                                         switch (i_lParam) {\r
355                                         case WM_RBUTTONUP: {\r
356                                                 POINT p;\r
357                                                 CHECK_TRUE( GetCursorPos(&p) );\r
358                                                 SetForegroundWindow(i_hwnd);\r
359                                                 HMENU hMenuSub = GetSubMenu(This->m_hMenuTaskTray, 0);\r
360                                                 if (This->m_engine.getIsEnabled())\r
361                                                         CheckMenuItem(hMenuSub, ID_MENUITEM_disable,\r
362                                                                                   MF_UNCHECKED | MF_BYCOMMAND);\r
363                                                 else\r
364                                                         CheckMenuItem(hMenuSub, ID_MENUITEM_disable,\r
365                                                                                   MF_CHECKED | MF_BYCOMMAND);\r
366                                                 CHECK_TRUE( SetMenuDefaultItem(hMenuSub,\r
367                                                                                                            ID_MENUITEM_investigate, FALSE) );\r
368 \r
369                                                 // create reload menu\r
370                                                 HMENU hMenuSubSub = GetSubMenu(hMenuSub, 1);\r
371                                                 Registry reg(MAYU_REGISTRY_ROOT);\r
372                                                 int mayuIndex;\r
373                                                 reg.read(_T(".mayuIndex"), &mayuIndex, 0);\r
374                                                 while (DeleteMenu(hMenuSubSub, 0, MF_BYPOSITION))\r
375                                                         ;\r
376                                                 tregex getName(_T("^([^;]*);"));\r
377                                                 for (int index = 0; ; index ++) {\r
378                                                         _TCHAR buf[100];\r
379                                                         _sntprintf(buf, NUMBER_OF(buf), _T(".mayu%d"), index);\r
380                                                         tstringi dot_mayu;\r
381                                                         if (!reg.read(buf, &dot_mayu))\r
382                                                                 break;\r
383                                                         tsmatch what;\r
384                                                         if (boost::regex_search(dot_mayu, what, getName)) {\r
385                                                                 MENUITEMINFO mii;\r
386                                                                 std::memset(&mii, 0, sizeof(mii));\r
387                                                                 mii.cbSize = sizeof(mii);\r
388                                                                 mii.fMask = MIIM_ID | MIIM_STATE | MIIM_TYPE;\r
389                                                                 mii.fType = MFT_STRING;\r
390                                                                 mii.fState =\r
391                                                                         MFS_ENABLED | ((mayuIndex == index) ? MFS_CHECKED : 0);\r
392                                                                 mii.wID = ID_MENUITEM_reloadBegin + index;\r
393                                                                 tstringi name(what.str(1));\r
394                                                                 mii.dwTypeData = const_cast<_TCHAR *>(name.c_str());\r
395                                                                 mii.cch = name.size();\r
396 \r
397                                                                 InsertMenuItem(hMenuSubSub, index, TRUE, &mii);\r
398                                                         }\r
399                                                 }\r
400 \r
401                                                 // show popup menu\r
402                                                 TrackPopupMenu(hMenuSub, TPM_LEFTALIGN,\r
403                                                                            p.x, p.y, 0, i_hwnd, NULL);\r
404                                                 // TrackPopupMenu may fail (ERROR_POPUP_ALREADY_ACTIVE)\r
405                                                 break;\r
406                                         }\r
407 \r
408                                         case WM_LBUTTONDBLCLK:\r
409                                                 SendMessage(i_hwnd, WM_COMMAND,\r
410                                                                         MAKELONG(ID_MENUITEM_investigate, 0), 0);\r
411                                                 break;\r
412                                         }\r
413                                 return 0;\r
414                         }\r
415 \r
416                         case WM_COMMAND: {\r
417                                 int notify_code = HIWORD(i_wParam);\r
418                                 int id = LOWORD(i_wParam);\r
419                                 if (notify_code == 0) // menu\r
420                                         switch (id) {\r
421                                         default:\r
422                                                 if (ID_MENUITEM_reloadBegin <= id) {\r
423                                                         Registry reg(MAYU_REGISTRY_ROOT);\r
424                                                         reg.write(_T(".mayuIndex"), id - ID_MENUITEM_reloadBegin);\r
425                                                         This->load();\r
426                                                 }\r
427                                                 break;\r
428                                         case ID_MENUITEM_reload:\r
429                                                 This->load();\r
430                                                 break;\r
431                                         case ID_MENUITEM_investigate: {\r
432                                                 ShowWindow(This->m_hwndLog, SW_SHOW);\r
433                                                 ShowWindow(This->m_hwndInvestigate, SW_SHOW);\r
434 \r
435                                                 RECT rc1, rc2;\r
436                                                 GetWindowRect(This->m_hwndInvestigate, &rc1);\r
437                                                 GetWindowRect(This->m_hwndLog, &rc2);\r
438 \r
439                                                 MoveWindow(This->m_hwndLog, rc1.left, rc1.bottom,\r
440                                                                    rcWidth(&rc1), rcHeight(&rc2), TRUE);\r
441 \r
442                                                 SetForegroundWindow(This->m_hwndLog);\r
443                                                 SetForegroundWindow(This->m_hwndInvestigate);\r
444                                                 break;\r
445                                         }\r
446                                         case ID_MENUITEM_setting:\r
447                                                 if (!This->m_isSettingDialogOpened) {\r
448                                                         This->m_isSettingDialogOpened = true;\r
449                                                         if (DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_setting),\r
450                                                                                   NULL, dlgSetting_dlgProc))\r
451                                                                 This->load();\r
452                                                         This->m_isSettingDialogOpened = false;\r
453                                                 }\r
454                                                 break;\r
455                                         case ID_MENUITEM_log:\r
456                                                 ShowWindow(This->m_hwndLog, SW_SHOW);\r
457                                                 SetForegroundWindow(This->m_hwndLog);\r
458                                                 break;\r
459                                         case ID_MENUITEM_check: {\r
460                                                 BOOL ret;\r
461                                                 BYTE keys[256];\r
462                                                 ret = GetKeyboardState(keys);\r
463                                                 if (ret == 0) {\r
464                                                         This->m_log << _T("Check Keystate Failed(%d)")\r
465                                                         << GetLastError() << std::endl;\r
466                                                 } else {\r
467                                                         This->m_log << _T("Check Keystate: ") << std::endl;\r
468                                                         for (int i = 0; i < 0xff; i++) {\r
469                                                                 USHORT asyncKey;\r
470                                                                 asyncKey = GetAsyncKeyState(i);\r
471                                                                 This->m_log << std::hex;\r
472                                                                 if (asyncKey & 0x8000) {\r
473                                                                         This->m_log << _T("  ") << VK2TCHAR[i]\r
474                                                                         << _T("(0x") << i << _T("): pressed!")\r
475                                                                         << std::endl;\r
476                                                                 }\r
477                                                                 if (i == 0x14 || // VK_CAPTITAL\r
478                                                                                 i == 0x15 || // VK_KANA\r
479                                                                                 i == 0x19 || // VK_KANJI\r
480                                                                                 i == 0x90 || // VK_NUMLOCK\r
481                                                                                 i == 0x91    // VK_SCROLL\r
482                                                                    ) {\r
483                                                                         if (keys[i] & 1) {\r
484                                                                                 This->m_log << _T("  ") << VK2TCHAR[i]\r
485                                                                                 << _T("(0x") << i << _T("): locked!")\r
486                                                                                 << std::endl;\r
487                                                                         }\r
488                                                                 }\r
489                                                                 This->m_log << std::dec;\r
490                                                         }\r
491                                                         This->m_log << std::endl;\r
492                                                 }\r
493                                                 break;\r
494                                         }\r
495                                         case ID_MENUITEM_version:\r
496                                                 ShowWindow(This->m_hwndVersion, SW_SHOW);\r
497                                                 SetForegroundWindow(This->m_hwndVersion);\r
498                                                 break;\r
499                                         case ID_MENUITEM_help: {\r
500                                                 _TCHAR buf[GANA_MAX_PATH];\r
501                                                 CHECK_TRUE( GetModuleFileName(g_hInst, buf, NUMBER_OF(buf)) );\r
502                                                 tstringi helpFilename = pathRemoveFileSpec(buf);\r
503                                                 helpFilename += _T("\\");\r
504                                                 helpFilename += loadString(IDS_helpFilename);\r
505                                                 ShellExecute(NULL, _T("open"), helpFilename.c_str(),\r
506                                                                          NULL, NULL, SW_SHOWNORMAL);\r
507                                                 break;\r
508                                         }\r
509                                         case ID_MENUITEM_disable:\r
510                                                 This->m_engine.enable(!This->m_engine.getIsEnabled());\r
511                                                 This->showTasktrayIcon();\r
512                                                 break;\r
513                                         case ID_MENUITEM_quit:\r
514                                                 This->m_engine.prepairQuit();\r
515                                                 PostQuitMessage(0);\r
516                                                 break;\r
517                                         }\r
518                                 return 0;\r
519                         }\r
520 \r
521                         case WM_APP_engineNotify: {\r
522                                 switch (i_wParam) {\r
523                                 case EngineNotify_shellExecute:\r
524                                         This->m_engine.shellExecute();\r
525                                         break;\r
526                                 case EngineNotify_loadSetting:\r
527                                         This->load();\r
528                                         break;\r
529                                 case EngineNotify_helpMessage:\r
530                                         This->showHelpMessage(false);\r
531                                         if (i_lParam)\r
532                                                 This->showHelpMessage(true);\r
533                                         break;\r
534                                 case EngineNotify_showDlg: {\r
535                                         // show investigate/log window\r
536                                         int sw = (i_lParam & ~MayuDialogType_mask);\r
537                                         HWND hwnd = NULL;\r
538                                         switch (static_cast<MayuDialogType>(\r
539                                                                 i_lParam & MayuDialogType_mask)) {\r
540                                         case MayuDialogType_investigate:\r
541                                                 hwnd = This->m_hwndInvestigate;\r
542                                                 break;\r
543                                         case MayuDialogType_log:\r
544                                                 hwnd = This->m_hwndLog;\r
545                                                 break;\r
546                                         }\r
547                                         if (hwnd) {\r
548                                                 ShowWindow(hwnd, sw);\r
549                                                 switch (sw) {\r
550                                                 case SW_SHOWNORMAL:\r
551                                                 case SW_SHOWMAXIMIZED:\r
552                                                 case SW_SHOW:\r
553                                                 case SW_RESTORE:\r
554                                                 case SW_SHOWDEFAULT:\r
555                                                         SetForegroundWindow(hwnd);\r
556                                                         break;\r
557                                                 }\r
558                                         }\r
559                                         break;\r
560                                 }\r
561                                 case EngineNotify_setForegroundWindow:\r
562                                         // FIXME: completely useless. why ?\r
563                                         setForegroundWindow(reinterpret_cast<HWND>(i_lParam));\r
564                                         {\r
565                                                 Acquire a(&This->m_log, 1);\r
566                                                 This->m_log << _T("setForegroundWindow(0x")\r
567                                                 << std::hex << i_lParam << std::dec << _T(")")\r
568                                                 << std::endl;\r
569                                         }\r
570                                         break;\r
571                                 case EngineNotify_clearLog:\r
572                                         SendMessage(This->m_hwndLog, WM_COMMAND,\r
573                                                                 MAKELONG(IDC_BUTTON_clearLog, 0), 0);\r
574                                         break;\r
575                                 default:\r
576                                         break;\r
577                                 }\r
578                                 return 0;\r
579                         }\r
580 \r
581                         case WM_APP_dlglogNotify: {\r
582                                 switch (i_wParam) {\r
583                                 case DlgLogNotify_logCleared:\r
584                                         This->showBanner(true);\r
585                                         break;\r
586                                 default:\r
587                                         break;\r
588                                 }\r
589                                 return 0;\r
590                         }\r
591 \r
592                         case WM_DESTROY:\r
593                                 if (This->m_usingSN) {\r
594                                         wtsUnRegisterSessionNotification(i_hwnd);\r
595                                         This->m_usingSN = false;\r
596                                 }\r
597                                 return 0;\r
598 \r
599                         default:\r
600                                 if (i_message == This->m_WM_TaskbarRestart) {\r
601                                         if (This->showTasktrayIcon(true)) {\r
602                                                 Acquire a(&This->m_log, 0);\r
603                                                 This->m_log << _T("Tasktray icon is updated.") << std::endl;\r
604                                         } else {\r
605                                                 Acquire a(&This->m_log, 1);\r
606                                                 This->m_log << _T("Tasktray icon already exists.") << std::endl;\r
607                                         }\r
608                                         return 0;\r
609                                 } else if (i_message == This->m_WM_MayuIPC) {\r
610                                         switch (static_cast<MayuIPCCommand>(i_wParam)) {\r
611                                         case MayuIPCCommand_Enable:\r
612                                                 This->m_engine.enable(!!i_lParam);\r
613                                                 This->showTasktrayIcon();\r
614                                                 if (i_lParam) {\r
615                                                         Acquire a(&This->m_log, 1);\r
616                                                         This->m_log << _T("Enabled by another application.")\r
617                                                         << std::endl;\r
618                                                 } else {\r
619                                                         Acquire a(&This->m_log, 1);\r
620                                                         This->m_log << _T("Disabled by another application.")\r
621                                                         << std::endl;\r
622                                                 }\r
623                                                 break;\r
624                                         }\r
625                                 }\r
626                         }\r
627                 return DefWindowProc(i_hwnd, i_message, i_wParam, i_lParam);\r
628         }\r
629 \r
630         /// load setting\r
631         void load() {\r
632                 Setting *newSetting = new Setting;\r
633 \r
634                 // set symbol\r
635                 for (int i = 1; i < __argc; ++ i) {\r
636                         if (__targv[i][0] == _T('-') && __targv[i][1] == _T('D'))\r
637                                 newSetting->m_symbols.insert(__targv[i] + 2);\r
638                 }\r
639 \r
640                 if (!SettingLoader(&m_log, &m_log).load(newSetting)) {\r
641                         ShowWindow(m_hwndLog, SW_SHOW);\r
642                         SetForegroundWindow(m_hwndLog);\r
643                         delete newSetting;\r
644                         Acquire a(&m_log, 0);\r
645                         m_log << _T("error: failed to load.") << std::endl;\r
646                         return;\r
647                 }\r
648                 m_log << _T("successfully loaded.") << std::endl;\r
649                 while (!m_engine.setSetting(newSetting))\r
650                         Sleep(1000);\r
651                 delete m_setting;\r
652                 m_setting = newSetting;\r
653         }\r
654 \r
655         // show message (a baloon from the task tray icon)\r
656         void showHelpMessage(bool i_doesShow = true) {\r
657                 if (m_canUseTasktrayBaloon) {\r
658                         if (i_doesShow) {\r
659                                 tstring helpMessage, helpTitle;\r
660                                 m_engine.getHelpMessages(&helpMessage, &helpTitle);\r
661                                 tcslcpy(m_ni.szInfo, helpMessage.c_str(), NUMBER_OF(m_ni.szInfo));\r
662                                 tcslcpy(m_ni.szInfoTitle, helpTitle.c_str(),\r
663                                                 NUMBER_OF(m_ni.szInfoTitle));\r
664                                 m_ni.dwInfoFlags = NIIF_INFO;\r
665                         } else\r
666                                 m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');\r
667                         CHECK_TRUE( Shell_NotifyIcon(NIM_MODIFY, &m_ni) );\r
668                 }\r
669         }\r
670 \r
671         // change the task tray icon\r
672         bool showTasktrayIcon(bool i_doesAdd = false) {\r
673                 m_ni.hIcon  = m_tasktrayIcon[m_engine.getIsEnabled() ? 1 : 0];\r
674                 m_ni.szInfo[0] = m_ni.szInfoTitle[0] = _T('\0');\r
675                 if (i_doesAdd) {\r
676                         // http://support.microsoft.com/kb/418138/JA/\r
677                         int guard = 60;\r
678                         for (; !Shell_NotifyIcon(NIM_ADD, &m_ni) && 0 < guard; -- guard) {\r
679                                 if (Shell_NotifyIcon(NIM_MODIFY, &m_ni)) {\r
680                                         return true;\r
681                                 }\r
682                                 Sleep(1000);                            // 1sec\r
683                         }\r
684                         return 0 < guard;\r
685                 } else {\r
686                         return !!Shell_NotifyIcon(NIM_MODIFY, &m_ni);\r
687                 }\r
688         }\r
689 \r
690         void showBanner(bool i_isCleared) {\r
691                 time_t now;\r
692                 time(&now);\r
693 \r
694                 _TCHAR starttimebuf[1024];\r
695                 _TCHAR timebuf[1024];\r
696 \r
697 #ifdef __BORLANDC__\r
698 #pragma message("\t\t****\tAfter std::ostream() is called,  ")\r
699 #pragma message("\t\t****\tstrftime(... \"%%#c\" ...) fails.")\r
700 #pragma message("\t\t****\tWhy ? Bug of Borland C++ 5.5.1 ? ")\r
701 #pragma message("\t\t****\t                         - nayuta")\r
702                 _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%Y/%m/%d %H:%M:%S"),\r
703                                   localtime(&now));\r
704                 _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%Y/%m/%d %H:%M:%S"),\r
705                                   localtime(&m_startTime));\r
706 #else\r
707                 _tcsftime(timebuf, NUMBER_OF(timebuf), _T("%#c"), localtime(&now));\r
708                 _tcsftime(starttimebuf, NUMBER_OF(starttimebuf), _T("%#c"),\r
709                                   localtime(&m_startTime));\r
710 #endif\r
711 \r
712                 Acquire a(&m_log, 0);\r
713                 m_log << _T("------------------------------------------------------------") << std::endl;\r
714                 m_log << loadString(IDS_mayu) << _T(" ") _T(VERSION);\r
715 #ifndef NDEBUG\r
716                 m_log << _T(" (DEBUG)");\r
717 #endif\r
718 #ifdef _UNICODE\r
719                 m_log << _T(" (UNICODE)");\r
720 #endif\r
721                 m_log << std::endl;\r
722                 m_log << _T("  built by ")\r
723                 << _T(LOGNAME) << _T("@") << toLower(_T(COMPUTERNAME))\r
724                 << _T(" (") << _T(__DATE__) <<  _T(" ")\r
725                 << _T(__TIME__) << _T(", ")\r
726                 << getCompilerVersionString() << _T(")") << std::endl;\r
727                 _TCHAR modulebuf[1024];\r
728                 CHECK_TRUE( GetModuleFileName(g_hInst, modulebuf,\r
729                                                                           NUMBER_OF(modulebuf)) );\r
730                 m_log << _T("started at ") << starttimebuf << std::endl;\r
731                 m_log << modulebuf << std::endl;\r
732                 m_log << _T("------------------------------------------------------------") << std::endl;\r
733 \r
734                 if (i_isCleared) {\r
735                         m_log << _T("log was cleared at ") << timebuf << std::endl;\r
736                 } else {\r
737                         m_log << _T("log begins at ") << timebuf << std::endl;\r
738                 }\r
739         }\r
740 \r
741 public:\r
742         ///\r
743         Mayu(HANDLE i_mutex)\r
744                         : m_hwndTaskTray(NULL),\r
745                         m_mutex(i_mutex),\r
746                         m_hwndLog(NULL),\r
747                         m_WM_TaskbarRestart(RegisterWindowMessage(_T("TaskbarCreated"))),\r
748                         m_WM_MayuIPC(RegisterWindowMessage(WM_MayuIPC_NAME)),\r
749                         m_canUseTasktrayBaloon(\r
750                                 PACKVERSION(5, 0) <= getDllVersion(_T("shlwapi.dll"))),\r
751                         m_log(WM_APP_msgStreamNotify),\r
752                         m_setting(NULL),\r
753                         m_isSettingDialogOpened(false),\r
754                         m_engine(m_log) {\r
755 #ifdef USE_MAILSLOT\r
756                 m_hNotifyMailslot = CreateMailslot(NOTIFY_MAILSLOT_NAME, 0, MAILSLOT_WAIT_FOREVER, (SECURITY_ATTRIBUTES *)NULL);\r
757                 ASSERT(m_hNotifyMailslot != INVALID_HANDLE_VALUE);\r
758                 m_hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
759                 ASSERT(m_hNotifyEvent);\r
760                 m_olNotify.Offset = 0;\r
761                 m_olNotify.OffsetHigh = 0;\r
762                 m_olNotify.hEvent = m_hNotifyEvent;\r
763 #endif // USE_MAILSLOT\r
764                 time(&m_startTime);\r
765 \r
766                 CHECK_TRUE( Register_focus() );\r
767                 CHECK_TRUE( Register_target() );\r
768                 CHECK_TRUE( Register_tasktray() );\r
769 \r
770                 // change dir\r
771 #if 0\r
772                 HomeDirectories pathes;\r
773                 getHomeDirectories(&pathes);\r
774                 for (HomeDirectories::iterator i = pathes.begin(); i != pathes.end(); ++ i)\r
775                         if (SetCurrentDirectory(i->c_str()))\r
776                                 break;\r
777 #endif\r
778 \r
779                 // create windows, dialogs\r
780                 tstringi title = loadString(IDS_mayu);\r
781                 m_hwndTaskTray = CreateWindow(_T("mayuTasktray"), title.c_str(),\r
782                                                                           WS_OVERLAPPEDWINDOW,\r
783                                                                           CW_USEDEFAULT, CW_USEDEFAULT,\r
784                                                                           CW_USEDEFAULT, CW_USEDEFAULT,\r
785                                                                           NULL, NULL, g_hInst, this);\r
786                 CHECK_TRUE( m_hwndTaskTray );\r
787 \r
788                 // set window handle of tasktray to hooks\r
789 #ifndef USE_MAILSLOT\r
790                 g_hookData->m_hwndTaskTray = reinterpret_cast<DWORD>(m_hwndTaskTray);\r
791 #endif // !USE_MAILSLOT\r
792                 CHECK_FALSE( installHooks(Engine::keyboardDetour, &m_engine) );\r
793                 m_usingSN = wtsRegisterSessionNotification(m_hwndTaskTray,\r
794                                         NOTIFY_FOR_THIS_SESSION);\r
795 \r
796                 DlgLogData dld;\r
797                 dld.m_log = &m_log;\r
798                 dld.m_hwndTaskTray = m_hwndTaskTray;\r
799                 m_hwndLog =\r
800                         CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_log), NULL,\r
801                                                           dlgLog_dlgProc, (LPARAM)&dld);\r
802                 CHECK_TRUE( m_hwndLog );\r
803 \r
804                 DlgInvestigateData did;\r
805                 did.m_engine = &m_engine;\r
806                 did.m_hwndLog = m_hwndLog;\r
807                 m_hwndInvestigate =\r
808                         CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_investigate), NULL,\r
809                                                           dlgInvestigate_dlgProc, (LPARAM)&did);\r
810                 CHECK_TRUE( m_hwndInvestigate );\r
811 \r
812                 m_hwndVersion =\r
813                         CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DIALOG_version),\r
814                                                           NULL, dlgVersion_dlgProc,\r
815                                                           (LPARAM)m_engine.getMayudVersion().c_str());\r
816                 CHECK_TRUE( m_hwndVersion );\r
817 \r
818                 // attach log\r
819 #ifdef LOG_TO_FILE\r
820                 tstring path;\r
821                 _TCHAR exePath[GANA_MAX_PATH];\r
822                 _TCHAR exeDrive[GANA_MAX_PATH];\r
823                 _TCHAR exeDir[GANA_MAX_PATH];\r
824                 GetModuleFileName(NULL, exePath, GANA_MAX_PATH);\r
825                 _tsplitpath_s(exePath, exeDrive, GANA_MAX_PATH, exeDir, GANA_MAX_PATH, NULL, 0, NULL, 0);\r
826                 path = exeDrive;\r
827                 path += exeDir;\r
828                 path += _T("mayu.log");\r
829                 m_logFile.open(path.c_str(), std::ios::app);\r
830                 m_logFile.imbue(std::locale("japanese"));\r
831 #endif // LOG_TO_FILE\r
832                 SendMessage(GetDlgItem(m_hwndLog, IDC_EDIT_log), EM_SETLIMITTEXT, 0, 0);\r
833                 m_log.attach(m_hwndTaskTray);\r
834 \r
835                 // start keyboard handler thread\r
836                 m_engine.setAssociatedWndow(m_hwndTaskTray);\r
837                 m_engine.start();\r
838 \r
839                 // show tasktray icon\r
840                 m_tasktrayIcon[0] = loadSmallIcon(IDI_ICON_mayu_disabled);\r
841                 m_tasktrayIcon[1] = loadSmallIcon(IDI_ICON_mayu);\r
842                 std::memset(&m_ni, 0, sizeof(m_ni));\r
843                 m_ni.uID    = ID_TaskTrayIcon;\r
844                 m_ni.hWnd   = m_hwndTaskTray;\r
845                 m_ni.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;\r
846                 m_ni.hIcon  = m_tasktrayIcon[1];\r
847                 m_ni.uCallbackMessage = WM_APP_taskTrayNotify;\r
848                 tstring tip = loadString(IDS_mayu);\r
849                 tcslcpy(m_ni.szTip, tip.c_str(), NUMBER_OF(m_ni.szTip));\r
850                 if (m_canUseTasktrayBaloon) {\r
851                         m_ni.cbSize = sizeof(m_ni);\r
852                         m_ni.uFlags |= NIF_INFO;\r
853                 } else\r
854                         m_ni.cbSize = NOTIFYICONDATA_V1_SIZE;\r
855                 showTasktrayIcon(true);\r
856 \r
857                 // create menu\r
858                 m_hMenuTaskTray = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU_tasktray));\r
859                 ASSERT(m_hMenuTaskTray);\r
860 \r
861                 // set initial lock state\r
862                 notifyLockState();\r
863 \r
864                 BOOL result;\r
865 \r
866                 ZeroMemory(&m_pi,sizeof(m_pi));\r
867                 ZeroMemory(&m_si,sizeof(m_si));\r
868                 m_si.cb=sizeof(m_si);\r
869 #ifdef _WIN64\r
870                 result = CreateProcess(_T("yamyd32"), _T("yamyd32"), NULL, NULL, FALSE,\r
871                                                            NORMAL_PRIORITY_CLASS, 0, NULL, &m_si, &m_pi);\r
872                 if (result == FALSE) {\r
873                         TCHAR buf[1024];\r
874                         TCHAR text[1024];\r
875                         TCHAR title[1024];\r
876 \r
877                         LoadString(GetModuleHandle(NULL), IDS_cannotInvoke,\r
878                                            text, sizeof(text)/sizeof(text[0]));\r
879                         LoadString(GetModuleHandle(NULL), IDS_mayu,\r
880                                            title, sizeof(title)/sizeof(title[0]));\r
881                         _stprintf_s(buf, sizeof(buf)/sizeof(buf[0]),\r
882                                                 text, _T("yamyd32"), GetLastError());\r
883                         MessageBox((HWND)NULL, buf, title, MB_OK | MB_ICONSTOP);\r
884                 } else {\r
885                         CloseHandle(m_pi.hThread);\r
886                         CloseHandle(m_pi.hProcess);\r
887                 }\r
888 #endif // _WIN64\r
889         }\r
890 \r
891         ///\r
892         ~Mayu() {\r
893                 ReleaseMutex(m_mutex);\r
894                 WaitForSingleObject(m_mutex, INFINITE);\r
895                 // first, detach log from edit control to avoid deadlock\r
896                 m_log.detach();\r
897 #ifdef LOG_TO_FILE\r
898                 m_logFile.close();\r
899 #endif // LOG_TO_FILE\r
900 \r
901                 // stop notify from mayu.dll\r
902                 g_hookData->m_hwndTaskTray = NULL;\r
903                 CHECK_FALSE( uninstallHooks() );\r
904                 PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);\r
905 \r
906                 // destroy windows\r
907                 CHECK_TRUE( DestroyWindow(m_hwndVersion) );\r
908                 CHECK_TRUE( DestroyWindow(m_hwndInvestigate) );\r
909                 CHECK_TRUE( DestroyWindow(m_hwndLog) );\r
910                 CHECK_TRUE( DestroyWindow(m_hwndTaskTray) );\r
911 \r
912                 // destroy menu\r
913                 DestroyMenu(m_hMenuTaskTray);\r
914 \r
915                 // delete tasktray icon\r
916                 CHECK_TRUE( Shell_NotifyIcon(NIM_DELETE, &m_ni) );\r
917                 CHECK_TRUE( DestroyIcon(m_tasktrayIcon[1]) );\r
918                 CHECK_TRUE( DestroyIcon(m_tasktrayIcon[0]) );\r
919 \r
920                 // stop keyboard handler thread\r
921                 m_engine.stop();\r
922 \r
923                 // remove setting;\r
924                 delete m_setting;\r
925 \r
926 #ifdef USE_MAILSLOT\r
927                 CloseHandle(m_hNotifyEvent);\r
928                 CloseHandle(m_hNotifyMailslot);\r
929 #endif // USE_MAILSLOT\r
930         }\r
931 \r
932         /// message loop\r
933         WPARAM messageLoop() {\r
934                 showBanner(false);\r
935                 load();\r
936 \r
937 #ifdef USE_MAILSLOT\r
938                 mailslotHandler(0, 0);\r
939                 while (1) {\r
940                         HANDLE handles[] = { m_hNotifyEvent };\r
941                         DWORD ret;\r
942                         switch (ret = MsgWaitForMultipleObjectsEx(NUMBER_OF(handles), &handles[0],\r
943                                                   INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE)) {\r
944                         case WAIT_OBJECT_0:                     // m_hNotifyEvent\r
945                                 break;\r
946 \r
947                         case WAIT_OBJECT_0 + NUMBER_OF(handles): {\r
948                                 MSG msg;\r
949                                 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {\r
950                                         if (msg.message == WM_QUIT) {\r
951                                                 return msg.wParam;\r
952                                         }\r
953                                         if (IsDialogMessage(m_hwndLog, &msg))\r
954                                                 break;\r
955                                         if (IsDialogMessage(m_hwndInvestigate, &msg))\r
956                                                 break;\r
957                                         if (IsDialogMessage(m_hwndVersion, &msg))\r
958                                                 break;\r
959                                         TranslateMessage(&msg);\r
960                                         DispatchMessage(&msg);\r
961                                         break;\r
962                                 }\r
963                                 break;\r
964                         }\r
965 \r
966                         case WAIT_IO_COMPLETION:\r
967                                 break;\r
968 \r
969                         case 0x102:\r
970                         default:\r
971                                 break;\r
972                         }\r
973                 }\r
974 #else // !USE_MAILSLOT\r
975                 MSG msg;\r
976                 while (0 < GetMessage(&msg, NULL, 0, 0)) {\r
977                         if (IsDialogMessage(m_hwndLog, &msg))\r
978                                 continue;\r
979                         if (IsDialogMessage(m_hwndInvestigate, &msg))\r
980                                 continue;\r
981                         if (IsDialogMessage(m_hwndVersion, &msg))\r
982                                 continue;\r
983                         TranslateMessage(&msg);\r
984                         DispatchMessage(&msg);\r
985                 }\r
986                 return msg.wParam;\r
987 #endif // !USE_MAILSLOT\r
988         }\r
989 };\r
990 \r
991 \r
992 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
993 // Functions\r
994 \r
995 \r
996 /// convert registry\r
997 void convertRegistry()\r
998 {\r
999         Registry reg(MAYU_REGISTRY_ROOT);\r
1000         tstringi dot_mayu;\r
1001         bool doesAdd = false;\r
1002         DWORD index;\r
1003         if (reg.read(_T(".mayu"), &dot_mayu)) {\r
1004                 reg.write(_T(".mayu0"), _T(";") + dot_mayu + _T(";"));\r
1005                 reg.remove(_T(".mayu"));\r
1006                 doesAdd = true;\r
1007                 index = 0;\r
1008         } else if (!reg.read(_T(".mayu0"), &dot_mayu)) {\r
1009                 reg.write(_T(".mayu0"), loadString(IDS_readFromHomeDirectory) + _T(";;"));\r
1010                 doesAdd = true;\r
1011                 index = 1;\r
1012         }\r
1013         if (doesAdd) {\r
1014                 Registry commonreg(HKEY_LOCAL_MACHINE, _T("Software\\GANAware\\mayu"));\r
1015                 tstringi dir, layout;\r
1016                 if (commonreg.read(_T("dir"), &dir) &&\r
1017                                 commonreg.read(_T("layout"), &layout)) {\r
1018                         tstringi tmp = _T(";") + dir + _T("\\dot.mayu");\r
1019                         if (layout == _T("109")) {\r
1020                                 reg.write(_T(".mayu1"), loadString(IDS_109Emacs) + tmp\r
1021                                                   + _T(";-DUSE109") _T(";-DUSEdefault"));\r
1022                                 reg.write(_T(".mayu2"), loadString(IDS_104on109Emacs) + tmp\r
1023                                                   + _T(";-DUSE109") _T(";-DUSEdefault") _T(";-DUSE104on109"));\r
1024                                 reg.write(_T(".mayu3"), loadString(IDS_109) + tmp\r
1025                                                   + _T(";-DUSE109"));\r
1026                                 reg.write(_T(".mayu4"), loadString(IDS_104on109) + tmp\r
1027                                                   + _T(";-DUSE109") _T(";-DUSE104on109"));\r
1028                         } else {\r
1029                                 reg.write(_T(".mayu1"), loadString(IDS_104Emacs) + tmp\r
1030                                                   + _T(";-DUSE104") _T(";-DUSEdefault"));\r
1031                                 reg.write(_T(".mayu2"), loadString(IDS_109on104Emacs) + tmp\r
1032                                                   + _T(";-DUSE104") _T(";-DUSEdefault") _T(";-DUSE109on104"));\r
1033                                 reg.write(_T(".mayu3"), loadString(IDS_104) + tmp\r
1034                                                   + _T(";-DUSE104"));\r
1035                                 reg.write(_T(".mayu4"), loadString(IDS_109on104) + tmp\r
1036                                                   + _T(";-DUSE104") _T(";-DUSE109on104"));\r
1037                         }\r
1038                         reg.write(_T(".mayuIndex"), index);\r
1039                 }\r
1040         }\r
1041 }\r
1042 \r
1043 \r
1044 /// main\r
1045 int WINAPI _tWinMain(HINSTANCE i_hInstance, HINSTANCE /* i_hPrevInstance */,\r
1046                                          LPTSTR /* i_lpszCmdLine */, int /* i_nCmdShow */)\r
1047 {\r
1048         g_hInst = i_hInstance;\r
1049 \r
1050         // set locale\r
1051         CHECK_TRUE( _tsetlocale(LC_ALL, _T("")) );\r
1052 \r
1053         // common controls\r
1054 #if defined(_WIN95)\r
1055         InitCommonControls();\r
1056 #else\r
1057         INITCOMMONCONTROLSEX icc;\r
1058         icc.dwSize = sizeof(icc);\r
1059         icc.dwICC = ICC_LISTVIEW_CLASSES;\r
1060         CHECK_TRUE( InitCommonControlsEx(&icc) );\r
1061 #endif\r
1062 \r
1063         // convert old registry to new registry\r
1064 #ifndef USE_INI\r
1065         convertRegistry();\r
1066 #endif // !USE_INI\r
1067 \r
1068         // is another mayu running ?\r
1069         HANDLE mutex = CreateMutex((SECURITY_ATTRIBUTES *)NULL, TRUE,\r
1070                                                            MUTEX_MAYU_EXCLUSIVE_RUNNING);\r
1071         if (GetLastError() == ERROR_ALREADY_EXISTS) {\r
1072                 // another mayu already running\r
1073                 tstring text = loadString(IDS_mayuAlreadyExists);\r
1074                 tstring title = loadString(IDS_mayu);\r
1075                 if (g_hookData) {\r
1076                         UINT WM_TaskbarRestart = RegisterWindowMessage(_T("TaskbarCreated"));\r
1077                         PostMessage(reinterpret_cast<HWND>(g_hookData->m_hwndTaskTray),\r
1078                                                 WM_TaskbarRestart, 0, 0);\r
1079                 }\r
1080                 MessageBox((HWND)NULL, text.c_str(), title.c_str(), MB_OK | MB_ICONSTOP);\r
1081                 return 1;\r
1082         }\r
1083 \r
1084         // check remote desktop\r
1085         DWORD sessionId;\r
1086         if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId) ||\r
1087                         wtsGetActiveConsoleSessionId() != sessionId) {\r
1088                 tstring text = loadString(IDS_executedInRemoteDesktop);\r
1089                 tstring title = loadString(IDS_mayu);\r
1090                 MessageBox((HWND)NULL, text.c_str(), title.c_str(), MB_OK | MB_ICONSTOP);\r
1091                 return 1;\r
1092         }\r
1093 \r
1094         try {\r
1095                 Mayu(mutex).messageLoop();\r
1096         } catch (ErrorMessage &i_e) {\r
1097                 tstring title = loadString(IDS_mayu);\r
1098                 MessageBox((HWND)NULL, i_e.getMessage().c_str(), title.c_str(),\r
1099                                    MB_OK | MB_ICONSTOP);\r
1100         }\r
1101 \r
1102         CHECK_TRUE( CloseHandle(mutex) );\r
1103         return 0;\r
1104 }\r