15 added + 1 modified, total 16 files
- TODO:
 
- FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
 
- FIXME("(this=%p,%p,%p,%08lx): stub!\n", iface, lpCallback, lpvRef, dwFlags);
 
- FIXME("(this=%p,%p,%p,%08lx): stub!\n", iface, lpCallback, lpvRef, dwFlags);
 
- FIXME("(this=%p,%s,%p): stub!\n",
 
- FIXME("(this=%p,%p,%ld,0x%08lx): stub!\n",
 
- FIXME("(this=%p,%p,%ld,0x%08lx): stub!\n",
 
- FIXME("(this=%p,%p): stub!\n",
 
- FIXME("(this=%p,%p): stub!\n",
 
- FIXME("(this=%p,%p,0x%08lx): stub!\n",
 
- FIXME("(this=%p,%p,%ld,%s): stub!\n",
 
- FIXME("(this=%p,%s,%p,%p,%p): stub!\n",
 
- FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
 
- FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
 
- FIXME("(this=%p,%p,%s): stub!\n",
 
- FIXME("(this=%p,%p,%s): stub!\n",
 
- FIXME("(this=%p,%p): stub!\n",
 
- FIXME("(this=%p,0x%08lx): stub!\n",
 
- FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
 
- FIXME("(this=%p,%p): stub!\n",
 
- FIXME("(this=%p,0x%08lx,%p,%p,0x%08lx): stub!\n",
 
- FIXME("(%p)->(%s,%p,%p,%08lx): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags);
 
- FIXME("(%p)->(%s,%p,%p,%08lx): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
 
- FIXME("(%p)->(%s,%08lx,%p,%08lx): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
 
- FIXME("(%p)->(%s,%08lx,%p,%08lx): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
 
- FIXME("(%p)->(%p,%s,%08lx): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
 
- FIXME("(%p)->(%p,%s,%08lx): stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
 
- FIXME("(%p)->(%p,%s,%08lx): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
 
- FIXME("(%p)->(%p,%s,%08lx): stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
 
- FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
 
- FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
 
- FIXME("(%p)->(%s): stub\n",This,debugstr_guid(rguid));
 
- FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
 
- FIXME("(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), pszName, pguidInstance);
 
- FIXME("(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), debugstr_w(pszName), pguidInstance);
 
- FIXME("(this=%p,%s,%p,%p,%p,%04lx): stub\n", This, ptszUserName, lpdiActionFormat,
 
- FIXME("(this=%p,%s,%p,%p,%p,%04lx): stub\n", This, debugstr_w(ptszUserName), lpdiActionFormat,
 
- FIXME("(this=%p,%p,%p,%04lx,%p): stub\n", This, lpdiCallback, lpdiCDParams,
 
- FIXME("(this=%p,%p,%p,%04lx,%p): stub\n", This, lpdiCallback, lpdiCDParams,
 
- FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
 
- FIXME: reuse already created dinput if present? */
 
- FIXME("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);	
 
- FIXME("(%p)->(%d),stub!\n",This,dolock);
 
- FIXME("(void): stub\n");
 
- FIXME("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
 
- FIXME do deadzone and saturation here */
 
- FIXME don't go off array */
 
- FIXME("found a joystick at %s!\n",buf);
 
- TODO: 
 
- FIXME("axe %d: cur=%d, min=%d, max=%d, fuzz=%d, flat=%d\n",
 
- FIXME("%d in deadzone, return mid.\n",val);
 
- FIXME("unhandled joystick button %x, value %d\n",ie.code,ie.value);
 
- FIXME("unhandled joystick axe event (code %d, value %d)\n",ie.code,ie.value);
 
- FIXME("joystick cannot handle type %d event (code %d)\n",ie.type,ie.code);
 
- FIXME("len %ld is not sizeof(DIJOYSTATE) or DIJOYSTATE2, unsupported format.\n",len);
 
- FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
 
- FIXME("DIGDD_PEEK\n");
 
- FIXME("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
 
- FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
 
- FIXME("buffersize = %ld\n",pd->dwData);
 
- FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
 
- FIXME("setting proprange %ld - %ld for dwObj %ld\n",pr->lMin,pr->lMax,ph->dwObj);
 
- FIXME("setting deadzone(%ld)\n",pd->dwData);
 
- FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
 
- FIXME: needs more items */
 
- FIXME("unhandled abs axis %d, ignoring!\n",i);
 
- FIXME("unimplemented axis range query.\n");
 
- FIXME: currently this can be only one.
 
- FIXME("Not more than one keyboard can be acquired at the same time.\n");
 
- FIXME: This is ugly and not thread safe :/ */
 
- FIXME: This is ugly but needed on Windows */
 
- FIXME mouse are bit choppy here. 
 
- FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
 
- FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
 
 
reactos/lib/dinput
diff -N Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile	29 Nov 2004 00:13:49 -0000	1.4
@@ -0,0 +1,9 @@
+# $Id: Makefile,v 1.4 2004/11/29 00:13:49 greatlrd Exp $
+
+PATH_TO_TOP = ../..
+
+TARGET_TYPE = winedll
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
 
reactos/lib/dinput
diff -N Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile.in	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,23 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = dinput.dll
+IMPORTS   = ole32 user32 advapi32 kernel32
+EXTRALIBS = -ldxguid -luuid
+
+C_SRCS = \
+	data_formats.c \
+	device.c \
+	dinput_main.c \
+	joystick_linux.c \
+	joystick_linuxinput.c \
+	keyboard.c \
+	mouse.c \
+	regsvr.c
+
+RC_SRCS = version.rc
+
+@MAKE_DLL_RULES@
+
+### Dependencies:
 
reactos/lib/dinput
diff -N Makefile.ros
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile.ros	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,28 @@
+# $Id: Makefile.ros,v 1.1 2004/11/29 00:13:49 greatlrd Exp $
+
+TARGET_NAME = dinput
+
+TARGET_OBJECTS = data_formats.o device.o dinput_main.o joystick_linux.o joystick_linuxinput.o keyboard.o mouse.o regsvr.o
+
+TARGET_CFLAGS =  -D__REACTOS__
+
+TARGET_SDKLIBS = libwine.a ole32.a user32.a advapi32.a kernel32.a ole32.a wine_uuid.a ntdll.a  winmm.a dxguid.a
+
+
+
+TARGET_RC_SRCS = version.rc
+TARGET_RC_BINSRC = 
+TARGET_RC_BINARIES = 
+
+default: all
+
+authors.c:
+ifeq ($(HOST),mingw32-linux)
+	echo 'const char * const SHELL_Authors[] = { "WINE team", "ReactOS team", 0 };' > authors.c
+else
+	echo const char * const SHELL_Authors[] = { "WINE team", "ReactOS team", 0 }; > authors.c
+endif
+
+DEP_OBJECTS = $(TARGET_OBJECTS)
+
+include $(TOOLS_PATH)/depend.mk
 
reactos/lib/dinput
diff -N Makefile.ros-template
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile.ros-template	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,28 @@
+# $Id: Makefile.ros-template,v 1.1 2004/11/29 00:13:49 greatlrd Exp $
+
+TARGET_NAME = dinput
+
+TARGET_OBJECTS = @C_SRCS@
+
+TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__
+
+TARGET_SDKLIBS = libwine.a @IMPORTS@ ole32.a wine_uuid.a ntdll.a  winmm.a dxguid.a
+
+
+
+TARGET_RC_SRCS = @RC_SRCS@
+TARGET_RC_BINSRC = @RC_BINSRC@
+TARGET_RC_BINARIES = @RC_BINARIES@
+
+default: all
+
+authors.c:
+ifeq ($(HOST),mingw32-linux)
+	echo 'const char * const SHELL_Authors[] = { "WINE team", "ReactOS team", 0 };' > authors.c
+else
+	echo const char * const SHELL_Authors[] = { "WINE team", "ReactOS team", 0 }; > authors.c
+endif
+
+DEP_OBJECTS = $(TARGET_OBJECTS)
+
+include $(TOOLS_PATH)/depend.mk
 
reactos/lib/dinput
diff -N data_formats.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ data_formats.c	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2004 Robert Reif
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* TODO:
+ * add keyboard
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "dinput.h"
+
+#define numObjects(x) (sizeof(x) / sizeof(x[0]))
+
+DIOBJECTDATAFORMAT dfDIJoystick[] = {
+  { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_POV,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
+  { &GUID_POV,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
+  { &GUID_POV,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
+  { &GUID_POV,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(11),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(12),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(13),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(14),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(15),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(16),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(17),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(18),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(19),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(20),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(21),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(22),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(23),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(24),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(25),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(26),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(27),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(28),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(29),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(30),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(31),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+};
+
+const DIDATAFORMAT c_dfDIJoystick = {
+    sizeof(DIDATAFORMAT),
+    sizeof(DIOBJECTDATAFORMAT),
+    DIDF_ABSAXIS,
+    sizeof(DIJOYSTATE2),
+    numObjects(dfDIJoystick),
+    dfDIJoystick
+};
+
+DIOBJECTDATAFORMAT dfDIJoystick2[] = {
+  { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_POV,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
+  { &GUID_POV,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
+  { &GUID_POV,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
+  { &GUID_POV,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(11),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(12),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(13),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(14),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(15),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(16),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(17),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(18),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(19),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(20),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(21),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(22),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(23),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(24),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(25),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(26),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(27),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(28),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(29),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(30),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(31),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(32),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(33),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(34),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(35),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(36),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(37),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(38),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(39),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(40),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(41),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(42),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(43),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(44),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(45),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(46),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(47),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(48),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(49),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(50),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(51),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(52),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(53),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(54),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(55),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(56),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(57),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(58),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(59),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(60),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(61),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(62),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(63),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(64),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(65),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(66),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(67),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(68),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(69),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(70),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(71),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(72),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(73),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(74),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(75),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(76),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(77),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(78),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(79),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(80),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(81),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(82),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(83),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(84),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(85),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(86),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(87),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(88),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(89),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(90),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(91),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(92),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(93),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(94),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(95),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(96),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(97),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(98),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(99),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(100),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(101),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(102),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(103),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(104),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(105),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(106),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(107),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(108),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(109),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(110),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(111),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(112),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(113),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(114),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(115),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(116),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(117),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(118),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(119),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(120),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(121),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(122),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(123),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(124),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(125),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(126),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { NULL,DIJOFS_BUTTON(127),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
+  { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lVX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lVY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lVZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lVRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lVRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lVRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lAX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lAY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lAZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lARx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lARy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lARz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lFX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lFY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lFZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lFRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lFRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lFRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
+};
+
+const DIDATAFORMAT c_dfDIJoystick2 = {
+    sizeof(DIDATAFORMAT),
+    sizeof(DIOBJECTDATAFORMAT),
+    DIDF_ABSAXIS,
+    sizeof(DIJOYSTATE2),
+    numObjects(dfDIJoystick2),
+    dfDIJoystick2
+};
+
+DIOBJECTDATAFORMAT dfDIMouse[] = {
+  { &GUID_XAxis,  DIMOFS_X, DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 },
+  { &GUID_YAxis,  DIMOFS_Y, DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 },
+  { &GUID_ZAxis,  DIMOFS_Z, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 },
+  { &GUID_Button, DIMOFS_BUTTON0, DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON1, DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON2, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON3, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }
+};
+
+const DIDATAFORMAT c_dfDIMouse = {
+    sizeof(DIDATAFORMAT),
+    sizeof(DIOBJECTDATAFORMAT),
+    DIDF_RELAXIS,
+    sizeof(DIMOUSESTATE),
+    numObjects(dfDIMouse),
+    dfDIMouse
+};
+
+DIOBJECTDATAFORMAT dfDIMouse2[] = {
+  { &GUID_XAxis,  DIMOFS_X, DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 },
+  { &GUID_YAxis,  DIMOFS_Y, DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 },
+  { &GUID_ZAxis,  DIMOFS_Z, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 },
+  { &GUID_Button, DIMOFS_BUTTON0, DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON1, DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON2, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON3, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON4, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON5, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON6, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 },
+  { &GUID_Button, DIMOFS_BUTTON7, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }
+};
+
+const DIDATAFORMAT c_dfDIMouse2 = {
+    sizeof(DIDATAFORMAT),
+    sizeof(DIOBJECTDATAFORMAT),
+    DIDF_RELAXIS,
+    sizeof(DIMOUSESTATE2),
+    numObjects(dfDIMouse2),
+    dfDIMouse2
+};
 
reactos/lib/dinput
diff -N device.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ device.c	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,884 @@
+/*		DirectInput Device
+ *
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1998,1999 Lionel Ulmer
+ *
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* This file contains all the Device specific functions that can be used as stubs
+   by real device implementations.
+
+   It also contains all the helper functions.
+*/
+#include "config.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "dinput.h"
+#include "device_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+
+/******************************************************************************
+ *	Various debugging tools
+ */
+void _dump_cooperativelevel_DI(DWORD dwFlags) {
+    if (TRACE_ON(dinput)) {
+	unsigned int   i;
+	static const struct {
+	    DWORD       mask;
+	    const char  *name;
+	} flags[] = {
+#define FE(x) { x, #x}
+	    FE(DISCL_BACKGROUND),
+	    FE(DISCL_EXCLUSIVE),
+	    FE(DISCL_FOREGROUND),
+	    FE(DISCL_NONEXCLUSIVE)
+#undef FE
+	};
+	for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
+	    if (flags[i].mask & dwFlags)
+		DPRINTF("%s ",flags[i].name);
+	DPRINTF("\n");
+    }
+}
+
+void _dump_EnumObjects_flags(DWORD dwFlags) {
+    if (TRACE_ON(dinput)) {
+	unsigned int   i;
+	DWORD type, instance;
+	static const struct {
+	    DWORD       mask;
+	    const char  *name;
+	} flags[] = {
+#define FE(x) { x, #x}
+	    FE(DIDFT_RELAXIS),
+	    FE(DIDFT_ABSAXIS),
+	    FE(DIDFT_PSHBUTTON),
+	    FE(DIDFT_TGLBUTTON),
+	    FE(DIDFT_POV),
+	    FE(DIDFT_COLLECTION),
+	    FE(DIDFT_NODATA),	    
+	    FE(DIDFT_FFACTUATOR),
+	    FE(DIDFT_FFEFFECTTRIGGER),
+	    FE(DIDFT_OUTPUT)
+#undef FE
+	};
+	type = (dwFlags & 0xFF0000FF);
+	instance = ((dwFlags >> 8) & 0xFFFF);
+	DPRINTF("Type:");
+	if (type == DIDFT_ALL) {
+	    DPRINTF(" DIDFT_ALL");
+	} else {
+	    for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++) {
+		if (flags[i].mask & type) {
+		    type &= ~flags[i].mask;
+		    DPRINTF(" %s",flags[i].name);
+		}
+	    }
+	    if (type) {
+		DPRINTF(" (unhandled: %08lx)", type);
+	    }
+	}
+	DPRINTF(" / Instance: ");
+	if (instance == ((DIDFT_ANYINSTANCE >> 8) & 0xFFFF)) {
+	    DPRINTF("DIDFT_ANYINSTANCE");
+	} else {
+	    DPRINTF("%3ld", instance);
+	}
+    }
+}
+
+void _dump_DIPROPHEADER(LPCDIPROPHEADER diph) {
+    if (TRACE_ON(dinput)) {
+	DPRINTF("  - dwObj = 0x%08lx\n", diph->dwObj);
+	DPRINTF("  - dwHow = %s\n",
+		((diph->dwHow == DIPH_DEVICE) ? "DIPH_DEVICE" :
+		 ((diph->dwHow == DIPH_BYOFFSET) ? "DIPH_BYOFFSET" :
+		  ((diph->dwHow == DIPH_BYID)) ? "DIPH_BYID" : "unknown")));
+    }
+}
+
+void _dump_OBJECTINSTANCEA(DIDEVICEOBJECTINSTANCEA *ddoi) {
+    if (TRACE_ON(dinput)) {
+	DPRINTF("    - enumerating : %s ('%s') - %2ld - 0x%08lx - %s\n",
+		debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, ddoi->tszName);
+    }
+}
+
+void _dump_OBJECTINSTANCEW(DIDEVICEOBJECTINSTANCEW *ddoi) {
+    if (TRACE_ON(dinput)) {
+	DPRINTF("    - enumerating : %s ('%s'), - %2ld - 0x%08lx - %s\n",
+		debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, debugstr_w(ddoi->tszName));
+    }
+}
+
+/* This function is a helper to convert a GUID into any possible DInput GUID out there */
+const char *_dump_dinput_GUID(const GUID *guid) {
+    unsigned int i;
+    static const struct {
+	const GUID *guid;
+	const char *name;
+    } guids[] = {
+#define FE(x) { &x, #x}
+	FE(GUID_XAxis),
+	FE(GUID_YAxis),
+	FE(GUID_ZAxis),
+	FE(GUID_RxAxis),
+	FE(GUID_RyAxis),
+	FE(GUID_RzAxis),
+	FE(GUID_Slider),
+	FE(GUID_Button),
+	FE(GUID_Key),
+	FE(GUID_POV),
+	FE(GUID_Unknown),
+	FE(GUID_SysMouse),
+	FE(GUID_SysKeyboard),
+	FE(GUID_Joystick),
+	FE(GUID_ConstantForce),
+	FE(GUID_RampForce),
+	FE(GUID_Square),
+	FE(GUID_Sine),
+	FE(GUID_Triangle),
+	FE(GUID_SawtoothUp),
+	FE(GUID_SawtoothDown),
+	FE(GUID_Spring),
+	FE(GUID_Damper),
+	FE(GUID_Inertia),
+	FE(GUID_Friction),
+	FE(GUID_CustomForce)
+#undef FE
+    };
+    if (guid == NULL)
+	return "null GUID";
+    for (i = 0; i < (sizeof(guids) / sizeof(guids[0])); i++) {
+	if (IsEqualGUID(guids[i].guid, guid)) {
+	    return guids[i].name;
+	}
+    }
+    return "Unknown GUID";
+}
+
+void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) {
+    unsigned int i;
+
+    TRACE("Dumping DIDATAFORMAT structure:\n");
+    TRACE("  - dwSize: %ld\n", df->dwSize);
+    if (df->dwSize != sizeof(DIDATAFORMAT)) {
+	WARN("Non-standard DIDATAFORMAT structure size (%ld instead of %d).\n", df->dwSize, sizeof(DIDATAFORMAT));
+    }
+    TRACE("  - dwObjsize: %ld\n", df->dwObjSize);
+    if (df->dwObjSize != sizeof(DIOBJECTDATAFORMAT)) {
+	WARN("Non-standard DIOBJECTDATAFORMAT structure size (%ld instead of %d).\n", df->dwObjSize, sizeof(DIOBJECTDATAFORMAT));
+    }
+    TRACE("  - dwFlags: 0x%08lx (", df->dwFlags);
+    switch (df->dwFlags) {
+        case DIDF_ABSAXIS: TRACE("DIDF_ABSAXIS"); break;
+	case DIDF_RELAXIS: TRACE("DIDF_RELAXIS"); break;
+	default: TRACE("unknown"); break;
+    }
+    TRACE(")\n");
+    TRACE("  - dwDataSize: %ld\n", df->dwDataSize);
+    TRACE("  - dwNumObjs: %ld\n", df->dwNumObjs);
+    
+    for (i = 0; i < df->dwNumObjs; i++) {
+	TRACE("  - Object %d:\n", i);
+	TRACE("      * GUID: %s ('%s')\n", debugstr_guid(df->rgodf[i].pguid), _dump_dinput_GUID(df->rgodf[i].pguid));
+	TRACE("      * dwOfs: %ld\n", df->rgodf[i].dwOfs);
+	TRACE("      * dwType: 0x%08lx\n", df->rgodf[i].dwType);
+	TRACE("        "); _dump_EnumObjects_flags(df->rgodf[i].dwType); TRACE("\n");
+	TRACE("      * dwFlags: 0x%08lx\n", df->rgodf[i].dwFlags);
+    }
+}
+
+/* Conversion between internal data buffer and external data buffer */
+void fill_DataFormat(void *out, const void *in, DataFormat *df) {
+    int i;
+    char *in_c = (char *) in;
+    char *out_c = (char *) out;
+    
+    if (df->dt == NULL) {
+	/* This means that the app uses Wine's internal data format */
+	memcpy(out, in, df->internal_format_size);
+    } else {
+	for (i = 0; i < df->size; i++) {
+	    if (df->dt[i].offset_in >= 0) {
+		switch (df->dt[i].size) {
+		    case 1:
+		        TRACE("Copying (c) to %d from %d (value %d)\n",
+			      df->dt[i].offset_out, df->dt[i].offset_in, *((char *) (in_c + df->dt[i].offset_in)));
+			*((char *) (out_c + df->dt[i].offset_out)) = *((char *) (in_c + df->dt[i].offset_in));
+			break;
+		    
+		    case 2:
+			TRACE("Copying (s) to %d from %d (value %d)\n",
+			      df->dt[i].offset_out, df->dt[i].offset_in, *((short *) (in_c + df->dt[i].offset_in)));
+			*((short *) (out_c + df->dt[i].offset_out)) = *((short *) (in_c + df->dt[i].offset_in));
+			break;
+		    
+		    case 4:
+			TRACE("Copying (i) to %d from %d (value %d)\n",
+			      df->dt[i].offset_out, df->dt[i].offset_in, *((int *) (in_c + df->dt[i].offset_in)));
+			*((int *) (out_c + df->dt[i].offset_out)) = *((int *) (in_c + df->dt[i].offset_in));
+			break;
+		    
+		    default:
+			memcpy((out_c + df->dt[i].offset_out), (in_c + df->dt[i].offset_in), df->dt[i].size);
+			break;
+		}
+	    } else {
+		switch (df->dt[i].size) {
+		    case 1:
+		        TRACE("Copying (c) to %d default value %d\n",
+			      df->dt[i].offset_out, df->dt[i].value);
+			*((char *) (out_c + df->dt[i].offset_out)) = (char) df->dt[i].value;
+			break;
+			
+		    case 2:
+			TRACE("Copying (s) to %d default value %d\n",
+			      df->dt[i].offset_out, df->dt[i].value);
+			*((short *) (out_c + df->dt[i].offset_out)) = (short) df->dt[i].value;
+			break;
+			
+		    case 4:
+			TRACE("Copying (i) to %d default value %d\n",
+			      df->dt[i].offset_out, df->dt[i].value);
+			*((int *) (out_c + df->dt[i].offset_out)) = (int) df->dt[i].value;
+			break;
+			
+		    default:
+			memset((out_c + df->dt[i].offset_out), df->dt[i].size, 0);
+			break;
+		}
+	    }
+	}
+    }
+}
+
+void release_DataFormat(DataFormat * format)
+{
+    TRACE("Deleting DataTransform : \n");
+
+    HeapFree(GetProcessHeap(), 0, format->dt);
+}
+
+DataFormat *create_DataFormat(const DIDATAFORMAT *wine_format, LPCDIDATAFORMAT asked_format, int *offset) {
+    DataFormat *ret;
+    DataTransform *dt;
+    unsigned int i, j;
+    int same = 1;
+    int *done;
+    int index = 0;
+    DWORD next = 0;
+    
+    ret = (DataFormat *) HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat));
+    
+    done = (int *) HeapAlloc(GetProcessHeap(), 0, sizeof(int) * asked_format->dwNumObjs);
+    memset(done, 0, sizeof(int) * asked_format->dwNumObjs);
+    
+    dt = (DataTransform *) HeapAlloc(GetProcessHeap(), 0, asked_format->dwNumObjs * sizeof(DataTransform));
+    
+    TRACE("Creating DataTransform : \n");
+    
+    for (i = 0; i < wine_format->dwNumObjs; i++) {
+	offset[i] = -1;
+	
+	for (j = 0; j < asked_format->dwNumObjs; j++) {
+	    if (done[j] == 1)
+		continue;
+	    
+	    if (/* Check if the application either requests any GUID and if not, it if matches
+		 * the GUID of the Wine object.
+		 */
+		((asked_format->rgodf[j].pguid == NULL) ||
+		 (IsEqualGUID(wine_format->rgodf[i].pguid, asked_format->rgodf[j].pguid)))
+		&&
+		(/* Then check if it accepts any instance id, and if not, if it matches Wine's
+		  * instance id.
+		  */
+		 ((asked_format->rgodf[j].dwType & 0x00FFFF00) == DIDFT_ANYINSTANCE) ||
+		 (DIDFT_GETINSTANCE(wine_format->rgodf[i].dwType) == DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType)))) {
+		
+		done[j] = 1;
+		
+		TRACE("Matching : \n");
+		TRACE("   - Asked (%d) :\n", j);
+		TRACE("       * GUID: %s ('%s')\n",
+		      debugstr_guid(asked_format->rgodf[j].pguid),
+		      _dump_dinput_GUID(asked_format->rgodf[j].pguid));
+		TRACE("       * Offset: %3ld\n", asked_format->rgodf[j].dwOfs);
+		TRACE("       * dwType: %08lx\n", asked_format->rgodf[j].dwType);
+		TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
+		
+		TRACE("   - Wine  (%d) :\n", j);
+		TRACE("       * GUID: %s ('%s')\n",
+		      debugstr_guid(wine_format->rgodf[j].pguid),
+		      _dump_dinput_GUID(wine_format->rgodf[j].pguid));
+		TRACE("       * Offset: %3ld\n", wine_format->rgodf[j].dwOfs);
+		TRACE("       * dwType: %08lx\n", wine_format->rgodf[j].dwType);
+		TRACE("         "); _dump_EnumObjects_flags(wine_format->rgodf[j].dwType); TRACE("\n");
+		
+		if (wine_format->rgodf[i].dwType & DIDFT_BUTTON)
+		    dt[index].size = sizeof(BYTE);
+		else
+		    dt[index].size = sizeof(DWORD);
+		dt[index].offset_in  = wine_format ->rgodf[i].dwOfs;
+                if (asked_format->rgodf[j].dwOfs < next) {
+                    WARN("bad format: dwOfs=%ld, changing to %ld\n", asked_format->rgodf[j].dwOfs, next);
+		    dt[index].offset_out = next;
+		    offset[i] = next;
+                } else {
+		    dt[index].offset_out = asked_format->rgodf[j].dwOfs;
+                    offset[i] = asked_format->rgodf[j].dwOfs;
+                }
+		dt[index].value = 0;
+                next = next + dt[index].size;
+		
+		if (wine_format->rgodf[i].dwOfs != dt[index].offset_out)
+		    same = 0;
+		
+		index++;
+		break;
+	    }
+	}
+	
+	if (j == asked_format->dwNumObjs)
+	    same = 0;
+    }
+    
+    TRACE("Setting to default value :\n");
+    for (j = 0; j < asked_format->dwNumObjs; j++) {
+	if (done[j] == 0) {
+	    TRACE("   - Asked (%d) :\n", j);
+	    TRACE("       * GUID: %s ('%s')\n",
+		  debugstr_guid(asked_format->rgodf[j].pguid),
+		  _dump_dinput_GUID(asked_format->rgodf[j].pguid));
+	    TRACE("       * Offset: %3ld\n", asked_format->rgodf[j].dwOfs);
+	    TRACE("       * dwType: %08lx\n", asked_format->rgodf[j].dwType);
+	    TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
+	    
+	    if (asked_format->rgodf[j].dwType & DIDFT_BUTTON)
+		dt[index].size = sizeof(BYTE);
+	    else
+		dt[index].size = sizeof(DWORD);
+	    dt[index].offset_in  = -1;
+	    dt[index].offset_out = asked_format->rgodf[j].dwOfs;
+	    dt[index].value = 0;
+	    index++;
+	    
+	    same = 0;
+	}
+    }
+    
+    ret->internal_format_size = wine_format->dwDataSize;
+    ret->size = index;
+    if (same) {
+	ret->dt = NULL;
+	HeapFree(GetProcessHeap(), 0, dt);
+    } else {
+	ret->dt = dt;
+    }
+    
+    HeapFree(GetProcessHeap(), 0, done);
+    
+    return ret;
+}
+
+BOOL DIEnumDevicesCallbackAtoW(LPCDIDEVICEOBJECTINSTANCEA lpddi, LPVOID lpvRef) {
+    DIDEVICEOBJECTINSTANCEW ddtmp;
+    device_enumobjects_AtoWcb_data* data;
+
+    data = (device_enumobjects_AtoWcb_data*) lpvRef;
+    
+    memset(&ddtmp, 0, sizeof(DIDEVICEINSTANCEW)); 
+    
+    ddtmp.dwSize = sizeof(DIDEVICEINSTANCEW);
+    ddtmp.guidType     = lpddi->guidType;
+    ddtmp.dwOfs        = lpddi->dwOfs;
+    ddtmp.dwType       = lpddi->dwType;
+    ddtmp.dwFlags      = lpddi->dwFlags;
+    MultiByteToWideChar(CP_ACP, 0, lpddi->tszName, -1, ddtmp.tszName, MAX_PATH);
+    
+    if (lpddi->dwSize == sizeof(DIDEVICEINSTANCEA)) {
+	/**
+	 * if dwSize < sizeof(DIDEVICEINSTANCEA of DInput version >= 5)
+	 *  force feedback and other newer datas aren't available
+	 */
+	ddtmp.dwFFMaxForce        = lpddi->dwFFMaxForce;
+	ddtmp.dwFFForceResolution = lpddi->dwFFForceResolution;
+	ddtmp.wCollectionNumber   = lpddi->wCollectionNumber;
+	ddtmp.wDesignatorIndex    = lpddi->wDesignatorIndex;
+	ddtmp.wUsagePage          = lpddi->wUsagePage;
+	ddtmp.wUsage              = lpddi->wUsage;
+	ddtmp.dwDimension         = lpddi->dwDimension;
+	ddtmp.wExponent           = lpddi->wExponent;
+	ddtmp.wReserved           = lpddi->wReserved;
+    }
+    return data->lpCallBack(&ddtmp, data->lpvRef);
+}
+
+/******************************************************************************
+ *	IDirectInputDeviceA
+ */
+
+HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
+	LPDIRECTINPUTDEVICE8A iface,LPCDIDATAFORMAT df
+) {
+    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
+    
+    TRACE("(this=%p,%p)\n",This,df);
+    
+    _dump_DIDATAFORMAT(df);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
+	LPDIRECTINPUTDEVICE8A iface,HWND hwnd,DWORD dwflags
+) {
+    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
+    TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
+    if (TRACE_ON(dinput)) {
+	TRACE(" cooperative level : ");
+	_dump_cooperativelevel_DI(dwflags);
+    }
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
+	LPDIRECTINPUTDEVICE8A iface,HANDLE hnd
+) {
+    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
+    FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
+    return DI_OK;
+}
+
+ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
+{
+    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
+    ULONG ref;
+    ref = InterlockedDecrement(&(This->ref));
+    if (ref == 0)
+        HeapFree(GetProcessHeap(),0,This);
+    return ref;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
+	LPDIRECTINPUTDEVICE8A iface,REFIID riid,LPVOID *ppobj
+)
+{
+    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
+    
+    TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    if (IsEqualGUID(&IID_IUnknown,riid)) {
+	IDirectInputDevice2_AddRef(iface);
+	*ppobj = This;
+	return DI_OK;
+    }
+    if (IsEqualGUID(&IID_IDirectInputDeviceA,riid)) {
+	IDirectInputDevice2_AddRef(iface);
+	*ppobj = This;
+	return DI_OK;
+    }
+    if (IsEqualGUID(&IID_IDirectInputDevice2A,riid)) {
+	IDirectInputDevice2_AddRef(iface);
+	*ppobj = This;
+	return DI_OK;
+    }
+    if (IsEqualGUID(&IID_IDirectInputDevice7A,riid)) {
+	IDirectInputDevice7_AddRef(iface);
+	*ppobj = This;
+	return DI_OK;
+    }
+    TRACE("Unsupported interface !\n");
+    return E_FAIL;
+}
+
+HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(
+	LPDIRECTINPUTDEVICE8W iface,REFIID riid,LPVOID *ppobj
+)
+{
+    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
+    
+    TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    if (IsEqualGUID(&IID_IUnknown,riid)) {
+	IDirectInputDevice2_AddRef(iface);
+	*ppobj = This;
+	return DI_OK;
+    }
+    if (IsEqualGUID(&IID_IDirectInputDeviceW,riid)) {
+	IDirectInputDevice2_AddRef(iface);
+	*ppobj = This;
+	return DI_OK;
+    }
+    if (IsEqualGUID(&IID_IDirectInputDevice2W,riid)) {
+	IDirectInputDevice2_AddRef(iface);
+	*ppobj = This;
+	return DI_OK;
+    }
+    if (IsEqualGUID(&IID_IDirectInputDevice7W,riid)) {
+	IDirectInputDevice7_AddRef(iface);
+	*ppobj = This;
+	return DI_OK;
+    }
+    TRACE("Unsupported interface !\n");
+    return E_FAIL;
+}
+
+ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
+	LPDIRECTINPUTDEVICE8A iface)
+{
+    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
+    return InterlockedIncrement(&(This->ref));
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags)
+{
+    FIXME("(this=%p,%p,%p,%08lx): stub!\n", iface, lpCallback, lpvRef, dwFlags);
+    if (TRACE_ON(dinput)) {
+	DPRINTF("  - flags = ");
+	_dump_EnumObjects_flags(dwFlags);
+	DPRINTF("\n");
+    }
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(
+	LPDIRECTINPUTDEVICE8W iface,
+	LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags)
+{
+    FIXME("(this=%p,%p,%p,%08lx): stub!\n", iface, lpCallback, lpvRef, dwFlags);
+    if (TRACE_ON(dinput)) {
+	DPRINTF("  - flags = ");
+	_dump_EnumObjects_flags(dwFlags);
+	DPRINTF("\n");
+    }
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
+	LPDIRECTINPUTDEVICE8A iface,
+	REFGUID rguid,
+	LPDIPROPHEADER pdiph)
+{
+    FIXME("(this=%p,%s,%p): stub!\n",
+	  iface, debugstr_guid(rguid), pdiph);
+    
+    if (TRACE_ON(dinput))
+	_dump_DIPROPHEADER(pdiph);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIDEVICEOBJECTINSTANCEA pdidoi,
+	DWORD dwObj,
+	DWORD dwHow)
+{
+    FIXME("(this=%p,%p,%ld,0x%08lx): stub!\n",
+	  iface, pdidoi, dwObj, dwHow);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(
+	LPDIRECTINPUTDEVICE8W iface,
+	LPDIDEVICEOBJECTINSTANCEW pdidoi,
+	DWORD dwObj,
+	DWORD dwHow)
+{
+    FIXME("(this=%p,%p,%ld,0x%08lx): stub!\n",
+	  iface, pdidoi, dwObj, dwHow);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIDEVICEINSTANCEA pdidi)
+{
+    FIXME("(this=%p,%p): stub!\n",
+	  iface, pdidi);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceInfo(
+	LPDIRECTINPUTDEVICE8W iface,
+	LPDIDEVICEINSTANCEW pdidi)
+{
+    FIXME("(this=%p,%p): stub!\n",
+	  iface, pdidi);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
+	LPDIRECTINPUTDEVICE8A iface,
+	HWND hwndOwner,
+	DWORD dwFlags)
+{
+    FIXME("(this=%p,%p,0x%08lx): stub!\n",
+	  iface, hwndOwner, dwFlags);
+
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
+	LPDIRECTINPUTDEVICE8A iface,
+	HINSTANCE hinst,
+	DWORD dwVersion,
+	REFGUID rguid)
+{
+    FIXME("(this=%p,%p,%ld,%s): stub!\n",
+	  iface, hinst, dwVersion, debugstr_guid(rguid));
+    return DI_OK;
+}
+
+/******************************************************************************
+ *	IDirectInputDevice2A
+ */
+
+HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
+	LPDIRECTINPUTDEVICE8A iface,
+	REFGUID rguid,
+	LPCDIEFFECT lpeff,
+	LPDIRECTINPUTEFFECT *ppdef,
+	LPUNKNOWN pUnkOuter)
+{
+    FIXME("(this=%p,%s,%p,%p,%p): stub!\n",
+	  iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIENUMEFFECTSCALLBACKA lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags)
+{
+    FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
+	  iface, lpCallback, lpvRef, dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
+	LPDIRECTINPUTDEVICE8W iface,
+	LPDIENUMEFFECTSCALLBACKW lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags)
+{
+    FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
+	  iface, lpCallback, lpvRef, dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIEFFECTINFOA lpdei,
+	REFGUID rguid)
+{
+    FIXME("(this=%p,%p,%s): stub!\n",
+	  iface, lpdei, debugstr_guid(rguid));
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo(
+	LPDIRECTINPUTDEVICE8W iface,
+	LPDIEFFECTINFOW lpdei,
+	REFGUID rguid)
+{
+    FIXME("(this=%p,%p,%s): stub!\n",
+	  iface, lpdei, debugstr_guid(rguid));
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDWORD pdwOut)
+{
+    FIXME("(this=%p,%p): stub!\n",
+	  iface, pdwOut);
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
+	LPDIRECTINPUTDEVICE8A iface,
+	DWORD dwFlags)
+{
+    FIXME("(this=%p,0x%08lx): stub!\n",
+	  iface, dwFlags);
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags)
+{
+    FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
+	  iface, lpCallback, lpvRef, dwFlags);
+    if (lpCallback)
+	lpCallback(NULL, lpvRef);
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIEFFESCAPE lpDIEEsc)
+{
+    FIXME("(this=%p,%p): stub!\n",
+	  iface, lpDIEEsc);
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
+	LPDIRECTINPUTDEVICE8A iface)
+{
+    /* Because wine devices do not need to be polled, just return DI_NOEFFECT */
+    return DI_NOEFFECT;
+}
+
+HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
+	LPDIRECTINPUTDEVICE8A iface,
+	DWORD cbObjectData,
+	LPCDIDEVICEOBJECTDATA rgdod,
+	LPDWORD pdwInOut,
+	DWORD dwFlags)
+{
+    FIXME("(this=%p,0x%08lx,%p,%p,0x%08lx): stub!\n",
+	  iface, cbObjectData, rgdod, pdwInOut, dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface,
+							  LPCSTR lpszFileName,
+							  LPDIENUMEFFECTSINFILECALLBACK pec,
+							  LPVOID pvRef,
+							  DWORD dwFlags)
+{
+    FIXME("(%p)->(%s,%p,%p,%08lx): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface,
+							  LPCWSTR lpszFileName,
+							  LPDIENUMEFFECTSINFILECALLBACK pec,
+							  LPVOID pvRef,
+							  DWORD dwFlags)
+{
+    FIXME("(%p)->(%s,%p,%p,%08lx): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface,
+							  LPCSTR lpszFileName,
+							  DWORD dwEntries,
+							  LPDIFILEEFFECT rgDiFileEft,
+							  DWORD dwFlags)
+{
+    FIXME("(%p)->(%s,%08lx,%p,%08lx): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface,
+							  LPCWSTR lpszFileName,
+							  DWORD dwEntries,
+							  LPDIFILEEFFECT rgDiFileEft,
+							  DWORD dwFlags)
+{
+    FIXME("(%p)->(%s,%08lx,%p,%08lx): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice8AImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,
+						       LPDIACTIONFORMATA lpdiaf,
+						       LPCSTR lpszUserName,
+						       DWORD dwFlags)
+{
+    FIXME("(%p)->(%p,%s,%08lx): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
+						       LPDIACTIONFORMATW lpdiaf,
+						       LPCWSTR lpszUserName,
+						       DWORD dwFlags)
+{
+    FIXME("(%p)->(%p,%s,%08lx): stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
+  
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice8AImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
+						     LPDIACTIONFORMATA lpdiaf,
+						     LPCSTR lpszUserName,
+						     DWORD dwFlags)
+{
+    FIXME("(%p)->(%p,%s,%08lx): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice8WImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
+						     LPDIACTIONFORMATW lpdiaf,
+						     LPCWSTR lpszUserName,
+						     DWORD dwFlags)
+{
+    FIXME("(%p)->(%p,%s,%08lx): stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
+						     LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
+{
+    FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
+    
+    return DI_OK;
+}
+
+HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
+						     LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
+{
+    FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
+    
+    return DI_OK;
+}
 
reactos/lib/dinput
diff -N device_private.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ device_private.h	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2000 Lionel Ulmer
+ * Copyright 2000-2001 TransGaming Technologies Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_DLLS_DINPUT_DINPUTDEVICE_PRIVATE_H
+#define __WINE_DLLS_DINPUT_DINPUTDEVICE_PRIVATE_H
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "dinput.h"
+
+/* Device implementation */
+typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
+struct IDirectInputDevice2AImpl
+{
+        IDirectInputDevice2AVtbl       *lpVtbl;
+        DWORD                           ref;
+        GUID                            guid;
+};
+
+/* Routines to do DataFormat / WineFormat conversions */
+typedef struct {
+  int size;
+  int offset_in;
+  int offset_out;
+  int value;
+} DataTransform;
+
+typedef struct {
+  int size;
+  int internal_format_size;
+  DataTransform *dt;
+} DataFormat;
+extern void fill_DataFormat(void *out, const void *in, DataFormat *df) ;
+extern DataFormat *create_DataFormat(const DIDATAFORMAT *wine_format, LPCDIDATAFORMAT asked_format, int *offset) ;
+extern void release_DataFormat(DataFormat *df) ;
+
+/* Used to fill events in the queue */
+#define GEN_EVENT(offset,data,xtime,seq)					\
+{										\
+  /* If queue_len > 0, queuing is requested -> TRACE the event queued */	\
+  if (This->queue_len > 0) {							\
+    int nq;									\
+    TRACE(" queueing %d at offset %d (queue head %d / size %d)\n", 		\
+	  (int) (data), (int) (offset),                           		\
+	  (int) (This->queue_head), (int) (This->queue_len));			\
+										\
+    nq = This->queue_head+1;							\
+    while (nq >= This->queue_len) nq -= This->queue_len;			\
+    if ((offset >= 0) && (nq != This->queue_tail)) {				\
+      This->data_queue[This->queue_head].dwOfs = offset;			\
+      This->data_queue[This->queue_head].dwData = data;				\
+      This->data_queue[This->queue_head].dwTimeStamp = xtime;			\
+      This->data_queue[This->queue_head].dwSequence = seq;			\
+      This->queue_head = nq;							\
+    } else                                                                      \
+      This->overflow = TRUE;                                                    \
+  }										\
+}
+
+/**
+ * Callback Data used by specific callback 
+ *  for EnumObject on 'W' interfaces
+ */
+typedef struct {
+  LPDIENUMDEVICEOBJECTSCALLBACKW lpCallBack;
+  LPVOID lpvRef;
+} device_enumobjects_AtoWcb_data;
+
+extern BOOL DIEnumDevicesCallbackAtoW(LPCDIDEVICEOBJECTINSTANCEA, LPVOID);
+
+
+/* Various debug tools */
+extern void _dump_cooperativelevel_DI(DWORD dwFlags) ;
+extern void _dump_EnumObjects_flags(DWORD dwFlags) ;
+extern void _dump_DIPROPHEADER(LPCDIPROPHEADER diph) ;
+extern void _dump_OBJECTINSTANCEA(DIDEVICEOBJECTINSTANCEA *ddoi) ;
+extern void _dump_OBJECTINSTANCEW(DIDEVICEOBJECTINSTANCEW *ddoi) ;
+extern void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) ;
+extern const char *_dump_dinput_GUID(const GUID *guid) ;
+
+/* And the stubs */
+extern HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
+	LPDIRECTINPUTDEVICE8A iface,LPCDIDATAFORMAT df ) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
+	LPDIRECTINPUTDEVICE8A iface,HWND hwnd,DWORD dwflags ) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
+	LPDIRECTINPUTDEVICE8A iface,HANDLE hnd ) ;
+extern ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface,REFIID riid,LPVOID *ppobj);
+extern HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W iface,REFIID riid,LPVOID *ppobj);
+extern ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
+	LPDIRECTINPUTDEVICE8A iface) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(
+	LPDIRECTINPUTDEVICE8W iface,
+	LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
+	LPDIRECTINPUTDEVICE8A iface,
+	REFGUID rguid,
+	LPDIPROPHEADER pdiph) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIDEVICEOBJECTINSTANCEA pdidoi,
+	DWORD dwObj,
+	DWORD dwHow) ;
+extern HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, 
+							     LPDIDEVICEOBJECTINSTANCEW pdidoi,
+							     DWORD dwObj,
+							     DWORD dwHow);
+extern HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIDEVICEINSTANCEA pdidi) ;
+extern HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceInfo(
+	LPDIRECTINPUTDEVICE8W iface,
+	LPDIDEVICEINSTANCEW pdidi) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
+	LPDIRECTINPUTDEVICE8A iface,
+	HWND hwndOwner,
+	DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
+	LPDIRECTINPUTDEVICE8A iface,
+	HINSTANCE hinst,
+	DWORD dwVersion,
+	REFGUID rguid) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
+	LPDIRECTINPUTDEVICE8A iface,
+	REFGUID rguid,
+	LPCDIEFFECT lpeff,
+	LPDIRECTINPUTEFFECT *ppdef,
+	LPUNKNOWN pUnkOuter) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIENUMEFFECTSCALLBACKA lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
+	LPDIRECTINPUTDEVICE8W iface,
+	LPDIENUMEFFECTSCALLBACKW lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIEFFECTINFOA lpdei,
+	REFGUID rguid) ;
+extern HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo(
+	LPDIRECTINPUTDEVICE8W iface,
+	LPDIEFFECTINFOW lpdei,
+	REFGUID rguid) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDWORD pdwOut) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
+	LPDIRECTINPUTDEVICE8A iface,
+	DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIEFFESCAPE lpDIEEsc) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
+	LPDIRECTINPUTDEVICE8A iface) ;
+extern HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
+	LPDIRECTINPUTDEVICE8A iface,
+	DWORD cbObjectData,
+	LPCDIDEVICEOBJECTDATA rgdod,
+	LPDWORD pdwInOut,
+	DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface,
+								 LPCSTR lpszFileName,
+								 LPDIENUMEFFECTSINFILECALLBACK pec,
+								 LPVOID pvRef,
+								 DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface,
+								 LPCWSTR lpszFileName,
+								 LPDIENUMEFFECTSINFILECALLBACK pec,
+								 LPVOID pvRef,
+								 DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface,
+								 LPCSTR lpszFileName,
+								 DWORD dwEntries,
+								 LPDIFILEEFFECT rgDiFileEft,
+								 DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface,
+								 LPCWSTR lpszFileName,
+								 DWORD dwEntries,
+								 LPDIFILEEFFECT rgDiFileEft,
+								 DWORD dwFlags) ;
+extern HRESULT WINAPI IDirectInputDevice8AImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,
+							      LPDIACTIONFORMATA lpdiaf,
+							      LPCSTR lpszUserName,
+							      DWORD dwFlags);
+extern HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
+							      LPDIACTIONFORMATW lpdiaf,
+							      LPCWSTR lpszUserName,
+							      DWORD dwFlags);
+extern HRESULT WINAPI IDirectInputDevice8AImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
+							    LPDIACTIONFORMATA lpdiaf,
+							    LPCSTR lpszUserName,
+							    DWORD dwFlags);
+extern HRESULT WINAPI IDirectInputDevice8WImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
+							    LPDIACTIONFORMATW lpdiaf,
+							    LPCWSTR lpszUserName,
+							    DWORD dwFlags);
+extern HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
+							    LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader);
+extern HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
+							    LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader);
+
+#endif /* __WINE_DLLS_DINPUT_DINPUTDEVICE_PRIVATE_H */
 
reactos/lib/dinput
diff -N dinput.stubs.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dinput.stubs.c	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,3 @@
+/* File generated automatically from dinput.spec; do not edit! */
+/* This file can be copied, modified and distributed without restriction. */
+
 
reactos/lib/dinput
diff -N dinput_main.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dinput_main.c	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,756 @@
+/*		DirectInput
+ *
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1998,1999 Lionel Ulmer
+ * Copyright 2000-2002 TransGaming Technologies Inc.
+ *
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* Status:
+ *
+ * - Tomb Raider 2 Demo:
+ *   Playable using keyboard only.
+ * - WingCommander Prophecy Demo:
+ *   Doesn't get Input Focus.
+ *
+ * - Fallout : works great in X and DGA mode
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define COBJMACROS
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "dinput_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+
+static IDirectInput7AVtbl ddi7avt;
+static IDirectInput7WVtbl ddi7wvt;
+static IDirectInput8AVtbl ddi8avt;
+static IDirectInput8WVtbl ddi8wvt;
+
+/* This array will be filled a dinput.so loading */
+#define MAX_WINE_DINPUT_DEVICES 4
+static dinput_device * dinput_devices[MAX_WINE_DINPUT_DEVICES];
+static int nrof_dinput_devices = 0;
+
+HINSTANCE DINPUT_instance = NULL;
+
+BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv)
+{
+    switch(reason)
+    {
+      case DLL_PROCESS_ATTACH:
+        DisableThreadLibraryCalls(inst);
+        DINPUT_instance = inst;
+        break;
+      case DLL_PROCESS_DETACH:
+        break;
+    }
+    return TRUE;
+}
+
+/* register a direct draw driver. We better not use malloc for we are in
+ * the ELF startup initialisation at this point.
+ */
+void dinput_register_device(dinput_device *device) {
+    int	i;
+
+    /* insert according to priority */
+    for (i=0;i<nrof_dinput_devices;i++) {
+	if (dinput_devices[i]->pref <= device->pref) {
+	    memcpy(dinput_devices+i+1,dinput_devices+i,sizeof(dinput_devices[0])*(nrof_dinput_devices-i));
+	    dinput_devices[i] = device;
+	    break;
+	}
+    }
+    if (i==nrof_dinput_devices)	/* not found, or too low priority */
+	dinput_devices[nrof_dinput_devices] = device;
+
+    nrof_dinput_devices++;
+
+    /* increase MAX_DDRAW_DRIVERS if the line below triggers */
+    assert(nrof_dinput_devices <= MAX_WINE_DINPUT_DEVICES);
+}
+
+/******************************************************************************
+ *	DirectInputCreateEx (DINPUT.@)
+ */
+HRESULT WINAPI DirectInputCreateEx(
+	HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI,
+	LPUNKNOWN punkOuter) 
+{
+	IDirectInputImpl* This;
+
+	TRACE("(0x%08lx,%04lx,%s,%p,%p)\n", (DWORD)hinst,dwVersion,debugstr_guid(riid),ppDI,punkOuter);
+
+	if (IsEqualGUID(&IID_IDirectInputA,riid) ||
+	    IsEqualGUID(&IID_IDirectInput2A,riid) ||
+	    IsEqualGUID(&IID_IDirectInput7A,riid)) {
+	  This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
+	  This->lpVtbl = &ddi7avt;
+	  This->ref = 1;
+	  This->version = 1;
+	  *ppDI = This;
+
+	  return DI_OK;
+	}
+
+	if (IsEqualGUID(&IID_IDirectInputW,riid) ||
+	    IsEqualGUID(&IID_IDirectInput2W,riid) ||
+	    IsEqualGUID(&IID_IDirectInput7W,riid)) {
+	  This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
+	  This->lpVtbl = &ddi7wvt;
+	  This->ref = 1;
+	  This->version = 1;
+	  *ppDI = This;
+
+	  return DI_OK;
+	}
+
+	if (IsEqualGUID(&IID_IDirectInput8A,riid)) {
+	  This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
+	  This->lpVtbl = &ddi8avt;
+	  This->ref = 1;
+	  This->version = 8;
+	  *ppDI = This;
+
+	  return DI_OK;
+	}
+
+	if (IsEqualGUID(&IID_IDirectInput8W,riid)) {
+	  This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
+	  This->lpVtbl = &ddi8wvt;
+	  This->ref = 1;
+	  This->version = 8;
+	  *ppDI = This;
+
+	  return DI_OK;
+	}
+
+	return DIERR_OLDDIRECTINPUTVERSION;
+}
+
+/******************************************************************************
+ *	DirectInputCreateA (DINPUT.@)
+ */
+HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
+{
+	IDirectInputImpl* This;
+	TRACE("(0x%08lx,%04lx,%p,%p)\n", (DWORD)hinst,dwVersion,ppDI,punkOuter);
+
+	//trace:dinput:DirectInputCreateA (0x00400000,0500,0x42bafc54,(nil))
+	This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
+	This->lpVtbl = &ddi7avt;
+	This->ref = 1;
+	if (dwVersion > 0x0700) {
+	    This->version = 8;
+	} else {
+	    /* We do not differientiate between version 1, 2 and 7 */
+	    This->version = 1;
+	}
+	*ppDI = (IDirectInputA*)This;
+	return 0;
+
+}
+
+/******************************************************************************
+ *	DirectInputCreateW (DINPUT.@)
+ */
+HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter)
+{
+	IDirectInputImpl* This;
+	TRACE("(0x%08lx,%04lx,%p,%p)\n", (DWORD)hinst,dwVersion,ppDI,punkOuter);
+	This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
+	This->lpVtbl = &ddi7wvt;
+	This->ref = 1;
+	if (dwVersion >= 0x0800) {
+	    This->version = 8;
+	} else {
+	    /* We do not differientiate between version 1, 2 and 7 */
+	    This->version = 1;
+	}
+	*ppDI = (IDirectInputW*)This;
+	return 0;
+}
+
+static char *_dump_DIDEVTYPE_value(DWORD dwDevType) {
+    switch (dwDevType) {
+        case 0: return "All devices";
+	case DIDEVTYPE_MOUSE: return "DIDEVTYPE_MOUSE";
+	case DIDEVTYPE_KEYBOARD: return "DIDEVTYPE_KEYBOARD";
+	case DIDEVTYPE_JOYSTICK: return "DIDEVTYPE_JOYSTICK";
+	case DIDEVTYPE_DEVICE: return "DIDEVTYPE_DEVICE";
+	default: return "Unkown";
+    }
+}
+
+static void _dump_EnumDevices_dwFlags(DWORD dwFlags) {
+    if (TRACE_ON(dinput)) {
+	unsigned int   i;
+	static const struct {
+	    DWORD       mask;
+	    const char  *name;
+	} flags[] = {
+#define FE(x) { x, #x}
+	    FE(DIEDFL_ALLDEVICES),
+	    FE(DIEDFL_ATTACHEDONLY),
+	    FE(DIEDFL_FORCEFEEDBACK),
+	    FE(DIEDFL_INCLUDEALIASES),
+	    FE(DIEDFL_INCLUDEPHANTOMS)
+#undef FE
+	};
+	if (dwFlags == 0) {
+	    DPRINTF("DIEDFL_ALLDEVICES");
+	    return;
+	}
+	for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
+	    if (flags[i].mask & dwFlags)
+		DPRINTF("%s ",flags[i].name);
+    }
+}
+
+/******************************************************************************
+ *	IDirectInputA_EnumDevices
+ */
+static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
+	LPDIRECTINPUT7A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
+	LPVOID pvRef, DWORD dwFlags)
+{
+    IDirectInputImpl *This = (IDirectInputImpl *)iface;
+    DIDEVICEINSTANCEA devInstance;
+    int i, j, r;
+    
+    TRACE("(this=%p,0x%04lx '%s',%p,%p,%04lx)\n",
+	  This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),
+	  lpCallback, pvRef, dwFlags);
+
+	if (nrof_dinput_devices==0){
+	  scan_mouse();
+	  scan_keyboard();
+	}
+	
+    TRACE(" flags: "); _dump_EnumDevices_dwFlags(dwFlags); TRACE("\n");
+    
+
+    for (i = 0; i < nrof_dinput_devices; i++) {
+        for (j = 0, r = -1; r != 0; j++) {
+	    devInstance.dwSize = sizeof(devInstance);
+	    TRACE("  - checking device %d ('%s')\n", i, dinput_devices[i]->name);
+		
+
+	    if ((r = dinput_devices[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->version, j))) {
+	        if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
+		    return 0;
+	    }
+	}
+    }
+    
+    return 0;
+}
+/******************************************************************************
+ *	IDirectInputW_EnumDevices
+ */
+static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
+	LPDIRECTINPUT7W iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback,
+	LPVOID pvRef, DWORD dwFlags) 
+{
+    IDirectInputImpl *This = (IDirectInputImpl *)iface;
+    DIDEVICEINSTANCEW devInstance;
+    int i, j, r;
+    
+		if (nrof_dinput_devices==0){
+	  scan_mouse();
+	  scan_keyboard();
+	}
+
+    TRACE("(this=%p,0x%04lx '%s',%p,%p,%04lx)\n",
+	  This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),
+	  lpCallback, pvRef, dwFlags);
+    TRACE(" flags: "); _dump_EnumDevices_dwFlags(dwFlags); TRACE("\n");
+
+
+    for (i = 0; i < nrof_dinput_devices; i++) {
+        for (j = 0, r = -1; r != 0; j++) {
+	    devInstance.dwSize = sizeof(devInstance);
+	    TRACE("  - checking device %d ('%s')\n", i, dinput_devices[i]->name);
+	    if ((r = dinput_devices[i]->enum_deviceW(dwDevType, dwFlags, &devInstance, This->version, j))) {
+	        if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
+		    return 0;
+	    }
+	}
+    }
+    
+    return 0;
+}
+
+static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)
+{
+	IDirectInputImpl *This = (IDirectInputImpl *)iface;
+	return InterlockedIncrement((&This->ref));
+}
+
+static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
+{
+	IDirectInputImpl *This = (IDirectInputImpl *)iface;
+	ULONG ref;
+	ref = InterlockedDecrement(&(This->ref));
+	if (ref == 0)
+		HeapFree(GetProcessHeap(),0,This);
+	return ref;
+}
+
+static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, REFIID riid, LPVOID *ppobj) {
+	IDirectInputImpl *This = (IDirectInputImpl *)iface;
+
+	TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+	if (IsEqualGUID(&IID_IUnknown,riid) ||
+	    IsEqualGUID(&IID_IDirectInputA,riid) ||
+	    IsEqualGUID(&IID_IDirectInput2A,riid) ||
+	    IsEqualGUID(&IID_IDirectInput7A,riid)) {
+		IDirectInputAImpl_AddRef(iface);
+		*ppobj = This;
+		return 0;
+	}
+	TRACE("Unsupported interface !\n");
+	return E_FAIL;
+}
+
+static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, REFIID riid, LPVOID *ppobj) {
+	IDirectInputImpl *This = (IDirectInputImpl *)iface;
+
+	TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+	if (IsEqualGUID(&IID_IUnknown,riid) ||
+	    IsEqualGUID(&IID_IDirectInputW,riid) ||
+	    IsEqualGUID(&IID_IDirectInput2W,riid) ||
+	    IsEqualGUID(&IID_IDirectInput7W,riid)) {
+		IDirectInputAImpl_AddRef((LPDIRECTINPUT7A) iface);
+		*ppobj = This;
+		return 0;
+	}
+	TRACE("Unsupported interface !\n");
+	return E_FAIL;
+}
+
+static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
+	LPDIRECTINPUT7A iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
+	LPUNKNOWN punk
+) {
+	IDirectInputImpl *This = (IDirectInputImpl *)iface;
+	HRESULT ret_value = DIERR_DEVICENOTREG;
+	int i;
+
+	TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);
+	
+	if (nrof_dinput_devices==0){
+	  scan_mouse();
+	  scan_keyboard();
+	}
+	
+	/* Loop on all the devices to see if anyone matches the given GUID */
+	for (i = 0; i < nrof_dinput_devices; i++) {
+	  HRESULT ret;
+	  if ((ret = dinput_devices[i]->create_deviceA(This, rguid, NULL, pdev)) == DI_OK)
+	    return DI_OK;
+
+	  if (ret == DIERR_NOINTERFACE)
+	    ret_value = DIERR_NOINTERFACE;
+	}
+
+	return ret_value;
+}
+
+static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7A iface, 
+						     REFGUID rguid, LPDIRECTINPUTDEVICEW* pdev, LPUNKNOWN punk) {
+        IDirectInputImpl *This = (IDirectInputImpl *)iface;
+	HRESULT ret_value = DIERR_DEVICENOTREG;
+	int i;
+    
+	TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);
+
+	if (nrof_dinput_devices==0){
+	  scan_mouse();
+	  scan_keyboard();
+	}
+	
+	/* Loop on all the devices to see if anyone matches the given GUID */
+	for (i = 0; i < nrof_dinput_devices; i++) {
+	  HRESULT ret;
+	  if ((ret = dinput_devices[i]->create_deviceW(This, rguid, NULL, pdev)) == DI_OK)
+	    return DI_OK;
+
+	  if (ret == DIERR_NOINTERFACE)
+	    ret_value = DIERR_NOINTERFACE;
+	}
+
+	return ret_value;
+}
+
+static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTANCE hinst, DWORD x) {
+	return DIERR_ALREADYINITIALIZED;
+}
+
+static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface,
+							REFGUID rguid) {
+  IDirectInputImpl *This = (IDirectInputImpl *)iface;
+
+  FIXME("(%p)->(%s): stub\n",This,debugstr_guid(rguid));
+
+  return DI_OK;
+}
+
+static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
+							HWND hwndOwner,
+							DWORD dwFlags) {
+  IDirectInputImpl *This = (IDirectInputImpl *)iface;
+  FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
+
+  return DI_OK;
+}
+
+static HRESULT WINAPI IDirectInput2AImpl_FindDevice(LPDIRECTINPUT7A iface, REFGUID rguid,
+						    LPCSTR pszName, LPGUID pguidInstance) {
+  IDirectInputImpl *This = (IDirectInputImpl *)iface;
+  FIXME("(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), pszName, pguidInstance);
+
+  return DI_OK;
+}
+
+static HRESULT WINAPI IDirectInput2WImpl_FindDevice(LPDIRECTINPUT7W iface, REFGUID rguid,
+						    LPCWSTR pszName, LPGUID pguidInstance) {
+  IDirectInputImpl *This = (IDirectInputImpl *)iface;
+  FIXME("(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), debugstr_w(pszName), pguidInstance);
+
+  return DI_OK;
+}
+
+static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, REFGUID rguid,
+							REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
+{
+  IDirectInputImpl *This = (IDirectInputImpl *)iface;
+  HRESULT ret_value = DIERR_DEVICENOTREG;
+  int i;
+
+  TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
+
+  if (nrof_dinput_devices==0){
+    scan_mouse();
+    scan_keyboard();
+  }  
+
+  /* Loop on all the devices to see if anyone matches the given GUID */
+  for (i = 0; i < nrof_dinput_devices; i++) {
+    HRESULT ret;
+    if ((ret = dinput_devices[i]->create_deviceA(This, rguid, riid, (LPDIRECTINPUTDEVICEA*) pvOut)) == DI_OK)
+      return DI_OK;
+
+    if (ret == DIERR_NOINTERFACE)
+      ret_value = DIERR_NOINTERFACE;
+  }
+
+  return ret_value;
+}
+
+static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, REFGUID rguid,
+							REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
+{
+  IDirectInputImpl *This = (IDirectInputImpl *)iface;
+  HRESULT ret_value = DIERR_DEVICENOTREG;
+  int i;
+
+  TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
+
+  	if (nrof_dinput_devices==0){
+	  scan_mouse();
+	  scan_keyboard();
+	}
+  
+
+
+  /* Loop on all the devices to see if anyone matches the given GUID */
+  for (i = 0; i < nrof_dinput_devices; i++) {
+    HRESULT ret;
+    if ((ret = dinput_devices[i]->create_deviceW(This, rguid, riid, (LPDIRECTINPUTDEVICEW*) pvOut)) == DI_OK)
+      return DI_OK;
+
+    if (ret == DIERR_NOINTERFACE)
+      ret_value = DIERR_NOINTERFACE;
+  }
+
+  return ret_value;
+}
+
+static HRESULT WINAPI IDirectInput8AImpl_QueryInterface(LPDIRECTINPUT8A iface, REFIID riid, LPVOID *ppobj) {
+      IDirectInputImpl *This = (IDirectInputImpl *)iface;
+
+      TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+      if (IsEqualGUID(&IID_IUnknown,riid) ||
+          IsEqualGUID(&IID_IDirectInput8A,riid)) {
+              IDirectInputAImpl_AddRef((LPDIRECTINPUT7A) iface);
+              *ppobj = This;
+              return 0;
+      }
+      TRACE("Unsupported interface !\n");
+      return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI IDirectInput8WImpl_QueryInterface(LPDIRECTINPUT8W iface, REFIID riid, LPVOID *ppobj) {
+      IDirectInputImpl *This = (IDirectInputImpl *)iface;
+
+      TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+      if (IsEqualGUID(&IID_IUnknown,riid) ||
+          IsEqualGUID(&IID_IDirectInput8W,riid)) {
+              IDirectInputAImpl_AddRef((LPDIRECTINPUT7A) iface);
+              *ppobj = This;
+              return 0;
+      }
+      TRACE("Unsupported interface !\n");
+      return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
+      LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat,
+      LPDIENUMDEVICESBYSEMANTICSCBA lpCallback,
+      LPVOID pvRef, DWORD dwFlags
+)
+{
+      IDirectInputImpl *This = (IDirectInputImpl *)iface;
+
+      FIXME("(this=%p,%s,%p,%p,%p,%04lx): stub\n", This, ptszUserName, lpdiActionFormat,
+            lpCallback, pvRef, dwFlags);
+      return 0;
+}
+
+static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
+      LPDIRECTINPUT8W iface, LPCWSTR ptszUserName, LPDIACTIONFORMATW lpdiActionFormat,
+      LPDIENUMDEVICESBYSEMANTICSCBW lpCallback,
+      LPVOID pvRef, DWORD dwFlags
+)
+{
+      IDirectInputImpl *This = (IDirectInputImpl *)iface;
+
+      FIXME("(this=%p,%s,%p,%p,%p,%04lx): stub\n", This, debugstr_w(ptszUserName), lpdiActionFormat,
+            lpCallback, pvRef, dwFlags);
+      return 0;
+}
+
+static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
+      LPDIRECTINPUT8A iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
+      LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData
+)
+{
+      IDirectInputImpl *This = (IDirectInputImpl *)iface;
+
+      FIXME("(this=%p,%p,%p,%04lx,%p): stub\n", This, lpdiCallback, lpdiCDParams,
+            dwFlags, pvRefData);
+      return 0;
+}
+
+static HRESULT WINAPI IDirectInput8WImpl_ConfigureDevices(
+      LPDIRECTINPUT8W iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
+      LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData
+)
+{
+      IDirectInputImpl *This = (IDirectInputImpl *)iface;
+
+      FIXME("(this=%p,%p,%p,%04lx,%p): stub\n", This, lpdiCallback, lpdiCDParams,
+            dwFlags, pvRefData);
+      return 0;
+}
+
+#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
+# define XCAST(fun)   (typeof(ddi7avt.fun))
+#else
+# define XCAST(fun)	(void*)
+#endif
+
+static IDirectInput7AVtbl ddi7avt = {
+	XCAST(QueryInterface)IDirectInputAImpl_QueryInterface,
+	XCAST(AddRef)IDirectInputAImpl_AddRef,
+	XCAST(Release)IDirectInputAImpl_Release,
+	XCAST(CreateDevice)IDirectInputAImpl_CreateDevice,
+	XCAST(EnumDevices)IDirectInputAImpl_EnumDevices,
+	XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
+	XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
+	XCAST(Initialize)IDirectInputAImpl_Initialize,
+	XCAST(FindDevice)IDirectInput2AImpl_FindDevice,
+	XCAST(CreateDeviceEx)IDirectInput7AImpl_CreateDeviceEx
+};
+
+#undef XCAST
+#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
+# define XCAST(fun)   (typeof(ddi7wvt.fun))
+#else
+# define XCAST(fun)	(void*)
+#endif
+
+static IDirectInput7WVtbl ddi7wvt = {
+	XCAST(QueryInterface)IDirectInputWImpl_QueryInterface,
+	XCAST(AddRef)IDirectInputAImpl_AddRef,
+	XCAST(Release)IDirectInputAImpl_Release,
+	XCAST(CreateDevice)IDirectInputWImpl_CreateDevice,
+	XCAST(EnumDevices)IDirectInputWImpl_EnumDevices,
+	XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
+	XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
+	XCAST(Initialize)IDirectInputAImpl_Initialize,
+	XCAST(FindDevice)IDirectInput2WImpl_FindDevice,
+	XCAST(CreateDeviceEx)IDirectInput7WImpl_CreateDeviceEx
+};
+#undef XCAST
+
+#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
+# define XCAST(fun)	(typeof(ddi8avt.fun))
+#else
+# define XCAST(fun)	(void*)
+#endif
+
+static IDirectInput8AVtbl ddi8avt = {
+	XCAST(QueryInterface)IDirectInput8AImpl_QueryInterface,
+	XCAST(AddRef)IDirectInputAImpl_AddRef,
+	XCAST(Release)IDirectInputAImpl_Release,
+	XCAST(CreateDevice)IDirectInputAImpl_CreateDevice,
+	XCAST(EnumDevices)IDirectInputAImpl_EnumDevices,
+	XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
+	XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
+	XCAST(Initialize)IDirectInputAImpl_Initialize,
+	XCAST(FindDevice)IDirectInput2AImpl_FindDevice,
+	XCAST(EnumDevicesBySemantics)IDirectInput8AImpl_EnumDevicesBySemantics,
+	XCAST(ConfigureDevices)IDirectInput8AImpl_ConfigureDevices
+};
+#undef XCAST
+
+#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
+# define XCAST(fun)	(typeof(ddi8wvt.fun))
+#else
+# define XCAST(fun)	(void*)
+#endif
+static IDirectInput8WVtbl ddi8wvt = {
+	XCAST(QueryInterface)IDirectInput8WImpl_QueryInterface,
+	XCAST(AddRef)IDirectInputAImpl_AddRef,
+	XCAST(Release)IDirectInputAImpl_Release,
+	XCAST(CreateDevice)IDirectInputWImpl_CreateDevice,
+	XCAST(EnumDevices)IDirectInputWImpl_EnumDevices,
+	XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
+	XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
+	XCAST(Initialize)IDirectInputAImpl_Initialize,
+	XCAST(FindDevice)IDirectInput2WImpl_FindDevice,
+	XCAST(EnumDevicesBySemantics)IDirectInput8WImpl_EnumDevicesBySemantics,
+	XCAST(ConfigureDevices)IDirectInput8WImpl_ConfigureDevices
+};
+#undef XCAST
+
+/*******************************************************************************
+ * DirectInput ClassFactory
+ */
+typedef struct
+{
+    /* IUnknown fields */
+    IClassFactoryVtbl          *lpVtbl;
+    DWORD                       ref;
+} IClassFactoryImpl;
+
+static HRESULT WINAPI DICF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
+	IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+
+	FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
+	return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DICF_AddRef(LPCLASSFACTORY iface) {
+	IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+	return InterlockedIncrement(&(This->ref));
+}
+
+static ULONG WINAPI DICF_Release(LPCLASSFACTORY iface) {
+	IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+	/* static class, won't be  freed */
+	return InterlockedDecrement(&(This->ref));
+}
+
+static HRESULT WINAPI DICF_CreateInstance(
+	LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
+) {
+	IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+
+	TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
+	if ( IsEqualGUID( &IID_IDirectInputA, riid ) ||
+	     IsEqualGUID( &IID_IDirectInputW, riid ) ||
+	     IsEqualGUID( &IID_IDirectInput2A, riid ) ||
+	     IsEqualGUID( &IID_IDirectInput2W, riid ) ||
+	     IsEqualGUID( &IID_IDirectInput7A, riid ) ||
+	     IsEqualGUID( &IID_IDirectInput7W, riid ) ||
+	     IsEqualGUID( &IID_IDirectInput8A, riid ) ||
+	     IsEqualGUID( &IID_IDirectInput8W, riid ) ) {
+		/* FIXME: reuse already created dinput if present? */
+		return DirectInputCreateEx(0,0,riid,ppobj,pOuter);
+	}
+
+	FIXME("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);	
+	return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI DICF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
+	IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+	FIXME("(%p)->(%d),stub!\n",This,dolock);
+	return S_OK;
+}
+
+static IClassFactoryVtbl DICF_Vtbl = {
+	DICF_QueryInterface,
+	DICF_AddRef,
+	DICF_Release,
+	DICF_CreateInstance,
+	DICF_LockServer
+};
+static IClassFactoryImpl DINPUT_CF = {&DICF_Vtbl, 1 };
+
+/***********************************************************************
+ *		DllCanUnloadNow (DINPUT.@)
+ */
+HRESULT WINAPI DINPUT_DllCanUnloadNow(void)
+{
+    FIXME("(void): stub\n");
+
+    return S_FALSE;
+}
+
+/***********************************************************************
+ *		DllGetClassObject (DINPUT.@)
+ */
+HRESULT WINAPI DINPUT_DllGetClassObject(REFCLSID rclsid, REFIID riid,
+					LPVOID *ppv)
+{
+    TRACE("(%p,%p,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+    if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
+    	*ppv = (LPVOID)&DINPUT_CF;
+	IClassFactory_AddRef((IClassFactory*)*ppv);
+    return S_OK;
+    }
+
+    FIXME("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+    return CLASS_E_CLASSNOTAVAILABLE;
+}
 
reactos/lib/dinput
diff -N dinput_private.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dinput_private.h	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000 Lionel Ulmer
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_DLLS_DINPUT_DINPUT_PRIVATE_H
+#define __WINE_DLLS_DINPUT_DINPUT_PRIVATE_H
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "dinput.h"
+
+/* Implementation specification */
+typedef struct IDirectInputImpl IDirectInputImpl;
+struct IDirectInputImpl
+{
+   LPVOID lpVtbl;
+   DWORD  ref;
+
+   /* Used to have an unique sequence number for all the events */
+   DWORD evsequence;
+
+   int version;
+};
+
+/* Function called by all devices that Wine supports */
+typedef struct dinput_device {
+    INT pref;
+    const char *name;
+    BOOL (*enum_deviceA)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, int version, int id);
+    BOOL (*enum_deviceW)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, int version, int id);
+    HRESULT (*create_deviceA)(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev);
+    HRESULT (*create_deviceW)(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev);
+} dinput_device;
+
+extern void dinput_register_device(dinput_device *device);
+
+extern HINSTANCE DINPUT_instance;
+
+void scan_keyboard();
+void scan_mouse();
+
+#endif /* __WINE_DLLS_DINPUT_DINPUT_PRIVATE_H */
 
reactos/lib/dinput
diff -N joystick_linux.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ joystick_linux.c	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,1715 @@
+/*		DirectInput Joystick device
+ *
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1998,1999 Lionel Ulmer
+ * Copyright 2000-2001 TransGaming Technologies Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * To Do:
+ *	dead zone
+ *	force feedback
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#ifdef HAVE_LINUX_22_JOYSTICK_API
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/fcntl.h>
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_SYS_ERRNO_H
+# include <sys/errno.h>
+#endif
+#ifdef HAVE_LINUX_IOCTL_H
+# include <linux/ioctl.h>
+#endif
+#ifdef HAVE_LINUX_JOYSTICK_H
+# include <linux/joystick.h>
+#endif
+#define JOYDEV	"/dev/js"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "dinput.h"
+
+#include "dinput_private.h"
+#include "device_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+
+typedef struct {
+    LONG lMin;
+    LONG lMax;
+    LONG lDeadZone;
+    LONG lSaturation;
+} ObjProps;
+
+typedef struct {
+    LONG lX;
+    LONG lY;
+} POV;
+
+typedef struct JoystickImpl JoystickImpl;
+static IDirectInputDevice8AVtbl JoystickAvt;
+static IDirectInputDevice8WVtbl JoystickWvt;
+struct JoystickImpl
+{
+        LPVOID                          lpVtbl;
+        DWORD                           ref;
+        GUID                            guid;
+	char				dev[32];
+
+	/* The 'parent' DInput */
+	IDirectInputImpl               *dinput;
+
+	/* joystick private */
+	int				joyfd;
+	DIJOYSTATE2			js;		/* wine data */
+	LPDIDATAFORMAT			user_df;	/* user defined format */
+	DataFormat			*transform;	/* wine to user format converter */
+	int				*offsets;	/* object offsets */
+	ObjProps			*props;
+        HANDLE				hEvent;
+        LPDIDEVICEOBJECTDATA 		data_queue;
+        int				queue_head, queue_tail, queue_len;
+	BOOL				acquired;
+	char				*name;
+	DIDEVCAPS			devcaps;
+	LONG				deadzone;
+	int				*axis_map;
+	int				axes;
+	int				buttons;
+	POV				povs[4];
+	CRITICAL_SECTION		crit;
+	BOOL				overflow;
+};
+
+static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
+  0x9e573ed9,
+  0x7734,
+  0x11d2,
+  {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
+};
+
+static void _dump_DIDEVCAPS(LPDIDEVCAPS lpDIDevCaps)
+{
+    TRACE("dwSize: %ld\n", lpDIDevCaps->dwSize);
+    TRACE("dwFlags: %08lx\n",lpDIDevCaps->dwFlags);
+    TRACE("dwDevType: %08lx %s\n", lpDIDevCaps->dwDevType,
+          lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
+          lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
+          lpDIDevCaps->dwDevType == DIDEVTYPE_MOUSE ? "DIDEVTYPE_MOUSE" :
+          lpDIDevCaps->dwDevType == DIDEVTYPE_KEYBOARD ? "DIDEVTYPE_KEYBOARD" :
+          lpDIDevCaps->dwDevType == DIDEVTYPE_JOYSTICK ? "DIDEVTYPE_JOYSTICK" :
+          lpDIDevCaps->dwDevType == DIDEVTYPE_HID ? "DIDEVTYPE_HID" : "UNKNOWN");
+    TRACE("dwAxes: %ld\n",lpDIDevCaps->dwAxes);
+    TRACE("dwButtons: %ld\n",lpDIDevCaps->dwButtons);
+    TRACE("dwPOVs: %ld\n",lpDIDevCaps->dwPOVs);
+    if (lpDIDevCaps->dwSize > sizeof(DIDEVCAPS_DX3)) {
+        TRACE("dwFFSamplePeriod: %ld\n",lpDIDevCaps->dwFFSamplePeriod);
+        TRACE("dwFFMinTimeResolution: %ld\n",lpDIDevCaps->dwFFMinTimeResolution);
+        TRACE("dwFirmwareRevision: %ld\n",lpDIDevCaps->dwFirmwareRevision);
+        TRACE("dwHardwareRevision: %ld\n",lpDIDevCaps->dwHardwareRevision);
+        TRACE("dwFFDriverVersion: %ld\n",lpDIDevCaps->dwFFDriverVersion);
+    }
+}
+
+static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, int version, int id)
+{
+    int fd = -1;
+    char dev[32];
+
+    if (dwFlags & DIEDFL_FORCEFEEDBACK) {
+        WARN("force feedback not supported\n");
+        return FALSE;
+    }
+
+    if ((dwDevType==0) || (GET_DIDEVICE_TYPE(dwDevType)==DIDEVTYPE_JOYSTICK)) {
+        /* check whether we have a joystick */
+        sprintf(dev, "%s%d", JOYDEV, id);
+        if ((fd = open(dev,O_RDONLY)) < 0) {
+            WARN("open(%s,O_RDONLY) failed: %s\n", dev, strerror(errno));
+            return FALSE;
+        }
+
+        /* Return joystick */
+        lpddi->guidInstance = DInput_Wine_Joystick_GUID;
+        lpddi->guidInstance.Data3 = id;
+        lpddi->guidProduct = DInput_Wine_Joystick_GUID;
+        /* we only support traditional joysticks for now */
+        if (version >= 8)
+            lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
+        else
+            lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
+        sprintf(lpddi->tszInstanceName, "Joystick %d", id);
+#if defined(JSIOCGNAME)
+        if (ioctl(fd,JSIOCGNAME(sizeof(lpddi->tszProductName)),lpddi->tszProductName) < 0) {
+            WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", dev, strerror(errno));
+            strcpy(lpddi->tszProductName, "Wine Joystick");
+        }
+#else
+        strcpy(lpddi->tszProductName, "Wine Joystick");
+#endif
+
+        lpddi->guidFFDriver = GUID_NULL;
+        close(fd);
+        TRACE("Enumerating the linux Joystick device: %s (%s)\n", dev, lpddi->tszProductName);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, int version, int id)
+{
+    int fd = -1;
+    char name[MAX_PATH];
+    char dev[32];
+    char friendly[32];
+
+    if (dwFlags & DIEDFL_FORCEFEEDBACK) {
+        WARN("force feedback not supported\n");
+        return FALSE;
+    }
+
+    if ((dwDevType==0) || (GET_DIDEVICE_TYPE(dwDevType)==DIDEVTYPE_JOYSTICK)) {
+        /* check whether we have a joystick */
+        sprintf(dev, "%s%d", JOYDEV, id);
+        if ((fd = open(dev,O_RDONLY)) < 0) {
+            WARN("open(%s,O_RDONLY) failed: %s\n", dev, strerror(errno));
+            return FALSE;
+        }
+
+        /* Return joystick */
+        lpddi->guidInstance = DInput_Wine_Joystick_GUID;
+        lpddi->guidInstance.Data3 = id;
+        lpddi->guidProduct = DInput_Wine_Joystick_GUID;
+        /* we only support traditional joysticks for now */
+        if (version >= 8)
+            lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
+        else
+            lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
+        sprintf(friendly, "Joystick %d", id);
+        MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH);
+#if defined(JSIOCGNAME)
+        if (ioctl(fd,JSIOCGNAME(sizeof(name)),name) < 0) {
+            WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", dev, strerror(errno));
+            strcpy(name, "Wine Joystick");
+        }
+#else
+        strcpy(name, "Wine Joystick");
+#endif
+        MultiByteToWideChar(CP_ACP, 0, name, -1, lpddi->tszProductName, MAX_PATH);
+        lpddi->guidFFDriver = GUID_NULL;
+        close(fd);
+        TRACE("Enumerating the linux Joystick device: %s (%s)\n",dev,name);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*
+ * Get a config key from either the app-specific or the default config
+ */
+
+inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
+                                    char *buffer, DWORD size )
+{
+    if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, buffer, &size ))
+        return 0;
+
+    if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, buffer, &size ))
+        return 0;
+
+    return ERROR_FILE_NOT_FOUND;
+}
+
+/*
+ * Setup the dinput options.
+ */
+
+static HRESULT setup_dinput_options(JoystickImpl * device)
+{
+    char buffer[MAX_PATH+1];
+    HKEY hkey, appkey = 0;
+    DWORD len;
+
+    buffer[MAX_PATH]='\0';
+
+    if (RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\dinput", &hkey)) hkey = 0;
+
+    len = GetModuleFileNameA( 0, buffer, MAX_PATH );
+    if (len && len < MAX_PATH) {
+        HKEY tmpkey;
+
+        if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\AppDefaults", &tmpkey )) {
+           char appname[MAX_PATH+16];
+           char *p = strrchr( buffer, '\\' );
+           if (p!=NULL) {
+                   strcpy(appname,p+1);
+                   strcat(appname,"\\dinput");
+                   TRACE("appname = [%s] \n",appname);
+                   if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
+           }
+           RegCloseKey( tmpkey );
+        }
+    }
+
+    /* get options */
+
+    if (!get_config_key( hkey, appkey, "DefaultDeadZone", buffer, MAX_PATH )) {
+        device->deadzone = atoi(buffer);
+        TRACE("setting default deadzone to: \"%s\" %ld\n", buffer, device->deadzone);
+    }
+
+    if (!get_config_key( hkey, appkey, device->name, buffer, MAX_PATH )) {
+        int tokens = 0;
+        int axis = 0;
+        int pov = 0;
+        char *delim = ",";
+        char * ptr;
+        TRACE("\"%s\" = \"%s\"\n", device->name, buffer);
+
+        device->axis_map = HeapAlloc(GetProcessHeap(), 0, device->axes * sizeof(int));
+        if (device->axis_map == 0)
+            return DIERR_OUTOFMEMORY;
+
+        if ((ptr = strtok(buffer, delim)) != NULL) {
+            do {
+                if (strcmp(ptr, "X") == 0) {
+                    device->axis_map[tokens] = 0;
+                    axis++;
+                } else if (strcmp(ptr, "Y") == 0) {
+                    device->axis_map[tokens] = 1;
+                    axis++;
+                } else if (strcmp(ptr, "Z") == 0) {
+                    device->axis_map[tokens] = 2;
+                    axis++;
+                } else if (strcmp(ptr, "Rx") == 0) {
+                    device->axis_map[tokens] = 3;
+                    axis++;
+                } else if (strcmp(ptr, "Ry") == 0) {
+                    device->axis_map[tokens] = 4;
+                    axis++;
+                } else if (strcmp(ptr, "Rz") == 0) {
+                    device->axis_map[tokens] = 5;
+                    axis++;
+                } else if (strcmp(ptr, "Slider1") == 0) {
+                    device->axis_map[tokens] = 6;
+                    axis++;
+                } else if (strcmp(ptr, "Slider2") == 0) {
+                    device->axis_map[tokens] = 7;
+                    axis++;
+                } else if (strcmp(ptr, "POV1") == 0) {
+                    device->axis_map[tokens++] = 8;
+                    device->axis_map[tokens] = 8;
+                    pov++;
+                } else if (strcmp(ptr, "POV2") == 0) {
+                    device->axis_map[tokens++] = 9;
+                    device->axis_map[tokens] = 9;
+                    pov++;
+                } else if (strcmp(ptr, "POV3") == 0) {
+                    device->axis_map[tokens++] = 10;
+                    device->axis_map[tokens] = 10;
+                    pov++;
+                } else if (strcmp(ptr, "POV4") == 0) {
+                    device->axis_map[tokens++] = 11;
+                    device->axis_map[tokens] = 11;
+                    pov++;
+                } else {
+                    ERR("invalid joystick axis type: %s\n", ptr);
+                    device->axis_map[tokens] = tokens;
+                    axis++;
+                }
+
+                tokens++;
+            } while ((ptr = strtok(NULL, delim)) != NULL);
+
+            if (tokens != device->devcaps.dwAxes) {
+                ERR("not all joystick axes mapped: %d axes(%d,%d), %d arguments\n", device->axes, axis, pov,tokens);
+                while (tokens < device->axes) {
+                    device->axis_map[tokens] = tokens;
+                    tokens++;
+                }
+            }
+        }
+
+        device->devcaps.dwAxes = axis;
+        device->devcaps.dwPOVs = pov;
+    }
+
+    if (appkey)
+        RegCloseKey( appkey );
+
+    if (hkey)
+        RegCloseKey( hkey );
+
+    return DI_OK;
+}
+
+void calculate_ids(JoystickImpl* device)
+{
+    int i;
+    int axis = 0;
+    int button = 0;
+    int pov = 0;
+    int axis_base;
+    int pov_base;
+    int button_base;
+
+    /* Make two passes over the format. The first counts the number
+     * for each type and the second sets the id */
+    for (i = 0; i < device->user_df->dwNumObjs; i++) {
+        if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_AXIS)
+            axis++;
+        else if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_POV)
+            pov++;
+        else if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_BUTTON)
+            button++;
+    }
+
+    axis_base = 0;
+    pov_base = axis;
+    button_base = axis + pov;
+
+    axis = 0;
+    button = 0;
+    pov = 0;
+
+    for (i = 0; i < device->user_df->dwNumObjs; i++) {
+        DWORD type = 0;
+        if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_AXIS) {
+            axis++;
+            type = DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) |
+                DIDFT_MAKEINSTANCE(axis + axis_base);
+            TRACE("axis type = 0x%08lx\n", type);
+        } else if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_POV) {
+            pov++;
+            type = DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) |
+                DIDFT_MAKEINSTANCE(pov + pov_base);
+            TRACE("POV type = 0x%08lx\n", type);
+        } else if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_BUTTON) {
+            button++;
+            type = DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) |
+                DIDFT_MAKEINSTANCE(button + button_base);
+            TRACE("button type = 0x%08lx\n", type);
+        }
+        device->user_df->rgodf[i].dwType = type;
+    }
+}
+
+static HRESULT alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput, LPDIRECTINPUTDEVICEA* pdev)
+{
+    DWORD i;
+    JoystickImpl* newDevice;
+    char name[MAX_PATH];
+    HRESULT hr;
+
+    newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
+    if (newDevice == 0) {
+        WARN("out of memory\n");
+        *pdev = 0;
+        return DIERR_OUTOFMEMORY;
+    }
+
+    sprintf(newDevice->dev, "%s%d", JOYDEV, rguid->Data3);
+
+    if ((newDevice->joyfd = open(newDevice->dev,O_RDONLY)) < 0) {
+        WARN("open(%s,O_RDONLY) failed: %s\n", newDevice->dev, strerror(errno));
+        HeapFree(GetProcessHeap(), 0, newDevice);
+        return DIERR_DEVICENOTREG;
+    }
+
+    /* get the device name */
+#if defined(JSIOCGNAME)
+    if (ioctl(newDevice->joyfd,JSIOCGNAME(MAX_PATH),name) < 0) {
+        WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", newDevice->dev, strerror(errno));
+        strcpy(name, "Wine Joystick");
+    }
+#else
+    strcpy(name, "Wine Joystick");
+#endif
+
+    /* copy the device name */
+    newDevice->name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
+    strcpy(newDevice->name, name);
+
+#ifdef JSIOCGAXES
+    if (ioctl(newDevice->joyfd,JSIOCGAXES,&newDevice->axes) < 0) {
+        WARN("ioctl(%s,JSIOCGAXES) failed: %s, defauting to 2\n", newDevice->dev, strerror(errno));
+        newDevice->axes = 2;
+    }
+#endif
+#ifdef JSIOCGBUTTONS
+    if (ioctl(newDevice->joyfd,JSIOCGBUTTONS,&newDevice->buttons) < 0) {
+        WARN("ioctl(%s,JSIOCGBUTTONS) failed: %s, defauting to 2\n", newDevice->dev, strerror(errno));
+        newDevice->buttons = 2;
+    }
+#endif
+
+    newDevice->lpVtbl = jvt;
+    newDevice->ref = 1;
+    newDevice->dinput = dinput;
+    newDevice->acquired = FALSE;
+    newDevice->overflow = FALSE;
+    CopyMemory(&(newDevice->guid),rguid,sizeof(*rguid));
+
+    /* setup_dinput_options may change these */
+    newDevice->deadzone = 5000;
+    newDevice->devcaps.dwButtons = newDevice->buttons;
+    newDevice->devcaps.dwAxes = newDevice->axes;
+    newDevice->devcaps.dwPOVs = 0;
+
+    /* do any user specified configuration */
+    hr = setup_dinput_options(newDevice);
+    if (hr != DI_OK)
+        goto FAILED1;
+
+    if (newDevice->axis_map == 0) {
+        newDevice->axis_map = HeapAlloc(GetProcessHeap(), 0, newDevice->axes * sizeof(int));
+        if (newDevice->axis_map == 0)
+            goto FAILED;
+
+        for (i = 0; i < newDevice->axes; i++)
+            newDevice->axis_map[i] = i;
+    }
+
+    /* wine uses DIJOYSTATE2 as it's internal format so copy
+     * the already defined format c_dfDIJoystick2 */
+    newDevice->user_df = HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2.dwSize);
+    if (newDevice->user_df == 0)
+        goto FAILED;
+
+    CopyMemory(newDevice->user_df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
+
+    /* copy default objects */
+    newDevice->user_df->rgodf = HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2.dwNumObjs*c_dfDIJoystick2.dwObjSize);
+    if (newDevice->user_df->rgodf == 0)
+        goto FAILED;
+
+    CopyMemory(newDevice->user_df->rgodf,c_dfDIJoystick2.rgodf,c_dfDIJoystick2.dwNumObjs*c_dfDIJoystick2.dwObjSize);
+
+    /* create default properties */
+    newDevice->props = HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2.dwNumObjs*sizeof(ObjProps));
+    if (newDevice->props == 0)
+        goto FAILED;
+
+    /* initialize default properties */
+    for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++) {
+        newDevice->props[i].lMin = 0;
+        newDevice->props[i].lMax = 0xffff;
+        newDevice->props[i].lDeadZone = newDevice->deadzone;	/* % * 1000 */
+        newDevice->props[i].lSaturation = 0;
+    }
+
+    /* create an offsets array */
+    newDevice->offsets = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,c_dfDIJoystick2.dwNumObjs*sizeof(int));
+    if (newDevice->offsets == 0)
+        goto FAILED;
+
+    /* create the default transform filter */
+    newDevice->transform = create_DataFormat(&c_dfDIJoystick2, newDevice->user_df, newDevice->offsets);
+
+    calculate_ids(newDevice);
+
+    IDirectInputDevice_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput);
+    InitializeCriticalSection(&(newDevice->crit));
+    newDevice->crit.DebugInfo->Spare[1] = (DWORD)"DINPUT_Mouse";
+
+    newDevice->devcaps.dwSize = sizeof(newDevice->devcaps);
+    newDevice->devcaps.dwFlags = DIDC_ATTACHED;
+    newDevice->devcaps.dwDevType = DIDEVTYPE_JOYSTICK;
+    newDevice->devcaps.dwFFSamplePeriod = 0;
+    newDevice->devcaps.dwFFMinTimeResolution = 0;
+    newDevice->devcaps.dwFirmwareRevision = 0;
+    newDevice->devcaps.dwHardwareRevision = 0;
+    newDevice->devcaps.dwFFDriverVersion = 0;
+
+    if (TRACE_ON(dinput)) {
+        _dump_DIDATAFORMAT(newDevice->user_df);
+       for (i = 0; i < (newDevice->axes); i++)
+           TRACE("axis_map[%ld] = %d\n", i, newDevice->axis_map[i]);
+        _dump_DIDEVCAPS(&newDevice->devcaps);
+    }
+
+    *pdev = (LPDIRECTINPUTDEVICEA)newDevice;
+
+    return DI_OK;
+
+FAILED:
+    hr = DIERR_OUTOFMEMORY;
+FAILED1:
+    if (newDevice->axis_map)
+        HeapFree(GetProcessHeap(),0,newDevice->axis_map);
+    if (newDevice->name)
+        HeapFree(GetProcessHeap(),0,newDevice->name);
+    if (newDevice->props)
+        HeapFree(GetProcessHeap(),0,newDevice->props);
+    if (newDevice->user_df->rgodf)
+        HeapFree(GetProcessHeap(),0,newDevice->user_df->rgodf);
+    if (newDevice->user_df)
+        HeapFree(GetProcessHeap(),0,newDevice->user_df);
+    if (newDevice)
+        HeapFree(GetProcessHeap(),0,newDevice);
+    *pdev = 0;
+
+    return hr;
+}
+
+static BOOL IsJoystickGUID(REFGUID guid)
+{
+    GUID wine_joystick = DInput_Wine_Joystick_GUID;
+    GUID dev_guid = *guid;
+
+    wine_joystick.Data3 = 0;
+    dev_guid.Data3 = 0;
+
+    return IsEqualGUID(&wine_joystick, &dev_guid);
+}
+
+static HRESULT joydev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
+{
+  if ((IsEqualGUID(&GUID_Joystick,rguid)) ||
+      (IsJoystickGUID(rguid))) {
+    if ((riid == NULL) ||
+	IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
+      return alloc_device(rguid, &JoystickAvt, dinput, pdev);
+    } else {
+      WARN("no interface\n");
+      *pdev = 0;
+      return DIERR_NOINTERFACE;
+    }
+  }
+
+  WARN("invalid device GUID\n");
+  *pdev = 0;
+  return DIERR_DEVICENOTREG;
+}
+
+static HRESULT joydev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
+{
+  if ((IsEqualGUID(&GUID_Joystick,rguid)) ||
+      (IsJoystickGUID(rguid))) {
+    if ((riid == NULL) ||
+	IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
+      return alloc_device(rguid, &JoystickWvt, dinput, (LPDIRECTINPUTDEVICEA *)pdev);
+    } else {
+      WARN("no interface\n");
+      *pdev = 0;
+      return DIERR_NOINTERFACE;
+    }
+  }
+
+  WARN("invalid device GUID\n");
+  *pdev = 0;
+  return DIERR_DEVICENOTREG;
+}
+
+static dinput_device joydev = {
+  10,
+  "Wine Linux joystick driver",
+  joydev_enum_deviceA,
+  joydev_enum_deviceW,
+  joydev_create_deviceA,
+  joydev_create_deviceW
+};
+
+DECL_GLOBAL_CONSTRUCTOR(joydev_register) { dinput_register_device(&joydev); }
+
+
+
+/******************************************************************************
+ *	Joystick
+ */
+static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
+{
+    JoystickImpl *This = (JoystickImpl *)iface;
+    ULONG ref;
+
+    ref = InterlockedDecrement((&This->ref));
+    if (ref)
+        return ref;
+
+    /* Free the device name */
+    if (This->name)
+        HeapFree(GetProcessHeap(),0,This->name);
+
+    /* Free the axis map */
+    if (This->axis_map)
+        HeapFree(GetProcessHeap(),0,This->axis_map);
+
+    /* Free the data queue */
+    if (This->data_queue != NULL)
+        HeapFree(GetProcessHeap(),0,This->data_queue);
+
+    /* Free the DataFormat */
+    HeapFree(GetProcessHeap(), 0, This->user_df->rgodf);
+    HeapFree(GetProcessHeap(), 0, This->user_df);
+
+    /* Free the properties */
+    HeapFree(GetProcessHeap(), 0, This->props);
+
+    /* Free the offsets array */
+    HeapFree(GetProcessHeap(),0,This->offsets);
+
+    /* release the data transform filter */
+    release_DataFormat(This->transform);
+
+    This->crit.DebugInfo->Spare[1] = 0;
+    DeleteCriticalSection(&(This->crit));
+    IDirectInputDevice_Release((LPDIRECTINPUTDEVICE8A)This->dinput);
+
+    HeapFree(GetProcessHeap(),0,This);
+    return 0;
+}
+
+/******************************************************************************
+  *   SetDataFormat : the application can choose the format of the data
+  *   the device driver sends back with GetDeviceState.
+  */
+static HRESULT WINAPI JoystickAImpl_SetDataFormat(
+    LPDIRECTINPUTDEVICE8A iface,
+    LPCDIDATAFORMAT df)
+{
+    JoystickImpl *This = (JoystickImpl *)iface;
+    unsigned int i;
+    LPDIDATAFORMAT new_df = 0;
+    LPDIOBJECTDATAFORMAT new_rgodf = 0;
+    ObjProps * new_props = 0;
+
+    TRACE("(%p,%p)\n",This,df);
+
+    if (This->acquired) {
+        WARN("acquired\n");
+        return DIERR_ACQUIRED;
+    }
+
+    if (TRACE_ON(dinput))
+        _dump_DIDATAFORMAT(df);
+
+    /* Store the new data format */
+    new_df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
+    if (new_df == 0)
+        goto FAILED;
+
+    new_rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
+    if (new_rgodf == 0)
+        goto FAILED;
+
+    new_props = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*sizeof(ObjProps));
+    if (new_props == 0)
+        goto FAILED;
+
+    HeapFree(GetProcessHeap(),0,This->user_df);
+    HeapFree(GetProcessHeap(),0,This->user_df->rgodf);
+    HeapFree(GetProcessHeap(),0,This->props);
+    release_DataFormat(This->transform);
+
+    This->user_df = new_df;
+    CopyMemory(This->user_df, df, df->dwSize);
+    This->user_df->rgodf = new_rgodf;
+    CopyMemory(This->user_df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
+    This->props = new_props;
+    for (i = 0; i < df->dwNumObjs; i++) {
+        This->props[i].lMin = 0;
+        This->props[i].lMax = 0xffff;
+        This->props[i].lDeadZone = 1000;
+        This->props[i].lSaturation = 0;
+    }
+    This->transform = create_DataFormat(&c_dfDIJoystick2, This->user_df, This->offsets);
+
+    calculate_ids(This);
+
+    return DI_OK;
+
+FAILED:
+    WARN("out of memory\n");
+    if (new_props)
+        HeapFree(GetProcessHeap(),0,new_props);
+    if (new_rgodf)
+        HeapFree(GetProcessHeap(),0,new_rgodf);
+    if (new_df)
+        HeapFree(GetProcessHeap(),0,new_df);
+    return DIERR_OUTOFMEMORY;
+}
+
+/******************************************************************************
+  *     Acquire : gets exclusive control of the joystick
+  */
+static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
+{
+    JoystickImpl *This = (JoystickImpl *)iface;
+
+    TRACE("(%p)\n",This);
+
+    if (This->acquired) {
+        WARN("already acquired\n");
+        return S_FALSE;
+    }
+
+    /* open the joystick device */
+    if (This->joyfd==-1) {
+        TRACE("opening joystick device %s\n", This->dev);
+
+        This->joyfd=open(This->dev,O_RDONLY);
+        if (This->joyfd==-1) {
+            ERR("open(%s) failed: %s\n", This->dev, strerror(errno));
+            return DIERR_NOTFOUND;
+        }
+    }
+
+    This->acquired = TRUE;
+
+    return DI_OK;
+}
+
+/******************************************************************************
+  *     Unacquire : frees the joystick
+  */
+static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
+{
+    JoystickImpl *This = (JoystickImpl *)iface;
+
+    TRACE("(%p)\n",This);
+
+    if (!This->acquired) {
+        WARN("not acquired\n");
+        return DIERR_NOTACQUIRED;
+    }
+
+    if (This->joyfd!=-1) {
+        TRACE("closing joystick device\n");
+        close(This->joyfd);
+        This->joyfd = -1;
+        This->acquired = FALSE;
+        return DI_OK;
+    }
+
+    This->acquired = FALSE;
+
+    return DI_NOEFFECT;
+}
+
+LONG map_axis(JoystickImpl * This, short val, short index)
+{
+    double    fval = val;
+    double    fmin = This->props[index].lMin;
+    double    fmax = This->props[index].lMax;
+    double    fret;
+
+    fret = (((fval + 32767.0) * (fmax - fmin)) / (32767.0*2.0)) + fmin;
+
+    if (fret >= 0.0)
+        fret += 0.5;
+    else
+        fret -= 0.5;
+
+    return fret;
+}
+
+/* convert wine format offset to user format object index */
+int offset_to_object(JoystickImpl *This, int offset)
+{
+    int i;
+
+    for (i = 0; i < This->user_df->dwNumObjs; i++) {
+        if (This->user_df->rgodf[i].dwOfs == offset)
+            return i;
+    }
+
+    return -1;
+}
+
+static LONG calculate_pov(JoystickImpl *This, int index)
+{
+    if (This->povs[index].lX < 16384) {
+        if (This->povs[index].lY < 16384)
+            This->js.rgdwPOV[index] = 31500;
+        else if (This->povs[index].lY > 49150)
+            This->js.rgdwPOV[index] = 22500;
+        else
+            This->js.rgdwPOV[index] = 27000;
+    } else if (This->povs[index].lX > 49150) {
+        if (This->povs[index].lY < 16384)
+            This->js.rgdwPOV[index] = 4500;
+        else if (This->povs[index].lY > 49150)
+            This->js.rgdwPOV[index] = 13500;
+        else
+            This->js.rgdwPOV[index] = 9000;
+    } else {
+        if (This->povs[index].lY < 16384)
+            This->js.rgdwPOV[index] = 0;
+        else if (This->povs[index].lY > 49150)
+            This->js.rgdwPOV[index] = 18000;
+        else
+            This->js.rgdwPOV[index] = -1;
+    }
+
+    return This->js.rgdwPOV[index];
+}
+
+static void joy_polldev(JoystickImpl *This) {
+    struct timeval tv;
+    fd_set	readfds;
+    struct	js_event jse;
+    TRACE("(%p)\n", This);
+
+    if (This->joyfd==-1) {
+        WARN("no device\n");
+        return;
+    }
+    while (1) {
+	memset(&tv,0,sizeof(tv));
+	FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
+	if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
+	    return;
+	/* we have one event, so we can read */
+	if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
+	    return;
+	}
+        TRACE("js_event: type 0x%x, number %d, value %d\n",
+              jse.type,jse.number,jse.value);
+        if (jse.type & JS_EVENT_BUTTON) {
+            int offset = This->offsets[jse.number + 12];
+            int value = jse.value?0x80:0x00;
+
+            This->js.rgbButtons[jse.number] = value;
+            GEN_EVENT(offset,value,jse.time,(This->dinput->evsequence)++);
+        } else if (jse.type & JS_EVENT_AXIS) {
+            int number = This->axis_map[jse.number];	/* wine format object index */
+            if (number < 12) {
+                int offset = This->offsets[number];
+                int index = offset_to_object(This, offset);
+                LONG value = map_axis(This, jse.value, index);
+
+                /* FIXME do deadzone and saturation here */
+
+                TRACE("changing axis %d => %d\n", jse.number, number);
+                switch (number) {
+                case 0:
+                    This->js.lX = value;
+                    break;
+                case 1:
+                    This->js.lY = value;
+                    break;
+                case 2:
+                    This->js.lZ = value;
+                    break;
+                case 3:
+                    This->js.lRx = value;
+                    break;
+                case 4:
+                    This->js.lRy = value;
+                    break;
+                case 5:
+                    This->js.lRz = value;
+                    break;
+                case 6:
+                    This->js.rglSlider[0] = value;
+                    break;
+                case 7:
+                    This->js.rglSlider[1] = value;
+                    break;
+                case 8:
+                    /* FIXME don't go off array */
+                    if (This->axis_map[jse.number + 1] == number)
+                        This->povs[0].lX = value;
+                    else if (This->axis_map[jse.number - 1] == number)
+                        This->povs[0].lY = value;
+                    value = calculate_pov(This, 0);
+                    break;
+                case 9:
+                    if (This->axis_map[jse.number + 1] == number)
+                        This->povs[1].lX = value;
+                    else if (This->axis_map[jse.number - 1] == number)
+                        This->povs[1].lY = value;
+                    value = calculate_pov(This, 1);
+                    break;
+                case 10:
+                    if (This->axis_map[jse.number + 1] == number)
+                        This->povs[2].lX = value;
+                    else if (This->axis_map[jse.number - 1] == number)
+                        This->povs[2].lY = value;
+                    value = calculate_pov(This, 2);
+                    break;
+                case 11:
+                    if (This->axis_map[jse.number + 1] == number)
+                        This->povs[3].lX = value;
+                    else if (This->axis_map[jse.number - 1] == number)
+                        This->povs[3].lY = value;
+                    value = calculate_pov(This, 3);
+                    break;
+                }
+
+                GEN_EVENT(offset,value,jse.time,(This->dinput->evsequence)++);
+            } else
+                WARN("axis %d not supported\n", number);
+        }
+    }
+}
+
+/******************************************************************************
+  *     GetDeviceState : returns the "state" of the joystick.
+  *
+  */
+static HRESULT WINAPI JoystickAImpl_GetDeviceState(
+    LPDIRECTINPUTDEVICE8A iface,
[truncated at 1000 lines; 719 more skipped]
 
reactos/lib/dinput
diff -N joystick_linuxinput.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ joystick_linuxinput.c	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,1090 @@
+/*		DirectInput Joystick device
+ *
+ * Copyright 1998,2000 Marcus Meissner
+ * Copyright 1998,1999 Lionel Ulmer
+ * Copyright 2000-2001 TransGaming Technologies Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#ifdef HAVE_LINUX_INPUT_H
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/fcntl.h>
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_SYS_ERRNO_H
+# include <sys/errno.h>
+#endif
+
+#ifdef HAVE_CORRECT_LINUXINPUT_H
+
+#ifdef HAVE_LINUX_INPUT_H
+# include <linux/input.h>
+#endif
+
+
+#define EVDEVPREFIX	"/dev/input/event"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "dinput.h"
+
+#include "dinput_private.h"
+#include "device_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+
+/* Wine joystick driver object instances */
+#define WINE_JOYSTICK_AXIS_BASE   0
+#define WINE_JOYSTICK_BUTTON_BASE 8
+
+typedef struct JoystickImpl JoystickImpl;
+static IDirectInputDevice8AVtbl JoystickAvt;
+static IDirectInputDevice8WVtbl JoystickWvt;
+struct JoystickImpl
+{
+        LPVOID                          lpVtbl;
+        DWORD                           ref;
+        GUID                            guid;
+
+
+	/* The 'parent' DInput */
+	IDirectInputImpl               *dinput;
+
+	/* joystick private */
+	/* what range and deadzone the game wants */
+	LONG				wantmin[ABS_MAX];
+	LONG				wantmax[ABS_MAX];
+	LONG				deadz[ABS_MAX];
+
+	/* autodetecting ranges per axe by following movement */
+	LONG				havemax[ABS_MAX];
+	LONG				havemin[ABS_MAX];
+
+	int				joyfd;
+
+	LPDIDATAFORMAT			df;
+        HANDLE				hEvent;
+        LPDIDEVICEOBJECTDATA 		data_queue;
+        int				queue_head, queue_tail, queue_len;
+	BOOL				overflow;
+	DIJOYSTATE2			js;
+
+	/* data returned by the EVIOCGABS() ioctl */
+	int				axes[ABS_MAX+1][5];
+
+#define AXE_ABS		0
+#define AXE_ABSMIN	1
+#define AXE_ABSMAX	2
+#define AXE_ABSFUZZ	3
+#define AXE_ABSFLAT	4
+
+
+	/* data returned by EVIOCGBIT for EV_ABS and EV_KEY */
+	BYTE				absbits[(ABS_MAX+7)/8];
+	BYTE				keybits[(KEY_MAX+7)/8];
+};
+
+/* This GUID is slightly different from the linux joystick one. Take note. */
+static GUID DInput_Wine_Joystick_GUID = { /* 9e573eda-7734-11d2-8d4a-23903fb6bdf7 */
+  0x9e573eda,
+  0x7734,
+  0x11d2,
+  {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
+};
+
+static void fake_current_js_state(JoystickImpl *ji);
+
+#define test_bit(arr,bit) (((BYTE*)arr)[bit>>3]&(1<<(bit&7)))
+
+static int joydev_have(void)
+{
+  int i, fd;
+  int havejoy = 0;
+
+  for (i=0;i<64;i++) {
+      char	buf[200];
+      BYTE	absbits[(ABS_MAX+7)/8],keybits[(KEY_MAX+7)/8];
+
+      sprintf(buf,EVDEVPREFIX"%d",i);
+      if (-1!=(fd=open(buf,O_RDONLY))) {
+	  if (-1==ioctl(fd,EVIOCGBIT(EV_ABS,sizeof(absbits)),absbits)) {
+	      perror("EVIOCGBIT EV_ABS");
+	      close(fd);
+	      continue;
+	  }
+	  if (-1==ioctl(fd,EVIOCGBIT(EV_KEY,sizeof(keybits)),keybits)) {
+	      perror("EVIOCGBIT EV_KEY");
+	      close(fd);
+	      continue;
+	  }
+	  /* A true joystick has at least axis X and Y, and at least 1
+	   * button. copied from linux/drivers/input/joydev.c */
+	  if (test_bit(absbits,ABS_X) && test_bit(absbits,ABS_Y) &&
+	      (   test_bit(keybits,BTN_TRIGGER)	||
+		  test_bit(keybits,BTN_A) 	||
+		  test_bit(keybits,BTN_1)
+	      )
+	  ) {
+	      FIXME("found a joystick at %s!\n",buf);
+	      havejoy = 1;
+	  }
+	  close(fd);
+      }
+      if (havejoy || (errno==ENODEV))
+	  break;
+  }
+  return havejoy;
+}
+
+static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, int version, int id)
+{
+  int havejoy = 0;
+
+  if (id != 0)
+      return FALSE;
+
+  if ((dwDevType != 0) && (GET_DIDEVICE_TYPE(dwDevType) != DIDEVTYPE_JOYSTICK))
+      return FALSE;
+
+  if (dwFlags & DIEDFL_FORCEFEEDBACK)
+    return FALSE;
+
+  havejoy = joydev_have();
+
+  if (!havejoy)
+      return FALSE;
+
+  TRACE("Enumerating the linuxinput Joystick device\n");
+
+  /* Return joystick */
+  lpddi->guidInstance	= GUID_Joystick;
+  lpddi->guidProduct	= DInput_Wine_Joystick_GUID;
+
+  lpddi->guidFFDriver = GUID_NULL;
+  if (version >= 8)
+    lpddi->dwDevType    = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
+  else
+    lpddi->dwDevType    = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
+
+  strcpy(lpddi->tszInstanceName, "Joystick");
+  /* ioctl JSIOCGNAME(len) */
+  strcpy(lpddi->tszProductName,	"Wine Joystick");
+  return TRUE;
+}
+
+static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, int version, int id)
+{
+  int havejoy = 0;
+
+  if (id != 0)
+      return FALSE;
+
+  if ((dwDevType != 0) && (GET_DIDEVICE_TYPE(dwDevType) != DIDEVTYPE_JOYSTICK))
+      return FALSE;
+
+  if (dwFlags & DIEDFL_FORCEFEEDBACK)
+    return FALSE;
+
+  havejoy = joydev_have();
+
+  if (!havejoy)
+      return FALSE;
+
+  TRACE("Enumerating the linuxinput Joystick device\n");
+
+  /* Return joystick */
+  lpddi->guidInstance	= GUID_Joystick;
+  lpddi->guidProduct	= DInput_Wine_Joystick_GUID;
+
+  lpddi->guidFFDriver = GUID_NULL;
+  lpddi->dwDevType    = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL<<8);
+
+  MultiByteToWideChar(CP_ACP, 0, "Joystick", -1, lpddi->tszInstanceName, MAX_PATH);
+  /* ioctl JSIOCGNAME(len) */
+  MultiByteToWideChar(CP_ACP, 0, "Wine Joystick", -1, lpddi->tszProductName, MAX_PATH);
+  return TRUE;
+}
+
+static JoystickImpl *alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput)
+{
+  JoystickImpl* newDevice;
+  int i;
+
+  newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
+  newDevice->lpVtbl = jvt;
+  newDevice->ref = 1;
+  newDevice->joyfd = -1;
+  newDevice->dinput = dinput;
+  memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
+  for (i=0;i<ABS_MAX;i++) {
+    newDevice->wantmin[i] = -32768;
+    newDevice->wantmax[i] =  32767;
+    /* TODO: 
+     * direct input defines a default for the deadzone somewhere; but as long
+     * as in map_axis the code for the dead zone is commented out its no
+     * problem
+     */
+    newDevice->deadz[i]   =  0;
+  }
+  fake_current_js_state(newDevice);
+  return newDevice;
+}
+
+static HRESULT joydev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
+{
+  int havejoy = 0;
+
+  havejoy = joydev_have();
+
+  if (!havejoy)
+      return DIERR_DEVICENOTREG;
+
+  if ((IsEqualGUID(&GUID_Joystick,rguid)) ||
+      (IsEqualGUID(&DInput_Wine_Joystick_GUID,rguid))) {
+    if ((riid == NULL) ||
+	IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
+      *pdev = (IDirectInputDeviceA*) alloc_device(rguid, &JoystickAvt, dinput);
+      TRACE("Creating a Joystick device (%p)\n", *pdev);
+      return DI_OK;
+    } else
+      return DIERR_NOINTERFACE;
+  }
+
+  return DIERR_DEVICENOTREG;
+}
+
+
+static HRESULT joydev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
+{
+  int havejoy = 0;
+
+  havejoy = joydev_have();
+
+  if (!havejoy)
+      return DIERR_DEVICENOTREG;
+
+  if ((IsEqualGUID(&GUID_Joystick,rguid)) ||
+      (IsEqualGUID(&DInput_Wine_Joystick_GUID,rguid))) {
+    if ((riid == NULL) ||
+	IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
+      *pdev = (IDirectInputDeviceW*) alloc_device(rguid, &JoystickWvt, dinput);
+      TRACE("Creating a Joystick device (%p)\n", *pdev);
+      return DI_OK;
+    } else
+      return DIERR_NOINTERFACE;
+  }
+
+  return DIERR_DEVICENOTREG;
+}
+
+static dinput_device joydev = {
+  20,
+  "Wine Linux-input joystick driver",
+  joydev_enum_deviceA,
+  joydev_enum_deviceW,
+  joydev_create_deviceA,
+  joydev_create_deviceW
+};
+
+DECL_GLOBAL_CONSTRUCTOR(joydev_register) { dinput_register_device(&joydev); }
+
+/******************************************************************************
+ *	Joystick
+ */
+static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
+{
+	JoystickImpl *This = (JoystickImpl *)iface;
+	ULONG ref;
+
+	ref = InterlockedDecrement(&(This->ref));
+	if (ref)
+		return ref;
+
+	/* Free the data queue */
+	if (This->data_queue != NULL)
+	  HeapFree(GetProcessHeap(),0,This->data_queue);
+
+	/* Free the DataFormat */
+	HeapFree(GetProcessHeap(), 0, This->df);
+
+	HeapFree(GetProcessHeap(),0,This);
+	return 0;
+}
+
+/******************************************************************************
+  *   SetDataFormat : the application can choose the format of the data
+  *   the device driver sends back with GetDeviceState.
+  */
+static HRESULT WINAPI JoystickAImpl_SetDataFormat(
+	LPDIRECTINPUTDEVICE8A iface,LPCDIDATAFORMAT df
+)
+{
+  JoystickImpl *This = (JoystickImpl *)iface;
+
+  TRACE("(this=%p,%p)\n",This,df);
+
+  _dump_DIDATAFORMAT(df);
+  
+  /* Store the new data format */
+  This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
+  memcpy(This->df, df, df->dwSize);
+  This->df->rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
+  memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
+
+  return 0;
+}
+
+/******************************************************************************
+  *     Acquire : gets exclusive control of the joystick
+  */
+static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
+{
+    int		i;
+    JoystickImpl *This = (JoystickImpl *)iface;
+    char	buf[200];
+
+    TRACE("(this=%p)\n",This);
+    if (This->joyfd!=-1)
+    	return 0;
+    for (i=0;i<64;i++) {
+      sprintf(buf,EVDEVPREFIX"%d",i);
+      if (-1==(This->joyfd=open(buf,O_RDONLY))) {
+	if (errno==ENODEV)
+	  return DIERR_NOTFOUND;
+	perror(buf);
+	continue;
+      }
+      if ((-1!=ioctl(This->joyfd,EVIOCGBIT(EV_ABS,sizeof(This->absbits)),This->absbits)) &&
+          (-1!=ioctl(This->joyfd,EVIOCGBIT(EV_KEY,sizeof(This->keybits)),This->keybits)) &&
+          (test_bit(This->absbits,ABS_X) && test_bit(This->absbits,ABS_Y) &&
+	   (test_bit(This->keybits,BTN_TRIGGER)||
+	    test_bit(This->keybits,BTN_A)	 ||
+	    test_bit(This->keybits,BTN_1)
+	  )
+	 )
+      )
+	break;
+      close(This->joyfd);
+      This->joyfd = -1;
+    }
+    if (This->joyfd==-1)
+    	return DIERR_NOTFOUND;
+
+    for (i=0;i<ABS_MAX;i++) {
+	if (test_bit(This->absbits,i)) {
+	  if (-1==ioctl(This->joyfd,EVIOCGABS(i),&(This->axes[i])))
+	    continue;
+	  FIXME("axe %d: cur=%d, min=%d, max=%d, fuzz=%d, flat=%d\n",
+	      i,
+	      This->axes[i][AXE_ABS],
+	      This->axes[i][AXE_ABSMIN],
+	      This->axes[i][AXE_ABSMAX],
+	      This->axes[i][AXE_ABSFUZZ],
+	      This->axes[i][AXE_ABSFLAT]
+	  );
+	  This->havemin[i] = This->axes[i][AXE_ABSMIN];
+	  This->havemax[i] = This->axes[i][AXE_ABSMAX];
+	}
+    }
+    MESSAGE("\n");
+
+	fake_current_js_state(This);
+
+    return 0;
+}
+
+/******************************************************************************
+  *     Unacquire : frees the joystick
+  */
+static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
+{
+    JoystickImpl *This = (JoystickImpl *)iface;
+
+    TRACE("(this=%p)\n",This);
+    if (This->joyfd!=-1) {
+  	close(This->joyfd);
+	This->joyfd = -1;
+	return DI_OK;
+    }
+    else 
+    	return DI_NOEFFECT;
+}
+
+/*
+ * This maps the read value (from the input event) to a value in the
+ * 'wanted' range. It also autodetects the possible range of the axe and
+ * adapts values accordingly.
+ */
+static int
+map_axis(JoystickImpl* This, int axis, int val) {
+    int	xmin = This->axes[axis][AXE_ABSMIN];
+    int	xmax = This->axes[axis][AXE_ABSMAX];
+    int hmax = This->havemax[axis];
+    int hmin = This->havemin[axis];
+    int	wmin = This->wantmin[axis];
+    int	wmax = This->wantmax[axis];
+    int ret;
+
+    if (val > hmax) This->havemax[axis] = hmax = val;
+    if (val < hmin) This->havemin[axis] = hmin = val;
+
+    if (xmin == xmax) return val;
+
+    /* map the value from the hmin-hmax range into the wmin-wmax range */
+    ret = (val * (wmax-wmin)) / (hmax-hmin) + wmin;
+
+#if 0
+    /* deadzone doesn't work comfortably enough right now. needs more testing*/
+    if ((ret > -deadz/2 ) && (ret < deadz/2)) {
+        FIXME("%d in deadzone, return mid.\n",val);
+	return (wmax-wmin)/2+wmin;
+    }
+#endif
+    return ret;
+}
+
+/* 
+ * set the current state of the js device as it would be with the middle
+ * values on the axes
+ */
+static void fake_current_js_state(JoystickImpl *ji)
+{
+	ji->js.lX  = map_axis(ji, ABS_X,  ji->axes[ABS_X ][AXE_ABS]);
+	ji->js.lY  = map_axis(ji, ABS_Y,  ji->axes[ABS_Y ][AXE_ABS]);
+	ji->js.lZ  = map_axis(ji, ABS_Z,  ji->axes[ABS_Z ][AXE_ABS]);
+	ji->js.lRx = map_axis(ji, ABS_RX, ji->axes[ABS_RX][AXE_ABS]);
+	ji->js.lRy = map_axis(ji, ABS_RY, ji->axes[ABS_RY][AXE_ABS]);
+	ji->js.lRz = map_axis(ji, ABS_RZ, ji->axes[ABS_RZ][AXE_ABS]);
+}
+
+static void joy_polldev(JoystickImpl *This) {
+    struct timeval tv;
+    fd_set	readfds;
+    struct	input_event ie;
+
+    if (This->joyfd==-1)
+	return;
+
+    while (1) {
+	memset(&tv,0,sizeof(tv));
+	FD_ZERO(&readfds);
+	FD_SET(This->joyfd,&readfds);
+
+	if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
+	    return;
+
+	/* we have one event, so we can read */
+	if (sizeof(ie)!=read(This->joyfd,&ie,sizeof(ie)))
+	    return;
+
+	TRACE("input_event: type %d, code %d, value %d\n",ie.type,ie.code,ie.value);
+	switch (ie.type) {
+	case EV_KEY:	/* button */
+	    switch (ie.code) {
+	    case BTN_TRIGGER:	/* normal flight stick */
+	    case BTN_A:		/* gamepad */
+	    case BTN_1:		/* generic */
+		This->js.rgbButtons[0] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(0),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_THUMB:
+	    case BTN_B:
+	    case BTN_2:
+		This->js.rgbButtons[1] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(1),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_THUMB2:
+	    case BTN_C:
+	    case BTN_3:
+		This->js.rgbButtons[2] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(2),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_TOP:
+	    case BTN_X:
+	    case BTN_4:
+		This->js.rgbButtons[3] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(3),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_TOP2:
+	    case BTN_Y:
+	    case BTN_5:
+		This->js.rgbButtons[4] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(4),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_PINKIE:
+	    case BTN_Z:
+	    case BTN_6:
+		This->js.rgbButtons[5] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(5),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_BASE:
+	    case BTN_TL:
+	    case BTN_7:
+		This->js.rgbButtons[6] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(6),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_BASE2:
+	    case BTN_TR:
+	    case BTN_8:
+		This->js.rgbButtons[7] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(7),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_BASE3:
+	    case BTN_TL2:
+	    case BTN_9:
+		This->js.rgbButtons[8] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(8),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_BASE4:
+	    case BTN_TR2:
+		This->js.rgbButtons[9] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(9),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case BTN_BASE5:
+	    case BTN_SELECT:
+		This->js.rgbButtons[10] = ie.value?0x80:0x00;
+		GEN_EVENT(DIJOFS_BUTTON(10),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    default:
+		FIXME("unhandled joystick button %x, value %d\n",ie.code,ie.value);
+		break;
+	    }
+	    break;
+	case EV_ABS:
+	    switch (ie.code) {
+	    case ABS_X:
+		This->js.lX = map_axis(This,ABS_X,ie.value);
+		GEN_EVENT(DIJOFS_X,This->js.lX,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case ABS_Y:
+		This->js.lY = map_axis(This,ABS_Y,ie.value);
+		GEN_EVENT(DIJOFS_Y,This->js.lY,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case ABS_Z:
+		This->js.lZ = map_axis(This,ABS_Z,ie.value);
+		GEN_EVENT(DIJOFS_Z,This->js.lZ,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case ABS_RX:
+		This->js.lRx = map_axis(This,ABS_RX,ie.value);
+		GEN_EVENT(DIJOFS_RX,This->js.lRx,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case ABS_RY:
+		This->js.lRy = map_axis(This,ABS_RY,ie.value);
+		GEN_EVENT(DIJOFS_RY,This->js.lRy,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    case ABS_RZ:
+		This->js.lRz = map_axis(This,ABS_RZ,ie.value);
+		GEN_EVENT(DIJOFS_RZ,This->js.lRz,ie.time.tv_usec,(This->dinput->evsequence)++);
+		break;
+	    default:
+		FIXME("unhandled joystick axe event (code %d, value %d)\n",ie.code,ie.value);
+		break;
+	    }
+	    break;
+	default:
+	    FIXME("joystick cannot handle type %d event (code %d)\n",ie.type,ie.code);
+	    break;
+	}
+    }
+}
+
+/******************************************************************************
+  *     GetDeviceState : returns the "state" of the joystick.
+  *
+  */
+static HRESULT WINAPI JoystickAImpl_GetDeviceState(
+	LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
+) {
+    JoystickImpl *This = (JoystickImpl *)iface;
+
+    joy_polldev(This);
+
+    TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
+    if ((len != sizeof(DIJOYSTATE)) && (len != sizeof(DIJOYSTATE2))) {
+    	FIXME("len %ld is not sizeof(DIJOYSTATE) or DIJOYSTATE2, unsupported format.\n",len);
+	return E_FAIL;
+    }
+    memcpy(ptr,&(This->js),len);
+    This->queue_head = 0;
+    This->queue_tail = 0;
+    return 0;
+}
+
+/******************************************************************************
+  *     GetDeviceData : gets buffered input data.
+  */
+static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface,
+					      DWORD dodsize,
+					      LPDIDEVICEOBJECTDATA dod,
+					      LPDWORD entries,
+					      DWORD flags
+) {
+  JoystickImpl *This = (JoystickImpl *)iface;
+
+  FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
+
+  joy_polldev(This);
+  if (flags & DIGDD_PEEK)
+    FIXME("DIGDD_PEEK\n");
+
+  if (dod == NULL) {
+  } else {
+  }
+  return 0;
+}
+
+/******************************************************************************
+  *     SetProperty : change input device properties
+  */
+static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
+					    REFGUID rguid,
+					    LPCDIPROPHEADER ph)
+{
+  JoystickImpl *This = (JoystickImpl *)iface;
+
+  FIXME("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
+  FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
+
+  if (!HIWORD(rguid)) {
+    switch ((DWORD)rguid) {
+    case (DWORD) DIPROP_BUFFERSIZE: {
+      LPCDIPROPDWORD	pd = (LPCDIPROPDWORD)ph;
+
+      FIXME("buffersize = %ld\n",pd->dwData);
+      break;
+    }
+    case (DWORD)DIPROP_RANGE: {
+      LPCDIPROPRANGE	pr = (LPCDIPROPRANGE)ph;
+
+      FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
+      switch (ph->dwObj) {
+      case 0:	/* X */
+      case 4:	/* Y */
+      case 8:	/* Z */
+      case 12:  /* Rx */
+      case 16:  /* Ry */
+      case 20:  /* Rz */
+	  This->wantmin[ph->dwObj/4] = pr->lMin;
+	  This->wantmax[ph->dwObj/4] = pr->lMax;
+	  break;
+      default:
+	  FIXME("setting proprange %ld - %ld for dwObj %ld\n",pr->lMin,pr->lMax,ph->dwObj);
+      }
+      break;
+    }
+    case (DWORD)DIPROP_DEADZONE: {
+      LPCDIPROPDWORD	pd = (LPCDIPROPDWORD)ph;
+
+      FIXME("setting deadzone(%ld)\n",pd->dwData);
+      This->deadz[ph->dwObj/4] = pd->dwData;
+      break;
+    }
+    default:
+      FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+      break;
+    }
+  }
+  fake_current_js_state(This);
+  return 0;
+}
+
+/******************************************************************************
+  *     SetEventNotification : specifies event to be sent on state change
+  */
+static HRESULT WINAPI JoystickAImpl_SetEventNotification(
+	LPDIRECTINPUTDEVICE8A iface, HANDLE hnd
+) {
+    JoystickImpl *This = (JoystickImpl *)iface;
+
+    TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
+    This->hEvent = hnd;
+    return DI_OK;
+}
+
+static HRESULT WINAPI JoystickAImpl_GetCapabilities(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIDEVCAPS lpDIDevCaps)
+{
+    JoystickImpl *This = (JoystickImpl *)iface;
+    int		xfd = This->joyfd;
+    int		i,axes,buttons;
+    int		wasacquired = 1;
+
+    TRACE("%p->(%p)\n",iface,lpDIDevCaps);
+    if (xfd==-1) {
+	/* yes, games assume we return something, even if unacquired */
+	JoystickAImpl_Acquire(iface);
+	xfd = This->joyfd;
+	wasacquired = 0;
+    }
+    lpDIDevCaps->dwFlags	= DIDC_ATTACHED;
+    lpDIDevCaps->dwDevType	= DIDEVTYPE_JOYSTICK;
+
+    axes=0;
+    for (i=0;i<ABS_MAX;i++) if (test_bit(This->absbits,i)) axes++;
+    buttons=0;
+    for (i=0;i<KEY_MAX;i++) if (test_bit(This->keybits,i)) buttons++;
+
+    lpDIDevCaps->dwAxes = axes;
+    lpDIDevCaps->dwButtons = buttons;
+
+    if (!wasacquired)
+	JoystickAImpl_Unacquire(iface);
+
+    return DI_OK;
+}
+
+static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE8A iface) {
+    JoystickImpl *This = (JoystickImpl *)iface;
+    TRACE("(),stub!\n");
+
+    joy_polldev(This);
+    return DI_OK;
+}
+
+/******************************************************************************
+  *     EnumObjects : enumerate the different buttons and axis...
+  */
+static HRESULT WINAPI JoystickAImpl_EnumObjects(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags)
+{
+  JoystickImpl *This = (JoystickImpl *)iface;
+  DIDEVICEOBJECTINSTANCEA ddoi;
+  int xfd = This->joyfd;
+
+
+  TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
+  if (TRACE_ON(dinput)) {
+    TRACE("  - flags = ");
+    _dump_EnumObjects_flags(dwFlags);
+    TRACE("\n");
+  }
+
+  if (xfd == -1) return DIERR_NOTACQUIRED;
+
+  /* Only the fields till dwFFMaxForce are relevant */
+  ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
+
+  /* For the joystick, do as is done in the GetCapabilities function */
+  /* FIXME: needs more items */
+  if ((dwFlags == DIDFT_ALL) ||
+      (dwFlags & DIDFT_AXIS)) {
+    BYTE i;
+
+    for (i = 0; i < ABS_MAX; i++) {
+      if (!test_bit(This->absbits,i)) continue;
+
+      switch (i) {
+      case ABS_X:
+	ddoi.guidType = GUID_XAxis;
+	ddoi.dwOfs = DIJOFS_X;
+	break;
+      case ABS_Y:
+	ddoi.guidType = GUID_YAxis;
+	ddoi.dwOfs = DIJOFS_Y;
+	break;
+      case ABS_Z:
+	ddoi.guidType = GUID_ZAxis;
+	ddoi.dwOfs = DIJOFS_Z;
+	break;
+      case ABS_RX:
+	ddoi.guidType = GUID_RxAxis;
+	ddoi.dwOfs = DIJOFS_RX;
+	break;
+      case ABS_RY:
+	ddoi.guidType = GUID_RyAxis;
+	ddoi.dwOfs = DIJOFS_RY;
+	break;
+      case ABS_RZ:
+	ddoi.guidType = GUID_RzAxis;
+	ddoi.dwOfs = DIJOFS_RZ;
+	break;
+      case ABS_THROTTLE:
+	ddoi.guidType = GUID_Slider;
+	ddoi.dwOfs = DIJOFS_SLIDER(0);
+	break;
+      default:
+	FIXME("unhandled abs axis %d, ignoring!\n",i);
+      }
+      ddoi.dwType = DIDFT_MAKEINSTANCE((1<<i) << WINE_JOYSTICK_AXIS_BASE) | DIDFT_ABSAXIS;
+      sprintf(ddoi.tszName, "%d-Axis", i);
+      _dump_OBJECTINSTANCEA(&ddoi);
+      if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE)
+	  return DI_OK;
+    }
+  }
+
+  if ((dwFlags == DIDFT_ALL) ||
+      (dwFlags & DIDFT_BUTTON)) {
+    int i;
+
+    /*The DInput SDK says that GUID_Button is only for mouse buttons but well*/
+
+    ddoi.guidType = GUID_Button;
+
+    for (i = 0; i < KEY_MAX; i++) {
+      if (!test_bit(This->keybits,i)) continue;
+
+      switch (i) {
+      case BTN_TRIGGER:
+      case BTN_A:
+      case BTN_1:
+	  ddoi.dwOfs = DIJOFS_BUTTON(0);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 0) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_THUMB:
+	case BTN_B:
+	case BTN_2:
+	  ddoi.dwOfs = DIJOFS_BUTTON(1);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 1) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_THUMB2:
+	case BTN_C:
+	case BTN_3:
+	  ddoi.dwOfs = DIJOFS_BUTTON(2);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 2) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_TOP:
+	case BTN_X:
+	case BTN_4:
+	  ddoi.dwOfs = DIJOFS_BUTTON(3);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 3) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_TOP2:
+	case BTN_Y:
+	case BTN_5:
+	  ddoi.dwOfs = DIJOFS_BUTTON(4);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 4) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_PINKIE:
+	case BTN_Z:
+	case BTN_6:
+	  ddoi.dwOfs = DIJOFS_BUTTON(5);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 5) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_BASE:
+	case BTN_TL:
+	case BTN_7:
+	  ddoi.dwOfs = DIJOFS_BUTTON(6);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 6) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_BASE2:
+	case BTN_TR:
+	case BTN_8:
+	  ddoi.dwOfs = DIJOFS_BUTTON(7);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 7) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_BASE3:
+	case BTN_TL2:
+	case BTN_9:
+	  ddoi.dwOfs = DIJOFS_BUTTON(8);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 8) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_BASE4:
+	case BTN_TR2:
+	  ddoi.dwOfs = DIJOFS_BUTTON(9);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 9) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+	case BTN_BASE5:
+	case BTN_SELECT:
+	  ddoi.dwOfs = DIJOFS_BUTTON(10);
+	  ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 10) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
+	  break;
+      }
+      sprintf(ddoi.tszName, "%d-Button", i);
+      _dump_OBJECTINSTANCEA(&ddoi);
+      if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE)
+	  return DI_OK;
+    }
+  }
+
+  if (xfd!=This->joyfd)
+    close(xfd);
+
+  return DI_OK;
+}
+
+static HRESULT WINAPI JoystickWImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
+						LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
+						LPVOID lpvRef,
+						DWORD dwFlags)
+{
+  JoystickImpl *This = (JoystickImpl *)iface;
+
+  device_enumobjects_AtoWcb_data data;
+
+  data.lpCallBack = lpCallback;
+  data.lpvRef = lpvRef;
+
+  return JoystickAImpl_EnumObjects((LPDIRECTINPUTDEVICE8A) This, (LPDIENUMDEVICEOBJECTSCALLBACKA) DIEnumDevicesCallbackAtoW, (LPVOID) &data, dwFlags);
+}
+
+/******************************************************************************
+  *     GetProperty : get input device properties
+  */
+static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
+						REFGUID rguid,
+						LPDIPROPHEADER pdiph)
+{
+  JoystickImpl *This = (JoystickImpl *)iface;
+
+  TRACE("(this=%p,%s,%p): stub!\n",
+	iface, debugstr_guid(rguid), pdiph);
+
+  if (TRACE_ON(dinput))
+    _dump_DIPROPHEADER(pdiph);
+
+  if (!HIWORD(rguid)) {
+    switch ((DWORD)rguid) {
+    case (DWORD) DIPROP_BUFFERSIZE: {
+      LPDIPROPDWORD	pd = (LPDIPROPDWORD)pdiph;
+
+      TRACE(" return buffersize = %d\n",This->queue_len);
+      pd->dwData = This->queue_len;
+      break;
+    }
+
+    case (DWORD) DIPROP_RANGE: {
+      /* LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph; */
+      if ((pdiph->dwHow == DIPH_BYID) &&
+	  (pdiph->dwObj & DIDFT_ABSAXIS)) {
+	/* The app is querying the current range of the axis : return the lMin and lMax values */
+	FIXME("unimplemented axis range query.\n");
+      }
+
+      break;
[truncated at 1000 lines; 94 more skipped]
 
reactos/lib/dinput
diff -N keyboard.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ keyboard.c	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,868 @@
+/*		DirectInput Keyboard device
+ *
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1998,1999 Lionel Ulmer
+ * Copyright 2000-2001 TransGaming Technologies Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "dinput.h"
+
+#include "dinput_private.h"
+#include "device_private.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+
+//fast fix misning from mingw headers
+#ifdef __REACTOS__
+#define LLKHF_EXTENDED       (KF_EXTENDED >> 8)
+#define LLKHF_INJECTED       0x00000010
+//#define LLKHF_ALTDOWN        (KF_ALTDOWN >> 8)
+#define LLKHF_UP             (KF_UP >> 8)
+#endif
+
+static IDirectInputDevice8AVtbl SysKeyboardAvt;
+static IDirectInputDevice8WVtbl SysKeyboardWvt;
+
+typedef struct SysKeyboardImpl SysKeyboardImpl;
+struct SysKeyboardImpl
+{
+        LPVOID                          lpVtbl;
+        DWORD                           ref;
+        GUID                            guid;
+
+	IDirectInputImpl*               dinput;
+
+	HANDLE	hEvent;
+        /* SysKeyboardAImpl */
+	int                             acquired;
+        int                             buffersize;  /* set in 'SetProperty'         */
+        LPDIDEVICEOBJECTDATA            buffer;      /* buffer for 'GetDeviceData'.
+                                                        Alloc at 'Acquire', Free at
+                                                        'Unacquire'                  */
+        int                             count;       /* number of objects in use in
+                                                        'buffer'                     */
+        int                             start;       /* 'buffer' rotates. This is the
+                                                        first in use (if count > 0)  */
+        BOOL                            overflow;    /* return DI_BUFFEROVERFLOW in
+                                                        'GetDeviceData'              */
+        CRITICAL_SECTION                crit;
+};
+
+SysKeyboardImpl *current; /* Today's acquired device
+FIXME: currently this can be only one.
+Maybe this should be a linked list or st.
+I don't know what the rules are for multiple acquired keyboards,
+but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason.
+*/
+
+static BYTE DInputKeyState[256]; /* array for 'GetDeviceState' */
+
+static CRITICAL_SECTION keyboard_crit;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+    0, 0, &keyboard_crit,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { 0, (DWORD)(__FILE__ ": keyboard_crit") }
+};
+static CRITICAL_SECTION keyboard_crit = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+static DWORD keyboard_users;
+
+#ifndef __REACTOS__
+static HHOOK keyboard_hook;
+#endif
+
+#ifdef __REACTOS__
+void reactos_input_keyboard();
+
+void reactos_input_keyboard()
+{
+  MSG msg;
+  BOOL fDone;
+  int disk_code = -1;
+  BOOL down;
+  BYTE oldDInputKeyState[256];
+  int t;
+  
+  memcpy(&oldDInputKeyState,&DInputKeyState,256);
+  GetKeyboardState(DInputKeyState);
+  
+  for( t=0;t<255;t++)
+  {
+	  if (oldDInputKeyState[t]!=DInputKeyState[t]) disk_code=t;	  
+  }
+  	
+
+  if (disk_code!=-1) {
+	  if (current->buffer != NULL)
+     {
+      int n;
+      n = (current->start + current->count) % current->buffersize;
+
+      current->buffer[n].dwOfs = (BYTE) disk_code;
+      current->buffer[n].dwData = DInputKeyState[disk_code];
+      current->buffer[n].dwTimeStamp = 10;
+      current->buffer[n].dwSequence = current->dinput->evsequence++;
+
+	  
+      if (current->count == current->buffersize)
+                {
+                  current->start = ++current->start % current->buffersize;
+                  current->overflow = TRUE;
+                }
+              else
+                current->count++;
+              
+            }
+  }
+
+
+}
+#endif
+#ifndef __REACTOS__
+LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
+{
+  TRACE("(%d,%d,%ld)\n", code, wparam, lparam);
+
+  if (code == HC_ACTION)
+    {
+      BYTE dik_code;
+      BOOL down;
+      DWORD timestamp;
+      
+      {
+        KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
+        dik_code = hook->scanCode;
+        if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
+        down = !(hook->flags & LLKHF_UP);
+        timestamp = hook->time;
+      }
+
+      DInputKeyState[dik_code] = (down ? 0x80 : 0);
+      TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]);
+      
+      if (current != NULL)
+        {
+          if (current->hEvent)
+            SetEvent(current->hEvent);
+
+          if (current->buffer != NULL)
+            {
+              int n;
+
+              EnterCriticalSection(&(current->crit));
+
+              n = (current->start + current->count) % current->buffersize;
+
+              current->buffer[n].dwOfs = dik_code;
+              current->buffer[n].dwData = down ? 0x80 : 0;
+              current->buffer[n].dwTimeStamp = timestamp;
+              current->buffer[n].dwSequence = current->dinput->evsequence++;
+
+	      TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n,
+		    current->buffer[n].dwOfs, current->buffer[n].dwData, current->buffer[n].dwTimeStamp, current->buffer[n].dwSequence);
+
+              if (current->count == current->buffersize)
+                {
+                  current->start = ++current->start % current->buffersize;
+                  current->overflow = TRUE;
+                }
+              else
+                current->count++;
+
+              LeaveCriticalSection(&(current->crit));
+            }
+        }
+    }
+
+  return CallNextHookEx(keyboard_hook, code, wparam, lparam);
+}
+#endif
+
+static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
+  0x0ab8648a,
+  0x7735,
+  0x11d2,
+  {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
+};
+
+static void fill_keyboard_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, int version) {
+    DWORD dwSize;
+    DIDEVICEINSTANCEA ddi;
+    
+    dwSize = lpddi->dwSize;
+
+    TRACE("%ld %p\n", dwSize, lpddi);
+    
+    memset(lpddi, 0, dwSize);
+    memset(&ddi, 0, sizeof(ddi));
+
+    ddi.dwSize = dwSize;
+    ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
+    ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
+    if (version >= 8)
+        ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8);
+    else
+        ddi.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
+    strcpy(ddi.tszInstanceName, "Keyboard");
+    strcpy(ddi.tszProductName, "Wine Keyboard");
+
+    memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
+}
+
+static void fill_keyboard_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, int version) {
+    DWORD dwSize;
+    DIDEVICEINSTANCEW ddi;
+    
+    dwSize = lpddi->dwSize;
+
+    TRACE("%ld %p\n", dwSize, lpddi);
+    
+    memset(lpddi, 0, dwSize);
+    memset(&ddi, 0, sizeof(ddi));
+ 
+    ddi.dwSize = dwSize;
+    ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
+    ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
+    if (version >= 8)
+        ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8);
+    else
+        ddi.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
+    MultiByteToWideChar(CP_ACP, 0, "Keyboard", -1, ddi.tszInstanceName, MAX_PATH);
+    MultiByteToWideChar(CP_ACP, 0, "Wine Keyboard", -1, ddi.tszProductName, MAX_PATH);
+
+    memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
+}
+ 
+static BOOL keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, int version, int id)
+{
+  if (id != 0)
+    return FALSE;
+
+  if ((dwDevType == 0) ||
+      ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 8)) ||
+      ((dwDevType == DI8DEVTYPE_KEYBOARD) && (version >= 8))) {
+    TRACE("Enumerating the Keyboard device\n");
+ 
+    fill_keyboard_dideviceinstanceA(lpddi, version);
+    
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, int version, int id)
+{
+  if (id != 0)
+    return FALSE;
+
+  if ((dwDevType == 0) ||
+      ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 8)) ||
+      ((dwDevType == DI8DEVTYPE_KEYBOARD) && (version >= 8))) {
+    TRACE("Enumerating the Keyboard device\n");
+
+    fill_keyboard_dideviceinstanceW(lpddi, version);
+    
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+static SysKeyboardImpl *alloc_device_keyboard(REFGUID rguid, LPVOID kvt, IDirectInputImpl *dinput)
+{
+    SysKeyboardImpl* newDevice;
+    newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl));
+    newDevice->lpVtbl = kvt;
+    newDevice->ref = 1;
+    memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
+    newDevice->dinput = dinput;
+
+#ifndef __REACTOS__
+    EnterCriticalSection(&keyboard_crit);
+
+    if (!keyboard_users++)
+        keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );
+
+    LeaveCriticalSection(&keyboard_crit);
+#endif
+    return newDevice;
+}
+
+
+static HRESULT keyboarddev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
+{
+  if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) ||          /* Generic Keyboard */
+      (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
+    if ((riid == NULL) ||
+	IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
+      *pdev = (IDirectInputDeviceA*) alloc_device_keyboard(rguid, &SysKeyboardAvt, dinput);
+      TRACE("Creating a Keyboard device (%p)\n", *pdev);
+      return DI_OK;
+    } else
+      return DIERR_NOINTERFACE;
+  }
+  return DIERR_DEVICENOTREG;
+}
+
+static HRESULT keyboarddev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
+{
+  if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) ||          /* Generic Keyboard */
+      (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
+    if ((riid == NULL) ||
+	IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
+	IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
+      *pdev = (IDirectInputDeviceW*) alloc_device_keyboard(rguid, &SysKeyboardWvt, dinput);
+      TRACE("Creating a Keyboard device (%p)\n", *pdev);
+      return DI_OK;
+    } else
+      return DIERR_NOINTERFACE;
+  }
+  return DIERR_DEVICENOTREG;
+}
+
+dinput_device keyboarddev = {
+  100,
+  "Wine keyboard driver",
+  keyboarddev_enum_deviceA,
+  keyboarddev_enum_deviceW,
+  keyboarddev_create_deviceA,
+  keyboarddev_create_deviceW
+};
+
+void scan_keyboard()
+{
+    dinput_register_device(&keyboarddev);
+}
+
+DECL_GLOBAL_CONSTRUCTOR(keyboarddev_register) { dinput_register_device(&keyboarddev); }
+
+static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
+{
+	SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+	ULONG ref;
+
+	ref = InterlockedDecrement(&(This->ref));
+	if (ref)
+		return ref;
+
+#ifndef __REACTOS__
+	EnterCriticalSection(&keyboard_crit);
+	if (!--keyboard_users) {
+	    UnhookWindowsHookEx( keyboard_hook );
+	    keyboard_hook = 0;
+	}
+	LeaveCriticalSection(&keyboard_crit);
+#endif
+
+	/* Free the data queue */
+	if (This->buffer != NULL)
+	  HeapFree(GetProcessHeap(),0,This->buffer);
+
+	DeleteCriticalSection(&(This->crit));
+
+	HeapFree(GetProcessHeap(),0,This);
+	return DI_OK;
+}
+
+static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
+	LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPCDIPROPHEADER ph
+)
+{
+	SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+
+	TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
+	TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
+            ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
+	if (!HIWORD(rguid)) {
+		switch ((DWORD)rguid) {
+		case (DWORD) DIPROP_BUFFERSIZE: {
+			LPCDIPROPDWORD	pd = (LPCDIPROPDWORD)ph;
+
+			TRACE("(buffersize=%ld)\n",pd->dwData);
+
+                        if (This->acquired)
+                           return DIERR_INVALIDPARAM;
+
+                        This->buffersize = pd->dwData;
+
+			break;
+		}
+		default:
+			WARN("Unknown type %ld\n",(DWORD)rguid);
+			break;
+		}
+	}
+	return DI_OK;
+}
+
+
+static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
+	LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
+)
+{
+    TRACE("(%p)->(%ld,%p)\n", iface, len, ptr);
+	
+#ifdef __REACTOS__
+	reactos_input_keyboard();
+#endif
+
+    /* Note: device does not need to be acquired */
+    if (len != 256)
+      return DIERR_INVALIDPARAM;
+
+    MsgWaitForMultipleObjectsEx(0, NULL, 0, 0, 0);
+
+    if (TRACE_ON(dinput)) {
+	int i;
+	for (i = 0; i < 256; i++) {
+	    if (DInputKeyState[i] != 0x00) {
+		TRACE(" - %02X: %02x\n", i, DInputKeyState[i]);
+	    }
+	}
+    }
+    
+    memcpy(ptr, DInputKeyState, 256);
+    return DI_OK;
+}
+
+static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
+	LPDIRECTINPUTDEVICE8A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
+	LPDWORD entries,DWORD flags
+)
+{
+	
+	SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+	int ret = DI_OK, i = 0;
+#ifdef __REACTOS__
+     reactos_input_keyboard();
+#endif
+
+	TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
+	      This,dodsize,dod,entries,entries?*entries:0,flags);
+
+	if (This->acquired == 0)
+	  return DIERR_NOTACQUIRED;
+
+        if (This->buffer == NULL)
+          return DIERR_NOTBUFFERED;
+
+        if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3))
+          return DIERR_INVALIDPARAM;
+
+        MsgWaitForMultipleObjectsEx(0, NULL, 0, 0, 0);
+
+        EnterCriticalSection(&(This->crit));
+
+        /* Copy item at a time for the case dodsize > sizeof(buffer[n]) */
+        while ((i < *entries || *entries == INFINITE) && i < This->count)
+          {
+            if (dod != NULL)
+              {
+                int n = (This->start + i) % This->buffersize;
+                LPDIDEVICEOBJECTDATA pd
+                   = (LPDIDEVICEOBJECTDATA)((BYTE *)dod + dodsize * i);
+                pd->dwOfs       = This->buffer[n].dwOfs;
+                pd->dwData      = This->buffer[n].dwData;
+                pd->dwTimeStamp = This->buffer[n].dwTimeStamp;
+                pd->dwSequence  = This->buffer[n].dwSequence;
+              }
+            i++;
+          }
+
+        *entries = i;
+
+        if (This->overflow)
+          ret = DI_BUFFEROVERFLOW;
+
+        if (!(flags & DIGDD_PEEK))
+          {
+            /* Empty buffer */
+            This->count -= i;
+            This->start = (This->start + i) % This->buffersize;
+            This->overflow = FALSE;
+          }
+
+        LeaveCriticalSection(&(This->crit));
+
+	TRACE("Returning %ld events queued\n", *entries);
+
+        return ret;
+}
+
+static HRESULT WINAPI SysKeyboardAImpl_EnumObjects(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
+	LPVOID lpvRef,
+	DWORD dwFlags)
+{
+    SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+    DIDEVICEOBJECTINSTANCEA ddoi;
+    int i;
+    
+    TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
+    if (TRACE_ON(dinput)) {
+        TRACE("  - flags = ");
+	_dump_EnumObjects_flags(dwFlags);
+	TRACE("\n");
+    }
+
+    /* Only the fields till dwFFMaxForce are relevant */
+    memset(&ddoi, 0, sizeof(ddoi));
+    ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
+
+    for (i = 0; i < 256; i++) {
+        /* Report 255 keys :-) */
+        ddoi.guidType = GUID_Key;
+	ddoi.dwOfs = i;
+	ddoi.dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_BUTTON;
+	GetKeyNameTextA(((i & 0x7f) << 16) | ((i & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName));
+	_dump_OBJECTINSTANCEA(&ddoi);
+	if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
+    }
+    
+    return DI_OK;
+}
+
+static HRESULT WINAPI SysKeyboardWImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
+						   LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
+						   LPVOID lpvRef,
+						   DWORD dwFlags)
+{
+  SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+
+  device_enumobjects_AtoWcb_data data;
+
+  data.lpCallBack = lpCallback;
+  data.lpvRef = lpvRef;
+
+  return SysKeyboardAImpl_EnumObjects((LPDIRECTINPUTDEVICE8A) This, (LPDIENUMDEVICEOBJECTSCALLBACKA) DIEnumDevicesCallbackAtoW, (LPVOID) &data, dwFlags);
+}
+
+static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface);
+
+static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
+{
+	SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+
+	TRACE("(this=%p)\n",This);
+
+        if (This->acquired)
+          return S_FALSE;
+
+        This->acquired = 1;
+
+        if (current != NULL)
+          {
+            FIXME("Not more than one keyboard can be acquired at the same time.\n");
+            SysKeyboardAImpl_Unacquire(iface);
+          }
+
+        current = This;
+
+        if (This->buffersize > 0)
+          {
+            This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                     This->buffersize * sizeof(*(This->buffer)));
+            This->start = 0;
+            This->count = 0;
+            This->overflow = FALSE;
+            InitializeCriticalSection(&(This->crit));
+          }
+        else
+          This->buffer = NULL;
+
+
+	return DI_OK;
+}
+
+static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
+{
+	SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+	TRACE("(this=%p)\n",This);
+
+        if (This->acquired == 0)
+          return DI_NOEFFECT;
+
+        if (current == This)
+          current = NULL;
+        else
+          ERR("this != current\n");
+
+        This->acquired = 0;
+
+        if (This->buffersize >= 0)
+          {
+            HeapFree(GetProcessHeap(), 0, This->buffer);
+            This->buffer = NULL;
+            DeleteCriticalSection(&(This->crit));
+          }
+
+	return DI_OK;
+}
+
+static HRESULT WINAPI SysKeyboardAImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface,
+							    HANDLE hnd) {
+  SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+
+  TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
+
+  This->hEvent = hnd;
+  return DI_OK;
+}
+
+/******************************************************************************
+  *     GetCapabilities : get the device capablitites
+  */
+static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIDEVCAPS lpDIDevCaps)
+{
+  SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+
+  TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
+
+  if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) {
+    lpDIDevCaps->dwFlags = DIDC_ATTACHED;
+    if (This->dinput->version >= 8)
+        lpDIDevCaps->dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8);
+    else
+        lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
+    lpDIDevCaps->dwAxes = 0;
+    lpDIDevCaps->dwButtons = 256;
+    lpDIDevCaps->dwPOVs = 0;
+    lpDIDevCaps->dwFFSamplePeriod = 0;
+    lpDIDevCaps->dwFFMinTimeResolution = 0;
+    lpDIDevCaps->dwFirmwareRevision = 100;
+    lpDIDevCaps->dwHardwareRevision = 100;
+    lpDIDevCaps->dwFFDriverVersion = 0;
+  } else if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS_DX3)) {
+    lpDIDevCaps->dwFlags = DIDC_ATTACHED;
+    lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
+    lpDIDevCaps->dwAxes = 0;
+    lpDIDevCaps->dwButtons = 256;
+    lpDIDevCaps->dwPOVs = 0;
+  } else {
+    WARN("invalid parameter\n");
+    return DIERR_INVALIDPARAM;
+  }
+
+  return DI_OK;
+}
+
+/******************************************************************************
+  *     GetObjectInfo : get information about a device object such as a button
+  *                     or axis
+  */
+static HRESULT WINAPI
+SysKeyboardAImpl_GetObjectInfo(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIDEVICEOBJECTINSTANCEA pdidoi,
+	DWORD dwObj,
+	DWORD dwHow)
+{
+    SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+    DIDEVICEOBJECTINSTANCEA ddoi;
+    DWORD dwSize = pdidoi->dwSize;
+    
+    TRACE("(this=%p,%p,%ld,0x%08lx)\n", This, pdidoi, dwObj, dwHow);
+
+    if (dwHow == DIPH_BYID) {
+        WARN(" querying by id not supported yet...\n");
+	return DI_OK;
+    }
+
+    memset(pdidoi, 0, dwSize);
+    memset(&ddoi, 0, sizeof(ddoi));
+
+    ddoi.dwSize = dwSize;
+    ddoi.guidType = GUID_Key;
+    ddoi.dwOfs = dwObj;
+    ddoi.dwType = DIDFT_MAKEINSTANCE(dwObj) | DIDFT_BUTTON;
+    GetKeyNameTextA(((dwObj & 0x7f) << 16) | ((dwObj & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName));
+
+    /* And return our just filled device object instance structure */
+    memcpy(pdidoi, &ddoi, (dwSize < sizeof(ddoi) ? dwSize : sizeof(ddoi)));
+    
+    _dump_OBJECTINSTANCEA(pdidoi);
+
+    return DI_OK;
+}
+
+static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
+						     LPDIDEVICEOBJECTINSTANCEW pdidoi,
+						     DWORD dwObj,
+						     DWORD dwHow)
+{
+    SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+    DIDEVICEOBJECTINSTANCEW ddoi;
+    DWORD dwSize = pdidoi->dwSize;
+    
+    TRACE("(this=%p,%p,%ld,0x%08lx)\n", This, pdidoi, dwObj, dwHow);
+
+    if (dwHow == DIPH_BYID) {
+        WARN(" querying by id not supported yet...\n");
+	return DI_OK;
+    }
+
+    memset(pdidoi, 0, dwSize);
+    memset(&ddoi, 0, sizeof(ddoi));
+
+    ddoi.dwSize = dwSize;
+    ddoi.guidType = GUID_Key;
+    ddoi.dwOfs = dwObj;
+    ddoi.dwType = DIDFT_MAKEINSTANCE(dwObj) | DIDFT_BUTTON;
+    GetKeyNameTextW(((dwObj & 0x7f) << 16) | ((dwObj & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName));
+
+    /* And return our just filled device object instance structure */
+    memcpy(pdidoi, &ddoi, (dwSize < sizeof(ddoi) ? dwSize : sizeof(ddoi)));
+    
+    _dump_OBJECTINSTANCEW(pdidoi);
+
+    return DI_OK;
+}
+
+/******************************************************************************
+  *     GetDeviceInfo : get information about a device's identity
+  */
+static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo(
+	LPDIRECTINPUTDEVICE8A iface,
+	LPDIDEVICEINSTANCEA pdidi)
+{
+    SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+    TRACE("(this=%p,%p)\n", This, pdidi);
+
+    if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
+        WARN(" dinput3 not supporte yet...\n");
+	return DI_OK;
+    }
+
+    fill_keyboard_dideviceinstanceA(pdidi, This->dinput->version);
+    
+    return DI_OK;
+}
+
+static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi) 
+{
+    SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+    TRACE("(this=%p,%p)\n", This, pdidi);
+
+    if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
+        WARN(" dinput3 not supporte yet...\n");
+	return DI_OK;
+    }
+
+    fill_keyboard_dideviceinstanceW(pdidi, This->dinput->version);
+    
+    return DI_OK;
+}
+
+static IDirectInputDevice8AVtbl SysKeyboardAvt =
+{
+	IDirectInputDevice2AImpl_QueryInterface,
+	IDirectInputDevice2AImpl_AddRef,
+	SysKeyboardAImpl_Release,
+	SysKeyboardAImpl_GetCapabilities,
+	SysKeyboardAImpl_EnumObjects,
+	IDirectInputDevice2AImpl_GetProperty,
+	SysKeyboardAImpl_SetProperty,
+	SysKeyboardAImpl_Acquire,
+	SysKeyboardAImpl_Unacquire,
+	SysKeyboardAImpl_GetDeviceState,
+	SysKeyboardAImpl_GetDeviceData,
+	IDirectInputDevice2AImpl_SetDataFormat,
+	SysKeyboardAImpl_SetEventNotification,
+	IDirectInputDevice2AImpl_SetCooperativeLevel,
+	SysKeyboardAImpl_GetObjectInfo,
+	SysKeyboardAImpl_GetDeviceInfo,
+	IDirectInputDevice2AImpl_RunControlPanel,
+	IDirectInputDevice2AImpl_Initialize,
+	IDirectInputDevice2AImpl_CreateEffect,
+	IDirectInputDevice2AImpl_EnumEffects,
+	IDirectInputDevice2AImpl_GetEffectInfo,
+	IDirectInputDevice2AImpl_GetForceFeedbackState,
+	IDirectInputDevice2AImpl_SendForceFeedbackCommand,
+	IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
+	IDirectInputDevice2AImpl_Escape,
+	IDirectInputDevice2AImpl_Poll,
+        IDirectInputDevice2AImpl_SendDeviceData,
+        IDirectInputDevice7AImpl_EnumEffectsInFile,
+        IDirectInputDevice7AImpl_WriteEffectToFile,
+        IDirectInputDevice8AImpl_BuildActionMap,
+        IDirectInputDevice8AImpl_SetActionMap,
+        IDirectInputDevice8AImpl_GetImageInfo
+};
+
+#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
+# define XCAST(fun)	(typeof(SysKeyboardWvt.fun))
+#else
+# define XCAST(fun)	(void*)
+#endif
+
+static IDirectInputDevice8WVtbl SysKeyboardWvt =
+{
+	IDirectInputDevice2WImpl_QueryInterface,
+	XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
+	XCAST(Release)SysKeyboardAImpl_Release,
+	XCAST(GetCapabilities)SysKeyboardAImpl_GetCapabilities,
+	SysKeyboardWImpl_EnumObjects,
+	XCAST(GetProperty)IDirectInputDevice2AImpl_GetProperty,
+	XCAST(SetProperty)SysKeyboardAImpl_SetProperty,
+	XCAST(Acquire)SysKeyboardAImpl_Acquire,
+	XCAST(Unacquire)SysKeyboardAImpl_Unacquire,
+	XCAST(GetDeviceState)SysKeyboardAImpl_GetDeviceState,
+	XCAST(GetDeviceData)SysKeyboardAImpl_GetDeviceData,
+	XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat,
+	XCAST(SetEventNotification)SysKeyboardAImpl_SetEventNotification,
+	XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel,
+	SysKeyboardWImpl_GetObjectInfo,
+	SysKeyboardWImpl_GetDeviceInfo,
+	XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
+	XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
+	XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
+	IDirectInputDevice2WImpl_EnumEffects,
+	IDirectInputDevice2WImpl_GetEffectInfo,
+	XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
+	XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
+	XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
+	XCAST(Escape)IDirectInputDevice2AImpl_Escape,
+	XCAST(Poll)IDirectInputDevice2AImpl_Poll,
+        XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
+        IDirectInputDevice7WImpl_EnumEffectsInFile,
+        IDirectInputDevice7WImpl_WriteEffectToFile,
+        IDirectInputDevice8WImpl_BuildActionMap,
+        IDirectInputDevice8WImpl_SetActionMap,
+        IDirectInputDevice8WImpl_GetImageInfo
+};
+#undef XCAST
 
reactos/lib/dinput
diff -N mouse.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mouse.c	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,1253 @@
+/*		DirectInput Mouse device
+ *
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1998,1999 Lionel Ulmer
+ * Copyright 2000-2001 TransGaming Technologies Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "dinput.h"
+
+#include "dinput_private.h"
+#include "device_private.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+#define MOUSE_HACK
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+typedef struct {
+                     POINT pt;
+                     DWORD mouseData;
+                     DWORD flags;
+                     DWORD time;
+                     ULONG_PTR dwExtraInfo;
+} MSLLHOOKSTRUCT, *PMSLLHOOKSTRUCT;
+
+/* Wine mouse driver object instances */
+#define WINE_MOUSE_X_AXIS_INSTANCE   0
+#define WINE_MOUSE_Y_AXIS_INSTANCE   1
+#define WINE_MOUSE_Z_AXIS_INSTANCE   2
+#define WINE_MOUSE_L_BUTTON_INSTANCE 0
+#define WINE_MOUSE_R_BUTTON_INSTANCE 1
+#define WINE_MOUSE_M_BUTTON_INSTANCE 2
+#define WINE_MOUSE_D_BUTTON_INSTANCE 3
+
+/* ------------------------------- */
+/* Wine mouse internal data format */
+/* ------------------------------- */
+
+/* Constants used to access the offset array */
+#define WINE_MOUSE_X_POSITION 0
+#define WINE_MOUSE_Y_POSITION 1
+#define WINE_MOUSE_Z_POSITION 2
+#define WINE_MOUSE_L_POSITION 3
+#define WINE_MOUSE_R_POSITION 4
+#define WINE_MOUSE_M_POSITION 5
+
+typedef struct {
+    LONG lX;
+    LONG lY;
+    LONG lZ;
+    BYTE rgbButtons[4];
+} Wine_InternalMouseData;
+
+#define WINE_INTERNALMOUSE_NUM_OBJS 6
+
+static const DIOBJECTDATAFORMAT Wine_InternalMouseObjectFormat[WINE_INTERNALMOUSE_NUM_OBJS] = {
+    { &GUID_XAxis,   FIELD_OFFSET(Wine_InternalMouseData, lX),
+	  DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
+    { &GUID_YAxis,   FIELD_OFFSET(Wine_InternalMouseData, lY),
+	  DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
+    { &GUID_ZAxis,   FIELD_OFFSET(Wine_InternalMouseData, lZ),
+	  DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
+    { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 0,
+	  DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 },
+    { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 1,
+	  DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 },
+    { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 2,
+	  DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 }
+};
+
+static const DIDATAFORMAT Wine_InternalMouseFormat = {
+    0, /* dwSize - unused */
+    0, /* dwObjsize - unused */
+    0, /* dwFlags - unused */
+    sizeof(Wine_InternalMouseData),
+    WINE_INTERNALMOUSE_NUM_OBJS, /* dwNumObjs */
+    (LPDIOBJECTDATAFORMAT) Wine_InternalMouseObjectFormat
+};
+
+static IDirectInputDevice8AVtbl SysMouseAvt;
+static IDirectInputDevice8WVtbl SysMouseWvt;
+
+typedef struct SysMouseImpl SysMouseImpl;
+
+typedef enum {
+    WARP_DONE,   /* Warping has been done */
+    WARP_NEEDED, /* Warping is needed */
+    WARP_STARTED /* Warping has been done, waiting for the warp event */
+} WARP_STATUS;
+
+struct SysMouseImpl
+{
+    LPVOID                          lpVtbl;
+    DWORD                           ref;
+    GUID                            guid;
+    
+    IDirectInputImpl               *dinput;
+    
+    /* The current data format and the conversion between internal
+       and external data formats */
+    DIDATAFORMAT	           *df;
+    DataFormat                     *wine_df;
+    int                             offset_array[WINE_INTERNALMOUSE_NUM_OBJS];
+    
+    /* SysMouseAImpl */
+    BYTE                            absolute;
+    /* Previous position for relative moves */
+    LONG			    prevX, prevY;
+    /* These are used in case of relative -> absolute transitions */
+    POINT                           org_coords;
+    HHOOK                           hook;
+    HWND			    win;
+    DWORD			    dwCoopLevel;
+    POINT      			    mapped_center;
+    DWORD			    win_centerX, win_centerY;
+    LPDIDEVICEOBJECTDATA 	    data_queue;
+    int				    queue_head, queue_tail, queue_len;
+    BOOL			    overflow;
+    /* warping: whether we need to move mouse back to middle once we
+     * reach window borders (for e.g. shooters, "surface movement" games) */
+    WARP_STATUS		            need_warp;
+    int				    acquired;
+    HANDLE			    hEvent;
+    CRITICAL_SECTION		    crit;
+    
+    /* This is for mouse reporting. */
+    Wine_InternalMouseData          m_state;
+};
+
+/* FIXME: This is ugly and not thread safe :/ */
+static IDirectInputDevice8A* current_lock = NULL;
+
+/* FIXME: This is ugly but needed on Windows */
+static int mouse_set = 0;
+
+static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
+    0x9e573ed8,
+    0x7734,
+    0x11d2,
+    {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
+};
+
+static void fill_mouse_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, int version) {
+    DWORD dwSize;
+    DIDEVICEINSTANCEA ddi;
+    
+    dwSize = lpddi->dwSize;
+
+    TRACE("%ld %p\n", dwSize, lpddi);
+    
+    memset(lpddi, 0, dwSize);
+    memset(&ddi, 0, sizeof(ddi));
+
+    ddi.dwSize = dwSize;
+    ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */
+    ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
+    if (version >= 8)
+        ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
+    else
+        ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
+    strcpy(ddi.tszInstanceName, "Mouse");
+    strcpy(ddi.tszProductName, "Wine Mouse");
+
+    memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
+}
+
+static void fill_mouse_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, int version) {
+    DWORD dwSize;
+    DIDEVICEINSTANCEW ddi;
+    
+    dwSize = lpddi->dwSize;
+
+    TRACE("%ld %p\n", dwSize, lpddi);
+    
+    memset(lpddi, 0, dwSize);
+    memset(&ddi, 0, sizeof(ddi));
+
+    ddi.dwSize = dwSize;
+    ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */
+    ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
+    if (version >= 8)
+        ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
+    else
+        ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
+    MultiByteToWideChar(CP_ACP, 0, "Mouse", -1, ddi.tszInstanceName, MAX_PATH);
+    MultiByteToWideChar(CP_ACP, 0, "Wine Mouse", -1, ddi.tszProductName, MAX_PATH);
+
+    memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
+}
+
+static BOOL mousedev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, int version, int id)
+{
+    if (id != 0)
+        return FALSE;
+
+    if ((dwDevType == 0) ||
+	((dwDevType == DIDEVTYPE_MOUSE) && (version < 8)) ||
+	((dwDevType == DI8DEVTYPE_MOUSE) && (version >= 8))) {
+	TRACE("Enumerating the mouse device\n");
+	
+	fill_mouse_dideviceinstanceA(lpddi, version);
+	
+	return TRUE;
+    }
+    
+    return FALSE;
+}
+
+static BOOL mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, int version, int id)
+{
+    if (id != 0)
+        return FALSE;
+
+    if ((dwDevType == 0) ||
+	((dwDevType == DIDEVTYPE_MOUSE) && (version < 8)) ||
+	((dwDevType == DI8DEVTYPE_MOUSE) && (version >= 8))) {
+	TRACE("Enumerating the mouse device\n");
+	
+	fill_mouse_dideviceinstanceW(lpddi, version);
+	
+	return TRUE;
+    }
+    
+    return FALSE;
+}
+
+static SysMouseImpl *alloc_device_mouse(REFGUID rguid, LPVOID mvt, IDirectInputImpl *dinput)
+{
+    int offset_array[WINE_INTERNALMOUSE_NUM_OBJS] = {
+	FIELD_OFFSET(Wine_InternalMouseData, lX),
+	FIELD_OFFSET(Wine_InternalMouseData, lY),
+	FIELD_OFFSET(Wine_InternalMouseData, lZ),
+	FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 0,
+	FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 1,
+	FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 2
+    };
+    SysMouseImpl* newDevice;
+    newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseImpl));
+    newDevice->ref = 1;
+    newDevice->lpVtbl = mvt;
+#ifndef __REACTOS__
+    InitializeCriticalSection(&(newDevice->crit));
+#endif
+    memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
+
+    /* Per default, Wine uses its internal data format */
+    newDevice->df = (DIDATAFORMAT *) &Wine_InternalMouseFormat;
+    memcpy(newDevice->offset_array, offset_array, WINE_INTERNALMOUSE_NUM_OBJS * sizeof(int));
+    newDevice->wine_df = (DataFormat *) HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat));
+    newDevice->wine_df->size = 0;
+    newDevice->wine_df->internal_format_size = Wine_InternalMouseFormat.dwDataSize;
+    newDevice->wine_df->dt = NULL;
+    newDevice->dinput = dinput;
+
+    return newDevice;
+}
+
+static HRESULT mousedev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
+{
+    if ((IsEqualGUID(&GUID_SysMouse,rguid)) ||             /* Generic Mouse */
+	(IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
+	if ((riid == NULL) ||
+	    IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
+	    IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
+	    IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
+	    IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
+	    *pdev = (IDirectInputDeviceA*) alloc_device_mouse(rguid, &SysMouseAvt, dinput);
+	    TRACE("Creating a Mouse device (%p)\n", *pdev);
+	    return DI_OK;
+	} else
+	    return DIERR_NOINTERFACE;
+    }
+    
+    return DIERR_DEVICENOTREG;
+}
+
+static HRESULT mousedev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
+{
+    if ((IsEqualGUID(&GUID_SysMouse,rguid)) ||             /* Generic Mouse */
+	(IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
+	if ((riid == NULL) ||
+	    IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
+	    IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
+	    IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
+	    IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
+	    *pdev = (IDirectInputDeviceW*) alloc_device_mouse(rguid, &SysMouseWvt, dinput);
+	    TRACE("Creating a Mouse device (%p)\n", *pdev);
+	    return DI_OK;
+	} else
+	    return DIERR_NOINTERFACE;
+    }
+    
+    return DIERR_DEVICENOTREG;
+}
+
+static dinput_device mousedev = {
+    100,
+    "Wine mouse driver",
+    mousedev_enum_deviceA,
+    mousedev_enum_deviceW,
+    mousedev_create_deviceA,
+    mousedev_create_deviceW
+};
+
+void scan_mouse()
+{
+    dinput_register_device(&mousedev);
+}
+
+DECL_GLOBAL_CONSTRUCTOR(mousedev_register) { dinput_register_device(&mousedev); }
+
+/******************************************************************************
+ *	SysMouseA (DInput Mouse support)
+ */
+
+/******************************************************************************
+  *     Release : release the mouse buffer.
+  */
+static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
+{
+    SysMouseImpl *This = (SysMouseImpl *)iface;
+    ULONG ref;
+ 
+    ref = InterlockedDecrement(&(This->ref));
+    if (ref)
+	return ref;
+    
+    /* Free the data queue */
+    if (This->data_queue != NULL)
+	HeapFree(GetProcessHeap(),0,This->data_queue);
+
+#ifndef __REACTOS__
+    if (This->hook) {
+	UnhookWindowsHookEx( This->hook );
+	if (This->dwCoopLevel & DISCL_EXCLUSIVE)
+            ShowCursor(TRUE); /* show cursor */
+    }
+    DeleteCriticalSection(&(This->crit));
+#endif
+
+#ifdef __REACTOS__
+if (This->dwCoopLevel & DISCL_EXCLUSIVE)
+            ShowCursor(TRUE); /* show cursor */
+    
+#endif
+    /* Free the DataFormat */
+    if (This->df != &(Wine_InternalMouseFormat)) {
+	HeapFree(GetProcessHeap(), 0, This->df->rgodf);
+	HeapFree(GetProcessHeap(), 0, This->df);
+    }
+    
+    HeapFree(GetProcessHeap(),0,This);
+    return 0;
+}
+
+
+/******************************************************************************
+  *     SetCooperativeLevel : store the window in which we will do our
+  *   grabbing.
+  */
+static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
+	LPDIRECTINPUTDEVICE8A iface,HWND hwnd,DWORD dwflags
+)
+{
+    SysMouseImpl *This = (SysMouseImpl *)iface;
+    
+    TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
+    
+    if (TRACE_ON(dinput)) {
+	TRACE(" cooperative level : ");
+	_dump_cooperativelevel_DI(dwflags);
+    }
+    
+    /* Store the window which asks for the mouse */
+    if (!hwnd)
+	hwnd = GetDesktopWindow();
+    This->win = hwnd;
+    This->dwCoopLevel = dwflags;
+    
+    return DI_OK;
+}
+
+
+/******************************************************************************
+  *     SetDataFormat : the application can choose the format of the data
+  *   the device driver sends back with GetDeviceState.
+  *
+  *   For the moment, only the "standard" configuration (c_dfDIMouse) is supported
+  *   in absolute and relative mode.
+  */
+static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
+	LPDIRECTINPUTDEVICE8A iface,LPCDIDATAFORMAT df
+)
+{
+    SysMouseImpl *This = (SysMouseImpl *)iface;
+    
+    TRACE("(this=%p,%p)\n",This,df);
+    
+    _dump_DIDATAFORMAT(df);
+    
+    /* Tests under windows show that a call to SetDataFormat always sets the mouse
+       in relative mode whatever the dwFlags value (DIDF_ABSAXIS/DIDF_RELAXIS).
+       To switch in absolute mode, SetProperty must be used. */
+    This->absolute = 0;
+    
+    /* Store the new data format */
+    This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
+    memcpy(This->df, df, df->dwSize);
+    This->df->rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
+    memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
+    
+    /* Prepare all the data-conversion filters */
+    This->wine_df = create_DataFormat(&(Wine_InternalMouseFormat), df, This->offset_array);
+    
+    return DI_OK;
+}
+
+/* low-level mouse hook */
+static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lparam )
+{
+    LRESULT ret;
+    MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
+    SysMouseImpl* This = (SysMouseImpl*) current_lock;
+    DWORD dwCoop;
+    static long last_event = 0;
+    int wdata;
+
+    if (code != HC_ACTION) return CallNextHookEx( This->hook, code, wparam, lparam );
+
+    EnterCriticalSection(&(This->crit));
+    dwCoop = This->dwCoopLevel;
+
+    /* Only allow mouse events every 10 ms.
+     * This is to allow the cursor to start acceleration before
+     * the warps happen. But if it involves a mouse button event we
+     * allow it since we don't want to loose the clicks.
+     */
+    if (((GetCurrentTime() - last_event) < 10)
+        && wparam == WM_MOUSEMOVE)
+	goto end;
+    else last_event = GetCurrentTime();
+    
+    /* Mouse moved -> send event if asked */
+    if (This->hEvent)
+        SetEvent(This->hEvent);
+    
+    if (wparam == WM_MOUSEMOVE) {
+	if (This->absolute) {
+	    if (hook->pt.x != This->prevX)
+		GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], hook->pt.x, hook->time, 0);
+	    if (hook->pt.y != This->prevY)
+		GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], hook->pt.y, hook->time, 0);
+	} else {
+	    /* Now, warp handling */
+	    if ((This->need_warp == WARP_STARTED) &&
+		(hook->pt.x == This->mapped_center.x) && (hook->pt.y == This->mapped_center.y)) {
+		/* Warp has been done... */
+		This->need_warp = WARP_DONE;
+		goto end;
+	    }
+	    
+	    /* Relative mouse input with absolute mouse event : the real fun starts here... */
+	    if ((This->need_warp == WARP_NEEDED) ||
+		(This->need_warp == WARP_STARTED)) {
+		if (hook->pt.x != This->prevX)
+		    GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], hook->pt.x - This->prevX,
+			      hook->time, (This->dinput->evsequence)++);
+		if (hook->pt.y != This->prevY)
+		    GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], hook->pt.y - This->prevY,
+			      hook->time, (This->dinput->evsequence)++);
+	    } else {
+		/* This is the first time the event handler has been called after a
+		   GetDeviceData or GetDeviceState. */
+		if (hook->pt.x != This->mapped_center.x) {
+		    GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], hook->pt.x - This->mapped_center.x,
+			      hook->time, (This->dinput->evsequence)++);
+		    This->need_warp = WARP_NEEDED;
+		}
+		
+		if (hook->pt.y != This->mapped_center.y) {
+		    GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], hook->pt.y - This->mapped_center.y,
+			      hook->time, (This->dinput->evsequence)++);
+		    This->need_warp = WARP_NEEDED;
+		}
+	    }
+	}
+	
+	This->prevX = hook->pt.x;
+	This->prevY = hook->pt.y;
+	
+	if (This->absolute) {
+	    This->m_state.lX = hook->pt.x;
+	    This->m_state.lY = hook->pt.y;
+	} else {
+	    This->m_state.lX = hook->pt.x - This->mapped_center.x;
+	    This->m_state.lY = hook->pt.y - This->mapped_center.y;
+	}
+    }
+    
+    TRACE(" msg %x pt %ld %ld (W=%d)\n",
+          wparam, hook->pt.x, hook->pt.y, (!This->absolute) && This->need_warp );
+    
+    switch(wparam) {
+        case WM_LBUTTONDOWN:
+	    GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0xFF,
+		      hook->time, This->dinput->evsequence++);
+	    This->m_state.rgbButtons[0] = 0xFF;
+	    break;
+	case WM_LBUTTONUP:
+	    GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0x00,
+		      hook->time, This->dinput->evsequence++);
+	    This->m_state.rgbButtons[0] = 0x00;
+	    break;
+	case WM_RBUTTONDOWN:
+	    GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0xFF,
+		      hook->time, This->dinput->evsequence++);
+	    This->m_state.rgbButtons[1] = 0xFF;
+	    break;
+	case WM_RBUTTONUP:
+	    GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0x00,
+		      hook->time, This->dinput->evsequence++);
+	    This->m_state.rgbButtons[1] = 0x00;
+	    break;
+	case WM_MBUTTONDOWN:
+	    GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0xFF,
+		      hook->time, This->dinput->evsequence++);
+	    This->m_state.rgbButtons[2] = 0xFF;
+	    break;
+	case WM_MBUTTONUP:
+	    GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0x00,
+		      hook->time, This->dinput->evsequence++);
+	    This->m_state.rgbButtons[2] = 0x00;
+	    break;
+	case WM_MOUSEWHEEL:
+	    wdata = (short)HIWORD(hook->mouseData);
+	    GEN_EVENT(This->offset_array[WINE_MOUSE_Z_POSITION], wdata,
+		      hook->time, This->dinput->evsequence++);
+	    This->m_state.lZ += wdata;
+	    break;
+    }
+    
+    TRACE("(X: %ld - Y: %ld   L: %02x M: %02x R: %02x)\n",
+	  This->m_state.lX, This->m_state.lY,
+	  This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
+    
+  end:
+    LeaveCriticalSection(&(This->crit));
+    
+    if (dwCoop & DISCL_NONEXCLUSIVE) {
+	/* Pass the events down to previous handlers (e.g. win32 input) */
+	ret = CallNextHookEx( This->hook, code, wparam, lparam );
+    } else {
+	/* Ignore message */
+	ret = 1;
+    }
+    return ret;
+}
+
+
+static void dinput_window_check(SysMouseImpl* This) {
+    RECT rect;
+    DWORD centerX, centerY;
+    
+    /* make sure the window hasn't moved */
+    GetWindowRect(This->win, &rect);
+    centerX = (rect.right  - rect.left) / 2;
+    centerY = (rect.bottom - rect.top ) / 2;
+    if (This->win_centerX != centerX || This->win_centerY != centerY) {
+	This->win_centerX = centerX;
+	This->win_centerY = centerY;
+    }
+    This->mapped_center.x = This->win_centerX;
+    This->mapped_center.y = This->win_centerY;
+    MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
+}
+
+
+/******************************************************************************
+  *     Acquire : gets exclusive control of the mouse
+  */
+static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
+{
+    SysMouseImpl *This = (SysMouseImpl *)iface;
+    RECT	rect;
+    
+    TRACE("(this=%p)\n",This);
+    
+    if (This->acquired == 0) {
+	POINT point;
+	
+	/* Store (in a global variable) the current lock */
+	current_lock = (IDirectInputDevice8A*)This;
+	
+	/* Init the mouse state */
+	GetCursorPos( &point );
+	if (This->absolute) {
+	    This->m_state.lX = point.x;
+	    This->m_state.lY = point.y;
+	    This->prevX = point.x;
+	    This->prevY = point.y;
+	} else {
+	    This->m_state.lX = 0;
+	    This->m_state.lY = 0;
+	    This->org_coords = point;
+	}
+	This->m_state.lZ = 0;
+	This->m_state.rgbButtons[0] = ((GetKeyState(VK_LBUTTON) & 0x80) ? 0xFF : 0x00);
+	This->m_state.rgbButtons[1] = ((GetKeyState(VK_RBUTTON) & 0x80) ? 0xFF : 0x00);
+	This->m_state.rgbButtons[2] = ((GetKeyState(VK_MBUTTON) & 0x80) ? 0xFF : 0x00);
+	
+	/* Install our mouse hook */
+	if (This->dwCoopLevel & DISCL_EXCLUSIVE)
+	    ShowCursor(FALSE); /* hide cursor */
+#ifndef __REACTOS__
+	This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 );
+#endif	
+	/* Get the window dimension and find the center */
+	GetWindowRect(This->win, &rect);
+	This->win_centerX = (rect.right  - rect.left) / 2;
+	This->win_centerY = (rect.bottom - rect.top ) / 2;
+	
+	/* Warp the mouse to the center of the window */
+	if (This->absolute == 0) {
+	    This->mapped_center.x = This->win_centerX;
+	    This->mapped_center.y = This->win_centerY;
+	    MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
+	    TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
+	    SetCursorPos( This->mapped_center.x, This->mapped_center.y );
+#ifdef MOUSE_HACK
+	    This->need_warp = WARP_DONE;
+#else
+	    This->need_warp = WARP_STARTED;
+#endif
+	}
+	
+	This->acquired = 1;
+	return DI_OK;
+    }
+    return S_FALSE;
+}
+
+/******************************************************************************
+  *     Unacquire : frees the mouse
+  */
+static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
+{
+    SysMouseImpl *This = (SysMouseImpl *)iface;
+    
+    TRACE("(this=%p)\n",This);
+    
+    if (This->acquired) {
+	/* Reinstall previous mouse event handler */
+
+#ifndef __REACTOS__
+	if (This->hook) {
+	    UnhookWindowsHookEx( This->hook );
+	    This->hook = 0;
+
+	    if (This->dwCoopLevel & DISCL_EXCLUSIVE)
+		ShowCursor(TRUE); /* show cursor */
+        }
+#endif
+#ifdef __REACTOS__
+	if (This->dwCoopLevel & DISCL_EXCLUSIVE)
+		ShowCursor(TRUE); /* show cursor */
+#endif
+
+        /* No more locks */
+        current_lock = NULL;
+	
+        /* Unacquire device */
+        This->acquired = 0;
+
+	/* And put the mouse cursor back where it was at acquire time */
+	if (This->absolute == 0) {
+	    TRACE(" warping mouse back to (%ld , %ld)\n", This->org_coords.x, This->org_coords.y);
+	    SetCursorPos(This->org_coords.x, This->org_coords.y);
+	}
+    } else {
+	return DI_NOEFFECT;
+    }
+	
+    return DI_OK;
+}
+
+// if you call poll then to getdevicestate
+// it did not send back right value in windows 
+int poll_mouse=0;
+static HRESULT WINAPI SysMouseAImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
+{
+ int retValue = DI_OK;
+ 
+SysMouseImpl *This = (SysMouseImpl *)iface;           
+ if (poll_mouse==0) {
+	                 retValue=SysMouseAImpl_Acquire(iface);	
+                     poll_mouse=1; 
+					 if (retValue!=DI_OK) retValue=DIERR_NOTACQUIRED;
+                     else retValue = DI_OK;
+                     }
+
+ return retValue;
+}
+	
+
+/******************************************************************************
+  *     GetDeviceState : returns the "state" of the mouse.
+  *
+  *   For the moment, only the "standard" return structure (DIMOUSESTATE) is
+  *   supported.
+  */
+static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
+	LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
+) {
+    SysMouseImpl *This = (SysMouseImpl *)iface;        
+    POINT point;    	 
+
+#ifndef __REACTOS__
+    EnterCriticalSection(&(This->crit));
+#endif
+    TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
+    	
+    /* Copy the current mouse state */	   
+    fill_DataFormat(ptr, &(This->m_state), This->wine_df);
+
+
+	// this fix windows bugs when 
+	// some program calling on mouse poll
+	if (poll_mouse==1) poll_mouse=0;		 
+	else {
+	      if (This->absolute == 0) {
+	                       This->m_state.lX = 0;
+	                       This->m_state.lY = 0;
+	                       This->m_state.lZ = 0;
+	                       } 
+	     }
+	
+	
+    /* Check if we need to do a mouse warping */
+    if (This->need_warp == WARP_NEEDED) {
+	dinput_window_check(This);
+	TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);	
+        if (mouse_set==0){
+           SetCursorPos( This->mapped_center.x, This->mapped_center.y );
+           mouse_set++;
+           }
+	
+#ifdef MOUSE_HACK
+	This->need_warp = WARP_DONE;
+#else
+	This->need_warp = WARP_STARTED;
+#endif
+    }
+
+#ifndef __REACTOS__
+    LeaveCriticalSection(&(This->crit));
+#endif
+
+    TRACE("(X: %ld - Y: %ld - Z: %ld  L: %02x M: %02x R: %02x)\n",
+	  This->m_state.lX, This->m_state.lY, This->m_state.lZ,
+	  This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
+    
+    return DI_OK;
+}
+
+/******************************************************************************
+  *     GetDeviceState : gets buffered input data.
+  */
+
+static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface,
+						  DWORD dodsize,
+						  LPDIDEVICEOBJECTDATA dod,
+						  LPDWORD entries,
+						  DWORD flags
+) {
+    SysMouseImpl *This = (SysMouseImpl *)iface;
+    DWORD len;
+    int nqtail;
+	
+    
+    TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
+    
+
+	// windows does not get any data if 
+	// we do not call manual to mouse Acquire
+	// this is only need if some apps calling on getdevice data direcly
+	// in windows GetdeviceData does always update first the data
+	// then return it.
+	SysMouseAImpl_Acquire(iface);
+
+
+    if (This->acquired == 0) {
+	WARN(" application tries to get data from an unacquired device !\n");
+	return DIERR_NOTACQUIRED;
+    }
+    
+	
+#ifndef __REACTOS__
+    EnterCriticalSection(&(This->crit));
+#endif
+
+	// FIXME mouse are bit choppy here. 
+
+    len = ((This->queue_head < This->queue_tail) ? This->queue_len : 0)
+	+ (This->queue_head - This->queue_tail);
+    if (len > *entries) len = *entries;
+    
+    if (dod == NULL) {
+	if (len)
+	    TRACE("Application discarding %ld event(s).\n", len);
+	
+	*entries = len;
+	nqtail = This->queue_tail + len;
+	while (nqtail >= This->queue_len) nqtail -= This->queue_len;
+    } else {
+	if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) {
+	    ERR("Wrong structure size !\n");
+#ifndef __REACTOS__
+	    LeaveCriticalSection(&(This->crit));
+#endif
+	    return DIERR_INVALIDPARAM;
+	}
+	
+	if (len)
+	    TRACE("Application retrieving %ld event(s).\n", len);
+	
+	*entries = 0;
+	nqtail = This->queue_tail;
+	while (len) {
+	    DWORD span = ((This->queue_head < nqtail) ? This->queue_len : This->queue_head) - nqtail;
+	    if (span > len)
+		span = len;
+	    
+	    /* Copy the buffered data into the application queue */
+	    memcpy(dod + *entries, This->data_queue + nqtail, span * dodsize);
+
+	    /* Advance position */
+	    nqtail += span;
+	    if (nqtail >= This->queue_len) nqtail -= This->queue_len;
+	    *entries += span;
+	    len -= span;
+	}
+    }
+    if (!(flags & DIGDD_PEEK))
+	This->queue_tail = nqtail;
+#ifndef __REACTOS__    
+    LeaveCriticalSection(&(This->crit));
+#endif    
+    /* Check if we need to do a mouse warping */
+   
+
+    if (This->need_warp == WARP_NEEDED) {
+	dinput_window_check(This);
+	TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
+        if (mouse_set==0){
+           SetCursorPos( This->mapped_center.x, This->mapped_center.y );
+           mouse_set++;
+           }
+	
+#ifdef MOUSE_HACK
+	This->need_warp = WARP_DONE;
+#else
+	This->need_warp = WARP_STARTED;
+#endif
+    }
+    return DI_OK;
+}
+
+/******************************************************************************
+  *     SetProperty : change input device properties
+  */
+static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
+					    REFGUID rguid,
+					    LPCDIPROPHEADER ph)
+{
+    SysMouseImpl *This = (SysMouseImpl *)iface;
+    
+    TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
+    
+    if (!HIWORD(rguid)) {
+	switch ((DWORD)rguid) {
+	    case (DWORD) DIPROP_BUFFERSIZE: {
+		LPCDIPROPDWORD	pd = (LPCDIPROPDWORD)ph;
+		
+		TRACE("buffersize = %ld\n",pd->dwData);
+		
+		This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
+								   pd->dwData * sizeof(DIDEVICEOBJECTDATA));
+		This->queue_head = 0;
+		This->queue_tail = 0;
+		This->queue_len  = pd->dwData;
+		break;
+	    }
+	    case (DWORD) DIPROP_AXISMODE: {
+		LPCDIPROPDWORD    pd = (LPCDIPROPDWORD)ph;
+		This->absolute = !(pd->dwData);
+		TRACE("Using %s coordinates mode now\n", This->absolute ? "absolute" : "relative");
+		break;
+	    }
+	    default:
+	      FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+	      break;
+	}
+    }
+    
+    return DI_OK;
+}
+
+/******************************************************************************
+  *     GetProperty : get input device properties
+  */
+static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
+						REFGUID rguid,
+						LPDIPROPHEADER pdiph)
+{
+    SysMouseImpl *This = (SysMouseImpl *)iface;
+    
+    TRACE("(this=%p,%s,%p): stub!\n",
+	  iface, debugstr_guid(rguid), pdiph);
+    
+    if (TRACE_ON(dinput))
+	_dump_DIPROPHEADER(pdiph);
+    
+    if (!HIWORD(rguid)) {
+	switch ((DWORD)rguid) {
+	    case (DWORD) DIPROP_BUFFERSIZE: {
+		LPDIPROPDWORD	pd = (LPDIPROPDWORD)pdiph;
+		
+		TRACE(" return buffersize = %d\n",This->queue_len);
+		pd->dwData = This->queue_len;
+		break;
+	    }
+	      
+	    case (DWORD) DIPROP_GRANULARITY: {
+		LPDIPROPDWORD pr = (LPDIPROPDWORD) pdiph;
+		
+		/* We'll just assume that the app asks about the Z axis */
+		pr->dwData = WHEEL_DELTA;
+		
+		break;
+	    }
+	      
+	    case (DWORD) DIPROP_RANGE: {
+		LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph;
+		
+		if ((pdiph->dwHow == DIPH_BYID) &&
+		    ((pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS)) ||
+		     (pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS)))) {
+		    /* Querying the range of either the X or the Y axis.  As I do
+		       not know the range, do as if the range were
+		       unrestricted...*/
+		    pr->lMin = DIPROPRANGE_NOMIN;
+		    pr->lMax = DIPROPRANGE_NOMAX;
+		}
+		
+		break;
+	    }
+	      
+	    default:
+	      FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+	      break;
+	  }
+      }
+    
+    return DI_OK;
+}
+
+
+
+/******************************************************************************
+  *     SetEventNotification : specifies event to be sent on state change
+  */
[truncated at 1000 lines; 257 more skipped]
 
reactos/lib/dinput
diff -N regsvr.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ regsvr.c	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,558 @@
+/*
+ *	self-registerable dll functions for dinput.dll
+ *
+ * Copyright (C) 2003 John K. Hohm
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "winerror.h"
+
+#include "dinput.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+
+/*
+ * Near the bottom of this file are the exported DllRegisterServer and
+ * DllUnregisterServer, which make all this worthwhile.
+ */
+
+/***********************************************************************
+ *		interface for self-registering
+ */
+struct regsvr_interface
+{
+    IID const *iid;		/* NULL for end of list */
+    LPCSTR name;		/* can be NULL to omit */
+    IID const *base_iid;	/* can be NULL to omit */
+    int num_methods;		/* can be <0 to omit */
+    CLSID const *ps_clsid;	/* can be NULL to omit */
+    CLSID const *ps_clsid32;	/* can be NULL to omit */
+};
+
+static HRESULT register_interfaces(struct regsvr_interface const *list);
+static HRESULT unregister_interfaces(struct regsvr_interface const *list);
+
+struct regsvr_coclass
+{
+    CLSID const *clsid;		/* NULL for end of list */
+    LPCSTR name;		/* can be NULL to omit */
+    LPCSTR ips;			/* can be NULL to omit */
+    LPCSTR ips32;		/* can be NULL to omit */
+    LPCSTR ips32_tmodel;	/* can be NULL to omit */
+    LPCSTR progid;		/* can be NULL to omit */
+    LPCSTR viprogid;		/* can be NULL to omit */
+    LPCSTR progid_extra;	/* can be NULL to omit */
+};
+
+static HRESULT register_coclasses(struct regsvr_coclass const *list);
+static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
+
+/***********************************************************************
+ *		static string constants
+ */
+static WCHAR const interface_keyname[10] = {
+    'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
+static WCHAR const base_ifa_keyname[14] = {
+    'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
+    'e', 0 };
+static WCHAR const num_methods_keyname[11] = {
+    'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
+static WCHAR const ps_clsid_keyname[15] = {
+    'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
+    'i', 'd', 0 };
+static WCHAR const ps_clsid32_keyname[17] = {
+    'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
+    'i', 'd', '3', '2', 0 };
+static WCHAR const clsid_keyname[6] = {
+    'C', 'L', 'S', 'I', 'D', 0 };
+static WCHAR const curver_keyname[7] = {
+    'C', 'u', 'r', 'V', 'e', 'r', 0 };
+static WCHAR const ips_keyname[13] = {
+    'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
+    0 };
+static WCHAR const ips32_keyname[15] = {
+    'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
+    '3', '2', 0 };
+static WCHAR const progid_keyname[7] = {
+    'P', 'r', 'o', 'g', 'I', 'D', 0 };
+static WCHAR const viprogid_keyname[25] = {
+    'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
+    'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
+    0 };
+static char const tmodel_valuename[] = "ThreadingModel";
+
+/***********************************************************************
+ *		static helper functions
+ */
+static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
+static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
+				   WCHAR const *value);
+static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
+				   char const *value);
+static LONG register_progid(WCHAR const *clsid,
+			    char const *progid, char const *curver_progid,
+			    char const *name, char const *extra);
+static LONG recursive_delete_key(HKEY key);
+static LONG recursive_delete_keyA(HKEY base, char const *name);
+static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
+
+/***********************************************************************
+ *		register_interfaces
+ */
+static HRESULT register_interfaces(struct regsvr_interface const *list)
+{
+    LONG res = ERROR_SUCCESS;
+    HKEY interface_key;
+
+    res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
+			  KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
+    if (res != ERROR_SUCCESS) goto error_return;
+
+    for (; res == ERROR_SUCCESS && list->iid; ++list) {
+	WCHAR buf[39];
+	HKEY iid_key;
+
+	StringFromGUID2(list->iid, buf, 39);
+	res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
+			      KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
+	if (res != ERROR_SUCCESS) goto error_close_interface_key;
+
+	if (list->name) {
+	    res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
+				 (CONST BYTE*)(list->name),
+				 strlen(list->name) + 1);
+	    if (res != ERROR_SUCCESS) goto error_close_iid_key;
+	}
+
+	if (list->base_iid) {
+	    register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
+	    if (res != ERROR_SUCCESS) goto error_close_iid_key;
+	}
+
+	if (0 <= list->num_methods) {
+	    static WCHAR const fmt[3] = { '%', 'd', 0 };
+	    HKEY key;
+
+	    res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
+				  KEY_READ | KEY_WRITE, NULL, &key, NULL);
+	    if (res != ERROR_SUCCESS) goto error_close_iid_key;
+
+	    wsprintfW(buf, fmt, list->num_methods);
+	    res = RegSetValueExW(key, NULL, 0, REG_SZ,
+				 (CONST BYTE*)buf,
+				 (lstrlenW(buf) + 1) * sizeof(WCHAR));
+	    RegCloseKey(key);
+
+	    if (res != ERROR_SUCCESS) goto error_close_iid_key;
+	}
+
+	if (list->ps_clsid) {
+	    register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
+	    if (res != ERROR_SUCCESS) goto error_close_iid_key;
+	}
+
+	if (list->ps_clsid32) {
+	    register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
+	    if (res != ERROR_SUCCESS) goto error_close_iid_key;
+	}
+
+    error_close_iid_key:
+	RegCloseKey(iid_key);
+    }
+
+error_close_interface_key:
+    RegCloseKey(interface_key);
+error_return:
+    return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ *		unregister_interfaces
+ */
+static HRESULT unregister_interfaces(struct regsvr_interface const *list)
+{
+    LONG res = ERROR_SUCCESS;
+    HKEY interface_key;
+
+    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
+			KEY_READ | KEY_WRITE, &interface_key);
+    if (res == ERROR_FILE_NOT_FOUND) return S_OK;
+    if (res != ERROR_SUCCESS) goto error_return;
+
+    for (; res == ERROR_SUCCESS && list->iid; ++list) {
+	WCHAR buf[39];
+
+	StringFromGUID2(list->iid, buf, 39);
+	res = recursive_delete_keyW(interface_key, buf);
+    }
+
+    RegCloseKey(interface_key);
+error_return:
+    return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ *		register_coclasses
+ */
+static HRESULT register_coclasses(struct regsvr_coclass const *list)
+{
+    LONG res = ERROR_SUCCESS;
+    HKEY coclass_key;
+
+    res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
+			  KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
+    if (res != ERROR_SUCCESS) goto error_return;
+
+    for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+	WCHAR buf[39];
+	HKEY clsid_key;
+
+	StringFromGUID2(list->clsid, buf, 39);
+	res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+			      KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
+	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+	if (list->name) {
+	    res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
+				 (CONST BYTE*)(list->name),
+				 strlen(list->name) + 1);
+	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+	}
+
+	if (list->ips) {
+	    res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
+	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+	}
+
+	if (list->ips32) {
+	    HKEY ips32_key;
+
+	    res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
+				  KEY_READ | KEY_WRITE, NULL,
+				  &ips32_key, NULL);
+	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+	    res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
+				 (CONST BYTE*)list->ips32,
+				 lstrlenA(list->ips32) + 1);
+	    if (res == ERROR_SUCCESS && list->ips32_tmodel)
+		res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
+				     (CONST BYTE*)list->ips32_tmodel,
+				     strlen(list->ips32_tmodel) + 1);
+	    RegCloseKey(ips32_key);
+	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+	}
+
+	if (list->progid) {
+	    res = register_key_defvalueA(clsid_key, progid_keyname,
+					 list->progid);
+	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+	    res = register_progid(buf, list->progid, NULL,
+				  list->name, list->progid_extra);
+	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+	}
+
+	if (list->viprogid) {
+	    res = register_key_defvalueA(clsid_key, viprogid_keyname,
+					 list->viprogid);
+	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+	    res = register_progid(buf, list->viprogid, list->progid,
+				  list->name, list->progid_extra);
+	    if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+	}
+
+    error_close_clsid_key:
+	RegCloseKey(clsid_key);
+    }
+
+error_close_coclass_key:
+    RegCloseKey(coclass_key);
+error_return:
+    return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ *		unregister_coclasses
+ */
+static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
+{
+    LONG res = ERROR_SUCCESS;
+    HKEY coclass_key;
+
+    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
+			KEY_READ | KEY_WRITE, &coclass_key);
+    if (res == ERROR_FILE_NOT_FOUND) return S_OK;
+    if (res != ERROR_SUCCESS) goto error_return;
+
+    for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+	WCHAR buf[39];
+
+	StringFromGUID2(list->clsid, buf, 39);
+	res = recursive_delete_keyW(coclass_key, buf);
+	if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+	if (list->progid) {
+	    res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
+	    if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+	}
+
+	if (list->viprogid) {
+	    res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
+	    if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+	}
+    }
+
+error_close_coclass_key:
+    RegCloseKey(coclass_key);
+error_return:
+    return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ *		regsvr_key_guid
+ */
+static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
+{
+    WCHAR buf[39];
+
+    StringFromGUID2(guid, buf, 39);
+    return register_key_defvalueW(base, name, buf);
+}
+
+/***********************************************************************
+ *		regsvr_key_defvalueW
+ */
+static LONG register_key_defvalueW(
+    HKEY base,
+    WCHAR const *name,
+    WCHAR const *value)
+{
+    LONG res;
+    HKEY key;
+
+    res = RegCreateKeyExW(base, name, 0, NULL, 0,
+			  KEY_READ | KEY_WRITE, NULL, &key, NULL);
+    if (res != ERROR_SUCCESS) return res;
+    res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
+			 (lstrlenW(value) + 1) * sizeof(WCHAR));
+    RegCloseKey(key);
+    return res;
+}
+
+/***********************************************************************
+ *		regsvr_key_defvalueA
+ */
+static LONG register_key_defvalueA(
+    HKEY base,
+    WCHAR const *name,
+    char const *value)
+{
+    LONG res;
+    HKEY key;
+
+    res = RegCreateKeyExW(base, name, 0, NULL, 0,
+			  KEY_READ | KEY_WRITE, NULL, &key, NULL);
+    if (res != ERROR_SUCCESS) return res;
+    res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
+			 lstrlenA(value) + 1);
+    RegCloseKey(key);
+    return res;
+}
+
+/***********************************************************************
+ *		regsvr_progid
+ */
+static LONG register_progid(
+    WCHAR const *clsid,
+    char const *progid,
+    char const *curver_progid,
+    char const *name,
+    char const *extra)
+{
+    LONG res;
+    HKEY progid_key;
+
+    res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
+			  NULL, 0, KEY_READ | KEY_WRITE, NULL,
+			  &progid_key, NULL);
+    if (res != ERROR_SUCCESS) return res;
+
+    if (name) {
+	res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
+			     (CONST BYTE*)name, strlen(name) + 1);
+	if (res != ERROR_SUCCESS) goto error_close_progid_key;
+    }
+
+    if (clsid) {
+	res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
+	if (res != ERROR_SUCCESS) goto error_close_progid_key;
+    }
+
+    if (curver_progid) {
+	res = register_key_defvalueA(progid_key, curver_keyname,
+				     curver_progid);
+	if (res != ERROR_SUCCESS) goto error_close_progid_key;
+    }
+
+    if (extra) {
+	HKEY extra_key;
+
+	res = RegCreateKeyExA(progid_key, extra, 0,
+			      NULL, 0, KEY_READ | KEY_WRITE, NULL,
+			      &extra_key, NULL);
+	if (res == ERROR_SUCCESS)
+	    RegCloseKey(extra_key);
+    }
+
+error_close_progid_key:
+    RegCloseKey(progid_key);
+    return res;
+}
+
+/***********************************************************************
+ *		recursive_delete_key
+ */
+static LONG recursive_delete_key(HKEY key)
+{
+    LONG res;
+    WCHAR subkey_name[MAX_PATH];
+    DWORD cName;
+    HKEY subkey;
+
+    for (;;) {
+	cName = sizeof(subkey_name) / sizeof(WCHAR);
+	res = RegEnumKeyExW(key, 0, subkey_name, &cName,
+			    NULL, NULL, NULL, NULL);
+	if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
+	    res = ERROR_SUCCESS; /* presumably we're done enumerating */
+	    break;
+	}
+	res = RegOpenKeyExW(key, subkey_name, 0,
+			    KEY_READ | KEY_WRITE, &subkey);
+	if (res == ERROR_FILE_NOT_FOUND) continue;
+	if (res != ERROR_SUCCESS) break;
+
+	res = recursive_delete_key(subkey);
+	RegCloseKey(subkey);
+	if (res != ERROR_SUCCESS) break;
+    }
+
+    if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
+    return res;
+}
+
+/***********************************************************************
+ *		recursive_delete_keyA
+ */
+static LONG recursive_delete_keyA(HKEY base, char const *name)
+{
+    LONG res;
+    HKEY key;
+
+    res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
+    if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
+    if (res != ERROR_SUCCESS) return res;
+    res = recursive_delete_key(key);
+    RegCloseKey(key);
+    return res;
+}
+
+/***********************************************************************
+ *		recursive_delete_keyW
+ */
+static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
+{
+    LONG res;
+    HKEY key;
+
+    res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
+    if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
+    if (res != ERROR_SUCCESS) return res;
+    res = recursive_delete_key(key);
+    RegCloseKey(key);
+    return res;
+}
+
+/***********************************************************************
+ *		coclass list
+ */
+static struct regsvr_coclass const coclass_list[] = {
+    {
+	&CLSID_DirectInput,
+	"DirectInput Object",
+	NULL,
+	"dinput.dll",
+	"Both"
+    },
+    {
+	&CLSID_DirectInputDevice,
+	"DirectInputDevice Object",
+	NULL,
+	"dinput.dll",
+	"Both"
+    },
+    { NULL }			/* list terminator */
+};
+
+/***********************************************************************
+ *		interface list
+ */
+
+static struct regsvr_interface const interface_list[] = {
+    { NULL }			/* list terminator */
+};
+
+/***********************************************************************
+ *		DllRegisterServer (DINPUT.@)
+ */
+HRESULT WINAPI DINPUT_DllRegisterServer(void)
+{
+    HRESULT hr;
+
+    TRACE("\n");
+
+    hr = register_coclasses(coclass_list);
+    if (SUCCEEDED(hr))
+	hr = register_interfaces(interface_list);
+    return hr;
+}
+
+/***********************************************************************
+ *		DllUnregisterServer (DINPUT.@)
+ */
+HRESULT WINAPI DINPUT_DllUnregisterServer(void)
+{
+    HRESULT hr;
+
+    TRACE("\n");
+
+    hr = unregister_coclasses(coclass_list);
+    if (SUCCEEDED(hr))
+	hr = unregister_interfaces(interface_list);
+    return hr;
+}
 
reactos/lib/dinput
diff -N version.rc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ version.rc	29 Nov 2004 00:13:49 -0000	1.1
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2001 Ove Kaaven
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define WINE_FILEDESCRIPTION_STR "Wine DirectInput"
+#define WINE_FILENAME_STR "dinput.dll"
+#define WINE_FILEVERSION 5,1,2600,881
+#define WINE_FILEVERSION_STR "5.1.2600.881"
+#define WINE_PRODUCTVERSION 5,1,2600,881
+#define WINE_PRODUCTVERSION_STR "5.1"
+
+#include "wine/wine_common_ver.rc"
 
CVSspam 0.2.8