Last active
December 17, 2024 06:08
-
-
Save m417z/f0cdf071868a6f31210e84dd0d444055 to your computer and use it in GitHub Desktop.
A mod that implements a workaround for Windhawk for https://github.com/mstorsjo/llvm-mingw/issues/459
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==WindhawkMod== | |
// @id process-shutdown-message-box-fix | |
// @name Process shutdown message box fix | |
// @description Fixes message box and beep sound on process shutdown, e.g. when launching folders via an explorer shortcut | |
// @version 0.3 | |
// @author m417z | |
// @github https://github.com/m417z | |
// @twitter https://twitter.com/m417z | |
// @homepage https://m417z.com/ | |
// @include * | |
// ==/WindhawkMod== | |
#include <stdlib.h> | |
// Just to make the mod depend on libc++. | |
#include <vector> | |
std::vector<int> g_v; | |
using _errno_t = decltype(&_errno); | |
HMODULE g_libCpp; | |
void** g_ppSetlocale; | |
HMODULE g_msvcrtModule; | |
_errno_t g_msvcrtErrno; | |
void** FindImportPtr(HMODULE hFindInModule, | |
PCSTR pModuleName, | |
PCSTR pImportName) { | |
IMAGE_DOS_HEADER* pDosHeader; | |
IMAGE_NT_HEADERS* pNtHeader; | |
ULONG_PTR ImageBase; | |
IMAGE_IMPORT_DESCRIPTOR* pImportDescriptor; | |
ULONG_PTR* pOriginalFirstThunk; | |
ULONG_PTR* pFirstThunk; | |
ULONG_PTR ImageImportByName; | |
// Init | |
pDosHeader = (IMAGE_DOS_HEADER*)hFindInModule; | |
pNtHeader = (IMAGE_NT_HEADERS*)((char*)pDosHeader + pDosHeader->e_lfanew); | |
if (!pNtHeader->OptionalHeader.DataDirectory[1].VirtualAddress) | |
return nullptr; | |
ImageBase = (ULONG_PTR)hFindInModule; | |
pImportDescriptor = | |
(IMAGE_IMPORT_DESCRIPTOR*)(ImageBase + | |
pNtHeader->OptionalHeader.DataDirectory[1] | |
.VirtualAddress); | |
// Search! | |
while (pImportDescriptor->OriginalFirstThunk) { | |
if (lstrcmpiA((char*)(ImageBase + pImportDescriptor->Name), | |
pModuleName) == 0) { | |
pOriginalFirstThunk = | |
(ULONG_PTR*)(ImageBase + pImportDescriptor->OriginalFirstThunk); | |
ImageImportByName = *pOriginalFirstThunk; | |
pFirstThunk = | |
(ULONG_PTR*)(ImageBase + pImportDescriptor->FirstThunk); | |
while (ImageImportByName) { | |
if (!(ImageImportByName & IMAGE_ORDINAL_FLAG)) { | |
if ((ULONG_PTR)pImportName & ~0xFFFF) { | |
ImageImportByName += sizeof(WORD); | |
if (lstrcmpA((char*)(ImageBase + ImageImportByName), | |
pImportName) == 0) | |
return (void**)pFirstThunk; | |
} | |
} else { | |
if (((ULONG_PTR)pImportName & ~0xFFFF) == 0) | |
if ((ImageImportByName & 0xFFFF) == | |
(ULONG_PTR)pImportName) | |
return (void**)pFirstThunk; | |
} | |
pOriginalFirstThunk++; | |
ImageImportByName = *pOriginalFirstThunk; | |
pFirstThunk++; | |
} | |
} | |
pImportDescriptor++; | |
} | |
return nullptr; | |
} | |
using SetLocale_t = char*(__cdecl*)(int category, const char* locale); | |
SetLocale_t SetLocale_Original; | |
char* __cdecl SetLocale_Wrapper(int category, const char* locale) { | |
// A workaround for https://github.com/mstorsjo/llvm-mingw/issues/459. | |
errno_t* err = g_msvcrtErrno(); | |
HMODULE module; | |
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | | |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, | |
(PCWSTR)err, &module) && | |
module == g_msvcrtModule) { | |
// Getting a process-wide errno from the module section instead of the | |
// thread errno from the heap means we have no PTD (Per-thread data) and | |
// setlocale will fail, likely with a message box and abort. Return NULL | |
// instead to let the caller handle it gracefully. | |
Wh_Log(L"Returning NULL for setlocale"); | |
return nullptr; | |
} | |
return SetLocale_Original(category, locale); | |
} | |
bool InitGlobals() { | |
if (!GetModuleHandleEx(0, L"libc++.dll", &g_libCpp)) { | |
Wh_Log(L"No libc++.dll"); | |
return false; | |
} | |
g_ppSetlocale = FindImportPtr(g_libCpp, "msvcrt.dll", "setlocale"); | |
if (!g_ppSetlocale) { | |
Wh_Log(L"No setlocale"); | |
return false; | |
} | |
if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, | |
(PCWSTR)*g_ppSetlocale, &g_msvcrtModule)) { | |
Wh_Log(L"No setlocale module"); | |
return false; | |
} | |
if (g_msvcrtModule != GetModuleHandle(L"msvcrt.dll")) { | |
Wh_Log(L"Bad setlocale module, already patched?"); | |
Wh_Log(L"%p %p", g_msvcrtModule, GetModuleHandle(L"msvcrt.dll")); | |
return false; | |
} | |
g_msvcrtErrno = (_errno_t)GetProcAddress(g_msvcrtModule, "_errno"); | |
if (!g_msvcrtErrno) { | |
Wh_Log(L"No _errno"); | |
return false; | |
} | |
return true; | |
} | |
BOOL Wh_ModInit() { | |
Wh_Log(L">"); | |
if (!InitGlobals()) { | |
if (g_msvcrtModule) { | |
FreeLibrary(g_msvcrtModule); | |
} | |
if (g_libCpp) { | |
FreeLibrary(g_libCpp); | |
} | |
return FALSE; | |
} | |
DWORD dwOldProtect; | |
VirtualProtect(g_ppSetlocale, sizeof(*g_ppSetlocale), | |
PAGE_EXECUTE_READWRITE, &dwOldProtect); | |
SetLocale_Original = (SetLocale_t)*g_ppSetlocale; | |
*g_ppSetlocale = (void*)SetLocale_Wrapper; | |
VirtualProtect(g_ppSetlocale, sizeof(*g_ppSetlocale), dwOldProtect, | |
&dwOldProtect); | |
return TRUE; | |
} | |
void Wh_ModUninit() { | |
Wh_Log(L">"); | |
DWORD dwOldProtect; | |
VirtualProtect(g_ppSetlocale, sizeof(*g_ppSetlocale), | |
PAGE_EXECUTE_READWRITE, &dwOldProtect); | |
*g_ppSetlocale = (void*)SetLocale_Original; | |
VirtualProtect(g_ppSetlocale, sizeof(*g_ppSetlocale), dwOldProtect, | |
&dwOldProtect); | |
FreeLibrary(g_msvcrtModule); | |
FreeLibrary(g_libCpp); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@mkacct It seems to happen because the process exits really quickly after launching. This mod tries to implement a workaround, but it's not perfect. Rather than improving it, I'd rather invest my time in a new Windhawk version with a proper fix.
For now, I suggest to exclude
wslservice.exe
in Windhawk, I assume you don't have relevant mods for it. For excluding a process in Windhawk, check out the short video here.Thanks for the feedback, and let me know if you need help with one of the steps.