+ {
+ parameters = GUI_ENCODE_SYSTEM (parameters);
+ params_w = GUI_SDATA (parameters);
+ }
+ if (STRINGP (operation))
+ {
+ operation = GUI_ENCODE_SYSTEM (operation);
+ ops_w = GUI_SDATA (operation);
+ }
+ result = (intptr_t) ShellExecuteW (NULL, ops_w, doc_w, params_w,
+ GUI_SDATA (current_dir),
+ (INTEGERP (show_flag)
+ ? XINT (show_flag) : SW_SHOWDEFAULT));
+#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
+ CURRENT_DIR, but in its subdirectory, then ShellExecute below
+ will fail to find it. So we need to make the file name is
+ absolute. But DOCUMENT does not have to be a file, it can be a
+ URL, for example. So we make it absolute only if it is an
+ existing file; if it is a file that does not exist, tough. */
+ GCPRO1 (absdoc);
+ absdoc = Fexpand_file_name (document, Qnil);
+ /* Don't call file handlers for file-exists-p, since they might
+ attempt to access the file, which could fail or produce undesired
+ consequences, see bug#16558 for an example. */
+ handler = Ffind_file_name_handler (absdoc, Qfile_exists_p);
+ if (NILP (handler))
+ {
+ Lisp_Object absdoc_encoded = ENCODE_FILE (absdoc);
+
+ if (faccessat (AT_FDCWD, SSDATA (absdoc_encoded), F_OK, AT_EACCESS) == 0)
+ document = absdoc_encoded;
+ else
+ document = ENCODE_FILE (document);
+ }
+ else
+ document = ENCODE_FILE (document);
+ UNGCPRO;
+ if (use_unicode)
+ {
+ wchar_t document_w[MAX_PATH], current_dir_w[MAX_PATH];
+
+ /* Encode filename, 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;
+
+ parameters = ENCODE_SYSTEM (parameters);
+ len = pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
+ SSDATA (parameters), -1, NULL, 0);
+ if (len > 32768)
+ len = 32768;
+ params_w = alloca (len * sizeof (wchar_t));
+ pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
+ SSDATA (parameters), -1, params_w, len);
+ }
+ if (STRINGP (operation))
+ {
+ /* Assume OPERATION is pure ASCII. */
+ const char *s = SSDATA (operation);
+ wchar_t *d;
+ int len = SBYTES (operation) + 1;
+
+ if (len > 32768)
+ len = 32768;
+ d = ops_w = alloca (len * sizeof (wchar_t));
+ while (d < ops_w + len - 1)
+ *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));
+ }
+ else
+ {
+ char document_a[MAX_PATH], current_dir_a[MAX_PATH];
+
+ 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);
+ params_a = SSDATA (parameters);
+ }
+ if (STRINGP (operation))
+ {
+ /* 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));
+ }
+#endif /* !CYGWIN */
+
+ if (result > 32)