ReactOS 0.4.15-dev-8236-g99f0937
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
11// The event handles to use in watching
13
14// The registry entries to watch
16{
17 { HKEY_CURRENT_USER, TEXT("Keyboard Layout\\Toggle") }, // WI_TOGGLE
18 { HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\CTF\\TIP") }, // WI_MACHINE_TIF
19 { HKEY_CURRENT_USER, TEXT("Keyboard Layout\\Preload") }, // WI_PRELOAD
20 { HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run") }, // WI_RUN
21 { HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\TIP") }, // WI_USER_TIF
22 { HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Speech") }, // WI_USER_SPEECH
23 { HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance") }, // WI_APPEARANCE
24 { HKEY_CURRENT_USER, TEXT("Control Panel\\Colors") }, // WI_COLORS
25 { HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop\\WindowMetrics") }, // WI_WINDOW_METRICS
26 { HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Speech") }, // WI_MACHINE_SPEECH
27 { HKEY_CURRENT_USER, TEXT("Keyboard Layout") }, // WI_KEYBOARD_LAYOUT
28 { HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\CTF\\Assemblies") }, // WI_ASSEMBLIES
29};
30
31// The timer IDs: For delaying ignitions
35
36// %WINDIR%/IME/sptip.dll!TF_CreateLangProfileUtil
38
39BOOL
41{
42 // NOTE: We don't support Win95/98/Me
43#ifdef SUPPORT_WIN9X
46#endif
47
48 // Create some nameless events and initialize them
49 for (SIZE_T iEvent = 0; iEvent < _countof(s_ahWatchEvents); ++iEvent)
50 {
52 InitEvent(iEvent, FALSE);
53 }
54
55 // Internat.exe is an enemy of ctfmon.exe
57
59
60 return TRUE;
61}
62
63VOID
65{
66 for (SIZE_T iEvent = 0; iEvent < _countof(s_ahWatchEvents); ++iEvent)
67 {
68 // Close the key
70 if (entry.hKey)
71 {
72 ::RegCloseKey(entry.hKey);
73 entry.hKey = NULL;
74 }
75
76 // Close the event handle
77 HANDLE& hEvent = s_ahWatchEvents[iEvent];
78 if (hEvent)
79 {
81 hEvent = NULL;
82 }
83 }
84}
85
86// advapi32!RegNotifyChangeKeyValue
88
91 HKEY hKey,
92 BOOL bWatchSubtree,
93 DWORD dwNotifyFilter,
95 BOOL fAsynchronous)
96{
97 static FN_RegNotifyChangeKeyValue s_fnRegNotifyChangeKeyValue = NULL;
98
99 if (!s_fnRegNotifyChangeKeyValue)
100 {
101 HINSTANCE hAdvApi32 = cicGetSystemModuleHandle(TEXT("advapi32.dll"), FALSE);
102 s_fnRegNotifyChangeKeyValue =
103 (FN_RegNotifyChangeKeyValue)GetProcAddress(hAdvApi32, "RegNotifyChangeKeyValue");
104 if (!s_fnRegNotifyChangeKeyValue)
106 }
107
108 return s_fnRegNotifyChangeKeyValue(hKey, bWatchSubtree, dwNotifyFilter, hEvent, fAsynchronous);
109}
110
111BOOL
113 _In_ SIZE_T iEvent,
114 _In_ BOOL bResetEvent)
115{
116 // Reset the signal status
117 if (bResetEvent)
119
120 // Close once to re-open
122 if (entry.hKey)
123 {
124 ::RegCloseKey(entry.hKey);
125 entry.hKey = NULL;
126 }
127
128 // Open or create a registry key to watch registry key
130 error = ::RegOpenKeyEx(entry.hRootKey, entry.pszSubKey, 0, KEY_READ, &entry.hKey);
131 if (error != ERROR_SUCCESS)
132 {
133 error = ::RegCreateKeyEx(entry.hRootKey, entry.pszSubKey, 0, NULL, 0,
134 KEY_ALL_ACCESS, NULL, &entry.hKey, NULL);
135 if (error != ERROR_SUCCESS)
136 return FALSE;
137 }
138
139 // Start registry watching
141 TRUE,
143 s_ahWatchEvents[iEvent],
144 TRUE);
145#ifndef NDEBUG
146 if (error != ERROR_SUCCESS)
147 OutputDebugStringA("RegNotifyChangeKeyValue failed\n");
148#endif
149 return error == ERROR_SUCCESS;
150}
151
152VOID
154{
155 // Post message 0x8002 to "SapiTipWorkerClass" windows
157
158 // Clear "ProfileInitialized" value
159 HKEY hKey;
161 TEXT("SOFTWARE\\Microsoft\\CTF\\Sapilayr"),
162 0, KEY_WRITE, &hKey);
163 if (error == ERROR_SUCCESS)
164 {
165 DWORD dwValue = 0, cbValue = sizeof(dwValue);
166 ::RegSetValueEx(hKey, TEXT("ProfileInitialized"), NULL, REG_DWORD, (LPBYTE)&dwValue, cbValue);
168 }
169
170 // Get %WINDIR%/IME/sptip.dll!TF_CreateLangProfileUtil function
171 HINSTANCE hSPTIP = cicLoadSystemLibrary(TEXT("IME\\sptip.dll"), TRUE);
172 FN_TF_CreateLangProfileUtil fnTF_CreateLangProfileUtil =
173 (FN_TF_CreateLangProfileUtil)::GetProcAddress(hSPTIP, "TF_CreateLangProfileUtil");
174 if (fnTF_CreateLangProfileUtil)
175 {
176 // Call it
177 ITfFnLangProfileUtil *pProfileUtil = NULL;
178 HRESULT hr = fnTF_CreateLangProfileUtil(&pProfileUtil);
179 if ((hr == S_OK) && pProfileUtil) // Success!
180 {
181 // Register profile
182 hr = pProfileUtil->RegisterActiveProfiles();
183 if (hr == S_OK)
184 TF_InvalidAssemblyListCacheIfExist(); // Invalidate the assembly list cache
185
186 pProfileUtil->Release();
187 }
188 }
189
190 if (hSPTIP)
191 ::FreeLibrary(hSPTIP);
192}
193
194VOID
196{
197 HKEY hKey;
199
200 // Delete internat.exe from registry "Run" key
201 LSTATUS error = ::RegOpenKeyEx(entry.hRootKey, entry.pszSubKey, 0, KEY_ALL_ACCESS, &hKey);
202 if (error == ERROR_SUCCESS)
203 {
204 ::RegDeleteValue(hKey, TEXT("internat.exe"));
206 }
207
208 // Kill the "Indicator" window (that internat.exe creates)
209 HWND hwndInternat = ::FindWindow(TEXT("Indicator"), NULL);
210 if (hwndInternat)
211 ::PostMessage(hwndInternat, WM_CLOSE, 0, 0);
212}
213
214// Post message 0x8002 to every "SapiTipWorkerClass" window.
215// Called from CRegWatcher::UpdateSpTip
218 _In_ HWND hWnd,
220{
221 TCHAR ClassName[MAX_PATH];
222
224
225 if (::GetClassName(hWnd, ClassName, _countof(ClassName)) &&
226 _tcsicmp(ClassName, TEXT("SapiTipWorkerClass")) == 0)
227 {
228 PostMessage(hWnd, 0x8002, 0, 0); // FIXME: Magic number
229 }
230
231 return TRUE;
232}
233
236 _In_ HWND hwnd,
237 _In_ UINT uMsg,
238 _In_ UINT_PTR idEvent,
240{
243 UNREFERENCED_PARAMETER(idEvent);
245
246 // Cancel the timer
248 {
251 }
252
253 TF_PostAllThreadMsg(15, 16);
254}
255
256VOID
258{
259 // Call SysColorTimerProc 0.5 seconds later (Delayed)
261 {
264 }
266}
267
270 _In_ HWND hwnd,
271 _In_ UINT uMsg,
272 _In_ UINT_PTR idEvent,
274{
277 UNREFERENCED_PARAMETER(idEvent);
279
280 // Cancel the timer
282 {
285 }
286
288 TF_PostAllThreadMsg(12, 16);
289}
290
293 _In_ HWND hwnd,
294 _In_ UINT uMsg,
295 _In_ UINT_PTR idEvent,
297{
300 UNREFERENCED_PARAMETER(idEvent);
302
303 // Cancel the timer
305 {
308 }
309
310 TF_PostAllThreadMsg(11, 16);
311}
312
313VOID
315 _In_ SIZE_T iEvent)
316{
317 InitEvent(iEvent, TRUE);
318
319 switch (iEvent)
320 {
321 case WI_TOGGLE:
322 {
323 // Call KbdToggleTimerProc 0.5 seconds later (Delayed)
325 {
328 }
330 break;
331 }
332 case WI_MACHINE_TIF:
333 case WI_PRELOAD:
334 case WI_USER_TIF:
337 case WI_ASSEMBLIES:
338 {
339 if (iEvent == WI_MACHINE_SPEECH)
340 UpdateSpTip();
341
342 // Call RegImxTimerProc 0.2 seconds later (Delayed)
344 {
347 }
349 break;
350 }
351 case WI_RUN: // The "Run" key is changed
352 {
353 KillInternat(); // Deny internat.exe the right to live
354 break;
355 }
356 case WI_USER_SPEECH:
357 case WI_APPEARANCE:
358 case WI_COLORS:
360 {
362 break;
363 }
364 default:
365 {
366 break;
367 }
368 }
369}
HRESULT(WINAPI * FN_TF_CreateLangProfileUtil)(ITfFnLangProfileUtil **)
Definition: CRegWatcher.cpp:37
LONG WINAPI DelayedRegNotifyChangeKeyValue(HKEY hKey, BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL fAsynchronous)
Definition: CRegWatcher.cpp:90
LONG(WINAPI * FN_RegNotifyChangeKeyValue)(HKEY, BOOL, DWORD, HANDLE, BOOL)
Definition: CRegWatcher.cpp:87
#define WATCHENTRY_MAX
Definition: CRegWatcher.h:17
HWND hWnd
Definition: settings.c:17
@ WI_ASSEMBLIES
Definition: precomp.h:45
@ WI_APPEARANCE
Definition: precomp.h:40
@ WI_COLORS
Definition: precomp.h:41
@ WI_MACHINE_TIF
Definition: precomp.h:35
@ WI_WINDOW_METRICS
Definition: precomp.h:42
@ WI_TOGGLE
Definition: precomp.h:34
@ WI_RUN
Definition: precomp.h:37
@ WI_USER_TIF
Definition: precomp.h:38
@ WI_PRELOAD
Definition: precomp.h:36
@ WI_MACHINE_SPEECH
Definition: precomp.h:43
@ WI_KEYBOARD_LAYOUT
Definition: precomp.h:44
@ WI_USER_SPEECH
Definition: precomp.h:39
HANDLE HKEY
Definition: registry.h:26
#define RegCloseKey(hKey)
Definition: registry.h:49
EXTERN_C HINSTANCE cicLoadSystemLibrary(_In_ LPCTSTR pszFileName, _In_ BOOL bSysWinDir)
Definition: cicbase.cpp:143
EXTERN_C HINSTANCE cicGetSystemModuleHandle(_In_ LPCTSTR pszFileName, _In_ BOOL bSysWinDir)
Definition: cicbase.cpp:130
#define CIC_OSINFO_NT
Definition: cicbase.h:44
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
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:26
#define error(str)
Definition: mkdosfs.c:1605
static HANDLE hEvent
Definition: comm.c:54
#define _In_
Definition: ms_sal.h:308
HRESULT WINAPI TF_InvalidAssemblyListCacheIfExist(void)
Definition: msctf.c:677
EXTERN_C HRESULT WINAPI TF_InvalidAssemblyListCache(VOID)
EXTERN_C HRESULT WINAPI TF_PostAllThreadMsg(DWORD dwUnknown1, DWORD dwUnknown2)
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
unsigned int UINT
Definition: ndis.h:50
#define BOOL
Definition: nt_native.h:43
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define KEY_READ
Definition: nt_native.h:1023
#define KEY_WRITE
Definition: nt_native.h:1031
#define DWORD
Definition: nt_native.h:44
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
long LONG
Definition: pedump.c:60
#define REG_DWORD
Definition: sdbapi.c:596
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:23
static BOOL Init()
Definition: CRegWatcher.cpp:40
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[WATCHENTRY_MAX]
Definition: CRegWatcher.h:22
static VOID Uninit()
Definition: CRegWatcher.cpp:64
static UINT s_nRegImxTimerId
Definition: CRegWatcher.h:23
static VOID CALLBACK KbdToggleTimerProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ UINT_PTR idEvent, _In_ DWORD dwTime)
static HANDLE s_ahWatchEvents[WATCHENTRY_MAX]
Definition: CRegWatcher.h:21
static UINT s_nKbdToggleTimerId
Definition: CRegWatcher.h:23
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:3748
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
#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:520
#define RegSetValueEx
Definition: winreg.h:533
#define RegCreateKeyEx
Definition: winreg.h:501
#define REG_NOTIFY_CHANGE_NAME
Definition: winreg.h:38
#define REG_NOTIFY_CHANGE_LAST_SET
Definition: winreg.h:40
#define RegDeleteValue
Definition: winreg.h:508
#define WM_CLOSE
Definition: winuser.h:1621
#define FindWindow
Definition: winuser.h:5786
#define GetClassName
Definition: winuser.h:5792
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:5841
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
char TCHAR
Definition: xmlstorage.h:189
#define _tcsicmp
Definition: xmlstorage.h:205