Object Oriented WinAPI hooks
Some time ago I was playing with a WH_GETMESSAGE
message hook to
intercept any mouse and keyboard input. The hook was installed in several UI threads
controlled by different application modules. In order to install a message hook,
you issue the following code:
const HHOOK hHook = ::SetWindowsHookEx(WH_GETMESSAGE, &GetMsgProc, NULL, ::GetCurrentThreadId());
and your GetMsgProc
looks like this one:
LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam) { // Extra work here... return ::CallNextHookEx(NULL, code, wParam, lParam); }
What if you need to pass control over to some object, invoke a member function?
Keep in mind that GetMsgProc
is a free function (that doesn't receive
hook handle in its parameters). Therefore you can't use anything to map invocation
context to OOP world citizens. You could use a global object to overcome this issue,
but still you can't install more than one message hook with the same callback function.
So the only thing that can map to an object ... is the callback function itself. Hopefully, we are able to create that function on the fly, in memory:
struct IGetMessageHookTarget { virtual LRESULT GetMsgProc(int code, WPARAM wParam, LPARAM lParam) { return ::CallNextHookEx(NULL, code, wParam, lParam); } }; class GetMessageHook : IGetMessageHookTarget { static const size_t ProcSize = 18; public: GetMessageHook() { BYTE getMsgProcBytes[ProcSize] = { 0x55, // push ebp 0x8B, 0xEC, // mov ebp,esp 0xA1, 0x00, 0x00, 0x00, 0x00, // mov eax,dword ptr ds:[this] 0xB9, 0x00, 0x00, 0x00, 0x00, // mov ecx,this 0x8B, 0x10, // mov edx,dword ptr [eax] 0x5D, // pop ebp 0xFF, 0xE2, // jmp edx }; *reinterpret_cast<size_t *>(&getMsgProcBytes[4]) = reinterpret_cast<size_t>(this); *reinterpret_cast<size_t *>(&getMsgProcBytes[4 + 1 + sizeof(size_t)]) = reinterpret_cast<size_t>(this); const HANDLE hCurrentProcess = ::GetCurrentProcess(); _getMsgProcBytes = ::VirtualAllocEx(hCurrentProcess, NULL, ProcSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); CopyMemory(_getMsgProcBytes, getMsgProcBytes, sizeof(getMsgProcBytes)); ::VirtualProtectEx(hCurrentProcess, _getMsgProcBytes, ProcSize, PAGE_EXECUTE, NULL); _hHook = ::SetWindowsHookEx(WH_GETMESSAGE, reinterpret_cast<HOOKPROC>(_getMsgProcBytes), NULL, ::GetCurrentThreadId()); } ~GetMessageHook() { ::UnhookWindowsHookEx(_hHook); ::VirtualFreeEx(::GetCurrentProcess(), _getMsgProcBytes, ProcSize, MEM_RELEASE); } protected: virtual LRESULT GetMsgProc(int code, WPARAM wParam, LPARAM lParam) { return ::CallNextHookEx(NULL, code, wParam, lParam); } private: HHOOK _hHook; LPVOID _getMsgProcBytes; };
GetMessageHook
constructor creates an in-memory code that passes
control over to GetMsgProc
member function. Believe me - it works.
At least on x86.
2 коммент.:
Thanks for the good writeup. It actually was a enjoyment account it.
Look advanced to far brought agreeable from you! However, how could we keep in touch?
Also visit my webpage - GFI Norte
After checking out a handful of the blog articles on your site, I seriously appreciate your way of blogging.
I added it to my bookmark site list and will be checking back soon.
Please visit my website as well and let me know your opinion.
Feel free to visit my web-site iphone 5 release date uk
Отправить комментарий