From: "Vincas Miliƫnas" Subject: [PATCH 3/3] user32: Added client-side raw input function implementations (try 6) Message-Id: <4E017243.9010000@gmail.com> Date: Wed, 22 Jun 2011 07:40:35 +0300 (see the message in the first part of the patch) --- dlls/user32/input.c | 402 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 379 insertions(+), 23 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 335be1f..653dca9 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -476,68 +476,385 @@ BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO plii) */ UINT WINAPI GetRawInputDeviceList(PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT puiNumDevices, UINT cbSize) { - FIXME("(pRawInputDeviceList=%p, puiNumDevices=%p, cbSize=%d) stub!\n", pRawInputDeviceList, puiNumDevices, cbSize); + BOOL ret = FALSE; + UINT result; - if(pRawInputDeviceList) - memset(pRawInputDeviceList, 0, sizeof *pRawInputDeviceList); - *puiNumDevices = 0; - return 0; + TRACE("(pRawInputDeviceList=%p, puiNumDevices=%p, cbSize=%d)\n", pRawInputDeviceList, puiNumDevices, cbSize); + + if (cbSize != sizeof( RAWINPUTDEVICELIST )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return (UINT)-1; + } + if (puiNumDevices == NULL) + { + SetLastError( ERROR_NOACCESS ); + return (UINT)-1; + } + + SERVER_START_REQ( get_raw_input_device_list ) + { + req->report_size_only = pRawInputDeviceList == NULL; + if (pRawInputDeviceList != NULL) + wine_server_set_reply( req, pRawInputDeviceList, *puiNumDevices * sizeof( RAWINPUTDEVICELIST ) ); + ret = !wine_server_call_err( req ); + if (pRawInputDeviceList == NULL) + { + *puiNumDevices = reply->num_devices; + result = 0; + } + else + { + result = reply->num_devices; + } + } + SERVER_END_REQ; + + return ret ? result : (UINT)-1; } +#define MOUSE_USAGE_PAGE 0x01 +#define MOUSE_USAGE_ID 0x02 +#define KEYBOARD_USAGE_PAGE 0x01 +#define KEYBOARD_USAGE_ID 0x06 /****************************************************************** * RegisterRawInputDevices (USER32.@) */ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) { - FIXME("(pRawInputDevices=%p, uiNumDevices=%d, cbSize=%d) stub!\n", pRawInputDevices, uiNumDevices, cbSize); + BOOL ret, result = TRUE; + UINT i; - return TRUE; -} + TRACE("(pRawInputDevices=%p, uiNumDevices=%d, cbSize=%d)\n", pRawInputDevices, uiNumDevices, cbSize); + + if (pRawInputDevices == NULL || uiNumDevices == 0 || cbSize != sizeof( RAWINPUTDEVICE )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + for (i = 0; i < uiNumDevices; i += 1) + { + RAWINPUTDEVICE *device = &pRawInputDevices[i]; + BOOL is_mouse = device->usUsagePage == MOUSE_USAGE_PAGE && device->usUsage == MOUSE_USAGE_ID; + BOOL is_keyboard = device->usUsagePage == KEYBOARD_USAGE_PAGE && device->usUsage == KEYBOARD_USAGE_ID; + UINT flags = device->dwFlags; + + if (device->usUsagePage == 0) + { + SetLastError( ERROR_INVALID_PARAMETER ); + result = FALSE; + break; + } + + if (flags & RIDEV_REMOVE) + { + if (device->hwndTarget != NULL) + { + SetLastError( ERROR_INVALID_PARAMETER ); + result = FALSE; + break; + } + + SERVER_START_REQ( unregister_raw_input_device ) + { + req->usage_page = device->usUsagePage; + req->usage = device->usUsage; + ret = !wine_server_call_err( req ); + } + SERVER_END_REQ; + + if (!ret) + { + result = FALSE; + break; + } + + continue; + } + + if (flags & RIDEV_PAGEONLY && device->usUsage == 0) + { + FIXME("RIDEV_PAGEONLY support is not implemented\n"); + if (flags & RIDEV_EXCLUDE) + { + FIXME("RIDEV_EXCLUDE support is not implemented\n"); + if (device->hwndTarget == NULL) + { + SetLastError( ERROR_INVALID_PARAMETER ); + result = FALSE; + break; + } + } + /* Prevent from being confused with RIDEV_NOLEGACY, because + RIDEV_NOLEGACY is identical to RIDEV_PAGEONLY | RIDEV_EXCLUDE */ + flags &= ~RIDEV_NOLEGACY; + } + + if (flags & RIDEV_NOHOTKEYS && is_keyboard) + { + FIXME("RIDEV_NOHOTKEYS support is not implemented\n"); + /* Prevent from being confused with RIDEV_CAPTUREMOUSE */ + flags &= ~RIDEV_NOHOTKEYS; + } + + if (flags & RIDEV_NOLEGACY && !is_mouse && !is_keyboard) + { + SetLastError( ERROR_INVALID_FLAGS ); + result = FALSE; + break; + } + else if (flags & RIDEV_NOLEGACY) + { + FIXME("RIDEV_NOLEGACY support is not implemented\n"); + + if (flags & RIDEV_CAPTUREMOUSE && is_mouse) + { + FIXME("RIDEV_CAPTUREMOUSE support is not implemented\n"); + if (device->hwndTarget == NULL) + { + SetLastError( ERROR_INVALID_FLAGS ); + result = FALSE; + break; + } + } + else if (flags & RIDEV_CAPTUREMOUSE && is_keyboard) + { + SetLastError( ERROR_INVALID_FLAGS ); + result = FALSE; + break; + } + + if (flags & RIDEV_APPKEYS && is_keyboard) + { + FIXME("RIDEV_APPKEYS support is not implemented\n"); + } + else if (flags & RIDEV_APPKEYS && is_mouse) + { + SetLastError( ERROR_INVALID_FLAGS ); + result = FALSE; + break; + } + } + else if (flags & RIDEV_CAPTUREMOUSE || flags & RIDEV_APPKEYS) + { + SetLastError( ERROR_INVALID_FLAGS ); + result = FALSE; + break; + } + + if (flags & RIDEV_INPUTSINK) + { + FIXME("RIDEV_INPUTSINK support is not implemented\n"); + if (device->hwndTarget == NULL) + { + SetLastError( ERROR_INVALID_PARAMETER ); + result = FALSE; + break; + } + } + + if (flags & RIDEV_EXINPUTSINK) + { + FIXME("RIDEV_EXINPUTSINK support is not implemented\n"); + } + + if (flags & RIDEV_DEVNOTIFY) + { + FIXME("RIDEV_DEVNOTIFY support is not implemented\n"); + } + + SERVER_START_REQ( register_raw_input_device ) + { + req->usage_page = device->usUsagePage; + req->usage = device->usUsage; + req->flags = device->dwFlags; + req->target_window = wine_server_user_handle( device->hwndTarget ); + ret = !wine_server_call_err( req ); + } + SERVER_END_REQ; + + if (!ret) + { + result = FALSE; + break; + } + } + return result; +} /****************************************************************** * GetRawInputData (USER32.@) */ 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; + } + if (pcbSize == NULL) + { + SetLastError( ERROR_NOACCESS ); + 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; + if (pData != NULL) + wine_server_set_reply( req, pData, *pcbSize ); + ret = !wine_server_call_err( req ); + if (pData == NULL) + { + *pcbSize = reply->size; + result = 0; + } + else + { + result = reply->size; + } + } + SERVER_END_REQ; + return ret ? result : (UINT)-1; +} /****************************************************************** * GetRawInputBuffer (USER32.@) */ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader) { - FIXME("(pData=%p, pcbSize=%p, cbSizeHeader=%d) stub!\n", pData, pcbSize, cbSizeHeader); + TRACE("(pData=%p, pcbSize=%p, cbSizeHeader=%d)\n", pData, pcbSize, cbSizeHeader); + + if (pcbSize == NULL || cbSizeHeader != sizeof( RAWINPUTHEADER )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return (UINT)-1; + } + + /* Since every raw input data entry is mapped to WM_INPUT one-to-one, + returning anything would make the data points to be processed twice */ + + *pcbSize = 0; return 0; } - /****************************************************************** * GetRawInputDeviceInfoA (USER32.@) */ UINT WINAPI GetRawInputDeviceInfoA(HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize) { - FIXME("(hDevice=%p, uiCommand=%d, pData=%p, pcbSize=%p) stub!\n", hDevice, uiCommand, pData, pcbSize); + TRACE("(hDevice=%p, uiCommand=%d, pData=%p, pcbSize=%p)\n", hDevice, uiCommand, pData, pcbSize); - return 0; -} + if (pcbSize == NULL) + { + SetLastError( ERROR_NOACCESS ); + return (UINT)-1; + } + if (uiCommand == RIDI_DEVICENAME && pData != NULL) + { + WCHAR buffer[256]; + UINT size = 256; + const UINT ret = GetRawInputDeviceInfoW( hDevice, uiCommand, buffer, &size ); + /* ret is the character count */ + if (ret == (UINT)-1) + { + return ret; + } + else if (ret > 0 && *pcbSize >= ret) + { + const int ret2 = wine_utf8_wcstombs( 0, buffer, ret, pData, *pcbSize ); + if (ret2 == -1) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return (UINT)-1; + } + else if (ret2 == -2) + { + SetLastError( ERROR_INTERNAL_ERROR ); + return (UINT)-1; + } + return ret; + } + else if (ret > 0) + { + *pcbSize = ret; + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return (UINT)-1; + } + else + { + *pcbSize = size; + return ret; + } + } + else + { + return GetRawInputDeviceInfoW( hDevice, uiCommand, pData, pcbSize ); + } +} /****************************************************************** * GetRawInputDeviceInfoW (USER32.@) */ UINT WINAPI GetRawInputDeviceInfoW(HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize) { - FIXME("(hDevice=%p, uiCommand=%d, pData=%p, pcbSize=%p) stub!\n", hDevice, uiCommand, pData, pcbSize); + BOOL ret; + UINT result, size_in_bytes; - return 0; + TRACE("(hDevice=%p, uiCommand=%d, pData=%p, pcbSize=%p)\n", hDevice, uiCommand, pData, pcbSize); + + if (pcbSize == NULL) + { + SetLastError( ERROR_NOACCESS ); + return (UINT)-1; + } + if (uiCommand == RIDI_DEVICEINFO && pData != NULL) + { + RID_DEVICE_INFO *info = (RID_DEVICE_INFO *)pData; + if (info->cbSize != sizeof( RID_DEVICE_INFO )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return (UINT)-1; + } + } + + size_in_bytes = uiCommand == RIDI_DEVICENAME ? *pcbSize * sizeof( WCHAR ) : *pcbSize; + + SERVER_START_REQ( get_raw_input_device_info ) + { + req->handle = wine_server_user_handle( hDevice ); + req->command = uiCommand; + req->report_size_only = pData == NULL; + if (pData != NULL) + wine_server_set_reply( req, pData, size_in_bytes ); + ret = !wine_server_call_err( req ); + if (pData == NULL) + { + *pcbSize = reply->size; + result = 0; + } + else + { + result = reply->size; + } + } + SERVER_END_REQ; + + return ret ? result : (UINT)-1; } @@ -546,9 +863,41 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE hDevice, UINT uiCommand, LPVOID pData, */ UINT WINAPI GetRegisteredRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, PUINT puiNumDevices, UINT cbSize) { - FIXME("(pRawInputDevices=%p, puiNumDevices=%p, cbSize=%d) stub!\n", pRawInputDevices, puiNumDevices, cbSize); + BOOL ret = FALSE; + UINT result; - return 0; + TRACE("(pRawInputDevices=%p, puiNumDevices=%p, cbSize=%d)\n", pRawInputDevices, puiNumDevices, cbSize); + + if (cbSize != sizeof( RAWINPUTDEVICE )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return (UINT)-1; + } + if (puiNumDevices == NULL) + { + SetLastError( ERROR_NOACCESS ); + return (UINT)-1; + } + + SERVER_START_REQ( get_registered_raw_input_devices ) + { + req->report_size_only = pRawInputDevices == NULL; + if (pRawInputDevices != NULL) + wine_server_set_reply( req, pRawInputDevices, *puiNumDevices * sizeof( RAWINPUTDEVICE ) ); + ret = !wine_server_call_err( req ); + if (pRawInputDevices == NULL) + { + *puiNumDevices = reply->num_devices; + result = 0; + } + else + { + result = reply->num_devices; + } + } + SERVER_END_REQ; + + return ret ? result : (UINT)-1; } @@ -557,11 +906,18 @@ UINT WINAPI GetRegisteredRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, PUINT */ LRESULT WINAPI DefRawInputProc(PRAWINPUT *paRawInput, INT nInput, UINT cbSizeHeader) { - FIXME("(paRawInput=%p, nInput=%d, cbSizeHeader=%d) stub!\n", *paRawInput, nInput, cbSizeHeader); + TRACE("(paRawInput=%p, nInput=%d, cbSizeHeader=%d)\n", *paRawInput, nInput, cbSizeHeader); - return 0; -} + if (cbSizeHeader != sizeof( RAWINPUTHEADER )) + { + /* Windows does not set last error code */ + return ERROR_INVALID_PARAMETER; + } + /* The supplied raw input entries can still be retrieved, so they will have to be released later */ + + return S_OK; +} /********************************************************************** * AttachThreadInput (USER32.@)