From 64fbabd8ceb117e3057ee4eb70cf710c7ecad4f6 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sun, 11 Jul 2021 17:02:04 +0200 Subject: [PATCH] Canonicalize paths during drag-and-drop Otherwise we will get a path from somewhere in `$WINEPREFIX/dosdevices`. --- src/wine-host/xdnd-proxy.cpp | 41 ++++++++++++++++++++++++++++-------- src/wine-host/xdnd-proxy.h | 8 +++---- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/wine-host/xdnd-proxy.cpp b/src/wine-host/xdnd-proxy.cpp index b5418c7e..e84138d1 100644 --- a/src/wine-host/xdnd-proxy.cpp +++ b/src/wine-host/xdnd-proxy.cpp @@ -24,6 +24,8 @@ using namespace std::literals::chrono_literals; +namespace fs = boost::filesystem; + // As defined in `editor.cpp` #define THROW_X11_ERROR(error) \ do { \ @@ -192,9 +194,9 @@ WineXdndProxy::Handle WineXdndProxy::get_handle() { return Handle(instance); } -void WineXdndProxy::begin_xdnd( - const boost::container::small_vector_base& file_paths, - HWND tracker_window) { +void WineXdndProxy::begin_xdnd(const boost::container::small_vector_base< + boost::filesystem::path>& file_paths, + HWND tracker_window) { if (file_paths.empty()) { throw std::runtime_error("Cannot drag-and-drop without any files"); } @@ -223,7 +225,7 @@ void WineXdndProxy::begin_xdnd( ((strlen(file_protocol) - 1 + sizeof('\n')) * file_paths.size())); for (const auto& path : file_paths) { dragged_files_uri_list.append(file_protocol); - dragged_files_uri_list.append(path); + dragged_files_uri_list.append(path.string()); dragged_files_uri_list.push_back('\n'); } @@ -708,7 +710,7 @@ void CALLBACK dnd_winevent_callback(HWINEVENTHOOK /*hWinEventHook*/, enumerator->Release(); // This will contain the normal, Unix-style paths to the files - boost::container::small_vector dragged_files; + boost::container::small_vector dragged_files; for (unsigned int format_idx = 0; format_idx < num_formats; format_idx++) { STGMEDIUM storage{}; if (HRESULT result = tracker_info->dataObject->GetData( @@ -733,15 +735,36 @@ void CALLBACK dnd_winevent_callback(HWINEVENTHOOK /*hWinEventHook*/, DragQueryFileW(drop, file_idx, file_name.data(), file_name.size()); - dragged_files.emplace_back( - wine_get_unix_file_name(file_name.data())); + // 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; case TYMED_FILE: { - dragged_files.emplace_back( - wine_get_unix_file_name(storage.lpszFileName)); + const char* unix_path = + wine_get_unix_file_name(storage.lpszFileName); + 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); + } + } } break; default: { std::cerr << "Unknown drag-and-drop format " diff --git a/src/wine-host/xdnd-proxy.h b/src/wine-host/xdnd-proxy.h index 9c0979d8..b933d41c 100644 --- a/src/wine-host/xdnd-proxy.h +++ b/src/wine-host/xdnd-proxy.h @@ -136,9 +136,9 @@ class WineXdndProxy { * Initiate the XDDN protocol by taking ownership of the `XdndSelection` * selection and setting up the event listeners. */ - void begin_xdnd( - const boost::container::small_vector_base& file_paths, - HWND tracker_window); + void begin_xdnd(const boost::container::small_vector_base< + boost::filesystem::path>& file_paths, + HWND tracker_window); /** * Release ownership of the selection stop listening for X11 events. @@ -236,7 +236,7 @@ class WineXdndProxy { /** * The files that are currently being dragged, stored as in `text/uri-list` - * format (i.e. a list of URIs, separated by line feeds) + * format (i.e. a list of URIs, each ending with a line feed) */ std::string dragged_files_uri_list;