set svn:eol-style to native
[reactos.git] / reactos / lib / dinput / dinput_main.c
index bd003d0..1edb9db 100644 (file)
-/*             DirectInput\r
- *\r
- * Copyright 1998 Marcus Meissner\r
- * Copyright 1998,1999 Lionel Ulmer\r
- * Copyright 2000-2002 TransGaming Technologies Inc.\r
- *\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-/* Status:\r
- *\r
- * - Tomb Raider 2 Demo:\r
- *   Playable using keyboard only.\r
- * - WingCommander Prophecy Demo:\r
- *   Doesn't get Input Focus.\r
- *\r
- * - Fallout : works great in X and DGA mode\r
- */\r
-\r
-#include "config.h"\r
-#include "wine/port.h"\r
-\r
-#include <assert.h>\r
-#include <stdarg.h>\r
-#include <string.h>\r
-\r
-#define COBJMACROS\r
-\r
-#include "wine/debug.h"\r
-#include "wine/unicode.h"\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "winuser.h"\r
-#include "winerror.h"\r
-#include "dinput_private.h"\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(dinput);\r
-\r
-static IDirectInput7AVtbl ddi7avt;\r
-static IDirectInput7WVtbl ddi7wvt;\r
-static IDirectInput8AVtbl ddi8avt;\r
-static IDirectInput8WVtbl ddi8wvt;\r
-\r
-/* This array will be filled a dinput.so loading */\r
-#define MAX_WINE_DINPUT_DEVICES 4\r
-static dinput_device * dinput_devices[MAX_WINE_DINPUT_DEVICES];\r
-static int nrof_dinput_devices = 0;\r
-\r
-HINSTANCE DINPUT_instance = NULL;\r
-\r
-BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv)\r
-{\r
-    switch(reason)\r
-    {\r
-      case DLL_PROCESS_ATTACH:\r
-        DisableThreadLibraryCalls(inst);\r
-        DINPUT_instance = inst;\r
-        break;\r
-      case DLL_PROCESS_DETACH:\r
-        break;\r
-    }\r
-    return TRUE;\r
-}\r
-\r
-/* register a direct draw driver. We better not use malloc for we are in\r
- * the ELF startup initialisation at this point.\r
- */\r
-void dinput_register_device(dinput_device *device) {\r
-    int        i;\r
-\r
-    /* insert according to priority */\r
-    for (i=0;i<nrof_dinput_devices;i++) {\r
-       if (dinput_devices[i]->pref <= device->pref) {\r
-           memcpy(dinput_devices+i+1,dinput_devices+i,sizeof(dinput_devices[0])*(nrof_dinput_devices-i));\r
-           dinput_devices[i] = device;\r
-           break;\r
-       }\r
-    }\r
-    if (i==nrof_dinput_devices)        /* not found, or too low priority */\r
-       dinput_devices[nrof_dinput_devices] = device;\r
-\r
-    nrof_dinput_devices++;\r
-\r
-    /* increase MAX_DDRAW_DRIVERS if the line below triggers */\r
-    assert(nrof_dinput_devices <= MAX_WINE_DINPUT_DEVICES);\r
-}\r
-\r
-/******************************************************************************\r
- *     DirectInputCreateEx (DINPUT.@)\r
- */\r
-HRESULT WINAPI DirectInputCreateEx(\r
-       HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI,\r
-       LPUNKNOWN punkOuter) \r
-{\r
-       IDirectInputImpl* This;\r
-\r
-       TRACE("(0x%08lx,%04lx,%s,%p,%p)\n", (DWORD)hinst,dwVersion,debugstr_guid(riid),ppDI,punkOuter);\r
-\r
-       if (IsEqualGUID(&IID_IDirectInputA,riid) ||\r
-           IsEqualGUID(&IID_IDirectInput2A,riid) ||\r
-           IsEqualGUID(&IID_IDirectInput7A,riid)) {\r
-         This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));\r
-         This->lpVtbl = &ddi7avt;\r
-         This->ref = 1;\r
-         This->version = 1;\r
-         *ppDI = This;\r
-\r
-         return DI_OK;\r
-       }\r
-\r
-       if (IsEqualGUID(&IID_IDirectInputW,riid) ||\r
-           IsEqualGUID(&IID_IDirectInput2W,riid) ||\r
-           IsEqualGUID(&IID_IDirectInput7W,riid)) {\r
-         This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));\r
-         This->lpVtbl = &ddi7wvt;\r
-         This->ref = 1;\r
-         This->version = 1;\r
-         *ppDI = This;\r
-\r
-         return DI_OK;\r
-       }\r
-\r
-       if (IsEqualGUID(&IID_IDirectInput8A,riid)) {\r
-         This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));\r
-         This->lpVtbl = &ddi8avt;\r
-         This->ref = 1;\r
-         This->version = 8;\r
-         *ppDI = This;\r
-\r
-         return DI_OK;\r
-       }\r
-\r
-       if (IsEqualGUID(&IID_IDirectInput8W,riid)) {\r
-         This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));\r
-         This->lpVtbl = &ddi8wvt;\r
-         This->ref = 1;\r
-         This->version = 8;\r
-         *ppDI = This;\r
-\r
-         return DI_OK;\r
-       }\r
-\r
-       return DIERR_OLDDIRECTINPUTVERSION;\r
-}\r
-\r
-/******************************************************************************\r
- *     DirectInputCreateA (DINPUT.@)\r
- */\r
-HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)\r
-{\r
-       IDirectInputImpl* This;\r
-       TRACE("(0x%08lx,%04lx,%p,%p)\n", (DWORD)hinst,dwVersion,ppDI,punkOuter);\r
-\r
-       //trace:dinput:DirectInputCreateA (0x00400000,0500,0x42bafc54,(nil))\r
-       This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));\r
-       This->lpVtbl = &ddi7avt;\r
-       This->ref = 1;\r
-       if (dwVersion > 0x0700) {\r
-           This->version = 8;\r
-       } else {\r
-           /* We do not differientiate between version 1, 2 and 7 */\r
-           This->version = 1;\r
-       }\r
-       *ppDI = (IDirectInputA*)This;\r
-       return 0;\r
-\r
-}\r
-\r
-/******************************************************************************\r
- *     DirectInputCreateW (DINPUT.@)\r
- */\r
-HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter)\r
-{\r
-       IDirectInputImpl* This;\r
-       TRACE("(0x%08lx,%04lx,%p,%p)\n", (DWORD)hinst,dwVersion,ppDI,punkOuter);\r
-       This = (IDirectInputImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));\r
-       This->lpVtbl = &ddi7wvt;\r
-       This->ref = 1;\r
-       if (dwVersion >= 0x0800) {\r
-           This->version = 8;\r
-       } else {\r
-           /* We do not differientiate between version 1, 2 and 7 */\r
-           This->version = 1;\r
-       }\r
-       *ppDI = (IDirectInputW*)This;\r
-       return 0;\r
-}\r
-\r
-static const char *_dump_DIDEVTYPE_value(DWORD dwDevType) {\r
-    switch (dwDevType) {\r
-        case 0: return "All devices";\r
-       case DIDEVTYPE_MOUSE: return "DIDEVTYPE_MOUSE";\r
-       case DIDEVTYPE_KEYBOARD: return "DIDEVTYPE_KEYBOARD";\r
-       case DIDEVTYPE_JOYSTICK: return "DIDEVTYPE_JOYSTICK";\r
-       case DIDEVTYPE_DEVICE: return "DIDEVTYPE_DEVICE";\r
-       default: return "Unkown";\r
-    }\r
-}\r
-\r
-static void _dump_EnumDevices_dwFlags(DWORD dwFlags) {\r
-    if (TRACE_ON(dinput)) {\r
-       unsigned int   i;\r
-       static const struct {\r
-           DWORD       mask;\r
-           const char  *name;\r
-       } flags[] = {\r
-#define FE(x) { x, #x}\r
-           FE(DIEDFL_ALLDEVICES),\r
-           FE(DIEDFL_ATTACHEDONLY),\r
-           FE(DIEDFL_FORCEFEEDBACK),\r
-           FE(DIEDFL_INCLUDEALIASES),\r
-           FE(DIEDFL_INCLUDEPHANTOMS)\r
-#undef FE\r
-       };\r
-       if (dwFlags == 0) {\r
-           DPRINTF("DIEDFL_ALLDEVICES");\r
-           return;\r
-       }\r
-       for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)\r
-           if (flags[i].mask & dwFlags)\r
-               DPRINTF("%s ",flags[i].name);\r
-    }\r
-}\r
-\r
-/******************************************************************************\r
- *     IDirectInputA_EnumDevices\r
- */\r
-static HRESULT WINAPI IDirectInputAImpl_EnumDevices(\r
-       LPDIRECTINPUT7A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,\r
-       LPVOID pvRef, DWORD dwFlags)\r
-{\r
-    IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-    DIDEVICEINSTANCEA devInstance;\r
-    int i, j, r;\r
-    \r
-    TRACE("(this=%p,0x%04lx '%s',%p,%p,%04lx)\n",\r
-         This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),\r
-         lpCallback, pvRef, dwFlags);\r
-\r
-       if (nrof_dinput_devices==0){\r
-         scan_mouse();\r
-         scan_keyboard();\r
-       }\r
-       \r
-    TRACE(" flags: "); _dump_EnumDevices_dwFlags(dwFlags); TRACE("\n");\r
-    \r
-\r
-    for (i = 0; i < nrof_dinput_devices; i++) {\r
-        for (j = 0, r = -1; r != 0; j++) {\r
-           devInstance.dwSize = sizeof(devInstance);\r
-           TRACE("  - checking device %d ('%s')\n", i, dinput_devices[i]->name);\r
-               \r
-\r
-           if ((r = dinput_devices[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->version, j))) {\r
-               if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)\r
-                   return 0;\r
-           }\r
-       }\r
-    }\r
-    \r
-    return 0;\r
-}\r
-/******************************************************************************\r
- *     IDirectInputW_EnumDevices\r
- */\r
-static HRESULT WINAPI IDirectInputWImpl_EnumDevices(\r
-       LPDIRECTINPUT7W iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback,\r
-       LPVOID pvRef, DWORD dwFlags) \r
-{\r
-    IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-    DIDEVICEINSTANCEW devInstance;\r
-    int i, j, r;\r
-    \r
-               if (nrof_dinput_devices==0){\r
-         scan_mouse();\r
-         scan_keyboard();\r
-       }\r
-\r
-    TRACE("(this=%p,0x%04lx '%s',%p,%p,%04lx)\n",\r
-         This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),\r
-         lpCallback, pvRef, dwFlags);\r
-    TRACE(" flags: "); _dump_EnumDevices_dwFlags(dwFlags); TRACE("\n");\r
-\r
-\r
-    for (i = 0; i < nrof_dinput_devices; i++) {\r
-        for (j = 0, r = -1; r != 0; j++) {\r
-           devInstance.dwSize = sizeof(devInstance);\r
-           TRACE("  - checking device %d ('%s')\n", i, dinput_devices[i]->name);\r
-           if ((r = dinput_devices[i]->enum_deviceW(dwDevType, dwFlags, &devInstance, This->version, j))) {\r
-               if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)\r
-                   return 0;\r
-           }\r
-       }\r
-    }\r
-    \r
-    return 0;\r
-}\r
-\r
-static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)\r
-{\r
-       IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-       return InterlockedIncrement((&This->ref));\r
-}\r
-\r
-static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)\r
-{\r
-       IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-       ULONG ref;\r
-       ref = InterlockedDecrement(&(This->ref));\r
-       if (ref == 0)\r
-               HeapFree(GetProcessHeap(),0,This);\r
-       return ref;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, REFIID riid, LPVOID *ppobj) {\r
-       IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-\r
-       TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);\r
-       if (IsEqualGUID(&IID_IUnknown,riid) ||\r
-           IsEqualGUID(&IID_IDirectInputA,riid) ||\r
-           IsEqualGUID(&IID_IDirectInput2A,riid) ||\r
-           IsEqualGUID(&IID_IDirectInput7A,riid)) {\r
-               IDirectInputAImpl_AddRef(iface);\r
-               *ppobj = This;\r
-               return 0;\r
-       }\r
-       TRACE("Unsupported interface !\n");\r
-       return E_FAIL;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, REFIID riid, LPVOID *ppobj) {\r
-       IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-\r
-       TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);\r
-       if (IsEqualGUID(&IID_IUnknown,riid) ||\r
-           IsEqualGUID(&IID_IDirectInputW,riid) ||\r
-           IsEqualGUID(&IID_IDirectInput2W,riid) ||\r
-           IsEqualGUID(&IID_IDirectInput7W,riid)) {\r
-               IDirectInputAImpl_AddRef((LPDIRECTINPUT7A) iface);\r
-               *ppobj = This;\r
-               return 0;\r
-       }\r
-       TRACE("Unsupported interface !\n");\r
-       return E_FAIL;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInputAImpl_CreateDevice(\r
-       LPDIRECTINPUT7A iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,\r
-       LPUNKNOWN punk\r
-) {\r
-       IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-       HRESULT ret_value = DIERR_DEVICENOTREG;\r
-       int i;\r
-\r
-       TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);\r
-       \r
-       if (nrof_dinput_devices==0){\r
-         scan_mouse();\r
-         scan_keyboard();\r
-       }\r
-       \r
-       /* Loop on all the devices to see if anyone matches the given GUID */\r
-       for (i = 0; i < nrof_dinput_devices; i++) {\r
-         HRESULT ret;\r
-         if ((ret = dinput_devices[i]->create_deviceA(This, rguid, NULL, pdev)) == DI_OK)\r
-           return DI_OK;\r
-\r
-         if (ret == DIERR_NOINTERFACE)\r
-           ret_value = DIERR_NOINTERFACE;\r
-       }\r
-\r
-       return ret_value;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7A iface, \r
-                                                    REFGUID rguid, LPDIRECTINPUTDEVICEW* pdev, LPUNKNOWN punk) {\r
-        IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-       HRESULT ret_value = DIERR_DEVICENOTREG;\r
-       int i;\r
-    \r
-       TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);\r
-\r
-       if (nrof_dinput_devices==0){\r
-         scan_mouse();\r
-         scan_keyboard();\r
-       }\r
-       \r
-       /* Loop on all the devices to see if anyone matches the given GUID */\r
-       for (i = 0; i < nrof_dinput_devices; i++) {\r
-         HRESULT ret;\r
-         if ((ret = dinput_devices[i]->create_deviceW(This, rguid, NULL, pdev)) == DI_OK)\r
-           return DI_OK;\r
-\r
-         if (ret == DIERR_NOINTERFACE)\r
-           ret_value = DIERR_NOINTERFACE;\r
-       }\r
-\r
-       return ret_value;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTANCE hinst, DWORD x) {\r
-       return DIERR_ALREADYINITIALIZED;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface,\r
-                                                       REFGUID rguid) {\r
-  IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-\r
-  FIXME("(%p)->(%s): stub\n",This,debugstr_guid(rguid));\r
-\r
-  return DI_OK;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,\r
-                                                       HWND hwndOwner,\r
-                                                       DWORD dwFlags) {\r
-  IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-  FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);\r
-\r
-  return DI_OK;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput2AImpl_FindDevice(LPDIRECTINPUT7A iface, REFGUID rguid,\r
-                                                   LPCSTR pszName, LPGUID pguidInstance) {\r
-  IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-  FIXME("(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), pszName, pguidInstance);\r
-\r
-  return DI_OK;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput2WImpl_FindDevice(LPDIRECTINPUT7W iface, REFGUID rguid,\r
-                                                   LPCWSTR pszName, LPGUID pguidInstance) {\r
-  IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-  FIXME("(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), debugstr_w(pszName), pguidInstance);\r
-\r
-  return DI_OK;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, REFGUID rguid,\r
-                                                       REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)\r
-{\r
-  IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-  HRESULT ret_value = DIERR_DEVICENOTREG;\r
-  int i;\r
-\r
-  TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);\r
-\r
-  if (nrof_dinput_devices==0){\r
-    scan_mouse();\r
-    scan_keyboard();\r
-  }  \r
-\r
-  /* Loop on all the devices to see if anyone matches the given GUID */\r
-  for (i = 0; i < nrof_dinput_devices; i++) {\r
-    HRESULT ret;\r
-    if ((ret = dinput_devices[i]->create_deviceA(This, rguid, riid, (LPDIRECTINPUTDEVICEA*) pvOut)) == DI_OK)\r
-      return DI_OK;\r
-\r
-    if (ret == DIERR_NOINTERFACE)\r
-      ret_value = DIERR_NOINTERFACE;\r
-  }\r
-\r
-  return ret_value;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, REFGUID rguid,\r
-                                                       REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)\r
-{\r
-  IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-  HRESULT ret_value = DIERR_DEVICENOTREG;\r
-  int i;\r
-\r
-  TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);\r
-\r
-       if (nrof_dinput_devices==0){\r
-         scan_mouse();\r
-         scan_keyboard();\r
-       }\r
-  \r
-\r
-\r
-  /* Loop on all the devices to see if anyone matches the given GUID */\r
-  for (i = 0; i < nrof_dinput_devices; i++) {\r
-    HRESULT ret;\r
-    if ((ret = dinput_devices[i]->create_deviceW(This, rguid, riid, (LPDIRECTINPUTDEVICEW*) pvOut)) == DI_OK)\r
-      return DI_OK;\r
-\r
-    if (ret == DIERR_NOINTERFACE)\r
-      ret_value = DIERR_NOINTERFACE;\r
-  }\r
-\r
-  return ret_value;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput8AImpl_QueryInterface(LPDIRECTINPUT8A iface, REFIID riid, LPVOID *ppobj) {\r
-      IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-\r
-      TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);\r
-      if (IsEqualGUID(&IID_IUnknown,riid) ||\r
-          IsEqualGUID(&IID_IDirectInput8A,riid)) {\r
-              IDirectInputAImpl_AddRef((LPDIRECTINPUT7A) iface);\r
-              *ppobj = This;\r
-              return 0;\r
-      }\r
-      TRACE("Unsupported interface !\n");\r
-      return E_NOINTERFACE;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput8WImpl_QueryInterface(LPDIRECTINPUT8W iface, REFIID riid, LPVOID *ppobj) {\r
-      IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-\r
-      TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);\r
-      if (IsEqualGUID(&IID_IUnknown,riid) ||\r
-          IsEqualGUID(&IID_IDirectInput8W,riid)) {\r
-              IDirectInputAImpl_AddRef((LPDIRECTINPUT7A) iface);\r
-              *ppobj = This;\r
-              return 0;\r
-      }\r
-      TRACE("Unsupported interface !\n");\r
-      return E_NOINTERFACE;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(\r
-      LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat,\r
-      LPDIENUMDEVICESBYSEMANTICSCBA lpCallback,\r
-      LPVOID pvRef, DWORD dwFlags\r
-)\r
-{\r
-      IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-\r
-      FIXME("(this=%p,%s,%p,%p,%p,%04lx): stub\n", This, ptszUserName, lpdiActionFormat,\r
-            lpCallback, pvRef, dwFlags);\r
-      return 0;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(\r
-      LPDIRECTINPUT8W iface, LPCWSTR ptszUserName, LPDIACTIONFORMATW lpdiActionFormat,\r
-      LPDIENUMDEVICESBYSEMANTICSCBW lpCallback,\r
-      LPVOID pvRef, DWORD dwFlags\r
-)\r
-{\r
-      IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-\r
-      FIXME("(this=%p,%s,%p,%p,%p,%04lx): stub\n", This, debugstr_w(ptszUserName), lpdiActionFormat,\r
-            lpCallback, pvRef, dwFlags);\r
-      return 0;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(\r
-      LPDIRECTINPUT8A iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,\r
-      LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData\r
-)\r
-{\r
-      IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-\r
-      FIXME("(this=%p,%p,%p,%04lx,%p): stub\n", This, lpdiCallback, lpdiCDParams,\r
-            dwFlags, pvRefData);\r
-      return 0;\r
-}\r
-\r
-static HRESULT WINAPI IDirectInput8WImpl_ConfigureDevices(\r
-      LPDIRECTINPUT8W iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,\r
-      LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData\r
-)\r
-{\r
-      IDirectInputImpl *This = (IDirectInputImpl *)iface;\r
-\r
-      FIXME("(this=%p,%p,%p,%04lx,%p): stub\n", This, lpdiCallback, lpdiCDParams,\r
-            dwFlags, pvRefData);\r
-      return 0;\r
-}\r
-\r
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)\r
-# define XCAST(fun)   (typeof(ddi7avt.fun))\r
-#else\r
-# define XCAST(fun)    (void*)\r
-#endif\r
-\r
-static IDirectInput7AVtbl ddi7avt = {\r
-       XCAST(QueryInterface)IDirectInputAImpl_QueryInterface,\r
-       XCAST(AddRef)IDirectInputAImpl_AddRef,\r
-       XCAST(Release)IDirectInputAImpl_Release,\r
-       XCAST(CreateDevice)IDirectInputAImpl_CreateDevice,\r
-       XCAST(EnumDevices)IDirectInputAImpl_EnumDevices,\r
-       XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,\r
-       XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,\r
-       XCAST(Initialize)IDirectInputAImpl_Initialize,\r
-       XCAST(FindDevice)IDirectInput2AImpl_FindDevice,\r
-       XCAST(CreateDeviceEx)IDirectInput7AImpl_CreateDeviceEx\r
-};\r
-\r
-#undef XCAST\r
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)\r
-# define XCAST(fun)   (typeof(ddi7wvt.fun))\r
-#else\r
-# define XCAST(fun)    (void*)\r
-#endif\r
-\r
-static IDirectInput7WVtbl ddi7wvt = {\r
-       XCAST(QueryInterface)IDirectInputWImpl_QueryInterface,\r
-       XCAST(AddRef)IDirectInputAImpl_AddRef,\r
-       XCAST(Release)IDirectInputAImpl_Release,\r
-       XCAST(CreateDevice)IDirectInputWImpl_CreateDevice,\r
-       XCAST(EnumDevices)IDirectInputWImpl_EnumDevices,\r
-       XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,\r
-       XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,\r
-       XCAST(Initialize)IDirectInputAImpl_Initialize,\r
-       XCAST(FindDevice)IDirectInput2WImpl_FindDevice,\r
-       XCAST(CreateDeviceEx)IDirectInput7WImpl_CreateDeviceEx\r
-};\r
-#undef XCAST\r
-\r
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)\r
-# define XCAST(fun)    (typeof(ddi8avt.fun))\r
-#else\r
-# define XCAST(fun)    (void*)\r
-#endif\r
-\r
-static IDirectInput8AVtbl ddi8avt = {\r
-       XCAST(QueryInterface)IDirectInput8AImpl_QueryInterface,\r
-       XCAST(AddRef)IDirectInputAImpl_AddRef,\r
-       XCAST(Release)IDirectInputAImpl_Release,\r
-       XCAST(CreateDevice)IDirectInputAImpl_CreateDevice,\r
-       XCAST(EnumDevices)IDirectInputAImpl_EnumDevices,\r
-       XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,\r
-       XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,\r
-       XCAST(Initialize)IDirectInputAImpl_Initialize,\r
-       XCAST(FindDevice)IDirectInput2AImpl_FindDevice,\r
-       XCAST(EnumDevicesBySemantics)IDirectInput8AImpl_EnumDevicesBySemantics,\r
-       XCAST(ConfigureDevices)IDirectInput8AImpl_ConfigureDevices\r
-};\r
-#undef XCAST\r
-\r
-#if !defined(__STRICT_ANSI__) && defined(__GNUC__)\r
-# define XCAST(fun)    (typeof(ddi8wvt.fun))\r
-#else\r
-# define XCAST(fun)    (void*)\r
-#endif\r
-static IDirectInput8WVtbl ddi8wvt = {\r
-       XCAST(QueryInterface)IDirectInput8WImpl_QueryInterface,\r
-       XCAST(AddRef)IDirectInputAImpl_AddRef,\r
-       XCAST(Release)IDirectInputAImpl_Release,\r
-       XCAST(CreateDevice)IDirectInputWImpl_CreateDevice,\r
-       XCAST(EnumDevices)IDirectInputWImpl_EnumDevices,\r
-       XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,\r
-       XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,\r
-       XCAST(Initialize)IDirectInputAImpl_Initialize,\r
-       XCAST(FindDevice)IDirectInput2WImpl_FindDevice,\r
-       XCAST(EnumDevicesBySemantics)IDirectInput8WImpl_EnumDevicesBySemantics,\r
-       XCAST(ConfigureDevices)IDirectInput8WImpl_ConfigureDevices\r
-};\r
-#undef XCAST\r
-\r
-/*******************************************************************************\r
- * DirectInput ClassFactory\r
- */\r
-typedef struct\r
-{\r
-    /* IUnknown fields */\r
-    IClassFactoryVtbl          *lpVtbl;\r
-    DWORD                       ref;\r
-} IClassFactoryImpl;\r
-\r
-static HRESULT WINAPI DICF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {\r
-       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;\r
-\r
-       FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);\r
-       return E_NOINTERFACE;\r
-}\r
-\r
-static ULONG WINAPI DICF_AddRef(LPCLASSFACTORY iface) {\r
-       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;\r
-       return InterlockedIncrement(&(This->ref));\r
-}\r
-\r
-static ULONG WINAPI DICF_Release(LPCLASSFACTORY iface) {\r
-       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;\r
-       /* static class, won't be  freed */\r
-       return InterlockedDecrement(&(This->ref));\r
-}\r
-\r
-static HRESULT WINAPI DICF_CreateInstance(\r
-       LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj\r
-) {\r
-       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;\r
-\r
-       TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);\r
-       if ( IsEqualGUID( &IID_IDirectInputA, riid ) ||\r
-            IsEqualGUID( &IID_IDirectInputW, riid ) ||\r
-            IsEqualGUID( &IID_IDirectInput2A, riid ) ||\r
-            IsEqualGUID( &IID_IDirectInput2W, riid ) ||\r
-            IsEqualGUID( &IID_IDirectInput7A, riid ) ||\r
-            IsEqualGUID( &IID_IDirectInput7W, riid ) ||\r
-            IsEqualGUID( &IID_IDirectInput8A, riid ) ||\r
-            IsEqualGUID( &IID_IDirectInput8W, riid ) ) {\r
-               /* FIXME: reuse already created dinput if present? */\r
-               return DirectInputCreateEx(0,0,riid,ppobj,pOuter);\r
-       }\r
-\r
-       FIXME("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);    \r
-       return E_NOINTERFACE;\r
-}\r
-\r
-static HRESULT WINAPI DICF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {\r
-       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;\r
-       FIXME("(%p)->(%d),stub!\n",This,dolock);\r
-       return S_OK;\r
-}\r
-\r
-static IClassFactoryVtbl DICF_Vtbl = {\r
-       DICF_QueryInterface,\r
-       DICF_AddRef,\r
-       DICF_Release,\r
-       DICF_CreateInstance,\r
-       DICF_LockServer\r
-};\r
-static IClassFactoryImpl DINPUT_CF = {&DICF_Vtbl, 1 };\r
-\r
-/***********************************************************************\r
- *             DllCanUnloadNow (DINPUT.@)\r
- */\r
-HRESULT WINAPI DINPUT_DllCanUnloadNow(void)\r
-{\r
-    FIXME("(void): stub\n");\r
-\r
-    return S_FALSE;\r
-}\r
-\r
-/***********************************************************************\r
- *             DllGetClassObject (DINPUT.@)\r
- */\r
-HRESULT WINAPI DINPUT_DllGetClassObject(REFCLSID rclsid, REFIID riid,\r
-                                       LPVOID *ppv)\r
-{\r
-    TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);\r
-    if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {\r
-       *ppv = (LPVOID)&DINPUT_CF;\r
-       IClassFactory_AddRef((IClassFactory*)*ppv);\r
-    return S_OK;\r
-    }\r
-\r
-    FIXME("(%s,%s,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);\r
-    return CLASS_E_CLASSNOTAVAILABLE;\r
-}\r
+/*             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 const 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("(%s,%s,%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("(%s,%s,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+    return CLASS_E_CLASSNOTAVAILABLE;
+}