reactos/sdk/lib/crt/process/process.c
2018-10-13 20:30:07 +02:00

686 lines
14 KiB
C

/*
* PROJECT: ReactOS CRT library
* LICENSE: GPL (?) - See COPYING in the top level directory
* FILE: lib/sdk/crt/process/process.c
* PURPOSE: Process management functions
* PROGRAMMERS: ???
*/
#include <precomp.h>
#include <process.h>
#include <tchar.h>
#include <internal/wine/msvcrt.h>
#ifdef _UNICODE
#define sT "S"
#define find_execT find_execW
#define argvtosT argvtosW
#define do_spawnT do_spawnW
#define valisttosT valisttosW
#define extT extW
#define access_dirT access_dirW
#else
#define sT "s"
#define find_execT find_execA
#define argvtosT argvtosA
#define do_spawnT do_spawnA
#define valisttosT valisttosA
#define extT extA
#define access_dirT access_dirA
#endif
#define MK_STR(s) #s
int access_dirT(const _TCHAR *_path);
_TCHAR const* extT[] =
{
_T(""),
_T(".bat"),
_T(".cmd"),
_T(".com"),
_T(".exe")
};
const _TCHAR* find_execT(const _TCHAR* path, _TCHAR* rpath)
{
_TCHAR *rp;
const _TCHAR *rd;
unsigned int i, found = 0;
TRACE(MK_STR(find_execT)"('%"sT"', %x)\n", path, rpath);
if (path == NULL)
{
return NULL;
}
if (_tcslen(path) > FILENAME_MAX - 1)
{
return path;
}
/* copy path in rpath */
for (rd = path, rp = rpath; *rd; *rp++ = *rd++)
;
*rp = 0;
/* try first with the name as is */
for (i = 0; i < sizeof(extT) / sizeof(*extT); i++)
{
_tcscpy(rp, extT[i]);
TRACE("trying '%"sT"'\n", rpath);
if (_taccess(rpath, F_OK) == 0 && access_dirT(rpath) != 0)
{
found = 1;
break;
}
}
if (!found)
{
_TCHAR* env = _tgetenv(_T("PATH"));
if (env)
{
_TCHAR* ep = env;
while (*ep && !found)
{
if (*ep == ';')
ep++;
rp=rpath;
for (; *ep && (*ep != ';'); *rp++ = *ep++)
;
if (rp > rpath)
{
rp--;
if (*rp != '/' && *rp != '\\')
{
*++rp = '\\';
}
rp++;
}
for (rd=path; *rd; *rp++ = *rd++)
;
for (i = 0; i < sizeof(extT) / sizeof(*extT); i++)
{
_tcscpy(rp, extT[i]);
TRACE("trying '%"sT"'\n", rpath);
if (_taccess(rpath, F_OK) == 0 && access_dirT(rpath) != 0)
{
found = 1;
break;
}
}
}
}
}
return found ? rpath : path;
}
static _TCHAR*
argvtosT(const _TCHAR* const* argv, _TCHAR delim)
{
int i;
size_t len;
_TCHAR *ptr, *str;
if (argv == NULL)
return NULL;
for (i = 0, len = 0; argv[i]; i++)
{
len += _tcslen(argv[i]) + 1;
}
str = ptr = (_TCHAR*) malloc((len + 1) * sizeof(_TCHAR));
if (str == NULL)
return NULL;
for(i = 0; argv[i]; i++)
{
len = _tcslen(argv[i]);
memcpy(ptr, argv[i], len * sizeof(_TCHAR));
ptr += len;
*ptr++ = delim;
}
*ptr = 0;
return str;
}
static _TCHAR*
valisttosT(const _TCHAR* arg0, va_list alist, _TCHAR delim)
{
va_list alist2;
_TCHAR *ptr, *str;
size_t len;
if (arg0 == NULL)
return NULL;
va_copy(alist2, alist);
ptr = (_TCHAR*)arg0;
len = 0;
do
{
len += _tcslen(ptr) + 1;
ptr = va_arg(alist, _TCHAR*);
}
while(ptr != NULL);
str = (_TCHAR*) malloc((len + 1) * sizeof(_TCHAR));
if (str == NULL)
{
va_end(alist2);
return NULL;
}
ptr = str;
do
{
len = _tcslen(arg0);
memcpy(ptr, arg0, len * sizeof(_TCHAR));
ptr += len;
*ptr++ = delim;
arg0 = va_arg(alist2, _TCHAR*);
}
while(arg0 != NULL);
*ptr = 0;
va_end(alist2);
return str;
}
static intptr_t
do_spawnT(int mode, const _TCHAR* cmdname, const _TCHAR* args, const _TCHAR* envp)
{
STARTUPINFO StartupInfo = {0};
PROCESS_INFORMATION ProcessInformation;
// char* fmode;
// HANDLE* hFile;
// int i, last;
BOOL bResult;
DWORD dwExitCode;
DWORD dwError;
DWORD dwFlags = 0;
TRACE(MK_STR(do_spawnT)"(%i,'%"sT"','%"sT"','%"sT"')",mode,cmdname,args,envp);
if (mode != _P_NOWAIT && mode != _P_NOWAITO && mode != _P_WAIT && mode != _P_DETACH && mode != _P_OVERLAY)
{
_set_errno ( EINVAL );
return( -1);
}
if (0 != _taccess(cmdname, F_OK))
{
_set_errno ( ENOENT );
return(-1);
}
if (0 == access_dirT(cmdname))
{
_set_errno ( EISDIR );
return(-1);
}
memset (&StartupInfo, 0, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
#if 0
for (last = i = 0; i < FDINFO_FD_MAX; i++)
{
if ((void*)-1 != _get_osfhandle(i))
{
last = i + 1;
}
}
if (last)
{
StartupInfo.cbReserved2 = sizeof(ULONG) + last * (sizeof(char) + sizeof(HANDLE));
StartupInfo.lpReserved2 = malloc(StartupInfo.cbReserved2);
if (StartupInfo.lpReserved2 == NULL)
{
_set_errno ( ENOMEM );
return -1;
}
*(DWORD*)StartupInfo.lpReserved2 = last;
fmode = (char*)(StartupInfo.lpReserved2 + sizeof(ULONG));
hFile = (HANDLE*)(StartupInfo.lpReserved2 + sizeof(ULONG) + last * sizeof(char));
for (i = 0; i < last; i++)
{
int _mode = __fileno_getmode(i);
HANDLE h = _get_osfhandle(i);
/* FIXME: The test of console handles (((ULONG)Handle) & 0x10000003) == 0x3)
* is possible wrong
*/
if ((((ULONG)h) & 0x10000003) == 0x3 || _mode & _O_NOINHERIT || (i < 3 && mode == _P_DETACH))
{
*hFile = INVALID_HANDLE_VALUE;
*fmode = 0;
}
else
{
DWORD dwFlags;
BOOL bFlag;
bFlag = GetHandleInformation(h, &dwFlags);
if (bFlag && (dwFlags & HANDLE_FLAG_INHERIT))
{
*hFile = h;
*fmode = (_O_ACCMODE & _mode) | (((_O_TEXT | _O_BINARY) & _mode) >> 8);
}
else
{
*hFile = INVALID_HANDLE_VALUE;
*fmode = 0;
}
}
fmode++;
hFile++;
}
}
#endif
create_io_inherit_block(&StartupInfo.cbReserved2, &StartupInfo.lpReserved2);
if (mode == _P_DETACH)
{
dwFlags |= DETACHED_PROCESS;
}
#ifdef _UNICODE
dwFlags |= CREATE_UNICODE_ENVIRONMENT;
#endif
bResult = CreateProcess((_TCHAR *)cmdname,
(_TCHAR *)args,
NULL,
NULL,
TRUE,
dwFlags,
(LPVOID)envp,
NULL,
&StartupInfo,
&ProcessInformation);
if (StartupInfo.lpReserved2)
{
free(StartupInfo.lpReserved2);
}
if (!bResult)
{
dwError = GetLastError();
ERR("%x\n", dwError);
_dosmaperr(dwError);
return(-1);
}
CloseHandle(ProcessInformation.hThread);
switch(mode)
{
case _P_NOWAIT:
case _P_NOWAITO:
return((intptr_t)ProcessInformation.hProcess);
case _P_OVERLAY:
CloseHandle(ProcessInformation.hProcess);
_exit(0);
case _P_WAIT:
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode);
CloseHandle(ProcessInformation.hProcess);
return( (int)dwExitCode); //CORRECT?
case _P_DETACH:
CloseHandle(ProcessInformation.hProcess);
return( 0);
}
return( (intptr_t)ProcessInformation.hProcess);
}
/*
* @implemented
*/
intptr_t _tspawnl(int mode, const _TCHAR *cmdname, const _TCHAR* arg0, ...)
{
va_list argp;
_TCHAR* args;
intptr_t ret = -1;
TRACE(MK_STR(_tspawnl)"('%"sT"')\n", cmdname);
va_start(argp, arg0);
args = valisttosT(arg0, argp, ' ');
if (args)
{
ret = do_spawnT(mode, cmdname, args, NULL);
free(args);
}
va_end(argp);
return ret;
}
/*
* @implemented
*/
intptr_t _tspawnv(int mode, const _TCHAR *cmdname, const _TCHAR* const* argv)
{
_TCHAR* args;
intptr_t ret = -1;
TRACE(MK_STR(_tspawnv)"('%"sT"')\n", cmdname);
args = argvtosT(argv, ' ');
if (args)
{
ret = do_spawnT(mode, cmdname, args, NULL);
free(args);
}
return ret;
}
/*
* @implemented
*/
intptr_t _tspawnle(int mode, const _TCHAR *cmdname, const _TCHAR* arg0, ... /*, NULL, const char* const* envp*/)
{
va_list argp;
_TCHAR* args;
_TCHAR* envs;
_TCHAR const * const* ptr;
intptr_t ret = -1;
TRACE(MK_STR(_tspawnle)"('%"sT"')\n", cmdname);
va_start(argp, arg0);
args = valisttosT(arg0, argp, ' ');
do
{
ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
}
while (ptr != NULL);
ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
envs = argvtosT(ptr, 0);
if (args)
{
ret = do_spawnT(mode, cmdname, args, envs);
free(args);
}
if (envs)
{
free(envs);
}
va_end(argp);
return ret;
}
/*
* @implemented
*/
intptr_t _tspawnve(int mode, const _TCHAR *cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
{
_TCHAR *args;
_TCHAR *envs;
intptr_t ret = -1;
TRACE(MK_STR(_tspawnve)"('%"sT"')\n", cmdname);
args = argvtosT(argv, ' ');
envs = argvtosT(envp, 0);
if (args)
{
ret = do_spawnT(mode, cmdname, args, envs);
free(args);
}
if (envs)
{
free(envs);
}
return ret;
}
/*
* @implemented
*/
intptr_t _tspawnvp(int mode, const _TCHAR* cmdname, const _TCHAR* const* argv)
{
_TCHAR pathname[FILENAME_MAX];
TRACE(MK_STR(_tspawnvp)"('%"sT"')\n", cmdname);
return _tspawnv(mode, find_execT(cmdname, pathname), argv);
}
/*
* @implemented
*/
intptr_t _tspawnlp(int mode, const _TCHAR* cmdname, const _TCHAR* arg0, .../*, NULL*/)
{
va_list argp;
_TCHAR* args;
intptr_t ret = -1;
_TCHAR pathname[FILENAME_MAX];
TRACE(MK_STR(_tspawnlp)"('%"sT"')\n", cmdname);
va_start(argp, arg0);
args = valisttosT(arg0, argp, ' ');
if (args)
{
ret = do_spawnT(mode, find_execT(cmdname, pathname), args, NULL);
free(args);
}
va_end(argp);
return ret;
}
/*
* @implemented
*/
intptr_t _tspawnlpe(int mode, const _TCHAR* cmdname, const _TCHAR* arg0, .../*, NULL, const char* const* envp*/)
{
va_list argp;
_TCHAR* args;
_TCHAR* envs;
_TCHAR const* const * ptr;
intptr_t ret = -1;
_TCHAR pathname[FILENAME_MAX];
TRACE(MK_STR(_tspawnlpe)"('%"sT"')\n", cmdname);
va_start(argp, arg0);
args = valisttosT(arg0, argp, ' ');
do
{
ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
}
while (ptr != NULL);
ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
envs = argvtosT(ptr, 0);
if (args)
{
ret = do_spawnT(mode, find_execT(cmdname, pathname), args, envs);
free(args);
}
if (envs)
{
free(envs);
}
va_end(argp);
return ret;
}
/*
* @implemented
*/
intptr_t _tspawnvpe(int mode, const _TCHAR* cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
{
_TCHAR pathname[FILENAME_MAX];
TRACE(MK_STR(_tspawnvpe)"('%"sT"')\n", cmdname);
return _tspawnve(mode, find_execT(cmdname, pathname), argv, envp);
}
/*
* @implemented
*/
intptr_t _texecl(const _TCHAR* cmdname, const _TCHAR* arg0, ...)
{
_TCHAR* args;
va_list argp;
intptr_t ret = -1;
TRACE(MK_STR(_texecl)"('%"sT"')\n", cmdname);
va_start(argp, arg0);
args = valisttosT(arg0, argp, ' ');
if (args)
{
ret = do_spawnT(_P_OVERLAY, cmdname, args, NULL);
free(args);
}
va_end(argp);
return ret;
}
/*
* @implemented
*/
intptr_t _texecv(const _TCHAR* cmdname, const _TCHAR* const* argv)
{
TRACE(MK_STR(_texecv)"('%"sT"')\n", cmdname);
return _tspawnv(_P_OVERLAY, cmdname, argv);
}
/*
* @implemented
*/
intptr_t _texecle(const _TCHAR* cmdname, const _TCHAR* arg0, ... /*, NULL, char* const* envp */)
{
va_list argp;
_TCHAR* args;
_TCHAR* envs;
_TCHAR const* const* ptr;
intptr_t ret = -1;
TRACE(MK_STR(_texecle)"('%"sT"')\n", cmdname);
va_start(argp, arg0);
args = valisttosT(arg0, argp, ' ');
do
{
ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
}
while (ptr != NULL);
ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
envs = argvtosT(ptr, 0);
if (args)
{
ret = do_spawnT(_P_OVERLAY, cmdname, args, envs);
free(args);
}
if (envs)
{
free(envs);
}
va_end(argp);
return ret;
}
/*
* @implemented
*/
intptr_t _texecve(const _TCHAR* cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
{
TRACE(MK_STR(_texecve)"('%"sT"')\n", cmdname);
return _tspawnve(_P_OVERLAY, cmdname, argv, envp);
}
/*
* @implemented
*/
intptr_t _texeclp(const _TCHAR* cmdname, const _TCHAR* arg0, ...)
{
_TCHAR* args;
va_list argp;
intptr_t ret = -1;
_TCHAR pathname[FILENAME_MAX];
TRACE(MK_STR(_texeclp)"('%"sT"')\n", cmdname);
va_start(argp, arg0);
args = valisttosT(arg0, argp, ' ');
if (args)
{
ret = do_spawnT(_P_OVERLAY, find_execT(cmdname, pathname), args, NULL);
free(args);
}
va_end(argp);
return ret;
}
/*
* @implemented
*/
intptr_t _texecvp(const _TCHAR* cmdname, const _TCHAR* const* argv)
{
TRACE(MK_STR(_texecvp)"('%"sT"')\n", cmdname);
return _tspawnvp(_P_OVERLAY, cmdname, argv);
}
/*
* @implemented
*/
intptr_t _texeclpe(const _TCHAR* cmdname, const _TCHAR* arg0, ... /*, NULL, char* const* envp */)
{
va_list argp;
_TCHAR* args;
_TCHAR* envs;
_TCHAR const* const* ptr;
intptr_t ret = -1;
_TCHAR pathname[FILENAME_MAX];
TRACE(MK_STR(_texeclpe)"('%"sT"')\n", cmdname);
va_start(argp, arg0);
args = valisttosT(arg0, argp, ' ');
do
{
ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
}
while (ptr != NULL);
ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
envs = argvtosT(ptr, 0);
if (args)
{
ret = do_spawnT(_P_OVERLAY, find_execT(cmdname, pathname), args, envs);
free(args);
}
if (envs)
{
free(envs);
}
va_end(argp);
return ret;
}
/*
* @implemented
*/
intptr_t _texecvpe(const _TCHAR* cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
{
TRACE(MK_STR(_texecvpe)"('%"sT"')\n", cmdname);
return _tspawnvpe(_P_OVERLAY, cmdname, argv, envp);
}