GuestImpl.cpp revision d192fe1aff95cbe0e50f3b2974225fc4b4969fd2
/* $Id$ */
/** @file
*
* VirtualBox COM class implementation
*/
/*
* Copyright (C) 2006-2008 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.
*
* 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.
*/
#include "GuestImpl.h"
#include "Global.h"
#include "ConsoleImpl.h"
#include "ProgressImpl.h"
#include "VMMDev.h"
#include "AutoCaller.h"
#include "Logging.h"
#ifdef VBOX_WITH_GUEST_CONTROL
#endif
// defines
/////////////////////////////////////////////////////////////////////////////
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
{
return S_OK;
}
void Guest::FinalRelease()
{
uninit ();
}
// public methods only for internal purposes
/////////////////////////////////////////////////////////////////////////////
/**
* Initializes the guest object.
*/
{
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
/* mData.mAdditionsActive is FALSE */
/* Confirm a successful initialization when it's the case */
else
mMemoryBalloonSize = 0; /* Default is no ballooning */
mStatUpdateInterval = 0; /* Default is not to report guest statistics at all */
/* Clear statistics. */
for (unsigned i = 0 ; i < GUESTSTATTYPE_MAX; i++)
mCurrentGuestStat[i] = 0;
#ifdef VBOX_WITH_GUEST_CONTROL
/* Init the context ID counter at 1000. */
mNextContextID = 1000;
#endif
return S_OK;
}
/**
* Uninitializes the instance and sets the ready flag to FALSE.
* Called either from FinalRelease() or by the parent when it gets destroyed.
*/
{
LogFlowThisFunc(("\n"));
#ifdef VBOX_WITH_GUEST_CONTROL
/* Clean up callback data. */
#endif
/* Enclose the state transition Ready->InUninit->NotReady */
AutoUninitSpan autoUninitSpan(this);
if (autoUninitSpan.uninitDone())
return;
}
// IGuest properties
/////////////////////////////////////////////////////////////////////////////
{
AutoCaller autoCaller(this);
// redirect the call to IMachine if no additions are installed
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
{
/* forward the information to the VMM device */
if (vmmDev)
}
return ret;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
/* forward the information to the VMM device */
if (vmmDev)
return S_OK;
}
{
AutoCaller autoCaller(this);
{
*aMemFreeTotal = 0;
if (rc == VINF_SUCCESS)
{
}
}
else
*aMemFreeTotal = 0;
return S_OK;
}
{
AutoCaller autoCaller(this);
if (enmType >= GUESTSTATTYPE_MAX)
return E_INVALIDARG;
return S_OK;
}
{
AutoCaller autoCaller(this);
/* forward the information to the VMM device */
if (vmmDev)
{
if (!aAllowInteractiveLogon)
return S_OK;
}
return setError(VBOX_E_VM_ERROR,
tr("VMM device is not available (is the VM running?)"));
}
#ifdef VBOX_WITH_GUEST_CONTROL
/**
* Creates the argument list as an array used for executing a program.
*
* @returns VBox status code.
*
* @todo
*
* @todo Respect spaces when quoting for arguments, e.g. "c:\\program files\\".
* @todo Handle empty ("") argguments.
*/
int Guest::prepareExecuteArgs(const char *pszArgs, void **ppvList, uint32_t *pcbList, uint32_t *pcArgs)
{
char **ppaArg;
int iArgs;
if (RT_SUCCESS(rc))
{
*pcbList = 0;
for (int i=0; i<iArgs; i++)
{
if (i > 0) /* Insert space as delimiter. */
if (RT_FAILURE(rc))
break;
else
{
if (RT_FAILURE(rc))
break;
}
}
if (RT_SUCCESS(rc))
{
if (pszTemp)
}
else
}
return rc;
}
/**
* Appends environment variables to the environment block. Each var=value pair is separated
* by NULL (\0) sequence. The whole block will be stored in one blob and disassembled on the
* guest side later to fit into the HGCM param structure.
*
* @returns VBox status code.
*
* @todo
*
*/
int Guest::prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv)
{
int rc = VINF_SUCCESS;
if (*ppvList)
{
{
rc = VERR_NO_MEMORY;
}
else
{
}
}
else
{
char *pcTmp;
{
/* Reset counters. */
*pcEnv = 0;
*pcbList = 0;
}
}
if (RT_SUCCESS(rc))
{
}
return rc;
}
/**
* Static callback function for receiving updates on guest control commands
* from the guest. Acts as a dispatcher for the actual class instance.
*
* @returns VBox status code.
*
* @todo
*
*/
void *pvParms,
{
using namespace guestControl;
/*
* No locking, as this is purely a notification which does not make any
* changes to the object state.
*/
LogFlowFunc(("pvExtension = %p, u32Function = %d, pvParms = %p, cbParms = %d\n",
int rc = VINF_SUCCESS;
if (u32Function == GUEST_EXEC_SEND_STATUS)
{
LogFlowFunc(("GUEST_EXEC_SEND_STATUS\n"));
}
else
return rc;
}
/* Notifier function for control execution stuff. */
{
int rc = VINF_SUCCESS;
{
/* @todo Copy void* buffer contents! */
/* Do progress handling. */
{
case PROC_STS_TEN: /* Terminated normally. */
case PROC_STS_TEA: /* Terminated abnormally. */
case PROC_STS_TES: /* Terminated through signal. */
break;
default:
break;
}
}
return rc;
}
{
{
return (it);
}
return it;
}
{
{
/* Notify outstanding waits for progress ... */
{
}
}
}
{
/** @todo Add value clamping! */
return uNewContext;
}
#endif /* VBOX_WITH_GUEST_CONTROL */
{
#ifndef VBOX_WITH_GUEST_CONTROL
#else /* VBOX_WITH_GUEST_CONTROL */
using namespace guestControl;
if (aFlags != 0) /* Flags are not supported at the moment. */
return E_INVALIDARG;
try
{
AutoCaller autoCaller(this);
/*
* Create progress object.
*/
{
//static_cast<IConsole *>(this),
FALSE);
}
/*
* Prepare process execution.
*/
int vrc = VINF_SUCCESS;
/* Adjust timeout */
if (aTimeoutMS == 0)
/* Prepare arguments. */
if(uNumArgs > 0)
{
}
if (RT_SUCCESS(vrc))
{
uint32_t uContextID = 0;
if (uNumArgs > 0)
if (RT_SUCCESS(vrc))
{
/* Prepare environment. */
{
if (RT_FAILURE(vrc))
break;
}
if (RT_SUCCESS(vrc))
{
Assert(uContextID > 0);
int i = 0;
/* Forward the information to the VMM device. */
if (vmmDev)
{
LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
i, paParms);
}
}
}
if (RT_SUCCESS(vrc))
{
/*
* Wait for the HGCM low level callback until the process
* has been started (or something went wrong). This is necessary to
* get the PID.
*/
do
{
unsigned cMsWait;
if (aTimeoutMS == RT_INDEFINITE_WAIT)
cMsWait = 1000;
else
{
if (cMsElapsed >= aTimeoutMS)
break; /* timed out */
}
RTThreadSleep(100);
/* Did we get some status? */
{
{
case PROC_STS_STARTED:
break;
case PROC_STS_ERROR:
break;
default:
break;
}
}
else /* If callback not called within time ... well, that's a timeout! */
vrc = VERR_TIMEOUT;
/*
* Do *not* remove the callback yet - we might wait with the IProgress object on something
* else (like end of process) ...
*/
if (RT_FAILURE(vrc))
{
{
}
else if (vrc == VERR_BAD_EXE_FORMAT)
{
}
else if (vrc == VERR_LOGON_FAILURE)
{
}
else if (vrc == VERR_TIMEOUT)
{
}
else
{
}
}
else
{
/* Return the progress to the caller. */
}
}
else
{
/* HGCM call went wrong. */
}
for (unsigned i = 0; i < uNumArgs; i++)
}
}
{
rc = E_OUTOFMEMORY;
}
return rc;
#endif /* VBOX_WITH_GUEST_CONTROL */
}
{
#ifndef VBOX_WITH_GUEST_CONTROL
#else /* VBOX_WITH_GUEST_CONTROL */
using namespace guestControl;
return S_OK;
#endif
}
// public methods only for internal purposes
/////////////////////////////////////////////////////////////////////////////
{
AutoCaller autoCaller(this);
/* Older Additions didn't have this finer grained capability bit,
* so enable it by default. Newer Additions will disable it immediately
* if relevant. */
}
{
AutoCaller autoCaller(this);
}
{
AutoCaller autoCaller(this);
}
/* vi: set tabstop=4 shiftwidth=4 expandtab: */