Commit fe1f1362 authored by Vitaliy Margolen's avatar Vitaliy Margolen Committed by Alexandre Julliard

dinput: Keep a list of all IDirectInput objects and check it instead of refcount…

dinput: Keep a list of all IDirectInput objects and check it instead of refcount to create/destroy hook thread.
parent 448dde9b
...@@ -77,8 +77,9 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv) ...@@ -77,8 +77,9 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv)
return TRUE; return TRUE;
} }
static BOOL create_hook_thread(void); static BOOL check_hook_thread(void);
static void release_hook_thread(void); static CRITICAL_SECTION dinput_hook_crit;
static struct list direct_input_list = LIST_INIT( direct_input_list );
/****************************************************************************** /******************************************************************************
* DirectInputCreateEx (DINPUT.@) * DirectInputCreateEx (DINPUT.@)
...@@ -88,55 +89,48 @@ HRESULT WINAPI DirectInputCreateEx( ...@@ -88,55 +89,48 @@ HRESULT WINAPI DirectInputCreateEx(
LPUNKNOWN punkOuter) LPUNKNOWN punkOuter)
{ {
IDirectInputImpl* This; IDirectInputImpl* This;
HRESULT res = DIERR_OLDDIRECTINPUTVERSION;
LPCVOID vtable = NULL; LPCVOID vtable = NULL;
TRACE("(%p,%04x,%s,%p,%p)\n", hinst, dwVersion, debugstr_guid(riid), ppDI, punkOuter); TRACE("(%p,%04x,%s,%p,%p)\n", hinst, dwVersion, debugstr_guid(riid), ppDI, punkOuter);
if (IsEqualGUID(&IID_IDirectInputA,riid) || if (IsEqualGUID( &IID_IDirectInputA, riid ) ||
IsEqualGUID(&IID_IDirectInput2A,riid) || IsEqualGUID( &IID_IDirectInput2A, riid ) ||
IsEqualGUID(&IID_IDirectInput7A,riid)) IsEqualGUID( &IID_IDirectInput7A, riid )) vtable = &ddi7avt;
{ else if (IsEqualGUID( &IID_IDirectInputW, riid ) ||
vtable = &ddi7avt; IsEqualGUID( &IID_IDirectInput2W, riid ) ||
res = DI_OK; IsEqualGUID( &IID_IDirectInput7W, riid )) vtable = &ddi7wvt;
} else if (IsEqualGUID( &IID_IDirectInput8A, riid )) vtable = &ddi8avt;
else if (IsEqualGUID( &IID_IDirectInput8W, riid )) vtable = &ddi8wvt;
if (IsEqualGUID(&IID_IDirectInputW,riid) || else
IsEqualGUID(&IID_IDirectInput2W,riid) || return DIERR_OLDDIRECTINPUTVERSION;
IsEqualGUID(&IID_IDirectInput7W,riid))
{
vtable = &ddi7wvt;
res = DI_OK;
}
if (IsEqualGUID(&IID_IDirectInput8A,riid))
{
vtable = &ddi8avt;
res = DI_OK;
}
if (IsEqualGUID(&IID_IDirectInput8W,riid)) if (!(This = HeapAlloc( GetProcessHeap(), 0, sizeof(IDirectInputImpl) )))
{ return DIERR_OUTOFMEMORY;
vtable = &ddi8wvt;
res = DI_OK;
}
if (res == DI_OK && !create_hook_thread()) res = DIERR_GENERIC;
if (res == DI_OK)
{
This = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectInputImpl));
This->lpVtbl = vtable; This->lpVtbl = vtable;
This->ref = 1; This->ref = 1;
This->dwVersion = dwVersion; This->dwVersion = dwVersion;
This->evsequence = 1; This->evsequence = 1;
*ppDI = This;
InitializeCriticalSection(&This->crit); InitializeCriticalSection(&This->crit);
This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit"); This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit");
list_init( &This->devices_list ); list_init( &This->devices_list );
/* Add self to the list of the IDirectInputs */
EnterCriticalSection( &dinput_hook_crit );
list_add_head( &direct_input_list, &This->entry );
LeaveCriticalSection( &dinput_hook_crit );
if (!check_hook_thread())
{
IUnknown_Release( (LPDIRECTINPUT7A)This );
return DIERR_GENERIC;
} }
return res;
*ppDI = This;
return DI_OK;
} }
/****************************************************************************** /******************************************************************************
...@@ -266,7 +260,12 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface) ...@@ -266,7 +260,12 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
ref = InterlockedDecrement( &This->ref ); ref = InterlockedDecrement( &This->ref );
if (ref) return ref; if (ref) return ref;
release_hook_thread(); /* Remove self from the list of the IDirectInputs */
EnterCriticalSection( &dinput_hook_crit );
list_remove( &This->entry );
LeaveCriticalSection( &dinput_hook_crit );
check_hook_thread();
This->crit.DebugInfo->Spare[0] = 0; This->crit.DebugInfo->Spare[0] = 0;
DeleteCriticalSection( &This->crit ); DeleteCriticalSection( &This->crit );
...@@ -734,7 +733,6 @@ static LRESULT CALLBACK dinput_hook_WndProc(HWND hWnd, UINT message, WPARAM wPar ...@@ -734,7 +733,6 @@ static LRESULT CALLBACK dinput_hook_WndProc(HWND hWnd, UINT message, WPARAM wPar
} }
static HWND hook_thread_hwnd; static HWND hook_thread_hwnd;
static LONG hook_thread_refcount;
static HANDLE hook_thread; static HANDLE hook_thread;
static const WCHAR classW[]={'H','o','o','k','_','L','L','_','C','L',0}; static const WCHAR classW[]={'H','o','o','k','_','L','L','_','C','L',0};
...@@ -763,7 +761,6 @@ static DWORD WINAPI hook_thread_proc(void *param) ...@@ -763,7 +761,6 @@ static DWORD WINAPI hook_thread_proc(void *param)
return 0; return 0;
} }
static CRITICAL_SECTION dinput_hook_crit;
static CRITICAL_SECTION_DEBUG dinput_critsect_debug = static CRITICAL_SECTION_DEBUG dinput_critsect_debug =
{ {
0, 0, &dinput_hook_crit, 0, 0, &dinput_hook_crit,
...@@ -772,15 +769,12 @@ static CRITICAL_SECTION_DEBUG dinput_critsect_debug = ...@@ -772,15 +769,12 @@ static CRITICAL_SECTION_DEBUG dinput_critsect_debug =
}; };
static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0, 0 }; static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0, 0 };
static BOOL create_hook_thread(void) static BOOL check_hook_thread(void)
{ {
LONG ref;
EnterCriticalSection(&dinput_hook_crit); EnterCriticalSection(&dinput_hook_crit);
ref = ++hook_thread_refcount; TRACE("IDirectInputs left: %d\n", list_count(&direct_input_list));
TRACE("Refcount %d\n", ref); if (!list_empty(&direct_input_list) && !hook_thread)
if (ref == 1)
{ {
DWORD tid; DWORD tid;
HANDLE event; HANDLE event;
...@@ -806,19 +800,7 @@ static BOOL create_hook_thread(void) ...@@ -806,19 +800,7 @@ static BOOL create_hook_thread(void)
} }
CloseHandle(event); CloseHandle(event);
} }
LeaveCriticalSection(&dinput_hook_crit); else if (list_empty(&direct_input_list) && hook_thread)
return hook_thread_hwnd != 0;
}
static void release_hook_thread(void)
{
LONG ref;
EnterCriticalSection(&dinput_hook_crit);
ref = --hook_thread_refcount;
TRACE("Releasing to %d\n", ref);
if (ref == 0)
{ {
HWND hwnd = hook_thread_hwnd; HWND hwnd = hook_thread_hwnd;
hook_thread_hwnd = 0; hook_thread_hwnd = 0;
...@@ -826,8 +808,11 @@ static void release_hook_thread(void) ...@@ -826,8 +808,11 @@ static void release_hook_thread(void)
/* wait for hook thread to exit */ /* wait for hook thread to exit */
WaitForSingleObject(hook_thread, INFINITE); WaitForSingleObject(hook_thread, INFINITE);
CloseHandle(hook_thread); CloseHandle(hook_thread);
hook_thread = NULL;
} }
LeaveCriticalSection(&dinput_hook_crit); LeaveCriticalSection(&dinput_hook_crit);
return hook_thread_hwnd != 0;
} }
HHOOK set_dinput_hook(int hook_id, LPVOID proc) HHOOK set_dinput_hook(int hook_id, LPVOID proc)
......
...@@ -34,6 +34,7 @@ struct IDirectInputImpl ...@@ -34,6 +34,7 @@ struct IDirectInputImpl
LONG ref; LONG ref;
CRITICAL_SECTION crit; CRITICAL_SECTION crit;
struct list entry; /* entry into list of all IDirectInputs */
DWORD evsequence; /* unique sequence number for events */ DWORD evsequence; /* unique sequence number for events */
DWORD dwVersion; /* direct input version number */ DWORD dwVersion; /* direct input version number */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment