shell32: Make ShellExecute use native file association databases as fallback path

Erik van Pienbroek erik at vanpienbroek.nl
Thu May 31 16:00:59 CDT 2012


Fixes http://bugs.winehq.org/show_bug.cgi?id=12464
Based on initial work from Jeff Miller

The ShellExecute and related functions currently only search
for known file associations inside the wine prefix. When an
attempt to done to open a file of which there is no registered
file association inside the wine prefix the ShellExecute call
will fail. This change adds a fallback path where an attempt is
done to open a file using the native file association databases
before giving up. On Linux environments the tool 'xdg-open' is
used for this, for Mac OS X environments the tool 'open' is used

Tested successfully on a Fedora 17 environment using the start.exe
command and Outlook 2007 by trying to open a .pdf file (where there
is no file association registered inside the wine prefix)
---
 dlls/shell32/shlexec.c |   35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c
index 77212f0..4b766ff 100644
--- a/dlls/shell32/shlexec.c
+++ b/dlls/shell32/shlexec.c
@@ -31,6 +31,9 @@
 #endif
 #include <ctype.h>
 #include <assert.h>
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
 
 #define COBJMACROS
 
@@ -1911,6 +1914,38 @@ static BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
         strcatW(lpstrTmpFile, lpFile);
         retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
     }
+#if defined(HAVE_FORK) && defined(HAVE_WAITPID)
+    /* Integration with native file association database */
+    else
+    {
+#ifdef __APPLE__
+        static const char * openCmd = "open";
+#else
+        static const char * openCmd = "xdg-open";
+#endif
+
+        pid_t cpid = fork();
+        if (!cpid)
+        {
+	    char * unix_name;
+            LPSTR (*wine_get_unix_file_name_ptr)(LPCWSTR) = NULL;
+
+            wine_get_unix_file_name_ptr = (void*)
+                GetProcAddress(GetModuleHandleA("KERNEL32"),
+                               "wine_get_unix_file_name");
+
+            unix_name = wine_get_unix_file_name_ptr(lpFile);
+            TRACE("running %s\n", unix_name);
+            execlp(openCmd, openCmd, unix_name, (char*) NULL);
+        } else {
+            int status;
+            waitpid(cpid, &status, 0);
+            TRACE("status %x\n", status);
+            if(!WEXITSTATUS(status))
+                retval = 33;
+        }
+    }
+#endif
 
     TRACE("retval %lu\n", retval);
 
-- 
1.7.10.2






More information about the wine-patches mailing list