VirtualBox

Changeset 99909 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
May 22, 2023 5:02:32 PM (19 months ago)
Author:
vboxsync
Message:

Main/ConsoleImpl: Split the VM config code into a common and architecture specific part in preparation for ARMv8, bugref:10384

Location:
trunk/src/VBox/Main
Files:
2 edited
1 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/Makefile.kmk

    r99845 r99909  
    11551155        src-client/ClientTokenHolder.cpp \
    11561156        src-client/ConsoleImpl.cpp \
    1157         src-client/ConsoleImpl2.cpp \
     1157        src-client/ConsoleImplConfigCommon.cpp \
     1158    src-client/ConsoleImplConfigX86.cpp \
    11581159        src-client/ConsoleImplTeleporter.cpp \
    11591160        src-client/ConsoleVRDPServer.cpp \
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r98340 r99909  
    3131# pragma once
    3232#endif
     33
     34#include <iprt/cpp/exception.h>
    3335
    3436#include "VirtualBoxBase.h"
     
    720722    void i_configAudioDriver(IVirtualBox *pVirtualBox, IMachine *pMachine, PCFGMNODE pLUN, const char *pszDriverName,
    721723                             bool fAudioEnabledIn, bool fAudioEnabledOut);
    722     int i_configConstructorInner(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock);
     724    int i_configConstructorInnerX86(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock);
    723725    int i_configCfgmOverlay(PCFGMNODE pRoot, IVirtualBox *pVirtualBox, IMachine *pMachine);
    724726    int i_configDumpAPISettingsTweaks(IVirtualBox *pVirtualBox, IMachine *pMachine);
     
    12191221};
    12201222
     1223
     1224class ConfigError : public RTCError
     1225{
     1226public:
     1227
     1228    ConfigError(const char *pcszFunction,
     1229                int vrc,
     1230                const char *pcszName)
     1231        : RTCError(Utf8StrFmt(Console::tr("%s failed: vrc=%Rrc, pcszName=%s"), pcszFunction, vrc, pcszName)),
     1232          m_vrc(vrc)
     1233    {
     1234        AssertMsgFailed(("%s\n", what())); // in strict mode, hit a breakpoint here
     1235    }
     1236
     1237    int m_vrc;
     1238};
     1239
     1240DECL_HIDDEN_THROW(Utf8Str *) GetExtraDataBoth(IVirtualBox *pVirtualBox, IMachine *pMachine, const char *pszName, Utf8Str *pStrValue);
     1241
    12211242#endif /* !MAIN_INCLUDED_ConsoleImpl_h */
    12221243/* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/src-client/ConsoleImplConfigCommon.cpp

    r99884 r99909  
    7171#include <iprt/string.h>
    7272#include <iprt/system.h>
    73 #include <iprt/cpp/exception.h>
    7473#if 0 /* enable to play with lots of memory. */
    7574# include <iprt/env.h>
     
    9089#include <VBox/vmm/pdmdev.h> /* For PDMAPICMODE enum. */
    9190#include <VBox/vmm/pdmstorageifs.h>
    92 #include <VBox/vmm/gcm.h>
    9391#include <VBox/version.h>
    9492#ifdef VBOX_WITH_SHARED_CLIPBOARD
     
    141139#endif
    142140#include "NetworkServiceRunner.h"
    143 #include "BusAssignmentManager.h"
    144141#ifdef VBOX_WITH_EXTPACK
    145142# include "ExtPackManagerImpl.h"
     
    150147*   Internal Functions                                                                                                           *
    151148*********************************************************************************************************************************/
    152 static Utf8Str *GetExtraDataBoth(IVirtualBox *pVirtualBox, IMachine *pMachine, const char *pszName, Utf8Str *pStrValue);
    153 
    154149
    155150/* Darwin compile kludge */
    156151#undef PVM
    157 
    158 /* Comment out the following line to remove VMWare compatibility hack. */
    159 #define VMWARE_NET_IN_SLOT_11
    160 
    161 /**
    162  * Translate IDE StorageControllerType_T to string representation.
    163  */
    164 static const char* controllerString(StorageControllerType_T enmType)
    165 {
    166     switch (enmType)
    167     {
    168         case StorageControllerType_PIIX3:
    169             return "PIIX3";
    170         case StorageControllerType_PIIX4:
    171             return "PIIX4";
    172         case StorageControllerType_ICH6:
    173             return "ICH6";
    174         default:
    175             return "Unknown";
    176     }
    177 }
    178 
    179 /**
    180  * Simple class for storing network boot information.
    181  */
    182 struct BootNic
    183 {
    184     ULONG          mInstance;
    185     PCIBusAddress  mPCIAddress;
    186 
    187     ULONG          mBootPrio;
    188     bool operator < (const BootNic &rhs) const
    189     {
    190         ULONG lval = mBootPrio     - 1; /* 0 will wrap around and get the lowest priority. */
    191         ULONG rval = rhs.mBootPrio - 1;
    192         return lval < rval; /* Zero compares as highest number (lowest prio). */
    193     }
    194 };
    195 
    196 #ifndef VBOX_WITH_EFI_IN_DD2
    197 static int findEfiRom(IVirtualBox* vbox, FirmwareType_T aFirmwareType, Utf8Str *pEfiRomFile)
    198 {
    199     Bstr aFilePath, empty;
    200     BOOL fPresent = FALSE;
    201     HRESULT hrc = vbox->CheckFirmwarePresent(aFirmwareType, empty.raw(),
    202                                              empty.asOutParam(), aFilePath.asOutParam(), &fPresent);
    203     AssertComRCReturn(hrc, Global::vboxStatusCodeFromCOM(hrc));
    204 
    205     if (!fPresent)
    206     {
    207         LogRel(("Failed to find an EFI ROM file.\n"));
    208         return VERR_FILE_NOT_FOUND;
    209     }
    210 
    211     *pEfiRomFile = Utf8Str(aFilePath);
    212 
    213     return VINF_SUCCESS;
    214 }
    215 #endif
    216 
    217 /**
    218  * @throws HRESULT on extra data retrival error.
    219  */
    220 static int getSmcDeviceKey(IVirtualBox *pVirtualBox, IMachine *pMachine, Utf8Str *pStrKey, bool *pfGetKeyFromRealSMC)
    221 {
    222     *pfGetKeyFromRealSMC = false;
    223 
    224     /*
    225      * The extra data takes precedence (if non-zero).
    226      */
    227     GetExtraDataBoth(pVirtualBox, pMachine, "VBoxInternal2/SmcDeviceKey", pStrKey);
    228     if (pStrKey->isNotEmpty())
    229         return VINF_SUCCESS;
    230 
    231 #ifdef RT_OS_DARWIN
    232 
    233     /*
    234      * Work done in EFI/DevSmc
    235      */
    236     *pfGetKeyFromRealSMC = true;
    237     int vrc = VINF_SUCCESS;
    238 
    239 #else
    240     /*
    241      * Is it apple hardware in bootcamp?
    242      */
    243     /** @todo implement + test RTSYSDMISTR_MANUFACTURER on all hosts.
    244      *        Currently falling back on the product name. */
    245     char szManufacturer[256];
    246     szManufacturer[0] = '\0';
    247     RTSystemQueryDmiString(RTSYSDMISTR_MANUFACTURER, szManufacturer, sizeof(szManufacturer));
    248     if (szManufacturer[0] != '\0')
    249     {
    250         if (   !strcmp(szManufacturer, "Apple Computer, Inc.")
    251             || !strcmp(szManufacturer, "Apple Inc.")
    252             )
    253             *pfGetKeyFromRealSMC = true;
    254     }
    255     else
    256     {
    257         char szProdName[256];
    258         szProdName[0] = '\0';
    259         RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME, szProdName, sizeof(szProdName));
    260         if (   (   !strncmp(szProdName, RT_STR_TUPLE("Mac"))
    261                 || !strncmp(szProdName, RT_STR_TUPLE("iMac"))
    262                 || !strncmp(szProdName, RT_STR_TUPLE("Xserve"))
    263                )
    264             && !strchr(szProdName, ' ')                             /* no spaces */
    265             && RT_C_IS_DIGIT(szProdName[strlen(szProdName) - 1])    /* version number */
    266            )
    267             *pfGetKeyFromRealSMC = true;
    268     }
    269 
    270     int vrc = VINF_SUCCESS;
    271 #endif
    272 
    273     return vrc;
    274 }
    275 
    276 
    277 /*
    278  * VC++ 8 / amd64 has some serious trouble with the next functions.
    279  * As a temporary measure, we'll drop global optimizations.
    280  */
    281 #if defined(_MSC_VER) && defined(RT_ARCH_AMD64)
    282 # if _MSC_VER >= RT_MSC_VER_VC80 && _MSC_VER < RT_MSC_VER_VC100
    283 #  pragma optimize("g", off)
    284 # endif
    285 #endif
    286 
    287 class ConfigError : public RTCError
    288 {
    289 public:
    290 
    291     ConfigError(const char *pcszFunction,
    292                 int vrc,
    293                 const char *pcszName)
    294         : RTCError(Utf8StrFmt(Console::tr("%s failed: vrc=%Rrc, pcszName=%s"), pcszFunction, vrc, pcszName)),
    295           m_vrc(vrc)
    296     {
    297         AssertMsgFailed(("%s\n", what())); // in strict mode, hit a breakpoint here
    298     }
    299 
    300     int m_vrc;
    301 };
    302 
    303152
    304153/**
     
    461310 *                          found).
    462311 */
    463 static Utf8Str *GetExtraDataBoth(IVirtualBox *pVirtualBox, IMachine *pMachine, const char *pszName, Utf8Str *pStrValue)
     312DECL_HIDDEN_THROW(Utf8Str *) GetExtraDataBoth(IVirtualBox *pVirtualBox, IMachine *pMachine, const char *pszName, Utf8Str *pStrValue)
    464313{
    465314    pStrValue->setNull();
     
    481330    return pStrValue;
    482331}
    483 
    484 
    485 /** Helper that finds out the next HBA port used
    486  */
    487 static LONG GetNextUsedPort(LONG aPortUsed[30], LONG lBaseVal, uint32_t u32Size)
    488 {
    489     LONG lNextPortUsed = 30;
    490     for (size_t j = 0; j < u32Size; ++j)
    491     {
    492         if (   aPortUsed[j] >  lBaseVal
    493             && aPortUsed[j] <= lNextPortUsed)
    494            lNextPortUsed = aPortUsed[j];
    495     }
    496     return lNextPortUsed;
    497 }
    498 
    499 #define MAX_BIOS_LUN_COUNT   4
    500 
    501 int Console::SetBiosDiskInfo(ComPtr<IMachine> pMachine, PCFGMNODE pCfg, PCFGMNODE pBiosCfg,
    502                              Bstr controllerName, const char * const s_apszBiosConfig[4])
    503 {
    504     RT_NOREF(pCfg);
    505     HRESULT             hrc;
    506 #define MAX_DEVICES     30
    507 #define H()     AssertLogRelMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
    508 
    509     LONG lPortLUN[MAX_BIOS_LUN_COUNT];
    510     LONG lPortUsed[MAX_DEVICES];
    511     uint32_t u32HDCount = 0;
    512 
    513     /* init to max value */
    514     lPortLUN[0] = MAX_DEVICES;
    515 
    516     com::SafeIfaceArray<IMediumAttachment> atts;
    517     hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(),
    518                                         ComSafeArrayAsOutParam(atts));  H();
    519     size_t uNumAttachments = atts.size();
    520     if (uNumAttachments > MAX_DEVICES)
    521     {
    522         LogRel(("Number of Attachments > Max=%d.\n", uNumAttachments));
    523         uNumAttachments = MAX_DEVICES;
    524     }
    525 
    526     /* Find the relevant ports/IDs, i.e the ones to which a HD is attached. */
    527     for (size_t j = 0; j < uNumAttachments; ++j)
    528     {
    529         IMediumAttachment *pMediumAtt = atts[j];
    530         LONG lPortNum = 0;
    531         hrc = pMediumAtt->COMGETTER(Port)(&lPortNum);                   H();
    532         if (SUCCEEDED(hrc))
    533         {
    534             DeviceType_T lType;
    535             hrc = pMediumAtt->COMGETTER(Type)(&lType);                  H();
    536             if (SUCCEEDED(hrc) && lType == DeviceType_HardDisk)
    537             {
    538                 /* find min port number used for HD */
    539                 if (lPortNum < lPortLUN[0])
    540                     lPortLUN[0] = lPortNum;
    541                 lPortUsed[u32HDCount++] = lPortNum;
    542                 LogFlowFunc(("HD port Count=%d\n", u32HDCount));
    543             }
    544         }
    545     }
    546 
    547 
    548     /* Pick only the top 4 used HD Ports as CMOS doesn't have space
    549      * to save details for all 30 ports
    550      */
    551     uint32_t u32MaxPortCount = MAX_BIOS_LUN_COUNT;
    552     if (u32HDCount < MAX_BIOS_LUN_COUNT)
    553         u32MaxPortCount = u32HDCount;
    554     for (size_t j = 1; j < u32MaxPortCount; j++)
    555         lPortLUN[j] = GetNextUsedPort(lPortUsed, lPortLUN[j-1], u32HDCount);
    556     if (pBiosCfg)
    557     {
    558         for (size_t j = 0; j < u32MaxPortCount; j++)
    559         {
    560             InsertConfigInteger(pBiosCfg, s_apszBiosConfig[j], lPortLUN[j]);
    561             LogFlowFunc(("Top %d HBA ports = %s, %d\n", j, s_apszBiosConfig[j], lPortLUN[j]));
    562         }
    563     }
    564     return VINF_SUCCESS;
    565 }
    566 
    567 #ifdef VBOX_WITH_PCI_PASSTHROUGH
    568 HRESULT Console::i_attachRawPCIDevices(PUVM pUVM, BusAssignmentManager *pBusMgr, PCFGMNODE pDevices)
    569 {
    570 # ifndef VBOX_WITH_EXTPACK
    571     RT_NOREF(pUVM);
    572 # endif
    573     HRESULT hrc = S_OK;
    574     PCFGMNODE pInst, pCfg, pLunL0, pLunL1;
    575 
    576     SafeIfaceArray<IPCIDeviceAttachment> assignments;
    577     ComPtr<IMachine> aMachine = i_machine();
    578 
    579     hrc = aMachine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
    580     if (   hrc != S_OK
    581         || assignments.size() < 1)
    582         return hrc;
    583 
    584     /*
    585      * PCI passthrough is only available if the proper ExtPack is installed.
    586      *
    587      * Note. Configuring PCI passthrough here and providing messages about
    588      * the missing extpack isn't exactly clean, but it is a necessary evil
    589      * to patch over legacy compatability issues introduced by the new
    590      * distribution model.
    591      */
    592 # ifdef VBOX_WITH_EXTPACK
    593     static const char *s_pszPCIRawExtPackName = "Oracle VM VirtualBox Extension Pack";
    594     if (!mptrExtPackManager->i_isExtPackUsable(s_pszPCIRawExtPackName))
    595         /* Always fatal! */
    596         return pVMM->pfnVMR3SetError(pUVM, VERR_NOT_FOUND, RT_SRC_POS,
    597                                      N_("Implementation of the PCI passthrough framework not found!\n"
    598                                         "The VM cannot be started. To fix this problem, either "
    599                                         "install the '%s' or disable PCI passthrough via VBoxManage"),
    600                                      s_pszPCIRawExtPackName);
    601 # endif
    602 
    603     /* Now actually add devices */
    604     PCFGMNODE pPCIDevs = NULL;
    605 
    606     if (assignments.size() > 0)
    607     {
    608         InsertConfigNode(pDevices, "pciraw",  &pPCIDevs);
    609 
    610         PCFGMNODE pRoot = CFGMR3GetParent(pDevices); Assert(pRoot);
    611 
    612         /* Tell PGM to tell GPCIRaw about guest mappings. */
    613         CFGMR3InsertNode(pRoot, "PGM", NULL);
    614         InsertConfigInteger(CFGMR3GetChild(pRoot, "PGM"), "PciPassThrough", 1);
    615 
    616         /*
    617          * Currently, using IOMMU needed for PCI passthrough
    618          * requires RAM preallocation.
    619          */
    620         /** @todo check if we can lift this requirement */
    621         CFGMR3RemoveValue(pRoot, "RamPreAlloc");
    622         InsertConfigInteger(pRoot, "RamPreAlloc", 1);
    623     }
    624 
    625     for (size_t iDev = 0; iDev < assignments.size(); iDev++)
    626     {
    627         ComPtr<IPCIDeviceAttachment> const assignment = assignments[iDev];
    628 
    629         LONG host;
    630         hrc = assignment->COMGETTER(HostAddress)(&host);            H();
    631         LONG guest;
    632         hrc = assignment->COMGETTER(GuestAddress)(&guest);          H();
    633         Bstr bstrDevName;
    634         hrc = assignment->COMGETTER(Name)(bstrDevName.asOutParam());   H();
    635 
    636         InsertConfigNodeF(pPCIDevs, &pInst, "%d", iDev);
    637         InsertConfigInteger(pInst, "Trusted", 1);
    638 
    639         PCIBusAddress HostPCIAddress(host);
    640         Assert(HostPCIAddress.valid());
    641         InsertConfigNode(pInst,        "Config",  &pCfg);
    642         InsertConfigString(pCfg,       "DeviceName",  bstrDevName);
    643 
    644         InsertConfigInteger(pCfg,      "DetachHostDriver",  1);
    645         InsertConfigInteger(pCfg,      "HostPCIBusNo",      HostPCIAddress.miBus);
    646         InsertConfigInteger(pCfg,      "HostPCIDeviceNo",   HostPCIAddress.miDevice);
    647         InsertConfigInteger(pCfg,      "HostPCIFunctionNo", HostPCIAddress.miFn);
    648 
    649         PCIBusAddress GuestPCIAddress(guest);
    650         Assert(GuestPCIAddress.valid());
    651         hrc = pBusMgr->assignHostPCIDevice("pciraw", pInst, HostPCIAddress, GuestPCIAddress, true);
    652         if (hrc != S_OK)
    653             return hrc;
    654 
    655         InsertConfigInteger(pCfg,      "GuestPCIBusNo",      GuestPCIAddress.miBus);
    656         InsertConfigInteger(pCfg,      "GuestPCIDeviceNo",   GuestPCIAddress.miDevice);
    657         InsertConfigInteger(pCfg,      "GuestPCIFunctionNo", GuestPCIAddress.miFn);
    658 
    659         /* the driver */
    660         InsertConfigNode(pInst,        "LUN#0",   &pLunL0);
    661         InsertConfigString(pLunL0,     "Driver", "pciraw");
    662         InsertConfigNode(pLunL0,       "AttachedDriver", &pLunL1);
    663 
    664         /* the Main driver */
    665         InsertConfigString(pLunL1,     "Driver", "MainPciRaw");
    666         InsertConfigNode(pLunL1,       "Config", &pCfg);
    667         PCIRawDev *pMainDev = new PCIRawDev(this);
    668 # error This is not allowed any more
    669         InsertConfigInteger(pCfg,      "Object", (uintptr_t)pMainDev);
    670     }
    671 
    672     return hrc;
    673 }
    674 #endif
    675332
    676333
     
    820477    try
    821478    {
    822         vrc = pConsole->i_configConstructorInner(pUVM, pVM, pVMM, &alock);
     479        vrc = pConsole->i_configConstructorInnerX86(pUVM, pVM, pVMM, &alock);
    823480    }
    824481    catch (...)
     
    835492}
    836493
    837 
    838 /**
    839  * Worker for configConstructor.
    840  *
    841  * @return  VBox status code.
    842  * @param   pUVM        The user mode VM handle.
    843  * @param   pVM         The cross context VM handle.
    844  * @param   pVMM        The VMM vtable.
    845  * @param   pAlock      The automatic lock instance.  This is for when we have
    846  *                      to leave it in order to avoid deadlocks (ext packs and
    847  *                      more).
    848  */
    849 int Console::i_configConstructorInner(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock)
    850 {
    851     RT_NOREF(pVM /* when everything is disabled */);
    852     VMMDev         *pVMMDev   = m_pVMMDev; Assert(pVMMDev);
    853     ComPtr<IMachine> pMachine = i_machine();
    854 
    855     int             vrc;
    856     HRESULT         hrc;
    857     Utf8Str         strTmp;
    858     Bstr            bstr;
    859 
    860 #define H()         AssertLogRelMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
    861 
    862     /*
    863      * Get necessary objects and frequently used parameters.
    864      */
    865     ComPtr<IVirtualBox> virtualBox;
    866     hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam());                             H();
    867 
    868     ComPtr<IHost> host;
    869     hrc = virtualBox->COMGETTER(Host)(host.asOutParam());                                   H();
    870 
    871     ComPtr<ISystemProperties> systemProperties;
    872     hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());           H();
    873 
    874     ComPtr<IBIOSSettings> biosSettings;
    875     hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam());                     H();
    876 
    877     ComPtr<INvramStore> nvramStore;
    878     hrc = pMachine->COMGETTER(NonVolatileStore)(nvramStore.asOutParam());                   H();
    879 
    880     hrc = pMachine->COMGETTER(HardwareUUID)(bstr.asOutParam());                             H();
    881     RTUUID HardwareUuid;
    882     vrc = RTUuidFromUtf16(&HardwareUuid, bstr.raw());
    883     AssertRCReturn(vrc, vrc);
    884 
    885     ULONG cRamMBs;
    886     hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs);                                        H();
    887 #if 0 /* enable to play with lots of memory. */
    888     if (RTEnvExist("VBOX_RAM_SIZE"))
    889         cRamMBs = RTStrToUInt64(RTEnvGet("VBOX_RAM_SIZE"));
    890 #endif
    891     uint64_t const cbRam   = cRamMBs * (uint64_t)_1M;
    892     uint32_t cbRamHole     = MM_RAM_HOLE_SIZE_DEFAULT;
    893     uint64_t uMcfgBase     = 0;
    894     uint32_t cbMcfgLength  = 0;
    895 
    896     ParavirtProvider_T enmParavirtProvider;
    897     hrc = pMachine->GetEffectiveParavirtProvider(&enmParavirtProvider);                     H();
    898 
    899     Bstr strParavirtDebug;
    900     hrc = pMachine->COMGETTER(ParavirtDebug)(strParavirtDebug.asOutParam());                H();
    901 
    902     BOOL fIOAPIC;
    903     uint32_t uIoApicPciAddress = NIL_PCIBDF;
    904     hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC);                                 H();
    905 
    906     ChipsetType_T chipsetType;
    907     hrc = pMachine->COMGETTER(ChipsetType)(&chipsetType);                                   H();
    908     if (chipsetType == ChipsetType_ICH9)
    909     {
    910         /* We'd better have 0x10000000 region, to cover 256 buses but this put
    911          * too much load on hypervisor heap. Linux 4.8 currently complains with
    912          * ``acpi PNP0A03:00: [Firmware Info]: MMCONFIG for domain 0000 [bus 00-3f]
    913          *   only partially covers this bridge'' */
    914         cbMcfgLength = 0x4000000; //0x10000000;
    915         cbRamHole += cbMcfgLength;
    916         uMcfgBase = _4G - cbRamHole;
    917     }
    918 
    919     /* Get the CPU profile name. */
    920     Bstr bstrCpuProfile;
    921     hrc = pMachine->COMGETTER(CPUProfile)(bstrCpuProfile.asOutParam());                     H();
    922 
    923     /* Check if long mode is enabled. */
    924     BOOL fIsGuest64Bit;
    925     hrc = pMachine->GetCPUProperty(CPUPropertyType_LongMode, &fIsGuest64Bit);               H();
    926 
    927     /*
    928      * Figure out the IOMMU config.
    929      */
    930 #if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL)
    931     IommuType_T enmIommuType;
    932     hrc = pMachine->COMGETTER(IommuType)(&enmIommuType);                                    H();
    933 
    934     /* Resolve 'automatic' type to an Intel or AMD IOMMU based on the host CPU. */
    935     if (enmIommuType == IommuType_Automatic)
    936     {
    937         if (   bstrCpuProfile.startsWith("AMD")
    938             || bstrCpuProfile.startsWith("Quad-Core AMD")
    939             || bstrCpuProfile.startsWith("Hygon"))
    940             enmIommuType = IommuType_AMD;
    941         else if (bstrCpuProfile.startsWith("Intel"))
    942         {
    943             if (   bstrCpuProfile.equals("Intel 8086")
    944                 || bstrCpuProfile.equals("Intel 80186")
    945                 || bstrCpuProfile.equals("Intel 80286")
    946                 || bstrCpuProfile.equals("Intel 80386")
    947                 || bstrCpuProfile.equals("Intel 80486"))
    948                 enmIommuType = IommuType_None;
    949             else
    950                 enmIommuType = IommuType_Intel;
    951         }
    952 # if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    953         else if (ASMIsAmdCpu())
    954             enmIommuType = IommuType_AMD;
    955         else if (ASMIsIntelCpu())
    956             enmIommuType = IommuType_Intel;
    957 # endif
    958         else
    959         {
    960             /** @todo Should we handle other CPUs like Shanghai, VIA etc. here? */
    961             LogRel(("WARNING! Unrecognized CPU type, IOMMU disabled.\n"));
    962             enmIommuType = IommuType_None;
    963         }
    964     }
    965 
    966     if (enmIommuType == IommuType_AMD)
    967     {
    968 # ifdef VBOX_WITH_IOMMU_AMD
    969         /*
    970          * Reserve the specific PCI address of the "SB I/O APIC" when using
    971          * an AMD IOMMU. Required by Linux guests, see @bugref{9654#c23}.
    972          */
    973         uIoApicPciAddress = VBOX_PCI_BDF_SB_IOAPIC;
    974 # else
    975         LogRel(("WARNING! AMD IOMMU not supported, IOMMU disabled.\n"));
    976         enmIommuType = IommuType_None;
    977 # endif
    978     }
    979 
    980     if (enmIommuType == IommuType_Intel)
    981     {
    982 # ifdef VBOX_WITH_IOMMU_INTEL
    983         /*
    984          * Reserve a unique PCI address for the I/O APIC when using
    985          * an Intel IOMMU. For convenience we use the same address as
    986          * we do on AMD, see @bugref{9967#c13}.
    987          */
    988         uIoApicPciAddress = VBOX_PCI_BDF_SB_IOAPIC;
    989 # else
    990         LogRel(("WARNING! Intel IOMMU not supported, IOMMU disabled.\n"));
    991         enmIommuType = IommuType_None;
    992 # endif
    993     }
    994 
    995     if (   enmIommuType == IommuType_AMD
    996         || enmIommuType == IommuType_Intel)
    997     {
    998         if (chipsetType != ChipsetType_ICH9)
    999             return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    1000                                          N_("IOMMU uses MSIs which requires the ICH9 chipset implementation."));
    1001         if (!fIOAPIC)
    1002             return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    1003                                          N_("IOMMU requires an I/O APIC for remapping interrupts."));
    1004     }
    1005 #else
    1006     IommuType_T const enmIommuType = IommuType_None;
    1007 #endif
    1008 
    1009     /* Instantiate the bus assignment manager. */
    1010     Assert(enmIommuType != IommuType_Automatic);
    1011     BusAssignmentManager *pBusMgr = mBusMgr = BusAssignmentManager::createInstance(pVMM, chipsetType, enmIommuType);
    1012 
    1013     ULONG cCpus = 1;
    1014     hrc = pMachine->COMGETTER(CPUCount)(&cCpus);                                            H();
    1015 
    1016     ULONG ulCpuExecutionCap = 100;
    1017     hrc = pMachine->COMGETTER(CPUExecutionCap)(&ulCpuExecutionCap);                         H();
    1018 
    1019     Bstr osTypeId;
    1020     hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam());                             H();
    1021     LogRel(("Guest OS type: '%s'\n", Utf8Str(osTypeId).c_str()));
    1022 
    1023     APICMode_T apicMode;
    1024     hrc = biosSettings->COMGETTER(APICMode)(&apicMode);                                     H();
    1025     uint32_t uFwAPIC;
    1026     switch (apicMode)
    1027     {
    1028         case APICMode_Disabled:
    1029             uFwAPIC = 0;
    1030             break;
    1031         case APICMode_APIC:
    1032             uFwAPIC = 1;
    1033             break;
    1034         case APICMode_X2APIC:
    1035             uFwAPIC = 2;
    1036             break;
    1037         default:
    1038             AssertMsgFailed(("Invalid APICMode=%d\n", apicMode));
    1039             uFwAPIC = 1;
    1040             break;
    1041     }
    1042 
    1043     ComPtr<IGuestOSType> pGuestOSType;
    1044     virtualBox->GetGuestOSType(osTypeId.raw(), pGuestOSType.asOutParam());
    1045 
    1046     BOOL fOsXGuest = FALSE;
    1047     BOOL fWinGuest = FALSE;
    1048     BOOL fOs2Guest = FALSE;
    1049     BOOL fW9xGuest = FALSE;
    1050     BOOL fDosGuest = FALSE;
    1051     if (!pGuestOSType.isNull())
    1052     {
    1053         Bstr guestTypeFamilyId;
    1054         hrc = pGuestOSType->COMGETTER(FamilyId)(guestTypeFamilyId.asOutParam());            H();
    1055         fOsXGuest = guestTypeFamilyId == Bstr("MacOS");
    1056         fWinGuest = guestTypeFamilyId == Bstr("Windows");
    1057         fOs2Guest = osTypeId.startsWith("OS2");
    1058         fW9xGuest = osTypeId.startsWith("Windows9");    /* Does not include Windows Me. */
    1059         fDosGuest = osTypeId.startsWith("DOS") || osTypeId.startsWith("Windows31");
    1060     }
    1061 
    1062     ULONG maxNetworkAdapters;
    1063     hrc = systemProperties->GetMaxNetworkAdapters(chipsetType, &maxNetworkAdapters);        H();
    1064 
    1065     /*
    1066      * Get root node first.
    1067      * This is the only node in the tree.
    1068      */
    1069     PCFGMNODE pRoot = pVMM->pfnCFGMR3GetRootU(pUVM);
    1070     Assert(pRoot);
    1071 
    1072     // catching throws from InsertConfigString and friends.
    1073     try
    1074     {
    1075 
    1076         /*
    1077          * Set the root (and VMM) level values.
    1078          */
    1079         hrc = pMachine->COMGETTER(Name)(bstr.asOutParam());                                 H();
    1080         InsertConfigString(pRoot,  "Name",                 bstr);
    1081         InsertConfigBytes(pRoot,   "UUID", &HardwareUuid, sizeof(HardwareUuid));
    1082         InsertConfigInteger(pRoot, "RamSize",              cbRam);
    1083         InsertConfigInteger(pRoot, "RamHoleSize",          cbRamHole);
    1084         InsertConfigInteger(pRoot, "NumCPUs",              cCpus);
    1085         InsertConfigInteger(pRoot, "CpuExecutionCap",      ulCpuExecutionCap);
    1086         InsertConfigInteger(pRoot, "TimerMillies",         10);
    1087 
    1088         BOOL fPageFusion = FALSE;
    1089         hrc = pMachine->COMGETTER(PageFusionEnabled)(&fPageFusion);                         H();
    1090         InsertConfigInteger(pRoot, "PageFusionAllowed",    fPageFusion); /* boolean */
    1091 
    1092         /* Not necessary, but makes sure this setting ends up in the release log. */
    1093         ULONG ulBalloonSize = 0;
    1094         hrc = pMachine->COMGETTER(MemoryBalloonSize)(&ulBalloonSize);                       H();
    1095         InsertConfigInteger(pRoot, "MemBalloonSize",       ulBalloonSize);
    1096 
    1097         /*
    1098          * EM values (before CPUM as it may need to set IemExecutesAll).
    1099          */
    1100         PCFGMNODE pEM;
    1101         InsertConfigNode(pRoot, "EM", &pEM);
    1102 
    1103         /* Triple fault behavior. */
    1104         BOOL fTripleFaultReset = false;
    1105         hrc = pMachine->GetCPUProperty(CPUPropertyType_TripleFaultReset, &fTripleFaultReset); H();
    1106         InsertConfigInteger(pEM, "TripleFaultReset", fTripleFaultReset);
    1107 
    1108         /*
    1109          * CPUM values.
    1110          */
    1111         PCFGMNODE pCPUM;
    1112         InsertConfigNode(pRoot, "CPUM", &pCPUM);
    1113         PCFGMNODE pIsaExts;
    1114         InsertConfigNode(pCPUM, "IsaExts", &pIsaExts);
    1115 
    1116         /* Host CPUID leaf overrides. */
    1117         for (uint32_t iOrdinal = 0; iOrdinal < _4K; iOrdinal++)
    1118         {
    1119             ULONG uLeaf, uSubLeaf, uEax, uEbx, uEcx, uEdx;
    1120             hrc = pMachine->GetCPUIDLeafByOrdinal(iOrdinal, &uLeaf, &uSubLeaf, &uEax, &uEbx, &uEcx, &uEdx);
    1121             if (hrc == E_INVALIDARG)
    1122                 break;
    1123             H();
    1124             PCFGMNODE pLeaf;
    1125             InsertConfigNode(pCPUM, Utf8StrFmt("HostCPUID/%RX32", uLeaf).c_str(), &pLeaf);
    1126             /** @todo Figure out how to tell the VMM about uSubLeaf   */
    1127             InsertConfigInteger(pLeaf, "eax", uEax);
    1128             InsertConfigInteger(pLeaf, "ebx", uEbx);
    1129             InsertConfigInteger(pLeaf, "ecx", uEcx);
    1130             InsertConfigInteger(pLeaf, "edx", uEdx);
    1131         }
    1132 
    1133         /* We must limit CPUID count for Windows NT 4, as otherwise it stops
    1134         with error 0x3e (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED). */
    1135         if (osTypeId == "WindowsNT4")
    1136         {
    1137             LogRel(("Limiting CPUID leaf count for NT4 guests\n"));
    1138             InsertConfigInteger(pCPUM, "NT4LeafLimit", true);
    1139         }
    1140 
    1141         if (fOsXGuest)
    1142         {
    1143             /* Expose extended MWAIT features to Mac OS X guests. */
    1144             LogRel(("Using MWAIT extensions\n"));
    1145             InsertConfigInteger(pIsaExts, "MWaitExtensions", true);
    1146 
    1147             /* Fake the CPU family/model so the guest works.  This is partly
    1148                because older mac releases really doesn't work on newer cpus,
    1149                and partly because mac os x expects more from systems with newer
    1150                cpus (MSRs, power features, whatever). */
    1151             uint32_t uMaxIntelFamilyModelStep = UINT32_MAX;
    1152             if (   osTypeId == "MacOS"
    1153                 || osTypeId == "MacOS_64")
    1154                 uMaxIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(1, 23, 6, 0); /* Penryn / X5482. */
    1155             else if (   osTypeId == "MacOS106"
    1156                      || osTypeId == "MacOS106_64")
    1157                 uMaxIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(1, 23, 6, 0); /* Penryn / X5482 */
    1158             else if (   osTypeId == "MacOS107"
    1159                      || osTypeId == "MacOS107_64")
    1160                 uMaxIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(1, 23, 6, 0); /* Penryn / X5482 */ /** @todo figure out
    1161                                                                                 what is required here. */
    1162             else if (   osTypeId == "MacOS108"
    1163                      || osTypeId == "MacOS108_64")
    1164                 uMaxIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(1, 23, 6, 0); /* Penryn / X5482 */ /** @todo figure out
    1165                                                                                 what is required here. */
    1166             else if (   osTypeId == "MacOS109"
    1167                      || osTypeId == "MacOS109_64")
    1168                 uMaxIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(1, 23, 6, 0); /* Penryn / X5482 */ /** @todo figure
    1169                                                                                 out what is required here. */
    1170             if (uMaxIntelFamilyModelStep != UINT32_MAX)
    1171                 InsertConfigInteger(pCPUM, "MaxIntelFamilyModelStep", uMaxIntelFamilyModelStep);
    1172         }
    1173 
    1174         /* CPU Portability level, */
    1175         ULONG uCpuIdPortabilityLevel = 0;
    1176         hrc = pMachine->COMGETTER(CPUIDPortabilityLevel)(&uCpuIdPortabilityLevel);          H();
    1177         InsertConfigInteger(pCPUM, "PortableCpuIdLevel", uCpuIdPortabilityLevel);
    1178 
    1179         /* Physical Address Extension (PAE) */
    1180         BOOL fEnablePAE = false;
    1181         hrc = pMachine->GetCPUProperty(CPUPropertyType_PAE, &fEnablePAE);                   H();
    1182         fEnablePAE |= fIsGuest64Bit;
    1183         InsertConfigInteger(pRoot, "EnablePAE", fEnablePAE);
    1184 
    1185         /* 64-bit guests (long mode) */
    1186         InsertConfigInteger(pCPUM, "Enable64bit", fIsGuest64Bit);
    1187 
    1188         /* APIC/X2APIC configuration */
    1189         BOOL fEnableAPIC = true;
    1190         BOOL fEnableX2APIC = true;
    1191         hrc = pMachine->GetCPUProperty(CPUPropertyType_APIC, &fEnableAPIC);                 H();
    1192         hrc = pMachine->GetCPUProperty(CPUPropertyType_X2APIC, &fEnableX2APIC);             H();
    1193         if (fEnableX2APIC)
    1194             Assert(fEnableAPIC);
    1195 
    1196         /* CPUM profile name. */
    1197         InsertConfigString(pCPUM, "GuestCpuName", bstrCpuProfile);
    1198 
    1199         /*
    1200          * Temporary(?) hack to make sure we emulate the ancient 16-bit CPUs
    1201          * correctly.   There are way too many #UDs we'll miss using VT-x,
    1202          * raw-mode or qemu for the 186 and 286, while we'll get undefined opcodes
    1203          * dead wrong on 8086 (see http://www.os2museum.com/wp/undocumented-8086-opcodes/).
    1204          */
    1205         if (   bstrCpuProfile.equals("Intel 80386") /* just for now */
    1206             || bstrCpuProfile.equals("Intel 80286")
    1207             || bstrCpuProfile.equals("Intel 80186")
    1208             || bstrCpuProfile.equals("Nec V20")
    1209             || bstrCpuProfile.equals("Intel 8086") )
    1210         {
    1211             InsertConfigInteger(pEM, "IemExecutesAll", true);
    1212             if (!bstrCpuProfile.equals("Intel 80386"))
    1213             {
    1214                 fEnableAPIC = false;
    1215                 fIOAPIC     = false;
    1216             }
    1217             fEnableX2APIC = false;
    1218         }
    1219 
    1220         /* Adjust firmware APIC handling to stay within the VCPU limits. */
    1221         if (uFwAPIC == 2 && !fEnableX2APIC)
    1222         {
    1223             if (fEnableAPIC)
    1224                 uFwAPIC = 1;
    1225             else
    1226                 uFwAPIC = 0;
    1227             LogRel(("Limiting the firmware APIC level from x2APIC to %s\n", fEnableAPIC ? "APIC" : "Disabled"));
    1228         }
    1229         else if (uFwAPIC == 1 && !fEnableAPIC)
    1230         {
    1231             uFwAPIC = 0;
    1232             LogRel(("Limiting the firmware APIC level from APIC to Disabled\n"));
    1233         }
    1234 
    1235         /* Speculation Control. */
    1236         BOOL fSpecCtrl = FALSE;
    1237         hrc = pMachine->GetCPUProperty(CPUPropertyType_SpecCtrl, &fSpecCtrl);      H();
    1238         InsertConfigInteger(pCPUM, "SpecCtrl", fSpecCtrl);
    1239 
    1240         /* Nested VT-x / AMD-V. */
    1241         BOOL fNestedHWVirt = FALSE;
    1242         hrc = pMachine->GetCPUProperty(CPUPropertyType_HWVirt, &fNestedHWVirt);      H();
    1243         InsertConfigInteger(pCPUM, "NestedHWVirt", fNestedHWVirt ? true : false);
    1244 
    1245         /*
    1246          * Hardware virtualization extensions.
    1247          */
    1248         /* Sanitize valid/useful APIC combinations, see @bugref{8868}. */
    1249         if (!fEnableAPIC)
    1250         {
    1251             if (fIsGuest64Bit)
    1252                 return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    1253                                              N_("Cannot disable the APIC for a 64-bit guest."));
    1254             if (cCpus > 1)
    1255                 return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    1256                                              N_("Cannot disable the APIC for an SMP guest."));
    1257             if (fIOAPIC)
    1258                 return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    1259                                              N_("Cannot disable the APIC when the I/O APIC is present."));
    1260         }
    1261 
    1262         BOOL fHMEnabled;
    1263         hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &fHMEnabled);     H();
    1264         if (cCpus > 1 && !fHMEnabled)
    1265         {
    1266             LogRel(("Forced fHMEnabled to TRUE by SMP guest.\n"));
    1267             fHMEnabled = TRUE;
    1268         }
    1269 
    1270         BOOL fHMForced;
    1271         fHMEnabled = fHMForced = TRUE;
    1272         LogRel(("fHMForced=true - No raw-mode support in this build!\n"));
    1273         if (!fHMForced) /* No need to query if already forced above. */
    1274         {
    1275             hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Force, &fHMForced); H();
    1276             if (fHMForced)
    1277                 LogRel(("fHMForced=true - HWVirtExPropertyType_Force\n"));
    1278         }
    1279         InsertConfigInteger(pRoot, "HMEnabled", fHMEnabled);
    1280 
    1281         /* /HM/xyz */
    1282         PCFGMNODE pHM;
    1283         InsertConfigNode(pRoot, "HM", &pHM);
    1284         InsertConfigInteger(pHM, "HMForced", fHMForced);
    1285         if (fHMEnabled)
    1286         {
    1287             /* Indicate whether 64-bit guests are supported or not. */
    1288             InsertConfigInteger(pHM, "64bitEnabled", fIsGuest64Bit);
    1289 
    1290             /** @todo Not exactly pretty to check strings; VBOXOSTYPE would be better,
    1291                 but that requires quite a bit of API change in Main. */
    1292             if (    fIOAPIC
    1293                 &&  (   osTypeId == "WindowsNT4"
    1294                      || osTypeId == "Windows2000"
    1295                      || osTypeId == "WindowsXP"
    1296                      || osTypeId == "Windows2003"))
    1297             {
    1298                 /* Only allow TPR patching for NT, Win2k, XP and Windows Server 2003. (32 bits mode)
    1299                  * We may want to consider adding more guest OSes (Solaris) later on.
    1300                  */
    1301                 InsertConfigInteger(pHM, "TPRPatchingEnabled", 1);
    1302             }
    1303         }
    1304 
    1305         /* HWVirtEx exclusive mode */
    1306         BOOL fHMExclusive = true;
    1307         hrc = systemProperties->COMGETTER(ExclusiveHwVirt)(&fHMExclusive);                  H();
    1308         InsertConfigInteger(pHM, "Exclusive", fHMExclusive);
    1309 
    1310         /* Nested paging (VT-x/AMD-V) */
    1311         BOOL fEnableNestedPaging = false;
    1312         hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &fEnableNestedPaging); H();
    1313         InsertConfigInteger(pHM, "EnableNestedPaging", fEnableNestedPaging);
    1314 
    1315         /* Large pages; requires nested paging */
    1316         BOOL fEnableLargePages = false;
    1317         hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_LargePages, &fEnableLargePages); H();
    1318         InsertConfigInteger(pHM, "EnableLargePages", fEnableLargePages);
    1319 
    1320         /* VPID (VT-x) */
    1321         BOOL fEnableVPID = false;
    1322         hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_VPID, &fEnableVPID);       H();
    1323         InsertConfigInteger(pHM, "EnableVPID", fEnableVPID);
    1324 
    1325         /* Unrestricted execution aka UX (VT-x) */
    1326         BOOL fEnableUX = false;
    1327         hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_UnrestrictedExecution, &fEnableUX); H();
    1328         InsertConfigInteger(pHM, "EnableUX", fEnableUX);
    1329 
    1330         /* Virtualized VMSAVE/VMLOAD (AMD-V) */
    1331         BOOL fVirtVmsaveVmload = true;
    1332         hrc = host->GetProcessorFeature(ProcessorFeature_VirtVmsaveVmload, &fVirtVmsaveVmload);     H();
    1333         InsertConfigInteger(pHM, "SvmVirtVmsaveVmload", fVirtVmsaveVmload);
    1334 
    1335         /* Indirect branch prediction boundraries. */
    1336         BOOL fIBPBOnVMExit = false;
    1337         hrc = pMachine->GetCPUProperty(CPUPropertyType_IBPBOnVMExit, &fIBPBOnVMExit); H();
    1338         InsertConfigInteger(pHM, "IBPBOnVMExit", fIBPBOnVMExit);
    1339 
    1340         BOOL fIBPBOnVMEntry = false;
    1341         hrc = pMachine->GetCPUProperty(CPUPropertyType_IBPBOnVMEntry, &fIBPBOnVMEntry); H();
    1342         InsertConfigInteger(pHM, "IBPBOnVMEntry", fIBPBOnVMEntry);
    1343 
    1344         BOOL fSpecCtrlByHost = false;
    1345         hrc = pMachine->GetCPUProperty(CPUPropertyType_SpecCtrlByHost, &fSpecCtrlByHost); H();
    1346         InsertConfigInteger(pHM, "SpecCtrlByHost", fSpecCtrlByHost);
    1347 
    1348         BOOL fL1DFlushOnSched = true;
    1349         hrc = pMachine->GetCPUProperty(CPUPropertyType_L1DFlushOnEMTScheduling, &fL1DFlushOnSched); H();
    1350         InsertConfigInteger(pHM, "L1DFlushOnSched", fL1DFlushOnSched);
    1351 
    1352         BOOL fL1DFlushOnVMEntry = false;
    1353         hrc = pMachine->GetCPUProperty(CPUPropertyType_L1DFlushOnVMEntry, &fL1DFlushOnVMEntry); H();
    1354         InsertConfigInteger(pHM, "L1DFlushOnVMEntry", fL1DFlushOnVMEntry);
    1355 
    1356         BOOL fMDSClearOnSched = true;
    1357         hrc = pMachine->GetCPUProperty(CPUPropertyType_MDSClearOnEMTScheduling, &fMDSClearOnSched); H();
    1358         InsertConfigInteger(pHM, "MDSClearOnSched", fMDSClearOnSched);
    1359 
    1360         BOOL fMDSClearOnVMEntry = false;
    1361         hrc = pMachine->GetCPUProperty(CPUPropertyType_MDSClearOnVMEntry, &fMDSClearOnVMEntry); H();
    1362         InsertConfigInteger(pHM, "MDSClearOnVMEntry", fMDSClearOnVMEntry);
    1363 
    1364         /* Reset overwrite. */
    1365         mfTurnResetIntoPowerOff = GetExtraDataBoth(virtualBox, pMachine,
    1366                                                    "VBoxInternal2/TurnResetIntoPowerOff", &strTmp)->equals("1");
    1367         if (mfTurnResetIntoPowerOff)
    1368             InsertConfigInteger(pRoot, "PowerOffInsteadOfReset", 1);
    1369 
    1370         /* Use NEM rather than HM. */
    1371         BOOL fUseNativeApi = false;
    1372         hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_UseNativeApi, &fUseNativeApi); H();
    1373         InsertConfigInteger(pHM, "UseNEMInstead", fUseNativeApi);
    1374 
    1375         /* Enable workaround for missing TLB flush for OS/2 guests, see ticketref:20625. */
    1376         if (osTypeId.startsWith("OS2"))
    1377             InsertConfigInteger(pHM, "MissingOS2TlbFlushWorkaround", 1);
    1378 
    1379         /*
    1380          * NEM
    1381          */
    1382         PCFGMNODE pNEM;
    1383         InsertConfigNode(pRoot, "NEM", &pNEM);
    1384         InsertConfigInteger(pNEM, "Allow64BitGuests", fIsGuest64Bit);
    1385 
    1386         /*
    1387          * Paravirt. provider.
    1388          */
    1389         PCFGMNODE pParavirtNode;
    1390         InsertConfigNode(pRoot, "GIM", &pParavirtNode);
    1391         const char *pcszParavirtProvider;
    1392         bool fGimDeviceNeeded = true;
    1393         switch (enmParavirtProvider)
    1394         {
    1395             case ParavirtProvider_None:
    1396                 pcszParavirtProvider = "None";
    1397                 fGimDeviceNeeded = false;
    1398                 break;
    1399 
    1400             case ParavirtProvider_Minimal:
    1401                 pcszParavirtProvider = "Minimal";
    1402                 break;
    1403 
    1404             case ParavirtProvider_HyperV:
    1405                 pcszParavirtProvider = "HyperV";
    1406                 break;
    1407 
    1408             case ParavirtProvider_KVM:
    1409                 pcszParavirtProvider = "KVM";
    1410                 break;
    1411 
    1412             default:
    1413                 AssertMsgFailed(("Invalid enmParavirtProvider=%d\n", enmParavirtProvider));
    1414                 return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("Invalid paravirt. provider '%d'"),
    1415                                              enmParavirtProvider);
    1416         }
    1417         InsertConfigString(pParavirtNode, "Provider", pcszParavirtProvider);
    1418 
    1419         /*
    1420          * Parse paravirt. debug options.
    1421          */
    1422         bool         fGimDebug          = false;
    1423         com::Utf8Str strGimDebugAddress = "127.0.0.1";
    1424         uint32_t     uGimDebugPort      = 50000;
    1425         if (strParavirtDebug.isNotEmpty())
    1426         {
    1427             /* Hyper-V debug options. */
    1428             if (enmParavirtProvider == ParavirtProvider_HyperV)
    1429             {
    1430                 bool         fGimHvDebug = false;
    1431                 com::Utf8Str strGimHvVendor;
    1432                 bool         fGimHvVsIf = false;
    1433                 bool         fGimHvHypercallIf = false;
    1434 
    1435                 size_t       uPos = 0;
    1436                 com::Utf8Str strDebugOptions = strParavirtDebug;
    1437                 com::Utf8Str strKey;
    1438                 com::Utf8Str strVal;
    1439                 while ((uPos = strDebugOptions.parseKeyValue(strKey, strVal, uPos)) != com::Utf8Str::npos)
    1440                 {
    1441                     if (strKey == "enabled")
    1442                     {
    1443                         if (strVal.toUInt32() == 1)
    1444                         {
    1445                             /* Apply defaults.
    1446                                The defaults are documented in the user manual,
    1447                                changes need to be reflected accordingly. */
    1448                             fGimHvDebug       = true;
    1449                             strGimHvVendor    = "Microsoft Hv";
    1450                             fGimHvVsIf        = true;
    1451                             fGimHvHypercallIf = false;
    1452                         }
    1453                         /* else: ignore, i.e. don't assert below with 'enabled=0'. */
    1454                     }
    1455                     else if (strKey == "address")
    1456                         strGimDebugAddress = strVal;
    1457                     else if (strKey == "port")
    1458                         uGimDebugPort = strVal.toUInt32();
    1459                     else if (strKey == "vendor")
    1460                         strGimHvVendor = strVal;
    1461                     else if (strKey == "vsinterface")
    1462                         fGimHvVsIf = RT_BOOL(strVal.toUInt32());
    1463                     else if (strKey == "hypercallinterface")
    1464                         fGimHvHypercallIf = RT_BOOL(strVal.toUInt32());
    1465                     else
    1466                     {
    1467                         AssertMsgFailed(("Unrecognized Hyper-V debug option '%s'\n", strKey.c_str()));
    1468                         return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    1469                                                      N_("Unrecognized Hyper-V debug option '%s' in '%s'"), strKey.c_str(),
    1470                                                      strDebugOptions.c_str());
    1471                     }
    1472                 }
    1473 
    1474                 /* Update HyperV CFGM node with active debug options. */
    1475                 if (fGimHvDebug)
    1476                 {
    1477                     PCFGMNODE pHvNode;
    1478                     InsertConfigNode(pParavirtNode, "HyperV", &pHvNode);
    1479                     InsertConfigString(pHvNode,  "VendorID", strGimHvVendor);
    1480                     InsertConfigInteger(pHvNode, "VSInterface", fGimHvVsIf ? 1 : 0);
    1481                     InsertConfigInteger(pHvNode, "HypercallDebugInterface", fGimHvHypercallIf ? 1 : 0);
    1482                     fGimDebug = true;
    1483                 }
    1484             }
    1485         }
    1486 
    1487         /*
    1488          * Guest Compatibility Manager.
    1489          */
    1490         PCFGMNODE   pGcmNode;
    1491         uint32_t    u32FixerSet = 0;
    1492         InsertConfigNode(pRoot, "GCM", &pGcmNode);
    1493         /* OS/2 and Win9x guests can run DOS apps so they get
    1494          * the DOS specific fixes as well.
    1495          */
    1496         if (fOs2Guest)
    1497             u32FixerSet = GCMFIXER_DBZ_DOS | GCMFIXER_DBZ_OS2;
    1498         else if (fW9xGuest)
    1499             u32FixerSet = GCMFIXER_DBZ_DOS | GCMFIXER_DBZ_WIN9X;
    1500         else if (fDosGuest)
    1501             u32FixerSet = GCMFIXER_DBZ_DOS;
    1502         InsertConfigInteger(pGcmNode, "FixerSet", u32FixerSet);
    1503 
    1504 
    1505         /*
    1506          * MM values.
    1507          */
    1508         PCFGMNODE pMM;
    1509         InsertConfigNode(pRoot, "MM", &pMM);
    1510         InsertConfigInteger(pMM, "CanUseLargerHeap", chipsetType == ChipsetType_ICH9);
    1511 
    1512         /*
    1513          * PDM config.
    1514          *  Load drivers in VBoxC.[so|dll]
    1515          */
    1516         PCFGMNODE pPDM;
    1517         PCFGMNODE pNode;
    1518         PCFGMNODE pMod;
    1519         InsertConfigNode(pRoot,    "PDM", &pPDM);
    1520         InsertConfigNode(pPDM,     "Devices", &pNode);
    1521         InsertConfigNode(pPDM,     "Drivers", &pNode);
    1522         InsertConfigNode(pNode,    "VBoxC", &pMod);
    1523 #ifdef VBOX_WITH_XPCOM
    1524         // VBoxC is located in the components subdirectory
    1525         char szPathVBoxC[RTPATH_MAX];
    1526         vrc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC"));  AssertRC(vrc);
    1527         strcat(szPathVBoxC, "/components/VBoxC");
    1528         InsertConfigString(pMod,   "Path",  szPathVBoxC);
    1529 #else
    1530         InsertConfigString(pMod,   "Path",  "VBoxC");
    1531 #endif
    1532 
    1533 
    1534         /*
    1535          * Block cache settings.
    1536          */
    1537         PCFGMNODE pPDMBlkCache;
    1538         InsertConfigNode(pPDM, "BlkCache", &pPDMBlkCache);
    1539 
    1540         /* I/O cache size */
    1541         ULONG ioCacheSize = 5;
    1542         hrc = pMachine->COMGETTER(IOCacheSize)(&ioCacheSize);                               H();
    1543         InsertConfigInteger(pPDMBlkCache, "CacheSize", ioCacheSize * _1M);
    1544 
    1545         /*
    1546          * Bandwidth groups.
    1547          */
    1548         ComPtr<IBandwidthControl> bwCtrl;
    1549 
    1550         hrc = pMachine->COMGETTER(BandwidthControl)(bwCtrl.asOutParam());                   H();
    1551 
    1552         com::SafeIfaceArray<IBandwidthGroup> bwGroups;
    1553         hrc = bwCtrl->GetAllBandwidthGroups(ComSafeArrayAsOutParam(bwGroups));              H();
    1554 
    1555         PCFGMNODE pAc;
    1556         InsertConfigNode(pPDM, "AsyncCompletion", &pAc);
    1557         PCFGMNODE pAcFile;
    1558         InsertConfigNode(pAc,  "File", &pAcFile);
    1559         PCFGMNODE pAcFileBwGroups;
    1560         InsertConfigNode(pAcFile,  "BwGroups", &pAcFileBwGroups);
    1561 #ifdef VBOX_WITH_NETSHAPER
    1562         PCFGMNODE pNetworkShaper;
    1563         InsertConfigNode(pPDM, "NetworkShaper",  &pNetworkShaper);
    1564         PCFGMNODE pNetworkBwGroups;
    1565         InsertConfigNode(pNetworkShaper, "BwGroups", &pNetworkBwGroups);
    1566 #endif /* VBOX_WITH_NETSHAPER */
    1567 
    1568         for (size_t i = 0; i < bwGroups.size(); i++)
    1569         {
    1570             Bstr strName;
    1571             hrc = bwGroups[i]->COMGETTER(Name)(strName.asOutParam());                       H();
    1572             if (strName.isEmpty())
    1573                 return pVMM->pfnVMR3SetError(pUVM, VERR_CFGM_NO_NODE, RT_SRC_POS, N_("No bandwidth group name specified"));
    1574 
    1575             BandwidthGroupType_T enmType = BandwidthGroupType_Null;
    1576             hrc = bwGroups[i]->COMGETTER(Type)(&enmType);                                   H();
    1577             LONG64 cMaxBytesPerSec = 0;
    1578             hrc = bwGroups[i]->COMGETTER(MaxBytesPerSec)(&cMaxBytesPerSec);                 H();
    1579 
    1580             if (enmType == BandwidthGroupType_Disk)
    1581             {
    1582                 PCFGMNODE pBwGroup;
    1583                 InsertConfigNode(pAcFileBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
    1584                 InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
    1585                 InsertConfigInteger(pBwGroup, "Start", cMaxBytesPerSec);
    1586                 InsertConfigInteger(pBwGroup, "Step", 0);
    1587             }
    1588 #ifdef VBOX_WITH_NETSHAPER
    1589             else if (enmType == BandwidthGroupType_Network)
    1590             {
    1591                 /* Network bandwidth groups. */
    1592                 PCFGMNODE pBwGroup;
    1593                 InsertConfigNode(pNetworkBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
    1594                 InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
    1595             }
    1596 #endif /* VBOX_WITH_NETSHAPER */
    1597         }
    1598 
    1599         /*
    1600          * Devices
    1601          */
    1602         PCFGMNODE pDevices = NULL;      /* /Devices */
    1603         PCFGMNODE pDev = NULL;          /* /Devices/Dev/ */
    1604         PCFGMNODE pInst = NULL;         /* /Devices/Dev/0/ */
    1605         PCFGMNODE pCfg = NULL;          /* /Devices/Dev/.../Config/ */
    1606         PCFGMNODE pLunL0 = NULL;        /* /Devices/Dev/0/LUN#0/ */
    1607         PCFGMNODE pLunL1 = NULL;        /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
    1608         PCFGMNODE pBiosCfg = NULL;      /* /Devices/pcbios/0/Config/ */
    1609         PCFGMNODE pNetBootCfg = NULL;   /* /Devices/pcbios/0/Config/NetBoot/ */
    1610 
    1611         InsertConfigNode(pRoot, "Devices", &pDevices);
    1612 
    1613         /*
    1614          * GIM Device
    1615          */
    1616         if (fGimDeviceNeeded)
    1617         {
    1618             InsertConfigNode(pDevices, "GIMDev", &pDev);
    1619             InsertConfigNode(pDev,     "0", &pInst);
    1620             InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    1621             //InsertConfigNode(pInst,    "Config", &pCfg);
    1622 
    1623             if (fGimDebug)
    1624             {
    1625                 InsertConfigNode(pInst,     "LUN#998", &pLunL0);
    1626                 InsertConfigString(pLunL0,  "Driver", "UDP");
    1627                 InsertConfigNode(pLunL0,    "Config", &pLunL1);
    1628                 InsertConfigString(pLunL1,  "ServerAddress", strGimDebugAddress);
    1629                 InsertConfigInteger(pLunL1, "ServerPort", uGimDebugPort);
    1630             }
    1631         }
    1632 
    1633         /*
    1634          * PC Arch.
    1635          */
    1636         InsertConfigNode(pDevices, "pcarch", &pDev);
    1637         InsertConfigNode(pDev,     "0", &pInst);
    1638         InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    1639         InsertConfigNode(pInst,    "Config", &pCfg);
    1640 
    1641         /*
    1642          * The time offset
    1643          */
    1644         LONG64 timeOffset;
    1645         hrc = biosSettings->COMGETTER(TimeOffset)(&timeOffset);                             H();
    1646         PCFGMNODE pTMNode;
    1647         InsertConfigNode(pRoot, "TM", &pTMNode);
    1648         InsertConfigInteger(pTMNode, "UTCOffset", timeOffset * 1000000);
    1649 
    1650         /*
    1651          * DMA
    1652          */
    1653         InsertConfigNode(pDevices, "8237A", &pDev);
    1654         InsertConfigNode(pDev,     "0", &pInst);
    1655         InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
    1656 
    1657         /*
    1658          * PCI buses.
    1659          */
    1660         uint32_t uIocPCIAddress, uHbcPCIAddress;
    1661         switch (chipsetType)
    1662         {
    1663             default:
    1664                 AssertFailed();
    1665                 RT_FALL_THRU();
    1666             case ChipsetType_PIIX3:
    1667                 /* Create the base for adding bridges on demand */
    1668                 InsertConfigNode(pDevices, "pcibridge", NULL);
    1669 
    1670                 InsertConfigNode(pDevices, "pci", &pDev);
    1671                 uHbcPCIAddress = (0x0 << 16) | 0;
    1672                 uIocPCIAddress = (0x1 << 16) | 0; // ISA controller
    1673                 break;
    1674             case ChipsetType_ICH9:
    1675                 /* Create the base for adding bridges on demand */
    1676                 InsertConfigNode(pDevices, "ich9pcibridge", NULL);
    1677 
    1678                 InsertConfigNode(pDevices, "ich9pci", &pDev);
    1679                 uHbcPCIAddress = (0x1e << 16) | 0;
    1680                 uIocPCIAddress = (0x1f << 16) | 0; // LPC controller
    1681                 break;
    1682         }
    1683         InsertConfigNode(pDev,     "0", &pInst);
    1684         InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    1685         InsertConfigNode(pInst,    "Config", &pCfg);
    1686         InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC);
    1687         if (chipsetType == ChipsetType_ICH9)
    1688         {
    1689             /* Provide MCFG info */
    1690             InsertConfigInteger(pCfg,  "McfgBase",   uMcfgBase);
    1691             InsertConfigInteger(pCfg,  "McfgLength", cbMcfgLength);
    1692 
    1693 #ifdef VBOX_WITH_PCI_PASSTHROUGH
    1694             /* Add PCI passthrough devices */
    1695             hrc = i_attachRawPCIDevices(pUVM, pBusMgr, pDevices);                           H();
    1696 #endif
    1697 
    1698             if (enmIommuType == IommuType_AMD)
    1699             {
    1700                 /* AMD IOMMU. */
    1701                 InsertConfigNode(pDevices, "iommu-amd", &pDev);
    1702                 InsertConfigNode(pDev,     "0", &pInst);
    1703                 InsertConfigInteger(pInst, "Trusted",   1); /* boolean */
    1704                 InsertConfigNode(pInst,    "Config", &pCfg);
    1705                 hrc = pBusMgr->assignPCIDevice("iommu-amd", pInst);                         H();
    1706 
    1707                 /* The AMD IOMMU device needs to know which PCI slot it's in, see @bugref{9654#c104}. */
    1708                 {
    1709                     PCIBusAddress Address;
    1710                     if (pBusMgr->findPCIAddress("iommu-amd", 0, Address))
    1711                     {
    1712                         uint32_t const u32IommuAddress = (Address.miDevice << 16) | Address.miFn;
    1713                         InsertConfigInteger(pCfg, "PCIAddress", u32IommuAddress);
    1714                     }
    1715                     else
    1716                         return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    1717                                                      N_("Failed to find PCI address of the assigned IOMMU device!"));
    1718                 }
    1719 
    1720                 PCIBusAddress PCIAddr = PCIBusAddress((int32_t)uIoApicPciAddress);
    1721                 hrc = pBusMgr->assignPCIDevice("sb-ioapic", NULL /* pCfg */, PCIAddr, true /*fGuestAddressRequired*/);  H();
    1722             }
    1723             else if (enmIommuType == IommuType_Intel)
    1724             {
    1725                 /* Intel IOMMU. */
    1726                 InsertConfigNode(pDevices, "iommu-intel", &pDev);
    1727                 InsertConfigNode(pDev,     "0", &pInst);
    1728                 InsertConfigInteger(pInst, "Trusted",   1); /* boolean */
    1729                 InsertConfigNode(pInst,    "Config", &pCfg);
    1730                 hrc = pBusMgr->assignPCIDevice("iommu-intel", pInst);                       H();
    1731 
    1732                 PCIBusAddress PCIAddr = PCIBusAddress((int32_t)uIoApicPciAddress);
    1733                 hrc = pBusMgr->assignPCIDevice("sb-ioapic", NULL /* pCfg */, PCIAddr, true /*fGuestAddressRequired*/);  H();
    1734             }
    1735         }
    1736 
    1737         /*
    1738          * Enable the following devices: HPET, SMC and LPC on MacOS X guests or on ICH9 chipset
    1739          */
    1740 
    1741         /*
    1742          * High Precision Event Timer (HPET)
    1743          */
    1744         BOOL fHPETEnabled;
    1745         /* Other guests may wish to use HPET too, but MacOS X not functional without it */
    1746         hrc = pMachine->COMGETTER(HPETEnabled)(&fHPETEnabled);                              H();
    1747         /* so always enable HPET in extended profile */
    1748         fHPETEnabled |= fOsXGuest;
    1749         /* HPET is always present on ICH9 */
    1750         fHPETEnabled |= (chipsetType == ChipsetType_ICH9);
    1751         if (fHPETEnabled)
    1752         {
    1753             InsertConfigNode(pDevices, "hpet", &pDev);
    1754             InsertConfigNode(pDev,     "0", &pInst);
    1755             InsertConfigInteger(pInst, "Trusted",   1); /* boolean */
    1756             InsertConfigNode(pInst,    "Config", &pCfg);
    1757             InsertConfigInteger(pCfg,  "ICH9", (chipsetType == ChipsetType_ICH9) ? 1 : 0);  /* boolean */
    1758         }
    1759 
    1760         /*
    1761          * System Management Controller (SMC)
    1762          */
    1763         BOOL fSmcEnabled;
    1764         fSmcEnabled = fOsXGuest;
    1765         if (fSmcEnabled)
    1766         {
    1767             InsertConfigNode(pDevices, "smc", &pDev);
    1768             InsertConfigNode(pDev,     "0", &pInst);
    1769             InsertConfigInteger(pInst, "Trusted",   1); /* boolean */
    1770             InsertConfigNode(pInst,    "Config", &pCfg);
    1771 
    1772             bool fGetKeyFromRealSMC;
    1773             Utf8Str strKey;
    1774             vrc = getSmcDeviceKey(virtualBox, pMachine, &strKey, &fGetKeyFromRealSMC);
    1775             AssertRCReturn(vrc, vrc);
    1776 
    1777             if (!fGetKeyFromRealSMC)
    1778                 InsertConfigString(pCfg,   "DeviceKey", strKey);
    1779             InsertConfigInteger(pCfg,  "GetKeyFromRealSMC", fGetKeyFromRealSMC);
    1780         }
    1781 
    1782         /*
    1783          * Low Pin Count (LPC) bus
    1784          */
    1785         BOOL fLpcEnabled;
    1786         /** @todo implement appropriate getter */
    1787         fLpcEnabled = fOsXGuest || (chipsetType == ChipsetType_ICH9);
    1788         if (fLpcEnabled)
    1789         {
    1790             InsertConfigNode(pDevices, "lpc", &pDev);
    1791             InsertConfigNode(pDev,     "0", &pInst);
    1792             hrc = pBusMgr->assignPCIDevice("lpc", pInst);                                   H();
    1793             InsertConfigInteger(pInst, "Trusted",   1); /* boolean */
    1794         }
    1795 
    1796         BOOL fShowRtc;
    1797         fShowRtc = fOsXGuest || (chipsetType == ChipsetType_ICH9);
    1798 
    1799         /*
    1800          * PS/2 keyboard & mouse.
    1801          */
    1802         InsertConfigNode(pDevices, "pckbd", &pDev);
    1803         InsertConfigNode(pDev,     "0", &pInst);
    1804         InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    1805         InsertConfigNode(pInst,    "Config", &pCfg);
    1806 
    1807         KeyboardHIDType_T aKbdHID;
    1808         hrc = pMachine->COMGETTER(KeyboardHIDType)(&aKbdHID);                               H();
    1809         if (aKbdHID != KeyboardHIDType_None)
    1810         {
    1811             InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    1812             InsertConfigString(pLunL0, "Driver",               "KeyboardQueue");
    1813             InsertConfigNode(pLunL0,   "Config", &pCfg);
    1814             InsertConfigInteger(pCfg,  "QueueSize",            64);
    1815 
    1816             InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
    1817             InsertConfigString(pLunL1, "Driver",               "MainKeyboard");
    1818         }
    1819 
    1820         PointingHIDType_T aPointingHID;
    1821         hrc = pMachine->COMGETTER(PointingHIDType)(&aPointingHID);                          H();
    1822         if (aPointingHID != PointingHIDType_None)
    1823         {
    1824             InsertConfigNode(pInst,    "LUN#1", &pLunL0);
    1825             InsertConfigString(pLunL0, "Driver",               "MouseQueue");
    1826             InsertConfigNode(pLunL0,   "Config", &pCfg);
    1827             InsertConfigInteger(pCfg, "QueueSize",            128);
    1828 
    1829             InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
    1830             InsertConfigString(pLunL1, "Driver",               "MainMouse");
    1831         }
    1832 
    1833         /*
    1834          * i8254 Programmable Interval Timer And Dummy Speaker
    1835          */
    1836         InsertConfigNode(pDevices, "i8254", &pDev);
    1837         InsertConfigNode(pDev,     "0", &pInst);
    1838         InsertConfigNode(pInst,    "Config", &pCfg);
    1839 #ifdef DEBUG
    1840         InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    1841 #endif
    1842 
    1843         /*
    1844          * i8259 Programmable Interrupt Controller.
    1845          */
    1846         InsertConfigNode(pDevices, "i8259", &pDev);
    1847         InsertConfigNode(pDev,     "0", &pInst);
    1848         InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    1849         InsertConfigNode(pInst,    "Config", &pCfg);
    1850 
    1851         /*
    1852          * Advanced Programmable Interrupt Controller.
    1853          * SMP: Each CPU has a LAPIC, but we have a single device representing all LAPICs states,
    1854          *      thus only single insert
    1855          */
    1856         if (fEnableAPIC)
    1857         {
    1858             InsertConfigNode(pDevices, "apic", &pDev);
    1859             InsertConfigNode(pDev, "0", &pInst);
    1860             InsertConfigInteger(pInst, "Trusted",          1); /* boolean */
    1861             InsertConfigNode(pInst,    "Config", &pCfg);
    1862             InsertConfigInteger(pCfg,  "IOAPIC", fIOAPIC);
    1863             PDMAPICMODE enmAPICMode = PDMAPICMODE_APIC;
    1864             if (fEnableX2APIC)
    1865                 enmAPICMode = PDMAPICMODE_X2APIC;
    1866             else if (!fEnableAPIC)
    1867                 enmAPICMode = PDMAPICMODE_NONE;
    1868             InsertConfigInteger(pCfg,  "Mode", enmAPICMode);
    1869             InsertConfigInteger(pCfg,  "NumCPUs", cCpus);
    1870 
    1871             if (fIOAPIC)
    1872             {
    1873                 /*
    1874                  * I/O Advanced Programmable Interrupt Controller.
    1875                  */
    1876                 InsertConfigNode(pDevices, "ioapic", &pDev);
    1877                 InsertConfigNode(pDev,     "0", &pInst);
    1878                 InsertConfigInteger(pInst, "Trusted",      1); /* boolean */
    1879                 InsertConfigNode(pInst,    "Config", &pCfg);
    1880                 InsertConfigInteger(pCfg,  "NumCPUs", cCpus);
    1881                 if (enmIommuType == IommuType_AMD)
    1882                     InsertConfigInteger(pCfg, "PCIAddress", uIoApicPciAddress);
    1883                 else if (enmIommuType == IommuType_Intel)
    1884                 {
    1885                     InsertConfigString(pCfg, "ChipType", "DMAR");
    1886                     InsertConfigInteger(pCfg, "PCIAddress", uIoApicPciAddress);
    1887                 }
    1888             }
    1889         }
    1890 
    1891         /*
    1892          * RTC MC146818.
    1893          */
    1894         InsertConfigNode(pDevices, "mc146818", &pDev);
    1895         InsertConfigNode(pDev,     "0", &pInst);
    1896         InsertConfigNode(pInst,    "Config", &pCfg);
    1897         BOOL fRTCUseUTC;
    1898         hrc = pMachine->COMGETTER(RTCUseUTC)(&fRTCUseUTC);                                  H();
    1899         InsertConfigInteger(pCfg,  "UseUTC", fRTCUseUTC ? 1 : 0);
    1900 
    1901         /*
    1902          * VGA.
    1903          */
    1904         ComPtr<IGraphicsAdapter> pGraphicsAdapter;
    1905         hrc = pMachine->COMGETTER(GraphicsAdapter)(pGraphicsAdapter.asOutParam());           H();
    1906         GraphicsControllerType_T enmGraphicsController;
    1907         hrc = pGraphicsAdapter->COMGETTER(GraphicsControllerType)(&enmGraphicsController);          H();
    1908         switch (enmGraphicsController)
    1909         {
    1910             case GraphicsControllerType_Null:
    1911                 break;
    1912 #ifdef VBOX_WITH_VMSVGA
    1913             case GraphicsControllerType_VMSVGA:
    1914                 InsertConfigInteger(pHM, "LovelyMesaDrvWorkaround", 1); /* hits someone else logging backdoor. */
    1915                 InsertConfigInteger(pNEM, "LovelyMesaDrvWorkaround", 1); /* hits someone else logging backdoor. */
    1916                 RT_FALL_THROUGH();
    1917             case GraphicsControllerType_VBoxSVGA:
    1918 #endif
    1919             case GraphicsControllerType_VBoxVGA:
    1920                 vrc = i_configGraphicsController(pDevices, enmGraphicsController, pBusMgr, pMachine, pGraphicsAdapter, biosSettings,
    1921                                                  RT_BOOL(fHMEnabled));
    1922                 if (FAILED(vrc))
    1923                     return vrc;
    1924                 break;
    1925             default:
    1926                 AssertMsgFailed(("Invalid graphicsController=%d\n", enmGraphicsController));
    1927                 return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    1928                                              N_("Invalid graphics controller type '%d'"), enmGraphicsController);
    1929         }
    1930 
    1931         /*
    1932          * Firmware.
    1933          */
    1934         FirmwareType_T eFwType =  FirmwareType_BIOS;
    1935         hrc = pMachine->COMGETTER(FirmwareType)(&eFwType);                                  H();
    1936 
    1937 #ifdef VBOX_WITH_EFI
    1938         BOOL fEfiEnabled = (eFwType >= FirmwareType_EFI) && (eFwType <= FirmwareType_EFIDUAL);
    1939 #else
    1940         BOOL fEfiEnabled = false;
    1941 #endif
    1942         if (!fEfiEnabled)
    1943         {
    1944             /*
    1945              * PC Bios.
    1946              */
    1947             InsertConfigNode(pDevices, "pcbios", &pDev);
    1948             InsertConfigNode(pDev,     "0", &pInst);
    1949             InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    1950             InsertConfigNode(pInst,    "Config", &pBiosCfg);
    1951             InsertConfigInteger(pBiosCfg,  "NumCPUs",              cCpus);
    1952             InsertConfigString(pBiosCfg,   "HardDiskDevice",       "piix3ide");
    1953             InsertConfigString(pBiosCfg,   "FloppyDevice",         "i82078");
    1954             InsertConfigInteger(pBiosCfg,  "IOAPIC",               fIOAPIC);
    1955             InsertConfigInteger(pBiosCfg,  "APIC",                 uFwAPIC);
    1956             BOOL fPXEDebug;
    1957             hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug);                     H();
    1958             InsertConfigInteger(pBiosCfg,  "PXEDebug",             fPXEDebug);
    1959             InsertConfigBytes(pBiosCfg,    "UUID", &HardwareUuid,sizeof(HardwareUuid));
    1960             BOOL fUuidLe;
    1961             hrc = biosSettings->COMGETTER(SMBIOSUuidLittleEndian)(&fUuidLe);                H();
    1962             InsertConfigInteger(pBiosCfg,  "UuidLe",               fUuidLe);
    1963             InsertConfigNode(pBiosCfg,     "NetBoot", &pNetBootCfg);
    1964             InsertConfigInteger(pBiosCfg,  "McfgBase",   uMcfgBase);
    1965             InsertConfigInteger(pBiosCfg,  "McfgLength", cbMcfgLength);
    1966 
    1967             AssertMsgReturn(SchemaDefs::MaxBootPosition <= 9, ("Too many boot devices %d\n", SchemaDefs::MaxBootPosition),
    1968                             VERR_INVALID_PARAMETER);
    1969 
    1970             for (ULONG pos = 1; pos <= SchemaDefs::MaxBootPosition; ++pos)
    1971             {
    1972                 DeviceType_T enmBootDevice;
    1973                 hrc = pMachine->GetBootOrder(pos, &enmBootDevice);                          H();
    1974 
    1975                 char szParamName[] = "BootDeviceX";
    1976                 szParamName[sizeof(szParamName) - 2] = (char)(pos - 1 + '0');
    1977 
    1978                 const char *pszBootDevice;
    1979                 switch (enmBootDevice)
    1980                 {
    1981                     case DeviceType_Null:
    1982                         pszBootDevice = "NONE";
    1983                         break;
    1984                     case DeviceType_HardDisk:
    1985                         pszBootDevice = "IDE";
    1986                         break;
    1987                     case DeviceType_DVD:
    1988                         pszBootDevice = "DVD";
    1989                         break;
    1990                     case DeviceType_Floppy:
    1991                         pszBootDevice = "FLOPPY";
    1992                         break;
    1993                     case DeviceType_Network:
    1994                         pszBootDevice = "LAN";
    1995                         break;
    1996                     default:
    1997                         AssertMsgFailed(("Invalid enmBootDevice=%d\n", enmBootDevice));
    1998                         return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    1999                                                      N_("Invalid boot device '%d'"), enmBootDevice);
    2000                 }
    2001                 InsertConfigString(pBiosCfg, szParamName, pszBootDevice);
    2002             }
    2003 
    2004             /** @todo @bugref{7145}: We might want to enable this by default for new VMs. For now,
    2005              *        this is required for Windows 2012 guests. */
    2006             if (osTypeId == "Windows2012_64")
    2007                 InsertConfigInteger(pBiosCfg, "DmiExposeMemoryTable", 1); /* boolean */
    2008         }
    2009         else
    2010         {
    2011             /* Autodetect firmware type, basing on guest type */
    2012             if (eFwType == FirmwareType_EFI)
    2013                 eFwType = fIsGuest64Bit ? FirmwareType_EFI64 : FirmwareType_EFI32;
    2014             bool const f64BitEntry = eFwType == FirmwareType_EFI64;
    2015 
    2016             Assert(eFwType == FirmwareType_EFI64 || eFwType == FirmwareType_EFI32 || eFwType == FirmwareType_EFIDUAL);
    2017 #ifdef VBOX_WITH_EFI_IN_DD2
    2018             const char *pszEfiRomFile = eFwType == FirmwareType_EFIDUAL ? "VBoxEFIDual.fd"
    2019                                       : eFwType == FirmwareType_EFI32   ? "VBoxEFI32.fd"
    2020                                       :                                   "VBoxEFI64.fd";
    2021 #else
    2022             Utf8Str efiRomFile;
    2023             vrc = findEfiRom(virtualBox, eFwType, &efiRomFile);
    2024             AssertRCReturn(vrc, vrc);
    2025             const char *pszEfiRomFile = efiRomFile.c_str();
    2026 #endif
    2027 
    2028             /* Get boot args */
    2029             Utf8Str bootArgs;
    2030             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/EfiBootArgs", &bootArgs);
    2031 
    2032             /* Get device props */
    2033             Utf8Str deviceProps;
    2034             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/EfiDeviceProps", &deviceProps);
    2035 
    2036             /* Get NVRAM file name */
    2037             Utf8Str strNvram = mptrNvramStore->i_getNonVolatileStorageFile();
    2038 
    2039             BOOL fUuidLe;
    2040             hrc = biosSettings->COMGETTER(SMBIOSUuidLittleEndian)(&fUuidLe);                H();
    2041 
    2042             /* Get graphics mode settings */
    2043             uint32_t u32GraphicsMode = UINT32_MAX;
    2044             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/EfiGraphicsMode", &strTmp);
    2045             if (strTmp.isEmpty())
    2046                 GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/EfiGopMode", &strTmp);
    2047             if (!strTmp.isEmpty())
    2048                 u32GraphicsMode = strTmp.toUInt32();
    2049 
    2050             /* Get graphics resolution settings, with some sanity checking */
    2051             Utf8Str strResolution;
    2052             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/EfiGraphicsResolution", &strResolution);
    2053             if (!strResolution.isEmpty())
    2054             {
    2055                 size_t pos = strResolution.find("x");
    2056                 if (pos != strResolution.npos)
    2057                 {
    2058                     Utf8Str strH, strV;
    2059                     strH.assignEx(strResolution, 0, pos);
    2060                     strV.assignEx(strResolution, pos+1, strResolution.length()-pos-1);
    2061                     uint32_t u32H = strH.toUInt32();
    2062                     uint32_t u32V = strV.toUInt32();
    2063                     if (u32H == 0 || u32V == 0)
    2064                         strResolution.setNull();
    2065                 }
    2066                 else
    2067                     strResolution.setNull();
    2068             }
    2069             else
    2070             {
    2071                 uint32_t u32H = 0;
    2072                 uint32_t u32V = 0;
    2073                 GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/EfiHorizontalResolution", &strTmp);
    2074                 if (strTmp.isEmpty())
    2075                     GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/EfiUgaHorizontalResolution", &strTmp);
    2076                 if (!strTmp.isEmpty())
    2077                     u32H = strTmp.toUInt32();
    2078 
    2079                 GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/EfiVerticalResolution", &strTmp);
    2080                 if (strTmp.isEmpty())
    2081                     GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/EfiUgaVerticalResolution", &strTmp);
    2082                 if (!strTmp.isEmpty())
    2083                     u32V = strTmp.toUInt32();
    2084                 if (u32H != 0 && u32V != 0)
    2085                     strResolution = Utf8StrFmt("%ux%u", u32H, u32V);
    2086             }
    2087 
    2088             /*
    2089              * EFI subtree.
    2090              */
    2091             InsertConfigNode(pDevices, "efi", &pDev);
    2092             InsertConfigNode(pDev,     "0", &pInst);
    2093             InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
    2094             InsertConfigNode(pInst,    "Config", &pCfg);
    2095             InsertConfigInteger(pCfg,  "NumCPUs",     cCpus);
    2096             InsertConfigInteger(pCfg,  "McfgBase",    uMcfgBase);
    2097             InsertConfigInteger(pCfg,  "McfgLength",  cbMcfgLength);
    2098             InsertConfigString(pCfg,   "EfiRom",      pszEfiRomFile);
    2099             InsertConfigString(pCfg,   "BootArgs",    bootArgs);
    2100             InsertConfigString(pCfg,   "DeviceProps", deviceProps);
    2101             InsertConfigInteger(pCfg,  "IOAPIC",      fIOAPIC);
    2102             InsertConfigInteger(pCfg,  "APIC",        uFwAPIC);
    2103             InsertConfigBytes(pCfg,    "UUID", &HardwareUuid,sizeof(HardwareUuid));
    2104             InsertConfigInteger(pCfg,  "UuidLe",      fUuidLe);
    2105             InsertConfigInteger(pCfg,  "64BitEntry",  f64BitEntry); /* boolean */
    2106             InsertConfigString(pCfg,   "NvramFile",   strNvram);
    2107             if (u32GraphicsMode != UINT32_MAX)
    2108                 InsertConfigInteger(pCfg,  "GraphicsMode",  u32GraphicsMode);
    2109             if (!strResolution.isEmpty())
    2110                 InsertConfigString(pCfg,   "GraphicsResolution", strResolution);
    2111 
    2112             /* For OS X guests we'll force passing host's DMI info to the guest */
    2113             if (fOsXGuest)
    2114             {
    2115                 InsertConfigInteger(pCfg, "DmiUseHostInfo", 1);
    2116                 InsertConfigInteger(pCfg, "DmiExposeMemoryTable", 1);
    2117             }
    2118 
    2119             /* Attach the NVRAM storage driver. */
    2120             InsertConfigNode(pInst,    "LUN#0",     &pLunL0);
    2121             InsertConfigString(pLunL0, "Driver",    "NvramStore");
    2122         }
    2123 
    2124         /*
    2125          * The USB Controllers.
    2126          */
    2127         com::SafeIfaceArray<IUSBController> usbCtrls;
    2128         hrc = pMachine->COMGETTER(USBControllers)(ComSafeArrayAsOutParam(usbCtrls));
    2129         bool fOhciPresent = false; /**< Flag whether at least one OHCI controller is present. */
    2130         bool fXhciPresent = false; /**< Flag whether at least one XHCI controller is present. */
    2131 
    2132         if (SUCCEEDED(hrc))
    2133         {
    2134             for (size_t i = 0; i < usbCtrls.size(); ++i)
    2135             {
    2136                 USBControllerType_T enmCtrlType;
    2137                 vrc = usbCtrls[i]->COMGETTER(Type)(&enmCtrlType);                                  H();
    2138                 if (enmCtrlType == USBControllerType_OHCI)
    2139                 {
    2140                     fOhciPresent = true;
    2141                     break;
    2142                 }
    2143                 else if (enmCtrlType == USBControllerType_XHCI)
    2144                 {
    2145                     fXhciPresent = true;
    2146                     break;
    2147                 }
    2148             }
    2149         }
    2150         else if (hrc != E_NOTIMPL)
    2151         {
    2152             H();
    2153         }
    2154 
    2155         /*
    2156          * Currently EHCI is only enabled when an OHCI or XHCI controller is present as well.
    2157          */
    2158         if (fOhciPresent || fXhciPresent)
    2159             mfVMHasUsbController = true;
    2160 
    2161         PCFGMNODE pUsbDevices = NULL; /**< Required for USB storage controller later. */
    2162         if (mfVMHasUsbController)
    2163         {
    2164             for (size_t i = 0; i < usbCtrls.size(); ++i)
    2165             {
    2166                 USBControllerType_T enmCtrlType;
    2167                 vrc = usbCtrls[i]->COMGETTER(Type)(&enmCtrlType);                                  H();
    2168 
    2169                 if (enmCtrlType == USBControllerType_OHCI)
    2170                 {
    2171                     InsertConfigNode(pDevices, "usb-ohci", &pDev);
    2172                     InsertConfigNode(pDev,     "0", &pInst);
    2173                     InsertConfigNode(pInst,    "Config", &pCfg);
    2174                     InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    2175                     hrc = pBusMgr->assignPCIDevice("usb-ohci", pInst);                          H();
    2176                     InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    2177                     InsertConfigString(pLunL0, "Driver",               "VUSBRootHub");
    2178                     InsertConfigNode(pLunL0,   "Config", &pCfg);
    2179 
    2180                     /*
    2181                      * Attach the status driver.
    2182                      */
    2183                     i_attachStatusDriver(pInst, DeviceType_USB);
    2184                 }
    2185 #ifdef VBOX_WITH_EHCI
    2186                 else if (enmCtrlType == USBControllerType_EHCI)
    2187                 {
    2188                     InsertConfigNode(pDevices, "usb-ehci", &pDev);
    2189                     InsertConfigNode(pDev,     "0", &pInst);
    2190                     InsertConfigNode(pInst,    "Config", &pCfg);
    2191                     InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
    2192                     hrc = pBusMgr->assignPCIDevice("usb-ehci", pInst);                  H();
    2193 
    2194                     InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    2195                     InsertConfigString(pLunL0, "Driver",               "VUSBRootHub");
    2196                     InsertConfigNode(pLunL0,   "Config", &pCfg);
    2197 
    2198                     /*
    2199                      * Attach the status driver.
    2200                      */
    2201                     i_attachStatusDriver(pInst, DeviceType_USB);
    2202                 }
    2203 #endif
    2204                 else if (enmCtrlType == USBControllerType_XHCI)
    2205                 {
    2206                     InsertConfigNode(pDevices, "usb-xhci", &pDev);
    2207                     InsertConfigNode(pDev,     "0", &pInst);
    2208                     InsertConfigNode(pInst,    "Config", &pCfg);
    2209                     InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
    2210                     hrc = pBusMgr->assignPCIDevice("usb-xhci", pInst);                  H();
    2211 
    2212                     InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    2213                     InsertConfigString(pLunL0, "Driver",               "VUSBRootHub");
    2214                     InsertConfigNode(pLunL0,   "Config", &pCfg);
    2215 
    2216                     InsertConfigNode(pInst,    "LUN#1", &pLunL1);
    2217                     InsertConfigString(pLunL1, "Driver",               "VUSBRootHub");
    2218                     InsertConfigNode(pLunL1,   "Config", &pCfg);
    2219 
    2220                     /*
    2221                      * Attach the status driver.
    2222                      */
    2223                     i_attachStatusDriver(pInst, DeviceType_USB, 2);
    2224                 }
    2225             } /* for every USB controller. */
    2226 
    2227 
    2228             /*
    2229              * Virtual USB Devices.
    2230              */
    2231             InsertConfigNode(pRoot, "USB", &pUsbDevices);
    2232 
    2233 #ifdef VBOX_WITH_USB
    2234             {
    2235                 /*
    2236                  * Global USB options, currently unused as we'll apply the 2.0 -> 1.1 morphing
    2237                  * on a per device level now.
    2238                  */
    2239                 InsertConfigNode(pUsbDevices, "USBProxy", &pCfg);
    2240                 InsertConfigNode(pCfg, "GlobalConfig", &pCfg);
    2241                 // This globally enables the 2.0 -> 1.1 device morphing of proxied devices to keep windows quiet.
    2242                 //InsertConfigInteger(pCfg, "Force11Device", true);
    2243                 // The following breaks stuff, but it makes MSDs work in vista. (I include it here so
    2244                 // that it's documented somewhere.) Users needing it can use:
    2245                 //      VBoxManage setextradata "myvm" "VBoxInternal/USB/USBProxy/GlobalConfig/Force11PacketSize" 1
    2246                 //InsertConfigInteger(pCfg, "Force11PacketSize", true);
    2247             }
    2248 #endif
    2249 
    2250 #ifdef VBOX_WITH_USB_CARDREADER
    2251             BOOL aEmulatedUSBCardReaderEnabled = FALSE;
    2252             hrc = pMachine->COMGETTER(EmulatedUSBCardReaderEnabled)(&aEmulatedUSBCardReaderEnabled);    H();
    2253             if (aEmulatedUSBCardReaderEnabled)
    2254             {
    2255                 InsertConfigNode(pUsbDevices, "CardReader", &pDev);
    2256                 InsertConfigNode(pDev,     "0", &pInst);
    2257                 InsertConfigNode(pInst,    "Config", &pCfg);
    2258 
    2259                 InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    2260 # ifdef VBOX_WITH_USB_CARDREADER_TEST
    2261                 InsertConfigString(pLunL0, "Driver", "DrvDirectCardReader");
    2262                 InsertConfigNode(pLunL0,   "Config", &pCfg);
    2263 # else
    2264                 InsertConfigString(pLunL0, "Driver", "UsbCardReader");
    2265                 InsertConfigNode(pLunL0,   "Config", &pCfg);
    2266 # endif
    2267              }
    2268 #endif
    2269 
    2270             /* Virtual USB Mouse/Tablet */
    2271             if (   aPointingHID == PointingHIDType_USBMouse
    2272                 || aPointingHID == PointingHIDType_USBTablet
    2273                 || aPointingHID == PointingHIDType_USBMultiTouch
    2274                 || aPointingHID == PointingHIDType_USBMultiTouchScreenPlusPad)
    2275             {
    2276                 InsertConfigNode(pUsbDevices, "HidMouse", &pDev);
    2277                 InsertConfigNode(pDev,     "0", &pInst);
    2278                 InsertConfigNode(pInst,    "Config", &pCfg);
    2279 
    2280                 if (aPointingHID == PointingHIDType_USBMouse)
    2281                     InsertConfigString(pCfg,   "Mode", "relative");
    2282                 else
    2283                     InsertConfigString(pCfg,   "Mode", "absolute");
    2284                 InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    2285                 InsertConfigString(pLunL0, "Driver",        "MouseQueue");
    2286                 InsertConfigNode(pLunL0,   "Config", &pCfg);
    2287                 InsertConfigInteger(pCfg,  "QueueSize",            128);
    2288 
    2289                 InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
    2290                 InsertConfigString(pLunL1, "Driver",        "MainMouse");
    2291             }
    2292             if (   aPointingHID == PointingHIDType_USBMultiTouch
    2293                 || aPointingHID == PointingHIDType_USBMultiTouchScreenPlusPad)
    2294             {
    2295                 InsertConfigNode(pDev,     "1", &pInst);
    2296                 InsertConfigNode(pInst,    "Config", &pCfg);
    2297 
    2298                 InsertConfigString(pCfg,   "Mode", "multitouch");
    2299                 InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    2300                 InsertConfigString(pLunL0, "Driver",        "MouseQueue");
    2301                 InsertConfigNode(pLunL0,   "Config", &pCfg);
    2302                 InsertConfigInteger(pCfg,  "QueueSize",            128);
    2303 
    2304                 InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
    2305                 InsertConfigString(pLunL1, "Driver",        "MainMouse");
    2306             }
    2307             if (aPointingHID == PointingHIDType_USBMultiTouchScreenPlusPad)
    2308             {
    2309                 InsertConfigNode(pDev,     "2", &pInst);
    2310                 InsertConfigNode(pInst,    "Config", &pCfg);
    2311 
    2312                 InsertConfigString(pCfg,   "Mode", "touchpad");
    2313                 InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    2314                 InsertConfigString(pLunL0, "Driver",        "MouseQueue");
    2315                 InsertConfigNode(pLunL0,   "Config", &pCfg);
    2316                 InsertConfigInteger(pCfg,  "QueueSize",            128);
    2317 
    2318                 InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
    2319                 InsertConfigString(pLunL1, "Driver",        "MainMouse");
    2320             }
    2321 
    2322             /* Virtual USB Keyboard */
    2323             if (aKbdHID == KeyboardHIDType_USBKeyboard)
    2324             {
    2325                 InsertConfigNode(pUsbDevices, "HidKeyboard", &pDev);
    2326                 InsertConfigNode(pDev,     "0", &pInst);
    2327                 InsertConfigNode(pInst,    "Config", &pCfg);
    2328 
    2329                 InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    2330                 InsertConfigString(pLunL0, "Driver",               "KeyboardQueue");
    2331                 InsertConfigNode(pLunL0,   "Config", &pCfg);
    2332                 InsertConfigInteger(pCfg,  "QueueSize",            64);
    2333 
    2334                 InsertConfigNode(pLunL0,   "AttachedDriver", &pLunL1);
    2335                 InsertConfigString(pLunL1, "Driver",               "MainKeyboard");
    2336             }
    2337         }
    2338 
    2339         /*
    2340          * Storage controllers.
    2341          */
    2342         com::SafeIfaceArray<IStorageController> ctrls;
    2343         PCFGMNODE aCtrlNodes[StorageControllerType_VirtioSCSI + 1] = {};
    2344         hrc = pMachine->COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(ctrls));       H();
    2345 
    2346         bool fFdcEnabled = false;
    2347         for (size_t i = 0; i < ctrls.size(); ++i)
    2348         {
    2349             DeviceType_T *paLedDevType = NULL;
    2350 
    2351             StorageControllerType_T enmCtrlType;
    2352             hrc = ctrls[i]->COMGETTER(ControllerType)(&enmCtrlType);                        H();
    2353             AssertRelease((unsigned)enmCtrlType < RT_ELEMENTS(aCtrlNodes)
    2354                           || enmCtrlType == StorageControllerType_USB);
    2355 
    2356             StorageBus_T enmBus;
    2357             hrc = ctrls[i]->COMGETTER(Bus)(&enmBus);                                        H();
    2358 
    2359             Bstr controllerName;
    2360             hrc = ctrls[i]->COMGETTER(Name)(controllerName.asOutParam());                   H();
    2361 
    2362             ULONG ulInstance = 999;
    2363             hrc = ctrls[i]->COMGETTER(Instance)(&ulInstance);                               H();
    2364 
    2365             BOOL fUseHostIOCache;
    2366             hrc = ctrls[i]->COMGETTER(UseHostIOCache)(&fUseHostIOCache);                    H();
    2367 
    2368             BOOL fBootable;
    2369             hrc = ctrls[i]->COMGETTER(Bootable)(&fBootable);                                H();
    2370 
    2371             PCFGMNODE pCtlInst = NULL;
    2372             const char *pszCtrlDev = i_storageControllerTypeToStr(enmCtrlType);
    2373             if (enmCtrlType != StorageControllerType_USB)
    2374             {
    2375                 /* /Devices/<ctrldev>/ */
    2376                 pDev = aCtrlNodes[enmCtrlType];
    2377                 if (!pDev)
    2378                 {
    2379                     InsertConfigNode(pDevices, pszCtrlDev, &pDev);
    2380                     aCtrlNodes[enmCtrlType] = pDev; /* IDE variants are handled in the switch */
    2381                 }
    2382 
    2383                 /* /Devices/<ctrldev>/<instance>/ */
    2384                 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pCtlInst);
    2385 
    2386                 /* Device config: /Devices/<ctrldev>/<instance>/<values> & /ditto/Config/<values> */
    2387                 InsertConfigInteger(pCtlInst, "Trusted",   1);
    2388                 InsertConfigNode(pCtlInst,    "Config",    &pCfg);
    2389             }
    2390 
    2391             static const char * const apszBiosConfigScsi[MAX_BIOS_LUN_COUNT] =
    2392             { "ScsiLUN1", "ScsiLUN2", "ScsiLUN3", "ScsiLUN4" };
    2393 
    2394             static const char * const apszBiosConfigSata[MAX_BIOS_LUN_COUNT] =
    2395             { "SataLUN1", "SataLUN2", "SataLUN3", "SataLUN4" };
    2396 
    2397             switch (enmCtrlType)
    2398             {
    2399                 case StorageControllerType_LsiLogic:
    2400                 {
    2401                     hrc = pBusMgr->assignPCIDevice("lsilogic", pCtlInst);                   H();
    2402 
    2403                     InsertConfigInteger(pCfg, "Bootable",  fBootable);
    2404 
    2405                     /* BIOS configuration values, first SCSI controller only. */
    2406                     if (   !pBusMgr->hasPCIDevice("lsilogic", 1)
    2407                         && !pBusMgr->hasPCIDevice("buslogic", 0)
    2408                         && !pBusMgr->hasPCIDevice("lsilogicsas", 0)
    2409                         && pBiosCfg)
    2410                     {
    2411                         InsertConfigString(pBiosCfg, "ScsiHardDiskDevice", "lsilogicscsi");
    2412                         hrc = SetBiosDiskInfo(pMachine, pCfg, pBiosCfg, controllerName, apszBiosConfigScsi);    H();
    2413                     }
    2414 
    2415                     /* Attach the status driver */
    2416                     i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk) | RT_BIT_32(DeviceType_DVD),
    2417                                          16, &paLedDevType, &mapMediumAttachments, pszCtrlDev, ulInstance);
    2418                     break;
    2419                 }
    2420 
    2421                 case StorageControllerType_BusLogic:
    2422                 {
    2423                     hrc = pBusMgr->assignPCIDevice("buslogic", pCtlInst);                   H();
    2424 
    2425                     InsertConfigInteger(pCfg, "Bootable",  fBootable);
    2426 
    2427                     /* BIOS configuration values, first SCSI controller only. */
    2428                     if (   !pBusMgr->hasPCIDevice("lsilogic", 0)
    2429                         && !pBusMgr->hasPCIDevice("buslogic", 1)
    2430                         && !pBusMgr->hasPCIDevice("lsilogicsas", 0)
    2431                         && pBiosCfg)
    2432                     {
    2433                         InsertConfigString(pBiosCfg, "ScsiHardDiskDevice", "buslogic");
    2434                         hrc = SetBiosDiskInfo(pMachine, pCfg, pBiosCfg, controllerName, apszBiosConfigScsi);    H();
    2435                     }
    2436 
    2437                     /* Attach the status driver */
    2438                     i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk) | RT_BIT_32(DeviceType_DVD),
    2439                                          16, &paLedDevType, &mapMediumAttachments, pszCtrlDev, ulInstance);
    2440                     break;
    2441                 }
    2442 
    2443                 case StorageControllerType_IntelAhci:
    2444                 {
    2445                     hrc = pBusMgr->assignPCIDevice("ahci", pCtlInst);                       H();
    2446 
    2447                     ULONG cPorts = 0;
    2448                     hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts);                          H();
    2449                     InsertConfigInteger(pCfg, "PortCount", cPorts);
    2450                     InsertConfigInteger(pCfg, "Bootable",  fBootable);
    2451 
    2452                     com::SafeIfaceArray<IMediumAttachment> atts;
    2453                     hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(),
    2454                                                                      ComSafeArrayAsOutParam(atts));  H();
    2455 
    2456                     /* Configure the hotpluggable flag for the port. */
    2457                     for (unsigned idxAtt = 0; idxAtt < atts.size(); ++idxAtt)
    2458                     {
    2459                         IMediumAttachment *pMediumAtt = atts[idxAtt];
    2460 
    2461                         LONG lPortNum = 0;
    2462                         hrc = pMediumAtt->COMGETTER(Port)(&lPortNum);                       H();
    2463 
    2464                         BOOL fHotPluggable = FALSE;
    2465                         hrc = pMediumAtt->COMGETTER(HotPluggable)(&fHotPluggable);          H();
    2466                         if (SUCCEEDED(hrc))
    2467                         {
    2468                             PCFGMNODE pPortCfg;
    2469                             char szName[24];
    2470                             RTStrPrintf(szName, sizeof(szName), "Port%d", lPortNum);
    2471 
    2472                             InsertConfigNode(pCfg, szName, &pPortCfg);
    2473                             InsertConfigInteger(pPortCfg, "Hotpluggable", fHotPluggable ? 1 : 0);
    2474                         }
    2475                     }
    2476 
    2477                     /* BIOS configuration values, first AHCI controller only. */
    2478                     if (   !pBusMgr->hasPCIDevice("ahci", 1)
    2479                         && pBiosCfg)
    2480                     {
    2481                         InsertConfigString(pBiosCfg, "SataHardDiskDevice", "ahci");
    2482                         hrc = SetBiosDiskInfo(pMachine, pCfg, pBiosCfg, controllerName, apszBiosConfigSata);    H();
    2483                     }
    2484 
    2485                     /* Attach the status driver */
    2486                     i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk) | RT_BIT_32(DeviceType_DVD),
    2487                                          cPorts, &paLedDevType, &mapMediumAttachments, pszCtrlDev, ulInstance);
    2488                     break;
    2489                 }
    2490 
    2491                 case StorageControllerType_PIIX3:
    2492                 case StorageControllerType_PIIX4:
    2493                 case StorageControllerType_ICH6:
    2494                 {
    2495                     /*
    2496                      * IDE (update this when the main interface changes)
    2497                      */
    2498                     hrc = pBusMgr->assignPCIDevice("piix3ide", pCtlInst);                   H();
    2499                     InsertConfigString(pCfg,   "Type", controllerString(enmCtrlType));
    2500 
    2501                     /* Attach the status driver */
    2502                     i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk) | RT_BIT_32(DeviceType_DVD),
    2503                                          4, &paLedDevType, &mapMediumAttachments, pszCtrlDev, ulInstance);
    2504 
    2505                     /* IDE flavors */
    2506                     aCtrlNodes[StorageControllerType_PIIX3] = pDev;
    2507                     aCtrlNodes[StorageControllerType_PIIX4] = pDev;
    2508                     aCtrlNodes[StorageControllerType_ICH6]  = pDev;
    2509                     break;
    2510                 }
    2511 
    2512                 case StorageControllerType_I82078:
    2513                 {
    2514                     /*
    2515                      * i82078 Floppy drive controller
    2516                      */
    2517                     fFdcEnabled = true;
    2518                     InsertConfigInteger(pCfg, "IRQ",       6);
    2519                     InsertConfigInteger(pCfg, "DMA",       2);
    2520                     InsertConfigInteger(pCfg, "MemMapped", 0 );
    2521                     InsertConfigInteger(pCfg, "IOBase",    0x3f0);
    2522 
    2523                     /* Attach the status driver */
    2524                     i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_Floppy),
    2525                                          2, NULL, &mapMediumAttachments, pszCtrlDev, ulInstance);
    2526                     break;
    2527                 }
    2528 
    2529                 case StorageControllerType_LsiLogicSas:
    2530                 {
    2531                     hrc = pBusMgr->assignPCIDevice("lsilogicsas", pCtlInst);                H();
    2532 
    2533                     InsertConfigString(pCfg,  "ControllerType", "SAS1068");
    2534                     InsertConfigInteger(pCfg, "Bootable",  fBootable);
    2535 
    2536                     /* BIOS configuration values, first SCSI controller only. */
    2537                     if (   !pBusMgr->hasPCIDevice("lsilogic", 0)
    2538                         && !pBusMgr->hasPCIDevice("buslogic", 0)
    2539                         && !pBusMgr->hasPCIDevice("lsilogicsas", 1)
    2540                         && pBiosCfg)
    2541                     {
    2542                         InsertConfigString(pBiosCfg, "ScsiHardDiskDevice", "lsilogicsas");
    2543                         hrc = SetBiosDiskInfo(pMachine, pCfg, pBiosCfg, controllerName, apszBiosConfigScsi);    H();
    2544                     }
    2545 
    2546                     ULONG cPorts = 0;
    2547                     hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts);                          H();
    2548                     InsertConfigInteger(pCfg, "NumPorts", cPorts);
    2549 
    2550                     /* Attach the status driver */
    2551                     i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk) | RT_BIT_32(DeviceType_DVD) /*?*/,
    2552                                          8, &paLedDevType, &mapMediumAttachments, pszCtrlDev, ulInstance);
    2553                     break;
    2554                 }
    2555 
    2556                 case StorageControllerType_USB:
    2557                 {
    2558                     if (pUsbDevices)
    2559                     {
    2560                         /*
    2561                          * USB MSDs are handled a bit different as the device instance
    2562                          * doesn't match the storage controller instance but the port.
    2563                          */
    2564                         InsertConfigNode(pUsbDevices, "Msd", &pDev);
    2565                         pCtlInst = pDev;
    2566                     }
    2567                     else
    2568                         return pVMM->pfnVMR3SetError(pUVM, VERR_NOT_FOUND, RT_SRC_POS,
    2569                                 N_("There is no USB controller enabled but there\n"
    2570                                    "is at least one USB storage device configured for this VM.\n"
    2571                                    "To fix this problem either enable the USB controller or remove\n"
    2572                                    "the storage device from the VM"));
    2573                     break;
    2574                 }
    2575 
    2576                 case StorageControllerType_NVMe:
    2577                 {
    2578                     hrc = pBusMgr->assignPCIDevice("nvme", pCtlInst);                       H();
    2579 
    2580                     ULONG cPorts = 0;
    2581                     hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts);                          H();
    2582                     InsertConfigInteger(pCfg, "NamespacesMax", cPorts);
    2583 
    2584                     /* Attach the status driver */
    2585                     i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk),
    2586                                          cPorts, NULL, &mapMediumAttachments, pszCtrlDev, ulInstance);
    2587                     break;
    2588                 }
    2589 
    2590                 case StorageControllerType_VirtioSCSI:
    2591                 {
    2592                     hrc = pBusMgr->assignPCIDevice("virtio-scsi", pCtlInst);                H();
    2593 
    2594                     ULONG cPorts = 0;
    2595                     hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts);                          H();
    2596                     InsertConfigInteger(pCfg, "NumTargets", cPorts);
    2597                     InsertConfigInteger(pCfg, "Bootable",   fBootable);
    2598 
    2599                     /* Attach the status driver */
    2600                     i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk) | RT_BIT_32(DeviceType_DVD) /*?*/,
    2601                                          cPorts, &paLedDevType, &mapMediumAttachments, pszCtrlDev, ulInstance);
    2602                     break;
    2603                 }
    2604 
    2605                 default:
    2606                     AssertLogRelMsgFailedReturn(("invalid storage controller type: %d\n", enmCtrlType), VERR_MAIN_CONFIG_CONSTRUCTOR_IPE);
    2607             }
    2608 
    2609             /* Attach the media to the storage controllers. */
    2610             com::SafeIfaceArray<IMediumAttachment> atts;
    2611             hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(),
    2612                                                             ComSafeArrayAsOutParam(atts));  H();
    2613 
    2614             /* Builtin I/O cache - per device setting. */
    2615             BOOL fBuiltinIOCache = true;
    2616             hrc = pMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache);                    H();
    2617 
    2618             bool fInsertDiskIntegrityDrv = false;
    2619             Bstr strDiskIntegrityFlag;
    2620             hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EnableDiskIntegrityDriver").raw(),
    2621                                          strDiskIntegrityFlag.asOutParam());
    2622             if (   hrc   == S_OK
    2623                 && strDiskIntegrityFlag == "1")
    2624                 fInsertDiskIntegrityDrv = true;
    2625 
    2626             for (size_t j = 0; j < atts.size(); ++j)
    2627             {
    2628                 IMediumAttachment *pMediumAtt = atts[j];
    2629                 vrc = i_configMediumAttachment(pszCtrlDev,
    2630                                                ulInstance,
    2631                                                enmBus,
    2632                                                !!fUseHostIOCache,
    2633                                                enmCtrlType == StorageControllerType_NVMe ? false : !!fBuiltinIOCache,
    2634                                                fInsertDiskIntegrityDrv,
    2635                                                false /* fSetupMerge */,
    2636                                                0 /* uMergeSource */,
    2637                                                0 /* uMergeTarget */,
    2638                                                pMediumAtt,
    2639                                                mMachineState,
    2640                                                NULL /* phrc */,
    2641                                                false /* fAttachDetach */,
    2642                                                false /* fForceUnmount */,
    2643                                                false /* fHotplug */,
    2644                                                pUVM,
    2645                                                pVMM,
    2646                                                paLedDevType,
    2647                                                NULL /* ppLunL0 */);
    2648                 if (RT_FAILURE(vrc))
    2649                     return vrc;
    2650             }
    2651             H();
    2652         }
    2653         H();
    2654 
    2655         /*
    2656          * Network adapters
    2657          */
    2658 #ifdef VMWARE_NET_IN_SLOT_11
    2659         bool fSwapSlots3and11 = false;
    2660 #endif
    2661         PCFGMNODE pDevPCNet = NULL;          /* PCNet-type devices */
    2662         InsertConfigNode(pDevices, "pcnet", &pDevPCNet);
    2663 #ifdef VBOX_WITH_E1000
    2664         PCFGMNODE pDevE1000 = NULL;          /* E1000-type devices */
    2665         InsertConfigNode(pDevices, "e1000", &pDevE1000);
    2666 #endif
    2667 #ifdef VBOX_WITH_VIRTIO
    2668         PCFGMNODE pDevVirtioNet = NULL;          /* Virtio network devices */
    2669         InsertConfigNode(pDevices, "virtio-net", &pDevVirtioNet);
    2670 #endif /* VBOX_WITH_VIRTIO */
    2671         PCFGMNODE pDevDP8390 = NULL;         /* DP8390-type devices */
    2672         InsertConfigNode(pDevices, "dp8390", &pDevDP8390);
    2673         PCFGMNODE pDev3C501 = NULL;          /* EtherLink-type devices */
    2674         InsertConfigNode(pDevices, "3c501",  &pDev3C501);
    2675 
    2676         std::list<BootNic> llBootNics;
    2677         for (ULONG uInstance = 0; uInstance < maxNetworkAdapters; ++uInstance)
    2678         {
    2679             ComPtr<INetworkAdapter> networkAdapter;
    2680             hrc = pMachine->GetNetworkAdapter(uInstance, networkAdapter.asOutParam());      H();
    2681             BOOL fEnabledNetAdapter = FALSE;
    2682             hrc = networkAdapter->COMGETTER(Enabled)(&fEnabledNetAdapter);                  H();
    2683             if (!fEnabledNetAdapter)
    2684                 continue;
    2685 
    2686             /*
    2687              * The virtual hardware type. Create appropriate device first.
    2688              */
    2689             const char *pszAdapterName = "pcnet";
    2690             NetworkAdapterType_T adapterType;
    2691             hrc = networkAdapter->COMGETTER(AdapterType)(&adapterType);                     H();
    2692             switch (adapterType)
    2693             {
    2694                 case NetworkAdapterType_Am79C970A:
    2695                 case NetworkAdapterType_Am79C973:
    2696                 case NetworkAdapterType_Am79C960:
    2697                     pDev = pDevPCNet;
    2698                     break;
    2699 #ifdef VBOX_WITH_E1000
    2700                 case NetworkAdapterType_I82540EM:
    2701                 case NetworkAdapterType_I82543GC:
    2702                 case NetworkAdapterType_I82545EM:
    2703                     pDev = pDevE1000;
    2704                     pszAdapterName = "e1000";
    2705                     break;
    2706 #endif
    2707 #ifdef VBOX_WITH_VIRTIO
    2708                 case NetworkAdapterType_Virtio:
    2709                     pDev = pDevVirtioNet;
    2710                     pszAdapterName = "virtio-net";
    2711                     break;
    2712 #endif /* VBOX_WITH_VIRTIO */
    2713                 case NetworkAdapterType_NE1000:
    2714                 case NetworkAdapterType_NE2000:
    2715                 case NetworkAdapterType_WD8003:
    2716                 case NetworkAdapterType_WD8013:
    2717                 case NetworkAdapterType_ELNK2:
    2718                     pDev = pDevDP8390;
    2719                     break;
    2720                 case NetworkAdapterType_ELNK1:
    2721                     pDev = pDev3C501;
    2722                     break;
    2723                 default:
    2724                     AssertMsgFailed(("Invalid network adapter type '%d' for slot '%d'", adapterType, uInstance));
    2725                     return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    2726                                                  N_("Invalid network adapter type '%d' for slot '%d'"), adapterType, uInstance);
    2727             }
    2728 
    2729             InsertConfigNode(pDev, Utf8StrFmt("%u", uInstance).c_str(), &pInst);
    2730             InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    2731             /* the first network card gets the PCI ID 3, the next 3 gets 8..10,
    2732              * next 4 get 16..19. */
    2733             int iPCIDeviceNo;
    2734             switch (uInstance)
    2735             {
    2736                 case 0:
    2737                     iPCIDeviceNo = 3;
    2738                     break;
    2739                 case 1: case 2: case 3:
    2740                     iPCIDeviceNo = uInstance - 1 + 8;
    2741                     break;
    2742                 case 4: case 5: case 6: case 7:
    2743                     iPCIDeviceNo = uInstance - 4 + 16;
    2744                     break;
    2745                 default:
    2746                     /* auto assignment */
    2747                     iPCIDeviceNo = -1;
    2748                     break;
    2749             }
    2750 #ifdef VMWARE_NET_IN_SLOT_11
    2751             /*
    2752              * Dirty hack for PCI slot compatibility with VMWare,
    2753              * it assigns slot 0x11 to the first network controller.
    2754              */
    2755             if (iPCIDeviceNo == 3 && adapterType == NetworkAdapterType_I82545EM)
    2756             {
    2757                 iPCIDeviceNo = 0x11;
    2758                 fSwapSlots3and11 = true;
    2759             }
    2760             else if (iPCIDeviceNo == 0x11 && fSwapSlots3and11)
    2761                 iPCIDeviceNo = 3;
    2762 #endif
    2763             PCIBusAddress PCIAddr = PCIBusAddress(0, iPCIDeviceNo, 0);
    2764             hrc = pBusMgr->assignPCIDevice(pszAdapterName, pInst, PCIAddr);                 H();
    2765 
    2766             InsertConfigNode(pInst, "Config", &pCfg);
    2767 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE   /* not safe here yet. */ /** @todo Make PCNet ring-0 safe on 32-bit mac kernels! */
    2768             if (pDev == pDevPCNet)
    2769                 InsertConfigInteger(pCfg, "R0Enabled",    false);
    2770 #endif
    2771             /*
    2772              * Collect information needed for network booting and add it to the list.
    2773              */
    2774             BootNic     nic;
    2775 
    2776             nic.mInstance    = uInstance;
    2777             /* Could be updated by reference, if auto assigned */
    2778             nic.mPCIAddress  = PCIAddr;
    2779 
    2780             hrc = networkAdapter->COMGETTER(BootPriority)(&nic.mBootPrio);                  H();
    2781 
    2782             llBootNics.push_back(nic);
    2783 
    2784             /*
    2785              * The virtual hardware type. PCNet supports three types, E1000 three,
    2786              * but VirtIO only one.
    2787              */
    2788             switch (adapterType)
    2789             {
    2790                 case NetworkAdapterType_Am79C970A:
    2791                     InsertConfigString(pCfg, "ChipType", "Am79C970A");
    2792                     break;
    2793                 case NetworkAdapterType_Am79C973:
    2794                     InsertConfigString(pCfg, "ChipType", "Am79C973");
    2795                     break;
    2796                 case NetworkAdapterType_Am79C960:
    2797                     InsertConfigString(pCfg, "ChipType", "Am79C960");
    2798                     break;
    2799                 case NetworkAdapterType_I82540EM:
    2800                     InsertConfigInteger(pCfg, "AdapterType", 0);
    2801                     break;
    2802                 case NetworkAdapterType_I82543GC:
    2803                     InsertConfigInteger(pCfg, "AdapterType", 1);
    2804                     break;
    2805                 case NetworkAdapterType_I82545EM:
    2806                     InsertConfigInteger(pCfg, "AdapterType", 2);
    2807                     break;
    2808                 case NetworkAdapterType_Virtio:
    2809                     break;
    2810                 case NetworkAdapterType_NE1000:
    2811                     InsertConfigString(pCfg, "DeviceType", "NE1000");
    2812                     break;
    2813                 case NetworkAdapterType_NE2000:
    2814                     InsertConfigString(pCfg, "DeviceType", "NE2000");
    2815                     break;
    2816                 case NetworkAdapterType_WD8003:
    2817                     InsertConfigString(pCfg, "DeviceType", "WD8003");
    2818                     break;
    2819                 case NetworkAdapterType_WD8013:
    2820                     InsertConfigString(pCfg, "DeviceType", "WD8013");
    2821                     break;
    2822                 case NetworkAdapterType_ELNK2:
    2823                     InsertConfigString(pCfg, "DeviceType", "3C503");
    2824                     break;
    2825                 case NetworkAdapterType_ELNK1:
    2826                     break;
    2827                 case NetworkAdapterType_Null:      AssertFailedBreak(); /* (compiler warnings) */
    2828 #ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK
    2829                 case NetworkAdapterType_32BitHack: AssertFailedBreak(); /* (compiler warnings) */
    2830 #endif
    2831             }
    2832 
    2833             /*
    2834              * Get the MAC address and convert it to binary representation
    2835              */
    2836             Bstr macAddr;
    2837             hrc = networkAdapter->COMGETTER(MACAddress)(macAddr.asOutParam());              H();
    2838             Assert(!macAddr.isEmpty());
    2839             Utf8Str macAddrUtf8 = macAddr;
    2840 #ifdef VBOX_WITH_CLOUD_NET
    2841             NetworkAttachmentType_T eAttachmentType;
    2842             hrc = networkAdapter->COMGETTER(AttachmentType)(&eAttachmentType);                 H();
    2843             if (eAttachmentType == NetworkAttachmentType_Cloud)
    2844             {
    2845                 mGateway.setLocalMacAddress(macAddrUtf8);
    2846                 /* We'll insert cloud MAC later, when it becomes known. */
    2847             }
    2848             else
    2849             {
    2850 #endif
    2851             char *macStr = (char*)macAddrUtf8.c_str();
    2852             Assert(strlen(macStr) == 12);
    2853             RTMAC Mac;
    2854             RT_ZERO(Mac);
    2855             char *pMac = (char*)&Mac;
    2856             for (uint32_t i = 0; i < 6; ++i)
    2857             {
    2858                 int c1 = *macStr++ - '0';
    2859                 if (c1 > 9)
    2860                     c1 -= 7;
    2861                 int c2 = *macStr++ - '0';
    2862                 if (c2 > 9)
    2863                     c2 -= 7;
    2864                 *pMac++ = (char)(((c1 & 0x0f) << 4) | (c2 & 0x0f));
    2865             }
    2866             InsertConfigBytes(pCfg, "MAC", &Mac, sizeof(Mac));
    2867 #ifdef VBOX_WITH_CLOUD_NET
    2868             }
    2869 #endif
    2870             /*
    2871              * Check if the cable is supposed to be unplugged
    2872              */
    2873             BOOL fCableConnected;
    2874             hrc = networkAdapter->COMGETTER(CableConnected)(&fCableConnected);              H();
    2875             InsertConfigInteger(pCfg, "CableConnected", fCableConnected ? 1 : 0);
    2876 
    2877             /*
    2878              * Line speed to report from custom drivers
    2879              */
    2880             ULONG ulLineSpeed;
    2881             hrc = networkAdapter->COMGETTER(LineSpeed)(&ulLineSpeed);                       H();
    2882             InsertConfigInteger(pCfg, "LineSpeed", ulLineSpeed);
    2883 
    2884             /*
    2885              * Attach the status driver.
    2886              */
    2887             i_attachStatusDriver(pInst, DeviceType_Network);
    2888 
    2889             /*
    2890              * Configure the network card now
    2891              */
    2892             bool fIgnoreConnectFailure = mMachineState == MachineState_Restoring;
    2893             vrc = i_configNetwork(pszAdapterName,
    2894                                   uInstance,
    2895                                   0,
    2896                                   networkAdapter,
    2897                                   pCfg,
    2898                                   pLunL0,
    2899                                   pInst,
    2900                                   false /*fAttachDetach*/,
    2901                                   fIgnoreConnectFailure,
    2902                                   pUVM,
    2903                                   pVMM);
    2904             if (RT_FAILURE(vrc))
    2905                 return vrc;
    2906         }
    2907 
    2908         /*
    2909          * Build network boot information and transfer it to the BIOS.
    2910          */
    2911         if (pNetBootCfg && !llBootNics.empty())  /* NetBoot node doesn't exist for EFI! */
    2912         {
    2913             llBootNics.sort();  /* Sort the list by boot priority. */
    2914 
    2915             char        achBootIdx[] = "0";
    2916             unsigned    uBootIdx = 0;
    2917 
    2918             for (std::list<BootNic>::iterator it = llBootNics.begin(); it != llBootNics.end(); ++it)
    2919             {
    2920                 /* A NIC with priority 0 is only used if it's first in the list. */
    2921                 if (it->mBootPrio == 0 && uBootIdx != 0)
    2922                     break;
    2923 
    2924                 PCFGMNODE pNetBtDevCfg;
    2925                 achBootIdx[0] = (char)('0' + uBootIdx++);   /* Boot device order. */
    2926                 InsertConfigNode(pNetBootCfg, achBootIdx, &pNetBtDevCfg);
    2927                 InsertConfigInteger(pNetBtDevCfg, "NIC", it->mInstance);
    2928                 InsertConfigInteger(pNetBtDevCfg, "PCIBusNo",      it->mPCIAddress.miBus);
    2929                 InsertConfigInteger(pNetBtDevCfg, "PCIDeviceNo",   it->mPCIAddress.miDevice);
    2930                 InsertConfigInteger(pNetBtDevCfg, "PCIFunctionNo", it->mPCIAddress.miFn);
    2931             }
    2932         }
    2933 
    2934         /*
    2935          * Serial (UART) Ports
    2936          */
    2937         /* serial enabled mask to be passed to dev ACPI */
    2938         uint16_t auSerialIoPortBase[SchemaDefs::SerialPortCount] = {0};
    2939         uint8_t auSerialIrq[SchemaDefs::SerialPortCount] = {0};
    2940         InsertConfigNode(pDevices, "serial", &pDev);
    2941         for (ULONG ulInstance = 0; ulInstance < SchemaDefs::SerialPortCount; ++ulInstance)
    2942         {
    2943             ComPtr<ISerialPort> serialPort;
    2944             hrc = pMachine->GetSerialPort(ulInstance, serialPort.asOutParam());             H();
    2945             BOOL fEnabledSerPort = FALSE;
    2946             if (serialPort)
    2947             {
    2948                 hrc = serialPort->COMGETTER(Enabled)(&fEnabledSerPort);                     H();
    2949             }
    2950             if (!fEnabledSerPort)
    2951             {
    2952                 m_aeSerialPortMode[ulInstance] = PortMode_Disconnected;
    2953                 continue;
    2954             }
    2955 
    2956             InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pInst);
    2957             InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
    2958             InsertConfigNode(pInst, "Config", &pCfg);
    2959 
    2960             ULONG ulIRQ;
    2961             hrc = serialPort->COMGETTER(IRQ)(&ulIRQ);                                       H();
    2962             InsertConfigInteger(pCfg, "IRQ", ulIRQ);
    2963             auSerialIrq[ulInstance] = (uint8_t)ulIRQ;
    2964 
    2965             ULONG ulIOBase;
    2966             hrc = serialPort->COMGETTER(IOBase)(&ulIOBase);                                 H();
    2967             InsertConfigInteger(pCfg, "IOBase", ulIOBase);
    2968             auSerialIoPortBase[ulInstance] = (uint16_t)ulIOBase;
    2969 
    2970             BOOL  fServer;
    2971             hrc = serialPort->COMGETTER(Server)(&fServer);                                  H();
    2972             hrc = serialPort->COMGETTER(Path)(bstr.asOutParam());                           H();
    2973             UartType_T eUartType;
    2974             const char *pszUartType;
    2975             hrc = serialPort->COMGETTER(UartType)(&eUartType);                              H();
    2976             switch (eUartType)
    2977             {
    2978                 case UartType_U16450: pszUartType = "16450"; break;
    2979                 case UartType_U16750: pszUartType = "16750"; break;
    2980                 default: AssertFailed(); RT_FALL_THRU();
    2981                 case UartType_U16550A: pszUartType = "16550A"; break;
    2982             }
    2983             InsertConfigString(pCfg, "UartType", pszUartType);
    2984 
    2985             PortMode_T eHostMode;
    2986             hrc = serialPort->COMGETTER(HostMode)(&eHostMode);                              H();
    2987 
    2988             m_aeSerialPortMode[ulInstance] = eHostMode;
    2989             if (eHostMode != PortMode_Disconnected)
    2990             {
    2991                 vrc = i_configSerialPort(pInst, eHostMode, Utf8Str(bstr).c_str(), RT_BOOL(fServer));
    2992                 if (RT_FAILURE(vrc))
    2993                     return vrc;
    2994             }
    2995         }
    2996 
    2997         /*
    2998          * Parallel (LPT) Ports
    2999          */
    3000         /* parallel enabled mask to be passed to dev ACPI */
    3001         uint16_t auParallelIoPortBase[SchemaDefs::ParallelPortCount] = {0};
    3002         uint8_t auParallelIrq[SchemaDefs::ParallelPortCount] = {0};
    3003         InsertConfigNode(pDevices, "parallel", &pDev);
    3004         for (ULONG ulInstance = 0; ulInstance < SchemaDefs::ParallelPortCount; ++ulInstance)
    3005         {
    3006             ComPtr<IParallelPort> parallelPort;
    3007             hrc = pMachine->GetParallelPort(ulInstance, parallelPort.asOutParam());         H();
    3008             BOOL fEnabledParPort = FALSE;
    3009             if (parallelPort)
    3010             {
    3011                 hrc = parallelPort->COMGETTER(Enabled)(&fEnabledParPort);                   H();
    3012             }
    3013             if (!fEnabledParPort)
    3014                 continue;
    3015 
    3016             InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pInst);
    3017             InsertConfigNode(pInst, "Config", &pCfg);
    3018 
    3019             ULONG ulIRQ;
    3020             hrc = parallelPort->COMGETTER(IRQ)(&ulIRQ);                                     H();
    3021             InsertConfigInteger(pCfg, "IRQ", ulIRQ);
    3022             auParallelIrq[ulInstance] = (uint8_t)ulIRQ;
    3023             ULONG ulIOBase;
    3024             hrc = parallelPort->COMGETTER(IOBase)(&ulIOBase);                               H();
    3025             InsertConfigInteger(pCfg,   "IOBase", ulIOBase);
    3026             auParallelIoPortBase[ulInstance] = (uint16_t)ulIOBase;
    3027 
    3028             hrc = parallelPort->COMGETTER(Path)(bstr.asOutParam());                         H();
    3029             if (!bstr.isEmpty())
    3030             {
    3031                 InsertConfigNode(pInst,     "LUN#0", &pLunL0);
    3032                 InsertConfigString(pLunL0,  "Driver", "HostParallel");
    3033                 InsertConfigNode(pLunL0,    "Config", &pLunL1);
    3034                 InsertConfigString(pLunL1,  "DevicePath", bstr);
    3035             }
    3036         }
    3037 
    3038         /*
    3039          * VMM Device
    3040          */
    3041         InsertConfigNode(pDevices, "VMMDev", &pDev);
    3042         InsertConfigNode(pDev,     "0", &pInst);
    3043         InsertConfigNode(pInst,    "Config", &pCfg);
    3044         InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    3045         hrc = pBusMgr->assignPCIDevice("VMMDev", pInst);                                    H();
    3046 
    3047         Bstr hwVersion;
    3048         hrc = pMachine->COMGETTER(HardwareVersion)(hwVersion.asOutParam());                 H();
    3049         if (hwVersion.compare(Bstr("1").raw()) == 0) /* <= 2.0.x */
    3050             InsertConfigInteger(pCfg, "HeapEnabled", 0);
    3051         Bstr snapshotFolder;
    3052         hrc = pMachine->COMGETTER(SnapshotFolder)(snapshotFolder.asOutParam());             H();
    3053         InsertConfigString(pCfg, "GuestCoreDumpDir", snapshotFolder);
    3054 
    3055         /* the VMM device's Main driver */
    3056         InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    3057         InsertConfigString(pLunL0, "Driver",               "HGCM");
    3058         InsertConfigNode(pLunL0,   "Config", &pCfg);
    3059 
    3060         /*
    3061          * Attach the status driver.
    3062          */
    3063         i_attachStatusDriver(pInst, DeviceType_SharedFolder);
    3064 
    3065         /*
    3066          * Audio configuration.
    3067          */
    3068 
    3069         /*
    3070          * AC'97 ICH / SoundBlaster16 audio / Intel HD Audio.
    3071          */
    3072         ComPtr<IAudioSettings> audioSettings;
    3073         hrc = pMachine->COMGETTER(AudioSettings)(audioSettings.asOutParam());               H();
    3074 
    3075         BOOL fAudioEnabled = FALSE;
    3076         ComPtr<IAudioAdapter> audioAdapter;
    3077         hrc = audioSettings->COMGETTER(Adapter)(audioAdapter.asOutParam());                 H();
    3078         if (audioAdapter)
    3079         {
    3080             hrc = audioAdapter->COMGETTER(Enabled)(&fAudioEnabled);                         H();
    3081         }
    3082 
    3083         if (fAudioEnabled)
    3084         {
    3085             AudioControllerType_T enmAudioController;
    3086             hrc = audioAdapter->COMGETTER(AudioController)(&enmAudioController);            H();
    3087             AudioCodecType_T enmAudioCodec;
    3088             hrc = audioAdapter->COMGETTER(AudioCodec)(&enmAudioCodec);                      H();
    3089 
    3090             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/Audio/Device/TimerHz", &strTmp);
    3091             const uint64_t uTimerHz = strTmp.toUInt64();
    3092 
    3093             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/Audio/Device/BufSizeInMs", &strTmp);
    3094             const uint64_t uBufSizeInMs = strTmp.toUInt64();
    3095 
    3096             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/Audio/Device/BufSizeOutMs", &strTmp);
    3097             const uint64_t uBufSizeOutMs = strTmp.toUInt64();
    3098 
    3099             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/Audio/Debug/Enabled", &strTmp);
    3100             const bool fDebugEnabled = strTmp.equalsIgnoreCase("true") || strTmp.equalsIgnoreCase("1");
    3101 
    3102             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/Audio/Debug/Level", &strTmp);
    3103             const uint32_t uDebugLevel = strTmp.toUInt32();
    3104 
    3105             Utf8Str strDebugPathOut;
    3106             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/Audio/Debug/PathOut", &strDebugPathOut);
    3107 
    3108 #ifdef VBOX_WITH_AUDIO_VALIDATIONKIT
    3109             GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/Audio/VaKit/Enabled", &strTmp); /* Deprecated; do not use! */
    3110             if (strTmp.isEmpty())
    3111                 GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/Audio/ValKit/Enabled", &strTmp);
    3112             /* Whether the Validation Kit audio backend runs as the primary backend.
    3113              * Can also be used with VBox release builds. */
    3114             const bool fValKitEnabled = strTmp.equalsIgnoreCase("true") || strTmp.equalsIgnoreCase("1");
    3115 #endif
    3116             /** @todo Implement an audio device class, similar to the audio backend class, to construct the common stuff
    3117              *        without duplicating (more) code. */
    3118 
    3119             const char *pszAudioDevice;
    3120             switch (enmAudioController)
    3121             {
    3122                 case AudioControllerType_AC97:
    3123                 {
    3124                     /* ICH AC'97. */
    3125                     pszAudioDevice = "ichac97";
    3126 
    3127                     InsertConfigNode(pDevices,      pszAudioDevice,         &pDev);
    3128                     InsertConfigNode(pDev,          "0",                    &pInst);
    3129                     InsertConfigInteger(pInst,      "Trusted",              1); /* boolean */
    3130                     hrc = pBusMgr->assignPCIDevice(pszAudioDevice, pInst);              H();
    3131                     InsertConfigNode(pInst,         "Config",               &pCfg);
    3132                     switch (enmAudioCodec)
    3133                     {
    3134                         case AudioCodecType_STAC9700:
    3135                             InsertConfigString(pCfg, "Codec",               "STAC9700");
    3136                             break;
    3137                         case AudioCodecType_AD1980:
    3138                             InsertConfigString(pCfg, "Codec",               "AD1980");
    3139                             break;
    3140                         default: AssertFailedBreak();
    3141                     }
    3142                     if (uTimerHz)
    3143                         InsertConfigInteger(pCfg,   "TimerHz",              uTimerHz);
    3144                     if (uBufSizeInMs)
    3145                         InsertConfigInteger(pCfg,   "BufSizeInMs",          uBufSizeInMs);
    3146                     if (uBufSizeOutMs)
    3147                         InsertConfigInteger(pCfg,   "BufSizeOutMs",         uBufSizeOutMs);
    3148                     InsertConfigInteger(pCfg,       "DebugEnabled",         fDebugEnabled);
    3149                     if (strDebugPathOut.isNotEmpty())
    3150                         InsertConfigString(pCfg,    "DebugPathOut",         strDebugPathOut);
    3151                     break;
    3152                 }
    3153                 case AudioControllerType_SB16:
    3154                 {
    3155                     /* Legacy SoundBlaster16. */
    3156                     pszAudioDevice = "sb16";
    3157 
    3158                     InsertConfigNode(pDevices,      pszAudioDevice,         &pDev);
    3159                     InsertConfigNode(pDev,          "0", &pInst);
    3160                     InsertConfigInteger(pInst,      "Trusted",              1); /* boolean */
    3161                     InsertConfigNode(pInst,         "Config",               &pCfg);
    3162                     InsertConfigInteger(pCfg,       "IRQ",                  5);
    3163                     InsertConfigInteger(pCfg,       "DMA",                  1);
    3164                     InsertConfigInteger(pCfg,       "DMA16",                5);
    3165                     InsertConfigInteger(pCfg,       "Port",                 0x220);
    3166                     InsertConfigInteger(pCfg,       "Version",              0x0405);
    3167                     if (uTimerHz)
    3168                         InsertConfigInteger(pCfg,   "TimerHz",              uTimerHz);
    3169                     InsertConfigInteger(pCfg,       "DebugEnabled",         fDebugEnabled);
    3170                     if (strDebugPathOut.isNotEmpty())
    3171                         InsertConfigString(pCfg,    "DebugPathOut",         strDebugPathOut);
    3172                     break;
    3173                 }
    3174                 case AudioControllerType_HDA:
    3175                 {
    3176                     /* Intel HD Audio. */
    3177                     pszAudioDevice = "hda";
    3178 
    3179                     InsertConfigNode(pDevices,      pszAudioDevice,         &pDev);
    3180                     InsertConfigNode(pDev,          "0",                    &pInst);
    3181                     InsertConfigInteger(pInst,      "Trusted",              1); /* boolean */
    3182                     hrc = pBusMgr->assignPCIDevice(pszAudioDevice, pInst);              H();
    3183                     InsertConfigNode(pInst,         "Config",               &pCfg);
    3184                     if (uBufSizeInMs)
    3185                         InsertConfigInteger(pCfg,   "BufSizeInMs",          uBufSizeInMs);
    3186                     if (uBufSizeOutMs)
    3187                         InsertConfigInteger(pCfg,   "BufSizeOutMs",         uBufSizeOutMs);
    3188                     InsertConfigInteger(pCfg,       "DebugEnabled",         fDebugEnabled);
    3189                     if (strDebugPathOut.isNotEmpty())
    3190                         InsertConfigString(pCfg,    "DebugPathOut",         strDebugPathOut);
    3191 
    3192                     /* macOS guests uses a different HDA variant to make 10.14+ (or maybe 10.13?) recognize the device. */
    3193                     if (fOsXGuest)
    3194                         InsertConfigString(pCfg,    "DeviceName",           "Intel Sunrise Point");
    3195                     break;
    3196                 }
    3197                 default:
    3198                     pszAudioDevice = "oops";
    3199                     AssertFailedBreak();
    3200             }
    3201 
    3202             PCFGMNODE pCfgAudioAdapter = NULL;
    3203             InsertConfigNode(pInst, "AudioConfig", &pCfgAudioAdapter);
    3204             SafeArray<BSTR> audioProps;
    3205             hrc = audioAdapter->COMGETTER(PropertiesList)(ComSafeArrayAsOutParam(audioProps));  H();
    3206 
    3207             std::list<Utf8Str> audioPropertyNamesList;
    3208             for (size_t i = 0; i < audioProps.size(); ++i)
    3209             {
    3210                 Bstr bstrValue;
    3211                 audioPropertyNamesList.push_back(Utf8Str(audioProps[i]));
    3212                 hrc = audioAdapter->GetProperty(audioProps[i], bstrValue.asOutParam());
    3213                 Utf8Str strKey(audioProps[i]);
    3214                 InsertConfigString(pCfgAudioAdapter, strKey.c_str(), bstrValue);
    3215             }
    3216 
    3217             /*
    3218              * The audio driver.
    3219              */
    3220             const char *pszAudioDriver = NULL;
    3221 #ifdef VBOX_WITH_AUDIO_VALIDATIONKIT
    3222             if (fValKitEnabled)
    3223             {
    3224                 pszAudioDriver = "ValidationKitAudio";
    3225                 LogRel(("Audio: ValidationKit driver active\n"));
    3226             }
    3227 #endif
    3228             /* If nothing else was selected before, ask the API. */
    3229             if (pszAudioDriver == NULL)
    3230             {
    3231                 AudioDriverType_T enmAudioDriver;
    3232                 hrc = audioAdapter->COMGETTER(AudioDriver)(&enmAudioDriver);                    H();
    3233 
    3234                 /* The "Default" audio driver needs special treatment, as we need to figure out which driver to use
    3235                  * by default on the current platform. */
    3236                 bool const fUseDefaultDrv = enmAudioDriver == AudioDriverType_Default;
    3237 
    3238                 AudioDriverType_T const enmDefaultAudioDriver = settings::MachineConfigFile::getHostDefaultAudioDriver();
    3239 
    3240                 if (fUseDefaultDrv)
    3241                 {
    3242                     enmAudioDriver = enmDefaultAudioDriver;
    3243                     if (enmAudioDriver == AudioDriverType_Null)
    3244                         LogRel(("Audio: Warning: No default driver detected for current platform -- defaulting to Null audio backend\n"));
    3245                 }
    3246 
    3247                 switch (enmAudioDriver)
    3248                 {
    3249                     case AudioDriverType_Default: /* Can't happen, but handle it anyway. */
    3250                         RT_FALL_THROUGH();
    3251                     case AudioDriverType_Null:
    3252                         pszAudioDriver = "NullAudio";
    3253                         break;
    3254 #ifdef RT_OS_WINDOWS
    3255 # ifdef VBOX_WITH_WINMM
    3256                     case AudioDriverType_WinMM:
    3257 #  error "Port WinMM audio backend!" /** @todo Still needed? */
    3258                         break;
    3259 # endif
    3260                     case AudioDriverType_DirectSound:
    3261                         /* Use the Windows Audio Session (WAS) API rather than Direct Sound on Windows
    3262                            versions we've tested it on (currently W7+).  Since Vista, Direct Sound has
    3263                            been emulated on top of WAS according to the docs, so better use WAS directly.
    3264 
    3265                            Set extradata value "VBoxInternal2/Audio/WindowsDrv" "dsound" to no use WasAPI.
    3266 
    3267                            Keep this hack for backwards compatibility (introduced < 7.0).
    3268                         */
    3269                         GetExtraDataBoth(virtualBox, pMachine, "VBoxInternal2/Audio/WindowsDrv", &strTmp); H();
    3270                         if (   enmDefaultAudioDriver == AudioDriverType_WAS
    3271                             && (   strTmp.isEmpty()
    3272                                 || strTmp.equalsIgnoreCase("was")
    3273                                 || strTmp.equalsIgnoreCase("wasapi")) )
    3274                         {
    3275                             /* Nothing to do here, fall through to WAS driver. */
    3276                         }
    3277                         else
    3278                         {
    3279                             pszAudioDriver = "DSoundAudio";
    3280                             break;
    3281                         }
    3282                         RT_FALL_THROUGH();
    3283                     case AudioDriverType_WAS:
    3284                         if (enmDefaultAudioDriver == AudioDriverType_WAS) /* WAS supported? */
    3285                             pszAudioDriver = "HostAudioWas";
    3286                         else if (enmDefaultAudioDriver == AudioDriverType_DirectSound)
    3287                         {
    3288                             LogRel(("Audio: Warning: Windows Audio Session (WAS) not supported, defaulting to DirectSound backend\n"));
    3289                             pszAudioDriver = "DSoundAudio";
    3290                         }
    3291                         break;
    3292 #endif /* RT_OS_WINDOWS */
    3293 #ifdef RT_OS_SOLARIS
    3294                     case AudioDriverType_SolAudio:
    3295                         /* Should not happen, as the Solaris Audio backend is not around anymore.
    3296                          * Remove this sometime later. */
    3297                         LogRel(("Audio: Warning: Solaris Audio is deprecated, please switch to OSS!\n"));
    3298                         LogRel(("Audio: Automatically setting host audio backend to OSS\n"));
    3299 
    3300                         /* Manually set backend to OSS for now. */
    3301                         pszAudioDriver = "OSSAudio";
    3302                         break;
    3303 #endif
    3304 #ifdef VBOX_WITH_AUDIO_OSS
    3305                     case AudioDriverType_OSS:
    3306                         pszAudioDriver = "OSSAudio";
    3307                         break;
    3308 #endif
    3309 #ifdef VBOX_WITH_AUDIO_ALSA
    3310                     case AudioDriverType_ALSA:
    3311                         pszAudioDriver = "ALSAAudio";
    3312                         break;
    3313 #endif
    3314 #ifdef VBOX_WITH_AUDIO_PULSE
    3315                     case AudioDriverType_Pulse:
    3316                         pszAudioDriver = "PulseAudio";
    3317                         break;
    3318 #endif
    3319 #ifdef RT_OS_DARWIN
    3320                     case AudioDriverType_CoreAudio:
    3321                         pszAudioDriver = "CoreAudio";
    3322                         break;
    3323 #endif
    3324                     default:
    3325                         pszAudioDriver = "oops";
    3326                         AssertFailedBreak();
    3327                 }
    3328 
    3329                 if (fUseDefaultDrv)
    3330                     LogRel(("Audio: Detected default audio driver type is '%s'\n", pszAudioDriver));
    3331             }
    3332 
    3333             BOOL fAudioEnabledIn = FALSE;
    3334             hrc = audioAdapter->COMGETTER(EnabledIn)(&fAudioEnabledIn);                            H();
    3335             BOOL fAudioEnabledOut = FALSE;
    3336             hrc = audioAdapter->COMGETTER(EnabledOut)(&fAudioEnabledOut);                          H();
    3337 
    3338             unsigned idxAudioLun = 0;
    3339 
    3340             InsertConfigNodeF(pInst, &pLunL0, "LUN#%u", idxAudioLun);
    3341             i_configAudioDriver(virtualBox, pMachine, pLunL0, pszAudioDriver, !!fAudioEnabledIn, !!fAudioEnabledOut);
    3342             idxAudioLun++;
    3343 
    3344 #ifdef VBOX_WITH_AUDIO_VRDE
    3345             /* Insert dummy audio driver to have the LUN configured. */
    3346             InsertConfigNodeF(pInst, &pLunL0, "LUN#%u", idxAudioLun);
    3347             InsertConfigString(pLunL0, "Driver", "AUDIO");
    3348             {
    3349                 AudioDriverCfg DrvCfgVRDE(pszAudioDevice, 0 /* Instance */, idxAudioLun, "AudioVRDE",
    3350                                           !!fAudioEnabledIn, !!fAudioEnabledOut);
    3351                 vrc = mAudioVRDE->InitializeConfig(&DrvCfgVRDE);
    3352                 AssertRCStmt(vrc, throw ConfigError(__FUNCTION__, vrc, "mAudioVRDE->InitializeConfig failed"));
    3353             }
    3354             idxAudioLun++;
    3355 #endif
    3356 
    3357 #ifdef VBOX_WITH_AUDIO_RECORDING
    3358             /* Insert dummy audio driver to have the LUN configured. */
    3359             InsertConfigNodeF(pInst, &pLunL0, "LUN#%u", idxAudioLun);
    3360             InsertConfigString(pLunL0, "Driver", "AUDIO");
    3361             {
    3362                 AudioDriverCfg DrvCfgVideoRec(pszAudioDevice, 0 /* Instance */, idxAudioLun, "AudioVideoRec",
    3363                                               false /*a_fEnabledIn*/, true /*a_fEnabledOut*/);
    3364                 vrc = mRecording.mAudioRec->InitializeConfig(&DrvCfgVideoRec);
    3365                 AssertRCStmt(vrc, throw ConfigError(__FUNCTION__, vrc, "Recording.mAudioRec->InitializeConfig failed"));
    3366             }
    3367             idxAudioLun++;
    3368 #endif
    3369 
    3370             if (fDebugEnabled)
    3371             {
    3372 #ifdef VBOX_WITH_AUDIO_DEBUG
    3373 # ifdef VBOX_WITH_AUDIO_VALIDATIONKIT
    3374                 /*
    3375                  * When both, ValidationKit and Debug mode (for audio) are enabled,
    3376                  * skip configuring the Debug audio driver, as both modes can
    3377                  * mess with the audio data and would lead to side effects.
    3378                  *
    3379                  * The ValidationKit audio driver has precedence over the Debug audio driver.
    3380                  *
    3381                  * This also can (and will) be used in VBox release builds.
    3382                  */
    3383                 if (fValKitEnabled)
    3384                 {
    3385                     LogRel(("Audio: Warning: ValidationKit running and Debug mode enabled -- disabling Debug driver\n"));
    3386                 }
    3387                 else /* Debug mode active -- run both (nice for catching errors / doing development). */
    3388                 {
    3389                     /*
    3390                      * The ValidationKit backend.
    3391                      */
    3392                     InsertConfigNodeF(pInst, &pLunL0, "LUN#%u", idxAudioLun);
    3393                     i_configAudioDriver(virtualBox, pMachine, pLunL0, "ValidationKitAudio",
    3394                                         !!fAudioEnabledIn, !!fAudioEnabledOut);
    3395                     idxAudioLun++;
    3396 # endif /* VBOX_WITH_AUDIO_VALIDATIONKIT */
    3397                     /*
    3398                      * The Debug audio backend.
    3399                      */
    3400                     InsertConfigNodeF(pInst, &pLunL0, "LUN#%u", idxAudioLun);
    3401                     i_configAudioDriver(virtualBox, pMachine, pLunL0, "DebugAudio",
    3402                                         !!fAudioEnabledIn, !!fAudioEnabledOut);
    3403                     idxAudioLun++;
    3404 # ifdef VBOX_WITH_AUDIO_VALIDATIONKIT
    3405                 }
    3406 # endif /* VBOX_WITH_AUDIO_VALIDATIONKIT */
    3407 #endif /* VBOX_WITH_AUDIO_DEBUG */
    3408 
    3409                 /*
    3410                  * Tweak the logging groups.
    3411                  */
    3412                 Utf8Str strGroups("drv_audio.e.l.l2.l3.f"
    3413                                   " audio_mixer.e.l.l2.l3.f"
    3414                                   " dev_hda_codec.e.l.l2.l3.f"
    3415                                   " dev_hda.e.l.l2.l3.f"
    3416                                   " dev_ac97.e.l.l2.l3.f"
    3417                                   " dev_sb16.e.l.l2.l3.f");
    3418 
    3419                 LogRel(("Audio: Debug level set to %RU32\n", uDebugLevel));
    3420 
    3421                 switch (uDebugLevel)
    3422                 {
    3423                     case 0:
    3424                         strGroups += " drv_host_audio.e.l.l2.l3.f";
    3425                         break;
    3426                     case 1:
    3427                         RT_FALL_THROUGH();
    3428                     case 2:
    3429                         RT_FALL_THROUGH();
    3430                     case 3:
    3431                         strGroups += " drv_host_audio.e.l.l2.l3.f+audio_test.e.l.l2.l3.f";
    3432                         break;
    3433                     case 4:
    3434                         RT_FALL_THROUGH();
    3435                     default:
    3436                         strGroups += " drv_host_audio.e.l.l2.l3.l4.f+audio_test.e.l.l2.l3.l4.f";
    3437                         break;
    3438                 }
    3439 
    3440                 vrc = RTLogGroupSettings(RTLogRelGetDefaultInstance(), strGroups.c_str());
    3441                 if (RT_FAILURE(vrc))
    3442                     LogRel(("Audio: Setting debug logging failed, vrc=%Rrc\n", vrc));
    3443             }
    3444         }
    3445 
    3446 #ifdef VBOX_WITH_SHARED_CLIPBOARD
    3447         /*
    3448          * Shared Clipboard.
    3449          */
    3450         {
    3451             ClipboardMode_T enmClipboardMode = ClipboardMode_Disabled;
    3452             hrc = pMachine->COMGETTER(ClipboardMode)(&enmClipboardMode); H();
    3453 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    3454             BOOL fFileTransfersEnabled;
    3455             hrc = pMachine->COMGETTER(ClipboardFileTransfersEnabled)(&fFileTransfersEnabled); H();
    3456 #endif
    3457 
    3458             /* Load the service */
    3459             vrc = pVMMDev->hgcmLoadService("VBoxSharedClipboard", "VBoxSharedClipboard");
    3460             if (RT_SUCCESS(vrc))
    3461             {
    3462                 LogRel(("Shared Clipboard: Service loaded\n"));
    3463 
    3464                 /* Set initial clipboard mode. */
    3465                 vrc = i_changeClipboardMode(enmClipboardMode);
    3466                 AssertLogRelMsg(RT_SUCCESS(vrc), ("Shared Clipboard: Failed to set initial clipboard mode (%d): vrc=%Rrc\n",
    3467                                                  enmClipboardMode, vrc));
    3468 
    3469                 /* Setup the service. */
    3470                 VBOXHGCMSVCPARM parm;
    3471                 HGCMSvcSetU32(&parm, !i_useHostClipboard());
    3472                 vrc = pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHCL_HOST_FN_SET_HEADLESS, 1, &parm);
    3473                 AssertLogRelMsg(RT_SUCCESS(vrc), ("Shared Clipboard: Failed to set initial headless mode (%RTbool): vrc=%Rrc\n",
    3474                                                  !i_useHostClipboard(), vrc));
    3475 
    3476 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    3477                 vrc = i_changeClipboardFileTransferMode(RT_BOOL(fFileTransfersEnabled));
    3478                 AssertLogRelMsg(RT_SUCCESS(vrc), ("Shared Clipboard: Failed to set initial file transfers mode (%u): vrc=%Rrc\n",
    3479                                                  fFileTransfersEnabled, vrc));
    3480 
    3481                 /** @todo Register area callbacks? (See also deregistration todo in Console::i_powerDown.) */
    3482 # endif
    3483             }
    3484             else
    3485                 LogRel(("Shared Clipboard: Not available, vrc=%Rrc\n", vrc));
    3486             vrc = VINF_SUCCESS;  /* None of the potential failures above are fatal. */
    3487         }
    3488 #endif /* VBOX_WITH_SHARED_CLIPBOARD */
    3489 
    3490         /*
    3491          * HGCM HostChannel.
    3492          */
    3493         {
    3494             Bstr value;
    3495             hrc = pMachine->GetExtraData(Bstr("HGCM/HostChannel").raw(),
    3496                                          value.asOutParam());
    3497 
    3498             if (   hrc   == S_OK
    3499                 && value == "1")
    3500             {
    3501                 vrc = pVMMDev->hgcmLoadService("VBoxHostChannel", "VBoxHostChannel");
    3502                 if (RT_FAILURE(vrc))
    3503                 {
    3504                     LogRel(("VBoxHostChannel is not available, vrc=%Rrc\n", vrc));
    3505                     /* That is not a fatal failure. */
    3506                     vrc = VINF_SUCCESS;
    3507                 }
    3508             }
    3509         }
    3510 
    3511 #ifdef VBOX_WITH_DRAG_AND_DROP
    3512         /*
    3513          * Drag and Drop.
    3514          */
    3515         {
    3516             DnDMode_T enmMode = DnDMode_Disabled;
    3517             hrc = pMachine->COMGETTER(DnDMode)(&enmMode);                                   H();
    3518 
    3519             /* Load the service */
    3520             vrc = pVMMDev->hgcmLoadService("VBoxDragAndDropSvc", "VBoxDragAndDropSvc");
    3521             if (RT_FAILURE(vrc))
    3522             {
    3523                 LogRel(("Drag and drop service is not available, vrc=%Rrc\n", vrc));
    3524                 /* That is not a fatal failure. */
    3525                 vrc = VINF_SUCCESS;
    3526             }
    3527             else
    3528             {
    3529                 vrc = HGCMHostRegisterServiceExtension(&m_hHgcmSvcExtDragAndDrop, "VBoxDragAndDropSvc",
    3530                                                        &GuestDnD::notifyDnDDispatcher,
    3531                                                        GuestDnDInst());
    3532                 if (RT_FAILURE(vrc))
    3533                     Log(("Cannot register VBoxDragAndDropSvc extension, vrc=%Rrc\n", vrc));
    3534                 else
    3535                 {
    3536                     LogRel(("Drag and drop service loaded\n"));
    3537                     vrc = i_changeDnDMode(enmMode);
    3538                 }
    3539             }
    3540         }
    3541 #endif /* VBOX_WITH_DRAG_AND_DROP */
    3542 
    3543 #if defined(VBOX_WITH_TPM)
    3544         /*
    3545          * Configure the Trusted Platform Module.
    3546          */
    3547         ComObjPtr<ITrustedPlatformModule> ptrTpm;
    3548         TpmType_T enmTpmType = TpmType_None;
    3549 
    3550         hrc = pMachine->COMGETTER(TrustedPlatformModule)(ptrTpm.asOutParam());              H();
    3551         hrc = ptrTpm->COMGETTER(Type)(&enmTpmType);                                         H();
    3552         if (enmTpmType != TpmType_None)
    3553         {
    3554             InsertConfigNode(pDevices, "tpm", &pDev);
    3555             InsertConfigNode(pDev,     "0", &pInst);
    3556             InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
    3557             InsertConfigNode(pInst,    "Config", &pCfg);
    3558             InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    3559 
    3560             switch (enmTpmType)
    3561             {
    3562                 case TpmType_v1_2:
    3563                 case TpmType_v2_0:
    3564                     InsertConfigString(pLunL0, "Driver",               "TpmEmuTpms");
    3565                     InsertConfigNode(pLunL0,   "Config", &pCfg);
    3566                     InsertConfigInteger(pCfg, "TpmVersion", enmTpmType == TpmType_v1_2 ? 1 : 2);
    3567                     InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
    3568                     InsertConfigString(pLunL1, "Driver", "NvramStore");
    3569                     break;
    3570                 case TpmType_Host:
    3571 #if defined(RT_OS_LINUX) || defined(RT_OS_WINDOWS)
    3572                     InsertConfigString(pLunL0, "Driver",               "TpmHost");
    3573                     InsertConfigNode(pLunL0,   "Config", &pCfg);
    3574 #endif
    3575                     break;
    3576                 case TpmType_Swtpm:
    3577                     hrc = ptrTpm->COMGETTER(Location)(bstr.asOutParam());                   H();
    3578                     InsertConfigString(pLunL0, "Driver",               "TpmEmu");
    3579                     InsertConfigNode(pLunL0,   "Config", &pCfg);
    3580                     InsertConfigString(pCfg,   "Location", bstr);
    3581                     break;
    3582                 default:
    3583                     AssertFailedBreak();
    3584             }
    3585         }
    3586 #endif
    3587 
    3588         /*
    3589          * ACPI
    3590          */
    3591         BOOL fACPI;
    3592         hrc = biosSettings->COMGETTER(ACPIEnabled)(&fACPI);                                 H();
    3593         if (fACPI)
    3594         {
    3595             /* Always show the CPU leafs when we have multiple VCPUs or when the IO-APIC is enabled.
    3596              * The Windows SMP kernel needs a CPU leaf or else its idle loop will burn cpu cycles; the
    3597              * intelppm driver refuses to register an idle state handler.
    3598              * Always show CPU leafs for OS X guests. */
    3599             BOOL fShowCpu = fOsXGuest;
    3600             if (cCpus > 1 || fIOAPIC)
    3601                 fShowCpu = true;
    3602 
    3603             BOOL fCpuHotPlug;
    3604             hrc = pMachine->COMGETTER(CPUHotPlugEnabled)(&fCpuHotPlug);                     H();
    3605 
    3606             InsertConfigNode(pDevices, "acpi", &pDev);
    3607             InsertConfigNode(pDev,     "0", &pInst);
    3608             InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
    3609             InsertConfigNode(pInst,    "Config", &pCfg);
    3610             hrc = pBusMgr->assignPCIDevice("acpi", pInst);                                  H();
    3611 
    3612             InsertConfigInteger(pCfg,  "NumCPUs",          cCpus);
    3613 
    3614             InsertConfigInteger(pCfg,  "IOAPIC", fIOAPIC);
    3615             InsertConfigInteger(pCfg,  "FdcEnabled", fFdcEnabled);
    3616             InsertConfigInteger(pCfg,  "HpetEnabled", fHPETEnabled);
    3617             InsertConfigInteger(pCfg,  "SmcEnabled", fSmcEnabled);
    3618             InsertConfigInteger(pCfg,  "ShowRtc",    fShowRtc);
    3619             if (fOsXGuest && !llBootNics.empty())
    3620             {
    3621                 BootNic aNic = llBootNics.front();
    3622                 uint32_t u32NicPCIAddr = (aNic.mPCIAddress.miDevice << 16) | aNic.mPCIAddress.miFn;
    3623                 InsertConfigInteger(pCfg, "NicPciAddress",    u32NicPCIAddr);
    3624             }
    3625             if (fOsXGuest && fAudioEnabled)
    3626             {
    3627                 PCIBusAddress Address;
    3628                 if (pBusMgr->findPCIAddress("hda", 0, Address))
    3629                 {
    3630                     uint32_t u32AudioPCIAddr = (Address.miDevice << 16) | Address.miFn;
    3631                     InsertConfigInteger(pCfg, "AudioPciAddress",    u32AudioPCIAddr);
    3632                 }
    3633             }
    3634             if (fOsXGuest)
    3635             {
    3636                 PCIBusAddress Address;
    3637                 if (pBusMgr->findPCIAddress("nvme", 0, Address))
    3638                 {
    3639                     uint32_t u32NvmePCIAddr = (Address.miDevice << 16) | Address.miFn;
    3640                     InsertConfigInteger(pCfg, "NvmePciAddress",    u32NvmePCIAddr);
    3641                 }
    3642             }
    3643             if (enmIommuType == IommuType_AMD)
    3644             {
    3645                 PCIBusAddress Address;
    3646                 if (pBusMgr->findPCIAddress("iommu-amd", 0, Address))
    3647                 {
    3648                     uint32_t u32IommuAddress = (Address.miDevice << 16) | Address.miFn;
    3649                     InsertConfigInteger(pCfg, "IommuAmdEnabled", true);
    3650                     InsertConfigInteger(pCfg, "IommuPciAddress", u32IommuAddress);
    3651                     if (pBusMgr->findPCIAddress("sb-ioapic", 0, Address))
    3652                     {
    3653                         uint32_t const u32SbIoapicAddress = (Address.miDevice << 16) | Address.miFn;
    3654                         InsertConfigInteger(pCfg, "SbIoApicPciAddress", u32SbIoapicAddress);
    3655                     }
    3656                     else
    3657                         return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    3658                                                      N_("AMD IOMMU is enabled, but the I/O APIC is not assigned a PCI address!"));
    3659                 }
    3660             }
    3661             else if (enmIommuType == IommuType_Intel)
    3662             {
    3663                 PCIBusAddress Address;
    3664                 if (pBusMgr->findPCIAddress("iommu-intel", 0, Address))
    3665                 {
    3666                     uint32_t u32IommuAddress = (Address.miDevice << 16) | Address.miFn;
    3667                     InsertConfigInteger(pCfg, "IommuIntelEnabled", true);
    3668                     InsertConfigInteger(pCfg, "IommuPciAddress", u32IommuAddress);
    3669                     if (pBusMgr->findPCIAddress("sb-ioapic", 0, Address))
    3670                     {
    3671                         uint32_t const u32SbIoapicAddress = (Address.miDevice << 16) | Address.miFn;
    3672                         InsertConfigInteger(pCfg, "SbIoApicPciAddress", u32SbIoapicAddress);
    3673                     }
    3674                     else
    3675                         return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    3676                                                      N_("Intel IOMMU is enabled, but the I/O APIC is not assigned a PCI address!"));
    3677                 }
    3678             }
    3679 
    3680             InsertConfigInteger(pCfg,  "IocPciAddress", uIocPCIAddress);
    3681             if (chipsetType == ChipsetType_ICH9)
    3682             {
    3683                 InsertConfigInteger(pCfg,  "McfgBase",   uMcfgBase);
    3684                 InsertConfigInteger(pCfg,  "McfgLength", cbMcfgLength);
    3685                 /* 64-bit prefetch window root resource: Only for ICH9 and if PAE or Long Mode is enabled (@bugref{5454}). */
    3686                 if (fIsGuest64Bit || fEnablePAE)
    3687                     InsertConfigInteger(pCfg,  "PciPref64Enabled", 1);
    3688             }
    3689             InsertConfigInteger(pCfg,  "HostBusPciAddress", uHbcPCIAddress);
    3690             InsertConfigInteger(pCfg,  "ShowCpu", fShowCpu);
    3691             InsertConfigInteger(pCfg,  "CpuHotPlug", fCpuHotPlug);
    3692 
    3693             InsertConfigInteger(pCfg,  "Serial0IoPortBase", auSerialIoPortBase[0]);
    3694             InsertConfigInteger(pCfg,  "Serial0Irq", auSerialIrq[0]);
    3695 
    3696             InsertConfigInteger(pCfg,  "Serial1IoPortBase", auSerialIoPortBase[1]);
    3697             InsertConfigInteger(pCfg,  "Serial1Irq", auSerialIrq[1]);
    3698 
    3699             if (auSerialIoPortBase[2])
    3700             {
    3701                 InsertConfigInteger(pCfg,  "Serial2IoPortBase", auSerialIoPortBase[2]);
    3702                 InsertConfigInteger(pCfg,  "Serial2Irq", auSerialIrq[2]);
    3703             }
    3704 
    3705             if (auSerialIoPortBase[3])
    3706             {
    3707                 InsertConfigInteger(pCfg,  "Serial3IoPortBase", auSerialIoPortBase[3]);
    3708                 InsertConfigInteger(pCfg,  "Serial3Irq", auSerialIrq[3]);
    3709             }
    3710 
    3711             InsertConfigInteger(pCfg,  "Parallel0IoPortBase", auParallelIoPortBase[0]);
    3712             InsertConfigInteger(pCfg,  "Parallel0Irq", auParallelIrq[0]);
    3713 
    3714             InsertConfigInteger(pCfg,  "Parallel1IoPortBase", auParallelIoPortBase[1]);
    3715             InsertConfigInteger(pCfg,  "Parallel1Irq", auParallelIrq[1]);
    3716 
    3717 #if defined(VBOX_WITH_TPM)
    3718             switch (enmTpmType)
    3719             {
    3720                 case TpmType_v1_2:
    3721                     InsertConfigString(pCfg, "TpmMode", "tis1.2");
    3722                     break;
    3723                 case TpmType_v2_0:
    3724                     InsertConfigString(pCfg, "TpmMode", "fifo2.0");
    3725                     break;
    3726                 /** @todo Host and swtpm. */
    3727                 default:
    3728                     break;
    3729             }
    3730 #endif
    3731 
    3732             InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    3733             InsertConfigString(pLunL0, "Driver",               "ACPIHost");
    3734             InsertConfigNode(pLunL0,   "Config", &pCfg);
    3735 
    3736             /* Attach the dummy CPU drivers */
    3737             for (ULONG iCpuCurr = 1; iCpuCurr < cCpus; iCpuCurr++)
    3738             {
    3739                 BOOL fCpuAttached = true;
    3740 
    3741                 if (fCpuHotPlug)
    3742                 {
    3743                     hrc = pMachine->GetCPUStatus(iCpuCurr, &fCpuAttached);                  H();
    3744                 }
    3745 
    3746                 if (fCpuAttached)
    3747                 {
    3748                     InsertConfigNode(pInst, Utf8StrFmt("LUN#%u", iCpuCurr).c_str(), &pLunL0);
    3749                     InsertConfigString(pLunL0, "Driver",           "ACPICpu");
    3750                     InsertConfigNode(pLunL0,   "Config", &pCfg);
    3751                 }
    3752             }
    3753         }
    3754 
    3755         /*
    3756          * Configure DBGF (Debug(ger) Facility) and DBGC (Debugger Console).
    3757          */
    3758         {
    3759             PCFGMNODE pDbgf;
    3760             InsertConfigNode(pRoot, "DBGF", &pDbgf);
    3761 
    3762             /* Paths to search for debug info and such things. */
    3763             hrc = pMachine->COMGETTER(SettingsFilePath)(bstr.asOutParam());                 H();
    3764             Utf8Str strSettingsPath(bstr);
    3765             bstr.setNull();
    3766             strSettingsPath.stripFilename();
    3767             strSettingsPath.append("/");
    3768 
    3769             char szHomeDir[RTPATH_MAX + 1];
    3770             int vrc2 = RTPathUserHome(szHomeDir, sizeof(szHomeDir) - 1);
    3771             if (RT_FAILURE(vrc2))
    3772                 szHomeDir[0] = '\0';
    3773             RTPathEnsureTrailingSeparator(szHomeDir, sizeof(szHomeDir));
    3774 
    3775 
    3776             Utf8Str strPath;
    3777             strPath.append(strSettingsPath).append("debug/;");
    3778             strPath.append(strSettingsPath).append(";");
    3779             strPath.append("cache*").append(strSettingsPath).append("dbgcache/;"); /* handy for symlinking to actual cache */
    3780             strPath.append(szHomeDir);
    3781 
    3782             InsertConfigString(pDbgf, "Path", strPath.c_str());
    3783 
    3784             /* Tracing configuration. */
    3785             BOOL fTracingEnabled;
    3786             hrc = pMachine->COMGETTER(TracingEnabled)(&fTracingEnabled);                    H();
    3787             if (fTracingEnabled)
    3788                 InsertConfigInteger(pDbgf, "TracingEnabled", 1);
    3789 
    3790             hrc = pMachine->COMGETTER(TracingConfig)(bstr.asOutParam());                    H();
    3791             if (fTracingEnabled)
    3792                 InsertConfigString(pDbgf, "TracingConfig", bstr);
    3793 
    3794             BOOL fAllowTracingToAccessVM;
    3795             hrc = pMachine->COMGETTER(AllowTracingToAccessVM)(&fAllowTracingToAccessVM);    H();
    3796             if (fAllowTracingToAccessVM)
    3797                 InsertConfigInteger(pPDM, "AllowTracingToAccessVM", 1);
    3798 
    3799             /* Debugger console config. */
    3800             PCFGMNODE pDbgc;
    3801             InsertConfigNode(pRoot, "DBGC", &pDbgc);
    3802 
    3803             hrc = virtualBox->COMGETTER(HomeFolder)(bstr.asOutParam());                     H();
    3804             Utf8Str strVBoxHome = bstr;
    3805             bstr.setNull();
    3806             if (strVBoxHome.isNotEmpty())
    3807                 strVBoxHome.append("/");
    3808             else
    3809             {
    3810                 strVBoxHome = szHomeDir;
    3811                 strVBoxHome.append("/.vbox");
    3812             }
    3813 
    3814             Utf8Str strFile(strVBoxHome);
    3815             strFile.append("dbgc-history");
    3816             InsertConfigString(pDbgc, "HistoryFile", strFile);
    3817 
    3818             strFile = strSettingsPath;
    3819             strFile.append("dbgc-init");
    3820             InsertConfigString(pDbgc, "LocalInitScript", strFile);
    3821 
    3822             strFile = strVBoxHome;
    3823             strFile.append("dbgc-init");
    3824             InsertConfigString(pDbgc, "GlobalInitScript", strFile);
    3825 
    3826             /*
    3827              * Configure guest debug settings.
    3828              */
    3829             ComObjPtr<IGuestDebugControl> ptrGstDbgCtrl;
    3830             GuestDebugProvider_T enmGstDbgProvider = GuestDebugProvider_None;
    3831 
    3832             hrc = pMachine->COMGETTER(GuestDebugControl)(ptrGstDbgCtrl.asOutParam());           H();
    3833             hrc = ptrGstDbgCtrl->COMGETTER(DebugProvider)(&enmGstDbgProvider);                  H();
    3834             if (enmGstDbgProvider != GuestDebugProvider_None)
    3835             {
    3836                 GuestDebugIoProvider_T enmGstDbgIoProvider = GuestDebugIoProvider_None;
    3837                 hrc = ptrGstDbgCtrl->COMGETTER(DebugIoProvider)(&enmGstDbgIoProvider);          H();
    3838                 hrc = ptrGstDbgCtrl->COMGETTER(DebugAddress)(bstr.asOutParam());                H();
    3839                 Utf8Str strAddress = bstr;
    3840                 bstr.setNull();
    3841 
    3842                 ULONG ulPort = 0;
    3843                 hrc = ptrGstDbgCtrl->COMGETTER(DebugPort)(&ulPort);                             H();
    3844 
    3845                 PCFGMNODE pDbgSettings;
    3846                 InsertConfigNode(pDbgc, "Dbg", &pDbgSettings);
    3847                 InsertConfigString(pDbgSettings, "Address", strAddress);
    3848                 InsertConfigInteger(pDbgSettings, "Port", ulPort);
    3849 
    3850                 switch (enmGstDbgProvider)
    3851                 {
    3852                     case GuestDebugProvider_Native:
    3853                         InsertConfigString(pDbgSettings, "StubType", "Native");
    3854                         break;
    3855                     case GuestDebugProvider_GDB:
    3856                         InsertConfigString(pDbgSettings, "StubType", "Gdb");
    3857                         break;
    3858                     case GuestDebugProvider_KD:
    3859                         InsertConfigString(pDbgSettings, "StubType", "Kd");
    3860                         break;
    3861                     default:
    3862                         AssertFailed();
    3863                         break;
    3864                 }
    3865 
    3866                 switch (enmGstDbgIoProvider)
    3867                 {
    3868                     case GuestDebugIoProvider_TCP:
    3869                         InsertConfigString(pDbgSettings, "Provider", "tcp");
    3870                         break;
    3871                     case GuestDebugIoProvider_UDP:
    3872                         InsertConfigString(pDbgSettings, "Provider", "udp");
    3873                         break;
    3874                     case GuestDebugIoProvider_IPC:
    3875                         InsertConfigString(pDbgSettings, "Provider", "ipc");
    3876                         break;
    3877                     default:
    3878                         AssertFailed();
    3879                         break;
    3880                 }
    3881             }
    3882         }
    3883     }
    3884     catch (ConfigError &x)
    3885     {
    3886         // InsertConfig threw something:
    3887         pVMM->pfnVMR3SetError(pUVM, x.m_vrc, RT_SRC_POS, "Caught ConfigError: %Rrc - %s", x.m_vrc, x.what());
    3888         return x.m_vrc;
    3889     }
    3890     catch (HRESULT hrcXcpt)
    3891     {
    3892         AssertLogRelMsgFailedReturn(("hrc=%Rhrc\n", hrcXcpt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
    3893     }
    3894 
    3895 #ifdef VBOX_WITH_EXTPACK
    3896     /*
    3897      * Call the extension pack hooks if everything went well thus far.
    3898      */
    3899     if (RT_SUCCESS(vrc))
    3900     {
    3901         pAlock->release();
    3902         vrc = mptrExtPackManager->i_callAllVmConfigureVmmHooks(this, pVM, pVMM);
    3903         pAlock->acquire();
    3904     }
    3905 #endif
    3906 
    3907     /*
    3908      * Apply the CFGM overlay.
    3909      */
    3910     if (RT_SUCCESS(vrc))
    3911         vrc = i_configCfgmOverlay(pRoot, virtualBox, pMachine);
    3912 
    3913     /*
    3914      * Dump all extradata API settings tweaks, both global and per VM.
    3915      */
    3916     if (RT_SUCCESS(vrc))
    3917         vrc = i_configDumpAPISettingsTweaks(virtualBox, pMachine);
    3918 
    3919 #undef H
    3920 
    3921     pAlock->release(); /* Avoid triggering the lock order inversion check. */
    3922 
    3923     /*
    3924      * Register VM state change handler.
    3925      */
    3926     int vrc2 = pVMM->pfnVMR3AtStateRegister(pUVM, Console::i_vmstateChangeCallback, this);
    3927     AssertRC(vrc2);
    3928     if (RT_SUCCESS(vrc))
    3929         vrc = vrc2;
    3930 
    3931     /*
    3932      * Register VM runtime error handler.
    3933      */
    3934     vrc2 = pVMM->pfnVMR3AtRuntimeErrorRegister(pUVM, Console::i_atVMRuntimeErrorCallback, this);
    3935     AssertRC(vrc2);
    3936     if (RT_SUCCESS(vrc))
    3937         vrc = vrc2;
    3938 
    3939     pAlock->acquire();
    3940 
    3941     LogFlowFunc(("vrc = %Rrc\n", vrc));
    3942     LogFlowFuncLeave();
    3943 
    3944     return vrc;
    3945 }
    3946494
    3947495/**
     
    4303851        }
    4304852    }
    4305 
    4306     return VINF_SUCCESS;
    4307 }
    4308 
    4309 int Console::i_configGraphicsController(PCFGMNODE pDevices,
    4310                                         const GraphicsControllerType_T enmGraphicsController,
    4311                                         BusAssignmentManager *pBusMgr,
    4312                                         const ComPtr<IMachine> &ptrMachine,
    4313                                         const ComPtr<IGraphicsAdapter> &ptrGraphicsAdapter,
    4314                                         const ComPtr<IBIOSSettings> &ptrBiosSettings,
    4315                                         bool fHMEnabled)
    4316 {
    4317     // InsertConfig* throws
    4318     try
    4319     {
    4320         PCFGMNODE pDev, pInst, pCfg, pLunL0;
    4321         HRESULT hrc;
    4322         Bstr    bstr;
    4323         const char *pcszDevice = "vga";
    4324 
    4325 #define H()         AssertLogRelMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
    4326         InsertConfigNode(pDevices, pcszDevice, &pDev);
    4327         InsertConfigNode(pDev,     "0", &pInst);
    4328         InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
    4329 
    4330         hrc = pBusMgr->assignPCIDevice(pcszDevice, pInst);                                  H();
    4331         InsertConfigNode(pInst,    "Config", &pCfg);
    4332         ULONG cVRamMBs;
    4333         hrc = ptrGraphicsAdapter->COMGETTER(VRAMSize)(&cVRamMBs);                           H();
    4334         InsertConfigInteger(pCfg,  "VRamSize",             cVRamMBs * _1M);
    4335         ULONG cMonitorCount;
    4336         hrc = ptrGraphicsAdapter->COMGETTER(MonitorCount)(&cMonitorCount);                  H();
    4337         InsertConfigInteger(pCfg,  "MonitorCount",         cMonitorCount);
    4338 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
    4339         InsertConfigInteger(pCfg,  "R0Enabled",            fHMEnabled);
    4340 #else
    4341         NOREF(fHMEnabled);
    4342 #endif
    4343         BOOL f3DEnabled;
    4344         hrc = ptrGraphicsAdapter->COMGETTER(Accelerate3DEnabled)(&f3DEnabled);              H();
    4345         InsertConfigInteger(pCfg,  "3DEnabled",            f3DEnabled);
    4346 
    4347         i_attachStatusDriver(pInst, DeviceType_Graphics3D);
    4348 
    4349 #ifdef VBOX_WITH_VMSVGA
    4350         if (   enmGraphicsController == GraphicsControllerType_VMSVGA
    4351             || enmGraphicsController == GraphicsControllerType_VBoxSVGA)
    4352         {
    4353             InsertConfigInteger(pCfg, "VMSVGAEnabled", true);
    4354             if (enmGraphicsController == GraphicsControllerType_VMSVGA)
    4355             {
    4356                 InsertConfigInteger(pCfg, "VMSVGAPciBarLayout", true);
    4357                 InsertConfigInteger(pCfg, "VMSVGAPciId", true);
    4358             }
    4359 # ifdef VBOX_WITH_VMSVGA3D
    4360             InsertConfigInteger(pCfg, "VMSVGA3dEnabled", f3DEnabled);
    4361 # else
    4362             LogRel(("VMSVGA3d not available in this build!\n"));
    4363 # endif /* VBOX_WITH_VMSVGA3D */
    4364         }
    4365 #else
    4366         RT_NOREF(enmGraphicsController);
    4367 #endif /* VBOX_WITH_VMSVGA */
    4368 
    4369         /* Custom VESA mode list */
    4370         unsigned cModes = 0;
    4371         for (unsigned iMode = 1; iMode <= 16; ++iMode)
    4372         {
    4373             char szExtraDataKey[sizeof("CustomVideoModeXX")];
    4374             RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%u", iMode);
    4375             hrc = ptrMachine->GetExtraData(Bstr(szExtraDataKey).raw(), bstr.asOutParam());  H();
    4376             if (bstr.isEmpty())
    4377                 break;
    4378             InsertConfigString(pCfg, szExtraDataKey, bstr);
    4379             ++cModes;
    4380         }
    4381         InsertConfigInteger(pCfg, "CustomVideoModes", cModes);
    4382 
    4383         /* VESA height reduction */
    4384         ULONG ulHeightReduction;
    4385         IFramebuffer *pFramebuffer = NULL;
    4386         hrc = i_getDisplay()->QueryFramebuffer(0, &pFramebuffer);
    4387         if (SUCCEEDED(hrc) && pFramebuffer)
    4388         {
    4389             hrc = pFramebuffer->COMGETTER(HeightReduction)(&ulHeightReduction);             H();
    4390             pFramebuffer->Release();
    4391             pFramebuffer = NULL;
    4392         }
    4393         else
    4394         {
    4395             /* If framebuffer is not available, there is no height reduction. */
    4396             ulHeightReduction = 0;
    4397         }
    4398         InsertConfigInteger(pCfg,  "HeightReduction", ulHeightReduction);
    4399 
    4400         /*
    4401          * BIOS logo
    4402          */
    4403         BOOL fFadeIn;
    4404         hrc = ptrBiosSettings->COMGETTER(LogoFadeIn)(&fFadeIn);                             H();
    4405         InsertConfigInteger(pCfg,  "FadeIn",  fFadeIn ? 1 : 0);
    4406         BOOL fFadeOut;
    4407         hrc = ptrBiosSettings->COMGETTER(LogoFadeOut)(&fFadeOut);                           H();
    4408         InsertConfigInteger(pCfg,  "FadeOut", fFadeOut ? 1: 0);
    4409         ULONG logoDisplayTime;
    4410         hrc = ptrBiosSettings->COMGETTER(LogoDisplayTime)(&logoDisplayTime);                H();
    4411         InsertConfigInteger(pCfg,  "LogoTime", logoDisplayTime);
    4412         Bstr bstrLogoImagePath;
    4413         hrc = ptrBiosSettings->COMGETTER(LogoImagePath)(bstrLogoImagePath.asOutParam());    H();
    4414         InsertConfigString(pCfg,   "LogoFile", bstrLogoImagePath);
    4415 
    4416         /*
    4417          * Boot menu
    4418          */
    4419         BIOSBootMenuMode_T eBootMenuMode;
    4420         int iShowBootMenu;
    4421         hrc = ptrBiosSettings->COMGETTER(BootMenuMode)(&eBootMenuMode);                     H();
    4422         switch (eBootMenuMode)
    4423         {
    4424             case BIOSBootMenuMode_Disabled: iShowBootMenu = 0;  break;
    4425             case BIOSBootMenuMode_MenuOnly: iShowBootMenu = 1;  break;
    4426             default:                        iShowBootMenu = 2;  break;
    4427         }
    4428         InsertConfigInteger(pCfg, "ShowBootMenu", iShowBootMenu);
    4429 
    4430         /* Attach the display. */
    4431         InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    4432         InsertConfigString(pLunL0, "Driver",               "MainDisplay");
    4433         InsertConfigNode(pLunL0,   "Config", &pCfg);
    4434     }
    4435     catch (ConfigError &x)
    4436     {
    4437         // InsertConfig threw something:
    4438         return x.m_vrc;
    4439     }
    4440 
    4441 #undef H
    4442853
    4443854    return VINF_SUCCESS;
  • trunk/src/VBox/Main/src-client/ConsoleImplConfigX86.cpp

    r99908 r99909  
    7171#include <iprt/string.h>
    7272#include <iprt/system.h>
    73 #include <iprt/cpp/exception.h>
    7473#if 0 /* enable to play with lots of memory. */
    7574# include <iprt/env.h>
     
    150149*   Internal Functions                                                                                                           *
    151150*********************************************************************************************************************************/
    152 static Utf8Str *GetExtraDataBoth(IVirtualBox *pVirtualBox, IMachine *pMachine, const char *pszName, Utf8Str *pStrValue);
    153 
    154151
    155152/* Darwin compile kludge */
     
    285282#endif
    286283
    287 class ConfigError : public RTCError
    288 {
    289 public:
    290 
    291     ConfigError(const char *pcszFunction,
    292                 int vrc,
    293                 const char *pcszName)
    294         : RTCError(Utf8StrFmt(Console::tr("%s failed: vrc=%Rrc, pcszName=%s"), pcszFunction, vrc, pcszName)),
    295           m_vrc(vrc)
    296     {
    297         AssertMsgFailed(("%s\n", what())); // in strict mode, hit a breakpoint here
    298     }
    299 
    300     int m_vrc;
    301 };
    302 
    303 
    304 /**
    305  * Helper that calls CFGMR3InsertString and throws an RTCError if that
    306  * fails (C-string variant).
    307  * @param   pNode           See CFGMR3InsertString.
    308  * @param   pcszName        See CFGMR3InsertString.
    309  * @param   pcszValue       The string value.
    310  */
    311 void Console::InsertConfigString(PCFGMNODE pNode, const char *pcszName, const char *pcszValue)
    312 {
    313     int vrc = mpVMM->pfnCFGMR3InsertString(pNode, pcszName, pcszValue);
    314     if (RT_FAILURE(vrc))
    315         throw ConfigError("CFGMR3InsertString", vrc, pcszName);
    316 }
    317 
    318 /**
    319  * Helper that calls CFGMR3InsertString and throws an RTCError if that
    320  * fails (Utf8Str variant).
    321  * @param   pNode           See CFGMR3InsertStringN.
    322  * @param   pcszName        See CFGMR3InsertStringN.
    323  * @param   rStrValue       The string value.
    324  */
    325 void Console::InsertConfigString(PCFGMNODE pNode, const char *pcszName, const Utf8Str &rStrValue)
    326 {
    327     int vrc = mpVMM->pfnCFGMR3InsertStringN(pNode, pcszName, rStrValue.c_str(), rStrValue.length());
    328     if (RT_FAILURE(vrc))
    329         throw ConfigError("CFGMR3InsertStringLengthKnown", vrc, pcszName);
    330 }
    331 
    332 /**
    333  * Helper that calls CFGMR3InsertString and throws an RTCError if that
    334  * fails (Bstr variant).
    335  *
    336  * @param   pNode           See CFGMR3InsertStringN.
    337  * @param   pcszName        See CFGMR3InsertStringN.
    338  * @param   rBstrValue      The string value.
    339  */
    340 void Console::InsertConfigString(PCFGMNODE pNode, const char *pcszName, const Bstr &rBstrValue)
    341 {
    342     InsertConfigString(pNode, pcszName, Utf8Str(rBstrValue));
    343 }
    344 
    345 /**
    346  * Helper that calls CFGMR3InsertStringFV and throws an RTCError if that fails.
    347  * @param   pNode           See CFGMR3InsertStringF.
    348  * @param   pcszName        See CFGMR3InsertStringF.
    349  * @param   pszFormat       See CFGMR3InsertStringF.
    350  * @param   ...             See CFGMR3InsertStringF.
    351  */
    352 void Console::InsertConfigStringF(PCFGMNODE pNode, const char *pcszName, const char *pszFormat, ...)
    353 {
    354     va_list va;
    355     va_start(va, pszFormat);
    356     int vrc = mpVMM->pfnCFGMR3InsertStringFV(pNode, pcszName, pszFormat, va);
    357     va_end(va);
    358     if (RT_FAILURE(vrc))
    359         throw ConfigError("CFGMR3InsertStringFV", vrc, pcszName);
    360 }
    361 
    362 
    363 /**
    364  * Helper that calls CFGMR3InsertPassword and throws an RTCError if that
    365  * fails (Utf8Str variant).
    366  * @param   pNode           See CFGMR3InsertPasswordN.
    367  * @param   pcszName        See CFGMR3InsertPasswordN.
    368  * @param   rStrValue       The string value.
    369  */
    370 void Console::InsertConfigPassword(PCFGMNODE pNode, const char *pcszName, const Utf8Str &rStrValue)
    371 {
    372     int vrc = mpVMM->pfnCFGMR3InsertPasswordN(pNode, pcszName, rStrValue.c_str(), rStrValue.length());
    373     if (RT_FAILURE(vrc))
    374         throw ConfigError("CFGMR3InsertPasswordLengthKnown", vrc, pcszName);
    375 }
    376 
    377 /**
    378  * Helper that calls CFGMR3InsertBytes and throws an RTCError if that fails.
    379  *
    380  * @param   pNode           See CFGMR3InsertBytes.
    381  * @param   pcszName        See CFGMR3InsertBytes.
    382  * @param   pvBytes         See CFGMR3InsertBytes.
    383  * @param   cbBytes         See CFGMR3InsertBytes.
    384  */
    385 void Console::InsertConfigBytes(PCFGMNODE pNode, const char *pcszName, const void *pvBytes, size_t cbBytes)
    386 {
    387     int vrc = mpVMM->pfnCFGMR3InsertBytes(pNode, pcszName, pvBytes, cbBytes);
    388     if (RT_FAILURE(vrc))
    389         throw ConfigError("CFGMR3InsertBytes", vrc, pcszName);
    390 }
    391 
    392 /**
    393  * Helper that calls CFGMR3InsertInteger and throws an RTCError if that
    394  * fails.
    395  *
    396  * @param   pNode           See CFGMR3InsertInteger.
    397  * @param   pcszName        See CFGMR3InsertInteger.
    398  * @param   u64Integer      See CFGMR3InsertInteger.
    399  */
    400 void Console::InsertConfigInteger(PCFGMNODE pNode, const char *pcszName, uint64_t u64Integer)
    401 {
    402     int vrc = mpVMM->pfnCFGMR3InsertInteger(pNode, pcszName, u64Integer);
    403     if (RT_FAILURE(vrc))
    404         throw ConfigError("CFGMR3InsertInteger", vrc, pcszName);
    405 }
    406 
    407 /**
    408  * Helper that calls CFGMR3InsertNode and throws an RTCError if that fails.
    409  *
    410  * @param   pNode           See CFGMR3InsertNode.
    411  * @param   pcszName        See CFGMR3InsertNode.
    412  * @param   ppChild         See CFGMR3InsertNode.
    413  */
    414 void Console::InsertConfigNode(PCFGMNODE pNode, const char *pcszName, PCFGMNODE *ppChild)
    415 {
    416     int vrc = mpVMM->pfnCFGMR3InsertNode(pNode, pcszName, ppChild);
    417     if (RT_FAILURE(vrc))
    418         throw ConfigError("CFGMR3InsertNode", vrc, pcszName);
    419 }
    420 
    421 /**
    422  * Helper that calls CFGMR3InsertNodeF and throws an RTCError if that fails.
    423  *
    424  * @param   pNode           See CFGMR3InsertNodeF.
    425  * @param   ppChild         See CFGMR3InsertNodeF.
    426  * @param   pszNameFormat   Name format string, see CFGMR3InsertNodeF.
    427  * @param   ...             Format arguments.
    428  */
    429 void Console::InsertConfigNodeF(PCFGMNODE pNode, PCFGMNODE *ppChild, const char *pszNameFormat, ...)
    430 {
    431     va_list va;
    432     va_start(va, pszNameFormat);
    433     int vrc = mpVMM->pfnCFGMR3InsertNodeF(pNode, ppChild, "%N", pszNameFormat, &va);
    434     va_end(va);
    435     if (RT_FAILURE(vrc))
    436         throw ConfigError("CFGMR3InsertNodeF", vrc, pszNameFormat);
    437 }
    438 
    439 /**
    440  * Helper that calls CFGMR3RemoveValue and throws an RTCError if that fails.
    441  *
    442  * @param   pNode           See CFGMR3RemoveValue.
    443  * @param   pcszName        See CFGMR3RemoveValue.
    444  */
    445 void Console::RemoveConfigValue(PCFGMNODE pNode, const char *pcszName)
    446 {
    447     int vrc = mpVMM->pfnCFGMR3RemoveValue(pNode, pcszName);
    448     if (RT_FAILURE(vrc))
    449         throw ConfigError("CFGMR3RemoveValue", vrc, pcszName);
    450 }
    451 
    452 /**
    453  * Gets an extra data value, consulting both machine and global extra data.
    454  *
    455  * @throws  HRESULT on failure
    456  * @returns pStrValue for the callers convenience.
    457  * @param   pVirtualBox     Pointer to the IVirtualBox interface.
    458  * @param   pMachine        Pointer to the IMachine interface.
    459  * @param   pszName         The value to get.
    460  * @param   pStrValue       Where to return it's value (empty string if not
    461  *                          found).
    462  */
    463 static Utf8Str *GetExtraDataBoth(IVirtualBox *pVirtualBox, IMachine *pMachine, const char *pszName, Utf8Str *pStrValue)
    464 {
    465     pStrValue->setNull();
    466 
    467     Bstr bstrName(pszName);
    468     Bstr bstrValue;
    469     HRESULT hrc = pMachine->GetExtraData(bstrName.raw(), bstrValue.asOutParam());
    470     if (FAILED(hrc))
    471         throw hrc;
    472     if (bstrValue.isEmpty())
    473     {
    474         hrc = pVirtualBox->GetExtraData(bstrName.raw(), bstrValue.asOutParam());
    475         if (FAILED(hrc))
    476             throw hrc;
    477     }
    478 
    479     if (bstrValue.isNotEmpty())
    480         *pStrValue = bstrValue;
    481     return pStrValue;
    482 }
    483 
    484 
    485284/** Helper that finds out the next HBA port used
    486285 */
     
    676475
    677476/**
    678  * Updates the device type for a LED.
    679  *
    680  * @param   penmSubTypeEntry    The sub-type entry to update.
    681  * @param   enmNewType          The new type.
    682  */
    683 void Console::i_setLedType(DeviceType_T *penmSubTypeEntry, DeviceType_T enmNewType)
    684 {
    685     /*
    686      * ASSUMES no race conditions here wrt concurrent type updating.
    687      */
    688     if (*penmSubTypeEntry != enmNewType)
    689     {
    690         *penmSubTypeEntry = enmNewType;
    691         ASMAtomicIncU32(&muLedGen);
    692     }
    693 }
    694 
    695 
    696 /**
    697  * Allocate a set of LEDs.
    698  *
    699  * This grabs a maLedSets entry and populates it with @a cLeds.
    700  *
    701  * @returns Index into maLedSets.
    702  * @param   cLeds       The number of LEDs in the set.
    703  * @param   fTypes      Bitmask of DeviceType_T values, e.g.
    704  *                      RT_BIT_32(DeviceType_Network).
    705  * @param   ppaSubTypes When not NULL, subtypes for each LED and return the
    706  *                      array pointer here.
    707  */
    708 uint32_t Console::i_allocateDriverLeds(uint32_t cLeds, uint32_t fTypes, DeviceType_T **ppaSubTypes)
    709 {
    710     Assert(cLeds > 0);
    711     Assert(cLeds < 1024);  /* Adjust if any driver supports >=1024 units! */
    712     Assert(!(fTypes & (RT_BIT_32(DeviceType_Null) | ~(RT_BIT_32(DeviceType_End) - 1))));
    713 
    714     /* Preallocate the arrays we need, bunching them together. */
    715     AssertCompile((unsigned)DeviceType_Null == 0);
    716     PPDMLED volatile *papLeds = (PPDMLED volatile *)RTMemAllocZ(  (sizeof(PPDMLED) + (ppaSubTypes ? sizeof(**ppaSubTypes) : 0))
    717                                                                 * cLeds);
    718     AssertStmt(papLeds, throw E_OUTOFMEMORY);
    719 
    720     /* Take the LED lock in allocation mode and see if there are more LED set entries availalbe. */
    721     {
    722         AutoWriteLock alock(mLedLock COMMA_LOCKVAL_SRC_POS);
    723         uint32_t const idxLedSet = mcLedSets;
    724         if (idxLedSet < RT_ELEMENTS(maLedSets))
    725         {
    726             /* Initialize the set and return the index. */
    727             PLEDSET pLS = &maLedSets[idxLedSet];
    728             pLS->papLeds = papLeds;
    729             pLS->cLeds = cLeds;
    730             pLS->fTypes = fTypes;
    731             if (ppaSubTypes)
    732                  *ppaSubTypes = pLS->paSubTypes = (DeviceType_T *)&papLeds[cLeds];
    733             else
    734                 pLS->paSubTypes = NULL;
    735 
    736             mcLedSets = idxLedSet + 1;
    737             LogRel2(("return idxLedSet=%d (mcLedSets=%u out of max %zu)\n", idxLedSet, mcLedSets, RT_ELEMENTS(maLedSets)));
    738             return idxLedSet;
    739         }
    740     }
    741 
    742     RTMemFree((void *)papLeds);
    743     AssertFailed();
    744     throw ConfigError("AllocateDriverPapLeds", VERR_OUT_OF_RANGE, "Too many LED sets");
    745 }
    746 
    747 
    748 /**
    749  * @throws ConfigError and std::bad_alloc.
    750  */
    751 void Console::i_attachStatusDriver(PCFGMNODE pCtlInst, uint32_t fTypes, uint32_t cLeds, DeviceType_T **ppaSubTypes,
    752                                    Console::MediumAttachmentMap *pmapMediumAttachments,
    753                                    const char *pcszDevice, unsigned uInstance)
    754 {
    755     PCFGMNODE pLunL0;
    756     InsertConfigNode(pCtlInst,  "LUN#999", &pLunL0);
    757     InsertConfigString(pLunL0,  "Driver",               "MainStatus");
    758     PCFGMNODE pCfg;
    759     InsertConfigNode(pLunL0,    "Config", &pCfg);
    760     uint32_t const iLedSet = i_allocateDriverLeds(cLeds, fTypes, ppaSubTypes);
    761     InsertConfigInteger(pCfg,   "iLedSet", iLedSet);
    762 
    763     InsertConfigInteger(pCfg,   "HasMediumAttachments", pmapMediumAttachments != NULL);
    764     if (pmapMediumAttachments)
    765     {
    766         AssertPtr(pcszDevice);
    767         InsertConfigStringF(pCfg, "DeviceInstance", "%s/%u", pcszDevice, uInstance);
    768     }
    769     InsertConfigInteger(pCfg,   "First",    0);
    770     InsertConfigInteger(pCfg,   "Last",     cLeds - 1);
    771 }
    772 
    773 
    774 /**
    775  * @throws ConfigError and std::bad_alloc.
    776  */
    777 void Console::i_attachStatusDriver(PCFGMNODE pCtlInst, DeviceType_T enmType, uint32_t cLeds /*= 1*/)
    778 {
    779     Assert(enmType > DeviceType_Null && enmType < DeviceType_End);
    780     i_attachStatusDriver(pCtlInst, RT_BIT_32(enmType), cLeds, NULL, NULL, NULL, 0);
    781 }
    782 
    783 
    784 /**
    785  * Construct the VM configuration tree (CFGM).
    786  *
    787  * This is a callback for VMR3Create() call. It is called from CFGMR3Init() in
    788  * the emulation thread (EMT). Any per thread COM/XPCOM initialization is done
    789  * here.
    790  *
    791  * @returns VBox status code.
    792  * @param   pUVM        The user mode VM handle.
    793  * @param   pVM         The cross context VM handle.
    794  * @param   pVMM        The VMM ring-3 vtable.
    795  * @param   pvConsole   Pointer to the VMPowerUpTask object.
    796  *
    797  * @note Locks the Console object for writing.
    798  */
    799 /*static*/ DECLCALLBACK(int)
    800 Console::i_configConstructor(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, void *pvConsole)
    801 {
    802     LogFlowFuncEnter();
    803 
    804     AssertReturn(pvConsole, VERR_INVALID_POINTER);
    805     ComObjPtr<Console> pConsole = static_cast<Console *>(pvConsole);
    806 
    807     AutoCaller autoCaller(pConsole);
    808     AssertComRCReturn(autoCaller.hrc(), VERR_ACCESS_DENIED);
    809 
    810     /* lock the console because we widely use internal fields and methods */
    811     AutoWriteLock alock(pConsole COMMA_LOCKVAL_SRC_POS);
    812 
    813     /*
    814      * Set the VM handle and do the rest of the job in an worker method so we
    815      * can easily reset the VM handle on failure.
    816      */
    817     pConsole->mpUVM = pUVM;
    818     pVMM->pfnVMR3RetainUVM(pUVM);
    819     int vrc;
    820     try
    821     {
    822         vrc = pConsole->i_configConstructorInner(pUVM, pVM, pVMM, &alock);
    823     }
    824     catch (...)
    825     {
    826         vrc = VERR_UNEXPECTED_EXCEPTION;
    827     }
    828     if (RT_FAILURE(vrc))
    829     {
    830         pConsole->mpUVM = NULL;
    831         pVMM->pfnVMR3ReleaseUVM(pUVM);
    832     }
    833 
    834     return vrc;
    835 }
    836 
    837 
    838 /**
    839477 * Worker for configConstructor.
    840478 *
     
    847485 *                      more).
    848486 */
    849 int Console::i_configConstructorInner(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock)
     487int Console::i_configConstructorInnerX86(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock)
    850488{
    851489    RT_NOREF(pVM /* when everything is disabled */);
     
    39453583}
    39463584
    3947 /**
    3948  * Configures an audio driver via CFGM by getting (optional) values from extra data.
    3949  *
    3950  * @param   pVirtualBox         Pointer to IVirtualBox instance.
    3951  * @param   pMachine            Pointer to IMachine instance.
    3952  * @param   pLUN                Pointer to CFGM node of LUN (the driver) to configure.
    3953  * @param   pszDrvName          Name of the driver to configure.
    3954  * @param   fAudioEnabledIn     IAudioAdapter::enabledIn value.
    3955  * @param   fAudioEnabledOut    IAudioAdapter::enabledOut value.
    3956  *
    3957  * @throws ConfigError or HRESULT on if there is trouble.
    3958  */
    3959 void Console::i_configAudioDriver(IVirtualBox *pVirtualBox, IMachine *pMachine, PCFGMNODE pLUN, const char *pszDrvName,
    3960                                   bool fAudioEnabledIn, bool fAudioEnabledOut)
    3961 {
    3962 #define H()     AssertLogRelMsgStmt(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), \
    3963                                     throw ConfigError(__FUNCTION__, VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR, "line: " RT_XSTR(__LINE__)))
    3964 
    3965     InsertConfigString(pLUN, "Driver", "AUDIO");
    3966 
    3967     PCFGMNODE pCfg;
    3968     InsertConfigNode(pLUN,   "Config", &pCfg);
    3969     InsertConfigString(pCfg,  "DriverName",    pszDrvName);
    3970     InsertConfigInteger(pCfg, "InputEnabled",  fAudioEnabledIn);
    3971     InsertConfigInteger(pCfg, "OutputEnabled", fAudioEnabledOut);
    3972 
    3973     Utf8Str strTmp;
    3974     GetExtraDataBoth(pVirtualBox, pMachine, "VBoxInternal2/Audio/Debug/Enabled", &strTmp);
    3975     const uint64_t fDebugEnabled = strTmp.equalsIgnoreCase("true") || strTmp.equalsIgnoreCase("1");
    3976     if (fDebugEnabled)
    3977     {
    3978         InsertConfigInteger(pCfg, "DebugEnabled",  fDebugEnabled);
    3979 
    3980         Utf8Str strDebugPathOut;
    3981         GetExtraDataBoth(pVirtualBox, pMachine, "VBoxInternal2/Audio/Debug/PathOut", &strDebugPathOut);
    3982         InsertConfigString(pCfg, "DebugPathOut",  strDebugPathOut.c_str());
    3983     }
    3984 
    3985     /*
    3986      * PCM input parameters (playback + recording).
    3987      * We have host driver specific ones as: VBoxInternal2/Audio/<DrvName>/<Value>
    3988      * And global ones for all host drivers: VBoxInternal2/Audio/<Value>
    3989      */
    3990     for (unsigned iDir = 0; iDir < 2; iDir++)
    3991     {
    3992         static const struct
    3993         {
    3994             const char *pszExtraName;
    3995             const char *pszCfgmName;
    3996         } s_aToCopy[] =
    3997         {   /* PCM  parameters: */
    3998             { "PCMSampleBit",        "PCMSampleBit"        },
    3999             { "PCMSampleHz",         "PCMSampleHz"         },
    4000             { "PCMSampleSigned",     "PCMSampleSigned"     },
    4001             { "PCMSampleSwapEndian", "PCMSampleSwapEndian" },
    4002             { "PCMSampleChannels",   "PCMSampleChannels"   },
    4003             /* Buffering stuff: */
    4004             { "PeriodSizeMs",        "PeriodSizeMs"        },
    4005             { "BufferSizeMs",        "BufferSizeMs"        },
    4006             { "PreBufferSizeMs",     "PreBufferSizeMs"     },
    4007         };
    4008 
    4009         PCFGMNODE   pDirNode = NULL;
    4010         const char *pszDir   = iDir == 0 ? "In" : "Out";
    4011         for (size_t i = 0; i < RT_ELEMENTS(s_aToCopy); i++)
    4012         {
    4013             char szExtra[128];
    4014             RTStrPrintf(szExtra, sizeof(szExtra), "VBoxInternal2/Audio/%s/%s%s", pszDrvName, s_aToCopy[i].pszExtraName, pszDir);
    4015             GetExtraDataBoth(pVirtualBox, pMachine, szExtra, &strTmp); /* throws hrc */
    4016             if (strTmp.isEmpty())
    4017             {
    4018                 RTStrPrintf(szExtra, sizeof(szExtra), "VBoxInternal2/Audio/%s%s", s_aToCopy[i].pszExtraName, pszDir);
    4019                 GetExtraDataBoth(pVirtualBox, pMachine, szExtra, &strTmp);
    4020                 if (strTmp.isEmpty())
    4021                     continue;
    4022             }
    4023 
    4024             uint32_t uValue;
    4025             int vrc = RTStrToUInt32Full(strTmp.c_str(), 0, &uValue);
    4026             if (RT_SUCCESS(vrc))
    4027             {
    4028                 if (!pDirNode)
    4029                     InsertConfigNode(pCfg, pszDir, &pDirNode);
    4030                 InsertConfigInteger(pDirNode, s_aToCopy[i].pszCfgmName, uValue);
    4031             }
    4032             else
    4033                 LogRel(("Ignoring malformed 32-bit unsigned integer config value '%s' = '%s': %Rrc\n", szExtra, strTmp.c_str(), vrc));
    4034         }
    4035     }
    4036 
    4037     PCFGMNODE pLunL1;
    4038     InsertConfigNode(pLUN, "AttachedDriver", &pLunL1);
    4039     InsertConfigString(pLunL1, "Driver", pszDrvName);
    4040     InsertConfigNode(pLunL1, "Config", &pCfg);
    4041 
    4042 #ifdef RT_OS_WINDOWS
    4043     if (strcmp(pszDrvName, "HostAudioWas") == 0)
    4044     {
    4045         Bstr bstrTmp;
    4046         HRESULT hrc = pMachine->COMGETTER(Id)(bstrTmp.asOutParam());                            H();
    4047         InsertConfigString(pCfg, "VmUuid", bstrTmp);
    4048     }
    4049 #endif
    4050 
    4051 #if defined(RT_OS_WINDOWS) || defined(RT_OS_LINUX)
    4052     if (   strcmp(pszDrvName, "HostAudioWas") == 0
    4053         || strcmp(pszDrvName, "PulseAudio") == 0)
    4054     {
    4055         Bstr bstrTmp;
    4056         HRESULT hrc = pMachine->COMGETTER(Name)(bstrTmp.asOutParam());                          H();
    4057         InsertConfigString(pCfg, "VmName", bstrTmp);
    4058     }
    4059 #endif
    4060 
    4061     LogFlowFunc(("szDrivName=%s\n", pszDrvName));
    4062 
    4063 #undef H
    4064 }
    4065 
    4066 /**
    4067  * Applies the CFGM overlay as specified by VBoxInternal/XXX extra data
    4068  * values.
    4069  *
    4070  * @returns VBox status code.
    4071  * @param   pRoot           The root of the configuration tree.
    4072  * @param   pVirtualBox     Pointer to the IVirtualBox interface.
    4073  * @param   pMachine        Pointer to the IMachine interface.
    4074  */
    4075 /* static */
    4076 int Console::i_configCfgmOverlay(PCFGMNODE pRoot, IVirtualBox *pVirtualBox, IMachine *pMachine)
    4077 {
    4078     /*
    4079      * CFGM overlay handling.
    4080      *
    4081      * Here we check the extra data entries for CFGM values
    4082      * and create the nodes and insert the values on the fly. Existing
    4083      * values will be removed and reinserted. CFGM is typed, so by default
    4084      * we will guess whether it's a string or an integer (byte arrays are
    4085      * not currently supported). It's possible to override this autodetection
    4086      * by adding "string:", "integer:" or "bytes:" (future).
    4087      *
    4088      * We first perform a run on global extra data, then on the machine
    4089      * extra data to support global settings with local overrides.
    4090      */
    4091     int vrc = VINF_SUCCESS;
    4092     bool fFirst = true;
    4093     try
    4094     {
    4095         /** @todo add support for removing nodes and byte blobs. */
    4096         /*
    4097          * Get the next key
    4098          */
    4099         SafeArray<BSTR> aGlobalExtraDataKeys;
    4100         SafeArray<BSTR> aMachineExtraDataKeys;
    4101         HRESULT hrc = pVirtualBox->GetExtraDataKeys(ComSafeArrayAsOutParam(aGlobalExtraDataKeys));
    4102         AssertMsg(SUCCEEDED(hrc), ("VirtualBox::GetExtraDataKeys failed with %Rhrc\n", hrc));
    4103 
    4104         // remember the no. of global values so we can call the correct method below
    4105         size_t cGlobalValues = aGlobalExtraDataKeys.size();
    4106 
    4107         hrc = pMachine->GetExtraDataKeys(ComSafeArrayAsOutParam(aMachineExtraDataKeys));
    4108         AssertMsg(SUCCEEDED(hrc), ("Machine::GetExtraDataKeys failed with %Rhrc\n", hrc));
    4109 
    4110         // build a combined list from global keys...
    4111         std::list<Utf8Str> llExtraDataKeys;
    4112 
    4113         for (size_t i = 0; i < aGlobalExtraDataKeys.size(); ++i)
    4114             llExtraDataKeys.push_back(Utf8Str(aGlobalExtraDataKeys[i]));
    4115         // ... and machine keys
    4116         for (size_t i = 0; i < aMachineExtraDataKeys.size(); ++i)
    4117             llExtraDataKeys.push_back(Utf8Str(aMachineExtraDataKeys[i]));
    4118 
    4119         size_t i2 = 0;
    4120         for (std::list<Utf8Str>::const_iterator it = llExtraDataKeys.begin();
    4121             it != llExtraDataKeys.end();
    4122             ++it, ++i2)
    4123         {
    4124             const Utf8Str &strKey = *it;
    4125 
    4126             /*
    4127              * We only care about keys starting with "VBoxInternal/" (skip "G:" or "M:")
    4128              */
    4129             if (!strKey.startsWith("VBoxInternal/"))
    4130                 continue;
    4131 
    4132             const char *pszExtraDataKey = strKey.c_str() + sizeof("VBoxInternal/") - 1;
    4133 
    4134             // get the value
    4135             Bstr bstrExtraDataValue;
    4136             if (i2 < cGlobalValues)
    4137                 // this is still one of the global values:
    4138                 hrc = pVirtualBox->GetExtraData(Bstr(strKey).raw(), bstrExtraDataValue.asOutParam());
    4139             else
    4140                 hrc = pMachine->GetExtraData(Bstr(strKey).raw(), bstrExtraDataValue.asOutParam());
    4141             if (FAILED(hrc))
    4142                 LogRel(("Warning: Cannot get extra data key %s, hrc = %Rhrc\n", strKey.c_str(), hrc));
    4143 
    4144             if (fFirst)
    4145             {
    4146                 fFirst = false;
    4147                 LogRel(("Extradata overrides:\n"));
    4148             }
    4149             LogRel(("  %s=\"%ls\"%s\n", strKey.c_str(), bstrExtraDataValue.raw(), i2 < cGlobalValues ? " (global)" : ""));
    4150 
    4151             /*
    4152              * The key will be in the format "Node1/Node2/Value" or simply "Value".
    4153              * Split the two and get the node, delete the value and create the node
    4154              * if necessary.
    4155              */
    4156             PCFGMNODE pNode;
    4157             const char *pszCFGMValueName = strrchr(pszExtraDataKey, '/');
    4158             if (pszCFGMValueName)
    4159             {
    4160                 /* terminate the node and advance to the value (Utf8Str might not
    4161                 offically like this but wtf) */
    4162                 *(char *)pszCFGMValueName = '\0';
    4163                 ++pszCFGMValueName;
    4164 
    4165                 /* does the node already exist? */
    4166                 pNode = mpVMM->pfnCFGMR3GetChild(pRoot, pszExtraDataKey);
    4167                 if (pNode)
    4168                     mpVMM->pfnCFGMR3RemoveValue(pNode, pszCFGMValueName);
    4169                 else
    4170                 {
    4171                     /* create the node */
    4172                     vrc = mpVMM->pfnCFGMR3InsertNode(pRoot, pszExtraDataKey, &pNode);
    4173                     if (RT_FAILURE(vrc))
    4174                     {
    4175                         AssertLogRelMsgRC(vrc, ("failed to insert node '%s'\n", pszExtraDataKey));
    4176                         continue;
    4177                     }
    4178                     Assert(pNode);
    4179                 }
    4180             }
    4181             else
    4182             {
    4183                 /* root value (no node path). */
    4184                 pNode = pRoot;
    4185                 pszCFGMValueName = pszExtraDataKey;
    4186                 pszExtraDataKey--;
    4187                 mpVMM->pfnCFGMR3RemoveValue(pNode, pszCFGMValueName);
    4188             }
    4189 
    4190             /*
    4191              * Now let's have a look at the value.
    4192              * Empty strings means that we should remove the value, which we've
    4193              * already done above.
    4194              */
    4195             Utf8Str strCFGMValueUtf8(bstrExtraDataValue);
    4196             if (strCFGMValueUtf8.isNotEmpty())
    4197             {
    4198                 uint64_t u64Value;
    4199 
    4200                 /* check for type prefix first. */
    4201                 if (!strncmp(strCFGMValueUtf8.c_str(), RT_STR_TUPLE("string:")))
    4202                     vrc = mpVMM->pfnCFGMR3InsertString(pNode, pszCFGMValueName, strCFGMValueUtf8.c_str() + sizeof("string:") - 1);
    4203                 else if (!strncmp(strCFGMValueUtf8.c_str(), RT_STR_TUPLE("integer:")))
    4204                 {
    4205                     vrc = RTStrToUInt64Full(strCFGMValueUtf8.c_str() + sizeof("integer:") - 1, 0, &u64Value);
    4206                     if (RT_SUCCESS(vrc))
    4207                         vrc = mpVMM->pfnCFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);
    4208                 }
    4209                 else if (!strncmp(strCFGMValueUtf8.c_str(), RT_STR_TUPLE("bytes:")))
    4210                 {
    4211                     char const *pszBase64 = strCFGMValueUtf8.c_str() + sizeof("bytes:") - 1;
    4212                     ssize_t cbValue = RTBase64DecodedSize(pszBase64, NULL);
    4213                     if (cbValue > 0)
    4214                     {
    4215                         void *pvBytes = RTMemTmpAlloc(cbValue);
    4216                         if (pvBytes)
    4217                         {
    4218                             vrc = RTBase64Decode(pszBase64, pvBytes, cbValue, NULL, NULL);
    4219                             if (RT_SUCCESS(vrc))
    4220                                 vrc = mpVMM->pfnCFGMR3InsertBytes(pNode, pszCFGMValueName, pvBytes, cbValue);
    4221                             RTMemTmpFree(pvBytes);
    4222                         }
    4223                         else
    4224                             vrc = VERR_NO_TMP_MEMORY;
    4225                     }
    4226                     else if (cbValue == 0)
    4227                         vrc = mpVMM->pfnCFGMR3InsertBytes(pNode, pszCFGMValueName, NULL, 0);
    4228                     else
    4229                         vrc = VERR_INVALID_BASE64_ENCODING;
    4230                 }
    4231                 /* auto detect type. */
    4232                 else if (RT_SUCCESS(RTStrToUInt64Full(strCFGMValueUtf8.c_str(), 0, &u64Value)))
    4233                     vrc = mpVMM->pfnCFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);
    4234                 else
    4235                     vrc = mpVMM->pfnCFGMR3InsertString(pNode, pszCFGMValueName, strCFGMValueUtf8.c_str());
    4236                 AssertLogRelMsgRCBreak(vrc, ("failed to insert CFGM value '%s' to key '%s'\n",
    4237                                              strCFGMValueUtf8.c_str(), pszExtraDataKey));
    4238             }
    4239         }
    4240     }
    4241     catch (ConfigError &x)
    4242     {
    4243         // InsertConfig threw something:
    4244         return x.m_vrc;
    4245     }
    4246     return vrc;
    4247 }
    4248 
    4249 /**
    4250  * Dumps the API settings tweaks as specified by VBoxInternal2/XXX extra data
    4251  * values.
    4252  *
    4253  * @returns VBox status code.
    4254  * @param   pVirtualBox     Pointer to the IVirtualBox interface.
    4255  * @param   pMachine        Pointer to the IMachine interface.
    4256  */
    4257 /* static */
    4258 int Console::i_configDumpAPISettingsTweaks(IVirtualBox *pVirtualBox, IMachine *pMachine)
    4259 {
    4260     {
    4261         SafeArray<BSTR> aGlobalExtraDataKeys;
    4262         HRESULT hrc = pVirtualBox->GetExtraDataKeys(ComSafeArrayAsOutParam(aGlobalExtraDataKeys));
    4263         AssertMsg(SUCCEEDED(hrc), ("VirtualBox::GetExtraDataKeys failed with %Rhrc\n", hrc));
    4264         bool hasKey = false;
    4265         for (size_t i = 0; i < aGlobalExtraDataKeys.size(); i++)
    4266         {
    4267             Utf8Str strKey(aGlobalExtraDataKeys[i]);
    4268             if (!strKey.startsWith("VBoxInternal2/"))
    4269                 continue;
    4270 
    4271             Bstr bstrValue;
    4272             hrc = pVirtualBox->GetExtraData(Bstr(strKey).raw(),
    4273                                             bstrValue.asOutParam());
    4274             if (FAILED(hrc))
    4275                 continue;
    4276             if (!hasKey)
    4277                 LogRel(("Global extradata API settings:\n"));
    4278             LogRel(("  %s=\"%ls\"\n", strKey.c_str(), bstrValue.raw()));
    4279             hasKey = true;
    4280         }
    4281     }
    4282 
    4283     {
    4284         SafeArray<BSTR> aMachineExtraDataKeys;
    4285         HRESULT hrc = pMachine->GetExtraDataKeys(ComSafeArrayAsOutParam(aMachineExtraDataKeys));
    4286         AssertMsg(SUCCEEDED(hrc), ("Machine::GetExtraDataKeys failed with %Rhrc\n", hrc));
    4287         bool hasKey = false;
    4288         for (size_t i = 0; i < aMachineExtraDataKeys.size(); i++)
    4289         {
    4290             Utf8Str strKey(aMachineExtraDataKeys[i]);
    4291             if (!strKey.startsWith("VBoxInternal2/"))
    4292                 continue;
    4293 
    4294             Bstr bstrValue;
    4295             hrc = pMachine->GetExtraData(Bstr(strKey).raw(),
    4296                                          bstrValue.asOutParam());
    4297             if (FAILED(hrc))
    4298                 continue;
    4299             if (!hasKey)
    4300                 LogRel(("Per-VM extradata API settings:\n"));
    4301             LogRel(("  %s=\"%ls\"\n", strKey.c_str(), bstrValue.raw()));
    4302             hasKey = true;
    4303         }
    4304     }
    4305 
    4306     return VINF_SUCCESS;
    4307 }
    43083585
    43093586int Console::i_configGraphicsController(PCFGMNODE pDevices,
     
    44433720    return VINF_SUCCESS;
    44443721}
    4445 
    4446 
    4447 /**
    4448  * Ellipsis to va_list wrapper for calling setVMRuntimeErrorCallback.
    4449  */
    4450 void Console::i_atVMRuntimeErrorCallbackF(uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
    4451 {
    4452     va_list va;
    4453     va_start(va, pszFormat);
    4454     i_atVMRuntimeErrorCallback(NULL, this, fFlags, pszErrorId, pszFormat, va);
    4455     va_end(va);
    4456 }
    4457 
    4458 /* XXX introduce RT format specifier */
    4459 static uint64_t formatDiskSize(uint64_t u64Size, const char **pszUnit)
    4460 {
    4461     if (u64Size > INT64_C(5000)*_1G)
    4462     {
    4463         *pszUnit = "TB";
    4464         return u64Size / _1T;
    4465     }
    4466     else if (u64Size > INT64_C(5000)*_1M)
    4467     {
    4468         *pszUnit = "GB";
    4469         return u64Size / _1G;
    4470     }
    4471     else
    4472     {
    4473         *pszUnit = "MB";
    4474         return u64Size / _1M;
    4475     }
    4476 }
    4477 
    4478 /**
    4479  * Checks the location of the given medium for known bugs affecting the usage
    4480  * of the host I/O cache setting.
    4481  *
    4482  * @returns VBox status code.
    4483  * @param   pMedium             The medium to check.
    4484  * @param   pfUseHostIOCache    Where to store the suggested host I/O cache setting.
    4485  */
    4486 int Console::i_checkMediumLocation(IMedium *pMedium, bool *pfUseHostIOCache)
    4487 {
    4488 #define H()         AssertLogRelMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
    4489     /*
    4490      * Some sanity checks.
    4491      */
    4492     RT_NOREF(pfUseHostIOCache);
    4493     ComPtr<IMediumFormat> pMediumFormat;
    4494     HRESULT hrc = pMedium->COMGETTER(MediumFormat)(pMediumFormat.asOutParam());             H();
    4495     ULONG uCaps = 0;
    4496     com::SafeArray <MediumFormatCapabilities_T> mediumFormatCap;
    4497     hrc = pMediumFormat->COMGETTER(Capabilities)(ComSafeArrayAsOutParam(mediumFormatCap));    H();
    4498 
    4499     for (ULONG j = 0; j < mediumFormatCap.size(); j++)
    4500         uCaps |= mediumFormatCap[j];
    4501 
    4502     if (uCaps & MediumFormatCapabilities_File)
    4503     {
    4504         Bstr bstrFile;
    4505         hrc = pMedium->COMGETTER(Location)(bstrFile.asOutParam());                  H();
    4506         Utf8Str const strFile(bstrFile);
    4507 
    4508         Bstr bstrSnap;
    4509         ComPtr<IMachine> pMachine = i_machine();
    4510         hrc = pMachine->COMGETTER(SnapshotFolder)(bstrSnap.asOutParam());           H();
    4511         Utf8Str const strSnap(bstrSnap);
    4512 
    4513         RTFSTYPE enmFsTypeFile = RTFSTYPE_UNKNOWN;
    4514         int vrc2 = RTFsQueryType(strFile.c_str(), &enmFsTypeFile);
    4515         AssertMsgRCReturn(vrc2, ("Querying the file type of '%s' failed!\n", strFile.c_str()), vrc2);
    4516 
    4517          /* Any VM which hasn't created a snapshot or saved the current state of the VM
    4518           * won't have a Snapshot folder yet so no need to log anything about the file system
    4519           * type of the non-existent directory in such cases. */
    4520         RTFSTYPE enmFsTypeSnap = RTFSTYPE_UNKNOWN;
    4521         vrc2 = RTFsQueryType(strSnap.c_str(), &enmFsTypeSnap);
    4522         if (RT_SUCCESS(vrc2) && !mfSnapshotFolderDiskTypeShown)
    4523         {
    4524             LogRel(("File system of '%s' (snapshots) is %s\n", strSnap.c_str(), RTFsTypeName(enmFsTypeSnap)));
    4525             mfSnapshotFolderDiskTypeShown = true;
    4526         }
    4527         LogRel(("File system of '%s' is %s\n", strFile.c_str(), RTFsTypeName(enmFsTypeFile)));
    4528         LONG64 i64Size;
    4529         hrc = pMedium->COMGETTER(LogicalSize)(&i64Size);                            H();
    4530 #ifdef RT_OS_WINDOWS
    4531         if (   enmFsTypeFile == RTFSTYPE_FAT
    4532             && i64Size >= _4G)
    4533         {
    4534             const char *pszUnit;
    4535             uint64_t u64Print = formatDiskSize((uint64_t)i64Size, &pszUnit);
    4536             i_atVMRuntimeErrorCallbackF(0, "FatPartitionDetected",
    4537                                         N_("The medium '%s' has a logical size of %RU64%s "
    4538                                            "but the file system the medium is located on seems "
    4539                                            "to be FAT(32) which cannot handle files bigger than 4GB.\n"
    4540                                            "We strongly recommend to put all your virtual disk images and "
    4541                                            "the snapshot folder onto an NTFS partition"),
    4542                                         strFile.c_str(), u64Print, pszUnit);
    4543         }
    4544 #else /* !RT_OS_WINDOWS */
    4545         if (   enmFsTypeFile == RTFSTYPE_FAT
    4546             || enmFsTypeFile == RTFSTYPE_EXT
    4547             || enmFsTypeFile == RTFSTYPE_EXT2
    4548             || enmFsTypeFile == RTFSTYPE_EXT3
    4549             || enmFsTypeFile == RTFSTYPE_EXT4)
    4550         {
    4551             RTFILE file;
    4552             int vrc = RTFileOpen(&file, strFile.c_str(), RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    4553             if (RT_SUCCESS(vrc))
    4554             {
    4555                 RTFOFF maxSize;
    4556                 /* Careful: This function will work only on selected local file systems! */
    4557                 vrc = RTFileQueryMaxSizeEx(file, &maxSize);
    4558                 RTFileClose(file);
    4559                 if (   RT_SUCCESS(vrc)
    4560                     && maxSize > 0
    4561                     && i64Size > (LONG64)maxSize)
    4562                 {
    4563                     const char *pszUnitSiz;
    4564                     const char *pszUnitMax;
    4565                     uint64_t u64PrintSiz = formatDiskSize((LONG64)i64Size, &pszUnitSiz);
    4566                     uint64_t u64PrintMax = formatDiskSize(maxSize, &pszUnitMax);
    4567                     i_atVMRuntimeErrorCallbackF(0, "FatPartitionDetected", /* <= not exact but ... */
    4568                                                 N_("The medium '%s' has a logical size of %RU64%s "
    4569                                                    "but the file system the medium is located on can "
    4570                                                    "only handle files up to %RU64%s in theory.\n"
    4571                                                    "We strongly recommend to put all your virtual disk "
    4572                                                    "images and the snapshot folder onto a proper "
    4573                                                    "file system (e.g. ext3) with a sufficient size"),
    4574                                                 strFile.c_str(), u64PrintSiz, pszUnitSiz, u64PrintMax, pszUnitMax);
    4575                 }
    4576             }
    4577         }
    4578 #endif /* !RT_OS_WINDOWS */
    4579 
    4580         /*
    4581          * Snapshot folder:
    4582          * Here we test only for a FAT partition as we had to create a dummy file otherwise
    4583          */
    4584         if (   enmFsTypeSnap == RTFSTYPE_FAT
    4585             && i64Size >= _4G
    4586             && !mfSnapshotFolderSizeWarningShown)
    4587         {
    4588             const char *pszUnit;
    4589             uint64_t u64Print = formatDiskSize(i64Size, &pszUnit);
    4590             i_atVMRuntimeErrorCallbackF(0, "FatPartitionDetected",
    4591 #ifdef RT_OS_WINDOWS
    4592                                         N_("The snapshot folder of this VM '%s' seems to be located on "
    4593                                            "a FAT(32) file system. The logical size of the medium '%s' "
    4594                                            "(%RU64%s) is bigger than the maximum file size this file "
    4595                                            "system can handle (4GB).\n"
    4596                                            "We strongly recommend to put all your virtual disk images and "
    4597                                            "the snapshot folder onto an NTFS partition"),
    4598 #else
    4599                                         N_("The snapshot folder of this VM '%s' seems to be located on "
    4600                                             "a FAT(32) file system. The logical size of the medium '%s' "
    4601                                             "(%RU64%s) is bigger than the maximum file size this file "
    4602                                             "system can handle (4GB).\n"
    4603                                             "We strongly recommend to put all your virtual disk images and "
    4604                                             "the snapshot folder onto a proper file system (e.g. ext3)"),
    4605 #endif
    4606                                         strSnap.c_str(), strFile.c_str(), u64Print, pszUnit);
    4607             /* Show this particular warning only once */
    4608             mfSnapshotFolderSizeWarningShown = true;
    4609         }
    4610 
    4611 #ifdef RT_OS_LINUX
    4612         /*
    4613          * Ext4 bug: Check if the host I/O cache is disabled and the disk image is located
    4614          *           on an ext4 partition.
    4615          * This bug apparently applies to the XFS file system as well.
    4616          * Linux 2.6.36 is known to be fixed (tested with 2.6.36-rc4).
    4617          */
    4618 
    4619         char szOsRelease[128];
    4620         int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szOsRelease, sizeof(szOsRelease));
    4621         bool fKernelHasODirectBug =    RT_FAILURE(vrc)
    4622                                     || (RTStrVersionCompare(szOsRelease, "2.6.36-rc4") < 0);
    4623 
    4624         if (   (uCaps & MediumFormatCapabilities_Asynchronous)
    4625             && !*pfUseHostIOCache
    4626             && fKernelHasODirectBug)
    4627         {
    4628             if (   enmFsTypeFile == RTFSTYPE_EXT4
    4629                 || enmFsTypeFile == RTFSTYPE_XFS)
    4630             {
    4631                 i_atVMRuntimeErrorCallbackF(0, "Ext4PartitionDetected",
    4632                                             N_("The host I/O cache for at least one controller is disabled "
    4633                                                "and the medium '%s' for this VM "
    4634                                                "is located on an %s partition. There is a known Linux "
    4635                                                "kernel bug which can lead to the corruption of the virtual "
    4636                                                "disk image under these conditions.\n"
    4637                                                "Either enable the host I/O cache permanently in the VM "
    4638                                                "settings or put the disk image and the snapshot folder "
    4639                                                "onto a different file system.\n"
    4640                                                "The host I/O cache will now be enabled for this medium"),
    4641                                             strFile.c_str(), enmFsTypeFile == RTFSTYPE_EXT4 ? "ext4" : "xfs");
    4642                 *pfUseHostIOCache = true;
    4643             }
    4644             else if (  (   enmFsTypeSnap == RTFSTYPE_EXT4
    4645                         || enmFsTypeSnap == RTFSTYPE_XFS)
    4646                      && !mfSnapshotFolderExt4WarningShown)
    4647             {
    4648                 i_atVMRuntimeErrorCallbackF(0, "Ext4PartitionDetected",
    4649                                             N_("The host I/O cache for at least one controller is disabled "
    4650                                                "and the snapshot folder for this VM "
    4651                                                "is located on an %s partition. There is a known Linux "
    4652                                                "kernel bug which can lead to the corruption of the virtual "
    4653                                                "disk image under these conditions.\n"
    4654                                                "Either enable the host I/O cache permanently in the VM "
    4655                                                "settings or put the disk image and the snapshot folder "
    4656                                                "onto a different file system.\n"
    4657                                                "The host I/O cache will now be enabled for this medium"),
    4658                                             enmFsTypeSnap == RTFSTYPE_EXT4 ? "ext4" : "xfs");
    4659                 *pfUseHostIOCache = true;
    4660                 mfSnapshotFolderExt4WarningShown = true;
    4661             }
    4662         }
    4663 
    4664         /*
    4665          * 2.6.18 bug: Check if the host I/O cache is disabled and the host is running
    4666          *             Linux 2.6.18. See @bugref{8690}. Apparently the same problem as
    4667          *             documented in https://lkml.org/lkml/2007/2/1/14. We saw such
    4668          *             kernel oopses on Linux 2.6.18-416.el5. We don't know when this
    4669          *             was fixed but we _know_ that 2.6.18 EL5 kernels are affected.
    4670          */
    4671         bool fKernelAsyncUnreliable =    RT_FAILURE(vrc)
    4672                                       || (RTStrVersionCompare(szOsRelease, "2.6.19") < 0);
    4673         if (   (uCaps & MediumFormatCapabilities_Asynchronous)
    4674             && !*pfUseHostIOCache
    4675             && fKernelAsyncUnreliable)
    4676         {
    4677             i_atVMRuntimeErrorCallbackF(0, "Linux2618TooOld",
    4678                                         N_("The host I/O cache for at least one controller is disabled. "
    4679                                            "There is a known Linux kernel bug which can lead to kernel "
    4680                                            "oopses under heavy load. To our knowledge this bug affects "
    4681                                            "all 2.6.18 kernels.\n"
    4682                                            "Either enable the host I/O cache permanently in the VM "
    4683                                            "settings or switch to a newer host kernel.\n"
    4684                                            "The host I/O cache will now be enabled for this medium"));
    4685             *pfUseHostIOCache = true;
    4686         }
    4687 #endif
    4688     }
    4689 #undef H
    4690 
    4691     return VINF_SUCCESS;
    4692 }
    4693 
    4694 /**
    4695  * Unmounts the specified medium from the specified device.
    4696  *
    4697  * @returns VBox status code.
    4698  * @param   pUVM            The usermode VM handle.
    4699  * @param   pVMM            The VMM vtable.
    4700  * @param   enmBus          The storage bus.
    4701  * @param   enmDevType      The device type.
    4702  * @param   pcszDevice      The device emulation.
    4703  * @param   uInstance       Instance of the device.
    4704  * @param   uLUN            The LUN on the device.
    4705  * @param   fForceUnmount   Whether to force unmounting.
    4706  */
    4707 int Console::i_unmountMediumFromGuest(PUVM pUVM, PCVMMR3VTABLE pVMM, StorageBus_T enmBus, DeviceType_T enmDevType,
    4708                                       const char *pcszDevice, unsigned uInstance, unsigned uLUN,
    4709                                       bool fForceUnmount) RT_NOEXCEPT
    4710 {
    4711     /* Unmount existing media only for floppy and DVD drives. */
    4712     int vrc = VINF_SUCCESS;
    4713     PPDMIBASE pBase;
    4714     if (enmBus == StorageBus_USB)
    4715         vrc = pVMM->pfnPDMR3UsbQueryDriverOnLun(pUVM, pcszDevice, uInstance, uLUN, "SCSI", &pBase);
    4716     else if (   (enmBus == StorageBus_SAS || enmBus == StorageBus_SCSI || enmBus == StorageBus_VirtioSCSI)
    4717              || (enmBus == StorageBus_SATA && enmDevType == DeviceType_DVD))
    4718         vrc = pVMM->pfnPDMR3QueryDriverOnLun(pUVM, pcszDevice, uInstance, uLUN, "SCSI", &pBase);
    4719     else /* IDE or Floppy */
    4720         vrc = pVMM->pfnPDMR3QueryLun(pUVM, pcszDevice, uInstance, uLUN, &pBase);
    4721 
    4722     if (RT_FAILURE(vrc))
    4723     {
    4724         if (vrc == VERR_PDM_LUN_NOT_FOUND || vrc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN)
    4725             vrc = VINF_SUCCESS;
    4726         AssertRC(vrc);
    4727     }
    4728     else
    4729     {
    4730         PPDMIMOUNT pIMount = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMOUNT);
    4731         AssertReturn(pIMount, VERR_INVALID_POINTER);
    4732 
    4733         /* Unmount the media (but do not eject the medium!) */
    4734         vrc = pIMount->pfnUnmount(pIMount, fForceUnmount, false /*=fEject*/);
    4735         if (vrc == VERR_PDM_MEDIA_NOT_MOUNTED)
    4736             vrc = VINF_SUCCESS;
    4737         /* for example if the medium is locked */
    4738         else if (RT_FAILURE(vrc))
    4739             return vrc;
    4740     }
    4741 
    4742     return vrc;
    4743 }
    4744 
    4745 /**
    4746  * Removes the currently attached medium driver form the specified device
    4747  * taking care of the controlelr specific configs wrt. to the attached driver chain.
    4748  *
    4749  * @returns VBox status code.
    4750  * @param   pCtlInst        The controler instance node in the CFGM tree.
    4751  * @param   pcszDevice      The device name.
    4752  * @param   uInstance       The device instance.
    4753  * @param   uLUN            The device LUN.
    4754  * @param   enmBus          The storage bus.
    4755  * @param   fAttachDetach   Flag whether this is a change while the VM is running
    4756  * @param   fHotplug        Flag whether the guest should be notified about the device change.
    4757  * @param   fForceUnmount   Flag whether to force unmounting the medium even if it is locked.
    4758  * @param   pUVM            The usermode VM handle.
    4759  * @param   pVMM            The VMM vtable.
    4760  * @param   enmDevType      The device type.
    4761  * @param   ppLunL0         Where to store the node to attach the new config to on success.
    4762  */
    4763 int Console::i_removeMediumDriverFromVm(PCFGMNODE pCtlInst,
    4764                                         const char *pcszDevice,
    4765                                         unsigned uInstance,
    4766                                         unsigned uLUN,
    4767                                         StorageBus_T enmBus,
    4768                                         bool fAttachDetach,
    4769                                         bool fHotplug,
    4770                                         bool fForceUnmount,
    4771                                         PUVM pUVM,
    4772                                         PCVMMR3VTABLE pVMM,
    4773                                         DeviceType_T enmDevType,
    4774                                         PCFGMNODE *ppLunL0)
    4775 {
    4776     int vrc = VINF_SUCCESS;
    4777     bool fAddLun = false;
    4778 
    4779     /* First check if the LUN already exists. */
    4780     PCFGMNODE pLunL0 = pVMM->pfnCFGMR3GetChildF(pCtlInst, "LUN#%u", uLUN);
    4781     AssertReturn(!RT_VALID_PTR(pLunL0) || fAttachDetach, VERR_INTERNAL_ERROR);
    4782 
    4783     if (pLunL0)
    4784     {
    4785         /*
    4786          * Unmount the currently mounted medium if we don't just hot remove the
    4787          * complete device (SATA) and it supports unmounting (DVD).
    4788          */
    4789         if (   (enmDevType != DeviceType_HardDisk)
    4790             && !fHotplug)
    4791         {
    4792             vrc = i_unmountMediumFromGuest(pUVM, pVMM, enmBus, enmDevType, pcszDevice, uInstance, uLUN, fForceUnmount);
    4793             if (RT_FAILURE(vrc))
    4794                 return vrc;
    4795         }
    4796 
    4797         /*
    4798          * Don't detach the SCSI driver when unmounting the current medium
    4799          * (we are not ripping out the device but only eject the medium).
    4800          */
    4801         char *pszDriverDetach = NULL;
    4802         if (   !fHotplug
    4803             && (   (enmBus == StorageBus_SATA && enmDevType == DeviceType_DVD)
    4804                 || enmBus == StorageBus_SAS
    4805                 || enmBus == StorageBus_SCSI
    4806                 || enmBus == StorageBus_VirtioSCSI
    4807                 || enmBus == StorageBus_USB))
    4808         {
    4809             /* Get the current attached driver we have to detach. */
    4810             PCFGMNODE pDrvLun = pVMM->pfnCFGMR3GetChildF(pCtlInst, "LUN#%u/AttachedDriver/", uLUN);
    4811             if (pDrvLun)
    4812             {
    4813                 char szDriver[128];
    4814                 RT_ZERO(szDriver);
    4815                 vrc  = pVMM->pfnCFGMR3QueryString(pDrvLun, "Driver", &szDriver[0], sizeof(szDriver));
    4816                 if (RT_SUCCESS(vrc))
    4817                     pszDriverDetach = RTStrDup(&szDriver[0]);
    4818 
    4819                 pLunL0 = pDrvLun;
    4820             }
    4821         }
    4822 
    4823         if (enmBus == StorageBus_USB)
    4824             vrc = pVMM->pfnPDMR3UsbDriverDetach(pUVM, pcszDevice, uInstance, uLUN, pszDriverDetach,
    4825                                                 0 /* iOccurence */, fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG);
    4826         else
    4827             vrc = pVMM->pfnPDMR3DriverDetach(pUVM, pcszDevice, uInstance, uLUN, pszDriverDetach,
    4828                                              0 /* iOccurence */, fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG);
    4829 
    4830         if (pszDriverDetach)
    4831         {
    4832             RTStrFree(pszDriverDetach);
    4833             /* Remove the complete node and create new for the new config. */
    4834             pVMM->pfnCFGMR3RemoveNode(pLunL0);
    4835             pLunL0 = pVMM->pfnCFGMR3GetChildF(pCtlInst, "LUN#%u", uLUN);
    4836             if (pLunL0)
    4837             {
    4838                 try
    4839                 {
    4840                     InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
    4841                 }
    4842                 catch (ConfigError &x)
    4843                 {
    4844                     // InsertConfig threw something:
    4845                     return x.m_vrc;
    4846                 }
    4847             }
    4848         }
    4849         if (vrc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN)
    4850             vrc = VINF_SUCCESS;
    4851         AssertRCReturn(vrc, vrc);
    4852 
    4853         /*
    4854          * Don't remove the LUN except for IDE/floppy/NVMe (which connects directly to the medium driver
    4855          * even for DVD devices) or if there is a hotplug event which rips out the complete device.
    4856          */
    4857         if (   fHotplug
    4858             || enmBus == StorageBus_IDE
    4859             || enmBus == StorageBus_Floppy
    4860             || enmBus == StorageBus_PCIe
    4861             || (enmBus == StorageBus_SATA && enmDevType != DeviceType_DVD))
    4862         {
    4863             fAddLun = true;
    4864             pVMM->pfnCFGMR3RemoveNode(pLunL0);
    4865         }
    4866     }
    4867     else
    4868         fAddLun = true;
    4869 
    4870     try
    4871     {
    4872         if (fAddLun)
    4873             InsertConfigNodeF(pCtlInst, &pLunL0, "LUN#%u", uLUN);
    4874     }
    4875     catch (ConfigError &x)
    4876     {
    4877         // InsertConfig threw something:
    4878         return x.m_vrc;
    4879     }
    4880 
    4881     if (ppLunL0)
    4882         *ppLunL0 = pLunL0;
    4883 
    4884     return vrc;
    4885 }
    4886 
    4887 int Console::i_configMediumAttachment(const char *pcszDevice,
    4888                                       unsigned uInstance,
    4889                                       StorageBus_T enmBus,
    4890                                       bool fUseHostIOCache,
    4891                                       bool fBuiltinIOCache,
    4892                                       bool fInsertDiskIntegrityDrv,
    4893                                       bool fSetupMerge,
    4894                                       unsigned uMergeSource,
    4895                                       unsigned uMergeTarget,
    4896                                       IMediumAttachment *pMediumAtt,
    4897                                       MachineState_T aMachineState,
    4898                                       HRESULT *phrc,
    4899                                       bool fAttachDetach,
    4900                                       bool fForceUnmount,
    4901                                       bool fHotplug,
    4902                                       PUVM pUVM,
    4903                                       PCVMMR3VTABLE pVMM,
    4904                                       DeviceType_T *paLedDevType,
    4905                                       PCFGMNODE *ppLunL0)
    4906 {
    4907     // InsertConfig* throws
    4908     try
    4909     {
    4910         int vrc = VINF_SUCCESS;
    4911         HRESULT hrc;
    4912         Bstr    bstr;
    4913         PCFGMNODE pCtlInst = NULL;
    4914 
    4915 // #define RC_CHECK()  AssertMsgReturn(RT_SUCCESS(vrc), ("vrc=%Rrc\n", vrc), vrc)
    4916 #define H()         AssertLogRelMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
    4917 
    4918         LONG lDev;
    4919         hrc = pMediumAtt->COMGETTER(Device)(&lDev);                                         H();
    4920         LONG lPort;
    4921         hrc = pMediumAtt->COMGETTER(Port)(&lPort);                                          H();
    4922         DeviceType_T enmType;
    4923         hrc = pMediumAtt->COMGETTER(Type)(&enmType);                                        H();
    4924         BOOL fNonRotational;
    4925         hrc = pMediumAtt->COMGETTER(NonRotational)(&fNonRotational);                        H();
    4926         BOOL fDiscard;
    4927         hrc = pMediumAtt->COMGETTER(Discard)(&fDiscard);                                    H();
    4928 
    4929         if (enmType == DeviceType_DVD)
    4930             fInsertDiskIntegrityDrv = false;
    4931 
    4932         unsigned uLUN;
    4933         PCFGMNODE pLunL0 = NULL;
    4934         hrc = Console::i_storageBusPortDeviceToLun(enmBus, lPort, lDev, uLUN);                H();
    4935 
    4936         /* Determine the base path for the device instance. */
    4937         if (enmBus != StorageBus_USB)
    4938             pCtlInst = pVMM->pfnCFGMR3GetChildF(pVMM->pfnCFGMR3GetRootU(pUVM), "Devices/%s/%u/", pcszDevice, uInstance);
    4939         else
    4940         {
    4941             /* If we hotplug a USB device create a new CFGM tree. */
    4942             if (!fHotplug)
    4943                 pCtlInst = pVMM->pfnCFGMR3GetChildF(pVMM->pfnCFGMR3GetRootU(pUVM), "USB/%s/", pcszDevice);
    4944             else
    4945                 pCtlInst = pVMM->pfnCFGMR3CreateTree(pUVM); /** @todo r=bird: Leaked in error paths! */
    4946         }
    4947         AssertReturn(pCtlInst, VERR_INTERNAL_ERROR);
    4948 
    4949         if (enmBus == StorageBus_USB)
    4950         {
    4951             PCFGMNODE pCfg = NULL;
    4952 
    4953             /* Create correct instance. */
    4954             if (!fHotplug)
    4955             {
    4956                 if (!fAttachDetach)
    4957                     InsertConfigNodeF(pCtlInst, &pCtlInst, "%d", lPort);
    4958                 else
    4959                     pCtlInst = pVMM->pfnCFGMR3GetChildF(pCtlInst, "%d/", lPort);
    4960             }
    4961 
    4962             if (!fAttachDetach)
    4963                 InsertConfigNode(pCtlInst, "Config", &pCfg);
    4964 
    4965             uInstance = lPort; /* Overwrite uInstance with the correct one. */
    4966 
    4967             /** @todo No LED after hotplugging. */
    4968             if (!fHotplug && !fAttachDetach)
    4969             {
    4970                 USBStorageDevice UsbMsd;
    4971                 UsbMsd.iPort = uInstance;
    4972                 vrc = RTUuidCreate(&UsbMsd.mUuid);
    4973                 AssertRCReturn(vrc, vrc);
    4974 
    4975                 InsertConfigStringF(pCtlInst, "UUID", "%RTuuid", &UsbMsd.mUuid);
    4976 
    4977                 mUSBStorageDevices.push_back(UsbMsd);
    4978 
    4979                 /** @todo This LED set is not freed if the device is unplugged.  We could
    4980                  *        keep the LED set index in the UsbMsd structure and clean it up in
    4981                  *        i_detachStorageDevice. */
    4982                 /* Attach the status driver */
    4983                 i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk),
    4984                                      8, &paLedDevType, &mapMediumAttachments, pcszDevice, 0);
    4985             }
    4986         }
    4987 
    4988         vrc = i_removeMediumDriverFromVm(pCtlInst, pcszDevice, uInstance, uLUN, enmBus, fAttachDetach,
    4989                                          fHotplug, fForceUnmount, pUVM, pVMM, enmType, &pLunL0);
    4990         if (RT_FAILURE(vrc))
    4991             return vrc;
    4992         if (ppLunL0)
    4993             *ppLunL0 = pLunL0;
    4994 
    4995         Utf8StrFmt devicePath("%s/%u/LUN#%u", pcszDevice, uInstance, uLUN);
    4996         mapMediumAttachments[devicePath] = pMediumAtt;
    4997 
    4998         ComPtr<IMedium> ptrMedium;
    4999         hrc = pMediumAtt->COMGETTER(Medium)(ptrMedium.asOutParam());                        H();
    5000 
    5001         /*
    5002          * 1. Only check this for hard disk images.
    5003          * 2. Only check during VM creation and not later, especially not during
    5004          *    taking an online snapshot!
    5005          */
    5006         if (   enmType == DeviceType_HardDisk
    5007             && (   aMachineState == MachineState_Starting
    5008                 || aMachineState == MachineState_Restoring))
    5009         {
    5010             vrc = i_checkMediumLocation(ptrMedium, &fUseHostIOCache);
    5011             if (RT_FAILURE(vrc))
    5012                 return vrc;
    5013         }
    5014 
    5015         BOOL fPassthrough = FALSE;
    5016         if (ptrMedium.isNotNull())
    5017         {
    5018             BOOL fHostDrive;
    5019             hrc = ptrMedium->COMGETTER(HostDrive)(&fHostDrive);                             H();
    5020             if (  (   enmType == DeviceType_DVD
    5021                    || enmType == DeviceType_Floppy)
    5022                 && !fHostDrive)
    5023             {
    5024                 /*
    5025                  * Informative logging.
    5026                  */
    5027                 Bstr bstrFile;
    5028                 hrc = ptrMedium->COMGETTER(Location)(bstrFile.asOutParam());                H();
    5029                 Utf8Str strFile(bstrFile);
    5030                 RTFSTYPE enmFsTypeFile = RTFSTYPE_UNKNOWN;
    5031                 (void)RTFsQueryType(strFile.c_str(), &enmFsTypeFile);
    5032                 LogRel(("File system of '%s' (%s) is %s\n",
    5033                        strFile.c_str(), enmType == DeviceType_DVD ? "DVD" : "Floppy", RTFsTypeName(enmFsTypeFile)));
    5034             }
    5035 
    5036             if (fHostDrive)
    5037             {
    5038                 hrc = pMediumAtt->COMGETTER(Passthrough)(&fPassthrough);                    H();
    5039             }
    5040         }
    5041 
    5042         ComObjPtr<IBandwidthGroup> pBwGroup;
    5043         Bstr bstrBwGroup;
    5044         hrc = pMediumAtt->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam());                 H();
    5045 
    5046         if (!pBwGroup.isNull())
    5047         {
    5048             hrc = pBwGroup->COMGETTER(Name)(bstrBwGroup.asOutParam());                      H();
    5049         }
    5050 
    5051         /*
    5052          * Insert the SCSI driver for hotplug events on the SCSI/USB based storage controllers
    5053          * or for SATA if the new device is a CD/DVD drive.
    5054          */
    5055         if (   (fHotplug || !fAttachDetach)
    5056             && (   enmBus == StorageBus_SCSI
    5057                 || enmBus == StorageBus_SAS
    5058                 || enmBus == StorageBus_USB
    5059                 || enmBus == StorageBus_VirtioSCSI
    5060                 || (enmBus == StorageBus_SATA && enmType == DeviceType_DVD && !fPassthrough)))
    5061         {
    5062             InsertConfigString(pLunL0, "Driver", "SCSI");
    5063             InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
    5064         }
    5065 
    5066         vrc = i_configMedium(pLunL0,
    5067                              !!fPassthrough,
    5068                              enmType,
    5069                              fUseHostIOCache,
    5070                              fBuiltinIOCache,
    5071                              fInsertDiskIntegrityDrv,
    5072                              fSetupMerge,
    5073                              uMergeSource,
    5074                              uMergeTarget,
    5075                              bstrBwGroup.isEmpty() ? NULL : Utf8Str(bstrBwGroup).c_str(),
    5076                              !!fDiscard,
    5077                              !!fNonRotational,
    5078                              ptrMedium,
    5079                              aMachineState,
    5080                              phrc);
    5081         if (RT_FAILURE(vrc))
    5082             return vrc;
    5083 
    5084         if (fAttachDetach)
    5085         {
    5086             /* Attach the new driver. */
    5087             if (enmBus == StorageBus_USB)
    5088             {
    5089                 if (fHotplug)
    5090                 {
    5091                     USBStorageDevice UsbMsd;
    5092                     RTUuidCreate(&UsbMsd.mUuid);
    5093                     UsbMsd.iPort = uInstance;
    5094                     vrc = pVMM->pfnPDMR3UsbCreateEmulatedDevice(pUVM, pcszDevice, pCtlInst, &UsbMsd.mUuid, NULL);
    5095                     if (RT_SUCCESS(vrc))
    5096                         mUSBStorageDevices.push_back(UsbMsd);
    5097                 }
    5098                 else
    5099                     vrc = pVMM->pfnPDMR3UsbDriverAttach(pUVM, pcszDevice, uInstance, uLUN,
    5100                                                         fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG, NULL /*ppBase*/);
    5101             }
    5102             else if (   !fHotplug
    5103                      && (   (enmBus == StorageBus_SAS || enmBus == StorageBus_SCSI || enmBus == StorageBus_VirtioSCSI)
    5104                          || (enmBus == StorageBus_SATA && enmType == DeviceType_DVD)))
    5105                 vrc = pVMM->pfnPDMR3DriverAttach(pUVM, pcszDevice, uInstance, uLUN,
    5106                                                  fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG, NULL /*ppBase*/);
    5107             else
    5108                 vrc = pVMM->pfnPDMR3DeviceAttach(pUVM, pcszDevice, uInstance, uLUN,
    5109                                                  fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG, NULL /*ppBase*/);
    5110             AssertRCReturn(vrc, vrc);
    5111 
    5112             /*
    5113              * Make the secret key helper interface known to the VD driver if it is attached,
    5114              * so we can get notified about missing keys.
    5115              */
    5116             PPDMIBASE pIBase = NULL;
    5117             vrc = pVMM->pfnPDMR3QueryDriverOnLun(pUVM, pcszDevice, uInstance, uLUN, "VD", &pIBase);
    5118             if (RT_SUCCESS(vrc) && pIBase)
    5119             {
    5120                 PPDMIMEDIA pIMedium = (PPDMIMEDIA)pIBase->pfnQueryInterface(pIBase, PDMIMEDIA_IID);
    5121                 if (pIMedium)
    5122                 {
    5123                     vrc = pIMedium->pfnSetSecKeyIf(pIMedium, mpIfSecKey, mpIfSecKeyHlp);
    5124                     Assert(RT_SUCCESS(vrc) || vrc == VERR_NOT_SUPPORTED);
    5125                 }
    5126             }
    5127 
    5128             /* There is no need to handle removable medium mounting, as we
    5129              * unconditionally replace everthing including the block driver level.
    5130              * This means the new medium will be picked up automatically. */
    5131         }
    5132 
    5133         if (paLedDevType)
    5134             i_setLedType(&paLedDevType[uLUN], enmType);
    5135 
    5136         /* Dump the changed LUN if possible, dump the complete device otherwise */
    5137         if (   aMachineState != MachineState_Starting
    5138             && aMachineState != MachineState_Restoring)
    5139             pVMM->pfnCFGMR3Dump(pLunL0 ? pLunL0 : pCtlInst);
    5140     }
    5141     catch (ConfigError &x)
    5142     {
    5143         // InsertConfig threw something:
    5144         return x.m_vrc;
    5145     }
    5146 
    5147 #undef H
    5148 
    5149     return VINF_SUCCESS;
    5150 }
    5151 
    5152 int Console::i_configMedium(PCFGMNODE pLunL0,
    5153                             bool fPassthrough,
    5154                             DeviceType_T enmType,
    5155                             bool fUseHostIOCache,
    5156                             bool fBuiltinIOCache,
    5157                             bool fInsertDiskIntegrityDrv,
    5158                             bool fSetupMerge,
    5159                             unsigned uMergeSource,
    5160                             unsigned uMergeTarget,
    5161                             const char *pcszBwGroup,
    5162                             bool fDiscard,
    5163                             bool fNonRotational,
    5164                             ComPtr<IMedium> ptrMedium,
    5165                             MachineState_T aMachineState,
    5166                             HRESULT *phrc)
    5167 {
    5168     // InsertConfig* throws
    5169     try
    5170     {
    5171         HRESULT hrc;
    5172         Bstr bstr;
    5173         PCFGMNODE pCfg = NULL;
    5174 
    5175 #define H() \
    5176     AssertMsgReturnStmt(SUCCEEDED(hrc), ("hrc=%Rhrc\n", hrc), if (phrc) *phrc = hrc, Global::vboxStatusCodeFromCOM(hrc))
    5177 
    5178 
    5179         BOOL fHostDrive = FALSE;
    5180         MediumType_T mediumType = MediumType_Normal;
    5181         if (ptrMedium.isNotNull())
    5182         {
    5183             hrc = ptrMedium->COMGETTER(HostDrive)(&fHostDrive);                             H();
    5184             hrc = ptrMedium->COMGETTER(Type)(&mediumType);                                  H();
    5185         }
    5186 
    5187         if (fHostDrive)
    5188         {
    5189             Assert(ptrMedium.isNotNull());
    5190             if (enmType == DeviceType_DVD)
    5191             {
    5192                 InsertConfigString(pLunL0, "Driver", "HostDVD");
    5193                 InsertConfigNode(pLunL0, "Config", &pCfg);
    5194 
    5195                 hrc = ptrMedium->COMGETTER(Location)(bstr.asOutParam());                    H();
    5196                 InsertConfigString(pCfg, "Path", bstr);
    5197 
    5198                 InsertConfigInteger(pCfg, "Passthrough", fPassthrough);
    5199             }
    5200             else if (enmType == DeviceType_Floppy)
    5201             {
    5202                 InsertConfigString(pLunL0, "Driver", "HostFloppy");
    5203                 InsertConfigNode(pLunL0, "Config", &pCfg);
    5204 
    5205                 hrc = ptrMedium->COMGETTER(Location)(bstr.asOutParam());                    H();
    5206                 InsertConfigString(pCfg, "Path", bstr);
    5207             }
    5208         }
    5209         else
    5210         {
    5211             if (fInsertDiskIntegrityDrv)
    5212             {
    5213                 /*
    5214                  * The actual configuration is done through CFGM extra data
    5215                  * for each inserted driver separately.
    5216                  */
    5217                 InsertConfigString(pLunL0, "Driver", "DiskIntegrity");
    5218                 InsertConfigNode(pLunL0, "Config", &pCfg);
    5219                 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
    5220             }
    5221 
    5222             InsertConfigString(pLunL0, "Driver", "VD");
    5223             InsertConfigNode(pLunL0, "Config", &pCfg);
    5224             switch (enmType)
    5225             {
    5226                 case DeviceType_DVD:
    5227                     InsertConfigString(pCfg, "Type", "DVD");
    5228                     InsertConfigInteger(pCfg, "Mountable", 1);
    5229                     break;
    5230                 case DeviceType_Floppy:
    5231                     InsertConfigString(pCfg, "Type", "Floppy 1.44");
    5232                     InsertConfigInteger(pCfg, "Mountable", 1);
    5233                     break;
    5234                 case DeviceType_HardDisk:
    5235                 default:
    5236                     InsertConfigString(pCfg, "Type", "HardDisk");
    5237                     InsertConfigInteger(pCfg, "Mountable", 0);
    5238             }
    5239 
    5240             if (    ptrMedium.isNotNull()
    5241                 && (   enmType == DeviceType_DVD
    5242                     || enmType == DeviceType_Floppy)
    5243                )
    5244             {
    5245                 // if this medium represents an ISO image and this image is inaccessible,
    5246                 // the ignore it instead of causing a failure; this can happen when we
    5247                 // restore a VM state and the ISO has disappeared, e.g. because the Guest
    5248                 // Additions were mounted and the user upgraded VirtualBox. Previously
    5249                 // we failed on startup, but that's not good because the only way out then
    5250                 // would be to discard the VM state...
    5251                 MediumState_T mediumState;
    5252                 hrc = ptrMedium->RefreshState(&mediumState);                                H();
    5253                 if (mediumState == MediumState_Inaccessible)
    5254                 {
    5255                     Bstr loc;
    5256                     hrc = ptrMedium->COMGETTER(Location)(loc.asOutParam());                 H();
    5257                     i_atVMRuntimeErrorCallbackF(0, "DvdOrFloppyImageInaccessible",
    5258                                                 N_("The image file '%ls' is inaccessible and is being ignored. "
    5259                                                    "Please select a different image file for the virtual %s drive."),
    5260                                                 loc.raw(),
    5261                                                 enmType == DeviceType_DVD ? "DVD" : "floppy");
    5262                     ptrMedium.setNull();
    5263                 }
    5264             }
    5265 
    5266             if (ptrMedium.isNotNull())
    5267             {
    5268                 /* Start with length of parent chain, as the list is reversed */
    5269                 unsigned uImage = 0;
    5270                 ComPtr<IMedium> ptrTmp = ptrMedium;
    5271                 while (ptrTmp.isNotNull())
    5272                 {
    5273                     uImage++;
    5274                     ComPtr<IMedium> ptrParent;
    5275                     hrc = ptrTmp->COMGETTER(Parent)(ptrParent.asOutParam());               H();
    5276                     ptrTmp = ptrParent;
    5277                 }
    5278                 /* Index of last image */
    5279                 uImage--;
    5280 
    5281 # ifdef VBOX_WITH_EXTPACK
    5282                 if (mptrExtPackManager->i_isExtPackUsable(ORACLE_PUEL_EXTPACK_NAME))
    5283                 {
    5284                     /* Configure loading the VDPlugin. */
    5285                     static const char s_szVDPlugin[] = "VDPluginCrypt";
    5286                     PCFGMNODE pCfgPlugins = NULL;
    5287                     PCFGMNODE pCfgPlugin = NULL;
    5288                     Utf8Str strPlugin;
    5289                     hrc = mptrExtPackManager->i_getLibraryPathForExtPack(s_szVDPlugin, ORACLE_PUEL_EXTPACK_NAME, &strPlugin);
    5290                     // Don't fail, this is optional!
    5291                     if (SUCCEEDED(hrc))
    5292                     {
    5293                         InsertConfigNode(pCfg, "Plugins", &pCfgPlugins);
    5294                         InsertConfigNode(pCfgPlugins, s_szVDPlugin, &pCfgPlugin);
    5295                         InsertConfigString(pCfgPlugin, "Path", strPlugin);
    5296                     }
    5297                 }
    5298 # endif
    5299 
    5300                 hrc = ptrMedium->COMGETTER(Location)(bstr.asOutParam());                    H();
    5301                 InsertConfigString(pCfg, "Path", bstr);
    5302 
    5303                 hrc = ptrMedium->COMGETTER(Format)(bstr.asOutParam());                      H();
    5304                 InsertConfigString(pCfg, "Format", bstr);
    5305 
    5306                 if (mediumType == MediumType_Readonly)
    5307                     InsertConfigInteger(pCfg, "ReadOnly", 1);
    5308                 else if (enmType == DeviceType_Floppy)
    5309                     InsertConfigInteger(pCfg, "MaybeReadOnly", 1);
    5310 
    5311                 /* Start without exclusive write access to the images. */
    5312                 /** @todo Live Migration: I don't quite like this, we risk screwing up when
    5313                  *        we're resuming the VM if some 3rd dude have any of the VDIs open
    5314                  *        with write sharing denied.  However, if the two VMs are sharing a
    5315                  *        image it really is necessary....
    5316                  *
    5317                  *        So, on the "lock-media" command, the target teleporter should also
    5318                  *        make DrvVD undo TempReadOnly.  It gets interesting if we fail after
    5319                  *        that. Grumble. */
    5320                 if (   enmType == DeviceType_HardDisk
    5321                     && aMachineState == MachineState_TeleportingIn)
    5322                     InsertConfigInteger(pCfg, "TempReadOnly", 1);
    5323 
    5324                 /* Flag for opening the medium for sharing between VMs. This
    5325                  * is done at the moment only for the first (and only) medium
    5326                  * in the chain, as shared media can have no diffs. */
    5327                 if (mediumType == MediumType_Shareable)
    5328                     InsertConfigInteger(pCfg, "Shareable", 1);
    5329 
    5330                 if (!fUseHostIOCache)
    5331                 {
    5332                     InsertConfigInteger(pCfg, "UseNewIo", 1);
    5333                     /*
    5334                      * Activate the builtin I/O cache for harddisks only.
    5335                      * It caches writes only which doesn't make sense for DVD drives
    5336                      * and just increases the overhead.
    5337                      */
    5338                     if (   fBuiltinIOCache
    5339                         && (enmType == DeviceType_HardDisk))
    5340                         InsertConfigInteger(pCfg, "BlockCache", 1);
    5341                 }
    5342 
    5343                 if (fSetupMerge)
    5344                 {
    5345                     InsertConfigInteger(pCfg, "SetupMerge", 1);
    5346                     if (uImage == uMergeSource)
    5347                         InsertConfigInteger(pCfg, "MergeSource", 1);
    5348                     else if (uImage == uMergeTarget)
    5349                         InsertConfigInteger(pCfg, "MergeTarget", 1);
    5350                 }
    5351 
    5352                 if (pcszBwGroup)
    5353                     InsertConfigString(pCfg, "BwGroup", pcszBwGroup);
    5354 
    5355                 if (fDiscard)
    5356                     InsertConfigInteger(pCfg, "Discard", 1);
    5357 
    5358                 if (fNonRotational)
    5359                     InsertConfigInteger(pCfg, "NonRotationalMedium", 1);
    5360 
    5361                 /* Pass all custom parameters. */
    5362                 bool fHostIP = true;
    5363                 bool fEncrypted = false;
    5364                 hrc = i_configMediumProperties(pCfg, ptrMedium, &fHostIP, &fEncrypted); H();
    5365 
    5366                 /* Create an inverted list of parents. */
    5367                 uImage--;
    5368                 ComPtr<IMedium> ptrParentMedium = ptrMedium;
    5369                 for (PCFGMNODE pParent = pCfg;; uImage--)
    5370                 {
    5371                     ComPtr<IMedium> ptrCurMedium;
    5372                     hrc = ptrParentMedium->COMGETTER(Parent)(ptrCurMedium.asOutParam());    H();
    5373                     if (ptrCurMedium.isNull())
    5374                         break;
    5375 
    5376                     PCFGMNODE pCur;
    5377                     InsertConfigNode(pParent, "Parent", &pCur);
    5378                     hrc = ptrCurMedium->COMGETTER(Location)(bstr.asOutParam()); H();
    5379                     InsertConfigString(pCur, "Path", bstr);
    5380 
    5381                     hrc = ptrCurMedium->COMGETTER(Format)(bstr.asOutParam());  H();
    5382                     InsertConfigString(pCur, "Format", bstr);
    5383 
    5384                     if (fSetupMerge)
    5385                     {
    5386                         if (uImage == uMergeSource)
    5387                             InsertConfigInteger(pCur, "MergeSource", 1);
    5388                         else if (uImage == uMergeTarget)
    5389                             InsertConfigInteger(pCur, "MergeTarget", 1);
    5390                     }
    5391 
    5392                     /* Configure medium properties. */
    5393                     hrc = i_configMediumProperties(pCur, ptrCurMedium, &fHostIP, &fEncrypted); H();
    5394 
    5395                     /* next */
    5396                     pParent = pCur;
    5397                     ptrParentMedium = ptrCurMedium;
    5398                 }
    5399 
    5400                 /* Custom code: put marker to not use host IP stack to driver
    5401                  * configuration node. Simplifies life of DrvVD a bit. */
    5402                 if (!fHostIP)
    5403                     InsertConfigInteger(pCfg, "HostIPStack", 0);
    5404 
    5405                 if (fEncrypted)
    5406                     m_cDisksEncrypted++;
    5407             }
    5408             else
    5409             {
    5410                 /* Set empty drive flag for DVD or floppy without media. */
    5411                 if (   enmType == DeviceType_DVD
    5412                     || enmType == DeviceType_Floppy)
    5413                     InsertConfigInteger(pCfg, "EmptyDrive", 1);
    5414             }
    5415         }
    5416 #undef H
    5417     }
    5418     catch (ConfigError &x)
    5419     {
    5420         // InsertConfig threw something:
    5421         return x.m_vrc;
    5422     }
    5423 
    5424     return VINF_SUCCESS;
    5425 }
    5426 
    5427 /**
    5428  * Adds the medium properties to the CFGM tree.
    5429  *
    5430  * @returns VBox status code.
    5431  * @param   pCur        The current CFGM node.
    5432  * @param   pMedium     The medium object to configure.
    5433  * @param   pfHostIP    Where to return the value of the \"HostIPStack\" property if found.
    5434  * @param   pfEncrypted Where to return whether the medium is encrypted.
    5435  */
    5436 int Console::i_configMediumProperties(PCFGMNODE pCur, IMedium *pMedium, bool *pfHostIP, bool *pfEncrypted)
    5437 {
    5438     /* Pass all custom parameters. */
    5439     SafeArray<BSTR> aNames;
    5440     SafeArray<BSTR> aValues;
    5441     HRESULT hrc = pMedium->GetProperties(NULL, ComSafeArrayAsOutParam(aNames), ComSafeArrayAsOutParam(aValues));
    5442     if (   SUCCEEDED(hrc)
    5443         && aNames.size() != 0)
    5444     {
    5445         PCFGMNODE pVDC;
    5446         InsertConfigNode(pCur, "VDConfig", &pVDC);
    5447         for (size_t ii = 0; ii < aNames.size(); ++ii)
    5448         {
    5449             if (aValues[ii] && *aValues[ii])
    5450             {
    5451                 Utf8Str const strName  = aNames[ii];
    5452                 Utf8Str const strValue = aValues[ii];
    5453                 size_t offSlash = strName.find("/", 0);
    5454                 if (   offSlash != strName.npos
    5455                     && !strName.startsWith("Special/"))
    5456                 {
    5457                     com::Utf8Str strFilter;
    5458                     hrc = strFilter.assignEx(strName, 0, offSlash);
    5459                     if (FAILED(hrc))
    5460                         break;
    5461 
    5462                     com::Utf8Str strKey;
    5463                     hrc = strKey.assignEx(strName, offSlash + 1, strName.length() - offSlash - 1); /* Skip slash */
    5464                     if (FAILED(hrc))
    5465                         break;
    5466 
    5467                     PCFGMNODE pCfgFilterConfig = mpVMM->pfnCFGMR3GetChild(pVDC, strFilter.c_str());
    5468                     if (!pCfgFilterConfig)
    5469                         InsertConfigNode(pVDC, strFilter.c_str(), &pCfgFilterConfig);
    5470 
    5471                     InsertConfigString(pCfgFilterConfig, strKey.c_str(), strValue);
    5472                 }
    5473                 else
    5474                 {
    5475                     InsertConfigString(pVDC, strName.c_str(), strValue);
    5476                     if (    strName.compare("HostIPStack") == 0
    5477                         &&  strValue.compare("0") == 0)
    5478                         *pfHostIP = false;
    5479                 }
    5480 
    5481                 if (   strName.compare("CRYPT/KeyId") == 0
    5482                     && pfEncrypted)
    5483                     *pfEncrypted = true;
    5484             }
    5485         }
    5486     }
    5487 
    5488     return hrc;
    5489 }
    5490 
    5491 
    5492 /**
    5493  * Configure proxy parameters the Network configuration tree.
    5494  *
    5495  * Parameters may differ depending on the IP address being accessed.
    5496  *
    5497  * @returns VBox status code.
    5498  *
    5499  * @param   virtualBox          The VirtualBox object.
    5500  * @param   pCfg                Configuration node for the driver.
    5501  * @param   pcszPrefix          The prefix for CFGM parameters: "Primary" or "Secondary".
    5502  * @param   strIpAddr           The public IP address to be accessed via a proxy.
    5503  *
    5504  * @thread EMT
    5505  */
    5506 int Console::i_configProxy(ComPtr<IVirtualBox> virtualBox, PCFGMNODE pCfg, const char *pcszPrefix, const com::Utf8Str &strIpAddr)
    5507 {
    5508 /** @todo r=bird: This code doesn't handle cleanup correctly and may leak
    5509  *        when hitting errors or throwing exceptions (bad_alloc). */
    5510     RTHTTPPROXYINFO ProxyInfo;
    5511     ComPtr<ISystemProperties> systemProperties;
    5512     ProxyMode_T enmProxyMode;
    5513     HRESULT hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
    5514     if (FAILED(hrc))
    5515     {
    5516         LogRel(("CLOUD-NET: Failed to obtain system properties. hrc=%x\n", hrc));
    5517         return false;
    5518     }
    5519     hrc = systemProperties->COMGETTER(ProxyMode)(&enmProxyMode);
    5520     if (FAILED(hrc))
    5521     {
    5522         LogRel(("CLOUD-NET: Failed to obtain default machine folder. hrc=%x\n", hrc));
    5523         return VERR_INTERNAL_ERROR;
    5524     }
    5525 
    5526     RTHTTP hHttp;
    5527     int vrc = RTHttpCreate(&hHttp);
    5528     if (RT_FAILURE(vrc))
    5529     {
    5530         LogRel(("CLOUD-NET: Failed to create HTTP context (vrc=%Rrc)\n", vrc));
    5531         return vrc;
    5532     }
    5533 
    5534     char *pszProxyType = NULL;
    5535 
    5536     if (enmProxyMode == ProxyMode_Manual)
    5537     {
    5538         /*
    5539          * Unfortunately we cannot simply call RTHttpSetProxyByUrl because it never
    5540          * exposes proxy settings. Calling RTHttpQueryProxyInfoForUrl afterward
    5541          * won't help either as it uses system-wide proxy settings instead of
    5542          * parameters we would have set with RTHttpSetProxyByUrl. Hence we parse
    5543          * proxy URL ourselves here.
    5544          */
    5545         Bstr proxyUrl;
    5546         hrc = systemProperties->COMGETTER(ProxyURL)(proxyUrl.asOutParam());
    5547         if (FAILED(hrc))
    5548         {
    5549             LogRel(("CLOUD-NET: Failed to obtain proxy URL. hrc=%x\n", hrc));
    5550             return false;
    5551         }
    5552         Utf8Str strProxyUrl = proxyUrl;
    5553         if (!strProxyUrl.contains("://"))
    5554             strProxyUrl = "http://" + strProxyUrl;
    5555         const char *pcszProxyUrl = strProxyUrl.c_str();
    5556         RTURIPARSED Parsed;
    5557         vrc = RTUriParse(pcszProxyUrl, &Parsed);
    5558         if (RT_FAILURE(vrc))
    5559         {
    5560             LogRel(("CLOUD-NET: Failed to parse proxy URL: %ls (vrc=%Rrc)\n", proxyUrl.raw(), vrc));
    5561             return false;
    5562         }
    5563 
    5564         pszProxyType = RTUriParsedScheme(pcszProxyUrl, &Parsed);
    5565         if (!pszProxyType)
    5566         {
    5567             LogRel(("CLOUD-NET: Failed to get proxy scheme from proxy URL: %s\n", pcszProxyUrl));
    5568             return false;
    5569         }
    5570         RTStrToUpper(pszProxyType);
    5571 
    5572         ProxyInfo.pszProxyHost = RTUriParsedAuthorityHost(pcszProxyUrl, &Parsed);
    5573         if (!ProxyInfo.pszProxyHost)
    5574         {
    5575             LogRel(("CLOUD-NET: Failed to get proxy host name from proxy URL: %s\n", pcszProxyUrl));
    5576             return false;
    5577         }
    5578         ProxyInfo.uProxyPort  = RTUriParsedAuthorityPort(pcszProxyUrl, &Parsed);
    5579         if (ProxyInfo.uProxyPort == UINT32_MAX)
    5580         {
    5581             LogRel(("CLOUD-NET: Failed to get proxy port from proxy URL: %s\n", pcszProxyUrl));
    5582             return false;
    5583         }
    5584         ProxyInfo.pszProxyUsername = RTUriParsedAuthorityUsername(pcszProxyUrl, &Parsed);
    5585         ProxyInfo.pszProxyPassword = RTUriParsedAuthorityPassword(pcszProxyUrl, &Parsed);
    5586     }
    5587     else if (enmProxyMode == ProxyMode_System)
    5588     {
    5589         vrc = RTHttpUseSystemProxySettings(hHttp);
    5590         if (RT_FAILURE(vrc))
    5591         {
    5592             LogRel(("%s: RTHttpUseSystemProxySettings() failed: %Rrc", __FUNCTION__, vrc));
    5593             RTHttpDestroy(hHttp);
    5594             return vrc;
    5595         }
    5596         vrc = RTHttpQueryProxyInfoForUrl(hHttp, ("http://" + strIpAddr).c_str(), &ProxyInfo);
    5597         RTHttpDestroy(hHttp);
    5598         if (RT_FAILURE(vrc))
    5599         {
    5600             LogRel(("CLOUD-NET: Failed to get proxy for %s (vrc=%Rrc)\n", strIpAddr.c_str(), vrc));
    5601             return vrc;
    5602         }
    5603 
    5604         switch (ProxyInfo.enmProxyType)
    5605         {
    5606             case RTHTTPPROXYTYPE_NOPROXY:
    5607                 /* Nothing to do */
    5608                 return VINF_SUCCESS;
    5609             case RTHTTPPROXYTYPE_HTTP:
    5610                 pszProxyType = RTStrDup("HTTP");
    5611                 break;
    5612             case RTHTTPPROXYTYPE_HTTPS:
    5613             case RTHTTPPROXYTYPE_SOCKS4:
    5614             case RTHTTPPROXYTYPE_SOCKS5:
    5615                 /* break; -- Fall through until support is implemented */
    5616             case RTHTTPPROXYTYPE_UNKNOWN:
    5617             case RTHTTPPROXYTYPE_INVALID:
    5618             case RTHTTPPROXYTYPE_END:
    5619             case RTHTTPPROXYTYPE_32BIT_HACK:
    5620                 LogRel(("CLOUD-NET: Unsupported proxy type %u\n", ProxyInfo.enmProxyType));
    5621                 RTHttpFreeProxyInfo(&ProxyInfo);
    5622                 return VERR_INVALID_PARAMETER;
    5623         }
    5624     }
    5625     else
    5626     {
    5627         Assert(enmProxyMode == ProxyMode_NoProxy);
    5628         return VINF_SUCCESS;
    5629     }
    5630 
    5631     /* Resolve proxy host name to IP address if necessary */
    5632     RTNETADDR addr;
    5633     RTSocketParseInetAddress(ProxyInfo.pszProxyHost, ProxyInfo.uProxyPort, &addr);
    5634     if (addr.enmType != RTNETADDRTYPE_IPV4)
    5635     {
    5636         LogRel(("CLOUD-NET: Unsupported address type %u\n", addr.enmType));
    5637         RTHttpFreeProxyInfo(&ProxyInfo);
    5638         return VERR_INVALID_PARAMETER;
    5639     }
    5640 
    5641     InsertConfigString(      pCfg, Utf8StrFmt("%sProxyType",     pcszPrefix).c_str(), pszProxyType);
    5642     InsertConfigInteger(     pCfg, Utf8StrFmt("%sProxyPort",     pcszPrefix).c_str(), ProxyInfo.uProxyPort);
    5643     if (ProxyInfo.pszProxyHost)
    5644         InsertConfigStringF( pCfg, Utf8StrFmt("%sProxyHost",     pcszPrefix).c_str(), "%RTnaipv4", addr.uAddr.IPv4);
    5645     if (ProxyInfo.pszProxyUsername)
    5646         InsertConfigString(  pCfg, Utf8StrFmt("%sProxyUser",     pcszPrefix).c_str(), ProxyInfo.pszProxyUsername);
    5647     if (ProxyInfo.pszProxyPassword)
    5648         InsertConfigPassword(pCfg, Utf8StrFmt("%sProxyPassword", pcszPrefix).c_str(), ProxyInfo.pszProxyPassword);
    5649 
    5650     RTHttpFreeProxyInfo(&ProxyInfo);
    5651     RTStrFree(pszProxyType);
    5652     return vrc;
    5653 }
    5654 
    5655 
    5656 /**
    5657  * Construct the Network configuration tree
    5658  *
    5659  * @returns VBox status code.
    5660  *
    5661  * @param   pszDevice           The PDM device name.
    5662  * @param   uInstance           The PDM device instance.
    5663  * @param   uLun                The PDM LUN number of the drive.
    5664  * @param   aNetworkAdapter     The network adapter whose attachment needs to be changed
    5665  * @param   pCfg                Configuration node for the device
    5666  * @param   pLunL0              To store the pointer to the LUN#0.
    5667  * @param   pInst               The instance CFGM node
    5668  * @param   fAttachDetach       To determine if the network attachment should
    5669  *                              be attached/detached after/before
    5670  *                              configuration.
    5671  * @param   fIgnoreConnectFailure
    5672  *                              True if connection failures should be ignored
    5673  *                              (makes only sense for bridged/host-only networks).
    5674  * @param   pUVM                The usermode VM handle.
    5675  * @param   pVMM                The VMM vtable.
    5676  *
    5677  * @note   Locks this object for writing.
    5678  * @thread EMT
    5679  */
    5680 int Console::i_configNetwork(const char *pszDevice,
    5681                              unsigned uInstance,
    5682                              unsigned uLun,
    5683                              INetworkAdapter *aNetworkAdapter,
    5684                              PCFGMNODE pCfg,
    5685                              PCFGMNODE pLunL0,
    5686                              PCFGMNODE pInst,
    5687                              bool fAttachDetach,
    5688                              bool fIgnoreConnectFailure,
    5689                              PUVM pUVM,
    5690                              PCVMMR3VTABLE pVMM)
    5691 {
    5692     RT_NOREF(fIgnoreConnectFailure);
    5693     AutoCaller autoCaller(this);
    5694     AssertComRCReturn(autoCaller.hrc(), VERR_ACCESS_DENIED);
    5695 
    5696     // InsertConfig* throws
    5697     try
    5698     {
    5699         int vrc = VINF_SUCCESS;
    5700         HRESULT hrc;
    5701         Bstr bstr;
    5702 
    5703 #ifdef VBOX_WITH_CLOUD_NET
    5704         /* We'll need device's pCfg for cloud attachments */
    5705         PCFGMNODE pDevCfg = pCfg;
    5706 #endif /* VBOX_WITH_CLOUD_NET */
    5707 
    5708 #define H()         AssertLogRelMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
    5709 
    5710         /*
    5711          * Locking the object before doing VMR3* calls is quite safe here, since
    5712          * we're on EMT. Write lock is necessary because we indirectly modify the
    5713          * meAttachmentType member.
    5714          */
    5715         AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    5716 
    5717         ComPtr<IMachine> pMachine = i_machine();
    5718 
    5719         ComPtr<IVirtualBox> virtualBox;
    5720         hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam());                         H();
    5721 
    5722         ComPtr<IHost> host;
    5723         hrc = virtualBox->COMGETTER(Host)(host.asOutParam());                               H();
    5724 
    5725         BOOL fSniffer;
    5726         hrc = aNetworkAdapter->COMGETTER(TraceEnabled)(&fSniffer);                          H();
    5727 
    5728         NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy;
    5729         hrc = aNetworkAdapter->COMGETTER(PromiscModePolicy)(&enmPromiscModePolicy);         H();
    5730         const char *pszPromiscuousGuestPolicy;
    5731         switch (enmPromiscModePolicy)
    5732         {
    5733             case NetworkAdapterPromiscModePolicy_Deny:          pszPromiscuousGuestPolicy = "deny"; break;
    5734             case NetworkAdapterPromiscModePolicy_AllowNetwork:  pszPromiscuousGuestPolicy = "allow-network"; break;
    5735             case NetworkAdapterPromiscModePolicy_AllowAll:      pszPromiscuousGuestPolicy = "allow-all"; break;
    5736             default: AssertFailedReturn(VERR_INTERNAL_ERROR_4);
    5737         }
    5738 
    5739         if (fAttachDetach)
    5740         {
    5741             vrc = pVMM->pfnPDMR3DeviceDetach(pUVM, pszDevice, uInstance, uLun, 0 /*fFlags*/);
    5742             if (vrc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN)
    5743                 vrc = VINF_SUCCESS;
    5744             AssertLogRelRCReturn(vrc, vrc);
    5745 
    5746             /* Nuke anything which might have been left behind. */
    5747             pVMM->pfnCFGMR3RemoveNode(pVMM->pfnCFGMR3GetChildF(pInst, "LUN#%u", uLun));
    5748         }
    5749 
    5750         Bstr networkName, trunkName, trunkType;
    5751         NetworkAttachmentType_T eAttachmentType;
    5752         hrc = aNetworkAdapter->COMGETTER(AttachmentType)(&eAttachmentType);                 H();
    5753 
    5754 #ifdef VBOX_WITH_NETSHAPER
    5755         ComObjPtr<IBandwidthGroup> pBwGroup;
    5756         Bstr bstrBwGroup;
    5757         hrc = aNetworkAdapter->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam());            H();
    5758 
    5759         if (!pBwGroup.isNull())
    5760         {
    5761             hrc = pBwGroup->COMGETTER(Name)(bstrBwGroup.asOutParam());                      H();
    5762         }
    5763 #endif /* VBOX_WITH_NETSHAPER */
    5764 
    5765         AssertMsg(uLun == 0, ("Network attachments with LUN > 0 are not supported yet\n"));
    5766         InsertConfigNodeF(pInst, &pLunL0, "LUN#%u", uLun);
    5767 
    5768         /*
    5769          * Do not insert neither a shaper nor a sniffer if we are not attached to anything.
    5770          * This way we can easily detect if we are attached to anything at the device level.
    5771          */
    5772 #ifdef VBOX_WITH_NETSHAPER
    5773         if (bstrBwGroup.isNotEmpty() && eAttachmentType != NetworkAttachmentType_Null)
    5774         {
    5775             InsertConfigString(pLunL0, "Driver", "NetShaper");
    5776             InsertConfigNode(pLunL0, "Config", &pCfg);
    5777             InsertConfigString(pCfg, "BwGroup", bstrBwGroup);
    5778             InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
    5779         }
    5780 #endif /* VBOX_WITH_NETSHAPER */
    5781 
    5782         if (fSniffer && eAttachmentType != NetworkAttachmentType_Null)
    5783         {
    5784             InsertConfigString(pLunL0, "Driver", "NetSniffer");
    5785             InsertConfigNode(pLunL0, "Config", &pCfg);
    5786             hrc = aNetworkAdapter->COMGETTER(TraceFile)(bstr.asOutParam());             H();
    5787             if (!bstr.isEmpty()) /* check convention for indicating default file. */
    5788                 InsertConfigString(pCfg, "File", bstr);
    5789             InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
    5790         }
    5791 
    5792         switch (eAttachmentType)
    5793         {
    5794             case NetworkAttachmentType_Null:
    5795                 break;
    5796 
    5797             case NetworkAttachmentType_NAT:
    5798             {
    5799                 ComPtr<INATEngine> natEngine;
    5800                 hrc = aNetworkAdapter->COMGETTER(NATEngine)(natEngine.asOutParam());        H();
    5801                 InsertConfigString(pLunL0, "Driver", "NAT");
    5802                 InsertConfigNode(pLunL0, "Config", &pCfg);
    5803 
    5804                 /* Configure TFTP prefix and boot filename. */
    5805                 hrc = virtualBox->COMGETTER(HomeFolder)(bstr.asOutParam());                 H();
    5806                 if (!bstr.isEmpty())
    5807                     InsertConfigStringF(pCfg, "TFTPPrefix", "%ls%c%s", bstr.raw(), RTPATH_DELIMITER, "TFTP");
    5808                 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam());                         H();
    5809                 InsertConfigStringF(pCfg, "BootFile", "%ls.pxe", bstr.raw());
    5810 
    5811                 hrc = natEngine->COMGETTER(Network)(bstr.asOutParam());                     H();
    5812                 if (!bstr.isEmpty())
    5813                     InsertConfigString(pCfg, "Network", bstr);
    5814                 else
    5815                 {
    5816                     ULONG uSlot;
    5817                     hrc = aNetworkAdapter->COMGETTER(Slot)(&uSlot);                         H();
    5818                     InsertConfigStringF(pCfg, "Network", "10.0.%d.0/24", uSlot+2);
    5819                 }
    5820                 hrc = natEngine->COMGETTER(HostIP)(bstr.asOutParam());                      H();
    5821                 if (!bstr.isEmpty())
    5822                     InsertConfigString(pCfg, "BindIP", bstr);
    5823                 ULONG mtu = 0;
    5824                 ULONG sockSnd = 0;
    5825                 ULONG sockRcv = 0;
    5826                 ULONG tcpSnd = 0;
    5827                 ULONG tcpRcv = 0;
    5828                 hrc = natEngine->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv); H();
    5829                 if (mtu)
    5830                     InsertConfigInteger(pCfg, "SlirpMTU", mtu);
    5831                 if (sockRcv)
    5832                     InsertConfigInteger(pCfg, "SockRcv", sockRcv);
    5833                 if (sockSnd)
    5834                     InsertConfigInteger(pCfg, "SockSnd", sockSnd);
    5835                 if (tcpRcv)
    5836                     InsertConfigInteger(pCfg, "TcpRcv", tcpRcv);
    5837                 if (tcpSnd)
    5838                     InsertConfigInteger(pCfg, "TcpSnd", tcpSnd);
    5839                 hrc = natEngine->COMGETTER(TFTPPrefix)(bstr.asOutParam());                  H();
    5840                 if (!bstr.isEmpty())
    5841                 {
    5842                     RemoveConfigValue(pCfg, "TFTPPrefix");
    5843                     InsertConfigString(pCfg, "TFTPPrefix", bstr);
    5844                 }
    5845                 hrc = natEngine->COMGETTER(TFTPBootFile)(bstr.asOutParam());                H();
    5846                 if (!bstr.isEmpty())
    5847                 {
    5848                     RemoveConfigValue(pCfg, "BootFile");
    5849                     InsertConfigString(pCfg, "BootFile", bstr);
    5850                 }
    5851                 hrc = natEngine->COMGETTER(TFTPNextServer)(bstr.asOutParam());              H();
    5852                 if (!bstr.isEmpty())
    5853                     InsertConfigString(pCfg, "NextServer", bstr);
    5854                 BOOL fDNSFlag;
    5855                 hrc = natEngine->COMGETTER(DNSPassDomain)(&fDNSFlag);                       H();
    5856                 InsertConfigInteger(pCfg, "PassDomain", fDNSFlag);
    5857                 hrc = natEngine->COMGETTER(DNSProxy)(&fDNSFlag);                            H();
    5858                 InsertConfigInteger(pCfg, "DNSProxy", fDNSFlag);
    5859                 hrc = natEngine->COMGETTER(DNSUseHostResolver)(&fDNSFlag);                  H();
    5860                 InsertConfigInteger(pCfg, "UseHostResolver", fDNSFlag);
    5861 
    5862                 ULONG aliasMode;
    5863                 hrc = natEngine->COMGETTER(AliasMode)(&aliasMode);                          H();
    5864                 InsertConfigInteger(pCfg, "AliasMode", aliasMode);
    5865 
    5866                 BOOL fLocalhostReachable;
    5867                 hrc = natEngine->COMGETTER(LocalhostReachable)(&fLocalhostReachable);       H();
    5868                 InsertConfigInteger(pCfg, "LocalhostReachable", fLocalhostReachable);
    5869 
    5870                 /* port-forwarding */
    5871                 SafeArray<BSTR> pfs;
    5872                 hrc = natEngine->COMGETTER(Redirects)(ComSafeArrayAsOutParam(pfs));         H();
    5873 
    5874                 PCFGMNODE pPFTree = NULL;
    5875                 if (pfs.size() > 0)
    5876                     InsertConfigNode(pCfg, "PortForwarding", &pPFTree);
    5877 
    5878                 for (unsigned int i = 0; i < pfs.size(); ++i)
    5879                 {
    5880                     PCFGMNODE pPF = NULL; /* /Devices/Dev/.../Config/PortForwarding/$n/ */
    5881 
    5882                     uint16_t port = 0;
    5883                     Utf8Str utf = pfs[i];
    5884                     Utf8Str strName;
    5885                     Utf8Str strProto;
    5886                     Utf8Str strHostPort;
    5887                     Utf8Str strHostIP;
    5888                     Utf8Str strGuestPort;
    5889                     Utf8Str strGuestIP;
    5890                     size_t pos, ppos;
    5891                     pos = ppos = 0;
    5892 #define ITERATE_TO_NEXT_TERM(res, str, pos, ppos) \
    5893     { \
    5894         pos = str.find(",", ppos); \
    5895         if (pos == Utf8Str::npos) \
    5896         { \
    5897             Log(( #res " extracting from %s is failed\n", str.c_str())); \
    5898             continue; \
    5899         } \
    5900         res = str.substr(ppos, pos - ppos); \
    5901         Log2((#res " %s pos:%d, ppos:%d\n", res.c_str(), pos, ppos)); \
    5902         ppos = pos + 1; \
    5903     } /* no do { ... } while because of 'continue' */
    5904                     ITERATE_TO_NEXT_TERM(strName, utf, pos, ppos);
    5905                     ITERATE_TO_NEXT_TERM(strProto, utf, pos, ppos);
    5906                     ITERATE_TO_NEXT_TERM(strHostIP, utf, pos, ppos);
    5907                     ITERATE_TO_NEXT_TERM(strHostPort, utf, pos, ppos);
    5908                     ITERATE_TO_NEXT_TERM(strGuestIP, utf, pos, ppos);
    5909                     strGuestPort = utf.substr(ppos, utf.length() - ppos);
    5910 #undef ITERATE_TO_NEXT_TERM
    5911 
    5912                     uint32_t proto = strProto.toUInt32();
    5913                     bool fValid = true;
    5914                     switch (proto)
    5915                     {
    5916                         case NATProtocol_UDP:
    5917                             strProto = "UDP";
    5918                             break;
    5919                         case NATProtocol_TCP:
    5920                             strProto = "TCP";
    5921                             break;
    5922                         default:
    5923                             fValid = false;
    5924                     }
    5925                     /* continue with next rule if no valid proto was passed */
    5926                     if (!fValid)
    5927                         continue;
    5928 
    5929                     InsertConfigNodeF(pPFTree, &pPF, "%u", i);
    5930 
    5931                     if (!strName.isEmpty())
    5932                         InsertConfigString(pPF, "Name", strName);
    5933 
    5934                     InsertConfigString(pPF, "Protocol", strProto);
    5935 
    5936                     if (!strHostIP.isEmpty())
    5937                         InsertConfigString(pPF, "BindIP", strHostIP);
    5938 
    5939                     if (!strGuestIP.isEmpty())
    5940                         InsertConfigString(pPF, "GuestIP", strGuestIP);
    5941 
    5942                     port = RTStrToUInt16(strHostPort.c_str());
    5943                     if (port)
    5944                         InsertConfigInteger(pPF, "HostPort", port);
    5945 
    5946                     port = RTStrToUInt16(strGuestPort.c_str());
    5947                     if (port)
    5948                         InsertConfigInteger(pPF, "GuestPort", port);
    5949                 }
    5950                 break;
    5951             }
    5952 
    5953             case NetworkAttachmentType_Bridged:
    5954             {
    5955 #if (defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)) && !defined(VBOX_WITH_NETFLT)
    5956                 hrc = i_attachToTapInterface(aNetworkAdapter);
    5957                 if (FAILED(hrc))
    5958                 {
    5959                     switch (hrc)
    5960                     {
    5961                         case E_ACCESSDENIED:
    5962                             return pVMM->pfnVMR3SetError(pUVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS,  N_(
    5963                                                          "Failed to open '/dev/net/tun' for read/write access. Please check the "
    5964                                                          "permissions of that node. Either run 'chmod 0666 /dev/net/tun' or "
    5965                                                          "change the group of that node and make yourself a member of that group. "
    5966                                                          "Make sure that these changes are permanent, especially if you are "
    5967                                                          "using udev"));
    5968                         default:
    5969                             AssertMsgFailed(("Could not attach to host interface! Bad!\n"));
    5970                             return pVMM->pfnVMR3SetError(pUVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS,
    5971                                                          N_("Failed to initialize Host Interface Networking"));
    5972                     }
    5973                 }
    5974 
    5975                 Assert((intptr_t)maTapFD[uInstance] >= 0);
    5976                 if ((intptr_t)maTapFD[uInstance] >= 0)
    5977                 {
    5978                     InsertConfigString(pLunL0, "Driver", "HostInterface");
    5979                     InsertConfigNode(pLunL0, "Config", &pCfg);
    5980                     InsertConfigInteger(pCfg, "FileHandle", (intptr_t)maTapFD[uInstance]);
    5981                 }
    5982 
    5983 #elif defined(VBOX_WITH_NETFLT)
    5984                 /*
    5985                  * This is the new VBoxNetFlt+IntNet stuff.
    5986                  */
    5987                 Bstr BridgedIfName;
    5988                 hrc = aNetworkAdapter->COMGETTER(BridgedInterface)(BridgedIfName.asOutParam());
    5989                 if (FAILED(hrc))
    5990                 {
    5991                     LogRel(("NetworkAttachmentType_Bridged: COMGETTER(BridgedInterface) failed, hrc (0x%x)\n", hrc));
    5992                     H();
    5993                 }
    5994 
    5995                 Utf8Str BridgedIfNameUtf8(BridgedIfName);
    5996                 const char *pszBridgedIfName = BridgedIfNameUtf8.c_str();
    5997 
    5998                 ComPtr<IHostNetworkInterface> hostInterface;
    5999                 hrc = host->FindHostNetworkInterfaceByName(BridgedIfName.raw(),
    6000                                                            hostInterface.asOutParam());
    6001                 if (!SUCCEEDED(hrc))
    6002                 {
    6003                     AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: FindByName failed, hrc=%Rhrc (0x%x)\n", hrc, hrc));
    6004                     return pVMM->pfnVMR3SetError(pUVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
    6005                                                  N_("Nonexistent host networking interface, name '%ls'"),
    6006                                                  BridgedIfName.raw());
    6007                 }
    6008 
    6009 # if defined(RT_OS_DARWIN)
    6010                 /* The name is in the format 'ifX: long name', chop it off at the colon. */
    6011                 char szTrunk[INTNET_MAX_TRUNK_NAME];
    6012                 RTStrCopy(szTrunk, sizeof(szTrunk), pszBridgedIfName);
    6013                 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk));
    6014 // Quick fix for @bugref{5633}
    6015 //                 if (!pszColon)
    6016 //                 {
    6017 //                     /*
    6018 //                     * Dynamic changing of attachment causes an attempt to configure
    6019 //                     * network with invalid host adapter (as it is must be changed before
    6020 //                     * the attachment), calling Detach here will cause a deadlock.
    6021 //                     * See @bugref{4750}.
    6022 //                     * hrc = aNetworkAdapter->Detach();                                   H();
    6023 //                     */
    6024 //                     return VMSetError(VMR3GetVM(mpUVM), VERR_INTERNAL_ERROR, RT_SRC_POS,
    6025 //                                       N_("Malformed host interface networking name '%ls'"),
    6026 //                                       BridgedIfName.raw());
    6027 //                 }
    6028                 if (pszColon)
    6029                     *pszColon = '\0';
    6030                 const char *pszTrunk = szTrunk;
    6031 
    6032 # elif defined(RT_OS_SOLARIS)
    6033                 /* The name is in the format 'ifX[:1] - long name, chop it off at space. */
    6034                 char szTrunk[256];
    6035                 strlcpy(szTrunk, pszBridgedIfName, sizeof(szTrunk));
    6036                 char *pszSpace = (char *)memchr(szTrunk, ' ', sizeof(szTrunk));
    6037 
    6038                 /*
    6039                  * Currently don't bother about malformed names here for the sake of people using
    6040                  * VBoxManage and setting only the NIC name from there. If there is a space we
    6041                  * chop it off and proceed, otherwise just use whatever we've got.
    6042                  */
    6043                 if (pszSpace)
    6044                     *pszSpace = '\0';
    6045 
    6046                 /* Chop it off at the colon (zone naming eg: e1000g:1 we need only the e1000g) */
    6047                 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk));
    6048                 if (pszColon)
    6049                     *pszColon = '\0';
    6050 
    6051                 const char *pszTrunk = szTrunk;
    6052 
    6053 # elif defined(RT_OS_WINDOWS)
    6054                 HostNetworkInterfaceType_T eIfType;
    6055                 hrc = hostInterface->COMGETTER(InterfaceType)(&eIfType);
    6056                 if (FAILED(hrc))
    6057                 {
    6058                     LogRel(("NetworkAttachmentType_Bridged: COMGETTER(InterfaceType) failed, hrc (0x%x)\n", hrc));
    6059                     H();
    6060                 }
    6061 
    6062                 if (eIfType != HostNetworkInterfaceType_Bridged)
    6063                     return pVMM->pfnVMR3SetError(pUVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
    6064                                                  N_("Interface ('%ls') is not a Bridged Adapter interface"),
    6065                                                  BridgedIfName.raw());
    6066 
    6067                 hrc = hostInterface->COMGETTER(Id)(bstr.asOutParam());
    6068                 if (FAILED(hrc))
    6069                 {
    6070                     LogRel(("NetworkAttachmentType_Bridged: COMGETTER(Id) failed, hrc (0x%x)\n", hrc));
    6071                     H();
    6072                 }
    6073                 Guid hostIFGuid(bstr);
    6074 
    6075                 INetCfg *pNc;
    6076                 ComPtr<INetCfgComponent> pAdaptorComponent;
    6077                 LPWSTR pszApp;
    6078 
    6079                 hrc = VBoxNetCfgWinQueryINetCfg(&pNc, FALSE, L"VirtualBox", 10, &pszApp);
    6080                 Assert(hrc == S_OK);
    6081                 if (hrc != S_OK)
    6082                 {
    6083                     LogRel(("NetworkAttachmentType_Bridged: Failed to get NetCfg, hrc=%Rhrc (0x%x)\n", hrc, hrc));
    6084                     H();
    6085                 }
    6086 
    6087                 /* get the adapter's INetCfgComponent*/
    6088                 hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.raw(),
    6089                                                       pAdaptorComponent.asOutParam());
    6090                 if (hrc != S_OK)
    6091                 {
    6092                     VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
    6093                     LogRel(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)\n", hrc));
    6094                     H();
    6095                 }
    6096 # define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\"
    6097                 char szTrunkName[INTNET_MAX_TRUNK_NAME];
    6098                 char *pszTrunkName = szTrunkName;
    6099                 wchar_t * pswzBindName;
    6100                 hrc = pAdaptorComponent->GetBindName(&pswzBindName);
    6101                 Assert(hrc == S_OK);
    6102                 if (hrc == S_OK)
    6103                 {
    6104                     int cwBindName = (int)wcslen(pswzBindName) + 1;
    6105                     int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX);
    6106                     if (sizeof(szTrunkName) > cbFullBindNamePrefix + cwBindName)
    6107                     {
    6108                         strcpy(szTrunkName, VBOX_WIN_BINDNAME_PREFIX);
    6109                         pszTrunkName += cbFullBindNamePrefix-1;
    6110                         if (!WideCharToMultiByte(CP_ACP, 0, pswzBindName, cwBindName, pszTrunkName,
    6111                                                 sizeof(szTrunkName) - cbFullBindNamePrefix + 1, NULL, NULL))
    6112                         {
    6113                             DWORD err = GetLastError();
    6114                             hrc = HRESULT_FROM_WIN32(err);
    6115                             AssertMsgFailed(("hrc=%Rhrc %#x\n", hrc, hrc));
    6116                             AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n",
    6117                                                    hrc, hrc, err));
    6118                         }
    6119                     }
    6120                     else
    6121                     {
    6122                         AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: insufficient szTrunkName buffer space\n"));
    6123                         /** @todo set appropriate error code */
    6124                         hrc = E_FAIL;
    6125                     }
    6126 
    6127                     if (hrc != S_OK)
    6128                     {
    6129                         AssertFailed();
    6130                         CoTaskMemFree(pswzBindName);
    6131                         VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
    6132                         H();
    6133                     }
    6134 
    6135                     /* we're not freeing the bind name since we'll use it later for detecting wireless*/
    6136                 }
    6137                 else
    6138                 {
    6139                     VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
    6140                     AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)",
    6141                                            hrc));
    6142                     H();
    6143                 }
    6144 
    6145                 const char *pszTrunk = szTrunkName;
    6146                 /* we're not releasing the INetCfg stuff here since we use it later to figure out whether it is wireless */
    6147 
    6148 # elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
    6149 #  if defined(RT_OS_FREEBSD)
    6150                 /*
    6151                  * If we bridge to a tap interface open it the `old' direct way.
    6152                  * This works and performs better than bridging a physical
    6153                  * interface via the current FreeBSD vboxnetflt implementation.
    6154                  */
    6155                 if (!strncmp(pszBridgedIfName, RT_STR_TUPLE("tap"))) {
    6156                     hrc = i_attachToTapInterface(aNetworkAdapter);
    6157                     if (FAILED(hrc))
    6158                     {
    6159                         switch (hrc)
    6160                         {
    6161                             case E_ACCESSDENIED:
    6162                                 return pVMM->pfnVMR3SetError(pUVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS,  N_(
    6163                                                              "Failed to open '/dev/%s' for read/write access.  Please check the "
    6164                                                              "permissions of that node, and that the net.link.tap.user_open "
    6165                                                              "sysctl is set.  Either run 'chmod 0666 /dev/%s' or change the "
    6166                                                              "group of that node to vboxusers and make yourself a member of "
    6167                                                              "that group.  Make sure that these changes are permanent."),
    6168                                                              pszBridgedIfName, pszBridgedIfName);
    6169                             default:
    6170                                 AssertMsgFailed(("Could not attach to tap interface! Bad!\n"));
    6171                                 return pVMM->pfnVMR3SetError(pUVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS,
    6172                                                              N_("Failed to initialize Host Interface Networking"));
    6173                         }
    6174                     }
    6175 
    6176                     Assert((intptr_t)maTapFD[uInstance] >= 0);
    6177                     if ((intptr_t)maTapFD[uInstance] >= 0)
    6178                     {
    6179                         InsertConfigString(pLunL0, "Driver", "HostInterface");
    6180                         InsertConfigNode(pLunL0, "Config", &pCfg);
    6181                         InsertConfigInteger(pCfg, "FileHandle", (intptr_t)maTapFD[uInstance]);
    6182                     }
    6183                     break;
    6184                 }
    6185 #  endif
    6186                 /** @todo Check for malformed names. */
    6187                 const char *pszTrunk = pszBridgedIfName;
    6188 
    6189                 /* Issue a warning if the interface is down */
    6190                 {
    6191                     int iSock = socket(AF_INET, SOCK_DGRAM, 0);
    6192                     if (iSock >= 0)
    6193                     {
    6194                         struct ifreq Req;
    6195                         RT_ZERO(Req);
    6196                         RTStrCopy(Req.ifr_name, sizeof(Req.ifr_name), pszBridgedIfName);
    6197                         if (ioctl(iSock, SIOCGIFFLAGS, &Req) >= 0)
    6198                             if ((Req.ifr_flags & IFF_UP) == 0)
    6199                                 i_atVMRuntimeErrorCallbackF(0, "BridgedInterfaceDown",
    6200                                      N_("Bridged interface %s is down. Guest will not be able to use this interface"),
    6201                                      pszBridgedIfName);
    6202 
    6203                         close(iSock);
    6204                     }
    6205                 }
    6206 
    6207 # else
    6208 #  error "PORTME (VBOX_WITH_NETFLT)"
    6209 # endif
    6210 
    6211 # if defined(RT_OS_DARWIN) && defined(VBOX_WITH_VMNET)
    6212                 InsertConfigString(pLunL0, "Driver", "VMNet");
    6213                 InsertConfigNode(pLunL0, "Config", &pCfg);
    6214                 InsertConfigString(pCfg, "Trunk", pszTrunk);
    6215                 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt);
    6216 # else
    6217                 InsertConfigString(pLunL0, "Driver", "IntNet");
    6218                 InsertConfigNode(pLunL0, "Config", &pCfg);
    6219                 InsertConfigString(pCfg, "Trunk", pszTrunk);
    6220                 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt);
    6221                 InsertConfigInteger(pCfg, "IgnoreConnectFailure", (uint64_t)fIgnoreConnectFailure);
    6222                 InsertConfigString(pCfg, "IfPolicyPromisc", pszPromiscuousGuestPolicy);
    6223                 char szNetwork[INTNET_MAX_NETWORK_NAME];
    6224 
    6225 #  if defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN)
    6226                 /*
    6227                  * 'pszTrunk' contains just the interface name required in ring-0, while 'pszBridgedIfName' contains
    6228                  * interface name + optional description. We must not pass any description to the VM as it can differ
    6229                  * for the same interface name, eg: "nge0 - ethernet" (GUI) vs "nge0" (VBoxManage).
    6230                  */
    6231                 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszTrunk);
    6232 #  else
    6233                 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszBridgedIfName);
    6234 #  endif
    6235                 InsertConfigString(pCfg, "Network", szNetwork);
    6236                 networkName = Bstr(szNetwork);
    6237                 trunkName = Bstr(pszTrunk);
    6238                 trunkType = Bstr(TRUNKTYPE_NETFLT);
    6239 
    6240                 BOOL fSharedMacOnWire = false;
    6241                 hrc = hostInterface->COMGETTER(Wireless)(&fSharedMacOnWire);
    6242                 if (FAILED(hrc))
    6243                 {
    6244                     LogRel(("NetworkAttachmentType_Bridged: COMGETTER(Wireless) failed, hrc (0x%x)\n", hrc));
    6245                     H();
    6246                 }
    6247                 else if (fSharedMacOnWire)
    6248                 {
    6249                     InsertConfigInteger(pCfg, "SharedMacOnWire", true);
    6250                     Log(("Set SharedMacOnWire\n"));
    6251                 }
    6252 
    6253 #  if defined(RT_OS_SOLARIS)
    6254 #   if 0 /* bird: this is a bit questionable and might cause more trouble than its worth.  */
    6255                 /* Zone access restriction, don't allow snooping the global zone. */
    6256                 zoneid_t ZoneId = getzoneid();
    6257                 if (ZoneId != GLOBAL_ZONEID)
    6258                 {
    6259                     InsertConfigInteger(pCfg, "IgnoreAllPromisc", true);
    6260                 }
    6261 #   endif
    6262 #  endif
    6263 # endif
    6264 
    6265 #elif defined(RT_OS_WINDOWS) /* not defined NetFlt */
    6266             /* NOTHING TO DO HERE */
    6267 #elif defined(RT_OS_LINUX)
    6268 /// @todo aleksey: is there anything to be done here?
    6269 #elif defined(RT_OS_FREEBSD)
    6270 /** @todo FreeBSD: Check out this later (HIF networking). */
    6271 #else
    6272 # error "Port me"
    6273 #endif
    6274                 break;
    6275             }
    6276 
    6277             case NetworkAttachmentType_Internal:
    6278             {
    6279                 hrc = aNetworkAdapter->COMGETTER(InternalNetwork)(bstr.asOutParam());       H();
    6280                 if (!bstr.isEmpty())
    6281                 {
    6282                     InsertConfigString(pLunL0, "Driver", "IntNet");
    6283                     InsertConfigNode(pLunL0, "Config", &pCfg);
    6284                     InsertConfigString(pCfg, "Network", bstr);
    6285                     InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_WhateverNone);
    6286                     InsertConfigString(pCfg, "IfPolicyPromisc", pszPromiscuousGuestPolicy);
    6287                     networkName = bstr;
    6288                     trunkType = Bstr(TRUNKTYPE_WHATEVER);
    6289                 }
    6290                 break;
    6291             }
    6292 
    6293             case NetworkAttachmentType_HostOnly:
    6294             {
    6295                 InsertConfigString(pLunL0, "Driver", "IntNet");
    6296                 InsertConfigNode(pLunL0, "Config", &pCfg);
    6297 
    6298                 Bstr HostOnlyName;
    6299                 hrc = aNetworkAdapter->COMGETTER(HostOnlyInterface)(HostOnlyName.asOutParam());
    6300                 if (FAILED(hrc))
    6301                 {
    6302                     LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(HostOnlyInterface) failed, hrc (0x%x)\n", hrc));
    6303                     H();
    6304                 }
    6305 
    6306                 Utf8Str HostOnlyNameUtf8(HostOnlyName);
    6307                 const char *pszHostOnlyName = HostOnlyNameUtf8.c_str();
    6308 #ifdef VBOX_WITH_VMNET
    6309                 /* Check if the matching host-only network has already been created. */
    6310                 Bstr bstrLowerIP, bstrUpperIP, bstrNetworkMask;
    6311                 BstrFmt bstrNetworkName("Legacy %s Network", pszHostOnlyName);
    6312                 ComPtr<IHostOnlyNetwork> hostOnlyNetwork;
    6313                 hrc = virtualBox->FindHostOnlyNetworkByName(bstrNetworkName.raw(), hostOnlyNetwork.asOutParam());
    6314                 if (FAILED(hrc))
    6315                 {
    6316                     /*
    6317                     * With VMNET there is no VBoxNetAdp to create vboxnetX adapters,
    6318                     * which means that the Host object won't be able to re-create
    6319                     * them from extra data. Go through existing DHCP/adapter config
    6320                     * to derive the parameters for the new network.
    6321                     */
    6322                     BstrFmt bstrOldNetworkName("HostInterfaceNetworking-%s", pszHostOnlyName);
    6323                     ComPtr<IDHCPServer> dhcpServer;
    6324                     hrc = virtualBox->FindDHCPServerByNetworkName(bstrOldNetworkName.raw(),
    6325                                                                 dhcpServer.asOutParam());
    6326                     if (SUCCEEDED(hrc))
    6327                     {
    6328                         /* There is a DHCP server available for this network. */
    6329                         hrc = dhcpServer->COMGETTER(LowerIP)(bstrLowerIP.asOutParam());
    6330                         if (FAILED(hrc))
    6331                         {
    6332                             LogRel(("Console::i_configNetwork: COMGETTER(LowerIP) failed, hrc (%Rhrc)\n", hrc));
    6333                             H();
    6334                         }
    6335                         hrc = dhcpServer->COMGETTER(UpperIP)(bstrUpperIP.asOutParam());
    6336                         if (FAILED(hrc))
    6337                         {
    6338                             LogRel(("Console::i_configNetwork: COMGETTER(UpperIP) failed, hrc (%Rhrc)\n", hrc));
    6339                             H();
    6340                         }
    6341                         hrc = dhcpServer->COMGETTER(NetworkMask)(bstrNetworkMask.asOutParam());
    6342                         if (FAILED(hrc))
    6343                         {
    6344                             LogRel(("Console::i_configNetwork: COMGETTER(NetworkMask) failed, hrc (%Rhrc)\n", hrc));
    6345                             H();
    6346                         }
    6347                     }
    6348                     else
    6349                     {
    6350                         /* No DHCP server for this hostonly interface, let's look at extra data */
    6351                         hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPAddress",
    6352                                                             pszHostOnlyName).raw(),
    6353                                                             bstrLowerIP.asOutParam());
    6354                         if (SUCCEEDED(hrc) && !bstrLowerIP.isEmpty())
    6355                             hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPNetMask",
    6356                                                                 pszHostOnlyName).raw(),
    6357                                                                 bstrNetworkMask.asOutParam());
    6358 
    6359                     }
    6360                     RTNETADDRIPV4 ipAddr, ipMask;
    6361                     vrc = bstrLowerIP.isEmpty() ? VERR_MISSING : RTNetStrToIPv4Addr(Utf8Str(bstrLowerIP).c_str(), &ipAddr);
    6362                     if (RT_FAILURE(vrc))
    6363                     {
    6364                         /* We failed to locate any valid config of this vboxnetX interface, assume defaults. */
    6365                         LogRel(("NetworkAttachmentType_HostOnly: Invalid or missing lower IP '%ls', using '%ls' instead.\n",
    6366                                 bstrLowerIP.raw(), getDefaultIPv4Address(Bstr(pszHostOnlyName)).raw()));
    6367                         bstrLowerIP = getDefaultIPv4Address(Bstr(pszHostOnlyName));
    6368                         bstrNetworkMask.setNull();
    6369                         bstrUpperIP.setNull();
    6370                         vrc = RTNetStrToIPv4Addr(Utf8Str(bstrLowerIP).c_str(), &ipAddr);
    6371                         AssertLogRelMsgReturn(RT_SUCCESS(vrc), ("RTNetStrToIPv4Addr(%ls) failed, vrc=%Rrc\n", bstrLowerIP.raw(), vrc),
    6372                                               VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
    6373                     }
    6374                     vrc = bstrNetworkMask.isEmpty() ? VERR_MISSING : RTNetStrToIPv4Addr(Utf8Str(bstrNetworkMask).c_str(), &ipMask);
    6375                     if (RT_FAILURE(vrc))
    6376                     {
    6377                         LogRel(("NetworkAttachmentType_HostOnly: Invalid or missing network mask '%ls', using '%s' instead.\n",
    6378                                 bstrNetworkMask.raw(), VBOXNET_IPV4MASK_DEFAULT));
    6379                         bstrNetworkMask = VBOXNET_IPV4MASK_DEFAULT;
    6380                         vrc = RTNetStrToIPv4Addr(Utf8Str(bstrNetworkMask).c_str(), &ipMask);
    6381                         AssertLogRelMsgReturn(RT_SUCCESS(vrc), ("RTNetStrToIPv4Addr(%ls) failed, vrc=%Rrc\n", bstrNetworkMask.raw(), vrc),
    6382                                               VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
    6383                     }
    6384                     vrc = bstrUpperIP.isEmpty() ? VERR_MISSING : RTNetStrToIPv4Addr(Utf8Str(bstrUpperIP).c_str(), &ipAddr);
    6385                     if (RT_FAILURE(vrc))
    6386                     {
    6387                         ipAddr.au32[0] = RT_H2N_U32((RT_N2H_U32(ipAddr.au32[0]) | ~RT_N2H_U32(ipMask.au32[0])) - 1); /* Do we need to exlude the last IP? */
    6388                         LogRel(("NetworkAttachmentType_HostOnly: Invalid or missing upper IP '%ls', using '%RTnaipv4' instead.\n",
    6389                                 bstrUpperIP.raw(), ipAddr));
    6390                         bstrUpperIP = BstrFmt("%RTnaipv4", ipAddr);
    6391                     }
    6392 
    6393                     /* All parameters are set, create the new network. */
    6394                     hrc = virtualBox->CreateHostOnlyNetwork(bstrNetworkName.raw(), hostOnlyNetwork.asOutParam());
    6395                     if (FAILED(hrc))
    6396                     {
    6397                         LogRel(("NetworkAttachmentType_HostOnly: failed to create host-only network, hrc (0x%x)\n", hrc));
    6398                         H();
    6399                     }
    6400                     hrc = hostOnlyNetwork->COMSETTER(NetworkMask)(bstrNetworkMask.raw());
    6401                     if (FAILED(hrc))
    6402                     {
    6403                         LogRel(("NetworkAttachmentType_HostOnly: COMSETTER(NetworkMask) failed, hrc (0x%x)\n", hrc));
    6404                         H();
    6405                     }
    6406                     hrc = hostOnlyNetwork->COMSETTER(LowerIP)(bstrLowerIP.raw());
    6407                     if (FAILED(hrc))
    6408                     {
    6409                         LogRel(("NetworkAttachmentType_HostOnly: COMSETTER(LowerIP) failed, hrc (0x%x)\n", hrc));
    6410                         H();
    6411                     }
    6412                     hrc = hostOnlyNetwork->COMSETTER(UpperIP)(bstrUpperIP.raw());
    6413                     if (FAILED(hrc))
    6414                     {
    6415                         LogRel(("NetworkAttachmentType_HostOnly: COMSETTER(UpperIP) failed, hrc (0x%x)\n", hrc));
    6416                         H();
    6417                     }
    6418                     LogRel(("Console: created host-only network '%ls' with mask '%ls' and range '%ls'-'%ls'\n",
    6419                             bstrNetworkName.raw(), bstrNetworkMask.raw(), bstrLowerIP.raw(), bstrUpperIP.raw()));
    6420                 }
    6421                 else
    6422                 {
    6423                     /* The matching host-only network already exists. Tell the user to switch to it. */
    6424                     hrc = hostOnlyNetwork->COMGETTER(NetworkMask)(bstrNetworkMask.asOutParam());
    6425                     if (FAILED(hrc))
    6426                     {
    6427                         LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(NetworkMask) failed, hrc (0x%x)\n", hrc));
    6428                         H();
    6429                     }
    6430                     hrc = hostOnlyNetwork->COMGETTER(LowerIP)(bstrLowerIP.asOutParam());
    6431                     if (FAILED(hrc))
    6432                     {
    6433                         LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(LowerIP) failed, hrc (0x%x)\n", hrc));
    6434                         H();
    6435                     }
    6436                     hrc = hostOnlyNetwork->COMGETTER(UpperIP)(bstrUpperIP.asOutParam());
    6437                     if (FAILED(hrc))
    6438                     {
    6439                         LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(UpperIP) failed, hrc (0x%x)\n", hrc));
    6440                         H();
    6441                     }
    6442                 }
    6443                 return pVMM->pfnVMR3SetError(pUVM, VERR_NOT_FOUND, RT_SRC_POS,
    6444                                              N_("Host-only adapters are no longer supported!\n"
    6445                                                 "For your convenience a host-only network named '%ls' has been "
    6446                                                 "created with network mask '%ls' and IP address range '%ls' - '%ls'.\n"
    6447                                                 "To fix this problem, switch to 'Host-only Network' "
    6448                                                 "attachment type in the VM settings.\n"),
    6449                                              bstrNetworkName.raw(), bstrNetworkMask.raw(),
    6450                                              bstrLowerIP.raw(), bstrUpperIP.raw());
    6451 #endif /* VBOX_WITH_VMNET */
    6452                 ComPtr<IHostNetworkInterface> hostInterface;
    6453                 hrc = host->FindHostNetworkInterfaceByName(HostOnlyName.raw(),
    6454                                                            hostInterface.asOutParam());
    6455                 if (!SUCCEEDED(hrc))
    6456                 {
    6457                     LogRel(("NetworkAttachmentType_HostOnly: FindByName failed, vrc=%Rrc\n", vrc));
    6458                     return pVMM->pfnVMR3SetError(pUVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
    6459                                                 N_("Nonexistent host networking interface, name '%ls'"), HostOnlyName.raw());
    6460                 }
    6461 
    6462                 char szNetwork[INTNET_MAX_NETWORK_NAME];
    6463                 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHostOnlyName);
    6464 
    6465 #if defined(RT_OS_WINDOWS)
    6466 # ifndef VBOX_WITH_NETFLT
    6467                 hrc = E_NOTIMPL;
    6468                 LogRel(("NetworkAttachmentType_HostOnly: Not Implemented\n"));
    6469                 H();
    6470 # else  /* defined VBOX_WITH_NETFLT*/
    6471                 /** @todo r=bird: Put this in a function. */
    6472 
    6473                 HostNetworkInterfaceType_T eIfType;
    6474                 hrc = hostInterface->COMGETTER(InterfaceType)(&eIfType);
    6475                 if (FAILED(hrc))
    6476                 {
    6477                     LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(InterfaceType) failed, hrc (0x%x)\n", hrc));
    6478                     H();
    6479                 }
    6480 
    6481                 if (eIfType != HostNetworkInterfaceType_HostOnly)
    6482                     return pVMM->pfnVMR3SetError(pUVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
    6483                                                  N_("Interface ('%ls') is not a Host-Only Adapter interface"),
    6484                                                  HostOnlyName.raw());
    6485 
    6486                 hrc = hostInterface->COMGETTER(Id)(bstr.asOutParam());
    6487                 if (FAILED(hrc))
    6488                 {
    6489                     LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(Id) failed, hrc (0x%x)\n", hrc));
    6490                     H();
    6491                 }
    6492                 Guid hostIFGuid(bstr);
    6493 
    6494                 INetCfg *pNc;
    6495                 ComPtr<INetCfgComponent> pAdaptorComponent;
    6496                 LPWSTR pszApp;
    6497                 hrc = VBoxNetCfgWinQueryINetCfg(&pNc, FALSE, L"VirtualBox", 10, &pszApp);
    6498                 Assert(hrc == S_OK);
    6499                 if (hrc != S_OK)
    6500                 {
    6501                     LogRel(("NetworkAttachmentType_HostOnly: Failed to get NetCfg, hrc=%Rhrc (0x%x)\n", hrc, hrc));
    6502                     H();
    6503                 }
    6504 
    6505                 /* get the adapter's INetCfgComponent*/
    6506                 hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.raw(),
    6507                                                       pAdaptorComponent.asOutParam());
    6508                 if (hrc != S_OK)
    6509                 {
    6510                     VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
    6511                     LogRel(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n", hrc, hrc));
    6512                     H();
    6513                 }
    6514 #  define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\"
    6515                 char szTrunkName[INTNET_MAX_TRUNK_NAME];
    6516                 bool fNdis6 = false;
    6517                 wchar_t * pwszHelpText;
    6518                 hrc = pAdaptorComponent->GetHelpText(&pwszHelpText);
    6519                 Assert(hrc == S_OK);
    6520                 if (hrc == S_OK)
    6521                 {
    6522                     Log(("help-text=%ls\n", pwszHelpText));
    6523                     if (!wcscmp(pwszHelpText, L"VirtualBox NDIS 6.0 Miniport Driver"))
    6524                         fNdis6 = true;
    6525                     CoTaskMemFree(pwszHelpText);
    6526                 }
    6527                 if (fNdis6)
    6528                 {
    6529                     strncpy(szTrunkName, pszHostOnlyName, sizeof(szTrunkName) - 1);
    6530                     Log(("trunk=%s\n", szTrunkName));
    6531                 }
    6532                 else
    6533                 {
    6534                     char *pszTrunkName = szTrunkName;
    6535                     wchar_t * pswzBindName;
    6536                     hrc = pAdaptorComponent->GetBindName(&pswzBindName);
    6537                     Assert(hrc == S_OK);
    6538                     if (hrc == S_OK)
    6539                     {
    6540                         int cwBindName = (int)wcslen(pswzBindName) + 1;
    6541                         int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX);
    6542                         if (sizeof(szTrunkName) > cbFullBindNamePrefix + cwBindName)
    6543                         {
    6544                             strcpy(szTrunkName, VBOX_WIN_BINDNAME_PREFIX);
    6545                             pszTrunkName += cbFullBindNamePrefix-1;
    6546                             if (!WideCharToMultiByte(CP_ACP, 0, pswzBindName, cwBindName, pszTrunkName,
    6547                                                      sizeof(szTrunkName) - cbFullBindNamePrefix + 1, NULL, NULL))
    6548                             {
    6549                                 DWORD err = GetLastError();
    6550                                 hrc = HRESULT_FROM_WIN32(err);
    6551                                 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n",
    6552                                                        hrc, hrc, err));
    6553                             }
    6554                         }
    6555                         else
    6556                         {
    6557                             AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: insufficient szTrunkName buffer space\n"));
    6558                             /** @todo set appropriate error code */
    6559                             hrc = E_FAIL;
    6560                         }
    6561 
    6562                         if (hrc != S_OK)
    6563                         {
    6564                             AssertFailed();
    6565                             CoTaskMemFree(pswzBindName);
    6566                             VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
    6567                             H();
    6568                         }
    6569                     }
    6570                     else
    6571                     {
    6572                         VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
    6573                         AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n",
    6574                                                hrc, hrc));
    6575                         H();
    6576                     }
    6577 
    6578 
    6579                     CoTaskMemFree(pswzBindName);
    6580                 }
    6581 
    6582                 trunkType = TRUNKTYPE_NETADP;
    6583                 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp);
    6584 
    6585                 pAdaptorComponent.setNull();
    6586                 /* release the pNc finally */
    6587                 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
    6588 
    6589                 const char *pszTrunk = szTrunkName;
    6590 
    6591                 InsertConfigString(pCfg, "Trunk", pszTrunk);
    6592                 InsertConfigString(pCfg, "Network", szNetwork);
    6593                 InsertConfigInteger(pCfg, "IgnoreConnectFailure", (uint64_t)fIgnoreConnectFailure); /** @todo why is this
    6594                                                                                                         windows only?? */
    6595                 networkName = Bstr(szNetwork);
    6596                 trunkName   = Bstr(pszTrunk);
    6597 # endif /* defined VBOX_WITH_NETFLT*/
    6598 #elif defined(RT_OS_DARWIN)
    6599                 InsertConfigString(pCfg, "Trunk", pszHostOnlyName);
    6600                 InsertConfigString(pCfg, "Network", szNetwork);
    6601                 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp);
    6602                 networkName = Bstr(szNetwork);
    6603                 trunkName   = Bstr(pszHostOnlyName);
    6604                 trunkType   = TRUNKTYPE_NETADP;
    6605 #else
    6606                 InsertConfigString(pCfg, "Trunk", pszHostOnlyName);
    6607                 InsertConfigString(pCfg, "Network", szNetwork);
    6608                 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt);
    6609                 networkName = Bstr(szNetwork);
    6610                 trunkName   = Bstr(pszHostOnlyName);
    6611                 trunkType   = TRUNKTYPE_NETFLT;
    6612 #endif
    6613                 InsertConfigString(pCfg, "IfPolicyPromisc", pszPromiscuousGuestPolicy);
    6614 
    6615 #if !defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
    6616 
    6617                 Bstr tmpAddr, tmpMask;
    6618 
    6619                 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPAddress",
    6620                                                        pszHostOnlyName).raw(),
    6621                                                tmpAddr.asOutParam());
    6622                 if (SUCCEEDED(hrc) && !tmpAddr.isEmpty())
    6623                 {
    6624                     hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPNetMask",
    6625                                                            pszHostOnlyName).raw(),
    6626                                                    tmpMask.asOutParam());
    6627                     if (SUCCEEDED(hrc) && !tmpMask.isEmpty())
    6628                         hrc = hostInterface->EnableStaticIPConfig(tmpAddr.raw(),
    6629                                                                   tmpMask.raw());
    6630                     else
    6631                         hrc = hostInterface->EnableStaticIPConfig(tmpAddr.raw(),
    6632                                                                   Bstr(VBOXNET_IPV4MASK_DEFAULT).raw());
    6633                 }
    6634                 else
    6635                 {
    6636                     /* Grab the IP number from the 'vboxnetX' instance number (see netif.h) */
    6637                     hrc = hostInterface->EnableStaticIPConfig(getDefaultIPv4Address(Bstr(pszHostOnlyName)).raw(),
    6638                                                               Bstr(VBOXNET_IPV4MASK_DEFAULT).raw());
    6639                 }
    6640 
    6641                 ComAssertComRC(hrc); /** @todo r=bird: Why this isn't fatal? (H()) */
    6642 
    6643                 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6Address",
    6644                                                        pszHostOnlyName).raw(),
    6645                                                tmpAddr.asOutParam());
    6646                 if (SUCCEEDED(hrc))
    6647                     hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6NetMask", pszHostOnlyName).raw(),
    6648                                                    tmpMask.asOutParam());
    6649                 if (SUCCEEDED(hrc) && !tmpAddr.isEmpty() && !tmpMask.isEmpty())
    6650                 {
    6651                     hrc = hostInterface->EnableStaticIPConfigV6(tmpAddr.raw(),
    6652                                                                 Utf8Str(tmpMask).toUInt32());
    6653                     ComAssertComRC(hrc); /** @todo r=bird: Why this isn't fatal? (H()) */
    6654                 }
    6655 #endif
    6656                 break;
    6657             }
    6658 
    6659             case NetworkAttachmentType_Generic:
    6660             {
    6661                 hrc = aNetworkAdapter->COMGETTER(GenericDriver)(bstr.asOutParam());         H();
    6662                 SafeArray<BSTR> names;
    6663                 SafeArray<BSTR> values;
    6664                 hrc = aNetworkAdapter->GetProperties(Bstr().raw(),
    6665                                                      ComSafeArrayAsOutParam(names),
    6666                                                      ComSafeArrayAsOutParam(values));       H();
    6667 
    6668                 InsertConfigString(pLunL0, "Driver", bstr);
    6669                 InsertConfigNode(pLunL0, "Config", &pCfg);
    6670                 for (size_t ii = 0; ii < names.size(); ++ii)
    6671                 {
    6672                     if (values[ii] && *values[ii])
    6673                     {
    6674                         Utf8Str const strName(names[ii]);
    6675                         Utf8Str const strValue(values[ii]);
    6676                         InsertConfigString(pCfg, strName.c_str(), strValue);
    6677                     }
    6678                 }
    6679                 break;
    6680             }
    6681 
    6682             case NetworkAttachmentType_NATNetwork:
    6683             {
    6684                 hrc = aNetworkAdapter->COMGETTER(NATNetwork)(bstr.asOutParam());            H();
    6685                 if (!bstr.isEmpty())
    6686                 {
    6687                     /** @todo add intnet prefix to separate namespaces, and add trunk if dealing with vboxnatX */
    6688                     InsertConfigString(pLunL0, "Driver", "IntNet");
    6689                     InsertConfigNode(pLunL0, "Config", &pCfg);
    6690                     InsertConfigString(pCfg, "Network", bstr);
    6691                     InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_WhateverNone);
    6692                     InsertConfigString(pCfg, "IfPolicyPromisc", pszPromiscuousGuestPolicy);
    6693                     networkName = bstr;
    6694                     trunkType = Bstr(TRUNKTYPE_WHATEVER);
    6695                 }
    6696                 break;
    6697             }
    6698 
    6699 #ifdef VBOX_WITH_CLOUD_NET
    6700             case NetworkAttachmentType_Cloud:
    6701             {
    6702                 static const char *s_pszCloudExtPackName = "Oracle VM VirtualBox Extension Pack";
    6703                 /*
    6704                  * Cloud network attachments do not work wihout installed extpack.
    6705                  * Without extpack support they won't work either.
    6706                  */
    6707 # ifdef VBOX_WITH_EXTPACK
    6708                 if (!mptrExtPackManager->i_isExtPackUsable(s_pszCloudExtPackName))
    6709 # endif
    6710                 {
    6711                     return pVMM->pfnVMR3SetError(pUVM, VERR_NOT_FOUND, RT_SRC_POS,
    6712                                                  N_("Implementation of the cloud network attachment not found!\n"
    6713                                                     "To fix this problem, either install the '%s' or switch to "
    6714                                                     "another network attachment type in the VM settings."),
    6715                                                  s_pszCloudExtPackName);
    6716                 }
    6717 
    6718                 ComPtr<ICloudNetwork> network;
    6719                 hrc = aNetworkAdapter->COMGETTER(CloudNetwork)(bstr.asOutParam());            H();
    6720                 hrc = pMachine->COMGETTER(Name)(mGateway.mTargetVM.asOutParam());            H();
    6721                 hrc = virtualBox->FindCloudNetworkByName(bstr.raw(), network.asOutParam());   H();
    6722                 hrc = generateKeys(mGateway);
    6723                 if (FAILED(hrc))
    6724                 {
    6725                     if (hrc == E_NOTIMPL)
    6726                         return pVMM->pfnVMR3SetError(pUVM, VERR_NOT_FOUND, RT_SRC_POS,
    6727                                                      N_("Failed to generate a key pair due to missing libssh\n"
    6728                                                         "To fix this problem, either build VirtualBox with libssh "
    6729                                                         "support or switch to another network attachment type in "
    6730                                                         "the VM settings."));
    6731                     return pVMM->pfnVMR3SetError(pUVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
    6732                                                  N_("Failed to generate a key pair due to libssh error!"));
    6733                 }
    6734                 hrc = startCloudGateway(virtualBox, network, mGateway);
    6735                 if (FAILED(hrc))
    6736                 {
    6737                     if (hrc == VBOX_E_OBJECT_NOT_FOUND)
    6738                         return pVMM->pfnVMR3SetError(pUVM, hrc, RT_SRC_POS,
    6739                                                     N_("Failed to start cloud gateway instance.\nCould not find suitable "
    6740                                                         "standard cloud images. Make sure you ran 'VBoxManage cloud network setup' "
    6741                                                         "with correct '--gateway-os-name' and '--gateway-os-version' parameters. "
    6742                                                         "Check VBoxSVC.log for actual values used to look up cloud images."));
    6743                     return pVMM->pfnVMR3SetError(pUVM, hrc, RT_SRC_POS,
    6744                                                  N_("Failed to start cloud gateway instance.\nMake sure you set up "
    6745                                                     "cloud networking properly with 'VBoxManage cloud network setup'. "
    6746                                                     "Check VBoxSVC.log for details."));
    6747                 }
    6748                 InsertConfigBytes(pDevCfg, "MAC", &mGateway.mCloudMacAddress, sizeof(mGateway.mCloudMacAddress));
    6749                 if (!bstr.isEmpty())
    6750                 {
    6751                     InsertConfigString(pLunL0, "Driver", "CloudTunnel");
    6752                     InsertConfigNode(pLunL0, "Config", &pCfg);
    6753                     InsertConfigPassword(pCfg, "SshKey", mGateway.mPrivateSshKey);
    6754                     InsertConfigString(pCfg, "PrimaryIP", mGateway.mCloudPublicIp);
    6755                     InsertConfigString(pCfg, "SecondaryIP", mGateway.mCloudSecondaryPublicIp);
    6756                     InsertConfigBytes(pCfg, "TargetMAC", &mGateway.mLocalMacAddress, sizeof(mGateway.mLocalMacAddress));
    6757                     hrc = i_configProxy(virtualBox, pCfg, "Primary", mGateway.mCloudPublicIp);
    6758                     if (FAILED(hrc))
    6759                     {
    6760                         return pVMM->pfnVMR3SetError(pUVM, hrc, RT_SRC_POS,
    6761                                                     N_("Failed to configure proxy for accessing cloud gateway instance via primary VNIC.\n"
    6762                                                         "Check VirtualBox.log for details."));
    6763                     }
    6764                     hrc = i_configProxy(virtualBox, pCfg, "Secondary", mGateway.mCloudSecondaryPublicIp);
    6765                     if (FAILED(hrc))
    6766                     {
    6767                         return pVMM->pfnVMR3SetError(pUVM, hrc, RT_SRC_POS,
    6768                                                     N_("Failed to configure proxy for accessing cloud gateway instance via secondary VNIC.\n"
    6769                                                         "Check VirtualBox.log for details."));
    6770                     }
    6771                     networkName = bstr;
    6772                     trunkType = Bstr(TRUNKTYPE_WHATEVER);
    6773                 }
    6774                 break;
    6775             }
    6776 #endif /* VBOX_WITH_CLOUD_NET */
    6777 
    6778 #ifdef VBOX_WITH_VMNET
    6779             case NetworkAttachmentType_HostOnlyNetwork:
    6780             {
    6781                 Bstr bstrId, bstrNetMask, bstrLowerIP, bstrUpperIP;
    6782                 ComPtr<IHostOnlyNetwork> network;
    6783                 hrc = aNetworkAdapter->COMGETTER(HostOnlyNetwork)(bstr.asOutParam());            H();
    6784                 hrc = virtualBox->FindHostOnlyNetworkByName(bstr.raw(), network.asOutParam());
    6785                 if (FAILED(hrc))
    6786                 {
    6787                     LogRel(("NetworkAttachmentType_HostOnlyNetwork: FindByName failed, hrc (0x%x)\n", hrc));
    6788                     return pVMM->pfnVMR3SetError(pUVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
    6789                                                  N_("Nonexistent host-only network '%ls'"), bstr.raw());
    6790                 }
    6791                 hrc = network->COMGETTER(Id)(bstrId.asOutParam());                               H();
    6792                 hrc = network->COMGETTER(NetworkMask)(bstrNetMask.asOutParam());                 H();
    6793                 hrc = network->COMGETTER(LowerIP)(bstrLowerIP.asOutParam());                     H();
    6794                 hrc = network->COMGETTER(UpperIP)(bstrUpperIP.asOutParam());                     H();
    6795                 if (!bstr.isEmpty())
    6796                 {
    6797                     InsertConfigString(pLunL0, "Driver", "VMNet");
    6798                     InsertConfigNode(pLunL0, "Config", &pCfg);
    6799                     // InsertConfigString(pCfg, "Trunk", bstr);
    6800                     // InsertConfigStringF(pCfg, "Network", "HostOnlyNetworking-%ls", bstr.raw());
    6801                     InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp);
    6802                     InsertConfigString(pCfg, "Id", bstrId);
    6803                     InsertConfigString(pCfg, "NetworkMask", bstrNetMask);
    6804                     InsertConfigString(pCfg, "LowerIP", bstrLowerIP);
    6805                     InsertConfigString(pCfg, "UpperIP", bstrUpperIP);
    6806                     // InsertConfigString(pCfg, "IfPolicyPromisc", pszPromiscuousGuestPolicy);
    6807                     networkName.setNull(); // We do not want DHCP server on our network!
    6808                     // trunkType = Bstr(TRUNKTYPE_WHATEVER);
    6809                 }
    6810                 break;
    6811             }
    6812 #endif /* VBOX_WITH_VMNET */
    6813 
    6814             default:
    6815                 AssertMsgFailed(("should not get here!\n"));
    6816                 break;
    6817         }
    6818 
    6819         /*
    6820          * Attempt to attach the driver.
    6821          */
    6822         switch (eAttachmentType)
    6823         {
    6824             case NetworkAttachmentType_Null:
    6825                 break;
    6826 
    6827             case NetworkAttachmentType_Bridged:
    6828             case NetworkAttachmentType_Internal:
    6829             case NetworkAttachmentType_HostOnly:
    6830 #ifdef VBOX_WITH_VMNET
    6831             case NetworkAttachmentType_HostOnlyNetwork:
    6832 #endif /* VBOX_WITH_VMNET */
    6833             case NetworkAttachmentType_NAT:
    6834             case NetworkAttachmentType_Generic:
    6835             case NetworkAttachmentType_NATNetwork:
    6836 #ifdef VBOX_WITH_CLOUD_NET
    6837             case NetworkAttachmentType_Cloud:
    6838 #endif /* VBOX_WITH_CLOUD_NET */
    6839             {
    6840                 if (SUCCEEDED(hrc) && RT_SUCCESS(vrc))
    6841                 {
    6842                     if (fAttachDetach)
    6843                     {
    6844                         vrc = pVMM->pfnPDMR3DriverAttach(mpUVM, pszDevice, uInstance, uLun, 0 /*fFlags*/, NULL /* ppBase */);
    6845                         //AssertRC(vrc);
    6846                     }
    6847 
    6848                     {
    6849                         /** @todo pritesh: get the dhcp server name from the
    6850                          * previous network configuration and then stop the server
    6851                          * else it may conflict with the dhcp server running  with
    6852                          * the current attachment type
    6853                          */
    6854                         /* Stop the hostonly DHCP Server */
    6855                     }
    6856 
    6857                     /*
    6858                      * NAT networks start their DHCP server theirself, see NATNetwork::Start()
    6859                      */
    6860                     if (   !networkName.isEmpty()
    6861                         && eAttachmentType != NetworkAttachmentType_NATNetwork)
    6862                     {
    6863                         /*
    6864                          * Until we implement service reference counters DHCP Server will be stopped
    6865                          * by DHCPServerRunner destructor.
    6866                          */
    6867                         ComPtr<IDHCPServer> dhcpServer;
    6868                         hrc = virtualBox->FindDHCPServerByNetworkName(networkName.raw(), dhcpServer.asOutParam());
    6869                         if (SUCCEEDED(hrc))
    6870                         {
    6871                             /* there is a DHCP server available for this network */
    6872                             BOOL fEnabledDhcp;
    6873                             hrc = dhcpServer->COMGETTER(Enabled)(&fEnabledDhcp);
    6874                             if (FAILED(hrc))
    6875                             {
    6876                                 LogRel(("DHCP svr: COMGETTER(Enabled) failed, hrc (%Rhrc)\n", hrc));
    6877                                 H();
    6878                             }
    6879 
    6880                             if (fEnabledDhcp)
    6881                                 hrc = dhcpServer->Start(trunkName.raw(), trunkType.raw());
    6882                         }
    6883                         else
    6884                             hrc = S_OK;
    6885                     }
    6886                 }
    6887 
    6888                 break;
    6889             }
    6890 
    6891             default:
    6892                 AssertMsgFailed(("should not get here!\n"));
    6893                 break;
    6894         }
    6895 
    6896         meAttachmentType[uInstance] = eAttachmentType;
    6897     }
    6898     catch (ConfigError &x)
    6899     {
    6900         // InsertConfig threw something:
    6901         return x.m_vrc;
    6902     }
    6903 
    6904 #undef H
    6905 
    6906     return VINF_SUCCESS;
    6907 }
    6908 
    6909 
    6910 /**
    6911  * Configures the serial port at the given CFGM node with the supplied parameters.
    6912  *
    6913  * @returns VBox status code.
    6914  * @param   pInst               The instance CFGM node.
    6915  * @param   ePortMode           The port mode to sue.
    6916  * @param   pszPath             The serial port path.
    6917  * @param   fServer             Flag whether the port should act as a server
    6918  *                              for the pipe and TCP mode or connect as a client.
    6919  */
    6920 int Console::i_configSerialPort(PCFGMNODE pInst, PortMode_T ePortMode, const char *pszPath, bool fServer)
    6921 {
    6922     PCFGMNODE pLunL0 = NULL;        /* /Devices/Dev/0/LUN#0/ */
    6923     PCFGMNODE pLunL1 = NULL;        /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
    6924     PCFGMNODE pLunL1Cfg = NULL;     /* /Devices/Dev/0/LUN#0/AttachedDriver/Config */
    6925 
    6926     try
    6927     {
    6928         InsertConfigNode(pInst, "LUN#0", &pLunL0);
    6929         if (ePortMode == PortMode_HostPipe)
    6930         {
    6931             InsertConfigString(pLunL0,     "Driver", "Char");
    6932             InsertConfigNode(pLunL0,       "AttachedDriver", &pLunL1);
    6933             InsertConfigString(pLunL1,     "Driver", "NamedPipe");
    6934             InsertConfigNode(pLunL1,       "Config", &pLunL1Cfg);
    6935             InsertConfigString(pLunL1Cfg,  "Location", pszPath);
    6936             InsertConfigInteger(pLunL1Cfg, "IsServer", fServer);
    6937         }
    6938         else if (ePortMode == PortMode_HostDevice)
    6939         {
    6940             InsertConfigString(pLunL0,     "Driver", "Host Serial");
    6941             InsertConfigNode(pLunL0,       "Config", &pLunL1);
    6942             InsertConfigString(pLunL1,     "DevicePath", pszPath);
    6943         }
    6944         else if (ePortMode == PortMode_TCP)
    6945         {
    6946             InsertConfigString(pLunL0,     "Driver", "Char");
    6947             InsertConfigNode(pLunL0,       "AttachedDriver", &pLunL1);
    6948             InsertConfigString(pLunL1,     "Driver", "TCP");
    6949             InsertConfigNode(pLunL1,       "Config", &pLunL1Cfg);
    6950             InsertConfigString(pLunL1Cfg,  "Location", pszPath);
    6951             InsertConfigInteger(pLunL1Cfg, "IsServer", fServer);
    6952         }
    6953         else if (ePortMode == PortMode_RawFile)
    6954         {
    6955             InsertConfigString(pLunL0,     "Driver", "Char");
    6956             InsertConfigNode(pLunL0,       "AttachedDriver", &pLunL1);
    6957             InsertConfigString(pLunL1,     "Driver", "RawFile");
    6958             InsertConfigNode(pLunL1,       "Config", &pLunL1Cfg);
    6959             InsertConfigString(pLunL1Cfg,  "Location", pszPath);
    6960         }
    6961     }
    6962     catch (ConfigError &x)
    6963     {
    6964         /* InsertConfig threw something */
    6965         return x.m_vrc;
    6966     }
    6967 
    6968     return VINF_SUCCESS;
    6969 }
    6970 
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette