ReactOS 0.4.16-dev-1946-g52006dd
CRegWatcher.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS CTF Monitor
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Registry watcher
5 * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#include "precomp.h"
9#include "CRegWatcher.h"
10#include <ime/indicml.h>
11
12// The event handles to use in watching
14
15// The registry entries to watch
17{
18 { HKEY_CURRENT_USER, TEXT("Keyboard Layout\\Toggle") }, // WI_TOGGLE
19 { HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\CTF\\TIP") }, // WI_MACHINE_TIF
20 { HKEY_CURRENT_USER, TEXT("Keyboard Layout\\Preload") }, // WI_PRELOAD
21 { HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run") }, // WI_RUN
22 { HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\TIP") }, // WI_USER_TIF
23 { HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Speech") }, // WI_USER_SPEECH
24 { HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance") }, // WI_APPEARANCE
25 { HKEY_CURRENT_USER, TEXT("Control Panel\\Colors") }, // WI_COLORS
26 { HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop\\WindowMetrics") }, // WI_WINDOW_METRICS
27 { HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Speech") }, // WI_MACHINE_SPEECH
28 { HKEY_CURRENT_USER, TEXT("Keyboard Layout") }, // WI_KEYBOARD_LAYOUT
29 { HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\Assemblies") }, // WI_ASSEMBLIES
30};
31
32// The timer IDs: For delaying ignitions
36
37// %WINDIR%/IME/sptip.dll!TF_CreateLangProfileUtil
39
40BOOL
42{
43 // NOTE: We don't support Win95/98/Me
44#ifdef SUPPORT_WIN9X
47#endif
48
49 // Create some nameless events and initialize them
50 for (SIZE_T iEvent = 0; iEvent < _countof(s_ahWatchEvents); ++iEvent)
51 {
53 InitEvent(iEvent, FALSE);
54 }
55
56 // Internat.exe is an enemy of ctfmon.exe
58
60
61 return TRUE;
62}
63
64VOID
66{
67 for (SIZE_T iEvent = 0; iEvent < _countof(s_ahWatchEvents); ++iEvent)
68 {
69 // Close the key
71 if (entry.hKey)
72 {
73 ::RegCloseKey(entry.hKey);
74 entry.hKey = NULL;
75 }
76
77 // Close the event handle
78 HANDLE& hEvent = s_ahWatchEvents[iEvent];
79 if (hEvent)
80 {
82 hEvent = NULL;
83 }
84 }
85}
86
87// advapi32!RegNotifyChangeKeyValue
89
92 HKEY hKey,
93 BOOL bWatchSubtree,
94 DWORD dwNotifyFilter,
96 BOOL fAsynchronous)
97{
98 static FN_RegNotifyChangeKeyValue s_fnRegNotifyChangeKeyValue = NULL;
99
100 if (!s_fnRegNotifyChangeKeyValue)
101 {
102 HINSTANCE hAdvApi32 = cicGetSystemModuleHandle(TEXT("advapi32.dll"), FALSE);
103 s_fnRegNotifyChangeKeyValue =
104 (FN_RegNotifyChangeKeyValue)GetProcAddress(hAdvApi32, "RegNotifyChangeKeyValue");
105 if (!s_fnRegNotifyChangeKeyValue)
107 }
108
109 return s_fnRegNotifyChangeKeyValue(hKey, bWatchSubtree, dwNotifyFilter, hEvent, fAsynchronous);
110}
111
112BOOL
114 _In_ SIZE_T iEvent,
115 _In_ BOOL bResetEvent)
116{
117 if (iEvent >= _countof(s_ahWatchEvents))
118 return FALSE;
119
120 // Reset the signal status
121 if (bResetEvent)
123
124 // Close once to re-open
126 if (entry.hKey)
127 {
128 ::RegCloseKey(entry.hKey);
129 entry.hKey = NULL;
130 }
131
132 // Open or create a registry key to watch registry key
134 error = ::RegOpenKeyEx(entry.hRootKey, entry.pszSubKey, 0, KEY_READ, &entry.hKey);
135 if (error != ERROR_SUCCESS)
136 {
137 error = ::RegCreateKeyEx(entry.hRootKey, entry.pszSubKey, 0, NULL, 0,
138 KEY_ALL_ACCESS, NULL, &entry.hKey, NULL);
139 if (error != ERROR_SUCCESS)
140 return FALSE;
141 }
142
143 // Start registry watching
145 TRUE,
147 s_ahWatchEvents[iEvent],
148 TRUE);
149#ifndef NDEBUG
150 if (error != ERROR_SUCCESS)
151 OutputDebugStringA("RegNotifyChangeKeyValue failed\n");
152#endif
153 return error == ERROR_SUCCESS;
154}
155
156VOID
158{
159 // Post message 0x8002 to "SapiTipWorkerClass" windows
161
162 // Clear "ProfileInitialized" value
163 HKEY hKey;
165 TEXT("SOFTWARE\\Microsoft\\CTF\\Sapilayr"),
166 0, KEY_WRITE, &hKey);
167 if (error == ERROR_SUCCESS)
168 {
169 DWORD dwValue = 0, cbValue = sizeof(dwValue);
170 ::RegSetValueEx(hKey, TEXT("ProfileInitialized"), NULL, REG_DWORD, (LPBYTE)&dwValue, cbValue);
172 }
173
174 // Get %WINDIR%/IME/sptip.dll!TF_CreateLangProfileUtil function
175 HINSTANCE hSPTIP = cicLoadSystemLibrary(TEXT("IME\\sptip.dll"), TRUE);
176 FN_TF_CreateLangProfileUtil fnTF_CreateLangProfileUtil =
177 (FN_TF_CreateLangProfileUtil)::GetProcAddress(hSPTIP, "TF_CreateLangProfileUtil");
178 if (fnTF_CreateLangProfileUtil)
179 {
180 // Call it
181 ITfFnLangProfileUtil *pProfileUtil = NULL;
182 HRESULT hr = fnTF_CreateLangProfileUtil(&pProfileUtil);
183 if ((hr == S_OK) && pProfileUtil) // Success!
184 {
185 // Register profile
186 hr = pProfileUtil->RegisterActiveProfiles();
187 if (hr == S_OK)
188 TF_InvalidAssemblyListCacheIfExist(); // Invalidate the assembly list cache
189
190 pProfileUtil->Release();
191 }
192 }
193
194 if (hSPTIP)
195 ::FreeLibrary(hSPTIP);
196}
197
198VOID
200{
201 HKEY hKey;
203
204 // Delete internat.exe from registry "Run" key
205 LSTATUS error = ::RegOpenKeyEx(entry.hRootKey, entry.pszSubKey, 0, KEY_ALL_ACCESS, &hKey);
206 if (error == ERROR_SUCCESS)
207 {
208 ::RegDeleteValue(hKey, TEXT("internat.exe"));
210 }
211
212 // Kill the "Indicator" window (that internat.exe creates)
213 HWND hwndInternat = ::FindWindow(INDICATOR_CLASS, NULL);
214 if (hwndInternat)
215 ::PostMessage(hwndInternat, WM_CLOSE, 0, 0);
216}
217
218// Post message 0x8002 to every "SapiTipWorkerClass" window.
219// Called from CRegWatcher::UpdateSpTip
222 _In_ HWND hWnd,
224{
225 TCHAR ClassName[MAX_PATH];
226
228
229 if (::GetClassName(hWnd, ClassName, _countof(ClassName)) &&
230 _tcsicmp(ClassName, TEXT("SapiTipWorkerClass")) == 0)
231 {
232 PostMessage(hWnd, 0x8002, 0, 0); // FIXME: Magic number
233 }
234
235 return TRUE;
236}
237
240 _In_ HWND hwnd,
241 _In_ UINT uMsg,
242 _In_ UINT_PTR idEvent,
244{
247 UNREFERENCED_PARAMETER(idEvent);
249
250 // Cancel the timer
252 {
255 }
256
257 TF_PostAllThreadMsg(15, 16);
258}
259
260VOID
262{
263 // Call SysColorTimerProc 0.5 seconds later (Delayed)
265 {
268 }
270}
271
274 _In_ HWND hwnd,
275 _In_ UINT uMsg,
276 _In_ UINT_PTR idEvent,
278{
281 UNREFERENCED_PARAMETER(idEvent);
283
284 // Cancel the timer
286 {
289 }
290
292 TF_PostAllThreadMsg(12, 16);
293}
294
297 _In_ HWND hwnd,
298 _In_ UINT uMsg,
299 _In_ UINT_PTR idEvent,
301{
304 UNREFERENCED_PARAMETER(idEvent);
306
307 // Cancel the timer
309 {
312 }
313
314 TF_PostAllThreadMsg(11, 16);
315}
316
317VOID
319 _In_ SIZE_T iEvent)
320{
321 if (iEvent >= _countof(s_ahWatchEvents))
322 return;
323
324 InitEvent(iEvent, TRUE);
325
326 switch (iEvent)
327 {
328 case WI_TOGGLE:
329 {
330 // Call KbdToggleTimerProc 0.5 seconds later (Delayed)
332 {
335 }
337 break;
338 }
339 case WI_MACHINE_TIF:
340 case WI_PRELOAD:
341 case WI_USER_TIF:
344 case WI_ASSEMBLIES:
345 {
346 if (iEvent == WI_MACHINE_SPEECH)
347 UpdateSpTip();
348
349 // Call RegImxTimerProc 0.2 seconds later (Delayed)
351 {
354 }
356 break;
357 }
358 case WI_RUN: // The "Run" key is changed
359 {
360 KillInternat(); // Deny internat.exe the right to live
361 break;
362 }
363 case WI_USER_SPEECH:
364 case WI_APPEARANCE:
365 case WI_COLORS:
367 {
369 break;
370 }
371 default:
372 {
373 break;
374 }
375 }
376}
HRESULT(WINAPI * FN_TF_CreateLangProfileUtil)(ITfFnLangProfileUtil **)
Definition: CRegWatcher.cpp:38
LONG WINAPI DelayedRegNotifyChangeKeyValue(HKEY hKey, BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL fAsynchronous)
Definition: CRegWatcher.cpp:91
LONG(WINAPI * FN_RegNotifyChangeKeyValue)(HKEY, BOOL, DWORD, HANDLE, BOOL)
Definition: CRegWatcher.cpp:88
HWND hWnd
Definition: settings.c:17
@ WI_ASSEMBLIES
Definition: precomp.h:46
@ WI_APPEARANCE
Definition: precomp.h:41
@ WI_COLORS
Definition: precomp.h:42
@ WI_MACHINE_TIF
Definition: precomp.h:36
@ WI_WINDOW_METRICS
Definition: precomp.h:43
@ WI_TOGGLE
Definition: precomp.h:35
@ WI_RUN
Definition: precomp.h:38
@ WI_USER_TIF
Definition: precomp.h:39
@ WI_REGEVTS_MAX
Definition: precomp.h:47
@ WI_PRELOAD
Definition: precomp.h:37
@ WI_MACHINE_SPEECH
Definition: precomp.h:44
@ WI_KEYBOARD_LAYOUT
Definition: precomp.h:45
@ WI_USER_SPEECH
Definition: precomp.h:40
EXTERN_C HRESULT WINAPI TF_InvalidAssemblyListCache(VOID)
Definition: utils.cpp:408
EXTERN_C HRESULT WINAPI TF_PostAllThreadMsg(_In_opt_ WPARAM wParam, _In_ DWORD dwFlags)
Definition: utils.cpp:432
#define RegCloseKey(hKey)
Definition: registry.h:49
HANDLE HKEY
Definition: registry.h:26
EXTERN_C HINSTANCE cicLoadSystemLibrary(_In_ LPCTSTR pszFileName, _In_ BOOL bSysWinDir)
Definition: cicbase.cpp:162
EXTERN_C HINSTANCE cicGetSystemModuleHandle(_In_ LPCTSTR pszFileName, _In_ BOOL bSysWinDir)
Definition: cicbase.cpp:149
#define CIC_OSINFO_NT
Definition: cicbase.h:56
LPARAM lParam
Definition: combotst.c:139
DWORD g_dwOsInfo
Definition: ctfmon.cpp:31
#define ERROR_SUCCESS
Definition: deptool.c:10
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
#define MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
void WINAPI SHIM_OBJ_NAME() OutputDebugStringA(LPCSTR lpOutputString)
Definition: ignoredbgout.c:18
#define INDICATOR_CLASS
Definition: indicml.h:19
HRESULT RegisterActiveProfiles(void)
ULONG Release()
#define S_OK
Definition: intsafe.h:52
uint32_t entry
Definition: isohybrid.c:63
#define TEXT(s)
Definition: k32.h:28
LONG_PTR LPARAM
Definition: minwindef.h:175
#define error(str)
Definition: mkdosfs.c:1605
static HANDLE hEvent
Definition: comm.c:54
HRESULT WINAPI TF_InvalidAssemblyListCacheIfExist(void)
Definition: msctf.cpp:660
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
unsigned int UINT
Definition: ndis.h:50
#define _In_
Definition: no_sal2.h:158
#define KEY_ALL_ACCESS
Definition: nt_native.h:1044
#define KEY_READ
Definition: nt_native.h:1026
#define BOOL
Definition: nt_native.h:43
#define KEY_WRITE
Definition: nt_native.h:1034
#define DWORD
Definition: nt_native.h:44
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
long LONG
Definition: pedump.c:60
#define REG_DWORD
Definition: sdbapi.c:615
HRESULT hr
Definition: shlfolder.c:183
#define _countof(array)
Definition: sndvol32.h:70
DWORD dwTime
Definition: solitaire.cpp:27
static BOOL InitEvent(_In_ SIZE_T iEvent, _In_ BOOL bResetEvent)
static UINT s_nSysColorTimerId
Definition: CRegWatcher.h:21
static BOOL Init()
Definition: CRegWatcher.cpp:41
static VOID CALLBACK SysColorTimerProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ UINT_PTR idEvent, _In_ DWORD dwTime)
static VOID OnEvent(_In_ SIZE_T iEvent)
static VOID UpdateSpTip()
static VOID StartSysColorChangeTimer()
static VOID KillInternat()
static BOOL CALLBACK EnumWndProc(_In_ HWND hWnd, _In_ LPARAM lParam)
static VOID CALLBACK RegImxTimerProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ UINT_PTR idEvent, _In_ DWORD dwTime)
static WATCHENTRY s_WatchEntries[WI_REGEVTS_MAX]
Definition: CRegWatcher.h:20
static VOID Uninit()
Definition: CRegWatcher.cpp:65
static HANDLE s_ahWatchEvents[WI_REGEVTS_MAX]
Definition: CRegWatcher.h:19
static UINT s_nRegImxTimerId
Definition: CRegWatcher.h:21
static VOID CALLBACK KbdToggleTimerProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ UINT_PTR idEvent, _In_ DWORD dwTime)
static UINT s_nKbdToggleTimerId
Definition: CRegWatcher.h:21
HKEY hRootKey
Definition: CRegWatcher.h:12
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
unsigned char * LPBYTE
Definition: typedefs.h:53
PVOID HANDLE
Definition: typedefs.h:73
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define CreateEvent
Definition: winbase.h:3497
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define RegOpenKeyEx
Definition: winreg.h:527
#define RegSetValueEx
Definition: winreg.h:540
#define RegCreateKeyEx
Definition: winreg.h:508
#define REG_NOTIFY_CHANGE_NAME
Definition: winreg.h:38
#define REG_NOTIFY_CHANGE_LAST_SET
Definition: winreg.h:40
#define RegDeleteValue
Definition: winreg.h:515
#define WM_CLOSE
Definition: winuser.h:1649
#define FindWindow
Definition: winuser.h:5888
#define GetClassName
Definition: winuser.h:5894
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
BOOL WINAPI EnumWindows(_In_ WNDENUMPROC lpEnumFunc, _In_ LPARAM lParam)
#define PostMessage
Definition: winuser.h:5943
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
char TCHAR
Definition: xmlstorage.h:189
#define _tcsicmp
Definition: xmlstorage.h:205