Index: src/libchcore/TStringPattern.cpp
===================================================================
diff -u -r3401d5079f33b29a7783b65bfad5f34d89a33ba5 -r6d90b96005710c802d5f141b69528e9e87a380c9
--- src/libchcore/TStringPattern.cpp	(.../TStringPattern.cpp)	(revision 3401d5079f33b29a7783b65bfad5f34d89a33ba5)
+++ src/libchcore/TStringPattern.cpp	(.../TStringPattern.cpp)	(revision 6d90b96005710c802d5f141b69528e9e87a380c9)
@@ -19,6 +19,8 @@
 #include "stdafx.h"
 #include "TStringPattern.h"
 #include <tchar.h>
+#include <regex>
+#include <boost/algorithm/string/replace.hpp>
 
 using namespace string;
 
@@ -33,32 +35,52 @@
 		}
 	}
 
-	TStringPattern::TStringPattern(EPatternType ePatternType) :
-		m_ePatternType(ePatternType)
+	TStringPattern::TStringPattern() :
+		m_ePatternType(EPatternType::eType_FilenameWildcard)
 	{
 	}
 
+	TStringPattern::TStringPattern(const TString& strPattern)
+	{
+		FromString(strPattern);
+	}
+	
 	TStringPattern::TStringPattern(const TString& strPattern, EPatternType ePatternType) :
 		m_strPattern(strPattern),
 		m_ePatternType(ePatternType)
 	{
 	}
 
-	TStringPattern TStringPattern::CreateFromString(const TString& strPattern, EPatternType eDefaultPatternType)
+	TStringPattern TStringPattern::CreateFromString(const TString& strPattern)
 	{
 		TStringPattern pattern;
-		pattern.FromString(strPattern, eDefaultPatternType);
+		pattern.FromString(strPattern);
 		return pattern;
 	}
 
-	void TStringPattern::FromString(const TString& strPattern, EPatternType eDefaultPatternType)
+	void TStringPattern::FromString(const TString& strPattern)
 	{
-		m_ePatternType = eDefaultPatternType;
-		if (strPattern.StartsWith(L"WC;"))
+		m_ePatternType = EPatternType::eType_FilenameWildcard;
+		if(strPattern.StartsWith(L"file:"))
 		{
-			m_strPattern = strPattern.Mid(3);
-			m_ePatternType = EPatternType::eType_Wildcard;
+			m_strPattern = strPattern.Mid(5);
+			m_ePatternType = EPatternType::eType_FilenameWildcard;
 		}
+		else if(strPattern.StartsWith(L"path:"))
+		{
+			m_strPattern = strPattern.Mid(5);
+			m_ePatternType = EPatternType::eType_FullPathWildcard;
+		}
+		else if(strPattern.StartsWith(L"rfile:"))
+		{
+			m_strPattern = strPattern.Mid(6);
+			m_ePatternType = EPatternType::eType_FilenameRegex;
+		}
+		else if(strPattern.StartsWith(L"rpath:"))
+		{
+			m_strPattern = strPattern.Mid(6);
+			m_ePatternType = EPatternType::eType_FullPathRegex;
+		}
 		else
 			m_strPattern = strPattern;
 	}
@@ -68,9 +90,21 @@
 		TString strPrefix;
 		switch (m_ePatternType)
 		{
-		case EPatternType::eType_Wildcard:
+		case EPatternType::eType_FilenameWildcard:
 			break;	// wildcard won't have any prefix (it's implicit)
 
+		case EPatternType::eType_FullPathWildcard:
+			strPrefix = L"path:";
+			break;
+
+		case EPatternType::eType_FilenameRegex:
+			strPrefix = L"rfile:";
+			break;
+
+		case EPatternType::eType_FullPathRegex:
+			strPrefix = L"rpath:";
+			break;
+
 		default:
 			throw std::invalid_argument("Pattern type not supported");
 		}
@@ -88,71 +122,51 @@
 		return m_ePatternType == rSrc.m_ePatternType && m_strPattern == rSrc.m_strPattern;
 	}
 
-	bool TStringPattern::MatchMask(LPCTSTR lpszMask, LPCTSTR lpszString) const
+	bool TStringPattern::Matches(const TSmartPath& pathToMatch) const
 	{
-		bool bMatch = true;
-
-		//iterate and delete '?' and '*' one by one
-		while (*lpszMask != _T('\0') && bMatch && *lpszString != _T('\0'))
+		switch(m_ePatternType)
 		{
-			if (*lpszMask == _T('?')) lpszString++;
-			else if (*lpszMask == _T('*'))
-			{
-				bMatch = Scan(lpszMask, lpszString);
-				lpszMask--;
-			}
-			else
-			{
-				bMatch = _tcicmp(*lpszMask, *lpszString);
-				lpszString++;
-			}
-			lpszMask++;
-		}
-		while (*lpszMask == _T('*') && bMatch)
-			lpszMask++;
+		case EPatternType::eType_FilenameWildcard:
+		{
+			if(m_strPattern == L"*" || m_strPattern == L"*.*")
+				return true;
 
-		return bMatch && *lpszString == _T('\0') && *lpszMask == _T('\0');
-	}
+			std::wstring strPattern = ConvertGlobToRegex();
 
-	// scan '?' and '*'
-	bool TStringPattern::Scan(LPCTSTR& lpszMask, LPCTSTR& lpszString) const
-	{
-		// remove the '?' and '*'
-		for (lpszMask++; *lpszString != _T('\0') && (*lpszMask == _T('?') || *lpszMask == _T('*')); lpszMask++)
-			if (*lpszMask == _T('?')) lpszString++;
-		while (*lpszMask == _T('*')) lpszMask++;
+			std::wstring strText(pathToMatch.GetFileName().ToString());
+			std::wregex pattern(strPattern, std::regex_constants::icase | std::regex_constants::ECMAScript);
 
-		// if lpszString is empty and lpszMask has more characters or,
-		// lpszMask is empty, return 
-		if (*lpszString == _T('\0') && *lpszMask != _T('\0'))
-			return false;
-		if (*lpszString == _T('\0') && *lpszMask == _T('\0'))
-			return true;
-		// else search substring
-		LPCTSTR wdsCopy = lpszMask;
-		LPCTSTR lpszStringCopy = lpszString;
-		bool bMatch = true;
-		do
+			return std::regex_match(strText, pattern);
+		}
+
+		case EPatternType::eType_FullPathWildcard:
 		{
-			if (!MatchMask(lpszMask, lpszString)) lpszStringCopy++;
-			lpszMask = wdsCopy;
-			lpszString = lpszStringCopy;
-			while (!(_tcicmp(*lpszMask, *lpszString)) && (*lpszString != '\0')) lpszString++;
-			wdsCopy = lpszMask;
-			lpszStringCopy = lpszString;
-		} while ((*lpszString != _T('\0')) ? !MatchMask(lpszMask, lpszString) : (bMatch = false) != false);
+			if(m_strPattern == L"*" || m_strPattern == L"*.*")
+				return true;
 
-		if (*lpszString == _T('\0') && *lpszMask == _T('\0')) return true;
+			std::wstring strPattern = ConvertGlobToRegex();
+			std::wstring strText(pathToMatch.ToString());
+			std::wregex pattern(strPattern, std::regex_constants::icase | std::regex_constants::ECMAScript);
 
-		return bMatch;
-	}
+			return std::regex_match(strText, pattern);
+		}
 
-	bool TStringPattern::Matches(const TSmartPath& pathToMatch) const
-	{
-		switch(m_ePatternType)
+		case EPatternType::eType_FilenameRegex:
 		{
-		case EPatternType::eType_Wildcard:
-			return MatchMask(m_strPattern.c_str(), pathToMatch.GetFileName().ToString());
+			std::wstring strText(pathToMatch.GetFileName().ToString());
+			std::wregex pattern(m_strPattern.c_str(), std::regex_constants::icase | std::regex_constants::ECMAScript);
+
+			return std::regex_match(strText, pattern);
+		}
+
+		case EPatternType::eType_FullPathRegex:
+		{
+			std::wstring strText(pathToMatch.ToString());
+			std::wregex pattern(m_strPattern.c_str(), std::regex_constants::icase | std::regex_constants::ECMAScript);
+
+			return std::regex_match(strText, pattern);
+		}
+
 		default:
 			throw std::invalid_argument("Unsupported pattern type");
 		}
@@ -163,4 +177,27 @@
 		m_ePatternType = ePatternType;
 		m_strPattern = strPattern;
 	}
+
+	std::wstring TStringPattern::ConvertGlobToRegex() const
+	{
+		std::wstring strPattern = m_strPattern.c_str();
+
+		boost::replace_all(strPattern, L"\\", L"\\\\");
+		boost::replace_all(strPattern, L"^", L"\\^");
+		boost::replace_all(strPattern, L".", L"\\.");
+		boost::replace_all(strPattern, L"$", L"\\$");
+		boost::replace_all(strPattern, L"|", L"\\|");
+		boost::replace_all(strPattern, L"(", L"\\(");
+		boost::replace_all(strPattern, L")", L"\\)");
+		boost::replace_all(strPattern, L"{", L"\\{");
+		boost::replace_all(strPattern, L"{", L"\\}");
+		boost::replace_all(strPattern, L"[", L"\\[");
+		boost::replace_all(strPattern, L"]", L"\\]");
+		boost::replace_all(strPattern, L"+", L"\\+");
+		boost::replace_all(strPattern, L"/", L"\\/");
+		boost::replace_all(strPattern, L"*", L".*");
+		boost::replace_all(strPattern, L"?", L".");
+
+		return strPattern;
+	}
 }
Index: src/libchcore/TStringPattern.h
===================================================================
diff -u -r3401d5079f33b29a7783b65bfad5f34d89a33ba5 -r6d90b96005710c802d5f141b69528e9e87a380c9
--- src/libchcore/TStringPattern.h	(.../TStringPattern.h)	(revision 3401d5079f33b29a7783b65bfad5f34d89a33ba5)
+++ src/libchcore/TStringPattern.h	(.../TStringPattern.h)	(revision 6d90b96005710c802d5f141b69528e9e87a380c9)
@@ -29,31 +29,34 @@
 	public:
 		enum class EPatternType
 		{
-			eType_Wildcard
+			eType_FilenameWildcard,
+			eType_FullPathWildcard,
+			eType_FilenameRegex,
+			eType_FullPathRegex,
 		};
 
 	public:
-		explicit TStringPattern(EPatternType ePatternType = EPatternType::eType_Wildcard);
-		explicit TStringPattern(const string::TString& strPattern, EPatternType ePatternType = EPatternType::eType_Wildcard);
+		TStringPattern();
+		explicit TStringPattern(const string::TString& strPattern);
+		explicit TStringPattern(const string::TString& strPattern, EPatternType ePatternType);
 
-		void SetPattern(const string::TString& strPattern, EPatternType ePatternType = EPatternType::eType_Wildcard);
+		void SetPattern(const string::TString& strPattern, EPatternType ePatternType = EPatternType::eType_FilenameWildcard);
 		bool Matches(const TSmartPath& pathToMatch) const;
 
 		EPatternType GetPatternType() const { return m_ePatternType; }
 		string::TString GetPattern() const { return m_strPattern; }
 
 		// string parsing
-		static TStringPattern CreateFromString(const string::TString& strPattern, EPatternType eDefaultPatternType = EPatternType::eType_Wildcard);
+		static TStringPattern CreateFromString(const string::TString& strPattern);
 
-		void FromString(const string::TString& strPattern, EPatternType eDefaultPatternType = EPatternType::eType_Wildcard);
+		void FromString(const string::TString& strPattern);
 		string::TString ToString() const;
 
 		bool operator==(const TStringPattern& rSrc) const;
 		bool operator!=(const TStringPattern& rSrc) const;
 
 	private:
-		bool MatchMask(LPCTSTR lpszMask, LPCTSTR lpszString) const;
-		bool Scan(LPCTSTR& lpszMask, LPCTSTR& lpszString) const;
+		std::wstring ConvertGlobToRegex() const;
 
 	private:
 		string::TString m_strPattern;
Index: src/libchcore/TStringPatternArray.cpp
===================================================================
diff -u -r3401d5079f33b29a7783b65bfad5f34d89a33ba5 -r6d90b96005710c802d5f141b69528e9e87a380c9
--- src/libchcore/TStringPatternArray.cpp	(.../TStringPatternArray.cpp)	(revision 3401d5079f33b29a7783b65bfad5f34d89a33ba5)
+++ src/libchcore/TStringPatternArray.cpp	(.../TStringPatternArray.cpp)	(revision 6d90b96005710c802d5f141b69528e9e87a380c9)
@@ -46,11 +46,11 @@
 		return true;
 	}
 
-	void TStringPatternArray::FromString(const TString& strPatterns, TStringPattern::EPatternType eDefaultPatternType)
+	void TStringPatternArray::FromString(const TString& strPatterns)
 	{
 		TStringArray arrPatterns;
 		strPatterns.Split(_T("|"), arrPatterns);
-		FromStringArray(arrPatterns, eDefaultPatternType);
+		FromStringArray(arrPatterns);
 	}
 
 	void TStringPatternArray::FromSerializedStringArray(const TStringArray& arrSerializedPatterns)
@@ -63,11 +63,11 @@
 		}
 	}
 
-	void TStringPatternArray::FromStringArray(const TStringArray& arrPatterns, TStringPattern::EPatternType eDefaultPatternType)
+	void TStringPatternArray::FromStringArray(const TStringArray& arrPatterns)
 	{
 		for (size_t stIndex = 0; stIndex < arrPatterns.GetCount(); ++stIndex)
 		{
-			Add(TStringPattern::CreateFromString(arrPatterns.GetAt(stIndex), eDefaultPatternType));
+			Add(TStringPattern::CreateFromString(arrPatterns.GetAt(stIndex)));
 		}
 	}
 
Index: src/libchcore/TStringPatternArray.h
===================================================================
diff -u -r3401d5079f33b29a7783b65bfad5f34d89a33ba5 -r6d90b96005710c802d5f141b69528e9e87a380c9
--- src/libchcore/TStringPatternArray.h	(.../TStringPatternArray.h)	(revision 3401d5079f33b29a7783b65bfad5f34d89a33ba5)
+++ src/libchcore/TStringPatternArray.h	(.../TStringPatternArray.h)	(revision 6d90b96005710c802d5f141b69528e9e87a380c9)
@@ -44,8 +44,8 @@
 		bool MatchesAll(const TSmartPath& pathToMatch) const;
 
 		// string parsing
-		void FromString(const string::TString& strPatterns, TStringPattern::EPatternType eDefaultPatternType = TStringPattern::EPatternType::eType_Wildcard);
-		void FromStringArray(const string::TStringArray& strPatterns, TStringPattern::EPatternType eDefaultPatternType = TStringPattern::EPatternType::eType_Wildcard);
+		void FromString(const string::TString& strPatterns);
+		void FromStringArray(const string::TStringArray& strPatterns);
 		string::TString ToString() const;
 
 		// serialization
Index: src/libchcore/Tests/TestsTStringPattern.cpp
===================================================================
diff -u -r3401d5079f33b29a7783b65bfad5f34d89a33ba5 -r6d90b96005710c802d5f141b69528e9e87a380c9
--- src/libchcore/Tests/TestsTStringPattern.cpp	(.../TestsTStringPattern.cpp)	(revision 3401d5079f33b29a7783b65bfad5f34d89a33ba5)
+++ src/libchcore/Tests/TestsTStringPattern.cpp	(.../TestsTStringPattern.cpp)	(revision 6d90b96005710c802d5f141b69528e9e87a380c9)
@@ -10,105 +10,175 @@
 	TStringPattern patternEmpty;
 	EXPECT_STREQ(L"", patternEmpty.ToString().c_str());
 	EXPECT_STREQ(L"", patternEmpty.GetPattern().c_str());
-	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_FilenameWildcard, patternEmpty.GetPatternType());
 }
 
 TEST(TestsTStringPattern, PatternConstruction)
 {
-	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_Wildcard);
+	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_FilenameWildcard);
 	EXPECT_STREQ(L"*.*", patternEmpty.ToString().c_str());
 	EXPECT_STREQ(L"*.*", patternEmpty.GetPattern().c_str());
-	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_FilenameWildcard, patternEmpty.GetPatternType());
 }
 
 TEST(TestsTStringPattern, SetPattern)
 {
-	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_Wildcard);
+	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_FilenameWildcard);
 
-	patternEmpty.SetPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard);
+	patternEmpty.SetPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard);
 
 	EXPECT_STREQ(L"*.bat", patternEmpty.ToString().c_str());
 	EXPECT_STREQ(L"*.bat", patternEmpty.GetPattern().c_str());
-	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_FilenameWildcard, patternEmpty.GetPatternType());
 }
 
 TEST(TestsTStringPattern, CreateFromSerializedString)
 {
-	TStringPattern patternEmpty = TStringPattern::CreateFromString(L"WC;*.*");
+	TStringPattern patternEmpty = TStringPattern::CreateFromString(L"file:*.*");
 
 	EXPECT_STREQ(L"*.*", patternEmpty.ToString().c_str());
 	EXPECT_STREQ(L"*.*", patternEmpty.GetPattern().c_str());
-	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_FilenameWildcard, patternEmpty.GetPatternType());
 }
 
 TEST(TestsTStringPattern, FromStringString)
 {
 	TStringPattern patternEmpty;
-	patternEmpty.FromString(L"WC;*.*");
+	patternEmpty.FromString(L"file:*.*");
 
-	EXPECT_STREQ(L"*.*", patternEmpty.ToString().c_str());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_FilenameWildcard, patternEmpty.GetPatternType());
 	EXPECT_STREQ(L"*.*", patternEmpty.GetPattern().c_str());
-	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+	EXPECT_STREQ(L"*.*", patternEmpty.ToString().c_str());
 }
 
+TEST(TestsTStringPattern, Matches_DoubleWildcard)
+{
+	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_FilenameWildcard);
+
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(L"autorun")));
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(L"autorun.txt")));
+}
+
+TEST(TestsTStringPattern, Matches_SingleWildcard)
+{
+	TStringPattern patternEmpty(L"*", TStringPattern::EPatternType::eType_FilenameWildcard);
+
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(L"autorun")));
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(L"autorun.txt")));
+}
+
 TEST(TestsTStringPattern, Matches_Positive_StarDotBat)
 {
-	TStringPattern patternEmpty(L"*.bat", TStringPattern::EPatternType::eType_Wildcard);
+	TStringPattern patternEmpty(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard);
 
 	EXPECT_TRUE(patternEmpty.Matches(PathFromString(L"autorun.bat")));
 }
 
 TEST(TestsTStringPattern, Matches_Negative_StarDotBat)
 {
-	TStringPattern patternEmpty(L"*.bat", TStringPattern::EPatternType::eType_Wildcard);
+	TStringPattern patternEmpty(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard);
 
 	EXPECT_FALSE(patternEmpty.Matches(PathFromString(L"autorun.batx")));
 }
 
 TEST(TestsTStringPattern, Matches_Positive_StarDotStar)
 {
-	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_Wildcard);
+	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_FilenameWildcard);
 
 	EXPECT_TRUE(patternEmpty.Matches(PathFromString(L"autorun.bat")));
 }
 
-TEST(TestsTStringPattern, Matches_Negative_StarDotStar)
-{
-	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_Wildcard);
-
-	EXPECT_FALSE(patternEmpty.Matches(PathFromString(L"autorun")));
-}
-
 ///////////////////////////////////////////////////////////
 // Multiple asterisks
 
 TEST(TestsTStringPattern, Matches_Positive_MultiStar)
 {
-	TStringPattern patternEmpty(L"ad*bo*", TStringPattern::EPatternType::eType_Wildcard);
+	TStringPattern patternEmpty(L"ad*bo*", TStringPattern::EPatternType::eType_FilenameWildcard);
 
 	EXPECT_TRUE(patternEmpty.Matches(PathFromString(L"addon-boo.bat")));
 }
 
 TEST(TestsTStringPattern, Matches_Negative_MultiStar)
 {
-	TStringPattern patternEmpty(L"ad*bo*", TStringPattern::EPatternType::eType_Wildcard);
+	TStringPattern patternEmpty(L"ad*bo*", TStringPattern::EPatternType::eType_FilenameWildcard);
 
 	EXPECT_FALSE(patternEmpty.Matches(PathFromString(L"addon-doo.bat")));
 }
 
 ////////////////////////////////////////////////////////////
 // asterisks
-
 TEST(TestsTStringPattern, Matches_Positive_QuestionMultiPos)
 {
-	TStringPattern patternEmpty(L"a??b?r", TStringPattern::EPatternType::eType_Wildcard);
+	TStringPattern patternEmpty(L"a??b?r", TStringPattern::EPatternType::eType_FilenameWildcard);
 
 	EXPECT_TRUE(patternEmpty.Matches(PathFromString(L"arbbar")));
 }
 
 TEST(TestsTStringPattern, Matches_Negative_QuestionMultiPos)
 {
-	TStringPattern patternEmpty(L"a??b?r", TStringPattern::EPatternType::eType_Wildcard);
+	TStringPattern patternEmpty(L"a??b?r", TStringPattern::EPatternType::eType_FilenameWildcard);
 
 	EXPECT_FALSE(patternEmpty.Matches(PathFromString(L"arbxar")));
 }
+
+// full path matching
+TEST(TestsTStringPattern, FullPath_MatchFilename)
+{
+	TStringPattern patternEmpty(L"a??b?r", TStringPattern::EPatternType::eType_FilenameWildcard);
+
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(LR"(c:\windows\arbbar)")));
+}
+
+TEST(TestsTStringPattern, FullPath_NotMatchWholePath)
+{
+	TStringPattern patternEmpty(L"a??b?r", TStringPattern::EPatternType::eType_FullPathWildcard);
+
+	EXPECT_FALSE(patternEmpty.Matches(PathFromString(LR"(c:\windows\arbbar)")));
+}
+
+TEST(TestsTStringPattern, FullPath_MatchWholePath)
+{
+	TStringPattern patternEmpty(L"*a??b?r", TStringPattern::EPatternType::eType_FullPathWildcard);
+
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(LR"(c:\windows\arbbar)")));
+}
+
+TEST(TestsTStringPattern, FullPath_MatchComplexPattern)
+{
+	TStringPattern patternEmpty(LR"(c:\*\a??b?r)", TStringPattern::EPatternType::eType_FullPathWildcard);
+
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(LR"(c:\windows\arbbar)")));
+}
+
+// auto-detection
+TEST(TestsTStringPattern, FullPath_DetectWildcard)
+{
+	TStringPattern patternEmpty(L"file:a??b?r");
+
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(LR"(c:\windows\arbbar)")));
+}
+
+TEST(TestsTStringPattern, FullPath_DetectFullPathWildcard)
+{
+	TStringPattern patternEmpty(L"path:a??b?r");
+
+	EXPECT_FALSE(patternEmpty.Matches(PathFromString(LR"(c:\windows\arbbar)")));
+}
+
+///////////////////////////////////////////////
+// regex
+
+// auto-detection
+TEST(TestsTStringPattern, RegexFullPath_DetectWildcard)
+{
+	TStringPattern patternEmpty(L"rfile:ar[bar]+");
+
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(LR"(c:\windows\arbbar)")));
+}
+
+TEST(TestsTStringPattern, RegexFullPath_DetectFullPathWildcard)
+{
+	TStringPattern patternEmpty(L"rpath:c:\\\\[a-z]+\\\\a[bar]*");
+
+	EXPECT_TRUE(patternEmpty.Matches(PathFromString(LR"(c:\windows\arbbar)")));
+}
Index: src/libchcore/Tests/TestsTStringPatternArray.cpp
===================================================================
diff -u -r3401d5079f33b29a7783b65bfad5f34d89a33ba5 -r6d90b96005710c802d5f141b69528e9e87a380c9
--- src/libchcore/Tests/TestsTStringPatternArray.cpp	(.../TestsTStringPatternArray.cpp)	(revision 3401d5079f33b29a7783b65bfad5f34d89a33ba5)
+++ src/libchcore/Tests/TestsTStringPatternArray.cpp	(.../TestsTStringPatternArray.cpp)	(revision 6d90b96005710c802d5f141b69528e9e87a380c9)
@@ -18,8 +18,8 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	EXPECT_EQ(2UL, arrPatterns.GetCount());
 	EXPECT_STREQ(L"*.bat", arrPatterns.GetAt(0).ToString().c_str());
@@ -30,8 +30,8 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.InsertAt(0, TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.InsertAt(0, TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.InsertAt(0, TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.InsertAt(0, TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	EXPECT_EQ(2UL, arrPatterns.GetCount());
 	EXPECT_STREQ(L"*.bat", arrPatterns.GetAt(1).ToString().c_str());
@@ -42,10 +42,10 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_FilenameWildcard));
 
-	arrPatterns.SetAt(0, TStringPattern(L"*.com", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.SetAt(0, TStringPattern(L"*.com", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	EXPECT_EQ(2UL, arrPatterns.GetCount());
 	EXPECT_STREQ(L"*.com", arrPatterns.GetAt(0).ToString().c_str());
@@ -56,8 +56,8 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	arrPatterns.RemoveAt(0);
 
@@ -69,8 +69,8 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	arrPatterns.Clear();
 
@@ -83,8 +83,8 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	EXPECT_TRUE(arrPatterns.MatchesAny(PathFromString(L"autostart.bat")));
 }
@@ -93,8 +93,8 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	EXPECT_FALSE(arrPatterns.MatchesAny(PathFromString(L"autostart.com")));
 }
@@ -105,8 +105,8 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.Add(TStringPattern(L"autostart.*", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.Add(TStringPattern(L"autostart.*", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	EXPECT_TRUE(arrPatterns.MatchesAll(PathFromString(L"autostart.bat")));
 }
@@ -115,8 +115,8 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.Add(TStringPattern(L"autostart.*", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.Add(TStringPattern(L"autostart.*", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	EXPECT_FALSE(arrPatterns.MatchesAll(PathFromString(L"autostart.exe")));
 }
@@ -127,8 +127,8 @@
 {
 	TStringPatternArray arrPatterns;
 
-	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
-	arrPatterns.Add(TStringPattern(L"autostart.*", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_FilenameWildcard));
+	arrPatterns.Add(TStringPattern(L"autostart.*", TStringPattern::EPatternType::eType_FilenameWildcard));
 
 	TStringArray arrElements = arrPatterns.ToSerializedStringArray();
 	EXPECT_EQ(2UL, arrElements.GetCount());