From 64bb9ae9a95b953879a8e581cef0e5dbb346704b Mon Sep 17 00:00:00 2001
From: "Admiral H. Curtiss" <pikachu025@gmail.com>
Date: Sun, 27 Nov 2022 03:58:16 +0100
Subject: [PATCH] Correctly call CoUninitialize() on Cubeb helper class
 destruction.

---
 Source/Core/AudioCommon/CubebStream.cpp   |  6 ++++--
 Source/Core/AudioCommon/CubebStream.h     |  1 +
 Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp | 15 +++++++++++++++
 Source/Core/Core/HW/EXI/EXI_DeviceMic.h   |  1 +
 4 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/Source/Core/AudioCommon/CubebStream.cpp b/Source/Core/AudioCommon/CubebStream.cpp
index 5d3d70d9cb..f4566cb57e 100644
--- a/Source/Core/AudioCommon/CubebStream.cpp
+++ b/Source/Core/AudioCommon/CubebStream.cpp
@@ -46,6 +46,7 @@ CubebStream::CubebStream()
     Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
     auto result = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
     m_coinit_success = result == S_OK;
+    m_should_couninit = result == S_OK || result == S_FALSE;
   });
   sync_event.Wait();
 }
@@ -137,11 +138,12 @@ CubebStream::~CubebStream()
     cubeb_stream_stop(m_stream);
     cubeb_stream_destroy(m_stream);
 #ifdef _WIN32
-    if (m_coinit_success)
+    if (m_should_couninit)
     {
-      m_coinit_success = false;
+      m_should_couninit = false;
       CoUninitialize();
     }
+    m_coinit_success = false;
   });
   sync_event.Wait();
 #endif
diff --git a/Source/Core/AudioCommon/CubebStream.h b/Source/Core/AudioCommon/CubebStream.h
index aaf5b82f8f..4b0c0e5eae 100644
--- a/Source/Core/AudioCommon/CubebStream.h
+++ b/Source/Core/AudioCommon/CubebStream.h
@@ -37,6 +37,7 @@ private:
 #ifdef _WIN32
   Common::WorkQueueThread<std::function<void()>> m_work_queue;
   bool m_coinit_success = false;
+  bool m_should_couninit = false;
 #endif
 
   static long DataCallback(cubeb_stream* stream, void* user_data, const void* /*input_buffer*/,
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp
index 408dfe5bc8..1b77be6b02 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp
@@ -221,6 +221,7 @@ CEXIMic::CEXIMic(int index)
     Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
     auto result = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
     m_coinit_success = result == S_OK;
+    m_should_couninit = result == S_OK || result == S_FALSE;
   });
   sync_event.Wait();
 #endif
@@ -231,6 +232,20 @@ CEXIMic::CEXIMic(int index)
 CEXIMic::~CEXIMic()
 {
   StreamTerminate();
+
+#ifdef _WIN32
+  if (m_should_couninit)
+  {
+    Common::Event sync_event;
+    m_work_queue.EmplaceItem([this, &sync_event] {
+      Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
+      m_should_couninit = false;
+      CoUninitialize();
+    });
+    sync_event.Wait();
+  }
+  m_coinit_success = false;
+#endif
 }
 
 bool CEXIMic::IsPresent() const
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMic.h b/Source/Core/Core/HW/EXI/EXI_DeviceMic.h
index 5342190905..a831ef33e5 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceMic.h
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceMic.h
@@ -104,6 +104,7 @@ private:
 #ifdef _WIN32
   Common::WorkQueueThread<std::function<void()>> m_work_queue;
   bool m_coinit_success = false;
+  bool m_should_couninit = false;
 #endif
 };
 }  // namespace ExpansionInterface