diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Main/include | |
parent | Initial commit. (diff) | |
download | virtualbox-upstream.tar.xz virtualbox-upstream.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Main/include')
149 files changed, 33827 insertions, 0 deletions
diff --git a/src/VBox/Main/include/AdditionsFacilityImpl.h b/src/VBox/Main/include/AdditionsFacilityImpl.h new file mode 100644 index 00000000..c5e0c021 --- /dev/null +++ b/src/VBox/Main/include/AdditionsFacilityImpl.h @@ -0,0 +1,110 @@ +/* $Id: AdditionsFacilityImpl.h $ */ +/** @file + * VirtualBox Main - Additions facility class. + */ + +/* + * Copyright (C) 2014-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_AdditionsFacilityImpl_h +#define MAIN_INCLUDED_AdditionsFacilityImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/time.h> +#include "AdditionsFacilityWrap.h" + +class Guest; + +/** + * A Guest Additions facility. + */ +class ATL_NO_VTABLE AdditionsFacility : + public AdditionsFacilityWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(AdditionsFacility) + + /** @name Initializer & uninitializer methods + * @{ */ + HRESULT init(Guest *a_pParent, AdditionsFacilityType_T a_enmFacility, AdditionsFacilityStatus_T a_enmStatus, + uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS); + void uninit(); + HRESULT FinalConstruct(); + void FinalRelease(); + /** @} */ + +public: + /** @name public internal methods + * @{ */ + LONG64 i_getLastUpdated() const; +#if 0 /* unused */ + AdditionsFacilityType_T i_getType() const; + AdditionsFacilityClass_T i_getClass() const; + const char *i_getName() const; +#endif + AdditionsFacilityStatus_T i_getStatus() const; + bool i_update(AdditionsFacilityStatus_T a_enmStatus, uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS); + /** @} */ + +private: + + /** @name Wrapped IAdditionsFacility properties + * @{ */ + HRESULT getClassType(AdditionsFacilityClass_T *aClassType); + HRESULT getLastUpdated(LONG64 *aLastUpdated); + HRESULT getName(com::Utf8Str &aName); + HRESULT getStatus(AdditionsFacilityStatus_T *aStatus); + HRESULT getType(AdditionsFacilityType_T *aType); + /** @} */ + + struct Data + { + /** Last update timestamp. */ + RTTIMESPEC mTimestamp; + /** The facilitie's current status. */ + AdditionsFacilityStatus_T mStatus; + /** Flags. */ + uint32_t mfFlags; + /** The facilitie's ID/type (static). */ + AdditionsFacilityType_T mType; + /** Index into s_aFacilityInfo. */ + size_t midxInfo; + } mData; + + /** Facility <-> string mappings. */ + struct FacilityInfo + { + /** The facilitie's name. */ + const char *mName; /* utf-8 */ + /** The facilitie's type. */ + AdditionsFacilityType_T mType; + /** The facilitie's class. */ + AdditionsFacilityClass_T mClass; + }; + static const FacilityInfo s_aFacilityInfo[8]; +}; + +#endif /* !MAIN_INCLUDED_AdditionsFacilityImpl_h */ + diff --git a/src/VBox/Main/include/ApplianceImpl.h b/src/VBox/Main/include/ApplianceImpl.h new file mode 100644 index 00000000..9c4884cd --- /dev/null +++ b/src/VBox/Main/include/ApplianceImpl.h @@ -0,0 +1,367 @@ +/* $Id: ApplianceImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ApplianceImpl_h +#define MAIN_INCLUDED_ApplianceImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* VBox includes */ +#include "VirtualSystemDescriptionWrap.h" +#include "ApplianceWrap.h" +#include "MediumFormatImpl.h" + +/** @todo This file needs massive cleanup. Split IAppliance in a public and + * private classes. */ +#include <iprt/tar.h> +#include "ovfreader.h" +#include <set> + +/* VBox forward declarations */ +class Certificate; +class Progress; +class VirtualSystemDescription; +struct VirtualSystemDescriptionEntry; +struct LocationInfo; +typedef struct VDINTERFACE *PVDINTERFACE; +typedef struct VDINTERFACEIO *PVDINTERFACEIO; +typedef struct SHASTORAGE *PSHASTORAGE; + +namespace ovf +{ + struct HardDiskController; + struct VirtualSystem; + class OVFReader; + struct DiskImage; + struct EnvelopeData; +} + +namespace xml +{ + class Document; + class ElementNode; +} + +namespace settings +{ + class MachineConfigFile; +} + +class ATL_NO_VTABLE Appliance : + public ApplianceWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(Appliance) + + HRESULT FinalConstruct(); + void FinalRelease(); + + + HRESULT init(VirtualBox *aVirtualBox); + void uninit(); + + /* public methods only for internal purposes */ + + static HRESULT i_setErrorStatic(HRESULT aResultCode, const char *aText, ...) + { + va_list va; + va_start(va, aText); + HRESULT hrc = setErrorInternalV(aResultCode, getStaticClassIID(), getStaticComponentName(), aText, va, false, true); + va_end(va); + return hrc; + } + + /* private instance data */ +private: + // wrapped IAppliance properties + HRESULT getPath(com::Utf8Str &aPath); + HRESULT getDisks(std::vector<com::Utf8Str> &aDisks); + HRESULT getCertificate(ComPtr<ICertificate> &aCertificateInfo); + HRESULT getVirtualSystemDescriptions(std::vector<ComPtr<IVirtualSystemDescription> > &aVirtualSystemDescriptions); + HRESULT getMachines(std::vector<com::Utf8Str> &aMachines); + + // wrapped IAppliance methods + HRESULT read(const com::Utf8Str &aFile, + ComPtr<IProgress> &aProgress); + HRESULT interpret(); + HRESULT importMachines(const std::vector<ImportOptions_T> &aOptions, + ComPtr<IProgress> &aProgress); + HRESULT createVFSExplorer(const com::Utf8Str &aURI, + ComPtr<IVFSExplorer> &aExplorer); + HRESULT write(const com::Utf8Str &aFormat, + const std::vector<ExportOptions_T> &aOptions, + const com::Utf8Str &aPath, + ComPtr<IProgress> &aProgress); + HRESULT getWarnings(std::vector<com::Utf8Str> &aWarnings); + HRESULT getPasswordIds(std::vector<com::Utf8Str> &aIdentifiers); + HRESULT getMediumIdsForPasswordId(const com::Utf8Str &aPasswordId, std::vector<com::Guid> &aIdentifiers); + HRESULT addPasswords(const std::vector<com::Utf8Str> &aIdentifiers, + const std::vector<com::Utf8Str> &aPasswords); + HRESULT createVirtualSystemDescriptions(ULONG aRequested, ULONG *aCreated); + /** weak VirtualBox parent */ + VirtualBox* const mVirtualBox; + + struct ImportStack; + class TaskOVF; + class TaskOPC; + class TaskCloud; + + struct Data; // opaque, defined in ApplianceImpl.cpp + Data *m; + + enum SetUpProgressMode { ImportFile, ImportS3, WriteFile, WriteS3, ExportCloud, ImportCloud }; + + enum ApplianceState { ApplianceIdle, ApplianceImporting, ApplianceExporting }; + void i_setApplianceState(const ApplianceState &state); + /** @name General stuff + * @{ + */ + bool i_isApplianceIdle(); + HRESULT i_searchUniqueVMName(Utf8Str &aName) const; + HRESULT i_ensureUniqueImageFilePath(const Utf8Str &aMachineFolder, + DeviceType_T aDeviceType, + Utf8Str &aName) const; + HRESULT i_setUpProgress(ComObjPtr<Progress> &pProgress, + const Utf8Str &strDescription, + SetUpProgressMode mode); + void i_addWarning(const char* aWarning, ...); + void i_disksWeight(); + void i_parseBucket(Utf8Str &aPath, Utf8Str &aBucket); + + static void i_importOrExportThreadTask(TaskOVF *pTask); + static void i_exportOPCThreadTask(TaskOPC *pTask); + static void i_importOrExportCloudThreadTask(TaskCloud *pTask); + + HRESULT i_initBackendNames(); + + Utf8Str i_typeOfVirtualDiskFormatFromURI(Utf8Str type) const; + +#if 0 /* unused */ + std::set<Utf8Str> i_URIFromTypeOfVirtualDiskFormat(Utf8Str type); +#endif + + HRESULT i_findMediumFormatFromDiskImage(const ovf::DiskImage &di, ComObjPtr<MediumFormat>& mf); + + RTVFSIOSTREAM i_manifestSetupDigestCalculationForGivenIoStream(RTVFSIOSTREAM hVfsIos, const char *pszManifestEntry, + bool fRead = true); + /** @} */ + + /** @name Read stuff + * @{ + */ + HRESULT i_readImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress); + + HRESULT i_readFS(TaskOVF *pTask); + HRESULT i_readFSOVF(TaskOVF *pTask); + HRESULT i_readFSOVA(TaskOVF *pTask); + HRESULT i_readOVFFile(TaskOVF *pTask, RTVFSIOSTREAM hIosOvf, const char *pszManifestEntry); + HRESULT i_readManifestFile(TaskOVF *pTask, RTVFSIOSTREAM hIosMf, const char *pszSubFileNm); + HRESULT i_readSignatureFile(TaskOVF *pTask, RTVFSIOSTREAM hIosCert, const char *pszSubFileNm); + HRESULT i_readTailProcessing(TaskOVF *pTask); + HRESULT i_readTailProcessingGetManifestData(void **ppvData, size_t *pcbData); + HRESULT i_readTailProcessingSignedData(PRTERRINFOSTATIC pErrInfo); + HRESULT i_readTailProcessingVerifySelfSignedOvfCert(TaskOVF *pTask, RTCRSTORE hTrustedCerts, PRTERRINFOSTATIC pErrInfo); + HRESULT i_readTailProcessingVerifyIssuedOvfCert(TaskOVF *pTask, RTCRSTORE hTrustedStore, PRTERRINFOSTATIC pErrInfo); + HRESULT i_readTailProcessingVerifyContentInfoCerts(void const *pvData, size_t cbData, + RTCRSTORE hTrustedStore, PRTERRINFOSTATIC pErrInfo); + HRESULT i_readTailProcessingVerifyAnalyzeSignerInfo(void const *pvData, size_t cbData, RTCRSTORE hTrustedStore, + uint32_t iSigner, PRTTIMESPEC pNow, int vrc, + PRTERRINFOSTATIC pErrInfo, PRTCRSTORE phTrustedStore2); + HRESULT i_readTailProcessingVerifyContentInfoFailOne(const char *pszSignature, int vrc, PRTERRINFOSTATIC pErrInfo); + + HRESULT i_gettingCloudData(TaskCloud *pTask); + /** @} */ + + /** @name Import stuff + * @{ + */ + HRESULT i_importImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress); + + HRESULT i_importFS(TaskOVF *pTask); + HRESULT i_importFSOVF(TaskOVF *pTask, AutoWriteLockBase &rWriteLock); + HRESULT i_importFSOVA(TaskOVF *pTask, AutoWriteLockBase &rWriteLock); + HRESULT i_importDoIt(TaskOVF *pTask, AutoWriteLockBase &rWriteLock, RTVFSFSSTREAM hVfsFssOva = NIL_RTVFSFSSTREAM); + + HRESULT i_verifyManifestFile(ImportStack &stack); + + void i_convertDiskAttachmentValues(const ovf::HardDiskController &hdc, + uint32_t ulAddressOnParent, + Utf8Str &controllerName, + int32_t &lControllerPort, + int32_t &lDevice); + + void i_importOneDiskImage(const ovf::DiskImage &di, + const Utf8Str &strDstPath, + ComObjPtr<Medium> &pTargetMedium, + ImportStack &stack); + + void i_importMachineGeneric(const ovf::VirtualSystem &vsysThis, + ComObjPtr<VirtualSystemDescription> &vsdescThis, + ComPtr<IMachine> &pNewMachineRet, + ImportStack &stack); + void i_importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThis, + ComPtr<IMachine> &pNewMachine, + ImportStack &stack); + void i_importMachines(ImportStack &stack); + HRESULT i_verifyStorageControllerPortValid(const StorageControllerType_T aStorageControllerType, + const uint32_t aControllerPort, + ULONG *ulMaxPorts); + + HRESULT i_preCheckImageAvailability(ImportStack &stack); + bool i_importEnsureOvaLookAhead(ImportStack &stack); + RTVFSIOSTREAM i_importOpenSourceFile(ImportStack &stack, Utf8Str const &rstrSrcPath, const char *pszManifestEntry); + HRESULT i_importCreateAndWriteDestinationFile(Utf8Str const &rstrDstPath, + RTVFSIOSTREAM hVfsIosSrc, Utf8Str const &rstrSrcLogNm); + + void i_importCopyFile(ImportStack &stack, Utf8Str const &rstrSrcPath, Utf8Str const &rstrDstPath, + const char *pszManifestEntry); + void i_importDecompressFile(ImportStack &stack, Utf8Str const &rstrSrcPath, Utf8Str const &rstrDstPath, + const char *pszManifestEntry); + HRESULT i_importCloudImpl(TaskCloud *pTask); + /** @} */ + + /** @name Write stuff + * @{ + */ + HRESULT i_writeImpl(ovf::OVFVersion_T aFormat, const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress); + HRESULT i_writeOPCImpl(ovf::OVFVersion_T aFormat, const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress); + HRESULT i_writeCloudImpl(const LocationInfo &aLocInfo, ComObjPtr<Progress> &aProgress); + + HRESULT i_writeFS(TaskOVF *pTask); + HRESULT i_writeFSOVF(TaskOVF *pTask, AutoWriteLockBase& writeLock); + HRESULT i_writeFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock); + HRESULT i_writeFSOPC(TaskOPC *pTask); + HRESULT i_exportCloudImpl(TaskCloud *pTask); + HRESULT i_writeFSImpl(TaskOVF *pTask, AutoWriteLockBase &writeLock, RTVFSFSSTREAM hVfsFssDst); + HRESULT i_writeBufferToFile(RTVFSFSSTREAM hVfsFssDst, const char *pszFilename, const void *pvContent, size_t cbContent); + + struct XMLStack; + + void i_buildXML(AutoWriteLockBase& writeLock, + xml::Document &doc, + XMLStack &stack, + const Utf8Str &strPath, + ovf::OVFVersion_T enFormat); + void i_buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock, + xml::ElementNode &elmToAddVirtualSystemsTo, + std::list<xml::ElementNode*> *pllElementsWithUuidAttributes, + ComObjPtr<VirtualSystemDescription> &vsdescThis, + ovf::OVFVersion_T enFormat, + XMLStack &stack); + /** @} */ + + friend class Machine; + friend class Certificate; +}; + +void i_parseURI(Utf8Str strUri, LocationInfo &locInfo); + +struct VirtualSystemDescriptionEntry +{ + uint32_t ulIndex; ///< zero-based index of this entry within array + VirtualSystemDescriptionType_T type; ///< type of this entry + Utf8Str strRef; ///< reference number (hard disk controllers only) + Utf8Str strOvf; ///< original OVF value (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 + bool skipIt; ///< used during export to skip some parts if it's needed +}; + +class ATL_NO_VTABLE VirtualSystemDescription : + public VirtualSystemDescriptionWrap +{ + friend class Appliance; + +public: + + DECLARE_COMMON_CLASS_METHODS(VirtualSystemDescription) + + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT init(); + void uninit(); + + /* public methods only for internal purposes */ + void i_addEntry(VirtualSystemDescriptionType_T aType, + const Utf8Str &strRef, + const Utf8Str &aOvfValue, + const Utf8Str &aVBoxValue, + uint32_t ulSizeMB = 0, + const Utf8Str &strExtraConfig = ""); + + std::list<VirtualSystemDescriptionEntry*> i_findByType(VirtualSystemDescriptionType_T aType); + const VirtualSystemDescriptionEntry* i_findControllerFromID(const Utf8Str &id); + const VirtualSystemDescriptionEntry* i_findByIndex(const uint32_t aIndex); + + void i_importVBoxMachineXML(const xml::ElementNode &elmMachine); + const settings::MachineConfigFile* i_getMachineConfig() const; + + /* private instance data */ +private: + + // wrapped IVirtualSystemDescription properties + HRESULT getCount(ULONG *aCount); + + // wrapped IVirtualSystemDescription methods + HRESULT getDescription(std::vector<VirtualSystemDescriptionType_T> &aTypes, + std::vector<com::Utf8Str> &aRefs, + std::vector<com::Utf8Str> &aOVFValues, + std::vector<com::Utf8Str> &aVBoxValues, + std::vector<com::Utf8Str> &aExtraConfigValues); + HRESULT getDescriptionByType(VirtualSystemDescriptionType_T aType, + std::vector<VirtualSystemDescriptionType_T> &aTypes, + std::vector<com::Utf8Str> &aRefs, + std::vector<com::Utf8Str> &aOVFValues, + std::vector<com::Utf8Str> &aVBoxValues, + std::vector<com::Utf8Str> &aExtraConfigValues); + HRESULT getValuesByType(VirtualSystemDescriptionType_T aType, + VirtualSystemDescriptionValueType_T aWhich, + std::vector<com::Utf8Str> &aValues); + HRESULT setFinalValues(const std::vector<BOOL> &aEnabled, + const std::vector<com::Utf8Str> &aVBoxValues, + const std::vector<com::Utf8Str> &aExtraConfigValues); + HRESULT addDescription(VirtualSystemDescriptionType_T aType, + const com::Utf8Str &aVBoxValue, + const com::Utf8Str &aExtraConfigValue); + HRESULT removeDescriptionByType(VirtualSystemDescriptionType_T aType); + void i_removeByType(VirtualSystemDescriptionType_T aType); + + struct Data; + Data *m; + + friend class Machine; +}; + +#endif /* !MAIN_INCLUDED_ApplianceImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/ApplianceImplPrivate.h b/src/VBox/Main/include/ApplianceImplPrivate.h new file mode 100644 index 00000000..f3641a8f --- /dev/null +++ b/src/VBox/Main/include/ApplianceImplPrivate.h @@ -0,0 +1,572 @@ +/* $Id: ApplianceImplPrivate.h $ */ +/** @file + * VirtualBox Appliance private data definitions + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ApplianceImplPrivate_h +#define MAIN_INCLUDED_ApplianceImplPrivate_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + + +class VirtualSystemDescription; + +#include "ovfreader.h" +#include "SecretKeyStore.h" +#include "ThreadTask.h" +#include "CertificateImpl.h" +#include <map> +#include <vector> +#include <iprt/manifest.h> +#include <iprt/vfs.h> +#include <iprt/crypto/x509.h> +#include <iprt/crypto/pkcs7.h> + +//////////////////////////////////////////////////////////////////////////////// +// +// Appliance data definition +// +//////////////////////////////////////////////////////////////////////////////// + +namespace settings +{ + struct AttachedDevice; +} + +typedef std::pair<Utf8Str, Utf8Str> STRPAIR; + +typedef std::vector<com::Guid> GUIDVEC; + +/* Describe a location for the import/export. The location could be a file on a + * local hard disk or a remote target based on the supported inet protocols. */ +struct LocationInfo +{ + LocationInfo() + : storageType(VFSType_File) {} + VFSType_T storageType; /* Which type of storage should be handled */ + Utf8Str strProvider; /* cloud provider name in case of export/import to Cloud */ + Utf8Str strPath; /* File path for the import/export */ + Utf8Str strHostname; /* Hostname on remote storage locations (could be empty) */ + Utf8Str strUsername; /* Username on remote storage locations (could be empty) */ + Utf8Str strPassword; /* Password on remote storage locations (could be empty) */ +}; + +/** + * opaque private instance data of Appliance class + */ +struct Appliance::Data +{ + enum digest_T {SHA1, SHA256}; + + Data() + : state(Appliance::ApplianceIdle) + , fDigestTypes(0) + , hOurManifest(NIL_RTMANIFEST) + , fManifest(true) + , fDeterminedDigestTypes(false) + , hTheirManifest(NIL_RTMANIFEST) + , hMemFileTheirManifest(NIL_RTVFSFILE) + , fSignerCertLoaded(false) + , fCertificateIsSelfSigned(false) + , fSignatureValid(false) + , fCertificateValid(false) + , fCertificateMissingPath(true) + , fCertificateValidTime(false) + , pbSignedDigest(NULL) + , cbSignedDigest(0) + , enmSignedDigestType(RTDIGESTTYPE_INVALID) + , fContentInfoLoaded(false) + , fContentInfoOkay(false) + , fContentInfoSameCert(false) + , fContentInfoValidSignature(false) + , fExportISOImages(false) + , pReader(NULL) + , ulWeightForXmlOperation(0) + , ulWeightForManifestOperation(0) + , ulTotalDisksMB(0) + , cDisks(0) + , m_cPwProvided(0) + { + RT_ZERO(SignerCert); + RT_ZERO(ContentInfo); + } + + ~Data() + { + if (pReader) + { + delete pReader; + pReader = NULL; + } + resetReadData(); + } + + /** + * Resets data used by read. + */ + void resetReadData(void) + { + strOvfManifestEntry.setNull(); + if (hOurManifest != NIL_RTMANIFEST) + { + RTManifestRelease(hOurManifest); + hOurManifest = NIL_RTMANIFEST; + } + if (hTheirManifest != NIL_RTMANIFEST) + { + RTManifestRelease(hTheirManifest); + hTheirManifest = NIL_RTMANIFEST; + } + if (hMemFileTheirManifest) + { + RTVfsFileRelease(hMemFileTheirManifest); + hMemFileTheirManifest = NIL_RTVFSFILE; + } + if (pbSignedDigest) + { + RTMemFree(pbSignedDigest); + pbSignedDigest = NULL; + cbSignedDigest = 0; + } + if (fSignerCertLoaded) + { + RTCrX509Certificate_Delete(&SignerCert); + fSignerCertLoaded = false; + } + RT_ZERO(SignerCert); + enmSignedDigestType = RTDIGESTTYPE_INVALID; + fCertificateIsSelfSigned = false; + fSignatureValid = false; + fCertificateValid = false; + fCertificateMissingPath = true; + fCertificateValidTime = false; + fDeterminedDigestTypes = false; + fDigestTypes = RTMANIFEST_ATTR_SHA1 | RTMANIFEST_ATTR_SHA256 | RTMANIFEST_ATTR_SHA512; + ptrCertificateInfo.setNull(); + strCertError.setNull(); + if (fContentInfoLoaded) + { + RTCrPkcs7ContentInfo_Delete(&ContentInfo); + fContentInfoLoaded = false; + } + RT_ZERO(ContentInfo); + } + + Appliance::ApplianceState state; + + LocationInfo locInfo; // location info for the currently processed OVF + /** The digests types to calculate (RTMANIFEST_ATTR_XXX) for the manifest. + * This will be a single value when exporting. Zero, one or two. */ + uint32_t fDigestTypes; + /** Manifest created while importing or exporting. */ + RTMANIFEST hOurManifest; + + /** @name Write data + * @{ */ + bool fManifest; // Create a manifest file on export + /** @} */ + + /** @name Read data + * @{ */ + /** The manifest entry name of the OVF-file. */ + Utf8Str strOvfManifestEntry; + + /** Set if we've parsed the manifest and determined the digest types. */ + bool fDeterminedDigestTypes; + + /** Manifest read in during read() and kept around for later verification. */ + RTMANIFEST hTheirManifest; + /** Memorized copy of the manifest file for signature checking purposes. */ + RTVFSFILE hMemFileTheirManifest; + + /** The signer certificate from the signature file (.cert). + * This will be used in the future provide information about the signer via + * the API. */ + RTCRX509CERTIFICATE SignerCert; + /** Set if the SignerCert member contains usable data. */ + bool fSignerCertLoaded; + /** Cached RTCrX509Validity_IsValidAtTimeSpec result set by read(). */ + bool fCertificateIsSelfSigned; + /** Set by read() if pbSignedDigest verified correctly against SignerCert. */ + bool fSignatureValid; + /** Set by read() when the SignerCert checked out fine. */ + bool fCertificateValid; + /** Set by read() when the SignerCert certificate path couldn't be built. */ + bool fCertificateMissingPath; + /** Set by read() when the SignerCert (+path) is valid in the temporal sense. */ + bool fCertificateValidTime; + /** For keeping certificate error messages we delay from read() to import(). */ + Utf8Str strCertError; + /** The signed digest of the manifest. */ + uint8_t *pbSignedDigest; + /** The size of the signed digest. */ + size_t cbSignedDigest; + /** The digest type used to sign the manifest. */ + RTDIGESTTYPE enmSignedDigestType; + /** The certificate info object. This is NULL if no signature and + * successfully loaded certificate. */ + ComObjPtr<Certificate> ptrCertificateInfo; + + /** The PKCS\#7/CMS signed data signing manifest, optional VBox extension. + * This contains at least one signature using the same certificate as above + * (SignerCert), but should preferrably use a different digest. The PKCS\#7/CMS + * format is a lot more versatile, allow multiple signatures using different + * digests and certificates, optionally with counter signed timestamps. + * Additional intermediate certificates can also be shipped, helping to bridge + * the gap to a trusted root certificate installed on the recieving system. */ + RTCRPKCS7CONTENTINFO ContentInfo; + /** Set if the ContentInfo member contains usable data. */ + bool fContentInfoLoaded; + /** Set by read() if the ContentInfo member checked out okay (says nothing about + * the signature or certificates within it). */ + bool fContentInfoOkay; + /** Set by read() if the ContentInfo member is using the SignerCert too. */ + bool fContentInfoSameCert; + /** Set by read() if the ContentInfo member contains valid signatures (not + * saying anything about valid signing certificates). */ + bool fContentInfoValidSignature; + /** Set by read() if we've already verified the signed data signature(s). */ + bool fContentInfoDoneVerification; + + bool fContentInfoVerifiedOkay; + /** @} */ + + bool fExportISOImages;// when 1 the ISO images are exported + + RTCList<ImportOptions_T> optListImport; + RTCList<ExportOptions_T> optListExport; + + ovf::OVFReader *pReader; + + std::list< ComObjPtr<VirtualSystemDescription> > + virtualSystemDescriptions; + + std::list<Utf8Str> llWarnings; + + ULONG ulWeightForXmlOperation; + ULONG ulWeightForManifestOperation; + ULONG ulTotalDisksMB; + ULONG cDisks; + + std::list<Guid> llGuidsMachinesCreated; + + /** Sequence of password identifiers to encrypt disk images during export. */ + std::vector<com::Utf8Str> m_vecPasswordIdentifiers; + /** Map to get all medium identifiers assoicated with a given password identifier. */ + std::map<com::Utf8Str, GUIDVEC> m_mapPwIdToMediumIds; + /** Secret key store used to hold the passwords during export. */ + SecretKeyStore *m_pSecretKeyStore; + /** Number of passwords provided. */ + uint32_t m_cPwProvided; +}; + +struct Appliance::XMLStack +{ + std::map<Utf8Str, const VirtualSystemDescriptionEntry*> mapDisks; + std::list<Utf8Str> mapDiskSequence; + std::list<Utf8Str> mapDiskSequenceForOneVM;//temporary keeps all disks attached to one exported VM + std::map<Utf8Str, bool> mapNetworks; +}; + +class Appliance::TaskOVF : public ThreadTask +{ +public: + enum TaskType + { + Read, + Import, + Write + }; + + TaskOVF(Appliance *aThat, + TaskType aType, + LocationInfo aLocInfo, + ComObjPtr<Progress> &aProgress) + : ThreadTask("TaskOVF"), + pAppliance(aThat), + taskType(aType), + locInfo(aLocInfo), + pProgress(aProgress), + enFormat(ovf::OVFVersion_unknown), + rc(S_OK) + { + switch (taskType) + { + case TaskOVF::Read: m_strTaskName = "ApplRead"; break; + case TaskOVF::Import: m_strTaskName = "ApplImp"; break; + case TaskOVF::Write: m_strTaskName = "ApplWrit"; break; + default: m_strTaskName = "ApplTask"; break; + } + } + + static DECLCALLBACK(int) updateProgress(unsigned uPercent, void *pvUser); + + Appliance *pAppliance; + TaskType taskType; + const LocationInfo locInfo; + ComObjPtr<Progress> pProgress; + + ovf::OVFVersion_T enFormat; + + HRESULT rc; + + void handler() + { + Appliance::i_importOrExportThreadTask(this); + } +}; + +class Appliance::TaskOPC : public ThreadTask +{ +public: + enum TaskType + { + Export + }; + + TaskOPC(Appliance *aThat, + TaskType aType, + LocationInfo aLocInfo, + ComObjPtr<Progress> &aProgress) + : ThreadTask("TaskOPC"), + pAppliance(aThat), + taskType(aType), + locInfo(aLocInfo), + pProgress(aProgress), + rc(S_OK) + { + m_strTaskName = "OPCExpt"; + } + + ~TaskOPC() + { + } + + static DECLCALLBACK(int) updateProgress(unsigned uPercent, void *pvUser); + + Appliance *pAppliance; + TaskType taskType; + const LocationInfo locInfo; + ComObjPtr<Progress> pProgress; + + HRESULT rc; + + void handler() + { + Appliance::i_exportOPCThreadTask(this); + } +}; + + +class Appliance::TaskCloud : public ThreadTask +{ +public: + enum TaskType + { + Export, + Import, + ReadData + }; + + TaskCloud(Appliance *aThat, + TaskType aType, + LocationInfo aLocInfo, + ComObjPtr<Progress> &aProgress) + : ThreadTask("TaskCloud"), + pAppliance(aThat), + taskType(aType), + locInfo(aLocInfo), + pProgress(aProgress), + rc(S_OK) + { + switch (taskType) + { + case TaskCloud::Export: m_strTaskName = "CloudExpt"; break; + case TaskCloud::Import: m_strTaskName = "CloudImpt"; break; + case TaskCloud::ReadData: m_strTaskName = "CloudRead"; break; + default: m_strTaskName = "CloudTask"; break; + } + } + + ~TaskCloud() + { + } + + static DECLCALLBACK(int) updateProgress(unsigned uPercent, void *pvUser); + + Appliance *pAppliance; + TaskType taskType; + const LocationInfo locInfo; + ComObjPtr<Progress> pProgress; + + HRESULT rc; + + void handler() + { + Appliance::i_importOrExportCloudThreadTask(this); + } +}; + +struct MyHardDiskAttachment +{ + ComPtr<IMachine> pMachine; + Utf8Str controllerName; + int32_t lControllerPort; // 0-29 for SATA + 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 strSettingsFilename; // Absolute path to VM config file + Utf8Str strMachineFolder; // Absolute path to VM folder (derived from strSettingsFilename) + Utf8Str strOsTypeVBox; // VirtualBox guest OS type as string + Utf8Str strPrimaryGroup; // VM primary group as string + Utf8Str strDescription; + 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 machine RAM in megabytes + Utf8Str strFirmwareType; //Firmware - BIOS or EFI +#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 + + /** @name File access related stuff (TAR stream) + * @{ */ + /** OVA file system stream handle. NIL if not OVA. */ + RTVFSFSSTREAM hVfsFssOva; + /** OVA lookahead I/O stream object. */ + RTVFSIOSTREAM hVfsIosOvaLookAhead; + /** OVA lookahead I/O stream object name. */ + char *pszOvaLookAheadName; + /** @} */ + + // 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::map<Utf8Str , Utf8Str> mapNewUUIDsToOriginalUUIDs; + + ImportStack(const LocationInfo &aLocInfo, + const ovf::DiskImagesMap &aMapDisks, + ComObjPtr<Progress> &aProgress, + RTVFSFSSTREAM aVfsFssOva) + : locInfo(aLocInfo), + mapDisks(aMapDisks), + pProgress(aProgress), + cCPUs(1), + fForceHWVirt(false), + fForceIOAPIC(false), + ulMemorySizeMB(0), + fSessionOpen(false), + hVfsFssOva(aVfsFssOva), + hVfsIosOvaLookAhead(NIL_RTVFSIOSTREAM), + pszOvaLookAheadName(NULL) + { + if (hVfsFssOva != NIL_RTVFSFSSTREAM) + RTVfsFsStrmRetain(hVfsFssOva); + + // 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(); + } + + ~ImportStack() + { + if (hVfsFssOva != NIL_RTVFSFSSTREAM) + { + RTVfsFsStrmRelease(hVfsFssOva); + hVfsFssOva = NIL_RTVFSFSSTREAM; + } + if (hVfsIosOvaLookAhead != NIL_RTVFSIOSTREAM) + { + RTVfsIoStrmRelease(hVfsIosOvaLookAhead); + hVfsIosOvaLookAhead = NIL_RTVFSIOSTREAM; + } + if (pszOvaLookAheadName) + { + RTStrFree(pszOvaLookAheadName); + pszOvaLookAheadName = NULL; + } + } + + HRESULT restoreOriginalUUIDOfAttachedDevice(settings::MachineConfigFile *config); + HRESULT saveOriginalUUIDOfAttachedDevice(settings::AttachedDevice &device, + const Utf8Str &newlyUuid); + RTVFSIOSTREAM claimOvaLookAHead(void); + +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// VirtualSystemDescription data definition +// +//////////////////////////////////////////////////////////////////////////////// + +struct VirtualSystemDescription::Data +{ + std::vector<VirtualSystemDescriptionEntry> + maDescriptions; // item descriptions + + ComPtr<Machine> pMachine; // VirtualBox machine this description was exported from (export only) + + settings::MachineConfigFile + *pConfig; // machine config created from <vbox:Machine> element if found (import only) +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// Internal helpers +// +//////////////////////////////////////////////////////////////////////////////// + +void convertCIMOSType2VBoxOSType(Utf8Str &strType, ovf::CIMOSType_T c, const Utf8Str &cStr); + +ovf::CIMOSType_T convertVBoxOSType2CIMOSType(const char *pcszVBox, BOOL fLongMode); + +Utf8Str convertNetworkAttachmentTypeToString(NetworkAttachmentType_T type); + + +#endif /* !MAIN_INCLUDED_ApplianceImplPrivate_h */ + diff --git a/src/VBox/Main/include/AudioAdapterImpl.h b/src/VBox/Main/include/AudioAdapterImpl.h new file mode 100644 index 00000000..f5e833ec --- /dev/null +++ b/src/VBox/Main/include/AudioAdapterImpl.h @@ -0,0 +1,94 @@ +/* $Id: AudioAdapterImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_AudioAdapterImpl_h +#define MAIN_INCLUDED_AudioAdapterImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +class AudioSettings; + +#include "AudioAdapterWrap.h" +namespace settings +{ + struct AudioAdapter; +} + +class ATL_NO_VTABLE AudioAdapter : + public AudioAdapterWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS (AudioAdapter) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(AudioSettings *aParent); + HRESULT init(AudioSettings *aParent, AudioAdapter *aThat); + HRESULT initCopy(AudioSettings *aParent, AudioAdapter *aThat); + void uninit(); + + // public methods only for internal purposes + HRESULT i_loadSettings(const settings::AudioAdapter &data); + HRESULT i_saveSettings(settings::AudioAdapter &data); + + void i_rollback(); + void i_commit(); + void i_copyFrom(AudioAdapter *aThat); + +private: + + // wrapped IAudioAdapter properties + HRESULT getEnabled(BOOL *aEnabled); + HRESULT setEnabled(BOOL aEnabled); + HRESULT getEnabledIn(BOOL *aEnabled); + HRESULT setEnabledIn(BOOL aEnabled); + HRESULT getEnabledOut(BOOL *aEnabled); + HRESULT setEnabledOut(BOOL aEnabled); + HRESULT getAudioDriver(AudioDriverType_T *aAudioDriver); + HRESULT setAudioDriver(AudioDriverType_T aAudioDriver); + HRESULT getAudioController(AudioControllerType_T *aAudioController); + HRESULT setAudioController(AudioControllerType_T aAudioController); + HRESULT getAudioCodec(AudioCodecType_T *aAudioCodec); + HRESULT setAudioCodec(AudioCodecType_T aAudioCodec); + HRESULT getPropertiesList(std::vector<com::Utf8Str>& aProperties); + HRESULT getProperty(const com::Utf8Str &aKey, com::Utf8Str &aValue); + HRESULT setProperty(const com::Utf8Str &aKey, const com::Utf8Str &aValue); + +private: + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_AudioAdapterImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/AudioDriver.h b/src/VBox/Main/include/AudioDriver.h new file mode 100644 index 00000000..b1124b66 --- /dev/null +++ b/src/VBox/Main/include/AudioDriver.h @@ -0,0 +1,144 @@ +/* $Id: AudioDriver.h $ */ +/** @file + * VirtualBox audio base class for Main audio drivers. + */ + +/* + * Copyright (C) 2018-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_AudioDriver_h +#define MAIN_INCLUDED_AudioDriver_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/ptr.h> +#include <VBox/com/string.h> +#include <VBox/com/AutoLock.h> + +using namespace com; + +/** + * Audio driver configuration for audio drivers implemented + * in Main. + */ +struct AudioDriverCfg +{ + AudioDriverCfg(Utf8Str a_strDev = "", unsigned a_uInst = 0, unsigned a_uLUN = 0, Utf8Str a_strName = "", + bool a_fEnabledIn = false, bool a_fEnabledOut = false) + : strDev(a_strDev) + , uInst(a_uInst) + , uLUN(a_uLUN) + , strName(a_strName) + , fEnabledIn(a_fEnabledIn) + , fEnabledOut(a_fEnabledOut) + { } + + /** Copy assignment operator. */ + AudioDriverCfg& operator=(AudioDriverCfg const &a_rThat) RT_NOEXCEPT + { + this->strDev = a_rThat.strDev; + this->uInst = a_rThat.uInst; + this->uLUN = a_rThat.uLUN; + this->strName = a_rThat.strName; + this->fEnabledIn = a_rThat.fEnabledIn; + this->fEnabledOut = a_rThat.fEnabledOut; + + return *this; + } + + /** The device name. */ + Utf8Str strDev; + /** The device instance. */ + unsigned uInst; + /** The LUN the driver is attached to. + * Set the UINT8_MAX if not attached. */ + unsigned uLUN; + /** The driver name. */ + Utf8Str strName; + /** Whether input is enabled. */ + bool fEnabledIn; + /** Whether output is enabled. */ + bool fEnabledOut; +}; + +class Console; + +/** + * Base class for all audio drivers implemented in Main. + */ +class AudioDriver +{ + +public: + AudioDriver(Console *pConsole); + virtual ~AudioDriver(); + + /** Copy assignment operator. */ + AudioDriver &operator=(AudioDriver const &a_rThat) RT_NOEXCEPT; + + Console *GetParent(void) { return mpConsole; } + + AudioDriverCfg *GetConfig(void) { return &mCfg; } + int InitializeConfig(AudioDriverCfg *pCfg); + + /** Checks if audio is configured or not. */ + bool isConfigured() const { return mCfg.strName.isNotEmpty(); } + + bool IsAttached(void) { return mfAttached; } + + int doAttachDriverViaEmt(PUVM pUVM, PCVMMR3VTABLE pVMM, util::AutoWriteLock *pAutoLock); + int doDetachDriverViaEmt(PUVM pUVM, PCVMMR3VTABLE pVMM, util::AutoWriteLock *pAutoLock); + +protected: + static DECLCALLBACK(int) attachDriverOnEmt(AudioDriver *pThis); + static DECLCALLBACK(int) detachDriverOnEmt(AudioDriver *pThis); + + int configure(unsigned uLUN, bool fAttach); + + /** + * Virtual function for child specific driver configuration. + * + * This is called at the end of AudioDriver::configure(). + * + * @returns VBox status code. + * @param pLunCfg CFGM configuration node of the driver. + * @param pVMM The VMM ring-3 vtable. + */ + virtual int configureDriver(PCFGMNODE pLunCfg, PCVMMR3VTABLE pVMM) + { + RT_NOREF(pLunCfg, pVMM); + return VINF_SUCCESS; + } + +protected: + + /** Pointer to parent. */ + Console *mpConsole; + /** The driver's configuration. */ + AudioDriverCfg mCfg; + /** Whether the driver is attached or not. */ + bool mfAttached; +}; + +#endif /* !MAIN_INCLUDED_AudioDriver_h */ + diff --git a/src/VBox/Main/include/AudioSettingsImpl.h b/src/VBox/Main/include/AudioSettingsImpl.h new file mode 100644 index 00000000..7786a27e --- /dev/null +++ b/src/VBox/Main/include/AudioSettingsImpl.h @@ -0,0 +1,84 @@ +/* $Id: AudioSettingsImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_AudioSettingsImpl_h +#define MAIN_INCLUDED_AudioSettingsImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "AudioAdapterImpl.h" +#include "GuestOSTypeImpl.h" + +#include "AudioSettingsWrap.h" +namespace settings +{ + struct AudioSettings; +} + +class ATL_NO_VTABLE AudioSettings : + public AudioSettingsWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(AudioSettings) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent); + HRESULT init(Machine *aParent, AudioSettings *aThat); + HRESULT initCopy(Machine *aParent, AudioSettings *aThat); + void uninit(); + + HRESULT getHostAudioDevice(AudioDirection_T aUsage, ComPtr<IHostAudioDevice> &aDevice); + HRESULT setHostAudioDevice(const ComPtr<IHostAudioDevice> &aDevice, AudioDirection_T aUsage); + HRESULT getAdapter(ComPtr<IAudioAdapter> &aAdapter); + + // public methods only for internal purposes + bool i_canChangeSettings(void); + void i_onAdapterChanged(IAudioAdapter *pAdapter); + void i_onHostDeviceChanged(IHostAudioDevice *pDevice, bool fIsNew, AudioDeviceState_T enmState, IVirtualBoxErrorInfo *pErrInfo); + void i_onSettingsChanged(void); + HRESULT i_loadSettings(const settings::AudioAdapter &data); + HRESULT i_saveSettings(settings::AudioAdapter &data); + void i_copyFrom(AudioSettings *aThat); + HRESULT i_applyDefaults(ComObjPtr<GuestOSType> &aGuestOsType); + + void i_rollback(); + void i_commit(); + +private: + + struct Data; + Data *m; +}; +#endif /* !MAIN_INCLUDED_AudioSettingsImpl_h */ + diff --git a/src/VBox/Main/include/AuthLibrary.h b/src/VBox/Main/include/AuthLibrary.h new file mode 100644 index 00000000..f432ff79 --- /dev/null +++ b/src/VBox/Main/include/AuthLibrary.h @@ -0,0 +1,54 @@ +/* $Id: AuthLibrary.h $ */ +/** @file + * Main - external authentication library interface. + */ + +/* + * Copyright (C) 2015-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_AuthLibrary_h +#define MAIN_INCLUDED_AuthLibrary_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/VBoxAuth.h> +#include <iprt/types.h> + +typedef struct AUTHLIBRARYCONTEXT +{ + RTLDRMOD hAuthLibrary; + PAUTHENTRY pfnAuthEntry; + PAUTHENTRY2 pfnAuthEntry2; + PAUTHENTRY3 pfnAuthEntry3; +} AUTHLIBRARYCONTEXT; + +int AuthLibLoad(AUTHLIBRARYCONTEXT *pAuthLibCtx, const char *pszLibrary); +void AuthLibUnload(AUTHLIBRARYCONTEXT *pAuthLibCtx); + +AuthResult AuthLibAuthenticate(const AUTHLIBRARYCONTEXT *pAuthLibCtx, + PCRTUUID pUuid, AuthGuestJudgement guestJudgement, + const char *pszUser, const char *pszPassword, const char *pszDomain, + uint32_t u32ClientId); +void AuthLibDisconnect(const AUTHLIBRARYCONTEXT *pAuthLibCtx, PCRTUUID pUuid, uint32_t u32ClientId); + +#endif /* !MAIN_INCLUDED_AuthLibrary_h */ diff --git a/src/VBox/Main/include/AutoCaller.h b/src/VBox/Main/include/AutoCaller.h new file mode 100644 index 00000000..00ec27d7 --- /dev/null +++ b/src/VBox/Main/include/AutoCaller.h @@ -0,0 +1,535 @@ +/* $Id: AutoCaller.h $ */ +/** @file + * + * VirtualBox object caller handling definitions + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_AutoCaller_h +#define MAIN_INCLUDED_AutoCaller_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "ObjectState.h" + +#include "VBox/com/AutoLock.h" + +// Forward declaration needed, but nothing more. +class VirtualBoxBase; + + +//////////////////////////////////////////////////////////////////////////////// +// +// AutoCaller* classes +// +//////////////////////////////////////////////////////////////////////////////// + + +/** + * Smart class that automatically increases the number of normal (non-limited) + * callers of the given VirtualBoxBase object when an instance is constructed + * and decreases it back when the created instance goes out of scope (i.e. gets + * destroyed). + * + * If #rc() returns a failure after the instance creation, it means that + * the managed VirtualBoxBase object is not Ready, or in any other invalid + * state, so that the caller must not use the object and can return this + * failed result code to the upper level. + * + * See ObjectState::addCaller() and ObjectState::releaseCaller() for more + * details about object callers. + * + * A typical usage pattern to declare a normal method of some object (i.e. a + * method that is valid only when the object provides its full + * functionality) is: + * <code> + * STDMETHODIMP Component::Foo() + * { + * AutoCaller autoCaller(this); + * HRESULT hrc = autoCaller.rc(); + * if (SUCCEEDED(hrc)) + * { + * ... + * } + * return hrc; + * } + * </code> + */ +class AutoCaller +{ +public: + /** + * Default constructor. Not terribly useful, but it's valid to create + * an instance without associating it with an object. It's a no-op, + * like the more useful constructor below when NULL is passed to it. + */ + AutoCaller() + { + init(NULL, false); + } + + /** + * Increases the number of callers of the given object by calling + * ObjectState::addCaller() for the corresponding member instance. + * + * @param aObj Object to add a normal caller to. If NULL, this + * instance is effectively turned to no-op (where + * rc() will return S_OK). + */ + AutoCaller(VirtualBoxBase *aObj) + { + init(aObj, false); + } + + /** + * If the number of callers was successfully increased, decreases it + * using ObjectState::releaseCaller(), otherwise does nothing. + */ + ~AutoCaller() + { + if (mObj && SUCCEEDED(mRC)) + mObj->getObjectState().releaseCaller(); + } + + /** + * Returns the stored result code returned by ObjectState::addCaller() + * after instance creation or after the last #add() call. A successful + * result code means the number of callers was successfully increased. + */ + HRESULT rc() const { return mRC; } + + /** + * Returns |true| if |SUCCEEDED(rc())| is |true|, for convenience. + * |true| means the number of callers was successfully increased. + */ + bool isOk() const { return SUCCEEDED(mRC); } + + /** + * Returns |true| if |FAILED(rc())| is |true|, for convenience. + * |true| means the number of callers was _not_ successfully increased. + */ + bool isNotOk() const { return FAILED(mRC); } + + /** + * Temporarily decreases the number of callers of the managed object. + * May only be called if #isOk() returns |true|. Note that #rc() will + * return E_FAIL after this method succeeds. + */ + void release() + { + Assert(SUCCEEDED(mRC)); + if (SUCCEEDED(mRC)) + { + if (mObj) + mObj->getObjectState().releaseCaller(); + mRC = E_FAIL; + } + } + + /** + * Restores the number of callers decreased by #release(). May only be + * called after #release(). + */ + void add() + { + Assert(!SUCCEEDED(mRC)); + if (mObj && !SUCCEEDED(mRC)) + mRC = mObj->getObjectState().addCaller(mLimited); + } + + /** + * Attaches another object to this caller instance. + * The previous object's caller is released before the new one is added. + * + * @param aObj New object to attach, may be @c NULL. + */ + void attach(VirtualBoxBase *aObj) + { + /* detect simple self-reattachment */ + if (mObj != aObj) + { + if (mObj && SUCCEEDED(mRC)) + release(); + else if (!mObj) + { + /* Fix up the success state when nothing is attached. Otherwise + * there are a couple of assertion which would trigger. */ + mRC = E_FAIL; + } + mObj = aObj; + add(); + } + } + + /** Verbose equivalent to <tt>attach(NULL)</tt>. */ + void detach() { attach(NULL); } + +protected: + /** + * Internal constructor: Increases the number of callers of the given + * object (either normal or limited variant) by calling + * ObjectState::addCaller() for the corresponding member instance. + * + * @param aObj Object to add a caller to. If NULL, this + * instance is effectively turned to no-op (where + * rc() will return S_OK). + * @param aLimited If |false|, then it's a regular caller, otherwise a + * limited caller. + */ + void init(VirtualBoxBase *aObj, bool aLimited) + { + mObj = aObj; + mRC = S_OK; + mLimited = aLimited; + if (mObj) + mRC = mObj->getObjectState().addCaller(mLimited); + } + +private: + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoCaller); + DECLARE_CLS_NEW_DELETE_NOOP(AutoCaller); + + VirtualBoxBase *mObj; + HRESULT mRC; + bool mLimited; +}; + +/** + * Smart class that automatically increases the number of limited callers of + * the given VirtualBoxBase object when an instance is constructed and + * decreases it back when the created instance goes out of scope (i.e. gets + * destroyed). + * + * A typical usage pattern to declare a limited method of some object (i.e. + * a method that is valid even if the object doesn't provide its full + * functionality) is: + * <code> + * STDMETHODIMP Component::Bar() + * { + * AutoLimitedCaller autoCaller(this); + * HRESULT hrc = autoCaller.rc(); + * if (SUCCEEDED(hrc)) + * { + * ... + * } + * return hrc; + * </code> + * + * See AutoCaller for more information about auto caller functionality. + */ +class AutoLimitedCaller : public AutoCaller +{ +public: + /** + * Default constructor. Not terribly useful, but it's valid to create + * an instance without associating it with an object. It's a no-op, + * like the more useful constructor below when NULL is passed to it. + */ + AutoLimitedCaller() + { + AutoCaller::init(NULL, true); + } + + /** + * Increases the number of callers of the given object by calling + * ObjectState::addCaller() for the corresponding member instance. + * + * @param aObj Object to add a limited caller to. If NULL, this + * instance is effectively turned to no-op (where + * rc() will return S_OK). + */ + AutoLimitedCaller(VirtualBoxBase *aObj) + { + AutoCaller::init(aObj, true); + } + +private: + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoLimitedCaller); /* Shuts up MSC warning C4625. */ +}; + +/** + * Smart class to enclose the state transition NotReady->InInit->Ready. + * + * The purpose of this span is to protect object initialization. + * + * Instances must be created as a stack-based variable taking |this| pointer + * as the argument at the beginning of init() methods of VirtualBoxBase + * subclasses. When this variable is created it automatically places the + * object to the InInit state. + * + * When the created variable goes out of scope (i.e. gets destroyed) then, + * depending on the result status of this initialization span, it either + * places the object to Ready or Limited state or calls the object's + * VirtualBoxBase::uninit() method which is supposed to place the object + * back to the NotReady state using the AutoUninitSpan class. + * + * The initial result status of the initialization span is determined by the + * @a aResult argument of the AutoInitSpan constructor (Result::Failed by + * default). Inside the initialization span, the success status can be set + * to Result::Succeeded using #setSucceeded(), to to Result::Limited using + * #setLimited() or to Result::Failed using #setFailed(). Please don't + * forget to set the correct success status before getting the AutoInitSpan + * variable destroyed (for example, by performing an early return from + * the init() method)! + * + * Note that if an instance of this class gets constructed when the object + * is in the state other than NotReady, #isOk() returns |false| and methods + * of this class do nothing: the state transition is not performed. + * + * A typical usage pattern is: + * <code> + * HRESULT Component::init() + * { + * AutoInitSpan autoInitSpan(this); + * AssertReturn(autoInitSpan.isOk(), E_FAIL); + * ... + * if (FAILED(rc)) + * return rc; + * ... + * if (SUCCEEDED(rc)) + * autoInitSpan.setSucceeded(); + * return rc; + * } + * </code> + * + * @note Never create instances of this class outside init() methods of + * VirtualBoxBase subclasses and never pass anything other than |this| + * as the argument to the constructor! + */ +class AutoInitSpan +{ +public: + + enum Result { Failed = 0x0, Succeeded = 0x1, Limited = 0x2 }; + + AutoInitSpan(VirtualBoxBase *aObj, Result aResult = Failed); + ~AutoInitSpan(); + + /** + * Returns |true| if this instance has been created at the right moment + * (when the object was in the NotReady state) and |false| otherwise. + */ + bool isOk() const { return mOk; } + + /** + * Sets the initialization status to Succeeded to indicates successful + * initialization. The AutoInitSpan destructor will place the managed + * VirtualBoxBase object to the Ready state. + */ + void setSucceeded() { mResult = Succeeded; } + + /** + * Sets the initialization status to Succeeded to indicate limited + * (partly successful) initialization. The AutoInitSpan destructor will + * place the managed VirtualBoxBase object to the Limited state. + */ + void setLimited() { mResult = Limited; } + + /** + * Sets the initialization status to Succeeded to indicate limited + * (partly successful) initialization but also adds the initialization + * error if required for further reporting. The AutoInitSpan destructor + * will place the managed VirtualBoxBase object to the Limited state. + */ + void setLimited(HRESULT rc) + { + mResult = Limited; + mFailedRC = rc; + mpFailedEI = new ErrorInfo(); + } + + /** + * Sets the initialization status to Failure to indicates failed + * initialization. The AutoInitSpan destructor will place the managed + * VirtualBoxBase object to the InitFailed state and will automatically + * call its uninit() method which is supposed to place the object back + * to the NotReady state using AutoUninitSpan. + */ + void setFailed(HRESULT rc = E_ACCESSDENIED) + { + mResult = Failed; + mFailedRC = rc; + mpFailedEI = new ErrorInfo(); + } + + /** Returns the current initialization result. */ + Result result() { return mResult; } + +private: + + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoInitSpan); + DECLARE_CLS_NEW_DELETE_NOOP(AutoInitSpan); + + VirtualBoxBase *mObj; + Result mResult : 3; // must be at least total number of bits + 1 (sign) + bool mOk : 1; + HRESULT mFailedRC; + ErrorInfo *mpFailedEI; +}; + +/** + * Smart class to enclose the state transition Limited->InInit->Ready. + * + * The purpose of this span is to protect object re-initialization. + * + * Instances must be created as a stack-based variable taking |this| pointer + * as the argument at the beginning of methods of VirtualBoxBase + * subclasses that try to re-initialize the object to bring it to the Ready + * state (full functionality) after partial initialization (limited + * functionality). When this variable is created, it automatically places + * the object to the InInit state. + * + * When the created variable goes out of scope (i.e. gets destroyed), + * depending on the success status of this initialization span, it either + * places the object to the Ready state or brings it back to the Limited + * state. + * + * The initial success status of the re-initialization span is |false|. In + * order to make it successful, #setSucceeded() must be called before the + * instance is destroyed. + * + * Note that if an instance of this class gets constructed when the object + * is in the state other than Limited, #isOk() returns |false| and methods + * of this class do nothing: the state transition is not performed. + * + * A typical usage pattern is: + * <code> + * HRESULT Component::reinit() + * { + * AutoReinitSpan autoReinitSpan(this); + * AssertReturn(autoReinitSpan.isOk(), E_FAIL); + * ... + * if (FAILED(rc)) + * return rc; + * ... + * if (SUCCEEDED(rc)) + * autoReinitSpan.setSucceeded(); + * return rc; + * } + * </code> + * + * @note Never create instances of this class outside re-initialization + * methods of VirtualBoxBase subclasses and never pass anything other than + * |this| as the argument to the constructor! + */ +class AutoReinitSpan +{ +public: + + AutoReinitSpan(VirtualBoxBase *aObj); + ~AutoReinitSpan(); + + /** + * Returns |true| if this instance has been created at the right moment + * (when the object was in the Limited state) and |false| otherwise. + */ + bool isOk() const { return mOk; } + + /** + * Sets the re-initialization status to Succeeded to indicates + * successful re-initialization. The AutoReinitSpan destructor will place + * the managed VirtualBoxBase object to the Ready state. + */ + void setSucceeded() { mSucceeded = true; } + +private: + + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoReinitSpan); + DECLARE_CLS_NEW_DELETE_NOOP(AutoReinitSpan); + + VirtualBoxBase *mObj; + bool mSucceeded : 1; + bool mOk : 1; +}; + +/** + * Smart class to enclose the state transition Ready->InUninit->NotReady, + * InitFailed->InUninit->NotReady. + * + * The purpose of this span is to protect object uninitialization. + * + * Instances must be created as a stack-based variable taking |this| pointer + * as the argument at the beginning of uninit() methods of VirtualBoxBase + * subclasses. When this variable is created it automatically places the + * object to the InUninit state, unless it is already in the NotReady state + * as indicated by #uninitDone() returning |true|. In the latter case, the + * uninit() method must immediately return because there should be nothing + * to uninitialize. + * + * When this variable goes out of scope (i.e. gets destroyed), it places the + * object to NotReady state. + * + * A typical usage pattern is: + * <code> + * void Component::uninit() + * { + * AutoUninitSpan autoUninitSpan(this); + * if (autoUninitSpan.uninitDone()) + * return; + * ... + * } + * </code> + * + * @note The constructor of this class blocks the current thread execution + * until the number of callers added to the object using + * ObjectState::addCaller() or AutoCaller drops to zero. For this reason, + * it is forbidden to create instances of this class (or call uninit()) + * within the AutoCaller or ObjectState::addCaller() scope because it is + * a guaranteed deadlock. + * + * @note Never create instances of this class outside uninit() methods and + * never pass anything other than |this| as the argument to the + * constructor! + */ +class AutoUninitSpan +{ +public: + + AutoUninitSpan(VirtualBoxBase *aObj, bool fTry = false); + ~AutoUninitSpan(); + + /** |true| when uninit() is called as a result of init() failure */ + bool initFailed() { return mInitFailed; } + + /** |true| when uninit() has already been called (so the object is NotReady) */ + bool uninitDone() { return mUninitDone; } + + /** |true| when uninit() has failed, relevant only if it was a "try uninit" */ + bool uninitFailed() { return mUninitFailed; } + + void setSucceeded(); + +private: + + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoUninitSpan); + DECLARE_CLS_NEW_DELETE_NOOP(AutoUninitSpan); + + VirtualBoxBase *mObj; + bool mInitFailed : 1; + bool mUninitDone : 1; + bool mUninitFailed : 1; +}; + +#endif /* !MAIN_INCLUDED_AutoCaller_h */ diff --git a/src/VBox/Main/include/AutoStateDep.h b/src/VBox/Main/include/AutoStateDep.h new file mode 100644 index 00000000..47a6d23f --- /dev/null +++ b/src/VBox/Main/include/AutoStateDep.h @@ -0,0 +1,214 @@ +/* $Id: AutoStateDep.h $ */ + +#ifndef MAIN_INCLUDED_AutoStateDep_h +#define MAIN_INCLUDED_AutoStateDep_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/** @file + * + * AutoStateDep template classes, formerly in MachineImpl.h. Use these if + * you need to ensure that the machine state does not change over a certain + * period of time. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + /** + * Helper class that safely manages the machine state dependency by + * calling Machine::addStateDependency() on construction and + * Machine::releaseStateDependency() on destruction. Intended for Machine + * children. The usage pattern is: + * + * @code + * AutoCaller autoCaller(this); + * if (FAILED(autoCaller.rc())) return autoCaller.rc(); + * + * Machine::AutoStateDependency<MutableStateDep> adep(mParent); + * if (FAILED(stateDep.rc())) return stateDep.rc(); + * ... + * // code that depends on the particular machine state + * ... + * @endcode + * + * Note that it is more convenient to use the following individual + * shortcut classes instead of using this template directly: + * AutoAnyStateDependency, AutoMutableStateDependency, + * AutoMutableOrSavedStateDependency, AutoMutableOrRunningStateDependency + * or AutoMutableOrSavedOrRunningStateDependency. The usage pattern is + * exactly the same as above except that there is no need to specify the + * template argument because it is already done by the shortcut class. + * + * @param taDepType Dependency type to manage. + */ + template <Machine::StateDependency taDepType = Machine::AnyStateDep> + class AutoStateDependency + { + public: + + AutoStateDependency(Machine *aThat) + : mThat(aThat), mRC(S_OK), + mMachineState(MachineState_Null), + mRegistered(FALSE) + { + Assert(aThat); + mRC = aThat->i_addStateDependency(taDepType, &mMachineState, + &mRegistered); + } + ~AutoStateDependency() + { + if (SUCCEEDED(mRC)) + mThat->i_releaseStateDependency(); + } + + /** Decreases the number of dependencies before the instance is + * destroyed. Note that will reset #rc() to E_FAIL. */ + void release() + { + AssertReturnVoid(SUCCEEDED(mRC)); + mThat->i_releaseStateDependency(); + mRC = E_FAIL; + } + + /** Restores the number of callers after by #release(). #rc() will be + * reset to the result of calling addStateDependency() and must be + * rechecked to ensure the operation succeeded. */ + void add() + { + AssertReturnVoid(!SUCCEEDED(mRC)); + mRC = mThat->i_addStateDependency(taDepType, &mMachineState, + &mRegistered); + } + + /** Returns the result of Machine::addStateDependency(). */ + HRESULT rc() const { return mRC; } + + /** Shortcut to SUCCEEDED(rc()). */ + bool isOk() const { return SUCCEEDED(mRC); } + + /** Returns the machine state value as returned by + * Machine::addStateDependency(). */ + MachineState_T machineState() const { return mMachineState; } + + /** Returns the machine state value as returned by + * Machine::addStateDependency(). */ + BOOL machineRegistered() const { return mRegistered; } + + protected: + + Machine *mThat; + HRESULT mRC; + MachineState_T mMachineState; + BOOL mRegistered; + + private: + + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoStateDependency); + DECLARE_CLS_NEW_DELETE_NOOP(AutoStateDependency); + }; + + /** + * Shortcut to AutoStateDependency<AnyStateDep>. + * See AutoStateDependency to get the usage pattern. + * + * Accepts any machine state and guarantees the state won't change before + * this object is destroyed. If the machine state cannot be protected (as + * a result of the state change currently in progress), this instance's + * #rc() method will indicate a failure, and the caller is not allowed to + * rely on any particular machine state and should return the failed + * result code to the upper level. + */ + typedef AutoStateDependency<Machine::AnyStateDep> AutoAnyStateDependency; + + /** + * Shortcut to AutoStateDependency<MutableStateDep>. + * See AutoStateDependency to get the usage pattern. + * + * Succeeds only if the machine state is in one of the mutable states, and + * guarantees the given mutable state won't change before this object is + * destroyed. If the machine is not mutable, this instance's #rc() method + * will indicate a failure, and the caller is not allowed to rely on any + * particular machine state and should return the failed result code to + * the upper level. + * + * Intended to be used within all setter methods of IMachine + * children objects (DVDDrive, NetworkAdapter, AudioAdapter, etc.) to + * provide data protection and consistency. There must be no VM process, + * i.e. use for settings changes which are valid when the VM is shut down. + */ + typedef AutoStateDependency<Machine::MutableStateDep> AutoMutableStateDependency; + + /** + * Shortcut to AutoStateDependency<MutableOrSavedStateDep>. + * See AutoStateDependency to get the usage pattern. + * + * Succeeds only if the machine state is in one of the mutable states, or + * if the machine is in the Saved state, and guarantees the given mutable + * state won't change before this object is destroyed. If the machine is + * not mutable, this instance's #rc() method will indicate a failure, and + * the caller is not allowed to rely on any particular machine state and + * should return the failed result code to the upper level. + * + * Intended to be used within setter methods of IMachine + * children objects that may operate on shut down or Saved machines. + */ + typedef AutoStateDependency<Machine::MutableOrSavedStateDep> AutoMutableOrSavedStateDependency; + + /** + * Shortcut to AutoStateDependency<MutableOrRunningStateDep>. + * See AutoStateDependency to get the usage pattern. + * + * Succeeds only if the machine state is in one of the mutable states, or + * if the machine is in the Running or Paused state, and guarantees the + * given mutable state won't change before this object is destroyed. If + * the machine is not mutable, this instance's #rc() method will indicate + * a failure, and the caller is not allowed to rely on any particular + * machine state and should return the failed result code to the upper + * level. + * + * Intended to be used within setter methods of IMachine + * children objects that may operate on shut down or running machines. + */ + typedef AutoStateDependency<Machine::MutableOrRunningStateDep> AutoMutableOrRunningStateDependency; + + /** + * Shortcut to AutoStateDependency<MutableOrSavedOrRunningStateDep>. + * See AutoStateDependency to get the usage pattern. + * + * Succeeds only if the machine state is in one of the mutable states, or + * if the machine is in the Running, Paused or Saved state, and guarantees + * the given mutable state won't change before this object is destroyed. + * If the machine is not mutable, this instance's #rc() method will + * indicate a failure, and the caller is not allowed to rely on any + * particular machine state and should return the failed result code to + * the upper level. + * + * Intended to be used within setter methods of IMachine + * children objects that may operate on shut down, running or saved + * machines. + */ + typedef AutoStateDependency<Machine::MutableOrSavedOrRunningStateDep> AutoMutableOrSavedOrRunningStateDependency; + +#endif /* !MAIN_INCLUDED_AutoStateDep_h */ + diff --git a/src/VBox/Main/include/AutostartDb.h b/src/VBox/Main/include/AutostartDb.h new file mode 100644 index 00000000..01a3c7bd --- /dev/null +++ b/src/VBox/Main/include/AutostartDb.h @@ -0,0 +1,109 @@ +/* $Id: AutostartDb.h $ */ +/** @file + * Main - Autostart database Interfaces. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_AutostartDb_h +#define MAIN_INCLUDED_AutostartDb_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/critsect.h> + +class AutostartDb +{ + public: + + AutostartDb(); + ~AutostartDb(); + + /** + * Sets the path to the autostart database. + * + * @returns VBox status code. + * @param pszAutostartDbPathNew Path to the autostart database. + */ + int setAutostartDbPath(const char *pszAutostartDbPathNew); + + /** + * Add a autostart VM to the global database. + * + * @returns VBox status code. + * @retval VERR_PATH_NOT_FOUND if the autostart database directory is not set. + * @param pszVMId ID of the VM to add. + */ + int addAutostartVM(const char *pszVMId); + + /** + * Remove a autostart VM from the global database. + * + * @returns VBox status code. + * @retval VERR_PATH_NOT_FOUND if the autostart database directory is not set. + * @param pszVMId ID of the VM to remove. + */ + int removeAutostartVM(const char *pszVMId); + + /** + * Add a autostop VM to the global database. + * + * @returns VBox status code. + * @retval VERR_PATH_NOT_FOUND if the autostart database directory is not set. + * @param pszVMId ID of the VM to add. + */ + int addAutostopVM(const char *pszVMId); + + /** + * Remove a autostop VM from the global database. + * + * @returns VBox status code. + * @retval VERR_PATH_NOT_FOUND if the autostart database directory is not set. + * @param pszVMId ID of the VM to remove. + */ + int removeAutostopVM(const char *pszVMId); + + private: + +#ifdef RT_OS_LINUX + /** Critical section protecting the database against concurrent access. */ + RTCRITSECT CritSect; + /** Path to the autostart database. */ + char *m_pszAutostartDbPath; + + /** + * Autostart database modification worker. + * + * @returns VBox status code. + * @param fAutostart Flag whether the autostart or autostop database is modified. + * @param fAddVM Flag whether a VM is added or removed from the database. + */ + int autostartModifyDb(bool fAutostart, bool fAddVM); +#endif +}; + +#endif /* !MAIN_INCLUDED_AutostartDb_h */ + diff --git a/src/VBox/Main/include/BIOSSettingsImpl.h b/src/VBox/Main/include/BIOSSettingsImpl.h new file mode 100644 index 00000000..ad6eeded --- /dev/null +++ b/src/VBox/Main/include/BIOSSettingsImpl.h @@ -0,0 +1,102 @@ +/* $Id: BIOSSettingsImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation - Machine BIOS settings. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_BIOSSettingsImpl_h +#define MAIN_INCLUDED_BIOSSettingsImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "BIOSSettingsWrap.h" + +class GuestOSType; + +namespace settings +{ + struct BIOSSettings; +} + +class ATL_NO_VTABLE BIOSSettings : + public BIOSSettingsWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(BIOSSettings) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *parent); + HRESULT init(Machine *parent, BIOSSettings *that); + HRESULT initCopy(Machine *parent, BIOSSettings *that); + void uninit(); + + // public methods for internal purposes only + HRESULT i_loadSettings(const settings::BIOSSettings &data); + HRESULT i_saveSettings(settings::BIOSSettings &data); + + void i_rollback(); + void i_commit(); + void i_copyFrom(BIOSSettings *aThat); + void i_applyDefaults(GuestOSType *aOsType); + +private: + + // wrapped IBIOSettings properties + HRESULT getLogoFadeIn(BOOL *enabled); + HRESULT setLogoFadeIn(BOOL enable); + HRESULT getLogoFadeOut(BOOL *enabled); + HRESULT setLogoFadeOut(BOOL enable); + HRESULT getLogoDisplayTime(ULONG *displayTime); + HRESULT setLogoDisplayTime(ULONG displayTime); + HRESULT getLogoImagePath(com::Utf8Str &imagePath); + HRESULT setLogoImagePath(const com::Utf8Str &imagePath); + HRESULT getBootMenuMode(BIOSBootMenuMode_T *bootMenuMode); + HRESULT setBootMenuMode(BIOSBootMenuMode_T bootMenuMode); + HRESULT getACPIEnabled(BOOL *enabled); + HRESULT setACPIEnabled(BOOL enable); + HRESULT getIOAPICEnabled(BOOL *aIOAPICEnabled); + HRESULT setIOAPICEnabled(BOOL aIOAPICEnabled); + HRESULT getAPICMode(APICMode_T *aAPICMode); + HRESULT setAPICMode(APICMode_T aAPICMode); + HRESULT getTimeOffset(LONG64 *offset); + HRESULT setTimeOffset(LONG64 offset); + HRESULT getPXEDebugEnabled(BOOL *enabled); + HRESULT setPXEDebugEnabled(BOOL enable); + HRESULT getSMBIOSUuidLittleEndian(BOOL *enabled); + HRESULT setSMBIOSUuidLittleEndian(BOOL enable); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_BIOSSettingsImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/BandwidthControlImpl.h b/src/VBox/Main/include/BandwidthControlImpl.h new file mode 100644 index 00000000..dfafb22e --- /dev/null +++ b/src/VBox/Main/include/BandwidthControlImpl.h @@ -0,0 +1,111 @@ +/* $Id: BandwidthControlImpl.h $ */ +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_BandwidthControlImpl_h +#define MAIN_INCLUDED_BandwidthControlImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "BandwidthControlWrap.h" + +class BandwidthGroup; + +namespace settings +{ + struct IOSettings; +} + +class ATL_NO_VTABLE BandwidthControl : + public BandwidthControlWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(BandwidthControl) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent); + HRESULT init(Machine *aParent, BandwidthControl *aThat); + HRESULT initCopy(Machine *aParent, BandwidthControl *aThat); + void uninit(); + + // public internal methods + HRESULT i_loadSettings(const settings::IOSettings &data); + HRESULT i_saveSettings(settings::IOSettings &data); + void i_rollback(); + void i_commit(); + void i_copyFrom(BandwidthControl *aThat); + Machine *i_getMachine() const; + HRESULT i_getBandwidthGroupByName(const Utf8Str &aName, + ComObjPtr<BandwidthGroup> &aBandwidthGroup, + bool aSetError /* = false */); + +private: + + // wrapped IBandwidthControl properties + HRESULT getNumGroups(ULONG *aNumGroups); + + // wrapped IBandwidthControl methods + HRESULT createBandwidthGroup(const com::Utf8Str &aName, + BandwidthGroupType_T aType, + LONG64 aMaxBytesPerSec); + HRESULT deleteBandwidthGroup(const com::Utf8Str &aName); + HRESULT getBandwidthGroup(const com::Utf8Str &aName, + ComPtr<IBandwidthGroup> &aBandwidthGroup); + HRESULT getAllBandwidthGroups(std::vector<ComPtr<IBandwidthGroup> > &aBandwidthGroups); + + // Data + typedef std::list< ComObjPtr<BandwidthGroup> > BandwidthGroupList; + + struct Data + { + Data(Machine *pMachine) + : pParent(pMachine) + { } + + ~Data() + {}; + + Machine * const pParent; + + // peer machine's bandwidth control + const ComObjPtr<BandwidthControl> pPeer; + + // the following fields need special backup/rollback/commit handling, + // so they cannot be a part of BackupableData + Backupable<BandwidthGroupList> llBandwidthGroups; + }; + + Data *m; +}; + +#endif /* !MAIN_INCLUDED_BandwidthControlImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/BandwidthGroupImpl.h b/src/VBox/Main/include/BandwidthGroupImpl.h new file mode 100644 index 00000000..6038b1d3 --- /dev/null +++ b/src/VBox/Main/include/BandwidthGroupImpl.h @@ -0,0 +1,115 @@ +/* $Id: BandwidthGroupImpl.h $ */ +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_BandwidthGroupImpl_h +#define MAIN_INCLUDED_BandwidthGroupImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/settings.h> +#include "BandwidthControlImpl.h" +#include "BandwidthGroupWrap.h" + + +class ATL_NO_VTABLE BandwidthGroup : + public BandwidthGroupWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(BandwidthGroup) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(BandwidthControl *aParent, + const com::Utf8Str &aName, + BandwidthGroupType_T aType, + LONG64 aMaxBytesPerSec); + HRESULT init(BandwidthControl *aParent, BandwidthGroup *aThat, bool aReshare = false); + HRESULT initCopy(BandwidthControl *aParent, BandwidthGroup *aThat); + void uninit(); + + // public methods only for internal purposes + void i_rollback(); + void i_commit(); + void i_unshare(); + void i_reference(); + void i_release(); + + ComObjPtr<BandwidthGroup> i_getPeer() { return m->pPeer; } + const Utf8Str &i_getName() const { return m->bd->mData.strName; } + BandwidthGroupType_T i_getType() const { return m->bd->mData.enmType; } + LONG64 i_getMaxBytesPerSec() const { return (LONG64)m->bd->mData.cMaxBytesPerSec; } + ULONG i_getReferences() const { return m->bd->cReferences; } + +private: + + // wrapped IBandwidthGroup properties + HRESULT getName(com::Utf8Str &aName); + HRESULT getType(BandwidthGroupType_T *aType); + HRESULT getReference(ULONG *aReferences); + HRESULT getMaxBytesPerSec(LONG64 *aMaxBytesPerSec); + HRESULT setMaxBytesPerSec(LONG64 MaxBytesPerSec); + + //////////////////////////////////////////////////////////////////////////////// + //// + //// private member data definition + //// + ////////////////////////////////////////////////////////////////////////////////// + // + struct BackupableBandwidthGroupData + { + BackupableBandwidthGroupData() + : cReferences(0) + { } + + settings::BandwidthGroup mData; + ULONG cReferences; + }; + + struct Data + { + Data(BandwidthControl * const aBandwidthControl) + : pParent(aBandwidthControl), + pPeer(NULL) + { } + + BandwidthControl * const pParent; + ComObjPtr<BandwidthGroup> pPeer; + + // use the XML settings structure in the members for simplicity + Backupable<BackupableBandwidthGroupData> bd; + }; + + Data *m; +}; + +#endif /* !MAIN_INCLUDED_BandwidthGroupImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/BusAssignmentManager.h b/src/VBox/Main/include/BusAssignmentManager.h new file mode 100644 index 00000000..13bc0a3d --- /dev/null +++ b/src/VBox/Main/include/BusAssignmentManager.h @@ -0,0 +1,90 @@ +/* $Id: BusAssignmentManager.h $ */ +/** @file + * VirtualBox bus slots assignment manager + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_BusAssignmentManager_h +#define MAIN_INCLUDED_BusAssignmentManager_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VBox/types.h" +#include "VBox/pci.h" +#include "VirtualBoxBase.h" +#include <vector> + +class BusAssignmentManager +{ +private: + struct State; + State *pState; + + BusAssignmentManager(); + virtual ~BusAssignmentManager(); + + HRESULT assignPCIDeviceImpl(const char *pszDevName, PCFGMNODE pCfg, PCIBusAddress& GuestAddress, + PCIBusAddress HostAddress, bool fGuestAddressRequired = false); + +public: + struct PCIDeviceInfo + { + com::Utf8Str strDeviceName; + PCIBusAddress guestAddress; + PCIBusAddress hostAddress; + }; + + static BusAssignmentManager *createInstance(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType); + virtual void AddRef(); + virtual void Release(); + + virtual HRESULT assignHostPCIDevice(const char *pszDevName, PCFGMNODE pCfg, PCIBusAddress HostAddress, + PCIBusAddress& GuestAddress, bool fAddressRequired = false) + { + return assignPCIDeviceImpl(pszDevName, pCfg, GuestAddress, HostAddress, fAddressRequired); + } + + virtual HRESULT assignPCIDevice(const char *pszDevName, PCFGMNODE pCfg, PCIBusAddress& Address, bool fAddressRequired = false) + { + PCIBusAddress HostAddress; + return assignPCIDeviceImpl(pszDevName, pCfg, Address, HostAddress, fAddressRequired); + } + + virtual HRESULT assignPCIDevice(const char *pszDevName, PCFGMNODE pCfg) + { + PCIBusAddress GuestAddress; + PCIBusAddress HostAddress; + return assignPCIDeviceImpl(pszDevName, pCfg, GuestAddress, HostAddress, false); + } + virtual bool findPCIAddress(const char *pszDevName, int iInstance, PCIBusAddress& Address); + virtual bool hasPCIDevice(const char *pszDevName, int iInstance) + { + PCIBusAddress Address; + return findPCIAddress(pszDevName, iInstance, Address); + } + virtual void listAttachedPCIDevices(std::vector<PCIDeviceInfo> &aAttached); +}; + +#endif /* !MAIN_INCLUDED_BusAssignmentManager_h */ diff --git a/src/VBox/Main/include/CPUProfileImpl.h b/src/VBox/Main/include/CPUProfileImpl.h new file mode 100644 index 00000000..7f647073 --- /dev/null +++ b/src/VBox/Main/include/CPUProfileImpl.h @@ -0,0 +1,75 @@ +/* $Id: CPUProfileImpl.h $ */ +/** @file + * VirtualBox Main - interface for CPU profiles, VBoxSVC. + */ + +/* + * Copyright (C) 2020-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_CPUProfileImpl_h +#define MAIN_INCLUDED_CPUProfileImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "CPUProfileWrap.h" + +struct CPUMDBENTRY; + +/** + * A CPU profile. + */ +class ATL_NO_VTABLE CPUProfile + : public CPUProfileWrap +{ +public: + /** @name COM and internal init/term/mapping cruft + * @{ */ + DECLARE_COMMON_CLASS_METHODS(CPUProfile) + HRESULT FinalConstruct(); + void FinalRelease(); + HRESULT initFromDbEntry(struct CPUMDBENTRY const *a_pDbEntry) RT_NOEXCEPT; + void uninit(); + /** @} */ + + bool i_match(CPUArchitecture_T a_enmArchitecture, CPUArchitecture_T a_enmSecondaryArch, + const com::Utf8Str &a_strNamePattern) const RT_NOEXCEPT; + +private: + /** @name Wrapped ICPUProfile attributes + * @{ */ + HRESULT getName(com::Utf8Str &aName) RT_OVERRIDE; + HRESULT getFullName(com::Utf8Str &aFullName) RT_OVERRIDE; + HRESULT getArchitecture(CPUArchitecture_T *aArchitecture) RT_OVERRIDE; + /** @} */ + + /** @name Data + * @{ */ + com::Utf8Str m_strName; + com::Utf8Str m_strFullName; + CPUArchitecture_T m_enmArchitecture; + /** @} */ +}; + +#endif /* !MAIN_INCLUDED_CPUProfileImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/CertificateImpl.h b/src/VBox/Main/include/CertificateImpl.h new file mode 100644 index 00000000..d17c5b7a --- /dev/null +++ b/src/VBox/Main/include/CertificateImpl.h @@ -0,0 +1,112 @@ +/* $Id: CertificateImpl.h $ */ +/** @file + * VirtualBox COM ICertificate implementation. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_CertificateImpl_h +#define MAIN_INCLUDED_CertificateImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* VBox includes */ +#include <iprt/crypto/x509.h> +#include "CertificateWrap.h" + +#include <vector> + +using namespace std; + +/** + * Implemenation of ICertificate. + * + * This implemenation is a very thin wrapper around an immutable + * RTCRX509CERTIFICATE and a few caller stated views. + * + * The views are whether the caller thinks the certificate is trustworthly, and + * whether the caller thinks it's expired or not. The caller could be sitting + * on more information, like timestamp and intermediate certificates, that helps + * inform the caller's view on these two topics. + * + * @remarks It could be helpful to let the caller also add certificate paths + * showing how this certificate ends up being trusted. However, that's + * possibly quite some work and will have to wait till required... + */ +class ATL_NO_VTABLE Certificate + : public CertificateWrap +{ + +public: + + DECLARE_COMMON_CLASS_METHODS(Certificate) + + HRESULT initCertificate(PCRTCRX509CERTIFICATE a_pCert, bool a_fTrusted, bool a_fExpired); + void uninit(); + + HRESULT FinalConstruct(); + void FinalRelease(); + +private: + // Wrapped ICertificate properties + HRESULT getVersionNumber(CertificateVersion_T *aVersionNumber); + HRESULT getSerialNumber(com::Utf8Str &aSerialNumber); + HRESULT getSignatureAlgorithmOID(com::Utf8Str &aSignatureAlgorithmOID); + HRESULT getSignatureAlgorithmName(com::Utf8Str &aSignatureAlgorithmName); + HRESULT getPublicKeyAlgorithmOID(com::Utf8Str &aPublicKeyAlgorithmOID); + HRESULT getPublicKeyAlgorithm(com::Utf8Str &aPublicKeyAlgorithm); + HRESULT getIssuerName(std::vector<com::Utf8Str> &aIssuerName); + HRESULT getSubjectName(std::vector<com::Utf8Str> &aSubjectName); + HRESULT getFriendlyName(com::Utf8Str &aFriendlyName); + HRESULT getValidityPeriodNotBefore(com::Utf8Str &aValidityPeriodNotBefore); + HRESULT getValidityPeriodNotAfter(com::Utf8Str &aValidityPeriodNotAfter); + HRESULT getSubjectPublicKey(std::vector<BYTE> &aSubjectPublicKey); + HRESULT getIssuerUniqueIdentifier(com::Utf8Str &aIssuerUniqueIdentifier); + HRESULT getSubjectUniqueIdentifier(com::Utf8Str &aSubjectUniqueIdentifier); + HRESULT getCertificateAuthority(BOOL *aCertificateAuthority); + HRESULT getKeyUsage(ULONG *aKeyUsage); + HRESULT getExtendedKeyUsage(std::vector<com::Utf8Str> &aExtendedKeyUsage); + HRESULT getRawCertData(std::vector<BYTE> &aRawCertData); + HRESULT getSelfSigned(BOOL *aSelfSigned); + HRESULT getTrusted(BOOL *aTrusted); + HRESULT getExpired(BOOL *aExpired); + + // Wrapped ICertificate methods + HRESULT isCurrentlyExpired(BOOL *aResult); + HRESULT queryInfo(LONG aWhat, com::Utf8Str &aResult); + + // Methods extracting COM data from the certificate object + HRESULT i_getAlgorithmName(PCRTCRX509ALGORITHMIDENTIFIER a_pAlgId, com::Utf8Str &a_rReturn); + HRESULT i_getX509Name(PCRTCRX509NAME a_pName, std::vector<com::Utf8Str> &a_rReturn); + HRESULT i_getTime(PCRTASN1TIME a_pTime, com::Utf8Str &a_rReturn); + HRESULT i_getUniqueIdentifier(PCRTCRX509UNIQUEIDENTIFIER a_pUniqueId, com::Utf8Str &a_rReturn); + HRESULT i_getEncodedBytes(PRTASN1CORE a_pAsn1Obj, std::vector<BYTE> &a_rReturn); + + struct Data; + /** Pointer to the private instance data */ + Data *m; +}; + +#endif /* !MAIN_INCLUDED_CertificateImpl_h */ + diff --git a/src/VBox/Main/include/ClientToken.h b/src/VBox/Main/include/ClientToken.h new file mode 100644 index 00000000..85681952 --- /dev/null +++ b/src/VBox/Main/include/ClientToken.h @@ -0,0 +1,118 @@ +/* $Id: ClientToken.h $ */ + +/** @file + * + * VirtualBox API client session token abstraction + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ClientToken_h +#define MAIN_INCLUDED_ClientToken_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/ptr.h> +#include <VBox/com/AutoLock.h> + +#include "MachineImpl.h" +#ifdef VBOX_WITH_GENERIC_SESSION_WATCHER +# include "TokenImpl.h" +#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + +#if defined(RT_OS_WINDOWS) +# define CTTOKENARG NULL +# define CTTOKENTYPE HANDLE +#elif defined(RT_OS_OS2) +# define CTTOKENARG NULLHANDLE +# define CTTOKENTYPE HMTX +#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) +# define CTTOKENARG -1 +# define CTTOKENTYPE int +#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER) +# define CTTOKENARG NULL +# define CTTOKENTYPE MachineToken * +#else +# error "Port me!" +#endif + +/** + * Class which represents a token which can be used to check for client + * crashes and similar purposes. + */ +class Machine::ClientToken +{ +public: + /** + * Constructor which creates a usable instance + * + * @param pMachine Reference to Machine object + * @param pSessionMachine Reference to corresponding SessionMachine object + */ + ClientToken(const ComObjPtr<Machine> &pMachine, SessionMachine *pSessionMachine); + + /** + * Default destructor. Cleans everything up. + */ + ~ClientToken(); + + /** + * Check if object contains a usable token. + */ + bool isReady(); + + /** + * Query token ID, which is a unique string value for this token. Do not + * assume any specific content/format, it is opaque information. + */ + void getId(Utf8Str &strId); + + /** + * Query token, which is platform dependent. + */ + CTTOKENTYPE getToken(); + +#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER + /** + * Release token now. Returns information if the client has terminated. + */ + bool release(); +#endif /* !VBOX_WITH_GENERIC_SESSION_WATCHER */ + +private: + /** + * Default constructor. Don't use, will not create a sensible instance. + */ + ClientToken(); + + Machine *mMachine; + CTTOKENTYPE mClientToken; + Utf8Str mClientTokenId; +#ifdef VBOX_WITH_GENERIC_SESSION_WATCHER + bool mClientTokenPassed; +#endif +}; + +#endif /* !MAIN_INCLUDED_ClientToken_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/ClientTokenHolder.h b/src/VBox/Main/include/ClientTokenHolder.h new file mode 100644 index 00000000..01f0e599 --- /dev/null +++ b/src/VBox/Main/include/ClientTokenHolder.h @@ -0,0 +1,112 @@ +/* $Id: ClientTokenHolder.h $ */ + +/** @file + * + * VirtualBox API client session token holder (in the client process) + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ClientTokenHolder_h +#define MAIN_INCLUDED_ClientTokenHolder_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "SessionImpl.h" + +#if defined(RT_OS_WINDOWS) +# define CTHSEMARG NULL +# define CTHSEMTYPE HANDLE +/* this second semaphore is only used on Windows */ +# define CTHTHREADSEMARG NULL +# define CTHTHREADSEMTYPE HANDLE +#elif defined(RT_OS_OS2) +# define CTHSEMARG NIL_RTSEMEVENT +# define CTHSEMTYPE RTSEMEVENT +#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) +# define CTHSEMARG -1 +# define CTHSEMTYPE int +#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER) +/* the token object based implementation needs no semaphores */ +#else +# error "Port me!" +#endif + + +/** + * Class which holds a client token. + */ +class Session::ClientTokenHolder +{ +public: +#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER + /** + * Constructor which creates a usable instance + * + * @param strTokenId String with identifier of the token + */ + ClientTokenHolder(const Utf8Str &strTokenId); +#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + /** + * Constructor which creates a usable instance + * + * @param aToken Reference to token object + */ + ClientTokenHolder(IToken *aToken); +#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + + /** + * Default destructor. Cleans everything up. + */ + ~ClientTokenHolder(); + + /** + * Check if object contains a usable token. + */ + bool isReady(); + +private: + /** + * Default constructor. Don't use, will not create a sensible instance. + */ + ClientTokenHolder(); + +#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER + Utf8Str mClientTokenId; +#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + ComPtr<IToken> mToken; +#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */ +#ifdef CTHSEMTYPE + CTHSEMTYPE mSem; +#endif +#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) + RTTHREAD mThread; +#endif +#ifdef RT_OS_WINDOWS + CTHTHREADSEMTYPE mThreadSem; +#endif +}; + +#endif /* !MAIN_INCLUDED_ClientTokenHolder_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/ClientWatcher.h b/src/VBox/Main/include/ClientWatcher.h new file mode 100644 index 00000000..84be5f7e --- /dev/null +++ b/src/VBox/Main/include/ClientWatcher.h @@ -0,0 +1,146 @@ +/* $Id: ClientWatcher.h $ */ +/** @file + * VirtualBox API client session watcher + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ClientWatcher_h +#define MAIN_INCLUDED_ClientWatcher_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + + +#include <list> +#include <VBox/com/ptr.h> +#include <VBox/com/AutoLock.h> + +#include "VirtualBoxImpl.h" + +#if defined(RT_OS_WINDOWS) +# define CWUPDATEREQARG NULL +# define CWUPDATEREQTYPE HANDLE +# define CW_MAX_CLIENTS _16K /**< Max number of clients we can watch (windows). */ +# ifndef DEBUG /* The debug version triggers worker thread code much much earlier. */ +# define CW_MAX_CLIENTS_PER_THREAD 63 /**< Max clients per watcher thread (windows). */ +# else +# define CW_MAX_CLIENTS_PER_THREAD 3 /**< Max clients per watcher thread (windows). */ +# endif +# define CW_MAX_HANDLES_PER_THREAD (CW_MAX_CLIENTS_PER_THREAD + 1) /**< Max handles per thread. */ + +#elif defined(RT_OS_OS2) +# define CWUPDATEREQARG NIL_RTSEMEVENT +# define CWUPDATEREQTYPE RTSEMEVENT + +#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER) +# define CWUPDATEREQARG NIL_RTSEMEVENT +# define CWUPDATEREQTYPE RTSEMEVENT + +#else +# error "Port me!" +#endif + +/** + * Class which checks for API clients which have crashed/exited, and takes + * the necessary cleanup actions. Singleton. + */ +class VirtualBox::ClientWatcher +{ +public: + /** + * Constructor which creates a usable instance + * + * @param pVirtualBox Reference to VirtualBox object + */ + ClientWatcher(const ComObjPtr<VirtualBox> &pVirtualBox); + + /** + * Default destructor. Cleans everything up. + */ + ~ClientWatcher(); + + bool isReady(); + + void update(); + void addProcess(RTPROCESS pid); + +private: + /** + * Default constructor. Don't use, will not create a sensible instance. + */ + ClientWatcher(); + + static DECLCALLBACK(int) worker(RTTHREAD hThreadSelf, void *pvUser); + uint32_t reapProcesses(void); + + VirtualBox *mVirtualBox; + RTTHREAD mThread; + CWUPDATEREQTYPE mUpdateReq; + util::RWLockHandle mLock; + + typedef std::list<RTPROCESS> ProcessList; + ProcessList mProcesses; + +#if defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER) + uint8_t mUpdateAdaptCtr; +#endif +#ifdef RT_OS_WINDOWS + /** Indicate a real update request is pending. + * To avoid race conditions this must be set before mUpdateReq is signalled and + * read after resetting mUpdateReq. */ + volatile bool mfUpdateReq; + /** Set when the worker threads are supposed to shut down. */ + volatile bool mfTerminate; + /** Number of active subworkers. + * When decremented to 0, subworker zero is signalled. */ + uint32_t volatile mcActiveSubworkers; + /** Number of valid handles in mahWaitHandles. */ + uint32_t mcWaitHandles; + /** The wait interval (usually INFINITE). */ + uint32_t mcMsWait; + /** Per subworker data. Subworker 0 is the main worker and does not have a + * pReq pointer since. */ + struct PerSubworker + { + /** The wait result. */ + DWORD dwWait; + /** The subworker index. */ + uint32_t iSubworker; + /** The subworker thread handle. */ + RTTHREAD hThread; + /** Self pointer (for worker thread). */ + VirtualBox::ClientWatcher *pSelf; + } maSubworkers[(CW_MAX_CLIENTS + CW_MAX_CLIENTS_PER_THREAD - 1) / CW_MAX_CLIENTS_PER_THREAD]; + /** Wait handle array. The mUpdateReq manual reset event handle is inserted + * every 64 entries, first entry being 0. */ + HANDLE mahWaitHandles[CW_MAX_CLIENTS + (CW_MAX_CLIENTS + CW_MAX_CLIENTS_PER_THREAD - 1) / CW_MAX_CLIENTS_PER_THREAD]; + + void subworkerWait(VirtualBox::ClientWatcher::PerSubworker *pSubworker, uint32_t cMsWait); + static DECLCALLBACK(int) subworkerThread(RTTHREAD hThreadSelf, void *pvUser); + void winResetHandleArray(uint32_t cProcHandles); +#endif +}; + +#endif /* !MAIN_INCLUDED_ClientWatcher_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/CloudGateway.h b/src/VBox/Main/include/CloudGateway.h new file mode 100644 index 00000000..9467a9f6 --- /dev/null +++ b/src/VBox/Main/include/CloudGateway.h @@ -0,0 +1,103 @@ +/* $Id: CloudGateway.h $ */ +/** @file + * Implementation of local and cloud gateway management. + */ + +/* + * Copyright (C) 2019-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_CloudGateway_h +#define MAIN_INCLUDED_CloudGateway_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +struct GatewayInfo +{ + Bstr mTargetVM; + Utf8Str mGatewayInstanceId; + Utf8Str mPublicSshKey; + Utf8Str mPrivateSshKey; + Bstr mCloudProvider; + Bstr mCloudProfile; + Utf8Str mCloudPublicIp; + Utf8Str mCloudSecondaryPublicIp; + RTMAC mCloudMacAddress; + RTMAC mLocalMacAddress; + int mAdapterSlot; + + HRESULT setCloudMacAddress(const Utf8Str& mac); + HRESULT setLocalMacAddress(const Utf8Str& mac); + + GatewayInfo() {} + + GatewayInfo(const GatewayInfo& other) + : mGatewayInstanceId(other.mGatewayInstanceId), + mPublicSshKey(other.mPublicSshKey), + mPrivateSshKey(other.mPrivateSshKey), + mCloudProvider(other.mCloudProvider), + mCloudProfile(other.mCloudProfile), + mCloudPublicIp(other.mCloudPublicIp), + mCloudSecondaryPublicIp(other.mCloudSecondaryPublicIp), + mCloudMacAddress(other.mCloudMacAddress), + mLocalMacAddress(other.mLocalMacAddress), + mAdapterSlot(other.mAdapterSlot) + {} + + GatewayInfo& operator=(const GatewayInfo& other) + { + mGatewayInstanceId = other.mGatewayInstanceId; + mPublicSshKey = other.mPublicSshKey; + mPrivateSshKey = other.mPrivateSshKey; + mCloudProvider = other.mCloudProvider; + mCloudProfile = other.mCloudProfile; + mCloudPublicIp = other.mCloudPublicIp; + mCloudSecondaryPublicIp = other.mCloudSecondaryPublicIp; + mCloudMacAddress = other.mCloudMacAddress; + mLocalMacAddress = other.mLocalMacAddress; + mAdapterSlot = other.mAdapterSlot; + return *this; + } + + void setNull() + { + mGatewayInstanceId.setNull(); + mPublicSshKey.setNull(); + mPrivateSshKey.setNull(); + mCloudProvider.setNull(); + mCloudProfile.setNull(); + mCloudPublicIp.setNull(); + mCloudSecondaryPublicIp.setNull(); + memset(&mCloudMacAddress, 0, sizeof(mCloudMacAddress)); + memset(&mLocalMacAddress, 0, sizeof(mLocalMacAddress)); + mAdapterSlot = -1; + } +}; + +class CloudNetwork; + +HRESULT startCloudGateway(ComPtr<IVirtualBox> virtualBox, ComPtr<ICloudNetwork> network, GatewayInfo& pGateways); +HRESULT stopCloudGateway(ComPtr<IVirtualBox> virtualBox, GatewayInfo& gateways); +HRESULT generateKeys(GatewayInfo& gateways); + +#endif /* !MAIN_INCLUDED_CloudGateway_h */ + diff --git a/src/VBox/Main/include/CloudNetworkImpl.h b/src/VBox/Main/include/CloudNetworkImpl.h new file mode 100644 index 00000000..ca22f6cf --- /dev/null +++ b/src/VBox/Main/include/CloudNetworkImpl.h @@ -0,0 +1,79 @@ +/* $Id: CloudNetworkImpl.h $ */ +/** @file + * ICloudNetwork implementation header, lives in VBoxSVC. + */ + +/* + * Copyright (C) 2019-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_CloudNetworkImpl_h +#define MAIN_INCLUDED_CloudNetworkImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "CloudNetworkWrap.h" + +namespace settings +{ + struct CloudNetwork; +} + +class ATL_NO_VTABLE CloudNetwork : + public CloudNetworkWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(CloudNetwork) + + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT init(VirtualBox *aVirtualBox, com::Utf8Str aName); + HRESULT i_loadSettings(const settings::CloudNetwork &data); + void uninit(); + HRESULT i_saveSettings(settings::CloudNetwork &data); + + // Internal methods + Utf8Str i_getNetworkName(); + Utf8Str i_getProvider(); + Utf8Str i_getProfile(); + Utf8Str i_getNetworkId(); +private: + + // Wrapped ICloudNetwork properties + HRESULT getNetworkName(com::Utf8Str &aNetworkName); + HRESULT setNetworkName(const com::Utf8Str &aNetworkName); + HRESULT getEnabled(BOOL *aEnabled); + HRESULT setEnabled(BOOL aEnabled); + HRESULT getProvider(com::Utf8Str &aProvider); + HRESULT setProvider(const com::Utf8Str &aProvider); + HRESULT getProfile(com::Utf8Str &aProfile); + HRESULT setProfile(const com::Utf8Str &aProfile); + HRESULT getNetworkId(com::Utf8Str &aNetworkId); + HRESULT setNetworkId(const com::Utf8Str &aNetworkId); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_CloudNetworkImpl_h */ diff --git a/src/VBox/Main/include/CloudProviderManagerImpl.h b/src/VBox/Main/include/CloudProviderManagerImpl.h new file mode 100644 index 00000000..43317c1c --- /dev/null +++ b/src/VBox/Main/include/CloudProviderManagerImpl.h @@ -0,0 +1,82 @@ +/* $Id: CloudProviderManagerImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2018-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_CloudProviderManagerImpl_h +#define MAIN_INCLUDED_CloudProviderManagerImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "CloudProviderManagerWrap.h" + +class ATL_NO_VTABLE CloudProviderManager + : public CloudProviderManagerWrap +{ +public: + CloudProviderManager(); + virtual ~CloudProviderManager(); + + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT init(VirtualBox *aVirtualBox); + void uninit(); + +#ifdef VBOX_WITH_EXTPACK + // Safe helpers, take care of caller and lock themselves. + bool i_canRemoveExtPack(IExtPack *aExtPack); + void i_addExtPack(IExtPack *aExtPack); +#endif + +private: + // wrapped ICloudProviderManager attributes and methods + HRESULT getProviders(std::vector<ComPtr<ICloudProvider> > &aProviders); + HRESULT getProviderById(const com::Guid &aProviderId, + ComPtr<ICloudProvider> &aProvider); + HRESULT getProviderByShortName(const com::Utf8Str &aProviderName, + ComPtr<ICloudProvider> &aProvider); + HRESULT getProviderByName(const com::Utf8Str &aProviderName, + ComPtr<ICloudProvider> &aProvider); + +private: +#ifdef VBOX_WITH_EXTPACK + typedef std::map<com::Utf8Str, ComPtr<ICloudProviderManager> > ExtPackNameCloudProviderManagerMap; + ExtPackNameCloudProviderManagerMap m_mapCloudProviderManagers; + + typedef std::vector<com::Utf8Str> ExtPackNameVec; + ExtPackNameVec m_astrExtPackNames; +#endif + + typedef std::vector<ComPtr<ICloudProvider> > CloudProviderVec; + CloudProviderVec m_apCloudProviders; + + VirtualBox * const m_pVirtualBox; +}; + +#endif /* !MAIN_INCLUDED_CloudProviderManagerImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/ConsoleImpl.h b/src/VBox/Main/include/ConsoleImpl.h new file mode 100644 index 00000000..9fb856d5 --- /dev/null +++ b/src/VBox/Main/include/ConsoleImpl.h @@ -0,0 +1,1192 @@ +/* $Id: ConsoleImpl.h $ */ +/** @file + * VBox Console COM Class definition + */ + +/* + * Copyright (C) 2005-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ConsoleImpl_h +#define MAIN_INCLUDED_ConsoleImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxBase.h" +#include "VBox/com/array.h" +#include "EventImpl.h" +#include "SecretKeyStore.h" +#include "ConsoleWrap.h" +#ifdef VBOX_WITH_RECORDING +# include "Recording.h" +#endif +#ifdef VBOX_WITH_CLOUD_NET +#include "CloudGateway.h" +#endif /* VBOX_WITH_CLOUD_NET */ + +class Guest; +class Keyboard; +class Mouse; +class Display; +class MachineDebugger; +class TeleporterStateSrc; +class OUSBDevice; +class RemoteUSBDevice; +class SharedFolder; +class VRDEServerInfo; +class EmulatedUSB; +class AudioVRDE; +#ifdef VBOX_WITH_AUDIO_RECORDING +class AudioVideoRec; +#endif +#ifdef VBOX_WITH_USB_CARDREADER +class UsbCardReader; +#endif +class ConsoleVRDPServer; +class VMMDev; +class Progress; +class BusAssignmentManager; +COM_STRUCT_OR_CLASS(IEventListener); +#ifdef VBOX_WITH_EXTPACK +class ExtPackManager; +#endif +class VMMDevMouseInterface; +class DisplayMouseInterface; +class VMPowerUpTask; +class VMPowerDownTask; +class NvramStore; + +#include <iprt/uuid.h> +#include <iprt/log.h> +#include <iprt/memsafer.h> +#include <VBox/RemoteDesktop/VRDE.h> +#include <VBox/vmm/pdmdrv.h> +#ifdef VBOX_WITH_GUEST_PROPS +# include <VBox/HostServices/GuestPropertySvc.h> /* For the property notification callback */ +#endif +#ifdef VBOX_WITH_USB +# include <VBox/vrdpusb.h> +#endif +#include <VBox/VBoxCryptoIf.h> + +#if defined(VBOX_WITH_GUEST_PROPS) || defined(VBOX_WITH_SHARED_CLIPBOARD) \ + || defined(VBOX_WITH_DRAG_AND_DROP) +# include "HGCM.h" /** @todo It should be possible to register a service + * extension using a VMMDev callback. */ +#endif + +struct VUSBIRHCONFIG; +typedef struct VUSBIRHCONFIG *PVUSBIRHCONFIG; + +#include <list> +#include <vector> + +// defines +/////////////////////////////////////////////////////////////////////////////// + +/** + * Checks the availability of the underlying VM device driver corresponding + * to the COM interface (IKeyboard, IMouse, IDisplay, etc.). When the driver is + * not available (NULL), sets error info and returns returns E_ACCESSDENIED. + * The translatable error message is defined in null context. + * + * Intended to used only within Console children (i.e. Keyboard, Mouse, + * Display, etc.). + * + * @param drv driver pointer to check (compare it with NULL) + */ +#define CHECK_CONSOLE_DRV(drv) \ + do { \ + if (!!(drv)) {} \ + else return setError(E_ACCESSDENIED, Console::tr("The console is not powered up (%Rfn)"), __FUNCTION__); \ + } while (0) + +// Console +/////////////////////////////////////////////////////////////////////////////// + +class ConsoleMouseInterface +{ +public: + virtual ~ConsoleMouseInterface() { } + virtual VMMDevMouseInterface *i_getVMMDevMouseInterface(){return NULL;} + virtual DisplayMouseInterface *i_getDisplayMouseInterface(){return NULL;} + virtual void i_onMouseCapabilityChange(BOOL supportsAbsolute, + BOOL supportsRelative, + BOOL supportsTouchScreen, + BOOL supportsTouchPad, + BOOL needsHostCursor) + { + RT_NOREF(supportsAbsolute, supportsRelative, supportsTouchScreen, supportsTouchPad, needsHostCursor); + } +}; + +/** IConsole implementation class */ +class ATL_NO_VTABLE Console : + public ConsoleWrap, + public ConsoleMouseInterface +{ + +public: + + DECLARE_COMMON_CLASS_METHODS(Console) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializers/uninitializers for internal purposes only + HRESULT initWithMachine(IMachine *aMachine, IInternalMachineControl *aControl, LockType_T aLockType); + void uninit(); + + + // public methods for internal purposes only + + /* + * Note: the following methods do not increase refcount. intended to be + * called only by the VM execution thread. + */ + + PCVMMR3VTABLE i_getVMMVTable() const RT_NOEXCEPT { return mpVMM; } + Guest *i_getGuest() const { return mGuest; } + Keyboard *i_getKeyboard() const { return mKeyboard; } + Mouse *i_getMouse() const { return mMouse; } + Display *i_getDisplay() const { return mDisplay; } + MachineDebugger *i_getMachineDebugger() const { return mDebugger; } +#ifdef VBOX_WITH_AUDIO_VRDE + AudioVRDE *i_getAudioVRDE() const { return mAudioVRDE; } +#endif +#ifdef VBOX_WITH_RECORDING + int i_recordingCreate(void); + void i_recordingDestroy(void); + int i_recordingEnable(BOOL fEnable, util::AutoWriteLock *pAutoLock); + int i_recordingGetSettings(settings::RecordingSettings &recording); + int i_recordingStart(util::AutoWriteLock *pAutoLock = NULL); + int i_recordingStop(util::AutoWriteLock *pAutoLock = NULL); +# ifdef VBOX_WITH_AUDIO_RECORDING + AudioVideoRec *i_recordingGetAudioDrv(void) const { return mRecording.mAudioRec; } +# endif + RecordingContext *i_recordingGetContext(void) { return &mRecording.mCtx; } +# ifdef VBOX_WITH_AUDIO_RECORDING + HRESULT i_recordingSendAudio(const void *pvData, size_t cbData, uint64_t uDurationMs); +# endif +#endif + + const ComPtr<IMachine> &i_machine() const { return mMachine; } + const Bstr &i_getId() const { return mstrUuid; } + + bool i_useHostClipboard() { return mfUseHostClipboard; } + + /** Method is called only from ConsoleVRDPServer */ + IVRDEServer *i_getVRDEServer() const { return mVRDEServer; } + + ConsoleVRDPServer *i_consoleVRDPServer() const { return mConsoleVRDPServer; } + + HRESULT i_updateMachineState(MachineState_T aMachineState); + HRESULT i_getNominalState(MachineState_T &aNominalState); + Utf8Str i_getAudioAdapterDeviceName(IAudioAdapter *aAudioAdapter); + + // events from IInternalSessionControl + HRESULT i_onNetworkAdapterChange(INetworkAdapter *aNetworkAdapter, BOOL changeAdapter); + HRESULT i_onAudioAdapterChange(IAudioAdapter *aAudioAdapter); + HRESULT i_onHostAudioDeviceChange(IHostAudioDevice *aDevice, BOOL aNew, AudioDeviceState_T aState, + IVirtualBoxErrorInfo *aErrInfo); + HRESULT i_onSerialPortChange(ISerialPort *aSerialPort); + HRESULT i_onParallelPortChange(IParallelPort *aParallelPort); + HRESULT i_onStorageControllerChange(const com::Guid& aMachineId, const com::Utf8Str& aControllerName); + HRESULT i_onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForce); + HRESULT i_onCPUChange(ULONG aCPU, BOOL aRemove); + HRESULT i_onCPUExecutionCapChange(ULONG aExecutionCap); + HRESULT i_onClipboardModeChange(ClipboardMode_T aClipboardMode); + HRESULT i_onClipboardFileTransferModeChange(bool aEnabled); + HRESULT i_onDnDModeChange(DnDMode_T aDnDMode); + HRESULT i_onVRDEServerChange(BOOL aRestart); + HRESULT i_onRecordingChange(BOOL fEnable); + HRESULT i_onUSBControllerChange(); + HRESULT i_onSharedFolderChange(BOOL aGlobal); + HRESULT i_onUSBDeviceAttach(IUSBDevice *aDevice, IVirtualBoxErrorInfo *aError, ULONG aMaskedIfs, + const Utf8Str &aCaptureFilename); + HRESULT i_onUSBDeviceDetach(IN_BSTR aId, IVirtualBoxErrorInfo *aError); + HRESULT i_onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup); + HRESULT i_onStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove, BOOL aSilent); + HRESULT i_onExtraDataChange(const Bstr &aMachineId, const Bstr &aKey, const Bstr &aVal); + HRESULT i_onGuestDebugControlChange(IGuestDebugControl *aGuestDebugControl); + + HRESULT i_getGuestProperty(const Utf8Str &aName, Utf8Str *aValue, LONG64 *aTimestamp, Utf8Str *aFlags); + HRESULT i_setGuestProperty(const Utf8Str &aName, const Utf8Str &aValue, const Utf8Str &aFlags); + HRESULT i_deleteGuestProperty(const Utf8Str &aName); + HRESULT i_enumerateGuestProperties(const Utf8Str &aPatterns, + std::vector<Utf8Str> &aNames, + std::vector<Utf8Str> &aValues, + std::vector<LONG64> &aTimestamps, + std::vector<Utf8Str> &aFlags); + HRESULT i_onlineMergeMedium(IMediumAttachment *aMediumAttachment, + ULONG aSourceIdx, ULONG aTargetIdx, + IProgress *aProgress); + HRESULT i_reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments); + HRESULT i_onVMProcessPriorityChange(VMProcPriority_T priority); + int i_hgcmLoadService(const char *pszServiceLibrary, const char *pszServiceName); + VMMDev *i_getVMMDev() { return m_pVMMDev; } + +#ifdef VBOX_WITH_EXTPACK + ExtPackManager *i_getExtPackManager(); +#endif + EventSource *i_getEventSource() { return mEventSource; } +#ifdef VBOX_WITH_USB_CARDREADER + UsbCardReader *i_getUsbCardReader() { return mUsbCardReader; } +#endif + + int i_VRDPClientLogon(uint32_t u32ClientId, const char *pszUser, const char *pszPassword, const char *pszDomain); + void i_VRDPClientStatusChange(uint32_t u32ClientId, const char *pszStatus); + void i_VRDPClientConnect(uint32_t u32ClientId); + void i_VRDPClientDisconnect(uint32_t u32ClientId, uint32_t fu32Intercepted); + void i_VRDPInterceptAudio(uint32_t u32ClientId); + void i_VRDPInterceptUSB(uint32_t u32ClientId, void **ppvIntercept); + void i_VRDPInterceptClipboard(uint32_t u32ClientId); + + void i_processRemoteUSBDevices(uint32_t u32ClientId, VRDEUSBDEVICEDESC *pDevList, uint32_t cbDevList, bool fDescExt); + void i_reportVmStatistics(ULONG aValidStats, ULONG aCpuUser, + ULONG aCpuKernel, ULONG aCpuIdle, + ULONG aMemTotal, ULONG aMemFree, + ULONG aMemBalloon, ULONG aMemShared, + ULONG aMemCache, ULONG aPageTotal, + ULONG aAllocVMM, ULONG aFreeVMM, + ULONG aBalloonedVMM, ULONG aSharedVMM, + ULONG aVmNetRx, ULONG aVmNetTx) + { + mControl->ReportVmStatistics(aValidStats, aCpuUser, aCpuKernel, aCpuIdle, + aMemTotal, aMemFree, aMemBalloon, aMemShared, + aMemCache, aPageTotal, aAllocVMM, aFreeVMM, + aBalloonedVMM, aSharedVMM, aVmNetRx, aVmNetTx); + } + void i_enableVMMStatistics(BOOL aEnable); + + HRESULT i_pause(Reason_T aReason); + HRESULT i_resume(Reason_T aReason, AutoWriteLock &alock); + HRESULT i_saveState(Reason_T aReason, const ComPtr<IProgress> &aProgress, + const ComPtr<ISnapshot> &aSnapshot, + const Utf8Str &aStateFilePath, bool fPauseVM, bool &fLeftPaused); + HRESULT i_cancelSaveState(); + + // callback callers (partly; for some events console callbacks are notified + // directly from IInternalSessionControl event handlers declared above) + void i_onMousePointerShapeChange(bool fVisible, bool fAlpha, + uint32_t xHot, uint32_t yHot, + uint32_t width, uint32_t height, + const uint8_t *pu8Shape, + uint32_t cbShape); + void i_onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelative, + BOOL supportsTouchScreen, BOOL supportsTouchPad, + BOOL needsHostCursor); + void i_onStateChange(MachineState_T aMachineState); + void i_onAdditionsStateChange(); + void i_onAdditionsOutdated(); + void i_onKeyboardLedsChange(bool fNumLock, bool fCapsLock, bool fScrollLock); + void i_onUSBDeviceStateChange(IUSBDevice *aDevice, bool aAttached, + IVirtualBoxErrorInfo *aError); + void i_onRuntimeError(BOOL aFatal, IN_BSTR aErrorID, IN_BSTR aMessage); + HRESULT i_onShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId); + void i_onVRDEServerInfoChange(); + HRESULT i_sendACPIMonitorHotPlugEvent(); + + static const PDMDRVREG DrvStatusReg; + + static HRESULT i_setErrorStatic(HRESULT aResultCode, const char *pcsz, ...); + static HRESULT i_setErrorStaticBoth(HRESULT aResultCode, int vrc, const char *pcsz, ...); + HRESULT i_setInvalidMachineStateError(); + + static const char *i_storageControllerTypeToStr(StorageControllerType_T enmCtrlType); + static HRESULT i_storageBusPortDeviceToLun(StorageBus_T enmBus, LONG port, LONG device, unsigned &uLun); + // Called from event listener + HRESULT i_onNATRedirectRuleChanged(ULONG ulInstance, BOOL aNatRuleRemove, + NATProtocol_T aProto, IN_BSTR aHostIp, LONG aHostPort, IN_BSTR aGuestIp, LONG aGuestPort); + HRESULT i_onNATDnsChanged(); + + // Mouse interface + VMMDevMouseInterface *i_getVMMDevMouseInterface(); + DisplayMouseInterface *i_getDisplayMouseInterface(); + + EmulatedUSB *i_getEmulatedUSB(void) { return mEmulatedUSB; } + + /** + * Sets the disk encryption keys. + * + * @returns COM status code. + * @param strCfg The config for the disks. + * + * @note One line in the config string contains all required data for one disk. + * The format for one disk is some sort of comma separated value using + * key=value pairs. + * There are two keys defined at the moment: + * - uuid: The uuid of the base image the key is for (with or without) + * the curly braces. + * - dek: The data encryption key in base64 encoding + */ + HRESULT i_setDiskEncryptionKeys(const Utf8Str &strCfg); + + int i_retainCryptoIf(PCVBOXCRYPTOIF *ppCryptoIf); + int i_releaseCryptoIf(PCVBOXCRYPTOIF pCryptoIf); + HRESULT i_unloadCryptoIfModule(void); + +#ifdef VBOX_WITH_GUEST_PROPS + // VMMDev needs: + HRESULT i_pullGuestProperties(ComSafeArrayOut(BSTR, names), ComSafeArrayOut(BSTR, values), + ComSafeArrayOut(LONG64, timestamps), ComSafeArrayOut(BSTR, flags)); + static DECLCALLBACK(int) i_doGuestPropNotification(void *pvExtension, uint32_t, void *pvParms, uint32_t cbParms); +#endif + +private: + + // wrapped IConsole properties + HRESULT getMachine(ComPtr<IMachine> &aMachine); + HRESULT getState(MachineState_T *aState); + HRESULT getGuest(ComPtr<IGuest> &aGuest); + HRESULT getKeyboard(ComPtr<IKeyboard> &aKeyboard); + HRESULT getMouse(ComPtr<IMouse> &aMouse); + HRESULT getDisplay(ComPtr<IDisplay> &aDisplay); + HRESULT getDebugger(ComPtr<IMachineDebugger> &aDebugger); + HRESULT getUSBDevices(std::vector<ComPtr<IUSBDevice> > &aUSBDevices); + HRESULT getRemoteUSBDevices(std::vector<ComPtr<IHostUSBDevice> > &aRemoteUSBDevices); + HRESULT getSharedFolders(std::vector<ComPtr<ISharedFolder> > &aSharedFolders); + HRESULT getVRDEServerInfo(ComPtr<IVRDEServerInfo> &aVRDEServerInfo); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + HRESULT getAttachedPCIDevices(std::vector<ComPtr<IPCIDeviceAttachment> > &aAttachedPCIDevices); + HRESULT getUseHostClipboard(BOOL *aUseHostClipboard); + HRESULT setUseHostClipboard(BOOL aUseHostClipboard); + HRESULT getEmulatedUSB(ComPtr<IEmulatedUSB> &aEmulatedUSB); + + // wrapped IConsole methods + HRESULT powerUp(ComPtr<IProgress> &aProgress); + HRESULT powerUpPaused(ComPtr<IProgress> &aProgress); + HRESULT powerDown(ComPtr<IProgress> &aProgress); + HRESULT reset(); + HRESULT pause(); + HRESULT resume(); + HRESULT powerButton(); + HRESULT sleepButton(); + HRESULT getPowerButtonHandled(BOOL *aHandled); + HRESULT getGuestEnteredACPIMode(BOOL *aEntered); + HRESULT getDeviceActivity(const std::vector<DeviceType_T> &aType, + std::vector<DeviceActivity_T> &aActivity); + HRESULT attachUSBDevice(const com::Guid &aId, const com::Utf8Str &aCaptureFilename); + HRESULT detachUSBDevice(const com::Guid &aId, + ComPtr<IUSBDevice> &aDevice); + HRESULT findUSBDeviceByAddress(const com::Utf8Str &aName, + ComPtr<IUSBDevice> &aDevice); + HRESULT findUSBDeviceById(const com::Guid &aId, + ComPtr<IUSBDevice> &aDevice); + HRESULT createSharedFolder(const com::Utf8Str &aName, + const com::Utf8Str &aHostPath, + BOOL aWritable, + BOOL aAutomount, + const com::Utf8Str &aAutoMountPoint); + HRESULT removeSharedFolder(const com::Utf8Str &aName); + HRESULT teleport(const com::Utf8Str &aHostname, + ULONG aTcpport, + const com::Utf8Str &aPassword, + ULONG aMaxDowntime, + ComPtr<IProgress> &aProgress); + HRESULT addEncryptionPassword(const com::Utf8Str &aId, const com::Utf8Str &aPassword, + BOOL aClearOnSuspend); + HRESULT addEncryptionPasswords(const std::vector<com::Utf8Str> &aIds, const std::vector<com::Utf8Str> &aPasswords, + BOOL aClearOnSuspend); + HRESULT removeEncryptionPassword(const com::Utf8Str &aId); + HRESULT clearAllEncryptionPasswords(); + + void notifyNatDnsChange(PUVM pUVM, PCVMMR3VTABLE pVMM, const char *pszDevice, ULONG ulInstanceMax); + Utf8Str VRDPServerErrorToMsg(int vrc); + + /** + * Base template for AutoVMCaller and SafeVMPtr. Template arguments + * have the same meaning as arguments of Console::addVMCaller(). + */ + template <bool taQuiet = false, bool taAllowNullVM = false> + class AutoVMCallerBase + { + public: + AutoVMCallerBase(Console *aThat) : mThat(aThat), mRC(E_FAIL) + { + Assert(aThat); + mRC = aThat->i_addVMCaller(taQuiet, taAllowNullVM); + } + ~AutoVMCallerBase() + { + doRelease(); + } + /** Decreases the number of callers before the instance is destroyed. */ + void releaseCaller() + { + Assert(SUCCEEDED(mRC)); + doRelease(); + } + /** Restores the number of callers after by #release(). #rc() must be + * rechecked to ensure the operation succeeded. */ + void addYY() + { + AssertReturnVoid(!SUCCEEDED(mRC)); + mRC = mThat->i_addVMCaller(taQuiet, taAllowNullVM); + } + /** Returns the result of Console::addVMCaller() */ + HRESULT rc() const { return mRC; } + /** Shortcut to SUCCEEDED(rc()) */ + bool isOk() const { return SUCCEEDED(mRC); } + protected: + Console *mThat; + void doRelease() + { + if (SUCCEEDED(mRC)) + { + mThat->i_releaseVMCaller(); + mRC = E_FAIL; + } + } + private: + HRESULT mRC; /* Whether the caller was added. */ + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoVMCallerBase); + }; + +#if 0 + /** + * Helper class that protects sections of code using the mpUVM pointer by + * automatically calling addVMCaller() on construction and + * releaseVMCaller() on destruction. Intended for Console methods dealing + * with mpUVM. The usage pattern is: + * <code> + * AutoVMCaller autoVMCaller(this); + * if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc(); + * ... + * VMR3ReqCall (mpUVM, ... + * </code> + * + * @note Temporarily locks the argument for writing. + * + * @sa SafeVMPtr, SafeVMPtrQuiet + * @note Obsolete, use SafeVMPtr + */ + typedef AutoVMCallerBase<false, false> AutoVMCaller; +#endif + + /** + * Same as AutoVMCaller but doesn't set extended error info on failure. + * + * @note Temporarily locks the argument for writing. + * @note Obsolete, use SafeVMPtrQuiet + */ + typedef AutoVMCallerBase<true, false> AutoVMCallerQuiet; + + /** + * Same as AutoVMCaller but allows a null VM pointer (to trigger an error + * instead of assertion). + * + * @note Temporarily locks the argument for writing. + * @note Obsolete, use SafeVMPtr + */ + typedef AutoVMCallerBase<false, true> AutoVMCallerWeak; + + /** + * Same as AutoVMCaller but doesn't set extended error info on failure + * and allows a null VM pointer (to trigger an error instead of + * assertion). + * + * @note Temporarily locks the argument for writing. + * @note Obsolete, use SafeVMPtrQuiet + */ + typedef AutoVMCallerBase<true, true> AutoVMCallerQuietWeak; + + /** + * Base template for SafeVMPtr and SafeVMPtrQuiet. + */ + template<bool taQuiet = false> + class SafeVMPtrBase : public AutoVMCallerBase<taQuiet, true> + { + typedef AutoVMCallerBase<taQuiet, true> Base; + public: + SafeVMPtrBase(Console *aThat) : Base(aThat), mRC(E_FAIL), mpUVM(NULL), mpVMM(NULL) + { + if (Base::isOk()) + mRC = aThat->i_safeVMPtrRetainer(&mpUVM, &mpVMM, taQuiet); + } + ~SafeVMPtrBase() + { + doRelease(); + } + /** Direct PUVM access. */ + PUVM rawUVM() const { return mpUVM; } + /** Direct PCVMMR3VTABLE access. */ + PCVMMR3VTABLE vtable() const { return mpVMM; } + /** Release the handles. */ + void release() + { + Assert(SUCCEEDED(mRC)); + doRelease(); + } + + /** The combined result of Console::addVMCaller() and Console::safeVMPtrRetainer */ + HRESULT rc() const { return Base::isOk()? mRC: Base::rc(); } + /** Shortcut to SUCCEEDED(rc()) */ + bool isOk() const { return SUCCEEDED(mRC) && Base::isOk(); } + + private: + void doRelease() + { + if (SUCCEEDED(mRC)) + { + Base::mThat->i_safeVMPtrReleaser(&mpUVM); + mRC = E_FAIL; + } + Base::doRelease(); + } + HRESULT mRC; /* Whether the VM ptr was retained. */ + PUVM mpUVM; + PCVMMR3VTABLE mpVMM; + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(SafeVMPtrBase); + }; + +public: + + /* + * Helper class that safely manages the Console::mpUVM pointer + * by calling addVMCaller() on construction and releaseVMCaller() on + * destruction. Intended for Console children. The usage pattern is: + * <code> + * Console::SafeVMPtr ptrVM(mParent); + * if (!ptrVM.isOk()) + * return ptrVM.rc(); + * ... + * VMR3ReqCall(ptrVM.rawUVM(), ... + * ... + * printf("%p\n", ptrVM.rawUVM()); + * </code> + * + * @note Temporarily locks the argument for writing. + * + * @sa SafeVMPtrQuiet, AutoVMCaller + */ + typedef SafeVMPtrBase<false> SafeVMPtr; + + /** + * A deviation of SafeVMPtr that doesn't set the error info on failure. + * Intended for pieces of code that don't need to return the VM access + * failure to the caller. The usage pattern is: + * <code> + * Console::SafeVMPtrQuiet pVM(mParent); + * if (pVM.rc()) + * VMR3ReqCall(pVM, ... + * return S_OK; + * </code> + * + * @note Temporarily locks the argument for writing. + * + * @sa SafeVMPtr, AutoVMCaller + */ + typedef SafeVMPtrBase<true> SafeVMPtrQuiet; + + class SharedFolderData + { + public: + SharedFolderData() + { } + + SharedFolderData(const Utf8Str &aHostPath, + bool aWritable, + bool aAutoMount, + const Utf8Str &aAutoMountPoint) + : m_strHostPath(aHostPath) + , m_fWritable(aWritable) + , m_fAutoMount(aAutoMount) + , m_strAutoMountPoint(aAutoMountPoint) + { } + + /** Copy constructor. */ + SharedFolderData(const SharedFolderData& aThat) + : m_strHostPath(aThat.m_strHostPath) + , m_fWritable(aThat.m_fWritable) + , m_fAutoMount(aThat.m_fAutoMount) + , m_strAutoMountPoint(aThat.m_strAutoMountPoint) + { } + + /** Copy assignment operator. */ + SharedFolderData &operator=(SharedFolderData const &a_rThat) RT_NOEXCEPT + { + m_strHostPath = a_rThat.m_strHostPath; + m_fWritable = a_rThat.m_fWritable; + m_fAutoMount = a_rThat.m_fAutoMount; + m_strAutoMountPoint = a_rThat.m_strAutoMountPoint; + + return *this; + } + + Utf8Str m_strHostPath; + bool m_fWritable; + bool m_fAutoMount; + Utf8Str m_strAutoMountPoint; + }; + + /** + * Class for managing emulated USB MSDs. + */ + class USBStorageDevice + { + public: + USBStorageDevice() + { } + /** The UUID associated with the USB device. */ + RTUUID mUuid; + /** Port of the storage device. */ + LONG iPort; + }; + + typedef std::map<Utf8Str, ComObjPtr<SharedFolder> > SharedFolderMap; + typedef std::map<Utf8Str, SharedFolderData> SharedFolderDataMap; + typedef std::map<Utf8Str, ComPtr<IMediumAttachment> > MediumAttachmentMap; + typedef std::list <USBStorageDevice> USBStorageDeviceList; + + static void i_powerUpThreadTask(VMPowerUpTask *pTask); + static void i_powerDownThreadTask(VMPowerDownTask *pTask); + +private: + + typedef std::list <ComObjPtr<OUSBDevice> > USBDeviceList; + typedef std::list <ComObjPtr<RemoteUSBDevice> > RemoteUSBDeviceList; + + HRESULT i_loadVMM(void) RT_NOEXCEPT; + HRESULT i_addVMCaller(bool aQuiet = false, bool aAllowNullVM = false); + void i_releaseVMCaller(); + HRESULT i_safeVMPtrRetainer(PUVM *a_ppUVM, PCVMMR3VTABLE *a_ppVMM, bool aQuiet) RT_NOEXCEPT; + void i_safeVMPtrReleaser(PUVM *a_ppUVM); + + HRESULT i_consoleInitReleaseLog(const ComPtr<IMachine> aMachine); + + HRESULT i_powerUp(IProgress **aProgress, bool aPaused); + HRESULT i_powerDown(IProgress *aProgress = NULL); + +/* Note: FreeBSD needs this whether netflt is used or not. */ +#if ((defined(RT_OS_LINUX) && !defined(VBOX_WITH_NETFLT)) || defined(RT_OS_FREEBSD)) + HRESULT i_attachToTapInterface(INetworkAdapter *networkAdapter); + HRESULT i_detachFromTapInterface(INetworkAdapter *networkAdapter); +#endif + HRESULT i_powerDownHostInterfaces(); + + HRESULT i_setMachineState(MachineState_T aMachineState, bool aUpdateServer = true); + HRESULT i_setMachineStateLocally(MachineState_T aMachineState) + { + return i_setMachineState(aMachineState, false /* aUpdateServer */); + } + + HRESULT i_findSharedFolder(const Utf8Str &strName, + ComObjPtr<SharedFolder> &aSharedFolder, + bool aSetError = false); + + HRESULT i_fetchSharedFolders(BOOL aGlobal); + bool i_findOtherSharedFolder(const Utf8Str &straName, + SharedFolderDataMap::const_iterator &aIt); + + HRESULT i_createSharedFolder(const Utf8Str &strName, const SharedFolderData &aData); + HRESULT i_removeSharedFolder(const Utf8Str &strName); + + HRESULT i_suspendBeforeConfigChange(PUVM pUVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock, bool *pfResume); + void i_resumeAfterConfigChange(PUVM pUVM, PCVMMR3VTABLE pVMM); + + static DECLCALLBACK(int) i_configConstructor(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, void *pvConsole); + void InsertConfigString(PCFGMNODE pNode, const char *pcszName, const char *pcszValue); + void InsertConfigString(PCFGMNODE pNode, const char *pcszName, const Utf8Str &rStrValue); + void InsertConfigString(PCFGMNODE pNode, const char *pcszName, const Bstr &rBstrValue); + void InsertConfigPassword(PCFGMNODE pNode, const char *pcszName, const Utf8Str &rStrValue); + void InsertConfigBytes(PCFGMNODE pNode, const char *pcszName, const void *pvBytes, size_t cbBytes); + void InsertConfigInteger(PCFGMNODE pNode, const char *pcszName, uint64_t u64Integer); + void InsertConfigNode(PCFGMNODE pNode, const char *pcszName, PCFGMNODE *ppChild); + void InsertConfigNodeF(PCFGMNODE pNode, PCFGMNODE *ppChild, const char *pszNameFormat, ...); + void RemoveConfigValue(PCFGMNODE pNode, const char *pcszName); + int SetBiosDiskInfo(ComPtr<IMachine> pMachine, PCFGMNODE pCfg, PCFGMNODE pBiosCfg, + Bstr controllerName, const char * const s_apszBiosConfig[4]); + void i_configAudioDriver(IVirtualBox *pVirtualBox, IMachine *pMachine, PCFGMNODE pLUN, const char *pszDriverName, + bool fAudioEnabledIn, bool fAudioEnabledOut); + int i_configConstructorInner(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock); + int i_configCfgmOverlay(PCFGMNODE pRoot, IVirtualBox *pVirtualBox, IMachine *pMachine); + int i_configDumpAPISettingsTweaks(IVirtualBox *pVirtualBox, IMachine *pMachine); + + int i_configGraphicsController(PCFGMNODE pDevices, + const GraphicsControllerType_T graphicsController, + BusAssignmentManager *pBusMgr, + const ComPtr<IMachine> &ptrMachine, + const ComPtr<IGraphicsAdapter> &ptrGraphicsAdapter, + const ComPtr<IBIOSSettings> &ptrBiosSettings, + bool fHMEnabled); + int i_checkMediumLocation(IMedium *pMedium, bool *pfUseHostIOCache); + int i_unmountMediumFromGuest(PUVM pUVM, PCVMMR3VTABLE pVMM, StorageBus_T enmBus, DeviceType_T enmDevType, + const char *pcszDevice, unsigned uInstance, unsigned uLUN, + bool fForceUnmount) RT_NOEXCEPT; + int i_removeMediumDriverFromVm(PCFGMNODE pCtlInst, + const char *pcszDevice, + unsigned uInstance, + unsigned uLUN, + StorageBus_T enmBus, + bool fAttachDetach, + bool fHotplug, + bool fForceUnmount, + PUVM pUVM, + PCVMMR3VTABLE pVMM, + DeviceType_T enmDevType, + PCFGMNODE *ppLunL0); + int i_configMediumAttachment(const char *pcszDevice, + unsigned uInstance, + StorageBus_T enmBus, + bool fUseHostIOCache, + bool fBuiltinIoCache, + bool fInsertDiskIntegrityDrv, + bool fSetupMerge, + unsigned uMergeSource, + unsigned uMergeTarget, + IMediumAttachment *pMediumAtt, + MachineState_T aMachineState, + HRESULT *phrc, + bool fAttachDetach, + bool fForceUnmount, + bool fHotplug, + PUVM pUVM, + PCVMMR3VTABLE pVMM, + DeviceType_T *paLedDevType, + PCFGMNODE *ppLunL0); + int i_configMedium(PCFGMNODE pLunL0, + bool fPassthrough, + DeviceType_T enmType, + bool fUseHostIOCache, + bool fBuiltinIoCache, + bool fInsertDiskIntegrityDrv, + bool fSetupMerge, + unsigned uMergeSource, + unsigned uMergeTarget, + const char *pcszBwGroup, + bool fDiscard, + bool fNonRotational, + ComPtr<IMedium> ptrMedium, + MachineState_T aMachineState, + HRESULT *phrc); + int i_configMediumProperties(PCFGMNODE pCur, IMedium *pMedium, bool *pfHostIP, bool *pfEncrypted); + static DECLCALLBACK(int) i_reconfigureMediumAttachment(Console *pThis, + PUVM pUVM, + PCVMMR3VTABLE pVMM, + const char *pcszDevice, + unsigned uInstance, + StorageBus_T enmBus, + bool fUseHostIOCache, + bool fBuiltinIoCache, + bool fInsertDiskIntegrityDrv, + bool fSetupMerge, + unsigned uMergeSource, + unsigned uMergeTarget, + IMediumAttachment *aMediumAtt, + MachineState_T aMachineState, + HRESULT *phrc); + static DECLCALLBACK(int) i_changeRemovableMedium(Console *pThis, + PUVM pUVM, + PCVMMR3VTABLE pVMM, + const char *pcszDevice, + unsigned uInstance, + StorageBus_T enmBus, + bool fUseHostIOCache, + IMediumAttachment *aMediumAtt, + bool fForce); + + HRESULT i_attachRawPCIDevices(PUVM pUVM, BusAssignmentManager *BusMgr, PCFGMNODE pDevices); + struct LEDSET; + typedef struct LEDSET *PLEDSET; + PPDMLED *i_getLedSet(uint32_t iLedSet); + uint32_t i_allocateDriverLeds(uint32_t cLeds, DeviceType_T enmType, DeviceType_T **ppSubTypes); + void i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType, + uint32_t uFirst, uint32_t uLast, + DeviceType_T **ppaSubTypes, + Console::MediumAttachmentMap *pmapMediumAttachments, + const char *pcszDevice, unsigned uInstance); + + int i_configNetwork(const char *pszDevice, unsigned uInstance, unsigned uLun, INetworkAdapter *aNetworkAdapter, + PCFGMNODE pCfg, PCFGMNODE pLunL0, PCFGMNODE pInst, bool fAttachDetach, bool fIgnoreConnectFailure, + PUVM pUVM, PCVMMR3VTABLE pVMM); + int i_configProxy(ComPtr<IVirtualBox> virtualBox, PCFGMNODE pCfg, const char *pcszPrefix, const com::Utf8Str &strIpAddr); + + int i_configSerialPort(PCFGMNODE pInst, PortMode_T ePortMode, const char *pszPath, bool fServer); + static DECLCALLBACK(void) i_vmstateChangeCallback(PUVM pUVM, PCVMMR3VTABLE pVMM, VMSTATE enmState, + VMSTATE enmOldState, void *pvUser); + static DECLCALLBACK(int) i_unplugCpu(Console *pThis, PUVM pUVM, PCVMMR3VTABLE pVMM, VMCPUID idCpu); + static DECLCALLBACK(int) i_plugCpu(Console *pThis, PUVM pUVM, PCVMMR3VTABLE pVMM, VMCPUID idCpu); + HRESULT i_doMediumChange(IMediumAttachment *aMediumAttachment, bool fForce, PUVM pUVM, PCVMMR3VTABLE pVMM); + HRESULT i_doCPURemove(ULONG aCpu, PUVM pUVM, PCVMMR3VTABLE pVMM); + HRESULT i_doCPUAdd(ULONG aCpu, PUVM pUVM, PCVMMR3VTABLE pVMM); + + HRESULT i_doNetworkAdapterChange(PUVM pUVM, PCVMMR3VTABLE pVMM, const char *pszDevice, unsigned uInstance, + unsigned uLun, INetworkAdapter *aNetworkAdapter); + static DECLCALLBACK(int) i_changeNetworkAttachment(Console *pThis, PUVM pUVM, PCVMMR3VTABLE pVMM, const char *pszDevice, + unsigned uInstance, unsigned uLun, INetworkAdapter *aNetworkAdapter); + static DECLCALLBACK(int) i_changeSerialPortAttachment(Console *pThis, PUVM pUVM, PCVMMR3VTABLE pVMM, ISerialPort *pSerialPort); + + int i_changeClipboardMode(ClipboardMode_T aClipboardMode); + int i_changeClipboardFileTransferMode(bool aEnabled); + int i_changeDnDMode(DnDMode_T aDnDMode); + +#ifdef VBOX_WITH_USB + HRESULT i_attachUSBDevice(IUSBDevice *aHostDevice, ULONG aMaskedIfs, const Utf8Str &aCaptureFilename); + HRESULT i_detachUSBDevice(const ComObjPtr<OUSBDevice> &aHostDevice); + + static DECLCALLBACK(int) i_usbAttachCallback(Console *that, PUVM pUVM, PCVMMR3VTABLE pVMM, IUSBDevice *aHostDevice, + PCRTUUID aUuid, const char *aBackend, const char *aAddress, + PCFGMNODE pRemoteCfg, USBConnectionSpeed_T enmSpeed, ULONG aMaskedIfs, + const char *pszCaptureFilename); + static DECLCALLBACK(int) i_usbDetachCallback(Console *that, PUVM pUVM, PCVMMR3VTABLE pVMM, PCRTUUID aUuid); + static DECLCALLBACK(PREMOTEUSBCALLBACK) i_usbQueryRemoteUsbBackend(void *pvUser, PCRTUUID pUuid, uint32_t idClient); + + /** Interface for the VRDP USB proxy backend to query for a device remote callback table. */ + REMOTEUSBIF mRemoteUsbIf; +#endif + + static DECLCALLBACK(int) i_attachStorageDevice(Console *pThis, + PUVM pUVM, + PCVMMR3VTABLE pVMM, + const char *pcszDevice, + unsigned uInstance, + StorageBus_T enmBus, + bool fUseHostIOCache, + IMediumAttachment *aMediumAtt, + bool fSilent); + static DECLCALLBACK(int) i_detachStorageDevice(Console *pThis, + PUVM pUVM, + PCVMMR3VTABLE pVMM, + const char *pcszDevice, + unsigned uInstance, + StorageBus_T enmBus, + IMediumAttachment *aMediumAtt, + bool fSilent); + HRESULT i_doStorageDeviceAttach(IMediumAttachment *aMediumAttachment, PUVM pUVM, PCVMMR3VTABLE pVMM, bool fSilent); + HRESULT i_doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PUVM pUVM, PCVMMR3VTABLE pVMM, bool fSilent); + + static DECLCALLBACK(int) i_stateProgressCallback(PUVM pUVM, unsigned uPercent, void *pvUser); + + static DECLCALLBACK(void) i_genericVMSetErrorCallback(PUVM pUVM, void *pvUser, int rc, RT_SRC_POS_DECL, + const char *pszErrorFmt, va_list va); + + void i_atVMRuntimeErrorCallbackF(uint32_t fFatal, const char *pszErrorId, const char *pszFormat, ...); + static DECLCALLBACK(void) i_atVMRuntimeErrorCallback(PUVM pUVM, void *pvUser, uint32_t fFatal, + const char *pszErrorId, const char *pszFormat, va_list va); + + HRESULT i_captureUSBDevices(PUVM pUVM); + void i_detachAllUSBDevices(bool aDone); + + + static DECLCALLBACK(int) i_vmm2User_SaveState(PCVMM2USERMETHODS pThis, PUVM pUVM); + static DECLCALLBACK(void) i_vmm2User_NotifyEmtInit(PCVMM2USERMETHODS pThis, PUVM pUVM, PUVMCPU pUVCpu); + static DECLCALLBACK(void) i_vmm2User_NotifyEmtTerm(PCVMM2USERMETHODS pThis, PUVM pUVM, PUVMCPU pUVCpu); + static DECLCALLBACK(void) i_vmm2User_NotifyPdmtInit(PCVMM2USERMETHODS pThis, PUVM pUVM); + static DECLCALLBACK(void) i_vmm2User_NotifyPdmtTerm(PCVMM2USERMETHODS pThis, PUVM pUVM); + static DECLCALLBACK(void) i_vmm2User_NotifyResetTurnedIntoPowerOff(PCVMM2USERMETHODS pThis, PUVM pUVM); + static DECLCALLBACK(void *) i_vmm2User_QueryGenericObject(PCVMM2USERMETHODS pThis, PUVM pUVM, PCRTUUID pUuid); + + static DECLCALLBACK(void *) i_drvStatus_QueryInterface(PPDMIBASE pInterface, const char *pszIID); + static DECLCALLBACK(void) i_drvStatus_UnitChanged(PPDMILEDCONNECTORS pInterface, unsigned iLUN); + static DECLCALLBACK(int) i_drvStatus_MediumEjected(PPDMIMEDIANOTIFY pInterface, unsigned iLUN); + static DECLCALLBACK(void) i_drvStatus_Destruct(PPDMDRVINS pDrvIns); + static DECLCALLBACK(int) i_drvStatus_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + + static DECLCALLBACK(int) i_pdmIfSecKey_KeyRetain(PPDMISECKEY pInterface, const char *pszId, const uint8_t **ppbKey, + size_t *pcbKey); + static DECLCALLBACK(int) i_pdmIfSecKey_KeyRelease(PPDMISECKEY pInterface, const char *pszId); + static DECLCALLBACK(int) i_pdmIfSecKey_PasswordRetain(PPDMISECKEY pInterface, const char *pszId, const char **ppszPassword); + static DECLCALLBACK(int) i_pdmIfSecKey_PasswordRelease(PPDMISECKEY pInterface, const char *pszId); + + static DECLCALLBACK(int) i_pdmIfSecKeyHlp_KeyMissingNotify(PPDMISECKEYHLP pInterface); + + int mcAudioRefs; + volatile uint32_t mcVRDPClients; + uint32_t mu32SingleRDPClientId; /* The id of a connected client in the single connection mode. */ + volatile bool mcGuestCredentialsProvided; + + static const char *sSSMConsoleUnit; + + HRESULT i_loadDataFromSavedState(); + int i_loadStateFileExecInternal(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, uint32_t u32Version); + + static DECLCALLBACK(int) i_saveStateFileExec(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser); + static DECLCALLBACK(int) i_loadStateFileExec(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser, + uint32_t uVersion, uint32_t uPass); + +#ifdef VBOX_WITH_GUEST_PROPS + HRESULT i_doEnumerateGuestProperties(const Utf8Str &aPatterns, + std::vector<Utf8Str> &aNames, + std::vector<Utf8Str> &aValues, + std::vector<LONG64> &aTimestamps, + std::vector<Utf8Str> &aFlags); + + void i_guestPropertiesHandleVMReset(void); + bool i_guestPropertiesVRDPEnabled(void); + void i_guestPropertiesVRDPUpdateLogon(uint32_t u32ClientId, const char *pszUser, const char *pszDomain); + void i_guestPropertiesVRDPUpdateActiveClient(uint32_t u32ClientId); + void i_guestPropertiesVRDPUpdateClientAttach(uint32_t u32ClientId, bool fAttached); + void i_guestPropertiesVRDPUpdateNameChange(uint32_t u32ClientId, const char *pszName); + void i_guestPropertiesVRDPUpdateIPAddrChange(uint32_t u32ClientId, const char *pszIPAddr); + void i_guestPropertiesVRDPUpdateLocationChange(uint32_t u32ClientId, const char *pszLocation); + void i_guestPropertiesVRDPUpdateOtherInfoChange(uint32_t u32ClientId, const char *pszOtherInfo); + void i_guestPropertiesVRDPUpdateDisconnect(uint32_t u32ClientId); +#endif + + /** @name Disk encryption support + * @{ */ + HRESULT i_consoleParseDiskEncryption(const char *psz, const char **ppszEnd); + HRESULT i_configureEncryptionForDisk(const Utf8Str &strId, unsigned *pcDisksConfigured); + HRESULT i_clearDiskEncryptionKeysOnAllAttachmentsWithKeyId(const Utf8Str &strId); + HRESULT i_initSecretKeyIfOnAllAttachments(void); + int i_consoleParseKeyValue(const char *psz, const char **ppszEnd, + char **ppszKey, char **ppszVal); + void i_removeSecretKeysOnSuspend(); + /** @} */ + + /** @name Teleporter support + * @{ */ + static DECLCALLBACK(int) i_teleporterSrcThreadWrapper(RTTHREAD hThreadSelf, void *pvUser); + HRESULT i_teleporterSrc(TeleporterStateSrc *pState); + HRESULT i_teleporterSrcReadACK(TeleporterStateSrc *pState, const char *pszWhich, const char *pszNAckMsg = NULL); + HRESULT i_teleporterSrcSubmitCommand(TeleporterStateSrc *pState, const char *pszCommand, bool fWaitForAck = true); + HRESULT i_teleporterTrg(PUVM pUVM, PCVMMR3VTABLE pVMM, IMachine *pMachine, Utf8Str *pErrorMsg, + bool fStartPaused, Progress *pProgress, bool *pfPowerOffOnFailure); + static DECLCALLBACK(int) i_teleporterTrgServeConnection(RTSOCKET Sock, void *pvUser); + /** @} */ + +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION + /** @name Encrypted log interface + * @{ */ + static DECLCALLBACK(int) i_logEncryptedOpen(PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilename, uint32_t fFlags); + static DECLCALLBACK(int) i_logEncryptedClose(PCRTLOGOUTPUTIF pIf, void *pvUser); + static DECLCALLBACK(int) i_logEncryptedDelete(PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilename); + static DECLCALLBACK(int) i_logEncryptedRename(PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilenameOld, + const char *pszFilenameNew, uint32_t fFlags); + static DECLCALLBACK(int) i_logEncryptedQuerySize(PCRTLOGOUTPUTIF pIf, void *pvUser, uint64_t *pcbSize); + static DECLCALLBACK(int) i_logEncryptedWrite(PCRTLOGOUTPUTIF pIf, void *pvUser, const void *pvBuf, + size_t cbWrite, size_t *pcbWritten); + static DECLCALLBACK(int) i_logEncryptedFlush(PCRTLOGOUTPUTIF pIf, void *pvUser); + /** @} */ +#endif + + bool mSavedStateDataLoaded : 1; + + const ComPtr<IMachine> mMachine; + const ComPtr<IInternalMachineControl> mControl; + + const ComPtr<IVRDEServer> mVRDEServer; + + ConsoleVRDPServer * const mConsoleVRDPServer; + bool mfVRDEChangeInProcess; + bool mfVRDEChangePending; + const ComObjPtr<Guest> mGuest; + const ComObjPtr<Keyboard> mKeyboard; + const ComObjPtr<Mouse> mMouse; + const ComObjPtr<Display> mDisplay; + const ComObjPtr<MachineDebugger> mDebugger; + const ComObjPtr<VRDEServerInfo> mVRDEServerInfo; + /** This can safely be used without holding any locks. + * An AutoCaller suffices to prevent it being destroy while in use and + * internally there is a lock providing the necessary serialization. */ + const ComObjPtr<EventSource> mEventSource; +#ifdef VBOX_WITH_EXTPACK + const ComObjPtr<ExtPackManager> mptrExtPackManager; +#endif + const ComObjPtr<EmulatedUSB> mEmulatedUSB; + const ComObjPtr<NvramStore> mptrNvramStore; + + USBDeviceList mUSBDevices; + RemoteUSBDeviceList mRemoteUSBDevices; + + SharedFolderDataMap m_mapGlobalSharedFolders; + SharedFolderDataMap m_mapMachineSharedFolders; + SharedFolderMap m_mapSharedFolders; // the console instances + + /** VMM loader handle. */ + RTLDRMOD mhModVMM; + /** The VMM vtable. */ + PCVMMR3VTABLE mpVMM; + /** The user mode VM handle. */ + PUVM mpUVM; + /** Holds the number of "readonly" mpUVM callers (users). */ + uint32_t mVMCallers; + /** Semaphore posted when the number of mpUVM callers drops to zero. */ + RTSEMEVENT mVMZeroCallersSem; + /** true when Console has entered the mpUVM destruction phase. */ + bool mVMDestroying : 1; + /** true when power down is initiated by vmstateChangeCallback (EMT). */ + bool mVMPoweredOff : 1; + /** true when vmstateChangeCallback shouldn't initiate a power down. */ + bool mVMIsAlreadyPoweringOff : 1; + /** true if we already showed the snapshot folder size warning. */ + bool mfSnapshotFolderSizeWarningShown : 1; + /** true if we already showed the snapshot folder ext4/xfs bug warning. */ + bool mfSnapshotFolderExt4WarningShown : 1; + /** true if we already listed the disk type of the snapshot folder. */ + bool mfSnapshotFolderDiskTypeShown : 1; + /** true if a USB controller is available (i.e. USB devices can be attached). */ + bool mfVMHasUsbController : 1; + /** Shadow of the VBoxInternal2/TurnResetIntoPowerOff extra data setting. + * This is initialized by Console::i_configConstructorInner(). */ + bool mfTurnResetIntoPowerOff : 1; + /** true if the VM power off was caused by reset. */ + bool mfPowerOffCausedByReset : 1; + + /** Pointer to the VMM -> User (that's us) callbacks. */ + struct MYVMM2USERMETHODS : public VMM2USERMETHODS + { + Console *pConsole; + /** The in-progress snapshot. */ + ISnapshot *pISnapshot; + } *mpVmm2UserMethods; + + /** The current network attachment type in the VM. + * This doesn't have to match the network attachment type maintained in the + * NetworkAdapter. This is needed to change the network attachment + * dynamically. + */ + typedef std::vector<NetworkAttachmentType_T> NetworkAttachmentTypeVector; + NetworkAttachmentTypeVector meAttachmentType; + + VMMDev * m_pVMMDev; + AudioVRDE * const mAudioVRDE; +#ifdef VBOX_WITH_USB_CARDREADER + UsbCardReader * const mUsbCardReader; +#endif + BusAssignmentManager* mBusMgr; + + /** @name LEDs and their management + * @{ */ + /** Number of LED sets in use in maLedSets. */ + uint32_t mcLedSets; + /** LED sets. */ + struct LEDSET + { + PPDMLED *papLeds; + uint32_t cLeds; + DeviceType_T enmType; + DeviceType_T *paSubTypes; /**< Optionally, device types for each individual LED. Runs parallel to papLeds. */ + } maLedSets[32]; + /** @} */ + + MediumAttachmentMap mapMediumAttachments; + + /** List of attached USB storage devices. */ + USBStorageDeviceList mUSBStorageDevices; + + /** Store for secret keys. */ + SecretKeyStore * const m_pKeyStore; + /** Number of disks configured for encryption. */ + unsigned m_cDisksEncrypted; + /** Number of disks which have the key in the map. */ + unsigned m_cDisksPwProvided; + + /** Current active port modes of the supported serial ports. */ + PortMode_T m_aeSerialPortMode[4]; + + /** Pointer to the key consumer -> provider (that's us) callbacks. */ + struct MYPDMISECKEY : public PDMISECKEY + { + Console *pConsole; + } *mpIfSecKey; + + /** Pointer to the key helpers -> provider (that's us) callbacks. */ + struct MYPDMISECKEYHLP : public PDMISECKEYHLP + { + Console *pConsole; + } *mpIfSecKeyHlp; + +/* Note: FreeBSD needs this whether netflt is used or not. */ +#if ((defined(RT_OS_LINUX) && !defined(VBOX_WITH_NETFLT)) || defined(RT_OS_FREEBSD)) + Utf8Str maTAPDeviceName[8]; + RTFILE maTapFD[8]; +#endif + + bool mVMStateChangeCallbackDisabled; + + bool mfUseHostClipboard; + + /** Local machine state value. */ + MachineState_T mMachineState; + + /** Machine uuid string. */ + Bstr mstrUuid; + + /** @name Members related to the cryptographic support interface. + * @{ */ + /** The loaded module handle if loaded. */ + RTLDRMOD mhLdrModCrypto; + /** Reference counter tracking how many users of the cryptographic support + * are there currently. */ + volatile uint32_t mcRefsCrypto; + /** Pointer to the cryptographic support interface. */ + PCVBOXCRYPTOIF mpCryptoIf; + /** @} */ + +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION + /** Flag whether the log is encrypted. */ + bool m_fEncryptedLog; + /** The file handle of the encrypted log. */ + RTVFSFILE m_hVfsFileLog; + /** The logging output interface for encrypted logs. */ + RTLOGOUTPUTIF m_LogOutputIf; + /** The log file key ID. */ + Utf8Str m_strLogKeyId; + /** The log file key store. */ + Utf8Str m_strLogKeyStore; +#endif + +#ifdef VBOX_WITH_DRAG_AND_DROP + HGCMSVCEXTHANDLE m_hHgcmSvcExtDragAndDrop; +#endif + + /** Pointer to the progress object of a live cancelable task. + * + * This is currently only used by Console::Teleport(), but is intended to later + * be used by the live snapshot code path as well. Actions like + * Console::PowerDown, which automatically cancels out the running snapshot / + * teleportation operation, will cancel the teleportation / live snapshot + * operation before starting. */ + ComPtr<IProgress> mptrCancelableProgress; + + ComPtr<IEventListener> mVmListener; + +#ifdef VBOX_WITH_RECORDING + struct Recording + { + Recording() +# ifdef VBOX_WITH_AUDIO_RECORDING + : mAudioRec(NULL) +# endif + { } + + /** The recording context. */ + RecordingContext mCtx; +# ifdef VBOX_WITH_AUDIO_RECORDING + /** Pointer to capturing audio backend. */ + AudioVideoRec * const mAudioRec; +# endif + } mRecording; +#endif /* VBOX_WITH_RECORDING */ + +#ifdef VBOX_WITH_CLOUD_NET + GatewayInfo mGateway; +#endif /* VBOX_WITH_CLOUD_NET */ + + friend class VMTask; + friend class ConsoleVRDPServer; +}; + +#endif /* !MAIN_INCLUDED_ConsoleImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/ConsoleVRDPServer.h b/src/VBox/Main/include/ConsoleVRDPServer.h new file mode 100644 index 00000000..7ff88079 --- /dev/null +++ b/src/VBox/Main/include/ConsoleVRDPServer.h @@ -0,0 +1,428 @@ +/* $Id: ConsoleVRDPServer.h $ */ +/** @file + * VBox Console VRDE Server Helper class and implementation of IVRDEServerInfo + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ConsoleVRDPServer_h +#define MAIN_INCLUDED_ConsoleVRDPServer_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VRDEServerInfoWrap.h" +#include "RemoteUSBBackend.h" +#include "HGCM.h" + +#include "AuthLibrary.h" + +#include <VBox/RemoteDesktop/VRDEImage.h> +#include <VBox/RemoteDesktop/VRDEMousePtr.h> +#include <VBox/RemoteDesktop/VRDESCard.h> +#include <VBox/RemoteDesktop/VRDETSMF.h> +#define VRDE_VIDEOIN_WITH_VRDEINTERFACE /* Get the VRDE interface definitions. */ +#include <VBox/RemoteDesktop/VRDEVideoIn.h> +#include <VBox/RemoteDesktop/VRDEInput.h> + +#include <VBox/HostServices/VBoxClipboardExt.h> +#include <VBox/HostServices/VBoxHostChannel.h> + +#include "SchemaDefs.h" + +// ConsoleVRDPServer +/////////////////////////////////////////////////////////////////////////////// + +class EmWebcam; + +typedef struct _VRDPInputSynch +{ + int cGuestNumLockAdaptions; + int cGuestCapsLockAdaptions; + + bool fGuestNumLock; + bool fGuestCapsLock; + bool fGuestScrollLock; + + bool fClientNumLock; + bool fClientCapsLock; + bool fClientScrollLock; +} VRDPInputSynch; + +/* Member of Console. Helper class for VRDP server management. Not a COM class. */ +class ConsoleVRDPServer +{ +public: + DECLARE_TRANSLATE_METHODS(ConsoleVRDPServer) + + ConsoleVRDPServer (Console *console); + ~ConsoleVRDPServer (); + + int Launch (void); + + void NotifyAbsoluteMouse (bool fGuestWantsAbsolute) + { + m_fGuestWantsAbsolute = fGuestWantsAbsolute; + } + + void NotifyKeyboardLedsChange (BOOL fNumLock, BOOL fCapsLock, BOOL fScrollLock) + { + bool fGuestNumLock = (fNumLock != FALSE); + bool fGuestCapsLock = (fCapsLock != FALSE); + bool fGuestScrollLock = (fScrollLock != FALSE); + + /* Might need to resync in case the guest itself changed the LED status. */ + if (m_InputSynch.fClientNumLock != fGuestNumLock) + { + m_InputSynch.cGuestNumLockAdaptions = 2; + } + + if (m_InputSynch.fClientCapsLock != fGuestCapsLock) + { + m_InputSynch.cGuestCapsLockAdaptions = 2; + } + + m_InputSynch.fGuestNumLock = fGuestNumLock; + m_InputSynch.fGuestCapsLock = fGuestCapsLock; + m_InputSynch.fGuestScrollLock = fGuestScrollLock; + } + + void EnableConnections (void); + void DisconnectClient (uint32_t u32ClientId, bool fReconnect); + int MousePointer(BOOL alpha, ULONG xHot, ULONG yHot, ULONG width, ULONG height, const uint8_t *pu8Shape); + void MousePointerUpdate (const VRDECOLORPOINTER *pPointer); + void MousePointerHide (void); + + void Stop (void); + + AuthResult Authenticate (const Guid &uuid, AuthGuestJudgement guestJudgement, + const char *pszUser, const char *pszPassword, const char *pszDomain, + uint32_t u32ClientId); + + void AuthDisconnect (const Guid &uuid, uint32_t u32ClientId); + + void USBBackendCreate (uint32_t u32ClientId, void **ppvIntercept); + void USBBackendDelete (uint32_t u32ClientId); + + void *USBBackendRequestPointer (uint32_t u32ClientId, const Guid *pGuid); + void USBBackendReleasePointer (const Guid *pGuid); + + /* Private interface for the RemoteUSBBackend destructor. */ + void usbBackendRemoveFromList (RemoteUSBBackend *pRemoteUSBBackend); + + /* Private methods for the Remote USB thread. */ + RemoteUSBBackend *usbBackendGetNext (RemoteUSBBackend *pRemoteUSBBackend); + + void notifyRemoteUSBThreadRunning (RTTHREAD thread); + bool isRemoteUSBThreadRunning (void); + void waitRemoteUSBThreadEvent (RTMSINTERVAL cMillies); + + void ClipboardCreate (uint32_t u32ClientId); + void ClipboardDelete (uint32_t u32ClientId); + + /* + * Forwarders to VRDP server library. + */ + void SendUpdate (unsigned uScreenId, void *pvUpdate, uint32_t cbUpdate) const; + void SendResize (void); + void SendUpdateBitmap (unsigned uScreenId, uint32_t x, uint32_t y, uint32_t w, uint32_t h) const; + + void SendAudioSamples (void const *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format) const; + void SendAudioVolume (uint16_t left, uint16_t right) const; + void SendUSBRequest (uint32_t u32ClientId, void *pvParms, uint32_t cbParms) const; + + void QueryInfo (uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut) const; + + int SendAudioInputBegin(void **ppvUserCtx, + void *pvContext, + uint32_t cSamples, + uint32_t iSampleHz, + uint32_t cChannels, + uint32_t cBits); + + void SendAudioInputEnd(void *pvUserCtx); + + int SCardRequest(void *pvUser, uint32_t u32Function, const void *pvData, uint32_t cbData); + + int VideoInDeviceAttach(const VRDEVIDEOINDEVICEHANDLE *pDeviceHandle, void *pvDeviceCtx); + int VideoInDeviceDetach(const VRDEVIDEOINDEVICEHANDLE *pDeviceHandle); + int VideoInGetDeviceDesc(void *pvUser, const VRDEVIDEOINDEVICEHANDLE *pDeviceHandle); + int VideoInControl(void *pvUser, const VRDEVIDEOINDEVICEHANDLE *pDeviceHandle, + const VRDEVIDEOINCTRLHDR *pReq, uint32_t cbReq); + + Console *getConsole(void) { return mConsole; } + + void onMousePointerShapeChange(BOOL visible, BOOL alpha, ULONG xHot, ULONG yHot, + ULONG width, ULONG height, ComSafeArrayIn(BYTE,shape)); + +private: + /* Note: This is not a ComObjPtr here, because the ConsoleVRDPServer object + * is actually just a part of the Console. + */ + Console *mConsole; + + HVRDESERVER mhServer; + int mServerInterfaceVersion; + + int32_t volatile mcInResize; /* Do not Stop the server if this is not 0. */ + + static int loadVRDPLibrary (const char *pszLibraryName); + + /** Static because will never load this more than once! */ + static RTLDRMOD mVRDPLibrary; + + static PFNVRDECREATESERVER mpfnVRDECreateServer; + + static VRDEENTRYPOINTS_4 mEntryPoints; + static VRDEENTRYPOINTS_4 *mpEntryPoints; + static VRDECALLBACKS_4 mCallbacks; + + static DECLCALLBACK(int) VRDPCallbackQueryProperty (void *pvCallback, uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut); + static DECLCALLBACK(int) VRDPCallbackClientLogon (void *pvCallback, uint32_t u32ClientId, const char *pszUser, const char *pszPassword, const char *pszDomain); + static DECLCALLBACK(void) VRDPCallbackClientConnect (void *pvCallback, uint32_t u32ClientId); + static DECLCALLBACK(void) VRDPCallbackClientDisconnect (void *pvCallback, uint32_t u32ClientId, uint32_t fu32Intercepted); + static DECLCALLBACK(int) VRDPCallbackIntercept (void *pvCallback, uint32_t u32ClientId, uint32_t fu32Intercept, void **ppvIntercept); + static DECLCALLBACK(int) VRDPCallbackUSB (void *pvCallback, void *pvIntercept, uint32_t u32ClientId, uint8_t u8Code, const void *pvRet, uint32_t cbRet); + static DECLCALLBACK(int) VRDPCallbackClipboard (void *pvCallback, void *pvIntercept, uint32_t u32ClientId, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData); + static DECLCALLBACK(bool) VRDPCallbackFramebufferQuery (void *pvCallback, unsigned uScreenId, VRDEFRAMEBUFFERINFO *pInfo); + static DECLCALLBACK(void) VRDPCallbackFramebufferLock (void *pvCallback, unsigned uScreenId); + static DECLCALLBACK(void) VRDPCallbackFramebufferUnlock (void *pvCallback, unsigned uScreenId); + static DECLCALLBACK(void) VRDPCallbackInput (void *pvCallback, int type, const void *pvInput, unsigned cbInput); + static DECLCALLBACK(void) VRDPCallbackVideoModeHint (void *pvCallback, unsigned cWidth, unsigned cHeight, unsigned cBitsPerPixel, unsigned uScreenId); + static DECLCALLBACK(void) VRDECallbackAudioIn (void *pvCallback, void *pvCtx, uint32_t u32ClientId, uint32_t u32Event, const void *pvData, uint32_t cbData); + + void fetchCurrentState(void); + + bool m_fGuestWantsAbsolute; + int m_mousex; + int m_mousey; + + ComPtr<IDisplaySourceBitmap> maSourceBitmaps[SchemaDefs::MaxGuestMonitors]; + + ComPtr<IEventListener> mConsoleListener; + + VRDPInputSynch m_InputSynch; + + int32_t mVRDPBindPort; + + RTCRITSECT mCritSect; + + int lockConsoleVRDPServer (void); + void unlockConsoleVRDPServer (void); + + int mcClipboardRefs; + HGCMSVCEXTHANDLE mhClipboard; + PFNVRDPCLIPBOARDEXTCALLBACK mpfnClipboardCallback; + + static DECLCALLBACK(int) ClipboardCallback (void *pvCallback, uint32_t u32ClientId, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData); + static DECLCALLBACK(int) ClipboardServiceExtension(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms); + +#ifdef VBOX_WITH_USB + RemoteUSBBackend *usbBackendFindByUUID (const Guid *pGuid); + RemoteUSBBackend *usbBackendFind (uint32_t u32ClientId); + + typedef struct _USBBackends + { + RemoteUSBBackend *pHead; + RemoteUSBBackend *pTail; + + RTTHREAD thread; + + bool fThreadRunning; + + RTSEMEVENT event; + } USBBackends; + + USBBackends mUSBBackends; + + void remoteUSBThreadStart (void); + void remoteUSBThreadStop (void); +#endif /* VBOX_WITH_USB */ + +#ifndef VBOX_WITH_VRDEAUTH_IN_VBOXSVC + /* External authentication library context. The library is loaded in the + * Authenticate method and unloaded at the object destructor. + */ + AUTHLIBRARYCONTEXT mAuthLibCtx; +#endif + + uint32_t volatile mu32AudioInputClientId; + + int32_t volatile mcClients; + +#if 0 /** @todo Chromium got removed (see @bugref{9529}) and this is not available for VMSVGA yet. */ + static DECLCALLBACK(void) H3DORBegin(const void *pvContext, void **ppvInstance, + const char *pszFormat); + static DECLCALLBACK(void) H3DORGeometry(void *pvInstance, + int32_t x, int32_t y, uint32_t w, uint32_t h); + static DECLCALLBACK(void) H3DORVisibleRegion(void *pvInstance, + uint32_t cRects, const RTRECT *paRects); + static DECLCALLBACK(void) H3DORFrame(void *pvInstance, + void *pvData, uint32_t cbData); + static DECLCALLBACK(void) H3DOREnd(void *pvInstance); + static DECLCALLBACK(int) H3DORContextProperty(const void *pvContext, uint32_t index, + void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut); +#endif + + void remote3DRedirect(bool fEnable); + + /* + * VRDE server optional interfaces. + */ + + /* Image update interface. */ + bool m_fInterfaceImage; + VRDEIMAGECALLBACKS m_interfaceCallbacksImage; + VRDEIMAGEINTERFACE m_interfaceImage; + static DECLCALLBACK(int) VRDEImageCbNotify (void *pvContext, + void *pvUser, + HVRDEIMAGE hVideo, + uint32_t u32Id, + void *pvData, + uint32_t cbData); + /* Mouse pointer interface. */ + VRDEMOUSEPTRINTERFACE m_interfaceMousePtr; + + /* Smartcard interface. */ + VRDESCARDINTERFACE m_interfaceSCard; + VRDESCARDCALLBACKS m_interfaceCallbacksSCard; + static DECLCALLBACK(int) VRDESCardCbNotify(void *pvContext, + uint32_t u32Id, + void *pvData, + uint32_t cbData); + static DECLCALLBACK(int) VRDESCardCbResponse(void *pvContext, + int rcRequest, + void *pvUser, + uint32_t u32Function, + void *pvData, + uint32_t cbData); + + /* TSMF interface. */ + VRDETSMFINTERFACE m_interfaceTSMF; + VRDETSMFCALLBACKS m_interfaceCallbacksTSMF; + static DECLCALLBACK(void) VRDETSMFCbNotify(void *pvContext, + uint32_t u32Notification, + void *pvChannel, + const void *pvParm, + uint32_t cbParm); + void setupTSMF(void); + + static DECLCALLBACK(int) tsmfHostChannelAttach(void *pvProvider, void **ppvInstance, uint32_t u32Flags, + VBOXHOSTCHANNELCALLBACKS *pCallbacks, void *pvCallbacks); + static DECLCALLBACK(void) tsmfHostChannelDetach(void *pvInstance); + static DECLCALLBACK(int) tsmfHostChannelSend(void *pvInstance, const void *pvData, uint32_t cbData); + static DECLCALLBACK(int) tsmfHostChannelRecv(void *pvInstance, void *pvData, uint32_t cbData, + uint32_t *pcbReturned, uint32_t *pcbRemaining); + static DECLCALLBACK(int) tsmfHostChannelControl(void *pvInstance, uint32_t u32Code, + const void *pvParm, uint32_t cbParm, + const void *pvData, uint32_t cbData, uint32_t *pcbDataReturned); + int tsmfLock(void); + void tsmfUnlock(void); + RTCRITSECT mTSMFLock; + + /* Video input interface. */ + VRDEVIDEOININTERFACE m_interfaceVideoIn; + VRDEVIDEOINCALLBACKS m_interfaceCallbacksVideoIn; + static DECLCALLBACK(void) VRDECallbackVideoInNotify(void *pvCallback, + uint32_t u32Id, + const void *pvData, + uint32_t cbData); + static DECLCALLBACK(void) VRDECallbackVideoInDeviceDesc(void *pvCallback, + int rcRequest, + void *pDeviceCtx, + void *pvUser, + const VRDEVIDEOINDEVICEDESC *pDeviceDesc, + uint32_t cbDevice); + static DECLCALLBACK(void) VRDECallbackVideoInControl(void *pvCallback, + int rcRequest, + void *pDeviceCtx, + void *pvUser, + const VRDEVIDEOINCTRLHDR *pControl, + uint32_t cbControl); + static DECLCALLBACK(void) VRDECallbackVideoInFrame(void *pvCallback, + int rcRequest, + void *pDeviceCtx, + const VRDEVIDEOINPAYLOADHDR *pFrame, + uint32_t cbFrame); + EmWebcam *mEmWebcam; + + /* Input interface. */ + VRDEINPUTINTERFACE m_interfaceInput; + VRDEINPUTCALLBACKS m_interfaceCallbacksInput; + static DECLCALLBACK(void) VRDECallbackInputSetup(void *pvCallback, + int rcRequest, + uint32_t u32Method, + const void *pvResult, + uint32_t cbResult); + static DECLCALLBACK(void) VRDECallbackInputEvent(void *pvCallback, + uint32_t u32Method, + const void *pvEvent, + uint32_t cbEvent); + uint64_t mu64TouchInputTimestampMCS; +}; + + +class Console; + +class ATL_NO_VTABLE VRDEServerInfo : + public VRDEServerInfoWrap +{ +public: + DECLARE_NOT_AGGREGATABLE(VRDEServerInfo) + + DECLARE_COMMON_CLASS_METHODS(VRDEServerInfo) + + HRESULT FinalConstruct(); + void FinalRelease(); + + /* Public initializer/uninitializer for internal purposes only. */ + HRESULT init(Console *aParent); + void uninit(); + +private: + // wrapped IVRDEServerInfo properties +#define DECL_GETTER(_aType, _aName) virtual HRESULT get##_aName(_aType *a##_aName) +#define DECL_GETTER_REF(_aType, _aName) virtual HRESULT get##_aName(_aType &a##_aName) + DECL_GETTER(BOOL, Active); + DECL_GETTER(LONG, Port); + DECL_GETTER(ULONG, NumberOfClients); + DECL_GETTER(LONG64, BeginTime); + DECL_GETTER(LONG64, EndTime); + DECL_GETTER(LONG64, BytesSent); + DECL_GETTER(LONG64, BytesSentTotal); + DECL_GETTER(LONG64, BytesReceived); + DECL_GETTER(LONG64, BytesReceivedTotal); + DECL_GETTER_REF(com::Utf8Str, User); + DECL_GETTER_REF(com::Utf8Str, Domain); + DECL_GETTER_REF(com::Utf8Str, ClientName); + DECL_GETTER_REF(com::Utf8Str, ClientIP); + DECL_GETTER(ULONG, ClientVersion); + DECL_GETTER(ULONG, EncryptionStyle); +#undef DECL_GETTER_REF +#undef DECL_GETTER + + Console * const mParent; +}; + +#endif /* !MAIN_INCLUDED_ConsoleVRDPServer_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/CryptoUtils.h b/src/VBox/Main/include/CryptoUtils.h new file mode 100644 index 00000000..7db74b96 --- /dev/null +++ b/src/VBox/Main/include/CryptoUtils.h @@ -0,0 +1,141 @@ +/* $Id: CryptoUtils.h $ */ +/** @file + * Main - Cryptographic utility functions used by both VBoxSVC and VBoxC. + */ + +/* + * Copyright (C) 2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_CryptoUtils_h +#define MAIN_INCLUDED_CryptoUtils_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/vfs.h> + +#include <VBox/VBoxCryptoIf.h> +#include <VBox/com/string.h> + +#include <VBox/vmm/ssm.h> +#include <VBox/vmm/vmmr3vtable.h> +#include <VBox/vmm/vmapi.h> + +#include "SecretKeyStore.h" +#ifdef VBOX_COM_INPROC +# include "ConsoleImpl.h" +#else +# include "MachineImpl.h" +# include "VirtualBoxImpl.h" +#endif + + +/** + * Class handling encrypted and non encrypted SSM files. + */ +class SsmStream +{ + public: +#ifdef VBOX_COM_INPROC + SsmStream(Console *pParent, PCVMMR3VTABLE pVMM, SecretKeyStore *pKeyStore, const Utf8Str &strKeyId, const Utf8Str &strKeyStore); +#else + SsmStream(VirtualBox *pParent, SecretKeyStore *pKeyStore, const Utf8Str &strKeyId, const Utf8Str &strKeyStore); +#endif + ~SsmStream(); + + /** + * Actually opens the stream for either reading or writing. + * + * @returns VBox status code. + * @param strFilename The filename of the saved state to open or create. + * @param fWrite Flag whether the stream should be opened for writing (true) or readonly (false). + * @param ppSsmHandle Where to store the SSM handle on success, don't call SSMR3Close() but the provided close() method. + */ + int open(const Utf8Str &strFilename, bool fWrite, PSSMHANDLE *ppSsmHandle); + + /** + * Opens the saved state file for reading, doesn't call SSMR3Open(). + * + * @returns VBox status code. + * @param strFilename The filename of the saved state to open. + */ + int open(const Utf8Str &strFilename); + + /** + * Creates a new saved state file under the given path. + * + * @returns VBox status code. + * @param strFilename The filename of the saved state to create. + */ + int create(const Utf8Str &strFilename); + + /** + * Returns the pointer to the stream operations table after a succesful opening/creation. + * + * @return VBox status code. + * @param ppStrmOps Where to store the pointer to the stream operations table on success. + * @param ppvStrmOpsUser Where to store the pointer to the opaque user data on success. + */ + int querySsmStrmOps(PCSSMSTRMOPS *ppStrmOps, void **ppvStrmOpsUser); + + /** + * Closes an previously opened stream. + * + * @returns VBox status code. + */ + int close(void); + + private: + + static DECLCALLBACK(int) i_ssmCryptoWrite(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite); + static DECLCALLBACK(int) i_ssmCryptoRead(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead); + static DECLCALLBACK(int) i_ssmCryptoSeek(void *pvUser, int64_t offSeek, unsigned uMethod, uint64_t *poffActual); + static DECLCALLBACK(uint64_t) i_ssmCryptoTell(void *pvUser); + static DECLCALLBACK(int) i_ssmCryptoSize(void *pvUser, uint64_t *pcb); + static DECLCALLBACK(int) i_ssmCryptoIsOk(void *pvUser); + static DECLCALLBACK(int) i_ssmCryptoClose(void *pvUser, bool fCancelled); + +#ifdef VBOX_COM_INPROC + Console *m_pParent; + PCVMMR3VTABLE m_pVMM; +#else + VirtualBox *m_pParent; +#endif + /** The key store for getting at passwords. */ + SecretKeyStore *m_pKeyStore; + /** The key ID holding the password, empty if the saved state is not encrypted. */ + Utf8Str m_strKeyId; + /** The keystore holding the encrypted DEK. */ + Utf8Str m_strKeyStore; + /** The VFS file handle. */ + RTVFSFILE m_hVfsFile; + /** The SSM handle when opened. */ + PSSMHANDLE m_pSsm; + /** The SSM stream callbacks table. */ + SSMSTRMOPS m_StrmOps; + /** The cryptographic interfacer. */ + PCVBOXCRYPTOIF m_pCryptoIf; +}; + +#endif /* !MAIN_INCLUDED_CryptoUtils_h */ diff --git a/src/VBox/Main/include/DHCPConfigImpl.h b/src/VBox/Main/include/DHCPConfigImpl.h new file mode 100644 index 00000000..c0504716 --- /dev/null +++ b/src/VBox/Main/include/DHCPConfigImpl.h @@ -0,0 +1,529 @@ +/* $Id: DHCPConfigImpl.h $ */ +/** @file + * VirtualBox Main - IDHCPConfig, IDHCPConfigGlobal, IDHCPConfigGroup, IDHCPConfigIndividual header. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_DHCPConfigImpl_h +#define MAIN_INCLUDED_DHCPConfigImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "DHCPGlobalConfigWrap.h" +#include "DHCPGroupConditionWrap.h" +#include "DHCPGroupConfigWrap.h" +#include "DHCPIndividualConfigWrap.h" +#include <VBox/settings.h> + + +class DHCPServer; +class DHCPGroupConfig; + + +/** + * Base class for the a DHCP configration layer. + * + * This does not inherit from DHCPConfigWrap because its children need to + * inherit from children of DHCPConfigWrap, which smells like trouble and thus + * wasn't even attempted. Instead, we have a hack for passing a pointer that we + * can call setError and such on. + */ +class DHCPConfig +{ +protected: + /** Config scope (global, group, vm+nic, mac). */ + DHCPConfigScope_T const m_enmScope; + /** Minimum lease time. */ + ULONG m_secMinLeaseTime; + /** Default lease time. */ + ULONG m_secDefaultLeaseTime; + /** Maximum lease time. */ + ULONG m_secMaxLeaseTime; + /** List of options which are forced upon the client when available, whether + * requested by it or not. */ + std::vector<DHCPOption_T> m_vecForcedOptions; + /** List of options which should be suppressed and not returned the the client + * when available and requested. */ + std::vector<DHCPOption_T> m_vecSuppressedOptions; + /** DHCP option map. */ + settings::DhcpOptionMap m_OptionMap; + /** The DHCP server parent (weak). */ + DHCPServer * const m_pParent; + /** The DHCP server parent (weak). */ + VirtualBox * const m_pVirtualBox; +private: + /** For setError and such. */ + VirtualBoxBase * const m_pHack; + +protected: + /** @name Constructors and destructors. + * @{ */ + DHCPConfig(DHCPConfigScope_T a_enmScope, VirtualBoxBase *a_pHack) + : m_enmScope(a_enmScope), m_secMinLeaseTime(0), m_secDefaultLeaseTime(0), m_secMaxLeaseTime(0), m_OptionMap() + , m_pParent(NULL), m_pVirtualBox(NULL), m_pHack(a_pHack) + {} + DHCPConfig(); + virtual ~DHCPConfig() + {} + HRESULT i_initWithDefaults(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent); + HRESULT i_initWithSettings(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, const settings::DHCPConfig &rConfig); + /** @} */ + + /** @name IDHCPConfig properties + * @{ */ + HRESULT i_getScope(DHCPConfigScope_T *aScope); + HRESULT i_getMinLeaseTime(ULONG *aMinLeaseTime); + HRESULT i_setMinLeaseTime(ULONG aMinLeaseTime); + HRESULT i_getDefaultLeaseTime(ULONG *aDefaultLeaseTime); + HRESULT i_setDefaultLeaseTime(ULONG aDefaultLeaseTime); + HRESULT i_getMaxLeaseTime(ULONG *aMaxLeaseTime); + HRESULT i_setMaxLeaseTime(ULONG aMaxLeaseTime); + HRESULT i_getForcedOptions(std::vector<DHCPOption_T> &aOptions); + HRESULT i_setForcedOptions(const std::vector<DHCPOption_T> &aOptions); + HRESULT i_getSuppressedOptions(std::vector<DHCPOption_T> &aOptions); + HRESULT i_setSuppressedOptions(const std::vector<DHCPOption_T> &aOptions); + /** @} */ + +public: + DECLARE_TRANSLATE_METHODS(DHCPConfig) + + /** @name IDHCPConfig methods + * @note public because the DHCPServer needs them for 6.0 interfaces. + * @todo Make protected again when IDHCPServer is cleaned up. + * @{ */ + virtual HRESULT i_setOption(DHCPOption_T aOption, DHCPOptionEncoding_T aEncoding, const com::Utf8Str &aValue); + + virtual HRESULT i_removeOption(DHCPOption_T aOption); + virtual HRESULT i_removeAllOptions(); + HRESULT i_getOption(DHCPOption_T aOption, DHCPOptionEncoding_T *aEncoding, com::Utf8Str &aValue); + HRESULT i_getAllOptions(std::vector<DHCPOption_T> &aOptions, std::vector<DHCPOptionEncoding_T> &aEncodings, + std::vector<com::Utf8Str> &aValues); + virtual HRESULT i_remove(); + /** @} */ + + +public: + HRESULT i_doWriteConfig(); + HRESULT i_saveSettings(settings::DHCPConfig &a_rDst); + DHCPConfigScope_T i_getScope() const RT_NOEXCEPT { return m_enmScope; } + virtual void i_writeDhcpdConfig(xml::ElementNode *pElm); +}; + + +/** + * Global DHCP configuration. + */ +class DHCPGlobalConfig : public DHCPGlobalConfigWrap, public DHCPConfig +{ +public: + DECLARE_TRANSLATE_METHODS(DHCPGlobalConfig) + + /** @name Constructors and destructors. + * @{ */ + DHCPGlobalConfig() + : DHCPConfig(DHCPConfigScope_Global, this) + { } + HRESULT FinalConstruct() + { + return BaseFinalConstruct(); + } + void FinalRelease() + { + uninit(); + BaseFinalRelease(); + } + HRESULT initWithDefaults(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent); + HRESULT initWithSettings(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, const settings::DHCPConfig &rConfig); + void uninit(); + /** @} */ + + HRESULT i_saveSettings(settings::DHCPConfig &a_rDst); + HRESULT i_getNetworkMask(com::Utf8Str &a_rDst); + HRESULT i_setNetworkMask(const com::Utf8Str &a_rSrc); + +protected: + /** @name wrapped IDHCPConfig properties + * @{ */ + HRESULT getScope(DHCPConfigScope_T *aScope) RT_OVERRIDE { return i_getScope(aScope); } + HRESULT getMinLeaseTime(ULONG *aMinLeaseTime) RT_OVERRIDE { return i_getMinLeaseTime(aMinLeaseTime); } + HRESULT setMinLeaseTime(ULONG aMinLeaseTime) RT_OVERRIDE { return i_setMinLeaseTime(aMinLeaseTime); } + HRESULT getDefaultLeaseTime(ULONG *aDefaultLeaseTime) RT_OVERRIDE { return i_getDefaultLeaseTime(aDefaultLeaseTime); } + HRESULT setDefaultLeaseTime(ULONG aDefaultLeaseTime) RT_OVERRIDE { return i_setDefaultLeaseTime(aDefaultLeaseTime); } + HRESULT getMaxLeaseTime(ULONG *aMaxLeaseTime) RT_OVERRIDE { return i_getMaxLeaseTime(aMaxLeaseTime); } + HRESULT setMaxLeaseTime(ULONG aMaxLeaseTime) RT_OVERRIDE { return i_setMaxLeaseTime(aMaxLeaseTime); } + HRESULT getForcedOptions(std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_getForcedOptions(aOptions); } + HRESULT setForcedOptions(const std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_setForcedOptions(aOptions); } + HRESULT getSuppressedOptions(std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_getSuppressedOptions(aOptions); } + HRESULT setSuppressedOptions(const std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_setSuppressedOptions(aOptions); } + /** @} */ + + /** @name wrapped IDHCPConfig methods + * @{ */ + HRESULT setOption(DHCPOption_T aOption, DHCPOptionEncoding_T aEncoding, const com::Utf8Str &aValue) RT_OVERRIDE + { + return i_setOption(aOption, aEncoding, aValue); + } + + HRESULT removeOption(DHCPOption_T aOption) RT_OVERRIDE + { + return i_removeOption(aOption); + } + + HRESULT removeAllOptions() RT_OVERRIDE + { + return i_removeAllOptions(); + } + + HRESULT getOption(DHCPOption_T aOption, DHCPOptionEncoding_T *aEncoding, com::Utf8Str &aValue) RT_OVERRIDE + { + return i_getOption(aOption, aEncoding, aValue); + } + + HRESULT getAllOptions(std::vector<DHCPOption_T> &aOptions, std::vector<DHCPOptionEncoding_T> &aEncodings, + std::vector<com::Utf8Str> &aValues) RT_OVERRIDE + { + return i_getAllOptions(aOptions, aEncodings, aValues); + } + + HRESULT remove() RT_OVERRIDE + { + return i_remove(); + } + /** @} */ + +public: + HRESULT i_setOption(DHCPOption_T aOption, DHCPOptionEncoding_T aEncoding, const com::Utf8Str &aValue) RT_OVERRIDE; + HRESULT i_removeOption(DHCPOption_T aOption) RT_OVERRIDE; + HRESULT i_removeAllOptions() RT_OVERRIDE; + HRESULT i_remove() RT_OVERRIDE; +}; + + +/** + * DHCP Group inclusion/exclusion condition. + */ +class DHCPGroupCondition : public DHCPGroupConditionWrap +{ +private: + /** Inclusive or exclusive condition. */ + bool m_fInclusive; + /** The condition type (or how m_strValue should be interpreted). */ + DHCPGroupConditionType_T m_enmType; + /** The value. Interpreted according to m_enmType. */ + com::Utf8Str m_strValue; + /** Pointer to the parent (weak). */ + DHCPGroupConfig *m_pParent; + +public: + DECLARE_TRANSLATE_METHODS(DHCPGroupCondition) + + /** @name Constructors and destructors. + * @{ */ + DHCPGroupCondition() + : m_enmType(DHCPGroupConditionType_MAC) + , m_pParent(NULL) + {} + HRESULT FinalConstruct() + { + return BaseFinalConstruct(); + } + void FinalRelease() + { + uninit(); + BaseFinalRelease(); + } + HRESULT initWithDefaults(DHCPGroupConfig *a_pParent, bool a_fInclusive, DHCPGroupConditionType_T a_enmType, + const com::Utf8Str a_strValue); + HRESULT initWithSettings(DHCPGroupConfig *a_pParent, const settings::DHCPGroupCondition &a_rSrc); + void uninit(); + /** @} */ + + HRESULT i_saveSettings(settings::DHCPGroupCondition &a_rDst); + static HRESULT i_validateTypeAndValue(DHCPGroupConditionType_T enmType, com::Utf8Str const &strValue, + VirtualBoxBase *pErrorDst); + + /** @name Internal accessors + * @{ */ + bool i_getInclusive() const RT_NOEXCEPT { return m_fInclusive; } + DHCPGroupConditionType_T i_getType() const RT_NOEXCEPT { return m_enmType; } + com::Utf8Str const &i_getValue() const RT_NOEXCEPT { return m_strValue; } + /** @} */ + +protected: + /** @name Wrapped IDHCPGroupCondition properties + * @{ */ + HRESULT getInclusive(BOOL *aInclusive) RT_OVERRIDE; + HRESULT setInclusive(BOOL aInclusive) RT_OVERRIDE; + HRESULT getType(DHCPGroupConditionType_T *aType) RT_OVERRIDE; + HRESULT setType(DHCPGroupConditionType_T aType) RT_OVERRIDE; + HRESULT getValue(com::Utf8Str &aValue) RT_OVERRIDE; + HRESULT setValue(const com::Utf8Str &aValue) RT_OVERRIDE; + /** @} */ + + /** @name Wrapped IDHCPGroupCondition methods + * @{ */ + HRESULT remove() RT_OVERRIDE; + /** @} */ +}; + + +/** + * Group configuration. + */ +class DHCPGroupConfig : public DHCPGroupConfigWrap, public DHCPConfig +{ +private: + /** Group name. */ + com::Utf8Str m_strName; + /** Group membership conditions. */ + std::vector<ComObjPtr<DHCPGroupCondition> > m_Conditions; + /** Iterator for m_Conditions. */ + typedef std::vector<ComObjPtr<DHCPGroupCondition> >::iterator ConditionsIterator; + +public: + DECLARE_TRANSLATE_METHODS(DHCPGroupConfig) + + /** @name Constructors and destructors. + * @{ */ + DHCPGroupConfig() + : DHCPConfig(DHCPConfigScope_Group, this) + { } + HRESULT FinalConstruct() + { + return BaseFinalConstruct(); + } + void FinalRelease() + { + uninit(); + BaseFinalRelease(); + } + HRESULT initWithDefaults(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, const com::Utf8Str &a_rName); + HRESULT initWithSettings(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, const settings::DHCPGroupConfig &a_rSrc); + void uninit(); + /** @} */ + + HRESULT i_saveSettings(settings::DHCPGroupConfig &a_rDst); + HRESULT i_removeCondition(DHCPGroupCondition *a_pCondition); + void i_writeDhcpdConfig(xml::ElementNode *a_pElmGroup) RT_OVERRIDE; + +protected: + /** @name Wrapped IDHCPConfig properties + * @{ */ + HRESULT getScope(DHCPConfigScope_T *aScope) RT_OVERRIDE { return i_getScope(aScope); } + HRESULT getMinLeaseTime(ULONG *aMinLeaseTime) RT_OVERRIDE { return i_getMinLeaseTime(aMinLeaseTime); } + HRESULT setMinLeaseTime(ULONG aMinLeaseTime) RT_OVERRIDE { return i_setMinLeaseTime(aMinLeaseTime); } + HRESULT getDefaultLeaseTime(ULONG *aDefaultLeaseTime) RT_OVERRIDE { return i_getDefaultLeaseTime(aDefaultLeaseTime); } + HRESULT setDefaultLeaseTime(ULONG aDefaultLeaseTime) RT_OVERRIDE { return i_setDefaultLeaseTime(aDefaultLeaseTime); } + HRESULT getMaxLeaseTime(ULONG *aMaxLeaseTime) RT_OVERRIDE { return i_getMaxLeaseTime(aMaxLeaseTime); } + HRESULT setMaxLeaseTime(ULONG aMaxLeaseTime) RT_OVERRIDE { return i_setMaxLeaseTime(aMaxLeaseTime); } + HRESULT getForcedOptions(std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_getForcedOptions(aOptions); } + HRESULT setForcedOptions(const std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_setForcedOptions(aOptions); } + HRESULT getSuppressedOptions(std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_getSuppressedOptions(aOptions); } + HRESULT setSuppressedOptions(const std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_setSuppressedOptions(aOptions); } + /** @} */ + + /** @name Wrapped IDHCPGroupConfig properties + * @{ */ + HRESULT getName(com::Utf8Str &aName) RT_OVERRIDE; + HRESULT setName(const com::Utf8Str &aName) RT_OVERRIDE; + HRESULT getConditions(std::vector<ComPtr<IDHCPGroupCondition> > &aConditions) RT_OVERRIDE; + /** @} */ + + /** @name Wrapped IDHCPConfig methods + * @{ */ + HRESULT setOption(DHCPOption_T aOption, DHCPOptionEncoding_T aEncoding, const com::Utf8Str &aValue) RT_OVERRIDE + { + return i_setOption(aOption, aEncoding, aValue); + } + + HRESULT removeOption(DHCPOption_T aOption) RT_OVERRIDE + { + return i_removeOption(aOption); + } + + HRESULT removeAllOptions() RT_OVERRIDE + { + return i_removeAllOptions(); + } + + HRESULT getOption(DHCPOption_T aOption, DHCPOptionEncoding_T *aEncoding, com::Utf8Str &aValue) RT_OVERRIDE + { + return i_getOption(aOption, aEncoding, aValue); + } + + HRESULT getAllOptions(std::vector<DHCPOption_T> &aOptions, std::vector<DHCPOptionEncoding_T> &aEncodings, + std::vector<com::Utf8Str> &aValues) RT_OVERRIDE + { + return i_getAllOptions(aOptions, aEncodings, aValues); + } + + HRESULT remove() RT_OVERRIDE + { + return i_remove(); + } + /** @} */ + + /** @name Wrapped IDHCPGroupConfig methods + * @{ */ + HRESULT addCondition(BOOL aInclusive, DHCPGroupConditionType_T aType, const com::Utf8Str &aValue, + ComPtr<IDHCPGroupCondition> &aCondition) RT_OVERRIDE; + HRESULT removeAllConditions() RT_OVERRIDE; + /** @} */ +}; + + +/** + * Individual DHCP configuration. + */ +class DHCPIndividualConfig : public DHCPIndividualConfigWrap, public DHCPConfig +{ +private: + /** The MAC address or all zeros. */ + RTMAC m_MACAddress; + /** The VM ID or all zeros. */ + com::Guid const m_idMachine; + /** The VM NIC slot number, or ~(ULONG)0. */ + ULONG const m_uSlot; + /** This is part of a hack to resolve the MAC address for + * DHCPConfigScope_MachineNIC instances. If non-zero, we m_MACAddress is valid. + * To deal with the impossibly theoretical scenario that the DHCP server is + * being started by more than one thread, this is a version number and not just + * a boolean indicator. */ + uint32_t volatile m_uMACAddressResolvedVersion; + + /** The fixed IPv4 address, empty if dynamic. */ + com::Utf8Str m_strFixedAddress; + +public: + DECLARE_TRANSLATE_METHODS(DHCPIndividualConfig) + + /** @name Constructors and destructors. + * @{ */ + DHCPIndividualConfig() + : DHCPConfig(DHCPConfigScope_MAC, this) + , m_uSlot(~(ULONG)0) + , m_uMACAddressResolvedVersion(0) + { + RT_ZERO(m_MACAddress); + } + HRESULT FinalConstruct() + { + return BaseFinalConstruct(); + } + void FinalRelease() + { + uninit(); + BaseFinalRelease(); + } + HRESULT initWithMachineIdAndSlot(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, com::Guid const &a_idMachine, + ULONG a_uSlot, uint32_t a_uMACAddressVersion); + HRESULT initWithMACAddress(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, PCRTMAC a_pMACAddress); + HRESULT initWithSettingsAndMachineIdAndSlot(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, + const settings::DHCPIndividualConfig &rData, com::Guid const &a_idMachine, + ULONG a_uSlot, uint32_t a_uMACAddressVersion); + HRESULT initWithSettingsAndMACAddress(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, + const settings::DHCPIndividualConfig &rData, PCRTMAC a_pMACAddress); + void uninit(); + /** @} */ + + /** @name Internal methods that are public for various reasons + * @{ */ + HRESULT i_saveSettings(settings::DHCPIndividualConfig &a_rDst); + RTMAC const &i_getMACAddress() const RT_NOEXCEPT { return m_MACAddress; } + com::Guid const &i_getMachineId() const RT_NOEXCEPT { return m_idMachine; } + ULONG i_getSlot() const RT_NOEXCEPT { return m_uSlot; } + HRESULT i_getMachineMAC(PRTMAC pMACAddress); + + HRESULT i_resolveMACAddress(uint32_t uVersion); + /** This is used to avoid producing bogus Dhcpd configuration elements. */ + bool i_isMACAddressResolved(uint32_t uVersion) const + { + return m_enmScope != DHCPConfigScope_MachineNIC || (int32_t)(m_uMACAddressResolvedVersion - uVersion) >= 0; + } + void i_writeDhcpdConfig(xml::ElementNode *pElm) RT_OVERRIDE; + /** @} */ + +protected: + /** @name wrapped IDHCPConfig properties + * @{ */ + HRESULT getScope(DHCPConfigScope_T *aScope) RT_OVERRIDE { return i_getScope(aScope); } + HRESULT getMinLeaseTime(ULONG *aMinLeaseTime) RT_OVERRIDE { return i_getMinLeaseTime(aMinLeaseTime); } + HRESULT setMinLeaseTime(ULONG aMinLeaseTime) RT_OVERRIDE { return i_setMinLeaseTime(aMinLeaseTime); } + HRESULT getDefaultLeaseTime(ULONG *aDefaultLeaseTime) RT_OVERRIDE { return i_getDefaultLeaseTime(aDefaultLeaseTime); } + HRESULT setDefaultLeaseTime(ULONG aDefaultLeaseTime) RT_OVERRIDE { return i_setDefaultLeaseTime(aDefaultLeaseTime); } + HRESULT getMaxLeaseTime(ULONG *aMaxLeaseTime) RT_OVERRIDE { return i_getMaxLeaseTime(aMaxLeaseTime); } + HRESULT setMaxLeaseTime(ULONG aMaxLeaseTime) RT_OVERRIDE { return i_setMaxLeaseTime(aMaxLeaseTime); } + HRESULT getForcedOptions(std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_getForcedOptions(aOptions); } + HRESULT setForcedOptions(const std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_setForcedOptions(aOptions); } + HRESULT getSuppressedOptions(std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_getSuppressedOptions(aOptions); } + HRESULT setSuppressedOptions(const std::vector<DHCPOption_T> &aOptions) RT_OVERRIDE { return i_setSuppressedOptions(aOptions); } + /** @} */ + + /** @name wrapped IDHCPConfig methods + * @{ */ + HRESULT setOption(DHCPOption_T aOption, DHCPOptionEncoding_T aEncoding, const com::Utf8Str &aValue) RT_OVERRIDE + { + return i_setOption(aOption, aEncoding, aValue); + } + + HRESULT removeOption(DHCPOption_T aOption) RT_OVERRIDE + { + return i_removeOption(aOption); + } + + HRESULT removeAllOptions() RT_OVERRIDE + { + return i_removeAllOptions(); + } + + HRESULT getOption(DHCPOption_T aOption, DHCPOptionEncoding_T *aEncoding, com::Utf8Str &aValue) RT_OVERRIDE + { + return i_getOption(aOption, aEncoding, aValue); + } + + HRESULT getAllOptions(std::vector<DHCPOption_T> &aOptions, std::vector<DHCPOptionEncoding_T> &aEncodings, + std::vector<com::Utf8Str> &aValues) RT_OVERRIDE + { + return i_getAllOptions(aOptions, aEncodings, aValues); + } + + HRESULT remove() RT_OVERRIDE + { + return i_remove(); + } + /** @} */ + + /** @name IDHCPIndividualConfig properties + * @{ */ + HRESULT getMACAddress(com::Utf8Str &aMacAddress) RT_OVERRIDE; + HRESULT getMachineId(com::Guid &aId) RT_OVERRIDE; + HRESULT getSlot(ULONG *aSlot) RT_OVERRIDE; + HRESULT getFixedAddress(com::Utf8Str &aFixedAddress) RT_OVERRIDE; + HRESULT setFixedAddress(const com::Utf8Str &aFixedAddress) RT_OVERRIDE; + /** @} */ +}; + +#endif /* !MAIN_INCLUDED_DHCPConfigImpl_h */ + diff --git a/src/VBox/Main/include/DHCPServerImpl.h b/src/VBox/Main/include/DHCPServerImpl.h new file mode 100644 index 00000000..cac13d18 --- /dev/null +++ b/src/VBox/Main/include/DHCPServerImpl.h @@ -0,0 +1,130 @@ +/* $Id: DHCPServerImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_DHCPServerImpl_h +#define MAIN_INCLUDED_DHCPServerImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "DHCPServerWrap.h" +#include <map> + +namespace settings +{ + struct DHCPServer; + struct DhcpOptValue; + typedef std::map<DHCPOption_T, DhcpOptValue> DhcpOptionMap; +} + +class DHCPConfig; +class DHCPIndividualConfig; + +/** + * A DHCP server for internal host-only & NAT networks. + * + * Old notes: + * + * for server configuration needs, it's perhaps better to use (VM,slot) pair + * (vm-name, slot) <----> (MAC) + * + * but for client configuration, when server will have MACs at hand, it'd be + * easier to requiest options by MAC. + * (MAC) <----> (option-list) + * + * Doubts: What should be done if MAC changed for (vm-name, slot), when syncing should? + * XML: serialization of dependecy (DHCP options) - (VM,slot) shouldn't be done via MAC in + * the middle. + */ +class ATL_NO_VTABLE DHCPServer + : public DHCPServerWrap +{ +public: + /** @name Constructors and destructors + * @{ */ + DECLARE_COMMON_CLASS_METHODS(DHCPServer) + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT init(VirtualBox *aVirtualBox, const com::Utf8Str &aName); + HRESULT init(VirtualBox *aVirtualBox, const settings::DHCPServer &data); + void uninit(); + /** @} */ + + /** @name Public internal methods. + * @{ */ + HRESULT i_saveSettings(settings::DHCPServer &data); + HRESULT i_removeConfig(DHCPConfig *pConfig, DHCPConfigScope_T enmScope); + /** @} */ + +private: + /** @name IDHCPServer Properties + * @{ */ + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource) RT_OVERRIDE; + HRESULT getEnabled(BOOL *aEnabled) RT_OVERRIDE; + HRESULT setEnabled(BOOL aEnabled) RT_OVERRIDE; + HRESULT getIPAddress(com::Utf8Str &aIPAddress) RT_OVERRIDE; + HRESULT getNetworkMask(com::Utf8Str &aNetworkMask) RT_OVERRIDE; + HRESULT getNetworkName(com::Utf8Str &aName) RT_OVERRIDE; + HRESULT getLowerIP(com::Utf8Str &aIPAddress) RT_OVERRIDE; + HRESULT getUpperIP(com::Utf8Str &aIPAddress) RT_OVERRIDE; + HRESULT setConfiguration(const com::Utf8Str &aIPAddress, const com::Utf8Str &aNetworkMask, + const com::Utf8Str &aFromIPAddress, const com::Utf8Str &aToIPAddress) RT_OVERRIDE; + HRESULT getGlobalConfig(ComPtr<IDHCPGlobalConfig> &aGlobalConfig) RT_OVERRIDE; + HRESULT getGroupConfigs(std::vector<ComPtr<IDHCPGroupConfig> > &aGroupConfigs) RT_OVERRIDE; + HRESULT getIndividualConfigs(std::vector<ComPtr<IDHCPIndividualConfig> > &aIndividualConfigs) ; + /** @} */ + + /** @name IDHCPServer Methods + * @{ */ + HRESULT start(const com::Utf8Str &aTrunkName, const com::Utf8Str &aTrunkType) RT_OVERRIDE; + HRESULT stop() RT_OVERRIDE; + HRESULT restart() RT_OVERRIDE; + HRESULT findLeaseByMAC(const com::Utf8Str &aMac, LONG aType, com::Utf8Str &aAddress, com::Utf8Str &aState, + LONG64 *aIssued, LONG64 *aExpire) RT_OVERRIDE; + HRESULT getConfig(DHCPConfigScope_T aScope, const com::Utf8Str &aName, ULONG aSlot, BOOL aMayAdd, + ComPtr<IDHCPConfig> &aConfig) RT_OVERRIDE; + /** @} */ + + /** @name Helpers + * @{ */ + HRESULT i_doSaveSettings(); + HRESULT i_calcLeasesConfigAndLogFilenames(const com::Utf8Str &aNetwork) RT_NOEXCEPT; + HRESULT i_writeDhcpdConfig(const char *pszFilename, uint32_t uMACAddressVersion) RT_NOEXCEPT; + + HRESULT i_vmNameToIdAndValidateSlot(const com::Utf8Str &aVmName, ULONG a_uSlot, com::Guid &idMachine); + HRESULT i_vmNameAndSlotToConfig(const com::Utf8Str &a_strVmName, ULONG a_uSlot, bool a_fCreateIfNeeded, + ComObjPtr<DHCPIndividualConfig> &a_rPtrConfig); + /** @} */ + + /** Private data */ + struct Data; + /** Private data. */ + Data *m; +}; + +#endif /* !MAIN_INCLUDED_DHCPServerImpl_h */ diff --git a/src/VBox/Main/include/DataStreamImpl.h b/src/VBox/Main/include/DataStreamImpl.h new file mode 100644 index 00000000..8239dcd7 --- /dev/null +++ b/src/VBox/Main/include/DataStreamImpl.h @@ -0,0 +1,78 @@ +/* $Id: DataStreamImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2018-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_DataStreamImpl_h +#define MAIN_INCLUDED_DataStreamImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "DataStreamWrap.h" + +#include <iprt/circbuf.h> +#include <iprt/semaphore.h> + +class ATL_NO_VTABLE DataStream + : public DataStreamWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(DataStream) + + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT init(unsigned long aBufferSize); + void uninit(); + + /// Feed data into the stream, used by the stream source. + /// Blocks if the internal buffer cannot take anything, otherwise + /// as much as the internal buffer can hold is taken (if smaller + /// than @a cbWrite). Modeled after RTStrmWriteEx. + int i_write(const void *pvBuf, size_t cbWrite, size_t *pcbWritten); + + /// Marks the end of the stream. + int i_close(); + +private: + // wrapped IDataStream attributes and methods + HRESULT getReadSize(ULONG *aReadSize); + HRESULT read(ULONG aSize, ULONG aTimeoutMS, std::vector<BYTE> &aData); + +private: + /** The temporary buffer the conversion process writes into and the user reads from. */ + PRTCIRCBUF m_pBuffer; + /** Event semaphore for waiting until data is available. */ + RTSEMEVENT m_hSemEvtDataAvail; + /** Event semaphore for waiting until there is room in the buffer for writing. */ + RTSEMEVENT m_hSemEvtBufSpcAvail; + /** Flag whether the end of stream flag is set. */ + bool m_fEos; +}; + +#endif /* !MAIN_INCLUDED_DataStreamImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/DisplayImpl.h b/src/VBox/Main/include/DisplayImpl.h new file mode 100644 index 00000000..a17b626e --- /dev/null +++ b/src/VBox/Main/include/DisplayImpl.h @@ -0,0 +1,562 @@ +/* $Id: DisplayImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_DisplayImpl_h +#define MAIN_INCLUDED_DisplayImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "SchemaDefs.h" + +#include <iprt/semaphore.h> +#include <VBox/vmm/pdmdrv.h> +#include <VBoxVideo.h> +#include <VBox/vmm/pdmifs.h> +#include <VBox/VMMDev.h> /* For struct VMMDevDisplayDef - why is it in that file? */ +#include "DisplayWrap.h" + +#include "DisplaySourceBitmapWrap.h" +#include "GuestScreenInfoWrap.h" + + +class Console; + +typedef struct _DISPLAYFBINFO +{ + /* The following 3 fields (u32Offset, u32MaxFramebufferSize and u32InformationSize) + * are not used by the current HGSMI. They are needed for backward compatibility with + * pre-HGSMI additions. + */ + uint32_t u32Offset; + uint32_t u32MaxFramebufferSize; + uint32_t u32InformationSize; + + ComPtr<IFramebuffer> pFramebuffer; + com::Guid framebufferId; + ComPtr<IDisplaySourceBitmap> pSourceBitmap; + bool fDisabled; + + uint32_t u32Caps; + + struct + { + ComPtr<IDisplaySourceBitmap> pSourceBitmap; + uint8_t *pu8Address; + uint32_t cbLine; + } updateImage; + + LONG xOrigin; + LONG yOrigin; + + ULONG w; + ULONG h; + + uint16_t u16BitsPerPixel; + uint8_t *pu8FramebufferVRAM; + uint32_t u32LineSize; + + uint16_t flags; + + VBOXVIDEOINFOHOSTEVENTS *pHostEvents; + + /** The framebuffer has default format and must be updates immediately. */ + bool fDefaultFormat; + +#ifdef VBOX_WITH_HGSMI + bool fVBVAEnabled; + bool fVBVAForceResize; + VBVAHOSTFLAGS RT_UNTRUSTED_VOLATILE_GUEST *pVBVAHostFlags; +#endif /* VBOX_WITH_HGSMI */ + +#ifdef VBOX_WITH_RECORDING + struct + { + ComPtr<IDisplaySourceBitmap> pSourceBitmap; + } Recording; +#endif /* VBOX_WITH_RECORDING */ + + /** Description of the currently plugged monitor with preferred mode, + * a.k.a the last mode hint sent. */ + struct VMMDevDisplayDef monitorDesc; +} DISPLAYFBINFO; + +/* The legacy VBVA (VideoAccel) data. + * + * Backward compatibility with the Guest Additions 3.x or older. + */ +typedef struct VIDEOACCEL +{ + VBVAMEMORY *pVbvaMemory; + bool fVideoAccelEnabled; + + uint8_t *pu8VbvaPartial; + uint32_t cbVbvaPartial; + + /* Old Guest Additions (3.x and older) use both VMMDev and DevVGA refresh timer + * to process the VBVABUFFER memory. Therefore the legacy VBVA (VideoAccel) host + * code can be executed concurrently by VGA refresh timer and the guest VMMDev + * request in SMP VMs. The semaphore serialized this. + */ + RTSEMXROADS hXRoadsVideoAccel; + +} VIDEOACCEL; + +class DisplayMouseInterface +{ +public: + virtual ~DisplayMouseInterface() { } + virtual HRESULT i_getScreenResolution(ULONG cScreen, ULONG *pcx, + ULONG *pcy, ULONG *pcBPP, LONG *pXOrigin, LONG *pYOrigin) = 0; + virtual void i_getFramebufferDimensions(int32_t *px1, int32_t *py1, + int32_t *px2, int32_t *py2) = 0; + virtual HRESULT i_reportHostCursorCapabilities(uint32_t fCapabilitiesAdded, uint32_t fCapabilitiesRemoved) = 0; + virtual HRESULT i_reportHostCursorPosition(int32_t x, int32_t y, bool fOutOfRange) = 0; + virtual bool i_isInputMappingSet(void) = 0; +}; + +class VMMDev; + +class ATL_NO_VTABLE Display : + public DisplayWrap, + public DisplayMouseInterface +{ +public: + + DECLARE_COMMON_CLASS_METHODS(Display) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Console *aParent); + void uninit(); + int i_registerSSM(PUVM pUVM); + + // public methods only for internal purposes + unsigned i_getMonitorCount() { return mcMonitors; } + int i_handleDisplayResize(unsigned uScreenId, uint32_t bpp, void *pvVRAM, + uint32_t cbLine, uint32_t w, uint32_t h, uint16_t flags, + int32_t xOrigin, int32_t yOrigin, bool fVGAResize); + void i_handleDisplayUpdate(unsigned uScreenId, int x, int y, int w, int h); + void i_handleUpdateVMMDevSupportsGraphics(bool fSupportsGraphics); + void i_handleUpdateGuestVBVACapabilities(uint32_t fNewCapabilities); + void i_handleUpdateVBVAInputMapping(int32_t xOrigin, int32_t yOrigin, uint32_t cx, uint32_t cy); +#ifdef VBOX_WITH_VIDEOHWACCEL + int i_handleVHWACommandProcess(int enmCmd, bool fGuestCmd, VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCommand); +#endif + int i_handle3DNotifyProcess(VBOX3DNOTIFY *p3DNotify); + + int i_saveVisibleRegion(uint32_t cRect, PRTRECT pRect); + int i_handleSetVisibleRegion(uint32_t cRect, PRTRECT pRect); + int i_handleUpdateMonitorPositions(uint32_t cPositions, PCRTPOINT paPositions); + int i_handleQueryVisibleRegion(uint32_t *pcRects, PRTRECT paRects); + + void i_VRDPConnectionEvent(bool fConnect); + void i_VideoAccelVRDP(bool fEnable, int c); + + /* Legacy video acceleration requests coming from the VGA refresh timer. */ + int VideoAccelEnableVGA(bool fEnable, VBVAMEMORY *pVbvaMemory); + + /* Legacy video acceleration requests coming from VMMDev. */ + int VideoAccelEnableVMMDev(bool fEnable, VBVAMEMORY *pVbvaMemory); + void VideoAccelFlushVMMDev(void); + + void i_UpdateDeviceCursorCapabilities(void); + +#ifdef VBOX_WITH_RECORDING + int i_recordingInvalidate(void); + void i_recordingScreenChanged(unsigned uScreenId); +#endif + + void i_notifyPowerDown(void); + + // DisplayMouseInterface methods + virtual HRESULT i_getScreenResolution(ULONG cScreen, ULONG *pcx, + ULONG *pcy, ULONG *pcBPP, LONG *pXOrigin, LONG *pYOrigin) + { + return getScreenResolution(cScreen, pcx, pcy, pcBPP, pXOrigin, pYOrigin, NULL); + } + virtual void i_getFramebufferDimensions(int32_t *px1, int32_t *py1, + int32_t *px2, int32_t *py2); + virtual HRESULT i_reportHostCursorCapabilities(uint32_t fCapabilitiesAdded, uint32_t fCapabilitiesRemoved); + virtual HRESULT i_reportHostCursorPosition(int32_t x, int32_t y, bool fOutOfRange); + virtual bool i_isInputMappingSet(void) + { + return cxInputMapping != 0 && cyInputMapping != 0; + } + + static const PDMDRVREG DrvReg; + +private: + // Wrapped IDisplay properties + virtual HRESULT getGuestScreenLayout(std::vector<ComPtr<IGuestScreenInfo> > &aGuestScreenLayout); + + // Wrapped IDisplay methods + virtual HRESULT getScreenResolution(ULONG aScreenId, + ULONG *aWidth, + ULONG *aHeight, + ULONG *aBitsPerPixel, + LONG *aXOrigin, + LONG *aYOrigin, + GuestMonitorStatus_T *aGuestMonitorStatus); + virtual HRESULT attachFramebuffer(ULONG aScreenId, + const ComPtr<IFramebuffer> &aFramebuffer, + com::Guid &aId); + virtual HRESULT detachFramebuffer(ULONG aScreenId, + const com::Guid &aId); + virtual HRESULT queryFramebuffer(ULONG aScreenId, + ComPtr<IFramebuffer> &aFramebuffer); + virtual HRESULT setVideoModeHint(ULONG aDisplay, + BOOL aEnabled, + BOOL aChangeOrigin, + LONG aOriginX, + LONG aOriginY, + ULONG aWidth, + ULONG aHeight, + ULONG aBitsPerPixel, + BOOL aNotify); + virtual HRESULT getVideoModeHint(ULONG aDisplay, + BOOL *aEnabled, + BOOL *aChangeOrigin, + LONG *aOriginX, + LONG *aOriginY, + ULONG *aWidth, + ULONG *aHeight, + ULONG *aBitsPerPixel); + virtual HRESULT setSeamlessMode(BOOL aEnabled); + virtual HRESULT takeScreenShot(ULONG aScreenId, + BYTE *aAddress, + ULONG aWidth, + ULONG aHeight, + BitmapFormat_T aBitmapFormat); + virtual HRESULT takeScreenShotToArray(ULONG aScreenId, + ULONG aWidth, + ULONG aHeight, + BitmapFormat_T aBitmapFormat, + std::vector<BYTE> &aScreenData); + virtual HRESULT drawToScreen(ULONG aScreenId, + BYTE *aAddress, + ULONG aX, + ULONG aY, + ULONG aWidth, + ULONG aHeight); + virtual HRESULT invalidateAndUpdate(); + virtual HRESULT invalidateAndUpdateScreen(ULONG aScreenId); + virtual HRESULT completeVHWACommand(BYTE *aCommand); + virtual HRESULT viewportChanged(ULONG aScreenId, + ULONG aX, + ULONG aY, + ULONG aWidth, + ULONG aHeight); + virtual HRESULT querySourceBitmap(ULONG aScreenId, + ComPtr<IDisplaySourceBitmap> &aDisplaySourceBitmap); + virtual HRESULT notifyScaleFactorChange(ULONG aScreenId, + ULONG aScaleFactorWMultiplied, + ULONG aScaleFactorHMultiplied); + virtual HRESULT notifyHiDPIOutputPolicyChange(BOOL fUnscaledHiDPI); + virtual HRESULT setScreenLayout(ScreenLayoutMode_T aScreenLayoutMode, + const std::vector<ComPtr<IGuestScreenInfo> > &aGuestScreenInfo); + virtual HRESULT detachScreens(const std::vector<LONG> &aScreenIds); + virtual HRESULT createGuestScreenInfo(ULONG aDisplay, + GuestMonitorStatus_T aStatus, + BOOL aPrimary, + BOOL aChangeOrigin, + LONG aOriginX, + LONG aOriginY, + ULONG aWidth, + ULONG aHeight, + ULONG aBitsPerPixel, + ComPtr<IGuestScreenInfo> &aGuestScreenInfo); + + // Wrapped IEventListener properties + + // Wrapped IEventListener methods + virtual HRESULT handleEvent(const ComPtr<IEvent> &aEvent); + + // other internal methods + HRESULT takeScreenShotWorker(ULONG aScreenId, + BYTE *aAddress, + ULONG aWidth, + ULONG aHeight, + BitmapFormat_T aBitmapFormat, + ULONG *pcbOut); + int processVBVAResize(PCVBVAINFOVIEW pView, PCVBVAINFOSCREEN pScreen, void *pvVRAM, bool fResetInputMapping); + + static DECLCALLBACK(void*) i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); + static DECLCALLBACK(int) i_drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) i_drvDestruct(PPDMDRVINS pDrvIns); + static DECLCALLBACK(void) i_drvPowerOff(PPDMDRVINS pDrvIns); + static DECLCALLBACK(int) i_displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, + uint32_t cbLine, uint32_t cx, uint32_t cy); + static DECLCALLBACK(void) i_displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterface, + uint32_t x, uint32_t y, uint32_t cx, uint32_t cy); + static DECLCALLBACK(void) i_displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterface); + static DECLCALLBACK(void) i_displayResetCallback(PPDMIDISPLAYCONNECTOR pInterface); + static DECLCALLBACK(void) i_displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled); + static DECLCALLBACK(void) i_displayProcessAdapterDataCallback(PPDMIDISPLAYCONNECTOR pInterface, + void *pvVRAM, uint32_t u32VRAMSize); + static DECLCALLBACK(void) i_displayProcessDisplayDataCallback(PPDMIDISPLAYCONNECTOR pInterface, + void *pvVRAM, unsigned uScreenId); + +#ifdef VBOX_WITH_VIDEOHWACCEL + static DECLCALLBACK(int) i_displayVHWACommandProcess(PPDMIDISPLAYCONNECTOR pInterface, int enmCmd, bool fGuestCmd, + VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCommand); +#endif + static DECLCALLBACK(int) i_display3DNotifyProcess(PPDMIDISPLAYCONNECTOR pInterface, + VBOX3DNOTIFY *p3DNotify); + +#ifdef VBOX_WITH_HGSMI + static DECLCALLBACK(int) i_displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, + VBVAHOSTFLAGS RT_UNTRUSTED_VOLATILE_GUEST *pHostFlags); + static DECLCALLBACK(void) i_displayVBVADisable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId); + static DECLCALLBACK(void) i_displayVBVAUpdateBegin(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId); + static DECLCALLBACK(void) i_displayVBVAUpdateProcess(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, + struct VBVACMDHDR const RT_UNTRUSTED_VOLATILE_GUEST *pCmd, size_t cbCmd); + static DECLCALLBACK(void) i_displayVBVAUpdateEnd(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, int32_t x, int32_t y, + uint32_t cx, uint32_t cy); + static DECLCALLBACK(int) i_displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, PCVBVAINFOVIEW pView, + PCVBVAINFOSCREEN pScreen, void *pvVRAM, + bool fResetInputMapping); + static DECLCALLBACK(int) i_displayVBVAMousePointerShape(PPDMIDISPLAYCONNECTOR pInterface, bool fVisible, bool fAlpha, + uint32_t xHot, uint32_t yHot, uint32_t cx, uint32_t cy, + const void *pvShape); + static DECLCALLBACK(void) i_displayVBVAGuestCapabilityUpdate(PPDMIDISPLAYCONNECTOR pInterface, uint32_t fCapabilities); + + static DECLCALLBACK(void) i_displayVBVAInputMappingUpdate(PPDMIDISPLAYCONNECTOR pInterface, int32_t xOrigin, int32_t yOrigin, + uint32_t cx, uint32_t cy); + static DECLCALLBACK(void) i_displayVBVAReportCursorPosition(PPDMIDISPLAYCONNECTOR pInterface, uint32_t fFlags, uint32_t uScreen, uint32_t x, uint32_t y); +#endif + + static DECLCALLBACK(int) i_displaySSMSaveScreenshot(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser); + static DECLCALLBACK(int) i_displaySSMLoadScreenshot(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser, + uint32_t uVersion, uint32_t uPass); + static DECLCALLBACK(int) i_displaySSMSave(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser); + static DECLCALLBACK(int) i_displaySSMLoad(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser, + uint32_t uVersion, uint32_t uPass); + + Console * const mParent; + /** Pointer to the associated display driver. */ + struct DRVMAINDISPLAY *mpDrv; + + unsigned mcMonitors; + /** Input mapping rectangle top left X relative to the first screen. */ + int32_t xInputMappingOrigin; + /** Input mapping rectangle top left Y relative to the first screen. */ + int32_t yInputMappingOrigin; + uint32_t cxInputMapping; /**< Input mapping rectangle width. */ + uint32_t cyInputMapping; /**< Input mapping rectangle height. */ + DISPLAYFBINFO maFramebuffers[SchemaDefs::MaxGuestMonitors]; + /** Does the VMM device have the "supports graphics" capability set? + * Does not go into the saved state as it is refreshed on restore. */ + bool mfVMMDevSupportsGraphics; + /** Mirror of the current guest VBVA capabilities. */ + uint32_t mfGuestVBVACapabilities; + /** Mirror of the current host cursor capabilities. */ + uint32_t mfHostCursorCapabilities; + + bool mfSourceBitmapEnabled; + bool volatile fVGAResizing; + + /** Are we in seamless mode? Not saved, as we exit seamless on saving. */ + bool mfSeamlessEnabled; + /** Last set seamless visible region, number of rectangles. */ + uint32_t mcRectVisibleRegion; + /** Last set seamless visible region, data. Freed on final clean-up. */ + PRTRECT mpRectVisibleRegion; + + bool mfVideoAccelVRDP; + uint32_t mfu32SupportedOrders; + /** Number of currently connected VRDP clients. */ + int32_t volatile mcVRDPRefs; + + /* The legacy VBVA data and methods. */ + VIDEOACCEL mVideoAccelLegacy; + + int i_VideoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory, PPDMIDISPLAYPORT pUpPort); + void i_VideoAccelFlush(PPDMIDISPLAYPORT pUpPort); + bool i_VideoAccelAllowed(void); + + int i_videoAccelRefreshProcess(PPDMIDISPLAYPORT pUpPort); + int i_videoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory, PPDMIDISPLAYPORT pUpPort); + int i_videoAccelFlush(PPDMIDISPLAYPORT pUpPort); + + /* Legacy pre-HGSMI handlers. */ + void processAdapterData(void *pvVRAM, uint32_t u32VRAMSize); + void processDisplayData(void *pvVRAM, unsigned uScreenId); + + /** Serializes access to mVideoAccelLegacy and mfVideoAccelVRDP, etc between VRDP and Display. */ + RTCRITSECT mVideoAccelLock; + +#ifdef VBOX_WITH_RECORDING + /* Serializes access to video recording source bitmaps. */ + RTCRITSECT mVideoRecLock; + /** Array which defines which screens are being enabled for recording. */ + bool maRecordingEnabled[SchemaDefs::MaxGuestMonitors]; +#endif + +public: + + static DECLCALLBACK(int) i_displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_t **ppbData, size_t *pcbData, + uint32_t *pcx, uint32_t *pcy, bool *pfMemFree); + +private: + static DECLCALLBACK(int) i_InvalidateAndUpdateEMT(Display *pDisplay, unsigned uId, bool fUpdateAll); + static DECLCALLBACK(int) i_drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address, ULONG x, ULONG y, + ULONG width, ULONG height); + + void i_updateGuestGraphicsFacility(void); + +#ifdef VBOX_WITH_HGSMI + volatile uint32_t mu32UpdateVBVAFlags; +#endif + +private: + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(Display); /* Shuts up MSC warning C4625. */ +}; + +/* The legacy VBVA helpers. */ +int videoAccelConstruct(VIDEOACCEL *pVideoAccel); +void videoAccelDestroy(VIDEOACCEL *pVideoAccel); +void i_vbvaSetMemoryFlags(VBVAMEMORY *pVbvaMemory, + bool fVideoAccelEnabled, + bool fVideoAccelVRDP, + uint32_t fu32SupportedOrders, + DISPLAYFBINFO *paFBInfos, + unsigned cFBInfos); +int videoAccelEnterVGA(VIDEOACCEL *pVideoAccel); +void videoAccelLeaveVGA(VIDEOACCEL *pVideoAccel); +int videoAccelEnterVMMDev(VIDEOACCEL *pVideoAccel); +void videoAccelLeaveVMMDev(VIDEOACCEL *pVideoAccel); + + +/* helper function, code in DisplayResampleImage.cpp */ +void BitmapScale32(uint8_t *dst, int dstW, int dstH, + const uint8_t *src, int iDeltaLine, int srcW, int srcH); + +/* helper function, code in DisplayPNGUtul.cpp */ +int DisplayMakePNG(uint8_t *pbData, uint32_t cx, uint32_t cy, + uint8_t **ppu8PNG, uint32_t *pcbPNG, uint32_t *pcxPNG, uint32_t *pcyPNG, + uint8_t fLimitSize); + +class ATL_NO_VTABLE DisplaySourceBitmap: + public DisplaySourceBitmapWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(DisplaySourceBitmap) + + HRESULT FinalConstruct(); + void FinalRelease(); + + /* Public initializer/uninitializer for internal purposes only. */ + HRESULT init(ComObjPtr<Display> pDisplay, unsigned uScreenId, DISPLAYFBINFO *pFBInfo); + void uninit(); + + bool i_usesVRAM(void) { return m.pu8Allocated == NULL; } + +private: + // wrapped IDisplaySourceBitmap properties + virtual HRESULT getScreenId(ULONG *aScreenId); + + // wrapped IDisplaySourceBitmap methods + virtual HRESULT queryBitmapInfo(BYTE **aAddress, + ULONG *aWidth, + ULONG *aHeight, + ULONG *aBitsPerPixel, + ULONG *aBytesPerLine, + BitmapFormat_T *aBitmapFormat); + + int initSourceBitmap(unsigned aScreenId, DISPLAYFBINFO *pFBInfo); + + struct Data + { + ComObjPtr<Display> pDisplay; + unsigned uScreenId; + DISPLAYFBINFO *pFBInfo; + + uint8_t *pu8Allocated; + + uint8_t *pu8Address; + ULONG ulWidth; + ULONG ulHeight; + ULONG ulBitsPerPixel; + ULONG ulBytesPerLine; + BitmapFormat_T bitmapFormat; + }; + + Data m; +}; + +class ATL_NO_VTABLE GuestScreenInfo: + public GuestScreenInfoWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(GuestScreenInfo) + + HRESULT FinalConstruct(); + void FinalRelease(); + + /* Public initializer/uninitializer for internal purposes only. */ + HRESULT init(ULONG aDisplay, + GuestMonitorStatus_T aGuestMonitorStatus, + BOOL aPrimary, + BOOL aChangeOrigin, + LONG aOriginX, + LONG aOriginY, + ULONG aWidth, + ULONG aHeight, + ULONG aBitsPerPixel); + void uninit(); + +private: + // wrapped IGuestScreenInfo properties + virtual HRESULT getScreenId(ULONG *aScreenId); + virtual HRESULT getGuestMonitorStatus(GuestMonitorStatus_T *aGuestMonitorStatus); + virtual HRESULT getPrimary(BOOL *aPrimary); + virtual HRESULT getOrigin(BOOL *aOrigin); + virtual HRESULT getOriginX(LONG *aOriginX); + virtual HRESULT getOriginY(LONG *aOriginY); + virtual HRESULT getWidth(ULONG *aWidth); + virtual HRESULT getHeight(ULONG *aHeight); + virtual HRESULT getBitsPerPixel(ULONG *aBitsPerPixel); + virtual HRESULT getExtendedInfo(com::Utf8Str &aExtendedInfo); + + ULONG mScreenId; + GuestMonitorStatus_T mGuestMonitorStatus; + BOOL mPrimary; + BOOL mOrigin; + LONG mOriginX; + LONG mOriginY; + ULONG mWidth; + ULONG mHeight; + ULONG mBitsPerPixel; +}; + +#endif /* !MAIN_INCLUDED_DisplayImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/DisplayUtils.h b/src/VBox/Main/include/DisplayUtils.h new file mode 100644 index 00000000..a86b44b7 --- /dev/null +++ b/src/VBox/Main/include/DisplayUtils.h @@ -0,0 +1,57 @@ +/* $Id: DisplayUtils.h $ */ +/** @file + * Display helper declarations + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_DisplayUtils_h +#define MAIN_INCLUDED_DisplayUtils_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VBox/com/string.h" + +#include "CryptoUtils.h" + +using namespace com; + +#define sSSMDisplayScreenshotVer 0x00010001 +#define sSSMDisplayVer 0x00010001 +#define sSSMDisplayVer2 0x00010002 +#define sSSMDisplayVer3 0x00010003 +#define sSSMDisplayVer4 0x00010004 +#define sSSMDisplayVer5 0x00010005 + +int readSavedGuestScreenInfo(SsmStream &ssmStream, const Utf8Str &strStateFilePath, + uint32_t u32ScreenId, uint32_t *pu32OriginX, uint32_t *pu32OriginY, + uint32_t *pu32Width, uint32_t *pu32Height, uint16_t *pu16Flags); + +int readSavedDisplayScreenshot(SsmStream &ssmStream, const Utf8Str &strStateFilePath, + uint32_t u32Type, uint8_t **ppu8Data, uint32_t *pcbData, + uint32_t *pu32Width, uint32_t *pu32Height); +void freeSavedDisplayScreenshot(uint8_t *pu8Data); + +#endif /* !MAIN_INCLUDED_DisplayUtils_h */ + diff --git a/src/VBox/Main/include/DrvAudioRec.h b/src/VBox/Main/include/DrvAudioRec.h new file mode 100644 index 00000000..babb7036 --- /dev/null +++ b/src/VBox/Main/include/DrvAudioRec.h @@ -0,0 +1,79 @@ +/* $Id: DrvAudioRec.h $ */ +/** @file + * VirtualBox driver interface video recording audio backend. + */ + +/* + * Copyright (C) 2017-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_DrvAudioRec_h +#define MAIN_INCLUDED_DrvAudioRec_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/ptr.h> +#include <VBox/settings.h> +#include <VBox/vmm/pdmdrv.h> +#include <VBox/vmm/pdmifs.h> + +#include "AudioDriver.h" +#include "Recording.h" + +using namespace com; + +class Console; + +class AudioVideoRec : public AudioDriver +{ + +public: + + AudioVideoRec(Console *pConsole); + virtual ~AudioVideoRec(void); + +public: + + static const PDMDRVREG DrvReg; + +public: + + int applyConfiguration(const settings::RecordingSettings &Settings); + +public: + + static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns); + static DECLCALLBACK(void) drvPowerOff(PPDMDRVINS pDrvIns); + +private: + + virtual int configureDriver(PCFGMNODE pLunCfg, PCVMMR3VTABLE pVMM) RT_OVERRIDE; + + /** Pointer to the associated video recording audio driver. */ + struct DRVAUDIORECORDING *mpDrv; + /** Recording settings used for configuring the driver. */ + struct settings::RecordingSettings mSettings; +}; + +#endif /* !MAIN_INCLUDED_DrvAudioRec_h */ + diff --git a/src/VBox/Main/include/DrvAudioVRDE.h b/src/VBox/Main/include/DrvAudioVRDE.h new file mode 100644 index 00000000..d807395e --- /dev/null +++ b/src/VBox/Main/include/DrvAudioVRDE.h @@ -0,0 +1,87 @@ +/* $Id: DrvAudioVRDE.h $ */ +/** @file + * VirtualBox driver interface to VRDE backend. + */ + +/* + * Copyright (C) 2014-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_DrvAudioVRDE_h +#define MAIN_INCLUDED_DrvAudioVRDE_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/ptr.h> +#include <VBox/com/string.h> + +#include <VBox/RemoteDesktop/VRDE.h> + +#include <VBox/vmm/pdmdrv.h> +#include <VBox/vmm/pdmifs.h> + +#include "AudioDriver.h" + +using namespace com; + +class Console; + +class AudioVRDE : public AudioDriver +{ + +public: + + AudioVRDE(Console *pConsole); + virtual ~AudioVRDE(void); + +public: + + static const PDMDRVREG DrvReg; + +public: + + void onVRDEClientConnect(uint32_t uClientID); + void onVRDEClientDisconnect(uint32_t uClientID); + int onVRDEControl(bool fEnable, uint32_t uFlags); + int onVRDEInputBegin(void *pvContext, PVRDEAUDIOINBEGIN pVRDEAudioBegin); + int onVRDEInputData(void *pvContext, const void *pvData, uint32_t cbData); + int onVRDEInputEnd(void *pvContext); + int onVRDEInputIntercept(bool fIntercept); + +public: + + static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns); + static DECLCALLBACK(void) drvPowerOff(PPDMDRVINS pDrvIns); + +private: + + virtual int configureDriver(PCFGMNODE pLunCfg, PCVMMR3VTABLE pVMM) RT_OVERRIDE; + + /** Pointer to the associated VRDE audio driver. */ + struct DRVAUDIOVRDE *mpDrv; + /** Protects accesses to mpDrv from racing driver destruction. */ + RTCRITSECT mCritSect; +}; + +#endif /* !MAIN_INCLUDED_DrvAudioVRDE_h */ + diff --git a/src/VBox/Main/include/EBMLWriter.h b/src/VBox/Main/include/EBMLWriter.h new file mode 100644 index 00000000..8234b04b --- /dev/null +++ b/src/VBox/Main/include/EBMLWriter.h @@ -0,0 +1,135 @@ +/* $Id: EBMLWriter.h $ */ +/** @file + * EBMLWriter.h - EBML writer. + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_EBMLWriter_h +#define MAIN_INCLUDED_EBMLWriter_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <stack> + +#include <iprt/critsect.h> +#include <iprt/file.h> + +#include <VBox/com/string.h> + + +/** No flags set. */ +#define VBOX_EBMLWRITER_FLAG_NONE 0 +/** The file handle was inherited. */ +#define VBOX_EBMLWRITER_FLAG_HANDLE_INHERITED RT_BIT(0) + +class EBMLWriter +{ +public: + typedef uint32_t EbmlClassId; + +private: + + struct EbmlSubElement + { + uint64_t offset; + EbmlClassId classId; + EbmlSubElement(uint64_t offs, EbmlClassId cid) : offset(offs), classId(cid) {} + }; + + /** Stack of EBML sub elements. */ + std::stack<EbmlSubElement> m_Elements; + /** The file's handle. */ + RTFILE m_hFile; + /** The file's name (path). */ + com::Utf8Str m_strFile; + /** Flags. */ + uint32_t m_fFlags; + +public: + + EBMLWriter(void) + : m_hFile(NIL_RTFILE) + , m_fFlags(VBOX_EBMLWRITER_FLAG_NONE) { } + + virtual ~EBMLWriter(void) { close(); } + +public: + + int createEx(const char *a_pszFile, PRTFILE phFile); + + int create(const char *a_pszFile, uint64_t fOpen); + + void close(void); + + /** Returns the file name. */ + const com::Utf8Str& getFileName(void) { return m_strFile; } + + /** Returns file size. */ + uint64_t getFileSize(void) { return RTFileTell(m_hFile); } + + /** Get reference to file descriptor */ + inline const RTFILE &getFile(void) { return m_hFile; } + + /** Returns available space on storage. */ + uint64_t getAvailableSpace(void); + + /** + * Returns whether the file is open or not. + * + * @returns True if open, false if not. + */ + bool isOpen(void) { return RTFileIsValid(m_hFile); } + +public: + + EBMLWriter &subStart(EbmlClassId classId); + + EBMLWriter &subEnd(EbmlClassId classId); + + EBMLWriter &serializeString(EbmlClassId classId, const char *str); + + EBMLWriter &serializeUnsignedInteger(EbmlClassId classId, uint64_t parm, size_t size = 0); + + EBMLWriter &serializeFloat(EbmlClassId classId, float value); + + EBMLWriter &serializeData(EbmlClassId classId, const void *pvData, size_t cbData); + + int write(const void *data, size_t size); + + void writeUnsignedInteger(uint64_t value, size_t size = sizeof(uint64_t)); + + void writeClassId(EbmlClassId parm); + + void writeSize(uint64_t parm); + + static inline size_t getSizeOfUInt(uint64_t arg); + +private: + + void operator=(const EBMLWriter &); +}; + +#endif /* !MAIN_INCLUDED_EBMLWriter_h */ + diff --git a/src/VBox/Main/include/EBML_MKV.h b/src/VBox/Main/include/EBML_MKV.h new file mode 100644 index 00000000..6e437b6b --- /dev/null +++ b/src/VBox/Main/include/EBML_MKV.h @@ -0,0 +1,106 @@ +/* $Id: EBML_MKV.h $ */ +/** @file + * EbmlMkvIDs.h - Matroska EBML Class IDs. + */ + +/* + * Copyright (C) 2017-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_EBML_MKV_h +#define MAIN_INCLUDED_EBML_MKV_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + + +/** Matroska EBML Class IDs supported by WebM. + * + * Keep the structure clean and group elements where it makes sense + * for easier reading / lookup. */ +enum MkvElem +{ + MkvElem_EBML = 0x1A45DFA3, + MkvElem_EBMLVersion = 0x4286, + MkvElem_EBMLReadVersion = 0x42F7, + MkvElem_EBMLMaxIDLength = 0x42F2, + MkvElem_EBMLMaxSizeLength = 0x42F3, + + MkvElem_DocType = 0x4282, + MkvElem_DocTypeVersion = 0x4287, + MkvElem_DocTypeReadVersion = 0x4285, + + MkvElem_Segment = 0x18538067, + MkvElem_Segment_Duration = 0x4489, + + MkvElem_SeekHead = 0x114D9B74, + MkvElem_Seek = 0x4DBB, + MkvElem_SeekID = 0x53AB, + MkvElem_SeekPosition = 0x53AC, + + MkvElem_Info = 0x1549A966, + MkvElem_TimecodeScale = 0x2AD7B1, + MkvElem_MuxingApp = 0x4D80, + MkvElem_WritingApp = 0x5741, + + MkvElem_Tracks = 0x1654AE6B, + MkvElem_TrackEntry = 0xAE, + MkvElem_TrackNumber = 0xD7, + MkvElem_TrackUID = 0x73C5, + MkvElem_TrackType = 0x83, + + MkvElem_Language = 0x22B59C, + + MkvElem_FlagLacing = 0x9C, + + MkvElem_Cluster = 0x1F43B675, + MkvElem_Timecode = 0xE7, + + MkvElem_SimpleBlock = 0xA3, + + MkvElem_SeekPreRoll = 0x56BB, + + MkvElem_CodecID = 0x86, + MkvElem_CodecDelay = 0x56AA, + MkvElem_CodecPrivate = 0x63A2, + MkvElem_CodecName = 0x258688, + + MkvElem_Video = 0xE0, + MkvElem_PixelWidth = 0xB0, + MkvElem_PixelHeight = 0xBA, + MkvElem_FrameRate = 0x2383E3, + + MkvElem_Audio = 0xE1, + MkvElem_SamplingFrequency = 0xB5, + MkvElem_OutputSamplingFrequency = 0x78B5, + MkvElem_Channels = 0x9F, + MkvElem_BitDepth = 0x6264, + + MkvElem_Cues = 0x1C53BB6B, + MkvElem_CuePoint = 0xBB, + MkvElem_CueTime = 0xB3, + MkvElem_CueTrackPositions = 0xB7, + MkvElem_CueTrack = 0xF7, + MkvElem_CueClusterPosition = 0xF1 +}; + +#endif /* !MAIN_INCLUDED_EBML_MKV_h */ + diff --git a/src/VBox/Main/include/EmulatedUSBImpl.h b/src/VBox/Main/include/EmulatedUSBImpl.h new file mode 100644 index 00000000..aaf23e40 --- /dev/null +++ b/src/VBox/Main/include/EmulatedUSBImpl.h @@ -0,0 +1,103 @@ +/* $Id: EmulatedUSBImpl.h $ */ +/** @file + * Emulated USB devices manager. + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_EmulatedUSBImpl_h +#define MAIN_INCLUDED_EmulatedUSBImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "EmulatedUSBWrap.h" + +#include <VBox/vrdpusb.h> + +class Console; +class EUSBWEBCAM; + +typedef std::map<Utf8Str, EUSBWEBCAM *> WebcamsMap; + +class ATL_NO_VTABLE EmulatedUSB : + public EmulatedUSBWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(EmulatedUSB) + + HRESULT FinalConstruct(); + void FinalRelease(); + + /* Public initializer/uninitializer for internal purposes only. */ + HRESULT init(ComObjPtr<Console> pConsole); + void uninit(); + + /* Public method for internal use. */ + static DECLCALLBACK(int) i_eusbCallback(void *pv, const char *pszId, uint32_t iEvent, + const void *pvData, uint32_t cbData); + + PEMULATEDUSBIF i_getEmulatedUsbIf(); + + HRESULT i_webcamAttachInternal(const com::Utf8Str &aPath, + const com::Utf8Str &aSettings, + const char *pszDriver, + void *pvObject); + HRESULT i_webcamDetachInternal(const com::Utf8Str &aPath); + +private: + + static DECLCALLBACK(int) eusbCallbackEMT(EmulatedUSB *pThis, char *pszId, uint32_t iEvent, + void *pvData, uint32_t cbData); + + static DECLCALLBACK(int) i_QueryEmulatedUsbDataById(void *pvUser, const char *pszId, void **ppvEmUsbCb, void **ppvEmUsbCbData, void **ppvObject); + + HRESULT webcamPathFromId(com::Utf8Str *pPath, const char *pszId); + + // wrapped IEmulatedUSB properties + virtual HRESULT getWebcams(std::vector<com::Utf8Str> &aWebcams); + + // wrapped IEmulatedUSB methods + virtual HRESULT webcamAttach(const com::Utf8Str &aPath, + const com::Utf8Str &aSettings); + virtual HRESULT webcamDetach(const com::Utf8Str &aPath); + + /* Data. */ + struct Data + { + Data() + { + } + + ComObjPtr<Console> pConsole; + WebcamsMap webcams; + }; + + Data m; + EMULATEDUSBIF mEmUsbIf; +}; + +#endif /* !MAIN_INCLUDED_EmulatedUSBImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/EventImpl.h b/src/VBox/Main/include/EventImpl.h new file mode 100644 index 00000000..0a3116a2 --- /dev/null +++ b/src/VBox/Main/include/EventImpl.h @@ -0,0 +1,188 @@ +/* $Id: EventImpl.h $ */ +/** @file + * VirtualBox COM IEvent implementation + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_EventImpl_h +#define MAIN_INCLUDED_EventImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "EventWrap.h" +#include "EventSourceWrap.h" +#include "VetoEventWrap.h" + + +class ATL_NO_VTABLE VBoxEvent + : public EventWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(VBoxEvent) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(IEventSource *aSource, VBoxEventType_T aType, BOOL aWaitable); + void uninit(); + +private: + // wrapped IEvent properties + HRESULT getType(VBoxEventType_T *aType); + HRESULT getSource(ComPtr<IEventSource> &aSource); + HRESULT getWaitable(BOOL *aWaitable); + + // wrapped IEvent methods + HRESULT setProcessed(); + HRESULT waitProcessed(LONG aTimeout, BOOL *aResult); + + struct Data; + Data* m; +}; + + +class ATL_NO_VTABLE VBoxVetoEvent + : public VetoEventWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(VBoxVetoEvent) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(IEventSource *aSource, VBoxEventType_T aType); + void uninit(); + +private: + // wrapped IEvent properties + HRESULT getType(VBoxEventType_T *aType); + HRESULT getSource(ComPtr<IEventSource> &aSource); + HRESULT getWaitable(BOOL *aWaitable); + + // wrapped IEvent methods + HRESULT setProcessed(); + HRESULT waitProcessed(LONG aTimeout, BOOL *aResult); + + // wrapped IVetoEvent methods + HRESULT addVeto(const com::Utf8Str &aReason); + HRESULT isVetoed(BOOL *aResult); + HRESULT getVetos(std::vector<com::Utf8Str> &aResult); + HRESULT addApproval(const com::Utf8Str &aReason); + HRESULT isApproved(BOOL *aResult); + HRESULT getApprovals(std::vector<com::Utf8Str> &aResult); + + struct Data; + Data* m; +}; + +class ATL_NO_VTABLE EventSource : + public EventSourceWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(EventSource) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(); + void uninit(); + +private: + // wrapped IEventSource methods + HRESULT createListener(ComPtr<IEventListener> &aListener); + HRESULT createAggregator(const std::vector<ComPtr<IEventSource> > &aSubordinates, + ComPtr<IEventSource> &aResult); + HRESULT registerListener(const ComPtr<IEventListener> &aListener, + const std::vector<VBoxEventType_T> &aInteresting, + BOOL aActive); + HRESULT unregisterListener(const ComPtr<IEventListener> &aListener); + HRESULT fireEvent(const ComPtr<IEvent> &aEvent, + LONG aTimeout, + BOOL *aResult); + HRESULT getEvent(const ComPtr<IEventListener> &aListener, + LONG aTimeout, + ComPtr<IEvent> &aEvent); + HRESULT eventProcessed(const ComPtr<IEventListener> &aListener, + const ComPtr<IEvent> &aEvent); + + + struct Data; + Data *m; + + friend class ListenerRecord; +}; + +class VBoxEventDesc +{ +public: + VBoxEventDesc() : mEvent(0), mEventSource(0) + {} + + VBoxEventDesc(IEvent *aEvent, IEventSource *aSource) + : mEvent(aEvent), mEventSource(aSource) + {} + + ~VBoxEventDesc() + {} + + void init(IEvent *aEvent, IEventSource *aSource) + { + mEvent = aEvent; + mEventSource = aSource; + } + + void uninit() + { + mEvent.setNull(); + mEventSource.setNull(); + } + + void getEvent(IEvent **aEvent) + { + mEvent.queryInterfaceTo(aEvent); + } + + BOOL fire(LONG aTimeout) + { + if (mEventSource && mEvent) + { + BOOL fDelivered = FALSE; + HRESULT hrc = mEventSource->FireEvent(mEvent, aTimeout, &fDelivered); + AssertComRCReturn(hrc, FALSE); + return fDelivered; + } + return FALSE; + } + +private: + ComPtr<IEvent> mEvent; + ComPtr<IEventSource> mEventSource; +}; + + +#endif /* !MAIN_INCLUDED_EventImpl_h */ diff --git a/src/VBox/Main/include/ExtPackManagerImpl.h b/src/VBox/Main/include/ExtPackManagerImpl.h new file mode 100644 index 00000000..dc4ce201 --- /dev/null +++ b/src/VBox/Main/include/ExtPackManagerImpl.h @@ -0,0 +1,322 @@ +/* $Id: ExtPackManagerImpl.h $ */ +/** @file + * VirtualBox Main - interface for Extension Packs, VBoxSVC & VBoxC. + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ExtPackManagerImpl_h +#define MAIN_INCLUDED_ExtPackManagerImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxBase.h" +#include <VBox/ExtPack/ExtPack.h> +#include "ExtPackWrap.h" +#include "ExtPackFileWrap.h" +#include "ExtPackManagerWrap.h" +#include <iprt/fs.h> + + +/** The name of the oracle extension back. */ +#define ORACLE_PUEL_EXTPACK_NAME "Oracle VM VirtualBox Extension Pack" + + +#ifndef VBOX_COM_INPROC +/** + * An extension pack file. + */ +class ATL_NO_VTABLE ExtPackFile : + public ExtPackFileWrap +{ +public: + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(ExtPackFile) + + HRESULT FinalConstruct(); + void FinalRelease(); + HRESULT initWithFile(const char *a_pszFile, const char *a_pszDigest, class ExtPackManager *a_pExtPackMgr, VirtualBox *a_pVirtualBox); + void uninit(); + /** @} */ + +private: + /** @name Misc init helpers + * @{ */ + HRESULT initFailed(const char *a_pszWhyFmt, ...); + /** @} */ + +private: + + // wrapped IExtPackFile properties + HRESULT getName(com::Utf8Str &aName); + HRESULT getDescription(com::Utf8Str &aDescription); + HRESULT getVersion(com::Utf8Str &aVersion); + HRESULT getRevision(ULONG *aRevision); + HRESULT getEdition(com::Utf8Str &aEdition); + HRESULT getVRDEModule(com::Utf8Str &aVRDEModule); + HRESULT getCryptoModule(com::Utf8Str &aCryptoModule); + HRESULT getPlugIns(std::vector<ComPtr<IExtPackPlugIn> > &aPlugIns); + HRESULT getUsable(BOOL *aUsable); + HRESULT getWhyUnusable(com::Utf8Str &aWhyUnusable); + HRESULT getShowLicense(BOOL *aShowLicense); + HRESULT getLicense(com::Utf8Str &aLicense); + HRESULT getFilePath(com::Utf8Str &aFilePath); + + // wrapped IExtPackFile methods + HRESULT queryLicense(const com::Utf8Str &aPreferredLocale, + const com::Utf8Str &aPreferredLanguage, + const com::Utf8Str &aFormat, + com::Utf8Str &aLicenseText); + HRESULT install(BOOL aReplace, + const com::Utf8Str &aDisplayInfo, + ComPtr<IProgress> &aProgess); + + struct Data; + /** Pointer to the private instance. */ + Data *m; + + friend class ExtPackManager; + friend class ExtPackInstallTask; +}; +#endif /* !VBOX_COM_INPROC */ + + +/** + * An installed extension pack. + */ +class ATL_NO_VTABLE ExtPack : + public ExtPackWrap +{ +public: + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(ExtPack) + + HRESULT FinalConstruct(); + void FinalRelease(); + HRESULT initWithDir(VirtualBox *a_pVirtualBox, VBOXEXTPACKCTX a_enmContext, const char *a_pszName, const char *a_pszDir); + void uninit(); + RTMEMEF_NEW_AND_DELETE_OPERATORS(); + /** @} */ + + /** @name Internal interfaces used by ExtPackManager. + * @{ */ +#ifndef VBOX_COM_INPROC + bool i_callInstalledHook(IVirtualBox *a_pVirtualBox, AutoWriteLock *a_pLock, PRTERRINFO pErrInfo); + HRESULT i_callUninstallHookAndClose(IVirtualBox *a_pVirtualBox, bool a_fForcedRemoval); + bool i_callVirtualBoxReadyHook(IVirtualBox *a_pVirtualBox, AutoWriteLock *a_pLock); +#endif +#ifdef VBOX_COM_INPROC + bool i_callConsoleReadyHook(IConsole *a_pConsole, AutoWriteLock *a_pLock); +#endif +#ifndef VBOX_COM_INPROC + bool i_callVmCreatedHook(IVirtualBox *a_pVirtualBox, IMachine *a_pMachine, AutoWriteLock *a_pLock); +#endif +#ifdef VBOX_COM_INPROC + bool i_callVmConfigureVmmHook(IConsole *a_pConsole, PVM a_pVM, PCVMMR3VTABLE a_pVMM, + AutoWriteLock *a_pLock, int *a_pvrc); + bool i_callVmPowerOnHook(IConsole *a_pConsole, PVM a_pVM, PCVMMR3VTABLE a_pVMM, AutoWriteLock *a_pLock, int *a_pvrc); + bool i_callVmPowerOffHook(IConsole *a_pConsole, PVM a_pVM, PCVMMR3VTABLE a_pVMM, AutoWriteLock *a_pLock); +#endif + HRESULT i_checkVrde(void); + HRESULT i_checkCrypto(void); + HRESULT i_getVrdpLibraryName(Utf8Str *a_pstrVrdeLibrary); + HRESULT i_getCryptoLibraryName(Utf8Str *a_pstrCryptoLibrary); + HRESULT i_getLibraryName(const char *a_pszModuleName, Utf8Str *a_pstrLibrary); + bool i_wantsToBeDefaultVrde(void) const; + bool i_wantsToBeDefaultCrypto(void) const; + HRESULT i_refresh(bool *pfCanDelete); +#ifndef VBOX_COM_INPROC + bool i_areThereCloudProviderUninstallVetos(); + void i_notifyCloudProviderManager(); +#endif + /** @} */ + +protected: + /** @name Internal helper methods. + * @{ */ + void i_probeAndLoad(void); + bool i_findModule(const char *a_pszName, const char *a_pszExt, VBOXEXTPACKMODKIND a_enmKind, + Utf8Str *a_ppStrFound, bool *a_pfNative, PRTFSOBJINFO a_pObjInfo) const; + static bool i_objinfoIsEqual(PCRTFSOBJINFO pObjInfo1, PCRTFSOBJINFO pObjInfo2); + /** @} */ + + /** @name Extension Pack Helpers + * @{ */ + static DECLCALLBACK(int) i_hlpFindModule(PCVBOXEXTPACKHLP pHlp, const char *pszName, const char *pszExt, + VBOXEXTPACKMODKIND enmKind, char *pszFound, size_t cbFound, bool *pfNative); + static DECLCALLBACK(int) i_hlpGetFilePath(PCVBOXEXTPACKHLP pHlp, const char *pszFilename, char *pszPath, size_t cbPath); + static DECLCALLBACK(VBOXEXTPACKCTX) i_hlpGetContext(PCVBOXEXTPACKHLP pHlp); + static DECLCALLBACK(int) i_hlpLoadHGCMService(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IConsole) *pConsole, const char *pszServiceLibrary, const char *pszServiceName); + static DECLCALLBACK(int) i_hlpLoadVDPlugin(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox, const char *pszPluginLibrary); + static DECLCALLBACK(int) i_hlpUnloadVDPlugin(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox, const char *pszPluginLibrary); + static DECLCALLBACK(uint32_t) i_hlpCreateProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IUnknown) *pInitiator, + const char *pcszDescription, uint32_t cOperations, + uint32_t uTotalOperationsWeight, const char *pcszFirstOperationDescription, + uint32_t uFirstOperationWeight, VBOXEXTPACK_IF_CS(IProgress) **ppProgressOut); + static DECLCALLBACK(uint32_t) i_hlpGetCanceledProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress, + bool *pfCanceled); + static DECLCALLBACK(uint32_t) i_hlpUpdateProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress, + uint32_t uPercent); + static DECLCALLBACK(uint32_t) i_hlpNextOperationProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress, + const char *pcszNextOperationDescription, + uint32_t uNextOperationWeight); + static DECLCALLBACK(uint32_t) i_hlpWaitOtherProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress, + VBOXEXTPACK_IF_CS(IProgress) *pProgressOther, + uint32_t cTimeoutMS); + static DECLCALLBACK(uint32_t) i_hlpCompleteProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress, + uint32_t uResultCode); + static DECLCALLBACK(uint32_t) i_hlpCreateEvent(PCVBOXEXTPACKHLP pHlp, + VBOXEXTPACK_IF_CS(IEventSource) *aSource, + /* VBoxEventType_T */ uint32_t aType, bool aWaitable, + VBOXEXTPACK_IF_CS(IEvent) **ppEventOut); + static DECLCALLBACK(uint32_t) i_hlpCreateVetoEvent(PCVBOXEXTPACKHLP pHlp, + VBOXEXTPACK_IF_CS(IEventSource) *aSource, + /* VBoxEventType_T */ uint32_t aType, + VBOXEXTPACK_IF_CS(IVetoEvent) **ppEventOut); + static DECLCALLBACK(const char *) i_hlpTranslate(PCVBOXEXTPACKHLP pHlp, + const char *pszComponent, + const char *pszSourceText, + const char *pszComment = NULL, + const size_t aNum = ~(size_t)0); + static DECLCALLBACK(int) i_hlpReservedN(PCVBOXEXTPACKHLP pHlp); + /** @} */ + +private: + + // wrapped IExtPack properties + HRESULT getName(com::Utf8Str &aName); + HRESULT getDescription(com::Utf8Str &aDescription); + HRESULT getVersion(com::Utf8Str &aVersion); + HRESULT getRevision(ULONG *aRevision); + HRESULT getEdition(com::Utf8Str &aEdition); + HRESULT getVRDEModule(com::Utf8Str &aVRDEModule); + HRESULT getCryptoModule(com::Utf8Str &aCryptoModule); + HRESULT getPlugIns(std::vector<ComPtr<IExtPackPlugIn> > &aPlugIns); + HRESULT getUsable(BOOL *aUsable); + HRESULT getWhyUnusable(com::Utf8Str &aWhyUnusable); + HRESULT getShowLicense(BOOL *aShowLicense); + HRESULT getLicense(com::Utf8Str &aLicense); + + // wrapped IExtPack methods + HRESULT queryLicense(const com::Utf8Str &aPreferredLocale, + const com::Utf8Str &aPreferredLanguage, + const com::Utf8Str &aFormat, + com::Utf8Str &aLicenseText); + HRESULT queryObject(const com::Utf8Str &aObjUuid, + ComPtr<IUnknown> &aReturnInterface); + + + struct Data; + /** Pointer to the private instance. */ + Data *m; + + friend class ExtPackManager; +}; + + +/** + * Extension pack manager. + */ +class ATL_NO_VTABLE ExtPackManager : + public ExtPackManagerWrap +{ +public: + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(ExtPackManager) + + HRESULT FinalConstruct(); + void FinalRelease(); + HRESULT initExtPackManager(VirtualBox *a_pVirtualBox, VBOXEXTPACKCTX a_enmContext); + void uninit(); + /** @} */ + + /** @name Internal interfaces used by other Main classes. + * @{ */ +#ifndef VBOX_COM_INPROC + HRESULT i_doInstall(ExtPackFile *a_pExtPackFile, bool a_fReplace, Utf8Str const *a_pstrDisplayInfo); + HRESULT i_doUninstall(const Utf8Str *a_pstrName, bool a_fForcedRemoval, const Utf8Str *a_pstrDisplayInfo); + void i_callAllVirtualBoxReadyHooks(void); + HRESULT i_queryObjects(const com::Utf8Str &aObjUuid, std::vector<ComPtr<IUnknown> > &aObjects, std::vector<com::Utf8Str> *a_pstrExtPackNames); +#endif +#ifdef VBOX_COM_INPROC + void i_callAllConsoleReadyHooks(IConsole *a_pConsole); +#endif +#ifndef VBOX_COM_INPROC + void i_callAllVmCreatedHooks(IMachine *a_pMachine); +#endif +#ifdef VBOX_COM_INPROC + int i_callAllVmConfigureVmmHooks(IConsole *a_pConsole, PVM a_pVM, PCVMMR3VTABLE a_pVMM); + int i_callAllVmPowerOnHooks(IConsole *a_pConsole, PVM a_pVM, PCVMMR3VTABLE a_pVMM); + void i_callAllVmPowerOffHooks(IConsole *a_pConsole, PVM a_pVM, PCVMMR3VTABLE a_pVMM); +#endif + HRESULT i_checkVrdeExtPack(Utf8Str const *a_pstrExtPack); + int i_getVrdeLibraryPathForExtPack(Utf8Str const *a_pstrExtPack, Utf8Str *a_pstrVrdeLibrary); + HRESULT i_checkCryptoExtPack(Utf8Str const *a_pstrExtPack); + int i_getCryptoLibraryPathForExtPack(Utf8Str const *a_pstrExtPack, Utf8Str *a_pstrVrdeLibrary); + HRESULT i_getLibraryPathForExtPack(const char *a_pszModuleName, const char *a_pszExtPack, Utf8Str *a_pstrLibrary); + HRESULT i_getDefaultVrdeExtPack(Utf8Str *a_pstrExtPack); + HRESULT i_getDefaultCryptoExtPack(Utf8Str *a_pstrExtPack); + bool i_isExtPackUsable(const char *a_pszExtPack); + void i_dumpAllToReleaseLog(void); + uint64_t i_getUpdateCounter(void); + /** @} */ + +private: + // wrapped IExtPackManager properties + HRESULT getInstalledExtPacks(std::vector<ComPtr<IExtPack> > &aInstalledExtPacks); + + // wrapped IExtPackManager methods + HRESULT find(const com::Utf8Str &aName, + ComPtr<IExtPack> &aReturnData); + HRESULT openExtPackFile(const com::Utf8Str &aPath, + ComPtr<IExtPackFile> &aFile); + HRESULT uninstall(const com::Utf8Str &aName, + BOOL aForcedRemoval, + const com::Utf8Str &aDisplayInfo, + ComPtr<IProgress> &aProgess); + HRESULT cleanup(); + HRESULT queryAllPlugInsForFrontend(const com::Utf8Str &aFrontendName, + std::vector<com::Utf8Str> &aPlugInModules); + HRESULT isExtPackUsable(const com::Utf8Str &aName, + BOOL *aUsable); + + bool i_areThereAnyRunningVMs(void) const; + HRESULT i_runSetUidToRootHelper(Utf8Str const *a_pstrDisplayInfo, const char *a_pszCommand, ...); + ExtPack *i_findExtPack(const char *a_pszName); + void i_removeExtPack(const char *a_pszName); + HRESULT i_refreshExtPack(const char *a_pszName, bool a_fUnsuableIsError, ExtPack **a_ppExtPack); + +private: + struct Data; + /** Pointer to the private instance. */ + Data *m; + + friend class ExtPackUninstallTask; +}; + +#endif /* !MAIN_INCLUDED_ExtPackManagerImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/ExtPackUtil.h b/src/VBox/Main/include/ExtPackUtil.h new file mode 100644 index 00000000..ec9ca730 --- /dev/null +++ b/src/VBox/Main/include/ExtPackUtil.h @@ -0,0 +1,158 @@ +/* $Id: ExtPackUtil.h $ */ +/** @file + * VirtualBox Main - Extension Pack Utilities and definitions, VBoxC, VBoxSVC, ++. + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ExtPackUtil_h +#define MAIN_INCLUDED_ExtPackUtil_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifdef __cplusplus +# include <iprt/cpp/ministring.h> +#endif +#include <iprt/fs.h> +#include <iprt/vfs.h> + + +/** @name VBOX_EXTPACK_DESCRIPTION_NAME + * The name of the description file in an extension pack. */ +#define VBOX_EXTPACK_DESCRIPTION_NAME "ExtPack.xml" +/** @name VBOX_EXTPACK_DESCRIPTION_NAME + * The name of the manifest file in an extension pack. */ +#define VBOX_EXTPACK_MANIFEST_NAME "ExtPack.manifest" +/** @name VBOX_EXTPACK_SIGNATURE_NAME + * The name of the signature file in an extension pack. */ +#define VBOX_EXTPACK_SIGNATURE_NAME "ExtPack.signature" +/** @name VBOX_EXTPACK_LICENSE_NAME_PREFIX + * The name prefix of a license file in an extension pack. There can be + * several license files in a pack, the variations being on locale, language + * and format (HTML, RTF, plain text). All extension packages shall include + * a */ +#define VBOX_EXTPACK_LICENSE_NAME_PREFIX "ExtPack-license" +/** @name VBOX_EXTPACK_SUFFIX + * The suffix of a extension pack tarball. */ +#define VBOX_EXTPACK_SUFFIX ".vbox-extpack" + +/** The minimum length (strlen) of a extension pack name. */ +#define VBOX_EXTPACK_NAME_MIN_LEN 3 +/** The max length (strlen) of a extension pack name. */ +#define VBOX_EXTPACK_NAME_MAX_LEN 64 + +/** The architecture-dependent application data subdirectory where the + * extension packs are installed. Relative to RTPathAppPrivateArch. */ +#define VBOX_EXTPACK_INSTALL_DIR "ExtensionPacks" +/** The architecture-independent application data subdirectory where the + * certificates are installed. Relative to RTPathAppPrivateNoArch. */ +#define VBOX_EXTPACK_CERT_DIR "ExtPackCertificates" + +/** The maximum entry name length. + * Play short and safe. */ +#define VBOX_EXTPACK_MAX_MEMBER_NAME_LENGTH 128 + + +#ifdef __cplusplus + +/** + * Plug-in descriptor. + */ +typedef struct VBOXEXTPACKPLUGINDESC +{ + /** The name. */ + RTCString strName; + /** The module name. */ + RTCString strModule; + /** The description. */ + RTCString strDescription; + /** The frontend or component which it plugs into. */ + RTCString strFrontend; +} VBOXEXTPACKPLUGINDESC; +/** Pointer to a plug-in descriptor. */ +typedef VBOXEXTPACKPLUGINDESC *PVBOXEXTPACKPLUGINDESC; + +/** + * Extension pack descriptor + * + * This is the internal representation of the ExtPack.xml. + */ +typedef struct VBOXEXTPACKDESC +{ + /** The name. */ + RTCString strName; + /** The description. */ + RTCString strDescription; + /** The version string. */ + RTCString strVersion; + /** The edition string. */ + RTCString strEdition; + /** The internal revision number. */ + uint32_t uRevision; + /** The name of the main module. */ + RTCString strMainModule; + /** The name of the main VM module, empty if none. */ + RTCString strMainVMModule; + /** The name of the VRDE module, empty if none. */ + RTCString strVrdeModule; + /** The name of the cryptographic module, empty if none. */ + RTCString strCryptoModule; + /** The number of plug-in descriptors. */ + uint32_t cPlugIns; + /** Pointer to an array of plug-in descriptors. */ + PVBOXEXTPACKPLUGINDESC paPlugIns; + /** Whether to show the license prior to installation. */ + bool fShowLicense; +} VBOXEXTPACKDESC; + +/** Pointer to a extension pack descriptor. */ +typedef VBOXEXTPACKDESC *PVBOXEXTPACKDESC; +/** Pointer to a const extension pack descriptor. */ +typedef VBOXEXTPACKDESC const *PCVBOXEXTPACKDESC; + + +void VBoxExtPackInitDesc(PVBOXEXTPACKDESC a_pExtPackDesc); +RTCString *VBoxExtPackLoadDesc(const char *a_pszDir, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo); +RTCString *VBoxExtPackLoadDescFromVfsFile(RTVFSFILE hVfsFile, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo); +RTCString *VBoxExtPackExtractNameFromTarballPath(const char *pszTarball); +void VBoxExtPackFreeDesc(PVBOXEXTPACKDESC a_pExtPackDesc); +bool VBoxExtPackIsValidName(const char *pszName); +bool VBoxExtPackIsValidMangledName(const char *pszMangledName, size_t cchMax = RTSTR_MAX); +RTCString *VBoxExtPackMangleName(const char *pszName); +RTCString *VBoxExtPackUnmangleName(const char *pszMangledName, size_t cbMax); +int VBoxExtPackCalcDir(char *pszExtPackDir, size_t cbExtPackDir, const char *pszParentDir, const char *pszName); +bool VBoxExtPackIsValidVersionString(const char *pszVersion); +bool VBoxExtPackIsValidEditionString(const char *pszEdition); +bool VBoxExtPackIsValidModuleString(const char *pszModule); + +int VBoxExtPackValidateMember(const char *pszName, RTVFSOBJTYPE enmType, RTVFSOBJ hVfsObj, char *pszError, size_t cbError); +int VBoxExtPackOpenTarFss(RTFILE hTarballFile, char *pszError, size_t cbError, PRTVFSFSSTREAM phTarFss, PRTMANIFEST phFileManifest); +int VBoxExtPackValidateTarball(RTFILE hTarballFile, const char *pszExtPackName, + const char *pszTarball, const char *pszTarballDigest, + char *pszError, size_t cbError, + PRTMANIFEST phValidManifest, PRTVFSFILE phXmlFile, RTCString *pStrDigest); +#endif /* __cplusplus */ + +#endif /* !MAIN_INCLUDED_ExtPackUtil_h */ + diff --git a/src/VBox/Main/include/Global.h b/src/VBox/Main/include/Global.h new file mode 100644 index 00000000..8244ef61 --- /dev/null +++ b/src/VBox/Main/include/Global.h @@ -0,0 +1,255 @@ +/* $Id: Global.h $ */ +/** @file + * VirtualBox COM API - Global Declarations and Definitions. + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_Global_h +#define MAIN_INCLUDED_Global_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* interface definitions */ +#include "VBox/com/VirtualBox.h" + +#include <VBox/ostypes.h> + +#include <iprt/types.h> + +#define VBOXOSHINT_NONE 0 +#define VBOXOSHINT_64BIT RT_BIT(0) +#define VBOXOSHINT_HWVIRTEX RT_BIT(1) +#define VBOXOSHINT_IOAPIC RT_BIT(2) +#define VBOXOSHINT_EFI RT_BIT(3) +#define VBOXOSHINT_PAE RT_BIT(4) +#define VBOXOSHINT_USBHID RT_BIT(5) +#define VBOXOSHINT_HPET RT_BIT(6) +#define VBOXOSHINT_USBTABLET RT_BIT(7) +#define VBOXOSHINT_RTCUTC RT_BIT(8) +#define VBOXOSHINT_ACCEL2D RT_BIT(9) +#define VBOXOSHINT_ACCEL3D RT_BIT(10) +#define VBOXOSHINT_FLOPPY RT_BIT(11) +#define VBOXOSHINT_NOUSB RT_BIT(12) +#define VBOXOSHINT_TFRESET RT_BIT(13) +#define VBOXOSHINT_USB3 RT_BIT(14) +#define VBOXOSHINT_X2APIC RT_BIT(15) +#define VBOXOSHINT_EFI_SECUREBOOT RT_BIT(16) +#define VBOXOSHINT_TPM RT_BIT(17) +#define VBOXOSHINT_TPM2 RT_BIT(18) +#define VBOXOSHINT_WDDM_GRAPHICS RT_BIT(19) + +/** The VBoxVRDP kludge extension pack name. + * + * This is not a valid extension pack name (dashes are not allowed), and + * hence will not conflict with real extension packs. + */ +#define VBOXVRDP_KLUDGE_EXTPACK_NAME "Built-in-VBoxVRDP" + +/** The VBoxPuelCrypto kludge extension pack name. + * + * This is not a valid extension pack name (dashes are not allowed), and + * hence will not conflict with real extension packs. + */ +#define VBOXPUELCRYPTO_KLUDGE_EXTPACK_NAME "Built-in-VBoxPuelCrypto" + +/** + * Contains global static definitions that can be referenced by all COM classes + * regardless of the apartment. + */ +class Global +{ +public: + + /** Represents OS Type <-> string mappings. */ + struct OSType + { + const char *familyId; /* utf-8 */ + const char *familyDescription; /* utf-8 */ + const char *id; /* utf-8, VM config file value */ + const char *description; /* utf-8 */ + const VBOXOSTYPE osType; + const uint32_t osHint; + const uint32_t recommendedCPUCount; + const uint32_t recommendedRAM; + const uint32_t recommendedVRAM; + const uint64_t recommendedHDD; + const GraphicsControllerType_T graphicsControllerType; + const NetworkAdapterType_T networkAdapterType; + const uint32_t numSerialEnabled; + const StorageControllerType_T dvdStorageControllerType; + const StorageBus_T dvdStorageBusType; + const StorageControllerType_T hdStorageControllerType; + const StorageBus_T hdStorageBusType; + const ChipsetType_T chipsetType; + const IommuType_T iommuType; + const AudioControllerType_T audioControllerType; + const AudioCodecType_T audioCodecType; + }; + + static const OSType sOSTypes[]; + static size_t cOSTypes; + + /** + * Maps VBOXOSTYPE to the OS type which is used in VM configs. + */ + static const char *OSTypeId(VBOXOSTYPE aOSType); + + /** + * Maps an OS type ID string to index into sOSTypes. + * @returns index on success, UINT32_MAX if not found. + */ + static uint32_t getOSTypeIndexFromId(const char *pszId); + + /** + * Get the network adapter limit for each chipset type. + */ + static uint32_t getMaxNetworkAdapters(ChipsetType_T aChipsetType); + + /** + * Returns @c true if the given machine state is an online state. This is a + * recommended way to detect if the VM is online (being executed in a + * dedicated process) or not. Note that some online states are also + * transitional states (see #IsTransient()). + */ + static bool IsOnline(MachineState_T aState) + { + return aState >= MachineState_FirstOnline && + aState <= MachineState_LastOnline; + } + + /** + * Returns @c true if the given machine state is a transient state. This is + * a recommended way to detect if the VM is performing some potentially + * lengthy operation (such as starting, stopping, saving, deleting + * snapshot, etc.). Note some (but not all) transitional states are also + * online states (see #IsOnline()). + */ + static bool IsTransient(MachineState_T aState) + { + return aState >= MachineState_FirstTransient && + aState <= MachineState_LastTransient; + } + + /** + * Shortcut to <tt>IsOnline(aState) || IsTransient(aState)</tt>. When it returns + * @c false, the VM is turned off (no VM process) and not busy with + * another exclusive operation. + */ + static bool IsOnlineOrTransient(MachineState_T aState) + { + return IsOnline(aState) || IsTransient(aState); + } + + /** + * Stringify a machine state - translated. + * + * Drop the Global:: prefix and include StringifyEnums.h for an untranslated + * version of this method. + * + * @returns Pointer to a read only string. + * @param aState Valid machine state. + */ + static const char *stringifyMachineState(MachineState_T aState); + + /** + * Stringify a session state - translated. + * + * Drop the Global:: prefix and include StringifyEnums.h for an untranslated + * version of this method. + * + * @returns Pointer to a read only string. + * @param aState Valid session state. + */ + static const char *stringifySessionState(SessionState_T aState); + + /** + * Stringify a device type. + * + * Drop the Global:: prefix and include StringifyEnums.h for an untranslated + * version of this method. + * + * @returns Pointer to a read only string. + * @param aType The device type. + */ + static const char *stringifyDeviceType(DeviceType_T aType); + + /** + * Stringify a storage controller type. + * + * Drop the Global:: prefix and include StringifyEnums.h for an untranslated + * version of this method. + * + * @returns Pointer to a read only string. + * @param aType The storage controller type. + */ + static const char *stringifyStorageControllerType(StorageControllerType_T aType); + +#if 0 /* unused */ + /** + * Stringify a storage bus type. + * + * Drop the Global:: prefix and include StringifyEnums.h for an untranslated + * version of this method. + * + * @returns Pointer to a read only string. + * @param aBus The storage bus type. + */ + static const char *stringifyStorageBus(StorageBus_T aBus); + + /** + * Stringify a reason. + * + * Drop the Global:: prefix and include StringifyEnums.h for an untranslated + * version of this method. + * + * @returns Pointer to a read only string. + * @param aReason The reason code. + */ + static const char *stringifyReason(Reason_T aReason); +#endif + + /** + * Try convert a COM status code to a VirtualBox status code (VBox/err.h). + * + * @returns VBox status code. + * @param aComStatus COM status code. + */ + static int vboxStatusCodeFromCOM(HRESULT aComStatus); + + /** + * Try convert a VirtualBox status code (VBox/err.h) to a COM status code. + * + * This is mainly intended for dealing with vboxStatusCodeFromCOM() return + * values. If used on anything else, it won't be able to cope with most of the + * input! + * + * @returns COM status code. + * @param aVBoxStatus VBox status code. + */ + static HRESULT vboxStatusCodeToCOM(int aVBoxStatus); +}; + +#endif /* !MAIN_INCLUDED_Global_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/GraphicsAdapterImpl.h b/src/VBox/Main/include/GraphicsAdapterImpl.h new file mode 100644 index 00000000..6be3dccf --- /dev/null +++ b/src/VBox/Main/include/GraphicsAdapterImpl.h @@ -0,0 +1,88 @@ +/* $Id: GraphicsAdapterImpl.h $ */ +/** @file + * Implementation of IGraphicsAdapter in VBoxSVC - Header. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GraphicsAdapterImpl_h +#define MAIN_INCLUDED_GraphicsAdapterImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "GraphicsAdapterWrap.h" + + +namespace settings +{ + struct GraphicsAdapter; +}; + + +class ATL_NO_VTABLE GraphicsAdapter : + public GraphicsAdapterWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(GraphicsAdapter) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent); + HRESULT init(Machine *aParent, GraphicsAdapter *aThat); + HRESULT initCopy(Machine *aParent, GraphicsAdapter *aThat); + void uninit(); + + + // public methods only for internal purposes + HRESULT i_loadSettings(const settings::GraphicsAdapter &data); + HRESULT i_saveSettings(settings::GraphicsAdapter &data); + + void i_rollback(); + void i_commit(); + void i_copyFrom(GraphicsAdapter *aThat); + +private: + + // wrapped IGraphicsAdapter properties + HRESULT getGraphicsControllerType(GraphicsControllerType_T *aGraphicsControllerType); + HRESULT setGraphicsControllerType(GraphicsControllerType_T aGraphicsControllerType); + HRESULT getVRAMSize(ULONG *aVRAMSize); + HRESULT setVRAMSize(ULONG aVRAMSize); + HRESULT getAccelerate3DEnabled(BOOL *aAccelerate3DEnabled); + HRESULT setAccelerate3DEnabled(BOOL aAccelerate3DEnabled); + HRESULT getAccelerate2DVideoEnabled(BOOL *aAccelerate2DVideoEnabled); + HRESULT setAccelerate2DVideoEnabled(BOOL aAccelerate2DVideoEnabled); + HRESULT getMonitorCount(ULONG *aMonitorCount); + HRESULT setMonitorCount(ULONG aMonitorCount); + + Machine * const mParent; + const ComObjPtr<GraphicsAdapter> mPeer; + Backupable<settings::GraphicsAdapter> mData; +}; + +#endif /* !MAIN_INCLUDED_GraphicsAdapterImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/GuestCtrlImplPrivate.h b/src/VBox/Main/include/GuestCtrlImplPrivate.h new file mode 100644 index 00000000..abdaafe0 --- /dev/null +++ b/src/VBox/Main/include/GuestCtrlImplPrivate.h @@ -0,0 +1,1422 @@ +/* $Id: GuestCtrlImplPrivate.h $ */ +/** @file + * Internal helpers/structures for guest control functionality. + */ + +/* + * Copyright (C) 2011-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestCtrlImplPrivate_h +#define MAIN_INCLUDED_GuestCtrlImplPrivate_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "ConsoleImpl.h" +#include "Global.h" + +#include <iprt/asm.h> +#include <iprt/env.h> +#include <iprt/semaphore.h> +#include <iprt/cpp/utils.h> + +#include <VBox/com/com.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/string.h> +#include <VBox/com/VirtualBox.h> +#include <VBox/err.h> /* VERR_GSTCTL_GUEST_ERROR */ + +#include <map> +#include <vector> + +using namespace com; + +#ifdef VBOX_WITH_GUEST_CONTROL +# include <VBox/GuestHost/GuestControl.h> +# include <VBox/HostServices/GuestControlSvc.h> +using namespace guestControl; +#endif + +/** Vector holding a process' CPU affinity. */ +typedef std::vector <LONG> ProcessAffinity; +/** Vector holding process startup arguments. */ +typedef std::vector <Utf8Str> ProcessArguments; + +class GuestProcessStreamBlock; +class GuestSession; + + +/** + * Simple structure mantaining guest credentials. + */ +struct GuestCredentials +{ + Utf8Str mUser; + Utf8Str mPassword; + Utf8Str mDomain; +}; + + +/** + * Wrapper around the RTEnv API, unusable base class. + * + * @remarks Feel free to elevate this class to iprt/cpp/env.h as RTCEnv. + */ +class GuestEnvironmentBase +{ +public: + /** + * Default constructor. + * + * The user must invoke one of the init methods before using the object. + */ + GuestEnvironmentBase(void) + : m_hEnv(NIL_RTENV) + , m_cRefs(1) + , m_fFlags(0) + { } + + /** + * Destructor. + */ + virtual ~GuestEnvironmentBase(void) + { + Assert(m_cRefs <= 1); + int rc = RTEnvDestroy(m_hEnv); AssertRC(rc); + m_hEnv = NIL_RTENV; + } + + /** + * Retains a reference to this object. + * @returns New reference count. + * @remarks Sharing an object is currently only safe if no changes are made to + * it because RTENV does not yet implement any locking. For the only + * purpose we need this, implementing IGuestProcess::environment by + * using IGuestSession::environmentBase, that's fine as the session + * base environment is immutable. + */ + uint32_t retain(void) + { + uint32_t cRefs = ASMAtomicIncU32(&m_cRefs); + Assert(cRefs > 1); Assert(cRefs < _1M); + return cRefs; + + } + /** Useful shortcut. */ + uint32_t retainConst(void) const { return unconst(this)->retain(); } + + /** + * Releases a reference to this object, deleting the object when reaching zero. + * @returns New reference count. + */ + uint32_t release(void) + { + uint32_t cRefs = ASMAtomicDecU32(&m_cRefs); + Assert(cRefs < _1M); + if (cRefs == 0) + delete this; + return cRefs; + } + + /** Useful shortcut. */ + uint32_t releaseConst(void) const { return unconst(this)->retain(); } + + /** + * Checks if the environment has been successfully initialized or not. + * + * @returns @c true if initialized, @c false if not. + */ + bool isInitialized(void) const + { + return m_hEnv != NIL_RTENV; + } + + /** + * Returns the variable count. + * @return Number of variables. + * @sa RTEnvCountEx + */ + uint32_t count(void) const + { + return RTEnvCountEx(m_hEnv); + } + + /** + * Deletes the environment change record entirely. + * + * The count() method will return zero after this call. + * + * @sa RTEnvReset + */ + void reset(void) + { + int rc = RTEnvReset(m_hEnv); + AssertRC(rc); + } + + /** + * Exports the environment change block as an array of putenv style strings. + * + * + * @returns VINF_SUCCESS or VERR_NO_MEMORY. + * @param pArray The output array. + */ + int queryPutEnvArray(std::vector<com::Utf8Str> *pArray) const + { + uint32_t cVars = RTEnvCountEx(m_hEnv); + try + { + pArray->resize(cVars); + for (uint32_t iVar = 0; iVar < cVars; iVar++) + { + const char *psz = RTEnvGetByIndexRawEx(m_hEnv, iVar); + AssertReturn(psz, VERR_INTERNAL_ERROR_3); /* someone is racing us! */ + (*pArray)[iVar] = psz; + } + return VINF_SUCCESS; + } + catch (std::bad_alloc &) + { + return VERR_NO_MEMORY; + } + } + + /** + * Applies an array of putenv style strings. + * + * @returns IPRT status code. + * @param rArray The array with the putenv style strings. + * @param pidxError Where to return the index causing trouble on + * failure. Optional. + * @sa RTEnvPutEx + */ + int applyPutEnvArray(const std::vector<com::Utf8Str> &rArray, size_t *pidxError = NULL) + { + size_t const cArray = rArray.size(); + for (size_t i = 0; i < cArray; i++) + { + int rc = RTEnvPutEx(m_hEnv, rArray[i].c_str()); + if (RT_FAILURE(rc)) + { + if (pidxError) + *pidxError = i; + return rc; + } + } + return VINF_SUCCESS; + } + + /** + * Applies the changes from another environment to this. + * + * @returns IPRT status code. + * @param rChanges Reference to an environment which variables will be + * imported and, if it's a change record, schedule + * variable unsets will be applied. + * @sa RTEnvApplyChanges + */ + int applyChanges(const GuestEnvironmentBase &rChanges) + { + return RTEnvApplyChanges(m_hEnv, rChanges.m_hEnv); + } + + /** + * See RTEnvQueryUtf8Block for details. + * @returns IPRT status code. + * @param ppszzBlock Where to return the block pointer. + * @param pcbBlock Where to optionally return the block size. + * @sa RTEnvQueryUtf8Block + */ + int queryUtf8Block(char **ppszzBlock, size_t *pcbBlock) + { + return RTEnvQueryUtf8Block(m_hEnv, true /*fSorted*/, ppszzBlock, pcbBlock); + } + + /** + * Frees what queryUtf8Block returned, NULL ignored. + * @sa RTEnvFreeUtf8Block + */ + static void freeUtf8Block(char *pszzBlock) + { + return RTEnvFreeUtf8Block(pszzBlock); + } + + /** + * Applies a block on the format returned by queryUtf8Block. + * + * @returns IPRT status code. + * @param pszzBlock Pointer to the block. + * @param cbBlock The size of the block. + * @param fNoEqualMeansUnset Whether the lack of a '=' (equal) sign in a + * string means it should be unset (@c true), or if + * it means the variable should be defined with an + * empty value (@c false, the default). + * @todo move this to RTEnv! + */ + int copyUtf8Block(const char *pszzBlock, size_t cbBlock, bool fNoEqualMeansUnset = false) + { + int rc = VINF_SUCCESS; + while (cbBlock > 0 && *pszzBlock != '\0') + { + const char *pszEnd = (const char *)memchr(pszzBlock, '\0', cbBlock); + if (!pszEnd) + return VERR_BUFFER_UNDERFLOW; + int rc2; + if (fNoEqualMeansUnset || strchr(pszzBlock, '=')) + rc2 = RTEnvPutEx(m_hEnv, pszzBlock); + else + rc2 = RTEnvSetEx(m_hEnv, pszzBlock, ""); + if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) + rc = rc2; + + /* Advance. */ + cbBlock -= pszEnd - pszzBlock; + if (cbBlock < 2) + return VERR_BUFFER_UNDERFLOW; + cbBlock--; + pszzBlock = pszEnd + 1; + } + + /* The remainder must be zero padded. */ + if (RT_SUCCESS(rc)) + { + if (ASMMemIsZero(pszzBlock, cbBlock)) + return VINF_SUCCESS; + return VERR_TOO_MUCH_DATA; + } + return rc; + } + + /** + * Get an environment variable. + * + * @returns IPRT status code. + * @param rName The variable name. + * @param pValue Where to return the value. + * @sa RTEnvGetEx + */ + int getVariable(const com::Utf8Str &rName, com::Utf8Str *pValue) const + { + size_t cchNeeded; + int rc = RTEnvGetEx(m_hEnv, rName.c_str(), NULL, 0, &cchNeeded); + if ( RT_SUCCESS(rc) + || rc == VERR_BUFFER_OVERFLOW) + { + try + { + pValue->reserve(cchNeeded + 1); + rc = RTEnvGetEx(m_hEnv, rName.c_str(), pValue->mutableRaw(), pValue->capacity(), NULL); + pValue->jolt(); + } + catch (std::bad_alloc &) + { + rc = VERR_NO_STR_MEMORY; + } + } + return rc; + } + + /** + * Checks if the given variable exists. + * + * @returns @c true if it exists, @c false if not or if it's an scheduled unset + * in a environment change record. + * @param rName The variable name. + * @sa RTEnvExistEx + */ + bool doesVariableExist(const com::Utf8Str &rName) const + { + return RTEnvExistEx(m_hEnv, rName.c_str()); + } + + /** + * Set an environment variable. + * + * @returns IPRT status code. + * @param rName The variable name. + * @param rValue The value of the variable. + * @sa RTEnvSetEx + */ + int setVariable(const com::Utf8Str &rName, const com::Utf8Str &rValue) + { + return RTEnvSetEx(m_hEnv, rName.c_str(), rValue.c_str()); + } + + /** + * Unset an environment variable. + * + * @returns IPRT status code. + * @param rName The variable name. + * @sa RTEnvUnsetEx + */ + int unsetVariable(const com::Utf8Str &rName) + { + return RTEnvUnsetEx(m_hEnv, rName.c_str()); + } + +protected: + /** + * Copy constructor. + * @throws HRESULT + */ + GuestEnvironmentBase(const GuestEnvironmentBase &rThat, bool fChangeRecord, uint32_t fFlags = 0) + : m_hEnv(NIL_RTENV) + , m_cRefs(1) + , m_fFlags(fFlags) + { + int rc = cloneCommon(rThat, fChangeRecord); + if (RT_FAILURE(rc)) + throw (Global::vboxStatusCodeToCOM(rc)); + } + + /** + * Common clone/copy method with type conversion abilities. + * + * @returns IPRT status code. + * @param rThat The object to clone. + * @param fChangeRecord Whether the this instance is a change record (true) + * or normal (false) environment. + */ + int cloneCommon(const GuestEnvironmentBase &rThat, bool fChangeRecord) + { + int rc = VINF_SUCCESS; + RTENV hNewEnv = NIL_RTENV; + if (rThat.m_hEnv != NIL_RTENV) + { + /* + * Clone it. + */ + if (RTEnvIsChangeRecord(rThat.m_hEnv) == fChangeRecord) + rc = RTEnvClone(&hNewEnv, rThat.m_hEnv); + else + { + /* Need to type convert it. */ + if (fChangeRecord) + rc = RTEnvCreateChangeRecordEx(&hNewEnv, rThat.m_fFlags); + else + rc = RTEnvCreateEx(&hNewEnv, rThat.m_fFlags); + if (RT_SUCCESS(rc)) + { + rc = RTEnvApplyChanges(hNewEnv, rThat.m_hEnv); + if (RT_FAILURE(rc)) + RTEnvDestroy(hNewEnv); + } + } + } + else + { + /* + * Create an empty one so the object works smoothly. + * (Relevant for GuestProcessStartupInfo and internal commands.) + */ + if (fChangeRecord) + rc = RTEnvCreateChangeRecordEx(&hNewEnv, rThat.m_fFlags); + else + rc = RTEnvCreateEx(&hNewEnv, rThat.m_fFlags); + } + if (RT_SUCCESS(rc)) + { + RTEnvDestroy(m_hEnv); + m_hEnv = hNewEnv; + m_fFlags = rThat.m_fFlags; + } + return rc; + } + + + /** The environment change record. */ + RTENV m_hEnv; + /** Reference counter. */ + uint32_t volatile m_cRefs; + /** RTENV_CREATE_F_XXX. */ + uint32_t m_fFlags; +}; + +class GuestEnvironmentChanges; + + +/** + * Wrapper around the RTEnv API for a normal environment. + */ +class GuestEnvironment : public GuestEnvironmentBase +{ +public: + /** + * Default constructor. + * + * The user must invoke one of the init methods before using the object. + */ + GuestEnvironment(void) + : GuestEnvironmentBase() + { } + + /** + * Copy operator. + * @param rThat The object to copy. + * @throws HRESULT + */ + GuestEnvironment(const GuestEnvironment &rThat) + : GuestEnvironmentBase(rThat, false /*fChangeRecord*/) + { } + + /** + * Copy operator. + * @param rThat The object to copy. + * @throws HRESULT + */ + GuestEnvironment(const GuestEnvironmentBase &rThat) + : GuestEnvironmentBase(rThat, false /*fChangeRecord*/) + { } + + /** + * Initialize this as a normal environment block. + * @returns IPRT status code. + * @param fFlags RTENV_CREATE_F_XXX + */ + int initNormal(uint32_t fFlags) + { + AssertReturn(m_hEnv == NIL_RTENV, VERR_WRONG_ORDER); + m_fFlags = fFlags; + return RTEnvCreateEx(&m_hEnv, fFlags); + } + + /** + * Replaces this environemnt with that in @a rThat. + * + * @returns IPRT status code + * @param rThat The environment to copy. If it's a different type + * we'll convert the data to a normal environment block. + */ + int copy(const GuestEnvironmentBase &rThat) + { + return cloneCommon(rThat, false /*fChangeRecord*/); + } + + /** + * @copydoc copy() + */ + GuestEnvironment &operator=(const GuestEnvironmentBase &rThat) + { + int rc = copy(rThat); + if (RT_FAILURE(rc)) + throw (Global::vboxStatusCodeToCOM(rc)); + return *this; + } + + /** @copydoc copy() */ + GuestEnvironment &operator=(const GuestEnvironment &rThat) + { return operator=((const GuestEnvironmentBase &)rThat); } + + /** @copydoc copy() */ + GuestEnvironment &operator=(const GuestEnvironmentChanges &rThat) + { return operator=((const GuestEnvironmentBase &)rThat); } + +}; + + +/** + * Wrapper around the RTEnv API for a environment change record. + * + * This class is used as a record of changes to be applied to a different + * environment block (in VBoxService before launching a new process). + */ +class GuestEnvironmentChanges : public GuestEnvironmentBase +{ +public: + /** + * Default constructor. + * + * The user must invoke one of the init methods before using the object. + */ + GuestEnvironmentChanges(void) + : GuestEnvironmentBase() + { } + + /** + * Copy operator. + * @param rThat The object to copy. + * @throws HRESULT + */ + GuestEnvironmentChanges(const GuestEnvironmentChanges &rThat) + : GuestEnvironmentBase(rThat, true /*fChangeRecord*/) + { } + + /** + * Copy operator. + * @param rThat The object to copy. + * @throws HRESULT + */ + GuestEnvironmentChanges(const GuestEnvironmentBase &rThat) + : GuestEnvironmentBase(rThat, true /*fChangeRecord*/) + { } + + /** + * Initialize this as a environment change record. + * @returns IPRT status code. + * @param fFlags RTENV_CREATE_F_XXX + */ + int initChangeRecord(uint32_t fFlags) + { + AssertReturn(m_hEnv == NIL_RTENV, VERR_WRONG_ORDER); + m_fFlags = fFlags; + return RTEnvCreateChangeRecordEx(&m_hEnv, fFlags); + } + + /** + * Replaces this environemnt with that in @a rThat. + * + * @returns IPRT status code + * @param rThat The environment to copy. If it's a different type + * we'll convert the data to a set of changes. + */ + int copy(const GuestEnvironmentBase &rThat) + { + return cloneCommon(rThat, true /*fChangeRecord*/); + } + + /** + * @copydoc copy() + */ + GuestEnvironmentChanges &operator=(const GuestEnvironmentBase &rThat) + { + int rc = copy(rThat); + if (RT_FAILURE(rc)) + throw (Global::vboxStatusCodeToCOM(rc)); + return *this; + } + + /** @copydoc copy() */ + GuestEnvironmentChanges &operator=(const GuestEnvironmentChanges &rThat) + { return operator=((const GuestEnvironmentBase &)rThat); } + + /** @copydoc copy() */ + GuestEnvironmentChanges &operator=(const GuestEnvironment &rThat) + { return operator=((const GuestEnvironmentBase &)rThat); } +}; + +/** + * Class for keeping guest error information. + */ +class GuestErrorInfo +{ +public: + + /** + * Enumeration for specifying the guest error type. + */ + enum Type + { + /** Guest error is anonymous. Avoid this. */ + Type_Anonymous = 0, + /** Guest error is from a guest session. */ + Type_Session, + /** Guest error is from a guest process. */ + Type_Process, + /** Guest error is from a guest file object. */ + Type_File, + /** Guest error is from a guest directory object. */ + Type_Directory, + /** Guest error is from a the built-in toolbox "vbox_cat" command. */ + Type_ToolCat, + /** Guest error is from a the built-in toolbox "vbox_ls" command. */ + Type_ToolLs, + /** Guest error is from a the built-in toolbox "vbox_rm" command. */ + Type_ToolRm, + /** Guest error is from a the built-in toolbox "vbox_mkdir" command. */ + Type_ToolMkDir, + /** Guest error is from a the built-in toolbox "vbox_mktemp" command. */ + Type_ToolMkTemp, + /** Guest error is from a the built-in toolbox "vbox_stat" command. */ + Type_ToolStat, + /** The usual 32-bit hack. */ + Type_32BIT_HACK = 0x7fffffff + }; + + /** + * Initialization constructor. + * + * @param eType Error type to use. + * @param rc IPRT-style rc to use. + * @param pcszWhat Subject to use. + */ + GuestErrorInfo(GuestErrorInfo::Type eType, int rc, const char *pcszWhat) + { + int rc2 = setV(eType, rc, pcszWhat); + if (RT_FAILURE(rc2)) + throw rc2; + } + + /** + * Returns the (IPRT-style) rc of this error. + * + * @returns VBox status code. + */ + int getRc(void) const { return mRc; } + + /** + * Returns the type of this error. + * + * @returns Error type. + */ + Type getType(void) const { return mType; } + + /** + * Returns the subject of this error. + * + * @returns Subject as a string. + */ + Utf8Str getWhat(void) const { return mWhat; } + + /** + * Sets the error information using a variable arguments list (va_list). + * + * @returns VBox status code. + * @param eType Error type to use. + * @param rc IPRT-style rc to use. + * @param pcszWhat Subject to use. + */ + int setV(GuestErrorInfo::Type eType, int rc, const char *pcszWhat) + { + mType = eType; + mRc = rc; + mWhat = pcszWhat; + + return VINF_SUCCESS; + } + +protected: + + /** Error type. */ + Type mType; + /** IPRT-style error code. */ + int mRc; + /** Subject string related to this error. */ + Utf8Str mWhat; +}; + +/** + * Structure for keeping all the relevant guest directory + * information around. + */ +struct GuestDirectoryOpenInfo +{ + GuestDirectoryOpenInfo(void) + : mFlags(0) { } + + /** The directory path. */ + Utf8Str mPath; + /** Then open filter. */ + Utf8Str mFilter; + /** Opening flags. */ + uint32_t mFlags; +}; + + +/** + * Structure for keeping all the relevant guest file + * information around. + */ +struct GuestFileOpenInfo +{ + GuestFileOpenInfo(void) + : mAccessMode((FileAccessMode_T)0) + , mOpenAction((FileOpenAction_T)0) + , mSharingMode((FileSharingMode_T)0) + , mCreationMode(0) + , mfOpenEx(0) { } + + /** + * Validates a file open info. + * + * @returns \c true if valid, \c false if not. + */ + bool IsValid(void) const + { + if (mfOpenEx) /** @todo Open flags not implemented yet. */ + return false; + + switch (mOpenAction) + { + case FileOpenAction_OpenExisting: + break; + case FileOpenAction_OpenOrCreate: + break; + case FileOpenAction_CreateNew: + break; + case FileOpenAction_CreateOrReplace: + break; + case FileOpenAction_OpenExistingTruncated: + { + if ( mAccessMode == FileAccessMode_ReadOnly + || mAccessMode == FileAccessMode_AppendOnly + || mAccessMode == FileAccessMode_AppendRead) + return false; + break; + } + case FileOpenAction_AppendOrCreate: /* Deprecated, do not use. */ + break; + default: + AssertFailedReturn(false); + break; + } + + return true; /** @todo Do we need more checks here? */ + } + + /** The filename. */ + Utf8Str mFilename; + /** The file access mode. */ + FileAccessMode_T mAccessMode; + /** The file open action. */ + FileOpenAction_T mOpenAction; + /** The file sharing mode. */ + FileSharingMode_T mSharingMode; + /** Octal creation mode. */ + uint32_t mCreationMode; + /** Extended open flags (currently none defined). */ + uint32_t mfOpenEx; +}; + + +/** + * Structure representing information of a + * file system object. + */ +struct GuestFsObjData +{ + GuestFsObjData(void) + : mType(FsObjType_Unknown) + , mObjectSize(0) + , mAllocatedSize(0) + , mAccessTime(0) + , mBirthTime(0) + , mChangeTime(0) + , mModificationTime(0) + , mUID(0) + , mGID(0) + , mNodeID(0) + , mNodeIDDevice(0) + , mNumHardLinks(0) + , mDeviceNumber(0) + , mGenerationID(0) + , mUserFlags(0) { } + + /** @name Helper functions to extract the data from a certin VBoxService tool's guest stream block. + * @{ */ + int FromLs(const GuestProcessStreamBlock &strmBlk, bool fLong); + int FromRm(const GuestProcessStreamBlock &strmBlk); + int FromStat(const GuestProcessStreamBlock &strmBlk); + int FromMkTemp(const GuestProcessStreamBlock &strmBlk); + /** @} */ + + /** @name Static helper functions to work with time from stream block keys. + * @{ */ + static PRTTIMESPEC TimeSpecFromKey(const GuestProcessStreamBlock &strmBlk, const Utf8Str &strKey, PRTTIMESPEC pTimeSpec); + static int64_t UnixEpochNsFromKey(const GuestProcessStreamBlock &strmBlk, const Utf8Str &strKey); + /** @} */ + + /** @name helper functions to work with IPRT stuff. + * @{ */ + RTFMODE GetFileMode(void) const; + /** @} */ + + Utf8Str mName; + FsObjType_T mType; + Utf8Str mFileAttrs; + int64_t mObjectSize; + int64_t mAllocatedSize; + int64_t mAccessTime; + int64_t mBirthTime; + int64_t mChangeTime; + int64_t mModificationTime; + Utf8Str mUserName; + int32_t mUID; + int32_t mGID; + Utf8Str mGroupName; + Utf8Str mACL; + int64_t mNodeID; + uint32_t mNodeIDDevice; + uint32_t mNumHardLinks; + uint32_t mDeviceNumber; + uint32_t mGenerationID; + uint32_t mUserFlags; +}; + + +/** + * Structure for keeping all the relevant guest session + * startup parameters around. + */ +class GuestSessionStartupInfo +{ +public: + + GuestSessionStartupInfo(void) + : mID(UINT32_MAX) + , mIsInternal(false /* Non-internal session */) + , mOpenTimeoutMS(30 * 1000 /* 30s opening timeout */) + , mOpenFlags(0 /* No opening flags set */) { } + + /** The session's friendly name. Optional. */ + Utf8Str mName; + /** The session's unique ID. Used to encode a context ID. + * UINT32_MAX if not initialized. */ + uint32_t mID; + /** Flag indicating if this is an internal session + * or not. Internal session are not accessible by + * public API clients. */ + bool mIsInternal; + /** Timeout (in ms) used for opening the session. */ + uint32_t mOpenTimeoutMS; + /** Session opening flags. */ + uint32_t mOpenFlags; +}; + + +/** + * Structure for keeping all the relevant guest process + * startup parameters around. + */ +class GuestProcessStartupInfo +{ +public: + + GuestProcessStartupInfo(void) + : mFlags(ProcessCreateFlag_None) + , mTimeoutMS(UINT32_MAX /* No timeout by default */) + , mPriority(ProcessPriority_Default) + , mAffinity(0) { } + + /** The process' friendly name. */ + Utf8Str mName; + /** The executable. */ + Utf8Str mExecutable; + /** Arguments vector (starting with argument \#0). */ + ProcessArguments mArguments; + /** The process environment change record. */ + GuestEnvironmentChanges mEnvironmentChanges; + /** Process creation flags. */ + uint32_t mFlags; + /** Timeout (in ms) the process is allowed to run. + * Specify UINT32_MAX if no timeout (unlimited run time) is given. */ + ULONG mTimeoutMS; + /** Process priority. */ + ProcessPriority_T mPriority; + /** Process affinity. At the moment we + * only support 64 VCPUs. API and + * guest can do more already! */ + uint64_t mAffinity; +}; + + +/** + * Class representing the "value" side of a "key=value" pair. + */ +class GuestProcessStreamValue +{ +public: + + GuestProcessStreamValue(void) { } + GuestProcessStreamValue(const char *pszValue) + : mValue(pszValue) {} + + GuestProcessStreamValue(const GuestProcessStreamValue& aThat) + : mValue(aThat.mValue) { } + + /** Copy assignment operator. */ + GuestProcessStreamValue &operator=(GuestProcessStreamValue const &a_rThat) RT_NOEXCEPT + { + mValue = a_rThat.mValue; + + return *this; + } + + Utf8Str mValue; +}; + +/** Map containing "key=value" pairs of a guest process stream. */ +typedef std::pair< Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPair; +typedef std::map < Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPairMap; +typedef std::map < Utf8Str, GuestProcessStreamValue >::iterator GuestCtrlStreamPairMapIter; +typedef std::map < Utf8Str, GuestProcessStreamValue >::const_iterator GuestCtrlStreamPairMapIterConst; + +/** + * Class representing a block of stream pairs (key=value). Each block in a raw guest + * output stream is separated by "\0\0", each pair is separated by "\0". The overall + * end of a guest stream is marked by "\0\0\0\0". + */ +class GuestProcessStreamBlock +{ +public: + + GuestProcessStreamBlock(void); + + virtual ~GuestProcessStreamBlock(void); + +public: + + void Clear(void); + +#ifdef DEBUG + void DumpToLog(void) const; +#endif + + const char *GetString(const char *pszKey) const; + size_t GetCount(void) const; + int GetRc(void) const; + int GetInt64Ex(const char *pszKey, int64_t *piVal) const; + int64_t GetInt64(const char *pszKey) const; + int GetUInt32Ex(const char *pszKey, uint32_t *puVal) const; + uint32_t GetUInt32(const char *pszKey, uint32_t uDefault = 0) const; + int32_t GetInt32(const char *pszKey, int32_t iDefault = 0) const; + + bool IsEmpty(void) { return mPairs.empty(); } + + int SetValue(const char *pszKey, const char *pszValue); + +protected: + + GuestCtrlStreamPairMap mPairs; +}; + +/** Vector containing multiple allocated stream pair objects. */ +typedef std::vector< GuestProcessStreamBlock > GuestCtrlStreamObjects; +typedef std::vector< GuestProcessStreamBlock >::iterator GuestCtrlStreamObjectsIter; +typedef std::vector< GuestProcessStreamBlock >::const_iterator GuestCtrlStreamObjectsIterConst; + +/** + * Class for parsing machine-readable guest process output by VBoxService' + * toolbox commands ("vbox_ls", "vbox_stat" etc), aka "guest stream". + */ +class GuestProcessStream +{ + +public: + + GuestProcessStream(); + + virtual ~GuestProcessStream(); + +public: + + int AddData(const BYTE *pbData, size_t cbData); + + void Destroy(); + +#ifdef DEBUG + void Dump(const char *pszFile); +#endif + + size_t GetOffset() { return m_offBuffer; } + + size_t GetSize() { return m_cbUsed; } + + int ParseBlock(GuestProcessStreamBlock &streamBlock); + +protected: + + /** Maximum allowed size the stream buffer can grow to. + * Defaults to 32 MB. */ + size_t m_cbMax; + /** Currently allocated size of internal stream buffer. */ + size_t m_cbAllocated; + /** Currently used size at m_offBuffer. */ + size_t m_cbUsed; + /** Current byte offset within the internal stream buffer. */ + size_t m_offBuffer; + /** Internal stream buffer. */ + BYTE *m_pbBuffer; +}; + +class Guest; +class Progress; + +class GuestWaitEventPayload +{ + +public: + + GuestWaitEventPayload(void) + : uType(0), + cbData(0), + pvData(NULL) { } + + /** + * Initialization constructor. Will throw() VBox status code (rc). + * + * @param uTypePayload Payload type to set. + * @param pvPayload Pointer to payload data to set (deep copy). + * @param cbPayload Size (in bytes) of payload data to set. + */ + GuestWaitEventPayload(uint32_t uTypePayload, + const void *pvPayload, uint32_t cbPayload) + : uType(0), + cbData(0), + pvData(NULL) + { + int rc = copyFrom(uTypePayload, pvPayload, cbPayload); + if (RT_FAILURE(rc)) + throw rc; + } + + virtual ~GuestWaitEventPayload(void) + { + Clear(); + } + + GuestWaitEventPayload& operator=(const GuestWaitEventPayload &that) + { + CopyFromDeep(that); + return *this; + } + +public: + + void Clear(void) + { + if (pvData) + { + Assert(cbData); + RTMemFree(pvData); + cbData = 0; + pvData = NULL; + } + uType = 0; + } + + int CopyFromDeep(const GuestWaitEventPayload &payload) + { + return copyFrom(payload.uType, payload.pvData, payload.cbData); + } + + const void* Raw(void) const { return pvData; } + + size_t Size(void) const { return cbData; } + + uint32_t Type(void) const { return uType; } + + void* MutableRaw(void) { return pvData; } + + Utf8Str ToString(void) + { + const char *pszStr = (const char *)pvData; + size_t cbStr = cbData; + + if (RT_FAILURE(RTStrValidateEncodingEx(pszStr, cbStr, + RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED | RTSTR_VALIDATE_ENCODING_EXACT_LENGTH))) + { + AssertFailed(); + return ""; + } + + return Utf8Str(pszStr, cbStr); + } + +protected: + + int copyFrom(uint32_t uTypePayload, const void *pvPayload, uint32_t cbPayload) + { + if (cbPayload > _64K) /* Paranoia. */ + return VERR_TOO_MUCH_DATA; + + Clear(); + + int rc = VINF_SUCCESS; + + if (cbPayload) + { + pvData = RTMemAlloc(cbPayload); + if (pvData) + { + uType = uTypePayload; + + memcpy(pvData, pvPayload, cbPayload); + cbData = cbPayload; + } + else + rc = VERR_NO_MEMORY; + } + else + { + uType = uTypePayload; + + pvData = NULL; + cbData = 0; + } + + return rc; + } + +protected: + + /** Type of payload. */ + uint32_t uType; + /** Size (in bytes) of payload. */ + uint32_t cbData; + /** Pointer to actual payload data. */ + void *pvData; +}; + +class GuestWaitEventBase +{ + +protected: + + GuestWaitEventBase(void); + virtual ~GuestWaitEventBase(void); + +public: + + uint32_t ContextID(void) { return mCID; }; + int GuestResult(void) { return mGuestRc; } + int Result(void) { return mRc; } + GuestWaitEventPayload & Payload(void) { return mPayload; } + int SignalInternal(int rc, int guestRc, const GuestWaitEventPayload *pPayload); + int Wait(RTMSINTERVAL uTimeoutMS); + +protected: + + int Init(uint32_t uCID); + +protected: + + /* Shutdown indicator. */ + bool mfAborted; + /* Associated context ID (CID). */ + uint32_t mCID; + /** The event semaphore for triggering + * the actual event. */ + RTSEMEVENT mEventSem; + /** The event's overall result. If + * set to VERR_GSTCTL_GUEST_ERROR, + * mGuestRc will contain the actual + * error code from the guest side. */ + int mRc; + /** The event'S overall result from the + * guest side. If used, mRc must be + * set to VERR_GSTCTL_GUEST_ERROR. */ + int mGuestRc; + /** The event's payload data. Optional. */ + GuestWaitEventPayload mPayload; +}; + +/** List of public guest event types. */ +typedef std::list < VBoxEventType_T > GuestEventTypes; + +class GuestWaitEvent : public GuestWaitEventBase +{ + +public: + + GuestWaitEvent(void); + virtual ~GuestWaitEvent(void); + +public: + + int Init(uint32_t uCID); + int Init(uint32_t uCID, const GuestEventTypes &lstEvents); + int Cancel(void); + const ComPtr<IEvent> Event(void) { return mEvent; } + bool HasGuestError(void) const { return mRc == VERR_GSTCTL_GUEST_ERROR; } + int GetGuestError(void) const { return mGuestRc; } + int SignalExternal(IEvent *pEvent); + const GuestEventTypes &Types(void) { return mEventTypes; } + size_t TypeCount(void) { return mEventTypes.size(); } + +protected: + + /** List of public event types this event should + * be signalled on. Optional. */ + GuestEventTypes mEventTypes; + /** Pointer to the actual public event, if any. */ + ComPtr<IEvent> mEvent; +}; +/** Map of pointers to guest events. The primary key + * contains the context ID. */ +typedef std::map < uint32_t, GuestWaitEvent* > GuestWaitEvents; +/** Map of wait events per public guest event. Nice for + * faster lookups when signalling a whole event group. */ +typedef std::map < VBoxEventType_T, GuestWaitEvents > GuestEventGroup; + +class GuestBase +{ + +public: + + GuestBase(void); + virtual ~GuestBase(void); + +public: + + /** Signals a wait event using a public guest event; also used for + * for external event listeners. */ + int signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent); + /** Signals a wait event using a guest rc. */ + int signalWaitEventInternal(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int guestRc, const GuestWaitEventPayload *pPayload); + /** Signals a wait event without letting public guest events know, + * extended director's cut version. */ + int signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int rc, int guestRc, const GuestWaitEventPayload *pPayload); + +public: + + int baseInit(void); + void baseUninit(void); + int cancelWaitEvents(void); + int dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); + int generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID); + int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, GuestWaitEvent **ppEvent); + int registerWaitEventEx(uint32_t uSessionID, uint32_t uObjectID, const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent); + int unregisterWaitEvent(GuestWaitEvent *pEvent); + int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent); + +public: + + static FsObjType_T fileModeToFsObjType(RTFMODE fMode); + static const char *fsObjTypeToStr(FsObjType_T enmType); + static const char *pathStyleToStr(PathStyle_T enmPathStyle); + static Utf8Str getErrorAsString(const Utf8Str &strAction, const GuestErrorInfo& guestErrorInfo); + static Utf8Str getErrorAsString(const GuestErrorInfo &guestErrorInfo); + +protected: + + /** Pointer to the console object. Needed + * for HGCM (VMMDev) communication. */ + Console *mConsole; + /** The next context ID counter component for this object. */ + uint32_t mNextContextID; + /** Local listener for handling the waiting events + * internally. */ + ComPtr<IEventListener> mLocalListener; + /** Critical section for wait events access. */ + RTCRITSECT mWaitEventCritSect; + /** Map of registered wait events per event group. */ + GuestEventGroup mWaitEventGroups; + /** Map of registered wait events. */ + GuestWaitEvents mWaitEvents; +}; + +/** + * Virtual class (interface) for guest objects (processes, files, ...) -- + * contains all per-object callback management. + */ +class GuestObject : public GuestBase +{ + friend class GuestSession; + +public: + + GuestObject(void); + virtual ~GuestObject(void); + +public: + + ULONG getObjectID(void) { return mObjectID; } + +protected: + + /** + * Called by IGuestSession when the session status has been changed. + * + * @returns VBox status code. + * @param enmSessionStatus New session status. + */ + virtual int i_onSessionStatusChange(GuestSessionStatus_T enmSessionStatus) = 0; + + /** + * Called by IGuestSession right before this object gets + * unregistered (removed) from the public object list. + */ + virtual int i_onUnregister(void) = 0; + + /** Callback dispatcher -- must be implemented by the actual object. */ + virtual int i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) = 0; + +protected: + + int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID); + int registerWaitEvent(const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent); + int sendMessage(uint32_t uFunction, uint32_t cParms, PVBOXHGCMSVCPARM paParms); + +protected: + + /** @name Common parameters for all derived objects. They have their own + * mData structure to keep their specific data around. + * @{ */ + /** Pointer to parent session. Per definition + * this objects *always* lives shorter than the + * parent. + * @todo r=bird: When wanting to use mSession in the + * IGuestProcess::getEnvironment() implementation I wanted to access + * GuestSession::mData::mpBaseEnvironment. Seeing the comment in + * GuestProcess::terminate() saying: + * "Now only API clients still can hold references to it." + * and recalling seeing similar things in VirtualBox.xidl or some such place, + * I'm wondering how this "per definition" behavior is enforced. Is there any + * GuestProcess:uninit() call or similar magic that invalidates objects that + * GuestSession loses track of in place like GuestProcess::terminate() that I've + * failed to spot? + * + * Please enlighten me. + */ + GuestSession *mSession; + /** The object ID -- must be unique for each guest + * object and is encoded into the context ID. Must + * be set manually when initializing the object. + * + * For guest processes this is the internal PID, + * for guest files this is the internal file ID. */ + uint32_t mObjectID; + /** @} */ +}; + +/** Returns the path separator based on \a a_enmPathStyle as a C-string. */ +#define PATH_STYLE_SEP_STR(a_enmPathStyle) a_enmPathStyle == PathStyle_DOS ? "\\" : "/" +#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) +# define PATH_STYLE_NATIVE PathStyle_DOS +#else +# define PATH_STYLE_NATIVE PathStyle_UNIX +#endif + +/** + * Class for handling guest / host path functions. + */ +class GuestPath +{ +private: + + /** + * Default constructor. + * + * Not directly instantiable (yet). + */ + GuestPath(void) { } + +public: + + /** @name Static helper functions. + * @{ */ + static int BuildDestinationPath(const Utf8Str &strSrcPath, PathStyle_T enmSrcPathStyle, Utf8Str &strDstPath, PathStyle_T enmDstPathStyle); + static int Translate(Utf8Str &strPath, PathStyle_T enmSrcPathStyle, PathStyle_T enmDstPathStyle, bool fForce = false); + /** @} */ +}; +#endif /* !MAIN_INCLUDED_GuestCtrlImplPrivate_h */ + diff --git a/src/VBox/Main/include/GuestDebugControlImpl.h b/src/VBox/Main/include/GuestDebugControlImpl.h new file mode 100644 index 00000000..23f684c4 --- /dev/null +++ b/src/VBox/Main/include/GuestDebugControlImpl.h @@ -0,0 +1,82 @@ +/* $Id: GuestDebugControlImpl.h $ */ +/** @file + * + * VirtualBox/GuestDebugControl COM class implementation + */ + +/* + * Copyright (C) 2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestDebugControlImpl_h +#define MAIN_INCLUDED_GuestDebugControlImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "GuestDebugControlWrap.h" + +namespace settings +{ + struct Debugging; +} + +class ATL_NO_VTABLE GuestDebugControl : + public GuestDebugControlWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(GuestDebugControl) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent); + HRESULT init(Machine *aParent, GuestDebugControl *aThat); + HRESULT initCopy(Machine *aParent, GuestDebugControl *aThat); + void uninit(); + + // public internal methods + HRESULT i_loadSettings(const settings::Debugging &data); + HRESULT i_saveSettings(settings::Debugging &data); + void i_rollback(); + void i_commit(); + void i_copyFrom(GuestDebugControl *aThat); + Machine *i_getMachine() const; + +private: + + // wrapped IGuestDebugControl properties + HRESULT getDebugProvider(GuestDebugProvider_T *aDebugProvider); + HRESULT setDebugProvider(GuestDebugProvider_T aDebugProvider); + HRESULT getDebugIoProvider(GuestDebugIoProvider_T *aDebugIoProvider); + HRESULT setDebugIoProvider(GuestDebugIoProvider_T aDebugIoProvider); + HRESULT getDebugAddress(com::Utf8Str &aAddress); + HRESULT setDebugAddress(const com::Utf8Str &aAddress); + HRESULT getDebugPort(ULONG *aPort); + HRESULT setDebugPort(ULONG aPort); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_GuestDebugControlImpl_h */ diff --git a/src/VBox/Main/include/GuestDirectoryImpl.h b/src/VBox/Main/include/GuestDirectoryImpl.h new file mode 100644 index 00000000..c2d6db7f --- /dev/null +++ b/src/VBox/Main/include/GuestDirectoryImpl.h @@ -0,0 +1,108 @@ +/* $Id: GuestDirectoryImpl.h $ */ +/** @file + * VirtualBox Main - Guest directory handling implementation. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestDirectoryImpl_h +#define MAIN_INCLUDED_GuestDirectoryImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "GuestDirectoryWrap.h" +#include "GuestFsObjInfoImpl.h" +#include "GuestProcessImpl.h" + +class GuestSession; + +/** + * TODO + */ +class ATL_NO_VTABLE GuestDirectory : + public GuestDirectoryWrap, + public GuestObject +{ +public: + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(GuestDirectory) + + int init(Console *pConsole, GuestSession *pSession, ULONG aObjectID, const GuestDirectoryOpenInfo &openInfo); + void uninit(void); + + HRESULT FinalConstruct(void); + void FinalRelease(void); + /** @} */ + +public: + /** @name Implemented virtual methods from GuestObject. + * @{ */ + int i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); + int i_onUnregister(void); + int i_onSessionStatusChange(GuestSessionStatus_T enmSessionStatus); + /** @} */ + +public: + /** @name Public internal methods. + * @{ */ + int i_closeInternal(int *pGuestRc); + int i_read(ComObjPtr<GuestFsObjInfo> &fsObjInfo, int *pGuestRc); + int i_readInternal(GuestFsObjData &objData, int *prcGuest); + /** @} */ + +public: + /** @name Public static internal methods. + * @{ */ + static Utf8Str i_guestErrorToString(int rcGuest, const char *pcszWhat); + /** @} */ + +private: + + /** Wrapped @name IGuestDirectory properties + * @{ */ + HRESULT getDirectoryName(com::Utf8Str &aDirectoryName); + HRESULT getFilter(com::Utf8Str &aFilter); + /** @} */ + + /** Wrapped @name IGuestDirectory methods. + * @{ */ + HRESULT close(); + HRESULT read(ComPtr<IFsObjInfo> &aObjInfo); + /** @} */ + + struct Data + { + /** The directory's open info. */ + GuestDirectoryOpenInfo mOpenInfo; + /** The process tool instance to use. */ + GuestProcessTool mProcessTool; + /** Object data cache. + * Its mName attribute acts as a beacon if the cache is valid or not. */ + GuestFsObjData mObjData; + } mData; +}; + +#endif /* !MAIN_INCLUDED_GuestDirectoryImpl_h */ + diff --git a/src/VBox/Main/include/GuestDnDPrivate.h b/src/VBox/Main/include/GuestDnDPrivate.h new file mode 100644 index 00000000..0be48cea --- /dev/null +++ b/src/VBox/Main/include/GuestDnDPrivate.h @@ -0,0 +1,1108 @@ +/* $Id: GuestDnDPrivate.h $ */ +/** @file + * Private guest drag and drop code, used by GuestDnDTarget + + * GuestDnDSource. + */ + +/* + * Copyright (C) 2011-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestDnDPrivate_h +#define MAIN_INCLUDED_GuestDnDPrivate_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/dir.h> +#include <iprt/file.h> +#include <iprt/path.h> + +#include <VBox/hgcmsvc.h> /* For PVBOXHGCMSVCPARM. */ +#include <VBox/GuestHost/DragAndDrop.h> +#include <VBox/GuestHost/DragAndDropDefs.h> +#include <VBox/HostServices/DragAndDropSvc.h> + +/** + * Forward prototype declarations. + */ +class Guest; +class GuestDnDBase; +class GuestDnDState; +class GuestDnDSource; +class GuestDnDTarget; +class Progress; + +/** + * Type definitions. + */ + +/** List (vector) of MIME types. */ +typedef std::vector<com::Utf8Str> GuestDnDMIMEList; + +/** + * Class to handle a guest DnD callback event. + */ +class GuestDnDCallbackEvent +{ +public: + + GuestDnDCallbackEvent(void) + : m_SemEvent(NIL_RTSEMEVENT) + , m_Rc(VINF_SUCCESS) { } + + virtual ~GuestDnDCallbackEvent(void); + +public: + + int Reset(void); + + int Notify(int rc = VINF_SUCCESS); + + int Result(void) const { return m_Rc; } + + int Wait(RTMSINTERVAL msTimeout); + +protected: + + /** Event semaphore to notify on error/completion. */ + RTSEMEVENT m_SemEvent; + /** Callback result. */ + int m_Rc; +}; + +/** + * Struct for handling the (raw) meta data. + */ +struct GuestDnDMetaData +{ + GuestDnDMetaData(void) + : pvData(NULL) + , cbData(0) + , cbAllocated(0) + , cbAnnounced(0) { } + + virtual ~GuestDnDMetaData(void) + { + reset(); + } + + /** + * Adds new meta data. + * + * @returns New (total) meta data size in bytes. + * @param pvDataAdd Pointer of data to add. + * @param cbDataAdd Size (in bytes) of data to add. + */ + size_t add(const void *pvDataAdd, size_t cbDataAdd) + { + LogFlowThisFunc(("cbAllocated=%zu, cbAnnounced=%zu, pvDataAdd=%p, cbDataAdd=%zu\n", + cbAllocated, cbAnnounced, pvDataAdd, cbDataAdd)); + if (!cbDataAdd) + return 0; + AssertPtrReturn(pvDataAdd, 0); + + const size_t cbAllocatedTmp = cbData + cbDataAdd; + if (cbAllocatedTmp > cbAllocated) + { + int rc = resize(cbAllocatedTmp); + if (RT_FAILURE(rc)) + return 0; + } + + Assert(cbAllocated >= cbData + cbDataAdd); + memcpy((uint8_t *)pvData + cbData, pvDataAdd, cbDataAdd); + + cbData += cbDataAdd; + cbAnnounced = cbData; + + return cbData; + } + + /** + * Adds new meta data. + * + * @returns New (total) meta data size in bytes. + * @param vecAdd Meta data to add. + */ + size_t add(const std::vector<BYTE> &vecAdd) + { + if (!vecAdd.size()) + return 0; + + if (vecAdd.size() > UINT32_MAX) /* Paranoia. */ + return 0; + + return add(&vecAdd.front(), (uint32_t)vecAdd.size()); + } + + /** + * Resets (clears) all data. + */ + void reset(void) + { + strFmt = ""; + + if (pvData) + { + Assert(cbAllocated); + RTMemFree(pvData); + pvData = NULL; + } + + cbData = 0; + cbAllocated = 0; + cbAnnounced = 0; + } + + /** + * Resizes the allocation size. + * + * @returns VBox status code. + * @param cbSize New allocation size (in bytes). + */ + int resize(size_t cbSize) + { + if (!cbSize) + { + reset(); + return VINF_SUCCESS; + } + + if (cbSize == cbAllocated) + return VINF_SUCCESS; + + cbSize = RT_ALIGN_Z(cbSize, PAGE_SIZE); + + if (cbSize > _32M) /* Meta data can be up to 32MB. */ + return VERR_BUFFER_OVERFLOW; + + void *pvTmp = NULL; + if (!cbAllocated) + { + Assert(cbData == 0); + pvTmp = RTMemAllocZ(cbSize); + } + else + { + AssertPtr(pvData); + pvTmp = RTMemRealloc(pvData, cbSize); + } + + if (pvTmp) + { + pvData = pvTmp; + cbAllocated = cbSize; + return VINF_SUCCESS; + } + + return VERR_NO_MEMORY; + } + + /** Format string of this meta data. */ + com::Utf8Str strFmt; + /** Pointer to allocated meta data. */ + void *pvData; + /** Used bytes of meta data. Must not exceed cbAllocated. */ + size_t cbData; + /** Size (in bytes) of allocated meta data. */ + size_t cbAllocated; + /** Size (in bytes) of announced meta data. */ + size_t cbAnnounced; +}; + +/** + * Struct for accounting shared DnD data to be sent/received. + */ +struct GuestDnDData +{ + GuestDnDData(void) + : cbExtra(0) + , cbProcessed(0) { } + + virtual ~GuestDnDData(void) + { + reset(); + } + + /** + * Adds processed data to the internal accounting. + * + * @returns New processed data size. + * @param cbDataAdd Bytes to add as done processing. + */ + size_t addProcessed(size_t cbDataAdd) + { + const size_t cbTotal = getTotalAnnounced(); RT_NOREF(cbTotal); + AssertReturn(cbProcessed + cbDataAdd <= cbTotal, 0); + cbProcessed += cbDataAdd; + return cbProcessed; + } + + /** + * Returns whether all data has been processed or not. + * + * @returns \c true if all data has been processed, \c false if not. + */ + bool isComplete(void) const + { + const size_t cbTotal = getTotalAnnounced(); + LogFlowFunc(("cbProcessed=%zu, cbTotal=%zu\n", cbProcessed, cbTotal)); + AssertReturn(cbProcessed <= cbTotal, true); + return (cbProcessed == cbTotal); + } + + /** + * Returns the percentage (0-100) of the already processed data. + * + * @returns Percentage (0-100) of the already processed data. + */ + uint8_t getPercentComplete(void) const + { + const size_t cbTotal = getTotalAnnounced(); + return (uint8_t)(cbProcessed * 100 / RT_MAX(cbTotal, 1)); + } + + /** + * Returns the remaining (outstanding) data left for processing. + * + * @returns Remaining (outstanding) data (in bytes) left for processing. + */ + size_t getRemaining(void) const + { + const size_t cbTotal = getTotalAnnounced(); + AssertReturn(cbProcessed <= cbTotal, 0); + return cbTotal - cbProcessed; + } + + /** + * Returns the total data size (in bytes) announced. + * + * @returns Total data size (in bytes) announced. + */ + size_t getTotalAnnounced(void) const + { + return Meta.cbAnnounced + cbExtra; + } + + /** + * Returns the total data size (in bytes) available. + * For receiving data, this represents the already received data. + * For sending data, this represents the data left to send. + * + * @returns Total data size (in bytes) available. + */ + size_t getTotalAvailable(void) const + { + return Meta.cbData + cbExtra; + } + + /** + * Resets all data. + */ + void reset(void) + { + Meta.reset(); + + cbExtra = 0; + cbProcessed = 0; + } + + /** For storing the actual meta data. + * This might be an URI list or just plain raw data, + * according to the format being sent. */ + GuestDnDMetaData Meta; + /** Extra data to send/receive (in bytes). Can be 0 for raw data. + * For (file) transfers this is the total size for all files. */ + size_t cbExtra; + /** Overall size (in bytes) of processed data. */ + size_t cbProcessed; +}; + +/** Initial object context state / no state set. */ +#define DND_OBJ_STATE_NONE 0 +/** The header was received / sent. */ +#define DND_OBJ_STATE_HAS_HDR RT_BIT(0) +/** Validation mask for object context state. */ +#define DND_OBJ_STATE_VALID_MASK UINT32_C(0x00000001) + +/** + * Base class for keeping around DnD (file) transfer data. + * Used for sending / receiving transfer data. + */ +struct GuestDnDTransferData +{ + +public: + + GuestDnDTransferData(void) + : cObjToProcess(0) + , cObjProcessed(0) + , pvScratchBuf(NULL) + , cbScratchBuf(0) { } + + virtual ~GuestDnDTransferData(void) + { + destroy(); + } + + /** + * Initializes a transfer data object. + * + * @param cbBuf Scratch buffer size (in bytes) to use. + * If not specified, DND_DEFAULT_CHUNK_SIZE will be used. + */ + int init(size_t cbBuf = DND_DEFAULT_CHUNK_SIZE) + { + reset(); + + pvScratchBuf = RTMemAlloc(cbBuf); + if (!pvScratchBuf) + return VERR_NO_MEMORY; + + cbScratchBuf = cbBuf; + return VINF_SUCCESS; + } + + /** + * Destroys a transfer data object. + */ + void destroy(void) + { + reset(); + + if (pvScratchBuf) + { + Assert(cbScratchBuf); + RTMemFree(pvScratchBuf); + pvScratchBuf = NULL; + } + cbScratchBuf = 0; + } + + /** + * Resets a transfer data object. + */ + void reset(void) + { + LogFlowFuncEnter(); + + cObjToProcess = 0; + cObjProcessed = 0; + } + + /** + * Returns whether this transfer object is complete or not. + * + * @returns \c true if complete, \c false if not. + */ + bool isComplete(void) const + { + return (cObjProcessed == cObjToProcess); + } + + /** Number of objects to process. */ + uint64_t cObjToProcess; + /** Number of objects already processed. */ + uint64_t cObjProcessed; + /** Pointer to an optional scratch buffer to use for + * doing the actual chunk transfers. */ + void *pvScratchBuf; + /** Size (in bytes) of scratch buffer. */ + size_t cbScratchBuf; +}; + +/** + * Class for keeping around DnD transfer send data (Host -> Guest). + */ +struct GuestDnDTransferSendData : public GuestDnDTransferData +{ + GuestDnDTransferSendData() + : fObjState(0) + { + RT_ZERO(List); + int rc2 = DnDTransferListInit(&List); + AssertRC(rc2); + } + + virtual ~GuestDnDTransferSendData() + { + destroy(); + } + + /** + * Destroys the object. + */ + void destroy(void) + { + DnDTransferListDestroy(&List); + } + + /** + * Resets the object. + */ + void reset(void) + { + DnDTransferListReset(&List); + fObjState = 0; + + GuestDnDTransferData::reset(); + } + + /** Transfer List to handle. */ + DNDTRANSFERLIST List; + /** Current state of object in transfer. + * This is needed for keeping compatibility to old(er) DnD HGCM protocols. + * + * At the moment we only support transferring one object at a time. */ + uint32_t fObjState; +}; + +/** + * Context structure for sending data to the guest. + */ +struct GuestDnDSendCtx : public GuestDnDData +{ + GuestDnDSendCtx(void); + + /** + * Resets the object. + */ + void reset(void); + + /** Pointer to guest target class this context belongs to. */ + GuestDnDTarget *pTarget; + /** Pointer to guest state this context belongs to. */ + GuestDnDState *pState; + /** Target (VM) screen ID. */ + uint32_t uScreenID; + /** Transfer data structure. */ + GuestDnDTransferSendData Transfer; + /** Callback event to use. */ + GuestDnDCallbackEvent EventCallback; +}; + +struct GuestDnDTransferRecvData : public GuestDnDTransferData +{ + GuestDnDTransferRecvData() + { + RT_ZERO(DroppedFiles); + int rc2 = DnDDroppedFilesInit(&DroppedFiles); + AssertRC(rc2); + + RT_ZERO(List); + rc2 = DnDTransferListInit(&List); + AssertRC(rc2); + + RT_ZERO(ObjCur); + rc2 = DnDTransferObjectInit(&ObjCur); + AssertRC(rc2); + } + + virtual ~GuestDnDTransferRecvData() + { + destroy(); + } + + /** + * Destroys the object. + */ + void destroy(void) + { + DnDTransferListDestroy(&List); + } + + /** + * Resets the object. + */ + void reset(void) + { + DnDDroppedFilesClose(&DroppedFiles); + DnDTransferListReset(&List); + DnDTransferObjectReset(&ObjCur); + + GuestDnDTransferData::reset(); + } + + /** The "VirtualBox Dropped Files" directory on the host we're going + * to utilize for transferring files from guest to the host. */ + DNDDROPPEDFILES DroppedFiles; + /** Transfer List to handle. + * Currently we only support one transfer list at a time. */ + DNDTRANSFERLIST List; + /** Current transfer object being handled. + * Currently we only support one transfer object at a time. */ + DNDTRANSFEROBJECT ObjCur; +}; + +/** + * Context structure for receiving data from the guest. + */ +struct GuestDnDRecvCtx : public GuestDnDData +{ + GuestDnDRecvCtx(void); + + /** + * Resets the object. + */ + void reset(void); + + /** Pointer to guest source class this context belongs to. */ + GuestDnDSource *pSource; + /** Pointer to guest state this context belongs to. */ + GuestDnDState *pState; + /** Formats offered by the guest (and supported by the host). */ + GuestDnDMIMEList lstFmtOffered; + /** Original drop format requested to receive from the guest. */ + com::Utf8Str strFmtReq; + /** Intermediate drop format to be received from the guest. + * Some original drop formats require a different intermediate + * drop format: + * + * Receiving a file link as "text/plain" requires still to + * receive the file from the guest as "text/uri-list" first, + * then pointing to the file path on the host with the data + * in "text/plain" format returned. */ + com::Utf8Str strFmtRecv; + /** Desired drop action to perform on the host. + * Needed to tell the guest if data has to be + * deleted e.g. when moving instead of copying. */ + VBOXDNDACTION enmAction; + /** Transfer data structure. */ + GuestDnDTransferRecvData Transfer; + /** Callback event to use. */ + GuestDnDCallbackEvent EventCallback; +}; + +/** + * Class for maintainig a (buffered) guest DnD message. + */ +class GuestDnDMsg +{ +public: + + GuestDnDMsg(void) + : uMsg(0) + , cParms(0) + , cParmsAlloc(0) + , paParms(NULL) { } + + virtual ~GuestDnDMsg(void) + { + reset(); + } + +public: + + /** + * Appends a new HGCM parameter to the message and returns the pointer to it. + */ + PVBOXHGCMSVCPARM getNextParam(void) + { + if (cParms >= cParmsAlloc) + { + if (!paParms) + paParms = (PVBOXHGCMSVCPARM)RTMemAlloc(4 * sizeof(VBOXHGCMSVCPARM)); + else + paParms = (PVBOXHGCMSVCPARM)RTMemRealloc(paParms, (cParmsAlloc + 4) * sizeof(VBOXHGCMSVCPARM)); + if (!paParms) + throw VERR_NO_MEMORY; + RT_BZERO(&paParms[cParmsAlloc], 4 * sizeof(VBOXHGCMSVCPARM)); + cParmsAlloc += 4; + } + + return &paParms[cParms++]; + } + + /** + * Returns the current parameter count. + * + * @returns Current parameter count. + */ + uint32_t getCount(void) const { return cParms; } + + /** + * Returns the pointer to the beginning of the HGCM parameters array. Use with care. + * + * @returns Pointer to the beginning of the HGCM parameters array. + */ + PVBOXHGCMSVCPARM getParms(void) const { return paParms; } + + /** + * Returns the message type. + * + * @returns Message type. + */ + uint32_t getType(void) const { return uMsg; } + + /** + * Resets the object. + */ + void reset(void) + { + if (paParms) + { + /* Remove deep copies. */ + for (uint32_t i = 0; i < cParms; i++) + { + if ( paParms[i].type == VBOX_HGCM_SVC_PARM_PTR + && paParms[i].u.pointer.size) + { + AssertPtr(paParms[i].u.pointer.addr); + RTMemFree(paParms[i].u.pointer.addr); + } + } + + RTMemFree(paParms); + paParms = NULL; + } + + uMsg = cParms = cParmsAlloc = 0; + } + + /** + * Appends a new message parameter of type pointer. + * + * @returns VBox status code. + * @param pvBuf Pointer to data to use. + * @param cbBuf Size (in bytes) of data to use. + */ + int appendPointer(void *pvBuf, uint32_t cbBuf) + { + PVBOXHGCMSVCPARM pParm = getNextParam(); + if (!pParm) + return VERR_NO_MEMORY; + + void *pvTmp = NULL; + if (cbBuf) + { + AssertPtr(pvBuf); + pvTmp = RTMemDup(pvBuf, cbBuf); + if (!pvTmp) + return VERR_NO_MEMORY; + } + + HGCMSvcSetPv(pParm, pvTmp, cbBuf); + return VINF_SUCCESS; + } + + /** + * Appends a new message parameter of type string. + * + * @returns VBox status code. + * @param pszString Pointer to string data to use. + */ + int appendString(const char *pszString) + { + PVBOXHGCMSVCPARM pParm = getNextParam(); + if (!pParm) + return VERR_NO_MEMORY; + + char *pszTemp = RTStrDup(pszString); + if (!pszTemp) + return VERR_NO_MEMORY; + + HGCMSvcSetStr(pParm, pszTemp); + return VINF_SUCCESS; + } + + /** + * Appends a new message parameter of type uint32_t. + * + * @returns VBox status code. + * @param u32Val uint32_t value to use. + */ + int appendUInt32(uint32_t u32Val) + { + PVBOXHGCMSVCPARM pParm = getNextParam(); + if (!pParm) + return VERR_NO_MEMORY; + + HGCMSvcSetU32(pParm, u32Val); + return VINF_SUCCESS; + } + + /** + * Appends a new message parameter of type uint64_t. + * + * @returns VBox status code. + * @param u64Val uint64_t value to use. + */ + int appendUInt64(uint64_t u64Val) + { + PVBOXHGCMSVCPARM pParm = getNextParam(); + if (!pParm) + return VERR_NO_MEMORY; + + HGCMSvcSetU64(pParm, u64Val); + return VINF_SUCCESS; + } + + /** + * Sets the HGCM message type (function number). + * + * @param uMsgType Message type to set. + */ + void setType(uint32_t uMsgType) { uMsg = uMsgType; } + +protected: + + /** Message type. */ + uint32_t uMsg; + /** Message parameters. */ + uint32_t cParms; + /** Size of array. */ + uint32_t cParmsAlloc; + /** Array of HGCM parameters */ + PVBOXHGCMSVCPARM paParms; +}; + +/** Guest DnD callback function definition. */ +typedef DECLCALLBACKPTR(int, PFNGUESTDNDCALLBACK,(uint32_t uMsg, void *pvParms, size_t cbParms, void *pvUser)); + +/** + * Structure for keeping a guest DnD callback. + * Each callback can handle one HGCM message, however, multiple HGCM messages can be registered + * to the same callback (function). + */ +typedef struct GuestDnDCallback +{ + GuestDnDCallback(void) + : uMessgage(0) + , pfnCallback(NULL) + , pvUser(NULL) { } + + GuestDnDCallback(PFNGUESTDNDCALLBACK pvCB, uint32_t uMsg, void *pvUsr = NULL) + : uMessgage(uMsg) + , pfnCallback(pvCB) + , pvUser(pvUsr) { } + + /** The HGCM message ID to handle. */ + uint32_t uMessgage; + /** Pointer to callback function. */ + PFNGUESTDNDCALLBACK pfnCallback; + /** Pointer to user-supplied data. */ + void *pvUser; +} GuestDnDCallback; + +/** Contains registered callback pointers for specific HGCM message types. */ +typedef std::map<uint32_t, GuestDnDCallback> GuestDnDCallbackMap; + +/** + * Class for keeping a DnD guest state around. + */ +class GuestDnDState +{ + +public: + DECLARE_TRANSLATE_METHODS(GuestDnDState) + + GuestDnDState(const ComObjPtr<Guest>& pGuest); + virtual ~GuestDnDState(void); + +public: + + VBOXDNDSTATE get(void) const { return m_enmState; } + int set(VBOXDNDSTATE enmState) { LogRel3(("DnD: State %s -> %s\n", DnDStateToStr(m_enmState), DnDStateToStr(enmState))); m_enmState = enmState; return 0; } + void lock() { RTCritSectEnter(&m_CritSect); }; + void unlock() { RTCritSectLeave(&m_CritSect); }; + + /** @name Guest response handling. + * @{ */ + int notifyAboutGuestResponse(int rcGuest = VINF_SUCCESS); + int waitForGuestResponseEx(RTMSINTERVAL msTimeout = 3000, int *prcGuest = NULL); + int waitForGuestResponse(int *prcGuest = NULL); + /** @} */ + + void setActionsAllowed(VBOXDNDACTIONLIST a) { m_dndLstActionsAllowed = a; } + VBOXDNDACTIONLIST getActionsAllowed(void) const { return m_dndLstActionsAllowed; } + + void setActionDefault(VBOXDNDACTION a) { m_dndActionDefault = a; } + VBOXDNDACTION getActionDefault(void) const { return m_dndActionDefault; } + + void setFormats(const GuestDnDMIMEList &lstFormats) { m_lstFormats = lstFormats; } + GuestDnDMIMEList formats(void) const { return m_lstFormats; } + + void reset(void); + + /** @name Callback handling. + * @{ */ + static DECLCALLBACK(int) i_defaultCallback(uint32_t uMsg, void *pvParms, size_t cbParms, void *pvUser); + int setCallback(uint32_t uMsg, PFNGUESTDNDCALLBACK pfnCallback, void *pvUser = NULL); + /** @} */ + + /** @name Progress handling. + * @{ */ + bool isProgressCanceled(void) const; + bool isProgressRunning(void) const; + int setProgress(unsigned uPercentage, uint32_t uState, int rcOp = VINF_SUCCESS, const Utf8Str &strMsg = ""); + HRESULT resetProgress(const ComObjPtr<Guest>& pParent, const Utf8Str &strDesc); + HRESULT queryProgressTo(IProgress **ppProgress); + /** @} */ + +public: + + /** @name HGCM callback handling. + @{ */ + int onDispatch(uint32_t u32Function, void *pvParms, uint32_t cbParms); + /** @} */ + +public: + + /** Pointer to context this class is tied to. */ + void *m_pvCtx; + RTCRITSECT m_CritSect; + /** The current state we're in. */ + VBOXDNDSTATE m_enmState; + /** The DnD protocol version to use, depending on the + * installed Guest Additions. See DragAndDropSvc.h for + * a protocol changelog. */ + uint32_t m_uProtocolVersion; + /** The guest feature flags reported to the host (VBOX_DND_GF_XXX). */ + uint64_t m_fGuestFeatures0; + /** Event for waiting for response. */ + RTSEMEVENT m_EventSem; + /** Last error reported from guest. + * Set to VERR_IPE_UNINITIALIZED_STATUS if not set yet. */ + int m_rcGuest; + /** Default action to perform in case of a + * successful drop. */ + VBOXDNDACTION m_dndActionDefault; + /** Actions supported by the guest in case of a successful drop. */ + VBOXDNDACTIONLIST m_dndLstActionsAllowed; + /** Format(s) requested/supported from the guest. */ + GuestDnDMIMEList m_lstFormats; + /** Pointer to IGuest parent object. */ + ComObjPtr<Guest> m_pParent; + /** Pointer to associated progress object. Optional. */ + ComObjPtr<Progress> m_pProgress; + /** Callback map. */ + GuestDnDCallbackMap m_mapCallbacks; +}; + +/** + * Private singleton class for the guest's DnD implementation. + * + * Can't be instanciated directly, only via the factory pattern. + * Keeps track of all ongoing DnD transfers. + */ +class GuestDnD +{ +public: + + /** + * Creates the Singleton GuestDnD object. + * + * @returns Newly created Singleton object, or NULL on failure. + */ + static GuestDnD *createInstance(const ComObjPtr<Guest>& pGuest) + { + Assert(NULL == GuestDnD::s_pInstance); + GuestDnD::s_pInstance = new GuestDnD(pGuest); + return GuestDnD::s_pInstance; + } + + /** + * Destroys the Singleton GuestDnD object. + */ + static void destroyInstance(void) + { + if (GuestDnD::s_pInstance) + { + delete GuestDnD::s_pInstance; + GuestDnD::s_pInstance = NULL; + } + } + + /** + * Returns the Singleton GuestDnD object. + * + * @returns Pointer to Singleton GuestDnD object, or NULL if not created yet. + */ + static inline GuestDnD *getInstance(void) + { + AssertPtr(GuestDnD::s_pInstance); + return GuestDnD::s_pInstance; + } + +protected: + + /** List of registered DnD sources. */ + typedef std::list< ComObjPtr<GuestDnDSource> > GuestDnDSrcList; + /** List of registered DnD targets. */ + typedef std::list< ComObjPtr<GuestDnDTarget> > GuestDnDTgtList; + + /** Constructor; will throw rc on failure. */ + GuestDnD(const ComObjPtr<Guest>& pGuest); + virtual ~GuestDnD(void); + +public: + + /** @name Public helper functions. + * @{ */ + HRESULT adjustScreenCoordinates(ULONG uScreenId, ULONG *puX, ULONG *puY) const; + GuestDnDState *getState(uint32_t = 0) const; + int hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const; + GuestDnDMIMEList defaultFormats(void) const { return m_strDefaultFormats; } + /** @} */ + + /** @name Source / target management. + * @{ */ + int registerSource(const ComObjPtr<GuestDnDSource> &Source); + int unregisterSource(const ComObjPtr<GuestDnDSource> &Source); + size_t getSourceCount(void); + + int registerTarget(const ComObjPtr<GuestDnDTarget> &Target); + int unregisterTarget(const ComObjPtr<GuestDnDTarget> &Target); + size_t getTargetCount(void); + /** @} */ + +public: + + /** @name Static low-level HGCM callback handler. + * @{ */ + static DECLCALLBACK(int) notifyDnDDispatcher(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms); + /** @} */ + + /** @name Static helper methods. + * @{ */ + static bool isFormatInFormatList(const com::Utf8Str &strFormat, const GuestDnDMIMEList &lstFormats); + static GuestDnDMIMEList toFormatList(const com::Utf8Str &strFormats, const com::Utf8Str &strSep = DND_FORMATS_SEPARATOR_STR); + static com::Utf8Str toFormatString(const GuestDnDMIMEList &lstFormats, const com::Utf8Str &strSep = DND_FORMATS_SEPARATOR_STR); + static GuestDnDMIMEList toFilteredFormatList(const GuestDnDMIMEList &lstFormatsSupported, const GuestDnDMIMEList &lstFormatsWanted); + static GuestDnDMIMEList toFilteredFormatList(const GuestDnDMIMEList &lstFormatsSupported, const com::Utf8Str &strFormatsWanted); + static DnDAction_T toMainAction(VBOXDNDACTION dndAction); + static std::vector<DnDAction_T> toMainActions(VBOXDNDACTIONLIST dndActionList); + static VBOXDNDACTION toHGCMAction(DnDAction_T enmAction); + static void toHGCMActions(DnDAction_T enmDefAction, VBOXDNDACTION *pDefAction, const std::vector<DnDAction_T> vecAllowedActions, VBOXDNDACTIONLIST *pLstAllowedActions); + /** @} */ + +protected: + + /** @name Singleton properties. + * @{ */ + /** List of supported default MIME/Content-type formats. */ + GuestDnDMIMEList m_strDefaultFormats; + /** Pointer to guest implementation. */ + const ComObjPtr<Guest> m_pGuest; + /** The current state from the guest. At the + * moment we only support only state a time (ARQ-style). */ + GuestDnDState *m_pState; + /** Critical section to serialize access. */ + RTCRITSECT m_CritSect; + /** Number of active transfers (guest->host or host->guest). */ + uint32_t m_cTransfersPending; + GuestDnDSrcList m_lstSrc; + GuestDnDTgtList m_lstTgt; + /** @} */ + +private: + + /** Static pointer to singleton instance. */ + static GuestDnD *s_pInstance; +}; + +/** Access to the GuestDnD's singleton instance. */ +#define GuestDnDInst() GuestDnD::getInstance() + +/** List of pointers to guest DnD Messages. */ +typedef std::list<GuestDnDMsg *> GuestDnDMsgList; + +/** + * IDnDBase class implementation for sharing code between + * IGuestDnDSource and IGuestDnDTarget implementation. + */ +class GuestDnDBase +{ +protected: + + GuestDnDBase(VirtualBoxBase *pBase); + + virtual ~GuestDnDBase(void); + +protected: + + /** Shared (internal) IDnDBase method implementations. + * @{ */ + bool i_isFormatSupported(const com::Utf8Str &aFormat) const; + const GuestDnDMIMEList &i_getFormats(void) const; + HRESULT i_addFormats(const GuestDnDMIMEList &aFormats); + HRESULT i_removeFormats(const GuestDnDMIMEList &aFormats); + /** @} */ + + /** @name Error handling. + * @{ */ + HRESULT i_setErrorV(int vrc, const char *pcszMsgFmt, va_list va); + HRESULT i_setError(int vrc, const char *pcszMsgFmt, ...); + HRESULT i_setErrorAndReset(const char *pcszMsgFmt, ...); + HRESULT i_setErrorAndReset(int vrc, const char *pcszMsgFmt, ...); + /** @} */ + +protected: + + /** @name Pure virtual functions needed to be implemented by the actual (derived) implementation. + * @{ */ + virtual void i_reset(void) = 0; + /** @} */ + +protected: + + /** @name Functions for handling a simple host HGCM message queue. + * @{ */ + int msgQueueAdd(GuestDnDMsg *pMsg); + GuestDnDMsg *msgQueueGetNext(void); + void msgQueueRemoveNext(void); + void msgQueueClear(void); + /** @} */ + + int sendCancel(void); + int updateProgress(GuestDnDData *pData, GuestDnDState *pState, size_t cbDataAdd = 0); + int waitForEvent(GuestDnDCallbackEvent *pEvent, GuestDnDState *pState, RTMSINTERVAL msTimeout); + +protected: + + /** Pointer to base class to use for stuff like error handlng. */ + VirtualBoxBase *m_pBase; + /** @name Public attributes (through getters/setters). + * @{ */ + /** Pointer to guest implementation. */ + const ComObjPtr<Guest> m_pGuest; + /** List of supported MIME types by the source. */ + GuestDnDMIMEList m_lstFmtSupported; + /** List of offered MIME types to the counterpart. */ + GuestDnDMIMEList m_lstFmtOffered; + /** Whether the object still is in pending state. */ + bool m_fIsPending; + /** Pointer to state bound to this object. */ + GuestDnDState *m_pState; + /** @} */ + + /** + * Internal stuff. + */ + struct + { + /** Outgoing message queue (FIFO). */ + GuestDnDMsgList lstMsgOut; + } m_DataBase; +}; +#endif /* !MAIN_INCLUDED_GuestDnDPrivate_h */ + diff --git a/src/VBox/Main/include/GuestDnDSourceImpl.h b/src/VBox/Main/include/GuestDnDSourceImpl.h new file mode 100644 index 00000000..c26881bb --- /dev/null +++ b/src/VBox/Main/include/GuestDnDSourceImpl.h @@ -0,0 +1,131 @@ +/* $Id: GuestDnDSourceImpl.h $ */ +/** @file + * VBox Console COM Class implementation - Guest drag'n drop source. + */ + +/* + * Copyright (C) 2014-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestDnDSourceImpl_h +#define MAIN_INCLUDED_GuestDnDSourceImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/GuestHost/DragAndDrop.h> +#include <VBox/HostServices/DragAndDropSvc.h> + +using namespace DragAndDropSvc; + +#include "GuestDnDSourceWrap.h" +#include "GuestDnDPrivate.h" + +class GuestDnDRecvDataTask; +struct GuestDnDRecvCtx; + +class ATL_NO_VTABLE GuestDnDSource : + public GuestDnDSourceWrap, + public GuestDnDBase +{ +public: + GuestDnDSource(void); + virtual ~GuestDnDSource(void); + + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_TRANSLATE_METHODS(GuestDnDSource); + + HRESULT init(const ComObjPtr<Guest>& pGuest); + void uninit(void); + + HRESULT FinalConstruct(void); + void FinalRelease(void); + /** @} */ + +private: + + /** Private wrapped @name IDnDBase methods. + * @{ */ + HRESULT isFormatSupported(const com::Utf8Str &aFormat, BOOL *aSupported); + HRESULT getFormats(GuestDnDMIMEList &aFormats); + HRESULT addFormats(const GuestDnDMIMEList &aFormats); + HRESULT removeFormats(const GuestDnDMIMEList &aFormats); + /** @} */ + + /** Private wrapped @name IDnDSource methods. + * @{ */ + HRESULT dragIsPending(ULONG uScreenId, GuestDnDMIMEList &aFormats, std::vector<DnDAction_T> &aAllowedActions, DnDAction_T *aDefaultAction); + HRESULT drop(const com::Utf8Str &aFormat, DnDAction_T aAction, ComPtr<IProgress> &aProgress); + HRESULT receiveData(std::vector<BYTE> &aData); + /** @} */ + +protected: + + /** @name Implemented virtual functions. + * @{ */ + void i_reset(void); + /** @} */ + +#ifdef VBOX_WITH_DRAG_AND_DROP_GH + /** @name Dispatch handlers for the HGCM callbacks. + * @{ */ + int i_onReceiveDataHdr(GuestDnDRecvCtx *pCtx, PVBOXDNDSNDDATAHDR pDataHdr); + int i_onReceiveData(GuestDnDRecvCtx *pCtx, PVBOXDNDSNDDATA pSndData); + int i_onReceiveDir(GuestDnDRecvCtx *pCtx, const char *pszPath, uint32_t cbPath, uint32_t fMode); + int i_onReceiveFileHdr(GuestDnDRecvCtx *pCtx, const char *pszPath, uint32_t cbPath, uint64_t cbSize, uint32_t fMode, uint32_t fFlags); + int i_onReceiveFileData(GuestDnDRecvCtx *pCtx,const void *pvData, uint32_t cbData); + /** @} */ +#endif + +protected: + + static Utf8Str i_guestErrorToString(int guestRc); + static Utf8Str i_hostErrorToString(int hostRc); + + /** @name Callbacks for dispatch handler. + * @{ */ + static DECLCALLBACK(int) i_receiveRawDataCallback(uint32_t uMsg, void *pvParms, size_t cbParms, void *pvUser); + static DECLCALLBACK(int) i_receiveTransferDataCallback(uint32_t uMsg, void *pvParms, size_t cbParms, void *pvUser); + /** @} */ + +protected: + + int i_receiveData(GuestDnDRecvCtx *pCtx, RTMSINTERVAL msTimeout); + int i_receiveRawData(GuestDnDRecvCtx *pCtx, RTMSINTERVAL msTimeout); + int i_receiveTransferData(GuestDnDRecvCtx *pCtx, RTMSINTERVAL msTimeout); + +protected: + + struct + { + /** Maximum data block size (in bytes) the source can handle. */ + uint32_t mcbBlockSize; + /** The context for receiving data from the guest. + * At the moment only one transfer at a time is supported. */ + GuestDnDRecvCtx mRecvCtx; + } mData; + + friend class GuestDnDRecvDataTask; +}; + +#endif /* !MAIN_INCLUDED_GuestDnDSourceImpl_h */ + diff --git a/src/VBox/Main/include/GuestDnDTargetImpl.h b/src/VBox/Main/include/GuestDnDTargetImpl.h new file mode 100644 index 00000000..0011709c --- /dev/null +++ b/src/VBox/Main/include/GuestDnDTargetImpl.h @@ -0,0 +1,128 @@ +/* $Id: GuestDnDTargetImpl.h $ */ +/** @file + * VBox Console COM Class implementation - Guest drag'n drop target. + */ + +/* + * Copyright (C) 2014-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestDnDTargetImpl_h +#define MAIN_INCLUDED_GuestDnDTargetImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "GuestDnDTargetWrap.h" +#include "GuestDnDPrivate.h" + +#include <VBox/GuestHost/DragAndDrop.h> +#include <VBox/HostServices/DragAndDropSvc.h> + +struct GuestDnDSendCtx; +class GuestDnDSendDataTask; + +class ATL_NO_VTABLE GuestDnDTarget : + public GuestDnDTargetWrap, + public GuestDnDBase +{ +public: + GuestDnDTarget(void); + virtual ~GuestDnDTarget(void); + + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_TRANSLATE_METHODS(GuestDnDTarget); + + HRESULT init(const ComObjPtr<Guest>& pGuest); + void uninit(void); + + HRESULT FinalConstruct(void); + void FinalRelease(void); + /** @} */ + +private: + + /** Private wrapped @name IDnDBase methods. + * @{ */ + HRESULT isFormatSupported(const com::Utf8Str &aFormat, BOOL *aSupported); + HRESULT getFormats(GuestDnDMIMEList &aFormats); + HRESULT addFormats(const GuestDnDMIMEList &aFormats); + HRESULT removeFormats(const GuestDnDMIMEList &aFormats); + /** @} */ + + /** Private wrapped @name IDnDTarget methods. + * @{ */ + HRESULT enter(ULONG aScreenId, ULONG ax, ULONG aY, DnDAction_T aDefaultAction, const std::vector<DnDAction_T> &aAllowedActions, const GuestDnDMIMEList &aFormats, DnDAction_T *aResultAction); + HRESULT move(ULONG aScreenId, ULONG aX, ULONG aY, DnDAction_T aDefaultAction, const std::vector<DnDAction_T> &aAllowedActions, const GuestDnDMIMEList &aFormats, DnDAction_T *aResultAction); + HRESULT leave(ULONG aScreenId); + HRESULT drop(ULONG aScreenId, ULONG aX, ULONG aY, DnDAction_T aDefaultAction, const std::vector<DnDAction_T> &aAllowedActions, const GuestDnDMIMEList &aFormats, com::Utf8Str &aFormat, DnDAction_T *aResultAction); + HRESULT sendData(ULONG aScreenId, const com::Utf8Str &aFormat, const std::vector<BYTE> &aData, ComPtr<IProgress> &aProgress); + HRESULT cancel(BOOL *aVeto); + /** @} */ + +protected: + + static Utf8Str i_guestErrorToString(int guestRc); + static Utf8Str i_hostErrorToString(int hostRc); + + /** @name Callbacks for dispatch handler. + * @{ */ + static DECLCALLBACK(int) i_sendTransferDataCallback(uint32_t uMsg, void *pvParms, size_t cbParms, void *pvUser); + /** @} */ + +protected: + + /** @name Implemented virtual functions. + * @{ */ + void i_reset(void); + /** @} */ + + int i_sendData(GuestDnDSendCtx *pCtx, RTMSINTERVAL msTimeout); + + int i_sendMetaDataBody(GuestDnDSendCtx *pCtx); + int i_sendMetaDataHeader(GuestDnDSendCtx *pCtx); + + int i_sendTransferData(GuestDnDSendCtx *pCtx, RTMSINTERVAL msTimeout); + int i_sendTransferListObject(GuestDnDSendCtx *pCtx, PDNDTRANSFERLIST pList, GuestDnDMsg *pMsg); + + int i_sendDirectory(GuestDnDSendCtx *pCtx, PDNDTRANSFEROBJECT pObj, GuestDnDMsg *pMsg); + int i_sendFile(GuestDnDSendCtx *pCtx, PDNDTRANSFEROBJECT pObj, GuestDnDMsg *pMsg); + int i_sendFileData(GuestDnDSendCtx *pCtx, PDNDTRANSFEROBJECT pObj, GuestDnDMsg *pMsg); + + int i_sendRawData(GuestDnDSendCtx *pCtx, RTMSINTERVAL msTimeout); + +protected: + + struct + { + /** Maximum data block size (in bytes) the target can handle. */ + uint32_t mcbBlockSize; + /** The context for sending data to the guest. + * At the moment only one transfer at a time is supported. */ + GuestDnDSendCtx mSendCtx; + } mData; + + friend class GuestDnDSendDataTask; +}; + +#endif /* !MAIN_INCLUDED_GuestDnDTargetImpl_h */ + diff --git a/src/VBox/Main/include/GuestFileImpl.h b/src/VBox/Main/include/GuestFileImpl.h new file mode 100644 index 00000000..e1531019 --- /dev/null +++ b/src/VBox/Main/include/GuestFileImpl.h @@ -0,0 +1,161 @@ +/* $Id: GuestFileImpl.h $ */ +/** @file + * VirtualBox Main - Guest file handling implementation. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestFileImpl_h +#define MAIN_INCLUDED_GuestFileImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxBase.h" +#include "EventImpl.h" + +#include "GuestCtrlImplPrivate.h" +#include "GuestFileWrap.h" + +class Console; +class GuestSession; +class GuestProcess; + +class ATL_NO_VTABLE GuestFile : + public GuestFileWrap, + public GuestObject +{ +public: + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(GuestFile) + + int init(Console *pConsole, GuestSession *pSession, ULONG uFileID, const GuestFileOpenInfo &openInfo); + void uninit(void); + + HRESULT FinalConstruct(void); + void FinalRelease(void); + /** @} */ + +public: + /** @name Implemented virtual methods from GuestObject. + * @{ */ + int i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); + int i_onUnregister(void); + int i_onSessionStatusChange(GuestSessionStatus_T enmSessionStatus); + /** @} */ + +public: + /** @name Public internal methods. + * @{ */ + int i_closeFile(int *pGuestRc); + EventSource *i_getEventSource(void) { return mEventSource; } + int i_onFileNotify(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); + int i_onGuestDisconnected(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); + int i_openFile(uint32_t uTimeoutMS, int *pGuestRc); + int i_queryInfo(GuestFsObjData &objData, int *prcGuest); + int i_readData(uint32_t uSize, uint32_t uTimeoutMS, void* pvData, uint32_t cbData, uint32_t* pcbRead); + int i_readDataAt(uint64_t uOffset, uint32_t uSize, uint32_t uTimeoutMS, + void* pvData, size_t cbData, size_t* pcbRead); + int i_seekAt(int64_t iOffset, GUEST_FILE_SEEKTYPE eSeekType, uint32_t uTimeoutMS, uint64_t *puOffset); + int i_setFileStatus(FileStatus_T fileStatus, int fileRc); + int i_waitForOffsetChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, uint64_t *puOffset); + int i_waitForRead(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead); + int i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, FileStatus_T *pFileStatus, int *pGuestRc); + int i_waitForWrite(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, uint32_t *pcbWritten); + int i_writeData(uint32_t uTimeoutMS, const void *pvData, uint32_t cbData, uint32_t *pcbWritten); + int i_writeDataAt(uint64_t uOffset, uint32_t uTimeoutMS, const void *pvData, uint32_t cbData, uint32_t *pcbWritten); + /** @} */ + + /** @name Static helper methods. + * @{ */ + static Utf8Str i_guestErrorToString(int guestRc, const char *pcszWhat); + /** @} */ + +public: + + /** @name Wrapped IGuestFile properties. + * @{ */ + HRESULT getCreationMode(ULONG *aCreationMode); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + HRESULT getId(ULONG *aId); + HRESULT getInitialSize(LONG64 *aInitialSize); + HRESULT getOffset(LONG64 *aOffset); + HRESULT getStatus(FileStatus_T *aStatus); + HRESULT getFilename(com::Utf8Str &aFilename); + HRESULT getAccessMode(FileAccessMode_T *aAccessMode); + HRESULT getOpenAction(FileOpenAction_T *aOpenAction); + /** @} */ + + /** @name Wrapped IGuestFile methods. + * @{ */ + HRESULT close(); + HRESULT queryInfo(ComPtr<IFsObjInfo> &aObjInfo); + HRESULT querySize(LONG64 *aSize); + HRESULT read(ULONG aToRead, + ULONG aTimeoutMS, + std::vector<BYTE> &aData); + HRESULT readAt(LONG64 aOffset, + ULONG aToRead, + ULONG aTimeoutMS, + std::vector<BYTE> &aData); + HRESULT seek(LONG64 aOffset, + FileSeekOrigin_T aWhence, + LONG64 *aNewOffset); + HRESULT setACL(const com::Utf8Str &aAcl, + ULONG aMode); + HRESULT setSize(LONG64 aSize); + HRESULT write(const std::vector<BYTE> &aData, + ULONG aTimeoutMS, + ULONG *aWritten); + HRESULT writeAt(LONG64 aOffset, + const std::vector<BYTE> &aData, + ULONG aTimeoutMS, + ULONG *aWritten); + /** @} */ + +private: + + /** This can safely be used without holding any locks. + * An AutoCaller suffices to prevent it being destroy while in use and + * internally there is a lock providing the necessary serialization. */ + const ComObjPtr<EventSource> mEventSource; + + struct Data + { + /** The file's open info. */ + GuestFileOpenInfo mOpenInfo; + /** The file's initial size on open. */ + uint64_t mInitialSize; + /** The current file status. */ + FileStatus_T mStatus; + /** The last returned process status + * returned from the guest side. */ + int mLastError; + /** The file's current offset. */ + uint64_t mOffCurrent; + } mData; +}; + +#endif /* !MAIN_INCLUDED_GuestFileImpl_h */ + diff --git a/src/VBox/Main/include/GuestFsObjInfoImpl.h b/src/VBox/Main/include/GuestFsObjInfoImpl.h new file mode 100644 index 00000000..b4955f40 --- /dev/null +++ b/src/VBox/Main/include/GuestFsObjInfoImpl.h @@ -0,0 +1,86 @@ +/* $Id: GuestFsObjInfoImpl.h $ */ +/** @file + * VirtualBox Main - Guest file system object information implementation. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestFsObjInfoImpl_h +#define MAIN_INCLUDED_GuestFsObjInfoImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "GuestFsObjInfoWrap.h" +#include "GuestCtrlImplPrivate.h" + +class ATL_NO_VTABLE GuestFsObjInfo + : public GuestFsObjInfoWrap +{ +public: + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(GuestFsObjInfo) + + int init(const GuestFsObjData &objData); + void uninit(void); + + HRESULT FinalConstruct(void); + void FinalRelease(void); + /** @} */ + + /** @name Internal access helpers. + * @{ */ + const GuestFsObjData &i_getData() const { return mData; } + /** @} */ + +private: + + /** Wrapped @name IGuestFsObjInfo properties. + * @{ */ + HRESULT getName(com::Utf8Str &aName); + HRESULT getType(FsObjType_T *aType); + HRESULT getFileAttributes(com::Utf8Str &aFileAttributes); + HRESULT getObjectSize(LONG64 *aObjectSize); + HRESULT getAllocatedSize(LONG64 *aAllocatedSize); + HRESULT getAccessTime(LONG64 *aAccessTime); + HRESULT getBirthTime(LONG64 *aBirthTime); + HRESULT getChangeTime(LONG64 *aChangeTime); + HRESULT getModificationTime(LONG64 *aModificationTime); + HRESULT getUID(LONG *aUID); + HRESULT getUserName(com::Utf8Str &aUserName); + HRESULT getGID(LONG *aGID); + HRESULT getGroupName(com::Utf8Str &aGroupName); + HRESULT getNodeId(LONG64 *aNodeId); + HRESULT getNodeIdDevice(ULONG *aNodeIdDevice); + HRESULT getHardLinks(ULONG *aHardLinks); + HRESULT getDeviceNumber(ULONG *aDeviceNumber); + HRESULT getGenerationId(ULONG *aGenerationId); + HRESULT getUserFlags(ULONG *aUserFlags); + /** @} */ + + GuestFsObjData mData; +}; + +#endif /* !MAIN_INCLUDED_GuestFsObjInfoImpl_h */ + diff --git a/src/VBox/Main/include/GuestImpl.h b/src/VBox/Main/include/GuestImpl.h new file mode 100644 index 00000000..a315a430 --- /dev/null +++ b/src/VBox/Main/include/GuestImpl.h @@ -0,0 +1,282 @@ +/* $Id: GuestImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestImpl_h +#define MAIN_INCLUDED_GuestImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "GuestWrap.h" +#include "VirtualBoxBase.h" +#include <iprt/list.h> +#include <iprt/time.h> +#include <VBox/ostypes.h> +#include <VBox/param.h> +#include <VBox/vmm/stam.h> + +#include "AdditionsFacilityImpl.h" +#ifdef VBOX_WITH_GUEST_CONTROL +# include "GuestCtrlImplPrivate.h" +# include "GuestSessionImpl.h" +#endif +#ifdef VBOX_WITH_DRAG_AND_DROP +# include "GuestDnDSourceImpl.h" +# include "GuestDnDTargetImpl.h" +#endif +#include "EventImpl.h" +#include "HGCM.h" + +typedef enum +{ + GUESTSTATTYPE_CPUUSER = 0, + GUESTSTATTYPE_CPUKERNEL = 1, + GUESTSTATTYPE_CPUIDLE = 2, + GUESTSTATTYPE_MEMTOTAL = 3, + GUESTSTATTYPE_MEMFREE = 4, + GUESTSTATTYPE_MEMBALLOON = 5, + GUESTSTATTYPE_MEMCACHE = 6, + GUESTSTATTYPE_PAGETOTAL = 7, + GUESTSTATTYPE_PAGEFREE = 8, + GUESTSTATTYPE_MAX = 9 +} GUESTSTATTYPE; + +class Console; + +class ATL_NO_VTABLE Guest : + public GuestWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS (Guest) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // Public initializer/uninitializer for internal purposes only. + HRESULT init(Console *aParent); + void uninit(); + + +public: + /** @name Static internal methods. + * @{ */ +#ifdef VBOX_WITH_GUEST_CONTROL + /** Static callback for handling guest control notifications. */ + static DECLCALLBACK(int) i_notifyCtrlDispatcher(void *pvExtension, uint32_t u32Function, void *pvData, uint32_t cbData); +#endif + static DECLCALLBACK(void) i_staticUpdateStats(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick); + /** @} */ + +public: + /** @name Public internal methods. + * @{ */ + void i_enableVMMStatistics(BOOL aEnable) { mCollectVMMStats = aEnable; }; + void i_setAdditionsInfo(const com::Utf8Str &aInterfaceVersion, VBOXOSTYPE aOsType); + void i_setAdditionsInfo2(uint32_t a_uFullVersion, const char *a_pszName, uint32_t a_uRevision, uint32_t a_fFeatures); + bool i_facilityIsActive(VBoxGuestFacilityType enmFacility); + bool i_facilityUpdate(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus, + uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS); + ComObjPtr<Console> i_getConsole(void) { return mParent; } + void i_setAdditionsStatus(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus, + uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS); + void i_onUserStateChanged(const Utf8Str &aUser, const Utf8Str &aDomain, VBoxGuestUserState enmState, + const uint8_t *puDetails, uint32_t cbDetails); + void i_setSupportedFeatures(uint32_t aCaps); + HRESULT i_setStatistic(ULONG aCpuId, GUESTSTATTYPE enmType, ULONG aVal); + BOOL i_isPageFusionEnabled(); + void i_setCpuCount(uint32_t aCpus) { mCpus = aCpus; } + static HRESULT i_setErrorStatic(HRESULT aResultCode, const char *aText, ...) + { + va_list va; + va_start(va, aText); + HRESULT hrc = setErrorInternalV(aResultCode, getStaticClassIID(), getStaticComponentName(), aText, va, false, true); + va_end(va); + return hrc; + } + uint32_t i_getAdditionsRevision(void) { return mData.mAdditionsRevision; } + uint32_t i_getAdditionsVersion(void) { return mData.mAdditionsVersionFull; } + VBOXOSTYPE i_getGuestOSType(void) const { return mData.mOSType; } + /** Checks if the guest OS type is part of the windows NT family. */ + bool i_isGuestInWindowsNtFamily(void) const + { + return mData.mOSType < VBOXOSTYPE_OS2 && mData.mOSType >= VBOXOSTYPE_WinNT; + } +#ifdef VBOX_WITH_GUEST_CONTROL + int i_dispatchToSession(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); + int i_sessionCreate(const GuestSessionStartupInfo &ssInfo, const GuestCredentials &guestCreds, + ComObjPtr<GuestSession> &pGuestSession); + int i_sessionDestroy(uint32_t uSessionID); + inline bool i_sessionExists(uint32_t uSessionID); + /** Returns the VBOX_GUESTCTRL_GF_0_XXX mask reported by the guest. */ + uint64_t i_getGuestControlFeatures0() const { return mData.mfGuestFeatures0; } + /** Returns the VBOX_GUESTCTRL_GF_1_XXX mask reported by the guest. */ + uint64_t i_getGuestControlFeatures1() const { return mData.mfGuestFeatures1; } +#endif + /** @} */ + +private: + + // wrapped IGuest properties + HRESULT getOSTypeId(com::Utf8Str &aOSTypeId); + HRESULT getAdditionsRunLevel(AdditionsRunLevelType_T *aAdditionsRunLevel); + HRESULT getAdditionsVersion(com::Utf8Str &aAdditionsVersion); + HRESULT getAdditionsRevision(ULONG *aAdditionsRevision); + HRESULT getDnDSource(ComPtr<IGuestDnDSource> &aDnDSource); + HRESULT getDnDTarget(ComPtr<IGuestDnDTarget> &aDnDTarget); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + HRESULT getFacilities(std::vector<ComPtr<IAdditionsFacility> > &aFacilities); + HRESULT getSessions(std::vector<ComPtr<IGuestSession> > &aSessions); + HRESULT getMemoryBalloonSize(ULONG *aMemoryBalloonSize); + HRESULT setMemoryBalloonSize(ULONG aMemoryBalloonSize); + HRESULT getStatisticsUpdateInterval(ULONG *aStatisticsUpdateInterval); + HRESULT setStatisticsUpdateInterval(ULONG aStatisticsUpdateInterval); + HRESULT internalGetStatistics(ULONG *aCpuUser, + ULONG *aCpuKernel, + ULONG *aCpuIdle, + ULONG *aMemTotal, + ULONG *aMemFree, + ULONG *aMemBalloon, + ULONG *aMemShared, + ULONG *aMemCache, + ULONG *aPagedTotal, + ULONG *aMemAllocTotal, + ULONG *aMemFreeTotal, + ULONG *aMemBalloonTotal, + ULONG *aMemSharedTotal); + HRESULT getFacilityStatus(AdditionsFacilityType_T aFacility, + LONG64 *aTimestamp, + AdditionsFacilityStatus_T *aStatus); + HRESULT getAdditionsStatus(AdditionsRunLevelType_T aLevel, + BOOL *aActive); + HRESULT setCredentials(const com::Utf8Str &aUserName, + const com::Utf8Str &aPassword, + const com::Utf8Str &aDomain, + BOOL aAllowInteractiveLogon); + + // wrapped IGuest methods + HRESULT createSession(const com::Utf8Str &aUser, + const com::Utf8Str &aPassword, + const com::Utf8Str &aDomain, + const com::Utf8Str &aSessionName, + ComPtr<IGuestSession> &aGuestSession); + + HRESULT findSession(const com::Utf8Str &aSessionName, + std::vector<ComPtr<IGuestSession> > &aSessions); + HRESULT shutdown(const std::vector<GuestShutdownFlag_T> &aFlags); + HRESULT updateGuestAdditions(const com::Utf8Str &aSource, + const std::vector<com::Utf8Str> &aArguments, + const std::vector<AdditionsUpdateFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + + + /** @name Private internal methods. + * @{ */ + void i_updateStats(uint64_t iTick); + static DECLCALLBACK(int) i_staticEnumStatsCallback(const char *pszName, STAMTYPE enmType, void *pvSample, + STAMUNIT enmUnit, const char *pszUnit, STAMVISIBILITY enmVisiblity, + const char *pszDesc, void *pvUser); + + /** @} */ + + typedef std::map< AdditionsFacilityType_T, ComObjPtr<AdditionsFacility> > FacilityMap; + typedef std::map< AdditionsFacilityType_T, ComObjPtr<AdditionsFacility> >::iterator FacilityMapIter; + typedef std::map< AdditionsFacilityType_T, ComObjPtr<AdditionsFacility> >::const_iterator FacilityMapIterConst; + +#ifdef VBOX_WITH_GUEST_CONTROL + /** Map for keeping the guest sessions. The primary key marks the guest session ID. */ + typedef std::map <uint32_t, ComObjPtr<GuestSession> > GuestSessions; +#endif + + struct Data + { + Data() : mOSType(VBOXOSTYPE_Unknown), mAdditionsRunLevel(AdditionsRunLevelType_None) + , mAdditionsVersionFull(0), mAdditionsRevision(0), mAdditionsFeatures(0) +#ifdef VBOX_WITH_GUEST_CONTROL + , mfGuestFeatures0(0), mfGuestFeatures1(0) +#endif + { } + + VBOXOSTYPE mOSType; /**@< For internal used. VBOXOSTYPE_Unknown if not reported. */ + Utf8Str mOSTypeId; + FacilityMap mFacilityMap; + AdditionsRunLevelType_T mAdditionsRunLevel; + uint32_t mAdditionsVersionFull; + Utf8Str mAdditionsVersionNew; + uint32_t mAdditionsRevision; + uint32_t mAdditionsFeatures; + Utf8Str mInterfaceVersion; +#ifdef VBOX_WITH_GUEST_CONTROL + GuestSessions mGuestSessions; + /** Guest control features (reported by the guest), VBOX_GUESTCTRL_GF_0_XXX. */ + uint64_t mfGuestFeatures0; + /** Guest control features (reported by the guest), VBOX_GUESTCTRL_GF_1_XXX. */ + uint64_t mfGuestFeatures1; +#endif + } mData; + + ULONG mMemoryBalloonSize; + ULONG mStatUpdateInterval; /**< In seconds. */ + uint64_t mNetStatRx; + uint64_t mNetStatTx; + uint64_t mNetStatLastTs; + ULONG mCurrentGuestStat[GUESTSTATTYPE_MAX]; + ULONG mCurrentGuestCpuUserStat[VMM_MAX_CPU_COUNT]; + ULONG mCurrentGuestCpuKernelStat[VMM_MAX_CPU_COUNT]; + ULONG mCurrentGuestCpuIdleStat[VMM_MAX_CPU_COUNT]; + ULONG mVmValidStats; + BOOL mCollectVMMStats; + BOOL mfPageFusionEnabled; + uint32_t mCpus; + + const ComObjPtr<Console> mParent; + + /** + * This can safely be used without holding any locks. + * An AutoCaller suffices to prevent it being destroy while in use and + * internally there is a lock providing the necessary serialization. + */ + const ComObjPtr<EventSource> mEventSource; +#ifdef VBOX_WITH_GUEST_CONTROL + /** General extension callback for guest control. */ + HGCMSVCEXTHANDLE mhExtCtrl; +#endif + +#ifdef VBOX_WITH_DRAG_AND_DROP + /** The guest's DnD source. */ + const ComObjPtr<GuestDnDSource> mDnDSource; + /** The guest's DnD target. */ + const ComObjPtr<GuestDnDTarget> mDnDTarget; +#endif + + RTTIMERLR mStatTimer; + uint32_t mMagic; /** @todo r=andy Rename this to something more meaningful. */ +}; +#define GUEST_MAGIC 0xCEED2006u /** @todo r=andy Not very well defined!? */ + +#endif /* !MAIN_INCLUDED_GuestImpl_h */ + diff --git a/src/VBox/Main/include/GuestOSTypeImpl.h b/src/VBox/Main/include/GuestOSTypeImpl.h new file mode 100644 index 00000000..8e69bc29 --- /dev/null +++ b/src/VBox/Main/include/GuestOSTypeImpl.h @@ -0,0 +1,131 @@ +/* $Id: GuestOSTypeImpl.h $ */ +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestOSTypeImpl_h +#define MAIN_INCLUDED_GuestOSTypeImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "Global.h" +#include "GuestOSTypeWrap.h" + +class ATL_NO_VTABLE GuestOSType : + public GuestOSTypeWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(GuestOSType) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(const Global::OSType &ostype); + void uninit(); + + // public methods only for internal purposes + const Utf8Str &i_id() const { return mID; } + const Utf8Str &i_familyId() const { return mFamilyID; } + bool i_is64Bit() const { return !!(mOSHint & VBOXOSHINT_64BIT); } + bool i_recommendedIOAPIC() const { return !!(mOSHint & VBOXOSHINT_IOAPIC); } + bool i_recommendedX2APIC() const { return !!(mOSHint & VBOXOSHINT_X2APIC); } + bool i_recommendedVirtEx() const { return !!(mOSHint & VBOXOSHINT_HWVIRTEX); } + bool i_recommendedEFI() const { return !!(mOSHint & VBOXOSHINT_EFI); } + bool i_recommendedEFISecureBoot() const { return !!(mOSHint & VBOXOSHINT_EFI_SECUREBOOT); } + bool i_recommendedTpm2() const { return !!(mOSHint & VBOXOSHINT_TPM2); } + NetworkAdapterType_T i_networkAdapterType() const { return mNetworkAdapterType; } + uint32_t i_numSerialEnabled() const { return mNumSerialEnabled; } + +private: + + // Wrapped IGuestOSType properties + HRESULT getFamilyId(com::Utf8Str &aFamilyId); + HRESULT getFamilyDescription(com::Utf8Str &aFamilyDescription); + HRESULT getId(com::Utf8Str &aId); + HRESULT getDescription(com::Utf8Str &aDescription); + HRESULT getIs64Bit(BOOL *aIs64Bit); + HRESULT getRecommendedIOAPIC(BOOL *aRecommendedIOAPIC); + HRESULT getRecommendedVirtEx(BOOL *aRecommendedVirtEx); + HRESULT getRecommendedRAM(ULONG *RAMSize); + HRESULT getRecommendedGraphicsController(GraphicsControllerType_T *aRecommendedGraphicsController); + HRESULT getRecommendedVRAM(ULONG *aVRAMSize); + HRESULT getRecommended2DVideoAcceleration(BOOL *aRecommended2DVideoAcceleration); + HRESULT getRecommended3DAcceleration(BOOL *aRecommended3DAcceleration); + HRESULT getRecommendedHDD(LONG64 *aHDDSize); + HRESULT getAdapterType(NetworkAdapterType_T *aNetworkAdapterType); + HRESULT getRecommendedPAE(BOOL *aRecommendedPAE); + HRESULT getRecommendedDVDStorageController(StorageControllerType_T *aStorageControllerType); + HRESULT getRecommendedFirmware(FirmwareType_T *aFirmwareType); + HRESULT getRecommendedDVDStorageBus(StorageBus_T *aStorageBusType); + HRESULT getRecommendedHDStorageController(StorageControllerType_T *aStorageControllerType); + HRESULT getRecommendedHDStorageBus(StorageBus_T *aStorageBusType); + HRESULT getRecommendedUSBHID(BOOL *aRecommendedUSBHID); + HRESULT getRecommendedHPET(BOOL *aRecommendedHPET); + HRESULT getRecommendedUSBTablet(BOOL *aRecommendedUSBTablet); + HRESULT getRecommendedRTCUseUTC(BOOL *aRecommendedRTCUseUTC); + HRESULT getRecommendedChipset(ChipsetType_T *aChipsetType); + HRESULT getRecommendedIommuType(IommuType_T *aIommuType); + HRESULT getRecommendedAudioController(AudioControllerType_T *aAudioController); + HRESULT getRecommendedAudioCodec(AudioCodecType_T *aAudioCodec); + HRESULT getRecommendedFloppy(BOOL *aRecommendedFloppy); + HRESULT getRecommendedUSB(BOOL *aRecommendedUSB); + HRESULT getRecommendedUSB3(BOOL *aRecommendedUSB3); + HRESULT getRecommendedTFReset(BOOL *aRecommendedTFReset); + HRESULT getRecommendedX2APIC(BOOL *aRecommendedX2APIC); + HRESULT getRecommendedCPUCount(ULONG *aRecommendedCPUCount); + HRESULT getRecommendedTpmType(TpmType_T *aRecommendedTpmType); + HRESULT getRecommendedSecureBoot(BOOL *aRecommendedSecureBoot); + HRESULT getRecommendedWDDMGraphics(BOOL *aRecommendedWDDMGraphics); + + + const Utf8Str mFamilyID; + const Utf8Str mFamilyDescription; + const Utf8Str mID; + const Utf8Str mDescription; + const VBOXOSTYPE mOSType; + const uint32_t mOSHint; + const uint32_t mRAMSize; + const uint32_t mCPUCount; + const GraphicsControllerType_T mGraphicsControllerType; + const uint32_t mVRAMSize; + const uint64_t mHDDSize; + const NetworkAdapterType_T mNetworkAdapterType; + const uint32_t mNumSerialEnabled; + const StorageControllerType_T mDVDStorageControllerType; + const StorageBus_T mDVDStorageBusType; + const StorageControllerType_T mHDStorageControllerType; + const StorageBus_T mHDStorageBusType; + const ChipsetType_T mChipsetType; + const IommuType_T mIommuType; + const AudioControllerType_T mAudioControllerType; + const AudioCodecType_T mAudioCodecType; +}; + +#endif /* !MAIN_INCLUDED_GuestOSTypeImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/GuestProcessImpl.h b/src/VBox/Main/include/GuestProcessImpl.h new file mode 100644 index 00000000..138529d3 --- /dev/null +++ b/src/VBox/Main/include/GuestProcessImpl.h @@ -0,0 +1,310 @@ +/* $Id: GuestProcessImpl.h $ */ +/** @file + * VirtualBox Main - Guest process handling implementation. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestProcessImpl_h +#define MAIN_INCLUDED_GuestProcessImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "GuestCtrlImplPrivate.h" +#include "GuestProcessWrap.h" + +#include <iprt/cpp/utils.h> + +class Console; +class GuestSession; +class GuestProcessStartTask; + +/** + * Class for handling a guest process. + */ +class ATL_NO_VTABLE GuestProcess : + public GuestProcessWrap, + public GuestObject +{ +public: + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(GuestProcess) + + int init(Console *aConsole, GuestSession *aSession, ULONG aObjectID, + const GuestProcessStartupInfo &aProcInfo, const GuestEnvironment *pBaseEnv); + void uninit(void); + HRESULT FinalConstruct(void); + void FinalRelease(void); + /** @} */ + +public: + /** @name Implemented virtual methods from GuestObject. + * @{ */ + int i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); + int i_onUnregister(void); + int i_onSessionStatusChange(GuestSessionStatus_T enmSessionStatus); + /** @} */ + +public: + /** @name Public internal methods. + * @{ */ + inline int i_checkPID(uint32_t uPID); + ProcessStatus_T i_getStatus(void); + int i_readData(uint32_t uHandle, uint32_t uSize, uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead, int *pGuestRc); + int i_startProcess(uint32_t cMsTimeout, int *pGuestRc); + int i_startProcessInner(uint32_t cMsTimeout, AutoWriteLock &rLock, GuestWaitEvent *pEvent, int *pGuestRc); + int i_startProcessAsync(void); + int i_terminateProcess(uint32_t uTimeoutMS, int *pGuestRc); + ProcessWaitResult_T i_waitFlagsToResult(uint32_t fWaitFlags); + int i_waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc); + int i_waitForInputNotify(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS, ProcessInputStatus_T *pInputStatus, uint32_t *pcbProcessed); + int i_waitForOutput(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS, void* pvData, size_t cbData, uint32_t *pcbRead); + int i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, ProcessStatus_T *pProcessStatus, int *pGuestRc); + int i_writeData(uint32_t uHandle, uint32_t uFlags, void *pvData, size_t cbData, uint32_t uTimeoutMS, uint32_t *puWritten, int *pGuestRc); + /** @} */ + + /** @name Static internal methods. + * @{ */ + static Utf8Str i_guestErrorToString(int rcGuest, const char *pcszWhat); + static Utf8Str i_statusToString(ProcessStatus_T enmStatus); + static bool i_isGuestError(int guestRc); + static ProcessWaitResult_T i_waitFlagsToResultEx(uint32_t fWaitFlags, ProcessStatus_T oldStatus, ProcessStatus_T newStatus, uint32_t uProcFlags, uint32_t uProtocol); +#if 0 /* unused */ + static bool i_waitResultImpliesEx(ProcessWaitResult_T waitResult, ProcessStatus_T procStatus, uint32_t uProtocol); +#endif + /** @} */ + +protected: + /** @name Protected internal methods. + * @{ */ + inline bool i_isAlive(void); + inline bool i_hasEnded(void); + int i_onGuestDisconnected(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); + int i_onProcessInputStatus(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); + int i_onProcessNotifyIO(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); + int i_onProcessStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); + int i_onProcessOutput(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); + int i_prepareExecuteEnv(const char *pszEnv, void **ppvList, ULONG *pcbList, ULONG *pcEnvVars); + int i_setProcessStatus(ProcessStatus_T procStatus, int procRc); + static int i_startProcessThreadTask(GuestProcessStartTask *pTask); + /** @} */ + +private: + /** Wrapped @name IProcess properties. + * @{ */ + HRESULT getArguments(std::vector<com::Utf8Str> &aArguments); + HRESULT getEnvironment(std::vector<com::Utf8Str> &aEnvironment); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + HRESULT getExecutablePath(com::Utf8Str &aExecutablePath); + HRESULT getExitCode(LONG *aExitCode); + HRESULT getName(com::Utf8Str &aName); + HRESULT getPID(ULONG *aPID); + HRESULT getStatus(ProcessStatus_T *aStatus); + /** @} */ + + /** Wrapped @name IProcess methods. + * @{ */ + HRESULT waitFor(ULONG aWaitFor, + ULONG aTimeoutMS, + ProcessWaitResult_T *aReason); + HRESULT waitForArray(const std::vector<ProcessWaitForFlag_T> &aWaitFor, + ULONG aTimeoutMS, + ProcessWaitResult_T *aReason); + HRESULT read(ULONG aHandle, + ULONG aToRead, + ULONG aTimeoutMS, + std::vector<BYTE> &aData); + HRESULT write(ULONG aHandle, + ULONG aFlags, + const std::vector<BYTE> &aData, + ULONG aTimeoutMS, + ULONG *aWritten); + HRESULT writeArray(ULONG aHandle, + const std::vector<ProcessInputFlag_T> &aFlags, + const std::vector<BYTE> &aData, + ULONG aTimeoutMS, + ULONG *aWritten); + HRESULT terminate(void); + /** @} */ + + /** + * This can safely be used without holding any locks. + * An AutoCaller suffices to prevent it being destroy while in use and + * internally there is a lock providing the necessary serialization. + */ + const ComObjPtr<EventSource> mEventSource; + + struct Data + { + /** The process startup information. */ + GuestProcessStartupInfo mProcess; + /** Reference to the immutable session base environment. NULL if the + * environment feature isn't supported. + * @remarks If there is proof that the uninit order of GuestSession and + * this class is what GuestObjectBase claims, then this isn't + * strictly necessary. */ + GuestEnvironment const *mpSessionBaseEnv; + /** Exit code if process has been terminated. */ + LONG mExitCode; + /** PID reported from the guest. + * Note: This is *not* the internal object ID! */ + ULONG mPID; + /** The current process status. */ + ProcessStatus_T mStatus; + /** The last returned process status + * returned from the guest side. */ + int mLastError; + + Data(void) : mpSessionBaseEnv(NULL) + { } + ~Data(void) + { + if (mpSessionBaseEnv) + { + mpSessionBaseEnv->releaseConst(); + mpSessionBaseEnv = NULL; + } + } + } mData; + + friend class GuestProcessStartTask; +}; + +/** + * Guest process tool wait flags. + */ +/** No wait flags specified; wait until process terminates. + * The maximum waiting time is set in the process' startup + * info. */ +#define GUESTPROCESSTOOL_WAIT_FLAG_NONE 0 +/** Wait until next stream block from stdout has been + * read in completely, then return. + */ +#define GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK RT_BIT(0) + +/** + * Structure for keeping a VBoxService toolbox tool's error info around. + */ +struct GuestProcessToolErrorInfo +{ + /** Return code from the guest side for executing the process tool. */ + int rcGuest; + /** The process tool's returned exit code. */ + int32_t iExitCode; +}; + +/** + * Internal class for handling the BusyBox-like tools built into VBoxService + * on the guest side. It's also called the VBoxService Toolbox (tm). + * + * Those initially were necessary to guarantee execution of commands (like "ls", "cat") + * under the behalf of a certain guest user. + * + * This class essentially helps to wrap all the gory details like process creation, + * information extraction and maintaining the overall status. + * + * Note! When implementing new functionality / commands, do *not* use this approach anymore! + * This class has to be kept to guarantee backwards-compatibility. + */ +class GuestProcessTool +{ +public: + DECLARE_TRANSLATE_METHODS(GuestProcessTool) + + GuestProcessTool(void); + + virtual ~GuestProcessTool(void); + +public: + + int init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pGuestRc); + + void uninit(void); + + int getCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock); + + int getRc(void) const; + + /** Returns the stdout output from the guest process tool. */ + GuestProcessStream &getStdOut(void) { return mStdOut; } + + /** Returns the stderr output from the guest process tool. */ + GuestProcessStream &getStdErr(void) { return mStdErr; } + + int wait(uint32_t fToolWaitFlags, int *pGuestRc); + + int waitEx(uint32_t fToolWaitFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc); + + bool isRunning(void); + + bool isTerminatedOk(void); + + int getTerminationStatus(int32_t *piExitCode = NULL); + + int terminate(uint32_t uTimeoutMS, int *pGuestRc); + +public: + + /** Wrapped @name Static run methods. + * @{ */ + static int run(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, int *pGuestRc); + + static int runErrorInfo(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, GuestProcessToolErrorInfo &errorInfo); + + static int runEx(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, + GuestCtrlStreamObjects *pStrmOutObjects, uint32_t cStrmOutObjects, int *pGuestRc); + + static int runExErrorInfo(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, + GuestCtrlStreamObjects *pStrmOutObjects, uint32_t cStrmOutObjects, GuestProcessToolErrorInfo &errorInfo); + /** @} */ + + /** Wrapped @name Static exit code conversion methods. + * @{ */ + static int exitCodeToRc(const GuestProcessStartupInfo &startupInfo, int32_t iExitCode); + + static int exitCodeToRc(const char *pszTool, int32_t iExitCode); + /** @} */ + + /** Wrapped @name Static guest error conversion methods. + * @{ */ + static Utf8Str guestErrorToString(const char *pszTool, const GuestErrorInfo& guestErrorInfo); + /** @} */ + +protected: + + /** Pointer to session this toolbox object is bound to. */ + ComObjPtr<GuestSession> pSession; + /** Pointer to process object this toolbox object is bound to. */ + ComObjPtr<GuestProcess> pProcess; + /** The toolbox' startup info. */ + GuestProcessStartupInfo mStartupInfo; + /** Stream object for handling the toolbox' stdout data. */ + GuestProcessStream mStdOut; + /** Stream object for handling the toolbox' stderr data. */ + GuestProcessStream mStdErr; +}; + +#endif /* !MAIN_INCLUDED_GuestProcessImpl_h */ + diff --git a/src/VBox/Main/include/GuestSessionImpl.h b/src/VBox/Main/include/GuestSessionImpl.h new file mode 100644 index 00000000..8630b32a --- /dev/null +++ b/src/VBox/Main/include/GuestSessionImpl.h @@ -0,0 +1,461 @@ +/* $Id: GuestSessionImpl.h $ */ +/** @file + * VirtualBox Main - Guest session handling. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestSessionImpl_h +#define MAIN_INCLUDED_GuestSessionImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "GuestSessionWrap.h" +#include "EventImpl.h" + +#include "GuestCtrlImplPrivate.h" +#include "GuestProcessImpl.h" +#include "GuestDirectoryImpl.h" +#include "GuestFileImpl.h" +#include "GuestFsObjInfoImpl.h" +#include "GuestSessionImplTasks.h" + +#include <iprt/asm.h> /** @todo r=bird: Needed for ASMBitSet() in GuestSession::Data constructor. Removed when + * that is moved into the class implementation file as it should be. */ +#include <deque> + +class GuestSessionTaskInternalStart; /* Needed for i_startSessionThreadTask(). */ + +/** + * Guest session implementation. + */ +class ATL_NO_VTABLE GuestSession + : public GuestSessionWrap + , public GuestBase +{ +public: + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(GuestSession) + + int init(Guest *pGuest, const GuestSessionStartupInfo &ssInfo, const GuestCredentials &guestCreds); + void uninit(void); + HRESULT FinalConstruct(void); + void FinalRelease(void); + /** @} */ + +private: + + /** Wrapped @name IGuestSession properties. + * @{ */ + HRESULT getUser(com::Utf8Str &aUser); + HRESULT getDomain(com::Utf8Str &aDomain); + HRESULT getName(com::Utf8Str &aName); + HRESULT getId(ULONG *aId); + HRESULT getTimeout(ULONG *aTimeout); + HRESULT setTimeout(ULONG aTimeout); + HRESULT getProtocolVersion(ULONG *aProtocolVersion); + HRESULT getStatus(GuestSessionStatus_T *aStatus); + HRESULT getEnvironmentChanges(std::vector<com::Utf8Str> &aEnvironmentChanges); + HRESULT setEnvironmentChanges(const std::vector<com::Utf8Str> &aEnvironmentChanges); + HRESULT getEnvironmentBase(std::vector<com::Utf8Str> &aEnvironmentBase); + HRESULT getProcesses(std::vector<ComPtr<IGuestProcess> > &aProcesses); + HRESULT getPathStyle(PathStyle_T *aPathStyle); + HRESULT getCurrentDirectory(com::Utf8Str &aCurrentDirectory); + HRESULT setCurrentDirectory(const com::Utf8Str &aCurrentDirectory); + HRESULT getUserDocuments(com::Utf8Str &aUserDocuments); + HRESULT getUserHome(com::Utf8Str &aUserHome); + HRESULT getDirectories(std::vector<ComPtr<IGuestDirectory> > &aDirectories); + HRESULT getFiles(std::vector<ComPtr<IGuestFile> > &aFiles); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + /** @} */ + + /** Wrapped @name IGuestSession methods. + * @{ */ + HRESULT close(); + + HRESULT copyFromGuest(const std::vector<com::Utf8Str> &aSources, + const std::vector<com::Utf8Str> &aFilters, + const std::vector<com::Utf8Str> &aFlags, + const com::Utf8Str &aDestination, + ComPtr<IProgress> &aProgress); + HRESULT copyToGuest(const std::vector<com::Utf8Str> &aSources, + const std::vector<com::Utf8Str> &aFilters, + const std::vector<com::Utf8Str> &aFlags, + const com::Utf8Str &aDestination, + ComPtr<IProgress> &aProgress); + + HRESULT directoryCopy(const com::Utf8Str &aSource, + const com::Utf8Str &aDestination, + const std::vector<DirectoryCopyFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT directoryCopyFromGuest(const com::Utf8Str &aSource, + const com::Utf8Str &aDestination, + const std::vector<DirectoryCopyFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT directoryCopyToGuest(const com::Utf8Str &aSource, + const com::Utf8Str &aDestination, + const std::vector<DirectoryCopyFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT directoryCreate(const com::Utf8Str &aPath, + ULONG aMode, + const std::vector<DirectoryCreateFlag_T> &aFlags); + HRESULT directoryCreateTemp(const com::Utf8Str &aTemplateName, + ULONG aMode, + const com::Utf8Str &aPath, + BOOL aSecure, + com::Utf8Str &aDirectory); + HRESULT directoryExists(const com::Utf8Str &aPath, + BOOL aFollowSymlinks, + BOOL *aExists); + HRESULT directoryOpen(const com::Utf8Str &aPath, + const com::Utf8Str &aFilter, + const std::vector<DirectoryOpenFlag_T> &aFlags, + ComPtr<IGuestDirectory> &aDirectory); + HRESULT directoryRemove(const com::Utf8Str &aPath); + HRESULT directoryRemoveRecursive(const com::Utf8Str &aPath, + const std::vector<DirectoryRemoveRecFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT environmentScheduleSet(const com::Utf8Str &aName, + const com::Utf8Str &aValue); + HRESULT environmentScheduleUnset(const com::Utf8Str &aName); + HRESULT environmentGetBaseVariable(const com::Utf8Str &aName, + com::Utf8Str &aValue); + HRESULT environmentDoesBaseVariableExist(const com::Utf8Str &aName, + BOOL *aExists); + + HRESULT fileCopy(const com::Utf8Str &aSource, + const com::Utf8Str &aDestination, + const std::vector<FileCopyFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT fileCopyToGuest(const com::Utf8Str &aSource, + const com::Utf8Str &aDestination, + const std::vector<FileCopyFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT fileCopyFromGuest(const com::Utf8Str &aSource, + const com::Utf8Str &aDestination, + const std::vector<FileCopyFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT fileCreateTemp(const com::Utf8Str &aTemplateName, + ULONG aMode, + const com::Utf8Str &aPath, + BOOL aSecure, + ComPtr<IGuestFile> &aFile); + HRESULT fileExists(const com::Utf8Str &aPath, + BOOL aFollowSymlinks, + BOOL *aExists); + HRESULT fileOpen(const com::Utf8Str &aPath, + FileAccessMode_T aAccessMode, + FileOpenAction_T aOpenAction, + ULONG aCreationMode, + ComPtr<IGuestFile> &aFile); + HRESULT fileOpenEx(const com::Utf8Str &aPath, + FileAccessMode_T aAccessMode, + FileOpenAction_T aOpenAction, + FileSharingMode_T aSharingMode, + ULONG aCreationMode, + const std::vector<FileOpenExFlag_T> &aFlags, + ComPtr<IGuestFile> &aFile); + HRESULT fileQuerySize(const com::Utf8Str &aPath, + BOOL aFollowSymlinks, + LONG64 *aSize); + HRESULT fsQueryFreeSpace(const com::Utf8Str &aPath, LONG64 *aFreeSpace); + HRESULT fsQueryInfo(const com::Utf8Str &aPath, ComPtr<IGuestFsInfo> &aInfo); + HRESULT fsObjExists(const com::Utf8Str &aPath, + BOOL aFollowSymlinks, + BOOL *pfExists); + HRESULT fsObjQueryInfo(const com::Utf8Str &aPath, + BOOL aFollowSymlinks, + ComPtr<IGuestFsObjInfo> &aInfo); + HRESULT fsObjRemove(const com::Utf8Str &aPath); + HRESULT fsObjRemoveArray(const std::vector<com::Utf8Str> &aPaths, + ComPtr<IProgress> &aProgress); + HRESULT fsObjRename(const com::Utf8Str &aOldPath, + const com::Utf8Str &aNewPath, + const std::vector<FsObjRenameFlag_T> &aFlags); + HRESULT fsObjMove(const com::Utf8Str &aSource, + const com::Utf8Str &aDestination, + const std::vector<FsObjMoveFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT fsObjMoveArray(const std::vector<com::Utf8Str> &aSource, + const com::Utf8Str &aDestination, + const std::vector<FsObjMoveFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT fsObjCopyArray(const std::vector<com::Utf8Str> &aSource, + const com::Utf8Str &aDestination, + const std::vector<FileCopyFlag_T> &aFlags, + ComPtr<IProgress> &aProgress); + HRESULT fsObjSetACL(const com::Utf8Str &aPath, + BOOL aFollowSymlinks, + const com::Utf8Str &aAcl, + ULONG aMode); + HRESULT processCreate(const com::Utf8Str &aCommand, + const std::vector<com::Utf8Str> &aArguments, + const std::vector<com::Utf8Str> &aEnvironment, + const std::vector<ProcessCreateFlag_T> &aFlags, + ULONG aTimeoutMS, + ComPtr<IGuestProcess> &aGuestProcess); + HRESULT processCreateEx(const com::Utf8Str &aCommand, + const std::vector<com::Utf8Str> &aArguments, + const std::vector<com::Utf8Str> &aEnvironment, + const std::vector<ProcessCreateFlag_T> &aFlags, + ULONG aTimeoutMS, + ProcessPriority_T aPriority, + const std::vector<LONG> &aAffinity, + ComPtr<IGuestProcess> &aGuestProcess); + HRESULT processGet(ULONG aPid, + ComPtr<IGuestProcess> &aGuestProcess); + HRESULT symlinkCreate(const com::Utf8Str &aSource, + const com::Utf8Str &aTarget, + SymlinkType_T aType); + HRESULT symlinkExists(const com::Utf8Str &aSymlink, + BOOL *aExists); + HRESULT symlinkRead(const com::Utf8Str &aSymlink, + const std::vector<SymlinkReadFlag_T> &aFlags, + com::Utf8Str &aTarget); + HRESULT waitFor(ULONG aWaitFor, + ULONG aTimeoutMS, + GuestSessionWaitResult_T *aReason); + HRESULT waitForArray(const std::vector<GuestSessionWaitForFlag_T> &aWaitFor, + ULONG aTimeoutMS, + GuestSessionWaitResult_T *aReason); + /** @} */ + + /** Map of guest directories. The key specifies the internal directory ID. */ + typedef std::map <uint32_t, ComObjPtr<GuestDirectory> > SessionDirectories; + /** Map of guest files. The key specifies the internal file ID. */ + typedef std::map <uint32_t, ComObjPtr<GuestFile> > SessionFiles; + /** Map of guest processes. The key specifies the internal process number. + * To retrieve the process' guest PID use the Id() method of the IProcess interface. */ + typedef std::map <uint32_t, ComObjPtr<GuestProcess> > SessionProcesses; + + /** Guest session object type enumeration. */ + enum SESSIONOBJECTTYPE + { + /** Invalid session object type. */ + SESSIONOBJECTTYPE_INVALID = 0, + /** Session object. */ + SESSIONOBJECTTYPE_SESSION = 1, + /** Directory object. */ + SESSIONOBJECTTYPE_DIRECTORY = 2, + /** File object. */ + SESSIONOBJECTTYPE_FILE = 3, + /** Process object. */ + SESSIONOBJECTTYPE_PROCESS = 4 + }; + + struct SessionObject + { + /** Creation timestamp (in ms). + * @note not used by anyone at the moment. */ + uint64_t msBirth; + /** The object type. */ + SESSIONOBJECTTYPE enmType; + /** Weak pointer to the object itself. + * Is NULL for SESSIONOBJECTTYPE_SESSION because GuestSession doesn't + * inherit from GuestObject. */ + GuestObject *pObject; + }; + + /** Map containing all objects bound to a guest session. + * The key specifies the (global) context ID. */ + typedef std::map<uint32_t, SessionObject> SessionObjects; + +public: + /** @name Public internal methods. + * @todo r=bird: Most of these are public for no real reason... + * @{ */ + HRESULT i_copyFromGuest(const GuestSessionFsSourceSet &SourceSet, const com::Utf8Str &strDestination, + ComPtr<IProgress> &pProgress); + HRESULT i_copyToGuest(const GuestSessionFsSourceSet &SourceSet, const com::Utf8Str &strDestination, + ComPtr<IProgress> &pProgress); + int i_closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc); + HRESULT i_directoryCopyFlagFromStr(const com::Utf8Str &strFlags, bool fStrict, DirectoryCopyFlag_T *pfFlags); + bool i_directoryExists(const Utf8Str &strPath); + inline bool i_directoryExists(uint32_t uDirID, ComObjPtr<GuestDirectory> *pDir); + int i_directoryUnregister(GuestDirectory *pDirectory); + int i_directoryRemove(const Utf8Str &strPath, uint32_t fFlags, int *pGuestRc); + int i_directoryCreate(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc); + int i_directoryOpen(const GuestDirectoryOpenInfo &openInfo, + ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc); + int i_directoryQueryInfo(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pGuestRc); + int i_dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); + int i_dispatchToThis(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); + HRESULT i_fileCopyFlagFromStr(const com::Utf8Str &strFlags, bool fStrict, FileCopyFlag_T *pfFlags); + inline bool i_fileExists(uint32_t uFileID, ComObjPtr<GuestFile> *pFile); + int i_fileUnregister(GuestFile *pFile); + int i_fileRemove(const Utf8Str &strPath, int *pGuestRc); + int i_fileOpenEx(const com::Utf8Str &aPath, FileAccessMode_T aAccessMode, FileOpenAction_T aOpenAction, + FileSharingMode_T aSharingMode, ULONG aCreationMode, + const std::vector<FileOpenExFlag_T> &aFlags, + ComObjPtr<GuestFile> &pFile, int *prcGuest); + int i_fileOpen(const GuestFileOpenInfo &openInfo, ComObjPtr<GuestFile> &pFile, int *pGuestRc); + int i_fileQueryInfo(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pGuestRc); + int i_fileQuerySize(const Utf8Str &strPath, bool fFollowSymlinks, int64_t *pllSize, int *pGuestRc); + int i_fsCreateTemp(const Utf8Str &strTemplate, const Utf8Str &strPath, bool fDirectory, + Utf8Str &strName, uint32_t fMode, bool fSecure, int *pGuestRc); + int i_fsQueryInfo(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pGuestRc); + const GuestCredentials &i_getCredentials(void); + EventSource *i_getEventSource(void) { return mEventSource; } + Utf8Str i_getName(void); + ULONG i_getId(void) { return mData.mSession.mID; } + bool i_isStarted(void) const; + HRESULT i_isStartedExternal(void); + bool i_isTerminated(void) const; + int i_onRemove(void); + int i_onSessionStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); + PathStyle_T i_getGuestPathStyle(void); + static PathStyle_T i_getHostPathStyle(void); + int i_startSession(int *pGuestRc); + int i_startSessionAsync(void); + Guest *i_getParent(void) { return mParent; } + uint32_t i_getProtocolVersion(void) { return mData.mProtocolVersion; } + int i_objectRegister(GuestObject *pObject, SESSIONOBJECTTYPE enmType, uint32_t *pidObject); + int i_objectUnregister(uint32_t uObjectID); + int i_objectsUnregister(void); + int i_objectsNotifyAboutStatusChange(GuestSessionStatus_T enmSessionStatus); + int i_pathRename(const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags, int *pGuestRc); + int i_pathUserDocuments(Utf8Str &strPath, int *prcGuest); + int i_pathUserHome(Utf8Str &strPath, int *prcGuest); + int i_processUnregister(GuestProcess *pProcess); + int i_processCreateEx(GuestProcessStartupInfo &procInfo, ComObjPtr<GuestProcess> &pProgress); + inline bool i_processExists(uint32_t uProcessID, ComObjPtr<GuestProcess> *pProcess); + inline int i_processGetByPID(ULONG uPID, ComObjPtr<GuestProcess> *pProcess); + int i_sendMessage(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms, + uint64_t fDst = VBOX_GUESTCTRL_DST_SESSION); + int i_setSessionStatus(GuestSessionStatus_T sessionStatus, int sessionRc); + int i_signalWaiters(GuestSessionWaitResult_T enmWaitResult, int rc /*= VINF_SUCCESS */); + int i_shutdown(uint32_t fFlags, int *prcGuest); + int i_determineProtocolVersion(void); + int i_waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestSessionWaitResult_T &waitResult, int *pGuestRc); + int i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS, + GuestSessionStatus_T *pSessionStatus, int *pGuestRc); + /** @} */ + +public: + + /** @name Static helper methods. + * @{ */ + static Utf8Str i_guestErrorToString(int guestRc); + static bool i_isTerminated(GuestSessionStatus_T enmStatus); + static int i_startSessionThreadTask(GuestSessionTaskInternalStart *pTask); + /** @} */ + +private: + + /** Pointer to the parent (Guest). */ + Guest *mParent; + /** + * The session's event source. This source is used for + * serving the internal listener as well as all other + * external listeners that may register to it. + * + * Note: This can safely be used without holding any locks. + * An AutoCaller suffices to prevent it being destroy while in use and + * internally there is a lock providing the necessary serialization. + */ + const ComObjPtr<EventSource> mEventSource; + + /** @todo r=bird: One of the core points of the DATA sub-structures in Main is + * hinding implementation details and stuff that requires including iprt/asm.h. + * The way it's used here totally defeats that purpose. You need to make it + * a pointer to a anynmous Data struct and define that structure in + * GuestSessionImpl.cpp and allocate it in the Init() function. + */ + struct Data + { + /** The session credentials. */ + GuestCredentials mCredentials; + /** The session's startup info. */ + GuestSessionStartupInfo mSession; + /** The session's object ID. + * Needed for registering wait events which are bound directly to this session. */ + uint32_t mObjectID; + /** The session's current status. */ + GuestSessionStatus_T mStatus; + /** The set of environment changes for the session for use when + * creating new guest processes. */ + GuestEnvironmentChanges mEnvironmentChanges; + /** Pointer to the immutable base environment for the session. + * @note This is not allocated until the guest reports it to the host. It is + * also shared with child processes. + * @todo This is actually not yet implemented, see + * GuestSession::i_onSessionStatusChange. */ + GuestEnvironment const *mpBaseEnvironment; + /** Directory objects bound to this session. */ + SessionDirectories mDirectories; + /** File objects bound to this session. */ + SessionFiles mFiles; + /** Process objects bound to this session. */ + SessionProcesses mProcesses; + /** Map of registered session objects (files, directories, ...). */ + SessionObjects mObjects; + /** Guest control protocol version to be used. + * Guest Additions < VBox 4.3 have version 1, + * any newer version will have version 2. */ + uint32_t mProtocolVersion; + /** Session timeout (in ms). */ + uint32_t mTimeout; + /** The last returned session status + * returned from the guest side. */ + int mRC; + /** Object ID allocation bitmap; clear bits are free, set bits are busy. */ + uint64_t bmObjectIds[VBOX_GUESTCTRL_MAX_OBJECTS / sizeof(uint64_t) / 8]; + + Data(void) + : mpBaseEnvironment(NULL) + { + RT_ZERO(bmObjectIds); + ASMBitSet(&bmObjectIds, VBOX_GUESTCTRL_MAX_OBJECTS - 1); /* Reserved for the session itself? */ + ASMBitSet(&bmObjectIds, 0); /* Let's reserve this too. */ + } + Data(const Data &rThat) + : mCredentials(rThat.mCredentials) + , mSession(rThat.mSession) + , mStatus(rThat.mStatus) + , mEnvironmentChanges(rThat.mEnvironmentChanges) + , mpBaseEnvironment(NULL) + , mDirectories(rThat.mDirectories) + , mFiles(rThat.mFiles) + , mProcesses(rThat.mProcesses) + , mObjects(rThat.mObjects) + , mProtocolVersion(rThat.mProtocolVersion) + , mTimeout(rThat.mTimeout) + , mRC(rThat.mRC) + { + memcpy(&bmObjectIds, &rThat.bmObjectIds, sizeof(bmObjectIds)); + } + ~Data(void) + { + if (mpBaseEnvironment) + { + mpBaseEnvironment->releaseConst(); + mpBaseEnvironment = NULL; + } + } + } mData; +}; + +#endif /* !MAIN_INCLUDED_GuestSessionImpl_h */ + diff --git a/src/VBox/Main/include/GuestSessionImplTasks.h b/src/VBox/Main/include/GuestSessionImplTasks.h new file mode 100644 index 00000000..f44f34d2 --- /dev/null +++ b/src/VBox/Main/include/GuestSessionImplTasks.h @@ -0,0 +1,435 @@ +/* $Id: GuestSessionImplTasks.h $ */ +/** @file + * VirtualBox Main - Guest session tasks header. + */ + +/* + * Copyright (C) 2018-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_GuestSessionImplTasks_h +#define MAIN_INCLUDED_GuestSessionImplTasks_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "GuestSessionWrap.h" +#include "EventImpl.h" +#include "ProgressImpl.h" + +#include "GuestCtrlImplPrivate.h" +#include "GuestSessionImpl.h" +#include "ThreadTask.h" + +#include <iprt/vfs.h> + +#include <vector> + +class Guest; +class GuestSessionTask; +class GuestSessionTaskInternalStart; + + +/** + * Structure for keeping a file system source specification, + * along with options. + */ +struct GuestSessionFsSourceSpec +{ + GuestSessionFsSourceSpec() + : enmType(FsObjType_Unknown) + , enmPathStyle(PathStyle_Unknown) + , fDryRun(false) { RT_ZERO(Type); } + + /** The (absolute) path to the source to use. */ + Utf8Str strSource; + /** Filter to use. Currently not implemented and thus ignored. */ + Utf8Str strFilter; + /** The root object type of this source (directory, file). */ + FsObjType_T enmType; + /** The path style to use. */ + PathStyle_T enmPathStyle; + /** Whether to do a dry run (e.g. not really touching anything) or not. */ + bool fDryRun; + /** Directory copy flags. */ + DirectoryCopyFlag_T fDirCopyFlags; + /** File copy flags. */ + FileCopyFlag_T fFileCopyFlags; + /** Union to keep type-specific data. Must be a POD type (zero'ing). */ + union + { + /** File-specific data. */ + struct + { + /** Source file offset to start copying from. */ + size_t offStart; + /** Host file handle to use for reading from / writing to. + * Optional and can be NULL if not used. */ + PRTFILE phFile; + /** Source size (in bytes) to copy. */ + uint64_t cbSize; + } File; + } Type; +}; + +/** A set of GuestSessionFsSourceSpec sources. */ +typedef std::vector<GuestSessionFsSourceSpec> GuestSessionFsSourceSet; + +/** + * Structure for keeping a file system entry. + */ +struct FsEntry +{ + /** The entrie's file mode. */ + RTFMODE fMode; + /** The entrie's path, relative to the list's root path. */ + Utf8Str strPath; +}; + +/** A vector of FsEntry entries. */ +typedef std::vector<FsEntry *> FsEntries; + +/** + * Class for storing and handling file system entries, neeed for doing + * internal file / directory operations to / from the guest. + */ +class FsList +{ +public: + + FsList(const GuestSessionTask &Task); + virtual ~FsList(); + +public: + + int Init(const Utf8Str &strSrcRootAbs, const Utf8Str &strDstRootAbs, const GuestSessionFsSourceSpec &SourceSpec); + void Destroy(void); + +#ifdef DEBUG + void DumpToLog(void); +#endif + + int AddEntryFromGuest(const Utf8Str &strFile, const GuestFsObjData &fsObjData); + int AddDirFromGuest(const Utf8Str &strPath, const Utf8Str &strSubDir = ""); + + int AddEntryFromHost(const Utf8Str &strFile, PCRTFSOBJINFO pcObjInfo); + int AddDirFromHost(const Utf8Str &strPath, const Utf8Str &strSubDir, char *pszPathReal, size_t cbPathReal, PRTDIRENTRYEX pDirEntry); + +public: + + /** The guest session task object this list is working on. */ + const GuestSessionTask &mTask; + /** File system filter / options to use for this task. */ + GuestSessionFsSourceSpec mSourceSpec; + /** The source' root path. Always in the source's path style! + * + * For a single file list this is the full (absolute) path to a file, + * for a directory list this is the source root directory. */ + Utf8Str mSrcRootAbs; + /** The destinations's root path. Always in the destination's path style! + * + * For a single file list this is the full (absolute) path to a file, + * for a directory list this is the destination root directory. */ + Utf8Str mDstRootAbs; + /** Total size (in bytes) of all list entries together. */ + uint64_t mcbTotalSize; + /** List of file system entries this list contains. */ + FsEntries mVecEntries; +}; + +/** A set of FsList lists. */ +typedef std::vector<FsList *> FsLists; + +/** + * Abstract base class for a lenghtly per-session operation which + * runs in a Main worker thread. + */ +class GuestSessionTask + : public ThreadTask +{ +public: + DECLARE_TRANSLATE_METHODS(GuestSessionTask) + + GuestSessionTask(GuestSession *pSession); + + virtual ~GuestSessionTask(void); + +public: + + /** + * Function which implements the actual task to perform. + * + * @returns VBox status code. + */ + virtual int Run(void) = 0; + + void handler() + { + int vrc = Run(); + if (RT_FAILURE(vrc)) /* Could be VERR_INTERRUPTED if the user manually canceled the task. */ + { + /* Make sure to let users know if there is a buggy task which failed but didn't set the progress object + * to a failed state, and if not canceled manually by the user. */ + BOOL fCanceled; + if (SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))) + { + if (!fCanceled) + { + BOOL fCompleted; + if (SUCCEEDED(mProgress->COMGETTER(Completed(&fCompleted)))) + { + if (!fCompleted) + setProgressErrorMsg(E_UNEXPECTED, + Utf8StrFmt(tr("Task '%s' failed with %Rrc, but progress is still pending. Please report this bug!\n"), + mDesc.c_str(), vrc)); + } + else + AssertReleaseMsgFailed(("Guest Control: Unable to retrieve progress completion status for task '%s' (task result is %Rrc)\n", + mDesc.c_str(), vrc)); + } + } + else + AssertReleaseMsgFailed(("Guest Control: Unable to retrieve progress cancellation status for task '%s' (task result is %Rrc)\n", + mDesc.c_str(), vrc)); + } + } + + // unused: int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress); + + virtual HRESULT Init(const Utf8Str &strTaskDesc) + { + setTaskDesc(strTaskDesc); + int rc = createAndSetProgressObject(); /* Single operation by default. */ + if (RT_FAILURE(rc)) + return E_FAIL; + + return S_OK; + } + + /** Returns the task's progress object. */ + const ComObjPtr<Progress>& GetProgressObject(void) const { return mProgress; } + + /** Returns the task's guest session object. */ + const ComObjPtr<GuestSession>& GetSession(void) const { return mSession; } + +protected: + + /** @name Directory handling primitives. + * @{ */ + int directoryCreateOnGuest(const com::Utf8Str &strPath, + uint32_t fMode, DirectoryCreateFlag_T enmDirectoryCreateFlags, + bool fFollowSymlinks, bool fCanExist); + int directoryCreateOnHost(const com::Utf8Str &strPath, uint32_t fMode, uint32_t fCreate, bool fCanExist); + /** @} */ + + /** @name File handling primitives. + * @{ */ + int fileClose(const ComObjPtr<GuestFile> &file); + int fileCopyFromGuestInner(const Utf8Str &strSrcFile, ComObjPtr<GuestFile> &srcFile, + const Utf8Str &strDstFile, PRTFILE phDstFile, + FileCopyFlag_T fFileCopyFlags, uint64_t offCopy, uint64_t cbSize); + int fileCopyFromGuest(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags); + int fileCopyToGuestInner(const Utf8Str &strSrcFile, RTVFSFILE hSrcFile, + const Utf8Str &strDstFile, ComObjPtr<GuestFile> &dstFile, + FileCopyFlag_T fFileCopyFlags, uint64_t offCopy, uint64_t cbSize); + + int fileCopyToGuest(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags); + /** @} */ + + /** @name Guest property handling primitives. + * @{ */ + int getGuestProperty(const ComObjPtr<Guest> &pGuest, const Utf8Str &strPath, Utf8Str &strValue); + /** @} */ + + int setProgress(ULONG uPercent); + int setProgressSuccess(void); + HRESULT setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg); + HRESULT setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg, const GuestErrorInfo &guestErrorInfo); + + inline void setTaskDesc(const Utf8Str &strTaskDesc) throw() + { + mDesc = strTaskDesc; + } + + int createAndSetProgressObject(ULONG cOperations = 1); + +protected: + + Utf8Str mDesc; + /** The guest session object this task is working on. */ + ComObjPtr<GuestSession> mSession; + /** Progress object for getting updated when running + * asynchronously. Optional. */ + ComObjPtr<Progress> mProgress; + /** The guest's path style as char representation (depending on the guest OS type set). */ + Utf8Str mstrGuestPathStyle; +}; + +/** + * Task for opening a guest session. + */ +class GuestSessionTaskOpen : public GuestSessionTask +{ +public: + + GuestSessionTaskOpen(GuestSession *pSession, + uint32_t uFlags, + uint32_t uTimeoutMS); + virtual ~GuestSessionTaskOpen(void); + int Run(void); + +protected: + + /** Session creation flags. */ + uint32_t mFlags; + /** Session creation timeout (in ms). */ + uint32_t mTimeoutMS; +}; + +class GuestSessionCopyTask : public GuestSessionTask +{ +public: + DECLARE_TRANSLATE_METHODS(GuestSessionCopyTask) + + GuestSessionCopyTask(GuestSession *pSession); + virtual ~GuestSessionCopyTask(); + +protected: + + /** Source set. */ + GuestSessionFsSourceSet mSources; + /** Destination to copy to. */ + Utf8Str mDest; + /** Vector of file system lists to handle. + * This either can be from the guest or the host side. */ + FsLists mVecLists; +}; + +/** + * Guest session task for copying files / directories from guest to the host. + */ +class GuestSessionTaskCopyFrom : public GuestSessionCopyTask +{ +public: + DECLARE_TRANSLATE_METHODS(GuestSessionTaskCopyFrom) + + GuestSessionTaskCopyFrom(GuestSession *pSession, GuestSessionFsSourceSet const &vecSrc, const Utf8Str &strDest); + virtual ~GuestSessionTaskCopyFrom(void); + + HRESULT Init(const Utf8Str &strTaskDesc); + int Run(void); +}; + +/** + * Task for copying directories from host to the guest. + */ +class GuestSessionTaskCopyTo : public GuestSessionCopyTask +{ +public: + DECLARE_TRANSLATE_METHODS(GuestSessionTaskCopyTo) + + GuestSessionTaskCopyTo(GuestSession *pSession, GuestSessionFsSourceSet const &vecSrc, const Utf8Str &strDest); + virtual ~GuestSessionTaskCopyTo(void); + + HRESULT Init(const Utf8Str &strTaskDesc); + int Run(void); +}; + +/** + * Guest session task for automatically updating the Guest Additions on the guest. + */ +class GuestSessionTaskUpdateAdditions : public GuestSessionTask +{ +public: + DECLARE_TRANSLATE_METHODS(GuestSessionTaskUpdateAdditions) + + GuestSessionTaskUpdateAdditions(GuestSession *pSession, const Utf8Str &strSource, + const ProcessArguments &aArguments, uint32_t fFlags); + virtual ~GuestSessionTaskUpdateAdditions(void); + int Run(void); + +protected: + + /** + * Suported OS types for automatic updating. + */ + enum eOSType + { + eOSType_Unknown = 0, + eOSType_Windows = 1, + eOSType_Linux = 2, + eOSType_Solaris = 3 + }; + + /** + * Structure representing a file to + * get off the .ISO, copied to the guest. + */ + struct ISOFile + { + ISOFile(const Utf8Str &aSource, + const Utf8Str &aDest, + uint32_t aFlags = 0) + : strSource(aSource), + strDest(aDest), + fFlags(aFlags) { } + + ISOFile(const Utf8Str &aSource, + const Utf8Str &aDest, + uint32_t aFlags, + const GuestProcessStartupInfo &aStartupInfo) + : strSource(aSource), + strDest(aDest), + fFlags(aFlags), + mProcInfo(aStartupInfo) + { + mProcInfo.mExecutable = strDest; + if (mProcInfo.mName.isEmpty()) + mProcInfo.mName = strDest; + } + + /** Source file on .ISO. */ + Utf8Str strSource; + /** Destination file on the guest. */ + Utf8Str strDest; + /** ISO file flags (see ISOFILE_FLAG_ defines). */ + uint32_t fFlags; + /** Optional arguments if this file needs to be + * executed. */ + GuestProcessStartupInfo mProcInfo; + }; + + int addProcessArguments(ProcessArguments &aArgumentsDest, const ProcessArguments &aArgumentsSource); + int copyFileToGuest(GuestSession *pSession, RTVFS hVfsIso, Utf8Str const &strFileSource, const Utf8Str &strFileDest, bool fOptional); + int runFileOnGuest(GuestSession *pSession, GuestProcessStartupInfo &procInfo); + int waitForGuestSession(ComObjPtr<Guest> pGuest); + + /** Files to handle. */ + std::vector<ISOFile> mFiles; + /** The (optionally) specified Guest Additions .ISO on the host + * which will be used for the updating process. */ + Utf8Str mSource; + /** (Optional) installer command line arguments. */ + ProcessArguments mArguments; + /** Update flags. */ + uint32_t mFlags; +}; +#endif /* !MAIN_INCLUDED_GuestSessionImplTasks_h */ diff --git a/src/VBox/Main/include/HGCM.h b/src/VBox/Main/include/HGCM.h new file mode 100644 index 00000000..9daafe32 --- /dev/null +++ b/src/VBox/Main/include/HGCM.h @@ -0,0 +1,69 @@ +/* $Id: HGCM.h $ */ +/** @file + * HGCM - Host-Guest Communication Manager. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HGCM_h +#define MAIN_INCLUDED_HGCM_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/vmm/pdmifs.h> + +#include <VBox/hgcmsvc.h> + +/* Handle of a HGCM service extension. */ +struct _HGCMSVCEXTHANDLEDATA; +typedef struct _HGCMSVCEXTHANDLEDATA *HGCMSVCEXTHANDLE; + +RT_C_DECLS_BEGIN +int HGCMHostInit(void); +int HGCMHostShutdown(bool fUvmIsInvalid = false); + +int HGCMHostReset(bool fForShutdown); + +int HGCMHostLoad(const char *pszServiceLibrary, const char *pszServiceName, + PUVM pUVM, PCVMMR3VTABLE pVMM, PPDMIHGCMPORT pHgcmPort); + +int HGCMHostRegisterServiceExtension(HGCMSVCEXTHANDLE *pHandle, const char *pszServiceName, PFNHGCMSVCEXT pfnExtension, void *pvExtension); +void HGCMHostUnregisterServiceExtension(HGCMSVCEXTHANDLE handle); + +int HGCMGuestConnect(PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, const char *pszServiceName, uint32_t *pClientID); +int HGCMGuestDisconnect(PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, uint32_t clientID); +int HGCMGuestCall(PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, uint32_t clientID, uint32_t function, uint32_t cParms, + VBOXHGCMSVCPARM *paParms, uint64_t tsArrival); +void HGCMGuestCancelled(PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, uint32_t idClient); + +int HGCMHostCall(const char *pszServiceName, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM aParms[]); +int HGCMBroadcastEvent(HGCMNOTIFYEVENT enmEvent); + +int HGCMHostSaveState(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM); +int HGCMHostLoadState(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, uint32_t uVersion); + +RT_C_DECLS_END + +#endif /* !MAIN_INCLUDED_HGCM_h */ + diff --git a/src/VBox/Main/include/HGCMObjects.h b/src/VBox/Main/include/HGCMObjects.h new file mode 100644 index 00000000..97322d98 --- /dev/null +++ b/src/VBox/Main/include/HGCMObjects.h @@ -0,0 +1,138 @@ +/* $Id: HGCMObjects.h $ */ +/** @file + * HGCMObjects - Host-Guest Communication Manager objects header. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HGCMObjects_h +#define MAIN_INCLUDED_HGCMObjects_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/assert.h> +#include <iprt/avl.h> +#include <iprt/critsect.h> +#include <iprt/asm.h> + +class HGCMObject; + +typedef struct ObjectAVLCore +{ + AVLU32NODECORE AvlCore; + HGCMObject *pSelf; +} ObjectAVLCore; + +typedef enum +{ + HGCMOBJ_CLIENT, + HGCMOBJ_THREAD, + HGCMOBJ_MSG, + HGCMOBJ_SizeHack = 0x7fffffff +} HGCMOBJ_TYPE; + + +/** + * A referenced object. + */ +class HGCMReferencedObject +{ + private: + int32_t volatile m_cRefs; + HGCMOBJ_TYPE m_enmObjType; + + protected: + virtual ~HGCMReferencedObject() + {} + + public: + HGCMReferencedObject(HGCMOBJ_TYPE enmObjType) + : m_cRefs(0) /** @todo change to 1! */ + , m_enmObjType(enmObjType) + {} + + void Reference() + { + int32_t cRefs = ASMAtomicIncS32(&m_cRefs); + NOREF(cRefs); + Log(("Reference(%p/%d): cRefs = %d\n", this, m_enmObjType, cRefs)); + } + + void Dereference() + { + int32_t cRefs = ASMAtomicDecS32(&m_cRefs); + Log(("Dereference(%p/%d): cRefs = %d \n", this, m_enmObjType, cRefs)); + AssertRelease(cRefs >= 0); + + if (cRefs) + { /* likely */ } + else + delete this; + } + + HGCMOBJ_TYPE Type() + { + return m_enmObjType; + } +}; + + +class HGCMObject : public HGCMReferencedObject +{ + private: + friend uint32_t hgcmObjMake(HGCMObject *pObject, uint32_t u32HandleIn); + + ObjectAVLCore m_core; + + protected: + virtual ~HGCMObject() + {} + + public: + HGCMObject(HGCMOBJ_TYPE enmObjType) + : HGCMReferencedObject(enmObjType) + {} + + uint32_t Handle() + { + return (uint32_t)m_core.AvlCore.Key; + } +}; + +int hgcmObjInit(); +void hgcmObjUninit(); + +uint32_t hgcmObjGenerateHandle(HGCMObject *pObject); +uint32_t hgcmObjAssignHandle(HGCMObject *pObject, uint32_t u32Handle); + +void hgcmObjDeleteHandle(uint32_t handle); + +HGCMObject *hgcmObjReference(uint32_t handle, HGCMOBJ_TYPE enmObjType); +void hgcmObjDereference(HGCMObject *pObject); + +uint32_t hgcmObjQueryHandleCount(); +void hgcmObjSetHandleCount(uint32_t u32HandleCount); + + +#endif /* !MAIN_INCLUDED_HGCMObjects_h */ diff --git a/src/VBox/Main/include/HGCMThread.h b/src/VBox/Main/include/HGCMThread.h new file mode 100644 index 00000000..d547fed4 --- /dev/null +++ b/src/VBox/Main/include/HGCMThread.h @@ -0,0 +1,238 @@ +/* $Id: HGCMThread.h $ */ +/** @file + * HGCMThread - Host-Guest Communication Manager worker threads header. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HGCMThread_h +#define MAIN_INCLUDED_HGCMThread_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/types.h> + +#include "HGCMObjects.h" + +/* Forward declaration of the worker thread class. */ +class HGCMThread; + +/** A handle for HGCM message. */ +typedef uint32_t HGCMMSGHANDLE; + +/* Forward declaration of message core class. */ +class HGCMMsgCore; + +/** @todo comment */ + +typedef HGCMMsgCore *FNHGCMNEWMSGALLOC(uint32_t u32MsgId); +typedef FNHGCMNEWMSGALLOC *PFNHGCMNEWMSGALLOC; + +/** Function that is called after message processing by worker thread, + * or if an error occurred during message handling after successfully + * posting (hgcmMsgPost) the message to worker thread. + * + * @param result Return code either from the service which actually processed the message + * or from HGCM. + * @param pMsgCore Pointer to just processed message. + * + * @return Restricted set of VBox status codes when guest call message: + * @retval VINF_SUCCESS on success + * @retval VERR_CANCELLED if the request was cancelled. + * @retval VERR_ALREADY_RESET if the VM is resetting. + * @retval VERR_NOT_AVAILABLE if HGCM has been disconnected from the VMMDev + * (shouldn't happen). + */ +typedef DECLCALLBACKTYPE(int, FNHGCMMSGCALLBACK,(int32_t result, HGCMMsgCore *pMsgCore)); +/** Pointer to a message completeion callback function. */ +typedef FNHGCMMSGCALLBACK *PFNHGCMMSGCALLBACK; + + +/** HGCM core message. */ +class HGCMMsgCore : public HGCMReferencedObject +{ + private: + friend class HGCMThread; + + /** Version of message header. */ + uint32_t m_u32Version; + + /** Message number/identifier. */ + uint32_t m_u32Msg; + + /** Thread the message belongs to, referenced by the message. */ + HGCMThread *m_pThread; + + /** Callback function pointer. */ + PFNHGCMMSGCALLBACK m_pfnCallback; + + /** Next element in a message queue. */ + HGCMMsgCore *m_pNext; + /** Previous element in a message queue. + * @todo seems not necessary. */ + HGCMMsgCore *m_pPrev; + + /** Various internal flags. */ + uint32_t m_fu32Flags; + + /** Result code for a Send */ + int32_t m_rcSend; + + protected: + void InitializeCore(uint32_t u32MsgId, HGCMThread *pThread); + + virtual ~HGCMMsgCore(); + + public: + HGCMMsgCore() : HGCMReferencedObject(HGCMOBJ_MSG) {}; + + uint32_t MsgId(void) { return m_u32Msg; }; + + HGCMThread *Thread(void) { return m_pThread; }; + + /** Initialize message after it was allocated. */ + virtual void Initialize(void) {}; + + /** Uninitialize message. */ + virtual void Uninitialize(void) {}; +}; + + +/** HGCM worker thread function. + * + * @param pThread The HGCM thread instance. + * @param pvUser User specified thread parameter. + */ +typedef DECLCALLBACKTYPE(void, FNHGCMTHREAD,(HGCMThread *pThread, void *pvUser)); +typedef FNHGCMTHREAD *PFNHGCMTHREAD; + + +/** + * Thread API. + * Based on thread handles. Internals of a thread are not exposed to users. + */ + +/** Initialize threads. + * + * @return VBox status code. + */ +int hgcmThreadInit(void); +void hgcmThreadUninit(void); + + +/** Create a HGCM worker thread. + * + * @param ppThread Where to return the pointer to the worker thread. + * @param pszThreadName Name of the thread, needed by runtime. + * @param pfnThread The worker thread function. + * @param pvUser A pointer passed to worker thread. + * @param pszStatsSubDir The "sub-directory" under "/HGCM/" where thread + * statistics should be registered. The caller, + * HGCMService, will deregister them. NULL if no stats. + * @param pUVM The user mode VM handle to register statistics with. + * NULL if no stats. + * @param pVMM The VMM vtable for statistics registration. NULL if + * no stats. + * + * @return VBox status code. + */ +int hgcmThreadCreate(HGCMThread **ppThread, const char *pszThreadName, PFNHGCMTHREAD pfnThread, void *pvUser, + const char *pszStatsSubDir, PUVM pUVM, PCVMMR3VTABLE pVMM); + +/** Wait for termination of a HGCM worker thread. + * + * @param pThread The HGCM thread. The passed in reference is always + * consumed. + * + * @return VBox status code. + */ +int hgcmThreadWait(HGCMThread *pThread); + +/** Allocate a message to be posted to HGCM worker thread. + * + * @param pThread The HGCM worker thread. + * @param ppHandle Where to store the pointer to the new message. + * @param u32MsgId Message identifier. + * @param pfnNewMessage New message allocation callback. + * + * @return VBox status code. + */ +int hgcmMsgAlloc(HGCMThread *pThread, HGCMMsgCore **ppHandle, uint32_t u32MsgId, PFNHGCMNEWMSGALLOC pfnNewMessage); + +/** Post a message to HGCM worker thread. + * + * @param pMsg The message. Reference will be consumed! + * @param pfnCallback Message completion callback. + * + * @return VBox status code. + * @retval VINF_HGCM_ASYNC_EXECUTE on success. + * + * @thread any + */ +int hgcmMsgPost(HGCMMsgCore *pMsg, PFNHGCMMSGCALLBACK pfnCallback); + +/** Send a message to HGCM worker thread. + * + * The function will return after message is processed by thread. + * + * @param pMsg The message. Reference will be consumed! + * + * @return VBox status code. + * + * @thread any + */ +int hgcmMsgSend(HGCMMsgCore *pMsg); + + +/* Wait for and get a message. + * + * @param pThread The HGCM worker thread. + * @param ppMsg Where to store returned message pointer. + * + * @return VBox status code. + * + * @thread worker thread + */ +int hgcmMsgGet(HGCMThread *pThread, HGCMMsgCore **ppMsg); + + +/** Worker thread has processed a message previously obtained with hgcmMsgGet. + * + * @param pMsg Processed message pointer. + * @param result Result code, VBox status code. + * + * @return Restricted set of VBox status codes when guest call message: + * @retval VINF_SUCCESS on success + * @retval VERR_CANCELLED if the request was cancelled. + * @retval VERR_ALREADY_RESET if the VM is resetting. + * @retval VERR_NOT_AVAILABLE if HGCM has been disconnected from the VMMDev + * (shouldn't happen). + * + * @thread worker thread + */ +int hgcmMsgComplete(HGCMMsgCore *pMsg, int32_t result); + + +#endif /* !MAIN_INCLUDED_HGCMThread_h */ + diff --git a/src/VBox/Main/include/HashedPw.h b/src/VBox/Main/include/HashedPw.h new file mode 100644 index 00000000..56583af3 --- /dev/null +++ b/src/VBox/Main/include/HashedPw.h @@ -0,0 +1,40 @@ +/* $Id: HashedPw.h $ */ +/** @file + * Main - Password Hashing + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HashedPw_h +#define MAIN_INCLUDED_HashedPw_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/cpp/ministring.h> + +bool VBoxIsPasswordHashed(RTCString const *a_pstrPassword); +void VBoxHashPassword(RTCString *a_pstrPassword); + +#endif /* !MAIN_INCLUDED_HashedPw_h */ + diff --git a/src/VBox/Main/include/HostAudioDeviceImpl.h b/src/VBox/Main/include/HostAudioDeviceImpl.h new file mode 100644 index 00000000..95bae526 --- /dev/null +++ b/src/VBox/Main/include/HostAudioDeviceImpl.h @@ -0,0 +1,58 @@ +/* $Id: HostAudioDeviceImpl.h $ */ + +/** @file + * VirtualBox COM class implementation - Host audio device implementation. + */ + +/* + * Copyright (C) 2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostAudioDeviceImpl_h +#define MAIN_INCLUDED_HostAudioDeviceImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "HostAudioDeviceWrap.h" + +class ATL_NO_VTABLE HostAudioDevice : + public HostAudioDeviceWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(HostAudioDevice) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(); + void uninit(); + +private: + + // wrapped IHostAudioDevice properties + +}; + +#endif /* !MAIN_INCLUDED_HostAudioDeviceImpl_h */ + diff --git a/src/VBox/Main/include/HostDriveImpl.h b/src/VBox/Main/include/HostDriveImpl.h new file mode 100644 index 00000000..9d793bb4 --- /dev/null +++ b/src/VBox/Main/include/HostDriveImpl.h @@ -0,0 +1,86 @@ +/* $Id: HostDriveImpl.h $ */ +/** @file + * VirtualBox Main - IHostDrive implementation, VBoxSVC. + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostDriveImpl_h +#define MAIN_INCLUDED_HostDriveImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "HostDriveWrap.h" + +class ATL_NO_VTABLE HostDrive + : public HostDriveWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(HostDrive) + + HRESULT FinalConstruct(); + void FinalRelease(); + + /** @name Public initializer/uninitializer for internal purposes only. + * @{ */ + HRESULT initFromPathAndModel(const com::Utf8Str &drivePath, const com::Utf8Str &driveModel); + void uninit(); + /** @} */ + + com::Utf8Str i_getDrivePath() { return m.drivePath; } + +private: + /** @name wrapped IHostDrive properties + * @{ */ + virtual HRESULT getPartitioningType(PartitioningType_T *aPartitioningType) RT_OVERRIDE; + virtual HRESULT getDrivePath(com::Utf8Str &aDrivePath) RT_OVERRIDE; + virtual HRESULT getUuid(com::Guid &aUuid) RT_OVERRIDE; + virtual HRESULT getSectorSize(ULONG *aSectorSize) RT_OVERRIDE; + virtual HRESULT getSize(LONG64 *aSize) RT_OVERRIDE; + virtual HRESULT getModel(com::Utf8Str &aModel) RT_OVERRIDE; + virtual HRESULT getPartitions(std::vector<ComPtr<IHostDrivePartition> > &aPartitions) RT_OVERRIDE; + /** @} */ + + /** Data. */ + struct Data + { + Data() : cbSector(0), cbDisk(0) + { + } + + PartitioningType_T partitioningType; + com::Utf8Str drivePath; + com::Guid uuid; + uint32_t cbSector; + uint64_t cbDisk; + com::Utf8Str model; + std::vector<ComPtr<IHostDrivePartition> > partitions; + }; + + Data m; +}; + +#endif /* !MAIN_INCLUDED_HostDriveImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/HostDrivePartitionImpl.h b/src/VBox/Main/include/HostDrivePartitionImpl.h new file mode 100644 index 00000000..ddd65262 --- /dev/null +++ b/src/VBox/Main/include/HostDrivePartitionImpl.h @@ -0,0 +1,126 @@ +/* $Id: HostDrivePartitionImpl.h $ */ +/** @file + * VirtualBox Main - IHostDrivePartition implementation, VBoxSVC. + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostDrivePartitionImpl_h +#define MAIN_INCLUDED_HostDrivePartitionImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "HostDrivePartitionWrap.h" + +#include <iprt/dvm.h> + +class ATL_NO_VTABLE HostDrivePartition + : public HostDrivePartitionWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(HostDrivePartition) + + HRESULT FinalConstruct(); + void FinalRelease(); + + /** @name Public initializer/uninitializer for internal purposes only. + * @{ */ + HRESULT initFromDvmVol(RTDVMVOLUME hVol); + void uninit(); + /** @} */ + +private: + /** @name wrapped IHostDrivePartition properties + * @{ */ + /* Common: */ + virtual HRESULT getNumber(ULONG *aNumber) RT_OVERRIDE { *aNumber = m.number; return S_OK; } + virtual HRESULT getSize(LONG64 *aSize) RT_OVERRIDE { *aSize = m.cbVol; return S_OK; } + virtual HRESULT getStart(LONG64 *aStart) RT_OVERRIDE { *aStart = m.offStart; return S_OK; } + virtual HRESULT getType(PartitionType_T *aType) RT_OVERRIDE { *aType = m.enmType; return S_OK; } + virtual HRESULT getActive(BOOL *aActive) RT_OVERRIDE { *aActive = m.active; return S_OK; } + /* MBR: */ + virtual HRESULT getTypeMBR(ULONG *aTypeMBR) RT_OVERRIDE { *aTypeMBR = m.bMBRType; return S_OK; } + virtual HRESULT getStartCylinder(ULONG *aStartCylinder) RT_OVERRIDE { *aStartCylinder = m.firstCylinder; return S_OK; } + virtual HRESULT getStartHead(ULONG *aStartHead) RT_OVERRIDE { *aStartHead = m.firstHead; return S_OK; } + virtual HRESULT getStartSector(ULONG *aStartSector) RT_OVERRIDE { *aStartSector = m.firstSector; return S_OK; } + virtual HRESULT getEndCylinder(ULONG *aEndCylinder) RT_OVERRIDE { *aEndCylinder = m.lastCylinder; return S_OK; } + virtual HRESULT getEndHead(ULONG *aEndHead) RT_OVERRIDE { *aEndHead = m.lastHead; return S_OK; } + virtual HRESULT getEndSector(ULONG *aEndSector) RT_OVERRIDE { *aEndSector = m.lastSector; return S_OK; } + /* GPT: */ + virtual HRESULT getTypeUuid(com::Guid &aTypeUuid) RT_OVERRIDE { aTypeUuid = m.typeUuid; return S_OK; } + virtual HRESULT getUuid(com::Guid &aUuid) RT_OVERRIDE { aUuid = m.uuid; return S_OK; } + virtual HRESULT getName(com::Utf8Str &aName) RT_OVERRIDE { return aName.assignEx(m.name); }; + /** @} */ + + /** Data. */ + struct Data + { + Data() + : number(0) + , cbVol(0) + , offStart(0) + , enmType(PartitionType_Unknown) + , active(FALSE) + , bMBRType(0) + , firstCylinder(0) + , firstHead(0) + , firstSector(0) + , lastCylinder(0) + , lastHead(0) + , lastSector(0) + , typeUuid() + , uuid() + , name() + { + } + + ULONG number; + LONG64 cbVol; + LONG64 offStart; + PartitionType_T enmType; + BOOL active; + /** @name MBR specifics + * @{ */ + uint8_t bMBRType; + uint16_t firstCylinder; + uint8_t firstHead; + uint8_t firstSector; + uint16_t lastCylinder; + uint8_t lastHead; + uint8_t lastSector; + /** @} */ + /** @name GPT specifics + * @{ */ + com::Guid typeUuid; + com::Guid uuid; + com::Utf8Str name; + /** @} */ + }; + + Data m; +}; + +#endif /* !MAIN_INCLUDED_HostDrivePartitionImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/HostHardwareLinux.h b/src/VBox/Main/include/HostHardwareLinux.h new file mode 100644 index 00000000..666c43f1 --- /dev/null +++ b/src/VBox/Main/include/HostHardwareLinux.h @@ -0,0 +1,209 @@ +/* $Id: HostHardwareLinux.h $ */ +/** @file + * VirtualBox Main - Classes for handling hardware detection under Linux. + * + * Please feel free to expand these to work for other systems (Solaris!) or to + * add new ones for other systems. + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostHardwareLinux_h +#define MAIN_INCLUDED_HostHardwareLinux_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/err.h> +#include <iprt/cpp/ministring.h> +#include <vector> +#include <vector.h> + +/** + * Class for probing and returning information about host DVD and floppy + * drives. To use this class, create an instance, call one of the update + * methods to do the actual probing and use the iterator methods to get the + * result of the probe. + */ +class VBoxMainDriveInfo +{ +public: + /** Structure describing a host drive */ + struct DriveInfo + { + /** The device node of the drive. */ + RTCString mDevice; + /** A unique identifier for the device, if available. This should be + * kept consistent across different probing methods of a given + * platform if at all possible. */ + RTCString mUdi; + /** A textual description of the drive. */ + RTCString mDescription; + + /** Constructors */ + DriveInfo(const RTCString &aDevice, + const RTCString &aUdi = "", + const RTCString &aDescription = "") + : mDevice(aDevice), + mUdi(aUdi), + mDescription(aDescription) + { } + }; + + /** List (resp vector) holding drive information */ + typedef std::vector<DriveInfo> DriveInfoList; + + /** + * Search for host floppy drives and rebuild the list, which remains empty + * until the first time this method is called. + * @returns iprt status code + */ + int updateFloppies() RT_NOEXCEPT; + + /** + * Search for host DVD drives and rebuild the list, which remains empty + * until the first time this method is called. + * @returns iprt status code + */ + int updateDVDs() RT_NOEXCEPT; + + /** + * Search for fixed disks (HDDs) and rebuild the list, which remains empty until + * the first time this method is called. + * @returns iprt status code + */ + int updateFixedDrives() RT_NOEXCEPT; + + /** Get the first element in the list of floppy drives. */ + DriveInfoList::const_iterator FloppyBegin() + { + return mFloppyList.begin(); + } + + /** Get the last element in the list of floppy drives. */ + DriveInfoList::const_iterator FloppyEnd() + { + return mFloppyList.end(); + } + + /** Get the first element in the list of DVD drives. */ + DriveInfoList::const_iterator DVDBegin() + { + return mDVDList.begin(); + } + + /** Get the last element in the list of DVD drives. */ + DriveInfoList::const_iterator DVDEnd() + { + return mDVDList.end(); + } + + /** Get the first element in the list of fixed drives. */ + DriveInfoList::const_iterator FixedDriveBegin() + { + return mFixedDriveList.begin(); + } + + /** Get the last element in the list of fixed drives. */ + DriveInfoList::const_iterator FixedDriveEnd() + { + return mFixedDriveList.end(); + } +private: + /** The list of currently available floppy drives */ + DriveInfoList mFloppyList; + /** The list of currently available DVD drives */ + DriveInfoList mDVDList; + /** The list of currently available fixed drives */ + DriveInfoList mFixedDriveList; +}; + +/** Convenience typedef. */ +typedef VBoxMainDriveInfo::DriveInfoList DriveInfoList; +/** Convenience typedef. */ +typedef VBoxMainDriveInfo::DriveInfo DriveInfo; + +/** Implementation of the hotplug waiter class below */ +class VBoxMainHotplugWaiterImpl +{ +public: + VBoxMainHotplugWaiterImpl(void) {} + virtual ~VBoxMainHotplugWaiterImpl(void) {} + /** @copydoc VBoxMainHotplugWaiter::Wait */ + virtual int Wait(RTMSINTERVAL cMillies) = 0; + /** @copydoc VBoxMainHotplugWaiter::Interrupt */ + virtual void Interrupt(void) = 0; + /** @copydoc VBoxMainHotplugWaiter::getStatus */ + virtual int getStatus(void) = 0; +}; + +/** + * Class for waiting for a hotplug event. To use this class, create an + * instance and call the @a Wait() method, which blocks until an event or a + * user-triggered interruption occurs. Call @a Interrupt() to interrupt the + * wait before an event occurs. + */ +class VBoxMainHotplugWaiter +{ + /** Class implementation. */ + VBoxMainHotplugWaiterImpl *mImpl; +public: + /** Constructor. Responsible for selecting the implementation. */ + VBoxMainHotplugWaiter(const char *pcszDevicesRoot); + /** Destructor. */ + ~VBoxMainHotplugWaiter (void) + { + delete mImpl; + } + /** + * Wait for a hotplug event. + * + * @returns VINF_SUCCESS if an event occurred or if Interrupt() was called. + * @returns VERR_TRY_AGAIN if the wait failed but this might (!) be a + * temporary failure. + * @returns VERR_NOT_SUPPORTED if the wait failed and will definitely not + * succeed if retried. + * @returns Possibly other iprt status codes otherwise. + * @param cMillies How long to wait for at most. + */ + int Wait (RTMSINTERVAL cMillies) + { + return mImpl->Wait(cMillies); + } + /** + * Interrupts an active wait. In the current implementation, the wait + * may not return until up to two seconds after calling this method. + */ + void Interrupt (void) + { + mImpl->Interrupt(); + } + + int getStatus(void) + { + return mImpl ? mImpl->getStatus() : VERR_NO_MEMORY; + } +}; + +#endif /* !MAIN_INCLUDED_HostHardwareLinux_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/HostImpl.h b/src/VBox/Main/include/HostImpl.h new file mode 100644 index 00000000..9f231920 --- /dev/null +++ b/src/VBox/Main/include/HostImpl.h @@ -0,0 +1,227 @@ +/* $Id: HostImpl.h $ */ +/** @file + * Implementation of IHost. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostImpl_h +#define MAIN_INCLUDED_HostImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "HostWrap.h" + +class HostUSBDeviceFilter; +class USBProxyService; +class SessionMachine; +class Progress; +class PerformanceCollector; +class HostDrive; +class HostDrivePartition; + +namespace settings +{ + struct Host; +} + +#include <list> + +class ATL_NO_VTABLE Host : + public HostWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(Host) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(VirtualBox *aParent); + void uninit(); + + // public methods only for internal purposes + + /** + * Override of the default locking class to be used for validating lock + * order with the standard member lock handle. + */ + virtual VBoxLockingClass getLockingClass() const + { + return LOCKCLASS_HOSTOBJECT; + } + + HRESULT i_loadSettings(const settings::Host &data); + HRESULT i_saveSettings(settings::Host &data); + + void i_updateProcessorFeatures(); + + HRESULT i_getDrives(DeviceType_T mediumType, bool fRefresh, MediaList *&pll, AutoWriteLock &treeLock); + HRESULT i_findHostDriveById(DeviceType_T mediumType, const Guid &uuid, bool fRefresh, ComObjPtr<Medium> &pMedium); + HRESULT i_findHostDriveByName(DeviceType_T mediumType, const Utf8Str &strLocationFull, bool fRefresh, ComObjPtr<Medium> &pMedium); + +#ifdef VBOX_WITH_USB + typedef std::list< ComObjPtr<HostUSBDeviceFilter> > USBDeviceFilterList; + + /** Must be called from under this object's lock. */ + USBProxyService* i_usbProxyService(); + + HRESULT i_addChild(HostUSBDeviceFilter *pChild); + HRESULT i_removeChild(HostUSBDeviceFilter *pChild); + VirtualBox* i_parent(); + + HRESULT i_onUSBDeviceFilterChange(HostUSBDeviceFilter *aFilter, BOOL aActiveChanged = FALSE); + void i_getUSBFilters(USBDeviceFilterList *aGlobalFiltes); + HRESULT i_checkUSBProxyService(); +#endif /* !VBOX_WITH_USB */ + + static void i_generateMACAddress(Utf8Str &mac); + +#ifdef RT_OS_WINDOWS + HRESULT i_updatePersistentConfigForHostOnlyAdapters(void); + HRESULT i_removePersistentConfig(const Bstr &bstrGuid); +#endif /* RT_OS_WINDOWS */ + + +private: + + // wrapped IHost properties + HRESULT getDVDDrives(std::vector<ComPtr<IMedium> > &aDVDDrives); + HRESULT getFloppyDrives(std::vector<ComPtr<IMedium> > &aFloppyDrives); + HRESULT getAudioDevices(std::vector<ComPtr<IHostAudioDevice> > &aAudioDevices); + HRESULT getUSBDevices(std::vector<ComPtr<IHostUSBDevice> > &aUSBDevices); + HRESULT getUSBDeviceFilters(std::vector<ComPtr<IHostUSBDeviceFilter> > &aUSBDeviceFilters); + HRESULT getNetworkInterfaces(std::vector<ComPtr<IHostNetworkInterface> > &aNetworkInterfaces); + HRESULT getNameServers(std::vector<com::Utf8Str> &aNameServers); + HRESULT getDomainName(com::Utf8Str &aDomainName); + HRESULT getSearchStrings(std::vector<com::Utf8Str> &aSearchStrings); + HRESULT getProcessorCount(ULONG *aProcessorCount); + HRESULT getProcessorOnlineCount(ULONG *aProcessorOnlineCount); + HRESULT getProcessorCoreCount(ULONG *aProcessorCoreCount); + HRESULT getProcessorOnlineCoreCount(ULONG *aProcessorOnlineCoreCount); + HRESULT getHostDrives(std::vector<ComPtr<IHostDrive> > &aHostDrives); + HRESULT getMemorySize(ULONG *aMemorySize); + HRESULT getMemoryAvailable(ULONG *aMemoryAvailable); + HRESULT getOperatingSystem(com::Utf8Str &aOperatingSystem); + HRESULT getOSVersion(com::Utf8Str &aOSVersion); + HRESULT getUTCTime(LONG64 *aUTCTime); + HRESULT getAcceleration3DAvailable(BOOL *aAcceleration3DAvailable); + HRESULT getVideoInputDevices(std::vector<ComPtr<IHostVideoInputDevice> > &aVideoInputDevices); + HRESULT getUpdateHost(ComPtr<IUpdateAgent> &aUpdate); + HRESULT getUpdateExtPack(ComPtr<IUpdateAgent> &aUpdate); + HRESULT getUpdateGuestAdditions(ComPtr<IUpdateAgent> &aUpdate); + HRESULT getUpdateResponse(BOOL *aUpdateNeeded); + HRESULT getUpdateVersion(com::Utf8Str &aUpdateVersion); + HRESULT getUpdateURL(com::Utf8Str &aUpdateURL); + HRESULT getUpdateCheckNeeded(BOOL *aUpdateCheckNeeded); + + // wrapped IHost methods + HRESULT getProcessorSpeed(ULONG aCpuId, + ULONG *aSpeed); + HRESULT getProcessorFeature(ProcessorFeature_T aFeature, + BOOL *aSupported); + HRESULT getProcessorDescription(ULONG aCpuId, + com::Utf8Str &aDescription); + HRESULT getProcessorCPUIDLeaf(ULONG aCpuId, + ULONG aLeaf, + ULONG aSubLeaf, + ULONG *aValEax, + ULONG *aValEbx, + ULONG *aValEcx, + ULONG *aValEdx); + HRESULT createHostOnlyNetworkInterface(ComPtr<IHostNetworkInterface> &aHostInterface, + ComPtr<IProgress> &aProgress); + HRESULT removeHostOnlyNetworkInterface(const com::Guid &aId, + ComPtr<IProgress> &aProgress); + HRESULT createUSBDeviceFilter(const com::Utf8Str &aName, + ComPtr<IHostUSBDeviceFilter> &aFilter); + HRESULT insertUSBDeviceFilter(ULONG aPosition, + const ComPtr<IHostUSBDeviceFilter> &aFilter); + HRESULT removeUSBDeviceFilter(ULONG aPosition); + HRESULT findHostDVDDrive(const com::Utf8Str &aName, + ComPtr<IMedium> &aDrive); + HRESULT findHostFloppyDrive(const com::Utf8Str &aName, + ComPtr<IMedium> &aDrive); + HRESULT findHostNetworkInterfaceByName(const com::Utf8Str &aName, + ComPtr<IHostNetworkInterface> &aNetworkInterface); + HRESULT findHostNetworkInterfaceById(const com::Guid &aId, + ComPtr<IHostNetworkInterface> &aNetworkInterface); + HRESULT findHostNetworkInterfacesOfType(HostNetworkInterfaceType_T aType, + std::vector<ComPtr<IHostNetworkInterface> > &aNetworkInterfaces); + HRESULT findUSBDeviceById(const com::Guid &aId, + ComPtr<IHostUSBDevice> &aDevice); + HRESULT findUSBDeviceByAddress(const com::Utf8Str &aName, + ComPtr<IHostUSBDevice> &aDevice); + HRESULT generateMACAddress(com::Utf8Str &aAddress); + + HRESULT addUSBDeviceSource(const com::Utf8Str &aBackend, const com::Utf8Str &aId, const com::Utf8Str &aAddress, + const std::vector<com::Utf8Str> &aPropertyNames, const std::vector<com::Utf8Str> &aPropertyValues); + + HRESULT removeUSBDeviceSource(const com::Utf8Str &aId); + + // Internal Methods. + + HRESULT i_buildDVDDrivesList(MediaList &list); + HRESULT i_buildFloppyDrivesList(MediaList &list); + HRESULT i_findHostDriveByNameOrId(DeviceType_T mediumType, const Utf8Str &strNameOrId, ComObjPtr<Medium> &pMedium); + +#if defined(RT_OS_SOLARIS) && defined(VBOX_USE_LIBHAL) + bool i_getDVDInfoFromHal(std::list< ComObjPtr<Medium> > &list); + bool i_getFloppyInfoFromHal(std::list< ComObjPtr<Medium> > &list); + HRESULT i_getFixedDrivesFromHal(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &list) RT_NOEXCEPT; +#endif + +#if defined(RT_OS_SOLARIS) + void i_getDVDInfoFromDevTree(std::list< ComObjPtr<Medium> > &list); + void i_parseMountTable(char *mountTable, std::list< ComObjPtr<Medium> > &list); + bool i_validateDevice(const char *deviceNode, bool isCDROM); + HRESULT i_getFixedDrivesFromDevTree(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &list) RT_NOEXCEPT; +#endif + + HRESULT i_updateNetIfList(); + +#ifndef RT_OS_WINDOWS + HRESULT i_parseResolvConf(); +#else + HRESULT i_fetchNameResolvingInformation(); +#endif + +#ifdef VBOX_WITH_RESOURCE_USAGE_API + void i_registerMetrics(PerformanceCollector *aCollector); + void i_registerDiskMetrics(PerformanceCollector *aCollector); + void i_unregisterMetrics(PerformanceCollector *aCollector); +#endif /* VBOX_WITH_RESOURCE_USAGE_API */ + +#ifdef RT_OS_WINDOWS + HRESULT i_getFixedDrivesFromGlobalNamespace(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &aDriveList) RT_NOEXCEPT; +#endif + HRESULT i_getDrivesPathsList(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &aDriveList) RT_NOEXCEPT; + + struct Data; // opaque data structure, defined in HostImpl.cpp + Data *m; +}; + +#endif /* !MAIN_INCLUDED_HostImpl_h */ + diff --git a/src/VBox/Main/include/HostNetworkInterfaceImpl.h b/src/VBox/Main/include/HostNetworkInterfaceImpl.h new file mode 100644 index 00000000..262e037f --- /dev/null +++ b/src/VBox/Main/include/HostNetworkInterfaceImpl.h @@ -0,0 +1,145 @@ +/* $Id: HostNetworkInterfaceImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostNetworkInterfaceImpl_h +#define MAIN_INCLUDED_HostNetworkInterfaceImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "HostNetworkInterfaceWrap.h" + +#ifdef VBOX_WITH_HOSTNETIF_API +struct NETIFINFO; +#endif + +class PerformanceCollector; + +class ATL_NO_VTABLE HostNetworkInterface : + public HostNetworkInterfaceWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(HostNetworkInterface) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Utf8Str aInterfaceName, Utf8Str aShortName, Guid aGuid, HostNetworkInterfaceType_T ifType); +#ifdef VBOX_WITH_HOSTNETIF_API + HRESULT init(Utf8Str aInterfaceName, HostNetworkInterfaceType_T ifType, struct NETIFINFO *pIfs); + HRESULT updateConfig(); +#endif + + HRESULT i_setVirtualBox(VirtualBox *pVirtualBox); +#ifdef RT_OS_WINDOWS + HRESULT i_updatePersistentConfig(); +#endif /* RT_OS_WINDOWS */ + +#ifdef VBOX_WITH_RESOURCE_USAGE_API + void i_registerMetrics(PerformanceCollector *aCollector, ComPtr<IUnknown> objptr); + void i_unregisterMetrics(PerformanceCollector *aCollector, ComPtr<IUnknown> objptr); +#endif + +private: + + // Wrapped IHostNetworkInterface properties + HRESULT getName(com::Utf8Str &aName); + HRESULT getShortName(com::Utf8Str &aShortName); + HRESULT getId(com::Guid &aGuiId); + HRESULT getDHCPEnabled(BOOL *aDHCPEnabled); + HRESULT getIPAddress(com::Utf8Str &aIPAddress); + HRESULT getNetworkMask(com::Utf8Str &aNetworkMask); + HRESULT getIPV6Supported(BOOL *aIPV6Supported); + HRESULT getIPV6Address(com::Utf8Str &aIPV6Address); + HRESULT getIPV6NetworkMaskPrefixLength(ULONG *aIPV6NetworkMaskPrefixLength); + HRESULT getHardwareAddress(com::Utf8Str &aHardwareAddress); + HRESULT getMediumType(HostNetworkInterfaceMediumType_T *aType); + HRESULT getStatus(HostNetworkInterfaceStatus_T *aStatus); + HRESULT getInterfaceType(HostNetworkInterfaceType_T *aType); + HRESULT getNetworkName(com::Utf8Str &aNetworkName); + HRESULT getWireless(BOOL *aWireless); + + // Wrapped IHostNetworkInterface methods + HRESULT enableStaticIPConfig(const com::Utf8Str &aIPAddress, + const com::Utf8Str &aNetworkMask); + HRESULT enableStaticIPConfigV6(const com::Utf8Str &aIPV6Address, + ULONG aIPV6NetworkMaskPrefixLength); + HRESULT enableDynamicIPConfig(); + HRESULT dHCPRediscover(); + + Utf8Str i_composeNetworkName(const Utf8Str szShortName); + +#if defined(RT_OS_WINDOWS) + HRESULT eraseAdapterConfigParameter(const char *szParamName); + HRESULT saveAdapterConfigParameter(const char *szParamName, const Utf8Str& strValue); + HRESULT saveAdapterConfigIPv4Dhcp(); + HRESULT saveAdapterConfigIPv4(ULONG addr, ULONG mask); + HRESULT saveAdapterConfigIPv6(const Utf8Str& addr, ULONG prefix); + HRESULT saveAdapterConfig(); + bool isInConfigFile(); +#endif /* defined(RT_OS_WINDOWS) */ + + const Utf8Str mInterfaceName; + const Guid mGuid; + const Utf8Str mNetworkName; + const Utf8Str mShortName; + HostNetworkInterfaceType_T mIfType; + + VirtualBox * const mVirtualBox; + + struct Data + { + Data() : IPAddress(0), networkMask(0), dhcpEnabled(FALSE), + mediumType(HostNetworkInterfaceMediumType_Unknown), + status(HostNetworkInterfaceStatus_Down), wireless(FALSE){} + + ULONG IPAddress; + ULONG networkMask; + Utf8Str IPV6Address; + ULONG IPV6NetworkMaskPrefixLength; + ULONG realIPAddress; + ULONG realNetworkMask; + Utf8Str realIPV6Address; + ULONG realIPV6PrefixLength; + BOOL dhcpEnabled; + Utf8Str hardwareAddress; + HostNetworkInterfaceMediumType_T mediumType; + HostNetworkInterfaceStatus_T status; + ULONG speedMbits; + BOOL wireless; + } m; + +}; + +typedef std::list<ComObjPtr<HostNetworkInterface> > HostNetworkInterfaceList; + +#endif /* !MAIN_INCLUDED_HostNetworkInterfaceImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/HostOnlyNetworkImpl.h b/src/VBox/Main/include/HostOnlyNetworkImpl.h new file mode 100644 index 00000000..c71338de --- /dev/null +++ b/src/VBox/Main/include/HostOnlyNetworkImpl.h @@ -0,0 +1,80 @@ +/* $Id: HostOnlyNetworkImpl.h $ */ +/** @file + * IHostOnlyNetwork implementation header, lives in VBoxSVC. + */ + +/* + * Copyright (C) 2021-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostOnlyNetworkImpl_h +#define MAIN_INCLUDED_HostOnlyNetworkImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "HostOnlyNetworkWrap.h" + +namespace settings +{ + struct HostOnlyNetwork; +} + +class ATL_NO_VTABLE HostOnlyNetwork : + public HostOnlyNetworkWrap +{ +public: + + DECLARE_EMPTY_CTOR_DTOR(HostOnlyNetwork) + + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT init(VirtualBox *aVirtualBox, com::Utf8Str aName); + HRESULT i_loadSettings(const settings::HostOnlyNetwork &data); + void uninit(); + HRESULT i_saveSettings(settings::HostOnlyNetwork &data); + + // Internal methods + // Utf8Str i_getNetworkName(); + // Utf8Str i_getNetworkId(); +private: + + // Wrapped IHostOnlyNetwork properties + HRESULT getNetworkName(com::Utf8Str &aNetworkName); + HRESULT setNetworkName(const com::Utf8Str &aNetworkName); + HRESULT getNetworkMask(com::Utf8Str &aNetworkMask); + HRESULT setNetworkMask(const com::Utf8Str &aNetworkMask); + HRESULT getEnabled(BOOL *aEnabled); + HRESULT setEnabled(BOOL aEnabled); + HRESULT getHostIP(com::Utf8Str &aHostIP); + HRESULT getLowerIP(com::Utf8Str &aLowerIP); + HRESULT setLowerIP(const com::Utf8Str &aLowerIP); + HRESULT getUpperIP(com::Utf8Str &aUpperIP); + HRESULT setUpperIP(const com::Utf8Str &aUpperIP); + HRESULT getId(com::Guid &aId); + HRESULT setId(const com::Guid &aId); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_HostOnlyNetworkImpl_h */ diff --git a/src/VBox/Main/include/HostPower.h b/src/VBox/Main/include/HostPower.h new file mode 100644 index 00000000..e157d6da --- /dev/null +++ b/src/VBox/Main/include/HostPower.h @@ -0,0 +1,136 @@ +/* $Id: HostPower.h $ */ +/** @file + * + * VirtualBox interface to host's power notification service + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostPower_h +#define MAIN_INCLUDED_HostPower_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifdef RT_OS_DARWIN /* first, so we can undef pVM in iprt/cdefs.h */ +# include <IOKit/pwr_mgt/IOPMLib.h> +# include <Carbon/Carbon.h> +#endif + +#include "VirtualBoxBase.h" + +#include <vector> + +#ifdef RT_OS_LINUX +# include <VBox/dbus.h> +#endif + +class HostPowerService +{ + public: + HostPowerService(VirtualBox *aVirtualBox); + virtual ~HostPowerService(); + void notify(Reason_T aReason); + + protected: + VirtualBox *mVirtualBox; + std::vector<ComPtr<IInternalSessionControl> > mSessionControls; +}; + +# if defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING) +/** + * The Windows hosted Power Service. + */ +class HostPowerServiceWin : public HostPowerService +{ +public: + + HostPowerServiceWin(VirtualBox *aVirtualBox); + virtual ~HostPowerServiceWin(); + +private: + + static DECLCALLBACK(int) NotificationThread(RTTHREAD ThreadSelf, void *pInstance); + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + + HWND mHwnd; + RTTHREAD mThread; +}; +# endif +# if defined(RT_OS_LINUX) || defined(DOXYGEN_RUNNING) +/** + * The Linux hosted Power Service. + */ +class HostPowerServiceLinux : public HostPowerService +{ +public: + + HostPowerServiceLinux(VirtualBox *aVirtualBox); + virtual ~HostPowerServiceLinux(); + +private: + + static DECLCALLBACK(int) powerChangeNotificationThread(RTTHREAD ThreadSelf, void *pInstance); + + /* Private member vars */ + /** Our message thread. */ + RTTHREAD mThread; + /** Our (private) connection to the DBus. Closing this will cause the + * message thread to exit. */ + DBusConnection *mpConnection; +}; + +# endif +# if defined(RT_OS_DARWIN) || defined(DOXYGEN_RUNNING) +/** + * The Darwin hosted Power Service. + */ +class HostPowerServiceDarwin : public HostPowerService +{ +public: + + HostPowerServiceDarwin(VirtualBox *aVirtualBox); + virtual ~HostPowerServiceDarwin(); + +private: + + static DECLCALLBACK(int) powerChangeNotificationThread(RTTHREAD ThreadSelf, void *pInstance); + static void powerChangeNotificationHandler(void *pvData, io_service_t service, natural_t messageType, void *pMessageArgument); + static void lowPowerHandler(void *pvData); + + void checkBatteryCriticalLevel(bool *pfCriticalChanged = NULL); + + /* Private member vars */ + RTTHREAD mThread; /* Our message thread. */ + + io_connect_t mRootPort; /* A reference to the Root Power Domain IOService */ + IONotificationPortRef mNotifyPort; /* Notification port allocated by IORegisterForSystemPower */ + io_object_t mNotifierObject; /* Notifier object, used to deregister later */ + CFRunLoopRef mRunLoop; /* A reference to the local thread run loop */ + + bool mCritical; /* Indicate if the battery was in the critical state last checked */ +}; +# endif + +#endif /* !MAIN_INCLUDED_HostPower_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/HostUSBDeviceImpl.h b/src/VBox/Main/include/HostUSBDeviceImpl.h new file mode 100644 index 00000000..431abb7b --- /dev/null +++ b/src/VBox/Main/include/HostUSBDeviceImpl.h @@ -0,0 +1,327 @@ +/* $Id: HostUSBDeviceImpl.h $ */ +/** @file + * VirtualBox IHostUSBDevice COM interface implementation. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostUSBDeviceImpl_h +#define MAIN_INCLUDED_HostUSBDeviceImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxBase.h" +#include "USBDeviceFilterImpl.h" +#include <VBox/usb.h> +#include "HostUSBDeviceWrap.h" + +class SessionMachine; +class USBProxyBackend; + +/** + * The unified state machine of HostUSBDevice. + * + * This is a super set of USBDEVICESTATE / USBDeviceState_T that + * includes additional states for tracking state transitions. + * + * @remarks + * The CapturingForVM and CapturingForProxy states have been merged + * into Capturing with a destination state (AttachingToVM or HeldByProxy). + * + * The DetachingFromVM state is a merge of DetachingFromVMToProxy and + * DetachingFromVMToHost and uses the destination state (HeldByProxy + * or ReleasingToHost) like Capturing. + * + * The *AwaitingDetach and *AwaitingReattach substates (optionally used + * in Capturing, AttachingToVM, DetachingFromVM and ReleasingToHost) are + * implemented via a substate kHostUSBDeviceSubState. + */ +typedef enum +{ + /** The device is unsupported (HUB). + * Next Host: PhysDetached. + * Next VBox: No change permitted. + */ + kHostUSBDeviceState_Unsupported = USBDEVICESTATE_UNSUPPORTED, + /** The device is used exclusivly by the host or is inaccessible for some other reason. + * Next Host: Capturable, Unused, PhysDetached. + * Run filters. + * Next VBox: No change permitted. + */ + kHostUSBDeviceState_UsedByHost = USBDEVICESTATE_USED_BY_HOST, + /** The device is used by the host but can be captured. + * Next Host: Unsupported, UsedByHost, Unused, PhysDetached. + * Run filters if Unused (for wildcard filters). + * Next VBox: CapturingForVM, CapturingForProxy. + */ + kHostUSBDeviceState_Capturable = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE, + /** The device is not used by the host and can be captured. + * Next Host: UsedByHost, Capturable, PhysDetached + * Don't run any filters (done on state entry). + * Next VBox: CapturingForVM, CapturingForProxy. + */ + kHostUSBDeviceState_Unused = USBDEVICESTATE_UNUSED, + /** The device is held captive by the proxy. + * Next Host: PhysDetached + * Next VBox: ReleasingHeld, AttachingToVM + */ + kHostUSBDeviceState_HeldByProxy = USBDEVICESTATE_HELD_BY_PROXY, + /** The device is in use by a VM. + * Next Host: PhysDetachingFromVM + * Next VBox: DetachingFromVM + */ + kHostUSBDeviceState_UsedByVM = USBDEVICESTATE_USED_BY_GUEST, + /** The device has been detach from both the host and VMs. + * This is the final state. */ + kHostUSBDeviceState_PhysDetached = 9, + + + /** The start of the transitional states. */ + kHostUSBDeviceState_FirstTransitional, + + /** The device is being seized from the host, either for HeldByProxy or for AttachToVM. + * + * On some hosts we will need to re-enumerate the in which case the sub-state + * is employed to track this progress. On others, this is synchronous or faked, and + * will will then leave the device in this state and poke the service thread to do + * the completion state change. + * + * Next Host: PhysDetached. + * Next VBox: HeldByProxy or AttachingToVM on success, + * previous state (Unused or Capturable) or UsedByHost on failure. + */ + kHostUSBDeviceState_Capturing = kHostUSBDeviceState_FirstTransitional, + + /** The device is being released back to the host, following VM or Proxy usage. + * Most hosts needs to re-enumerate the device and will therefore employ the + * sub-state as during capturing. On the others we'll just leave it to the usb + * service thread to advance the device state. + * + * Next Host: Unused, UsedByHost, Capturable. + * No filters. + * Next VBox: PhysDetached (timeout), HeldByProxy (failure). + */ + kHostUSBDeviceState_ReleasingToHost, + + /** The device is being attached to a VM. + * + * This requires IPC to the VM and we will not advance the state until + * that completes. + * + * Next Host: PhysDetachingFromVM. + * Next VBox: UsedByGuest, HeldByProxy (failure). + */ + kHostUSBDeviceState_AttachingToVM, + + /** The device is being detached from a VM and will be returned to the proxy or host. + * + * This involves IPC and may or may not also require re-enumeration of the + * device. Which means that it might transition directly into the ReleasingToHost state + * because the client (VM) will do the actual re-enumeration. + * + * Next Host: PhysDetachingFromVM (?) or just PhysDetached. + * Next VBox: ReleasingToHost, HeldByProxy. + */ + kHostUSBDeviceState_DetachingFromVM, + + /** The device has been physically removed while a VM used it. + * + * This is the device state while VBoxSVC is doing IPC to the client (VM) telling it + * to detach it. + * + * Next Host: None. + * Next VBox: PhysDetached + */ + kHostUSBDeviceState_PhysDetachingFromVM, + + /** Just an invalid state value for use as default for some methods. */ + kHostUSBDeviceState_Invalid = 0x7fff +} HostUSBDeviceState; + + +/** + * Sub-state for dealing with device re-enumeration. + */ +typedef enum +{ + /** Not in any sub-state. */ + kHostUSBDeviceSubState_Default = 0, + /** Awaiting a logical device detach following a device re-enumeration. */ + kHostUSBDeviceSubState_AwaitingDetach, + /** Awaiting a logical device re-attach following a device re-enumeration. */ + kHostUSBDeviceSubState_AwaitingReAttach +} HostUSBDeviceSubState; + + +/** + * Object class used to hold Host USB Device properties. + */ +class ATL_NO_VTABLE HostUSBDevice : + public HostUSBDeviceWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(HostUSBDevice) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(PUSBDEVICE aUsb, USBProxyBackend *aUSBProxyBackend); + void uninit(); + + // public methods only for internal purposes + + /** @note Must be called from under the object read lock. */ + const Guid& i_getId() const { return mId; } + + /** @note Must be called from under the object read lock. */ + HostUSBDeviceState i_getUnistate() const { return mUniState; } + + /** @note Must be called from under the object read lock. */ + const char *i_getStateName() { return i_stateName (mUniState, mPendingUniState, mUniSubState); } + + /** @note Must be called from under the object read lock. */ + bool i_isCapturableOrHeld() + { + return mUniState == kHostUSBDeviceState_Unused + || mUniState == kHostUSBDeviceState_Capturable + || mUniState == kHostUSBDeviceState_HeldByProxy; + } + + /** @note Must be called from under the object read lock. */ + ComObjPtr<SessionMachine> &i_getMachine() { return mMachine; } + + /** @note Must be called from under the object read lock. */ + PCUSBDEVICE i_getUsbData() const { return mUsb; } + + USBProxyBackend *i_getUsbProxyBackend() const { return mUSBProxyBackend; } + + com::Utf8Str i_getName(); + + HRESULT i_requestCaptureForVM(SessionMachine *aMachine, bool aSetError, + const com::Utf8Str &aCaptureFilename, ULONG aMaskedIfs = 0); + HRESULT i_onDetachFromVM(SessionMachine *aMachine, bool aDone, bool *aRunFilters, bool aAbnormal = false); + HRESULT i_requestReleaseToHost(); + HRESULT i_requestHold(); + bool i_wasActuallyDetached(); + void i_onPhysicalDetached(); + + bool i_isMatch(const USBDeviceFilter::BackupableUSBDeviceFilterData &aData); + int i_compare(PCUSBDEVICE aDev2); + static int i_compare(PCUSBDEVICE aDev1, PCUSBDEVICE aDev2, bool aIsAwaitingReAttach = false); + + bool i_updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMachine **aIgnoreMachine); + bool i_updateStateFake(PCUSBDEVICE aDev, bool *aRunFilters, SessionMachine **aIgnoreMachine); + + static const char *i_stateName(HostUSBDeviceState aState, + HostUSBDeviceState aPendingState = kHostUSBDeviceState_Invalid, + HostUSBDeviceSubState aSubState = kHostUSBDeviceSubState_Default); + + void *i_getBackendUserData() { return m_pvBackendUser; } + void i_setBackendUserData(void *pvBackendUser) { m_pvBackendUser = pvBackendUser; } + +protected: + + HRESULT i_attachToVM(SessionMachine *aMachine, const com::Utf8Str &aCaptureFilename, ULONG aMaskedIfs = 0); + void i_detachFromVM(HostUSBDeviceState aFinalState); + void i_onPhysicalDetachedInternal(); + bool i_hasAsyncOperationTimedOut() const; + + bool i_setState (HostUSBDeviceState aNewState, HostUSBDeviceState aNewPendingState = kHostUSBDeviceState_Invalid, + HostUSBDeviceSubState aNewSubState = kHostUSBDeviceSubState_Default); + bool i_startTransition (HostUSBDeviceState aNewState, HostUSBDeviceState aFinalState, + HostUSBDeviceSubState aNewSubState = kHostUSBDeviceSubState_Default); + bool i_advanceTransition(bool aSkipReAttach = false); + bool i_failTransition(HostUSBDeviceState a_enmStateHint); + USBDeviceState_T i_canonicalState() const; + +private: + + // wrapped IUSBDevice properties + HRESULT getId(com::Guid &aId); + HRESULT getVendorId(USHORT *aVendorId); + HRESULT getProductId(USHORT *aProductId); + HRESULT getRevision(USHORT *aRevision); + HRESULT getManufacturer(com::Utf8Str &aManufacturer); + HRESULT getProduct(com::Utf8Str &aProduct); + HRESULT getSerialNumber(com::Utf8Str &aSerialNumber); + HRESULT getAddress(com::Utf8Str &aAddress); + HRESULT getPort(USHORT *aPort); + HRESULT getPortPath(com::Utf8Str &aPortPath); + HRESULT getVersion(USHORT *aVersion); + HRESULT getPortVersion(USHORT *aPortVersion); + HRESULT getSpeed(USBConnectionSpeed_T *aSpeed); + HRESULT getRemote(BOOL *aRemote); + HRESULT getState(USBDeviceState_T *aState); + HRESULT getBackend(com::Utf8Str &aBackend); + HRESULT getDeviceInfo(std::vector<com::Utf8Str> &aInfo); + + + const Guid mId; + + /** @name The state machine variables + * Only setState(), init() and uninit() will modify these members! + * @{ */ + /** The RTTimeNanoTS() corresponding to the last state change. + * + * Old state machine: RTTimeNanoTS() of when mIsStatePending was set or mDetaching changed + * from kNotDetaching. For operations that cannot be canceled it's 0. */ + uint64_t mLastStateChangeTS; + /** Current state. */ + HostUSBDeviceState mUniState; + /** Sub-state for tracking re-enumeration. */ + HostUSBDeviceSubState mUniSubState; + /** The final state of an pending transition. + * This is mainly a measure to reduce the number of HostUSBDeviceState values. */ + HostUSBDeviceState mPendingUniState; + /** Previous state. + * This is used for bailing out when a transition like capture fails. */ + HostUSBDeviceState mPrevUniState; + /** Indicator set by onDetachedPhys and check when advancing a transitional state. */ + bool mIsPhysicallyDetached; + /** @} */ + + /** The machine the usb device is (being) attached to. */ + ComObjPtr<SessionMachine> mMachine; + /** Pointer to the USB Proxy Backend instance. */ + USBProxyBackend *mUSBProxyBackend; + /** Pointer to the USB Device structure owned by this device. + * Only used for host devices. */ + PUSBDEVICE mUsb; + /** The interface mask to be used in the pending capture. + * This is a filter property. */ + ULONG mMaskedIfs; + /** The name of this device. */ + Utf8Str mNameObj; + /** The name of this device (for logging purposes). + * This points to the string in mNameObj. */ + const char *mName; + /** The filename to capture the USB traffic to. */ + com::Utf8Str mCaptureFilename; + /** Optional opaque user data assigned by the USB proxy backend owning the device. */ + void *m_pvBackendUser; +}; + +#endif /* !MAIN_INCLUDED_HostUSBDeviceImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/HostVideoInputDeviceImpl.h b/src/VBox/Main/include/HostVideoInputDeviceImpl.h new file mode 100644 index 00000000..7cac928b --- /dev/null +++ b/src/VBox/Main/include/HostVideoInputDeviceImpl.h @@ -0,0 +1,82 @@ +/* $Id: HostVideoInputDeviceImpl.h $ */ +/** @file + * A host video capture device description. + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_HostVideoInputDeviceImpl_h +#define MAIN_INCLUDED_HostVideoInputDeviceImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "HostVideoInputDeviceWrap.h" + +#include <list> + +class HostVideoInputDevice; + +typedef std::list<ComObjPtr<HostVideoInputDevice> > HostVideoInputDeviceList; + +class ATL_NO_VTABLE HostVideoInputDevice : + public HostVideoInputDeviceWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(HostVideoInputDevice) + + HRESULT FinalConstruct(); + void FinalRelease(); + + /* Public initializer/uninitializer for internal purposes only. */ + HRESULT init(const com::Utf8Str &name, const com::Utf8Str &path, const com::Utf8Str &alias); + void uninit(); + + static HRESULT queryHostDevices(VirtualBox *pVirtualBox, HostVideoInputDeviceList *pList); + +private: + + // wrapped IHostVideoInputDevice properties + virtual HRESULT getName(com::Utf8Str &aName) { aName = m.name; return S_OK; } + virtual HRESULT getPath(com::Utf8Str &aPath) { aPath = m.path; return S_OK; } + virtual HRESULT getAlias(com::Utf8Str &aAlias) { aAlias = m.alias; return S_OK; } + + /* Data. */ + struct Data + { + Data() + { + } + + com::Utf8Str name; + com::Utf8Str path; + com::Utf8Str alias; + }; + + Data m; +}; + +#endif /* !MAIN_INCLUDED_HostVideoInputDeviceImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/KeyboardImpl.h b/src/VBox/Main/include/KeyboardImpl.h new file mode 100644 index 00000000..4eda3f6e --- /dev/null +++ b/src/VBox/Main/include/KeyboardImpl.h @@ -0,0 +1,110 @@ +/* $Id: KeyboardImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_KeyboardImpl_h +#define MAIN_INCLUDED_KeyboardImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "KeyboardWrap.h" +#include "EventImpl.h" + +#include <VBox/vmm/pdmdrv.h> + +/** Limit of simultaneously attached devices (just USB and/or PS/2). */ +enum { KEYBOARD_MAX_DEVICES = 2 }; + +/** Simple keyboard event class. */ +class KeyboardEvent +{ +public: + KeyboardEvent() : scan(-1) {} + KeyboardEvent(int _scan) : scan(_scan) {} + bool i_isValid() + { + return (scan & ~0x80) && !(scan & ~0xFF); + } + int scan; +}; +class Console; + +class ATL_NO_VTABLE Keyboard : + public KeyboardWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(Keyboard) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Console *aParent); + void uninit(); + + static const PDMDRVREG DrvReg; + + Console *i_getParent() const + { + return mParent; + } + +private: + + // Wrapped Keyboard properties + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + HRESULT getKeyboardLEDs(std::vector<KeyboardLED_T> &aKeyboardLEDs); + + // Wrapped Keyboard members + HRESULT putScancode(LONG aScancode); + HRESULT putScancodes(const std::vector<LONG> &aScancodes, + ULONG *aCodesStored); + HRESULT putCAD(); + HRESULT releaseKeys(); + HRESULT putUsageCode(LONG aUsageCode, LONG aUsagePage, BOOL fKeyRelease); + + static DECLCALLBACK(void) i_keyboardLedStatusChange(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds); + static DECLCALLBACK(void) i_keyboardSetActive(PPDMIKEYBOARDCONNECTOR pInterface, bool fActive); + static DECLCALLBACK(void *) i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); + static DECLCALLBACK(int) i_drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) i_drvDestruct(PPDMDRVINS pDrvIns); + + void onKeyboardLedsChange(PDMKEYBLEDS enmLeds); + + Console * const mParent; + /** Pointer to the associated keyboard driver(s). */ + struct DRVMAINKEYBOARD *mpDrv[KEYBOARD_MAX_DEVICES]; + + /* The current guest keyboard LED status. */ + PDMKEYBLEDS menmLeds; + + const ComObjPtr<EventSource> mEventSource; +}; + +#endif /* !MAIN_INCLUDED_KeyboardImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/LoggingNew.h b/src/VBox/Main/include/LoggingNew.h new file mode 100644 index 00000000..b4917cb9 --- /dev/null +++ b/src/VBox/Main/include/LoggingNew.h @@ -0,0 +1,60 @@ +/* $Id: LoggingNew.h $ */ +/** @file + * VirtualBox COM - logging macros and function definitions, for new code. + */ + +/* + * Copyright (C) 2017-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_LoggingNew_h +#define MAIN_INCLUDED_LoggingNew_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifdef MAIN_INCLUDED_Logging_h +# error "You must include LoggingNew.h as the first include!" +#endif +#define MAIN_INCLUDED_Logging_h /* Prevent Logging.h from being included. */ + +#ifndef LOG_GROUP +# error "You must define LOG_GROUP immediately before including LoggingNew.h!" +#endif + +#ifdef LOG_GROUP_MAIN_OVERRIDE +# error "Please, don't define LOG_GROUP_MAIN_OVERRIDE anymore!" +#endif + +#include <VBox/log.h> + + +#ifndef VBOXSVC_LOG_DEFAULT +# define VBOXSVC_LOG_DEFAULT "all" +#endif + +#ifndef VBOXSDS_LOG_DEFAULT +# define VBOXSDS_LOG_DEFAULT "all" +#endif + +#endif /* !MAIN_INCLUDED_LoggingNew_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ + diff --git a/src/VBox/Main/include/MachineDebuggerImpl.h b/src/VBox/Main/include/MachineDebuggerImpl.h new file mode 100644 index 00000000..1bf40f0b --- /dev/null +++ b/src/VBox/Main/include/MachineDebuggerImpl.h @@ -0,0 +1,176 @@ +/* $Id: MachineDebuggerImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MachineDebuggerImpl_h +#define MAIN_INCLUDED_MachineDebuggerImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "MachineDebuggerWrap.h" +#include <iprt/log.h> +#include <VBox/vmm/em.h> + +class Console; +class Progress; + +class ATL_NO_VTABLE MachineDebugger : + public MachineDebuggerWrap +{ + +public: + + DECLARE_COMMON_CLASS_METHODS (MachineDebugger) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init (Console *aParent); + void uninit(); + + // "public-private methods" + void i_flushQueuedSettings(); + +private: + + // wrapped IMachineDeugger properties + HRESULT getSingleStep(BOOL *aSingleStep); + HRESULT setSingleStep(BOOL aSingleStep); + HRESULT getExecuteAllInIEM(BOOL *aExecuteAllInIEM); + HRESULT setExecuteAllInIEM(BOOL aExecuteAllInIEM); + HRESULT getLogEnabled(BOOL *aLogEnabled); + HRESULT setLogEnabled(BOOL aLogEnabled); + HRESULT getLogDbgFlags(com::Utf8Str &aLogDbgFlags); + HRESULT getLogDbgGroups(com::Utf8Str &aLogDbgGroups); + HRESULT getLogDbgDestinations(com::Utf8Str &aLogDbgDestinations); + HRESULT getLogRelFlags(com::Utf8Str &aLogRelFlags); + HRESULT getLogRelGroups(com::Utf8Str &aLogRelGroups); + HRESULT getLogRelDestinations(com::Utf8Str &aLogRelDestinations); + HRESULT getExecutionEngine(VMExecutionEngine_T *apenmEngine); + HRESULT getHWVirtExNestedPagingEnabled(BOOL *aHWVirtExNestedPagingEnabled); + HRESULT getHWVirtExVPIDEnabled(BOOL *aHWVirtExVPIDEnabled); + HRESULT getHWVirtExUXEnabled(BOOL *aHWVirtExUXEnabled); + HRESULT getOSName(com::Utf8Str &aOSName); + HRESULT getOSVersion(com::Utf8Str &aOSVersion); + HRESULT getPAEEnabled(BOOL *aPAEEnabled); + HRESULT getVirtualTimeRate(ULONG *aVirtualTimeRate); + HRESULT setVirtualTimeRate(ULONG aVirtualTimeRate); + HRESULT getUptime(LONG64 *aUptime); + + // wrapped IMachineDeugger methods + HRESULT dumpGuestCore(const com::Utf8Str &aFilename, + const com::Utf8Str &aCompression); + HRESULT dumpHostProcessCore(const com::Utf8Str &aFilename, + const com::Utf8Str &aCompression); + HRESULT info(const com::Utf8Str &aName, + const com::Utf8Str &aArgs, + com::Utf8Str &aInfo); + HRESULT injectNMI(); + HRESULT modifyLogGroups(const com::Utf8Str &aSettings); + HRESULT modifyLogFlags(const com::Utf8Str &aSettings); + HRESULT modifyLogDestinations(const com::Utf8Str &aSettings); + HRESULT readPhysicalMemory(LONG64 aAddress, + ULONG aSize, + std::vector<BYTE> &aBytes); + HRESULT writePhysicalMemory(LONG64 aAddress, + ULONG aSize, + const std::vector<BYTE> &aBytes); + HRESULT readVirtualMemory(ULONG aCpuId, + LONG64 aAddress, + ULONG aSize, + std::vector<BYTE> &aBytes); + HRESULT writeVirtualMemory(ULONG aCpuId, + LONG64 aAddress, + ULONG aSize, + const std::vector<BYTE> &aBytes); + HRESULT loadPlugIn(const com::Utf8Str &aName, + com::Utf8Str &aPlugInName); + HRESULT unloadPlugIn(const com::Utf8Str &aName); + HRESULT detectOS(com::Utf8Str &aOs); + HRESULT queryOSKernelLog(ULONG aMaxMessages, + com::Utf8Str &aDmesg); + HRESULT getRegister(ULONG aCpuId, + const com::Utf8Str &aName, + com::Utf8Str &aValue); + HRESULT getRegisters(ULONG aCpuId, + std::vector<com::Utf8Str> &aNames, + std::vector<com::Utf8Str> &aValues); + HRESULT setRegister(ULONG aCpuId, + const com::Utf8Str &aName, + const com::Utf8Str &aValue); + HRESULT setRegisters(ULONG aCpuId, + const std::vector<com::Utf8Str> &aNames, + const std::vector<com::Utf8Str> &aValues); + HRESULT dumpGuestStack(ULONG aCpuId, + com::Utf8Str &aStack); + HRESULT resetStats(const com::Utf8Str &aPattern); + HRESULT dumpStats(const com::Utf8Str &aPattern); + HRESULT getStats(const com::Utf8Str &aPattern, + BOOL aWithDescriptions, + com::Utf8Str &aStats); + HRESULT getCPULoad(ULONG aCpuId, ULONG *aPctExecuting, ULONG *aPctHalted, ULONG *aPctOther, LONG64 *aMsInterval) RT_OVERRIDE; + HRESULT takeGuestSample(const com::Utf8Str &aFilename, ULONG aUsInterval, LONG64 aUsSampleTime, ComPtr<IProgress> &pProgress); + HRESULT getUVMAndVMMFunctionTable(LONG64 aMagicVersion, LONG64 *aVMMFunctionTable, LONG64 *aUVM); + + // private methods + bool i_queueSettings() const; + HRESULT i_getEmExecPolicyProperty(EMEXECPOLICY enmPolicy, BOOL *pfEnforced); + HRESULT i_setEmExecPolicyProperty(EMEXECPOLICY enmPolicy, BOOL fEnforce); + + /** RTLogGetFlags, RTLogGetGroupSettings and RTLogGetDestinations function. */ + typedef DECLCALLBACKTYPE(int, FNLOGGETSTR,(PRTLOGGER, char *, size_t)); + /** Function pointer. */ + typedef FNLOGGETSTR *PFNLOGGETSTR; + HRESULT i_logStringProps(PRTLOGGER pLogger, PFNLOGGETSTR pfnLogGetStr, const char *pszLogGetStr, Utf8Str *pstrSettings); + + static DECLCALLBACK(int) i_dbgfProgressCallback(void *pvUser, unsigned uPercentage); + + Console * const mParent; + /** @name Flags whether settings have been queued because they could not be sent + * to the VM (not up yet, etc.) + * @{ */ + uint8_t maiQueuedEmExecPolicyParams[EMEXECPOLICY_END]; + int mSingleStepQueued; + int mLogEnabledQueued; + uint32_t mVirtualTimeRateQueued; + bool mFlushMode; + /** @} */ + + /** @name Sample report related things. + * @{ */ + /** Sample report handle. */ + DBGFSAMPLEREPORT m_hSampleReport; + /** Progress object for the currently taken guest sample. */ + ComObjPtr<Progress> m_Progress; + /** Filename to dump the report to. */ + com::Utf8Str m_strFilename; + /** @} */ +}; + +#endif /* !MAIN_INCLUDED_MachineDebuggerImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/MachineImpl.h b/src/VBox/Main/include/MachineImpl.h new file mode 100644 index 00000000..da911acf --- /dev/null +++ b/src/VBox/Main/include/MachineImpl.h @@ -0,0 +1,1691 @@ +/* $Id: MachineImpl.h $ */ +/** @file + * Implementation of IMachine in VBoxSVC - Header. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MachineImpl_h +#define MAIN_INCLUDED_MachineImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "AuthLibrary.h" +#include "VirtualBoxBase.h" +#include "ProgressImpl.h" +#include "VRDEServerImpl.h" +#include "MediumAttachmentImpl.h" +#include "PCIDeviceAttachmentImpl.h" +#include "MediumLock.h" +#include "NetworkAdapterImpl.h" +#include "AudioSettingsImpl.h" +#include "SerialPortImpl.h" +#include "ParallelPortImpl.h" +#include "BIOSSettingsImpl.h" +#include "RecordingSettingsImpl.h" +#include "GraphicsAdapterImpl.h" +#include "StorageControllerImpl.h" // required for MachineImpl.h to compile on Windows +#include "USBControllerImpl.h" // required for MachineImpl.h to compile on Windows +#include "BandwidthControlImpl.h" +#include "BandwidthGroupImpl.h" +#include "TrustedPlatformModuleImpl.h" +#include "NvramStoreImpl.h" +#include "GuestDebugControlImpl.h" +#ifdef VBOX_WITH_RESOURCE_USAGE_API +# include "Performance.h" +# include "PerformanceImpl.h" +#endif +#include "ThreadTask.h" + +// generated header +#include "SchemaDefs.h" + +#include "VBox/com/ErrorInfo.h" + +#include <iprt/time.h> +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION +# include <VBox/VBoxCryptoIf.h> +# include <iprt/vfs.h> +#endif + +#include <list> +#include <vector> + +#include "MachineWrap.h" + +/** @todo r=klaus after moving the various Machine settings structs to + * MachineImpl.cpp it should be possible to eliminate this include. */ +#include <VBox/settings.h> + +// defines +//////////////////////////////////////////////////////////////////////////////// + +// helper declarations +//////////////////////////////////////////////////////////////////////////////// + +class Progress; +class ProgressProxy; +class Keyboard; +class Mouse; +class Display; +class MachineDebugger; +class USBController; +class USBDeviceFilters; +class Snapshot; +class SharedFolder; +class HostUSBDevice; +class StorageController; +class SessionMachine; +#ifdef VBOX_WITH_UNATTENDED +class Unattended; +#endif + +// Machine class +//////////////////////////////////////////////////////////////////////////////// +// +class ATL_NO_VTABLE Machine : + public MachineWrap +{ + +public: + + enum StateDependency + { + AnyStateDep = 0, + MutableStateDep, + MutableOrSavedStateDep, + MutableOrRunningStateDep, + MutableOrSavedOrRunningStateDep, + }; + + /** + * Internal machine data. + * + * Only one instance of this data exists per every machine -- it is shared + * by the Machine, SessionMachine and all SnapshotMachine instances + * associated with the given machine using the util::Shareable template + * through the mData variable. + * + * @note |const| members are persistent during lifetime so can be + * accessed without locking. + * + * @note There is no need to lock anything inside init() or uninit() + * methods, because they are always serialized (see AutoCaller). + */ + struct Data + { + /** + * Data structure to hold information about sessions opened for the + * given machine. + */ + struct Session + { + /** Type of lock which created this session */ + LockType_T mLockType; + + /** Control of the direct session opened by lockMachine() */ + ComPtr<IInternalSessionControl> mDirectControl; + + typedef std::list<ComPtr<IInternalSessionControl> > RemoteControlList; + + /** list of controls of all opened remote sessions */ + RemoteControlList mRemoteControls; + + /** launchVMProcess() and OnSessionEnd() progress indicator */ + ComObjPtr<ProgressProxy> mProgress; + + /** + * PID of the session object that must be passed to openSession() + * to finalize the launchVMProcess() request (i.e., PID of the + * process created by launchVMProcess()) + */ + RTPROCESS mPID; + + /** Current session state */ + SessionState_T mState; + + /** Session name string (of the primary session) */ + Utf8Str mName; + + /** Session machine object */ + ComObjPtr<SessionMachine> mMachine; + + /** Medium object lock collection. */ + MediumLockListMap mLockedMedia; + }; + + Data(); + ~Data(); + + const Guid mUuid; + BOOL mRegistered; + + Utf8Str m_strConfigFile; + Utf8Str m_strConfigFileFull; + + // machine settings XML file + settings::MachineConfigFile *pMachineConfigFile; + uint32_t flModifications; + bool m_fAllowStateModification; + + BOOL mAccessible; + com::ErrorInfo mAccessError; + + MachineState_T mMachineState; + RTTIMESPEC mLastStateChange; + + /* Note: These are guarded by VirtualBoxBase::stateLockHandle() */ + uint32_t mMachineStateDeps; + RTSEMEVENTMULTI mMachineStateDepsSem; + uint32_t mMachineStateChangePending; + + BOOL mCurrentStateModified; + /** Guest properties have been modified and need saving since the + * machine was started, or there are transient properties which need + * deleting and the machine is being shut down. */ + BOOL mGuestPropertiesModified; + + Session mSession; + + ComObjPtr<Snapshot> mFirstSnapshot; + ComObjPtr<Snapshot> mCurrentSnapshot; + + // list of files to delete in Delete(); this list is filled by Unregister() + std::list<Utf8Str> llFilesToDelete; + +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION + /* Store for secret keys. */ + SecretKeyStore *mpKeyStore; + BOOL fEncrypted; + /* KeyId of the password encrypting the DEK */ + com::Utf8Str mstrKeyId; + /* Store containing the DEK used for encrypting the VM */ + com::Utf8Str mstrKeyStore; + /* KeyId of the password encrypting the DEK for log files */ + com::Utf8Str mstrLogKeyId; + /* Store containing the DEK used for encrypting the VM's log files */ + com::Utf8Str mstrLogKeyStore; +#endif + }; + + /** + * Saved state data. + * + * It's actually only the state file path string and its encryption + * settings, but it needs to be separate from Data, because Machine + * and SessionMachine instances share it, while SnapshotMachine does + * not. + * + * The data variable is |mSSData|. + */ + struct SSData + { + Utf8Str strStateFilePath; +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION + /* KeyId of the password encrypting the DEK for saved state */ + com::Utf8Str strStateKeyId; + /* Store containing the DEK used for encrypting saved state */ + com::Utf8Str strStateKeyStore; +#endif + }; + + /** + * User changeable machine data. + * + * This data is common for all machine snapshots, i.e. it is shared + * by all SnapshotMachine instances associated with the given machine + * using the util::Backupable template through the |mUserData| variable. + * + * SessionMachine instances can alter this data and discard changes. + * + * @note There is no need to lock anything inside init() or uninit() + * methods, because they are always serialized (see AutoCaller). + */ + struct UserData + { + settings::MachineUserData s; + }; + + /** + * Hardware data. + * + * This data is unique for a machine and for every machine snapshot. + * Stored using the util::Backupable template in the |mHWData| variable. + * + * SessionMachine instances can alter this data and discard changes. + * + * @todo r=klaus move all "pointer" objects out of this struct, as they + * need non-obvious handling when creating a new session or when taking + * a snapshot. Better do this right straight away, not relying on the + * template magic which doesn't work right in this case. + */ + struct HWData + { + /** + * Data structure to hold information about a guest property. + */ + struct GuestProperty { + /** Property value */ + Utf8Str strValue; + /** Property timestamp */ + LONG64 mTimestamp; + /** Property flags */ + ULONG mFlags; + }; + + HWData(); + ~HWData(); + + Bstr mHWVersion; + Guid mHardwareUUID; /**< If Null, use mData.mUuid. */ + ULONG mMemorySize; + ULONG mMemoryBalloonSize; + BOOL mPageFusionEnabled; + settings::RecordingSettings mRecordSettings; + BOOL mHWVirtExEnabled; + BOOL mHWVirtExNestedPagingEnabled; + BOOL mHWVirtExLargePagesEnabled; + BOOL mHWVirtExVPIDEnabled; + BOOL mHWVirtExUXEnabled; + BOOL mHWVirtExForceEnabled; + BOOL mHWVirtExUseNativeApi; + BOOL mHWVirtExVirtVmsaveVmload; + BOOL mPAEEnabled; + settings::Hardware::LongModeType mLongMode; + BOOL mTripleFaultReset; + BOOL mAPIC; + BOOL mX2APIC; + BOOL mIBPBOnVMExit; + BOOL mIBPBOnVMEntry; + BOOL mSpecCtrl; + BOOL mSpecCtrlByHost; + BOOL mL1DFlushOnSched; + BOOL mL1DFlushOnVMEntry; + BOOL mMDSClearOnSched; + BOOL mMDSClearOnVMEntry; + BOOL mNestedHWVirt; + ULONG mCPUCount; + BOOL mCPUHotPlugEnabled; + ULONG mCpuExecutionCap; + uint32_t mCpuIdPortabilityLevel; + Utf8Str mCpuProfile; + BOOL mHPETEnabled; + + BOOL mCPUAttached[SchemaDefs::MaxCPUCount]; + + std::list<settings::CpuIdLeaf> mCpuIdLeafList; + + DeviceType_T mBootOrder[SchemaDefs::MaxBootPosition]; + + typedef std::list<ComObjPtr<SharedFolder> > SharedFolderList; + SharedFolderList mSharedFolders; + + ClipboardMode_T mClipboardMode; + BOOL mClipboardFileTransfersEnabled; + + DnDMode_T mDnDMode; + + typedef std::map<Utf8Str, GuestProperty> GuestPropertyMap; + GuestPropertyMap mGuestProperties; + + FirmwareType_T mFirmwareType; + KeyboardHIDType_T mKeyboardHIDType; + PointingHIDType_T mPointingHIDType; + ChipsetType_T mChipsetType; + IommuType_T mIommuType; + ParavirtProvider_T mParavirtProvider; + Utf8Str mParavirtDebug; + BOOL mEmulatedUSBCardReaderEnabled; + + BOOL mIOCacheEnabled; + ULONG mIOCacheSize; + + typedef std::list<ComObjPtr<PCIDeviceAttachment> > PCIDeviceAssignmentList; + PCIDeviceAssignmentList mPCIDeviceAssignments; + + settings::Debugging mDebugging; + settings::Autostart mAutostart; + + Utf8Str mDefaultFrontend; + }; + + typedef std::list<ComObjPtr<MediumAttachment> > MediumAttachmentList; + + DECLARE_COMMON_CLASS_METHODS(Machine) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only: + + // initializer for creating a new, empty machine + HRESULT init(VirtualBox *aParent, + const Utf8Str &strConfigFile, + const Utf8Str &strName, + const StringsList &llGroups, + const Utf8Str &strOsTypeId, + GuestOSType *aOsType, + const Guid &aId, + bool fForceOverwrite, + bool fDirectoryIncludesUUID, + const com::Utf8Str &aCipher, + const com::Utf8Str &aPasswordId, + const com::Utf8Str &aPassword); + + // initializer for loading existing machine XML (either registered or not) + HRESULT initFromSettings(VirtualBox *aParent, + const Utf8Str &strConfigFile, + const Guid *aId, + const com::Utf8Str &strPassword); + + // initializer for machine config in memory (OVF import) + HRESULT init(VirtualBox *aParent, + const Utf8Str &strName, + const Utf8Str &strSettingsFilename, + const settings::MachineConfigFile &config); + + void uninit(); + +#ifdef VBOX_WITH_RESOURCE_USAGE_API + // Needed from VirtualBox, for the delayed metrics cleanup. + void i_unregisterMetrics(PerformanceCollector *aCollector, Machine *aMachine); +#endif /* VBOX_WITH_RESOURCE_USAGE_API */ + +protected: + HRESULT initImpl(VirtualBox *aParent, + const Utf8Str &strConfigFile); + HRESULT initDataAndChildObjects(); + HRESULT i_registeredInit(); + HRESULT i_tryCreateMachineConfigFile(bool fForceOverwrite); + void uninitDataAndChildObjects(); + +public: + + + // public methods only for internal purposes + + virtual bool i_isSnapshotMachine() const + { + return false; + } + + virtual bool i_isSessionMachine() const + { + return false; + } + + /** + * Override of the default locking class to be used for validating lock + * order with the standard member lock handle. + */ + virtual VBoxLockingClass getLockingClass() const + { + return LOCKCLASS_MACHINEOBJECT; + } + + /// @todo (dmik) add lock and make non-inlined after revising classes + // that use it. Note: they should enter Machine lock to keep the returned + // information valid! + bool i_isRegistered() { return !!mData->mRegistered; } + + // unsafe inline public methods for internal purposes only (ensure there is + // a caller and a read lock before calling them!) + + /** + * Returns the VirtualBox object this machine belongs to. + * + * @note This method doesn't check this object's readiness. Intended to be + * used by ready Machine children (whose readiness is bound to the parent's + * one) or after doing addCaller() manually. + */ + VirtualBox* i_getVirtualBox() const { return mParent; } + + /** + * Checks if this machine is accessible, without attempting to load the + * config file. + * + * @note This method doesn't check this object's readiness. Intended to be + * used by ready Machine children (whose readiness is bound to the parent's + * one) or after doing addCaller() manually. + */ + bool i_isAccessible() const { return !!mData->mAccessible; } + + /** + * Returns this machine ID. + * + * @note This method doesn't check this object's readiness. Intended to be + * used by ready Machine children (whose readiness is bound to the parent's + * one) or after adding a caller manually. + */ + const Guid& i_getId() const { return mData->mUuid; } + + /** + * Returns the snapshot ID this machine represents or an empty UUID if this + * instance is not SnapshotMachine. + * + * @note This method doesn't check this object's readiness. Intended to be + * used by ready Machine children (whose readiness is bound to the parent's + * one) or after adding a caller manually. + */ + inline const Guid& i_getSnapshotId() const; + + /** + * Returns this machine's full settings file path. + * + * @note This method doesn't lock this object or check its readiness. + * Intended to be used only after doing addCaller() manually and locking it + * for reading. + */ + const Utf8Str& i_getSettingsFileFull() const { return mData->m_strConfigFileFull; } + + /** + * Returns this machine name. + * + * @note This method doesn't lock this object or check its readiness. + * Intended to be used only after doing addCaller() manually and locking it + * for reading. + */ + const Utf8Str& i_getName() const { return mUserData->s.strName; } + + enum + { + IsModified_MachineData = 0x000001, + IsModified_Storage = 0x000002, + IsModified_NetworkAdapters = 0x000008, + IsModified_SerialPorts = 0x000010, + IsModified_ParallelPorts = 0x000020, + IsModified_VRDEServer = 0x000040, + IsModified_AudioSettings = 0x000080, + IsModified_USB = 0x000100, + IsModified_BIOS = 0x000200, + IsModified_SharedFolders = 0x000400, + IsModified_Snapshots = 0x000800, + IsModified_BandwidthControl = 0x001000, + IsModified_Recording = 0x002000, + IsModified_GraphicsAdapter = 0x004000, + IsModified_TrustedPlatformModule = 0x008000, + IsModified_NvramStore = 0x010000, + IsModified_GuestDebugControl = 0x020000, + }; + + /** + * Returns various information about this machine. + * + * @note This method doesn't lock this object or check its readiness. + * Intended to be used only after doing addCaller() manually and locking it + * for reading. + */ + Utf8Str i_getOSTypeId() const { return mUserData->s.strOsType; } + ChipsetType_T i_getChipsetType() const { return mHWData->mChipsetType; } + FirmwareType_T i_getFirmwareType() const { return mHWData->mFirmwareType; } + ParavirtProvider_T i_getParavirtProvider() const { return mHWData->mParavirtProvider; } + Utf8Str i_getParavirtDebug() const { return mHWData->mParavirtDebug; } + + void i_setModified(uint32_t fl, bool fAllowStateModification = true); + void i_setModifiedLock(uint32_t fl, bool fAllowStateModification = true); + + MachineState_T i_getMachineState() const { return mData->mMachineState; } + + bool i_isStateModificationAllowed() const { return mData->m_fAllowStateModification; } + void i_allowStateModification() { mData->m_fAllowStateModification = true; } + void i_disallowStateModification() { mData->m_fAllowStateModification = false; } + + const StringsList &i_getGroups() const { return mUserData->s.llGroups; } + + // callback handlers + virtual HRESULT i_onNetworkAdapterChange(INetworkAdapter * /* networkAdapter */, BOOL /* changeAdapter */) { return S_OK; } + virtual HRESULT i_onNATRedirectRuleChanged(ULONG /* slot */, BOOL /* fRemove */ , const Utf8Str & /* name */, + NATProtocol_T /* protocol */, const Utf8Str & /* host ip */, LONG /* host port */, + const Utf8Str & /* guest port */, LONG /* guest port */ ) { return S_OK; } + virtual HRESULT i_onAudioAdapterChange(IAudioAdapter * /* audioAdapter */) { return S_OK; } + virtual HRESULT i_onHostAudioDeviceChange(IHostAudioDevice *, BOOL /* new */, AudioDeviceState_T, IVirtualBoxErrorInfo *) { return S_OK; } + virtual HRESULT i_onSerialPortChange(ISerialPort * /* serialPort */) { return S_OK; } + virtual HRESULT i_onParallelPortChange(IParallelPort * /* parallelPort */) { return S_OK; } + virtual HRESULT i_onVRDEServerChange(BOOL /* aRestart */) { return S_OK; } + virtual HRESULT i_onUSBControllerChange() { return S_OK; } + virtual HRESULT i_onStorageControllerChange(const com::Guid & /* aMachineId */, const com::Utf8Str & /* aControllerName */) { return S_OK; } + virtual HRESULT i_onCPUChange(ULONG /* aCPU */, BOOL /* aRemove */) { return S_OK; } + virtual HRESULT i_onCPUExecutionCapChange(ULONG /* aExecutionCap */) { return S_OK; } + virtual HRESULT i_onMediumChange(IMediumAttachment * /* mediumAttachment */, BOOL /* force */) { return S_OK; } + virtual HRESULT i_onSharedFolderChange() { return S_OK; } + virtual HRESULT i_onVMProcessPriorityChange(VMProcPriority_T /* aPriority */) { return S_OK; } + virtual HRESULT i_onClipboardModeChange(ClipboardMode_T /* aClipboardMode */) { return S_OK; } + virtual HRESULT i_onClipboardFileTransferModeChange(BOOL /* aEnable */) { return S_OK; } + virtual HRESULT i_onDnDModeChange(DnDMode_T /* aDnDMode */) { return S_OK; } + virtual HRESULT i_onBandwidthGroupChange(IBandwidthGroup * /* aBandwidthGroup */) { return S_OK; } + virtual HRESULT i_onStorageDeviceChange(IMediumAttachment * /* mediumAttachment */, BOOL /* remove */, + BOOL /* silent */) { return S_OK; } + virtual HRESULT i_onRecordingChange(BOOL /* aEnable */) { return S_OK; } + virtual HRESULT i_onGuestDebugControlChange(IGuestDebugControl * /* guestDebugControl */) { return S_OK; } + + + HRESULT i_saveRegistryEntry(settings::MachineRegistryEntry &data); + + int i_calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult); + void i_copyPathRelativeToMachine(const Utf8Str &strSource, Utf8Str &strTarget); + + void i_getLogFolder(Utf8Str &aLogFolder); + Utf8Str i_getLogFilename(ULONG idx); + Utf8Str i_getHardeningLogFilename(void); + Utf8Str i_getDefaultNVRAMFilename(); + Utf8Str i_getSnapshotNVRAMFilename(); + SettingsVersion_T i_getSettingsVersion(void); + + void i_composeSavedStateFilename(Utf8Str &strStateFilePath); + + bool i_isUSBControllerPresent(); + + HRESULT i_launchVMProcess(IInternalSessionControl *aControl, + const Utf8Str &strType, + const std::vector<com::Utf8Str> &aEnvironmentChanges, + ProgressProxy *aProgress); + + HRESULT i_getDirectControl(ComPtr<IInternalSessionControl> *directControl) + { + HRESULT rc; + *directControl = mData->mSession.mDirectControl; + + if (!*directControl) + rc = E_ACCESSDENIED; + else + rc = S_OK; + + return rc; + } + + bool i_isSessionOpen(ComObjPtr<SessionMachine> &aMachine, + ComPtr<IInternalSessionControl> *aControl = NULL, + bool aRequireVM = false, + bool aAllowClosing = false); + bool i_isSessionSpawning(); + + bool i_isSessionOpenOrClosing(ComObjPtr<SessionMachine> &aMachine, + ComPtr<IInternalSessionControl> *aControl = NULL) + { return i_isSessionOpen(aMachine, aControl, false /* aRequireVM */, true /* aAllowClosing */); } + + bool i_isSessionOpenVM(ComObjPtr<SessionMachine> &aMachine, + ComPtr<IInternalSessionControl> *aControl = NULL) + { return i_isSessionOpen(aMachine, aControl, true /* aRequireVM */, false /* aAllowClosing */); } + + bool i_checkForSpawnFailure(); + + HRESULT i_prepareRegister(); + + HRESULT i_getSharedFolder(const Utf8Str &aName, + ComObjPtr<SharedFolder> &aSharedFolder, + bool aSetError = false) + { + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + return i_findSharedFolder(aName, aSharedFolder, aSetError); + } + + HRESULT i_addStateDependency(StateDependency aDepType = AnyStateDep, + MachineState_T *aState = NULL, + BOOL *aRegistered = NULL); + void i_releaseStateDependency(); + + HRESULT i_getStorageControllerByName(const Utf8Str &aName, + ComObjPtr<StorageController> &aStorageController, + bool aSetError = false); + + HRESULT i_getMediumAttachmentsOfController(const Utf8Str &aName, + MediumAttachmentList &aAttachments); + + HRESULT i_getUSBControllerByName(const Utf8Str &aName, + ComObjPtr<USBController> &aUSBController, + bool aSetError = false); + + HRESULT i_getBandwidthGroup(const Utf8Str &strBandwidthGroup, + ComObjPtr<BandwidthGroup> &pBandwidthGroup, + bool fSetError = false) + { + return mBandwidthControl->i_getBandwidthGroupByName(strBandwidthGroup, + pBandwidthGroup, + fSetError); + } + + static HRESULT i_setErrorStatic(HRESULT aResultCode, const char *pcszMsg, ...); + +protected: + + class ClientToken; + + HRESULT i_checkStateDependency(StateDependency aDepType); + + Machine *i_getMachine(); + + void i_ensureNoStateDependencies(AutoWriteLock &alock); + + virtual HRESULT i_setMachineState(MachineState_T aMachineState); + + HRESULT i_findSharedFolder(const Utf8Str &aName, + ComObjPtr<SharedFolder> &aSharedFolder, + bool aSetError = false); + + HRESULT i_loadSettings(bool aRegistered); + HRESULT i_loadMachineDataFromSettings(const settings::MachineConfigFile &config, + const Guid *puuidRegistry); + HRESULT i_loadSnapshot(const settings::Snapshot &data, + const Guid &aCurSnapshotId); + HRESULT i_loadHardware(const Guid *puuidRegistry, + const Guid *puuidSnapshot, + const settings::Hardware &data, + const settings::Debugging *pDbg, + const settings::Autostart *pAutostart, + const settings::RecordingSettings &recording); + HRESULT i_loadDebugging(const settings::Debugging *pDbg); + HRESULT i_loadAutostart(const settings::Autostart *pAutostart); + HRESULT i_loadStorageControllers(const settings::Storage &data, + const Guid *puuidRegistry, + const Guid *puuidSnapshot); + HRESULT i_loadStorageDevices(StorageController *aStorageController, + const settings::StorageController &data, + const Guid *puuidRegistry, + const Guid *puuidSnapshot); + + HRESULT i_findSnapshotById(const Guid &aId, + ComObjPtr<Snapshot> &aSnapshot, + bool aSetError = false); + HRESULT i_findSnapshotByName(const Utf8Str &strName, + ComObjPtr<Snapshot> &aSnapshot, + bool aSetError = false); + + ULONG i_getUSBControllerCountByType(USBControllerType_T enmType); + + enum + { + /* flags for #saveSettings() */ + SaveS_ResetCurStateModified = 0x01, + SaveS_Force = 0x04, + SaveS_RemoveBackup = 0x08, + /* flags for #saveStateSettings() */ + SaveSTS_CurStateModified = 0x20, + SaveSTS_StateFilePath = 0x40, + SaveSTS_StateTimeStamp = 0x80 + }; + + HRESULT i_prepareSaveSettings(bool *pfNeedsGlobalSaveSettings, + bool *pfSettingsFileIsNew); + HRESULT i_saveSettings(bool *pfNeedsGlobalSaveSettings, AutoWriteLock &alock, int aFlags = 0); + + void i_copyMachineDataToSettings(settings::MachineConfigFile &config); + HRESULT i_saveAllSnapshots(settings::MachineConfigFile &config); + HRESULT i_saveHardware(settings::Hardware &data, settings::Debugging *pDbg, + settings::Autostart *pAutostart, settings::RecordingSettings &recording); + HRESULT i_saveStorageControllers(settings::Storage &data); + HRESULT i_saveStorageDevices(ComObjPtr<StorageController> aStorageController, + settings::StorageController &data); + HRESULT i_saveStateSettings(int aFlags); + + void i_addMediumToRegistry(ComObjPtr<Medium> &pMedium); + + HRESULT i_deleteFile(const Utf8Str &strFile, bool fIgnoreFailures = false, const Utf8Str &strWhat = "", int *prc = NULL); + + HRESULT i_createImplicitDiffs(IProgress *aProgress, + ULONG aWeight, + bool aOnline); + HRESULT i_deleteImplicitDiffs(bool aOnline); + + MediumAttachment* i_findAttachment(const MediumAttachmentList &ll, + const Utf8Str &aControllerName, + LONG aControllerPort, + LONG aDevice); + MediumAttachment* i_findAttachment(const MediumAttachmentList &ll, + ComObjPtr<Medium> pMedium); + MediumAttachment* i_findAttachment(const MediumAttachmentList &ll, + Guid &id); + + HRESULT i_detachDevice(MediumAttachment *pAttach, + AutoWriteLock &writeLock, + Snapshot *pSnapshot); + + HRESULT i_detachAllMedia(AutoWriteLock &writeLock, + Snapshot *pSnapshot, + CleanupMode_T cleanupMode, + MediaList &llMedia); + + void i_commitMedia(bool aOnline = false); + void i_rollbackMedia(); + + bool i_isInOwnDir(Utf8Str *aSettingsDir = NULL) const; + + void i_rollback(bool aNotify); + void i_commit(); + void i_copyFrom(Machine *aThat); + bool i_isControllerHotplugCapable(StorageControllerType_T enmCtrlType); + + Utf8Str i_getExtraData(const Utf8Str &strKey); + + com::Utf8Str i_controllerNameFromBusType(StorageBus_T aBusType); + +#ifdef VBOX_WITH_GUEST_PROPS + HRESULT i_getGuestPropertyFromService(const com::Utf8Str &aName, com::Utf8Str &aValue, + LONG64 *aTimestamp, com::Utf8Str &aFlags) const; + HRESULT i_setGuestPropertyToService(const com::Utf8Str &aName, const com::Utf8Str &aValue, + const com::Utf8Str &aFlags, bool fDelete); + HRESULT i_getGuestPropertyFromVM(const com::Utf8Str &aName, com::Utf8Str &aValue, + LONG64 *aTimestamp, com::Utf8Str &aFlags) const; + HRESULT i_setGuestPropertyToVM(const com::Utf8Str &aName, const com::Utf8Str &aValue, + const com::Utf8Str &aFlags, bool fDelete); + HRESULT i_enumerateGuestPropertiesInService(const com::Utf8Str &aPatterns, + std::vector<com::Utf8Str> &aNames, + std::vector<com::Utf8Str> &aValues, + std::vector<LONG64> &aTimestamps, + std::vector<com::Utf8Str> &aFlags); + HRESULT i_enumerateGuestPropertiesOnVM(const com::Utf8Str &aPatterns, + std::vector<com::Utf8Str> &aNames, + std::vector<com::Utf8Str> &aValues, + std::vector<LONG64> &aTimestamps, + std::vector<com::Utf8Str> &aFlags); + +#endif /* VBOX_WITH_GUEST_PROPS */ + +#ifdef VBOX_WITH_RESOURCE_USAGE_API + void i_getDiskList(MediaList &list); + void i_registerMetrics(PerformanceCollector *aCollector, Machine *aMachine, RTPROCESS pid); + + pm::CollectorGuest *mCollectorGuest; +#endif /* VBOX_WITH_RESOURCE_USAGE_API */ + + Machine * const mPeer; + + VirtualBox * const mParent; + + Shareable<Data> mData; + Shareable<SSData> mSSData; + + Backupable<UserData> mUserData; + Backupable<HWData> mHWData; + + /** + * Hard disk and other media data. + * + * The usage policy is the same as for mHWData, but a separate field + * is necessary because hard disk data requires different procedures when + * taking or deleting snapshots, etc. + * + * @todo r=klaus change this to a regular list and use the normal way to + * handle the settings when creating a session or taking a snapshot. + * Same thing applies to mStorageControllers and mUSBControllers. + */ + Backupable<MediumAttachmentList> mMediumAttachments; + + // the following fields need special backup/rollback/commit handling, + // so they cannot be a part of HWData + + const ComObjPtr<VRDEServer> mVRDEServer; + const ComObjPtr<SerialPort> mSerialPorts[SchemaDefs::SerialPortCount]; + const ComObjPtr<ParallelPort> mParallelPorts[SchemaDefs::ParallelPortCount]; + const ComObjPtr<AudioSettings> mAudioSettings; + const ComObjPtr<USBDeviceFilters> mUSBDeviceFilters; + const ComObjPtr<BIOSSettings> mBIOSSettings; + const ComObjPtr<RecordingSettings> mRecordingSettings; + const ComObjPtr<GraphicsAdapter> mGraphicsAdapter; + const ComObjPtr<BandwidthControl> mBandwidthControl; + const ComObjPtr<GuestDebugControl> mGuestDebugControl; + + const ComObjPtr<TrustedPlatformModule> mTrustedPlatformModule; + const ComObjPtr<NvramStore> mNvramStore; + + typedef std::vector<ComObjPtr<NetworkAdapter> > NetworkAdapterVector; + NetworkAdapterVector mNetworkAdapters; + + typedef std::list<ComObjPtr<StorageController> > StorageControllerList; + Backupable<StorageControllerList> mStorageControllers; + + typedef std::list<ComObjPtr<USBController> > USBControllerList; + Backupable<USBControllerList> mUSBControllers; + + uint64_t uRegistryNeedsSaving; + + /** + * Abstract base class for all Machine or SessionMachine related + * asynchronous tasks. This is necessary since RTThreadCreate cannot call + * a (non-static) method as its thread function, so instead we have it call + * the static Machine::taskHandler, which then calls the handler() method + * in here (implemented by the subclasses). + */ + class Task : public ThreadTask + { + public: + Task(Machine *m, Progress *p, const Utf8Str &t) + : ThreadTask(t), + m_pMachine(m), + m_machineCaller(m), + m_pProgress(p), + m_machineStateBackup(m->mData->mMachineState) // save the current machine state + {} + virtual ~Task(){} + + void modifyBackedUpState(MachineState_T s) + { + *const_cast<MachineState_T *>(&m_machineStateBackup) = s; + } + + ComObjPtr<Machine> m_pMachine; + AutoCaller m_machineCaller; + ComObjPtr<Progress> m_pProgress; + const MachineState_T m_machineStateBackup; + }; + + class DeleteConfigTask; + void i_deleteConfigHandler(DeleteConfigTask &task); + +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION + class ChangeEncryptionTask; + void i_changeEncryptionHandler(ChangeEncryptionTask &task); + HRESULT i_changeEncryptionForComponent(ChangeEncryptionTask &task, const com::Utf8Str strDirectory, + const com::Utf8Str strFilePattern, com::Utf8Str &strKeyStore, + com::Utf8Str &strKeyId, int iCipherMode); + int i_findFiles(std::list<com::Utf8Str> &lstFiles, const com::Utf8Str &strDir, + const com::Utf8Str &strPattern); + int i_createIoStreamForFile(const char *pszFilename, PCVBOXCRYPTOIF pCryptoIf, + const char *pszKeyStore, const char *pszPassword, + uint64_t fOpen, PRTVFSIOSTREAM phVfsIos); +#endif + + friend class Appliance; + friend class RecordingSettings; + friend class RecordingScreenSettings; + friend class SessionMachine; + friend class SnapshotMachine; + friend class VirtualBox; + + friend class MachineCloneVM; + friend class MachineMoveVM; +private: + // wrapped IMachine properties + HRESULT getParent(ComPtr<IVirtualBox> &aParent); + HRESULT getIcon(std::vector<BYTE> &aIcon); + HRESULT setIcon(const std::vector<BYTE> &aIcon); + HRESULT getAccessible(BOOL *aAccessible); + HRESULT getAccessError(ComPtr<IVirtualBoxErrorInfo> &aAccessError); + HRESULT getName(com::Utf8Str &aName); + HRESULT setName(const com::Utf8Str &aName); + HRESULT getDescription(com::Utf8Str &aDescription); + HRESULT setDescription(const com::Utf8Str &aDescription); + HRESULT getId(com::Guid &aId); + HRESULT getGroups(std::vector<com::Utf8Str> &aGroups); + HRESULT setGroups(const std::vector<com::Utf8Str> &aGroups); + HRESULT getOSTypeId(com::Utf8Str &aOSTypeId); + HRESULT setOSTypeId(const com::Utf8Str &aOSTypeId); + HRESULT getHardwareVersion(com::Utf8Str &aHardwareVersion); + HRESULT setHardwareVersion(const com::Utf8Str &aHardwareVersion); + HRESULT getHardwareUUID(com::Guid &aHardwareUUID); + HRESULT setHardwareUUID(const com::Guid &aHardwareUUID); + HRESULT getCPUCount(ULONG *aCPUCount); + HRESULT setCPUCount(ULONG aCPUCount); + HRESULT getCPUHotPlugEnabled(BOOL *aCPUHotPlugEnabled); + HRESULT setCPUHotPlugEnabled(BOOL aCPUHotPlugEnabled); + HRESULT getCPUExecutionCap(ULONG *aCPUExecutionCap); + HRESULT setCPUExecutionCap(ULONG aCPUExecutionCap); + HRESULT getCPUIDPortabilityLevel(ULONG *aCPUIDPortabilityLevel); + HRESULT setCPUIDPortabilityLevel(ULONG aCPUIDPortabilityLevel); + HRESULT getCPUProfile(com::Utf8Str &aCPUProfile); + HRESULT setCPUProfile(const com::Utf8Str &aCPUProfile); + HRESULT getMemorySize(ULONG *aMemorySize); + HRESULT setMemorySize(ULONG aMemorySize); + HRESULT getMemoryBalloonSize(ULONG *aMemoryBalloonSize); + HRESULT setMemoryBalloonSize(ULONG aMemoryBalloonSize); + HRESULT getPageFusionEnabled(BOOL *aPageFusionEnabled); + HRESULT setPageFusionEnabled(BOOL aPageFusionEnabled); + HRESULT getGraphicsAdapter(ComPtr<IGraphicsAdapter> &aGraphicsAdapter); + HRESULT getBIOSSettings(ComPtr<IBIOSSettings> &aBIOSSettings); + HRESULT getTrustedPlatformModule(ComPtr<ITrustedPlatformModule> &aTrustedPlatformModule); + HRESULT getNonVolatileStore(ComPtr<INvramStore> &aNvramStore); + HRESULT getRecordingSettings(ComPtr<IRecordingSettings> &aRecordingSettings); + HRESULT getFirmwareType(FirmwareType_T *aFirmwareType); + HRESULT setFirmwareType(FirmwareType_T aFirmwareType); + HRESULT getPointingHIDType(PointingHIDType_T *aPointingHIDType); + HRESULT setPointingHIDType(PointingHIDType_T aPointingHIDType); + HRESULT getKeyboardHIDType(KeyboardHIDType_T *aKeyboardHIDType); + HRESULT setKeyboardHIDType(KeyboardHIDType_T aKeyboardHIDType); + HRESULT getHPETEnabled(BOOL *aHPETEnabled); + HRESULT setHPETEnabled(BOOL aHPETEnabled); + HRESULT getChipsetType(ChipsetType_T *aChipsetType); + HRESULT setChipsetType(ChipsetType_T aChipsetType); + HRESULT getIommuType(IommuType_T *aIommuType); + HRESULT setIommuType(IommuType_T aIommuType); + HRESULT getSnapshotFolder(com::Utf8Str &aSnapshotFolder); + HRESULT setSnapshotFolder(const com::Utf8Str &aSnapshotFolder); + HRESULT getVRDEServer(ComPtr<IVRDEServer> &aVRDEServer); + HRESULT getEmulatedUSBCardReaderEnabled(BOOL *aEmulatedUSBCardReaderEnabled); + HRESULT setEmulatedUSBCardReaderEnabled(BOOL aEmulatedUSBCardReaderEnabled); + HRESULT getMediumAttachments(std::vector<ComPtr<IMediumAttachment> > &aMediumAttachments); + HRESULT getUSBControllers(std::vector<ComPtr<IUSBController> > &aUSBControllers); + HRESULT getUSBDeviceFilters(ComPtr<IUSBDeviceFilters> &aUSBDeviceFilters); + HRESULT getAudioSettings(ComPtr<IAudioSettings> &aAudioSettings); + HRESULT getStorageControllers(std::vector<ComPtr<IStorageController> > &aStorageControllers); + HRESULT getSettingsFilePath(com::Utf8Str &aSettingsFilePath); + HRESULT getSettingsAuxFilePath(com::Utf8Str &aSettingsAuxFilePath); + HRESULT getSettingsModified(BOOL *aSettingsModified); + HRESULT getSessionState(SessionState_T *aSessionState); + HRESULT getSessionType(SessionType_T *aSessionType); + HRESULT getSessionName(com::Utf8Str &aSessionType); + HRESULT getSessionPID(ULONG *aSessionPID); + HRESULT getState(MachineState_T *aState); + HRESULT getLastStateChange(LONG64 *aLastStateChange); + HRESULT getStateFilePath(com::Utf8Str &aStateFilePath); + HRESULT getLogFolder(com::Utf8Str &aLogFolder); + HRESULT getCurrentSnapshot(ComPtr<ISnapshot> &aCurrentSnapshot); + HRESULT getSnapshotCount(ULONG *aSnapshotCount); + HRESULT getCurrentStateModified(BOOL *aCurrentStateModified); + HRESULT getSharedFolders(std::vector<ComPtr<ISharedFolder> > &aSharedFolders); + HRESULT getClipboardMode(ClipboardMode_T *aClipboardMode); + HRESULT setClipboardMode(ClipboardMode_T aClipboardMode); + HRESULT getClipboardFileTransfersEnabled(BOOL *aEnabled); + HRESULT setClipboardFileTransfersEnabled(BOOL aEnabled); + HRESULT getDnDMode(DnDMode_T *aDnDMode); + HRESULT setDnDMode(DnDMode_T aDnDMode); + HRESULT getTeleporterEnabled(BOOL *aTeleporterEnabled); + HRESULT setTeleporterEnabled(BOOL aTeleporterEnabled); + HRESULT getTeleporterPort(ULONG *aTeleporterPort); + HRESULT setTeleporterPort(ULONG aTeleporterPort); + HRESULT getTeleporterAddress(com::Utf8Str &aTeleporterAddress); + HRESULT setTeleporterAddress(const com::Utf8Str &aTeleporterAddress); + HRESULT getTeleporterPassword(com::Utf8Str &aTeleporterPassword); + HRESULT setTeleporterPassword(const com::Utf8Str &aTeleporterPassword); + HRESULT getParavirtProvider(ParavirtProvider_T *aParavirtProvider); + HRESULT setParavirtProvider(ParavirtProvider_T aParavirtProvider); + HRESULT getParavirtDebug(com::Utf8Str &aParavirtDebug); + HRESULT setParavirtDebug(const com::Utf8Str &aParavirtDebug); + HRESULT getRTCUseUTC(BOOL *aRTCUseUTC); + HRESULT setRTCUseUTC(BOOL aRTCUseUTC); + HRESULT getIOCacheEnabled(BOOL *aIOCacheEnabled); + HRESULT setIOCacheEnabled(BOOL aIOCacheEnabled); + HRESULT getIOCacheSize(ULONG *aIOCacheSize); + HRESULT setIOCacheSize(ULONG aIOCacheSize); + HRESULT getPCIDeviceAssignments(std::vector<ComPtr<IPCIDeviceAttachment> > &aPCIDeviceAssignments); + HRESULT getBandwidthControl(ComPtr<IBandwidthControl> &aBandwidthControl); + HRESULT getTracingEnabled(BOOL *aTracingEnabled); + HRESULT setTracingEnabled(BOOL aTracingEnabled); + HRESULT getTracingConfig(com::Utf8Str &aTracingConfig); + HRESULT setTracingConfig(const com::Utf8Str &aTracingConfig); + HRESULT getAllowTracingToAccessVM(BOOL *aAllowTracingToAccessVM); + HRESULT setAllowTracingToAccessVM(BOOL aAllowTracingToAccessVM); + HRESULT getAutostartEnabled(BOOL *aAutostartEnabled); + HRESULT setAutostartEnabled(BOOL aAutostartEnabled); + HRESULT getAutostartDelay(ULONG *aAutostartDelay); + HRESULT setAutostartDelay(ULONG aAutostartDelay); + HRESULT getAutostopType(AutostopType_T *aAutostopType); + HRESULT setAutostopType(AutostopType_T aAutostopType); + HRESULT getDefaultFrontend(com::Utf8Str &aDefaultFrontend); + HRESULT setDefaultFrontend(const com::Utf8Str &aDefaultFrontend); + HRESULT getUSBProxyAvailable(BOOL *aUSBProxyAvailable); + HRESULT getVMProcessPriority(VMProcPriority_T *aVMProcessPriority); + HRESULT setVMProcessPriority(VMProcPriority_T aVMProcessPriority); + HRESULT getStateKeyId(com::Utf8Str &aKeyId); + HRESULT getStateKeyStore(com::Utf8Str &aKeyStore); + HRESULT getLogKeyId(com::Utf8Str &aKeyId); + HRESULT getLogKeyStore(com::Utf8Str &aKeyStore); + HRESULT getGuestDebugControl(ComPtr<IGuestDebugControl> &aGuestDebugControl); + + // wrapped IMachine methods + HRESULT lockMachine(const ComPtr<ISession> &aSession, + LockType_T aLockType); + HRESULT launchVMProcess(const ComPtr<ISession> &aSession, + const com::Utf8Str &aType, + const std::vector<com::Utf8Str> &aEnvironmentChanges, + ComPtr<IProgress> &aProgress); + HRESULT setBootOrder(ULONG aPosition, + DeviceType_T aDevice); + HRESULT getBootOrder(ULONG aPosition, + DeviceType_T *aDevice); + HRESULT attachDevice(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + DeviceType_T aType, + const ComPtr<IMedium> &aMedium); + HRESULT attachDeviceWithoutMedium(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + DeviceType_T aType); + HRESULT detachDevice(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice); + HRESULT passthroughDevice(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + BOOL aPassthrough); + HRESULT temporaryEjectDevice(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + BOOL aTemporaryEject); + HRESULT nonRotationalDevice(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + BOOL aNonRotational); + HRESULT setAutoDiscardForDevice(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + BOOL aDiscard); + HRESULT setHotPluggableForDevice(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + BOOL aHotPluggable); + HRESULT setBandwidthGroupForDevice(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + const ComPtr<IBandwidthGroup> &aBandwidthGroup); + HRESULT setNoBandwidthGroupForDevice(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice); + HRESULT unmountMedium(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + BOOL aForce); + HRESULT mountMedium(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + const ComPtr<IMedium> &aMedium, + BOOL aForce); + HRESULT getMedium(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + ComPtr<IMedium> &aMedium); + HRESULT getMediumAttachmentsOfController(const com::Utf8Str &aName, + std::vector<ComPtr<IMediumAttachment> > &aMediumAttachments); + HRESULT getMediumAttachment(const com::Utf8Str &aName, + LONG aControllerPort, + LONG aDevice, + ComPtr<IMediumAttachment> &aAttachment); + HRESULT attachHostPCIDevice(LONG aHostAddress, + LONG aDesiredGuestAddress, + BOOL aTryToUnbind); + HRESULT detachHostPCIDevice(LONG aHostAddress); + HRESULT getNetworkAdapter(ULONG aSlot, + ComPtr<INetworkAdapter> &aAdapter); + HRESULT addStorageController(const com::Utf8Str &aName, + StorageBus_T aConnectionType, + ComPtr<IStorageController> &aController); + HRESULT getStorageControllerByName(const com::Utf8Str &aName, + ComPtr<IStorageController> &aStorageController); + HRESULT getStorageControllerByInstance(StorageBus_T aConnectionType, + ULONG aInstance, + ComPtr<IStorageController> &aStorageController); + HRESULT removeStorageController(const com::Utf8Str &aName); + HRESULT setStorageControllerBootable(const com::Utf8Str &aName, + BOOL aBootable); + HRESULT addUSBController(const com::Utf8Str &aName, + USBControllerType_T aType, + ComPtr<IUSBController> &aController); + HRESULT removeUSBController(const com::Utf8Str &aName); + HRESULT getUSBControllerByName(const com::Utf8Str &aName, + ComPtr<IUSBController> &aController); + HRESULT getUSBControllerCountByType(USBControllerType_T aType, + ULONG *aControllers); + HRESULT getSerialPort(ULONG aSlot, + ComPtr<ISerialPort> &aPort); + HRESULT getParallelPort(ULONG aSlot, + ComPtr<IParallelPort> &aPort); + HRESULT getExtraDataKeys(std::vector<com::Utf8Str> &aKeys); + HRESULT getExtraData(const com::Utf8Str &aKey, + com::Utf8Str &aValue); + HRESULT setExtraData(const com::Utf8Str &aKey, + const com::Utf8Str &aValue); + HRESULT getCPUProperty(CPUPropertyType_T aProperty, + BOOL *aValue); + HRESULT setCPUProperty(CPUPropertyType_T aProperty, + BOOL aValue); + HRESULT getCPUIDLeafByOrdinal(ULONG aOrdinal, + ULONG *aIdx, + ULONG *aSubIdx, + ULONG *aValEax, + ULONG *aValEbx, + ULONG *aValEcx, + ULONG *aValEdx); + HRESULT getCPUIDLeaf(ULONG aIdx, ULONG aSubIdx, + ULONG *aValEax, + ULONG *aValEbx, + ULONG *aValEcx, + ULONG *aValEdx); + HRESULT setCPUIDLeaf(ULONG aIdx, ULONG aSubIdx, + ULONG aValEax, + ULONG aValEbx, + ULONG aValEcx, + ULONG aValEdx); + HRESULT removeCPUIDLeaf(ULONG aIdx, ULONG aSubIdx); + HRESULT removeAllCPUIDLeaves(); + HRESULT getHWVirtExProperty(HWVirtExPropertyType_T aProperty, + BOOL *aValue); + HRESULT setHWVirtExProperty(HWVirtExPropertyType_T aProperty, + BOOL aValue); + HRESULT setSettingsFilePath(const com::Utf8Str &aSettingsFilePath, + ComPtr<IProgress> &aProgress); + HRESULT saveSettings(); + HRESULT discardSettings(); + HRESULT unregister(AutoCaller &aAutoCaller, + CleanupMode_T aCleanupMode, + std::vector<ComPtr<IMedium> > &aMedia); + HRESULT deleteConfig(const std::vector<ComPtr<IMedium> > &aMedia, + ComPtr<IProgress> &aProgress); + HRESULT exportTo(const ComPtr<IAppliance> &aAppliance, + const com::Utf8Str &aLocation, + ComPtr<IVirtualSystemDescription> &aDescription); + HRESULT findSnapshot(const com::Utf8Str &aNameOrId, + ComPtr<ISnapshot> &aSnapshot); + HRESULT createSharedFolder(const com::Utf8Str &aName, + const com::Utf8Str &aHostPath, + BOOL aWritable, + BOOL aAutomount, + const com::Utf8Str &aAutoMountPoint); + HRESULT removeSharedFolder(const com::Utf8Str &aName); + HRESULT canShowConsoleWindow(BOOL *aCanShow); + HRESULT showConsoleWindow(LONG64 *aWinId); + HRESULT getGuestProperty(const com::Utf8Str &aName, + com::Utf8Str &aValue, + LONG64 *aTimestamp, + com::Utf8Str &aFlags); + HRESULT getGuestPropertyValue(const com::Utf8Str &aProperty, + com::Utf8Str &aValue); + HRESULT getGuestPropertyTimestamp(const com::Utf8Str &aProperty, + LONG64 *aValue); + HRESULT setGuestProperty(const com::Utf8Str &aProperty, + const com::Utf8Str &aValue, + const com::Utf8Str &aFlags); + HRESULT setGuestPropertyValue(const com::Utf8Str &aProperty, + const com::Utf8Str &aValue); + HRESULT deleteGuestProperty(const com::Utf8Str &aName); + HRESULT enumerateGuestProperties(const com::Utf8Str &aPatterns, + std::vector<com::Utf8Str> &aNames, + std::vector<com::Utf8Str> &aValues, + std::vector<LONG64> &aTimestamps, + std::vector<com::Utf8Str> &aFlags); + HRESULT querySavedGuestScreenInfo(ULONG aScreenId, + ULONG *aOriginX, + ULONG *aOriginY, + ULONG *aWidth, + ULONG *aHeight, + BOOL *aEnabled); + HRESULT readSavedThumbnailToArray(ULONG aScreenId, + BitmapFormat_T aBitmapFormat, + ULONG *aWidth, + ULONG *aHeight, + std::vector<BYTE> &aData); + HRESULT querySavedScreenshotInfo(ULONG aScreenId, + ULONG *aWidth, + ULONG *aHeight, + std::vector<BitmapFormat_T> &aBitmapFormats); + HRESULT readSavedScreenshotToArray(ULONG aScreenId, + BitmapFormat_T aBitmapFormat, + ULONG *aWidth, + ULONG *aHeight, + std::vector<BYTE> &aData); + + HRESULT hotPlugCPU(ULONG aCpu); + HRESULT hotUnplugCPU(ULONG aCpu); + HRESULT getCPUStatus(ULONG aCpu, + BOOL *aAttached); + HRESULT getEffectiveParavirtProvider(ParavirtProvider_T *aParavirtProvider); + HRESULT queryLogFilename(ULONG aIdx, + com::Utf8Str &aFilename); + HRESULT readLog(ULONG aIdx, + LONG64 aOffset, + LONG64 aSize, + std::vector<BYTE> &aData); + HRESULT cloneTo(const ComPtr<IMachine> &aTarget, + CloneMode_T aMode, + const std::vector<CloneOptions_T> &aOptions, + ComPtr<IProgress> &aProgress); + HRESULT moveTo(const com::Utf8Str &aTargetPath, + const com::Utf8Str &aType, + ComPtr<IProgress> &aProgress); + HRESULT saveState(ComPtr<IProgress> &aProgress); + HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile); + HRESULT discardSavedState(BOOL aFRemoveFile); + HRESULT takeSnapshot(const com::Utf8Str &aName, + const com::Utf8Str &aDescription, + BOOL aPause, + com::Guid &aId, + ComPtr<IProgress> &aProgress); + HRESULT deleteSnapshot(const com::Guid &aId, + ComPtr<IProgress> &aProgress); + HRESULT deleteSnapshotAndAllChildren(const com::Guid &aId, + ComPtr<IProgress> &aProgress); + HRESULT deleteSnapshotRange(const com::Guid &aStartId, + const com::Guid &aEndId, + ComPtr<IProgress> &aProgress); + HRESULT restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot, + ComPtr<IProgress> &aProgress); + HRESULT applyDefaults(const com::Utf8Str &aFlags); + HRESULT changeEncryption(const com::Utf8Str &aCurrentPassword, + const com::Utf8Str &aCipher, + const com::Utf8Str &aNewPassword, + const com::Utf8Str &aNewPasswordId, + BOOL aForce, + ComPtr<IProgress> &aProgress); + HRESULT getEncryptionSettings(com::Utf8Str &aCipher, + com::Utf8Str &aPasswordId); + HRESULT checkEncryptionPassword(const com::Utf8Str &aPassword); + HRESULT addEncryptionPassword(const com::Utf8Str &aId, + const com::Utf8Str &aPassword); + HRESULT addEncryptionPasswords(const std::vector<com::Utf8Str> &aIds, + const std::vector<com::Utf8Str> &aPasswords); + HRESULT removeEncryptionPassword(AutoCaller &autoCaller, + const com::Utf8Str &aId); + HRESULT clearAllEncryptionPasswords(AutoCaller &autoCaller); + + // wrapped IInternalMachineControl properties + + // wrapped IInternalMachineControl methods + HRESULT updateState(MachineState_T aState); + HRESULT beginPowerUp(const ComPtr<IProgress> &aProgress); + HRESULT endPowerUp(LONG aResult); + HRESULT beginPoweringDown(ComPtr<IProgress> &aProgress); + HRESULT endPoweringDown(LONG aResult, + const com::Utf8Str &aErrMsg); + HRESULT runUSBDeviceFilters(const ComPtr<IUSBDevice> &aDevice, + BOOL *aMatched, + ULONG *aMaskedInterfaces); + HRESULT captureUSBDevice(const com::Guid &aId, + const com::Utf8Str &aCaptureFilename); + HRESULT detachUSBDevice(const com::Guid &aId, + BOOL aDone); + HRESULT autoCaptureUSBDevices(); + HRESULT detachAllUSBDevices(BOOL aDone); + HRESULT onSessionEnd(const ComPtr<ISession> &aSession, + ComPtr<IProgress> &aProgress); + HRESULT finishOnlineMergeMedium(); + HRESULT pullGuestProperties(std::vector<com::Utf8Str> &aNames, + std::vector<com::Utf8Str> &aValues, + std::vector<LONG64> &aTimestamps, + std::vector<com::Utf8Str> &aFlags); + HRESULT pushGuestProperty(const com::Utf8Str &aName, + const com::Utf8Str &aValue, + LONG64 aTimestamp, + const com::Utf8Str &aFlags, + BOOL fWasDeleted); + HRESULT lockMedia(); + HRESULT unlockMedia(); + HRESULT ejectMedium(const ComPtr<IMediumAttachment> &aAttachment, + ComPtr<IMediumAttachment> &aNewAttachment); + HRESULT reportVmStatistics(ULONG aValidStats, + ULONG aCpuUser, + ULONG aCpuKernel, + ULONG aCpuIdle, + ULONG aMemTotal, + ULONG aMemFree, + ULONG aMemBalloon, + ULONG aMemShared, + ULONG aMemCache, + ULONG aPagedTotal, + ULONG aMemAllocTotal, + ULONG aMemFreeTotal, + ULONG aMemBalloonTotal, + ULONG aMemSharedTotal, + ULONG aVmNetRx, + ULONG aVmNetTx); + HRESULT authenticateExternal(const std::vector<com::Utf8Str> &aAuthParams, + com::Utf8Str &aResult); + +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION + HRESULT i_setInaccessible(void); +#endif +}; + +// SessionMachine class +//////////////////////////////////////////////////////////////////////////////// + +/** + * @note Notes on locking objects of this class: + * SessionMachine shares some data with the primary Machine instance (pointed + * to by the |mPeer| member). In order to provide data consistency it also + * shares its lock handle. This means that whenever you lock a SessionMachine + * instance using Auto[Reader]Lock or AutoMultiLock, the corresponding Machine + * instance is also locked in the same lock mode. Keep it in mind. + */ +class ATL_NO_VTABLE SessionMachine : + public Machine +{ +public: + VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(SessionMachine, IMachine) + + DECLARE_NOT_AGGREGATABLE(SessionMachine) + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(SessionMachine) + COM_INTERFACE_ENTRY(ISupportErrorInfo) + COM_INTERFACE_ENTRY(IMachine) + COM_INTERFACE_ENTRY2(IDispatch, IMachine) + COM_INTERFACE_ENTRY(IInternalMachineControl) + VBOX_TWEAK_INTERFACE_ENTRY(IMachine) + END_COM_MAP() + + DECLARE_COMMON_CLASS_METHODS(SessionMachine) + + HRESULT FinalConstruct(); + void FinalRelease(); + + struct Uninit + { + enum Reason { Unexpected, Abnormal, Normal }; + }; + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aMachine); + void uninit() { uninit(Uninit::Unexpected); } + void uninit(Uninit::Reason aReason); + + + // util::Lockable interface + RWLockHandle *lockHandle() const; + + // public methods only for internal purposes + + virtual bool i_isSessionMachine() const + { + return true; + } + +#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER + bool i_checkForDeath(); + + void i_getTokenId(Utf8Str &strTokenId); +#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + IToken *i_getToken(); +#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + // getClientToken must be only used by callers who can guarantee that + // the object cannot be deleted in the mean time, i.e. have a caller/lock. + ClientToken *i_getClientToken(); + + HRESULT i_onNetworkAdapterChange(INetworkAdapter *networkAdapter, BOOL changeAdapter); + HRESULT i_onNATRedirectRuleChanged(ULONG ulSlot, BOOL aNatRuleRemove, const Utf8Str &aRuleName, + NATProtocol_T aProto, const Utf8Str &aHostIp, LONG aHostPort, + const Utf8Str &aGuestIp, LONG aGuestPort) RT_OVERRIDE; + HRESULT i_onStorageControllerChange(const com::Guid &aMachineId, const com::Utf8Str &aControllerName); + HRESULT i_onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForce); + HRESULT i_onVMProcessPriorityChange(VMProcPriority_T aPriority); + HRESULT i_onAudioAdapterChange(IAudioAdapter *audioAdapter); + HRESULT i_onHostAudioDeviceChange(IHostAudioDevice *aDevice, BOOL aNew, AudioDeviceState_T aState, IVirtualBoxErrorInfo *aErrInfo); + HRESULT i_onSerialPortChange(ISerialPort *serialPort); + HRESULT i_onParallelPortChange(IParallelPort *parallelPort); + HRESULT i_onCPUChange(ULONG aCPU, BOOL aRemove); + HRESULT i_onVRDEServerChange(BOOL aRestart); + HRESULT i_onRecordingChange(BOOL aEnable); + HRESULT i_onUSBControllerChange(); + HRESULT i_onUSBDeviceAttach(IUSBDevice *aDevice, + IVirtualBoxErrorInfo *aError, + ULONG aMaskedIfs, + const com::Utf8Str &aCaptureFilename); + HRESULT i_onUSBDeviceDetach(IN_BSTR aId, + IVirtualBoxErrorInfo *aError); + HRESULT i_onSharedFolderChange(); + HRESULT i_onClipboardModeChange(ClipboardMode_T aClipboardMode); + HRESULT i_onClipboardFileTransferModeChange(BOOL aEnable); + HRESULT i_onDnDModeChange(DnDMode_T aDnDMode); + HRESULT i_onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup); + HRESULT i_onStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove, BOOL aSilent); + HRESULT i_onCPUExecutionCapChange(ULONG aCpuExecutionCap); + HRESULT i_onGuestDebugControlChange(IGuestDebugControl *guestDebugControl); + + bool i_hasMatchingUSBFilter(const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs); + + HRESULT i_lockMedia(); + HRESULT i_unlockMedia(); + + HRESULT i_saveStateWithReason(Reason_T aReason, ComPtr<IProgress> &aProgress); + +private: + + // wrapped IInternalMachineControl properties + + // wrapped IInternalMachineControl methods + HRESULT setRemoveSavedStateFile(BOOL aRemove); + HRESULT updateState(MachineState_T aState); + HRESULT beginPowerUp(const ComPtr<IProgress> &aProgress); + HRESULT endPowerUp(LONG aResult); + HRESULT beginPoweringDown(ComPtr<IProgress> &aProgress); + HRESULT endPoweringDown(LONG aResult, + const com::Utf8Str &aErrMsg); + HRESULT runUSBDeviceFilters(const ComPtr<IUSBDevice> &aDevice, + BOOL *aMatched, + ULONG *aMaskedInterfaces); + HRESULT captureUSBDevice(const com::Guid &aId, const com::Utf8Str &aCaptureFilename); + HRESULT detachUSBDevice(const com::Guid &aId, + BOOL aDone); + HRESULT autoCaptureUSBDevices(); + HRESULT detachAllUSBDevices(BOOL aDone); + HRESULT onSessionEnd(const ComPtr<ISession> &aSession, + ComPtr<IProgress> &aProgress); + HRESULT finishOnlineMergeMedium(); + HRESULT pullGuestProperties(std::vector<com::Utf8Str> &aNames, + std::vector<com::Utf8Str> &aValues, + std::vector<LONG64> &aTimestamps, + std::vector<com::Utf8Str> &aFlags); + HRESULT pushGuestProperty(const com::Utf8Str &aName, + const com::Utf8Str &aValue, + LONG64 aTimestamp, + const com::Utf8Str &aFlags, + BOOL fWasDeleted); + HRESULT lockMedia(); + HRESULT unlockMedia(); + HRESULT ejectMedium(const ComPtr<IMediumAttachment> &aAttachment, + ComPtr<IMediumAttachment> &aNewAttachment); + HRESULT reportVmStatistics(ULONG aValidStats, + ULONG aCpuUser, + ULONG aCpuKernel, + ULONG aCpuIdle, + ULONG aMemTotal, + ULONG aMemFree, + ULONG aMemBalloon, + ULONG aMemShared, + ULONG aMemCache, + ULONG aPagedTotal, + ULONG aMemAllocTotal, + ULONG aMemFreeTotal, + ULONG aMemBalloonTotal, + ULONG aMemSharedTotal, + ULONG aVmNetRx, + ULONG aVmNetTx); + HRESULT authenticateExternal(const std::vector<com::Utf8Str> &aAuthParams, + com::Utf8Str &aResult); + + + struct ConsoleTaskData + { + ConsoleTaskData() + : mLastState(MachineState_Null), + mDeleteSnapshotInfo(NULL) + { } + + MachineState_T mLastState; + ComObjPtr<Progress> mProgress; + + // used when deleting online snaphshot + void *mDeleteSnapshotInfo; + }; + + class SaveStateTask; + class SnapshotTask; + class TakeSnapshotTask; + class DeleteSnapshotTask; + class RestoreSnapshotTask; + + void i_saveStateHandler(SaveStateTask &aTask); + + // Override some functionality for SessionMachine, this is where the + // real action happens (the Machine methods are just dummies). + HRESULT saveState(ComPtr<IProgress> &aProgress); + HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile); + HRESULT discardSavedState(BOOL aFRemoveFile); + HRESULT takeSnapshot(const com::Utf8Str &aName, + const com::Utf8Str &aDescription, + BOOL aPause, + com::Guid &aId, + ComPtr<IProgress> &aProgress); + HRESULT deleteSnapshot(const com::Guid &aId, + ComPtr<IProgress> &aProgress); + HRESULT deleteSnapshotAndAllChildren(const com::Guid &aId, + ComPtr<IProgress> &aProgress); + HRESULT deleteSnapshotRange(const com::Guid &aStartId, + const com::Guid &aEndId, + ComPtr<IProgress> &aProgress); + HRESULT restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot, + ComPtr<IProgress> &aProgress); + + void i_releaseSavedStateFile(const Utf8Str &strSavedStateFile, Snapshot *pSnapshotToIgnore); + + void i_takeSnapshotHandler(TakeSnapshotTask &aTask); + static void i_takeSnapshotProgressCancelCallback(void *pvUser); + HRESULT i_finishTakingSnapshot(TakeSnapshotTask &aTask, AutoWriteLock &alock, bool aSuccess); + HRESULT i_deleteSnapshot(const com::Guid &aStartId, + const com::Guid &aEndId, + BOOL aDeleteAllChildren, + ComPtr<IProgress> &aProgress); + void i_deleteSnapshotHandler(DeleteSnapshotTask &aTask); + void i_restoreSnapshotHandler(RestoreSnapshotTask &aTask); + + HRESULT i_prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD, + const Guid &machineId, + const Guid &snapshotId, + bool fOnlineMergePossible, + MediumLockList *aVMMALockList, + ComObjPtr<Medium> &aSource, + ComObjPtr<Medium> &aTarget, + bool &fMergeForward, + ComObjPtr<Medium> &pParentForTarget, + MediumLockList * &aChildrenToReparent, + bool &fNeedOnlineMerge, + MediumLockList * &aMediumLockList, + ComPtr<IToken> &aHDLockToken); + void i_cancelDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD, + const ComObjPtr<Medium> &aSource, + MediumLockList *aChildrenToReparent, + bool fNeedsOnlineMerge, + MediumLockList *aMediumLockList, + const ComPtr<IToken> &aHDLockToken, + const Guid &aMediumId, + const Guid &aSnapshotId); + HRESULT i_onlineMergeMedium(const ComObjPtr<MediumAttachment> &aMediumAttachment, + const ComObjPtr<Medium> &aSource, + const ComObjPtr<Medium> &aTarget, + bool fMergeForward, + const ComObjPtr<Medium> &pParentForTarget, + MediumLockList *aChildrenToReparent, + MediumLockList *aMediumLockList, + ComObjPtr<Progress> &aProgress, + bool *pfNeedsMachineSaveSettings); + + HRESULT i_setMachineState(MachineState_T aMachineState); + HRESULT i_updateMachineStateOnClient(); + + bool mRemoveSavedState; + + ConsoleTaskData mConsoleTaskData; + + /** client token for this machine */ + ClientToken *mClientToken; + + int miNATNetworksStarted; + + AUTHLIBRARYCONTEXT mAuthLibCtx; +}; + +// SnapshotMachine class +//////////////////////////////////////////////////////////////////////////////// + +/** + * @note Notes on locking objects of this class: + * SnapshotMachine shares some data with the primary Machine instance (pointed + * to by the |mPeer| member). In order to provide data consistency it also + * shares its lock handle. This means that whenever you lock a SessionMachine + * instance using Auto[Reader]Lock or AutoMultiLock, the corresponding Machine + * instance is also locked in the same lock mode. Keep it in mind. + */ +class ATL_NO_VTABLE SnapshotMachine : + public Machine +{ +public: + VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(SnapshotMachine, IMachine) + + DECLARE_NOT_AGGREGATABLE(SnapshotMachine) + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(SnapshotMachine) + COM_INTERFACE_ENTRY(ISupportErrorInfo) + COM_INTERFACE_ENTRY(IMachine) + COM_INTERFACE_ENTRY2(IDispatch, IMachine) + VBOX_TWEAK_INTERFACE_ENTRY(IMachine) + END_COM_MAP() + + DECLARE_COMMON_CLASS_METHODS(SnapshotMachine) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(SessionMachine *aSessionMachine, + IN_GUID aSnapshotId, + const Utf8Str &aStateFilePath); + HRESULT initFromSettings(Machine *aMachine, + const settings::Hardware &hardware, + const settings::Debugging *pDbg, + const settings::Autostart *pAutostart, + const settings::RecordingSettings &recording, + IN_GUID aSnapshotId, + const Utf8Str &aStateFilePath); + void uninit(); + + // util::Lockable interface + RWLockHandle *lockHandle() const; + + // public methods only for internal purposes + + virtual bool i_isSnapshotMachine() const + { + return true; + } + + HRESULT i_onSnapshotChange(Snapshot *aSnapshot); + + // unsafe inline public methods for internal purposes only (ensure there is + // a caller and a read lock before calling them!) + + const Guid& i_getSnapshotId() const { return mSnapshotId; } + +private: + + Guid mSnapshotId; + /** This field replaces mPeer for SessionMachine instances, as having + * a peer reference is plain meaningless and causes many subtle problems + * with saving settings and the like. */ + Machine * const mMachine; + + friend class Snapshot; +}; + +// third party methods that depend on SnapshotMachine definition + +inline const Guid &Machine::i_getSnapshotId() const +{ + return (i_isSnapshotMachine()) + ? static_cast<const SnapshotMachine*>(this)->i_getSnapshotId() + : Guid::Empty; +} + + +#endif /* !MAIN_INCLUDED_MachineImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/MachineImplCloneVM.h b/src/VBox/Main/include/MachineImplCloneVM.h new file mode 100644 index 00000000..b8164c57 --- /dev/null +++ b/src/VBox/Main/include/MachineImplCloneVM.h @@ -0,0 +1,63 @@ +/* $Id: MachineImplCloneVM.h $ */ +/** @file + * Definition of MachineCloneVM + */ + +/* + * Copyright (C) 2011-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MachineImplCloneVM_h +#define MAIN_INCLUDED_MachineImplCloneVM_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "MachineImpl.h" +#include "ProgressImpl.h" + +/* Forward declaration of the d-pointer. */ +struct MachineCloneVMPrivate; + +class MachineCloneVM +{ +public: + DECLARE_TRANSLATE_METHODS(MachineCloneVM) + + MachineCloneVM(ComObjPtr<Machine> pSrcMachine, ComObjPtr<Machine> pTrgMachine, CloneMode_T mode, const RTCList<CloneOptions_T> &opts); + ~MachineCloneVM(); + + HRESULT start(IProgress **pProgress); + +protected: + HRESULT run(); + void destroy(); + + /* d-pointer */ + MachineCloneVM(MachineCloneVMPrivate &d); + MachineCloneVMPrivate *d_ptr; + + friend struct MachineCloneVMPrivate; +}; + +#endif /* !MAIN_INCLUDED_MachineImplCloneVM_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ + diff --git a/src/VBox/Main/include/MachineImplMoveVM.h b/src/VBox/Main/include/MachineImplMoveVM.h new file mode 100644 index 00000000..9b462e43 --- /dev/null +++ b/src/VBox/Main/include/MachineImplMoveVM.h @@ -0,0 +1,146 @@ +/* $Id: MachineImplMoveVM.h $ */ +/** @file + * Definition of MachineMoveVM + */ + +/* + * Copyright (C) 2011-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MachineImplMoveVM_h +#define MAIN_INCLUDED_MachineImplMoveVM_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "MachineImpl.h" +#include "ProgressImpl.h" +#include "ThreadTask.h" + +///////////////////////////////////////////////////////////////////////////// + +enum VBoxFolder_t +{ + VBox_UnknownFolderType = 0, + VBox_OutsideVMfolder, + VBox_SettingFolder, + VBox_LogFolder, + VBox_StateFolder, + VBox_SnapshotFolder +}; + +typedef struct +{ + bool fSnapshot; + Utf8Str strBaseName; + ComPtr<IMedium> pMedium; + uint32_t uIdx; + ULONG uWeight; +} MEDIUMTASKMOVE; + +typedef struct +{ + RTCList<MEDIUMTASKMOVE> chain; + DeviceType_T devType; + bool fCreateDiffs; + bool fAttachLinked; +} MEDIUMTASKCHAINMOVE; + +typedef struct +{ + Guid snapshotUuid; + Utf8Str strFile; + ULONG uWeight; +} SNAPFILETASKMOVE; + +struct fileList_t; + +class MachineMoveVM : public ThreadTask +{ + std::vector<ComObjPtr<Machine> > machineList; + RTCList<MEDIUMTASKCHAINMOVE> m_llMedias; + RTCList<SNAPFILETASKMOVE> m_llSaveStateFiles; + RTCList<SNAPFILETASKMOVE> m_llNVRAMFiles; + std::map<Utf8Str, MEDIUMTASKMOVE> m_finalMediumsMap; + std::map<Utf8Str, SNAPFILETASKMOVE> m_finalSaveStateFilesMap; + std::map<Utf8Str, SNAPFILETASKMOVE> m_finalNVRAMFilesMap; + std::map<VBoxFolder_t, Utf8Str> m_vmFolders; + + ComObjPtr<Machine> m_pMachine; + ComObjPtr<Progress> m_pProgress; + ComObjPtr<Progress> m_pRollBackProgress; + Utf8Str m_targetPath; + Utf8Str m_type; + HRESULT m_result; + +public: + DECLARE_TRANSLATE_METHODS(MachineMoveVM) + + MachineMoveVM(ComObjPtr<Machine> aMachine, + const com::Utf8Str &aTargetPath, + const com::Utf8Str &aType, + ComObjPtr<Progress> &aProgress) + : ThreadTask("TaskMoveVM") + , m_pMachine(aMachine) + , m_pProgress(aProgress) + , m_targetPath(aTargetPath) + , m_type(aType.isEmpty() ? "basic" : aType) + , m_result(S_OK) + { + } + + virtual ~MachineMoveVM() + { + } + + HRESULT init(); +private: + static DECLCALLBACK(int) updateProgress(unsigned uPercent, void *pvUser); + static DECLCALLBACK(int) copyFileProgress(unsigned uPercentage, void *pvUser); + static void i_MoveVMThreadTask(MachineMoveVM *task); + +public: + void handler() + { + i_MoveVMThreadTask(this); + } + +private: + HRESULT createMachineList(const ComPtr<ISnapshot> &pSnapshot); + inline HRESULT queryBaseName(const ComPtr<IMedium> &pMedium, Utf8Str &strBaseName) const; + HRESULT queryMediasForAllStates(); + void updateProgressStats(MEDIUMTASKCHAINMOVE &mtc, ULONG &uCount, ULONG &uTotalWeight) const; + HRESULT addSaveState(const ComObjPtr<Machine> &machine); + HRESULT addNVRAM(const ComObjPtr<Machine> &machine); + void printStateFile(settings::SnapshotsList &snl); + HRESULT getFilesList(const Utf8Str &strRootFolder, fileList_t &filesList); + HRESULT getFolderSize(const Utf8Str &strRootFolder, uint64_t &size); + HRESULT deleteFiles(const RTCList<Utf8Str> &listOfFiles); + void updatePathsToStateFiles(const Utf8Str &sourcePath, const Utf8Str &targetPath); + void updatePathsToNVRAMFiles(const Utf8Str &sourcePath, const Utf8Str &targetPath); + HRESULT moveAllDisks(const std::map<Utf8Str, MEDIUMTASKMOVE> &listOfDisks, const Utf8Str &strTargetFolder = Utf8Str::Empty); + HRESULT restoreAllDisks(const std::map<Utf8Str, MEDIUMTASKMOVE> &listOfDisks); + HRESULT isMediumTypeSupportedForMoving(const ComPtr<IMedium> &pMedium); +}; + +#endif /* !MAIN_INCLUDED_MachineImplMoveVM_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ + diff --git a/src/VBox/Main/include/MachineLaunchVMCommonWorker.h b/src/VBox/Main/include/MachineLaunchVMCommonWorker.h new file mode 100644 index 00000000..240db496 --- /dev/null +++ b/src/VBox/Main/include/MachineLaunchVMCommonWorker.h @@ -0,0 +1,49 @@ +/* $Id: MachineLaunchVMCommonWorker.h $ */ +/** @file + * VirtualBox Main - VM process launcher helper for VBoxSVC & VBoxSDS. + */ + +/* + * Copyright (C) 2011-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MachineLaunchVMCommonWorker_h +#define MAIN_INCLUDED_MachineLaunchVMCommonWorker_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <vector> +#include "VirtualBoxBase.h" + +int MachineLaunchVMCommonWorker(const Utf8Str &aNameOrId, + const Utf8Str &aComment, + const Utf8Str &aFrontend, + const std::vector<com::Utf8Str> &aEnvironmentChanges, + const Utf8Str &aExtraArg, + const Utf8Str &aFilename, + uint32_t aFlags, + void *aExtraData, + RTPROCESS &aPid); + +#endif /* !MAIN_INCLUDED_MachineLaunchVMCommonWorker_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ + diff --git a/src/VBox/Main/include/Makefile.kup b/src/VBox/Main/include/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/Main/include/Makefile.kup diff --git a/src/VBox/Main/include/Matching.h b/src/VBox/Main/include/Matching.h new file mode 100644 index 00000000..e80856bb --- /dev/null +++ b/src/VBox/Main/include/Matching.h @@ -0,0 +1,540 @@ +/* $Id: Matching.h $ */ +/** @file + * Declaration of template classes that provide simple API to + * do matching between values and value filters constructed from strings. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_Matching_h +#define MAIN_INCLUDED_Matching_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/string.h> + +#include <list> +#include <limits> +#include <algorithm> + +// min and max don't allow us to use numeric_limits::min() and max() +#if defined (_MSC_VER) +#undef min +#undef max +#endif + +namespace matching +{ + +using namespace std; +using namespace com; + +class ParsedFilter_base +{ +public: + + ParsedFilter_base() : mValid (false), mNull (true), mErrorPosition (0) {}; + + /** + * Returns @c true if the filter is valid, @c false otherwise. + */ + bool isValid() const { return mNull || mValid; } + bool isNull() const { return mNull; } + + /** + * Returns the error position from the beginning of the filter + * string if #isValid() is false. Positions are zero-based. + */ + size_t errorPosition() const { return mErrorPosition; } + +protected: + + /** + * Returns @c true if current isNull() and isValid() values make further + * detailed matching meaningful, otherwise returns @c false. + * Must be called as a first method of every isMatch() implementation, + * so that isMatch() will immediately return @c false if isPreMatch() returns + * false. + */ + bool isPreMatch() const + { + if (isNull() || !isValid()) + return false; + return true; + } + + bool mValid : 1; + bool mNull : 1; + size_t mErrorPosition; +}; + +class ParsedIntervalFilter_base : public ParsedFilter_base +{ +public: + virtual ~ParsedIntervalFilter_base() { /* Make VC++ 14.2 happy */ } + +protected: + + enum Mode { Single, Start, End }; + + union Widest + { + int64_t ll; + uint64_t ull; + }; + + struct Limits + { + Widest min; + Widest max; + }; + + ParsedIntervalFilter_base() {} + + /** + * Called by #parse when a value token is encountered. + * This method can modify mNull, mValid and mErrorPosition when + * appropriate. Parsing stops if mValid is false after this method + * returns (mErrorPosition most point to the error position in this case). + */ + virtual void parseValue (const char *aFilter, size_t aStart, size_t aEnd, + Mode aMode) = 0; + + static void parse (const char *aFilter, + ParsedIntervalFilter_base *that); + + static size_t parseValue (const char *aFilter, size_t aStart, size_t aEnd, + bool aIsSigned, const Limits &aLimits, + Widest &val); +}; + +/** + * Represents a parsed interval filter. + * The string format is: + * "int:(\<m\>|([\<m\>]-[\<n\>]))|(\<m\>|([\<m\>]-[\<n\>]))+" + * where \<m\> and \<n\> are numbers in the decimal, hex (0xNNN) or octal + * (0NNN) form, and \<m\> \< \<n\>. Spaces are allowed around \<m\> and \<n\>. + * + * @tparam T type of values to match. Must be a fundamental integer type. + */ +template <class T> +class ParsedIntervalFilter : public ParsedIntervalFilter_base +{ + typedef ParsedIntervalFilter_base Base; + typedef numeric_limits <T> Lim; + + typedef std::list <T> List; + typedef std::pair <T, T> Pair; + typedef std::list <Pair> PairList; + +public: + + ParsedIntervalFilter() {} + + ParsedIntervalFilter (const Bstr &aFilter) { Base::parse (Utf8Str (aFilter), this); } + + ParsedIntervalFilter &operator= (const Bstr &aFilter) + { + mValues.clear(); + mIntervals.clear(); + Base::parse (Utf8Str (aFilter), this); + return *this; + } + + bool isMatch (const T &aValue) const + { + if (!isPreMatch()) + return false; + + { + typename List::const_iterator it = + std::find (mValues.begin(), mValues.end(), aValue); + if (it != mValues.end()) + return true; + } + + for (typename PairList::const_iterator it = mIntervals.begin(); + it != mIntervals.end(); ++ it) + { + if ((*it).first <= aValue && + aValue <= (*it).second) + return true; + } + + return false; + } + +protected: + + struct Limits : public Base::Limits + { + Limits() + { + if (Lim::is_signed) + { + min.ll = (int64_t) Lim::min(); + max.ll = (int64_t) Lim::max(); + } + else + { + min.ull = (uint64_t) Lim::min(); + max.ull = (uint64_t) Lim::max(); + } + } + + static T toValue (const Widest &aWidest) + { + if (Lim::is_signed) + return (T) aWidest.ll; + else + return (T) aWidest.ull; + } + }; + + virtual void parseValue (const char *aFilter, size_t aStart, size_t aEnd, + Mode aMode) + { + AssertReturn (Lim::is_integer, (void) 0); + AssertReturn ( + (Lim::is_signed && Lim::digits <= numeric_limits <int64_t>::digits) || + (!Lim::is_signed && Lim::digits <= numeric_limits <uint64_t>::digits), + (void) 0); + + Limits limits; + Widest val; + size_t parsed = aEnd; + + if (aStart != aEnd) + parsed = Base::parseValue (aFilter, aStart, aEnd, + Lim::is_signed, limits, val); + + if (parsed != aEnd) + { + mValid = false; + mErrorPosition = parsed; + return; + } + + switch (aMode) + { + /// @todo (dmik): future optimizations: + // 1) join intervals when they overlap + // 2) ignore single values that are within any existing interval + case Base::Single: + { + if (aStart == aEnd) + { + // an empty string (contains only spaces after "int:") + mValid = false; + mErrorPosition = aEnd; + AssertReturn (!mValues.size() && !mIntervals.size(), (void) 0); + break; + } + mValues.push_back (limits.toValue (val)); + break; + } + case Base::Start: + { + // aStart == aEnd means smth. like "-[NNN]" + T m = aStart == aEnd ? limits.toValue (limits.min) + : limits.toValue (val); + mIntervals.push_back (Pair (m, m)); + break; + } + case Base::End: + { + // aStart == aEnd means smth. like "[NNN]-" + T n = aStart == aEnd ? limits.toValue (limits.max) + : limits.toValue (val); + if (n < mIntervals.back().first) + { + // error at the beginning of N + mValid = false; + mErrorPosition = aStart; + break; + } + mIntervals.back().second = n; + break; + } + } + } + + std::list <T> mValues; + std::list <std::pair <T, T> > mIntervals; +}; + +/** + * Represents a boolean filter. + * The string format is: "true|false|yes|no|1|0" or an empty string (any match). + */ + +class ParsedBoolFilter : public ParsedFilter_base +{ +public: + + ParsedBoolFilter() : mValue (false), mValueAny (false) {} + + ParsedBoolFilter (const Bstr &aFilter) { parse (aFilter); } + + ParsedBoolFilter &operator= (const Bstr &aFilter) + { + parse (aFilter); + return *this; + } + + bool isMatch (const bool aValue) const + { + if (!isPreMatch()) + return false; + + return mValueAny || mValue == aValue; + } + + bool isMatch (const BOOL aValue) const + { + return isMatch (bool (aValue == TRUE)); + } + +private: + + void parse (const Bstr &aFilter); + + bool mValue : 1; + bool mValueAny : 1; +}; + +class ParsedRegexpFilter_base : public ParsedFilter_base +{ +protected: + + ParsedRegexpFilter_base (bool aDefIgnoreCase = false, + size_t aMinLen = 0, size_t aMaxLen = 0) + : mIgnoreCase (aDefIgnoreCase) + , mMinLen (aMinLen) + , mMaxLen (aMaxLen) + {} + + ParsedRegexpFilter_base (const Bstr &aFilter, bool aDefIgnoreCase = false, + size_t aMinLen = 0, size_t aMaxLen = 0) + : mIgnoreCase (aDefIgnoreCase) + , mMinLen (aMinLen) + , mMaxLen (aMaxLen) + { + parse (aFilter); + } + + ParsedRegexpFilter_base &operator= (const Bstr &aFilter) + { + parse (aFilter); + return *this; + } + + bool isMatch (const Bstr &aValue) const; + +private: + + void parse (const Bstr &aFilter); + + bool mIgnoreCase : 1; + + size_t mMinLen; + size_t mMaxLen; + + Bstr mSimple; +}; + +/** + * Represents a parsed regexp filter. + * + * The string format is: "rx:\<regexp\>" or "\<string\>" + * where \<regexp\> is a valid regexp and \<string\> is the exact match. + * + * @tparam Conv + * class that must define a public static function + * <tt>Bstr toBstr (T aValue)</tt>, where T is the + * type of values that should be accepted by #isMatch(). + * This function is used to get the string representation of T + * for regexp matching. + * @tparam aIgnoreCase + * true if the case insensitive comparison should be done by default + * and false otherwise + * @tparam aMinLen + * minimum string length, or 0 if not limited. + * Used only when the filter string represents the exact match. + * @tparam aMaxLen + * maximum string length, or 0 if not limited. + * Used only when the filter string represents the exact match. + */ +template <class Conv, bool aIgnoreCase, size_t aMinLen = 0, size_t aMaxLen = 0> +class ParsedRegexpFilter : public ParsedRegexpFilter_base +{ +public: + + enum { IgnoreCase = aIgnoreCase, MinLen = aMinLen, MaxLen = aMaxLen }; + + ParsedRegexpFilter() : ParsedRegexpFilter_base (IgnoreCase, MinLen, MaxLen) {} + + ParsedRegexpFilter (const Bstr &aFilter) + : ParsedRegexpFilter_base (aFilter, IgnoreCase, MinLen, MaxLen) {} + + ParsedRegexpFilter &operator= (const Bstr &aFilter) + { + ParsedRegexpFilter_base::operator= (aFilter); + return *this; + } + + template <class T> + bool isMatch (const T &aValue) const + { + if (!this->isPreMatch()) + return false; + + return ParsedRegexpFilter_base::isMatch (Conv::toBstr (aValue)); + } + +protected: +}; + +/** + * Joins two filters into one. + * Only one filter is active (i.e. used for matching or for error reporting) + * at any given time. The active filter is chosen every time when a new + * filter string is assigned to an instance of this class -- the filter + * for which isNull() = false after parsing the string becomes the active + * one (F1 is tried first). + * + * Both filters must have <tt>bool isMatch(const T&)</tt> methods where T is + * the same type as used in #isMatch(). + * + * @tparam F1 first filter class + * @tparam F2 second filter class + */ +template <class F1, class F2> +class TwoParsedFilters +{ +public: + + TwoParsedFilters() {} + + TwoParsedFilters (const Bstr &aFilter) + { + mFilter1 = aFilter; + if (mFilter1.isNull()) + mFilter2 = aFilter; + } + + TwoParsedFilters &operator= (const Bstr &aFilter) + { + mFilter1 = aFilter; + if (mFilter1.isNull()) + mFilter2 = aFilter; + else + mFilter2 = F2(); // reset to null + return *this; + } + + template <class T> + bool isMatch (const T &aValue) const + { + return mFilter1.isMatch (aValue) || mFilter2.isMatch (aValue); + } + + bool isValid() const { return isNull() || (mFilter1.isValid() && mFilter2.isValid()); } + + bool isNull() const { return mFilter1.isNull() && mFilter2.isNull(); } + + size_t errorPosition() const + { + return !mFilter1.isValid() ? mFilter1.errorPosition() : + !mFilter2.isValid() ? mFilter2.errorPosition() : 0; + } + + const F1 &first() const { return mFilter1; } + const F2 &second() const { return mFilter2; } + +private: + + F1 mFilter1; + F2 mFilter2; +}; + +/** + * Inherits from the given parsed filter class and keeps the string used to + * construct the filter as a member. + * + * @tparam F parsed filter class + */ +template <class F> +class Matchable : public F +{ +public: + + Matchable() {} + + /** + * Creates a new parsed filter from the given filter string. + * If the string format is invalid, #isValid() will return false. + */ + Matchable (const Bstr &aString) + : F (aString), mString (aString) {} + + Matchable (CBSTR aString) + : F (Bstr (aString)), mString (aString) {} + + /** + * Assigns a new filter string to this object and recreates the parser. + * If the string format is invalid, #isValid() will return false. + */ + Matchable &operator= (const Bstr &aString) + { + F::operator= (aString); + mString = aString; + return *this; + } + + Matchable &operator= (CBSTR aString) + { + F::operator= (Bstr (aString)); + mString = aString; + return *this; + } + + /** + * Returns the filter string allowing to use the instance where + * Str can be used. + */ + operator const Bstr&() const { return mString; } + + /** Returns the filter string */ + const Bstr& string() const { return mString; } + +private: + + Bstr mString; +}; + +} /* namespace matching */ + +#endif /* !MAIN_INCLUDED_Matching_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/MediumAttachmentImpl.h b/src/VBox/Main/include/MediumAttachmentImpl.h new file mode 100644 index 00000000..45249a12 --- /dev/null +++ b/src/VBox/Main/include/MediumAttachmentImpl.h @@ -0,0 +1,146 @@ +/* $Id: MediumAttachmentImpl.h $ */ +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MediumAttachmentImpl_h +#define MAIN_INCLUDED_MediumAttachmentImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "MediumAttachmentWrap.h" + +class ATL_NO_VTABLE MediumAttachment : + public MediumAttachmentWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(MediumAttachment) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent, + Medium *aMedium, + const Utf8Str &aControllerName, + LONG aPort, + LONG aDevice, + DeviceType_T aType, + bool aImplicit, + bool aPassthrough, + bool aTempEject, + bool aNonRotational, + bool aDiscard, + bool aHotPluggable, + const Utf8Str &strBandwidthGroup); + HRESULT initCopy(Machine *aParent, MediumAttachment *aThat); + void uninit(); + + // public internal methods + void i_rollback(); + void i_commit(); + + // unsafe public methods for internal purposes only (ensure there is + // a caller and a read lock before calling them!) + bool i_isImplicit() const; + void i_setImplicit(bool aImplicit); + + const ComObjPtr<Medium>& i_getMedium() const; + const Utf8Str &i_getControllerName() const; + LONG i_getPort() const; + LONG i_getDevice() const; + DeviceType_T i_getType() const; + bool i_getPassthrough() const; + bool i_getTempEject() const; + bool i_getNonRotational() const; + bool i_getDiscard() const; + Utf8Str& i_getBandwidthGroup() const; + bool i_getHotPluggable() const; + + bool i_matches(const Utf8Str &aControllerName, LONG aPort, LONG aDevice); + + /** Must be called from under this object's write lock. */ + void i_updateName(const Utf8Str &aName); + + /** Must be called from under this object's write lock. */ + void i_updateMedium(const ComObjPtr<Medium> &aMedium); + + /** Must be called from under this object's write lock. */ + void i_updatePassthrough(bool aPassthrough); + + /** Must be called from under this object's write lock. */ + void i_updateTempEject(bool aTempEject); + + /** Must be called from under this object's write lock. */ + void i_updateNonRotational(bool aNonRotational); + + /** Must be called from under this object's write lock. */ + void i_updateDiscard(bool aDiscard); + + /** Must be called from under this object's write lock. */ + void i_updateEjected(); + + /** Must be called from under this object's write lock. */ + void i_updateBandwidthGroup(const Utf8Str &aBandwidthGroup); + + void i_updateParentMachine(Machine * const pMachine); + + /** Must be called from under this object's write lock. */ + void i_updateHotPluggable(bool aHotPluggable); + + /** Construct a unique and somewhat descriptive name for logging. */ + void i_updateLogName(void); + + /** Get a unique and somewhat descriptive name for logging. */ + const char *i_getLogName(void) const { return mLogName.c_str(); } + +private: + + // Wrapped IMediumAttachment properties + HRESULT getMachine(ComPtr<IMachine> &aMachine); + HRESULT getMedium(ComPtr<IMedium> &aHardDisk); + HRESULT getController(com::Utf8Str &aController); + HRESULT getPort(LONG *aPort); + HRESULT getDevice(LONG *aDevice); + HRESULT getType(DeviceType_T *aType); + HRESULT getPassthrough(BOOL *aPassthrough); + HRESULT getTemporaryEject(BOOL *aTemporaryEject); + HRESULT getIsEjected(BOOL *aEjected); + HRESULT getDiscard(BOOL *aDiscard); + HRESULT getNonRotational(BOOL *aNonRotational); + HRESULT getBandwidthGroup(ComPtr<IBandwidthGroup> &aBandwidthGroup); + HRESULT getHotPluggable(BOOL *aHotPluggable); + + struct Data; + Data *m; + + Utf8Str mLogName; /**< For logging purposes */ +}; + +#endif /* !MAIN_INCLUDED_MediumAttachmentImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/MediumFormatImpl.h b/src/VBox/Main/include/MediumFormatImpl.h new file mode 100644 index 00000000..c23a7ae9 --- /dev/null +++ b/src/VBox/Main/include/MediumFormatImpl.h @@ -0,0 +1,125 @@ +/* $Id: MediumFormatImpl.h $ */ +/** @file + * MediumFormat COM class implementation + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MediumFormatImpl_h +#define MAIN_INCLUDED_MediumFormatImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "MediumFormatWrap.h" + + +struct VDBACKENDINFO; + +/** + * The MediumFormat class represents the backend used to store medium data + * (IMediumFormat interface). + * + * @note Instances of this class are permanently caller-referenced by Medium + * objects (through addCaller()) so that an attempt to uninitialize or delete + * them before all Medium objects are uninitialized will produce an endless + * wait! + */ +class ATL_NO_VTABLE MediumFormat : + public MediumFormatWrap +{ +public: + + struct Property + { + Utf8Str strName; + Utf8Str strDescription; + DataType_T type; + ULONG flags; + Utf8Str strDefaultValue; + }; + + typedef std::vector<Property> PropertyArray; + typedef std::vector<com::Utf8Str> StrArray; + + DECLARE_COMMON_CLASS_METHODS(MediumFormat) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(const VDBACKENDINFO *aVDInfo); + void uninit(); + + // public methods for internal purposes only + // (ensure there is a caller and a read lock before calling them!) + + /** Const, no need to lock */ + const Utf8Str &i_getId() const { return m.strId; } + /** Const, no need to lock */ + const Utf8Str &i_getName() const { return m.strName; } + /** Const, no need to lock */ + const StrArray &i_getFileExtensions() const { return m.maFileExtensions; } + /** Const, no need to lock */ + MediumFormatCapabilities_T i_getCapabilities() const { return m.capabilities; } + /** Const, no need to lock */ + const PropertyArray &i_getProperties() const { return m.maProperties; } + +private: + + // wrapped IMediumFormat properties + HRESULT getId(com::Utf8Str &aId); + HRESULT getName(com::Utf8Str &aName); + HRESULT getCapabilities(std::vector<MediumFormatCapabilities_T> &aCapabilities); + + // wrapped IMediumFormat methods + HRESULT describeFileExtensions(std::vector<com::Utf8Str> &aExtensions, + std::vector<DeviceType_T> &aTypes); + HRESULT describeProperties(std::vector<com::Utf8Str> &aNames, + std::vector<com::Utf8Str> &aDescriptions, + std::vector<DataType_T> &aTypes, + std::vector<ULONG> &aFlags, + std::vector<com::Utf8Str> &aDefaults); + + // types + typedef std::vector<DeviceType_T> DeviceTypeArray; + + // data + struct Data + { + Data() : capabilities((MediumFormatCapabilities_T)0) {} + + const Utf8Str strId; + const Utf8Str strName; + const StrArray maFileExtensions; + const DeviceTypeArray maDeviceTypes; + const MediumFormatCapabilities_T capabilities; + const PropertyArray maProperties; + }; + + Data m; +}; + +#endif /* !MAIN_INCLUDED_MediumFormatImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/MediumIOImpl.h b/src/VBox/Main/include/MediumIOImpl.h new file mode 100644 index 00000000..220bc4c0 --- /dev/null +++ b/src/VBox/Main/include/MediumIOImpl.h @@ -0,0 +1,92 @@ +/* $Id: MediumIOImpl.h $ */ +/** @file + * VirtualBox COM class implementation - MediumIO. + */ + +/* + * Copyright (C) 2018-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MediumIOImpl_h +#define MAIN_INCLUDED_MediumIOImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "MediumIOWrap.h" +#include "VirtualBoxBase.h" +#include "AutoCaller.h" + +class ATL_NO_VTABLE MediumIO : + public MediumIOWrap +{ +public: + /** @name Dummy/standard constructors and destructors. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(MediumIO) + HRESULT FinalConstruct(); + void FinalRelease(); + /** @} */ + + /** @name Initializer & uninitializer. + * @{ */ + HRESULT initForMedium(Medium *pMedium, VirtualBox *pVirtualBox, bool fWritable, + com::Utf8Str const &rStrKeyId, com::Utf8Str const &rStrPassword); + void uninit(); + /** @} */ + +private: + /** @name Wrapped IMediumIO properties + * @{ */ + HRESULT getMedium(ComPtr<IMedium> &a_rPtrMedium); + HRESULT getWritable(BOOL *a_fWritable); + HRESULT getExplorer(ComPtr<IVFSExplorer> &a_rPtrExplorer); + /** @} */ + + /** @name Wrapped IMediumIO methods + * @{ */ + HRESULT read(LONG64 a_off, ULONG a_cbRead, std::vector<BYTE> &a_rData); + HRESULT write(LONG64 a_off, const std::vector<BYTE> &a_rData, ULONG *a_pcbWritten); + HRESULT formatFAT(BOOL a_fQuick); + HRESULT initializePartitionTable(PartitionTableType_T a_enmFormat, BOOL a_fWholeDiskInOneEntry); + HRESULT convertToStream(const com::Utf8Str &aFormat, + const std::vector<MediumVariant_T> &aVariant, + ULONG aBufferSize, + ComPtr<IDataStream> &aStream, + ComPtr<IProgress> &aProgress); + HRESULT close(); + /** @} */ + + /** @name Internal workers. + * @{ */ + void i_close(); + /** @} */ + + struct Data; + Data *m; + + class StreamTask; + friend class StreamTask; +}; + +#endif /* !MAIN_INCLUDED_MediumIOImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ + diff --git a/src/VBox/Main/include/MediumImpl.h b/src/VBox/Main/include/MediumImpl.h new file mode 100644 index 00000000..1b550277 --- /dev/null +++ b/src/VBox/Main/include/MediumImpl.h @@ -0,0 +1,473 @@ +/* $Id: MediumImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MediumImpl_h +#define MAIN_INCLUDED_MediumImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/vd.h> +#include "MediumWrap.h" +#include "VirtualBoxBase.h" +#include "AutoCaller.h" +#include "SecretKeyStore.h" +class Progress; +class MediumFormat; +class MediumLockList; +struct MediumCryptoFilterSettings; + +namespace settings +{ + struct Medium; +} + +//////////////////////////////////////////////////////////////////////////////// + +/** + * Medium component class for all media types. + */ +class ATL_NO_VTABLE Medium : + public MediumWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(Medium) + + HRESULT FinalConstruct(); + void FinalRelease(); + + enum HDDOpenMode { OpenReadWrite, OpenReadOnly }; + // have to use a special enum for the overloaded init() below; + // can't use AccessMode_T from XIDL because that's mapped to an int + // and would be ambiguous + + // public initializer/uninitializer for internal purposes only + + // initializer to create empty medium (VirtualBox::CreateMedium()) + HRESULT init(VirtualBox *aVirtualBox, + const Utf8Str &aFormat, + const Utf8Str &aLocation, + const Guid &uuidMachineRegistry, + const DeviceType_T aDeviceType); + + // initializer for opening existing media + // (VirtualBox::OpenMedium(); Machine::AttachDevice()) + HRESULT init(VirtualBox *aVirtualBox, + const Utf8Str &aLocation, + HDDOpenMode enOpenMode, + bool fForceNewUuid, + DeviceType_T aDeviceType); + + // initializer used when loading settings + HRESULT initOne(Medium *aParent, + DeviceType_T aDeviceType, + const Guid &uuidMachineRegistry, + const Utf8Str &strMachineFolder, + const settings::Medium &data); + static HRESULT initFromSettings(VirtualBox *aVirtualBox, + DeviceType_T aDeviceType, + const Guid &uuidMachineRegistry, + const Utf8Str &strMachineFolder, + const settings::Medium &data, + AutoWriteLock &mediaTreeLock, + std::list<std::pair<Guid, DeviceType_T> > &uIdsForNotify); + + // initializer for host floppy/DVD + HRESULT init(VirtualBox *aVirtualBox, + DeviceType_T aDeviceType, + const Utf8Str &aLocation, + const Utf8Str &aDescription = Utf8Str::Empty); + + void uninit(); + + void i_deparent(); + void i_setParent(const ComObjPtr<Medium> &pParent); + + // unsafe methods for internal purposes only (ensure there is + // a caller and a read lock before calling them!) + const ComObjPtr<Medium>& i_getParent() const; + const MediaList& i_getChildren() const; + + const Guid& i_getId() const; + MediumState_T i_getState() const; + MediumVariant_T i_getVariant() const; + bool i_isHostDrive() const; + const Utf8Str& i_getLocationFull() const; + const Utf8Str& i_getFormat() const; + const ComObjPtr<MediumFormat> & i_getMediumFormat() const; + bool i_isMediumFormatFile() const; + uint64_t i_getSize() const; + uint64_t i_getLogicalSize() const; + DeviceType_T i_getDeviceType() const; + MediumType_T i_getType() const; + Utf8Str i_getName(); + + /* handles caller/locking itself */ + bool i_addRegistry(const Guid &id); + bool i_addRegistryNoCallerCheck(const Guid &id); + /* handles caller/locking itself, caller is responsible for tree lock */ + bool i_addRegistryAll(const Guid &id); + /* handles caller/locking itself */ + bool i_removeRegistry(const Guid& id); + /* handles caller/locking itself, caller is responsible for tree lock */ + bool i_removeRegistryAll(const Guid& id); + bool i_isInRegistry(const Guid& id); + bool i_getFirstRegistryMachineId(Guid &uuid) const; + void i_markRegistriesModified(); + + HRESULT i_setPropertyDirect(const Utf8Str &aName, const Utf8Str &aValue); + + HRESULT i_addBackReference(const Guid &aMachineId, + const Guid &aSnapshotId = Guid::Empty); + HRESULT i_removeBackReference(const Guid &aMachineId, + const Guid &aSnapshotId = Guid::Empty); + + + const Guid* i_getFirstMachineBackrefId() const; + const Guid* i_getAnyMachineBackref(const Guid &aId) const; + const Guid* i_getFirstMachineBackrefSnapshotId() const; + size_t i_getMachineBackRefCount() const; + +#ifdef DEBUG + void i_dumpBackRefs(); +#endif + + HRESULT i_updatePath(const Utf8Str &strOldPath, const Utf8Str &strNewPath); + + /* handles caller/locking itself */ + ComObjPtr<Medium> i_getBase(uint32_t *aLevel = NULL); + /* handles caller/locking itself */ + uint32_t i_getDepth(); + + bool i_isReadOnly(); + void i_updateId(const Guid &id); + + void i_saveSettingsOne(settings::Medium &data, + const Utf8Str &strHardDiskFolder); + HRESULT i_saveSettings(settings::Medium &data, + const Utf8Str &strHardDiskFolder); + + HRESULT i_createMediumLockList(bool fFailIfInaccessible, + Medium *pToLock, + bool fMediumLockWriteAll, + Medium *pToBeParent, + MediumLockList &mediumLockList); + + HRESULT i_createDiffStorage(ComObjPtr<Medium> &aTarget, + MediumVariant_T aVariant, + MediumLockList *pMediumLockList, + ComObjPtr<Progress> *aProgress, + bool aWait, + bool aNotify); + Utf8Str i_getPreferredDiffFormat(); + MediumVariant_T i_getPreferredDiffVariant(); + + HRESULT i_close(AutoCaller &autoCaller); + HRESULT i_unlockRead(MediumState_T *aState); + HRESULT i_unlockWrite(MediumState_T *aState); + HRESULT i_deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait, bool aNotify); + HRESULT i_markForDeletion(); + HRESULT i_unmarkForDeletion(); + HRESULT i_markLockedForDeletion(); + HRESULT i_unmarkLockedForDeletion(); + + HRESULT i_queryPreferredMergeDirection(const ComObjPtr<Medium> &pOther, + bool &fMergeForward); + + HRESULT i_prepareMergeTo(const ComObjPtr<Medium> &pTarget, + const Guid *aMachineId, + const Guid *aSnapshotId, + bool fLockMedia, + bool &fMergeForward, + ComObjPtr<Medium> &pParentForTarget, + MediumLockList * &aChildrenToReparent, + MediumLockList * &aMediumLockList); + HRESULT i_mergeTo(const ComObjPtr<Medium> &pTarget, + bool fMergeForward, + const ComObjPtr<Medium> &pParentForTarget, + MediumLockList *aChildrenToReparent, + MediumLockList *aMediumLockList, + ComObjPtr<Progress> *aProgress, + bool aWait, + bool aNotify); + void i_cancelMergeTo(MediumLockList *aChildrenToReparent, + MediumLockList *aMediumLockList); + + HRESULT i_resize(uint64_t aLogicalSize, + MediumLockList *aMediumLockList, + ComObjPtr<Progress> *aProgress, + bool aWait, + bool aNotify); + + HRESULT i_fixParentUuidOfChildren(MediumLockList *pChildrenToReparent); + + HRESULT i_addRawToFss(const char *aFilename, SecretKeyStore *pKeyStore, RTVFSFSSTREAM hVfsFssDst, + const ComObjPtr<Progress> &aProgress, bool fSparse); + + HRESULT i_exportFile(const char *aFilename, + const ComObjPtr<MediumFormat> &aFormat, + MediumVariant_T aVariant, + SecretKeyStore *pKeyStore, + RTVFSIOSTREAM hVfsIosDst, + const ComObjPtr<Progress> &aProgress); + HRESULT i_importFile(const char *aFilename, + const ComObjPtr<MediumFormat> &aFormat, + MediumVariant_T aVariant, + RTVFSIOSTREAM hVfsIosSrc, + const ComObjPtr<Medium> &aParent, + const ComObjPtr<Progress> &aProgress, + bool aNotify); + + HRESULT i_cloneToEx(const ComObjPtr<Medium> &aTarget, MediumVariant_T aVariant, + const ComObjPtr<Medium> &aParent, IProgress **aProgress, + uint32_t idxSrcImageSame, uint32_t idxDstImageSame, bool aNotify); + + const Utf8Str& i_getKeyId(); + + HRESULT i_openForIO(bool fWritable, SecretKeyStore *pKeyStore, PVDISK *ppHdd, MediumLockList *pMediumLockList, + struct MediumCryptoFilterSettings *pCryptoSettings); + +private: + + // wrapped IMedium properties + HRESULT getId(com::Guid &aId); + HRESULT getDescription(AutoCaller &autoCaller, com::Utf8Str &aDescription); + HRESULT setDescription(AutoCaller &autoCaller, const com::Utf8Str &aDescription); + HRESULT getState(MediumState_T *aState); + HRESULT getVariant(std::vector<MediumVariant_T> &aVariant); + HRESULT getLocation(com::Utf8Str &aLocation); + HRESULT setLocation(const com::Utf8Str &aLocation); + HRESULT getName(com::Utf8Str &aName); + HRESULT getDeviceType(DeviceType_T *aDeviceType); + HRESULT getHostDrive(BOOL *aHostDrive); + HRESULT getSize(LONG64 *aSize); + HRESULT getFormat(com::Utf8Str &aFormat); + HRESULT getMediumFormat(ComPtr<IMediumFormat> &aMediumFormat); + HRESULT getType(AutoCaller &autoCaller, MediumType_T *aType); + HRESULT setType(AutoCaller &autoCaller, MediumType_T aType); + HRESULT getAllowedTypes(std::vector<MediumType_T> &aAllowedTypes); + HRESULT getParent(AutoCaller &autoCaller, ComPtr<IMedium> &aParent); + HRESULT getChildren(AutoCaller &autoCaller, std::vector<ComPtr<IMedium> > &aChildren); + HRESULT getBase(AutoCaller &autoCaller, ComPtr<IMedium> &aBase); + HRESULT getReadOnly(AutoCaller &autoCaller, BOOL *aReadOnly); + HRESULT getLogicalSize(LONG64 *aLogicalSize); + HRESULT getAutoReset(BOOL *aAutoReset); + HRESULT setAutoReset(BOOL aAutoReset); + HRESULT getLastAccessError(com::Utf8Str &aLastAccessError); + HRESULT getMachineIds(std::vector<com::Guid> &aMachineIds); + + // wrapped IMedium methods + HRESULT setIds(AutoCaller &aAutoCaller, + BOOL aSetImageId, + const com::Guid &aImageId, + BOOL aSetParentId, + const com::Guid &aParentId); + HRESULT refreshState(AutoCaller &aAutoCaller, + MediumState_T *aState); + HRESULT getSnapshotIds(const com::Guid &aMachineId, + std::vector<com::Guid> &aSnapshotIds); + HRESULT lockRead(ComPtr<IToken> &aToken); + HRESULT lockWrite(ComPtr<IToken> &aToken); + HRESULT close(AutoCaller &aAutoCaller); + HRESULT getProperty(const com::Utf8Str &aName, + com::Utf8Str &aValue); + HRESULT setProperty(const com::Utf8Str &aName, + const com::Utf8Str &aValue); + HRESULT getProperties(const com::Utf8Str &aNames, + std::vector<com::Utf8Str> &aReturnNames, + std::vector<com::Utf8Str> &aReturnValues); + HRESULT setProperties(const std::vector<com::Utf8Str> &aNames, + const std::vector<com::Utf8Str> &aValues); + HRESULT createBaseStorage(LONG64 aLogicalSize, + const std::vector<MediumVariant_T> &aVariant, + ComPtr<IProgress> &aProgress); + HRESULT deleteStorage(ComPtr<IProgress> &aProgress); + HRESULT createDiffStorage(AutoCaller &autoCaller, + const ComPtr<IMedium> &aTarget, + const std::vector<MediumVariant_T> &aVariant, + ComPtr<IProgress> &aProgress); + HRESULT mergeTo(const ComPtr<IMedium> &aTarget, + ComPtr<IProgress> &aProgress); + HRESULT cloneTo(const ComPtr<IMedium> &aTarget, + const std::vector<MediumVariant_T> &aVariant, + const ComPtr<IMedium> &aParent, + ComPtr<IProgress> &aProgress); + HRESULT resizeAndCloneTo(const ComPtr<IMedium> &aTarget, + LONG64 aLogicalSize, + const std::vector<MediumVariant_T> &aVariant, + const ComPtr<IMedium> &aParent, + ComPtr<IProgress> &aProgress); + HRESULT cloneToBase(const ComPtr<IMedium> &aTarget, + const std::vector<MediumVariant_T> &aVariant, + ComPtr<IProgress> &aProgress); + HRESULT moveTo(AutoCaller &autoCaller, + const com::Utf8Str &aLocation, + ComPtr<IProgress> &aProgress); + HRESULT compact(ComPtr<IProgress> &aProgress); + HRESULT resize(LONG64 aLogicalSize, + ComPtr<IProgress> &aProgress); + HRESULT reset(AutoCaller &autoCaller, ComPtr<IProgress> &aProgress); + HRESULT changeEncryption(const com::Utf8Str &aCurrentPassword, const com::Utf8Str &aCipher, + const com::Utf8Str &aNewPassword, const com::Utf8Str &aNewPasswordId, + ComPtr<IProgress> &aProgress); + HRESULT getEncryptionSettings(AutoCaller &autoCaller, com::Utf8Str &aCipher, com::Utf8Str &aPasswordId); + HRESULT checkEncryptionPassword(const com::Utf8Str &aPassword); + HRESULT openForIO(BOOL aWritable, com::Utf8Str const &aPassword, ComPtr<IMediumIO> &aMediumIO); + + // Private internal nmethods + HRESULT i_queryInfo(bool fSetImageId, bool fSetParentId, AutoCaller &autoCaller); + HRESULT i_canClose(); + HRESULT i_unregisterWithVirtualBox(); + HRESULT i_setStateError(); + HRESULT i_setLocation(const Utf8Str &aLocation, const Utf8Str &aFormat = Utf8Str::Empty); + HRESULT i_setFormat(const Utf8Str &aFormat); + VDTYPE i_convertDeviceType(); + DeviceType_T i_convertToDeviceType(VDTYPE enmType); + Utf8Str i_vdError(int aVRC); + + bool i_isPropertyForFilter(const com::Utf8Str &aName); + + HRESULT i_getFilterProperties(std::vector<com::Utf8Str> &aReturnNames, + std::vector<com::Utf8Str> &aReturnValues); + + HRESULT i_preparationForMoving(const Utf8Str &aLocation); + bool i_isMoveOperation(const ComObjPtr<Medium> &pTarget) const; + bool i_resetMoveOperationData(); + Utf8Str i_getNewLocationForMoving() const; + + static DECLCALLBACK(void) i_vdErrorCall(void *pvUser, int rc, RT_SRC_POS_DECL, + const char *pszFormat, va_list va); + static DECLCALLBACK(bool) i_vdConfigAreKeysValid(void *pvUser, + const char *pszzValid); + static DECLCALLBACK(int) i_vdConfigQuerySize(void *pvUser, const char *pszName, + size_t *pcbValue); + static DECLCALLBACK(int) i_vdConfigUpdate(void *pvUser, bool fCreate, + const char *pszName, const char *pszValue); + + static DECLCALLBACK(int) i_vdConfigQuery(void *pvUser, const char *pszName, + char *pszValue, size_t cchValue); + + static DECLCALLBACK(bool) i_vdCryptoConfigAreKeysValid(void *pvUser, + const char *pszzValid); + static DECLCALLBACK(int) i_vdCryptoConfigQuerySize(void *pvUser, const char *pszName, + size_t *pcbValue); + static DECLCALLBACK(int) i_vdCryptoConfigQuery(void *pvUser, const char *pszName, + char *pszValue, size_t cchValue); + + static DECLCALLBACK(int) i_vdCryptoKeyRetain(void *pvUser, const char *pszId, + const uint8_t **ppbKey, size_t *pcbKey); + static DECLCALLBACK(int) i_vdCryptoKeyRelease(void *pvUser, const char *pszId); + static DECLCALLBACK(int) i_vdCryptoKeyStorePasswordRetain(void *pvUser, const char *pszId, const char **ppszPassword); + static DECLCALLBACK(int) i_vdCryptoKeyStorePasswordRelease(void *pvUser, const char *pszId); + static DECLCALLBACK(int) i_vdCryptoKeyStoreSave(void *pvUser, const void *pvKeyStore, size_t cbKeyStore); + static DECLCALLBACK(int) i_vdCryptoKeyStoreReturnParameters(void *pvUser, const char *pszCipher, + const uint8_t *pbDek, size_t cbDek); + + class Task; + class CreateBaseTask; + class CreateDiffTask; + class CloneTask; + class MoveTask; + class CompactTask; + class ResizeTask; + class ResetTask; + class DeleteTask; + class MergeTask; + class ImportTask; + class EncryptTask; + friend class Task; + friend class CreateBaseTask; + friend class CreateDiffTask; + friend class CloneTask; + friend class MoveTask; + friend class CompactTask; + friend class ResizeTask; + friend class ResetTask; + friend class DeleteTask; + friend class MergeTask; + friend class ImportTask; + friend class EncryptTask; + + HRESULT i_taskCreateBaseHandler(Medium::CreateBaseTask &task); + HRESULT i_taskCreateDiffHandler(Medium::CreateDiffTask &task); + HRESULT i_taskMergeHandler(Medium::MergeTask &task); + HRESULT i_taskCloneHandler(Medium::CloneTask &task); + HRESULT i_taskMoveHandler(Medium::MoveTask &task); + HRESULT i_taskDeleteHandler(Medium::DeleteTask &task); + HRESULT i_taskResetHandler(Medium::ResetTask &task); + HRESULT i_taskCompactHandler(Medium::CompactTask &task); + HRESULT i_taskResizeHandler(Medium::ResizeTask &task); + HRESULT i_taskImportHandler(Medium::ImportTask &task); + HRESULT i_taskEncryptHandler(Medium::EncryptTask &task); + + void i_taskEncryptSettingsSetup(struct MediumCryptoFilterSettings *pSettings, const char *pszCipher, + const char *pszKeyStore, const char *pszPassword, + bool fCreateKeyStore); + + struct Data; // opaque data struct, defined in MediumImpl.cpp + Data *m; +}; + + +/** + * Settings for a crypto filter instance. + */ +struct MediumCryptoFilterSettings +{ + MediumCryptoFilterSettings() + : fCreateKeyStore(false), + pszPassword(NULL), + pszKeyStore(NULL), + pszKeyStoreLoad(NULL), + pbDek(NULL), + cbDek(0), + pszCipher(NULL), + pszCipherReturned(NULL) + { } + + bool fCreateKeyStore; + const char *pszPassword; + char *pszKeyStore; + const char *pszKeyStoreLoad; + + const uint8_t *pbDek; + size_t cbDek; + const char *pszCipher; + + /** The cipher returned by the crypto filter. */ + char *pszCipherReturned; + + PVDINTERFACE vdFilterIfaces; + + VDINTERFACECONFIG vdIfCfg; + VDINTERFACECRYPTO vdIfCrypto; +}; + + + +#endif /* !MAIN_INCLUDED_MediumImpl_h */ + diff --git a/src/VBox/Main/include/MediumLock.h b/src/VBox/Main/include/MediumLock.h new file mode 100644 index 00000000..ad02501a --- /dev/null +++ b/src/VBox/Main/include/MediumLock.h @@ -0,0 +1,351 @@ +/* $Id: MediumLock.h $ */ + +/** @file + * + * VirtualBox medium object lock collections + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MediumLock_h +#define MAIN_INCLUDED_MediumLock_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* interface definitions */ +#include "VBox/com/VirtualBox.h" +#include "VirtualBoxBase.h" +#include "AutoCaller.h" + +#include <iprt/types.h> + +#include <list> +#include <map> + +class Medium; +class MediumAttachment; + +/** + * Single entry for medium lock lists. Has a medium object reference, + * information about what kind of lock should be taken, and if it is + * locked right now. + */ +class MediumLock +{ +public: + /** + * Default medium lock constructor. + */ + MediumLock(); + + /** + * Default medium lock destructor. + */ + ~MediumLock(); + + /** + * Create a new medium lock description + * + * @param aMedium Reference to medium object + * @param aLockWrite @c true means a write lock should be taken + */ + MediumLock(const ComObjPtr<Medium> &aMedium, bool aLockWrite); + + /** + * Copy constructor. Needed because we contain an AutoCaller + * instance which is deliberately not copyable. The copy is not + * marked as locked, so be careful. + * + * @param aMediumLock Reference to source object. + */ + MediumLock(const MediumLock &aMediumLock); + + /** + * Update a medium lock description. + * + * @note May be used in locked state. + * + * @return COM status code + * @param aLockWrite @c true means a write lock should be taken + */ + HRESULT UpdateLock(bool aLockWrite); + + /** + * Get medium object reference. + */ + const ComObjPtr<Medium> &GetMedium() const; + + /** + * Get medium object lock request type. + */ + bool GetLockRequest() const; + + /** + * Check if this medium object has been locked by this MediumLock. + */ + bool IsLocked() const; + + /** + * Acquire a medium lock. + * + * @return COM status code + * @param aIgnoreLockedMedia If set ignore all media which is already + * locked in an incompatible way. + */ + HRESULT Lock(bool aIgnoreLockedMedia = false); + + /** + * Release a medium lock. + * + * @return COM status code + */ + HRESULT Unlock(); + +private: + ComObjPtr<Medium> mMedium; + ComPtr<IToken> mToken; + AutoCaller mMediumCaller; + bool mLockWrite; + bool mIsLocked; + /** Flag whether the medium was skipped when taking the locks. + * Only existing and accessible media objects need to be locked. */ + bool mLockSkipped; +}; + + +/** + * Medium lock list. Meant for storing the ordered locking information + * for a single medium chain. + */ +class MediumLockList +{ +public: + + /* Base list data type. */ + typedef std::list<MediumLock> Base; + + /** + * Default medium lock list constructor. + */ + MediumLockList(); + + /** + * Default medium lock list destructor. + */ + ~MediumLockList(); + + /** + * Checks if medium lock declaration list is empty. + * + * @return true if list is empty. + */ + bool IsEmpty(); + + /** + * Add a new medium lock declaration to the end of the list. + * + * @note May be only used in unlocked state. + * + * @return COM status code + * @param aMedium Reference to medium object + * @param aLockWrite @c true means a write lock should be taken + */ + HRESULT Append(const ComObjPtr<Medium> &aMedium, bool aLockWrite); + + /** + * Add a new medium lock declaration to the beginning of the list. + * + * @note May be only used in unlocked state. + * + * @return COM status code + * @param aMedium Reference to medium object + * @param aLockWrite @c true means a write lock should be taken + */ + HRESULT Prepend(const ComObjPtr<Medium> &aMedium, bool aLockWrite); + + /** + * Update a medium lock declaration. + * + * @note May be used in locked state. + * + * @return COM status code + * @param aMedium Reference to medium object + * @param aLockWrite @c true means a write lock should be taken + */ + HRESULT Update(const ComObjPtr<Medium> &aMedium, bool aLockWrite); + + /** + * Remove a medium lock declaration and return an updated iterator. + * + * @note May be used in locked state. + * + * @return COM status code + * @param aIt Iterator for the element to remove + */ + HRESULT RemoveByIterator(Base::iterator &aIt); + + /** + * Clear all medium lock declarations. + * + * @note Implicitly unlocks all locks. + * + * @return COM status code + */ + HRESULT Clear(); + + /** + * Get iterator begin() for base list. + */ + Base::iterator GetBegin(); + + /** + * Get iterator end() for base list. + */ + Base::iterator GetEnd(); + + /** + * Acquire all medium locks "atomically", i.e. all or nothing. + * + * @return COM status code + * @param aSkipOverLockedMedia If set ignore all media which is already + * locked for reading or writing. For callers + * which need to know which medium objects + * have been locked by this lock list you + * can iterate over the list and check the + * MediumLock state. + */ + HRESULT Lock(bool aSkipOverLockedMedia = false); + + /** + * Release all medium locks. + * + * @return COM status code + */ + HRESULT Unlock(); + +private: + Base mMediumLocks; + bool mIsLocked; +}; + +/** + * Medium lock list map. Meant for storing a collection of lock lists. + * The usual use case is creating such a map when locking all medium chains + * belonging to one VM, however that's not the limit. Be creative. + */ +class MediumLockListMap +{ +public: + + /** + * Default medium lock list map constructor. + */ + MediumLockListMap(); + + /** + * Default medium lock list map destructor. + */ + ~MediumLockListMap(); + + /** + * Checks if medium lock list map is empty. + * + * @return true if list is empty. + */ + bool IsEmpty(); + + /** + * Insert a new medium lock list into the map. + * + * @note May be only used in unlocked state. + * + * @return COM status code + * @param aMediumAttachment Reference to medium attachment object, the key. + * @param aMediumLockList Reference to medium lock list object + */ + HRESULT Insert(const ComObjPtr<MediumAttachment> &aMediumAttachment, MediumLockList *aMediumLockList); + + /** + * Replace the medium lock list key by a different one. + * + * @note May be used in locked state. + * + * @return COM status code + * @param aMediumAttachmentOld Reference to medium attachment object. + * @param aMediumAttachmentNew Reference to medium attachment object. + */ + HRESULT ReplaceKey(const ComObjPtr<MediumAttachment> &aMediumAttachmentOld, const ComObjPtr<MediumAttachment> &aMediumAttachmentNew); + + /** + * Remove a medium lock list from the map. The list will get deleted. + * + * @note May be only used in unlocked state. + * + * @return COM status code + * @param aMediumAttachment Reference to medium attachment object, the key. + */ + HRESULT Remove(const ComObjPtr<MediumAttachment> &aMediumAttachment); + + /** + * Clear all medium lock declarations in this map. + * + * @note Implicitly unlocks all locks. + * + * @return COM status code + */ + HRESULT Clear(); + + /** + * Get the medium lock list identified by the given key. + * + * @note May be used in locked state. + * + * @return COM status code + * @param aMediumAttachment Key for medium attachment object. + * @param aMediumLockList Out: medium attachment object reference. + */ + HRESULT Get(const ComObjPtr<MediumAttachment> &aMediumAttachment, MediumLockList * &aMediumLockList); + + /** + * Acquire all medium locks "atomically", i.e. all or nothing. + * + * @return COM status code + */ + HRESULT Lock(); + + /** + * Release all medium locks. + * + * @return COM status code + */ + HRESULT Unlock(); + +private: + typedef std::map<ComObjPtr<MediumAttachment>, MediumLockList *> Base; + Base mMediumLocks; + bool mIsLocked; +}; + +#endif /* !MAIN_INCLUDED_MediumLock_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/MouseImpl.h b/src/VBox/Main/include/MouseImpl.h new file mode 100644 index 00000000..f2b1439e --- /dev/null +++ b/src/VBox/Main/include/MouseImpl.h @@ -0,0 +1,175 @@ +/* $Id: MouseImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_MouseImpl_h +#define MAIN_INCLUDED_MouseImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "MouseWrap.h" +#include "ConsoleImpl.h" +#include "EventImpl.h" +#include <VBox/vmm/pdmdrv.h> + +/** Maximum number of devices supported */ +enum { MOUSE_MAX_DEVICES = 4 }; +/** Mouse driver instance data. */ +typedef struct DRVMAINMOUSE DRVMAINMOUSE, *PDRVMAINMOUSE; + +class ATL_NO_VTABLE Mouse : + public MouseWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS (Mouse) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(ConsoleMouseInterface *parent); + void uninit(); + + static const PDMDRVREG DrvReg; + + ConsoleMouseInterface *i_getParent() const + { + return mParent; + } + + /** notify the front-end of guest capability changes */ + void i_onVMMDevGuestCapsChange(uint32_t fCaps) + { + mfVMMDevGuestCaps = fCaps; + i_sendMouseCapsNotifications(); + } + + void updateMousePointerShape(bool fVisible, bool fAlpha, + uint32_t hotX, uint32_t hotY, + uint32_t width, uint32_t height, + const uint8_t *pu8Shape, uint32_t cbShape); +private: + + // Wrapped IMouse properties + HRESULT getAbsoluteSupported(BOOL *aAbsoluteSupported); + HRESULT getRelativeSupported(BOOL *aRelativeSupported); + HRESULT getTouchScreenSupported(BOOL *aTouchScreenSupported); + HRESULT getTouchPadSupported(BOOL *aTouchPadSupported); + HRESULT getNeedsHostCursor(BOOL *aNeedsHostCursor); + HRESULT getPointerShape(ComPtr<IMousePointerShape> &aPointerShape); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + + // Wrapped IMouse methods + HRESULT putMouseEvent(LONG aDx, + LONG aDy, + LONG aDz, + LONG aDw, + LONG aButtonState); + HRESULT putMouseEventAbsolute(LONG aX, + LONG aY, + LONG aDz, + LONG aDw, + LONG aButtonState); + HRESULT putEventMultiTouch(LONG aCount, + const std::vector<LONG64> &aContacts, + BOOL isTouchScreen, + ULONG aScanTime); + HRESULT putEventMultiTouchString(LONG aCount, + const com::Utf8Str &aContacts, + BOOL isTouchScreen, + ULONG aScanTime); + + + static DECLCALLBACK(void *) i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); + static DECLCALLBACK(void) i_mouseReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs, bool fMTAbs, bool fMTRel); + static DECLCALLBACK(int) i_drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) i_drvDestruct(PPDMDRVINS pDrvIns); + + HRESULT i_updateVMMDevMouseCaps(uint32_t fCapsAdded, uint32_t fCapsRemoved); + HRESULT i_reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz, + int32_t dw, uint32_t fButtons); + HRESULT i_reportAbsEventToMouseDev(int32_t x, int32_t y, int32_t dz, + int32_t dw, uint32_t fButtons); + HRESULT i_reportMTEventToMouseDev(int32_t x, int32_t z, uint32_t cContact, + uint32_t fContact); + HRESULT i_reportMultiTouchEventToDevice(uint8_t cContacts, const uint64_t *pau64Contacts, bool fTouchScreen, uint32_t u32ScanTime); + HRESULT i_reportAbsEventToVMMDev(int32_t x, int32_t y, int32_t dz, int32_t dw, uint32_t fButtons); + HRESULT i_reportAbsEventToInputDevices(int32_t x, int32_t y, int32_t dz, int32_t dw, uint32_t fButtons, + bool fUsesVMMDevEvent); + HRESULT i_reportAbsEventToDisplayDevice(int32_t x, int32_t y); + HRESULT i_convertDisplayRes(LONG x, LONG y, int32_t *pxAdj, int32_t *pyAdj, + bool *pfValid); + HRESULT i_putEventMultiTouch(LONG aCount, const LONG64 *paContacts, BOOL isTouchScreen, ULONG aScanTime); + + uint32_t i_getDeviceCaps(void); + void i_sendMouseCapsNotifications(void); + bool i_guestNeedsHostCursor(void); + bool i_vmmdevCanAbs(void); + bool i_deviceCanAbs(void); + bool i_supportsAbs(uint32_t fCaps) const; + bool i_supportsAbs(void); + bool i_supportsRel(void); + bool i_supportsTS(void); + bool i_supportsTP(void); + + ConsoleMouseInterface * const mParent; + /** Pointer to the associated mouse driver. */ + struct DRVMAINMOUSE *mpDrv[MOUSE_MAX_DEVICES]; + + uint32_t mfVMMDevGuestCaps; /** We cache this to avoid access races */ + int32_t mcLastX; + int32_t mcLastY; + uint32_t mfLastButtons; + + ComPtr<IMousePointerShape> mPointerShape; + struct + { + bool fVisible; + bool fAlpha; + uint32_t hotX; + uint32_t hotY; + uint32_t width; + uint32_t height; + uint8_t *pu8Shape; + uint32_t cbShape; + } mPointerData; + + const ComObjPtr<EventSource> mEventSource; + VBoxEventDesc mMouseEvent; + + void i_fireMouseEvent(bool fAbsolute, LONG x, LONG y, LONG dz, LONG dw, + LONG fButtons); + + void i_fireMultiTouchEvent(uint8_t cContacts, + const LONG64 *paContacts, + bool fTouchScreen, + uint32_t u32ScanTime); +}; + +#endif /* !MAIN_INCLUDED_MouseImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/NATEngineImpl.h b/src/VBox/Main/include/NATEngineImpl.h new file mode 100644 index 00000000..1abe61b5 --- /dev/null +++ b/src/VBox/Main/include/NATEngineImpl.h @@ -0,0 +1,124 @@ +/* $Id: NATEngineImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_NATEngineImpl_h +#define MAIN_INCLUDED_NATEngineImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "NATEngineWrap.h" + +namespace settings +{ + struct NAT; +} + + +class ATL_NO_VTABLE NATEngine : + public NATEngineWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(NATEngine) + + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT init(Machine *aParent, INetworkAdapter *aAdapter); + HRESULT init(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat); + HRESULT initCopy(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat); + void uninit(); + + bool i_isModified(); + void i_rollback(); + void i_commit(); + void i_copyFrom(NATEngine *aThat); + void i_applyDefaults(); + bool i_hasDefaults(); + HRESULT i_loadSettings(const settings::NAT &data); + HRESULT i_saveSettings(settings::NAT &data); + +private: + + // wrapped INATEngine properties + HRESULT setNetwork(const com::Utf8Str &aNetwork); + HRESULT getNetwork(com::Utf8Str &aNetwork); + HRESULT setHostIP(const com::Utf8Str &aHostIP); + HRESULT getHostIP(com::Utf8Str &aBindIP); + HRESULT setLocalhostReachable(BOOL fLocalhostReachable); + HRESULT getLocalhostReachable(BOOL *pfLocalhostReachable); + /* TFTP properties */ + HRESULT setTFTPPrefix(const com::Utf8Str &aTFTPPrefix); + HRESULT getTFTPPrefix(com::Utf8Str &aTFTPPrefix); + HRESULT setTFTPBootFile(const com::Utf8Str &aTFTPBootFile); + HRESULT getTFTPBootFile(com::Utf8Str &aTFTPBootFile); + HRESULT setTFTPNextServer(const com::Utf8Str &aTFTPNextServer); + HRESULT getTFTPNextServer(com::Utf8Str &aTFTPNextServer); + /* DNS properties */ + HRESULT setDNSPassDomain(BOOL aDNSPassDomain); + HRESULT getDNSPassDomain(BOOL *aDNSPassDomain); + HRESULT setDNSProxy(BOOL aDNSProxy); + HRESULT getDNSProxy(BOOL *aDNSProxy); + HRESULT getDNSUseHostResolver(BOOL *aDNSUseHostResolver); + HRESULT setDNSUseHostResolver(BOOL aDNSUseHostResolver); + /* Alias properties */ + HRESULT setAliasMode(ULONG aAliasMode); + HRESULT getAliasMode(ULONG *aAliasMode); + + HRESULT getRedirects(std::vector<com::Utf8Str> &aRedirects); + + HRESULT setNetworkSettings(ULONG aMtu, + ULONG aSockSnd, + ULONG aSockRcv, + ULONG aTcpWndSnd, + ULONG aTcpWndRcv); + + HRESULT getNetworkSettings(ULONG *aMtu, + ULONG *aSockSnd, + ULONG *aSockRcv, + ULONG *aTcpWndSnd, + ULONG *aTcpWndRcv); + + HRESULT addRedirect(const com::Utf8Str &aName, + NATProtocol_T aProto, + const com::Utf8Str &aHostIP, + USHORT aHostPort, + const com::Utf8Str &aGuestIP, + USHORT aGuestPort); + + HRESULT removeRedirect(const com::Utf8Str &aName); + + struct Data; + Data *mData; + const ComObjPtr<NATEngine> mPeer; + Machine * const mParent; + INetworkAdapter * const mAdapter; +}; +#endif /* !MAIN_INCLUDED_NATEngineImpl_h */ diff --git a/src/VBox/Main/include/NATNetworkImpl.h b/src/VBox/Main/include/NATNetworkImpl.h new file mode 100644 index 00000000..c2e1f7ac --- /dev/null +++ b/src/VBox/Main/include/NATNetworkImpl.h @@ -0,0 +1,143 @@ +/* $Id: NATNetworkImpl.h $ */ +/** @file + * INATNetwork implementation header, lives in VBoxSVC. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_NATNetworkImpl_h +#define MAIN_INCLUDED_NATNetworkImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VBoxEvents.h" +#include "NATNetworkWrap.h" + +#ifdef VBOX_WITH_HOSTNETIF_API +struct NETIFINFO; +#endif + +namespace settings +{ + struct NATNetwork; + struct NATRule; + typedef std::map<com::Utf8Str, NATRule> NATRulesMap; +} + +#ifdef RT_OS_WINDOWS +# define NATSR_EXECUTABLE_NAME "VBoxNetNAT.exe" +#else +# define NATSR_EXECUTABLE_NAME "VBoxNetNAT" +#endif + +#undef ADDR_ANY ///@todo ADDR_ANY collides with some windows header! + +enum ADDRESSLOOKUPTYPE +{ + ADDR_GATEWAY, + ADDR_DHCP, + ADDR_DHCPLOWERIP, + ADDR_ANY +}; + +class NATNetworkServiceRunner: public NetworkServiceRunner +{ +public: + NATNetworkServiceRunner(): NetworkServiceRunner(NATSR_EXECUTABLE_NAME){} + ~NATNetworkServiceRunner(){} +}; + +class ATL_NO_VTABLE NATNetwork : + public NATNetworkWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(NATNetwork) + + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT init(VirtualBox *aVirtualBox, com::Utf8Str aName); + HRESULT i_loadSettings(const settings::NATNetwork &data); + void uninit(); + HRESULT i_saveSettings(settings::NATNetwork &data); + +private: + + // Wrapped INATNetwork properties + HRESULT getNetworkName(com::Utf8Str &aNetworkName); + HRESULT setNetworkName(const com::Utf8Str &aNetworkName); + HRESULT getEnabled(BOOL *aEnabled); + HRESULT setEnabled(BOOL aEnabled); + HRESULT getNetwork(com::Utf8Str &aNetwork); + HRESULT setNetwork(const com::Utf8Str &aNetwork); + HRESULT getGateway(com::Utf8Str &aGateway); + HRESULT getIPv6Enabled(BOOL *aIPv6Enabled); + HRESULT setIPv6Enabled(BOOL aIPv6Enabled); + HRESULT getIPv6Prefix(com::Utf8Str &aIPv6Prefix); + HRESULT setIPv6Prefix(const com::Utf8Str &aIPv6Prefix); + HRESULT getAdvertiseDefaultIPv6RouteEnabled(BOOL *aAdvertiseDefaultIPv6RouteEnabled); + HRESULT setAdvertiseDefaultIPv6RouteEnabled(BOOL aAdvertiseDefaultIPv6RouteEnabled); + HRESULT getNeedDhcpServer(BOOL *aNeedDhcpServer); + HRESULT setNeedDhcpServer(BOOL aNeedDhcpServer); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + HRESULT getPortForwardRules4(std::vector<com::Utf8Str> &aPortForwardRules4); + HRESULT getLocalMappings(std::vector<com::Utf8Str> &aLocalMappings); + HRESULT getLoopbackIp6(LONG *aLoopbackIp6); + HRESULT setLoopbackIp6(LONG aLoopbackIp6); + HRESULT getPortForwardRules6(std::vector<com::Utf8Str> &aPortForwardRules6); + + // wrapped INATNetwork methods + HRESULT addLocalMapping(const com::Utf8Str &aHostid, + LONG aOffset); + HRESULT addPortForwardRule(BOOL aIsIpv6, + const com::Utf8Str &aRuleName, + NATProtocol_T aProto, + const com::Utf8Str &aHostIP, + USHORT aHostPort, + const com::Utf8Str &aGuestIP, + USHORT aGuestPort); + HRESULT removePortForwardRule(BOOL aISipv6, + const com::Utf8Str &aRuleName); + HRESULT start(); + HRESULT stop(); + + // Internal methods + HRESULT setErrorBusy(); + + int i_recalculateIpv4AddressAssignments(); + int i_findFirstAvailableOffset(ADDRESSLOOKUPTYPE, uint32_t *); + int i_recalculateIPv6Prefix(); + + void i_getPortForwardRulesFromMap(std::vector<Utf8Str> &aPortForwardRules, settings::NATRulesMap &aRules); + + void i_updateDnsOptions(); + void i_updateDomainNameOption(ComPtr<IHost> &host); + void i_updateDomainNameServerOption(ComPtr<IHost> &host); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_NATNetworkImpl_h */ diff --git a/src/VBox/Main/include/NetworkAdapterImpl.h b/src/VBox/Main/include/NetworkAdapterImpl.h new file mode 100644 index 00000000..ca03c118 --- /dev/null +++ b/src/VBox/Main/include/NetworkAdapterImpl.h @@ -0,0 +1,141 @@ +/* $Id: NetworkAdapterImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_NetworkAdapterImpl_h +#define MAIN_INCLUDED_NetworkAdapterImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "NetworkAdapterWrap.h" + +class GuestOSType; +class BandwidthControl; +class BandwidthGroup; +class NATEngine; + +namespace settings +{ + struct NetworkAdapter; +} + +class ATL_NO_VTABLE NetworkAdapter : + public NetworkAdapterWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(NetworkAdapter) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent, ULONG aSlot); + HRESULT init(Machine *aParent, NetworkAdapter *aThat, bool aReshare = false); + HRESULT initCopy(Machine *aParent, NetworkAdapter *aThat); + void uninit(); + + // public methods only for internal purposes + HRESULT i_loadSettings(BandwidthControl *bwctl, const settings::NetworkAdapter &data); + HRESULT i_saveSettings(settings::NetworkAdapter &data); + + bool i_isModified(); + void i_rollback(); + void i_commit(); + void i_copyFrom(NetworkAdapter *aThat); + void i_applyDefaults(GuestOSType *aOsType); + bool i_hasDefaults(); + + ComObjPtr<NetworkAdapter> i_getPeer(); + +private: + + // wrapped INetworkAdapter properties + HRESULT getAdapterType(NetworkAdapterType_T *aAdapterType); + HRESULT setAdapterType(NetworkAdapterType_T aAdapterType); + HRESULT getSlot(ULONG *aSlot); + HRESULT getEnabled(BOOL *aEnabled); + HRESULT setEnabled(BOOL aEnabled); + HRESULT getMACAddress(com::Utf8Str &aMACAddress); + HRESULT setMACAddress(const com::Utf8Str &aMACAddress); + HRESULT getAttachmentType(NetworkAttachmentType_T *aAttachmentType); + HRESULT setAttachmentType(NetworkAttachmentType_T aAttachmentType); + HRESULT getBridgedInterface(com::Utf8Str &aBridgedInterface); + HRESULT setBridgedInterface(const com::Utf8Str &aBridgedInterface); + HRESULT getHostOnlyInterface(com::Utf8Str &aHostOnlyInterface); + HRESULT setHostOnlyInterface(const com::Utf8Str &aHostOnlyInterface); + HRESULT getHostOnlyNetwork(com::Utf8Str &aHostOnlyNetwork); + HRESULT setHostOnlyNetwork(const com::Utf8Str &aHostOnlyNetwork); + HRESULT getInternalNetwork(com::Utf8Str &aInternalNetwork); + HRESULT setInternalNetwork(const com::Utf8Str &aInternalNetwork); + HRESULT getNATNetwork(com::Utf8Str &aNATNetwork); + HRESULT setNATNetwork(const com::Utf8Str &aNATNetwork); + HRESULT getGenericDriver(com::Utf8Str &aGenericDriver); + HRESULT setGenericDriver(const com::Utf8Str &aGenericDriver); + HRESULT getCloudNetwork(com::Utf8Str &aCloudNetwork); + HRESULT setCloudNetwork(const com::Utf8Str &aCloudNetwork); + HRESULT getCableConnected(BOOL *aCableConnected); + HRESULT setCableConnected(BOOL aCableConnected); + HRESULT getLineSpeed(ULONG *aLineSpeed); + HRESULT setLineSpeed(ULONG aLineSpeed); + HRESULT getPromiscModePolicy(NetworkAdapterPromiscModePolicy_T *aPromiscModePolicy); + HRESULT setPromiscModePolicy(NetworkAdapterPromiscModePolicy_T aPromiscModePolicy); + HRESULT getTraceEnabled(BOOL *aTraceEnabled); + HRESULT setTraceEnabled(BOOL aTraceEnabled); + HRESULT getTraceFile(com::Utf8Str &aTraceFile); + HRESULT setTraceFile(const com::Utf8Str &aTraceFile); + HRESULT getNATEngine(ComPtr<INATEngine> &aNATEngine); + HRESULT getBootPriority(ULONG *aBootPriority); + HRESULT setBootPriority(ULONG aBootPriority); + HRESULT getBandwidthGroup(ComPtr<IBandwidthGroup> &aBandwidthGroup); + HRESULT setBandwidthGroup(const ComPtr<IBandwidthGroup> &aBandwidthGroup); + + // wrapped INetworkAdapter methods + HRESULT getProperty(const com::Utf8Str &aKey, + com::Utf8Str &aValue); + HRESULT setProperty(const com::Utf8Str &aKey, + const com::Utf8Str &aValue); + HRESULT getProperties(const com::Utf8Str &aNames, + std::vector<com::Utf8Str> &aReturnNames, + std::vector<com::Utf8Str> &aReturnValues); + // Misc. + void i_generateMACAddress(); + HRESULT i_updateMacAddress(Utf8Str aMacAddress); + void i_updateBandwidthGroup(BandwidthGroup *aBwGroup); + HRESULT i_switchFromNatNetworking(const com::Utf8Str &aNatnetworkName); + HRESULT i_switchToNatNetworking(const com::Utf8Str &aNatNetworkName); + + + Machine * const mParent; + const ComObjPtr<NetworkAdapter> mPeer; + const ComObjPtr<NATEngine> mNATEngine; + + Backupable<settings::NetworkAdapter> mData; +}; + +#endif /* !MAIN_INCLUDED_NetworkAdapterImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/NetworkServiceRunner.h b/src/VBox/Main/include/NetworkServiceRunner.h new file mode 100644 index 00000000..ea3b840d --- /dev/null +++ b/src/VBox/Main/include/NetworkServiceRunner.h @@ -0,0 +1,87 @@ +/* $Id: NetworkServiceRunner.h $ */ +/** @file + * VirtualBox Main - interface for VBox DHCP server. + */ + +/* + * Copyright (C) 2009-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_NetworkServiceRunner_h +#define MAIN_INCLUDED_NetworkServiceRunner_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/string.h> + + +/** @name Internal networking trunk type option values (NetworkServiceRunner::kpszKeyTrunkType) + * @{ */ +#define TRUNKTYPE_WHATEVER "whatever" +#define TRUNKTYPE_NETFLT "netflt" +#define TRUNKTYPE_NETADP "netadp" +#define TRUNKTYPE_SRVNAT "srvnat" +/** @} */ + +/** + * Network service runner. + * + * Build arguments, starts and stops network service processes. + */ +class NetworkServiceRunner +{ +public: + NetworkServiceRunner(const char *aProcName); + virtual ~NetworkServiceRunner(); + + /** @name Argument management + * @{ */ + int addArgument(const char *pszArgument); + int addArgPair(const char *pszOption, const char *pszValue); + void resetArguments(); + /** @} */ + + int start(bool aKillProcessOnStop); + int stop(); + void detachFromServer(); + bool isRunning(); + + RTPROCESS getPid() const; + + /** @name Common options + * @{ */ + static const char * const kpszKeyNetwork; + static const char * const kpszKeyTrunkType; + static const char * const kpszTrunkName; + static const char * const kpszMacAddress; + static const char * const kpszIpAddress; + static const char * const kpszIpNetmask; + static const char * const kpszKeyNeedMain; + /** @} */ + +private: + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_NetworkServiceRunner_h */ + diff --git a/src/VBox/Main/include/NvramStoreImpl.h b/src/VBox/Main/include/NvramStoreImpl.h new file mode 100644 index 00000000..bb637689 --- /dev/null +++ b/src/VBox/Main/include/NvramStoreImpl.h @@ -0,0 +1,156 @@ +/* $Id: NvramStoreImpl.h $ */ +/** @file + * VirtualBox COM NVRAM store class implementation + */ + +/* + * Copyright (C) 2021-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_NvramStoreImpl_h +#define MAIN_INCLUDED_NvramStoreImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "NvramStoreWrap.h" +#include "SecretKeyStore.h" +#include <VBox/vmm/pdmdrv.h> +#include <VBox/VBoxCryptoIf.h> + + +#ifdef VBOX_COM_INPROC +class Console; +#else +class GuestOSType; + +namespace settings +{ + struct NvramSettings; +} +#endif + +class ATL_NO_VTABLE NvramStore : + public NvramStoreWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(NvramStore) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only +#ifdef VBOX_COM_INPROC + HRESULT init(Console *aParent, const com::Utf8Str &strNonVolatileStorageFile); +#else + HRESULT init(Machine *parent); + HRESULT init(Machine *parent, NvramStore *that); + HRESULT initCopy(Machine *parent, NvramStore *that); +#endif + void uninit(); + + // public methods for internal purposes only +#ifndef VBOX_COM_INPROC + HRESULT i_loadSettings(const settings::NvramSettings &data); + HRESULT i_saveSettings(settings::NvramSettings &data); +#endif + +#ifdef VBOX_COM_INPROC + static const PDMDRVREG DrvReg; +#else + void i_rollback(); + void i_commit(); + void i_copyFrom(NvramStore *aThat); + HRESULT i_applyDefaults(GuestOSType *aOSType); +#endif + + com::Utf8Str i_getNonVolatileStorageFile(); + void i_updateNonVolatileStorageFile(const com::Utf8Str &aNonVolatileStorageFile); + + int i_loadStore(const char *pszPath); + int i_saveStore(void); + +#ifndef VBOX_COM_INPROC + HRESULT i_retainUefiVarStore(PRTVFS phVfs, bool fReadonly); + HRESULT i_releaseUefiVarStore(RTVFS hVfs); +#endif + +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION + HRESULT i_updateEncryptionSettings(const com::Utf8Str &strKeyId, + const com::Utf8Str &strKeyStore); + HRESULT i_getEncryptionSettings(com::Utf8Str &strKeyId, + com::Utf8Str &strKeyStore); + + int i_addPassword(const Utf8Str &strKeyId, const Utf8Str &strPassword); + int i_removePassword(const Utf8Str &strKeyId); + int i_removeAllPasswords(); +#endif + +private: + + int initImpl(void); + + // Wrapped NVRAM store properties + HRESULT getNonVolatileStorageFile(com::Utf8Str &aNonVolatileStorageFile); + HRESULT getUefiVariableStore(ComPtr<IUefiVariableStore> &aUefiVarStore); + HRESULT getKeyId(com::Utf8Str &aKeyId); + HRESULT getKeyStore(com::Utf8Str &aKeyStore); + + // Wrapped NVRAM store members + HRESULT initUefiVariableStore(ULONG aSize); + + int i_loadStoreFromTar(RTVFSFSSTREAM hVfsFssTar); + int i_saveStoreAsTar(const char *pszPath); + + int i_retainCryptoIf(PCVBOXCRYPTOIF *ppCryptoIf); + int i_releaseCryptoIf(PCVBOXCRYPTOIF pCryptoIf); + +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION + int i_setupEncryptionOrDecryption(RTVFSIOSTREAM hVfsIosInOut, bool fEncrypt, + PCVBOXCRYPTOIF *ppCryptoIf, SecretKey **ppKey, + PRTVFSIOSTREAM phVfsIos); + void i_releaseEncryptionOrDecryptionResources(RTVFSIOSTREAM hVfsIos, PCVBOXCRYPTOIF pCryptoIf, + SecretKey *pKey); +#endif + +#ifdef VBOX_COM_INPROC + static DECLCALLBACK(int) i_SsmSaveExec(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM); + static DECLCALLBACK(int) i_SsmLoadExec(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass); + + static DECLCALLBACK(int) i_nvramStoreQuerySize(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath, + uint64_t *pcb); + static DECLCALLBACK(int) i_nvramStoreReadAll(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath, + void *pvBuf, size_t cbRead); + static DECLCALLBACK(int) i_nvramStoreWriteAll(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath, + const void *pvBuf, size_t cbWrite); + static DECLCALLBACK(int) i_nvramStoreDelete(PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath); + static DECLCALLBACK(void *) i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); + static DECLCALLBACK(int) i_drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) i_drvDestruct(PPDMDRVINS pDrvIns); +#endif + + struct Data; // opaque data struct, defined in NvramStoreImpl.cpp + Data *m; +}; + +#endif /* !MAIN_INCLUDED_NvramStoreImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/ObjectState.h b/src/VBox/Main/include/ObjectState.h new file mode 100644 index 00000000..669af905 --- /dev/null +++ b/src/VBox/Main/include/ObjectState.h @@ -0,0 +1,150 @@ +/* $Id: ObjectState.h $ */ +/** @file + * + * VirtualBox object state handling definitions + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ObjectState_h +#define MAIN_INCLUDED_ObjectState_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VBox/com/defs.h" +#include "VBox/com/AutoLock.h" +#include "VBox/com/ErrorInfo.h" + +// Forward declaration needed, but nothing more. +class VirtualBoxBase; + +//////////////////////////////////////////////////////////////////////////////// +// +// ObjectState +// +//////////////////////////////////////////////////////////////////////////////// + +/** + * Thec functionality implemented by this class is the primary object state + * (used by VirtualBoxBase and thus part of all API classes) that indicates + * if the object is ready to serve the calls, and if not, what stage it is + * currently at. Here is the primary state diagram: + * + * +-------------------------------------------------------+ + * | | + * | (InitFailed) -----------------------+ | + * | ^ | | + * v | v | + * [*] ---> NotReady ----> (InInit) -----> Ready -----> (InUninit) ----+ + * ^ | + * | v + * | Limited + * | | + * +-------+ + * + * The object is fully operational only when its state is Ready. The Limited + * state means that only some vital part of the object is operational, and it + * requires some sort of reinitialization to become fully operational. The + * NotReady state means the object is basically dead: it either was not yet + * initialized after creation at all, or was uninitialized and is waiting to be + * destroyed when the last reference to it is released. All other states are + * transitional. + * + * The NotReady->InInit->Ready, NotReady->InInit->Limited and + * NotReady->InInit->InitFailed transition is done by the AutoInitSpan smart + * class. + * + * The Limited->InInit->Ready, Limited->InInit->Limited and + * Limited->InInit->InitFailed transition is done by the AutoReinitSpan smart + * class. + * + * The Ready->InUninit->NotReady and InitFailed->InUninit->NotReady + * transitions are done by the AutoUninitSpan smart class. + * + * In order to maintain the primary state integrity and declared functionality + * the following rules apply everywhere: + * + * 1) Use the above Auto*Span classes to perform state transitions. See the + * individual class descriptions for details. + * + * 2) All public methods of subclasses (i.e. all methods that can be called + * directly, not only from within other methods of the subclass) must have a + * standard prolog as described in the AutoCaller and AutoLimitedCaller + * documentation. Alternatively, they must use #addCaller() and + * #releaseCaller() directly (and therefore have both the prolog and the + * epilog), but this is not recommended because it is easy to forget the + * matching release, e.g. returning before reaching the call. + */ +class ObjectState +{ +public: + enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited }; + + ObjectState(VirtualBoxBase *aObj); + ~ObjectState(); + + State getState(); + + HRESULT addCaller(bool aLimited = false); + void releaseCaller(); + + bool autoInitSpanConstructor(State aExpectedState); + void autoInitSpanDestructor(State aNewState, HRESULT aFailedRC, com::ErrorInfo *aFailedEI); + State autoUninitSpanConstructor(bool fTry); + void autoUninitSpanDestructor(); + +private: + ObjectState(); + + void setState(State aState); + + /** Pointer to the managed object, mostly for error signalling or debugging + * purposes, not used much. Guaranteed to be valid during the lifetime of + * this object, no need to mess with refcount. */ + VirtualBoxBase *mObj; + /** Primary state of this object */ + State mState; + /** Thread that caused the last state change */ + RTTHREAD mStateChangeThread; + /** Result code for failed object initialization */ + HRESULT mFailedRC; + /** Error information for failed object initialization */ + com::ErrorInfo *mpFailedEI; + /** Total number of active calls to this object */ + unsigned mCallers; + /** Posted when the number of callers drops to zero */ + RTSEMEVENT mZeroCallersSem; + /** Posted when the object goes from InInit/InUninit to some other state */ + RTSEMEVENTMULTI mInitUninitSem; + /** Number of threads waiting for mInitUninitDoneSem */ + unsigned mInitUninitWaiters; + + /** Protects access to state related data members */ + util::RWLockHandle mStateLock; + +private: + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(ObjectState); /* Shuts up MSC warning C4625. */ +}; + +#endif /* !MAIN_INCLUDED_ObjectState_h */ diff --git a/src/VBox/Main/include/PCIDeviceAttachmentImpl.h b/src/VBox/Main/include/PCIDeviceAttachmentImpl.h new file mode 100644 index 00000000..9f3998c0 --- /dev/null +++ b/src/VBox/Main/include/PCIDeviceAttachmentImpl.h @@ -0,0 +1,79 @@ +/* $Id: PCIDeviceAttachmentImpl.h $ */ + +/** @file + * + * PCI attachment information implmentation. + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_PCIDeviceAttachmentImpl_h +#define MAIN_INCLUDED_PCIDeviceAttachmentImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "PCIDeviceAttachmentWrap.h" + +namespace settings +{ + struct HostPCIDeviceAttachment; +} + +class ATL_NO_VTABLE PCIDeviceAttachment : + public PCIDeviceAttachmentWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(PCIDeviceAttachment) + + // public initializer/uninitializer for internal purposes only + HRESULT init(IMachine * aParent, + const Utf8Str &aDevName, + LONG aHostAddess, + LONG aGuestAddress, + BOOL fPhysical); + HRESULT initCopy(IMachine *aParent, PCIDeviceAttachment *aThat); + void uninit(); + + // settings + HRESULT i_loadSettings(IMachine * aParent, + const settings::HostPCIDeviceAttachment& aHpda); + HRESULT i_saveSettings(settings::HostPCIDeviceAttachment &data); + + HRESULT FinalConstruct(); + void FinalRelease(); + +private: + + // wrapped IPCIDeviceAttachment properties + HRESULT getName(com::Utf8Str &aName); + HRESULT getIsPhysicalDevice(BOOL *aIsPhysicalDevice); + HRESULT getHostAddress(LONG *aHostAddress); + HRESULT getGuestAddress(LONG *aGuestAddress); + + struct Data; + Data* m; +}; + +#endif /* !MAIN_INCLUDED_PCIDeviceAttachmentImpl_h */ diff --git a/src/VBox/Main/include/PCIRawDevImpl.h b/src/VBox/Main/include/PCIRawDevImpl.h new file mode 100644 index 00000000..6d5923b9 --- /dev/null +++ b/src/VBox/Main/include/PCIRawDevImpl.h @@ -0,0 +1,64 @@ +/* $Id: PCIRawDevImpl.h $ */ +/** @file + * VirtualBox Driver interface to raw PCI device + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_PCIRawDevImpl_h +#define MAIN_INCLUDED_PCIRawDevImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/vmm/pdmdrv.h> + +class Console; +struct DRVMAINPCIRAWDEV; + +class PCIRawDev +{ + public: + PCIRawDev(Console *console); + virtual ~PCIRawDev(); + + static const PDMDRVREG DrvReg; + + Console *getParent() const + { + return mParent; + } + + private: + static DECLCALLBACK(void *) drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); + static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns); + static DECLCALLBACK(int) drvDeviceConstructComplete(PPDMIPCIRAWCONNECTOR pInterface, const char *pcszName, + uint32_t uHostPCIAddress, uint32_t uGuestPCIAddress, + int rc); + + Console * const mParent; + struct DRVMAINPCIRAWDEV *mpDrv; +}; + +#endif /* !MAIN_INCLUDED_PCIRawDevImpl_h */ diff --git a/src/VBox/Main/include/ParallelPortImpl.h b/src/VBox/Main/include/ParallelPortImpl.h new file mode 100644 index 00000000..a3b79143 --- /dev/null +++ b/src/VBox/Main/include/ParallelPortImpl.h @@ -0,0 +1,87 @@ +/* $Id: ParallelPortImpl.h $ */ + +/** @file + * VirtualBox COM class implementation. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ParallelPortImpl_h +#define MAIN_INCLUDED_ParallelPortImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "ParallelPortWrap.h" + +namespace settings +{ + struct ParallelPort; +} + +class ATL_NO_VTABLE ParallelPort : + public ParallelPortWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(ParallelPort) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent, ULONG aSlot); + HRESULT init(Machine *aParent, ParallelPort *aThat); + HRESULT initCopy(Machine *parent, ParallelPort *aThat); + void uninit(); + + HRESULT i_loadSettings(const settings::ParallelPort &data); + HRESULT i_saveSettings(settings::ParallelPort &data); + + // public methods only for internal purposes + bool i_isModified(); + void i_rollback(); + void i_commit(); + void i_copyFrom(ParallelPort *aThat); + void i_applyDefaults(); + bool i_hasDefaults(); + +private: + + // Wrapped IParallelPort properties + HRESULT getEnabled(BOOL *aEnabled); + HRESULT setEnabled(BOOL aEnabled); + HRESULT getSlot(ULONG *aSlot); + HRESULT getIRQ(ULONG *aIRQ); + HRESULT setIRQ(ULONG aIRQ); + HRESULT getIOBase(ULONG *aIOBase); + HRESULT setIOBase(ULONG aIOBase); + HRESULT getPath(com::Utf8Str &aPath); + HRESULT setPath(const com::Utf8Str &aPath); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_ParallelPortImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/Performance.h b/src/VBox/Main/include/Performance.h new file mode 100644 index 00000000..1c092558 --- /dev/null +++ b/src/VBox/Main/include/Performance.h @@ -0,0 +1,915 @@ +/* $Id: Performance.h $ */ +/** @file + * VirtualBox Main - Performance Classes declaration. + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_Performance_h +#define MAIN_INCLUDED_Performance_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/defs.h> +#include <VBox/com/ptr.h> +#include <VBox/com/string.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/types.h> +#include <iprt/err.h> +#include <iprt/cpp/lock.h> + +#include <algorithm> +#include <functional> /* For std::fun_ptr in testcase */ +#include <list> +#include <vector> +#include <queue> + +#include "MediumImpl.h" + +/* Forward decl. */ +class Machine; + +namespace pm +{ + /* CPU load is measured in 1/1000 of per cent. */ + const uint64_t PM_CPU_LOAD_MULTIPLIER = UINT64_C(100000); + /* Network load is measured in 1/1000 of per cent. */ + const uint64_t PM_NETWORK_LOAD_MULTIPLIER = UINT64_C(100000); + /* Disk load is measured in 1/1000 of per cent. */ + const uint64_t PM_DISK_LOAD_MULTIPLIER = UINT64_C(100000); + /* Sampler precision in milliseconds. */ + const uint64_t PM_SAMPLER_PRECISION_MS = 50; + + /* Sub Metrics **********************************************************/ + class CircularBuffer + { + public: + CircularBuffer() : mData(0), mLength(0), mEnd(0), mWrapped(false) {}; + ~CircularBuffer() { if (mData) RTMemFree(mData); }; + void init(ULONG length); + ULONG length(); + ULONG getSequenceNumber() { return mSequenceNumber; } + void put(ULONG value); + void copyTo(ULONG *data); + private: + ULONG *mData; + ULONG mLength; + ULONG mEnd; + ULONG mSequenceNumber; + bool mWrapped; + }; + + class SubMetric : public CircularBuffer + { + public: + SubMetric(com::Utf8Str name, const char *description) + : mName(name), mDescription(description) {}; + void query(ULONG *data); + const char *getName() { return mName.c_str(); }; + const char *getDescription() { return mDescription; }; + private: + const com::Utf8Str mName; + const char *mDescription; + }; + + + enum { + COLLECT_NONE = 0x0, + COLLECT_CPU_LOAD = 0x1, + COLLECT_RAM_USAGE = 0x2, + COLLECT_GUEST_STATS = 0x4 + }; + typedef int HintFlags; + typedef std::pair<RTPROCESS, HintFlags> ProcessFlagsPair; + + class CollectorHints + { + public: + typedef std::list<ProcessFlagsPair> ProcessList; + + CollectorHints() : mHostFlags(COLLECT_NONE) {} + void collectHostCpuLoad() + { mHostFlags |= COLLECT_CPU_LOAD; } + void collectHostRamUsage() + { mHostFlags |= COLLECT_RAM_USAGE; } + void collectHostRamVmm() + { mHostFlags |= COLLECT_GUEST_STATS; } + void collectProcessCpuLoad(RTPROCESS process) + { findProcess(process).second |= COLLECT_CPU_LOAD; } + void collectProcessRamUsage(RTPROCESS process) + { findProcess(process).second |= COLLECT_RAM_USAGE; } + void collectGuestStats(RTPROCESS process) + { findProcess(process).second |= COLLECT_GUEST_STATS; } + bool isHostCpuLoadCollected() const + { return (mHostFlags & COLLECT_CPU_LOAD) != 0; } + bool isHostRamUsageCollected() const + { return (mHostFlags & COLLECT_RAM_USAGE) != 0; } + bool isHostRamVmmCollected() const + { return (mHostFlags & COLLECT_GUEST_STATS) != 0; } + bool isProcessCpuLoadCollected(RTPROCESS process) + { return (findProcess(process).second & COLLECT_CPU_LOAD) != 0; } + bool isProcessRamUsageCollected(RTPROCESS process) + { return (findProcess(process).second & COLLECT_RAM_USAGE) != 0; } + bool isGuestStatsCollected(RTPROCESS process) + { return (findProcess(process).second & COLLECT_GUEST_STATS) != 0; } + void getProcesses(std::vector<RTPROCESS>& processes) const + { + processes.clear(); + processes.reserve(mProcesses.size()); + for (ProcessList::const_iterator it = mProcesses.begin(); it != mProcesses.end(); ++it) + processes.push_back(it->first); + } + const ProcessList& getProcessFlags() const + { + return mProcesses; + } + private: + HintFlags mHostFlags; + ProcessList mProcesses; + + ProcessFlagsPair& findProcess(RTPROCESS process) + { + ProcessList::iterator it; + for (it = mProcesses.begin(); it != mProcesses.end(); ++it) + if (it->first == process) + return *it; + + /* Not found -- add new */ + mProcesses.push_back(ProcessFlagsPair(process, COLLECT_NONE)); + return mProcesses.back(); + } + }; + + /* Guest Collector Classes *********************************/ + /* + * WARNING! The bits in the following masks must correspond to parameters + * of CollectorGuest::updateStats(). + */ + typedef enum + { + VMSTATMASK_NONE = 0x00000000, + VMSTATMASK_GUEST_CPUUSER = 0x00000001, + VMSTATMASK_GUEST_CPUKERNEL = 0x00000002, + VMSTATMASK_GUEST_CPUIDLE = 0x00000004, + VMSTATMASK_GUEST_MEMTOTAL = 0x00000008, + VMSTATMASK_GUEST_MEMFREE = 0x00000010, + VMSTATMASK_GUEST_MEMBALLOON = 0x00000020, + VMSTATMASK_GUEST_MEMSHARED = 0x00000040, + VMSTATMASK_GUEST_MEMCACHE = 0x00000080, + VMSTATMASK_GUEST_PAGETOTAL = 0x00000100, + VMSTATMASK_VMM_ALLOC = 0x00010000, + VMSTATMASK_VMM_FREE = 0x00020000, + VMSTATMASK_VMM_BALOON = 0x00040000, + VMSTATMASK_VMM_SHARED = 0x00080000, + VMSTATMASK_NET_RX = 0x01000000, + VMSTATMASK_NET_TX = 0x02000000 + } VMSTATMASK; + + const ULONG VMSTATS_GUEST_CPULOAD = + VMSTATMASK_GUEST_CPUUSER | VMSTATMASK_GUEST_CPUKERNEL | + VMSTATMASK_GUEST_CPUIDLE; + const ULONG VMSTATS_GUEST_RAMUSAGE = + VMSTATMASK_GUEST_MEMTOTAL | VMSTATMASK_GUEST_MEMFREE | + VMSTATMASK_GUEST_MEMBALLOON | VMSTATMASK_GUEST_MEMSHARED | + VMSTATMASK_GUEST_MEMCACHE | VMSTATMASK_GUEST_PAGETOTAL; + const ULONG VMSTATS_VMM_RAM = + VMSTATMASK_VMM_ALLOC | VMSTATMASK_VMM_FREE| + VMSTATMASK_VMM_BALOON | VMSTATMASK_VMM_SHARED; + const ULONG VMSTATS_NET_RATE = + VMSTATMASK_NET_RX | VMSTATMASK_NET_TX; + const ULONG VMSTATS_ALL = + VMSTATS_GUEST_CPULOAD | VMSTATS_GUEST_RAMUSAGE | + VMSTATS_VMM_RAM | VMSTATS_NET_RATE; + class CollectorGuest; + + class CollectorGuestRequest + { + public: + CollectorGuestRequest() + : mCGuest(0) {}; + virtual ~CollectorGuestRequest() {}; + void setGuest(CollectorGuest *aGuest) { mCGuest = aGuest; }; + CollectorGuest *getGuest() { return mCGuest; }; + virtual HRESULT execute() = 0; + + virtual void debugPrint(void *aObject, const char *aFunction, const char *aText) = 0; + protected: + CollectorGuest *mCGuest; + const char *mDebugName; + }; + + class CGRQEnable : public CollectorGuestRequest + { + public: + CGRQEnable(ULONG aMask) + : mMask(aMask) {}; + HRESULT execute(); + + void debugPrint(void *aObject, const char *aFunction, const char *aText); + private: + ULONG mMask; + }; + + class CGRQDisable : public CollectorGuestRequest + { + public: + CGRQDisable(ULONG aMask) + : mMask(aMask) {}; + HRESULT execute(); + + void debugPrint(void *aObject, const char *aFunction, const char *aText); + private: + ULONG mMask; + }; + + class CGRQAbort : public CollectorGuestRequest + { + public: + CGRQAbort() {}; + HRESULT execute(); + + void debugPrint(void *aObject, const char *aFunction, const char *aText); + }; + + class CollectorGuestQueue + { + public: + CollectorGuestQueue(); + ~CollectorGuestQueue(); + void push(CollectorGuestRequest* rq); + CollectorGuestRequest* pop(); + private: + RTCLockMtx mLockMtx; + RTSEMEVENT mEvent; + std::queue<CollectorGuestRequest*> mQueue; + }; + + class CollectorGuestManager; + + class CollectorGuest + { + public: + CollectorGuest(Machine *machine, RTPROCESS process); + ~CollectorGuest(); + + void setManager(CollectorGuestManager *aManager) + { mManager = aManager; }; + bool isUnregistered() { return mUnregistered; }; + bool isEnabled() { return mEnabled != 0; }; + bool isValid(ULONG mask) { return (mValid & mask) == mask; }; + void invalidate(ULONG mask) { mValid &= ~mask; }; + void unregister() { mUnregistered = true; }; + void updateStats(ULONG aValidStats, ULONG aCpuUser, + ULONG aCpuKernel, ULONG aCpuIdle, + ULONG aMemTotal, ULONG aMemFree, + ULONG aMemBalloon, ULONG aMemShared, + ULONG aMemCache, ULONG aPageTotal, + ULONG aAllocVMM, ULONG aFreeVMM, + ULONG aBalloonedVMM, ULONG aSharedVMM, + ULONG aVmNetRx, ULONG aVmNetTx); + HRESULT enable(ULONG mask); + HRESULT disable(ULONG mask); + + HRESULT enqueueRequest(CollectorGuestRequest *aRequest); + HRESULT enableInternal(ULONG mask); + HRESULT disableInternal(ULONG mask); + + const com::Utf8Str& getVMName() const { return mMachineName; }; + + RTPROCESS getProcess() { return mProcess; }; + ULONG getCpuUser() { return mCpuUser; }; + ULONG getCpuKernel() { return mCpuKernel; }; + ULONG getCpuIdle() { return mCpuIdle; }; + ULONG getMemTotal() { return mMemTotal; }; + ULONG getMemFree() { return mMemFree; }; + ULONG getMemBalloon() { return mMemBalloon; }; + ULONG getMemShared() { return mMemShared; }; + ULONG getMemCache() { return mMemCache; }; + ULONG getPageTotal() { return mPageTotal; }; + ULONG getAllocVMM() { return mAllocVMM; }; + ULONG getFreeVMM() { return mFreeVMM; }; + ULONG getBalloonedVMM() { return mBalloonedVMM; }; + ULONG getSharedVMM() { return mSharedVMM; }; + ULONG getVmNetRx() { return mVmNetRx; }; + ULONG getVmNetTx() { return mVmNetTx; }; + + private: + HRESULT enableVMMStats(bool mCollectVMMStats); + + CollectorGuestManager *mManager; + + bool mUnregistered; + ULONG mEnabled; + ULONG mValid; + Machine *mMachine; + com::Utf8Str mMachineName; + RTPROCESS mProcess; + ComPtr<IConsole> mConsole; + ComPtr<IGuest> mGuest; + ULONG mCpuUser; + ULONG mCpuKernel; + ULONG mCpuIdle; + ULONG mMemTotal; + ULONG mMemFree; + ULONG mMemBalloon; + ULONG mMemShared; + ULONG mMemCache; + ULONG mPageTotal; + ULONG mAllocVMM; + ULONG mFreeVMM; + ULONG mBalloonedVMM; + ULONG mSharedVMM; + ULONG mVmNetRx; + ULONG mVmNetTx; + }; + + typedef std::list<CollectorGuest*> CollectorGuestList; + class CollectorGuestManager + { + public: + CollectorGuestManager(); + ~CollectorGuestManager(); + void registerGuest(CollectorGuest* pGuest); + void unregisterGuest(CollectorGuest* pGuest); + CollectorGuest *getVMMStatsProvider() { return mVMMStatsProvider; }; + void preCollect(CollectorHints& hints, uint64_t iTick); + void destroyUnregistered(); + HRESULT enqueueRequest(CollectorGuestRequest *aRequest); + + CollectorGuest *getBlockedGuest() { return mGuestBeingCalled; }; + + static DECLCALLBACK(int) requestProcessingThread(RTTHREAD aThread, void *pvUser); + private: + RTTHREAD mThread; + CollectorGuestList mGuests; + CollectorGuest *mVMMStatsProvider; + CollectorGuestQueue mQueue; + CollectorGuest *mGuestBeingCalled; + }; + + /* Collector Hardware Abstraction Layer *********************************/ + typedef std::list<RTCString> DiskList; + + class CollectorHAL + { + public: + CollectorHAL() {}; + virtual ~CollectorHAL() { }; + virtual int preCollect(const CollectorHints& /* hints */, uint64_t /* iTick */) { return VINF_SUCCESS; } + /** Returns averaged CPU usage in 1/1000th per cent across all host's CPUs. */ + virtual int getHostCpuLoad(ULONG *user, ULONG *kernel, ULONG *idle); + /** Returns the average frequency in MHz across all host's CPUs. */ + virtual int getHostCpuMHz(ULONG *mhz); + /** Returns the amount of physical memory in kilobytes. */ + virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available); + /** Returns file system counters in megabytes. */ + virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available); + /** Returns disk size in bytes. */ + virtual int getHostDiskSize(const char *name, uint64_t *size); + /** Returns CPU usage in 1/1000th per cent by a particular process. */ + virtual int getProcessCpuLoad(RTPROCESS process, ULONG *user, ULONG *kernel); + /** Returns the amount of memory used by a process in kilobytes. */ + virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used); + + /** Returns CPU usage counters in platform-specific units. */ + virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle); + /** Returns received and transmitted bytes. */ + virtual int getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx); + /** Returns disk usage counters in platform-specific units. */ + virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms); + /** Returns process' CPU usage counter in platform-specific units. */ + virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total); + + /** Returns the lists of disks (aggregate and physical) used by the specified file system. */ + virtual int getDiskListByFs(const char *name, DiskList& listUsage, DiskList& listLoad); + }; + + extern CollectorHAL *createHAL(); + + /* Base Metrics *********************************************************/ + class BaseMetric + { + public: + BaseMetric(CollectorHAL *hal, const com::Utf8Str name, ComPtr<IUnknown> object) + : mPeriod(0), mLength(0), mHAL(hal), mName(name), mObject(object), + mLastSampleTaken(0), mEnabled(false), mUnregistered(false) {}; + virtual ~BaseMetric() {}; + + virtual void init(ULONG period, ULONG length) = 0; + virtual void preCollect(CollectorHints& hints, uint64_t iTick) = 0; + virtual void collect() = 0; + virtual const char *getUnit() = 0; + virtual ULONG getMinValue() = 0; + virtual ULONG getMaxValue() = 0; + virtual ULONG getScale() = 0; + + bool collectorBeat(uint64_t nowAt); + + virtual HRESULT enable() { mEnabled = true; return S_OK; }; + virtual HRESULT disable() { mEnabled = false; return S_OK; }; + void unregister() { mUnregistered = true; }; + + bool isUnregistered() { return mUnregistered; }; + bool isEnabled() { return mEnabled; }; + ULONG getPeriod() { return mPeriod; }; + ULONG getLength() { return mLength; }; + const char *getName() { return mName.c_str(); }; + ComPtr<IUnknown> getObject() { return mObject; }; + bool associatedWith(ComPtr<IUnknown> object) { return mObject == object; }; + + protected: + ULONG mPeriod; + ULONG mLength; + CollectorHAL *mHAL; + const com::Utf8Str mName; + ComPtr<IUnknown> mObject; + uint64_t mLastSampleTaken; + bool mEnabled; + bool mUnregistered; + }; + + class BaseGuestMetric : public BaseMetric + { + public: + BaseGuestMetric(CollectorGuest *cguest, const char *name, ComPtr<IUnknown> object) + : BaseMetric(NULL, name, object), mCGuest(cguest) {}; + protected: + CollectorGuest *mCGuest; + }; + + class HostCpuLoad : public BaseMetric + { + public: + HostCpuLoad(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle) + : BaseMetric(hal, "CPU/Load", object), mUser(user), mKernel(kernel), mIdle(idle) {}; + ~HostCpuLoad() { delete mUser; delete mKernel; delete mIdle; }; + + void init(ULONG period, ULONG length); + + void collect(); + const char *getUnit() { return "%"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; }; + ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; } + + protected: + SubMetric *mUser; + SubMetric *mKernel; + SubMetric *mIdle; + }; + + class HostCpuLoadRaw : public HostCpuLoad + { + public: + HostCpuLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle) + : HostCpuLoad(hal, object, user, kernel, idle), mUserPrev(0), mKernelPrev(0), mIdlePrev(0) {}; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + private: + uint64_t mUserPrev; + uint64_t mKernelPrev; + uint64_t mIdlePrev; + }; + + class HostCpuMhz : public BaseMetric + { + public: + HostCpuMhz(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *mhz) + : BaseMetric(hal, "CPU/MHz", object), mMHz(mhz) {}; + ~HostCpuMhz() { delete mMHz; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& /* hints */, uint64_t /* iTick */) {} + void collect(); + const char *getUnit() { return "MHz"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + private: + SubMetric *mMHz; + }; + + class HostRamUsage : public BaseMetric + { + public: + HostRamUsage(CollectorHAL *hal, ComPtr<IUnknown> object, SubMetric *total, SubMetric *used, SubMetric *available) + : BaseMetric(hal, "RAM/Usage", object), mTotal(total), mUsed(used), mAvailable(available) {}; + ~HostRamUsage() { delete mTotal; delete mUsed; delete mAvailable; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + const char *getUnit() { return "kB"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + private: + SubMetric *mTotal; + SubMetric *mUsed; + SubMetric *mAvailable; + }; + + class HostNetworkSpeed : public BaseMetric + { + public: + HostNetworkSpeed(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str shortname, com::Utf8Str /* ifname */, uint32_t speed, SubMetric *linkspeed) + : BaseMetric(hal, name, object), mShortName(shortname), mSpeed(speed), mLinkSpeed(linkspeed) {}; + ~HostNetworkSpeed() { delete mLinkSpeed; }; + + void init(ULONG period, ULONG length); + + void preCollect(CollectorHints& /* hints */, uint64_t /* iTick */) {}; + void collect() { if (mSpeed) mLinkSpeed->put(mSpeed); }; + const char *getUnit() { return "mbit/s"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + private: + com::Utf8Str mShortName; + uint32_t mSpeed; + SubMetric *mLinkSpeed; + }; + + class HostNetworkLoadRaw : public BaseMetric + { + public: + HostNetworkLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str shortname, com::Utf8Str ifname, uint32_t speed, SubMetric *rx, SubMetric *tx) + : BaseMetric(hal, name, object), mShortName(shortname), mInterfaceName(ifname), mRx(rx), mTx(tx), mRxPrev(0), mTxPrev(0), mRc(VINF_SUCCESS) { mSpeed = (uint64_t)speed * (1000000/8); /* Convert to bytes/sec */ }; + ~HostNetworkLoadRaw() { delete mRx; delete mTx; }; + + void init(ULONG period, ULONG length); + + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + const char *getUnit() { return "%"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return PM_NETWORK_LOAD_MULTIPLIER; }; + ULONG getScale() { return PM_NETWORK_LOAD_MULTIPLIER / 100; } + + private: + com::Utf8Str mShortName; + com::Utf8Str mInterfaceName; + SubMetric *mRx; + SubMetric *mTx; + uint64_t mRxPrev; + uint64_t mTxPrev; + uint64_t mSpeed; + int mRc; + }; + + class HostFilesystemUsage : public BaseMetric + { + public: + HostFilesystemUsage(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str fsname, SubMetric *total, SubMetric *used, SubMetric *available) + : BaseMetric(hal, name, object), mFsName(fsname), mTotal(total), mUsed(used), mAvailable(available) {}; + ~HostFilesystemUsage() { delete mTotal; delete mUsed; delete mAvailable; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + const char *getUnit() { return "MB"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + private: + com::Utf8Str mFsName; + SubMetric *mTotal; + SubMetric *mUsed; + SubMetric *mAvailable; + }; + + class HostDiskUsage : public BaseMetric + { + public: + HostDiskUsage(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str diskname, SubMetric *total) + : BaseMetric(hal, name, object), mDiskName(diskname), mTotal(total) {}; + ~HostDiskUsage() { delete mTotal; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + const char *getUnit() { return "MB"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + private: + com::Utf8Str mDiskName; + SubMetric *mTotal; + }; + + class HostDiskLoadRaw : public BaseMetric + { + public: + HostDiskLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str diskname, SubMetric *util) + : BaseMetric(hal, name, object), mDiskName(diskname), mUtil(util), mDiskPrev(0), mTotalPrev(0) {}; + ~HostDiskLoadRaw() { delete mUtil; }; + + void init(ULONG period, ULONG length); + + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + const char *getUnit() { return "%"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return PM_DISK_LOAD_MULTIPLIER; }; + ULONG getScale() { return PM_DISK_LOAD_MULTIPLIER / 100; } + + private: + com::Utf8Str mDiskName; + SubMetric *mUtil; + uint64_t mDiskPrev; + uint64_t mTotalPrev; + }; + + +#ifndef VBOX_COLLECTOR_TEST_CASE + class HostRamVmm : public BaseMetric + { + public: + HostRamVmm(CollectorGuestManager *gm, ComPtr<IUnknown> object, SubMetric *allocVMM, SubMetric *freeVMM, SubMetric *balloonVMM, SubMetric *sharedVMM) + : BaseMetric(NULL, "RAM/VMM", object), mCollectorGuestManager(gm), + mAllocVMM(allocVMM), mFreeVMM(freeVMM), mBalloonVMM(balloonVMM), mSharedVMM(sharedVMM), + mAllocCurrent(0), mFreeCurrent(0), mBalloonedCurrent(0), mSharedCurrent(0) {}; + ~HostRamVmm() { delete mAllocVMM; delete mFreeVMM; delete mBalloonVMM; delete mSharedVMM; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + HRESULT enable(); + HRESULT disable(); + const char *getUnit() { return "kB"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + + private: + CollectorGuestManager *mCollectorGuestManager; + SubMetric *mAllocVMM; + SubMetric *mFreeVMM; + SubMetric *mBalloonVMM; + SubMetric *mSharedVMM; + ULONG mAllocCurrent; + ULONG mFreeCurrent; + ULONG mBalloonedCurrent; + ULONG mSharedCurrent; + }; +#endif /* VBOX_COLLECTOR_TEST_CASE */ + + class MachineCpuLoad : public BaseMetric + { + public: + MachineCpuLoad(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel) + : BaseMetric(hal, "CPU/Load", object), mProcess(process), mUser(user), mKernel(kernel) {}; + ~MachineCpuLoad() { delete mUser; delete mKernel; }; + + void init(ULONG period, ULONG length); + void collect(); + const char *getUnit() { return "%"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; }; + ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; } + protected: + RTPROCESS mProcess; + SubMetric *mUser; + SubMetric *mKernel; + }; + + class MachineCpuLoadRaw : public MachineCpuLoad + { + public: + MachineCpuLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *user, SubMetric *kernel) + : MachineCpuLoad(hal, object, process, user, kernel), mHostTotalPrev(0), mProcessUserPrev(0), mProcessKernelPrev(0) {}; + + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + private: + uint64_t mHostTotalPrev; + uint64_t mProcessUserPrev; + uint64_t mProcessKernelPrev; + }; + + class MachineRamUsage : public BaseMetric + { + public: + MachineRamUsage(CollectorHAL *hal, ComPtr<IUnknown> object, RTPROCESS process, SubMetric *used) + : BaseMetric(hal, "RAM/Usage", object), mProcess(process), mUsed(used) {}; + ~MachineRamUsage() { delete mUsed; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + const char *getUnit() { return "kB"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + private: + RTPROCESS mProcess; + SubMetric *mUsed; + }; + + +#ifndef VBOX_COLLECTOR_TEST_CASE + typedef std::list<ComObjPtr<Medium> > MediaList; + class MachineDiskUsage : public BaseMetric + { + public: + MachineDiskUsage(CollectorHAL *hal, ComPtr<IUnknown> object, MediaList &disks, SubMetric *used) + : BaseMetric(hal, "Disk/Usage", object), mDisks(disks), mUsed(used) {}; + ~MachineDiskUsage() { delete mUsed; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + const char *getUnit() { return "MB"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + private: + MediaList mDisks; + SubMetric *mUsed; + }; + + /* + * Although MachineNetRate is measured for VM, not for the guest, it is + * derived from BaseGuestMetric since it uses the same mechanism for + * data collection -- values get pushed by Guest class along with other + * guest statistics. + */ + class MachineNetRate : public BaseGuestMetric + { + public: + MachineNetRate(CollectorGuest *cguest, ComPtr<IUnknown> object, SubMetric *rx, SubMetric *tx) + : BaseGuestMetric(cguest, "Net/Rate", object), mRx(rx), mTx(tx) {}; + ~MachineNetRate() { delete mRx; delete mTx; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + HRESULT enable(); + HRESULT disable(); + const char *getUnit() { return "B/s"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + private: + SubMetric *mRx, *mTx; + }; + + class GuestCpuLoad : public BaseGuestMetric + { + public: + GuestCpuLoad(CollectorGuest *cguest, ComPtr<IUnknown> object, SubMetric *user, SubMetric *kernel, SubMetric *idle) + : BaseGuestMetric(cguest, "Guest/CPU/Load", object), mUser(user), mKernel(kernel), mIdle(idle) {}; + ~GuestCpuLoad() { delete mUser; delete mKernel; delete mIdle; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + HRESULT enable(); + HRESULT disable(); + const char *getUnit() { return "%"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return PM_CPU_LOAD_MULTIPLIER; }; + ULONG getScale() { return PM_CPU_LOAD_MULTIPLIER / 100; } + protected: + SubMetric *mUser; + SubMetric *mKernel; + SubMetric *mIdle; + }; + + class GuestRamUsage : public BaseGuestMetric + { + public: + GuestRamUsage(CollectorGuest *cguest, ComPtr<IUnknown> object, SubMetric *total, SubMetric *free, SubMetric *balloon, SubMetric *shared, SubMetric *cache, SubMetric *pagedtotal) + : BaseGuestMetric(cguest, "Guest/RAM/Usage", object), mTotal(total), mFree(free), mBallooned(balloon), mCache(cache), mPagedTotal(pagedtotal), mShared(shared) {}; + ~GuestRamUsage() { delete mTotal; delete mFree; delete mBallooned; delete mShared; delete mCache; delete mPagedTotal; }; + + void init(ULONG period, ULONG length); + void preCollect(CollectorHints& hints, uint64_t iTick); + void collect(); + HRESULT enable(); + HRESULT disable(); + const char *getUnit() { return "kB"; }; + ULONG getMinValue() { return 0; }; + ULONG getMaxValue() { return INT32_MAX; }; + ULONG getScale() { return 1; } + private: + SubMetric *mTotal, *mFree, *mBallooned, *mCache, *mPagedTotal, *mShared; + }; +#endif /* VBOX_COLLECTOR_TEST_CASE */ + + /* Aggregate Functions **************************************************/ + class Aggregate + { + public: + virtual ULONG compute(ULONG *data, ULONG length) = 0; + virtual const char *getName() = 0; + virtual ~Aggregate() {} + }; + + class AggregateAvg : public Aggregate + { + public: + virtual ULONG compute(ULONG *data, ULONG length); + virtual const char *getName(); + }; + + class AggregateMin : public Aggregate + { + public: + virtual ULONG compute(ULONG *data, ULONG length); + virtual const char *getName(); + }; + + class AggregateMax : public Aggregate + { + public: + virtual ULONG compute(ULONG *data, ULONG length); + virtual const char *getName(); + }; + + /* Metric Class *********************************************************/ + class Metric + { + public: + Metric(BaseMetric *baseMetric, SubMetric *subMetric, Aggregate *aggregate) : + mName(subMetric->getName()), mBaseMetric(baseMetric), mSubMetric(subMetric), mAggregate(aggregate) + { + if (mAggregate) + { + mName.append(":"); + mName.append(mAggregate->getName()); + } + } + + ~Metric() + { + delete mAggregate; + } + bool associatedWith(ComPtr<IUnknown> object) { return getObject() == object; }; + + const char *getName() { return mName.c_str(); }; + ComPtr<IUnknown> getObject() { return mBaseMetric->getObject(); }; + const char *getDescription() + { return mAggregate ? "" : mSubMetric->getDescription(); }; + const char *getUnit() { return mBaseMetric->getUnit(); }; + ULONG getMinValue() { return mBaseMetric->getMinValue(); }; + ULONG getMaxValue() { return mBaseMetric->getMaxValue(); }; + ULONG getPeriod() { return mBaseMetric->getPeriod(); }; + ULONG getLength() + { return mAggregate ? 1 : mBaseMetric->getLength(); }; + ULONG getScale() { return mBaseMetric->getScale(); } + void query(ULONG **data, ULONG *count, ULONG *sequenceNumber); + + private: + RTCString mName; + BaseMetric *mBaseMetric; + SubMetric *mSubMetric; + Aggregate *mAggregate; + }; + + /* Filter Class *********************************************************/ + + class Filter + { + public: + Filter(const std::vector<com::Utf8Str> &metricNames, + const std::vector<ComPtr<IUnknown> > &objects); + Filter(const com::Utf8Str &name, const ComPtr<IUnknown> &aObject); + static bool patternMatch(const char *pszPat, const char *pszName, + bool fSeenColon = false); + bool match(const ComPtr<IUnknown> object, const RTCString &name) const; + private: + typedef std::pair<const ComPtr<IUnknown>, const RTCString> FilterElement; + typedef std::list<FilterElement> ElementList; + + ElementList mElements; + + void processMetricList(const com::Utf8Str &name, const ComPtr<IUnknown> object); + }; +} +#endif /* !MAIN_INCLUDED_Performance_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/PerformanceImpl.h b/src/VBox/Main/include/PerformanceImpl.h new file mode 100644 index 00000000..3b8154cc --- /dev/null +++ b/src/VBox/Main/include/PerformanceImpl.h @@ -0,0 +1,206 @@ +/* $Id: PerformanceImpl.h $ */ + +/** @file + * + * VBox Performance COM class implementation. + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_PerformanceImpl_h +#define MAIN_INCLUDED_PerformanceImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "PerformanceCollectorWrap.h" +#include "PerformanceMetricWrap.h" + +#include <VBox/com/com.h> +#include <VBox/com/array.h> +//#ifdef VBOX_WITH_RESOURCE_USAGE_API +#include <iprt/timer.h> +//#endif /* VBOX_WITH_RESOURCE_USAGE_API */ + +#include <list> + +namespace pm +{ + class Metric; + class BaseMetric; + class CollectorHAL; + class CollectorGuest; + class CollectorGuestManager; +} + +#undef min +#undef max + +/* Each second we obtain new CPU load stats. */ +#define VBOX_USAGE_SAMPLER_MIN_INTERVAL 1000 + +class ATL_NO_VTABLE PerformanceMetric : + public PerformanceMetricWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(PerformanceMetric) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(pm::Metric *aMetric); + HRESULT init(pm::BaseMetric *aMetric); + void uninit(); + +private: + + // wrapped IPerformanceMetric properties + HRESULT getMetricName(com::Utf8Str &aMetricName); + HRESULT getObject(ComPtr<IUnknown> &aObject); + HRESULT getDescription(com::Utf8Str &aDescription); + HRESULT getPeriod(ULONG *aPeriod); + HRESULT getCount(ULONG *aCount); + HRESULT getUnit(com::Utf8Str &aUnit); + HRESULT getMinimumValue(LONG *aMinimumValue); + HRESULT getMaximumValue(LONG *aMaximumValue); + + struct Data + { + /* Constructor. */ + Data() + : period(0), count(0), min(0), max(0) + { + } + + Utf8Str name; + ComPtr<IUnknown> object; + Utf8Str description; + ULONG period; + ULONG count; + Utf8Str unit; + LONG min; + LONG max; + }; + + Data m; +}; + + +class ATL_NO_VTABLE PerformanceCollector : + public PerformanceCollectorWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(PerformanceCollector) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializers/uninitializers only for internal purposes + HRESULT init(); + void uninit(); + + // public methods only for internal purposes + + void registerBaseMetric(pm::BaseMetric *baseMetric); + void registerMetric(pm::Metric *metric); + void unregisterBaseMetricsFor(const ComPtr<IUnknown> &object, const Utf8Str name = "*"); + void unregisterMetricsFor(const ComPtr<IUnknown> &object, const Utf8Str name = "*"); + void registerGuest(pm::CollectorGuest* pGuest); + void unregisterGuest(pm::CollectorGuest* pGuest); + + void suspendSampling(); + void resumeSampling(); + + // public methods for internal purposes only + // (ensure there is a caller and a read lock before calling them!) + + pm::CollectorHAL *getHAL() { return m.hal; }; + pm::CollectorGuestManager *getGuestManager() { return m.gm; }; + +private: + + // wrapped IPerformanceCollector properties + HRESULT getMetricNames(std::vector<com::Utf8Str> &aMetricNames); + + // wrapped IPerformanceCollector methods + HRESULT getMetrics(const std::vector<com::Utf8Str> &aMetricNames, + const std::vector<ComPtr<IUnknown> > &aObjects, + std::vector<ComPtr<IPerformanceMetric> > &aMetrics); + HRESULT setupMetrics(const std::vector<com::Utf8Str> &aMetricNames, + const std::vector<ComPtr<IUnknown> > &aObjects, + ULONG aPeriod, + ULONG aCount, + std::vector<ComPtr<IPerformanceMetric> > &aAffectedMetrics); + HRESULT enableMetrics(const std::vector<com::Utf8Str> &aMetricNames, + const std::vector<ComPtr<IUnknown> > &aObjects, + std::vector<ComPtr<IPerformanceMetric> > &aAffectedMetrics); + HRESULT disableMetrics(const std::vector<com::Utf8Str> &aMetricNames, + const std::vector<ComPtr<IUnknown> > &aObjects, + std::vector<ComPtr<IPerformanceMetric> > &aAffectedMetrics); + HRESULT queryMetricsData(const std::vector<com::Utf8Str> &aMetricNames, + const std::vector<ComPtr<IUnknown> > &aObjects, + std::vector<com::Utf8Str> &aReturnMetricNames, + std::vector<ComPtr<IUnknown> > &aReturnObjects, + std::vector<com::Utf8Str> &aReturnUnits, + std::vector<ULONG> &aReturnScales, + std::vector<ULONG> &aReturnSequenceNumbers, + std::vector<ULONG> &aReturnDataIndices, + std::vector<ULONG> &aReturnDataLengths, + std::vector<LONG> &aReturnData); + + + HRESULT toIPerformanceMetric(pm::Metric *src, ComPtr<IPerformanceMetric> &dst); + HRESULT toIPerformanceMetric(pm::BaseMetric *src, ComPtr<IPerformanceMetric> &dst); + + static DECLCALLBACK(void) staticSamplerCallback(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick); + void samplerCallback(uint64_t iTick); + + const Utf8Str& getFailedGuestName(); + + typedef std::list<pm::Metric*> MetricList; + typedef std::list<pm::BaseMetric*> BaseMetricList; + +/** PerformanceMetric::mMagic value. */ +#define PERFORMANCE_METRIC_MAGIC UINT32_C(0xABBA1972) + uint32_t mMagic; + const Utf8Str mUnknownGuest; + + struct Data + { + Data() : hal(0) {}; + + BaseMetricList baseMetrics; + MetricList metrics; + RTTIMERLR sampler; + pm::CollectorHAL *hal; + pm::CollectorGuestManager *gm; + }; + + Data m; +}; + +#endif /* !MAIN_INCLUDED_PerformanceImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/ProgressImpl.h b/src/VBox/Main/include/ProgressImpl.h new file mode 100644 index 00000000..473f6c8a --- /dev/null +++ b/src/VBox/Main/include/ProgressImpl.h @@ -0,0 +1,259 @@ +/* $Id: ProgressImpl.h $ */ +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ProgressImpl_h +#define MAIN_INCLUDED_ProgressImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "ProgressWrap.h" +#include "VirtualBoxBase.h" +#include "EventImpl.h" + +#include <iprt/semaphore.h> + +//////////////////////////////////////////////////////////////////////////////// + +/** + * Class for progress objects. + */ +class ATL_NO_VTABLE Progress : + public ProgressWrap +{ +public: + DECLARE_NOT_AGGREGATABLE(Progress) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + + /** + * Simplified constructor for progress objects that have only one + * operation as a task. + * @param aParent + * @param aInitiator + * @param aDescription + * @param aCancelable + * @return + */ + HRESULT init( +#if !defined(VBOX_COM_INPROC) + VirtualBox *aParent, +#endif + IUnknown *aInitiator, + const Utf8Str &aDescription, + BOOL aCancelable) + { + return init( +#if !defined(VBOX_COM_INPROC) + aParent, +#endif + aInitiator, + aDescription, + aCancelable, + 1, // cOperations + 1, // ulTotalOperationsWeight + aDescription, // aFirstOperationDescription + 1); // ulFirstOperationWeight + } + + /** + * Not quite so simplified constructor for progress objects that have + * more than one operation, but all sub-operations are weighed the same. + * @param aParent + * @param aInitiator + * @param aDescription + * @param aCancelable + * @param cOperations + * @param aFirstOperationDescription + * @return + */ + HRESULT init( +#if !defined(VBOX_COM_INPROC) + VirtualBox *aParent, +#endif + IUnknown *aInitiator, + const Utf8Str &aDescription, BOOL aCancelable, + ULONG cOperations, + const Utf8Str &aFirstOperationDescription) + { + return init( +#if !defined(VBOX_COM_INPROC) + aParent, +#endif + aInitiator, + aDescription, + aCancelable, + cOperations, // cOperations + cOperations, // ulTotalOperationsWeight = cOperations + aFirstOperationDescription, // aFirstOperationDescription + 1); // ulFirstOperationWeight: weigh them all the same + } + + HRESULT init( +#if !defined(VBOX_COM_INPROC) + VirtualBox *aParent, +#endif + IUnknown *aInitiator, + const Utf8Str &aDescription, + BOOL aCancelable, + ULONG cOperations, + ULONG ulTotalOperationsWeight, + const Utf8Str &aFirstOperationDescription, + ULONG ulFirstOperationWeight); + + HRESULT init(BOOL aCancelable, + ULONG aOperationCount, + const Utf8Str &aOperationDescription); + + void uninit(); + + + // public methods only for internal purposes + HRESULT i_notifyComplete(HRESULT aResultCode); + HRESULT i_notifyComplete(HRESULT aResultCode, + const GUID &aIID, + const char *pcszComponent, + const char *aText, + ...); + HRESULT i_notifyCompleteV(HRESULT aResultCode, + const GUID &aIID, + const char *pcszComponent, + const char *aText, + va_list va); + HRESULT i_notifyCompleteBoth(HRESULT aResultCode, + int vrc, + const GUID &aIID, + const char *pcszComponent, + const char *aText, + ...); + HRESULT i_notifyCompleteBothV(HRESULT aResultCode, + int vrc, + const GUID &aIID, + const char *pcszComponent, + const char *aText, + va_list va); + + bool i_setCancelCallback(void (*pfnCallback)(void *), void *pvUser); + + static DECLCALLBACK(int) i_iprtProgressCallback(unsigned uPercentage, void *pvUser); + static DECLCALLBACK(int) i_vdProgressCallback(void *pvUser, unsigned uPercentage); + +protected: + DECLARE_COMMON_CLASS_METHODS(Progress) + +#if !defined(VBOX_COM_INPROC) + /** Weak parent. */ + VirtualBox * const mParent; +#endif + const ComObjPtr<EventSource> pEventSource; + const ComPtr<IUnknown> mInitiator; + + const Guid mId; + const com::Utf8Str mDescription; + + uint64_t m_ullTimestamp; // progress object creation timestamp, for ETA computation + + void (*m_pfnCancelCallback)(void *); + void *m_pvCancelUserArg; + + /* The fields below are to be properly initialized by subclasses */ + + BOOL mCompleted; + BOOL mCancelable; + BOOL mCanceled; + HRESULT mResultCode; + ComPtr<IVirtualBoxErrorInfo> mErrorInfo; + + ULONG m_cOperations; // number of operations (so that progress dialog can + // display something like 1/3) + ULONG m_ulTotalOperationsWeight; // sum of weights of all operations, given to constructor + + ULONG m_ulOperationsCompletedWeight; // summed-up weight of operations that have been completed; initially 0 + + ULONG m_ulCurrentOperation; // operations counter, incremented with + // each setNextOperation() + com::Utf8Str m_operationDescription; // name of current operation; initially + // from constructor, changed with setNextOperation() + ULONG m_ulCurrentOperationWeight; // weight of current operation, given to setNextOperation() + ULONG m_ulOperationPercent; // percentage of current operation, set with setCurrentOperationProgress() + ULONG m_cMsTimeout; /**< Automatic timeout value. 0 means none. */ + +private: + // wrapped IProgress properties + HRESULT getId(com::Guid &aId); + HRESULT getDescription(com::Utf8Str &aDescription); + HRESULT getInitiator(ComPtr<IUnknown> &aInitiator); + HRESULT getCancelable(BOOL *aCancelable); + HRESULT getPercent(ULONG *aPercent); + HRESULT getTimeRemaining(LONG *aTimeRemaining); + HRESULT getCompleted(BOOL *aCompleted); + HRESULT getCanceled(BOOL *aCanceled); + HRESULT getResultCode(LONG *aResultCode); + HRESULT getErrorInfo(ComPtr<IVirtualBoxErrorInfo> &aErrorInfo); + HRESULT getOperationCount(ULONG *aOperationCount); + HRESULT getOperation(ULONG *aOperation); + HRESULT getOperationDescription(com::Utf8Str &aOperationDescription); + HRESULT getOperationPercent(ULONG *aOperationPercent); + HRESULT getOperationWeight(ULONG *aOperationWeight); + HRESULT getTimeout(ULONG *aTimeout); + HRESULT setTimeout(ULONG aTimeout); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + + // wrapped IProgress methods + HRESULT waitForCompletion(LONG aTimeout); + HRESULT waitForOperationCompletion(ULONG aOperation, + LONG aTimeout); + HRESULT cancel(); + + // wrapped IInternalProgressControl methods + HRESULT setCurrentOperationProgress(ULONG aPercent); + HRESULT waitForOtherProgressCompletion(const ComPtr<IProgress> &aProgressOther, + ULONG aTimeoutMS); + HRESULT setNextOperation(const com::Utf8Str &aNextOperationDescription, + ULONG aNextOperationsWeight); + HRESULT notifyPointOfNoReturn(); + HRESULT notifyComplete(LONG aResultCode, + const ComPtr<IVirtualBoxErrorInfo> &aErrorInfo); + + // internal helper methods + HRESULT i_notifyCompleteWorker(HRESULT aResultCode, const ComPtr<IVirtualBoxErrorInfo> &aErrorInfo); + double i_calcTotalPercent(); + void i_checkForAutomaticTimeout(void); + + RTSEMEVENTMULTI mCompletedSem; + ULONG mWaitersCount; + +private: + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(Progress); /* Shuts up MSC warning C4625. */ +}; + +#endif /* !MAIN_INCLUDED_ProgressImpl_h */ + diff --git a/src/VBox/Main/include/ProgressProxyImpl.h b/src/VBox/Main/include/ProgressProxyImpl.h new file mode 100644 index 00000000..2e57409c --- /dev/null +++ b/src/VBox/Main/include/ProgressProxyImpl.h @@ -0,0 +1,130 @@ +/* $Id: ProgressProxyImpl.h $ */ +/** @file + * IProgress implementation for Machine::LaunchVMProcess in VBoxSVC. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ProgressProxyImpl_h +#define MAIN_INCLUDED_ProgressProxyImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#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 Progress +{ +public: + VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(ProgressProxy, IProgress) + + 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) + VBOX_TWEAK_INTERFACE_ENTRY(IProgress) + END_COM_MAP() + + HRESULT FinalConstruct(); + void FinalRelease(); + HRESULT init( +#ifndef VBOX_COM_INPROC + VirtualBox *pParent, +#endif + IUnknown *pInitiator, + Utf8Str strDescription, + BOOL fCancelable); + HRESULT init( +#ifndef VBOX_COM_INPROC + VirtualBox *pParent, +#endif + IUnknown *pInitiator, + Utf8Str strDescription, + BOOL fCancelable, + ULONG uTotalOperationsWeight, + Utf8Str strFirstOperationDescription, + 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 char *pcszComponent, + const char *aText, ...); + bool setOtherProgressObject(IProgress *pOtherProgress); + +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 /* !MAIN_INCLUDED_ProgressProxyImpl_h */ + diff --git a/src/VBox/Main/include/QMTranslator.h b/src/VBox/Main/include/QMTranslator.h new file mode 100644 index 00000000..82b9439f --- /dev/null +++ b/src/VBox/Main/include/QMTranslator.h @@ -0,0 +1,79 @@ +/* $Id: QMTranslator.h $ */ +/** @file + * VirtualBox API translation handling class + */ + +/* + * Copyright (C) 2014-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_QMTranslator_h +#define MAIN_INCLUDED_QMTranslator_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +class QMTranslator_Impl; + +class QMTranslator +{ +public: + QMTranslator(); + virtual ~QMTranslator(); + + /** + * Gets translation from loaded QM file + * + * @param pszContext QM context to look for translation + * @param pszSource Source string in one-byte encoding + * @param ppszSafeSource Where to return pointer to a safe copy of @a + * pszSource for the purpose of reverse translation. + * Will be set to NULL if @a pszSource is returned. + * @param pszDisamb Disambiguationg comment, empty by default + * @param aNum Plural form indicator. + * + * @returns Pointer to a translation (UTF-8 encoding), source string on failure. + */ + const char *translate(const char *pszContext, const char *pszSource, const char **ppszSafeSource, + const char *pszDisamb = NULL, const size_t aNum = ~(size_t)0) const RT_NOEXCEPT; + + /** + * Loads and parses QM file + * + * @param pszFilename The name of the file to load + * @param hStrCache The string cache to use for storing strings. + * + * @returns VBox status code. + */ + int load(const char *pszFilename, RTSTRCACHE hStrCache) RT_NOEXCEPT; + +private: + /** QMTranslator implementation. + * To separate all the code from the interface */ + QMTranslator_Impl *m_impl; + + /* If copying is required, please define the following operators */ + void operator=(QMTranslator &); + QMTranslator(const QMTranslator &); +}; + +#endif /* !MAIN_INCLUDED_QMTranslator_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/Recording.h b/src/VBox/Main/include/Recording.h new file mode 100644 index 00000000..0c4c9361 --- /dev/null +++ b/src/VBox/Main/include/Recording.h @@ -0,0 +1,174 @@ +/* $Id: Recording.h $ */ +/** @file + * Recording code header. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_Recording_h +#define MAIN_INCLUDED_Recording_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/err.h> +#include <VBox/settings.h> + +#include "RecordingStream.h" + +class Console; + +/** + * Class for managing a recording context. + */ +class RecordingContext +{ +public: + + RecordingContext(); + + RecordingContext(Console *ptrConsole, const settings::RecordingSettings &Settings); + + virtual ~RecordingContext(void); + +public: + + const settings::RecordingSettings &GetConfig(void) const; + RecordingStream *GetStream(unsigned uScreen) const; + size_t GetStreamCount(void) const; +#ifdef VBOX_WITH_AUDIO_RECORDING + PRECORDINGCODEC GetCodecAudio(void) { return &this->m_CodecAudio; } +#endif + + int Create(Console *pConsole, const settings::RecordingSettings &Settings); + void Destroy(void); + + int Start(void); + int Stop(void); + + int SendAudioFrame(const void *pvData, size_t cbData, uint64_t uTimestampMs); + int SendVideoFrame(uint32_t uScreen, + uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP, + uint32_t uBytesPerLine, uint32_t uSrcWidth, uint32_t uSrcHeight, + uint8_t *puSrcData, uint64_t msTimestamp); +public: + + bool IsFeatureEnabled(RecordingFeature_T enmFeature); + bool IsReady(void); + bool IsReady(uint32_t uScreen, uint64_t msTimestamp); + bool IsStarted(void); + bool IsLimitReached(void); + bool IsLimitReached(uint32_t uScreen, uint64_t msTimestamp); + bool NeedsUpdate( uint32_t uScreen, uint64_t msTimestamp); + + DECLCALLBACK(int) OnLimitReached(uint32_t uScreen, int rc); + +protected: + + int createInternal(Console *ptrConsole, const settings::RecordingSettings &Settings); + int startInternal(void); + int stopInternal(void); + + void destroyInternal(void); + + RecordingStream *getStreamInternal(unsigned uScreen) const; + + int processCommonData(RecordingBlockMap &mapCommon, RTMSINTERVAL msTimeout); + int writeCommonData(RecordingBlockMap &mapCommon, PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, uint64_t msAbsPTS, uint32_t uFlags); + + int lock(void); + int unlock(void); + + static DECLCALLBACK(int) threadMain(RTTHREAD hThreadSelf, void *pvUser); + + int threadNotify(void); + +protected: + + int audioInit(const settings::RecordingScreenSettings &screenSettings); + + static DECLCALLBACK(int) audioCodecWriteDataCallback(PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, uint64_t msAbsPTS, uint32_t uFlags, void *pvUser); + +protected: + + /** + * Enumeration for a recording context state. + */ + enum RECORDINGSTS + { + /** Context not initialized. */ + RECORDINGSTS_UNINITIALIZED = 0, + /** Context was created. */ + RECORDINGSTS_CREATED = 1, + /** Context was started. */ + RECORDINGSTS_STARTED = 2, + /** The usual 32-bit hack. */ + RECORDINGSTS_32BIT_HACK = 0x7fffffff + }; + + /** Pointer to the console object. */ + Console *m_pConsole; + /** Used recording configuration. */ + settings::RecordingSettings m_Settings; + /** The current state. */ + RECORDINGSTS m_enmState; + /** Critical section to serialize access. */ + RTCRITSECT m_CritSect; + /** Semaphore to signal the encoding worker thread. */ + RTSEMEVENT m_WaitEvent; + /** Shutdown indicator. */ + bool m_fShutdown; + /** Encoding worker thread. */ + RTTHREAD m_Thread; + /** Vector of current recording streams. + * Per VM screen (display) one recording stream is being used. */ + RecordingStreams m_vecStreams; + /** Number of streams in vecStreams which currently are enabled for recording. */ + uint16_t m_cStreamsEnabled; + /** Timestamp (in ms) of when recording has been started. */ + uint64_t m_tsStartMs; +#ifdef VBOX_WITH_AUDIO_RECORDING + /** Audio codec to use. + * + * We multiplex audio data from this recording context to all streams, + * to avoid encoding the same audio data for each stream. We ASSUME that + * all audio data of a VM will be the same for each stream at a given + * point in time. */ + RECORDINGCODEC m_CodecAudio; +#endif /* VBOX_WITH_AUDIO_RECORDING */ + /** Block map of raw common data blocks which need to get encoded first. */ + RecordingBlockMap m_mapBlocksRaw; + /** Block map of encoded common blocks. + * + * Only do the encoding of common data blocks only once and then multiplex + * the encoded data to all affected recording streams. + * + * This avoids doing the (expensive) encoding + multiplexing work in other + * threads like EMT / audio async I/O.. + * + * For now this only affects audio, e.g. all recording streams + * need to have the same audio data at a specific point in time. */ + RecordingBlockMap m_mapBlocksEncoded; +}; +#endif /* !MAIN_INCLUDED_Recording_h */ + diff --git a/src/VBox/Main/include/RecordingInternals.h b/src/VBox/Main/include/RecordingInternals.h new file mode 100644 index 00000000..49e91235 --- /dev/null +++ b/src/VBox/Main/include/RecordingInternals.h @@ -0,0 +1,504 @@ +/* $Id: RecordingInternals.h $ */ +/** @file + * Recording internals header. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_RecordingInternals_h +#define MAIN_INCLUDED_RecordingInternals_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <list> + +#include <iprt/assert.h> +#include <iprt/types.h> /* drag in stdint.h before vpx does it. */ + +#include "VBox/com/string.h" +#include "VBox/com/VirtualBox.h" +#include "VBox/settings.h" +#include <VBox/vmm/pdmaudioifs.h> + +#ifdef VBOX_WITH_LIBVPX +# define VPX_CODEC_DISABLE_COMPAT 1 +# include "vpx/vp8cx.h" +# include "vpx/vpx_image.h" +# include "vpx/vpx_encoder.h" +#endif /* VBOX_WITH_LIBVPX */ + +#ifdef VBOX_WITH_LIBVORBIS +# include "vorbis/vorbisenc.h" +#endif + + +/********************************************************************************************************************************* +* Defines * +*********************************************************************************************************************************/ +#define VBOX_RECORDING_VORBIS_HZ_MAX 48000 /**< Maximum sample rate (in Hz) Vorbis can handle. */ +#define VBOX_RECORDING_VORBIS_FRAME_MS_DEFAULT 20 /**< Default Vorbis frame size (in ms). */ + + +/********************************************************************************************************************************* +* Prototypes * +*********************************************************************************************************************************/ +struct RECORDINGCODEC; +typedef RECORDINGCODEC *PRECORDINGCODEC; + +struct RECORDINGFRAME; +typedef RECORDINGFRAME *PRECORDINGFRAME; + + +/********************************************************************************************************************************* +* Internal structures, defines and APIs * +*********************************************************************************************************************************/ + +/** + * Enumeration for specifying a (generic) codec type. + */ +typedef enum RECORDINGCODECTYPE +{ + /** Invalid codec type. Do not use. */ + RECORDINGCODECTYPE_INVALID = 0, + /** Video codec. */ + RECORDINGCODECTYPE_VIDEO, + /** Audio codec. */ + RECORDINGCODECTYPE_AUDIO +} RECORDINGCODECTYPE; + +/** + * Structure for keeping a codec operations table. + */ +typedef struct RECORDINGCODECOPS +{ + /** + * Initializes a codec. + * + * @returns VBox status code. + * @param pCodec Codec instance to initialize. + */ + DECLCALLBACKMEMBER(int, pfnInit, (PRECORDINGCODEC pCodec)); + + /** + * Destroys a codec. + * + * @returns VBox status code. + * @param pCodec Codec instance to destroy. + */ + DECLCALLBACKMEMBER(int, pfnDestroy, (PRECORDINGCODEC pCodec)); + + /** + * Parses an options string to configure advanced / hidden / experimental features of a recording stream. + * Unknown values will be skipped. Optional. + * + * @returns VBox status code. + * @param pCodec Codec instance to parse options for. + * @param strOptions Options string to parse. + */ + DECLCALLBACKMEMBER(int, pfnParseOptions, (PRECORDINGCODEC pCodec, const com::Utf8Str &strOptions)); + + /** + * Feeds the codec encoder with data to encode. + * + * @returns VBox status code. + * @param pCodec Codec instance to use. + * @param pFrame Pointer to frame data to encode. + * @param pcEncoded Where to return the number of encoded blocks in \a pvDst on success. Optional. + * @param pcbEncoded Where to return the number of encoded bytes in \a pvDst on success. Optional. + */ + DECLCALLBACKMEMBER(int, pfnEncode, (PRECORDINGCODEC pCodec, const PRECORDINGFRAME pFrame, size_t *pcEncoded, size_t *pcbEncoded)); + + /** + * Tells the codec to finalize the current stream. Optional. + * + * @returns VBox status code. + * @param pCodec Codec instance to finalize stream for. + */ + DECLCALLBACKMEMBER(int, pfnFinalize, (PRECORDINGCODEC pCodec)); +} RECORDINGCODECOPS, *PRECORDINGCODECOPS; + +/** No encoding flags set. */ +#define RECORDINGCODEC_ENC_F_NONE UINT32_C(0) +/** Data block is a key block. */ +#define RECORDINGCODEC_ENC_F_BLOCK_IS_KEY RT_BIT_32(0) +/** Data block is invisible. */ +#define RECORDINGCODEC_ENC_F_BLOCK_IS_INVISIBLE RT_BIT_32(1) +/** Encoding flags valid mask. */ +#define RECORDINGCODEC_ENC_F_VALID_MASK 0x1 + +/** + * Structure for keeping a codec callback table. + */ +typedef struct RECORDINGCODECCALLBACKS +{ + /** + * Callback for notifying that encoded data has been written. + * + * @returns VBox status code. + * @param pCodec Pointer to codec instance which has written the data. + * @param pvData Pointer to written data (encoded). + * @param cbData Size (in bytes) of \a pvData. + * @param msAbsPTS Absolute PTS (in ms) of the written data. + * @param uFlags Encoding flags of type RECORDINGCODEC_ENC_F_XXX. + * @param pvUser User-supplied pointer. + */ + DECLCALLBACKMEMBER(int, pfnWriteData, (PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, uint64_t msAbsPTS, uint32_t uFlags, void *pvUser)); + /** User-supplied data pointer. */ + void *pvUser; +} RECORDINGCODECCALLBACKS, *PRECORDINGCODECCALLBACKS; + +/** + * Structure for keeping generic codec parameters. + */ +typedef struct RECORDINGCODECPARMS +{ + /** The generic codec type. */ + RECORDINGCODECTYPE enmType; + /** The specific codec type, based on \a enmType. */ + union + { + /** The container's video codec to use. */ + RecordingVideoCodec_T enmVideoCodec; + /** The container's audio codec to use. */ + RecordingAudioCodec_T enmAudioCodec; + }; + union + { + struct + { + /** Frames per second. */ + uint8_t uFPS; + /** Target width (in pixels) of encoded video image. */ + uint16_t uWidth; + /** Target height (in pixels) of encoded video image. */ + uint16_t uHeight; + /** Minimal delay (in ms) between two video frames. + * This value is based on the configured FPS rate. */ + uint32_t uDelayMs; + } Video; + struct + { + /** The codec's used PCM properties. */ + PDMAUDIOPCMPROPS PCMProps; + } Audio; + }; + /** Desired (average) bitrate (in kbps) to use, for codecs which support bitrate management. + * Set to 0 to use a variable bit rate (VBR) (if available, otherwise fall back to CBR). */ + uint32_t uBitrate; + /** Time (in ms) the encoder expects us to send data to encode. + * + * For Vorbis, valid frame sizes are powers of two from 64 to 8192 bytes. + */ + uint32_t msFrame; + /** The frame size in bytes (based on \a msFrame). */ + uint32_t cbFrame; + /** The frame size in samples per frame (based on \a msFrame). */ + uint32_t csFrame; +} RECORDINGCODECPARMS, *PRECORDINGCODECPARMS; + +#ifdef VBOX_WITH_LIBVPX +/** + * VPX encoder state (needs libvpx). + */ +typedef struct RECORDINGCODECVPX +{ + /** VPX codec context. */ + vpx_codec_ctx_t Ctx; + /** VPX codec configuration. */ + vpx_codec_enc_cfg_t Cfg; + /** VPX image context. */ + vpx_image_t RawImage; + /** Pointer to the codec's internal YUV buffer. */ + uint8_t *pu8YuvBuf; + /** The encoder's deadline (in ms). + * The more time the encoder is allowed to spend encoding, the better the encoded + * result, in exchange for higher CPU usage and time spent encoding. */ + unsigned int uEncoderDeadline; +} RECORDINGCODECVPX; +/** Pointer to a VPX encoder state. */ +typedef RECORDINGCODECVPX *PRECORDINGCODECVPX; +#endif /* VBOX_WITH_LIBVPX */ + +#ifdef VBOX_WITH_LIBVORBIS +/** + * Vorbis encoder state (needs libvorbis + libogg). + */ +typedef struct RECORDINGCODECVORBIS +{ + /** Basic information about the audio in a Vorbis bitstream. */ + vorbis_info info; + /** Encoder state. */ + vorbis_dsp_state dsp_state; + /** Current block being worked on. */ + vorbis_block block_cur; +} RECORDINGCODECVORBIS; +/** Pointer to a Vorbis encoder state. */ +typedef RECORDINGCODECVORBIS *PRECORDINGCODECVORBIS; +#endif /* VBOX_WITH_LIBVORBIS */ + +/** + * Structure for keeping a codec's internal state. + */ +typedef struct RECORDINGCODECSTATE +{ + /** Timestamp Timestamp (PTS, in ms) of the last frame was encoded. */ + uint64_t tsLastWrittenMs; + /** Number of encoding errors. */ + uint64_t cEncErrors; +} RECORDINGCODECSTATE; +/** Pointer to an internal encoder state. */ +typedef RECORDINGCODECSTATE *PRECORDINGCODECSTATE; + +/** + * Structure for keeping codec-specific data. + */ +typedef struct RECORDINGCODEC +{ + /** Callback table for codec operations. */ + RECORDINGCODECOPS Ops; + /** Table for user-supplied callbacks. */ + RECORDINGCODECCALLBACKS Callbacks; + /** Generic codec parameters. */ + RECORDINGCODECPARMS Parms; + /** Generic codec parameters. */ + RECORDINGCODECSTATE State; + +#ifdef VBOX_WITH_LIBVPX + union + { + RECORDINGCODECVPX VPX; + } Video; +#endif + +#ifdef VBOX_WITH_AUDIO_RECORDING + union + { +# ifdef VBOX_WITH_LIBVORBIS + RECORDINGCODECVORBIS Vorbis; +# endif /* VBOX_WITH_LIBVORBIS */ + } Audio; +#endif /* VBOX_WITH_AUDIO_RECORDING */ + + /** Internal scratch buffer for en-/decoding steps. */ + void *pvScratch; + /** Size (in bytes) of \a pvScratch. */ + uint32_t cbScratch; + +#ifdef VBOX_WITH_STATISTICS /** @todo Register these values with STAM. */ + struct + { + /** Number of frames encoded. */ + uint64_t cEncBlocks; + /** Total time (in ms) of already encoded audio data. */ + uint64_t msEncTotal; + } STAM; +#endif +} RECORDINGCODEC, *PRECORDINGCODEC; + +/** + * Enumeration for supported pixel formats. + */ +enum RECORDINGPIXELFMT +{ + /** Unknown pixel format. */ + RECORDINGPIXELFMT_UNKNOWN = 0, + /** RGB 24. */ + RECORDINGPIXELFMT_RGB24 = 1, + /** RGB 24. */ + RECORDINGPIXELFMT_RGB32 = 2, + /** RGB 565. */ + RECORDINGPIXELFMT_RGB565 = 3, + /** The usual 32-bit hack. */ + RECORDINGPIXELFMT_32BIT_HACK = 0x7fffffff +}; + +/** + * Enumeration for a recording frame type. + */ +enum RECORDINGFRAME_TYPE +{ + /** Invalid frame type; do not use. */ + RECORDINGFRAME_TYPE_INVALID = 0, + /** Frame is an audio frame. */ + RECORDINGFRAME_TYPE_AUDIO = 1, + /** Frame is an video frame. */ + RECORDINGFRAME_TYPE_VIDEO = 2, + /** Frame contains a video frame pointer. */ + RECORDINGFRAME_TYPE_VIDEO_PTR = 3 +}; + +/** + * Structure for keeping a single recording video frame. + */ +typedef struct RECORDINGVIDEOFRAME +{ + /** X origin (in pixel) of this frame. */ + uint16_t uX; + /** X origin (in pixel) of this frame. */ + uint16_t uY; + /** X resolution (in pixel) of this frame. */ + uint16_t uWidth; + /** Y resolution (in pixel) of this frame. */ + uint16_t uHeight; + /** Bits per pixel (BPP). */ + uint8_t uBPP; + /** Pixel format of this frame. */ + RECORDINGPIXELFMT enmPixelFmt; + /** Bytes per scan line. */ + uint16_t uBytesPerLine; + /** RGB buffer containing the unmodified frame buffer data from Main's display. */ + uint8_t *pu8RGBBuf; + /** Size (in bytes) of the RGB buffer. */ + size_t cbRGBBuf; +} RECORDINGVIDEOFRAME, *PRECORDINGVIDEOFRAME; + +/** + * Structure for keeping a single recording audio frame. + */ +typedef struct RECORDINGAUDIOFRAME +{ + /** Pointer to audio data. */ + uint8_t *pvBuf; + /** Size (in bytes) of audio data. */ + size_t cbBuf; +} RECORDINGAUDIOFRAME, *PRECORDINGAUDIOFRAME; + +/** + * Structure for keeping a single recording audio frame. + */ +typedef struct RECORDINGFRAME +{ + /** List node. */ + RTLISTNODE Node; + /** Stream index (hint) where this frame should go to. + * Specify UINT16_MAX to broadcast to all streams. */ + uint16_t idStream; + /** The frame type. */ + RECORDINGFRAME_TYPE enmType; + /** Timestamp (PTS, in ms). */ + uint64_t msTimestamp; + union + { +#ifdef VBOX_WITH_AUDIO_RECORDING + /** Audio frame data. */ + RECORDINGAUDIOFRAME Audio; +#endif + /** Video frame data. */ + RECORDINGVIDEOFRAME Video; + /** A (weak) pointer to a video frame. */ + RECORDINGVIDEOFRAME *VideoPtr; + }; +} RECORDINGFRAME, *PRECORDINGFRAME; + +/** + * Enumeration for specifying a video recording block type. + */ +typedef enum RECORDINGBLOCKTYPE +{ + /** Uknown block type, do not use. */ + RECORDINGBLOCKTYPE_UNKNOWN = 0, + /** The block is a video frame. */ + RECORDINGBLOCKTYPE_VIDEO, + /** The block is an audio frame. */ + RECORDINGBLOCKTYPE_AUDIO +} RECORDINGBLOCKTYPE; + +#ifdef VBOX_WITH_AUDIO_RECORDING +int RecordingVideoFrameInit(PRECORDINGVIDEOFRAME pFrame, int w, int h, uint8_t uBPP, RECORDINGPIXELFMT enmPixelFmt); +void RecordingVideoFrameDestroy(PRECORDINGVIDEOFRAME pFrame); +void RecordingAudioFrameFree(PRECORDINGAUDIOFRAME pFrame); +#endif +void RecordingVideoFrameFree(PRECORDINGVIDEOFRAME pFrame); +void RecordingFrameFree(PRECORDINGFRAME pFrame); + +/** + * Generic structure for keeping a single video recording (data) block. + */ +struct RecordingBlock +{ + RecordingBlock() + : enmType(RECORDINGBLOCKTYPE_UNKNOWN) + , cRefs(0) + , uFlags(RECORDINGCODEC_ENC_F_NONE) + , pvData(NULL) + , cbData(0) { } + + virtual ~RecordingBlock() + { + Reset(); + } + + void Reset(void) + { + switch (enmType) + { + case RECORDINGBLOCKTYPE_UNKNOWN: + break; + + case RECORDINGBLOCKTYPE_VIDEO: + RecordingVideoFrameFree((PRECORDINGVIDEOFRAME)pvData); + break; + +#ifdef VBOX_WITH_AUDIO_RECORDING + case RECORDINGBLOCKTYPE_AUDIO: + RecordingAudioFrameFree((PRECORDINGAUDIOFRAME)pvData); + break; +#endif + default: + AssertFailed(); + break; + } + + enmType = RECORDINGBLOCKTYPE_UNKNOWN; + cRefs = 0; + pvData = NULL; + cbData = 0; + } + + /** The block's type. */ + RECORDINGBLOCKTYPE enmType; + /** Number of references held of this block. */ + uint16_t cRefs; + /** Block flags of type RECORDINGCODEC_ENC_F_XXX. */ + uint64_t uFlags; + /** The (absolute) timestamp (in ms, PTS) of this block. */ + uint64_t msTimestamp; + /** Opaque data block to the actual block data, depending on the block's type. */ + void *pvData; + /** Size (in bytes) of the (opaque) data block. */ + size_t cbData; +}; + +/** List for keeping video recording (data) blocks. */ +typedef std::list<RecordingBlock *> RecordingBlockList; + +int recordingCodecCreateAudio(PRECORDINGCODEC pCodec, RecordingAudioCodec_T enmAudioCodec); +int recordingCodecCreateVideo(PRECORDINGCODEC pCodec, RecordingVideoCodec_T enmVideoCodec); +int recordingCodecInit(const PRECORDINGCODEC pCodec, const PRECORDINGCODECCALLBACKS pCallbacks, const settings::RecordingScreenSettings &Settings); +int recordingCodecDestroy(PRECORDINGCODEC pCodec); +int recordingCodecEncode(PRECORDINGCODEC pCodec, const PRECORDINGFRAME pFrame, size_t *pcEncoded, size_t *pcbEncoded); +int recordingCodecFinalize(PRECORDINGCODEC pCodec); +bool recordingCodecIsInitialized(const PRECORDINGCODEC pCodec); +uint32_t recordingCodecGetWritable(const PRECORDINGCODEC pCodec, uint64_t msTimestamp); +#endif /* !MAIN_INCLUDED_RecordingInternals_h */ diff --git a/src/VBox/Main/include/RecordingScreenSettingsImpl.h b/src/VBox/Main/include/RecordingScreenSettingsImpl.h new file mode 100644 index 00000000..59ff1935 --- /dev/null +++ b/src/VBox/Main/include/RecordingScreenSettingsImpl.h @@ -0,0 +1,141 @@ +/* $Id: RecordingScreenSettingsImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation - Recording settings of one virtual screen. + */ + +/* + * Copyright (C) 2018-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_RecordingScreenSettingsImpl_h +#define MAIN_INCLUDED_RecordingScreenSettingsImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "RecordingScreenSettingsWrap.h" + +class RecordingSettings; + +namespace settings +{ + struct RecordingScreenSettings; +} + +class ATL_NO_VTABLE RecordingScreenSettings : + public RecordingScreenSettingsWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(RecordingScreenSettings) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(RecordingSettings *aParent, uint32_t uScreenId, const settings::RecordingScreenSettings& aThat); + HRESULT init(RecordingSettings *aParent, RecordingScreenSettings *aThat); + HRESULT initCopy(RecordingSettings *aParent, RecordingScreenSettings *aThat); + void uninit(void); + + // public methods only for internal purposes + HRESULT i_loadSettings(const settings::RecordingScreenSettings &data); + HRESULT i_saveSettings(settings::RecordingScreenSettings &data); + + void i_rollback(void); + void i_commit(void); + void i_copyFrom(RecordingScreenSettings *aThat); + void i_applyDefaults(void); + + settings::RecordingScreenSettings &i_getData(void); + + int32_t i_reference(void); + int32_t i_release(void); + int32_t i_getReferences(void); + +private: + + // wrapped IRecordingScreenSettings methods + HRESULT isFeatureEnabled(RecordingFeature_T aFeature, BOOL *aEnabled); + + // wrapped IRecordingScreenSettings properties + HRESULT getId(ULONG *id); + HRESULT getEnabled(BOOL *enabled); + HRESULT setEnabled(BOOL enabled); + HRESULT getFeatures(std::vector<RecordingFeature_T> &aFeatures); + HRESULT setFeatures(const std::vector<RecordingFeature_T> &aFeatures); + HRESULT getDestination(RecordingDestination_T *aDestination); + HRESULT setDestination(RecordingDestination_T aDestination); + + HRESULT getFilename(com::Utf8Str &aFilename); + HRESULT setFilename(const com::Utf8Str &aFilename); + HRESULT getMaxTime(ULONG *aMaxTimeS); + HRESULT setMaxTime(ULONG aMaxTimeS); + HRESULT getMaxFileSize(ULONG *aMaxFileSizeMB); + HRESULT setMaxFileSize(ULONG aMaxFileSizeMB); + HRESULT getOptions(com::Utf8Str &aOptions); + HRESULT setOptions(const com::Utf8Str &aOptions); + + HRESULT getAudioCodec(RecordingAudioCodec_T *aCodec); + HRESULT setAudioCodec(RecordingAudioCodec_T aCodec); + HRESULT getAudioDeadline(RecordingCodecDeadline_T *aDeadline); + HRESULT setAudioDeadline(RecordingCodecDeadline_T aDeadline); + HRESULT getAudioRateControlMode(RecordingRateControlMode_T *aMode); + HRESULT setAudioRateControlMode(RecordingRateControlMode_T aMode); + HRESULT getAudioHz(ULONG *aHz); + HRESULT setAudioHz(ULONG aHz); + HRESULT getAudioBits(ULONG *aBits); + HRESULT setAudioBits(ULONG aBits); + HRESULT getAudioChannels(ULONG *aChannels); + HRESULT setAudioChannels(ULONG aChannels); + + HRESULT getVideoCodec(RecordingVideoCodec_T *aCodec); + HRESULT setVideoCodec(RecordingVideoCodec_T aCodec); + HRESULT getVideoDeadline(RecordingCodecDeadline_T *aDeadline); + HRESULT setVideoDeadline(RecordingCodecDeadline_T aDeadline); + HRESULT getVideoWidth(ULONG *aVideoWidth); + HRESULT setVideoWidth(ULONG aVideoWidth); + HRESULT getVideoHeight(ULONG *aVideoHeight); + HRESULT setVideoHeight(ULONG aVideoHeight); + HRESULT getVideoRate(ULONG *aVideoRate); + HRESULT setVideoRate(ULONG aVideoRate); + HRESULT getVideoRateControlMode(RecordingRateControlMode_T *aMode); + HRESULT setVideoRateControlMode(RecordingRateControlMode_T aMode); + HRESULT getVideoFPS(ULONG *aVideoFPS); + HRESULT setVideoFPS(ULONG aVideoFPS); + HRESULT getVideoScalingMode(RecordingVideoScalingMode_T *aMode); + HRESULT setVideoScalingMode(RecordingVideoScalingMode_T aMode); + +private: + + // internal methods + int i_initInternal(); + +private: + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_RecordingScreenSettingsImpl_h */ + diff --git a/src/VBox/Main/include/RecordingSettingsImpl.h b/src/VBox/Main/include/RecordingSettingsImpl.h new file mode 100644 index 00000000..4fb7bb82 --- /dev/null +++ b/src/VBox/Main/include/RecordingSettingsImpl.h @@ -0,0 +1,102 @@ +/* $Id: RecordingSettingsImpl.h $ */ +/** @file + * VirtualBox COM class implementation - Machine recording screen settings. + */ + +/* + * Copyright (C) 2018-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_RecordingSettingsImpl_h +#define MAIN_INCLUDED_RecordingSettingsImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "RecordingSettingsWrap.h" + +namespace settings +{ + struct RecordingSettings; + struct RecordingScreenSettings; +} + +class RecordingScreenSettings; + +class ATL_NO_VTABLE RecordingSettings + : public RecordingSettingsWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(RecordingSettings) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *parent); + HRESULT init(Machine *parent, RecordingSettings *aThat); + HRESULT initCopy(Machine *parent, RecordingSettings *aThat); + void uninit(); + + // public methods only for internal purposes + HRESULT i_loadSettings(const settings::RecordingSettings &data); + HRESULT i_saveSettings(settings::RecordingSettings &data); + + void i_rollback(void); + void i_commit(void); + HRESULT i_copyFrom(RecordingSettings *aThat); + void i_applyDefaults(void); + + int i_getDefaultFilename(Utf8Str &strFile, uint32_t idScreen, bool fWithFileExtension); + int i_getFilename(Utf8Str &strFile, uint32_t idScreen, const Utf8Str &strTemplate); + bool i_canChangeSettings(void); + void i_onSettingsChanged(void); + +private: + + /** Map of screen settings objects. The key specifies the screen ID. */ + typedef std::map <uint32_t, ComObjPtr<RecordingScreenSettings> > RecordingScreenSettingsObjMap; + + void i_reset(void); + int i_syncToMachineDisplays(uint32_t cDisplays); + int i_createScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap, uint32_t idScreen, const settings::RecordingScreenSettings &data); + int i_destroyScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap, uint32_t idScreen); + int i_destroyAllScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap); + +private: + + // wrapped IRecordingSettings properties + HRESULT getEnabled(BOOL *enabled); + HRESULT setEnabled(BOOL enable); + HRESULT getScreens(std::vector<ComPtr<IRecordingScreenSettings> > &aRecordScreenSettings); + + // wrapped IRecordingSettings methods + HRESULT getScreenSettings(ULONG uScreenId, ComPtr<IRecordingScreenSettings> &aRecordScreenSettings); + +private: + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_RecordingSettingsImpl_h */ + diff --git a/src/VBox/Main/include/RecordingStream.h b/src/VBox/Main/include/RecordingStream.h new file mode 100644 index 00000000..ae17a7a7 --- /dev/null +++ b/src/VBox/Main/include/RecordingStream.h @@ -0,0 +1,234 @@ +/* $Id: RecordingStream.h $ */ +/** @file + * Recording stream code header. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_RecordingStream_h +#define MAIN_INCLUDED_RecordingStream_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <map> +#include <vector> + +#include <iprt/critsect.h> + +#include "RecordingInternals.h" + +class WebMWriter; +class RecordingContext; + +/** Structure for queuing all blocks bound to a single timecode. + * This can happen if multiple tracks are being involved. */ +struct RecordingBlocks +{ + virtual ~RecordingBlocks() + { + Clear(); + } + + /** + * Resets a recording block list by removing (destroying) + * all current elements. + */ + void Clear() + { + while (!List.empty()) + { + RecordingBlock *pBlock = List.front(); + List.pop_front(); + delete pBlock; + } + + Assert(List.size() == 0); + } + + /** The actual block list for this timecode. */ + RecordingBlockList List; +}; + +/** A block map containing all currently queued blocks. + * The key specifies a unique timecode, whereas the value + * is a list of blocks which all correlate to the same key (timecode). */ +typedef std::map<uint64_t, RecordingBlocks *> RecordingBlockMap; + +/** + * Structure for holding a set of recording (data) blocks. + */ +struct RecordingBlockSet +{ + virtual ~RecordingBlockSet() + { + Clear(); + } + + /** + * Resets a recording block set by removing (destroying) + * all current elements. + */ + void Clear(void) + { + RecordingBlockMap::iterator it = Map.begin(); + while (it != Map.end()) + { + it->second->Clear(); + delete it->second; + Map.erase(it); + it = Map.begin(); + } + + Assert(Map.size() == 0); + } + + /** Timestamp (in ms) when this set was last processed. */ + uint64_t tsLastProcessedMs; + /** All blocks related to this block set. */ + RecordingBlockMap Map; +}; + +/** + * Class for managing a recording stream. + * + * A recording stream represents one entity to record (e.g. on screen / monitor), + * so there is a 1:1 mapping (stream <-> monitors). + */ +class RecordingStream +{ +public: + + RecordingStream(RecordingContext *pCtx, uint32_t uScreen, const settings::RecordingScreenSettings &Settings); + + virtual ~RecordingStream(void); + +public: + + int Init(RecordingContext *pCtx, uint32_t uScreen, const settings::RecordingScreenSettings &Settings); + int Uninit(void); + + int Process(RecordingBlockMap &mapBlocksCommon); + int SendAudioFrame(const void *pvData, size_t cbData, uint64_t msTimestamp); + int SendVideoFrame(uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine, + uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData, uint64_t msTimestamp); + + const settings::RecordingScreenSettings &GetConfig(void) const; + uint16_t GetID(void) const { return this->m_uScreenID; }; +#ifdef VBOX_WITH_AUDIO_RECORDING + PRECORDINGCODEC GetAudioCodec(void) { return this->m_pCodecAudio; }; +#endif + PRECORDINGCODEC GetVideoCodec(void) { return &this->m_CodecVideo; }; + + bool IsLimitReached(uint64_t msTimestamp) const; + bool IsReady(void) const; + bool NeedsUpdate(uint64_t msTimestamp) const; + +public: + + static DECLCALLBACK(int) codecWriteDataCallback(PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, uint64_t msAbsPTS, uint32_t uFlags, void *pvUser); + +protected: + + int open(const settings::RecordingScreenSettings &screenSettings); + int close(void); + + int initInternal(RecordingContext *pCtx, uint32_t uScreen, const settings::RecordingScreenSettings &screenSettings); + int uninitInternal(void); + + int initVideo(const settings::RecordingScreenSettings &screenSettings); + int unitVideo(void); + + bool isLimitReachedInternal(uint64_t msTimestamp) const; + int iterateInternal(uint64_t msTimestamp); + + int codecWriteToWebM(PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, uint64_t msAbsPTS, uint32_t uFlags); + + void lock(void); + void unlock(void); + +protected: + + /** + * Enumeration for a recording stream state. + */ + enum RECORDINGSTREAMSTATE + { + /** Stream not initialized. */ + RECORDINGSTREAMSTATE_UNINITIALIZED = 0, + /** Stream was initialized. */ + RECORDINGSTREAMSTATE_INITIALIZED = 1, + /** The usual 32-bit hack. */ + RECORDINGSTREAMSTATE_32BIT_HACK = 0x7fffffff + }; + + /** Recording context this stream is associated to. */ + RecordingContext *m_pCtx; + /** The current state. */ + RECORDINGSTREAMSTATE m_enmState; + struct + { + /** File handle to use for writing. */ + RTFILE m_hFile; + /** Pointer to WebM writer instance being used. */ + WebMWriter *m_pWEBM; + } File; + bool m_fEnabled; + /** Track number of audio stream. + * Set to UINT8_MAX if not being used. */ + uint8_t m_uTrackAudio; + /** Track number of video stream. + * Set to UINT8_MAX if not being used. */ + uint8_t m_uTrackVideo; + /** Screen ID. */ + uint16_t m_uScreenID; + /** Critical section to serialize access. */ + RTCRITSECT m_CritSect; + /** Timestamp (in ms) of when recording has been started. */ + uint64_t m_tsStartMs; +#ifdef VBOX_WITH_AUDIO_RECORDING + /** Pointer to audio codec instance data to use. + * + * We multiplex audio data from the recording context to all streams, + * to avoid encoding the same audio data for each stream. We ASSUME that + * all audio data of a VM will be the same for each stream at a given + * point in time. + * + * Might be NULL if not being used. */ + PRECORDINGCODEC m_pCodecAudio; +#endif /* VBOX_WITH_AUDIO_RECORDING */ + /** Video codec instance data to use. */ + RECORDINGCODEC m_CodecVideo; + /** Screen settings to use. */ + settings::RecordingScreenSettings + m_ScreenSettings; + /** Common set of recording (data) blocks, needed for + * multiplexing to all recording streams. */ + RecordingBlockSet m_Blocks; +}; + +/** Vector of recording streams. */ +typedef std::vector <RecordingStream *> RecordingStreams; + +#endif /* !MAIN_INCLUDED_RecordingStream_h */ + diff --git a/src/VBox/Main/include/RecordingUtils.h b/src/VBox/Main/include/RecordingUtils.h new file mode 100644 index 00000000..d8c82084 --- /dev/null +++ b/src/VBox/Main/include/RecordingUtils.h @@ -0,0 +1,217 @@ +/* $Id: RecordingUtils.h $ */ +/** @file + * Recording utility header. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_RecordingUtils_h +#define MAIN_INCLUDED_RecordingUtils_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "RecordingInternals.h" + + +/** + * Iterator class for running through a BGRA32 image buffer and converting + * it to RGB. + */ +class ColorConvBGRA32Iter +{ +private: + enum { PIX_SIZE = 4 }; +public: + ColorConvBGRA32Iter(unsigned aWidth, unsigned aHeight, uint8_t *aBuf) + { + mPos = 0; + mSize = aWidth * aHeight * PIX_SIZE; + mBuf = aBuf; + } + + /** + * Convert the next pixel to RGB. + * + * @returns true on success, false if we have reached the end of the buffer + * @param aRed where to store the red value. + * @param aGreen where to store the green value. + * @param aBlue where to store the blue value. + */ + bool getRGB(unsigned *aRed, unsigned *aGreen, unsigned *aBlue) + { + bool rc = false; + if (mPos + PIX_SIZE <= mSize) + { + *aRed = mBuf[mPos + 2]; + *aGreen = mBuf[mPos + 1]; + *aBlue = mBuf[mPos ]; + mPos += PIX_SIZE; + rc = true; + } + return rc; + } + + /** + * Skip forward by a certain number of pixels. + * + * @param aPixels How many pixels to skip. + */ + void skip(unsigned aPixels) + { + mPos += PIX_SIZE * aPixels; + } +private: + /** Size of the picture buffer. */ + unsigned mSize; + /** Current position in the picture buffer. */ + unsigned mPos; + /** Address of the picture buffer. */ + uint8_t *mBuf; +}; + +/** + * Iterator class for running through an BGR24 image buffer and converting + * it to RGB. + */ +class ColorConvBGR24Iter +{ +private: + enum { PIX_SIZE = 3 }; +public: + ColorConvBGR24Iter(unsigned aWidth, unsigned aHeight, uint8_t *aBuf) + { + mPos = 0; + mSize = aWidth * aHeight * PIX_SIZE; + mBuf = aBuf; + } + + /** + * Convert the next pixel to RGB. + * + * @returns true on success, false if we have reached the end of the buffer. + * @param aRed where to store the red value. + * @param aGreen where to store the green value. + * @param aBlue where to store the blue value. + */ + bool getRGB(unsigned *aRed, unsigned *aGreen, unsigned *aBlue) + { + bool rc = false; + if (mPos + PIX_SIZE <= mSize) + { + *aRed = mBuf[mPos + 2]; + *aGreen = mBuf[mPos + 1]; + *aBlue = mBuf[mPos ]; + mPos += PIX_SIZE; + rc = true; + } + return rc; + } + + /** + * Skip forward by a certain number of pixels. + * + * @param aPixels How many pixels to skip. + */ + void skip(unsigned aPixels) + { + mPos += PIX_SIZE * aPixels; + } +private: + /** Size of the picture buffer. */ + unsigned mSize; + /** Current position in the picture buffer. */ + unsigned mPos; + /** Address of the picture buffer. */ + uint8_t *mBuf; +}; + +/** + * Iterator class for running through an BGR565 image buffer and converting + * it to RGB. + */ +class ColorConvBGR565Iter +{ +private: + enum { PIX_SIZE = 2 }; +public: + ColorConvBGR565Iter(unsigned aWidth, unsigned aHeight, uint8_t *aBuf) + { + mPos = 0; + mSize = aWidth * aHeight * PIX_SIZE; + mBuf = aBuf; + } + + /** + * Convert the next pixel to RGB. + * + * @returns true on success, false if we have reached the end of the buffer. + * @param aRed Where to store the red value. + * @param aGreen where to store the green value. + * @param aBlue where to store the blue value. + */ + bool getRGB(unsigned *aRed, unsigned *aGreen, unsigned *aBlue) + { + bool rc = false; + if (mPos + PIX_SIZE <= mSize) + { + unsigned uFull = (((unsigned) mBuf[mPos + 1]) << 8) + | ((unsigned) mBuf[mPos]); + *aRed = (uFull >> 8) & ~7; + *aGreen = (uFull >> 3) & ~3 & 0xff; + *aBlue = (uFull << 3) & ~7 & 0xff; + mPos += PIX_SIZE; + rc = true; + } + return rc; + } + + /** + * Skip forward by a certain number of pixels. + * + * @param aPixels How many pixels to skip. + */ + void skip(unsigned aPixels) + { + mPos += PIX_SIZE * aPixels; + } +private: + /** Size of the picture buffer. */ + unsigned mSize; + /** Current position in the picture buffer. */ + unsigned mPos; + /** Address of the picture buffer. */ + uint8_t *mBuf; +}; + +int RecordingUtilsRGBToYUV(RECORDINGPIXELFMT enmPixelFormat, + uint8_t *paDst, uint32_t uDstWidth, uint32_t uDstHeight, + uint8_t *paSrc, uint32_t uSrcWidth, uint32_t uSrcHeight); + +#ifdef DEBUG +int RecordingUtilsDbgDumpFrameEx(const uint8_t *pu8RGBBuf, size_t cbRGBBuf, const char *pszPath, const char *pszPrefx, uint16_t uWidth, uint32_t uHeight, uint8_t uBPP); +int RecordingUtilsDbgDumpFrame(const PRECORDINGFRAME pFrame); +#endif + +#endif /* !MAIN_INCLUDED_RecordingUtils_h */ + diff --git a/src/VBox/Main/include/RemoteUSBBackend.h b/src/VBox/Main/include/RemoteUSBBackend.h new file mode 100644 index 00000000..dc59fccc --- /dev/null +++ b/src/VBox/Main/include/RemoteUSBBackend.h @@ -0,0 +1,153 @@ +/* $Id: RemoteUSBBackend.h $ */ +/** @file + * + * VirtualBox Remote USB backend + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_RemoteUSBBackend_h +#define MAIN_INCLUDED_RemoteUSBBackend_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "RemoteUSBDeviceImpl.h" + +#include <VBox/RemoteDesktop/VRDE.h> +#include <VBox/vrdpusb.h> + +#include <iprt/critsect.h> + +//typedef enum +//{ +// RDLIdle = 0, +// RDLReqSent, +// RDLObtained +//} RDLState; + +class Console; +class ConsoleVRDPServer; + +DECLCALLBACK(int) USBClientResponseCallback (void *pv, uint32_t u32ClientId, uint8_t code, const void *pvRet, uint32_t cbRet); + + +/* How many remote devices can be attached to a remote client. + * Normally a client computer has 2-8 physical USB ports, so 16 devices + * should be usually enough. + */ +#define VRDP_MAX_USB_DEVICES_PER_CLIENT (16) + +class RemoteUSBBackendListable +{ + public: + RemoteUSBBackendListable *pNext; + RemoteUSBBackendListable *pPrev; + + RemoteUSBBackendListable() : pNext (NULL), pPrev (NULL) {}; +}; + +class RemoteUSBBackend: public RemoteUSBBackendListable +{ + public: + RemoteUSBBackend(Console *console, ConsoleVRDPServer *server, uint32_t u32ClientId); + ~RemoteUSBBackend(); + + uint32_t ClientId (void) { return mu32ClientId; } + + void AddRef (void); + void Release (void); + + REMOTEUSBCALLBACK *GetBackendCallbackPointer (void) { return &mCallback; } + + void NotifyDelete (void); + + void PollRemoteDevices (void); + + public: /* Functions for internal use. */ + ConsoleVRDPServer *VRDPServer (void) { return mServer; }; + + bool pollingEnabledURB (void) { return mfPollURB; } + + int saveDeviceList (const void *pvList, uint32_t cbList); + + int negotiateResponse (const VRDEUSBREQNEGOTIATERET *pret, uint32_t cbRet); + + int reapURB (const void *pvBody, uint32_t cbBody); + + void request (void); + void release (void); + + PREMOTEUSBDEVICE deviceFromId (VRDEUSBDEVID id); + + void addDevice (PREMOTEUSBDEVICE pDevice); + void removeDevice (PREMOTEUSBDEVICE pDevice); + + bool addUUID (const Guid *pUuid); + bool findUUID (const Guid *pUuid); + void removeUUID (const Guid *pUuid); + + private: + Console *mConsole; + ConsoleVRDPServer *mServer; + + int cRefs; + + uint32_t mu32ClientId; + + RTCRITSECT mCritsect; + + REMOTEUSBCALLBACK mCallback; + + bool mfHasDeviceList; + + void *mpvDeviceList; + uint32_t mcbDeviceList; + + typedef enum { + PollRemoteDevicesStatus_Negotiate, + PollRemoteDevicesStatus_WaitNegotiateResponse, + PollRemoteDevicesStatus_SendRequest, + PollRemoteDevicesStatus_WaitResponse, + PollRemoteDevicesStatus_Dereferenced + } PollRemoteDevicesStatus; + + PollRemoteDevicesStatus menmPollRemoteDevicesStatus; + + bool mfPollURB; + + PREMOTEUSBDEVICE mpDevices; + + bool mfWillBeDeleted; + + Guid aGuids[VRDP_MAX_USB_DEVICES_PER_CLIENT]; + + /* VRDP_USB_VERSION_2: the client version. */ + uint32_t mClientVersion; + + /* VRDP_USB_VERSION_3: the client sends VRDE_USB_REQ_DEVICE_LIST_EXT_RET. */ + bool mfDescExt; +}; + +#endif /* !MAIN_INCLUDED_RemoteUSBBackend_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/RemoteUSBDeviceImpl.h b/src/VBox/Main/include/RemoteUSBDeviceImpl.h new file mode 100644 index 00000000..2adbee08 --- /dev/null +++ b/src/VBox/Main/include/RemoteUSBDeviceImpl.h @@ -0,0 +1,136 @@ +/* $Id: RemoteUSBDeviceImpl.h $ */ + +/** @file + * + * VirtualBox IHostUSBDevice COM interface implementation + * for remote (VRDP) USB devices + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_RemoteUSBDeviceImpl_h +#define MAIN_INCLUDED_RemoteUSBDeviceImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "HostUSBDeviceWrap.h" + +struct _VRDEUSBDEVICEDESC; +typedef _VRDEUSBDEVICEDESC VRDEUSBDEVICEDESC; + +class ATL_NO_VTABLE RemoteUSBDevice : + public HostUSBDeviceWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(RemoteUSBDevice) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(uint32_t u32ClientId, VRDEUSBDEVICEDESC *pDevDesc, bool fDescExt); + void uninit(); + + // public methods only for internal purposes + bool dirty(void) const { return mData.dirty; } + void dirty(bool aDirty) { mData.dirty = aDirty; } + + uint16_t devId(void) const { return mData.devId; } + uint32_t clientId(void) { return mData.clientId; } + + bool captured(void) const { return mData.state == USBDeviceState_Captured; } + void captured(bool aCaptured) + { + if (aCaptured) + { + Assert(mData.state == USBDeviceState_Available); + mData.state = USBDeviceState_Captured; + } + else + { + Assert(mData.state == USBDeviceState_Captured); + mData.state = USBDeviceState_Available; + } + } + +private: + + // wrapped IUSBDevice properties + HRESULT getId(com::Guid &aId); + HRESULT getVendorId(USHORT *aVendorId); + HRESULT getProductId(USHORT *aProductId); + HRESULT getRevision(USHORT *aRevision); + HRESULT getManufacturer(com::Utf8Str &aManufacturer); + HRESULT getProduct(com::Utf8Str &aProduct); + HRESULT getSerialNumber(com::Utf8Str &aSerialNumber); + HRESULT getAddress(com::Utf8Str &aAddress); + HRESULT getPort(USHORT *aPort); + HRESULT getVersion(USHORT *aVersion); + HRESULT getPortPath(com::Utf8Str &aAddress); + HRESULT getSpeed(USBConnectionSpeed_T *aSpeed); + HRESULT getRemote(BOOL *aRemote); + HRESULT getBackend(com::Utf8Str &aBackend); + HRESULT getDeviceInfo(std::vector<com::Utf8Str> &aInfo); + + // wrapped IHostUSBDevice properties + HRESULT getState(USBDeviceState_T *aState); + + + struct Data + { + Data() : vendorId(0), productId(0), revision(0), port(0), version(1), + speed(USBConnectionSpeed_Null), dirty(FALSE), + devId(0), clientId(0) {} + + const Guid id; + + const uint16_t vendorId; + const uint16_t productId; + const uint16_t revision; + + const Utf8Str manufacturer; + const Utf8Str product; + const Utf8Str serialNumber; + + const Utf8Str address; + const Utf8Str backend; + + const uint16_t port; + const Utf8Str portPath; + const uint16_t version; + const USBConnectionSpeed_T speed; + + USBDeviceState_T state; + bool dirty; + + const uint16_t devId; + const uint32_t clientId; + }; + + Data mData; +}; + +#endif /* !MAIN_INCLUDED_RemoteUSBDeviceImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/SecretKeyStore.h b/src/VBox/Main/include/SecretKeyStore.h new file mode 100644 index 00000000..27d738ec --- /dev/null +++ b/src/VBox/Main/include/SecretKeyStore.h @@ -0,0 +1,216 @@ +/* $Id: SecretKeyStore.h $ */ +/** @file + * Main - Secret key interface. + */ + +/* + * Copyright (C) 2015-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_SecretKeyStore_h +#define MAIN_INCLUDED_SecretKeyStore_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxBase.h" +#include "VBox/com/array.h" + +class SecretKey +{ + public: + + /** + * Constructor for a secret key. + * + * @param pbKey The key buffer. + * @param cbKey Size of the key. + * @param fKeyBufNonPageable Flag whether the key buffer should be non pageable. + */ + SecretKey(const uint8_t *pbKey, size_t cbKey, bool fKeyBufNonPageable); + + /** + * Secret key destructor. + */ + ~SecretKey(); + + /** + * Increments the reference counter of the key. + * + * @returns The new reference count. + */ + uint32_t retain(); + + /** + * Releases a reference of the key. + * If the reference counter reaches 0 the key buffer might be protected + * against further access or the data will become scrambled. + * + * @returns The new reference count. + */ + uint32_t release(); + + /** + * Returns the reference count of the secret key. + */ + uint32_t refCount(); + + /** + * Sets the possible number of users for this key. + * + * @returns VBox status code. + * @param cUsers The possible number of user for this key. + */ + int setUsers(uint32_t cUsers); + + /** + * Returns the possible amount of users. + * + * @returns Possible amount of users. + */ + uint32_t getUsers(); + + /** + * Sets the remove on suspend flag. + * + * @returns VBox status code. + * @param fRemoveOnSuspend Flag whether to remove the key on host suspend. + */ + int setRemoveOnSuspend(bool fRemoveOnSuspend); + + /** + * Returns whether the key should be destroyed on suspend. + */ + bool getRemoveOnSuspend(); + + /** + * Returns the buffer to the key. + */ + const void *getKeyBuffer(); + + /** + * Returns the size of the key. + */ + size_t getKeySize(); + + private: + /** Reference counter of the key. */ + volatile uint32_t m_cRefs; + /** Key material. */ + uint8_t *m_pbKey; + /** Size of the key in bytes. */ + size_t m_cbKey; + /** Flag whether to remove the key on suspend. */ + bool m_fRemoveOnSuspend; + /** Number of entities which will use this key. */ + uint32_t m_cUsers; +}; + +class SecretKeyStore +{ + public: + + typedef std::map<com::Utf8Str, SecretKey *> SecretKeyMap; + + /** + * Constructor for a secret key store. + * + * @param fKeyBufNonPageable Flag whether the key buffer is required to + * be non pageable. + */ + SecretKeyStore(bool fKeyBufNonPageable); + + /** + * Destructor of a secret key store. This will free all stored secret keys + * inluding the key buffers. Make sure there no one accesses one of the keys + * stored. + */ + ~SecretKeyStore(); + + /** + * Add a secret key to the store. + * + * @returns VBox status code. + * @param strKeyId The key identifier. + * @param pbKey The key to store. + * @param cbKey Size of the key. + */ + int addSecretKey(const com::Utf8Str &strKeyId, const uint8_t *pbKey, size_t cbKey); + + /** + * Deletes a key from the key store associated with the given identifier. + * + * @returns VBox status code. + * @param strKeyId The key identifier. + */ + int deleteSecretKey(const com::Utf8Str &strKeyId); + + /** + * Returns the secret key object associated with the given identifier. + * This increments the reference counter of the secret key object. + * + * @returns VBox status code. + * @param strKeyId The key identifier. + * @param ppKey Where to store the secret key object on success. + */ + int retainSecretKey(const com::Utf8Str &strKeyId, SecretKey **ppKey); + + /** + * Releases a reference to the secret key object. + * + * @returns VBox status code. + * @param strKeyId The key identifier. + */ + int releaseSecretKey(const com::Utf8Str &strKeyId); + + /** + * Deletes all secret keys from the key store. + * + * @returns VBox status code. + * @param fSuspend Flag whether to delete only keys which are + * marked for deletion during a suspend. + * @param fForce Flag whether to force deletion if some keys + * are still in use. Otherwise an error is returned. + */ + int deleteAllSecretKeys(bool fSuspend, bool fForce); + + /** + * Iterators for enumerating keys + */ + SecretKeyMap::iterator begin() + { + return m_mapSecretKeys.begin(); + } + + SecretKeyMap::iterator end() + { + return m_mapSecretKeys.end(); + } + + private: + + /** The map to map key identifers to secret keys. */ + SecretKeyMap m_mapSecretKeys; + /** Flag whether key buffers should be non pagable. */ + bool m_fKeyBufNonPageable; +}; + +#endif /* !MAIN_INCLUDED_SecretKeyStore_h */ diff --git a/src/VBox/Main/include/SerialPortImpl.h b/src/VBox/Main/include/SerialPortImpl.h new file mode 100644 index 00000000..ad9cd827 --- /dev/null +++ b/src/VBox/Main/include/SerialPortImpl.h @@ -0,0 +1,102 @@ +/* $Id: SerialPortImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_SerialPortImpl_h +#define MAIN_INCLUDED_SerialPortImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "SerialPortWrap.h" + +class GuestOSType; + +namespace settings +{ + struct SerialPort; +} + +class ATL_NO_VTABLE SerialPort : + public SerialPortWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(SerialPort) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent, ULONG aSlot); + HRESULT init(Machine *aParent, SerialPort *aThat); + HRESULT initCopy(Machine *parent, SerialPort *aThat); + void uninit(); + + // public methods only for internal purposes + HRESULT i_loadSettings(const settings::SerialPort &data); + HRESULT i_saveSettings(settings::SerialPort &data); + + bool i_isModified(); + void i_rollback(); + void i_commit(); + void i_copyFrom(SerialPort *aThat); + + void i_applyDefaults(GuestOSType *aOsType); + bool i_hasDefaults(); + + // public methods for internal purposes only + // (ensure there is a caller and a read lock before calling them!) + +private: + + HRESULT i_checkSetPath(const Utf8Str &str); + + // Wrapped ISerialPort properties + HRESULT getEnabled(BOOL *aEnabled); + HRESULT setEnabled(BOOL aEnabled); + HRESULT getHostMode(PortMode_T *aHostMode); + HRESULT setHostMode(PortMode_T aHostMode); + HRESULT getSlot(ULONG *aSlot); + HRESULT getIRQ(ULONG *aIRQ); + HRESULT setIRQ(ULONG aIRQ); + HRESULT getIOBase(ULONG *aIOBase); + HRESULT setIOBase(ULONG aIOBase); + HRESULT getServer(BOOL *aServer); + HRESULT setServer(BOOL aServer); + HRESULT getPath(com::Utf8Str &aPath); + HRESULT setPath(const com::Utf8Str &aPath); + HRESULT getUartType(UartType_T *aUartType); + HRESULT setUartType(UartType_T aUartType); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_SerialPortImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/SessionImpl.h b/src/VBox/Main/include/SessionImpl.h new file mode 100644 index 00000000..f66e122e --- /dev/null +++ b/src/VBox/Main/include/SessionImpl.h @@ -0,0 +1,188 @@ +/* $Id: SessionImpl.h $ */ +/** @file + * VBox Client Session COM Class definition + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_SessionImpl_h +#define MAIN_INCLUDED_SessionImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "SessionWrap.h" +#include "ConsoleImpl.h" + +#ifdef RT_OS_WINDOWS +# include "win/resource.h" +#endif + +#if defined(RT_OS_WINDOWS) && !RT_MSC_PREREQ(RT_MSC_VER_VC140) +[threading(free)] +#endif +class ATL_NO_VTABLE Session : + public SessionWrap +#ifdef RT_OS_WINDOWS + , public ATL::CComCoClass<Session, &CLSID_Session> +#endif +{ +public: + + DECLARE_CLASSFACTORY() + + // Do not use any ATL registry support. + //DECLARE_REGISTRY_RESOURCEID(IDR_VIRTUALBOX) + + DECLARE_NOT_AGGREGATABLE(Session) + + DECLARE_COMMON_CLASS_METHODS(Session) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializers/uninitializers only for internal purposes + HRESULT init(); + void uninit(); + +private: + + // Wrapped ISession properties + HRESULT getState(SessionState_T *aState); + HRESULT getType(SessionType_T *aType); + HRESULT getName(com::Utf8Str &aName); + HRESULT setName(const com::Utf8Str &aName); + HRESULT getMachine(ComPtr<IMachine> &aMachine); + HRESULT getConsole(ComPtr<IConsole> &aConsole); + + // Wrapped ISession methods + HRESULT unlockMachine(); + + // Wrapped IInternalSessionControl properties + HRESULT getPID(ULONG *aPid); + HRESULT getRemoteConsole(ComPtr<IConsole> &aRemoteConsole); + HRESULT getNominalState(MachineState_T *aNominalState); + + // Wrapped IInternalSessionControl methods +#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER + HRESULT assignMachine(const ComPtr<IMachine> &aMachine, + LockType_T aLockType, + const com::Utf8Str &aTokenId); +#else + HRESULT assignMachine(const ComPtr<IMachine> &aMachine, + LockType_T aLockType, + const ComPtr<IToken> &aToken); +#endif /* !VBOX_WITH_GENERIC_SESSION_WATCHER */ + HRESULT assignRemoteMachine(const ComPtr<IMachine> &aMachine, + const ComPtr<IConsole> &aConsole); + HRESULT updateMachineState(MachineState_T aMachineState); + HRESULT uninitialize(); + HRESULT onNetworkAdapterChange(const ComPtr<INetworkAdapter> &aNetworkAdapter, + BOOL aChangeAdapter); + HRESULT onAudioAdapterChange(const ComPtr<IAudioAdapter> &aAudioAdapter); + HRESULT onHostAudioDeviceChange(const ComPtr<IHostAudioDevice> &aDevice, + BOOL aNew, AudioDeviceState_T aState, + const ComPtr<IVirtualBoxErrorInfo> &aErrInfo); + HRESULT onSerialPortChange(const ComPtr<ISerialPort> &aSerialPort); + HRESULT onParallelPortChange(const ComPtr<IParallelPort> &aParallelPort); + HRESULT onStorageControllerChange(const Guid &aMachineId, const com::Utf8Str& aControllerName); + HRESULT onMediumChange(const ComPtr<IMediumAttachment> &aMediumAttachment, + BOOL aForce); + HRESULT onStorageDeviceChange(const ComPtr<IMediumAttachment> &aMediumAttachment, + BOOL aRemove, + BOOL aSilent); + HRESULT onVMProcessPriorityChange(VMProcPriority_T priority); + HRESULT onClipboardModeChange(ClipboardMode_T aClipboardMode); + HRESULT onClipboardFileTransferModeChange(BOOL aEnabled); + HRESULT onDnDModeChange(DnDMode_T aDndMode); + HRESULT onCPUChange(ULONG aCpu, + BOOL aAdd); + HRESULT onCPUExecutionCapChange(ULONG aExecutionCap); + HRESULT onVRDEServerChange(BOOL aRestart); + HRESULT onRecordingChange(BOOL aEnable); + HRESULT onUSBControllerChange(); + HRESULT onSharedFolderChange(BOOL aGlobal); + HRESULT onGuestDebugControlChange(const ComPtr<IGuestDebugControl> &aGuestDebugControl); + HRESULT onUSBDeviceAttach(const ComPtr<IUSBDevice> &aDevice, + const ComPtr<IVirtualBoxErrorInfo> &aError, + ULONG aMaskedInterfaces, + const com::Utf8Str &aCaptureFilename); + HRESULT onUSBDeviceDetach(const com::Guid &aId, + const ComPtr<IVirtualBoxErrorInfo> &aError); + HRESULT onShowWindow(BOOL aCheck, + BOOL *aCanShow, + LONG64 *aWinId); + HRESULT onBandwidthGroupChange(const ComPtr<IBandwidthGroup> &aBandwidthGroup); + HRESULT accessGuestProperty(const com::Utf8Str &aName, + const com::Utf8Str &aValue, + const com::Utf8Str &aFlags, + ULONG aAccessMode, + com::Utf8Str &aRetValue, + LONG64 *aRetTimestamp, + com::Utf8Str &aRetFlags); + HRESULT enumerateGuestProperties(const com::Utf8Str &aPatterns, + std::vector<com::Utf8Str> &aKeys, + std::vector<com::Utf8Str> &aValues, + std::vector<LONG64> &aTimestamps, + std::vector<com::Utf8Str> &aFlags); + HRESULT onlineMergeMedium(const ComPtr<IMediumAttachment> &aMediumAttachment, + ULONG aSourceIdx, + ULONG aTargetIdx, + const ComPtr<IProgress> &aProgress); + HRESULT reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments); + HRESULT enableVMMStatistics(BOOL aEnable); + HRESULT pauseWithReason(Reason_T aReason); + HRESULT resumeWithReason(Reason_T aReason); + HRESULT saveStateWithReason(Reason_T aReason, + const ComPtr<IProgress> &aProgress, + const ComPtr<ISnapshot> &aSnapshot, + const Utf8Str &aStateFilePath, + BOOL aPauseVM, + BOOL *aLeftPaused); + HRESULT cancelSaveStateWithReason(); + + + HRESULT i_unlockMachine(bool aFinalRelease, bool aFromServer, AutoWriteLock &aLockW); + + SessionState_T mState; + SessionType_T mType; + Utf8Str mName; + + ComPtr<IInternalMachineControl> mControl; + +#ifndef VBOX_COM_INPROC_API_CLIENT + ComObjPtr<Console> mConsole; +#endif + + ComPtr<IMachine> mRemoteMachine; + ComPtr<IConsole> mRemoteConsole; + + ComPtr<IVirtualBox> mVirtualBox; + + class ClientTokenHolder; + + ClientTokenHolder *mClientTokenHolder; +}; + +#endif /* !MAIN_INCLUDED_SessionImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/SharedFolderImpl.h b/src/VBox/Main/include/SharedFolderImpl.h new file mode 100644 index 00000000..b26002c6 --- /dev/null +++ b/src/VBox/Main/include/SharedFolderImpl.h @@ -0,0 +1,129 @@ +/* $Id: SharedFolderImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_SharedFolderImpl_h +#define MAIN_INCLUDED_SharedFolderImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "SharedFolderWrap.h" +#include <VBox/shflsvc.h> + +class Console; + +class ATL_NO_VTABLE SharedFolder : + public SharedFolderWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS (SharedFolder) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aMachine, const com::Utf8Str &aName, const com::Utf8Str &aHostPath, + bool aWritable, bool aAutoMount, const com::Utf8Str &aAutoMountPoint, bool fFailOnError); + HRESULT initCopy(Machine *aMachine, SharedFolder *aThat); + HRESULT init(Console *aConsole, const com::Utf8Str &aName, const com::Utf8Str &aHostPath, + bool aWritable, bool aAutoMount, const com::Utf8Str &aAutoMountPoint, bool fFailOnError); +// HRESULT init(VirtualBox *aVirtualBox, const Utf8Str &aName, const Utf8Str &aHostPath, +// bool aWritable, const com::Utf8Str &aAutoMountPoint, bool aAutoMount, bool fFailOnError); + void uninit(); + + // public methods for internal purposes only + // (ensure there is a caller and a read lock before calling them!) + + /** + * Public internal method. Returns the shared folder's name. Needs caller! Locking not necessary. + * @return + */ + const Utf8Str &i_getName() const; + + /** + * Public internal method. Returns the shared folder's host path. Needs caller! Locking not necessary. + * @return + */ + const Utf8Str &i_getHostPath() const; + + /** + * Public internal method. Returns true if the shared folder is writable. Needs caller and locking! + * @return + */ + bool i_isWritable() const; + + /** + * Public internal method. Returns true if the shared folder is auto-mounted. Needs caller and locking! + * @return + */ + bool i_isAutoMounted() const; + + /** + * Public internal method for getting the auto mount point. + */ + const Utf8Str &i_getAutoMountPoint() const; + +protected: + + HRESULT i_protectedInit(VirtualBoxBase *aParent, + const Utf8Str &aName, + const Utf8Str &aHostPath, + bool aWritable, + bool aAutoMount, + const com::Utf8Str &aAutoMountPoint, + bool fFailOnError); +private: + + // wrapped ISharedFolder properies. + HRESULT getName(com::Utf8Str &aName); + HRESULT getHostPath(com::Utf8Str &aHostPath); + HRESULT getAccessible(BOOL *aAccessible); + HRESULT getWritable(BOOL *aWritable); + HRESULT setWritable(BOOL aWritable); + HRESULT getAutoMount(BOOL *aAutoMount); + HRESULT setAutoMount(BOOL aAutoMount); + HRESULT getAutoMountPoint(com::Utf8Str &aAutoMountPoint); + HRESULT setAutoMountPoint(com::Utf8Str const &aAutoMountPoint); + HRESULT getLastAccessError(com::Utf8Str &aLastAccessError); + + VirtualBoxBase * const mParent; + + /* weak parents (only one of them is not null) */ +#if !defined(VBOX_COM_INPROC) + Machine * const mMachine; + VirtualBox * const mVirtualBox; +#else + Console * const mConsole; +#endif + + struct Data; // opaque data struct, defined in SharedFolderImpl.cpp + Data *m; +}; + +#endif /* !MAIN_INCLUDED_SharedFolderImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/SnapshotImpl.h b/src/VBox/Main/include/SnapshotImpl.h new file mode 100644 index 00000000..ea6fd309 --- /dev/null +++ b/src/VBox/Main/include/SnapshotImpl.h @@ -0,0 +1,142 @@ +/* $Id: SnapshotImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_SnapshotImpl_h +#define MAIN_INCLUDED_SnapshotImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "SnapshotWrap.h" + +class SnapshotMachine; + +namespace settings +{ + struct Snapshot; +} + +class ATL_NO_VTABLE Snapshot : + public SnapshotWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(Snapshot) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer only for internal purposes + HRESULT init(VirtualBox *aVirtualBox, + const Guid &aId, + const com::Utf8Str &aName, + const com::Utf8Str &aDescription, + const RTTIMESPEC &aTimeStamp, + SnapshotMachine *aMachine, + Snapshot *aParent); + void uninit(); + + void i_beginSnapshotDelete(); + + void i_deparent(); + + // public methods only for internal purposes + + /** + * Override of the default locking class to be used for validating lock + * order with the standard member lock handle. + */ + virtual VBoxLockingClass getLockingClass() const + { + return LOCKCLASS_SNAPSHOTOBJECT; + } + + const ComObjPtr<Snapshot>& i_getParent() const; + const ComObjPtr<Snapshot> i_getFirstChild() const; + + const Utf8Str& i_getStateFilePath() const; + + uint32_t i_getDepth(); + + ULONG i_getChildrenCount(); + ULONG i_getAllChildrenCount(); + + const ComObjPtr<SnapshotMachine>& i_getSnapshotMachine() const; + + Guid i_getId() const; + const Utf8Str& i_getName() const; + RTTIMESPEC i_getTimeStamp() const; + + ComObjPtr<Snapshot> i_findChildOrSelf(IN_GUID aId); + ComObjPtr<Snapshot> i_findChildOrSelf(const com::Utf8Str &aName); + + void i_updateSavedStatePaths(const Utf8Str &strOldPath, + const Utf8Str &strNewPath); + void i_updateSavedStatePathsImpl(const Utf8Str &strOldPath, + const Utf8Str &strNewPath); + + bool i_sharesSavedStateFile(const Utf8Str &strPath, + Snapshot *pSnapshotToIgnore); + + void i_updateNVRAMPaths(const Utf8Str &strOldPath, + const Utf8Str &strNewPath); + void i_updateNVRAMPathsImpl(const Utf8Str &strOldPath, + const Utf8Str &strNewPath); + + HRESULT i_saveSnapshotOne(settings::Snapshot &data) const; + HRESULT i_saveSnapshot(settings::Snapshot &data) const; + + HRESULT i_uninitAll(AutoWriteLock &writeLock, + CleanupMode_T cleanupMode, + MediaList &llMedia, + std::list<Utf8Str> &llFilenames); + + +private: + + struct Data; // opaque, defined in SnapshotImpl.cpp + + // wrapped ISnapshot properties + HRESULT getId(com::Guid &aId); + HRESULT getName(com::Utf8Str &aName); + HRESULT setName(const com::Utf8Str &aName); + HRESULT getDescription(com::Utf8Str &aDescription); + HRESULT setDescription(const com::Utf8Str &aDescription); + HRESULT getTimeStamp(LONG64 *aTimeStamp); + HRESULT getOnline(BOOL *aOnline); + HRESULT getMachine(ComPtr<IMachine> &aMachine); + HRESULT getParent(ComPtr<ISnapshot> &aParent); + HRESULT getChildren(std::vector<ComPtr<ISnapshot> > &aChildren); + + // wrapped ISnapshot methods + HRESULT getChildrenCount(ULONG *aChildrenCount); + + Data *m; +}; + +#endif /* !MAIN_INCLUDED_SnapshotImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/StorageControllerImpl.h b/src/VBox/Main/include/StorageControllerImpl.h new file mode 100644 index 00000000..8ff7611f --- /dev/null +++ b/src/VBox/Main/include/StorageControllerImpl.h @@ -0,0 +1,107 @@ +/* $Id: StorageControllerImpl.h $ */ + +/** @file + * + * VBox StorageController COM Class declaration. + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_StorageControllerImpl_h +#define MAIN_INCLUDED_StorageControllerImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif +#include "StorageControllerWrap.h" + +class ATL_NO_VTABLE StorageController : + public StorageControllerWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(StorageController) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent, + const com::Utf8Str &aName, + StorageBus_T aBus, + ULONG aInstance, + bool fBootable); + HRESULT init(Machine *aParent, + StorageController *aThat, + bool aReshare = false); + HRESULT initCopy(Machine *aParent, + StorageController *aThat); + void uninit(); + + // public methods only for internal purposes + const Utf8Str &i_getName() const; + StorageControllerType_T i_getControllerType() const; + StorageBus_T i_getStorageBus() const; + ULONG i_getInstance() const; + bool i_getBootable() const; + HRESULT i_checkPortAndDeviceValid(LONG aControllerPort, + LONG aDevice); + void i_setBootable(BOOL fBootable); + void i_rollback(); + void i_commit(); + + // public methods for internal purposes only + // (ensure there is a caller and a read lock before calling them!) + + void i_unshare(); + + /** @note this doesn't require a read lock since mParent is constant. */ + Machine* i_getMachine(); + ComObjPtr<StorageController> i_getPeer(); + +private: + + // Wrapped IStorageController properties + HRESULT getName(com::Utf8Str &aName); + HRESULT setName(const com::Utf8Str &aName); + HRESULT getMaxDevicesPerPortCount(ULONG *aMaxDevicesPerPortCount); + HRESULT getMinPortCount(ULONG *aMinPortCount); + HRESULT getMaxPortCount(ULONG *aMaxPortCount); + HRESULT getInstance(ULONG *aInstance); + HRESULT setInstance(ULONG aInstance); + HRESULT getPortCount(ULONG *aPortCount); + HRESULT setPortCount(ULONG aPortCount); + HRESULT getBus(StorageBus_T *aBus); + HRESULT getControllerType(StorageControllerType_T *aControllerType); + HRESULT setControllerType(StorageControllerType_T aControllerType); + HRESULT getUseHostIOCache(BOOL *aUseHostIOCache); + HRESULT setUseHostIOCache(BOOL aUseHostIOCache); + HRESULT getBootable(BOOL *aBootable); + + void i_printList(); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_StorageControllerImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/SystemPropertiesImpl.h b/src/VBox/Main/include/SystemPropertiesImpl.h new file mode 100644 index 00000000..90fe0e65 --- /dev/null +++ b/src/VBox/Main/include/SystemPropertiesImpl.h @@ -0,0 +1,220 @@ +/* $Id: SystemPropertiesImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_SystemPropertiesImpl_h +#define MAIN_INCLUDED_SystemPropertiesImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "MediumFormatImpl.h" +#include "SystemPropertiesWrap.h" + +class CPUProfile; + +namespace settings +{ + struct SystemProperties; +} + +class ATL_NO_VTABLE SystemProperties : + public SystemPropertiesWrap +{ +public: + typedef std::list<ComObjPtr<MediumFormat> > MediumFormatList; + typedef std::list<ComObjPtr<CPUProfile> > CPUProfileList_T; + + DECLARE_COMMON_CLASS_METHODS(SystemProperties) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(VirtualBox *aParent); + void uninit(); + + // public methods for internal purposes only + // (ensure there is a caller and a read lock before calling them!) + HRESULT i_loadSettings(const settings::SystemProperties &data); + HRESULT i_saveSettings(settings::SystemProperties &data); + + ComObjPtr<MediumFormat> i_mediumFormat(const Utf8Str &aFormat); + ComObjPtr<MediumFormat> i_mediumFormatFromExtension(const Utf8Str &aExt); + + int i_loadVDPlugin(const char *pszPluginLibrary); + int i_unloadVDPlugin(const char *pszPluginLibrary); + + HRESULT i_getDefaultAdditionsISO(com::Utf8Str &aDefaultAdditionsISO); + +private: + + // wrapped ISystemProperties properties + HRESULT getMinGuestRAM(ULONG *aMinGuestRAM) RT_OVERRIDE; + HRESULT getMaxGuestRAM(ULONG *aMaxGuestRAM) RT_OVERRIDE; + HRESULT getMinGuestVRAM(ULONG *aMinGuestVRAM) RT_OVERRIDE; + HRESULT getMaxGuestVRAM(ULONG *aMaxGuestVRAM) RT_OVERRIDE; + HRESULT getMinGuestCPUCount(ULONG *aMinGuestCPUCount) RT_OVERRIDE; + HRESULT getMaxGuestCPUCount(ULONG *aMaxGuestCPUCount) RT_OVERRIDE; + HRESULT getMaxGuestMonitors(ULONG *aMaxGuestMonitors) RT_OVERRIDE; + HRESULT getInfoVDSize(LONG64 *aInfoVDSize) RT_OVERRIDE; + HRESULT getSerialPortCount(ULONG *aSerialPortCount) RT_OVERRIDE; + HRESULT getParallelPortCount(ULONG *aParallelPortCount) RT_OVERRIDE; + HRESULT getMaxBootPosition(ULONG *aMaxBootPosition) RT_OVERRIDE; + HRESULT getRawModeSupported(BOOL *aRawModeSupported) RT_OVERRIDE; + HRESULT getExclusiveHwVirt(BOOL *aExclusiveHwVirt) RT_OVERRIDE; + HRESULT setExclusiveHwVirt(BOOL aExclusiveHwVirt) RT_OVERRIDE; + HRESULT getDefaultMachineFolder(com::Utf8Str &aDefaultMachineFolder) RT_OVERRIDE; + HRESULT setDefaultMachineFolder(const com::Utf8Str &aDefaultMachineFolder) RT_OVERRIDE; + HRESULT getLoggingLevel(com::Utf8Str &aLoggingLevel) RT_OVERRIDE; + HRESULT setLoggingLevel(const com::Utf8Str &aLoggingLevel) RT_OVERRIDE; + HRESULT getMediumFormats(std::vector<ComPtr<IMediumFormat> > &aMediumFormats) RT_OVERRIDE; + HRESULT getDefaultHardDiskFormat(com::Utf8Str &aDefaultHardDiskFormat) RT_OVERRIDE; + HRESULT setDefaultHardDiskFormat(const com::Utf8Str &aDefaultHardDiskFormat) RT_OVERRIDE; + HRESULT getFreeDiskSpaceWarning(LONG64 *aFreeDiskSpaceWarning) RT_OVERRIDE; + HRESULT setFreeDiskSpaceWarning(LONG64 aFreeDiskSpaceWarning) RT_OVERRIDE; + HRESULT getFreeDiskSpacePercentWarning(ULONG *aFreeDiskSpacePercentWarning) RT_OVERRIDE; + HRESULT setFreeDiskSpacePercentWarning(ULONG aFreeDiskSpacePercentWarning) RT_OVERRIDE; + HRESULT getFreeDiskSpaceError(LONG64 *aFreeDiskSpaceError) RT_OVERRIDE; + HRESULT setFreeDiskSpaceError(LONG64 aFreeDiskSpaceError) RT_OVERRIDE; + HRESULT getFreeDiskSpacePercentError(ULONG *aFreeDiskSpacePercentError) RT_OVERRIDE; + HRESULT setFreeDiskSpacePercentError(ULONG aFreeDiskSpacePercentError) RT_OVERRIDE; + HRESULT getVRDEAuthLibrary(com::Utf8Str &aVRDEAuthLibrary) RT_OVERRIDE; + HRESULT setVRDEAuthLibrary(const com::Utf8Str &aVRDEAuthLibrary) RT_OVERRIDE; + HRESULT getWebServiceAuthLibrary(com::Utf8Str &aWebServiceAuthLibrary) RT_OVERRIDE; + HRESULT setWebServiceAuthLibrary(const com::Utf8Str &aWebServiceAuthLibrary) RT_OVERRIDE; + HRESULT getDefaultVRDEExtPack(com::Utf8Str &aDefaultVRDEExtPack) RT_OVERRIDE; + HRESULT setDefaultVRDEExtPack(const com::Utf8Str &aDefaultVRDEExtPack) RT_OVERRIDE; + HRESULT getDefaultCryptoExtPack(com::Utf8Str &aDefaultCryptoExtPack) RT_OVERRIDE; + HRESULT setDefaultCryptoExtPack(const com::Utf8Str &aDefaultCryptoExtPack) RT_OVERRIDE; + HRESULT getLogHistoryCount(ULONG *aLogHistoryCount) RT_OVERRIDE; + HRESULT setLogHistoryCount(ULONG aLogHistoryCount) RT_OVERRIDE; + HRESULT getDefaultAudioDriver(AudioDriverType_T *aDefaultAudioDriver) RT_OVERRIDE; + HRESULT getAutostartDatabasePath(com::Utf8Str &aAutostartDatabasePath) RT_OVERRIDE; + HRESULT setAutostartDatabasePath(const com::Utf8Str &aAutostartDatabasePath) RT_OVERRIDE; + HRESULT getDefaultAdditionsISO(com::Utf8Str &aDefaultAdditionsISO) RT_OVERRIDE; + HRESULT setDefaultAdditionsISO(const com::Utf8Str &aDefaultAdditionsISO) RT_OVERRIDE; + HRESULT getDefaultFrontend(com::Utf8Str &aDefaultFrontend) RT_OVERRIDE; + HRESULT setDefaultFrontend(const com::Utf8Str &aDefaultFrontend) RT_OVERRIDE; + HRESULT getScreenShotFormats(std::vector<BitmapFormat_T> &aScreenShotFormats) RT_OVERRIDE; + HRESULT getProxyMode(ProxyMode_T *pProxyMode) RT_OVERRIDE; + HRESULT setProxyMode(ProxyMode_T aProxyMode) RT_OVERRIDE; + HRESULT getProxyURL(com::Utf8Str &aProxyURL) RT_OVERRIDE; + HRESULT setProxyURL(const com::Utf8Str &aProxyURL) RT_OVERRIDE; + HRESULT getSupportedParavirtProviders(std::vector<ParavirtProvider_T> &aSupportedParavirtProviders) RT_OVERRIDE; + HRESULT getSupportedClipboardModes(std::vector<ClipboardMode_T> &aSupportedClipboardModes) RT_OVERRIDE; + HRESULT getSupportedDnDModes(std::vector<DnDMode_T> &aSupportedDnDModes) RT_OVERRIDE; + HRESULT getSupportedFirmwareTypes(std::vector<FirmwareType_T> &aSupportedFirmwareTypes) RT_OVERRIDE; + HRESULT getSupportedPointingHIDTypes(std::vector<PointingHIDType_T> &aSupportedPointingHIDTypes) RT_OVERRIDE; + HRESULT getSupportedKeyboardHIDTypes(std::vector<KeyboardHIDType_T> &aSupportedKeyboardHIDTypes) RT_OVERRIDE; + HRESULT getSupportedVFSTypes(std::vector<VFSType_T> &aSupportedVFSTypes) RT_OVERRIDE; + HRESULT getSupportedImportOptions(std::vector<ImportOptions_T> &aSupportedImportOptions) RT_OVERRIDE; + HRESULT getSupportedExportOptions(std::vector<ExportOptions_T> &aSupportedExportOptions) RT_OVERRIDE; + HRESULT getSupportedRecordingFeatures(std::vector<RecordingFeature_T> &aSupportedRecordingFeatures) RT_OVERRIDE; + HRESULT getSupportedRecordingAudioCodecs(std::vector<RecordingAudioCodec_T> &aSupportedRecordingAudioCodecs) RT_OVERRIDE; + HRESULT getSupportedRecordingVideoCodecs(std::vector<RecordingVideoCodec_T> &aSupportedRecordingVideoCodecs) RT_OVERRIDE; + HRESULT getSupportedRecordingVSModes(std::vector<RecordingVideoScalingMode_T> &aSupportedRecordingVideoScalingModes) RT_OVERRIDE; + HRESULT getSupportedRecordingARCModes(std::vector<RecordingRateControlMode_T> &aSupportedRecordingAudioRateControlModes) RT_OVERRIDE; + HRESULT getSupportedRecordingVRCModes(std::vector<RecordingRateControlMode_T> &aSupportedRecordingVideoRateControlModes) RT_OVERRIDE; + HRESULT getSupportedGraphicsControllerTypes(std::vector<GraphicsControllerType_T> &aSupportedGraphicsControllerTypes) RT_OVERRIDE; + HRESULT getSupportedCloneOptions(std::vector<CloneOptions_T> &aSupportedCloneOptions) RT_OVERRIDE; + HRESULT getSupportedAutostopTypes(std::vector<AutostopType_T> &aSupportedAutostopTypes) RT_OVERRIDE; + HRESULT getSupportedVMProcPriorities(std::vector<VMProcPriority_T> &aSupportedVMProcPriorities) RT_OVERRIDE; + HRESULT getSupportedNetworkAttachmentTypes(std::vector<NetworkAttachmentType_T> &aSupportedNetworkAttachmentTypes) RT_OVERRIDE; + HRESULT getSupportedNetworkAdapterTypes(std::vector<NetworkAdapterType_T> &aSupportedNetworkAdapterTypes) RT_OVERRIDE; + HRESULT getSupportedPortModes(std::vector<PortMode_T> &aSupportedPortModes) RT_OVERRIDE; + HRESULT getSupportedUartTypes(std::vector<UartType_T> &aSupportedUartTypes) RT_OVERRIDE; + HRESULT getSupportedUSBControllerTypes(std::vector<USBControllerType_T> &aSupportedUSBControllerTypes) RT_OVERRIDE; + HRESULT getSupportedAudioDriverTypes(std::vector<AudioDriverType_T> &aSupportedAudioDriverTypes) RT_OVERRIDE; + HRESULT getSupportedAudioControllerTypes(std::vector<AudioControllerType_T> &aSupportedAudioControllerTypes) RT_OVERRIDE; + HRESULT getSupportedStorageBuses(std::vector<StorageBus_T> &aSupportedStorageBuses) RT_OVERRIDE; + HRESULT getSupportedStorageControllerTypes(std::vector<StorageControllerType_T> &aSupportedStorageControllerTypes) RT_OVERRIDE; + HRESULT getSupportedChipsetTypes(std::vector<ChipsetType_T> &aSupportedChipsetTypes) RT_OVERRIDE; + HRESULT getSupportedIommuTypes(std::vector<IommuType_T> &aSupportedIommuTypes) RT_OVERRIDE; + HRESULT getSupportedTpmTypes(std::vector<TpmType_T> &aSupportedTpmTypes) RT_OVERRIDE; + HRESULT getLanguageId(com::Utf8Str &aLanguageId) RT_OVERRIDE; + HRESULT setLanguageId(const com::Utf8Str &aLanguageId) RT_OVERRIDE; + + // wrapped ISystemProperties methods + HRESULT getMaxNetworkAdapters(ChipsetType_T aChipset, + ULONG *aMaxNetworkAdapters) RT_OVERRIDE; + HRESULT getMaxNetworkAdaptersOfType(ChipsetType_T aChipset, + NetworkAttachmentType_T aType, + ULONG *aMaxNetworkAdapters) RT_OVERRIDE; + HRESULT getMaxDevicesPerPortForStorageBus(StorageBus_T aBus, + ULONG *aMaxDevicesPerPort) RT_OVERRIDE; + HRESULT getMinPortCountForStorageBus(StorageBus_T aBus, + ULONG *aMinPortCount) RT_OVERRIDE; + HRESULT getMaxPortCountForStorageBus(StorageBus_T aBus, + ULONG *aMaxPortCount) RT_OVERRIDE; + HRESULT getMaxInstancesOfStorageBus(ChipsetType_T aChipset, + StorageBus_T aBus, + ULONG *aMaxInstances) RT_OVERRIDE; + HRESULT getDeviceTypesForStorageBus(StorageBus_T aBus, + std::vector<DeviceType_T> &aDeviceTypes) RT_OVERRIDE; + HRESULT getStorageBusForStorageControllerType(StorageControllerType_T aStorageControllerType, + StorageBus_T *aStorageBus) RT_OVERRIDE; + HRESULT getStorageControllerTypesForStorageBus(StorageBus_T aStorageBus, + std::vector<StorageControllerType_T> &aStorageControllerTypes) RT_OVERRIDE; + HRESULT getDefaultIoCacheSettingForStorageController(StorageControllerType_T aControllerType, + BOOL *aEnabled) RT_OVERRIDE; + HRESULT getStorageControllerHotplugCapable(StorageControllerType_T aControllerType, + BOOL *aHotplugCapable) RT_OVERRIDE; + HRESULT getMaxInstancesOfUSBControllerType(ChipsetType_T aChipset, + USBControllerType_T aType, + ULONG *aMaxInstances) RT_OVERRIDE; + HRESULT getCPUProfiles(CPUArchitecture_T aArchitecture, const com::Utf8Str &aNamePattern, + std::vector<ComPtr<ICPUProfile> > &aProfiles) RT_OVERRIDE; + + HRESULT i_getUserHomeDirectory(Utf8Str &strPath); + HRESULT i_setDefaultMachineFolder(const Utf8Str &strPath); + HRESULT i_setLoggingLevel(const com::Utf8Str &aLoggingLevel); + HRESULT i_setDefaultHardDiskFormat(const com::Utf8Str &aFormat); + HRESULT i_setVRDEAuthLibrary(const com::Utf8Str &aPath); + + HRESULT i_setWebServiceAuthLibrary(const com::Utf8Str &aPath); + HRESULT i_setDefaultVRDEExtPack(const com::Utf8Str &aExtPack); + HRESULT i_setDefaultCryptoExtPack(const com::Utf8Str &aExtPack); + HRESULT i_setAutostartDatabasePath(const com::Utf8Str &aPath); + HRESULT i_setDefaultAdditionsISO(const com::Utf8Str &aPath); + HRESULT i_setDefaultFrontend(const com::Utf8Str &aDefaultFrontend); + + VirtualBox * const mParent; + + settings::SystemProperties *m; + + MediumFormatList m_llMediumFormats; + + bool m_fLoadedX86CPUProfiles; /**< Set if we've loaded the x86 and AMD64 CPU profiles. */ + CPUProfileList_T m_llCPUProfiles; /**< List of loaded CPU profiles. */ + + friend class VirtualBox; +}; + +#endif /* !MAIN_INCLUDED_SystemPropertiesImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/TextScript.h b/src/VBox/Main/include/TextScript.h new file mode 100644 index 00000000..21284df5 --- /dev/null +++ b/src/VBox/Main/include/TextScript.h @@ -0,0 +1,251 @@ +/* $Id: TextScript.h $ */ +/** @file + * Classes for reading/parsing/saving text scripts (unattended installation, ++). + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_TextScript_h +#define MAIN_INCLUDED_TextScript_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxBase.h" +#include <iprt/cpp/utils.h> +#include <vector> + + +/** + * Base class for all the script readers/editors. + * + * @todo get rid of this silly bugger. + */ +class AbstractScript + : public RTCNonCopyable +{ +protected: + /** For setting errors. + * Yeah, class isn't entirely abstract now. */ + VirtualBoxBase *mpSetError; + +private: /* no default constructors for children. */ + AbstractScript() {} + +public: + DECLARE_TRANSLATE_METHODS(AbstractScript) + + AbstractScript(VirtualBoxBase *pSetError) : mpSetError(pSetError) {} + virtual ~AbstractScript() {} + + /** + * Read a script from a file + */ + virtual HRESULT read(const Utf8Str &rStrFilename) = 0; + + /** + * Read a script from a VFS file handle. + */ + virtual HRESULT readFromHandle(RTVFSFILE hVfsFile, const char *pszFilename) = 0; + + /** + * Parse the script + */ + virtual HRESULT parse() = 0; + + /** + * Save a script to a string. + * + * This is used by save() and later others to deloy the script. + */ + virtual HRESULT saveToString(Utf8Str &rStrDst) = 0; + + /** + * Save a script to a file. + * @param rStrPath Where to save the script. This normally points to a + * file, but in a number of child use cases it's + * actually giving a directory to put the script in + * using the default deloyment filename. One day we + * might make the caller do this path joining. + * @param fOverwrite Whether to overwrite the file or not. + */ + virtual HRESULT save(const Utf8Str &rStrPath, bool fOverwrite) = 0; + + /** + * Path where an actual script with user's data is located + */ + virtual const Utf8Str &getActualScriptPath() const = 0; +}; + +/** + * Base class for text based script readers/editors. + * + * This deals with reading the file into a string data member, writing it back + * out to a file, and remember the filenames. + */ +class BaseTextScript : public AbstractScript +{ +protected: + const char * const mpszDefaultTemplateFilename; /**< The default template filename. Can be empty. */ + const char * const mpszDefaultFilename; /**< Filename to use when someone calls save() with a directory path. Can be NULL. */ + RTCString mStrScriptFullContent; /**< Raw text file content. Produced by read() and typically only used by parse(). */ + Utf8Str mStrOriginalPath; /**< Path where an original script is located (set by read()). */ + Utf8Str mStrSavedPath; /**< Path where an saved script with user's data is located (set by save()). */ + +public: + DECLARE_TRANSLATE_METHODS(BaseTextScript) + + BaseTextScript(VirtualBoxBase *pSetError, const char *pszDefaultTemplateFilename, const char *pszDefaultFilename) + : AbstractScript(pSetError) + , mpszDefaultTemplateFilename(pszDefaultTemplateFilename) + , mpszDefaultFilename(pszDefaultFilename) + { } + virtual ~BaseTextScript() {} + + HRESULT read(const Utf8Str &rStrFilename); + HRESULT readFromHandle(RTVFSFILE hVfsFile, const char *pszFilename); + HRESULT save(const Utf8Str &rStrFilename, bool fOverwrite); + + /** + * Gets the default filename for this class of scripts (empty if none). + * + * @note Just the filename, no path. + */ + const char *getDefaultFilename() const + { + return mpszDefaultFilename; + } + + /** + * Gets the default template filename for this class of scripts (empty if none). + * + * @note Just the filename, no path. + */ + const char *getDefaultTemplateFilename() const + { + return mpszDefaultTemplateFilename; + } + + /** + * Path to the file we last saved the script as. + */ + const Utf8Str &getActualScriptPath() const + { + return mStrSavedPath; + } + + /** + * Path where an original script is located + */ + const Utf8Str &getOriginalScriptPath() const + { + return mStrOriginalPath; + } +}; + + +/** + * Generic line based text script editor. + * + * This is used for editing isolinux configuratin files among other things. + */ +class GeneralTextScript : public BaseTextScript +{ +protected: + RTCList<RTCString> mScriptContentByLines; /**< Content index by line. This contains the edited version. */ + bool mfDataParsed; /**< Indicates whether the script has been parse() yet. */ + +public: + DECLARE_TRANSLATE_METHODS(GeneralTextScript) + + GeneralTextScript(VirtualBoxBase *pSetError, const char *pszDefaultTemplateFilename = NULL, const char *pszDefaultFilename = NULL) + : BaseTextScript(pSetError, pszDefaultTemplateFilename, pszDefaultFilename), mfDataParsed(false) + {} + virtual ~GeneralTextScript() {} + + HRESULT parse(); + HRESULT saveToString(Utf8Str &rStrDst); + + //////////////////New functions////////////////////////////// + + bool isDataParsed() const + { + return mfDataParsed; + } + + /** + * Returns the actual size of script in lines + */ + size_t getLineNumbersOfScript() const + { + return mScriptContentByLines.size(); + } + + /** + * Gets a read-only reference to the given line, returning Utf8Str::Empty if + * idxLine is out of range. + * + * @returns Line string reference or Utf8Str::Empty. + * @param idxLine The line number. + * + * @todo RTCList doesn't allow this method to be const. + */ + RTCString const &getContentOfLine(size_t idxLine); + + /** + * Set new content of line + */ + HRESULT setContentOfLine(size_t idxLine, const Utf8Str &newContent); + + /** + * Find a substring in the script + * Returns a list with the found lines + * @throws std::bad_alloc + */ + std::vector<size_t> findTemplate(const Utf8Str &rStrNeedle, RTCString::CaseSensitivity enmCase = RTCString::CaseSensitive); + + /** + * In line @a idxLine replace the first occurence of @a rStrNeedle with + * @a rStrRelacement. + */ + HRESULT findAndReplace(size_t idxLine, const Utf8Str &rStrNeedle, const Utf8Str &rStrReplacement); + + /** + * Append a string into the end of the given line. + */ + HRESULT appendToLine(size_t idxLine, const Utf8Str &rStrToAppend); + + /** + * Prepend a string in the beginning of the given line. + */ + HRESULT prependToLine(size_t idxLine, const Utf8Str &rStrToPrepend); + + /** + * Append a new line at the end of the list of line. + */ + HRESULT appendLine(const Utf8Str &rStrLineToAppend); + //////////////////New functions////////////////////////////// +}; + + +#endif /* !MAIN_INCLUDED_TextScript_h */ diff --git a/src/VBox/Main/include/ThreadTask.h b/src/VBox/Main/include/ThreadTask.h new file mode 100644 index 00000000..c743e2cc --- /dev/null +++ b/src/VBox/Main/include/ThreadTask.h @@ -0,0 +1,78 @@ +/** @file + * VirtualBox ThreadTask class definition + */ + +/* + * Copyright (C) 2015-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ThreadTask_h +#define MAIN_INCLUDED_ThreadTask_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VBox/com/string.h" + +/** + * The class ThreadVoidData is used as a base class for any data which we want to pass into a thread + */ +struct ThreadVoidData +{ +public: + ThreadVoidData() { } + virtual ~ThreadVoidData() { } +}; + + +class ThreadTask +{ +public: + ThreadTask(const Utf8Str &t) + : m_strTaskName(t) + , mAsync(false) + { } + + virtual ~ThreadTask() + { } + + HRESULT createThread(void); + HRESULT createThreadWithType(RTTHREADTYPE enmType); + + inline Utf8Str getTaskName() const { return m_strTaskName; } + bool isAsync() { return mAsync; } + +protected: + HRESULT createThreadInternal(RTTHREADTYPE enmType); + static DECLCALLBACK(int) taskHandlerThreadProc(RTTHREAD thread, void *pvUser); + + ThreadTask() : m_strTaskName("GenericTask") + { } + + Utf8Str m_strTaskName; + bool mAsync; + +private: + virtual void handler() = 0; +}; + +#endif /* !MAIN_INCLUDED_ThreadTask_h */ + diff --git a/src/VBox/Main/include/TokenImpl.h b/src/VBox/Main/include/TokenImpl.h new file mode 100644 index 00000000..433f835f --- /dev/null +++ b/src/VBox/Main/include/TokenImpl.h @@ -0,0 +1,118 @@ +/* $Id: TokenImpl.h $ */ +/** @file + * Token COM class implementations - MachineToken and MediumLockToken + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_TokenImpl_h +#define MAIN_INCLUDED_TokenImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "TokenWrap.h" +#include "MachineImpl.h" + + +/** + * The MachineToken class automates cleanup of a SessionMachine object. + */ +class ATL_NO_VTABLE MachineToken : + public TokenWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(MachineToken) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(const ComObjPtr<SessionMachine> &pSessionMachine); + void uninit(bool fAbandon); + +private: + + // wrapped IToken methods + HRESULT abandon(AutoCaller &aAutoCaller); + HRESULT dummy(); + + // data + struct Data + { + Data() + { + } + + ComObjPtr<SessionMachine> pSessionMachine; + }; + + Data m; +}; + + +class Medium; + +/** + * The MediumLockToken class automates cleanup of a Medium lock. + */ +class ATL_NO_VTABLE MediumLockToken : + public TokenWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(MediumLockToken) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(const ComObjPtr<Medium> &pMedium, bool fWrite); + void uninit(); + +private: + + // wrapped IToken methods + HRESULT abandon(AutoCaller &aAutoCaller); + HRESULT dummy(); + + // data + struct Data + { + Data() : + fWrite(false) + { + } + + ComObjPtr<Medium> pMedium; + bool fWrite; + }; + + Data m; +}; + + +#endif /* !MAIN_INCLUDED_TokenImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/TrustAnchorsAndCerts.h b/src/VBox/Main/include/TrustAnchorsAndCerts.h new file mode 100644 index 00000000..120807d0 --- /dev/null +++ b/src/VBox/Main/include/TrustAnchorsAndCerts.h @@ -0,0 +1,53 @@ +/* $Id: TrustAnchorsAndCerts.h $ */ +/** @file + * Main - Collection of trust anchors and certificates included in VBoxSVC. + */ + +/* + * Copyright (C) 2021-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_TrustAnchorsAndCerts_h +#define MAIN_INCLUDED_TrustAnchorsAndCerts_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/cdefs.h> + +RT_C_DECLS_BEGIN + +extern const unsigned char g_abUefiMicrosoftKek[]; +extern const unsigned g_cbUefiMicrosoftKek; + +extern const unsigned char g_abUefiMicrosoftCa[]; +extern const unsigned g_cbUefiMicrosoftCa; + +extern const unsigned char g_abUefiMicrosoftProPca[]; +extern const unsigned g_cbUefiMicrosoftProPca; + +extern const unsigned char g_abUefiOracleDefPk[]; +extern const unsigned g_cbUefiOracleDefPk; + +RT_C_DECLS_END + +#endif /* !MAIN_INCLUDED_TrustAnchorsAndCerts_h */ + diff --git a/src/VBox/Main/include/TrustedPlatformModuleImpl.h b/src/VBox/Main/include/TrustedPlatformModuleImpl.h new file mode 100644 index 00000000..af359a84 --- /dev/null +++ b/src/VBox/Main/include/TrustedPlatformModuleImpl.h @@ -0,0 +1,84 @@ +/* $Id: TrustedPlatformModuleImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation - Machine Trusted Platform Module settings. + */ + +/* + * Copyright (C) 2021-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_TrustedPlatformModuleImpl_h +#define MAIN_INCLUDED_TrustedPlatformModuleImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "TrustedPlatformModuleWrap.h" + +class GuestOSType; + +namespace settings +{ + struct TpmSettings; +} + +class ATL_NO_VTABLE TrustedPlatformModule : + public TrustedPlatformModuleWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(TrustedPlatformModule) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *parent); + HRESULT init(Machine *parent, TrustedPlatformModule *that); + HRESULT initCopy(Machine *parent, TrustedPlatformModule *that); + void uninit(); + + // public methods for internal purposes only + HRESULT i_loadSettings(const settings::TpmSettings &data); + HRESULT i_saveSettings(settings::TpmSettings &data); + + void i_rollback(); + void i_commit(); + void i_copyFrom(TrustedPlatformModule *aThat); + void i_applyDefaults(GuestOSType *aOsType); + +private: + + // wrapped ITrustedPlatformModule properties + HRESULT getType(TpmType_T *aType); + HRESULT setType(TpmType_T aType); + HRESULT getLocation(com::Utf8Str &location); + HRESULT setLocation(const com::Utf8Str &location); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_TrustedPlatformModuleImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/USBControllerImpl.h b/src/VBox/Main/include/USBControllerImpl.h new file mode 100644 index 00000000..16f15688 --- /dev/null +++ b/src/VBox/Main/include/USBControllerImpl.h @@ -0,0 +1,88 @@ +/* $Id: USBControllerImpl.h $ */ + +/** @file + * + * VBox USBController COM Class declaration. + */ + +/* + * Copyright (C) 2005-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_USBControllerImpl_h +#define MAIN_INCLUDED_USBControllerImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "USBControllerWrap.h" + +class HostUSBDevice; +class USBDeviceFilter; + +namespace settings +{ + struct USBController; +} + +class ATL_NO_VTABLE USBController : + public USBControllerWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(USBController) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent, const com::Utf8Str &aName, USBControllerType_T enmType); + HRESULT init(Machine *aParent, USBController *aThat, bool fReshare = false); + HRESULT initCopy(Machine *aParent, USBController *aThat); + void uninit(); + + // public methods only for internal purposes + void i_rollback(); + void i_commit(); + void i_copyFrom(USBController *aThat); + void i_unshare(); + + ComObjPtr<USBController> i_getPeer(); + const Utf8Str &i_getName() const; + const USBControllerType_T &i_getControllerType() const; + +private: + + // wrapped IUSBController properties + HRESULT getName(com::Utf8Str &aName); + HRESULT setName(const com::Utf8Str &aName); + HRESULT getType(USBControllerType_T *aType); + HRESULT setType(USBControllerType_T aType); + HRESULT getUSBStandard(USHORT *aUSBStandard); + + void printList(); + + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_USBControllerImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/USBDeviceFilterImpl.h b/src/VBox/Main/include/USBDeviceFilterImpl.h new file mode 100644 index 00000000..69c13116 --- /dev/null +++ b/src/VBox/Main/include/USBDeviceFilterImpl.h @@ -0,0 +1,240 @@ +/* $Id: USBDeviceFilterImpl.h $ */ +/** @file + * Declaration of USBDeviceFilter and HostUSBDeviceFilter. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_USBDeviceFilterImpl_h +#define MAIN_INCLUDED_USBDeviceFilterImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/settings.h> +#include "Matching.h" +#include <VBox/usbfilter.h> +#include "USBDeviceFilterWrap.h" + +class USBDeviceFilters; +class Host; +namespace settings +{ + struct USBDeviceFilter; +} + +// USBDeviceFilter +//////////////////////////////////////////////////////////////////////////////// + +class ATL_NO_VTABLE USBDeviceFilter : + public USBDeviceFilterWrap +{ +public: + + struct BackupableUSBDeviceFilterData + { + typedef matching::Matchable <matching::ParsedBoolFilter> BOOLFilter; + + BackupableUSBDeviceFilterData() : mId (NULL) {} + BackupableUSBDeviceFilterData(const BackupableUSBDeviceFilterData &aThat) : + mRemote(aThat.mRemote), mId(aThat.mId) + { + mData.strName = aThat.mData.strName; + mData.fActive = aThat.mData.fActive; + mData.ulMaskedInterfaces = aThat.mData.ulMaskedInterfaces; + USBFilterClone(&mUSBFilter, &aThat.mUSBFilter); + } + + /** Remote or local matching criterion. */ + BOOLFilter mRemote; + + /** The filter data blob. */ + USBFILTER mUSBFilter; + + /** Arbitrary ID field (not used by the class itself) */ + void *mId; + + settings::USBDeviceFilter mData; + }; + + DECLARE_COMMON_CLASS_METHODS(USBDeviceFilter) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(USBDeviceFilters *aParent, + const settings::USBDeviceFilter &data); + HRESULT init(USBDeviceFilters *aParent, IN_BSTR aName); + HRESULT init(USBDeviceFilters *aParent, USBDeviceFilter *aThat, + bool aReshare = false); + HRESULT initCopy(USBDeviceFilters *aParent, USBDeviceFilter *aThat); + void uninit(); + + // public methods only for internal purposes + bool i_isModified(); + void i_rollback(); + void i_commit(); + + void unshare(); + + // public methods for internal purposes only + // (ensure there is a caller and a read lock before calling them!) + void *& i_getId() { return bd->mId; } + const BackupableUSBDeviceFilterData& i_getData() { return *bd.data(); } + ComObjPtr<USBDeviceFilter> i_peer() { return mPeer; } + + // tr() wants to belong to a class it seems, thus this one here. + static HRESULT i_usbFilterFieldFromString(PUSBFILTER aFilter, + USBFILTERIDX aIdx, + const Utf8Str &aValue, + Utf8Str &aErrStr); + + static const char* i_describeUSBFilterIdx(USBFILTERIDX aIdx); + +private: + + // wrapped IUSBDeviceFilter properties + HRESULT getName(com::Utf8Str &aName); + HRESULT setName(const com::Utf8Str &aName); + HRESULT getActive(BOOL *aActive); + HRESULT setActive(BOOL aActive); + HRESULT getVendorId(com::Utf8Str &aVendorId); + HRESULT setVendorId(const com::Utf8Str &aVendorId); + HRESULT getProductId(com::Utf8Str &aProductId); + HRESULT setProductId(const com::Utf8Str &aProductId); + HRESULT getRevision(com::Utf8Str &aRevision); + HRESULT setRevision(const com::Utf8Str &aRevision); + HRESULT getManufacturer(com::Utf8Str &aManufacturer); + HRESULT setManufacturer(const com::Utf8Str &aManufacturer); + HRESULT getProduct(com::Utf8Str &aProduct); + HRESULT setProduct(const com::Utf8Str &aProduct); + HRESULT getSerialNumber(com::Utf8Str &aSerialNumber); + HRESULT setSerialNumber(const com::Utf8Str &aSerialNumber); + HRESULT getPort(com::Utf8Str &aPort); + HRESULT setPort(const com::Utf8Str &aPort); + HRESULT getRemote(com::Utf8Str &aRemote); + HRESULT setRemote(const com::Utf8Str &aRemote); + HRESULT getMaskedInterfaces(ULONG *aMaskedInterfaces); + HRESULT setMaskedInterfaces(ULONG aMaskedInterfaces); + + // wrapped IUSBDeviceFilter methods + HRESULT i_usbFilterFieldGetter(USBFILTERIDX aIdx, com::Utf8Str &aStr); + HRESULT i_usbFilterFieldSetter(USBFILTERIDX aIdx, const com::Utf8Str &strNew); + + USBDeviceFilters * const mParent; + USBDeviceFilter * const mPeer; + + Backupable<BackupableUSBDeviceFilterData> bd; + + bool m_fModified; + + /** Used externally to indicate this filter is in the list + (not touched by the class itself except that in init()/uninit()) */ + bool mInList; + + friend class USBDeviceFilters; +}; +#include "HostUSBDeviceFilterWrap.h" + +// HostUSBDeviceFilter +//////////////////////////////////////////////////////////////////////////////// + +class ATL_NO_VTABLE HostUSBDeviceFilter : + public HostUSBDeviceFilterWrap +{ +public: + + struct BackupableUSBDeviceFilterData : public USBDeviceFilter::BackupableUSBDeviceFilterData + { + BackupableUSBDeviceFilterData() {} + }; + + DECLARE_COMMON_CLASS_METHODS (HostUSBDeviceFilter) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Host *aParent, + const settings::USBDeviceFilter &data); + HRESULT init(Host *aParent, IN_BSTR aName); + void uninit(); + + // public methods for internal purposes only + // (ensure there is a caller and a read lock before calling them!) + void i_saveSettings(settings::USBDeviceFilter &data); + + void*& i_getId() { return bd.data()->mId; } + + const BackupableUSBDeviceFilterData& i_getData() { return *bd.data(); } + + // util::Lockable interface + RWLockHandle *lockHandle() const; + +private: + + // wrapped IHostUSBDeviceFilter properties + HRESULT getName(com::Utf8Str &aName); + HRESULT setName(const com::Utf8Str &aName); + HRESULT getActive(BOOL *aActive); + HRESULT setActive(BOOL aActive); + HRESULT getVendorId(com::Utf8Str &aVendorId); + HRESULT setVendorId(const com::Utf8Str &aVendorId); + HRESULT getProductId(com::Utf8Str &aProductId); + HRESULT setProductId(const com::Utf8Str &aProductId); + HRESULT getRevision(com::Utf8Str &aRevision); + HRESULT setRevision(const com::Utf8Str &aRevision); + HRESULT getManufacturer(com::Utf8Str &aManufacturer); + HRESULT setManufacturer(const com::Utf8Str &aManufacturer); + HRESULT getProduct(com::Utf8Str &aProduct); + HRESULT setProduct(const com::Utf8Str &aProduct); + HRESULT getSerialNumber(com::Utf8Str &aSerialNumber); + HRESULT setSerialNumber(const com::Utf8Str &aSerialNumber); + HRESULT getPort(com::Utf8Str &aPort); + HRESULT setPort(const com::Utf8Str &aPort); + HRESULT getRemote(com::Utf8Str &aRemote); + HRESULT setRemote(const com::Utf8Str &aRemote); + HRESULT getMaskedInterfaces(ULONG *aMaskedInterfaces); + HRESULT setMaskedInterfaces(ULONG aMaskedInterfaces); + + // wrapped IHostUSBDeviceFilter properties + HRESULT getAction(USBDeviceFilterAction_T *aAction); + HRESULT setAction(USBDeviceFilterAction_T aAction); + + HRESULT i_usbFilterFieldGetter(USBFILTERIDX aIdx, com::Utf8Str &aStr); + HRESULT i_usbFilterFieldSetter(USBFILTERIDX aIdx, const com::Utf8Str &aStr); + + Host * const mParent; + + Backupable<BackupableUSBDeviceFilterData> bd; + + /** Used externally to indicate this filter is in the list + (not touched by the class itself except that in init()/uninit()) */ + bool mInList; + + friend class Host; +}; + +#endif /* !MAIN_INCLUDED_USBDeviceFilterImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/USBDeviceFiltersImpl.h b/src/VBox/Main/include/USBDeviceFiltersImpl.h new file mode 100644 index 00000000..1daf5d53 --- /dev/null +++ b/src/VBox/Main/include/USBDeviceFiltersImpl.h @@ -0,0 +1,97 @@ +/* $Id: USBDeviceFiltersImpl.h $ */ +/** @file + * VBox USBDeviceFilters COM Class declaration. + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_USBDeviceFiltersImpl_h +#define MAIN_INCLUDED_USBDeviceFiltersImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "USBDeviceFiltersWrap.h" + +class HostUSBDevice; +class USBDeviceFilter; + +namespace settings +{ + struct USB; +} + +class ATL_NO_VTABLE USBDeviceFilters : + public USBDeviceFiltersWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(USBDeviceFilters) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent); + HRESULT init(Machine *aParent, USBDeviceFilters *aThat); + HRESULT initCopy(Machine *aParent, USBDeviceFilters *aThat); + void uninit(); + + // public methods only for internal purposes + HRESULT i_loadSettings(const settings::USB &data); + HRESULT i_saveSettings(settings::USB &data); + + void i_rollback(); + void i_commit(); + void i_copyFrom(USBDeviceFilters *aThat); + +#ifdef VBOX_WITH_USB + HRESULT i_onDeviceFilterChange(USBDeviceFilter *aFilter, + BOOL aActiveChanged = FALSE); + bool i_hasMatchingFilter(const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs); + bool i_hasMatchingFilter(IUSBDevice *aUSBDevice, ULONG *aMaskedIfs); + HRESULT i_notifyProxy(bool aInsertFilters); +#endif /* VBOX_WITH_USB */ + + // public methods for internal purposes only + // (ensure there is a caller and a read lock before calling them!) + Machine* i_getMachine(); + +private: + + // Wrapped IUSBDeviceFilters attributes + HRESULT getDeviceFilters(std::vector<ComPtr<IUSBDeviceFilter> > &aDeviceFilters); + + // wrapped IUSBDeviceFilters methods + HRESULT createDeviceFilter(const com::Utf8Str &aName, + ComPtr<IUSBDeviceFilter> &aFilter); + HRESULT insertDeviceFilter(ULONG aPosition, + const ComPtr<IUSBDeviceFilter> &aFilter); + HRESULT removeDeviceFilter(ULONG aPosition, + ComPtr<IUSBDeviceFilter> &aFilter); + struct Data; + Data *m; +}; + +#endif /* !MAIN_INCLUDED_USBDeviceFiltersImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/USBDeviceImpl.h b/src/VBox/Main/include/USBDeviceImpl.h new file mode 100644 index 00000000..d0985239 --- /dev/null +++ b/src/VBox/Main/include/USBDeviceImpl.h @@ -0,0 +1,118 @@ +/* $Id: USBDeviceImpl.h $ */ +/** @file + * Header file for the OUSBDevice (IUSBDevice) class, VBoxC. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_USBDeviceImpl_h +#define MAIN_INCLUDED_USBDeviceImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "USBDeviceWrap.h" + +/** + * Object class used for maintaining devices attached to a USB controller. + * Generally this contains much less information. + */ +class ATL_NO_VTABLE OUSBDevice : + public USBDeviceWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(OUSBDevice) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(IUSBDevice *a_pUSBDevice); + void uninit(); + + // public methods only for internal purposes + const Guid &i_id() const { return mData.id; } + +private: + + // Wrapped IUSBDevice properties + HRESULT getId(com::Guid &aId); + HRESULT getVendorId(USHORT *aVendorId); + HRESULT getProductId(USHORT *aProductId); + HRESULT getRevision(USHORT *aRevision); + HRESULT getManufacturer(com::Utf8Str &aManufacturer); + HRESULT getProduct(com::Utf8Str &aProduct); + HRESULT getSerialNumber(com::Utf8Str &aSerialNumber); + HRESULT getAddress(com::Utf8Str &aAddress); + HRESULT getPort(USHORT *aPort); + HRESULT getPortPath(com::Utf8Str &aPortPath); + HRESULT getVersion(USHORT *aVersion); + HRESULT getSpeed(USBConnectionSpeed_T *aSpeed); + HRESULT getRemote(BOOL *aRemote); + HRESULT getBackend(com::Utf8Str &aBackend); + HRESULT getDeviceInfo(std::vector<com::Utf8Str> &aInfo); + + struct Data + { + Data() : vendorId(0), productId(0), revision(0), port(0), + version(1), speed(USBConnectionSpeed_Null), + remote(FALSE) {} + + /** The UUID of this device. */ + const Guid id; + + /** The vendor id of this USB device. */ + const USHORT vendorId; + /** The product id of this USB device. */ + const USHORT productId; + /** The product revision number of this USB device. + * (high byte = integer; low byte = decimal) */ + const USHORT revision; + /** The Manufacturer string. (Quite possibly NULL.) */ + const com::Utf8Str manufacturer; + /** The Product string. (Quite possibly NULL.) */ + const com::Utf8Str product; + /** The SerialNumber string. (Quite possibly NULL.) */ + const com::Utf8Str serialNumber; + /** The host specific address of the device. */ + const com::Utf8Str address; + /** The device specific backend. */ + const com::Utf8Str backend; + /** The host port number. */ + const USHORT port; + /** The host port path. */ + const com::Utf8Str portPath; + /** The major USB version number of the device. */ + const USHORT version; + /** The speed at which the device is communicating. */ + const USBConnectionSpeed_T speed; + /** Remote (VRDP) or local device. */ + const BOOL remote; + }; + + Data mData; +}; + +#endif /* !MAIN_INCLUDED_USBDeviceImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/USBGetDevices.h b/src/VBox/Main/include/USBGetDevices.h new file mode 100644 index 00000000..39470b7f --- /dev/null +++ b/src/VBox/Main/include/USBGetDevices.h @@ -0,0 +1,114 @@ +/* $Id: USBGetDevices.h $ */ +/** @file + * VirtualBox Linux host USB device enumeration. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_USBGetDevices_h +#define MAIN_INCLUDED_USBGetDevices_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/usb.h> +#include <iprt/mem.h> +#include <iprt/string.h> + +/** + * Free all the members of a USB device created by the Linux enumeration code. + * + * @note This duplicates a USBProxyService method which we needed access too + * without pulling in the rest of the proxy service code. + * + * @param pDevice Pointer to the device. + */ +DECLINLINE(void) deviceFreeMembers(PUSBDEVICE pDevice) +{ + RTStrFree((char *)pDevice->pszManufacturer); + pDevice->pszManufacturer = NULL; + RTStrFree((char *)pDevice->pszProduct); + pDevice->pszProduct = NULL; + RTStrFree((char *)pDevice->pszSerialNumber); + pDevice->pszSerialNumber = NULL; + + RTStrFree((char *)pDevice->pszAddress); + pDevice->pszAddress = NULL; +} + +/** + * Free one USB device created by the Linux enumeration code. + * + * @note This duplicates a USBProxyService method which we needed access too + * without pulling in the rest of the proxy service code. + * + * @param pDevice Pointer to the device. NULL is OK. + */ +DECLINLINE(void) deviceFree(PUSBDEVICE pDevice) +{ + if (pDevice) + { + deviceFreeMembers(pDevice); + RTMemFree(pDevice); + } +} + +/** + * Free a linked list of USB devices created by the Linux enumeration code. + * @param ppHead Pointer to the first device in the linked list + */ +DECLINLINE(void) deviceListFree(PUSBDEVICE *ppHead) +{ + PUSBDEVICE pHead = *ppHead; + while (pHead) + { + PUSBDEVICE pNext = pHead->pNext; + deviceFree(pHead); + pHead = pNext; + } + *ppHead = NULL; +} + +RT_C_DECLS_BEGIN + +extern bool USBProxyLinuxCheckDeviceRoot(const char *pcszRoot, bool fIsDeviceNodes); + +#ifdef UNIT_TEST +void TestUSBSetupInit(const char *pcszUsbfsRoot, bool fUsbfsAccessible, + const char *pcszDevicesRoot, bool fDevicesAccessible, + int rcMethodInitResult); +void TestUSBSetEnv(const char *pcszEnvUsb, const char *pcszEnvUsbRoot); +#endif + +extern int USBProxyLinuxChooseMethod(bool *pfUsingUsbfsDevices, const char **ppcszDevicesRoot); +#ifdef UNIT_TEST +extern void TestUSBSetAvailableUsbfsDevices(const char **pacszDeviceAddresses); +extern void TestUSBSetAccessibleFiles(const char **pacszAccessibleFiles); +#endif + +extern PUSBDEVICE USBProxyLinuxGetDevices(const char *pcszDevicesRoot, bool fUseSysfs); + +RT_C_DECLS_END + +#endif /* !MAIN_INCLUDED_USBGetDevices_h */ + diff --git a/src/VBox/Main/include/USBIdDatabase.h b/src/VBox/Main/include/USBIdDatabase.h new file mode 100644 index 00000000..66e3cca1 --- /dev/null +++ b/src/VBox/Main/include/USBIdDatabase.h @@ -0,0 +1,226 @@ +/* $Id: USBIdDatabase.h $ */ +/** @file + * USB device vendor and product ID database. + */ + +/* + * Copyright (C) 2015-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_USBIdDatabase_h +#define MAIN_INCLUDED_USBIdDatabase_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/assert.h> +#include <iprt/stdint.h> +#include <iprt/cpp/ministring.h> +#include <iprt/bldprog-strtab.h> + + +/** Saves a few bytes (~25%) on strings. */ +#define USB_ID_DATABASE_WITH_COMPRESSION + +/** Max string length. */ +#define USB_ID_DATABASE_MAX_STRING _1K + + +AssertCompileSize(RTBLDPROGSTRREF, sizeof(uint32_t)); + + +/** + * Elements of product table. + */ +typedef struct USBIDDBPROD +{ + /** Product ID. */ + uint16_t idProduct; +} USBIDDBPROD; +AssertCompileSize(USBIDDBPROD, sizeof(uint16_t)); + + +/** + * Element of vendor table. + */ +typedef struct USBIDDBVENDOR +{ + /** Vendor ID. */ + uint16_t idVendor; + /** Index of the first product. */ + uint16_t iProduct; + /** Number of products. */ + uint16_t cProducts; +} USBIDDBVENDOR; +AssertCompileSize(USBIDDBVENDOR, sizeof(uint16_t) * 3); + + +/** + * Wrapper for static array of Aliases. + */ +class USBIdDatabase +{ +public: // For assertions and statis in the generator. + /** The compressed string table. */ + static RTBLDPROGSTRTAB const s_StrTab; + + /** Number of vendors in the two parallel arrays. */ + static const size_t s_cVendors; + /** Vendor IDs lookup table. */ + static const USBIDDBVENDOR s_aVendors[]; + /** Vendor names table running parallel to s_aVendors. */ + static const RTBLDPROGSTRREF s_aVendorNames[]; + + /** Number of products in the two parallel arrays. */ + static const size_t s_cProducts; + /** Vendor+Product keys for lookup purposes. */ + static const USBIDDBPROD s_aProducts[]; + /** Product names table running parallel to s_aProducts. */ + static const RTBLDPROGSTRREF s_aProductNames[]; + +public: + static RTCString returnString(PCRTBLDPROGSTRREF pStr) + { + char szTmp[USB_ID_DATABASE_MAX_STRING * 2]; + ssize_t cchTmp = RTBldProgStrTabQueryString(&s_StrTab, pStr->off, pStr->cch, szTmp, sizeof(szTmp)); + return RTCString(szTmp, (size_t)RT_MAX(cchTmp, 0)); + } + +private: + /** + * Performs a binary lookup of @a idVendor. + * + * @returns The index in the vendor tables, UINT32_MAX if not found. + * @param idVendor The vendor ID. + */ + static uint32_t lookupVendor(uint16_t idVendor) + { + size_t iEnd = s_cVendors; + if (iEnd) + { + size_t iStart = 0; + for (;;) + { + size_t idx = iStart + (iEnd - iStart) / 2; + if (s_aVendors[idx].idVendor < idVendor) + { + idx++; + if (idx < iEnd) + iStart = idx; + else + break; + } + else if (s_aVendors[idx].idVendor > idVendor) + { + if (idx != iStart) + iEnd = idx; + else + break; + } + else + return (uint32_t)idx; + } + } + return UINT32_MAX; + } + + /** + * Performs a binary lookup of @a idProduct. + * + * @returns The index in the product tables, UINT32_MAX if not found. + * @param idProduct The product ID. + * @param iStart The index of the first entry for the vendor. + * @param iEnd The index of after the last entry. + */ + static uint32_t lookupProduct(uint16_t idProduct, size_t iStart, size_t iEnd) + { + if (iStart < iEnd) + { + for (;;) + { + size_t idx = iStart + (iEnd - iStart) / 2; + if (s_aProducts[idx].idProduct < idProduct) + { + idx++; + if (idx < iEnd) + iStart = idx; + else + break; + } + else if (s_aProducts[idx].idProduct > idProduct) + { + if (idx != iStart) + iEnd = idx; + else + break; + } + else + return (uint32_t)idx; + } + } + return UINT32_MAX; + } + + +public: + static RTCString findProduct(uint16_t idVendor, uint16_t idProduct) + { + uint32_t idxVendor = lookupVendor(idVendor); + if (idxVendor != UINT32_MAX) + { + uint32_t idxProduct = lookupProduct(idProduct, s_aVendors[idxVendor].iProduct, + s_aVendors[idxVendor].iProduct + s_aVendors[idxVendor].cProducts); + if (idxProduct != UINT32_MAX) + return returnString(&s_aProductNames[idxProduct]); + } + return RTCString(); + } + + static RTCString findVendor(uint16_t idVendor) + { + uint32_t idxVendor = lookupVendor(idVendor); + if (idxVendor != UINT32_MAX) + return returnString(&s_aVendorNames[idxVendor]); + return RTCString(); + } + + static RTCString findVendorAndProduct(uint16_t idVendor, uint16_t idProduct, RTCString *pstrProduct) + { + uint32_t idxVendor = lookupVendor(idVendor); + if (idxVendor != UINT32_MAX) + { + uint32_t idxProduct = lookupProduct(idProduct, s_aVendors[idxVendor].iProduct, + s_aVendors[idxVendor].iProduct + s_aVendors[idxVendor].cProducts); + if (idxProduct != UINT32_MAX) + *pstrProduct = returnString(&s_aProductNames[idxProduct]); + else + pstrProduct->setNull(); + return returnString(&s_aVendorNames[idxVendor]); + } + pstrProduct->setNull(); + return RTCString(); + } + +}; + + +#endif /* !MAIN_INCLUDED_USBIdDatabase_h */ + diff --git a/src/VBox/Main/include/USBProxyBackend.h b/src/VBox/Main/include/USBProxyBackend.h new file mode 100644 index 00000000..8af51a5b --- /dev/null +++ b/src/VBox/Main/include/USBProxyBackend.h @@ -0,0 +1,448 @@ +/* $Id: USBProxyBackend.h $ */ +/** @file + * VirtualBox USB Proxy Backend (base) class. + */ + +/* + * Copyright (C) 2005-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_USBProxyBackend_h +#define MAIN_INCLUDED_USBProxyBackend_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/usb.h> +#include <VBox/usbfilter.h> + +#include <iprt/socket.h> +#include <iprt/poll.h> +#include <iprt/semaphore.h> +#include <iprt/cpp/utils.h> + +#include "VirtualBoxBase.h" +#include "VirtualBoxImpl.h" +#include "HostUSBDeviceImpl.h" +#include "USBProxyBackendWrap.h" +class USBProxyService; + +/** + * Base class for the USB Proxy Backend. + */ +class ATL_NO_VTABLE USBProxyBackend + : public USBProxyBackendWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(USBProxyBackend) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + virtual int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId, + const com::Utf8Str &strAddress, bool fLoadingSettings); + virtual void uninit(); + + bool isActive(void); + const com::Utf8Str &i_getId(); + const com::Utf8Str &i_getAddress(); + virtual const com::Utf8Str &i_getBackend(); + uint32_t i_getRefCount(); + + virtual bool i_isDevReEnumerationRequired(); + + /** @name Interface for the USBController and the Host object. + * @{ */ + virtual void *insertFilter(PCUSBFILTER aFilter); + virtual void removeFilter(void *aId); + /** @} */ + + /** @name Interfaces for the HostUSBDevice + * @{ */ + virtual int captureDevice(HostUSBDevice *aDevice); + virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess); + virtual int releaseDevice(HostUSBDevice *aDevice); + virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess); + /** @} */ + + static void freeDevice(PUSBDEVICE pDevice); + +protected: + int start(void); + int stop(void); + virtual void serviceThreadInit(void); + virtual void serviceThreadTerm(void); + + virtual int wait(RTMSINTERVAL aMillies); + virtual int interruptWait(void); + virtual PUSBDEVICE getDevices(void); + uint32_t incRef(); + uint32_t decRef(); + + static HRESULT setError(HRESULT aResultCode, const char *aText, ...); + + static void initFilterFromDevice(PUSBFILTER aFilter, HostUSBDevice *aDevice); + static void freeDeviceMembers(PUSBDEVICE pDevice); + + /** + * Backend specific callback when a device was added. + * (Currently only Linux uses it to adjust the udev polling). + */ + virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, PUSBDEVICE pDev); + virtual bool isFakeUpdateRequired(); + +private: + + // wrapped IUSBProxyBackend properties + HRESULT getName(com::Utf8Str &aName); + HRESULT getType(com::Utf8Str &aType); + + static DECLCALLBACK(int) serviceThread(RTTHREAD Thread, void *pvUser); + + void updateDeviceList(PUSBDEVICE pDevices); + +protected: + /** Pointer to the owning USB Proxy Service object. */ + USBProxyService *m_pUsbProxyService; + /** Thread handle of the service thread. */ + RTTHREAD mThread; + /** Flag which stop() sets to cause serviceThread to return. */ + bool volatile mTerminate; + /** Id of the instance. */ + const com::Utf8Str m_strId; + /** Address of the instance. */ + const com::Utf8Str m_strAddress; + /** Backend identifier as used in the settings. */ + const com::Utf8Str m_strBackend; + /** Reference counter which prevents the backend instance from being removed. */ + uint32_t m_cRefs; + /** List of smart HostUSBDevice pointers. */ + typedef std::list<ComObjPtr<HostUSBDevice> > HostUSBDeviceList; + /** List of the known USB devices for this backend. */ + HostUSBDeviceList m_llDevices; +}; + + +# if defined(RT_OS_DARWIN) || defined(DOXYGEN_RUNNING) +# include <VBox/param.h> +# undef PAGE_SHIFT +# undef PAGE_SIZE +# define OSType Carbon_OSType +# include <Carbon/Carbon.h> +# undef OSType +# undef PVM + +/** + * The Darwin hosted USB Proxy Backend. + */ +class USBProxyBackendDarwin : public USBProxyBackend +{ +public: + DECLARE_COMMON_CLASS_METHODS(USBProxyBackendDarwin) + + int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId, + const com::Utf8Str &strAddress, bool fLoadingSettings); + void uninit(); + + virtual int captureDevice(HostUSBDevice *aDevice); + virtual int releaseDevice(HostUSBDevice *aDevice); + +protected: + virtual int wait(RTMSINTERVAL aMillies); + virtual int interruptWait (void); + virtual PUSBDEVICE getDevices (void); + virtual void serviceThreadInit (void); + virtual void serviceThreadTerm (void); + virtual bool isFakeUpdateRequired(); + +private: + /** Reference to the runloop of the service thread. + * This is NULL if the service thread isn't running. */ + CFRunLoopRef mServiceRunLoopRef; + /** The opaque value returned by DarwinSubscribeUSBNotifications. */ + void *mNotifyOpaque; + /** A hack to work around the problem with the usb device enumeration + * not including newly attached devices. */ + bool mWaitABitNextTime; +}; +# endif /* RT_OS_DARWIN */ + + +# if defined(RT_OS_LINUX) || defined(DOXYGEN_RUNNING) +# include <stdio.h> +# ifdef VBOX_USB_WITH_SYSFS +# include <HostHardwareLinux.h> +# endif + +/** + * The Linux hosted USB Proxy Backend. + */ +class USBProxyBackendLinux: public USBProxyBackend +{ +public: + DECLARE_COMMON_CLASS_METHODS(USBProxyBackendLinux) + + int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId, + const com::Utf8Str &strAddress, bool fLoadingSettings); + void uninit(); + + virtual int captureDevice(HostUSBDevice *aDevice); + virtual int releaseDevice(HostUSBDevice *aDevice); + +protected: + int initUsbfs(void); + int initSysfs(void); + void doUsbfsCleanupAsNeeded(void); + virtual int wait(RTMSINTERVAL aMillies); + virtual int interruptWait(void); + virtual PUSBDEVICE getDevices(void); + virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, PUSBDEVICE aUSBDevice); + virtual bool isFakeUpdateRequired(); + +private: + int waitUsbfs(RTMSINTERVAL aMillies); + int waitSysfs(RTMSINTERVAL aMillies); + +private: + /** File handle to the '/proc/bus/usb/devices' file. */ + RTFILE mhFile; + /** Pipe used to interrupt wait(), the read end. */ + RTPIPE mhWakeupPipeR; + /** Pipe used to interrupt wait(), the write end. */ + RTPIPE mhWakeupPipeW; + /** The root of usbfs. */ + Utf8Str mDevicesRoot; + /** Whether we're using \<mUsbfsRoot\>/devices or /sys/whatever. */ + bool mUsingUsbfsDevices; + /** Number of 500ms polls left to do. See usbDeterminState for details. */ + unsigned mUdevPolls; +# ifdef VBOX_USB_WITH_SYSFS + /** Object used for polling for hotplug events from hal. */ + VBoxMainHotplugWaiter *mpWaiter; +# endif +}; +# endif /* RT_OS_LINUX */ + + +# if defined(RT_OS_OS2) || defined(DOXYGEN_RUNNING) +# include <usbcalls.h> + +/** + * The Linux hosted USB Proxy Backend. + */ +class USBProxyBackendOs2 : public USBProxyBackend +{ +public: + DECLARE_COMMON_CLASS_METHODS(USBProxyBackendOs2) + + virtual int captureDevice(HostUSBDevice *aDevice); + virtual int releaseDevice(HostUSBDevice *aDevice); + +protected: + virtual int wait(RTMSINTERVAL aMillies); + virtual int interruptWait(void); + virtual PUSBDEVICE getDevices(void); + int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc); + +private: + /** The notification event semaphore */ + HEV mhev; + /** The notification id. */ + USBNOTIFY mNotifyId; + /** The usbcalls.dll handle. */ + HMODULE mhmod; + /** UsbRegisterChangeNotification */ + APIRET (APIENTRY *mpfnUsbRegisterChangeNotification)(PUSBNOTIFY, HEV, HEV); + /** UsbDeregisterNotification */ + APIRET (APIENTRY *mpfnUsbDeregisterNotification)(USBNOTIFY); + /** UsbQueryNumberDevices */ + APIRET (APIENTRY *mpfnUsbQueryNumberDevices)(PULONG); + /** UsbQueryDeviceReport */ + APIRET (APIENTRY *mpfnUsbQueryDeviceReport)(ULONG, PULONG, PVOID); +}; +# endif /* RT_OS_OS2 */ + + +# if defined(RT_OS_SOLARIS) || defined(DOXYGEN_RUNNING) +# include <libdevinfo.h> + +/** + * The Solaris hosted USB Proxy Backend. + */ +class USBProxyBackendSolaris : public USBProxyBackend +{ +public: + DECLARE_COMMON_CLASS_METHODS(USBProxyBackendSolaris) + + int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId, + const com::Utf8Str &strAddress, bool fLoadingSettings); + void uninit(); + + virtual void *insertFilter (PCUSBFILTER aFilter); + virtual void removeFilter (void *aID); + + virtual int captureDevice(HostUSBDevice *aDevice); + virtual int releaseDevice(HostUSBDevice *aDevice); + virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess); + virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess); + + virtual bool i_isDevReEnumerationRequired(); + +protected: + virtual int wait(RTMSINTERVAL aMillies); + virtual int interruptWait(void); + virtual PUSBDEVICE getDevices(void); + +private: + RTSEMEVENT mNotifyEventSem; + /** Whether we've successfully initialized the USBLib and should call USBLibTerm in the destructor. */ + bool mUSBLibInitialized; +}; +#endif /* RT_OS_SOLARIS */ + + +# if defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING) +/** + * The Windows hosted USB Proxy Backend. + */ +class USBProxyBackendWindows : public USBProxyBackend +{ +public: + DECLARE_COMMON_CLASS_METHODS(USBProxyBackendWindows) + + int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId, + const com::Utf8Str &strAddress, bool fLoadingSettings); + void uninit(); + + virtual void *insertFilter (PCUSBFILTER aFilter); + virtual void removeFilter (void *aID); + + virtual int captureDevice(HostUSBDevice *aDevice); + virtual int releaseDevice(HostUSBDevice *aDevice); + + virtual bool i_isDevReEnumerationRequired(); + +protected: + virtual int wait(RTMSINTERVAL aMillies); + virtual int interruptWait(void); + virtual PUSBDEVICE getDevices(void); + +private: + + HANDLE mhEventInterrupt; +}; +# endif /* RT_OS_WINDOWS */ + +# if defined(RT_OS_FREEBSD) || defined(DOXYGEN_RUNNING) +/** + * The FreeBSD hosted USB Proxy Backend. + */ +class USBProxyBackendFreeBSD : public USBProxyBackend +{ +public: + DECLARE_COMMON_CLASS_METHODS(USBProxyBackendFreeBSD) + + int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId, + const com::Utf8Str &strAddress, bool fLoadingSettings); + void uninit(); + + virtual int captureDevice(HostUSBDevice *aDevice); + virtual int releaseDevice(HostUSBDevice *aDevice); + +protected: + int initUsbfs(void); + int initSysfs(void); + virtual int wait(RTMSINTERVAL aMillies); + virtual int interruptWait(void); + virtual PUSBDEVICE getDevices(void); + int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc); + virtual bool isFakeUpdateRequired(); + +private: + RTSEMEVENT mNotifyEventSem; +}; +# endif /* RT_OS_FREEBSD */ + +/** + * USB/IP Proxy receive state. + */ +typedef enum USBIPRECVSTATE +{ + /** Invalid state. */ + kUsbIpRecvState_Invalid = 0, + /** There is no request waiting for an answer. */ + kUsbIpRecvState_None, + /** Waiting for the complete reception of UsbIpRetDevList. */ + kUsbIpRecvState_Hdr, + /** Waiting for the complete reception of a UsbIpExportedDevice structure. */ + kUsbIpRecvState_ExportedDevice, + /** Waiting for a complete reception of a UsbIpDeviceInterface structure to skip. */ + kUsbIpRecvState_DeviceInterface, + /** 32bit hack. */ + kUsbIpRecvState_32Bit_Hack = 0x7fffffff +} USBIPRECVSTATE; +/** Pointer to a USB/IP receive state enum. */ +typedef USBIPRECVSTATE *PUSBIPRECVSTATE; + +struct UsbIpExportedDevice; + +/** + * The USB/IP Proxy Backend. + */ +class USBProxyBackendUsbIp: public USBProxyBackend +{ +public: + DECLARE_COMMON_CLASS_METHODS(USBProxyBackendUsbIp) + + int init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId, + const com::Utf8Str &strAddress, bool fLoadingSettings); + void uninit(); + + virtual int captureDevice(HostUSBDevice *aDevice); + virtual int releaseDevice(HostUSBDevice *aDevice); + +protected: + virtual int wait(RTMSINTERVAL aMillies); + virtual int interruptWait(void); + virtual PUSBDEVICE getDevices(void); + virtual bool isFakeUpdateRequired(); + +private: + int updateDeviceList(bool *pfDeviceListChanged); + bool hasDevListChanged(PUSBDEVICE pDevices); + void freeDeviceList(PUSBDEVICE pHead); + void resetRecvState(); + int reconnect(); + void disconnect(); + int startListExportedDevicesReq(); + void advanceState(USBIPRECVSTATE enmRecvState); + int receiveData(); + int processData(); + int addDeviceToList(UsbIpExportedDevice *pDev); + + struct Data; // opaque data struct, defined in USBProxyBackendUsbIp.cpp + Data *m; +}; + +#endif /* !MAIN_INCLUDED_USBProxyBackend_h */ + diff --git a/src/VBox/Main/include/USBProxyService.h b/src/VBox/Main/include/USBProxyService.h new file mode 100644 index 00000000..ea1149fd --- /dev/null +++ b/src/VBox/Main/include/USBProxyService.h @@ -0,0 +1,147 @@ +/* $Id: USBProxyService.h $ */ +/** @file + * VirtualBox USB Proxy Service (base) class. + */ + +/* + * Copyright (C) 2005-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_USBProxyService_h +#define MAIN_INCLUDED_USBProxyService_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/usb.h> +#include <VBox/usbfilter.h> + +#include "VirtualBoxBase.h" +#include "VirtualBoxImpl.h" +#include "HostUSBDeviceImpl.h" +#include "USBProxyBackend.h" + +class Host; + +namespace settings +{ + struct USBDeviceSource; + typedef std::list<USBDeviceSource> USBDeviceSourcesList; +} + + +/** + * Base class for the USB Proxy service. + */ +class USBProxyService + : public Lockable +{ +public: + DECLARE_TRANSLATE_METHODS(USBProxyService) + + USBProxyService(Host *aHost); + virtual HRESULT init(void); + virtual ~USBProxyService(); + + /** + * Override of the default locking class to be used for validating lock + * order with the standard member lock handle. + */ + virtual VBoxLockingClass getLockingClass() const + { + // the USB proxy service uses the Host object lock, so return the + // same locking class as the host + return LOCKCLASS_HOSTOBJECT; + } + + void uninit(void); + + bool isActive(void); + int getLastError(void); + + RWLockHandle *lockHandle() const; + + /** @name Interface for the USBController and the Host object. + * @{ */ + void *insertFilter(PCUSBFILTER aFilter); + void removeFilter(void *aId); + /** @} */ + + /** @name Host Interfaces + * @{ */ + HRESULT getDeviceCollection(std::vector<ComPtr<IHostUSBDevice> > &aUSBDevices); + HRESULT addUSBDeviceSource(const com::Utf8Str &aBackend, const com::Utf8Str &aId, const com::Utf8Str &aAddress, + const std::vector<com::Utf8Str> &aPropertyNames, const std::vector<com::Utf8Str> &aPropertyValues); + HRESULT removeUSBDeviceSource(const com::Utf8Str &aId); + /** @} */ + + /** @name SessionMachine Interfaces + * @{ */ + HRESULT captureDeviceForVM(SessionMachine *aMachine, IN_GUID aId, const com::Utf8Str &aCaptureFilename); + HRESULT detachDeviceFromVM(SessionMachine *aMachine, IN_GUID aId, bool aDone); + HRESULT autoCaptureDevicesForVM(SessionMachine *aMachine); + HRESULT detachAllDevicesFromVM(SessionMachine *aMachine, bool aDone, bool aAbnormal); + /** @} */ + + typedef std::list< ComObjPtr<HostUSBDeviceFilter> > USBDeviceFilterList; + + HRESULT i_loadSettings(const settings::USBDeviceSourcesList &llUSBDeviceSources); + HRESULT i_saveSettings(settings::USBDeviceSourcesList &llUSBDeviceSources); + + void i_deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, PUSBDEVICE aUSBDevice); + void i_deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice); + void i_updateDeviceState(ComObjPtr<HostUSBDevice> &aDevice, PUSBDEVICE aUSBDevice, bool fFakeUpdate); + +protected: + ComObjPtr<HostUSBDevice> findDeviceById(IN_GUID aId); + + static HRESULT setError(HRESULT aResultCode, const char *aText, ...); + + USBProxyBackend *findUsbProxyBackendById(const com::Utf8Str &strId); + + HRESULT createUSBDeviceSource(const com::Utf8Str &aBackend, const com::Utf8Str &aId, + const com::Utf8Str &aAddress, const std::vector<com::Utf8Str> &aPropertyNames, + const std::vector<com::Utf8Str> &aPropertyValues, bool fLoadingSettings); + +private: + + HRESULT runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice, + SessionMachinesList &llOpenedMachines, + SessionMachine *aIgnoreMachine); + bool runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice); + + void deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, bool fRunFilters, SessionMachine *aIgnoreMachine); + + /** Pointer to the Host object. */ + Host *mHost; + /** List of smart HostUSBDevice pointers. */ + typedef std::list<ComObjPtr<HostUSBDevice> > HostUSBDeviceList; + /** List of the known USB devices. */ + HostUSBDeviceList mDevices; + /** List of USBProxyBackend pointers. */ + typedef std::list<ComObjPtr<USBProxyBackend> > USBProxyBackendList; + /** List of active USB backends. */ + USBProxyBackendList mBackends; + int mLastError; +}; + +#endif /* !MAIN_INCLUDED_USBProxyService_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/UefiVariableStoreImpl.h b/src/VBox/Main/include/UefiVariableStoreImpl.h new file mode 100644 index 00000000..7a8e9d7d --- /dev/null +++ b/src/VBox/Main/include/UefiVariableStoreImpl.h @@ -0,0 +1,104 @@ +/* $Id: UefiVariableStoreImpl.h $ */ +/** @file + * VirtualBox COM UEFI variable store class implementation + */ + +/* + * Copyright (C) 2021-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_UefiVariableStoreImpl_h +#define MAIN_INCLUDED_UefiVariableStoreImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "UefiVariableStoreWrap.h" +#include <iprt/types.h> + +#include <iprt/formats/efi-common.h> + +class NvramStore; +class Machine; + +class ATL_NO_VTABLE UefiVariableStore : + public UefiVariableStoreWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(UefiVariableStore) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(NvramStore *aParent, Machine *pMachine); + void uninit(); + + // public methods for internal purposes only + +private: + + // Wrapped NVRAM store properties + HRESULT getSecureBootEnabled(BOOL *pfEnabled); + HRESULT setSecureBootEnabled(BOOL fEnabled); + + // Wrapped NVRAM store members + HRESULT addVariable(const com::Utf8Str &aName, const com::Guid &aOwnerUuid, const std::vector<UefiVariableAttributes_T> &aAttributes, + const std::vector<BYTE> &aData); + HRESULT deleteVariable(const com::Utf8Str &aName, const com::Guid &aOwnerUuid); + HRESULT changeVariable(const com::Utf8Str &aName, const std::vector<BYTE> &aData); + HRESULT queryVariableByName(const com::Utf8Str &aName, com::Guid &aOwnerUuid, std::vector<UefiVariableAttributes_T> &aAttributes, + std::vector<BYTE> &aData); + HRESULT queryVariables(std::vector<com::Utf8Str> &aNames, std::vector<com::Guid> &aOwnerUuids); + HRESULT enrollOraclePlatformKey(void); + HRESULT enrollPlatformKey(const std::vector<BYTE> &aData, const com::Guid &aOwnerUuid); + HRESULT addKek(const std::vector<BYTE> &aData, const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType); + HRESULT addSignatureToDb(const std::vector<BYTE> &aData, const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType); + HRESULT addSignatureToDbx(const std::vector<BYTE> &aData, const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType); + HRESULT enrollDefaultMsSignatures(void); + + int i_uefiVarStoreSetVarAttr(const char *pszVar, uint32_t fAttr); + int i_uefiVarStoreQueryVarAttr(const char *pszVar, uint32_t *pfAttr); + int i_uefiVarStoreQueryVarSz(const char *pszVar, uint64_t *pcbVar); + int i_uefiVarStoreQueryVarOwnerUuid(const char *pszVar, PRTUUID pUuid); + uint32_t i_uefiVarAttrToMask(const std::vector<UefiVariableAttributes_T> &aAttributes); + void i_uefiAttrMaskToVec(uint32_t fAttr, std::vector<UefiVariableAttributes_T> &aAttributes); + + HRESULT i_retainUefiVariableStore(bool fReadonly); + HRESULT i_releaseUefiVariableStore(void); + + HRESULT i_uefiVarStoreAddVar(PCEFI_GUID pGuid, const char *pszVar, uint32_t fAttr, PRTVFSFILE phVfsFile); + HRESULT i_uefiVarStoreOpenVar(const char *pszVar, PRTVFSFILE phVfsFile); + HRESULT i_uefiVarStoreSetVar(PCEFI_GUID pGuid, const char *pszVar, uint32_t fAttr, const void *pvData, size_t cbData); + HRESULT i_uefiVarStoreQueryVar(const char *pszVar, void *pvData, size_t cbData); + HRESULT i_uefiSigDbAddSig(RTEFISIGDB hEfiSigDb, const void *pvData, size_t cbData, const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType); + HRESULT i_uefiVarStoreAddSignatureToDbVec(PCEFI_GUID pGuid, const char *pszDb, const std::vector<BYTE> &aData, + const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType); + HRESULT i_uefiVarStoreAddSignatureToDb(PCEFI_GUID pGuid, const char *pszDb, const void *pvData, size_t cbData, + const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType); + + struct Data; // opaque data struct, defined in UefiVariableStoreImpl.cpp + Data *m; +}; + +#endif /* !MAIN_INCLUDED_UefiVariableStoreImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/UnattendedImpl.h b/src/VBox/Main/include/UnattendedImpl.h new file mode 100644 index 00000000..3345e0af --- /dev/null +++ b/src/VBox/Main/include/UnattendedImpl.h @@ -0,0 +1,318 @@ +/* $Id: UnattendedImpl.h $ */ +/** @file + * Unattended class header + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_UnattendedImpl_h +#define MAIN_INCLUDED_UnattendedImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/ostypes.h> +#include <iprt/time.h> +#include "UnattendedWrap.h" + +/* Forward declarations. */ +class UnattendedInstaller; +struct UnattendedInstallationDisk; +struct ControllerSlot; + +/** + * A data type to store image data which is read from intall.wim file. + * Currently relevant only for Windows OSs. + */ +struct WIMImage +{ + Utf8Str mName; + Utf8Str mVersion; + Utf8Str mArch; + Utf8Str mFlavor; + RTCList<RTCString, RTCString *> mLanguages; + Utf8Str mDefaultLanguage; + uint32_t mImageIndex; + VBOXOSTYPE mOSType; + WIMImage() : mImageIndex(0), mOSType(VBOXOSTYPE_Unknown) { } + const Utf8Str &formatName(Utf8Str &r_strName) const; + VBOXOSTYPE mEnmOsType; +}; + +/** + * Class implementing the IUnattended interface. + * + * This class is instantiated on the request by IMachine::getUnattended. + */ +class ATL_NO_VTABLE Unattended + : public UnattendedWrap +{ +public: + DECLARE_COMMON_CLASS_METHODS(Unattended) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT initUnattended(VirtualBox *aParent); + void uninit(); + + // public methods for internal purposes + Utf8Str const &i_getIsoPath() const; + Utf8Str const &i_getUser() const; + Utf8Str const &i_getPassword() const; + Utf8Str const &i_getFullUserName() const; + Utf8Str const &i_getProductKey() const; + Utf8Str const &i_getProxy() const; + Utf8Str const &i_getAdditionsIsoPath() const; + bool i_getInstallGuestAdditions() const; + Utf8Str const &i_getValidationKitIsoPath() const; + bool i_getInstallTestExecService() const; + Utf8Str const &i_getTimeZone() const; + PCRTTIMEZONEINFO i_getTimeZoneInfo() const; + Utf8Str const &i_getLocale() const; + Utf8Str const &i_getLanguage() const; + Utf8Str const &i_getCountry() const; + bool i_isMinimalInstallation() const; + Utf8Str const &i_getHostname() const; + Utf8Str const &i_getAuxiliaryBasePath() const; + ULONG i_getImageIndex() const; + Utf8Str const &i_getScriptTemplatePath() const; + Utf8Str const &i_getPostInstallScriptTemplatePath() const; + Utf8Str const &i_getPostInstallCommand() const; + /** The directory where the unattended install config and script is + * located, from the perspective of the running unattended install. */ + Utf8Str const &i_getAuxiliaryInstallDir() const; + Utf8Str const &i_getExtraInstallKernelParameters() const; + + bool i_isRtcUsingUtc() const; + bool i_isGuestOs64Bit() const; + bool i_isFirmwareEFI() const; + Utf8Str const &i_getDetectedOSVersion(); + bool i_getAvoidUpdatesOverNetwork() const; + +private: + ComPtr<VirtualBox> const mParent; /**< Strong reference to the parent object (VirtualBox/IMachine). */ + ComPtr<Machine> mMachine; /**< Strong reference to the machine object (Machine/IMachine). */ + Guid mMachineUuid; /**< The machine UUID. */ + RTNATIVETHREAD mhThreadReconfigureVM; /**< Set when reconfigureVM is running. */ + Utf8Str mStrGuestOsTypeId; /**< Guest OS type ID (set by prepare). */ + bool mfRtcUseUtc; /**< Copy of IMachine::RTCUseUTC (locking reasons). */ + bool mfGuestOs64Bit; /**< 64-bit (true) or 32-bit guest OS (set by prepare). */ + FirmwareType_T menmFirmwareType; /**< Firmware type BIOS/EFI (set by prepare). */ + UnattendedInstaller *mpInstaller; /**< The installer instance (set by prepare, deleted by done). */ + + /** @name Values of the IUnattended attributes. + * @{ */ + Utf8Str mStrUser; + Utf8Str mStrPassword; + Utf8Str mStrFullUserName; + Utf8Str mStrProductKey; + Utf8Str mStrIsoPath; + Utf8Str mStrAdditionsIsoPath; + bool mfInstallGuestAdditions; + bool mfInstallTestExecService; + Utf8Str mStrValidationKitIsoPath; + Utf8Str mStrTimeZone; + PCRTTIMEZONEINFO mpTimeZoneInfo; + Utf8Str mStrLocale; + Utf8Str mStrLanguage; /**< (only relevant for windows at the moment) */ + Utf8Str mStrCountry; + RTCList<RTCString, RTCString *> mPackageSelectionAdjustments; + Utf8Str mStrHostname; + Utf8Str mStrAuxiliaryBasePath; + bool mfIsDefaultAuxiliaryBasePath; + ULONG midxImage; + Utf8Str mStrScriptTemplatePath; + Utf8Str mStrPostInstallScriptTemplatePath; + Utf8Str mStrPostInstallCommand; + Utf8Str mStrExtraInstallKernelParameters; + Utf8Str mStrProxy; + + bool mfDoneDetectIsoOS; /**< Set by detectIsoOS(), cleared by setIsoPath(). */ + Utf8Str mStrDetectedOSTypeId; + Utf8Str mStrDetectedOSVersion; + Utf8Str mStrDetectedOSFlavor; + VBOXOSTYPE mEnmOsType; + RTCList<RTCString, RTCString *> mDetectedOSLanguages; /**< (only relevant for windows at the moment) */ + Utf8Str mStrDetectedOSHints; + RTCList<WIMImage> mDetectedImages; + bool mfAvoidUpdatesOverNetwork; + /** @} */ + + // wrapped IUnattended functions: + + /** + * Checks what mStrIsoPath points to and sets the detectedOS* properties. + */ + HRESULT detectIsoOS(); + + /** + * Prepare any data, environment, etc. + */ + HRESULT prepare(); + + /** + * Prepare installation ISO/floppy. + */ + HRESULT constructMedia(); + + /** + * Prepare a VM to run an unattended installation + */ + HRESULT reconfigureVM(); + + /** + * Done with all media construction and VM configuration and stuff. + */ + HRESULT done(); + + // wrapped IUnattended attributes: + HRESULT getIsoPath(com::Utf8Str &isoPath); + HRESULT setIsoPath(const com::Utf8Str &isoPath); + HRESULT getUser(com::Utf8Str &user); + HRESULT setUser(const com::Utf8Str &user); + HRESULT getPassword(com::Utf8Str &password); + HRESULT setPassword(const com::Utf8Str &password); + HRESULT getFullUserName(com::Utf8Str &user); + HRESULT setFullUserName(const com::Utf8Str &user); + HRESULT getProductKey(com::Utf8Str &productKey); + HRESULT setProductKey(const com::Utf8Str &productKey); + HRESULT getAdditionsIsoPath(com::Utf8Str &additionsIsoPath); + HRESULT setAdditionsIsoPath(const com::Utf8Str &additionsIsoPath); + HRESULT getInstallGuestAdditions(BOOL *installGuestAdditions); + HRESULT setInstallGuestAdditions(BOOL installGuestAdditions); + HRESULT getValidationKitIsoPath(com::Utf8Str &aValidationKitIsoPath); + HRESULT setValidationKitIsoPath(const com::Utf8Str &aValidationKitIsoPath); + HRESULT getInstallTestExecService(BOOL *aInstallTestExecService); + HRESULT setInstallTestExecService(BOOL aInstallTestExecService); + HRESULT getTimeZone(com::Utf8Str &aTimezone); + HRESULT setTimeZone(const com::Utf8Str &aTimezone); + HRESULT getLocale(com::Utf8Str &aLocale); + HRESULT setLocale(const com::Utf8Str &aLocale); + HRESULT getLanguage(com::Utf8Str &aLanguage); + HRESULT setLanguage(const com::Utf8Str &aLanguage); + HRESULT getCountry(com::Utf8Str &aCountry); + HRESULT setCountry(const com::Utf8Str &aCountry); + HRESULT getProxy(com::Utf8Str &aProxy); + HRESULT setProxy(const com::Utf8Str &aProxy); + HRESULT getPackageSelectionAdjustments(com::Utf8Str &aPackageSelectionAdjustments); + HRESULT setPackageSelectionAdjustments(const com::Utf8Str &aPackageSelectionAdjustments); + HRESULT getHostname(com::Utf8Str &aHostname); + HRESULT setHostname(const com::Utf8Str &aHostname); + HRESULT getAuxiliaryBasePath(com::Utf8Str &aAuxiliaryBasePath); + HRESULT setAuxiliaryBasePath(const com::Utf8Str &aAuxiliaryBasePath); + HRESULT getImageIndex(ULONG *index); + HRESULT setImageIndex(ULONG index); + HRESULT getMachine(ComPtr<IMachine> &aMachine); + HRESULT setMachine(const ComPtr<IMachine> &aMachine); + HRESULT getScriptTemplatePath(com::Utf8Str &aScriptTemplatePath); + HRESULT setScriptTemplatePath(const com::Utf8Str &aScriptTemplatePath); + HRESULT getPostInstallScriptTemplatePath(com::Utf8Str &aPostInstallScriptTemplatePath); + HRESULT setPostInstallScriptTemplatePath(const com::Utf8Str &aPostInstallScriptTemplatePath); + HRESULT getPostInstallCommand(com::Utf8Str &aPostInstallCommand); + HRESULT setPostInstallCommand(const com::Utf8Str &aPostInstallCommand); + HRESULT getExtraInstallKernelParameters(com::Utf8Str &aExtraInstallKernelParameters); + HRESULT setExtraInstallKernelParameters(const com::Utf8Str &aExtraInstallKernelParameters); + HRESULT getDetectedOSTypeId(com::Utf8Str &aDetectedOSTypeId); + HRESULT getDetectedOSVersion(com::Utf8Str &aDetectedOSVersion); + HRESULT getDetectedOSLanguages(com::Utf8Str &aDetectedOSLanguages); + HRESULT getDetectedOSFlavor(com::Utf8Str &aDetectedOSFlavor); + HRESULT getDetectedOSHints(com::Utf8Str &aDetectedOSHints); + HRESULT getDetectedImageNames(std::vector<com::Utf8Str> &aDetectedImageNames); + HRESULT getDetectedImageIndices(std::vector<ULONG> &aDetectedImageIndices); + HRESULT getIsUnattendedInstallSupported(BOOL *aIsUnattendedInstallSupported); + HRESULT getAvoidUpdatesOverNetwork(BOOL *aAvoidUpdatesOverNetwork); + HRESULT setAvoidUpdatesOverNetwork(BOOL aAvoidUpdatesOverNetwork); + //internal functions + + /** + * Worker for detectIsoOs(). + * + * @returns COM status code. + * @retval S_OK if detected. + * @retval S_FALSE if not detected. + * + * @param hVfsIso The ISO file system handle. + */ + HRESULT i_innerDetectIsoOS(RTVFS hVfsIso); + typedef union DETECTBUFFER + { + char sz[4096]; + char ach[4096]; + uint8_t ab[4096]; + uint32_t au32[1024]; + } DETECTBUFFER; + HRESULT i_innerDetectIsoOSWindows(RTVFS hVfsIso, DETECTBUFFER *puBuf); + HRESULT i_innerDetectIsoOSLinux(RTVFS hVfsIso, DETECTBUFFER *puBuf); + HRESULT i_innerDetectIsoOSLinuxFedora(RTVFS hVfsIso, DETECTBUFFER *puBuf, char *pszVolId); + HRESULT i_innerDetectIsoOSOs2(RTVFS hVfsIso, DETECTBUFFER *puBuf); + HRESULT i_innerDetectIsoOSFreeBsd(RTVFS hVfsIso, DETECTBUFFER *puBuf); + + /** + * Worker for reconfigureVM(). + * The caller makes sure to close the session whatever happens. + */ + HRESULT i_innerReconfigureVM(AutoMultiWriteLock2 &rAutoLock, StorageBus_T enmRecommendedStorageBus, + ComPtr<IMachine> const &rPtrSessionMachine); + HRESULT i_reconfigureFloppy(com::SafeIfaceArray<IStorageController> &rControllers, + std::vector<UnattendedInstallationDisk> &rVecInstallatationDisks, + ComPtr<IMachine> const &rPtrSessionMachine, + AutoMultiWriteLock2 &rAutoLock); + HRESULT i_reconfigureIsos(com::SafeIfaceArray<IStorageController> &rControllers, + std::vector<UnattendedInstallationDisk> &rVecInstallatationDisks, + ComPtr<IMachine> const &rPtrSessionMachine, + AutoMultiWriteLock2 &rAutoLock, StorageBus_T enmRecommendedStorageBus); + + /** + * Adds all free slots on the controller to @a rOutput. + */ + HRESULT i_findOrCreateNeededFreeSlots(const Utf8Str &rStrControllerName, StorageBus_T enmStorageBus, + ComPtr<IMachine> const &rPtrSessionMachine, uint32_t cSlotsNeeded, + std::list<ControllerSlot> &rDvdSlots); + + /** + * Attach to VM a disk + */ + HRESULT i_attachImage(UnattendedInstallationDisk const *pImage, ComPtr<IMachine> const &rPtrSessionMachine, + AutoMultiWriteLock2 &rLock); + + /* + * Wrapper functions + */ + + /** + * Check whether guest is 64bit platform or not + */ + bool i_isGuestOSArchX64(Utf8Str const &rStrGuestOsTypeId); + + /** + * Updates the detected attributes when the image index or image list changes. + * + * @returns true if we've got all necessary stuff for a successful detection. + */ + bool i_updateDetectedAttributeForImage(WIMImage const &rImage); + +}; + +#endif /* !MAIN_INCLUDED_UnattendedImpl_h */ diff --git a/src/VBox/Main/include/UnattendedInstaller.h b/src/VBox/Main/include/UnattendedInstaller.h new file mode 100644 index 00000000..2c4689da --- /dev/null +++ b/src/VBox/Main/include/UnattendedInstaller.h @@ -0,0 +1,891 @@ +/* $Id: UnattendedInstaller.h $ */ +/** @file + * UnattendedInstaller class header + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_UnattendedInstaller_h +#define MAIN_INCLUDED_UnattendedInstaller_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "UnattendedScript.h" + +/* Forward declarations */ +class Unattended; +class UnattendedInstaller; +class BaseTextScript; + + +/** + * The abstract UnattendedInstaller class declaration + * + * The class is intended to service a new VM that this VM will be able to + * execute an unattended installation + */ +class UnattendedInstaller : public RTCNonCopyable +{ +/*data*/ +protected: + /** Main unattended installation script. */ + UnattendedScriptTemplate mMainScript; + /** Full path to the main template file (set by initInstaller). */ + Utf8Str mStrMainScriptTemplate; + + /** Post installation (shell) script. */ + UnattendedScriptTemplate mPostScript; + /** Full path to the post template file (set by initInstaller). */ + Utf8Str mStrPostScriptTemplate; + + /** Pointer to the parent object. + * We use this for setting errors and querying attributes. */ + Unattended *mpParent; + /** The path of the extra ISO image we create (set by initInstaller). + * This is only valid when isAdditionsIsoNeeded() returns true. */ + Utf8Str mStrAuxiliaryIsoFilePath; + /** The path of the extra floppy image we create (set by initInstaller) + * This is only valid when isAdditionsFloppyNeeded() returns true. */ + Utf8Str mStrAuxiliaryFloppyFilePath; + /** The boot device. */ + DeviceType_T const meBootDevice; + /** Default extra install kernel parameters (set by constructor). + * This can be overridden by the extraInstallKernelParameters attribute of + * IUnattended. */ + Utf8Str mStrDefaultExtraInstallKernelParameters; + /** The directory of the post install script in the unattended install + * environment, i.e. when it gets started by the unattended installer + * of the respective guest OS. */ + Utf8Str mStrAuxiliaryInstallDir; + +private: + UnattendedInstaller(); /* no default constructors */ + +public: + DECLARE_TRANSLATE_METHODS(UnattendedInstaller) + + /** + * Regular constructor. + * + * @param pParent The parent object. Used for setting + * errors and querying attributes. + * @param pszMainScriptTemplateName The name of the template file (no path) + * for the main unattended installer + * script. + * @param pszPostScriptTemplateName The name of the template file (no path) + * for the post installation script. + * @param pszMainScriptFilename The main unattended installer script + * filename (on aux media). + * @param pszPostScriptFilename The post installation script filename + * (on aux media). + * @param enmBootDevice The boot device type. + */ + UnattendedInstaller(Unattended *pParent, + const char *pszMainScriptTemplateName, const char *pszPostScriptTemplateName, + const char *pszMainScriptFilename, const char *pszPostScriptFilename, + DeviceType_T enmBootDevice = DeviceType_DVD); + virtual ~UnattendedInstaller(); + + /** + * Instantiates the appropriate child class. + * + * @returns Pointer to the new instance, NULL if no appropriate installer. + * @param enmDetectedOSType The detected guest OS type value. + * @param strDetectedOSType The detected guest OS type string + * @param strDetectedOSVersion The detected guest OS version. + * @param strDetectedOSFlavor The detected guest OS flavor. + * @param strDetectedOSHints Hints about the detected guest OS. + * @param pParent The parent object. Used for setting errors + * and querying attributes. + * @throws std::bad_alloc + */ + static UnattendedInstaller *createInstance(VBOXOSTYPE enmDetectedOSType, const Utf8Str &strDetectedOSType, + const Utf8Str &strDetectedOSVersion, const Utf8Str &strDetectedOSFlavor, + const Utf8Str &strDetectedOSHints, Unattended *pParent); + + /** + * Initialize the installer. + * + * @note This is called immediately after instantiation and the caller will + * always destroy the unattended installer instance on failure, so it + * is not necessary to keep track of whether this succeeded or not. + */ + virtual HRESULT initInstaller(); + +#if 0 /* These are now in the AUX VISO. */ + /** + * Whether the VBox Guest Additions ISO is needed or not. + * + * The default implementation always returns false when a VISO is used, see + * UnattendedInstaller::addFilesToAuxVisoVectors. + */ + virtual bool isAdditionsIsoNeeded() const; + + /** + * Whether the VBox validation kit ISO is needed or not. + * + * The default implementation always returns false when a VISO is used, see + * UnattendedInstaller::addFilesToAuxVisoVectors. + */ + virtual bool isValidationKitIsoNeeded() const; +#endif + + /** + * Indicates whether an original installation ISO is needed or not. + */ + virtual bool isOriginalIsoNeeded() const { return true; } + + /** + * Indicates whether a floppy image is needed or not. + */ + virtual bool isAuxiliaryFloppyNeeded() const { return false; } + + /** + * Indicates whether an additional or replacement ISO image is needed or not. + */ + virtual bool isAuxiliaryIsoNeeded() const; + + /** + * Indicates whether we should boot from the auxiliary ISO image. + * + * Will boot from installation ISO if false. + */ + virtual bool bootFromAuxiliaryIso() const { return isAuxiliaryIsoNeeded(); } + + /** + * Indicates whether a the auxiliary ISO is a .viso-file rather than an + * .iso-file. + * + * Different worker methods are used depending on the return value. A + * .viso-file is generally only used when the installation media needs to + * be remastered with small changes and additions. + */ + virtual bool isAuxiliaryIsoIsVISO() const { return true; } + + /* + * Getters + */ + DeviceType_T getBootableDeviceType() const { return meBootDevice; } + const Utf8Str &getTemplateFilePath() const { return mStrMainScriptTemplate; } + const Utf8Str &getPostTemplateFilePath() const { return mStrPostScriptTemplate; } + const Utf8Str &getAuxiliaryIsoFilePath() const { return mStrAuxiliaryIsoFilePath; } + const Utf8Str &getAuxiliaryFloppyFilePath() const { return mStrAuxiliaryFloppyFilePath; } + const Utf8Str &getDefaultExtraInstallKernelParameters() const { return mStrDefaultExtraInstallKernelParameters; } + const Utf8Str &getAuxiliaryInstallDir() const { return mStrAuxiliaryInstallDir; } + + /* + * Setters + */ + void setTemplatePath(const Utf8Str& data); /**< @todo r=bird: This is confusing as heck. Dir for a while, then it's a file. Not a comment about it. Brilliant. */ + + /** + * Prepares the unattended scripts, does all but write them to the installation + * media. + */ + HRESULT prepareUnattendedScripts(); + + /** + * Prepares the media - floppy image, ISO image. + * + * This method calls prepareAuxFloppyImage() and prepareAuxIsoImage(), child + * classes may override these methods or methods they call. + * + * @returns COM status code. + * @param fOverwrite Whether to overwrite media files or fail if they + * already exist. + */ + HRESULT prepareMedia(bool fOverwrite = true); + +protected: + /** + * Prepares (creates) the auxiliary floppy image. + * + * This is called by the base class prepareMedia() when + * isAuxiliaryFloppyNeeded() is true. The base class implementation puts the + * edited unattended script onto it. + */ + HRESULT prepareAuxFloppyImage(bool fOverwrite); + + /** + * Creates and formats (FAT12) a floppy image. + * + * This can be overridden to do more preparation work or/and create a different + * sized floppy. + * + * @returns COM status code. + * @param pszFilename The path to the image file. + * @param fOverwrite Whether to overwrite the file. + * @param phVfsFile Where to return a read-writable handle to the newly + * created image. + */ + virtual HRESULT newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile); + + /** + * Copies files to the auxiliary floppy image. + * + * The base class implementation copies the main and post scripts to the root of + * the floppy using the default script names. Child classes may override this + * to add additional or different files. + * + * @returns COM status code. + * @param hVfs The floppy image VFS handle. + */ + virtual HRESULT copyFilesToAuxFloppyImage(RTVFS hVfs); + + /** + * Adds the given script to the root of the floppy image under the default + * script filename. + * + * @returns COM status code. + * @param pEditor The script to add. + * @param hVfs The VFS to add it to. + */ + HRESULT addScriptToFloppyImage(BaseTextScript *pEditor, RTVFS hVfs); + + /** + * Copy an arbritrary file onto the floopy image. + * + * @returns COM status code. + * @param hVfs The VFS to add it to. + * @param pszSrc The source filename. + * @param pszDst The destination filename (on @a hVfs). + */ + HRESULT addFileToFloppyImage(RTVFS hVfs, const char *pszSrc, const char *pszDst); + + /** + * Prepares (creates) the auxiliary ISO image. + * + * This is called by the base class prepareMedia() when isAuxiliaryIsoNeeded() + * is true. The base class implementation puts the edited unattended script + * onto it. + */ + virtual HRESULT prepareAuxIsoImage(bool fOverwrite); + + /** + * Opens the installation ISO image. + * + * @returns COM status code. + * @param phVfsIso Where to return the VFS handle for the ISO. + * @param fFlags RTFSISO9660_F_XXX flags to pass to the + * RTFsIso9660VolOpen API. + */ + virtual HRESULT openInstallIsoImage(PRTVFS phVfsIso, uint32_t fFlags = 0); + + /** + * Creates and configures the ISO maker instance. + * + * This can be overridden to set configure options. + * + * @returns COM status code. + * @param phIsoMaker Where to return the ISO maker. + */ + virtual HRESULT newAuxIsoImageMaker(PRTFSISOMAKER phIsoMaker); + + /** + * Adds files to the auxiliary ISO image maker. + * + * The base class implementation copies just the mMainScript and mPostScript + * files to root directory using the default filenames. + * + * @returns COM status code. + * @param hIsoMaker The ISO maker handle. + * @param hVfsOrgIso The VFS handle to the original ISO in case files + * needs to be added from it. + */ + virtual HRESULT addFilesToAuxIsoImageMaker(RTFSISOMAKER hIsoMaker, RTVFS hVfsOrgIso); + + /** + * Adds the given script to the ISO maker. + * + * @returns COM status code. + * @param pEditor The script to add. + * @param hIsoMaker The ISO maker to add it to. + * @param pszDstFilename The file name (w/ path) to add it under. If NULL, + * the default script filename is used to add it to the + * root. + */ + HRESULT addScriptToIsoMaker(BaseTextScript *pEditor, RTFSISOMAKER hIsoMaker, const char *pszDstFilename = NULL); + + /** + * Writes the ISO image to disk. + * + * @returns COM status code. + * @param hIsoMaker The ISO maker handle. + * @param pszFilename The filename. + * @param fOverwrite Whether to overwrite the destination file or not. + */ + HRESULT finalizeAuxIsoImage(RTFSISOMAKER hIsoMaker, const char *pszFilename, bool fOverwrite); + + /** + * Adds files to the .viso-file vectors. + * + * The base class implementation adds the script from mAlg, additions ISO + * content to '/vboxadditions', and validation kit ISO to '/vboxvalidationkit'. + * + * @returns COM status code. + * @param rVecArgs The ISO maker argument list that will be turned into + * a .viso-file. + * @param rVecFiles The list of files we've created. This is for + * cleaning up at the end. + * @param hVfsOrgIso The VFS handle to the original ISO in case files + * needs to be added from it. + * @param fOverwrite Whether to overwrite files or not. + */ + virtual HRESULT addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles, + RTVFS hVfsOrgIso, bool fOverwrite); + + /** + * Saves the given script to disk and adds it to the .viso-file vectors. + * + * @returns COM status code. + * @param pEditor The script to add. + * @param rVecArgs The ISO maker argument list that will be turned into + * a .viso-file. + * @param rVecFiles The list of files we've created. This is for + * cleaning up at the end. + * @param fOverwrite Whether to overwrite files or not. + */ + HRESULT addScriptToVisoVectors(BaseTextScript *pEditor, RTCList<RTCString> &rVecArgs, + RTCList<RTCString> &rVecFiles, bool fOverwrite); + + /** + * Writes out the .viso-file to disk. + * + * @returns COM status code. + * @param rVecArgs The ISO maker argument list to write out. + * @param pszFilename The filename. + * @param fOverwrite Whether to overwrite the destination file or not. + */ + HRESULT finalizeAuxVisoFile(RTCList<RTCString> const &rVecArgs, const char *pszFilename, bool fOverwrite); + + /** + * Loads @a pszFilename from @a hVfsOrgIso into @a pEditor and parses it. + * + * @returns COM status code. + * @param hVfsOrgIso The handle to the original installation ISO. + * @param pszFilename The filename to open and load from the ISO. + * @param pEditor The editor instance to load the file into and + * do the parseing with. + */ + HRESULT loadAndParseFileFromIso(RTVFS hVfsOrgIso, const char *pszFilename, AbstractScript *pEditor); +}; + + +/** + * Windows installer, for versions up to xp 64 / w2k3. + */ +class UnattendedWindowsSifInstaller : public UnattendedInstaller +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedWindowsSifInstaller) + + UnattendedWindowsSifInstaller(Unattended *pParent) + : UnattendedInstaller(pParent, + "win_nt5_unattended.sif", "win_postinstall.cmd", + "WINNT.SIF", "VBOXPOST.CMD") + { + Assert(isOriginalIsoNeeded()); Assert(isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); Assert(!bootFromAuxiliaryIso()); + mStrAuxiliaryInstallDir = "A:\\"; + } + ~UnattendedWindowsSifInstaller() {} + + bool isAuxiliaryFloppyNeeded() const { return true; } + bool bootFromAuxiliaryIso() const { return false; } + +}; + +/** + * Windows installer, for versions starting with Vista. + */ +class UnattendedWindowsXmlInstaller : public UnattendedInstaller +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedWindowsXmlInstaller) + + UnattendedWindowsXmlInstaller(Unattended *pParent) + : UnattendedInstaller(pParent, + "win_nt6_unattended.xml", "win_postinstall.cmd", + "autounattend.xml", "VBOXPOST.CMD") + { + Assert(isOriginalIsoNeeded()); Assert(isAuxiliaryFloppyNeeded() || isAuxiliaryIsoNeeded()); Assert(isAuxiliaryIsoIsVISO()); Assert(!bootFromAuxiliaryIso()); + if (isAuxiliaryFloppyNeeded()) + mStrAuxiliaryInstallDir = "A:\\"; + else if (bootFromAuxiliaryIso()) + mStrAuxiliaryInstallDir = "D:\\"; + else + mStrAuxiliaryInstallDir = "E:\\"; + } + ~UnattendedWindowsXmlInstaller() {} + + bool isAuxiliaryFloppyNeeded() const { return !mpParent->i_isFirmwareEFI(); } + bool isAuxiliaryIsoNeeded() const { return UnattendedInstaller::isAuxiliaryIsoNeeded() || mpParent->i_isFirmwareEFI(); } + bool isAuxiliaryIsoIsVISO() const { return true; } + bool bootFromAuxiliaryIso() const { return false; } +}; + + +/** + * OS/2 installer. + */ +class UnattendedOs2Installer : public UnattendedInstaller +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedOs2Installer) + + UnattendedOs2Installer(Unattended *pParent, Utf8Str const &rStrHints); + ~UnattendedOs2Installer() {} + + /* Remaster original ISO with auxiliary floppy used for el torito floppy emulation: */ + bool isOriginalIsoNeeded() const RT_OVERRIDE { return false; } + bool isAuxiliaryFloppyNeeded() const RT_OVERRIDE { return true; } + bool isAuxiliaryIsoNeeded() const RT_OVERRIDE { return true; } + +protected: + HRESULT replaceAuxFloppyImageBootSector(RTVFSFILE hVfsFile) RT_NOEXCEPT; + HRESULT newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile) RT_OVERRIDE; + HRESULT copyFilesToAuxFloppyImage(RTVFS hVfs) RT_OVERRIDE; + HRESULT addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles, + RTVFS hVfsOrgIso, bool fOverwrite) RT_OVERRIDE; + + HRESULT splitResponseFile() RT_NOEXCEPT; + + /** + * Splits up the given file into sub-files and writes them out with the auxilary + * path base as prefix. + * + * The source file contains @@VBOX_SPLITTER_START[filename]@@ and + * @@VBOX_SPLITTER_END[filename]@@ markup that is used to split it up. Any + * text between END and START tags are ignored and can be used for comments. + * + * @returns COM status code (error info set). + * @param pszFileToSplit The name of the file to split. + * @param rVecSplitFiles Vector where names of the sub-files are appended + * (without any path or prefix). + */ + HRESULT splitFile(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT; + + /** + * Splits up the given editor output into sub-files and writes them out with the + * auxilary path base as prefix. + * + * The source file contains @@VBOX_SPLITTER_START[filename]@@ and + * @@VBOX_SPLITTER_END[filename]@@ markup that is used to split it up. Any + * text between END and START tags are ignored and can be used for comments. + * + * @returns COM status code (error info set). + * @param pEditor The editor which output should be split. + * @param rVecSplitFiles Vector where names of the sub-files are appended + * (without any path or prefix). + */ + HRESULT splitFile(BaseTextScript *pEditor, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT; + + HRESULT splitFileInner(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles, + const char *pszSrc, size_t cbLeft) RT_NOEXCEPT; + + static int patchTestCfg(uint8_t *pbFile, size_t cbFile, const char *pszFilename, UnattendedOs2Installer *pThis); + static int patchOs2Ldr(uint8_t *pbFile, size_t cbFile, const char *pszFilename, UnattendedOs2Installer *pThis); + + /** The OS2SE20.SRC path ("\\OS2IMAGES"). */ + Utf8Str mStrOs2Images; + /** Files split out from os2_response_files.rsp (bare filenames, no paths). */ + RTCList<RTCString> mVecSplitFiles; +}; + + + +/** + * Base class for the unattended linux installers. + */ +class UnattendedLinuxInstaller : public UnattendedInstaller +{ +protected: + /** Array of linux parameter patterns that should be removed by editIsoLinuxCfg. + * The patterns are proceed by RTStrSimplePatternNMatch. */ + RTCList<RTCString, RTCString *> mArrStrRemoveInstallKernelParameters; + +public: + DECLARE_TRANSLATE_METHODS(UnattendedLinuxInstaller) + + UnattendedLinuxInstaller(Unattended *pParent, + const char *pszMainScriptTemplateName, const char *pszPostScriptTemplateName, + const char *pszMainScriptFilename, const char *pszPostScriptFilename = "vboxpostinstall.sh") + : UnattendedInstaller(pParent, + pszMainScriptTemplateName, pszPostScriptTemplateName, + pszMainScriptFilename, pszPostScriptFilename) {} + ~UnattendedLinuxInstaller() {} + + bool isAuxiliaryIsoNeeded() const { return true; } + +protected: + /** + * Performs basic edits on a isolinux.cfg file. + * + * @returns COM status code + * @param pEditor Editor with the isolinux.cfg file loaded and parsed. + */ + virtual HRESULT editIsoLinuxCfg(GeneralTextScript *pEditor); + /** + * Performs basic common edits on a isolinux.cfg and menu configuration file(s) (txt.cfg or menu.cfg etc). + * + * @returns COM status code + * @param pEditor Editor with the isolinux.cfg file loaded and parsed. + */ + virtual HRESULT editIsoLinuxCommon(GeneralTextScript *pEditor); +}; + + +/** + * Debian installer. + * + * This will remaster the orignal ISO and therefore be producing a .viso-file. + */ +class UnattendedDebianInstaller : public UnattendedLinuxInstaller +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedDebianInstaller) + + UnattendedDebianInstaller(Unattended *pParent, + const char *pszMainScriptTemplateName = "debian_preseed.cfg", + const char *pszPostScriptTemplateName = "debian_postinstall.sh", + const char *pszMainScriptFilename = "preseed.cfg") + : UnattendedLinuxInstaller(pParent, pszMainScriptTemplateName, pszPostScriptTemplateName, pszMainScriptFilename) + { + Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); + Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); + mStrDefaultExtraInstallKernelParameters.setNull(); + mStrDefaultExtraInstallKernelParameters += " auto=true"; + mStrDefaultExtraInstallKernelParameters.append(" preseed/file=/cdrom/").append(pszMainScriptFilename); + mStrDefaultExtraInstallKernelParameters += " priority=critical"; + mStrDefaultExtraInstallKernelParameters += " quiet"; + mStrDefaultExtraInstallKernelParameters += " splash"; + mStrDefaultExtraInstallKernelParameters += " noprompt"; /* no questions about things like CD/DVD ejections */ + mStrDefaultExtraInstallKernelParameters += " noshell"; /* No shells on VT1-3 (debian, not ubuntu). */ + mStrDefaultExtraInstallKernelParameters += " automatic-ubiquity"; // ubiquity + // the following can probably go into the preseed.cfg: + mStrDefaultExtraInstallKernelParameters.append(" debian-installer/locale=").append(pParent->i_getLocale()); + mStrDefaultExtraInstallKernelParameters += " keyboard-configuration/layoutcode=us"; + mStrDefaultExtraInstallKernelParameters += " languagechooser/language-name=English"; /** @todo fixme */ + mStrDefaultExtraInstallKernelParameters.append(" localechooser/supported-locales=").append(pParent->i_getLocale()).append(".UTF-8"); + mStrDefaultExtraInstallKernelParameters.append(" countrychooser/shortlist=").append(pParent->i_getCountry()); // ubiquity? + mStrDefaultExtraInstallKernelParameters += " --"; + } + ~UnattendedDebianInstaller() {} + + bool isOriginalIsoNeeded() const { return false; } + +protected: + HRESULT addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles, + RTVFS hVfsOrgIso, bool fOverwrite); + /** + * Performs basic edits on menu configuration file(s) of isolinux (txt.cfg or menu.cfg etc). + * + * @returns COM status code + * @param pEditor Editor with the menu config. file loaded and parsed. + */ + HRESULT editDebianMenuCfg(GeneralTextScript *pEditor); + /** + * Performs basic edits on grub configuration file (grub.cfg). + * + * @returns COM status code + * @param pEditor Editor with the grub.cfg file loaded and parsed. + */ + HRESULT editDebianGrubCfg(GeneralTextScript *pEditor); + + /** + * Performs basic edits on a isolinux.cfg file. + * + * @returns COM status code + * @param pEditor Editor with the isolinux.cfg file loaded and parsed. + * @param pszMenuConfigFileName Name of the menu config file to include in isolinux.txt. On Debians (at least) + it includes the kernel command line with our preseed file and command line argument. + */ + virtual HRESULT editIsoLinuxCfg(GeneralTextScript *pEditor, const char *pszMenuConfigFileName); + +private: + + /** + * Tries to set label name of a label line. + * + * @returns true if label line is found and label name can be set. + * @param pEditor Editor with the menu configuration file loaded and parsed. + * @param vecLineNumbers Indices of the label lines (within pEditor data). + * @param pszKeyWord The keyword searched within the original label name. + * @param pszNewLabelName The new name of the label. + */ + bool modifyLabelLine(GeneralTextScript *pEditor, const std::vector<size_t> &vecLineNumbers, + const char *pszKeyWord, const char *pszNewLabelName); +}; + + +/** + * Ubuntu installer (same as debian, except for the template). + */ +class UnattendedUbuntuInstaller : public UnattendedDebianInstaller +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedUbuntuInstaller) + + UnattendedUbuntuInstaller(Unattended *pParent) + : UnattendedDebianInstaller(pParent, "ubuntu_preseed.cfg") + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + ~UnattendedUbuntuInstaller() {} +}; + + +/** + * RHEL 6 installer. + * + * This serves as a base for the kickstart based installers. + */ +class UnattendedRhel6Installer : public UnattendedLinuxInstaller +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedRhel6Installer) + + UnattendedRhel6Installer(Unattended *pParent, + const char *pszMainScriptTemplateName = "redhat67_ks.cfg", + const char *pszPostScriptTemplateName = "redhat_postinstall.sh", + const char *pszMainScriptFilename = "ks.cfg") + : UnattendedLinuxInstaller(pParent, pszMainScriptTemplateName, pszPostScriptTemplateName, pszMainScriptFilename) + { + Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); + Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); + mStrDefaultExtraInstallKernelParameters.assign(" ks=cdrom:/").append(pszMainScriptFilename).append(' '); + mArrStrRemoveInstallKernelParameters.append("rd.live.check"); /* Disables the checkisomd5 step. Required for VISO. */ + } + ~UnattendedRhel6Installer() {} + + bool isAuxiliaryIsoIsVISO() { return true; } + bool isOriginalIsoNeeded() const { return false; } + +protected: + HRESULT addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles, + RTVFS hVfsOrgIso, bool fOverwrite); +}; + +/** + * RHEL 7 installer (same as RHEL 6). + * The class was added for better handling any possible subtle difference between RHEL6 and RHEL7. + */ +class UnattendedRhel7Installer : public UnattendedRhel6Installer +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedRhel7Installer) + + UnattendedRhel7Installer(Unattended *pParent) + : UnattendedRhel6Installer(pParent) + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + + UnattendedRhel7Installer(Unattended *pParent, + const char *pszMainScriptTemplateName, + const char *pszPostScriptTemplateName, + const char *pszMainScriptFilename) + : UnattendedRhel6Installer(pParent, pszMainScriptTemplateName, pszPostScriptTemplateName, pszMainScriptFilename) + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + ~UnattendedRhel7Installer() {} +}; + + +/** + * RHEL 8 installer (same as RHEL 7). + * The class was added for better handling any possible subtle difference between RHEL7 and RHEL8. + */ +class UnattendedRhel8Installer : public UnattendedRhel7Installer +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedRhel8Installer) + + UnattendedRhel8Installer(Unattended *pParent) + : UnattendedRhel7Installer(pParent) + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + + UnattendedRhel8Installer(Unattended *pParent, + const char *pszMainScriptTemplateName, + const char *pszPostScriptTemplateName, + const char *pszMainScriptFilename) + : UnattendedRhel7Installer(pParent, pszMainScriptTemplateName, pszPostScriptTemplateName, pszMainScriptFilename) + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + ~UnattendedRhel8Installer() {} +}; + + +/** + * RHEL 5 installer (same as RHEL 6, except for the kickstart template). + */ +class UnattendedRhel5Installer : public UnattendedRhel6Installer +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedRhel5Installer) + + UnattendedRhel5Installer(Unattended *pParent) : UnattendedRhel6Installer(pParent, "rhel5_ks.cfg") {} + ~UnattendedRhel5Installer() {} +}; + + +/** + * RHEL 4 installer (same as RHEL 6, except for the kickstart template). + */ +class UnattendedRhel4Installer : public UnattendedRhel6Installer +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedRhel4Installer) + + UnattendedRhel4Installer(Unattended *pParent) : UnattendedRhel6Installer(pParent, "rhel4_ks.cfg") {} + ~UnattendedRhel4Installer() {} +}; + + +/** + * RHEL 3 installer (same as RHEL 6, except for the kickstart template). + */ +class UnattendedRhel3Installer : public UnattendedRhel6Installer +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedRhel3Installer) + + UnattendedRhel3Installer(Unattended *pParent) : UnattendedRhel6Installer(pParent, "rhel3_ks.cfg") {} + ~UnattendedRhel3Installer() {} +}; + + +/** + * Fedora installer (same as RHEL 6, except for the template). + */ +class UnattendedFedoraInstaller : public UnattendedRhel6Installer +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedFedoraInstaller) + + UnattendedFedoraInstaller(Unattended *pParent) + : UnattendedRhel6Installer(pParent, "fedora_ks.cfg") + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + ~UnattendedFedoraInstaller() {} +}; + + +/** + * Oracle Linux 6 installer. Same as RHEL 6, except for the templates. + * The reason of adding new class is to sepatate the RHEL from OL. + */ +class UnattendedOracleLinux6Installer : public UnattendedRhel6Installer +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedOracleLinux6Installer) + + UnattendedOracleLinux6Installer(Unattended *pParent, + const char *pszMainScriptTemplateName = "ol_ks.cfg", + const char *pszPostScriptTemplateName = "ol_postinstall.sh", + const char *pszMainScriptFilename = "ks.cfg") + : UnattendedRhel6Installer(pParent, pszMainScriptTemplateName, pszPostScriptTemplateName, pszMainScriptFilename) + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + ~UnattendedOracleLinux6Installer() {} +}; + + +/** + * Oracle Linux 7 installer. Same as OL 6. + * The class was added for better handling any possible subtle difference between OL6 and OL7. + */ +class UnattendedOracleLinux7Installer : public UnattendedOracleLinux6Installer +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedOracleLinux7Installer) + + UnattendedOracleLinux7Installer(Unattended *pParent) + : UnattendedOracleLinux6Installer(pParent) + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + + UnattendedOracleLinux7Installer(Unattended *pParent, + const char *pszMainScriptTemplateName, + const char *pszPostScriptTemplateName, + const char *pszMainScriptFilename) + : UnattendedOracleLinux6Installer(pParent, pszMainScriptTemplateName, pszPostScriptTemplateName, pszMainScriptFilename) + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + ~UnattendedOracleLinux7Installer() {} +}; + + +/** + * Oracle Linux 8 installer. Same as OL 7. + * The class was added for better handling any possible subtle difference between OL7 and OL8. + */ +class UnattendedOracleLinux8Installer : public UnattendedOracleLinux7Installer +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedOracleLinux8Installer) + + UnattendedOracleLinux8Installer(Unattended *pParent) + : UnattendedOracleLinux7Installer(pParent) + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + + UnattendedOracleLinux8Installer(Unattended *pParent, + const char *pszMainScriptTemplateName, + const char *pszPostScriptTemplateName, + const char *pszMainScriptFilename) + : UnattendedOracleLinux7Installer(pParent, pszMainScriptTemplateName, pszPostScriptTemplateName, pszMainScriptFilename) + { Assert(!isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(isAuxiliaryIsoIsVISO()); } + ~UnattendedOracleLinux8Installer() {} +}; + +#if 0 /* fixme */ +/** + * SUSE linux installer. + * + * @todo needs fixing. + */ +class UnattendedSuseInstaller : public UnattendedLinuxInstaller +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedSuseInstaller) + + UnattendedSuseInstaller(BaseTextScript *pAlg, Unattended *pParent) + : UnattendedLinuxInstaller(pAlg, pParent, "suse_autoinstall.xml") + { Assert(isOriginalIsoNeeded()); Assert(isAuxiliaryIsoNeeded()); Assert(!isAuxiliaryFloppyNeeded()); Assert(!isAuxiliaryIsoIsVISO()); } + ~UnattendedSuseInstaller() {} + + HRESULT setupScriptOnAuxiliaryCD(const Utf8Str &path); +}; +#endif + +/** + * Base class for the unattended FreeBSD installers. + */ +class UnattendedFreeBsdInstaller : public UnattendedInstaller +{ +public: + UnattendedFreeBsdInstaller(Unattended *pParent) + : UnattendedInstaller(pParent, + "freebsd_installer.cfg", "freebsd_postinstall.sh", + "installerconfig", "vboxpostinstall.sh") {} + ~UnattendedFreeBsdInstaller() {} + + bool isAuxiliaryIsoNeeded() const { return true; } + bool isOriginalIsoNeeded() const { return false; } + +protected: + HRESULT addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles, + RTVFS hVfsOrgIso, bool fOverwrite); +}; + +#endif /* !MAIN_INCLUDED_UnattendedInstaller_h */ diff --git a/src/VBox/Main/include/UnattendedScript.h b/src/VBox/Main/include/UnattendedScript.h new file mode 100644 index 00000000..970a01af --- /dev/null +++ b/src/VBox/Main/include/UnattendedScript.h @@ -0,0 +1,193 @@ +/* $Id: UnattendedScript.h $ */ +/** @file + * Classes for reading/parsing/saving scripts for unattended installation. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_UnattendedScript_h +#define MAIN_INCLUDED_UnattendedScript_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "TextScript.h" +#include "iprt/expreval.h" + +using namespace xml; + +class Unattended; + + +/** + * Generic unattended text script template editor. + * + * This just perform variable replacements, no other editing possible. + * + * Everything happens during saveToString, parse is a noop. + */ +class UnattendedScriptTemplate : public BaseTextScript +{ +protected: + /** Where to get the replacement strings from. */ + Unattended *mpUnattended; + +public: + DECLARE_TRANSLATE_METHODS(UnattendedScriptTemplate) + + UnattendedScriptTemplate(Unattended *pUnattended, const char *pszDefaultTemplateFilename, const char *pszDefaultFilename); + virtual ~UnattendedScriptTemplate() {} + + HRESULT parse() { return S_OK; } + HRESULT saveToString(Utf8Str &rStrDst); + +protected: + typedef enum + { + kValueEscaping_None, + kValueEscaping_Bourne, + kValueEscaping_XML_Element, + kValueEscaping_XML_Attribute_Double_Quotes + } kEvalEscaping_T; + + /** + * Gets the replacement value for the given placeholder. + * + * @returns COM status code. + * @param pachPlaceholder The placholder string. Not zero terminated. + * @param cchPlaceholder The length of the placeholder. + * @param fOutputting Indicates whether we actually need the correct value + * or is just syntax checking excluded template parts. + * @param rValue Where to return the value. + */ + HRESULT getReplacement(const char *pachPlaceholder, size_t cchPlaceholder, bool fOutputting, RTCString &rValue); + + /** + * Gets the replacement value for the given expression placeholder + * (@@VBOX_INSERT[expr]@@ and friends). + * + * @returns COM status code. + * @param hEvaluator The evaluator to use for the expression. + * @param pachPlaceholder The placholder string. Not zero terminated. + * @param cchPlaceholder The length of the placeholder. + * @param fOutputting Indicates whether we actually need the correct value + * or is just syntax checking excluded template parts. + * @param ppszValue Where to return the value. Free by calling + * RTStrFree. Set to NULL for empty string. + */ + HRESULT getReplacementForExpr(RTEXPREVAL hEvaluator, const char *pachPlaceholder, size_t cchPlaceholder, + bool fOutputting, char **ppszValue) RT_NOEXCEPT; + + /** + * Resolves a conditional expression. + * + * @returns COM status code. + * @param hEvaluator The evaluator to use for the expression. + * @param pachPlaceholder The placholder string. Not zero terminated. + * @param cchPlaceholder The length of the placeholder. + * @param pfOutputting Where to return the result of the conditional. This + * holds the current outputting state on input in case + * someone want to sanity check anything. + */ + HRESULT resolveConditionalExpr(RTEXPREVAL hEvaluator, const char *pachPlaceholder, size_t cchPlaceholder, + bool *pfOutputting) RT_NOEXCEPT; + + /** @callback_method_impl{FNRTEXPREVALQUERYVARIABLE} */ + static DECLCALLBACK(int) queryVariableForExpr(const char *pchName, size_t cchName, void *pvUser, + char **ppszValue) RT_NOEXCEPT; + + /** + * Gets a variable. + * + * This is used both for getting replacements (@@VBOX_INSERT_XXX@@) and in + * expressions (@@VBOX_INSERT[expr]@@, @@VBOX_COND[expr]@@). + * + * @returns VBox status code. + * @retval VERR_NOT_FOUND if variable does not exist. + * + * @param pchName The variable name. Not zero terminated. + * @param cchName The length of the name. + * @param rstrTmp String object that can be used for keeping the + * value returned via @a *ppszValue. + * @param ppszValue If a value is desired, this is where to return + * it. This points to a string that should be + * accessible for a little while after the function + * returns. Use @a rstrTmp for storage if + * necessary. + * + * This will be NULL when called from the 'defined' + * operator. In which case no errors should be + * set. + * @throws std::bad_alloc + * @see FNRTEXPREVALQUERYVARIABLE + */ + virtual int queryVariable(const char *pchName, size_t cchName, Utf8Str &rstrTmp, const char **ppszValue); + + /** + * Get the result of a conditional. + * + * @returns COM status code. + * @param pachPlaceholder The placholder string. Not zero terminated. + * @param cchPlaceholder The length of the placeholder. + * @param pfOutputting Where to return the result of the conditional. + * This holds the current outputting state on input + * in case someone want to sanity check anything. + */ + virtual HRESULT getConditional(const char *pachPlaceholder, size_t cchPlaceholder, bool *pfOutputting); +}; + +#if 0 /* convert when we fix SUSE */ +/** + * SUSE unattended XML file editor. + */ +class UnattendedSUSEXMLScript : public UnattendedXMLScript +{ +public: + DECLARE_TRANSLATE_METHODS(UnattendedSUSEXMLScript) + + UnattendedSUSEXMLScript(VirtualBoxBase *pSetError, const char *pszDefaultFilename = "autoinst.xml") + : UnattendedXMLScript(pSetError, pszDefaultFilename) {} + ~UnattendedSUSEXMLScript() {} + + HRESULT parse(); + +protected: + HRESULT setFieldInElement(xml::ElementNode *pElement, const DataId enmDataId, const Utf8Str &rStrValue); + +private: + //////////////////New functions////////////////////////////// + /** @throws std::bad_alloc */ + HRESULT LoopThruSections(const xml::ElementNode *pelmRoot); + /** @throws std::bad_alloc */ + HRESULT HandleUserAccountsSection(const xml::ElementNode *pelmSection); + /** @throws std::bad_alloc */ + Utf8Str createProbableValue(const DataId enmDataId, const xml::ElementNode *pCurElem); + /** @throws std::bad_alloc */ + Utf8Str createProbableUserHomeDir(const xml::ElementNode *pCurElem); + //////////////////New functions////////////////////////////// +}; +#endif + + +#endif /* !MAIN_INCLUDED_UnattendedScript_h */ + diff --git a/src/VBox/Main/include/UpdateAgentImpl.h b/src/VBox/Main/include/UpdateAgentImpl.h new file mode 100644 index 00000000..db70fa43 --- /dev/null +++ b/src/VBox/Main/include/UpdateAgentImpl.h @@ -0,0 +1,220 @@ +/* $Id: UpdateAgentImpl.h $ */ +/** @file + * Update agent COM class implementation - Header + */ + +/* + * Copyright (C) 2020-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_UpdateAgentImpl_h +#define MAIN_INCLUDED_UpdateAgentImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/http.h> + +#include <VBox/settings.h> + +#include "EventImpl.h" +#include "UpdateAgentWrap.h" +#include "HostUpdateAgentWrap.h" + +class UpdateAgentTask; +struct UpdateAgentTaskParms; + +struct UpdateAgentTaskResult +{ + Utf8Str strVer; + Utf8Str strWebUrl; + Utf8Str strDownloadUrl; + UpdateSeverity_T enmSeverity; + Utf8Str strReleaseNotes; +}; + +class UpdateAgentBase +{ +protected: /* Not directly instancable. */ + + UpdateAgentBase() + : m_VirtualBox(NULL) + , m(new settings::UpdateAgent) { } + + virtual ~UpdateAgentBase() { delete m; } + +public: + + /** @name Pure virtual public methods for internal purposes only + * (ensure there is a caller and a read lock before calling them!) + * @{ */ + virtual HRESULT i_loadSettings(const settings::UpdateAgent &data) = 0; + virtual HRESULT i_saveSettings(settings::UpdateAgent &data) = 0; + + virtual HRESULT i_setCheckCount(ULONG aCount) = 0; + virtual HRESULT i_setLastCheckDate(const com::Utf8Str &aDate) = 0; + /** @} */ + +protected: + + /** @name Pure virtual internal task callbacks. + * @{ */ + friend UpdateAgentTask; + virtual DECLCALLBACK(HRESULT) i_checkForUpdateTask(UpdateAgentTask *pTask) = 0; + /** @} */ + + /** @name Static helper methods. + * @{ */ + static Utf8Str i_getPlatformInfo(void); + const char *i_proxyModeToStr(ProxyMode_T enmMode); + bool i_urlSchemeIsSupported(const Utf8Str &strUrl) const; + /** @} */ + +protected: + /** The update agent's event source. */ + const ComObjPtr<EventSource> m_EventSource; + VirtualBox * const m_VirtualBox; + + /** @name Data members. + * @{ */ + settings::UpdateAgent *m; + + struct Data + { + UpdateAgentTaskResult m_lastResult; + Utf8Str m_strName; + /** Vector of update channels this agent supports. */ + const std::vector<UpdateChannel_T> m_enmChannels; + bool m_fHidden; + UpdateState_T m_enmState; + uint32_t m_uOrder; + + Data(void) + { + m_fHidden = true; + m_enmState = UpdateState_Invalid; + m_uOrder = UINT32_MAX; + } + } mData; + /** @} */ +}; + +class ATL_NO_VTABLE UpdateAgent : + public UpdateAgentWrap, + public UpdateAgentBase +{ +public: + DECLARE_COMMON_CLASS_METHODS(UpdateAgent) + + /** @name COM and internal init/term/mapping cruft. + * @{ */ + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT init(VirtualBox *aVirtualBox); + void uninit(void); + /** @} */ + + /** @name Public methods for internal purposes only + * (ensure there is a caller and a read lock before calling them!) + * @{ */ + HRESULT i_loadSettings(const settings::UpdateAgent &data); + HRESULT i_saveSettings(settings::UpdateAgent &data); + + virtual HRESULT i_setCheckCount(ULONG aCount); + virtual HRESULT i_setLastCheckDate(const com::Utf8Str &aDate); + /** @} */ + +protected: + + /** @name Internal helper methods. + * @{ */ + HRESULT i_getProxyMode(ProxyMode_T *aMode); + HRESULT i_getProxyURL(com::Utf8Str &aAddress); + HRESULT i_configureProxy(RTHTTP hHttp); + HRESULT i_commitSettings(AutoWriteLock &aLock); + HRESULT i_reportError(int vrc, const char *pcszMsgFmt, ...); + /** @} */ + +protected: + /** @name Wrapped IUpdateAgent attributes and methods. + * @{ */ + HRESULT checkFor(ComPtr<IProgress> &aProgress); + HRESULT download(ComPtr<IProgress> &aProgress); + HRESULT install(ComPtr<IProgress> &aProgress); + HRESULT rollback(void); + + HRESULT getName(com::Utf8Str &aName); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + HRESULT getOrder(ULONG *aOrder); + HRESULT getDependsOn(std::vector<com::Utf8Str> &aDeps); + HRESULT getVersion(com::Utf8Str &aVer); + HRESULT getDownloadUrl(com::Utf8Str &aUrl); + HRESULT getWebUrl(com::Utf8Str &aUrl); + HRESULT getReleaseNotes(com::Utf8Str &aRelNotes); + HRESULT getEnabled(BOOL *aEnabled); + HRESULT setEnabled(BOOL aEnabled); + HRESULT getHidden(BOOL *aHidden); + HRESULT getState(UpdateState_T *aState); + HRESULT getCheckCount(ULONG *aCount); + HRESULT getCheckFrequency(ULONG *aFreqSeconds); + HRESULT setCheckFrequency(ULONG aFreqSeconds); + HRESULT getChannel(UpdateChannel_T *aChannel); + HRESULT setChannel(UpdateChannel_T aChannel); + HRESULT getRepositoryURL(com::Utf8Str &aRepo); + HRESULT setRepositoryURL(const com::Utf8Str &aRepo); + HRESULT getLastCheckDate(com::Utf8Str &aData); + HRESULT getIsCheckNeeded(BOOL *aCheckNeeded); + HRESULT getSupportedChannels(std::vector<UpdateChannel_T> &aSupportedChannels); + /** @} */ +}; + +/** @todo Put this into an own module, e.g. HostUpdateAgentImpl.[cpp|h]. */ + +class ATL_NO_VTABLE HostUpdateAgent : + public UpdateAgent +{ +public: + /** @name COM and internal init/term/mapping cruft. + * @{ */ + DECLARE_COMMON_CLASS_METHODS(HostUpdateAgent) + + HRESULT init(VirtualBox *aVirtualBox); + void uninit(void); + + HRESULT FinalConstruct(void); + void FinalRelease(void); + /** @} */ + +private: + /** @name Implemented (pure) virtual methods from UpdateAgent. + * @{ */ + HRESULT checkFor(ComPtr<IProgress> &aProgress); + + DECLCALLBACK(HRESULT) i_checkForUpdateTask(UpdateAgentTask *pTask); + /** @} */ + + HRESULT i_checkForUpdate(void); + HRESULT i_checkForUpdateInner(RTHTTP hHttp, com::Utf8Str const &strUrl, com::Utf8Str const &strUserAgent); +}; + +#endif /* !MAIN_INCLUDED_UpdateAgentImpl_h */ + diff --git a/src/VBox/Main/include/UsbCardReader.h b/src/VBox/Main/include/UsbCardReader.h new file mode 100644 index 00000000..1071ecf4 --- /dev/null +++ b/src/VBox/Main/include/UsbCardReader.h @@ -0,0 +1,87 @@ +/* $Id: UsbCardReader.h $ */ + +/** @file + * VirtualBox Driver interface to the virtual Usb Card Reader. + */ + +/* + * Copyright (C) 2011-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_UsbCardReader_h +#define MAIN_INCLUDED_UsbCardReader_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/vmm/pdmcardreaderinfs.h> +#include <VBox/vmm/pdmdrv.h> + +#define USBCARDREADER_OID "46225eac-10c9-4b57-92b6-e59efd48009f" + +class Console; +typedef struct USBCARDREADER USBCARDREADER; +typedef struct UCRREMOTE UCRREMOTE; + +class UsbCardReader +{ + public: + UsbCardReader(Console *console); + virtual ~UsbCardReader(); + + static const PDMDRVREG DrvReg; + USBCARDREADER *mpDrv; + + Console *getParent(void) { return mParent; } + + int VRDENotify(uint32_t u32Id, void *pvData, uint32_t cbData); + int VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Function, void *pvData, uint32_t cbData); + + int EstablishContext(USBCARDREADER *pDrv); + int ReleaseContext(USBCARDREADER *pDrv); + int GetStatusChange(USBCARDREADER *pDrv, void *pvUser, uint32_t u32Timeout, + PDMICARDREADER_READERSTATE *paReaderStats, uint32_t cReaderStats); + int Connect(USBCARDREADER *pDrv, void *pvUser, const char *pszReaderName, + uint32_t u32ShareMode, uint32_t u32PreferredProtocols); + int Disconnect(USBCARDREADER *pDrv, void *pvUser, uint32_t u32Mode); + int Status(USBCARDREADER *pDrv, void *pvUser); + int Transmit(USBCARDREADER *pDrv, void *pvUser, PDMICARDREADER_IO_REQUEST *pioSendRequest, + uint8_t *pu8SendBuffer, uint32_t cbSendBuffer, uint32_t cbRecvBuffer); + int Control(USBCARDREADER *pDrv, void *pvUser, uint32_t u32ControlCode, + uint8_t *pu8InBuffer, uint32_t cbInBuffer, uint32_t cbOutBuffer); + int GetAttrib(USBCARDREADER *pDrv, void *pvUser, uint32_t u32AttrId, uint32_t cbAttrib); + int SetAttrib(USBCARDREADER *pDrv, void *pvUser, uint32_t u32AttrId, + uint8_t *pu8Attrib, uint32_t cbAttrib); + + private: + static DECLCALLBACK(void *) drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); + static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns); + + int vrdeSCardRequest(void *pvUser, uint32_t u32Function, const void *pvData, uint32_t cbData); + + Console * const mParent; + + UCRREMOTE *m_pRemote; +}; + +#endif /* !MAIN_INCLUDED_UsbCardReader_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/UsbWebcamInterface.h b/src/VBox/Main/include/UsbWebcamInterface.h new file mode 100644 index 00000000..bedb5a2b --- /dev/null +++ b/src/VBox/Main/include/UsbWebcamInterface.h @@ -0,0 +1,79 @@ +/* $Id: UsbWebcamInterface.h $ */ +/** @file + * VirtualBox PDM Driver for Emulated USB Webcam + */ + +/* + * Copyright (C) 2011-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_UsbWebcamInterface_h +#define MAIN_INCLUDED_UsbWebcamInterface_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/vmm/pdmdrv.h> +#define VRDE_VIDEOIN_WITH_VRDEINTERFACE /* Get the VRDE interface definitions. */ +#include <VBox/RemoteDesktop/VRDEVideoIn.h> + +class ConsoleVRDPServer; +typedef struct EMWEBCAMDRV EMWEBCAMDRV; +typedef struct EMWEBCAMREMOTE EMWEBCAMREMOTE; + +class EmWebcam +{ + public: + EmWebcam(ConsoleVRDPServer *pServer); + virtual ~EmWebcam(); + + static const PDMDRVREG DrvReg; + + void EmWebcamConstruct(EMWEBCAMDRV *pDrv); + void EmWebcamDestruct(EMWEBCAMDRV *pDrv); + + /* Callbacks. */ + void EmWebcamCbNotify(uint32_t u32Id, const void *pvData, uint32_t cbData); + void EmWebcamCbDeviceDesc(int rcRequest, void *pDeviceCtx, void *pvUser, + const VRDEVIDEOINDEVICEDESC *pDeviceDesc, uint32_t cbDeviceDesc); + void EmWebcamCbControl(int rcRequest, void *pDeviceCtx, void *pvUser, + const VRDEVIDEOINCTRLHDR *pControl, uint32_t cbControl); + void EmWebcamCbFrame(int rcRequest, void *pDeviceCtx, + const VRDEVIDEOINPAYLOADHDR *pFrame, uint32_t cbFrame); + + /* Methods for the PDM driver. */ + int SendControl(EMWEBCAMDRV *pDrv, void *pvUser, uint64_t u64DeviceId, + const VRDEVIDEOINCTRLHDR *pControl, uint32_t cbControl); + + private: + static DECLCALLBACK(void *) drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); + static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns); + + ConsoleVRDPServer * const mParent; + + EMWEBCAMDRV *mpDrv; + EMWEBCAMREMOTE *mpRemote; + uint64_t volatile mu64DeviceIdSrc; +}; + +#endif /* !MAIN_INCLUDED_UsbWebcamInterface_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/VBoxNls.h b/src/VBox/Main/include/VBoxNls.h new file mode 100644 index 00000000..7f8aae2f --- /dev/null +++ b/src/VBox/Main/include/VBoxNls.h @@ -0,0 +1,65 @@ +/* $Id: VBoxNls.h $ */ +/** @file + * VBox NLS. + */ + +/* + * Copyright (C) 2020-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +#ifndef MAIN_INCLUDED_VBoxNls_h +#define MAIN_INCLUDED_VBoxNls_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifdef VBOX_WITH_MAIN_NLS + +#include <VBox/com/defs.h> +#include <VBox/com/ptr.h> +#include <VBox/com/string.h> +#include "VirtualBoxTranslator.h" + + +# define DECLARE_TRANSLATION_CONTEXT(ctx) \ +struct ctx \ +{\ + static const char *tr(const char *pszSource, const char *pszComment = NULL, const size_t aNum = ~(size_t)0) \ + { \ + return VirtualBoxTranslator::translate(NULL, #ctx, pszSource, pszComment, aNum); \ + } \ +} +#else +# define DECLARE_TRANSLATION_CONTEXT(ctx) \ +struct ctx \ +{\ + static const char *tr(const char *pszSource, const char *pszComment = NULL, const size_t aNum = ~(size_t)0) \ + { \ + NOREF(pszComment); \ + NOREF(aNum); \ + return pszSource; \ + } \ +} +#endif + +#endif /* !MAIN_INCLUDED_VBoxNls_h */ + diff --git a/src/VBox/Main/include/VFSExplorerImpl.h b/src/VBox/Main/include/VFSExplorerImpl.h new file mode 100644 index 00000000..b3b0b5c3 --- /dev/null +++ b/src/VBox/Main/include/VFSExplorerImpl.h @@ -0,0 +1,101 @@ +/* $Id: VFSExplorerImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2009-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_VFSExplorerImpl_h +#define MAIN_INCLUDED_VFSExplorerImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VFSExplorerWrap.h" + +class ATL_NO_VTABLE VFSExplorer : + public VFSExplorerWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(VFSExplorer) + + // public initializer/uninitializer for internal purposes only + HRESULT FinalConstruct() { return BaseFinalConstruct(); } + void FinalRelease() { uninit(); BaseFinalRelease(); } + + HRESULT init(VFSType_T aType, Utf8Str aFilePath, Utf8Str aHostname, Utf8Str aUsername, Utf8Str aPassword, VirtualBox *aVirtualBox); + void uninit(); + + /* public methods only for internal purposes */ + static HRESULT setErrorStatic(HRESULT aResultCode, const char *aText, ...) + { + va_list va; + va_start(va, aText); + HRESULT hrc = setErrorInternalV(aResultCode, getStaticClassIID(), getStaticComponentName(), aText, va, false, true); + va_end(va); + return hrc; + } + +private: + + // wrapped IVFSExplorer properties + HRESULT getPath(com::Utf8Str &aPath); + HRESULT getType(VFSType_T *aType); + + // wrapped IVFSExplorer methods + HRESULT update(ComPtr<IProgress> &aProgress); + HRESULT cd(const com::Utf8Str &aDir, ComPtr<IProgress> &aProgress); + HRESULT cdUp(ComPtr<IProgress> &aProgress); + HRESULT entryList(std::vector<com::Utf8Str> &aNames, + std::vector<ULONG> &aTypes, + std::vector<LONG64> &aSizes, + std::vector<ULONG> &aModes); + HRESULT exists(const std::vector<com::Utf8Str> &aNames, + std::vector<com::Utf8Str> &aExists); + HRESULT remove(const std::vector<com::Utf8Str> &aNames, + ComPtr<IProgress> &aProgress); + + /* Private member vars */ + VirtualBox * const mVirtualBox; + + //////////////////////////////////////////////////////////////////////////////// + //// + //// VFSExplorer definitions + //// + ////////////////////////////////////////////////////////////////////////////////// + // + class TaskVFSExplorer; /* Worker thread helper */ + struct Data; + Data *m; + + /* Private member methods */ + FsObjType_T i_iprtToVfsObjType(RTFMODE aType) const; + + HRESULT i_updateFS(TaskVFSExplorer *aTask); + HRESULT i_deleteFS(TaskVFSExplorer *aTask); + +}; + +#endif /* !MAIN_INCLUDED_VFSExplorerImpl_h */ + diff --git a/src/VBox/Main/include/VMMDev.h b/src/VBox/Main/include/VMMDev.h new file mode 100644 index 00000000..864e7c2e --- /dev/null +++ b/src/VBox/Main/include/VMMDev.h @@ -0,0 +1,115 @@ +/* $Id: VMMDev.h $ */ +/** @file + * VirtualBox Driver interface to VMM device + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_VMMDev_h +#define MAIN_INCLUDED_VMMDev_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxBase.h" +#include <VBox/vmm/pdmdrv.h> +#include <VBox/hgcmsvc.h> +#include <iprt/asm.h> + +class Console; + +class VMMDevMouseInterface +{ +public: + virtual ~VMMDevMouseInterface() { /* Make VC++ 19.2 happy. */ } + virtual PPDMIVMMDEVPORT getVMMDevPort() = 0; +}; + +class VMMDev : public VMMDevMouseInterface +{ +public: + VMMDev(Console *console); + virtual ~VMMDev(); + static const PDMDRVREG DrvReg; + /** Pointer to the associated VMMDev driver. */ + struct DRVMAINVMMDEV *mpDrv; + + bool fSharedFolderActive; + bool isShFlActive() + { + return fSharedFolderActive; + } + + Console *getParent() + { + return mParent; + } + + int WaitCredentialsJudgement (uint32_t u32Timeout, uint32_t *pu32GuestFlags); + int SetCredentialsJudgementResult (uint32_t u32Flags); + + PPDMIVMMDEVPORT getVMMDevPort(); + +#ifdef VBOX_WITH_HGCM + int hgcmLoadService (const char *pszServiceLibrary, const char *pszServiceName); + int hgcmHostCall (const char *pszServiceName, uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms); + void hgcmShutdown(bool fUvmIsInvalid = false); + + bool hgcmIsActive (void) { return ASMAtomicReadBool(&m_fHGCMActive); } +#endif /* VBOX_WITH_HGCM */ + +private: +#ifdef VBOX_WITH_HGCM +# ifdef VBOX_WITH_GUEST_PROPS + void i_guestPropSetMultiple(void *names, void *values, void *timestamps, void *flags); + void i_guestPropSet(const char *pszName, const char *pszValue, const char *pszFlags); + int i_guestPropSetGlobalPropertyFlags(uint32_t fFlags); + int i_guestPropLoadAndConfigure(); +# endif +#endif + static DECLCALLBACK(void *) drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); + static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); + static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns); + static DECLCALLBACK(void) drvReset(PPDMDRVINS pDrvIns); + static DECLCALLBACK(void) drvPowerOn(PPDMDRVINS pDrvIns); + static DECLCALLBACK(void) drvPowerOff(PPDMDRVINS pDrvIns); + static DECLCALLBACK(void) drvSuspend(PPDMDRVINS pDrvIns); + static DECLCALLBACK(void) drvResume(PPDMDRVINS pDrvIns); + static DECLCALLBACK(int) hgcmSave(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM); + static DECLCALLBACK(int) hgcmLoad(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass); + + Console * const mParent; + + RTSEMEVENT mCredentialsEvent; + uint32_t mu32CredentialsFlags; + +#ifdef VBOX_WITH_HGCM + bool volatile m_fHGCMActive; +#endif /* VBOX_WITH_HGCM */ +}; + +/** VMMDev object ID used by Console::i_vmm2User_QueryGenericObject and VMMDev::drvConstruct. */ +#define VMMDEV_OID "e2ff0c7b-c02b-46d0-aa90-b9caf0f60561" + +#endif /* !MAIN_INCLUDED_VMMDev_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/VRDEServerImpl.h b/src/VBox/Main/include/VRDEServerImpl.h new file mode 100644 index 00000000..04a6e78f --- /dev/null +++ b/src/VBox/Main/include/VRDEServerImpl.h @@ -0,0 +1,98 @@ +/* $Id: VRDEServerImpl.h $ */ + +/** @file + * + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_VRDEServerImpl_h +#define MAIN_INCLUDED_VRDEServerImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VRDEServerWrap.h" + +namespace settings +{ + struct VRDESettings; +} + +class ATL_NO_VTABLE VRDEServer : + public VRDEServerWrap +{ +public: + + DECLARE_COMMON_CLASS_METHODS(VRDEServer) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(Machine *aParent); + HRESULT init(Machine *aParent, VRDEServer *aThat); + HRESULT initCopy(Machine *aParent, VRDEServer *aThat); + void uninit(); + + // public methods only for internal purposes + HRESULT i_loadSettings(const settings::VRDESettings &data); + HRESULT i_saveSettings(settings::VRDESettings &data); + void i_rollback(); + void i_commit(); + void i_copyFrom(VRDEServer *aThat); + +private: + + // wrapped IVRDEServer properties + HRESULT getEnabled(BOOL *aEnabled); + HRESULT setEnabled(BOOL aEnabled); + HRESULT getAuthType(AuthType_T *aAuthType); + HRESULT setAuthType(AuthType_T aAuthType); + HRESULT getAuthTimeout(ULONG *aAuthTimeout); + HRESULT setAuthTimeout(ULONG aAuthTimeout); + HRESULT getAllowMultiConnection(BOOL *aAllowMultiConnection); + HRESULT setAllowMultiConnection(BOOL aAllowMultiConnection); + HRESULT getReuseSingleConnection(BOOL *aReuseSingleConnection); + HRESULT setReuseSingleConnection(BOOL aReuseSingleConnection); + HRESULT getVRDEExtPack(com::Utf8Str &aVRDEExtPack); + HRESULT setVRDEExtPack(const com::Utf8Str &aVRDEExtPack); + HRESULT getAuthLibrary(com::Utf8Str &aAuthLibrary); + HRESULT setAuthLibrary(const com::Utf8Str &aAuthLibrary); + HRESULT getVRDEProperties(std::vector<com::Utf8Str> &aVRDEProperties); + + // wrapped IVRDEServer methods + HRESULT setVRDEProperty(const com::Utf8Str &aKey, + const com::Utf8Str &aValue); + HRESULT getVRDEProperty(const com::Utf8Str &aKey, + com::Utf8Str &aValue); + + Machine * const mParent; + const ComObjPtr<VRDEServer> mPeer; + + Backupable<settings::VRDESettings> mData; +}; + +#endif /* !MAIN_INCLUDED_VRDEServerImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/VirtualBoxBase.h b/src/VBox/Main/include/VirtualBoxBase.h new file mode 100644 index 00000000..4a92a871 --- /dev/null +++ b/src/VBox/Main/include/VirtualBoxBase.h @@ -0,0 +1,1118 @@ +/* $Id: VirtualBoxBase.h $ */ +/** @file + * VirtualBox COM base classes definition + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_VirtualBoxBase_h +#define MAIN_INCLUDED_VirtualBoxBase_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/cdefs.h> +#include <iprt/thread.h> + +#include <list> +#include <map> + +#include "ObjectState.h" + +#include "VBox/com/AutoLock.h" +#include "VBox/com/string.h" +#include "VBox/com/Guid.h" + +#include "VBox/com/VirtualBox.h" + +#include "VirtualBoxTranslator.h" + +// avoid including VBox/settings.h and VBox/xml.h; only declare the classes +namespace xml +{ +class File; +} + +namespace com +{ +class ErrorInfo; +} + +using namespace com; +using namespace util; + +class VirtualBox; +class Machine; +class Medium; +class Host; +typedef std::list<ComObjPtr<Medium> > MediaList; +typedef std::list<Utf8Str> StringsList; + +//////////////////////////////////////////////////////////////////////////////// +// +// COM helpers +// +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(VBOX_WITH_XPCOM) + +/* use a special version of the singleton class factory, + * see KB811591 in msdn for more info. */ + +#undef DECLARE_CLASSFACTORY_SINGLETON +#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(CMyComClassFactorySingleton<obj>) + +/** + * @todo r=bird: This CMyComClassFactorySingleton stuff is probably obsoleted by + * microatl.h? Right? + */ + +template <class T> +class CMyComClassFactorySingleton : public ATL::CComClassFactory +{ +public: + CMyComClassFactorySingleton() : + m_hrCreate(S_OK), m_spObj(NULL) + { + } + virtual ~CMyComClassFactorySingleton() + { + if (m_spObj) + m_spObj->Release(); + } + // IClassFactory + STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) + { + HRESULT hRes = E_POINTER; + if (ppvObj != NULL) + { + *ppvObj = NULL; + // no aggregation for singletons + AssertReturn(pUnkOuter == NULL, CLASS_E_NOAGGREGATION); + if (m_hrCreate == S_OK && m_spObj == NULL) + { + Lock(); + __try + { + // Fix: The following If statement was moved inside the __try statement. + // Did another thread arrive here first? + if (m_hrCreate == S_OK && m_spObj == NULL) + { + // lock the module to indicate activity + // (necessary for the monitor shutdown thread to correctly + // terminate the module in case when CreateInstance() fails) + ATL::_pAtlModule->Lock(); + ATL::CComObjectCached<T> *p; + m_hrCreate = ATL::CComObjectCached<T>::CreateInstance(&p); + if (SUCCEEDED(m_hrCreate)) + { + m_hrCreate = p->QueryInterface(IID_IUnknown, (void **)&m_spObj); + if (FAILED(m_hrCreate)) + { + delete p; + } + } + ATL::_pAtlModule->Unlock(); + } + } + __finally + { + Unlock(); + } + } + if (m_hrCreate == S_OK) + { + hRes = m_spObj->QueryInterface(riid, ppvObj); + } + else + { + hRes = m_hrCreate; + } + } + return hRes; + } + HRESULT m_hrCreate; + IUnknown *m_spObj; +}; + +#endif /* !defined(VBOX_WITH_XPCOM) */ + +//////////////////////////////////////////////////////////////////////////////// +// +// Macros +// +//////////////////////////////////////////////////////////////////////////////// + +/** + * Special version of the Assert macro to be used within VirtualBoxBase + * subclasses. + * + * In the debug build, this macro is equivalent to Assert. + * In the release build, this macro uses |setError(E_FAIL, ...)| to set the + * error info from the asserted expression. + * + * @see VirtualBoxBase::setError + * + * @param expr Expression which should be true. + */ +#define ComAssert(expr) \ + do { \ + if (RT_LIKELY(!!(expr))) \ + { /* likely */ } \ + else \ + { \ + AssertMsgFailed(("%s\n", #expr)); \ + setError(E_FAIL, \ + VirtualBoxBase::tr("Assertion failed: [%s] at '%s' (%d) in %s.\nPlease contact the product vendor!"), \ + #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + } \ + } while (0) + +/** + * Special version of the AssertFailed macro to be used within VirtualBoxBase + * subclasses. + * + * In the debug build, this macro is equivalent to AssertFailed. + * In the release build, this macro uses |setError(E_FAIL, ...)| to set the + * error info from the asserted expression. + * + * @see VirtualBoxBase::setError + * + */ +#define ComAssertFailed() \ + do { \ + AssertFailed(); \ + setError(E_FAIL, \ + VirtualBoxBase::tr("Assertion failed: at '%s' (%d) in %s.\nPlease contact the product vendor!"), \ + __FILE__, __LINE__, __PRETTY_FUNCTION__); \ + } while (0) + +/** + * Special version of the AssertMsg macro to be used within VirtualBoxBase + * subclasses. + * + * See ComAssert for more info. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#define ComAssertMsg(expr, a) \ + do { \ + if (RT_LIKELY(!!(expr))) \ + { /* likely */ } \ + else \ + { \ + Utf8StrFmt MyAssertMsg a; /* may throw bad_alloc */ \ + AssertMsgFailed(("%s\n", MyAssertMsg.c_str())); \ + setError(E_FAIL, \ + VirtualBoxBase::tr("Assertion failed: [%s] at '%s' (%d) in %s.\n%s.\nPlease contact the product vendor!"), \ + #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__, MyAssertMsg.c_str()); \ + } \ + } while (0) + +/** + * Special version of the AssertMsgFailed macro to be used within VirtualBoxBase + * subclasses. + * + * See ComAssert for more info. + * + * @param a printf argument list (in parenthesis). + */ +#define ComAssertMsgFailed(a) \ + do { \ + Utf8StrFmt MyAssertMsg a; /* may throw bad_alloc */ \ + AssertMsgFailed(("%s\n", MyAssertMsg.c_str())); \ + setError(E_FAIL, \ + VirtualBoxBase::tr("Assertion failed: at '%s' (%d) in %s.\n%s.\nPlease contact the product vendor!"), \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, MyAssertMsg.c_str()); \ + } while (0) + +/** + * Special version of the AssertRC macro to be used within VirtualBoxBase + * subclasses. + * + * See ComAssert for more info. + * + * @param vrc VBox status code. + */ +#define ComAssertRC(vrc) ComAssertMsgRC(vrc, ("%Rra", vrc)) + +/** + * Special version of the AssertMsgRC macro to be used within VirtualBoxBase + * subclasses. + * + * See ComAssert for more info. + * + * @param vrc VBox status code. + * @param msg printf argument list (in parenthesis). + */ +#define ComAssertMsgRC(vrc, msg) ComAssertMsg(RT_SUCCESS(vrc), msg) + +/** + * Special version of the AssertComRC macro to be used within VirtualBoxBase + * subclasses. + * + * See ComAssert for more info. + * + * @param hrc COM result code + */ +#define ComAssertComRC(hrc) ComAssertMsg(SUCCEEDED(hrc), ("COM RC=%Rhrc (0x%08X)", (hrc), (hrc))) + + +/** Special version of ComAssert that returns ret if expr fails */ +#define ComAssertRet(expr, ret) \ + do { ComAssert(expr); if (!(expr)) return (ret); } while (0) +/** Special version of ComAssertMsg that returns ret if expr fails */ +#define ComAssertMsgRet(expr, a, ret) \ + do { ComAssertMsg(expr, a); if (!(expr)) return (ret); } while (0) +/** Special version of ComAssertRC that returns ret if vrc does not succeed */ +#define ComAssertRCRet(vrc, ret) \ + do { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) return (ret); } while (0) +/** Special version of ComAssertComRC that returns ret if rc does not succeed */ +#define ComAssertComRCRet(rc, ret) \ + do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (ret); } while (0) +/** Special version of ComAssertComRC that returns rc if rc does not succeed */ +#define ComAssertComRCRetRC(rc) \ + do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (rc); } while (0) +/** Special version of ComAssertFailed that returns ret */ +#define ComAssertFailedRet(ret) \ + do { ComAssertFailed(); return (ret); } while (0) +/** Special version of ComAssertMsgFailed that returns ret */ +#define ComAssertMsgFailedRet(msg, ret) \ + do { ComAssertMsgFailed(msg); return (ret); } while (0) + + +/** Special version of ComAssert that returns void if expr fails */ +#define ComAssertRetVoid(expr) \ + do { ComAssert(expr); if (!(expr)) return; } while (0) +/** Special version of ComAssertMsg that returns void if expr fails */ +#define ComAssertMsgRetVoid(expr, a) \ + do { ComAssertMsg(expr, a); if (!(expr)) return; } while (0) +/** Special version of ComAssertRC that returns void if vrc does not succeed */ +#define ComAssertRCRetVoid(vrc) \ + do { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) return; } while (0) +/** Special version of ComAssertComRC that returns void if rc does not succeed */ +#define ComAssertComRCRetVoid(rc) \ + do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return; } while (0) +/** Special version of ComAssertFailed that returns void */ +#define ComAssertFailedRetVoid() \ + do { ComAssertFailed(); return; } while (0) +/** Special version of ComAssertMsgFailed that returns void */ +#define ComAssertMsgFailedRetVoid(msg) \ + do { ComAssertMsgFailed(msg); return; } while (0) + + +/** Special version of ComAssert that evaluates eval and breaks if expr fails */ +#define ComAssertBreak(expr, eval) \ + if (1) { ComAssert(expr); if (!(expr)) { eval; break; } } else do {} while (0) +/** Special version of ComAssertMsg that evaluates eval and breaks if expr fails */ +#define ComAssertMsgBreak(expr, a, eval) \ + if (1) { ComAssertMsg(expr, a); if (!(expr)) { eval; break; } } else do {} while (0) +/** Special version of ComAssertRC that evaluates eval and breaks if vrc does not succeed */ +#define ComAssertRCBreak(vrc, eval) \ + if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { eval; break; } } else do {} while (0) +/** Special version of ComAssertFailed that evaluates eval and breaks */ +#define ComAssertFailedBreak(eval) \ + if (1) { ComAssertFailed(); { eval; break; } } else do {} while (0) +/** Special version of ComAssertMsgFailed that evaluates eval and breaks */ +#define ComAssertMsgFailedBreak(msg, eval) \ + if (1) { ComAssertMsgFailed (msg); { eval; break; } } else do {} while (0) +/** Special version of ComAssertComRC that evaluates eval and breaks if rc does not succeed */ +#define ComAssertComRCBreak(rc, eval) \ + if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { eval; break; } } else do {} while (0) +/** Special version of ComAssertComRC that just breaks if rc does not succeed */ +#define ComAssertComRCBreakRC(rc) \ + if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { break; } } else do {} while (0) + + +/** Special version of ComAssert that evaluates eval and throws it if expr fails */ +#define ComAssertThrow(expr, eval) \ + do { ComAssert(expr); if (!(expr)) { throw (eval); } } while (0) +/** Special version of ComAssertRC that evaluates eval and throws it if vrc does not succeed */ +#define ComAssertRCThrow(vrc, eval) \ + do { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { throw (eval); } } while (0) +/** Special version of ComAssertComRC that evaluates eval and throws it if rc does not succeed */ +#define ComAssertComRCThrow(rc, eval) \ + do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw (eval); } } while (0) +/** Special version of ComAssertComRC that just throws rc if rc does not succeed */ +#define ComAssertComRCThrowRC(rc) \ + do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw rc; } } while (0) +/** Special version of ComAssert that throws eval */ +#define ComAssertFailedThrow(eval) \ + do { ComAssertFailed(); { throw (eval); } } while (0) + +//////////////////////////////////////////////////////////////////////////////// + +/** + * Checks that the pointer argument is not NULL and returns E_INVALIDARG + + * extended error info on failure. + * @param arg Input pointer-type argument (strings, interface pointers...) + */ +#define CheckComArgNotNull(arg) \ + do { \ + if (RT_LIKELY((arg) != NULL)) \ + { /* likely */ }\ + else \ + return setError(E_INVALIDARG, VirtualBoxBase::tr("Argument %s is NULL"), #arg); \ + } while (0) + +/** + * Checks that the pointer argument is a valid pointer or NULL and returns + * E_INVALIDARG + extended error info on failure. + * @param arg Input pointer-type argument (strings, interface pointers...) + */ +#define CheckComArgMaybeNull(arg) \ + do { \ + if (RT_LIKELY(RT_VALID_PTR(arg) || (arg) == NULL)) \ + { /* likely */ }\ + else \ + return setError(E_INVALIDARG, \ + VirtualBoxBase::tr("Argument %s is an invalid pointer"), #arg); \ + } while (0) + +/** + * Checks that the given pointer to an argument is valid and returns + * E_POINTER + extended error info otherwise. + * @param arg Pointer argument. + */ +#define CheckComArgPointerValid(arg) \ + do { \ + if (RT_LIKELY(RT_VALID_PTR(arg))) \ + { /* likely */ }\ + else \ + return setError(E_POINTER, \ + VirtualBoxBase::tr("Argument %s points to invalid memory location (%p)"), \ + #arg, (void *)(arg)); \ + } while (0) + +/** + * Checks that safe array argument is not NULL and returns E_INVALIDARG + + * extended error info on failure. + * @param arg Input safe array argument (strings, interface pointers...) + */ +#define CheckComArgSafeArrayNotNull(arg) \ + do { \ + if (RT_LIKELY(!ComSafeArrayInIsNull(arg))) \ + { /* likely */ }\ + else \ + return setError(E_INVALIDARG, \ + VirtualBoxBase::tr("Argument %s is NULL"), #arg); \ + } while (0) + +/** + * Checks that a string input argument is valid (not NULL or obviously invalid + * pointer), returning E_INVALIDARG + extended error info if invalid. + * @param a_bstrIn Input string argument (IN_BSTR). + */ +#define CheckComArgStr(a_bstrIn) \ + do { \ + IN_BSTR const bstrInCheck = (a_bstrIn); /* type check */ \ + if (RT_LIKELY(RT_VALID_PTR(bstrInCheck))) \ + { /* likely */ }\ + else \ + return setError(E_INVALIDARG, \ + VirtualBoxBase::tr("Argument %s is an invalid pointer"), #a_bstrIn); \ + } while (0) +/** + * Checks that the string argument is not a NULL, a invalid pointer or an empty + * string, returning E_INVALIDARG + extended error info on failure. + * @param a_bstrIn Input string argument (BSTR etc.). + */ +#define CheckComArgStrNotEmptyOrNull(a_bstrIn) \ + do { \ + IN_BSTR const bstrInCheck = (a_bstrIn); /* type check */ \ + if (RT_LIKELY(RT_VALID_PTR(bstrInCheck) && *(bstrInCheck) != '\0')) \ + { /* likely */ }\ + else \ + return setError(E_INVALIDARG, \ + VirtualBoxBase::tr("Argument %s is empty or an invalid pointer"), \ + #a_bstrIn); \ + } while (0) + +/** + * Converts the Guid input argument (string) to a Guid object, returns with + * E_INVALIDARG and error message on failure. + * + * @param a_Arg Argument. + * @param a_GuidVar The Guid variable name. + */ +#define CheckComArgGuid(a_Arg, a_GuidVar) \ + do { \ + Guid tmpGuid(a_Arg); \ + (a_GuidVar) = tmpGuid; \ + if (RT_LIKELY((a_GuidVar).isValid())) \ + { /* likely */ }\ + else \ + return setError(E_INVALIDARG, \ + VirtualBoxBase::tr("GUID argument %s is not valid (\"%ls\")"), \ + #a_Arg, Bstr(a_Arg).raw()); \ + } while (0) + +/** + * Checks that the given expression (that must involve the argument) is true and + * returns E_INVALIDARG + extended error info on failure. + * @param arg Argument. + * @param expr Expression to evaluate. + */ +#define CheckComArgExpr(arg, expr) \ + do { \ + if (RT_LIKELY(!!(expr))) \ + { /* likely */ }\ + else \ + return setError(E_INVALIDARG, \ + VirtualBoxBase::tr("Argument %s is invalid (must be %s)"), \ + #arg, #expr); \ + } while (0) + +/** + * Checks that the given expression (that must involve the argument) is true and + * returns E_INVALIDARG + extended error info on failure. The error message must + * be customized. + * @param arg Argument. + * @param expr Expression to evaluate. + * @param msg Parenthesized printf-like expression (must start with a verb, + * like "must be one of...", "is not within..."). + */ +#define CheckComArgExprMsg(arg, expr, msg) \ + do { \ + if (RT_LIKELY(!!(expr))) \ + { /* likely */ }\ + else \ + return setError(E_INVALIDARG, VirtualBoxBase::tr("Argument %s %s"), \ + #arg, Utf8StrFmt msg .c_str()); \ + } while (0) + +/** + * Checks that the given pointer to an output argument is valid and returns + * E_POINTER + extended error info otherwise. + * @param arg Pointer argument. + */ +#define CheckComArgOutPointerValid(arg) \ + do { \ + if (RT_LIKELY(RT_VALID_PTR(arg))) \ + { /* likely */ }\ + else \ + return setError(E_POINTER, \ + VirtualBoxBase::tr("Output argument %s points to invalid memory location (%p)"), \ + #arg, (void *)(arg)); \ + } while (0) + +/** + * Checks that the given pointer to an output safe array argument is valid and + * returns E_POINTER + extended error info otherwise. + * @param arg Safe array argument. + */ +#define CheckComArgOutSafeArrayPointerValid(arg) \ + do { \ + if (RT_LIKELY(!ComSafeArrayOutIsNull(arg))) \ + { /* likely */ }\ + else \ + return setError(E_POINTER, \ + VirtualBoxBase::tr("Output argument %s points to invalid memory location (%p)"), \ + #arg, (void*)(arg)); \ + } while (0) + +/** + * Sets the extended error info and returns E_NOTIMPL. + */ +#define ReturnComNotImplemented() \ + do { \ + return setError(E_NOTIMPL, VirtualBoxBase::tr("Method %s is not implemented"), __FUNCTION__); \ + } while (0) + +/** + * Declares an empty constructor and destructor for the given class. + * This is useful to prevent the compiler from generating the default + * ctor and dtor, which in turn allows to use forward class statements + * (instead of including their header files) when declaring data members of + * non-fundamental types with constructors (which are always called implicitly + * by constructors and by the destructor of the class). + * + * This macro is to be placed within (the public section of) the class + * declaration. Its counterpart, DEFINE_EMPTY_CTOR_DTOR, must be placed + * somewhere in one of the translation units (usually .cpp source files). + * + * @param cls class to declare a ctor and dtor for + */ +#define DECLARE_EMPTY_CTOR_DTOR(cls) cls(); virtual ~cls(); + +/** + * Defines an empty constructor and destructor for the given class. + * See DECLARE_EMPTY_CTOR_DTOR for more info. + */ +#define DEFINE_EMPTY_CTOR_DTOR(cls) \ + cls::cls() { /*empty*/ } \ + cls::~cls() { /*empty*/ } + +/** + * A variant of 'throw' that hits a debug breakpoint first to make + * finding the actual thrower possible. + */ +#ifdef DEBUG +# define DebugBreakThrow(a) \ + do { \ + RTAssertDebugBreak(); \ + throw (a); \ + } while (0) +#else +# define DebugBreakThrow(a) throw (a) +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +// VirtualBoxBase +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef VBOX_WITH_MAIN_NLS +# define DECLARE_TRANSLATE_METHODS(cls) \ + static inline const char *tr(const char *aSourceText, \ + const char *aComment = NULL, \ + const size_t aNum = ~(size_t)0) \ + { \ + return VirtualBoxTranslator::translate(NULL, #cls, aSourceText, aComment, aNum); \ + } +#else +# define DECLARE_TRANSLATE_METHODS(cls) \ + static inline const char *tr(const char *aSourceText, \ + const char *aComment = NULL, \ + const size_t aNum = ~(size_t)0) \ + { \ + RT_NOREF(aComment, aNum); \ + return aSourceText; \ + } +#endif + +#define DECLARE_COMMON_CLASS_METHODS(cls) \ + DECLARE_EMPTY_CTOR_DTOR(cls) \ + DECLARE_TRANSLATE_METHODS(cls) + +#define VIRTUALBOXBASE_ADD_VIRTUAL_COMPONENT_METHODS(cls, iface) \ + virtual const IID& getClassIID() const \ + { \ + return cls::getStaticClassIID(); \ + } \ + static const IID& getStaticClassIID() \ + { \ + return COM_IIDOF(iface); \ + } \ + virtual const char* getComponentName() const \ + { \ + return cls::getStaticComponentName(); \ + } \ + static const char* getStaticComponentName() \ + { \ + return #cls; \ + } + +/** + * VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT: + * This macro must be used once in the declaration of any class derived + * from VirtualBoxBase. It implements the pure virtual getClassIID() and + * getComponentName() methods. If this macro is not present, instances + * of a class derived from VirtualBoxBase cannot be instantiated. + * + * @param cls The class name, e.g. "Class". + * @param iface The interface name which this class implements, e.g. "IClass". + */ +#ifdef VBOX_WITH_XPCOM + #define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(cls, iface) \ + VIRTUALBOXBASE_ADD_VIRTUAL_COMPONENT_METHODS(cls, iface) +#else // !VBOX_WITH_XPCOM + #define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(cls, iface) \ + VIRTUALBOXBASE_ADD_VIRTUAL_COMPONENT_METHODS(cls, iface) \ + STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) \ + { \ + const ATL::_ATL_INTMAP_ENTRY* pEntries = cls::_GetEntries(); \ + Assert(pEntries); \ + if (!pEntries) \ + return S_FALSE; \ + BOOL bSupports = FALSE; \ + BOOL bISupportErrorInfoFound = FALSE; \ + while (pEntries->pFunc != NULL && !bSupports) \ + { \ + if (!bISupportErrorInfoFound) \ + bISupportErrorInfoFound = InlineIsEqualGUID(*(pEntries->piid), IID_ISupportErrorInfo); \ + else \ + bSupports = InlineIsEqualGUID(*(pEntries->piid), riid); \ + pEntries++; \ + } \ + Assert(bISupportErrorInfoFound); \ + return bSupports ? S_OK : S_FALSE; \ + } +#endif // !VBOX_WITH_XPCOM + +/** + * VBOX_TWEAK_INTERFACE_ENTRY: + * Macro for defining magic interface entries needed for all interfaces + * implemented by any subclass of VirtualBoxBase. + */ +#ifdef VBOX_WITH_XPCOM +#define VBOX_TWEAK_INTERFACE_ENTRY(iface) +#else // !VBOX_WITH_XPCOM +#define VBOX_TWEAK_INTERFACE_ENTRY(iface) \ + COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.m_p) +#endif // !VBOX_WITH_XPCOM + + +/** + * Abstract base class for all component classes implementing COM + * interfaces of the VirtualBox COM library. + * + * Declares functionality that should be available in all components. + * + * The object state logic is documented in ObjectState.h. + */ +class ATL_NO_VTABLE VirtualBoxBase + : public Lockable + , public ATL::CComObjectRootEx<ATL::CComMultiThreadModel> +#if !defined (VBOX_WITH_XPCOM) + , public ISupportErrorInfo +#endif +{ +protected: +#ifdef RT_OS_WINDOWS + ComPtr<IUnknown> m_pUnkMarshaler; +#endif + + HRESULT BaseFinalConstruct(); + void BaseFinalRelease(); + +public: + DECLARE_COMMON_CLASS_METHODS(VirtualBoxBase) + + /** + * Uninitialization method. + * + * Must be called by all final implementations (component classes) when the + * last reference to the object is released, before calling the destructor. + * + * @note Never call this method the AutoCaller scope or after the + * ObjectState::addCaller() call not paired by + * ObjectState::releaseCaller() because it is a guaranteed deadlock. + * See AutoUninitSpan and AutoCaller.h/ObjectState.h for details. + */ + virtual void uninit() + { } + + /** + */ + ObjectState &getObjectState() + { + return mState; + } + + /** + * Pure virtual method for simple run-time type identification without + * having to enable C++ RTTI. + * + * This *must* be implemented by every subclass deriving from VirtualBoxBase; + * use the VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT macro to do that most easily. + */ + virtual const IID& getClassIID() const = 0; + + /** + * Pure virtual method for simple run-time type identification without + * having to enable C++ RTTI. + * + * This *must* be implemented by every subclass deriving from VirtualBoxBase; + * use the VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT macro to do that most easily. + */ + virtual const char* getComponentName() const = 0; + + /** + * Virtual method which determines the locking class to be used for validating + * lock order with the standard member lock handle. This method is overridden + * in a number of subclasses. + */ + virtual VBoxLockingClass getLockingClass() const + { + return LOCKCLASS_OTHEROBJECT; + } + + virtual RWLockHandle *lockHandle() const; + + static HRESULT handleUnexpectedExceptions(VirtualBoxBase *const aThis, RT_SRC_POS_DECL); + + static HRESULT setErrorInternalF(HRESULT aResultCode, + const GUID &aIID, + const char *aComponent, + bool aWarning, + bool aLogIt, + LONG aResultDetail, + const char *aText, ...); + static HRESULT setErrorInternalV(HRESULT aResultCode, + const GUID &aIID, + const char *aComponent, + const char *aText, + va_list aArgs, + bool aWarning, + bool aLogIt, + LONG aResultDetail = 0); + static void clearError(void); + + HRESULT setError(HRESULT aResultCode); + HRESULT setError(HRESULT aResultCode, const char *pcsz, ...); + HRESULT setError(const ErrorInfo &ei); + HRESULT setErrorVrcV(int vrc, const char *pcszMsgFmt, va_list va_args); + HRESULT setErrorVrc(int vrc); + HRESULT setErrorVrc(int vrc, const char *pcszMsgFmt, ...); + HRESULT setErrorBoth(HRESULT hrc, int vrc); + HRESULT setErrorBoth(HRESULT hrc, int vrc, const char *pcszMsgFmt, ...); + HRESULT setWarning(HRESULT aResultCode, const char *pcsz, ...); + HRESULT setErrorNoLog(HRESULT aResultCode, const char *pcsz, ...); + + + /** Initialize COM for a new thread. */ + static HRESULT initializeComForThread(void) + { +#ifndef VBOX_WITH_XPCOM + HRESULT hrc = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE | COINIT_SPEED_OVER_MEMORY); + AssertComRCReturn(hrc, hrc); +#endif + return S_OK; + } + + /** Uninitializes COM for a dying thread. */ + static void uninitializeComForThread(void) + { +#ifndef VBOX_WITH_XPCOM + CoUninitialize(); +#endif + } + + +private: + /** Object for representing object state */ + ObjectState mState; + + /** User-level object lock for subclasses */ + RWLockHandle *mObjectLock; + + /** Slot of this object in the g_aClassFactoryStats array */ + uint32_t iFactoryStat; + +private: + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(VirtualBoxBase); /* Shuts up MSC warning C4625. */ +}; + +/** Structure for counting the currently existing and ever created objects + * for each component name. */ +typedef struct CLASSFACTORY_STAT +{ + const char *psz; + uint64_t current; + uint64_t overall; +} CLASSFACTORY_STAT; + +/** Maximum number of component names to deal with. There will be debug + * assertions if the value is too low. Since the table is global and its + * entries are reasonably small, it's not worth squeezing out the last bit. */ +#define CLASSFACTORYSTATS_MAX 128 + +/* global variables (defined in VirtualBoxBase.cpp) */ +extern CLASSFACTORY_STAT g_aClassFactoryStats[CLASSFACTORYSTATS_MAX]; +extern RWLockHandle *g_pClassFactoryStatsLock; + +extern void APIDumpComponentFactoryStats(); + +/** + * Dummy macro that is used to shut down Qt's lupdate tool warnings in some + * situations. This macro needs to be present inside (better at the very + * beginning) of the declaration of the class that uses translation, to make + * lupdate happy. + */ +#define Q_OBJECT + +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// + + +/** + * Simple template that manages data structure allocation/deallocation + * and supports data pointer sharing (the instance that shares the pointer is + * not responsible for memory deallocation as opposed to the instance that + * owns it). + */ +template <class D> +class Shareable +{ +public: + + Shareable() : mData(NULL), mIsShared(FALSE) {} + virtual ~Shareable() { free(); } + + void allocate() { attach(new D); } + + virtual void free() { + if (mData) { + if (!mIsShared) + delete mData; + mData = NULL; + mIsShared = false; + } + } + + void attach(D *d) { + AssertMsg(d, ("new data must not be NULL")); + if (d && mData != d) { + if (mData && !mIsShared) + delete mData; + mData = d; + mIsShared = false; + } + } + + void attach(Shareable &d) { + AssertMsg( + d.mData == mData || !d.mIsShared, + ("new data must not be shared") + ); + if (this != &d && !d.mIsShared) { + attach(d.mData); + d.mIsShared = true; + } + } + + void share(D *d) { + AssertMsg(d, ("new data must not be NULL")); + if (mData != d) { + if (mData && !mIsShared) + delete mData; + mData = d; + mIsShared = true; + } + } + + void share(const Shareable &d) { share(d.mData); } + + void attachCopy(const D *d) { + AssertMsg(d, ("data to copy must not be NULL")); + if (d) + attach(new D(*d)); + } + + void attachCopy(const Shareable &d) { + attachCopy(d.mData); + } + + virtual D *detach() { + D *d = mData; + mData = NULL; + mIsShared = false; + return d; + } + + D *data() const { + return mData; + } + + D *operator->() const { + AssertMsg(mData, ("data must not be NULL")); + return mData; + } + + bool isNull() const { return mData == NULL; } + bool operator!() const { return isNull(); } + + bool isShared() const { return mIsShared; } + +protected: + + D *mData; + bool mIsShared; +}; + +/** + * Simple template that enhances Shareable<> and supports data + * backup/rollback/commit (using the copy constructor of the managed data + * structure). + */ +template<class D> +class Backupable : public Shareable<D> +{ +public: + + Backupable() : Shareable<D>(), mBackupData(NULL) {} + + void free() + { + AssertMsg(this->mData || !mBackupData, ("backup must be NULL if data is NULL")); + rollback(); + Shareable<D>::free(); + } + + D *detach() + { + AssertMsg(this->mData || !mBackupData, ("backup must be NULL if data is NULL")); + rollback(); + return Shareable<D>::detach(); + } + + void share(const Backupable &d) + { + AssertMsg(!d.isBackedUp(), ("data to share must not be backed up")); + if (!d.isBackedUp()) + Shareable<D>::share(d.mData); + } + + /** + * Stores the current data pointer in the backup area, allocates new data + * using the copy constructor on current data and makes new data active. + * + * @deprecated Use backupEx to avoid throwing wild out-of-memory exceptions. + */ + void backup() + { + AssertMsg(this->mData, ("data must not be NULL")); + if (this->mData && !mBackupData) + { + D *pNewData = new D(*this->mData); + mBackupData = this->mData; + this->mData = pNewData; + } + } + + /** + * Stores the current data pointer in the backup area, allocates new data + * using the copy constructor on current data and makes new data active. + * + * @returns S_OK, E_OUTOFMEMORY or E_FAIL (internal error). + */ + HRESULT backupEx() + { + AssertMsgReturn(this->mData, ("data must not be NULL"), E_FAIL); + if (this->mData && !mBackupData) + { + try + { + D *pNewData = new D(*this->mData); + mBackupData = this->mData; + this->mData = pNewData; + } + catch (std::bad_alloc &) + { + return E_OUTOFMEMORY; + } + } + return S_OK; + } + + /** + * Deletes new data created by #backup() and restores previous data pointer + * stored in the backup area, making it active again. + */ + void rollback() + { + if (this->mData && mBackupData) + { + delete this->mData; + this->mData = mBackupData; + mBackupData = NULL; + } + } + + /** + * Commits current changes by deleting backed up data and clearing up the + * backup area. The new data pointer created by #backup() remains active + * and becomes the only managed pointer. + * + * This method is much faster than #commitCopy() (just a single pointer + * assignment operation), but makes the previous data pointer invalid + * (because it is freed). For this reason, this method must not be + * used if it's possible that data managed by this instance is shared with + * some other Shareable instance. See #commitCopy(). + */ + void commit() + { + if (this->mData && mBackupData) + { + if (!this->mIsShared) + delete mBackupData; + mBackupData = NULL; + this->mIsShared = false; + } + } + + /** + * Commits current changes by assigning new data to the previous data + * pointer stored in the backup area using the assignment operator. + * New data is deleted, the backup area is cleared and the previous data + * pointer becomes active and the only managed pointer. + * + * This method is slower than #commit(), but it keeps the previous data + * pointer valid (i.e. new data is copied to the same memory location). + * For that reason it's safe to use this method on instances that share + * managed data with other Shareable instances. + */ + void commitCopy() + { + if (this->mData && mBackupData) + { + *mBackupData = *(this->mData); + delete this->mData; + this->mData = mBackupData; + mBackupData = NULL; + } + } + + void assignCopy(const D *pData) + { + AssertMsg(this->mData, ("data must not be NULL")); + AssertMsg(pData, ("data to copy must not be NULL")); + if (this->mData && pData) + { + if (!mBackupData) + { + D *pNewData = new D(*pData); + mBackupData = this->mData; + this->mData = pNewData; + } + else + *this->mData = *pData; + } + } + + void assignCopy(const Backupable &d) + { + assignCopy(d.mData); + } + + bool isBackedUp() const + { + return mBackupData != NULL; + } + + D *backedUpData() const + { + return mBackupData; + } + +protected: + + D *mBackupData; +}; + +#endif /* !MAIN_INCLUDED_VirtualBoxBase_h */ + diff --git a/src/VBox/Main/include/VirtualBoxClientImpl.h b/src/VBox/Main/include/VirtualBoxClientImpl.h new file mode 100644 index 00000000..ad39811c --- /dev/null +++ b/src/VBox/Main/include/VirtualBoxClientImpl.h @@ -0,0 +1,144 @@ +/* $Id: VirtualBoxClientImpl.h $ */ +/** @file + * Header file for the VirtualBoxClient (IVirtualBoxClient) class, VBoxC. + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_VirtualBoxClientImpl_h +#define MAIN_INCLUDED_VirtualBoxClientImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxClientWrap.h" +#include "EventImpl.h" +#include "VirtualBoxTranslator.h" + +#ifdef RT_OS_WINDOWS +# include "win/resource.h" +#endif + +class ATL_NO_VTABLE VirtualBoxClient : + public VirtualBoxClientWrap +#ifdef RT_OS_WINDOWS + , public ATL::CComCoClass<VirtualBoxClient, &CLSID_VirtualBoxClient> +#endif +{ +public: + DECLARE_CLASSFACTORY_SINGLETON(VirtualBoxClient) + + // Do not use any ATL registry support. + //DECLARE_REGISTRY_RESOURCEID(IDR_VIRTUALBOX) + + DECLARE_NOT_AGGREGATABLE(VirtualBoxClient) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(); + void uninit(); + +#ifdef RT_OS_WINDOWS + /* HACK ALERT! Implemented in dllmain.cpp. */ + ULONG InternalRelease(); +#endif + +private: + // wrapped IVirtualBoxClient properties + virtual HRESULT getVirtualBox(ComPtr<IVirtualBox> &aVirtualBox); + virtual HRESULT getSession(ComPtr<ISession> &aSession); + virtual HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + + // wrapped IVirtualBoxClient methods + virtual HRESULT checkMachineError(const ComPtr<IMachine> &aMachine); + + /** Instance counter for simulating something similar to a singleton. + * Only the first instance will be a usable object, all additional + * instances will return a failure at creation time and will not work. */ + static uint32_t g_cInstances; + +#ifdef RT_OS_WINDOWS + virtual HRESULT i_investigateVirtualBoxObjectCreationFailure(HRESULT hrc); +#endif + +#ifdef VBOX_WITH_SDS + int i_getServiceAccountAndStartType(const wchar_t *pwszServiceName, + wchar_t *pwszAccountName, size_t cwcAccountName, uint32_t *puStartType); +#endif + + static DECLCALLBACK(int) SVCWatcherThread(RTTHREAD ThreadSelf, void *pvUser); + + struct Data + { + Data() + : m_ThreadWatcher(NIL_RTTHREAD) + , m_SemEvWatcher(NIL_RTSEMEVENT) +#ifdef VBOX_WITH_MAIN_NLS + , m_pVBoxTranslator(NULL) + , m_pTrComponent(NULL) +#endif + {} + + ~Data() + { + /* HACK ALERT! This is for DllCanUnloadNow(). */ + if (m_pEventSource.isNotNull()) + { + s_cUnnecessaryAtlModuleLocks--; + AssertMsg(s_cUnnecessaryAtlModuleLocks == 0, ("%d\n", s_cUnnecessaryAtlModuleLocks)); + } + } + + ComPtr<IVirtualBox> m_pVirtualBox; + ComPtr<IToken> m_pToken; + const ComObjPtr<EventSource> m_pEventSource; + ComPtr<IEventSource> m_pVBoxEventSource; + ComPtr<IEventListener> m_pVBoxEventListener; + + RTTHREAD m_ThreadWatcher; + RTSEMEVENT m_SemEvWatcher; +#ifdef VBOX_WITH_MAIN_NLS + VirtualBoxTranslator *m_pVBoxTranslator; + PTRCOMPONENT m_pTrComponent; +#endif + }; + + Data mData; + +public: + /** Hack for discounting the AtlModule lock held by Data::m_pEventSource during + * DllCanUnloadNow(). This is incremented to 1 when init() initialized + * m_pEventSource and is decremented by the Data destructor (above). */ + static LONG s_cUnnecessaryAtlModuleLocks; + +#ifdef VBOX_WITH_MAIN_NLS + HRESULT i_reloadApiLanguage(); + HRESULT i_registerEventListener(); + void i_unregisterEventListener(); +#endif +}; + +#endif /* !MAIN_INCLUDED_VirtualBoxClientImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h b/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h new file mode 100644 index 00000000..62f98436 --- /dev/null +++ b/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h @@ -0,0 +1,175 @@ +/* $Id: VirtualBoxErrorInfoImpl.h $ */ +/** @file + * VirtualBoxErrorInfo COM class definition. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_VirtualBoxErrorInfoImpl_h +#define MAIN_INCLUDED_VirtualBoxErrorInfoImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxBase.h" + +using namespace com; + +class ATL_NO_VTABLE VirtualBoxErrorInfo + : public ATL::CComObjectRootEx<ATL::CComMultiThreadModel> + , VBOX_SCRIPTABLE_IMPL(IVirtualBoxErrorInfo) +#ifndef VBOX_WITH_XPCOM /* IErrorInfo doesn't inherit from IDispatch, ugly 3am hack: */ + , public IDispatch +#endif +{ +public: + + DECLARE_NOT_AGGREGATABLE(VirtualBoxErrorInfo) + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(VirtualBoxErrorInfo) + COM_INTERFACE_ENTRY(IErrorInfo) + COM_INTERFACE_ENTRY(IVirtualBoxErrorInfo) + COM_INTERFACE_ENTRY(IDispatch) + COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler) + END_COM_MAP() + + DECLARE_TRANSLATE_METHODS(VirtualBoxErrorInfo) + + HRESULT FinalConstruct() + { +#ifndef VBOX_WITH_XPCOM + return CoCreateFreeThreadedMarshaler((IUnknown *)(void *)this, &m_pUnkMarshaler); +#else + return S_OK; +#endif + } + + void FinalRelease() + { +#ifndef VBOX_WITH_XPCOM + if (m_pUnkMarshaler) + { + m_pUnkMarshaler->Release(); + m_pUnkMarshaler = NULL; + } +#endif + } + +#ifndef VBOX_WITH_XPCOM + + HRESULT init(IErrorInfo *aInfo); + + STDMETHOD(GetGUID)(GUID *guid); + STDMETHOD(GetSource)(BSTR *pBstrSource); + 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); + } + + STDMETHOD(GetIDsOfNames)(REFIID rIID, LPOLESTR *papwszNames, UINT cNames, LCID Lcid, DISPID *paDispIDs) + { + return idi::GetIDsOfNames(rIID, papwszNames, cNames, Lcid, paDispIDs); + } + + 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(VBOX_WITH_XPCOM) + + HRESULT init(nsIException *aInfo); + + NS_DECL_NSIEXCEPTION + +#endif + + VirtualBoxErrorInfo() + : m_resultCode(S_OK), + m_resultDetail(0) + {} + virtual ~VirtualBoxErrorInfo() {} + + // public initializer/uninitializer for internal purposes only + HRESULT init(HRESULT aResultCode, + const GUID &aIID, + const char *pcszComponent, + const Utf8Str &strText, + IVirtualBoxErrorInfo *aNext = NULL); + + HRESULT initEx(HRESULT aResultCode, + LONG aResultDetail, + const GUID &aIID, + const char *pcszComponent, + const Utf8Str &strText, + IVirtualBoxErrorInfo *aNext = NULL); + + HRESULT init(const com::ErrorInfo &ei, + IVirtualBoxErrorInfo *aNext = NULL); + + // IVirtualBoxErrorInfo properties + STDMETHOD(COMGETTER(ResultCode))(LONG *aResultCode); + STDMETHOD(COMGETTER(ResultDetail))(LONG *aResultDetail); + STDMETHOD(COMGETTER(InterfaceID))(BSTR *aIID); + STDMETHOD(COMGETTER(Component))(BSTR *aComponent); + STDMETHOD(COMGETTER(Text))(BSTR *aText); + STDMETHOD(COMGETTER(Next))(IVirtualBoxErrorInfo **aNext); + + const char* getComponentName() const { return "VirtualBoxErrorInfo"; } + +private: + static HRESULT setError(HRESULT rc, + const char * /* a */, + const char * /* b */, + void * /* c */) { return rc; } + + HRESULT m_resultCode; + LONG m_resultDetail; + Utf8Str m_strText; + Guid m_IID; + Utf8Str m_strComponent; + ComPtr<IVirtualBoxErrorInfo> mNext; + +#ifndef VBOX_WITH_XPCOM + IUnknown *m_pUnkMarshaler; +#endif +}; + +#endif /* !MAIN_INCLUDED_VirtualBoxErrorInfoImpl_h */ + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/VirtualBoxImpl.h b/src/VBox/Main/include/VirtualBoxImpl.h new file mode 100644 index 00000000..b0bc6250 --- /dev/null +++ b/src/VBox/Main/include/VirtualBoxImpl.h @@ -0,0 +1,502 @@ +/* $Id: VirtualBoxImpl.h $ */ +/** @file + * VirtualBox COM class implementation + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_VirtualBoxImpl_h +#define MAIN_INCLUDED_VirtualBoxImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/VBoxCryptoIf.h> + +#include "VirtualBoxBase.h" +#include "objectslist.h" +#include "VirtualBoxWrap.h" + +#ifdef RT_OS_WINDOWS +# include "win/resource.h" +#endif + +//#ifdef DEBUG_bird +//# define VBOXSVC_WITH_CLIENT_WATCHER +//#endif + +namespace com +{ + class Event; + class EventQueue; +} + +class SessionMachine; +class GuestOSType; +class Progress; +class Host; +class SystemProperties; +class DHCPServer; +class PerformanceCollector; +class CloudProviderManager; +#ifdef VBOX_WITH_EXTPACK +class ExtPackManager; +#endif +class AutostartDb; +class NATNetwork; +#ifdef VBOX_WITH_CLOUD_NET +class CloudNetwork; +#endif /* VBOX_WITH_CLOUD_NET */ + + +typedef std::list<ComObjPtr<SessionMachine> > SessionMachinesList; + +#ifdef RT_OS_WINDOWS +class SVCHlpClient; +#endif + +namespace settings +{ + class MainConfigFile; + struct MediaRegistry; +} + + +#if defined(VBOX_WITH_SDS) && !defined(VBOX_WITH_XPCOM) +class VirtualBoxClassFactory; /* See ../src-server/win/svcmain.cpp */ +#endif + +class ATL_NO_VTABLE VirtualBox : + public VirtualBoxWrap +#ifdef RT_OS_WINDOWS + , public ATL::CComCoClass<VirtualBox, &CLSID_VirtualBox> +#endif +{ + +public: + + typedef std::list<ComPtr<IInternalSessionControl> > InternalControlList; + typedef ObjectsList<Machine> MachinesOList; + +#if 0 /* obsoleted by AsyncEvent */ + class CallbackEvent; + friend class CallbackEvent; +#endif + class AsyncEvent; + friend class AsyncEvent; + +#ifndef VBOX_WITH_XPCOM +# ifdef VBOX_WITH_SDS + DECLARE_CLASSFACTORY_EX(VirtualBoxClassFactory) +# else + DECLARE_CLASSFACTORY_SINGLETON(VirtualBox) +# endif +#endif + + // Do not use any ATL registry support. + //DECLARE_REGISTRY_RESOURCEID(IDR_VIRTUALBOX) + + // Kind of redundant (VirtualBoxWrap declares itself not aggregatable and + // CComCoClass<VirtualBox, &CLSID_VirtualBox> as aggregatable, the former + // is the first inheritance), but the C++ multiple inheritance rules and + // the class factory in svcmain.cpp needs this to disambiguate. + DECLARE_NOT_AGGREGATABLE(VirtualBox) + + // to postpone generation of the default ctor/dtor + DECLARE_COMMON_CLASS_METHODS(VirtualBox) + + HRESULT FinalConstruct(); + void FinalRelease(); + + // public initializer/uninitializer for internal purposes only + HRESULT init(); + HRESULT initMachines(); + HRESULT initMedia(const Guid &uuidMachineRegistry, + const settings::MediaRegistry &mediaRegistry, + const Utf8Str &strMachineFolder); + void uninit(); + + // public methods only for internal purposes + + /** + * Override of the default locking class to be used for validating lock + * order with the standard member lock handle. + */ + virtual VBoxLockingClass getLockingClass() const + { + return LOCKCLASS_VIRTUALBOXOBJECT; + } + +#ifdef DEBUG + void i_dumpAllBackRefs(); +#endif + + HRESULT i_postEvent(Event *event); + + HRESULT i_addProgress(IProgress *aProgress); + HRESULT i_removeProgress(IN_GUID aId); + +#ifdef RT_OS_WINDOWS + typedef HRESULT (*PFN_SVC_HELPER_CLIENT_T)(SVCHlpClient *aClient, Progress *aProgress, void *aUser, int *aVrc); + HRESULT i_startSVCHelperClient(bool aPrivileged, + PFN_SVC_HELPER_CLIENT_T aFunc, + void *aUser, Progress *aProgress); +#endif + + void i_addProcessToReap(RTPROCESS pid); + void i_updateClientWatcher(); + + int i_loadVDPlugin(const char *pszPluginLibrary); + int i_unloadVDPlugin(const char *pszPluginLibrary); + + void i_onMediumRegistered(const Guid &aMediumId, const DeviceType_T aDevType, BOOL aRegistered); + void i_onMediumConfigChanged(IMedium *aMedium); + void i_onMediumChanged(IMediumAttachment* aMediumAttachment); + void i_onStorageControllerChanged(const Guid &aMachineId, const com::Utf8Str &aControllerName); + void i_onStorageDeviceChanged(IMediumAttachment* aStorageDevice, BOOL fRemoved, BOOL fSilent); + void i_onMachineStateChanged(const Guid &aId, MachineState_T aState); + void i_onMachineDataChanged(const Guid &aId, BOOL aTemporary = FALSE); + void i_onMachineGroupsChanged(const Guid &aId); + BOOL i_onExtraDataCanChange(const Guid &aId, const Utf8Str &aKey, const Utf8Str &aValue, Bstr &aError); + void i_onExtraDataChanged(const Guid &aId, const Utf8Str &aKey, const Utf8Str &aValue); + void i_onMachineRegistered(const Guid &aId, BOOL aRegistered); + void i_onSessionStateChanged(const Guid &aId, SessionState_T aState); + + void i_onSnapshotTaken(const Guid &aMachineId, const Guid &aSnapshotId); + void i_onSnapshotDeleted(const Guid &aMachineId, const Guid &aSnapshotId); + void i_onSnapshotRestored(const Guid &aMachineId, const Guid &aSnapshotId); + void i_onSnapshotChanged(const Guid &aMachineId, const Guid &aSnapshotId); + + void i_onGuestPropertyChanged(const Guid &aMachineId, const Utf8Str &aName, const Utf8Str &aValue, const Utf8Str &aFlags, + const BOOL fWasDeleted); + void i_onNatRedirectChanged(const Guid &aMachineId, ULONG ulSlot, bool fRemove, const Utf8Str &aName, + NATProtocol_T aProto, const Utf8Str &aHostIp, uint16_t aHostPort, + const Utf8Str &aGuestIp, uint16_t aGuestPort); + void i_onNATNetworkChanged(const Utf8Str &aNetworkName); + void i_onNATNetworkStartStop(const Utf8Str &aNetworkName, BOOL aStart); + void i_onNATNetworkSetting(const Utf8Str &aNetworkName, BOOL aEnabled, const Utf8Str &aNetwork, + const Utf8Str &aGateway, BOOL aAdvertiseDefaultIpv6RouteEnabled, + BOOL fNeedDhcpServer); + void i_onNATNetworkPortForward(const Utf8Str &aNetworkName, BOOL create, BOOL fIpv6, + const Utf8Str &aRuleName, NATProtocol_T proto, + const Utf8Str &aHostIp, LONG aHostPort, + const Utf8Str &aGuestIp, LONG aGuestPort); + void i_onHostNameResolutionConfigurationChange(); + + int i_natNetworkRefInc(const Utf8Str &aNetworkName); + int i_natNetworkRefDec(const Utf8Str &aNetworkName); + + RWLockHandle *i_getNatNetLock() const; + bool i_isNatNetStarted(const Utf8Str &aNetworkName) const; + + void i_onCloudProviderListChanged(BOOL aRegistered); + void i_onCloudProviderRegistered(const Utf8Str &aProviderId, BOOL aRegistered); + void i_onCloudProviderUninstall(const Utf8Str &aProviderId); + + void i_onProgressCreated(const Guid &aId, BOOL aCreated); + + void i_onLanguageChanged(const Utf8Str &aLanguageId); + +#ifdef VBOX_WITH_UPDATE_AGENT + void i_onUpdateAgentAvailable(IUpdateAgent *aAgent, + const Utf8Str &aVer, UpdateChannel_T aChannel, UpdateSeverity_T aSev, + const Utf8Str &aDownloadURL, const Utf8Str &aWebURL, const Utf8Str &aReleaseNotes); + void i_onUpdateAgentError(IUpdateAgent *aAgent, const Utf8Str &aErrMsg, LONG aRc); + void i_onUpdateAgentStateChanged(IUpdateAgent *aAgent, UpdateState_T aState); + void i_onUpdateAgentSettingsChanged(IUpdateAgent *aAgent, const Utf8Str &aAttributeHint); +#endif /* VBOX_WITH_UPDATE_AGENT */ + +#ifdef VBOX_WITH_CLOUD_NET + HRESULT i_findCloudNetworkByName(const com::Utf8Str &aNetworkName, + ComObjPtr<CloudNetwork> *aNetwork = NULL); + HRESULT i_getEventSource(ComPtr<IEventSource>& aSource); +#endif /* VBOX_WITH_CLOUD_NET */ + + ComObjPtr<GuestOSType> i_getUnknownOSType(); + + void i_getOpenedMachines(SessionMachinesList &aMachines, + InternalControlList *aControls = NULL); + MachinesOList &i_getMachinesList(); + + HRESULT i_findMachine(const Guid &aId, + bool fPermitInaccessible, + bool aSetError, + ComObjPtr<Machine> *aMachine = NULL); + + HRESULT i_findMachineByName(const Utf8Str &aName, + bool aSetError, + ComObjPtr<Machine> *aMachine = NULL); + + HRESULT i_validateMachineGroup(const com::Utf8Str &aGroup, bool fPrimary); + HRESULT i_convertMachineGroups(const std::vector<com::Utf8Str> aMachineGroups, StringsList *pllMachineGroups); + + HRESULT i_findHardDiskById(const Guid &id, + bool aSetError, + ComObjPtr<Medium> *aHardDisk = NULL); + HRESULT i_findHardDiskByLocation(const Utf8Str &strLocation, + bool aSetError, + ComObjPtr<Medium> *aHardDisk = NULL); + HRESULT i_findDVDOrFloppyImage(DeviceType_T mediumType, + const Guid *aId, + const Utf8Str &aLocation, + bool aSetError, + ComObjPtr<Medium> *aImage = NULL); + HRESULT i_findRemoveableMedium(DeviceType_T mediumType, + const Guid &uuid, + bool fRefresh, + bool aSetError, + ComObjPtr<Medium> &pMedium); + + HRESULT i_findGuestOSType(const Utf8Str &strOSType, + ComObjPtr<GuestOSType> &guestOSType); + + const Guid &i_getGlobalRegistryId() const; + + const ComObjPtr<Host> &i_host() const; + SystemProperties *i_getSystemProperties() const; + CloudProviderManager *i_getCloudProviderManager() const; +#ifdef VBOX_WITH_EXTPACK + ExtPackManager *i_getExtPackManager() const; +#endif +#ifdef VBOX_WITH_RESOURCE_USAGE_API + const ComObjPtr<PerformanceCollector> &i_performanceCollector() const; +#endif /* VBOX_WITH_RESOURCE_USAGE_API */ + + void i_getDefaultMachineFolder(Utf8Str &str) const; + void i_getDefaultHardDiskFormat(Utf8Str &str) const; + + /** Returns the VirtualBox home directory */ + const Utf8Str &i_homeDir() const; + int i_calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult); + void i_copyPathRelativeToConfig(const Utf8Str &strSource, Utf8Str &strTarget); + HRESULT i_registerMedium(const ComObjPtr<Medium> &pMedium, ComObjPtr<Medium> *ppMedium, + AutoWriteLock &mediaTreeLock, bool fCalledFromMediumInit = false); + HRESULT i_unregisterMedium(Medium *pMedium); + HRESULT i_unregisterMachineMedia(const Guid &id); + HRESULT i_unregisterMachine(Machine *pMachine, CleanupMode_T aCleanupMode, const Guid &id); + void i_rememberMachineNameChangeForMedia(const Utf8Str &strOldConfigDir, + const Utf8Str &strNewConfigDir); + void i_saveMediaRegistry(settings::MediaRegistry &mediaRegistry, + const Guid &uuidRegistry, + const Utf8Str &strMachineFolder); + HRESULT i_saveSettings(); + void i_markRegistryModified(const Guid &uuid); + void i_unmarkRegistryModified(const Guid &uuid); + void i_saveModifiedRegistries(); + static const com::Utf8Str &i_getVersionNormalized(); + static HRESULT i_ensureFilePathExists(const Utf8Str &strFileName, bool fCreate); + const Utf8Str& i_settingsFilePath(); + AutostartDb* i_getAutostartDb() const; + RWLockHandle& i_getMachinesListLockHandle(); + RWLockHandle& i_getMediaTreeLockHandle(); + int i_encryptSetting(const Utf8Str &aPlaintext, Utf8Str *aCiphertext); + int i_decryptSetting(Utf8Str *aPlaintext, const Utf8Str &aCiphertext); + void i_storeSettingsKey(const Utf8Str &aKey); + bool i_isMediaUuidInUse(const Guid &aId, DeviceType_T deviceType); + HRESULT i_retainCryptoIf(PCVBOXCRYPTOIF *ppCryptoIf); + HRESULT i_releaseCryptoIf(PCVBOXCRYPTOIF pCryptoIf); + HRESULT i_unloadCryptoIfModule(void); + + + +private: + class ClientWatcher; + + // wrapped IVirtualBox properties + HRESULT getVersion(com::Utf8Str &aVersion); + HRESULT getVersionNormalized(com::Utf8Str &aVersionNormalized); + HRESULT getRevision(ULONG *aRevision); + HRESULT getPackageType(com::Utf8Str &aPackageType); + HRESULT getAPIVersion(com::Utf8Str &aAPIVersion); + HRESULT getAPIRevision(LONG64 *aAPIRevision); + HRESULT getHomeFolder(com::Utf8Str &aHomeFolder); + HRESULT getSettingsFilePath(com::Utf8Str &aSettingsFilePath); + HRESULT getHost(ComPtr<IHost> &aHost); + HRESULT getSystemProperties(ComPtr<ISystemProperties> &aSystemProperties); + HRESULT getMachines(std::vector<ComPtr<IMachine> > &aMachines); + HRESULT getMachineGroups(std::vector<com::Utf8Str> &aMachineGroups); + HRESULT getHardDisks(std::vector<ComPtr<IMedium> > &aHardDisks); + HRESULT getDVDImages(std::vector<ComPtr<IMedium> > &aDVDImages); + HRESULT getFloppyImages(std::vector<ComPtr<IMedium> > &aFloppyImages); + HRESULT getProgressOperations(std::vector<ComPtr<IProgress> > &aProgressOperations); + HRESULT getGuestOSTypes(std::vector<ComPtr<IGuestOSType> > &aGuestOSTypes); + HRESULT getSharedFolders(std::vector<ComPtr<ISharedFolder> > &aSharedFolders); + HRESULT getPerformanceCollector(ComPtr<IPerformanceCollector> &aPerformanceCollector); + HRESULT getDHCPServers(std::vector<ComPtr<IDHCPServer> > &aDHCPServers); + HRESULT getNATNetworks(std::vector<ComPtr<INATNetwork> > &aNATNetworks); + HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); + HRESULT getExtensionPackManager(ComPtr<IExtPackManager> &aExtensionPackManager); + HRESULT getHostOnlyNetworks(std::vector<ComPtr<IHostOnlyNetwork> > &aHostOnlyNetworks); + HRESULT getInternalNetworks(std::vector<com::Utf8Str> &aInternalNetworks); + HRESULT getGenericNetworkDrivers(std::vector<com::Utf8Str> &aGenericNetworkDrivers); + HRESULT getCloudNetworks(std::vector<ComPtr<ICloudNetwork> > &aCloudNetworks); + HRESULT getCloudProviderManager(ComPtr<ICloudProviderManager> &aCloudProviderManager); + + // wrapped IVirtualBox methods + HRESULT composeMachineFilename(const com::Utf8Str &aName, + const com::Utf8Str &aGroup, + const com::Utf8Str &aCreateFlags, + const com::Utf8Str &aBaseFolder, + com::Utf8Str &aFile); + HRESULT createMachine(const com::Utf8Str &aSettingsFile, + const com::Utf8Str &aName, + const std::vector<com::Utf8Str> &aGroups, + const com::Utf8Str &aOsTypeId, + const com::Utf8Str &aFlags, + const com::Utf8Str &aCipher, + const com::Utf8Str &aPasswordId, + const com::Utf8Str &aPassword, + ComPtr<IMachine> &aMachine); + HRESULT openMachine(const com::Utf8Str &aSettingsFile, + const com::Utf8Str &aPassword, + ComPtr<IMachine> &aMachine); + HRESULT registerMachine(const ComPtr<IMachine> &aMachine); + HRESULT findMachine(const com::Utf8Str &aNameOrId, + ComPtr<IMachine> &aMachine); + HRESULT getMachinesByGroups(const std::vector<com::Utf8Str> &aGroups, + std::vector<ComPtr<IMachine> > &aMachines); + HRESULT getMachineStates(const std::vector<ComPtr<IMachine> > &aMachines, + std::vector<MachineState_T> &aStates); + HRESULT createAppliance(ComPtr<IAppliance> &aAppliance); + HRESULT createUnattendedInstaller(ComPtr<IUnattended> &aUnattended); + HRESULT createMedium(const com::Utf8Str &aFormat, + const com::Utf8Str &aLocation, + AccessMode_T aAccessMode, + DeviceType_T aDeviceType, + ComPtr<IMedium> &aMedium); + HRESULT openMedium(const com::Utf8Str &aLocation, + DeviceType_T aDeviceType, + AccessMode_T aAccessMode, + BOOL aForceNewUuid, + ComPtr<IMedium> &aMedium); + HRESULT getGuestOSType(const com::Utf8Str &aId, + ComPtr<IGuestOSType> &aType); + HRESULT createSharedFolder(const com::Utf8Str &aName, + const com::Utf8Str &aHostPath, + BOOL aWritable, + BOOL aAutomount, + const com::Utf8Str &aAutoMountPoint); + HRESULT removeSharedFolder(const com::Utf8Str &aName); + HRESULT getExtraDataKeys(std::vector<com::Utf8Str> &aKeys); + HRESULT getExtraData(const com::Utf8Str &aKey, + com::Utf8Str &aValue); + HRESULT setExtraData(const com::Utf8Str &aKey, + const com::Utf8Str &aValue); + HRESULT setSettingsSecret(const com::Utf8Str &aPassword); + HRESULT createDHCPServer(const com::Utf8Str &aName, + ComPtr<IDHCPServer> &aServer); + HRESULT findDHCPServerByNetworkName(const com::Utf8Str &aName, + ComPtr<IDHCPServer> &aServer); + HRESULT removeDHCPServer(const ComPtr<IDHCPServer> &aServer); + HRESULT createNATNetwork(const com::Utf8Str &aNetworkName, + ComPtr<INATNetwork> &aNetwork); + HRESULT findNATNetworkByName(const com::Utf8Str &aNetworkName, + ComPtr<INATNetwork> &aNetwork); + HRESULT removeNATNetwork(const ComPtr<INATNetwork> &aNetwork); + HRESULT createHostOnlyNetwork(const com::Utf8Str &aNetworkName, + ComPtr<IHostOnlyNetwork> &aNetwork); + HRESULT findHostOnlyNetworkByName(const com::Utf8Str &aNetworkName, + ComPtr<IHostOnlyNetwork> &aNetwork); + HRESULT findHostOnlyNetworkById(const com::Guid &aId, + ComPtr<IHostOnlyNetwork> &aNetwork); + HRESULT removeHostOnlyNetwork(const ComPtr<IHostOnlyNetwork> &aNetwork); + HRESULT createCloudNetwork(const com::Utf8Str &aNetworkName, + ComPtr<ICloudNetwork> &aNetwork); + HRESULT findCloudNetworkByName(const com::Utf8Str &aNetworkName, + ComPtr<ICloudNetwork> &aNetwork); + HRESULT removeCloudNetwork(const ComPtr<ICloudNetwork> &aNetwork); + HRESULT checkFirmwarePresent(FirmwareType_T aFirmwareType, + const com::Utf8Str &aVersion, + com::Utf8Str &aUrl, + com::Utf8Str &aFile, + BOOL *aResult); + HRESULT findProgressById(const com::Guid &aId, + ComPtr<IProgress> &aProgressObject); + + static HRESULT i_setErrorStaticBoth(HRESULT aResultCode, int vrc, const char *aText, ...) + { + va_list va; + va_start (va, aText); + HRESULT hrc = setErrorInternalV(aResultCode, getStaticClassIID(), getStaticComponentName(), aText, va, false, true, vrc); + va_end(va); + return hrc; + } + + HRESULT i_registerMachine(Machine *aMachine); + HRESULT i_registerDHCPServer(DHCPServer *aDHCPServer, + bool aSaveRegistry = true); + HRESULT i_unregisterDHCPServer(DHCPServer *aDHCPServer); + HRESULT i_registerNATNetwork(NATNetwork *aNATNetwork, + bool aSaveRegistry = true); + HRESULT i_unregisterNATNetwork(NATNetwork *aNATNetwork, + bool aSaveRegistry = true); + HRESULT i_checkMediaForConflicts(const Guid &aId, + const Utf8Str &aLocation, + Utf8Str &aConflictType, + ComObjPtr<Medium> *pDupMedium); + int i_decryptSettings(); + int i_decryptMediumSettings(Medium *pMedium); + int i_decryptSettingBytes(uint8_t *aPlaintext, + const uint8_t *aCiphertext, + size_t aCiphertextSize) const; + int i_encryptSettingBytes(const uint8_t *aPlaintext, + uint8_t *aCiphertext, + size_t aPlaintextSize, + size_t aCiphertextSize) const; + void i_reportDriverVersions(void); + + struct Data; // opaque data structure, defined in VirtualBoxImpl.cpp + + Data *m; + + /* static variables (defined in VirtualBoxImpl.cpp) */ + static com::Utf8Str sVersion; + static com::Utf8Str sVersionNormalized; + static ULONG sRevision; + static com::Utf8Str sPackageType; + static com::Utf8Str sAPIVersion; + static std::map<com::Utf8Str, int> sNatNetworkNameToRefCount; + static RWLockHandle* spMtxNatNetworkNameToRefCountLock; + + static DECLCALLBACK(int) AsyncEventHandler(RTTHREAD thread, void *pvUser); + +#ifdef RT_OS_WINDOWS + friend class StartSVCHelperClientData; + static void i_SVCHelperClientThreadTask(StartSVCHelperClientData *pTask); +#endif + +#if defined(RT_OS_WINDOWS) && defined(VBOXSVC_WITH_CLIENT_WATCHER) +protected: + void i_callHook(const char *a_pszFunction) RT_OVERRIDE; + bool i_watchClientProcess(RTPROCESS a_pidClient, const char *a_pszFunction); +public: + static void i_logCaller(const char *a_pszFormat, ...); +private: + +#endif +}; + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* !MAIN_INCLUDED_VirtualBoxImpl_h */ + diff --git a/src/VBox/Main/include/VirtualBoxSDSImpl.h b/src/VBox/Main/include/VirtualBoxSDSImpl.h new file mode 100644 index 00000000..3a495fc2 --- /dev/null +++ b/src/VBox/Main/include/VirtualBoxSDSImpl.h @@ -0,0 +1,161 @@ +/* $Id: VirtualBoxSDSImpl.h $ */ +/** @file + * VBox Global COM Class definition + */ + +/* + * Copyright (C) 2017-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_VirtualBoxSDSImpl_h +#define MAIN_INCLUDED_VirtualBoxSDSImpl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "VirtualBoxBase.h" + +/* Enable the watcher code in debug builds. */ +#ifdef DEBUG +# define WITH_WATCHER +#endif + + +class VBoxSDSPerUserData; /* See VirtualBoxSDSImpl.cpp. */ +struct VBoxSDSWatcher; /* See VirtualBoxSDSImpl.cpp. */ + +/** + * The IVirtualBoxSDS implementation. + * + * This class helps different VBoxSVC processes make sure a user only have a + * single VirtualBox instance. + * + * @note This is a simple internal class living in a privileged process. So, we + * do not use the API wrappers as they add complexity. In particular, + * they add the auto caller logic, which is an excellent tool to create + * unkillable processes. If an API method during development or product + * for instance triggers an NT exception like STATUS_ACCESS_VIOLATION, the + * caller will be unwound without releasing the caller. When uninit is + * called during COM shutdown/whatever, the thread gets stuck waiting for + * the long gone caller and cannot be killed (Windows 10, build 16299), + * requiring a reboot to continue. + * + * @todo Would be very nice to get rid of the ATL cruft too here. + */ +class VirtualBoxSDS + : public IVirtualBoxSDS + , public ATL::CComObjectRootEx<ATL::CComMultiThreadModel> + , public ATL::CComCoClass<VirtualBoxSDS, &CLSID_VirtualBoxSDS> +{ +private: + typedef std::map<com::Utf8Str, VBoxSDSPerUserData *> UserDataMap_T; + /** Per user data map (key is SID string). + * This is an insert-only map! */ + UserDataMap_T m_UserDataMap; + /** Number of registered+watched VBoxSVC processes. */ + uint32_t m_cVBoxSvcProcesses; +#ifdef WITH_WATCHER + /** Number of watcher threads. */ + uint32_t m_cWatchers; + /** Pointer to an array of watcher pointers. */ + VBoxSDSWatcher **m_papWatchers; + /** Lock protecting m_papWatchers and associated structures. */ + RTCRITSECT m_WatcherCritSect; +#endif + /** Lock protecting m_UserDataMap . */ + RTCRITSECTRW m_MapCritSect; + +public: + DECLARE_CLASSFACTORY_SINGLETON(VirtualBoxSDS) + DECLARE_NOT_AGGREGATABLE(VirtualBoxSDS) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(VirtualBoxSDS) + COM_INTERFACE_ENTRY(IVirtualBoxSDS) + END_COM_MAP() + + DECLARE_COMMON_CLASS_METHODS(VirtualBoxSDS) + + HRESULT FinalConstruct(); + void FinalRelease(); + +private: + + /** @name IVirtualBoxSDS methods + * @{ */ + STDMETHOD(RegisterVBoxSVC)(IVBoxSVCRegistration *aVBoxSVC, LONG aPid, IUnknown **aExistingVirtualBox); + STDMETHOD(DeregisterVBoxSVC)(IVBoxSVCRegistration *aVBoxSVC, LONG aPid); + STDMETHOD(LaunchVMProcess)(IN_BSTR aMachine, IN_BSTR aComment, IN_BSTR aFrontend, + ComSafeArrayIn(IN_BSTR, aEnvironmentChanges), IN_BSTR aCmdOptions, + ULONG aSessionId, ULONG *aPid); + /** @} */ + + + /** @name Private methods + * @{ */ + /** + * Gets the client user SID of the + */ + static bool i_getClientUserSid(com::Utf8Str *a_pStrSid, com::Utf8Str *a_pStrUsername); + + /** + * Returns whether a VBoxSDS feature is enabled or not. + * + * @returns \c true if enabled, \c false if not. + * @param a_pwszFeature Feature to check enabled status for. + */ + static bool i_isFeatureEnabled(wchar_t const *a_pwszFeature); + + /** + * Looks up the given user. + * + * @returns Pointer to the LOCKED per user data. NULL if not found. + * @param a_rStrUserSid The user SID. + */ + VBoxSDSPerUserData *i_lookupPerUserData(com::Utf8Str const &a_rStrUserSid); + + /** + * Looks up the given user, creating it if not found + * + * @returns Pointer to the LOCKED per user data. NULL on allocation error. + * @param a_rStrUserSid The user SID. + * @param a_rStrUsername The user name if available. + */ + VBoxSDSPerUserData *i_lookupOrCreatePerUserData(com::Utf8Str const &a_rStrUserSid, com::Utf8Str const &a_rStrUsername); + +#ifdef WITH_WATCHER + static DECLCALLBACK(int) i_watcherThreadProc(RTTHREAD hSelf, void *pvUser); + bool i_watchIt(VBoxSDSPerUserData *pProcess, HANDLE hProcess, RTPROCESS pid); + void i_stopWatching(VBoxSDSPerUserData *pProcess, RTPROCESS pid); + void i_shutdownAllWatchers(void); + + void i_decrementClientCount(); + void i_incrementClientCount(); +#endif + /** @} */ +}; + +#ifdef WITH_WATCHER +void VBoxSDSNotifyClientCount(uint32_t cClients); +#endif + +#endif /* !MAIN_INCLUDED_VirtualBoxSDSImpl_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/VirtualBoxTranslator.h b/src/VBox/Main/include/VirtualBoxTranslator.h new file mode 100644 index 00000000..3921bf14 --- /dev/null +++ b/src/VBox/Main/include/VirtualBoxTranslator.h @@ -0,0 +1,165 @@ +/* $Id: VirtualBoxTranslator.h $ */ +/** @file + * VirtualBox Translator. + */ + +/* + * Copyright (C) 2005-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_VirtualBoxTranslator_h +#define MAIN_INCLUDED_VirtualBoxTranslator_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <list> + +#include <iprt/cpp/lock.h> +#include <VBox/com/AutoLock.h> + +COM_STRUCT_OR_CLASS(IVirtualBox); +class QMTranslator; + +class VirtualBoxTranslator + : public util::RWLockHandle +{ +public: + virtual ~VirtualBoxTranslator(); + + static VirtualBoxTranslator *instance(); + /* Returns instance if exists, returns NULL otherwise. */ + static VirtualBoxTranslator *tryInstance() RT_NOEXCEPT; + void release(); + + /* Load language based on settings in the VirtualBox config */ + HRESULT loadLanguage(ComPtr<IVirtualBox> aVirtualBox); + +private: + /** Translator component. */ + struct TranslatorComponent + { + QMTranslator *pTranslator; + /** Path to translation files. It includes file prefix, i.e '/path/to/folder/file_prefix'. */ + com::Utf8Str strPath; + + TranslatorComponent() : pTranslator(NULL) {} + }; +public: + /** Pointer to a translator component. */ + typedef TranslatorComponent *PTRCOMPONENT; + + /** + * Registers the translation for a component. + * + * @returns VBox status code + * @param aTranslationPath Path to the translation files, this includes the + * base filename prefix. + * @param aDefault Use this as the default translation component, i.e. + * when translate() is called with NULL for @a + * aComponent. + * @param aComponent Pointer to where is the component handle should be + * returned on success. The return value must be used + * for all subsequent calls to translate(). + */ + static int registerTranslation(const char *aTranslationPath, + bool aDefault, + PTRCOMPONENT *aComponent); + + /** + * Removes translations for a component. + * + * @returns VBox status code + * @param aComponent The component. NULL is quietly (VWRN_NOT_FOUND) + * ignored . + */ + static int unregisterTranslation(PTRCOMPONENT aComponent); + + /** + * Translates @a aSourceText to user language. + * Uses component marked as default if @a aTranslationComponent is NULL + * + * @returns Translated string or @a aSourceText. The returned string is + * valid only during lifetime of the translator instance. + */ + static const char *translate(PTRCOMPONENT aComponent, + const char *aContext, + const char *aSourceText, + const char *aComment = NULL, + const size_t aNum = ~(size_t)0) RT_NOEXCEPT; + + /** + * Returns source text stored in the cache if exists. + * Otherwise, the pszTranslation itself returned. + */ + static const char *trSource(const char *aTranslation) RT_NOEXCEPT; + + /* Convenience function used by VirtualBox::init */ + int i_loadLanguage(const char *pszLang); + + static int32_t initCritSect(); + + com::Utf8Str language(); + +private: + static RTCRITSECTRW s_instanceRwLock; + static VirtualBoxTranslator *s_pInstance; + + uint32_t m_cInstanceRefs; + + typedef std::list<TranslatorComponent> TranslatorList; + TranslatorList m_lTranslators; + TranslatorComponent *m_pDefaultComponent; + + /* keep the language code for registration */ + com::Utf8Str m_strLanguage; + + /** String cache that all translation strings are stored in. + * This is a add-only cache, which allows translate() to return C-strings w/o + * needing to think about racing loadLanguage() wrt string lifetime. */ + RTSTRCACHE m_hStrCache; + /** RTStrCacheCreate status code. */ + int m_rcCache; + + VirtualBoxTranslator(); + + int i_loadLanguageForComponent(TranslatorComponent *aComponent, const char *aLang); + + int i_setLanguageFile(TranslatorComponent *aComponent, const char *aFileName); + + int i_registerTranslation(const char *aTranslationPath, + bool aDefault, + PTRCOMPONENT *aComponent); + + int i_unregisterTranslation(PTRCOMPONENT aComponent); + + const char *i_translate(PTRCOMPONENT aComponent, + const char *aContext, + const char *aSourceText, + const char *aComment = NULL, + const size_t aNum = ~(size_t)0) RT_NOEXCEPT; +}; + +/** Pointer to a translator component. */ +typedef VirtualBoxTranslator::PTRCOMPONENT PTRCOMPONENT; + +#endif /* !MAIN_INCLUDED_VirtualBoxTranslator_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/WebMWriter.h b/src/VBox/Main/include/WebMWriter.h new file mode 100644 index 00000000..e03a4798 --- /dev/null +++ b/src/VBox/Main/include/WebMWriter.h @@ -0,0 +1,579 @@ +/* $Id: WebMWriter.h $ */ +/** @file + * WebMWriter.h - WebM container handling. + */ + +/* + * Copyright (C) 2013-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_WebMWriter_h +#define MAIN_INCLUDED_WebMWriter_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/buildconfig.h> +#include <iprt/mem.h> +#include <iprt/rand.h> +#include <iprt/string.h> + +#include "VBox/com/VirtualBox.h" +#include <VBox/version.h> + +#include "EBMLWriter.h" +#include "EBML_MKV.h" + +#include <queue> +#include <map> +#include <list> + +#ifdef VBOX_WITH_LIBVPX +# ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4668) /* vpx_codec.h(64) : warning C4668: '__GNUC__' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */ +# include <vpx/vpx_encoder.h> +# pragma warning(pop) +# else +# include <vpx/vpx_encoder.h> +# endif +#endif /* VBOX_WITH_LIBVPX */ + +/** No flags specified. */ +#define VBOX_WEBM_BLOCK_FLAG_NONE 0 +/** Invisible block which can be skipped. */ +#define VBOX_WEBM_BLOCK_FLAG_INVISIBLE 0x08 +/** The block marks a key frame. */ +#define VBOX_WEBM_BLOCK_FLAG_KEY_FRAME 0x80 + +/** The default timecode scale factor for WebM -- all timecodes in the segments are expressed in ms. + * This allows every cluster to have blocks with positive values up to 32.767 seconds. */ +#define VBOX_WEBM_TIMECODESCALE_FACTOR_MS 1000000 + +/** Maximum time (in ms) a cluster can store. */ +#define VBOX_WEBM_CLUSTER_MAX_LEN_MS INT16_MAX + +/** Maximum time a block can store. + * With signed 16-bit timecodes and a default timecode scale of 1ms per unit this makes 65536ms. */ +#define VBOX_WEBM_BLOCK_MAX_LEN_MS UINT16_MAX + +#ifdef VBOX_WITH_LIBVORBIS +# pragma pack(push) +# pragma pack(1) + /** Ogg Vorbis codec private data within the MKV (WEBM) container. + * Taken from: https://www.matroska.org/technical/codec_specs.html */ + typedef struct WEBMOGGVORBISPRIVDATA + { + WEBMOGGVORBISPRIVDATA(uint32_t a_cbHdrIdent, uint32_t a_cbHdrComments, uint32_t a_cbHdrSetup) + : cbHdrIdent(a_cbHdrIdent) + , cbHdrComments(a_cbHdrComments) + { + RT_NOREF(a_cbHdrSetup); + + /* We supply 3 headers total: The "real" header, comments header + setup header. */ + cHeaders = 3 /* Headers */ - 1; /* Note: Always "minus one" here. */ + + Assert(a_cbHdrIdent <= UINT8_MAX); + Assert(a_cbHdrComments <= UINT8_MAX); + Assert(a_cbHdrSetup <= _8K); + Assert(a_cbHdrIdent + a_cbHdrComments + a_cbHdrSetup <= sizeof(abHdr)); + } + + /** Number of private headers - 1. */ + uint8_t cHeaders; + /** Size of identification header (in bytes). */ + uint8_t cbHdrIdent; + /** < Size of comments header (in bytes). */ + uint8_t cbHdrComments; + /** < Header code area. */ + uint8_t abHdr[UINT8_MAX /* Header */ + UINT8_MAX /* Comments header */ + _8K /* Setup header */]; + + } WEBMOGGVORBISPRIVDATA, *PWEBMOGGVORBISPRIVDATA; +# pragma pack(pop) +#endif + +class WebMWriter : public EBMLWriter +{ + +public: + + /** Defines an absolute WebM timecode (Block + Cluster). */ + typedef uint64_t WebMTimecodeAbs; + + /** Defines a relative WebM timecode (Block). */ + typedef uint16_t WebMTimecodeRel; + + /** Defines the WebM block flags data type. */ + typedef uint8_t WebMBlockFlags; + + /** + * Track type enumeration. + */ + enum WebMTrackType + { + /** Unknown / invalid type. */ + WebMTrackType_Invalid = 0, + /** Only writes audio. */ + WebMTrackType_Audio = 1, + /** Only writes video. */ + WebMTrackType_Video = 2 + }; + + struct WebMTrack; + + /** + * Structure for defining a WebM simple block. + */ + struct WebMSimpleBlock + { + WebMSimpleBlock(WebMTrack *a_pTrack, + WebMTimecodeAbs a_tcAbsPTSMs, const void *a_pvData, size_t a_cbData, WebMBlockFlags a_fFlags) + : pTrack(a_pTrack) + { + Data.tcAbsPTSMs = a_tcAbsPTSMs; + Data.cb = a_cbData; + Data.fFlags = a_fFlags; + + if (Data.cb) + { + Data.pv = RTMemDup(a_pvData, a_cbData); + if (!Data.pv) + throw; + } + } + + virtual ~WebMSimpleBlock() + { + if (Data.pv) + { + Assert(Data.cb); + RTMemFree(Data.pv); + } + } + + WebMTrack *pTrack; + + /** Actual simple block data. */ + struct + { + WebMTimecodeAbs tcAbsPTSMs; + WebMTimecodeRel tcRelToClusterMs; + void *pv; + size_t cb; + WebMBlockFlags fFlags; + } Data; + }; + + /** A simple block queue.*/ + typedef std::queue<WebMSimpleBlock *> WebMSimpleBlockQueue; + + /** Structure for queuing all simple blocks bound to a single timecode. + * This can happen if multiple tracks are being involved. */ + struct WebMTimecodeBlocks + { + WebMTimecodeBlocks(void) + : fClusterNeeded(false) + , fClusterStarted(false) { } + + /** The actual block queue for this timecode. */ + WebMSimpleBlockQueue Queue; + /** Whether a new cluster is needed for this timecode or not. */ + bool fClusterNeeded; + /** Whether a new cluster already has been started for this timecode or not. */ + bool fClusterStarted; + + /** + * Enqueues a simple block into the internal queue. + * + * @param a_pBlock Block to enqueue and take ownership of. + */ + void Enqueue(WebMSimpleBlock *a_pBlock) + { + Queue.push(a_pBlock); + + if (a_pBlock->Data.fFlags & VBOX_WEBM_BLOCK_FLAG_KEY_FRAME) + fClusterNeeded = true; + } + }; + + /** A block map containing all currently queued blocks. + * The key specifies a unique timecode, whereas the value + * is a queue of blocks which all correlate to the key (timecode). */ + typedef std::map<WebMTimecodeAbs, WebMTimecodeBlocks> WebMBlockMap; + + /** + * Structure for defining a WebM (encoding) queue. + */ + struct WebMQueue + { + WebMQueue(void) + : tcAbsLastBlockWrittenMs(0) + , tsLastProcessedMs(0) { } + + /** Blocks as FIFO (queue). */ + WebMBlockMap Map; + /** Absolute timecode (in ms) of last written block to queue. */ + WebMTimecodeAbs tcAbsLastBlockWrittenMs; + /** Time stamp (in ms) of when the queue was processed last. */ + uint64_t tsLastProcessedMs; + }; + + /** + * Structure for keeping a WebM track entry. + */ + struct WebMTrack + { + WebMTrack(WebMTrackType a_enmType, PRECORDINGCODEC pTheCodec, uint8_t a_uTrack, uint64_t a_offID) + : enmType(a_enmType) + , pCodec(pTheCodec) + , uTrack(a_uTrack) + , offUUID(a_offID) + , cTotalBlocks(0) + , tcAbsLastWrittenMs(0) + { + uUUID = RTRandU32(); + } + + /** The type of this track. */ + WebMTrackType enmType; + /** Pointer to codec data to use. */ + PRECORDINGCODEC pCodec; + /** Track parameters. */ + union + { + struct + { + /** Sample rate of input data. */ + uint32_t uHz; + /** Duration of the frame in samples (per channel). + * Valid frame size are: + * + * ms Frame size + * 2.5 120 + * 5 240 + * 10 480 + * 20 (Default) 960 + * 40 1920 + * 60 2880 + */ + uint16_t framesPerBlock; + /** How many milliseconds (ms) one written (simple) block represents. */ + uint16_t msPerBlock; + } Audio; + }; + /** This track's track number. Also used as key in track map. */ + uint8_t uTrack; + /** The track's "UUID". + * Needed in case this track gets mux'ed with tracks from other files. Not really unique though. */ + uint32_t uUUID; + /** Absolute offset in file of track UUID. + * Needed to write the hash sum within the footer. */ + uint64_t offUUID; + /** Total number of blocks. */ + uint64_t cTotalBlocks; + /** Absoute timecode (in ms) of last write. */ + WebMTimecodeAbs tcAbsLastWrittenMs; + }; + + /** + * Structure for a single cue point track position entry. + */ + struct WebMCueTrackPosEntry + { + WebMCueTrackPosEntry(uint64_t a_offCluster) + : offCluster(a_offCluster) { } + + /** Offset (in bytes) of the related cluster containing the given position. */ + uint64_t offCluster; + }; + + /** Map for keeping track position entries for a single cue point. + * The key is the track number (*not* UUID!). */ + typedef std::map<uint8_t, WebMCueTrackPosEntry *> WebMCueTrackPosMap; + + /** + * Structure for keeping a cue point. + */ + struct WebMCuePoint + { + WebMCuePoint(WebMTimecodeAbs a_tcAbs) + : tcAbs(a_tcAbs) { } + + virtual ~WebMCuePoint() + { + Clear(); + } + + void Clear(void) + { + WebMCueTrackPosMap::iterator itTrackPos = Pos.begin(); + while (itTrackPos != Pos.end()) + { + WebMCueTrackPosEntry *pTrackPos = itTrackPos->second; + AssertPtr(pTrackPos); + delete pTrackPos; + + Pos.erase(itTrackPos); + itTrackPos = Pos.begin(); + } + + Assert(Pos.empty()); + } + + /** Map containing all track positions for this specific cue point. */ + WebMCueTrackPosMap Pos; + /** Absolute time code according to the segment time base. */ + WebMTimecodeAbs tcAbs; + }; + + /** List of cue points. */ + typedef std::list<WebMCuePoint *> WebMCuePointList; + + /** + * Structure for keeping a WebM cluster entry. + */ + struct WebMCluster + { + WebMCluster(void) + : uID(0) + , offStart(0) + , fOpen(false) + , tcAbsStartMs(0) + , cBlocks(0) { } + + /** This cluster's ID. */ + uint64_t uID; + /** Absolute offset (in bytes) of this cluster. + * Needed for seeking info table. */ + uint64_t offStart; + /** Whether this cluster element is opened currently. */ + bool fOpen; + /** Absolute timecode (in ms) when this cluster starts. */ + WebMTimecodeAbs tcAbsStartMs; + /** Absolute timecode (in ms) of when last written to this cluster. */ + WebMTimecodeAbs tcAbsLastWrittenMs; + /** Number of (simple) blocks in this cluster. */ + uint64_t cBlocks; + }; + + /** + * Structure for keeping a WebM segment entry. + * + * Current we're only using one segment. + */ + struct WebMSegment + { + WebMSegment(void) + : m_tcAbsStartMs(0) + , m_tcAbsLastWrittenMs(0) + , m_offStart(0) + , m_offInfo(0) + , m_offSeekInfo(0) + , m_offTracks(0) + , m_offCues(0) + , m_cClusters(0) + { + m_uTimecodeScaleFactor = VBOX_WEBM_TIMECODESCALE_FACTOR_MS; + + LogFunc(("Default timecode scale is: %RU64ns\n", m_uTimecodeScaleFactor)); + } + + virtual ~WebMSegment() + { + uninit(); + } + + /** + * Initializes a segment. + * + * @returns VBox status code. + */ + int init(void) + { + return RTCritSectInit(&m_CritSect); + } + + /** + * Uninitializes a segment. + */ + void uninit(void) + { + clear(); + + RTCritSectDelete(&m_CritSect); + } + + /** + * Clear the segment's data by removing (and freeing) all data. + */ + void clear(void) + { + WebMCuePointList::iterator itCuePoint = m_lstCuePoints.begin(); + while (itCuePoint != m_lstCuePoints.end()) + { + WebMCuePoint *pCuePoint = (*itCuePoint); + AssertPtr(pCuePoint); + delete pCuePoint; + + m_lstCuePoints.erase(itCuePoint); + itCuePoint = m_lstCuePoints.begin(); + } + + Assert(m_lstCuePoints.empty()); + } + + /** Critical section for serializing access to this segment. */ + RTCRITSECT m_CritSect; + + /** The timecode scale factor of this segment. */ + uint64_t m_uTimecodeScaleFactor; + + /** Absolute timecode (in ms) when starting this segment. */ + WebMTimecodeAbs m_tcAbsStartMs; + /** Absolute timecode (in ms) of last write. */ + WebMTimecodeAbs m_tcAbsLastWrittenMs; + + /** Absolute offset (in bytes) of CurSeg. */ + uint64_t m_offStart; + /** Absolute offset (in bytes) of general info. */ + uint64_t m_offInfo; + /** Absolute offset (in bytes) of seeking info. */ + uint64_t m_offSeekInfo; + /** Absolute offset (in bytes) of tracks. */ + uint64_t m_offTracks; + /** Absolute offset (in bytes) of cues table. */ + uint64_t m_offCues; + /** List of cue points. Needed for seeking table. */ + WebMCuePointList m_lstCuePoints; + + /** Total number of clusters. */ + uint64_t m_cClusters; + + /** Map of tracks. + * The key marks the track number (*not* the UUID!). */ + std::map <uint8_t, WebMTrack *> m_mapTracks; + + /** Current cluster which is being handled. + * + * Note that we don't need (and shouldn't need, as this can be a *lot* of data!) a + * list of all clusters. */ + WebMCluster m_CurCluster; + + WebMQueue m_queueBlocks; + + } m_CurSeg; + + /** Audio codec to use. */ + RecordingAudioCodec_T m_enmAudioCodec; + /** Video codec to use. */ + RecordingVideoCodec_T m_enmVideoCodec; + + /** Whether we're currently in the tracks section. */ + bool m_fInTracksSection; + + /** Size of timecodes (in bytes). */ + size_t m_cbTimecode; + /** Maximum value a timecode can have. */ + uint32_t m_uTimecodeMax; + +#ifdef VBOX_WITH_LIBVPX + /** + * Block data for VP8-encoded video data. + */ + struct BlockData_VP8 + { + const vpx_codec_enc_cfg_t *pCfg; + const vpx_codec_cx_pkt_t *pPkt; + }; +#endif /* VBOX_WITH_LIBVPX */ + + /** + * Block data for encoded audio data. + */ + struct BlockData_Audio + { + /** Pointer to encoded audio data. */ + const void *pvData; + /** Size (in bytes) of encoded audio data. */ + size_t cbData; + /** PTS (in ms) of encoded audio data. */ + uint64_t uPTSMs; + }; + +public: + + WebMWriter(); + + virtual ~WebMWriter(); + +public: + + int OpenEx(const char *a_pszFilename, PRTFILE a_phFile, + RecordingAudioCodec_T a_enmAudioCodec, RecordingVideoCodec_T a_enmVideoCodec); + + int Open(const char *a_pszFilename, uint64_t a_fOpen, + RecordingAudioCodec_T a_enmAudioCodec, RecordingVideoCodec_T a_enmVideoCodec); + + int Close(void); + + int AddAudioTrack(PRECORDINGCODEC pCodec, uint16_t uHz, uint8_t cChannels, uint8_t cBits, uint8_t *puTrack); + + int AddVideoTrack(PRECORDINGCODEC pCodec, uint16_t uWidth, uint16_t uHeight, uint32_t uFPS, uint8_t *puTrack); + + int WriteBlock(uint8_t uTrack, const void *pvData, size_t cbData, WebMTimecodeAbs tcAbsPTSMs, WebMBlockFlags uFlags); + + const com::Utf8Str& GetFileName(void); + + uint64_t GetFileSize(void); + + uint64_t GetAvailableSpace(void); + + /** + * Returns the number of written WebM clusters. + * + * @returns Number of written WebM clusters; 0 when no clusters written (empty file). + */ + uint64_t GetClusters(void) const { return m_CurSeg.m_cClusters; } + +protected: + + int init(RecordingAudioCodec_T a_enmAudioCodec, RecordingVideoCodec_T a_enmVideoCodec); + + void destroy(void); + + int writeHeader(void); + + void writeSeekHeader(void); + + int writeFooter(void); + + int writeSimpleBlockEBML(WebMTrack *a_pTrack, WebMSimpleBlock *a_pBlock); + + int writeSimpleBlockQueued(WebMTrack *a_pTrack, WebMSimpleBlock *a_pBlock); + + int processQueue(WebMQueue *pQueue, bool fForce); + +protected: + + typedef std::map <uint8_t, WebMTrack *> WebMTracks; +}; + +#endif /* !MAIN_INCLUDED_WebMWriter_h */ diff --git a/src/VBox/Main/include/Wrapper.h b/src/VBox/Main/include/Wrapper.h new file mode 100644 index 00000000..8e994f30 --- /dev/null +++ b/src/VBox/Main/include/Wrapper.h @@ -0,0 +1,504 @@ +/* $Id: Wrapper.h $ */ +/** @file + * VirtualBox COM - API wrapper helpers. + */ + +/* + * Copyright (C) 2012-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_Wrapper_h +#define MAIN_INCLUDED_Wrapper_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <vector> +#include <VBox/com/ptr.h> +#include <VBox/com/array.h> + +#include "AutoCaller.h" + + +/** + * Checks that the given pointer to an output argument is valid and throws + * E_POINTER + extended error info otherwise. + * @param arg Pointer argument. + */ +#define CheckComArgOutPointerValidThrow(arg) \ + do { \ + if (RT_LIKELY(RT_VALID_PTR(arg))) \ + { /* likely */ }\ + /* Have to use use VirtualBoxBase::tr here or lupdate won't be able to figure out the context, \ + as it is picking it up right here rather than in the places where the macro is actually used. */ \ + else throw setError(E_POINTER, VirtualBoxBase::tr("Output argument %s points to invalid memory location (%p)"), \ + #arg, (void *)(arg)); \ + } while (0) + + +class BSTROutConverter +{ +public: + BSTROutConverter() : mDst(NULL) + { + } + + BSTROutConverter(BSTR *aDst) : mDst(aDst) + { + } + + ~BSTROutConverter() + { + if (mDst) + Bstr(mStr).detachTo(mDst); + } + + com::Utf8Str &str() + { + return mStr; + } + +private: + com::Utf8Str mStr; + BSTR *mDst; +}; + +class BSTRInConverter +{ +public: + BSTRInConverter() : mSrc() + { + } + + BSTRInConverter(CBSTR aSrc) : mSrc(aSrc) + { + } + + ~BSTRInConverter() + { + } + + const com::Utf8Str &str() + { + return mSrc; + } + +private: + const com::Utf8Str mSrc; +}; + +class ArrayBSTROutConverter +{ +public: + ArrayBSTROutConverter() : +#ifdef VBOX_WITH_XPCOM + mDstSize(NULL), + mDst(NULL) +#else // !VBOX_WITH_XPCOM + mDst(NULL) +#endif // !VBOX_WITH_XPCOM + { + } + + ArrayBSTROutConverter(ComSafeArrayOut(BSTR, aDst)) : +#ifdef VBOX_WITH_XPCOM + mDstSize(aDstSize), + mDst(aDst) +#else // !VBOX_WITH_XPCOM + mDst(aDst) +#endif // !VBOX_WITH_XPCOM + { + } + + ~ArrayBSTROutConverter() + { + if (mDst) + { + com::SafeArray<BSTR> outArray(mArray.size()); + for (size_t i = 0; i < mArray.size(); i++) + Bstr(mArray[i]).detachTo(&outArray[i]); + outArray.detachTo(ComSafeArrayOutArg(mDst)); + } + } + + std::vector<com::Utf8Str> &array() + { + return mArray; + } + +private: + std::vector<com::Utf8Str> mArray; +#ifdef VBOX_WITH_XPCOM + PRUint32 *mDstSize; + BSTR **mDst; +#else // !VBOX_WITH_XPCOM + SAFEARRAY **mDst; +#endif // !VBOX_WITH_XPCOM +}; + +class ArrayBSTRInConverter +{ +public: + ArrayBSTRInConverter() + { + } + + ArrayBSTRInConverter(ComSafeArrayIn(IN_BSTR, aSrc)) + { + if (!ComSafeArrayInIsNull(aSrc)) + { + com::SafeArray<IN_BSTR> inArray(ComSafeArrayInArg(aSrc)); + mArray.resize(inArray.size()); + for (size_t i = 0; i < inArray.size(); i++) + mArray[i] = inArray[i]; + } + } + + ~ArrayBSTRInConverter() + { + } + + const std::vector<com::Utf8Str> &array() + { + return mArray; + } + +private: + std::vector<com::Utf8Str> mArray; +}; + +class UuidOutConverter +{ +public: + UuidOutConverter() : mDst(NULL) + { + } + + UuidOutConverter(BSTR *aDst) : mDst(aDst) + { + } + + ~UuidOutConverter() + { + if (mDst) + mUuid.toUtf16().detachTo(mDst); + } + + com::Guid &uuid() + { + return mUuid; + } + +private: + com::Guid mUuid; + BSTR *mDst; +}; + +class UuidInConverter +{ +public: + UuidInConverter() : mSrc() + { + } + + UuidInConverter(CBSTR aSrc) : mSrc(aSrc) + { + } + + ~UuidInConverter() + { + } + + const com::Guid &uuid() + { + return mSrc; + } + +private: + const com::Guid mSrc; +}; + +class ArrayUuidOutConverter +{ +public: + ArrayUuidOutConverter() : +#ifdef VBOX_WITH_XPCOM + mDstSize(NULL), + mDst(NULL) +#else // !VBOX_WITH_XPCOM + mDst(NULL) +#endif // !VBOX_WITH_XPCOM + { + } + + ArrayUuidOutConverter(ComSafeArrayOut(BSTR, aDst)) : +#ifdef VBOX_WITH_XPCOM + mDstSize(aDstSize), + mDst(aDst) +#else // !VBOX_WITH_XPCOM + mDst(aDst) +#endif // !VBOX_WITH_XPCOM + { + } + + ~ArrayUuidOutConverter() + { + if (mDst) + { + com::SafeArray<BSTR> outArray(mArray.size()); + for (size_t i = 0; i < mArray.size(); i++) + mArray[i].toUtf16().detachTo(&outArray[i]); + outArray.detachTo(ComSafeArrayOutArg(mDst)); + } + } + + std::vector<com::Guid> &array() + { + return mArray; + } + +private: + std::vector<com::Guid> mArray; +#ifdef VBOX_WITH_XPCOM + PRUint32 *mDstSize; + BSTR **mDst; +#else // !VBOX_WITH_XPCOM + SAFEARRAY **mDst; +#endif // !VBOX_WITH_XPCOM +}; + +template <class A> +class ComTypeOutConverter +{ +public: + ComTypeOutConverter() : mDst(NULL) + { + } + + ComTypeOutConverter(A **aDst) : mDst(aDst) + { + } + + ~ComTypeOutConverter() + { + if (mDst) + mPtr.queryInterfaceTo(mDst); + } + + ComPtr<A> &ptr() + { + return mPtr; + } + +private: + ComPtr<A> mPtr; + A **mDst; +}; + +template <class A> +class ComTypeInConverter +{ +public: + ComTypeInConverter() : mSrc(NULL) + { + } + + ComTypeInConverter(A *aSrc) : mSrc(aSrc) + { + } + + ~ComTypeInConverter() + { + } + + const ComPtr<A> &ptr() + { + return mSrc; + } + +private: + const ComPtr<A> mSrc; +}; + +template <class A> +class ArrayComTypeOutConverter +{ +public: + ArrayComTypeOutConverter() : +#ifdef VBOX_WITH_XPCOM + mDstSize(NULL), + mDst(NULL) +#else // !VBOX_WITH_XPCOM + mDst(NULL) +#endif // !VBOX_WITH_XPCOM + { + } + + ArrayComTypeOutConverter(ComSafeArrayOut(A *, aDst)) : +#ifdef VBOX_WITH_XPCOM + mDstSize(aDstSize), + mDst(aDst) +#else // !VBOX_WITH_XPCOM + mDst(aDst) +#endif // !VBOX_WITH_XPCOM + { + } + + ~ArrayComTypeOutConverter() + { + if (mDst) + { + com::SafeIfaceArray<A> outArray(mArray); + outArray.detachTo(ComSafeArrayOutArg(mDst)); + } + } + + std::vector<ComPtr<A> > &array() + { + return mArray; + } + +private: + std::vector<ComPtr<A> > mArray; +#ifdef VBOX_WITH_XPCOM + PRUint32 *mDstSize; + A ***mDst; +#else // !VBOX_WITH_XPCOM + SAFEARRAY **mDst; +#endif // !VBOX_WITH_XPCOM +}; + +template <class A> +class ArrayComTypeInConverter +{ +public: + ArrayComTypeInConverter() + { + } + + ArrayComTypeInConverter(ComSafeArrayIn(A *, aSrc)) + { + if (!ComSafeArrayInIsNull(aSrc)) + { + com::SafeIfaceArray<A> inArray(ComSafeArrayInArg(aSrc)); + mArray.resize(inArray.size()); + for (size_t i = 0; i < inArray.size(); i++) + mArray[i] = inArray[i]; + } + } + + ~ArrayComTypeInConverter() + { + } + + const std::vector<ComPtr<A> > &array() + { + return mArray; + } + +private: + std::vector<ComPtr<A> > mArray; +}; + +template <typename A> +class ArrayOutConverter +{ +public: + ArrayOutConverter() : +#ifdef VBOX_WITH_XPCOM + mDstSize(NULL), + mDst(NULL) +#else // !VBOX_WITH_XPCOM + mDst(NULL) +#endif // !VBOX_WITH_XPCOM + { + } + + ArrayOutConverter(ComSafeArrayOut(A, aDst)) : +#ifdef VBOX_WITH_XPCOM + mDstSize(aDstSize), + mDst(aDst) +#else // !VBOX_WITH_XPCOM + mDst(aDst) +#endif // !VBOX_WITH_XPCOM + { + } + + ~ArrayOutConverter() + { + if (mDst) + { + com::SafeArray<A> outArray(mArray.size()); + for (size_t i = 0; i < mArray.size(); i++) + outArray[i] = mArray[i]; + outArray.detachTo(ComSafeArrayOutArg(mDst)); + } + } + + std::vector<A> &array() + { + return mArray; + } + +private: + std::vector<A> mArray; +#ifdef VBOX_WITH_XPCOM + PRUint32 *mDstSize; + A **mDst; +#else // !VBOX_WITH_XPCOM + SAFEARRAY **mDst; +#endif // !VBOX_WITH_XPCOM +}; + +template <typename A> +class ArrayInConverter +{ +public: + ArrayInConverter() + { + } + + ArrayInConverter(ComSafeArrayIn(A, aSrc)) + { + if (!ComSafeArrayInIsNull(aSrc)) + { + com::SafeArray<A> inArray(ComSafeArrayInArg(aSrc)); + mArray.resize(inArray.size()); + for (size_t i = 0; i < inArray.size(); i++) + mArray[i] = inArray[i]; + } + } + + ~ArrayInConverter() + { + } + + const std::vector<A> &array() + { + return mArray; + } + +private: + std::vector<A> mArray; +}; + +#endif /* !MAIN_INCLUDED_Wrapper_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/netif.h b/src/VBox/Main/include/netif.h new file mode 100644 index 00000000..a48b8c92 --- /dev/null +++ b/src/VBox/Main/include/netif.h @@ -0,0 +1,145 @@ +/* $Id: netif.h $ */ +/** @file + * Main - Network Interfaces. + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_netif_h +#define MAIN_INCLUDED_netif_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/net.h> +/** @todo r=bird: The inlined code below that drags in asm.h here. I doubt + * speed is very important here, so move it into a .cpp file, please. */ +#include <iprt/asm.h> + +#ifndef RT_OS_WINDOWS +# include <arpa/inet.h> +# include <stdio.h> +#endif /* !RT_OS_WINDOWS */ + +#define VBOXNET_IPV4ADDR_DEFAULT 0x0138A8C0 /* 192.168.56.1 */ +#define VBOXNET_IPV4MASK_DEFAULT "255.255.255.0" + +#define VBOXNET_MAX_SHORT_NAME 50 + +#if 1 +/** + * Encapsulation type. + * @note Must match HostNetworkInterfaceMediumType_T exactly. + * @todo r=bird: Why are we duplicating HostNetworkInterfaceMediumType_T here?!? + */ +typedef enum NETIFTYPE +{ + NETIF_T_UNKNOWN, + NETIF_T_ETHERNET, + NETIF_T_PPP, + NETIF_T_SLIP +} NETIFTYPE; + +/** + * Current state of the interface. + * @note Must match HostNetworkInterfaceStatus_T exactly. + * @todo r=bird: Why are we duplicating HostNetworkInterfaceStatus_T here?!? + */ +typedef enum NETIFSTATUS +{ + NETIF_S_UNKNOWN, + NETIF_S_UP, + NETIF_S_DOWN +} NETIFSTATUS; + +/** + * Host Network Interface Information. + */ +typedef struct NETIFINFO +{ + NETIFINFO *pNext; + RTNETADDRIPV4 IPAddress; + RTNETADDRIPV4 IPNetMask; + RTNETADDRIPV6 IPv6Address; + RTNETADDRIPV6 IPv6NetMask; + BOOL fDhcpEnabled; + BOOL fIsDefault; + BOOL fWireless; + RTMAC MACAddress; + NETIFTYPE enmMediumType; + NETIFSTATUS enmStatus; + uint32_t uSpeedMbits; + RTUUID Uuid; + char szShortName[VBOXNET_MAX_SHORT_NAME]; + char szName[1]; +} NETIFINFO; + +/** Pointer to a network interface info. */ +typedef NETIFINFO *PNETIFINFO; +/** Pointer to a const network interface info. */ +typedef NETIFINFO const *PCNETIFINFO; +#endif + +int NetIfList(std::list <ComObjPtr<HostNetworkInterface> > &list); +int NetIfEnableStaticIpConfig(VirtualBox *pVBox, HostNetworkInterface * pIf, ULONG aOldIp, ULONG aNewIp, ULONG aMask); +int NetIfEnableStaticIpConfigV6(VirtualBox *pVBox, HostNetworkInterface *pIf, const Utf8Str &aOldIPV6Address, const Utf8Str &aIPV6Address, ULONG aIPV6MaskPrefixLength); +int NetIfEnableDynamicIpConfig(VirtualBox *pVBox, HostNetworkInterface * pIf); +#ifdef RT_OS_WINDOWS +int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVBox, IHostNetworkInterface **aHostNetworkInterface, IProgress **aProgress, + IN_BSTR bstrName = NULL); +#else +int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVBox, IHostNetworkInterface **aHostNetworkInterface, IProgress **aProgress, + const char *pszName = NULL); +#endif +int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *pVBox, const Guid &aId, IProgress **aProgress); +int NetIfGetConfig(HostNetworkInterface * pIf, NETIFINFO *); +int NetIfGetConfigByName(PNETIFINFO pInfo); +int NetIfGetState(const char *pcszIfName, NETIFSTATUS *penmState); +int NetIfGetLinkSpeed(const char *pcszIfName, uint32_t *puMbits); +int NetIfDhcpRediscover(VirtualBox *pVBox, HostNetworkInterface * pIf); +int NetIfAdpCtlOut(const char *pszName, const char *pszCmd, char *pszBuffer, size_t cBufSize); + +DECLINLINE(Bstr) getDefaultIPv4Address(Bstr bstrIfName) +{ + /* Get the index from the name */ + Utf8Str strTmp = bstrIfName; + const char *pcszIfName = strTmp.c_str(); + size_t iPos = strcspn(pcszIfName, "0123456789"); + uint32_t uInstance = 0; + if (pcszIfName[iPos]) + uInstance = RTStrToUInt32(pcszIfName + iPos); + + in_addr tmp; +#if defined(RT_OS_WINDOWS) + tmp.S_un.S_addr = VBOXNET_IPV4ADDR_DEFAULT + (uInstance << 16); +#else + tmp.s_addr = VBOXNET_IPV4ADDR_DEFAULT + (uInstance << 16); +#endif + char *addr = inet_ntoa(tmp); + return Bstr(addr); +} + +#endif /* !MAIN_INCLUDED_netif_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/objectslist.h b/src/VBox/Main/include/objectslist.h new file mode 100644 index 00000000..2dd2f92d --- /dev/null +++ b/src/VBox/Main/include/objectslist.h @@ -0,0 +1,224 @@ +/* $Id: objectslist.h $ */ +/** @file + * + * List of COM objects + */ + +/* + * Copyright (C) 2009-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_objectslist_h +#define MAIN_INCLUDED_objectslist_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <list> +#include <VBox/com/ptr.h> + +/** + * Implements a "flat" objects list with a lock. Since each such list + * has its own lock it is not a good idea to implement trees with this. + * + * ObjectList<T> is designed to behave as if it were a std::list of + * COM pointers of class T; in other words, + * ObjectList<Medium> behaves like std::list< ComObjPtr<Medium> > but + * it's less typing. Iterators, front(), size(), begin() and end() + * are implemented. + * + * In addition it automatically includes an RWLockHandle which can be + * accessed with getLockHandle(). + * + * If you need the raw std::list for some reason you can access it with + * getList(). + * + * The destructor automatically calls uninit() on every contained + * COM object. If this is not desired, clear the member list before + * deleting the list object. + */ +template<typename T> +class ObjectsList +{ +public: + typedef ComObjPtr<T> MyType; + typedef std::list<MyType> MyList; + + typedef typename MyList::iterator iterator; + typedef typename MyList::const_iterator const_iterator; + // typename is necessary to disambiguate "::iterator" in templates; see + // the "this might hurt your head" part in + // http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18 + + ObjectsList(RWLockHandle &lockHandle) + : m_lock(lockHandle) + { } + + ~ObjectsList() + { + uninitAll(); + } + +private: + // prohibit copying and assignment + ObjectsList(const ObjectsList &d); + ObjectsList& operator=(const ObjectsList &d); + +public: + + /** + * Returns the lock handle which protects this list, for use with + * AutoReadLock or AutoWriteLock. + */ + RWLockHandle& getLockHandle() + { + return m_lock; + } + + /** + * Calls m_ll.push_back(p) with locking. + * @param p + */ + void addChild(MyType p) + { + AutoWriteLock al(m_lock COMMA_LOCKVAL_SRC_POS); + m_ll.push_back(p); + } + + /** + * Calls m_ll.remove(p) with locking. Does NOT call uninit() + * on the contained object. + * @param p + */ + void removeChild(MyType p) + { + AutoWriteLock al(m_lock COMMA_LOCKVAL_SRC_POS); + m_ll.remove(p); + } + + /** + * Appends all objects from another list to the member list. + * Locks the other list for reading but does not lock "this" + * (because it might be on the caller's stack and needs no + * locking). + * @param ll + */ + void appendOtherList(ObjectsList<T> &ll) + { + AutoReadLock alr(ll.getLockHandle() COMMA_LOCKVAL_SRC_POS); + for (const_iterator it = ll.begin(); + it != ll.end(); + ++it) + { + m_ll.push_back(*it); + } + } + + /** + * Calls uninit() on every COM object on the list and then + * clears the list, with locking. + */ + void uninitAll() + { + /* The implementation differs from the high level description, because + * it isn't safe to hold any locks when invoking uninit() methods. It + * leads to incorrect lock order (first lock, then the Caller related + * event semaphore) and thus deadlocks. Dropping the lock is vital, + * and means we can't rely on iterators while not holding the lock. */ + AutoWriteLock al(m_lock COMMA_LOCKVAL_SRC_POS); + while (!m_ll.empty()) + { + /* Need a copy of the element, have to delete the entry before + * dropping the lock, otherwise someone else might mess with the + * list in the mean time, leading to erratic behavior. */ + MyType q = m_ll.front(); + m_ll.pop_front(); + al.release(); + q->uninit(); + al.acquire(); + } + } + + /** + * Returns the no. of objects on the list (std::list compatibility) + * with locking. + */ + size_t size() + { + AutoReadLock al(m_lock COMMA_LOCKVAL_SRC_POS); + return m_ll.size(); + } + + /** + * Returns a raw pointer to the member list of objects. + * Does not lock! + * @return + */ + MyList& getList() + { + return m_ll; + } + + /** + * Returns the first object on the list (std::list compatibility) + * with locking. + */ + MyType front() + { + AutoReadLock al(m_lock COMMA_LOCKVAL_SRC_POS); + return m_ll.front(); + } + + /** + * Returns the begin iterator from the list (std::list compatibility). + * Does not lock! + * @return + */ + iterator begin() + { + return m_ll.begin(); + } + + /** + * Returns the end iterator from the list (std::list compatibility). + * Does not lock! + */ + iterator end() + { + return m_ll.end(); + } + + void insert(iterator it, MyType &p) + { + m_ll.insert(it, p); + } + + void erase(iterator it) + { + m_ll.erase(it); + } + +private: + MyList m_ll; + RWLockHandle &m_lock; +}; + +#endif /* !MAIN_INCLUDED_objectslist_h */ diff --git a/src/VBox/Main/include/ovfreader.h b/src/VBox/Main/include/ovfreader.h new file mode 100644 index 00000000..848434b6 --- /dev/null +++ b/src/VBox/Main/include/ovfreader.h @@ -0,0 +1,732 @@ +/* $Id: ovfreader.h $ */ +/** @file + * VirtualBox Main - OVF reader declarations. + * + * Depends only on IPRT, including the RTCString and IPRT XML classes. + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_ovfreader_h +#define MAIN_INCLUDED_ovfreader_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "iprt/cpp/xml.h" +#include <map> +#include <vector> + +namespace ovf +{ + +//////////////////////////////////////////////////////////////////////////////// +// +// Errors +// +//////////////////////////////////////////////////////////////////////////////// + +/** + * Thrown by OVFReader for any kind of error that is not an XML error but + * still makes the OVF impossible to parse. Based on xml::LogicError so + * that one catch() for all xml::LogicError can handle all possible errors. + */ +class OVFLogicError : public xml::LogicError +{ +public: + OVFLogicError(const char *aFormat, ...); +}; + + +//////////////////////////////////////////////////////////////////////////////// +// +// Enumerations +// +//////////////////////////////////////////////////////////////////////////////// + +/** + * CIM OS values. + * + * The OVF 1.10 spec refers to some CIM_OperatingSystem.mof doc. Could this be it: + * http://cvs.opengroup.org/cgi-bin/cvsweb.cgi/pegasus/Schemas/CIM231/DMTF/System/CIM_OperatingSystem.mof + * + * @todo r=bird: Why are the values are repeating 'CIMOS'. CIMOSType_T is also + * repeating it self, 'Type' and '_T'. Why not call it kCIOMOpSys, + * easier to read as well. + * Then also apply: s/CIMOSType_CIMOS_/kCIMOpSys_/g + */ +enum CIMOSType_T +{ + CIMOSType_CIMOS_Unknown = 0, + CIMOSType_CIMOS_Other = 1, + CIMOSType_CIMOS_MACOS = 2, + CIMOSType_CIMOS_ATTUNIX = 3, + CIMOSType_CIMOS_DGUX = 4, + CIMOSType_CIMOS_DECNT = 5, + CIMOSType_CIMOS_Tru64UNIX = 6, + CIMOSType_CIMOS_OpenVMS = 7, + CIMOSType_CIMOS_HPUX = 8, + CIMOSType_CIMOS_AIX = 9, + CIMOSType_CIMOS_MVS = 10, + CIMOSType_CIMOS_OS400 = 11, + CIMOSType_CIMOS_OS2 = 12, + CIMOSType_CIMOS_JavaVM = 13, + CIMOSType_CIMOS_MSDOS = 14, + CIMOSType_CIMOS_WIN3x = 15, + CIMOSType_CIMOS_WIN95 = 16, + CIMOSType_CIMOS_WIN98 = 17, + CIMOSType_CIMOS_WINNT = 18, + CIMOSType_CIMOS_WINCE = 19, + CIMOSType_CIMOS_NCR3000 = 20, + CIMOSType_CIMOS_NetWare = 21, + CIMOSType_CIMOS_OSF = 22, + CIMOSType_CIMOS_DCOS = 23, + CIMOSType_CIMOS_ReliantUNIX = 24, + CIMOSType_CIMOS_SCOUnixWare = 25, + CIMOSType_CIMOS_SCOOpenServer = 26, + CIMOSType_CIMOS_Sequent = 27, + CIMOSType_CIMOS_IRIX = 28, + CIMOSType_CIMOS_Solaris = 29, + CIMOSType_CIMOS_SunOS = 30, + CIMOSType_CIMOS_U6000 = 31, + CIMOSType_CIMOS_ASERIES = 32, + CIMOSType_CIMOS_HPNonStopOS = 33, + CIMOSType_CIMOS_HPNonStopOSS = 34, + CIMOSType_CIMOS_BS2000 = 35, + CIMOSType_CIMOS_LINUX = 36, + CIMOSType_CIMOS_Lynx = 37, + CIMOSType_CIMOS_XENIX = 38, + CIMOSType_CIMOS_VM = 39, + CIMOSType_CIMOS_InteractiveUNIX = 40, + CIMOSType_CIMOS_BSDUNIX = 41, + CIMOSType_CIMOS_FreeBSD = 42, + CIMOSType_CIMOS_NetBSD = 43, + CIMOSType_CIMOS_GNUHurd = 44, + CIMOSType_CIMOS_OS9 = 45, + CIMOSType_CIMOS_MACHKernel = 46, + CIMOSType_CIMOS_Inferno = 47, + CIMOSType_CIMOS_QNX = 48, + CIMOSType_CIMOS_EPOC = 49, + CIMOSType_CIMOS_IxWorks = 50, + CIMOSType_CIMOS_VxWorks = 51, + CIMOSType_CIMOS_MiNT = 52, + CIMOSType_CIMOS_BeOS = 53, + CIMOSType_CIMOS_HPMPE = 54, + CIMOSType_CIMOS_NextStep = 55, + CIMOSType_CIMOS_PalmPilot = 56, + CIMOSType_CIMOS_Rhapsody = 57, + CIMOSType_CIMOS_Windows2000 = 58, + CIMOSType_CIMOS_Dedicated = 59, + CIMOSType_CIMOS_OS390 = 60, + CIMOSType_CIMOS_VSE = 61, + CIMOSType_CIMOS_TPF = 62, + CIMOSType_CIMOS_WindowsMe = 63, + CIMOSType_CIMOS_CalderaOpenUNIX = 64, + CIMOSType_CIMOS_OpenBSD = 65, + CIMOSType_CIMOS_NotApplicable = 66, + CIMOSType_CIMOS_WindowsXP = 67, + CIMOSType_CIMOS_zOS = 68, + CIMOSType_CIMOS_MicrosoftWindowsServer2003 = 69, + CIMOSType_CIMOS_MicrosoftWindowsServer2003_64 = 70, + CIMOSType_CIMOS_WindowsXP_64 = 71, + CIMOSType_CIMOS_WindowsXPEmbedded = 72, + CIMOSType_CIMOS_WindowsVista = 73, + CIMOSType_CIMOS_WindowsVista_64 = 74, + CIMOSType_CIMOS_WindowsEmbeddedforPointofService = 75, + CIMOSType_CIMOS_MicrosoftWindowsServer2008 = 76, + CIMOSType_CIMOS_MicrosoftWindowsServer2008_64 = 77, + CIMOSType_CIMOS_FreeBSD_64 = 78, + CIMOSType_CIMOS_RedHatEnterpriseLinux = 79, + CIMOSType_CIMOS_RedHatEnterpriseLinux_64 = 80, + CIMOSType_CIMOS_Solaris_64 = 81, + CIMOSType_CIMOS_SUSE = 82, + CIMOSType_CIMOS_SUSE_64 = 83, + CIMOSType_CIMOS_SLES = 84, + CIMOSType_CIMOS_SLES_64 = 85, + CIMOSType_CIMOS_NovellOES = 86, + CIMOSType_CIMOS_NovellLinuxDesktop = 87, + CIMOSType_CIMOS_SunJavaDesktopSystem = 88, + CIMOSType_CIMOS_Mandriva = 89, + CIMOSType_CIMOS_Mandriva_64 = 90, + CIMOSType_CIMOS_TurboLinux = 91, + CIMOSType_CIMOS_TurboLinux_64 = 92, + CIMOSType_CIMOS_Ubuntu = 93, + CIMOSType_CIMOS_Ubuntu_64 = 94, + CIMOSType_CIMOS_Debian = 95, + CIMOSType_CIMOS_Debian_64 = 96, + CIMOSType_CIMOS_Linux_2_4_x = 97, + CIMOSType_CIMOS_Linux_2_4_x_64 = 98, + CIMOSType_CIMOS_Linux_2_6_x = 99, + CIMOSType_CIMOS_Linux_2_6_x_64 = 100, + CIMOSType_CIMOS_Linux_64 = 101, + CIMOSType_CIMOS_Other_64 = 102, + // types added with CIM 2.25.0 follow: + CIMOSType_CIMOS_WindowsServer2008R2 = 103, + CIMOSType_CIMOS_VMwareESXi = 104, + CIMOSType_CIMOS_Windows7 = 105, + CIMOSType_CIMOS_CentOS = 106, + CIMOSType_CIMOS_CentOS_64 = 107, + CIMOSType_CIMOS_OracleLinux = 108, + CIMOSType_CIMOS_OracleLinux_64 = 109, + CIMOSType_CIMOS_eComStation = 110, + // no new types added with CIM 2.26.0 + CIMOSType_CIMOS_WindowsServer2011 = 111, + CIMOSType_CIMOS_WindowsServer2012 = 112, + CIMOSType_CIMOS_Windows8 = 113, + CIMOSType_CIMOS_Windows8_64 = 114, + CIMOSType_CIMOS_WindowsServer2012R2 = 115, + CIMOSType_CIMOS_Windows8_1 = 116, + CIMOSType_CIMOS_Windows8_1_64 = 117, + CIMOSType_CIMOS_WindowsServer2016 = 118, + CIMOSType_CIMOS_Windows10 = 119, + CIMOSType_CIMOS_Windows10_64 = 120, + // the above covers up to CIM 2.52.0, without checking when it was added +}; + +enum OVFVersion_T +{ + OVFVersion_unknown, + OVFVersion_0_9, + OVFVersion_1_0, + OVFVersion_2_0 +}; + +const char* const OVF09_URI_string = "http://www.vmware.com/schema/ovf/1/envelope"; +const char* const OVF10_URI_string = "http://schemas.dmtf.org/ovf/envelope/1"; +const char* const OVF20_URI_string = "http://schemas.dmtf.org/ovf/envelope/2"; + +const char* const DTMF_SPECS_URI = "http://schemas.dmtf.org/wbem/cim-html/2/"; + +//////////////////////////////////////////////////////////////////////////////// +// +// Envelope data +// +//////////////////////////////////////////////////////////////////////////////// +struct EnvelopeData +{ + OVFVersion_T version;//OVF standard version, it is used internally only by VirtualBox + RTCString lang;//language + + OVFVersion_T getOVFVersion() const + { + return version; + } + + + RTCString getStringOVFVersion() const + { + if (version == OVFVersion_0_9) + return "0.9"; + else if (version == OVFVersion_1_0) + return "1.0"; + else if (version == OVFVersion_2_0) + return "2.0"; + else + return ""; + } + + void setOVFVersion(OVFVersion_T v) + { + version = v; + } +}; + + +struct FileReference +{ + RTCString strHref; // value from /References/File/@href (filename) + RTCString strDiskId; // value from /References/File/@id () +}; + +typedef std::map<uint32_t, FileReference> FileReferenceMap; + +//////////////////////////////////////////////////////////////////////////////// +// +// Hardware definition structs +// +//////////////////////////////////////////////////////////////////////////////// + +struct DiskImage +{ + // fields from /DiskSection/Disk + RTCString strDiskId; // value from DiskSection/Disk/@diskId + int64_t iCapacity; // value from DiskSection/Disk/@capacity; + // (maximum size for dynamic images, I guess; we always translate this to bytes) + int64_t iPopulatedSize; // optional value from DiskSection/Disk/@populatedSize + // (actual used size of disk, always in bytes; can be an estimate of used disk + // space, but cannot be larger than iCapacity; -1 if not set) + RTCString strFormat; // value from DiskSection/Disk/@format + // typically http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized + RTCString uuidVBox; // optional; if the file was exported by VirtualBox >= 3.2, + // then this has the UUID with which the disk was registered + + // fields from /References/File; the spec says the file reference from disk can be empty, + // so in that case, strFilename will be empty, then a new disk should be created + RTCString strHref; // value from /References/File/@href (filename); if empty, then the remaining fields are ignored + int64_t iSize; // value from /References/File/@size (optional according to spec; then we set -1 here) + int64_t iChunkSize; // value from /References/File/@chunkSize (optional, unsupported) + RTCString strCompression; // value from /References/File/@compression (optional, can be "gzip" according to spec) + + // additional field which has a descriptive size in megabytes derived from the above; this can be used for progress reports + uint32_t ulSuggestedSizeMB; +}; + +enum ResourceType_T +{ + ResourceType_Other = 1, + ResourceType_ComputerSystem = 2, + ResourceType_Processor = 3, + ResourceType_Memory = 4, + ResourceType_IDEController = 5, + ResourceType_ParallelSCSIHBA = 6, + ResourceType_FCHBA = 7, + ResourceType_iSCSIHBA = 8, + ResourceType_IBHCA = 9, + ResourceType_EthernetAdapter = 10, + ResourceType_OtherNetworkAdapter = 11, + ResourceType_IOSlot = 12, + ResourceType_IODevice = 13, + ResourceType_FloppyDrive = 14, + ResourceType_CDDrive = 15, + ResourceType_DVDDrive = 16, + ResourceType_HardDisk = 17, + ResourceType_TapeDrive = 18, + ResourceType_StorageExtent = 19, + ResourceType_OtherStorageDevice = 20, + ResourceType_SerialPort = 21, + ResourceType_ParallelPort = 22, + ResourceType_USBController = 23, + ResourceType_GraphicsController = 24, + ResourceType_IEEE1394Controller = 25, + ResourceType_PartitionableUnit = 26, + ResourceType_BasePartitionableUnit = 27, + ResourceType_Power = 28, + ResourceType_CoolingCapacity = 29, + ResourceType_EthernetSwitchPort = 30, + ResourceType_LogicalDisk = 31, + ResourceType_StorageVolume = 32, + ResourceType_EthernetConnection = 33, + ResourceType_SoundCard = 35 /**< @todo r=klaus: Not part of OVF/CIM spec, should use "Other" or some value from 0x8000..0xffff. */ +}; + + +enum StorageAccessType_T +{ StorageAccessType_Unknown = 0, + StorageAccessType_Readable = 1, + StorageAccessType_Writeable = 2, + StorageAccessType_ReadWrite = 3 +}; + +enum ComplianceType_T +{ ComplianceType_No = 0, + ComplianceType_Soft = 1, + ComplianceType_Medium = 2, + ComplianceType_Strong = 3 +}; + +class VirtualHardwareItem +{ +public: + RTCString strDescription; + RTCString strCaption; + RTCString strElementName; + + RTCString strInstanceID; + RTCString strParent; + + ResourceType_T resourceType; + RTCString strOtherResourceType; + RTCString strResourceSubType; + bool fResourceRequired; + + RTCString strHostResource; ///< "Abstractly specifies how a device shall connect to a resource on the deployment platform. + /// Not all devices need a backing." Used with disk items, for which this + /// references a virtual disk from the Disks section. + bool fAutomaticAllocation; + bool fAutomaticDeallocation; + RTCString strConnection; ///< "All Ethernet adapters that specify the same abstract network connection name within an OVF + /// package shall be deployed on the same network. The abstract network connection name shall be + /// listed in the NetworkSection at the outermost envelope level." We ignore this and only set up + /// a network adapter depending on the network name. + RTCString strAddress; ///< "Device-specific. For an Ethernet adapter, this specifies the MAC address." + int32_t lAddress; ///< strAddress as an integer, if applicable. + RTCString strAddressOnParent;///< "For a device, this specifies its location on the controller." + RTCString strAllocationUnits;///< "Specifies the units of allocation used. For example, “byte * 2^20”." + uint64_t ullVirtualQuantity; ///< "Specifies the quantity of resources presented. For example, “256”." + uint64_t ullReservation; ///< "Specifies the minimum quantity of resources guaranteed to be available." + uint64_t ullLimit; ///< "Specifies the maximum quantity of resources that will be granted." + uint64_t ullWeight; ///< "Specifies a relative priority for this allocation in relation to other allocations." + + RTCString strConsumerVisibility; + RTCString strMappingBehavior; + RTCString strPoolID; + uint32_t ulBusNumber; ///< seen with IDE controllers, but not listed in OVF spec + + int m_iLineNumber; ///< line number of \<Item\> element in XML source; cached for error messages + + VirtualHardwareItem() + : fResourceRequired(false) + , fAutomaticAllocation(false) + , fAutomaticDeallocation(false) + , ullVirtualQuantity(0) + , ullReservation(0) + , ullLimit(0) + , ullWeight(0) + , ulBusNumber(0) + , m_iLineNumber(0) + , fDefault(false) + { + itemName = "Item"; + } + + virtual ~VirtualHardwareItem() { /* Makes MSC happy. */ } + + void fillItem(const xml::ElementNode *item); + + void setDefaultFlag() + { + fDefault = true; + } + + bool isThereDefaultValues() const + { + return fDefault; + } + + void checkConsistencyAndCompliance() RT_THROW(OVFLogicError) + { + _checkConsistencyAndCompliance(); + } + +protected: + virtual void _checkConsistencyAndCompliance() RT_THROW(OVFLogicError); + virtual const RTCString& getItemName() + { + return _getItemName(); + } + +private: + RTCString itemName; + bool fDefault;//true means that some fields were absent in the XML and some default values were assigned to. + + virtual const RTCString& _getItemName() + { + return itemName; + } +}; + +class StorageItem: public VirtualHardwareItem +{ + //see DMTF Schema Documentation http://schemas.dmtf.org/wbem/cim-html/2/ + StorageAccessType_T accessType; + RTCString strHostExtentName; +#if 0 /* unused */ + int16_t hostExtentNameFormat; + int16_t hostExtentNameNamespace; + int64_t hostExtentStartingAddress; +#endif + int64_t hostResourceBlockSize; + int64_t limit; + RTCString strOtherHostExtentNameFormat; + RTCString strOtherHostExtentNameNamespace; + int64_t reservation; + int64_t virtualQuantity; + RTCString strVirtualQuantityUnits; + int64_t virtualResourceBlockSize; + +public: + StorageItem() + : VirtualHardwareItem() + , accessType(StorageAccessType_Unknown) +#if 0 /* unused */ + , hostExtentNameFormat(-1) + , hostExtentNameNamespace(-1) + , hostExtentStartingAddress(-1) +#endif + , hostResourceBlockSize(-1) + , limit(-1) + , reservation(-1) + , virtualQuantity(-1) + , virtualResourceBlockSize(-1) + { + itemName = "StorageItem"; + }; + + void fillItem(const xml::ElementNode *item); + +protected: + virtual void _checkConsistencyAndCompliance() RT_THROW(OVFLogicError); +private: + RTCString itemName; + + virtual const RTCString& _getItemName() + { + return itemName; + } +}; + + +class EthernetPortItem: public VirtualHardwareItem +{ + //see DMTF Schema Documentation http://schemas.dmtf.org/wbem/cim-html/2/ +#if 0 /* unused */ + uint16_t DefaultPortVID; + uint16_t DefaultPriority; + uint16_t DesiredVLANEndpointMode; + uint32_t GroupID; + uint32_t ManagerID; + uint16_t NetworkPortProfileIDType; +#endif + RTCString strNetworkPortProfileID; + RTCString strOtherEndpointMode; + RTCString strOtherNetworkPortProfileIDTypeInfo; + RTCString strPortCorrelationID; +#if 0 /* unused */ + uint16_t PortVID; + bool Promiscuous; + uint64_t ReceiveBandwidthLimit; + uint16_t ReceiveBandwidthReservation; + bool SourceMACFilteringEnabled; + uint32_t VSITypeID; + uint8_t VSITypeIDVersion; + uint16_t AllowedPriorities[256]; + uint16_t AllowedToReceiveVLANs[256]; + uint16_t AllowedToTransmitVLANs[256]; +#endif + RTCString strAllowedToReceiveMACAddresses; + RTCString strAllowedToTransmitMACAddresses; + +public: + EthernetPortItem() : VirtualHardwareItem() + { + itemName = "EthernetPortItem"; + }; + + void fillItem(const xml::ElementNode *item); + +protected: + virtual void _checkConsistencyAndCompliance() RT_THROW(OVFLogicError); +private: + RTCString itemName; + + virtual const RTCString& _getItemName() + { + return itemName; + } +}; + +typedef std::map<RTCString, DiskImage> DiskImagesMap; + +struct VirtualSystem; + + +/** + * VirtualHardwareItem pointer vector with safe cleanup. + * + * We need to use object pointers because we also want EthernetPortItem and + * StorageItems to go into the container. + */ +class HardwareItemVector : public std::vector<VirtualHardwareItem *> +{ +public: + HardwareItemVector() : std::vector<VirtualHardwareItem *>() { } + ~HardwareItemVector() + { + for (iterator it = begin(); it != end(); ++it) + delete(*it); + clear(); + } + + /* There is no copying of this vector. We'd need something like shared_ptr for that. */ +private: + HardwareItemVector(const VirtualSystem &); + +}; + +struct HardDiskController +{ + RTCString strIdController; // instance ID (Item/InstanceId); this gets referenced from VirtualDisk + + enum ControllerSystemType { IDE, SATA, SCSI, VIRTIOSCSI }; + ControllerSystemType system; // one of IDE, SATA, SCSI, VIRTIOSCSI + + RTCString strControllerType; + // controller subtype (Item/ResourceSubType); e.g. "LsiLogic"; can be empty (esp. for IDE) + // note that we treat LsiLogicSAS as a SCSI controller (system == SCSI) even though VirtualBox + // treats it as a fourth class besides IDE, SATA, SCSI + + int32_t lAddress; // value from OVF "Address" element + bool fPrimary; // controller index; this is determined heuristically by the OVF reader and will + // be true for the first controller of this type (e.g. IDE primary ctler) or + // false for the next (e.g. IDE secondary ctler) + + HardDiskController() + : lAddress(0), + fPrimary(true) + { } +}; + +typedef std::map<RTCString, HardDiskController> ControllersMap; + +struct VirtualDisk +{ + RTCString strIdController; // SCSI (or IDE) controller this disk is connected to; + // this must match HardDiskController.strIdController and + // points into VirtualSystem.mapControllers + uint32_t ulAddressOnParent; // parsed strAddressOnParent of hardware item; will be 0 or 1 for IDE + // and possibly higher for disks attached to SCSI controllers (untested) + RTCString strDiskId; // if the hard disk has an ovf:/disk/<id> reference, + // this receives the <id> component; points to one of the + // references in Appliance::Data.mapDisks + bool fEmpty; //true - empty disk, e.g. the component <rasd:HostResource>...</rasd:HostResource> is absent. +}; + +typedef std::map<RTCString, VirtualDisk> VirtualDisksMap; + +/** + * A list of EthernetAdapters is contained in VirtualSystem, representing the + * ethernet adapters in the virtual system. + */ +struct EthernetAdapter +{ + RTCString strAdapterType; // "PCNet32" or "E1000" or whatever; from <rasd:ResourceSubType> + RTCString strNetworkName; // from <rasd:Connection> +}; + +typedef std::list<EthernetAdapter> EthernetAdaptersList; + +/** + * A list of VirtualSystem structs is created by OVFReader::read(). Each refers to + * a \<VirtualSystem\> block in the OVF file. + */ +struct VirtualSystem +{ + RTCString strName; // copy of VirtualSystem/@id + + RTCString strDescription; // copy of VirtualSystem/AnnotationSection content, if any + + CIMOSType_T cimos; + RTCString strCimosDesc; // readable description of the cimos type in the case of cimos = 0/1/102 + RTCString strTypeVBox; // optional type from @vbox:ostype attribute (VirtualBox 4.0 or higher) + + RTCString strVirtualSystemType; // generic hardware description; OVF says this can be something like "vmx-4" or "xen"; + // VMware Workstation 6.5 is "vmx-07" + + HardwareItemVector vecHardwareItems; //< vector containing all virtual hardware items in parsing order. + + uint64_t ullMemorySize; // always in bytes, copied from llHardwareItems; default = 0 (unspecified) + uint16_t cCPUs; // no. of CPUs, copied from llHardwareItems; default = 1 + + EthernetAdaptersList llEthernetAdapters; // (one for each VirtualSystem/Item[@ResourceType=10]element) + + ControllersMap mapControllers; + // list of hard disk controllers + // (one for each VirtualSystem/Item[@ResourceType=6] element with accumulated data from children) + + VirtualDisksMap mapVirtualDisks; + // (one for each VirtualSystem/Item[@ResourceType=17] element with accumulated data from children) + + bool fHasFloppyDrive; // true if there's a floppy item in mapHardwareItems + bool fHasCdromDrive; // true if there's a CD-ROM item in mapHardwareItems; ISO images are not yet supported by OVFtool + bool fHasUsbController; // true if there's a USB controller item in mapHardwareItems + + RTCString strSoundCardType; // if not empty, then the system wants a soundcard; this then specifies the hardware; + // VMware Workstation 6.5 uses "ensoniq1371" for example + + RTCString strLicenseText; // license info if any; receives contents of VirtualSystem/EulaSection/License + + RTCString strProduct; // product info if any; receives contents of VirtualSystem/ProductSection/Product + RTCString strVendor; // product info if any; receives contents of VirtualSystem/ProductSection/Vendor + RTCString strVersion; // product info if any; receives contents of VirtualSystem/ProductSection/Version + RTCString strProductUrl; // product info if any; receives contents of VirtualSystem/ProductSection/ProductUrl + RTCString strVendorUrl; // product info if any; receives contents of VirtualSystem/ProductSection/VendorUrl + + const xml::ElementNode *pelmVBoxMachine; // pointer to <vbox:Machine> element under <VirtualSystem> element or NULL if not present + + VirtualSystem() + : cimos(CIMOSType_CIMOS_Unknown), + ullMemorySize(0), + cCPUs(1), + fHasFloppyDrive(false), + fHasCdromDrive(false), + fHasUsbController(false), + pelmVBoxMachine(NULL) + { + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// Class OVFReader +// +//////////////////////////////////////////////////////////////////////////////// + +/** + * OVFReader attempts to open, read in and parse an OVF XML file. This is all done + * in the constructor; if there is any kind of error in the file -- filesystem error + * from IPRT, XML parsing errors from libxml, or OVF logical errors --, exceptions + * are thrown. These are all based on xml::Error. + * + * Hence, use this class as follows: +<code> + OVFReader *pReader = NULL; + try + { + pReader = new("/path/to/file.ovf"); + } + catch (xml::Error &e) + { + printf("A terrible thing happened: %s", e.what()); + } + // now go look at pReader->m_llVirtualSystem and what's in there + if (pReader) + delete pReader; +</code> + */ +class OVFReader +{ +public: + OVFReader(); + OVFReader(const void *pvBuf, size_t cbSize, const RTCString &path); + OVFReader(const RTCString &path); + + // Data fields + EnvelopeData m_envelopeData; //data of root element "Envelope" + RTCString m_strPath; // file name given to constructor + DiskImagesMap m_mapDisks; // map of DiskImage structs, sorted by DiskImage.strDiskId + std::list<VirtualSystem> m_llVirtualSystems; // list of virtual systems, created by and valid after read() + +private: + xml::Document m_doc; + + void parse(); + void LoopThruSections(const xml::ElementNode *pReferencesElem, const xml::ElementNode *pCurElem); + void HandleDiskSection(const xml::ElementNode *pReferencesElem, const xml::ElementNode *pSectionElem); + void HandleNetworkSection(const xml::ElementNode *pSectionElem); + void HandleVirtualSystemContent(const xml::ElementNode *pContentElem); +}; + +} // end namespace ovf + +#endif /* !MAIN_INCLUDED_ovfreader_h */ + diff --git a/src/VBox/Main/include/vbox-libhal.h b/src/VBox/Main/include/vbox-libhal.h new file mode 100644 index 00000000..09aa113b --- /dev/null +++ b/src/VBox/Main/include/vbox-libhal.h @@ -0,0 +1,80 @@ +/* $Id: vbox-libhal.h $ */ +/** @file + * + * Module to dynamically load libhal and libdbus and load all symbols + * which are needed by VirtualBox. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_vbox_libhal_h +#define MAIN_INCLUDED_vbox_libhal_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <stdint.h> + +#define LIB_HAL "libhal.so.1" + +/** Types from the dbus and hal header files which we need. These are taken more or less + verbatim from the DBus and Hal public interface header files. */ +struct DBusError +{ + const char *name; + const char *message; + unsigned int dummy1 : 1; /**< placeholder */ + unsigned int dummy2 : 1; /**< placeholder */ + unsigned int dummy3 : 1; /**< placeholder */ + unsigned int dummy4 : 1; /**< placeholder */ + unsigned int dummy5 : 1; /**< placeholder */ + void *padding1; /**< placeholder */ +}; +struct DBusConnection; +typedef struct DBusConnection DBusConnection; +typedef uint32_t dbus_bool_t; +typedef enum { DBUS_BUS_SESSON, DBUS_BUS_SYSTEM, DBUS_BUS_STARTER } DBusBusType; +struct LibHalContext_s; +typedef struct LibHalContext_s LibHalContext; + +/** The following are the symbols which we need from libdbus and libhal. */ +extern void (*gDBusErrorInit)(DBusError *); +extern DBusConnection *(*gDBusBusGet)(DBusBusType, DBusError *); +extern void (*gDBusErrorFree)(DBusError *); +extern void (*gDBusConnectionUnref)(DBusConnection *); +extern LibHalContext *(*gLibHalCtxNew)(void); +extern dbus_bool_t (*gLibHalCtxSetDBusConnection)(LibHalContext *, DBusConnection *); +extern dbus_bool_t (*gLibHalCtxInit)(LibHalContext *, DBusError *); +extern char **(*gLibHalFindDeviceStringMatch)(LibHalContext *, const char *, const char *, int *, + DBusError *); +extern char *(*gLibHalDeviceGetPropertyString)(LibHalContext *, const char *, const char *, + DBusError *); +extern void (*gLibHalFreeString)(char *); +extern void (*gLibHalFreeStringArray)(char **); +extern dbus_bool_t (*gLibHalCtxShutdown)(LibHalContext *, DBusError *); +extern dbus_bool_t (*gLibHalCtxFree)(LibHalContext *); + +extern bool gLibHalCheckPresence(void); + +#endif /* !MAIN_INCLUDED_vbox_libhal_h */ +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Main/include/vector.h b/src/VBox/Main/include/vector.h new file mode 100644 index 00000000..7c43dc8a --- /dev/null +++ b/src/VBox/Main/include/vector.h @@ -0,0 +1,368 @@ +/* $Id: vector.h $ */ +/** @file + * STL-inspired vector implementation in C + * @note functions in this file are inline to prevent warnings about + * unused static functions. I assume that in this day and age a + * compiler makes its own decisions about whether to actually + * inline a function. + * @note as this header is included in rdesktop-vrdp, we do not include other + * required header files here (to wit assert.h, err.h, mem.h and + * types.h). These must be included first. If this moves to iprt, we + * should write a wrapper around it doing that. + * @todo can we do more of the type checking at compile time somehow? + */ + +/* + * Copyright (C) 2008-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_vector_h +#define MAIN_INCLUDED_vector_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <stdlib.h> + + +/********************************************************************************************************************************* +* Helper macros and definitions * +*********************************************************************************************************************************/ + +/** The unit by which the vector capacity is increased */ +#define VECTOR_ALLOC_UNIT 16 + +/** Calculate a hash of a string of tokens for sanity type checking */ +#define VECTOR_TOKEN_HASH(token) \ + ((unsigned) \ + ( VECTOR_TOKEN_HASH4(token, 0) \ + ^ VECTOR_TOKEN_HASH4(token, 4) \ + ^ VECTOR_TOKEN_HASH4(token, 8) \ + ^ VECTOR_TOKEN_HASH4(token, 12))) + +/** Helper macro for @a VECTOR_TOKEN_HASH */ +#define VECTOR_TOKEN_HASH_VALUE(token, place, mul) \ + (sizeof(#token) > place ? #token[place] * mul : 0) + +/** Helper macro for @a VECTOR_TOKEN_HASH */ +#define VECTOR_TOKEN_HASH4(token, place) \ + VECTOR_TOKEN_HASH_VALUE(token, place, 0x1) \ + ^ VECTOR_TOKEN_HASH_VALUE(token, place + 1, 0x100) \ + ^ VECTOR_TOKEN_HASH_VALUE(token, place + 2, 0x10000) \ + ^ VECTOR_TOKEN_HASH_VALUE(token, place + 3, 0x1000000) + +/** Generic vector structure, used by @a VECTOR_OBJ and @a VECTOR_PTR */ +#define VECTOR_STRUCT \ +{ \ + /** The number of elements in the vector */ \ + size_t mcElements; \ + /** The current capacity of the vector */ \ + size_t mcCapacity; \ + /** The size of an element */ \ + size_t mcbElement; \ + /** Hash value of the element type */ \ + unsigned muTypeHash; \ + /** The elements themselves */ \ + void *mpvaElements; \ + /** Destructor for elements - takes a pointer to an element. */ \ + void (*mpfnCleanup)(void *); \ +} + +/*** Structure definitions ***/ + +/** A vector of values or objects */ +typedef struct VECTOR_OBJ VECTOR_STRUCT VECTOR_OBJ; + +/** A vector of pointer values. (A handy special case.) */ +typedef struct VECTOR_PTR VECTOR_STRUCT VECTOR_PTR; + +/** Convenience macro for annotating the type of the vector. Unfortunately the + * type name is only cosmetic. */ +/** @todo can we do something useful with the type? */ +#define VECTOR_OBJ(type) VECTOR_OBJ + +/** Convenience macro for annotating the type of the vector. Unfortunately the + * type name is only cosmetic. */ +#define VECTOR_PTR(type) VECTOR_PTR + +/*** Private helper functions and macros ***/ + +#define VEC_GET_ELEMENT_OBJ(pvaElements, cbElement, cElement) \ + ((void *)((char *)(pvaElements) + (cElement) * (cbElement))) + +#define VEC_GET_ELEMENT_PTR(pvaElements, cElement) \ + (*(void **)VEC_GET_ELEMENT_OBJ(pvaElements, sizeof(void *), cElement)) + +/** Default cleanup function that does nothing. */ +DECLINLINE(void) vecNoCleanup(void *pvElement) +{ + (void) pvElement; +} + +/** Expand an existing vector, implementation */ +DECLINLINE(int) vecExpand(size_t *pcCapacity, void **ppvaElements, + size_t cbElement) +{ + size_t cOldCap, cNewCap; + void *pRealloc; + + cOldCap = *pcCapacity; + cNewCap = cOldCap + VECTOR_ALLOC_UNIT; + pRealloc = RTMemRealloc(*ppvaElements, cNewCap * cbElement); + if (!pRealloc) + return VERR_NO_MEMORY; + *pcCapacity = cNewCap; + *ppvaElements = pRealloc; + return VINF_SUCCESS; +} + +/** Expand an existing vector */ +#define VEC_EXPAND(pvec) vecExpand(&(pvec)->mcCapacity, &(pvec)->mpvaElements, \ + (pvec)->mcbElement) + +/** Reset a vector, cleaning up all its elements. */ +DECLINLINE(void) vecClearObj(VECTOR_OBJ *pvec) +{ + unsigned i; + + for (i = 0; i < pvec->mcElements; ++i) + pvec->mpfnCleanup(VEC_GET_ELEMENT_OBJ(pvec->mpvaElements, + pvec->mcbElement, i)); + pvec->mcElements = 0; +} + +/** Reset a pointer vector, cleaning up all its elements. */ +DECLINLINE(void) vecClearPtr(VECTOR_PTR *pvec) +{ + unsigned i; + + for (i = 0; i < pvec->mcElements; ++i) + pvec->mpfnCleanup(VEC_GET_ELEMENT_PTR(pvec->mpvaElements, i)); + pvec->mcElements = 0; +} + +/** Clean up a vector */ +DECLINLINE(void) vecCleanupObj(VECTOR_OBJ *pvec) +{ + vecClearObj(pvec); + RTMemFree(pvec->mpvaElements); + pvec->mpvaElements = NULL; +} + +/** Clean up a pointer vector */ +DECLINLINE(void) vecCleanupPtr(VECTOR_PTR *pvec) +{ + vecClearPtr(pvec); + RTMemFree(pvec->mpvaElements); + pvec->mpvaElements = NULL; +} + +/** Initialise a vector structure, implementation */ +#define VEC_INIT(pvec, cbElement, uTypeHash, pfnCleanup) \ + pvec->mcElements = pvec->mcCapacity = 0; \ + pvec->mcbElement = cbElement; \ + pvec->muTypeHash = uTypeHash; \ + pvec->mpfnCleanup = pfnCleanup ? pfnCleanup : vecNoCleanup; \ + pvec->mpvaElements = NULL; + +/** Initialise a vector. */ +DECLINLINE(void) vecInitObj(VECTOR_OBJ *pvec, size_t cbElement, + unsigned uTypeHash, void (*pfnCleanup)(void *)) +{ + VEC_INIT(pvec, cbElement, uTypeHash, pfnCleanup) +} + +/** Initialise a pointer vector. */ +DECLINLINE(void) vecInitPtr(VECTOR_PTR *pvec, size_t cbElement, + unsigned uTypeHash, void (*pfnCleanup)(void *)) +{ + VEC_INIT(pvec, cbElement, uTypeHash, pfnCleanup) +} + +/** Add an element onto the end of a vector */ +DECLINLINE(int) vecPushBackObj(VECTOR_OBJ *pvec, unsigned uTypeHash, + void *pvElement) +{ + int rc2; + AssertReturn(pvec->muTypeHash == uTypeHash, VERR_INVALID_PARAMETER); + if ( pvec->mcElements == pvec->mcCapacity + && RT_FAILURE((rc2 = VEC_EXPAND(pvec)))) + return rc2; + memcpy(VEC_GET_ELEMENT_OBJ(pvec->mpvaElements, pvec->mcbElement, + pvec->mcElements), pvElement, pvec->mcbElement); + ++pvec->mcElements; + return VINF_SUCCESS; +} + +/** Add a pointer onto the end of a pointer vector */ +DECLINLINE(int) vecPushBackPtr(VECTOR_PTR *pvec, unsigned uTypeHash, + void *pv) +{ + int rc2; + AssertReturn(pvec->muTypeHash == uTypeHash, VERR_INVALID_PARAMETER); + if ( pvec->mcElements == pvec->mcCapacity + && RT_FAILURE((rc2 = VEC_EXPAND(pvec)))) + return rc2; + VEC_GET_ELEMENT_PTR(pvec->mpvaElements, pvec->mcElements) = pv; + ++pvec->mcElements; + return VINF_SUCCESS; +} + + +/********************************************************************************************************************************* +* Public interface macros * +*********************************************************************************************************************************/ + +/** + * Initialise a vector structure. Always succeeds. + * @param pvec pointer to an uninitialised vector structure + * @param type the type of the objects in the vector. As this is + * hashed by the preprocessor use of space etc is + * important. + * @param pfnCleanup cleanup function (void (*pfn)(void *)) that is called + * on a pointer to a vector element when that element is + * dropped + */ +#define VEC_INIT_OBJ(pvec, type, pfnCleanup) \ + vecInitObj(pvec, sizeof(type), VECTOR_TOKEN_HASH(type), \ + (void (*)(void*)) pfnCleanup) + +/** + * Initialise a vector-of-pointers structure. Always succeeds. + * @param pvec pointer to an uninitialised vector structure + * @param type the type of the pointers in the vector, including the + * final "*". As this is hashed by the preprocessor use + * of space etc is important. + * @param pfnCleanup cleanup function (void (*pfn)(void *)) that is called + * directly on a vector element when that element is + * dropped + */ +#define VEC_INIT_PTR(pvec, type, pfnCleanup) \ + vecInitPtr(pvec, sizeof(type), VECTOR_TOKEN_HASH(type), \ + (void (*)(void*)) pfnCleanup) + +/** + * Clean up a vector. + * @param pvec pointer to the vector to clean up. The clean up function + * specified at initialisation (if any) is called for each element + * in the vector. After clean up, the vector structure is invalid + * until it is re-initialised + */ +#define VEC_CLEANUP_OBJ vecCleanupObj + +/** + * Clean up a vector-of-pointers. + * @param pvec pointer to the vector to clean up. The clean up function + * specified at initialisation (if any) is called for each element + * in the vector. After clean up, the vector structure is invalid + * until it is re-initialised + */ +#define VEC_CLEANUP_PTR vecCleanupPtr + +/** + * Reinitialises a vector structure to empty. + * @param pvec pointer to the vector to re-initialise. The clean up function + * specified at initialisation (if any) is called for each element + * in the vector. + */ +#define VEC_CLEAR_OBJ vecClearObj + +/** + * Reinitialises a vector-of-pointers structure to empty. + * @param pvec pointer to the vector to re-initialise. The clean up function + * specified at initialisation (if any) is called for each element + * in the vector. + */ +#define VEC_CLEAR_PTR vecClearPtr + +/** + * Adds an element to the back of a vector. The element will be byte-copied + * and become owned by the vector, to be cleaned up by the vector's clean-up + * routine when the element is dropped. + * @returns iprt status code (VINF_SUCCESS or VERR_NO_MEMORY) + * @returns VERR_INVALID_PARAMETER if the type does not match the type given + * when the vector was initialised (asserted) + * @param pvec pointer to the vector on to which the element should be + * added + * @param type the type of the vector as specified at initialisation. + * Spacing etc is important. + * @param pvElement void pointer to the element to be added + */ +#define VEC_PUSH_BACK_OBJ(pvec, type, pvElement) \ + vecPushBackObj(pvec, VECTOR_TOKEN_HASH(type), \ + (pvElement) + ((pvElement) - (type *)(pvElement))) + +/** + * Adds a pointer to the back of a vector-of-pointers. The pointer will become + * owned by the vector, to be cleaned up by the vector's clean-up routine when + * it is dropped. + * @returns iprt status code (VINF_SUCCESS or VERR_NO_MEMORY) + * @returns VERR_INVALID_PARAMETER if the type does not match the type given + * when the vector was initialised (asserted) + * @param pvec pointer to the vector on to which the element should be + * added + * @param type the type of the vector as specified at initialisation. + * Spacing etc is important. + * @param pvElement the pointer to be added, typecast to pointer-to-void + */ +#define VEC_PUSH_BACK_PTR(pvec, type, pvElement) \ + vecPushBackPtr(pvec, VECTOR_TOKEN_HASH(type), \ + (pvElement) + ((pvElement) - (type)(pvElement))) + +/** + * Returns the count of elements in a vector. + * @param pvec pointer to the vector. + */ +#define VEC_SIZE_OBJ(pvec) (pvec)->mcElements + +/** + * Returns the count of elements in a vector-of-pointers. + * @param pvec pointer to the vector. + */ +#define VEC_SIZE_PTR VEC_SIZE_OBJ + +/** + * Iterates over a vector. + * + * Iterates over the vector elements from first to last and execute the + * following instruction or block on each iteration with @a pIterator set to + * point to the current element (that is, a pointer to the pointer element for + * a vector-of-pointers). Use in the same way as a "for" statement. + * + * @param pvec Pointer to the vector to be iterated over. + * @param type The type of the vector, must match the type specified at + * vector initialisation (including whitespace etc). + * @param pIterator A pointer to @a type which will be set to point to the + * current vector element on each iteration. + * + * @todo can we assert the correctness of the type in some way? + */ +#define VEC_FOR_EACH(pvec, type, pIterator) \ + for (pIterator = (type *) (pvec)->mpvaElements; \ + (pvec)->muTypeHash == VECTOR_TOKEN_HASH(type) \ + && pIterator < (type *) (pvec)->mpvaElements + (pvec)->mcElements; \ + ++pIterator) + +#endif /* !MAIN_INCLUDED_vector_h */ diff --git a/src/VBox/Main/include/win/resource.h b/src/VBox/Main/include/win/resource.h new file mode 100644 index 00000000..d7eea1f1 --- /dev/null +++ b/src/VBox/Main/include/win/resource.h @@ -0,0 +1,43 @@ +/* $Id: resource.h $ */ +/** @file + * + * Resource definitions + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef MAIN_INCLUDED_win_resource_h +#define MAIN_INCLUDED_win_resource_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + + +// registry script resource ID +#define IDR_VIRTUALBOX 101 + +// service name string resource ID +#define IDS_SERVICENAME 102 + + +#endif /* !MAIN_INCLUDED_win_resource_h */ |