[Çözüldü]war in the north fare sorunu

Başlatan tokurugur, 28 Şubat 2012 - 20:27:46

« önceki - sonraki »

0 Üyeler ve 3 Ziyaretçi konuyu incelemekte.

tokurugur

selam arkadaşlar
wine ile ltr:war in the north kurdum. oyunun giriş ekranında hiç bir sorun yoktu fakat oyunun başlangıç sahnesi açıldığında fark ettim ki fare çalışmıyor. wineHQ sitesinde hatayı aratınca Mouse / keyboard input not handled (RawInput) (Bug 20395 ) adıyla bir bak çözümünü eklemişler. Kodu indirdim fakat nasıl çalıştıracağımı bilmiyorum yardım ederseniz sevinirim. Sitedeki kod aşağıdadır.
teşekkürler...

diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 1ffce8d..9f498eb 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -476,23 +476,229 @@ 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 (!ret || pRawInputDeviceList == NULL)
+        {
+            *puiNumDevices = reply->num_devices;
+            result = 0;
+        }
+        else
+            result = reply->num_devices;
+    }
+    SERVER_END_REQ;
+
+    return ret ? result : (UINT)-1;
}

+#define HID_USAGE_PAGE_GENERIC     ((unsigned short)0x01)
+#define HID_USAGE_GENERIC_MOUSE    ((unsigned short)0x02)
+#define HID_USAGE_GENERIC_KEYBOARD ((unsigned short)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 == HID_USAGE_PAGE_GENERIC &&
+            device->usUsage == HID_USAGE_GENERIC_MOUSE;
+        BOOL is_keyboard = device->usUsagePage == HID_USAGE_PAGE_GENERIC &&
+            device->usUsage == HID_USAGE_GENERIC_KEYBOARD;
+        UINT device_flags = device->dwFlags, registration_flags = 0;
+
+        if (device->usUsagePage == 0)
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            result = FALSE;
+            break;
+        }
+
+        /* RIDEV_* values can overlap, therefore we need to remove confirmed cases */
+
+        if ((device_flags & RIDEV_REMOVE) == RIDEV_REMOVE)
+        {
+            if (device->hwndTarget != NULL)
+            {
+                SetLastError( ERROR_INVALID_PARAMETER );
+                result = FALSE;
+                break;
+            }
+            device_flags       &= ~RIDEV_REMOVE;
+            registration_flags |= REGISTER_RAW_INPUT_DEVICE_REMOVE;
+        }
+
+        if ((device_flags & RIDEV_NOHOTKEYS) == RIDEV_NOHOTKEYS && is_keyboard)
+        {
+            FIXME("RIDEV_NOHOTKEYS support is not implemented\n");
+            device_flags       &= ~RIDEV_NOHOTKEYS;
+            registration_flags |= REGISTER_RAW_INPUT_DEVICE_NOHOTKEYS;
+        }
+
+        if ((device_flags & RIDEV_NOLEGACY) == RIDEV_NOLEGACY && !is_mouse && !is_keyboard)
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            result = FALSE;
+            break;
+        }
+        else if ((device_flags & RIDEV_NOLEGACY) == RIDEV_NOLEGACY)
+        {
+            device_flags       &= ~RIDEV_NOLEGACY;
+            registration_flags |= REGISTER_RAW_INPUT_DEVICE_NOLEGACY;
+
+            if ((device_flags & RIDEV_CAPTUREMOUSE) == RIDEV_CAPTUREMOUSE && is_mouse)
+            {
+                FIXME("RIDEV_CAPTUREMOUSE support is not implemented\n");
+                if (device->hwndTarget == NULL)
+                {
+                    SetLastError( ERROR_INVALID_FLAGS );
+                    result = FALSE;
+                    break;
+                }
+                device_flags       &= ~RIDEV_CAPTUREMOUSE;
+                registration_flags |= REGISTER_RAW_INPUT_DEVICE_CAPTUREMOUSE;
+            }
+            /* RIDEV_CAPTUREMOUSE && is_keyboard is not possible, because
+               RIDEV_CAPTUREMOUSE == RIDEV_NOHOTKEYS */
+
+            if ((device_flags & RIDEV_APPKEYS) == RIDEV_APPKEYS && is_keyboard)
+            {
+                FIXME("RIDEV_APPKEYS support is not implemented\n");
+                device_flags       &= ~RIDEV_APPKEYS;
+                registration_flags |= REGISTER_RAW_INPUT_DEVICE_APPKEYS;
+            }
+            else if ((device_flags & RIDEV_APPKEYS) == RIDEV_APPKEYS && is_mouse)
+            {
+                SetLastError( ERROR_INVALID_FLAGS );
+                result = FALSE;
+                break;
+            }
+        }
+        else if ((device_flags & RIDEV_CAPTUREMOUSE) == RIDEV_CAPTUREMOUSE ||
+            (device_flags & RIDEV_APPKEYS) == RIDEV_APPKEYS)
+        {
+            SetLastError( ERROR_INVALID_FLAGS );
+            result = FALSE;
+            break;
+        }
+
+        if ((device_flags & RIDEV_PAGEONLY) == RIDEV_PAGEONLY && device->usUsage == 0)
+        {
+            device_flags       &= ~RIDEV_PAGEONLY;
+            registration_flags |= REGISTER_RAW_INPUT_DEVICE_PAGEONLY;
+        }
+        else if (((device_flags & RIDEV_PAGEONLY) == RIDEV_PAGEONLY && device->usUsage != 0) ||
+            ((device_flags & RIDEV_PAGEONLY) != RIDEV_PAGEONLY && device->usUsage == 0))
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            result = FALSE;
+            break;
+        }
+
+        if ((device_flags & RIDEV_EXCLUDE) == RIDEV_EXCLUDE)
+        {
+            if (device->hwndTarget != NULL)
+            {
+                SetLastError( ERROR_INVALID_PARAMETER );
+                result = FALSE;
+                break;
+            }
+            device_flags       &= ~RIDEV_EXCLUDE;
+            registration_flags |= REGISTER_RAW_INPUT_DEVICE_EXCLUDE;
+        }
+
+        if ((device_flags & RIDEV_INPUTSINK) == RIDEV_INPUTSINK)
+        {
+            FIXME("RIDEV_INPUTSINK support is not implemented\n");
+            if (device->hwndTarget == NULL)
+            {
+                SetLastError( ERROR_INVALID_PARAMETER );
+                result = FALSE;
+                break;
+            }
+            device_flags       &= ~RIDEV_INPUTSINK;
+            registration_flags |= REGISTER_RAW_INPUT_DEVICE_INPUTSINK;
+        }
+
+        if ((device_flags & RIDEV_EXINPUTSINK) == RIDEV_EXINPUTSINK)
+        {
+            FIXME("RIDEV_EXINPUTSINK support is not implemented\n");
+            if (device->hwndTarget == NULL)
+            {
+                SetLastError( ERROR_INVALID_PARAMETER );
+                result = FALSE;
+                break;
+            }
+            device_flags       &= ~RIDEV_EXINPUTSINK;
+            registration_flags |= REGISTER_RAW_INPUT_DEVICE_EXINPUTSINK;
+        }
+
+        if ((device_flags & RIDEV_DEVNOTIFY) == RIDEV_DEVNOTIFY)
+        {
+            FIXME("RIDEV_DEVNOTIFY support is not implemented\n");
+            device_flags       &= ~RIDEV_DEVNOTIFY;
+            registration_flags |= REGISTER_RAW_INPUT_DEVICE_DEVNOTIFY;
+        }
+
+        /* If anything is left, it's invalid */
+        if (device_flags)
+        {
+            SetLastError( ERROR_INVALID_FLAGS );
+            result = FALSE;
+            break;
+        }
+
+        SERVER_START_REQ( register_raw_input_device )
+        {
+            req->usage_page    = device->usUsagePage;
+            req->usage         = device->usUsage;
+            req->flags         = registration_flags;
+            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;
}


@@ -501,10 +707,43 @@ 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",
-            hRawInput, uiCommand, pData, pcbSize, cbSizeHeader);
-
-    return 0;
+    BOOL ret;
+    UINT result;
+
+    TRACE("(hRawInput=%p, uiCommand=%d, pData=%p, pcbSize=%p, cbSizeHeader=%d)\n",
+            hRawInput, uiCommand, pData, pcbSize, cbSizeHeader);
+
+    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;
}


@@ -513,8 +752,18 @@ 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);
+     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;
}

@@ -524,20 +773,91 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize,
*/
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 = WideCharToMultiByte( CP_ACP, 0, buffer, ret, pData, *pcbSize, NULL, NULL );
+            return ret2 ? ret2 : (UINT)-1;
+        }
+        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 (!ret || pData == NULL)
+        {
+            *pcbSize = reply->size;
+            result = 0;
+        }
+        else
+            result = reply->size;
+    }
+    SERVER_END_REQ;
+
+    return ret ? result : (UINT)-1;
}


@@ -546,9 +866,39 @@ 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 (!ret || pRawInputDevices == NULL)
+        {
+            *puiNumDevices = reply->num_devices;
+            result = 0;
+        }
+        else
+            result = reply->num_devices;
+    }
+    SERVER_END_REQ;
+
+    return ret ? result : (UINT)-1;
}


@@ -557,11 +907,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.@)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index d45edf1..86fa729 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -77,6 +77,18 @@ static struct {

static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
static int (WINAPI *pGetMouseMovePointsEx) (UINT, LPMOUSEMOVEPOINT, LPMOUSEMOVEPOINT, int, DWORD);
+static LRESULT (WINAPI *pDefRawInputProc) (PRAWINPUT*, INT, UINT);
+static UINT (WINAPI *pGetRawInputBuffer) (PRAWINPUT, PUINT, UINT);
+static INT (WINAPI *pGetRawInputData) (HRAWINPUT, UINT, LPVOID, PUINT, UINT);
+static UINT (WINAPI *pGetRawInputDeviceInfoA) (HANDLE, UINT, LPVOID, PUINT);
+static UINT (WINAPI *pGetRawInputDeviceInfoW) (HANDLE, UINT, LPVOID, PUINT);
+static UINT (WINAPI *pGetRawInputDeviceList) (PRAWINPUTDEVICELIST, PUINT, UINT);
+static UINT (WINAPI *pGetRegisteredRawInputDevices) (PRAWINPUTDEVICE, PUINT, UINT);
+static BOOL (WINAPI *pRegisterRawInputDevices) (PRAWINPUTDEVICE, UINT, UINT);
+
+#define HID_USAGE_PAGE_GENERIC     ((unsigned short)0x01)
+#define HID_USAGE_GENERIC_MOUSE    ((unsigned short)0x02)
+#define HID_USAGE_GENERIC_KEYBOARD ((unsigned short)0x06)

#define MAXKEYEVENTS 12
#define MAXKEYMESSAGES MAXKEYEVENTS /* assuming a key event generates one
@@ -160,6 +172,14 @@ static void init_function_pointers(void)

     GET_PROC(SendInput)
     GET_PROC(GetMouseMovePointsEx)
+    GET_PROC(DefRawInputProc)
+    GET_PROC(GetRawInputBuffer)
+    GET_PROC(GetRawInputData)
+    GET_PROC(GetRawInputDeviceInfoA)
+    GET_PROC(GetRawInputDeviceInfoW)
+    GET_PROC(GetRawInputDeviceList)
+    GET_PROC(GetRegisteredRawInputDevices)
+    GET_PROC(RegisterRawInputDevices)

#undef GET_PROC
}
@@ -1598,6 +1618,958 @@ static void test_keyboard_layout_name(void)
     ok(!strcmp(klid, "00000409"), "expected 00000409, got %s\n", klid);
}

+static void test_def_raw_input_proc(void)
+{
+    RAWINPUT *input = NULL;
+    LRESULT ret;
+
+    if (!pDefRawInputProc)
+    {
+        win_skip("DefRawInputProc is not available\n");
+        return;
+    }
+
+    ret = pDefRawInputProc(&input, 0, sizeof(RAWINPUTHEADER));
+    ok(ret == S_OK, "Given (&input, 0, sizeof), "
+        "DefRawInputProc should acknowledge that no data was provided\n");
+}
+
+static void test_get_raw_input_device_list(void)
+{
+    RAWINPUTDEVICELIST *device_list;
+    UINT ret, count, count2;
+    DWORD error;
+
+    if (!pGetRawInputDeviceList)
+    {
+        win_skip("GetRawInputDeviceList is not available\n");
+        return;
+    }
+
+    count = 0;
+    ret = pGetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST));
+    ok(ret == 0 && count >= 1, "Given (NULL, &count, sizeof), "
+        "GetRawInputDeviceList should return the number of raw input devices\n");
+
+    device_list = HeapAlloc(GetProcessHeap(), 0, count * sizeof(RAWINPUTDEVICELIST));
+    memset(device_list, 0xFF, count * sizeof(RAWINPUTDEVICELIST));
+
+    SetLastError(0xdeadbeef);
+    count2 = 0;
+    ret = pGetRawInputDeviceList(device_list, &count2, sizeof(RAWINPUTDEVICELIST));
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INSUFFICIENT_BUFFER && count2 == count,
+        "Given (device_list, &count2 = 0, sizeof), GetRawInputDeviceList should return an error, "
+        "but got a wrong one: %u\n", error);
+
+    count2 = count;
+    ret = pGetRawInputDeviceList(device_list, &count2, sizeof(RAWINPUTDEVICELIST));
+    ok(ret == count && count == count2, "Given (device_list, &count2 = count, sizeof), "
+        "GetRawInputDeviceList should return the list of raw input devices\n");
+
+    ok(device_list[0].hDevice != NULL,
+        "First device should have a non-null handle\n");
+    ok(device_list[0].dwType == RIM_TYPEMOUSE || device_list[0].dwType == RIM_TYPEKEYBOARD,
+        "First device should be a mouse or a keyboard");
+
+    HeapFree(GetProcessHeap(), 0, device_list);
+}
+
+static void test_get_raw_input_device_info_w(void)
+{
+    UINT ret, size = 0, count;
+    RAWINPUTDEVICELIST *devices;
+    WCHAR buffer[1024];
+    RID_DEVICE_INFO info;
+    DWORD error;
+
+    if (!pGetRawInputDeviceInfoW || !pGetRawInputDeviceList)
+    {
+        win_skip("GetRawInputDeviceInfoW and GetRawInputDeviceList are not available\n");
+        return;
+    }
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRawInputDeviceInfoW(NULL, 0, NULL, NULL);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_NOACCESS, "Given (NULL, 0, NULL, NULL), "
+        "GetRawInputDeviceInfoW should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    size = 0;
+    ret = pGetRawInputDeviceInfoW(NULL, 0, NULL, &size);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_HANDLE,
+        "Given (NULL, 0, NULL, &size), "
+        "GetRawInputDeviceInfoW should return an error, but got a wrong one: %u\n", error);
+
+    ok(pGetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) == 0,
+        "Failed to get raw input device count\n");
+    ok(count > 0, "Should have at least one raw input device available\n");
+    ok((devices = HeapAlloc(GetProcessHeap(), 0, count * sizeof(RAWINPUTDEVICELIST))) != NULL,
+        "Failed to allocate memory for devices\n");
+    ok(pGetRawInputDeviceList(devices, &count, sizeof(RAWINPUTDEVICELIST)) == count,
+        "Failed to retrieve raw input device list");
+
+    SetLastError(0xdeadbeef);
+    size = 0;
+    ret = pGetRawInputDeviceInfoW(devices[0].hDevice, 0, NULL, &size);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_PARAMETER,
+        "Given (hDevice, 0, NULL, &size), "
+        "GetRawInputDeviceInfoW should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    size = 0;
+    ret = pGetRawInputDeviceInfoW(devices[0].hDevice, RIDI_DEVICENAME, buffer, &size);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INSUFFICIENT_BUFFER,
+        "Given (hDevice, RIDI_DEVICENAME, buffer, &size = 0), "
+        "GetRawInputDeviceInfoW should return an error, but got a wrong one: %u\n", error);
+
+    size = 0;
+    ret = pGetRawInputDeviceInfoW(devices[0].hDevice, RIDI_DEVICENAME, NULL, &size);
+    ok(ret == 0 && size > 0, "Given (hDevice, RIDI_DEVICENAME, NULL, &size), "
+        "GetRawInputDeviceInfoW should return the required size to retrieve the device info\n");
+
+    buffer[0] = 0;
+    ret = pGetRawInputDeviceInfoW(devices[0].hDevice, RIDI_DEVICENAME, buffer, &size);
+    ok(ret != (UINT)-1 && size > 0 && lstrlenW(buffer) > 5,
+        "Given (hDevice, RIDI_DEVICENAME, buffer, &size), "
+        "GetRawInputDeviceInfoW should retrieve the device name\n");
+
+    size = sizeof(RID_DEVICE_INFO);
+    info.cbSize = sizeof(RID_DEVICE_INFO);
+    ret = pGetRawInputDeviceInfoW(devices[0].hDevice, RIDI_DEVICEINFO, &info, &size);
+    ok(ret != (UINT)-1 && ret > 0 && size > 0,
+        "Given (hDevice, RIDI_DEVICEINFO, &info, &size), "
+        "GetRawInputDeviceInfoW should retrieve the device info\n");
+
+    HeapFree(GetProcessHeap(), 0, devices);
+}
+
+static void test_get_raw_input_device_info_a(void)
+{
+    UINT ret, size = 0, count;
+    RAWINPUTDEVICELIST *devices;
+    char buffer[1024];
+    RID_DEVICE_INFO info;
+    DWORD error;
+
+    if (!pGetRawInputDeviceInfoA || !pGetRawInputDeviceList)
+    {
+        win_skip("GetRawInputDeviceInfoA and GetRawInputDeviceList are not available\n");
+        return;
+    }
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRawInputDeviceInfoA(NULL, 0, NULL, NULL);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_NOACCESS, "Given (NULL, 0, NULL, NULL), "
+        "GetRawInputDeviceInfoA should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    size = 0;
+    ret = pGetRawInputDeviceInfoA(NULL, 0, NULL, &size);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_HANDLE,
+        "Given (NULL, 0, NULL, &size), "
+        "GetRawInputDeviceInfoA should return an error, but got a wrong one: %u\n", error);
+
+    ok(pGetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) == 0,
+        "Failed to get raw input device count\n");
+    ok(count > 0, "Should have at least one raw input device available\n");
+    ok((devices = HeapAlloc(GetProcessHeap(), 0, count * sizeof(RAWINPUTDEVICELIST))) != NULL,
+        "Failed to allocate memory for devices\n");
+    ok(pGetRawInputDeviceList(devices, &count, sizeof(RAWINPUTDEVICELIST)) == count,
+        "Failed to retrieve raw input device list");
+
+    SetLastError(0xdeadbeef);
+    size = 0;
+    ret = pGetRawInputDeviceInfoA(devices[0].hDevice, 0, NULL, &size);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_PARAMETER,
+        "Given (hDevice, 0, NULL, &size), "
+        "GetRawInputDeviceInfoA should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    size = 0;
+    ret = pGetRawInputDeviceInfoA(devices[0].hDevice, RIDI_DEVICENAME, buffer, &size);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INSUFFICIENT_BUFFER,
+        "Given (hDevice, RIDI_DEVICENAME, buffer, &size = 0), "
+        "GetRawInputDeviceInfoA should return an error, but got a wrong one: %u\n", error);
+
+    size = 0;
+    ret = pGetRawInputDeviceInfoA(devices[0].hDevice, RIDI_DEVICENAME, NULL, &size);
+    ok(ret == 0 && size > 0, "Given (hDevice, RIDI_DEVICENAME, NULL, &size), "
+        "GetRawInputDeviceInfoA should return the required size to retrieve "
+        "the device info\n");
+
+    buffer[0] = 0;
+    ret = pGetRawInputDeviceInfoA(devices[0].hDevice, RIDI_DEVICENAME, buffer, &size);
+    ok(ret != (UINT)-1 && size > 0 && strlen(buffer) > 5,
+        "Given (hDevice, RIDI_DEVICENAME, buffer, &size), "
+        "GetRawInputDeviceInfoA should retrieve the device name\n");
+
+    size = sizeof(RID_DEVICE_INFO);
+    info.cbSize = sizeof(RID_DEVICE_INFO);
+    ret = pGetRawInputDeviceInfoA(devices[0].hDevice, RIDI_DEVICEINFO, &info, &size);
+    ok(ret != (UINT)-1 && ret > 0 && size > 0,
+        "Given (hDevice, RIDI_DEVICEINFO, &info, &size), "
+        "GetRawInputDeviceInfoA should retrieve the device info\n");
+
+    HeapFree(GetProcessHeap(), 0, devices);
+}
+
+static void test_register_raw_input_devices(void)
+{
+    RAWINPUTDEVICE device;
+    BOOL ret;
+    DWORD error;
+
+    if (!pRegisterRawInputDevices)
+    {
+        win_skip("RegisterRawInputDevices is not available\n");
+        return;
+    }
+
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(NULL, 0, 0);
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_PARAMETER, "Given (NULL, 0, 0), "
+        "RegisterRawInputDevices should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(NULL, 0, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(ret == FALSE && error == ERROR_INVALID_PARAMETER,
+        "Given (NULL, 0, sizeof), "
+        "RegisterRawInputDevices should return an error, but got a wrong one: %u\n", error);
+
+    device.usUsagePage = 0;
+    device.usUsage     = 0;
+    device.dwFlags     = 0;
+    device.hwndTarget  = NULL;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 0, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_PARAMETER,
+        "Given (&device{0,0,0,0}, 0, sizeof), "
+        "RegisterRawInputDevices should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(ret == FALSE && error == ERROR_INVALID_PARAMETER,
+        "Given (&device{0,0,0,0}, 1, sizeof), "
+        "RegisterRawInputDevices should return an error, but got a wrong one: %u\n", error);
+
+    device.usUsagePage = HID_USAGE_PAGE_GENERIC;
+    device.usUsage     = HID_USAGE_GENERIC_MOUSE;
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,2,0,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully subscribe to "
+        "a mouse raw input device\n");
+
+    device.dwFlags = RIDEV_REMOVE;
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,2,RIDEV_REMOVE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully unsubscribe from "
+        "a mouse raw input device\n");
+
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,2,RIDEV_REMOVE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should return success even if already unsubscribed\n");
+
+    device.usUsagePage = 0xFF;
+    device.usUsage     = 0xFF;
+    device.dwFlags     = 0;
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{0xFF,0xFF,0,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully subscribe to a non-existing device\n");
+
+    device.dwFlags = RIDEV_REMOVE;
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{0xFF,0xFF,RIDEV_REMOVE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully unsubscribe from "
+        "a non-existing device\n");
+
+    /* Test precondition assertions of various flags */
+    device.usUsagePage = HID_USAGE_PAGE_GENERIC;
+    device.usUsage     = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags     = RIDEV_REMOVE;
+    device.hwndTarget  = (HWND)-1;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_PARAMETER,
+        "Given (&device{1,2,RIDEV_REMOVE,-1}, 1, sizeof), "
+        "RegisterRawInputDevices should fail to unsubscribe from a device, "
+        "when hwndTarget is non-null, but got a wrong error: %u\n", error);
+
+    device.usUsage    = 0xFF;
+    device.dwFlags    = RIDEV_PAGEONLY;
+    device.hwndTarget = NULL;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_PARAMETER,
+        "Given (&device{1,0xFF,RIDEV_PAGEONLY,0}, 1, sizeof), "
+        "RegisterRawInputDevices should fail, because RIDEV_PAGEONLY "
+        "requires usUsage to be zero, but got a wrong error: %u\n", error);
+
+    device.usUsage    = 0;
+    device.dwFlags    = RIDEV_EXCLUDE;
+    device.hwndTarget = NULL;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_PARAMETER,
+        "Given (&device{1,0,RIDEV_EXCLUDE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should fail, because RIDEV_EXCLUDE "
+        "requires usUsage to be non-zero, but got a wrong error: %u\n", error);
+
+    device.usUsage    = 0xFF;
+    device.dwFlags    = RIDEV_NOLEGACY;
+    device.hwndTarget = NULL;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_PARAMETER,
+        "Given (&device{1,0xFF,RIDEV_NOLEGACY,0}, 1, sizeof), "
+        "RegisterRawInputDevices should fail, because RIDEV_NOLEGACY is only available for "
+        "mouse or keyboard devices, but got a wrong error: %u\n", error);
+
+    device.usUsage    = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags    = RIDEV_INPUTSINK;
+    device.hwndTarget = NULL;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_PARAMETER,
+        "Given (&device{1,2,RIDEV_INPUTSINK,0}, 1, sizeof), "
+        "RegisterRawInputDevices should fail, because RIDEV_INPUTSINK "
+        "requires hwndTarget to be non-null, but got a wrong error: %u\n", error);
+
+    /* Since RIDEV_CAPTUREMOUSE == RIDEV_NOHOTKEYS, scope it for the mouse device */
+    device.usUsage    = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags    = RIDEV_CAPTUREMOUSE;
+    device.hwndTarget = NULL;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_FLAGS,
+        "Given (&device{1,2,RIDEV_CAPTUREMOUSE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should fail, because RIDEV_CAPTUREMOUSE "
+        "must be combined with RIDEV_NOLEGACY, but got a wrong error: %u\n", error);
+
+    device.usUsage    = HID_USAGE_GENERIC_KEYBOARD;
+    device.dwFlags    = RIDEV_APPKEYS;
+    device.hwndTarget = NULL;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_FLAGS,
+        "Given (&device{1,6,RIDEV_APPKEYS,0}, 1, sizeof), "
+        "RegisterRawInputDevices should fail, because RIDEV_APPKEYS "
+        "must be combined with RIDEV_NOLEGACY, but got a wrong error: %u\n", error);
+
+    device.usUsage    = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags    = RIDEV_NOLEGACY | RIDEV_APPKEYS;
+    device.hwndTarget = NULL;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_FLAGS,
+        "Given (&device{1,2,RIDEV_NOLEGACY|RIDEV_APPKEYS,0}, 1, sizeof), "
+        "RegisterRawInputDevices should fail, because RIDEV_APPKEYS "
+        "can be used only on a keyboard device, but got a wrong error: %u\n", error);
+
+    device.usUsage    = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags    = RIDEV_NOHOTKEYS;
+    device.hwndTarget = NULL;
+    SetLastError(0xdeadbeef);
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_FLAGS,
+        "Given (&device{1,2,RIDEV_NOHOTKEYS,0}, 1, sizeof), "
+        "RegisterRawInputDevices should fail, because RIDEV_NOHOTKEYS "
+        "can be used only on a keyboard device, but got a wrong error: %u\n", error);
+}
+
+static void test_get_registered_raw_input_devices(void)
+{
+    RAWINPUTDEVICE device, device2;
+    UINT ret, count;
+    BOOL ret2;
+    DWORD error;
+
+    if (!pGetRegisteredRawInputDevices || !pRegisterRawInputDevices)
+    {
+        win_skip("GetRegisteredRawInputDevices and RegisterRawInputDevices are not available\n");
+        return;
+    }
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRegisteredRawInputDevices(NULL, NULL, 0);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_PARAMETER,
+        "Given (NULL, NULL, 0), "
+        "GetRegisteredRawInputDevices should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRegisteredRawInputDevices(NULL, NULL, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_NOACCESS, "Given (NULL, NULL, sizeof), "
+        "GetRegisteredRawInputDevices should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRegisteredRawInputDevices(NULL, &count, 1);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_PARAMETER,
+        "Given (NULL, &count, 1), "
+        "GetRegisteredRawInputDevices should return an error, but got a wrong one: %u\n", error);
+
+    count = 0xdeadbeef;
+    ret = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret == 0 && count == 0, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that no devices are registered\n");
+
+    device.usUsagePage = HID_USAGE_PAGE_GENERIC;
+    device.usUsage     = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags     = 0;
+    device.hwndTarget  = NULL;
+    ret2 = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret2, "Given (&device{1,2,0,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully subscribe to a mouse raw input device\n");
+
+    ret = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret == 0 && count == 1, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that one device is registered\n");
+
+    memset(&device2, 0xFF, sizeof(RAWINPUTDEVICE));
+    ret = pGetRegisteredRawInputDevices(&device2, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret == 1 && memcmp(&device, &device2, sizeof(RAWINPUTDEVICE)) == 0,
+        "Given (&device2, &count, sizeof), GetRegisteredRawInputDevices "
+        "should return an identical device to the one registered\n");
+
+    ret2 = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret2, "Given (&device{1,2,0,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully reregister a device\n");
+
+    memset(&device2, 0xFF, sizeof(RAWINPUTDEVICE));
+    ret = pGetRegisteredRawInputDevices(&device2, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret == 1 && memcmp(&device, &device2, sizeof(RAWINPUTDEVICE)) == 0,
+        "Given (&device2, &count, sizeof), "
+        "GetRegisteredRawInputDevices should still return one device registered\n");
+
+    device.dwFlags = RIDEV_REMOVE;
+    ret2 = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret2, "Given (&device{1,2,RIDEV_REMOVE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully unsubscribe from a mouse raw input device\n");
+
+    count = 0xdeadbeef;
+    ret = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret == 0 && count == 0, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that no devices are registered\n");
+}
+
+static void test_register_raw_input_devices_with_flags(void)
+{
+    RAWINPUTDEVICE device, devices[2];
+    BOOL ret;
+    UINT ret2, count;
+    DWORD error;
+
+    if (!pGetRegisteredRawInputDevices || !pRegisterRawInputDevices)
+    {
+        win_skip("GetRegisteredRawInputDevices and RegisterRawInputDevices are not available\n");
+        return;
+    }
+
+    /* Assert that there are not devices registered */
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 0, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that no devices are registered\n");
+
+    /* Subscribe and unsubscribe from all devices in usage page */
+    device.usUsagePage = HID_USAGE_PAGE_GENERIC;
+    device.usUsage     = 0;
+    device.dwFlags     = RIDEV_PAGEONLY;
+    device.hwndTarget  = NULL;
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,0,RIDEV_PAGEONLY,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully subscribe to "
+        "devices from that usage page\n");
+
+    device.dwFlags = RIDEV_REMOVE | RIDEV_PAGEONLY;
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,0,RIDEV_REMOVE|RIDEV_PAGEONLY,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully unsubscribe from "
+        "devices from that usage page\n");
+
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 0, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that no devices are registered\n");
+
+    /* Should override a device exclusion with an inclusion */
+    devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
+    devices[0].usUsage     = HID_USAGE_GENERIC_MOUSE;
+    devices[0].dwFlags     = RIDEV_EXCLUDE;
+    devices[0].hwndTarget  = NULL;
+    devices[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
+    devices[1].usUsage     = HID_USAGE_GENERIC_MOUSE;
+    devices[1].dwFlags     = 0;
+    devices[1].hwndTarget  = NULL;
+    ret = pRegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&devices{{1,2,RIDEV_EXCLUDE,0},{1,2,0,0}}, 2, sizeof), "
+        "RegisterRawInputDevices should successfully subscribe to a device\n");
+
+    devices[1].dwFlags = RIDEV_REMOVE;
+    ret = pRegisterRawInputDevices(&devices[1], 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,2,RIDEV_REMOVE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully unsubscribe from a device\n");
+
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 0, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that no devices are registered\n");
+
+    /* Should register a usage page and a device from that usage page,
+       unsubscribing from them separately */
+    devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
+    devices[0].usUsage     = 0;
+    devices[0].dwFlags     = RIDEV_PAGEONLY;
+    devices[0].hwndTarget  = NULL;
+    devices[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
+    devices[1].usUsage     = HID_USAGE_GENERIC_MOUSE;
+    devices[1].dwFlags     = 0;
+    devices[1].hwndTarget  = NULL;
+    ret = pRegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&devices{{1,0,RIDEV_PAGEONLY,0},{1,2,0,0}}, 2, sizeof), "
+        "RegisterRawInputDevices should successfully subscribe to "
+        "usage page devices and a device from that usage page\n");
+
+    devices[0].dwFlags = RIDEV_REMOVE | RIDEV_PAGEONLY;
+    ret = pRegisterRawInputDevices(&devices[0], 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,2,RIDEV_REMOVE|RIDEV_PAGEONLY,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully unsubscribe from a mouse raw input device\n");
+
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 1, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that one device is registered\n");
+
+    devices[1].dwFlags = RIDEV_REMOVE;
+    ret = pRegisterRawInputDevices(&devices[1], 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,2,RIDEV_REMOVE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully unsubscribe from a mouse raw input device\n");
+
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 0, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that no devices are registered\n");
+
+    /* Should allow to exclude a device */
+    device.usUsagePage = HID_USAGE_PAGE_GENERIC;
+    device.usUsage     = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags     = RIDEV_EXCLUDE;
+    device.hwndTarget  = NULL;
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,2,RIDEV_EXCLUDE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully exclude a device from input feed\n");
+
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 1, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that one device is registered\n");
+
+    device.dwFlags = RIDEV_REMOVE;
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&device{1,2,RIDEV_REMOVE,0}, 1, sizeof), "
+        "RegisterRawInputDevices should successfully remove the subscribtion\n");
+
+    /* Should include a usage page and exclude a device */
+    devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
+    devices[0].usUsage     = 0;
+    devices[0].dwFlags     = RIDEV_PAGEONLY;
+    devices[0].hwndTarget  = NULL;
+    devices[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
+    devices[1].usUsage     = HID_USAGE_GENERIC_MOUSE;
+    devices[1].dwFlags     = RIDEV_EXCLUDE;
+    devices[1].hwndTarget  = NULL;
+    ret = pRegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&devices{{1,2,RIDEV_EXCLUDE,0},{1,2,0,0}}, 2, sizeof), "
+        "RegisterRawInputDevices should successfully subscribe to a device\n");
+
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 2, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return two entries\n");
+
+    devices[0].dwFlags = RIDEV_REMOVE | RIDEV_PAGEONLY;
+    devices[1].dwFlags = RIDEV_REMOVE;
+    ret = pRegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&devices{{1,2,RIDEV_REMOVE|RIDEV_PAGEONLY,0},{1,2,RIDEV_REMOVE,0}}, 1, sizeof),"
+        "RegisterRawInputDevices should successfully remove the subscribtions\n");
+
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 0, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that no devices are registered\n");
+
+    /* Should allow to subscribe and unsubscribe in the same call */
+    devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
+    devices[0].usUsage     = HID_USAGE_GENERIC_MOUSE;
+    devices[0].dwFlags     = 0;
+    devices[0].hwndTarget  = NULL;
+    devices[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
+    devices[1].usUsage     = HID_USAGE_GENERIC_MOUSE;
+    devices[1].dwFlags     = RIDEV_REMOVE;
+    devices[1].hwndTarget  = NULL;
+    ret = pRegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Given (&devices{{1,2,0,0},{1,2,RIDEV_REMOVE,0}}, 2, sizeof), "
+        "RegisterRawInputDevices should successfully subscribe and unsubscribe\n");
+
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 0, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that no devices are registered\n");
+
+    /* Test reaction to an invalid flag */
+    SetLastError(0xdeadbeef);
+    device.usUsagePage = HID_USAGE_PAGE_GENERIC;
+    device.usUsage     = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags     = 0x80000000;
+    device.hwndTarget  = NULL;
+    ret = pRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
+    error = GetLastError();
+    ok(!ret && error == ERROR_INVALID_FLAGS,
+        "Given (&device{1,2,0x80000000,0}, 1, sizeof), "
+        "RegisterRawInputDevices should fail to register a device with "
+        "invalid flags specified, but got a wrong error: %u\n", error);
+}
+
+static void test_get_raw_input_buffer(void)
+{
+    UINT ret, size;
+    DWORD error;
+
+    if (!pGetRawInputBuffer)
+    {
+        win_skip("GetRawInputBuffer is not available\n");
+        return;
+    }
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRawInputBuffer(NULL, NULL, 0);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_PARAMETER,
+        "Given (NULL, NULL, 0), "
+        "GetRawInputBuffer should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRawInputBuffer(NULL, NULL, sizeof(RAWINPUTHEADER));
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_PARAMETER,
+        "Given (NULL, NULL, sizeof), "
+        "GetRawInputBuffer should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRawInputBuffer(NULL, &size, 1);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_PARAMETER,
+        "Given (NULL, &size, 1), "
+        "GetRawInputBuffer should return an error, but got a wrong one: %u\n", error);
+
+    size = (UINT)-1;
+    ret = pGetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER));
+    ok(ret == 0 && size == 0, "Given (NULL, &size, sizeof), "
+        "GetRawInputBuffer should that no data is buffered\n");
+}
+
+static void test_get_raw_input_data(void)
+{
+    UINT ret, count;
+    DWORD error;
+
+    if (!pGetRawInputData)
+    {
+        win_skip("GetRawInputData is not available\n");
+        return;
+    }
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRawInputData(NULL, 0, NULL, NULL, 0);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_PARAMETER,
+        "Given (NULL, 0, NULL, NULL, 0), "
+        "GetRawInputData should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRawInputData(NULL, 0, NULL, NULL, sizeof(RAWINPUTHEADER));
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_HANDLE,
+        "Given (NULL, 0, NULL, NULL, sizeof), "
+        "GetRawInputData should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRawInputData(NULL, 0, NULL, &count, 1);
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_PARAMETER,
+        "Given (NULL, 0, NULL, &count, 1), "
+        "GetRawInputData should return an error, but got a wrong one: %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pGetRawInputData(NULL, 0, NULL, &count, sizeof(RAWINPUTHEADER));
+    error = GetLastError();
+    ok(ret == (UINT)-1 && error == ERROR_INVALID_HANDLE,
+        "Given (NULL, 0, NULL, &count, sizeof), "
+        "GetRawInputData should return an error, but got a wrong one: %u\n", error);
+}
+
+static BOOL wm_input_recieved;
+static BOOL legacy_mouse_message_recieved;
+static BOOL legacy_keyboard_message_recieved;
+
+static LRESULT CALLBACK get_raw_input_data_wnd_proc(HWND hWnd, UINT msg,
+    WPARAM wParam, LPARAM lParam)
+{
+    UINT dwSize, ret2;
+    RAWINPUT *raw;
+    BOOL ret;
+    LRESULT ret3;
+    DWORD error;
+
+    legacy_mouse_message_recieved    |= msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST;
+    legacy_keyboard_message_recieved |= msg >= WM_KEYFIRST   && msg <= WM_KEYLAST;
+
+    switch (msg)
+    {
+    case WM_INPUT:
+        /* Now that we have a valid HRAWINPUT handle,
+           let's test the case, when &dwSize is NULL */
+        SetLastError(0xdeadbeef);
+        ret = pGetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, NULL,
+            sizeof(RAWINPUTHEADER));
+        error = GetLastError();
+        ok(ret == (UINT)-1 && error == ERROR_NOACCESS,
+            "Given (lParam, RID_INPUT, NULL, NULL, sizeof), "
+            "GetRawInputData should return an error, but got a wrong one: %u\n", error);
+
+        /* Test retrieving of RAWINPUT data */
+        ret2 = pGetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize,
+            sizeof(RAWINPUTHEADER));
+        ok(ret2 == 0, "Failed to retrieve raw input data size\n");
+        if (!(raw = HeapAlloc(GetProcessHeap(), 0, dwSize)))
+            break;
+        ret2 = pGetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw, &dwSize,
+            sizeof(RAWINPUTHEADER));
+        ok(ret2 == dwSize, "Failed to retrieve raw input data\n");
+        ok(raw->header.dwType == RIM_TYPEMOUSE || raw->header.dwType == RIM_TYPEKEYBOARD,
+            "Raw input data entry must be from mouse or keyboard\n");
+        ret3 = pDefRawInputProc(&raw, 1, sizeof(RAWINPUTHEADER));
+        HeapFree(GetProcessHeap(), 0, raw);
+        wm_input_recieved = TRUE;
+        return ret3;
+    }
+    return DefWindowProcA(hWnd, msg, wParam, lParam);
+}
+
+#define ID_TIMER 1
+
+static void timer_proc(HWND hParent, UINT uMsg, UINT uEventID, DWORD dwTimer)
+{
+    PostQuitMessage(0);
+}
+
+static HWND test_get_raw_input_data_simulation_setup(HANDLE hInstance, const char *class_name,
+    RAWINPUTDEVICE *device, INPUT *input, UINT input_count)
+{
+    MSG msg;
+    BOOL ret;
+
+    HWND hWnd = CreateWindowA(class_name, "GetRawInputDataTest",
+        WS_OVERLAPPEDWINDOW, 10, 10, 200, 200,
+        NULL, NULL, hInstance, NULL);
+    assert(hWnd);
+
+    ShowWindow(hWnd, SW_SHOW);
+    SetWindowPos(hWnd, HWND_TOPMOST, 10, 10, 200, 200, SWP_NOSIZE|SWP_NOMOVE);
+    SetForegroundWindow(hWnd);
+    UpdateWindow(hWnd);
+    SetFocus(hWnd);
+
+    wm_input_recieved                = FALSE;
+    legacy_mouse_message_recieved    = FALSE;
+    legacy_keyboard_message_recieved = FALSE;
+
+    device->hwndTarget = hWnd;
+    ret = pRegisterRawInputDevices(device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Failed to register raw input devices: %u\n", GetLastError());
+
+    pSendInput(input_count, input, sizeof(INPUT));
+
+    /* Give half a second of running time for each test to be sure all messages are processed */
+    SetTimer(hWnd, ID_TIMER, 500, (TIMERPROC)timer_proc);
+
+    while (1 == 1)
+    {
+        ret = GetMessageA(&msg, NULL, 0, 0);
+        if (!ret || ret == (BOOL)-1)
+            break;
+        TranslateMessage(&msg);
+        DispatchMessageA(&msg);
+    }
+
+    ok(ret != -1, "Error getting window message: %u\n", GetLastError());
+    ok(wm_input_recieved, "WM_INPUT was not received\n");
+
+    return hWnd;
+}
+
+static void test_get_raw_input_data_simulation_teardown(HWND hWnd, RAWINPUTDEVICE *device)
+{
+    BOOL ret;
+    UINT size, ret2;
+    DWORD count;
+    RAWINPUT *raw;
+
+    KillTimer(hWnd, ID_TIMER);
+
+    device->dwFlags    = RIDEV_REMOVE | (device->usUsage == 0 ? RIDEV_PAGEONLY : 0);
+    device->hwndTarget = NULL;
+    ret = pRegisterRawInputDevices(device, 1, sizeof(RAWINPUTDEVICE));
+    ok(ret, "Failed to unregister raw input device: %u\n", GetLastError());
+
+    count = 0xdeadbeef;
+    ret2 = pGetRegisteredRawInputDevices(NULL, &count, sizeof(RAWINPUTDEVICE));
+    ok(ret2 == 0 && count == 0, "Given (NULL, &count, sizeof), "
+        "GetRegisteredRawInputDevices should return that no devices are registered\n");
+
+    DestroyWindow(hWnd);
+
+    /* Clear raw input buffer */
+    ret2 = pGetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER));
+    if (ret2 == 0 && size > 0 &&
+        (raw = HeapAlloc(GetProcessHeap(), 0, size * sizeof(RAWINPUT))))
+    {
+        pGetRawInputBuffer(raw, &size, sizeof(RAWINPUTHEADER));
+        HeapFree(GetProcessHeap(), 0, raw);
+    }
+}
+
+static void test_get_raw_input_data_simulation(void)
+{
+    HWND hWnd;
+    WNDCLASSA wclass;
+    HANDLE hInstance = GetModuleHandleA( NULL );
+    INPUT mouse_input[5], keyboard_input;
+    ATOM registration;
+    RAWINPUTDEVICE device;
+    unsigned int i;
+
+    if (!pRegisterRawInputDevices || !pGetRawInputData || !pDefRawInputProc ||
+        !pGetRawInputBuffer || !pSendInput)
+    {
+        win_skip("Functions required to perform raw input simulation are not available\n");
+        return;
+    }
+
+    wclass.lpszClassName = "GetRawInputDataTestClass";
+    wclass.style         = CS_HREDRAW | CS_VREDRAW;
+    wclass.lpfnWndProc   = get_raw_input_data_wnd_proc;
+    wclass.hInstance     = hInstance;
+    wclass.hIcon         = LoadIconA(0, IDI_APPLICATION);
+    wclass.hCursor       = LoadCursorA(NULL, IDC_ARROW);
+    wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+    wclass.lpszMenuName  = NULL;
+    wclass.cbClsExtra    = 0;
+    wclass.cbWndExtra    = 0;
+    registration = RegisterClassA(&wclass);
+    assert(registration);
+
+    /* Setup fixtures */
+    device.usUsagePage = HID_USAGE_PAGE_GENERIC;
+
+    memset(&keyboard_input, 0, sizeof(keyboard_input));
+    keyboard_input.type   = INPUT_KEYBOARD;
+    keyboard_input.ki.wVk = VK_SPACE;
+
+    /* Be sure to move over the window, because the absolute window position on the screen
+       depends on how desktop widgets are placed */
+    memset(&mouse_input, 0, sizeof(mouse_input));
+    mouse_input[0].type           = INPUT_MOUSE;
+    mouse_input[0].mi.dx          = mouse_input[0].mi.dy = 15;
+    mouse_input[0].mi.dwFlags     = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
+    mouse_input[1].type           = INPUT_MOUSE;
+    mouse_input[1].mi.mouseData   = 0x0078;
+    mouse_input[1].mi.dwFlags     = MOUSEEVENTF_WHEEL;
+    for (i = 2; i < sizeof(mouse_input) / sizeof(mouse_input[0]); i++)
+    {
+        mouse_input[i].type       = INPUT_MOUSE;
+        mouse_input[i].mi.dx      = mouse_input[i].mi.dy = 30;
+        mouse_input[i].mi.dwFlags = MOUSEEVENTF_MOVE;
+    }
+
+    /* Test WM_INPUT for mouse */
+    device.usUsage = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags = 0;
+
+    hWnd = test_get_raw_input_data_simulation_setup(hInstance, wclass.lpszClassName, &device,
+        mouse_input, 5);
+    ok(legacy_mouse_message_recieved, "Should have received legacy mouse messages\n");
+    test_get_raw_input_data_simulation_teardown(hWnd, &device);
+
+    /* Test WM_INPUT for keyboard */
+    device.usUsage = HID_USAGE_GENERIC_KEYBOARD;
+    device.dwFlags = 0;
+
+    hWnd = test_get_raw_input_data_simulation_setup(hInstance, wclass.lpszClassName, &device,
+        &keyboard_input, 1);
+    ok(legacy_keyboard_message_recieved, "Should have received legacy keyboard messages\n");
+    test_get_raw_input_data_simulation_teardown(hWnd, &device);
+
+    /* Test RIDEV_PAGEONLY using mouse */
+    device.usUsage = 0;
+    device.dwFlags = RIDEV_PAGEONLY;
+
+    hWnd = test_get_raw_input_data_simulation_setup(hInstance, wclass.lpszClassName, &device,
+        mouse_input, 5);
+    ok(legacy_mouse_message_recieved, "Should have received legacy mouse messages\n");
+    test_get_raw_input_data_simulation_teardown(hWnd, &device);
+
+    /* Test RIDEV_PAGEONLY using keyboard */
+    device.usUsage = 0;
+    device.dwFlags = RIDEV_PAGEONLY;
+
+    hWnd = test_get_raw_input_data_simulation_setup(hInstance, wclass.lpszClassName, &device,
+        &keyboard_input, 1);
+    ok(legacy_keyboard_message_recieved, "Should have received legacy keyboard messages\n");
+    test_get_raw_input_data_simulation_teardown(hWnd, &device);
+
+    /* Test RIDEV_NOLEGACY for mouse */
+    device.usUsage = HID_USAGE_GENERIC_MOUSE;
+    device.dwFlags = RIDEV_NOLEGACY;
+
+    hWnd = test_get_raw_input_data_simulation_setup(hInstance, wclass.lpszClassName, &device,
+        mouse_input, 5);
+    ok(!legacy_mouse_message_recieved, "Should have not received legacy mouse messages\n");
+    test_get_raw_input_data_simulation_teardown(hWnd, &device);
+
+    /* Test RIDEV_NOLEGACY for keyboard */
+    device.usUsage = HID_USAGE_GENERIC_KEYBOARD;
+    device.dwFlags = RIDEV_NOLEGACY;
+
+    hWnd = test_get_raw_input_data_simulation_setup(hInstance, wclass.lpszClassName, &device,
+        &keyboard_input, 1);
+    ok(!legacy_keyboard_message_recieved, "Should have not received legacy keyboard messages\n");
+    test_get_raw_input_data_simulation_teardown(hWnd, &device);
+}
+
START_TEST(input)
{
     init_function_pointers();
@@ -1617,6 +2589,17 @@ START_TEST(input)
     test_get_async_key_state();
     test_keyboard_layout_name();

+    test_def_raw_input_proc();
+    test_get_raw_input_device_list();
+    test_get_raw_input_device_info_w();
+    test_get_raw_input_device_info_a();
+    test_register_raw_input_devices();
+    test_get_registered_raw_input_devices();
+    test_register_raw_input_devices_with_flags();
+    test_get_raw_input_buffer();
+    test_get_raw_input_data();
+    test_get_raw_input_data_simulation();
+
     if(pGetMouseMovePointsEx)
         test_GetMouseMovePointsEx();
     else
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index ee438b4..6399f2f 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -4878,6 +4878,91 @@ struct set_suspend_context_reply
};


+
+struct get_raw_input_device_list_request
+{
+    struct request_header __header;
+    unsigned int report_size_only;
+};
+struct get_raw_input_device_list_reply
+{
+    struct reply_header __header;
+    unsigned int num_devices;
+    /* VARARG(devices,bytes); */
+    char __pad_12[4];
+};
+
+
+struct register_raw_input_device_request
+{
+    struct request_header __header;
+    unsigned short usage_page;
+    unsigned short usage;
+    unsigned int flags;
+    user_handle_t target_window;
+};
+struct register_raw_input_device_reply
+{
+    struct reply_header __header;
+};
+#define REGISTER_RAW_INPUT_DEVICE_REMOVE       0x0001
+#define REGISTER_RAW_INPUT_DEVICE_PAGEONLY     0x0002
+#define REGISTER_RAW_INPUT_DEVICE_EXCLUDE      0x0004
+#define REGISTER_RAW_INPUT_DEVICE_NOLEGACY     0x0008
+#define REGISTER_RAW_INPUT_DEVICE_NOHOTKEYS    0x0010
+#define REGISTER_RAW_INPUT_DEVICE_CAPTUREMOUSE 0x0020
+#define REGISTER_RAW_INPUT_DEVICE_APPKEYS      0x0040
+#define REGISTER_RAW_INPUT_DEVICE_INPUTSINK    0x0080
+#define REGISTER_RAW_INPUT_DEVICE_EXINPUTSINK  0x0100
+#define REGISTER_RAW_INPUT_DEVICE_DEVNOTIFY    0x0200
+
+
+struct get_registered_raw_input_devices_request
+{
+    struct request_header __header;
+    unsigned int report_size_only;
+};
+struct get_registered_raw_input_devices_reply
+{
+    struct reply_header __header;
+    unsigned int num_devices;
+    /* VARARG(devices,bytes); */
+    char __pad_12[4];
+};
+
+
+struct get_raw_input_device_info_request
+{
+    struct request_header __header;
+    user_handle_t handle;
+    unsigned int command;
+    unsigned int report_size_only;
+};
+struct get_raw_input_device_info_reply
+{
+    struct reply_header __header;
+    data_size_t size;
+    /* VARARG(info,bytes); */
+    char __pad_12[4];
+};
+
+
+struct get_raw_input_data_request
+{
+    struct request_header __header;
+    user_handle_t handle;
+    unsigned int command;
+    unsigned int report_size_only;
+};
+struct get_raw_input_data_reply
+{
+    struct reply_header __header;
+    data_size_t size;
+    /* VARARG(data,bytes); */
+    char __pad_12[4];
+};
+
+
enum request
{
     REQ_new_process,
@@ -5127,6 +5212,11 @@ enum request
     REQ_set_cursor,
     REQ_get_suspend_context,
     REQ_set_suspend_context,
+    REQ_get_raw_input_device_list,
+    REQ_register_raw_input_device,
+    REQ_get_registered_raw_input_devices,
+    REQ_get_raw_input_device_info,
+    REQ_get_raw_input_data,
     REQ_NB_REQUESTS
};

@@ -5381,6 +5471,11 @@ union generic_request
     struct set_cursor_request set_cursor_request;
     struct get_suspend_context_request get_suspend_context_request;
     struct set_suspend_context_request set_suspend_context_request;
+    struct get_raw_input_device_list_request get_raw_input_device_list_request;
+    struct register_raw_input_device_request register_raw_input_device_request;
+    struct get_registered_raw_input_devices_request get_registered_raw_input_devices_request;
+    struct get_raw_input_device_info_request get_raw_input_device_info_request;
+    struct get_raw_input_data_request get_raw_input_data_request;
};
union generic_reply
{
@@ -5633,8 +5728,13 @@ union generic_reply
     struct set_cursor_reply set_cursor_reply;
     struct get_suspend_context_reply get_suspend_context_reply;
     struct set_suspend_context_reply set_suspend_context_reply;
+    struct get_raw_input_device_list_reply get_raw_input_device_list_reply;
+    struct register_raw_input_device_reply register_raw_input_device_reply;
+    struct get_registered_raw_input_devices_reply get_registered_raw_input_devices_reply;
+    struct get_raw_input_device_info_reply get_raw_input_device_info_reply;
+    struct get_raw_input_data_reply get_raw_input_data_reply;
};

-#define SERVER_PROTOCOL_VERSION 425
+#define SERVER_PROTOCOL_VERSION 430

#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/Makefile.in b/server/Makefile.in
index a2f1a52..c12b2df 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -28,6 +28,7 @@ C_SRCS = \
procfs.c \
ptrace.c \
queue.c \
+ raw_input.c \
region.c \
registry.c \
request.c \
diff --git a/server/process.c b/server/process.c
index c88c89b..3702333 100644
--- a/server/process.c
+++ b/server/process.c
@@ -48,6 +48,7 @@
#include "request.h"
#include "user.h"
#include "security.h"
+#include "raw_input.h"

/* process structure */

@@ -333,10 +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;
diff --git a/server/process.h b/server/process.h
index da51a0e..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;
@@ -81,6 +82,10 @@ struct process
     client_ptr_t         peb;             /* PEB address in client address space */
     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 123f16a..f147037 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3365,3 +3365,58 @@ enum coords_relative
@REQ(set_suspend_context)
     VARARG(context,context);   /* thread context */
@END
+
+
+/* Get the raw input device list */
+@REQ(get_raw_input_device_list)
+    unsigned int report_size_only; /* reply only with the device count */
+@REPLY
+    unsigned int num_devices;      /* number of raw input device in the system */
+    VARARG(devices,bytes);         /* RAWINPUTDEVICELIST structures */
+@END
+
+/* Register a raw input device */
+@REQ(register_raw_input_device)
+    unsigned short usage_page;     /* usage page of the device group to register to */
+    unsigned short usage;          /* usage id of the device to register to */
+    unsigned int flags;            /* configuration of the registration (see below) */
+    user_handle_t target_window;   /* optional window handle to receive input messages */
+@END
+#define REGISTER_RAW_INPUT_DEVICE_REMOVE       0x0001
+#define REGISTER_RAW_INPUT_DEVICE_PAGEONLY     0x0002
+#define REGISTER_RAW_INPUT_DEVICE_EXCLUDE      0x0004
+#define REGISTER_RAW_INPUT_DEVICE_NOLEGACY     0x0008
+#define REGISTER_RAW_INPUT_DEVICE_NOHOTKEYS    0x0010
+#define REGISTER_RAW_INPUT_DEVICE_CAPTUREMOUSE 0x0020
+#define REGISTER_RAW_INPUT_DEVICE_APPKEYS      0x0040
+#define REGISTER_RAW_INPUT_DEVICE_INPUTSINK    0x0080
+#define REGISTER_RAW_INPUT_DEVICE_EXINPUTSINK  0x0100
+#define REGISTER_RAW_INPUT_DEVICE_DEVNOTIFY    0x0200
+
+/* Get the registered raw input devices */
+@REQ(get_registered_raw_input_devices)
+    unsigned int report_size_only; /* reply only with the device count */
+@REPLY
+    unsigned int num_devices;      /* number of raw input device registrations */
+    VARARG(devices,bytes);         /* RAWINPUTDEVICE structures */
+@END
+
+/* Get the raw input device info */
+@REQ(get_raw_input_device_info)
+    user_handle_t handle;          /* raw input device handle */
+    unsigned int command;          /* desired characteristic of the device */
+    unsigned int report_size_only; /* reply only with the required size to store the data */
+@REPLY
+    data_size_t size;              /* size of the data about the device */
+    VARARG(info,bytes);            /* string or data structure about the device */
+@END
+
+/* 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 required size to store the data */
+@REPLY
+    data_size_t size;              /* size of the data */
+    VARARG(data,bytes);            /* RAWINPUTHEADER or RAWINPUT data structure */
+@END
diff --git a/server/queue.c b/server/queue.c
index 03b0e92..577126c 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))
@@ -437,6 +438,12 @@ static inline int is_keyboard_msg( struct message *msg )
     return (msg->msg >= WM_KEYFIRST && msg->msg <= WM_KEYLAST);
}

+/* check whether msg is a mouse message */
+static inline int is_mouse_msg( struct message *msg )
+{
+    return (msg->msg >= WM_MOUSEFIRST && msg->msg <= WM_MOUSELAST);
+}
+
/* check if message is matched by the filter */
static inline int check_msg_filter( unsigned int msg, unsigned int first, unsigned int last )
{
@@ -1455,7 +1462,10 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg
     if (win != desktop->cursor.win) always_queue = 1;
     desktop->cursor.win = win;

-    if (!always_queue || merge_message( input, msg )) free_message( msg );
+    if ((is_keyboard_msg( msg ) && is_nolegacy_set_for_raw_input_keyboard()) ||
+            (is_mouse_msg( msg ) && is_nolegacy_set_for_raw_input_mouse()) ||
+            !always_queue || merge_message( input, msg ))
+        free_message( msg );
     else
     {
         msg->unique_id = 0;  /* will be set once we return it to the app */
@@ -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
new file mode 100644
index 0000000..3721187
--- /dev/null
+++ b/server/raw_input.c
@@ -0,0 +1,582 @@
+/*
+ * Server-side Raw Input Handling
+ *
+ * Copyright (C) 2011 Vincas Miliūnas
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winternl.h"
+
+#include "object.h"
+#include "process.h"
+#include "request.h"
+#include "user.h"
+#include "raw_input.h"
+
+#define MOUSE_DEVICE_HANDLE    ((user_handle_t)0x01)
+#define KEYBOARD_DEVICE_HANDLE ((user_handle_t)0x02)
+
+#define HID_USAGE_PAGE_GENERIC     ((unsigned short)0x01)
+#define HID_USAGE_GENERIC_MOUSE    ((unsigned short)0x02)
+#define HID_USAGE_GENERIC_KEYBOARD ((unsigned short)0x06)
+
+struct raw_registration
+{
+    struct list    entry;
+    unsigned short usage_page;
+    unsigned short usage;
+    unsigned int   flags;
+    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;
+    const WCHAR      *name;
+    RID_DEVICE_INFO   info;
+};
+
+static const WCHAR mouse_raw_input_device_name[] =
+    {'W','I','N','E',' ','R','a','w',' ','I','n','p','u','t',' ',
+        'M','o','u','s','e','\0'};
+static const WCHAR keyboard_raw_input_device_name[] =
+    {'W','I','N','E',' ','R','a','w',' ','I','n','p','u','t',' ',
+        'K','e','y','b','o','a','r','d','\0'};
+
+/* standard raw input devices with typical device info values */
+static const struct raw_device raw_devices[] =
+{
+    {MOUSE_DEVICE_HANDLE, mouse_raw_input_device_name,
+        {sizeof( RID_DEVICE_INFO ), RIM_TYPEMOUSE, {.mouse = {1, 3, 100, FALSE}}}},
+    {KEYBOARD_DEVICE_HANDLE, keyboard_raw_input_device_name,
+        {sizeof( RID_DEVICE_INFO ), RIM_TYPEKEYBOARD, {.keyboard = {4, 0, 1, 12, 3, 101}}}}
+};
+#define NUM_RAW_DEVICES (sizeof( raw_devices ) / sizeof( raw_devices[0] ))
+
+/* Get the raw input device list */
+DECL_HANDLER(get_raw_input_device_list)
+{
+    unsigned int i, size_in_bytes;
+    RAWINPUTDEVICELIST *result;
+
+    reply->num_devices = NUM_RAW_DEVICES;
+    if (!reply->num_devices || req->report_size_only)
+        return;
+
+    size_in_bytes = reply->num_devices * sizeof( RAWINPUTDEVICELIST );
+    if (size_in_bytes > get_reply_max_size())
+    {
+        set_error( STATUS_BUFFER_TOO_SMALL );
+        return;
+    }
+
+    result = set_reply_data_size( size_in_bytes );
+    if (!result)
+    {
+        set_error( STATUS_NO_MEMORY );
+        return;
+    }
+
+    for (i = 0; i < reply->num_devices; i++)
+    {
+        /* Currently fake handles are provided, however they are only used to
+           identify the devices for the GetRawInputDeviceInfo function, thus it
+           should not create any undesirable side effects */
+        result[i].hDevice = (HANDLE)raw_devices[i].handle;
+        result[i].dwType  = raw_devices[i].info.dwType;
+    }
+}
+
+/* Get the raw input device info */
+DECL_HANDLER(get_raw_input_device_info)
+{
+    BOOL valid = FALSE;
+    unsigned int i, size_in_bytes;
+    void *source = NULL;
+
+    for (i = 0; i < NUM_RAW_DEVICES; i++)
+    {
+        if (raw_devices[i].handle != req->handle)
+            continue;
+        valid = TRUE;
+
+        switch (req->command)
+        {
+        case RIDI_DEVICENAME:
+            /* reply->size is the character count */
+            reply->size = lstrlenW( raw_devices[i].name ) + 1;
+            source      = (void *)raw_devices[i].name;
+            break;
+        case RIDI_DEVICEINFO:
+            reply->size = sizeof( RID_DEVICE_INFO );
+            source      = (void *)&raw_devices[i].info;
+            break;
+        case RIDI_PREPARSEDDATA:
+            /* No preparsed data available */
+            reply->size = 0;
+            break;
+        default:
+            set_error( STATUS_INVALID_PARAMETER );
+            break;
+        }
+        if (get_error() > 0 || req->report_size_only)
+            break;
+
+        size_in_bytes = req->command == RIDI_DEVICENAME ?
+            reply->size * sizeof( WCHAR ) : reply->size;
+        if (size_in_bytes > get_reply_max_size())
+        {
+            set_error( STATUS_BUFFER_TOO_SMALL );
+        }
+        else if (size_in_bytes > 0)
+        {
+            void *target = set_reply_data_size( size_in_bytes );
+            if (!target)
+            {
+                set_error( STATUS_NO_MEMORY );
+                break;
+            }
+
+            memcpy( target, source, size_in_bytes );
+        }
+        break;
+    }
+    if (!valid)
+        set_error( STATUS_INVALID_HANDLE );
+}
+
+/* Get the registered raw input devices */
+DECL_HANDLER(get_registered_raw_input_devices)
+{
+    unsigned int index = 0, size_in_bytes;
+    struct raw_registration *registration;
+    RAWINPUTDEVICE *result;
+
+    reply->num_devices = list_count(&current->process->raw_registered);
+    if (!reply->num_devices || req->report_size_only)
+        return;
+
+    size_in_bytes = reply->num_devices * sizeof( RAWINPUTDEVICE );
+    if (size_in_bytes > get_reply_max_size())
+    {
+        set_error( STATUS_BUFFER_TOO_SMALL );
+        return;
+    }
+
+    result = set_reply_data_size( size_in_bytes );
+    if (!result)
+    {
+        set_error( STATUS_NO_MEMORY );
+        return;
+    }
+
+    LIST_FOR_EACH_ENTRY( registration, &current->process->raw_registered,
+        struct raw_registration, entry )
+    {
+        result[index].usUsagePage = registration->usage_page;
+        result[index].usUsage     = registration->usage;
+        result[index].dwFlags     = registration->flags;
+        result[index].hwndTarget  = (HWND)registration->target_window;
+        index += 1;
+    }
+}
+
+/* Register a raw input device */
+DECL_HANDLER(register_raw_input_device)
+{
+    struct raw_registration *registration;
+    LIST_FOR_EACH_ENTRY( registration, &current->process->raw_registered,
+        struct raw_registration, entry )
+    {
+        /* * They must be on the same usage page
+           * both marked as PAGEONLY or
+             both not marked as PAGEONLY and have identical usage ids */
+        if (registration->usage_page != req->usage_page ||
+                (!(registration->flags & REGISTER_RAW_INPUT_DEVICE_PAGEONLY &&
+                req->flags & REGISTER_RAW_INPUT_DEVICE_PAGEONLY) &&
+                (registration->flags & REGISTER_RAW_INPUT_DEVICE_PAGEONLY ||
+                req->flags & REGISTER_RAW_INPUT_DEVICE_PAGEONLY ||
+                registration->usage != req->usage)))
+            continue;
+
+        if (req->flags & REGISTER_RAW_INPUT_DEVICE_REMOVE)
+        {
+            list_remove( &registration->entry );
+            free( registration );
+            return;
+        }
+
+        /* Update existing registration */
+        registration->flags         = req->flags;
+        registration->target_window = req->target_window;
+        return;
+    }
+
+    if (req->flags & REGISTER_RAW_INPUT_DEVICE_REMOVE ||
+            !(registration = mem_alloc( sizeof( *registration ) )))
+        return;
+
+    registration->usage_page    = req->usage_page;
+    registration->usage         = req->usage;
+    registration->flags         = req->flags;
+    registration->target_window = req->target_window;
+
+    list_add_tail( &current->process->raw_registered, &registration->entry );
+}
+
+/* Get raw input data */
+DECL_HANDLER(get_raw_input_data)
+{
+    void *ptr;
+    struct raw_input *queued, *input = NULL;
+
+    LIST_FOR_EACH_ENTRY( queued, &current->process->raw_inputs, struct raw_input, entry )
+    {
+        if (queued->handle == req->handle)
+        {
+            input = queued;
+            break;
+        }
+    }
+    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 = sizeof( RAWINPUT );
+    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;
+}
+
+/* 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( &current->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, &current->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( &current->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 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, &current->process->raw_registered,
+        struct raw_registration, entry )
+    {
+        if (registration->usage_page != usage_page)
+            continue;
+        else if (registration->flags & REGISTER_RAW_INPUT_DEVICE_EXCLUDE &&
+                registration->usage == usage)
+            return NULL;
+        else if (registration->flags & REGISTER_RAW_INPUT_DEVICE_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( RAWINPUT );
+    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( RAWINPUT );
+    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 );
+}
+
+/* Check if nolegacy flag is set for a mouse device registration */
+BOOL is_nolegacy_set_for_raw_input_mouse(void)
+{
+    struct raw_registration *registration = find_registered_usage( HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE );
+    return registration ? registration->flags & REGISTER_RAW_INPUT_DEVICE_NOLEGACY : FALSE;
+}
+
+/* Check if nolegacy flag is set for a keyboard device registration */
+BOOL is_nolegacy_set_for_raw_input_keyboard(void)
+{
+    struct raw_registration *registration = find_registered_usage( HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD );
+    return registration ? registration->flags & REGISTER_RAW_INPUT_DEVICE_NOLEGACY : FALSE;
+}
diff --git a/server/raw_input.h b/server/raw_input.h
new file mode 100644
index 0000000..c8cf0b1
--- /dev/null
+++ b/server/raw_input.h
@@ -0,0 +1,39 @@
+/*
+ * Server-side Raw Input Queuing Functions
+ *
+ * Copyright (C) 2011 Vincas Miliūnas
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_SERVER_RAW_INPUT_H
+#define __WINE_SERVER_RAW_INPUT_H
+
+#include "wine/server_protocol.h"
+
+#define MAX_RAW_INPUT_QUEUE_LENGTH 32
+
+struct raw_input;
+
+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);
+
+extern BOOL is_nolegacy_set_for_raw_input_mouse(void);
+extern BOOL is_nolegacy_set_for_raw_input_keyboard(void);
+
+#endif  /* __WINE_SERVER_RAW_INPUT_H */
diff --git a/server/request.h b/server/request.h
index d2ca2f6..848997e 100644
--- a/server/request.h
+++ b/server/request.h
@@ -358,6 +358,11 @@ DECL_HANDLER(free_user_handle);
DECL_HANDLER(set_cursor);
DECL_HANDLER(get_suspend_context);
DECL_HANDLER(set_suspend_context);
+DECL_HANDLER(get_raw_input_device_list);
+DECL_HANDLER(register_raw_input_device);
+DECL_HANDLER(get_registered_raw_input_devices);
+DECL_HANDLER(get_raw_input_device_info);
+DECL_HANDLER(get_raw_input_data);

#ifdef WANT_REQUEST_HANDLERS

@@ -611,6 +616,11 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_set_cursor,
     (req_handler)req_get_suspend_context,
     (req_handler)req_set_suspend_context,
+    (req_handler)req_get_raw_input_device_list,
+    (req_handler)req_register_raw_input_device,
+    (req_handler)req_get_registered_raw_input_devices,
+    (req_handler)req_get_raw_input_device_info,
+    (req_handler)req_get_raw_input_data,
};

C_ASSERT( sizeof(affinity_t) == 8 );
@@ -2134,6 +2144,31 @@ C_ASSERT( sizeof(struct set_cursor_reply) == 56 );
C_ASSERT( sizeof(struct get_suspend_context_request) == 16 );
C_ASSERT( sizeof(struct get_suspend_context_reply) == 8 );
C_ASSERT( sizeof(struct set_suspend_context_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_device_list_request, report_size_only) == 12 );
+C_ASSERT( sizeof(struct get_raw_input_device_list_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_device_list_reply, num_devices) == 8 );
+C_ASSERT( sizeof(struct get_raw_input_device_list_reply) == 16 );
+C_ASSERT( FIELD_OFFSET(struct register_raw_input_device_request, usage_page) == 12 );
+C_ASSERT( FIELD_OFFSET(struct register_raw_input_device_request, usage) == 14 );
+C_ASSERT( FIELD_OFFSET(struct register_raw_input_device_request, flags) == 16 );
+C_ASSERT( FIELD_OFFSET(struct register_raw_input_device_request, target_window) == 20 );
+C_ASSERT( sizeof(struct register_raw_input_device_request) == 24 );
+C_ASSERT( FIELD_OFFSET(struct get_registered_raw_input_devices_request, report_size_only) == 12 );
+C_ASSERT( sizeof(struct get_registered_raw_input_devices_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_registered_raw_input_devices_reply, num_devices) == 8 );
+C_ASSERT( sizeof(struct get_registered_raw_input_devices_reply) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_device_info_request, handle) == 12 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_device_info_request, command) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_device_info_request, report_size_only) == 20 );
+C_ASSERT( sizeof(struct get_raw_input_device_info_request) == 24 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_device_info_reply, size) == 8 );
+C_ASSERT( sizeof(struct get_raw_input_device_info_reply) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_data_request, handle) == 12 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_data_request, command) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_data_request, report_size_only) == 20 );
+C_ASSERT( sizeof(struct get_raw_input_data_request) == 24 );
+C_ASSERT( FIELD_OFFSET(struct get_raw_input_data_reply, size) == 8 );
+C_ASSERT( sizeof(struct get_raw_input_data_reply) == 16 );

#endif  /* WANT_REQUEST_HANDLERS */

diff --git a/server/trace.c b/server/trace.c
index 37ea216..060d3fc 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3903,6 +3903,62 @@ static void dump_set_suspend_context_request( const struct set_suspend_context_r
     dump_varargs_context( " context=", cur_size );
}

+static void dump_get_raw_input_device_list_request( const struct get_raw_input_device_list_request *req )
+{
+    fprintf( stderr, " report_size_only=%08x", req->report_size_only );
+}
+
+static void dump_get_raw_input_device_list_reply( const struct get_raw_input_device_list_reply *req )
+{
+    fprintf( stderr, " num_devices=%08x", req->num_devices );
+    dump_varargs_bytes( ", devices=", cur_size );
+}
+
+static void dump_register_raw_input_device_request( const struct register_raw_input_device_request *req )
+{
+    fprintf( stderr, " usage_page=%04x", req->usage_page );
+    fprintf( stderr, ", usage=%04x", req->usage );
+    fprintf( stderr, ", flags=%08x", req->flags );
+    fprintf( stderr, ", target_window=%08x", req->target_window );
+}
+
+static void dump_get_registered_raw_input_devices_request( const struct get_registered_raw_input_devices_request *req )
+{
+    fprintf( stderr, " report_size_only=%08x", req->report_size_only );
+}
+
+static void dump_get_registered_raw_input_devices_reply( const struct get_registered_raw_input_devices_reply *req )
+{
+    fprintf( stderr, " num_devices=%08x", req->num_devices );
+    dump_varargs_bytes( ", devices=", cur_size );
+}
+
+static void dump_get_raw_input_device_info_request( const struct get_raw_input_device_info_request *req )
+{
+    fprintf( stderr, " handle=%08x", req->handle );
+    fprintf( stderr, ", command=%08x", req->command );
+    fprintf( stderr, ", report_size_only=%08x", req->report_size_only );
+}
+
+static void dump_get_raw_input_device_info_reply( const struct get_raw_input_device_info_reply *req )
+{
+    fprintf( stderr, " size=%u", req->size );
+    dump_varargs_bytes( ", info=", cur_size );
+}
+
+static void dump_get_raw_input_data_request( const struct get_raw_input_data_request *req )
+{
+    fprintf( stderr, " handle=%08x", req->handle );
+    fprintf( stderr, ", command=%08x", req->command );
+    fprintf( stderr, ", report_size_only=%08x", req->report_size_only );
+}
+
+static void dump_get_raw_input_data_reply( const struct get_raw_input_data_reply *req )
+{
+    fprintf( stderr, " size=%u", req->size );
+    dump_varargs_bytes( ", data=", cur_size );
+}
+
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_new_process_request,
     (dump_func)dump_get_new_process_info_request,
@@ -4151,6 +4207,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_set_cursor_request,
     (dump_func)dump_get_suspend_context_request,
     (dump_func)dump_set_suspend_context_request,
+    (dump_func)dump_get_raw_input_device_list_request,
+    (dump_func)dump_register_raw_input_device_request,
+    (dump_func)dump_get_registered_raw_input_devices_request,
+    (dump_func)dump_get_raw_input_device_info_request,
+    (dump_func)dump_get_raw_input_data_request,
};

static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -4401,6 +4462,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_set_cursor_reply,
     (dump_func)dump_get_suspend_context_reply,
     NULL,
+    (dump_func)dump_get_raw_input_device_list_reply,
+    NULL,
+    (dump_func)dump_get_registered_raw_input_devices_reply,
+    (dump_func)dump_get_raw_input_device_info_reply,
+    (dump_func)dump_get_raw_input_data_reply,
};

static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -4651,6 +4717,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "set_cursor",
     "get_suspend_context",
     "set_suspend_context",
+    "get_raw_input_device_list",
+    "register_raw_input_device",
+    "get_registered_raw_input_devices",
+    "get_raw_input_device_info",
+    "get_raw_input_data",
};

static const struct



if

@tokurugur, değiştirmeniz gereken dosya a/dlls/user32/input.c. Bu dosyanın tam yolunu öğreniniz, elinizdeki yamayı da input.c olarak kaydedin. Eski input.c'nin olduğu dizindeyken patch -b input.c < /yamanın/yolu/input.c komutunu veriniz. Ya da patch -b -p1 < /yamanın/yolu/input.c

tokurugur

Alıntı yapılan: if - 28 Şubat 2012 - 20:45:05
@tokurugur, değiştirmeniz gereken dosya a/dlls/user32/input.c. Bu dosyanın tam yolunu öğreniniz, elinizdeki yamayı da input.c olarak kaydedin. Eski input.c'nin olduğu dizindeyken patch -b input.c < /yamanın/yolu/input.c komutunu veriniz. Ya da patch -b -p1 < /yamanın/yolu/input.c

dosya yolunu bir türlü bulamıyorum da biraz daha yardımcı olabilir misiniz?

if

@tokurugur, sudo find / -name input.c ne diyor?

ebubekirs

Ev dizininiz altında .wine klasörü olmalı. Orada olabilir bir ihtimal.

Not: @if belirtmiş arama yöntemini.
Dünyaya gelen de benim, dünyadan giden de benim

tokurugur

Alıntı yapılan: if - 28 Şubat 2012 - 21:21:04
@tokurugur, sudo find / -name input.c ne diyor?
siziede zahmet verdim ama öyle bir dosya bulamıyor?

if

#6
@tokurugur, önemli değil. Hata kaydına baktım da o dosya wine kaynağının içerisindeymiş ve http://osdir.com/ml/wine-bugs/2011-10/msg05385.html bağlantısında ne yapılması gerektiği anlatılmış. http://sourceforge.net/projects/wine/files/Source/ bağlantısından kaynağı indirip açacaksınız, yamayı uygulayacaksınız, ./tools/make_requests komutunu vereceksiniz ve ardından derlemeye geçeceksiniz. Tabi bundan önce kurulu wine'ı kaldırmanız gerek.

Bu yama 1.3.2 ve sonraki sürümlerle çalışıyormuş. wine-1.4-rc1.tar.bz2 gibi rc içeren kaynakları indirmeyin. 1.3.2 ve üzeri bir sürüm kaynağını indirin. Açtığınızda Diyelim dosyanın adı wine-1.3.2 oldu ve bu dosya ~/Masaüstü dizininde. Uygulamanız gereken komutlar hemen hemen şöyledir: cd ~/Masaüstü/wine-1.3.2
ile dosyanın içerisine girersiniz. input.c muhatemelen bu dosya içerisinde bulunan src dosyası altındadır ama siz yine de nerede olduğunu bulunuz. Diyelim src dizinindeyse: cd src
patch -b < /yamanın/yolu/input.c
ile yamayı eklersiniz. Sonra cd ..
./tools/make_requests
./configure
make
sudo make install
ile kurarsınız.

tokurugur

#7
hemen deniyorum çok teşekkür ederim.


Mesaj tekrarı yüzünden mesajınız birleştirildi. Bu mesajın gönderim tarihi : 28 Şubat 2012 - 22:24:20

Alıntı yapılan: if - 28 Şubat 2012 - 21:37:07
@tokurugur, önemli değil. Hata kaydına baktım da o dosya wine kaynağının içerisindeymiş ve http://osdir.com/ml/wine-bugs/2011-10/msg05385.html bağlantısında ne yapılması gerektiği anlatılmış. http://sourceforge.net/projects/wine/files/Source/ bağlantısından kaynağı indirip açacaksınız, yamayı uygulayacaksınız, ./tools/make_requests komutunu vereceksiniz ve ardından derlemeye geçeceksiniz. Tabi bundan önce kurulu wine'ı kaldırmanız gerek.

Bu yama 1.3.2 ve sonraki sürümlerle çalışıyormuş. wine-1.4-rc1.tar.bz2 gibi rc içeren kaynakları indirmeyin. 1.3.2 ve üzeri bir sürüm kaynağını indirin. Açtığınızda Diyelim dosyanın adı wine-1.3.2 oldu ve bu dosya ~/Masaüstü dizininde. Uygulamanız gereken komutlar hemen hemen şöyledir: cd ~/Masaüstü/wine-1.3.2
ile dosyanın içerisine girersiniz. input.c muhatemelen bu dosya içerisinde bulunan src dosyası altındadır ama siz yine de nerede olduğunu bulunuz. Diyelim src dizinindeyse: cd src
patch -b < /yamanın/yolu/input.c
ile yamayı eklersiniz. Sonra cd ..
./tools/make_requests
./configure
make
sudo make install
ile kurarsınız.

hocam dediklerinizi denedim ve alttaki gibi bir sonuç çıkıyor;
tokurugur@Tokur-HPC:~/wine-1.3.31/dlls/user32$ patch -b < /home/tokurugur/wine-1.3.31/dlls/user32/input.c
patching file input.c
Hunk #1 FAILED at 476.
Hunk #2 FAILED at 501.
Hunk #3 FAILED at 513.
Hunk #4 FAILED at 524.
Hunk #5 FAILED at 546.
Hunk #6 FAILED at 557.
6 out of 6 hunks FAILED -- saving rejects to file input.c.rej
patching file input.c
Hunk #1 FAILED at 77.
Hunk #2 FAILED at 160.
Hunk #3 FAILED at 1598.
Hunk #4 FAILED at 1617.
4 out of 4 hunks FAILED -- saving rejects to file input.c.rej
can't find file to patch at input line 1490
Perhaps you should have used the -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
|index ee438b4..6399f2f 100644
|--- a/include/wine/server_protocol.h
|+++ b/include/wine/server_protocol.h
--------------------------
File to patch:

KemalALKIN

Arkadaşım işin kolayı var:
www.playonlinux.com buradaki programı bilgisayarınıza kurun ismi playonlinux bunu neden önerdin dersen bunda istediğin kadar wine makinesi oluşturabilirisniz ayrı ayrı ve farklı farklı sürümler ile. Wine sürümlerini yönet diye bir kısım var oradan raw3 veya rawinput2 wine sürümlerini kurup kullanırsanız fare sorunu çözülmüş olan özel hazır wine ile keyfine bakarsınız. Örnek onlive programında işime yaradı.
www.tckemal.ist

if

@tokurugur, komutu şöyle vermemiz gerekmiş: patch -p1 < /yamanın/yolu/input.c

tokurugur

playonlinux ile çözdüm.
çok teşekkürler yardımlarınız için.

if

@tokurugur, çözülen başlıklara çözüldü etiketi için imzamdaki bağlantıdan faydalanabilirsiniz:)