Commit 6d731d41 authored by Eli Zaretskii's avatar Eli Zaretskii
Browse files

Extend and improve w32-shell-execute on MS-Windows.

 src/w32fns.c (Fw32_shell_execute) [!CYGWIN]: Use ShellExecuteEx, to
 support more "verbs".
parent f58269c4
2014-03-21 Eli Zaretskii <eliz@gnu.org>
* w32fns.c (Fw32_shell_execute) [!CYGWIN]: Use ShellExecuteEx, to
support more "verbs".
2014-03-21 Daniel Colascione <dancol@dancol.org>
Always prohibit dumping a dumped Emacs.
......
......@@ -6868,24 +6868,33 @@ handler application, but typically it is one of the following common
specified DOCUMENT.
\"find\" - initiate search starting from DOCUMENT, which must specify
a directory.
\"delete\" - move DOCUMENT, a file or a directory, to Recycle Bin.
\"copy\" - copy DOCUMENT, which must be a file or a directory, into
the clipboard.
\"cut\" - move DOCUMENT, a file or a directory, into the clipboard.
\"paste\" - paste the file whose name is in the clipboard into DOCUMENT,
which must be a directory.
\"pastelink\"
- create a shortcut in DOCUMENT (which must be a directory)
the file or directory whose name is in the clipboard.
\"runas\" - run DOCUMENT, which must be an excutable file, with
elevated privileges (a.k.a. \"as Administrator\").
\"properties\"
- open the the property sheet dialog for DOCUMENT; works
for *.lnk desktop shortcuts, and little or nothing else.
- open the the property sheet dialog for DOCUMENT.
nil - invoke the default OPERATION, or \"open\" if default is
not defined or unavailable.
DOCUMENT is typically the name of a document file or a URL, but can
also be an executable program to run, or a directory to open in the
Windows Explorer. If it is a file, it must be a local one; this
function does not support remote file names.
Windows Explorer. If it is a file or a directory, it must be a local
one; this function does not support remote file names.
If DOCUMENT is an executable program, the optional third arg PARAMETERS
can be a string containing command line parameters that will be passed
to the program. Some values of OPERATION also require parameters (e.g.,
\"printto\" requires the printer address). Otherwise, PARAMETERS should
be nil or unspecified.
can be a string containing command line parameters, separated by blanks,
that will be passed to the program. Some values of OPERATION also require
parameters (e.g., \"printto\" requires the printer address). Otherwise,
PARAMETERS should be nil or unspecified. Note that double quote characters
in PARAMETERS must each be enclosed in 2 additional quotes, as in \"\"\".
Optional fourth argument SHOW-FLAG can be used to control how the
application will be displayed when it is invoked. If SHOW-FLAG is nil
......@@ -6908,6 +6917,7 @@ a ShowWindow flag:
int use_unicode = w32_unicode_filenames;
char *doc_a = NULL, *params_a = NULL, *ops_a = NULL;
Lisp_Object absdoc, handler;
BOOL success;
struct gcpro gcpro1;
#endif
......@@ -6935,7 +6945,48 @@ a ShowWindow flag:
GUI_SDATA (current_dir),
(INTEGERP (show_flag)
? XINT (show_flag) : SW_SHOWDEFAULT));
if (result > 32)
return Qt;
switch (result)
{
case SE_ERR_ACCESSDENIED:
errstr = w32_strerror (ERROR_ACCESS_DENIED);
break;
case SE_ERR_ASSOCINCOMPLETE:
case SE_ERR_NOASSOC:
errstr = w32_strerror (ERROR_NO_ASSOCIATION);
break;
case SE_ERR_DDEBUSY:
case SE_ERR_DDEFAIL:
errstr = w32_strerror (ERROR_DDE_FAIL);
break;
case SE_ERR_DDETIMEOUT:
errstr = w32_strerror (ERROR_TIMEOUT);
break;
case SE_ERR_DLLNOTFOUND:
errstr = w32_strerror (ERROR_DLL_NOT_FOUND);
break;
case SE_ERR_FNF:
errstr = w32_strerror (ERROR_FILE_NOT_FOUND);
break;
case SE_ERR_OOM:
errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY);
break;
case SE_ERR_PNF:
errstr = w32_strerror (ERROR_PATH_NOT_FOUND);
break;
case SE_ERR_SHARE:
errstr = w32_strerror (ERROR_SHARING_VIOLATION);
break;
default:
errstr = w32_strerror (0);
break;
}
#else /* !CYGWIN */
current_dir = ENCODE_FILE (current_dir);
/* We have a situation here. If DOCUMENT is a relative file name,
but its name includes leading directories, i.e. it lives not in
......@@ -6965,6 +7016,7 @@ a ShowWindow flag:
if (use_unicode)
{
wchar_t document_w[MAX_PATH], current_dir_w[MAX_PATH];
SHELLEXECUTEINFOW shexinfo_w;
/* Encode filename, current directory and parameters, and
convert operation to UTF-16. */
......@@ -6998,14 +7050,28 @@ a ShowWindow flag:
*d++ = *s++;
*d = 0;
}
result = (intptr_t) ShellExecuteW (NULL, ops_w, doc_w, params_w,
current_dir_w,
(INTEGERP (show_flag)
? XINT (show_flag) : SW_SHOWDEFAULT));
/* Using ShellExecuteEx and setting the SEE_MASK_INVOKEIDLIST
flag succeeds with more OPERATIONs (a.k.a. "verbs"), as it is
able to invoke verbs from shortcut menu extensions, not just
static verbs listed in the Registry. */
memset (&shexinfo_w, 0, sizeof (shexinfo_w));
shexinfo_w.cbSize = sizeof (shexinfo_w);
shexinfo_w.fMask =
SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
shexinfo_w.hwnd = NULL;
shexinfo_w.lpVerb = ops_w;
shexinfo_w.lpFile = doc_w;
shexinfo_w.lpParameters = params_w;
shexinfo_w.lpDirectory = current_dir_w;
shexinfo_w.nShow =
(INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT);
success = ShellExecuteExW (&shexinfo_w);
}
else
{
char document_a[MAX_PATH], current_dir_a[MAX_PATH];
SHELLEXECUTEINFOA shexinfo_a;
filename_to_ansi (SSDATA (current_dir), current_dir_a);
filename_to_ansi (SSDATA (document), document_a);
......@@ -7020,51 +7086,27 @@ a ShowWindow flag:
/* Assume OPERATION is pure ASCII. */
ops_a = SSDATA (operation);
}
result = (intptr_t) ShellExecuteA (NULL, ops_a, doc_a, params_a,
current_dir_a,
(INTEGERP (show_flag)
? XINT (show_flag) : SW_SHOWDEFAULT));
memset (&shexinfo_a, 0, sizeof (shexinfo_a));
shexinfo_a.cbSize = sizeof (shexinfo_a);
shexinfo_a.fMask =
SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
shexinfo_a.hwnd = NULL;
shexinfo_a.lpVerb = ops_a;
shexinfo_a.lpFile = doc_a;
shexinfo_a.lpParameters = params_a;
shexinfo_a.lpDirectory = current_dir_a;
shexinfo_a.nShow =
(INTEGERP (show_flag) ? XINT (show_flag) : SW_SHOWDEFAULT);
success = ShellExecuteExA (&shexinfo_a);
}
#endif /* !CYGWIN */
if (result > 32)
if (success)
return Qt;
switch (result)
{
case SE_ERR_ACCESSDENIED:
errstr = w32_strerror (ERROR_ACCESS_DENIED);
break;
case SE_ERR_ASSOCINCOMPLETE:
case SE_ERR_NOASSOC:
errstr = w32_strerror (ERROR_NO_ASSOCIATION);
break;
case SE_ERR_DDEBUSY:
case SE_ERR_DDEFAIL:
errstr = w32_strerror (ERROR_DDE_FAIL);
break;
case SE_ERR_DDETIMEOUT:
errstr = w32_strerror (ERROR_TIMEOUT);
break;
case SE_ERR_DLLNOTFOUND:
errstr = w32_strerror (ERROR_DLL_NOT_FOUND);
break;
case SE_ERR_FNF:
errstr = w32_strerror (ERROR_FILE_NOT_FOUND);
break;
case SE_ERR_OOM:
errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY);
break;
case SE_ERR_PNF:
errstr = w32_strerror (ERROR_PATH_NOT_FOUND);
break;
case SE_ERR_SHARE:
errstr = w32_strerror (ERROR_SHARING_VIOLATION);
break;
default:
errstr = w32_strerror (0);
break;
}
errstr = w32_strerror (0);
#endif /* !CYGWIN */
/* The error string might be encoded in the locale's encoding. */
if (!NILP (Vlocale_coding_system))
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment