В официальном драйвере Alps-pointing-device для Lenovo-G550 под Windows 7 есть такой баг: в настройках тачпада присутствует опция «использовать кнопки Назад/Вперёд», и она работает, но только в Проводнике Windows, а ведь так хотелось, чтобы это работало во всех приложениях.
В общем, используя догадки и приложения для отслеживания вызовов API-функций Windows, выяснил, что процесс Apoint.exe при каждом жесте Вперёд/Назад вызывает функции GetForegroundWindow и GetClassNameA.
И вот оно решение → перехватывать вызов GetClassNameA и всегда возвращать класс окон проводника, а именно — «CabinetWClass».
Перехватывать API я уже давно могу при помощи моего перехватчика:
#pragma pack(1)
class DETOUR
{
struct JMP
{
BYTE instr;
#ifdef WIN32
DWORD
#else
long long
#endif
addr;
}
body_orig,*proc_body;
#ifdef WIN32
DWORD
#else
long long
#endif
addr_my_relative_to_orig;
public:
template<typename T>
void InitAndSet(T hooked_addr,T my_proc)
{
Init(hooked_addr,my_proc);
Set();
}
template<typename T>
void Init(T hooked_addr,T my_proc)
{
proc_body = (JMP*)hooked_addr;
body_orig = *proc_body;
#ifdef WIN32
addr_my_relative_to_orig = DWORD(my_proc)-DWORD(hooked_addr)-5;
#else
???????
#endif
DWORD trash;
VirtualProtect(hooked_addr,5,PAGE_EXECUTE_READWRITE,&trash);
}
__forceinline void Set()
{
#ifdef WIN32
proc_body->instr = 0xE9;
#else
?????
#endif
proc_body->addr = addr_my_relative_to_orig;
}
__forceinline void Restore()
{
*proc_body = body_orig;
}
};
#pragma pack()
И код в DLL'ке, которую нужно inject в целевой процесс:
DETOUR detGetClassNameA;
int _stdcall myGetClassNameA(HWND hwnd,LPSTR buf,int buf_len)
{
static char str[] = "CabinetWClass";
lstrcpyA(buf,str);
return (sizeof str) - 1;
}
BOOL __stdcall myMain(HINSTANCE hModule,DWORD reason,LPVOID lpReserved) // точка входа DllMain
{
if(reason==DLL_PROCESS_ATTACH)
detGetClassNameA.InitAndSet(GetClassNameA,myGetClassNameA);
return TRUE;
}
И радость, работает! Но только в 32-битной Windows, для 64-битной ещё не разобрался какую иструкцию процессора использовать.