0

I want to check if winproc of a window form was subclassed. Any winapi or spy++ trick to do this?

MarkJoy
  • 55
  • 6
  • why did I get downvote for this question? If you think this is a silly question then let me know. Otherwise, post your answer here. – MarkJoy May 07 '17 at 03:13
  • I'm going to guess it was downvoted because there's very little context here. It's difficult to ask a meaningful question in as little text as you've given. Show what you've tried to solve the problem, and what problems you've run into. – Carcigenicate May 07 '17 at 03:31
  • well, I have an application. This application load a 3rd party .dll . This dll causes the application behave in a different way, which I think the dll subclassed the main app. So I want to check it, but I don't know how. I think it's a simple question to understand. – MarkJoy May 07 '17 at 03:45

1 Answers1

2

you can use next code for determinate is window subclassed by another module (different from module which register window class )

BOOL IsSubclassed(HWND hwnd)
{
    LPARAM pfn = (IsWindowUnicode(hwnd) ? GetWindowLongPtrW : GetWindowLongPtrA)
        (hwnd, GWLP_WNDPROC);

    HMODULE hmod;
    //if (RtlPcToFileHeader(pfn, &hmod))
    if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|
            GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (PCWSTR)pfn, &hmod))
    {
        DbgPrint("pfn=%p hmod=%p\n", pfn, hmod);

        return hmod != (HMODULE)GetClassLongPtrW(hwnd, GCLP_HMODULE);
    }

    // pfn not in any module - guess subclassed
    return TRUE;
}

note: GetWindowLongPtrA(hwnd, GWLP_WNDPROC) and GetWindowLongPtrW(hwnd, GWLP_WNDPROC) - always return different result - one address of the window procedure and another - handle representing the address of the window procedure : special internal value meaningful only to CallWindowProc - for determine which version A or W retrieves the address of the window procedure - need call IsWindowUnicode. this is undocumented, but reasonable. if subclassed procedure have the same ANSI or UNICODE native that original procedure it can direct call original. if native is different - need translation (Unicode <-> ANSI) for window messages. windows assume that caller or GetWindowLongPtrA is native ANSI window and caller of GetWindowLongPtrW is native UNICODE window. and return pointer to the window procedure if the same native (A and A or W and W) otherwise returned handle

from another side GetClassLongPtrW(hwnd, GCLP_HMODULE) and GetClassLongPtrA(hwnd, GCLP_HMODULE) - always return the same result

RbMm
  • 31,280
  • 3
  • 35
  • 56
  • result - `IsSubclassed` of course correct retrieve `HMODULE` for current window procedure and original `HMODULE` for `RegisterClass` call and compare it. usually if *another* dll subclass window procedure - if will be placed inside this dll or in allocated memory stub - and as result `HMODULE` will be different and `IsSubclassed` return true. but say if you use ATL, which always allocate stubs for window proc, `IsSubclassed` - always return true. from another side - may be your guess about 3rd party .dll is false - it not subclass any window. – RbMm May 07 '17 at 09:39
  • @MarkJoy - but main point i show - you need get the current windows procedure address and look to where it point – RbMm May 07 '17 at 09:40
  • I tried your code and here is the result. Before subclassing: - pfn: 157817552 - hmod: 261157889 - GetClassLongPtrW(hwnd, GCLP_HMODULE): 11796480 - IsSubclassed: true After subclassing: - pfn: 261129728 - hmod: 0 - GetClassLongPtrW(hwnd, GCLP_HMODULE): 11796480 - IsSubclassed: true – MarkJoy May 07 '17 at 10:02
  • @MarkJoy - you paste wrong data - can not be hmod: 261157889. in any case. and for pfn: 157817552. and need look all this values in hex but not in dec – RbMm May 07 '17 at 10:12
  • Ok, I convert numbers into hex. Here is the result after running the code one more time. After subclassing hmod is 0x3 ?? Before subclassing: pfn: 0x10231ad0 hmod: 0x8a5f501 GetClassLongPtrW(hwnd, GCLP_HMODULE): 0xb40000 IsSubclassed: true After subclassing: pfn: 0x8a58630 hmod: 0x3 GetClassLongPtrW(hwnd, GCLP_HMODULE): 0xb40000 IsSubclassed: true – MarkJoy May 07 '17 at 10:18
  • @MarkJoy `hmod: 0x8a5f501` - this can not be. at first hmod always must have 0000 at the end (64kb aligned) at second `0x10231ad0` and `0x8a5f501` absolute unrelated . you paste wrong values. can not GetModuleHandleExW return `0x8a5f501` for `0x10231ad0` – RbMm May 07 '17 at 10:20
  • @MarkJoy - your original window proc is `****1ad0` (high 4 bytes always different because module is loaded every time at new base (aslr) but low 4 bytes - this is offset in module - constant) but how you paste `hmod` from `pfn` is wrong - can not be so result. look better. how you give this values (form debugger view, or by dbgprint ) ? – RbMm May 07 '17 at 10:29
  • you also can use [RtlPcToFileHeader](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680603(v=vs.85).aspx) instead `GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT` (i edit post) and `DbgPrint("pfn=%p hmod=%p\n", pfn, hmod);` (or how you debug print) but what you paste as `hmod` is definitely wrong – RbMm May 07 '17 at 10:40
  • Sorry, I printed the result in wrong order. Here is the updated one: Before Subclassing: pfn: 0x8d01ad0 hmod: 0x8ab0000 GetClassLongPtrW(hwnd, GCLP_HMODULE): 0x1150000 IsSubclassed: 1 After Subclassing: pfn: 0xf3786a0 hmod: 0xf360000 GetClassLongPtrW(hwnd, GCLP_HMODULE): 0x1150000 IsSubclassed: 1 – MarkJoy May 07 '17 at 10:44
  • @MarkJoy - now result is correct. however you say that *Before Subclassing* - window procedure is in *8ab0000* when `WNDCLASS.hInstance` (what is GetClassLongPtrW(hwnd, GCLP_HMODULE) return) - in *1150000* - so already in different modules. think window was already subclassed, which and show my proc. look under debugger, or by `GetModuleFileName` which is this modules ? – RbMm May 07 '17 at 10:48
  • I ran your code against a qt window. It seems that qt window is already subclassed by qt's framework. When I ran your code against a normal window, I got correct result: Before Subclassing: pfn: 0x13c0348 hmod: 0x1380000 GetClassLongPtrW(hwnd, GCLP_HMODULE): 0x1380000 IsSubclassed *: 0 After Subclassing: pfn: 0xfca2ac0 hmod: 0xfc90000 GetClassLongPtrW(hwnd, GCLP_HMODULE): 0x1380000 IsSubclassed *: 1 – MarkJoy May 07 '17 at 11:51
  • Thanks a lot for your help. Although this seems not to work in case of qt window, but if qt window is already subclassed by qt's framework then there is nothing we can do. Any idea to check in case of qt window? – MarkJoy May 07 '17 at 11:56
  • 1
    @MarkJoy I not familiar with QT, so may be it like ATL always redirect window procedure to thunk (in heap) for bind context (class to window). however even in this case we can got useful info (for research) - if `hmod` which we get from `pfn` is 0 - we have thunk(stub) and impossible say - are this make creator of window or 3-rd party code. but if we have not 0 hmod - we can get name of this module and understand who is subclass window – RbMm May 07 '17 at 11:59
  • Sorry to ask you more, but any idea to solve [this question](http://stackoverflow.com/questions/43849907/cant-click-on-controls-menu-when-detach-mdi-child-out-of-mdi-client-area) – MarkJoy May 08 '17 at 14:24