Rabbit Remote Control 0.1.0-bate16
Loading...
Searching...
No Matches
HookWindows.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QApplication>
4#include <QKeyEvent>
5#include <QLoggingCategory>
6#include <RabbitCommonTools.h>
7#include <QMessageBox>
8#include <QCheckBox>
9
10#include "FrmViewer.h"
11#include "HookWindows.h"
12#include "RabbitCommonTools.h"
13
14static Q_LOGGING_CATEGORY(log, "Plugin.Hook.Windows")
15
16CHookWindows::CHookWindows(CParameterPlugin *pParaClient, QObject *parent)
17 : CHook(pParaClient, parent),
18 m_hKeyboard(nullptr)
19{
20}
21
22CHookWindows::~CHookWindows()
23{
24 qDebug(log) << "CHookWindows::~CHookWindows()";
25}
26
27// See: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985(v=vs.85)
28LRESULT CALLBACK CHookWindows::keyboardHookProc(INT code, WPARAM wparam, LPARAM lparam)
29{
30 if (code == HC_ACTION)
31 {
32 KBDLLHOOKSTRUCT* hook = reinterpret_cast<KBDLLHOOKSTRUCT*>(lparam);
33 /*
34 qDebug(log) << "process vkCode:" << hook->vkCode
35 << "scanCode:" << hook->scanCode
36 << "flags:" << hook->flags;//*/
37 int key = 0;
38 Qt::KeyboardModifiers keyMdf = Qt::NoModifier;
39 // See: [virtual-key-codes](https://learn.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes)
40 switch(hook->vkCode)
41 {
42 case VK_TAB:
43 {
44 key = Qt::Key_Tab;
45 break;
46 }
47 case VK_DELETE:
48 {
49 key = Qt::Key_Delete;
50 break;
51 }
52 case VK_LWIN:
53 {
54 key = Qt::Key_Super_L;
55 keyMdf = Qt::MetaModifier;
56 break;
57 }
58 case VK_RWIN:
59 {
60 key = Qt::Key_Super_R;
61 keyMdf = Qt::MetaModifier;
62 break;
63 }
64 case VK_MENU:
65 case VK_LMENU:
66 case VK_RMENU:
67 {
68 key = Qt::Key_Alt;
69 keyMdf = Qt::KeyboardModifier::AltModifier;
70 break;
71 }
72 case VK_CONTROL:
73 case VK_LCONTROL:
74 case VK_RCONTROL:
75 {
76 key = Qt::Key_Control;
77 keyMdf = Qt::KeyboardModifier::ControlModifier;
78 break;
79 }
80 /*
81 //直接发送给应用窗口,跳过了qt的事件队列。所以会导到 CFrmViewer 得不到组合键。例如大写字母
82 case VK_SHIFT:
83 case VK_LSHIFT:
84 case VK_RSHIFT:
85 {
86 key = Qt::Key_Shift;
87 keyMdf = Qt::KeyboardModifier::ShiftModifier;
88 break;
89 }//*/
90 default:
91 break;
92 }
93 if(key) {
94 CFrmViewer* self = qobject_cast<CFrmViewer*>(QApplication::focusWidget());
95 WId foreground_window = reinterpret_cast<WId>(GetForegroundWindow());
96 if (self && self->parentWidget()->window()->winId() == foreground_window)
97 {
98 if(wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN)
99 //emit self->sigKeyPressEvent(new QKeyEvent(QKeyEvent::KeyPress, key, keyMdf));
100 QApplication::postEvent(self, new QKeyEvent(QKeyEvent::KeyPress, key, keyMdf));
101 if(wparam == WM_KEYUP || wparam == WM_SYSKEYUP)
102 //emit self->sigKeyReleaseEvent(new QKeyEvent(QKeyEvent::KeyRelease, key, keyMdf));
103 QApplication::postEvent(self, new QKeyEvent(QKeyEvent::KeyRelease, key, keyMdf));
104 /*
105 qDebug(log) << (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN ? "KEYDOWN" : "KEYUP")
106 << "key:" << key << "keymdf:" << keyMdf
107 << "process vkCode:" << hook->vkCode
108 << "scanCode:" << hook->scanCode
109 << "flags:" << hook->flags;//*/
110 /* the hook procedure did not process the message,
111 * it is highly recommended that you call CallNextHookEx
112 * and return the value it returns; otherwise,
113 * other applications that have installed WH_KEYBOARD_LL hooks
114 * will not receive hook notifications and may behave incorrectly
115 * as a result. If the hook procedure processed the message,
116 * it may return a nonzero value to prevent the system
117 * from passing the message to the rest of the hook chain
118 * or the target window procedure.
119 */
120 return 1;
121 }
122 }
123 }
124
125 return CallNextHookEx(nullptr, code, wparam, lparam);
126}
127
128// See: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexw
129int CHookWindows::OnRegisterKeyboard()
130{
131 if(m_hKeyboard)
132 UnRegisterKeyboard();
133 m_hKeyboard = SetWindowsHookExW(WH_KEYBOARD_LL, keyboardHookProc, nullptr, 0);
134 if(NULL == m_hKeyboard) {
135 qCritical(log) << "SetWindowsHookExW error:" << GetLastError();
136 return -1;
137 }
138 return 0;
139}
140
141int CHookWindows::OnUnRegisterKeyboard()
142{
143 if(m_hKeyboard)
144 {
145 UnhookWindowsHookEx(m_hKeyboard);
146 m_hKeyboard = nullptr;
147 }
148 return 0;
149}
150
151int CHookWindows::OnDisableDesktopShortcuts()
152{
153 DisableTaskManager(true);
154 return 0;
155}
156
157int CHookWindows::OnRestoreDesktopShortcuts()
158{
159 DisableTaskManager(false);
160 return 0;
161}
162
163// 启用备份和恢复权限
164bool EnableDebugPrivileges() {
165 HANDLE hToken = NULL;
166 LUID sedebugnameValue;
167 TOKEN_PRIVILEGES tkp;
168
169 // 获取当前进程的访问令牌
170 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
171 qDebug(log) << "OpenProcessToken failed. Error:" << GetLastError();
172 return false;
173 }
174
175 do {
176 // 查找 SE_DEBUG_NAME 权限的LUID
177 if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &sedebugnameValue)) {
178 qDebug(log) << "LookupPrivilegeValue (SE_DEBUG_NAME) failed. Error:" << GetLastError();
179 break;
180 }
181
182 // 设置权限结构
183 tkp.PrivilegeCount = 1;
184 tkp.Privileges[0].Luid = sedebugnameValue;
185 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
186
187 // 调整权限
188 if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
189 qDebug(log) << "AdjustTokenPrivileges failed. Error:" << GetLastError();
190 break;
191 }
192
193 // 检查权限是否成功启用
194 if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
195 qDebug(log) << "The token does not have the specified privileges.";
196 break;
197 }
198 qDebug(log) << "Debug privileges enabled successfully.";
199 }while(0);
200
201 CloseHandle(hToken);
202 return true;
203}
204
205//添加注册屏蔽 Ctrl+Alt+del
206//在注册表该目录下增加新内容
207#define TASKMANAGERSystem "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"
208#define TASKMANAGERExplorer "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"
209#define WINLOGON "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"
210void CHookWindows::DisableTaskManager(bool flag)
211{
212 // 屏蔽ctrl + alt +del 需要修改注册表的值, 取得管理员权限, 关闭360等杀毒软件
213 int value = flag ? 0x00000001 : 0x00000000;
214 QSettings system(TASKMANAGERSystem, QSettings::NativeFormat);
215 system.setValue("DisableTaskMgr", value); //任务管理器
216 system.setValue("DisableChangePassword", value); //更改密码
217 system.setValue("DisableSwitchUserOption", value); //切换用户
218 system.setValue("DisableCAD", value); // Disable ctrl+alt+del
219 system.setValue("DisableLockWorkstation", value); //锁定计算机
220
221 QSettings explorer(TASKMANAGERExplorer, QSettings::NativeFormat);
222 explorer.setValue("NoLogOff", value); //注销
223
224 /*
225 QSettings winlogon(WINLOGON, QSettings::NativeFormat);
226 winlogon.setValue("DisableCAD", value); // Disable ctrl+alt+del
227 winlogon.setValue("DisableLockWorkstation", value); //锁定计算机
228 //*/
229}
230
231bool CHookWindows::DisableWindowsKey()
232{
233 // 方法1: 使用 RegisterHotKey 来占用 Windows 键
234 bool success = true;
235
236 // 注册热键来拦截 Windows 键
237 if (!RegisterHotKey(nullptr, 1, MOD_WIN, VK_LWIN)) {
238 qCritical(log) << "注册左 Windows 键拦截失败:" << GetLastError();
239 success = false;
240 }
241
242 if (!RegisterHotKey(nullptr, 2, MOD_WIN, VK_RWIN)) {
243 qCritical(log) << "注册右 Windows 键拦截失败:" << GetLastError();
244 success = false;
245 }
246
247 // 方法2: 修改注册表禁用 Windows 键
248 HKEY hKey;
249 LONG result = RegCreateKeyExW(HKEY_CURRENT_USER,
250 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
251 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, nullptr);
252
253 if (result == ERROR_SUCCESS) {
254 DWORD value = 1; // 1 表示禁用 Windows 键
255 result = RegSetValueExW(hKey, L"NoWinKeys", 0, REG_DWORD,
256 reinterpret_cast<const BYTE*>(&value), sizeof(value));
257
258 if (result == ERROR_SUCCESS) {
259 qDebug(log) << "注册表设置成功,Windows 键已禁用";
260 } else {
261 qWarning(log) << "注册表设置失败:" << result;
262 success = false;
263 }
264 RegCloseKey(hKey);
265 } else {
266 qWarning(log) << "创建注册表键失败:" << result;
267 success = false;
268 }
269
270 return success;
271}
272
273bool CHookWindows::EnableWindowsKey()
274{
275 bool success = true;
276
277 // 取消注册热键
278 UnregisterHotKey(nullptr, 1);
279 UnregisterHotKey(nullptr, 2);
280
281 // 恢复注册表设置
282 HKEY hKey;
283 LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
284 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
285 0, KEY_ALL_ACCESS, &hKey);
286
287 if (result == ERROR_SUCCESS) {
288 result = RegDeleteValueW(hKey, L"NoWinKeys");
289 if (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND) {
290 qDebug(log) << "Windows 键已恢复";
291 } else {
292 qWarning(log) << "删除注册表值失败:" << result;
293 success = false;
294 }
295 RegCloseKey(hKey);
296 }
297
298 return success;
299}
300
301bool CHookWindows::DisableTaskManager()
302{
303 bool bRet = false;
304 HKEY hKey;
305 LONG result = RegCreateKeyExW(HKEY_CURRENT_USER,
306 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
307 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, nullptr);
308
309 if (result == ERROR_SUCCESS) {
310 DWORD value = 1; // 1 表示禁用任务管理器
311 result = RegSetValueExW(hKey, L"DisableTaskMgr", 0, REG_DWORD,
312 reinterpret_cast<const BYTE*>(&value), sizeof(value));
313
314 if (result == ERROR_SUCCESS) {
315 qDebug(log) << "任务管理器已禁用";
316 bRet = true;
317 } else {
318 qWarning(log) << "禁用任务管理器失败:" << result;
319 }
320 RegCloseKey(hKey);
321 }
322
323 return bRet;
324}
325
326bool CHookWindows::EnableTaskManager()
327{
328 HKEY hKey;
329 LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
330 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
331 0, KEY_ALL_ACCESS, &hKey);
332
333 if (result == ERROR_SUCCESS) {
334 result = RegDeleteValueW(hKey, L"DisableTaskMgr");
335 RegCloseKey(hKey);
336
337 if (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND) {
338 qDebug(log) << "任务管理器已恢复";
339 return true;
340 }
341 }
342
343 return false;
344}
The class is the HOOK abstract class.
Definition Hook.h:15
Global parameters of plugins.