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