summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2015-07-30 19:50:51 +0300
committerEli Zaretskii <eliz@gnu.org>2015-07-30 19:50:51 +0300
commitf3f15aef9a2d79252ec061093c25160f29809976 (patch)
tree2c309a0e9c153ff79a3f8a265decdd2712e8f003
parent91718f5f451aa99aaf9e4c48ecfc4d5c0535dc79 (diff)
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)
-rw-r--r--src/w32.c2
-rw-r--r--src/w32.h1
-rw-r--r--src/w32fns.c28
3 files changed, 23 insertions, 8 deletions
diff --git a/src/w32.c b/src/w32.c
index 8721ed919f..296729a0e0 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 e62b93c8e2..338cb06b19 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 499450f4c9..c742ca8534 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)