winedos / Fix winevdm argument passing
Jukka Heinonen
jhei at iki.fi
Fri May 2 05:15:47 CDT 2003
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/>
More information about the wine-patches
mailing list