process-win.cpp revision 025753bddaf4d9177cc80dde6963bb4e922c075d
083dd76e9fd7a829b1ed67ffc9003276643e7db1vboxsync * IPRT - Process, Windows.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2010 Oracle Corporation
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * available from http://www.virtualbox.org. This file is free software;
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * you can redistribute it and/or modify it under the terms of the GNU
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * General Public License (GPL) as published by the Free Software
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * The contents of this file may alternatively be used under the terms
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * of the Common Development and Distribution License Version 1.0
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * VirtualBox OSE distribution, in which case the provisions of the
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * CDDL are applicable instead of those of the GPL.
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * You may elect to license modified versions of this file under the
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * terms and conditions of either the GPL or the CDDL or both.
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync/*******************************************************************************
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync* Header Files *
85c594c1140f082dd862abde9dc7825137a3d51avboxsync*******************************************************************************/
463d00559e51c6e08ccc9f5a77d2ee6d122b6e8cvboxsync/*******************************************************************************
6edb4183bc898fddcd0987b6c5c3903b8246fe45vboxsync* Structures and Typedefs *
584a4e8a4f886566a96ba14cdaab6e94162545a8vboxsync*******************************************************************************/
85c594c1140f082dd862abde9dc7825137a3d51avboxsynctypedef WINADVAPI BOOL WINAPI FNCREATEPROCESSWITHLOGON(LPCWSTR,
507ebf9b3b77c84000a55645867db6617b5324bcvboxsynctypedef FNCREATEPROCESSWITHLOGON *PFNCREATEPROCESSWITHLOGON;
34822e8b7d00c04a0bc98c0d1a565a00d9bb1fd9vboxsynctypedef DWORD WINAPI FNWTSGETACTIVECONSOLESESSIONID();
34822e8b7d00c04a0bc98c0d1a565a00d9bb1fd9vboxsynctypedef FNWTSGETACTIVECONSOLESESSIONID *PFNWTSGETACTIVECONSOLESESSIONID;
507ebf9b3b77c84000a55645867db6617b5324bcvboxsynctypedef HANDLE WINAPI FNCREATETOOLHELP32SNAPSHOT(DWORD, DWORD);
507ebf9b3b77c84000a55645867db6617b5324bcvboxsynctypedef FNCREATETOOLHELP32SNAPSHOT *PFNCREATETOOLHELP32SNAPSHOT;
83b8ea36fb307b6264bc47ae9f7f67b1d32e3388vboxsynctypedef BOOL WINAPI FNPROCESS32FIRST(HANDLE, LPPROCESSENTRY32);
83b8ea36fb307b6264bc47ae9f7f67b1d32e3388vboxsynctypedef BOOL WINAPI FNPROCESS32NEXT(HANDLE, LPPROCESSENTRY32);
34822e8b7d00c04a0bc98c0d1a565a00d9bb1fd9vboxsynctypedef BOOL WINAPI FNENUMPROCESSES(DWORD*, DWORD, DWORD*);
507ebf9b3b77c84000a55645867db6617b5324bcvboxsynctypedef DWORD FNGETMODULEBASENAME(HANDLE, HMODULE, LPTSTR, DWORD);
98da2c2cca8786e117ad93a31c6b2c6c1c3cdc78vboxsynctypedef BOOL WINAPI FNCREATEENVIRONMENTBLOCK(LPVOID *, HANDLE, BOOL);
507ebf9b3b77c84000a55645867db6617b5324bcvboxsynctypedef FNCREATEENVIRONMENTBLOCK *PFNCREATEENVIRONMENTBLOCK;
507ebf9b3b77c84000a55645867db6617b5324bcvboxsynctypedef BOOL WINAPI FNPFNDESTROYENVIRONMENTBLOCK(LPVOID);
507ebf9b3b77c84000a55645867db6617b5324bcvboxsynctypedef FNPFNDESTROYENVIRONMENTBLOCK *PFNPFNDESTROYENVIRONMENTBLOCK;
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsynctypedef BOOL WINAPI FNLOADUSERPROFILEW(HANDLE, LPPROFILEINFOW);
fde449f361029c75f9bf28f145bd1ba7b36a9c77vboxsynctypedef BOOL WINAPI FNUNLOADUSERPROFILE(HANDLE, HANDLE);
85c594c1140f082dd862abde9dc7825137a3d51avboxsync/*******************************************************************************
34822e8b7d00c04a0bc98c0d1a565a00d9bb1fd9vboxsync* Global Variables *
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync*******************************************************************************/
fde449f361029c75f9bf28f145bd1ba7b36a9c77vboxsync/** Init once structure. */
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsyncstatic RTONCE g_rtProcWinInitOnce = RTONCE_INITIALIZER;
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync/** Critical section protecting the process array. */
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync/** The number of processes in the array. */
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync/** The current allocation size. */
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync/** Array containing the live or non-reaped child processes. */
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync /** The process ID. */
83b8ea36fb307b6264bc47ae9f7f67b1d32e3388vboxsync /** The process handle. */
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * Clean up the globals.
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * @param enmReason Ignored.
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * @param iStatus Ignored.
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * @param pvUser Ignored.
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsyncstatic DECLCALLBACK(void) rtProcWinTerm(RTTERMREASON enmReason, int32_t iStatus, void *pvUser)
85c594c1140f082dd862abde9dc7825137a3d51avboxsync while (i-- > 0)
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * Initialize the globals.
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * @returns IPRT status code.
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * @param pvUser1 Ignored.
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * @param pvUser2 Ignored.
85c594c1140f082dd862abde9dc7825137a3d51avboxsyncstatic DECLCALLBACK(int32_t) rtProcWinInitOnce(void *pvUser1, void *pvUser2)
85c594c1140f082dd862abde9dc7825137a3d51avboxsync /** @todo init once, terminate once - this is a generic thing which should
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * have some kind of static and simpler setup! */
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * Gets the process handle for a process from g_paProcesses.
999b9efb1c9a95fee642550c525ca0cf7c6f07b5vboxsync * @returns Process handle if found, NULL if not.
999b9efb1c9a95fee642550c525ca0cf7c6f07b5vboxsync * @param pid The process to remove (pid).
999b9efb1c9a95fee642550c525ca0cf7c6f07b5vboxsync while (i-- > 0)
eb5d68001efb9346c3341aa46f2871b973b47107vboxsync * Removes a process from g_paProcesses and closes the process handle.
999b9efb1c9a95fee642550c525ca0cf7c6f07b5vboxsync * @param pid The process to remove (pid).
999b9efb1c9a95fee642550c525ca0cf7c6f07b5vboxsync while (i-- > 0)
fde449f361029c75f9bf28f145bd1ba7b36a9c77vboxsync memmove(&g_paProcesses[i], &g_paProcesses[i + 1], cToMove * sizeof(g_paProcesses[0]));
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * Adds a process to g_paProcesses.
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * @returns IPRT status code.
eb5d68001efb9346c3341aa46f2871b973b47107vboxsync * @param pid The process id.
eb5d68001efb9346c3341aa46f2871b973b47107vboxsync * @param hProcess The process handle.
eb5d68001efb9346c3341aa46f2871b973b47107vboxsyncstatic int rtProcWinAddPid(RTPROCESS pid, HANDLE hProcess)
eb5d68001efb9346c3341aa46f2871b973b47107vboxsync void *pvNew = RTMemRealloc(g_paProcesses, (i + 16) * sizeof(g_paProcesses[0]));
584a4e8a4f886566a96ba14cdaab6e94162545a8vboxsyncRTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
584a4e8a4f886566a96ba14cdaab6e94162545a8vboxsync return RTProcCreateEx(pszExec, papszArgs, Env, fFlags,
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * Map some important or much used Windows error codes
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * to our error codes.
34822e8b7d00c04a0bc98c0d1a565a00d9bb1fd9vboxsync * @return Mapped IPRT status code.
34822e8b7d00c04a0bc98c0d1a565a00d9bb1fd9vboxsync * @param dwError Windows error code to map to IPRT code.
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync case ERROR_ACCOUNT_RESTRICTION: /* See: http://support.microsoft.com/kb/303846/ */
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync /* Could trigger a debug assertion! */
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * Get the process token (not the process handle like the name might indicate)
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * of the process indicated by @a dwPID if the @a pSID matches.
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * @returns IPRT status code.
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync * @param dwPID The process identifier.
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * @param pSID The secure identifier of the user.
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * @param phToken Where to return the token handle - duplicate,
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * caller closes it on success.
85c594c1140f082dd862abde9dc7825137a3d51avboxsyncstatic int rtProcGetProcessHandle(DWORD dwPID, PSID pSID, PHANDLE phToken)
85c594c1140f082dd862abde9dc7825137a3d51avboxsync bool fFound = false;
e38719852d98638514dba23fbacf53ad11361d6avboxsync HANDLE hProc = OpenProcess(MAXIMUM_ALLOWED, TRUE, dwPID);
0c1bdc5adae416967cb64e09f8ec81a5b77fe31dvboxsync TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE
85c594c1140f082dd862abde9dc7825137a3d51avboxsync | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync fRc = GetTokenInformation(hTokenProc, TokenUser, NULL, 0, &dwSize);
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync PTOKEN_USER pTokenUser = (PTOKEN_USER)RTMemAlloc(dwSize);
f6b7aa2d424718f1bf8ca45a37b219b986f1024bvboxsync AssertPtrReturn(pTokenUser, VERR_NO_MEMORY); /** @todo r=bird: Leaking handles when we're out of memory... */
85c594c1140f082dd862abde9dc7825137a3d51avboxsync NULL, SecurityIdentification, TokenPrimary, phToken))
1c8130d3c423590046a8ed4f3059de38ac5dcc14vboxsync * So we found the process instance which belongs to the user we want to
1c8130d3c423590046a8ed4f3059de38ac5dcc14vboxsync * to run our new process under. This duplicated token will be used for
1c8130d3c423590046a8ed4f3059de38ac5dcc14vboxsync * the actual CreateProcessAsUserW() call then.
85c594c1140f082dd862abde9dc7825137a3d51avboxsync return VERR_NOT_FOUND; /* No error occurred, but we didn't find the right process. */
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * Finds a one of the processes in @a papszNames running with user @a pSID and
85c594c1140f082dd862abde9dc7825137a3d51avboxsync * returns a duplicate handle to its token.
bool fFound = false;
fFound = true;
if (hProc)
if (pszProcName)
fFound = true;
if (pszProcName)
return fFound;
static int rtProcUserLogon(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain, HANDLE *phToken)
* Because we have to deal with http://support.microsoft.com/kb/245683
phToken);
if (!fRc)
return VINF_SUCCESS;
while ( pBlock
char *pszEntry;
size_t l;
return rc;
return rc;
static int rtProcEnvironmentCreateFromAccount(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain,
return rc;
static int rtProcCreateAsUserHlp(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszExec, PRTUTF16 pwszCmdLine,
if (!fRc)
bool fFound = false;
NULL,
&cbSid,
NULL,
&sidNameUse);
if (!fRc)
if ( !fRc
&& cbSid > 0)
PSID pSid = (PSID)RTMemAlloc(cbSid * sizeof(wchar_t)); /** @todo r=bird: What's the relationship between wchar_t and PSID? */
AssertPtrReturn(pSid, VERR_NO_MEMORY); /** @todo r=bird: Leaking token handles when we're out of memory... */
if (cchDomain > 0)
AssertPtrReturn(pwszDomain, VERR_NO_MEMORY); /** @todo r=bird: Leaking token handles when we're out of memory... */
pSid,
&cbSid,
static const char * const s_papszProcNames[] =
if (fRc)
#ifdef RT_STRICT
if (!fRc)
AssertMsgFailed(("Unloading user profile failed with error %u (%#x) - Are all handles closed? (dwErr=%u)",
return rc;
RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
AssertReturn(!(fFlags & ~(RTPROC_FLAGS_DETACHED | RTPROC_FLAGS_HIDDEN | RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_SAME_CONTRACT | RTPROC_FLAGS_NO_PROFILE | RTPROC_FLAGS_NO_WINDOW)), VERR_INVALID_PARAMETER);
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);
return VERR_PROCESS_NOT_FOUND;
switch (WaitRc)
case WAIT_OBJECT_0:
if (pProcStatus)
case WAIT_TIMEOUT:
case WAIT_FAILED:
case WAIT_ABANDONED:
AssertFailed();
return rc;
return VINF_SUCCESS;
if (!fRc)
return rc;
BOOL fRc = GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
return dwProcessAffinityMask;