VirtualBox

Ignore:
Timestamp:
Oct 21, 2008 1:03:49 PM (16 years ago)
Author:
vboxsync
Message:

Main (Guest Properties): added host-side callbacks

File:
1 edited

Legend:

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

    r13431 r13436  
    16831683
    16841684    return S_OK;
     1685}
     1686
     1687STDMETHODIMP
     1688Machine::COMGETTER(GuestPropertyNotificationPatterns) (BSTR *aPatterns)
     1689{
     1690    if (!aPatterns)
     1691        return E_POINTER;
     1692
     1693    AutoCaller autoCaller (this);
     1694    CheckComRCReturnRC (autoCaller.rc());
     1695
     1696    AutoReadLock alock (this);
     1697
     1698    mHWData->mGuestPropertyNotificationPatterns.cloneTo (aPatterns);
     1699
     1700    return RT_LIKELY(aPatterns != NULL) ? S_OK : E_OUTOFMEMORY;
     1701}
     1702
     1703STDMETHODIMP
     1704Machine::COMSETTER(GuestPropertyNotificationPatterns) (INPTR BSTR aPatterns)
     1705{
     1706    AssertLogRelReturn (VALID_PTR(aPatterns), E_POINTER);
     1707    AutoCaller autoCaller (this);
     1708    CheckComRCReturnRC (autoCaller.rc());
     1709
     1710    AutoWriteLock alock (this);
     1711
     1712    HRESULT rc = checkStateDependency (MutableStateDep);
     1713    CheckComRCReturnRC (rc);
     1714
     1715    mHWData.backup();
     1716    mHWData->mGuestPropertyNotificationPatterns = aPatterns;
     1717
     1718    return RT_LIKELY(!mHWData->mGuestPropertyNotificationPatterns.isNull())
     1719               ? S_OK : E_OUTOFMEMORY;
    16851720}
    16861721
     
    27942829}
    27952830
     2831/**
     2832 * Matches a sample name against a pattern.
     2833 *
     2834 * @returns True if matches, false if not.
     2835 * @param   pszPat      Pattern.
     2836 * @param   cchPat      Number of characters in pszPat
     2837 * @param   pszName     Name to match against the pattern.
     2838 * @todo move this into IPRT
     2839 */
     2840static bool matchesSinglePatternEx(const char *pszPat, size_t cchPat, const char *pszName)
     2841{
     2842    size_t iPat = 0;
     2843    /* ASSUMES ASCII */
     2844    for (;;)
     2845    {
     2846        char chPat = pszPat[iPat];
     2847        switch (chPat)
     2848        {
     2849            default:
     2850                if (*pszName != chPat)
     2851                    return false;
     2852                break;
     2853
     2854            case '*':
     2855            {
     2856                while (   ((chPat = pszPat[++iPat]) == '*' || chPat == '?')
     2857                       && (iPat < cchPat)
     2858                      )
     2859                    /* nothing */;
     2860
     2861                for (;;)
     2862                {
     2863                    char ch = *pszName++;
     2864                    if (    ch == chPat
     2865                        &&  (   !chPat
     2866                             || matchesSinglePatternEx(pszPat + iPat + 1,
     2867                                                       cchPat - iPat - 1, pszName)
     2868                            )
     2869                       )
     2870                        return true;
     2871                    if (!ch)
     2872                        return false;
     2873                }
     2874                /* won't ever get here */
     2875                break;
     2876            }
     2877
     2878            case '?':
     2879                if (!*pszName)
     2880                    return false;
     2881                break;
     2882
     2883            case '\0':
     2884                return !*pszName;
     2885        }
     2886        pszName++;
     2887        pszPat++;
     2888        if (iPat == cchPat)
     2889            return !*pszName;
     2890    }
     2891    return true;
     2892}
     2893
     2894/* Checks to see if a pattern matches a name. */
     2895static bool matchesSinglePattern(const char *pszPat, const char *pszName)
     2896{
     2897    return matchesSinglePatternEx(pszPat, strlen(pszPat), pszName);
     2898}
     2899
     2900/* Checks to see if the given string matches against one of the patterns in
     2901 * the list. */
     2902static bool matchesPattern(const char *paszPatterns, size_t cchPatterns,
     2903                           const char *pszString)
     2904{
     2905    size_t iOffs = 0;
     2906    /* If the first pattern in the list is empty, treat it as "match all". */
     2907    bool matched = (cchPatterns > 0) && (0 == *paszPatterns) ? true : false;
     2908    while ((iOffs < cchPatterns) && !matched)
     2909    {
     2910        size_t cchCurrent;
     2911        if (   RT_SUCCESS(RTStrNLenEx(paszPatterns + iOffs,
     2912                                      cchPatterns - iOffs, &cchCurrent))
     2913            && (cchCurrent > 0)
     2914           )
     2915        {
     2916            matched = matchesSinglePattern(paszPatterns + iOffs, pszString);
     2917            iOffs += cchCurrent + 1;
     2918        }
     2919        else
     2920            iOffs = cchPatterns;
     2921    }
     2922    return matched;
     2923}
     2924
     2925/* Checks to see if the given string matches against one of the patterns in
     2926 * the comma-separated list.  Note that spaces at the beginning of patterns
     2927 * are ignored - '?' should be used here if that is really needed. */
     2928static bool matchesPatternComma(const char *pcszPatterns, const char *pcszString)
     2929{
     2930    AssertPtr(pcszPatterns);
     2931    const char *pcszCur = pcszPatterns;
     2932    /* If list is empty, treat it as "match all". */
     2933    bool matched = (0 == *pcszPatterns) ? true : false;
     2934    bool done = false;
     2935    while (!done && !matched)
     2936    {
     2937        const char *pcszNext = strchr(pcszCur, ',');
     2938        if (pcszNext != NULL)
     2939        {
     2940            matched = matchesSinglePatternEx(pcszCur, pcszNext - pcszCur, pcszString);
     2941            pcszCur = pcszNext;
     2942            while ((',' == *pcszCur) || (' ' == *pcszCur))
     2943                ++pcszCur;
     2944        }
     2945        else
     2946        {
     2947            matched = matchesSinglePattern(pcszCur, pcszString);
     2948            done = true;
     2949        }
     2950    }
     2951    return matched;
     2952}
     2953
    27962954STDMETHODIMP Machine::SetGuestProperty (INPTR BSTR aName, INPTR BSTR aValue, INPTR BSTR aFlags)
    27972955{
     
    28072965    if ((aFlags != NULL) && !VALID_PTR (aFlags))
    28082966        return E_INVALIDARG;
     2967
     2968    Utf8Str utf8Name(aName);
     2969    Utf8Str utf8Flags(aFlags);
     2970    Utf8Str utf8Patterns(mHWData->mGuestPropertyNotificationPatterns);
     2971    if (   utf8Name.isNull()
     2972        || ((aFlags != NULL) && utf8Flags.isNull())
     2973        || utf8Patterns.isNull()
     2974       )
     2975        return E_OUTOFMEMORY;
     2976
    28092977    uint32_t fFlags = NILFLAG;
    2810     if ((aFlags != NULL) && RT_FAILURE (validateFlags (Utf8Str(aFlags).raw(), &fFlags)))
     2978    if ((aFlags != NULL) && RT_FAILURE (validateFlags (utf8Flags.raw(), &fFlags))
     2979       )
    28112980        return setError (E_INVALIDARG, tr ("Invalid flag values: '%ls'"),
    28122981                aFlags);
     
    28883057                                                 &dummy, &dummy64, &dummy);
    28893058    }
     3059    if (SUCCEEDED (rc) && matchesPatternComma (utf8Patterns.raw(), utf8Name.raw()))
     3060        mParent->onGuestPropertyChange (mData->mUuid, aName, aValue, aFlags);
    28903061    return rc;
    28913062#endif /* else !defined (VBOX_WITH_GUEST_PROPS) */
     
    28953066{
    28963067    return SetGuestProperty(aName, aValue, NULL);
    2897 }
    2898 
    2899 /**
    2900  * Matches a sample name against a pattern.
    2901  *
    2902  * @returns True if matches, false if not.
    2903  * @param   pszPat      Pattern.
    2904  * @param   pszName     Name to match against the pattern.
    2905  * @todo move this into IPRT
    2906  */
    2907 static bool matchesSinglePattern(const char *pszPat, const char *pszName)
    2908 {
    2909     /* ASSUMES ASCII */
    2910     for (;;)
    2911     {
    2912         char chPat = *pszPat;
    2913         switch (chPat)
    2914         {
    2915             default:
    2916                 if (*pszName != chPat)
    2917                     return false;
    2918                 break;
    2919 
    2920             case '*':
    2921             {
    2922                 while ((chPat = *++pszPat) == '*' || chPat == '?')
    2923                     /* nothing */;
    2924 
    2925                 for (;;)
    2926                 {
    2927                     char ch = *pszName++;
    2928                     if (    ch == chPat
    2929                         &&  (   !chPat
    2930                              || matchesSinglePattern(pszPat + 1, pszName)))
    2931                         return true;
    2932                     if (!ch)
    2933                         return false;
    2934                 }
    2935                 /* won't ever get here */
    2936                 break;
    2937             }
    2938 
    2939             case '?':
    2940                 if (!*pszName)
    2941                     return false;
    2942                 break;
    2943 
    2944             case '\0':
    2945                 return !*pszName;
    2946         }
    2947         pszName++;
    2948         pszPat++;
    2949     }
    2950     return true;
    2951 }
    2952 
    2953 /* Checks to see if the given string matches against one of the patterns in
    2954  * the list. */
    2955 static bool matchesPattern(const char *paszPatterns, size_t cchPatterns,
    2956                            const char *pszString)
    2957 {
    2958     size_t iOffs = 0;
    2959     /* If the first pattern in the list is empty, treat it as "match all". */
    2960     bool matched = (cchPatterns > 0) && (0 == *paszPatterns) ? true : false;
    2961     while ((iOffs < cchPatterns) && !matched)
    2962     {
    2963         size_t cchCurrent;
    2964         if (   RT_SUCCESS(RTStrNLenEx(paszPatterns + iOffs,
    2965                                       cchPatterns - iOffs, &cchCurrent))
    2966             && (cchCurrent > 0)
    2967            )
    2968         {
    2969             matched = matchesSinglePattern(paszPatterns + iOffs, pszString);
    2970             iOffs += cchCurrent + 1;
    2971         }
    2972         else
    2973             iOffs = cchPatterns;
    2974     }
    2975     return matched;
    29763068}
    29773069
     
    30043096
    30053097/*
    3006  * Set up the pattern parameter, translating the comma-separated list to a
    3007  * double-terminated zero-separated one.
    3008  */
    3009 /** @todo skip this conversion. */
    3010         Utf8Str Utf8PatternsIn = aPatterns;
    3011         if ((aPatterns != NULL) && Utf8PatternsIn.isNull())
    3012             return E_OUTOFMEMORY;
    3013         size_t cchPatterns = Utf8PatternsIn.length();
    3014         Utf8Str Utf8Patterns(cchPatterns + 2);  /* Double terminator */
    3015         if (Utf8Patterns.isNull())
    3016             return E_OUTOFMEMORY;
    3017         char *pszPatterns = Utf8Patterns.mutableRaw();
    3018         unsigned iPatterns = 0;
    3019         for (unsigned i = 0; i < cchPatterns; ++i)
    3020         {
    3021             char cIn = Utf8PatternsIn.raw()[i];
    3022             if ((cIn != ',') && (cIn != ' '))
    3023                 pszPatterns[iPatterns] = cIn;
    3024             else if (cIn != ' ')
    3025                 pszPatterns[iPatterns] = '\0';
    3026             if (cIn != ' ')
    3027                 ++iPatterns;
    3028         }
    3029         pszPatterns[iPatterns] = '\0';
    3030         ++iPatterns;
    3031 
    3032 /*
    30333098 * Look for matching patterns and build up a list.
    30343099 */
     
    30363101        for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin();
    30373102             it != mHWData->mGuestProperties.end(); ++it)
    3038             if (matchesPattern(pszPatterns, iPatterns, Utf8Str(it->mName).raw()))
     3103            if (matchesPatternComma(Utf8Str(aPatterns).raw(), Utf8Str(it->mName).raw()))
    30393104                propList.push_back(*it);
    30403105
     
    51265191
    51275192        Key guestPropertiesNode = aNode.findKey ("GuestProperties");
     5193        Bstr notificationPatterns ("");
    51285194        if (!guestPropertiesNode.isNull())
    51295195        {
     
    51465212                mHWData->mGuestProperties.push_back(property);
    51475213            }
     5214            notificationPatterns = guestPropertiesNode.stringValue ("NotificationPatterns");
    51485215        }
    51495216        mHWData->mPropertyServiceActive = false;
     5217        mHWData->mGuestPropertyNotificationPatterns = notificationPatterns;
    51505218    }
    51515219#endif /* VBOX_WITH_GUEST_PROPS defined */
     
    65336601            propertyNode.setValue <Bstr> ("flags", Bstr(szFlags));
    65346602        }
     6603        guestPropertiesNode.setValue <Bstr> ("NotificationPatterns",
     6604                                             mHWData->mGuestPropertyNotificationPatterns);
    65356605    }
    65366606#endif /* VBOX_WITH_GUEST_PROPS defined */
     
    92279297    /* send a callback notification if appropriate */
    92289298    alock.leave();
    9229     // doGuestPropertyCallback(aName, aValue, aFlags);
     9299    if (matchesPatternComma (Utf8Str(mHWData->mGuestPropertyNotificationPatterns).raw(),
     9300                             Utf8Str(aName).raw()))
     9301        mParent->onGuestPropertyChange (mData->mUuid, aName, aValue, aFlags);
    92309302
    92319303    return S_OK;
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