VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/SystemPropertiesImpl.cpp@ 105924

Last change on this file since 105924 was 105873, checked in by vboxsync, 9 months ago

IPRT/cpp/utils: Moved MY_VECTOR_ASSIGN_ARRAY into IPRT and renamed it to RT_CPP_VECTOR_ASSIGN_ARRAY. Macro was needed in several modules (to avoid code duplication).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 56.3 KB
Line 
1/* $Id: SystemPropertiesImpl.cpp 105873 2024-08-27 14:52:54Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN_SYSTEMPROPERTIES
29#include "SystemPropertiesImpl.h"
30#include "VirtualBoxImpl.h"
31#include "MachineImpl.h"
32#ifdef VBOX_WITH_EXTPACK
33# include "ExtPackManagerImpl.h"
34#endif
35#include "CPUProfileImpl.h"
36#include "AutoCaller.h"
37#include "Global.h"
38#include "LoggingNew.h"
39#include "AutostartDb.h"
40#include "VirtualBoxTranslator.h"
41
42// generated header
43#include "SchemaDefs.h"
44
45#include <iprt/dir.h>
46#include <iprt/ldr.h>
47#include <iprt/locale.h>
48#include <iprt/path.h>
49#include <iprt/string.h>
50#include <iprt/uri.h>
51#include <iprt/cpp/utils.h>
52
53#include <iprt/errcore.h>
54#include <VBox/param.h>
55#include <VBox/settings.h>
56#include <VBox/vd.h>
57#include <VBox/vmm/cpum.h>
58
59
60// constructor / destructor
61/////////////////////////////////////////////////////////////////////////////
62
63SystemProperties::SystemProperties()
64 : mParent(NULL)
65 , m(new settings::SystemProperties)
66 , m_fLoadedX86CPUProfiles(false)
67{
68}
69
70SystemProperties::~SystemProperties()
71{
72 delete m;
73}
74
75
76HRESULT SystemProperties::FinalConstruct()
77{
78 return BaseFinalConstruct();
79}
80
81void SystemProperties::FinalRelease()
82{
83 uninit();
84 BaseFinalRelease();
85}
86
87// public methods only for internal purposes
88/////////////////////////////////////////////////////////////////////////////
89
90/**
91 * Initializes the system information object.
92 *
93 * @returns COM result indicator
94 */
95HRESULT SystemProperties::init(VirtualBox *aParent)
96{
97 LogFlowThisFunc(("aParent=%p\n", aParent));
98
99 ComAssertRet(aParent, E_FAIL);
100
101 /* Enclose the state transition NotReady->InInit->Ready */
102 AutoInitSpan autoInitSpan(this);
103 AssertReturn(autoInitSpan.isOk(), E_FAIL);
104
105 unconst(mParent) = aParent;
106
107 i_setDefaultMachineFolder(Utf8Str::Empty);
108 i_setLoggingLevel(Utf8Str::Empty);
109 i_setDefaultHardDiskFormat(Utf8Str::Empty);
110
111 i_setVRDEAuthLibrary(Utf8Str::Empty);
112 i_setDefaultVRDEExtPack(Utf8Str::Empty);
113 i_setDefaultCryptoExtPack(Utf8Str::Empty);
114
115 m->uLogHistoryCount = 3;
116
117 HRESULT hrc = S_OK;
118
119 /* Fetch info of all available hd backends. */
120
121 /// @todo NEWMEDIA VDBackendInfo needs to be improved to let us enumerate
122 /// any number of backends
123
124 VDBACKENDINFO aVDInfo[100];
125 unsigned cEntries;
126 int vrc = VDBackendInfo(RT_ELEMENTS(aVDInfo), aVDInfo, &cEntries);
127 AssertRC(vrc);
128 if (RT_SUCCESS(vrc))
129 {
130 for (unsigned i = 0; i < cEntries; ++ i)
131 {
132 ComObjPtr<MediumFormat> hdf;
133 hrc = hdf.createObject();
134 if (FAILED(hrc)) break;
135
136 hrc = hdf->init(&aVDInfo[i]);
137 if (FAILED(hrc)) break;
138
139 m_llMediumFormats.push_back(hdf);
140 }
141 }
142
143 if (SUCCEEDED(hrc))
144 {
145 hrc = unconst(m_platformProperties).createObject();
146 if (SUCCEEDED(hrc))
147 {
148 hrc = m_platformProperties->init(mParent);
149 if (SUCCEEDED(hrc))
150 hrc = m_platformProperties->i_setArchitecture(PlatformProperties::s_getHostPlatformArchitecture());
151 }
152 }
153
154 /* Confirm a successful initialization */
155 if (SUCCEEDED(hrc))
156 autoInitSpan.setSucceeded();
157
158 return hrc;
159}
160
161/**
162 * Uninitializes the instance and sets the ready flag to FALSE.
163 * Called either from FinalRelease() or by the parent when it gets destroyed.
164 */
165void SystemProperties::uninit()
166{
167 LogFlowThisFunc(("\n"));
168
169 /* Enclose the state transition Ready->InUninit->NotReady */
170 AutoUninitSpan autoUninitSpan(this);
171 if (autoUninitSpan.uninitDone())
172 return;
173
174 unconst(mParent) = NULL;
175}
176
177// wrapped ISystemProperties properties
178/////////////////////////////////////////////////////////////////////////////
179
180HRESULT SystemProperties::getMinGuestRAM(ULONG *minRAM)
181
182{
183 /* no need to lock, this is const */
184 AssertCompile(MM_RAM_MIN_IN_MB >= SchemaDefs::MinGuestRAM);
185 *minRAM = MM_RAM_MIN_IN_MB;
186
187 return S_OK;
188}
189
190HRESULT SystemProperties::getMaxGuestRAM(ULONG *maxRAM)
191{
192 /* no need to lock, this is const */
193 AssertCompile(MM_RAM_MAX_IN_MB <= SchemaDefs::MaxGuestRAM);
194 ULONG maxRAMSys = MM_RAM_MAX_IN_MB;
195 ULONG maxRAMArch = maxRAMSys;
196 *maxRAM = RT_MIN(maxRAMSys, maxRAMArch);
197
198 return S_OK;
199}
200
201HRESULT SystemProperties::getMinGuestVRAM(ULONG *minVRAM)
202{
203 /* no need to lock, this is const */
204 *minVRAM = SchemaDefs::MinGuestVRAM;
205
206 return S_OK;
207}
208
209HRESULT SystemProperties::getMaxGuestVRAM(ULONG *maxVRAM)
210{
211 /* no need to lock, this is const */
212 *maxVRAM = SchemaDefs::MaxGuestVRAM;
213
214 return S_OK;
215}
216
217HRESULT SystemProperties::getMinGuestCPUCount(ULONG *minCPUCount)
218{
219 /* no need to lock, this is const */
220 *minCPUCount = SchemaDefs::MinCPUCount; // VMM_MIN_CPU_COUNT
221
222 return S_OK;
223}
224
225HRESULT SystemProperties::getMaxGuestCPUCount(ULONG *maxCPUCount)
226{
227 /* no need to lock, this is const */
228 *maxCPUCount = SchemaDefs::MaxCPUCount; // VMM_MAX_CPU_COUNT
229
230 return S_OK;
231}
232
233HRESULT SystemProperties::getMaxGuestMonitors(ULONG *maxMonitors)
234{
235
236 /* no need to lock, this is const */
237 *maxMonitors = SchemaDefs::MaxGuestMonitors;
238
239 return S_OK;
240}
241
242
243HRESULT SystemProperties::getInfoVDSize(LONG64 *infoVDSize)
244{
245 /*
246 * The BIOS supports currently 32 bit LBA numbers (implementing the full
247 * 48 bit range is in theory trivial, but the crappy compiler makes things
248 * more difficult). This translates to almost 2 TiBytes (to be on the safe
249 * side, the reported limit is 1 MiByte less than that, as the total number
250 * of sectors should fit in 32 bits, too), which should be enough for the
251 * moment. Since the MBR partition tables support only 32bit sector numbers
252 * and thus the BIOS can only boot from disks smaller than 2T this is a
253 * rather hard limit.
254 *
255 * The virtual ATA/SATA disks support complete LBA48, and SCSI supports
256 * LBA64 (almost, more like LBA55 in practice), so the theoretical maximum
257 * disk size is 128 PiByte/16 EiByte. The GUI works nicely with 6 orders
258 * of magnitude, but not with 11..13 orders of magnitude.
259 */
260 /* no need to lock, this is const */
261 *infoVDSize = 2 * _1T - _1M;
262
263 return S_OK;
264}
265
266
267HRESULT SystemProperties::getDefaultIoCacheSettingForStorageController(StorageControllerType_T aControllerType,
268 BOOL *aEnabled)
269{
270 /* no need to lock, this is const */
271 switch (aControllerType)
272 {
273 case StorageControllerType_LsiLogic:
274 case StorageControllerType_BusLogic:
275 case StorageControllerType_IntelAhci:
276 case StorageControllerType_LsiLogicSas:
277 case StorageControllerType_USB:
278 case StorageControllerType_NVMe:
279 case StorageControllerType_VirtioSCSI:
280 *aEnabled = false;
281 break;
282 case StorageControllerType_PIIX3:
283 case StorageControllerType_PIIX4:
284 case StorageControllerType_ICH6:
285 case StorageControllerType_I82078:
286 *aEnabled = true;
287 break;
288 default:
289 AssertMsgFailed(("Invalid controller type %d\n", aControllerType));
290 }
291 return S_OK;
292}
293
294HRESULT SystemProperties::getCPUProfiles(CPUArchitecture_T aArchitecture, const com::Utf8Str &aNamePattern,
295 std::vector<ComPtr<ICPUProfile> > &aProfiles)
296{
297 /*
298 * Validate and adjust the architecture.
299 */
300 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
301 CPUArchitecture_T enmSecondaryArch = aArchitecture;
302 bool fLoaded;
303 switch (aArchitecture)
304 {
305 case CPUArchitecture_Any:
306 aArchitecture = CPUArchitecture_AMD64;
307 RT_FALL_THROUGH();
308 case CPUArchitecture_AMD64:
309 enmSecondaryArch = CPUArchitecture_x86;
310 RT_FALL_THROUGH();
311 case CPUArchitecture_x86:
312 fLoaded = m_fLoadedX86CPUProfiles;
313 break;
314 default:
315 return setError(E_INVALIDARG, tr("Invalid or unsupported architecture value: %d"), aArchitecture);
316 }
317
318 /*
319 * Do we need to load the profiles?
320 */
321 HRESULT hrc;
322 if (fLoaded)
323 hrc = S_OK;
324 else
325 {
326 alock.release();
327 AutoWriteLock alockWrite(this COMMA_LOCKVAL_SRC_POS);
328
329 /*
330 * Translate the architecture to a VMM module handle.
331 */
332 const char *pszVMM;
333 switch (aArchitecture)
334 {
335 case CPUArchitecture_AMD64:
336 case CPUArchitecture_x86:
337 pszVMM = "VBoxVMM";
338 fLoaded = m_fLoadedX86CPUProfiles;
339 break;
340 default:
341 AssertFailedReturn(E_INVALIDARG);
342 }
343 if (fLoaded)
344 hrc = S_OK;
345 else
346 {
347 char szPath[RTPATH_MAX];
348 int vrc = RTPathAppPrivateArch(szPath, sizeof(szPath));
349 if (RT_SUCCESS(vrc))
350 vrc = RTPathAppend(szPath, sizeof(szPath), pszVMM);
351 if (RT_SUCCESS(vrc))
352 vrc = RTStrCat(szPath, sizeof(szPath), RTLdrGetSuff());
353 if (RT_SUCCESS(vrc))
354 {
355 RTLDRMOD hMod = NIL_RTLDRMOD;
356 vrc = RTLdrLoad(szPath, &hMod);
357 if (RT_SUCCESS(vrc))
358 {
359 /*
360 * Resolve the CPUMDb APIs we need.
361 */
362 PFNCPUMDBGETENTRIES pfnGetEntries
363 = (PFNCPUMDBGETENTRIES)RTLdrGetFunction(hMod, "CPUMR3DbGetEntries");
364 PFNCPUMDBGETENTRYBYINDEX pfnGetEntryByIndex
365 = (PFNCPUMDBGETENTRYBYINDEX)RTLdrGetFunction(hMod, "CPUMR3DbGetEntryByIndex");
366 if (pfnGetEntries && pfnGetEntryByIndex)
367 {
368 size_t const cExistingProfiles = m_llCPUProfiles.size();
369
370 /*
371 * Instantate the profiles.
372 */
373 hrc = S_OK;
374 uint32_t const cEntries = pfnGetEntries();
375 for (uint32_t i = 0; i < cEntries; i++)
376 {
377 PCCPUMDBENTRY pDbEntry = pfnGetEntryByIndex(i);
378 AssertBreakStmt(pDbEntry, hrc = setError(E_UNEXPECTED, "CPUMR3DbGetEntryByIndex failed for %i", i));
379
380 ComObjPtr<CPUProfile> ptrProfile;
381 hrc = ptrProfile.createObject();
382 if (SUCCEEDED(hrc))
383 {
384 hrc = ptrProfile->initFromDbEntry(pDbEntry);
385 if (SUCCEEDED(hrc))
386 {
387 try
388 {
389 m_llCPUProfiles.push_back(ptrProfile);
390 continue;
391 }
392 catch (std::bad_alloc &)
393 {
394 hrc = E_OUTOFMEMORY;
395 }
396 }
397 }
398 break;
399 }
400
401 /*
402 * On success update the flag and retake the read lock.
403 * If we fail, drop the profiles we added to the list.
404 */
405 if (SUCCEEDED(hrc))
406 {
407 switch (aArchitecture)
408 {
409 case CPUArchitecture_AMD64:
410 case CPUArchitecture_x86:
411 m_fLoadedX86CPUProfiles = true;
412 break;
413 default:
414 AssertFailedStmt(hrc = E_INVALIDARG);
415 }
416
417 alockWrite.release();
418 alock.acquire();
419 }
420 else
421 m_llCPUProfiles.resize(cExistingProfiles);
422 }
423 else
424 hrc = setErrorVrc(VERR_SYMBOL_NOT_FOUND,
425 tr("'%s' is missing symbols: CPUMR3DbGetEntries, CPUMR3DbGetEntryByIndex"), szPath);
426 RTLdrClose(hMod);
427 }
428 else
429 hrc = setErrorVrc(vrc, tr("Failed to construct load '%s': %Rrc"), szPath, vrc);
430 }
431 else
432 hrc = setErrorVrc(vrc, tr("Failed to construct path to the VMM DLL/Dylib/SharedObject: %Rrc"), vrc);
433 }
434 }
435 if (SUCCEEDED(hrc))
436 {
437 /*
438 * Return the matching profiles.
439 */
440 /* Count matches: */
441 size_t cMatches = 0;
442 for (CPUProfileList_T::const_iterator it = m_llCPUProfiles.begin(); it != m_llCPUProfiles.end(); ++it)
443 if ((*it)->i_match(aArchitecture, enmSecondaryArch, aNamePattern))
444 cMatches++;
445
446 /* Resize the output array. */
447 try
448 {
449 aProfiles.resize(cMatches);
450 }
451 catch (std::bad_alloc &)
452 {
453 aProfiles.resize(0);
454 hrc = E_OUTOFMEMORY;
455 }
456
457 /* Get the return objects: */
458 if (SUCCEEDED(hrc) && cMatches > 0)
459 {
460 size_t iMatch = 0;
461 for (CPUProfileList_T::const_iterator it = m_llCPUProfiles.begin(); it != m_llCPUProfiles.end(); ++it)
462 if ((*it)->i_match(aArchitecture, enmSecondaryArch, aNamePattern))
463 {
464 AssertBreakStmt(iMatch < cMatches, hrc = E_UNEXPECTED);
465 hrc = (*it).queryInterfaceTo(aProfiles[iMatch].asOutParam());
466 if (SUCCEEDED(hrc))
467 iMatch++;
468 else
469 break;
470 }
471 AssertStmt(iMatch == cMatches || FAILED(hrc), hrc = E_UNEXPECTED);
472 }
473 }
474 return hrc;
475}
476
477
478HRESULT SystemProperties::getDefaultMachineFolder(com::Utf8Str &aDefaultMachineFolder)
479{
480 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
481 aDefaultMachineFolder = m->strDefaultMachineFolder;
482 return S_OK;
483}
484
485HRESULT SystemProperties::setDefaultMachineFolder(const com::Utf8Str &aDefaultMachineFolder)
486{
487 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
488 HRESULT hrc = i_setDefaultMachineFolder(aDefaultMachineFolder);
489 alock.release();
490 if (SUCCEEDED(hrc))
491 {
492 // VirtualBox::i_saveSettings() needs vbox write lock
493 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
494 hrc = mParent->i_saveSettings();
495 }
496
497 return hrc;
498}
499
500HRESULT SystemProperties::getLoggingLevel(com::Utf8Str &aLoggingLevel)
501{
502 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
503
504 aLoggingLevel = m->strLoggingLevel;
505
506 if (aLoggingLevel.isEmpty())
507 aLoggingLevel = VBOXSVC_LOG_DEFAULT;
508
509 return S_OK;
510}
511
512
513HRESULT SystemProperties::setLoggingLevel(const com::Utf8Str &aLoggingLevel)
514{
515 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
516 HRESULT hrc = i_setLoggingLevel(aLoggingLevel);
517 alock.release();
518
519 if (SUCCEEDED(hrc))
520 {
521 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
522 hrc = mParent->i_saveSettings();
523 }
524 else
525 LogRel(("Cannot set passed logging level=%s, or the default one - Error=%Rhrc \n", aLoggingLevel.c_str(), hrc));
526
527 return hrc;
528}
529
530HRESULT SystemProperties::getMediumFormats(std::vector<ComPtr<IMediumFormat> > &aMediumFormats)
531{
532 MediumFormatList mediumFormats(m_llMediumFormats);
533 aMediumFormats.resize(mediumFormats.size());
534 size_t i = 0;
535 for (MediumFormatList::const_iterator it = mediumFormats.begin(); it != mediumFormats.end(); ++it, ++i)
536 (*it).queryInterfaceTo(aMediumFormats[i].asOutParam());
537 return S_OK;
538}
539
540HRESULT SystemProperties::getDefaultHardDiskFormat(com::Utf8Str &aDefaultHardDiskFormat)
541{
542 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
543 aDefaultHardDiskFormat = m->strDefaultHardDiskFormat;
544 return S_OK;
545}
546
547
548HRESULT SystemProperties::setDefaultHardDiskFormat(const com::Utf8Str &aDefaultHardDiskFormat)
549{
550 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
551 HRESULT hrc = i_setDefaultHardDiskFormat(aDefaultHardDiskFormat);
552 alock.release();
553 if (SUCCEEDED(hrc))
554 {
555 // VirtualBox::i_saveSettings() needs vbox write lock
556 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
557 hrc = mParent->i_saveSettings();
558 }
559
560 return hrc;
561}
562
563HRESULT SystemProperties::getFreeDiskSpaceWarning(LONG64 *aFreeSpace)
564{
565 NOREF(aFreeSpace);
566 ReturnComNotImplemented();
567}
568
569HRESULT SystemProperties::setFreeDiskSpaceWarning(LONG64 /* aFreeSpace */)
570{
571 ReturnComNotImplemented();
572}
573
574HRESULT SystemProperties::getFreeDiskSpacePercentWarning(ULONG *aFreeSpacePercent)
575{
576 NOREF(aFreeSpacePercent);
577 ReturnComNotImplemented();
578}
579
580HRESULT SystemProperties::setFreeDiskSpacePercentWarning(ULONG /* aFreeSpacePercent */)
581{
582 ReturnComNotImplemented();
583}
584
585HRESULT SystemProperties::getFreeDiskSpaceError(LONG64 *aFreeSpace)
586{
587 NOREF(aFreeSpace);
588 ReturnComNotImplemented();
589}
590
591HRESULT SystemProperties::setFreeDiskSpaceError(LONG64 /* aFreeSpace */)
592{
593 ReturnComNotImplemented();
594}
595
596HRESULT SystemProperties::getFreeDiskSpacePercentError(ULONG *aFreeSpacePercent)
597{
598 NOREF(aFreeSpacePercent);
599 ReturnComNotImplemented();
600}
601
602HRESULT SystemProperties::setFreeDiskSpacePercentError(ULONG /* aFreeSpacePercent */)
603{
604 ReturnComNotImplemented();
605}
606
607HRESULT SystemProperties::getVRDEAuthLibrary(com::Utf8Str &aVRDEAuthLibrary)
608{
609 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
610
611 aVRDEAuthLibrary = m->strVRDEAuthLibrary;
612
613 return S_OK;
614}
615
616HRESULT SystemProperties::setVRDEAuthLibrary(const com::Utf8Str &aVRDEAuthLibrary)
617{
618 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
619 HRESULT hrc = i_setVRDEAuthLibrary(aVRDEAuthLibrary);
620 alock.release();
621 if (SUCCEEDED(hrc))
622 {
623 // VirtualBox::i_saveSettings() needs vbox write lock
624 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
625 hrc = mParent->i_saveSettings();
626 }
627
628 return hrc;
629}
630
631HRESULT SystemProperties::getWebServiceAuthLibrary(com::Utf8Str &aWebServiceAuthLibrary)
632{
633 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
634
635 aWebServiceAuthLibrary = m->strWebServiceAuthLibrary;
636
637 return S_OK;
638}
639
640HRESULT SystemProperties::setWebServiceAuthLibrary(const com::Utf8Str &aWebServiceAuthLibrary)
641{
642 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
643 HRESULT hrc = i_setWebServiceAuthLibrary(aWebServiceAuthLibrary);
644 alock.release();
645
646 if (SUCCEEDED(hrc))
647 {
648 // VirtualBox::i_saveSettings() needs vbox write lock
649 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
650 hrc = mParent->i_saveSettings();
651 }
652
653 return hrc;
654}
655
656HRESULT SystemProperties::getDefaultVRDEExtPack(com::Utf8Str &aExtPack)
657{
658 HRESULT hrc = S_OK;
659 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
660 Utf8Str strExtPack(m->strDefaultVRDEExtPack);
661 if (strExtPack.isNotEmpty())
662 {
663 if (strExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
664 hrc = S_OK;
665 else
666#ifdef VBOX_WITH_EXTPACK
667 hrc = mParent->i_getExtPackManager()->i_checkVrdeExtPack(&strExtPack);
668#else
669 hrc = setError(E_FAIL, tr("The extension pack '%s' does not exist"), strExtPack.c_str());
670#endif
671 }
672 else
673 {
674#ifdef VBOX_WITH_EXTPACK
675 hrc = mParent->i_getExtPackManager()->i_getDefaultVrdeExtPack(&strExtPack);
676#endif
677 if (strExtPack.isEmpty())
678 {
679 /*
680 * Klugde - check if VBoxVRDP.dll/.so/.dylib is installed.
681 * This is hardcoded uglyness, sorry.
682 */
683 char szPath[RTPATH_MAX];
684 int vrc = RTPathAppPrivateArch(szPath, sizeof(szPath));
685 if (RT_SUCCESS(vrc))
686 vrc = RTPathAppend(szPath, sizeof(szPath), "VBoxVRDP");
687 if (RT_SUCCESS(vrc))
688 vrc = RTStrCat(szPath, sizeof(szPath), RTLdrGetSuff());
689 if (RT_SUCCESS(vrc) && RTFileExists(szPath))
690 {
691 /* Illegal extpack name, so no conflict. */
692 strExtPack = VBOXVRDP_KLUDGE_EXTPACK_NAME;
693 }
694 }
695 }
696
697 if (SUCCEEDED(hrc))
698 aExtPack = strExtPack;
699
700 return S_OK;
701}
702
703
704HRESULT SystemProperties::setDefaultVRDEExtPack(const com::Utf8Str &aExtPack)
705{
706 HRESULT hrc = S_OK;
707 if (aExtPack.isNotEmpty())
708 {
709 if (aExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
710 hrc = S_OK;
711 else
712#ifdef VBOX_WITH_EXTPACK
713 hrc = mParent->i_getExtPackManager()->i_checkVrdeExtPack(&aExtPack);
714#else
715 hrc = setError(E_FAIL, tr("The extension pack '%s' does not exist"), aExtPack.c_str());
716#endif
717 }
718 if (SUCCEEDED(hrc))
719 {
720 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
721 hrc = i_setDefaultVRDEExtPack(aExtPack);
722 if (SUCCEEDED(hrc))
723 {
724 /* VirtualBox::i_saveSettings() needs the VirtualBox write lock. */
725 alock.release();
726 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
727 hrc = mParent->i_saveSettings();
728 }
729 }
730
731 return hrc;
732}
733
734
735HRESULT SystemProperties::getDefaultCryptoExtPack(com::Utf8Str &aExtPack)
736{
737 HRESULT hrc = S_OK;
738 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
739 Utf8Str strExtPack(m->strDefaultCryptoExtPack);
740 if (strExtPack.isNotEmpty())
741 {
742 if (strExtPack.equals(VBOXPUELCRYPTO_KLUDGE_EXTPACK_NAME))
743 hrc = S_OK;
744 else
745#ifdef VBOX_WITH_EXTPACK
746 hrc = mParent->i_getExtPackManager()->i_checkCryptoExtPack(&strExtPack);
747#else
748 hrc = setError(E_FAIL, tr("The extension pack '%s' does not exist"), strExtPack.c_str());
749#endif
750 }
751 else
752 {
753#ifdef VBOX_WITH_EXTPACK
754 hrc = mParent->i_getExtPackManager()->i_getDefaultCryptoExtPack(&strExtPack);
755#endif
756 if (strExtPack.isEmpty())
757 {
758 /*
759 * Klugde - check if VBoxPuelCrypto.dll/.so/.dylib is installed.
760 * This is hardcoded uglyness, sorry.
761 */
762 char szPath[RTPATH_MAX];
763 int vrc = RTPathAppPrivateArch(szPath, sizeof(szPath));
764 if (RT_SUCCESS(vrc))
765 vrc = RTPathAppend(szPath, sizeof(szPath), "VBoxPuelCrypto");
766 if (RT_SUCCESS(vrc))
767 vrc = RTStrCat(szPath, sizeof(szPath), RTLdrGetSuff());
768 if (RT_SUCCESS(vrc) && RTFileExists(szPath))
769 {
770 /* Illegal extpack name, so no conflict. */
771 strExtPack = VBOXPUELCRYPTO_KLUDGE_EXTPACK_NAME;
772 }
773 }
774 }
775
776 if (SUCCEEDED(hrc))
777 aExtPack = strExtPack;
778
779 return S_OK;
780}
781
782
783HRESULT SystemProperties::setDefaultCryptoExtPack(const com::Utf8Str &aExtPack)
784{
785 HRESULT hrc = S_OK;
786 if (aExtPack.isNotEmpty())
787 {
788 if (aExtPack.equals(VBOXPUELCRYPTO_KLUDGE_EXTPACK_NAME))
789 hrc = S_OK;
790 else
791#ifdef VBOX_WITH_EXTPACK
792 hrc = mParent->i_getExtPackManager()->i_checkCryptoExtPack(&aExtPack);
793#else
794 hrc = setError(E_FAIL, tr("The extension pack '%s' does not exist"), aExtPack.c_str());
795#endif
796 }
797 if (SUCCEEDED(hrc))
798 {
799 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
800 hrc = i_setDefaultCryptoExtPack(aExtPack);
801 if (SUCCEEDED(hrc))
802 {
803 /* VirtualBox::i_saveSettings() needs the VirtualBox write lock. */
804 alock.release();
805 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
806 hrc = mParent->i_saveSettings();
807 }
808 }
809
810 return hrc;
811}
812
813
814HRESULT SystemProperties::getLogHistoryCount(ULONG *count)
815{
816 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
817
818 *count = m->uLogHistoryCount;
819
820 return S_OK;
821}
822
823
824HRESULT SystemProperties::setLogHistoryCount(ULONG count)
825{
826 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
827 m->uLogHistoryCount = count;
828 alock.release();
829
830 // VirtualBox::i_saveSettings() needs vbox write lock
831 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
832 return mParent->i_saveSettings();
833}
834
835HRESULT SystemProperties::getDefaultAudioDriver(AudioDriverType_T *aAudioDriver)
836{
837 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
838
839 *aAudioDriver = settings::MachineConfigFile::getHostDefaultAudioDriver();
840
841 return S_OK;
842}
843
844HRESULT SystemProperties::getAutostartDatabasePath(com::Utf8Str &aAutostartDbPath)
845{
846 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
847
848 aAutostartDbPath = m->strAutostartDatabasePath;
849
850 return S_OK;
851}
852
853HRESULT SystemProperties::setAutostartDatabasePath(const com::Utf8Str &aAutostartDbPath)
854{
855 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
856 HRESULT hrc = i_setAutostartDatabasePath(aAutostartDbPath);
857 alock.release();
858
859 if (SUCCEEDED(hrc))
860 {
861 // VirtualBox::i_saveSettings() needs vbox write lock
862 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
863 hrc = mParent->i_saveSettings();
864 }
865
866 return hrc;
867}
868
869HRESULT SystemProperties::getDefaultAdditionsISO(com::Utf8Str &aDefaultAdditionsISO)
870{
871 return i_getDefaultAdditionsISO(aDefaultAdditionsISO);
872}
873
874HRESULT SystemProperties::setDefaultAdditionsISO(const com::Utf8Str &aDefaultAdditionsISO)
875{
876 RT_NOREF(aDefaultAdditionsISO);
877 /** @todo not yet implemented, settings handling is missing */
878 ReturnComNotImplemented();
879#if 0 /* not implemented */
880 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
881 HRESULT hrc = i_setDefaultAdditionsISO(aDefaultAdditionsISO);
882 alock.release();
883
884 if (SUCCEEDED(hrc))
885 {
886 // VirtualBox::i_saveSettings() needs vbox write lock
887 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
888 hrc = mParent->i_saveSettings();
889 }
890
891 return hrc;
892#endif
893}
894
895HRESULT SystemProperties::getDefaultFrontend(com::Utf8Str &aDefaultFrontend)
896{
897 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
898 aDefaultFrontend = m->strDefaultFrontend;
899 return S_OK;
900}
901
902HRESULT SystemProperties::setDefaultFrontend(const com::Utf8Str &aDefaultFrontend)
903{
904 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
905 if (m->strDefaultFrontend == aDefaultFrontend)
906 return S_OK;
907 HRESULT hrc = i_setDefaultFrontend(aDefaultFrontend);
908 alock.release();
909
910 if (SUCCEEDED(hrc))
911 {
912 // VirtualBox::i_saveSettings() needs vbox write lock
913 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
914 hrc = mParent->i_saveSettings();
915 }
916
917 return hrc;
918}
919
920HRESULT SystemProperties::getScreenShotFormats(std::vector<BitmapFormat_T> &aBitmapFormats)
921{
922 aBitmapFormats.push_back(BitmapFormat_BGR0);
923 aBitmapFormats.push_back(BitmapFormat_BGRA);
924 aBitmapFormats.push_back(BitmapFormat_RGBA);
925 aBitmapFormats.push_back(BitmapFormat_PNG);
926 return S_OK;
927}
928
929HRESULT SystemProperties::getPlatform(ComPtr<IPlatformProperties> &aPlatformProperties)
930{
931 /* No need to lock, as m_platformProperties is const. */
932
933 return m_platformProperties.queryInterfaceTo(aPlatformProperties.asOutParam());
934}
935
936HRESULT SystemProperties::getProxyMode(ProxyMode_T *pProxyMode)
937{
938 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
939 ProxyMode_T enmMode = *pProxyMode = (ProxyMode_T)m->uProxyMode;
940 AssertMsgReturn(enmMode == ProxyMode_System || enmMode == ProxyMode_NoProxy || enmMode == ProxyMode_Manual,
941 ("enmMode=%d\n", enmMode), E_UNEXPECTED);
942 return S_OK;
943}
944
945HRESULT SystemProperties::setProxyMode(ProxyMode_T aProxyMode)
946{
947 /* Validate input. */
948 switch (aProxyMode)
949 {
950 case ProxyMode_System:
951 case ProxyMode_NoProxy:
952 case ProxyMode_Manual:
953 break;
954 default:
955 return setError(E_INVALIDARG, tr("Invalid ProxyMode value: %d"), (int)aProxyMode);
956 }
957
958 /* Set and write out settings. */
959 {
960 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
961 m->uProxyMode = aProxyMode;
962 }
963 AutoWriteLock alock(mParent COMMA_LOCKVAL_SRC_POS); /* required for saving. */
964 return mParent->i_saveSettings();
965}
966
967HRESULT SystemProperties::getProxyURL(com::Utf8Str &aProxyURL)
968{
969 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
970 aProxyURL = m->strProxyUrl;
971 return S_OK;
972}
973
974HRESULT SystemProperties::setProxyURL(const com::Utf8Str &aProxyURL)
975{
976 /*
977 * Validate input.
978 */
979 Utf8Str const *pStrProxyUrl = &aProxyURL;
980 Utf8Str strTmp;
981 if (pStrProxyUrl->isNotEmpty())
982 {
983 /* RTUriParse requires a scheme, so append 'http://' if none seems present: */
984 if (pStrProxyUrl->find("://") == RTCString::npos)
985 {
986 strTmp.printf("http://%s", aProxyURL.c_str());
987 pStrProxyUrl = &strTmp;
988 }
989
990 /* Use RTUriParse to check the format. There must be a hostname, but nothing
991 can follow it and the port. */
992 RTURIPARSED Parsed;
993 int vrc = RTUriParse(pStrProxyUrl->c_str(), &Parsed);
994 if (RT_FAILURE(vrc))
995 return setErrorBoth(E_INVALIDARG, vrc, tr("Failed to parse proxy URL: %Rrc"), vrc);
996 if ( Parsed.cchAuthorityHost == 0
997 && !RTUriIsSchemeMatch(pStrProxyUrl->c_str(), "direct"))
998 return setError(E_INVALIDARG, tr("Proxy URL must include a hostname"));
999 if (Parsed.cchPath > 0)
1000 return setError(E_INVALIDARG, tr("Proxy URL must not include a path component (%.*s)"),
1001 Parsed.cchPath, pStrProxyUrl->c_str() + Parsed.offPath);
1002 if (Parsed.cchQuery > 0)
1003 return setError(E_INVALIDARG, tr("Proxy URL must not include a query component (?%.*s)"),
1004 Parsed.cchQuery, pStrProxyUrl->c_str() + Parsed.offQuery);
1005 if (Parsed.cchFragment > 0)
1006 return setError(E_INVALIDARG, tr("Proxy URL must not include a fragment component (#%.*s)"),
1007 Parsed.cchFragment, pStrProxyUrl->c_str() + Parsed.offFragment);
1008 }
1009
1010 /*
1011 * Set and write out settings.
1012 */
1013 {
1014 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1015 m->strProxyUrl = *pStrProxyUrl;
1016 }
1017 AutoWriteLock alock(mParent COMMA_LOCKVAL_SRC_POS); /* required for saving. */
1018 return mParent->i_saveSettings();
1019}
1020
1021HRESULT SystemProperties::getSupportedPlatformArchitectures(std::vector<PlatformArchitecture_T> &aSupportedPlatformArchitectures)
1022{
1023 static const PlatformArchitecture_T s_aPlatformArchitectures[] =
1024 {
1025#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
1026 /* Currently x86 can run x86 VMs only. */
1027 PlatformArchitecture_x86
1028#elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
1029 /* Currently ARM can run x86 emulation and if enabled ARM VMs. */
1030 PlatformArchitecture_x86
1031# ifdef VBOX_WITH_VIRT_ARMV8
1032 , PlatformArchitecture_ARM
1033# endif
1034#else
1035# error "Port me!"
1036 PlatformArchitecture_None
1037#endif
1038 };
1039 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedPlatformArchitectures, s_aPlatformArchitectures);
1040
1041#ifdef VBOX_WITH_VIRT_ARMV8
1042 Bstr bstrEnableX86OnArm;
1043 HRESULT hrc =mParent->GetExtraData(Bstr("VBoxInternal2/EnableX86OnArm").raw(), bstrEnableX86OnArm.asOutParam());
1044 if (FAILED(hrc) || !bstrEnableX86OnArm.equals("1"))
1045 {
1046 Assert(aSupportedPlatformArchitectures[0] == PlatformArchitecture_x86);
1047 if (aSupportedPlatformArchitectures[0] == PlatformArchitecture_x86)
1048 aSupportedPlatformArchitectures.erase(aSupportedPlatformArchitectures.begin());
1049 }
1050#endif
1051 return S_OK;
1052}
1053
1054HRESULT SystemProperties::getSupportedClipboardModes(std::vector<ClipboardMode_T> &aSupportedClipboardModes)
1055{
1056 static const ClipboardMode_T s_aClipboardModes[] =
1057 {
1058 ClipboardMode_Disabled,
1059 ClipboardMode_HostToGuest,
1060 ClipboardMode_GuestToHost,
1061 ClipboardMode_Bidirectional,
1062 };
1063 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedClipboardModes, s_aClipboardModes);
1064 return S_OK;
1065}
1066
1067HRESULT SystemProperties::getSupportedDnDModes(std::vector<DnDMode_T> &aSupportedDnDModes)
1068{
1069 static const DnDMode_T s_aDnDModes[] =
1070 {
1071 DnDMode_Disabled,
1072 DnDMode_HostToGuest,
1073 DnDMode_GuestToHost,
1074 DnDMode_Bidirectional,
1075 };
1076 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedDnDModes, s_aDnDModes);
1077 return S_OK;
1078}
1079
1080HRESULT SystemProperties::getSupportedPointingHIDTypes(std::vector<PointingHIDType_T> &aSupportedPointingHIDTypes)
1081{
1082 static const PointingHIDType_T s_aPointingHIDTypes[] =
1083 {
1084 PointingHIDType_PS2Mouse,
1085#ifdef DEBUG
1086 PointingHIDType_USBMouse,
1087#endif
1088 PointingHIDType_USBTablet,
1089#ifdef DEBUG
1090 PointingHIDType_ComboMouse,
1091#endif
1092 PointingHIDType_USBMultiTouch,
1093 PointingHIDType_USBMultiTouchScreenPlusPad,
1094 };
1095 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedPointingHIDTypes, s_aPointingHIDTypes);
1096 return S_OK;
1097}
1098
1099HRESULT SystemProperties::getSupportedKeyboardHIDTypes(std::vector<KeyboardHIDType_T> &aSupportedKeyboardHIDTypes)
1100{
1101 static const KeyboardHIDType_T s_aKeyboardHIDTypes[] =
1102 {
1103 KeyboardHIDType_PS2Keyboard,
1104 KeyboardHIDType_USBKeyboard,
1105#ifdef DEBUG
1106 KeyboardHIDType_ComboKeyboard,
1107#endif
1108 };
1109 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedKeyboardHIDTypes, s_aKeyboardHIDTypes);
1110 return S_OK;
1111}
1112
1113HRESULT SystemProperties::getSupportedVFSTypes(std::vector<VFSType_T> &aSupportedVFSTypes)
1114{
1115 static const VFSType_T s_aVFSTypes[] =
1116 {
1117 VFSType_File,
1118 VFSType_Cloud,
1119 VFSType_S3,
1120#ifdef DEBUG
1121 VFSType_WebDav,
1122#endif
1123 };
1124 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedVFSTypes, s_aVFSTypes);
1125 return S_OK;
1126}
1127
1128HRESULT SystemProperties::getSupportedImportOptions(std::vector<ImportOptions_T> &aSupportedImportOptions)
1129{
1130 static const ImportOptions_T s_aImportOptions[] =
1131 {
1132 ImportOptions_KeepAllMACs,
1133 ImportOptions_KeepNATMACs,
1134 ImportOptions_ImportToVDI,
1135 };
1136 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedImportOptions, s_aImportOptions);
1137 return S_OK;
1138}
1139
1140HRESULT SystemProperties::getSupportedExportOptions(std::vector<ExportOptions_T> &aSupportedExportOptions)
1141{
1142 static const ExportOptions_T s_aExportOptions[] =
1143 {
1144 ExportOptions_CreateManifest,
1145 ExportOptions_ExportDVDImages,
1146 ExportOptions_StripAllMACs,
1147 ExportOptions_StripAllNonNATMACs,
1148 };
1149 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedExportOptions, s_aExportOptions);
1150 return S_OK;
1151}
1152
1153HRESULT SystemProperties::getSupportedGraphicsFeatures(std::vector<GraphicsFeature_T> &aSupportedGraphicsFeatures)
1154{
1155 static const GraphicsFeature_T s_aGraphicsFeatures[] =
1156 {
1157#ifdef VBOX_WITH_VIDEOHWACCEL
1158 GraphicsFeature_Acceleration2DVideo,
1159#endif
1160#ifdef VBOX_WITH_3D_ACCELERATION
1161 GraphicsFeature_Acceleration3D
1162#endif
1163 };
1164 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedGraphicsFeatures, s_aGraphicsFeatures);
1165
1166 return S_OK;
1167}
1168
1169HRESULT SystemProperties::getSupportedRecordingFeatures(std::vector<RecordingFeature_T> &aSupportedRecordingFeatures)
1170{
1171#ifdef VBOX_WITH_RECORDING
1172 static const RecordingFeature_T s_aRecordingFeatures[] =
1173 {
1174# ifdef VBOX_WITH_AUDIO_RECORDING
1175 RecordingFeature_Audio,
1176# endif
1177 RecordingFeature_Video,
1178 };
1179 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedRecordingFeatures, s_aRecordingFeatures);
1180#else /* !VBOX_WITH_RECORDING */
1181 aSupportedRecordingFeatures.clear();
1182#endif /* VBOX_WITH_RECORDING */
1183 return S_OK;
1184}
1185
1186HRESULT SystemProperties::getSupportedRecordingAudioCodecs(std::vector<RecordingAudioCodec_T> &aSupportedRecordingAudioCodecs)
1187{
1188 static const RecordingAudioCodec_T s_aRecordingAudioCodecs[] =
1189 {
1190 RecordingAudioCodec_None,
1191#ifdef DEBUG
1192 RecordingAudioCodec_WavPCM,
1193#endif
1194#ifdef VBOX_WITH_LIBVORBIS
1195 RecordingAudioCodec_OggVorbis,
1196#endif
1197 };
1198 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedRecordingAudioCodecs, s_aRecordingAudioCodecs);
1199 return S_OK;
1200}
1201
1202HRESULT SystemProperties::getSupportedRecordingVideoCodecs(std::vector<RecordingVideoCodec_T> &aSupportedRecordingVideoCodecs)
1203{
1204 static const RecordingVideoCodec_T s_aRecordingVideoCodecs[] =
1205 {
1206 RecordingVideoCodec_None,
1207#ifdef VBOX_WITH_LIBVPX
1208 RecordingVideoCodec_VP8,
1209#endif
1210#ifdef DEBUG
1211 RecordingVideoCodec_VP9,
1212 RecordingVideoCodec_AV1,
1213#endif
1214 };
1215 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedRecordingVideoCodecs, s_aRecordingVideoCodecs);
1216 return S_OK;
1217}
1218
1219HRESULT SystemProperties::getSupportedRecordingVSModes(std::vector<RecordingVideoScalingMode_T> &aSupportedRecordingVideoScalingModes)
1220{
1221 static const RecordingVideoScalingMode_T s_aRecordingVideoScalingModes[] =
1222 {
1223 RecordingVideoScalingMode_None,
1224#ifdef DEBUG
1225 RecordingVideoScalingMode_NearestNeighbor,
1226 RecordingVideoScalingMode_Bilinear,
1227 RecordingVideoScalingMode_Bicubic,
1228#endif
1229 };
1230 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedRecordingVideoScalingModes, s_aRecordingVideoScalingModes);
1231 return S_OK;
1232}
1233
1234HRESULT SystemProperties::getSupportedRecordingARCModes(std::vector<RecordingRateControlMode_T> &aSupportedRecordingAudioRateControlModes)
1235{
1236 static const RecordingRateControlMode_T s_aRecordingAudioRateControlModes[] =
1237 {
1238#ifdef DEBUG
1239 RecordingRateControlMode_ABR,
1240 RecordingRateControlMode_CBR,
1241#endif
1242 RecordingRateControlMode_VBR
1243 };
1244 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedRecordingAudioRateControlModes, s_aRecordingAudioRateControlModes);
1245 return S_OK;
1246}
1247
1248HRESULT SystemProperties::getSupportedRecordingVRCModes(std::vector<RecordingRateControlMode_T> &aSupportedRecordingVideoRateControlModes)
1249{
1250 static const RecordingRateControlMode_T s_aRecordingVideoRateControlModes[] =
1251 {
1252#ifdef DEBUG
1253 RecordingRateControlMode_ABR,
1254 RecordingRateControlMode_CBR,
1255#endif
1256 RecordingRateControlMode_VBR
1257 };
1258 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedRecordingVideoRateControlModes, s_aRecordingVideoRateControlModes);
1259 return S_OK;
1260}
1261
1262HRESULT SystemProperties::getSupportedCloneOptions(std::vector<CloneOptions_T> &aSupportedCloneOptions)
1263{
1264 static const CloneOptions_T s_aCloneOptions[] =
1265 {
1266 CloneOptions_Link,
1267 CloneOptions_KeepAllMACs,
1268 CloneOptions_KeepNATMACs,
1269 CloneOptions_KeepDiskNames,
1270 CloneOptions_KeepHwUUIDs,
1271 };
1272 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedCloneOptions, s_aCloneOptions);
1273 return S_OK;
1274}
1275
1276HRESULT SystemProperties::getSupportedAutostopTypes(std::vector<AutostopType_T> &aSupportedAutostopTypes)
1277{
1278 static const AutostopType_T s_aAutostopTypes[] =
1279 {
1280 AutostopType_Disabled,
1281 AutostopType_SaveState,
1282 AutostopType_PowerOff,
1283 AutostopType_AcpiShutdown,
1284 };
1285 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedAutostopTypes, s_aAutostopTypes);
1286 return S_OK;
1287}
1288
1289HRESULT SystemProperties::getSupportedVMProcPriorities(std::vector<VMProcPriority_T> &aSupportedVMProcPriorities)
1290{
1291 static const VMProcPriority_T s_aVMProcPriorities[] =
1292 {
1293 VMProcPriority_Default,
1294 VMProcPriority_Flat,
1295 VMProcPriority_Low,
1296 VMProcPriority_Normal,
1297 VMProcPriority_High,
1298 };
1299 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedVMProcPriorities, s_aVMProcPriorities);
1300 return S_OK;
1301}
1302
1303HRESULT SystemProperties::getSupportedNetworkAttachmentTypes(std::vector<NetworkAttachmentType_T> &aSupportedNetworkAttachmentTypes)
1304{
1305 static const NetworkAttachmentType_T s_aNetworkAttachmentTypes[] =
1306 {
1307 NetworkAttachmentType_NAT,
1308 NetworkAttachmentType_Bridged,
1309 NetworkAttachmentType_Internal,
1310 NetworkAttachmentType_HostOnly,
1311#ifdef VBOX_WITH_VMNET
1312 NetworkAttachmentType_HostOnlyNetwork,
1313#endif /* VBOX_WITH_VMNET */
1314 NetworkAttachmentType_Generic,
1315 NetworkAttachmentType_NATNetwork,
1316#ifdef VBOX_WITH_CLOUD_NET
1317 NetworkAttachmentType_Cloud,
1318#endif
1319 NetworkAttachmentType_Null,
1320 };
1321 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedNetworkAttachmentTypes, s_aNetworkAttachmentTypes);
1322 return S_OK;
1323}
1324
1325HRESULT SystemProperties::getSupportedPortModes(std::vector<PortMode_T> &aSupportedPortModes)
1326{
1327 static const PortMode_T s_aPortModes[] =
1328 {
1329 PortMode_Disconnected,
1330 PortMode_HostPipe,
1331 PortMode_HostDevice,
1332 PortMode_RawFile,
1333 PortMode_TCP,
1334 };
1335 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedPortModes, s_aPortModes);
1336 return S_OK;
1337}
1338
1339HRESULT SystemProperties::getSupportedAudioDriverTypes(std::vector<AudioDriverType_T> &aSupportedAudioDriverTypes)
1340{
1341 static const AudioDriverType_T s_aAudioDriverTypes[] =
1342 {
1343 AudioDriverType_Default,
1344#ifdef RT_OS_WINDOWS
1345# if 0 /* deprecated for many years now */
1346 AudioDriverType_WinMM,
1347# endif
1348 AudioDriverType_WAS,
1349 AudioDriverType_DirectSound,
1350#endif
1351#ifdef RT_OS_DARWIN
1352 AudioDriverType_CoreAudio,
1353#endif
1354#ifdef RT_OS_OS2
1355 AudioDriverType_MMPM,
1356#endif
1357#ifdef RT_OS_SOLARIS
1358# if 0 /* deprecated for many years now */
1359 AudioDriverType_SolAudio,
1360# endif
1361#endif
1362#ifdef VBOX_WITH_AUDIO_ALSA
1363 AudioDriverType_ALSA,
1364#endif
1365#ifdef VBOX_WITH_AUDIO_OSS
1366 AudioDriverType_OSS,
1367#endif
1368#ifdef VBOX_WITH_AUDIO_PULSE
1369 AudioDriverType_Pulse,
1370#endif
1371 AudioDriverType_Null,
1372 };
1373 RT_CPP_VECTOR_ASSIGN_ARRAY(aSupportedAudioDriverTypes, s_aAudioDriverTypes);
1374 return S_OK;
1375}
1376
1377HRESULT SystemProperties::getExecutionEnginesForVmCpuArchitecture(CPUArchitecture_T aCpuArchitecture,
1378 std::vector<VMExecutionEngine_T> &aExecutionEngines)
1379{
1380 switch (aCpuArchitecture)
1381 {
1382 case CPUArchitecture_x86:
1383 case CPUArchitecture_AMD64:
1384 {
1385 static const VMExecutionEngine_T s_aExecEngines[] =
1386 {
1387 VMExecutionEngine_Default,
1388#ifdef RT_ARCH_AMD64
1389# ifndef VBOX_WITH_DRIVERLESS_FORCED
1390 VMExecutionEngine_HwVirt,
1391# endif
1392# ifdef VBOX_WITH_NATIVE_NEM
1393 VMExecutionEngine_NativeApi,
1394# endif
1395#endif
1396 VMExecutionEngine_Interpreter,
1397#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
1398 VMExecutionEngine_Recompiler,
1399#endif
1400 };
1401 RT_CPP_VECTOR_ASSIGN_ARRAY(aExecutionEngines, s_aExecEngines);
1402 break;
1403 }
1404
1405 case CPUArchitecture_ARMv8_32:
1406 aExecutionEngines.clear(); /* Currently not supported at all. */
1407 break;
1408
1409 case CPUArchitecture_ARMv8_64:
1410 {
1411#ifdef VBOX_WITH_VIRT_ARMV8
1412 static const VMExecutionEngine_T s_aExecEngines[] =
1413 {
1414 VMExecutionEngine_Default,
1415# ifdef VBOX_WITH_NATIVE_NEM
1416 VMExecutionEngine_NativeApi,
1417# endif
1418 };
1419 RT_CPP_VECTOR_ASSIGN_ARRAY(aExecutionEngines, s_aExecEngines);
1420#else
1421 aExecutionEngines.clear();
1422#endif
1423 break;
1424 }
1425
1426 default:
1427 AssertFailedStmt(aExecutionEngines.clear());
1428 break;
1429 }
1430
1431 return S_OK;
1432}
1433
1434
1435// public methods only for internal purposes
1436/////////////////////////////////////////////////////////////////////////////
1437
1438HRESULT SystemProperties::i_loadSettings(const settings::SystemProperties &data)
1439{
1440 AutoCaller autoCaller(this);
1441 if (FAILED(autoCaller.hrc())) return autoCaller.hrc();
1442
1443 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1444
1445 i_setLoggingLevel(data.strLoggingLevel); /* ignore errors here! */
1446
1447 HRESULT hrc = i_setDefaultMachineFolder(data.strDefaultMachineFolder);
1448 if (FAILED(hrc)) return hrc;
1449
1450 hrc = i_setDefaultHardDiskFormat(data.strDefaultHardDiskFormat);
1451 if (FAILED(hrc)) return hrc;
1452
1453 hrc = i_setVRDEAuthLibrary(data.strVRDEAuthLibrary);
1454 if (FAILED(hrc)) return hrc;
1455
1456 hrc = i_setWebServiceAuthLibrary(data.strWebServiceAuthLibrary);
1457 if (FAILED(hrc)) return hrc;
1458
1459 hrc = i_setDefaultVRDEExtPack(data.strDefaultVRDEExtPack);
1460 if (FAILED(hrc)) return hrc;
1461
1462 hrc = i_setDefaultCryptoExtPack(data.strDefaultCryptoExtPack);
1463 if (FAILED(hrc)) return hrc;
1464
1465 m->uLogHistoryCount = data.uLogHistoryCount;
1466 m->uProxyMode = data.uProxyMode;
1467 m->strProxyUrl = data.strProxyUrl;
1468
1469 m->strLanguageId = data.strLanguageId;
1470
1471 hrc = i_setAutostartDatabasePath(data.strAutostartDatabasePath);
1472 if (FAILED(hrc)) return hrc;
1473
1474 {
1475 /* must ignore errors signalled here, because the guest additions
1476 * file may not exist, and in this case keep the empty string */
1477 ErrorInfoKeeper eik;
1478 (void)i_setDefaultAdditionsISO(data.strDefaultAdditionsISO);
1479 }
1480
1481 hrc = i_setDefaultFrontend(data.strDefaultFrontend);
1482 if (FAILED(hrc)) return hrc;
1483
1484 return S_OK;
1485}
1486
1487HRESULT SystemProperties::i_saveSettings(settings::SystemProperties &data)
1488{
1489 AutoCaller autoCaller(this);
1490 if (FAILED(autoCaller.hrc())) return autoCaller.hrc();
1491
1492 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1493
1494 data = *m;
1495
1496 return S_OK;
1497}
1498
1499/**
1500 * Returns a medium format object corresponding to the given format
1501 * identifier or null if no such format.
1502 *
1503 * @param aFormat Format identifier.
1504 *
1505 * @return ComObjPtr<MediumFormat>
1506 */
1507ComObjPtr<MediumFormat> SystemProperties::i_mediumFormat(const Utf8Str &aFormat)
1508{
1509 ComObjPtr<MediumFormat> format;
1510
1511 AutoCaller autoCaller(this);
1512 AssertComRCReturn (autoCaller.hrc(), format);
1513
1514 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1515
1516 for (MediumFormatList::const_iterator it = m_llMediumFormats.begin();
1517 it != m_llMediumFormats.end();
1518 ++ it)
1519 {
1520 /* MediumFormat is all const, no need to lock */
1521
1522 if ((*it)->i_getId().compare(aFormat, Utf8Str::CaseInsensitive) == 0)
1523 {
1524 format = *it;
1525 break;
1526 }
1527 }
1528
1529 return format;
1530}
1531
1532/**
1533 * Returns a medium format object corresponding to the given file extension or
1534 * null if no such format.
1535 *
1536 * @param aExt File extension.
1537 *
1538 * @return ComObjPtr<MediumFormat>
1539 */
1540ComObjPtr<MediumFormat> SystemProperties::i_mediumFormatFromExtension(const Utf8Str &aExt)
1541{
1542 ComObjPtr<MediumFormat> format;
1543
1544 AutoCaller autoCaller(this);
1545 AssertComRCReturn (autoCaller.hrc(), format);
1546
1547 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1548
1549 bool fFound = false;
1550 for (MediumFormatList::const_iterator it = m_llMediumFormats.begin();
1551 it != m_llMediumFormats.end() && !fFound;
1552 ++it)
1553 {
1554 /* MediumFormat is all const, no need to lock */
1555 MediumFormat::StrArray aFileList = (*it)->i_getFileExtensions();
1556 for (MediumFormat::StrArray::const_iterator it1 = aFileList.begin();
1557 it1 != aFileList.end();
1558 ++it1)
1559 {
1560 if ((*it1).compare(aExt, Utf8Str::CaseInsensitive) == 0)
1561 {
1562 format = *it;
1563 fFound = true;
1564 break;
1565 }
1566 }
1567 }
1568
1569 return format;
1570}
1571
1572
1573/**
1574 * VD plugin load
1575 */
1576int SystemProperties::i_loadVDPlugin(const char *pszPluginLibrary)
1577{
1578 int vrc = VDPluginLoadFromFilename(pszPluginLibrary);
1579 LogFlowFunc(("pszPluginLibrary='%s' -> %Rrc\n", pszPluginLibrary, vrc));
1580 return vrc;
1581}
1582
1583/**
1584 * VD plugin unload
1585 */
1586int SystemProperties::i_unloadVDPlugin(const char *pszPluginLibrary)
1587{
1588 int vrc = VDPluginUnloadFromFilename(pszPluginLibrary);
1589 LogFlowFunc(("pszPluginLibrary='%s' -> %Rrc\n", pszPluginLibrary, vrc));
1590 return vrc;
1591}
1592
1593/**
1594 * Internally usable version of getDefaultAdditionsISO.
1595 */
1596HRESULT SystemProperties::i_getDefaultAdditionsISO(com::Utf8Str &aDefaultAdditionsISO)
1597{
1598 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1599 if (m->strDefaultAdditionsISO.isNotEmpty())
1600 aDefaultAdditionsISO = m->strDefaultAdditionsISO;
1601 else
1602 {
1603 /* no guest additions, check if it showed up in the mean time */
1604 alock.release();
1605 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
1606 if (m->strDefaultAdditionsISO.isEmpty())
1607 {
1608 ErrorInfoKeeper eik;
1609 (void)i_setDefaultAdditionsISO("");
1610 }
1611 aDefaultAdditionsISO = m->strDefaultAdditionsISO;
1612 }
1613 return S_OK;
1614}
1615
1616// private methods
1617/////////////////////////////////////////////////////////////////////////////
1618
1619/**
1620 * Returns the user's home directory. Wrapper around RTPathUserHome().
1621 * @param strPath
1622 * @return
1623 */
1624HRESULT SystemProperties::i_getUserHomeDirectory(Utf8Str &strPath)
1625{
1626 char szHome[RTPATH_MAX];
1627 int vrc = RTPathUserHome(szHome, sizeof(szHome));
1628 if (RT_FAILURE(vrc))
1629 return setErrorBoth(E_FAIL, vrc,
1630 tr("Cannot determine user home directory (%Rrc)"),
1631 vrc);
1632 strPath = szHome;
1633 return S_OK;
1634}
1635
1636/**
1637 * Internal implementation to set the default machine folder. Gets called
1638 * from the public attribute setter as well as loadSettings(). With 4.0,
1639 * the "default default" machine folder has changed, and we now require
1640 * a full path always.
1641 * @param strPath
1642 * @return
1643 */
1644HRESULT SystemProperties::i_setDefaultMachineFolder(const Utf8Str &strPath)
1645{
1646 Utf8Str path(strPath); // make modifiable
1647 if ( path.isEmpty() // used by API calls to reset the default
1648 || path == "Machines" // this value (exactly like this, without path) is stored
1649 // in VirtualBox.xml if user upgrades from before 4.0 and
1650 // has not changed the default machine folder
1651 )
1652 {
1653 // new default with VirtualBox 4.0: "$HOME/VirtualBox VMs"
1654 HRESULT hrc = i_getUserHomeDirectory(path);
1655 if (FAILED(hrc)) return hrc;
1656 path += RTPATH_SLASH_STR "VirtualBox VMs";
1657 }
1658
1659 if (!RTPathStartsWithRoot(path.c_str()))
1660 return setError(E_INVALIDARG,
1661 tr("Given default machine folder '%s' is not fully qualified"),
1662 path.c_str());
1663
1664 m->strDefaultMachineFolder = path;
1665
1666 return S_OK;
1667}
1668
1669HRESULT SystemProperties::i_setLoggingLevel(const com::Utf8Str &aLoggingLevel)
1670{
1671 static const char s_szDefaultLevel[] = VBOXSVC_LOG_DEFAULT;
1672 const char *pszUseLoggingLevel = aLoggingLevel.isEmpty() || aLoggingLevel.equalsIgnoreCase(s_szDefaultLevel)
1673 ? s_szDefaultLevel : aLoggingLevel.c_str();
1674 HRESULT hrc = S_OK;
1675 PRTLOGGER const pRelLog = RTLogRelGetDefaultInstance();
1676 if (pRelLog)
1677 {
1678 int vrc = RTLogGroupSettings(pRelLog, pszUseLoggingLevel);
1679 if (RT_FAILURE(vrc))
1680 {
1681 LogRel(("Failed to set release logging level to '%s': %Rrc\n", pszUseLoggingLevel, vrc));
1682 hrc = setErrorVrc(vrc, tr("RTLogGroupSettings failed: %Rrc (input: %s)"), vrc, pszUseLoggingLevel);
1683
1684 // If attempted logging level not the default one then use the default one.
1685 if (pszUseLoggingLevel != s_szDefaultLevel)
1686 {
1687 pszUseLoggingLevel = s_szDefaultLevel;
1688 vrc = RTLogGroupSettings(pRelLog, s_szDefaultLevel);
1689 if (RT_FAILURE(vrc))
1690 LogRel(("Failed to set default release logging level: %Rrc\n", vrc));
1691 }
1692 }
1693 }
1694
1695 // Set to passed value or if default used/attempted (even if error condition) use empty string.
1696 if (pszUseLoggingLevel == s_szDefaultLevel)
1697 m->strLoggingLevel.setNull();
1698 else
1699 m->strLoggingLevel = aLoggingLevel;
1700
1701 return hrc;
1702}
1703
1704HRESULT SystemProperties::i_setDefaultHardDiskFormat(const com::Utf8Str &aFormat)
1705{
1706 if (!aFormat.isEmpty())
1707 m->strDefaultHardDiskFormat = aFormat;
1708 else
1709 m->strDefaultHardDiskFormat = "VDI";
1710
1711 return S_OK;
1712}
1713
1714HRESULT SystemProperties::i_setVRDEAuthLibrary(const com::Utf8Str &aPath)
1715{
1716 if (!aPath.isEmpty())
1717 m->strVRDEAuthLibrary = aPath;
1718 else
1719 m->strVRDEAuthLibrary = "VBoxAuth";
1720
1721 return S_OK;
1722}
1723
1724HRESULT SystemProperties::i_setWebServiceAuthLibrary(const com::Utf8Str &aPath)
1725{
1726 if (!aPath.isEmpty())
1727 m->strWebServiceAuthLibrary = aPath;
1728 else
1729 m->strWebServiceAuthLibrary = "VBoxAuth";
1730
1731 return S_OK;
1732}
1733
1734HRESULT SystemProperties::i_setDefaultVRDEExtPack(const com::Utf8Str &aExtPack)
1735{
1736 m->strDefaultVRDEExtPack = aExtPack;
1737
1738 return S_OK;
1739}
1740
1741HRESULT SystemProperties::i_setDefaultCryptoExtPack(const com::Utf8Str &aExtPack)
1742{
1743 m->strDefaultCryptoExtPack = aExtPack;
1744
1745 return S_OK;
1746}
1747
1748HRESULT SystemProperties::i_setAutostartDatabasePath(const com::Utf8Str &aPath)
1749{
1750 HRESULT hrc = S_OK;
1751 AutostartDb *autostartDb = this->mParent->i_getAutostartDb();
1752
1753 if (!aPath.isEmpty())
1754 {
1755 /* Update path in the autostart database. */
1756 int vrc = autostartDb->setAutostartDbPath(aPath.c_str());
1757 if (RT_SUCCESS(vrc))
1758 m->strAutostartDatabasePath = aPath;
1759 else
1760 hrc = setErrorBoth(E_FAIL, vrc, tr("Cannot set the autostart database path (%Rrc)"), vrc);
1761 }
1762 else
1763 {
1764 int vrc = autostartDb->setAutostartDbPath(NULL);
1765 if (RT_SUCCESS(vrc) || vrc == VERR_NOT_SUPPORTED)
1766 m->strAutostartDatabasePath = "";
1767 else
1768 hrc = setErrorBoth(E_FAIL, vrc, tr("Deleting the autostart database path failed (%Rrc)"), vrc);
1769 }
1770
1771 return hrc;
1772}
1773
1774HRESULT SystemProperties::i_setDefaultAdditionsISO(const com::Utf8Str &aPath)
1775{
1776 com::Utf8Str path(aPath);
1777 if (path.isEmpty())
1778 {
1779 char strTemp[RTPATH_MAX];
1780 int vrc = RTPathAppPrivateNoArch(strTemp, sizeof(strTemp));
1781 AssertRC(vrc);
1782 Utf8Str strSrc1 = Utf8Str(strTemp).append("/VBoxGuestAdditions.iso");
1783
1784 vrc = RTPathExecDir(strTemp, sizeof(strTemp));
1785 AssertRC(vrc);
1786 Utf8Str strSrc2 = Utf8Str(strTemp).append("/additions/VBoxGuestAdditions.iso");
1787
1788 vrc = RTPathUserHome(strTemp, sizeof(strTemp));
1789 AssertRC(vrc);
1790 Utf8Str strSrc3 = Utf8StrFmt("%s/VBoxGuestAdditions_%s.iso", strTemp, VirtualBox::i_getVersionNormalized().c_str());
1791
1792 /* Check the standard image locations */
1793 if (RTFileExists(strSrc1.c_str()))
1794 path = strSrc1;
1795 else if (RTFileExists(strSrc2.c_str()))
1796 path = strSrc2;
1797 else if (RTFileExists(strSrc3.c_str()))
1798 path = strSrc3;
1799 else
1800 return setError(E_FAIL,
1801 tr("Cannot determine default Guest Additions ISO location. Most likely they are not available"));
1802 }
1803
1804 if (!RTPathStartsWithRoot(path.c_str()))
1805 return setError(E_INVALIDARG,
1806 tr("Given default machine Guest Additions ISO file '%s' is not fully qualified"),
1807 path.c_str());
1808
1809 if (!RTFileExists(path.c_str()))
1810 return setError(E_INVALIDARG,
1811 tr("Given default machine Guest Additions ISO file '%s' does not exist"),
1812 path.c_str());
1813
1814 m->strDefaultAdditionsISO = path;
1815
1816 return S_OK;
1817}
1818
1819HRESULT SystemProperties::i_setDefaultFrontend(const com::Utf8Str &aDefaultFrontend)
1820{
1821 m->strDefaultFrontend = aDefaultFrontend;
1822
1823 return S_OK;
1824}
1825
1826HRESULT SystemProperties::getLanguageId(com::Utf8Str &aLanguageId)
1827{
1828#ifdef VBOX_WITH_MAIN_NLS
1829 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1830 aLanguageId = m->strLanguageId;
1831 alock.release();
1832
1833 HRESULT hrc = S_OK;
1834 if (aLanguageId.isEmpty())
1835 {
1836 char szLocale[256];
1837 memset(szLocale, 0, sizeof(szLocale));
1838 int vrc = RTLocaleQueryNormalizedBaseLocaleName(szLocale, sizeof(szLocale));
1839 if (RT_SUCCESS(vrc))
1840 aLanguageId = szLocale;
1841 else
1842 hrc = Global::vboxStatusCodeToCOM(vrc);
1843 }
1844 return hrc;
1845#else
1846 aLanguageId = "C";
1847 return S_OK;
1848#endif
1849}
1850
1851HRESULT SystemProperties::setLanguageId(const com::Utf8Str &aLanguageId)
1852{
1853#ifdef VBOX_WITH_MAIN_NLS
1854 VirtualBoxTranslator *pTranslator = VirtualBoxTranslator::instance();
1855 if (!pTranslator)
1856 return E_FAIL;
1857
1858 HRESULT hrc = S_OK;
1859 int vrc = pTranslator->i_loadLanguage(aLanguageId.c_str());
1860 if (RT_SUCCESS(vrc))
1861 {
1862 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1863 m->strLanguageId = aLanguageId;
1864 alock.release();
1865
1866 // VirtualBox::i_saveSettings() needs vbox write lock
1867 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
1868 hrc = mParent->i_saveSettings();
1869 }
1870 else
1871 hrc = Global::vboxStatusCodeToCOM(vrc);
1872
1873 pTranslator->release();
1874
1875 if (SUCCEEDED(hrc))
1876 mParent->i_onLanguageChanged(aLanguageId);
1877
1878 return hrc;
1879#else
1880 NOREF(aLanguageId);
1881 return E_NOTIMPL;
1882#endif
1883}
Note: See TracBrowser for help on using the repository browser.

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