Commit in reactos/lib/dinput on MAIN
Makefile+91.3 -> 1.4
Makefile.in+23added 1.1
Makefile.ros+28added 1.1
Makefile.ros-template+28added 1.1
data_formats.c+302added 1.1
device.c+884added 1.1
device_private.h+236added 1.1
dinput.stubs.c+3added 1.1
dinput_main.c+756added 1.1
dinput_private.h+58added 1.1
joystick_linux.c+1715added 1.1
joystick_linuxinput.c+1090added 1.1
keyboard.c+868added 1.1
mouse.c+1253added 1.1
regsvr.c+558added 1.1
version.rc+26added 1.1
+7837
15 added + 1 modified, total 16 files
first port of wine directx support to reactos

add wine dinput and dinput8 it have been modify to working in windows and reactos. 
when reactos got hooks implant remove all #ifdef __REACTOS__  and code that belong it compelete, then  
remove all #ifndef __REACTOS__  to geting in working in reactos and windows. 
dxguid comes from mingw with some modify 

todo
rewrite dection code of keyboard, mouse, joystick to using windows registers to get what type of hardware.

Limit
Only keyboard are working in reactos for moment.

reactos/lib/dinput
Makefile 1.3 -> 1.4
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
Makefile.in added at 1.1
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
Makefile.ros added at 1.1
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
Makefile.ros-template added at 1.1
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
data_formats.c added at 1.1
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
device.c added at 1.1
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
device_private.h added at 1.1
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
dinput.stubs.c added at 1.1
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
dinput_main.c added at 1.1
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
dinput_private.h added at 1.1
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
joystick_linux.c added at 1.1
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
joystick_linuxinput.c added at 1.1
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
keyboard.c added at 1.1
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
mouse.c added at 1.1
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
regsvr.c added at 1.1
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
version.rc added at 1.1
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