/* * 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 #include #include #include #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); }