When INPUT type is INPUT_HARDWARE and hi.uMsg is WM_INPUT_DEVICE_CHANGE, the RAWINPUT structure usage is a non-standard extension for Wine internal usage:
* header.wParam contains the message GIDC_ARRIVAL / GIDC_REMOVAL wparam,
* hid.bRawData contains two words, which are the HID device UsagePage and Usage words, instead of a real HID report.
This will let us use the same entry point and structures to send device notifications as for the HID reports in the future (which will be sent with INPUT_HARDWARE type / WM_INPUT uMsg instead).
This currently does nothing, because the INPUT_HARDWARE messages are currently dropped, and because winedevice.exe desktop is different from the default desktop.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/Makefile.in | 2 +- dlls/hidclass.sys/pnp.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/dlls/hidclass.sys/Makefile.in b/dlls/hidclass.sys/Makefile.in index 4b1e9338eb4..09281c118b4 100644 --- a/dlls/hidclass.sys/Makefile.in +++ b/dlls/hidclass.sys/Makefile.in @@ -1,6 +1,6 @@ MODULE = hidclass.sys IMPORTLIB = hidclass -IMPORTS = hal ntoskrnl +IMPORTS = hal ntoskrnl user32
EXTRADLLFLAGS = -mno-cygwin
diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index 4490f1eba23..b5862a01593 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -30,6 +30,7 @@ #include "ddk/hidtypes.h" #include "ddk/wdm.h" #include "regstr.h" +#include "winuser.h" #include "wine/debug.h" #include "wine/asm.h" #include "wine/list.h" @@ -103,6 +104,30 @@ static UINT32 alloc_rawinput_handle(void) return InterlockedIncrement(&counter); }
+/* make sure bRawData can hold UsagePage and Usage without requiring additional allocation */ +C_ASSERT(offsetof(RAWINPUT, data.hid.bRawData[2 * sizeof(USAGE)]) < sizeof(RAWINPUT)); + +static void send_wm_input_device_change(BASE_DEVICE_EXTENSION *ext, LPARAM param) +{ + RAWINPUT rawinput; + INPUT input; + + rawinput.header.dwType = RIM_TYPEHID; + rawinput.header.dwSize = offsetof(RAWINPUT, data.hid.bRawData[2 * sizeof(USAGE)]); + rawinput.header.hDevice = ULongToHandle(ext->u.pdo.rawinput_handle); + rawinput.header.wParam = param; + rawinput.data.hid.dwCount = 0; + rawinput.data.hid.dwSizeHid = 0; + ((USAGE *)rawinput.data.hid.bRawData)[0] = ext->u.pdo.preparsed_data->caps.UsagePage; + ((USAGE *)rawinput.data.hid.bRawData)[1] = ext->u.pdo.preparsed_data->caps.Usage; + + input.type = INPUT_HARDWARE; + input.u.hi.uMsg = WM_INPUT_DEVICE_CHANGE; + input.u.hi.wParamH = 0; + input.u.hi.wParamL = 0; + __wine_send_input(0, &input, &rawinput); +} + static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *bus_pdo) { WCHAR device_id[MAX_DEVICE_ID_LEN], instance_id[MAX_DEVICE_ID_LEN]; @@ -262,6 +287,8 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) sizeof(HID_XFER_PACKET) + pdo_ext->u.pdo.preparsed_data->caps.InputReportByteLength);
HID_StartDeviceThread(child_pdo); + + send_wm_input_device_change(pdo_ext, GIDC_ARRIVAL); }
static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) @@ -433,6 +460,8 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp) { IRP *queued_irp;
+ send_wm_input_device_change(ext, GIDC_REMOVAL); + IoSetDeviceInterfaceState(&ext->u.pdo.link_name, FALSE); if (ext->u.pdo.is_mouse) IoSetDeviceInterfaceState(&ext->u.pdo.mouse_link_name, FALSE);
When msg is WM_INPUT_DEVICE_CHANGE.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/protocol.def | 39 +++++++++++++++++++++------------------ server/trace.c | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+), 18 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 9361933d47c..6263f7a544e 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -278,30 +278,32 @@ struct hw_msg_source unsigned int origin; /* source origin (IMO_* values) */ };
+union rawinput +{ + int type; + struct + { + int type; /* RIM_TYPEKEYBOARD */ + unsigned int message; /* message generated by this rawinput event */ + unsigned short vkey; /* virtual key code */ + unsigned short scan; /* scan code */ + } kbd; + struct + { + int type; /* RIM_TYPEMOUSE */ + int x; /* x coordinate */ + int y; /* y coordinate */ + unsigned int data; /* mouse data */ + } mouse; +}; + struct hardware_msg_data { lparam_t info; /* extra info */ unsigned int hw_id; /* unique id */ unsigned int flags; /* hook flags */ struct hw_msg_source source; /* message source */ - union - { - int type; - struct - { - int type; /* RIM_TYPEKEYBOARD */ - unsigned int message; /* message generated by this rawinput event */ - unsigned short vkey; /* virtual key code */ - unsigned short scan; /* scan code */ - } kbd; - struct - { - int type; /* RIM_TYPEMOUSE */ - int x; /* x coordinate */ - int y; /* y coordinate */ - unsigned int data; /* mouse data */ - } mouse; - } rawinput; + union rawinput rawinput; /* rawinput message data */ };
struct callback_msg_data @@ -346,6 +348,7 @@ typedef union int type; /* INPUT_HARDWARE */ unsigned int msg; /* message code */ lparam_t lparam; /* message param */ + union rawinput rawinput;/* rawinput message data */ } hw; } hw_input_t;
diff --git a/server/trace.c b/server/trace.c index 645c183a52f..cddeaa2d769 100644 --- a/server/trace.c +++ b/server/trace.c @@ -394,6 +394,24 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data ) } }
+static void dump_rawinput( const char *prefix, const union rawinput *rawinput ) +{ + switch (rawinput->type) + { + case RIM_TYPEMOUSE: + fprintf( stderr, "%s{type=MOUSE,x=%d,y=%d,data=%08x}", prefix, rawinput->mouse.x, + rawinput->mouse.y, rawinput->mouse.data ); + break; + case RIM_TYPEKEYBOARD: + fprintf( stderr, "%s{type=KEYBOARD,message=%04x,vkey=%04hx,scan=%04hx}", prefix, + rawinput->kbd.message, rawinput->kbd.vkey, rawinput->kbd.scan ); + break; + default: + fprintf( stderr, "%s{type=%04x}", prefix, rawinput->type ); + break; + } +} + static void dump_hw_input( const char *prefix, const hw_input_t *input ) { switch (input->type) @@ -414,6 +432,11 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input ) case INPUT_HARDWARE: fprintf( stderr, "%s{type=HARDWARE,msg=%04x", prefix, input->hw.msg ); dump_uint64( ",lparam=", &input->hw.lparam ); + switch (input->hw.msg) + { + case WM_INPUT_DEVICE_CHANGE: + dump_rawinput( ",rawinput=", &input->hw.rawinput ); + } fputc( '}', stderr ); break; default:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/protocol.def | 8 ++++++++ server/trace.c | 5 +++++ 2 files changed, 13 insertions(+)
diff --git a/server/protocol.def b/server/protocol.def index 6263f7a544e..813b0dc7374 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -295,6 +295,14 @@ union rawinput int y; /* y coordinate */ unsigned int data; /* mouse data */ } mouse; + struct + { + int type; /* RIM_TYPEHID */ + unsigned int device; /* rawinput device index */ + unsigned int param; /* rawinput message param */ + unsigned short usage_page;/* HID usage page */ + unsigned short usage; /* HID usage */ + } hid; };
struct hardware_msg_data diff --git a/server/trace.c b/server/trace.c index cddeaa2d769..39178b8434c 100644 --- a/server/trace.c +++ b/server/trace.c @@ -406,6 +406,11 @@ static void dump_rawinput( const char *prefix, const union rawinput *rawinput ) fprintf( stderr, "%s{type=KEYBOARD,message=%04x,vkey=%04hx,scan=%04hx}", prefix, rawinput->kbd.message, rawinput->kbd.vkey, rawinput->kbd.scan ); break; + case RIM_TYPEHID: + fprintf( stderr, "%s{type=HID,device=%04x,param=%04x,page=%04hx,usage=%04hx}", + prefix, rawinput->hid.device, rawinput->hid.param, rawinput->hid.usage_page, + rawinput->hid.usage ); + break; default: fprintf( stderr, "%s{type=%04x}", prefix, rawinput->type ); break;
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/message.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c index f87ef9fb3af..148b35f8caf 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -35,6 +35,7 @@ #include "dbt.h" #include "dde.h" #include "imm.h" +#include "hidusage.h" #include "ddk/imm.h" #include "wine/server.h" #include "user_private.h" @@ -3233,6 +3234,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r struct send_message_info info; int prev_x, prev_y, new_x, new_y; INT counter = global_key_state_counter; + USAGE hid_usage_page, hid_usage; NTSTATUS ret; BOOL wait;
@@ -3242,6 +3244,15 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r info.flags = 0; info.timeout = 0;
+ if (input->type == INPUT_HARDWARE && rawinput->header.dwType == RIM_TYPEHID) + { + if (input->u.hi.uMsg == WM_INPUT_DEVICE_CHANGE) + { + hid_usage_page = ((USAGE *)rawinput->data.hid.bRawData)[0]; + hid_usage = ((USAGE *)rawinput->data.hid.bRawData)[1]; + } + } + SERVER_START_REQ( send_hardware_message ) { req->win = wine_server_user_handle( hwnd ); @@ -3267,6 +3278,24 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r case INPUT_HARDWARE: req->input.hw.msg = input->u.hi.uMsg; req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH ); + switch (input->u.hi.uMsg) + { + case WM_INPUT_DEVICE_CHANGE: + req->input.hw.rawinput.type = rawinput->header.dwType; + switch (rawinput->header.dwType) + { + case RIM_TYPEHID: + assert( rawinput->data.hid.dwCount <= 1 ); + req->input.hw.rawinput.hid.device = HandleToUlong( rawinput->header.hDevice ); + req->input.hw.rawinput.hid.param = rawinput->header.wParam; + req->input.hw.rawinput.hid.usage_page = hid_usage_page; + req->input.hw.rawinput.hid.usage = hid_usage; + break; + default: + assert( 0 ); + break; + } + } break; } if (key_state_info) wine_server_set_reply( req, key_state_info->state,