summaryrefslogtreecommitdiff
path: root/src/VBox/Main
diff options
context:
space:
mode:
authorMichael Meskes <meskes@debian.org>2010-06-04 09:49:50 +0200
committerMichael Meskes <meskes@debian.org>2010-06-04 09:49:50 +0200
commite13debb062071c46f2707d0d0e59c57675b49360 (patch)
tree922f54068563b5cf3274bae8ba8122ce4b4ede1d /src/VBox/Main
parentabd0051802e55207e88435a185ff8d6e6b8d17d5 (diff)
downloadvirtualbox-upstream/3.2.2-dfsg.tar.gz
Imported Upstream version 3.2.2-dfsgupstream/3.2.2-dfsg
Diffstat (limited to 'src/VBox/Main')
-rw-r--r--src/VBox/Main/ApplianceImpl.cpp69
-rw-r--r--src/VBox/Main/ApplianceImplExport.cpp142
-rw-r--r--src/VBox/Main/ApplianceImplImport.cpp423
-rw-r--r--src/VBox/Main/ConsoleImpl.cpp410
-rw-r--r--src/VBox/Main/ConsoleImplTeleporter.cpp220
-rw-r--r--src/VBox/Main/Global.cpp22
-rw-r--r--src/VBox/Main/GuestImpl.cpp223
-rw-r--r--src/VBox/Main/HostImpl.cpp8
-rw-r--r--src/VBox/Main/MachineImpl.cpp95
-rw-r--r--src/VBox/Main/Makefile.kmk114
-rw-r--r--src/VBox/Main/MediumImpl.cpp42
-rw-r--r--src/VBox/Main/ProgressImpl.cpp99
-rw-r--r--src/VBox/Main/ProgressProxyImpl.cpp693
-rw-r--r--src/VBox/Main/SessionImpl.cpp34
-rw-r--r--src/VBox/Main/StorageControllerImpl.cpp5
-rw-r--r--src/VBox/Main/VirtualBoxImpl.cpp104
-rw-r--r--src/VBox/Main/glue/tests/Makefile.kmk48
-rw-r--r--src/VBox/Main/glue/tests/TestVBox.java107
-rw-r--r--src/VBox/Main/hgcm/HGCMThread.cpp37
-rw-r--r--src/VBox/Main/idl/VirtualBox.xidl75
-rw-r--r--src/VBox/Main/idl/midl.xsl12
-rw-r--r--src/VBox/Main/include/ApplianceImpl.h13
-rw-r--r--src/VBox/Main/include/ApplianceImplPrivate.h77
-rw-r--r--src/VBox/Main/include/ConsoleImpl.h9
-rw-r--r--src/VBox/Main/include/GuestImpl.h15
-rw-r--r--src/VBox/Main/include/MachineImpl.h10
-rw-r--r--src/VBox/Main/include/ProgressCombinedImpl.h7
-rw-r--r--src/VBox/Main/include/ProgressImpl.h12
-rw-r--r--src/VBox/Main/include/ProgressProxyImpl.h120
-rw-r--r--src/VBox/Main/include/VirtualBoxErrorInfoImpl.h77
-rw-r--r--src/VBox/Main/include/VirtualBoxImpl.h13
-rw-r--r--src/VBox/Main/include/ovfreader.h4
-rw-r--r--src/VBox/Main/linux/PerformanceLinux.cpp5
-rw-r--r--src/VBox/Main/webservice/Makefile.kmk174
-rw-r--r--src/VBox/Main/webservice/filesplitter.cpp184
-rw-r--r--src/VBox/Main/webservice/glue-jaxws.xsl12
-rw-r--r--src/VBox/Main/webservice/vboxweb.cpp23
-rw-r--r--src/VBox/Main/webservice/websrv-php.xsl36
-rw-r--r--src/VBox/Main/webservice/websrv-python.xsl26
-rw-r--r--src/VBox/Main/webservice/webtest.cpp80
-rw-r--r--src/VBox/Main/xml/Settings.cpp66
-rw-r--r--src/VBox/Main/xml/ovfreader.cpp23
-rw-r--r--src/VBox/Main/xpcom/server.cpp6
43 files changed, 2753 insertions, 1221 deletions
diff --git a/src/VBox/Main/ApplianceImpl.cpp b/src/VBox/Main/ApplianceImpl.cpp
index 36e9cb96d..dbab2ad23 100644
--- a/src/VBox/Main/ApplianceImpl.cpp
+++ b/src/VBox/Main/ApplianceImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: ApplianceImpl.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: ApplianceImpl.cpp 29984 2010-06-02 12:22:39Z vboxsync $ */
/** @file
*
* IAppliance and IVirtualSystem COM class implementations.
@@ -672,6 +672,15 @@ void Appliance::disksWeight()
}
+/**
+ * Called from Appliance::importImpl() and Appliance::writeImpl() to set up a
+ * progress object with the proper weights and maximum progress values.
+ *
+ * @param pProgress
+ * @param bstrDescription
+ * @param mode
+ * @return
+ */
HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress,
const Bstr &bstrDescription,
SetUpProgressMode mode)
@@ -684,6 +693,8 @@ HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress,
// compute the disks weight (this sets ulTotalDisksMB and cDisks in the instance data)
disksWeight();
+ m->ulWeightForManifestOperation = 0;
+
ULONG cOperations;
ULONG ulTotalOperationsWeight;
@@ -691,19 +702,28 @@ HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress,
+ m->cDisks; // plus one per disk
if (m->ulTotalDisksMB)
{
- m->ulWeightPerOperation = (ULONG)((double)m->ulTotalDisksMB * 1 / 100); // use 1% of the progress for the XML
- ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightPerOperation;
+ m->ulWeightForXmlOperation = (ULONG)((double)m->ulTotalDisksMB * 1 / 100); // use 1% of the progress for the XML
+ ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightForXmlOperation;
}
else
{
// no disks to export:
- m->ulWeightPerOperation = 1;
+ m->ulWeightForXmlOperation = 1;
ulTotalOperationsWeight = 1;
}
switch (mode)
{
- case Regular:
+ case ImportFileNoManifest:
+ break;
+
+ case ImportFileWithManifest:
+ case WriteFile:
+ ++cOperations; // another one for creating the manifest
+
+ // assume that checking or creating the manifest will take 10% of the time it takes to export the disks
+ m->ulWeightForManifestOperation = m->ulTotalDisksMB / 10;
+ ulTotalOperationsWeight += m->ulWeightForManifestOperation;
break;
case ImportS3:
@@ -717,7 +737,7 @@ HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress,
ULONG ulImportWeight = (ULONG)((double)ulTotalOperationsWeight * 50 / 100); // use 50% for import
ulTotalOperationsWeight += ulImportWeight;
- m->ulWeightPerOperation = ulImportWeight; /* save for using later */
+ m->ulWeightForXmlOperation = ulImportWeight; /* save for using later */
ULONG ulInitWeight = (ULONG)((double)ulTotalOperationsWeight * 0.1 / 100); // use 0.1% for init
ulTotalOperationsWeight += ulInitWeight;
@@ -730,14 +750,14 @@ HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress,
if (m->ulTotalDisksMB)
{
- m->ulWeightPerOperation = (ULONG)((double)m->ulTotalDisksMB * 1 / 100); // use 1% of the progress for OVF file upload (we didn't know the size at this point)
- ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightPerOperation;
+ m->ulWeightForXmlOperation = (ULONG)((double)m->ulTotalDisksMB * 1 / 100); // use 1% of the progress for OVF file upload (we didn't know the size at this point)
+ ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightForXmlOperation;
}
else
{
// no disks to export:
ulTotalOperationsWeight = 1;
- m->ulWeightPerOperation = 1;
+ m->ulWeightForXmlOperation = 1;
}
ULONG ulOVFCreationWeight = (ULONG)((double)ulTotalOperationsWeight * 50.0 / 100.0); /* Use 50% for the creation of the OVF & the disks */
ulTotalOperationsWeight += ulOVFCreationWeight;
@@ -745,8 +765,8 @@ HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress,
break;
}
- Log(("Setting up progress object: ulTotalMB = %d, cDisks = %d, => cOperations = %d, ulTotalOperationsWeight = %d, m->ulWeightPerOperation = %d\n",
- m->ulTotalDisksMB, m->cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightPerOperation));
+ Log(("Setting up progress object: ulTotalMB = %d, cDisks = %d, => cOperations = %d, ulTotalOperationsWeight = %d, m->ulWeightForXmlOperation = %d\n",
+ m->ulTotalDisksMB, m->cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightForXmlOperation));
rc = pProgress->init(mVirtualBox, static_cast<IAppliance*>(this),
bstrDescription,
@@ -754,7 +774,7 @@ HRESULT Appliance::setUpProgress(ComObjPtr<Progress> &pProgress,
cOperations, // ULONG cOperations,
ulTotalOperationsWeight, // ULONG ulTotalOperationsWeight,
bstrDescription, // CBSTR bstrFirstOperationDescription,
- m->ulWeightPerOperation); // ULONG ulFirstOperationWeight,
+ m->ulWeightForXmlOperation); // ULONG ulFirstOperationWeight,
return rc;
}
@@ -1036,10 +1056,10 @@ STDMETHODIMP VirtualSystemDescription::GetDescription(ComSafeArrayOut(VirtualSys
bstr = vsde.strOvf;
bstr.cloneTo(&sfaOrigValues[i]);
- bstr = vsde.strVbox;
+ bstr = vsde.strVboxCurrent;
bstr.cloneTo(&sfaVboxValues[i]);
- bstr = vsde.strExtraConfig;
+ bstr = vsde.strExtraConfigCurrent;
bstr.cloneTo(&sfaExtraConfigValues[i]);
}
@@ -1099,10 +1119,10 @@ STDMETHODIMP VirtualSystemDescription::GetDescriptionByType(VirtualSystemDescrip
bstr = vsde->strOvf;
bstr.cloneTo(&sfaOrigValues[i]);
- bstr = vsde->strVbox;
+ bstr = vsde->strVboxCurrent;
bstr.cloneTo(&sfaVboxValues[i]);
- bstr = vsde->strExtraConfig;
+ bstr = vsde->strExtraConfigCurrent;
bstr.cloneTo(&sfaExtraConfigValues[i]);
}
@@ -1147,8 +1167,8 @@ STDMETHODIMP VirtualSystemDescription::GetValuesByType(VirtualSystemDescriptionT
{
case VirtualSystemDescriptionValueType_Reference: bstr = vsde->strRef; break;
case VirtualSystemDescriptionValueType_Original: bstr = vsde->strOvf; break;
- case VirtualSystemDescriptionValueType_Auto: bstr = vsde->strVbox; break;
- case VirtualSystemDescriptionValueType_ExtraConfig: bstr = vsde->strExtraConfig; break;
+ case VirtualSystemDescriptionValueType_Auto: bstr = vsde->strVboxCurrent; break;
+ case VirtualSystemDescriptionValueType_ExtraConfig: bstr = vsde->strExtraConfigCurrent; break;
}
bstr.cloneTo(&sfaValues[i]);
@@ -1200,8 +1220,8 @@ STDMETHODIMP VirtualSystemDescription::SetFinalValues(ComSafeArrayIn(BOOL, aEnab
if (sfaEnabled[i])
{
- vsde.strVbox = sfaVboxValues[i];
- vsde.strExtraConfig = sfaExtraConfigValues[i];
+ vsde.strVboxCurrent = sfaVboxValues[i];
+ vsde.strExtraConfigCurrent = sfaExtraConfigValues[i];
}
else
vsde.type = VirtualSystemDescriptionType_Ignore;
@@ -1249,8 +1269,12 @@ void VirtualSystemDescription::addEntry(VirtualSystemDescriptionType_T aType,
vsde.type = aType;
vsde.strRef = strRef;
vsde.strOvf = aOvfValue;
- vsde.strVbox = aVboxValue;
- vsde.strExtraConfig = strExtraConfig;
+ vsde.strVboxSuggested // remember original value
+ = vsde.strVboxCurrent // and set current value which can be overridden by setFinalValues()
+ = aVboxValue;
+ vsde.strExtraConfigSuggested
+ = vsde.strExtraConfigCurrent
+ = strExtraConfig;
vsde.ulSizeMB = ulSizeMB;
m->llDescriptions.push_back(vsde);
@@ -1299,6 +1323,7 @@ const VirtualSystemDescriptionEntry* VirtualSystemDescription::findControllerFro
case VirtualSystemDescriptionType_HardDiskControllerIDE:
case VirtualSystemDescriptionType_HardDiskControllerSATA:
case VirtualSystemDescriptionType_HardDiskControllerSCSI:
+ case VirtualSystemDescriptionType_HardDiskControllerSAS:
if (d.strRef == strRef)
return &d;
break;
diff --git a/src/VBox/Main/ApplianceImplExport.cpp b/src/VBox/Main/ApplianceImplExport.cpp
index 3d4a51af4..3e57ef38c 100644
--- a/src/VBox/Main/ApplianceImplExport.cpp
+++ b/src/VBox/Main/ApplianceImplExport.cpp
@@ -1,4 +1,4 @@
-/* $Id: ApplianceImplExport.cpp 29389 2010-05-11 20:10:16Z vboxsync $ */
+/* $Id: ApplianceImplExport.cpp 29984 2010-06-02 12:22:39Z vboxsync $ */
/** @file
*
* IAppliance and IVirtualSystem COM class implementations.
@@ -264,7 +264,7 @@ STDMETHODIMP Machine::Export(IAppliance *aAppliance, IVirtualSystemDescription *
// it should be a SCSI controller
Utf8Str strVbox = "LsiLogicSas";
lSCSIControllerIndex = (int32_t)pNewDesc->m->llDescriptions.size();
- pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskControllerSCSI,
+ pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskControllerSAS,
Utf8StrFmt("%d", lSCSIControllerIndex),
strVbox,
strVbox);
@@ -627,10 +627,9 @@ HRESULT Appliance::writeImpl(OVFFormat aFormat, const LocationInfo &aLocInfo, Co
HRESULT rc = S_OK;
try
{
- Bstr progressDesc = BstrFmt(tr("Export appliance '%s'"),
- aLocInfo.strPath.c_str());
-
- rc = setUpProgress(aProgress, progressDesc, (aLocInfo.storageType == VFSType_File) ? Regular : WriteS3);
+ rc = setUpProgress(aProgress,
+ BstrFmt(tr("Export appliance '%s'"), aLocInfo.strPath.c_str()),
+ (aLocInfo.storageType == VFSType_File) ? WriteFile : WriteS3);
/* Initialize our worker task */
std::auto_ptr<TaskOVF> task(new TaskOVF(this, TaskOVF::Write, aLocInfo, aProgress));
@@ -660,6 +659,7 @@ HRESULT Appliance::writeImpl(OVFFormat aFormat, const LocationInfo &aLocInfo, Co
* @param stack Structure for temporary private data shared with caller.
*/
void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSystemsTo,
+ std::list<xml::ElementNode*> *pllElementsWithUuidAttributes,
ComObjPtr<VirtualSystemDescription> &vsdescThis,
OVFFormat enFormat,
XMLStack &stack)
@@ -682,7 +682,7 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
if (llName.size() != 1)
throw setError(VBOX_E_NOT_SUPPORTED,
tr("Missing VM name"));
- Utf8Str &strVMName = llName.front()->strVbox;
+ Utf8Str &strVMName = llName.front()->strVboxCurrent;
pelmVirtualSystem->setAttribute("ovf:id", strVMName);
// product info
@@ -691,11 +691,11 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
std::list<VirtualSystemDescriptionEntry*> llVendor = vsdescThis->findByType(VirtualSystemDescriptionType_Vendor);
std::list<VirtualSystemDescriptionEntry*> llVendorUrl = vsdescThis->findByType(VirtualSystemDescriptionType_VendorUrl);
std::list<VirtualSystemDescriptionEntry*> llVersion = vsdescThis->findByType(VirtualSystemDescriptionType_Version);
- bool fProduct = llProduct.size() && !llProduct.front()->strVbox.isEmpty();
- bool fProductUrl = llProductUrl.size() && !llProductUrl.front()->strVbox.isEmpty();
- bool fVendor = llVendor.size() && !llVendor.front()->strVbox.isEmpty();
- bool fVendorUrl = llVendorUrl.size() && !llVendorUrl.front()->strVbox.isEmpty();
- bool fVersion = llVersion.size() && !llVersion.front()->strVbox.isEmpty();
+ bool fProduct = llProduct.size() && !llProduct.front()->strVboxCurrent.isEmpty();
+ bool fProductUrl = llProductUrl.size() && !llProductUrl.front()->strVboxCurrent.isEmpty();
+ bool fVendor = llVendor.size() && !llVendor.front()->strVboxCurrent.isEmpty();
+ bool fVendorUrl = llVendorUrl.size() && !llVendorUrl.front()->strVboxCurrent.isEmpty();
+ bool fVersion = llVersion.size() && !llVersion.front()->strVboxCurrent.isEmpty();
if (fProduct ||
fProductUrl ||
fVersion ||
@@ -722,21 +722,21 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
pelmAnnotationSection->createChild("Info")->addContent("Meta-information about the installed software");
if (fProduct)
- pelmAnnotationSection->createChild("Product")->addContent(llProduct.front()->strVbox);
+ pelmAnnotationSection->createChild("Product")->addContent(llProduct.front()->strVboxCurrent);
if (fVendor)
- pelmAnnotationSection->createChild("Vendor")->addContent(llVendor.front()->strVbox);
+ pelmAnnotationSection->createChild("Vendor")->addContent(llVendor.front()->strVboxCurrent);
if (fVersion)
- pelmAnnotationSection->createChild("Version")->addContent(llVersion.front()->strVbox);
+ pelmAnnotationSection->createChild("Version")->addContent(llVersion.front()->strVboxCurrent);
if (fProductUrl)
- pelmAnnotationSection->createChild("ProductUrl")->addContent(llProductUrl.front()->strVbox);
+ pelmAnnotationSection->createChild("ProductUrl")->addContent(llProductUrl.front()->strVboxCurrent);
if (fVendorUrl)
- pelmAnnotationSection->createChild("VendorUrl")->addContent(llVendorUrl.front()->strVbox);
+ pelmAnnotationSection->createChild("VendorUrl")->addContent(llVendorUrl.front()->strVboxCurrent);
}
// description
std::list<VirtualSystemDescriptionEntry*> llDescription = vsdescThis->findByType(VirtualSystemDescriptionType_Description);
if (llDescription.size() &&
- !llDescription.front()->strVbox.isEmpty())
+ !llDescription.front()->strVboxCurrent.isEmpty())
{
/* <Section ovf:required="false" xsi:type="ovf:AnnotationSection_Type">
<Info>A human-readable annotation</Info>
@@ -753,13 +753,13 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
pelmAnnotationSection = pelmVirtualSystem->createChild("AnnotationSection");
pelmAnnotationSection->createChild("Info")->addContent("A human-readable annotation");
- pelmAnnotationSection->createChild("Annotation")->addContent(llDescription.front()->strVbox);
+ pelmAnnotationSection->createChild("Annotation")->addContent(llDescription.front()->strVboxCurrent);
}
// license
std::list<VirtualSystemDescriptionEntry*> llLicense = vsdescThis->findByType(VirtualSystemDescriptionType_License);
if (llLicense.size() &&
- !llLicense.front()->strVbox.isEmpty())
+ !llLicense.front()->strVboxCurrent.isEmpty())
{
/* <EulaSection>
<Info ovf:msgid="6">License agreement for the Virtual System.</Info>
@@ -775,7 +775,7 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
pelmEulaSection = pelmVirtualSystem->createChild("EulaSection");
pelmEulaSection->createChild("Info")->addContent("License agreement for the virtual system");
- pelmEulaSection->createChild("License")->addContent(llLicense.front()->strVbox);
+ pelmEulaSection->createChild("License")->addContent(llLicense.front()->strVboxCurrent);
}
// operating system
@@ -874,12 +874,13 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
( desc.type == VirtualSystemDescriptionType_HardDiskControllerIDE ? "HardDiskControllerIDE"
: desc.type == VirtualSystemDescriptionType_HardDiskControllerSATA ? "HardDiskControllerSATA"
: desc.type == VirtualSystemDescriptionType_HardDiskControllerSCSI ? "HardDiskControllerSCSI"
+ : desc.type == VirtualSystemDescriptionType_HardDiskControllerSAS ? "HardDiskControllerSAS"
: desc.type == VirtualSystemDescriptionType_HardDiskImage ? "HardDiskImage"
: Utf8StrFmt("%d", desc.type).c_str()),
desc.strRef.c_str(),
desc.strOvf.c_str(),
- desc.strVbox.c_str(),
- desc.strExtraConfig.c_str()));
+ desc.strVboxCurrent.c_str(),
+ desc.strExtraConfigCurrent.c_str()));
ovf::ResourceType_T type = (ovf::ResourceType_T)0; // if this becomes != 0 then we do stuff
Utf8Str strResourceSubType;
@@ -917,7 +918,7 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
{
strDescription = "Number of virtual CPUs";
type = ovf::ResourceType_Processor; // 3
- desc.strVbox.toInt(uTemp);
+ desc.strVboxCurrent.toInt(uTemp);
lVirtualQuantity = (int32_t)uTemp;
strCaption = Utf8StrFmt("%d virtual CPU", lVirtualQuantity); // without this ovftool won't eat the item
}
@@ -937,7 +938,7 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
{
strDescription = "Memory Size";
type = ovf::ResourceType_Memory; // 4
- desc.strVbox.toInt(uTemp);
+ desc.strVboxCurrent.toInt(uTemp);
lVirtualQuantity = (int32_t)(uTemp / _1M);
strAllocationUnits = "MegaBytes";
strCaption = Utf8StrFmt("%d MB of memory", lVirtualQuantity); // without this ovftool won't eat the item
@@ -957,7 +958,7 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
{
strDescription = "IDE Controller";
type = ovf::ResourceType_IDEController; // 5
- strResourceSubType = desc.strVbox;
+ strResourceSubType = desc.strVboxCurrent;
if (!lIDEPrimaryControllerIndex)
{
@@ -1003,13 +1004,13 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
lAddress = 0;
lBusNumber = 0;
- if ( desc.strVbox.isEmpty() // AHCI is the default in VirtualBox
- || (!desc.strVbox.compare("ahci", Utf8Str::CaseInsensitive))
- )
+ if ( desc.strVboxCurrent.isEmpty() // AHCI is the default in VirtualBox
+ || (!desc.strVboxCurrent.compare("ahci", Utf8Str::CaseInsensitive))
+ )
strResourceSubType = "AHCI";
else
throw setError(VBOX_E_NOT_SUPPORTED,
- tr("Invalid config string \"%s\" in SATA controller"), desc.strVbox.c_str());
+ tr("Invalid config string \"%s\" in SATA controller"), desc.strVboxCurrent.c_str());
// remember this ID
idSATAController = ulInstanceID;
@@ -1018,6 +1019,7 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
break;
case VirtualSystemDescriptionType_HardDiskControllerSCSI:
+ case VirtualSystemDescriptionType_HardDiskControllerSAS:
/* <Item>
<rasd:Caption>scsiController0</rasd:Caption>
<rasd:Description>SCSI Controller</rasd:Description>
@@ -1038,17 +1040,17 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
lAddress = 0;
lBusNumber = 0;
- if ( desc.strVbox.isEmpty() // LsiLogic is the default in VirtualBox
- || (!desc.strVbox.compare("lsilogic", Utf8Str::CaseInsensitive))
+ if ( desc.strVboxCurrent.isEmpty() // LsiLogic is the default in VirtualBox
+ || (!desc.strVboxCurrent.compare("lsilogic", Utf8Str::CaseInsensitive))
)
strResourceSubType = "lsilogic";
- else if (!desc.strVbox.compare("buslogic", Utf8Str::CaseInsensitive))
+ else if (!desc.strVboxCurrent.compare("buslogic", Utf8Str::CaseInsensitive))
strResourceSubType = "buslogic";
- else if (!desc.strVbox.compare("lsilogicsas", Utf8Str::CaseInsensitive))
+ else if (!desc.strVboxCurrent.compare("lsilogicsas", Utf8Str::CaseInsensitive))
strResourceSubType = "lsilogicsas";
else
throw setError(VBOX_E_NOT_SUPPORTED,
- tr("Invalid config string \"%s\" in SCSI controller"), desc.strVbox.c_str());
+ tr("Invalid config string \"%s\" in SCSI/SAS controller"), desc.strVboxCurrent.c_str());
// remember this ID
idSCSIController = ulInstanceID;
@@ -1078,12 +1080,12 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
strHostResource = Utf8StrFmt("/disk/%s", strDiskID.c_str());
// controller=<index>;channel=<c>
- size_t pos1 = desc.strExtraConfig.find("controller=");
- size_t pos2 = desc.strExtraConfig.find("channel=");
+ size_t pos1 = desc.strExtraConfigCurrent.find("controller=");
+ size_t pos2 = desc.strExtraConfigCurrent.find("channel=");
int32_t lControllerIndex = -1;
if (pos1 != Utf8Str::npos)
{
- RTStrToInt32Ex(desc.strExtraConfig.c_str() + pos1 + 11, NULL, 0, &lControllerIndex);
+ RTStrToInt32Ex(desc.strExtraConfigCurrent.c_str() + pos1 + 11, NULL, 0, &lControllerIndex);
if (lControllerIndex == lIDEPrimaryControllerIndex)
ulParent = idIDEPrimaryController;
else if (lControllerIndex == lIDESecondaryControllerIndex)
@@ -1094,7 +1096,7 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
ulParent = idSATAController;
}
if (pos2 != Utf8Str::npos)
- RTStrToInt32Ex(desc.strExtraConfig.c_str() + pos2 + 8, NULL, 0, &lAddressOnParent);
+ RTStrToInt32Ex(desc.strExtraConfigCurrent.c_str() + pos2 + 8, NULL, 0, &lAddressOnParent);
LogFlowFunc(("HardDiskImage details: pos1=%d, pos2=%d, lControllerIndex=%d, lIDEPrimaryControllerIndex=%d, lIDESecondaryControllerIndex=%d, ulParent=%d, lAddressOnParent=%d\n",
pos1, pos2, lControllerIndex, lIDEPrimaryControllerIndex, lIDESecondaryControllerIndex, ulParent, lAddressOnParent));
@@ -1103,7 +1105,7 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
|| lAddressOnParent == -1
)
throw setError(VBOX_E_NOT_SUPPORTED,
- tr("Missing or bad extra config string in hard disk image: \"%s\""), desc.strExtraConfig.c_str());
+ tr("Missing or bad extra config string in hard disk image: \"%s\""), desc.strExtraConfigCurrent.c_str());
stack.mapDisks[strDiskID] = &desc;
}
@@ -1155,7 +1157,7 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
* To be compatible with vmware & others we set
* PCNet32 for our PCNet types & E1000 for the
* E1000 cards. */
- switch (desc.strVbox.toInt32())
+ switch (desc.strVboxCurrent.toInt32())
{
case NetworkAdapterType_Am79C970A:
case NetworkAdapterType_Am79C973: strResourceSubType = "PCNet32"; break;
@@ -1297,8 +1299,9 @@ void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSys
// write the machine config to the vbox:Machine element
pConfig->buildMachineXML(*pelmVBoxMachine,
settings::MachineConfigFile::BuildMachineXML_WriteVboxVersionAttribute
- | settings::MachineConfigFile::BuildMachineXML_SkipRemovableMedia);
+ | settings::MachineConfigFile::BuildMachineXML_SkipRemovableMedia,
// but not BuildMachineXML_IncludeSnapshots
+ pllElementsWithUuidAttributes);
delete pConfig;
}
catch (...)
@@ -1424,6 +1427,10 @@ HRESULT Appliance::writeFS(const LocationInfo &locInfo, const OVFFormat enFormat
else
pelmToAddVirtualSystemsTo = pelmRoot; // add virtual system directly under root element
+ // this list receives pointers to the XML elements in the machine XML which
+ // might have UUIDs that need fixing after we know the UUIDs of the exported images
+ std::list<xml::ElementNode*> llElementsWithUuidAttributes;
+
list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
/* Iterate throughs all virtual systems of that appliance */
for (it = m->virtualSystemDescriptions.begin();
@@ -1432,6 +1439,7 @@ HRESULT Appliance::writeFS(const LocationInfo &locInfo, const OVFFormat enFormat
{
ComObjPtr<VirtualSystemDescription> vsdescThis = *it;
buildXMLForOneVirtualSystem(*pelmToAddVirtualSystemsTo,
+ &llElementsWithUuidAttributes,
vsdescThis,
enFormat,
stack); // disks and networks stack
@@ -1463,7 +1471,7 @@ HRESULT Appliance::writeFS(const LocationInfo &locInfo, const OVFFormat enFormat
const VirtualSystemDescriptionEntry *pDiskEntry = itS->second;
// source path: where the VBox image is
- const Utf8Str &strSrcFilePath = pDiskEntry->strVbox;
+ const Utf8Str &strSrcFilePath = pDiskEntry->strVboxCurrent;
Bstr bstrSrcFilePath(strSrcFilePath);
if (!RTPathExists(strSrcFilePath.c_str()))
/* This isn't allowed */
@@ -1510,9 +1518,8 @@ HRESULT Appliance::writeFS(const LocationInfo &locInfo, const OVFFormat enFormat
if (FAILED(rc)) throw rc;
// advance to the next operation
- if (!pProgress.isNull())
- pProgress->SetNextOperation(BstrFmt(tr("Exporting to disk image '%s'"), strTargetFilePath.c_str()),
- pDiskEntry->ulSizeMB); // operation's weight, as set up with the IProgress originally);
+ pProgress->SetNextOperation(BstrFmt(tr("Exporting to disk image '%s'"), strTargetFilePath.c_str()),
+ pDiskEntry->ulSizeMB); // operation's weight, as set up with the IProgress originally);
// now wait for the background disk operation to complete; this throws HRESULTs on error
waitForAsyncProgress(pProgress, pProgress2);
@@ -1537,6 +1544,11 @@ HRESULT Appliance::writeFS(const LocationInfo &locInfo, const OVFFormat enFormat
// capacity is reported in megabytes, so...
cbCapacity *= _1M;
+ Bstr uuidTarget;
+ rc = pTargetDisk->COMGETTER(Id)(uuidTarget.asOutParam());
+ if (FAILED(rc)) throw rc;
+ Guid guidTarget(uuidTarget);
+
// upon success, close the disk as well
rc = pTargetDisk->Close();
if (FAILED(rc)) throw rc;
@@ -1561,14 +1573,34 @@ HRESULT Appliance::writeFS(const LocationInfo &locInfo, const OVFFormat enFormat
: "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized"
// correct string as communicated to us by VMware (public bug #6612)
);
- pelmDisk->setAttribute("vbox:uuid", Utf8StrFmt("%RTuuid", guidSource.raw()).c_str());
+
+ // add the UUID of the newly created target image to the OVF disk element, but in the
+ // vbox: namespace since it's not part of the standard
+ pelmDisk->setAttribute("vbox:uuid", Utf8StrFmt("%RTuuid", guidTarget.raw()).c_str());
+
+ // now, we might have other XML elements from vbox:Machine pointing to this image,
+ // but those would refer to the UUID of the _source_ image (which we created the
+ // export image from); those UUIDs need to be fixed to the export image
+ for (std::list<xml::ElementNode*>::iterator eit = llElementsWithUuidAttributes.begin();
+ eit != llElementsWithUuidAttributes.end();
+ ++eit)
+ {
+ xml::ElementNode *pelmImage = *eit;
+ // overwrite existing uuid attribute
+ pelmImage->setAttribute("uuid", guidTarget.toStringCurly());
+ }
}
// now go write the XML
xml::XmlFileWriter writer(doc);
writer.write(locInfo.strPath.c_str(), false /*fSafe*/);
- /* Create & write the manifest file */
+ // Create & write the manifest file
+ Utf8Str strMfFile = manifestFileName(locInfo.strPath.c_str());
+ const char *pcszManifestFileOnly = RTPathFilename(strMfFile.c_str());
+ pProgress->SetNextOperation(BstrFmt(tr("Creating manifest file '%s'"), pcszManifestFileOnly),
+ m->ulWeightForManifestOperation); // operation's weight, as set up with the IProgress originally);
+
const char** ppManifestFiles = (const char**)RTMemAlloc(sizeof(char*)*diskList.size() + 1);
ppManifestFiles[0] = locInfo.strPath.c_str();
list<Utf8Str>::const_iterator it1;
@@ -1577,13 +1609,12 @@ HRESULT Appliance::writeFS(const LocationInfo &locInfo, const OVFFormat enFormat
it1 != diskList.end();
++it1, ++i)
ppManifestFiles[i] = (*it1).c_str();
- Utf8Str strMfFile = manifestFileName(locInfo.strPath.c_str());
- int vrc = RTManifestWriteFiles(strMfFile.c_str(), ppManifestFiles, diskList.size()+1);
+ int vrc = RTManifestWriteFiles(strMfFile.c_str(), ppManifestFiles, diskList.size()+1, NULL, NULL);
RTMemFree(ppManifestFiles);
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR,
- tr("Couldn't create manifest file '%s' (%Rrc)"),
- RTPathFilename(strMfFile.c_str()), vrc);
+ tr("Could not create manifest file '%s' (%Rrc)"),
+ pcszManifestFileOnly, vrc);
}
catch(xml::Error &x)
{
@@ -1677,9 +1708,9 @@ HRESULT Appliance::writeS3(TaskOVF *pTask)
throw setError(VBOX_E_FILE_ERROR,
tr("Cannot find source file '%s'"), strTmpOvf.c_str());
/* Add the OVF file */
- filesList.push_back(pair<Utf8Str, ULONG>(strTmpOvf, m->ulWeightPerOperation)); /* Use 1% of the total for the OVF file upload */
+ filesList.push_back(pair<Utf8Str, ULONG>(strTmpOvf, m->ulWeightForXmlOperation)); /* Use 1% of the total for the OVF file upload */
Utf8Str strMfFile = manifestFileName(strTmpOvf);
- filesList.push_back(pair<Utf8Str, ULONG>(strMfFile , m->ulWeightPerOperation)); /* Use 1% of the total for the manifest file upload */
+ filesList.push_back(pair<Utf8Str, ULONG>(strMfFile , m->ulWeightForXmlOperation)); /* Use 1% of the total for the manifest file upload */
/* Now add every disks of every virtual system */
list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
@@ -1720,8 +1751,7 @@ HRESULT Appliance::writeS3(TaskOVF *pTask)
const pair<Utf8Str, ULONG> &s = (*it1);
char *pszFilename = RTPathFilename(s.first.c_str());
/* Advance to the next operation */
- if (!pTask->pProgress.isNull())
- pTask->pProgress->SetNextOperation(BstrFmt(tr("Uploading file '%s'"), pszFilename), s.second);
+ pTask->pProgress->SetNextOperation(BstrFmt(tr("Uploading file '%s'"), pszFilename), s.second);
vrc = RTS3PutKey(hS3, bucket.c_str(), pszFilename, s.first.c_str());
if (RT_FAILURE(vrc))
{
diff --git a/src/VBox/Main/ApplianceImplImport.cpp b/src/VBox/Main/ApplianceImplImport.cpp
index 641ebbdd1..027ffc427 100644
--- a/src/VBox/Main/ApplianceImplImport.cpp
+++ b/src/VBox/Main/ApplianceImplImport.cpp
@@ -1,4 +1,4 @@
-/* $Id: ApplianceImplImport.cpp 29422 2010-05-12 14:08:52Z vboxsync $ */
+/* $Id: ApplianceImplImport.cpp 29981 2010-06-02 12:11:39Z vboxsync $ */
/** @file
*
* IAppliance and IVirtualSystem COM class implementations.
@@ -49,7 +49,9 @@ using namespace std;
////////////////////////////////////////////////////////////////////////////////
/**
- * Public method implementation.
+ * Public method implementation. This opens the OVF with ovfreader.cpp.
+ * Thread implementation is in Appliance::readImpl().
+ *
* @param path
* @return
*/
@@ -99,7 +101,8 @@ STDMETHODIMP Appliance::Read(IN_BSTR path, IProgress **aProgress)
}
/**
- * Public method implementation.
+ * Public method implementation. This looks at the output of ovfreader.cpp and creates
+ * VirtualSystemDescription instances.
* @return
*/
STDMETHODIMP Appliance::Interpret()
@@ -440,15 +443,20 @@ STDMETHODIMP Appliance::Interpret()
/* Check for the constrains */
if (cSCSIused < 1)
{
+ VirtualSystemDescriptionType_T vsdet = VirtualSystemDescriptionType_HardDiskControllerSCSI;
Utf8Str hdcController = "LsiLogic";
if (!hdc.strControllerType.compare("lsilogicsas", Utf8Str::CaseInsensitive))
+ {
+ // OVF considers SAS a variant of SCSI but VirtualBox considers it a class of its own
+ vsdet = VirtualSystemDescriptionType_HardDiskControllerSAS;
hdcController = "LsiLogicSas";
+ }
else if (!hdc.strControllerType.compare("BusLogic", Utf8Str::CaseInsensitive))
hdcController = "BusLogic";
- pNewDesc->addEntry(VirtualSystemDescriptionType_HardDiskControllerSCSI,
- strControllerID,
- hdc.strControllerType,
- hdcController);
+ pNewDesc->addEntry(vsdet,
+ strControllerID,
+ hdc.strControllerType,
+ hdcController);
}
else
addWarning(tr("The virtual system \"%s\" requests support for an additional SCSI controller of type \"%s\" with ID %s, but VirtualBox presently supports only one SCSI controller."),
@@ -538,7 +546,9 @@ STDMETHODIMP Appliance::Interpret()
}
/**
- * Public method implementation.
+ * Public method implementation. This creates one or more new machines according to the
+ * VirtualSystemScription instances created by Appliance::Interpret().
+ * Thread implementation is in Appliance::importImpl().
* @param aProgress
* @return
*/
@@ -586,6 +596,7 @@ STDMETHODIMP Appliance::ImportMachines(IProgress **aProgress)
/**
* Implementation for reading an OVF. This starts a new thread which will call
* Appliance::taskThreadImportOrExport() which will then call readFS() or readS3().
+ * This will then open the OVF with ovfreader.cpp.
*
* This is in a separate private method because it is used from two locations:
*
@@ -634,7 +645,9 @@ HRESULT Appliance::readImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &a
/**
* Actual worker code for reading an OVF from disk. This is called from Appliance::taskThreadImportOrExport()
- * and therefore runs on the OVF read worker thread. This runs in two contexts:
+ * and therefore runs on the OVF read worker thread. This opens the OVF with ovfreader.cpp.
+ *
+ * This runs in two contexts:
*
* 1) in a first worker thread; in that case, Appliance::Read() called Appliance::readImpl();
*
@@ -662,7 +675,7 @@ HRESULT Appliance::readFS(const LocationInfo &locInfo)
m->pReader = new ovf::OVFReader(locInfo.strPath);
/* Create the SHA1 sum of the OVF file for later validation */
char *pszDigest;
- int vrc = RTSha1Digest(locInfo.strPath.c_str(), &pszDigest);
+ int vrc = RTSha1Digest(locInfo.strPath.c_str(), &pszDigest, NULL, NULL);
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR,
tr("Couldn't calculate SHA1 digest for file '%s' (%Rrc)"),
@@ -761,8 +774,7 @@ HRESULT Appliance::readS3(TaskOVF *pTask)
RTS3Destroy(hS3);
hS3 = NIL_RTS3;
- if (!pTask->pProgress.isNull())
- pTask->pProgress->SetNextOperation(Bstr(tr("Reading")), 1);
+ pTask->pProgress->SetNextOperation(Bstr(tr("Reading")), 1);
/* Prepare the temporary reading of the OVF */
ComObjPtr<Progress> progress;
@@ -911,6 +923,9 @@ void Appliance::convertDiskAttachmentValues(const ovf::HardDiskController &hdc,
* Implementation for importing OVF data into VirtualBox. This starts a new thread which will call
* Appliance::taskThreadImportOrExport().
*
+ * This creates one or more new machines according to the VirtualSystemScription instances created by
+ * Appliance::Interpret().
+ *
* This is in a separate private method because it is used from two locations:
*
* 1) from the public Appliance::ImportMachines().
@@ -920,15 +935,30 @@ void Appliance::convertDiskAttachmentValues(const ovf::HardDiskController &hdc,
* @param aProgress
* @return
*/
-HRESULT Appliance::importImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress)
+HRESULT Appliance::importImpl(const LocationInfo &aLocInfo,
+ ComObjPtr<Progress> &aProgress)
{
- Bstr progressDesc = BstrFmt(tr("Importing appliance '%s'"),
- aLocInfo.strPath.c_str());
HRESULT rc = S_OK;
+ SetUpProgressMode mode;
+ m->strManifestFile.setNull();
+ if (aLocInfo.storageType == VFSType_File)
+ {
+ Utf8Str strMfFile = manifestFileName(aLocInfo.strPath);
+ if (RTPathExists(strMfFile.c_str()))
+ {
+ m->strManifestFile = strMfFile;
+ mode = ImportFileWithManifest;
+ }
+ else
+ mode = ImportFileNoManifest;
+ }
+ else
+ mode = ImportS3;
+
rc = setUpProgress(aProgress,
- progressDesc,
- (aLocInfo.storageType == VFSType_File) ? Regular : ImportS3);
+ BstrFmt(tr("Importing appliance '%s'"), aLocInfo.strPath.c_str()),
+ mode);
if (FAILED(rc)) throw rc;
/* Initialize our worker task */
@@ -944,43 +974,6 @@ HRESULT Appliance::importImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress>
}
/**
- * Used by Appliance::importMachineGeneric() to store
- * input parameters and rollback information.
- */
-struct Appliance::ImportStack
-{
- // input pointers
- const LocationInfo &locInfo; // ptr to location info from Appliance::importFS()
- Utf8Str strSourceDir; // directory where source files reside
- const ovf::DiskImagesMap &mapDisks; // ptr to disks map in OVF
- ComObjPtr<Progress> &pProgress; // progress object passed into Appliance::importFS()
-
- // session (not initially created)
- ComPtr<ISession> pSession; // session opened in Appliance::importFS() for machine manipulation
- bool fSessionOpen; // true if the pSession is currently open and needs closing
-
- // a list of images that we created/imported; this is initially empty
- // and will be cleaned up on errors
- list<MyHardDiskAttachment> llHardDiskAttachments; // disks that were attached
- list< ComPtr<IMedium> > llHardDisksCreated; // media that were created
- list<Bstr> llMachinesRegistered; // machines that were registered; list of string UUIDs
-
- ImportStack(const LocationInfo &aLocInfo,
- const ovf::DiskImagesMap &aMapDisks,
- ComObjPtr<Progress> &aProgress)
- : locInfo(aLocInfo),
- mapDisks(aMapDisks),
- pProgress(aProgress),
- fSessionOpen(false)
- {
- // disk images have to be on the same place as the OVF file. So
- // strip the filename out of the full file path
- strSourceDir = aLocInfo.strPath;
- strSourceDir.stripFilename();
- }
-};
-
-/**
* Checks if a manifest file exists in the given location and, if so, verifies
* that the relevant files (the OVF XML and the disks referenced by it, as
* represented by the VirtualSystemDescription instances contained in this appliance)
@@ -991,13 +984,17 @@ struct Appliance::ImportStack
* @return
*/
HRESULT Appliance::manifestVerify(const LocationInfo &locInfo,
- const ovf::OVFReader &reader)
+ const ovf::OVFReader &reader,
+ ComObjPtr<Progress> &pProgress)
{
HRESULT rc = S_OK;
- Utf8Str strMfFile = manifestFileName(locInfo.strPath);
- if (RTPathExists(strMfFile.c_str()))
+ if (!m->strManifestFile.isEmpty())
{
+ const char *pcszManifestFileOnly = RTPathFilename(m->strManifestFile.c_str());
+ pProgress->SetNextOperation(BstrFmt(tr("Verifying manifest file '%s'"), pcszManifestFileOnly),
+ m->ulWeightForManifestOperation); // operation's weight, as set up with the IProgress originally
+
list<Utf8Str> filesList;
Utf8Str strSrcDir(locInfo.strPath);
strSrcDir.stripFilename();
@@ -1035,35 +1032,35 @@ HRESULT Appliance::manifestVerify(const LocationInfo &locInfo,
++it1, ++i)
{
char* pszDigest;
- vrc = RTSha1Digest((*it1).c_str(), &pszDigest);
+ vrc = RTSha1Digest((*it1).c_str(), &pszDigest, NULL, NULL);
pTestList[i].pszTestFile = (char*)(*it1).c_str();
pTestList[i].pszTestDigest = pszDigest;
}
// this call can take a very long time
size_t cIndexOnError;
- vrc = RTManifestVerify(strMfFile.c_str(),
+ vrc = RTManifestVerify(m->strManifestFile.c_str(),
pTestList,
filesList.size() + 1,
&cIndexOnError);
- // clean up
- for (size_t j = 1;
- j < filesList.size();
- ++j)
- RTStrFree(pTestList[j].pszTestDigest);
- RTMemFree(pTestList);
-
if (vrc == VERR_MANIFEST_DIGEST_MISMATCH)
rc = setError(VBOX_E_FILE_ERROR,
tr("The SHA1 digest of '%s' does not match the one in '%s'"),
RTPathFilename(pTestList[cIndexOnError].pszTestFile),
- RTPathFilename(strMfFile.c_str()));
+ pcszManifestFileOnly);
else if (RT_FAILURE(vrc))
rc = setError(VBOX_E_FILE_ERROR,
tr("Could not verify the content of '%s' against the available files (%Rrc)"),
- RTPathFilename(strMfFile.c_str()),
+ pcszManifestFileOnly,
vrc);
+
+ // clean up
+ for (size_t j = 1;
+ j < filesList.size();
+ ++j)
+ RTStrFree(pTestList[j].pszTestDigest);
+ RTMemFree(pTestList);
}
return rc;
@@ -1071,7 +1068,10 @@ HRESULT Appliance::manifestVerify(const LocationInfo &locInfo,
/**
* Actual worker code for importing OVF data into VirtualBox. This is called from Appliance::taskThreadImportOrExport()
- * and therefore runs on the OVF import worker thread. This runs in two contexts:
+ * and therefore runs on the OVF import worker thread. This creates one or more new machines according to the
+ * VirtualSystemScription instances created by Appliance::Interpret().
+ *
+ * This runs in two contexts:
*
* 1) in a first worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl();
*
@@ -1115,7 +1115,7 @@ HRESULT Appliance::importFS(const LocationInfo &locInfo,
try
{
// if a manifest file exists, verify the content; we then need all files which are referenced by the OVF & the OVF itself
- rc = manifestVerify(locInfo, reader);
+ rc = manifestVerify(locInfo, reader, pProgress);
if (FAILED(rc)) throw rc;
// create a session for the machine + disks we manipulate below
@@ -1143,13 +1143,72 @@ HRESULT Appliance::importFS(const LocationInfo &locInfo,
// -- or this is an OVF from an older vbox or an external source, and then we need to translate the
// VirtualSystemDescriptionEntry and do import work
- // @todo r=dj make this selection configurable at run-time, and from the GUI as well
+ // Even for the vbox:Machine case, there are a number of configuration items that will be taken from
+ // the OVF because otherwise the "override import parameters" mechanism in the GUI won't work.
+
+ // VM name
+ std::list<VirtualSystemDescriptionEntry*> vsdeName = vsdescThis->findByType(VirtualSystemDescriptionType_Name);
+ if (vsdeName.size() < 1)
+ throw setError(VBOX_E_FILE_ERROR,
+ tr("Missing VM name"));
+ stack.strNameVBox = vsdeName.front()->strVboxCurrent;
+
+ // guest OS type
+ std::list<VirtualSystemDescriptionEntry*> vsdeOS;
+ vsdeOS = vsdescThis->findByType(VirtualSystemDescriptionType_OS);
+ if (vsdeOS.size() < 1)
+ throw setError(VBOX_E_FILE_ERROR,
+ tr("Missing guest OS type"));
+ stack.strOsTypeVBox = vsdeOS.front()->strVboxCurrent;
+
+ // CPU count
+ std::list<VirtualSystemDescriptionEntry*> vsdeCPU = vsdescThis->findByType(VirtualSystemDescriptionType_CPU);
+ ComAssertMsgThrow(vsdeCPU.size() == 1, ("CPU count missing"), E_FAIL);
+ const Utf8Str &cpuVBox = vsdeCPU.front()->strVboxCurrent;
+ stack.cCPUs = (uint32_t)RTStrToUInt64(cpuVBox.c_str());
+ // We need HWVirt & IO-APIC if more than one CPU is requested
+ if (stack.cCPUs > 1)
+ {
+ stack.fForceHWVirt = true;
+ stack.fForceIOAPIC = true;
+ }
+
+ // RAM
+ std::list<VirtualSystemDescriptionEntry*> vsdeRAM = vsdescThis->findByType(VirtualSystemDescriptionType_Memory);
+ ComAssertMsgThrow(vsdeRAM.size() == 1, ("RAM size missing"), E_FAIL);
+ const Utf8Str &memoryVBox = vsdeRAM.front()->strVboxCurrent;
+ stack.ulMemorySizeMB = (uint32_t)RTStrToUInt64(memoryVBox.c_str());
+ // USB controller
+#ifdef VBOX_WITH_USB
+ /* USB Controller */
+ std::list<VirtualSystemDescriptionEntry*> vsdeUSBController = vsdescThis->findByType(VirtualSystemDescriptionType_USBController);
+ // USB support is enabled if there's at least one such entry; to disable USB support,
+ // the type of the USB item would have been changed to "ignore"
+ stack.fUSBEnabled = vsdeUSBController.size() > 0;
+#endif
+ // audio adapter
+ std::list<VirtualSystemDescriptionEntry*> vsdeAudioAdapter = vsdescThis->findByType(VirtualSystemDescriptionType_SoundCard);
+ /* @todo: we support one audio adapter only */
+ if (vsdeAudioAdapter.size() > 0)
+ stack.strAudioAdapter = vsdeAudioAdapter.front()->strVboxCurrent;
+
+ // import vbox:machine or OVF now
if (vsdescThis->m->pConfig)
+ // vbox:Machine config
importVBoxMachine(vsdescThis, pNewMachine, stack);
else
+ // generic OVF config
importMachineGeneric(vsysThis, vsdescThis, pNewMachine, stack);
+ // for the description of the new machine, always use the OVF entry, the user may have changed it in the import config
+ std::list<VirtualSystemDescriptionEntry*> vsdeDescription = vsdescThis->findByType(VirtualSystemDescriptionType_Description);
+ if (vsdeDescription.size())
+ {
+ const Utf8Str &strDescription = vsdeDescription.front()->strVboxCurrent;
+ rc = pNewMachine->COMSETTER(Description)(Bstr(strDescription));
+ if (FAILED(rc)) throw rc;
+ }
} // for (it = pAppliance->m->llVirtualSystems.begin() ...
}
catch (HRESULT rc2)
@@ -1215,6 +1274,7 @@ HRESULT Appliance::importFS(const LocationInfo &locInfo,
// restore the appliance state
appLock.acquire();
m->state = Data::ApplianceIdle;
+ appLock.release();
LogFlowFunc(("rc=%Rhrc\n", rc));
LogFlowFuncLeave();
@@ -1258,7 +1318,6 @@ void Appliance::importOneDiskImage(const ovf::DiskImage &di,
if ( strTargetPath.isEmpty()
|| RTPathExists(strTargetPath.c_str())
)
- /* This isn't allowed */
throw setError(VBOX_E_FILE_ERROR,
tr("Destination file '%s' exists"),
strTargetPath.c_str());
@@ -1293,7 +1352,7 @@ void Appliance::importOneDiskImage(const ovf::DiskImage &di,
if (FAILED(rc)) throw rc;
// advance to the next operation
- stack.pProgress->SetNextOperation(BstrFmt(tr("Creating virtual disk image '%s'"), strTargetPath.c_str()),
+ stack.pProgress->SetNextOperation(BstrFmt(tr("Creating disk image '%s'"), strTargetPath.c_str()),
di.ulSuggestedSizeMB); // operation's weight, as set up with the IProgress originally
}
else
@@ -1312,12 +1371,12 @@ void Appliance::importOneDiskImage(const ovf::DiskImage &di,
// First open the existing disk image
rc = mVirtualBox->OpenHardDisk(Bstr(strSrcFilePath),
- AccessMode_ReadOnly,
- false,
- NULL,
- false,
- NULL,
- pSourceHD.asOutParam());
+ AccessMode_ReadOnly,
+ false,
+ NULL,
+ false,
+ NULL,
+ pSourceHD.asOutParam());
if (FAILED(rc)) throw rc;
fSourceHdNeedsClosing = true;
@@ -1366,77 +1425,54 @@ void Appliance::importOneDiskImage(const ovf::DiskImage &di,
* up any leftovers from this function. For this, the given ImportStack instance has received information
* about what needs cleaning up (to support rollback).
*
- * @param locInfo
- * @param vsysThis
- * @param vsdescThis
- * @param pNewMachine
- * @param stack
+ * @param vsysThis OVF virtual system (machine) to import.
+ * @param vsdescThis Matching virtual system description (machine) to import.
+ * @param pNewMachine out: Newly created machine.
+ * @param stack Cleanup stack for when this throws.
*/
void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
ComObjPtr<VirtualSystemDescription> &vsdescThis,
ComPtr<IMachine> &pNewMachine,
ImportStack &stack)
{
- /* Guest OS type */
- std::list<VirtualSystemDescriptionEntry*> vsdeOS;
- vsdeOS = vsdescThis->findByType(VirtualSystemDescriptionType_OS);
- if (vsdeOS.size() < 1)
- throw setError(VBOX_E_FILE_ERROR,
- tr("Missing guest OS type"));
- const Utf8Str &strOsTypeVBox = vsdeOS.front()->strVbox;
+ HRESULT rc;
- /* Now that we know the base system get our internal defaults based on that. */
+ // Get the instance of IGuestOSType which matches our string guest OS type so we
+ // can use recommended defaults for the new machine where OVF doesen't provice any
ComPtr<IGuestOSType> osType;
- HRESULT rc = mVirtualBox->GetGuestOSType(Bstr(strOsTypeVBox), osType.asOutParam());
+ rc = mVirtualBox->GetGuestOSType(Bstr(stack.strOsTypeVBox), osType.asOutParam());
if (FAILED(rc)) throw rc;
/* Create the machine */
- /* First get the name */
- std::list<VirtualSystemDescriptionEntry*> vsdeName = vsdescThis->findByType(VirtualSystemDescriptionType_Name);
- if (vsdeName.size() < 1)
- throw setError(VBOX_E_FILE_ERROR,
- tr("Missing VM name"));
- const Utf8Str &strNameVBox = vsdeName.front()->strVbox;
- rc = mVirtualBox->CreateMachine(Bstr(strNameVBox),
- Bstr(strOsTypeVBox),
+ rc = mVirtualBox->CreateMachine(Bstr(stack.strNameVBox),
+ Bstr(stack.strOsTypeVBox),
NULL,
NULL,
FALSE,
pNewMachine.asOutParam());
if (FAILED(rc)) throw rc;
- // and the description
+ // set the description
std::list<VirtualSystemDescriptionEntry*> vsdeDescription = vsdescThis->findByType(VirtualSystemDescriptionType_Description);
if (vsdeDescription.size())
{
- const Utf8Str &strDescription = vsdeDescription.front()->strVbox;
+ const Utf8Str &strDescription = vsdeDescription.front()->strVboxCurrent;
rc = pNewMachine->COMSETTER(Description)(Bstr(strDescription));
if (FAILED(rc)) throw rc;
}
- /* CPU count */
- std::list<VirtualSystemDescriptionEntry*> vsdeCPU = vsdescThis->findByType(VirtualSystemDescriptionType_CPU);
- ComAssertMsgThrow(vsdeCPU.size() == 1, ("CPU count missing"), E_FAIL);
- const Utf8Str &cpuVBox = vsdeCPU.front()->strVbox;
- ULONG tmpCount = (ULONG)RTStrToUInt64(cpuVBox.c_str());
- rc = pNewMachine->COMSETTER(CPUCount)(tmpCount);
+ // CPU count
+ rc = pNewMachine->COMSETTER(CPUCount)(stack.cCPUs);
if (FAILED(rc)) throw rc;
- bool fEnableIOApic = false;
- /* We need HWVirt & IO-APIC if more than one CPU is requested */
- if (tmpCount > 1)
+
+ if (stack.fForceHWVirt)
{
rc = pNewMachine->SetHWVirtExProperty(HWVirtExPropertyType_Enabled, TRUE);
if (FAILED(rc)) throw rc;
-
- fEnableIOApic = true;
}
- /* RAM */
- std::list<VirtualSystemDescriptionEntry*> vsdeRAM = vsdescThis->findByType(VirtualSystemDescriptionType_Memory);
- ComAssertMsgThrow(vsdeRAM.size() == 1, ("RAM size missing"), E_FAIL);
- const Utf8Str &memoryVBox = vsdeRAM.front()->strVbox;
- ULONG tt = (ULONG)RTStrToUInt64(memoryVBox.c_str());
- rc = pNewMachine->COMSETTER(MemorySize)(tt);
+ // RAM
+ rc = pNewMachine->COMSETTER(MemorySize)(stack.ulMemorySizeMB);
if (FAILED(rc)) throw rc;
/* VRAM */
@@ -1453,16 +1489,16 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
// import a Windows VM because if if Windows was installed without IOAPIC,
// it will not mind finding an one later on, but if Windows was installed
// _with_ an IOAPIC, it will bluescreen if it's not found
- if (!fEnableIOApic)
+ if (!stack.fForceIOAPIC)
{
Bstr bstrFamilyId;
rc = osType->COMGETTER(FamilyId)(bstrFamilyId.asOutParam());
if (FAILED(rc)) throw rc;
if (bstrFamilyId == "Windows")
- fEnableIOApic = true;
+ stack.fForceIOAPIC = true;
}
- if (fEnableIOApic)
+ if (stack.fForceIOAPIC)
{
ComPtr<IBIOSSettings> pBIOSSettings;
rc = pNewMachine->COMGETTER(BIOSSettings)(pBIOSSettings.asOutParam());
@@ -1472,15 +1508,10 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
if (FAILED(rc)) throw rc;
}
- /* Audio Adapter */
- std::list<VirtualSystemDescriptionEntry*> vsdeAudioAdapter = vsdescThis->findByType(VirtualSystemDescriptionType_SoundCard);
- /* @todo: we support one audio adapter only */
- if (vsdeAudioAdapter.size() > 0)
- {
- const Utf8Str& audioAdapterVBox = vsdeAudioAdapter.front()->strVbox;
- if (audioAdapterVBox.compare("null", Utf8Str::CaseInsensitive) != 0)
+ if (!stack.strAudioAdapter.isEmpty())
+ if (stack.strAudioAdapter.compare("null", Utf8Str::CaseInsensitive) != 0)
{
- uint32_t audio = RTStrToUInt32(audioAdapterVBox.c_str());
+ uint32_t audio = RTStrToUInt32(stack.strAudioAdapter.c_str()); // should be 0 for AC97
ComPtr<IAudioAdapter> audioAdapter;
rc = pNewMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam());
if (FAILED(rc)) throw rc;
@@ -1489,19 +1520,13 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
rc = audioAdapter->COMSETTER(AudioController)(static_cast<AudioControllerType_T>(audio));
if (FAILED(rc)) throw rc;
}
- }
#ifdef VBOX_WITH_USB
/* USB Controller */
- std::list<VirtualSystemDescriptionEntry*> vsdeUSBController = vsdescThis->findByType(VirtualSystemDescriptionType_USBController);
- // USB support is enabled if there's at least one such entry; to disable USB support,
- // the type of the USB item would have been changed to "ignore"
- bool fUSBEnabled = vsdeUSBController.size() > 0;
-
ComPtr<IUSBController> usbController;
rc = pNewMachine->COMGETTER(USBController)(usbController.asOutParam());
if (FAILED(rc)) throw rc;
- rc = usbController->COMSETTER(Enabled)(fUSBEnabled);
+ rc = usbController->COMSETTER(Enabled)(stack.fUSBEnabled);
if (FAILED(rc)) throw rc;
#endif /* VBOX_WITH_USB */
@@ -1530,7 +1555,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
{
const VirtualSystemDescriptionEntry* pvsys = *nwIt;
- const Utf8Str &nwTypeVBox = pvsys->strVbox;
+ const Utf8Str &nwTypeVBox = pvsys->strVboxCurrent;
uint32_t tt1 = RTStrToUInt32(nwTypeVBox.c_str());
ComPtr<INetworkAdapter> pNetworkAdapter;
rc = pNewMachine->GetNetworkAdapter((ULONG)a, pNetworkAdapter.asOutParam());
@@ -1542,7 +1567,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
if (FAILED(rc)) throw rc;
// default is NAT; change to "bridged" if extra conf says so
- if (!pvsys->strExtraConfig.compare("type=Bridged", Utf8Str::CaseInsensitive))
+ if (!pvsys->strExtraConfigCurrent.compare("type=Bridged", Utf8Str::CaseInsensitive))
{
/* Attach to the right interface */
rc = pNetworkAdapter->AttachToBridgedInterface();
@@ -1575,7 +1600,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
}
}
/* Next test for host only interfaces */
- else if (!pvsys->strExtraConfig.compare("type=HostOnly", Utf8Str::CaseInsensitive))
+ else if (!pvsys->strExtraConfigCurrent.compare("type=HostOnly", Utf8Str::CaseInsensitive))
{
/* Attach to the right interface */
rc = pNetworkAdapter->AttachToHostOnlyInterface();
@@ -1625,7 +1650,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
rc = pNewMachine->AddStorageController(Bstr("IDE Controller"), StorageBus_IDE, pController.asOutParam());
if (FAILED(rc)) throw rc;
- const char *pcszIDEType = vsdeHDCIDE.front()->strVbox.c_str();
+ const char *pcszIDEType = vsdeHDCIDE.front()->strVboxCurrent.c_str();
if (!strcmp(pcszIDEType, "PIIX3"))
rc = pController->COMSETTER(ControllerType)(StorageControllerType_PIIX3);
else if (!strcmp(pcszIDEType, "PIIX4"))
@@ -1647,7 +1672,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
if (vsdeHDCSATA.size() > 0)
{
ComPtr<IStorageController> pController;
- const Utf8Str &hdcVBox = vsdeHDCSATA.front()->strVbox;
+ const Utf8Str &hdcVBox = vsdeHDCSATA.front()->strVboxCurrent;
if (hdcVBox == "AHCI")
{
rc = pNewMachine->AddStorageController(Bstr("SATA Controller"), StorageBus_SATA, pController.asOutParam());
@@ -1670,7 +1695,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
Bstr bstrName(L"SCSI Controller");
StorageBus_T busType = StorageBus_SCSI;
StorageControllerType_T controllerType;
- const Utf8Str &hdcVBox = vsdeHDCSCSI.front()->strVbox;
+ const Utf8Str &hdcVBox = vsdeHDCSCSI.front()->strVboxCurrent;
if (hdcVBox == "LsiLogic")
controllerType = StorageControllerType_LsiLogic;
else if (hdcVBox == "LsiLogicSas")
@@ -1693,6 +1718,20 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
if (FAILED(rc)) throw rc;
}
+ /* Hard disk controller SAS */
+ std::list<VirtualSystemDescriptionEntry*> vsdeHDCSAS = vsdescThis->findByType(VirtualSystemDescriptionType_HardDiskControllerSAS);
+ if (vsdeHDCSAS.size() > 1)
+ throw setError(VBOX_E_FILE_ERROR,
+ tr("Too many SAS controllers in OVF; import facility only supports one"));
+ if (vsdeHDCSAS.size() > 0)
+ {
+ ComPtr<IStorageController> pController;
+ rc = pNewMachine->AddStorageController(Bstr(L"SAS Controller"), StorageBus_SAS, pController.asOutParam());
+ if (FAILED(rc)) throw rc;
+ rc = pController->COMSETTER(ControllerType)(StorageControllerType_LsiLogicSas);
+ if (FAILED(rc)) throw rc;
+ }
+
/* Now its time to register the machine before we add any hard disks */
rc = mVirtualBox->RegisterMachine(pNewMachine);
if (FAILED(rc)) throw rc;
@@ -1862,7 +1901,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
ComPtr<IMedium> pTargetHD;
importOneDiskImage(ovfDiskImage,
- vsdeHD->strVbox,
+ vsdeHD->strVboxCurrent,
pTargetHD,
stack);
@@ -1888,7 +1927,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
mhda.lControllerPort,
mhda.lDevice);
- Log(("Attaching disk %s to port %d on device %d\n", vsdeHD->strVbox.c_str(), mhda.lControllerPort, mhda.lDevice));
+ Log(("Attaching disk %s to port %d on device %d\n", vsdeHD->strVboxCurrent.c_str(), mhda.lControllerPort, mhda.lDevice));
rc = sMachine->AttachDevice(mhda.controllerType, // wstring name
mhda.lControllerPort, // long controllerPort
@@ -1938,7 +1977,10 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
* and import the disk into VirtualBox, which creates a new UUID for it. In the machine config,
* replace the old UUID with the new one.
*
- * 3) Create the VirtualBox machine with the modfified machine config.
+ * 3) Change the machine config according to the OVF virtual system descriptions, in case the
+ * caller has modified them using setFinalValues().
+ *
+ * 4) Create the VirtualBox machine with the modfified machine config.
*
* @param config
* @param pNewMachine
@@ -1956,13 +1998,72 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
HRESULT rc = getDefaultHardDiskFolder(strDefaultHardDiskFolder);
if (FAILED(rc)) throw rc;
- // step 1): scan the machine config for attachments
+ /*
+ *
+ * step 1): modify machine config according to OVF config, in case the user
+ * has modified them using setFinalValues()
+ *
+ */
+
+// std::list<VirtualSystemDescriptionEntry*> llVSDEs;
+
+ config.hardwareMachine.cCPUs = stack.cCPUs;
+ config.hardwareMachine.ulMemorySizeMB = stack.ulMemorySizeMB;
+ if (stack.fForceIOAPIC)
+ config.hardwareMachine.fHardwareVirt = true;
+ if (stack.fForceIOAPIC)
+ config.hardwareMachine.biosSettings.fIOAPICEnabled = true;
+
+/*
+ <const name="HardDiskControllerIDE" value="14" />
+ <const name="HardDiskControllerSATA" value="15" />
+ <const name="HardDiskControllerSCSI" value="16" />
+ <const name="HardDiskControllerSAS" value="17" />
+ <const name="HardDiskImage" value="18" />
+ <const name="Floppy" value="19" />
+ <const name="CDROM" value="20" />
+ <const name="NetworkAdapter" value="21" />
+*/
+
+#ifdef VBOX_WITH_USB
+ // disable USB if user disabled USB
+ config.hardwareMachine.usbController.fEnabled = stack.fUSBEnabled;
+#endif
+
+ // audio adapter: only config is turning it off presently
+ if (stack.strAudioAdapter.isEmpty())
+ config.hardwareMachine.audioAdapter.fEnabled = false;
+
+ /*
+ *
+ * step 2: scan the machine config for media attachments
+ *
+ */
+
+ // for each storage controller...
for (settings::StorageControllersList::iterator sit = config.storageMachine.llStorageControllers.begin();
sit != config.storageMachine.llStorageControllers.end();
++sit)
{
settings::StorageController &sc = *sit;
+ // find the OVF virtual system description entry for this storage controller
+ switch (sc.storageBus)
+ {
+ case StorageBus_SATA:
+ break;
+
+ case StorageBus_SCSI:
+ break;
+
+ case StorageBus_IDE:
+ break;
+
+ case StorageBus_SAS:
+ break;
+ }
+
+ // for each medium attachment to this controller...
for (settings::AttachedDevicesList::iterator dit = sc.llAttachedDevices.begin();
dit != sc.llAttachedDevices.end();
++dit)
@@ -1991,7 +2092,11 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
strTargetPath.append(di.strHref);
searchUniqueDiskImageFilePath(strTargetPath);
- // step 2): for each attachment, import the disk...
+ /*
+ *
+ * step 3: import disk
+ *
+ */
ComPtr<IMedium> pTargetHD;
importOneDiskImage(di,
strTargetPath,
@@ -2019,14 +2124,11 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
} // for (settings::AttachedDevicesList::const_iterator dit = sc.llAttachedDevices.begin();
} // for (settings::StorageControllersList::const_iterator sit = config.storageMachine.llStorageControllers.begin();
- // step 3): create the machine and have it import the config
-
- // use the name that we computed in the OVF fields to avoid duplicates
- std::list<VirtualSystemDescriptionEntry*> vsdeName = vsdescThis->findByType(VirtualSystemDescriptionType_Name);
- if (vsdeName.size() < 1)
- throw setError(VBOX_E_FILE_ERROR,
- tr("Missing VM name"));
- const Utf8Str &strNameVBox = vsdeName.front()->strVbox;
+ /*
+ *
+ * step 4): create the machine and have it import the config
+ *
+ */
ComObjPtr<Machine> pNewMachine;
rc = pNewMachine.createObject();
@@ -2035,8 +2137,8 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
// this magic constructor fills the new machine object with the MachineConfig
// instance that we created from the vbox:Machine
rc = pNewMachine->init(mVirtualBox,
- strNameVBox, // name from just above (can be suffixed to avoid duplicates)
- config); // the whole machine config
+ stack.strNameVBox, // name from OVF preparations; can be suffixed to avoid duplicates, or changed by user
+ config); // the whole machine config
if (FAILED(rc)) throw rc;
// return the new machine as an IMachine
@@ -2186,8 +2288,7 @@ HRESULT Appliance::importS3(TaskOVF *pTask)
RTS3Destroy(hS3);
hS3 = NIL_RTS3;
- if (!pTask->pProgress.isNull())
- pTask->pProgress->SetNextOperation(BstrFmt(tr("Importing appliance")), m->ulWeightPerOperation);
+ pTask->pProgress->SetNextOperation(BstrFmt(tr("Importing appliance")), m->ulWeightForXmlOperation);
ComObjPtr<Progress> progress;
/* Import the whole temporary OVF & the disk images */
diff --git a/src/VBox/Main/ConsoleImpl.cpp b/src/VBox/Main/ConsoleImpl.cpp
index e1faceff1..a90d1161c 100644
--- a/src/VBox/Main/ConsoleImpl.cpp
+++ b/src/VBox/Main/ConsoleImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: ConsoleImpl.cpp 29580 2010-05-17 18:23:00Z vboxsync $ */
+/* $Id: ConsoleImpl.cpp 29971 2010-06-02 08:51:13Z vboxsync $ */
/** @file
* VBox Console COM Class implementation
*/
@@ -211,13 +211,11 @@ struct VMPowerUpTask : public VMProgressTask
VMPowerUpTask(Console *aConsole,
Progress *aProgress)
: VMProgressTask(aConsole, aProgress, false /* aUsesVMPtr */),
- mSetVMErrorCallback(NULL),
mConfigConstructor(NULL),
mStartPaused(false),
mTeleporterEnabled(FALSE)
{}
- PFNVMATERROR mSetVMErrorCallback;
PFNCFGMCONSTRUCTOR mConfigConstructor;
Utf8Str mSavedStateFile;
Console::SharedFolderDataMap mSharedFolders;
@@ -1684,7 +1682,7 @@ STDMETHODIMP Console::PowerDown(IProgress **aProgress)
case MachineState_Saved:
return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down a saved virtual machine"));
case MachineState_Stopping:
- return setError(VBOX_E_INVALID_VM_STATE, tr("Virtual machine is being powered down"));
+ return setError(VBOX_E_INVALID_VM_STATE, tr("The virtual machine is being powered down"));
default:
return setError(VBOX_E_INVALID_VM_STATE,
tr("Invalid machine state: %s (must be Running, Paused or Stuck)"),
@@ -3416,106 +3414,108 @@ HRESULT Console::onNetworkAdapterChange(INetworkAdapter *aNetworkAdapter, BOOL c
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Don't do anything if the VM isn't running */
- if (!mpVM)
- return S_OK;
-
- /* protect mpVM */
- AutoVMCaller autoVMCaller(this);
- if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+ HRESULT rc = S_OK;
- /* Get the properties we need from the adapter */
- BOOL fCableConnected, fTraceEnabled;
- HRESULT rc = aNetworkAdapter->COMGETTER(CableConnected)(&fCableConnected);
- AssertComRC(rc);
- if (SUCCEEDED(rc))
- {
- rc = aNetworkAdapter->COMGETTER(TraceEnabled)(&fTraceEnabled);
- AssertComRC(rc);
- }
- if (SUCCEEDED(rc))
+ /* don't trigger network change if the VM isn't running */
+ if (mpVM)
{
- ULONG ulInstance;
- rc = aNetworkAdapter->COMGETTER(Slot)(&ulInstance);
+ /* protect mpVM */
+ AutoVMCaller autoVMCaller(this);
+ if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+
+ /* Get the properties we need from the adapter */
+ BOOL fCableConnected, fTraceEnabled;
+ rc = aNetworkAdapter->COMGETTER(CableConnected)(&fCableConnected);
AssertComRC(rc);
if (SUCCEEDED(rc))
{
- /*
- * Find the pcnet instance, get the config interface and update
- * the link state.
- */
- NetworkAdapterType_T adapterType;
- rc = aNetworkAdapter->COMGETTER(AdapterType)(&adapterType);
+ rc = aNetworkAdapter->COMGETTER(TraceEnabled)(&fTraceEnabled);
+ AssertComRC(rc);
+ }
+ if (SUCCEEDED(rc))
+ {
+ ULONG ulInstance;
+ rc = aNetworkAdapter->COMGETTER(Slot)(&ulInstance);
AssertComRC(rc);
- const char *pszAdapterName = NULL;
- switch (adapterType)
+ if (SUCCEEDED(rc))
{
- case NetworkAdapterType_Am79C970A:
- case NetworkAdapterType_Am79C973:
- pszAdapterName = "pcnet";
- break;
+ /*
+ * Find the pcnet instance, get the config interface and update
+ * the link state.
+ */
+ NetworkAdapterType_T adapterType;
+ rc = aNetworkAdapter->COMGETTER(AdapterType)(&adapterType);
+ AssertComRC(rc);
+ const char *pszAdapterName = NULL;
+ switch (adapterType)
+ {
+ case NetworkAdapterType_Am79C970A:
+ case NetworkAdapterType_Am79C973:
+ pszAdapterName = "pcnet";
+ break;
#ifdef VBOX_WITH_E1000
- case NetworkAdapterType_I82540EM:
- case NetworkAdapterType_I82543GC:
- case NetworkAdapterType_I82545EM:
- pszAdapterName = "e1000";
- break;
+ case NetworkAdapterType_I82540EM:
+ case NetworkAdapterType_I82543GC:
+ case NetworkAdapterType_I82545EM:
+ pszAdapterName = "e1000";
+ break;
#endif
#ifdef VBOX_WITH_VIRTIO
- case NetworkAdapterType_Virtio:
- pszAdapterName = "virtio-net";
- break;
+ case NetworkAdapterType_Virtio:
+ pszAdapterName = "virtio-net";
+ break;
#endif
- default:
- AssertFailed();
- pszAdapterName = "unknown";
- break;
- }
+ default:
+ AssertFailed();
+ pszAdapterName = "unknown";
+ break;
+ }
- PPDMIBASE pBase;
- int vrc = PDMR3QueryDeviceLun(mpVM, pszAdapterName, ulInstance, 0, &pBase);
- ComAssertRC(vrc);
- if (RT_SUCCESS(vrc))
- {
- Assert(pBase);
- PPDMINETWORKCONFIG pINetCfg;
- pINetCfg = PDMIBASE_QUERY_INTERFACE(pBase, PDMINETWORKCONFIG);
- if (pINetCfg)
+ PPDMIBASE pBase;
+ int vrc = PDMR3QueryDeviceLun(mpVM, pszAdapterName, ulInstance, 0, &pBase);
+ ComAssertRC(vrc);
+ if (RT_SUCCESS(vrc))
{
- Log(("Console::onNetworkAdapterChange: setting link state to %d\n",
- fCableConnected));
- vrc = pINetCfg->pfnSetLinkState(pINetCfg,
- fCableConnected ? PDMNETWORKLINKSTATE_UP
- : PDMNETWORKLINKSTATE_DOWN);
- ComAssertRC(vrc);
- }
+ Assert(pBase);
+ PPDMINETWORKCONFIG pINetCfg;
+ pINetCfg = PDMIBASE_QUERY_INTERFACE(pBase, PDMINETWORKCONFIG);
+ if (pINetCfg)
+ {
+ Log(("Console::onNetworkAdapterChange: setting link state to %d\n",
+ fCableConnected));
+ vrc = pINetCfg->pfnSetLinkState(pINetCfg,
+ fCableConnected ? PDMNETWORKLINKSTATE_UP
+ : PDMNETWORKLINKSTATE_DOWN);
+ ComAssertRC(vrc);
+ }
#ifdef VBOX_DYNAMIC_NET_ATTACH
- if (RT_SUCCESS(vrc) && changeAdapter)
- {
- VMSTATE enmVMState = VMR3GetState(mpVM);
- if ( enmVMState == VMSTATE_RUNNING /** @todo LiveMigration: Forbit or deal correctly with the _LS variants */
- || enmVMState == VMSTATE_SUSPENDED)
+ if (RT_SUCCESS(vrc) && changeAdapter)
{
- if (fTraceEnabled && fCableConnected && pINetCfg)
+ VMSTATE enmVMState = VMR3GetState(mpVM);
+ if ( enmVMState == VMSTATE_RUNNING /** @todo LiveMigration: Forbid or deal correctly with the _LS variants */
+ || enmVMState == VMSTATE_SUSPENDED)
{
- vrc = pINetCfg->pfnSetLinkState(pINetCfg, PDMNETWORKLINKSTATE_DOWN);
- ComAssertRC(vrc);
- }
-
- rc = doNetworkAdapterChange(pszAdapterName, ulInstance, 0, aNetworkAdapter);
-
- if (fTraceEnabled && fCableConnected && pINetCfg)
- {
- vrc = pINetCfg->pfnSetLinkState(pINetCfg, PDMNETWORKLINKSTATE_UP);
- ComAssertRC(vrc);
+ if (fTraceEnabled && fCableConnected && pINetCfg)
+ {
+ vrc = pINetCfg->pfnSetLinkState(pINetCfg, PDMNETWORKLINKSTATE_DOWN);
+ ComAssertRC(vrc);
+ }
+
+ rc = doNetworkAdapterChange(pszAdapterName, ulInstance, 0, aNetworkAdapter);
+
+ if (fTraceEnabled && fCableConnected && pINetCfg)
+ {
+ vrc = pINetCfg->pfnSetLinkState(pINetCfg, PDMNETWORKLINKSTATE_UP);
+ ComAssertRC(vrc);
+ }
}
}
- }
#endif /* VBOX_DYNAMIC_NET_ATTACH */
- }
+ }
- if (RT_FAILURE(vrc))
- rc = E_FAIL;
+ if (RT_FAILURE(vrc))
+ rc = E_FAIL;
+ }
}
}
@@ -3723,17 +3723,17 @@ HRESULT Console::onSerialPortChange(ISerialPort *aSerialPort)
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Don't do anything if the VM isn't running */
- if (!mpVM)
- return S_OK;
-
HRESULT rc = S_OK;
- /* protect mpVM */
- AutoVMCaller autoVMCaller(this);
- if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+ /* don't trigger serial port change if the VM isn't running */
+ if (mpVM)
+ {
+ /* protect mpVM */
+ AutoVMCaller autoVMCaller(this);
+ if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
- /* nothing to do so far */
+ /* nothing to do so far */
+ }
/* notify console callbacks on success */
if (SUCCEEDED(rc))
@@ -3757,17 +3757,17 @@ HRESULT Console::onParallelPortChange(IParallelPort *aParallelPort)
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Don't do anything if the VM isn't running */
- if (!mpVM)
- return S_OK;
-
HRESULT rc = S_OK;
- /* protect mpVM */
- AutoVMCaller autoVMCaller(this);
- if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+ /* don't trigger parallel port change if the VM isn't running */
+ if (mpVM)
+ {
+ /* protect mpVM */
+ AutoVMCaller autoVMCaller(this);
+ if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
- /* nothing to do so far */
+ /* nothing to do so far */
+ }
/* notify console callbacks on success */
if (SUCCEEDED(rc))
@@ -3791,17 +3791,17 @@ HRESULT Console::onStorageControllerChange()
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Don't do anything if the VM isn't running */
- if (!mpVM)
- return S_OK;
-
HRESULT rc = S_OK;
- /* protect mpVM */
- AutoVMCaller autoVMCaller(this);
- if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+ /* don't trigger storage controller change if the VM isn't running */
+ if (mpVM)
+ {
+ /* protect mpVM */
+ AutoVMCaller autoVMCaller(this);
+ if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
- /* nothing to do so far */
+ /* nothing to do so far */
+ }
/* notify console callbacks on success */
if (SUCCEEDED(rc))
@@ -3825,17 +3825,17 @@ HRESULT Console::onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForc
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Don't do anything if the VM isn't running */
- if (!mpVM)
- return S_OK;
-
HRESULT rc = S_OK;
- /* protect mpVM */
- AutoVMCaller autoVMCaller(this);
- if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+ /* don't trigger medium change if the VM isn't running */
+ if (mpVM)
+ {
+ /* protect mpVM */
+ AutoVMCaller autoVMCaller(this);
+ if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
- rc = doMediumChange(aMediumAttachment, !!aForce);
+ rc = doMediumChange(aMediumAttachment, !!aForce);
+ }
/* notify console callbacks on success */
if (SUCCEEDED(rc))
@@ -3859,20 +3859,20 @@ HRESULT Console::onCPUChange(ULONG aCPU, BOOL aRemove)
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Don't do anything if the VM isn't running */
- if (!mpVM)
- return S_OK;
-
HRESULT rc = S_OK;
- /* protect mpVM */
- AutoVMCaller autoVMCaller(this);
- if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+ /* don't trigger CPU change if the VM isn't running */
+ if (mpVM)
+ {
+ /* protect mpVM */
+ AutoVMCaller autoVMCaller(this);
+ if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
- if (aRemove)
- rc = doCPURemove(aCPU);
- else
- rc = doCPUAdd(aCPU);
+ if (aRemove)
+ rc = doCPURemove(aCPU);
+ else
+ rc = doCPUAdd(aCPU);
+ }
/* notify console callbacks on success */
if (SUCCEEDED(rc))
@@ -3974,22 +3974,24 @@ HRESULT Console::onUSBControllerChange()
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Ignore if no VM is running yet. */
- if (!mpVM)
- return S_OK;
-
HRESULT rc = S_OK;
-/// @todo (dmik)
-// check for the Enabled state and disable virtual USB controller??
-// Anyway, if we want to query the machine's USB Controller we need to cache
-// it to mUSBController in #init() (as it is done with mDVDDrive).
-//
-// bird: While the VM supports hot-plugging, I doubt any guest can handle it at this time... :-)
-//
-// /* protect mpVM */
-// AutoVMCaller autoVMCaller(this);
-// if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+ /* don't trigger USB controller change if the VM isn't running */
+ if (mpVM)
+ {
+ /// @todo implement one day.
+ // Anyway, if we want to query the machine's USB Controller we need
+ // to cache it to mUSBController in #init() (similar to mDVDDrive).
+ //
+ // bird: While the VM supports hot-plugging, I doubt any guest can
+ // handle it at this time... :-)
+
+ /* protect mpVM */
+ AutoVMCaller autoVMCaller(this);
+ if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc();
+
+ /* nothing to do so far */
+ }
/* notify console callbacks on success */
if (SUCCEEDED(rc))
@@ -4899,7 +4901,7 @@ HRESULT Console::addVMCaller(bool aQuiet /* = false */,
{
/* powerDown() is waiting for all callers to finish */
return aQuiet ? E_ACCESSDENIED : setError(E_ACCESSDENIED,
- tr("Virtual machine is being powered down"));
+ tr("The virtual machine is being powered down"));
}
if (mpVM == NULL)
@@ -4908,7 +4910,7 @@ HRESULT Console::addVMCaller(bool aQuiet /* = false */,
/* The machine is not powered up */
return aQuiet ? E_ACCESSDENIED : setError(E_ACCESSDENIED,
- tr("Virtual machine is not powered up"));
+ tr("The virtual machine is not powered up"));
}
++ mVMCallers;
@@ -5112,7 +5114,7 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
if (Global::IsOnlineOrTransient(mMachineState))
return setError(VBOX_E_INVALID_VM_STATE,
- tr("Virtual machine is already running or busy (machine state: %s)"),
+ tr("The virtual machine is already running or busy (machine state: %s)"),
Global::stringifyMachineState(mMachineState));
HRESULT rc = S_OK;
@@ -5225,10 +5227,40 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
progressDesc = tr("Teleporting virtual machine");
else
progressDesc = tr("Starting virtual machine");
- rc = powerupProgress->init(static_cast<IConsole *>(this),
- progressDesc,
- fTeleporterEnabled /* aCancelable */);
- if (FAILED(rc)) return rc;
+ if (mMachineState == MachineState_Saved || !fTeleporterEnabled)
+ rc = powerupProgress->init(static_cast<IConsole *>(this),
+ progressDesc,
+ FALSE /* aCancelable */);
+ else
+ rc = powerupProgress->init(static_cast<IConsole *>(this),
+ progressDesc,
+ TRUE /* aCancelable */,
+ 3 /* cOperations */,
+ 10 /* ulTotalOperationsWeight */,
+ Bstr(tr("Teleporting virtual machine")),
+ 1 /* ulFirstOperationWeight */,
+ NULL);
+ if (FAILED(rc))
+ return rc;
+
+ /* Tell VBoxSVC and Machine about the progress object so they can combine
+ proxy it to any openRemoteSession caller. */
+ rc = mControl->BeginPowerUp(powerupProgress);
+ if (FAILED(rc))
+ {
+ LogFlowThisFunc(("BeginPowerUp failed\n"));
+ return rc;
+ }
+
+ BOOL fCanceled;
+ rc = powerupProgress->COMGETTER(Canceled)(&fCanceled);
+ if (FAILED(rc))
+ return rc;
+ if (fCanceled)
+ {
+ LogFlowThisFunc(("Canceled in BeginPowerUp\n"));
+ return setError(E_FAIL, tr("Powerup was canceled"));
+ }
/* setup task object and thread to carry out the operation
* asynchronously */
@@ -5236,7 +5268,6 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
std::auto_ptr<VMPowerUpTask> task(new VMPowerUpTask(this, powerupProgress));
ComAssertComRCRetRC(task->rc());
- task->mSetVMErrorCallback = setVMErrorCallback;
task->mConfigConstructor = configConstructor;
task->mSharedFolders = sharedFolders;
task->mStartPaused = aPaused;
@@ -6836,40 +6867,30 @@ DECLCALLBACK(int) Console::stateProgressCallback(PVM pVM, unsigned uPercent, voi
}
/**
- * VM error callback function. Called by the various VM components.
+ * @copydoc FNVMATERROR
*
- * @param pVM VM handle. Can be NULL if an error occurred before
- * successfully creating a VM.
- * @param pvUser Pointer to the VMProgressTask structure.
- * @param rc VBox status code.
- * @param pszFormat Printf-like error message.
- * @param args Various number of arguments for the error message.
- *
- * @thread EMT, VMPowerUp...
- *
- * @note The VMProgressTask structure modified by this callback is not thread
- * safe.
+ * @remarks Might be some tiny serialization concerns with access to the string
+ * object here...
*/
-/* static */ DECLCALLBACK(void)
-Console::setVMErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
- const char *pszFormat, va_list args)
+/*static*/ DECLCALLBACK(void)
+Console::genericVMSetErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
+ const char *pszErrorFmt, va_list va)
{
- VMProgressTask *task = static_cast<VMProgressTask *>(pvUser);
- AssertReturnVoid(task);
+ Utf8Str *pErrorText = (Utf8Str *)pvUser;
+ AssertPtr(pErrorText);
- /* we ignore RT_SRC_POS_DECL arguments to avoid confusion of end-users */
+ /* We ignore RT_SRC_POS_DECL arguments to avoid confusion of end-users. */
va_list va2;
- va_copy(va2, args); /* Have to make a copy here or GCC will break. */
+ va_copy(va2, va);
- /* append to the existing error message if any */
- if (task->mErrorMsg.length())
- task->mErrorMsg = Utf8StrFmt("%s.\n%N (%Rrc)", task->mErrorMsg.raw(),
- pszFormat, &va2, rc, rc);
+ /* Append to any the existing error message. */
+ if (pErrorText->length())
+ *pErrorText = Utf8StrFmt("%s.\n%N (%Rrc)", pErrorText->c_str(),
+ pszErrorFmt, &va2, rc, rc);
else
- task->mErrorMsg = Utf8StrFmt("%N (%Rrc)",
- pszFormat, &va2, rc, rc);
+ *pErrorText = Utf8StrFmt("%N (%Rrc)", pszErrorFmt, &va2, rc, rc);
- va_end (va2);
+ va_end(va2);
}
/**
@@ -7267,7 +7288,7 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
*/
alock.leave();
- vrc = VMR3Create(cCpus, task->mSetVMErrorCallback, task.get(),
+ vrc = VMR3Create(cCpus, Console::genericVMSetErrorCallback, &task->mErrorMsg,
task->mConfigConstructor, static_cast<Console *>(console),
&pVM);
@@ -7372,9 +7393,15 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
else if (task->mTeleporterEnabled)
{
/* -> ConsoleImplTeleporter.cpp */
- vrc = console->teleporterTrg(pVM, pMachine, task->mStartPaused, task->mProgress);
- if (RT_FAILURE(vrc) && !task->mErrorMsg.length())
- rc = E_FAIL; /* Avoid the "Missing error message..." assertion. */
+ bool fPowerOffOnFailure;
+ rc = console->teleporterTrg(pVM, pMachine, &task->mErrorMsg, task->mStartPaused,
+ task->mProgress, &fPowerOffOnFailure);
+ if (FAILED(rc) && fPowerOffOnFailure)
+ {
+ ErrorInfoKeeper eik;
+ int vrc2 = VMR3PowerOff(pVM);
+ AssertRC(vrc2);
+ }
}
else if (task->mStartPaused)
/* done */
@@ -7410,7 +7437,7 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
* be sticky but our error callback isn't.
*/
alock.leave();
- VMR3AtErrorDeregister(pVM, task->mSetVMErrorCallback, task.get());
+ VMR3AtErrorDeregister(pVM, Console::genericVMSetErrorCallback, &task->mErrorMsg);
/** @todo register another VMSetError callback? */
alock.enter();
}
@@ -7484,34 +7511,17 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
{
/* Notify the progress object of the success */
task->mProgress->notifyComplete(S_OK);
- console->mControl->SetPowerUpInfo(NULL);
}
else
{
/* The progress object will fetch the current error info */
task->mProgress->notifyComplete(rc);
- ProgressErrorInfo info(task->mProgress);
- ComObjPtr<VirtualBoxErrorInfo> errorInfo;
- rc = errorInfo.createObject();
- if (SUCCEEDED(rc))
- {
- errorInfo->init(info.getResultCode(),
- info.getInterfaceID(),
- info.getComponent(),
- info.getText());
- console->mControl->SetPowerUpInfo(errorInfo);
- }
- else
- {
- /* If it's not possible to create an IVirtualBoxErrorInfo object
- * signal success, as not signalling anything will cause a stuck
- * progress object in VBoxSVC. */
- console->mControl->SetPowerUpInfo(NULL);
- }
-
LogRel(("Power up failed (vrc=%Rrc, rc=%Rhrc (%#08X))\n", vrc, rc, rc));
}
+ /* Notify VBoxSVC and any waiting openRemoteSession progress object. */
+ console->mControl->EndPowerUp(rc);
+
#if defined(RT_OS_WINDOWS)
/* uninitialize COM */
CoUninitialize();
diff --git a/src/VBox/Main/ConsoleImplTeleporter.cpp b/src/VBox/Main/ConsoleImplTeleporter.cpp
index 14c011dfa..208dfa5aa 100644
--- a/src/VBox/Main/ConsoleImplTeleporter.cpp
+++ b/src/VBox/Main/ConsoleImplTeleporter.cpp
@@ -1,4 +1,4 @@
-/* $Id: ConsoleImplTeleporter.cpp 29250 2010-05-09 17:53:58Z vboxsync $ */
+/* $Id: ConsoleImplTeleporter.cpp 29965 2010-06-01 18:41:10Z vboxsync $ */
/** @file
* VBox Console COM Class implementation, The Teleporter Part.
*/
@@ -120,6 +120,7 @@ public:
PRTTIMERLR mphTimerLR;
bool mfLockedMedia;
int mRc;
+ Utf8Str mErrorText;
TeleporterStateTrg(Console *pConsole, PVM pVM, Progress *pProgress,
IMachine *pMachine, IInternalMachineControl *pControl,
@@ -131,6 +132,7 @@ public:
, mphTimerLR(phTimerLR)
, mfLockedMedia(false)
, mRc(VINF_SUCCESS)
+ , mErrorText()
{
}
};
@@ -218,31 +220,55 @@ static int teleporterTcpReadLine(TeleporterState *pState, char *pszBuf, size_t c
*/
HRESULT
Console::teleporterSrcReadACK(TeleporterStateSrc *pState, const char *pszWhich,
- const char *pszNAckMsg /*= NULL*/)
+ const char *pszNAckMsg /*= NULL*/)
{
- char szMsg[128];
+ char szMsg[256];
int vrc = teleporterTcpReadLine(pState, szMsg, sizeof(szMsg));
if (RT_FAILURE(vrc))
return setError(E_FAIL, tr("Failed reading ACK(%s): %Rrc"), pszWhich, vrc);
- if (strcmp(szMsg, "ACK"))
+
+ if (!strcmp(szMsg, "ACK"))
+ return S_OK;
+
+ if (!strncmp(szMsg, "NACK=", sizeof("NACK=") - 1))
{
- if (!strncmp(szMsg, "NACK=", sizeof("NACK=") - 1))
+ char *pszMsgText = strchr(szMsg, ';');
+ if (pszMsgText)
+ *pszMsgText++ = '\0';
+
+ int32_t vrc2;
+ vrc = RTStrToInt32Full(&szMsg[sizeof("NACK=") - 1], 10, &vrc2);
+ if (vrc == VINF_SUCCESS)
{
- int32_t vrc2;
- vrc = RTStrToInt32Full(&szMsg[sizeof("NACK=") - 1], 10, &vrc2);
- if (vrc == VINF_SUCCESS)
+ /*
+ * Well formed NACK, transform it into an error.
+ */
+ if (pszNAckMsg)
{
- if (pszNAckMsg)
- {
- LogRel(("Teleporter: %s: NACK=%Rrc (%d)\n", pszWhich, vrc2, vrc2));
- return setError(E_FAIL, pszNAckMsg);
- }
- return setError(E_FAIL, "NACK(%s) - %Rrc (%d)", pszWhich, vrc2, vrc2);
+ LogRel(("Teleporter: %s: NACK=%Rrc (%d)\n", pszWhich, vrc2, vrc2));
+ return setError(E_FAIL, pszNAckMsg);
}
+
+ if (pszMsgText)
+ {
+ pszMsgText = RTStrStrip(pszMsgText);
+ for (size_t off = 0; pszMsgText[off]; off++)
+ if (pszMsgText[off] == '\r')
+ pszMsgText[off] = '\n';
+
+ LogRel(("Teleporter: %s: NACK=%Rrc (%d) - '%s'\n", pszWhich, vrc2, vrc2, pszMsgText));
+ if (strlen(pszMsgText) > 4)
+ return setError(E_FAIL, "%s", pszMsgText);
+ return setError(E_FAIL, "NACK(%s) - %Rrc (%d) '%s'", pszWhich, vrc2, vrc2, pszMsgText);
+ }
+
+ return setError(E_FAIL, "NACK(%s) - %Rrc (%d)", pszWhich, vrc2, vrc2);
}
- return setError(E_FAIL, tr("%s: Expected ACK or NACK, got '%s'"), pszWhich, szMsg);
+
+ if (pszMsgText)
+ pszMsgText[-1] = ';';
}
- return S_OK;
+ return setError(E_FAIL, tr("%s: Expected ACK or NACK, got '%s'"), pszWhich, szMsg);
}
@@ -663,13 +689,24 @@ Console::teleporterSrc(TeleporterStateSrc *pState)
if (FAILED(hrc))
return hrc;
+ RTSocketRetain(pState->mhSocket);
void *pvUser = static_cast<void *>(static_cast<TeleporterState *>(pState));
vrc = VMR3Teleport(pState->mpVM, pState->mcMsMaxDowntime,
&g_teleporterTcpOps, pvUser,
teleporterProgressCallback, pvUser,
&pState->mfSuspendedByUs);
+ RTSocketRelease(pState->mhSocket);
if (RT_FAILURE(vrc))
+ {
+ if ( vrc == VERR_SSM_CANCELLED
+ && RT_SUCCESS(RTTcpSelectOne(pState->mhSocket, 1)))
+ {
+ hrc = teleporterSrcReadACK(pState, "load-complete");
+ if (FAILED(hrc))
+ return hrc;
+ }
return setError(E_FAIL, tr("VMR3Teleport -> %Rrc"), vrc);
+ }
hrc = teleporterSrcReadACK(pState, "load-complete");
if (FAILED(hrc))
@@ -978,36 +1015,44 @@ Console::Teleport(IN_BSTR aHostname, ULONG aPort, IN_BSTR aPassword, ULONG aMaxD
* @returns VBox status code.
* @param pVM The VM handle
* @param pMachine The IMachine for the virtual machine.
+ * @param pErrorMsg Pointer to the error string for VMSetError.
* @param fStartPaused Whether to start it in the Paused (true) or
* Running (false) state,
* @param pProgress Pointer to the progress object.
+ * @param pfPowerOffOnFailure Whether the caller should power off
+ * the VM on failure.
*
* @remarks The caller expects error information to be set on failure.
* @todo Check that all the possible failure paths sets error info...
*/
-int
-Console::teleporterTrg(PVM pVM, IMachine *pMachine, bool fStartPaused, Progress *pProgress)
+HRESULT
+Console::teleporterTrg(PVM pVM, IMachine *pMachine, Utf8Str *pErrorMsg, bool fStartPaused,
+ Progress *pProgress, bool *pfPowerOffOnFailure)
{
+ LogThisFunc(("pVM=%p pMachine=%p fStartPaused=%RTbool pProgress=%p\n", pVM, pMachine, fStartPaused, pProgress));
+
+ *pfPowerOffOnFailure = true;
+
/*
* Get the config.
*/
ULONG uPort;
HRESULT hrc = pMachine->COMGETTER(TeleporterPort)(&uPort);
if (FAILED(hrc))
- return VERR_GENERAL_FAILURE;
+ return hrc;
ULONG const uPortOrg = uPort;
Bstr bstrAddress;
hrc = pMachine->COMGETTER(TeleporterAddress)(bstrAddress.asOutParam());
if (FAILED(hrc))
- return VERR_GENERAL_FAILURE;
+ return hrc;
Utf8Str strAddress(bstrAddress);
const char *pszAddress = strAddress.isEmpty() ? NULL : strAddress.c_str();
Bstr bstrPassword;
hrc = pMachine->COMGETTER(TeleporterPassword)(bstrPassword.asOutParam());
if (FAILED(hrc))
- return VERR_GENERAL_FAILURE;
+ return hrc;
Utf8Str strPassword(bstrPassword);
strPassword.append('\n'); /* To simplify password checking. */
@@ -1033,12 +1078,12 @@ Console::teleporterTrg(PVM pVM, IMachine *pMachine, bool fStartPaused, Progress
if (FAILED(hrc))
{
RTTcpServerDestroy(hServer);
- return VERR_GENERAL_FAILURE;
+ return hrc;
}
}
}
if (RT_FAILURE(vrc))
- return vrc;
+ return setError(E_FAIL, tr("RTTcpServerCreateEx failed with status %Rrc"), vrc);
/*
* Create a one-shot timer for timing out after 5 mins.
@@ -1061,59 +1106,66 @@ Console::teleporterTrg(PVM pVM, IMachine *pMachine, bool fStartPaused, Progress
if (pProgress->setCancelCallback(teleporterProgressCancelCallback, pvUser))
{
LogRel(("Teleporter: Waiting for incoming VM...\n"));
- vrc = RTTcpServerListen(hServer, Console::teleporterTrgServeConnection, &theState);
- pProgress->setCancelCallback(NULL, NULL);
-
- bool fPowerOff = false;
- if (vrc == VERR_TCP_SERVER_STOP)
+ hrc = pProgress->SetNextOperation(Bstr(tr("Waiting for incoming VM")), 1);
+ if (SUCCEEDED(hrc))
{
- vrc = theState.mRc;
- /* Power off the VM on failure unless the state callback
- already did that. */
- if (RT_FAILURE(vrc))
+ vrc = RTTcpServerListen(hServer, Console::teleporterTrgServeConnection, &theState);
+ pProgress->setCancelCallback(NULL, NULL);
+
+ if (vrc == VERR_TCP_SERVER_STOP)
{
- VMSTATE enmVMState = VMR3GetState(pVM);
- if ( enmVMState != VMSTATE_OFF
- && enmVMState != VMSTATE_POWERING_OFF)
- fPowerOff = true;
+ vrc = theState.mRc;
+ /* Power off the VM on failure unless the state callback
+ already did that. */
+ *pfPowerOffOnFailure = false;
+ if (RT_SUCCESS(vrc))
+ hrc = S_OK;
+ else
+ {
+ VMSTATE enmVMState = VMR3GetState(pVM);
+ if ( enmVMState != VMSTATE_OFF
+ && enmVMState != VMSTATE_POWERING_OFF)
+ *pfPowerOffOnFailure = true;
+
+ /* Set error. */
+ if (pErrorMsg->length())
+ hrc = setError(E_FAIL, "%s", pErrorMsg->c_str());
+ else
+ hrc = setError(E_FAIL, tr("Teleporation failed (%Rrc)"), vrc);
+ }
}
- }
- else if (vrc == VERR_TCP_SERVER_SHUTDOWN)
- {
- BOOL fCancelled = TRUE;
- hrc = pProgress->COMGETTER(Canceled)(&fCancelled);
- if (FAILED(hrc) || fCancelled)
+ else if (vrc == VERR_TCP_SERVER_SHUTDOWN)
{
- setError(E_FAIL, tr("Teleporting canceled"));
- vrc = VERR_SSM_CANCELLED;
+ BOOL fCancelled = TRUE;
+ hrc = pProgress->COMGETTER(Canceled)(&fCancelled);
+ if (FAILED(hrc) || fCancelled)
+ hrc = setError(E_FAIL, tr("Teleporting canceled"));
+ else
+ hrc = setError(E_FAIL, tr("Teleporter timed out waiting for incoming connection"));
+ LogRel(("Teleporter: RTTcpServerListen aborted - %Rrc\n", vrc));
}
else
{
- setError(E_FAIL, tr("Teleporter timed out waiting for incoming connection"));
- vrc = VERR_TIMEOUT;
+ hrc = setError(E_FAIL, tr("Unexpected RTTcpServerListen status code %Rrc"), vrc);
+ LogRel(("Teleporter: Unexpected RTTcpServerListen rc: %Rrc\n", vrc));
}
- LogRel(("Teleporter: RTTcpServerListen aborted - %Rrc\n", vrc));
- fPowerOff = true;
}
else
- {
- LogRel(("Teleporter: Unexpected RTTcpServerListen rc: %Rrc\n", vrc));
- vrc = VERR_IPE_UNEXPECTED_STATUS;
- fPowerOff = true;
- }
-
- if (fPowerOff)
- {
- int vrc2 = VMR3PowerOff(pVM);
- AssertRC(vrc2);
- }
+ LogThisFunc(("SetNextOperation failed, %Rhrc\n", hrc));
}
else
- vrc = VERR_SSM_CANCELLED;
+ {
+ LogThisFunc(("Canceled - check point #1\n"));
+ hrc = setError(E_FAIL, tr("Teleporting canceled"));
+ }
}
+ else
+ hrc = setError(E_FAIL, "RTTimerLRStart -> %Rrc", vrc);
RTTimerLRDestroy(hTimerLR);
}
+ else
+ hrc = setError(E_FAIL, "RTTimerLRCreate -> %Rrc", vrc);
RTTcpServerDestroy(hServer);
/*
@@ -1121,9 +1173,12 @@ Console::teleporterTrg(PVM pVM, IMachine *pMachine, bool fStartPaused, Progress
* value before returning.
*/
if (uPortOrg != uPort)
+ {
+ ErrorInfoKeeper Eik;
pMachine->COMSETTER(TeleporterPort)(uPortOrg);
+ }
- return vrc;
+ return hrc;
}
@@ -1158,7 +1213,7 @@ static int teleporterTcpWriteACK(TeleporterStateTrg *pState, bool fAutomaticUnlo
}
-static int teleporterTcpWriteNACK(TeleporterStateTrg *pState, int32_t rc2)
+static int teleporterTcpWriteNACK(TeleporterStateTrg *pState, int32_t rc2, const char *pszMsgText = NULL)
{
/*
* Unlock media sending the NACK. That way the other doesn't have to spin
@@ -1166,8 +1221,17 @@ static int teleporterTcpWriteNACK(TeleporterStateTrg *pState, int32_t rc2)
*/
teleporterTrgUnlockMedia(pState);
- char szMsg[64];
- size_t cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d\n", rc2);
+ char szMsg[256];
+ size_t cch;
+ if (pszMsgText && *pszMsgText)
+ {
+ cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d;%s\n", rc2, pszMsgText);
+ for (size_t off = 6; off + 1 < cch; off++)
+ if (szMsg[off] == '\n')
+ szMsg[off] = '\r';
+ }
+ else
+ cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d\n", rc2);
int rc = RTTcpWrite(pState->mhSocket, szMsg, cch);
if (RT_FAILURE(rc))
LogRel(("Teleporter: RTTcpWrite(,%s,%zu) -> %Rrc\n", szMsg, cch, rc));
@@ -1221,7 +1285,24 @@ Console::teleporterTrgServeConnection(RTSOCKET Sock, void *pvUser)
vrc = teleporterTcpWriteACK(pState);
if (RT_FAILURE(vrc))
return VINF_SUCCESS;
- LogRel(("Teleporter: Incoming VM!\n"));
+
+ /*
+ * Update the progress bar, with peer name if available.
+ */
+ HRESULT hrc;
+ RTNETADDR Addr;
+ vrc = RTTcpGetPeerAddress(Sock, &Addr);
+ if (RT_SUCCESS(vrc))
+ {
+ LogRel(("Teleporter: Incoming VM from %RTnaddr!\n", &Addr));
+ hrc = pState->mptrProgress->SetNextOperation(Bstr(Utf8StrFmt(tr("Teleporting VM from %RTnaddr"), &Addr)), 8);
+ }
+ else
+ {
+ LogRel(("Teleporter: Incoming VM!\n"));
+ hrc = pState->mptrProgress->SetNextOperation(Bstr(tr("Teleporting VM")), 8);
+ }
+ AssertMsg(SUCCEEDED(hrc) || hrc == E_FAIL, ("%Rhrc\n", hrc));
/*
* Stop the server and cancel the timeout timer.
@@ -1250,16 +1331,21 @@ Console::teleporterTrgServeConnection(RTSOCKET Sock, void *pvUser)
if (RT_FAILURE(vrc))
break;
+ int vrc2 = VMR3AtErrorRegister(pState->mpVM, Console::genericVMSetErrorCallback, &pState->mErrorText); AssertRC(vrc2);
RTSocketRetain(pState->mhSocket); /* For concurrent access by I/O thread and EMT. */
pState->moffStream = 0;
+
void *pvUser2 = static_cast<void *>(static_cast<TeleporterState *>(pState));
vrc = VMR3LoadFromStream(pState->mpVM, &g_teleporterTcpOps, pvUser2,
teleporterProgressCallback, pvUser2);
+
RTSocketRelease(pState->mhSocket);
+ vrc2 = VMR3AtErrorDeregister(pState->mpVM, Console::genericVMSetErrorCallback, &pState->mErrorText); AssertRC(vrc2);
+
if (RT_FAILURE(vrc))
{
LogRel(("Teleporter: VMR3LoadFromStream -> %Rrc\n", vrc));
- teleporterTcpWriteNACK(pState, vrc);
+ teleporterTcpWriteNACK(pState, vrc, pState->mErrorText.c_str());
break;
}
@@ -1284,7 +1370,7 @@ Console::teleporterTrgServeConnection(RTSOCKET Sock, void *pvUser)
}
else if (!strcmp(szCmd, "lock-media"))
{
- HRESULT hrc = pState->mpControl->LockMedia();
+ hrc = pState->mpControl->LockMedia();
if (SUCCEEDED(hrc))
{
pState->mfLockedMedia = true;
diff --git a/src/VBox/Main/Global.cpp b/src/VBox/Main/Global.cpp
index 325f32106..a704c209b 100644
--- a/src/VBox/Main/Global.cpp
+++ b/src/VBox/Main/Global.cpp
@@ -1,4 +1,4 @@
-/* $Id: Global.cpp 29595 2010-05-18 08:05:46Z vboxsync $ */
+/* $Id: Global.cpp 29815 2010-05-26 13:41:36Z vboxsync $ */
/** @file
*
@@ -165,19 +165,19 @@ const Global::OSType Global::sOSTypes[SchemaDefs::OSTypeId_COUNT] =
StorageControllerType_IntelAhci, StorageBus_SATA },
{ "Linux", "Linux", SchemaDefs_OSTypeId_Mandriva, "Mandriva",
VBOXOSTYPE_Mandriva, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
- 384, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ 512, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA },
{ "Linux", "Linux", SchemaDefs_OSTypeId_Mandriva_64, "Mandriva (64 bit)",
VBOXOSTYPE_Mandriva_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
- 384, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ 512, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA },
{ "Linux", "Linux", SchemaDefs_OSTypeId_RedHat, "Red Hat",
- VBOXOSTYPE_RedHat, VBOXOSHINT_RTCUTC,
- 384, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ VBOXOSTYPE_RedHat, VBOXOSHINT_RTCUTC | VBOXOSHINT_PAE,
+ 512, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA },
{ "Linux", "Linux", SchemaDefs_OSTypeId_RedHat_64, "Red Hat (64 bit)",
- VBOXOSTYPE_RedHat_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
- 384, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ VBOXOSTYPE_RedHat_x64, VBOXOSHINT_64BIT | VBOXOSHINT_PAE | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
+ 512, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA },
{ "Linux", "Linux", SchemaDefs_OSTypeId_Turbolinux, "Turbolinux",
VBOXOSTYPE_Turbolinux, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
@@ -205,11 +205,11 @@ const Global::OSType Global::sOSTypes[SchemaDefs::OSTypeId_COUNT] =
StorageControllerType_IntelAhci, StorageBus_SATA },
{ "Linux", "Linux", SchemaDefs_OSTypeId_Oracle, "Oracle",
VBOXOSTYPE_Oracle, VBOXOSHINT_RTCUTC,
- 384, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ 512, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA },
{ "Linux", "Linux", SchemaDefs_OSTypeId_Oracle_64, "Oracle (64 bit)",
VBOXOSTYPE_Oracle_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
- 384, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ 512, 12, 8 * _1K, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA },
{ "Linux", "Linux", SchemaDefs_OSTypeId_Linux, "Other Linux",
VBOXOSTYPE_Linux, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
@@ -275,11 +275,11 @@ const Global::OSType Global::sOSTypes[SchemaDefs::OSTypeId_COUNT] =
VBOXOSTYPE_OS2, VBOXOSHINT_HWVIRTEX,
96, 4, 2 * _1K, NetworkAdapterType_Am79C973, 1, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE },
- { "MacOS", "Mac OS X", SchemaDefs_OSTypeId_MacOS, "Mac OS X",
+ { "MacOS", "Mac OS X", SchemaDefs_OSTypeId_MacOS, "Mac OS X Server",
VBOXOSTYPE_MacOS, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_EFI | VBOXOSHINT_PAE | VBOXOSHINT_USBHID | VBOXOSHINT_HPET | VBOXOSHINT_USBTABLET,
1024, 4, 20 * _1K, NetworkAdapterType_I82543GC, 0, StorageControllerType_ICH6, StorageBus_IDE,
StorageControllerType_ICH6, StorageBus_IDE },
- { "MacOS", "Mac OS X", SchemaDefs_OSTypeId_MacOS_64, "Mac OS X (64 bit)",
+ { "MacOS", "Mac OS X", SchemaDefs_OSTypeId_MacOS_64, "Mac OS X Server (64 bit)",
VBOXOSTYPE_MacOS_x64, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_EFI | VBOXOSHINT_PAE | VBOXOSHINT_64BIT | VBOXOSHINT_USBHID | VBOXOSHINT_HPET | VBOXOSHINT_USBTABLET,
1024, 4, 20 * _1K, NetworkAdapterType_I82543GC, 0, StorageControllerType_ICH6, StorageBus_IDE,
StorageControllerType_ICH6, StorageBus_IDE },
diff --git a/src/VBox/Main/GuestImpl.cpp b/src/VBox/Main/GuestImpl.cpp
index 13e7395a7..029c1774c 100644
--- a/src/VBox/Main/GuestImpl.cpp
+++ b/src/VBox/Main/GuestImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: GuestImpl.cpp 29645 2010-05-18 15:41:46Z vboxsync $ */
+/* $Id: GuestImpl.cpp 29997 2010-06-02 13:39:06Z vboxsync $ */
/** @file
*
@@ -268,9 +268,13 @@ STDMETHODIMP Guest::COMSETTER(MemoryBalloonSize) (ULONG aMemoryBalloonSize)
{
mMemoryBalloonSize = aMemoryBalloonSize;
/* forward the information to the VMM device */
- VMMDev *vmmDev = mParent->getVMMDev();
- if (vmmDev)
- vmmDev->getVMMDevPort()->pfnSetMemoryBalloon(vmmDev->getVMMDevPort(), aMemoryBalloonSize);
+ VMMDev *pVMMDev = mParent->getVMMDev();
+ if (pVMMDev)
+ {
+ PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
+ ComAssertRet(pVMMDevPort, E_FAIL);
+ pVMMDevPort->pfnSetMemoryBalloon(pVMMDevPort, aMemoryBalloonSize);
+ }
}
return ret;
@@ -298,9 +302,13 @@ STDMETHODIMP Guest::COMSETTER(StatisticsUpdateInterval)(ULONG aUpdateInterval)
mStatUpdateInterval = aUpdateInterval;
/* forward the information to the VMM device */
- VMMDev *vmmDev = mParent->getVMMDev();
- if (vmmDev)
- vmmDev->getVMMDevPort()->pfnSetStatisticsInterval(vmmDev->getVMMDevPort(), aUpdateInterval);
+ VMMDev *pVMMDev = mParent->getVMMDev();
+ if (pVMMDev)
+ {
+ PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
+ ComAssertRet(pVMMDevPort, E_FAIL);
+ pVMMDevPort->pfnSetStatisticsInterval(pVMMDevPort, aUpdateInterval);
+ }
return S_OK;
}
@@ -392,14 +400,17 @@ STDMETHODIMP Guest::SetCredentials(IN_BSTR aUserName, IN_BSTR aPassword,
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* forward the information to the VMM device */
- VMMDev *vmmDev = mParent->getVMMDev();
- if (vmmDev)
+ VMMDev *pVMMDev = mParent->getVMMDev();
+ if (pVMMDev)
{
+ PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
+ ComAssertRet(pVMMDevPort, E_FAIL);
+
uint32_t u32Flags = VMMDEV_SETCREDENTIALS_GUESTLOGON;
if (!aAllowInteractiveLogon)
u32Flags = VMMDEV_SETCREDENTIALS_NOLOCALLOGON;
- vmmDev->getVMMDevPort()->pfnSetCredentials(vmmDev->getVMMDevPort(),
+ pVMMDevPort->pfnSetCredentials(pVMMDevPort,
Utf8Str(aUserName).raw(), Utf8Str(aPassword).raw(),
Utf8Str(aDomain).raw(), u32Flags);
return S_OK;
@@ -483,25 +494,36 @@ DECLCALLBACK(int) Guest::doGuestCtrlNotification(void *pvExtension,
ComObjPtr<Guest> pGuest = reinterpret_cast<Guest *>(pvExtension);
int rc = VINF_SUCCESS;
- if (u32Function == GUEST_EXEC_SEND_STATUS)
+ if (u32Function == GUEST_DISCONNECTED)
+ {
+ LogFlowFunc(("GUEST_DISCONNECTED\n"));
+
+ PCALLBACKDATACLIENTDISCONNECTED pCBData = reinterpret_cast<PCALLBACKDATACLIENTDISCONNECTED>(pvParms);
+ AssertPtr(pCBData);
+ AssertReturn(sizeof(CALLBACKDATACLIENTDISCONNECTED) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(CALLBACKDATAMAGICCLIENTDISCONNECTED == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+ rc = pGuest->notifyCtrlClientDisconnected(u32Function, pCBData);
+ }
+ else if (u32Function == GUEST_EXEC_SEND_STATUS)
{
LogFlowFunc(("GUEST_EXEC_SEND_STATUS\n"));
- PHOSTEXECCALLBACKDATA pCBData = reinterpret_cast<PHOSTEXECCALLBACKDATA>(pvParms);
+ PCALLBACKDATAEXECSTATUS pCBData = reinterpret_cast<PCALLBACKDATAEXECSTATUS>(pvParms);
AssertPtr(pCBData);
- AssertReturn(sizeof(HOSTEXECCALLBACKDATA) == cbParms, VERR_INVALID_PARAMETER);
- AssertReturn(HOSTEXECCALLBACKDATAMAGIC == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+ AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(CALLBACKDATAMAGICEXECSTATUS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
- rc = pGuest->notifyCtrlExec(u32Function, pCBData);
+ rc = pGuest->notifyCtrlExecStatus(u32Function, pCBData);
}
else if (u32Function == GUEST_EXEC_SEND_OUTPUT)
{
LogFlowFunc(("GUEST_EXEC_SEND_OUTPUT\n"));
- PHOSTEXECOUTCALLBACKDATA pCBData = reinterpret_cast<PHOSTEXECOUTCALLBACKDATA>(pvParms);
+ PCALLBACKDATAEXECOUT pCBData = reinterpret_cast<PCALLBACKDATAEXECOUT>(pvParms);
AssertPtr(pCBData);
- AssertReturn(sizeof(HOSTEXECOUTCALLBACKDATA) == cbParms, VERR_INVALID_PARAMETER);
- AssertReturn(HOSTEXECOUTCALLBACKDATAMAGIC == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+ AssertReturn(sizeof(CALLBACKDATAEXECOUT) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(CALLBACKDATAMAGICEXECOUT == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
rc = pGuest->notifyCtrlExecOut(u32Function, pCBData);
}
@@ -511,8 +533,8 @@ DECLCALLBACK(int) Guest::doGuestCtrlNotification(void *pvExtension,
}
/* Function for handling the execution start/termination notification. */
-int Guest::notifyCtrlExec(uint32_t u32Function,
- PHOSTEXECCALLBACKDATA pData)
+int Guest::notifyCtrlExecStatus(uint32_t u32Function,
+ PCALLBACKDATAEXECSTATUS pData)
{
LogFlowFuncEnter();
int rc = VINF_SUCCESS;
@@ -525,7 +547,7 @@ int Guest::notifyCtrlExec(uint32_t u32Function,
/* Callback can be called several times. */
if (it != mCallbackList.end())
{
- PHOSTEXECCALLBACKDATA pCBData = (HOSTEXECCALLBACKDATA*)it->pvData;
+ PCALLBACKDATAEXECSTATUS pCBData = (PCALLBACKDATAEXECSTATUS)it->pvData;
AssertPtr(pCBData);
pCBData->u32PID = pData->u32PID;
@@ -587,11 +609,11 @@ int Guest::notifyCtrlExec(uint32_t u32Function,
{
/* Not found, add to list. */
GuestProcess p;
- p.mPID = pCBData->u32PID;
+ p.mPID = pCBData->u32PID;
p.mStatus = pCBData->u32Status;
p.mExitCode = pCBData->u32Flags; /* Contains exit code. */
p.mFlags = 0;
-
+
mGuestProcessList.push_back(p);
}
else /* Update list. */
@@ -616,7 +638,7 @@ int Guest::notifyCtrlExec(uint32_t u32Function,
LogFlowFunc(("Callback (context ID=%u, status=%u) progress already marked as completed\n",
pData->hdr.u32ContextID, pData->u32Status));
}
- ASMAtomicWriteBool(&it->bCalled, true);
+ ASMAtomicWriteBool(&it->fCalled, true);
}
else
LogFlowFunc(("Unexpected callback (magic=%u, context ID=%u) arrived\n", pData->hdr.u32Magic, pData->hdr.u32ContextID));
@@ -625,8 +647,8 @@ int Guest::notifyCtrlExec(uint32_t u32Function,
}
/* Function for handling the execution output notification. */
-int Guest::notifyCtrlExecOut(uint32_t u32Function,
- PHOSTEXECOUTCALLBACKDATA pData)
+int Guest::notifyCtrlExecOut(uint32_t u32Function,
+ PCALLBACKDATAEXECOUT pData)
{
LogFlowFuncEnter();
int rc = VINF_SUCCESS;
@@ -637,8 +659,8 @@ int Guest::notifyCtrlExecOut(uint32_t u32Function,
CallbackListIter it = getCtrlCallbackContextByID(pData->hdr.u32ContextID);
if (it != mCallbackList.end())
{
- Assert(!it->bCalled);
- PHOSTEXECOUTCALLBACKDATA pCBData = (HOSTEXECOUTCALLBACKDATA*)it->pvData;
+ Assert(!it->fCalled);
+ PCALLBACKDATAEXECOUT pCBData = (CALLBACKDATAEXECOUT*)it->pvData;
AssertPtr(pCBData);
pCBData->u32PID = pData->u32PID;
@@ -661,7 +683,7 @@ int Guest::notifyCtrlExecOut(uint32_t u32Function,
pCBData->pvData = NULL;
pCBData->cbData = 0;
}
- ASMAtomicWriteBool(&it->bCalled, true);
+ ASMAtomicWriteBool(&it->fCalled, true);
}
else
LogFlowFunc(("Unexpected callback (magic=%u, context ID=%u) arrived\n", pData->hdr.u32Magic, pData->hdr.u32ContextID));
@@ -669,6 +691,26 @@ int Guest::notifyCtrlExecOut(uint32_t u32Function,
return rc;
}
+int Guest::notifyCtrlClientDisconnected(uint32_t u32Function,
+ PCALLBACKDATACLIENTDISCONNECTED pData)
+{
+ LogFlowFuncEnter();
+ int rc = VINF_SUCCESS;
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ /** @todo Maybe use a map instead of list for fast context lookup. */
+ CallbackListIter it;
+ for (it = mCallbackList.begin(); it != mCallbackList.end(); it++)
+ {
+ if (it->mContextID == pData->hdr.u32ContextID)
+ destroyCtrlCallbackContext(it);
+ }
+
+ LogFlowFuncLeave();
+ return rc;
+}
+
Guest::CallbackListIter Guest::getCtrlCallbackContextByID(uint32_t u32ContextID)
{
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -715,9 +757,9 @@ void Guest::destroyCtrlCallbackContext(Guest::CallbackListIter it)
BOOL fCancelled;
if (SUCCEEDED(it->pProgress->COMGETTER(Canceled)(&fCancelled)) && !fCancelled)
it->pProgress->Cancel();
- /*
- * Do *not NULL pProgress here, because waiting function like executeProcess()
- * will still rely on this object for checking whether they have to give up!
+ /*
+ * Do *not NULL pProgress here, because waiting function like executeProcess()
+ * will still rely on this object for checking whether they have to give up!
*/
}
LogFlowFuncLeave();
@@ -737,7 +779,7 @@ uint32_t Guest::addCtrlCallbackContext(eVBoxGuestCtrlCallbackType enmType, void
CallbackContext context;
context.mContextID = uNewContext;
context.mType = enmType;
- context.bCalled = false;
+ context.fCalled = false;
context.pvData = pvData;
context.cbData = cbData;
context.pProgress = pProgress;
@@ -745,9 +787,10 @@ uint32_t Guest::addCtrlCallbackContext(eVBoxGuestCtrlCallbackType enmType, void
uint32_t nCallbacks;
{
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ /// @todo r=bird: check if already in the list and find another one.
mCallbackList.push_back(context);
nCallbacks = mCallbackList.size();
- }
+ }
#if 0
if (nCallbacks > 256) /* Don't let the container size get too big! */
@@ -771,6 +814,8 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
IN_BSTR aUserName, IN_BSTR aPassword,
ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress)
{
+/** @todo r=bird: Eventually we should clean up all the timeout parameters
+ * in the API and have the same way of specifying infinite waits! */
#ifndef VBOX_WITH_GUEST_CONTROL
ReturnComNotImplemented();
#else /* VBOX_WITH_GUEST_CONTROL */
@@ -828,6 +873,7 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
AssertReturn(papszArgv, E_OUTOFMEMORY);
for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++)
{
+ /// @todo r=bird: RTUtf16ToUtf8().
int cbLen = RTStrAPrintf(&papszArgv[i], "%s", Utf8Str(args[i]).raw());
if (cbLen < 0)
vrc = VERR_NO_MEMORY;
@@ -867,10 +913,10 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
if (RT_SUCCESS(vrc))
{
- PHOSTEXECCALLBACKDATA pData = (HOSTEXECCALLBACKDATA*)RTMemAlloc(sizeof(HOSTEXECCALLBACKDATA));
+ PCALLBACKDATAEXECSTATUS pData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS));
AssertReturn(pData, VBOX_E_IPRT_ERROR);
- uContextID = addCtrlCallbackContext(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START,
- pData, sizeof(HOSTEXECCALLBACKDATA), progress);
+ uContextID = addCtrlCallbackContext(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START,
+ pData, sizeof(CALLBACKDATAEXECSTATUS), progress);
Assert(uContextID > 0);
VBOXHGCMSVCPARM paParms[15];
@@ -889,11 +935,11 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
VMMDev *vmmDev;
{
- /* Make sure mParent is valid, so set the read lock while using.
+ /* Make sure mParent is valid, so set the read lock while using.
* Do not keep this lock while doing the actual call, because in the meanwhile
* another thread could request a write lock which would be a bad idea ... */
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
+
/* Forward the information to the VMM device. */
AssertPtr(mParent);
vmmDev = mParent->getVMMDev();
@@ -925,7 +971,7 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
if (it != mCallbackList.end())
{
uint64_t u64Started = RTTimeMilliTS();
- while (!it->bCalled)
+ while (!it->fCalled)
{
/* Check for timeout. */
unsigned cMsWait;
@@ -941,12 +987,15 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
/* Check for manual stop. */
if (!it->pProgress.isNull())
- {
+ {
rc = it->pProgress->COMGETTER(Canceled)(&fCanceled);
if (FAILED(rc)) throw rc;
if (fCanceled)
- break; /* Client wants to abort. */
+ break; /* HGCM/guest wants to abort because of status change. */
+
}
+ /// @todo r=bird: two operation progress object and wait first operation.
+ /// IProgress::WaitForOperationCompletion.
RTThreadSleep(cMsWait);
}
}
@@ -954,13 +1003,13 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
/* Was the whole thing canceled? */
if (!fCanceled)
{
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- PHOSTEXECCALLBACKDATA pData = (HOSTEXECCALLBACKDATA*)it->pvData;
- Assert(it->cbData == sizeof(HOSTEXECCALLBACKDATA));
+ PCALLBACKDATAEXECSTATUS pData = (PCALLBACKDATAEXECSTATUS)it->pvData;
+ Assert(it->cbData == sizeof(CALLBACKDATAEXECSTATUS));
AssertPtr(pData);
- if (it->bCalled)
+ if (it->fCalled)
{
/* Did we get some status? */
switch (pData->u32Status)
@@ -969,7 +1018,7 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
/* Process is (still) running; get PID. */
*aPID = pData->u32PID;
break;
-
+
/* In any other case the process either already
* terminated or something else went wrong, so no PID ... */
case PROC_STS_TEN: /* Terminated normally. */
@@ -978,17 +1027,17 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
case PROC_STS_TOK:
case PROC_STS_TOA:
case PROC_STS_DWN:
- /*
+ /*
* Process (already) ended, but we want to get the
- * PID anyway to retrieve the output in a later call.
+ * PID anyway to retrieve the output in a later call.
*/
*aPID = pData->u32PID;
break;
-
+
case PROC_STS_ERROR:
vrc = pData->u32Flags; /* u32Flags member contains IPRT error code. */
break;
-
+
default:
vrc = VERR_INVALID_PARAMETER; /* Unknown status, should never happen! */
break;
@@ -1008,6 +1057,11 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
rc = setError(VBOX_E_IPRT_ERROR,
tr("The file '%s' was not found on guest"), Utf8Command.raw());
}
+ else if (vrc == VERR_PATH_NOT_FOUND)
+ {
+ rc = setError(VBOX_E_IPRT_ERROR,
+ tr("The path to file '%s' was not found on guest"), Utf8Command.raw());
+ }
else if (vrc == VERR_BAD_EXE_FORMAT)
{
rc = setError(VBOX_E_IPRT_ERROR,
@@ -1023,11 +1077,6 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
rc = setError(VBOX_E_IPRT_ERROR,
tr("The guest did not respond within time (%ums)"), aTimeoutMS);
}
- else if (vrc == VERR_INVALID_PARAMETER)
- {
- rc = setError(VBOX_E_IPRT_ERROR,
- tr("The guest reported an unknown process status (%u)"), pData->u32Status);
- }
else if (vrc == VERR_PERMISSION_DENIED)
{
rc = setError(VBOX_E_IPRT_ERROR,
@@ -1035,9 +1084,13 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
}
else
{
- rc = setError(E_UNEXPECTED,
- tr("The service call failed with error %Rrc"), vrc);
- }
+ if (pData->u32Status == PROC_STS_ERROR)
+ rc = setError(VBOX_E_IPRT_ERROR,
+ tr("Process could not be started: %Rrc"), pData->u32Flags);
+ else
+ rc = setError(E_UNEXPECTED,
+ tr("The service call failed with error %Rrc"), vrc);
+ }
}
else /* Execution went fine. */
{
@@ -1085,6 +1138,8 @@ STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
STDMETHODIMP Guest::GetProcessOutput(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, ULONG64 aSize, ComSafeArrayOut(BYTE, aData))
{
+/** @todo r=bird: Eventually we should clean up all the timeout parameters
+ * in the API and have the same way of specifying infinite waits! */
#ifndef VBOX_WITH_GUEST_CONTROL
ReturnComNotImplemented();
#else /* VBOX_WITH_GUEST_CONTROL */
@@ -1096,7 +1151,7 @@ STDMETHODIMP Guest::GetProcessOutput(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS,
return E_INVALIDARG;
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
HRESULT rc = S_OK;
@@ -1122,31 +1177,31 @@ STDMETHODIMP Guest::GetProcessOutput(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS,
aTimeoutMS = UINT32_MAX;
/* Search for existing PID. */
- PHOSTEXECOUTCALLBACKDATA pData = (HOSTEXECOUTCALLBACKDATA*)RTMemAlloc(sizeof(HOSTEXECOUTCALLBACKDATA));
+ PCALLBACKDATAEXECOUT pData = (CALLBACKDATAEXECOUT*)RTMemAlloc(sizeof(CALLBACKDATAEXECOUT));
AssertReturn(pData, VBOX_E_IPRT_ERROR);
uint32_t uContextID = addCtrlCallbackContext(VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT,
- pData, sizeof(HOSTEXECOUTCALLBACKDATA), progress);
+ pData, sizeof(CALLBACKDATAEXECOUT), progress);
Assert(uContextID > 0);
-
+
size_t cbData = (size_t)RT_MIN(aSize, _64K);
com::SafeArray<BYTE> outputData(cbData);
-
+
VBOXHGCMSVCPARM paParms[5];
int i = 0;
paParms[i++].setUInt32(uContextID);
paParms[i++].setUInt32(aPID);
paParms[i++].setUInt32(aFlags); /** @todo Should represent stdout and/or stderr. */
-
+
int vrc = VINF_SUCCESS;
-
+
{
VMMDev *vmmDev;
{
- /* Make sure mParent is valid, so set the read lock while using.
+ /* Make sure mParent is valid, so set the read lock while using.
* Do not keep this lock while doing the actual call, because in the meanwhile
* another thread could request a write lock which would be a bad idea ... */
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
+
/* Forward the information to the VMM device. */
AssertPtr(mParent);
vmmDev = mParent->getVMMDev();
@@ -1159,11 +1214,11 @@ STDMETHODIMP Guest::GetProcessOutput(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS,
i, paParms);
}
}
-
+
if (RT_SUCCESS(vrc))
{
LogFlowFunc(("Waiting for HGCM callback (timeout=%ldms) ...\n", aTimeoutMS));
-
+
/*
* Wait for the HGCM low level callback until the process
* has been started (or something went wrong). This is necessary to
@@ -1174,7 +1229,7 @@ STDMETHODIMP Guest::GetProcessOutput(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS,
if (it != mCallbackList.end())
{
uint64_t u64Started = RTTimeMilliTS();
- while (!it->bCalled)
+ while (!it->fCalled)
{
/* Check for timeout. */
unsigned cMsWait;
@@ -1197,26 +1252,26 @@ STDMETHODIMP Guest::GetProcessOutput(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS,
break; /* Client wants to abort. */
}
RTThreadSleep(cMsWait);
- }
-
+ }
+
/* Was the whole thing canceled? */
if (!fCanceled)
{
- if (it->bCalled)
+ if (it->fCalled)
{
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
+
/* Did we get some output? */
- pData = (HOSTEXECOUTCALLBACKDATA*)it->pvData;
- Assert(it->cbData == sizeof(HOSTEXECOUTCALLBACKDATA));
+ pData = (PCALLBACKDATAEXECOUT)it->pvData;
+ Assert(it->cbData == sizeof(CALLBACKDATAEXECOUT));
AssertPtr(pData);
-
+
if (pData->cbData)
{
/* Do we need to resize the array? */
if (pData->cbData > cbData)
outputData.resize(pData->cbData);
-
+
/* Fill output in supplied out buffer. */
memcpy(outputData.raw(), pData->pvData, pData->cbData);
outputData.resize(pData->cbData); /* Shrink to fit actual buffer size. */
@@ -1260,12 +1315,12 @@ STDMETHODIMP Guest::GetProcessOutput(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS,
}
else /* PID lookup failed. */
rc = setError(VBOX_E_IPRT_ERROR,
- tr("Process (PID %u) not found!"), aPID);
+ tr("Process (PID %u) not found!"), aPID);
}
else /* HGCM operation failed. */
rc = setError(E_UNEXPECTED,
tr("The HGCM call failed with error %Rrc"), vrc);
-
+
/* Cleanup. */
progress->uninit();
progress.setNull();
@@ -1292,21 +1347,21 @@ STDMETHODIMP Guest::GetProcessStatus(ULONG aPID, ULONG *aExitCode, ULONG *aFlags
using namespace guestControl;
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
HRESULT rc = S_OK;
try
{
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
+
GuestProcessIterConst it;
for (it = mGuestProcessList.begin(); it != mGuestProcessList.end(); it++)
{
if (it->mPID == aPID)
break;
}
-
+
if (it != mGuestProcessList.end())
{
*aExitCode = it->mExitCode;
diff --git a/src/VBox/Main/HostImpl.cpp b/src/VBox/Main/HostImpl.cpp
index a1edc2dd3..a1894e4a5 100644
--- a/src/VBox/Main/HostImpl.cpp
+++ b/src/VBox/Main/HostImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: HostImpl.cpp 29620 2010-05-18 12:15:55Z vboxsync $ */
+/* $Id: HostImpl.cpp 29945 2010-06-01 12:49:25Z vboxsync $ */
/** @file
* VirtualBox COM class implementation: Host
*/
@@ -500,12 +500,6 @@ STDMETHODIMP Host::COMGETTER(NetworkInterfaces)(ComSafeArrayOut(IHostNetworkInte
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* The code is so hideously complicated that I can't tell whether the
- * host object lock is really needed. It was taken here, and as the
- * VirtualBox (mParent) is taken as well below nested deep down that
- * would be a lock order violation. */
- AutoMultiWriteLock2 alock(m->pParent, this COMMA_LOCKVAL_SRC_POS);
-
std::list <ComObjPtr<HostNetworkInterface> > list;
# ifdef VBOX_WITH_HOSTNETIF_API
diff --git a/src/VBox/Main/MachineImpl.cpp b/src/VBox/Main/MachineImpl.cpp
index e13be6044..aa6fc5d70 100644
--- a/src/VBox/Main/MachineImpl.cpp
+++ b/src/VBox/Main/MachineImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: MachineImpl.cpp 29620 2010-05-18 12:15:55Z vboxsync $ */
+/* $Id: MachineImpl.cpp 29971 2010-06-02 08:51:13Z vboxsync $ */
/** @file
* Implementation of IMachine in VBoxSVC.
*/
@@ -35,6 +35,7 @@
#include "VirtualBoxImpl.h"
#include "MachineImpl.h"
#include "ProgressImpl.h"
+#include "ProgressProxyImpl.h"
#include "MediumAttachmentImpl.h"
#include "MediumImpl.h"
#include "MediumLock.h"
@@ -4965,8 +4966,9 @@ STDMETHODIMP Machine::QueryLogFilename(ULONG aIdx, BSTR *aName)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
Utf8Str log = queryLogFilename(aIdx);
- if (RTFileExists(log.c_str()))
- log.cloneTo(aName);
+ if (!RTFileExists(log.c_str()))
+ log.setNull();
+ log.cloneTo(aName);
return S_OK;
}
@@ -5173,7 +5175,8 @@ HRESULT Machine::openSession(IInternalSessionControl *aControl)
AssertReturn(aControl, E_FAIL);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -5325,6 +5328,8 @@ HRESULT Machine::openSession(IInternalSessionControl *aControl)
if (mData->mSession.mState == SessionState_Spawning)
{
/* Note that the progress object is finalized later */
+ /** @todo Consider checking mData->mSession.mProgress for cancellation
+ * around here. */
/* We don't reset mSession.mPid here because it is necessary for
* SessionMachine::uninit() to reap the child process later. */
@@ -5376,7 +5381,7 @@ HRESULT Machine::openSession(IInternalSessionControl *aControl)
if (FAILED(rc))
sessionMachine->uninit();
- LogFlowThisFunc(("rc=%08X\n", rc));
+ LogFlowThisFunc(("rc=%Rhrc\n", rc));
LogFlowThisFuncLeave();
return rc;
}
@@ -5388,7 +5393,7 @@ HRESULT Machine::openSession(IInternalSessionControl *aControl)
HRESULT Machine::openRemoteSession(IInternalSessionControl *aControl,
IN_BSTR aType,
IN_BSTR aEnvironment,
- Progress *aProgress)
+ ProgressProxy *aProgress)
{
LogFlowThisFuncEnter();
@@ -5612,6 +5617,7 @@ HRESULT Machine::openRemoteSession(IInternalSessionControl *aControl,
return S_OK;
}
+
/**
* @note Locks this object for writing, calls the client process
* (outside the lock).
@@ -5837,7 +5843,7 @@ bool Machine::checkForSpawnFailure()
/* the process was already unexpectedly terminated, we just need to set an
* error and finalize session spawning */
rc = setError(E_FAIL,
- tr("Virtual machine '%ls' has terminated unexpectedly during startup"),
+ tr("The virtual machine '%ls' has terminated unexpectedly during startup"),
getName().raw());
#else
@@ -5853,19 +5859,19 @@ bool Machine::checkForSpawnFailure()
{
if (RT_SUCCESS(vrc) && status.enmReason == RTPROCEXITREASON_NORMAL)
rc = setError(E_FAIL,
- tr("Virtual machine '%ls' has terminated unexpectedly during startup with exit code %d"),
+ tr("The virtual machine '%ls' has terminated unexpectedly during startup with exit code %d"),
getName().raw(), status.iStatus);
else if (RT_SUCCESS(vrc) && status.enmReason == RTPROCEXITREASON_SIGNAL)
rc = setError(E_FAIL,
- tr("Virtual machine '%ls' has terminated unexpectedly during startup because of signal %d"),
+ tr("The virtual machine '%ls' has terminated unexpectedly during startup because of signal %d"),
getName().raw(), status.iStatus);
else if (RT_SUCCESS(vrc) && status.enmReason == RTPROCEXITREASON_ABEND)
rc = setError(E_FAIL,
- tr("Virtual machine '%ls' has terminated abnormally"),
+ tr("The virtual machine '%ls' has terminated abnormally"),
getName().raw(), status.iStatus);
else
rc = setError(E_FAIL,
- tr("Virtual machine '%ls' has terminated unexpectedly during startup (%Rrc)"),
+ tr("The virtual machine '%ls' has terminated unexpectedly during startup (%Rrc)"),
getName().raw(), rc);
}
@@ -9823,45 +9829,43 @@ STDMETHODIMP SessionMachine::GetIPCId(BSTR *aId)
/**
* @note Locks this object for writing.
*/
-STDMETHODIMP SessionMachine::SetPowerUpInfo(IVirtualBoxErrorInfo *aError)
+STDMETHODIMP SessionMachine::BeginPowerUp(IProgress *aProgress)
{
AutoCaller autoCaller(this);
AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- if ( mData->mSession.mState == SessionState_Open
- && mData->mSession.mProgress)
+ if (mData->mSession.mState != SessionState_Open)
+ return VBOX_E_INVALID_OBJECT_STATE;
+
+ if (!mData->mSession.mProgress.isNull())
+ mData->mSession.mProgress->setOtherProgressObject(aProgress);
+
+ return S_OK;
+}
+
+
+/**
+ * @note Locks this object for writing.
+ */
+STDMETHODIMP SessionMachine::EndPowerUp(LONG iResult)
+{
+ AutoCaller autoCaller(this);
+ AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ if (mData->mSession.mState != SessionState_Open)
+ return VBOX_E_INVALID_OBJECT_STATE;
+
+ /* Finalize the openRemoteSession progress object. */
+ if (mData->mSession.mProgress)
{
- /* Finalize the progress, since the remote session has completed
- * power on (successful or not). */
- if (aError)
- {
- /* Transfer error information immediately, as the
- * IVirtualBoxErrorInfo object is most likely transient. */
- HRESULT rc;
- LONG rRc = S_OK;
- rc = aError->COMGETTER(ResultCode)(&rRc);
- AssertComRCReturnRC(rc);
- Bstr rIID;
- rc = aError->COMGETTER(InterfaceID)(rIID.asOutParam());
- AssertComRCReturnRC(rc);
- Bstr rComponent;
- rc = aError->COMGETTER(Component)(rComponent.asOutParam());
- AssertComRCReturnRC(rc);
- Bstr rText;
- rc = aError->COMGETTER(Text)(rText.asOutParam());
- AssertComRCReturnRC(rc);
- mData->mSession.mProgress->notifyComplete(rRc, Guid(rIID), rComponent, Utf8Str(rText).raw());
- }
- else
- mData->mSession.mProgress->notifyComplete(S_OK);
+ mData->mSession.mProgress->notifyComplete((HRESULT)iResult);
mData->mSession.mProgress.setNull();
-
- return S_OK;
}
- else
- return VBOX_E_INVALID_OBJECT_STATE;
+ return S_OK;
}
/**
@@ -10055,13 +10059,16 @@ STDMETHODIMP SessionMachine::OnSessionEnd(ISession *aSession,
/* Create the progress object the client will use to wait until
* #checkForDeath() is called to uninitialize this session object after
- * it releases the IPC semaphore. */
+ * it releases the IPC semaphore.
+ * Note! Because we're "reusing" mProgress here, this must be a proxy
+ * object just like for openRemoteSession. */
Assert(mData->mSession.mProgress.isNull());
- ComObjPtr<Progress> progress;
+ ComObjPtr<ProgressProxy> progress;
progress.createObject();
ComPtr<IUnknown> pPeer(mPeer);
progress->init(mParent, pPeer,
- Bstr(tr("Closing session")), FALSE /* aCancelable */);
+ Bstr(tr("Closing session")),
+ FALSE /* aCancelable */);
progress.queryInterfaceTo(aProgress);
mData->mSession.mProgress = progress;
}
diff --git a/src/VBox/Main/Makefile.kmk b/src/VBox/Main/Makefile.kmk
index ca129c365..39c5f33ce 100644
--- a/src/VBox/Main/Makefile.kmk
+++ b/src/VBox/Main/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 29162 2010-05-06 15:15:40Z vboxsync $
+# $Id: Makefile.kmk 29859 2010-05-28 13:17:24Z vboxsync $
## @file
# Makefile for the VBox Main module.
#
@@ -76,18 +76,18 @@ VBOX_IDL_HEADER.XPCOM = $(VBOX_PATH_SDK)/bindings/xpcom/include/VirtualBox_XPCO
# The MS COM specific stuff.
if defined(VBOX_ONLY_SDK) || "$(KBUILD_TARGET)" == "win"
OTHERS += \
- $(VBOX_IDL_FILE.MSCOM) \
- $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h \
- $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox.tlb \
- $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox_i.c
+ $(VBOX_IDL_FILE.MSCOM) \
+ $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h \
+ $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox.tlb \
+ $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox_i.c
OTHER_CLEAN += \
- $(VBOX_IDL_FILE.MSCOM) \
- $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h \
- $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox.tlb \
- $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox_i.c \
- $(PATH_VBoxCOM)/VirtualBox.h \
- $(PATH_VBoxCOM)/VirtualBox_i.c \
- $(PATH_VBoxCOM)/VirtualBox.tlb
+ $(VBOX_IDL_FILE.MSCOM) \
+ $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h \
+ $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox.tlb \
+ $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox_i.c \
+ $(PATH_VBoxCOM)/VirtualBox.h \
+ $(PATH_VBoxCOM)/VirtualBox_i.c \
+ $(PATH_VBoxCOM)/VirtualBox.tlb
VBOX_MAIN_PREREQS += $(PATH_VBoxCOM)/VirtualBox_i.c
BLDDIRS += $(VBOX_PATH_SDK)/bindings/mscom/idl
@@ -224,10 +224,10 @@ VBoxSVC_DEFS = \
$(if $(VBOX_WITH_VUSB),VBOX_WITH_VUSB,)
ifdef VBOX_WITH_USB
VBoxSVC_DEFS += \
- VBOX_WITH_USB \
- $(if $(VBOX_WITH_EHCI),VBOX_WITH_EHCI,) \
- $(if $(VBOX_WITH_NEW_USB_CODE_ON_DARWIN),VBOX_WITH_NEW_USB_CODE_ON_DARWIN,) \
- $(if $(VBOX_WITH_NEW_USB_CODE_ON_SOLARIS),VBOX_WITH_NEW_USB_CODE_ON_SOLARIS,)
+VBOX_WITH_USB \
+ $(if $(VBOX_WITH_EHCI),VBOX_WITH_EHCI,) \
+ $(if $(VBOX_WITH_NEW_USB_CODE_ON_DARWIN),VBOX_WITH_NEW_USB_CODE_ON_DARWIN,) \
+ $(if $(VBOX_WITH_NEW_USB_CODE_ON_SOLARIS),VBOX_WITH_NEW_USB_CODE_ON_SOLARIS,)
endif
VBoxSVC_DEFS.win += VBOX_COM_OUTOFPROC_MODULE
VBoxSVC_DEFS.win.x86 += _WIN32_WINNT=0x0500
@@ -301,6 +301,7 @@ VBoxSVC_SOURCES = \
MediumAttachmentImpl.cpp \
MediumFormatImpl.cpp \
ProgressImpl.cpp \
+ ProgressProxyImpl.cpp \
HostImpl.cpp \
HostNetworkInterfaceImpl.cpp \
DHCPServerImpl.cpp \
@@ -353,9 +354,9 @@ ifdef VBOX_WITH_USB
linux/USBProxyServiceLinux.cpp_DEFS += VBOX_WITH_SYSFS_BY_DEFAULT
endif
VBoxSVC_SOURCES += \
- USBDeviceFilterImpl.cpp \
- USBProxyService.cpp \
- HostUSBDeviceImpl.cpp
+ USBDeviceFilterImpl.cpp \
+ USBProxyService.cpp \
+ HostUSBDeviceImpl.cpp
VBoxSVC_SOURCES.darwin += darwin/USBProxyServiceDarwin.cpp
VBoxSVC_SOURCES.linux += linux/USBProxyServiceLinux.cpp
VBoxSVC_SOURCES.os2 += os2/USBProxyServiceOs2.cpp
@@ -391,8 +392,8 @@ endif
ifdef VBOX_WITH_RESOURCE_USAGE_API
VBoxSVC_SOURCES += \
- PerformanceImpl.cpp \
- Performance.cpp
+ PerformanceImpl.cpp \
+ Performance.cpp
VBoxSVC_SOURCES.darwin += darwin/PerformanceDarwin.cpp
VBoxSVC_SOURCES.freebsd += freebsd/PerformanceFreeBSD.cpp
VBoxSVC_SOURCES.linux += linux/PerformanceLinux.cpp
@@ -479,8 +480,8 @@ if ( defined(VBOX_WITH_QTGUI) \
VBoxTestOGL_SOURCES = generic/OpenGLTestApp.cpp
VBoxTestOGL_LIBS = \
$(if $(VBOX_WITH_CROGL), \
- $(PATH_LIB)/VBoxOGLhostspuload$(VBOX_SUFF_LIB) \
- $(VBOX_LIB_OGL_HOSTCRUTIL),) \
+ $(PATH_LIB)/VBoxOGLhostspuload$(VBOX_SUFF_LIB) \
+ $(VBOX_LIB_OGL_HOSTCRUTIL),) \
$(if $(VBOX_WITH_VIDEOHWACCEL), $(PATH_LIB)/VBoxOGL2D$(VBOX_SUFF_LIB),) \
$(LIB_RUNTIME)
VBoxTestOGL_DEFS += \
@@ -609,7 +610,7 @@ VBoxC_LIBS += \
ifdef VBOX_WITH_NETFLT
VBoxC_LIBS.win += $(PATH_LIB)/WinNetConfig.lib \
- $(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/comsupp.lib \
+ $(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/comsupp.lib \
$(PATH_SDK_WINPSDK_LIB)/WbemUuid.Lib
endif
@@ -734,11 +735,11 @@ if defined(VBOX_WITH_HARDENING) && "$(KBUILD_TARGET)" == "linux"
INSTALLS.linux += VBoxMain-hardening-inst
VBoxMain-hardening-inst_INST = $(INST_BIN)components/
VBoxMain-hardening-inst_SYMLINKS = \
- VBoxDDU.so=>../VBoxDDU.so \
- VBoxREM.so=>../VBoxREM.so \
- VBoxRT.so=>../VBoxRT.so \
- VBoxVMM.so=>../VBoxVMM.so \
- VBoxXPCOM.so=>../VBoxXPCOM.so
+ VBoxDDU.so=>../VBoxDDU.so \
+ VBoxREM.so=>../VBoxREM.so \
+ VBoxRT.so=>../VBoxRT.so \
+ VBoxVMM.so=>../VBoxVMM.so \
+ VBoxXPCOM.so=>../VBoxXPCOM.so
endif
@@ -829,6 +830,61 @@ VBoxC_VBOX_HEADERS = \
VBoxC_VBOX_TRANSLATIONS = \
nls/VBoxC_de.ts
+ifdef VBOX_WITH_JMSCOM
+INSTALLS += VBoxJMscom-inst-jar
+
+#
+# Java glue JAR files
+#
+VBOX_JMSCOM_JAR = $(VBoxJMscom-inst-jar_0_OUTDIR)/vboxjmscom.jar
+VBOX_JMSCOM_TARGET := $(PATH_TARGET)/vboxjmscom-gen
+VBOX_JMSCOM_GEN = $(VBOX_JMSCOM_TARGET)/jmscomgen
+VBOX_JMSCOM_JDEST := $(VBOX_JMSCOM_TARGET)/jdest
+VBOX_GLUE_XSLT_DIR := $(PATH_ROOT)/src/VBox/Main/glue
+VBOX_JACOB_DIR := $(PATH_ROOT)/src/libs/jacob-1.15-M3
+
+VBoxJMscom-inst-jar_INST = $(INST_SDK)bindings/mscom/java/
+VBoxJMscom-inst-jar_SOURCES = \
+ $(VBOX_JMSCOM_JAR)
+VBoxJMscom-inst-jar_CLEAN = \
+ $(VBOX_JMSCOM_JAR) \
+ $(VBOX_JMSCOM_GEN)/jmscomglue.list \
+ $(wildcard \
+ $(VBOX_JMSCOM_GEN)/java/*.java \
+ $(VBOX_JMSCOM_JDEST)/*.class \
+ $(VBOX_JMSCOM_JDEST)/*/*.class \
+ $(VBOX_JMSCOM_JDEST)/*/*/*.class \
+ $(VBOX_JMSCOM_JDEST)/*/*/*/*.class \
+ )
+VBoxJMscom-inst-jar_BLDDIRS += $(VBOX_JMSCOM_GEN)/java
+
+$(VBOX_JMSCOM_GEN)/jmscomglue.list: \
+ $(VBOX_XIDL_FILE) \
+ $(VBOX_GLUE_XSLT_DIR)/glue-java.xsl \
+ $(VBOX_FILESPLIT) \
+ | $(VBOX_JMSCOM_GEN)/java/
+ $(call MSG_L1,Generating Java glue files from XIDL)
+ $(QUIET)$(RM) -f $(wildcard $(VBOX_JMSCOM_GEN)/java/*.java)
+ $(QUIET)$(VBOX_XSLTPROC) \
+ --stringparam G_vboxApiSuffix $(VBOX_API_SUFFIX) \
+ --stringparam G_vboxGlueStyle mscom \
+ -o $(VBOX_JMSCOM_GEN)/java/merged.file $(VBOX_GLUE_XSLT_DIR)/glue-java.xsl $<
+ $(QUIET)$(VBOX_FILESPLIT) $(VBOX_JMSCOM_GEN)/java/merged.file $(VBOX_JMSCOM_GEN)/java
+ $(QUIET)echo $(VBOX_JMSCOM_GEN)/java/*.java > $@
+
+$$(VBOX_JMSCOM_JAR): $(VBOX_JMSCOM_GEN)/jmscomglue.list | $$(dir $$@)
+ $(call MSG_TOOL,javac,$(notdir $@),jmscomgen.list,)
+ $(QUIET)$(RM) -Rf $(VBOX_JMSCOM_JDEST)
+ $(QUIET)$(MKDIR) -p $(VBOX_JMSCOM_JDEST)
+ $(call MSG_TOOL,javac,$(notdir $@),...,)
+ $(VBOX_JAVAC) $(VBOX_JAVAC_OPTS) \
+ @$(VBOX_JMSCOM_GEN)/jmscomglue.list \
+ -d $(VBOX_JMSCOM_JDEST) -classpath $(VBOX_JMSCOM_JDEST)$(VBOX_SEP)$(VBOX_JACOB_DIR)/jacob.jar
+ $(call MSG_LINK,$(notdir $@),$@)
+ $(VBOX_JAR) cf $@ -C $(VBOX_JMSCOM_JDEST) .
+
+endif # VBOX_WITH_JMSCOM
+
updatenls::
$(VBOX_LUPDATE) $(VBoxSVC_SOURCES) $(VBoxSVC_VBOX_HEADERS) -ts $(VBoxSVC_VBOX_TRANSLATIONS)
$(VBOX_LUPDATE) $(VBoxC_SOURCES) $(VBoxC_VBOX_HEADERS) -ts $(VBoxC_VBOX_TRANSLATIONS)
diff --git a/src/VBox/Main/MediumImpl.cpp b/src/VBox/Main/MediumImpl.cpp
index edfff34c9..61d04da96 100644
--- a/src/VBox/Main/MediumImpl.cpp
+++ b/src/VBox/Main/MediumImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: MediumImpl.cpp 29618 2010-05-18 12:07:30Z vboxsync $ */
+/* $Id: MediumImpl.cpp 29940 2010-06-01 11:09:44Z vboxsync $ */
/** @file
* VirtualBox COM class implementation
*/
@@ -1440,12 +1440,12 @@ STDMETHODIMP Medium::COMSETTER(Type)(MediumType_T aType)
m->type = aType;
+ mlock.release();
+
// saveSettings needs vbox lock
- ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox);
- mlock.leave();
AutoWriteLock alock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
- HRESULT rc = pVirtualBox->saveSettings();
+ HRESULT rc = m->pVirtualBox->saveSettings();
return rc;
}
@@ -1558,8 +1558,7 @@ STDMETHODIMP Medium::COMSETTER(AutoReset)(BOOL aAutoReset)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* VirtualBox::saveSettings() needs a write lock */
- AutoMultiWriteLock2 alock(m->pVirtualBox, this COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS);
if (m->pParent.isNull())
return setError(VBOX_E_NOT_SUPPORTED,
@@ -1570,6 +1569,11 @@ STDMETHODIMP Medium::COMSETTER(AutoReset)(BOOL aAutoReset)
{
m->autoReset = !!aAutoReset;
+ mlock.release();
+
+ // saveSettings needs vbox lock
+ AutoWriteLock alock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
+
return m->pVirtualBox->saveSettings();
}
@@ -1979,8 +1983,7 @@ STDMETHODIMP Medium::SetProperty(IN_BSTR aName, IN_BSTR aValue)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* VirtualBox::saveSettings() needs a write lock */
- AutoMultiWriteLock2 alock(m->pVirtualBox, this COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS);
switch (m->state)
{
@@ -2002,6 +2005,10 @@ STDMETHODIMP Medium::SetProperty(IN_BSTR aName, IN_BSTR aValue)
else
it->second = aValue;
+ mlock.release();
+
+ // saveSettings needs vbox lock
+ AutoWriteLock alock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
HRESULT rc = m->pVirtualBox->saveSettings();
return rc;
@@ -2050,8 +2057,7 @@ STDMETHODIMP Medium::SetProperties(ComSafeArrayIn(IN_BSTR, aNames),
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* VirtualBox::saveSettings() needs a write lock */
- AutoMultiWriteLock2 alock(m->pVirtualBox, this COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS);
com::SafeArray<IN_BSTR> names(ComSafeArrayInArg(aNames));
com::SafeArray<IN_BSTR> values(ComSafeArrayInArg(aValues));
@@ -2080,6 +2086,10 @@ STDMETHODIMP Medium::SetProperties(ComSafeArrayIn(IN_BSTR, aNames),
it->second = values[i];
}
+ mlock.release();
+
+ // saveSettings needs vbox lock
+ AutoWriteLock alock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
HRESULT rc = m->pVirtualBox->saveSettings();
return rc;
@@ -3448,9 +3458,7 @@ HRESULT Medium::queryInfo()
|| m->state == MediumState_LockedWrite);
alock.leave();
-
vrc = RTSemEventMultiWait(m->queryInfoSem, RT_INDEFINITE_WAIT);
-
alock.enter();
AssertRC(vrc);
@@ -5160,7 +5168,7 @@ HRESULT Medium::taskCreateBaseHandler(Medium::CreateBaseTask &task)
ComAssertRCThrow(vrc, E_FAIL);
/* unlock before the potentially lengthy operation */
- thisLock.leave();
+ thisLock.release();
try
{
@@ -5294,7 +5302,7 @@ HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task)
/* the two media are now protected by their non-default states;
* unlock the media before the potentially lengthy operation */
- mediaLock.leave();
+ mediaLock.release();
try
{
@@ -5411,7 +5419,7 @@ HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task)
{
if (fNeedsSaveSettings)
{
- mediaLock.leave();
+ mediaLock.release();
AutoWriteLock vboxlock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
m->pVirtualBox->saveSettings();
}
@@ -5816,7 +5824,7 @@ HRESULT Medium::taskCloneHandler(Medium::CloneTask &task)
Assert(pParent.isNull() || pParent->m->state == MediumState_LockedRead);
/* unlock before the potentially lengthy operation */
- thisLock.leave();
+ thisLock.release();
/* ensure the target directory exists */
rc = VirtualBox::ensureFilePathExists(targetLocation);
@@ -6237,7 +6245,7 @@ HRESULT Medium::taskCompactHandler(Medium::CompactTask &task)
Utf8Str location(m->strLocationFull);
/* unlock before the potentially lengthy operation */
- thisLock.leave();
+ thisLock.release();
vrc = VDCompact(hdd, VD_LAST_IMAGE, task.mVDOperationIfaces);
if (RT_FAILURE(vrc))
diff --git a/src/VBox/Main/ProgressImpl.cpp b/src/VBox/Main/ProgressImpl.cpp
index 90b9589c3..39ec05c29 100644
--- a/src/VBox/Main/ProgressImpl.cpp
+++ b/src/VBox/Main/ProgressImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: ProgressImpl.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: ProgressImpl.cpp 29989 2010-06-02 12:46:49Z vboxsync $ */
/** @file
*
* VirtualBox Progress COM class implementation
@@ -330,7 +330,7 @@ STDMETHODIMP ProgressBase::COMGETTER(TimeRemaining)(LONG *aTimeRemaining)
{
uint64_t ullTimeNow = RTTimeMilliTS();
uint64_t ullTimeElapsed = ullTimeNow - m_ullTimestamp;
- uint64_t ullTimeTotal = (uint64_t)(ullTimeElapsed / dPercentDone * 100);
+ uint64_t ullTimeTotal = (uint64_t)(ullTimeElapsed * 100 / dPercentDone);
uint64_t ullTimeRemaining = ullTimeTotal - ullTimeElapsed;
// Log(("ProgressBase::GetTimeRemaining: dPercentDone %RI32, ullTimeNow = %RI64, ullTimeElapsed = %RI64, ullTimeTotal = %RI64, ullTimeRemaining = %RI64\n",
@@ -834,20 +834,17 @@ STDMETHODIMP Progress::WaitForCompletion (LONG aTimeout)
/* if we're already completed, take a shortcut */
if (!mCompleted)
{
- RTTIMESPEC time;
- RTTimeNow(&time); /** @todo r=bird: Use monotonic time (RTTimeMilliTS()) here because of daylight saving and things like that. */
-
int vrc = VINF_SUCCESS;
bool fForever = aTimeout < 0;
int64_t timeLeft = aTimeout;
- int64_t lastTime = RTTimeSpecGetMilli(&time);
+ int64_t lastTime = RTTimeMilliTS();
while (!mCompleted && (fForever || timeLeft > 0))
{
mWaitersCount++;
alock.leave();
vrc = RTSemEventMultiWait(mCompletedSem,
- fForever ? RT_INDEFINITE_WAIT : (unsigned)timeLeft);
+ fForever ? RT_INDEFINITE_WAIT : (RTMSINTERVAL)timeLeft);
alock.enter();
mWaitersCount--;
@@ -860,9 +857,9 @@ STDMETHODIMP Progress::WaitForCompletion (LONG aTimeout)
if (!fForever)
{
- RTTimeNow (&time);
- timeLeft -= RTTimeSpecGetMilli(&time) - lastTime;
- lastTime = RTTimeSpecGetMilli(&time);
+ int64_t now = RTTimeMilliTS();
+ timeLeft -= now - lastTime;
+ lastTime = now;
}
}
@@ -900,13 +897,10 @@ STDMETHODIMP Progress::WaitForOperationCompletion(ULONG aOperation, LONG aTimeou
if ( !mCompleted
&& aOperation >= m_ulCurrentOperation)
{
- RTTIMESPEC time;
- RTTimeNow (&time);
-
int vrc = VINF_SUCCESS;
bool fForever = aTimeout < 0;
int64_t timeLeft = aTimeout;
- int64_t lastTime = RTTimeSpecGetMilli (&time);
+ int64_t lastTime = RTTimeMilliTS();
while ( !mCompleted && aOperation >= m_ulCurrentOperation
&& (fForever || timeLeft > 0))
@@ -927,9 +921,9 @@ STDMETHODIMP Progress::WaitForOperationCompletion(ULONG aOperation, LONG aTimeou
if (!fForever)
{
- RTTimeNow(&time);
- timeLeft -= RTTimeSpecGetMilli(&time) - lastTime;
- lastTime = RTTimeSpecGetMilli(&time);
+ int64_t now = RTTimeMilliTS();
+ timeLeft -= now - lastTime;
+ lastTime = now;
}
}
@@ -957,11 +951,15 @@ STDMETHODIMP Progress::Cancel()
if (!mCanceled)
{
+ LogThisFunc(("Canceling\n"));
mCanceled = TRUE;
if (m_pfnCancelCallback)
m_pfnCancelCallback(m_pvCancelUserArg);
}
+ else
+ LogThisFunc(("Already canceled\n"));
+
return S_OK;
}
@@ -1010,7 +1008,9 @@ STDMETHODIMP Progress::SetNextOperation(IN_BSTR bstrNextOperationDescription, UL
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- AssertReturn(!mCompleted && !mCanceled, E_FAIL);
+ if (mCanceled)
+ return E_FAIL;
+ AssertReturn(!mCompleted, E_FAIL);
AssertReturn(m_ulCurrentOperation + 1 < m_cOperations, E_FAIL);
++m_ulCurrentOperation;
@@ -1148,6 +1148,22 @@ HRESULT Progress::notifyComplete(HRESULT aResultCode)
}
/**
+ * Wrapper around Progress:notifyCompleteV.
+ */
+HRESULT Progress::notifyComplete(HRESULT aResultCode,
+ const GUID &aIID,
+ const Bstr &aComponent,
+ const char *aText,
+ ...)
+{
+ va_list va;
+ va_start(va, aText);
+ HRESULT hrc = notifyCompleteV(aResultCode, aIID, aComponent, aText, va);
+ va_end(va);
+ return hrc;
+}
+
+/**
* Marks the operation as complete and attaches full error info.
*
* See com::SupportErrorInfoImpl::setError(HRESULT, const GUID &, const wchar_t
@@ -1158,18 +1174,15 @@ HRESULT Progress::notifyComplete(HRESULT aResultCode)
* @param aComponent Name of the component that generates the error.
* @param aText Error message (must not be null), an RTStrPrintf-like
* format string in UTF-8 encoding.
- * @param ... List of arguments for the format string.
+ * @param va List of arguments for the format string.
*/
-HRESULT Progress::notifyComplete(HRESULT aResultCode,
- const GUID &aIID,
- const Bstr &aComponent,
- const char *aText,
- ...)
+HRESULT Progress::notifyCompleteV(HRESULT aResultCode,
+ const GUID &aIID,
+ const Bstr &aComponent,
+ const char *aText,
+ va_list va)
{
- va_list args;
- va_start(args, aText);
- Utf8Str text = Utf8StrFmtVA(aText, args);
- va_end (args);
+ Utf8Str text = Utf8StrFmtVA(aText, va);
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
@@ -1230,9 +1243,13 @@ bool Progress::notifyPointOfNoReturn(void)
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
if (mCanceled)
+ {
+ LogThisFunc(("returns false\n"));
return false;
+ }
mCancelable = FALSE;
+ LogThisFunc(("returns true\n"));
return true;
}
@@ -1570,13 +1587,10 @@ STDMETHODIMP CombinedProgress::WaitForCompletion (LONG aTimeout)
/* if we're already completed, take a shortcut */
if (!mCompleted)
{
- RTTIMESPEC time;
- RTTimeNow(&time);
-
HRESULT rc = S_OK;
bool forever = aTimeout < 0;
int64_t timeLeft = aTimeout;
- int64_t lastTime = RTTimeSpecGetMilli(&time);
+ int64_t lastTime = RTTimeMilliTS();
while (!mCompleted && (forever || timeLeft > 0))
{
@@ -1591,9 +1605,9 @@ STDMETHODIMP CombinedProgress::WaitForCompletion (LONG aTimeout)
if (!forever)
{
- RTTimeNow(&time);
- timeLeft -= RTTimeSpecGetMilli(&time) - lastTime;
- lastTime = RTTimeSpecGetMilli(&time);
+ int64_t now = RTTimeMilliTS();
+ timeLeft -= now - lastTime;
+ lastTime = now;
}
}
@@ -1657,12 +1671,9 @@ STDMETHODIMP CombinedProgress::WaitForOperationCompletion (ULONG aOperation, LON
LogFlowThisFunc(("will wait for mProgresses [%d] (%d)\n",
progress, operation));
- RTTIMESPEC time;
- RTTimeNow (&time);
-
bool forever = aTimeout < 0;
int64_t timeLeft = aTimeout;
- int64_t lastTime = RTTimeSpecGetMilli (&time);
+ int64_t lastTime = RTTimeMilliTS();
while (!mCompleted && aOperation >= m_ulCurrentOperation &&
(forever || timeLeft > 0))
@@ -1680,9 +1691,9 @@ STDMETHODIMP CombinedProgress::WaitForOperationCompletion (ULONG aOperation, LON
if (!forever)
{
- RTTimeNow(&time);
- timeLeft -= RTTimeSpecGetMilli(&time) - lastTime;
- lastTime = RTTimeSpecGetMilli(&time);
+ int64_t now = RTTimeMilliTS();
+ timeLeft -= now - lastTime;
+ lastTime = now;
}
}
@@ -1706,6 +1717,7 @@ STDMETHODIMP CombinedProgress::Cancel()
if (!mCanceled)
{
+ LogThisFunc(("Canceling\n"));
mCanceled = TRUE;
/** @todo Teleportation: Shouldn't this be propagated to mProgresses? If
* powerUp creates passes a combined progress object to the client, I
@@ -1715,6 +1727,9 @@ STDMETHODIMP CombinedProgress::Cancel()
m_pfnCancelCallback(m_pvCancelUserArg);
}
+ else
+ LogThisFunc(("Already canceled\n"));
+
return S_OK;
}
diff --git a/src/VBox/Main/ProgressProxyImpl.cpp b/src/VBox/Main/ProgressProxyImpl.cpp
new file mode 100644
index 000000000..042414620
--- /dev/null
+++ b/src/VBox/Main/ProgressProxyImpl.cpp
@@ -0,0 +1,693 @@
+/* $Id: ProgressProxyImpl.cpp 29948 2010-06-01 12:55:23Z vboxsync $ */
+/** @file
+ * IProgress implementation for Machine::openRemoteSession in VBoxSVC.
+ */
+
+/*
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <iprt/types.h>
+
+#if defined (VBOX_WITH_XPCOM)
+#include <nsIServiceManager.h>
+#include <nsIExceptionService.h>
+#include <nsCOMPtr.h>
+#endif /* defined (VBOX_WITH_XPCOM) */
+
+#include "ProgressProxyImpl.h"
+
+#include "VirtualBoxImpl.h"
+#include "VirtualBoxErrorInfoImpl.h"
+
+#include "Logging.h"
+
+#include <iprt/time.h>
+#include <iprt/semaphore.h>
+
+#include <VBox/err.h>
+
+////////////////////////////////////////////////////////////////////////////////
+// ProgressProxy class
+////////////////////////////////////////////////////////////////////////////////
+
+// constructor / destructor / uninitializer
+////////////////////////////////////////////////////////////////////////////////
+
+
+HRESULT ProgressProxy::FinalConstruct()
+{
+ mfMultiOperation = false;
+ muOtherProgressStartWeight = 0;
+ muOtherProgressWeight = 0;
+ muOtherProgressStartOperation = 0;
+
+ HRESULT rc = Progress::FinalConstruct();
+ return rc;
+}
+
+/**
+ * Initalize it as a one operation Progress object.
+ *
+ * This is used by SessionMachine::OnSessionEnd.
+ */
+HRESULT ProgressProxy::init(
+#if !defined (VBOX_COM_INPROC)
+ VirtualBox *pParent,
+#endif
+ IUnknown *pInitiator,
+ CBSTR bstrDescription,
+ BOOL fCancelable)
+{
+ mfMultiOperation = false;
+ muOtherProgressStartWeight = 1;
+ muOtherProgressWeight = 1;
+ muOtherProgressStartOperation = 1;
+
+ return Progress::init(
+#if !defined (VBOX_COM_INPROC)
+ pParent,
+#endif
+ pInitiator,
+ bstrDescription,
+ fCancelable,
+ 1 /* cOperations */,
+ 1 /* ulTotalOperationsWeight */,
+ bstrDescription /* bstrFirstOperationDescription */,
+ 1 /* ulFirstOperationWeight */,
+ NULL /* pId */);
+}
+
+/**
+ * Initialize for proxying one other progress object.
+ *
+ * This is tailored explicitly for the openRemoteSession code, so we start out
+ * with one operation where we don't have any remote object (powerUp). Then a
+ * remote object is added and stays with us till the end.
+ *
+ * The user must do normal completion notification or risk leave the threads
+ * waiting forever!
+ */
+HRESULT ProgressProxy::init(
+#if !defined (VBOX_COM_INPROC)
+ VirtualBox *pParent,
+#endif
+ IUnknown *pInitiator,
+ CBSTR bstrDescription,
+ BOOL fCancelable,
+ ULONG uTotalOperationsWeight,
+ CBSTR bstrFirstOperationDescription,
+ ULONG uFirstOperationWeight,
+ ULONG cOtherProgressObjectOperations)
+{
+ mfMultiOperation = false;
+ muOtherProgressStartWeight = uFirstOperationWeight;
+ muOtherProgressWeight = uTotalOperationsWeight - uFirstOperationWeight;
+ muOtherProgressStartOperation = 1;
+
+ return Progress::init(
+#if !defined (VBOX_COM_INPROC)
+ pParent,
+#endif
+ pInitiator,
+ bstrDescription,
+ fCancelable,
+ 1 + cOtherProgressObjectOperations /* cOperations */,
+ uTotalOperationsWeight,
+ bstrFirstOperationDescription,
+ uFirstOperationWeight,
+ NULL);
+}
+
+void ProgressProxy::FinalRelease()
+{
+ uninit();
+ mfMultiOperation = false;
+ muOtherProgressStartWeight = 0;
+ muOtherProgressWeight = 0;
+ muOtherProgressStartOperation = 0;
+}
+
+void ProgressProxy::uninit()
+{
+ LogFlowThisFunc(("\n"));
+
+ mptrOtherProgress.setNull();
+ Progress::uninit();
+}
+
+// Public methods
+////////////////////////////////////////////////////////////////////////////////
+
+/** Just a wrapper so we can automatically do the handover before setting
+ * the result locally. */
+HRESULT ProgressProxy::notifyComplete(HRESULT aResultCode)
+{
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ clearOtherProgressObjectInternal(true /* fEarly */);
+ HRESULT hrc = S_OK;
+ if (!mCompleted)
+ hrc = Progress::notifyComplete(aResultCode);
+ return hrc;
+}
+
+/** Just a wrapper so we can automatically do the handover before setting
+ * the result locally. */
+HRESULT ProgressProxy::notifyComplete(HRESULT aResultCode,
+ const GUID &aIID,
+ const Bstr &aComponent,
+ const char *aText,
+ ...)
+{
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ clearOtherProgressObjectInternal(true /* fEarly */);
+
+ HRESULT hrc = S_OK;
+ if (!mCompleted)
+ {
+ va_list va;
+ va_start(va, aText);
+ hrc = Progress::notifyCompleteV(aResultCode, aIID, aComponent, aText, va);
+ va_end(va);
+ }
+ return hrc;
+}
+
+/**
+ * Sets the other progress object unless the operation has been completed /
+ * canceled already.
+ *
+ * @returns false if failed/canceled, true if not.
+ * @param pOtherProgress The other progress object. Must not be NULL.
+ */
+bool ProgressProxy::setOtherProgressObject(IProgress *pOtherProgress)
+{
+ LogFlowThisFunc(("setOtherProgressObject: %p\n", pOtherProgress));
+ ComPtr<IProgress> ptrOtherProgress = pOtherProgress;
+
+ /*
+ * Query information from the other progress object before we grab the
+ * lock.
+ */
+ ULONG cOperations;
+ HRESULT hrc = pOtherProgress->COMGETTER(OperationCount)(&cOperations);
+ if (FAILED(hrc))
+ cOperations = 1;
+
+ Bstr bstrOperationDescription;
+ hrc = pOtherProgress->COMGETTER(Description)(bstrOperationDescription.asOutParam());
+ if (FAILED(hrc))
+ bstrOperationDescription = "oops";
+
+
+ /*
+ * Take the lock and check for cancelation, cancel the other object if
+ * we've been canceled already.
+ */
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ BOOL fCompletedOrCanceled = mCompleted || mCanceled;
+ if (!fCompletedOrCanceled)
+ {
+ /*
+ * Advance to the next object and operation. If the other object has
+ * more operations than anticipated, adjust our internal count.
+ */
+ mptrOtherProgress = ptrOtherProgress;
+ mfMultiOperation = cOperations > 1;
+
+ muOtherProgressStartWeight = m_ulOperationsCompletedWeight + m_ulCurrentOperationWeight;
+ muOtherProgressWeight = m_ulTotalOperationsWeight - muOtherProgressStartWeight;
+ Progress::SetNextOperation(bstrOperationDescription, muOtherProgressWeight);
+
+ muOtherProgressStartOperation = m_ulCurrentOperation;
+ m_cOperations = cOperations + m_ulCurrentOperation;
+
+ /*
+ * Check for cancelation and completion.
+ */
+ BOOL f;
+ hrc = ptrOtherProgress->COMGETTER(Completed)(&f);
+ fCompletedOrCanceled = FAILED(hrc) || f;
+
+ if (!fCompletedOrCanceled)
+ {
+ hrc = ptrOtherProgress->COMGETTER(Canceled)(&f);
+ fCompletedOrCanceled = SUCCEEDED(hrc) && f;
+ }
+
+ if (fCompletedOrCanceled)
+ {
+ LogFlowThisFunc(("Other object completed or canceled, clearing...\n"));
+ clearOtherProgressObjectInternal(false /*fEarly*/);
+ }
+ else
+ {
+ /*
+ * Finally, mirror the cancelable property.
+ * Note! Note necessary if we do passthru!
+ */
+ if (mCancelable)
+ {
+ hrc = ptrOtherProgress->COMGETTER(Cancelable)(&f);
+ if (SUCCEEDED(hrc) && !f)
+ {
+ LogFlowThisFunc(("The other progress object is not cancelable\n"));
+ mCancelable = FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ LogFlowThisFunc(("mCompleted=%RTbool mCanceled=%RTbool - Canceling the other progress object!\n",
+ mCompleted, mCanceled));
+ hrc = ptrOtherProgress->Cancel();
+ LogFlowThisFunc(("Cancel -> %Rhrc", hrc));
+ }
+
+ LogFlowThisFunc(("Returns %RTbool\n", !fCompletedOrCanceled));
+ return !fCompletedOrCanceled;
+}
+
+// Internal methods.
+////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Clear the other progress object reference, first copying over its state.
+ *
+ * This is used internally when completion is signalled one way or another.
+ *
+ * @param fEarly Early clearing or not.
+ */
+void ProgressProxy::clearOtherProgressObjectInternal(bool fEarly)
+{
+ if (mptrOtherProgress.isNotNull())
+ {
+ ComPtr<IProgress> ptrOtherProgress = mptrOtherProgress;
+ mptrOtherProgress.setNull();
+ copyProgressInfo(ptrOtherProgress, fEarly);
+ }
+}
+
+/**
+ * Called to copy over the progress information from @a pOtherProgress.
+ *
+ * @param pOtherProgress The source of the information.
+ * @param fEarly Early copy.
+ *
+ * @note The caller owns the write lock and as cleared mptrOtherProgress
+ * already (or we might recurse forever)!
+ */
+void ProgressProxy::copyProgressInfo(IProgress *pOtherProgress, bool fEarly)
+{
+ HRESULT hrc;
+ LogFlowThisFunc(("\n"));
+
+ /*
+ * No point in doing this if the progress object was canceled already.
+ */
+ if (!mCanceled)
+ {
+ /* Detect if the other progress object was canceled. */
+ BOOL fCanceled;
+ hrc = pOtherProgress->COMGETTER(Canceled)(&fCanceled);
+ if (FAILED(hrc))
+ fCanceled = FALSE;
+ if (fCanceled)
+ {
+ LogFlowThisFunc(("Canceled\n"));
+ mCanceled = TRUE;
+ if (m_pfnCancelCallback)
+ m_pfnCancelCallback(m_pvCancelUserArg);
+ }
+ else
+ {
+ /* Has it completed? */
+ BOOL fCompleted;
+ hrc = pOtherProgress->COMGETTER(Completed)(&fCompleted);
+ if (FAILED(hrc))
+ fCompleted = TRUE;
+ Assert(fCompleted || fEarly);
+ if (fCompleted)
+ {
+ /* Check the result. */
+ LONG hrcResult;
+ hrc = pOtherProgress->COMGETTER(ResultCode)(&hrcResult);
+ if (FAILED(hrc))
+ hrcResult = hrc;
+ if (SUCCEEDED((HRESULT)hrcResult))
+ LogFlowThisFunc(("Succeeded\n"));
+ else
+ {
+ /* Get the error information. */
+ ComPtr<IVirtualBoxErrorInfo> ptrErrorInfo;
+ hrc = pOtherProgress->COMGETTER(ErrorInfo)(ptrErrorInfo.asOutParam());
+ if (SUCCEEDED(hrc))
+ {
+ Bstr bstrIID;
+ hrc = ptrErrorInfo->COMGETTER(InterfaceID)(bstrIID.asOutParam()); AssertComRC(hrc);
+ if (FAILED(hrc))
+ bstrIID.setNull();
+
+ Bstr bstrComponent;
+ hrc = ptrErrorInfo->COMGETTER(Component)(bstrComponent.asOutParam()); AssertComRC(hrc);
+ if (FAILED(hrc))
+ bstrComponent = "failed";
+
+ Bstr bstrText;
+ hrc = ptrErrorInfo->COMGETTER(Text)(bstrText.asOutParam()); AssertComRC(hrc);
+ if (FAILED(hrc))
+ bstrText = "<failed>";
+
+ Utf8Str strText(bstrText);
+ LogFlowThisFunc(("Got ErrorInfo(%s); hrcResult=%Rhrc\n", strText.c_str(), hrcResult));
+ Progress::notifyComplete((HRESULT)hrcResult, Guid(bstrIID), bstrComponent, "%s", strText.c_str());
+ }
+ else
+ {
+ LogFlowThisFunc(("ErrorInfo failed with hrc=%Rhrc; hrcResult=%Rhrc\n", hrc, hrcResult));
+ Progress::notifyComplete((HRESULT)hrcResult, COM_IIDOF(IProgress), Bstr("ProgressProxy"),
+ tr("No error info"));
+ }
+ }
+ }
+ else
+ LogFlowThisFunc(("Not completed\n"));
+ }
+ }
+ else
+ LogFlowThisFunc(("Already canceled\n"));
+
+ /*
+ * Did cancelable state change (point of no return)?
+ */
+ if (mCancelable && !mCompleted && !mCanceled)
+ {
+ BOOL fCancelable;
+ hrc = pOtherProgress->COMGETTER(Cancelable)(&fCancelable); AssertComRC(hrc);
+ if (SUCCEEDED(hrc) && !fCancelable)
+ {
+ LogFlowThisFunc(("point-of-no-return reached\n"));
+ mCancelable = FALSE;
+ }
+ }
+}
+
+
+// IProgress properties
+////////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP ProgressProxy::COMGETTER(Cancelable)(BOOL *aCancelable)
+{
+ CheckComArgOutPointerValid(aCancelable);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ /* ASSUME: The cancelable property can only change to FALSE. */
+ if (!mCancelable || mptrOtherProgress.isNull())
+ *aCancelable = mCancelable;
+ else
+ {
+ hrc = mptrOtherProgress->COMGETTER(Cancelable)(aCancelable);
+ if (SUCCEEDED(hrc) && !*aCancelable)
+ {
+ LogFlowThisFunc(("point-of-no-return reached\n"));
+ mCancelable = FALSE;
+ }
+ }
+ }
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(Percent)(ULONG *aPercent)
+{
+ CheckComArgOutPointerValid(aPercent);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ if (mptrOtherProgress.isNull())
+ hrc = Progress::COMGETTER(Percent)(aPercent);
+ else
+ {
+ /*
+ * Get the overall percent of the other object and adjust it with
+ * the weighting given to the period before proxying started.
+ */
+ ULONG uPct;
+ hrc = mptrOtherProgress->COMGETTER(Percent)(&uPct);
+ if (SUCCEEDED(hrc))
+ {
+ double rdPercent = ((double)uPct / 100 * muOtherProgressWeight + muOtherProgressStartWeight)
+ / m_ulTotalOperationsWeight * 100;
+ *aPercent = RT_MIN((ULONG)rdPercent, 99); /* mptrOtherProgress is cleared when its completed, so we can never return 100%. */
+ }
+ }
+ }
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(TimeRemaining)(LONG *aTimeRemaining)
+{
+ CheckComArgOutPointerValid(aTimeRemaining);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ if (mptrOtherProgress.isNull())
+ hrc = Progress::COMGETTER(TimeRemaining)(aTimeRemaining);
+ else
+ hrc = mptrOtherProgress->COMGETTER(TimeRemaining)(aTimeRemaining);
+ }
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(Completed)(BOOL *aCompleted)
+{
+ /* Not proxied since we EXPECT a normal completion notification call. */
+ return Progress::COMGETTER(Completed)(aCompleted);
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(Canceled)(BOOL *aCanceled)
+{
+ CheckComArgOutPointerValid(aCanceled);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ /* Check the local data first, then the other object. */
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ hrc = Progress::COMGETTER(Canceled)(aCanceled);
+ if ( SUCCEEDED(hrc)
+ && !*aCanceled
+ && mptrOtherProgress.isNotNull()
+ && mCancelable)
+ {
+ hrc = mptrOtherProgress->COMGETTER(Canceled)(aCanceled);
+ if (SUCCEEDED(hrc) && *aCanceled)
+ /* This will not complete the object, only mark it as canceled. */
+ clearOtherProgressObjectInternal(false /*fEarly*/);
+ }
+ }
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(ResultCode)(LONG *aResultCode)
+{
+ /* Not proxied since we EXPECT a normal completion notification call. */
+ return Progress::COMGETTER(ResultCode)(aResultCode);
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(ErrorInfo)(IVirtualBoxErrorInfo **aErrorInfo)
+{
+ /* Not proxied since we EXPECT a normal completion notification call. */
+ return Progress::COMGETTER(ErrorInfo)(aErrorInfo);
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(Operation)(ULONG *aOperation)
+{
+ CheckComArgOutPointerValid(aOperation);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (mptrOtherProgress.isNull())
+ hrc = Progress::COMGETTER(Operation)(aOperation);
+ else
+ {
+ ULONG uCurOtherOperation;
+ hrc = mptrOtherProgress->COMGETTER(Operation)(&uCurOtherOperation);
+ if (SUCCEEDED(hrc))
+ *aOperation = uCurOtherOperation + muOtherProgressStartOperation;
+ }
+ }
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(OperationDescription)(BSTR *aOperationDescription)
+{
+ CheckComArgOutPointerValid(aOperationDescription);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (mptrOtherProgress.isNull() || !mfMultiOperation)
+ hrc = Progress::COMGETTER(OperationDescription)(aOperationDescription);
+ else
+ hrc = mptrOtherProgress->COMGETTER(OperationDescription)(aOperationDescription);
+ }
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(OperationPercent)(ULONG *aOperationPercent)
+{
+ CheckComArgOutPointerValid(aOperationPercent);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (mptrOtherProgress.isNull() || !mfMultiOperation)
+ hrc = Progress::COMGETTER(OperationPercent)(aOperationPercent);
+ else
+ hrc = mptrOtherProgress->COMGETTER(OperationPercent)(aOperationPercent);
+ }
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::COMSETTER(Timeout)(ULONG aTimeout)
+{
+ /* Not currently supported. */
+ NOREF(aTimeout);
+ AssertFailed();
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP ProgressProxy::COMGETTER(Timeout)(ULONG *aTimeout)
+{
+ /* Not currently supported. */
+ CheckComArgOutPointerValid(aTimeout);
+
+ AssertFailed();
+ return E_NOTIMPL;
+}
+
+// IProgress methods
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP ProgressProxy::WaitForCompletion(LONG aTimeout)
+{
+ HRESULT hrc;
+ LogFlowThisFuncEnter();
+ LogFlowThisFunc(("aTimeout=%d\n", aTimeout));
+
+ /* No need to wait on the proxied object for these since we'll get the
+ normal completion notifications. */
+ hrc = Progress::WaitForCompletion(aTimeout);
+
+ LogFlowThisFuncLeave();
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::WaitForOperationCompletion(ULONG aOperation, LONG aTimeout)
+{
+ LogFlowThisFuncEnter();
+ LogFlowThisFunc(("aOperation=%d aTimeout=%d\n", aOperation, aTimeout));
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ CheckComArgExpr(aOperation, aOperation < m_cOperations);
+
+ /*
+ * Check if we can wait locally.
+ */
+ if ( aOperation + 1 == m_cOperations /* final operation */
+ || mptrOtherProgress.isNull())
+ {
+ /* ASSUMES that Progress::WaitForOperationCompletion is using
+ AutoWriteLock::leave() as it saves us from duplicating the code! */
+ hrc = Progress::WaitForOperationCompletion(aOperation, aTimeout);
+ }
+ else
+ {
+ LogFlowThisFunc(("calling the other object...\n"));
+ ComPtr<IProgress> ptrOtherProgress = mptrOtherProgress;
+ alock.release();
+
+ hrc = ptrOtherProgress->WaitForOperationCompletion(aOperation, aTimeout);
+ }
+ }
+
+ LogFlowThisFuncLeave();
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::Cancel()
+{
+ LogFlowThisFunc(("\n"));
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (mptrOtherProgress.isNull() || !mCancelable)
+ hrc = Progress::Cancel();
+ else
+ {
+ hrc = mptrOtherProgress->Cancel();
+ if (SUCCEEDED(hrc))
+ clearOtherProgressObjectInternal(false /*fEarly*/);
+ }
+ }
+
+ LogFlowThisFunc(("returns %Rhrc\n", hrc));
+ return hrc;
+}
+
+STDMETHODIMP ProgressProxy::SetCurrentOperationProgress(ULONG aPercent)
+{
+ /* Not supported - why do we actually expose this? */
+ NOREF(aPercent);
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP ProgressProxy::SetNextOperation(IN_BSTR bstrNextOperationDescription, ULONG ulNextOperationsWeight)
+{
+ /* Not supported - why do we actually expose this? */
+ NOREF(bstrNextOperationDescription);
+ NOREF(ulNextOperationsWeight);
+ return E_NOTIMPL;
+}
+
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */
+
diff --git a/src/VBox/Main/SessionImpl.cpp b/src/VBox/Main/SessionImpl.cpp
index fc4f5feaf..47d74fce9 100644
--- a/src/VBox/Main/SessionImpl.cpp
+++ b/src/VBox/Main/SessionImpl.cpp
@@ -1,6 +1,6 @@
+/* $Id: SessionImpl.cpp 29953 2010-06-01 15:03:06Z vboxsync $ */
/** @file
- *
- * VBox Client Session COM Class implementation
+ * VBox Client Session COM Class implementation in VBoxC.
*/
/*
@@ -180,13 +180,21 @@ STDMETHODIMP Session::COMGETTER(Machine)(IMachine **aMachine)
CHECK_OPEN();
- HRESULT rc = E_FAIL;
-
+ HRESULT rc;
if (mConsole)
rc = mConsole->machine().queryInterfaceTo(aMachine);
else
rc = mRemoteMachine.queryInterfaceTo(aMachine);
- ComAssertComRC(rc);
+ if (FAILED(rc))
+ {
+ /** @todo VBox 3.3: replace E_FAIL with rc here. */
+ if (mConsole)
+ setError(E_FAIL, tr("Failed to query the session machine (%Rhrc)"), rc);
+ else if (FAILED_DEAD_INTERFACE(rc))
+ setError(E_FAIL, tr("Peer process crashed"));
+ else
+ setError(E_FAIL, tr("Failed to query the remote session machine (%Rhrc)"), rc);
+ }
return rc;
}
@@ -202,13 +210,21 @@ STDMETHODIMP Session::COMGETTER(Console)(IConsole **aConsole)
CHECK_OPEN();
- HRESULT rc = E_FAIL;
-
+ HRESULT rc;
if (mConsole)
rc = mConsole.queryInterfaceTo(aConsole);
else
rc = mRemoteConsole.queryInterfaceTo(aConsole);
- ComAssertComRC(rc);
+ if (FAILED(rc))
+ {
+ /** @todo VBox 3.3: replace E_FAIL with rc here. */
+ if (mConsole)
+ setError(E_FAIL, tr("Failed to query the console (%Rhrc)"), rc);
+ else if (FAILED_DEAD_INTERFACE(rc))
+ setError(E_FAIL, tr("Peer process crashed"));
+ else
+ setError(E_FAIL, tr("Failed to query the remote console (%Rhrc)"), rc);
+ }
return rc;
}
@@ -365,7 +381,7 @@ STDMETHODIMP Session::AssignRemoteMachine(IMachine *aMachine, IConsole *aConsole
/* query IInternalMachineControl interface */
mControl = aMachine;
- AssertReturn(!!mControl, E_FAIL); // This test appears to be redundant --JS
+ AssertReturn(!!mControl, E_FAIL);
/// @todo (dmik)
// currently, the remote session returns the same machine and
diff --git a/src/VBox/Main/StorageControllerImpl.cpp b/src/VBox/Main/StorageControllerImpl.cpp
index d30326672..a8146be8c 100644
--- a/src/VBox/Main/StorageControllerImpl.cpp
+++ b/src/VBox/Main/StorageControllerImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: StorageControllerImpl.cpp 29480 2010-05-14 15:24:19Z vboxsync $ */
+/* $Id: StorageControllerImpl.cpp 29686 2010-05-20 11:46:09Z vboxsync $ */
/** @file
*
@@ -143,7 +143,8 @@ HRESULT StorageController::init(Machine *aParent,
m->bd->strName = aName;
m->bd->mInstance = aInstance;
m->bd->mStorageBus = aStorageBus;
- if (aStorageBus != StorageBus_IDE)
+ if ( aStorageBus != StorageBus_IDE
+ && aStorageBus != StorageBus_Floppy)
m->bd->fUseHostIOCache = false;
else
m->bd->fUseHostIOCache = true;
diff --git a/src/VBox/Main/VirtualBoxImpl.cpp b/src/VBox/Main/VirtualBoxImpl.cpp
index 0f660a5a7..dbb68c7e0 100644
--- a/src/VBox/Main/VirtualBoxImpl.cpp
+++ b/src/VBox/Main/VirtualBoxImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: VirtualBoxImpl.cpp 28955 2010-05-02 18:03:45Z vboxsync $ */
+/* $Id: VirtualBoxImpl.cpp 29937 2010-06-01 08:41:32Z vboxsync $ */
/** @file
* Implementation of IVirtualBox in VBoxSVC.
@@ -56,6 +56,7 @@
#include "MediumImpl.h"
#include "SharedFolderImpl.h"
#include "ProgressImpl.h"
+#include "ProgressProxyImpl.h"
#include "HostImpl.h"
#include "USBControllerImpl.h"
#include "SystemPropertiesImpl.h"
@@ -1993,24 +1994,36 @@ STDMETHODIMP VirtualBox::OpenRemoteSession(ISession *aSession,
ComAssertMsgRet(!!control, ("No IInternalSessionControl interface"),
E_INVALIDARG);
+ /* get the teleporter enable state for the progress object init. */
+ BOOL fTeleporterEnabled;
+ rc = machine->COMGETTER(TeleporterEnabled)(&fTeleporterEnabled);
+ if (FAILED(rc))
+ return rc;
+
/* create a progress object */
- ComObjPtr<Progress> progress;
+ ComObjPtr<ProgressProxy> progress;
progress.createObject();
- progress->init(this, static_cast <IMachine *>(machine),
- Bstr(tr("Spawning session")),
- FALSE /* aCancelable */);
-
- rc = machine->openRemoteSession(control, aType, aEnvironment, progress);
-
+ rc = progress->init(this,
+ static_cast<IMachine *>(machine),
+ Bstr(tr("Spawning session")),
+ TRUE /* aCancelable */,
+ fTeleporterEnabled ? 20 : 10 /* uTotalOperationsWeight */,
+ Bstr(tr("Spawning session")),
+ 2 /* uFirstOperationWeight */,
+ fTeleporterEnabled ? 3 : 1 /* cOtherProgressObjectOperations */);
if (SUCCEEDED(rc))
{
- progress.queryInterfaceTo(aProgress);
+ rc = machine->openRemoteSession(control, aType, aEnvironment, progress);
+ if (SUCCEEDED(rc))
+ {
+ progress.queryInterfaceTo(aProgress);
- /* signal the client watcher thread */
- updateClientWatcher();
+ /* signal the client watcher thread */
+ updateClientWatcher();
- /* fire an event */
- onSessionStateChange(id, SessionState_Spawning);
+ /* fire an event */
+ onSessionStateChange(id, SessionState_Spawning);
+ }
}
return rc;
@@ -4454,6 +4467,7 @@ DECLCALLBACK(int) VirtualBox::AsyncEventHandler(RTTHREAD thread, void *pvUser)
return 0;
}
+
////////////////////////////////////////////////////////////////////////////////
/**
@@ -4486,6 +4500,70 @@ void *VirtualBox::CallbackEvent::handler()
callbacks = mVirtualBox->m->llCallbacks;
}
+#ifdef RT_OS_WINDOWS
+#if 0
+ // WIP
+
+ LPTYPEINFO ptinfo;
+ HRESULT hr;
+ LPTYPELIB ptlib;
+ DISPID dispid;
+
+ /* Real solution must cache all needed dispids once, ofc */
+ hr = ::LoadRegTypeLib(LIBID_VirtualBox, kTypeLibraryMajorVersion, kTypeLibraryMinorVersion, LOCALE_SYSTEM_DEFAULT, &ptlib);
+ hr = ptlib->GetTypeInfoOfGuid(IID_IVirtualBoxCallback, &ptinfo);
+ ptlib->Release();
+
+ OLECHAR FAR* szMember = L"OnMachineStateChange";
+
+ hr = ::DispGetIDsOfNames(ptinfo, &szMember, 1, &dispid);
+ ptinfo->Release();
+
+ int nConnections = mVirtualBox->m_vec.GetSize();
+ for (int i=0; i<nConnections; i++)
+ {
+ ComPtr<IUnknown> sp = mVirtualBox->m_vec.GetAt(i);
+ ComPtr<IVirtualBoxCallback> cbI;
+ ComPtr<IDispatch> cbD;
+
+ cbI = sp;
+ cbD = sp;
+
+ /**
+ * Would be like this in ideal world, unfortunately our consumers want to be invoked via IDispatch,
+ * thus going the hard way.
+ */
+#if 0
+ if (cbI != NULL)
+ {
+ HRESULT hrc = handleCallback(cbI);
+ if (hrc == VBOX_E_DONT_CALL_AGAIN)
+ {
+ // need to handle that somehow, maybe just set element to 0
+ }
+ }
+#endif
+ if (cbI != NULL && cbD != NULL)
+ {
+ CComVariant varResult, arg1, arg2;
+
+ ::VariantClear(&varResult);
+ ::VariantClear(&arg1);
+ ::VariantClear(&arg2);
+
+ VARIANTARG args[] = {arg1, arg2};
+ DISPPARAMS disp = { args, NULL, sizeof(args)/sizeof(args[0]), 0};
+
+ cbD->Invoke(dispid, IID_NULL,
+ LOCALE_USER_DEFAULT,
+ DISPATCH_METHOD,
+ &disp, &varResult,
+ NULL, NULL);
+ }
+ }
+#endif
+#endif
+
for (CallbackList::const_iterator it = callbacks.begin();
it != callbacks.end();
++it)
diff --git a/src/VBox/Main/glue/tests/Makefile.kmk b/src/VBox/Main/glue/tests/Makefile.kmk
new file mode 100644
index 000000000..e5473468f
--- /dev/null
+++ b/src/VBox/Main/glue/tests/Makefile.kmk
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2010 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+ifeq ($(KBUILD_HOST),darwin)
+ VBOX_BIN=/Applications/VirtualBox.app/Contents/MacOS
+ VBOX_SDK=$(VBOX_BIN)/sdk
+# JAVA_ARGS += -d32
+endif
+
+ifeq ($(KBUILD_HOST),linux)
+ VBOX_SDK=/home/nike/work/ws/out/linux.amd64/debug/bin/sdk
+ VBOX_BIN=/home/nike/work/ws/out/linux.amd64/debug/bin
+endif
+
+ifeq ($(KBUILD_HOST),win)
+ VBOX_SDK=e:/ws/out/win.amd64/debug/bin/sdk
+ VBOX_BIN=e:/ws/out/win.amd64/debug/bin
+ JACOB_DIR=e:/ws/src/libs/jacob-1.15-M3/
+ JACOB_JAR=$(JACOB_DIR)/jacob.jar
+ CLASSPATH += $(JACOB_JAR)$(SEP)
+ JAVA_ARGS += -Djava.library.path=$(JACOB_DIR)
+endif
+
+ifeq ($(KBUILD_HOST),win)
+ VBOX_JAR=$(VBOX_SDK)/bindings/mscom/java/vboxjmscom.jar
+ SEP=\;
+else
+ VBOX_JAR=$(VBOX_SDK)/bindings/xpcom/java/vboxjxpcom.jar
+ SEP=:
+endif
+
+JAVA_ARGS += -Dvbox.home=$(VBOX_BIN)
+CLASSPATH := $(CLASSPATH)$(VBOX_JAR)$(SEP).
+
+all: testvb
+
+testvb:
+ javac -cp $(VBOX_JAR) TestVBox.java
+ java $(JAVA_ARGS) -cp $(CLASSPATH) TestVBox
+
diff --git a/src/VBox/Main/glue/tests/TestVBox.java b/src/VBox/Main/glue/tests/TestVBox.java
new file mode 100644
index 000000000..d480f88f7
--- /dev/null
+++ b/src/VBox/Main/glue/tests/TestVBox.java
@@ -0,0 +1,107 @@
+/* $Id:$ */
+/*
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+import org.virtualbox_3_2.*;
+import java.util.List;
+
+class VBoxCallbacks extends VBoxObjectBase implements IVirtualBoxCallback
+{
+ public void onGuestPropertyChange(String machineId, String name, String value, String flags)
+ {
+ System.out.println("onGuestPropertyChange -- VM: " + machineId + ", " + name + "->" + value);
+ }
+ public void onSnapshotChange(String machineId, String snapshotId)
+ {
+ }
+ public void onSnapshotDeleted(String machineId, String snapshotId)
+ {
+ }
+ public void onSnapshotTaken(String machineId, String snapshotId) {}
+ public void onSessionStateChange(String machineId, SessionState state)
+ {
+ System.out.println("onSessionStateChange -- VM: " + machineId + ", state: " + state);
+ }
+ public void onMachineRegistered(String machineId, Boolean registered) {}
+ public void onMediumRegistered(String mediumId, DeviceType mediumType, Boolean registered) {}
+ public void onExtraDataChange(String machineId, String key, String value)
+ {
+ System.out.println("onExtraDataChange -- VM: " + machineId + ": " + key+"->"+value);
+ }
+ public Boolean onExtraDataCanChange(String machineId, String key, String value, Holder<String> error) { return true; }
+ public void onMachineDataChange(String machineId)
+ {}
+ public void onMachineStateChange(String machineId, MachineState state)
+ {
+ System.out.println("onMachineStateChange -- VM: " + machineId + ", state: " + state);
+ }
+}
+
+public class TestVBox
+{
+ static void testCallbacks(VirtualBoxManager mgr, IVirtualBox vbox)
+ {
+ IVirtualBoxCallback cbs = mgr.createIVirtualBoxCallback(new VBoxCallbacks());
+ vbox.registerCallback(cbs);
+ for (int i=0; i<100; i++)
+ {
+ mgr.waitForEvents(500);
+ }
+ vbox.unregisterCallback(cbs);
+ }
+
+ static void testEnumeration(VirtualBoxManager mgr, IVirtualBox vbox)
+ {
+ List<IMachine> machs = vbox.getMachines();
+ for (IMachine m : machs)
+ {
+ System.out.println("VM name: " + m.getName());// + ", RAM size: " + m.getMemorySize() + "MB");
+ System.out.println(" HWVirt: " + m.getHWVirtExProperty(HWVirtExPropertyType.Enabled)
+ + ", Nested Paging: " + m.getHWVirtExProperty(HWVirtExPropertyType.NestedPaging)
+ + ", PAE: " + m.getCPUProperty(CPUPropertyType.PAE) );
+ }
+ }
+
+ static void testStart(VirtualBoxManager mgr, IVirtualBox vbox)
+ {
+ String m = vbox.getMachines().get(0).getName();
+ System.out.println("\nAttempting to start VM '" + m + "'");
+ mgr.startVm(m, null, 7000);
+ }
+
+ public static void main(String[] args)
+ {
+ VirtualBoxManager mgr = VirtualBoxManager.getInstance(null);
+
+ System.out.println("\n--> initialized\n");
+
+ try
+ {
+ IVirtualBox vbox = mgr.getVBox();
+ System.out.println("VirtualBox version: " + vbox.getVersion() + "\n");
+ testEnumeration(mgr, vbox);
+ testStart(mgr, vbox);
+ //testCallbacks(mgr, vbox);
+
+ System.out.println("done, press Enter...");
+ int ch = System.in.read();
+ }
+ catch (Throwable e)
+ {
+ e.printStackTrace();
+ }
+
+ mgr.cleanup();
+
+ System.out.println("\n--< done\n");
+ }
+
+}
diff --git a/src/VBox/Main/hgcm/HGCMThread.cpp b/src/VBox/Main/hgcm/HGCMThread.cpp
index f60ae03a0..edeadcffb 100644
--- a/src/VBox/Main/hgcm/HGCMThread.cpp
+++ b/src/VBox/Main/hgcm/HGCMThread.cpp
@@ -89,6 +89,7 @@ class HGCMThread: public HGCMObject
/* A caller thread waits for completion of a SENT message on this event. */
RTSEMEVENTMULTI m_eventSend;
+ int32_t volatile m_i32MessagesProcessed;
/* Critical section for accessing the thread data, mostly for message queues. */
RTCRITSECT m_critsect;
@@ -212,6 +213,7 @@ HGCMThread::HGCMThread ()
m_thread (NIL_RTTHREAD),
m_eventThread (0),
m_eventSend (0),
+ m_i32MessagesProcessed (0),
m_fu32ThreadFlags (0),
m_pMsgInputQueueHead (NULL),
m_pMsgInputQueueTail (NULL),
@@ -432,12 +434,30 @@ int HGCMThread::MsgPost (HGCMMsgCore *pMsg, PHGCMMSGCALLBACK pfnCallback, bool f
if (fWait)
{
+ /* Immediately check if the message has been processed. */
while ((pMsg->m_fu32Flags & HGCM_MSG_F_PROCESSED) == 0)
{
- RTSemEventMultiWait (m_eventSend, RT_INDEFINITE_WAIT);
- RTSemEventMultiReset (m_eventSend);
+ /* Poll infrequently to make sure no completed message has been missed. */
+ RTSemEventMultiWait (m_eventSend, 1000);
LogFlow(("HGCMThread::MsgPost: wait completed flags = %08X\n", pMsg->m_fu32Flags));
+
+ if ((pMsg->m_fu32Flags & HGCM_MSG_F_PROCESSED) == 0)
+ {
+ RTThreadYield();
+ }
+ }
+
+ /* 'Our' message has been processed, so should reset the semaphore.
+ * There is still possible that another message has been processed
+ * and the semaphore has been signalled again.
+ * Reset only if there are no other messages completed.
+ */
+ int32_t c = ASMAtomicDecS32(&m_i32MessagesProcessed);
+ Assert(c >= 0);
+ if (c == 0)
+ {
+ RTSemEventMultiReset (m_eventSend);
}
rc = pMsg->m_rcSend;
@@ -580,6 +600,14 @@ void HGCMThread::MsgComplete (HGCMMsgCore *pMsg, int32_t result)
bool fWaited = ((pMsg->m_fu32Flags & HGCM_MSG_F_WAIT) != 0);
+ if (fWaited)
+ {
+ ASMAtomicIncS32(&m_i32MessagesProcessed);
+
+ /* This should be done before setting the HGCM_MSG_F_PROCESSED flag. */
+ pMsg->m_rcSend = result;
+ }
+
/* The message is now completed. */
pMsg->m_fu32Flags &= ~HGCM_MSG_F_IN_PROCESS;
pMsg->m_fu32Flags &= ~HGCM_MSG_F_WAIT;
@@ -591,11 +619,6 @@ void HGCMThread::MsgComplete (HGCMMsgCore *pMsg, int32_t result)
if (fWaited)
{
- /* If message is being waited, then it is referenced by the waiter and the pointer
- * if valid even after hgcmObjDeleteHandle.
- */
- pMsg->m_rcSend = result;
-
/* Wake up all waiters. so they can decide if their message has been processed. */
RTSemEventMultiSignal (m_eventSend);
}
diff --git a/src/VBox/Main/idl/VirtualBox.xidl b/src/VBox/Main/idl/VirtualBox.xidl
index b28f960d1..526b2cfdc 100644
--- a/src/VBox/Main/idl/VirtualBox.xidl
+++ b/src/VBox/Main/idl/VirtualBox.xidl
@@ -2729,6 +2729,16 @@
If the environment string is @c null or empty, the server environment
is inherited by the started process as is.
+ The progress object will have at least 2 operation. The first operation
+ covers the period up to the new VM process calls powerUp. The
+ subsequent operations mirrors the <link to="IConsole::powerUp"/>
+ progress object. Because <link to="IConsole::powerUp"/> may require
+ some extra operation, the <link to="IProgress::operationCount"/> may
+ change at the completion of operation1.
+
+ For details on the teleportation progress operation, see
+ <link to="IConsole::powerUp"/>.
+
<see>openExistingSession</see>
<result name="E_UNEXPECTED">
@@ -3238,13 +3248,13 @@
VirtualBox front-end such as the GUI, and the suggestions can be displayed to the
user. In particular, the <link to="#virtualSystemDescriptions" /> array contains
instances of <link to="IVirtualSystemDescription" /> which represent the virtual
- systems in the OVF, which in turn describe the virtual hardware prescribed by the
- OVF (network and hardware adapters, virtual disk images, memory size and so on).
+ systems (machines) in the OVF, which in turn describe the virtual hardware prescribed
+ by the OVF (network and hardware adapters, virtual disk images, memory size and so on).
The GUI can then give the user the option to confirm and/or change these suggestions.
</li>
<li>If desired, call <link to="IVirtualSystemDescription::setFinalValues" /> for each
- virtual system to override the suggestions made by the interpret() routine.
+ virtual system (machine) to override the suggestions made by the interpret() routine.
</li>
<li>Finally, call <link to="#importMachines" /> to create virtual machines in
@@ -3261,12 +3271,12 @@
</li>
<li>For each machine you would like to export, call <link to="IMachine::export" />
- with the IAppliance object you just created. This creates an instance of
+ with the IAppliance object you just created. Each such call creates one instance of
<link to="IVirtualSystemDescription" /> inside the appliance.
</li>
<li>If desired, call <link to="IVirtualSystemDescription::setFinalValues" /> for each
- virtual system to override the suggestions made by the export() routine.
+ virtual system (machine) to override the suggestions made by the export() routine.
</li>
<li>Finally, call <link to="#write" /> with a path specification to have the OVF
@@ -3324,7 +3334,7 @@
<attribute name="virtualSystemDescriptions" type="IVirtualSystemDescription" readonly="yes" safearray="yes">
<desc> Array of virtual system descriptions. One such description is created
- for each virtual system found in the OVF.
+ for each virtual system (machine) found in the OVF.
This array is empty until either <link to="#interpret" /> (for import) or <link to="IMachine::export" />
(for export) has been called.
</desc>
@@ -3489,11 +3499,12 @@
wsmap="managed"
>
- <desc>This interface is used in the <link to="IAppliance::virtualSystemDescriptions" /> array.
- After <link to="IAppliance::interpret" /> has been called, that array contains
- information about how the virtual systems described in the OVF should best be imported into VirtualBox
- virtual machines. See <link to="IAppliance" /> for the steps required to import an OVF
- into VirtualBox.
+ <desc>Represents one virtual system (machine) in an appliance. This interface is used in
+ the <link to="IAppliance::virtualSystemDescriptions" /> array. After
+ <link to="IAppliance::interpret" /> has been called, that array contains information
+ about how the virtual systems described in the OVF should best be imported into
+ VirtualBox virtual machines. See <link to="IAppliance" /> for the steps required to
+ import an OVF into VirtualBox.
</desc>
<attribute name="count" type="unsigned long" readonly="yes">
@@ -3749,7 +3760,7 @@
<interface
name="IInternalMachineControl" extends="$unknown"
- uuid="57e9a280-8d57-4331-aa31-f009f5194f52"
+ uuid="26604a54-8628-491b-a0ea-e1392a16d13b"
internal="yes"
wsmap="suppress"
>
@@ -3777,15 +3788,28 @@
<param name="id" type="wstring" dir="return"/>
</method>
- <method name="setPowerUpInfo">
+ <method name="beginPowerUp">
<desc>
- Transfers success (@c null) or error information for this session.
- This method updates the progress object to signal completion of the
- <link to="IVirtualBox::openRemoteSession"/> method if appropriate,
- which means that the progress object returned by
- <link to="IConsole::powerUp"/>.
+ Tells VBoxSVC that <link to="IConsole::powerUp"/> is under ways and
+ gives it the progress object that should be part of any pending
+ <link to="IVirtualBox::openRemoteSession"/> operations. The progress
+ object may be called back to reflect an early cancelation, so some care
+ have to be taken with respect to any cancelation callbacks. The console
+ object will call <link to="IInternalMachineControl::endPowerUp"/>
+ to signal the completion of the progress object.
</desc>
- <param name="error" type="IVirtualBoxErrorInfo" dir="in"/>
+ <param name="progress" type="IProgress" dir="in"/>
+ </method>
+
+ <method name="endPowerUp">
+ <desc>
+ Tells VBoxSVC that <link to="IConsole::powerUp"/> has completed.
+ This method may query status information from the progress object it
+ received in <link to="IInternalMachineControl::beginPowerUp"/> and copy
+ it over to any in progress <link to="IVirtualBox::openRemoteSession"/>
+ call in order to complete that progress object.
+ </desc>
+ <param name="result" type="long" dir="in"/>
</method>
<method name="runUSBDeviceFilters">
@@ -6836,6 +6860,16 @@
it will continue its execution the point where the state has
been saved.
+ If the machine <link to="IMachine::teleporterEnabled"/> property is
+ enabled on the machine being powered up, the machine will wait for an
+ incoming teleportation in the <link to="MachineState_TeleportingIn"/>
+ state. The returned progress object will have at least three
+ operations where the last three are defined as: (1) powering up and
+ starting TCP server, (2) waiting for incoming teleportations, and
+ (3) perform teleportation. These operations will be reflected as the
+ last three operations of the progress objected returned by
+ <link to="IVirtualBox::openRemoteSession"/> as well.
+
<note>
Unless you are trying to write a new VirtualBox front-end that
performs direct machine execution (like the VirtualBox or VBoxSDL
@@ -14515,6 +14549,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<class name="VirtualBox" uuid="B1A7A4F2-47B9-4A1E-82B2-07CCD5323C3F"
namespace="virtualbox.org">
<interface name="IVirtualBox" default="yes"/>
+ <eventsink name="IVirtualBoxCallback" default="yes"/>
</class>
</module>
@@ -14522,6 +14557,8 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<class name="Session" uuid="3C02F46D-C9D2-4F11-A384-53F0CF917214"
namespace="virtualbox.org">
<interface name="ISession" default="yes"/>
+ <eventsink name="IConsoleCallback" default="yes"/>
+
</class>
<class name="CallbackWrapper" uuid="49EE8561-5563-4715-B18C-A4B1A490DAFE"
namespace="virtualbox.org">
diff --git a/src/VBox/Main/idl/midl.xsl b/src/VBox/Main/idl/midl.xsl
index dca1adb03..b8bca3833 100644
--- a/src/VBox/Main/idl/midl.xsl
+++ b/src/VBox/Main/idl/midl.xsl
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<!-- $Id: midl.xsl 29200 2010-05-07 12:14:18Z vboxsync $ -->
+<!-- $Id: midl.xsl 29874 2010-05-28 18:14:44Z vboxsync $ -->
<!--
* A template to generate a MS IDL compatible interface definition file
@@ -632,6 +632,16 @@
<xsl:value-of select="@name"/>
<xsl:text>;&#x0A;</xsl:text>
</xsl:for-each>
+ <xsl:for-each select="eventsink">
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <xsl:when test="@default='yes'"><xsl:text>[default,source]</xsl:text></xsl:when>
+ <xsl:otherwise><xsl:text>[source]</xsl:text></xsl:otherwise>
+ </xsl:choose>
+ <xsl:text> interface </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>;&#x0A;</xsl:text>
+ </xsl:for-each>
<xsl:text>&#x0A;}; /* coclass </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text> */&#x0A;&#x0A;</xsl:text>
diff --git a/src/VBox/Main/include/ApplianceImpl.h b/src/VBox/Main/include/ApplianceImpl.h
index 14a8f0247..eac4fb26f 100644
--- a/src/VBox/Main/include/ApplianceImpl.h
+++ b/src/VBox/Main/include/ApplianceImpl.h
@@ -1,4 +1,4 @@
-/* $Id: ApplianceImpl.h 29422 2010-05-12 14:08:52Z vboxsync $ */
+/* $Id: ApplianceImpl.h 29925 2010-05-31 18:33:15Z vboxsync $ */
/** @file
*
@@ -119,7 +119,7 @@ private:
void addWarning(const char* aWarning, ...);
void disksWeight();
- enum SetUpProgressMode { Regular, ImportS3, WriteS3 };
+ enum SetUpProgressMode { ImportFileWithManifest, ImportFileNoManifest, ImportS3, WriteFile, WriteS3 };
HRESULT setUpProgress(ComObjPtr<Progress> &pProgress,
const Bstr &bstrDescription,
SetUpProgressMode mode);
@@ -144,7 +144,7 @@ private:
int32_t &lDevice);
HRESULT importImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress);
- HRESULT manifestVerify(const LocationInfo &locInfo, const ovf::OVFReader &reader);
+ HRESULT manifestVerify(const LocationInfo &locInfo, const ovf::OVFReader &reader, ComObjPtr<Progress> &pProgress);
HRESULT importFS(const LocationInfo &locInfo, ComObjPtr<Progress> &aProgress);
@@ -167,6 +167,7 @@ private:
struct XMLStack;
void buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSystemsTo,
+ std::list<xml::ElementNode*> *pllElementsWithUuidAttributes,
ComObjPtr<VirtualSystemDescription> &vsdescThis,
OVFFormat enFormat,
XMLStack &stack);
@@ -183,8 +184,10 @@ struct VirtualSystemDescriptionEntry
VirtualSystemDescriptionType_T type; // type of this entry
Utf8Str strRef; // reference number (hard disk controllers only)
Utf8Str strOvf; // original OVF value (type-dependent)
- Utf8Str strVbox; // configuration value (type-dependent)
- Utf8Str strExtraConfig; // extra configuration key=value strings (type-dependent)
+ Utf8Str strVboxSuggested; // configuration value (type-dependent); original value suggested by interpret()
+ Utf8Str strVboxCurrent; // configuration value (type-dependent); current value, either from interpret() or setFinalValue()
+ Utf8Str strExtraConfigSuggested; // extra configuration key=value strings (type-dependent); original value suggested by interpret()
+ Utf8Str strExtraConfigCurrent; // extra configuration key=value strings (type-dependent); current value, either from interpret() or setFinalValue()
uint32_t ulSizeMB; // hard disk images only: a copy of ovf::DiskImage::ulSuggestedSizeMB
};
diff --git a/src/VBox/Main/include/ApplianceImplPrivate.h b/src/VBox/Main/include/ApplianceImplPrivate.h
index f88043fb4..b09eea658 100644
--- a/src/VBox/Main/include/ApplianceImplPrivate.h
+++ b/src/VBox/Main/include/ApplianceImplPrivate.h
@@ -61,23 +61,24 @@ struct Appliance::Data
}
}
- ApplianceState state;
+ ApplianceState state;
- LocationInfo locInfo; // location info for the currently processed OVF
+ LocationInfo locInfo; // location info for the currently processed OVF
- ovf::OVFReader *pReader;
-
- bool fBusyWriting; // state protection; while this is true nobody else can call methods
+ ovf::OVFReader *pReader;
std::list< ComObjPtr<VirtualSystemDescription> >
- virtualSystemDescriptions;
+ virtualSystemDescriptions;
+
+ std::list<Utf8Str> llWarnings;
- std::list<Utf8Str> llWarnings;
+ Utf8Str strManifestFile; // on import, contains path of manifest file if it exists
- ULONG ulWeightPerOperation;
- ULONG ulTotalDisksMB;
- ULONG cDisks;
- Utf8Str strOVFSHA1Digest;
+ ULONG ulWeightForXmlOperation;
+ ULONG ulWeightForManifestOperation;
+ ULONG ulTotalDisksMB;
+ ULONG cDisks;
+ Utf8Str strOVFSHA1Digest;
};
struct Appliance::XMLStack
@@ -130,6 +131,60 @@ struct MyHardDiskAttachment
int32_t lDevice; // IDE: 0 or 1, otherwise 0 always
};
+/**
+ * Used by Appliance::importMachineGeneric() to store
+ * input parameters and rollback information.
+ */
+struct Appliance::ImportStack
+{
+ // input pointers
+ const LocationInfo &locInfo; // ptr to location info from Appliance::importFS()
+ Utf8Str strSourceDir; // directory where source files reside
+ const ovf::DiskImagesMap &mapDisks; // ptr to disks map in OVF
+ ComObjPtr<Progress> &pProgress; // progress object passed into Appliance::importFS()
+
+ // input parameters from VirtualSystemDescriptions
+ Utf8Str strNameVBox; // VM name
+ Utf8Str strOsTypeVBox; // VirtualBox guest OS type as string
+ uint32_t cCPUs; // CPU count
+ bool fForceHWVirt; // if true, we force enabling hardware virtualization
+ bool fForceIOAPIC; // if true, we force enabling the IOAPIC
+ uint32_t ulMemorySizeMB; // virtual machien RAM in megabytes
+#ifdef VBOX_WITH_USB
+ bool fUSBEnabled;
+#endif
+ Utf8Str strAudioAdapter; // if not empty, then the guest has audio enabled, and this is the decimal
+ // representation of the audio adapter (should always be "0" for AC97 presently)
+
+ // session (not initially created)
+ ComPtr<ISession> pSession; // session opened in Appliance::importFS() for machine manipulation
+ bool fSessionOpen; // true if the pSession is currently open and needs closing
+
+ // a list of images that we created/imported; this is initially empty
+ // and will be cleaned up on errors
+ std::list<MyHardDiskAttachment> llHardDiskAttachments; // disks that were attached
+ std::list< ComPtr<IMedium> > llHardDisksCreated; // media that were created
+ std::list<Bstr> llMachinesRegistered; // machines that were registered; list of string UUIDs
+
+ ImportStack(const LocationInfo &aLocInfo,
+ const ovf::DiskImagesMap &aMapDisks,
+ ComObjPtr<Progress> &aProgress)
+ : locInfo(aLocInfo),
+ mapDisks(aMapDisks),
+ pProgress(aProgress),
+ cCPUs(1),
+ fForceHWVirt(false),
+ fForceIOAPIC(false),
+ ulMemorySizeMB(0),
+ fSessionOpen(false)
+ {
+ // disk images have to be on the same place as the OVF file. So
+ // strip the filename out of the full file path
+ strSourceDir = aLocInfo.strPath;
+ strSourceDir.stripFilename();
+ }
+};
+
////////////////////////////////////////////////////////////////////////////////
//
// VirtualSystemDescription data definition
diff --git a/src/VBox/Main/include/ConsoleImpl.h b/src/VBox/Main/include/ConsoleImpl.h
index aad6de296..9198f1b1b 100644
--- a/src/VBox/Main/include/ConsoleImpl.h
+++ b/src/VBox/Main/include/ConsoleImpl.h
@@ -1,4 +1,4 @@
-/* $Id: ConsoleImpl.h 29580 2010-05-17 18:23:00Z vboxsync $ */
+/* $Id: ConsoleImpl.h 29965 2010-06-01 18:41:10Z vboxsync $ */
/** @file
* VBox Console COM Class definition
*/
@@ -518,8 +518,8 @@ private:
static DECLCALLBACK(int) stateProgressCallback(PVM pVM, unsigned uPercent, void *pvUser);
- static DECLCALLBACK(void) setVMErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
- const char *pszFormat, va_list args);
+ static DECLCALLBACK(void) genericVMSetErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
+ const char *pszErrorFmt, va_list va);
static DECLCALLBACK(void) setVMRuntimeErrorCallbackF(PVM pVM, void *pvUser, uint32_t fFatal,
const char *pszErrorId,
@@ -572,7 +572,8 @@ private:
HRESULT teleporterSrc(TeleporterStateSrc *pState);
HRESULT teleporterSrcReadACK(TeleporterStateSrc *pState, const char *pszWhich, const char *pszNAckMsg = NULL);
HRESULT teleporterSrcSubmitCommand(TeleporterStateSrc *pState, const char *pszCommand, bool fWaitForAck = true);
- int teleporterTrg(PVM pVM, IMachine *pMachine, bool fStartPaused, Progress *pProgress);
+ HRESULT teleporterTrg(PVM pVM, IMachine *pMachine, Utf8Str *pErrorMsg, bool fStartPaused,
+ Progress *pProgress, bool *pfPowerOffOnFailure);
static DECLCALLBACK(int) teleporterTrgServeConnection(RTSOCKET Sock, void *pvUser);
/** @} */
diff --git a/src/VBox/Main/include/GuestImpl.h b/src/VBox/Main/include/GuestImpl.h
index cb9039f22..032a1ed97 100644
--- a/src/VBox/Main/include/GuestImpl.h
+++ b/src/VBox/Main/include/GuestImpl.h
@@ -126,7 +126,7 @@ private:
void *pvData;
uint32_t cbData;
/** Atomic flag whether callback was called. */
- volatile bool bCalled;
+ volatile bool fCalled;
/** Pointer to user-supplied IProgress. */
ComObjPtr<Progress> pProgress;
};
@@ -136,10 +136,10 @@ private:
struct GuestProcess
{
- uint32_t mPID;
- uint32_t mStatus;
- uint32_t mFlags;
- uint32_t mExitCode;
+ uint32_t mPID;
+ uint32_t mStatus;
+ uint32_t mFlags;
+ uint32_t mExitCode;
};
typedef std::list< GuestProcess > GuestProcessList;
typedef std::list< GuestProcess >::iterator GuestProcessIter;
@@ -147,8 +147,9 @@ private:
int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv);
/** Handler for guest execution control notifications. */
- int notifyCtrlExec(uint32_t u32Function, PHOSTEXECCALLBACKDATA pData);
- int notifyCtrlExecOut(uint32_t u32Function, PHOSTEXECOUTCALLBACKDATA pData);
+ int notifyCtrlClientDisconnected(uint32_t u32Function, PCALLBACKDATACLIENTDISCONNECTED pData);
+ int notifyCtrlExecStatus(uint32_t u32Function, PCALLBACKDATAEXECSTATUS pData);
+ int notifyCtrlExecOut(uint32_t u32Function, PCALLBACKDATAEXECOUT pData);
CallbackListIter getCtrlCallbackContextByID(uint32_t u32ContextID);
GuestProcessIter getProcessByPID(uint32_t u32PID);
void destroyCtrlCallbackContext(CallbackListIter it);
diff --git a/src/VBox/Main/include/MachineImpl.h b/src/VBox/Main/include/MachineImpl.h
index e66b135f6..548ce1781 100644
--- a/src/VBox/Main/include/MachineImpl.h
+++ b/src/VBox/Main/include/MachineImpl.h
@@ -1,4 +1,4 @@
-/* $Id: MachineImpl.h 29462 2010-05-14 11:27:59Z vboxsync $ */
+/* $Id: MachineImpl.h 29864 2010-05-28 13:34:53Z vboxsync $ */
/** @file
* VirtualBox COM class implementation
*/
@@ -53,6 +53,7 @@
////////////////////////////////////////////////////////////////////////////////
class Progress;
+class ProgressProxy;
class Keyboard;
class Mouse;
class Display;
@@ -124,7 +125,7 @@ public:
RemoteControlList mRemoteControls;
/** openRemoteSession() and OnSessionEnd() progress indicator */
- ComObjPtr<Progress> mProgress;
+ ComObjPtr<ProgressProxy> mProgress;
/**
* PID of the session object that must be passed to openSession() to
@@ -621,7 +622,7 @@ public:
HRESULT openSession(IInternalSessionControl *aControl);
HRESULT openRemoteSession(IInternalSessionControl *aControl,
IN_BSTR aType, IN_BSTR aEnvironment,
- Progress *aProgress);
+ ProgressProxy *aProgress);
HRESULT openExistingSession(IInternalSessionControl *aControl);
HRESULT getDirectControl(ComPtr<IInternalSessionControl> *directControl)
@@ -886,7 +887,8 @@ public:
STDMETHOD(SetRemoveSavedState)(BOOL aRemove);
STDMETHOD(UpdateState)(MachineState_T machineState);
STDMETHOD(GetIPCId)(BSTR *id);
- STDMETHOD(SetPowerUpInfo)(IVirtualBoxErrorInfo *aError);
+ STDMETHOD(BeginPowerUp)(IProgress *aProgress);
+ STDMETHOD(EndPowerUp)(LONG iResult);
STDMETHOD(RunUSBDeviceFilters)(IUSBDevice *aUSBDevice, BOOL *aMatched, ULONG *aMaskedIfs);
STDMETHOD(CaptureUSBDevice)(IN_BSTR aId);
STDMETHOD(DetachUSBDevice)(IN_BSTR aId, BOOL aDone);
diff --git a/src/VBox/Main/include/ProgressCombinedImpl.h b/src/VBox/Main/include/ProgressCombinedImpl.h
index 57bd23ab6..b74372307 100644
--- a/src/VBox/Main/include/ProgressCombinedImpl.h
+++ b/src/VBox/Main/include/ProgressCombinedImpl.h
@@ -1,4 +1,4 @@
-/* $Id: ProgressCombinedImpl.h 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: ProgressCombinedImpl.h 29923 2010-05-31 17:55:44Z vboxsync $ */
/** @file
*
* VirtualBox COM class implementation
@@ -31,6 +31,11 @@
* that follow each other in the same order as progress objects are passed to
* the #init() method.
*
+ * @note CombinedProgress is legacy code and deprecated. It does not support
+ * weighted operations, all suboperations are assumed to take the same
+ * amount of time. For new code, please use IProgress directly which
+ * has supported multiple weighted suboperations since VirtualBox 3.0.
+ *
* Individual progress objects are sequentially combined so that this progress
* object:
*
diff --git a/src/VBox/Main/include/ProgressImpl.h b/src/VBox/Main/include/ProgressImpl.h
index 41cf845df..de174fe07 100644
--- a/src/VBox/Main/include/ProgressImpl.h
+++ b/src/VBox/Main/include/ProgressImpl.h
@@ -1,4 +1,4 @@
-/* $Id: ProgressImpl.h 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: ProgressImpl.h 29916 2010-05-31 15:26:56Z vboxsync $ */
/** @file
*
* VirtualBox COM class implementation
@@ -70,7 +70,7 @@ public:
STDMETHOD(COMGETTER(ResultCode)) (LONG *aResultCode);
STDMETHOD(COMGETTER(ErrorInfo)) (IVirtualBoxErrorInfo **aErrorInfo);
STDMETHOD(COMGETTER(OperationCount)) (ULONG *aOperationCount);
- STDMETHOD(COMGETTER(Operation)) (ULONG *aCount);
+ STDMETHOD(COMGETTER(Operation)) (ULONG *aOperation);
STDMETHOD(COMGETTER(OperationDescription)) (BSTR *aOperationDescription);
STDMETHOD(COMGETTER(OperationPercent)) (ULONG *aOperationPercent);
STDMETHOD(COMSETTER(Timeout)) (ULONG aTimeout);
@@ -260,7 +260,13 @@ public:
HRESULT notifyComplete(HRESULT aResultCode,
const GUID &aIID,
const Bstr &aComponent,
- const char *aText, ...);
+ const char *aText,
+ ...);
+ HRESULT notifyCompleteV(HRESULT aResultCode,
+ const GUID &aIID,
+ const Bstr &aComponent,
+ const char *aText,
+ va_list va);
bool notifyPointOfNoReturn(void);
/** For com::SupportErrorInfoImpl. */
diff --git a/src/VBox/Main/include/ProgressProxyImpl.h b/src/VBox/Main/include/ProgressProxyImpl.h
new file mode 100644
index 000000000..164637888
--- /dev/null
+++ b/src/VBox/Main/include/ProgressProxyImpl.h
@@ -0,0 +1,120 @@
+/* $Id: ProgressProxyImpl.h 29937 2010-06-01 08:41:32Z vboxsync $ */
+/** @file
+ * IProgress implementation for Machine::openRemoteSession in VBoxSVC.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_PROGRESSPROXYIMPL
+#define ____H_PROGRESSPROXYIMPL
+
+#include "ProgressImpl.h"
+#include "AutoCaller.h"
+
+
+/**
+ * The ProgressProxy class allows proxying the important Progress calls and
+ * attributes to a different IProgress object for a period of time.
+ */
+class ATL_NO_VTABLE ProgressProxy :
+ //public com::SupportErrorInfoDerived<Progress, ProgressProxy, IProgress>,
+ public Progress,
+ public VirtualBoxSupportTranslation<ProgressProxy>
+{
+public:
+ VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(ProgressProxy)
+ DECLARE_NOT_AGGREGATABLE(ProgressProxy)
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ BEGIN_COM_MAP(ProgressProxy)
+ COM_INTERFACE_ENTRY (ISupportErrorInfo)
+ COM_INTERFACE_ENTRY (IProgress)
+ COM_INTERFACE_ENTRY2(IDispatch, IProgress)
+ END_COM_MAP()
+
+ HRESULT FinalConstruct();
+ void FinalRelease();
+ HRESULT init(
+#if !defined (VBOX_COM_INPROC)
+ VirtualBox *pParent,
+#endif
+ IUnknown *pInitiator,
+ CBSTR bstrDescription,
+ BOOL fCancelable);
+ HRESULT init(
+#if !defined (VBOX_COM_INPROC)
+ VirtualBox *pParent,
+#endif
+ IUnknown *pInitiator,
+ CBSTR bstrDescription,
+ BOOL fCancelable,
+ ULONG uTotalOperationsWeight,
+ CBSTR bstrFirstOperationDescription,
+ ULONG uFirstOperationWeight,
+ ULONG cOtherProgressObjectOperations);
+ void uninit();
+
+ // IProgress properties
+ STDMETHOD(COMGETTER(Cancelable))(BOOL *aCancelable);
+ STDMETHOD(COMGETTER(Percent))(ULONG *aPercent);
+ STDMETHOD(COMGETTER(TimeRemaining))(LONG *aTimeRemaining);
+ STDMETHOD(COMGETTER(Completed))(BOOL *aCompleted);
+ STDMETHOD(COMGETTER(Canceled))(BOOL *aCanceled);
+ STDMETHOD(COMGETTER(ResultCode))(LONG *aResultCode);
+ STDMETHOD(COMGETTER(ErrorInfo))(IVirtualBoxErrorInfo **aErrorInfo);
+ //STDMETHOD(COMGETTER(OperationCount))(ULONG *aOperationCount); - not necessary
+ STDMETHOD(COMGETTER(Operation))(ULONG *aOperation);
+ STDMETHOD(COMGETTER(OperationDescription))(BSTR *aOperationDescription);
+ STDMETHOD(COMGETTER(OperationPercent))(ULONG *aOperationPercent);
+ STDMETHOD(COMSETTER(Timeout))(ULONG aTimeout);
+ STDMETHOD(COMGETTER(Timeout))(ULONG *aTimeout);
+
+ // IProgress methods
+ STDMETHOD(WaitForCompletion)(LONG aTimeout);
+ STDMETHOD(WaitForOperationCompletion)(ULONG aOperation, LONG aTimeout);
+ STDMETHOD(Cancel)();
+ STDMETHOD(SetCurrentOperationProgress)(ULONG aPercent);
+ STDMETHOD(SetNextOperation)(IN_BSTR bstrNextOperationDescription, ULONG ulNextOperationsWeight);
+
+ // public methods only for internal purposes
+
+ HRESULT notifyComplete(HRESULT aResultCode);
+ HRESULT notifyComplete(HRESULT aResultCode,
+ const GUID &aIID,
+ const Bstr &aComponent,
+ const char *aText, ...);
+ bool setOtherProgressObject(IProgress *pOtherProgress);
+
+ /** For com::SupportErrorInfoImpl. */
+ static const char *ComponentName() { return "ProgressProxy"; }
+
+protected:
+ void clearOtherProgressObjectInternal(bool fEarly);
+ void copyProgressInfo(IProgress *pOtherProgress, bool fEarly);
+
+private:
+ /** The other progress object. This can be NULL. */
+ ComPtr<IProgress> mptrOtherProgress;
+ /** Set if the other progress object has multiple operations. */
+ bool mfMultiOperation;
+ /** The weight the other progress object started at. */
+ ULONG muOtherProgressStartWeight;
+ /** The weight of other progress object. */
+ ULONG muOtherProgressWeight;
+ /** The operation number the other progress object started at. */
+ ULONG muOtherProgressStartOperation;
+
+};
+
+#endif /* !____H_PROGRESSPROXYIMPL */
+
diff --git a/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h b/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h
index b439124b2..186bfed48 100644
--- a/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h
+++ b/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h
@@ -1,10 +1,9 @@
/** @file
- *
- * VirtualBoxErrorInfo COM classe definition
+ * VirtualBoxErrorInfo COM class definition.
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -23,8 +22,11 @@
using namespace com;
class ATL_NO_VTABLE VirtualBoxErrorInfo
- : public CComObjectRootEx <CComMultiThreadModel>
- , public IVirtualBoxErrorInfo
+ : public CComObjectRootEx<CComMultiThreadModel>
+ , VBOX_SCRIPTABLE_IMPL(IVirtualBoxErrorInfo)
+#ifndef VBOX_WITH_XPCOM /* IErrorInfo doesn't inherit from IDispatch, ugly 3am hack: */
+ , public IDispatch
+#endif
{
public:
@@ -35,44 +37,69 @@ public:
BEGIN_COM_MAP(VirtualBoxErrorInfo)
COM_INTERFACE_ENTRY(IErrorInfo)
COM_INTERFACE_ENTRY(IVirtualBoxErrorInfo)
+ COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
-#if defined (RT_OS_WINDOWS)
+#ifndef VBOX_WITH_XPCOM
+
+ HRESULT init(IErrorInfo *aInfo);
+
+ STDMETHOD(GetGUID)(GUID *guid);
+ STDMETHOD(GetSource)(BSTR *source);
+ STDMETHOD(GetDescription)(BSTR *description);
+ STDMETHOD(GetHelpFile)(BSTR *pBstrHelpFile);
+ STDMETHOD(GetHelpContext)(DWORD *pdwHelpContext);
+
+ // IDispatch forwarding - 3am hack.
+ typedef IDispatchImpl<IVirtualBoxErrorInfo, &IID_IVirtualBoxErrorInfo, &LIBID_VirtualBox, kTypeLibraryMajorVersion, kTypeLibraryMinorVersion> idi;
+
+ STDMETHOD(GetTypeInfoCount)(UINT *pcInfo)
+ {
+ return idi::GetTypeInfoCount(pcInfo);
+ }
+
+ STDMETHOD(GetTypeInfo)(UINT iInfo, LCID Lcid, ITypeInfo **ppTypeInfo)
+ {
+ return idi::GetTypeInfo(iInfo, Lcid, ppTypeInfo);
+ }
- HRESULT init (IErrorInfo *aInfo);
+ STDMETHOD(GetIDsOfNames)(REFIID rIID, LPOLESTR *papwszNames, UINT cNames, LCID Lcid, DISPID *paDispIDs)
+ {
+ return idi::GetIDsOfNames(rIID, papwszNames, cNames, Lcid, paDispIDs);
+ }
- STDMETHOD(GetGUID) (GUID *guid);
- STDMETHOD(GetSource) (BSTR *source);
- STDMETHOD(GetDescription) (BSTR *description);
- STDMETHOD(GetHelpFile) (BSTR *pBstrHelpFile);
- STDMETHOD(GetHelpContext) (DWORD *pdwHelpContext);
+ STDMETHOD(Invoke)(DISPID idDispMember, REFIID rIID, LCID Lcid, WORD fw, DISPPARAMS *pDispParams,
+ VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *piErrArg)
+ {
+ return idi::Invoke(idDispMember, rIID, Lcid, fw, pDispParams, pVarResult, pExcepInfo, piErrArg);
+ }
-#else // !defined (RT_OS_WINDOWS)
+#else // defined(VBOX_WITH_XPCOM)
- HRESULT init (nsIException *aInfo);
+ HRESULT init(nsIException *aInfo);
NS_DECL_NSIEXCEPTION
#endif
- VirtualBoxErrorInfo() : mResultCode (S_OK) {}
+ VirtualBoxErrorInfo() : mResultCode(S_OK) {}
// public initializer/uninitializer for internal purposes only
- HRESULT init (HRESULT aResultCode, const GUID &aIID,
- CBSTR aComponent, CBSTR aText,
- IVirtualBoxErrorInfo *aNext = NULL);
+ HRESULT init(HRESULT aResultCode, const GUID &aIID,
+ CBSTR aComponent, CBSTR aText,
+ IVirtualBoxErrorInfo *aNext = NULL);
// IVirtualBoxErrorInfo properties
- STDMETHOD(COMGETTER(ResultCode)) (LONG *aResultCode);
- STDMETHOD(COMGETTER(InterfaceID)) (BSTR *aIID);
- STDMETHOD(COMGETTER(Component)) (BSTR *aComponent);
- STDMETHOD(COMGETTER(Text)) (BSTR *aText);
- STDMETHOD(COMGETTER(Next)) (IVirtualBoxErrorInfo **aNext);
+ STDMETHOD(COMGETTER(ResultCode))(LONG *aResultCode);
+ STDMETHOD(COMGETTER(InterfaceID))(BSTR *aIID);
+ STDMETHOD(COMGETTER(Component))(BSTR *aComponent);
+ STDMETHOD(COMGETTER(Text))(BSTR *aText);
+ STDMETHOD(COMGETTER(Next))(IVirtualBoxErrorInfo **aNext);
private:
// FIXME: declare these here until VBoxSupportsTranslation base
// is available in this class.
- static const char *tr (const char *a) { return a; }
+ static const char *tr(const char *a) { return a; }
static HRESULT setError(HRESULT rc,
const char * /* a */,
const char * /* b */,
@@ -85,6 +112,6 @@ private:
ComPtr<IVirtualBoxErrorInfo> mNext;
};
-#endif // ____H_VIRTUALBOXERRORINFOIMPL
+#endif // !____H_VIRTUALBOXERRORINFOIMPL
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/include/VirtualBoxImpl.h b/src/VBox/Main/include/VirtualBoxImpl.h
index 1c30d4d28..64cf7ddf5 100644
--- a/src/VBox/Main/include/VirtualBoxImpl.h
+++ b/src/VBox/Main/include/VirtualBoxImpl.h
@@ -1,4 +1,4 @@
-/* $Id: VirtualBoxImpl.h 28944 2010-04-30 17:49:02Z vboxsync $ */
+/* $Id: VirtualBoxImpl.h 29925 2010-05-31 18:33:15Z vboxsync $ */
/** @file
*
@@ -62,6 +62,8 @@ class ATL_NO_VTABLE VirtualBox :
VBOX_SCRIPTABLE_IMPL(IVirtualBox)
#ifdef RT_OS_WINDOWS
, public CComCoClass<VirtualBox, &CLSID_VirtualBox>
+ , public IConnectionPointContainerImpl<VirtualBox>
+ , public IConnectionPointImpl<VirtualBox, &IID_IVirtualBoxCallback, CComDynamicUnkArray>
#endif
{
@@ -83,11 +85,18 @@ public:
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(VirtualBox)
- COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY2(IDispatch, IVirtualBox)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(IVirtualBox)
+ COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()
+#ifdef RT_OS_WINDOWS
+ BEGIN_CONNECTION_POINT_MAP(VirtualBox)
+ CONNECTION_POINT_ENTRY(IID_IVirtualBoxCallback)
+ END_CONNECTION_POINT_MAP()
+#endif
+
// to postpone generation of the default ctor/dtor
VirtualBox();
~VirtualBox();
diff --git a/src/VBox/Main/include/ovfreader.h b/src/VBox/Main/include/ovfreader.h
index 3b4fa7dbc..698019045 100644
--- a/src/VBox/Main/include/ovfreader.h
+++ b/src/VBox/Main/include/ovfreader.h
@@ -1,4 +1,4 @@
-/* $Id: ovfreader.h 29422 2010-05-12 14:08:52Z vboxsync $ */
+/* $Id: ovfreader.h 29925 2010-05-31 18:33:15Z vboxsync $ */
/** @file
* OVF reader declarations.
*
@@ -310,7 +310,7 @@ struct VirtualSystem
{
iprt::MiniString strName; // copy of VirtualSystem/@id
- iprt::MiniString strDescription; // copy of VirtualSystem/Info content
+ iprt::MiniString strDescription; // copy of VirtualSystem/AnnotationSection content, if any
CIMOSType_T cimos;
iprt::MiniString strCimosDesc; // readable description of the cimos type in the case of cimos = 0/1/102
diff --git a/src/VBox/Main/linux/PerformanceLinux.cpp b/src/VBox/Main/linux/PerformanceLinux.cpp
index 1f763e5ba..87e3faa33 100644
--- a/src/VBox/Main/linux/PerformanceLinux.cpp
+++ b/src/VBox/Main/linux/PerformanceLinux.cpp
@@ -1,4 +1,4 @@
-/* $Id: PerformanceLinux.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: PerformanceLinux.cpp 29969 2010-06-02 07:31:27Z vboxsync $ */
/** @file
*
@@ -182,6 +182,7 @@ int CollectorLinux::getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uin
long long unsigned int u64Tmp;
unsigned uTmp;
unsigned long ulTmp;
+ signed long ilTmp;
ULONG u32user, u32kernel;
char buf[80]; /* @todo: this should be tied to max allowed proc name. */
@@ -196,7 +197,7 @@ int CollectorLinux::getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uin
"%ld %ld %ld %ld %ld %ld %llu %lu %u",
&pid2, buf, &c, &iTmp, &iTmp, &iTmp, &iTmp, &iTmp, &uTmp,
&ulTmp, &ulTmp, &ulTmp, &ulTmp, &u32user, &u32kernel,
- &ulTmp, &ulTmp, &ulTmp, &ulTmp, &ulTmp, &ulTmp, &u64Tmp,
+ &ilTmp, &ilTmp, &ilTmp, &ilTmp, &ilTmp, &ilTmp, &u64Tmp,
&ulTmp, memPagesUsed) == 24)
{
Assert((pid_t)process == pid2);
diff --git a/src/VBox/Main/webservice/Makefile.kmk b/src/VBox/Main/webservice/Makefile.kmk
index a3a7bfc67..9824126af 100644
--- a/src/VBox/Main/webservice/Makefile.kmk
+++ b/src/VBox/Main/webservice/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 28800 2010-04-27 08:22:32Z vboxsync $
+# $Id: Makefile.kmk 29843 2010-05-27 11:18:30Z vboxsync $
## @file
# Sub-Makefile for the VBox web service.
#
@@ -208,33 +208,33 @@ ifdef VBOX_GSOAP_INSTALLED
split-soapC_SOURCES = split-soapC.cpp
vboxsoap_SOURCES = \
- $(VBOXWEB_OUT_DIR)/soapC-1.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-2.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-3.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-4.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-5.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-6.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-7.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-8.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-9.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-10.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-11.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-12.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-13.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-14.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-15.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-16.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-17.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-18.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-19.cpp \
- $(VBOXWEB_OUT_DIR)/soapC-20.cpp
+ $(VBOXWEB_OUT_DIR)/soapC-1.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-2.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-3.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-4.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-5.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-6.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-7.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-8.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-9.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-10.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-11.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-12.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-13.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-14.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-15.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-16.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-17.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-18.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-19.cpp \
+ $(VBOXWEB_OUT_DIR)/soapC-20.cpp
endif
vboxsoap_CLEAN := $(vboxsoap_SOURCES) # lazy bird
vboxsoap_SOURCES += \
- $(VBOX_GSOAP_CXX_SOURCES)
+ $(VBOX_GSOAP_CXX_SOURCES)
vboxsoap_ORDERDEPS = \
- $(VBOXWEB_IDL_SRC) \
- $(VBOXWEB_OUT_DIR)/gsoap_copy_all_ts
+ $(VBOXWEB_IDL_SRC) \
+ $(VBOXWEB_OUT_DIR)/gsoap_copy_all_ts
ifn1of ($(KBUILD_TARGET), win)
$(VBOX_GSOAP_CXX_SOURCES)_CXXFLAGS = -Wno-format
endif
@@ -262,9 +262,9 @@ endif
vboxwebsrv_TEMPLATE = VBOXMAINCLIENTEXE
vboxwebsrv_DEFS += SOCKET_CLOSE_ON_EXEC
vboxwebsrv_INCS = \
- $(VBOX_GSOAP_INCS) \
- $(VBOXWEB_OUT_DIR) \
- .
+ $(VBOX_GSOAP_INCS) \
+ $(VBOXWEB_OUT_DIR) \
+ .
ifdef VBOX_USE_VCC80
vboxwebsrv_CXXFLAGS.win += -bigobj
endif
@@ -272,16 +272,16 @@ endif
vboxwebsrv_CXXFLAGS += -Wno-shadow
endif
vboxwebsrv_LIBS += \
- $(PATH_LIB)/vboxsoap$(VBOX_SUFF_LIB) \
- $(VBOX_GSOAP_CXX_LIBS)
+ $(PATH_LIB)/vboxsoap$(VBOX_SUFF_LIB) \
+ $(VBOX_GSOAP_CXX_LIBS)
vboxwebsrv_LIBS.solaris += socket nsl
vboxwebsrv_SOURCES = \
- vboxweb.cpp \
- $(VBOXWEB_OUT_DIR)/methodmaps.cpp \
- $(VBOXWEB_OUT_DIR)/soapServer.cpp
+ vboxweb.cpp \
+ $(VBOXWEB_OUT_DIR)/methodmaps.cpp \
+ $(VBOXWEB_OUT_DIR)/soapServer.cpp
vboxwebsrv_CLEAN = \
- $(VBOXWEB_OUT_DIR)/methodmaps.cpp \
- $(VBOXWEB_OUT_DIR)/soapServer.cpp
+ $(VBOXWEB_OUT_DIR)/methodmaps.cpp \
+ $(VBOXWEB_OUT_DIR)/soapServer.cpp
vboxwebsrv_ORDERDEPS = $(VBOXWEB_OUT_DIR)/gsoap_copy_all_ts
endif # !VBOX_ONLY_SDK
@@ -300,18 +300,18 @@ endif
webtest_CXXFLAGS += -Wno-shadow
endif
webtest_INCS := \
- $(VBOX_GSOAP_INCS) \
- $(VBOXWEB_OUT_DIR) \
- .
+ $(VBOX_GSOAP_INCS) \
+ $(VBOXWEB_OUT_DIR) \
+ .
webtest_LIBS += \
- $(PATH_LIB)/vboxsoap$(VBOX_SUFF_LIB) \
- $(VBOX_GSOAP_CXX_LIBS)
+ $(PATH_LIB)/vboxsoap$(VBOX_SUFF_LIB) \
+ $(VBOX_GSOAP_CXX_LIBS)
webtest_LIBS.solaris += nsl
webtest_SOURCES = \
- webtest.cpp \
- $(VBOXWEB_OUT_DIR)/soapClient.cpp
+ webtest.cpp \
+ $(VBOXWEB_OUT_DIR)/soapClient.cpp
webtest_CLEAN = \
- $(VBOXWEB_OUT_DIR)/soapClient.cpp
+ $(VBOXWEB_OUT_DIR)/soapClient.cpp
webtest_ORDERDEPS = $(VBOXWEB_OUT_DIR)/gsoap_copy_all_ts
endif # !VBOX_ONLY_SDK
@@ -322,21 +322,21 @@ endif
#
## @todo figure out whether the SDK really needs this or not...
OTHER_CLEAN += \
- $(wildcard $(VBOXWEB_OUT_DIR)/soap*.h) \
- $(wildcard $(VBOXWEB_OUT_DIR)/soap*.cpp) \
- $(wildcard $(VBOXWEB_OUT_DIR)/*.nsmap) \
- $(VBOXWEB_GSOAPH_FROM_XSLT) \
- $(VBOXWEB_GSOAPH_FROM_GSOAP) \
- $(VBOXWEB_SOAP_CLIENT_H) \
- $(VBOXWEB_SOAP_SERVER_H) \
- $(VBOXWEB_OUT_DIR)/gsoap_generate_all_ts \
- $(VBOXWEB_OUT_DIR)/gsoap_copy_all_ts \
- $(wildcard $(PATH_TARGET_SOAPDEMOXML)/*) \
- $(PATH_TARGET_SOAPDEMOXML)/dummy_file \
- $(wildcard $(PATH_TARGET_SOAPDEMOHEADERS)/*) \
- $(PATH_TARGET_SOAPDEMOHEADERS)/dummy_file \
- $(wildcard $(PATH_TARGET_SOAPDEMONSMAPS)/*) \
- $(PATH_TARGET_SOAPDEMONSMAPS)/dummy_file
+ $(wildcard $(VBOXWEB_OUT_DIR)/soap*.h) \
+ $(wildcard $(VBOXWEB_OUT_DIR)/soap*.cpp) \
+ $(wildcard $(VBOXWEB_OUT_DIR)/*.nsmap) \
+ $(VBOXWEB_GSOAPH_FROM_XSLT) \
+ $(VBOXWEB_GSOAPH_FROM_GSOAP) \
+ $(VBOXWEB_SOAP_CLIENT_H) \
+ $(VBOXWEB_SOAP_SERVER_H) \
+ $(VBOXWEB_OUT_DIR)/gsoap_generate_all_ts \
+ $(VBOXWEB_OUT_DIR)/gsoap_copy_all_ts \
+ $(wildcard $(PATH_TARGET_SOAPDEMOXML)/*) \
+ $(PATH_TARGET_SOAPDEMOXML)/dummy_file \
+ $(wildcard $(PATH_TARGET_SOAPDEMOHEADERS)/*) \
+ $(PATH_TARGET_SOAPDEMOHEADERS)/dummy_file \
+ $(wildcard $(PATH_TARGET_SOAPDEMONSMAPS)/*) \
+ $(PATH_TARGET_SOAPDEMONSMAPS)/dummy_file
endif # VBOX_GSOAP_INSTALLED
@@ -364,13 +364,13 @@ define find_java_files
$(shell find $(1) -name \*.java)
endef
-
VBOX_JAXWS_LIBDIR = $(VBOX_PATH_WEBSERVICE)/jaxlibs
# well, not really good
VBOX_JAVA15 = $(firstword $(wildcard \
/usr/lib/jvm/java-1.5.0-sun/bin/java \
- /usr/jdk/jdk1.5*/bin/java \
- /opt/sun-jdk-1.5*/bin/java))
+ /usr/jdk/jdk1.5*/bin/java \
+ /opt/sun-jdk-1.5*/bin/java \
+ /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Commands/java))
ifndef VBOX_JAVA15
$(error Failed to autodetect VBOX_JAVA15, please set it manually)
endif
@@ -386,26 +386,18 @@ endef
$(error Failed to autodetect VBOX_WSIMPORT16, please set it manually)
endif
VBOX_JAR = jar
- # Keep in sync with G_virtualBoxPackage in glue-jaxws.xsl
- # Changed with every new version, so beware!
- if $(VBOX_VERSION_BUILD) < 51
- VBOX_API_SUFFIX = _$(VBOX_VERSION_MAJOR)_$(VBOX_VERSION_MINOR)
- else
- VBOX_API_SUFFIX = _$(VBOX_VERSION_MAJOR)_$(expr $(VBOX_VERSION_MINOR) + 1)
- endif
- VBOX_JAVA_PACKAGE = org.virtualbox$(VBOX_API_SUFFIX)
VBOXWEB_OTHERS += \
- $(VBOXWEB_GLUE_JAVA_TMP) \
- $(VBOXWEB_GLUE_PYTHON) \
- $(VBOXWEB_WS_PYTHON) \
- $(VBOXWEB_WS_PERL) \
- $(VBOXWEB_WS_PHP) \
- $(VBOXWEB_PYTHONWSSAMPLE)\
- $(VBOXWEB_JAXWSSAMPLE) \
- $(VBOXWEB_METRICSAMPLE) \
- $(VBOXWEB_JAVA15_JAR) \
- $(VBOXWEB_JAVA16_JAR)
+ $(VBOXWEB_GLUE_JAVA_TMP) \
+ $(VBOXWEB_GLUE_PYTHON) \
+ $(VBOXWEB_WS_PYTHON) \
+ $(VBOXWEB_WS_PERL) \
+ $(VBOXWEB_WS_PHP) \
+ $(VBOXWEB_PYTHONWSSAMPLE)\
+ $(VBOXWEB_JAXWSSAMPLE) \
+ $(VBOXWEB_METRICSAMPLE) \
+ $(VBOXWEB_JAVA15_JAR) \
+ $(VBOXWEB_JAVA16_JAR)
#
# Install sample code.
@@ -414,20 +406,13 @@ endef
vboxwebinst_INST = $(INST_SDK)bindings/webservice/
vboxwebinst_MODE = a+rx,u+w
vboxwebinst_SOURCES = \
- samples/java/axis/clienttest.java=>java/axis/samples/clienttest.java \
- samples/java/jax-ws/Makefile.glue=>java/jax-ws/src/Makefile \
- samples/java/jax-ws/Makefile=>java/jax-ws/samples/Makefile \
- samples/perl/clienttest.pl=>perl/samples/clienttest.pl \
- samples/php/clienttest.php=>php/samples/clienttest.php \
- samples/python/Makefile=>python/samples/Makefile \
- samples/python/Makefile.glue=>python/lib/Makefile
-
- #
- # filesplitter - build helper, splits up the java classes.
- #
- BLDPROGS += filesplitter
- filesplitter_TEMPLATE = VBOXBLDPROG
- filesplitter_SOURCES = filesplitter.cpp
+ samples/java/axis/clienttest.java=>java/axis/samples/clienttest.java \
+ samples/java/jax-ws/Makefile.glue=>java/jax-ws/src/Makefile \
+ samples/java/jax-ws/Makefile=>java/jax-ws/samples/Makefile \
+ samples/perl/clienttest.pl=>perl/samples/clienttest.pl \
+ samples/php/clienttest.php=>php/samples/clienttest.php \
+ samples/python/Makefile=>python/samples/Makefile \
+ samples/python/Makefile.glue=>python/lib/Makefile
endif # VBOX_ONLY_SDK
@@ -619,7 +604,7 @@ $(VBOXWEB_METRICSAMPLE): $(VBOX_PATH_WEBSERVICE)/samples/java/jax-ws/metrictest.
$(QUIET)$(SED) -e 's/{VBOX_API_SUFFIX}/$(VBOX_API_SUFFIX)/' < $< > $@
# generate jax-ws wrapper for java client code
-$(VBOXWEB_GLUE_JAVA_TMP): $(VBOXWEB_IDL_SRC) $(VBOX_PATH_WEBSERVICE)/glue-jaxws.xsl $(VBOX_PATH_WEBSERVICE)/websrv-shared.inc.xsl $$(TARGET_filesplitter) $(RECOMPILE_ON_MAKEFILE_CURRENT) | $$(dir $$@)
+$(VBOXWEB_GLUE_JAVA_TMP): $(VBOXWEB_IDL_SRC) $(VBOX_PATH_WEBSERVICE)/glue-jaxws.xsl $(VBOX_PATH_WEBSERVICE)/websrv-shared.inc.xsl $(RECOMPILE_ON_MAKEFILE_CURRENT) | $$(dir $$@)
$(QUIET)$(MKDIR) -p $(@D)
$(call MSG_GENERATE,,$@,$(VBOXWEB_IDL_SRC) using glue-jaxws.xsl)
$(QUIET)$(VBOX_XSLTPROC) $(VBOXWEB_XSLTPROC_VERBOSE) \
@@ -628,7 +613,7 @@ $(VBOXWEB_GLUE_JAVA_TMP): $(VBOXWEB_IDL_SRC) $(VBOX_PATH_WEBSERVICE)/glue-jaxws.
$(call MSG_GENERATE,,java client glue files in $(VBOXWEB_PATH_SDK_GLUE_JAVA))
$(RM) -R -f $(VBOXWEB_PATH_SDK_GLUE_JAVA)
$(QUIET)$(MKDIR) -p $(VBOXWEB_PATH_SDK_GLUE_JAVA)
- $(QUIET)$(TARGET_filesplitter) $@ $(VBOXWEB_PATH_SDK_GLUE_JAVA)
+ $(QUIET)$(VBOX_FILESPLIT) $@ $(VBOXWEB_PATH_SDK_GLUE_JAVA)
$(QUIET)$(CP) -f $(VBOX_PATH_WEBSERVICE)/../../../../COPYING.LIB $(VBOXWEB_PATH_SDK_GLUE_JAVA)
$(VBOXWEB_GLUE_JAVA_TMP).done: $(VBOXWEB_GLUE_JAVA_TMP)
@@ -664,4 +649,3 @@ $(VBOXWEB_JAVA16_JAR): $(VBOXWEB_GLUE_JAVA_TMP).done $(VBOXWEB_WSDL) $(VBOXWEBSE
endif # VBOX_ONLY_SDK
include $(KBUILD_PATH)/subfooter.kmk
-
diff --git a/src/VBox/Main/webservice/filesplitter.cpp b/src/VBox/Main/webservice/filesplitter.cpp
deleted file mode 100644
index 9fb716d25..000000000
--- a/src/VBox/Main/webservice/filesplitter.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/** @file
- * File splitter: splits a text file according to ###### markers in it.
- */
-
-/*
- * Copyright (C) 2006-2009 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-static unsigned long lineNumber(const char *pStr, const char *pPos)
-{
- unsigned long cLine = 0;
- while (*pStr && pStr < pPos)
- {
- pStr = strchr(pStr, '\n');
- if (!pStr)
- break;
- ++cLine;
- ++pStr;
- }
-
- return cLine;
-}
-
-int main(int argc, char *argv[])
-{
- int rc = 0;
- const char *pcszBeginMarker = "\n// ##### BEGINFILE \"";
- const char *pcszEndMarker = "\n// ##### ENDFILE";
- const size_t cbBeginMarker = strlen(pcszBeginMarker);
- FILE *pFileIn = NULL;
- char *pBuffer = NULL;
-
- do {
- if (argc != 3)
- {
- fprintf(stderr, "filesplitter: Must be started with exactly two arguments,\n"
- "1) the input file and 2) the directory where to put the output files\n");
- rc = 2;
- break;
- }
-
- struct stat lStat;
- if ( stat(argv[2], &lStat) != 0
- || (lStat.st_mode & S_IFMT) != S_IFDIR)
- {
- fprintf(stderr, "filesplitter: Given argument \"%s\" is not a valid directory.\n", argv[2]);
- rc = 2;
- break;
- }
-
- if ( stat(argv[1], &lStat)
- || !(pFileIn = fopen(argv[1], "r")))
- {
- fprintf(stderr, "filesplitter: Cannot open file \"%s\" for reading.\n", argv[1]);
- rc = 2;
- break;
- }
-
- if (!(pBuffer = (char*)malloc(lStat.st_size + 1)))
- {
- fprintf(stderr, "filesplitter: Failed to allocate %ld bytes.\n", (long)lStat.st_size);
- rc = 2;
- break;
- }
-
- if (fread(pBuffer, 1, lStat.st_size, pFileIn) != lStat.st_size)
- {
- fprintf(stderr, "filesplitter: Failed to read %ld bytes from input file.\n", (long)lStat.st_size);
- rc = 2;
- break;
- }
- pBuffer[lStat.st_size] = '\0';
-
- const char *pSearch = pBuffer;
- unsigned long cFiles = 0;
- size_t cbDirName = strlen(argv[2]);
-
- do
- {
- /* find begin marker */
- const char *pBegin = strstr(pSearch, pcszBeginMarker);
- if (!pBegin)
- break;
-
- /* find line after begin marker */
- const char *pLineAfterBegin = strchr(pBegin + cbBeginMarker, '\n');
- if (!pLineAfterBegin)
- {
- fprintf(stderr, "filesplitter: No newline after begin-file marker found.\n");
- rc = 2;
- break;
- }
- ++pLineAfterBegin;
-
- /* find second quote in begin marker line */
- const char *pSecondQuote = strchr(pBegin + cbBeginMarker, '\"');
- if ( !pSecondQuote
- || pSecondQuote >= pLineAfterBegin)
- {
- fprintf(stderr, "filesplitter: Can't parse filename after begin-file marker (line %lu).\n", lineNumber(pBuffer, pcszBeginMarker));
- rc = 2;
- break;
- }
-
- /* find end marker */
- const char *pEnd = strstr(pLineAfterBegin, pcszEndMarker);
- if (!pEnd)
- {
- fprintf(stderr, "filesplitter: No matching end-line marker for begin-file marker found (line %lu).\n", lineNumber(pBuffer, pcszBeginMarker));
- rc = 2;
- break;
- }
-
- /* construct output filename */
- char *pszFilename;
- size_t cbFilename;
- cbFilename = pSecondQuote - (pBegin + cbBeginMarker);
- if (!(pszFilename = (char*)malloc(cbDirName + 1 + cbFilename + 1)))
- {
- fprintf(stderr, "filesplitter: Can't allocate memory for filename.\n");
- rc = 2;
- break;
- }
- memcpy(pszFilename, argv[2], cbDirName);
- pszFilename[cbDirName] = '/';
- memcpy(pszFilename + cbDirName + 1, pBegin + cbBeginMarker, cbFilename);
- pszFilename[cbFilename + 1 + cbDirName] = '\0';
-
- /* create output file and write file contents */
- FILE *pFileOut;
- if (!(pFileOut = fopen(pszFilename, "w")))
- {
- fprintf(stderr, "filesplitter: Failed to open file \"%s\" for writing\n", pszFilename);
- rc = 2;
- }
- else
- {
- size_t cbFile = pEnd - pLineAfterBegin;
- if (fwrite(pLineAfterBegin, 1, cbFile, pFileOut) != cbFile)
- {
- fprintf(stderr, "filesplitter: Failed to write %ld bytes to file \"%s\"\n", (long)cbFile, pszFilename);
- rc = 2;
- }
-
- fclose(pFileOut);
-
- if (!rc)
- {
- ++cFiles;
- pSearch = strchr(pEnd, '\n');
- }
- }
-
- free(pszFilename);
-
- if (rc)
- break;
-
- } while (pSearch);
-
- printf("filesplitter: Created %lu files.\n", cFiles);
- } while (0);
-
- if (pBuffer)
- free(pBuffer);
- if (pFileIn)
- fclose(pFileIn);
-
- return rc;
-}
diff --git a/src/VBox/Main/webservice/glue-jaxws.xsl b/src/VBox/Main/webservice/glue-jaxws.xsl
index 61cb412a1..ae871b60f 100644
--- a/src/VBox/Main/webservice/glue-jaxws.xsl
+++ b/src/VBox/Main/webservice/glue-jaxws.xsl
@@ -50,7 +50,7 @@
<xsl:template name="fileheader">
<xsl:param name="name" />
<xsl:text>/**
- * Copyright (C) 2008-2009 Sun Microsystems, Inc.
+ * Copyright (C) 2008-2010 Oracle Corporation
*
* This file is part of a free software library; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General
@@ -59,19 +59,15 @@
* The library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY of any kind.
*
- * Sun LGPL Disclaimer: For the avoidance of doubt, except that if
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if
* any license choice other than GPL or LGPL is available it will
- * apply instead, Sun elects to use only the Lesser General Public
+ * apply instead, Oracle elects to use only the Lesser General Public
* License version 2.1 (LGPLv2) at this time for any software where
* a choice of LGPL license versions is made available with the
* language indicating that LGPLv2 or any later version may be used,
* or where a choice of which version of the LGPL is applied is
* otherwise unspecified.
*
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
- * Clara, CA 95054 USA or visit http://www.sun.com if you need
- * additional information or have any questions.
- *
</xsl:text>
<xsl:value-of select="concat(' * ',$name)"/>
<xsl:text>
@@ -957,7 +953,7 @@ public class IWebsessionManager {
<xsl:call-template name="fatalError">
<xsl:with-param name="msg" select="concat('Interface generation: interface &quot;', $ifname, '&quot; has invalid &quot;extends&quot; value ', $extends, '.')" />
</xsl:call-template>
- </xsl:otherwise>>
+ </xsl:otherwise>
</xsl:choose>
<!-- interface (class) constructor -->
diff --git a/src/VBox/Main/webservice/vboxweb.cpp b/src/VBox/Main/webservice/vboxweb.cpp
index fab1a440b..57fc3c042 100644
--- a/src/VBox/Main/webservice/vboxweb.cpp
+++ b/src/VBox/Main/webservice/vboxweb.cpp
@@ -1471,6 +1471,8 @@ int __vbox__IManagedObjectRef_USCOREgetInterfaceName(
WEBDEBUG(("\n-- entering %s\n", __FUNCTION__));
do {
+ util::AutoReadLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
+
ManagedObjectRef *pRef;
if (!ManagedObjectRef::findRefFromId(req->_USCOREthis, &pRef, false))
resp->returnval = pRef->getInterfaceName();
@@ -1502,6 +1504,8 @@ int __vbox__IManagedObjectRef_USCORErelease(
WEBDEBUG(("\n-- entering %s\n", __FUNCTION__));
do {
+ util::AutoReadLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
+
ManagedObjectRef *pRef;
if ((rc = ManagedObjectRef::findRefFromId(req->_USCOREthis, &pRef, false)))
{
@@ -1555,10 +1559,6 @@ int __vbox__IManagedObjectRef_USCORErelease(
* a much better solution, both for performance and cleanliness, for the webservice
* client to clean up itself.
*
- * Preconditions: Caller must have locked g_mutexSessions.
- * Since this gets called from main() like other SOAP method
- * implementations, this is ensured.
- *
* @param
* @param vbox__IWebsessionManager_USCORElogon
* @param vbox__IWebsessionManager_USCORElogonResponse
@@ -1584,8 +1584,8 @@ int __vbox__IWebsessionManager_USCORElogon(
if (!(pSession->authenticate(req->username.c_str(),
req->password.c_str())))
{
- // in the new session, create a managed object reference (moref) for the
- // global VirtualBox object; this encodes the session ID in the moref so
+ // in the new session, create a managed object reference (MOR) for the
+ // global VirtualBox object; this encodes the session ID in the MOR so
// that it will be implicitly be included in all future requests of this
// webservice client
ManagedObjectRef *pRef = new ManagedObjectRef(*pSession, g_pcszIVirtualBox, g_pVirtualBox);
@@ -1603,10 +1603,6 @@ int __vbox__IWebsessionManager_USCORElogon(
/**
* Returns the ISession object that was created for the webservice client
* on logon.
- *
- * Preconditions: Caller must have locked g_mutexSessions.
- * Since this gets called from main() like other SOAP method
- * implementations, this is ensured.
*/
int __vbox__IWebsessionManager_USCOREgetSessionObject(
struct soap*,
@@ -1617,6 +1613,9 @@ int __vbox__IWebsessionManager_USCOREgetSessionObject(
WEBDEBUG(("\n-- entering %s\n", __FUNCTION__));
do {
+ // findSessionFromRef needs read lock
+ util::AutoReadLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
+
WebServiceSession* pSession;
if ((pSession = WebServiceSession::findSessionFromRef(req->refIVirtualBox)))
{
@@ -1633,10 +1632,6 @@ int __vbox__IWebsessionManager_USCOREgetSessionObject(
/**
* hard-coded implementation for IWebsessionManager::logoff.
*
- * Preconditions: Caller must have locked g_mutexSessions.
- * Since this gets called from main() like other SOAP method
- * implementations, this is ensured.
- *
* @param
* @param vbox__IWebsessionManager_USCORElogon
* @param vbox__IWebsessionManager_USCORElogonResponse
diff --git a/src/VBox/Main/webservice/websrv-php.xsl b/src/VBox/Main/webservice/websrv-php.xsl
index 1dd6595d2..147ae0b7d 100644
--- a/src/VBox/Main/webservice/websrv-php.xsl
+++ b/src/VBox/Main/webservice/websrv-php.xsl
@@ -348,22 +348,26 @@ class <xsl:value-of select="$ifname"/>Collection extends VBox_EnumCollection {
<xsl:text>&lt;?php
/*
-* Copyright (C) 2009 Sun Microsystems, Inc.
-*
-* This file is part of VirtualBox Open Source Edition (OSE), as
-* available from http://www.virtualbox.org. This file is free software;
-* you can redistribute it and/or modify it under the terms of the GNU
-* General Public License (GPL) as published by the Free Software
-* Foundation, in version 2 as it comes in the "COPYING" file of the
-* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-*
-* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
-* Clara, CA 95054 USA or visit http://www.sun.com if you need
-* additional information or have any questions.
-*
-* This file is autogenerated from VirtualBox.xidl, DO NOT EDIT!
-*/
+ * Copyright (C) 2008-2010 Oracle Corporation
+ *
+ * This file is part of a free software library; you can redistribute
+ * it and/or modify it under the terms of the GNU Lesser General
+ * Public License version 2.1 as published by the Free Software
+ * Foundation and shipped in the "COPYING.LIB" file with this library.
+ * The library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY of any kind.
+ *
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if
+ * any license choice other than GPL or LGPL is available it will
+ * apply instead, Oracle elects to use only the Lesser General Public
+ * License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the
+ * language indicating that LGPLv2 or any later version may be used,
+ * or where a choice of which version of the LGPL is applied is
+ * otherwise unspecified.
+ *
+ * This file is autogenerated from VirtualBox.xidl, DO NOT EDIT!
+ */
class VBox_ManagedObject
{
diff --git a/src/VBox/Main/webservice/websrv-python.xsl b/src/VBox/Main/webservice/websrv-python.xsl
index aaaa30302..9accb148f 100644
--- a/src/VBox/Main/webservice/websrv-python.xsl
+++ b/src/VBox/Main/webservice/websrv-python.xsl
@@ -442,19 +442,23 @@ class <xsl:value-of select="@name"/>:
</xsl:template>
<xsl:template match="/">
-<xsl:text># Copyright (C) 2008-2009 Sun Microsystems, Inc.
+<xsl:text># Copyright (C) 2008-2010 Oracle Corporation
#
-# This file is part of VirtualBox Open Source Edition (OSE), as
-# available from http://www.virtualbox.org. This file is free software;
-# you can redistribute it and/or modify it under the terms of the GNU
-# General Public License (GPL) as published by the Free Software
-# Foundation, in version 2 as it comes in the "COPYING" file of the
-# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+# This file is part of a free software library; you can redistribute
+# it and/or modify it under the terms of the GNU Lesser General
+# Public License version 2.1 as published by the Free Software
+# Foundation and shipped in the "COPYING.LIB" file with this library.
+# The library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY of any kind.
#
-# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
-# Clara, CA 95054 USA or visit http://www.sun.com if you need
-# additional information or have any questions.
+# Oracle LGPL Disclaimer: For the avoidance of doubt, except that if
+# any license choice other than GPL or LGPL is available it will
+# apply instead, Oracle elects to use only the Lesser General Public
+# License version 2.1 (LGPLv2) at this time for any software where
+# a choice of LGPL license versions is made available with the
+# language indicating that LGPLv2 or any later version may be used,
+# or where a choice of which version of the LGPL is applied is
+# otherwise unspecified.
#
# This file is autogenerated from VirtualBox.xidl, DO NOT EDIT!
#
diff --git a/src/VBox/Main/webservice/webtest.cpp b/src/VBox/Main/webservice/webtest.cpp
index 65c1a4822..e28d95063 100644
--- a/src/VBox/Main/webservice/webtest.cpp
+++ b/src/VBox/Main/webservice/webtest.cpp
@@ -48,6 +48,7 @@ int main(int argc, char* argv[])
" - IVirtualBox:\n"
" - webtest version <vboxref>: IVirtualBox::getVersion().\n"
" - webtest gethost <vboxref>: IVirtualBox::getHost().\n"
+ " - webtest getpc <vboxref>: IVirtualBox::getPerformanceCollector().\n"
" - webtest getmachines <vboxref>: IVirtualBox::getMachines().\n"
" - webtest createmachine <vboxref> <baseFolder> <name>: IVirtualBox::createMachine().\n"
" - webtest registermachine <vboxref> <machineref>: IVirtualBox::registerMachine().\n"
@@ -60,6 +61,9 @@ int main(int argc, char* argv[])
" - webtest getid <machineref>: IMachine::getId().\n"
" - webtest getostype <machineref>: IMachine::getGuestOSType().\n"
" - webtest savesettings <machineref>: IMachine::saveSettings().\n"
+ " - IPerformanceCollector:\n"
+ " - webtest setupmetrics <pcref>: IPerformanceCollector::setupMetrics()\n"
+ " - webtest querymetricsdata <pcref>: IPerformanceCollector::QueryMetricsData()\n"
" - All managed object references:\n"
" - webtest getif <ref>: report interface of object.\n"
" - webtest release <ref>: IUnknown::Release().\n";
@@ -166,6 +170,26 @@ int main(int argc, char* argv[])
}
}
}
+ else if (!strcmp(pcszMode, "getpc"))
+ {
+ if (argc < 3)
+ std::cout << "Not enough arguments for \"" << pcszMode << "\" mode.\n";
+ else
+ {
+ _vbox__IVirtualBox_USCOREgetPerformanceCollector req;
+ req._USCOREthis = argv[2];
+ _vbox__IVirtualBox_USCOREgetPerformanceCollectorResponse resp;
+
+ if (!(soaprc = soap_call___vbox__IVirtualBox_USCOREgetPerformanceCollector(&soap,
+ pcszArgEndpoint,
+ NULL,
+ &req,
+ &resp)))
+ {
+ std::cout << "Performance collector objref " << resp.returnval << "\n";
+ }
+ }
+ }
else if (!strcmp(pcszMode, "getmachines"))
{
if (argc < 3)
@@ -324,6 +348,62 @@ int main(int argc, char* argv[])
std::cout << "Settings saved\n";
}
}
+ else if (!strcmp(pcszMode, "setupmetrics"))
+ {
+ if (argc < 3)
+ std::cout << "Not enough arguments for \"" << pcszMode << "\" mode.\n";
+ else
+ {
+ _vbox__IPerformanceCollector_USCOREsetupMetrics req;
+ req._USCOREthis = argv[2];
+// req.metricNames[0] = "*";
+// req.objects
+ req.period = 1; // seconds
+ req.count = 100;
+ _vbox__IPerformanceCollector_USCOREsetupMetricsResponse resp;
+ if (!(soaprc = soap_call___vbox__IPerformanceCollector_USCOREsetupMetrics(&soap,
+ pcszArgEndpoint,
+ NULL,
+ &req,
+ &resp)))
+ {
+ size_t c = resp.returnval.size();
+ for (size_t i = 0;
+ i < c;
+ ++i)
+ {
+ std::cout << "Metric " << i << ": objref " << resp.returnval[i] << "\n";
+ }
+ }
+ }
+ }
+ else if (!strcmp(pcszMode, "querymetricsdata"))
+ {
+ if (argc < 3)
+ std::cout << "Not enough arguments for \"" << pcszMode << "\" mode.\n";
+ else
+ {
+ _vbox__IPerformanceCollector_USCOREqueryMetricsData req;
+ req._USCOREthis = argv[2];
+// req.metricNames[0] = "*";
+// req.objects
+ _vbox__IPerformanceCollector_USCOREqueryMetricsDataResponse resp;
+ if (!(soaprc = soap_call___vbox__IPerformanceCollector_USCOREqueryMetricsData(&soap,
+ pcszArgEndpoint,
+ NULL,
+ &req,
+ &resp)))
+ {
+ size_t c = resp.returnval.size();
+ for (size_t i = 0;
+ i < c;
+ ++i)
+ {
+ std::cout << "long " << i << ": " << resp.returnval[i] << "\n";
+ }
+ }
+ }
+ }
else if (!strcmp(pcszMode, "release"))
{
if (argc < 3)
diff --git a/src/VBox/Main/xml/Settings.cpp b/src/VBox/Main/xml/Settings.cpp
index 7ff36f93d..9027e5dac 100644
--- a/src/VBox/Main/xml/Settings.cpp
+++ b/src/VBox/Main/xml/Settings.cpp
@@ -1,4 +1,4 @@
-/* $Id: Settings.cpp 29593 2010-05-18 07:23:46Z vboxsync $ */
+/* $Id: Settings.cpp 29873 2010-05-28 17:14:53Z vboxsync $ */
/** @file
* Settings File Manipulation API.
*
@@ -429,19 +429,6 @@ com::Utf8Str ConfigFileBase::makeString(const RTTIMESPEC &stamp)
}
/**
- * Helper to create a string for a GUID.
- * @param guid
- * @return
- */
-com::Utf8Str ConfigFileBase::makeString(const Guid &guid)
-{
- Utf8Str str("{");
- str.append(guid.toString());
- str.append("}");
- return str;
-}
-
-/**
* Helper method to read in an ExtraData subtree and stores its contents
* in the given map of extradata items. Used for both main and machine
* extradata (MainConfigFile and MachineConfigFile).
@@ -1161,7 +1148,7 @@ void MainConfigFile::writeHardDisk(xml::ElementNode &elmMedium,
uint32_t level) // 0 for "root" call, incremented with each recursion
{
xml::ElementNode *pelmHardDisk = elmMedium.createChild("HardDisk");
- pelmHardDisk->setAttribute("uuid", makeString(mdm.uuid));
+ pelmHardDisk->setAttribute("uuid", mdm.uuid.toStringCurly());
pelmHardDisk->setAttribute("location", mdm.strLocation);
pelmHardDisk->setAttribute("format", mdm.strFormat);
if (mdm.fAutoReset)
@@ -1221,7 +1208,7 @@ void MainConfigFile::write(const com::Utf8Str strFilename)
// <MachineEntry uuid="{5f102a55-a51b-48e3-b45a-b28d33469488}" src="/mnt/innotek-unix/vbox-machines/Windows 5.1 XP 1 (Office 2003)/Windows 5.1 XP 1 (Office 2003).xml"/>
const MachineRegistryEntry &mre = *it;
xml::ElementNode *pelmMachineEntry = pelmMachineRegistry->createChild("MachineEntry");
- pelmMachineEntry->setAttribute("uuid", makeString(mre.uuid));
+ pelmMachineEntry->setAttribute("uuid", mre.uuid.toStringCurly());
pelmMachineEntry->setAttribute("src", mre.strSettingsFile);
}
@@ -1242,7 +1229,7 @@ void MainConfigFile::write(const com::Utf8Str strFilename)
{
const Medium &mdm = *it;
xml::ElementNode *pelmMedium = pelmDVDImages->createChild("Image");
- pelmMedium->setAttribute("uuid", makeString(mdm.uuid));
+ pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
pelmMedium->setAttribute("location", mdm.strLocation);
if (mdm.strDescription.length())
pelmMedium->setAttribute("Description", mdm.strDescription);
@@ -1255,7 +1242,7 @@ void MainConfigFile::write(const com::Utf8Str strFilename)
{
const Medium &mdm = *it;
xml::ElementNode *pelmMedium = pelmFloppyImages->createChild("Image");
- pelmMedium->setAttribute("uuid", makeString(mdm.uuid));
+ pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
pelmMedium->setAttribute("location", mdm.strLocation);
if (mdm.strDescription.length())
pelmMedium->setAttribute("Description", mdm.strDescription);
@@ -3062,7 +3049,7 @@ void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
if ( (m->sv >= SettingsVersion_v1_9)
&& (!hw.uuid.isEmpty())
)
- pelmHardware->setAttribute("uuid", makeString(hw.uuid));
+ pelmHardware->setAttribute("uuid", hw.uuid.toStringCurly());
xml::ElementNode *pelmCPU = pelmHardware->createChild("CPU");
@@ -3296,7 +3283,7 @@ void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
pelmDVD->setAttribute("passthrough", att.fPassThrough);
if (!att.uuid.isEmpty())
- pelmDVD->createChild("Image")->setAttribute("uuid", makeString(att.uuid));
+ pelmDVD->createChild("Image")->setAttribute("uuid", att.uuid.toStringCurly());
else if (att.strHostDriveSrc.length())
pelmDVD->createChild("HostDrive")->setAttribute("src", att.strHostDriveSrc);
}
@@ -3312,7 +3299,7 @@ void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
const AttachedDevice &att = sctl.llAttachedDevices.front();
pelmFloppy->setAttribute("enabled", true);
if (!att.uuid.isEmpty())
- pelmFloppy->createChild("Image")->setAttribute("uuid", makeString(att.uuid));
+ pelmFloppy->createChild("Image")->setAttribute("uuid", att.uuid.toStringCurly());
else if (att.strHostDriveSrc.length())
pelmFloppy->createChild("HostDrive")->setAttribute("src", att.strHostDriveSrc);
}
@@ -3652,10 +3639,15 @@ void MachineConfigFile::buildNetworkXML(NetworkAttachmentType_T mode,
* an empty drive is always written instead. This is for the OVF export case.
* This parameter is ignored unless the settings version is at least v1.9, which
* is always the case when this gets called for OVF export.
+ * @param pllElementsWithUuidAttributes If not NULL, must point to a list of element node
+ * pointers to which we will append all allements that we created here that contain
+ * UUID attributes. This allows the OVF export code to quickly replace the internal
+ * media UUIDs with the UUIDs of the media that were exported.
*/
void MachineConfigFile::buildStorageControllersXML(xml::ElementNode &elmParent,
const Storage &st,
- bool fSkipRemovableMedia)
+ bool fSkipRemovableMedia,
+ std::list<xml::ElementNode*> *pllElementsWithUuidAttributes)
{
xml::ElementNode *pelmStorageControllers = elmParent.createChild("StorageControllers");
@@ -3758,12 +3750,20 @@ void MachineConfigFile::buildStorageControllersXML(xml::ElementNode &elmParent,
pelmDevice->setAttribute("port", att.lPort);
pelmDevice->setAttribute("device", att.lDevice);
+ // attached image, if any
if ( !att.uuid.isEmpty()
&& ( att.deviceType == DeviceType_HardDisk
|| !fSkipRemovableMedia
)
)
- pelmDevice->createChild("Image")->setAttribute("uuid", makeString(att.uuid));
+ {
+ xml::ElementNode *pelmImage = pelmDevice->createChild("Image");
+ pelmImage->setAttribute("uuid", att.uuid.toStringCurly());
+
+ // if caller wants a list of UUID elements, give it to them
+ if (pllElementsWithUuidAttributes)
+ pllElementsWithUuidAttributes->push_back(pelmImage);
+ }
else if ( (m->sv >= SettingsVersion_v1_9)
&& (att.strHostDriveSrc.length())
)
@@ -3784,7 +3784,7 @@ void MachineConfigFile::buildSnapshotXML(xml::ElementNode &elmParent,
{
xml::ElementNode *pelmSnapshot = elmParent.createChild("Snapshot");
- pelmSnapshot->setAttribute("uuid", makeString(snap.uuid));
+ pelmSnapshot->setAttribute("uuid", snap.uuid.toStringCurly());
pelmSnapshot->setAttribute("name", snap.strName);
pelmSnapshot->setAttribute("timeStamp", makeString(snap.timestamp));
@@ -3797,7 +3797,8 @@ void MachineConfigFile::buildSnapshotXML(xml::ElementNode &elmParent,
buildHardwareXML(*pelmSnapshot, snap.hardware, snap.storage);
buildStorageControllersXML(*pelmSnapshot,
snap.storage,
- false /* fSkipRemovableMedia */);
+ false /* fSkipRemovableMedia */,
+ NULL); /* pllElementsWithUuidAttributes */
// we only skip removable media for OVF, but we never get here for OVF
// since snapshots never get written then
@@ -3845,15 +3846,18 @@ void MachineConfigFile::buildSnapshotXML(xml::ElementNode &elmParent,
*
* @param elmMachine XML <Machine> element to add attributes and elements to.
* @param fl Flags.
+ * @param pllElementsWithUuidAttributes pointer to list that should receive UUID elements or NULL;
+ * see buildStorageControllersXML() for details.
*/
void MachineConfigFile::buildMachineXML(xml::ElementNode &elmMachine,
- uint32_t fl)
+ uint32_t fl,
+ std::list<xml::ElementNode*> *pllElementsWithUuidAttributes)
{
if (fl & BuildMachineXML_WriteVboxVersionAttribute)
// add settings version attribute to machine element
setVersionAttribute(elmMachine);
- elmMachine.setAttribute("uuid", makeString(uuid));
+ elmMachine.setAttribute("uuid", uuid.toStringCurly());
elmMachine.setAttribute("name", strName);
if (!fNameSync)
elmMachine.setAttribute("nameSync", fNameSync);
@@ -3864,7 +3868,7 @@ void MachineConfigFile::buildMachineXML(xml::ElementNode &elmMachine,
elmMachine.setAttribute("stateFile", strStateFile);
if ( (fl & BuildMachineXML_IncludeSnapshots)
&& !uuidCurrentSnapshot.isEmpty())
- elmMachine.setAttribute("currentSnapshot", makeString(uuidCurrentSnapshot));
+ elmMachine.setAttribute("currentSnapshot", uuidCurrentSnapshot.toStringCurly());
if (strSnapshotFolder.length())
elmMachine.setAttribute("snapshotFolder", strSnapshotFolder);
if (!fCurrentStateModified)
@@ -3896,7 +3900,8 @@ void MachineConfigFile::buildMachineXML(xml::ElementNode &elmMachine,
buildHardwareXML(elmMachine, hardwareMachine, storageMachine);
buildStorageControllersXML(elmMachine,
storageMachine,
- !!(fl & BuildMachineXML_SkipRemovableMedia));
+ !!(fl & BuildMachineXML_SkipRemovableMedia),
+ pllElementsWithUuidAttributes);
}
/**
@@ -4084,8 +4089,9 @@ void MachineConfigFile::write(const com::Utf8Str &strFilename)
xml::ElementNode *pelmMachine = m->pelmRoot->createChild("Machine");
buildMachineXML(*pelmMachine,
- MachineConfigFile::BuildMachineXML_IncludeSnapshots);
+ MachineConfigFile::BuildMachineXML_IncludeSnapshots,
// but not BuildMachineXML_WriteVboxVersionAttribute
+ NULL); /* pllElementsWithUuidAttributes */
// now go write the XML
xml::XmlFileWriter writer(*m->pDoc);
diff --git a/src/VBox/Main/xml/ovfreader.cpp b/src/VBox/Main/xml/ovfreader.cpp
index 4be482683..18e3dba82 100644
--- a/src/VBox/Main/xml/ovfreader.cpp
+++ b/src/VBox/Main/xml/ovfreader.cpp
@@ -1,4 +1,4 @@
-/* $Id: ovfreader.cpp 29422 2010-05-12 14:08:52Z vboxsync $ */
+/* $Id: ovfreader.cpp 29893 2010-05-31 10:37:17Z vboxsync $ */
/** @file
*
* OVF reader declarations. Depends only on IPRT, including the iprt::MiniString
@@ -85,7 +85,9 @@ void OVFReader::LoopThruSections(const xml::ElementNode *pReferencesElem,
const char *pcszElemName = pElem->getName();
const char *pcszTypeAttr = "";
const xml::AttributeNode *pTypeAttr;
- if ((pTypeAttr = pElem->findAttribute("type")))
+ if ( ((pTypeAttr = pElem->findAttribute("xsi:type")))
+ || ((pTypeAttr = pElem->findAttribute("type")))
+ )
pcszTypeAttr = pTypeAttr->getValue();
if ( (!strcmp(pcszElemName, "DiskSection"))
@@ -96,7 +98,7 @@ void OVFReader::LoopThruSections(const xml::ElementNode *pReferencesElem,
{
HandleDiskSection(pReferencesElem, pElem);
}
- else if ( (!strcmp(pcszElemName, "NetworkSection"))
+ else if ( (!strcmp(pcszElemName, "NetworkSection"))
|| ( (!strcmp(pcszElemName, "Section"))
&& (!strcmp(pcszTypeAttr, "ovf:NetworkSection_Type"))
)
@@ -294,8 +296,19 @@ void OVFReader::HandleVirtualSystemContent(const xml::ElementNode *pelmVirtualSy
while ((pelmThis = loop.forAllNodes()))
{
const char *pcszElemName = pelmThis->getName();
- const xml::AttributeNode *pTypeAttr = pelmThis->findAttribute("type");
- const char *pcszTypeAttr = (pTypeAttr) ? pTypeAttr->getValue() : "";
+ const char *pcszTypeAttr = "";
+ if (!strcmp(pcszElemName, "Section")) // OVF 0.9 used "Section" element always with a varying "type" attribute
+ {
+ const xml::AttributeNode *pTypeAttr;
+ if ( ((pTypeAttr = pelmThis->findAttribute("type")))
+ || ((pTypeAttr = pelmThis->findAttribute("xsi:type")))
+ )
+ pcszTypeAttr = pTypeAttr->getValue();
+ else
+ throw OVFLogicError(N_("Error reading \"%s\": element \"Section\" has no \"type\" attribute, line %d"),
+ m_strPath.c_str(),
+ pelmThis->getLineNumber());
+ }
if ( (!strcmp(pcszElemName, "EulaSection"))
|| (!strcmp(pcszTypeAttr, "ovf:EulaSection_Type"))
diff --git a/src/VBox/Main/xpcom/server.cpp b/src/VBox/Main/xpcom/server.cpp
index 2372e3a80..5c5e3c194 100644
--- a/src/VBox/Main/xpcom/server.cpp
+++ b/src/VBox/Main/xpcom/server.cpp
@@ -1,4 +1,4 @@
-/* $Id: server.cpp 29385 2010-05-11 18:05:44Z vboxsync $ */
+/* $Id: server.cpp 29864 2010-05-28 13:34:53Z vboxsync $ */
/** @file
* XPCOM server process (VBoxSVC) start point.
*/
@@ -66,6 +66,7 @@
#include <MediumImpl.h>
#include <MediumFormatImpl.h>
#include <ProgressCombinedImpl.h>
+#include <ProgressProxyImpl.h>
#include <VRDPServerImpl.h>
#include <SharedFolderImpl.h>
#include <HostImpl.h>
@@ -127,6 +128,9 @@ NS_IMPL_THREADSAFE_ISUPPORTS1_CI(Progress, IProgress)
NS_DECL_CLASSINFO(CombinedProgress)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(CombinedProgress, IProgress)
+NS_DECL_CLASSINFO(ProgressProxy)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(ProgressProxy, IProgress)
+
NS_DECL_CLASSINFO(SharedFolder)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(SharedFolder, ISharedFolder)