pythoncom crashes on KeyDown when used hooked to certain applications

I think the problem is that when pyHook gets called back by Windows, the first thing it does is get the window name for the window with focus.

PSTR win_name = NULL;
...
// grab the window name if possible
win_len = GetWindowTextLength(hwnd);
if(win_len > 0) {
  win_name = (PSTR) malloc(sizeof(char) * win_len + 1);
  GetWindowText(hwnd, win_name, win_len + 1);
}

So I think the problem here is that, even if GetWindowText is not returning wide characters, it can return non-ascii characters from an ANSI codepage. That won’t fail, however, until we do this:

// pass the message on to the Python function
arglist = Py_BuildValue("(iiiiiiiz)", wParam, kbd->vkCode, kbd->scanCode, ascii,
                        kbd->flags, kbd->time, hwnd, win_name);

Here, because of the z in the format string, the data in the win_name variable is being converted to a unicode str with Py_BuildValue assuming it is ASCII. But it’s not: and so it can trigger a UnicodeDecodeError. This then causes the arglist to be NULL and therefore your function to be called with no arguments.

So I’m not completely sure on the best fix here. But I just changed both bits of code to use wide characters and unicode instead of ascii, and rebuilt pyHook, and that seemed to fix it. I think it will only work in Python 3 versions, but for Python 2, I think the old pyHook still works anyway.

LPWSTR win_name = NULL;

...
// grab the window name if possible
win_len = GetWindowTextLengthW(hwnd);
if(win_len > 0) {
  win_name = (LPWSTR) malloc(sizeof(wchar_t) * win_len + 1);
  GetWindowTextW(hwnd, win_name, win_len + 1);
}

and

// pass the message on to the Python function
arglist = Py_BuildValue("(iiiiiiiu)", wParam, kbd->vkCode, kbd->scanCode, ascii,
                        kbd->flags, kbd->time, hwnd, win_name);

The problem occurs only with windows with non-ascii characters in their title: Skype is one.

Leave a Comment