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