start.exe: Add /Unix switch for native file managers.
authorVincent Povirk <madewokherd+d41d@gmail.com>
Sun, 13 Apr 2008 00:30:42 +0000 (20:30 -0400)
committerAlexandre Julliard <julliard@winehq.org>
Thu, 17 Apr 2008 10:35:31 +0000 (12:35 +0200)
programs/start/En.rc
programs/start/resources.h
programs/start/start.c

index 3817a59677eee78e29c3165f0d05eeb8e76f4944..212046c6b2c6aa1d88f77d3e7d81275097dc2e45 100644 (file)
@@ -33,6 +33,7 @@ Options: \n\
 /MAX[imized] Start the program maximized. \n\
 /R[estored]  Start the program normally (neither minimized nor maximized). \n\
 /W[ait]      Wait for started program to finish, then exit with its exit code. \n\
+/Unix        Use a Unix filename and start the file like windows explorer. \n\
 /L           Show end-user license. \n\
  \n\
 start.exe version 0.2 Copyright (C) 2003, Dan Kegel \n\
@@ -59,5 +60,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. \n\
 See the COPYING.LIB file for license information. \n\
 "
 
-STRING_EXECFAIL "Application could not be started, or no application associated with the specified file.\nShellExecuteEx failed"
+STRING_EXECFAIL, "Application could not be started, or no application associated with the specified file.\nShellExecuteEx failed"
+
+STRING_UNIXFAIL "Could not translate the specified Unix filename to a DOS filename."
 }
index fb4fff8832c379e97512622d63b6e6e30780703b..f5abd31302a23a9d45d809adeba3a1d508a93efd 100644 (file)
@@ -21,3 +21,4 @@
 #define STRING_USAGE 101
 #define STRING_LICENSE 102
 #define STRING_EXECFAIL 103
+#define STRING_UNIXFAIL 104
index 58748c8ba375ad4aaaef165f96937760a4e20648..c7a4ba438fc85baf07109a8e3e44165ca08e7ca2 100644 (file)
@@ -151,13 +151,37 @@ static WCHAR *build_args( int argc, WCHAR **argvW )
        return ret;
 }
 
+static WCHAR *get_parent_dir(WCHAR* path)
+{
+       WCHAR *last_slash;
+       WCHAR *result;
+       int len;
+
+       last_slash = strrchrW( path, '\\' );
+       if (last_slash == NULL)
+               len = 1;
+       else
+               len = last_slash - path + 1;
+
+       result = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+       CopyMemory(result, path, (len-1)*sizeof(WCHAR));
+       result[len-1] = '\0';
+
+       return result;
+}
+
 int wmain (int argc, WCHAR *argv[])
 {
        SHELLEXECUTEINFOW sei;
        WCHAR *args = NULL;
        int i;
+       int unix_mode = 0;
+       WCHAR *dos_filename = NULL;
+       WCHAR *parent_directory = NULL;
+       DWORD binary_type;
 
        static const WCHAR openW[] = { 'o', 'p', 'e', 'n', 0 };
+       static const WCHAR unixW[] = { 'u', 'n', 'i', 'x', 0 };
 
        memset(&sei, 0, sizeof(sei));
        sei.cbSize = sizeof(sei);
@@ -178,6 +202,10 @@ int wmain (int argc, WCHAR *argv[])
                if (argv[i][0] != '/')
                        break;
 
+               /* Unix paths can start with / so we have to assume anything following /U is not a flag */
+               if (unix_mode)
+                       break;
+
                /* Handle all options in this word */
                for (ci=0; argv[i][ci]; ) {
                        /* Skip slash */
@@ -198,6 +226,15 @@ int wmain (int argc, WCHAR *argv[])
                        case 'R':
                                /* sei.nShow = SW_SHOWNORMAL; */
                                break;
+                       case 'u':
+                       case 'U':
+                               if (strncmpiW(&argv[i][ci], unixW, 4) == 0)
+                                       unix_mode = 1;
+                               else {
+                                       WINE_ERR("Option '%s' not recognized\n", wine_dbgstr_w( argv[i]+ci-1));
+                                       usage();
+                               }
+                               break;
                        case 'w':
                        case 'W':
                                sei.fMask |= SEE_MASK_NOCLOSEPROCESS;
@@ -220,10 +257,68 @@ int wmain (int argc, WCHAR *argv[])
        args = build_args( argc - i, &argv[i] );
        sei.lpParameters = args;
 
-       if (!ShellExecuteExW(&sei))
+       if (unix_mode) {
+               LPWSTR (*wine_get_dos_file_name_ptr)(LPCSTR);
+               char* multibyte_unixpath;
+               int multibyte_unixpath_len;
+
+               wine_get_dos_file_name_ptr = (void*)GetProcAddress(GetModuleHandle("KERNEL32"), "wine_get_dos_file_name");
+
+               if (!wine_get_dos_file_name_ptr)
+                       fatal_string(STRING_UNIXFAIL);
+
+               multibyte_unixpath_len = WideCharToMultiByte(CP_UNIXCP, 0, sei.lpFile, -1, NULL, 0, NULL, NULL);
+               multibyte_unixpath = HeapAlloc(GetProcessHeap(), 0, multibyte_unixpath_len);
+
+               WideCharToMultiByte(CP_UNIXCP, 0, sei.lpFile, -1, multibyte_unixpath, multibyte_unixpath_len, NULL, NULL);
+
+               dos_filename = wine_get_dos_file_name_ptr(multibyte_unixpath);
+
+               HeapFree(GetProcessHeap(), 0, multibyte_unixpath);
+
+               if (!dos_filename)
+                       fatal_string(STRING_UNIXFAIL);
+
+               sei.lpFile = dos_filename;
+               sei.lpDirectory = parent_directory = get_parent_dir(dos_filename);
+
+                if (GetBinaryTypeW(sei.lpFile, &binary_type)) {
+                    WCHAR *commandline;
+                    STARTUPINFOW startup_info;
+                    PROCESS_INFORMATION process_information;
+                    static WCHAR commandlineformat[] = {'"','%','s','"','%','s',0};
+
+                    /* explorer on windows always quotes the filename when running a binary on windows (see bug 5224) so we have to use CreateProcessW in this case */
+
+                    commandline = HeapAlloc(GetProcessHeap(), 0, (strlenW(sei.lpFile)+3+strlenW(sei.lpParameters))*sizeof(WCHAR));
+                    sprintfW(commandline, commandlineformat, sei.lpFile, sei.lpParameters);
+
+                    ZeroMemory(&startup_info, sizeof(startup_info));
+                    startup_info.cb = sizeof(startup_info);
+
+                    if (!CreateProcessW(
+                            NULL, /* lpApplicationName */
+                            commandline, /* lpCommandLine */
+                            NULL, /* lpProcessAttributes */
+                            NULL, /* lpThreadAttributes */
+                            FALSE, /* bInheritHandles */
+                            CREATE_NEW_CONSOLE, /* dwCreationFlags */
+                            NULL, /* lpEnvironment */
+                            sei.lpDirectory, /* lpCurrentDirectory */
+                            &startup_info, /* lpStartupInfo */
+                            &process_information /* lpProcessInformation */ ))
+                    {
+                       fatal_string_error(STRING_EXECFAIL, GetLastError());
+                    }
+                    sei.hProcess = process_information.hProcess;
+                }
+       }
+       else if (!ShellExecuteExW(&sei))
                fatal_string_error(STRING_EXECFAIL, GetLastError());
 
        HeapFree( GetProcessHeap(), 0, args );
+       HeapFree( GetProcessHeap(), 0, dos_filename );
+       HeapFree( GetProcessHeap(), 0, parent_directory );
 
        if (sei.fMask & SEE_MASK_NOCLOSEPROCESS) {
                DWORD exitcode;