VirtualBox

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

Last change on this file since 49644 was 49644, checked in by vboxsync, 11 years ago

stage 1/8 of 6813 changes

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