This patch fixes regression caused by winevdm changes. It also adds support for >126 byte DOS command lines. Changelog: Fix argument passing to DOS program from winevdm. Add support for invoking DOS programs with long command lines. Index: programs/winevdm/winevdm.c =================================================================== RCS file: /home/wine/wine/programs/winevdm/winevdm.c,v retrieving revision 1.1 diff -u -r1.1 winevdm.c --- programs/winevdm/winevdm.c 27 Apr 2003 00:47:58 -0000 1.1 +++ programs/winevdm/winevdm.c 2 May 2003 10:06:58 -0000 @@ -69,10 +69,11 @@ len+=2; /* for the quotes */ } - if (!(cmd_line = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return NULL; + if (!(cmd_line = HeapAlloc( GetProcessHeap(), 0, len ? len + 1 : 2 ))) + return NULL; p = cmd_line; - *p++ = len; + *p++ = (len < 256) ? len : 255; for (arg = argv; *arg; arg++) { int has_space,has_quote; @@ -130,7 +131,7 @@ *p++='"'; *p++=' '; } - if (p > cmd_line) p--; /* remove last space */ + if (len) p--; /* remove last space */ *p = '\0'; return cmd_line; } @@ -207,7 +208,8 @@ { if (instance == 11) /* try DOS format */ { - wine_load_dos_exe( appname, cmdline ); + /* loader expects arguments to be regular C strings */ + wine_load_dos_exe( appname, cmdline + 1 ); /* if we get back here it failed */ instance = GetLastError(); } Index: dlls/winedos/module.c =================================================================== RCS file: /home/wine/wine/dlls/winedos/module.c,v retrieving revision 1.33 diff -u -r1.33 module.c --- dlls/winedos/module.c 27 Apr 2003 20:38:22 -0000 1.33 +++ dlls/winedos/module.c 2 May 2003 10:07:15 -0000 @@ -105,7 +105,7 @@ static HANDLE dosvm_thread, loop_thread; static DWORD dosvm_tid, loop_tid; -static void MZ_Launch( LPCSTR cmdline ); +static void MZ_Launch( LPCSTR cmdtail, int length ); static BOOL MZ_InitTask(void); static void MZ_CreatePSP( LPVOID lpPSP, WORD env, WORD par ) @@ -124,34 +124,32 @@ /* FIXME: more PSP stuff */ } -static void MZ_FillPSP( LPVOID lpPSP, LPCSTR cmdline, int length ) +static void MZ_FillPSP( LPVOID lpPSP, LPCSTR cmdtail, int length ) { - PDB16 *psp = lpPSP; + PDB16 *psp = lpPSP; - while(length > 0 && *cmdline != ' ') { - length--; - cmdline++; - } + if(length > 127) + { + WARN( "Command tail truncated! (length %d)\n", length ); + length = 126; + } - /* command.com does not skip over multiple spaces */ + psp->cmdLine[0] = length; - if(length > 126) { /* - * FIXME: If length > 126 we should put truncated command line to - * PSP and store the entire command line in the environment - * variable CMDLINE. + * Length of exactly 127 bytes means that full command line is + * stored in environment variable CMDLINE and PSP contains + * command tail truncated to 126 bytes. */ - FIXME("Command line truncated! (length %d > maximum length 126)\n", - length); - length = 126; - } + if(length == 127) + length = 126; - psp->cmdLine[0] = length; - if(length > 0) - memmove(psp->cmdLine+1, cmdline, length); - psp->cmdLine[length+1] = '\r'; + if(length > 0) + memmove(psp->cmdLine+1, cmdtail, length); - /* FIXME: more PSP stuff */ + psp->cmdLine[length+1] = '\r'; + + /* FIXME: more PSP stuff */ } /* default INT 08 handler: increases timer tick counter but not much more */ @@ -353,11 +351,78 @@ */ void WINAPI wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline ) { - HANDLE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); - if (hFile == INVALID_HANDLE_VALUE) return; - DOSVM_isdosexe = TRUE; - if (MZ_DoLoadImage( hFile, filename, NULL )) MZ_Launch( cmdline ); + char dos_cmdtail[126]; + int dos_length = 0; + HANDLE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, 0 ); + if (hFile == INVALID_HANDLE_VALUE) return; + DOSVM_isdosexe = TRUE; + + if(cmdline && *cmdline) + { + dos_length = strlen(cmdline); + memmove( dos_cmdtail + 1, cmdline, + (dos_length < 125) ? dos_length : 125 ); + + /* Non-empty command tail always starts with at least one space. */ + dos_cmdtail[0] = ' '; + dos_length++; + + /* + * If command tail is longer than 126 characters, + * set tail length to 127 and fill CMDLINE environment variable + * with full command line (this includes filename). + */ + if (dos_length > 126) + { + char *cmd = HeapAlloc( GetProcessHeap(), 0, + dos_length + strlen(filename) + 4 ); + char *ptr = cmd; + + if (!cmd) + return; + + /* + * Append filename. If path includes spaces, quote the path. + */ + if (strchr(filename, ' ')) + { + *ptr++ = '\"'; + strcpy( ptr, filename ); + ptr += strlen(filename); + *ptr++ = '\"'; + } + else + { + strcpy( ptr, filename ); + ptr += strlen(filename); + } + + /* + * Append command tail. + */ + if (cmdline[0] != ' ') + *ptr++ = ' '; + strcpy( ptr, cmdline ); + + /* + * Set environment variable. This will be passed to + * new DOS process. + */ + if (!SetEnvironmentVariableA( "CMDLINE", cmd )) + { + HeapFree(GetProcessHeap(), 0, cmd ); + return; + } + + HeapFree(GetProcessHeap(), 0, cmd ); + dos_length = 127; + } + } + + if (MZ_DoLoadImage( hFile, filename, NULL )) + MZ_Launch( dos_cmdtail, dos_length ); } /*********************************************************************** @@ -391,13 +456,18 @@ ExecBlock *blk = (ExecBlock *)paramblk; LPBYTE cmdline = PTR_REAL_TO_LIN(SELECTOROF(blk->cmdline),OFFSETOF(blk->cmdline)); LPBYTE envblock = PTR_REAL_TO_LIN(psp->environment, 0); - BYTE cmdLength = cmdline[0]; + int cmdLength = cmdline[0]; /* - * FIXME: If cmdLength == 126, PSP may contain truncated version - * of the full command line. In this case environment - * variable CMDLINE contains the entire command line. + * If cmdLength is 127, command tail is truncated and environment + * variable CMDLINE should contain full command line + * (this includes filename). */ + if (cmdLength == 127) + { + FIXME( "CMDLINE argument passing is unimplemented.\n" ); + cmdLength = 126; /* FIXME */ + } fullCmdLength = (strlen(filename) + 1) + cmdLength + 1; /* filename + space + cmdline + terminating null character */ @@ -560,14 +630,14 @@ return TRUE; } -static void MZ_Launch( LPCSTR cmdline ) +static void MZ_Launch( LPCSTR cmdtail, int length ) { TDB *pTask = GlobalLock16( GetCurrentTask() ); BYTE *psp_start = PTR_REAL_TO_LIN( DOSVM_psp, 0 ); DWORD rv; SYSLEVEL *lock; - MZ_FillPSP(psp_start, cmdline, cmdline ? strlen(cmdline) : 0); + MZ_FillPSP(psp_start, cmdtail, length); pTask->flags |= TDBF_WINOLDAP; /* DTA is set to PSP:0080h when a program is started. */ -- Jukka Heinonen <http://www.iki.fi/jhei/>