VirtualBox

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

Last change on this file since 73768 was 68986, checked in by vboxsync, 7 years ago

VMM: Add new QueryGenericObject entry to VMM2USER callback table, for querying API objects by UUID.
PDM: Add new QueryGenericUserObject entry to trusted DevHlp callback table, for querying API objects by UUID from PDM devices.
Main/Session+Console+Machine+Snapshot: Implement this callback and provide the console and snapshot objects this way.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use