Module: wine Branch: refs/heads/master Commit: f29d4af34b4ef88838d545788de0d5f107ff6375 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=f29d4af34b4ef88838d54578...
Author: Dmitry Timoshkov dmitry@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); }