Skip to content

Instantly share code, notes, and snippets.

@pfn
Created February 19, 2016 19:53
Show Gist options
  • Save pfn/8652e9971e4a0253a61b to your computer and use it in GitHub Desktop.
Save pfn/8652e9971e4a0253a61b to your computer and use it in GitHub Desktop.
hooking WndProc in hexchat
from ctypes import *
from ctypes.wintypes import *
import hexchat
import traceback
import sys
__module_name__ = "sethook"
__module_version__ = "1.0"
__module_description__ = "Demonstration of calling SetWindowsLongPtr from ctypes"
WINDOWPROC = WINFUNCTYPE(LPARAM, HWND, UINT, WPARAM, LPARAM)
windll.user32.GetWindowLongPtrA.restype = c_void_p
windll.user32.SetWindowLongPtrA.argtypes = [HWND, c_int, c_void_p]
windll.user32.SetWindowLongPtrA.restype = c_void_p
windll.user32.CallWindowProcA.restype = c_void_p
windll.user32.CallWindowProcA.argtypes = [c_void_p, HWND, c_int, WPARAM, LPARAM]
def log(msg):
ctx = hexchat.find_context(channel=">>python<<")
if ctx:
ctx.emit_print("Notice", "sethook", msg)
unload_hook = None
ENUMWINDOWSPROC = WINFUNCTYPE(BOOL, HWND, LPARAM)
def getLastError():
errno = windll.kernel32.GetLastError()
buf = create_string_buffer(128)
windll.kernel32.FormatMessageA(0x1000, None, errno, 0, pointer(buf), 128, 0)
return buf.value
def unload(arg):
hexchat.unhook(unload_hook)
result = windll.user32.SetWindowLongPtrA(foundHwnd[0], -4, OriginalWndProc)
log("unload result: %x %d" % (result, result))
log("Unloaded sethook")
currentThread = windll.kernel32.GetCurrentThreadId()
def enumWindow(hwnd, lParam):
r = windll.user32.GetWindowThreadProcessId(hwnd, None)
if r == currentThread and windll.user32.IsWindowVisible(hwnd):
hwndOut = cast(lParam, POINTER(HWND))
hwndOut[0] = hwnd
title = create_string_buffer(128)
windll.user32.GetWindowTextA(hwnd, title, 128)
log("%s" % title.value)
return True
unload_hook = hexchat.hook_unload(unload)
foundHwnd = pointer(HWND(0))
r = windll.user32.EnumWindows(ENUMWINDOWSPROC(enumWindow), foundHwnd)
if not r:
log("Failed: %s" % getLastError())
OriginalWndProc = windll.user32.GetWindowLongPtrA(foundHwnd[0], -4)
if OriginalWndProc == 0:
log("Failed: %s" % getLastError())
wrappedWndProc = WINDOWPROC(OriginalWndProc)
def init(ignored):
def WindowProc(hwnd, msg, wParam, lParam):
log("YO")
return windll.user32.CallWindowProcA(OriginalWndProc, hwnd, msg, wParam, lParam)
result = windll.user32.SetWindowLongPtrA(foundHwnd[0], -4, cast(WINDOWPROC(WindowProc), c_void_p))
if result == 0 or result != OriginalWndProc:
log("Failed: %d: %s" % (result, getLastError()))
log("Loaded sethook")
hexchat.hook_timer(5000, init)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment