How to call fuction-pointer from SetWindowsHookEx callback - c++

I tried to call a function-pointer from a dll that hooks the WM_LBUTONDOWN or WM_TOUCH message on all windows displayed at screen.
I have the following dll source code:
typedef void (*PtrFonct)(int nCode, WPARAM wParam, LPARAM lParam);
PtrFonct pf;
HHOOK global;
extern "C" __declspec(dllexport) LRESULT WINAPI procedure(int nCode, WPARAM wParam,LPARAM lParam)
{
if (nCode == HC_ACTION){
MSG* pMSG = (MSG*)lParam;
if (pMSG->message == WM_LBUTTONDOWN){
pf(nCode, wParam, lParam);
}
}
return CallNextHookEx(global, nCode, wParam, lParam);
}
extern "C" __declspec(dllexport) BOOL setCallback(void ((*callbackFunc)(int, WPARAM, LPARAM))){
pf = callbackFunc;
if (pf)
return TRUE;
return FALSE;
}
and my listener source code is the following one:
MSG message;
HMODULE lib = LoadLibrary(L"C:/HookTouch.dll");
if (lib) {
HOOKPROC procedure = (HOOKPROC)GetProcAddress(lib, "_procedure#12");
dllFunct fonctionCallback = (dllFunct)GetProcAddress(lib, "setCallback");
if (fonctionCallback)
fonctionCallback(MyCallback);
if (procedure)
hook = SetWindowsHookEx(WH_GETMESSAGE, procedure, lib, 0);
}
else
printf("Can't find dll!\n");
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
FreeLibrary(lib);
UnhookWindowsHookEx(hook);
My own callback to display "Hello click" is this one:
void MyCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
printf("Hello Click\n");
}
I know my hook is working because I can display a message on click by using a message box instead of pf(nCode, wParam, lParam) but when I use this function-pointer, MyCallback is not triggered.
I checked if my function was well affected to the pf function-pointer and all seems to be ok.
Do you know why the call of pf(nCode, wParam, lParam) don't trigger the MyCallback function of the listener?

You are calling setCallback only for the dll that's loaded in your process. The dll's that will be injected by SetWindowsHookEx in all the other process will not have the callback set. On top of that, MyCallback is only defined in your own process; the Dll's injected in other processes have no trivial way of accessing it.
Since you cannot know which processes Windows has injected for you, you will need the Dll to broadcast its 'location' to you, via Inter-Process communcation, eg. Named Pipes. Once you have the process ID of each of the DLL's that were injected, you can use CreateRemoteThread to call a function inside the Dll, like setCallback.. there's still some work to be done so that the Dll can directly call you callback: You will need to give the Dll the exact offset of your callback from the module base, and the Dll will then need to use CreateRemoteThread itself to issue the call.
This all quickly becomes too tedious, and you would be wise to just use Named Pipe communication instead of issuing direct function calls.
Tip: An easy way to log things from other processes is using OutputDebugString. Alternatively, write to a file.

This approach will not work.
A message hook runs in the context of each thread that is being hooked. Each hooked process will get its own copy of your DLL injected into it. As such, only the copy that originally installed the hook will have a valid function pointer set. Besides, you can't call your callback function across process boundaries anyway.
You need to use a different IPC mechanism to let your injected hooks communicate back to your main app process.
For instance, you could create a hidden HWND and store it in a block of global shared memory and then each injected hook can send window messages to it, like WM_COPYDATA. Or, your main app can open a named pipe that each injected hook can then connect to and send data to.

Related

Do CustomDialogProc have to be static. WinAPI

I've been looking at creating a custom control with WinApi for my application, and I have made a class which contains the CustomDialogProc and CreateWindowEx and RegisterClass() functions.
I can set a breakpoint inside the CustomDialogProc and it hits, so the class is registered correctly.
However, I have to declare the CustomDialogProc function as static int he header of my class
static LRESULT CALLBACK CustomDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam);
If I don't set it to static, I get the error
Error C3867 'CustomControl::CustomDialogProc': non-standard syntax; use '&' to create a pointer to member
IS this necessary, this requires all my controls created within this control to be static as well. What if I want multiple instances of this control?
How can I get around this? The main MsgProc doesn't seem to be a static function. Neither is the UpDownDialogProc in the first link shown below
Below is my code for CustomControl.h in case anyone needs it.
Put together from code found at:
https://msdn.microsoft.com/en-us/library/windows/desktop/hh298353(v=vs.85).aspx
https://www.codeproject.com/Articles/485767/True-Windows-control-subclassing
Thanks,
#pragma once
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
class CustomControl
{
public:
CustomControl();
~CustomControl();
LRESULT CALLBACK CustomDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
//DO STUFF HERE
break;
}
}
bool CreateControl(HWND hwnd, HINSTANCE* m_hApp_instance)
{
g_hInst = m_hApp_instance;
RegisterSubClass(*g_hInst, WC_LISTBOX, TEXT("CustomControl"), CustomDialogProc);
HWND hwndCustom = CreateWindow(TEXT("CustomControl"), NULL, WS_CHILD | WS_VISIBLE,
0, 0, 0, 0, hwnd, (HMENU)100, *g_hInst, NULL);
return true;
}
private:
HINSTANCE* g_hInst;
WNDPROC RegisterSubClass(HINSTANCE hInstance, LPCTSTR ParentClass, LPCTSTR ChildClassName, WNDPROC ChildProc) {
WNDCLASSEX twoWayStruct;
WNDPROC parentWndProc;
if (GetClassInfoEx(NULL, ParentClass, &twoWayStruct)) {
parentWndProc = twoWayStruct.lpfnWndProc; // save the original message handler
twoWayStruct.cbSize = sizeof(WNDCLASSEX); // does not always get filled properly
twoWayStruct.hInstance = hInstance;
twoWayStruct.lpszClassName = ChildClassName;
twoWayStruct.lpfnWndProc = ChildProc;
/* Register the window class, and if it fails return 0 */
if (RegisterClassEx(&twoWayStruct))
return parentWndProc; // returns the parent class WndProc pointer;
// subclass MUST call it instead of DefWindowProc();
// if you do not save it, this function is wasted
}
return 0;
}
};
The most common way is to use SetWindowLongPtr to store a pointer to the object associated with the window handle.
HWND hWnd = CreateWindow(...);
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) this);
And then in your dialog proc, get that pointer and call into your class:
// this static method is registered with your window class
static LRESULT CALLBACK CustomDialogProcStatic(HWND hWnd, UINT uMsg, WPARAM wParam,LPARAM lParam)
{
auto pThis = (CustomControl*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (pThis != NULL)
return pThis->CustomDialogProcInstance(hWnd, uMsg, wParam, lParam);
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
// this instance method is called by the static method
LRESULT CustomDialogProcInstance(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
...
}
Make sure you manage your window and class life cycle appropriately to prevent the window proc from calling a deleted object instance. In many cases, this is as simple as ensuring DestroyWindow is called if your class is destructed.
The Windows API is C language based. It knows nothing about C++, non-static member functions, objects, etc.
So yes, all of your functions that will communicate with the Windows API directly must be static class member functions, or non-class / global / "free" functions.
That doesn't preclude you from writing a C++ wrapper for a C API. That's what libraries such as Microsoft's MFC or the old Borland OWL libraries accomplish. Other independent groups have also written wrappers for the Windows API.
Note that these differing libraries accomplish the goal of hooking a C based API to C++ in different ways. One is to use the SetWindowLongPtr method mentioned in the answer given by #MichaelGunter. Another method is to use maps to associate window handles and static Window procedures.
I would suggest before you try this on your own (creating a wrapper), you investigate how others have done this already, and choose the best approach that fits. Another suggestion is that before you even create a wrapper, you should know the C based API on much more than a cursory level. You need advanced to expert knowledge of any C API you plan to create a C++ wrapper for if you want the wrapper to work relatively flawless under different scenarios.

FromHandlePermanent always returns null in injected DLL

I am writing a test automation program, that must interact with a grid control in a legacy MFC application. My program must connect to the legacy app, and read the data from the grid.
I know the HWND of the window that contains the grid, and so now I need to find the CWnd-derived class pointer associated with that HWND. CWnd::FromHandlePermanent seems to be my friend, but yes, I know, you cannot call CWnd::FromHandlePermanent from outside the application, as the AFX window map (afxMapHWND()) is only contained in the target application.
Therefore, I inject a DLL (using CreateRemoteThread/LoadLibrary) into the target app, and get it to call FromHandlePermanent. But even this is not good enough, because I am not in the thread of the HWND, and afxMapHWND() is looking at the wrong local thread storage.
Therefore, in my injected DLL, I also (temporarily) subclass the WndProc of the HWND (SetWindowLong etc), then call SendMessage. Now I am in the correct thread (the main thread of the target application) and I try to call CWnd::FromHandlePermanent with my HWND, but it returns NULL!!
If I look at afxMapHWND()->m_permanentMap->m_nCount, we see it is 0. So there are NO attached classes in the permanentMap, which seems wrong to me.
So how can I get the derived CWnd pointer??
Some other info:
The Target application is statically linked to MFC
It's a different version of MFC, the windowclass is AfxWnd70s
I am using VS2010 to compile the injected DLL
The injected DLL also links statically to the (VS2010) MFC libraries.
Here is the code in the injected DLL:
// this is how we pass the HWND to the target DLL
// (this shared segment is also loaded in calling app)
#pragma data_seg (".shared")
__declspec(dllexport) HWND g_hWnd = 0;
#pragma data_seg ()
#pragma comment(linker,"/SECTION:.shared,RWS")
BEGIN_MESSAGE_MAP(CLibSpyMFCDllApp, CWinApp)
END_MESSAGE_MAP()
CLibSpyMFCDllApp::CLibSpyMFCDllApp()
{
}
CLibSpyMFCDllApp theApp;
extern CHandleMap* PASCAL afxMapHWND(BOOL bCreate = FALSE);
UINT g_WM_GETGRIDDATA = 0;
WNDPROC wpOrigEditProc;
LRESULT CALLBACK SpySubProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (g_WM_GETGRIDDATA != 0 && message == g_WM_GETGRIDDATA) {
CWnd * target1 = CWnd::FromHandlePermanent(hWnd);
// fails - target1 is null
return 0;
}
return CallWindowProc((WNDPROC ) wpOrigEditProc, hWnd, message, wParam, lParam);
}
BOOL CLibSpyMFCDllApp::InitInstance()
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CWinApp::InitInstance();
if (g_hWnd) {
g_WM_GETGRIDDATA = RegisterWindowMessage(L"GetGridData");
wpOrigEditProc = (WNDPROC) SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG) SpySubProc);
::SendMessage(g_hWnd, g_WM_GETGRIDDATA, 0, 0);
SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG) wpOrigEditProc);
}
return TRUE;
}

Subclassing an edit control from a user defined class/pointer-to-member-function

I think I've fallen in the same trap as many before me where I try to impose a nice OO methodology on win32 API programming. No MFC, no AFX, I'm not even using VC++, I'm using C::B with gcc.
I think what I'm trying to do is impossible, but since MFC exists (although I'm not using it) there must be some way.
I've created a class to contain several window controls. It implements handlers for WM_CREATE and WM_COMMAND, and keeps track of all the associated data around my small group of controls (ID codes and HWNDs).
It works great for buttons, static controls, even light GDI methods, but it all breaks down when I try to subclass an edit control.
Really, I just want to capture the "enter" key, but as anybody who's been down that road before will attest, when an edit control has focus, the parent window doesn't receive WM_KEYDOWN or WM_COMMAND, we are left to implement our own proc. Super lame.
OK, so subclassing an edit control is fine, if the editProc is global or static. I know that is because SetWindowLongPtr needs a function address, and that concept is nebulous for a member function.
So the object of my class is declared as "static" inside the parent WndProc. But the function is not "static" because then I wouldn't have access to non-static data members (completely defeating the purpose of this exercise). I'm hoping that because the objest is itself static, I should be able to properly define the address of one of its member functions.
Readers that have tried this before will either have given up and used MFC or something else, or perhaps have found a clever work-around.
I'll let this sample code do the rest of the talking: (simplified - will not compile as such)
/**** myprogram.c ****/
#include "MyControlGroup.h"
int winMain(){ // etc... }
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// object is static becuse it only needs to be initialized once
static MyControlGroup myControl;
if (msg == WM_CREATE)
myControl.onWMCreate(hWnd);
else if (msg == WM_COMMAND)
myControl.onWMCommand( wParam, lParam );
else if (msg == WM_DESTROY)
PostQuitMessage(0);
return DefWindowProcW(l_hWnd, l_msg, l_wParam, l_lParam);
}
The header file for my class:
/**** MyControlGroup.h ****/
class MyControlGroup
{
private:
HWND m_hWndParent;
HWND m_hWndEditBox;
int m_editBoxID;
public:
MyControlGroup();
void onWMCreate(HWND);
void onWMCommand(WPARAM, LPARAM);
// want to find a way to pass the address of this function to SetWindowLongPtr
LRESULT myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
...and the implementation:
/**** MyControlGroup.cpp ****/
static int staticID = 1;
MyControlGroup::MyControlGroup()
{
m_editBoxID = staticID++;
}
void MyControlGroup::onWMCreate(HWND hWnd)
{
// My control group has buttons, static controls, and other stuff which are created here with CreateWindowW. It also has an edit control:
m_hWndEditBox = CreateWindowW(L"EDIT", L"initial text", WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 150, 20, hWnd, (HMENU)m_editBoxID, NULL, NULL);
/*
To subclass the edit control, I need a pointer to my customized proc. That means I
need a pointer-to-member-function, but SetWindowLongPtr needs a pointer to global or
static function (__stdcall or CALLBACK, but not __thiscall).
*/
// I'd like to do something like this, adapted from a great write-up at
// http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible
LERSULT (MyControlGroup::*myEditProcPtr)(HWND, UINT, WPARAM, LPARAM);
myEditProcPtr = &MyControlGroup::myEditProc;
// Up to now it compiles ok, but then when I try to pass it to SetWindowLongPtr, I get
// an "invalid cast" error. Any ideas?
SetWindowLongPtr(m_hWndEditBox, GWLP_WNDPROC, (LPARAM)myEditProcPtr);
}
void MyControlGroup::onWMCommand(WPARAM wParam, LPARAM lParam){ /* process parent window messages. Editboxes don't generate WM_COMMAND or WM_KEYDOWN in the parent :''( */}
LRESULT MyControlGroup::myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// process messages like IDOK, WM_KEYDOWN and so on in the edit control
}
Even once I get this done, I'll still need to figure out a way to pass the address of the parent WndProc to myEditProc for the return value, but until I get past this there is no point in worrying about that.
Thanks in advance for reading!
myEditProc needs to be a static function.
Once you've done that you can pass the address of the function directly without going through the intermediate variable:
static LRESULT myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
...
SetWindowLongPtr(m_hWndEditBox, GWLP_WNDPROC, (LPARAM)myEditProc);
To access your class data from the static function, you can save it in the userdata field of the edit control, e.g.:
// before sub-classing the control
SetWindowLongPtr(m_hWndEditBox, GWLP_USERDATA, (LPARAM)this);
// in the sub-class procedure
MyControlGroup* pThis = (MyControlGroup*)GetWindowLongPtr(m_hWndEditBox, GWLP_USERDATA);
But as #K-ballo suggested, SetWindowSubclass is definitely the way to do this unless you want compatibility with pre-XP. It handles the sub-classing procedure for you automatically, lets you associate a userdata pointer (e.g. this) that is automatically passed to the sub-class procedure, and safely handles removing the sub-class at the end.

Pointer to a callback in a DLL

I'm calling a Dialog that has it's resources and dlg-procedure in a DLL.
I'm not using a DEF file or LIB file. The function names are known, the function args are known, I'm using GetProcAddress to get a pointer to the functions I'm interested in.
'Why' I'm doing it this way is of no consequence, it's an experiment in 'learning'.
This works on _cdecl functions, but on the CALLBACK (_stdcall), I can't get a pointer to the actual dialog procedure (it returns 0).
Here's how I'm doing my pointers:
//////////////////// DLL TEST STUFF ////////////////////////////
#define DLLPATH "../../testdll/release/testdll.dll"
//typedef some function pointers
typedef HINSTANCE (__cdecl *INSTPROC )(void);
typedef int (__cdecl *VOIDPROC )(void);
typedef LRESULT (__stdcall *DLGROC )(HWND, UINT, WPARAM, LPARAM );
///////////////////////////////////////////////////////////////
As I said, any function that is NOT a callback returns a valid result, additionally, the dialog pops up as expected, no problems with DLL's HINSTANCE.
But without a pointer to it's dlgproc, no button messages have anywhere to go.
Here's some more test code:
//use DLL funcs without lib or def files
//this works
GetInst = (INSTPROC)GetProcAddress(Loadme,"getinst");
//this works
GetID = (VOIDPROC)GetProcAddress(Loadme,"getid");
//this doesn't work, rets 0
DlgProc = (DLGPROC) GetProcAddress(Loadme,"dllProc");
//test for result
dllid =(GetID)();
dllinst=(GetInst)();
//compare hinst OK
wsprintf(buf,"dllinst=%x Loadme=%x",dllinst, Loadme);
MessageBox(hwnd,buf,"",MB_OK);
//check resOurce ID OK
wsprintf(buf,"GetID returned: %d",dllid);
MessageBox(hwnd,buf,"",MB_OK);
//check dllProc addr NOGO, ret=0
wsprintf(buf,"dllProc=%x",DlgProc);
MessageBox(hwnd,buf,"",MB_OK);
// DLL instance, resource ID, parent, dlgproc
DialogBox(Loadme , MAKEINTRESOURCE(dllid), hwnd, DlgProc);
//dialog loads and shows, can't get dlgproc addr
FreeLibrary(Loadme);
///////////////// END DLL TEST STUFF ///////////////
On the DLL side of things, it looks like this:
__declspec(dllexport) LRESULT CALLBACK dllProc(
HWND hwnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
hpwnd=hwnd;
switch (Message){
case WM_INITDIALOG:
MessageBox(hwnd,"At DlgProc...","",MB_OK);
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam)){
case IDEND:
case IDCANEND:
EndDialog(hwnd,0);
return TRUE;
}
return TRUE;
}
return FALSE;
}
Which really doesn't matter at this point, since I can't get a pointer to the callback in the first place.
If anyone happens to know the fix for getting a pointer to the callback, I would very much appreciate your input.
Thanks for your patience.
You need to declare your dllProc inside an extern "C" block to prevent its name being decorated when exported, so that when you ask for a function called "dllProc" such a function is found (instead of "dllProc#blahmoocow" or whatever madness the C++ decoration produces. :-)).
Place this declaration before the dllProc definition:
extern "C"
{
__declspec(dllexport) LRESULT CALLBACK dllProc(
HWND hwnd, UINT Message, WPARAM wParam, PARAM lParam);
}
You can also then drop the __declspec(dllexport) from the dllProc definition.

Implement user activity logger in old application?

How to go about implementing a user activity logger in MFC application.To get to know what are all the features are used most in an existing application.
You can override the windows procedure of your application window:
class CMyMainWindow {
void LogUsageData(UINT message);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
LogData(message);
return CWnd::WindowProc(message, wParam, lParam); // route message to message map
}
}
Note that the task is not so trivial: LogUsageData should discard most messages, focusing only on the ones defined in the message map.
However, this should be a good place to start.