Fix "Open file location" getting stuck after Windows 11 update

We will run InvokeCommand API on separate STA thread and pump messages while waiting for them to finish.

Fixes #2303
Fixes #2321
Fixes #2375
This commit is contained in:
ge0rdi
2026-07-15 14:14:10 +02:00
parent 86e8a24b16
commit 4fd5545485
+47 -1
View File
@@ -24,6 +24,52 @@
#include <propvarutil.h> #include <propvarutil.h>
#include <algorithm> #include <algorithm>
#include <propkey.h> #include <propkey.h>
#include <thread>
// Execute function on a separate STA thread while pumping messages on caller thread.
template <typename TFunc>
static auto ExecuteOnSTAThread(TFunc&& func) -> decltype(func())
{
using ReturnType = decltype(func());
ReturnType result{};
std::thread worker([&func, &result]() mutable {
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
result = func();
CoUninitialize();
});
// Pump messages while waiting for the worker (dialog) to finish
while (true)
{
HANDLE hWorker = worker.native_handle();
if (MsgWaitForMultipleObjects(1, &hWorker, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0)
break;
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
PostQuitMessage((int)msg.wParam);
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
worker.join();
return result;
}
// Wrapper for IContextMenu::InvokeCommand that runs on separate STA thread and pumps messages
static HRESULT InvokeCommandSafe(IContextMenu* pMenu, LPCMINVOKECOMMANDINFO pInfo)
{
return ExecuteOnSTAThread([&]() {
return pMenu->InvokeCommand(pInfo);
});
}
static CString g_RenameText; static CString g_RenameText;
static POINT g_RenamePos; static POINT g_RenamePos;
@@ -3113,7 +3159,7 @@ void CMenuContainer::ActivateItem( int index, TActivateType type, const POINT *p
} }
else else
{ {
HRESULT hr=pInvokeMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info); HRESULT hr=InvokeCommandSafe(pInvokeMenu,(LPCMINVOKECOMMANDINFO)&info);
LOG_MENU(LOG_EXECUTE,L"Invoke command, ptr=%p, res=%d",this,hr); LOG_MENU(LOG_EXECUTE,L"Invoke command, ptr=%p, res=%d",this,hr);
executeSuccess=SUCCEEDED(hr); executeSuccess=SUCCEEDED(hr);
} }