VirtualBox

source: vbox/trunk/src/VBox/Main/VRDEServerImpl.cpp@ 33944

Last change on this file since 33944 was 33593, checked in by vboxsync, 14 years ago

Main: export VRDEServerImpl.cpp to OSE.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.2 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. 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
22#include <iprt/cpp/utils.h>
23#include <iprt/ctype.h>
24#include <iprt/ldr.h>
25
26#include <VBox/err.h>
27
28#include <VBox/RemoteDesktop/VRDE.h>
29
30#include "AutoStateDep.h"
31#include "AutoCaller.h"
32#include "Logging.h"
33
34// defines
35/////////////////////////////////////////////////////////////////////////////
36#define VRDP_DEFAULT_PORT_STR "3389"
37
38// constructor / destructor
39/////////////////////////////////////////////////////////////////////////////
40
41VRDEServer::VRDEServer()
42 : mParent(NULL)
43{
44}
45
46VRDEServer::~VRDEServer()
47{
48}
49
50HRESULT VRDEServer::FinalConstruct()
51{
52 return S_OK;
53}
54
55void VRDEServer::FinalRelease()
56{
57 uninit();
58}
59
60// public initializer/uninitializer for internal purposes only
61/////////////////////////////////////////////////////////////////////////////
62
63/**
64 * Initializes the VRDP server object.
65 *
66 * @param aParent Handle of the parent object.
67 */
68HRESULT VRDEServer::init (Machine *aParent)
69{
70 LogFlowThisFunc(("aParent=%p\n", aParent));
71
72 ComAssertRet(aParent, E_INVALIDARG);
73
74 /* Enclose the state transition NotReady->InInit->Ready */
75 AutoInitSpan autoInitSpan(this);
76 AssertReturn(autoInitSpan.isOk(), E_FAIL);
77
78 unconst(mParent) = aParent;
79 /* mPeer is left null */
80
81 mData.allocate();
82
83 mData->mAuthType = AuthType_Null;
84 mData->mAuthTimeout = 0;
85 mData->mEnabled = FALSE;
86 mData->mAllowMultiConnection = FALSE;
87 mData->mReuseSingleConnection = FALSE;
88 mData->mVideoChannel = FALSE;
89 mData->mVideoChannelQuality = 75;
90 mData->mVRDELibrary = (const char *)NULL;
91
92 /* Confirm a successful initialization */
93 autoInitSpan.setSucceeded();
94
95 return S_OK;
96}
97
98/**
99 * Initializes the object given another object
100 * (a kind of copy constructor). This object shares data with
101 * the object passed as an argument.
102 *
103 * @note This object must be destroyed before the original object
104 * it shares data with is destroyed.
105 *
106 * @note Locks @a aThat object for reading.
107 */
108HRESULT VRDEServer::init (Machine *aParent, VRDEServer *aThat)
109{
110 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
111
112 ComAssertRet(aParent && aThat, E_INVALIDARG);
113
114 /* Enclose the state transition NotReady->InInit->Ready */
115 AutoInitSpan autoInitSpan(this);
116 AssertReturn(autoInitSpan.isOk(), E_FAIL);
117
118 unconst(mParent) = aParent;
119 unconst(mPeer) = aThat;
120
121 AutoCaller thatCaller (aThat);
122 AssertComRCReturnRC(thatCaller.rc());
123
124 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
125 mData.share (aThat->mData);
126
127 /* Confirm a successful initialization */
128 autoInitSpan.setSucceeded();
129
130 return S_OK;
131}
132
133/**
134 * Initializes the guest object given another guest object
135 * (a kind of copy constructor). This object makes a private copy of data
136 * of the original object passed as an argument.
137 *
138 * @note Locks @a aThat object for reading.
139 */
140HRESULT VRDEServer::initCopy (Machine *aParent, VRDEServer *aThat)
141{
142 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
143
144 ComAssertRet(aParent && aThat, E_INVALIDARG);
145
146 /* Enclose the state transition NotReady->InInit->Ready */
147 AutoInitSpan autoInitSpan(this);
148 AssertReturn(autoInitSpan.isOk(), E_FAIL);
149
150 unconst(mParent) = aParent;
151 /* mPeer is left null */
152
153 AutoCaller thatCaller (aThat);
154 AssertComRCReturnRC(thatCaller.rc());
155
156 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
157 mData.attachCopy (aThat->mData);
158
159 /* Confirm a successful initialization */
160 autoInitSpan.setSucceeded();
161
162 return S_OK;
163}
164
165/**
166 * Uninitializes the instance and sets the ready flag to FALSE.
167 * Called either from FinalRelease() or by the parent when it gets destroyed.
168 */
169void VRDEServer::uninit()
170{
171 LogFlowThisFunc(("\n"));
172
173 /* Enclose the state transition Ready->InUninit->NotReady */
174 AutoUninitSpan autoUninitSpan(this);
175 if (autoUninitSpan.uninitDone())
176 return;
177
178 mData.free();
179
180 unconst(mPeer) = NULL;
181 unconst(mParent) = NULL;
182}
183
184/**
185 * Loads settings from the given machine node.
186 * May be called once right after this object creation.
187 *
188 * @param aMachineNode <Machine> node.
189 *
190 * @note Locks this object for writing.
191 */
192HRESULT VRDEServer::loadSettings(const settings::VRDESettings &data)
193{
194 using namespace settings;
195
196 AutoCaller autoCaller(this);
197 AssertComRCReturnRC(autoCaller.rc());
198
199 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
200
201 mData->mEnabled = data.fEnabled;
202 mData->mAuthType = data.authType;
203 mData->mAuthTimeout = data.ulAuthTimeout;
204 mData->mAllowMultiConnection = data.fAllowMultiConnection;
205 mData->mReuseSingleConnection = data.fReuseSingleConnection;
206 mData->mVideoChannel = data.fVideoChannel;
207 mData->mVideoChannelQuality = data.ulVideoChannelQuality;
208 mData->mVRDELibrary = data.strVRDELibrary;
209 mData->mProperties = data.mapProperties;
210
211 return S_OK;
212}
213
214/**
215 * Saves settings to the given machine node.
216 *
217 * @param aMachineNode <Machine> node.
218 *
219 * @note Locks this object for reading.
220 */
221HRESULT VRDEServer::saveSettings(settings::VRDESettings &data)
222{
223 AutoCaller autoCaller(this);
224 AssertComRCReturnRC(autoCaller.rc());
225
226 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
227
228 data.fEnabled = !!mData->mEnabled;
229 data.authType = mData->mAuthType;
230 data.ulAuthTimeout = mData->mAuthTimeout;
231 data.fAllowMultiConnection = !!mData->mAllowMultiConnection;
232 data.fReuseSingleConnection = !!mData->mReuseSingleConnection;
233 data.fVideoChannel = !!mData->mVideoChannel;
234 data.ulVideoChannelQuality = mData->mVideoChannelQuality;
235 data.strVRDELibrary = mData->mVRDELibrary;
236 data.mapProperties = mData->mProperties;
237
238 return S_OK;
239}
240
241// IVRDEServer properties
242/////////////////////////////////////////////////////////////////////////////
243
244STDMETHODIMP VRDEServer::COMGETTER(Enabled) (BOOL *aEnabled)
245{
246 CheckComArgOutPointerValid(aEnabled);
247
248 AutoCaller autoCaller(this);
249 if (FAILED(autoCaller.rc())) return autoCaller.rc();
250
251 *aEnabled = mData->mEnabled;
252
253 return S_OK;
254}
255
256STDMETHODIMP VRDEServer::COMSETTER(Enabled) (BOOL aEnabled)
257{
258 AutoCaller autoCaller(this);
259 if (FAILED(autoCaller.rc())) return autoCaller.rc();
260
261 /* the machine can also be in saved state for this property to change */
262 AutoMutableOrSavedStateDependency adep (mParent);
263 if (FAILED(adep.rc())) return adep.rc();
264
265 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
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 mParent->onVRDEServerChange(/* aRestart */ TRUE);
283 }
284
285 return S_OK;
286}
287
288static int 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 vrdpServerVerifyPortsString(Bstr ports)
317{
318 com::Utf8Str portRange = ports;
319
320 const char *pszPortRange = portRange.c_str();
321
322 if (!pszPortRange || *pszPortRange == 0) /* Reject empty string. */
323 return VERR_INVALID_PARAMETER;
324
325 /* The string should be like "1000-1010,1020,2000-2003" */
326 while (*pszPortRange)
327 {
328 const char *pszStart = pszPortRange;
329 const char *pszDash = NULL;
330 const char *pszEnd = pszStart;
331
332 while (*pszEnd && *pszEnd != ',')
333 {
334 if (*pszEnd == '-')
335 {
336 if (pszDash != NULL)
337 return VERR_INVALID_PARAMETER; /* More than one '-'. */
338
339 pszDash = pszEnd;
340 }
341 else if (!RT_C_IS_DIGIT(*pszEnd))
342 return VERR_INVALID_PARAMETER;
343
344 pszEnd++;
345 }
346
347 /* Update the next range pointer. */
348 pszPortRange = pszEnd;
349 if (*pszPortRange == ',')
350 {
351 pszPortRange++;
352 }
353
354 /* A probably valid range. Verify and parse it. */
355 int rc;
356 if (pszDash)
357 {
358 rc = portParseNumber(NULL, pszStart, pszDash);
359 if (RT_SUCCESS(rc))
360 rc = portParseNumber(NULL, pszDash + 1, pszEnd);
361 }
362 else
363 rc = portParseNumber(NULL, pszStart, pszEnd);
364
365 if (RT_FAILURE(rc))
366 return rc;
367 }
368
369 return VINF_SUCCESS;
370}
371
372STDMETHODIMP VRDEServer::SetVRDEProperty (IN_BSTR aKey, IN_BSTR aValue)
373{
374 LogFlowThisFunc(("\n"));
375
376 AutoCaller autoCaller(this);
377 if (FAILED(autoCaller.rc())) return autoCaller.rc();
378
379 /* The machine needs to be mutable. */
380 AutoMutableStateDependency adep(mParent);
381 if (FAILED(adep.rc())) return adep.rc();
382
383 Bstr key = aKey;
384
385 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
386
387 /* Special processing for some "standard" properties. */
388 if (key == Bstr("TCP/Ports"))
389 {
390 Bstr ports = aValue;
391
392 /* Verify the string. */
393 int vrc = vrdpServerVerifyPortsString(ports);
394 if (RT_FAILURE(vrc))
395 return E_INVALIDARG;
396
397 if (ports != mData->mProperties["TCP/Ports"])
398 {
399 /* Port value is not verified here because it is up to VRDP transport to
400 * use it. Specifying a wrong port number will cause a running server to
401 * stop. There is no fool proof here.
402 */
403 mData.backup();
404 if (ports == Bstr("0"))
405 mData->mProperties["TCP/Ports"] = VRDP_DEFAULT_PORT_STR;
406 else
407 mData->mProperties["TCP/Ports"] = ports;
408
409 /* leave the lock before informing callbacks */
410 alock.release();
411
412 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
413 mParent->setModified(Machine::IsModified_VRDEServer);
414 mlock.release();
415
416 /* Avoid deadlock when onVRDEServerChange eventually calls SetExtraData. */
417 adep.release();
418
419 mParent->onVRDEServerChange(/* aRestart */ TRUE);
420 }
421 }
422 else
423 {
424 /* Generic properties processing.
425 * Look up the old value first; if nothing's changed then do nothing.
426 */
427 Utf8Str strValue(aValue);
428 Utf8Str strKey(aKey);
429 Utf8Str strOldValue;
430
431 settings::StringsMap::const_iterator it = mData->mProperties.find(strKey);
432 if (it != mData->mProperties.end())
433 strOldValue = it->second;
434
435 if (strOldValue != strValue)
436 {
437 if (strValue.isEmpty())
438 mData->mProperties.erase(strKey);
439 else
440 mData->mProperties[strKey] = strValue;
441
442 /* leave the lock before informing callbacks */
443 alock.release();
444
445 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
446 mParent->setModified(Machine::IsModified_VRDEServer);
447 mlock.release();
448
449 /* Avoid deadlock when onVRDEServerChange eventually calls SetExtraData. */
450 adep.release();
451
452 mParent->onVRDEServerChange(/* aRestart */ TRUE);
453 }
454 }
455
456 return S_OK;
457}
458
459STDMETHODIMP VRDEServer::GetVRDEProperty (IN_BSTR aKey, BSTR *aValue)
460{
461 CheckComArgOutPointerValid(aValue);
462
463 AutoCaller autoCaller(this);
464 if (FAILED(autoCaller.rc())) return autoCaller.rc();
465
466 Bstr key = aKey;
467 Bstr value;
468
469 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
470
471 Utf8Str strKey(key);
472 settings::StringsMap::const_iterator it = mData->mProperties.find(strKey);
473 if (it != mData->mProperties.end())
474 {
475 value = it->second; // source is a Utf8Str
476 value.cloneTo(aValue);
477 }
478
479 return S_OK;
480}
481
482
483STDMETHODIMP VRDEServer::COMGETTER(AuthType) (AuthType_T *aType)
484{
485 CheckComArgOutPointerValid(aType);
486
487 AutoCaller autoCaller(this);
488 if (FAILED(autoCaller.rc())) return autoCaller.rc();
489
490 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
491
492 *aType = mData->mAuthType;
493
494 return S_OK;
495}
496
497STDMETHODIMP VRDEServer::COMSETTER(AuthType) (AuthType_T aType)
498{
499 AutoCaller autoCaller(this);
500 if (FAILED(autoCaller.rc())) return autoCaller.rc();
501
502 /* the machine needs to be mutable */
503 AutoMutableStateDependency adep(mParent);
504 if (FAILED(adep.rc())) return adep.rc();
505
506 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
507
508 if (mData->mAuthType != aType)
509 {
510 mData.backup();
511 mData->mAuthType = aType;
512
513 /* leave the lock before informing callbacks */
514 alock.release();
515
516 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
517 mParent->setModified(Machine::IsModified_VRDEServer);
518 mlock.release();
519
520 mParent->onVRDEServerChange(/* aRestart */ TRUE);
521 }
522
523 return S_OK;
524}
525
526STDMETHODIMP VRDEServer::COMGETTER(AuthTimeout) (ULONG *aTimeout)
527{
528 CheckComArgOutPointerValid(aTimeout);
529
530 AutoCaller autoCaller(this);
531 if (FAILED(autoCaller.rc())) return autoCaller.rc();
532
533 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
534
535 *aTimeout = mData->mAuthTimeout;
536
537 return S_OK;
538}
539
540STDMETHODIMP VRDEServer::COMSETTER(AuthTimeout) (ULONG aTimeout)
541{
542 AutoCaller autoCaller(this);
543 if (FAILED(autoCaller.rc())) return autoCaller.rc();
544
545 /* the machine needs to be mutable */
546 AutoMutableStateDependency adep(mParent);
547 if (FAILED(adep.rc())) return adep.rc();
548
549 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
550
551 if (aTimeout != mData->mAuthTimeout)
552 {
553 mData.backup();
554 mData->mAuthTimeout = aTimeout;
555
556 /* leave the lock before informing callbacks */
557 alock.release();
558
559 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
560 mParent->setModified(Machine::IsModified_VRDEServer);
561 mlock.release();
562
563 /* sunlover 20060131: This setter does not require the notification
564 * really */
565#if 0
566 mParent->onVRDEServerChange();
567#endif
568 }
569
570 return S_OK;
571}
572
573STDMETHODIMP VRDEServer::COMGETTER(AllowMultiConnection) (
574 BOOL *aAllowMultiConnection)
575{
576 CheckComArgOutPointerValid(aAllowMultiConnection);
577
578 AutoCaller autoCaller(this);
579 if (FAILED(autoCaller.rc())) return autoCaller.rc();
580
581 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
582
583 *aAllowMultiConnection = mData->mAllowMultiConnection;
584
585 return S_OK;
586}
587
588STDMETHODIMP VRDEServer::COMSETTER(AllowMultiConnection) (
589 BOOL aAllowMultiConnection)
590{
591 AutoCaller autoCaller(this);
592 if (FAILED(autoCaller.rc())) return autoCaller.rc();
593
594 /* the machine needs to be mutable */
595 AutoMutableStateDependency adep(mParent);
596 if (FAILED(adep.rc())) return adep.rc();
597
598 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
599
600 if (mData->mAllowMultiConnection != aAllowMultiConnection)
601 {
602 mData.backup();
603 mData->mAllowMultiConnection = aAllowMultiConnection;
604
605 /* leave the lock before informing callbacks */
606 alock.release();
607
608 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
609 mParent->setModified(Machine::IsModified_VRDEServer);
610 mlock.release();
611
612 mParent->onVRDEServerChange(/* aRestart */ TRUE); // @todo does it need a restart?
613 }
614
615 return S_OK;
616}
617
618STDMETHODIMP VRDEServer::COMGETTER(ReuseSingleConnection) (
619 BOOL *aReuseSingleConnection)
620{
621 CheckComArgOutPointerValid(aReuseSingleConnection);
622
623 AutoCaller autoCaller(this);
624 if (FAILED(autoCaller.rc())) return autoCaller.rc();
625
626 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
627
628 *aReuseSingleConnection = mData->mReuseSingleConnection;
629
630 return S_OK;
631}
632
633STDMETHODIMP VRDEServer::COMSETTER(ReuseSingleConnection) (
634 BOOL aReuseSingleConnection)
635{
636 AutoCaller autoCaller(this);
637 if (FAILED(autoCaller.rc())) return autoCaller.rc();
638
639 /* the machine needs to be mutable */
640 AutoMutableStateDependency adep(mParent);
641 if (FAILED(adep.rc())) return adep.rc();
642
643 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
644
645 if (mData->mReuseSingleConnection != aReuseSingleConnection)
646 {
647 mData.backup();
648 mData->mReuseSingleConnection = aReuseSingleConnection;
649
650 /* leave the lock before informing callbacks */
651 alock.release();
652
653 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
654 mParent->setModified(Machine::IsModified_VRDEServer);
655 mlock.release();
656
657 mParent->onVRDEServerChange(/* aRestart */ TRUE); // @todo needs a restart?
658 }
659
660 return S_OK;
661}
662
663STDMETHODIMP VRDEServer::COMGETTER(VideoChannel) (
664 BOOL *aVideoChannel)
665{
666 CheckComArgOutPointerValid(aVideoChannel);
667
668 AutoCaller autoCaller(this);
669 if (FAILED(autoCaller.rc())) return autoCaller.rc();
670
671 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
672
673 *aVideoChannel = mData->mVideoChannel;
674
675 return S_OK;
676}
677
678STDMETHODIMP VRDEServer::COMSETTER(VideoChannel) (
679 BOOL aVideoChannel)
680{
681 AutoCaller autoCaller(this);
682 if (FAILED(autoCaller.rc())) return autoCaller.rc();
683
684 /* the machine needs to be mutable */
685 AutoMutableStateDependency adep(mParent);
686 if (FAILED(adep.rc())) return adep.rc();
687
688 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
689
690 if (mData->mVideoChannel != aVideoChannel)
691 {
692 mData.backup();
693 mData->mVideoChannel = aVideoChannel;
694
695 /* leave the lock before informing callbacks */
696 alock.release();
697
698 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
699 mParent->setModified(Machine::IsModified_VRDEServer);
700 mlock.release();
701
702 mParent->onVRDEServerChange(/* aRestart */ TRUE);
703 }
704
705 return S_OK;
706}
707
708STDMETHODIMP VRDEServer::COMGETTER(VideoChannelQuality) (
709 ULONG *aVideoChannelQuality)
710{
711 CheckComArgOutPointerValid(aVideoChannelQuality);
712
713 AutoCaller autoCaller(this);
714 if (FAILED(autoCaller.rc())) return autoCaller.rc();
715
716 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
717
718 *aVideoChannelQuality = mData->mVideoChannelQuality;
719
720 return S_OK;
721}
722
723STDMETHODIMP VRDEServer::COMSETTER(VideoChannelQuality) (
724 ULONG aVideoChannelQuality)
725{
726 AutoCaller autoCaller(this);
727 if (FAILED(autoCaller.rc())) return autoCaller.rc();
728
729 /* the machine needs to be mutable */
730 AutoMutableStateDependency adep(mParent);
731 if (FAILED(adep.rc())) return adep.rc();
732
733 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
734
735 aVideoChannelQuality = RT_CLAMP(aVideoChannelQuality, 10, 100);
736
737 if (mData->mVideoChannelQuality != aVideoChannelQuality)
738 {
739 mData.backup();
740 mData->mVideoChannelQuality = aVideoChannelQuality;
741
742 /* leave the lock before informing callbacks */
743 alock.release();
744
745 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
746 mParent->setModified(Machine::IsModified_VRDEServer);
747 mlock.release();
748
749 mParent->onVRDEServerChange(/* aRestart */ FALSE);
750 }
751
752 return S_OK;
753}
754
755STDMETHODIMP VRDEServer::COMGETTER(VRDELibrary) (BSTR *aVRDELibrary)
756{
757 CheckComArgOutPointerValid(aVRDELibrary);
758
759 AutoCaller autoCaller(this);
760 if (FAILED(autoCaller.rc())) return autoCaller.rc();
761
762 Bstr bstrLibrary;
763
764 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
765 bstrLibrary = mData->mVRDELibrary;
766 alock.release();
767
768 if (!bstrLibrary.isEmpty())
769 {
770 BOOL fRegistered = FALSE;
771 HRESULT hrc = mParent->getVirtualBox()->VRDEIsLibraryRegistered(bstrLibrary.raw(), &fRegistered);
772 if (FAILED(hrc) || !fRegistered)
773 return setError(E_FAIL, "The library is not registered\n");
774 }
775 else
776 {
777 /* Get the global setting. */
778 ComPtr<ISystemProperties> systemProperties;
779 HRESULT hrc = mParent->getVirtualBox()->COMGETTER(SystemProperties)(systemProperties.asOutParam());
780
781 if (SUCCEEDED(hrc))
782 hrc = systemProperties->COMGETTER(DefaultVRDELibrary)(bstrLibrary.asOutParam());
783
784 if (FAILED(hrc))
785 return setError(hrc, "failed to query the library setting\n");
786 }
787
788 bstrLibrary.cloneTo(aVRDELibrary);
789
790 return S_OK;
791}
792
793STDMETHODIMP VRDEServer::COMSETTER(VRDELibrary) (IN_BSTR aVRDELibrary)
794{
795 AutoCaller autoCaller(this);
796 if (FAILED(autoCaller.rc())) return autoCaller.rc();
797
798 /* the machine needs to be mutable */
799 AutoMutableStateDependency adep(mParent);
800 if (FAILED(adep.rc())) return adep.rc();
801
802 Bstr bstrLibrary(aVRDELibrary);
803
804 if (!bstrLibrary.isEmpty())
805 {
806 BOOL fRegistered = FALSE;
807 HRESULT rc = mParent->getVirtualBox()->VRDEIsLibraryRegistered(bstrLibrary.raw(), &fRegistered);
808 if (FAILED(rc) || !fRegistered)
809 return setError(E_FAIL, "The library is not registered\n");
810 }
811
812 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
813
814 if (mData->mVRDELibrary != aVRDELibrary)
815 {
816 mData.backup();
817 mData->mVRDELibrary = aVRDELibrary;
818
819 /* leave the lock before informing callbacks */
820 alock.release();
821
822 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
823 mParent->setModified(Machine::IsModified_VRDEServer);
824 mlock.release();
825
826 mParent->onVRDEServerChange(/* aRestart */ TRUE);
827 }
828
829 return S_OK;
830}
831
832// public methods only for internal purposes
833/////////////////////////////////////////////////////////////////////////////
834
835/**
836 * @note Locks this object for writing.
837 */
838void VRDEServer::rollback()
839{
840 /* sanity */
841 AutoCaller autoCaller(this);
842 AssertComRCReturnVoid(autoCaller.rc());
843
844 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
845
846 mData.rollback();
847}
848
849/**
850 * @note Locks this object for writing, together with the peer object (also
851 * for writing) if there is one.
852 */
853void VRDEServer::commit()
854{
855 /* sanity */
856 AutoCaller autoCaller(this);
857 AssertComRCReturnVoid (autoCaller.rc());
858
859 /* sanity too */
860 AutoCaller peerCaller (mPeer);
861 AssertComRCReturnVoid (peerCaller.rc());
862
863 /* lock both for writing since we modify both (mPeer is "master" so locked
864 * first) */
865 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
866
867 if (mData.isBackedUp())
868 {
869 mData.commit();
870 if (mPeer)
871 {
872 /* attach new data to the peer and reshare it */
873 mPeer->mData.attach (mData);
874 }
875 }
876}
877
878/**
879 * @note Locks this object for writing, together with the peer object
880 * represented by @a aThat (locked for reading).
881 */
882void VRDEServer::copyFrom (VRDEServer *aThat)
883{
884 AssertReturnVoid (aThat != NULL);
885
886 /* sanity */
887 AutoCaller autoCaller(this);
888 AssertComRCReturnVoid (autoCaller.rc());
889
890 /* sanity too */
891 AutoCaller thatCaller (aThat);
892 AssertComRCReturnVoid (thatCaller.rc());
893
894 /* peer is not modified, lock it for reading (aThat is "master" so locked
895 * first) */
896 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
897 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
898
899 /* this will back up current data */
900 mData.assignCopy (aThat->mData);
901}
902/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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