When the MMDeviceEnumerator class is created by two different threads at the same time, there may be a race condition where one of the thread starts using it while the other is still enumerating audio devices.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mmdevapi/devenum.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c index fc33cac17ec..6528cfc0288 100644 --- a/dlls/mmdevapi/devenum.c +++ b/dlls/mmdevapi/devenum.c @@ -858,16 +858,29 @@ static const IMMDeviceCollectionVtbl MMDevColVtbl = MMDevCol_Item };
+static CRITICAL_SECTION devenum_init_cs; +static CRITICAL_SECTION_DEBUG devenum_init_cs_debug = +{ + 0, 0, &devenum_init_cs, + { &devenum_init_cs_debug.ProcessLocksList, &devenum_init_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": devenum_init_cs") } +}; +static CRITICAL_SECTION devenum_init_cs = { &devenum_init_cs_debug, -1, 0, 0, 0, 0 }; + HRESULT MMDevEnum_Create(REFIID riid, void **ppv) { - MMDevEnumImpl *This = MMDevEnumerator; + MMDevEnumImpl *This;
- if (!This) + EnterCriticalSection(&devenum_init_cs); + if (!(This = MMDevEnumerator)) { This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); *ppv = NULL; if (!This) + { + LeaveCriticalSection(&devenum_init_cs); return E_OUTOFMEMORY; + } This->ref = 1; This->IMMDeviceEnumerator_iface.lpVtbl = &MMDevEnumVtbl; MMDevEnumerator = This; @@ -876,6 +889,8 @@ HRESULT MMDevEnum_Create(REFIID riid, void **ppv) load_driver_devices(eRender); load_driver_devices(eCapture); } + LeaveCriticalSection(&devenum_init_cs); + return IMMDeviceEnumerator_QueryInterface(&This->IMMDeviceEnumerator_iface, riid, ppv); }
@@ -886,8 +901,11 @@ void MMDevEnum_Free(void) RegCloseKey(key_render); RegCloseKey(key_capture); key_render = key_capture = NULL; + + EnterCriticalSection(&devenum_init_cs); HeapFree(GetProcessHeap(), 0, MMDevEnumerator); MMDevEnumerator = NULL; + LeaveCriticalSection(&devenum_init_cs); }
static HRESULT WINAPI MMDevEnum_QueryInterface(IMMDeviceEnumerator *iface, REFIID riid, void **ppv)