From b0a4828158be76c439db0b74274aaa445207437c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincas=20Mili=C5=ABnas?= Date: Sun, 26 Jun 2011 23:43:32 +0300 Subject: [PATCH 19/20] server+user32: Added GetRawInputBuffer implementation (try 16) --- dlls/user32/input.c | 29 ++++++++++++++++- dlls/user32/tests/input.c | 23 +++++++------- server/protocol.def | 9 +++++ server/queue.c | 46 ++++++++++++++++++++++++++++ server/raw_input.c | 73 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+), 14 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 9ccfcfb..bbef25f 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -766,9 +766,34 @@ UINT WINAPI GetRawInputData(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, P */ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader) { - FIXME("(pData=%p, pcbSize=%p, cbSizeHeader=%d) stub!\n", pData, pcbSize, cbSizeHeader); + BOOL ret; + UINT result; + + TRACE("(pData=%p, pcbSize=%p, cbSizeHeader=%d)\n", pData, pcbSize, cbSizeHeader); + + if (pcbSize == NULL || cbSizeHeader != sizeof( RAWINPUTHEADER )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return (UINT)-1; + } + + SERVER_START_REQ( get_raw_input_buffer ) + { + req->report_size_only = pData == NULL; + if (pData != NULL) + wine_server_set_reply( req, pData, *pcbSize ); + ret = !wine_server_call_err( req ); + if (!ret || pData == NULL) + { + *pcbSize = reply->minimum_size; + result = 0; + } + else + result = reply->count; + } + SERVER_END_REQ; - return 0; + return ret ? result : (UINT)-1; } diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 3ecaba7..e1ce96f 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -2439,31 +2439,31 @@ static void test_get_raw_input_buffer(void) SetLastError(0xdeadbeef); ret = pGetRawInputBuffer(NULL, NULL, 0); error = GetLastError(); - todo_wine ok(ret == (UINT)-1, "GetRawInputBuffer returned wrong value: " + ok(ret == (UINT)-1, "GetRawInputBuffer returned wrong value: " "expected (UINT)-1, got %u\n", ret); - todo_wine ok(error == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned " + ok(error == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned " "wrong error code: %u\n", error); SetLastError(0xdeadbeef); ret = pGetRawInputBuffer(NULL, NULL, sizeof(RAWINPUTHEADER)); error = GetLastError(); - todo_wine ok(ret == (UINT)-1, "GetRawInputBuffer returned wrong value: " + ok(ret == (UINT)-1, "GetRawInputBuffer returned wrong value: " "expected (UINT)-1, got %u\n", ret); - todo_wine ok(error == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned " + ok(error == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned " "wrong error code: %u\n", error); SetLastError(0xdeadbeef); ret = pGetRawInputBuffer(NULL, &size, 1); error = GetLastError(); - todo_wine ok(ret == (UINT)-1, "GetRawInputBuffer returned wrong value: " + ok(ret == (UINT)-1, "GetRawInputBuffer returned wrong value: " "expected (UINT)-1, got %u\n", ret); - todo_wine ok(error == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned " + ok(error == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned " "wrong error code: %u\n", error); size = 0xdeadbeef; ret = pGetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER)); ok(ret == 0, "GetRawInputBuffer returned wrong value: expected 0, got %u\n", ret); - todo_wine ok(size == 0, "GetRawInputBuffer returned wrong minimal buffer size: " + ok(size == 0, "GetRawInputBuffer returned wrong minimal buffer size: " "expected 0, got %u\n", size); } @@ -2571,7 +2571,7 @@ static HWND test_get_raw_input_data_simulation_setup(HANDLE hInstance, const cha size = 0xdeadbeef; ret2 = pGetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER)); ok(ret2 == 0, "GetRawInputBuffer returned wrong value: expected 0, got %u\n", ret2); - todo_wine ok(size == 0, "GetRawInputBuffer returned incorrect minimum buffer size: " + ok(size == 0, "GetRawInputBuffer returned incorrect minimum buffer size: " "expected 0, got %u\n", size); /* First send input to test raw input buffer */ @@ -2582,7 +2582,7 @@ static HWND test_get_raw_input_data_simulation_setup(HANDLE hInstance, const cha size = 0; ret2 = pGetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER)); ok(ret2 == 0, "GetRawInputBuffer returned wrong value: expected 0, got %u\n", ret2); - todo_wine ok(size > 0, "GetRawInputBuffer returned incorrect minimum buffer size: " + ok(size > 0, "GetRawInputBuffer returned incorrect minimum buffer size: " "expected x > 0, got %u\n", size); /* Size variable is the size of a single entry of what GetRawInputBuffer will return, @@ -2593,8 +2593,7 @@ static HWND test_get_raw_input_data_simulation_setup(HANDLE hInstance, const cha if (raw) { ret3 = pGetRawInputBuffer(raw, &size, sizeof(RAWINPUTHEADER)); - todo_wine ok(ret3 > 0 && ret3 != (UINT)-1, - "GetRawInputBuffer failed to read raw input buffer\n"); + ok(ret3 > 0 && ret3 != (UINT)-1, "GetRawInputBuffer failed to read raw input buffer\n"); for (i = 0, raw2 = raw; ret3 != (UINT)-1 && i < ret3; i++) { ok(raw2->header.dwType == RIM_TYPEMOUSE || raw2->header.dwType == RIM_TYPEKEYBOARD, @@ -2621,7 +2620,7 @@ static HWND test_get_raw_input_data_simulation_setup(HANDLE hInstance, const cha "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); - todo_wine ok(size > 0, "GetRawInputBuffer returned incorrect minimum buffer size: " + ok(size > 0, "GetRawInputBuffer returned incorrect minimum buffer size: " "expected x > 0, got %u\n", size); /* Give half a second of running time for each test to be sure all messages are processed */ diff --git a/server/protocol.def b/server/protocol.def index e5162f9..b94a869 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3425,3 +3425,12 @@ struct raw_input_device_registration data_size_t size; /* size of the raw input data */ VARARG(data,bytes); /* RAWINPUTHEADER or RAWINPUT data structure */ @END + +/* Get buffered raw input data */ +@REQ(get_raw_input_buffer) + unsigned int report_size_only; /* reply only with the minimum size to get the first entry */ +@REPLY + unsigned int count; /* count of raw input events returned */ + data_size_t minimum_size; /* minimum buffer size to retrieve a buffered entry */ + VARARG(data,bytes); /* RAWINPUT data structures */ +@END diff --git a/server/queue.c b/server/queue.c index 0a1611f..f1b7e03 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2024,6 +2024,52 @@ void free_hotkeys( struct desktop *desktop, user_handle_t window ) } +/* Get the count and handles of queued raw input messages */ +BOOL get_queued_raw_input_message_handles( lparam_t **handles, unsigned int *count ) +{ + struct msg_queue *queue = get_current_queue(); + struct message *msg; + unsigned int index = 0; + + if (!queue->rawinput_count) + { + *handles = NULL; + *count = 0; + return TRUE; + } + + *handles = mem_alloc( queue->rawinput_count * sizeof( lparam_t ) ); + if (!*handles) + return FALSE; + + *count = queue->rawinput_count; + + LIST_FOR_EACH_ENTRY( msg, &queue->msg_list[POST_MESSAGE], struct message, entry ) + { + if (msg->msg == WM_INPUT) + (*handles)[index++] = msg->lparam; + } + + return TRUE; +} + +/* Remove given amount of raw input messages */ +void dequeue_raw_input_messages( unsigned int count ) +{ + struct msg_queue *queue = get_current_queue(); + struct message *msg, *msg2; + + LIST_FOR_EACH_ENTRY_SAFE( msg, msg2, &queue->msg_list[POST_MESSAGE], struct message, entry ) + { + if (msg->msg != WM_INPUT) + continue; + if (!count--) + break; + remove_queue_message( queue, msg, POST_MESSAGE ); + } +} + + /* check if the thread owning the window is hung */ DECL_HANDLER(is_window_hung) { diff --git a/server/raw_input.c b/server/raw_input.c index deefaec..6fd0d82 100644 --- a/server/raw_input.c +++ b/server/raw_input.c @@ -46,6 +46,9 @@ #define HID_USAGE_GENERIC_MOUSE ((unsigned short)0x02) #define HID_USAGE_GENERIC_KEYBOARD ((unsigned short)0x06) +extern BOOL get_queued_raw_input_message_handles( lparam_t **handles, unsigned int *count ); +extern void dequeue_raw_input_messages( unsigned int count ); + struct raw_registration { struct list entry; @@ -602,3 +605,73 @@ DECL_HANDLER(get_raw_input_data) if (req->command == RID_INPUT) input->retrieved = TRUE; } + +/* Get buffered raw input data */ +DECL_HANDLER(get_raw_input_buffer) +{ + unsigned int i, count, written_count = 0, written_size = 0; + lparam_t *handles; + RAWINPUT *result = NULL; + + reply->count = 0; + reply->minimum_size = 0; + + if (!get_queued_raw_input_message_handles( &handles, &count )) + { + set_error( STATUS_NO_MEMORY ); + return; + } + if (!count) + return; + + if (!req->report_size_only) + { + result = set_reply_data_size( get_reply_max_size() ); + if (!result) + { + free( handles ); + set_error( STATUS_NO_MEMORY ); + return; + } + } + + for (i = 0; i < count; i++) + { + struct raw_input *input = find_raw_input_event( handles[i] ); + + if (!input) + continue; + + if (!reply->minimum_size) + reply->minimum_size = input->raw.header.dwSize; + + if (written_size + input->raw.header.dwSize > get_reply_max_size() || + req->report_size_only) + break; + + memcpy( result, &input->raw, input->raw.header.dwSize ); + + written_count += 1; + written_size += input->raw.header.dwSize; + result = NEXTRAWINPUTBLOCK( result ); + + remove_raw_input( input ); + } + + free( handles ); + + if (req->report_size_only) + return; + + /* Windows needs the buffer to be at least 1 byte larger then + the minimum needed space */ + if (reply->minimum_size >= get_reply_max_size() || !written_count) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + return; + } + + reply->count = written_count; + + dequeue_raw_input_messages( written_count ); +} -- 1.7.3.4