Reputation: 123
I'm trying to intercept an HID "Mice/other poninting device" left button clicks, and I'm just losing it. I'm running on 64bits Win 11 if it makes any difference.
SetWindowsHookExW returns 0 & GetLastError also returns 0. WinError() call simply returns "[WinError 126] The specified module could not be found."
Please Please help!! Below is my code.
import ctypes
from ctypes import wintypes
import win32api
import win32con
# Define the callback function type
HOOKPROC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM)
# Define the callback function for the mouse hook
def low_level_mouse_proc(nCode, wParam, lParam):
if nCode == 0:
return 1
# if wParam == win32con.WM_LBUTTONDOWN: # Intercept left-click down event
# print("Left click intercepted, disabling original click")
# # Return 1 to block the default left-click
# return 1
#
# if wParam == win32con.WM_LBUTTONUP: # Intercept left-click up event
# print("Left click release intercepted")
# # Return 1 to block the default left-click
# return 1
# Call next hook in chain if we are not blocking
return ctypes.windll.user32.CallNextHookEx(None, nCode, wParam, lParam)
# Convert the Python function to a C callback function
low_level_mouse_proc_c = HOOKPROC(low_level_mouse_proc)
# Setting the hook
def set_mouse_hook():
WH_MOUSE_LL = 14
module = ctypes.WinDLL('kernel32', use_last_error=True)
print("Hooking")
mouse_hook = ctypes.windll.user32.SetWindowsHookExW(
WH_MOUSE_LL,
low_level_mouse_proc_c,
module.GetModuleHandleW(None), # Ensure proper module handle
0
)
if not mouse_hook:
print(ctypes.WinError())
return mouse_hook
Upvotes: 0
Views: 68
Reputation: 41147
In short, your code is full of Undefined Behavior.
The cause is explained in [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) - that's a common pitfall when working with CTypes (calling functions).
The error you're getting (126) is also triggered by that. Check the @TODO line in my code (below).
I'm posting a corrected variant.
code00.py:
#!/usr/bin/env python
import ctypes as cts
import msvcrt
import sys
from ctypes import wintypes as wts
import win32api as wapi
import win32con as wcon
WH_MOUSE = 7
WH_MOUSE_LL = 14
LRESULT = cts.c_size_t
HOOKProc = cts.WINFUNCTYPE(LRESULT, cts.c_int, wts.WPARAM, wts.LPARAM)
LowLevelMouseProc = HOOKProc
MouseProc = HOOKProc
kernel32 = cts.windll.kernel32
user32 = cts.windll.user32
SetWindowsHookExA = user32.SetWindowsHookExA
SetWindowsHookExA.argtypes = (cts.c_int, HOOKProc, wts.HINSTANCE, wts.DWORD)
SetWindowsHookExA.restype = wts.HHOOK
CallNextHookEx = user32.CallNextHookEx
CallNextHookEx.argtypes = (wts.HHOOK, cts.c_int, wts.WPARAM, wts.LPARAM)
CallNextHookEx.restype = LRESULT
UnhookWindowsHookEx = user32.UnhookWindowsHookEx
UnhookWindowsHookEx.argtypes = (wts.HHOOK,)
UnhookWindowsHookEx = wts.BOOL
GetLastError = kernel32.GetLastError
GetLastError.argtypes = ()
GetLastError.restype = wts.DWORD
GetModuleHandleW = kernel32.GetModuleHandleW
GetModuleHandleW.argtypes = (wts.LPCWSTR,)
GetModuleHandleW.restype = wts.HMODULE # @TODO - cfati: Decomment to run into your error
GetCurrentThreadId = kernel32.GetCurrentThreadId
GetCurrentThreadId.argtypes = ()
GetCurrentThreadId.restype = wts.DWORD
def handle_mouse_event(code, w_param, l_param):
#print("kkt")
if code < 0:
return CallNextHookEx(code, w_param, l_param)
else:
if w_param == wcon.WM_LBUTTONDOWN:
print("LB down")
elif w_param == wcon.WM_LBUTTONUP:
print("LB up")
return CallNextHookEx(code, w_param, l_param)
low_level_mouse_proc = LowLevelMouseProc(handle_mouse_event)
def main(*argv):
k = b"\x00"
while k != b"\x1B":
print("Press a key (ESC to continue) ...")
k = msvcrt.getch()
print("Add hook:")
hinstance = GetModuleHandleW(None)
tid = 0 #GetCurrentThreadId()
print(hinstance, tid)
hook = SetWindowsHookExA(
WH_MOUSE_LL,
low_level_mouse_proc,
hinstance,
tid,
)
print(f"Hook function: {hook}")
if not hook:
print(f"Hook creation failed: {GetLastError()}")
return -1
k = b"\x00"
while k != b"\x1B":
print("Press a key (ESC to continue) ...")
k = msvcrt.getch()
UnhookWindowsHookEx(hook)
if __name__ == "__main__":
print(
"Python {:s} {:03d}bit on {:s}\n".format(
" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32,
sys.platform,
)
)
rc = main(*sys.argv[1:])
print("\nDone.\n")
sys.exit(rc)
Not posting the output, as there's nothing relevant. Note that after setting the hook:
Mouse has a huge lag (it's almost unusable)
I don't see any text printed from the callback
Might be related:
Upvotes: 0