Fix argument passing to DOS program from winevdm.

Add support for invoking DOS programs with long command lines.
This commit is contained in:
Jukka Heinonen 2003-05-02 20:11:52 +00:00 committed by Alexandre Julliard
parent 6ac3bee094
commit f93d452d78
2 changed files with 107 additions and 35 deletions

View File

@ -105,7 +105,7 @@ static WORD init_cs,init_ip,init_ss,init_sp;
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,31 +124,29 @@ static void MZ_CreatePSP( LPVOID lpPSP, WORD env, WORD par )
/* 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;
while(length > 0 && *cmdline != ' ') {
length--;
cmdline++;
}
/* command.com does not skip over multiple spaces */
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.
*/
FIXME("Command line truncated! (length %d > maximum length 126)\n",
length);
if(length > 127)
{
WARN( "Command tail truncated! (length %d)\n", length );
length = 126;
}
psp->cmdLine[0] = length;
/*
* 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.
*/
if(length == 127)
length = 126;
if(length > 0)
memmove(psp->cmdLine+1, cmdline, length);
memmove(psp->cmdLine+1, cmdtail, length);
psp->cmdLine[length+1] = '\r';
/* FIXME: more PSP stuff */
@ -353,11 +351,78 @@ load_error:
*/
void WINAPI wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline )
{
HANDLE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
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 (MZ_DoLoadImage( hFile, filename, NULL )) MZ_Launch( cmdline );
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 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para
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 @@ static BOOL MZ_InitTask(void)
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. */

View File

@ -69,10 +69,11 @@ static char *build_command_line( char **argv )
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 @@ static char *build_command_line( char **argv )
*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 @@ int main( int argc, char *argv[] )
{
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();
}