Index: src/ch/FeedbackHandler.h
===================================================================
diff -u -r671f4b1792a20d98b186f4e0a9cc6a620dede019 -r2755e12daeccb1935f569e7235e685e566b0b098
--- src/ch/FeedbackHandler.h	(.../FeedbackHandler.h)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
+++ src/ch/FeedbackHandler.h	(.../FeedbackHandler.h)	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -22,6 +22,7 @@
 #include "../libchcore/IFeedbackHandlerFactory.h"
 #include "../libchcore/TFeedbackHandlerBase.h"
 #include "../libchcore/EFeedbackResult.h"
+#include "../libchcore/EFileError.h"
 
 class CFeedbackHandler : public chcore::TFeedbackHandlerBase
 {
Index: src/libchcore/IFeedbackHandler.h
===================================================================
diff -u -r3c343f2e7aa0d489706136e78f2f56cdd5d417a9 -r2755e12daeccb1935f569e7235e685e566b0b098
--- src/libchcore/IFeedbackHandler.h	(.../IFeedbackHandler.h)	(revision 3c343f2e7aa0d489706136e78f2f56cdd5d417a9)
+++ src/libchcore/IFeedbackHandler.h	(.../IFeedbackHandler.h)	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -25,21 +25,10 @@
 #include "TFileInfo.h"
 #include "ISerializerRowReader.h"
 #include "ISerializerRowData.h"
+#include "EFileError.h"
 
 BEGIN_CHCORE_NAMESPACE
 
-enum class EFileError
-{
-	eDeleteError,		///< Problem occurred when tried to delete the fs object
-	eSeekError,			///< Problem occurred when tried to set file pointer
-	eResizeError,		///< Problem occurred when tried to change size of the fs object
-	eReadError,			///< Problem occurred when tried to read data from file
-	eWriteError,		///< Problem occurred when tried to write data to a file
-	eFinalizeError,		///< Problem occurred when tried to finalize file
-	eFastMoveError,		///< Problem occurred when tried to perform fast move operation (that does not involve copying contents)
-	eCreateError		///< Problem occurred when tried to create the fs object
-};
-
 class LIBCHCORE_API IFeedbackHandler
 {
 public:
Index: src/libchcore/TFeedbackHandlerBase.h
===================================================================
diff -u -r671f4b1792a20d98b186f4e0a9cc6a620dede019 -r2755e12daeccb1935f569e7235e685e566b0b098
--- src/libchcore/TFeedbackHandlerBase.h	(.../TFeedbackHandlerBase.h)	(revision 671f4b1792a20d98b186f4e0a9cc6a620dede019)
+++ src/libchcore/TFeedbackHandlerBase.h	(.../TFeedbackHandlerBase.h)	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -52,12 +52,6 @@
 	void SetNotEnoughSpacePermanentResponse(EFeedbackResult ePermanentResult) { m_eNotEnoughSpace = ePermanentResult; }
 	EFeedbackResult GetNotEnoughSpacePermanentResponse() const { return m_eNotEnoughSpace; }
 
-	void SetOperationFinishedPermanentResponse(EFeedbackResult ePermanentResult) { m_eOperationFinished = ePermanentResult; }
-	EFeedbackResult GetOperationFinishedPermanentResponse() const { return m_eOperationFinished; }
-
-	void SetOperationErrorPermanentResponse(EFeedbackResult ePermanentResult) { m_eOperationError = ePermanentResult; }
-	EFeedbackResult GetOperationErrorPermanentResponse() const { return m_eOperationError; }
-
 	// resets the permanent status from all responses
 	virtual void RestoreDefaults() override;
 
Index: src/libchcore/TFileFilter.cpp
===================================================================
diff -u -r7972b0944e0a947144fbdb93262f7d73ac528dc7 -r2755e12daeccb1935f569e7235e685e566b0b098
--- src/libchcore/TFileFilter.cpp	(.../TFileFilter.cpp)	(revision 7972b0944e0a947144fbdb93262f7d73ac528dc7)
+++ src/libchcore/TFileFilter.cpp	(.../TFileFilter.cpp)	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -24,11 +24,6 @@
 BEGIN_CHCORE_NAMESPACE
 
 ////////////////////////////////////////////////////////////////////////////
-bool _tcicmp(TCHAR c1, TCHAR c2)
-{
-	TCHAR ch1[2]={c1, 0}, ch2[2]={c2, 0};
-	return (_tcsicmp(ch1, ch2) == 0);
-}
 
 TFileFilter::TFileFilter() :
 	m_oidObjectID(0),
@@ -154,21 +149,27 @@
 	size_t stCount = m_astrMask.Get().GetCount();
 	if(stCount > 0)
 	{
-		strMask = m_astrMask.Get().GetAt(0);
+		strMask = m_astrMask.Get().GetAt(0).ToSerializedString();
 		for(size_t stIndex = 1; stIndex < stCount; stIndex++)
 		{
-			strMask += _T("|") + m_astrMask.Get().GetAt(stIndex);
+			strMask += _T("|") + m_astrMask.Get().GetAt(stIndex).ToSerializedString();
 		}
 	}
 
 	return strMask;
 }
 
-void TFileFilter::SetCombinedMask(const TString& pMask)
+void TFileFilter::SetCombinedMask(const TString& strMask)
 {
-	m_astrMask.Modify().Clear();
+	TStringArray arrMasks;
+	strMask.Split(_T("|"), arrMasks);
 
-	pMask.Split(_T("|"), m_astrMask.Modify());
+	TStringPatternArray& rPatterns = m_astrMask.Modify();
+	rPatterns.Clear();
+	for (size_t stIndex = 0; stIndex < arrMasks.GetCount(); ++stIndex)
+	{
+		rPatterns.Add(TStringPattern::CreateFromSerializedString(arrMasks.GetAt(stIndex)));
+	}
 }
 
 TString TFileFilter::GetCombinedExcludeMask() const
@@ -177,30 +178,36 @@
 	size_t stCount = m_astrExcludeMask.Get().GetCount();
 	if(stCount > 0)
 	{
-		strMask = m_astrExcludeMask.Get().GetAt(0);
+		strMask = m_astrExcludeMask.Get().GetAt(0).ToSerializedString();
 		for(size_t stIndex = 1; stIndex < stCount; stIndex++)
 		{
-			strMask += _T("|") + m_astrExcludeMask.Get().GetAt(stIndex);
+			strMask += _T("|") + m_astrExcludeMask.Get().GetAt(stIndex).ToSerializedString();
 		}
 	}
 
 	return strMask;
 }
 
-void TFileFilter::SetCombinedExcludeMask(const TString& pMask)
+void TFileFilter::SetCombinedExcludeMask(const TString& strMask)
 {
-	m_astrExcludeMask.Modify().Clear();
+	TStringArray arrMasks;
+	strMask.Split(_T("|"), arrMasks);
 
-	pMask.Split(_T("|"), m_astrExcludeMask.Modify());
+	TStringPatternArray& rPatterns = m_astrExcludeMask.Modify();
+	rPatterns.Clear();
+	for (size_t stIndex = 0; stIndex < arrMasks.GetCount(); ++stIndex)
+	{
+		rPatterns.Add(TStringPattern::CreateFromSerializedString(arrMasks.GetAt(stIndex)));
+	}
 }
 
 void TFileFilter::StoreInConfig(TConfig& rConfig) const
 {
 	SetConfigValue(rConfig, _T("IncludeMask.Use"), m_bUseMask.Get());
-	SetConfigValue(rConfig, _T("IncludeMask.MaskList.Mask"), m_astrMask.Get());
+	SetConfigValue(rConfig, _T("IncludeMask.MaskList.Mask"), m_astrMask.Get().ToStringArray());
 
 	SetConfigValue(rConfig, _T("ExcludeMask.Use"), m_bUseExcludeMask.Get());
-	SetConfigValue(rConfig, _T("ExcludeMask.MaskList.Mask"), m_astrExcludeMask.Get());
+	SetConfigValue(rConfig, _T("ExcludeMask.MaskList.Mask"), m_astrExcludeMask.Get().ToStringArray());
 
 	SetConfigValue(rConfig, _T("SizeA.Use"), m_bUseSize1.Get());
 	SetConfigValue(rConfig, _T("SizeA.FilteringType"), m_eSizeCmpType1.Get());
@@ -235,14 +242,17 @@
 	if(!GetConfigValue(rConfig, _T("IncludeMask.Use"), m_bUseMask.Modify()))
 		m_bUseMask = false;
 
+	TStringArray arrMask;
 	m_astrMask.Modify().Clear();
-	GetConfigValue(rConfig, _T("IncludeMask.MaskList.Mask"), m_astrMask.Modify());
+	GetConfigValue(rConfig, _T("IncludeMask.MaskList.Mask"), arrMask);
+	m_astrMask.Modify().FromStringArray(arrMask);
 
 	if(!GetConfigValue(rConfig, _T("ExcludeMask.Use"), m_bUseExcludeMask.Modify()))
 		m_bUseExcludeMask = false;
 
 	m_astrExcludeMask.Modify().Clear();
-	GetConfigValue(rConfig, _T("ExcludeMask.MaskList.Mask"), m_astrExcludeMask.Modify());
+	GetConfigValue(rConfig, _T("ExcludeMask.MaskList.Mask"), arrMask);
+	m_astrExcludeMask.Modify().FromStringArray(arrMask);
 
 	if(!GetConfigValue(rConfig, _T("SizeA.Use"), m_bUseSize1.Modify()))
 		m_bUseSize1 = false;
@@ -303,24 +313,15 @@
 	// check by mask
 	if(m_bUseMask)
 	{
-		bool bRes=false;
-		for(TStringArray::const_iterator iterMask = m_astrMask.Get().Begin(); iterMask != m_astrMask.Get().End(); ++iterMask)
-		{
-			if(MatchMask((*iterMask).c_str(), spInfo->GetFullFilePath().GetFileName().ToString()))
-				bRes = true;
-		}
-		if(!bRes)
+		if (!m_astrMask.Get().MatchesAny(spInfo->GetFullFilePath().GetFileName().ToString()))
 			return false;
 	}
 
 	// excluding mask
 	if(m_bUseExcludeMask)
 	{
-		for(TStringArray::const_iterator iterExcludeMask = m_astrExcludeMask.Get().Begin(); iterExcludeMask != m_astrExcludeMask.Get().End(); ++iterExcludeMask)
-		{
-			if(MatchMask((*iterExcludeMask).c_str(), spInfo->GetFullFilePath().GetFileName().ToString()))
-				return false;
-		}
+		if (m_astrExcludeMask.Get().MatchesAny(spInfo->GetFullFilePath().GetFileName().ToString()))
+			return false;
 	}
 
 	// by size
@@ -474,66 +475,6 @@
 	return true;
 }
 
-bool TFileFilter::MatchMask(LPCTSTR lpszMask, LPCTSTR lpszString) const
-{
-	bool bMatch = 1;
-
-	//iterate and delete '?' and '*' one by one
-	while(*lpszMask != _T('\0') && bMatch && *lpszString != _T('\0'))
-	{
-		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++;
-
-	return bMatch && *lpszString == _T('\0') && *lpszMask == _T('\0');
-}
-
-// scan '?' and '*'
-bool TFileFilter::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++;
-
-	// 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
-	else
-	{
-		LPCTSTR wdsCopy = lpszMask;
-		LPCTSTR lpszStringCopy = lpszString;
-		bool bMatch = true;
-		do 
-		{
-			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 (*lpszString == _T('\0') && *lpszMask == _T('\0')) return true;
-
-		return bMatch;
-	}
-}
-
 void TFileFilter::InitColumns(IColumnsDefinition& rColumns)
 {
 	rColumns.AddColumn(_T("id"), ColumnType<object_id_t>::value);
Index: src/libchcore/TFileFilter.h
===================================================================
diff -u -ra44714d5c7ec0f50a376f4d0ea919ee5a224f834 -r2755e12daeccb1935f569e7235e685e566b0b098
--- src/libchcore/TFileFilter.h	(.../TFileFilter.h)	(revision a44714d5c7ec0f50a376f4d0ea919ee5a224f834)
+++ src/libchcore/TFileFilter.h	(.../TFileFilter.h)	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -23,6 +23,7 @@
 #include <atltime.h>
 #include "TDateTime.h"
 #include "TStringArray.h"
+#include "TStringPatternArray.h"
 #include <bitset>
 #include "TSharedModificationTracker.h"
 
@@ -90,18 +91,12 @@
 	TString GetCombinedMask() const;
 	void SetCombinedMask(const TString& pMask);
 
-	//   const TStringArray& GetMaskArray() const { return m_astrMask; }
-	//   TStringArray& GetMaskArray() { return m_astrMask; }
-
 	bool GetUseExcludeMask() const;
 	void SetUseExcludeMask(bool bUseExcludeMask);
 
 	TString GetCombinedExcludeMask() const;
 	void SetCombinedExcludeMask(const TString& pMask);
 
-	//   const TStringArray& GetExcludeMaskArray() const { return m_astrExcludeMask; }
-	//   TStringArray& GetExcludeMaskArray() { return m_astrExcludeMask; }
-
 	bool GetUseSize1() const;
 	void SetUseSize1(bool bUseSize1);
 
@@ -175,10 +170,6 @@
 	int GetDirectory() const { return m_iDirectory; }
 	void SetDirectory(int iDirectory) { m_iDirectory = iDirectory; }
 
-protected:
-	bool MatchMask(LPCTSTR lpszMask, LPCTSTR lpszString) const;
-	bool Scan(LPCTSTR& lpszMask, LPCTSTR& lpszString) const;
-
 private:
 	enum EModifications
 	{
@@ -225,11 +216,11 @@
 
 	// files mask
 	TSharedModificationTracker<bool, Bitset, eMod_UseMask> m_bUseMask;
-	TSharedModificationTracker<TStringArray, Bitset, eMod_Mask> m_astrMask;
+	TSharedModificationTracker<TStringPatternArray, Bitset, eMod_Mask> m_astrMask;
 
 	// files mask-
 	TSharedModificationTracker<bool, Bitset, eMod_UseExcludeMask> m_bUseExcludeMask;
-	TSharedModificationTracker<TStringArray, Bitset, eMod_ExcludeMask> m_astrExcludeMask;
+	TSharedModificationTracker<TStringPatternArray, Bitset, eMod_ExcludeMask> m_astrExcludeMask;
 
 	// size filtering
 	TSharedModificationTracker<bool, Bitset, eMod_UseSize1> m_bUseSize1;
Index: src/libchcore/TString.cpp
===================================================================
diff -u -r2fe97a93f21771d75901d4b6559057d1ea055104 -r2755e12daeccb1935f569e7235e685e566b0b098
--- src/libchcore/TString.cpp	(.../TString.cpp)	(revision 2fe97a93f21771d75901d4b6559057d1ea055104)
+++ src/libchcore/TString.cpp	(.../TString.cpp)	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -117,7 +117,7 @@
  * \param[in] src - source TString object
  * \return A reference to the current TString.
  */
-const TString& TString::operator=(const TString& rSrc)
+TString& TString::operator=(const TString& rSrc)
 {
 	if(this != &rSrc)
 		SetString(rSrc.m_pszData);
Index: src/libchcore/TString.h
===================================================================
diff -u -r2fe97a93f21771d75901d4b6559057d1ea055104 -r2755e12daeccb1935f569e7235e685e566b0b098
--- src/libchcore/TString.h	(.../TString.h)	(revision 2fe97a93f21771d75901d4b6559057d1ea055104)
+++ src/libchcore/TString.h	(.../TString.h)	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -56,7 +56,7 @@
 /** \name Operators */
 /**@{*/
 	// assignment
-	const TString& operator=(const TString& src);			///< Assign operator for TString objects
+	TString& operator=(const TString& src);			///< Assign operator for TString objects
 	TString operator+(const TString& src) const;	///< Concatenate operator for TString objects
 	const TString& operator+=(const TString& src);		///< Merge operator for TString objects
 	
Index: src/libchcore/Tests/TestsTFileFilter.cpp
===================================================================
diff -u
--- src/libchcore/Tests/TestsTFileFilter.cpp	(revision 0)
+++ src/libchcore/Tests/TestsTFileFilter.cpp	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -0,0 +1,54 @@
+#include "stdafx.h"
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "../TFileFilter.h"
+
+using namespace chcore;
+
+TEST(TestsTFileFilter, DefaultConstruction)
+{
+	TFileFilter filter;
+
+	// other
+	EXPECT_EQ(0, filter.GetObjectID());
+	
+	EXPECT_EQ(false, filter.GetUseMask());
+	EXPECT_STREQ(L"", filter.GetCombinedMask().c_str());
+
+	EXPECT_EQ(false, filter.GetUseExcludeMask());
+	EXPECT_STREQ(L"", filter.GetCombinedExcludeMask().c_str());
+
+	EXPECT_EQ(false, filter.GetUseSize1());
+	EXPECT_EQ(TFileFilter::eSizeCmp_Greater, filter.GetSizeType1());
+	EXPECT_EQ(0, filter.GetSize1());
+
+	EXPECT_EQ(false, filter.GetUseSize2());
+	EXPECT_EQ(TFileFilter::eSizeCmp_Less, filter.GetSizeType2());
+	EXPECT_EQ(0, filter.GetSize2());
+
+	// dates
+	EXPECT_EQ(TFileFilter::eDateType_Created, filter.GetDateType());
+
+	// date 1
+	EXPECT_EQ(false, filter.GetUseDateTime1());
+	EXPECT_EQ(TFileFilter::eDateCmp_Greater, filter.GetDateCmpType1());
+	EXPECT_EQ(false, filter.GetUseDate1());
+	EXPECT_EQ(false, filter.GetUseTime1());
+//	EXPECT_EQ(TDateTime(), filter.GetDateTime1());
+
+	// date 2
+	EXPECT_EQ(false, filter.GetUseDateTime2());
+	EXPECT_EQ(TFileFilter::eDateCmp_Less, filter.GetDateCmpType2());
+	EXPECT_EQ(false, filter.GetUseDate2());
+	EXPECT_EQ(false, filter.GetUseTime2());
+//	EXPECT_EQ(TDateTime(), filter.GetDateTime2());
+
+	// attributes
+	EXPECT_EQ(false, filter.GetUseAttributes());
+	EXPECT_EQ(2, filter.GetArchive());
+	EXPECT_EQ(2, filter.GetReadOnly());
+	EXPECT_EQ(2, filter.GetHidden());
+	EXPECT_EQ(2, filter.GetSystem());
+	EXPECT_EQ(2, filter.GetDirectory());
+
+}
Index: src/libchcore/Tests/TestsTStringPattern.cpp
===================================================================
diff -u
--- src/libchcore/Tests/TestsTStringPattern.cpp	(revision 0)
+++ src/libchcore/Tests/TestsTStringPattern.cpp	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -0,0 +1,114 @@
+#include "stdafx.h"
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "../TStringPattern.h"
+
+using namespace chcore;
+
+TEST(TestsTStringPattern, DefaultConstruction)
+{
+	TStringPattern patternEmpty;
+	EXPECT_STREQ(L"WC;", patternEmpty.ToSerializedString().c_str());
+	EXPECT_STREQ(L"", patternEmpty.GetPattern().c_str());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+}
+
+TEST(TestsTStringPattern, PatternConstruction)
+{
+	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_Wildcard);
+	EXPECT_STREQ(L"WC;*.*", patternEmpty.ToSerializedString().c_str());
+	EXPECT_STREQ(L"*.*", patternEmpty.GetPattern().c_str());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+}
+
+TEST(TestsTStringPattern, SetPattern)
+{
+	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_Wildcard);
+
+	patternEmpty.SetPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard);
+
+	EXPECT_STREQ(L"WC;*.bat", patternEmpty.ToSerializedString().c_str());
+	EXPECT_STREQ(L"*.bat", patternEmpty.GetPattern().c_str());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+}
+
+TEST(TestsTStringPattern, CreateFromSerializedString)
+{
+	TStringPattern patternEmpty = TStringPattern::CreateFromSerializedString(L"WC;*.*");
+
+	EXPECT_STREQ(L"WC;*.*", patternEmpty.ToSerializedString().c_str());
+	EXPECT_STREQ(L"*.*", patternEmpty.GetPattern().c_str());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+}
+
+TEST(TestsTStringPattern, FromSerializedString)
+{
+	TStringPattern patternEmpty;
+	patternEmpty.FromSerializedString(L"WC;*.*");
+
+	EXPECT_STREQ(L"WC;*.*", patternEmpty.ToSerializedString().c_str());
+	EXPECT_STREQ(L"*.*", patternEmpty.GetPattern().c_str());
+	EXPECT_EQ(TStringPattern::EPatternType::eType_Wildcard, patternEmpty.GetPatternType());
+}
+
+TEST(TestsTStringPattern, Matches_Positive_StarDotBat)
+{
+	TStringPattern patternEmpty(L"*.bat", TStringPattern::EPatternType::eType_Wildcard);
+
+	EXPECT_TRUE(patternEmpty.Matches(L"autorun.bat"));
+}
+
+TEST(TestsTStringPattern, Matches_Negative_StarDotBat)
+{
+	TStringPattern patternEmpty(L"*.bat", TStringPattern::EPatternType::eType_Wildcard);
+
+	EXPECT_FALSE(patternEmpty.Matches(L"autorun.batx"));
+}
+
+TEST(TestsTStringPattern, Matches_Positive_StarDotStar)
+{
+	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_Wildcard);
+
+	EXPECT_TRUE(patternEmpty.Matches(L"autorun.bat"));
+}
+
+TEST(TestsTStringPattern, Matches_Negative_StarDotStar)
+{
+	TStringPattern patternEmpty(L"*.*", TStringPattern::EPatternType::eType_Wildcard);
+
+	EXPECT_FALSE(patternEmpty.Matches(L"autorun"));
+}
+
+///////////////////////////////////////////////////////////
+// Multiple asterisks
+
+TEST(TestsTStringPattern, Matches_Positive_MultiStar)
+{
+	TStringPattern patternEmpty(L"ad*bo*", TStringPattern::EPatternType::eType_Wildcard);
+
+	EXPECT_TRUE(patternEmpty.Matches(L"addon-boo.bat"));
+}
+
+TEST(TestsTStringPattern, Matches_Negative_MultiStar)
+{
+	TStringPattern patternEmpty(L"ad*bo*", TStringPattern::EPatternType::eType_Wildcard);
+
+	EXPECT_FALSE(patternEmpty.Matches(L"addon-doo.bat"));
+}
+
+////////////////////////////////////////////////////////////
+// asterisks
+
+TEST(TestsTStringPattern, Matches_Positive_QuestionMultiPos)
+{
+	TStringPattern patternEmpty(L"a??b?r", TStringPattern::EPatternType::eType_Wildcard);
+
+	EXPECT_TRUE(patternEmpty.Matches(L"arbbar"));
+}
+
+TEST(TestsTStringPattern, Matches_Negative_QuestionMultiPos)
+{
+	TStringPattern patternEmpty(L"a??b?r", TStringPattern::EPatternType::eType_Wildcard);
+
+	EXPECT_FALSE(patternEmpty.Matches(L"arbxar"));
+}
Index: src/libchcore/Tests/TestsTStringPatternArray.cpp
===================================================================
diff -u
--- src/libchcore/Tests/TestsTStringPatternArray.cpp	(revision 0)
+++ src/libchcore/Tests/TestsTStringPatternArray.cpp	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -0,0 +1,149 @@
+#include "stdafx.h"
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "../TStringPatternArray.h"
+#include "../TStringArray.h"
+
+using namespace chcore;
+
+TEST(TestsTStringPatternArray, DefaultConstruction)
+{
+	TStringPatternArray arrPatterns;
+
+	EXPECT_EQ(0, arrPatterns.GetCount());
+}
+
+TEST(TestsTStringPatternArray, AddElements)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+
+	EXPECT_EQ(2, arrPatterns.GetCount());
+	EXPECT_STREQ(L"WC;*.bat", arrPatterns.GetAt(0).ToSerializedString().c_str());
+	EXPECT_STREQ(L"WC;*.exe", arrPatterns.GetAt(1).ToSerializedString().c_str());
+}
+
+TEST(TestsTStringPatternArray, InsertAt)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.InsertAt(0, TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.InsertAt(0, TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+
+	EXPECT_EQ(2, arrPatterns.GetCount());
+	EXPECT_STREQ(L"WC;*.bat", arrPatterns.GetAt(1).ToSerializedString().c_str());
+	EXPECT_STREQ(L"WC;*.exe", arrPatterns.GetAt(0).ToSerializedString().c_str());
+}
+
+TEST(TestsTStringPatternArray, SetAt)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+
+	arrPatterns.SetAt(0, TStringPattern(L"*.com", TStringPattern::EPatternType::eType_Wildcard));
+
+	EXPECT_EQ(2, arrPatterns.GetCount());
+	EXPECT_STREQ(L"WC;*.com", arrPatterns.GetAt(0).ToSerializedString().c_str());
+	EXPECT_STREQ(L"WC;*.exe", arrPatterns.GetAt(1).ToSerializedString().c_str());
+}
+
+TEST(TestsTStringPatternArray, RemoveAt)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+
+	arrPatterns.RemoveAt(0);
+
+	EXPECT_EQ(1, arrPatterns.GetCount());
+	EXPECT_STREQ(L"WC;*.exe", arrPatterns.GetAt(0).ToSerializedString().c_str());
+}
+
+TEST(TestsTStringPatternArray, Clear)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+
+	arrPatterns.Clear();
+
+	EXPECT_EQ(0, arrPatterns.GetCount());
+}
+
+/////////////////////////////////////////////////
+// matches any
+TEST(TestsTStringPatternArray, MatchesAny_Positive)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+
+	EXPECT_TRUE(arrPatterns.MatchesAny(L"autostart.bat"));
+}
+
+TEST(TestsTStringPatternArray, MatchesAny_Negative)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"*.exe", TStringPattern::EPatternType::eType_Wildcard));
+
+	EXPECT_FALSE(arrPatterns.MatchesAny(L"autostart.com"));
+}
+
+/////////////////////////////////////////////////
+// matches all
+TEST(TestsTStringPatternArray, MatchesAll_Positive)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"autostart.*", TStringPattern::EPatternType::eType_Wildcard));
+
+	EXPECT_TRUE(arrPatterns.MatchesAll(L"autostart.bat"));
+}
+
+TEST(TestsTStringPatternArray, MatchesAll_Negative)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"autostart.*", TStringPattern::EPatternType::eType_Wildcard));
+
+	EXPECT_FALSE(arrPatterns.MatchesAll(L"autostart.exe"));
+}
+
+/////////////////////////////////////////////////
+// serialization
+TEST(TestsTStringPatternArray, ToStringArray)
+{
+	TStringPatternArray arrPatterns;
+
+	arrPatterns.Add(TStringPattern(L"*.bat", TStringPattern::EPatternType::eType_Wildcard));
+	arrPatterns.Add(TStringPattern(L"autostart.*", TStringPattern::EPatternType::eType_Wildcard));
+
+	TStringArray arrElements = arrPatterns.ToStringArray();
+	EXPECT_EQ(2, arrElements.GetCount());
+	EXPECT_STREQ(L"WC;*.bat", arrElements.GetAt(0).c_str());
+	EXPECT_STREQ(L"WC;autostart.*", arrElements.GetAt(1).c_str());
+}
+
+TEST(TestsTStringPatternArray, FromStringArray)
+{
+	TStringArray arrElements;
+	arrElements.Add(L"WC;*.bat");
+	arrElements.Add(L"WC;autostart.*");
+
+	TStringPatternArray arrPatterns;
+	arrPatterns.FromStringArray(arrElements);
+
+	EXPECT_STREQ(L"WC;*.bat", arrPatterns.GetAt(0).ToSerializedString().c_str());
+	EXPECT_STREQ(L"WC;autostart.*", arrPatterns.GetAt(1).ToSerializedString().c_str());
+}
Index: src/libchcore/libchcore.vc140.vcxproj
===================================================================
diff -u -rd6c3523b8a96c26c0c448dc35964d172661e9be5 -r2755e12daeccb1935f569e7235e685e566b0b098
--- src/libchcore/libchcore.vc140.vcxproj	(.../libchcore.vc140.vcxproj)	(revision d6c3523b8a96c26c0c448dc35964d172661e9be5)
+++ src/libchcore/libchcore.vc140.vcxproj	(.../libchcore.vc140.vcxproj)	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -492,6 +492,7 @@
     <ClInclude Include="ConfigNode.h" />
     <ClInclude Include="ConfigNodeContainer.h" />
     <ClInclude Include="EFeedbackResult.h" />
+    <ClInclude Include="EFileError.h" />
     <ClInclude Include="ESubTaskTypes.h" />
     <ClInclude Include="IColumnsDefinition.h" />
     <ClInclude Include="IFeedbackHandler.h" />
@@ -516,9 +517,12 @@
     <ClInclude Include="TFakeFileSerializer.h" />
     <ClInclude Include="TFeedbackHandlerBase.h" />
     <ClInclude Include="TFeedbackHandlerWrapper.h" />
+    <ClInclude Include="TFileAlreadyExistsFilter.h" />
+    <ClInclude Include="TFileErrorFilter.h" />
     <ClInclude Include="TFileTime.h" />
     <ClInclude Include="TModificationTracker.h" />
     <ClInclude Include="TModPathContainer.h" />
+    <ClInclude Include="TNotEnoughSpaceFilter.h" />
     <ClInclude Include="TObsoleteFiles.h" />
     <ClInclude Include="TOverlappedDataBufferQueue.h" />
     <ClInclude Include="TPathContainer.h" />
@@ -544,6 +548,8 @@
     <ClInclude Include="TSQLiteTaskSchema.h" />
     <ClInclude Include="TSQLiteTransaction.h" />
     <ClInclude Include="TStringException.h" />
+    <ClInclude Include="TStringPattern.h" />
+    <ClInclude Include="TStringPatternArray.h" />
     <ClInclude Include="TSubTaskArray.h" />
     <ClInclude Include="TSubTaskArrayStatsSnapshot.h" />
     <ClInclude Include="TSubTaskBase.h" />
@@ -636,6 +642,12 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="Tests\TestsTFileFilter.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+    </ClCompile>
     <ClCompile Include="Tests\TestsTModificationTracker.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -690,6 +702,18 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="Tests\TestsTStringPattern.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="Tests\TestsTStringPatternArray.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+    </ClCompile>
     <ClCompile Include="Tests\TOverlappedDataBufferQueueTests.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -706,8 +730,11 @@
     <ClCompile Include="TFakeFileSerializer.cpp" />
     <ClCompile Include="TFeedbackHandlerBase.cpp" />
     <ClCompile Include="TFeedbackHandlerWrapper.cpp" />
+    <ClCompile Include="TFileAlreadyExistsFilter.cpp" />
+    <ClCompile Include="TFileErrorFilter.cpp" />
     <ClCompile Include="TFileTime.cpp" />
     <ClCompile Include="TModPathContainer.cpp" />
+    <ClCompile Include="TNotEnoughSpaceFilter.cpp" />
     <ClCompile Include="TObsoleteFiles.cpp" />
     <ClCompile Include="TOverlappedDataBufferQueue.cpp" />
     <ClCompile Include="TPathContainer.cpp" />
@@ -732,6 +759,8 @@
     <ClCompile Include="TSQLiteTaskSchema.cpp" />
     <ClCompile Include="TSQLiteTransaction.cpp" />
     <ClCompile Include="TStringException.cpp" />
+    <ClCompile Include="TStringPattern.cpp" />
+    <ClCompile Include="TStringPatternArray.cpp" />
     <ClCompile Include="TSubTaskArray.cpp" />
     <ClCompile Include="TSubTaskArrayStatsSnapshot.cpp" />
     <ClCompile Include="TSubTaskBase.cpp" />
Index: src/libchcore/libchcore.vc140.vcxproj.filters
===================================================================
diff -u -r7972b0944e0a947144fbdb93262f7d73ac528dc7 -r2755e12daeccb1935f569e7235e685e566b0b098
--- src/libchcore/libchcore.vc140.vcxproj.filters	(.../libchcore.vc140.vcxproj.filters)	(revision 7972b0944e0a947144fbdb93262f7d73ac528dc7)
+++ src/libchcore/libchcore.vc140.vcxproj.filters	(.../libchcore.vc140.vcxproj.filters)	(revision 2755e12daeccb1935f569e7235e685e566b0b098)
@@ -377,6 +377,24 @@
     <ClInclude Include="TBufferSizes.h">
       <Filter>Source Files\Tools\Data Buffer</Filter>
     </ClInclude>
+    <ClInclude Include="TFileErrorFilter.h">
+      <Filter>Source Files\Feedback</Filter>
+    </ClInclude>
+    <ClInclude Include="TFileAlreadyExistsFilter.h">
+      <Filter>Source Files\Feedback</Filter>
+    </ClInclude>
+    <ClInclude Include="TNotEnoughSpaceFilter.h">
+      <Filter>Source Files\Feedback</Filter>
+    </ClInclude>
+    <ClInclude Include="EFileError.h">
+      <Filter>Source Files\Feedback</Filter>
+    </ClInclude>
+    <ClInclude Include="TStringPattern.h">
+      <Filter>Source Files\Tools</Filter>
+    </ClInclude>
+    <ClInclude Include="TStringPatternArray.h">
+      <Filter>Source Files\Tools</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="TSubTaskArray.cpp">
@@ -694,5 +712,29 @@
     <ClCompile Include="Tests\TestsTSharedModificationTracker.cpp">
       <Filter>Tests</Filter>
     </ClCompile>
+    <ClCompile Include="TFileErrorFilter.cpp">
+      <Filter>Source Files\Feedback</Filter>
+    </ClCompile>
+    <ClCompile Include="TFileAlreadyExistsFilter.cpp">
+      <Filter>Source Files\Feedback</Filter>
+    </ClCompile>
+    <ClCompile Include="TNotEnoughSpaceFilter.cpp">
+      <Filter>Source Files\Feedback</Filter>
+    </ClCompile>
+    <ClCompile Include="TStringPattern.cpp">
+      <Filter>Source Files\Tools</Filter>
+    </ClCompile>
+    <ClCompile Include="TStringPatternArray.cpp">
+      <Filter>Source Files\Tools</Filter>
+    </ClCompile>
+    <ClCompile Include="Tests\TestsTStringPatternArray.cpp">
+      <Filter>Tests</Filter>
+    </ClCompile>
+    <ClCompile Include="Tests\TestsTFileFilter.cpp">
+      <Filter>Tests</Filter>
+    </ClCompile>
+    <ClCompile Include="Tests\TestsTStringPattern.cpp">
+      <Filter>Tests</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file