#include // NT 4 doesn't have FlashWindowEx. typedef BOOL (WINAPI *t_FlashWindowEx)(FLASHWINFO*); t_FlashWindowEx p_FlashWindowEx; #define FlashWindowEx p_FlashWindowEx #ifdef USE_DETOURS #include "detours.h" // see http://research.microsoft.com/sn/detours/ extern "C" { DETOUR_TRAMPOLINE(BOOL WINAPI Real_SetForegroundWindow(HWND hWnd), SetForegroundWindow); } #else // IAT patching hook method. See http://www.naughter.com/hookimportfunction.html // compile with cl /LD focuskiller.cpp HookImportFunction.cpp user32.lib #include "HookImportFunction.h" typedef BOOL (WINAPI *t_SetForegroundWindow)(HWND); t_SetForegroundWindow Real_SetForegroundWindow; #endif DWORD mypid; BOOL WINAPI Mine_SetForegroundWindow(HWND hWnd) { DWORD pid; HWND fg = GetForegroundWindow(); HWND owner = GetWindow(hWnd, GW_OWNER); GetWindowThreadProcessId(fg, &pid); #ifdef _DEBUG char buf[500]; wsprintf(buf, "SetForegroundWindow(%x): owner = %x, %d <-> %d", hWnd, owner, pid, mypid); OutputDebugString(buf); #endif // Disallow if // a) another process' window is in the foreground // b) the window to be put in front is a top-level window (should avoid putting one IDEA project in front of another one) if (mypid != pid || owner == NULL) { if (FlashWindowEx != NULL) { FLASHWINFO fw; fw.cbSize = sizeof(fw); fw.hwnd = hWnd; fw.uCount = 5; fw.dwTimeout = 0; fw.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG; FlashWindowEx(&fw); } else { FlashWindow(hWnd, TRUE); } return TRUE; // fake success } return Real_SetForegroundWindow(hWnd); } void HookFunctions(HMODULE hModule) { #ifdef USE_DETOURS #ifdef _DEBUG OutputDebugString("Using Detours hook..."); #endif DetourFunctionWithTrampoline((PBYTE)Real_SetForegroundWindow, (PBYTE)Mine_SetForegroundWindow); #else #ifdef _DEBUG OutputDebugString("Using IAT patching hook..."); #endif HOOKFUNCDESC hook; hook.szFunc = "SetForegroundWindow"; hook.pProc = (PROC)Mine_SetForegroundWindow; // hooking LoadLibrary and waiting until awt.dll is being loaded by java would be more correct but this works too HMODULE awtModule = LoadLibrary("awt.dll"); BOOL b = HookImportFunctionsByName(awtModule, "user32.dll", 1, &hook, (PROC *)&Real_SetForegroundWindow, NULL); if (!b) { char buf[200]; wsprintf(buf, "Hooking SetForegroundWindow failed [0x%x]", GetLastError()); OutputDebugString(buf); } #endif #ifdef _DEBUG OutputDebugString("Functions hooked"); #endif } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { if (fdwReason == DLL_PROCESS_ATTACH) { #ifdef _DEBUG char buf[200]; wsprintf(buf, "DLL Attached"); OutputDebugString(buf); #endif mypid = GetCurrentProcessId(); p_FlashWindowEx = (t_FlashWindowEx)GetProcAddress(GetModuleHandle("user32.dll"), "FlashWindowEx"); DisableThreadLibraryCalls((HMODULE)hinstDLL); HookFunctions((HMODULE)hinstDLL); } return TRUE; }