process-win.cpp revision 35125574a1b91c9941c7069baf8c9f67ce379302
/* $Id$ */
/** @file
* IPRT - Process, Windows.
*/
/*
* Copyright (C) 2006-2010 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP RTLOGGROUP_PROCESS
#include <Windows.h>
#include <process.h>
#include <errno.h>
/*
* This is from Winternl.h. It has been copied here
* because the header does not define a calling convention for
* its prototypes and just assumes that _stdcall is the standard
* calling convention.
*/
typedef struct _PEB
{
typedef struct _PROCESS_BASIC_INFORMATION
{
typedef enum _PROCESSINFOCLASS
{
/** @todo r=michael This function currently does not work correctly if the arguments
contain spaces. */
RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
{
/*
* Validate input.
*/
/* later: path searching. */
/*
* Spawn the child.
*/
/** @todo utf-8 considerations! */
{
if (pProcess)
{
/*
* GetProcessId requires XP SP1 or later
*/
#if defined(RT_ARCH_AMD64)
#else /* !RT_ARCH_AMD64 */
static bool fInitialized = false;
if (!fInitialized)
{
if (hmodKernel32)
fInitialized = true;
}
if (pfnGetProcessId)
{
if (!*pProcess)
{
return rc;
}
}
else
{
/*
* Fall back to the NT api for older versions.
*/
if (Status != 0)
{
int rc = ERROR_INTERNAL_ERROR; /* (we don't have a valid conversion here, but this shouldn't happen anyway.) */
AssertMsgFailed(("failed to get pid from hProcess=%#x rc=%Rrc Status=%#x\n", hProcess, rc, Status));
return rc;
}
}
#endif /* !RT_ARCH_AMD64 */
}
return VINF_SUCCESS;
}
return rc;
}
RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
{
#if 1 /* needs more work... dinner time. */
int rc;
/*
* Input validation
*/
/** @todo search the PATH (add flag for this). */
/*
* Get the file descriptors for the handles we've been passed.
*
* It seems there is no point in trying to convince a child process's CRT
* that any of the standard file handles is non-TEXT. So, we don't...
*/
#if 1 /* The CRT should keep the standard handles up to date. */
#else
#endif
for (int i = 0; i < 3; i++)
{
if (paHandles[i])
{
{
case RTHANDLETYPE_FILE:
break;
case RTHANDLETYPE_PIPE:
break;
//case RTHANDLETYPE_SOCKET:
// *aphStds[i] = paHandles[i]->u.hSocket != NIL_RTSOCKET
// ? (HANDLE)RTTcpToNative(paHandles[i]->u.hSocket)
// : INVALID_HANDLE_VALUE;
// break;
default:
}
}
}
/*
* Create the environment block, command line and convert the executable
* name.
*/
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
if (pszAsUser)
{
/** @todo - Maybe use CreateProcessWithLoginW? That'll require a password, but
* we may need that anyway because it looks like LogonUserW is the only
* way to get a hToken. FIXME */
}
if (RT_SUCCESS(rc))
{
/*
* Get going...
*/
if (hToken == INVALID_HANDLE_VALUE)
NULL, /* pProcessAttributes */
NULL, /* pThreadAttributes */
TRUE, /* fInheritHandles */
CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
NULL, /* pCurrentDirectory */
&ProcInfo);
else
NULL, /* pProcessAttributes */
NULL, /* pThreadAttributes */
TRUE, /* fInheritHandles */
CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
NULL, /* pCurrentDirectory */
&ProcInfo);
if (fRc)
{
if (phProcess)
{
/** @todo Remember the process handle and pick it up in RTProcWait. */
}
else
rc = VINF_SUCCESS;
}
else
if (hToken != INVALID_HANDLE_VALUE)
}
}
}
}
return rc;
#else
return VERR_NOT_IMPLEMENTED;
#endif
}
{
AssertReturn(!(fFlags & ~(RTPROCWAIT_FLAGS_BLOCK | RTPROCWAIT_FLAGS_NOBLOCK)), VERR_INVALID_PARAMETER);
/*
* Open the process.
*/
{
/*
* Wait for it to terminate.
*/
while (WaitRc == WAIT_IO_COMPLETION)
switch (WaitRc)
{
/*
* It has terminated.
*/
case WAIT_OBJECT_0:
{
{
/** @todo the exit code can be special statuses. */
if (pProcStatus)
{
}
return VINF_SUCCESS;
}
break;
}
/*
* It hasn't terminated just yet.
*/
case WAIT_TIMEOUT:
return VERR_PROCESS_RUNNING;
/*
* Something went wrong...
*/
case WAIT_FAILED:
break;
case WAIT_ABANDONED:
AssertFailed();
return VERR_GENERAL_FAILURE;
default:
return VERR_GENERAL_FAILURE;
}
}
return RTErrConvertFromWin32(dwErr);
}
{
/** @todo this isn't quite right. */
}
{
{
if (fRc)
return VINF_SUCCESS;
}
return RTErrConvertFromWin32(dwErr);
}
{
BOOL fRc = GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
return dwProcessAffinityMask;
}