blob: 0d19a53f2d7a82a7136d22c5a708efa7bda672fb [file] [log] [blame]
#include <windows.h>
// 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;
}