VirtualBox

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

Last change on this file since 105659 was 105455, checked in by vboxsync, 4 months ago

Main: Special API tweak for ARM host disabling x86-on-arm by default (set global VBoxInternal2/EnableX86OnArm extradata to 1 to enable).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 56.9 KB
Line 
1/* $Id: SystemPropertiesImpl.cpp 105455 2024-07-23 19:02:30Z 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
1066#ifdef VBOX_WITH_VIRT_ARMV8
1067 Bstr bstrEnableX86OnArm;
1068 HRESULT hrc =mParent->GetExtraData(Bstr("VBoxInternal2/EnableX86OnArm").raw(), bstrEnableX86OnArm.asOutParam());
1069 if (FAILED(hrc) || !bstrEnableX86OnArm.equals("1"))
1070 {
1071 Assert(aSupportedPlatformArchitectures[0] == PlatformArchitecture_x86);
1072 if (aSupportedPlatformArchitectures[0] == PlatformArchitecture_x86)
1073 aSupportedPlatformArchitectures.erase(aSupportedPlatformArchitectures.begin());
1074 }
1075#endif
1076 return S_OK;
1077}
1078
1079HRESULT SystemProperties::getSupportedClipboardModes(std::vector<ClipboardMode_T> &aSupportedClipboardModes)
1080{
1081 static const ClipboardMode_T s_aClipboardModes[] =
1082 {
1083 ClipboardMode_Disabled,
1084 ClipboardMode_HostToGuest,
1085 ClipboardMode_GuestToHost,
1086 ClipboardMode_Bidirectional,
1087 };
1088 MY_VECTOR_ASSIGN_ARRAY(aSupportedClipboardModes, s_aClipboardModes);
1089 return S_OK;
1090}
1091
1092HRESULT SystemProperties::getSupportedDnDModes(std::vector<DnDMode_T> &aSupportedDnDModes)
1093{
1094 static const DnDMode_T s_aDnDModes[] =
1095 {
1096 DnDMode_Disabled,
1097 DnDMode_HostToGuest,
1098 DnDMode_GuestToHost,
1099 DnDMode_Bidirectional,
1100 };
1101 MY_VECTOR_ASSIGN_ARRAY(aSupportedDnDModes, s_aDnDModes);
1102 return S_OK;
1103}
1104
1105HRESULT SystemProperties::getSupportedPointingHIDTypes(std::vector<PointingHIDType_T> &aSupportedPointingHIDTypes)
1106{
1107 static const PointingHIDType_T s_aPointingHIDTypes[] =
1108 {
1109 PointingHIDType_PS2Mouse,
1110#ifdef DEBUG
1111 PointingHIDType_USBMouse,
1112#endif
1113 PointingHIDType_USBTablet,
1114#ifdef DEBUG
1115 PointingHIDType_ComboMouse,
1116#endif
1117 PointingHIDType_USBMultiTouch,
1118 PointingHIDType_USBMultiTouchScreenPlusPad,
1119 };
1120 MY_VECTOR_ASSIGN_ARRAY(aSupportedPointingHIDTypes, s_aPointingHIDTypes);
1121 return S_OK;
1122}
1123
1124HRESULT SystemProperties::getSupportedKeyboardHIDTypes(std::vector<KeyboardHIDType_T> &aSupportedKeyboardHIDTypes)
1125{
1126 static const KeyboardHIDType_T s_aKeyboardHIDTypes[] =
1127 {
1128 KeyboardHIDType_PS2Keyboard,
1129 KeyboardHIDType_USBKeyboard,
1130#ifdef DEBUG
1131 KeyboardHIDType_ComboKeyboard,
1132#endif
1133 };
1134 MY_VECTOR_ASSIGN_ARRAY(aSupportedKeyboardHIDTypes, s_aKeyboardHIDTypes);
1135 return S_OK;
1136}
1137
1138HRESULT SystemProperties::getSupportedVFSTypes(std::vector<VFSType_T> &aSupportedVFSTypes)
1139{
1140 static const VFSType_T s_aVFSTypes[] =
1141 {
1142 VFSType_File,
1143 VFSType_Cloud,
1144 VFSType_S3,
1145#ifdef DEBUG
1146 VFSType_WebDav,
1147#endif
1148 };
1149 MY_VECTOR_ASSIGN_ARRAY(aSupportedVFSTypes, s_aVFSTypes);
1150 return S_OK;
1151}
1152
1153HRESULT SystemProperties::getSupportedImportOptions(std::vector<ImportOptions_T> &aSupportedImportOptions)
1154{
1155 static const ImportOptions_T s_aImportOptions[] =
1156 {
1157 ImportOptions_KeepAllMACs,
1158 ImportOptions_KeepNATMACs,
1159 ImportOptions_ImportToVDI,
1160 };
1161 MY_VECTOR_ASSIGN_ARRAY(aSupportedImportOptions, s_aImportOptions);
1162 return S_OK;
1163}
1164
1165HRESULT SystemProperties::getSupportedExportOptions(std::vector<ExportOptions_T> &aSupportedExportOptions)
1166{
1167 static const ExportOptions_T s_aExportOptions[] =
1168 {
1169 ExportOptions_CreateManifest,
1170 ExportOptions_ExportDVDImages,
1171 ExportOptions_StripAllMACs,
1172 ExportOptions_StripAllNonNATMACs,
1173 };
1174 MY_VECTOR_ASSIGN_ARRAY(aSupportedExportOptions, s_aExportOptions);
1175 return S_OK;
1176}
1177
1178HRESULT SystemProperties::getSupportedRecordingFeatures(std::vector<RecordingFeature_T> &aSupportedRecordingFeatures)
1179{
1180#ifdef VBOX_WITH_RECORDING
1181 static const RecordingFeature_T s_aRecordingFeatures[] =
1182 {
1183# ifdef VBOX_WITH_AUDIO_RECORDING
1184 RecordingFeature_Audio,
1185# endif
1186 RecordingFeature_Video,
1187 };
1188 MY_VECTOR_ASSIGN_ARRAY(aSupportedRecordingFeatures, s_aRecordingFeatures);
1189#else /* !VBOX_WITH_RECORDING */
1190 aSupportedRecordingFeatures.clear();
1191#endif /* VBOX_WITH_RECORDING */
1192 return S_OK;
1193}
1194
1195HRESULT SystemProperties::getSupportedRecordingAudioCodecs(std::vector<RecordingAudioCodec_T> &aSupportedRecordingAudioCodecs)
1196{
1197 static const RecordingAudioCodec_T s_aRecordingAudioCodecs[] =
1198 {
1199 RecordingAudioCodec_None,
1200#ifdef DEBUG
1201 RecordingAudioCodec_WavPCM,
1202#endif
1203#ifdef VBOX_WITH_LIBVORBIS
1204 RecordingAudioCodec_OggVorbis,
1205#endif
1206 };
1207 MY_VECTOR_ASSIGN_ARRAY(aSupportedRecordingAudioCodecs, s_aRecordingAudioCodecs);
1208 return S_OK;
1209}
1210
1211HRESULT SystemProperties::getSupportedRecordingVideoCodecs(std::vector<RecordingVideoCodec_T> &aSupportedRecordingVideoCodecs)
1212{
1213 static const RecordingVideoCodec_T s_aRecordingVideoCodecs[] =
1214 {
1215 RecordingVideoCodec_None,
1216#ifdef VBOX_WITH_LIBVPX
1217 RecordingVideoCodec_VP8,
1218#endif
1219#ifdef DEBUG
1220 RecordingVideoCodec_VP9,
1221 RecordingVideoCodec_AV1,
1222#endif
1223 };
1224 MY_VECTOR_ASSIGN_ARRAY(aSupportedRecordingVideoCodecs, s_aRecordingVideoCodecs);
1225 return S_OK;
1226}
1227
1228HRESULT SystemProperties::getSupportedRecordingVSModes(std::vector<RecordingVideoScalingMode_T> &aSupportedRecordingVideoScalingModes)
1229{
1230 static const RecordingVideoScalingMode_T s_aRecordingVideoScalingModes[] =
1231 {
1232 RecordingVideoScalingMode_None,
1233#ifdef DEBUG
1234 RecordingVideoScalingMode_NearestNeighbor,
1235 RecordingVideoScalingMode_Bilinear,
1236 RecordingVideoScalingMode_Bicubic,
1237#endif
1238 };
1239 MY_VECTOR_ASSIGN_ARRAY(aSupportedRecordingVideoScalingModes, s_aRecordingVideoScalingModes);
1240 return S_OK;
1241}
1242
1243HRESULT SystemProperties::getSupportedRecordingARCModes(std::vector<RecordingRateControlMode_T> &aSupportedRecordingAudioRateControlModes)
1244{
1245 static const RecordingRateControlMode_T s_aRecordingAudioRateControlModes[] =
1246 {
1247#ifdef DEBUG
1248 RecordingRateControlMode_ABR,
1249 RecordingRateControlMode_CBR,
1250#endif
1251 RecordingRateControlMode_VBR
1252 };
1253 MY_VECTOR_ASSIGN_ARRAY(aSupportedRecordingAudioRateControlModes, s_aRecordingAudioRateControlModes);
1254 return S_OK;
1255}
1256
1257HRESULT SystemProperties::getSupportedRecordingVRCModes(std::vector<RecordingRateControlMode_T> &aSupportedRecordingVideoRateControlModes)
1258{
1259 static const RecordingRateControlMode_T s_aRecordingVideoRateControlModes[] =
1260 {
1261#ifdef DEBUG
1262 RecordingRateControlMode_ABR,
1263 RecordingRateControlMode_CBR,
1264#endif
1265 RecordingRateControlMode_VBR
1266 };
1267 MY_VECTOR_ASSIGN_ARRAY(aSupportedRecordingVideoRateControlModes, s_aRecordingVideoRateControlModes);
1268 return S_OK;
1269}
1270
1271HRESULT SystemProperties::getSupportedCloneOptions(std::vector<CloneOptions_T> &aSupportedCloneOptions)
1272{
1273 static const CloneOptions_T s_aCloneOptions[] =
1274 {
1275 CloneOptions_Link,
1276 CloneOptions_KeepAllMACs,
1277 CloneOptions_KeepNATMACs,
1278 CloneOptions_KeepDiskNames,
1279 CloneOptions_KeepHwUUIDs,
1280 };
1281 MY_VECTOR_ASSIGN_ARRAY(aSupportedCloneOptions, s_aCloneOptions);
1282 return S_OK;
1283}
1284
1285HRESULT SystemProperties::getSupportedAutostopTypes(std::vector<AutostopType_T> &aSupportedAutostopTypes)
1286{
1287 static const AutostopType_T s_aAutostopTypes[] =
1288 {
1289 AutostopType_Disabled,
1290 AutostopType_SaveState,
1291 AutostopType_PowerOff,
1292 AutostopType_AcpiShutdown,
1293 };
1294 MY_VECTOR_ASSIGN_ARRAY(aSupportedAutostopTypes, s_aAutostopTypes);
1295 return S_OK;
1296}
1297
1298HRESULT SystemProperties::getSupportedVMProcPriorities(std::vector<VMProcPriority_T> &aSupportedVMProcPriorities)
1299{
1300 static const VMProcPriority_T s_aVMProcPriorities[] =
1301 {
1302 VMProcPriority_Default,
1303 VMProcPriority_Flat,
1304 VMProcPriority_Low,
1305 VMProcPriority_Normal,
1306 VMProcPriority_High,
1307 };
1308 MY_VECTOR_ASSIGN_ARRAY(aSupportedVMProcPriorities, s_aVMProcPriorities);
1309 return S_OK;
1310}
1311
1312HRESULT SystemProperties::getSupportedNetworkAttachmentTypes(std::vector<NetworkAttachmentType_T> &aSupportedNetworkAttachmentTypes)
1313{
1314 static const NetworkAttachmentType_T s_aNetworkAttachmentTypes[] =
1315 {
1316 NetworkAttachmentType_NAT,
1317 NetworkAttachmentType_Bridged,
1318 NetworkAttachmentType_Internal,
1319 NetworkAttachmentType_HostOnly,
1320#ifdef VBOX_WITH_VMNET
1321 NetworkAttachmentType_HostOnlyNetwork,
1322#endif /* VBOX_WITH_VMNET */
1323 NetworkAttachmentType_Generic,
1324 NetworkAttachmentType_NATNetwork,
1325#ifdef VBOX_WITH_CLOUD_NET
1326 NetworkAttachmentType_Cloud,
1327#endif
1328 NetworkAttachmentType_Null,
1329 };
1330 MY_VECTOR_ASSIGN_ARRAY(aSupportedNetworkAttachmentTypes, s_aNetworkAttachmentTypes);
1331 return S_OK;
1332}
1333
1334HRESULT SystemProperties::getSupportedPortModes(std::vector<PortMode_T> &aSupportedPortModes)
1335{
1336 static const PortMode_T s_aPortModes[] =
1337 {
1338 PortMode_Disconnected,
1339 PortMode_HostPipe,
1340 PortMode_HostDevice,
1341 PortMode_RawFile,
1342 PortMode_TCP,
1343 };
1344 MY_VECTOR_ASSIGN_ARRAY(aSupportedPortModes, s_aPortModes);
1345 return S_OK;
1346}
1347
1348HRESULT SystemProperties::getSupportedAudioDriverTypes(std::vector<AudioDriverType_T> &aSupportedAudioDriverTypes)
1349{
1350 static const AudioDriverType_T s_aAudioDriverTypes[] =
1351 {
1352 AudioDriverType_Default,
1353#ifdef RT_OS_WINDOWS
1354# if 0 /* deprecated for many years now */
1355 AudioDriverType_WinMM,
1356# endif
1357 AudioDriverType_WAS,
1358 AudioDriverType_DirectSound,
1359#endif
1360#ifdef RT_OS_DARWIN
1361 AudioDriverType_CoreAudio,
1362#endif
1363#ifdef RT_OS_OS2
1364 AudioDriverType_MMPM,
1365#endif
1366#ifdef RT_OS_SOLARIS
1367# if 0 /* deprecated for many years now */
1368 AudioDriverType_SolAudio,
1369# endif
1370#endif
1371#ifdef VBOX_WITH_AUDIO_ALSA
1372 AudioDriverType_ALSA,
1373#endif
1374#ifdef VBOX_WITH_AUDIO_OSS
1375 AudioDriverType_OSS,
1376#endif
1377#ifdef VBOX_WITH_AUDIO_PULSE
1378 AudioDriverType_Pulse,
1379#endif
1380 AudioDriverType_Null,
1381 };
1382 MY_VECTOR_ASSIGN_ARRAY(aSupportedAudioDriverTypes, s_aAudioDriverTypes);
1383 return S_OK;
1384}
1385
1386HRESULT SystemProperties::getExecutionEnginesForVmCpuArchitecture(CPUArchitecture_T aCpuArchitecture,
1387 std::vector<VMExecutionEngine_T> &aExecutionEngines)
1388{
1389 switch (aCpuArchitecture)
1390 {
1391 case CPUArchitecture_x86:
1392 case CPUArchitecture_AMD64:
1393 {
1394 static const VMExecutionEngine_T s_aExecEngines[] =
1395 {
1396 VMExecutionEngine_Default,
1397#ifdef RT_ARCH_AMD64
1398# ifndef VBOX_WITH_DRIVERLESS_FORCED
1399 VMExecutionEngine_HwVirt,
1400# endif
1401# ifdef VBOX_WITH_NATIVE_NEM
1402 VMExecutionEngine_NativeApi,
1403# endif
1404#endif
1405 VMExecutionEngine_Interpreter,
1406#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
1407 VMExecutionEngine_Recompiler,
1408#endif
1409 };
1410 MY_VECTOR_ASSIGN_ARRAY(aExecutionEngines, s_aExecEngines);
1411 break;
1412 }
1413
1414 case CPUArchitecture_ARMv8_32:
1415 aExecutionEngines.clear(); /* Currently not supported at all. */
1416 break;
1417
1418 case CPUArchitecture_ARMv8_64:
1419 {
1420#ifdef VBOX_WITH_VIRT_ARMV8
1421 static const VMExecutionEngine_T s_aExecEngines[] =
1422 {
1423 VMExecutionEngine_Default,
1424# ifdef VBOX_WITH_NATIVE_NEM
1425 VMExecutionEngine_NativeApi,
1426# endif
1427 };
1428 MY_VECTOR_ASSIGN_ARRAY(aExecutionEngines, s_aExecEngines);
1429#else
1430 aExecutionEngines.clear();
1431#endif
1432 break;
1433 }
1434
1435 default:
1436 AssertFailedStmt(aExecutionEngines.clear());
1437 break;
1438 }
1439
1440 return S_OK;
1441}
1442
1443
1444// public methods only for internal purposes
1445/////////////////////////////////////////////////////////////////////////////
1446
1447HRESULT SystemProperties::i_loadSettings(const settings::SystemProperties &data)
1448{
1449 AutoCaller autoCaller(this);
1450 if (FAILED(autoCaller.hrc())) return autoCaller.hrc();
1451
1452 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1453
1454 i_setLoggingLevel(data.strLoggingLevel); /* ignore errors here! */
1455
1456 HRESULT hrc = i_setDefaultMachineFolder(data.strDefaultMachineFolder);
1457 if (FAILED(hrc)) return hrc;
1458
1459 hrc = i_setDefaultHardDiskFormat(data.strDefaultHardDiskFormat);
1460 if (FAILED(hrc)) return hrc;
1461
1462 hrc = i_setVRDEAuthLibrary(data.strVRDEAuthLibrary);
1463 if (FAILED(hrc)) return hrc;
1464
1465 hrc = i_setWebServiceAuthLibrary(data.strWebServiceAuthLibrary);
1466 if (FAILED(hrc)) return hrc;
1467
1468 hrc = i_setDefaultVRDEExtPack(data.strDefaultVRDEExtPack);
1469 if (FAILED(hrc)) return hrc;
1470
1471 hrc = i_setDefaultCryptoExtPack(data.strDefaultCryptoExtPack);
1472 if (FAILED(hrc)) return hrc;
1473
1474 m->uLogHistoryCount = data.uLogHistoryCount;
1475 m->uProxyMode = data.uProxyMode;
1476 m->strProxyUrl = data.strProxyUrl;
1477
1478 m->strLanguageId = data.strLanguageId;
1479
1480 hrc = i_setAutostartDatabasePath(data.strAutostartDatabasePath);
1481 if (FAILED(hrc)) return hrc;
1482
1483 {
1484 /* must ignore errors signalled here, because the guest additions
1485 * file may not exist, and in this case keep the empty string */
1486 ErrorInfoKeeper eik;
1487 (void)i_setDefaultAdditionsISO(data.strDefaultAdditionsISO);
1488 }
1489
1490 hrc = i_setDefaultFrontend(data.strDefaultFrontend);
1491 if (FAILED(hrc)) return hrc;
1492
1493 return S_OK;
1494}
1495
1496HRESULT SystemProperties::i_saveSettings(settings::SystemProperties &data)
1497{
1498 AutoCaller autoCaller(this);
1499 if (FAILED(autoCaller.hrc())) return autoCaller.hrc();
1500
1501 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1502
1503 data = *m;
1504
1505 return S_OK;
1506}
1507
1508/**
1509 * Returns a medium format object corresponding to the given format
1510 * identifier or null if no such format.
1511 *
1512 * @param aFormat Format identifier.
1513 *
1514 * @return ComObjPtr<MediumFormat>
1515 */
1516ComObjPtr<MediumFormat> SystemProperties::i_mediumFormat(const Utf8Str &aFormat)
1517{
1518 ComObjPtr<MediumFormat> format;
1519
1520 AutoCaller autoCaller(this);
1521 AssertComRCReturn (autoCaller.hrc(), format);
1522
1523 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1524
1525 for (MediumFormatList::const_iterator it = m_llMediumFormats.begin();
1526 it != m_llMediumFormats.end();
1527 ++ it)
1528 {
1529 /* MediumFormat is all const, no need to lock */
1530
1531 if ((*it)->i_getId().compare(aFormat, Utf8Str::CaseInsensitive) == 0)
1532 {
1533 format = *it;
1534 break;
1535 }
1536 }
1537
1538 return format;
1539}
1540
1541/**
1542 * Returns a medium format object corresponding to the given file extension or
1543 * null if no such format.
1544 *
1545 * @param aExt File extension.
1546 *
1547 * @return ComObjPtr<MediumFormat>
1548 */
1549ComObjPtr<MediumFormat> SystemProperties::i_mediumFormatFromExtension(const Utf8Str &aExt)
1550{
1551 ComObjPtr<MediumFormat> format;
1552
1553 AutoCaller autoCaller(this);
1554 AssertComRCReturn (autoCaller.hrc(), format);
1555
1556 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1557
1558 bool fFound = false;
1559 for (MediumFormatList::const_iterator it = m_llMediumFormats.begin();
1560 it != m_llMediumFormats.end() && !fFound;
1561 ++it)
1562 {
1563 /* MediumFormat is all const, no need to lock */
1564 MediumFormat::StrArray aFileList = (*it)->i_getFileExtensions();
1565 for (MediumFormat::StrArray::const_iterator it1 = aFileList.begin();
1566 it1 != aFileList.end();
1567 ++it1)
1568 {
1569 if ((*it1).compare(aExt, Utf8Str::CaseInsensitive) == 0)
1570 {
1571 format = *it;
1572 fFound = true;
1573 break;
1574 }
1575 }
1576 }
1577
1578 return format;
1579}
1580
1581
1582/**
1583 * VD plugin load
1584 */
1585int SystemProperties::i_loadVDPlugin(const char *pszPluginLibrary)
1586{
1587 int vrc = VDPluginLoadFromFilename(pszPluginLibrary);
1588 LogFlowFunc(("pszPluginLibrary='%s' -> %Rrc\n", pszPluginLibrary, vrc));
1589 return vrc;
1590}
1591
1592/**
1593 * VD plugin unload
1594 */
1595int SystemProperties::i_unloadVDPlugin(const char *pszPluginLibrary)
1596{
1597 int vrc = VDPluginUnloadFromFilename(pszPluginLibrary);
1598 LogFlowFunc(("pszPluginLibrary='%s' -> %Rrc\n", pszPluginLibrary, vrc));
1599 return vrc;
1600}
1601
1602/**
1603 * Internally usable version of getDefaultAdditionsISO.
1604 */
1605HRESULT SystemProperties::i_getDefaultAdditionsISO(com::Utf8Str &aDefaultAdditionsISO)
1606{
1607 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1608 if (m->strDefaultAdditionsISO.isNotEmpty())
1609 aDefaultAdditionsISO = m->strDefaultAdditionsISO;
1610 else
1611 {
1612 /* no guest additions, check if it showed up in the mean time */
1613 alock.release();
1614 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
1615 if (m->strDefaultAdditionsISO.isEmpty())
1616 {
1617 ErrorInfoKeeper eik;
1618 (void)i_setDefaultAdditionsISO("");
1619 }
1620 aDefaultAdditionsISO = m->strDefaultAdditionsISO;
1621 }
1622 return S_OK;
1623}
1624
1625// private methods
1626/////////////////////////////////////////////////////////////////////////////
1627
1628/**
1629 * Returns the user's home directory. Wrapper around RTPathUserHome().
1630 * @param strPath
1631 * @return
1632 */
1633HRESULT SystemProperties::i_getUserHomeDirectory(Utf8Str &strPath)
1634{
1635 char szHome[RTPATH_MAX];
1636 int vrc = RTPathUserHome(szHome, sizeof(szHome));
1637 if (RT_FAILURE(vrc))
1638 return setErrorBoth(E_FAIL, vrc,
1639 tr("Cannot determine user home directory (%Rrc)"),
1640 vrc);
1641 strPath = szHome;
1642 return S_OK;
1643}
1644
1645/**
1646 * Internal implementation to set the default machine folder. Gets called
1647 * from the public attribute setter as well as loadSettings(). With 4.0,
1648 * the "default default" machine folder has changed, and we now require
1649 * a full path always.
1650 * @param strPath
1651 * @return
1652 */
1653HRESULT SystemProperties::i_setDefaultMachineFolder(const Utf8Str &strPath)
1654{
1655 Utf8Str path(strPath); // make modifiable
1656 if ( path.isEmpty() // used by API calls to reset the default
1657 || path == "Machines" // this value (exactly like this, without path) is stored
1658 // in VirtualBox.xml if user upgrades from before 4.0 and
1659 // has not changed the default machine folder
1660 )
1661 {
1662 // new default with VirtualBox 4.0: "$HOME/VirtualBox VMs"
1663 HRESULT hrc = i_getUserHomeDirectory(path);
1664 if (FAILED(hrc)) return hrc;
1665 path += RTPATH_SLASH_STR "VirtualBox VMs";
1666 }
1667
1668 if (!RTPathStartsWithRoot(path.c_str()))
1669 return setError(E_INVALIDARG,
1670 tr("Given default machine folder '%s' is not fully qualified"),
1671 path.c_str());
1672
1673 m->strDefaultMachineFolder = path;
1674
1675 return S_OK;
1676}
1677
1678HRESULT SystemProperties::i_setLoggingLevel(const com::Utf8Str &aLoggingLevel)
1679{
1680 static const char s_szDefaultLevel[] = VBOXSVC_LOG_DEFAULT;
1681 const char *pszUseLoggingLevel = aLoggingLevel.isEmpty() || aLoggingLevel.equalsIgnoreCase(s_szDefaultLevel)
1682 ? s_szDefaultLevel : aLoggingLevel.c_str();
1683 HRESULT hrc = S_OK;
1684 PRTLOGGER const pRelLog = RTLogRelGetDefaultInstance();
1685 if (pRelLog)
1686 {
1687 int vrc = RTLogGroupSettings(pRelLog, pszUseLoggingLevel);
1688 if (RT_FAILURE(vrc))
1689 {
1690 LogRel(("Failed to set release logging level to '%s': %Rrc\n", pszUseLoggingLevel, vrc));
1691 hrc = setErrorVrc(vrc, tr("RTLogGroupSettings failed: %Rrc (input: %s)"), vrc, pszUseLoggingLevel);
1692
1693 // If attempted logging level not the default one then use the default one.
1694 if (pszUseLoggingLevel != s_szDefaultLevel)
1695 {
1696 pszUseLoggingLevel = s_szDefaultLevel;
1697 vrc = RTLogGroupSettings(pRelLog, s_szDefaultLevel);
1698 if (RT_FAILURE(vrc))
1699 LogRel(("Failed to set default release logging level: %Rrc\n", vrc));
1700 }
1701 }
1702 }
1703
1704 // Set to passed value or if default used/attempted (even if error condition) use empty string.
1705 if (pszUseLoggingLevel == s_szDefaultLevel)
1706 m->strLoggingLevel.setNull();
1707 else
1708 m->strLoggingLevel = aLoggingLevel;
1709
1710 return hrc;
1711}
1712
1713HRESULT SystemProperties::i_setDefaultHardDiskFormat(const com::Utf8Str &aFormat)
1714{
1715 if (!aFormat.isEmpty())
1716 m->strDefaultHardDiskFormat = aFormat;
1717 else
1718 m->strDefaultHardDiskFormat = "VDI";
1719
1720 return S_OK;
1721}
1722
1723HRESULT SystemProperties::i_setVRDEAuthLibrary(const com::Utf8Str &aPath)
1724{
1725 if (!aPath.isEmpty())
1726 m->strVRDEAuthLibrary = aPath;
1727 else
1728 m->strVRDEAuthLibrary = "VBoxAuth";
1729
1730 return S_OK;
1731}
1732
1733HRESULT SystemProperties::i_setWebServiceAuthLibrary(const com::Utf8Str &aPath)
1734{
1735 if (!aPath.isEmpty())
1736 m->strWebServiceAuthLibrary = aPath;
1737 else
1738 m->strWebServiceAuthLibrary = "VBoxAuth";
1739
1740 return S_OK;
1741}
1742
1743HRESULT SystemProperties::i_setDefaultVRDEExtPack(const com::Utf8Str &aExtPack)
1744{
1745 m->strDefaultVRDEExtPack = aExtPack;
1746
1747 return S_OK;
1748}
1749
1750HRESULT SystemProperties::i_setDefaultCryptoExtPack(const com::Utf8Str &aExtPack)
1751{
1752 m->strDefaultCryptoExtPack = aExtPack;
1753
1754 return S_OK;
1755}
1756
1757HRESULT SystemProperties::i_setAutostartDatabasePath(const com::Utf8Str &aPath)
1758{
1759 HRESULT hrc = S_OK;
1760 AutostartDb *autostartDb = this->mParent->i_getAutostartDb();
1761
1762 if (!aPath.isEmpty())
1763 {
1764 /* Update path in the autostart database. */
1765 int vrc = autostartDb->setAutostartDbPath(aPath.c_str());
1766 if (RT_SUCCESS(vrc))
1767 m->strAutostartDatabasePath = aPath;
1768 else
1769 hrc = setErrorBoth(E_FAIL, vrc, tr("Cannot set the autostart database path (%Rrc)"), vrc);
1770 }
1771 else
1772 {
1773 int vrc = autostartDb->setAutostartDbPath(NULL);
1774 if (RT_SUCCESS(vrc) || vrc == VERR_NOT_SUPPORTED)
1775 m->strAutostartDatabasePath = "";
1776 else
1777 hrc = setErrorBoth(E_FAIL, vrc, tr("Deleting the autostart database path failed (%Rrc)"), vrc);
1778 }
1779
1780 return hrc;
1781}
1782
1783HRESULT SystemProperties::i_setDefaultAdditionsISO(const com::Utf8Str &aPath)
1784{
1785 com::Utf8Str path(aPath);
1786 if (path.isEmpty())
1787 {
1788 char strTemp[RTPATH_MAX];
1789 int vrc = RTPathAppPrivateNoArch(strTemp, sizeof(strTemp));
1790 AssertRC(vrc);
1791 Utf8Str strSrc1 = Utf8Str(strTemp).append("/VBoxGuestAdditions.iso");
1792
1793 vrc = RTPathExecDir(strTemp, sizeof(strTemp));
1794 AssertRC(vrc);
1795 Utf8Str strSrc2 = Utf8Str(strTemp).append("/additions/VBoxGuestAdditions.iso");
1796
1797 vrc = RTPathUserHome(strTemp, sizeof(strTemp));
1798 AssertRC(vrc);
1799 Utf8Str strSrc3 = Utf8StrFmt("%s/VBoxGuestAdditions_%s.iso", strTemp, VirtualBox::i_getVersionNormalized().c_str());
1800
1801 /* Check the standard image locations */
1802 if (RTFileExists(strSrc1.c_str()))
1803 path = strSrc1;
1804 else if (RTFileExists(strSrc2.c_str()))
1805 path = strSrc2;
1806 else if (RTFileExists(strSrc3.c_str()))
1807 path = strSrc3;
1808 else
1809 return setError(E_FAIL,
1810 tr("Cannot determine default Guest Additions ISO location. Most likely they are not available"));
1811 }
1812
1813 if (!RTPathStartsWithRoot(path.c_str()))
1814 return setError(E_INVALIDARG,
1815 tr("Given default machine Guest Additions ISO file '%s' is not fully qualified"),
1816 path.c_str());
1817
1818 if (!RTFileExists(path.c_str()))
1819 return setError(E_INVALIDARG,
1820 tr("Given default machine Guest Additions ISO file '%s' does not exist"),
1821 path.c_str());
1822
1823 m->strDefaultAdditionsISO = path;
1824
1825 return S_OK;
1826}
1827
1828HRESULT SystemProperties::i_setDefaultFrontend(const com::Utf8Str &aDefaultFrontend)
1829{
1830 m->strDefaultFrontend = aDefaultFrontend;
1831
1832 return S_OK;
1833}
1834
1835HRESULT SystemProperties::getLanguageId(com::Utf8Str &aLanguageId)
1836{
1837#ifdef VBOX_WITH_MAIN_NLS
1838 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1839 aLanguageId = m->strLanguageId;
1840 alock.release();
1841
1842 HRESULT hrc = S_OK;
1843 if (aLanguageId.isEmpty())
1844 {
1845 char szLocale[256];
1846 memset(szLocale, 0, sizeof(szLocale));
1847 int vrc = RTLocaleQueryNormalizedBaseLocaleName(szLocale, sizeof(szLocale));
1848 if (RT_SUCCESS(vrc))
1849 aLanguageId = szLocale;
1850 else
1851 hrc = Global::vboxStatusCodeToCOM(vrc);
1852 }
1853 return hrc;
1854#else
1855 aLanguageId = "C";
1856 return S_OK;
1857#endif
1858}
1859
1860HRESULT SystemProperties::setLanguageId(const com::Utf8Str &aLanguageId)
1861{
1862#ifdef VBOX_WITH_MAIN_NLS
1863 VirtualBoxTranslator *pTranslator = VirtualBoxTranslator::instance();
1864 if (!pTranslator)
1865 return E_FAIL;
1866
1867 HRESULT hrc = S_OK;
1868 int vrc = pTranslator->i_loadLanguage(aLanguageId.c_str());
1869 if (RT_SUCCESS(vrc))
1870 {
1871 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1872 m->strLanguageId = aLanguageId;
1873 alock.release();
1874
1875 // VirtualBox::i_saveSettings() needs vbox write lock
1876 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
1877 hrc = mParent->i_saveSettings();
1878 }
1879 else
1880 hrc = Global::vboxStatusCodeToCOM(vrc);
1881
1882 pTranslator->release();
1883
1884 if (SUCCEEDED(hrc))
1885 mParent->i_onLanguageChanged(aLanguageId);
1886
1887 return hrc;
1888#else
1889 NOREF(aLanguageId);
1890 return E_NOTIMPL;
1891#endif
1892}
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