ConsoleImpl.cpp revision 55d7f78467f8aefc7dff60f188bdf0f80523862c
* If \a aUsesVMPtr parameter is true, the task structure will also add itself * as a Console::mpUVM caller with the same meaning as above. See * Console::addVMCaller() for more info. /** Releases the VM caller before destruction. Not normally necessary. */ /* array of progress objects for hard disk reset operations */ // Handler for global events //////////////////////////////////////////////////////////////////////////////// /* now we can operate with redirects */ // constructor / destructor ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// /* Enclose the state transition NotReady->InInit->Ready */ /* Cache essential properties and objects */ /* Create associated child COM objects */ // Event source may be needed by other children /* Grab global and machine shared folder lists */ /* Create other child objects */ // VirtualBox 4.0: We no longer initialize the VMMDev instance here, // which starts the HGCM thread. Instead, this is now done in the // power-up thread when a VM is actually being powered up to avoid // having HGCM threads all over the place every time a session is // opened, even if that session will not run a VM. // unconst(m_pVMMDev) = new VMMDev(this); // AssertReturn(mVMMDev, E_FAIL); /* VirtualBox events registration. */ /* Confirm a successful initialization when it's the case */ /* Let the extension packs have a go at things (hold no locks). */ * Uninitializes the Console object. /* Enclose the state transition Ready->InUninit->NotReady */ /* power down the VM if necessary */ // if the VM had a VMMDev with an HGCM thread, then remove that here // we don't perform uninit() as it's possible that some pending event refers to this source * Handles guest properties on a VM reset. * We must delete properties that are flagged TRANSRESET. * @todo r=bird: Would be more efficient if we added a request to the HGCM * service to do this instead of detouring thru VBoxSVC. * (IMachine::SetGuestProperty ends up in VBoxSVC, which in turns calls * back into the VM process and the HGCM service.) /* Delete all properties which have the flag "TRANSRESET". */ LogRel((
"RESET: Could not delete transient property \"%ls\", rc=%Rhrc\n",
LogRel((
"RESET: Unable to enumerate guest properties, rc=%Rhrc\n",
hrc));
#
endif /* VBOX_WITH_GUEST_PROPS */ * Used by VRDEServer and others to talke to the extension pack manager. * @returns The extension pack manager. /* Console has been already uninitialized, deny request */ LogRel((
"AUTH: Access denied (Console uninitialized).\n"));
LogRel((
"AUTH: User: [%s]. Domain: [%s]. Authentication type: [%s]\n",
/* Call the external library. */ LogRel((
"AUTH: Delegated to guest.\n"));
LogFlowFunc((
"External auth asked for guest judgement\n"));
// @todo r=dj locking required here for m_pVMMDev? /* Issue the request to guest. Assume that the call does not require EMT. It should not. */ /* Ask the guest to judge these credentials. */ LogFlowFunc((
"Wait for credentials judgement rc = %Rrc!!!\n",
rc));
LogRel((
"AUTH: Access denied.\n"));
LogRel((
"AUTH: Access granted.\n"));
/* Multiconnection check must be made after authentication, so bad clients would not interfere with a good one. */ /* Note: the 'mcVRDPClients' variable is incremented in ClientConnect callback, which is called when the client * is successfully connected, that is after the ClientLogon callback. Therefore the mcVRDPClients * value is 0 for first client. /* There is a client already. * If required drop the existing client connection and let the connecting one in. LogRel((
"AUTH: Multiple connections are not enabled. Disconnecting existing client.\n"));
LogRel((
"AUTH: Multiple connections are not enabled. Access denied.\n"));
/* Save the connected client id. From now on it will be necessary to disconnect this one. */ #
endif /* VBOX_WITH_GUEST_PROPS */ /* Check if the successfully verified credentials are to be sent to the guest. */ /* Provide credentials only if there are no logged in users. */ /* And only if there are no connected clients. */ // @todo r=dj locking required here for m_pVMMDev? #
endif /* VBOX_WITH_GUEST_PROPS */ * Loads various console data stored in the saved state file. * This method does validation of the state file and returns an error info * The method does nothing if the machine is not in the Saved file or if * console data from it has already been loaded. * @note The caller must lock this object for writing. tr(
"The saved state file '%ls' is invalid (%Rrc). Delete the saved state and try again"),
* Callback handler to save various console data to the state file, * called when the user saves the VM state. * @param pvUser pointer to Console * @note Locks the Console object for reading. * Callback handler to load various console data from the state file. * Called when the VM is being restored from the saved state. * @param pvUser pointer to Console * @param uVersion Console unit version. * Should match sSSMConsoleVer. * @param uPass The data pass. * @note Should locks the Console object for writing, if necessary. /* Currently, nothing to do when we've been called from VMR3Load*. */ * Method to load various console data from the state file. * Called from #loadDataFromSavedState. * @param pvUser pointer to Console * @param u32Version Console unit version. * Should match sSSMConsoleVer. * @note Locks the Console object for writing. false /* fFailOnError */);
* No locking, as this is purely a notification which does not make any * changes to the object state. Log5((
"Console::doGuestPropNotification: pCBData={.pcszName=%s, .pcszValue=%s, .pcszFlags=%s}\n",
LogFunc((
"Console::doGuestPropNotification: hrc=%Rhrc pCBData={.pcszName=%s, .pcszValue=%s, .pcszFlags=%s}\n",
* Now things get slightly complicated. Due to a race with the guest adding * properties, there is no good way to know how much to enlarge a buffer for * the service to enumerate into. We choose a decent starting size and loop a * few times, each time retrying with the size suggested by the service plus tr(
"Temporary failure due to guest activity, please retry"));
* Finally we have to unpack the data returned by the service into the safe * arrays supplied by the caller. We start by counting the number of entries. /* The list is terminated by a zero-length string at the end of a set /* We are counting sets of four strings. */ for (
unsigned j = 0; j <
4; ++j)
* And now we create the COM safe arrays and fill them in. /* Rely on the service to have formated the data correctly. */ #
endif /* VBOX_WITH_GUEST_PROPS *////////////////////////////////////////////////////////////////////////////// /* mMachine is constant during life time, no need to lock */ /* callers expect to get a valid reference, better fail than crash them */ /* we return our local state (since it's always the same as on the server) */ /* mGuest is constant during life time, no need to lock */ /* mKeyboard is constant during life time, no need to lock */ /* mMouse is constant during life time, no need to lock */ /* mDisplay is constant during life time, no need to lock */ /* we need a write lock because of the lazy mDebugger initialization*/ /* check if we have to create the debugger object */ /* mDisplay is constant during life time, no need to lock */ /* loadDataFromSavedState() needs a write lock */ /* Read console data stored in the saved state file (if not yet done) */ // no need to lock - lifetime constant ///////////////////////////////////////////////////////////////////////////// /* Try cancel the teleportation. */ /* Try cancel the live snapshot. */ /* Try cancel the FT sync. */ /* extra nice error message for a common case */ tr(
"Invalid machine state: %s (must be Running, Paused or Stuck)"),
/* memorize the current machine state */ * request a progress object from the server * (this will set the machine state to Stopping on the server to block * others from accessing this machine) /* sync the state with the server */ /* setup task object and thread to carry out the operation asynchronously */ /* task is now owned by powerDownThread(), so release it */ /* pass the progress to the caller */ /* preserve existing error info */ * cancel the requested power down procedure. * This will reset the machine state to the state it had right * before calling mControl->BeginPoweringDown(). /** @todo r=bird: This should be allowed on paused VMs as well. Later. */ /* leave the lock before a VMR3* call (EMT will call us back)! */ tr(
"Could not reset the machine (%Rrc)"),
Log((
"UnplugCpu: rc=%Rrc\n",
vrc));
/* Check if the CPU is present */ /* Leave the lock before any EMT/VMMDev call. */ /* Check if the CPU is unlocked */ /* Notify the guest if possible. */ /* It will take some time until the event is processed in the guest. Wait... */ /* Query one time. It is possible that the user ejected the CPU. */ /* If the CPU was unlocked we can detach it now. */ * Call worker in EMT, that's faster and safer than doing everything /* Detach it from the VM */ tr(
"Hot-Remove failed (rc=%Rrc)"),
vrc);
/* nuke anything which might have been left behind. */ Log((
"PlugCpu: rc=%Rrc\n",
rc));
/** @todo r=bird: This should be allowed on paused VMs as well. Later. */ /* Check if the CPU is present */ tr(
"CPU %d is already attached"),
aCpu);
* Call worker in EMT, that's faster and safer than doing everything * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait * here to make requests from under the lock in order to serialize them. /* leave the lock before a VMR3* call (EMT will call us back)! */ tr(
"Could not add CPU to the machine (%Rrc)"),
/* Notify the guest if possible. */ /** @todo warning if the guest doesn't support it */ /* leave the lock before a VMR3* call (EMT will call us back)! */ tr(
"Cannot resume the machine as it is not paused (machine state: %s)"),
/* leave the lock before a VMR3* call (EMT will call us back)! */ tr(
"Could not resume the machine execution (%Rrc)"),
/** @todo leave the console lock? */ /* get the acpi device interface and press the button. */ tr(
"Controlled power off failed (%Rrc)"),
/** @todo leave the console lock? */ /* get the acpi device interface and check if the button press was handled. */ tr(
"Checking if the ACPI Power Button event was handled by the guest OS failed (%Rrc)"),
tr(
"Invalid machine state %s when checking if the guest entered the ACPI mode)"),
/** @todo leave the console lock? */ /* get the acpi device interface and query the information. */ /** @todo leave the console lock? */ /* get the acpi device interface and press the sleep button. */ tr(
"Sending sleep button event failed (%Rrc)"),
tr(
"Cannot save the execution state as the machine is not running or paused (machine state: %s)"),
/* memorize the current machine state */ * request a saved state file path from the server * (this will set the machine state to Saving on the server to block * others from accessing this machine) /* sync the state with the server */ /* ensure the directory for the saved state file exists */ tr(
"Could not create a directory '%s' to save the state to (%Rrc)"),
/* create a task object early to ensure mpVM protection is successful */ * If we fail here it means a PowerDown() call happened on another * thread while we were doing Pause() (which leaves the Console lock). * We assign PowerDown() a higher precedence than SaveState(), * therefore just return the error to the caller. /* create a thread to wait until the VM state is saved */ /* task is now owned by saveStateThread(), so release it */ /* return the progress to the caller */ /* preserve existing error info */ * cancel the requested save state procedure. * This will reset the machine state to the state it had right * before calling mControl->BeginSavingState(). /* restore the paused state if appropriate */ /* restore the running state if appropriate */ tr(
"Cannot adopt the saved machine state as the machine is not in Powered Off, Teleported or Aborted state (machine state: %s)"),
tr(
"Cannot delete the machine state as the machine is not in the saved state (machine state: %s)"),
* Saved -> PoweredOff transition will be detected in the SessionMachine /** read the value of a LEd. */ * Note: we don't lock the console object here because * readAndClearLed() should be thread safe. /* Get LED array to read */ tr(
"Invalid device type: %d"),
tr(
"Cannot attach a USB device to the machine which is not running or paused (machine state: %s)"),
/* Don't proceed unless we've found the usb controller. */ tr(
"The virtual machine does not have a USB controller"));
/* leave the lock because the USB Proxy service may call us back * (via onUSBDeviceAttach()) */ /* Request the device capture */ #
else /* !VBOX_WITH_USB */ tr(
"The virtual machine does not have a USB controller"));
#
endif /* !VBOX_WITH_USB */ tr(
"USB device with UUID {%RTuuid} is not attached to this machine"),
* Inform the USB device and USB proxy about what's cooking. /* Request the PDM to detach the USB device. */ /* leave the lock since we don't need it any more (note though that * the USB Proxy service must not call us back here) */ /* Request the device release. Even if it fails, the device will * remain as held by proxy, which is OK for us (the VM process). */ #
else /* !VBOX_WITH_USB */ tr(
"The virtual machine does not have a USB controller"));
#
endif /* !VBOX_WITH_USB */ tr(
"Could not find a USB device with address '%ls'"),
#
else /* !VBOX_WITH_USB */#
endif /* !VBOX_WITH_USB */ tr(
"Could not find a USB device with uuid {%RTuuid}"),
#
else /* !VBOX_WITH_USB */#
endif /* !VBOX_WITH_USB */ /// @todo see @todo in AttachUSBDevice() about the Paused state tr(
"Cannot create a transient shared folder on the machine in the saved state"));
tr(
"Cannot create a transient shared folder on the machine while it is changing the state (machine state: %s)"),
tr(
"Shared folder named '%s' already exists"),
true /* fFailOnError */);
/* If the VM is online and supports shared folders, share this folder * under the specified name. (Ignore any failure to obtain the VM handle.) */ /* first, remove the machine or the global folder if there is any */ /* second, create the given folder */ /* notify console callbacks after the folder is added to the list */ /// @todo see @todo in AttachUSBDevice() about the Paused state tr(
"Cannot remove a transient shared folder from the machine in the saved state"));
tr(
"Cannot remove a transient shared folder from the machine while it is changing the state (machine state: %s)"),
/* protect the VM handle (if not NULL) */ /* if the VM is online and supports shared folders, UNshare this /* first, remove the given folder */ /* first, remove the machine or the global folder if there is any */ /* don't check rc here because we need to remove the console * folder from the collection even on failure */ /* notify console callbacks after the folder is removed to the list */ tr(
"Cannot take a snapshot of the machine while it is changing the state (machine state: %s)"),
/* prepare the progress object: a) count the no. of hard disk attachments to get a matching no. of progress sub-operations */ return setError(
rc,
tr(
"Cannot get medium attachments of the machine"));
// assume that creating a diff image takes as long as saving a 1MB state // (note, the same value must be used in SessionMachine::BeginTakingSnapshot() on the server!) // b) one extra sub-operations for online snapshots OR offline snapshots that have a saved state (needs to be copied) // finally, create the progress object Bstr(
tr(
"Taking a snapshot of the virtual machine")).
raw(),
Bstr(
tr(
"Setting up snapshot operation")).
raw(),
// first sub-op description 1);
// ulFirstOperationWeight * If we fail here it means a PowerDown() call happened on another * thread while we were doing Pause() (which leaves the Console lock). * We assign PowerDown() a higher precedence than TakeSnapshot(), * therefore just return the error to the caller. /* memorize the current machine state */ tr(
"Could not create VMTakeSnap thread (%Rrc)"),
tr(
"Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"),
tr(
"Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"),
tr(
"Cannot delete the current state of the running machine (machine state: %s)"),
// Non-interface public methods ///////////////////////////////////////////////////////////////////////////// tr(
"Invalid machine state: %s"),
* @copydoc VirtualBox::handleUnexpectedExceptions /* re-throw the current exception */ tr(
"Unexpected exception: %s [%s]\n%s[%d] (%s)"),
tr(
"Unknown exception\n%s[%d] (%s)"),
/* should not get here */ ///////////////////////////////////////////////////////////////////////////// * Process a medium change. * @param aMediumAttachment The medium attachment with the new medium state. * @param fForce Force medium chance, if it is locked or not. * @param pVM Safe VM handle. * @note Locks this object for writing. /* We will need to release the write lock before calling EMT */ * Call worker in EMT, that's faster and safer than doing everything * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait * here to make requests from under the lock in order to serialize them. /* leave the lock before waiting for a result (EMT will call us back!) */ tr(
"Could not unmount the currently mounted media/drive (%Rrc)"),
* Performs the medium change in EMT. * @returns VBox status code. * @param pThis Pointer to the Console object. * @param pVM The VM handle. * @param pcszDevice The PDM device name. * @param uInstance The PDM device instance. * @param uLun The PDM LUN number of the drive. * @param fHostDrive True if this is a host drive attachment. * @param pszPath The path to the media / drive which is now being mounted / captured. * If NULL no media or drive is attached and the LUN will be configured with * the default block driver with no media. This will also be the state if * mounting / capturing the specified media / drive fails. * @param pszFormat Medium format string, usually "RAW". * @param fPassthrough Enables using passthrough mode of the host DVD drive if applicable. LogFlowFunc((
"pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p, fForce=%d\n",
* The VM must not be running since it might have pending I/O to * the drive which is being changed. /* disable the callback to prevent Console-level state change */ /* Determine the base path for the device instance. */ false /* fBuiltinIoCache */,
true /* fAttachDetach */,
NULL /* paLedDevType */);
/** @todo this dumps everything attached to this device instance, which * is more than necessary. Dumping the changed LUN would be enough. */ * Resume the VM if necessary. /* disable the callback to prevent Console-level state change */ /* too bad, we failed. try to sync the console state with the VMM state */ /// @todo (r=dmik) if we failed with drive mount, then the VMR3Resume // error (if any) will be hidden from the caller. For proper reporting // of such multiple errors to the caller we need to enhance the // IVirtualBoxError interface. For now, give the first error the higher * Attach a new storage device to the VM. * @param aMediumAttachment The medium attachment which is added. * @param pVM Safe VM handle. * @note Locks this object for writing. /* We will need to release the write lock before calling EMT */ * Call worker in EMT, that's faster and safer than doing everything * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait * here to make requests from under the lock in order to serialize them. /* leave the lock before waiting for a result (EMT will call us back!) */ tr(
"Could not unmount the currently mounted media/drive (%Rrc)"),
* Performs the storage attach operation in EMT. * @returns VBox status code. * @param pThis Pointer to the Console object. * @param pVM The VM handle. * @param pcszDevice The PDM device name. * @param uInstance The PDM device instance. LogFlowFunc((
"pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p\n",
* The VM must not be running since it might have pending I/O to * the drive which is being changed. /* disable the callback to prevent Console-level state change */ /* Determine the base path for the device instance. */ false /* fBuiltinIoCache */,
true /* fAttachDetach */,
false /* fForceUnmount */,
NULL /* paLedDevType */);
/** @todo this dumps everything attached to this device instance, which * is more than necessary. Dumping the changed LUN would be enough. */ * Resume the VM if necessary. /* disable the callback to prevent Console-level state change */ /* too bad, we failed. try to sync the console state with the VMM state */ /** @todo: if we failed with drive mount, then the VMR3Resume * error (if any) will be hidden from the caller. For proper reporting * of such multiple errors to the caller we need to enhance the * IVirtualBoxError interface. For now, give the first error the higher * Attach a new storage device to the VM. * @param aMediumAttachment The medium attachment which is added. * @param pVM Safe VM handle. * @note Locks this object for writing. /* We will need to release the write lock before calling EMT */ * Call worker in EMT, that's faster and safer than doing everything * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait * here to make requests from under the lock in order to serialize them. /* leave the lock before waiting for a result (EMT will call us back!) */ tr(
"Could not unmount the currently mounted media/drive (%Rrc)"),
* Performs the storage detach operation in EMT. * @returns VBox status code. * @param pThis Pointer to the Console object. * @param pVM The VM handle. * @param pcszDevice The PDM device name. * @param uInstance The PDM device instance. LogFlowFunc((
"pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, pMediumAtt=%p\n",
* The VM must not be running since it might have pending I/O to * the drive which is being changed. /* disable the callback to prevent Console-level state change */ /* Determine the base path for the device instance. */ /* First check if the LUN really exists. */ * Resume the VM if necessary. /* disable the callback to prevent Console-level state change */ /* too bad, we failed. try to sync the console state with the VMM state */ /** @todo: if we failed with drive mount, then the VMR3Resume * error (if any) will be hidden from the caller. For proper reporting * of such multiple errors to the caller we need to enhance the * IVirtualBoxError interface. For now, give the first error the higher * Called by IInternalSessionControl::OnNetworkAdapterChange(). * @note Locks this object for writing. /* don't trigger network change if the VM isn't running */ /* Get the properties we need from the adapter */ * Find the adapter instance, get the config interface and update Log((
"Console::onNetworkAdapterChange: setting link state to %d\n",
/* notify console callbacks on success */ * Called by IInternalSessionControl::OnNATEngineChange(). * @note Locks this object for writing. /* don't trigger nat engine change if the VM isn't running */ * Find the adapter instance, get the config interface and update /* look down for PDMINETWORKNATCONFIG interface */ /** @todo r=bird: This stinks! */ }
while (0);
/* break loop */ * Process a network adaptor change. * @returns COM status code. * @parma pVM The VM handle (caller hold this safely). * @param pszDevice The PDM device name. * @param uInstance The PDM device instance. * @param uLun The PDM LUN number of the drive. * @param aNetworkAdapter The network adapter whose attachment needs to be changed * @note Locks this object for writing. LogFlowThisFunc((
"pszDevice=%p:{%s} uInstance=%u uLun=%u aNetworkAdapter=%p\n",
/* We will need to release the write lock before calling EMT */ * Call worker in EMT, that's faster and safer than doing everything * using VM3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait * here to make requests from under the lock in order to serialize them. /* leave the lock before waiting for a result (EMT will call us back!) */ tr(
"Could not change the network adaptor attachement type (%Rrc)"),
* Performs the Network Adaptor change in EMT. * @returns VBox status code. * @param pThis Pointer to the Console object. * @param pVM The VM handle. * @param pszDevice The PDM device name. * @param uInstance The PDM device instance. * @param uLun The PDM LUN number of the drive. * @param aNetworkAdapter The network adapter whose attachment needs to be changed * @note Locks the Console object for writing. LogFlowFunc((
"pThis=%p pszDevice=%p:{%s} uInstance=%u uLun=%u aNetworkAdapter=%p\n",
* The VM must not be running since it might have pending I/O to * the drive which is being changed. /* disable the callback to prevent Console-level state change */ true /*fAttachDetach*/,
false /*fIgnoreConnectFailure*/);
* Resume the VM if necessary. /* disable the callback to prevent Console-level state change */ /* too bad, we failed. try to sync the console state with the VMM state */ /// @todo (r=dmik) if we failed with drive mount, then the VMR3Resume // error (if any) will be hidden from the caller. For proper reporting // of such multiple errors to the caller we need to enhance the // IVirtualBoxError interface. For now, give the first error the higher * Called by IInternalSessionControl::OnSerialPortChange(). * @note Locks this object for writing. /* don't trigger serial port change if the VM isn't running */ /* nothing to do so far */ /* notify console callbacks on success */ * Called by IInternalSessionControl::OnParallelPortChange(). * @note Locks this object for writing. /* don't trigger parallel port change if the VM isn't running */ /* nothing to do so far */ /* notify console callbacks on success */ * Called by IInternalSessionControl::OnStorageControllerChange(). * @note Locks this object for writing. /* don't trigger storage controller change if the VM isn't running */ /* nothing to do so far */ /* notify console callbacks on success */ * Called by IInternalSessionControl::OnMediumChange(). * @note Locks this object for writing. /* don't trigger medium change if the VM isn't running */ /* notify console callbacks on success */ * Called by IInternalSessionControl::OnCPUChange(). * @note Locks this object for writing. /* don't trigger CPU change if the VM isn't running */ /* notify console callbacks on success */ * Called by IInternalSessionControl::OnCpuExecutionCapChange(). * @note Locks this object for writing. /* don't trigger the CPU priority change if the VM isn't running */ /* No need to call in the EMT thread. */ /* notify console callbacks on success */ * Called by IInternalSessionControl::OnVRDEServerChange(). * @note Locks this object for writing. /* VRDP server may call this Console object back from other threads (VRDP INPUT or OUTPUT). */ // If there was no VRDP server started the 'stop' will do nothing. // However if a server was started and this notification was called, // we have to restart the server. /* notify console callbacks on success */ * @note Locks this object for reading. * Called by IInternalSessionControl::OnUSBControllerChange(). * @note Locks this object for writing. /* don't trigger USB controller change if the VM isn't running */ /// @todo implement one day. // Anyway, if we want to query the machine's USB Controller we need // to cache it to mUSBController in #init() (similar to mDVDDrive). // bird: While the VM supports hot-plugging, I doubt any guest can // handle it at this time... :-) /* nothing to do so far */ /* notify console callbacks on success */ * Called by IInternalSessionControl::OnSharedFolderChange(). * @note Locks this object for writing. /* notify console callbacks on success */ * Called by IInternalSessionControl::OnUSBDeviceAttach() or locally by * processRemoteUSBDevices() after IInternalMachineControl::RunUSBDeviceFilters() * returns TRUE for a given remote USB device. * @return S_OK if the device was attached to the VM. * @return failure if not attached. * The device in question. * The interfaces to hide from the guest. * @note Locks this object for writing. /* Get the VM pointer (we don't need error info, since it's a callback). */ /* The VM may be no more operational when this message arrives * (e.g. it may be Saving or Stopping or just PoweredOff) -- * autoVMCaller.rc() will return a failure in this case. */ /* notify callbacks about the error */ /* Don't proceed unless there's at least one USB hub. */ /* take the current error info */ /* the error must be a VirtualBoxErrorInfo instance */ /* notify callbacks about the error */ #
else /* !VBOX_WITH_USB */#
endif /* !VBOX_WITH_USB */ * Called by IInternalSessionControl::OnUSBDeviceDetach() and locally by * processRemoteUSBDevices(). * @note Locks this object for writing. /* The VM may be no more operational when this message arrives * (e.g. it may be Saving or Stopping or just PoweredOff). Use * AutoVMCaller to detect it -- AutoVMCaller::rc() will return a * failure in this case. */ /* the device must be in the list otherwise */ /* notify callback about an error */ /* take the current error info */ /* the error must be a VirtualBoxErrorInfo instance */ /* notify callbacks about the error */ #
else /* !VBOX_WITH_USB */#
endif /* !VBOX_WITH_USB */ * Called by IInternalSessionControl::OnBandwidthGroupChange(). * @note Locks this object for writing. /* don't trigger the CPU priority change if the VM isn't running */ /* No need to call in the EMT thread. */ /* notify console callbacks on success */ * Called by IInternalSessionControl::OnStorageDeviceChange(). * @note Locks this object for writing. /* don't trigger medium change if the VM isn't running */ /* notify console callbacks on success */ * @note Temporarily locks this object for writing. #
else /* VBOX_WITH_GUEST_PROPS */ /* protect mpVM (if not NULL) */ /* Note: validity of mVMMDev which is bound to uninit() is guaranteed by * autoVMCaller, so there is no need to hold a lock of this */ /* The + 1 is the null terminator */ /* The returned string should never be able to be greater than our buffer */ tr(
"The service call failed with the error %Rrc"),
#
endif /* VBOX_WITH_GUEST_PROPS */ * @note Temporarily locks this object for writing. #
else /* VBOX_WITH_GUEST_PROPS */ /* protect mpVM (if not NULL) */ /* Note: validity of mVMMDev which is bound to uninit() is guaranteed by * autoVMCaller, so there is no need to hold a lock of this */ /* The + 1 is the null terminator */ /* The + 1 is the null terminator */ /* The + 1 is the null terminator */ tr(
"The service call failed with the error %Rrc"),
#
endif /* VBOX_WITH_GUEST_PROPS */ * @note Temporarily locks this object for writing. #
else /* VBOX_WITH_GUEST_PROPS */ /* protect mpVM (if not NULL) */ /* Note: validity of mVMMDev which is bound to uninit() is guaranteed by * autoVMCaller, so there is no need to hold a lock of this */ #
endif /* VBOX_WITH_GUEST_PROPS */ * Internal: helper function for connecting progress reporting * @note Temporarily locks this object for writing. bird: And/or reading? /* Get the VM - must be done before the read-locking. */ /* We will need to release the lock before doing the actual merge */ /* paranoia - we don't want merges to happen while teleporting etc. */ /** @todo AssertComRC -> AssertComRCReturn! Could potentially end up * using uninitialized variables here. */ tr(
"Could not find storage controller '%ls'"),
/* Pause the VM, as it might have pending IO on this drive */ /* disable the callback to prevent Console-level state change */ /* error handling is after resuming the VM */ /* disable the callback to prevent Console-level state change */ /* too bad, we failed. try to sync the console state with the VMM state */ /* Finally trigger the merge. */ /* Pause the VM, as it might have pending IO on this drive */ /* disable the callback to prevent Console-level state change */ /* Update medium chain and state now, so that the VM can continue. */ /* error handling is after resuming the VM */ /* disable the callback to prevent Console-level state change */ /* too bad, we failed. try to sync the console state with the VMM state */ * Gets called by Session::UpdateMachineState() * (IInternalSessionControl::updateMachineState()). * Must be called only in certain cases (see the implementation). * @note Locks this object for writing. * @note Locks this object for writing. LogFlowThisFunc((
"fVisible=%d, fAlpha=%d, xHot = %d, yHot = %d, width=%d, height=%d, shape=%p\n",
/* We need a write lock because we alter the cached callback data */ /* Save the callback arguments */ /* start with not valid */ * @note Locks this object for writing. LogFlowThisFunc((
"supportsAbsolute=%d supportsRelative=%d needsHostCursor=%d\n",
/* We need a write lock because we alter the cached callback data */ /* save the callback arguments */ * @note Locks this object for reading. * @note Locks this object for reading. * @note Locks this object for reading. * This notification only is for reporting an incompatible * Guest Additions interface, *not* the Guest Additions version! * The user will be notified inside the guest if new Guest * @note Locks this object for writing. /* We need a write lock because we alter the cached callback data */ /* save the callback arguments */ * @note Locks this object for reading. * @note Locks this object for reading. * @note Locks this object for reading. //////////////////////////////////////////////////////////////////////////////// * Increases the usage counter of the mpVM pointer. Guarantees that * VMR3Destroy() will not be called on it at least until releaseVMCaller() * If this method returns a failure, the caller is not allowed to use mpVM * and may return the failed result code to the upper level. This method sets * the extended error info on failure if \a aQuiet is false. * Setting \a aQuiet to true is useful for methods that don't want to return * the failed result code to the caller when this method fails (e.g. need to * silently check for the mpVM availability). * When mpVM is NULL but \a aAllowNullVM is true, a corresponding error will be * returned instead of asserting. Having it false is intended as a sanity check * for methods that have checked mMachineState and expect mpVM *NOT* to be NULL. * @param aQuiet true to suppress setting error info * @param aAllowNullVM true to accept mpVM being NULL and return a failure * (otherwise this method will assert if mpVM is NULL) * @note Locks this object for writing. /* powerDown() is waiting for all callers to finish */ tr(
"The virtual machine is being powered down"));
/* The machine is not powered up */ tr(
"The virtual machine is not powered up"));
* Decreases the usage counter of the mpVM pointer. Must always complete * the addVMCaller() call after the mpVM pointer is no more necessary. * @note Locks this object for writing. /* inform powerDown() there are no more callers */ * Repeat the checks done by addVMCaller. if (
mVMDestroying)
/* powerDown() is waiting for all callers to finish */ * Retain a reference to the user mode VM handle and get the global handle. * Initialize the release logging facility. In case something * goes wrong, there will be no release logging. Maybe in the future * we can add some logic to use different file names in this case. * Note that the logic must be in sync with Machine::DeleteSettings(). /* make sure the Logs folder exists */ * Rename .(n-1) to .(n), .(n-2) to .(n-1), ..., and the last log file to .1 * Overwrite target files in case they exist. /* If the old file doesn't exist, delete the new file (if it * exists) to provide correct rotation even if the sequence is NULL /* pfnBeginEnd */, 0
/* cHistory */, 0
/* cbHistoryFileMax */, 0
/* uHistoryTimeMax */,
/* some introductory information */ "VirtualBox %s r%u %s (%s %s) release log\n" /* the package type is interesting for Linux distributions */ /* register this logger as the release logger */ /* Explicitly flush the log in case of VBOX_RELEASE_LOG=buffered. */ tr(
"Failed to open release log (%s, %Rrc)"),
/* If we've made any directory changes, flush the directory to increase the likelihood that the log file will be usable after a system panic. Tip: Try 'export VBOX_RELEASE_LOG_FLAGS=flush' if the last bits of the log is missing. Just don't have too high hopes for this to help. */ * Common worker for PowerUp and PowerUpPaused. * @returns COM status code. * @param aProgress Where to return the progress object. * @param aPaused true if PowerUpPaused called. tr(
"The virtual machine is already running or busy (machine state: %s)"),
/* test and clear the TeleporterEnabled property */ #
if 0
/** @todo we should save it afterwards, but that isn't necessarily a good idea. Find a better place for this (VBoxSVC). */ /* test the FaultToleranceState property */ /* Create a progress object to track progress of this operation. Must * be done as early as possible (together with BeginPowerUp()) as this * is vital for communicating as much as possible early powerup * failure information to the API caller */ progressDesc =
tr(
"Fault Tolerance syncing of remote virtual machine");
FALSE /* aCancelable */);
10 /* ulTotalOperationsWeight */,
Bstr(
tr(
"Teleporting virtual machine")).
raw(),
1 /* ulFirstOperationWeight */,
10 /* ulTotalOperationsWeight */,
Bstr(
tr(
"Fault Tolerance syncing of remote virtual machine")).
raw(),
1 /* ulFirstOperationWeight */,
/* Tell VBoxSVC and Machine about the progress object so they can /** @todo this code prevents starting a VM with unavailable bridged * networking interface. The only benefit is a slightly better error * message, which should be moved to the driver code. This is the * only reason why I left the code in for now. The driver allows * unavailable bridged networking interfaces in certain circumstances, * and this is sabotaged by this check. The VM will initially have no * network connectivity, but the user can fix this at runtime. */ /* the network cards will undergo a quick consistency check */ /* a valid host interface must have been set */ tr(
"VM cannot start because host interface networking requires a host interface name to be set"));
tr(
"VM cannot start because the host interface '%ls' does not exist"),
/* Read console data stored in the saved state file (if not yet done) */ /* Check all types of shared folders and compose a single list */ /* first, insert global folders */ /* second, insert machine folders */ /* third, insert console folders */ * Saved VMs will have to prove that their saved states seem kosher. tr(
"VM cannot start because the saved state file '%ls' is invalid (%Rrc). Delete the saved state prior to starting the VM"),
/* setup task object and thread to carry out the operation /* Reset differencing hard disks for which autoReset is true, * but only if the machine has no snapshots OR the current snapshot * is an OFFLINE snapshot; otherwise we would reset the current * differencing image of an ONLINE snapshot which contains the disk * state of the machine while it was previously running, but without * the corresponding machine state, which is equivalent to powering * off a running machine and not good idea /** @todo later applies to floppies as well */ /* save for later use on the powerup thread */ LogFlowThisFunc((
"Machine has a current snapshot which is online, skipping immutable images reset\n"));
/* setup host core dumper for the VM */ * Try create the directory. /* pass the progress object to the caller if requested */ /* there are no other operations to track, return the powerup /* create a combined progress object */ /* task is now owned by powerUpThread(), so release it */ /* finally, set the state: no right to fail in this method afterwards * since we've already started the thread and it is now responsible for * any error reporting and appropriate state change! */ /* The progress object will fetch the current error info */ /* Save the error info across the IPC below. Can't be done before the * progress notification above, as saving the error info deletes it * from the current context, and thus the progress object wouldn't be /* signal end of operation */ * Internal power off worker routine. * This method may be called only at certain places with the following meaning * - if the machine state is either Running or Paused, a normal * Console-initiated powerdown takes place (e.g. PowerDown()); * - if the machine state is Saving, saveStateThread() has successfully done its * - if the machine state is Starting or Restoring, powerUpThread() has failed * - if the machine state is Stopping, the VM has powered itself off (i.e. not * as a result of the powerDown() call). * Calling it in situations other than the above will cause unexpected behavior. * Note that this method should be the only one that destroys mpVM and sets it * @param aProgress Progress object to run (may be NULL). * @note Locks this object for writing. * @note Never call this method from a thread that called addVMCaller() or * instantiated an AutoVMCaller object; first call releaseVMCaller() or * release(). Otherwise it will deadlock. /* Total # of steps for the progress object. Must correspond to the * number of "advance percent count" comments in this method! */ LogRel((
"Console::powerDown(): A request to power off the VM has been issued (mMachineState=%s, InUninit=%d)\n",
/* Check if we need to power off the VM. In case of mVMPoweredOff=true, the * VM has already powered itself off in vmstateChangeCallback() and is just * notifying Console about that. In case of Starting or Restoring, * powerUpThread() is calling us on failure, so the VM is already off at * Go to Stopping state if not already there. * vmstateChangeCallback() needs it to set the state to Saved on * VMSTATE_TERMINATED. In terms of protecting from inappropriate operations * while leaving the lock below, Saving or Restoring should be fine too. * Ditto for TeleportingPausedVM -> Teleported. /* ---------------------------------------------------------------------- * DONE with necessary state changes, perform the power down actions (it's * safe to leave the object lock now if needed) * ---------------------------------------------------------------------- */ /* Stop the VRDP server to prevent new clients connection while VM is being /* Leave the lock since EMT will call us back as addVMCaller() * in updateDisplayData(). */ /* advance percent count */ /* ---------------------------------------------------------------------- * Now, wait for all mpVM callers to finish their work if there are still * some on other threads. NO methods that need mpVM (or initiate other calls * that need it) may be called after this point * ---------------------------------------------------------------------- */ /* go to the destroying state to prevent from adding new callers */ /* advance percent count */ * Power off the VM if not already done that. * Leave the lock since EMT will call vmstateChangeCallback. * Note that VMR3PowerOff() may fail here (invalid VMSTATE) if the * VM-(guest-)initiated power off happened in parallel a ms before this * call. So far, we let this error pop up on the user's side. /* advance percent count */ /* Shutdown HGCM services before destroying the VM. */ /* Leave the lock since EMT will call us back as addVMCaller() */ /* advance percent count */ #
endif /* VBOX_WITH_HGCM */ /* If we are called from Console::uninit(), then try to destroy the VM even * on failure (this will most likely fail too, but what to do?..) */ /* If the machine has an USB controller, release all USB devices * (symmetric to the code in captureUSBDevices()) */ /* Now we've got to destroy the VM as well. (mpVM is not valid beyond * this point). We leave the lock before calling VMR3Destroy() because * it will result into calling destructors of drivers associated with * Console children which may in turn try to lock Console (e.g. by * instantiating SafeVMPtr to access mpVM). It's safe here because * mVMDestroying is set which should prevent any activity. */ /* Set mpUVM to NULL early just in case if some old code is not using * addVMCaller()/releaseVMCaller(). (We have our own ref on pUVM.) */ /* take the lock again */ /* advance percent count */ /* Note: the Console-level machine state change happens on the * VMSTATE_TERMINATE state change in vmstateChangeCallback(). If * powerDown() is called from EMT (i.e. from vmstateChangeCallback() * on receiving VM-initiated VMSTATE_OFF), VMSTATE_TERMINATE hasn't * occurred yet. This is okay, because mMachineState is already * Stopping in this case, so any other attempt to call PowerDown() /* bad bad bad, but what to do? (Give Console our UVM ref.) */ tr(
"Could not destroy the machine. (Error: %Rrc)"),
/* Complete the detaching of the USB devices. */ /* advance percent count */ tr(
"Could not power off the machine. (Error: %Rrc)"),
* Finished with the destruction. * Note that if something impossible happened and we've failed to destroy * the VM, mVMDestroying will remain true and mMachineState will be * something like Stopping, so most Console methods will return an error * @note Locks this object for writing. LogThisFunc((
"machineState=%s -> %s aUpdateServer=%RTbool\n",
// possibly, we need to redo onStateChange() using the dedicated // Event thread, like it is done in VirtualBox. This will make it // much safer (no deadlocks possible if someone tries to use the // console from the callback), however, listeners will lose the // ability to synchronously react to state changes (is it really /* Server notification MUST be done from under the lock; otherwise * the machine state here and on the server might go out of sync * which can lead to various unexpected results (like the machine * state being >= MachineState_Running on the server, while the * session state is already SessionState_Unlocked at the same time * Cross-lock conditions should be carefully watched out: calling * UpdateState we will require Machine and SessionMachine locks * (remember that here we're holding the Console lock here, and also * all locks that have been entered by the thread before calling * Searches for a shared folder with the given logical name * in the collection of shared folders. * @param aName logical name of the shared folder * @param aSharedFolder where to return the found object * @param aSetError whether to set the error info if the folder is * S_OK when found or E_INVALIDARG when not found * @note The caller must lock this object for writing. tr(
"Could not find a shared folder named '%s'."),
* Fetches the list of global or machine shared folders from the server. * @param aGlobal true to fetch global folders. * @note The caller must lock this object for writing. /* Check if we're online and keep it that way. */ /// @todo grab & process global folders when they are done /* send changes to HGCM if the VM is running */ /* a new machine folder is added or * the existing machine folder is changed */ ;
/* the console folder exists, nothing to do */ /* remove the old machine folder (when changed) * or the global folder if any (when new) */ /* create the new machine folder */ /* forget the processed (or identical) folder */ /* process outdated (removed) folders */ ;
/* the console folder exists, nothing to do */ /* remove the outdated machine folder */ /* create the global folder if there is any */ N_(
"Broken shared folder!"));
* Searches for a shared folder with the given name in the list of machine * shared folders and then in the list of the global shared folders. * @param aName Name of the folder to search for. * @param aIt Where to store the pointer to the found folder. * @return @c true if the folder was found and @c false otherwise. * @note The caller must lock this object for reading. /* first, search machine folders */ /* second, search machine folders */ * Calls the HGCM service to add a shared folder definition. * @param aName Shared folder name. * @param aHostPath Shared folder path. * @note Must be called from under AutoVMCaller and when mpVM != NULL! * @note Doesn't lock anything. // check whether the path is valid and exists /* Check whether the path is full (absolute) */ tr(
"Invalid shared folder path: '%s' (%Rrc)"),
tr(
"Shared folder path '%s' is not absolute"),
tr(
"Shared folder path '%s' does not exist on the host"),
// now that we know the path is good, give it to HGCM * Auto-mount flag; is indicated by using the SHFL_CPARMS_ADD_MAPPING2 * define below. This shows the host service that we have supplied * an additional parameter (auto-mount) and keeps the actual command tr(
"Could not create a shared folder '%s' mapped to '%s' (%Rrc)"),
* Calls the HGCM service to remove the shared folder definition. * @param aName Shared folder name. * @note Must be called from under AutoVMCaller and when mpVM != NULL! * @note Doesn't lock anything. tr(
"Could not remove the shared folder '%s' (%Rrc)"),
* VM state callback function. Called by the VMM * using its state machine states. * Primarily used to handle VM initiated power off, suspend and state saving, * but also for doing termination completed work (VMSTATE_TERMINATE). * In general this function is called in the context of the EMT. * @param aVM The VM handle. * @param aState The new state. * @param aOldState The old state. * @param aUser The user argument (pointer to the Console object). * @note Locks the Console object for writing. LogFlowFunc((
"Changing state from %s to %s (aVM=%p)\n",
/* Note that we must let this method proceed even if Console::uninit() has * been already called. In such case this VMSTATE change is a result of: * 1) powerDown() called from uninit() itself, or * 2) VM-(guest-)initiated power off. */ /* Do we still think that it is running? It may happen if this is a LogFlowFunc((
"VM has powered itself off but Console still thinks it is running. Notifying.\n"));
/* prevent powerDown() from calling VMR3PowerOff() again */ * request a progress object from the server * (this will set the machine state to Stopping on the server * to block others from accessing this machine) /* sync the state with the server */ /* Setup task object and thread to carry out the operation * asynchronously (if we call powerDown() right here but there * is one or more mpVM callers (added with addVMCaller()) we'll /* If creating a task failed, this can currently mean one of * two: either Console::uninit() has been called just a ms * before (so a powerDown() call is already on the way), or * powerDown() itself is being already executed. Just do LogFlowFunc((
"Console is already being uninitialized.\n"));
/* task is now owned by powerDownThread(), so release it */ /* The VM has been completely destroyed. * Note: This state change can happen at two points: * 1) At the end of VMR3Destroy() if it was not called from EMT. * 2) At the end of vmR3EmulationThread if VMR3Destroy() was /* Terminate host interface networking. If aVM is NULL, we've been * manually called from powerUpThread() either before calling * VMR3Create() or after VMR3Create() failed, so no need to touch /* From now on the machine is officially powered down or remains in /* successfully powered down */ /* failed to start, but be patient: set back to PoweredOff * (for similarity with the below) */ /* failed to load the saved state file, but be patient: set * back to Saved (to preserve the saved state file) */ /* Teleportation failed or was canceled. Back to powered off. */ /* Successfully teleported the VM. */ /* Fault tolerant sync failed or was canceled. Back to powered off. */ /* The worker thread handles the transition. */ /* Fatal errors are only for running VMs. */ /* Note! 'Pause' is used here in want of something better. There * are currently only two places where fatal errors might be * raised, so it is not worth adding a new externally * visible state for this yet. */ /* Guru are only for running VMs */ default:
/* shut up gcc */ * Sends a request to VMM to attach the given host device. * After this method succeeds, the attached device will appear in the * mUSBDevices collection. * @param aHostDevice device to attach * @note Synchronously calls EMT. * @note Must be called from under this object's lock. /* still want a lock object because we need to leave it */ * Get the address and the Uuid, and call the pfnCreateProxyDevice roothub * method in EMT (using usbAttachCallback()). /* leave the lock before a VMR3* call (EMT will call us back)! */ /** @todo just do everything here and only wrap the PDMR3Usb call. That'll offload some notification stuff from the EMT thread. */ tr(
"Failed to attach the USB device. (No available ports on the USB controller)."));
tr(
"Not permitted to open the USB device, check usbfs options"));
tr(
"Failed to create a proxy device for the USB device. (Error: %Rrc)"),
* USB device attach callback used by AttachUSBDevice(). * Note that AttachUSBDevice() doesn't return until this callback is executed, * so we don't use AutoCaller and don't care about reference counters of * interface pointers passed in. * @note Locks the console object for writing. /* Create a OUSBDevice and add it to the device list */ * Sends a request to VMM to detach the given host device. After this method * succeeds, the detached device will disappear from the mUSBDevices * @param aIt Iterator pointing to the device to detach. * @note Synchronously calls EMT. * @note Must be called from under this object's lock. /* still want a lock object because we need to leave it */ /* if the device is attached, then there must at least one USB hub. */ /* leave the lock before a VMR3* call (EMT will call us back)! */ /** @todo just do everything here and only wrap the PDMR3Usb call. That'll offload some notification stuff from the EMT thread. */ * USB device detach callback used by DetachUSBDevice(). * Note that DetachUSBDevice() doesn't return until this callback is executed, * so we don't use AutoCaller and don't care about reference counters of * interface pointers passed in. * @note Locks the console object for writing. * If that was a remote device, release the backend pointer. * The pointer was requested in usbAttachCallback. /* Remove the device from the collection */ #
endif /* VBOX_WITH_USB *//* Note: FreeBSD needs this whether netflt is used or not. */ * Helper function to handle host interface device creation and attachment. * @param networkAdapter the network adapter which attachment should be reset * @return COM status code * @note The caller must lock this object for writing. * @todo Move this back into the driver! #
endif /* VBOX_STRICT */ * Allocate a host interface device /* The name of the TAP interface we are using */ LogRel((
"No TAP device name was supplied.\n"));
rc =
setError(
E_FAIL,
tr(
"No TAP device name was supplied for the host networking interface"));
/* If we are using a static TAP device then try to open it. */ tr(
"Failed to open the host network interface %ls"),
* Here is the right place to communicate the TAP file descriptor and * the host interface name to the server if/when it becomes really tr(
"could not set up the host networking device for non blocking access: %s"),
/* will be handled by our caller */ tr(
"Could not set up the host networking device: %Rrc"),
/* The name of the TAP interface we are using */ LogRel((
"No TAP device name was supplied.\n"));
rc =
setError(
E_FAIL,
tr(
"No TAP device name was supplied for the host networking interface"));
/* If we are using a static TAP device then try to open it. */ /* will be handled by our caller */ tr(
"Failed to open the host network interface %ls"),
/* in case of failure, cleanup. */ LogRel((
"General failure attaching to host interface\n"));
tr(
"General failure attaching to host interface"));
* Helper function to handle detachment from a host interface * @param networkAdapter the network adapter which attachment should be reset * @return COM status code * @note The caller must lock this object for writing. * @todo Move this back into the driver! #
endif /* VBOX_STRICT */ /* is there an open TAP device? */ /* If the name is empty, this is a dynamic TAP device, so close it now, so that the termination script can remove the interface. Otherwise we still need the FD to pass to the termination script. */ /* If we are using a static TAP device, we close it now, after having called the /* the TAP device name and handle are no longer valid */ #
endif /* (RT_OS_LINUX || RT_OS_FREEBSD) && !VBOX_WITH_NETFLT */ * Called at power down to terminate host interface networking. * @note The caller must lock this object for writing. * host interface termination handling #
endif /* (RT_OS_LINUX || RT_OS_FREEBSD) && !VBOX_WITH_NETFLT */ * Process callback handler for VMR3LoadFromFile, VMR3LoadFromStream, VMR3Save * @param pVM The VM handle. * @param uPercent Completion percentage (0-100). * @param pvUser Pointer to an IProgress instance. /* update the progress object */ * @remarks Might be some tiny serialization concerns with access to the string /* We ignore RT_SRC_POS_DECL arguments to avoid confusion of end-users. */ /* Append to any the existing error message. */ * VM runtime error callback function. * See VMSetRuntimeError for the detailed description of parameters. * @param pVM The VM handle. * @param pvUser The user argument. * @param fFlags The action flags. See VMSETRTERR_FLAGS_*. * @param pszErrorId Error ID string. * @param pszFormat Error message format string. * @param va Error message arguments. LogRel((
"Console: VM runtime error: fatal=%RTbool, errorID=%s message=\"%s\"\n",
* Captures USB devices that match filters of the VM. * @param pVM The VM handle. * @note The caller must lock this object for writing. /* If the machine has an USB controller, ask the USB proxy service to /* leave the lock before calling Host in VBoxSVC since Host may call * us back from under its lock (e.g. onUSBDeviceAttach()) which would * produce an inter-process dead-lock otherwise. */ * Detach all USB device which are attached to the VM for the * purpose of clean up and such like. * @note The caller must lock this object for writing. /* leave the lock before calling Host in VBoxSVC since Host may call * us back from under its lock (e.g. onUSBDeviceAttach()) which would * produce an inter-process dead-lock otherwise. */ * @note Locks this object for writing. /* Console has been already uninitialized, deny request */ * Mark all existing remote USB devices as dirty. * Process the pDevList and add devices those are not already in the mRemoteUSBDevices list. /** @todo (sunlover) REMOTE_USB Strict validation of the pDevList. */ /* The cbDevList condition must be checked first, because the function can * receive pDevList = NULL and cbDevList = 0 on client disconnect. /* Sanitize incoming strings in case they aren't valid UTF-8. */ /* The device is already in the list. */ LogRel((
"Remote USB: ++++ Vendor %04X. Product %04X. Name = [%s].\n",
/* Create the device object and add the new device to list. */ /* Check if the device is ok for current USB filters. */ /// @todo (r=dmik) warning reporting subsystem * Remove dirty devices, that is those which are not reported by the server anymore. LogRel((
"Remote USB: ---- Vendor %04X. Product %04X. Name = [%ls].\n",
/* Detach the device from VM. */ /* And remove it from the list. */ * Progress cancelation callback for fault tolerance VM poweron * Thread function which starts the VM (also from saved state) and * @param Thread The thread id. * @param pvUser Pointer to a VMPowerUpTask structure. * @return VINF_SUCCESS (ignored). * @note Locks the Console object for writing. /* Set up a build identifier so that it can be seen from core dumps what * exact build was used to produce the core. */ /* Note: no need to use addCaller() because VMPowerUpTask does that */ /* The lock is also used as a signal from the task initiator (which * releases it only after RTThreadCreate()) that we can start the job */ // Create the VMM device object, which starts the HGCM thread; do this only // once for the console, for the pathological case that the same console // object is used to power up a VM twice. VirtualBox 4.0: we now do that // here instead of the Console constructor (see Console::init()) /* wait for auto reset ops to complete so that we can successfully lock * the attached hard disks by calling LockMedia() below */ * Lock attached media. This method will also check their accessibility. * If we're a teleporter, we'll have to postpone this action so we can * migrate between local processes. * Note! The media will be unlocked automatically by * SessionMachine::setMachineState() when the VM is powered down. /* Create the VRDP server. In case of headless operation, this will * also create the framebuffer, required at VM creation. /* Does VRDP server call Console from the other thread? * Not sure (and can change), so leave the lock just in case. errMsg =
Utf8StrFmt(
tr(
"VirtualBox Remote Desktop Extension server can't bind to the port: %s"),
LogRel((
"VRDE: Warning: failed to launch VRDE server (%Rrc): '%s'\n",
/* This means that the VRDE is not installed. */ LogRel((
"VRDE: VirtualBox Remote Desktop Extension is not available.\n"));
/* Fail, if the server is installed but can't start. */ /* VRDE library file is missing. */ errMsg =
Utf8StrFmt(
tr(
"Could not find the VirtualBox Remote Desktop Extension library."));
LogRel((
"VRDE: Failed: (%Rrc), error message: '%s'\n",
* leave the lock since EMT will call Console. It's safe because * mMachineState is either Starting or Restoring state here. /* Enable client connections to the server. */ * Register our load/save state file handlers * Synchronize debugger settings /* Does the code below call Console from the other thread? * Not sure, so leave the lock just in case. */ N_(
"The shared folder '%s' could not be set up: %ls.\n" "The shared folder setup will not be complete. It is recommended to power down the virtual machine and fix the shared folder settings while the machine is not running"),
rc =
S_OK;
// do not fail with broken shared folders /* enter the lock again */ /* leave the lock before a lengthy operation */ /* Power off in case we failed loading or resuming the VM */ /* Power on the FT enabled VM. */ /* Power on the VM (i.e. start executing) */ /* enter the lock again */ /* On failure, destroy the VM */ /* preserve existing error info */ /* powerDown() will call VMR3Destroy() and do all necessary * cleanup (VRDP, USB devices) */ * Deregister the VMSetError callback. This is necessary as the * pfnVMAtError() function passed to VMR3Create() is supposed to * be sticky but our error callback isn't. /** @todo register another VMSetError callback? */ * If VMR3Create() failed it has released the VM memory. /* If VMR3Create() or one of the other calls in this function fail, * an appropriate error message has been set in task->mErrorMsg. * However since that happens via a callback, the rc status code in * this function is not updated. /* If the error message is not set but we've got a failure, * convert the VBox status code into a meaningful error message. * This becomes unused once all the sources of errors set the * appropriate error message themselves. /* Set the error message as the COM error. * Progress::notifyComplete() will pick it up later. */ * 1) we failed before VMR3Create() was called; * 2) VMR3Create() failed. * In both cases, there is no need to call powerDown(), but we still * vmstateChangeCallback() for that purpose. /* preserve existing error info */ * Evaluate the final result. Note that the appropriate mMachineState value * is already set by vmstateChangeCallback() in all cases. /* leave the lock, don't need it any more */ /* Notify the progress object of the success */ /* The progress object will fetch the current error info */ LogRel((
"Power up failed (vrc=%Rrc, rc=%Rhrc (%#08X))\n",
vrc,
rc,
rc));
/* Notify VBoxSVC and any waiting openRemoteSession progress object. */ * Reconfigures a medium attachment (part of taking or deleting an online snapshot). * @param pConsole Reference to the console object. * @param pVM The VM handle. * @param lInstance The instance of the controller. * @param pcszDevice The name of the controller type. * @param enmBus The storage bus type of the controller. * @param fSetupMerge Whether to set up a medium merge * @param uMergeSource Merge source image index * @param uMergeTarget Merge target image index * @param aMediumAtt The medium attachment. * @param aMachineState The current machine state. * @param phrc Where to store com error - only valid if we return VERR_GENERAL_FAILURE. * @return VBox status code. /* Ignore attachments other than hard disks, since at the moment they are * not subject to snapshotting in general. */ /* Determine the base path for the device instance. */ /* Update the device instance configuration. */ true /* fAttachDetach */,
false /* fForceUnmount */,
NULL /* paLedDevType */);
/** @todo this dumps everything attached to this device instance, which * is more than necessary. Dumping the changed LUN would be enough. */ * Progress cancelation callback employed by Console::fntTakeSnapshotWorker. * Worker thread created by Console::TakeSnapshot. * @param Thread The current thread (ignored). * @param pvUser The task. * @return VINF_SUCCESS (ignored). // taking a snapshot consists of the following: // 1) creating a diff image for each virtual hard disk, into which write operations go after // the snapshot has been created (done in VBoxSVC, in SessionMachine::BeginTakingSnapshot) // 2) creating a Snapshot object with the state of the machine (hardware + storage, // done in VBoxSVC, also in SessionMachine::BeginTakingSnapshot) // 3) saving the state of the virtual machine (here, in the VM process, if the machine is online) * request creating the diff images on the server and create the snapshot object * (this will set the machine state to Saving on the server to block * others from accessing this machine) * state file is non-null only when the VM is paused * (i.e. creating a snapshot online) /* sync the state with the server */ // STEP 3: save the VM state (if online) pTask->
ulMemSize);
// operation weight, same as computed when setting up progress object true /*fContinueAfterwards*/,
tr(
"Failed to save the machine state to '%s' (%Rrc)"),
// STEP 4: reattach hard disks LogFlowFunc((
"Reattaching new differencing hard disks...\n"));
1);
// operation weight, same as computed when setting up progress object * We can't pass a storage controller object directly * (g++ complains about not being able to pass non POD types through '...') * so we have to query needed values here and pass them. * don't leave the lock since reconfigureMediumAttachment * isn't going to need the Console lock. * finalize the requested snapshot object. * This will reset the machine state to the state it had right * before calling mControl->BeginTakingSnapshot(). // do not throw rc here because we can't call EndTakingSnapshot() twice /* preserve existing error info */ if (
FAILED(
rc))
/* Must come before calling setMachineState. */ * Fix up the machine state. * For live snapshots we do all the work, for the two other variations we * just update the local copy. /** @todo this could probably be made more generic and reused elsewhere. */ /* paranoid cleanup on for a failed online snapshot. */ /*else: somebody else has change the state... Leave it. */ /* check the remote state to see that we got it right. */ if (
SUCCEEDED(
rc))
/* The failure cases are handled above. */ * Thread for executing the saved state operation. * @param Thread The thread handle. * @param pvUser Pointer to a VMSaveTask structure. * @return VINF_SUCCESS (ignored). * @note Locks the Console object for writing. false,
/*fContinueAfterwards*/ /* lock the console once we're going to access it */ /* synchronize the state with the server */ * The machine has been successfully saved, so power it down * (vmstateChangeCallback() will set state to Saved on success). * Note: we release the task's VM caller, otherwise it will * Finalize the requested save state procedure. In case of failure it will * reset the machine state to the state it had right before calling * mControl->BeginSavingState(). This must be the last thing because it * will set the progress to completed, and that means that the frontend * can immediately uninit the associated console object. * Thread for powering down the Console. * @param Thread The thread handle. * @param pvUser Pointer to the VMTask structure. * @return VINF_SUCCESS (ignored). * @note Locks the Console object for writing. /* Note: no need to use addCaller() to protect Console because VMTask does /* wait until the method tat started us returns */ /* release VM caller to avoid the powerDown() deadlock */ /* complete the operation */ * @interface_method_impl{VMM2USERMETHODS,pfnSaveState} * For now, just call SaveState. We should probably try notify the GUI so * it can pop up a progress object and stuff. * @interface_method_impl{VMM2USERMETHODS,pfnNotifyEmtInit} * @interface_method_impl{VMM2USERMETHODS,pfnNotifyEmtTerm} * @interface_method_impl{VMM2USERMETHODS,pfnNotifyPdmtInit} * @interface_method_impl{VMM2USERMETHODS,pfnNotifyPdmtTerm} * The Main status driver instance data. /** The LED connectors. */ /** Pointer to the LED ports interface above us. */ /** Pointer to the array of LED pointers. */ /** The unit number corresponding to the first entry in the LED array. */ /** The unit number corresponding to the last entry in the LED array. * (The size of the LED array is iLastLUN - iFirstLUN + 1.) */ /** Pointer to the driver instance. */ /** The Media Notify interface. */ /** Map for translating PDM storage controller/LUN information to * IMediumAttachment references. */ /** Device name+instance for mapping */ /** Pointer to the Console object, for driver triggered activities. */ * Notification about a unit which have been changed. * The driver must discard any pointers to data owned by * the unit and requery it. * @param pInterface Pointer to the interface structure containing the called function pointer. * @param iLUN The unit number. Log((
"drvStatus_UnitChanged: iLUN=%d pLed=%p\n",
iLUN,
pLed));
* Notification about a medium eject. * @param pInterface Pointer to the interface structure containing the called function pointer. * @param uLUN The unit number. * @interface_method_impl{PDMIBASE,pfnQueryInterface} * Destruct a status driver instance. * @param pDrvIns The driver instance data. * Construct a status driver instance. * @copydoc FNPDMDRVCONSTRUCT * Validate configuration. (
"Configuration error: Not possible to attach anything to this driver!\n"),
AssertMsgFailed((
"Configuration error: Failed to query the \"papLeds\" value! rc=%Rrc\n",
rc));
AssertMsgFailed((
"Configuration error: Failed to query the \"pmapMediumAttachments\" value! rc=%Rrc\n",
rc));
AssertMsgFailed((
"Configuration error: Failed to query the \"DeviceInstance\" value! rc=%Rrc\n",
rc));
AssertMsgFailed((
"Configuration error: Failed to query the \"pConsole\" value! rc=%Rrc\n",
rc));
AssertMsgFailed((
"Configuration error: Failed to query the \"First\" value! rc=%Rrc\n",
rc));
AssertMsgFailed((
"Configuration error: Failed to query the \"Last\" value! rc=%Rrc\n",
rc));
* Get the ILedPorts interface of the above driver/device and * query the LEDs we want. * Console status driver (LED) registration record. "Main status driver (Main as in the API).",
/* vi: set tabstop=4 shiftwidth=4 expandtab: */