Dmitry Timoshkov : winmm: Protect drivers list by a critical section.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Feb 14 07:28:20 CST 2006


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

Author: Dmitry Timoshkov <dmitry at codeweavers.com>
Date:   Tue Feb 14 12:22:57 2006 +0100

winmm: Protect drivers list by a critical section.

---

 dlls/winmm/driver.c |  152 ++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 112 insertions(+), 40 deletions(-)

diff --git a/dlls/winmm/driver.c b/dlls/winmm/driver.c
index f1a5ea0..9e3696f 100644
--- a/dlls/winmm/driver.c
+++ b/dlls/winmm/driver.c
@@ -40,6 +40,15 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(driver);
 
+static CRITICAL_SECTION mmdriver_lock;
+static CRITICAL_SECTION_DEBUG mmdriver_lock_debug =
+{
+    0, 0, &mmdriver_lock,
+    { &mmdriver_lock_debug.ProcessLocksList, &mmdriver_lock_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": mmdriver_lock") }
+};
+static CRITICAL_SECTION mmdriver_lock = { &mmdriver_lock_debug, -1, 0, 0, 0, 0 };
+
 static LPWINE_DRIVER   lpDrvItemList  /* = NULL */;
 static const WCHAR HKLM_BASE[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
                                   'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n',0};
@@ -49,6 +58,24 @@ LPWINE_DRIVER   (*pFnOpenDriver16)(LPCWS
 LRESULT         (*pFnCloseDriver16)(UINT16,LPARAM,LPARAM) /* = NULL */;
 LRESULT         (*pFnSendMessage16)(UINT16,UINT,LPARAM,LPARAM) /* = NULL */;
 
+static void DRIVER_Dump(const char *comment)
+{
+#if 0
+    LPWINE_DRIVER 	lpDrv;
+
+    TRACE("%s\n", comment);
+
+    EnterCriticalSection( &mmdriver_lock );
+
+    for (lpDrv = lpDrvItemList; lpDrv != NULL; lpDrv = lpDrv->lpNextItem)
+    {
+        TRACE("%p, magic %04lx, id %p, next %p\n", lpDrv, lpDrv->dwMagic, (void *)lpDrv->d.d32.dwDriverID, lpDrv->lpNextItem);
+    }
+
+    LeaveCriticalSection( &mmdriver_lock );
+#endif
+}
+
 /**************************************************************************
  *			DRIVER_GetNumberOfModuleRefs		[internal]
  *
@@ -59,6 +86,8 @@ static	unsigned DRIVER_GetNumberOfModule
     LPWINE_DRIVER	lpDrv;
     unsigned		count = 0;
 
+    EnterCriticalSection( &mmdriver_lock );
+
     if (found) *found = NULL;
     for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem)
     {
@@ -68,6 +97,8 @@ static	unsigned DRIVER_GetNumberOfModule
 	    count++;
 	}
     }
+
+    LeaveCriticalSection( &mmdriver_lock );
     return count;
 }
 
@@ -91,6 +122,9 @@ LPWINE_DRIVER	DRIVER_FindFromHDrvr(HDRVR
     }
     __ENDTRY;
 
+    if (d) TRACE("%p -> %p, %p\n", hDrvr, d->d.d32.lpDrvProc, (void *)d->d.d32.dwDriverID);
+    else TRACE("%p -> NULL\n", hDrvr);
+
     return d;
 }
 
@@ -155,6 +189,8 @@ static	BOOL	DRIVER_RemoveFromList(LPWINE
 	}
     }
 
+    EnterCriticalSection( &mmdriver_lock );
+
     if (lpDrv->lpPrevItem)
 	lpDrv->lpPrevItem->lpNextItem = lpDrv->lpNextItem;
     else
@@ -163,6 +199,11 @@ static	BOOL	DRIVER_RemoveFromList(LPWINE
 	lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem;
     /* trash magic number */
     lpDrv->dwMagic ^= 0xa5a5a5a5;
+    lpDrv->d.d32.lpDrvProc = NULL;
+    lpDrv->d.d32.dwDriverID = 0;
+    lpDrv->d.d16.hDriver16 = 0;
+
+    LeaveCriticalSection( &mmdriver_lock );
 
     return TRUE;
 }
@@ -187,8 +228,19 @@ static	BOOL	DRIVER_AddToList(LPWINE_DRIV
 	    /* returned value is not checked */
 	    DRIVER_SendMessage(lpNewDrv, DRV_ENABLE, 0L, 0L);
 	}
+
+	/* Now just open a new instance of a driver on this module */
+	lpNewDrv->d.d32.dwDriverID = DRIVER_SendMessage(lpNewDrv, DRV_OPEN, lParam1, lParam2);
+
+	if (lpNewDrv->d.d32.dwDriverID == 0)
+        {
+	    TRACE("DRV_OPEN failed on driver %p\n", lpNewDrv);
+	    return FALSE;
+	}
     }
 
+    EnterCriticalSection( &mmdriver_lock );
+
     lpNewDrv->lpNextItem = NULL;
     if (lpDrvItemList == NULL) {
 	lpDrvItemList = lpNewDrv;
@@ -202,16 +254,7 @@ static	BOOL	DRIVER_AddToList(LPWINE_DRIV
 	lpNewDrv->lpPrevItem = lpDrv;
     }
 
-    if (!(lpNewDrv->dwFlags & WINE_GDF_16BIT)) {
-	/* Now just open a new instance of a driver on this module */
-	lpNewDrv->d.d32.dwDriverID = DRIVER_SendMessage(lpNewDrv, DRV_OPEN, lParam1, lParam2);
-
-	if (lpNewDrv->d.d32.dwDriverID == 0) {
-	    TRACE("DRV_OPEN failed on driver %p\n", lpNewDrv);
-	    DRIVER_RemoveFromList(lpNewDrv);
-	    return FALSE;
-	}
-    }
+    LeaveCriticalSection( &mmdriver_lock );
     return TRUE;
 }
 
@@ -226,6 +269,8 @@ BOOL	DRIVER_GetLibName(LPCWSTR keyName, 
     static const WCHAR wszSystemIni[] = {'S','Y','S','T','E','M','.','I','N','I',0};
     WCHAR       wsznull = '\0';
 
+    TRACE("registry: %s, %s, %p, %d\n", debugstr_w(keyName), debugstr_w(sectName), buf, sz);
+
     lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, HKLM_BASE, 0, KEY_QUERY_VALUE, &hKey);
     if (lRet == ERROR_SUCCESS) {
 	lRet = RegOpenKeyExW(hKey, sectName, 0, KEY_QUERY_VALUE, &hSecKey);
@@ -237,8 +282,10 @@ BOOL	DRIVER_GetLibName(LPCWSTR keyName, 
         RegCloseKey( hKey );
     }
     if (lRet == ERROR_SUCCESS) return TRUE;
+
     /* default to system.ini if we can't find it in the registry,
      * to support native installations where system.ini is still used */
+    TRACE("system.ini: %s, %s, %p, %d\n", debugstr_w(keyName), debugstr_w(sectName), buf, sz);
     return GetPrivateProfileStringW(sectName, keyName, &wsznull, buf, sz / sizeof(WCHAR), wszSystemIni);
 }
 
@@ -355,12 +402,14 @@ done:
 HDRVR WINAPI OpenDriver(LPCWSTR lpDriverName, LPCWSTR lpSectionName, LPARAM lParam)
 {
     LPWINE_DRIVER	lpDrv = NULL;
-    WCHAR 		libName[128];
+    WCHAR 		libName[MAX_PATH + 1];
     LPCWSTR		lsn = lpSectionName;
 
     TRACE("(%s, %s, 0x%08lx);\n", 
           debugstr_w(lpDriverName), debugstr_w(lpSectionName), lParam);
 
+    DRIVER_Dump("BEFORE:");
+
     if (lsn == NULL) {
         static const WCHAR wszDrivers32[] = {'D','r','i','v','e','r','s','3','2',0};
 	lstrcpynW(libName, lpDriverName, sizeof(libName) / sizeof(WCHAR));
@@ -386,10 +435,12 @@ HDRVR WINAPI OpenDriver(LPCWSTR lpDriver
     }
     TRACE("Failed to open driver %s from system.ini file, section %s\n", 
           debugstr_w(lpDriverName), debugstr_w(lpSectionName));
-    return 0;
 
- the_end:
-    if (lpDrv)	TRACE("=> %p\n", lpDrv);
+the_end:
+    TRACE("=> %p\n", lpDrv);
+
+    DRIVER_Dump("AFTER:");
+
     return (HDRVR)lpDrv;
 }
 
@@ -399,10 +450,13 @@ HDRVR WINAPI OpenDriver(LPCWSTR lpDriver
  */
 LRESULT WINAPI CloseDriver(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2)
 {
+    BOOL ret;
     LPWINE_DRIVER	lpDrv;
 
     TRACE("(%p, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
 
+    DRIVER_Dump("BEFORE:");
+
     if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL)
     {
 	if (lpDrv->dwFlags & WINE_GDF_16BIT)
@@ -411,35 +465,39 @@ LRESULT WINAPI CloseDriver(HDRVR hDrvr, 
                 pFnCloseDriver16(lpDrv->d.d16.hDriver16, lParam1, lParam2);
         }
 	else
-        {
 	    DRIVER_SendMessage(lpDrv, DRV_CLOSE, lParam1, lParam2);
-            lpDrv->d.d32.dwDriverID = 0;
-        }
-	if (DRIVER_RemoveFromList(lpDrv)) {
-            if (!(lpDrv->dwFlags & WINE_GDF_16BIT))
-            {
-                LPWINE_DRIVER       lpDrv0;
 
-                if (lpDrv->dwFlags & WINE_GDF_SESSION)
-                    FIXME("Shouldn't happen (%p)\n", lpDrv);
-                /* if driver has an opened session instance, we have to close it too */
-                if (DRIVER_GetNumberOfModuleRefs(lpDrv->d.d32.hModule, &lpDrv0) == 1 &&
-                    (lpDrv0->dwFlags & WINE_GDF_SESSION))
-                {
-                    DRIVER_SendMessage(lpDrv0, DRV_CLOSE, 0L, 0L);
-                    lpDrv0->d.d32.dwDriverID = 0;
-                    DRIVER_RemoveFromList(lpDrv0);
-                    FreeLibrary(lpDrv0->d.d32.hModule);
-                    HeapFree(GetProcessHeap(), 0, lpDrv0);
-                }
-                FreeLibrary(lpDrv->d.d32.hModule);
+        DRIVER_RemoveFromList(lpDrv);
+
+        if (!(lpDrv->dwFlags & WINE_GDF_16BIT))
+        {
+            LPWINE_DRIVER lpDrv0;
+
+            if (lpDrv->dwFlags & WINE_GDF_SESSION)
+                FIXME("WINE_GDF_SESSION: Shouldn't happen (%p)\n", lpDrv);
+            /* if driver has an opened session instance, we have to close it too */
+            if (DRIVER_GetNumberOfModuleRefs(lpDrv->d.d32.hModule, &lpDrv0) == 1 &&
+                (lpDrv0->dwFlags & WINE_GDF_SESSION))
+            {
+                DRIVER_SendMessage(lpDrv0, DRV_CLOSE, 0, 0);
+                DRIVER_RemoveFromList(lpDrv0);
+                FreeLibrary(lpDrv0->d.d32.hModule);
+                HeapFree(GetProcessHeap(), 0, lpDrv0);
             }
-            HeapFree(GetProcessHeap(), 0, lpDrv);
-            return TRUE;
+            FreeLibrary(lpDrv->d.d32.hModule);
         }
+        HeapFree(GetProcessHeap(), 0, lpDrv);
+        ret = TRUE;
     }
-    WARN("Failed to close driver\n");
-    return FALSE;
+    else
+    {
+        WARN("Failed to close driver\n");
+        ret = FALSE;
+    }
+
+    DRIVER_Dump("AFTER:");
+
+    return ret;
 }
 
 /**************************************************************************
@@ -580,11 +638,25 @@ void    DRIVER_UnloadAll(void)
     LPWINE_DRIVER 	lpNextDrv = NULL;
     unsigned            count = 0;
 
+restart:
+    EnterCriticalSection( &mmdriver_lock );
+
     for (lpDrv = lpDrvItemList; lpDrv != NULL; lpDrv = lpNextDrv)
     {
         lpNextDrv = lpDrv->lpNextItem;
-        CloseDriver((HDRVR)lpDrv, 0, 0);
-        count++;
+
+        /* session instances will be unloaded automatically */
+        if (!(lpDrv->dwFlags & WINE_GDF_SESSION))
+        {
+            LeaveCriticalSection( &mmdriver_lock );
+            CloseDriver((HDRVR)lpDrv, 0, 0);
+            count++;
+            /* restart from the beginning of the list */
+            goto restart;
+        }
     }
+
+    LeaveCriticalSection( &mmdriver_lock );
+
     TRACE("Unloaded %u drivers\n", count);
 }




More information about the wine-cvs mailing list