-
Notifications
You must be signed in to change notification settings - Fork 166
Add Toggle Hidden Files mod #2636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add Toggle Hidden Files mod #2636
Conversation
| // @author Asteski | ||
| // @github https://github.com/Asteski | ||
| // @include explorer.exe | ||
| // @compilerOptions -std=c++20 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this compiler option needed?
| LoadSettings(); | ||
|
|
||
| // Install keyboard hook | ||
| g_hKeyboardHook = SetWindowsHookExW(WH_KEYBOARD_LL, KeyboardHookProc, GetModuleHandle(nullptr), 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the documentation:
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
Wh_ModInit is either called on the initial Explorer thread, or in a dedicated Windhawk thread. Not in all cases that thread has a message loop. To make it work in all cases, create a dedicated thread for it. Here's an example:
https://github.com/m417z/7-Taskbar-Numberer/blob/master/dll/keybd_hook.c
|
This mod has no good reason to run as part of explorer.exe, except that it's convenient. We discussed it here: #1916 (comment)
Currently, Windhawk doesn't have a built-in functionality for something like that, but for now, I implemented some code that can be added to a mod to make it run as part of a separate windhawk.exe process: Details
////////////////////////////////////////////////////////////////////////////////
// Windhawk tool mod implementation for mods which don't need to inject to other
// processes or hook other functions. Context:
// https://github.com/ramensoftware/windhawk-mods/pull/1916
//
// The mod will load and run in a dedicated windhawk.exe process.
//
// Paste the code below as part of the mod code, and use these callbacks:
// * WhTool_ModInit
// * WhTool_ModSettingsChanged
// * WhTool_ModUninit
//
// Currently, other callbacks are not supported.
bool g_isToolModProcessLauncher;
HANDLE g_toolModProcessMutex;
void WINAPI EntryPoint_Hook() {
Wh_Log(L">");
ExitThread(0);
}
BOOL Wh_ModInit() {
bool isService = false;
bool isToolModProcess = false;
bool isCurrentToolModProcess = false;
int argc;
LPWSTR* argv = CommandLineToArgvW(GetCommandLine(), &argc);
if (!argv) {
Wh_Log(L"CommandLineToArgvW failed");
return FALSE;
}
for (int i = 1; i < argc; i++) {
if (wcscmp(argv[i], L"-service") == 0) {
isService = true;
break;
}
}
for (int i = 1; i < argc - 1; i++) {
if (wcscmp(argv[i], L"-tool-mod") == 0) {
isToolModProcess = true;
if (wcscmp(argv[i + 1], WH_MOD_ID) == 0) {
isCurrentToolModProcess = true;
}
break;
}
}
LocalFree(argv);
if (isService) {
return FALSE;
}
if (isCurrentToolModProcess) {
g_toolModProcessMutex =
CreateMutex(nullptr, TRUE, L"windhawk-tool-mod_" WH_MOD_ID);
if (!g_toolModProcessMutex) {
Wh_Log(L"CreateMutex failed");
ExitProcess(1);
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
Wh_Log(L"Tool mod already running (%s)", WH_MOD_ID);
ExitProcess(1);
}
if (!WhTool_ModInit()) {
ExitProcess(1);
}
IMAGE_DOS_HEADER* dosHeader =
(IMAGE_DOS_HEADER*)GetModuleHandle(nullptr);
IMAGE_NT_HEADERS* ntHeaders =
(IMAGE_NT_HEADERS*)((BYTE*)dosHeader + dosHeader->e_lfanew);
DWORD entryPointRVA = ntHeaders->OptionalHeader.AddressOfEntryPoint;
void* entryPoint = (BYTE*)dosHeader + entryPointRVA;
Wh_SetFunctionHook(entryPoint, (void*)EntryPoint_Hook, nullptr);
return TRUE;
}
if (isToolModProcess) {
return FALSE;
}
g_isToolModProcessLauncher = true;
return TRUE;
}
void Wh_ModAfterInit() {
if (!g_isToolModProcessLauncher) {
return;
}
WCHAR currentProcessPath[MAX_PATH];
switch (GetModuleFileName(nullptr, currentProcessPath,
ARRAYSIZE(currentProcessPath))) {
case 0:
case ARRAYSIZE(currentProcessPath):
Wh_Log(L"GetModuleFileName failed");
return;
}
WCHAR
commandLine[MAX_PATH + 2 +
(sizeof(L" -tool-mod \"" WH_MOD_ID "\"") / sizeof(WCHAR)) - 1];
swprintf_s(commandLine, L"\"%s\" -tool-mod \"%s\"", currentProcessPath,
WH_MOD_ID);
HMODULE kernelModule = GetModuleHandle(L"kernelbase.dll");
if (!kernelModule) {
kernelModule = GetModuleHandle(L"kernel32.dll");
if (!kernelModule) {
Wh_Log(L"No kernelbase.dll/kernel32.dll");
return;
}
}
using CreateProcessInternalW_t = BOOL(WINAPI*)(
HANDLE hUserToken, LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, WINBOOL bInheritHandles,
DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation,
PHANDLE hRestrictedUserToken);
CreateProcessInternalW_t pCreateProcessInternalW =
(CreateProcessInternalW_t)GetProcAddress(kernelModule,
"CreateProcessInternalW");
if (!pCreateProcessInternalW) {
Wh_Log(L"No CreateProcessInternalW");
return;
}
STARTUPINFO si{
.cb = sizeof(STARTUPINFO),
.dwFlags = STARTF_FORCEOFFFEEDBACK,
};
PROCESS_INFORMATION pi;
if (!pCreateProcessInternalW(nullptr, currentProcessPath, commandLine,
nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS,
nullptr, nullptr, &si, &pi, nullptr)) {
Wh_Log(L"CreateProcess failed");
return;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
void Wh_ModSettingsChanged() {
if (g_isToolModProcessLauncher) {
return;
}
WhTool_ModSettingsChanged();
}
void Wh_ModUninit() {
if (g_isToolModProcessLauncher) {
return;
}
WhTool_ModUninit();
ExitProcess(0);
}Please do the following:
Please try it and let me know if it behaves as expected in all cases. If it is, let's adapt it. In the future, such functionality might become part of Windhawk. |
Toggle Hidden Files
This mod allows you to toggle the visibility of hidden files in Windows Explorer using the Ctrl+H keyboard shortcut.
Features
Usage
Settings
Technical Details