Skip to content

Commit f2ecea2

Browse files
feat(shell): fully support onecommander
close #211
1 parent 8e7d07e commit f2ecea2

File tree

3 files changed

+88
-19
lines changed

3 files changed

+88
-19
lines changed

scripts/inject_onecommander.xpr64

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<XenosConfig>
2+
<imagePath>D:\breeze-shell\build\windows\x64\releasedbg\shell.dll</imagePath>
3+
<manualMapFlags>0</manualMapFlags>
4+
<procName>OneCommander.exe</procName>
5+
<hijack>0</hijack>
6+
<unlink>0</unlink>
7+
<erasePE>0</erasePE>
8+
<close>0</close>
9+
<krnHandle>0</krnHandle>
10+
<injIndef>0</injIndef>
11+
<processMode>0</processMode>
12+
<injectMode>0</injectMode>
13+
<delay>0</delay>
14+
<period>0</period>
15+
<skip>0</skip>
16+
<procCmdLine>C:/</procCmdLine>
17+
<initRoutine/>
18+
<initArgs/>
19+
</XenosConfig>
20+

src/inject/inject.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ std::vector<DWORD> GetExplorerPIDs() {
3636
pe32.dwSize = sizeof(PROCESSENTRY32);
3737
if (Process32First(hSnapshot, &pe32)) {
3838
do {
39-
if (strcmp(pe32.szExeFile, "explorer.exe") == 0) {
39+
std::string exeFile(pe32.szExeFile);
40+
if (exeFile == "explorer.exe" || exeFile == "OneCommander.exe") {
4041
pids.push_back(pe32.th32ProcessID);
4142
}
4243
} while (Process32Next(hSnapshot, &pe32));

src/shell/contextmenu/hooks.cc

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#include "./hooks.h"
22
#include "../config.h"
3+
#include "../entry.h"
4+
#include "../script/quickjspp.hpp"
5+
#include "blook/memo.h"
36
#include "contextmenu.h"
47
#include "menu_render.h"
5-
#include "../script/quickjspp.hpp"
6-
#include "../entry.h"
78

89
#include "blook/blook.h"
910
#include <atlcomcli.h>
11+
#include <atomic>
1012
#include <shobjidl_core.h>
1113
#include <thread>
1214

@@ -15,7 +17,6 @@
1517
#include "Windows.h"
1618
#include "shlobj_core.h"
1719

18-
1920
std::atomic_bool mb_shell::context_menu_hooks::has_active_menu = false;
2021

2122
void mb_shell::context_menu_hooks::install_common_hook() {
@@ -43,21 +44,18 @@ void mb_shell::context_menu_hooks::install_common_hook() {
4344
menu menu = menu::construct_with_hmenu(hMenu, hWnd);
4445
perf.end("construct_with_hmenu");
4546

46-
auto selected_menu_future = renderer
47-
.add_task([&]() {
48-
auto menu_render = menu_render::create(x, y, menu);
49-
menu_render.rt->last_time = menu_render.rt->clock.now();
50-
51-
perf.end("menu_render::create");
52-
menu_render.rt->start_loop();
47+
auto selected_menu_future = renderer.add_task([&]() {
48+
auto menu_render = menu_render::create(x, y, menu);
49+
menu_render.rt->last_time = menu_render.rt->clock.now();
5350

54-
return menu_render.selected_menu;
55-
});
51+
perf.end("menu_render::create");
52+
menu_render.rt->start_loop();
5653

57-
qjs::wait_with_msgloop([&]() {
58-
selected_menu_future.wait();
54+
return menu_render.selected_menu;
5955
});
6056

57+
qjs::wait_with_msgloop([&]() { selected_menu_future.wait(); });
58+
6159
auto selected_menu = selected_menu_future.get();
6260

6361
has_active_menu = false;
@@ -110,6 +108,55 @@ void mb_shell::context_menu_hooks::install_SHCreateDefaultContextMenu_hook() {
110108
auto SHELL32_SHCreateDefaultContextMenu =
111109
shell32.value()->exports("SHELL32_SHCreateDefaultContextMenu");
112110

111+
static std::atomic_bool close_next_create_window_exw_window = false;
112+
113+
auto user32 = proc->module("user32.dll");
114+
auto CreateWindowExWFunc = user32.value()->exports("CreateWindowExW");
115+
if (!CreateWindowExWFunc) {
116+
std::cerr << "Failed to find CreateWindowExW in user32.dll" << std::endl;
117+
}
118+
static auto CreateWindowExWHook = CreateWindowExWFunc->inline_hook();
119+
CreateWindowExWHook->install(+[](DWORD dwExStyle, LPCWSTR lpClassName,
120+
LPCWSTR lpWindowName, DWORD dwStyle, int X,
121+
int Y, int nWidth, int nHeight,
122+
HWND hWndParent, HMENU hMenu,
123+
HINSTANCE hInstance,
124+
LPVOID lpParam) -> HWND {
125+
std::wstring class_name = [&]{
126+
if (!lpClassName) {
127+
return std::wstring(L"");
128+
}
129+
if (blook::Pointer((void*)lpClassName).try_read<int>()) {
130+
return std::wstring(lpClassName);
131+
} else {
132+
// read as registered class
133+
wchar_t class_name_buffer[256];
134+
if (GetClassNameW((HWND)lpClassName, class_name_buffer, 256) > 0) {
135+
return std::wstring(class_name_buffer);
136+
} else {
137+
return std::wstring(L"");
138+
}
139+
}
140+
}();
141+
142+
bool should_close =
143+
close_next_create_window_exw_window &&
144+
class_name.starts_with(L"HwndWrapper[OneCommander.exe");
145+
146+
if (should_close) {
147+
dwStyle &= ~WS_VISIBLE;
148+
}
149+
150+
auto res = CreateWindowExWHook->call_trampoline<HWND>(
151+
dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight,
152+
hWndParent, hMenu, hInstance, lpParam);
153+
if (res && should_close) {
154+
close_next_create_window_exw_window = false;
155+
PostMessageW(res, WM_CLOSE, 0, 0);
156+
}
157+
return res;
158+
});
159+
113160
/**
114161
prototype: SHSTDAPI SHCreateDefaultContextMenu(
115162
[in] const DEFCONTEXTMENU *pdcm,
@@ -123,12 +170,11 @@ void mb_shell::context_menu_hooks::install_SHCreateDefaultContextMenu_hook() {
123170
SHELL32_SHCreateDefaultContextMenu->inline_hook();
124171
SHCreateDefaultContextMenuHook->install(+[](DEFCONTEXTMENU *def, REFIID riid,
125172
void **ppv) -> HRESULT {
126-
IContextMenu *pdcm = NULL;
127173
SHCreateDefaultContextMenuHook->uninstall();
128-
auto res =
129-
SHCreateDefaultContextMenu(def, riid, reinterpret_cast<void **>(&pdcm));
174+
auto res = SHCreateDefaultContextMenu(def, riid, ppv);
130175
SHCreateDefaultContextMenuHook->install();
131176

177+
IContextMenu *pdcm = (IContextMenu *)*ppv;
132178
if (SUCCEEDED(res) && pdcm) {
133179
IContextMenu2 *pcm2 = NULL;
134180

@@ -158,8 +204,10 @@ void mb_shell::context_menu_hooks::install_SHCreateDefaultContextMenu_hook() {
158204

159205
pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
160206
}
207+
208+
close_next_create_window_exw_window = true;
161209
}
162210

163-
return S_FALSE;
211+
return res;
164212
});
165213
}

0 commit comments

Comments
 (0)