ConsoleImpl.cpp revision 7413b370d1af0fbac98c8ba74551c32e715b3af7
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * VBox Console COM Class implementation
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2010 Oracle Corporation
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * available from http://www.virtualbox.org. This file is free software;
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * you can redistribute it and/or modify it under the terms of the GNU
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * General Public License (GPL) as published by the Free Software
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync/** @todo Move the TAP mess back into the driver! */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync// generated header
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync// VMTask and friends
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync////////////////////////////////////////////////////////////////////////////////
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Task structure for asynchronous VM operations.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Once created, the task structure adds itself as a Console caller. This means:
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * 1. The user must check for #rc() before using the created structure
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * (e.g. passing it as a thread function argument). If #rc() returns a
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * failure, the Console object may not be used by the task (see
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Console::addCaller() for more details).
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * 2. On successful initialization, the structure keeps the Console caller
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * until destruction (to ensure Console remains in the Ready state and won't
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * be accidentally uninitialized). Forgetting to delete the created task
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * will lead to Console::uninit() stuck waiting for releasing all added
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * If \a aUsesVMPtr parameter is true, the task structure will also add itself
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * as a Console::mpVM caller with the same meaning as above. See
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Console::addVMCaller() for more info.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Releases the VM caller before destruction. Not normally necessary. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync : VMProgressTask(aConsole, aProgress, false /* aUsesVMPtr */),
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync Bstr bstrSavedStateFile; // received from BeginTakeSnapshot()
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync : VMProgressTask(aConsole, aProgress, false /* aUsesVMPtr */),
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* array of progress objects for hard disk reset operations */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync typedef std::list< ComPtr<IProgress> > ProgressList;
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync : VMProgressTask(aConsole, aProgress, true /* aUsesVMPtr */),
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync// ConsoleCallbackRegistration
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync////////////////////////////////////////////////////////////////////////////////
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Registered IConsoleCallback, used by Console::CallbackList and
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Console::mCallbacks.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * In addition to keeping the interface pointer this also keeps track of the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * methods that asked to not be called again. The latter is for reducing
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * unnecessary IPC.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Bitmap of disabled callback methods, that is methods that has return
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * VBOX_E_DONT_CALL_AGAIN. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Callback bit indexes (for bmDisabled). */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync typedef enum
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync ConsoleCallbackRegistration(IConsoleCallback *pIConsoleCallback)
280173a9a1d01b33c087a762ffb9e522efe5c0d5vboxsync /* nothing */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* nothing */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /** Equal operator for std::find. */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync bool operator==(const ConsoleCallbackRegistration &rThat) const
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Checks if the callback is wanted, i.e. if the method hasn't yet returned
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * VBOX_E_DONT_CALL_AGAIN.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns @c true if it is wanted, @c false if not.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param enmBit The callback, be sure to get this one right!
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Called in response to VBOX_E_DONT_CALL_AGAIN.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param enmBit The callback, be sure to get this one right!
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Handle a callback return code, picking up VBOX_E_DONT_CALL_AGAIN.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @returns hrc or S_OK if VBOX_E_DONT_CALL_AGAIN.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param enmBit The callback, be sure to get this one right!
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param hrc The status code returned by the callback.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync inline HRESULT handleResult(CallbackBit enmBit, HRESULT hrc)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_ARGS5(a1,a2,a3,a4,a5) a1, a2, a3, a4, a5
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_ARGS6(a1,a2,a3,a4,a5,a6) a1, a2, a3, a4, a5, a6
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_ARGS7(a1,a2,a3,a4,a5,a6,a7) a1, a2, a3, a4, a5, a6, a7
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_ARGS8(a1,a2,a3,a4,a5,a6,a7,a8) a1, a2, a3, a4, a5, a6, a7, a8
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Macro used to prepare for COM event firing, note CComObjectRootEx locking.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Actual event firing for all connection points.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Note some subtlety in the fact that connection point list access
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * must be synchronized with CComObjectRootEx Lock()/Unlock() methods.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync for (int i=0; i<nConnections; i++) \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync this->mComEvHelper.fire(cbD, evDesc, &varResult); \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * A bit non-trivial part about those macros is that we rely heavily on C++ type
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * casting and assignment operator overloading in CComVariant when instantiating
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * member template add(), and every add() here could be, ofc, different function.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_COM_ARGS1(a1) if (nConnections) evDesc.add(a1)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_COM_ARGS2(a1,a2) if (nConnections) evDesc.add(a1).add(a2)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_COM_ARGS3(a1,a2,a3) if (nConnections) evDesc.add(a1).add(a2).add(a3)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_COM_ARGS4(a1,a2,a3,a4) if (nConnections) evDesc.add(a1).add(a2).add(a3).add(a4)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_COM_ARGS5(a1,a2,a3,a4,a5) if (nConnections) evDesc.add(a1).add(a2).add(a3).add(a4).add(a5)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_COM_ARGS6(a1,a2,a3,a4,a5,a6) if (nConnections) evDesc.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_COM_ARGS7(a1,a2,a3,a4,a5,a6,a7) if (nConnections) evDesc.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define PREP_COM_ARGS8(a1,a2,a3,a4,a5,a6,a7,a8) if (nConnections) evDesc.add(a1).add(a2).add(a3).add(a4).add(a5).add(a6).add(a7).add(a8)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * No COM events for XPCOM targets ofc.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Macro for iterating the callback list (Console::mCallbacks) and invoking the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * given method on each entry, along with firing appropriate COM events on Windows.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * This handles VBOX_E_DONT_CALL_AGAIN as well as removing dead interfaces
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * which. This makes the code a big and clunky, thus this macro. It may make
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * debugging and selective logging a bit of a pain, but duplicating this code
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * some seventeen times is much more of a pain.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * The caller must hold the console object lock - read or write, we don't care.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * The caller must be a Console method - the console members accessible thru the
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * 'this' pointer.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param CallbackMethod The callback method, like OnKeyboardLedsChange.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param InvokeCb Callbacks invocation code
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param PreprEvent Event preparation code
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * @param Args Number of callback arguments
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define CONSOLE_DO_CALLBACKS_GEN(CallbackMethod, Argc, Args, PrepComArgs, MaybeComma) \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync evDesc.init(mEventSource, VBoxEventType_##CallbackMethod MaybeComma Args); \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync CallbackList::iterator it = this->mCallbacks.begin(); \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync if (it->isWanted(ConsoleCallbackRegistration::k ## CallbackMethod)) \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync HRESULT hrc = it->ptrICb-> CallbackMethod (Args); \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync hrc = it->handleResult(ConsoleCallbackRegistration::k ## CallbackMethod, hrc); \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync continue; \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync } while (0)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync/* Actual invocation macroses for different number of parameters */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync CONSOLE_DO_CALLBACKS_GEN(CallbackMethod, 0, PREP_ARGS0(), PREP_COM_ARGS0(), NO_COMMA)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define CONSOLE_DO_CALLBACKS1(CallbackMethod,Arg1) \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync CONSOLE_DO_CALLBACKS_GEN(CallbackMethod, 1, PREP_ARGS1(Arg1), PREP_COM_ARGS1(Arg1), COMMA)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define CONSOLE_DO_CALLBACKS2(CallbackMethod,Arg1,Arg2) \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync CONSOLE_DO_CALLBACKS_GEN(CallbackMethod, 2, PREP_ARGS2(Arg1,Arg2),PREP_COM_ARGS2(Arg1,Arg2), COMMA)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define CONSOLE_DO_CALLBACKS3(CallbackMethod,Arg1,Arg2,Arg3) \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync CONSOLE_DO_CALLBACKS_GEN(CallbackMethod, 3, PREP_ARGS3(Arg1,Arg2,Arg3), PREP_COM_ARGS3(Arg1,Arg2,Arg3), COMMA)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define CONSOLE_DO_CALLBACKS4(CallbackMethod,Arg1,Arg2,Arg3,Arg4) \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync CONSOLE_DO_CALLBACKS_GEN(CallbackMethod, 4, PREP_ARGS4(Arg1,Arg2,Arg3,Arg4), PREP_COM_ARGS4(Arg1,Arg2,Arg3,Arg4), COMMA)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define CONSOLE_DO_CALLBACKS7(CallbackMethod,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7) \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync CONSOLE_DO_CALLBACKS_GEN(CallbackMethod, 7, PREP_ARGS7(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7), PREP_COM_ARGS7(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7), COMMA)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync#define CONSOLE_DO_CALLBACKS8(CallbackMethod,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7,Arg8) \
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync CONSOLE_DO_CALLBACKS_GEN(CallbackMethod, 8, PREP_ARGS8(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7,Arg8), PREP_COM_ARGS8(Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7, Arg8), COMMA)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync// constructor / destructor
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync/////////////////////////////////////////////////////////////////////////////
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync for (ULONG slot = 0; slot < SchemaDefs::NetworkAdapterCount; ++slot)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync meAttachmentType[slot] = NetworkAttachmentType_Null;
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync memset(&mapSharedFolderLed, 0, sizeof(mapSharedFolderLed));
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync for (unsigned i = 0; i < RT_ELEMENTS(maStorageDevType); ++ i)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync// public initializer/uninitializer for internal purposes only
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync/////////////////////////////////////////////////////////////////////////////
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsyncHRESULT Console::init(IMachine *aMachine, IInternalMachineControl *aControl)
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* Enclose the state transition NotReady->InInit->Ready */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync LogFlowThisFunc(("aMachine=%p, aControl=%p\n", aMachine, aControl));
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* Cache essential properties and objects */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rc = mMachine->COMGETTER(VRDPServer)(unconst(mVRDPServer).asOutParam());
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* Create associated child COM objects */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync // Event source may be needed by other children
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync rc = mEventSource->init(static_cast<IConsole*>(this));
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* Grab global and machine shared folder lists */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* Create other child objects */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync unconst(mConsoleVRDPServer) = new ConsoleVRDPServer(this);
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* Confirm a successful initialization when it's the case */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Uninitializes the Console object.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* Enclose the state transition Ready->InUninit->NotReady */
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync LogFlowThisFunc(("initFailed()=%d\n", autoUninitSpan.initFailed()));
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * Uninit all children that use addDependentChild()/removeDependentChild()
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync * in their init()/uninit() methods.
8c48cf39dfb84c1f26e0e7fbd1c407e25a34eef1vboxsync /* power down the VM if necessary */
if (mDisplay)
if (mMouse)
if (mKeyboard)
if (mGuest)
if (mConsoleVRDPServer)
delete mConsoleVRDPServer;
#ifdef VBOX_WITH_VRDP
#ifdef VBOX_WITH_GUEST_PROPS
HRESULT hrc = mMachine->GetExtraData(Bstr("VBoxInternal2/EnableGuestPropertiesVRDP"), value.asOutParam());
void Console::updateGuestPropertiesVRDPLogon(uint32_t u32ClientId, const char *pszUser, const char *pszDomain)
if (!enabledGuestPropertiesVRDP())
int rc;
char *pszPropertyName;
char *pszClientId;
mMachine->SetGuestProperty(Bstr("/VirtualBox/HostInfo/VRDP/LastConnectedClient"), Bstr(pszClientId), Bstr("RDONLYGUEST"));
if (!enabledGuestPropertiesVRDP())
int rc;
char *pszPropertyName;
char *pszClientId;
mMachine->SetGuestProperty(Bstr("/VirtualBox/HostInfo/VRDP/LastDisconnectedClient"), Bstr(pszClientId), bstrReadOnlyGuest);
int Console::VRDPClientLogon(uint32_t u32ClientId, const char *pszUser, const char *pszPassword, const char *pszDomain)
return VERR_ACCESS_DENIED;
switch (authType)
case VRDPAuthType_Null:
case VRDPAuthType_External:
result = mConsoleVRDPServer->Authenticate(uuid, guestJudgement, pszUser, pszPassword, pszDomain, u32ClientId);
case VRDPAuthType_Guest:
if (mVMMDev)
switch (u32GuestFlags & (VMMDEV_CREDENTIALS_JUDGE_OK | VMMDEV_CREDENTIALS_JUDGE_DENY | VMMDEV_CREDENTIALS_JUDGE_NOJUDGEMENT))
result = mConsoleVRDPServer->Authenticate(uuid, guestJudgement, pszUser, pszPassword, pszDomain, u32ClientId);
switch (guestJudgement)
AssertFailed();
return VERR_ACCESS_DENIED;
/* Multiconnection check must be made after authentication, so bad clients would not interfere with a good one. */
LogFlowFunc(("allowMultiConnection %d, reuseSingleConnection = %d, mcVRDPClients = %d, mu32SingleRDPClientId = %d\n", allowMultiConnection, reuseSingleConnection, mcVRDPClients, mu32SingleRDPClientId));
/* Note: the 'mcVRDPClients' variable is incremented in ClientConnect callback, which is called when the client
if (mcVRDPClients != 0)
return VERR_ACCESS_DENIED;
#ifdef VBOX_WITH_GUEST_PROPS
&& mVMMDev)
return VINF_SUCCESS;
#ifdef VBOX_WITH_VRDP
#ifdef VBOX_WITH_VRDP
if (u32Clients == 0)
#ifdef VBOX_WITH_VRDP
mcAudioRefs--;
if (mcAudioRefs <= 0)
if (mAudioSniffer)
if (port)
#ifdef VBOX_WITH_GUEST_PROPS
#ifdef VBOX_WITH_VRDP
++mcAudioRefs;
if (mAudioSniffer)
if (port)
#ifdef VBOX_WITH_VRDP
return S_OK;
return rc;
mSavedStateDataLoaded = true;
return rc;
DECLCALLBACK(void)
++ it)
DECLCALLBACK(int)
return VERR_VERSION_MISMATCH;
bool writable = true;
delete[] buf;
delete[] buf;
return VINF_SUCCESS;
#ifdef VBOX_WITH_GUEST_PROPS
void *pvParms,
using namespace guestProp;
int rc;
flags);
LogFunc(("Console::doGuestPropNotification: hrc=%Rhrc pCBData={.pcszName=%s, .pcszValue=%s, .pcszFlags=%s}\n",
return rc;
using namespace guestProp;
// parm[0].u.pointer.size = (uint32_t)utf8Patterns.length() + 1;
// parm[0].u.pointer.size = 1;
return E_OUTOFMEMORY;
&parm[0]);
const char *pszBuf
unsigned cEntries = 0;
++cEntries;
for (unsigned i = 0; i < cEntries; ++i)
return S_OK;
return E_FAIL;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return S_OK;
if (!mDebugger)
return S_OK;
return S_OK;
STDMETHODIMP Console::COMGETTER(RemoteUSBDevices)(ComSafeArrayOut(IHostUSBDevice *, aRemoteUSBDevices))
return S_OK;
return S_OK;
return S_OK;
return S_OK;
return E_POINTER;
switch (mMachineState)
case MachineState_Running:
case MachineState_Paused:
case MachineState_Stuck:
case MachineState_Teleporting:
case MachineState_Saved:
case MachineState_Stopping:
return S_OK;
return setInvalidMachineStateError();
vrc);
return rc;
return vrc;
return setInvalidMachineStateError();
if (!fCpuAttached)
bool fLocked = true;
vrc = getVMMDev()->getVMMDevPort()->pfnCpuHotUnplug(getVMMDev()->getVMMDevPort(), idCpuCore, idCpuPackage);
} while (cTries-- > 0);
this, aCpu);
return rc;
return VINF_SUCCESS;
return setInvalidMachineStateError();
if (fCpuAttached)
this, aCpu);
vrc);
vrc = getVMMDev()->getVMMDevPort()->pfnCpuHotPlug(getVMMDev()->getVMMDevPort(), idCpuCore, idCpuPackage);
return rc;
switch (mMachineState)
case MachineState_Running:
case MachineState_Teleporting:
case MachineState_Paused:
case MachineState_Saving:
return setInvalidMachineStateError();
return hrc;
int vrc;
vrc);
return rc;
return setInvalidMachineStateError();
vrc);
return rc;
return setInvalidMachineStateError();
bool handled = false;
vrc);
return rc;
bool entered = false;
return S_OK;
return setInvalidMachineStateError();
vrc);
return rc;
bool fBeganSavingState = false;
bool fTaskCreationFailed = false;
fTaskCreationFailed = true;
fBeganSavingState = true;
if (fBeganSavingState)
Resume();
return rc;
tr("Cannot adopt the saved machine state as the machine is not in Powered Off, Teleported or Aborted state (machine state: %s)"),
return rc;
if (!pLed)
return u32;
switch (aDeviceType)
case DeviceType_Floppy:
case DeviceType_DVD:
case DeviceType_HardDisk:
case DeviceType_Network:
case DeviceType_USB:
case DeviceType_SharedFolder:
case PDMLED_READING:
case PDMLED_WRITING:
return S_OK;
#ifdef VBOX_WITH_USB
return rc;
#ifdef VBOX_WITH_USB
++ it;
if (!device)
return rc2;
return rc;
#ifdef VBOX_WITH_USB
aAddress);
return E_NOTIMPL;
#ifdef VBOX_WITH_USB
return E_NOTIMPL;
tr("Cannot create a transient shared folder on the machine while it is changing the state (machine state: %s)"),
aName);
return rc;
tr("Cannot remove a transient shared folder from the machine while it is changing the state (machine state: %s)"),
return rc;
return rc;
for (size_t i = 0;
return rc;
++cOperations;
// b) one extra sub-operations for online snapshots OR offline snapshots that have a saved state (needs to be copied)
bool fTakingSnapshotOnline = ((mMachineState == MachineState_Running) || (mMachineState == MachineState_Paused));
LogFlowFunc(("fTakingSnapshotOnline = %d, mMachineState = %d\n", fTakingSnapshotOnline, mMachineState));
++cOperations;
return rc;
return E_OUTOFMEMORY;
(void*)pTask,
vrc);
delete pTask;
return rc;
return S_OK;
return S_OK;
void *pvCallback;
return S_OK;
return S_OK;
return rc;
return setError(E_FAIL, tr("Could not load the external authentication library '%s' (%Rrc)"), filename, rc);
AssertFailed();
return E_FAIL;
switch (enmCtrlType)
return NULL;
HRESULT Console::convertBusPortDeviceToLun(StorageBus_T enmBus, LONG port, LONG device, unsigned &uLun)
switch (enmBus)
case StorageBus_IDE:
case StorageBus_Floppy:
return S_OK;
case StorageBus_SATA:
case StorageBus_SCSI:
case StorageBus_SAS:
return S_OK;
uLun = 0;
if (pMedium)
&pReq,
fForce);
return S_OK;
if (!pMedium)
vrc);
const char *pcszDevice,
unsigned uInstance,
bool fUseHostIOCache,
bool fForce)
bool fResume;
switch (enmVMState)
case VMSTATE_RESETTING:
case VMSTATE_RUNNING:
fResume = true;
case VMSTATE_SUSPENDED:
case VMSTATE_CREATED:
case VMSTATE_OFF:
fResume = false;
case VMSTATE_RUNNING_LS:
pVM,
if (fResume)
return rcRet;
if (mpVM)
switch (adapterType)
#ifdef VBOX_WITH_E1000
#ifdef VBOX_WITH_VIRTIO
AssertFailed();
if (pINetCfg)
#ifdef VBOX_DYNAMIC_NET_ATTACH
if ( enmVMState == VMSTATE_RUNNING /** @todo LiveMigration: Forbid or deal correctly with the _LS variants */
return rc;
#ifdef VBOX_DYNAMIC_NET_ATTACH
unsigned uInstance,
unsigned uLun,
return S_OK;
vrc);
const char *pszDevice,
unsigned uInstance,
unsigned uLun,
&& (uLun == 0)
bool fResume;
switch (enmVMState)
case VMSTATE_RESETTING:
case VMSTATE_RUNNING:
fResume = true;
case VMSTATE_SUSPENDED:
case VMSTATE_CREATED:
case VMSTATE_OFF:
fResume = false;
rcRet = pThis->configNetwork(pszDevice, uInstance, uLun, aNetworkAdapter, pCfg, pLunL0, pInst, true);
if (fResume)
return rcRet;
if (mpVM)
return rc;
if (mpVM)
return rc;
if (mpVM)
return rc;
if (mpVM)
return rc;
if (mpVM)
if (aRemove)
return rc;
if ( mVRDPServer
if (aRestart)
if (vrdpEnabled)
return rc;
if (mpVM)
return rc;
if (aGlobal)
return rc;
HRESULT Console::onUSBDeviceAttach(IUSBDevice *aDevice, IVirtualBoxErrorInfo *aError, ULONG aMaskedIfs)
#ifdef VBOX_WITH_USB
return S_OK;
return E_FAIL;
return rc;
return E_FAIL;
#ifdef VBOX_WITH_USB
++ it;
return S_OK;
return rc;
return E_FAIL;
#ifndef VBOX_WITH_GUEST_PROPS
return E_INVALIDARG;
return E_POINTER;
return E_POINTER;
return E_POINTER;
using namespace guestProp;
vrc);
return rc;
#ifndef VBOX_WITH_GUEST_PROPS
return E_INVALIDARG;
return E_INVALIDARG;
return E_INVALIDARG;
using namespace guestProp;
vrc);
return rc;
#ifndef VBOX_WITH_GUEST_PROPS
return E_POINTER;
return E_POINTER;
return E_POINTER;
return E_POINTER;
return E_POINTER;
if (pProgress)
switch (mMachineState)
return setInvalidMachineStateError();
if (pMedium)
unsigned uLUN;
mVMStateChangeCallbackDisabled = true;
mVMStateChangeCallbackDisabled = false;
pVM,
&rc);
mVMStateChangeCallbackDisabled = true;
mVMStateChangeCallbackDisabled = false;
return rc;
if (pIBase)
if (!pIMedium)
mVMStateChangeCallbackDisabled = true;
mVMStateChangeCallbackDisabled = false;
pVM,
&rc);
mVMStateChangeCallbackDisabled = true;
mVMStateChangeCallbackDisabled = false;
return rc;
return rc;
, E_FAIL);
#ifdef RT_OS_WINDOWS
CONSOLE_DO_CALLBACKS7(OnMousePointerShapeChange, fVisible, fAlpha, xHot, yHot, width, height, pShape);
CONSOLE_DO_CALLBACKS8(OnMousePointerShapeChange, fVisible, fAlpha, xHot, yHot, width, height, pShapeSize, pShape);
void Console::onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelative, BOOL needsHostCursor)
CONSOLE_DO_CALLBACKS3(OnMouseCapabilityChange, supportsAbsolute, supportsRelative, needsHostCursor);
*aWinId = 0;
if (aCheck)
return hrc;
++it;
if (fDelivered)
if (aCanShowEvent)
return hrc;
if (*aWinId == 0)
++it;
if (fDelivered)
if (aShowEvent)
return S_OK;
if (mVMDestroying)
++ mVMCallers;
return S_OK;
--mVMCallers;
if (cHistoryFiles)
#ifdef VBOX_BLEEDING_EDGE
RTLogRelLogger(loggerRelease, 0, ~0U, "Maximum user application address: 0x%p\n", sysInfo.lpMaximumApplicationAddress);
#ifdef VBOX_OSE
RTProcSelf(),
return hrc;
return E_POINTER;
++slot)
if (!enabled)
switch (netattach)
#ifdef RT_OS_WINDOWS
if (!hostif)
tr("VM cannot start because the saved state file '%ls' is invalid (%Rrc). Delete the saved state prior to starting the VM"),
#if 0 /** @todo we should save it afterwards, but that isn't necessarily a good idea. Find a better place for this (VBoxSVC). */
if (fTeleporterEnabled)
else if (fTeleporterEnabled)
NULL);
return rc;
return rc;
return rc;
if (fCanceled)
if (pCurrentSnapshot)
if (!fCurrentSnapshotIsOnline)
for (size_t i = 0;
if (autoReset)
LogFlowThisFunc(("Machine has a current snapshot which is online, skipping immutable images reset\n"));
if (aProgress)
else if (fTeleporterEnabled)
return S_OK;
LogRel(("Console::powerDown(): A request to power off the VM has been issued (mMachineState=%s, InUninit=%d)\n",
if ( !mVMPoweredOff
mVMPoweredOff = true;
if (mConsoleVRDPServer)
if (aProgress)
mVMDestroying = true;
if (mVMCallers > 0)
mVMCallers));
if (aProgress)
if (!mVMPoweredOff)
mVMPoweredOff = false;
if (aProgress)
#ifdef VBOX_WITH_HGCM
if (mVMMDev)
if (aProgress)
bool fHasUSBController = false;
fHasUSBController = true;
if (aProgress)
vrc);
if (fHasUSBController)
if (aProgress)
vrc);
mVMDestroying = false;
if (aProgress)
return rc;
Global::stringifyMachineState(mMachineState), Global::stringifyMachineState(aMachineState), aUpdateServer));
if (aUpdateServer)
return rc;
return S_OK;
if (aSetError)
aName);
return VBOX_E_FILE_ERROR;
if (aGlobal)
if (online)
if (online)
if (online)
return rc;
return S_OK;
return S_OK;
void *aUser)
switch (aState)
case VMSTATE_OFF:
case VMSTATE_TERMINATED:
if (aVM)
AssertFailed();
case MachineState_Stopping:
case MachineState_Saving:
case MachineState_Starting:
case MachineState_Restoring:
case VMSTATE_SUSPENDED:
case MachineState_Teleporting:
case MachineState_Saving:
case MachineState_Restoring:
case MachineState_Stopping:
case MachineState_Running:
case VMSTATE_SUSPENDED_LS:
case VMSTATE_SUSPENDED_EXT_LS:
case MachineState_Teleporting:
case MachineState_Saving:
AssertMsgFailed(("%s/%s -> %s\n", Global::stringifyMachineState(that->mMachineState), VMR3GetStateName(aOldState), VMR3GetStateName(aState) ));
case VMSTATE_RUNNING:
case VMSTATE_RUNNING_LS:
("%s/%s -> %s\n", Global::stringifyMachineState(that->mMachineState), VMR3GetStateName(aOldState), VMR3GetStateName(aState) ));
case VMSTATE_FATAL_ERROR:
case VMSTATE_GURU_MEDITATION:
#ifdef VBOX_WITH_USB
/** @todo just do everything here and only wrap the PDMR3Usb call. That'll offload some notification stuff from the EMT thread. */
switch (vrc)
case VERR_VUSB_NO_PORTS:
vrc);
return hrc;
DECLCALLBACK(int)
Console::usbAttachCallback(Console *that, IUSBDevice *aHostDevice, PCRTUUID aUuid, bool aRemote, const char *aAddress, ULONG aMaskedIfs)
if (aRemote)
pvRemoteBackend = that->consoleVRDPServer()->USBBackendRequestPointer(pRemoteUSBDevice->clientId(), &guid);
if (!pvRemoteBackend)
return vrc;
/** @todo just do everything here and only wrap the PDMR3Usb call. That'll offload some notification stuff from the EMT thread. */
return S_OK;
DECLCALLBACK(int)
if (fRemote)
return vrc;
# ifdef VBOX_STRICT
# ifdef RT_OS_LINUX
memcpy(IfReq.ifr_name, str.raw(), sizeof(IfReq.ifr_name) - 1); /** @todo bitch about names which are too long... */
if (rcVBox != 0)
LogRel(("Configuration error: Failed to configure /dev/net/tun non blocking. Error: %s\n", strerror(iErr)));
switch (rcVBox)
case VERR_ACCESS_DENIED:
rcVBox);
memcpy(szTapdev + strlen(szTapdev), str.raw(), sizeof(szTapdev) - strlen(szTapdev) - 1); /** @todo bitch about names which are too long... */
switch (rcVBox)
case VERR_ACCESS_DENIED:
return rc;
# ifdef VBOX_STRICT
bool isStatic = true;
isStatic = false;
if (isStatic)
return rc;
if (!enabled)
return rc;
return VINF_SUCCESS;
const char *pszErrorId,
void Console::processRemoteUSBDevices(uint32_t u32ClientId, VRDPUSBDEVICEDESC *pDevList, uint32_t cbDevList)
LogFlowThisFunc(("u32ClientId = %d, pDevList=%p, cbDevList = %d\n", u32ClientId, pDevList, cbDevList));
++it)
bool fNewDevice = true;
++it)
fNewDevice = false;
if (fNewDevice)
if (fMatched)
++ it;
if (!device)
#if defined(RT_OS_WINDOWS)
#ifdef VBOX_WITH_VRDP
switch (vrc)
case VERR_FILE_NOT_FOUND:
vrc);
&pVM);
#ifdef VBOX_WITH_VRDP
if (machineDebugger)
++ it)
/* -> ConsoleImplTeleporter.cpp */
bool fPowerOffOnFailure;
vrc);
* need to go back to the PoweredOff/Saved state. Reuse
console);
#if defined(RT_OS_WINDOWS)
return VINF_SUCCESS;
const char *pcszDevice,
unsigned uInstance,
bool fUseHostIOCache,
bool fSetupMerge,
unsigned uMergeSource,
unsigned uMergeTarget,
int rc;
#define RC_CHECK() do { if (RT_FAILURE(rc)) { AssertMsgFailed(("rc=%Rrc\n", rc)); return rc; } } while (0)
#define H() do { if (FAILED(hrc)) { AssertMsgFailed(("hrc=%Rhrc (%#x)\n", hrc, hrc)); *phrc = hrc; return VERR_GENERAL_FAILURE; } } while (0)
return VINF_SUCCESS;
phrc,
pVM,
RC_CHECK();
#undef H
return VINF_SUCCESS;
bool fBeganTakingSnapshot = false;
bool fSuspenededBySave = false;
throw rc;
fBeganTakingSnapshot = true;
(void*)pTask,
throw rc;
for (size_t i = 0;
throw rc;
throw rc;
throw rc;
throw rc;
throw rc;
throw rc;
that,
atts[i],
&rc);
throw rc;
LogFlowFunc(("EndTakingSnapshot -> %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(that->mMachineState)));
if (fBeganTakingSnapshot)
LogFunc(("Caught %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(that->mMachineState)));
switch (enmVMState)
case VMSTATE_RUNNING:
case VMSTATE_RUNNING_LS:
case VMSTATE_DEBUGGING:
case VMSTATE_DEBUGGING_LS:
case VMSTATE_POWERING_OFF:
case VMSTATE_POWERING_OFF_LS:
case VMSTATE_RESETTING:
case VMSTATE_RESETTING_LS:
case VMSTATE_GURU_MEDITATION:
case VMSTATE_FATAL_ERROR:
case VMSTATE_FATAL_ERROR_LS:
case VMSTATE_SUSPENDED:
case VMSTATE_SUSPENDED_LS:
case VMSTATE_SUSPENDING:
case VMSTATE_SUSPENDING_LS:
if (fSuspenededBySave)
delete pTask;
return VINF_SUCCESS;
bool fSuspenededBySave;
return VINF_SUCCESS;
return VINF_SUCCESS;
typedef struct DRVMAINSTATUS
return NULL;
while (iLed-- > 0)
return rc;
return rc;
return rc;
AssertMsgFailed(("Configuration error: Invalid unit range %u-%u\n", pData->iFirstLUN, pData->iLastLUN));
return VERR_GENERAL_FAILURE;
return VINF_SUCCESS;
sizeof(DRVMAINSTATUS),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,