GuestProcessImpl.cpp revision cd4a988686e583349e3326d6316d68f1657b8f34
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* $Id$ */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/** @file
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * VirtualBox Main - Guest process handling.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Copyright (C) 2012-2013 Oracle Corporation
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * available from http://www.virtualbox.org. This file is free software;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * you can redistribute it and/or modify it under the terms of the GNU
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * General Public License (GPL) as published by the Free Software
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/**
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Locking rules:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * - When the main dispatcher (callbackDispatcher) is called it takes the
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * WriteLock while dispatching to the various on* methods.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * - All other outer functions (accessible by Main) must not own a lock
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * while waiting for a callback or for an event.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * - Only keep Read/WriteLocks as short as possible and only when necessary.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/*******************************************************************************
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync* Header Files *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync*******************************************************************************/
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include "GuestProcessImpl.h"
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include "GuestSessionImpl.h"
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include "GuestCtrlImplPrivate.h"
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include "ConsoleImpl.h"
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include "VirtualBoxErrorInfoImpl.h"
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include "Global.h"
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include "AutoCaller.h"
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include "VBoxEvents.h"
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include <memory> /* For auto_ptr. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include <iprt/asm.h>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include <iprt/cpp/utils.h> /* For unconst(). */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include <iprt/getopt.h>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include <VBox/com/listeners.h>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include <VBox/com/array.h>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifdef LOG_GROUP
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync #undef LOG_GROUP
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#include <VBox/log.h>
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncclass GuestProcessTask
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpublic:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestProcessTask(GuestProcess *pProcess)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync : mProcess(pProcess),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mRC(VINF_SUCCESS) { }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync virtual ~GuestProcessTask(void) { }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int rc(void) const { return mRC; }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync bool isOk(void) const { return RT_SUCCESS(mRC); }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync const ComObjPtr<GuestProcess> &Process(void) const { return mProcess; }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncprotected:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync const ComObjPtr<GuestProcess> mProcess;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int mRC;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync};
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncclass GuestProcessStartTask : public GuestProcessTask
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpublic:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestProcessStartTask(GuestProcess *pProcess)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync : GuestProcessTask(pProcess) { }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync};
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/**
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Internal listener class to serve events in an
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * active manner, e.g. without polling delays.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncclass GuestProcessListener
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncpublic:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestProcessListener(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT init(GuestProcess *pProcess)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mProcess = pProcess;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync void uninit(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mProcess.setNull();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (aType)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VBoxEventType_OnGuestProcessStateChanged:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VBoxEventType_OnGuestProcessInputNotify:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VBoxEventType_OnGuestProcessOutput:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(!mProcess.isNull());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int rc2 = mProcess->signalWaitEvents(aType, aEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifdef DEBUG_andy
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Signalling events of type=%ld, process=%p resulted in rc=%Rrc\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync aType, mProcess, rc2));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertMsgFailed(("Unhandled event %ld\n", aType));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncprivate:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComObjPtr<GuestProcess> mProcess;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync};
f9a51917495bc8ba8b60632219652a7b122c1190vboxsynctypedef ListenerImpl<GuestProcessListener, GuestProcess*> GuestProcessListenerImpl;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncVBOX_LISTENER_DECLARE(GuestProcessListenerImpl)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync// constructor / destructor
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/////////////////////////////////////////////////////////////////////////////
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncDEFINE_EMPTY_CTOR_DTOR(GuestProcess)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncHRESULT GuestProcess::FinalConstruct(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return BaseFinalConstruct();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid GuestProcess::FinalRelease(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uninit();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync BaseFinalRelease();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncLeave();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync// public initializer/uninitializer for internal purposes only
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/////////////////////////////////////////////////////////////////////////////
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::init(Console *aConsole, GuestSession *aSession,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ULONG aProcessID, const GuestProcessStartupInfo &aProcInfo)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("aConsole=%p, aSession=%p, aProcessID=%RU32\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync aConsole, aSession, aProcessID));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(aConsole, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(aSession, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Enclose the state transition NotReady->InInit->Ready. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoInitSpan autoInitSpan(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync autoInitSpan.setSucceeded();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = bindToSession(aConsole, aSession, aProcessID /* Object ID */);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = unconst(mEventSource).createObject();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(hr))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NO_MEMORY;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = mEventSource->init(static_cast<IGuestProcess*>(this));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(hr))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_COM_UNEXPECTED;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync try
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestProcessListener *pListener = new GuestProcessListener();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComObjPtr<GuestProcessListenerImpl> thisListener;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = thisListener.createObject();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (SUCCEEDED(hr))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = thisListener->init(pListener, this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (SUCCEEDED(hr))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync com::SafeArray <VBoxEventType_T> eventTypes;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessInputNotify);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessOutput);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = mEventSource->RegisterListener(thisListener,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComSafeArrayAsInParam(eventTypes),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync TRUE /* Active listener */);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (SUCCEEDED(hr))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = baseInit();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mLocalListener = thisListener;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_COM_UNEXPECTED;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_COM_UNEXPECTED;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync catch(std::bad_alloc &)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NO_MEMORY;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess = aProcInfo;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mExitCode = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mPID = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mRC = VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mStatus = ProcessStatus_Undefined;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Everything else will be set by the actual starting routine. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Confirm a successful initialization when it's the case. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync autoInitSpan.setSucceeded();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync autoInitSpan.setFailed();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/**
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Uninitializes the instance.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Called from FinalRelease().
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncvoid GuestProcess::uninit(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Enclose the state transition Ready->InUninit->NotReady. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoUninitSpan autoUninitSpan(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (autoUninitSpan.uninitDone())
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("mCmd=%s, PID=%RU32\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess.mCommand.c_str(), mData.mPID));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Terminate process if not already done yet. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int guestRc = VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = terminateProcess(30 * 1000, &guestRc); /** @todo Make timeouts configurable. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Note: Don't return here yet; first uninit all other stuff in
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * case of failure. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifdef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync baseUninit();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mEventSource->UnregisterListener(mLocalListener);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mLocalListener.setNull();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync unconst(mEventSource).setNull();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc, guestRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync// implementation of public getters/setters for attributes
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/////////////////////////////////////////////////////////////////////////////
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::COMGETTER(Arguments)(ComSafeArrayOut(BSTR, aArguments))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutSafeArrayPointerValid(aArguments);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync com::SafeArray<BSTR> collection(mData.mProcess.mArguments.size());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync size_t s = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (ProcessArguments::const_iterator it = mData.mProcess.mArguments.begin();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync it != mData.mProcess.mArguments.end();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync it++, s++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Bstr tmp = *it;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync tmp.cloneTo(&collection[s]);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync collection.detachTo(ComSafeArrayOutArg(aArguments));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::COMGETTER(Environment)(ComSafeArrayOut(BSTR, aEnvironment))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutSafeArrayPointerValid(aEnvironment);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync com::SafeArray<BSTR> arguments(mData.mProcess.mEnvironment.Size());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (size_t i = 0; i < arguments.size(); i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Bstr tmp = mData.mProcess.mEnvironment.Get(i);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync tmp.cloneTo(&arguments[i]);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync arguments.detachTo(ComSafeArrayOutArg(aEnvironment));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::COMGETTER(EventSource)(IEventSource ** aEventSource)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutPointerValid(aEventSource);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync // no need to lock - lifetime constant
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mEventSource.queryInterfaceTo(aEventSource);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(S_OK);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::COMGETTER(ExecutablePath)(BSTR *aExecutablePath)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutPointerValid(aExecutablePath);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess.mCommand.cloneTo(aExecutablePath);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::COMGETTER(ExitCode)(LONG *aExitCode)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutPointerValid(aExitCode);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *aExitCode = mData.mExitCode;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::COMGETTER(Name)(BSTR *aName)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutPointerValid(aName);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess.mName.cloneTo(aName);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::COMGETTER(PID)(ULONG *aPID)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutPointerValid(aPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *aPID = mData.mPID;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::COMGETTER(Status)(ProcessStatus_T *aStatus)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *aStatus = mData.mStatus;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync// private methods
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/////////////////////////////////////////////////////////////////////////////
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifdef DEBUG
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("uPID=%RU32, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mPID, pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (pCbCtx->uFunction)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case GUEST_DISCONNECTED:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = onGuestDisconnected(pCbCtx, pSvcCb);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case GUEST_EXEC_STATUS:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = onProcessStatusChange(pCbCtx, pSvcCb);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case GUEST_EXEC_OUTPUT:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = onProcessOutput(pCbCtx, pSvcCb);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case GUEST_EXEC_INPUT_STATUS:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = onProcessInputStatus(pCbCtx, pSvcCb);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Silently ignore not implemented functions. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NOT_SUPPORTED;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifdef DEBUG
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/**
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Checks if the current assigned PID matches another PID (from a callback).
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * In protocol v1 we don't have the possibility to terminate/kill
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * processes so it can happen that a formerly started process A
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * (which has the context ID 0 (session=0, process=0, count=0) will
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * send a delayed message to the host if this process has already
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * been discarded there and the same context ID was reused by
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * a process B. Process B in turn then has a different guest PID.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * @return IPRT status code.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * @param uPID PID to check.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncinline int GuestProcess::checkPID(uint32_t uPID)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Was there a PID assigned yet? */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mData.mPID)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mSession->getProtocolVersion() < 2)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Simply ignore the stale requests. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return (mData.mPID == uPID)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ? VINF_SUCCESS : VERR_NOT_FOUND;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef DEBUG_andy
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* This should never happen! */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertReleaseMsg(mData.mPID == uPID, ("Unterminated guest process (guest PID %RU32) sent data to a newly started process (host PID %RU32)\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uPID, mData.mPID));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* static */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncUtf8Str GuestProcess::guestErrorToString(int guestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Utf8Str strError;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (guestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_FILE_NOT_FOUND: /* This is the most likely error. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("The specified file was not found on guest"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_INVALID_VM_HANDLE:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("VMM device is not available (is the VM running?)"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_HGCM_SERVICE_NOT_FOUND:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("The guest execution service is not available"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_PATH_NOT_FOUND:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("Could not resolve path to specified file was not found on guest"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_BAD_EXE_FORMAT:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("The specified file is not an executable format on guest"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_AUTHENTICATION_FAILURE:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("The specified user was not able to logon on guest"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_INVALID_NAME:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("The specified file is an invalid name"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_TIMEOUT:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("The guest did not respond within time"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_CANCELLED:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("The execution operation was canceled"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_PERMISSION_DENIED:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("Invalid user/password credentials"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_MAX_PROCS_REACHED:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("Maximum number of concurrent guest processes has been reached"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_NOT_FOUND:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt(tr("The guest execution service is not ready (yet)"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync strError += Utf8StrFmt("%Rrc", guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return strError;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncinline bool GuestProcess::isAlive(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return ( mData.mStatus == ProcessStatus_Started
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || mData.mStatus == ProcessStatus_Paused
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || mData.mStatus == ProcessStatus_Terminating);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncbool GuestProcess::isReady(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mData.mStatus == ProcessStatus_Started)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(mData.mPID); /* PID must not be 0. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return true;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return false;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::onGuestDisconnected(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("uPID=%RU32\n", mData.mPID));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = setProcessStatus(ProcessStatus_Down, VINF_SUCCESS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::onProcessInputStatus(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pCallback is optional. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pSvcCbData->mParms < 5)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VERR_INVALID_PARAMETER;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CALLBACKDATA_PROC_INPUT dataCb;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pSvcCb->mpaParms[0] always contains the context ID. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = pSvcCbData->mpaParms[1].getUInt32(&dataCb.uPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pSvcCbData->mpaParms[2].getUInt32(&dataCb.uStatus);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pSvcCbData->mpaParms[3].getUInt32(&dataCb.uFlags);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pSvcCbData->mpaParms[4].getUInt32(&dataCb.uProcessed);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("uPID=%RU32, uStatus=%RU32, uFlags=%RI32, cbProcessed=%RU32\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync dataCb.uPID, dataCb.uStatus, dataCb.uFlags, dataCb.uProcessed));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = checkPID(dataCb.uPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessInputStatus_T inputStatus = ProcessInputStatus_Undefined;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (dataCb.uStatus)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case INPUT_STS_WRITTEN:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync inputStatus = ProcessInputStatus_Written;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case INPUT_STS_ERROR:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync inputStatus = ProcessInputStatus_Broken;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case INPUT_STS_TERMINATED:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync inputStatus = ProcessInputStatus_Broken;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case INPUT_STS_OVERFLOW:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync inputStatus = ProcessInputStatus_Overflow;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case INPUT_STS_UNDEFINED:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Fall through is intentional. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertMsg(!dataCb.uProcessed, ("Processed data is not 0 in undefined input state\n"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (inputStatus != ProcessInputStatus_Undefined)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fireGuestProcessInputNotifyEvent(mEventSource, mSession, this,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mPID, 0 /* StdIn */, dataCb.uProcessed, inputStatus);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::onProcessNotifyIO(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VERR_NOT_IMPLEMENTED;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::onProcessStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pSvcCbData->mParms < 5)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VERR_INVALID_PARAMETER;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CALLBACKDATA_PROC_STATUS dataCb;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pSvcCb->mpaParms[0] always contains the context ID. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = pSvcCbData->mpaParms[1].getUInt32(&dataCb.uPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pSvcCbData->mpaParms[2].getUInt32(&dataCb.uStatus);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pSvcCbData->mpaParms[3].getUInt32(&dataCb.uFlags);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pSvcCbData->mpaParms[4].getPointer(&dataCb.pvData, &dataCb.cbData);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("uPID=%RU32, uStatus=%RU32, uFlags=%RU32\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync dataCb.uPID, dataCb.uStatus, dataCb.uFlags));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = checkPID(dataCb.uPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessStatus_T procStatus = ProcessStatus_Undefined;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int procRc = VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (dataCb.uStatus)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PROC_STS_STARTED:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procStatus = ProcessStatus_Started;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mPID = dataCb.uPID; /* Set the process PID. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PROC_STS_TEN:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procStatus = ProcessStatus_TerminatedNormally;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mExitCode = dataCb.uFlags; /* Contains the exit code. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PROC_STS_TES:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procStatus = ProcessStatus_TerminatedSignal;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mExitCode = dataCb.uFlags; /* Contains the signal. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PROC_STS_TEA:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procStatus = ProcessStatus_TerminatedAbnormally;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PROC_STS_TOK:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procStatus = ProcessStatus_TimedOutKilled;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PROC_STS_TOA:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procStatus = ProcessStatus_TimedOutAbnormally;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PROC_STS_DWN:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procStatus = ProcessStatus_Down;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PROC_STS_ERROR:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procRc = dataCb.uFlags; /* mFlags contains the IPRT error sent from the guest. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procStatus = ProcessStatus_Error;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case PROC_STS_UNDEFINED:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Silently skip this request. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync procStatus = ProcessStatus_Undefined;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Got rc=%Rrc, procSts=%ld, procRc=%Rrc\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc, procStatus, procRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Set the process status. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int rc2 = setProcessStatus(procStatus, procRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = rc2;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::onProcessOutput(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pSvcCbData->mParms < 5)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VERR_INVALID_PARAMETER;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CALLBACKDATA_PROC_OUTPUT dataCb;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pSvcCb->mpaParms[0] always contains the context ID. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = pSvcCbData->mpaParms[1].getUInt32(&dataCb.uPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pSvcCbData->mpaParms[2].getUInt32(&dataCb.uHandle);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pSvcCbData->mpaParms[3].getUInt32(&dataCb.uFlags);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pSvcCbData->mpaParms[4].getPointer(&dataCb.pvData, &dataCb.cbData);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRCReturn(vrc, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("uPID=%RU32, uHandle=%RU32, uFlags=%RI32, pvData=%p, cbData=%RU32\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync dataCb.uPID, dataCb.uHandle, dataCb.uFlags, dataCb.pvData, dataCb.cbData));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = checkPID(dataCb.uPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync com::SafeArray<BYTE> data((size_t)dataCb.cbData);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (dataCb.cbData)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync data.initFrom((BYTE*)dataCb.pvData, dataCb.cbData);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fireGuestProcessOutputEvent(mEventSource, mSession, this,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mPID, dataCb.uHandle, dataCb.cbData, ComSafeArrayAsInParam(data));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::readData(uint32_t uHandle, uint32_t uSize, uint32_t uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync void *pvData, size_t cbData, uint32_t *pcbRead, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("uPID=%RU32, uHandle=%RU32, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%RU32, pGuestRc=%p\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mPID, uHandle, uSize, uTimeoutMS, pvData, cbData, pGuestRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertReturn(uSize, VERR_INVALID_PARAMETER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pvData, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertReturn(cbData >= uSize, VERR_INVALID_PARAMETER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pcbRead is optional. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ( mData.mStatus != ProcessStatus_Started
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Skip reading if the process wasn't started with the appropriate
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * flags. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || ( ( uHandle == OUTPUT_HANDLE_ID_STDOUT
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || uHandle == OUTPUT_HANDLE_ID_STDOUT_DEPRECATED)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && !(mData.mProcess.mFlags & ProcessCreateFlag_WaitForStdOut))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || ( uHandle == OUTPUT_HANDLE_ID_STDERR
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && !(mData.mProcess.mFlags & ProcessCreateFlag_WaitForStdErr))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync )
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pcbRead)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *pcbRead = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *pGuestRc = VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VINF_SUCCESS; /* Nothing to read anymore. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestWaitEvent *pEvent = NULL;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync std::list < VBoxEventType_T > eventTypes;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync try
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * On Guest Additions < 4.3 there is no guarantee that the process status
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * change arrives *after* the output event, e.g. if this was the last output
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * block being read and the process will report status "terminate".
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * So just skip checking for process status change and only wait for the
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * output event.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mSession->getProtocolVersion() >= 2)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessOutput);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = registerWaitEvent(eventTypes, &pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync catch (std::bad_alloc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NO_MEMORY;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync VBOXHGCMSVCPARM paParms[8];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int i = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(pEvent->ContextID());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(mData.mPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(uHandle);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(0 /* Flags, none set yet. */);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync alock.release(); /* Drop the write lock before sending. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = sendCommand(HOST_EXEC_GET_OUTPUT, i, paParms);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = waitForOutput(pEvent, uHandle, uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pvData, cbData, pcbRead);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync unregisterWaitEvent(pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* Does not do locking; caller is responsible for that! */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::setProcessStatus(ProcessStatus_T procStatus, int procRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("oldStatus=%ld, newStatus=%ld, procRc=%Rrc\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mStatus, procStatus, procRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (procStatus == ProcessStatus_Error)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertMsg(RT_FAILURE(procRc), ("Guest rc must be an error (%Rrc)\n", procRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Do not allow overwriting an already set error. If this happens
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * this means we forgot some error checking/locking somewhere. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync //AssertMsg(RT_SUCCESS(mData.mRC), ("Guest rc already set (to %Rrc)\n", mData.mRC));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertMsg(RT_SUCCESS(procRc), ("Guest rc must not be an error (%Rrc)\n", procRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mData.mStatus != procStatus) /* Was there a process status change? */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mStatus = procStatus;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mRC = procRc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComObjPtr<VirtualBoxErrorInfo> errorInfo;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr = errorInfo.createObject();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComAssertComRC(hr);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(mData.mRC))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int rc2 = errorInfo->initEx(VBOX_E_IPRT_ERROR, mData.mRC,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync COM_IIDOF(IGuestProcess), getComponentName(),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync guestErrorToString(mData.mRC));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRC(rc2);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fireGuestProcessStateChangedEvent(mEventSource, mSession, this,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mPID, mData.mStatus, errorInfo);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* static */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncHRESULT GuestProcess::setErrorExternal(VirtualBoxBase *pInterface, int guestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(pInterface);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return pInterface->setError(VBOX_E_IPRT_ERROR, GuestProcess::guestErrorToString(guestRc).c_str());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::startProcess(uint32_t uTimeoutMS, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("uTimeoutMS=%RU32, procCmd=%s, procTimeoutMS=%RU32, procFlags=%x\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uTimeoutMS, mData.mProcess.mCommand.c_str(), mData.mProcess.mTimeoutMS, mData.mProcess.mFlags));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Wait until the caller function (if kicked off by a thread)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * has returned and continue operation. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mStatus = ProcessStatus_Starting;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestWaitEvent *pEvent = NULL;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync std::list < VBoxEventType_T > eventTypes;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync try
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = registerWaitEvent(eventTypes, &pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync catch (std::bad_alloc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NO_MEMORY;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestSession *pSession = mSession;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(pSession);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync const GuestCredentials &sessionCreds = pSession->getCredentials();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Prepare arguments. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync char *pszArgs = NULL;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync size_t cArgs = mData.mProcess.mArguments.size();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (cArgs >= UINT32_MAX)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_BUFFER_OVERFLOW;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ( RT_SUCCESS(vrc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && cArgs)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync char **papszArgv = (char**)RTMemAlloc((cArgs + 1) * sizeof(char*));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertReturn(papszArgv, VERR_NO_MEMORY);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (size_t i = 0; i < cArgs && RT_SUCCESS(vrc); i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync const char *pszCurArg = mData.mProcess.mArguments[i].c_str();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(pszCurArg);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = RTStrDupEx(&papszArgv[i], pszCurArg);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync papszArgv[cArgs] = NULL;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = RTGetOptArgvToString(&pszArgs, papszArgv, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (papszArgv)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync size_t i = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync while (papszArgv[i])
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync RTStrFree(papszArgv[i++]);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync RTMemFree(papszArgv);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Calculate arguments size (in bytes). */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync size_t cbArgs = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Prepare environment. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync void *pvEnv = NULL;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync size_t cbEnv = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = mData.mProcess.mEnvironment.BuildEnvironmentBlock(&pvEnv, &cbEnv, NULL /* cEnv */);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(mSession);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t uProtocol = mSession->getProtocolVersion();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Prepare HGCM call. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync VBOXHGCMSVCPARM paParms[16];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int i = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(pEvent->ContextID());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setPointer((void*)mData.mProcess.mCommand.c_str(),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (ULONG)mData.mProcess.mCommand.length() + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(mData.mProcess.mFlags);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32((uint32_t)mData.mProcess.mArguments.size());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setPointer((void*)pszArgs, (uint32_t)cbArgs);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32((uint32_t)mData.mProcess.mEnvironment.Size());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32((uint32_t)cbEnv);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setPointer((void*)pvEnv, (uint32_t)cbEnv);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (uProtocol < 2)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* In protocol v1 (VBox < 4.3) the credentials were part of the execution
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * call. In newer protocols these credentials are part of the opened guest
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * session, so not needed anymore here. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setPointer((void*)sessionCreds.mUser.c_str(), (ULONG)sessionCreds.mUser.length() + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setPointer((void*)sessionCreds.mPassword.c_str(), (ULONG)sessionCreds.mPassword.length() + 1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * If the WaitForProcessStartOnly flag is set, we only want to define and wait for a timeout
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * until the process was started - the process itself then gets an infinite timeout for execution.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * This is handy when we want to start a process inside a worker thread within a certain timeout
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * but let the started process perform lengthly operations then.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mData.mProcess.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(UINT32_MAX /* Infinite timeout */);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(mData.mProcess.mTimeoutMS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (uProtocol >= 2)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(mData.mProcess.mPriority);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* CPU affinity: We only support one CPU affinity block at the moment,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * so that makes up to 64 CPUs total. This can be more in the future. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(1);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* The actual CPU affinity blocks. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setPointer((void*)&mData.mProcess.mAffinity, sizeof(mData.mProcess.mAffinity));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync alock.release(); /* Drop the write lock before sending. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = sendCommand(HOST_EXEC_CMD, i, paParms);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int rc2 = setProcessStatus(ProcessStatus_Error, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRC(rc2);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestEnvironment::FreeEnvironmentBlock(pvEnv);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pszArgs)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync RTStrFree(pszArgs);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = waitForStatusChange(pEvent, uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync NULL /* Process status */, pGuestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync unregisterWaitEvent(pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::startProcessAsync(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync try
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Asynchronously start the process on the guest by kicking off a
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * worker thread. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync std::auto_ptr<GuestProcessStartTask> pTask(new GuestProcessStartTask(this));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertReturn(pTask->isOk(), pTask->rc());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = RTThreadCreate(NULL, GuestProcess::startProcessThread,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync (void *)pTask.get(), 0,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync RTTHREADTYPE_MAIN_WORKER, 0,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync "gctlPrcStart");
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pTask is now owned by startProcessThread(), so release it. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pTask.release();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync catch(std::bad_alloc &)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NO_MEMORY;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* static */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncDECLCALLBACK(int) GuestProcess::startProcessThread(RTTHREAD Thread, void *pvUser)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFunc(("pvUser=%p\n", pvUser));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync std::auto_ptr<GuestProcessStartTask> pTask(static_cast<GuestProcessStartTask*>(pvUser));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(pTask.get());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync const ComObjPtr<GuestProcess> pProcess(pTask->Process());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(!pProcess.isNull());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(pProcess);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = pProcess->startProcess(30 * 1000 /* 30s timeout */,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync NULL /* Guest rc, ignored */);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Nothing to do here anymore. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::terminateProcess(uint32_t uTimeoutMS, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pGuestRc is optional. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("uTimeoutMS=%RU32\n", uTimeoutMS));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mData.mStatus != ProcessStatus_Started)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Process not started (yet), nothing to terminate\n"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VINF_SUCCESS; /* Nothing to do (anymore). */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(mSession);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Note: VBox < 4.3 (aka protocol version 1) does not
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * support this, so just skip. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mSession->getProtocolVersion() < 2)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NOT_SUPPORTED;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestWaitEvent *pEvent = NULL;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync std::list < VBoxEventType_T > eventTypes;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync try
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = registerWaitEvent(eventTypes, &pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync catch (std::bad_alloc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NO_MEMORY;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync VBOXHGCMSVCPARM paParms[4];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int i = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(pEvent->ContextID());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(mData.mPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync alock.release(); /* Drop the write lock before sending. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = sendCommand(HOST_EXEC_TERMINATE, i, paParms);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = waitForStatusChange(pEvent, uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync NULL /* ProcessStatus */, pGuestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync unregisterWaitEvent(pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* static */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncProcessWaitResult_T GuestProcess::waitFlagsToResultEx(uint32_t fWaitFlags,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessStatus_T procStatus, uint32_t uProcFlags,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t uProtocol)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessWaitResult_T waitResult = ProcessWaitResult_None;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ( (fWaitFlags & ProcessWaitForFlag_Terminate)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || (fWaitFlags & ProcessWaitForFlag_StdIn)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || (fWaitFlags & ProcessWaitForFlag_StdOut)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || (fWaitFlags & ProcessWaitForFlag_StdErr))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (procStatus)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TerminatedNormally:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TerminatedSignal:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TerminatedAbnormally:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Down:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = ProcessWaitResult_Terminate;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TimedOutKilled:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TimedOutAbnormally:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = ProcessWaitResult_Timeout;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Error:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Handled above. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Started:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * If ProcessCreateFlag_WaitForProcessStartOnly was specified on process creation the
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * caller is not interested in getting further process statuses -- so just don't notify
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * anything here anymore and return.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (uProcFlags & ProcessCreateFlag_WaitForProcessStartOnly)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = ProcessWaitResult_Start;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Undefined:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Starting:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* No result available yet. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertMsgFailed(("Unhandled process status %ld\n", procStatus));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (fWaitFlags & ProcessWaitForFlag_Start)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (procStatus)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Started:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Paused:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Terminating:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TerminatedNormally:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TerminatedSignal:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TerminatedAbnormally:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Down:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = ProcessWaitResult_Start;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Error:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = ProcessWaitResult_Error;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TimedOutKilled:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_TimedOutAbnormally:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = ProcessWaitResult_Timeout;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Undefined:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessStatus_Starting:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* No result available yet. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertMsgFailed(("Unhandled process status %ld\n", procStatus));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Filter out waits which are *not* supported using
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * older guest control Guest Additions.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ** @todo ProcessWaitForFlag_Std* flags are not implemented yet.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (uProtocol < 99) /* See @todo above. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ( waitResult == ProcessWaitResult_None
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* We don't support waiting for stdin, out + err,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * just skip waiting then. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && ( (fWaitFlags & ProcessWaitForFlag_StdIn)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || (fWaitFlags & ProcessWaitForFlag_StdOut)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || (fWaitFlags & ProcessWaitForFlag_StdErr)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync )
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync )
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Use _WaitFlagNotSupported because we don't know what to tell the caller. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = ProcessWaitResult_WaitFlagNotSupported;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return waitResult;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncProcessWaitResult_T GuestProcess::waitFlagsToResult(uint32_t fWaitFlags)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(mSession);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return GuestProcess::waitFlagsToResultEx(fWaitFlags, mData.mStatus, mData.mProcess.mFlags,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mSession->getProtocolVersion());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, mStatus=%RU32, pGuestRc=%p\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fWaitFlags, uTimeoutMS, mData.mStatus, pGuestRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Did some error occur before? Then skip waiting and return. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mData.mStatus == ProcessStatus_Error)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = ProcessWaitResult_Error;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertMsg(RT_FAILURE(mData.mRC), ("No error rc (%Rrc) set when guest process indicated an error\n", mData.mRC));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *pGuestRc = mData.mRC; /* Return last set error. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VERR_GSTCTL_GUEST_ERROR;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = waitFlagsToResult(fWaitFlags);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("procStatus=%ld, procRc=%Rrc, waitResult=%ld\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mStatus, mData.mRC, waitResult));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* No waiting needed? Return immediately using the last set error. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (waitResult != ProcessWaitResult_None)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *pGuestRc = mData.mRC; /* Return last set error (if any). */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return RT_SUCCESS(mData.mRC) ? VINF_SUCCESS : VERR_GSTCTL_GUEST_ERROR;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync alock.release(); /* Release lock before waiting. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestWaitEvent *pEvent = NULL;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync std::list < VBoxEventType_T > eventTypes;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync try
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = registerWaitEvent(eventTypes, &pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync catch (std::bad_alloc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NO_MEMORY;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Do the actual waiting.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessStatus_T processStatus = ProcessStatus_Undefined;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint64_t u64StartMS = RTTimeMilliTS();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (;;)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint64_t u32ElapsedMS = RTTimeMilliTS() - u64StartMS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ( uTimeoutMS != RT_INDEFINITE_WAIT
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && u32ElapsedMS >= uTimeoutMS)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_TIMEOUT;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = waitForStatusChange(pEvent,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uTimeoutMS == RT_INDEFINITE_WAIT
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ? RT_INDEFINITE_WAIT : uTimeoutMS - u32ElapsedMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync &processStatus, pGuestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync alock.acquire();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult = waitFlagsToResultEx(fWaitFlags, processStatus,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess.mFlags, mSession->getProtocolVersion());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Got new status change: waitResult=%ld, processStatus=%ld\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult, processStatus));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (ProcessWaitResult_None != waitResult) /* We got a waiting result. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else /* Waiting failed, bail out. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync unregisterWaitEvent(pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("waitResult=%ld, processStatus=%ld, rc=%Rrc\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync waitResult, processStatus, vrc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::waitForInputNotify(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessInputStatus_T *pInputStatus, uint32_t *pcbProcessed)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync VBoxEventType_T evtType;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComPtr<IEvent> pIEvent;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = waitForEvent(pEvent, uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync &evtType, pIEvent.asOutParam());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (evtType == VBoxEventType_OnGuestProcessInputNotify)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComPtr<IGuestProcessInputNotifyEvent> pProcessEvent = pIEvent;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(!pProcessEvent.isNull());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pInputStatus)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr2 = pProcessEvent->COMGETTER(Status)(pInputStatus);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComAssertComRC(hr2);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pcbProcessed)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr2 = pProcessEvent->COMGETTER(Processed)((ULONG*)pcbProcessed);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComAssertComRC(hr2);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Returning pEvent=%p, uHandle=%RU32, rc=%Rrc\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pEvent, uHandle, vrc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::waitForOutput(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync void *pvData, size_t cbData, uint32_t *pcbRead)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync VBoxEventType_T evtType;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComPtr<IEvent> pIEvent;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync do
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = waitForEvent(pEvent, uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync &evtType, pIEvent.asOutParam());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (evtType == VBoxEventType_OnGuestProcessOutput)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComPtr<IGuestProcessOutputEvent> pProcessEvent = pIEvent;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(!pProcessEvent.isNull());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ULONG uHandleEvent;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr = pProcessEvent->COMGETTER(Handle)(&uHandleEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (uHandleEvent == uHandle)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pvData)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync com::SafeArray <BYTE> data;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = pProcessEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComAssertComRC(hr);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync size_t cbRead = data.size();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (cbRead)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (cbRead <= cbData)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Copy data from event into our buffer. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync memcpy(pvData, data.raw(), data.size());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_BUFFER_OVERFLOW;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pcbRead)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ULONG cbRead;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = pProcessEvent->COMGETTER(Processed)(&cbRead);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComAssertComRC(hr);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *pcbRead = (uint32_t)cbRead;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync } while (RT_SUCCESS(vrc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessStatus_T *pProcessStatus, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pProcessStatus is optional. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pGuestRc is optional. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync VBoxEventType_T evtType;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComPtr<IEvent> pIEvent;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = waitForEvent(pEvent, uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync &evtType, pIEvent.asOutParam());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(evtType == VBoxEventType_OnGuestProcessStateChanged);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComPtr<IGuestProcessStateChangedEvent> pProcessEvent = pIEvent;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(!pProcessEvent.isNull());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pProcessStatus)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = pProcessEvent->COMGETTER(Status)(pProcessStatus);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComAssertComRC(hr);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComPtr<IVirtualBoxErrorInfo> errorInfo;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = pProcessEvent->COMGETTER(Error)(errorInfo.asOutParam());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComAssertComRC(hr);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LONG lGuestRc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComAssertComRC(hr);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("resultDetail=%RI32 (rc=%Rrc)\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync lGuestRc, lGuestRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE((int)lGuestRc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_GSTCTL_GUEST_ERROR;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *pGuestRc = (int)lGuestRc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/* static */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncbool GuestProcess::waitResultImpliesEx(ProcessWaitResult_T waitResult,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessStatus_T procStatus, uint32_t uProcFlags,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t uProtocol)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync bool fImplies;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (waitResult)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_Start:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fImplies = procStatus == ProcessStatus_Started;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_Terminate:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fImplies = ( procStatus == ProcessStatus_TerminatedNormally
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || procStatus == ProcessStatus_TerminatedSignal
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || procStatus == ProcessStatus_TerminatedAbnormally
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || procStatus == ProcessStatus_TimedOutKilled
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || procStatus == ProcessStatus_TimedOutAbnormally
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || procStatus == ProcessStatus_Down
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync || procStatus == ProcessStatus_Error);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fImplies = false;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return fImplies;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcess::writeData(uint32_t uHandle, uint32_t uFlags,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync void *pvData, size_t cbData, uint32_t uTimeoutMS, uint32_t *puWritten, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("uPID=%RU32, uHandle=%RU32, uFlags=%RU32, pvData=%p, cbData=%RU32, uTimeoutMS=%RU32, puWritten=%p, pGuestRc=%p\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mPID, uHandle, uFlags, pvData, cbData, uTimeoutMS, puWritten, pGuestRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* All is optional. There can be 0 byte writes. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mData.mStatus != ProcessStatus_Started)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (puWritten)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *puWritten = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *pGuestRc = VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VINF_SUCCESS; /* Not available for writing (anymore). */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync GuestWaitEvent *pEvent = NULL;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync std::list < VBoxEventType_T > eventTypes;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync try
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * On Guest Additions < 4.3 there is no guarantee that the process status
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * change arrives *after* the input event, e.g. if this was the last input
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * block being written and the process will report status "terminate".
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * So just skip checking for process status change and only wait for the
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * input event.
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mSession->getProtocolVersion() >= 2)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync eventTypes.push_back(VBoxEventType_OnGuestProcessInputNotify);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = registerWaitEvent(eventTypes, &pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync catch (std::bad_alloc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NO_MEMORY;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync VBOXHGCMSVCPARM paParms[5];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int i = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(pEvent->ContextID());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(mData.mPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32(uFlags);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setPointer(pvData, (uint32_t)cbData);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync paParms[i++].setUInt32((uint32_t)cbData);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync alock.release(); /* Drop the write lock before sending. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t cbProcessed = 0;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = sendCommand(HOST_EXEC_SET_INPUT, i, paParms);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessInputStatus_T inputStatus;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = waitForInputNotify(pEvent, uHandle, uTimeoutMS,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync &inputStatus, &cbProcessed);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /** @todo Set guestRc. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (puWritten)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *puWritten = cbProcessed;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /** @todo Error handling. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync unregisterWaitEvent(pEvent);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Returning cbProcessed=%RU32, rc=%Rrc\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync cbProcessed, vrc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync// implementation of public methods
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync/////////////////////////////////////////////////////////////////////////////
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::Read(ULONG aHandle, ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (aToRead == 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return setError(E_INVALIDARG, tr("The size to read is zero"));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutSafeArrayPointerValid(aData);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync com::SafeArray<BYTE> data((size_t)aToRead);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(data.size() >= aToRead);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr = S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t cbRead; int guestRc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = readData(aHandle, aToRead, aTimeoutMS, data.raw(), aToRead, &cbRead, &guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (data.size() != cbRead)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync data.resize(cbRead);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync data.detachTo(ComSafeArrayOutArg(aData));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (vrc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_GSTCTL_GUEST_ERROR:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = setError(VBOX_E_IPRT_ERROR,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync tr("Reading from process \"%s\" (PID %RU32) failed: %Rrc"),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess.mCommand.c_str(), mData.mPID, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("rc=%Rrc, cbRead=%RU32\n", vrc, cbRead));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return hr;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::Terminate(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr = S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int guestRc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = terminateProcess(30 * 1000 /* Timeout in ms */,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync &guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (vrc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_GSTCTL_GUEST_ERROR:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_NOT_SUPPORTED:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = setError(VBOX_E_IPRT_ERROR,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync tr("Terminating process \"%s\" (PID %RU32) not supported by installed Guest Additions"),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess.mCommand.c_str(), mData.mPID);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = setError(VBOX_E_IPRT_ERROR,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync tr("Terminating process \"%s\" (PID %RU32) failed: %Rrc"),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess.mCommand.c_str(), mData.mPID, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Remove the process from our internal session list. Only an API client
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * now may hold references to it. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(mSession);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mSession->processRemoveFromList(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return hr;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::WaitFor(ULONG aWaitFlags, ULONG aTimeoutMS, ProcessWaitResult_T *aReason)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutPointerValid(aReason);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Note: Do not hold any locks here while waiting!
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr = S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int guestRc; ProcessWaitResult_T waitResult;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = waitFor(aWaitFlags, aTimeoutMS, waitResult, &guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *aReason = waitResult;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (vrc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_GSTCTL_GUEST_ERROR:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_TIMEOUT:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *aReason = ProcessWaitResult_Timeout;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = setError(VBOX_E_IPRT_ERROR,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync tr("Waiting for process \"%s\" (PID %RU32) failed: %Rrc"),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess.mCommand.c_str(), mData.mPID, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return hr;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::WaitForArray(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitResult_T *aReason)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutPointerValid(aReason);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Note: Do not hold any locks here while waiting!
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t fWaitFor = ProcessWaitForFlag_None;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync com::SafeArray<ProcessWaitForFlag_T> flags(ComSafeArrayInArg(aFlags));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (size_t i = 0; i < flags.size(); i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fWaitFor |= flags[i];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return WaitFor(fWaitFor, aTimeoutMS, aReason);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::Write(ULONG aHandle, ULONG aFlags,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutPointerValid(aWritten);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync com::SafeArray<BYTE> data(ComSafeArrayInArg(aData));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr = S_OK;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t cbWritten; int guestRc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = writeData(aHandle, aFlags, data.raw(), data.size(), aTimeoutMS, &cbWritten, &guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (vrc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case VERR_GSTCTL_GUEST_ERROR:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync hr = setError(VBOX_E_IPRT_ERROR,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync tr("Writing to process \"%s\" (PID %RU32) failed: %Rrc"),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mData.mProcess.mCommand.c_str(), mData.mPID, vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("rc=%Rrc, aWritten=%RU32\n", vrc, cbWritten));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *aWritten = (ULONG)cbWritten;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return hr;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncSTDMETHODIMP GuestProcess::WriteArray(ULONG aHandle, ComSafeArrayIn(ProcessInputFlag_T, aFlags),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#ifndef VBOX_WITH_GUEST_CONTROL
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ReturnComNotImplemented();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync CheckComArgOutPointerValid(aWritten);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AutoCaller autoCaller(this);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /*
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * Note: Do not hold any locks here while writing!
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ULONG fWrite = ProcessInputFlag_None;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync com::SafeArray<ProcessInputFlag_T> flags(ComSafeArrayInArg(aFlags));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync for (size_t i = 0; i < flags.size(); i++)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fWrite |= flags[i];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return Write(aHandle, fWrite, ComSafeArrayInArg(aData), aTimeoutMS, aWritten);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync///////////////////////////////////////////////////////////////////////////////
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncGuestProcessTool::GuestProcessTool(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync : pSession(NULL)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncGuestProcessTool::~GuestProcessTool(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Terminate(30 * 1000, NULL /* pGuestRc */);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcessTool::Init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync bool fAsync, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("pGuestSession=%p, szCmd=%s, fAsync=%RTbool\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pGuestSession, startupInfo.mCommand.c_str(), fAsync));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pGuestSession, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pSession = pGuestSession;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mStartupInfo = startupInfo;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Make sure the process is hidden. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync mStartupInfo.mFlags |= ProcessCreateFlag_Hidden;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc = pSession->processCreateExInteral(mStartupInfo, pProcess);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = fAsync ? pProcess->startProcessAsync() : pProcess->startProcess(30 * 1000 /* 30s timeout */,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pGuestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ( RT_SUCCESS(vrc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && !fAsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && ( pGuestRc
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && RT_FAILURE(*pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync )
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync )
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_GSTCTL_GUEST_ERROR;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcessTool::GetCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync const GuestProcessStream *pStream = NULL;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (uHandle == OUTPUT_HANDLE_ID_STDOUT)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pStream = &mStdOut;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else if (uHandle == OUTPUT_HANDLE_ID_STDERR)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pStream = &mStdErr;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (!pStream)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VERR_INVALID_PARAMETER;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync do
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Try parsing the data to see if the current block is complete. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = mStdOut.ParseBlock(strmBlock);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (strmBlock.GetCount())
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync } while (RT_SUCCESS(vrc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("rc=%Rrc, %RU64 pairs\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc, strmBlock.GetCount()));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncbool GuestProcessTool::IsRunning(void)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertReturn(!pProcess.isNull(), true);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessStatus_T procStatus = ProcessStatus_Undefined;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr = pProcess->COMGETTER(Status(&procStatus));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(SUCCEEDED(hr));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ( procStatus != ProcessStatus_Started
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && procStatus != ProcessStatus_Paused
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && procStatus != ProcessStatus_Terminating)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return false;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return true;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcessTool::TerminatedOk(LONG *pExitCode)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(!pProcess.isNull());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* pExitCode is optional. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (!IsRunning())
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LONG exitCode;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync HRESULT hr = pProcess->COMGETTER(ExitCode(&exitCode));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(SUCCEEDED(hr));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pExitCode)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *pExitCode = exitCode;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (exitCode != 0)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VERR_NOT_EQUAL; /** @todo Special guest control rc needed! */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return VERR_INVALID_STATE; /** @todo Special guest control rc needed! */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcessTool::Wait(uint32_t fFlags, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return WaitEx(fFlags, NULL /* pStreamBlock */, pGuestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcessTool::WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("pSession=%p, fFlags=0x%x, pStreamBlock=%p, pGuestRc=%p\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pSession, fFlags, pStreamBlock, pGuestRc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtrReturn(pSession, VERR_INVALID_POINTER);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(!pProcess.isNull());
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Other parameters are optional. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Can we parse the next block without waiting? */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(pStreamBlock);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStreamBlock);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Do the waiting. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t fWaitFlags = ProcessWaitForFlag_Terminate;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fWaitFlags |= ProcessWaitForFlag_StdOut;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdErr)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fWaitFlags |= ProcessWaitForFlag_StdErr;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("waitFlags=0x%x\n", fWaitFlags));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /** @todo Decrease timeout. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int guestRc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync bool fDone = false;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync BYTE byBuf[_64K];
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uint32_t cbRead;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync bool fHandleStdOut = false;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync bool fHandleStdErr = false;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync ProcessWaitResult_T waitRes;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync do
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pProcess->waitFor(fWaitFlags,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uTimeoutMS, waitRes, &guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync switch (waitRes)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_StdIn:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_NOT_IMPLEMENTED;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_StdOut:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fHandleStdOut = true;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_StdErr:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fHandleStdErr = true;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_WaitFlagNotSupported:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (fWaitFlags & ProcessWaitForFlag_StdOut)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fHandleStdOut = true;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (fWaitFlags & ProcessWaitForFlag_StdErr)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fHandleStdErr = true;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Since waiting for stdout / stderr is not supported by the guest,
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync * wait a bit to not hog the CPU too much when polling for data. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync RTThreadSleep(1); /* Optional, don't check rc. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_Error:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_GSTCTL_GUEST_ERROR;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_Terminate:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fDone = true;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_Timeout:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = VERR_TIMEOUT;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_Start:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync case ProcessWaitResult_Status:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync /* Not used here, just skip. */
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync default:
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertReleaseMsgFailed(("Unhandled process wait result %ld\n", waitRes));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (fHandleStdOut)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uTimeoutMS, byBuf, sizeof(byBuf),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync &cbRead, &guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (cbRead)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Received %RU64 bytes from stdout\n", cbRead));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = mStdOut.AddData(byBuf, cbRead);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if ( RT_SUCCESS(vrc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync && (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertPtr(pStreamBlock);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStreamBlock);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_SUCCESS(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fDone = true;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fHandleStdOut = false;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (fHandleStdErr)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDERR, sizeof(byBuf),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync uTimeoutMS, byBuf, sizeof(byBuf),
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync &cbRead, &guestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (RT_FAILURE(vrc))
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync break;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (cbRead)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Received %RU64 bytes from stderr\n", cbRead));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc = mStdErr.AddData(byBuf, cbRead);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync fHandleStdErr = false;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync } while (!fDone && RT_SUCCESS(vrc));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFunc(("Loop ended with rc=%Rrc, guestRc=%Rrc, waitRes=%ld\n",
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync vrc, guestRc, waitRes));
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync *pGuestRc = guestRc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(vrc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return vrc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsyncint GuestProcessTool::Terminate(uint32_t uTimeoutMS, int *pGuestRc)
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync{
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowThisFuncEnter();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int rc = VINF_SUCCESS;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync if (!pProcess.isNull())
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync {
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync rc = pProcess->terminateProcess(uTimeoutMS, pGuestRc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync Assert(pSession);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync int rc2 = pSession->processRemoveFromList(pProcess);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync AssertRC(rc2);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync pProcess.setNull();
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync }
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync else
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync rc = VERR_NOT_FOUND;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync LogFlowFuncLeaveRC(rc);
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync return rc;
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync}
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync
f9a51917495bc8ba8b60632219652a7b122c1190vboxsync