]> git.eshelyaron.com Git - emacs.git/commitdiff
Support long URLs in w32-shell-execute
authorEli Zaretskii <eliz@gnu.org>
Thu, 30 Jul 2015 16:50:51 +0000 (19:50 +0300)
committerEli Zaretskii <eliz@gnu.org>
Thu, 30 Jul 2015 16:50:51 +0000 (19:50 +0300)
* src/w32fns.c (Fw32_shell_execute): Don't use filename_to_utf16
and filename_to_ansi to convert the DOCUMENT argument, as it could
be a URL that is not limited to MAX_PATH characters.  Instead, use
MultiByteToWideChar directly, and allocate heap storage as
required to accommodate the converted string.  Likewise with
non-Unicode operation.  Ensure OPERATION is null-terminated, even
if it is longer than 32K bytes.  (Bug#21158)

src/w32.c
src/w32.h
src/w32fns.c

index 8721ed919fcf085aa92523201e0e4c662e756360..296729a0e0beefc0ed0ab0f65e6ae673f2ce40a2 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1490,7 +1490,7 @@ static int file_name_codepage;
 
 /* Produce a Windows ANSI codepage suitable for encoding file names.
    Return the information about that codepage in CP_INFO.  */
-static int
+int
 codepage_for_filenames (CPINFO *cp_info)
 {
   /* A simple cache to avoid calling GetCPInfo every time we need to
index e62b93c8e2bb2e013e7bf0f75b3ddca9bf5057a6..338cb06b193cf84cd8e6b6bb3d2bbc1d11d54761 100644 (file)
--- a/src/w32.h
+++ b/src/w32.h
@@ -192,6 +192,7 @@ extern int  filename_from_ansi (const char *, char *);
 extern int  filename_to_ansi (const char *, char *);
 extern int  filename_from_utf16 (const wchar_t *, char *);
 extern int  filename_to_utf16 (const char *, wchar_t *);
+extern int  codepage_for_filenames (CPINFO *);
 extern Lisp_Object ansi_encode_filename (Lisp_Object);
 extern int  w32_copy_file (const char *, const char *, int, int, int);
 
index 499450f4c927c7c4c54aa14e6d43c9cdf3d877e2..c742ca8534ffd323e5b20ac37ed8a57850012015 100644 (file)
@@ -7090,6 +7090,8 @@ a ShowWindow flag:
 
   const char file_url_str[] = "file:///";
   const int file_url_len = sizeof (file_url_str) - 1;
+  int doclen;
+
   if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0)
     {
       /* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to
@@ -7144,16 +7146,21 @@ a ShowWindow flag:
   UNGCPRO;
 
   current_dir = ENCODE_FILE (current_dir);
+  /* Cannot use filename_to_utf16/ansi with DOCUMENT, since it could
+     be a URL that is not limited to MAX_PATH chararcters.  */
+  doclen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+                                SSDATA (document), -1, NULL, 0);
+  doc_w = xmalloc (doclen * sizeof (wchar_t));
+  pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+                       SSDATA (document), -1, doc_w, doclen);
   if (use_unicode)
     {
-      wchar_t document_w[MAX_PATH], current_dir_w[MAX_PATH];
+      wchar_t current_dir_w[MAX_PATH];
       SHELLEXECUTEINFOW shexinfo_w;
 
-      /* Encode filename, current directory and parameters, and
-        convert operation to UTF-16.  */
+      /* Encode the current directory and parameters, and convert
+        operation to UTF-16.  */
       filename_to_utf16 (SSDATA (current_dir), current_dir_w);
-      filename_to_utf16 (SSDATA (document), document_w);
-      doc_w = document_w;
       if (STRINGP (parameters))
        {
          int len;
@@ -7166,6 +7173,7 @@ a ShowWindow flag:
          params_w = alloca (len * sizeof (wchar_t));
          pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
                                SSDATA (parameters), -1, params_w, len);
+         params_w[len - 1] = 0;
        }
       if (STRINGP (operation))
        {
@@ -7198,15 +7206,19 @@ a ShowWindow flag:
       shexinfo_w.nShow =
        (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT);
       success = ShellExecuteExW (&shexinfo_w);
+      xfree (doc_w);
     }
   else
     {
       char document_a[MAX_PATH], current_dir_a[MAX_PATH];
       SHELLEXECUTEINFOA shexinfo_a;
+      int codepage = codepage_for_filenames (NULL);
+      int ldoc_a = pWideCharToMultiByte (codepage, 0, doc_w, -1, NULL, 0,
+                                        NULL, NULL);
 
+      doc_a = xmalloc (ldoc_a);
+      pWideCharToMultiByte (codepage, 0, doc_w, -1, doc_a, ldoc_a, NULL, NULL);
       filename_to_ansi (SSDATA (current_dir), current_dir_a);
-      filename_to_ansi (SSDATA (document), document_a);
-      doc_a = document_a;
       if (STRINGP (parameters))
        {
          parameters = ENCODE_SYSTEM (parameters);
@@ -7229,6 +7241,8 @@ a ShowWindow flag:
       shexinfo_a.nShow =
        (INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT);
       success = ShellExecuteExA (&shexinfo_a);
+      xfree (doc_w);
+      xfree (doc_a);
     }
 
   if (success)