// W32LowLevelMonitor.cc --- ActivityMonitor for W32
//
// Copyright (C) 2007, 2010, 2012 Ray Satiro <raysatiro@yahoo.com>
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//

#ifndef W32LOWLEVELMONITOR_HH
#define W32LOWLEVELMONITOR_HH

#include "InputMonitor.hh"

class W32LowLevelMonitor :
  public InputMonitor
{
public:
  W32LowLevelMonitor();
  virtual ~W32LowLevelMonitor();
  bool init();
  void terminate();
  static W32LowLevelMonitor *singleton;

protected:
  static DWORD WINAPI thread_Dispatch( LPVOID );
  static DWORD WINAPI thread_Callback( LPVOID );

private:

  struct thread_struct
    {
      volatile bool active;
      DWORD id;
      HANDLE handle;
      const char *name;
      thread_struct()
        {
          active = false;
          id = 0;
          handle = NULL;
          name = NULL;
        }
    };
  static thread_struct *dispatch, *callback;

  bool wait_for_thread_queue( thread_struct * );
  void terminate_thread( thread_struct * );
  void wait_for_thread_to_exit( thread_struct * );
  void unhook();

  DWORD dispatch_thread();
  DWORD time_critical_callback_thread();

  static LRESULT CALLBACK k_hook_callback( int, WPARAM, LPARAM );
  static LRESULT CALLBACK m_hook_callback( int, WPARAM, LPARAM );

  static volatile HHOOK k_hook;
  static volatile HHOOK m_hook;

  static HMODULE process_handle;
};

#ifndef WM_XBUTTONDOWN
#define WM_XBUTTONDOWN 523
#endif

#ifndef WM_XBUTTONUP
#define WM_XBUTTONUP 524
#endif

#ifndef WM_XBUTTONDBLCLK
#define WM_XBUTTONDBLCLK 525
#endif

#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 526
#endif

#define LLKHF_INJECTED 0x00000010
#define LLMHF_INJECTED 0x00000001

typedef struct {
    DWORD vkCode;
    DWORD scanCode;
    DWORD flags;
    DWORD time;
    ULONG_PTR dwExtraInfo;
} _KBDLLHOOKSTRUCT;

typedef struct {
    POINT pt;
    DWORD mouseData;
    DWORD flags;
    DWORD time;
    ULONG_PTR dwExtraInfo;
} _MSLLHOOKSTRUCT;

#endif // W32LOWLEVELMONITOR_HH
