From 8f7242900c1658935614bb9906483fe6bece4231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincas=20Mili=C5=ABnas?= Date: Wed, 29 Jun 2011 13:19:38 +0300 Subject: [PATCH 18/20] server+user32: Added GetRawInputData implementation (try 16) --- dlls/user32/input.c | 38 +++++- dlls/user32/tests/input.c | 22 ++-- server/process.c | 5 +- server/process.h | 4 + server/protocol.def | 10 ++ server/queue.c | 16 ++ server/raw_input.c | 334 ++++++++++++++++++++++++++++++++++++++++++++- server/raw_input.h | 9 +- 8 files changed, 421 insertions(+), 17 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 432410d..9ccfcfb 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -722,12 +722,44 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(PRAWINPUTDEVICE pRawInputD */ UINT WINAPI GetRawInputData(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader) { - FIXME("(hRawInput=%p, uiCommand=%d, pData=%p, pcbSize=%p, cbSizeHeader=%d) stub!\n", + BOOL ret; + UINT result; + + TRACE("(hRawInput=%p, uiCommand=%d, pData=%p, pcbSize=%p, cbSizeHeader=%d)\n", hRawInput, uiCommand, pData, pcbSize, cbSizeHeader); - return 0; -} + if (cbSizeHeader != sizeof( RAWINPUTHEADER )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return (UINT)-1; + } + SERVER_START_REQ( get_raw_input_data ) + { + req->handle = wine_server_user_handle( hRawInput ); + req->command = uiCommand; + req->report_size_only = pData == NULL || pcbSize == NULL; + if (pData != NULL && pcbSize != NULL) + wine_server_set_reply( req, pData, *pcbSize ); + ret = !wine_server_call_err( req ); + if ((!ret || pData == NULL) && pcbSize != NULL) + { + *pcbSize = reply->size; + result = 0; + } + else + result = reply->size; + } + SERVER_END_REQ; + + /* Error for an invalid handle is checked before checking if pcbSize is NULL on windows */ + if (ret && pcbSize != NULL) + return result; + else if (ret && pcbSize == NULL) + SetLastError( ERROR_NOACCESS ); + + return (UINT)-1; +} /****************************************************************** * GetRawInputBuffer (USER32.@) diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index d2ac666..3ecaba7 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -2395,33 +2395,33 @@ static void test_get_raw_input_data(void) SetLastError(0xdeadbeef); ret = pGetRawInputData(NULL, 0, NULL, NULL, 0); error = GetLastError(); - todo_wine ok(ret == (UINT)-1, "GetRawInputData returned wrong value: " + ok(ret == (UINT)-1, "GetRawInputData returned wrong value: " "expected (UINT)-1, got %u\n", ret); - todo_wine ok(error == ERROR_INVALID_PARAMETER, "GetRawInputData returned " + ok(error == ERROR_INVALID_PARAMETER, "GetRawInputData returned " "wrong error code: %u\n", error); SetLastError(0xdeadbeef); ret = pGetRawInputData(NULL, 0, NULL, NULL, sizeof(RAWINPUTHEADER)); error = GetLastError(); - todo_wine ok(ret == (UINT)-1, "GetRawInputData returned wrong value: " + ok(ret == (UINT)-1, "GetRawInputData returned wrong value: " "expected (UINT)-1, got %u\n", ret); - todo_wine ok(error == ERROR_INVALID_HANDLE, "GetRawInputData returned " + ok(error == ERROR_INVALID_HANDLE, "GetRawInputData returned " "wrong error code: %u\n", error); SetLastError(0xdeadbeef); ret = pGetRawInputData(NULL, 0, NULL, &count, 1); error = GetLastError(); - todo_wine ok(ret == (UINT)-1, "GetRawInputData returned wrong value: " + ok(ret == (UINT)-1, "GetRawInputData returned wrong value: " "expected (UINT)-1, got %u\n", ret); - todo_wine ok(error == ERROR_INVALID_PARAMETER, "GetRawInputData returned " + ok(error == ERROR_INVALID_PARAMETER, "GetRawInputData returned " "wrong error code: %u\n", error); SetLastError(0xdeadbeef); ret = pGetRawInputData(NULL, 0, NULL, &count, sizeof(RAWINPUTHEADER)); error = GetLastError(); - todo_wine ok(ret == (UINT)-1, "GetRawInputData returned wrong value: " + ok(ret == (UINT)-1, "GetRawInputData returned wrong value: " "expected (UINT)-1, got %u\n", ret); - todo_wine ok(error == ERROR_INVALID_HANDLE, "GetRawInputData returned " + ok(error == ERROR_INVALID_HANDLE, "GetRawInputData returned " "wrong error code: %u\n", error); } @@ -2577,7 +2577,7 @@ static HWND test_get_raw_input_data_simulation_setup(HANDLE hInstance, const cha /* First send input to test raw input buffer */ pSendInput(input_count, input, sizeof(INPUT)); - todo_wine ok(GetQueueStatus(QS_RAWINPUT), "GetQueueStatus returned that the queue was " + ok(GetQueueStatus(QS_RAWINPUT), "GetQueueStatus returned that the queue was " "not marked as containing raw input messages, expected otherwise\n"); size = 0; ret2 = pGetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER)); @@ -2617,7 +2617,7 @@ static HWND test_get_raw_input_data_simulation_setup(HANDLE hInstance, const cha /* Proceed with testing other functionality */ pSendInput(input_count, input, sizeof(INPUT)); - todo_wine ok(GetQueueStatus(QS_RAWINPUT), "GetQueueStatus returned that the queue was " + ok(GetQueueStatus(QS_RAWINPUT), "GetQueueStatus returned that the queue was " "not marked as containing raw input messages, expected otherwise\n"); ret2 = pGetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER)); ok(ret2 == 0, "GetRawInputBuffer returned wrong value: expected 0, got %u\n", ret2); @@ -2637,7 +2637,7 @@ static HWND test_get_raw_input_data_simulation_setup(HANDLE hInstance, const cha } ok(ret != -1, "Error getting window message: %u\n", GetLastError()); - todo_wine ok(wm_input_recieved, "WM_INPUT was not received\n"); + ok(wm_input_recieved, "WM_INPUT was not received\n"); ok(!GetQueueStatus(QS_RAWINPUT), "GetQueueStatus returned that the queue was " "marked as containing raw input messages, expected otherwise\n"); diff --git a/server/process.c b/server/process.c index 96709e8..6b5e348 100644 --- a/server/process.c +++ b/server/process.c @@ -334,11 +334,14 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit process->desktop = 0; process->token = NULL; process->trace_data = 0; + process->raw_input_len = 0; + process->raw_input_index = 0; list_init( &process->thread_list ); list_init( &process->locks ); list_init( &process->classes ); list_init( &process->dlls ); list_init( &process->raw_registered ); + list_init( &process->raw_inputs ); process->start_time = current_time; process->end_time = 0; @@ -421,7 +424,7 @@ static void process_destroy( struct object *obj ) close_process_handles( process ); set_process_startup_state( process, STARTUP_ABORTED ); - release_raw_input( &process->raw_registered ); + release_raw_input( &process->raw_registered, &process->raw_inputs ); if (process->console) release_object( process->console ); if (process->parent) release_object( process->parent ); if (process->msg_fd) release_object( process->msg_fd ); diff --git a/server/process.h b/server/process.h index b1ceded..d4dc9f3 100644 --- a/server/process.h +++ b/server/process.h @@ -22,6 +22,7 @@ #define __WINE_SERVER_PROCESS_H #include "object.h" +#include "raw_input.h" struct atom_table; struct handle_table; @@ -82,6 +83,9 @@ struct process client_ptr_t ldt_copy; /* pointer to LDT copy in client addr space */ unsigned int trace_data; /* opaque data used by the process tracing mechanism */ struct list raw_registered; /* registered raw input devices */ + struct list raw_inputs; /* queued raw inputs */ + unsigned int raw_input_len; /* number of valid raw input event ids */ + unsigned int raw_input_index; /* number of raw input events issued */ }; struct process_snapshot diff --git a/server/protocol.def b/server/protocol.def index 70b3e49..e5162f9 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3415,3 +3415,13 @@ struct raw_input_device_registration #define RAW_INPUT_DEVICE_FLAG_INPUTSINK 0x0080 #define RAW_INPUT_DEVICE_FLAG_EXINPUTSINK 0x0100 #define RAW_INPUT_DEVICE_FLAG_DEVNOTIFY 0x0200 + +/* Get raw input data */ +@REQ(get_raw_input_data) + user_handle_t handle; /* raw input event handle */ + unsigned int command; /* instruction to reply with just the header or the whole data */ + unsigned int report_size_only; /* reply only with the required size to store the data */ +@REPLY + data_size_t size; /* size of the raw input data */ + VARARG(data,bytes); /* RAWINPUTHEADER or RAWINPUT data structure */ +@END diff --git a/server/queue.c b/server/queue.c index 03b0e92..0a1611f 100644 --- a/server/queue.c +++ b/server/queue.c @@ -40,6 +40,7 @@ #include "process.h" #include "request.h" #include "user.h" +#include "raw_input.h" #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE #define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST)) @@ -121,6 +122,7 @@ struct msg_queue unsigned int changed_mask; /* changed wakeup mask */ int paint_count; /* pending paint messages count */ int hotkey_count; /* pending hotkey messages count */ + int rawinput_count; /* pending raw input messages count */ int quit_message; /* is there a pending quit message? */ int exit_code; /* exit code of pending quit message */ int cursor_count; /* per-queue cursor show count */ @@ -281,6 +283,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ queue->changed_mask = 0; queue->paint_count = 0; queue->hotkey_count = 0; + queue->rawinput_count = 0; queue->quit_message = 0; queue->cursor_count = 0; queue->recv_result = NULL; @@ -604,6 +607,8 @@ static void remove_queue_message( struct msg_queue *queue, struct message *msg, clear_queue_bits( queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE ); if (msg->msg == WM_HOTKEY && --queue->hotkey_count == 0) clear_queue_bits( queue, QS_HOTKEY ); + if (msg->msg == WM_INPUT && --queue->rawinput_count == 0) + clear_queue_bits( queue, QS_RAWINPUT ); break; } free_message( msg ); @@ -1952,6 +1957,11 @@ void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lpa set_queue_bits( thread->queue, QS_HOTKEY ); thread->queue->hotkey_count++; } + if (message == WM_INPUT) + { + set_queue_bits( thread->queue, QS_RAWINPUT ); + thread->queue->rawinput_count++; + } } release_object( thread ); } @@ -2195,9 +2205,15 @@ DECL_HANDLER(send_hardware_message) switch (req->input.type) { case INPUT_MOUSE: + queue_mouse_raw_input( req->input.mouse.flags, req->input.mouse.info, + req->input.mouse.data, req->input.mouse.x, req->input.mouse.y, desktop->cursor.x, + desktop->cursor.y, desktop->foreground_input ? desktop->foreground_input->focus : 0 ); reply->wait = queue_mouse_message( desktop, req->win, &req->input, req->flags, sender ); break; case INPUT_KEYBOARD: + queue_keyboard_raw_input( req->input.kbd.flags, req->input.kbd.info, + req->input.kbd.vkey, req->input.kbd.scan, + desktop->foreground_input ? desktop->foreground_input->focus : 0 ); reply->wait = queue_keyboard_message( desktop, req->win, &req->input, req->flags, sender ); break; case INPUT_HARDWARE: diff --git a/server/raw_input.c b/server/raw_input.c index e53c14a..deefaec 100644 --- a/server/raw_input.c +++ b/server/raw_input.c @@ -37,6 +37,8 @@ #include "request.h" #include "user.h" +#define MAX_RAW_INPUT_QUEUE_LENGTH 32 + #define MOUSE_DEVICE_HANDLE ((user_handle_t)0x01) #define KEYBOARD_DEVICE_HANDLE ((user_handle_t)0x02) @@ -53,6 +55,17 @@ struct raw_registration user_handle_t target_window; }; +struct raw_input +{ + struct list entry; + unsigned int handle; + user_handle_t device_handle; + unsigned short input_usage_page; + unsigned short input_usage; + BOOL retrieved; + RAWINPUT raw; +}; + struct raw_device { user_handle_t handle; @@ -78,9 +91,10 @@ static const struct raw_device raw_devices[] = #define NUM_RAW_DEVICES (sizeof( raw_devices ) / sizeof( raw_devices[0] )) /* Release allocated raw input data */ -void release_raw_input( struct list *registrations ) +void release_raw_input( struct list *registrations, struct list *inputs ) { struct raw_registration *registration, *registration2; + struct raw_input *input, *input2; LIST_FOR_EACH_ENTRY_SAFE( registration, registration2, registrations, struct raw_registration, entry ) @@ -88,6 +102,12 @@ void release_raw_input( struct list *registrations ) list_remove( ®istration->entry ); free( registration ); } + + LIST_FOR_EACH_ENTRY_SAFE( input, input2, inputs, struct raw_input, entry ) + { + list_remove( &input->entry ); + free( input ); + } } /* Register or unregister a given raw input device registration */ @@ -133,6 +153,274 @@ static void register_raw_input_device( struct raw_input_device_registration *new list_add_tail( ¤t->process->raw_registered, ®istration->entry ); } +/* Remove a raw input event from the queue */ +static void remove_raw_input( struct raw_input *input ) +{ + list_remove( &input->entry ); + current->process->raw_input_len -= 1; + free( input ); +} + +/* Queue a raw input event */ +static void queue_raw_input( struct raw_input *input, struct raw_registration *registration, + user_handle_t focus ) +{ + user_handle_t target; + struct raw_input *queued, *prev = NULL; + + input->handle = current->process->raw_input_index++; + + /* Prevent unprocessed raw input entries from being queued indefinitely */ + if (current->process->raw_input_len == MAX_RAW_INPUT_QUEUE_LENGTH) + { + struct raw_input *head = LIST_ENTRY( list_head( ¤t->process->raw_inputs ), + struct raw_input, entry ); + remove_raw_input( head ); + } + + /* Select raw input events that come from this device's input subcomponent and release + already processed ones, except for the last one, because it can still be + retrieved multiple times while processing its WIM_INPUT message */ + LIST_FOR_EACH_ENTRY( queued, ¤t->process->raw_inputs, struct raw_input, entry ) + { + /* Scope for the particular device and it's input subcomponent */ + if (queued->device_handle != input->device_handle || + queued->input_usage_page != input->input_usage_page || + queued->input_usage != input->input_usage) + continue; + + if (!queued->retrieved) + break; + + if (prev) + remove_raw_input( prev ); + + prev = queued; + } + + list_add_tail( ¤t->process->raw_inputs, &input->entry ); + current->process->raw_input_len += 1; + + target = registration->target_window ? registration->target_window : focus; + if (target) + post_message( target, WM_INPUT, RIM_INPUT, input->handle ); +} + +/* Find a queued raw input event by its handle id */ +static struct raw_input *find_raw_input_event( unsigned int handle ) +{ + struct raw_input *input; + LIST_FOR_EACH_ENTRY( input, ¤t->process->raw_inputs, struct raw_input, entry ) + { + if (input->handle == handle) + return input; + } + return NULL; +} + +/* Find a raw input registration, that matches given usage page/id */ +static struct raw_registration *find_registered_usage( unsigned short usage_page, + unsigned short usage ) +{ + struct raw_registration *registration, *found = NULL; + LIST_FOR_EACH_ENTRY( registration, ¤t->process->raw_registered, + struct raw_registration, entry ) + { + if (registration->usage_page != usage_page) + continue; + else if (registration->flags & RAW_INPUT_DEVICE_FLAG_EXCLUDE && + registration->usage == usage) + return NULL; + else if (registration->flags & RAW_INPUT_DEVICE_FLAG_PAGEONLY) + found = registration; + else if (registration->usage == usage) + return registration; + } + return found; +} + +/* Determine mouse flags */ +static unsigned int map_mouse_flags( unsigned int flags, unsigned int mouse_data ) +{ + unsigned int result = 0; + if (flags & MOUSEEVENTF_LEFTDOWN) + result |= RI_MOUSE_LEFT_BUTTON_DOWN; + if (flags & MOUSEEVENTF_LEFTUP) + result |= RI_MOUSE_LEFT_BUTTON_UP; + if (flags & MOUSEEVENTF_RIGHTDOWN) + result |= RI_MOUSE_RIGHT_BUTTON_DOWN; + if (flags & MOUSEEVENTF_RIGHTUP) + result |= RI_MOUSE_RIGHT_BUTTON_UP; + if (flags & MOUSEEVENTF_MIDDLEDOWN) + result |= RI_MOUSE_MIDDLE_BUTTON_DOWN; + if (flags & MOUSEEVENTF_MIDDLEUP) + result |= RI_MOUSE_MIDDLE_BUTTON_UP; + if (flags & MOUSEEVENTF_WHEEL) + result |= RI_MOUSE_WHEEL; + if (flags & MOUSEEVENTF_HWHEEL) + result |= RI_MOUSE_HORIZONTAL_WHEEL; + if (flags & MOUSEEVENTF_XDOWN && mouse_data == XBUTTON1) + result |= RI_MOUSE_BUTTON_4_DOWN; + if (flags & MOUSEEVENTF_XUP && mouse_data == XBUTTON1) + result |= RI_MOUSE_BUTTON_4_UP; + if (flags & MOUSEEVENTF_XDOWN && mouse_data == XBUTTON2) + result |= RI_MOUSE_BUTTON_5_DOWN; + if (flags & MOUSEEVENTF_XUP && mouse_data == XBUTTON2) + result |= RI_MOUSE_BUTTON_5_UP; + return result; +} + +/* Queue a mouse raw input event */ +void queue_mouse_raw_input( unsigned int flags, unsigned int info, + unsigned int data, unsigned int input_x, unsigned int input_y, + unsigned int desktop_x, unsigned int desktop_y, user_handle_t focus ) +{ + /* We know the device handle and its input subcomponent usage page/id in advance */ + const user_handle_t device_handle = MOUSE_DEVICE_HANDLE; + const unsigned short input_usage_page = HID_USAGE_PAGE_GENERIC; + const unsigned short input_usage = HID_USAGE_GENERIC_MOUSE; + struct raw_input *input; + + struct raw_registration *registration = find_registered_usage( input_usage_page, input_usage ); + if (!registration || !(input = mem_alloc( sizeof( *input ) ))) + return; + + input->device_handle = device_handle; + input->input_usage_page = input_usage_page; + input->input_usage = input_usage; + input->retrieved = FALSE; + + input->raw.header.dwType = RIM_TYPEMOUSE; + input->raw.header.dwSize = sizeof( RAWINPUTHEADER ) + sizeof( RAWMOUSE ); + input->raw.header.hDevice = (HANDLE)device_handle; + input->raw.header.wParam = RIM_INPUT; + + if (flags & MOUSEEVENTF_MOVE && flags & MOUSEEVENTF_ABSOLUTE) + { + input->raw.data.mouse.lLastX = input_x - desktop_x; + input->raw.data.mouse.lLastY = input_y - desktop_y; + if (flags & ~(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE) && + input_x == desktop_x && input_y == desktop_y) + flags &= ~MOUSEEVENTF_MOVE; + } + else if (flags & MOUSEEVENTF_MOVE) + { + input->raw.data.mouse.lLastX = input_x; + input->raw.data.mouse.lLastY = input_y; + } + else + { + input->raw.data.mouse.lLastX = 0; + input->raw.data.mouse.lLastY = 0; + } + + input->raw.data.mouse.usFlags = MOUSE_MOVE_RELATIVE; + input->raw.data.mouse.usButtonFlags = map_mouse_flags( flags, data ); + if (input->raw.data.mouse.usButtonFlags & (RI_MOUSE_WHEEL | RI_MOUSE_HORIZONTAL_WHEEL)) + input->raw.data.mouse.usButtonData = data; + else + input->raw.data.mouse.usButtonData = 0; + /* ulRawButtons is undocumented and hardware/drivers dependent, + therefore 0 is a valid value */ + input->raw.data.mouse.ulRawButtons = 0; + input->raw.data.mouse.ulExtraInformation = info; + + /* Filter out zero values that come after a scroll wheel event, + so it would be identical to windows */ + if (!input->raw.data.mouse.usButtonFlags && + !input->raw.data.mouse.lLastX && !input->raw.data.mouse.lLastY) + { + free( input ); + return; + } + + queue_raw_input( input, registration, focus ); +} + +/* Determine keyboard flags */ +static unsigned int map_keyboard_flags( unsigned int flags, unsigned int vk_code ) +{ + unsigned int result = 0; + + if (flags & KEYEVENTF_KEYUP) + result |= RI_KEY_BREAK; + else + result |= RI_KEY_MAKE; + + /* The extended keys are placed on the right side + Right shift doesn't have this flag */ + if (flags & KEYEVENTF_EXTENDEDKEY && vk_code != VK_SHIFT && vk_code != VK_RSHIFT) + result |= RI_KEY_E0; + + return result; +} + +/* Determine keyboard virtual key-code */ +static unsigned int map_keyboard_vk_code( unsigned int vk_code ) +{ + switch (vk_code) + { + case VK_LSHIFT: + case VK_RSHIFT: + return VK_SHIFT; + case VK_LCONTROL: + case VK_RCONTROL: + return VK_CONTROL; + case VK_LMENU: + case VK_RMENU: + return VK_MENU; + default: + return vk_code; + } +} + +/* Determine keyboard message code */ +static unsigned int map_keyboard_message_code( unsigned int flags, unsigned int vk_code ) +{ + /* Windows use WM_SYSKEYDOWN only for alt key-press */ + if (!(flags & KEYEVENTF_KEYUP) && (vk_code == VK_MENU || vk_code == VK_LMENU || + vk_code == VK_RMENU)) + return WM_SYSKEYDOWN; + else if (flags & KEYEVENTF_KEYUP) + return WM_KEYUP; + else + return WM_KEYDOWN; +} + +/* Queue a keyboard raw input event */ +void queue_keyboard_raw_input( unsigned int flags, unsigned int info, unsigned int vk_code, + unsigned int scan_code, user_handle_t focus ) +{ + /* We know the device handle and its input subcomponent usage page/id in advance */ + const user_handle_t device_handle = KEYBOARD_DEVICE_HANDLE; + const unsigned short input_usage_page = HID_USAGE_PAGE_GENERIC; + const unsigned short input_usage = HID_USAGE_GENERIC_KEYBOARD; + struct raw_input *input; + + struct raw_registration *registration = find_registered_usage( input_usage_page, input_usage ); + if (!registration || !(input = mem_alloc( sizeof( *input ) ))) + return; + + input->device_handle = device_handle; + input->input_usage_page = input_usage_page; + input->input_usage = input_usage; + input->retrieved = FALSE; + + input->raw.header.dwType = RIM_TYPEKEYBOARD; + input->raw.header.dwSize = sizeof( RAWINPUTHEADER ) + sizeof( RAWKEYBOARD ); + input->raw.header.hDevice = (HANDLE)device_handle; + input->raw.header.wParam = RIM_INPUT; + + input->raw.data.keyboard.MakeCode = scan_code; + input->raw.data.keyboard.Flags = map_keyboard_flags( flags, vk_code ); + input->raw.data.keyboard.Reserved = 0; + input->raw.data.keyboard.VKey = map_keyboard_vk_code( vk_code ); + input->raw.data.keyboard.Message = map_keyboard_message_code( flags, vk_code ); + input->raw.data.keyboard.ExtraInformation = info; + + queue_raw_input( input, registration, focus ); +} + /* Get the raw input device list */ DECL_HANDLER(get_raw_input_device_list) { @@ -270,3 +558,47 @@ DECL_HANDLER(register_raw_input_devices) for (i = 0; i < req->count; i++) register_raw_input_device( ®istrations[i] ); } + +/* Get raw input data */ +DECL_HANDLER(get_raw_input_data) +{ + void *ptr; + struct raw_input *input = find_raw_input_event( req->handle ); + + if (!input) + { + set_error( STATUS_INVALID_HANDLE ); + return; + } + + if (req->command == RID_HEADER) + reply->size = sizeof( RAWINPUTHEADER ); + else if (req->command == RID_INPUT) + reply->size = input->raw.header.dwSize; + else + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + + if (req->report_size_only) + return; + + if (reply->size > get_reply_max_size()) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + return; + } + + ptr = set_reply_data_size( reply->size ); + if (!ptr) + { + set_error( STATUS_NO_MEMORY ); + return; + } + + memcpy( ptr, &input->raw, reply->size ); + + if (req->command == RID_INPUT) + input->retrieved = TRUE; +} diff --git a/server/raw_input.h b/server/raw_input.h index 3c79800..d881585 100644 --- a/server/raw_input.h +++ b/server/raw_input.h @@ -21,8 +21,15 @@ #ifndef __WINE_SERVER_RAW_INPUT_H #define __WINE_SERVER_RAW_INPUT_H +#include "wine/server_protocol.h" #include "wine/list.h" -extern void release_raw_input( struct list *registrations ); +extern void release_raw_input( struct list *registrations, struct list *inputs ); + +extern void queue_mouse_raw_input( unsigned int flags, unsigned int info, + unsigned int data, unsigned int input_x, unsigned int input_y, + unsigned int desktop_x, unsigned int desktop_y, user_handle_t focus ); +extern void queue_keyboard_raw_input( unsigned int flags, unsigned int info, + unsigned int vk_code, unsigned int scan_code, user_handle_t focus ); #endif /* __WINE_SERVER_RAW_INPUT_H */ -- 1.7.3.4