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