VirtualBox

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

Last change on this file since 105305 was 104753, checked in by vboxsync, 7 months ago

Main/SystemPropertiesImpl.cpp: Workaround for incorrect warning in g++ 13.2 when passing an array with a single entry to std::vector::assign. Corrected incorrect naming of static local variables. Introduced a MY_VECTOR_ASSIGN_ARRAY macro to reduce the typing involved in the std::vector::assign calls. [build fix]

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

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