WH_MOUSE_LL The hook is not called for the entered events (mouse_event, SendInput)

My code uses a WH_MOUSE_LL hook to initially suppress all mouse inputs unless a specific value is set for the dwExtraInfo property. The program is also registered for raw input for mouse devices, so that I can determine which device is responsible for the input. When I receive the WM_INPUT message and determine the source, depending on the device, I can just let the event take effect, in which case I recreate it using SendInput (also tried to supplant the mouse_event that was replaced) by providing data in the property dwExtraInfo. The idea is that the hook should see this new attached event, see additional information and not suppress it. Unfortunately, the injected event is never crocheted. The corresponding WM_INPUT message is visible by the window procedure, and SendInput returns 1, so it seems that the event is being generated. I read that the context switches to the thread that the hook set, and that it should have a message loop. I believe that my code corresponds to this qualification (since Application.Run () starts a message loop in a stream - I also tried writing a handwritten message outline in Win32 style). Does anyone have any idea why this is happening and / or how to fix it?

The following code demonstrates the problem. It should work with links to System and System.Windows.Forms.

Main class:

using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Windows.Forms; using Win32; public class LLMH : Form { private static LowLevelMouseProc _proc = HookCallback; private static IntPtr _hookID = IntPtr.Zero; private InputProcessor inputProcessor; private static IntPtr extraInfoPointer; private const int EXTRA_INFO = 1000; public static void Main() { _hookID = SetHook(_proc); LLMH app = new LLMH(); app.inputProcessor = new InputProcessor(); app.RegisterDevice(0x01, 0x02, (int)RawInputDeviceFlag.RIDEV_INPUTSINK); int extraInfo = EXTRA_INFO; LLMH.extraInfoPointer = new IntPtr(extraInfo); Application.Run(); UnhookWindowsHookEx(_hookID); } public void RegisterDevice(ushort usagePage, ushort usage, int flags) { inputProcessor.RegisterDevice(usagePage, usage, flags, this.Handle); } protected override void WndProc(ref Message message) { switch (message.Msg) { case (int)WindowsMessage.WM_INPUT: Console.WriteLine("Received WM_INPUT."); RawInput rawInput = inputProcessor.GetRawInput(ref message); String name = inputProcessor.GetRawInputDeviceName(rawInput); Console.WriteLine("rawInput.extraInfo: {0}", rawInput.mouse.extraInformation); if (rawInput.mouse.extraInformation != EXTRA_INFO) { Console.WriteLine("Creating local mouse event."); //mouse_event( // (int)rawInput.mouse.flags, // rawInput.mouse.lastX, // rawInput.mouse.lastY, // rawInput.mouse.buttonData, // extraInfoPointer); INPUT input = new INPUT(); input.type = (int)RawInputType.MOUSE; input.mkhi.mi.dwFlags = (uint)rawInput.mouse.flags; input.mkhi.mi.dx = rawInput.mouse.lastX; input.mkhi.mi.dy = rawInput.mouse.lastY; input.mkhi.mi.mouseData = rawInput.mouse.buttonData; input.mkhi.mi.dwExtraInfo = extraInfoPointer; Console.WriteLine("Return value of SendInput: {0}", SendInput(1, ref input, Marshal.SizeOf(input))); } base.WndProc(ref message); break; default: base.WndProc(ref message); break; } } private static IntPtr SetHook(LowLevelMouseProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx((int)WindowsHook.WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam); private static IntPtr HookCallback( int nCode, IntPtr wParam, IntPtr lParam) { Console.WriteLine("\nIn hook."); if (nCode >= 0) { MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); if (hookStruct.dwExtraInfo == LLMH.extraInfoPointer) { Console.WriteLine("Extra info matches. hookStruct.dwExtraInfo: {0}", hookStruct.dwExtraInfo); } else { Console.WriteLine("Extra info doesn't match. hookStruct.dwExtraInfo: {0}", hookStruct.dwExtraInfo); return new IntPtr(-1); } } return CallNextHookEx(_hookID, nCode, wParam, lParam); } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("user32.dll", SetLastError = true)] public static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); [DllImport("user32.dll")] public static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, IntPtr dwExtraInfo); } 

Class InputProcessor:

 using System; using System.Runtime.InteropServices; using System.Windows.Forms; using Win32; public class InputProcessor { public RawInput GetRawInput(ref Message message) { uint size = 0; // Call with null pointer to get amount of memory required for buffer. GetRawInputData( message.LParam, (uint)RawInputDeviceCommand.RID_INPUT, IntPtr.Zero, ref size, (uint)Marshal.SizeOf(typeof(RawInputHeader))); IntPtr buffer = Marshal.AllocHGlobal((int)size); if (GetRawInputData( message.LParam, (uint)RawInputDeviceCommand.RID_INPUT, buffer, ref size, (uint)Marshal.SizeOf(typeof(RawInputHeader))) == size) { RawInput input = (RawInput)Marshal.PtrToStructure(buffer, typeof(RawInput)); Marshal.FreeHGlobal(buffer); return input; } else { throw new ApplicationException("Failed to return Raw Input"); } } public String GetRawInputDeviceName(RawInput rawInput) { uint length = 0; // Determine amount of memory to allocate for device name. GetRawInputDeviceInfo( rawInput.header.device, (uint)RawInputDeviceCommand.RIDI_DEVICENAME, IntPtr.Zero, ref length); String deviceName = String.Empty; if (length > 0) { IntPtr data = Marshal.AllocHGlobal((int)length); GetRawInputDeviceInfo(rawInput.header.device, (uint)RawInputDeviceCommand.RIDI_DEVICENAME, data, ref length); deviceName = (String)Marshal.PtrToStringAnsi(data); Marshal.FreeHGlobal(data); } return deviceName; } public void RegisterDevice(ushort usagePage, ushort usage, int flags, IntPtr windowHandle) { RawInputDevice[] inputDevices = new RawInputDevice[1]; inputDevices[0].usagePage = usagePage; inputDevices[0].usage = usage; inputDevices[0].flags = flags; inputDevices[0].windowHandle = windowHandle; if (!RegisterRawInputDevices(inputDevices, (uint)inputDevices.Length, (uint)Marshal.SizeOf(inputDevices[0]))) { throw new ApplicationException("Failed to register raw input devices."); } } [DllImport("user32.dll", SetLastError = true)] public static extern uint GetRawInputDeviceInfo( IntPtr deviceHandle, uint command, IntPtr data, ref uint size); [DllImport("User32.dll")] public static extern bool RegisterRawInputDevices( RawInputDevice[] rawInputDevice, uint numDevices, uint size); [DllImport("User32.dll")] public static extern int GetRawInputData( IntPtr rawInput, uint command, IntPtr data, ref uint size, uint headerSize); [DllImport("user32.dll")] public static extern uint GetRawInputDeviceList( IntPtr rawInputDeviceList, ref uint numDevices, uint size); } 

Additional P / Invoke structures, enumerations, etc.

 using System; using System.Runtime.InteropServices; namespace Win32 { public enum WindowsMessage { WM_NULL = 0x0000, WM_CREATE = 0x0001, WM_DESTROY = 0x0002, WM_MOVE = 0x0003, WM_SIZE = 0x0005, WM_ACTIVATE = 0x0006, WM_SETFOCUS = 0x0007, WM_KILLFOCUS = 0x0008, WM_QUIT = 0x0012, WM_INPUT = 0x00FF, WM_LBUTTONDOWN = 0x0201, WM_LBUTTONUP = 0x0202, WM_MOUSEMOVE = 0x0200, WM_MOUSEWHEEL = 0x020A, WM_RBUTTONDOWN = 0x0204, WM_RBUTTONUP = 0x0205 } public enum WindowsHook { WH_MOUSE_LL = 14 } [StructLayout(LayoutKind.Sequential)] public struct POINT { public int x; public int y; } [StructLayout(LayoutKind.Sequential)] public struct MSLLHOOKSTRUCT { public POINT pt; public uint mouseData; public uint flags; public uint time; public IntPtr dwExtraInfo; } // Raw Input section. [StructLayout(LayoutKind.Sequential)] public struct RawInput { public RawInputHeader header; public RawInputMouse mouse; public RawInputKeyboard keyboard; public RawInputHID hid; } [StructLayout(LayoutKind.Sequential)] public struct RawInputHeader { public RawInputType type; public int size; public IntPtr device; public IntPtr wParam; } [StructLayout(LayoutKind.Sequential)] public struct RawInputMouse { public RawMouseFlags flags; public ushort buttonData; public RawMouseButtons buttonflags; public uint rawButtons; public int lastX; public int lastY; public uint extraInformation; } [StructLayout(LayoutKind.Sequential)] public struct RawInputKeyboard { public ushort makeCode; public ushort flags; public ushort reserved; public ushort virtualKeyCode; public uint message; public ulong extraInformation; } [StructLayout(LayoutKind.Sequential)] public struct RawInputHID { public int size; public int count; public IntPtr data; } public enum RawInputType { MOUSE = 0, KEYBOARD = 1, HID = 2 } [Flags()] public enum RawMouseFlags : ushort { MOVE_RELATIVE = 0, MOVE_ABSOLUTE = 1, VIRTUAL_DESKTOP = 2, ATTRIBUTES_CHANGED = 4 } [Flags()] public enum RawMouseButtons : ushort { None = 0, LeftDown = 0x0001, LeftUp = 0x0002, RightDown = 0x0004, RightUp = 0x0008, MiddleDown = 0x0010, MiddleUp = 0x0020, Button4Down = 0x0040, Button4Up = 0x0080, Button5Down = 0x0100, Button5Up = 0x0200, MouseWheel = 0x0400 } [StructLayout(LayoutKind.Sequential)] public struct RawInputDeviceList { public IntPtr device; public uint type; } [StructLayout(LayoutKind.Sequential)] public struct RawInputDevice { [MarshalAs(UnmanagedType.U2)] public ushort usagePage; [MarshalAs(UnmanagedType.U2)] public ushort usage; [MarshalAs(UnmanagedType.U4)] public int flags; public IntPtr windowHandle; } public enum RawInputDeviceFlag : int { RIDEV_REMOVE = 0x00000001, RIDEV_EXCLUDE = 0x00000010, RIDEV_PAGEONLY = 0x00000020, RIDEV_NOLEGACY = 0x00000030, RIDEV_INPUTSINK = 0x00000100, RIDEV_CAPTUREMOUSE = 0x00000200, RIDEV_NOHOTKEYS = 0x00000200, RIDEV_APPKEYS = 0x00000400, RIDEV_EXMODEMASK = 0x00000F0 } public enum RawInputDeviceCommand : int { RID_INPUT = 0x10000003, RIDI_DEVICENAME = 0x20000007, RIDI_DEVICEINFO = 0x2000000b } public enum HIDUsage : ushort { Pointer = 0x01, Mouse = 0x02, Joystick = 0x04, Gamepad = 0x05, Keyboard = 0x06, Keypad = 0x07, SystemControl = 0x80, X = 0x30, Y = 0x31, Z = 0x32, RelativeX = 0x33, RelativeY = 0x34, RelativeZ = 0x35, Slider = 0x36, Dial = 0x37, Wheel = 0x38, HatSwitch = 0x39, CountedBuffer = 0x3A, ByteCount = 0x3B, MotionWakeup = 0x3C, VX = 0x40, VY = 0x41, VZ = 0x42, VBRX = 0x43, VBRY = 0x44, VBRZ = 0x45, VNO = 0x46, SystemControlPower = 0x81, SystemControlSleep = 0x82, SystemControlWake = 0x83, SystemControlContextMenu = 0x84, SystemControlMainMenu = 0x85, SystemControlApplicationMenu = 0x86, SystemControlHelpMenu = 0x87, SystemControlMenuExit = 0x88, SystemControlMenuSelect = 0x89, SystemControlMenuRight = 0x8A, SystemControlMenuLeft = 0x8B, SystemControlMenuUp = 0x8C, SystemControlMenuDown = 0x8D, KeyboardNoEvent = 0x00, KeyboardRollover = 0x01, KeyboardPostFail = 0x02, KeyboardUndefined = 0x03, KeyboardaA = 0x04, KeyboardzZ = 0x1D, Keyboard1 = 0x1E, Keyboard0 = 0x27, KeyboardLeftControl = 0xE0, KeyboardLeftShift = 0xE1, KeyboardLeftALT = 0xE2, KeyboardLeftGUI = 0xE3, KeyboardRightControl = 0xE4, KeyboardRightShift = 0xE5, KeyboardRightALT = 0xE6, KeyboardRightGUI = 0xE7, KeyboardScrollLock = 0x47, KeyboardNumLock = 0x53, KeyboardCapsLock = 0x39, KeyboardF1 = 0x3A, KeyboardF12 = 0x45, KeyboardReturn = 0x28, KeyboardEscape = 0x29, KeyboardDelete = 0x2A, KeyboardPrintScreen = 0x46, LEDNumLock = 0x01, LEDCapsLock = 0x02, LEDScrollLock = 0x03, LEDCompose = 0x04, LEDKana = 0x05, LEDPower = 0x06, LEDShift = 0x07, LEDDoNotDisturb = 0x08, LEDMute = 0x09, LEDToneEnable = 0x0A, LEDHighCutFilter = 0x0B, LEDLowCutFilter = 0x0C, LEDEqualizerEnable = 0x0D, LEDSoundFieldOn = 0x0E, LEDSurroundFieldOn = 0x0F, LEDRepeat = 0x10, LEDStereo = 0x11, LEDSamplingRateDirect = 0x12, LEDSpinning = 0x13, LEDCAV = 0x14, LEDCLV = 0x15, LEDRecordingFormatDet = 0x16, LEDOffHook = 0x17, LEDRing = 0x18, LEDMessageWaiting = 0x19, LEDDataMode = 0x1A, LEDBatteryOperation = 0x1B, LEDBatteryOK = 0x1C, LEDBatteryLow = 0x1D, LEDSpeaker = 0x1E, LEDHeadset = 0x1F, LEDHold = 0x20, LEDMicrophone = 0x21, LEDCoverage = 0x22, LEDNightMode = 0x23, LEDSendCalls = 0x24, LEDCallPickup = 0x25, LEDConference = 0x26, LEDStandBy = 0x27, LEDCameraOn = 0x28, LEDCameraOff = 0x29, LEDOnLine = 0x2A, LEDOffLine = 0x2B, LEDBusy = 0x2C, LEDReady = 0x2D, LEDPaperOut = 0x2E, LEDPaperJam = 0x2F, LEDRemote = 0x30, LEDForward = 0x31, LEDReverse = 0x32, LEDStop = 0x33, LEDRewind = 0x34, LEDFastForward = 0x35, LEDPlay = 0x36, LEDPause = 0x37, LEDRecord = 0x38, LEDError = 0x39, LEDSelectedIndicator = 0x3A, LEDInUseIndicator = 0x3B, LEDMultiModeIndicator = 0x3C, LEDIndicatorOn = 0x3D, LEDIndicatorFlash = 0x3E, LEDIndicatorSlowBlink = 0x3F, LEDIndicatorFastBlink = 0x40, LEDIndicatorOff = 0x41, LEDFlashOnTime = 0x42, LEDSlowBlinkOnTime = 0x43, LEDSlowBlinkOffTime = 0x44, LEDFastBlinkOnTime = 0x45, LEDFastBlinkOffTime = 0x46, LEDIndicatorColor = 0x47, LEDRed = 0x48, LEDGreen = 0x49, LEDAmber = 0x4A, LEDGenericIndicator = 0x3B, TelephonyPhone = 0x01, TelephonyAnsweringMachine = 0x02, TelephonyMessageControls = 0x03, TelephonyHandset = 0x04, TelephonyHeadset = 0x05, TelephonyKeypad = 0x06, TelephonyProgrammableButton = 0x07, SimulationRudder = 0xBA, SimulationThrottle = 0xBB } public enum HIDUsagePage : ushort { Undefined = 0x00, Generic = 0x01, Simulation = 0x02, VR = 0x03, Sport = 0x04, Game = 0x05, Keyboard = 0x07, LED = 0x08, Button = 0x09, Ordinal = 0x0A, Telephony = 0x0B, Consumer = 0x0C, Digitizer = 0x0D, PID = 0x0F, Unicode = 0x10, AlphaNumeric = 0x14, Medical = 0x40, MonitorPage0 = 0x80, MonitorPage1 = 0x81, MonitorPage2 = 0x82, MonitorPage3 = 0x83, PowerPage0 = 0x84, PowerPage1 = 0x85, PowerPage2 = 0x86, PowerPage3 = 0x87, BarCode = 0x8C, Scale = 0x8D, MSR = 0x8E } // SendInput section. [StructLayout(LayoutKind.Sequential)] public struct MOUSEINPUT { public int dx; public int dy; public uint mouseData; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] public struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] public struct HARDWAREINPUT { public int uMsg; public short wParamL; public short wParamH; } [StructLayout(LayoutKind.Explicit)] public struct MOUSEKEYBDHARDWAREINPUT { [FieldOffset(0)] public MOUSEINPUT mi; [FieldOffset(0)] public KEYBDINPUT ki; [FieldOffset(0)] public HARDWAREINPUT hi; } [StructLayout(LayoutKind.Sequential)] public struct INPUT { public int type; public MOUSEKEYBDHARDWAREINPUT mkhi; } 

}

Program output after one WM_LBUTTONDOWN event:

 In hook. Extra info doesn't match. hookStruct.dwExtraInfo: 0 Received WM_INPUT. rawInput.extraInfo: 0 Creating local mouse event. Return value of SendInput: 1 Received WM_INPUT. rawInput.extraInfo: 1000 
+4
source share
1 answer

Have you tried SendMessage (this.Handle, WM _...?

-one
source

Source: https://habr.com/ru/post/1299914/


All Articles