Hans Leidekker : msvcrt: Implement _wspawnv{, e, p, pe}.

Alexandre Julliard julliard at winehq.org
Mon Sep 24 08:08:05 CDT 2007


Module: wine
Branch: master
Commit: 1efae756c3e23b43004994436934b1ea4e0347e9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1efae756c3e23b43004994436934b1ea4e0347e9

Author: Hans Leidekker <hans at it.vu.nl>
Date:   Fri Sep 21 15:50:01 2007 +0200

msvcrt: Implement _wspawnv{, e, p, pe}.

---

 dlls/msvcrt/file.c      |   14 ++--
 dlls/msvcrt/msvcrt.h    |    3 +-
 dlls/msvcrt/msvcrt.spec |    8 +-
 dlls/msvcrt/process.c   |  183 ++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 195 insertions(+), 13 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index c46b5c4..4ceae0b 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -283,23 +283,23 @@ static int msvcrt_init_fp(MSVCRT_FILE* file, int fd, unsigned stream_flags)
  *      04      char    file flags (wxflag): repeated for each fd
  *      4+NBFD  HANDLE  file handle: repeated for each fd
  */
-unsigned msvcrt_create_io_inherit_block(STARTUPINFOA* si)
+unsigned msvcrt_create_io_inherit_block(WORD *size, BYTE **block)
 {
   int         fd;
   char*       wxflag_ptr;
   HANDLE*     handle_ptr;
 
-  si->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * MSVCRT_fdend;
-  si->lpReserved2 = MSVCRT_calloc(si->cbReserved2, 1);
-  if (!si->lpReserved2)
+  *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * MSVCRT_fdend;
+  *block = MSVCRT_calloc(*size, 1);
+  if (!*block)
   {
-    si->cbReserved2 = 0;
+    *size = 0;
     return FALSE;
   }
-  wxflag_ptr = (char*)si->lpReserved2 + sizeof(unsigned);
+  wxflag_ptr = (char*)*block + sizeof(unsigned);
   handle_ptr = (HANDLE*)(wxflag_ptr + MSVCRT_fdend * sizeof(char));
 
-  *(unsigned*)si->lpReserved2 = MSVCRT_fdend;
+  *(unsigned*)*block = MSVCRT_fdend;
   for (fd = 0; fd < MSVCRT_fdend; fd++)
   {
     /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index cc3cdd7..204fe9c 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -152,7 +152,7 @@ extern void msvcrt_free_args(void);
 extern void msvcrt_init_signals(void);
 extern void msvcrt_free_signals(void);
 
-extern unsigned msvcrt_create_io_inherit_block(STARTUPINFOA*);
+extern unsigned msvcrt_create_io_inherit_block(WORD*, BYTE**);
 
 /* run-time error codes */
 #define _RT_STACK       0
@@ -652,6 +652,7 @@ int           MSVCRT__dup(int);
 int           MSVCRT__dup2(int, int);
 int           MSVCRT__pipe(int *, unsigned int, int);
 MSVCRT_wchar_t* _wgetenv(const MSVCRT_wchar_t*);
+void          _wsearchenv(const MSVCRT_wchar_t*, const MSVCRT_wchar_t*, MSVCRT_wchar_t*);
 #endif
 
 #endif /* __WINE_MSVCRT_H */
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 74d1fad..5711946 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -559,10 +559,10 @@
 @ stub _wspawnle #(long wstr wstr) varargs
 @ stub _wspawnlp #(long wstr wstr) varargs
 @ stub _wspawnlpe #(long wstr wstr) varargs
-@ stub _wspawnv #(long wstr ptr)
-@ stub _wspawnve #(long wstr ptr ptr)
-@ stub _wspawnvp #(long wstr ptr)
-@ stub _wspawnvpe #(long wstr ptr ptr)
+@ stdcall _wspawnv(long wstr ptr)
+@ stdcall _wspawnve(long wstr ptr ptr)
+@ stdcall _wspawnvp(long wstr ptr)
+@ stdcall _wspawnvpe(long wstr ptr ptr)
 @ cdecl _wsplitpath(wstr wstr wstr wstr wstr)
 @ cdecl _wstat(wstr ptr) MSVCRT__wstat
 @ cdecl _wstati64(wstr ptr) MSVCRT__wstati64
diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c
index c6c3a7e..14f8e9a 100644
--- a/dlls/msvcrt/process.c
+++ b/dlls/msvcrt/process.c
@@ -31,6 +31,7 @@
 
 #include "msvcrt.h"
 #include "wine/debug.h"
+#include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 
@@ -48,7 +49,7 @@ static MSVCRT_intptr_t msvcrt_spawn(int flags, const char* exe, char* cmdline, c
 
   memset(&si, 0, sizeof(si));
   si.cb = sizeof(si);
-  msvcrt_create_io_inherit_block(&si);
+  msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2);
   if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
                      flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0,
                      env, NULL, &si, &pi))
@@ -81,6 +82,52 @@ static MSVCRT_intptr_t msvcrt_spawn(int flags, const char* exe, char* cmdline, c
   return -1; /* can't reach here */
 }
 
+static MSVCRT_intptr_t msvcrt_spawn_wide(int flags, const MSVCRT_wchar_t* exe, MSVCRT_wchar_t* cmdline, MSVCRT_wchar_t* env)
+{
+  STARTUPINFOW si;
+  PROCESS_INFORMATION pi;
+
+  if ((unsigned)flags > MSVCRT__P_DETACH)
+  {
+    *MSVCRT__errno() = MSVCRT_EINVAL;
+    return -1;
+  }
+
+  memset(&si, 0, sizeof(si));
+  si.cb = sizeof(si);
+  msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2);
+  if (!CreateProcessW(exe, cmdline, NULL, NULL, TRUE,
+                     flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0,
+                     env, NULL, &si, &pi))
+  {
+    msvcrt_set_errno(GetLastError());
+    MSVCRT_free(si.lpReserved2);
+    return -1;
+  }
+
+  MSVCRT_free(si.lpReserved2);
+  switch(flags)
+  {
+  case MSVCRT__P_WAIT:
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
+    return pi.dwProcessId;
+  case MSVCRT__P_DETACH:
+    CloseHandle(pi.hProcess);
+    pi.hProcess = 0;
+    /* fall through */
+  case MSVCRT__P_NOWAIT:
+  case MSVCRT__P_NOWAITO:
+    CloseHandle(pi.hThread);
+    return (MSVCRT_intptr_t)pi.hProcess;
+  case  MSVCRT__P_OVERLAY:
+    MSVCRT__exit(0);
+  }
+  return -1; /* can't reach here */
+}
+
 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
  * extra '\0' to terminate it
  */
@@ -126,6 +173,48 @@ static char* msvcrt_argvtos(const char* const* arg, char delim)
   return ret;
 }
 
+static MSVCRT_wchar_t* msvcrt_argvtos_wide(const MSVCRT_wchar_t* const* arg, MSVCRT_wchar_t delim)
+{
+  const MSVCRT_wchar_t* const* a;
+  long size;
+  MSVCRT_wchar_t* p;
+  MSVCRT_wchar_t* ret;
+
+  if (!arg && !delim)
+  {
+      /* Return NULL for an empty environment list */
+      return NULL;
+  }
+
+  /* get length */
+  a = arg;
+  size = 0;
+  while (*a)
+  {
+    size += strlenW(*a) + 1;
+    a++;
+  }
+
+  ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t));
+  if (!ret)
+    return NULL;
+
+  /* fill string */
+  a = arg;
+  p = ret;
+  while (*a)
+  {
+    int len = strlenW(*a);
+    memcpy(p,*a,len * sizeof(MSVCRT_wchar_t));
+    p += len;
+    *p++ = delim;
+    a++;
+  }
+  if (delim && p > ret) p[-1] = 0;
+  else *p = 0;
+  return ret;
+}
+
 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
  * extra '\0' to terminate it
  */
@@ -488,6 +577,63 @@ MSVCRT_intptr_t CDECL _spawnve(int flags, const char* name, const char* const* a
 }
 
 /*********************************************************************
+ *      _wspawnve (MSVCRT.@)
+ *
+ * Unicode version of _spawnve
+ */
+MSVCRT_intptr_t CDECL _wspawnve(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
+                                const MSVCRT_wchar_t* const* envv)
+{
+  MSVCRT_wchar_t * args = msvcrt_argvtos_wide(argv,' ');
+  MSVCRT_wchar_t * envs = msvcrt_argvtos_wide(envv,0);
+  MSVCRT_wchar_t fullname[MAX_PATH];
+  const MSVCRT_wchar_t *p;
+  int len;
+  MSVCRT_intptr_t ret = -1;
+
+  TRACE(":call (%s), params (%s), env (%s)\n",debugstr_w(name),debugstr_w(args),
+   envs?"Custom":"Null");
+
+  /* no check for NULL name.
+     native doesn't do it */
+
+  p = memchrW(name, '\0', MAX_PATH);
+  if( !p )
+    p = name + MAX_PATH - 1;
+  len = p - name;
+
+  /* extra-long names are silently truncated. */
+  memcpy(fullname, name, len * sizeof(MSVCRT_wchar_t));
+
+  for( p--; p >= name; p-- )
+  {
+    if( *p == '\\' || *p == '/' || *p == ':' || *p == '.' )
+      break;
+  }
+
+  /* if no extension is given, assume .exe */
+  if( (p < name || *p != '.') && len <= MAX_PATH - 5 )
+  {
+    static const MSVCRT_wchar_t dotexe[] = {'.','e','x','e'};
+
+    FIXME("only trying .exe when no extension given\n");
+    memcpy(fullname+len, dotexe, 4 * sizeof(MSVCRT_wchar_t));
+    len += 4;
+  }
+
+  fullname[len] = '\0';
+
+  if (args)
+  {
+    ret = msvcrt_spawn_wide(flags, fullname, args, envs);
+    MSVCRT_free(args);
+  }
+  MSVCRT_free(envs);
+
+  return ret;
+}
+
+/*********************************************************************
  *		_spawnv (MSVCRT.@)
  *
  * Like on Windows, this function does not handle arguments with spaces
@@ -499,6 +645,16 @@ MSVCRT_intptr_t CDECL _spawnv(int flags, const char* name, const char* const* ar
 }
 
 /*********************************************************************
+ *      _wspawnv (MSVCRT.@)
+ *
+ * Unicode version of _spawnv
+ */
+MSVCRT_intptr_t CDECL _wspawnv(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
+{
+  return _wspawnve(flags, name, argv, NULL);
+}
+
+/*********************************************************************
  *		_spawnvpe (MSVCRT.@)
  *
  * Like on Windows, this function does not handle arguments with spaces
@@ -513,6 +669,21 @@ MSVCRT_intptr_t CDECL _spawnvpe(int flags, const char* name, const char* const*
 }
 
 /*********************************************************************
+ *      _wspawnvpe (MSVCRT.@)
+ *
+ * Unicode version of _spawnvpe
+ */
+MSVCRT_intptr_t CDECL _wspawnvpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
+                                 const MSVCRT_wchar_t* const* envv)
+{
+  static const MSVCRT_wchar_t path[] = {'P','A','T','H',0};
+  MSVCRT_wchar_t fullname[MAX_PATH];
+
+  _wsearchenv(name, path, fullname);
+  return _wspawnve(flags, fullname[0] ? fullname : name, argv, envv);
+}
+
+/*********************************************************************
  *		_spawnvp (MSVCRT.@)
  *
  * Like on Windows, this function does not handle arguments with spaces
@@ -524,6 +695,16 @@ MSVCRT_intptr_t CDECL _spawnvp(int flags, const char* name, const char* const* a
 }
 
 /*********************************************************************
+ *      _wspawnvp (MSVCRT.@)
+ *
+ * Unicode version of _spawnvp
+ */
+MSVCRT_intptr_t CDECL _wspawnvp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
+{
+  return _wspawnvpe(flags, name, argv, NULL);
+}
+
+/*********************************************************************
  *		_popen (MSVCRT.@)
  * FIXME: convert to _wpopen and call that from here instead?  But it
  * would have to convert the command back to ANSI to call msvcrt_spawn,




More information about the wine-cvs mailing list