2

I have been writting a DLL, and tried to get notification about locking the screen by user. I found that WM_WTSSESSION_CHANGE will be suitable for my needs, but I cannot read this message in my library, moreover when I have spied the app with the spyxx.exe I could see that the WM_WTSSESSION_CHANGE message is posted.

Could anyone take a look and say what am I doing wrong?

Some essentials listings:

setting up WndProc callback:

HHOOK hook = SetWindowsHookEx(
        WH_CALLWNDPROC,
        (HOOKPROC) __monitor,
        hInstance,
        GetCurrentThreadId());

registry for event notification:

WTSRegisterSessionNotification(hwnd, NOTIFY_FOR_THIS_SESSION);

a callback function:

LRESULT CALLBACK __monitor(
    int code,
    WPARAM wParam,
    LPARAM lParam)
{

    CWPSTRUCT *msg= (CWPSTRUCT *) lParam;
    // have verified that the statement : hwnd == msg->hwnd is true
    switch (msg->message)
    {
        // ...
        case WM_DESTROY:
            //... this case is handled OK
            break;
        case WM_WTSSESSION_CHANGE:
            //... FAIL, never enters here
            break;
    }
// CallNextHookEx ..
}
  • Which window does `hwnd` refer to in your call to `WTSRegisterSessionNotificanion`? – Ross Ridge Aug 19 '14 at 14:39
  • hwnd refers to the top-level window of the application – Erl Shagrat Aug 19 '14 at 15:33
  • Where does your DLL get `hwnd` from? Are you sure `hwnd` is running in the thread context that `GetCurrentThreadId()` refers to? Have you considered having your DLL simply spawn a thread with its own hidden HWND to receive the message instead of hooking someone else's HWND? – Remy Lebeau Aug 19 '14 at 17:33
  • 1
    `WH_CALLWNDPROC` is only for `Sent` messages. – user1793036 Aug 20 '14 at 01:40

2 Answers2

2

You don't need a Windows-hook as a callback, any window procedure with message-loop will do the trick. Use normal approach.

Did you check the return value of WTSRegisterSessionNotification? You may need elevated rights (Admin rights).

Ajay
  • 18,086
  • 12
  • 59
  • 105
  • I'm aware that a normal approach will work too, Using of a Windows-hook as a callback is a result of a library design. Yes, I have already checked the return value of `WTSRegisterSessionNotification` and it returns always a TRUE. Also ran my test application with Admin rights and nothing has changed. – Erl Shagrat Aug 19 '14 at 15:26
  • Consider subclassing the HWND using `SetWindowSubClass()` instead of using a lower-level hook. – Remy Lebeau Aug 19 '14 at 17:34
  • Sticking to a design that is flawed seems futile – David Heffernan Aug 19 '14 at 19:25
2

It looks like you're running into two problems. The first is that thread id you pass to SetWindowsHookEx must be the same thread id of the thread your main top-level window runs in. Fixing the that problem will mean that the hook function will be called in the same thread as the window. If you need to process it in another thread you'll have to have the hook function signal the the other thread.

The second is that the WH_CALLWNDPROC hook functions don't appear to be delivered WM_WTSSESSION_CHANGE messages, probably because it's posted rather than sent. Using a WH_GETMESSAGE hook works however.

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
  • After hooking to `WH_GETMESSAGE`, finally start catching the messages Many thanks! – Erl Shagrat Aug 20 '14 at 17:21
  • Yah, I didn't realize why `WH_CALLWNDPROC` wasn't working until another question here had me looking more closely at the messages the two different hooks were capturing. It's not obvious from the documentation that when `DispatchMessage` calls the windows procedure this isn't considered a call of the windows procedure by the `WH_CALLWNDPROC` hook logic. – Ross Ridge Aug 20 '14 at 18:00