In cases where MF is already shut down, simply forwarding MFShutdown() to RtwqShutdown() will corrupt the Rtwq lock count if async result objects still exist, because they hold a lock. JR East Train Simulator does this.
From: Conor McCarthy cmccarthy@codeweavers.com
In cases where MF is already shut down, simply forwarding MFShutdown() to RtwqShutdown() will corrupt the Rtwq lock count if async result objects still exist, because they hold a lock. JR East Train Simulator does this. --- dlls/mfplat/main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 4ed607686f1..9b73a5b9ef0 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -70,6 +70,8 @@ struct local_handler IMFActivate *activate; };
+static LONG startup_count; + static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers); @@ -1598,6 +1600,8 @@ HRESULT WINAPI MFStartup(ULONG version, DWORD flags) if (version != MF_VERSION_XP && version != MF_VERSION_WIN7) return MF_E_BAD_STARTUP_VERSION;
+ InterlockedIncrement(&startup_count); + RtwqStartup();
return S_OK; @@ -1610,6 +1614,15 @@ HRESULT WINAPI MFShutdown(void) { TRACE("\n");
+ /* NOTE: if startup_count is zero, calling MFStartup() and MFShutdown() + * simultaneously from different threads is inherently a race condition due + * to the requirement that MFShutdown() have no effect if startup_count is + * zero. No synchronisation is needed here. */ + if (startup_count <= 0) + return S_OK; + + InterlockedDecrement(&startup_count); + RtwqShutdown();
return S_OK;
Is it possible we need to do that in rtworkq instead? It would be best if there was a way to verify which side this belongs to. According to docs mfplat is supposed to initialize winsocks too, so maybe it belongs to both sides.