Changeset 13436 in vbox for trunk/src/VBox/Main/MachineImpl.cpp
- Timestamp:
- Oct 21, 2008 1:03:49 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MachineImpl.cpp
r13431 r13436 1683 1683 1684 1684 return S_OK; 1685 } 1686 1687 STDMETHODIMP 1688 Machine::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 1703 STDMETHODIMP 1704 Machine::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; 1685 1720 } 1686 1721 … … 2794 2829 } 2795 2830 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 */ 2840 static 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. */ 2895 static 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. */ 2902 static 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. */ 2928 static 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 2796 2954 STDMETHODIMP Machine::SetGuestProperty (INPTR BSTR aName, INPTR BSTR aValue, INPTR BSTR aFlags) 2797 2955 { … … 2807 2965 if ((aFlags != NULL) && !VALID_PTR (aFlags)) 2808 2966 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 2809 2977 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 ) 2811 2980 return setError (E_INVALIDARG, tr ("Invalid flag values: '%ls'"), 2812 2981 aFlags); … … 2888 3057 &dummy, &dummy64, &dummy); 2889 3058 } 3059 if (SUCCEEDED (rc) && matchesPatternComma (utf8Patterns.raw(), utf8Name.raw())) 3060 mParent->onGuestPropertyChange (mData->mUuid, aName, aValue, aFlags); 2890 3061 return rc; 2891 3062 #endif /* else !defined (VBOX_WITH_GUEST_PROPS) */ … … 2895 3066 { 2896 3067 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 IPRT2906 */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 == chPat2929 && ( !chPat2930 || 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 in2954 * 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 else2973 iOffs = cchPatterns;2974 }2975 return matched;2976 3068 } 2977 3069 … … 3004 3096 3005 3097 /* 3006 * Set up the pattern parameter, translating the comma-separated list to a3007 * 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 /*3033 3098 * Look for matching patterns and build up a list. 3034 3099 */ … … 3036 3101 for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin(); 3037 3102 it != mHWData->mGuestProperties.end(); ++it) 3038 if (matchesPattern (pszPatterns, iPatterns, Utf8Str(it->mName).raw()))3103 if (matchesPatternComma(Utf8Str(aPatterns).raw(), Utf8Str(it->mName).raw())) 3039 3104 propList.push_back(*it); 3040 3105 … … 5126 5191 5127 5192 Key guestPropertiesNode = aNode.findKey ("GuestProperties"); 5193 Bstr notificationPatterns (""); 5128 5194 if (!guestPropertiesNode.isNull()) 5129 5195 { … … 5146 5212 mHWData->mGuestProperties.push_back(property); 5147 5213 } 5214 notificationPatterns = guestPropertiesNode.stringValue ("NotificationPatterns"); 5148 5215 } 5149 5216 mHWData->mPropertyServiceActive = false; 5217 mHWData->mGuestPropertyNotificationPatterns = notificationPatterns; 5150 5218 } 5151 5219 #endif /* VBOX_WITH_GUEST_PROPS defined */ … … 6533 6601 propertyNode.setValue <Bstr> ("flags", Bstr(szFlags)); 6534 6602 } 6603 guestPropertiesNode.setValue <Bstr> ("NotificationPatterns", 6604 mHWData->mGuestPropertyNotificationPatterns); 6535 6605 } 6536 6606 #endif /* VBOX_WITH_GUEST_PROPS defined */ … … 9227 9297 /* send a callback notification if appropriate */ 9228 9298 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); 9230 9302 9231 9303 return S_OK;
Note:
See TracChangeset
for help on using the changeset viewer.