MZ_Exec() patch, try 3

chrismorgan at rcn.com chrismorgan at rcn.com
Mon Oct 21 17:06:40 CDT 2002


Alright, yet another revision of this patch.  This one uses dynamic memory allocation via HeapAlloc/Free(), doesn't modify the input command line and doesn't try to close process handles if CreateProcess failed.  Third time a charm? ;-)

* dlls/winedos/module.c:
Chris Morgan <cmorgan at alum.wpi.edu>
Call CreateProcessA() when executing non-dos applications from a dos application.



-------------- next part --------------
Index: dlls/winedos/module.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/module.c,v
retrieving revision 1.23
diff -u -r1.23 module.c
--- dlls/winedos/module.c	18 Oct 2002 23:48:58 -0000	1.23
+++ dlls/winedos/module.c	21 Oct 2002 22:00:16 -0000
@@ -339,17 +339,78 @@
 
 /***********************************************************************
  *		MZ_Exec
+ *
+ * this may only be called from existing DOS processes
  */
 BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
 {
-  /* this may only be called from existing DOS processes
-   * (i.e. one DOS app spawning another) */
-  /* FIXME: do we want to check binary type first, to check
-   * whether it's a NE/PE executable? */
+  DWORD binType;
+  STARTUPINFOA st;
+  PROCESS_INFORMATION pe;
+  BOOL status;
+
   HANDLE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
 			     NULL, OPEN_EXISTING, 0, 0);
   BOOL ret = FALSE;
+
+  if(!GetBinaryTypeA(filename, &binType))   /* determine what kind of binary this is */
+  {
+    return FALSE; /* binary is not an executable */
+  }
+
   if (hFile == INVALID_HANDLE_VALUE) return FALSE;
+
+  /* handle non-dos executables */
+  if(binType != SCS_DOS_BINARY)
+  {
+    if(func == 0) /* load and execute */
+    {
+      LPBYTE fullCmdLine;
+      WORD fullCmdLength;
+      LPBYTE psp_start = (LPBYTE)((DWORD)DOSVM_psp << 4);
+      PDB16 *psp = (PDB16 *)psp_start;
+      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];
+
+      fullCmdLength = (strlen(filename) + 1) + cmdLength + 1; /* filename + space + cmdline + terminating null character */
+
+      fullCmdLine = HeapAlloc(GetProcessHeap(), 0, fullCmdLength);
+
+      /* build the full command line from the executable file and the command line being passed in */
+      snprintf(fullCmdLine, fullCmdLength, "%s ", filename); /* start off with the executable filename and a space */
+      memcpy(fullCmdLine + strlen(fullCmdLine), cmdline + 1, cmdLength); /* append cmdline onto the end */
+      fullCmdLine[fullCmdLength - 1] = 0; /* null terminate string */
+
+      ZeroMemory (&st, sizeof(STARTUPINFOA));
+      st.cb = sizeof(STARTUPINFOA);
+      status = CreateProcessA (NULL, fullCmdLine, NULL, NULL, TRUE,
+               0, envblock, NULL, &st, &pe);
+
+      WaitForSingleObject(pe.hProcess, INFINITE);  /* wait here until the child process is complete */
+
+      HeapFree(GetProcessHeap(), 0, fullCmdLine);  /* free the memory we allocated */
+
+      /* clean up PROCESS_INFORMATION handles if necessary */
+      if(status)
+      {
+        CloseHandle(pe.hProcess);
+        CloseHandle(pe.hThread);
+      }
+
+      ret = TRUE;
+    } else
+    {
+      FIXME("EXEC type of %d not implemented for non-dos executables\n", func);
+      ret = FALSE;
+    }
+
+    CloseHandle(hFile);
+    return ret;
+  } /* if(binType != SCS_DOS_BINARY) */
+
+  /* handle dos executables */
   switch (func) {
   case 0: /* load and execute */
   case 1: /* load but don't execute */


More information about the wine-devel mailing list