VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/SessionImpl.cpp

Last change on this file was 98262, checked in by vboxsync, 16 months ago

Main: rc() -> hrc()/vrc(). bugref:10223

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.9 KB
RevLine 
[29853]1/* $Id: SessionImpl.cpp 98262 2023-01-24 01:42:14Z vboxsync $ */
[1]2/** @file
[29853]3 * VBox Client Session COM Class implementation in VBoxC.
[1]4 */
5
6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[1]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
[1]26 */
27
[67914]28#define LOG_GROUP LOG_GROUP_MAIN_SESSION
29#include "LoggingNew.h"
30
[1]31#include "SessionImpl.h"
32#include "ConsoleImpl.h"
[93410]33#include "ClientTokenHolder.h"
[23675]34#include "Global.h"
[93410]35#include "StringifyEnums.h"
[1]36
[25860]37#include "AutoCaller.h"
[1]38
[76474]39#include <iprt/errcore.h>
[1]40#include <iprt/process.h>
41
[67914]42
[1]43/**
44 * Local macro to check whether the session is open and return an error if not.
45 * @note Don't forget to do |Auto[Reader]Lock alock (this);| before using this
46 * macro.
47 */
48#define CHECK_OPEN() \
49 do { \
[31008]50 if (mState != SessionState_Locked) \
[91312]51 return setError(E_UNEXPECTED, Session::tr("The session is not locked (session state: %s)"), \
[52232]52 Global::stringifySessionState(mState)); \
[1]53 } while (0)
54
55// constructor / destructor
56/////////////////////////////////////////////////////////////////////////////
57
[52232]58Session::Session()
59{
60}
61
62Session::~Session()
63{
64}
65
[1]66HRESULT Session::FinalConstruct()
67{
[21878]68 LogFlowThisFunc(("\n"));
[1]69
[94949]70 HRESULT hrc = init();
[37423]71
72 BaseFinalConstruct();
73
[94949]74 return hrc;
[1]75}
76
77void Session::FinalRelease()
78{
[21878]79 LogFlowThisFunc(("\n"));
[1]80
[31070]81 uninit();
[37423]82
[35638]83 BaseFinalRelease();
[1]84}
85
86// public initializer/uninitializer for internal purposes only
87/////////////////////////////////////////////////////////////////////////////
88
89/**
90 * Initializes the Session object.
91 */
92HRESULT Session::init()
93{
94 /* Enclose the state transition NotReady->InInit->Ready */
[21878]95 AutoInitSpan autoInitSpan(this);
96 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[1]97
98 LogFlowThisFuncEnter();
99
[31008]100 mState = SessionState_Unlocked;
[7207]101 mType = SessionType_Null;
[1]102
[47561]103 mClientTokenHolder = NULL;
[1]104
105 /* Confirm a successful initialization when it's the case */
106 autoInitSpan.setSucceeded();
107
108 LogFlowThisFuncLeave();
109
110 return S_OK;
111}
112
113/**
114 * Uninitializes the Session object.
115 *
116 * @note Locks this object for writing.
117 */
[31070]118void Session::uninit()
[1]119{
120 LogFlowThisFuncEnter();
121
122 /* Enclose the state transition Ready->InUninit->NotReady */
[21878]123 AutoUninitSpan autoUninitSpan(this);
[1]124 if (autoUninitSpan.uninitDone())
125 {
[21878]126 LogFlowThisFunc(("Already uninitialized.\n"));
[1]127 LogFlowThisFuncLeave();
128 return;
129 }
130
[8057]131 /* close() needs write lock */
[25310]132 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]133
[31008]134 if (mState != SessionState_Unlocked)
[1]135 {
[31008]136 Assert(mState == SessionState_Locked ||
[26186]137 mState == SessionState_Spawning);
[1]138
[94949]139 HRESULT hrc = i_unlockMachine(true /* aFinalRelease */, false /* aFromServer */, alock);
140 AssertComRC(hrc);
[1]141 }
142
143 LogFlowThisFuncLeave();
144}
145
146// ISession properties
147/////////////////////////////////////////////////////////////////////////////
148
[52232]149HRESULT Session::getState(SessionState_T *aState)
[1]150{
[25310]151 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]152
153 *aState = mState;
154
155 return S_OK;
156}
157
[52232]158HRESULT Session::getType(SessionType_T *aType)
[1]159{
[25310]160 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]161
162 CHECK_OPEN();
163
164 *aType = mType;
165 return S_OK;
166}
167
[55800]168HRESULT Session::getName(com::Utf8Str &aName)
169{
170 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
171
172 aName = mName;
173 return S_OK;
174}
175
176HRESULT Session::setName(const com::Utf8Str &aName)
177{
178 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
179
180 if (mState != SessionState_Unlocked)
181 return setError(VBOX_E_INVALID_OBJECT_STATE, tr("Trying to set name for a session which is not in state \"unlocked\""));
182
183 mName = aName;
184 return S_OK;
185}
186
[52232]187HRESULT Session::getMachine(ComPtr<IMachine> &aMachine)
[1]188{
[25310]189 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]190
191 CHECK_OPEN();
192
[94949]193 HRESULT hrc;
[48282]194#ifndef VBOX_COM_INPROC_API_CLIENT
[1]195 if (mConsole)
[94949]196 hrc = mConsole->i_machine().queryInterfaceTo(aMachine.asOutParam());
[1]197 else
[48282]198#endif
[94949]199 hrc = mRemoteMachine.queryInterfaceTo(aMachine.asOutParam());
200 if (FAILED(hrc))
[29953]201 {
[48282]202#ifndef VBOX_COM_INPROC_API_CLIENT
[29953]203 if (mConsole)
[94949]204 setError(hrc, tr("Failed to query the session machine"));
[48282]205 else
206#endif
[94949]207 if (FAILED_DEAD_INTERFACE(hrc))
208 setError(hrc, tr("Peer process crashed"));
[29953]209 else
[94949]210 setError(hrc, tr("Failed to query the remote session machine"));
[29953]211 }
[1]212
[94949]213 return hrc;
[1]214}
215
[52232]216HRESULT Session::getConsole(ComPtr<IConsole> &aConsole)
[1]217{
[25310]218 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]219
220 CHECK_OPEN();
221
[94949]222 HRESULT hrc = S_OK;
[48282]223#ifndef VBOX_COM_INPROC_API_CLIENT
[1]224 if (mConsole)
[94949]225 hrc = mConsole.queryInterfaceTo(aConsole.asOutParam());
[1]226 else
[48282]227#endif
[94949]228 hrc = mRemoteConsole.queryInterfaceTo(aConsole.asOutParam());
[35638]229
[94949]230 if (FAILED(hrc))
[29953]231 {
[48282]232#ifndef VBOX_COM_INPROC_API_CLIENT
[29953]233 if (mConsole)
[94949]234 setError(hrc, tr("Failed to query the console"));
[48282]235 else
236#endif
[94949]237 if (FAILED_DEAD_INTERFACE(hrc))
238 setError(hrc, tr("Peer process crashed"));
[29953]239 else
[94949]240 setError(hrc, tr("Failed to query the remote console"));
[29953]241 }
[1]242
[94949]243 return hrc;
[1]244}
245
246// ISession methods
247/////////////////////////////////////////////////////////////////////////////
[52232]248HRESULT Session::unlockMachine()
[1]249{
[21878]250 LogFlowThisFunc(("mState=%d, mType=%d\n", mState, mType));
[1]251
252 /* close() needs write lock */
[25310]253 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]254
255 CHECK_OPEN();
[56450]256 return i_unlockMachine(false /* aFinalRelease */, false /* aFromServer */, alock);
[1]257}
258
259// IInternalSessionControl methods
260/////////////////////////////////////////////////////////////////////////////
[52232]261HRESULT Session::getPID(ULONG *aPid)
[1]262{
[25310]263 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]264
[26186]265 *aPid = (ULONG)RTProcSelf();
266 AssertCompile(sizeof(*aPid) == sizeof(RTPROCESS));
[1]267
268 return S_OK;
269}
270
[52232]271HRESULT Session::getRemoteConsole(ComPtr<IConsole> &aConsole)
[1]272{
[20274]273 LogFlowThisFuncEnter();
[92274]274#ifndef VBOX_COM_INPROC_API_CLIENT
[25310]275 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]276
[92271]277 if (mType == SessionType_WriteLock && !!mConsole)
278 {
279 /* return a failure if the session already transitioned to Closing
280 * but the server hasn't processed Machine::OnSessionEnd() yet. */
281 if (mState == SessionState_Locked)
282 {
283 mConsole.queryInterfaceTo(aConsole.asOutParam());
[1]284
[92271]285 LogFlowThisFuncLeave();
286 return S_OK;
287 }
[15834]288 return VBOX_E_INVALID_VM_STATE;
[92271]289 }
290 return setError(VBOX_E_INVALID_OBJECT_STATE, "This is not a direct session");
[12658]291
[48282]292#else /* VBOX_COM_INPROC_API_CLIENT */
[63258]293 RT_NOREF(aConsole);
[48299]294 AssertFailed();
[48282]295 return VBOX_E_INVALID_OBJECT_STATE;
296#endif /* VBOX_COM_INPROC_API_CLIENT */
[1]297}
298
[55214]299HRESULT Session::getNominalState(MachineState_T *aNominalState)
300{
301 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
302 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
303 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
304#ifndef VBOX_COM_INPROC_API_CLIENT
305 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
306
307 return mConsole->i_getNominalState(*aNominalState);
308#else
[63258]309 RT_NOREF(aNominalState);
[55214]310 AssertFailed();
311 return E_NOTIMPL;
312#endif
313}
314
[48431]315#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
[52248]316HRESULT Session::assignMachine(const ComPtr<IMachine> &aMachine,
[52481]317 LockType_T aLockType,
318 const com::Utf8Str &aTokenId)
[52248]319#else
320HRESULT Session::assignMachine(const ComPtr<IMachine> &aMachine,
[52481]321 LockType_T aLockType,
322 const ComPtr<IToken> &aToken)
[52248]323#endif /* !VBOX_WITH_GENERIC_SESSION_WATCHER */
[1]324{
[25310]325 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]326
[31008]327 AssertReturn(mState == SessionState_Unlocked, VBOX_E_INVALID_VM_STATE);
[1]328
329 if (!aMachine)
330 {
331 /*
332 * A special case: the server informs us that this session has been
[31008]333 * passed to IMachine::launchVMProcess() so this session will become
334 * remote (but not existing) when AssignRemoteMachine() is called.
[1]335 */
336
[21878]337 AssertReturn(mType == SessionType_Null, VBOX_E_INVALID_OBJECT_STATE);
[7207]338 mType = SessionType_Remote;
339 mState = SessionState_Spawning;
[1]340
341 return S_OK;
342 }
343
344 /* query IInternalMachineControl interface */
345 mControl = aMachine;
[21878]346 AssertReturn(!!mControl, E_FAIL);
[1]347
[94949]348 HRESULT hrc = S_OK;
[48282]349#ifndef VBOX_COM_INPROC_API_CLIENT
[55214]350 if (aLockType == LockType_VM)
351 {
352 /* This is what is special about VM processes: they have a Console
353 * object which is the root of all VM related activity. */
[94949]354 hrc = mConsole.createObject();
355 AssertComRCReturn(hrc, hrc);
[1]356
[94949]357 hrc = mConsole->initWithMachine(aMachine, mControl, aLockType);
358 AssertComRCReturn(hrc, hrc);
[55214]359 }
360 else
361 mRemoteMachine = aMachine;
[48299]362#else
[63258]363 RT_NOREF(aLockType);
[48299]364 mRemoteMachine = aMachine;
[48282]365#endif
[1]366
[48431]367#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
[47561]368 Utf8Str strTokenId(aTokenId);
369 Assert(!strTokenId.isEmpty());
[48431]370#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
[52248]371 Assert(!aToken.isNull());
[48431]372#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
[47561]373 /* create the machine client token */
374 try
375 {
[48431]376#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
[47561]377 mClientTokenHolder = new ClientTokenHolder(strTokenId);
[48431]378#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
379 mClientTokenHolder = new ClientTokenHolder(aToken);
380#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
[47561]381 if (!mClientTokenHolder->isReady())
382 {
383 delete mClientTokenHolder;
384 mClientTokenHolder = NULL;
[94949]385 hrc = E_FAIL;
[47561]386 }
387 }
388 catch (std::bad_alloc &)
389 {
[94949]390 hrc = E_OUTOFMEMORY;
[47561]391 }
[1]392
393 /*
394 * Reference the VirtualBox object to ensure the server is up
395 * until the session is closed
396 */
[94949]397 if (SUCCEEDED(hrc))
398 hrc = aMachine->COMGETTER(Parent)(mVirtualBox.asOutParam());
[1]399
[94949]400 if (SUCCEEDED(hrc))
[25149]401 {
[31019]402 mType = SessionType_WriteLock;
[31008]403 mState = SessionState_Locked;
[1]404 }
405 else
406 {
407 /* some cleanup */
408 mControl.setNull();
[48282]409#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]410 if (!mConsole.isNull())
411 {
412 mConsole->uninit();
413 mConsole.setNull();
414 }
[48282]415#endif
[1]416 }
417
[94949]418 return hrc;
[1]419}
420
[52232]421HRESULT Session::assignRemoteMachine(const ComPtr<IMachine> &aMachine,
422 const ComPtr<IConsole> &aConsole)
423
[1]424{
[55214]425 AssertReturn(aMachine, E_INVALIDARG);
[1]426
[25310]427 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]428
[31008]429 AssertReturn(mState == SessionState_Unlocked ||
[52232]430 mState == SessionState_Spawning, VBOX_E_INVALID_VM_STATE);
[1]431
[94949]432 HRESULT hrc = E_FAIL;
[1]433
434 /* query IInternalMachineControl interface */
435 mControl = aMachine;
[29853]436 AssertReturn(!!mControl, E_FAIL);
[1]437
438 /// @todo (dmik)
439 // currently, the remote session returns the same machine and
440 // console objects as the direct session, thus giving the
441 // (remote) client full control over the direct session. For the
442 // console, it is the desired behavior (the ability to control
443 // VM execution is a must for the remote session). What about
444 // the machine object, we may want to prevent the remote client
445 // from modifying machine data. In this case, we must:
446 // 1) assign the Machine object (instead of the SessionMachine
447 // object that is passed to this method) to mRemoteMachine;
448 // 2) remove GetMachine() property from the IConsole interface
449 // because it always returns the SessionMachine object
450 // (alternatively, we can supply a separate IConsole
451 // implementation that will return the Machine object in
452 // response to GetMachine()).
453
454 mRemoteMachine = aMachine;
455 mRemoteConsole = aConsole;
456
457 /*
458 * Reference the VirtualBox object to ensure the server is up
459 * until the session is closed
460 */
[94949]461 hrc = aMachine->COMGETTER(Parent)(mVirtualBox.asOutParam());
[1]462
[94949]463 if (SUCCEEDED(hrc))
[1]464 {
465 /*
466 * RemoteSession type can be already set by AssignMachine() when its
467 * argument is NULL (a special case)
468 */
[7207]469 if (mType != SessionType_Remote)
[31008]470 mType = SessionType_Shared;
[1]471 else
[26186]472 Assert(mState == SessionState_Spawning);
[1]473
[31008]474 mState = SessionState_Locked;
[1]475 }
476 else
477 {
478 /* some cleanup */
479 mControl.setNull();
480 mRemoteMachine.setNull();
481 mRemoteConsole.setNull();
482 }
483
[94949]484 LogFlowThisFunc(("hrc=%08X\n", hrc));
[1]485 LogFlowThisFuncLeave();
486
[94949]487 return hrc;
[1]488}
489
[52232]490HRESULT Session::updateMachineState(MachineState_T aMachineState)
[1]491{
492
[51903]493 if (getObjectState().getState() != ObjectState::Ready)
[1]494 {
495 /*
496 * We might have already entered Session::uninit() at this point, so
497 * return silently (not interested in the state change during uninit)
498 */
[21878]499 LogFlowThisFunc(("Already uninitialized.\n"));
[1]500 return S_OK;
501 }
502
[25310]503 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]504
[31008]505 if (mState == SessionState_Unlocking)
[1]506 {
[31008]507 LogFlowThisFunc(("Already being unlocked.\n"));
[1]508 return S_OK;
509 }
510
[31008]511 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]512 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[1]513
[21878]514 AssertReturn(!mControl.isNull(), E_FAIL);
[48282]515#ifndef VBOX_COM_INPROC_API_CLIENT
[21878]516 AssertReturn(!mConsole.isNull(), E_FAIL);
[1]517
[51612]518 return mConsole->i_updateMachineState(aMachineState);
[48282]519#else
[63258]520 RT_NOREF(aMachineState);
[48282]521 return S_OK;
522#endif
[1]523}
524
[52232]525HRESULT Session::uninitialize()
[1]526{
527 LogFlowThisFuncEnter();
528
[21878]529 AutoCaller autoCaller(this);
[1]530
[94949]531 HRESULT hrc = S_OK;
[1]532
[51903]533 if (getObjectState().getState() == ObjectState::Ready)
[1]534 {
[8057]535 /* close() needs write lock */
[25310]536 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[1]537
[93410]538 LogFlowThisFunc(("mState=%s, mType=%d\n", ::stringifySessionState(mState), mType));
[1]539
[31008]540 if (mState == SessionState_Unlocking)
[1]541 {
[31008]542 LogFlowThisFunc(("Already being unlocked.\n"));
[1]543 return S_OK;
544 }
545
[56683]546 if ( mState == SessionState_Locked
547 || mState == SessionState_Spawning)
548 { /* likely */ }
549 else
550 {
551#ifndef DEBUG_bird /* bird: hitting this all the time running tdAddBaseic1.py. */
552 AssertMsgFailed(("Session is in wrong state (%d), expected locked (%d) or spawning (%d)\n",
553 mState, SessionState_Locked, SessionState_Spawning));
554#endif
555 return VBOX_E_INVALID_VM_STATE;
556 }
[1]557
558 /* close ourselves */
[94949]559 hrc = i_unlockMachine(false /* aFinalRelease */, true /* aFromServer */, alock);
[1]560 }
[51903]561 else if (getObjectState().getState() == ObjectState::InUninit)
[1]562 {
563 /*
564 * We might have already entered Session::uninit() at this point,
565 * return silently
566 */
[21878]567 LogFlowThisFunc(("Already uninitialized.\n"));
[1]568 }
569 else
570 {
[55988]571 Log1WarningThisFunc(("UNEXPECTED uninitialization!\n"));
[98262]572 hrc = autoCaller.hrc();
[1]573 }
574
[94949]575 LogFlowThisFunc(("hrc=%08X\n", hrc));
[1]576 LogFlowThisFuncLeave();
577
[94949]578 return hrc;
[1]579}
580
[52232]581HRESULT Session::onNetworkAdapterChange(const ComPtr<INetworkAdapter> &aNetworkAdapter,
582 BOOL aChangeAdapter)
583
[1]584{
[21878]585 LogFlowThisFunc(("\n"));
[1]586
[25310]587 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]588 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]589 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]590#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]591 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[1]592
[52232]593 return mConsole->i_onNetworkAdapterChange(aNetworkAdapter, aChangeAdapter);
[48282]594#else
[63258]595 RT_NOREF(aNetworkAdapter, aChangeAdapter);
[48282]596 return S_OK;
597#endif
[1]598}
599
[68485]600HRESULT Session::onAudioAdapterChange(const ComPtr<IAudioAdapter> &aAudioAdapter)
601{
602 LogFlowThisFunc(("\n"));
603
604 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
605 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
606 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
607#ifndef VBOX_COM_INPROC_API_CLIENT
608 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
609
610 return mConsole->i_onAudioAdapterChange(aAudioAdapter);
611#else
612 RT_NOREF(aAudioAdapter);
613 return S_OK;
614#endif
615
616}
617
[95423]618HRESULT Session::onHostAudioDeviceChange(const ComPtr<IHostAudioDevice> &aDevice,
619 BOOL aNew, AudioDeviceState_T aState,
620 const ComPtr<IVirtualBoxErrorInfo> &aErrInfo)
621{
622 LogFlowThisFunc(("\n"));
623
624 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
625 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
626 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
627#ifndef VBOX_COM_INPROC_API_CLIENT
628 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
629
630 return mConsole->i_onHostAudioDeviceChange(aDevice, aNew, aState, aErrInfo);
631#else
632 RT_NOREF(aDevice, aNew, aState, aErrInfo);
633 return S_OK;
634#endif
635}
636
[52232]637HRESULT Session::onSerialPortChange(const ComPtr<ISerialPort> &aSerialPort)
[1]638{
[21878]639 LogFlowThisFunc(("\n"));
[1]640
[25310]641 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]642 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]643 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]644#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]645 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[1]646
[52232]647 return mConsole->i_onSerialPortChange(aSerialPort);
[48282]648#else
[63258]649 RT_NOREF(aSerialPort);
[48282]650 return S_OK;
651#endif
[1]652}
653
[52232]654HRESULT Session::onParallelPortChange(const ComPtr<IParallelPort> &aParallelPort)
[1]655{
[21878]656 LogFlowThisFunc(("\n"));
[1]657
[25310]658 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]659 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]660 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]661#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]662 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[1]663
[52232]664 return mConsole->i_onParallelPortChange(aParallelPort);
[48282]665#else
[63258]666 RT_NOREF(aParallelPort);
[48282]667 return S_OK;
668#endif
[1]669}
670
[78261]671HRESULT Session::onStorageControllerChange(const Guid &aMachineId, const Utf8Str &aControllerName)
[3494]672{
[21878]673 LogFlowThisFunc(("\n"));
[3494]674
[25310]675 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]676 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]677 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]678#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]679 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[3494]680
[78261]681 return mConsole->i_onStorageControllerChange(aMachineId, aControllerName);
[48282]682#else
[78261]683 NOREF(aMachineId);
684 NOREF(aControllerName);
[48282]685 return S_OK;
686#endif
[3494]687}
688
[52232]689HRESULT Session::onMediumChange(const ComPtr<IMediumAttachment> &aMediumAttachment,
690 BOOL aForce)
[3652]691{
[21878]692 LogFlowThisFunc(("\n"));
[3652]693
[25310]694 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]695 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]696 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]697#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]698 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[3652]699
[51612]700 return mConsole->i_onMediumChange(aMediumAttachment, aForce);
[48282]701#else
[63258]702 RT_NOREF(aMediumAttachment, aForce);
[48282]703 return S_OK;
704#endif
[3652]705}
706
[77910]707HRESULT Session::onVMProcessPriorityChange(VMProcPriority_T priority)
708{
709 LogFlowThisFunc(("\n"));
710
711 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
712 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
713 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
714#ifndef VBOX_COM_INPROC_API_CLIENT
715 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
716
717 return mConsole->i_onVMProcessPriorityChange(priority);
718#else
719 RT_NOREF(priority);
720 return S_OK;
721#endif
722}
723
[52232]724HRESULT Session::onCPUChange(ULONG aCpu, BOOL aAdd)
[25901]725{
726 LogFlowThisFunc(("\n"));
727
728 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]729 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]730 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]731#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]732 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[25901]733
[52232]734 return mConsole->i_onCPUChange(aCpu, aAdd);
[48282]735#else
[63258]736 RT_NOREF(aCpu, aAdd);
[48282]737 return S_OK;
738#endif
[25901]739}
740
[52232]741HRESULT Session::onCPUExecutionCapChange(ULONG aExecutionCap)
[31332]742{
743 LogFlowThisFunc(("\n"));
744
745 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
746 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
747 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]748#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]749 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[31332]750
[51612]751 return mConsole->i_onCPUExecutionCapChange(aExecutionCap);
[48282]752#else
[63258]753 RT_NOREF(aExecutionCap);
[48282]754 return S_OK;
755#endif
[31332]756}
757
[52232]758HRESULT Session::onVRDEServerChange(BOOL aRestart)
[1]759{
[21878]760 LogFlowThisFunc(("\n"));
[1]761
[25310]762 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]763 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]764 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]765#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]766 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[1]767
[51612]768 return mConsole->i_onVRDEServerChange(aRestart);
[48282]769#else
[63258]770 RT_NOREF(aRestart);
[48282]771 return S_OK;
772#endif
[1]773}
774
[75488]775HRESULT Session::onRecordingChange(BOOL aEnable)
[46465]776{
777 LogFlowThisFunc(("\n"));
778
779 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
780 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
781 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]782#ifndef VBOX_COM_INPROC_API_CLIENT
[46465]783 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
784
[75488]785 return mConsole->i_onRecordingChange(aEnable);
[48282]786#else
[75496]787 RT_NOREF(aEnable);
[48282]788 return S_OK;
789#endif
[46465]790}
791
[52232]792HRESULT Session::onUSBControllerChange()
[1]793{
[21878]794 LogFlowThisFunc(("\n"));
[1]795
[25310]796 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]797 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]798 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]799#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]800 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[1]801
[51612]802 return mConsole->i_onUSBControllerChange();
[48282]803#else
804 return S_OK;
805#endif
[1]806}
807
[52232]808HRESULT Session::onSharedFolderChange(BOOL aGlobal)
[4041]809{
[21878]810 LogFlowThisFunc(("\n"));
[4041]811
[25310]812 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]813 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]814 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]815#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]816 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[4041]817
[51612]818 return mConsole->i_onSharedFolderChange(aGlobal);
[48282]819#else
[63258]820 RT_NOREF(aGlobal);
[48282]821 return S_OK;
822#endif
[4041]823}
824
[52232]825HRESULT Session::onClipboardModeChange(ClipboardMode_T aClipboardMode)
[41925]826{
827 LogFlowThisFunc(("\n"));
828
829 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
830 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
831 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]832#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]833 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[41925]834
[51612]835 return mConsole->i_onClipboardModeChange(aClipboardMode);
[48282]836#else
[63258]837 RT_NOREF(aClipboardMode);
[48282]838 return S_OK;
839#endif
[41925]840}
841
[81286]842HRESULT Session::onClipboardFileTransferModeChange(BOOL aEnabled)
843{
844 LogFlowThisFunc(("\n"));
845
846 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
847 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
848 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
849#ifndef VBOX_COM_INPROC_API_CLIENT
850 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
851
852 return mConsole->i_onClipboardFileTransferModeChange(RT_BOOL(aEnabled));
853#else
854 RT_NOREF(aEnabled);
855 return S_OK;
856#endif
857}
858
[52232]859HRESULT Session::onDnDModeChange(DnDMode_T aDndMode)
[42261]860{
861 LogFlowThisFunc(("\n"));
862
863 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
864 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[48282]865#ifndef VBOX_COM_INPROC_API_CLIENT
[42261]866 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[55214]867 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[42261]868
[52232]869 return mConsole->i_onDnDModeChange(aDndMode);
[48282]870#else
[63258]871 RT_NOREF(aDndMode);
[48282]872 return S_OK;
873#endif
[42261]874}
875
[96888]876HRESULT Session::onGuestDebugControlChange(const ComPtr<IGuestDebugControl> &aGuestDebugControl)
877{
878 LogFlowThisFunc(("\n"));
879
880 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
881 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
882 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
883#ifndef VBOX_COM_INPROC_API_CLIENT
884 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
885
886 return mConsole->i_onGuestDebugControlChange(aGuestDebugControl);
887#else
[96890]888 RT_NOREF(aGuestDebugControl);
[96888]889 return S_OK;
890#endif
891}
892
[52232]893HRESULT Session::onUSBDeviceAttach(const ComPtr<IUSBDevice> &aDevice,
894 const ComPtr<IVirtualBoxErrorInfo> &aError,
[53062]895 ULONG aMaskedInterfaces,
896 const com::Utf8Str &aCaptureFilename)
[1]897{
[21878]898 LogFlowThisFunc(("\n"));
[1]899
[25310]900 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]901 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]902 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]903#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]904 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[1]905
[53062]906 return mConsole->i_onUSBDeviceAttach(aDevice, aError, aMaskedInterfaces, aCaptureFilename);
[48282]907#else
[63258]908 RT_NOREF(aDevice, aError, aMaskedInterfaces, aCaptureFilename);
[48282]909 return S_OK;
910#endif
[1]911}
912
[52232]913HRESULT Session::onUSBDeviceDetach(const com::Guid &aId,
914 const ComPtr<IVirtualBoxErrorInfo> &aError)
[1]915{
[21878]916 LogFlowThisFunc(("\n"));
[1]917
[25310]918 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[31008]919 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
[31019]920 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]921#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]922 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[1]923
[52232]924 return mConsole->i_onUSBDeviceDetach(aId.toUtf16().raw(), aError);
[48282]925#else
[63258]926 RT_NOREF(aId, aError);
[48282]927 return S_OK;
928#endif
[1]929}
930
[52232]931HRESULT Session::onShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId)
[2463]932{
[25310]933 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[2463]934
[31019]935 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]936#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]937 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[48282]938#endif
[11918]939
[31008]940 if (mState != SessionState_Locked)
[11918]941 {
942 /* the call from Machine issued when the session is open can arrive
943 * after the session starts closing or gets closed. Note that when
944 * aCheck is false, we return E_FAIL to indicate that aWinId we return
945 * is not valid */
946 *aCanShow = FALSE;
947 *aWinId = 0;
948 return aCheck ? S_OK : E_FAIL;
949 }
950
[48282]951#ifndef VBOX_COM_INPROC_API_CLIENT
[51612]952 return mConsole->i_onShowWindow(aCheck, aCanShow, aWinId);
[48282]953#else
954 return S_OK;
955#endif
[2463]956}
957
[52232]958HRESULT Session::onBandwidthGroupChange(const ComPtr<IBandwidthGroup> &aBandwidthGroup)
[34587]959{
960 LogFlowThisFunc(("\n"));
961
962 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
963 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
964 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]965#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]966 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[34587]967
[51612]968 return mConsole->i_onBandwidthGroupChange(aBandwidthGroup);
[48282]969#else
[63258]970 RT_NOREF(aBandwidthGroup);
[48282]971 return S_OK;
972#endif
[34587]973}
974
[52232]975HRESULT Session::onStorageDeviceChange(const ComPtr<IMediumAttachment> &aMediumAttachment, BOOL aRemove, BOOL aSilent)
[36991]976{
977 LogFlowThisFunc(("\n"));
978
979 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
980 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
981 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]982#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]983 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[36991]984
[51612]985 return mConsole->i_onStorageDeviceChange(aMediumAttachment, aRemove, aSilent);
[48282]986#else
[63258]987 RT_NOREF(aMediumAttachment, aRemove, aSilent);
[48282]988 return S_OK;
989#endif
[36991]990}
991
[52232]992HRESULT Session::accessGuestProperty(const com::Utf8Str &aName, const com::Utf8Str &aValue, const com::Utf8Str &aFlags,
[52251]993 ULONG aAccessMode, com::Utf8Str &aRetValue, LONG64 *aRetTimestamp, com::Utf8Str &aRetFlags)
[10233]994{
[48299]995#ifdef VBOX_WITH_GUEST_PROPS
996# ifndef VBOX_COM_INPROC_API_CLIENT
[31008]997 if (mState != SessionState_Locked)
[26186]998 return setError(VBOX_E_INVALID_VM_STATE,
[31008]999 tr("Machine is not locked by session (session state: %s)."),
[26186]1000 Global::stringifySessionState(mState));
[31019]1001 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[52232]1002 if (aName.isEmpty())
1003 return E_INVALIDARG;
[52251]1004 if (aAccessMode == 0 && !RT_VALID_PTR(aRetTimestamp))
[11083]1005 return E_POINTER;
[42382]1006
1007 /* If this session is not in a VM process fend off the call. The caller
1008 * handles this correctly, by doing the operation in VBoxSVC. */
1009 if (!mConsole)
1010 return E_ACCESSDENIED;
1011
[52251]1012 HRESULT hr;
1013 if (aAccessMode == 2)
1014 hr = mConsole->i_deleteGuestProperty(aName);
1015 else if (aAccessMode == 1)
1016 hr = mConsole->i_setGuestProperty(aName, aValue, aFlags);
1017 else if (aAccessMode == 0)
1018 hr = mConsole->i_getGuestProperty(aName, &aRetValue, aRetTimestamp, &aRetFlags);
[10233]1019 else
[52251]1020 hr = E_INVALIDARG;
[48299]1021
[52251]1022 return hr;
[48299]1023# else /* VBOX_COM_INPROC_API_CLIENT */
1024 /** @todo This is nonsense, non-VM API users shouldn't need to deal with this
1025 * method call, VBoxSVC should be clever enough to see that the
1026 * session doesn't have a console! */
[63258]1027 RT_NOREF(aName, aValue, aFlags, aAccessMode, aRetValue, aRetTimestamp, aRetFlags);
[48299]1028 return E_ACCESSDENIED;
1029# endif /* VBOX_COM_INPROC_API_CLIENT */
1030
1031#else /* VBOX_WITH_GUEST_PROPS */
[14715]1032 ReturnComNotImplemented();
[48299]1033#endif /* VBOX_WITH_GUEST_PROPS */
[10233]1034}
1035
[52232]1036HRESULT Session::enumerateGuestProperties(const com::Utf8Str &aPatterns,
1037 std::vector<com::Utf8Str> &aKeys,
1038 std::vector<com::Utf8Str> &aValues,
1039 std::vector<LONG64> &aTimestamps,
1040 std::vector<com::Utf8Str> &aFlags)
[11041]1041{
[48282]1042#if defined(VBOX_WITH_GUEST_PROPS) && !defined(VBOX_COM_INPROC_API_CLIENT)
[31008]1043 if (mState != SessionState_Locked)
[26186]1044 return setError(VBOX_E_INVALID_VM_STATE,
[31008]1045 tr("Machine is not locked by session (session state: %s)."),
[26186]1046 Global::stringifySessionState(mState));
[31019]1047 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[42382]1048
1049 /* If this session is not in a VM process fend off the call. The caller
1050 * handles this correctly, by doing the operation in VBoxSVC. */
1051 if (!mConsole)
1052 return E_ACCESSDENIED;
1053
[52252]1054 return mConsole->i_enumerateGuestProperties(aPatterns, aKeys, aValues, aTimestamps, aFlags);
[52232]1055
[11041]1056#else /* VBOX_WITH_GUEST_PROPS not defined */
[63258]1057 RT_NOREF(aPatterns, aKeys, aValues, aTimestamps, aFlags);
[14715]1058 ReturnComNotImplemented();
[11041]1059#endif /* VBOX_WITH_GUEST_PROPS not defined */
1060}
1061
[52232]1062HRESULT Session::onlineMergeMedium(const ComPtr<IMediumAttachment> &aMediumAttachment, ULONG aSourceIdx,
1063 ULONG aTargetIdx, const ComPtr<IProgress> &aProgress)
[28835]1064{
[31008]1065 if (mState != SessionState_Locked)
[28835]1066 return setError(VBOX_E_INVALID_VM_STATE,
[31008]1067 tr("Machine is not locked by session (session state: %s)."),
[28835]1068 Global::stringifySessionState(mState));
[48282]1069#ifndef VBOX_COM_INPROC_API_CLIENT
[31019]1070 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[42382]1071 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[28835]1072
[51612]1073 return mConsole->i_onlineMergeMedium(aMediumAttachment,
1074 aSourceIdx, aTargetIdx,
1075 aProgress);
[48282]1076#else
[63258]1077 RT_NOREF(aMediumAttachment, aSourceIdx, aTargetIdx, aProgress);
[48299]1078 AssertFailed();
[48282]1079 return E_NOTIMPL;
1080#endif
[28835]1081}
1082
[55214]1083HRESULT Session::reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments)
1084{
1085 if (mState != SessionState_Locked)
1086 return setError(VBOX_E_INVALID_VM_STATE,
1087 tr("Machine is not locked by session (session state: %s)."),
1088 Global::stringifySessionState(mState));
1089#ifndef VBOX_COM_INPROC_API_CLIENT
1090 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
1091 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
1092
1093 return mConsole->i_reconfigureMediumAttachments(aAttachments);
1094#else
[63258]1095 RT_NOREF(aAttachments);
[55214]1096 AssertFailed();
1097 return E_NOTIMPL;
1098#endif
1099}
1100
[52232]1101HRESULT Session::enableVMMStatistics(BOOL aEnable)
[40084]1102{
[40748]1103 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1104 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
1105 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]1106#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]1107 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
[40748]1108
[51612]1109 mConsole->i_enableVMMStatistics(aEnable);
[40177]1110
1111 return S_OK;
[48282]1112#else
[63258]1113 RT_NOREF(aEnable);
[48299]1114 AssertFailed();
[48282]1115 return E_NOTIMPL;
1116#endif
[40084]1117}
1118
[52232]1119HRESULT Session::pauseWithReason(Reason_T aReason)
[46775]1120{
1121 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1122 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
1123 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]1124#ifndef VBOX_COM_INPROC_API_CLIENT
[46775]1125 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
1126
[51612]1127 return mConsole->i_pause(aReason);
[48282]1128#else
[63258]1129 RT_NOREF(aReason);
[48299]1130 AssertFailed();
[48282]1131 return E_NOTIMPL;
1132#endif
[46775]1133}
1134
[52232]1135HRESULT Session::resumeWithReason(Reason_T aReason)
[46775]1136{
1137 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1138 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
1139 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]1140#ifndef VBOX_COM_INPROC_API_CLIENT
[46775]1141 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
1142
[55214]1143 AutoWriteLock dummyLock(mConsole COMMA_LOCKVAL_SRC_POS);
1144 return mConsole->i_resume(aReason, dummyLock);
[48282]1145#else
[63258]1146 RT_NOREF(aReason);
[48299]1147 AssertFailed();
[48282]1148 return E_NOTIMPL;
1149#endif
[46775]1150}
1151
[68986]1152HRESULT Session::saveStateWithReason(Reason_T aReason,
1153 const ComPtr<IProgress> &aProgress,
1154 const ComPtr<ISnapshot> &aSnapshot,
1155 const Utf8Str &aStateFilePath,
[63258]1156 BOOL aPauseVM, BOOL *aLeftPaused)
[46775]1157{
1158 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1159 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
1160 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
[48282]1161#ifndef VBOX_COM_INPROC_API_CLIENT
[46775]1162 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
1163
[55214]1164 bool fLeftPaused = false;
[94949]1165 HRESULT hrc = mConsole->i_saveState(aReason, aProgress, aSnapshot, aStateFilePath, !!aPauseVM, fLeftPaused);
[55214]1166 if (aLeftPaused)
1167 *aLeftPaused = fLeftPaused;
[94949]1168 return hrc;
[48282]1169#else
[68986]1170 RT_NOREF(aReason, aProgress, aSnapshot, aStateFilePath, aPauseVM, aLeftPaused);
[48299]1171 AssertFailed();
[48282]1172 return E_NOTIMPL;
1173#endif
[46775]1174}
1175
[55214]1176HRESULT Session::cancelSaveStateWithReason()
1177{
1178 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1179 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
1180 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
1181#ifndef VBOX_COM_INPROC_API_CLIENT
1182 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
1183
1184 return mConsole->i_cancelSaveState();
1185#else
1186 AssertFailed();
1187 return E_NOTIMPL;
1188#endif
1189}
1190
[1]1191// private methods
1192///////////////////////////////////////////////////////////////////////////////
1193
1194/**
[31070]1195 * Unlocks a machine associated with the current session.
[1]1196 *
1197 * @param aFinalRelease called as a result of FinalRelease()
1198 * @param aFromServer called as a result of Uninitialize()
[65103]1199 * @param aLockW The write lock this object is protected with.
[56448]1200 * Must be acquired already and will be released
1201 * and later reacquired during the unlocking.
[1]1202 *
[66217]1203 * @note To be called only from #uninit(), ISession::UnlockMachine() or
1204 * ISession::Uninitialize().
[1]1205 */
[56450]1206HRESULT Session::i_unlockMachine(bool aFinalRelease, bool aFromServer, AutoWriteLock &aLockW)
[1]1207{
1208 LogFlowThisFuncEnter();
[21878]1209 LogFlowThisFunc(("aFinalRelease=%d, isFromServer=%d\n",
[1]1210 aFinalRelease, aFromServer));
1211
[93410]1212 LogFlowThisFunc(("mState=%s, mType=%d\n", ::stringifySessionState(mState), mType));
[1]1213
[56450]1214 Assert(aLockW.isWriteLockOnCurrentThread());
[56448]1215
[31008]1216 if (mState != SessionState_Locked)
[1]1217 {
[26186]1218 Assert(mState == SessionState_Spawning);
[1]1219
[13431]1220 /* The session object is going to be uninitialized before it has been
1221 * assigned a direct console of the machine the client requested to open
1222 * a remote session to using IVirtualBox:: openRemoteSession(). It is OK
[33540]1223 * only if this close request comes from the server (for example, it
[13431]1224 * detected that the VM process it started terminated before opening a
1225 * direct session). Otherwise, it means that the client is too fast and
1226 * trying to close the session before waiting for the progress object it
1227 * got from IVirtualBox:: openRemoteSession() to complete, so assert. */
[26186]1228 Assert(aFromServer);
[1]1229
[31008]1230 mState = SessionState_Unlocked;
[7207]1231 mType = SessionType_Null;
[47561]1232
1233 Assert(!mClientTokenHolder);
1234
[1]1235 LogFlowThisFuncLeave();
1236 return S_OK;
1237 }
1238
1239 /* go to the closing state */
[31008]1240 mState = SessionState_Unlocking;
[1]1241
[31019]1242 if (mType == SessionType_WriteLock)
[1]1243 {
[48282]1244#ifndef VBOX_COM_INPROC_API_CLIENT
[42382]1245 if (!mConsole.isNull())
1246 {
1247 mConsole->uninit();
1248 mConsole.setNull();
1249 }
[48299]1250#else
1251 mRemoteMachine.setNull();
[48282]1252#endif
[1]1253 }
1254 else
1255 {
1256 mRemoteMachine.setNull();
1257 mRemoteConsole.setNull();
1258 }
1259
[21878]1260 ComPtr<IProgress> progress;
[1]1261
1262 if (!aFinalRelease && !aFromServer)
1263 {
1264 /*
1265 * We trigger OnSessionEnd() only when the session closes itself using
1266 * Close(). Note that if isFinalRelease = TRUE here, this means that
1267 * the client process has already initialized the termination procedure
1268 * without issuing Close() and the IPC channel is no more operational --
1269 * so we cannot call the server's method (it will definitely fail). The
1270 * server will instead simply detect the abnormal client death (since
1271 * OnSessionEnd() is not called) and reset the machine state to Aborted.
1272 */
1273
1274 /*
1275 * while waiting for OnSessionEnd() to complete one of our methods
1276 * can be called by the server (for example, Uninitialize(), if the
1277 * direct session has initiated a closure just a bit before us) so
1278 * we need to release the lock to avoid deadlocks. The state is already
[7207]1279 * SessionState_Closing here, so it's safe.
[1]1280 */
[56450]1281 aLockW.release();
[1]1282
[56450]1283 Assert(!aLockW.isWriteLockOnCurrentThread());
[56449]1284
[21878]1285 LogFlowThisFunc(("Calling mControl->OnSessionEnd()...\n"));
[94949]1286 HRESULT hrc = mControl->OnSessionEnd(this, progress.asOutParam());
1287 LogFlowThisFunc(("mControl->OnSessionEnd()=%08X\n", hrc));
[1]1288
[56450]1289 aLockW.acquire();
[1]1290
1291 /*
1292 * If we get E_UNEXPECTED this means that the direct session has already
1293 * been closed, we're just too late with our notification and nothing more
[30134]1294 *
1295 * bird: Seems E_ACCESSDENIED is what gets returned these days; see
[59996]1296 * ObjectState::addCaller.
[1]1297 */
[94949]1298 if (mType != SessionType_WriteLock && (hrc == E_UNEXPECTED || hrc == E_ACCESSDENIED))
1299 hrc = S_OK;
[1]1300
[57326]1301#if !defined(DEBUG_bird) && !defined(DEBUG_andy) /* I don't want clients crashing on me just because VBoxSVC went belly up. */
[94949]1302 AssertComRC(hrc);
[31244]1303#endif
[1]1304 }
1305
1306 mControl.setNull();
1307
[31019]1308 if (mType == SessionType_WriteLock)
[1]1309 {
[47561]1310 if (mClientTokenHolder)
1311 {
1312 delete mClientTokenHolder;
1313 mClientTokenHolder = NULL;
1314 }
1315
[1]1316 if (!aFinalRelease && !aFromServer)
1317 {
1318 /*
1319 * Wait for the server to grab the semaphore and destroy the session
1320 * machine (allowing us to open a new session with the same machine
1321 * once this method returns)
1322 */
[26186]1323 Assert(!!progress);
[1]1324 if (progress)
[26186]1325 progress->WaitForCompletion(-1);
[1]1326 }
1327 }
1328
[31008]1329 mState = SessionState_Unlocked;
[7207]1330 mType = SessionType_Null;
[1]1331
1332 /* release the VirtualBox instance as the very last step */
1333 mVirtualBox.setNull();
1334
1335 LogFlowThisFuncLeave();
1336 return S_OK;
1337}
1338
[14772]1339/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use