I have to use a simple function from a DLL; I am able to load the library but GetProcAddress returns NULL. I think I understood name mangling but maybe I'm doing something wrong. Thanks (Code follows, asap I'll add other information required):
mydll.h
#ifdef MYDLL_EXPORTS
#define MYDLL_API extern "C" __declspec(dllexport)
#else
#define MYDLL_API extern "C" __declspec(dllimport)
#endif
MYDLL_API void testFunction(void);
MYDLL_API LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam);
mydll.cpp
#include "stdafx.h"
#include "mydll.h"
// This is an example of an exported function.
MYDLL_API void testFunction(void)
{
MessageBox(NULL, (LPCWSTR)L"Test", (LPCWSTR)L"Test", MB_OK);
}
MYDLL_API LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// processes the message
if(nCode >= 0)
{
if(wParam != NULL && wParam == MK_RBUTTON)
{
MessageBox(NULL, (LPCWSTR)L"Captured mouse right button", (LPCWSTR)L"Test", MB_OK);
}
}
// calls next hook in chain
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
code from main.cpp
...
case WM_CREATE:
{
// creates state for window
stateClassPointer = new stateClass();
// saves states pointer in a space reserved for user data
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) stateClassPointer);
// now it will load DLL and set up hook procedure for mouse events
// declares local variables
HOOKPROC hkprcMouseProc;
HINSTANCE hinstDLL;
HHOOK hhookMouseProc;
//FARPROC WINAPI test;
// loads DLL
if((hinstDLL = LoadLibrary(TEXT("C:\\Users\\Francesco\\Dropbox\\poli\\bi\\not\\pds\\sp\\wk5\\lsp5\\Debug\\mydll.dll"))) == NULL)
{
MessageBox(hWnd, (LPCWSTR)L"Error loading DLL", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR);
break;
}
// saves DLL handle in the state class
stateClassPointer->setHInstance(hinstDLL);
// sets up hook procedure for mouse events
if((hkprcMouseProc = (HOOKPROC)GetProcAddress(hinstDLL, "mouseProc")) == NULL)
{
MessageBox(hWnd, (LPCWSTR)L"Error setting windows hook: GetProcAddress", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR);
break;
}
if((hhookMouseProc = SetWindowsHookEx(WH_MOUSE, hkprcMouseProc, hinstDLL, 0)) == NULL)
{
MessageBox(hWnd, (LPCWSTR)L"Error setting windows hook: SetWindowsHookEx", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR);
break;
}
// saves hook handle in the state class
stateClassPointer->setHHook(hhookMouseProc);
/*test = GetProcAddress(hinstDLL, "testFunction");
test();*/
}
break;
...
Yes, the MessageBox() call succeeded without errors. Move the GetLastError() call before it.
The error is otherwise predictable, it couldn't find "mouseProc". The name will be mangled in the DLL, most probably "_mouseProc#12". Use dumpbin.exe /exports on your DLL to be sure.
Fwiw: you can make this code less painful by not dynamically loading the DLL but just linking its import library. The fact that the DLL will be injected into other processes doesn't also mean you have to inject it in yours. All you need is the module handle so you can call SetWindowsHookEx(). Get that from the DllMain() entry point or by using GetModuleHandle().
Related
I've got this code to load a bitmap:
HBITMAP reg_hbmCS = NULL;
LRESULT CALLBACK WndProc(HWND hRegWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
reg_hbmCS = LoadBitmap(NULL, MAKEINTRESOURCE(IDB_CSBITMAP));
if(!reg_hbmCS)
MessageBox(hRegWnd,
"No se ha podido cargar el icono del programa.\r\n"
"Pruebe a reinstalar el programa para solucionar este problema.",
"Atención", MB_ICONEXCLAMATION | MB_OK);
break;
case WM_CLOSE:
DeleteObject(reg_hbmCS);
DestroyWindow(hRegWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hRegWnd, message, wParam, lParam);
}
return 0;
}
The problem is that the reg_hbmCS won't load, so I don't have the bitmap available (it prompts with the message box in (if !reg_hbmCS).
Here my resources.h:
#ifndef RESOURCES_H
#define RESOURCES_H
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
#define IDI_CSICO 101
#define IDB_CSBITMAP 201
#endif // RESOURCES_H
And my resources.rc:
#include <windows.h>
#include "resources.h"
IDI_CSICO ICON "CS-Nursing.ico"
IDB_CSBITMAP BITMAP DISCARDABLE "CS-Nursing.bmp"
In case it was necessary, I use Code::Blocks 12.11 on WindowsXP SP3.
Any help will be much appreciated.
LoadBitmap is probably failing because you haven't told it where to find the bitmap resource. The first parameter to LoadBitmap is a handle to the instance of the module containing the bitmap resource (unless you are loading a system bitmap in which case it is NULL). Since the bitmap resource is being compiled into your application, you need to pass a handle to the instance of your application module as the first parameter when you call LoadBitmap. You can get this handle from the first parameter in your WinMain function. Many people store this parameter in a global variable so that it can be accessed easily from other functions. If the call to LoadBitmap still fails then you should call GetLastError to get a code describing why the call failed. See Windows System Error Codes.
Changed the resources.rc file:
//IDB_CSBITMAP BITMAP DISCARDABLE "CS-Nursing.bmp"
IDB_CSBITMAP BITMAP "CS-Nursing.bmp"
Now it works perfectly, will mark this as solved, thank you all for your help.
I have a code to display a part of screen when mouse moves. But the WH_MOUSE doesn't work. I need to change GetModuleHandle(0), 0 to hInst, GetCurrentThreadId().
But then the application will work only when the mouse is over the application itself.
I want it global and I tried WH_MOUSE_LL, it is slower then WH_MOUSE.
Is that possible to use WH_MOUSE globally without DLL?
void SetHook()
{
gMouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, GetModuleHandle(0), 0);
}
//================================================================================
// Mouse Hook
static LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0) {
return CallNextHookEx(gMouseHook, nCode, wParam, lParam);
}
if (wParam == WM_MOUSEMOVE) {
MOUSEHOOKSTRUCT *mouseInfo = (MOUSEHOOKSTRUCT*)lParam;
int x = mouseInfo->pt.x;
int y = mouseInfo->pt.y;
PrintScreen(x, y);
}
return CallNextHookEx(gMouseHook, nCode, wParam, lParam);
}
Is that possible to use WH_MOUSE globally without DLL?
No, the hook procedure needs to be in a DLL so that it can be injected into other processes.
I tried WH_MOUSE_LL, it is slower then WH_MOUSE.
That probably means your hook procedure is slow.
I am trying to set a global GetMessage hook on all threads. This is my DLL:
#include <windows.h>
__declspec(dllexport) LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MessageBeep(0);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
As you can see, it's not much. I just want it to call MessageBeep whenever it's called.
#include <windows.h>
typedef LRESULT (CALLBACK *LPGetMsgProc)(int nCode, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow)
{
if(!(HMODULE hDll = LoadLibrary("library.dll")))
return 1;
if(!(LPGetMsgProc pfnProc = (LPGetMsgProc)GetProcAddress(hDll, "GetMsgProc#12")))
return 2;
HHOOK hMsgHook = SetWindowsHookEx(WH_GETMESSAGE, pfnProc, hInstance, 0);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0) {}
UnhookWindowsHookEx(hMsgHook);
return 0;
}
My WinMain loads the library, gets the procedure and sets the hook. However, MessageBeep is never being called. Is there something I'm doing wrong here?
Also, one other thing has been bothering me. In this call:
if(!(LPGetMsgProc pfnProc = (LPGetMsgProc)GetProcAddress(hDll, "GetMsgProc#12")))
I was forced to use "GetMsgProc#12" because I couldn't get it right any other way. Can somebody please tell me how I'm supposed to use a .def file or something else so I can just have it as "GetMsgProc"? Though MSDN stated that since I have __declspec(dllexport) in my declaration I wouldn't need it...
My IDE is Code::Blocks with MinGW. Thanks in advance.
The third parameter...
HHOOK hMsgHook = SetWindowsHookEx(WH_GETMESSAGE, pfnProc, hInstance, 0);
...is the handle passed into your WinMain function. But it needs to refer to the DLL where the callback function resides - in your case, that'd be hDLL.
I want to build a software test automation software and I'm playing around with Windows Hooks for that.
So I built the following C code. Can anyone tell me how to correct it ?
#include "windows.h"
// the call back function
LRESULT CALLBACK JournalRecordProc(int code, WPARAM wParam, LPARAM lParam)
{
HHOOK hhk = 0;
if (code > 0)
{
// save Data in File
}
if (code < 0)
{
// work done: now pass on to the next one that does hooking
CallNextHookEx(hhk, code, wParam, lParam);
}
/*
if (code == )
{
// ESC button pressed -> finished recording
UnhookWindowsHookEx(hhk);
}
*/
}
int main()
{
int iRet = 0;
HHOOK hHook = 0;
HINSTANCE hMod = 0;
HOOKPROC (*hHookProc)(int, WPARAM, LPARAM);
hHookProc = &JournalRecordProc;
// type of hook, callback function handle, hinstance [dll ?], 0 for systemwide
hHook = SetWindowsHookEx(WH_JOURNALRECORD, hHookProc, hMod, 0);
return iRet;
}
When I compile this I get the compiler errors:
error C2440: '=': 'LRESULT (__stdcall
*)(int,WPARAM,LPARAM)' kann nicht in 'HOOKPROC (__cdecl
*)(int,WPARAM,LPARAM)' konvertiert werden (could not be converted)
error C2440: 'Funktion': 'HOOKPROC (__cdecl *)(int,WPARAM,LPARAM)' kann nicht in 'HOOKPROC' konvertiert werden (could not be converted)
warning C4024: 'SetWindowsHookExA': Unterschiedliche Typen für formalen und übergebenen Parameter 2
There's no need to declare a separate hHookProc variable - just pass your procedure to SetWindowsHookEx directly:
hHook = SetWindowsHookEx(WH_JOURNALRECORD, JournalRecordProc, hMod, 0);
You're also going to need a valid module handle:
HINSTANCE hMod = GetModuleHandle(NULL);
Having made those edits, and made your JournalRecordProc return a value, it all now compiles and works for me (in that SetWindowsHookEx succeeds, anyway).
I'm trying a little concept test to change one of the features of the logitech MS3200 keyboard (the zoom feature). I've got the keys that are sent from the zoom control. So, I have a main app, and a dll that contains a hook procedure.
Here's the main app:
#include <stdio.h>
#include <windows.h>
HANDLE hHook;
int main()
{
HINSTANCE hMod = GetModuleHandle(NULL);
hHook = SetWindowsHookEx(WH_KEYBOARD, HookProc,0,0);
if(hHook == NULL)
printf("Unable to set hook! Error: %d", GetLastError());
else
printf("Hook set successfully!");
while(TRUE)
{
Sleep(1000);
}
return 0;
}
And here is the hook procedure dll:
#include <windows.h>
int __declspec (dllexport) HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
if(wParam == VK_ADD || wParam == VK_SUBTRACT)
{
short status = GetKeyState(VK_CONTROL);
if(status == 1)
{
if(wParam == VK_ADD)
wParam = VK_UP;
else
wParam = VK_DOWN;
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
int WINAPI dllmain(HINSTANCE hMod, DWORD data, LPVOID lpVOid)
{
return 0;
}
I need to be able to access what's returned by SetWindowsHookEx (hHook) from the dll, in order to call CallNextHookEx().
It's probably possible, but it's not worth your time to investigate.
Instead, move the hook setting code to the DLL.
Oh, and I think you need to pass the DLL module handle to the hook setting function, not a NULL
One possible way to handle this would be to have another exported function in your DLL to pass the hHook to, and save that in a variable local within the DLL for use in the HookProc.
HANDLE dllHook;
void __declspec (dllexport) HookHandle(HANDLE hHook)
{
dllHook = hHook;
}
int __declspec (dllexport) HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0 && dllHook!= NULL)
{
return CallNextHookEx(dllHook, nCode, wParam, lParam);
}
//....
}
int WINAPI dllmain(HINSTANCE hMod, DWORD data, LPVOID lpVOid)
{
dllHook = NULL; //initialize
return 0;
}
Code in a DLL can't directly access variables in the calling app, because there's no guarantee that the app that loads the DLL will have those variables defined, and even if it did, the DLL has no way to know where it would be stored.
You could have a global variable in the DLL and an extra entry point to set it, which you call after calling SetWindowsHookEx. The DLL would need to wait until this entry point is called before calling CallNextHookEx.
On NT/XP/2003 etc the first param to CallNextHookEx is ignored. See the documentation for CallNextHookEx:
http://msdn.microsoft.com/en-us/library/ms644974%28VS.85%29.aspx
hth