From f3f15aef9a2d79252ec061093c25160f29809976 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 30 Jul 2015 19:50:51 +0300 Subject: [PATCH] Support long URLs in w32-shell-execute * 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 | 2 +- src/w32.h | 1 + src/w32fns.c | 28 +++++++++++++++++++++------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/w32.c b/src/w32.c index 8721ed919fc..296729a0e0b 100644 --- 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 diff --git a/src/w32.h b/src/w32.h index e62b93c8e2b..338cb06b193 100644 --- 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); diff --git a/src/w32fns.c b/src/w32fns.c index 499450f4c92..c742ca8534f 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -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) -- 2.39.2