Subject: Re: bug#19141: Emacs 24.4: ShellExecute fails in one case under Windows 7
From: Eli Zaretskii <[email-masked]>
To: AW <[email-masked]>, Bastien Guerry <[email-masked]>
Cc: [email-masked]
Date: Tue, 25 Nov 2014 19:12:25 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

Adding Bastien to the addressees, as this is at least somewhat related
to Org and its maintenance procedures.

> From: AW <[email-masked]>
> Date: Fri, 21 Nov 2014 12:30:10 +0100
> 
> What works:
> 
> [[fuu:baz.pdf]] - a link to a local file, which has to be opened in a pdf
> viewer, using an abbrevation for the path.
> 
> [[faa:baz.pdf]] -- a link to a file on the server (SBS 2011), using an
> abbrevation for the path.
> 
> [[file://SBS2011/Emacs/baz.tex]] -- a link to a file on the server, using
> a share name, but no abbrevation for the path.
> 
> [[foo:baz.tex]] -- a link to a file on the server, using an abbrevation
> for the share name and the path, but the file will be opened in Emacs.
> 
> 
> WHAT DOESN'T WORK:
> 
> [[foo:baz.pdf]] -- a link to a file on the server, using an abbrevation
> for the share name and the path, but the file will be opened in a PDF
> viewer.
> 
> [[foo:baz.html]] -- same case, but html file, which should be opened with
> firefox.

Actually, in my testing "file://SBS2011/Emacs/baz.tex" didn't work,
either.  (I tried with a .html file, perhaps that made the difference
for some reason.  E.g., perhaps *.tex files are served by Emacs in
your setup, or anyway by some program whose invocation doesn't go
through w32-shell-execute.)

> If I put the cursor on one of the links below the line "WHAT DOESN'T
> WORK" and try to open it (C-c C-l), I expect that Emacs opens the file
> with -- depending on the file type -- a pdf viewer or a browser.
> 
> But I get an error message, see below ("ShellExecute failed:...") => file
> can not be found.
> 
> This used to work with Emacs 24.3. The share //SBS2011/Emacs and
> U:/Emacs are the same folder on the server. 
> 
> tl;dr: ShellExecute fails, if
> 
> 1. the path uses an abbrevation for the file name +
> 2. the abbrevation contains a share name          +
> 3. the file has to be opened with an external software
> 
> This used to work under Emacs 24.3

The real reason is much simpler: ShellExecute fails if the file name
it receives is in UNC form and uses forward slashes, as in
//SBS2011/Emacs (as opposed to \\SBS2011\Emacs).

This fundamental problem is not new, it existed also in Emacs 24.3.  I
see in Org's git repository and emacs-orgmode mailing list that this
problem was discovered and reported 6.5 years ago, see

  http://lists.gnu.org/archive/html/emacs-orgmode/2008-05/msg00168.html

Unfortunately, instead of filing a bug against Emacs about this
problem, the Org maintainer preferred to paper over it, by running the
link's file name through convert-standard-filename, which on Windows
just _happens_ to mirror all forward slashes to backslashes.  But that
is NEVER the right solution, because every Emacs primitive that deals
with file names will generally call expand-file-name internally, which
will convert backslashes back to forward slashes.  It just _happened_
that w32-shell-execute didn't do that, until Emacs 24.4 (where a call
to expand-file-name was introduced to solve an unrelated problem with
ShellExecute).

So this problem lay dormant for more than 6 years, until now, because
application code relied on internal implementation details of a
certain Emacs primitive.

Please don't do that!  I think it's a no-brainer that problems in
Emacs primitives should be reported and solved in Emacs, not worked
around in application code.

In addition, almost any use of convert-standard-filename is wrong,
with a single exception: when a file name defined by Emacs sources
might be invalid on some filesystem.  This is what "standard" in the
function's name means.  Any other use of this function should
immediately cause alarms to go off, as it usually means some real
underlying problem is being papered over.

Anyway, I fixed this problem in 73cad91 on the emacs-24 branch.  If
the OP can rebuild Emacs, the patch is below.  Please remove the calls
to convert-standard-filename from org.el:org-open-file, as it should
no longer be needed with the real problem fixed.

(Btw, the Org ChangeLog does not mention the addition of calls to
convert-standard-filename, for some reason, and neither does the
Org's Git commit log for the corresponding commit.)

I'm closing this bug.  Thanks for reporting it, and for the easy to
follow reproduction recipe.

--- src/w32fns.c~0	2014-11-19 07:33:11 +0200
+++ src/w32fns.c	2014-11-25 17:38:23 +0200
@@ -7019,7 +7019,14 @@ a ShowWindow flag:
       Lisp_Object absdoc_encoded = ENCODE_FILE (absdoc);
 
       if (faccessat (AT_FDCWD, SSDATA (absdoc_encoded), F_OK, AT_EACCESS) == 0)
-	document = absdoc_encoded;
+	{
+	  /* ShellExecute fails if DOCUMENT is a UNC with forward
+	     slashes (expand-file-name above converts all backslashes
+	     to forward slashes).  Now that we know DOCUMENT is a
+	     file, we can mirror all forward slashes into backslashes.  */
+	  unixtodos_filename (SSDATA (absdoc_encoded));
+	  document = absdoc_encoded;
+	}
       else
 	document = ENCODE_FILE (document);
     }