From 56193df2fd4719fd6d2a0214f42a7574e7600cb1 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 13 Jan 2011 20:41:27 +0100 Subject: [PATCH] winevdm: Try to exec dosbox if DOS is not supported natively. --- programs/winevdm/winevdm.c | 94 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/programs/winevdm/winevdm.c b/programs/winevdm/winevdm.c index 65f4bf2b87d..ca55d80c567 100644 --- a/programs/winevdm/winevdm.c +++ b/programs/winevdm/winevdm.c @@ -18,14 +18,19 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "config.h" +#include "wine/port.h" + #include #include +#include #include "windef.h" #include "winbase.h" #include "wine/winbase16.h" #include "winuser.h" #include "wincon.h" +#include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(winevdm); @@ -101,6 +106,93 @@ typedef struct { #include "poppack.h" +/*********************************************************************** + * find_dosbox + */ +static char *find_dosbox(void) +{ + const char *envpath = getenv( "PATH" ); + struct stat st; + char *path, *p, *buffer, *dir; + + if (!envpath) return NULL; + path = HeapAlloc( GetProcessHeap(), 0, strlen(envpath) ); + buffer = HeapAlloc( GetProcessHeap(), 0, strlen(path) + sizeof("/dosbox") ); + strcpy( path, envpath ); + p = path; + while (*p) + { + while (*p == ':') p++; + if (!*p) break; + dir = p; + while (*p && *p != ':') p++; + *p++ = 0; + strcpy( buffer, dir ); + strcat( buffer, "/dosbox" ); + if (!stat( buffer, &st )) + { + HeapFree( GetProcessHeap(), 0, path ); + return buffer; + } + } + HeapFree( GetProcessHeap(), 0, buffer ); + HeapFree( GetProcessHeap(), 0, path ); + return NULL; +} + + +/*********************************************************************** + * start_dosbox + */ +static void start_dosbox( const char *appname, const char *args ) +{ + static const WCHAR cfgW[] = {'c','f','g',0}; + const char *config_dir = wine_get_config_dir(); + WCHAR path[MAX_PATH], config[MAX_PATH]; + HANDLE file; + char *p, *buffer; + int i; + int ret = 1; + DWORD written, drives = GetLogicalDrives(); + char *dosbox = find_dosbox(); + + if (!dosbox) return; + if (!GetTempPathW( MAX_PATH, path )) return; + if (!GetTempFileNameW( path, cfgW, 0, config )) return; + if (!GetCurrentDirectoryW( MAX_PATH, path )) return; + file = CreateFileW( config, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); + if (file == INVALID_HANDLE_VALUE) return; + + buffer = HeapAlloc( GetProcessHeap(), 0, sizeof("[autoexec]") + + 25 * (strlen(config_dir) + sizeof("mount c /dosdevices/c:")) + + 4 * strlenW( path ) + + 6 + strlen( appname ) + strlen( args ) + 20 ); + p = buffer; + p += sprintf( p, "[autoexec]\n" ); + for (i = 0; i < 25; i++) + if (drives & (1 << i)) + p += sprintf( p, "mount %c %s/dosdevices/%c:\n", 'a' + i, config_dir, 'a' + i ); + p += sprintf( p, "%c:\ncd ", path[0] ); + p += WideCharToMultiByte( CP_UNIXCP, 0, path + 2, -1, p, 4 * strlenW(path), NULL, NULL ) - 1; + p += sprintf( p, "\n%s %s\n", appname, args ); + p += sprintf( p, "exit\n" ); + if (WriteFile( file, buffer, strlen(buffer), &written, NULL ) && written == strlen(buffer)) + { + const char *args[4]; + char *config_file = wine_get_unix_file_name( config ); + args[0] = dosbox; + args[1] = "-conf"; + args[2] = config_file; + args[3] = NULL; + ret = spawnvp( _P_WAIT, args[0], args ); + } + CloseHandle( file ); + DeleteFileW( config ); + HeapFree( GetProcessHeap(), 0, buffer ); + ExitProcess( ret ); +} + + /*********************************************************************** * start_dos_exe */ @@ -119,6 +211,8 @@ static void start_dos_exe( LPCSTR filename, LPCSTR cmdline ) } else reason = "because the DOS memory range is unavailable"; + start_dosbox( filename, cmdline ); + WINE_MESSAGE( "winevdm: Cannot start DOS application %s\n", filename ); WINE_MESSAGE( " %s.\n", reason ); WINE_MESSAGE( " Try running this application with DOSBox.\n" );