ReactOS 0.4.16-dev-1401-gf1332c7
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 {
157 return TRUE;
158 }
159 }
160
161 /* Unhook */
163 {
166 }
168 {
171 }
172 if (g_pShared->hWinHook)
173 {
176 }
177
179 return !bDoHook;
180}
181
182// indicdll!12
185{
187 {
188 *pnID = g_pShared->nHotID;
189 *pdwItemData = g_pShared->dwHotMenuItemData;
191 }
192 else
193 {
194 WARN("EnterProtectedSection failed\n");
195 *pnID = 0;
196 *pdwItemData = 0;
197 }
198}
199
200// indicdll!14
203{
205 {
206 g_pShared->nHotID = nID;
207 g_pShared->dwHotMenuItemData = dwItemData;
209 }
210 else
211 {
212 WARN("EnterProtectedSection failed\n");
213 }
214}
215
220{
221 switch (dwReason)
222 {
224 {
225 TRACE("DLL_PROCESS_ATTACH\n");
226 g_hInstance = hinstDLL;
227
229 0, sizeof(SHARED_DATA), TEXT("InternatSHData"));
230 if (!g_hShared)
231 {
232 ERR("!g_hShared\n");
233 return FALSE;
234 }
235
236 BOOL bAlreadyExists = GetLastError() == ERROR_ALREADY_EXISTS;
237 TRACE("bAlreadyExists: %d\n", bAlreadyExists);
238
240 if (!g_pShared)
241 {
242 ERR("!g_pShared\n");
243 return FALSE;
244 }
245
246 if (!bAlreadyExists)
247 ZeroMemory(g_pShared, sizeof(*g_pShared));
248
250 {
252 TRACE("hKbSwitchWnd: %p\n", g_pShared->hKbSwitchWnd);
253 }
254
255 g_hMutex = CreateMutex(NULL, FALSE, TEXT("INDICDLL_PROTECTED"));
256 if (!g_hMutex)
257 {
258 ERR("Failed to create mutex\n");
259 return FALSE;
260 }
261 break;
262 }
264 {
265 TRACE("DLL_PROCESS_DETACH\n");
266 if (g_hMutex)
270 break;
271 }
272 }
273
274 return TRUE;
275}
#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:217
VOID APIENTRY GetPenMenuData(PUINT pnID, PDWORD_PTR pdwItemData)
Definition: indicdll.c:184
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:52
FN_SetPenMenuData SetPenMenuData
Definition: kbswitch.c:53
#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:5862
#define HCBT_ACTIVATE
Definition: winuser.h:60
#define KF_ALTDOWN
Definition: winuser.h:2468
#define VK_CONTROL
Definition: winuser.h:2222
#define HC_ACTION
Definition: winuser.h:48
#define VK_RSHIFT
Definition: winuser.h:2302
#define WH_SHELL
Definition: winuser.h:40
#define VK_LSHIFT
Definition: winuser.h:2301
#define WH_CBT
Definition: winuser.h:35
#define VK_LCONTROL
Definition: winuser.h:2303
#define SetWindowsHookEx
Definition: winuser.h:5941
#define VK_RCONTROL
Definition: winuser.h:2304
#define KF_UP
Definition: winuser.h:2470
BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK)
#define HCBT_SETFOCUS
Definition: winuser.h:64
#define VK_RMENU
Definition: winuser.h:2306
#define PostMessage
Definition: winuser.h:5917
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
#define KF_REPEAT
Definition: winuser.h:2469
#define VK_SHIFT
Definition: winuser.h:2221
SHORT WINAPI GetKeyState(_In_ int)
#define VK_LMENU
Definition: winuser.h:2305
#define VK_MENU
Definition: winuser.h:2223