VirtualBox

Ignore:
Timestamp:
Nov 4, 2008 9:46:13 AM (16 years ago)
Author:
vboxsync
Message:

Recommitted r38734: Guest Properties (HostServices and Main): major clean up of the guest property service

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r13762 r13779  
    9696#include <algorithm>
    9797#include <memory> // for auto_ptr
     98#include <vector>
    9899
    99100
     
    10621063            rc = VERR_UNRESOLVED_ERROR;  /** @todo translate error code */
    10631064    return rc;
     1065}
     1066
     1067HRESULT Console::doEnumerateGuestProperties (INPTR BSTR aPatterns,
     1068                                             ComSafeArrayOut(BSTR, aNames),
     1069                                             ComSafeArrayOut(BSTR, aValues),
     1070                                             ComSafeArrayOut(ULONG64, aTimestamps),
     1071                                             ComSafeArrayOut(BSTR, aFlags))
     1072{
     1073    using namespace guestProp;
     1074
     1075    VBOXHGCMSVCPARM parm[3];
     1076
     1077    Utf8Str utf8Patterns(aPatterns);
     1078    parm[0].type = VBOX_HGCM_SVC_PARM_PTR;
     1079    parm[0].u.pointer.addr = utf8Patterns.mutableRaw();
     1080    parm[0].u.pointer.size = utf8Patterns.length() + 1;
     1081
     1082    /*
     1083     * Now things get slightly complicated.  Due to a race with the guest adding
     1084     * properties, there is no good way to know how much large a buffer to provide
     1085     * the service to enumerate into.  We choose a decent starting size and loop a
     1086     * few times, each time retrying with the size suggested by the service plus
     1087     * one Kb.
     1088     */
     1089    size_t cchBuf = 4096;
     1090    Utf8Str Utf8Buf;
     1091    int vrc = VERR_BUFFER_OVERFLOW;
     1092    for (unsigned i = 0; i < 10 && (VERR_BUFFER_OVERFLOW == vrc); ++i)
     1093    {
     1094        Utf8Buf.alloc(cchBuf + 1024);
     1095        if (Utf8Buf.isNull())
     1096            return E_OUTOFMEMORY;
     1097        parm[1].type = VBOX_HGCM_SVC_PARM_PTR;
     1098        parm[1].u.pointer.addr = Utf8Buf.mutableRaw();
     1099        parm[1].u.pointer.size = cchBuf + 1024;
     1100        vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", ENUM_PROPS_HOST, 3,
     1101                                     &parm[0]);
     1102        if (parm[2].type != VBOX_HGCM_SVC_PARM_32BIT)
     1103            return setError (E_FAIL, tr ("Internal application error"));
     1104        cchBuf = parm[2].u.uint32;
     1105    }
     1106    if (VERR_BUFFER_OVERFLOW == vrc)
     1107        return setError (E_UNEXPECTED, tr ("Temporary failure due to guest activity, please retry"));
     1108
     1109    /*
     1110     * Finally we have to unpack the data returned by the service into the safe
     1111     * arrays supplied by the caller.  We start by counting the number of entries.
     1112     */
     1113    const char *pszBuf
     1114        = reinterpret_cast<const char *>(parm[1].u.pointer.addr);
     1115    unsigned cEntries = 0;
     1116    /* The list is terminated by a zero-length string at the end of a set
     1117     * of four strings. */
     1118    for (size_t i = 0; strlen(pszBuf + i) != 0; )
     1119    {
     1120       /* We are counting sets of four strings. */
     1121       for (unsigned j = 0; j < 4; ++j)
     1122           i += strlen(pszBuf + i) + 1;
     1123       ++cEntries;
     1124    }
     1125
     1126    /*
     1127     * And now we create the COM safe arrays and fill them in.
     1128     */
     1129    com::SafeArray <BSTR> names(cEntries);
     1130    com::SafeArray <BSTR> values(cEntries);
     1131    com::SafeArray <ULONG64> timestamps(cEntries);
     1132    com::SafeArray <BSTR> flags(cEntries);
     1133    size_t iBuf = 0;
     1134    /* Rely on the service to have formated the data correctly. */
     1135    for (unsigned i = 0; i < cEntries; ++i)
     1136    {
     1137        size_t cchName = strlen(pszBuf + iBuf);
     1138        Bstr(pszBuf + iBuf).detachTo(&names[i]);
     1139        iBuf += cchName + 1;
     1140        size_t cchValue = strlen(pszBuf + iBuf);
     1141        Bstr(pszBuf + iBuf).detachTo(&values[i]);
     1142        iBuf += cchValue + 1;
     1143        size_t cchTimestamp = strlen(pszBuf + iBuf);
     1144        timestamps[i] = RTStrToUInt64(pszBuf + iBuf);
     1145        iBuf += cchTimestamp + 1;
     1146        size_t cchFlags = strlen(pszBuf + iBuf);
     1147        Bstr(pszBuf + iBuf).detachTo(&flags[i]);
     1148        iBuf += cchFlags + 1;
     1149    }
     1150    names.detachTo(ComSafeArrayOutArg (aNames));
     1151    values.detachTo(ComSafeArrayOutArg (aValues));
     1152    timestamps.detachTo(ComSafeArrayOutArg (aTimestamps));
     1153    flags.detachTo(ComSafeArrayOutArg (aFlags));
     1154    return S_OK;
    10641155}
    10651156#endif
     
    36873778     * autoVMCaller, so there is no need to hold a lock of this */
    36883779
    3689     using namespace guestProp;
    3690 
    3691     VBOXHGCMSVCPARM parm[3];
    3692 
    3693     Utf8Str utf8Patterns(aPatterns);
    3694     parm[0].type = VBOX_HGCM_SVC_PARM_PTR;
    3695     parm[0].u.pointer.addr = utf8Patterns.mutableRaw();
    3696     parm[0].u.pointer.size = utf8Patterns.length() + 1;
    3697 
    3698     /*
    3699      * Now things get slightly complicated.  Due to a race with the guest adding
    3700      * properties, there is no good way to know how much large a buffer to provide
    3701      * the service to enumerate into.  We choose a decent starting size and loop a
    3702      * few times, each time retrying with the size suggested by the service plus
    3703      * one Kb.
    3704      */
    3705     size_t cchBuf = 4096;
    3706     Utf8Str Utf8Buf;
    3707     int vrc = VERR_BUFFER_OVERFLOW;
    3708     for (unsigned i = 0; i < 10 && (VERR_BUFFER_OVERFLOW == vrc); ++i)
    3709     {
    3710         Utf8Buf.alloc(cchBuf + 1024);
    3711         if (Utf8Buf.isNull())
    3712             return E_OUTOFMEMORY;
    3713         parm[1].type = VBOX_HGCM_SVC_PARM_PTR;
    3714         parm[1].u.pointer.addr = Utf8Buf.mutableRaw();
    3715         parm[1].u.pointer.size = cchBuf + 1024;
    3716         vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", ENUM_PROPS_HOST, 3,
    3717                                      &parm[0]);
    3718         if (parm[2].type != VBOX_HGCM_SVC_PARM_32BIT)
    3719             return setError (E_FAIL, tr ("Internal application error"));
    3720         cchBuf = parm[2].u.uint32;
    3721     }
    3722     if (VERR_BUFFER_OVERFLOW == vrc)
    3723         return setError (E_UNEXPECTED, tr ("Temporary failure due to guest activity, please retry"));
    3724 
    3725     /*
    3726      * Finally we have to unpack the data returned by the service into the safe
    3727      * arrays supplied by the caller.  We start by counting the number of entries.
    3728      */
    3729     const char *pszBuf
    3730         = reinterpret_cast<const char *>(parm[1].u.pointer.addr);
    3731     unsigned cEntries = 0;
    3732     /* The list is terminated by a zero-length string at the end of a set
    3733      * of four strings. */
    3734     for (size_t i = 0; strlen(pszBuf + i) != 0; )
    3735     {
    3736        /* We are counting sets of four strings. */
    3737        for (unsigned j = 0; j < 4; ++j)
    3738            i += strlen(pszBuf + i) + 1;
    3739        ++cEntries;
    3740     }
    3741 
    3742     /*
    3743      * And now we create the COM safe arrays and fill them in.
    3744      */
    3745     com::SafeArray <BSTR> names(cEntries);
    3746     com::SafeArray <BSTR> values(cEntries);
    3747     com::SafeArray <ULONG64> timestamps(cEntries);
    3748     com::SafeArray <BSTR> flags(cEntries);
    3749     size_t iBuf = 0;
    3750     /* Rely on the service to have formated the data correctly. */
    3751     for (unsigned i = 0; i < cEntries; ++i)
    3752     {
    3753         size_t cchName = strlen(pszBuf + iBuf);
    3754         Bstr(pszBuf + iBuf).detachTo(&names[i]);
    3755         iBuf += cchName + 1;
    3756         size_t cchValue = strlen(pszBuf + iBuf);
    3757         Bstr(pszBuf + iBuf).detachTo(&values[i]);
    3758         iBuf += cchValue + 1;
    3759         size_t cchTimestamp = strlen(pszBuf + iBuf);
    3760         timestamps[i] = RTStrToUInt64(pszBuf + iBuf);
    3761         iBuf += cchTimestamp + 1;
    3762         size_t cchFlags = strlen(pszBuf + iBuf);
    3763         Bstr(pszBuf + iBuf).detachTo(&flags[i]);
    3764         iBuf += cchFlags + 1;
    3765     }
    3766     names.detachTo(ComSafeArrayOutArg (aNames));
    3767     values.detachTo(ComSafeArrayOutArg (aValues));
    3768     timestamps.detachTo(ComSafeArrayOutArg (aTimestamps));
    3769     flags.detachTo(ComSafeArrayOutArg (aFlags));
    3770     return S_OK;
     3780    return doEnumerateGuestProperties (aPatterns, ComSafeArrayOutArg(aNames),
     3781                                       ComSafeArrayOutArg(aValues),
     3782                                       ComSafeArrayOutArg(aTimestamps),
     3783                                       ComSafeArrayOutArg(aFlags));
    37713784#endif /* else !defined (VBOX_WITH_GUEST_PROPS) */
    37723785}
     
    46334646#ifdef VBOX_WITH_HGCM
    46344647
     4648# ifdef VBOX_WITH_GUEST_PROPS
     4649
     4650    /* Save all guest property store entries to the machine XML file */
     4651    com::SafeArray <BSTR> namesOut;
     4652    com::SafeArray <BSTR> valuesOut;
     4653    com::SafeArray <ULONG64> timestampsOut;
     4654    com::SafeArray <BSTR> flagsOut;
     4655    Bstr pattern("");
     4656    if (pattern.isNull())
     4657        rc = E_OUTOFMEMORY;
     4658    else
     4659        rc = doEnumerateGuestProperties (Bstr (""), ComSafeArrayAsOutParam (namesOut),
     4660                                        ComSafeArrayAsOutParam (valuesOut),
     4661                                        ComSafeArrayAsOutParam (timestampsOut),
     4662                                        ComSafeArrayAsOutParam (flagsOut));
     4663    if (SUCCEEDED(rc))
     4664    {
     4665        try
     4666        {
     4667            std::vector <BSTR> names;
     4668            std::vector <BSTR> values;
     4669            std::vector <ULONG64> timestamps;
     4670            std::vector <BSTR> flags;
     4671            for (unsigned i = 0; i < namesOut.size(); ++i)
     4672            {
     4673                uint32_t fFlags;
     4674                guestProp::validateFlags (Utf8Str(flagsOut[i]).raw(), &fFlags);
     4675                if (   !( fFlags & guestProp::TRANSIENT)
     4676                    || (mMachineState == MachineState_Saving)
     4677                  )
     4678                {
     4679                    names.push_back(namesOut[i]);
     4680                    values.push_back(valuesOut[i]);
     4681                    timestamps.push_back(timestampsOut[i]);
     4682                    flags.push_back(flagsOut[i]);
     4683                }
     4684            }
     4685            com::SafeArray <BSTR> namesIn (names);
     4686            com::SafeArray <BSTR> valuesIn (values);
     4687            com::SafeArray <ULONG64> timestampsIn (timestamps);
     4688            com::SafeArray <BSTR> flagsIn (flags);
     4689            if (   namesIn.isNull()
     4690                || valuesIn.isNull()
     4691                || timestampsIn.isNull()
     4692                || flagsIn.isNull()
     4693                )
     4694                throw std::bad_alloc();
     4695            /* PushGuestProperties() calls DiscardSettings(), which calls us back */
     4696            alock.leave();
     4697            mControl->PushGuestProperties (ComSafeArrayAsInParam (namesIn),
     4698                                          ComSafeArrayAsInParam (valuesIn),
     4699                                          ComSafeArrayAsInParam (timestampsIn),
     4700                                          ComSafeArrayAsInParam (flagsIn));
     4701            alock.enter();
     4702        }
     4703        catch (std::bad_alloc)
     4704        {
     4705            rc = E_OUTOFMEMORY;
     4706        }
     4707    }
     4708
     4709    /* advance percent count */
     4710    if (aProgress)
     4711        aProgress->notifyProgress (99 * (++ step) / StepCount );
     4712
     4713# endif /* VBOX_WITH_GUEST_PROPS defined */
     4714
    46354715    /* Shutdown HGCM services before stopping the guest, because they might
    46364716     * need a cleanup. */
     
    46504730    if (aProgress)
    46514731        aProgress->notifyProgress (99 * (++ step) / StepCount );
    4652 
    4653 # ifdef VBOX_WITH_GUEST_PROPS
    4654 
    4655     /* Save all guest property store entries to the machine XML file */
    4656     PCFGMNODE pValues = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Values/");
    4657     PCFGMNODE pTimestamps = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Timestamps/");
    4658     PCFGMNODE pFlags = CFGMR3GetChild (CFGMR3GetRoot (mpVM), "GuestProps/Flags/");
    4659 
    4660     /* Count the number of entries we have */
    4661     unsigned cValues = 0;
    4662     PCFGMLEAF pValue;
    4663     for (pValue = CFGMR3GetFirstValue (pValues); pValue != NULL;
    4664          pValue = CFGMR3GetNextValue (pValue))
    4665     {
    4666         char szPropName[guestProp::MAX_NAME_LEN];
    4667         vrc = CFGMR3GetValueName (pValue, szPropName, sizeof(szPropName));
    4668         if (RT_SUCCESS(vrc))
    4669         {
    4670             /* Do not send transient properties unless we are saving state */
    4671             uint32_t fFlags = guestProp::NILFLAG;
    4672             CFGMR3QueryU32 (pFlags, szPropName, &fFlags);
    4673             if (!(fFlags & guestProp::TRANSIENT) ||
    4674                 (mMachineState == MachineState_Saving))
    4675                 ++cValues;
    4676         }
    4677     }
    4678 
    4679     /* And pack them into safe arrays */
    4680     com::SafeArray <BSTR> names(cValues);
    4681     com::SafeArray <BSTR> values(cValues);
    4682     com::SafeArray <ULONG64> timestamps(cValues);
    4683     com::SafeArray <BSTR> flags(cValues);
    4684     pValue = CFGMR3GetFirstValue (pValues);
    4685 
    4686     vrc = VINF_SUCCESS;
    4687     unsigned iProp = 0;
    4688     while (pValue != NULL && RT_SUCCESS (vrc))
    4689     {
    4690         using namespace guestProp;
    4691 
    4692         char szPropName [MAX_NAME_LEN];
    4693         char szPropValue [MAX_VALUE_LEN];
    4694         char szPropFlags [MAX_FLAGS_LEN];
    4695         ULONG64 u64Timestamp = 0;  /* default */
    4696         vrc = CFGMR3GetValueName (pValue, szPropName, sizeof (szPropName));
    4697         if (RT_SUCCESS(vrc))
    4698             vrc = CFGMR3QueryString (pValues, szPropName, szPropValue,
    4699                                      sizeof (szPropValue));
    4700         if (RT_SUCCESS(vrc))
    4701         {
    4702             uint32_t fFlags = NILFLAG;
    4703             CFGMR3QueryU32 (pFlags, szPropName, &fFlags);
    4704             /* Skip transient properties unless we are saving state */
    4705             if (!(fFlags & TRANSIENT) ||
    4706                 (mMachineState == MachineState_Saving))
    4707             {
    4708                 writeFlags(fFlags, szPropFlags);
    4709                 CFGMR3QueryU64 (pTimestamps, szPropName, &u64Timestamp);
    4710                 Bstr(szPropName).cloneTo(&names[iProp]);
    4711                 Bstr(szPropValue).cloneTo(&values[iProp]);
    4712                 timestamps[iProp] = u64Timestamp;
    4713                 Bstr(szPropFlags).cloneTo(&flags[iProp]);
    4714                 ++iProp;
    4715                 if (iProp >= cValues)
    4716                     vrc = VERR_TOO_MUCH_DATA;
    4717             }
    4718             pValue = CFGMR3GetNextValue (pValue);
    4719         }
    4720     }
    4721 
    4722     if (RT_SUCCESS(vrc) || (VERR_TOO_MUCH_DATA == vrc))
    4723     {
    4724         /* PushGuestProperties() calls DiscardSettings(), which calls us back */
    4725         alock.leave();
    4726         mControl->PushGuestProperties (ComSafeArrayAsInParam (names),
    4727                                        ComSafeArrayAsInParam (values),
    4728                                        ComSafeArrayAsInParam (timestamps),
    4729                                        ComSafeArrayAsInParam (flags));
    4730         alock.enter();
    4731     }
    4732 
    4733     /* advance percent count */
    4734     if (aProgress)
    4735         aProgress->notifyProgress (99 * (++ step) / StepCount );
    4736 
    4737 # endif /* VBOX_WITH_GUEST_PROPS defined */
    47384732
    47394733#endif /* VBOX_WITH_HGCM */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette