emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r116824: Extend and improve w32-shell-execute on MS-


From: Eli Zaretskii
Subject: [Emacs-diffs] trunk r116824: Extend and improve w32-shell-execute on MS-Windows.
Date: Fri, 21 Mar 2014 08:51:20 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 116824
revision-id: address@hidden
parent: address@hidden
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Fri 2014-03-21 10:51:02 +0200
message:
  Extend and improve w32-shell-execute on MS-Windows.
  
   src/w32fns.c (Fw32_shell_execute) [!CYGWIN]: Use ShellExecuteEx, to
   support more "verbs".
modified:
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/w32fns.c                   w32fns.c-20091113204419-o5vbwnq5f7feedwu-945
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2014-03-21 07:26:47 +0000
+++ b/src/ChangeLog     2014-03-21 08:51:02 +0000
@@ -1,3 +1,8 @@
+2014-03-21  Eli Zaretskii  <address@hidden>
+
+       * w32fns.c (Fw32_shell_execute) [!CYGWIN]: Use ShellExecuteEx, to
+       support more "verbs".
+
 2014-03-21  Daniel Colascione  <address@hidden>
 
        Always prohibit dumping a dumped Emacs.

=== modified file 'src/w32fns.c'
--- a/src/w32fns.c      2014-03-19 17:43:18 +0000
+++ b/src/w32fns.c      2014-03-21 08:51:02 +0000
@@ -6868,24 +6868,33 @@
                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 @@
   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 @@
                                     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 @@
   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 @@
            *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 @@
          /* 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);
     }
+
+  if (success)
+    return Qt;
+
+  errstr = w32_strerror (0);
+
 #endif /* !CYGWIN */
 
-  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;
-    }
   /* The error string might be encoded in the locale's encoding.  */
   if (!NILP (Vlocale_coding_system))
     {


reply via email to

[Prev in Thread] Current Thread [Next in Thread]