ca0ee85505c252493a3ee53577848ef8939f991bvboxsync/* $Id$ */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync/** @file
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * Guest Control Service: Internal function used by service, Main and testcase.
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync/*
a9749534ba173982f6c3bafe8d51ccd22960e493vboxsync * Copyright (C) 2010-2011 Oracle Corporation
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * available from http://www.virtualbox.org. This file is free software;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * General Public License (GPL) as published by the Free Software
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync/*******************************************************************************
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync* Header Files *
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync*******************************************************************************/
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#define LOG_GROUP LOG_GROUP_HGCM
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <VBox/HostServices/GuestControlSvc.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync/** @todo Remove unused header files below! */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/alloca.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/initterm.h>
4d98012b3229f47c9fb4eb767563359484284077vboxsync#include <iprt/crc.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/ctype.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/env.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/file.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/getopt.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/handle.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/mem.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/message.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/param.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/path.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/pipe.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/poll.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/process.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/stream.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include <iprt/thread.h>
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync#include "gctrl.h"
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsyncnamespace guestControl {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync/**
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * Creates the argument list as an array used for executing a program.
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * @returns VBox status code.
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * @todo
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * @todo Respect spaces when quoting for arguments, e.g. "c:\\program files\\".
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * @todo Handle empty ("") arguments.
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsyncint gctrlPrepareExecArgv(char *pszArgs, void **ppvList, uint32_t *pcbList, uint32_t *pcArgs)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync{
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync char **ppaArg;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync int iArgs;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync int rc = RTGetOptArgvFromString(&ppaArg, &iArgs, pszArgs, NULL);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (RT_SUCCESS(rc))
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync char *pszTemp = NULL;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *pcbList = 0;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync for (int i=0; i<iArgs; i++)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (i > 0) /* Insert space as delimiter. */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync rc = RTStrAAppendN(&pszTemp, " ", 1);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (RT_FAILURE(rc))
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync break;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync else
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync rc = RTStrAAppendN(&pszTemp, ppaArg[i], strlen(ppaArg[i]));
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (RT_FAILURE(rc))
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync break;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTGetOptArgvFree(ppaArg);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (RT_SUCCESS(rc))
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *ppvList = pszTemp;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *pcArgs = iArgs;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *pcbList = strlen(pszTemp) + 1; /* Include zero termination. */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync else
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTStrFree(pszTemp);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync return rc;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync}
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync/**
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * Appends environment variables to the environment block. Each var=value pair is separated
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * by NULL (\0) sequence. The whole block will be stored in one blob and disassembled on the
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * guest side later to fit into the HGCM param structure.
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * @returns VBox status code.
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync * @todo
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync */
11d817ec366e01926a69295682502feb90d1d859vboxsyncint gctrlAddToExecEnvv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync{
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync int rc = VINF_SUCCESS;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync uint32_t cbLen = strlen(pszEnv);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (*ppvList)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync uint32_t cbNewLen = *pcbList + cbLen + 1; /* Include zero termination. */
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync char *pvTmp = (char*)RTMemRealloc(*ppvList, cbNewLen);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (NULL == pvTmp)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync rc = VERR_NO_MEMORY;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync else
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync memcpy(pvTmp + *pcbList, pszEnv, cbLen);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pvTmp[cbNewLen - 1] = '\0'; /* Add zero termination. */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *ppvList = (void**)pvTmp;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync else
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync char *pcTmp;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (RTStrAPrintf(&pcTmp, "%s", pszEnv) > 0)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *ppvList = (void**)pcTmp;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync /* Reset counters. */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *pcEnv = 0;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *pcbList = 0;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (RT_SUCCESS(rc))
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *pcbList += cbLen + 1; /* Include zero termination. */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *pcEnv += 1; /* Increase env pairs count. */
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync return rc;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync}
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync/*
ca0ee85505c252493a3ee53577848ef8939f991bvboxsyncint gctrlAllocateExecBlock(PVBOXGUESTCTRLEXECBLOCK *ppBlock,
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync const char *pszCmd, uint32_t fFlags,
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync uint32_t cArgs, const char * const *papszArgs,
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync uint32_t cEnvVars, const char * const *papszEnv,
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync const char *pszStdIn, const char *pszStdOut, const char *pszStdErr,
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync const char *pszUsername, const char *pszPassword, RTMSINTERVAL cMillies)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync{
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync PVBOXGUESTCTRLEXECBLOCK pNewBlock = (VBOXGUESTCTRLEXECBLOCK*)RTMemAlloc(sizeof(VBOXGUESTCTRLEXECBLOCK));
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync int rc;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (pNewBlock)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *ppBlock = pNewBlock;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync rc = VINF_SUCCESS;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync else
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync rc = VERR_NO_MEMORY;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync return rc;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync}
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsyncint gctrlFreeExecBlock(PVBOXGUESTCTRLEXECBLOCK pBlock)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync{
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync AssertPtr(pBlock);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTStrFree(pBlock->pszCmd);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTMemFree(pBlock->pvArgs);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTMemFree(pBlock->pvEnv);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTStrFree(pBlock->pszStdIn);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTStrFree(pBlock->pszStdOut);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTStrFree(pBlock->pszStdErr);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTStrFree(pBlock->pszUsername);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTStrFree(pBlock->pszPassword);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RT_ZERO(*pBlock);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync return VINF_SUCCESS;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync}
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsyncint gctrlPrepareHostCmdExec(PVBOXHGCMSVCPARM *ppaParms, uint32_t *pcParms,
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync PVBOXGUESTCTRLEXECBLOCK pBlock)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync{
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync AssertPtr(ppaParms);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync AssertPtr(pBlock);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync PVBOXHGCMSVCPARM pNewParms =
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync (VBOXHGCMSVCPARM*)RTMemAlloc(sizeof(VBOXHGCMSVCPARM) * 13);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync int rc;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (pNewParms)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync {
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[0].setUInt32(HOST_EXEC_CMD);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[1].setUInt32(pBlock->u32Flags);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[2].setPointer((void*)pBlock->pszCmd, (uint32_t)strlen(pBlock->pszCmd) + 1);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[3].setUInt32(pBlock->u32Args);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[4].setPointer((void*)pBlock->pvArgs, pBlock->cbArgs);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[5].setUInt32(pBlock->u32EnvVars);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[6].setPointer((void*)pBlock->pvEnv, pBlock->cbEnv);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[7].setPointer((void*)pBlock->pszStdIn, (uint32_t)strlen(pBlock->pszStdIn) + 1);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[8].setPointer((void*)pBlock->pszStdOut, (uint32_t)strlen(pBlock->pszStdOut) + 1);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[9].setPointer((void*)pBlock->pszStdErr, (uint32_t)strlen(pBlock->pszStdErr) + 1);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[10].setPointer((void*)pBlock->pszUsername, (uint32_t)strlen(pBlock->pszUsername) + 1);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[11].setPointer((void*)pBlock->pszPassword, (uint32_t)strlen(pBlock->pszPassword) + 1);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync pNewParms[12].setUInt32(pBlock->cMillies);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *ppaParms = pNewParms;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync rc = VINF_SUCCESS;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync }
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync else
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync rc = VERR_NO_MEMORY;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync if (pcParms)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync *pcParms = 13;
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync return rc;
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync}
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsyncvoid gctrlFreeHostCmd(PVBOXHGCMSVCPARM paParms)
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync{
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync RTMemFree(paParms);
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync}
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync*/
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync}
ca0ee85505c252493a3ee53577848ef8939f991bvboxsync