VirtualBox

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

Last change on this file was 108641, checked in by vboxsync, 3 weeks ago

Removed 2D video acceleration (aka VHWA / VBOX_WITH_VIDEOHWACCEL). bugref:10756

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

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