dinput: Keep a list of all IDirectInput objects and check it instead of refcount to create/destroy hook thread.

This commit is contained in:
Vitaliy Margolen 2007-07-06 23:36:18 -06:00 committed by Alexandre Julliard
parent 448dde9be8
commit fe1f1362b8
2 changed files with 52 additions and 66 deletions

View File

@ -77,8 +77,9 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv)
return TRUE;
}
static BOOL create_hook_thread(void);
static void release_hook_thread(void);
static BOOL check_hook_thread(void);
static CRITICAL_SECTION dinput_hook_crit;
static struct list direct_input_list = LIST_INIT( direct_input_list );
/******************************************************************************
* DirectInputCreateEx (DINPUT.@)
@ -88,55 +89,48 @@ HRESULT WINAPI DirectInputCreateEx(
LPUNKNOWN punkOuter)
{
IDirectInputImpl* This;
HRESULT res = DIERR_OLDDIRECTINPUTVERSION;
LPCVOID vtable = NULL;
TRACE("(%p,%04x,%s,%p,%p)\n", hinst, dwVersion, debugstr_guid(riid), ppDI, punkOuter);
if (IsEqualGUID(&IID_IDirectInputA,riid) ||
IsEqualGUID(&IID_IDirectInput2A,riid) ||
IsEqualGUID(&IID_IDirectInput7A,riid))
if (IsEqualGUID( &IID_IDirectInputA, riid ) ||
IsEqualGUID( &IID_IDirectInput2A, riid ) ||
IsEqualGUID( &IID_IDirectInput7A, riid )) vtable = &ddi7avt;
else if (IsEqualGUID( &IID_IDirectInputW, riid ) ||
IsEqualGUID( &IID_IDirectInput2W, riid ) ||
IsEqualGUID( &IID_IDirectInput7W, riid )) vtable = &ddi7wvt;
else if (IsEqualGUID( &IID_IDirectInput8A, riid )) vtable = &ddi8avt;
else if (IsEqualGUID( &IID_IDirectInput8W, riid )) vtable = &ddi8wvt;
else
return DIERR_OLDDIRECTINPUTVERSION;
if (!(This = HeapAlloc( GetProcessHeap(), 0, sizeof(IDirectInputImpl) )))
return DIERR_OUTOFMEMORY;
This->lpVtbl = vtable;
This->ref = 1;
This->dwVersion = dwVersion;
This->evsequence = 1;
InitializeCriticalSection(&This->crit);
This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit");
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())
{
vtable = &ddi7avt;
res = DI_OK;
IUnknown_Release( (LPDIRECTINPUT7A)This );
return DIERR_GENERIC;
}
if (IsEqualGUID(&IID_IDirectInputW,riid) ||
IsEqualGUID(&IID_IDirectInput2W,riid) ||
IsEqualGUID(&IID_IDirectInput7W,riid))
{
vtable = &ddi7wvt;
res = DI_OK;
}
if (IsEqualGUID(&IID_IDirectInput8A,riid))
{
vtable = &ddi8avt;
res = DI_OK;
}
if (IsEqualGUID(&IID_IDirectInput8W,riid))
{
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->ref = 1;
This->dwVersion = dwVersion;
This->evsequence = 1;
*ppDI = This;
InitializeCriticalSection(&This->crit);
This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit");
list_init( &This->devices_list );
}
return res;
*ppDI = This;
return DI_OK;
}
/******************************************************************************
@ -266,7 +260,12 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
ref = InterlockedDecrement( &This->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;
DeleteCriticalSection( &This->crit );
@ -734,7 +733,6 @@ static LRESULT CALLBACK dinput_hook_WndProc(HWND hWnd, UINT message, WPARAM wPar
}
static HWND hook_thread_hwnd;
static LONG hook_thread_refcount;
static HANDLE hook_thread;
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)
return 0;
}
static CRITICAL_SECTION dinput_hook_crit;
static CRITICAL_SECTION_DEBUG dinput_critsect_debug =
{
0, 0, &dinput_hook_crit,
@ -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 BOOL create_hook_thread(void)
static BOOL check_hook_thread(void)
{
LONG ref;
EnterCriticalSection(&dinput_hook_crit);
ref = ++hook_thread_refcount;
TRACE("Refcount %d\n", ref);
if (ref == 1)
TRACE("IDirectInputs left: %d\n", list_count(&direct_input_list));
if (!list_empty(&direct_input_list) && !hook_thread)
{
DWORD tid;
HANDLE event;
@ -806,19 +800,7 @@ static BOOL create_hook_thread(void)
}
CloseHandle(event);
}
LeaveCriticalSection(&dinput_hook_crit);
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)
else if (list_empty(&direct_input_list) && hook_thread)
{
HWND hwnd = hook_thread_hwnd;
hook_thread_hwnd = 0;
@ -826,8 +808,11 @@ static void release_hook_thread(void)
/* wait for hook thread to exit */
WaitForSingleObject(hook_thread, INFINITE);
CloseHandle(hook_thread);
hook_thread = NULL;
}
LeaveCriticalSection(&dinput_hook_crit);
return hook_thread_hwnd != 0;
}
HHOOK set_dinput_hook(int hook_id, LPVOID proc)

View File

@ -34,6 +34,7 @@ struct IDirectInputImpl
LONG ref;
CRITICAL_SECTION crit;
struct list entry; /* entry into list of all IDirectInputs */
DWORD evsequence; /* unique sequence number for events */
DWORD dwVersion; /* direct input version number */