Rabbit Remote Control 0.0.35
Loading...
Searching...
No Matches
HookWindows.cpp
1#include <QApplication>
2#include <QKeyEvent>
3#include <QLoggingCategory>
4#include <RabbitCommonTools.h>
5#include <QMessageBox>
6#include <QCheckBox>
7
8#include "FrmViewer.h"
9#include "HookWindows.h"
10#include "RabbitCommonTools.h"
11
12static Q_LOGGING_CATEGORY(log, "Client.Hook.Windows")
13
14CHookWindows::CHookWindows(CParameterClient *pParaClient, QObject *parent)
15 : CHook(pParaClient, parent),
16 m_hKeyboard(nullptr)
17{
18}
19
20CHookWindows::~CHookWindows()
21{
22 qDebug(log) << "CHookWindows::~CHookWindows()";
23}
24
25// See: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985(v=vs.85)
26LRESULT CALLBACK CHookWindows::keyboardHookProc(INT code, WPARAM wparam, LPARAM lparam)
27{
28 if (code == HC_ACTION)
29 {
30 KBDLLHOOKSTRUCT* hook = reinterpret_cast<KBDLLHOOKSTRUCT*>(lparam);
31 /*
32 qDebug(log) << "process vkCode:" << hook->vkCode
33 << "scanCode:" << hook->scanCode
34 << "flags:" << hook->flags;//*/
35 int key = 0;
36 Qt::KeyboardModifiers keyMdf = Qt::NoModifier;
37 // See: [virtual-key-codes](https://learn.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes)
38 switch(hook->vkCode)
39 {
40 case VK_TAB:
41 {
42 key = Qt::Key_Tab;
43 break;
44 }
45 case VK_DELETE:
46 {
47 key = Qt::Key_Delete;
48 break;
49 }
50 case VK_LWIN:
51 {
52 key = Qt::Key_Super_L;
53 keyMdf = Qt::MetaModifier;
54 break;
55 }
56 case VK_RWIN:
57 {
58 key = Qt::Key_Super_R;
59 keyMdf = Qt::MetaModifier;
60 break;
61 }
62 case VK_MENU:
63 case VK_LMENU:
64 case VK_RMENU:
65 {
66 key = Qt::Key_Alt;
67 //keyMdf = Qt::KeyboardModifier::AltModifier;
68 break;
69 }
70 case VK_CONTROL:
71 case VK_LCONTROL:
72 case VK_RCONTROL:
73 {
74 key = Qt::Key_Control;
75 //keyMdf = Qt::KeyboardModifier::ControlModifier;
76 break;
77 }
78 case VK_SHIFT:
79 case VK_LSHIFT:
80 case VK_RSHIFT:
81 {
82 key = Qt::Key_Shift;
83 //keyMdf = Qt::KeyboardModifier::ShiftModifier;
84 break;
85 }
86 default:
87 break;
88 }
89 if(key) {
90 CFrmViewer* self = qobject_cast<CFrmViewer*>(QApplication::focusWidget());
91 WId foreground_window = reinterpret_cast<WId>(GetForegroundWindow());
92 if (self && self->parentWidget()->window()->winId() == foreground_window)
93 {
94 if(wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN)
95 emit self->sigKeyPressEvent(new QKeyEvent(QKeyEvent::KeyPress, key, keyMdf));
96 //QApplication::postEvent(self, new QKeyEvent(QKeyEvent::KeyPress, key, keyMdf));
97 if(wparam == WM_KEYUP || wparam == WM_SYSKEYUP)
98 emit self->sigKeyReleaseEvent(new QKeyEvent(QKeyEvent::KeyRelease, key, Qt::NoModifier));
99 //QApplication::postEvent(self, new QKeyEvent(QKeyEvent::KeyRelease, key, Qt::NoModifier));
100 //*
101 qDebug(log) << "process vkCode:" << hook->vkCode
102 << "scanCode:" << hook->scanCode
103 << "flags:" << hook->flags;//*/
104 /* the hook procedure did not process the message,
105 * it is highly recommended that you call CallNextHookEx
106 * and return the value it returns; otherwise,
107 * other applications that have installed WH_KEYBOARD_LL hooks
108 * will not receive hook notifications and may behave incorrectly
109 * as a result. If the hook procedure processed the message,
110 * it may return a nonzero value to prevent the system
111 * from passing the message to the rest of the hook chain
112 * or the target window procedure.
113 */
114 return 1;
115 }
116 }
117 }
118
119 return CallNextHookEx(nullptr, code, wparam, lparam);
120}
121
122// See: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexw
123int CHookWindows::RegisterKeyboard()
124{
125 if(!RabbitCommon::CTools::Instance()->HasAdministratorPrivilege()
126 && m_pParameterClient->GetPromptAdministratorPrivilege())
127 {
128 int nRet = 0;
129 QMessageBox msg(
130 QMessageBox::Warning, tr("Warning"),
131 tr("The programe is not administrator privilege.\n"
132 "Don't disable system shortcuts(eg: Ctrl+Alt+del).\n"
133 "Restart program by administrator?"),
134 QMessageBox::Yes | QMessageBox::No);
135 msg.setCheckBox(new QCheckBox(tr("Always shown"), &msg));
136 msg.checkBox()->setCheckable(true);
137 msg.checkBox()->setChecked(
138 m_pParameterClient->GetPromptAdministratorPrivilege());
139 nRet = msg.exec();
140 if(QMessageBox::Yes == nRet) {
141 RabbitCommon::CTools::Instance()->StartWithAdministratorPrivilege(true);
142 }
143 if(m_pParameterClient->GetPromptAdministratorPrivilege()
144 != msg.checkBox()->isChecked()) {
145 m_pParameterClient->SetPromptAdministratorPrivilege(
146 msg.checkBox()->isChecked());
147 }
148 }
149
150 if(m_hKeyboard)
151 UnRegisterKeyboard();
152 DisableTaskManager(true);
153 m_hKeyboard = SetWindowsHookExW(WH_KEYBOARD_LL, keyboardHookProc, nullptr, 0);
154 if(NULL == m_hKeyboard) {
155 qCritical(log) << "SetWindowsHookExW error:" << GetLastError();
156 return -1;
157 }
158 return 0;
159}
160
161int CHookWindows::UnRegisterKeyboard()
162{
163 if(m_hKeyboard)
164 {
165 UnhookWindowsHookEx(m_hKeyboard);
166 m_hKeyboard = nullptr;
167 }
168 DisableTaskManager(false);
169 return 0;
170}
171
172// 启用备份和恢复权限
173bool EnableDebugPrivileges() {
174 HANDLE hToken = NULL;
175 LUID sedebugnameValue;
176 TOKEN_PRIVILEGES tkp;
177
178 // 获取当前进程的访问令牌
179 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
180 qDebug(log) << "OpenProcessToken failed. Error:" << GetLastError();
181 return false;
182 }
183
184 do {
185 // 查找 SE_DEBUG_NAME 权限的LUID
186 if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &sedebugnameValue)) {
187 qDebug(log) << "LookupPrivilegeValue (SE_DEBUG_NAME) failed. Error:" << GetLastError();
188 break;
189 }
190
191 // 设置权限结构
192 tkp.PrivilegeCount = 1;
193 tkp.Privileges[0].Luid = sedebugnameValue;
194 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
195
196 // 调整权限
197 if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
198 qDebug(log) << "AdjustTokenPrivileges failed. Error:" << GetLastError();
199 break;
200 }
201
202 // 检查权限是否成功启用
203 if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
204 qDebug(log) << "The token does not have the specified privileges.";
205 break;
206 }
207 qDebug(log) << "Debug privileges enabled successfully.";
208 }while(0);
209
210 CloseHandle(hToken);
211 return true;
212}
213
214//添加注册屏蔽 Ctrl+Alt+del
215//在注册表该目录下增加新内容
216#define TASKMANAGERSystem "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"
217#define TASKMANAGERExplorer "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"
218void CHookWindows::DisableTaskManager(bool flag)
219{
220 // 屏蔽ctrl + alt +del 需要修改注册表的值, 取得管理员权限, 关闭360等杀毒软件
221 int value = flag ? 0x00000001 : 0x00000000;
222 QSettings settings(TASKMANAGERSystem, QSettings::NativeFormat);
223 settings.setValue("DisableTaskMgr", value); //任务管理器
224 settings.setValue("DisableChangePassword", value); //更改密码
225 settings.setValue("DisableLockWorkstation", value); //锁定计算机
226 settings.setValue("DisableSwitchUserOption", value); //切换用户
227
228 QSettings settings2(TASKMANAGERExplorer, QSettings::NativeFormat);
229 settings2.setValue("NoLogOff", value); //注销
230}
A widget which displays output image from a CConnectDesktop and sends input keypresses and mouse acti...
Definition FrmViewer.h:49
The class is the HOOK abstract class.
Definition Hook.h:15
The parameters of client.