process-win.cpp revision 760446f710619a9daa6cedc7f0601f49e4ea3442
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Process, Windows.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2010 Oracle Corporation
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * available from http://www.virtualbox.org. This file is free software;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * terms and conditions of either the GPL or the CDDL or both.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/*******************************************************************************
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync* Header Files *
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync*******************************************************************************/
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/*******************************************************************************
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync* Structures and Typedefs *
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync*******************************************************************************/
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef WINADVAPI BOOL WINAPI FNCREATEPROCESSWITHLOGON(LPCWSTR,
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef FNCREATEPROCESSWITHLOGON *PFNCREATEPROCESSWITHLOGON;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef DWORD WINAPI FNWTSGETACTIVECONSOLESESSIONID();
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef FNWTSGETACTIVECONSOLESESSIONID *PFNWTSGETACTIVECONSOLESESSIONID;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef HANDLE WINAPI FNCREATETOOLHELP32SNAPSHOT(DWORD, DWORD);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef FNCREATETOOLHELP32SNAPSHOT *PFNCREATETOOLHELP32SNAPSHOT;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef BOOL WINAPI FNPROCESS32FIRST(HANDLE, LPPROCESSENTRY32);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef BOOL WINAPI FNPROCESS32NEXT(HANDLE, LPPROCESSENTRY32);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef BOOL WINAPI FNENUMPROCESSES(DWORD*, DWORD, DWORD*);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynctypedef DWORD FNGETMODULEBASENAME(HANDLE, HMODULE, LPTSTR, DWORD);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/*******************************************************************************
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync* Global Variables *
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync*******************************************************************************/
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** Init once structure. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic RTONCE g_rtProcWinInitOnce = RTONCE_INITIALIZER;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** Critical section protecting the process array. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** The number of processes in the array. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** The current allocation size. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** Array containing the live or non-reaped child processes. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /** The process ID. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /** The process handle. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Clean up the globals.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @param enmReason Ignored.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @param iStatus Ignored.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @param pvUser Ignored.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic DECLCALLBACK(void) rtProcWinTerm(RTTERMREASON enmReason, int32_t iStatus, void *pvUser)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync while (i-- > 0)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Initialize the globals.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @returns IPRT status code.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @param pvUser1 Ignored.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @param pvUser2 Ignored.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic DECLCALLBACK(int32_t) rtProcWinInitOnce(void *pvUser1, void *pvUser2)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /** @todo init once, terminate once - this is a generic thing which should
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * have some kind of static and simpler setup! */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Gets the process handle for a process from g_paProcesses.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @returns Process handle if found, NULL if not.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @param pid The process to remove (pid).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync while (i-- > 0)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Removes a process from g_paProcesses.
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync * @param pid The process to remove (pid).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync while (i-- > 0)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync memmove(&g_paProcesses[i], &g_paProcesses[i + 1], cToMove * sizeof(g_paProcesses[0]));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Adds a process to g_paProcesses.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @returns IPRT status code.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @param pid The process id.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @param hProcess The process handle.
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsyncstatic int rtProcWinAddPid(RTPROCESS pid, HANDLE hProcess)
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync void *pvNew = RTMemRealloc(g_paProcesses, (i + 16) * sizeof(g_paProcesses[0]));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncRTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync return RTProcCreateEx(pszExec, papszArgs, Env, fFlags,
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic int rtProcGetProcessHandle(DWORD dwPID, PSID pSID, PHANDLE phToken)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync HANDLE hProc = OpenProcess(MAXIMUM_ALLOWED, TRUE, dwPID);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE |
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync fRc = GetTokenInformation(hTokenProc, TokenUser, NULL, 0, &dwSize);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync PTOKEN_USER pTokenUser = (PTOKEN_USER)RTMemAlloc(dwSize);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync NULL, SecurityIdentification, TokenPrimary, phToken))
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * So we found the process instance which belongs to the user we want to
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * to run our new process under. This duplicated token will be used for
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * the actual CreateProcessAsUserW() call then.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync return VERR_NOT_FOUND; /* No error occured, but we didn't find the right process. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic BOOL rtProcFindProcessByName(const char *pszName, PSID pSID, PHANDLE phToken)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * On modern systems (W2K+) try the Toolhelp32 API first; this is more stable
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * and reliable. Fallback to EnumProcess on NT4.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync PFNCREATETOOLHELP32SNAPSHOT pfnCreateToolhelp32Snapshot;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = RTLdrGetSymbol(hKernel32, "CreateToolhelp32Snapshot", (void**)&pfnCreateToolhelp32Snapshot);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = RTLdrGetSymbol(hKernel32, "Process32First", (void**)&pfnProcess32First);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = RTLdrGetSymbol(hKernel32, "Process32Next", (void**)&pfnProcess32Next);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync HANDLE hSnap = pfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync && RT_SUCCESS(rtProcGetProcessHandle(procEntry.th32ProcessID, pSID, phToken)))
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync } while (pfnProcess32Next(hSnap, &procEntry) && !fFound);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync else /* Process32First */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync else /* hSnap =! INVALID_HANDLE_VALUE */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync else /* CreateToolhelp32Snapshot / Toolhelp32 API not available. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * NT4 needs a copy of "PSAPI.dll" (redistributed by Microsoft and not
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * part of the OS) in order to get a lookup. If we don't have this DLL
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * we are not able to get a token and therefore no UI will be visible.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = RTLdrGetSymbol(hPSAPI, "EnumProcesses", (void**)&pfnEnumProcesses);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = RTLdrGetSymbol(hPSAPI, "GetModuleBaseName", (void**)&pfnGetModuleBaseName);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /** @todo Retry if pBytesReturned equals cbBytes! */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DWORD dwPIDs[4096]; /* Should be sufficient for now. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync if (pfnEnumProcesses(dwPIDs, sizeof(dwPIDs), &cbBytes))
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync for (DWORD dwIdx = 0; dwIdx < cbBytes/sizeof(DWORD) && !fFound; dwIdx++)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync if (pfnGetModuleBaseName(hProc, 0, pszProcName, dwSize) == dwSize)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync } while (GetLastError() == ERROR_INSUFFICIENT_BUFFER);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync && RT_SUCCESS(rtProcGetProcessHandle(dwPIDs[dwIdx], pSID, phToken)))
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic int rtProcCreateAsUserHlp(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszExec, PRTUTF16 pwszCmdLine,
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo, uint32_t fFlags)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * If we run as a service CreateProcessWithLogon will fail,
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * so don't even try it (because of Local System context).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * This may fail on too old (NT4) platforms or if the calling process
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * is running on a SYSTEM account (like a service, ERROR_ACCESS_DENIED) on newer
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * platforms (however, this works on W2K!).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync PFNCREATEPROCESSWITHLOGON pfnCreateProcessWithLogonW;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = RTLdrGetSymbol(hAdvAPI32, "CreateProcessWithLogonW", (void**)&pfnCreateProcessWithLogonW);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Did the API call above fail because we're running on a too old OS (NT4) or
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * we're running as a Windows service?
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync * So if we want to start a process from a service (RTPROC_FLAGS_SERVICE),
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * we have to do the following:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * - Check the credentials supplied and get the user SID.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * - If valid get the correct Explorer/VBoxTray instance corresponding to that
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * user. This of course is only possible if that user is logged in (over
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * physical console or terminal services).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * - If we found the user's Explorer/VBoxTray app, use and modify the token to
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * use it in order to allow the newly started process acess the user's
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * desktop. If there's no Explorer/VBoxTray app we cannot display the started
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * process (but run it without UI).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * The following restrictions apply:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * - A process only can show its UI when the user the process should run
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * under is logged in (has a desktop).
cf3aad827eee194a3e6e68796710074b44164371vboxsync * - We do not want to display a process of user A run on the desktop
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * of user B on multi session systems.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * The following rights are needed in order to use LogonUserW and
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * CreateProcessAsUserW, so the local policy has to be modified to:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * - SE_TCB_NAME = Act as part of the operating system
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * - SE_INCREASE_QUOTA_NAME
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * We may fail here with ERROR_PRIVILEGE_NOT_HELD.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Because we have to deal with http://support.microsoft.com/kb/245683
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * for NULL domain names when running on NT4 here, pass an empty string if so.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * However, passing FQDNs should work!
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ((DWORD)(LOBYTE(LOWORD(GetVersion()))) < 5) /* < Windows 2000. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DWORD cbName = 0; /* Must be zero to query size! */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync PSID pSID = (PSID)RTMemAlloc(cbName * sizeof(wchar_t));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /** @todo No way to allocate a PRTUTF16 directly? */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pwszDomain = (PRTUTF16)RTMemAlloc(cbDomain * sizeof(RTUTF16));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* Note: Also supports FQDNs! */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync "VBoxTray.exe",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync "explorer.exe"
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync dwErr = GetLastError(); /* LookupAccountNameW() failed. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync else /* !RTPROC_FLAGS_SERVICE */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* Nothing to do here right now. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * If we didn't find a matching VBoxTray, just use the token we got
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * above from LogonUserW(). This enables us to at least run processes with
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * desktop interaction without UI.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync phToken = fFound ? &hTokenUserDesktop : &hTokenLogon;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Useful KB articles:
c58c758d3642ac45d3f12356c406c631fcd8f538vboxsync dwErr = GetLastError(); /* CreateProcessAsUserW() failed. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Map some important or much used Windows error codes
6c2750d8e30830bf114880ca33922b108ab3e942vboxsync * to our error codes.
6c2750d8e30830bf114880ca33922b108ab3e942vboxsync case ERROR_ACCOUNT_RESTRICTION: /* See: http://support.microsoft.com/kb/303846/ */
6c2750d8e30830bf114880ca33922b108ab3e942vboxsync /* Could trigger a debug assertion! */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncRTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Input validation
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync AssertReturn(!(fFlags & ~(RTPROC_FLAGS_DAEMONIZE_DEPRECATED | RTPROC_FLAGS_DETACHED | RTPROC_FLAGS_SERVICE)), VERR_INVALID_PARAMETER);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync AssertReturn(!(fFlags & RTPROC_FLAGS_DETACHED) || !phProcess, VERR_INVALID_PARAMETER);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync AssertReturn(hEnv != NIL_RTENV, VERR_INVALID_PARAMETER);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync AssertPtrReturn(papszArgs, VERR_INVALID_PARAMETER);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync AssertPtrNullReturn(pszAsUser, VERR_INVALID_POINTER);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync AssertReturn(!pszAsUser || *pszAsUser, VERR_INVALID_PARAMETER);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync AssertReturn(!pszPassword || pszAsUser, VERR_INVALID_PARAMETER);
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync AssertPtrNullReturn(pszPassword, VERR_INVALID_POINTER);
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync /** @todo search the PATH (add flag for this). */
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync * Initialize the globals.
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL, NULL);
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync * Get the file descriptors for the handles we've been passed.
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync * It seems there is no point in trying to convince a child process's CRT
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * that any of the standard file handles is non-TEXT. So, we don't...
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync#if 1 /* The CRT should keep the standard handles up to date. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
if (paHandles[i])
case RTHANDLETYPE_FILE:
case RTHANDLETYPE_PIPE:
case RTHANDLETYPE_SOCKET:
&ProcInfo))
if (phProcess)
return rc;
AssertReturn(!(fFlags & ~(RTPROCWAIT_FLAGS_BLOCK | RTPROCWAIT_FLAGS_NOBLOCK)), VERR_INVALID_PARAMETER);
switch (WaitRc)
case WAIT_OBJECT_0:
if (pProcStatus)
return VINF_SUCCESS;
case WAIT_TIMEOUT:
return VERR_PROCESS_RUNNING;
case WAIT_FAILED:
case WAIT_ABANDONED:
AssertFailed();
return VERR_GENERAL_FAILURE;
return VERR_GENERAL_FAILURE;
return VERR_PROCESS_NOT_FOUND;
if (!fRc)
return rc;
BOOL fRc = GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
return dwProcessAffinityMask;