ReactOS 0.4.16-dev-1515-g853b446
indicdll.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Keyboard Layout Switcher
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Switching Keyboard Layouts
5 * COPYRIGHT: Copyright Dmitry Chapyshev (dmitry@reactos.org)
6 * Copyright Colin Finck (mail@colinfinck.de)
7 * Copyright 2022-2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
8 */
9
10#include "../kbswitch.h"
11#include "resource.h"
12
13#include <wine/debug.h>
15
16typedef struct tagSHARED_DATA
17{
18 HHOOK hWinHook;
25
30
31#define MUTEX_TIMEOUT_MS (4 * 1000)
32
34{
36 if (dwWaitResult == WAIT_OBJECT_0)
37 return TRUE;
38
39 if (dwWaitResult == WAIT_TIMEOUT)
40 WARN("Timeout while waiting for mutex.\n");
41 else
42 WARN("Failed to acquire mutex. Error code: %lu\n", GetLastError());
43
44 return FALSE;
45}
46
48{
50}
51
52static inline VOID
54{
57}
58
59static LRESULT CALLBACK
61{
62 if (code < 0)
64
65 switch (code)
66 {
67 case HCBT_ACTIVATE:
68 case HCBT_SETFOCUS:
69 {
70 HWND hwndFocus = (HWND)wParam;
71 if (hwndFocus && hwndFocus != g_pShared->hKbSwitchWnd)
73 break;
74 }
75 }
76
78}
79
80static LRESULT CALLBACK
82{
83 if (code < 0)
85
86 switch (code)
87 {
88 case HSHELL_WINDOWACTIVATED:
89 {
91 break;
92 }
93 case HSHELL_LANGUAGE:
94 {
96 break;
97 }
98 }
99
101}
102
103static inline BOOL
104CheckVirtualKey(UINT vKey, UINT vKey0, UINT vKey1, UINT vKey2)
105{
106 return vKey == vKey0 || vKey == vKey1 || vKey == vKey2;
107}
108
109static LRESULT CALLBACK
111{
112 if (code < 0)
114
115 if (code == HC_ACTION)
116 {
117 UINT vKey = (UINT)wParam;
118 LONG keyFlags = HIWORD(lParam);
119 if (!(keyFlags & KF_UP) && !(keyFlags & KF_REPEAT))
120 {
121 BOOL bShiftPressed = (GetKeyState(VK_SHIFT) < 0);
122 BOOL bAltPressed = (keyFlags & KF_ALTDOWN) || (GetKeyState(VK_MENU) < 0);
123 BOOL bCtrlPressed = (GetKeyState(VK_CONTROL) < 0);
124 // Detect Alt+Shift and Ctrl+Shift
125 if ((bAltPressed && CheckVirtualKey(vKey, VK_SHIFT, VK_LSHIFT, VK_RSHIFT)) ||
126 (bShiftPressed && CheckVirtualKey(vKey, VK_MENU, VK_LMENU, VK_RMENU)) ||
127 (bCtrlPressed && CheckVirtualKey(vKey, VK_SHIFT, VK_LSHIFT, VK_RSHIFT)) ||
128 (bShiftPressed && CheckVirtualKey(vKey, VK_CONTROL, VK_LCONTROL, VK_RCONTROL)))
129 {
131 }
132 }
133 }
134
136}
137
140{
141 TRACE("bDoHook: %d\n", bDoHook);
142
144 return FALSE;
145
146 if (bDoHook)
147 {
151
152 if (g_pShared->hWinHook &&
155 {
156 // Find kbswitch window if necessary
158 {
160 TRACE("hKbSwitchWnd: %p\n", g_pShared->hKbSwitchWnd);
161 }
162
164 return TRUE;
165 }
166 }
167
168 /* Unhook */
170 {
173 }
175 {
178 }
179 if (g_pShared->hWinHook)
180 {
183 }
184
186 return !bDoHook;
187}
188
189// indicdll!12
192{
194 {
195 *pnID = g_pShared->nHotID;
196 *pdwItemData = g_pShared->dwHotMenuItemData;
198 }
199 else
200 {
201 WARN("EnterProtectedSection failed\n");
202 *pnID = 0;
203 *pdwItemData = 0;
204 }
205}
206
207// indicdll!14
210{
212 {
213 g_pShared->nHotID = nID;
214 g_pShared->dwHotMenuItemData = dwItemData;
216 }
217 else
218 {
219 WARN("EnterProtectedSection failed\n");
220 }
221}
222
227{
228 switch (dwReason)
229 {
231 {
232 TRACE("DLL_PROCESS_ATTACH\n");
233 g_hInstance = hinstDLL;
234
236 0, sizeof(SHARED_DATA), TEXT("InternatSHData"));
237 if (!g_hShared)
238 {
239 ERR("!g_hShared\n");
240 return FALSE;
241 }
242
243 BOOL bAlreadyExists = GetLastError() == ERROR_ALREADY_EXISTS;
244 TRACE("bAlreadyExists: %d\n", bAlreadyExists);
245
247 if (!g_pShared)
248 {
249 ERR("!g_pShared\n");
250 return FALSE;
251 }
252
253 if (!bAlreadyExists)
254 ZeroMemory(g_pShared, sizeof(*g_pShared));
255
256 g_hMutex = CreateMutex(NULL, FALSE, TEXT("INDICDLL_PROTECTED"));
257 if (!g_hMutex)
258 {
259 ERR("Failed to create mutex\n");
260 return FALSE;
261 }
262 break;
263 }
265 {
266 TRACE("DLL_PROCESS_DETACH\n");
267 if (g_hMutex)
271 break;
272 }
273 }
274
275 return TRUE;
276}
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
DWORD dwReason
Definition: misc.cpp:135
ULONG_PTR * PDWORD_PTR
Definition: basetsd.h:182
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
struct @1766 Msg[]
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define APIENTRY
Definition: api.h:79
#define CloseHandle
Definition: compat.h:739
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#define UnmapViewOfFile
Definition: compat.h:746
HANDLE HWND
Definition: compat.h:19
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CALLBACK
Definition: compat.h:35
#define MapViewOfFile
Definition: compat.h:745
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
static BOOL CheckVirtualKey(UINT vKey, UINT vKey0, UINT vKey1, UINT vKey2)
Definition: indicdll.c:104
static VOID LeaveProtectedSection(VOID)
Definition: indicdll.c:47
struct tagSHARED_DATA * PSHARED_DATA
struct tagSHARED_DATA SHARED_DATA
BOOL WINAPI DllMain(IN HINSTANCE hinstDLL, IN DWORD dwReason, IN LPVOID lpvReserved)
Definition: indicdll.c:224
VOID APIENTRY GetPenMenuData(PUINT pnID, PDWORD_PTR pdwItemData)
Definition: indicdll.c:191
static VOID PostMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: indicdll.c:53
static LRESULT CALLBACK ShellHookProc(INT code, WPARAM wParam, LPARAM lParam)
Definition: indicdll.c:81
HANDLE g_hMutex
Definition: indicdll.c:29
HANDLE g_hShared
Definition: indicdll.c:27
HINSTANCE g_hInstance
Definition: indicdll.c:26
PSHARED_DATA g_pShared
Definition: indicdll.c:28
static LRESULT CALLBACK WinHookProc(INT code, WPARAM wParam, LPARAM lParam)
Definition: indicdll.c:60
static BOOL EnterProtectedSection(VOID)
Definition: indicdll.c:33
#define MUTEX_TIMEOUT_MS
Definition: indicdll.c:31
static LRESULT CALLBACK KeyboardProc(INT code, WPARAM wParam, LPARAM lParam)
Definition: indicdll.c:110
#define INDICATOR_CLASS
Definition: indicml.h:19
#define TEXT(s)
Definition: k32.h:28
FN_KbSwitchSetHooks KbSwitchSetHooks
Definition: kbswitch.c:53
FN_SetPenMenuData SetPenMenuData
Definition: kbswitch.c:54
#define WM_WINDOW_ACTIVATE
Definition: kbswitch.h:28
#define WM_LANG_CHANGED
Definition: kbswitch.h:27
static IN DWORD IN LPVOID lpvReserved
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
unsigned int * PUINT
Definition: ndis.h:50
unsigned int UINT
Definition: ndis.h:50
#define _In_
Definition: no_sal2.h:158
#define PAGE_READWRITE
Definition: nt_native.h:1304
long LONG
Definition: pedump.c:60
#define TRACE(s)
Definition: solgame.cpp:4
Definition: inflate.c:139
HHOOK hWinHook
Definition: indicdll.c:18
HWND hKbSwitchWnd
Definition: indicdll.c:21
DWORD_PTR dwHotMenuItemData
Definition: indicdll.c:23
HHOOK hKeyboardHook
Definition: indicdll.c:20
HHOOK hShellHook
Definition: indicdll.c:19
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH ReleaseMutex(IN HANDLE hMutex)
Definition: synch.c:618
uint32_t DWORD_PTR
Definition: typedefs.h:65
int32_t INT
Definition: typedefs.h:58
#define IN
Definition: typedefs.h:39
#define HIWORD(l)
Definition: typedefs.h:247
#define ZeroMemory
Definition: winbase.h:1753
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FILE_MAP_WRITE
Definition: winbase.h:162
#define CreateFileMapping
Definition: winbase.h:3791
#define CreateMutex
Definition: winbase.h:3797
#define WAIT_OBJECT_0
Definition: winbase.h:439
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define WINAPI
Definition: msvc.h:6
#define WH_KEYBOARD
Definition: winuser.h:32
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define FindWindow
Definition: winuser.h:5888
#define HCBT_ACTIVATE
Definition: winuser.h:60
#define KF_ALTDOWN
Definition: winuser.h:2485
#define VK_CONTROL
Definition: winuser.h:2239
#define HC_ACTION
Definition: winuser.h:48
#define VK_RSHIFT
Definition: winuser.h:2319
#define WH_SHELL
Definition: winuser.h:40
#define VK_LSHIFT
Definition: winuser.h:2318
#define WH_CBT
Definition: winuser.h:35
#define VK_LCONTROL
Definition: winuser.h:2320
#define SetWindowsHookEx
Definition: winuser.h:5967
#define VK_RCONTROL
Definition: winuser.h:2321
#define KF_UP
Definition: winuser.h:2487
BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK)
#define HCBT_SETFOCUS
Definition: winuser.h:64
#define VK_RMENU
Definition: winuser.h:2323
#define PostMessage
Definition: winuser.h:5943
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
#define KF_REPEAT
Definition: winuser.h:2486
#define VK_SHIFT
Definition: winuser.h:2238
SHORT WINAPI GetKeyState(_In_ int)
#define VK_LMENU
Definition: winuser.h:2322
#define VK_MENU
Definition: winuser.h:2240