VirtualBox

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

Last change on this file since 34645 was 34574, checked in by vboxsync, 14 years ago

Make vrde auth library configurable per VM.

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