ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dinput_main.c
Go to the documentation of this file.
00001 /*      DirectInput
00002  *
00003  * Copyright 1998 Marcus Meissner
00004  * Copyright 1998,1999 Lionel Ulmer
00005  * Copyright 2000-2002 TransGaming Technologies Inc.
00006  * Copyright 2007 Vitaliy Margolen
00007  *
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 /* Status:
00024  *
00025  * - Tomb Raider 2 Demo:
00026  *   Playable using keyboard only.
00027  * - WingCommander Prophecy Demo:
00028  *   Doesn't get Input Focus.
00029  *
00030  * - Fallout : works great in X and DGA mode
00031  */
00032 
00033 #include "config.h"
00034 #include <assert.h>
00035 #include <stdarg.h>
00036 #include <string.h>
00037 
00038 #define COBJMACROS
00039 #define NONAMELESSUNION
00040 
00041 #include "wine/debug.h"
00042 #include "wine/unicode.h"
00043 #include "windef.h"
00044 #include "winbase.h"
00045 #include "winuser.h"
00046 #include "winerror.h"
00047 #include "dinput_private.h"
00048 #include "device_private.h"
00049 
00050 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
00051 
00052 static const IDirectInput7AVtbl ddi7avt;
00053 static const IDirectInput7WVtbl ddi7wvt;
00054 static const IDirectInput8AVtbl ddi8avt;
00055 static const IDirectInput8WVtbl ddi8wvt;
00056 
00057 static inline IDirectInputImpl *impl_from_IDirectInput7W( IDirectInput7W *iface )
00058 {
00059     return CONTAINING_RECORD( iface, IDirectInputImpl, lpVtbl7w );
00060 }
00061 
00062 static inline IDirectInputImpl *impl_from_IDirectInput8A( IDirectInput8A *iface )
00063 {
00064     return CONTAINING_RECORD( iface, IDirectInputImpl, lpVtbl8a );
00065 }
00066 
00067 static inline IDirectInputImpl *impl_from_IDirectInput8W( IDirectInput8W *iface )
00068 {
00069     return CONTAINING_RECORD( iface, IDirectInputImpl, lpVtbl8w );
00070 }
00071 
00072 static inline IDirectInput7W *IDirectInput7W_from_impl( IDirectInputImpl *iface )
00073 {
00074     return (IDirectInput7W *)(&iface->lpVtbl7w);
00075 }
00076 
00077 static const struct dinput_device *dinput_devices[] =
00078 {
00079     &mouse_device,
00080     &keyboard_device,
00081     &joystick_linuxinput_device,
00082     &joystick_linux_device
00083 };
00084 #define NB_DINPUT_DEVICES (sizeof(dinput_devices)/sizeof(dinput_devices[0]))
00085 
00086 static HINSTANCE DINPUT_instance = NULL;
00087 
00088 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv)
00089 {
00090     switch(reason)
00091     {
00092       case DLL_PROCESS_ATTACH:
00093         DisableThreadLibraryCalls(inst);
00094         DINPUT_instance = inst;
00095         break;
00096       case DLL_PROCESS_DETACH:
00097         break;
00098     }
00099     return TRUE;
00100 }
00101 
00102 static BOOL check_hook_thread(void);
00103 static CRITICAL_SECTION dinput_hook_crit;
00104 static struct list direct_input_list = LIST_INIT( direct_input_list );
00105 
00106 /******************************************************************************
00107  *  DirectInputCreateEx (DINPUT.@)
00108  */
00109 HRESULT WINAPI DirectInputCreateEx(
00110     HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI,
00111     LPUNKNOWN punkOuter) 
00112 {
00113     IDirectInputImpl* This;
00114 
00115     TRACE("(%p,%04x,%s,%p,%p)\n", hinst, dwVersion, debugstr_guid(riid), ppDI, punkOuter);
00116 
00117     if (IsEqualGUID( &IID_IUnknown,       riid ) ||
00118         IsEqualGUID( &IID_IDirectInputA,  riid ) ||
00119         IsEqualGUID( &IID_IDirectInput2A, riid ) ||
00120         IsEqualGUID( &IID_IDirectInput7A, riid ) ||
00121         IsEqualGUID( &IID_IDirectInputW,  riid ) ||
00122         IsEqualGUID( &IID_IDirectInput2W, riid ) ||
00123         IsEqualGUID( &IID_IDirectInput7W, riid ) ||
00124         IsEqualGUID( &IID_IDirectInput8A, riid ) ||
00125         IsEqualGUID( &IID_IDirectInput8W, riid ))
00126     {
00127         if (!(This = HeapAlloc( GetProcessHeap(), 0, sizeof(IDirectInputImpl) )))
00128             return DIERR_OUTOFMEMORY;
00129     }
00130     else
00131         return DIERR_OLDDIRECTINPUTVERSION;
00132 
00133     This->lpVtbl      = &ddi7avt;
00134     This->lpVtbl7w    = &ddi7wvt;
00135     This->lpVtbl8a    = &ddi8avt;
00136     This->lpVtbl8w    = &ddi8wvt;
00137     This->ref         = 0;
00138     This->dwVersion   = dwVersion;
00139     This->evsequence  = 1;
00140 
00141     InitializeCriticalSection(&This->crit);
00142     This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit");
00143 
00144     list_init( &This->devices_list );
00145 
00146     /* Add self to the list of the IDirectInputs */
00147     EnterCriticalSection( &dinput_hook_crit );
00148     list_add_head( &direct_input_list, &This->entry );
00149     LeaveCriticalSection( &dinput_hook_crit );
00150 
00151     if (!check_hook_thread())
00152     {
00153         IUnknown_Release( (LPDIRECTINPUT7A)This );
00154         return DIERR_GENERIC;
00155     }
00156 
00157     IDirectInput_QueryInterface( (IDirectInput7A *)This, riid, ppDI );
00158     return DI_OK;
00159 }
00160 
00161 /******************************************************************************
00162  *  DirectInputCreateA (DINPUT.@)
00163  */
00164 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
00165 {
00166     return DirectInputCreateEx(hinst, dwVersion, &IID_IDirectInput7A, (LPVOID *)ppDI, punkOuter);
00167 }
00168 
00169 /******************************************************************************
00170  *  DirectInputCreateW (DINPUT.@)
00171  */
00172 HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter)
00173 {
00174     return DirectInputCreateEx(hinst, dwVersion, &IID_IDirectInput7W, (LPVOID *)ppDI, punkOuter);
00175 }
00176 
00177 static const char *_dump_DIDEVTYPE_value(DWORD dwDevType) {
00178     switch (dwDevType) {
00179         case 0: return "All devices";
00180     case DIDEVTYPE_MOUSE: return "DIDEVTYPE_MOUSE";
00181     case DIDEVTYPE_KEYBOARD: return "DIDEVTYPE_KEYBOARD";
00182     case DIDEVTYPE_JOYSTICK: return "DIDEVTYPE_JOYSTICK";
00183     case DIDEVTYPE_DEVICE: return "DIDEVTYPE_DEVICE";
00184     default: return "Unknown";
00185     }
00186 }
00187 
00188 static void _dump_EnumDevices_dwFlags(DWORD dwFlags) {
00189     if (TRACE_ON(dinput)) {
00190     unsigned int   i;
00191     static const struct {
00192         DWORD       mask;
00193         const char  *name;
00194     } flags[] = {
00195 #define FE(x) { x, #x}
00196         FE(DIEDFL_ALLDEVICES),
00197         FE(DIEDFL_ATTACHEDONLY),
00198         FE(DIEDFL_FORCEFEEDBACK),
00199         FE(DIEDFL_INCLUDEALIASES),
00200         FE(DIEDFL_INCLUDEPHANTOMS)
00201 #undef FE
00202     };
00203     TRACE(" flags: ");
00204     if (dwFlags == 0) {
00205         TRACE("DIEDFL_ALLDEVICES");
00206         return;
00207     }
00208     for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
00209         if (flags[i].mask & dwFlags)
00210         TRACE("%s ",flags[i].name);
00211     }
00212     TRACE("\n");
00213 }
00214 
00215 void _dump_diactionformatA(LPDIACTIONFORMATA lpdiActionFormat) {
00216     unsigned int i;
00217 
00218     FIXME("diaf.dwSize = %d\n", lpdiActionFormat->dwSize);
00219     FIXME("diaf.dwActionSize = %d\n", lpdiActionFormat->dwActionSize);
00220     FIXME("diaf.dwDataSize = %d\n", lpdiActionFormat->dwDataSize);
00221     FIXME("diaf.dwNumActions = %d\n", lpdiActionFormat->dwNumActions);
00222     FIXME("diaf.rgoAction = %p\n", lpdiActionFormat->rgoAction);
00223     for (i=0;i<lpdiActionFormat->dwNumActions;i++) {
00224         FIXME("diaf.rgoAction[%u]:\n", i);
00225         FIXME("\tuAppData=%lx\n", lpdiActionFormat->rgoAction[i].uAppData);
00226         FIXME("\tdwSemantics=%x\n", lpdiActionFormat->rgoAction[i].dwSemantics);
00227         FIXME("\tdwFlags=%x\n", lpdiActionFormat->rgoAction[i].dwFlags);
00228         FIXME("\tszActionName=%s\n", debugstr_a(lpdiActionFormat->rgoAction[i].u.lptszActionName));
00229         FIXME("\tguidInstance=%s\n", debugstr_guid(&lpdiActionFormat->rgoAction[i].guidInstance));
00230         FIXME("\tdwObjID=%x\n", lpdiActionFormat->rgoAction[i].dwObjID);
00231         FIXME("\tdwHow=%x\n", lpdiActionFormat->rgoAction[i].dwHow);
00232     }
00233     FIXME("diaf.guidActionMap = %s\n", debugstr_guid(&lpdiActionFormat->guidActionMap));
00234     FIXME("diaf.dwGenre = %d\n", lpdiActionFormat->dwGenre);
00235     FIXME("diaf.dwBufferSize = %d\n", lpdiActionFormat->dwBufferSize);
00236     FIXME("diaf.lAxisMin = %d\n", lpdiActionFormat->lAxisMin);
00237     FIXME("diaf.lAxisMax = %d\n", lpdiActionFormat->lAxisMax);
00238     FIXME("diaf.hInstString = %p\n", lpdiActionFormat->hInstString);
00239     FIXME("diaf.ftTimeStamp ...\n");
00240     FIXME("diaf.dwCRC = %x\n", lpdiActionFormat->dwCRC);
00241     FIXME("diaf.tszActionMap = %s\n", debugstr_a(lpdiActionFormat->tszActionMap));
00242 }
00243 
00244 /******************************************************************************
00245  *  IDirectInputA_EnumDevices
00246  */
00247 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
00248     LPDIRECTINPUT7A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
00249     LPVOID pvRef, DWORD dwFlags)
00250 {
00251     IDirectInputImpl *This = (IDirectInputImpl *)iface;
00252     DIDEVICEINSTANCEA devInstance;
00253     unsigned int i;
00254     int j, r;
00255 
00256     TRACE("(this=%p,0x%04x '%s',%p,%p,%04x)\n",
00257       This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),
00258       lpCallback, pvRef, dwFlags);
00259     _dump_EnumDevices_dwFlags(dwFlags);
00260 
00261     for (i = 0; i < NB_DINPUT_DEVICES; i++) {
00262         if (!dinput_devices[i]->enum_deviceA) continue;
00263         for (j = 0, r = -1; r != 0; j++) {
00264         devInstance.dwSize = sizeof(devInstance);
00265         TRACE("  - checking device %u ('%s')\n", i, dinput_devices[i]->name);
00266         if ((r = dinput_devices[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->dwVersion, j))) {
00267             if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
00268             return 0;
00269         }
00270     }
00271     }
00272     
00273     return 0;
00274 }
00275 /******************************************************************************
00276  *  IDirectInputW_EnumDevices
00277  */
00278 static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
00279     LPDIRECTINPUT7W iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback,
00280     LPVOID pvRef, DWORD dwFlags) 
00281 {
00282     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
00283     DIDEVICEINSTANCEW devInstance;
00284     unsigned int i;
00285     int j, r;
00286 
00287     TRACE("(this=%p,0x%04x '%s',%p,%p,%04x)\n",
00288       This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),
00289       lpCallback, pvRef, dwFlags);
00290     _dump_EnumDevices_dwFlags(dwFlags);
00291 
00292     for (i = 0; i < NB_DINPUT_DEVICES; i++) {
00293         if (!dinput_devices[i]->enum_deviceW) continue;
00294         for (j = 0, r = -1; r != 0; j++) {
00295         devInstance.dwSize = sizeof(devInstance);
00296         TRACE("  - checking device %u ('%s')\n", i, dinput_devices[i]->name);
00297         if ((r = dinput_devices[i]->enum_deviceW(dwDevType, dwFlags, &devInstance, This->dwVersion, j))) {
00298             if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
00299             return 0;
00300         }
00301     }
00302     }
00303     
00304     return 0;
00305 }
00306 
00307 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)
00308 {
00309     IDirectInputImpl *This = (IDirectInputImpl *)iface;
00310     ULONG ref = InterlockedIncrement(&This->ref);
00311 
00312     TRACE( "(%p) incrementing from %d\n", This, ref - 1);
00313     return ref;
00314 }
00315 
00316 static ULONG WINAPI IDirectInputWImpl_AddRef(LPDIRECTINPUT7W iface)
00317 {
00318     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
00319     return IDirectInputAImpl_AddRef( (IDirectInput7A *)This );
00320 }
00321 
00322 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
00323 {
00324     IDirectInputImpl *This = (IDirectInputImpl *)iface;
00325     ULONG ref = InterlockedDecrement( &This->ref );
00326 
00327     TRACE( "(%p) releasing from %d\n", This, ref + 1 );
00328 
00329     if (ref) return ref;
00330 
00331     /* Remove self from the list of the IDirectInputs */
00332     EnterCriticalSection( &dinput_hook_crit );
00333     list_remove( &This->entry );
00334     LeaveCriticalSection( &dinput_hook_crit );
00335 
00336     check_hook_thread();
00337 
00338     This->crit.DebugInfo->Spare[0] = 0;
00339     DeleteCriticalSection( &This->crit );
00340     HeapFree( GetProcessHeap(), 0, This );
00341 
00342     return 0;
00343 }
00344 
00345 static ULONG WINAPI IDirectInputWImpl_Release(LPDIRECTINPUT7W iface)
00346 {
00347     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
00348     return IDirectInputAImpl_Release( (IDirectInput7A *)This );
00349 }
00350 
00351 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, REFIID riid, LPVOID *ppobj)
00352 {
00353     IDirectInputImpl *This = (IDirectInputImpl *)iface;
00354 
00355     TRACE( "(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj );
00356 
00357     if (IsEqualGUID( &IID_IUnknown, riid ) ||
00358         IsEqualGUID( &IID_IDirectInputA,  riid ) ||
00359         IsEqualGUID( &IID_IDirectInput2A, riid ) ||
00360         IsEqualGUID( &IID_IDirectInput7A, riid ))
00361     {
00362         *ppobj = &This->lpVtbl;
00363         IUnknown_AddRef( (IUnknown*)*ppobj );
00364 
00365         return DI_OK;
00366     }
00367 
00368     if (IsEqualGUID( &IID_IDirectInputW,  riid ) ||
00369         IsEqualGUID( &IID_IDirectInput2W, riid ) ||
00370         IsEqualGUID( &IID_IDirectInput7W, riid ))
00371     {
00372         *ppobj = &This->lpVtbl7w;
00373         IUnknown_AddRef( (IUnknown*)*ppobj );
00374 
00375         return DI_OK;
00376     }
00377 
00378     if (IsEqualGUID( &IID_IDirectInput8A, riid ))
00379     {
00380         *ppobj = &This->lpVtbl8a;
00381         IUnknown_AddRef( (IUnknown*)*ppobj );
00382 
00383         return DI_OK;
00384     }
00385 
00386     if (IsEqualGUID( &IID_IDirectInput8W, riid ))
00387     {
00388         *ppobj = &This->lpVtbl8w;
00389         IUnknown_AddRef( (IUnknown*)*ppobj );
00390 
00391         return DI_OK;
00392     }
00393 
00394     FIXME( "Unsupported interface !\n" );
00395     return E_FAIL;
00396 }
00397 
00398 static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, REFIID riid, LPVOID *ppobj)
00399 {
00400     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
00401     return IDirectInputAImpl_QueryInterface( (IDirectInput7A *)This, riid, ppobj );
00402 }
00403 
00404 static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTANCE hinst, DWORD x) {
00405     TRACE("(this=%p,%p,%x)\n",iface, hinst, x);
00406     
00407     /* Initialize can return: DIERR_BETADIRECTINPUTVERSION, DIERR_OLDDIRECTINPUTVERSION and DI_OK.
00408      * Since we already initialized the device, return DI_OK. In the past we returned DIERR_ALREADYINITIALIZED
00409      * which broke applications like Tomb Raider Legend because it isn't a legal return value.
00410      */
00411     return DI_OK;
00412 }
00413 
00414 static HRESULT WINAPI IDirectInputWImpl_Initialize(LPDIRECTINPUT7W iface, HINSTANCE hinst, DWORD x)
00415 {
00416     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
00417     return IDirectInputAImpl_Initialize( (IDirectInput7A *)This, hinst, x );
00418 }
00419 
00420 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface, REFGUID rguid)
00421 {
00422     IDirectInputImpl *This = (IDirectInputImpl *)iface;
00423     HRESULT hr;
00424     LPDIRECTINPUTDEVICEA device;
00425 
00426     TRACE( "(%p)->(%s)\n", This, debugstr_guid(rguid) );
00427 
00428     hr = IDirectInput_CreateDevice( iface, rguid, &device, NULL );
00429     if (hr != DI_OK) return DI_NOTATTACHED;
00430 
00431     IUnknown_Release( device );
00432 
00433     return DI_OK;
00434 }
00435 
00436 static HRESULT WINAPI IDirectInputWImpl_GetDeviceStatus(LPDIRECTINPUT7W iface, REFGUID rguid)
00437 {
00438     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
00439     return IDirectInputAImpl_GetDeviceStatus( (IDirectInput7A *)This, rguid );
00440 }
00441 
00442 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
00443                             HWND hwndOwner,
00444                             DWORD dwFlags)
00445 {
00446     IDirectInputImpl *This = (IDirectInputImpl *)iface;
00447 
00448     FIXME( "(%p)->(%p,%08x): stub\n", This, hwndOwner, dwFlags );
00449 
00450     return DI_OK;
00451 }
00452 
00453 static HRESULT WINAPI IDirectInputWImpl_RunControlPanel(LPDIRECTINPUT7W iface, HWND hwndOwner, DWORD dwFlags)
00454 {
00455     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
00456     return IDirectInputAImpl_RunControlPanel( (IDirectInput7A *)This, hwndOwner, dwFlags );
00457 }
00458 
00459 static HRESULT WINAPI IDirectInput2AImpl_FindDevice(LPDIRECTINPUT7A iface, REFGUID rguid,
00460                             LPCSTR pszName, LPGUID pguidInstance)
00461 {
00462     IDirectInputImpl *This = (IDirectInputImpl *)iface;
00463 
00464     FIXME( "(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), pszName, pguidInstance );
00465 
00466     return DI_OK;
00467 }
00468 
00469 static HRESULT WINAPI IDirectInput2WImpl_FindDevice(LPDIRECTINPUT7W iface, REFGUID rguid,
00470                             LPCWSTR pszName, LPGUID pguidInstance)
00471 {
00472     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
00473 
00474     FIXME( "(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), debugstr_w(pszName), pguidInstance );
00475 
00476     return DI_OK;
00477 }
00478 
00479 static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, REFGUID rguid,
00480                             REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
00481 {
00482   IDirectInputImpl *This = (IDirectInputImpl *)iface;
00483   HRESULT ret_value = DIERR_DEVICENOTREG;
00484   unsigned int i;
00485 
00486   TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
00487 
00488   if (!rguid || !pvOut) return E_POINTER;
00489 
00490   /* Loop on all the devices to see if anyone matches the given GUID */
00491   for (i = 0; i < NB_DINPUT_DEVICES; i++) {
00492     HRESULT ret;
00493 
00494     if (!dinput_devices[i]->create_deviceA) continue;
00495     if ((ret = dinput_devices[i]->create_deviceA(This, rguid, riid, (LPDIRECTINPUTDEVICEA*) pvOut)) == DI_OK)
00496     {
00497       EnterCriticalSection( &This->crit );
00498       list_add_tail( &This->devices_list, &(*(IDirectInputDevice2AImpl**)pvOut)->entry );
00499       LeaveCriticalSection( &This->crit );
00500       return DI_OK;
00501     }
00502 
00503     if (ret == DIERR_NOINTERFACE)
00504       ret_value = DIERR_NOINTERFACE;
00505   }
00506 
00507   if (ret_value == DIERR_NOINTERFACE)
00508   {
00509     WARN("invalid device GUID %s\n", debugstr_guid(rguid));
00510   }
00511 
00512   return ret_value;
00513 }
00514 
00515 static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, REFGUID rguid,
00516                             REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
00517 {
00518   IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
00519   HRESULT ret_value = DIERR_DEVICENOTREG;
00520   unsigned int i;
00521 
00522   TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
00523 
00524   if (!rguid || !pvOut) return E_POINTER;
00525 
00526   /* Loop on all the devices to see if anyone matches the given GUID */
00527   for (i = 0; i < NB_DINPUT_DEVICES; i++) {
00528     HRESULT ret;
00529 
00530     if (!dinput_devices[i]->create_deviceW) continue;
00531     if ((ret = dinput_devices[i]->create_deviceW(This, rguid, riid, (LPDIRECTINPUTDEVICEW*) pvOut)) == DI_OK)
00532     {
00533       EnterCriticalSection( &This->crit );
00534       list_add_tail( &This->devices_list, &(*(IDirectInputDevice2AImpl**)pvOut)->entry );
00535       LeaveCriticalSection( &This->crit );
00536       return DI_OK;
00537     }
00538 
00539     if (ret == DIERR_NOINTERFACE)
00540       ret_value = DIERR_NOINTERFACE;
00541   }
00542 
00543   return ret_value;
00544 }
00545 
00546 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(LPDIRECTINPUT7A iface, REFGUID rguid,
00547                                                      LPDIRECTINPUTDEVICEA* pdev, LPUNKNOWN punk)
00548 {
00549     return IDirectInput7AImpl_CreateDeviceEx(iface, rguid, NULL, (LPVOID*)pdev, punk);
00550 }
00551 
00552 static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7W iface, REFGUID rguid,
00553                                                      LPDIRECTINPUTDEVICEW* pdev, LPUNKNOWN punk)
00554 {
00555     return IDirectInput7WImpl_CreateDeviceEx(iface, rguid, NULL, (LPVOID*)pdev, punk);
00556 }
00557 
00558 /*******************************************************************************
00559  *      DirectInput8
00560  */
00561 
00562 static ULONG WINAPI IDirectInput8AImpl_AddRef(LPDIRECTINPUT8A iface)
00563 {
00564     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00565     return IDirectInputAImpl_AddRef( (IDirectInput7A *)This );
00566 }
00567 
00568 static ULONG WINAPI IDirectInput8WImpl_AddRef(LPDIRECTINPUT8W iface)
00569 {
00570     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00571     return IDirectInputAImpl_AddRef( (IDirectInput7A *)This );
00572 }
00573 
00574 static HRESULT WINAPI IDirectInput8AImpl_QueryInterface(LPDIRECTINPUT8A iface, REFIID riid, LPVOID *ppobj)
00575 {
00576     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00577     return IDirectInputAImpl_QueryInterface( (IDirectInput7A *)This, riid, ppobj );
00578 }
00579 
00580 static HRESULT WINAPI IDirectInput8WImpl_QueryInterface(LPDIRECTINPUT8W iface, REFIID riid, LPVOID *ppobj)
00581 {
00582     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00583     return IDirectInputAImpl_QueryInterface( (IDirectInput7A *)This, riid, ppobj );
00584 }
00585 
00586 static ULONG WINAPI IDirectInput8AImpl_Release(LPDIRECTINPUT8A iface)
00587 {
00588     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00589     return IDirectInputAImpl_Release( (IDirectInput7A *)This );
00590 }
00591 
00592 static ULONG WINAPI IDirectInput8WImpl_Release(LPDIRECTINPUT8W iface)
00593 {
00594     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00595     return IDirectInputAImpl_Release( (IDirectInput7A *)This );
00596 }
00597 
00598 static HRESULT WINAPI IDirectInput8AImpl_CreateDevice(LPDIRECTINPUT8A iface, REFGUID rguid,
00599                                                       LPDIRECTINPUTDEVICE8A* pdev, LPUNKNOWN punk)
00600 {
00601     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00602     return IDirectInput7AImpl_CreateDeviceEx( (IDirectInput7A *)This, rguid, NULL, (LPVOID*)pdev, punk );
00603 }
00604 
00605 static HRESULT WINAPI IDirectInput8WImpl_CreateDevice(LPDIRECTINPUT8W iface, REFGUID rguid,
00606                                                       LPDIRECTINPUTDEVICE8W* pdev, LPUNKNOWN punk)
00607 {
00608     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00609     return IDirectInput7WImpl_CreateDeviceEx( IDirectInput7W_from_impl( This ), rguid, NULL, (LPVOID*)pdev, punk );
00610 }
00611 
00612 static HRESULT WINAPI IDirectInput8AImpl_EnumDevices(LPDIRECTINPUT8A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
00613                                                      LPVOID pvRef, DWORD dwFlags)
00614 {
00615     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00616     return IDirectInputAImpl_EnumDevices( (IDirectInput7A *)This, dwDevType, lpCallback, pvRef, dwFlags );
00617 }
00618 
00619 static HRESULT WINAPI IDirectInput8WImpl_EnumDevices(LPDIRECTINPUT8W iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback,
00620                                                      LPVOID pvRef, DWORD dwFlags)
00621 {
00622     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00623     return IDirectInputWImpl_EnumDevices( IDirectInput7W_from_impl( This ), dwDevType, lpCallback, pvRef, dwFlags );
00624 }
00625 
00626 static HRESULT WINAPI IDirectInput8AImpl_GetDeviceStatus(LPDIRECTINPUT8A iface, REFGUID rguid)
00627 {
00628     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00629     return IDirectInputAImpl_GetDeviceStatus( (IDirectInput7A *)This, rguid );
00630 }
00631 
00632 static HRESULT WINAPI IDirectInput8WImpl_GetDeviceStatus(LPDIRECTINPUT8W iface, REFGUID rguid)
00633 {
00634     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00635     return IDirectInputAImpl_GetDeviceStatus( (IDirectInput7A *)This, rguid );
00636 }
00637 
00638 static HRESULT WINAPI IDirectInput8AImpl_RunControlPanel(LPDIRECTINPUT8A iface, HWND hwndOwner, DWORD dwFlags)
00639 {
00640     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00641     return IDirectInputAImpl_RunControlPanel( (IDirectInput7A *)This, hwndOwner, dwFlags );
00642 }
00643 
00644 static HRESULT WINAPI IDirectInput8WImpl_RunControlPanel(LPDIRECTINPUT8W iface, HWND hwndOwner, DWORD dwFlags)
00645 {
00646     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00647     return IDirectInputAImpl_RunControlPanel( (IDirectInput7A *)This, hwndOwner, dwFlags );
00648 }
00649 
00650 static HRESULT WINAPI IDirectInput8AImpl_Initialize(LPDIRECTINPUT8A iface, HINSTANCE hinst, DWORD x)
00651 {
00652     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00653     return IDirectInputAImpl_Initialize( (IDirectInput7A *)This, hinst, x );
00654 }
00655 
00656 static HRESULT WINAPI IDirectInput8WImpl_Initialize(LPDIRECTINPUT8W iface, HINSTANCE hinst, DWORD x)
00657 {
00658     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00659     return IDirectInputAImpl_Initialize( (IDirectInput7A *)This, hinst, x );
00660 }
00661 
00662 static HRESULT WINAPI IDirectInput8AImpl_FindDevice(LPDIRECTINPUT8A iface, REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance)
00663 {
00664     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00665     return IDirectInput2AImpl_FindDevice( (IDirectInput7A *)This, rguid, pszName, pguidInstance );
00666 }
00667 
00668 static HRESULT WINAPI IDirectInput8WImpl_FindDevice(LPDIRECTINPUT8W iface, REFGUID rguid, LPCWSTR pszName, LPGUID pguidInstance)
00669 {
00670     IDirectInput7W *This = IDirectInput7W_from_impl( impl_from_IDirectInput8W( iface ) );
00671     return IDirectInput2WImpl_FindDevice( This, rguid, pszName, pguidInstance );
00672 }
00673 
00674 static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
00675       LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat,
00676       LPDIENUMDEVICESBYSEMANTICSCBA lpCallback,
00677       LPVOID pvRef, DWORD dwFlags
00678 )
00679 {
00680     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00681 
00682     FIXME("(this=%p,%s,%p,%p,%p,%04x): stub\n", This, ptszUserName, lpdiActionFormat,
00683           lpCallback, pvRef, dwFlags);
00684 #define X(x) if (dwFlags & x) FIXME("\tdwFlags |= "#x"\n");
00685     X(DIEDBSFL_ATTACHEDONLY)
00686     X(DIEDBSFL_THISUSER)
00687     X(DIEDBSFL_FORCEFEEDBACK)
00688     X(DIEDBSFL_AVAILABLEDEVICES)
00689     X(DIEDBSFL_MULTIMICEKEYBOARDS)
00690     X(DIEDBSFL_NONGAMINGDEVICES)
00691 #undef X
00692 
00693     _dump_diactionformatA(lpdiActionFormat);
00694 
00695     return DI_OK;
00696 }
00697 
00698 static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
00699       LPDIRECTINPUT8W iface, LPCWSTR ptszUserName, LPDIACTIONFORMATW lpdiActionFormat,
00700       LPDIENUMDEVICESBYSEMANTICSCBW lpCallback,
00701       LPVOID pvRef, DWORD dwFlags
00702 )
00703 {
00704       IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00705 
00706       FIXME("(this=%p,%s,%p,%p,%p,%04x): stub\n", This, debugstr_w(ptszUserName), lpdiActionFormat,
00707             lpCallback, pvRef, dwFlags);
00708       return 0;
00709 }
00710 
00711 static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
00712       LPDIRECTINPUT8A iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
00713       LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData
00714 )
00715 {
00716       IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
00717 
00718       FIXME("(this=%p,%p,%p,%04x,%p): stub\n", This, lpdiCallback, lpdiCDParams,
00719             dwFlags, pvRefData);
00720       return 0;
00721 }
00722 
00723 static HRESULT WINAPI IDirectInput8WImpl_ConfigureDevices(
00724       LPDIRECTINPUT8W iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
00725       LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData
00726 )
00727 {
00728       IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
00729 
00730       FIXME("(this=%p,%p,%p,%04x,%p): stub\n", This, lpdiCallback, lpdiCDParams,
00731             dwFlags, pvRefData);
00732       return 0;
00733 }
00734 
00735 static const IDirectInput7AVtbl ddi7avt = {
00736     IDirectInputAImpl_QueryInterface,
00737     IDirectInputAImpl_AddRef,
00738     IDirectInputAImpl_Release,
00739     IDirectInputAImpl_CreateDevice,
00740     IDirectInputAImpl_EnumDevices,
00741     IDirectInputAImpl_GetDeviceStatus,
00742     IDirectInputAImpl_RunControlPanel,
00743     IDirectInputAImpl_Initialize,
00744     IDirectInput2AImpl_FindDevice,
00745     IDirectInput7AImpl_CreateDeviceEx
00746 };
00747 
00748 static const IDirectInput7WVtbl ddi7wvt = {
00749     IDirectInputWImpl_QueryInterface,
00750     IDirectInputWImpl_AddRef,
00751     IDirectInputWImpl_Release,
00752     IDirectInputWImpl_CreateDevice,
00753     IDirectInputWImpl_EnumDevices,
00754     IDirectInputWImpl_GetDeviceStatus,
00755     IDirectInputWImpl_RunControlPanel,
00756     IDirectInputWImpl_Initialize,
00757     IDirectInput2WImpl_FindDevice,
00758     IDirectInput7WImpl_CreateDeviceEx
00759 };
00760 
00761 static const IDirectInput8AVtbl ddi8avt = {
00762     IDirectInput8AImpl_QueryInterface,
00763     IDirectInput8AImpl_AddRef,
00764     IDirectInput8AImpl_Release,
00765     IDirectInput8AImpl_CreateDevice,
00766     IDirectInput8AImpl_EnumDevices,
00767     IDirectInput8AImpl_GetDeviceStatus,
00768     IDirectInput8AImpl_RunControlPanel,
00769     IDirectInput8AImpl_Initialize,
00770     IDirectInput8AImpl_FindDevice,
00771     IDirectInput8AImpl_EnumDevicesBySemantics,
00772     IDirectInput8AImpl_ConfigureDevices
00773 };
00774 
00775 static const IDirectInput8WVtbl ddi8wvt = {
00776     IDirectInput8WImpl_QueryInterface,
00777     IDirectInput8WImpl_AddRef,
00778     IDirectInput8WImpl_Release,
00779     IDirectInput8WImpl_CreateDevice,
00780     IDirectInput8WImpl_EnumDevices,
00781     IDirectInput8WImpl_GetDeviceStatus,
00782     IDirectInput8WImpl_RunControlPanel,
00783     IDirectInput8WImpl_Initialize,
00784     IDirectInput8WImpl_FindDevice,
00785     IDirectInput8WImpl_EnumDevicesBySemantics,
00786     IDirectInput8WImpl_ConfigureDevices
00787 };
00788 
00789 /*******************************************************************************
00790  * DirectInput ClassFactory
00791  */
00792 typedef struct
00793 {
00794     /* IUnknown fields */
00795     const IClassFactoryVtbl    *lpVtbl;
00796     LONG                        ref;
00797 } IClassFactoryImpl;
00798 
00799 static HRESULT WINAPI DICF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
00800     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
00801 
00802     FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
00803     return E_NOINTERFACE;
00804 }
00805 
00806 static ULONG WINAPI DICF_AddRef(LPCLASSFACTORY iface) {
00807     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
00808     return InterlockedIncrement(&(This->ref));
00809 }
00810 
00811 static ULONG WINAPI DICF_Release(LPCLASSFACTORY iface) {
00812     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
00813     /* static class, won't be  freed */
00814     return InterlockedDecrement(&(This->ref));
00815 }
00816 
00817 static HRESULT WINAPI DICF_CreateInstance(
00818     LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
00819 ) {
00820     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
00821 
00822     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
00823         if ( IsEqualGUID( &IID_IUnknown, riid ) ||
00824              IsEqualGUID( &IID_IDirectInputA, riid ) ||
00825          IsEqualGUID( &IID_IDirectInputW, riid ) ||
00826          IsEqualGUID( &IID_IDirectInput2A, riid ) ||
00827          IsEqualGUID( &IID_IDirectInput2W, riid ) ||
00828          IsEqualGUID( &IID_IDirectInput7A, riid ) ||
00829          IsEqualGUID( &IID_IDirectInput7W, riid ) ||
00830          IsEqualGUID( &IID_IDirectInput8A, riid ) ||
00831          IsEqualGUID( &IID_IDirectInput8W, riid ) ) {
00832         /* FIXME: reuse already created dinput if present? */
00833         return DirectInputCreateEx(0,0,riid,ppobj,pOuter);
00834     }
00835 
00836     FIXME("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);    
00837     return E_NOINTERFACE;
00838 }
00839 
00840 static HRESULT WINAPI DICF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
00841     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
00842     FIXME("(%p)->(%d),stub!\n",This,dolock);
00843     return S_OK;
00844 }
00845 
00846 static const IClassFactoryVtbl DICF_Vtbl = {
00847     DICF_QueryInterface,
00848     DICF_AddRef,
00849     DICF_Release,
00850     DICF_CreateInstance,
00851     DICF_LockServer
00852 };
00853 static IClassFactoryImpl DINPUT_CF = {&DICF_Vtbl, 1 };
00854 
00855 /***********************************************************************
00856  *      DllCanUnloadNow (DINPUT.@)
00857  */
00858 HRESULT WINAPI DllCanUnloadNow(void)
00859 {
00860     FIXME("(void): stub\n");
00861 
00862     return S_FALSE;
00863 }
00864 
00865 /***********************************************************************
00866  *      DllGetClassObject (DINPUT.@)
00867  */
00868 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
00869 {
00870     TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
00871     if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
00872         *ppv = &DINPUT_CF;
00873     IClassFactory_AddRef((IClassFactory*)*ppv);
00874     return S_OK;
00875     }
00876 
00877     FIXME("(%s,%s,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
00878     return CLASS_E_CLASSNOTAVAILABLE;
00879 }
00880 
00881 /******************************************************************************
00882  *  DInput hook thread
00883  */
00884 
00885 static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam )
00886 {
00887     IDirectInputImpl *dinput;
00888     int skip = 0;
00889 
00890     if (code != HC_ACTION) return CallNextHookEx( 0, code, wparam, lparam );
00891 
00892     EnterCriticalSection( &dinput_hook_crit );
00893     LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry )
00894     {
00895         IDirectInputDevice2AImpl *dev;
00896 
00897         EnterCriticalSection( &dinput->crit );
00898         LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDevice2AImpl, entry )
00899             if (dev->acquired && dev->event_proc)
00900             {
00901                 TRACE("calling %p->%p (%lx %lx)\n", dev, dev->event_proc, wparam, lparam);
00902                 dev->event_proc( (LPDIRECTINPUTDEVICE8A)dev, wparam, lparam );
00903                 skip |= dev->dwCoopLevel & DISCL_EXCLUSIVE;
00904             }
00905         LeaveCriticalSection( &dinput->crit );
00906     }
00907     LeaveCriticalSection( &dinput_hook_crit );
00908 
00909     return skip ? 1 : CallNextHookEx( 0, code, wparam, lparam );
00910 }
00911 
00912 static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam )
00913 {
00914     CWPSTRUCT *msg = (CWPSTRUCT *)lparam;
00915     IDirectInputImpl *dinput;
00916     HWND foreground;
00917 
00918     if (code != HC_ACTION || (msg->message != WM_KILLFOCUS &&
00919         msg->message != WM_ACTIVATEAPP && msg->message != WM_ACTIVATE))
00920         return CallNextHookEx( 0, code, wparam, lparam );
00921 
00922     foreground = GetForegroundWindow();
00923 
00924     EnterCriticalSection( &dinput_hook_crit );
00925 
00926     LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry )
00927     {
00928         IDirectInputDevice2AImpl *dev;
00929 
00930         EnterCriticalSection( &dinput->crit );
00931         LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDevice2AImpl, entry )
00932         {
00933             if (!dev->acquired) continue;
00934 
00935             if (msg->hwnd == dev->win && msg->hwnd != foreground)
00936             {
00937                 TRACE( "%p window is not foreground - unacquiring %p\n", dev->win, dev );
00938                 IDirectInputDevice_Unacquire( (LPDIRECTINPUTDEVICE8A)dev );
00939             }
00940         }
00941         LeaveCriticalSection( &dinput->crit );
00942     }
00943     LeaveCriticalSection( &dinput_hook_crit );
00944 
00945     return CallNextHookEx( 0, code, wparam, lparam );
00946 }
00947 
00948 static DWORD WINAPI hook_thread_proc(void *param)
00949 {
00950     static HHOOK kbd_hook, mouse_hook;
00951     MSG msg;
00952 
00953     /* Force creation of the message queue */
00954     PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE );
00955     SetEvent(*(LPHANDLE)param);
00956 
00957     while (GetMessageW( &msg, 0, 0, 0 ))
00958     {
00959         UINT kbd_cnt = 0, mice_cnt = 0;
00960 
00961         if (msg.message == WM_USER+0x10)
00962         {
00963             IDirectInputImpl *dinput;
00964 
00965             TRACE( "Processing hook change notification lp:%ld\n", msg.lParam );
00966 
00967             if (!msg.wParam && !msg.lParam)
00968             {
00969                 if (kbd_hook) UnhookWindowsHookEx( kbd_hook );
00970                 if (mouse_hook) UnhookWindowsHookEx( mouse_hook );
00971                 kbd_hook = mouse_hook = NULL;
00972                 break;
00973             }
00974 
00975             EnterCriticalSection( &dinput_hook_crit );
00976 
00977             /* Count acquired keyboards and mice*/
00978             LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry )
00979             {
00980                 IDirectInputDevice2AImpl *dev;
00981 
00982                 EnterCriticalSection( &dinput->crit );
00983                 LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDevice2AImpl, entry )
00984                 {
00985                     if (!dev->acquired || !dev->event_proc) continue;
00986 
00987                     if (IsEqualGUID( &dev->guid, &GUID_SysKeyboard ) ||
00988                         IsEqualGUID( &dev->guid, &DInput_Wine_Keyboard_GUID ))
00989                         kbd_cnt++;
00990                     else
00991                         if (IsEqualGUID( &dev->guid, &GUID_SysMouse ) ||
00992                             IsEqualGUID( &dev->guid, &DInput_Wine_Mouse_GUID ))
00993                             mice_cnt++;
00994                 }
00995                 LeaveCriticalSection( &dinput->crit );
00996             }
00997             LeaveCriticalSection( &dinput_hook_crit );
00998 
00999             if (kbd_cnt && !kbd_hook)
01000                 kbd_hook = SetWindowsHookExW( WH_KEYBOARD_LL, LL_hook_proc, DINPUT_instance, 0 );
01001             else if (!kbd_cnt && kbd_hook)
01002             {
01003                 UnhookWindowsHookEx( kbd_hook );
01004                 kbd_hook = NULL;
01005             }
01006 
01007             if (mice_cnt && !mouse_hook)
01008                 mouse_hook = SetWindowsHookExW( WH_MOUSE_LL, LL_hook_proc, DINPUT_instance, 0 );
01009             else if (!mice_cnt && mouse_hook)
01010             {
01011                 UnhookWindowsHookEx( mouse_hook );
01012                 mouse_hook = NULL;
01013             }
01014         }
01015         TranslateMessage(&msg);
01016         DispatchMessageW(&msg);
01017     }
01018 
01019     return 0;
01020 }
01021 
01022 static DWORD hook_thread_id;
01023 
01024 static CRITICAL_SECTION_DEBUG dinput_critsect_debug =
01025 {
01026     0, 0, &dinput_hook_crit,
01027     { &dinput_critsect_debug.ProcessLocksList, &dinput_critsect_debug.ProcessLocksList },
01028       0, 0, { (DWORD_PTR)(__FILE__ ": dinput_hook_crit") }
01029 };
01030 static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0, 0 };
01031 
01032 static BOOL check_hook_thread(void)
01033 {
01034     static HANDLE hook_thread;
01035 
01036     EnterCriticalSection(&dinput_hook_crit);
01037 
01038     TRACE("IDirectInputs left: %d\n", list_count(&direct_input_list));
01039     if (!list_empty(&direct_input_list) && !hook_thread)
01040     {
01041         HANDLE event;
01042 
01043         event = CreateEventW(NULL, FALSE, FALSE, NULL);
01044         hook_thread = CreateThread(NULL, 0, hook_thread_proc, &event, 0, &hook_thread_id);
01045         if (event && hook_thread)
01046         {
01047             HANDLE handles[2];
01048             handles[0] = event;
01049             handles[1] = hook_thread;
01050             WaitForMultipleObjects(2, handles, FALSE, INFINITE);
01051         }
01052         LeaveCriticalSection(&dinput_hook_crit);
01053         CloseHandle(event);
01054     }
01055     else if (list_empty(&direct_input_list) && hook_thread)
01056     {
01057         DWORD tid = hook_thread_id;
01058 
01059         hook_thread_id = 0;
01060         PostThreadMessageW(tid, WM_USER+0x10, 0, 0);
01061         LeaveCriticalSection(&dinput_hook_crit);
01062 
01063         /* wait for hook thread to exit */
01064         WaitForSingleObject(hook_thread, INFINITE);
01065         CloseHandle(hook_thread);
01066         hook_thread = NULL;
01067     }
01068     else
01069         LeaveCriticalSection(&dinput_hook_crit);
01070 
01071     return hook_thread_id != 0;
01072 }
01073 
01074 void check_dinput_hooks(LPDIRECTINPUTDEVICE8A iface)
01075 {
01076     static HHOOK callwndproc_hook;
01077     static ULONG foreground_cnt;
01078     IDirectInputDevice2AImpl *dev = (IDirectInputDevice2AImpl *)iface;
01079 
01080     EnterCriticalSection(&dinput_hook_crit);
01081 
01082     if (dev->dwCoopLevel & DISCL_FOREGROUND)
01083     {
01084         if (dev->acquired)
01085             foreground_cnt++;
01086         else
01087             foreground_cnt--;
01088     }
01089 
01090     if (foreground_cnt && !callwndproc_hook)
01091         callwndproc_hook = SetWindowsHookExW( WH_CALLWNDPROC, callwndproc_proc,
01092                                               DINPUT_instance, GetCurrentThreadId() );
01093     else if (!foreground_cnt && callwndproc_hook)
01094     {
01095         UnhookWindowsHookEx( callwndproc_hook );
01096         callwndproc_hook = NULL;
01097     }
01098 
01099     PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, 0 );
01100 
01101     LeaveCriticalSection(&dinput_hook_crit);
01102 }

Generated on Sun May 27 2012 04:21:31 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.