msvcrt: Implement _wspawnv{, e, p, pe}.
This commit is contained in:
parent
7d3d98eb5c
commit
1efae756c3
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -487,6 +576,63 @@ MSVCRT_intptr_t CDECL _spawnve(int flags, const char* name, const char* const* a
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _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.@)
|
||||
*
|
||||
|
@ -498,6 +644,16 @@ MSVCRT_intptr_t CDECL _spawnv(int flags, const char* name, const char* const* ar
|
|||
return _spawnve(flags, name, argv, NULL);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _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.@)
|
||||
*
|
||||
|
@ -512,6 +668,21 @@ MSVCRT_intptr_t CDECL _spawnvpe(int flags, const char* name, const char* const*
|
|||
return _spawnve(flags, fullname[0] ? fullname : name, argv, envv);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _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.@)
|
||||
*
|
||||
|
@ -523,6 +694,16 @@ MSVCRT_intptr_t CDECL _spawnvp(int flags, const char* name, const char* const* a
|
|||
return _spawnvpe(flags, name, argv, NULL);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _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
|
||||
|
|
Loading…
Reference in New Issue