Added full support for xbuttons (side mouse buttons).

diff --git a/dlls/user/message.c b/dlls/user/message.c
index aa5b4b3..f4d3694 100644
--- a/dlls/user/message.c
+++ b/dlls/user/message.c
@@ -47,7 +47,7 @@
 WINE_DECLARE_DEBUG_CHANNEL(key);
 
 #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
-#define WM_NCMOUSELAST  WM_NCMBUTTONDBLCLK
+#define WM_NCMOUSELAST  (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
 
 #define MAX_PACK_COUNT 4
 
@@ -1704,7 +1704,8 @@
 
     if ((msg->message == WM_LBUTTONDOWN) ||
         (msg->message == WM_RBUTTONDOWN) ||
-        (msg->message == WM_MBUTTONDOWN))
+        (msg->message == WM_MBUTTONDOWN) ||
+        (msg->message == WM_XBUTTONDOWN))
     {
         BOOL update = remove;
 
@@ -1718,6 +1719,7 @@
         {
            if ((msg->message == clk_msg.message) &&
                (msg->hwnd == clk_msg.hwnd) &&
+               (msg->wParam == clk_msg.wParam) &&
                (msg->time - clk_msg.time < GetDoubleClickTime()) &&
                (abs(msg->pt.x - clk_msg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK)/2) &&
                (abs(msg->pt.y - clk_msg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK)/2))
@@ -1774,7 +1776,8 @@
 
     if ((msg->message == WM_LBUTTONDOWN) ||
         (msg->message == WM_RBUTTONDOWN) ||
-        (msg->message == WM_MBUTTONDOWN))
+        (msg->message == WM_MBUTTONDOWN) ||
+        (msg->message == WM_XBUTTONDOWN))
     {
         /* Send the WM_PARENTNOTIFY,
          * note that even for double/nonclient clicks
diff --git a/dlls/x11drv/mouse.c b/dlls/x11drv/mouse.c
index 6a0c264..3379ee9 100644
--- a/dlls/x11drv/mouse.c
+++ b/dlls/x11drv/mouse.c
@@ -41,7 +41,14 @@
 
 /**********************************************************************/
 
-#define NB_BUTTONS   5     /* Windows can handle 3 buttons and the wheel too */
+#ifndef Button6Mask
+#define Button6Mask (1<<13)
+#endif
+#ifndef Button7Mask
+#define Button7Mask (1<<14)
+#endif
+
+#define NB_BUTTONS   7     /* Windows can handle 5 buttons and the wheel too */
 
 static const UINT button_down_flags[NB_BUTTONS] =
 {
@@ -49,7 +56,9 @@
     MOUSEEVENTF_MIDDLEDOWN,
     MOUSEEVENTF_RIGHTDOWN,
     MOUSEEVENTF_WHEEL,
-    MOUSEEVENTF_WHEEL
+    MOUSEEVENTF_WHEEL,
+    MOUSEEVENTF_XDOWN,
+    MOUSEEVENTF_XDOWN
 };
 
 static const UINT button_up_flags[NB_BUTTONS] =
@@ -58,7 +67,9 @@
     MOUSEEVENTF_MIDDLEUP,
     MOUSEEVENTF_RIGHTUP,
     0,
-    0
+    0,
+    MOUSEEVENTF_XUP,
+    MOUSEEVENTF_XUP
 };
 
 POINT cursor_pos;
@@ -89,6 +100,8 @@
     key_state_table[VK_LBUTTON] = (state & Button1Mask ? 0x80 : 0);
     key_state_table[VK_MBUTTON] = (state & Button2Mask ? 0x80 : 0);
     key_state_table[VK_RBUTTON] = (state & Button3Mask ? 0x80 : 0);
+    key_state_table[VK_XBUTTON1]= (state & Button6Mask ? 0x80 : 0);
+    key_state_table[VK_XBUTTON2]= (state & Button7Mask ? 0x80 : 0);
 }
 
 
@@ -130,7 +143,7 @@
 
     if (window != data->grab_window &&
         /* ignore event if a button is pressed, since the mouse is then grabbed too */
-        !(state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)))
+        !(state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask|Button6Mask|Button7Mask)))
     {
         SERVER_START_REQ( update_window_zorder )
         {
@@ -325,6 +338,18 @@
         queue_raw_mouse_message( WM_MOUSEWHEEL, hwnd, pt.x, pt.y, data, time,
                                  extra_info, injected_flags );
     }
+    if (flags & MOUSEEVENTF_XDOWN)
+    {
+        key_state_table[VK_XBUTTON1 + data - 1] |= 0xc0;
+        queue_raw_mouse_message( WM_XBUTTONDOWN, hwnd, pt.x, pt.y, data, time,
+                                 extra_info, injected_flags );
+    }
+    if (flags & MOUSEEVENTF_XUP)
+    {
+        key_state_table[VK_XBUTTON1 + data - 1] &= ~0x80;
+        queue_raw_mouse_message( WM_XBUTTONUP, hwnd, pt.x, pt.y, data, time,
+                                 extra_info, injected_flags );
+    }
 }
 
 
@@ -724,6 +749,12 @@
     case 4:
         wData = -WHEEL_DELTA;
         break;
+    case 5:
+        wData = XBUTTON1;
+        break;
+    case 6:
+        wData = XBUTTON2;
+        break;
     }
 
     update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
@@ -740,15 +771,26 @@
 {
     XButtonEvent *event = &xev->xbutton;
     int buttonNum = event->button - 1;
+    WORD wData = 0;
     POINT pt;
 
     if (buttonNum >= NB_BUTTONS || !button_up_flags[buttonNum]) return;
     if (!hwnd) return;
 
+    switch (buttonNum)
+    {
+    case 5:
+        wData = XBUTTON1;
+        break;
+    case 6:
+        wData = XBUTTON2;
+        break;
+    }
+
     update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
 
     X11DRV_send_mouse_input( hwnd, button_up_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE,
-                             pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
+                             pt.x, pt.y, wData, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
 }
 
 
diff --git a/include/winuser.h b/include/winuser.h
index 331e537..e6356a0 100644
--- a/include/winuser.h
+++ b/include/winuser.h
@@ -1115,6 +1115,9 @@
 #define WM_XBUTTONUP        0x020C
 #define WM_XBUTTONDBLCLK    0x020D
 
+#define XBUTTON1            0x0001
+#define XBUTTON2            0x0002
+
 #define WM_MOUSEFIRST       0x0200
 #define WM_MOUSELAST        0x020D
 
@@ -2558,6 +2561,8 @@
 #define MOUSEEVENTF_RIGHTUP     0x0010
 #define MOUSEEVENTF_MIDDLEDOWN  0x0020
 #define MOUSEEVENTF_MIDDLEUP    0x0040
+#define MOUSEEVENTF_XDOWN       0x0080
+#define MOUSEEVENTF_XUP         0x0100
 #define MOUSEEVENTF_WHEEL       0x0800
 #define MOUSEEVENTF_ABSOLUTE    0x8000