desktop/win32/source/loader.cxx |   42 ++++++++++++++++++++++++++++------------
 1 file changed, 30 insertions(+), 12 deletions(-)

New commits:
commit fdd07300524b278a9f674e5b13a8dabebed5e82f
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Dec 8 18:25:48 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sun Dec 8 16:13:13 2024 +0100

    tdf#138615: canonicalize the paths with wildcards, to process long paths
    
    Now that we discontinued support of Windows 7, PathCchCanonicalizeEx is
    definitely available.
    
    Change-Id: I38b0ff5b6810dfbd6ee6fe84693f71b8392a1808
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178086
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/desktop/win32/source/loader.cxx b/desktop/win32/source/loader.cxx
index 5374c286aa41..3e306dbdd70c 100644
--- a/desktop/win32/source/loader.cxx
+++ b/desktop/win32/source/loader.cxx
@@ -34,6 +34,10 @@
 #include <boost/property_tree/ptree.hpp>
 #include <boost/property_tree/ini_parser.hpp>
 
+// For PathCchCanonicalizeEx
+#include <pathcch.h>
+#pragma comment(lib, "Pathcch.lib")
+
 namespace {
 
 void fail()
@@ -249,6 +253,7 @@ int officeloader_impl(bool bAllowConsole)
 
     std::vector<std::wstring> aEscapedArgs;
     bool bHeadlessMode = false;
+    const size_t nPathSize = 32 * 1024;
     for (std::wstring_view arg : CommandArgs())
     {
         // Check command line arguments for "--headless" parameter. We only 
set the environment
@@ -258,25 +263,38 @@ int officeloader_impl(bool bAllowConsole)
         if (arg == L"-headless" || arg == L"--headless")
             bHeadlessMode = true;
         // check for wildcards in arguments - Windows does not expand 
automatically
-        else if (arg.find_first_of(L"*?") != std::wstring_view::npos)
+        else if (arg.size() < nPathSize && arg.find_first_of(L"*?") != 
std::wstring_view::npos)
         {
+            const wchar_t* path(arg.data());
+            // 1. PathCchCanonicalizeEx only works with backslashes, so 
preprocess to comply
+            wchar_t buf1[nPathSize], buf2[nPathSize];
+            arg.copy(buf1, arg.size());
+            buf1[arg.size()] = '
+            std::replace(buf1, buf1 + arg.size(), '/', '\');
+            // 2. Canonicalize the path: if needed, drop the .. and . 
segments; if long, make sure
+            //    that path has \?\ long path prefix present (required for 
FindFirstFileW)
+            if (SUCCEEDED(
+                    PathCchCanonicalizeEx(buf2, std::size(buf1), buf1, 
PATHCCH_ALLOW_LONG_PATHS)))
+                path = buf2;
+            // 3. Expand the wildcards
             WIN32_FIND_DATAW aFindData;
-            HANDLE h = FindFirstFileW(arg.data(), &aFindData);
+            HANDLE h = FindFirstFileW(path, &aFindData);
             if (h != INVALID_HANDLE_VALUE)
             {
-                const int nPathSize = 32 * 1024;
                 wchar_t drive[3];
-                wchar_t dir[nPathSize];
-                wchar_t path[nPathSize];
-                _wsplitpath_s(arg.data(), drive, std::size(drive), dir, 
std::size(dir), nullptr, 0,
-                              nullptr, 0);
-                do
+                bool splitted = _wsplitpath_s(path, drive, std::size(drive), 
buf1, std::size(buf1),
+                                              nullptr, 0, nullptr, 0) == 0;
+                if (splitted)
                 {
-                    _wmakepath_s(path, std::size(path), drive, dir, 
aFindData.cFileName, nullptr);
-                    aEscapedArgs.push_back(EscapeArg(path));
-                } while (FindNextFileW(h, &aFindData));
+                    do
+                    {
+                        if (_wmakepath_s(buf2, drive, buf1, 
aFindData.cFileName, nullptr) == 0)
+                            aEscapedArgs.push_back(EscapeArg(buf2));
+                    } while (FindNextFileW(h, &aFindData));
+                }
                 FindClose(h);
-                continue;
+                if (splitted)
+                    continue;
             }
         }
 

Reply via email to