Commit 1efae756 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

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

parent 7d3d98eb
...@@ -283,23 +283,23 @@ static int msvcrt_init_fp(MSVCRT_FILE* file, int fd, unsigned stream_flags) ...@@ -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 * 04 char file flags (wxflag): repeated for each fd
* 4+NBFD HANDLE file handle: 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; int fd;
char* wxflag_ptr; char* wxflag_ptr;
HANDLE* handle_ptr; HANDLE* handle_ptr;
si->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * MSVCRT_fdend; *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * MSVCRT_fdend;
si->lpReserved2 = MSVCRT_calloc(si->cbReserved2, 1); *block = MSVCRT_calloc(*size, 1);
if (!si->lpReserved2) if (!*block)
{ {
si->cbReserved2 = 0; *size = 0;
return FALSE; return FALSE;
} }
wxflag_ptr = (char*)si->lpReserved2 + sizeof(unsigned); wxflag_ptr = (char*)*block + sizeof(unsigned);
handle_ptr = (HANDLE*)(wxflag_ptr + MSVCRT_fdend * sizeof(char)); 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++) for (fd = 0; fd < MSVCRT_fdend; fd++)
{ {
/* to be inherited, we need it to be open, and that DONTINHERIT isn't set */ /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */
......
...@@ -152,7 +152,7 @@ extern void msvcrt_free_args(void); ...@@ -152,7 +152,7 @@ extern void msvcrt_free_args(void);
extern void msvcrt_init_signals(void); extern void msvcrt_init_signals(void);
extern void msvcrt_free_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 */ /* run-time error codes */
#define _RT_STACK 0 #define _RT_STACK 0
...@@ -652,6 +652,7 @@ int MSVCRT__dup(int); ...@@ -652,6 +652,7 @@ int MSVCRT__dup(int);
int MSVCRT__dup2(int, int); int MSVCRT__dup2(int, int);
int MSVCRT__pipe(int *, unsigned int, int); int MSVCRT__pipe(int *, unsigned int, int);
MSVCRT_wchar_t* _wgetenv(const MSVCRT_wchar_t*); MSVCRT_wchar_t* _wgetenv(const MSVCRT_wchar_t*);
void _wsearchenv(const MSVCRT_wchar_t*, const MSVCRT_wchar_t*, MSVCRT_wchar_t*);
#endif #endif
#endif /* __WINE_MSVCRT_H */ #endif /* __WINE_MSVCRT_H */
...@@ -559,10 +559,10 @@ ...@@ -559,10 +559,10 @@
@ stub _wspawnle #(long wstr wstr) varargs @ stub _wspawnle #(long wstr wstr) varargs
@ stub _wspawnlp #(long wstr wstr) varargs @ stub _wspawnlp #(long wstr wstr) varargs
@ stub _wspawnlpe #(long wstr wstr) varargs @ stub _wspawnlpe #(long wstr wstr) varargs
@ stub _wspawnv #(long wstr ptr) @ stdcall _wspawnv(long wstr ptr)
@ stub _wspawnve #(long wstr ptr ptr) @ stdcall _wspawnve(long wstr ptr ptr)
@ stub _wspawnvp #(long wstr ptr) @ stdcall _wspawnvp(long wstr ptr)
@ stub _wspawnvpe #(long wstr ptr ptr) @ stdcall _wspawnvpe(long wstr ptr ptr)
@ cdecl _wsplitpath(wstr wstr wstr wstr wstr) @ cdecl _wsplitpath(wstr wstr wstr wstr wstr)
@ cdecl _wstat(wstr ptr) MSVCRT__wstat @ cdecl _wstat(wstr ptr) MSVCRT__wstat
@ cdecl _wstati64(wstr ptr) MSVCRT__wstati64 @ cdecl _wstati64(wstr ptr) MSVCRT__wstati64
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "msvcrt.h" #include "msvcrt.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
...@@ -48,7 +49,7 @@ static MSVCRT_intptr_t msvcrt_spawn(int flags, const char* exe, char* cmdline, c ...@@ -48,7 +49,7 @@ static MSVCRT_intptr_t msvcrt_spawn(int flags, const char* exe, char* cmdline, c
memset(&si, 0, sizeof(si)); memset(&si, 0, sizeof(si));
si.cb = 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, if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0, flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0,
env, NULL, &si, &pi)) env, NULL, &si, &pi))
...@@ -81,6 +82,52 @@ static MSVCRT_intptr_t msvcrt_spawn(int flags, const char* exe, char* cmdline, c ...@@ -81,6 +82,52 @@ static MSVCRT_intptr_t msvcrt_spawn(int flags, const char* exe, char* cmdline, c
return -1; /* can't reach here */ 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 /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
* extra '\0' to terminate it * extra '\0' to terminate it
*/ */
...@@ -126,6 +173,48 @@ static char* msvcrt_argvtos(const char* const* arg, char delim) ...@@ -126,6 +173,48 @@ static char* msvcrt_argvtos(const char* const* arg, char delim)
return ret; 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 /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
* extra '\0' to terminate it * extra '\0' to terminate it
*/ */
...@@ -488,6 +577,63 @@ MSVCRT_intptr_t CDECL _spawnve(int flags, const char* name, const char* const* a ...@@ -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.@) * _spawnv (MSVCRT.@)
* *
* Like on Windows, this function does not handle arguments with spaces * 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 ...@@ -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.@) * _spawnvpe (MSVCRT.@)
* *
* Like on Windows, this function does not handle arguments with spaces * 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* ...@@ -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.@) * _spawnvp (MSVCRT.@)
* *
* Like on Windows, this function does not handle arguments with spaces * 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 ...@@ -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.@) * _popen (MSVCRT.@)
* FIXME: convert to _wpopen and call that from here instead? But it * 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, * would have to convert the command back to ANSI to call msvcrt_spawn,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment