Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendinput_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
1.7.6.1
|