We need to make sure all (important) cleanup is finished when we exit DllMain, otherwise we might already unload krnl386 and deadlock Since we can't have a synchronous DestroyWindow, use an extra message Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52511 Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de> Code flow is like follows: - DOSVM_Exit -> RtlExitUserThread -> LdrShutdownThread - acquire loader lock - send DLL_THREAD_DETACH to imm32 - - calls DestroyWindow on its window - - WM_DESTROY is handled asynchonously! - send DLL_THREAD_DETACH to krnl386.exe - - TASK_ExitTask - - try get win16 lock, is blocked by ime32 meanwhile, at ime32 - handles WM_DESTROY - already have win16 lock from user32 - __wine_ime_wnd_proc (WM_DESTROY) -> imm_couninit_thread -> CoRevokeInitializeSpy - LdrGetProcedureAddress (want CoRevokeInitializeSpy) - try get loader_lock, is blocked Solution is to wait in ime32 DllMain until the cleanup as happened, aka CoRevokeInitializeSpy has finished. -- v5: imm32: Prevent deadlock on unload https://gitlab.winehq.org/wine/wine/-/merge_requests/1456