xref: /reactos/base/applications/ctfmon/ctfmon.cpp (revision 6bc40d36)
1079b3654SKatayama Hirofumi MZ /*
2079b3654SKatayama Hirofumi MZ  * PROJECT:     ReactOS CTF Monitor
3079b3654SKatayama Hirofumi MZ  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4079b3654SKatayama Hirofumi MZ  * PURPOSE:     Providing Language Bar front-end
5079b3654SKatayama Hirofumi MZ  * COPYRIGHT:   Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6079b3654SKatayama Hirofumi MZ  */
7079b3654SKatayama Hirofumi MZ 
8079b3654SKatayama Hirofumi MZ #include "precomp.h"
9079b3654SKatayama Hirofumi MZ #include "CRegWatcher.h"
10079b3654SKatayama Hirofumi MZ #include "CLoaderWnd.h"
11079b3654SKatayama Hirofumi MZ 
12079b3654SKatayama Hirofumi MZ // kernel32!SetProcessShutdownParameters
13079b3654SKatayama Hirofumi MZ typedef BOOL (WINAPI *FN_SetProcessShutdownParameters)(DWORD, DWORD);
14079b3654SKatayama Hirofumi MZ FN_SetProcessShutdownParameters g_fnSetProcessShutdownParameters = NULL;
15079b3654SKatayama Hirofumi MZ 
16bfa3e554SKatayama Hirofumi MZ // kernel32!GetSystemWow64DirectoryA
17bfa3e554SKatayama Hirofumi MZ typedef UINT (WINAPI *FN_GetSystemWow64DirectoryA)(LPSTR, UINT);
18bfa3e554SKatayama Hirofumi MZ FN_GetSystemWow64DirectoryA g_fnGetSystemWow64DirectoryA = NULL;
19079b3654SKatayama Hirofumi MZ // kernel32!GetSystemWow64DirectoryW
20079b3654SKatayama Hirofumi MZ typedef UINT (WINAPI *FN_GetSystemWow64DirectoryW)(LPWSTR, UINT);
21079b3654SKatayama Hirofumi MZ FN_GetSystemWow64DirectoryW g_fnGetSystemWow64DirectoryW = NULL;
22079b3654SKatayama Hirofumi MZ 
23079b3654SKatayama Hirofumi MZ HINSTANCE   g_hInst         = NULL;     // The application instance
24079b3654SKatayama Hirofumi MZ HINSTANCE   g_hKernel32     = NULL;     // The "kernel32.dll" instance
25079b3654SKatayama Hirofumi MZ UINT        g_uACP          = CP_ACP;   // The active codepage
26079b3654SKatayama Hirofumi MZ BOOL        g_fWinLogon     = FALSE;    // Is it a log-on process?
27079b3654SKatayama Hirofumi MZ HANDLE      g_hCicMutex     = NULL;     // The Cicero mutex
28079b3654SKatayama Hirofumi MZ BOOL        g_bOnWow64      = FALSE;    // Is the app running on WoW64?
29079b3654SKatayama Hirofumi MZ BOOL        g_fNoRunKey     = FALSE;    // Don't write registry key "Run"?
30079b3654SKatayama Hirofumi MZ BOOL        g_fJustRunKey   = FALSE;    // Just write registry key "Run"?
317d6fc57eSKatayama Hirofumi MZ DWORD       g_dwOsInfo      = 0;        // The OS version info. See cicGetOSInfo
32f4460c3fSKatayama Hirofumi MZ CLoaderWnd* g_pLoaderWnd    = NULL;     // Tipbar loader window
33079b3654SKatayama Hirofumi MZ 
34079b3654SKatayama Hirofumi MZ static VOID
ParseCommandLine(_In_ LPCTSTR pszCmdLine)35079b3654SKatayama Hirofumi MZ ParseCommandLine(
36bfa3e554SKatayama Hirofumi MZ     _In_ LPCTSTR pszCmdLine)
37079b3654SKatayama Hirofumi MZ {
38079b3654SKatayama Hirofumi MZ     g_fNoRunKey = g_fJustRunKey = FALSE;
39079b3654SKatayama Hirofumi MZ 
40bfa3e554SKatayama Hirofumi MZ     for (LPCTSTR pch = pszCmdLine; *pch; ++pch)
41079b3654SKatayama Hirofumi MZ     {
42079b3654SKatayama Hirofumi MZ         // Skip space
43bfa3e554SKatayama Hirofumi MZ         while (*pch == TEXT(' '))
44079b3654SKatayama Hirofumi MZ             ++pch;
45079b3654SKatayama Hirofumi MZ 
46bfa3e554SKatayama Hirofumi MZ         if (*pch == TEXT('\0'))
47079b3654SKatayama Hirofumi MZ             return;
48079b3654SKatayama Hirofumi MZ 
49bfa3e554SKatayama Hirofumi MZ         if ((*pch == TEXT('-')) || (*pch == TEXT('/')))
50079b3654SKatayama Hirofumi MZ         {
51079b3654SKatayama Hirofumi MZ             ++pch;
52079b3654SKatayama Hirofumi MZ             switch (*pch)
53079b3654SKatayama Hirofumi MZ             {
54bfa3e554SKatayama Hirofumi MZ                 case TEXT('N'): case TEXT('n'): // Found "/N" option
55079b3654SKatayama Hirofumi MZ                     g_fNoRunKey = TRUE;
56079b3654SKatayama Hirofumi MZ                     break;
57079b3654SKatayama Hirofumi MZ 
58bfa3e554SKatayama Hirofumi MZ                 case TEXT('R'): case TEXT('r'): // Found "/R" option
59079b3654SKatayama Hirofumi MZ                     g_fJustRunKey = TRUE;
60079b3654SKatayama Hirofumi MZ                     break;
61079b3654SKatayama Hirofumi MZ 
62079b3654SKatayama Hirofumi MZ                 case UNICODE_NULL:
63079b3654SKatayama Hirofumi MZ                     return;
64079b3654SKatayama Hirofumi MZ 
65079b3654SKatayama Hirofumi MZ                 default:
66079b3654SKatayama Hirofumi MZ                     break;
67079b3654SKatayama Hirofumi MZ             }
68079b3654SKatayama Hirofumi MZ         }
69079b3654SKatayama Hirofumi MZ     }
70079b3654SKatayama Hirofumi MZ }
71079b3654SKatayama Hirofumi MZ 
72079b3654SKatayama Hirofumi MZ static VOID
WriteRegRun(VOID)73079b3654SKatayama Hirofumi MZ WriteRegRun(VOID)
74079b3654SKatayama Hirofumi MZ {
75079b3654SKatayama Hirofumi MZ     if (g_fNoRunKey) // If "/N" option is specified
76079b3654SKatayama Hirofumi MZ         return; // Don't write
77079b3654SKatayama Hirofumi MZ 
78079b3654SKatayama Hirofumi MZ     // Open "Run" key
79079b3654SKatayama Hirofumi MZ     HKEY hKey;
80bfa3e554SKatayama Hirofumi MZ     LSTATUS error = ::RegCreateKey(HKEY_CURRENT_USER,
81bfa3e554SKatayama Hirofumi MZ                                    TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"),
82079b3654SKatayama Hirofumi MZ                                    &hKey);
83079b3654SKatayama Hirofumi MZ     if (error != ERROR_SUCCESS)
84079b3654SKatayama Hirofumi MZ         return;
85079b3654SKatayama Hirofumi MZ 
86079b3654SKatayama Hirofumi MZ     // Write the module path
877d6fc57eSKatayama Hirofumi MZ     CicSystemModulePath ModPath;
88bfa3e554SKatayama Hirofumi MZ     if (ModPath.Init(TEXT("ctfmon.exe"), FALSE))
89079b3654SKatayama Hirofumi MZ     {
90bfa3e554SKatayama Hirofumi MZ         DWORD cbData = (ModPath.m_cchPath + 1) * sizeof(TCHAR);
91bfa3e554SKatayama Hirofumi MZ         ::RegSetValueEx(hKey, TEXT("ctfmon.exe"), 0, REG_SZ, (BYTE*)ModPath.m_szPath, cbData);
92079b3654SKatayama Hirofumi MZ     }
93079b3654SKatayama Hirofumi MZ 
94079b3654SKatayama Hirofumi MZ     ::RegCloseKey(hKey);
95079b3654SKatayama Hirofumi MZ }
96079b3654SKatayama Hirofumi MZ 
97079b3654SKatayama Hirofumi MZ static HRESULT
GetGlobalCompartment(_In_ REFGUID guid,_Inout_ ITfCompartment ** ppComp)98079b3654SKatayama Hirofumi MZ GetGlobalCompartment(
99079b3654SKatayama Hirofumi MZ     _In_ REFGUID guid,
100079b3654SKatayama Hirofumi MZ     _Inout_ ITfCompartment **ppComp)
101079b3654SKatayama Hirofumi MZ {
102079b3654SKatayama Hirofumi MZ     *ppComp = NULL;
103079b3654SKatayama Hirofumi MZ 
104079b3654SKatayama Hirofumi MZ     ITfCompartmentMgr *pCompMgr = NULL;
105079b3654SKatayama Hirofumi MZ     HRESULT hr = TF_GetGlobalCompartment(&pCompMgr);
106079b3654SKatayama Hirofumi MZ     if (FAILED(hr))
107079b3654SKatayama Hirofumi MZ         return hr;
108079b3654SKatayama Hirofumi MZ 
109079b3654SKatayama Hirofumi MZ     if (!pCompMgr)
110079b3654SKatayama Hirofumi MZ         return E_FAIL;
111079b3654SKatayama Hirofumi MZ 
112079b3654SKatayama Hirofumi MZ     hr = pCompMgr->GetCompartment(guid, ppComp);
113079b3654SKatayama Hirofumi MZ     pCompMgr->Release();
114079b3654SKatayama Hirofumi MZ     return hr;
115079b3654SKatayama Hirofumi MZ }
116079b3654SKatayama Hirofumi MZ 
117079b3654SKatayama Hirofumi MZ static HRESULT
SetGlobalCompartmentDWORD(_In_ REFGUID guid,_In_ DWORD dwValue)118079b3654SKatayama Hirofumi MZ SetGlobalCompartmentDWORD(
119079b3654SKatayama Hirofumi MZ     _In_ REFGUID guid,
120079b3654SKatayama Hirofumi MZ     _In_ DWORD dwValue)
121079b3654SKatayama Hirofumi MZ {
122079b3654SKatayama Hirofumi MZ     HRESULT hr;
123079b3654SKatayama Hirofumi MZ     VARIANT vari;
124079b3654SKatayama Hirofumi MZ     ITfCompartment *pComp;
125079b3654SKatayama Hirofumi MZ 
126079b3654SKatayama Hirofumi MZ     hr = GetGlobalCompartment(guid, &pComp);
127079b3654SKatayama Hirofumi MZ     if (FAILED(hr))
128079b3654SKatayama Hirofumi MZ         return hr;
129079b3654SKatayama Hirofumi MZ 
130079b3654SKatayama Hirofumi MZ     V_VT(&vari) = VT_I4;
131079b3654SKatayama Hirofumi MZ     V_I4(&vari) = dwValue;
132079b3654SKatayama Hirofumi MZ     hr = pComp->SetValue(0, &vari);
133079b3654SKatayama Hirofumi MZ 
134079b3654SKatayama Hirofumi MZ     pComp->Release();
135079b3654SKatayama Hirofumi MZ     return hr;
136079b3654SKatayama Hirofumi MZ }
137079b3654SKatayama Hirofumi MZ 
138079b3654SKatayama Hirofumi MZ static BOOL
CheckX64System(_In_ LPTSTR lpCmdLine)139079b3654SKatayama Hirofumi MZ CheckX64System(
140bfa3e554SKatayama Hirofumi MZ     _In_ LPTSTR lpCmdLine)
141079b3654SKatayama Hirofumi MZ {
142079b3654SKatayama Hirofumi MZ     // Is the system x64?
143079b3654SKatayama Hirofumi MZ     SYSTEM_INFO SystemInfo;
144079b3654SKatayama Hirofumi MZ     ::GetSystemInfo(&SystemInfo);
145079b3654SKatayama Hirofumi MZ     if (SystemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_IA64 ||
146079b3654SKatayama Hirofumi MZ         SystemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_AMD64)
147079b3654SKatayama Hirofumi MZ     {
148079b3654SKatayama Hirofumi MZ         return FALSE;
149079b3654SKatayama Hirofumi MZ     }
150079b3654SKatayama Hirofumi MZ 
151079b3654SKatayama Hirofumi MZ     // Get GetSystemWow64DirectoryW function
152bfa3e554SKatayama Hirofumi MZ     g_hKernel32 = cicGetSystemModuleHandle(TEXT("kernel32.dll"), FALSE);
153bfa3e554SKatayama Hirofumi MZ #ifdef UNICODE
154079b3654SKatayama Hirofumi MZ     g_fnGetSystemWow64DirectoryW =
155079b3654SKatayama Hirofumi MZ         (FN_GetSystemWow64DirectoryW)::GetProcAddress(g_hKernel32, "GetSystemWow64DirectoryW");
156079b3654SKatayama Hirofumi MZ     if (!g_fnGetSystemWow64DirectoryW)
157079b3654SKatayama Hirofumi MZ         return FALSE;
158bfa3e554SKatayama Hirofumi MZ #else
159bfa3e554SKatayama Hirofumi MZ     g_fnGetSystemWow64DirectoryA =
160bfa3e554SKatayama Hirofumi MZ         (FN_GetSystemWow64DirectoryA)::GetProcAddress(g_hKernel32, "GetSystemWow64DirectoryA");
161bfa3e554SKatayama Hirofumi MZ     if (!g_fnGetSystemWow64DirectoryA)
162bfa3e554SKatayama Hirofumi MZ         return FALSE;
163bfa3e554SKatayama Hirofumi MZ #endif
164079b3654SKatayama Hirofumi MZ 
165079b3654SKatayama Hirofumi MZ     // Build WoW64 ctfmon.exe pathname
166bfa3e554SKatayama Hirofumi MZ     TCHAR szPath[MAX_PATH];
167bfa3e554SKatayama Hirofumi MZ #ifdef UNICODE
168079b3654SKatayama Hirofumi MZ     UINT cchPath = g_fnGetSystemWow64DirectoryW(szPath, _countof(szPath));
169bfa3e554SKatayama Hirofumi MZ #else
170bfa3e554SKatayama Hirofumi MZ     UINT cchPath = g_fnGetSystemWow64DirectoryA(szPath, _countof(szPath));
171bfa3e554SKatayama Hirofumi MZ #endif
172bfa3e554SKatayama Hirofumi MZ     if (!cchPath && FAILED(StringCchCat(szPath, _countof(szPath), TEXT("\\ctfmon.exe"))))
173079b3654SKatayama Hirofumi MZ         return FALSE;
174079b3654SKatayama Hirofumi MZ 
175079b3654SKatayama Hirofumi MZ     // Create a WoW64 ctfmon.exe process
176079b3654SKatayama Hirofumi MZ     PROCESS_INFORMATION pi;
177bfa3e554SKatayama Hirofumi MZ     STARTUPINFO si = { sizeof(si) };
178079b3654SKatayama Hirofumi MZ     si.wShowWindow = SW_SHOWMINNOACTIVE;
179bfa3e554SKatayama Hirofumi MZ     if (!::CreateProcess(szPath, lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
180079b3654SKatayama Hirofumi MZ         return FALSE;
181079b3654SKatayama Hirofumi MZ 
182079b3654SKatayama Hirofumi MZ     ::CloseHandle(pi.hThread);
183079b3654SKatayama Hirofumi MZ     ::CloseHandle(pi.hProcess);
184079b3654SKatayama Hirofumi MZ     return TRUE;
185079b3654SKatayama Hirofumi MZ }
186079b3654SKatayama Hirofumi MZ 
187079b3654SKatayama Hirofumi MZ static BOOL
InitApp(_In_ HINSTANCE hInstance,_In_ LPTSTR lpCmdLine)188079b3654SKatayama Hirofumi MZ InitApp(
189079b3654SKatayama Hirofumi MZ     _In_ HINSTANCE hInstance,
190bfa3e554SKatayama Hirofumi MZ     _In_ LPTSTR lpCmdLine)
191079b3654SKatayama Hirofumi MZ {
192079b3654SKatayama Hirofumi MZ     g_hInst     = hInstance;    // Save the instance handle
193079b3654SKatayama Hirofumi MZ 
1947d6fc57eSKatayama Hirofumi MZ     g_bOnWow64  = cicIsWow64();   // Is the current process on WoW64?
195c4308d1eSKatayama Hirofumi MZ     cicGetOSInfo(&g_uACP, &g_dwOsInfo); // Get OS info
196079b3654SKatayama Hirofumi MZ 
197079b3654SKatayama Hirofumi MZ     // Create a mutex for Cicero
198079b3654SKatayama Hirofumi MZ     g_hCicMutex = TF_CreateCicLoadMutex(&g_fWinLogon);
199079b3654SKatayama Hirofumi MZ     if (!g_hCicMutex)
200079b3654SKatayama Hirofumi MZ         return FALSE;
201079b3654SKatayama Hirofumi MZ 
202079b3654SKatayama Hirofumi MZ     // Write to "Run" registry key for starting up
203079b3654SKatayama Hirofumi MZ     WriteRegRun();
204079b3654SKatayama Hirofumi MZ 
205079b3654SKatayama Hirofumi MZ     // Call SetProcessShutdownParameters if possible
206c4308d1eSKatayama Hirofumi MZ     if (g_dwOsInfo & CIC_OSINFO_NT)
207079b3654SKatayama Hirofumi MZ     {
208bfa3e554SKatayama Hirofumi MZ         g_hKernel32 = cicGetSystemModuleHandle(TEXT("kernel32.dll"), FALSE);
209079b3654SKatayama Hirofumi MZ         g_fnSetProcessShutdownParameters =
210079b3654SKatayama Hirofumi MZ             (FN_SetProcessShutdownParameters)
211079b3654SKatayama Hirofumi MZ                 ::GetProcAddress(g_hKernel32, "SetProcessShutdownParameters");
212079b3654SKatayama Hirofumi MZ         if (g_fnSetProcessShutdownParameters)
213079b3654SKatayama Hirofumi MZ             g_fnSetProcessShutdownParameters(0xF0, SHUTDOWN_NORETRY);
214079b3654SKatayama Hirofumi MZ     }
215079b3654SKatayama Hirofumi MZ 
216079b3654SKatayama Hirofumi MZ     // Start text framework
217079b3654SKatayama Hirofumi MZ     TF_InitSystem();
218079b3654SKatayama Hirofumi MZ 
219079b3654SKatayama Hirofumi MZ     // Start watching registry if x86/x64 native
220079b3654SKatayama Hirofumi MZ     if (!g_bOnWow64)
221079b3654SKatayama Hirofumi MZ         CRegWatcher::Init();
222079b3654SKatayama Hirofumi MZ 
223f4460c3fSKatayama Hirofumi MZ     // Create Tipbar loader window
224*b48e77e1SKatayama Hirofumi MZ     g_pLoaderWnd = new(cicNoThrow) CLoaderWnd();
225079b3654SKatayama Hirofumi MZ     if (!g_pLoaderWnd || !g_pLoaderWnd->Init())
226079b3654SKatayama Hirofumi MZ         return FALSE;
227079b3654SKatayama Hirofumi MZ 
228079b3654SKatayama Hirofumi MZ     if (g_pLoaderWnd->CreateWnd())
229079b3654SKatayama Hirofumi MZ     {
230079b3654SKatayama Hirofumi MZ         // Go to the bottom of the hell
231079b3654SKatayama Hirofumi MZ         ::SetWindowPos(g_pLoaderWnd->m_hWnd, HWND_BOTTOM, 0, 0, 0, 0,
232079b3654SKatayama Hirofumi MZ                        SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
233079b3654SKatayama Hirofumi MZ     }
234079b3654SKatayama Hirofumi MZ 
235f4460c3fSKatayama Hirofumi MZ     // Display Tipbar Popup if x86/x64 native and necessary
236079b3654SKatayama Hirofumi MZ     if (!g_bOnWow64)
237079b3654SKatayama Hirofumi MZ         GetPopupTipbar(g_pLoaderWnd->m_hWnd, g_fWinLogon);
238079b3654SKatayama Hirofumi MZ 
239079b3654SKatayama Hirofumi MZ     // Do x64 stuffs
240079b3654SKatayama Hirofumi MZ     CheckX64System(lpCmdLine);
241079b3654SKatayama Hirofumi MZ 
242079b3654SKatayama Hirofumi MZ     return TRUE;
243079b3654SKatayama Hirofumi MZ }
244079b3654SKatayama Hirofumi MZ 
245079b3654SKatayama Hirofumi MZ VOID
UninitApp(VOID)246079b3654SKatayama Hirofumi MZ UninitApp(VOID)
247079b3654SKatayama Hirofumi MZ {
248f4460c3fSKatayama Hirofumi MZ     // Close Tipbar Popup
249079b3654SKatayama Hirofumi MZ     ClosePopupTipbar();
250079b3654SKatayama Hirofumi MZ 
251079b3654SKatayama Hirofumi MZ     // Close the mutex
252079b3654SKatayama Hirofumi MZ     ::CloseHandle(g_hCicMutex);
253079b3654SKatayama Hirofumi MZ     g_hCicMutex = NULL;
254079b3654SKatayama Hirofumi MZ 
255079b3654SKatayama Hirofumi MZ     // Quit watching registry if x86/x64 native
256079b3654SKatayama Hirofumi MZ     if (!g_bOnWow64)
257079b3654SKatayama Hirofumi MZ         CRegWatcher::Uninit();
258079b3654SKatayama Hirofumi MZ }
259079b3654SKatayama Hirofumi MZ 
260079b3654SKatayama Hirofumi MZ static INT
DoMainLoop(VOID)261079b3654SKatayama Hirofumi MZ DoMainLoop(VOID)
262079b3654SKatayama Hirofumi MZ {
263079b3654SKatayama Hirofumi MZ     MSG msg;
264079b3654SKatayama Hirofumi MZ 
265079b3654SKatayama Hirofumi MZ     if (g_bOnWow64) // Is the current process on WoW64?
266079b3654SKatayama Hirofumi MZ     {
267079b3654SKatayama Hirofumi MZ         // Just a simple message loop
268bfa3e554SKatayama Hirofumi MZ         while (::GetMessage(&msg, NULL, 0, 0))
269079b3654SKatayama Hirofumi MZ         {
270079b3654SKatayama Hirofumi MZ             ::TranslateMessage(&msg);
271bfa3e554SKatayama Hirofumi MZ             ::DispatchMessage(&msg);
272079b3654SKatayama Hirofumi MZ         }
273079b3654SKatayama Hirofumi MZ         return (INT)msg.wParam;
274079b3654SKatayama Hirofumi MZ     }
275079b3654SKatayama Hirofumi MZ 
276079b3654SKatayama Hirofumi MZ     // Open the existing event by the name
277bfa3e554SKatayama Hirofumi MZ     HANDLE hSwitchEvent = ::OpenEvent(SYNCHRONIZE, FALSE, TEXT("WinSta0_DesktopSwitch"));
278079b3654SKatayama Hirofumi MZ 
279079b3654SKatayama Hirofumi MZ     // The target events to watch
280079b3654SKatayama Hirofumi MZ     HANDLE ahEvents[WATCHENTRY_MAX + 1];
281079b3654SKatayama Hirofumi MZ 
282079b3654SKatayama Hirofumi MZ     // Borrow some handles from CRegWatcher
283079b3654SKatayama Hirofumi MZ     CopyMemory(ahEvents, CRegWatcher::s_ahWatchEvents, WATCHENTRY_MAX * sizeof(HANDLE));
284079b3654SKatayama Hirofumi MZ 
285079b3654SKatayama Hirofumi MZ     ahEvents[WI_DESKTOP_SWITCH] = hSwitchEvent; // Add it
286079b3654SKatayama Hirofumi MZ 
287079b3654SKatayama Hirofumi MZ     // Another message loop
288079b3654SKatayama Hirofumi MZ     for (;;)
289079b3654SKatayama Hirofumi MZ     {
290079b3654SKatayama Hirofumi MZ         // Wait for target signal
291079b3654SKatayama Hirofumi MZ         DWORD dwWait = ::MsgWaitForMultipleObjects(_countof(ahEvents), ahEvents, 0, INFINITE,
292079b3654SKatayama Hirofumi MZ                                                    QS_ALLINPUT);
293079b3654SKatayama Hirofumi MZ         if (dwWait == (WAIT_OBJECT_0 + _countof(ahEvents))) // Is input available?
294079b3654SKatayama Hirofumi MZ         {
295079b3654SKatayama Hirofumi MZ             // Do the events
296bfa3e554SKatayama Hirofumi MZ             while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
297079b3654SKatayama Hirofumi MZ             {
298079b3654SKatayama Hirofumi MZ                 if (msg.message == WM_QUIT)
299079b3654SKatayama Hirofumi MZ                     goto Quit;
300079b3654SKatayama Hirofumi MZ 
301079b3654SKatayama Hirofumi MZ                 ::TranslateMessage(&msg);
302bfa3e554SKatayama Hirofumi MZ                 ::DispatchMessage(&msg);
303079b3654SKatayama Hirofumi MZ             }
304079b3654SKatayama Hirofumi MZ         }
305079b3654SKatayama Hirofumi MZ         else if (dwWait == (WAIT_OBJECT_0 + WI_DESKTOP_SWITCH)) // Desktop switch?
306079b3654SKatayama Hirofumi MZ         {
307079b3654SKatayama Hirofumi MZ             SetGlobalCompartmentDWORD(GUID_COMPARTMENT_SPEECH_OPENCLOSE, 0);
308079b3654SKatayama Hirofumi MZ             ::ResetEvent(hSwitchEvent);
309079b3654SKatayama Hirofumi MZ         }
310079b3654SKatayama Hirofumi MZ         else // Do the other events
311079b3654SKatayama Hirofumi MZ         {
312079b3654SKatayama Hirofumi MZ             CRegWatcher::OnEvent(dwWait - WAIT_OBJECT_0);
313079b3654SKatayama Hirofumi MZ         }
314079b3654SKatayama Hirofumi MZ     }
315079b3654SKatayama Hirofumi MZ 
316079b3654SKatayama Hirofumi MZ Quit:
317079b3654SKatayama Hirofumi MZ     ::CloseHandle(hSwitchEvent);
318079b3654SKatayama Hirofumi MZ 
319079b3654SKatayama Hirofumi MZ     return (INT)msg.wParam;
320079b3654SKatayama Hirofumi MZ }
321079b3654SKatayama Hirofumi MZ 
322079b3654SKatayama Hirofumi MZ // The main function for Unicode Win32
323079b3654SKatayama Hirofumi MZ EXTERN_C INT WINAPI
_tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInst,LPTSTR lpCmdLine,INT nCmdShow)324bfa3e554SKatayama Hirofumi MZ _tWinMain(
325079b3654SKatayama Hirofumi MZ     HINSTANCE hInstance,
326079b3654SKatayama Hirofumi MZ     HINSTANCE hPrevInst,
327bfa3e554SKatayama Hirofumi MZ     LPTSTR lpCmdLine,
328079b3654SKatayama Hirofumi MZ     INT nCmdShow)
329079b3654SKatayama Hirofumi MZ {
330079b3654SKatayama Hirofumi MZ     UNREFERENCED_PARAMETER(hPrevInst);
331079b3654SKatayama Hirofumi MZ     UNREFERENCED_PARAMETER(nCmdShow);
332079b3654SKatayama Hirofumi MZ 
333079b3654SKatayama Hirofumi MZ     // Parse command line
334079b3654SKatayama Hirofumi MZ     ParseCommandLine(lpCmdLine);
335079b3654SKatayama Hirofumi MZ 
336079b3654SKatayama Hirofumi MZ     if (g_fJustRunKey) // If "/R" option is specified
337079b3654SKatayama Hirofumi MZ     {
338079b3654SKatayama Hirofumi MZ         // Just write registry and exit
339079b3654SKatayama Hirofumi MZ         WriteRegRun();
340079b3654SKatayama Hirofumi MZ         return 1;
341079b3654SKatayama Hirofumi MZ     }
342079b3654SKatayama Hirofumi MZ 
343079b3654SKatayama Hirofumi MZ     // Initialize the application
344079b3654SKatayama Hirofumi MZ     if (!InitApp(hInstance, lpCmdLine))
345079b3654SKatayama Hirofumi MZ         return 0;
346079b3654SKatayama Hirofumi MZ 
347079b3654SKatayama Hirofumi MZ     // The main loop
348079b3654SKatayama Hirofumi MZ     INT ret = DoMainLoop();
349079b3654SKatayama Hirofumi MZ 
350079b3654SKatayama Hirofumi MZ     // Clean up the loader
351079b3654SKatayama Hirofumi MZ     if (g_pLoaderWnd)
352079b3654SKatayama Hirofumi MZ     {
353079b3654SKatayama Hirofumi MZ         delete g_pLoaderWnd;
354079b3654SKatayama Hirofumi MZ         g_pLoaderWnd = NULL;
355079b3654SKatayama Hirofumi MZ     }
356079b3654SKatayama Hirofumi MZ 
357079b3654SKatayama Hirofumi MZ     // Un-initialize app and text framework
358079b3654SKatayama Hirofumi MZ     if (!CLoaderWnd::s_bUninitedSystem)
359079b3654SKatayama Hirofumi MZ     {
360079b3654SKatayama Hirofumi MZ         UninitApp();
361079b3654SKatayama Hirofumi MZ         TF_UninitSystem();
362079b3654SKatayama Hirofumi MZ     }
363079b3654SKatayama Hirofumi MZ 
364079b3654SKatayama Hirofumi MZ     return ret;
365079b3654SKatayama Hirofumi MZ }
366