Originally Posted by
bithub
I don't think the SetWindowHookEx call needs to be in the DLL. Just the hook procedure needs to be in the DLL.
Yeah, it does... the call to SetWindowsHookEx() and the DLLHookProc() have to be in the same scope otherwise the function pointer is invalid.
Here's an example that returns the window handle in a message to the main window proc in an EXE and exports a call that lets you retrieve the program's name....
The DLL...
Code:
/// self
#include "Helper.h"
/////////////////////////////////////////////////////////////////
// Shared data segment
#pragma data_seg("Hook")
HINSTANCE hdll = NULL; // dll handle
HWND HWind = NULL; // handle of Server window
HHOOK Hook = NULL; // message hook handle
LAUNCHINFO LInfo = {0}; // info about program launch
#pragma data_seg()
#pragma comment(linker,"/SECTION:Hook,S")
/////////////////////////////////////////////////////////////////////////////////////////
// Export
//
// return launch info to server
MMAPI VOID HelperGetInfo(pLAUNCHINFO Info)
{ memcpy(Info,&LInfo,sizeof(LInfo)); }
/////////////////////////////////////////////////////////////////////////////////////////
// gather information
//
// get information about launched program
VOID HookGetInfo(HWND wParm)
{ TCHAR cmdl[MAX_PATH] = {0}; // command line
TCHAR pgm[MAX_PATH] = {0}; // program name
PTCHAR args; // arguments
// purge old data
memset(&LInfo,0,sizeof(LAUNCHINFO));
// set program window handle
LInfo.Handle = wParm;
// get program info
GetModuleFileName(NULL,pgm,MAX_PATH);
_wsplitpath(pgm,NULL,NULL,LInfo.Name,LInfo.Ext);
// get launched file info
wcsncpy(cmdl,GetCommandLine(),MAX_PATH);
args = PathGetArgs(cmdl);
if(wcslen(args) < 1)
return;
args = wcsrchr(args,L'.');
if (args)
{ wcscpy(LInfo.Type,args);
// fix trailing quote
args = wcsrchr(LInfo.Type,L'\"');
if (args)
*args = 0; } }
/////////////////////////////////////////////////////////////////////////////////////////
// Handle Shell Hook
//
// hook tosser
MMAPI LRESULT CALLBACK AppCatcher(INT Code, WPARAM wParm, LPARAM lParm)
{ switch (Code)
{ case HSHELL_WINDOWCREATED : // new window
// gather launch info
HookGetInfo((HWND) wParm);
// send message to Server, wparam = Handle
PostMessage(HWind,UM_HELPERRUN,wParm,0);
break;
case HSHELL_WINDOWDESTROYED : // window closing
// send messate to Server
PostMessage(HWind,UM_HELPEREXIT,wParm,0);
break; }
return CallNextHookEx(RMHook,Code,wParm,lParm); }
/////////////////////////////////////////////////////////////////
// Set the shell hook
// Returns hook status 1 = active, 0 = not
//
// apply the hook to launched programs
MMAPI BOOL WINAPI SetHook(HWND hWind)
{ HWind = hWind; // handle of window to receive message
Hook = SetWindowsHookEx(WH_SHELL,&AppCatcher,hdll,0);
return (Hook != NULL); }
// remove the hook from launched programs
MMAPI BOOL WINAPI FreeHook(void)
{ return UnhookWindowsHookEx(Hook); }
/////////////////////////////////////////////////////////////////
// DLL entry point
//
BOOL APIENTRY DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
{ if (reason == DLL_PROCESS_ATTACH) // save instance handle
hdll = hinst;
return 1; }
And the header file....
Code:
#ifndef HELPER_H
#define HELPER_H
// for the compiler
#define UNICODE
#define _UNICODE
#define WIN32_DEFAULT_LIBS
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0502
#define _X86_
// project global headers
#include <windows.h>
#include <shlwapi.h>
#include <wchar.h>
#include <globaldefs.h>
#pragma lib "Helper.lib"
#define MMAPI __declspec(dllexport)
// messages sent by helper dll
#define UM_HELPERRUN WM_APP + 444
#define UM_HELPEREXIT WM_APP + 445
// launch information
#pragma pack(1)
typedef struct tLAUNCHINFO
{ TCHAR Name[MAX_PROGRAMNAME]; // short program name
TCHAR Ext[MAX_TYPENAME]; // program type
TCHAR Type[MAX_TYPENAME]; // file type
HWND Handle; } // program window handle
LAUNCHINFO, *pLAUNCHINFO;
#pragma pack()
// retrieve the command line
MMAPI VOID HelperGetInfo(pLAUNCHINFO Info);
// set the hook
MMAPI BOOL WINAPI SetHook(HWND hWind);
// release the hook
MMAPI BOOL WINAPI FreeHook(void);
#endif // HELPER_H
This is extracted from working code, some things were changed to not advertise which application ... so any errors are not my fault.