diff --git a/CHANGELOG.md b/CHANGELOG.md index 50d3f41a..6e4e48fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ Versioning](https://semver.org/spec/v2.0.0.html). ### Fixed +- Fixed crashes or freezes when a plugin uses the Windows drag-and-drop system + to transfer arbitrary data. This prevents **Reaktor** from freezing when + editing a patch after upgrading to yabridge 3.4.0. - Fixed the process status detection treating a process as dead when the user doesn't have permissions to access the child process's memory. This fixes a seemingly very rare regression from yabridge 3.4.0 where the Wine plugin host diff --git a/src/wine-host/xdnd-proxy.cpp b/src/wine-host/xdnd-proxy.cpp index c00d6833..e34769d6 100644 --- a/src/wine-host/xdnd-proxy.cpp +++ b/src/wine-host/xdnd-proxy.cpp @@ -802,39 +802,53 @@ void CALLBACK dnd_winevent_callback(HWINEVENTHOOK /*hWinEventHook*/, result == S_OK) { switch (storage.tymed) { case TYMED_HGLOBAL: { - auto drop = static_cast(GlobalLock(storage.hGlobal)); - if (!drop) { - std::cerr << "Failed to lock global memory in " - "drag-and-drop operation" - << std::endl; - continue; - } - - std::array file_name{0}; - const uint32_t num_files = DragQueryFileW( - drop, 0xFFFFFFFF, file_name.data(), file_name.size()); - for (uint32_t file_idx = 0; file_idx < num_files; - file_idx++) { - file_name[0] = 0; - DragQueryFileW(drop, file_idx, file_name.data(), - file_name.size()); - - // Normalize the paths to something a bit more friendly - const char* unix_path = - wine_get_unix_file_name(file_name.data()); - if (unix_path) { - boost::system::error_code err; - const fs::path cannonical_path = - boost::filesystem::canonical(unix_path, err); - if (err) { - dragged_files.emplace_back(unix_path); - } else { - dragged_files.emplace_back(cannonical_path); + switch (supported_formats[format_idx].cfFormat) { + case CF_HDROP: { + auto drop = + static_cast(GlobalLock(storage.hGlobal)); + if (!drop) { + std::cerr << "Failed to lock global memory in " + "drag-and-drop operation" + << std::endl; + continue; } - } - } - GlobalUnlock(storage.hGlobal); + std::array file_name{0}; + const uint32_t num_files = DragQueryFileW( + drop, 0xFFFFFFFF, file_name.data(), + file_name.size()); + for (uint32_t file_idx = 0; file_idx < num_files; + file_idx++) { + file_name[0] = 0; + DragQueryFileW(drop, file_idx, file_name.data(), + file_name.size()); + + // Normalize the paths to something a bit more + // friendly + const char* unix_path = + wine_get_unix_file_name(file_name.data()); + if (unix_path) { + boost::system::error_code err; + const fs::path cannonical_path = + boost::filesystem::canonical(unix_path, + err); + if (err) { + dragged_files.emplace_back(unix_path); + } else { + dragged_files.emplace_back( + cannonical_path); + } + } + } + + GlobalUnlock(storage.hGlobal); + } break; + default: { + std::cerr << "Unknown format in drag-and-drop: " + << supported_formats[format_idx].cfFormat + << std::endl; + } break; + } } break; case TYMED_FILE: { const char* unix_path = @@ -851,8 +865,8 @@ void CALLBACK dnd_winevent_callback(HWINEVENTHOOK /*hWinEventHook*/, } } break; default: { - std::cerr << "Unknown drag-and-drop format " - << storage.tymed << std::endl; + std::cerr << "Unknown drag-and-drop type: " << storage.tymed + << std::endl; } break; }