Skip to content

Commit 60954db

Browse files
feat(shell): restore old win11 menu patch method with try catch
1 parent c8c27e2 commit 60954db

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/shell/fix_win11_menu.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "blook/blook.h"
1010
#include "blook/memo.h"
11+
#include "cpptrace/basic.hpp"
1112
#include "utils.h"
1213
#include "zasm/base/immediate.hpp"
1314
#include "zasm/x86/mnemonic.hpp"
@@ -22,6 +23,8 @@
2223
#include <string>
2324
#include <vector>
2425

26+
#include "cpptrace/from_current.hpp"
27+
2528
#define REG_KEY_PATH_LENGTH 1024
2629

2730
typedef enum _KEY_INFORMATION_CLASS {
@@ -109,4 +112,70 @@ void mb_shell::fix_win11_menu::install() {
109112
return RegGetValueHook->call_trampoline<long>(
110113
hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData);
111114
});
115+
116+
// approch 2: patch the shell32.dll to predent the shift key is pressed
117+
std::thread([=]() {
118+
CPPTRACE_TRY {
119+
if (auto shell32 = proc->module("shell32.dll")) {
120+
// mov ecx, 10
121+
// call GetKeyState/GetAsyncKeyState
122+
auto disasm = shell32.value()->section(".text")->disassembly();
123+
124+
auto patch_area = [&](auto mem) {
125+
for (auto it = mem.begin(); it != mem.end(); ++it) {
126+
auto &insn = *it;
127+
if (insn->getMnemonic() == zasm::x86::Mnemonic::Mov) {
128+
if (insn->getOperand(0) == zasm::x86::ecx &&
129+
insn->getOperand(1).template holds<zasm::Imm>() &&
130+
insn->getOperand(1)
131+
.template get<zasm::Imm>()
132+
.template value<int>() == 0x10) {
133+
auto &next = *std::next(it);
134+
if (next->getMnemonic() == zasm::x86::Mnemonic::Call &&
135+
next->getOperand(0).template holds<zasm::Mem>()) {
136+
insn.ptr()
137+
.reassembly([](auto a) {
138+
a.mov(zasm::x86::ecx, 0x10);
139+
a.mov(zasm::x86::eax, 0xffff);
140+
a.nop();
141+
a.nop();
142+
})
143+
.patch();
144+
145+
return true;
146+
}
147+
}
148+
}
149+
}
150+
151+
return false;
152+
};
153+
154+
// the function to determine if show win10 menu or win11 menu calls
155+
// SetMessageExtraInfo, so we use it as a hint
156+
auto extraInfo =
157+
GetProcAddress(LoadLibraryA("user32.dll"), "SetMessageExtraInfo");
158+
for (auto &ins : disasm) {
159+
if (ins->getMnemonic() == zasm::x86::Mnemonic::Call) {
160+
auto xrefs = ins.xrefs();
161+
if (xrefs.empty())
162+
continue;
163+
if (auto ptr = xrefs[0].try_read<void *>();
164+
ptr.has_value() && ptr.value() == extraInfo) {
165+
if (patch_area(ins.ptr()
166+
.find_upwards({0x40, 0x55})
167+
->range_size(0x150)
168+
.disassembly()))
169+
break;
170+
}
171+
}
172+
}
173+
}
174+
}
175+
CPPTRACE_CATCH(...) {
176+
std::println("Failed to patch shell32.dll for win11 menu fix:");
177+
178+
cpptrace::from_current_exception().print();
179+
}
180+
}).detach();
112181
}

0 commit comments

Comments
 (0)