Why does this window subclassing code crash? - winapi

I am trying to subclass the window that currently has focus. I do this by monitoring for HCBT_ACTIVATE events using a CBT hook, and set and unset the WndProc of the focused and previously focused windows.
The problem is that it only works whenever I have a breakpoint set somewhere in the code.
If there is no breakpoint, once my application exits, all the windows that I have subclassed crashes in order, even though I have removed the subclassing and restored the original WndProc.
I have verified that Unsubclass() is called whenever my application shuts down.
// code extracts
HINSTANCE hInst;
HHOOK hHook;
#pragma data_seg(".shared")
HWND hWndSubclass = 0;
FARPROC lpfnOldWndProc = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:.shared,rws")
void Unsubclass()
{
// if the window still exists
if (hWndSubclass != 0 && IsWindow(hWndSubclass))
{
SetWindowLongPtr(hWndSubclass, GWLP_WNDPROC, (LPARAM)lpfnOldWndProc);
hWndSubclass = 0;
}
}
static LRESULT CALLBACK SubClassFunc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_MOVING)
{
// this is just test code so I can see it works (it does)
RECT* r = (RECT*)lParam;
r->right = r->left + 500;
r->bottom = r->top + 500;
return TRUE;
}
else if (message == WM_DESTROY)
{
Unsubclass();
}
return CallWindowProc((WNDPROC)lpfnOldWndProc, hWndSubclass, message, wParam, lParam);
}
void SubclassWindow(HWND hWnd)
{
// remove the subclassing for the old window
Unsubclass();
// subclass the new window
lpfnOldWndProc = (FARPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LPARAM)SubClassFunc);
hWndSubclass = hWnd;
}
static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_ACTIVATE)
{
SubclassWindow((HWND)wParam);
}
return 0;
}
// ... code that initializes the CBT proc
__declspec(dllexport) BOOL Setup()
{
hHook = SetWindowsHookEx(WH_CBT, CBTProc, hInst, 0);
}
__declspec(dllexport) BOOL Teardown()
{
UnhookWindowsHookEx(hHook);
Unsubclass();
}
BOOL APIENTRY DllMain( HINSTANCE hInstance,
DWORD Reason,
LPVOID Reserved
)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
hInst = hInstance;
return TRUE;
case DLL_PROCESS_DETACH:
Unsubclass();
return TRUE;
}
return TRUE;
}

Your problems hinge on several fronts:
UnHookWindowsHook does not unload injected dlls, all it does is remove the hook proc. If the dlls need to be unloaded its up to them to invent some kind of unloading mechanism.
SetWindowLongPtr typically fails when called from a process other than the process that owns the window.
The nett result of this is, its very difficult to safely remove windows hooks. First thing, your OldWindowProc pointer should not be stored in the shared data area. Next, in order to remove the subclass, you need to be able to co-erce the (currently) subclassed process to perform the un-subclassing.
What you could do is, first, register a new unique message id and place it in your shared area using RegisterWindowMessage. WM_REMOVE_HOOK.
UINT idWM_REMOVE_HOOK = RegisterWindowMessage("WM_REMOVE_HOOK");
Now, whenever you need to remove a hook,
SendMessage(hWndSubClass,idWM_REMOVE_HOOK,0,0);
In your subclass proc:
if(uMsg == WM_DESTROY || uMsg == idWM_REMOVE_HOOK)
{
Unsubclass(hwnd);
}
Remove the call to UnSubClass in DLL_PROCESS_DETATCH. Its a dangerous race condition thats going to cause your dll being unloaded in some random process to trash the hook data of a potentially valid hook in another process.

lpfnOldWndProc and hWndSubclass are global pointers. Seems like you've got only one per process. What if a process creates more than one window?
Then you will unsubclass only the last one.
EDIT: Also, why do you tear down in Process DETACH?

You are creating a global system-wide hook in a DLL. You need to store the HHOOK handle and your subclassing information in a block of shared memory so all instances of your DLL in all running processes can have access to them. Your variables are declared global in code, but each individual instance of the DLL will have its own local copy of them, and thus they will not be not initialized in all but 1 of your DLL instances (the one that calls Setup()). They need to be shared globally within the entire system instead.
You also should not be calling TearDown() in DLL_PROCESS_DETACH, either. Every instance of the DLL is going to call TearDown() when their respective processes terminate, but only the single instance that actually called Setup() should be the one to call Teardown().

If the debugger will cause the process to succeed by adding a breakpoint then most likely, this is a timing issue.
What possibly happens is that your main application is closing itself and freeing resources just before the subclassed windows get the messages they need to remove the subclass again. You might want to give them a few processing cycles to handle their own messages between the unhooking and the unsubclassing. (In Delphi you could do this by calling Application.ProcessMessages but in your C++ version? Don't know the answer to that.

Related

SetWindowHookEx() returns NULL

I'm trying to create an application that will be notified about each active window change in Windows so it could do some tasks like detecting window titles, therefore "punishing" bad people accessing bad content on our PC machines. So, this is really important for the application because it's purpose is to log "bad" applications from history.
So, in my main function, I started a thread for my WindowLogger.
windowThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) WindowLogger,
(LPVOID) argv[0], 0, NULL );
if (windowThread)
{
// Also a bit of protection here..
return WaitForSingleObject(windowThread, INFINITE);
}
Then, here is my WindowLogger procedure:
// Function called by main function to install hook
DWORD WINAPI
WindowLogger(LPVOID lpParameter)
{
HHOOK hWinHook;
HINSTANCE hExe = GetModuleHandle(NULL);
if (!hExe)
{
return 1;
}
else
{
hWinHook = SetWindowsHookEx(WH_CBT, (HOOKPROC) CBTProc, hExe, 0);
MSG msg;
// I AM UNSURE ABOUT THIS PART..
// Probably wrong code :D ..
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
if (msg.message == HCBT_ACTIVATE) {
// my code to log the window name
}
}
UnhookWindowsHookEx(hWinHook);
}
return 0;
}
And finally, my CBTProc callback function, it logs the windows using my log() function:
LRESULT CALLBACK
CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
switch (nCode)
{
case HCBT_ACTIVATE:
{
HWND foreground = GetForegroundWindow();
char window_title[50];
if (foreground)
GetWindowText(foreground, window_title, 25);
log("|");
log(&window_title[0]);
log("|");
}
}
}
So I had debugged the program and what I figured out is that hWinHook becomes NULL after SetWindowsHookEx() -- this is what probably causes my program to mailfunction..
.. Can you help me out with this?
Thanks in advance.
Passing 0 for the dwThreadId parameter to SetWindowsHookEx is used to register a hook for all threads in the system, i.e. a global hook. However to do this, your hook code needs to be located within a DLL (so that the DLL can be mapped into the address space of other processes). Since your hook code is in your main executable rather than a DLL the call is failing.

how to create a hidden window by extending CWnd class in visual c++

Can any one help me in creating a Hidden window by extending CWnd class. I'm new to windows programming.
I've tried creating one, but the issue is code breaks down when trying to register the window class or creating a window.
class HiddenWindow : public CWnd
{
public:
HiddenWindow();
~HiddenWindow();
protected:
afx_msg LRESULT DoNOOP(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
This is my .cpp file
HiddenWindow::HiddenWindow()
{
CString wcn = ::AfxRegisterWndClass(NULL);//code fails here because of AfxGetInstanceHandle( )
BOOL created = this->CreateEx(0, wcn, _T("YourHiddenWindowClass"), 0, 0, 0, 0, NULL,HWND_MESSAGE,0);
}
HiddenWindow::~HiddenWindow()
{
}
BEGIN_MESSAGE_MAP(HiddenWindow, CWnd)
ON_MESSAGE(WM_USER + 1, DoNOOP)
END_MESSAGE_MAP()
LRESULT HiddenWindow::DoNOOP(WPARAM wParam, LPARAM lParam)
{
AfxMessageBox(_T("Test"));
return LRESULT(true);
}
I have done this in MFC by overriding the Create, the constructor is
way too early
Try :
BOOL HiddenWindow::Create()
{
if (!CWnd::CreateEx(0, AfxRegisterWndClass(0),
_T("HiddenWindow Notification Sink"),
WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL))
{
TRACE0("Warning: unable to create HiddenWindow window!\n");
return FALSE;
}
return TRUE;
}
you are not
"extending CWnd class"
you are using C++ not C#, hence you are deriving class.
You do not really have to do it if you need basic functionality. Just call create passing windows styles you need without WS_VISIBLE, as you did. You have to however provide window class as an argument since your window is not a child window.
If you need to handle messages or need to implement different that default behavior you have to derive own class but still you do not have to override Create member.
You should never do anything but initialize member variables in the constructor. You should never try to allocate memory or call other functions the may allocate memory. you should not do anything that may cause irrevocable error. There is no way to gracefully exit if contractor fails.

Proper way of destroying window resources

This is excerpt from my code based on win32 api:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void __fastcall TMyThread::Execute(void)
{
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WindowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = class_name.c_str();
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK);
return;
}
hwnd = CreateWindowEx(0, class_name.c_str(), NULL, 0, 0, 0, 100, 100, HWND_MESSAGE, NULL, wc.hInstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, L"Window Creation Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK);
return;
}
MSG msg;
BOOL ret;
while ((ret = GetMessage(&msg, 0, 0, 0)) != 0)
{
if (ret != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
My questions:
Is it required to do some resource cleanup after quitting message loop (like CloseHandle for example)? Quite often i am seeing code samples without any such things. Is it correct?
Can newly created window receive messages into thread queue before first call of GetMessage function (we suppose that window was successfully created i.e. function CreateWindowEx returned without errors)?
Please take in mind that TMyThread is not main thread of application. So it can be created and destroyed many times in one application run. Please don't pay attention to quite simplified window creation. This particular window is not meant to be visible on screen. It is created solely for purpose of receiving messages from another application. This is highlighted by using HWND_MESSAGE value of hWndParent parameter when calling CreateWindowEx function.
By creating, running and destroying thread in the above example again and again I have found out that two methods needs to be called after quitting from message loop. First is DestroyWindow and second is UnregisterClass. In regular application DestroyWindow function should be called in WM_CLOSE handler after the user confirms that he really wants to close the application. DestroyWindow function then sends WM_DESTROY and WM_NCDESTROY messages to window. In response to WM_DESTROY message application should call PostQuitMessage(0) function which results to immediately quitting message loop. So this part of code is not neccessary in all scenarios. I needed to call DestroyWindow function explicitly because I exit message loop by simply sending WM_QUIT message. When not doing it sometimes I received error 1412 (ERROR_CLASS_HAS_WINDOWS) when trying to unregister window class.
if (hwnd != NULL)
{
ret = DestroyWindow(hwnd);
if (ret == 0)
{
str.printf(L"Window destroying failed (GetLastError = %d)!", GetLastError());
ShowError(str);
}
hwnd = NULL;
}
ret = UnregisterClass(class_name.c_str(), wc.hInstance);
if (ret == 0)
{
str.printf(L"Window class unregistration failed (GetLastError = %d)!", GetLastError());
ShowError(str);
}
You must be very careful with resources in Win32. Make sure you've looked at the documentation carefully to determine what Windows itself will unload for you and what you have to unload yourself.
For examples, HWNDs will get destroyed as parent HWNDs get destroyed.
The best trick is to attempt to unload everything you've personally created. If you get an error returned from a particular function on unload, you likely should not unload it as it's been unloaded by Windows or some related resource.
It is important not to unload things when it is not necessary, as that could cause a crash.
So for example, an icon created with a window that's directly from a resource likely shouldn't be unloaded. But an HBITMAP you create that you draw to other windows, should most definitely be unloaded.
Your section question can be determined by a quick test with breakpoints. I do not know off the top of my head.

Subclassing notepad’s Edit class (WINAPI)

I have set a SetWindowsHookEx on the Edit class of notepad, but I am not sure how to continue from here.
I wish to subclass the Edit class to my own procedure, then manipulate the text or just save it to a file, then it must be send back the notepad control/class.
There are easier ways to get the text from notepad, but I am trying to learn WINAPI and Subclassing so this is a good way for me to learn it.
My SetWindowsHookEx looks like this:
SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, npThreadId);
How do I use the hook type : WH_GETMESSAGE to get the text from the Edit class in notepad and transfer it to my GetMsgProc(I think) function?
Is it the right hook type at all?
Do I send it a message? If yes, how do I do that?
My code look like this:
dllHeader.h:
#ifdef DLLAPI
#else
#define DLLAPI extern "C" __declspec(dllimport)
#endif
DLLAPI bool hookNotepad();
dll.cpp:
#include "stdafx.h"
#include <windows.h>
#define DLLAPI extern "C" __declspec(dllexport)
#include "dllHeader.h"
// Forward references
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
// Global variables
HHOOK g_hHook = NULL; // Hook for Notepad 'EDIT' class
HINSTANCE g_hInstDll = NULL; // DllMain entry (DLL_PROCESS_ATTACH)
HWND npHWND = NULL; // Notepad handle
DWORD npThreadId = NULL; // Notepad thread ID
HWND npeHWND = NULL; // Notepad 'EDIT' class handle
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hInstDll = hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
bool hookNotepad ()
{
npHWND = FindWindow(TEXT("Notepad"), NULL); // Finds Notepad
if (npHWND) //Notepad found
{
npeHWND = FindWindowEx(npHWND, NULL, L"Edit", NULL); // Finds the 'EDIT' class in notepad
npThreadId = GetWindowThreadProcessId(npeHWND, NULL); //Find ThreadID for Notepad 'EDIT' class
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, npThreadId); //Set hook in Notepad 'EDIT' class
if (g_hHook) //if the hook is a succes then...
{
MessageBox(NULL,TEXT("Hook set in Notepad EDIT class!"), NULL, MB_OK);
// Now what? How to subclass the npeHWND (The 'EDIT' class of Notepad) to my own procedure?
}
else
{
MessageBox(NULL,TEXT("SetWindowsHookEx error!"), NULL, MB_OK); //If the hook fails.
}
}
return 0;
}
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
MessageBox(NULL,TEXT("This never get called. Why?"), NULL, MB_OK);
}
return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
}
exe.cpp
#include <stdlib.h>
#include "stdafx.h"
#include <strsafe.h>
#include "C:\Users\Kristensen\Documents\Visual Studio 2012\Projects\dll\dll\dllHeader.h"
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
hookNotepad();
return 0;
}
I am a bit a lost on how to proceed from here… Any hints? Links? Tips?
I have read the documentation on MSDN regarding the SetWindowsHookEx function – but I did not find a clear answer there.
WH_GETMESSAGE is called when the hooked thread calls GetMessage() or PeekMessage() to retrieve a message from its message queue, but not all messages go through the message queue, so you may have to use the WH_CALLWNDPROC/RET hooks as well, depending on what kind of messages you are trying to intercept.
Your global variables need to be stored in a block of shared memory or else they will only be accessible to the process that installs the hook, since a new copy of the DLL gets loaded when hooking other processes.
You cannot subclass an HWND that is owned by another process. You would have to inject code into that process and then that code can subclass locally as needed. SetWindowsHookEx() can be used to inject code into other processes, but CreateRemoteThread() may be better to use for that, depending on your needs.

Win32 WH_CBT Hook - close window before it is created

I´m a currently running a global hook that watches for a certain window and then closes it with PostMessage(hWnd,WM_CLOSE,0,0);
The DLL containing the hook:
LRESULT CALLBACK MyFunc(int code, WPARAM wParam, LPARAM lParam)
{
switch(code)
{
case HCBT_CREATEWND:
{
HWND hWnd = (HWND)wParam;
//GetWindowText(hWnd, wintext, 80) returns nothing
//if ( strcmp(wintext, ("Kaspersky Internet Security: license notification")) == 0 )
// {
// Beep(70,100);
// PostMessage(hWnd,WM_CLOSE,0,0);
// }
break;
}
case HCBT_ACTIVATE:
{
HWND hWnd = (HWND)wParam;
GetWindowText(hWnd, wintext, 80);
if ( strcmp(wintext, ("Kaspersky Internet Security: license notification")) == 0 )
{
Beep(70,100);
PostMessage(hWnd,WM_CLOSE,0,0);
}
break;
}
}
...
As you can see i´m using GetWindowText(hWnd, wintext, 80) to determine by window title if the currently activated window is the one to be closed. i´m
closing the window when it is being activated and not when it is created. I would like to close the window when it is being created, that is when HCBT_CREATEWND is true.
The thing is that I can´t use GetWindowText(hWnd, wintext, 80) to get the window title and thereby determine if the window should be closed because when HCBT_CREATEWND is called the window hasn't been fully created and has no title, GetWindowText(hWnd, wintext, 80) returns nothing.
To summarize my question: is it possible to get the title of the window or in any other way determine what kind of window it is, when HCBT_CREATEWND is true?
Could you try GetClassName instead of reading the window text?
It's probably more reliable the reading the window text (internationalization). An easy way to discover a window's class name is to use the spy++ utility - a handy tutorial is described here.
The window isn't created yet. Which means you won't be able to call ::GetWindowText(). Instead use the lParam as an LPCBT_CREATEWND. This gives you access to the CREATESTRUCT via a pointer. You can use the lpszName to get access to the window name.
Something like this --
CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
switch(nCode)
{
case HCBT_CREATEWND:
{
LPCBT_CREATEWND lpCreate = (LPCBT_CREATEWND)lParam;
lpCreate->lpcs->lpszName; // this is the name
break;
}
}
}

Resources