Repository: microsoft/terminal (language: cpp)

Issue:
Dragging and dropping paths to terminal stops at 16 items
### Windows Terminal version

1.15.2713.0

### Windows build number

10.0.22000.0

### Other Software

_No response_

### Steps to reproduce

1. Highlight more than 16 items from an archive (7zip, WinRAR, etc.)
2. Drag and drop highlighted items into terminal

### Expected Behavior

Should write paths equal to the amount of items highlighted

### Actual Behavior

Only writes up to 16 paths




Discussion / hints:
This issue occurs in other UWP or WinAppSDK apps.
It appears that the culprit is that `GetStorageItemsAsync()` from the drag event only returns up to 16 items.

Perhaps this is a bug from WinRT?
Sure _sounds_ like something outside our control. I'd probably file this at https://github.com/microsoft/WindowsAppSDK/issues? They'd at least have a better way to investigate. 
Makes sense, I'll go ahead and file an issue over there.

> Sure _sounds_ like something outside our control.

Despite this being an external issue, is this something that we want to fix? 
I have a workaround solution that appears to work and can open a PR for.
> I have a workaround solution that appears to work and can open a PR for.

Oh well let's try that! It wouldn't be the first workaround for weird platform behavior in our codebase 😉 
Upon looking into a little further, it appears the issue only occurs when dragging and dropping from archives (7zip, WinRAR, and others). It works fine if you do it from the native file explorer though; probably because it doesn't create any temp files.

I can still open a pull request for this edge case unless you're on the side that it isn't worth fixing.
I'd love to see the PR! If it's something we can work around, let's do it. Thanks @jiejasonliu 

Fix patch:
diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp
index a5e4b2bde1f..378c3d89f3c 100644
--- a/src/cascadia/TerminalControl/TermControl.cpp
+++ b/src/cascadia/TerminalControl/TermControl.cpp
@@ -25,6 +25,7 @@ using namespace winrt::Windows::UI::ViewManagement;
 using namespace winrt::Windows::UI::Input;
 using namespace winrt::Windows::System;
 using namespace winrt::Windows::ApplicationModel::DataTransfer;
+using namespace winrt::Windows::Storage::Streams;
 
 // The minimum delay between updates to the scroll bar's values.
 // The updates are throttled to limit power usage.
@@ -2526,16 +2527,57 @@ namespace winrt::Microsoft::Terminal::Control::implementation
 
             if (items.Size() > 0)
             {
-                std::wstring allPaths;
-                for (auto item : items)
+                std::vector<std::wstring> fullPaths;
+
+                // GH#14628: Workaround for GetStorageItemsAsync() only returning 16 items
+                // at most when dragging and dropping from archives (zip, 7z, rar, etc.)
+                if (items.Size() == 16 && e.DataView().Contains(winrt::hstring{ L"FileDrop" }))
                 {
-                    // Join the paths with spaces
-                    if (!allPaths.empty())
+                    auto fileDropData = co_await e.DataView().GetDataAsync(winrt::hstring{ L"FileDrop" });
+                    if (fileDropData != nullptr)
+                    {
+                        auto stream = fileDropData.as<IRandomAccessStream>();
+                        stream.Seek(0);
+
+                        const uint32_t streamSize = gsl::narrow_cast<uint32_t>(stream.Size());
+                        const Buffer buf(streamSize);
+                        const auto buffer = co_await stream.ReadAsync(buf, streamSize, InputStreamOptions::None);
+
+                        const HGLOBAL hGlobal = buffer.data();
+                        const auto count = DragQueryFileW(static_cast<HDROP>(hGlobal), 0xFFFFFFFF, nullptr, 0);
+                        fullPaths.reserve(count);
+
+                        for (unsigned int i = 0; i < count; i++)
+                        {
+                            std::wstring path;
+                            path.resize(wil::max_path_length);
+                            const auto charsCopied = DragQueryFileW(static_cast<HDROP>(hGlobal), i, path.data(), wil::max_path_length);
+
+                            if (charsCopied > 0)
+                            {
+                                path.resize(charsCopied);
+                                fullPaths.emplace_back(std::move(path));
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    fullPaths.reserve(items.Size());
+                    for (const auto& item : items)
                     {
-                        allPaths += L" ";
+                        fullPaths.emplace_back(item.Path());
                     }
+                }
 
-                    std::wstring fullPath{ item.Path() };
+                std::wstring allPathsString;
+                for (auto& fullPath : fullPaths)
+                {
+                    // Join the paths with spaces
+                    if (!allPathsString.empty())
+                    {
+                        allPathsString += L" ";
+                    }
 
                     // Fix path for WSL
                     // In the fullness of time, we should likely plumb this up
@@ -2591,10 +2633,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
                         fullPath += L"\"";
                     }
 
-                    allPaths += fullPath;
+                    allPathsString += fullPath;
                 }
 
-                _core.PasteText(winrt::hstring{ allPaths });
+                _core.PasteText(winrt::hstring{ allPathsString });
             }
         }
     }
diff --git a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj
index 2fed39fb8a4..6209e907f3c 100644
--- a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj
+++ b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj
@@ -88,7 +88,7 @@
 
   <ItemDefinitionGroup>
     <Link>
-      <AdditionalDependencies>dwrite.lib;dxgi.lib;d2d1.lib;d3d11.lib;shcore.lib;winmm.lib;pathcch.lib;propsys.lib;uiautomationcore.lib;Shlwapi.lib;ntdll.lib;user32.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>dwrite.lib;dxgi.lib;d2d1.lib;d3d11.lib;shcore.lib;winmm.lib;pathcch.lib;propsys.lib;uiautomationcore.lib;Shlwapi.lib;ntdll.lib;user32.lib;shell32.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <!--
       ControlLib contains a DllMain that we need to force the use of.
       If you don't have this, then you'll see an error like
diff --git a/src/cascadia/TerminalControl/pch.h b/src/cascadia/TerminalControl/pch.h
index 88d4efe85f0..cbbe86ac0a9 100644
--- a/src/cascadia/TerminalControl/pch.h
+++ b/src/cascadia/TerminalControl/pch.h
@@ -48,6 +48,7 @@
 #include <winrt/Windows.ui.xaml.shapes.h>
 #include <winrt/Windows.ApplicationModel.DataTransfer.h>
 #include <winrt/Windows.Storage.h>
+#include <winrt/Windows.Storage.Streams.h>
 #include <winrt/Windows.UI.Xaml.Shapes.h>
 
 #include <winrt/Microsoft.Terminal.TerminalConnection.h>
@@ -59,6 +60,7 @@
 TRACELOGGING_DECLARE_PROVIDER(g_hTerminalControlProvider);
 #include <telemetry/ProjectTelemetry.h>
 
+#include <shellapi.h>
 #include <ShlObj_core.h>
 #include <WinUser.h>
 


Test patch: