summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-client/GuestSessionImplTasks.cpp')
-rw-r--r--src/VBox/Main/src-client/GuestSessionImplTasks.cpp245
1 files changed, 180 insertions, 65 deletions
diff --git a/src/VBox/Main/src-client/GuestSessionImplTasks.cpp b/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
index 84866b30..759020d9 100644
--- a/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
+++ b/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
@@ -1,11 +1,10 @@
-
/* $Id: GuestSessionImplTasks.cpp $ */
/** @file
- * VirtualBox Main - XXX.
+ * VirtualBox Main - Guest session tasks.
*/
/*
- * Copyright (C) 2012 Oracle Corporation
+ * Copyright (C) 2012-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -138,6 +137,9 @@ int GuestSessionTask::setProgressSuccess(void)
HRESULT GuestSessionTask::setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg)
{
+ LogFlowFunc(("hr=%Rhrc, strMsg=%s\n",
+ hr, strMsg.c_str()));
+
if (mProgress.isNull()) /* Progress is optional. */
return hr; /* Return original rc. */
@@ -158,6 +160,62 @@ HRESULT GuestSessionTask::setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg)
return hr; /* Return original rc. */
}
+SessionTaskOpen::SessionTaskOpen(GuestSession *pSession,
+ uint32_t uFlags,
+ uint32_t uTimeoutMS)
+ : GuestSessionTask(pSession),
+ mFlags(uFlags),
+ mTimeoutMS(uTimeoutMS)
+{
+
+}
+
+SessionTaskOpen::~SessionTaskOpen(void)
+{
+
+}
+
+int SessionTaskOpen::Run(int *pGuestRc)
+{
+ LogFlowThisFuncEnter();
+
+ ComObjPtr<GuestSession> pSession = mSession;
+ Assert(!pSession.isNull());
+
+ AutoCaller autoCaller(pSession);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ int vrc = pSession->startSessionInternal(pGuestRc);
+ /* Nothing to do here anymore. */
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int SessionTaskOpen::RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress)
+{
+ LogFlowThisFunc(("strDesc=%s\n", strDesc.c_str()));
+
+ mDesc = strDesc;
+ mProgress = pProgress;
+
+ int rc = RTThreadCreate(NULL, SessionTaskOpen::taskThread, this,
+ 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
+ "gctlSesOpen");
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+/* static */
+int SessionTaskOpen::taskThread(RTTHREAD Thread, void *pvUser)
+{
+ std::auto_ptr<SessionTaskOpen> task(static_cast<SessionTaskOpen*>(pvUser));
+ AssertReturn(task.get(), VERR_GENERAL_FAILURE);
+
+ LogFlowFunc(("pTask=%p\n", task.get()));
+ return task->Run(NULL /* guestRc */);
+}
+
SessionTaskCopyTo::SessionTaskCopyTo(GuestSession *pSession,
const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags)
: GuestSessionTask(pSession),
@@ -245,6 +303,7 @@ int SessionTaskCopyTo::Run(void)
}
else
{
+ rc = VINF_SUCCESS;
pFile = mSourceFile;
/* Size + offset are optional. */
}
@@ -258,14 +317,20 @@ int SessionTaskCopyTo::Run(void)
/* Startup process. */
ComObjPtr<GuestProcess> pProcess; int guestRc;
- rc = pSession->processCreateExInteral(procInfo, pProcess);
if (RT_SUCCESS(rc))
- rc = pProcess->startProcess(&guestRc);
+ rc = pSession->processCreateExInteral(procInfo, pProcess);
+ if (RT_SUCCESS(rc))
+ {
+ Assert(!pProcess.isNull());
+ rc = pProcess->startProcess(30 * 1000 /* 30s timeout */,
+ &guestRc);
+ }
+
if (RT_FAILURE(rc))
{
switch (rc)
{
- case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ case VERR_GSTCTL_GUEST_ERROR:
setProgressErrorMsg(VBOX_E_IPRT_ERROR,
GuestProcess::guestErrorToString(guestRc));
break;
@@ -301,7 +366,7 @@ int SessionTaskCopyTo::Run(void)
/* If the guest does not support waiting for stdin, we now yield in
* order to reduce the CPU load due to busy waiting. */
if (waitRes == ProcessWaitResult_WaitFlagNotSupported)
- RTThreadSleep(1); /* Optional, don't check rc. */
+ RTThreadYield(); /* Optional, don't check rc. */
size_t cbRead = 0;
if (mSourceSize) /* If we have nothing to write, take a shortcut. */
@@ -312,7 +377,7 @@ int SessionTaskCopyTo::Run(void)
if (RT_SUCCESS(rc))
{
rc = RTFileRead(*pFile, (uint8_t*)byBuf,
- RT_MIN(cbToRead, sizeof(byBuf)), &cbRead);
+ RT_MIN((size_t)cbToRead, sizeof(byBuf)), &cbRead);
/*
* Some other error occured? There might be a chance that RTFileRead
* could not resolve/map the native error code to an IPRT code, so just
@@ -360,7 +425,7 @@ int SessionTaskCopyTo::Run(void)
{
switch (rc)
{
- case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ case VERR_GSTCTL_GUEST_ERROR:
setProgressErrorMsg(VBOX_E_IPRT_ERROR,
GuestProcess::guestErrorToString(guestRc));
break;
@@ -403,7 +468,8 @@ int SessionTaskCopyTo::Run(void)
break;
} /* for */
- LogFlowThisFunc(("Copy loop ended with rc=%Rrc\n" ,rc));
+ LogFlowThisFunc(("Copy loop ended with rc=%Rrc, cbToRead=%RU64, cbWrittenTotal=%RU64, cbFileSize=%RU64\n",
+ rc, cbToRead, cbWrittenTotal, mSourceSize));
if ( !fCanceled
|| RT_SUCCESS(rc))
@@ -471,9 +537,6 @@ int SessionTaskCopyTo::Run(void)
rc = setProgressSuccess();
}
}
-
- if (!pProcess.isNull())
- pProcess->uninit();
} /* processCreateExInteral */
if (!mSourceFile) /* Only close locally opened files. */
@@ -536,7 +599,7 @@ int SessionTaskCopyFrom::Run(void)
* Note: There will be races between querying file size + reading the guest file's
* content because we currently *do not* lock down the guest file when doing the
* actual operations.
- ** @todo Implement guest file locking!
+ ** @todo Use the IGuestFile API for locking down the file on the guest!
*/
GuestFsObjData objData; int guestRc;
int rc = pSession->fileQueryInfoInternal(Utf8Str(mSource), objData, &guestRc);
@@ -567,8 +630,8 @@ int SessionTaskCopyFrom::Run(void)
else
{
GuestProcessStartupInfo procInfo;
- procInfo.mName = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
- mSource.c_str(), mDest.c_str(), objData.mObjectSize);
+ procInfo.mName = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
+ mSource.c_str(), mDest.c_str(), objData.mObjectSize);
procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT);
procInfo.mFlags = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;
@@ -579,12 +642,13 @@ int SessionTaskCopyFrom::Run(void)
ComObjPtr<GuestProcess> pProcess;
rc = pSession->processCreateExInteral(procInfo, pProcess);
if (RT_SUCCESS(rc))
- rc = pProcess->startProcess(&guestRc);
+ rc = pProcess->startProcess(30 * 1000 /* 30s timeout */,
+ &guestRc);
if (RT_FAILURE(rc))
{
switch (rc)
{
- case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ case VERR_GSTCTL_GUEST_ERROR:
setProgressErrorMsg(VBOX_E_IPRT_ERROR,
GuestProcess::guestErrorToString(guestRc));
break;
@@ -613,7 +677,7 @@ int SessionTaskCopyFrom::Run(void)
{
switch (rc)
{
- case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ case VERR_GSTCTL_GUEST_ERROR:
setProgressErrorMsg(VBOX_E_IPRT_ERROR,
GuestProcess::guestErrorToString(guestRc));
break;
@@ -634,9 +698,9 @@ int SessionTaskCopyFrom::Run(void)
/* If the guest does not support waiting for stdin, we now yield in
* order to reduce the CPU load due to busy waiting. */
if (waitRes == ProcessWaitResult_WaitFlagNotSupported)
- RTThreadSleep(1); /* Optional, don't check rc. */
+ RTThreadYield(); /* Optional, don't check rc. */
- size_t cbRead;
+ uint32_t cbRead = 0; /* readData can return with VWRN_GSTCTL_OBJECTSTATE_CHANGED. */
rc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
&cbRead, &guestRc);
@@ -644,7 +708,7 @@ int SessionTaskCopyFrom::Run(void)
{
switch (rc)
{
- case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ case VERR_GSTCTL_GUEST_ERROR:
setProgressErrorMsg(VBOX_E_IPRT_ERROR,
GuestProcess::guestErrorToString(guestRc));
break;
@@ -711,7 +775,7 @@ int SessionTaskCopyFrom::Run(void)
/* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
* to the destination -> access denied. */
setProgressErrorMsg(VBOX_E_IPRT_ERROR,
- Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
+ Utf8StrFmt(GuestSession::tr("Unable to write \"%s\" to \"%s\": Access denied"),
mSource.c_str(), mDest.c_str()));
rc = VERR_GENERAL_FAILURE; /* Fudge. */
}
@@ -742,9 +806,6 @@ int SessionTaskCopyFrom::Run(void)
rc = setProgressSuccess();
}
}
-
- if (!pProcess.isNull())
- pProcess->uninit();
}
RTFileClose(fileDest);
@@ -781,10 +842,13 @@ int SessionTaskCopyFrom::taskThread(RTTHREAD Thread, void *pvUser)
}
SessionTaskUpdateAdditions::SessionTaskUpdateAdditions(GuestSession *pSession,
- const Utf8Str &strSource, uint32_t uFlags)
+ const Utf8Str &strSource,
+ const ProcessArguments &aArguments,
+ uint32_t uFlags)
: GuestSessionTask(pSession)
{
mSource = strSource;
+ mArguments = aArguments;
mFlags = uFlags;
}
@@ -793,6 +857,45 @@ SessionTaskUpdateAdditions::~SessionTaskUpdateAdditions(void)
}
+int SessionTaskUpdateAdditions::addProcessArguments(ProcessArguments &aArgumentsDest,
+ const ProcessArguments &aArgumentsSource)
+{
+ int rc = VINF_SUCCESS;
+
+ try
+ {
+ /* Filter out arguments which already are in the destination to
+ * not end up having them specified twice. Not the fastest method on the
+ * planet but does the job. */
+ ProcessArguments::const_iterator itSource = aArgumentsSource.begin();
+ while (itSource != aArgumentsSource.end())
+ {
+ bool fFound = false;
+ ProcessArguments::iterator itDest = aArgumentsDest.begin();
+ while (itDest != aArgumentsDest.end())
+ {
+ if ((*itDest).equalsIgnoreCase((*itSource)))
+ {
+ fFound = true;
+ break;
+ }
+ itDest++;
+ }
+
+ if (!fFound)
+ aArgumentsDest.push_back((*itSource));
+
+ itSource++;
+ }
+ }
+ catch(std::bad_alloc &)
+ {
+ return VERR_NO_MEMORY;
+ }
+
+ return rc;
+}
+
int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO,
Utf8Str const &strFileSource, const Utf8Str &strFileDest,
bool fOptional, uint32_t *pcbSize)
@@ -820,8 +923,8 @@ int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFS
/* Copy over the Guest Additions file to the guest. */
if (RT_SUCCESS(rc))
{
- LogFlowThisFunc(("Copying Guest Additions installer file \"%s\" to \"%s\" on guest ...\n",
- strFileSource.c_str(), strFileDest.c_str()));
+ LogRel(("Copying Guest Additions installer file \"%s\" to \"%s\" on guest ...\n",
+ strFileSource.c_str(), strFileDest.c_str()));
if (RT_SUCCESS(rc))
{
@@ -858,8 +961,8 @@ int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFS
/* Determine where the installer image ended up and if it has the correct size. */
if (RT_SUCCESS(rc))
{
- LogFlowThisFunc(("Verifying Guest Additions installer file \"%s\" ...\n",
- strFileDest.c_str()));
+ LogRel(("Verifying Guest Additions installer file \"%s\" ...\n",
+ strFileDest.c_str()));
GuestFsObjData objData;
int64_t cbSizeOnGuest; int guestRc;
@@ -874,15 +977,15 @@ int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFS
{
if (RT_SUCCESS(rc)) /* Size does not match. */
{
- LogFlowThisFunc(("Size of Guest Additions installer file \"%s\" does not match: %RI64bytes copied, %RU64bytes expected\n",
- strFileDest.c_str(), cbSizeOnGuest, cbSize));
+ LogRel(("Size of Guest Additions installer file \"%s\" does not match: %RI64 bytes copied, %RU64 bytes expected\n",
+ strFileDest.c_str(), cbSizeOnGuest, cbSize));
rc = VERR_BROKEN_PIPE; /** @todo Find a better error. */
}
else
{
switch (rc)
{
- case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ case VERR_GSTCTL_GUEST_ERROR:
setProgressErrorMsg(VBOX_E_IPRT_ERROR,
GuestProcess::guestErrorToString(guestRc));
break;
@@ -899,7 +1002,7 @@ int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFS
if (RT_SUCCESS(rc))
{
if (pcbSize)
- *pcbSize = cbSizeOnGuest;
+ *pcbSize = (uint32_t)cbSizeOnGuest;
}
}
@@ -933,7 +1036,7 @@ int SessionTaskUpdateAdditions::runFileOnGuest(GuestSession *pSession, GuestProc
procInfo.mCommand.c_str(), exitCode));
break;
- case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ case VERR_GSTCTL_GUEST_ERROR:
setProgressErrorMsg(VBOX_E_IPRT_ERROR,
GuestProcess::guestErrorToString(guestRc));
break;
@@ -1036,7 +1139,7 @@ int SessionTaskUpdateAdditions::Run(void)
}
Utf8Str strOSVer;
- eOSType osType;
+ eOSType osType = eOSType_Unknown;
if (RT_SUCCESS(rc))
{
/*
@@ -1066,21 +1169,30 @@ int SessionTaskUpdateAdditions::Run(void)
* can't do automated updates here. */
/* Windows XP 64-bit (5.2) is a Windows 2003 Server actually, so skip this here. */
if ( RT_SUCCESS(rc)
- && ( strOSVer.startsWith("5.0") /* Exclude the build number. */
- || strOSVer.startsWith("5.1")) /* Exclude the build number. */
- )
+ && RTStrVersionCompare(strOSVer.c_str(), "5.0") >= 0)
{
- /* If we don't have AdditionsUpdateFlag_WaitForUpdateStartOnly set we can't continue
- * because the Windows Guest Additions installer will fail because of WHQL popups. If the
- * flag is set this update routine ends successfully as soon as the installer was started
- * (and the user has to deal with it in the guest). */
- if (!(mFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly))
+ if ( strOSVer.startsWith("5.0") /* Exclude the build number. */
+ || strOSVer.startsWith("5.1") /* Exclude the build number. */)
{
- hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
- Utf8StrFmt(GuestSession::tr("Windows 2000 and XP are not supported for automatic updating due to WHQL interaction, please update manually")));
- rc = VERR_NOT_SUPPORTED;
+ /* If we don't have AdditionsUpdateFlag_WaitForUpdateStartOnly set we can't continue
+ * because the Windows Guest Additions installer will fail because of WHQL popups. If the
+ * flag is set this update routine ends successfully as soon as the installer was started
+ * (and the user has to deal with it in the guest). */
+ if (!(mFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly))
+ {
+ hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
+ Utf8StrFmt(GuestSession::tr("Windows 2000 and XP are not supported for automatic updating due to WHQL interaction, please update manually")));
+ rc = VERR_NOT_SUPPORTED;
+ }
}
}
+ else
+ {
+ hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
+ Utf8StrFmt(GuestSession::tr("%s (%s) not supported for automatic updating, please update manually"),
+ strOSType.c_str(), strOSVer.c_str()));
+ rc = VERR_NOT_SUPPORTED;
+ }
}
else if (strOSType.contains("Solaris", Utf8Str::CaseInsensitive))
{
@@ -1090,7 +1202,8 @@ int SessionTaskUpdateAdditions::Run(void)
osType = eOSType_Linux;
#if 1 /* Only Windows is supported (and tested) at the moment. */
- if (osType != eOSType_Windows)
+ if ( RT_SUCCESS(rc)
+ && osType != eOSType_Windows)
{
hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
Utf8StrFmt(GuestSession::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"),
@@ -1172,15 +1285,15 @@ int SessionTaskUpdateAdditions::Run(void)
{
switch (rc)
{
- case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
- setProgressErrorMsg(VBOX_E_IPRT_ERROR,
- GuestProcess::guestErrorToString(guestRc));
+ case VERR_GSTCTL_GUEST_ERROR:
+ hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ GuestProcess::guestErrorToString(guestRc));
break;
default:
- setProgressErrorMsg(VBOX_E_IPRT_ERROR,
- Utf8StrFmt(GuestSession::tr("Error creating installation directory \"%s\" on the guest: %Rrc"),
- strUpdateDir.c_str(), rc));
+ hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error creating installation directory \"%s\" on the guest: %Rrc"),
+ strUpdateDir.c_str(), rc));
break;
}
}
@@ -1262,6 +1375,10 @@ int SessionTaskUpdateAdditions::Run(void)
* using a running VBoxTray instance via balloon messages in the
* Windows taskbar. */
siInstaller.mArguments.push_back(Utf8Str("/post_installstatus"));
+ /* Add optional installer command line arguments from the API to the
+ * installer's startup info. */
+ rc = addProcessArguments(siInstaller.mArguments, mArguments);
+ AssertRC(rc);
/* If the caller does not want to wait for out guest update process to end,
* complete the progress object now so that the caller can do other work. */
if (mFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly)
@@ -1373,25 +1490,23 @@ int SessionTaskUpdateAdditions::Run(void)
Utf8Str strError = Utf8StrFmt("No further error information available (%Rrc)", rc);
if (!mProgress.isNull()) /* Progress object is optional. */
{
- ComPtr<IVirtualBoxErrorInfo> pError;
- hr = mProgress->COMGETTER(ErrorInfo)(pError.asOutParam());
- Assert(!pError.isNull());
- if (SUCCEEDED(hr))
+ com::ProgressErrorInfo errorInfo(mProgress);
+ if ( errorInfo.isFullAvailable()
+ || errorInfo.isBasicAvailable())
{
- Bstr strVal;
- hr = pError->COMGETTER(Text)(strVal.asOutParam());
- if ( SUCCEEDED(hr)
- && strVal.isNotEmpty())
- strError = strVal;
+ strError = errorInfo.getText();
}
}
- LogRel(("Automatic update of Guest Additions failed: %s\n", strError.c_str()));
+ LogRel(("Automatic update of Guest Additions failed: %s (%Rhrc)\n",
+ strError.c_str(), hr));
}
LogRel(("Please install Guest Additions manually\n"));
}
+ /** @todo Clean up copied / left over installation files. */
+
LogFlowFuncLeaveRC(rc);
return rc;
}