Module: wine Branch: master Commit: 1efae756c3e23b43004994436934b1ea4e0347e9 URL: http://source.winehq.org/git/wine.git/?a=commit;h=1efae756c3e23b430049944369...
Author: Hans Leidekker hans@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,