3

I have a little problem with Qt , here is my code :

SessionSnatcher.h:

#ifndef SESSIONSNATCHER_H
#define SESSIONSNATCHER_H

#include <Windows.h>
#include <QThread>
#include <QtCore>
#include <QDebug>


class SessionSnatcher : public QThread
{
public:
    SessionSnatcher();
    ~SessionSnatcher();
    void run();
    void SetPID(int pid);
    void SetTID(int tid);
    int GetPID();
    int GetTID();
    HWND GetCOProductControl();

private:

    //HWND GetCOProductControl();
    void CALLBACK SessionSnatcher::handler(HWINEVENTHOOK hook , DWORD event , LONG idChild , LONG idObject , DWORD dwEventThread , DWORD dwmsEventTime);
    HWINEVENTHOOK hook;
    int PID , TID;

};

#endif // SESSIONSNATCHER_H

SessionSnatcher.cpp :

#include "sessionsnatcher.h"

SessionSnatcher::SessionSnatcher()
{

}

SessionSnatcher::~SessionSnatcher()
{
    UnhookWinEvent(hook);
}

void CALLBACK SessionSnatcher::handler(HWINEVENTHOOK hook , DWORD event , LONG idChild , LONG idObject , DWORD dwEventThread , DWORD dwmsEventTime)
{

}

void SessionSnatcher::run()
{
    hook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND , EVENT_SYSTEM_FOREGROUND , NULL , &SessionSnatcher::handler , PID , TID , WINEVENT_OUTOFCONTEXT);
}



HWND SessionSnatcher::GetCOProductControl()
{
    HWND TPanel = FindWindow(L"TPanel" , NULL);
    return TPanel;
}

void SessionSnatcher::SetPID(int pid)
{
    PID = pid;
}

void SessionSnatcher::SetTID(int tid)
{
    TID = tid;
}

int SessionSnatcher::GetPID()
{
    return PID;
}

int SessionSnatcher::GetTID()
{
    return TID;
}

And now i keep getting this error :

D:\TT\sessionsnatcher.cpp:25: error: C2664: 'HWINEVENTHOOK SetWinEventHook(DWORD,DWORD,HMODULE,WINEVENTPROC,DWORD,DWORD,DWORD)' : cannot convert argument 4 from 'void (__stdcall SessionSnatcher::* )(HWINEVENTHOOK,DWORD,LONG,LONG,DWORD,DWORD)' to 'WINEVENTPROC'
There is no context in which this conversion is possible

Before this i was using "handler" instead of "&SessionSnatcher::handler" but i had a problem saying it was a member and it cant be used like that. Now i cant work it out. It worked well on Visual Studio When i tried it , all i had to do was cast like (WINEVENTPROC)handler , but i think since im using a separate class i cant do that anymore.

Any tips ?

RedZ
  • 857
  • 1
  • 13
  • 25

1 Answers1

2

You have fallen victim to the hidden this parameter in every non-static class methods. A modern solution is to use std::bind, but that won't help you with a C-based API or a C++ API that predates C++11.

The typical solution when std::bind isn't available is a free function or static method that

  1. meets the prototype you need to supply,
  2. maps the callback to the object, and
  3. invokes the desired method on the object found in 2.

Often Win32 API calls have a pointer to a user argument you can use to make this easy: just cast the pointer to SessionSnatcher * and call the function. I don't see a user argument in WinEventProc's parameter list, so you'll have to get creative and map one of the event ids or handles WinEventProc does provide and uniquely identifies a SessionSnatcher.

Or if you only have one SessionSnatcher you can write the function to always use that one SessionSnatcher.

Here is a generic example:

#include <iostream>
#include <map>

typedef int (*funcp)(int id, int p1, int p2);
// using typedef instead of using on purpose because that's what'll be in
// the Windows API

class test
{
private:
    static std::map<int, test*> tests; // our map of id -> test objects
    int id; // this test's id. Only included for proof
public:
    test(int id):id(id)
    {
        tests[id] = this; // put in map. In the real world test for collision first
    }

    // function that will eventually be called
    int func(int p1, int p2)
    {
        (void) p1;
        (void) p2;
        std::cout << "Called func for " << id << std::endl;
        return 0;
    }

    // static method that can be called by API
    static int staticfunc(int id, int p1, int p2)
    {
        // look up object and call non-static method
        // I recommend at() instead of [] because you get a catchable exception
        // rather than a crash over null pointer if id is unknown.
        return tests.at(id)->func(p1, p2);
    }
};

// allocating storage for static map
std::map<int, test*> test::tests;

// function mocking up API. Takes a function and an identifier used by called function
int caller(funcp func,
           int id)
{
    return func(id, 100, 20); // just calls the function
}

// tester
int main(void)
{
    test a(1); // create a test
    test b(2); // create a test

    try
    {
        caller(test::staticfunc, 2); // call test 2 through API
        caller(test::staticfunc, 1); // call test 1 through API
        caller(test::staticfunc, 10); // throw exception over unknown id
    }
    catch (std::exception &e)
    {
        std::cout << "Failed call: " << e.what() << std::endl;
    }
}

Typical output:

Called func for 2
Called func for 1
Failed call: map::at

"map::at" isn't much of an exception message, but it can be converted into a useful log message. At any rate it beats a segfault with no information.

Community
  • 1
  • 1
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • Thank you for your answer , i have tried using a free function for the callback (i hope thats what you meant) but i still got the same error ! – RedZ Jun 11 '16 at 01:23
  • But it worked with the original `handler` function, yes? Currently `SessionSnatcher::handler` appears to be missing `WinEventProc`'s third parameter: `HWND hwnd`. A free function that is also missing this parameter will generate the exact same error message. Sorry I did not spot that earlier. – user4581301 Jun 11 '16 at 01:30
  • You know i've just tried to remove (WINEVENTPROC) from handler and i still get an error , and BTW ive noticed i missed HWND's parameter from the Handler Callback i dont know how i missed it ! Current Error : `sessionsnatcher.obj:-1: error: LNK2019: unresolved external symbol __imp__SetWinEventHook@28 referenced in function "public: virtual void __thiscall SessionSnatcher::run(void)" (?run@SessionSnatcher@@UAEXXZ)` – RedZ Jun 11 '16 at 01:42
  • Have you added `User32` to Project->Properties->Configuration Properties->Linker->Input->Additional Dependencies? – user4581301 Jun 11 '16 at 02:00
  • Wow ! even though that was the first thing i always do but i forgot it this time ! That was it , Just `LIBS += -luser32` solved it. Thanks for you help @user4581301 – RedZ Jun 11 '16 at 02:04