[PATCH] mmdevapi: Guard MMDevEnum_Create against concurrent initialization.

Rémi Bernon rbernon at codeweavers.com
Wed Jun 2 14:48:19 CDT 2021


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 at 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)
-- 
2.31.0




More information about the wine-devel mailing list