VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/VRDEServerImpl.cpp@ 98103

Last change on this file since 98103 was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.8 KB
RevLine 
[54971]1/* $Id: VRDEServerImpl.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
[33593]2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[33593]8 *
[96407]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
[33593]26 */
27
[76592]28#define LOG_GROUP LOG_GROUP_MAIN_VRDESERVER
[33593]29#include "VRDEServerImpl.h"
30#include "MachineImpl.h"
31#include "VirtualBoxImpl.h"
[34244]32#ifdef VBOX_WITH_EXTPACK
33# include "ExtPackManagerImpl.h"
34#endif
[33593]35
36#include <iprt/cpp/utils.h>
37#include <iprt/ctype.h>
38#include <iprt/ldr.h>
[35105]39#include <iprt/path.h>
[33593]40
41#include <VBox/err.h>
[35105]42#include <VBox/sup.h>
[46820]43#include <VBox/com/array.h>
[33593]44
45#include <VBox/RemoteDesktop/VRDE.h>
46
47#include "AutoStateDep.h"
48#include "AutoCaller.h"
[34244]49#include "Global.h"
[76592]50#include "LoggingNew.h"
[33593]51
52// defines
53/////////////////////////////////////////////////////////////////////////////
54#define VRDP_DEFAULT_PORT_STR "3389"
55
56// constructor / destructor
57/////////////////////////////////////////////////////////////////////////////
58
59VRDEServer::VRDEServer()
60 : mParent(NULL)
61{
62}
63
64VRDEServer::~VRDEServer()
65{
66}
67
68HRESULT VRDEServer::FinalConstruct()
69{
[35638]70 return BaseFinalConstruct();
[33593]71}
72
73void VRDEServer::FinalRelease()
74{
75 uninit();
[35638]76 BaseFinalRelease();
[33593]77}
78
79// public initializer/uninitializer for internal purposes only
80/////////////////////////////////////////////////////////////////////////////
81
82/**
83 * Initializes the VRDP server object.
84 *
85 * @param aParent Handle of the parent object.
86 */
[44407]87HRESULT VRDEServer::init(Machine *aParent)
[33593]88{
89 LogFlowThisFunc(("aParent=%p\n", aParent));
90
91 ComAssertRet(aParent, E_INVALIDARG);
92
93 /* Enclose the state transition NotReady->InInit->Ready */
94 AutoInitSpan autoInitSpan(this);
95 AssertReturn(autoInitSpan.isOk(), E_FAIL);
96
97 unconst(mParent) = aParent;
98 /* mPeer is left null */
99
100 mData.allocate();
101
[62982]102 mData->fEnabled = false;
103
[33593]104 /* Confirm a successful initialization */
105 autoInitSpan.setSucceeded();
106
107 return S_OK;
108}
109
110/**
111 * Initializes the object given another object
112 * (a kind of copy constructor). This object shares data with
113 * the object passed as an argument.
114 *
115 * @note This object must be destroyed before the original object
116 * it shares data with is destroyed.
117 *
118 * @note Locks @a aThat object for reading.
119 */
[44407]120HRESULT VRDEServer::init(Machine *aParent, VRDEServer *aThat)
[33593]121{
122 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
123
124 ComAssertRet(aParent && aThat, E_INVALIDARG);
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 unconst(mPeer) = aThat;
132
[44407]133 AutoCaller thatCaller(aThat);
[33593]134 AssertComRCReturnRC(thatCaller.rc());
135
136 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[44407]137 mData.share(aThat->mData);
[33593]138
139 /* Confirm a successful initialization */
140 autoInitSpan.setSucceeded();
141
142 return S_OK;
143}
144
145/**
146 * Initializes the guest object given another guest object
147 * (a kind of copy constructor). This object makes a private copy of data
148 * of the original object passed as an argument.
149 *
150 * @note Locks @a aThat object for reading.
151 */
[44407]152HRESULT VRDEServer::initCopy(Machine *aParent, VRDEServer *aThat)
[33593]153{
154 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
155
156 ComAssertRet(aParent && aThat, E_INVALIDARG);
157
158 /* Enclose the state transition NotReady->InInit->Ready */
159 AutoInitSpan autoInitSpan(this);
160 AssertReturn(autoInitSpan.isOk(), E_FAIL);
161
162 unconst(mParent) = aParent;
163 /* mPeer is left null */
164
[44407]165 AutoCaller thatCaller(aThat);
[33593]166 AssertComRCReturnRC(thatCaller.rc());
167
168 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[44407]169 mData.attachCopy(aThat->mData);
[33593]170
171 /* Confirm a successful initialization */
172 autoInitSpan.setSucceeded();
173
174 return S_OK;
175}
176
177/**
178 * Uninitializes the instance and sets the ready flag to FALSE.
179 * Called either from FinalRelease() or by the parent when it gets destroyed.
180 */
181void VRDEServer::uninit()
182{
183 LogFlowThisFunc(("\n"));
184
185 /* Enclose the state transition Ready->InUninit->NotReady */
186 AutoUninitSpan autoUninitSpan(this);
187 if (autoUninitSpan.uninitDone())
188 return;
189
190 mData.free();
191
192 unconst(mPeer) = NULL;
193 unconst(mParent) = NULL;
194}
195
196/**
197 * Loads settings from the given machine node.
198 * May be called once right after this object creation.
199 *
[65063]200 * @param data Configuration settings.
[33593]201 *
202 * @note Locks this object for writing.
203 */
[49644]204HRESULT VRDEServer::i_loadSettings(const settings::VRDESettings &data)
[33593]205{
206 using namespace settings;
207
208 AutoCaller autoCaller(this);
209 AssertComRCReturnRC(autoCaller.rc());
210
211 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[61009]212 mData.assignCopy(&data);
[33593]213
214 return S_OK;
215}
216
217/**
218 * Saves settings to the given machine node.
219 *
[65063]220 * @param data Configuration settings.
[33593]221 *
222 * @note Locks this object for reading.
223 */
[49644]224HRESULT VRDEServer::i_saveSettings(settings::VRDESettings &data)
[33593]225{
226 AutoCaller autoCaller(this);
227 AssertComRCReturnRC(autoCaller.rc());
228
229 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[61009]230 data = *mData.data();
[33593]231
232 return S_OK;
233}
234
235// IVRDEServer properties
236/////////////////////////////////////////////////////////////////////////////
237
[49644]238HRESULT VRDEServer::getEnabled(BOOL *aEnabled)
[33593]239{
[49644]240 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[33593]241
[61009]242 *aEnabled = mData->fEnabled;
[33593]243
244 return S_OK;
245}
246
[49644]247HRESULT VRDEServer::setEnabled(BOOL aEnabled)
[33593]248{
249 /* the machine can also be in saved state for this property to change */
[54843]250 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
[33593]251 if (FAILED(adep.rc())) return adep.rc();
252
253 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
254
[46585]255 HRESULT rc = S_OK;
256
[61009]257 if (mData->fEnabled != RT_BOOL(aEnabled))
[33593]258 {
259 mData.backup();
[61009]260 mData->fEnabled = RT_BOOL(aEnabled);
[33593]261
262 /* leave the lock before informing callbacks */
263 alock.release();
264
265 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
[51498]266 mParent->i_setModified(Machine::IsModified_VRDEServer);
[33593]267 mlock.release();
268
[51498]269 /* Avoid deadlock when i_onVRDEServerChange eventually calls SetExtraData. */
[33593]270 adep.release();
271
[51498]272 rc = mParent->i_onVRDEServerChange(/* aRestart */ TRUE);
[61611]273 if (FAILED(rc))
274 {
275 /* Failed to enable/disable the server. Revert the internal state. */
[61624]276 adep.add();
277 if (SUCCEEDED(adep.rc()))
[61611]278 {
279 alock.acquire();
280 mData->fEnabled = !RT_BOOL(aEnabled);
281 alock.release();
[61624]282 mlock.acquire();
[61611]283 mParent->i_setModified(Machine::IsModified_VRDEServer);
284 }
285 }
[33593]286 }
287
[46585]288 return rc;
[33593]289}
290
[49644]291static int i_portParseNumber(uint16_t *pu16Port, const char *pszStart, const char *pszEnd)
[33593]292{
293 /* Gets a string of digits, converts to 16 bit port number.
294 * Note: pszStart <= pszEnd is expected, the string contains
295 * only digits and pszEnd points to the char after last
296 * digit.
297 */
[85255]298 size_t cch = (size_t)(pszEnd - pszStart);
[33593]299 if (cch > 0 && cch <= 5) /* Port is up to 5 decimal digits. */
300 {
301 unsigned uPort = 0;
302 while (pszStart != pszEnd)
303 {
[85255]304 uPort = uPort * 10 + (unsigned)(*pszStart - '0');
[33593]305 pszStart++;
306 }
307
308 if (uPort != 0 && uPort < 0x10000)
309 {
310 if (pu16Port)
311 *pu16Port = (uint16_t)uPort;
312 return VINF_SUCCESS;
313 }
314 }
315
316 return VERR_INVALID_PARAMETER;
317}
318
[67793]319static int i_vrdpServerVerifyPortsString(const com::Utf8Str &aPortRange)
[33593]320{
[67793]321 const char *pszPortRange = aPortRange.c_str();
[33593]322
323 if (!pszPortRange || *pszPortRange == 0) /* Reject empty string. */
324 return VERR_INVALID_PARAMETER;
325
326 /* The string should be like "1000-1010,1020,2000-2003" */
327 while (*pszPortRange)
328 {
329 const char *pszStart = pszPortRange;
330 const char *pszDash = NULL;
331 const char *pszEnd = pszStart;
332
333 while (*pszEnd && *pszEnd != ',')
334 {
335 if (*pszEnd == '-')
336 {
337 if (pszDash != NULL)
338 return VERR_INVALID_PARAMETER; /* More than one '-'. */
339
340 pszDash = pszEnd;
341 }
342 else if (!RT_C_IS_DIGIT(*pszEnd))
343 return VERR_INVALID_PARAMETER;
344
345 pszEnd++;
346 }
347
348 /* Update the next range pointer. */
349 pszPortRange = pszEnd;
350 if (*pszPortRange == ',')
351 {
352 pszPortRange++;
353 }
354
355 /* A probably valid range. Verify and parse it. */
356 int rc;
357 if (pszDash)
358 {
[49644]359 rc = i_portParseNumber(NULL, pszStart, pszDash);
[33593]360 if (RT_SUCCESS(rc))
[49644]361 rc = i_portParseNumber(NULL, pszDash + 1, pszEnd);
[33593]362 }
363 else
[49644]364 rc = i_portParseNumber(NULL, pszStart, pszEnd);
[33593]365
366 if (RT_FAILURE(rc))
367 return rc;
368 }
369
370 return VINF_SUCCESS;
371}
372
[49644]373HRESULT VRDEServer::setVRDEProperty(const com::Utf8Str &aKey, const com::Utf8Str &aValue)
[33593]374{
375 LogFlowThisFunc(("\n"));
376
[44407]377 /* the machine can also be in saved state for this property to change */
[54843]378 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
[33593]379 if (FAILED(adep.rc())) return adep.rc();
380
381 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
382
383 /* Special processing for some "standard" properties. */
[53344]384 if (aKey == "TCP/Ports")
[33593]385 {
[53344]386 /* Verify the string. "0" means the default port. */
387 Utf8Str strPorts = aValue == "0"?
388 VRDP_DEFAULT_PORT_STR:
389 aValue;
390 int vrc = i_vrdpServerVerifyPortsString(strPorts);
[33593]391 if (RT_FAILURE(vrc))
392 return E_INVALIDARG;
393
[61009]394 if (strPorts != mData->mapProperties["TCP/Ports"])
[33593]395 {
396 /* Port value is not verified here because it is up to VRDP transport to
397 * use it. Specifying a wrong port number will cause a running server to
398 * stop. There is no fool proof here.
399 */
400 mData.backup();
[61009]401 mData->mapProperties["TCP/Ports"] = strPorts;
[33593]402
403 /* leave the lock before informing callbacks */
404 alock.release();
405
406 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
[51498]407 mParent->i_setModified(Machine::IsModified_VRDEServer);
[33593]408 mlock.release();
409
[51498]410 /* Avoid deadlock when i_onVRDEServerChange eventually calls SetExtraData. */
[33593]411 adep.release();
412
[51498]413 mParent->i_onVRDEServerChange(/* aRestart */ TRUE);
[33593]414 }
415 }
416 else
417 {
418 /* Generic properties processing.
419 * Look up the old value first; if nothing's changed then do nothing.
420 */
421 Utf8Str strOldValue;
422
[61009]423 settings::StringsMap::const_iterator it = mData->mapProperties.find(aKey);
424 if (it != mData->mapProperties.end())
[33593]425 strOldValue = it->second;
426
[49644]427 if (strOldValue != aValue)
[33593]428 {
[49644]429 if (aValue.isEmpty())
[61009]430 mData->mapProperties.erase(aKey);
[33593]431 else
[61009]432 mData->mapProperties[aKey] = aValue;
[33593]433
434 /* leave the lock before informing callbacks */
435 alock.release();
436
437 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
[51498]438 mParent->i_setModified(Machine::IsModified_VRDEServer);
[33593]439 mlock.release();
440
[51498]441 /* Avoid deadlock when i_onVRDEServerChange eventually calls SetExtraData. */
[33593]442 adep.release();
443
[51498]444 mParent->i_onVRDEServerChange(/* aRestart */ TRUE);
[33593]445 }
446 }
447
448 return S_OK;
449}
450
[49644]451HRESULT VRDEServer::getVRDEProperty(const com::Utf8Str &aKey, com::Utf8Str &aValue)
[33593]452{
453 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[61009]454 settings::StringsMap::const_iterator it = mData->mapProperties.find(aKey);
455 if (it != mData->mapProperties.end())
[49644]456 aValue = it->second; // source is a Utf8Str
457 else if (aKey == "TCP/Ports")
458 aValue = VRDP_DEFAULT_PORT_STR;
[33593]459
460 return S_OK;
461}
462
[91514]463/*
464 * Work around clang being unhappy about PFNVRDESUPPORTEDPROPERTIES
465 * ("exception specifications are not allowed beyond a single level of
466 * indirection"). The original comment for 13.0 check said: "assuming
467 * this issue will be fixed eventually". Well, 13.0 is now out, and
468 * it was not.
469 */
470#define CLANG_EXCEPTION_SPEC_HACK (RT_CLANG_PREREQ(11, 0) /* && !RT_CLANG_PREREQ(13, 0) */)
471
472#if CLANG_EXCEPTION_SPEC_HACK
[85276]473static int loadVRDELibrary(const char *pszLibraryName, RTLDRMOD *phmod, void *ppfn)
474#else
[35105]475static int loadVRDELibrary(const char *pszLibraryName, RTLDRMOD *phmod, PFNVRDESUPPORTEDPROPERTIES *ppfn)
[85276]476#endif
[35105]477{
478 int rc = VINF_SUCCESS;
[33593]479
[35105]480 RTLDRMOD hmod = NIL_RTLDRMOD;
481
[35188]482 RTERRINFOSTATIC ErrInfo;
483 RTErrInfoInitStatic(&ErrInfo);
[35105]484 if (RTPathHavePath(pszLibraryName))
[35188]485 rc = SUPR3HardenedLdrLoadPlugIn(pszLibraryName, &hmod, &ErrInfo.Core);
[35105]486 else
[35191]487 rc = SUPR3HardenedLdrLoadAppPriv(pszLibraryName, &hmod, RTLDRLOAD_FLAGS_LOCAL, &ErrInfo.Core);
[35105]488 if (RT_SUCCESS(rc))
489 {
490 rc = RTLdrGetSymbol(hmod, "VRDESupportedProperties", (void **)ppfn);
491
492 if (RT_FAILURE(rc) && rc != VERR_SYMBOL_NOT_FOUND)
493 LogRel(("VRDE: Error resolving symbol '%s', rc %Rrc.\n", "VRDESupportedProperties", rc));
494 }
495 else
496 {
[35188]497 if (RTErrInfoIsSet(&ErrInfo.Core))
498 LogRel(("VRDE: Error loading the library '%s': %s (%Rrc)\n", pszLibraryName, ErrInfo.Core.pszMsg, rc));
[35105]499 else
500 LogRel(("VRDE: Error loading the library '%s' rc = %Rrc.\n", pszLibraryName, rc));
501
502 hmod = NIL_RTLDRMOD;
503 }
504
505 if (RT_SUCCESS(rc))
506 {
507 *phmod = hmod;
508 }
509 else
510 {
511 if (hmod != NIL_RTLDRMOD)
512 {
513 RTLdrClose(hmod);
514 hmod = NIL_RTLDRMOD;
515 }
516 }
517
518 return rc;
519}
520
[49644]521HRESULT VRDEServer::getVRDEProperties(std::vector<com::Utf8Str> &aProperties)
[35105]522{
523 size_t cProperties = 0;
[49644]524 aProperties.resize(0);
[35105]525 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[61009]526 if (!mData->fEnabled)
[35105]527 {
528 return S_OK;
529 }
530 alock.release();
531
532 /*
533 * Check that a VRDE extension pack name is set and resolve it into a
534 * library path.
535 */
536 Bstr bstrExtPack;
537 HRESULT hrc = COMGETTER(VRDEExtPack)(bstrExtPack.asOutParam());
538 Log(("VRDEPROP: get extpack hrc 0x%08X, isEmpty %d\n", hrc, bstrExtPack.isEmpty()));
539 if (FAILED(hrc))
540 return hrc;
541 if (bstrExtPack.isEmpty())
542 return E_FAIL;
543
544 Utf8Str strExtPack(bstrExtPack);
545 Utf8Str strVrdeLibrary;
546 int vrc = VINF_SUCCESS;
547 if (strExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
548 strVrdeLibrary = "VBoxVRDP";
549 else
550 {
551#ifdef VBOX_WITH_EXTPACK
[51498]552 VirtualBox *pVirtualBox = mParent->i_getVirtualBox();
[50355]553 ExtPackManager *pExtPackMgr = pVirtualBox->i_getExtPackManager();
[50914]554 vrc = pExtPackMgr->i_getVrdeLibraryPathForExtPack(&strExtPack, &strVrdeLibrary);
[35105]555#else
556 vrc = VERR_FILE_NOT_FOUND;
557#endif
558 }
559 Log(("VRDEPROP: library get rc %Rrc\n", vrc));
560
561 if (RT_SUCCESS(vrc))
562 {
563 /*
564 * Load the VRDE library and start the server, if it is enabled.
565 */
566 PFNVRDESUPPORTEDPROPERTIES pfn = NULL;
567 RTLDRMOD hmod = NIL_RTLDRMOD;
[91514]568#if CLANG_EXCEPTION_SPEC_HACK
[85276]569 vrc = loadVRDELibrary(strVrdeLibrary.c_str(), &hmod, (void **)&pfn);
570#else
[35105]571 vrc = loadVRDELibrary(strVrdeLibrary.c_str(), &hmod, &pfn);
[85276]572#endif
[35105]573 Log(("VRDEPROP: load library [%s] rc %Rrc\n", strVrdeLibrary.c_str(), vrc));
574 if (RT_SUCCESS(vrc))
575 {
576 const char * const *papszNames = pfn();
577
578 if (papszNames)
579 {
580 size_t i;
581 for (i = 0; papszNames[i] != NULL; ++i)
582 {
583 cProperties++;
584 }
585 }
586 Log(("VRDEPROP: %d properties\n", cProperties));
587
588 if (cProperties > 0)
589 {
[49644]590 aProperties.resize(cProperties);
[58043]591 for (size_t i = 0; i < cProperties && papszNames[i] != NULL; ++i)
[35105]592 {
[49644]593 aProperties[i] = papszNames[i];
[35105]594 }
595 }
596
597 /* Do not forget to unload the library. */
598 RTLdrClose(hmod);
599 hmod = NIL_RTLDRMOD;
600 }
601 }
602
603 if (RT_FAILURE(vrc))
604 {
605 return E_FAIL;
606 }
607
608 return S_OK;
609}
610
[49644]611
612HRESULT VRDEServer::getAuthType(AuthType_T *aType)
[33593]613{
614 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
615
[61009]616 *aType = mData->authType;
[33593]617
618 return S_OK;
619}
620
[49644]621HRESULT VRDEServer::setAuthType(AuthType_T aType)
[33593]622{
[44407]623 /* the machine can also be in saved state for this property to change */
[54843]624 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
[33593]625 if (FAILED(adep.rc())) return adep.rc();
626
627 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
628
[61009]629 if (mData->authType != aType)
[33593]630 {
631 mData.backup();
[61009]632 mData->authType = aType;
[33593]633
634 /* leave the lock before informing callbacks */
635 alock.release();
636
637 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
[51498]638 mParent->i_setModified(Machine::IsModified_VRDEServer);
[33593]639 mlock.release();
640
[51498]641 mParent->i_onVRDEServerChange(/* aRestart */ TRUE);
[33593]642 }
643
644 return S_OK;
645}
646
[49644]647HRESULT VRDEServer::getAuthTimeout(ULONG *aTimeout)
[33593]648{
649 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
650
[61009]651 *aTimeout = mData->ulAuthTimeout;
[33593]652
653 return S_OK;
654}
655
[49644]656
657HRESULT VRDEServer::setAuthTimeout(ULONG aTimeout)
[33593]658{
[44407]659 /* the machine can also be in saved state for this property to change */
[54843]660 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
[33593]661 if (FAILED(adep.rc())) return adep.rc();
662
663 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
664
[61009]665 if (aTimeout != mData->ulAuthTimeout)
[33593]666 {
667 mData.backup();
[61009]668 mData->ulAuthTimeout = aTimeout;
[33593]669
670 /* leave the lock before informing callbacks */
671 alock.release();
672
673 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
[51498]674 mParent->i_setModified(Machine::IsModified_VRDEServer);
[33593]675 mlock.release();
676
677 /* sunlover 20060131: This setter does not require the notification
678 * really */
679#if 0
680 mParent->onVRDEServerChange();
681#endif
682 }
683
684 return S_OK;
685}
686
[49644]687HRESULT VRDEServer::getAuthLibrary(com::Utf8Str &aLibrary)
[34574]688{
689 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[61009]690 aLibrary = mData->strAuthLibrary;
[34574]691 alock.release();
692
[49644]693 if (aLibrary.isEmpty())
[34574]694 {
695 /* Get the global setting. */
696 ComPtr<ISystemProperties> systemProperties;
[51498]697 HRESULT hrc = mParent->i_getVirtualBox()->COMGETTER(SystemProperties)(systemProperties.asOutParam());
[34574]698 if (SUCCEEDED(hrc))
[49644]699 {
[49662]700 Bstr strlib;
[49644]701 hrc = systemProperties->COMGETTER(VRDEAuthLibrary)(strlib.asOutParam());
[49662]702 if (SUCCEEDED(hrc))
703 aLibrary = Utf8Str(strlib).c_str();
[49644]704 }
[34574]705
706 if (FAILED(hrc))
[91503]707 return setError(hrc, tr("failed to query the library setting\n"));
[34574]708 }
709
710 return S_OK;
711}
712
[49644]713
714HRESULT VRDEServer::setAuthLibrary(const com::Utf8Str &aLibrary)
[34574]715{
[44407]716 /* the machine can also be in saved state for this property to change */
[54843]717 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
[34574]718 if (FAILED(adep.rc())) return adep.rc();
719
720 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
721
[61009]722 if (mData->strAuthLibrary != aLibrary)
[34574]723 {
724 mData.backup();
[61009]725 mData->strAuthLibrary = aLibrary;
[34574]726
727 /* leave the lock before informing callbacks */
728 alock.release();
729
730 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
[51498]731 mParent->i_setModified(Machine::IsModified_VRDEServer);
[34574]732 mlock.release();
733
[51498]734 mParent->i_onVRDEServerChange(/* aRestart */ TRUE);
[34574]735 }
736
737 return S_OK;
738}
739
[49644]740
741HRESULT VRDEServer::getAllowMultiConnection(BOOL *aAllowMultiConnection)
[33593]742{
743 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
744
[61009]745 *aAllowMultiConnection = mData->fAllowMultiConnection;
[33593]746
747 return S_OK;
748}
749
[49644]750
751HRESULT VRDEServer::setAllowMultiConnection(BOOL aAllowMultiConnection)
[33593]752{
[44407]753 /* the machine can also be in saved state for this property to change */
[54843]754 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
[33593]755 if (FAILED(adep.rc())) return adep.rc();
756
757 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
758
[61009]759 if (mData->fAllowMultiConnection != RT_BOOL(aAllowMultiConnection))
[33593]760 {
761 mData.backup();
[61009]762 mData->fAllowMultiConnection = RT_BOOL(aAllowMultiConnection);
[33593]763
764 /* leave the lock before informing callbacks */
765 alock.release();
766
767 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
[51498]768 mParent->i_setModified(Machine::IsModified_VRDEServer);
[33593]769 mlock.release();
770
[63563]771 mParent->i_onVRDEServerChange(/* aRestart */ TRUE); /// @todo does it need a restart?
[33593]772 }
773
774 return S_OK;
775}
776
[49644]777HRESULT VRDEServer::getReuseSingleConnection(BOOL *aReuseSingleConnection)
[33593]778{
779 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
780
[61009]781 *aReuseSingleConnection = mData->fReuseSingleConnection;
[33593]782
783 return S_OK;
784}
785
[49644]786
787HRESULT VRDEServer::setReuseSingleConnection(BOOL aReuseSingleConnection)
[33593]788{
[54843]789 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
[33593]790 if (FAILED(adep.rc())) return adep.rc();
791
792 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
793
[61009]794 if (mData->fReuseSingleConnection != RT_BOOL(aReuseSingleConnection))
[33593]795 {
796 mData.backup();
[61009]797 mData->fReuseSingleConnection = RT_BOOL(aReuseSingleConnection);
[33593]798
799 /* leave the lock before informing callbacks */
800 alock.release();
801
802 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
[51498]803 mParent->i_setModified(Machine::IsModified_VRDEServer);
[33593]804 mlock.release();
805
[63563]806 mParent->i_onVRDEServerChange(/* aRestart */ TRUE); /// @todo needs a restart?
[33593]807 }
808
809 return S_OK;
810}
811
[49644]812HRESULT VRDEServer::getVRDEExtPack(com::Utf8Str &aExtPack)
[33593]813{
[49644]814 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[61009]815 Utf8Str strExtPack = mData->strVrdeExtPack;
[49644]816 alock.release();
817 HRESULT hrc = S_OK;
[33593]818
[49644]819 if (strExtPack.isNotEmpty())
[33593]820 {
[49644]821 if (strExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
822 hrc = S_OK;
823 else
[34244]824 {
825#ifdef VBOX_WITH_EXTPACK
[51498]826 ExtPackManager *pExtPackMgr = mParent->i_getVirtualBox()->i_getExtPackManager();
[50914]827 hrc = pExtPackMgr->i_checkVrdeExtPack(&strExtPack);
[34244]828#else
[49644]829 hrc = setError(E_FAIL, tr("Extension pack '%s' does not exist"), strExtPack.c_str());
[34244]830#endif
831 }
[49644]832 if (SUCCEEDED(hrc))
833 aExtPack = strExtPack;
[33593]834 }
[49644]835 else
836 {
837 /* Get the global setting. */
838 ComPtr<ISystemProperties> systemProperties;
[51498]839 hrc = mParent->i_getVirtualBox()->COMGETTER(SystemProperties)(systemProperties.asOutParam());
[49644]840 if (SUCCEEDED(hrc))
[49662]841 {
[77436]842 Bstr bstr;
843 hrc = systemProperties->COMGETTER(DefaultVRDEExtPack)(bstr.asOutParam());
[49662]844 if (SUCCEEDED(hrc))
[77436]845 aExtPack = bstr;
[49662]846 }
[49644]847 }
[34244]848 return hrc;
[33593]849}
850
[49644]851// public methods only for internal purposes
852/////////////////////////////////////////////////////////////////////////////
853HRESULT VRDEServer::setVRDEExtPack(const com::Utf8Str &aExtPack)
[33593]854{
[49644]855 HRESULT hrc = S_OK;
856 /* the machine can also be in saved state for this property to change */
[54843]857 AutoMutableOrSavedOrRunningStateDependency adep(mParent);
[49644]858 hrc = adep.rc();
[34244]859 if (SUCCEEDED(hrc))
[33593]860 {
[49644]861 /*
862 * If not empty, check the specific extension pack.
863 */
864 if (!aExtPack.isEmpty())
[34244]865 {
[49644]866 if (aExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
867 hrc = S_OK;
868 else
[34244]869 {
870#ifdef VBOX_WITH_EXTPACK
[51498]871 ExtPackManager *pExtPackMgr = mParent->i_getVirtualBox()->i_getExtPackManager();
[50914]872 hrc = pExtPackMgr->i_checkVrdeExtPack(&aExtPack);
[34244]873#else
[49644]874 hrc = setError(E_FAIL, tr("Extension pack '%s' does not exist"), aExtPack.c_str());
[34244]875#endif
876 }
[49644]877 }
878 if (SUCCEEDED(hrc))
879 {
880 /*
881 * Update the setting if there is an actual change, post an
882 * change event to trigger a VRDE server restart.
883 */
884 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[61009]885 if (aExtPack != mData->strVrdeExtPack)
[49644]886 {
887 mData.backup();
[61009]888 mData->strVrdeExtPack = aExtPack;
[33593]889
[49644]890 /* leave the lock before informing callbacks */
891 alock.release();
[33593]892
[49644]893 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
[51498]894 mParent->i_setModified(Machine::IsModified_VRDEServer);
[49644]895 mlock.release();
[33593]896
[51498]897 mParent->i_onVRDEServerChange(/* aRestart */ TRUE);
[34244]898 }
899 }
[33593]900 }
901
[34244]902 return hrc;
[33593]903}
904
905// public methods only for internal purposes
906/////////////////////////////////////////////////////////////////////////////
907
908/**
909 * @note Locks this object for writing.
910 */
[49644]911void VRDEServer::i_rollback()
[33593]912{
913 /* sanity */
914 AutoCaller autoCaller(this);
915 AssertComRCReturnVoid(autoCaller.rc());
916
917 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
918
919 mData.rollback();
920}
921
922/**
923 * @note Locks this object for writing, together with the peer object (also
924 * for writing) if there is one.
925 */
[49644]926void VRDEServer::i_commit()
[33593]927{
928 /* sanity */
929 AutoCaller autoCaller(this);
[44407]930 AssertComRCReturnVoid(autoCaller.rc());
[33593]931
932 /* sanity too */
[44407]933 AutoCaller peerCaller(mPeer);
934 AssertComRCReturnVoid(peerCaller.rc());
[33593]935
936 /* lock both for writing since we modify both (mPeer is "master" so locked
937 * first) */
938 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
939
940 if (mData.isBackedUp())
941 {
942 mData.commit();
943 if (mPeer)
944 {
945 /* attach new data to the peer and reshare it */
[44407]946 mPeer->mData.attach(mData);
[33593]947 }
948 }
949}
950
951/**
952 * @note Locks this object for writing, together with the peer object
953 * represented by @a aThat (locked for reading).
954 */
[49644]955void VRDEServer::i_copyFrom(VRDEServer *aThat)
[33593]956{
[44407]957 AssertReturnVoid(aThat != NULL);
[33593]958
959 /* sanity */
960 AutoCaller autoCaller(this);
[44407]961 AssertComRCReturnVoid(autoCaller.rc());
[33593]962
963 /* sanity too */
[44407]964 AutoCaller thatCaller(aThat);
965 AssertComRCReturnVoid(thatCaller.rc());
[33593]966
967 /* peer is not modified, lock it for reading (aThat is "master" so locked
968 * first) */
969 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
970 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
971
972 /* this will back up current data */
[44407]973 mData.assignCopy(aThat->mData);
[33593]974}
975/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use