b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync/* $Id$ */
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync/** @file
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync * VBoxAutostart - VirtualBox Autostart service, stop machines during system shutdown.
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync */
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync/*
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync * Copyright (C) 2012 Oracle Corporation
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync *
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync * available from http://www.virtualbox.org. This file is free software;
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync * General Public License (GPL) as published by the Free Software
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync */
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <VBox/com/com.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <VBox/com/string.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <VBox/com/Guid.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <VBox/com/array.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <VBox/com/ErrorInfo.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <VBox/com/errorprint.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <iprt/thread.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <iprt/stream.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <iprt/log.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <iprt/assert.h>
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync#include <iprt/message.h>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <algorithm>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <list>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include <string>
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync#include "VBoxAutostart.h"
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsyncusing namespace com;
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync/**
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync * VM list entry.
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsynctypedef struct AUTOSTOPVM
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync{
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /** ID of the VM to start. */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync Bstr strId;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /** Action to do with the VM. */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync AutostopType_T enmAutostopType;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync} AUTOSTOPVM;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsyncstatic HRESULT autostartSaveVMState(ComPtr<IConsole> &console)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync{
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync HRESULT rc = S_OK;
7ffe7543b32c5dfd3aede1d7f2c1332c7508f6ccvboxsync ComPtr<IMachine> machine;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync ComPtr<IProgress> progress;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync do
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /* first pause so we don't trigger a live save which needs more time/resources */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync bool fPaused = false;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync rc = console->Pause();
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (FAILED(rc))
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync bool fError = true;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (rc == VBOX_E_INVALID_VM_STATE)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /* check if we are already paused */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync MachineState_T machineState;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /* the error code was lost by the previous instruction */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync rc = VBOX_E_INVALID_VM_STATE;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (machineState != MachineState_Paused)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync RTMsgError("Machine in invalid state %d -- %s\n",
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync machineState, machineStateToName(machineState, false));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync else
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync fError = false;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync fPaused = true;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (fError)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync break;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
7ffe7543b32c5dfd3aede1d7f2c1332c7508f6ccvboxsync CHECK_ERROR(console, COMGETTER(Machine)(machine.asOutParam()));
7ffe7543b32c5dfd3aede1d7f2c1332c7508f6ccvboxsync CHECK_ERROR(machine, SaveState(progress.asOutParam()));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (FAILED(rc))
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (!fPaused)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync console->Resume();
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync break;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync rc = showProgress(progress);
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_PROGRESS_ERROR(progress, ("Failed to save machine state"));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (FAILED(rc))
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (!fPaused)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync console->Resume();
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync } while (0);
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync return rc;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync}
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
91b827c98a305956e75cb1618af6ae17e450fb88vboxsyncDECLHIDDEN(RTEXITCODE) autostartStopMain(PCFGAST pCfgAst)
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync{
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync int vrc = VINF_SUCCESS;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync std::list<AUTOSTOPVM> listVM;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /*
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync * Build a list of all VMs we need to autostop first, apply the overrides
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync * from the configuration and start the VMs afterwards.
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync com::SafeIfaceArray<IMachine> machines;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync HRESULT rc = g_pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (SUCCEEDED(rc))
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /*
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync * Iterate through the collection and construct a list of machines
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync * we have to check.
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync for (size_t i = 0; i < machines.size(); ++i)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (machines[i])
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync BOOL fAccessible;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible)(&fAccessible));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (!fAccessible)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync continue;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync AutostopType_T enmAutostopType;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostopType)(&enmAutostopType));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if (enmAutostopType != AutostopType_Disabled)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync AUTOSTOPVM autostopVM;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(machines[i], COMGETTER(Id)(autostopVM.strId.asOutParam()));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync autostopVM.enmAutostopType = enmAutostopType;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync listVM.push_back(autostopVM);
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if ( SUCCEEDED(rc)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync && listVM.size())
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync std::list<AUTOSTOPVM>::iterator it;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync for (it = listVM.begin(); it != listVM.end(); it++)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync MachineState_T enmMachineState;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync ComPtr<IMachine> machine;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(g_pVirtualBox, FindMachine((*it).strId.raw(),
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync machine.asOutParam()));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(machine, COMGETTER(State)(&enmMachineState));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync /* Wait until the VM changes from a transient state back. */
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync while ( enmMachineState >= MachineState_FirstTransient
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync && enmMachineState <= MachineState_LastTransient)
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync {
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync RTThreadSleep(1000);
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync CHECK_ERROR_BREAK(machine, COMGETTER(State)(&enmMachineState));
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync }
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /* Only power off running machines. */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync if ( enmMachineState == MachineState_Running
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync || enmMachineState == MachineState_Paused)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync ComPtr<IConsole> console;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync ComPtr<IProgress> progress;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /* open a session for the VM */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(machine, LockMachine(g_pSession, LockType_Shared));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /* get the associated console */
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(g_pSession, COMGETTER(Console)(console.asOutParam()));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync switch ((*it).enmAutostopType)
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync case AutostopType_SaveState:
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync rc = autostartSaveVMState(console);
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync break;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync case AutostopType_PowerOff:
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync rc = showProgress(progress);
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_PROGRESS_ERROR(progress, ("Failed to power off machine"));
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync break;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync case AutostopType_AcpiShutdown:
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync BOOL fGuestEnteredACPI = false;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(console, GetGuestEnteredACPIMode(&fGuestEnteredACPI));
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync if (fGuestEnteredACPI && enmMachineState == MachineState_Running)
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync CHECK_ERROR_BREAK(console, PowerButton());
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync
b6013430932520fe58eba109db1dfce66a7cad88vboxsync autostartSvcLogInfo("Waiting for VM \"%ls\" to power off...\n", (*it).strId.raw());
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync do
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync {
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync RTThreadSleep(1000);
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync CHECK_ERROR_BREAK(machine, COMGETTER(State)(&enmMachineState));
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync } while (enmMachineState == MachineState_Running);
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync else
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync {
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync /* Use save state instead and log this to the console. */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync autostartSvcLogWarning("The guest of VM \"%ls\" does not support ACPI shutdown or is currently paused, saving state...\n",
b6013430932520fe58eba109db1dfce66a7cad88vboxsync (*it).strId.raw());
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync rc = autostartSaveVMState(console);
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync break;
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync default:
b6013430932520fe58eba109db1dfce66a7cad88vboxsync autostartSvcLogWarning("Unknown autostop type for VM \"%ls\"\n", (*it).strId.raw());
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
0073ab680739b243ea5b24de5e7d016ee87bab94vboxsync g_pSession->UnlockMachine();
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
60a1f1bab21018ee6d72ab23895e5f78d40db90dvboxsync }
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync return rcExit;
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync}
b56ca3f25c9c141f3c0855b656f8f64bbfa19496vboxsync