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

Alexandre Julliard julliard at wine.codeweavers.com
Mon Jul 9 10:24:58 CDT 2007


Module: wine
Branch: master
Commit: fe1f1362b88280724043ff21ab67ee6010773451
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=fe1f1362b88280724043ff21ab67ee6010773451

Author: Vitaliy Margolen <wine-patches at kievinfo.com>
Date:   Fri Jul  6 23:36:18 2007 -0600

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

---

 dlls/dinput/dinput_main.c    |  109 ++++++++++++++++++------------------------
 dlls/dinput/dinput_private.h |    1 +
 2 files changed, 48 insertions(+), 62 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 52be7f3..2399f2c 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -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))
-    {
-        vtable = &ddi7avt;
-        res = DI_OK;
-    }
+    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 (IsEqualGUID(&IID_IDirectInputW,riid) ||
-        IsEqualGUID(&IID_IDirectInput2W,riid) ||
-        IsEqualGUID(&IID_IDirectInput7W,riid))
-    {
-        vtable = &ddi7wvt;
-        res = DI_OK;
-    }
+    if (!(This = HeapAlloc( GetProcessHeap(), 0, sizeof(IDirectInputImpl) )))
+        return DIERR_OUTOFMEMORY;
 
-    if (IsEqualGUID(&IID_IDirectInput8A,riid))
-    {
-        vtable = &ddi8avt;
-        res = DI_OK;
-    }
+    This->lpVtbl      = vtable;
+    This->ref         = 1;
+    This->dwVersion   = dwVersion;
+    This->evsequence  = 1;
 
-    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");
 
-        InitializeCriticalSection(&This->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)
     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)
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index b29f61e..a5b74dc 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -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 */




More information about the wine-cvs mailing list