-
Notifications
You must be signed in to change notification settings - Fork 166
Add Internet Status Indicator Mod #2167
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
Conversation
m417z
left a comment
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.
Thanks for the contribution. I guess the mod, or most of it, was created with AI, which is quite impressive.
This mod has no good reason to run as part of explorer.exe, except that it's convenient. We discussed it here: #1916 (comment)
This mod is injected into explorer and runs as part of it. This is suboptimal for the following reasons:
- There can be more than one explorer.exe process in case the "launch folder windows in separate process" option is enabled, and for other reasons.
- This mod doesn't have a good reason to be injected into explorer.exe, it's just convenient. But by doing so, a mistake or instability in the mod affects the whole shell.
This is not the first mod to take this approach. Here are other recent mods:
And maybe also:
All three mods could be separate tools, they don't use and don't need Windhawk's injection and hooking capabilities. On the other hand, I can understand that the ease of mod installation is appealing. I wonder if Windhawk needs to come up with a new type of mods which run as part of a dedicated process.
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:
- Add the code above at the end of your mod code
- Replace
Wh_ModInit,Wh_ModSettingsChanged,Wh_ModUninitin your code toWhTool_*, e.g.WhTool_ModInit - Change the target process from
explorer.exetowindhawk.exe
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.
|
I have made the changes as specified, is there anything else? |
|
Looks like you didn't do this part:
Note that there's attached code under that "Details" collapsed section. |
You're right |
|
Several users reported that the tray icon isn't being created on startup. The reason is that the mod doesn't handle the taskbar creation notification. |
|
Changing the target process from windhawk.exe to explorer.exe fixes the issue, do you want to proceed with that? |
|
Maybe it makes it less likely because the mod starts working at a later stage this way, but it can still run too early, before the tray is ready. Also, it won't restore the tray icon if explorer crashes or restarts. Have you tried adding handling for the "TaskbarCreated" message as I suggested? |
No description provided.