Actually return the number of events in Mouse_GetDeviceData (fixes
Wing Commander Prophecy). Added timestamp and sequence generation,
critical section for mousedata. Disabled mouse warping in
GetDeviceData for now (generates excess mouse events).

diff --git a/windows/dinput.c b/windows/dinput.c
index 5759f01..36b4ba8 100644
--- a/windows/dinput.c
+++ b/windows/dinput.c
@@ -20,6 +20,7 @@
 
 #include "config.h"
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 #include <assert.h>
 #ifdef HAVE_SYS_SIGNAL_H
@@ -76,20 +77,25 @@
         ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
         DWORD                           ref;
         GUID                            guid;
+
+	LPDIDATAFORMAT			df;
         /* SysMouseAImpl */
         BYTE                            absolute;
         /* Previous position for relative moves */
-        LONG prevX, prevY;
-        LPMOUSE_EVENT_PROC prev_handler;
-        HWND win;
-        DWORD win_centerX, win_centerY;
-        LPDIDEVICEOBJECTDATA data_queue;
-        int queue_pos, queue_len;
-        int need_warp;
-        int acquired;
-        HANDLE hEvent;
+        LONG				prevX, prevY;
+        LPMOUSE_EVENT_PROC		prev_handler;
+        HWND				win;
+        DWORD				win_centerX, win_centerY;
+        LPDIDEVICEOBJECTDATA 		data_queue;
+        int				queue_pos, queue_len;
+        int				need_warp;
+        int				acquired;
+        HANDLE				hEvent;
+	CRITICAL_SECTION		crit;
 };
 
+static int evsequence=0;
+
 
 /* UIDs for Wine "drivers".
    When enumerating each device supporting DInput, they have two UIDs :
@@ -161,43 +167,39 @@
 	LPVOID pvRef, DWORD dwFlags
 )
 {
-  ICOM_THIS(IDirectInputAImpl,iface);
-  DIDEVICEINSTANCEA devInstance;
-  int ret;
+	ICOM_THIS(IDirectInputAImpl,iface);
+	DIDEVICEINSTANCEA devInstance;
+	int ret;
 
-  TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
+	TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
 
-  devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
-  
-  if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
-  /* Return keyboard */
-    devInstance.guidInstance = GUID_SysKeyboard;         /* DInput's GUID */
-    devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
-    devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
-  strcpy(devInstance.tszInstanceName, "Keyboard");
-  strcpy(devInstance.tszProductName, "Wine Keyboard");
-  
-  ret = lpCallback(&devInstance, pvRef);
-    TRACE("Keyboard registered\n");
-  
-    if (ret == DIENUM_STOP)
-    return 0;
-  }
-  
-  if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
-  /* Return mouse */
-    devInstance.guidInstance = GUID_SysMouse;         /* DInput's GUID */
-    devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
-    devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
-  strcpy(devInstance.tszInstanceName, "Mouse");
-  strcpy(devInstance.tszProductName, "Wine Mouse");
-  
-  ret = lpCallback(&devInstance, pvRef);
-    TRACE("Mouse registered\n");
-  }
+	devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
+	if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
+		/* Return keyboard */
+		devInstance.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
+		devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
+		devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
+		strcpy(devInstance.tszInstanceName, "Keyboard");
+		strcpy(devInstance.tszProductName, "Wine Keyboard");
 
-  /* Should also do joystick enumerations.... */
+		ret = lpCallback(&devInstance, pvRef);
+		TRACE("Keyboard registered\n");
+		if (ret == DIENUM_STOP)
+			return 0;
+	}
   
+	if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_MOUSE)) {
+		/* Return mouse */
+		devInstance.guidInstance = GUID_SysMouse;/* DInput's GUID */
+		devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
+		devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
+		strcpy(devInstance.tszInstanceName, "Mouse");
+		strcpy(devInstance.tszProductName, "Wine Mouse");
+
+		ret = lpCallback(&devInstance, pvRef);
+		TRACE("Mouse registered\n");
+	}
+	/* Should also do joystick enumerations.... */
 	return 0;
 }
 
@@ -239,10 +241,12 @@
 	}
 	if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) ||             /* Generic Mouse */
 	    (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
-                SysKeyboardAImpl* newDevice;
+                SysMouseAImpl* newDevice;
 		newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
 		newDevice->ref = 1;
 		newDevice->lpvtbl = &SysMouseAvt;
+		InitializeCriticalSection(&(newDevice->crit));
+		MakeCriticalSectionGlobal(&(newDevice->crit));
 		memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
                 *pdev=(IDirectInputDeviceA*)newDevice;
 		return DI_OK;
@@ -414,12 +418,19 @@
 )
 {
 	ICOM_THIS(SysKeyboardAImpl,iface);
+	HRESULT	ret;
+	int	i;
 
 	TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
 	      This,dodsize,dod,entries,entries?*entries:0,flags);
 
-	return KEYBOARD_Driver->pGetDIData(
+	ret=KEYBOARD_Driver->pGetDIData(
 		This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
+	for (i=0;i<*entries;i++) {
+		dod[i].dwTimeStamp = time(NULL);
+		dod[i].dwSequence = evsequence++;
+	}
+	return ret;
 }
 
 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
@@ -652,6 +663,7 @@
 	   mouse device) */
 	if (This->prev_handler != NULL)
 	  MOUSE_Enable(This->prev_handler);
+	DeleteCriticalSection(&(This->crit));
 	
 	HeapFree(GetProcessHeap(),0,This);
 	return 0;
@@ -733,29 +745,31 @@
   else
     ERR("Neither absolute nor relative flag set.");
   
+  This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
+  memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
   return 0;
 }
 
+#define GEN_EVENT(offset,data,xtime,seq)			\
+{								\
+  if (This->queue_pos < This->queue_len) {			\
+    This->data_queue[This->queue_pos].dwOfs = offset;		\
+    This->data_queue[This->queue_pos].dwData = data;		\
+    This->data_queue[This->queue_pos].dwTimeStamp = xtime;	\
+    This->data_queue[This->queue_pos].dwSequence = seq;		\
+    This->queue_pos++;						\
+  }								\
+}
 
-
-#define GEN_EVENT(offset,data,time,seq)						\
-{										\
-  if (This->queue_pos < This->queue_len) {					\
-    This->data_queue[This->queue_pos].dwOfs = offset;				\
-    This->data_queue[This->queue_pos].dwData = data;				\
-    This->data_queue[This->queue_pos].dwTimeStamp = time;			\
-    This->data_queue[This->queue_pos].dwSequence = seq;			\
-    This->queue_pos++;								\
-  }										\
-  }
   
 /* Our private mouse event handler */
 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
 				      DWORD cButtons, DWORD dwExtraInfo )
 {
-  DWORD posX, posY, keyState, time, extra;
+  DWORD posX, posY, keyState, xtime, extra;
   SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
   
+  EnterCriticalSection(&(This->crit));
   /* Mouse moved -> send event if asked */
   if (This->hEvent)
     SetEvent(This->hEvent);
@@ -764,7 +778,7 @@
       && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
     WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
     keyState = wme->keyState;
-    time = wme->time;
+    xtime = wme->time;
     extra = (DWORD)wme->hWnd;
     
     assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
@@ -772,6 +786,7 @@
     posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
   } else {
     ERR("Mouse event not supported...\n");
+    LeaveCriticalSection(&(This->crit));
     return ;
   }
 
@@ -780,26 +795,26 @@
   if ( dwFlags & MOUSEEVENTF_MOVE ) {
     if (This->absolute) {
       if (posX != This->prevX)
-	GEN_EVENT(DIMOFS_X, posX, time, 0);
+	GEN_EVENT(DIMOFS_X, posX, xtime, 0);
       if (posY != This->prevY)
-	GEN_EVENT(DIMOFS_Y, posY, time, 0);
+	GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
     } else {
       /* Relative mouse input : the real fun starts here... */
       if (This->need_warp) {
 	if (posX != This->prevX)
-	  GEN_EVENT(DIMOFS_X, posX - This->prevX, time, 0);
+	  GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
 	if (posY != This->prevY)
-	  GEN_EVENT(DIMOFS_Y, posY - This->prevY, time, 0);
+	  GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
       } else {
 	/* This is the first time the event handler has been called after a
 	   GetData of GetState. */
 	if (posX != This->win_centerX) {
-	  GEN_EVENT(DIMOFS_X, posX - This->win_centerX, time, 0);
+	  GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
 	  This->need_warp = 1;
 	}
 	  
 	if (posY != This->win_centerY) {
-	  GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, time, 0);
+	  GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
 	  This->need_warp = 1;
 	}
       }
@@ -809,43 +824,44 @@
     if (TRACE_ON(dinput))
       DPRINTF(" LD ");
 
-    GEN_EVENT(DIMOFS_BUTTON0, 0xFF, time, 0);
+    GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
   }
   if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
     if (TRACE_ON(dinput))
       DPRINTF(" LU ");
 
-    GEN_EVENT(DIMOFS_BUTTON0, 0x00, time, 0);
+    GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
   }
   if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
     if (TRACE_ON(dinput))
       DPRINTF(" RD ");
 
-    GEN_EVENT(DIMOFS_BUTTON1, 0xFF, time, 0);
+    GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
   }
   if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
     if (TRACE_ON(dinput))
       DPRINTF(" RU ");
 
-    GEN_EVENT(DIMOFS_BUTTON1, 0x00, time, 0);
+    GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
   }
   if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
     if (TRACE_ON(dinput))
       DPRINTF(" MD ");
 
-    GEN_EVENT(DIMOFS_BUTTON2, 0xFF, time, 0);
+    GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
   }
   if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
     if (TRACE_ON(dinput))
       DPRINTF(" MU ");
 
-    GEN_EVENT(DIMOFS_BUTTON2, 0x00, time, 0);
+    GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
   }
   if (TRACE_ON(dinput))
     DPRINTF("\n");
 
   This->prevX = posX;
   This->prevY = posY;
+  LeaveCriticalSection(&(This->crit));
 }
 
 
@@ -983,11 +999,11 @@
 ) {
   ICOM_THIS(SysMouseAImpl,iface);
   
-  TRACE("(%p)->(%ld,%p,%p(0x%08lx),0x%08lx)\n",
-	This,dodsize,dod,entries,*entries,flags);
+  EnterCriticalSection(&(This->crit));
+  TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
 
   if (flags & DIGDD_PEEK)
-    TRACE("DIGDD_PEEK\n");
+    FIXME("DIGDD_PEEK\n");
 
   if (dod == NULL) {
     *entries = This->queue_pos;
@@ -1000,18 +1016,23 @@
     }
     if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
       ERR("Wrong structure size !\n");
+      LeaveCriticalSection(&(This->crit));
       return DIERR_INVALIDPARAM;
     }
 
-    TRACE("Application retrieving %d event(s).\n", This->queue_pos); 
+    if (This->queue_pos)
+    	TRACE("Application retrieving %d event(s).\n", This->queue_pos); 
     
     /* Copy the buffered data into the application queue */
     memcpy(dod, This->data_queue, This->queue_pos * dodsize);
-    
+    *entries = This->queue_pos;
+
     /* Reset the event queue */
     This->queue_pos = 0;
   }
+  LeaveCriticalSection(&(This->crit));
   
+#if 0 /* FIXME: seems to create motion events, which fire back at us. */
   /* Check if we need to do a mouse warping */
   if (This->need_warp) {
     POINT point;
@@ -1020,11 +1041,12 @@
     point.x = This->win_centerX;
     point.y = This->win_centerY;
     MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
+
     DISPLAY_MoveCursor(point.x, point.y);
 
     This->need_warp = 0;
   }
-  
+#endif
   return 0;
 }
 
@@ -1059,7 +1081,7 @@
       break;
     }
     default:
-      WARN("Unknown type %ld\n",(DWORD)rguid);
+      FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
       break;
     }
   }