May 02, 2024, 03:19:37 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Stuck On a Hook

Started by Zen, July 17, 2006, 03:59:54 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Zen

Ok, i am trying to get a hook to work, so far so good, untill i try to call CallNextHookEx, then it just crashes programs all over my system. I have no idea why, but its really driving me crazy now, so i seek the help of the community.

Here is the code...

declare import,SetWindowsHookExA(int idHook,unsigned int lpfn,unsigned int *hMod,unsigned int dwThreadId),unsigned int;
declare import,CallNextHookEx(unsigned int something,int nCode,void* wParam,void* lParam),unsigned int;
declare import,UnhookWindowsHookEx(unsigned int hhk),int;

declare import,GetModuleHandleA(string *lpModuleName),unsigned int;

struct CWPSTRUCT {
void *lParam;
void *wParam;
unsigned int message;
unsigned int hwnd;
}

struct CREATESTRUCT {
void *lpCreateParams;
unsigned int hInstance;
unsigned int hMenu;
unsigned int hwndParent;
int cy;
int cx;
int y;
int x;
unsigned int style;
string *lpszName;
string *lpszClass;
unsigned int dwExStyle;
};

class TestWindow : CWindow {

unsigned int m_Hook;

declare OnClose(),int {

UnhookWindowsHookEx(m_Hook);

Destroy();

return true;

}

declare OnCreate(),int {

m_Hook = SetWindowsHookExA(4,&HookRoutine,GetModuleHandleA(null),0);

if(m_Hook = null) {
MessageBox(0,"Failed To Create The Hook","Hook Information");
}

CenterWindow();

return true;

}

}

global sub main() {

TestWindow Main;

Main.Create(0,0,640,480,AWS_VISIBLE|AWS_CAPTION|AWS_SYSMENU,0,"Hook Testing",null);

Main.AddControl(CTBUTTON,"Button1",38,31,70,20,0x50000000|AWS_TABSTOP|ABS_OWNERDRAW,0,1);

do {

Wait();

} until(Main.m_hwnd = 0);

return 0;

}

sub HookRoutine(int nCode,void *wParam,void *lParam),int {

switch(*(CWPSTRUCT)lParam.message) {

case 0x0001: //WM_CREATE

//Something Is Being Created

}

return CallNextHookEx(null,nCode,wParam,lParam);

}


If anyone can help me out here that would be great.

Thanks
Lewis

JR

return CallNextHookEx(null,nCode,wParam,lParam);

As the first parameter you don't have to pass null,  but the handle of the hook returned by SetWindowsHookA.

Zen

Hmm, i didnt bother with that as the SDK says it was ignored.

Ill give it a whirl

Lewis

Ionic Wind Support Team

Well for one wparam and lparam are of type UINT (DWORD), not pointers.  You can still cast them in your callback function.  Thery are also wrong in your CWPSTRUCT. And you need to pass the handle of the hook returned by SetWindowsHookExA.

Your also creating a local hook, which in a class based language is kind of an overkill.  Considering you can just create your own class, override WndProc and create your own custom stuff.


Class myButtonClass : CButton
{
declare virtual WndProc(unsigned int message, unsigned int wparam, unsigned int lparam),int; //override
}

myButtonClass::WndProc(unsigned int message, unsigned int wparam, unsigned int lparam),int
{
      //handle any messages you want for this class, send the rest to the base class implimentation
      select(message)
      {
             case 0x0001: //WM_CREATE
             //Something Is Being Create
             //if we don't want any further processing
             return true;
      }
      //if we want to the default implementation to handle it then:
      return CButton!!WndProc(message, wparam, lparam);
}


This way the override is local and only effects the buttons your create. 

When you use SetWindowsHookExA your function will be called for every window being created in the thread, including windows that are created by the controls themselves such as a combobox control.  So you need to filter out who the message is for.

Paul.
Ionic Wind Support Team

Zen

Nope, didnt work either. Still crashes explorer and numerous other windows that i have open.

Lewis

Zen

Hi Paul, Yes i know i could do it that way, but i do want to be able to do it for all windows, but i will be filtering out the message for certain controls, its as much an experiment too as it is make the program, i like to try things to expand my knowledge aswell as build applications.

Ohh i didnt think i could cast them as something else if i created them as UINT's, although i did try it like that too. could you possibly correct the mistakes i have made?

Lewis

Ionic Wind Support Team

July 17, 2006, 04:56:27 PM #6 Last Edit: July 17, 2006, 05:00:00 PM by Paul Turley
And the final thing that is probabably calling your hook to fail is that hook functions must exist in a DLL if the threadID parameter is 0. 

See:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp

Quote
lpfn
    [in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link library (DLL). Otherwise, lpfn can point to a hook procedure in the code associated with the current process.
hMod
    [in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.
dwThreadId
    [in] Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread.

When the thread ID pareameter is zero your hooking all windows that share your current desktop.  And Windows cannot inject an executable into another process.  Only a DLL.  So for a simple hook in the current running executable you need GetCurrentThreadID.

Something like this should work.  But I am reluctant to run it since I have to much crap open right now ;)  Note that m_hook was moved out of the class definition since the hook procedure needs it too.


declare import,SetWindowsHookExA(int idHook,unsigned int lpfn,unsigned int *hMod,unsigned int dwThreadId),unsigned int;
declare import,CallNextHookEx(unsigned int hhk,int nCode,uint wParam,uint lParam),unsigned int;
declare import,UnhookWindowsHookEx(unsigned int hhk),int;
declare import,GetCurrentThreadId(),uint;

declare import,GetModuleHandleA(string *lpModuleName),unsigned int;

struct CWPSTRUCT {
uint lParam;
uint wParam;
unsigned int message;
unsigned int hwnd;
}

struct CREATESTRUCT {
void *lpCreateParams;
unsigned int hInstance;
unsigned int hMenu;
unsigned int hwndParent;
int cy;
int cx;
int y;
int x;
unsigned int style;
string *lpszName;
string *lpszClass;
unsigned int dwExStyle;
};

unsigned int m_Hook;


class TestWindow : CWindow {
declare OnClose(),int {
UnhookWindowsHookEx(m_Hook);
Destroy();
return true;
}

declare OnCreate(),int {
m_Hook = SetWindowsHookExA(4,&HookRoutine,NULL,GetCurrentThreadID());
if(m_Hook = null) {
MessageBox(0,"Failed To Create The Hook","Hook Information");
}
CenterWindow();
return true;

}
}

global sub main() {
TestWindow Main;
Main.Create(0,0,640,480,AWS_VISIBLE|AWS_CAPTION|AWS_SYSMENU,0,"Hook Testing",null);
Main.AddControl(CTBUTTON,"Button1",38,31,70,20,0x50000000|AWS_TABSTOP|ABS_OWNERDRAW,0,1);
do {
Wait();
} until(!Main.IsValid());
return 0;
}

sub HookRoutine(int nCode,uint wParam,uint lParam),int {
switch(*(CWPSTRUCT)lParam.message) {
case 0x0001: //WM_CREATE
//Something Is Being Created
}
return CallNextHookEx(m_hook,nCode,wParam,lParam);
}
Ionic Wind Support Team

Ionic Wind Support Team

Edited since hmod must be NULL if threadID is used.
Ionic Wind Support Team

Zen

Ohh dear, i dont even get a window with that exmple lol. I actually tried getting the GetTreadId to work with GetCurrentThread yesterday, i didnt realise there was a GetCurrentThreadId API call.

Anyway, i will study your example and try to get something among the 2 to work.

Thanks.
Lewis

Ionic Wind Support Team

Edited again, forgot the return type on GetCurrentThreadID
Ionic Wind Support Team

Zen

Yep, Your update did the trick ;)

Thanks Paul
Lewis

Zen

Well it seemed pointless to start a new topic as its still part of this project. Now that i have got the hooks to work, i now need to subclass certain controls etc. I know i can do it the easy way as Paul suggests and just subclass the classes wndProc or even just derive a new class, but i want to do it this way lol.

For some reason my subclassing routine is causing the application to crash, i have a feeling that i have again declared some types wrong, but im not sure what exactly.

Here is my code anyway...

/***********************************/
/*** Declare Windows API Imports ***/
/***********************************/

declare import,SetWindowsHookExA(int idHook,unsigned int lpfn,unsigned int *hMod,unsigned int dwThreadId),unsigned int;
declare import,CallNextHookEx(unsigned int hhk,int nCode,unsigned int wParam,unsigned int lParam),unsigned int;
declare import,UnhookWindowsHookEx(unsigned int hhk),int;

declare import,GetCurrentThreadId(),unsigned int;

declare import,OutputDebugStringA(string str);

declare import,SetWindowLongA(unsigned int hWnd,int nIndex,unsigned int dwNewLong),unsigned int;
declare import,GetWindowLong(unsigned int hWnd,int nIndex),unsigned int;
declare import,CallWindowProcA(unsigned int *lpPrevWndFunc,unsigned int hWnd,unsigned int Msg,unsigned int wParam,unsigned int lParam),int;

/*************************/
/*** Create Structures ***/
/*************************/

struct CWPSTRUCT {
unsigned int *lParam;
unsigned int *wParam;
unsigned int message;
unsigned int hwnd;
}

struct CREATESTRUCT {
void *lpCreateParams;
unsigned int hInstance;
unsigned int hMenu;
unsigned int hwndParent;
int cy;
int cx;
int y;
int x;
unsigned int style;
string *lpszName;
string *lpszClass;
unsigned int dwExStyle;
};

/************************/
/*** Global Variables ***/
/************************/

unsigned int m_Hook;
unsigned int OldWindowProc;

/********************************/
/*** Create Test Window Class ***/
/********************************/

class TestWindow : CWindow {

declare OnClose(),int {

UnhookWindowsHookEx(m_Hook);

Destroy();

return true;

}

declare OnCreate(),int {

CenterWindow();

return true;

}

}

/*******************************/
/*** Application Entry Point ***/
/*******************************/

global sub main() {

m_Hook = SetWindowsHookExA(4,&HookRoutine,null,GetCurrentThreadId());

if(m_Hook = null) {
MessageBox(0,"Failed To Create The Hook","Hook Information");
} else {
OutputDebugStringA("Hook Installed");
}

TestWindow Main;

Main.Create(0,0,640,480,AWS_VISIBLE|AWS_CAPTION|AWS_SYSMENU,0,"Hook Testing",null);

Main.AddControl(CTBUTTON,"Button1",38,31,70,20,0x50000000|AWS_TABSTOP,0x0,1);

do {

Wait();

} until(!Main.IsValid());

return 0;

}

/*************************************************/
/*** Subroutine Called When The Hook Is Called ***/
/*************************************************/

sub HookRoutine(int nCode,unsigned int wParam,unsigned int lParam),int {

if(*(CWPSTRUCT)lParam.message = 0x0001 /* WM_CREATE */ ) {

CREATESTRUCT *Temp = *(CWPSTRUCT)lParam.*(CREATESTRUCT)lParam;
unsigned int *TempHwnd = *(CWPSTRUCT)lParam.*(unsigned int)hwnd;

switch(Temp->*(string)lpszClass) {

case "AuroraWndClass":

OutputDebugStringA("Aurora Window Class Found");

case "Button":

OutputDebugStringA("Button Class Found");

OldWindowProc = SetWindowLongA(TempHwnd,(-4),&SubclassRoutine);

if(OldWindowProc = 0) {
OutputDebugStringA("Failed To Set Subclass Routine");
}

}

}

return CallNextHookEx(m_Hook,nCode,wParam,lParam);

}

sub SubclassRoutine(unsigned int hwnd,unsigned int uMsg,unsigned int wParam,unsigned int lParam),int {

OutputDebugStringa("Subclass Routine Called");

switch(uMsg) {

case 0x0001: //WM_CREATE

OutputDebugStringA("Class Found In Subclassing Routine");
SetWindowLongA(hwnd,-4,&oldWindowProc);

}

return CallWindowProcA(&oldWindowProc,hwnd,uMsg,wParam,lParam);

}


Lewis

Ionic Wind Support Team

Ummm.  Your receiving the WM_CREATE message and then immediatly restoring the old wndproc?  I don't think you can do that from within the subclassed wndproc itself.  It's normally done outside of the subclassed controls message handlers, like when the parent window is destroyed.

If your having problems converting API functions you should try Sapero's windows unclude files.



Ionic Wind Support Team

Zen

Im following an example done in VB6, as regards to how it is structured. so everything is in the same order lol. After placing debug statements in, it seems to be crashing after the return statement. so thats why i couldnt figure out wht was cusing it. Even without the callWindowProcA call it does it.

So i am a bit puzzled
Lewis

Parker

July 18, 2006, 09:56:57 AM #14 Last Edit: July 18, 2006, 09:58:53 AM by Parker
typedef struct {
    LPARAM lParam;
    WPARAM wParam;
    UINT message;
    HWND hwnd;
} CWPSTRUCT, *PCWPSTRUCT;


struct CWPSTRUCT {
    UINT lParam;
    UINT wParam;
    UINT message;
    UINT hwnd;
}


Currently you still have pointers for lParam and wParam, which may be the problem. At least it's worth a try and may eliminate future problems if it's not the current one.

Edit: If you could provide a link to the VB code, maybe I could translate it for you.

Zen

Yes sorry, i have actually chnged them since i posted the code, it makes no diference unfortunatley.

I will keep cracking at it though.

Lewis

Zen

VB Code...

Public Function fSetStyle(ByVal hwnd As Long, _
    ByVal Msg As Long, ByVal wParam As Long, _
    ByVal lParam As Long) As Long

Dim C As CREATESTRUCT
'
' This callback routine is called by Windows whenever a message
' is sent to the control indicated by hwnd. We are only interested
' in the create message.
'
Select Case Msg
    Case WM_CREATE
        '
        ' When a create message is sent, the lParam parameter has the
        ' address of a CreateStruct structure containing style
        ' information for the control being created.  This structure
        ' is copied locally, modified and then copied back so that the
        ' control is created with our desired style.
        '
        Call CopyMemory(C, ByVal lParam, Len(C))
        C.style = mlSetStyle
        Call CopyMemory(ByVal lParam, C, Len(C))
        '
        ' Set the new style.
        '
        Call SetWindowLong(hwnd, GWL_STYLE, C.style)
        '
        ' Unsub-class the control by assigning it the address
        ' of its original window procedure.
        '
        Call SetWindowLong(hwnd, GWL_WNDPROC, mlHookWndProc)
End Select
'
' Call the original window procedure.
'
fSetStyle = CallWindowProc(mlHookWndProc, hwnd, Msg, wParam, lParam)
End Function


Note: I have never used VB before :D

Lewis

Parker

global sub fSetStyle(hwnd As uint,
    Msg As uint, wParam As uint,
    lParam As uint),uint
{
/*'
' This callback routine is called by Windows whenever a message
' is sent to the control indicated by hwnd. We are only interested
' in the create message.
'*/
Select Msg {
    Case WM_CREATE:
        /*'
        ' When a create message is sent, the lParam parameter has the
        ' address of a CreateStruct structure containing style
        ' information for the control being created.  This structure
        ' is copied locally, modified and then copied back so that the
        ' control is created with our desired style.
        '*/
        *(CREATESTRUCT)lParam.style = mlSetStyle;
        /*'
        ' Set the new style.
        '*/
        SetWindowLong(hwnd, GWL_STYLE, *(CREATESTRUCT)lParam.style);
        /*'
        ' Unsub-class the control by assigning it the address
        ' of its original window procedure.
        '*/
        SetWindowLong(hwnd, GWL_WNDPROC, &mlHookWndProc);
}
/*'
' Call the original window procedure.
'*/
return CallWindowProc(mlHookWndProc, hwnd, Msg, wParam, lParam);
}


I think that's the translation, although you'll need to define a mlHookWndProc and I'm not exactly sure what mlSetStyle is (constant? sub? function?) If it's a subroutine, you'll need the parenthesis () because VB can call functions without them, while Aurora can't. I assume mlHookWndProc is something like a "Long" or UINT that contains the function address.

Also all of your handles shouldn't be pointers, just unsigned int's.
declare import,SetWindowsHookExA(int idHook,unsigned int lpfn,unsigned int *hMod,unsigned int dwThreadId),unsigned int;
should be
declare import,SetWindowsHookExA(int idHook,unsigned int lpfn,unsigned int hMod,unsigned int dwThreadId),unsigned int;

Zen

Hmm, well your translation is exactly what i have. So i have no idea why it isnt working. I really am stook on this one.

Lewis

Ionic Wind Support Team

When restoring the old window process it is not the address of the local variable you should be sending.

SetWindowLongA(hwnd,-4,oldWindowProc);

NOT SetWindowLongA(hwnd,-4,&oldWindowProc);

Same thing goes for CallWndProc

return CallWindowProcA(oldWindowProc,hwnd,uMsg,wParam,lParam);

NOT return CallWindowProcA(&oldWindowProc,hwnd,uMsg,wParam,lParam);

Whenver your taking an address of a pointer think twice "is this what the parameter specifies" when reading the MSDN description.  Don't depend on VB code, find C examples as they will be much easier to convert.  Anyway here is your working version. I Changed the declare for CallWndProcA, removed the two address of operators and away you go.

Paul.



/***********************************/
/*** Declare Windows API Imports ***/
/***********************************/

declare import,SetWindowsHookExA(int idHook,unsigned int lpfn,unsigned int *hMod,unsigned int dwThreadId),unsigned int;
declare import,CallNextHookEx(unsigned int hhk,int nCode,unsigned int wParam,unsigned int lParam),unsigned int;
declare import,UnhookWindowsHookEx(unsigned int hhk),int;

declare import,GetCurrentThreadId(),unsigned int;

declare import,OutputDebugStringA(string str);

declare import,SetWindowLongA(unsigned int hWnd,int nIndex,unsigned int dwNewLong),unsigned int;
declare import,GetWindowLong(unsigned int hWnd,int nIndex),unsigned int;
declare import,CallWindowProcA(unsigned int lpPrevWndFunc,unsigned int hWnd,unsigned int Msg,unsigned int wParam,unsigned int lParam),int;

/*************************/
/*** Create Structures ***/
/*************************/

struct CWPSTRUCT {
unsigned int *lParam;
unsigned int *wParam;
unsigned int message;
unsigned int hwnd;
}

struct CREATESTRUCT {
void *lpCreateParams;
unsigned int hInstance;
unsigned int hMenu;
unsigned int hwndParent;
int cy;
int cx;
int y;
int x;
unsigned int style;
string *lpszName;
string *lpszClass;
unsigned int dwExStyle;
};

/************************/
/*** Global Variables ***/
/************************/

unsigned int m_Hook;
unsigned int OldWindowProc;

/********************************/
/*** Create Test Window Class ***/
/********************************/

class TestWindow : CWindow {

declare OnClose(),int {

UnhookWindowsHookEx(m_Hook);

Destroy();

return true;

}

declare OnCreate(),int {

CenterWindow();

return true;

}

}

/*******************************/
/*** Application Entry Point ***/
/*******************************/

global sub main() {

m_Hook = SetWindowsHookExA(4,&HookRoutine,null,GetCurrentThreadId());

if(m_Hook = null) {
MessageBox(0,"Failed To Create The Hook","Hook Information");
} else {
OutputDebugStringA("Hook Installed");
}

TestWindow Main;

Main.Create(0,0,640,480,AWS_VISIBLE|AWS_CAPTION|AWS_SYSMENU,0,"Hook Testing",null);

Main.AddControl(CTBUTTON,"Button1",38,31,70,20,0x50000000|AWS_TABSTOP,0x0,1);

do {

Wait();

} until(!Main.IsValid());

return 0;

}

/*************************************************/
/*** Subroutine Called When The Hook Is Called ***/
/*************************************************/

sub HookRoutine(int nCode,unsigned int wParam,unsigned int lParam),int {

if(*(CWPSTRUCT)lParam.message = 0x0001 /* WM_CREATE */ ) {

CREATESTRUCT *Temp = *(CWPSTRUCT)lParam.*(CREATESTRUCT)lParam;
unsigned int *TempHwnd = *(CWPSTRUCT)lParam.*(unsigned int)hwnd;

switch(Temp->*(string)lpszClass) {

case "AuroraWndClass":

OutputDebugStringA("Aurora Window Class Found");

case "Button":

OutputDebugStringA("Button Class Found");

OldWindowProc = SetWindowLongA(TempHwnd,(-4),&SubclassRoutine);

if(OldWindowProc = 0) {
OutputDebugStringA("Failed To Set Subclass Routine");
}

}

}

return CallNextHookEx(m_Hook,nCode,wParam,lParam);

}

sub SubclassRoutine(unsigned int hwnd,unsigned int uMsg,unsigned int wParam,unsigned int lParam),int {

OutputDebugStringa("Subclass Routine Called");

switch(uMsg) {

case 0x0001: //WM_CREATE

OutputDebugStringA("Class Found In Subclassing Routine");
SetWindowLongA(hwnd,-4,oldWindowProc);

}

return CallWindowProcA(oldWindowProc,hwnd,uMsg,wParam,lParam);

}
Ionic Wind Support Team

Zen

Ohh yes of course. I was obviously getting thinking i was passing back a subroutine, which i guess i am in some way. How stupid of me, always the simple things in life that cause the big problems.

Thanks again Paul

Lewis