diff --git a/Cargo.toml b/Cargo.toml index df94d3ba..69bbf657 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,12 +4,6 @@ version = "0.1.0" authors = ["Nicolas Patry "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" - [target.'cfg(target_os = "macos")'.dependencies] cocoa = "0.20" core-graphics = {version = "0.19.0", features = ["highsierra"]} @@ -19,6 +13,8 @@ core-graphics = {version = "0.19.0", features = ["highsierra"]} libc = "0.2" x11 = {version = "2.18", features = ["xlib", "xrecord"]} +[target.'cfg(target_os = "windows")'.dependencies] +winapi = { version = "0.3", features = ["winuser", "errhandlingapi"] } [dev-dependencies] tokio = {version = "0.2", features=["process", "rt-core", "io-util", "macros"]} diff --git a/examples/simulate.rs b/examples/simulate.rs index f06110fc..be1a993a 100644 --- a/examples/simulate.rs +++ b/examples/simulate.rs @@ -14,8 +14,8 @@ fn send(event_type: &EventType) { } fn main() { - send(&EventType::KeyPress { code: 39 }); - send(&EventType::KeyRelease { code: 39 }); + send(&EventType::KeyPress { code: 83 }); + send(&EventType::KeyRelease { code: 83 }); send(&EventType::MouseMove { x: 0.0, y: 0.0 }); send(&EventType::MouseMove { x: 400.0, y: 400.0 }); diff --git a/src/lib.rs b/src/lib.rs index dfbd698d..9ac4406d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,3 +11,9 @@ mod linux; #[cfg(target_os = "linux")] pub use crate::linux::{listen, simulate}; + +#[cfg(target_os = "windows")] +mod win; + +#[cfg(target_os = "windows")] +pub use crate::win::{listen, simulate}; \ No newline at end of file diff --git a/src/linux/mod.rs b/src/linux/mod.rs index 83cb4499..5a50a4d0 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -1,7 +1,7 @@ extern crate libc; extern crate x11; -use crate::rdev::{Event, EventType, SimulateError}; +use crate::rdev::{Event, EventType, SimulateError, Callback}; use std::ffi::CString; use std::os::raw::c_int; use std::ptr::{null, null_mut}; @@ -12,8 +12,6 @@ use x11::xtest; static mut EVENT_COUNT: u32 = 0; -type Callback = fn(event: Event); - fn default_callback(event: Event) { println!("Default : Event {:?}", event); } diff --git a/src/rdev.rs b/src/rdev.rs index b217a902..871e1cce 100644 --- a/src/rdev.rs +++ b/src/rdev.rs @@ -1,5 +1,8 @@ use std::time::SystemTime; +/// Callback type to send to listen function. +pub type Callback = fn(event: Event); + /// Marking an error when we tried to simulate and event #[derive(Debug)] pub struct SimulateError; diff --git a/src/win/mod.rs b/src/win/mod.rs new file mode 100644 index 00000000..66499d42 --- /dev/null +++ b/src/win/mod.rs @@ -0,0 +1,241 @@ +extern crate winapi; + +use crate::rdev::{Callback, Event, EventType, SimulateError}; +use std::mem::{size_of, transmute, transmute_copy}; +use std::ptr::null_mut; +use std::time::SystemTime; +use winapi::ctypes::c_int; +use winapi::shared::windef::{HHOOK}; +use winapi::um::errhandlingapi::GetLastError; +use winapi::um::winuser::{ + CallNextHookEx, GetMessageA, GetSystemMetrics, SendInput, SetWindowsHookExA, HC_ACTION, INPUT, + INPUT_KEYBOARD, INPUT_MOUSE, KBDLLHOOKSTRUCT, KEYBDINPUT, KEYEVENTF_KEYUP, LPINPUT, + MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_HWHEEL, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, + MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, + MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, MOUSEEVENTF_XUP, MOUSEINPUT, + MSLLHOOKSTRUCT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, WHEEL_DELTA, WH_KEYBOARD_LL, + WH_MOUSE_LL, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, + WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_XBUTTONDOWN, + WM_XBUTTONUP, +}; + +static KEYEVENTF_KEYDOWN: u32 = 0; // Not defined in win32 but define here for clarity + +fn default_callback(event: Event) { + println!("Default : Event {:?}", event); +} + +static mut GLOBAL_CALLBACK: Callback = default_callback; +static mut HOOK: HHOOK = null_mut(); + +unsafe fn get_code(lpdata: isize) -> u8 { + let kb = *(lpdata as *const KBDLLHOOKSTRUCT); + kb.vkCode as u8 +} +unsafe fn get_point(lpdata: isize) -> (i32, i32) { + let mouse = *(lpdata as *const MSLLHOOKSTRUCT); + (mouse.pt.x, mouse.pt.y) +} +/// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644986(v=vs.85) +unsafe fn get_delta(lpdata: isize) -> i32 { + let mouse = *(lpdata as *const MSLLHOOKSTRUCT); + (mouse.mouseData as i32 >> 16) as i32 +} +unsafe fn get_button_code(lpdata: isize) -> i32 { + let mouse = *(lpdata as *const MSLLHOOKSTRUCT); + (mouse.mouseData as i32 >> 16) as i32 +} + +unsafe extern "system" fn raw_callback(code: i32, param: usize, lpdata: isize) -> isize { + if code == HC_ACTION { + let opt = match param { + x if x == WM_KEYDOWN as usize => { + let code = get_code(lpdata); + Some(EventType::KeyPress { code }) + } + x if x == WM_KEYUP as usize => { + let code = get_code(lpdata); + Some(EventType::KeyRelease { code }) + } + x if x == WM_LBUTTONDOWN as usize => Some(EventType::ButtonPress { code: 1 }), + x if x == WM_LBUTTONUP as usize => Some(EventType::ButtonRelease { code: 1 }), + x if x == WM_MBUTTONDOWN as usize => Some(EventType::ButtonPress { code: 2 }), + x if x == WM_MBUTTONUP as usize => Some(EventType::ButtonRelease { code: 2 }), + x if x == WM_RBUTTONDOWN as usize => Some(EventType::ButtonPress { code: 3 }), + x if x == WM_RBUTTONUP as usize => Some(EventType::ButtonRelease { code: 3 }), + x if x == WM_XBUTTONDOWN as usize => { + let code = get_button_code(lpdata) as u8 + 3; + Some(EventType::ButtonPress { code }) + } + x if x == WM_XBUTTONUP as usize => { + let code = get_button_code(lpdata) as u8 + 3; + + Some(EventType::ButtonRelease { code }) + } + + x if x == WM_MOUSEMOVE as usize => { + let (x, y) = get_point(lpdata); + Some(EventType::MouseMove { + x: x as f64, + y: y as f64, + }) + } + x if x == WM_MOUSEWHEEL as usize => { + let delta = get_delta(lpdata); + Some(EventType::Wheel { + delta_x: 0, + delta_y: (delta as i64) / WHEEL_DELTA as i64, + }) + } + x if x == WM_MOUSEHWHEEL as usize => { + let delta = get_delta(lpdata); + + Some(EventType::Wheel { + delta_x: (delta as i64) / WHEEL_DELTA as i64, + delta_y: 0, + }) + } + _ => None, + }; + + if let Some(event_type) = opt { + let event = Event { + event_type, + time: SystemTime::now(), + name: None, + }; + GLOBAL_CALLBACK(event); + } + } + CallNextHookEx(HOOK, code, param, lpdata) +} + +unsafe fn set_key_hook() { + let hook = SetWindowsHookExA(WH_KEYBOARD_LL, Some(raw_callback), null_mut(), 0); + if hook == null_mut() { + let error = GetLastError(); + panic!("Can't set system hook! {:?}", error) + } + HOOK = hook; +} +unsafe fn set_mouse_hook() { + let hook = SetWindowsHookExA(WH_MOUSE_LL, Some(raw_callback), null_mut(), 0); + if hook == null_mut() { + let error = GetLastError(); + panic!("Can't set system hook! {:?}", error) + } + HOOK = hook; +} + +pub fn listen(callback: Callback) { + unsafe { + GLOBAL_CALLBACK = callback; + set_key_hook(); + set_mouse_hook(); + + GetMessageA(null_mut(), null_mut(), 0, 0); + } +} + +fn mouse_event(flags: u32, data: u32, dx: i32, dy: i32) -> Result<(), SimulateError> { + let mut input = INPUT { + type_: INPUT_MOUSE, + u: unsafe { + transmute(MOUSEINPUT { + dx, + dy, + mouseData: data, + dwFlags: flags, + time: 0, + dwExtraInfo: 0, + }) + }, + }; + let value = unsafe { SendInput(1, &mut input as LPINPUT, size_of::() as c_int) }; + if value!= 1{ + Err(SimulateError) + }else{ + Ok(()) + } +} + +fn keyboard_event(flags: u32, vk: u16, scan: u16) -> Result<(), SimulateError> { + let mut input = INPUT { + type_: INPUT_KEYBOARD, + u: unsafe { + transmute_copy(&KEYBDINPUT { + wVk: vk, + wScan: scan, + dwFlags: flags, + time: 0, + dwExtraInfo: 0, + }) + }, + }; + let value = unsafe { SendInput(1, &mut input as LPINPUT, size_of::() as c_int) }; + if value != 1{ + Err(SimulateError) + }else{ + Ok(()) + } +} + +pub fn simulate(event_type: &EventType) -> Result<(), SimulateError> { + match event_type { + EventType::KeyPress { code } => keyboard_event(KEYEVENTF_KEYDOWN, *code as u16, 0), + EventType::KeyRelease { code } => keyboard_event(KEYEVENTF_KEYUP, *code as u16, 0), + EventType::ButtonPress { code } => match code { + 1 => mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0), + 2 => mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0), + 3 => mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0), + _ => mouse_event(MOUSEEVENTF_XDOWN, 0, 0, (code - 3) as i32), + }, + EventType::ButtonRelease { code } => match code { + 1 => mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0), + 2 => mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0), + 3 => mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0), + _ => mouse_event(MOUSEEVENTF_XUP, 0, 0, (code - 3) as i32), + }, + EventType::Wheel { delta_x, delta_y } => { + let result_x = if *delta_x != 0 { + mouse_event( + MOUSEEVENTF_HWHEEL, + 0, + (delta_x * WHEEL_DELTA as i64) as i32, + 0, + ) + } else { + Ok(()) + }; + + let result_y = if *delta_y != 0 { + mouse_event( + MOUSEEVENTF_WHEEL, + 0, + 0, + (delta_y * WHEEL_DELTA as i64) as i32, + ) + } else { + Ok(()) + }; + + if result_x.is_ok() && result_y.is_ok() { + Ok(()) + } else { + Err(SimulateError) + } + } + EventType::MouseMove { x, y } => { + let width = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) }; + let height = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) }; + + + mouse_event( + MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, + 0, + (*x * 65335.0) as i32 / width, + (*y * 65335.0) as i32 / height, + ) + } + } +} diff --git a/src/win/windows.cpp b/src/win/windows.cpp new file mode 100644 index 00000000..a86e7b87 --- /dev/null +++ b/src/win/windows.cpp @@ -0,0 +1,586 @@ +#include +#include +#include "app.h" + +#pragma comment( lib, "user32.lib") +#pragma comment( lib, "gdi32.lib") + +#define NUMHOOKS 7 + +// Global variables + +typedef struct _MYHOOKDATA +{ + int nType; + HOOKPROC hkprc; + HHOOK hhook; +} MYHOOKDATA; + +MYHOOKDATA myhookdata[NUMHOOKS]; + +HWND gh_hwndMain; + +// Hook procedures + +LRESULT WINAPI CallWndProc(int, WPARAM, LPARAM); +LRESULT WINAPI CBTProc(int, WPARAM, LPARAM); +LRESULT WINAPI DebugProc(int, WPARAM, LPARAM); +LRESULT WINAPI GetMsgProc(int, WPARAM, LPARAM); +LRESULT WINAPI KeyboardProc(int, WPARAM, LPARAM); +LRESULT WINAPI MouseProc(int, WPARAM, LPARAM); +LRESULT WINAPI MessageProc(int, WPARAM, LPARAM); + +void LookUpTheMessage(PMSG, LPTSTR); + +LRESULT WINAPI MainWndProc(HWND hwndMain, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static BOOL afHooks[NUMHOOKS]; + int index; + static HMENU hmenu; + + gh_hwndMain = hwndMain; + + switch (uMsg) + { + case WM_CREATE: + + // Save the menu handle + + hmenu = GetMenu(hwndMain); + + // Initialize structures with hook data. The menu-item identifiers are + // defined as 0 through 6 in the header file app.h. They can be used to + // identify array elements both here and during the WM_COMMAND message. + + myhookdata[IDM_CALLWNDPROC].nType = WH_CALLWNDPROC; + myhookdata[IDM_CALLWNDPROC].hkprc = CallWndProc; + myhookdata[IDM_CBT].nType = WH_CBT; + myhookdata[IDM_CBT].hkprc = CBTProc; + myhookdata[IDM_DEBUG].nType = WH_DEBUG; + myhookdata[IDM_DEBUG].hkprc = DebugProc; + myhookdata[IDM_GETMESSAGE].nType = WH_GETMESSAGE; + myhookdata[IDM_GETMESSAGE].hkprc = GetMsgProc; + myhookdata[IDM_KEYBOARD].nType = WH_KEYBOARD; + myhookdata[IDM_KEYBOARD].hkprc = KeyboardProc; + myhookdata[IDM_MOUSE].nType = WH_MOUSE; + myhookdata[IDM_MOUSE].hkprc = MouseProc; + myhookdata[IDM_MSGFILTER].nType = WH_MSGFILTER; + myhookdata[IDM_MSGFILTER].hkprc = MessageProc; + + // Initialize all flags in the array to FALSE. + + memset(afHooks, FALSE, sizeof(afHooks)); + + return 0; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + // The user selected a hook command from the menu. + + case IDM_CALLWNDPROC: + case IDM_CBT: + case IDM_DEBUG: + case IDM_GETMESSAGE: + case IDM_KEYBOARD: + case IDM_MOUSE: + case IDM_MSGFILTER: + + // Use the menu-item identifier as an index + // into the array of structures with hook data. + + index = LOWORD(wParam); + + // If the selected type of hook procedure isn't + // installed yet, install it and check the + // associated menu item. + + if (!afHooks[index]) + { + myhookdata[index].hhook = SetWindowsHookEx( + myhookdata[index].nType, + myhookdata[index].hkprc, + (HINSTANCE) NULL, GetCurrentThreadId()); + CheckMenuItem(hmenu, index, + MF_BYCOMMAND | MF_CHECKED); + afHooks[index] = TRUE; + } + + // If the selected type of hook procedure is + // already installed, remove it and remove the + // check mark from the associated menu item. + + else + { + UnhookWindowsHookEx(myhookdata[index].hhook); + CheckMenuItem(hmenu, index, + MF_BYCOMMAND | MF_UNCHECKED); + afHooks[index] = FALSE; + } + + default: + return (DefWindowProc(hwndMain, uMsg, wParam, + lParam)); + } + break; + + // + // Process other messages. + // + + default: + return DefWindowProc(hwndMain, uMsg, wParam, lParam); + } + return NULL; +} + +/**************************************************************** + WH_CALLWNDPROC hook procedure + ****************************************************************/ + +LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + CHAR szCWPBuf[256]; + CHAR szMsg[16]; + HDC hdc; + static int c = 0; + size_t cch; + HRESULT hResult; + + if (nCode < 0) // do not process message + return CallNextHookEx(myhookdata[IDM_CALLWNDPROC].hhook, nCode, wParam, lParam); + + // Call an application-defined function that converts a message + // constant to a string and copies it to a buffer. + + LookUpTheMessage((PMSG) lParam, szMsg); + + hdc = GetDC(gh_hwndMain); + + switch (nCode) + { + case HC_ACTION: + hResult = StringCchPrintf(szCWPBuf, 256/sizeof(TCHAR), + "CALLWNDPROC - tsk: %ld, msg: %s, %d times ", + wParam, szMsg, c++); + if (FAILED(hResult)) + { + // TODO: writer error handler + } + hResult = StringCchLength(szCWPBuf, 256/sizeof(TCHAR), &cch); + if (FAILED(hResult)) + { + // TODO: write error handler + } + TextOut(hdc, 2, 15, szCWPBuf, cch); + break; + + default: + break; + } + + ReleaseDC(gh_hwndMain, hdc); + + return CallNextHookEx(myhookdata[IDM_CALLWNDPROC].hhook, nCode, wParam, lParam); +} + +/**************************************************************** + WH_GETMESSAGE hook procedure + ****************************************************************/ + +LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + CHAR szMSGBuf[256]; + CHAR szRem[16]; + CHAR szMsg[16]; + HDC hdc; + static int c = 0; + size_t cch; + HRESULT hResult; + + if (nCode < 0) // do not process message + return CallNextHookEx(myhookdata[IDM_GETMESSAGE].hhook, nCode, + wParam, lParam); + + switch (nCode) + { + case HC_ACTION: + switch (wParam) + { + case PM_REMOVE: + hResult = StringCchCopy(szRem, 16/sizeof(TCHAR), "PM_REMOVE"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case PM_NOREMOVE: + hResult = StringCchCopy(szRem, 16/sizeof(TCHAR), "PM_NOREMOVE"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + default: + hResult = StringCchCopy(szRem, 16/sizeof(TCHAR), "Unknown"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + } + + // Call an application-defined function that converts a + // message constant to a string and copies it to a + // buffer. + + LookUpTheMessage((PMSG) lParam, szMsg); + + hdc = GetDC(gh_hwndMain); + hResult = StringCchPrintf(szMSGBuf, 256/sizeof(TCHAR), + "GETMESSAGE - wParam: %s, msg: %s, %d times ", + szRem, szMsg, c++); + if (FAILED(hResult)) + { + // TODO: write error handler + } + hResult = StringCchLength(szMSGBuf, 256/sizeof(TCHAR), &cch); + if (FAILED(hResult)) + { + // TODO: write error handler + } + TextOut(hdc, 2, 35, szMSGBuf, cch); + break; + + default: + break; + } + + ReleaseDC(gh_hwndMain, hdc); + + return CallNextHookEx(myhookdata[IDM_GETMESSAGE].hhook, nCode, wParam, lParam); +} + +/**************************************************************** + WH_DEBUG hook procedure + ****************************************************************/ + +LRESULT CALLBACK DebugProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + CHAR szBuf[128]; + HDC hdc; + static int c = 0; + size_t cch; + HRESULT hResult; + + if (nCode < 0) // do not process message + return CallNextHookEx(myhookdata[IDM_DEBUG].hhook, nCode, + wParam, lParam); + + hdc = GetDC(gh_hwndMain); + + switch (nCode) + { + case HC_ACTION: + hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), + "DEBUG - nCode: %d, tsk: %ld, %d times ", + nCode,wParam, c++); + if (FAILED(hResult)) + { + // TODO: write error handler + } + hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch); + if (FAILED(hResult)) + { + // TODO: write error handler + } + TextOut(hdc, 2, 55, szBuf, cch); + break; + + default: + break; + } + + ReleaseDC(gh_hwndMain, hdc); + + return CallNextHookEx(myhookdata[IDM_DEBUG].hhook, nCode, wParam, lParam); +} + +/**************************************************************** + WH_CBT hook procedure + ****************************************************************/ + +LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + CHAR szBuf[128]; + CHAR szCode[128]; + HDC hdc; + static int c = 0; + size_t cch; + HRESULT hResult; + + if (nCode < 0) // do not process message + return CallNextHookEx(myhookdata[IDM_CBT].hhook, nCode, wParam, + lParam); + + hdc = GetDC(gh_hwndMain); + + switch (nCode) + { + case HCBT_ACTIVATE: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_ACTIVATE"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case HCBT_CLICKSKIPPED: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_CLICKSKIPPED"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case HCBT_CREATEWND: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_CREATEWND"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case HCBT_DESTROYWND: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_DESTROYWND"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case HCBT_KEYSKIPPED: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_KEYSKIPPED"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case HCBT_MINMAX: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_MINMAX"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case HCBT_MOVESIZE: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_MOVESIZE"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case HCBT_QS: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_QS"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case HCBT_SETFOCUS: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_SETFOCUS"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case HCBT_SYSCOMMAND: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_SYSCOMMAND"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + default: + hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "Unknown"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + } + hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), "CBT - nCode: %s, tsk: %ld, %d times ", + szCode, wParam, c++); + if (FAILED(hResult)) + { + // TODO: write error handler + } + hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch); + if (FAILED(hResult)) + { + // TODO: write error handler + } + TextOut(hdc, 2, 75, szBuf, cch); + ReleaseDC(gh_hwndMain, hdc); + + return CallNextHookEx(myhookdata[IDM_CBT].hhook, nCode, wParam, lParam); +} + +/**************************************************************** + WH_MOUSE hook procedure + ****************************************************************/ + +LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + CHAR szBuf[128]; + CHAR szMsg[16]; + HDC hdc; + static int c = 0; + size_t cch; + HRESULT hResult; + + if (nCode < 0) // do not process the message + return CallNextHookEx(myhookdata[IDM_MOUSE].hhook, nCode, + wParam, lParam); + + // Call an application-defined function that converts a message + // constant to a string and copies it to a buffer. + + LookUpTheMessage((PMSG) lParam, szMsg); + + hdc = GetDC(gh_hwndMain); + hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), + "MOUSE - nCode: %d, msg: %s, x: %d, y: %d, %d times ", + nCode, szMsg, LOWORD(lParam), HIWORD(lParam), c++); + if (FAILED(hResult)) + { + // TODO: write error handler + } + hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch); + if (FAILED(hResult)) + { + // TODO: write error handler + } + TextOut(hdc, 2, 95, szBuf, cch); + ReleaseDC(gh_hwndMain, hdc); + + return CallNextHookEx(myhookdata[IDM_MOUSE].hhook, nCode, wParam, lParam); +} + +/**************************************************************** + WH_KEYBOARD hook procedure + ****************************************************************/ + +LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + CHAR szBuf[128]; + HDC hdc; + static int c = 0; + size_t cch; + HRESULT hResult; + + if (nCode < 0) // do not process message + return CallNextHookEx(myhookdata[IDM_KEYBOARD].hhook, nCode, + wParam, lParam); + + hdc = GetDC(gh_hwndMain); + hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), "KEYBOARD - nCode: %d, vk: %d, %d times ", nCode, wParam, c++); + if (FAILED(hResult)) + { + // TODO: write error handler + } + hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch); + if (FAILED(hResult)) + { + // TODO: write error handler + } + TextOut(hdc, 2, 115, szBuf, cch); + ReleaseDC(gh_hwndMain, hdc); + + return CallNextHookEx(myhookdata[IDM_KEYBOARD].hhook, nCode, wParam, lParam); +} + +/**************************************************************** + WH_MSGFILTER hook procedure + ****************************************************************/ + +LRESULT CALLBACK MessageProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + CHAR szBuf[128]; + CHAR szMsg[16]; + CHAR szCode[32]; + HDC hdc; + static int c = 0; + size_t cch; + HRESULT hResult; + + if (nCode < 0) // do not process message + return CallNextHookEx(myhookdata[IDM_MSGFILTER].hhook, nCode, + wParam, lParam); + + switch (nCode) + { + case MSGF_DIALOGBOX: + hResult = StringCchCopy(szCode, 32/sizeof(TCHAR), "MSGF_DIALOGBOX"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case MSGF_MENU: + hResult = StringCchCopy(szCode, 32/sizeof(TCHAR), "MSGF_MENU"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + case MSGF_SCROLLBAR: + hResult = StringCchCopy(szCode, 32/sizeof(TCHAR), "MSGF_SCROLLBAR"); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + + default: + hResult = StringCchPrintf(szCode, 128/sizeof(TCHAR), "Unknown: %d", nCode); + if (FAILED(hResult)) + { + // TODO: write error handler + } + break; + } + + // Call an application-defined function that converts a message + // constant to a string and copies it to a buffer. + + LookUpTheMessage((PMSG) lParam, szMsg); + + hdc = GetDC(gh_hwndMain); + hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), + "MSGFILTER nCode: %s, msg: %s, %d times ", + szCode, szMsg, c++); + if (FAILED(hResult)) + { + // TODO: write error handler + } + hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch); + if (FAILED(hResult)) + { + // TODO: write error handler + } + TextOut(hdc, 2, 135, szBuf, cch); + ReleaseDC(gh_hwndMain, hdc); + + return CallNextHookEx(myhookdata[IDM_MSGFILTER].hhook, nCode, wParam, lParam); +} \ No newline at end of file