From 33b1a277e18a0b297cf58322ee94c881f03a93ad Mon Sep 17 00:00:00 2001 From: Tina Murimi Date: Tue, 22 Aug 2023 17:22:57 +0300 Subject: [PATCH] Only prepend if not root folder and validate directory source (#154) --- .gitignore | 1 + .../LogMonitorTests/ConfigFileParserTests.cpp | 75 +++++++++++---- .../LogMonitorTests/LogMonitorTests.cpp | 2 +- LogMonitor/LogMonitorTests/pch.h | 2 +- LogMonitor/docs/README.md | 22 +++++ .../src/LogMonitor/ConfigFileParser.cpp | 46 ++++++++- ...Utilities.cpp => FileMonitorUtilities.cpp} | 95 ++++++++++++------- .../FileMonitor/FileMonitorUtilities.h | 47 +++++++++ .../src/LogMonitor/FileMonitor/Utilities.h | 37 -------- LogMonitor/src/LogMonitor/LogFileMonitor.cpp | 30 ++++-- LogMonitor/src/LogMonitor/LogFileMonitor.h | 2 + LogMonitor/src/LogMonitor/LogMonitor.vcxproj | 4 +- .../src/LogMonitor/LogMonitor.vcxproj.filters | 4 +- .../src/LogMonitor/Parser/ConfigFileParser.h | 2 + .../src/LogMonitor/Parser/LoggerSettings.h | 8 -- LogMonitor/src/LogMonitor/Utility.cpp | 6 ++ LogMonitor/src/LogMonitor/Utility.h | 17 +++- LogMonitor/src/LogMonitor/pch.h | 2 +- 18 files changed, 287 insertions(+), 115 deletions(-) rename LogMonitor/src/LogMonitor/FileMonitor/{Utilities.cpp => FileMonitorUtilities.cpp} (66%) create mode 100644 LogMonitor/src/LogMonitor/FileMonitor/FileMonitorUtilities.h delete mode 100644 LogMonitor/src/LogMonitor/FileMonitor/Utilities.h diff --git a/.gitignore b/.gitignore index 3e759b7..4ec8368 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ bld/ # Visual Studio 2015/2017 cache/options directory .vs/ +.vscode/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ diff --git a/LogMonitor/LogMonitorTests/ConfigFileParserTests.cpp b/LogMonitor/LogMonitorTests/ConfigFileParserTests.cpp index 59df307..a145fe5 100644 --- a/LogMonitor/LogMonitorTests/ConfigFileParserTests.cpp +++ b/LogMonitor/LogMonitorTests/ConfigFileParserTests.cpp @@ -1337,6 +1337,65 @@ namespace LogMonitorTests } } + TEST_METHOD(TestRootDirectoryConfigurations) + { + + const std::wstring directory = L"C:\\"; + bool includeSubdirectories = false; + + std::wstring configFileStr; + std::wstring configFileStrFormat = + L"{ \ + \"LogConfig\": { \ + \"sources\": [ \ + {\ + \"type\": \"File\",\ + \"directory\": \"%s\",\ + \"includeSubdirectories\": %s\ + }\ + ]\ + }\ + }"; + + // Valid: Root dir and includeSubdirectories = false + { + configFileStr = Utility::FormatString( + configFileStrFormat.c_str(), + Utility::ReplaceAll(directory, L"\\", L"\\\\").c_str(), + includeSubdirectories ? L"true" : L"false"); + + JsonFileParser jsonParser(configFileStr); + LoggerSettings settings; + + bool success = ReadConfigFile(jsonParser, settings); + Assert::IsTrue(success); + + std::wstring output = RecoverOuput(); + Assert::AreEqual(L"", output.c_str()); + } + + // Invalid: Root dir and includeSubdirectories = true + { + includeSubdirectories = true; + configFileStr = Utility::FormatString( + configFileStrFormat.c_str(), + Utility::ReplaceAll(directory, L"\\", L"\\\\").c_str(), + includeSubdirectories ? L"true" : L"false"); + + fflush(stdout); + ZeroMemory(bigOutBuf, sizeof(bigOutBuf)); + + JsonFileParser jsonParser(configFileStr); + LoggerSettings settings; + + bool success = ReadConfigFile(jsonParser, settings); + Assert::IsTrue(success); + + std::wstring output = RecoverOuput(); + Assert::IsTrue(output.find(L"WARNING") != std::wstring::npos); + } + } + /// /// Check that invalid ETW sources are not returned by ReadConfigFile. /// @@ -1557,28 +1616,12 @@ namespace LogMonitorTests TEST_METHOD(TestInvalidWaitInSeconds) { std::wstring directory = L"C:\\LogMonitor\\logs"; - - std::wstring configFileStrFormat = - L"{ \ - \"LogConfig\": { \ - \"sources\": [ \ - {\ - \"type\": \"File\",\ - \"directory\": \"%s\",\ - \"waitInSeconds\": %f\ - }\ - ]\ - }\ - }"; - TestInvalidWaitInSecondsValues(L"-10", false); TestInvalidWaitInSecondsValues(L"-Inf", true); } private: - void TestWaitInSecondsValues(std::wstring waitInSeconds, bool asString = false) { - std::wstring configFileStrFormat; std::wstring directory = L"C:\\LogMonitor\\logs"; std::wstring configFileStr = GetConfigFileStrFormat(directory, waitInSeconds, asString); diff --git a/LogMonitor/LogMonitorTests/LogMonitorTests.cpp b/LogMonitor/LogMonitorTests/LogMonitorTests.cpp index 9ec03f5..5aba0f2 100644 --- a/LogMonitor/LogMonitorTests/LogMonitorTests.cpp +++ b/LogMonitor/LogMonitorTests/LogMonitorTests.cpp @@ -9,7 +9,7 @@ #include "../src/LogMonitor/EtwMonitor.cpp" #include "../src/LogMonitor/EventMonitor.cpp" #include "../src/LogMonitor/JsonFileParser.cpp" -#include "../src/LogMonitor/FileMonitor/Utilities.cpp" +#include "../src/LogMonitor/FileMonitor/FileMonitorUtilities.cpp" #include "../src/LogMonitor/LogFileMonitor.cpp" #include "../src/LogMonitor/ProcessMonitor.cpp" #include "../src/LogMonitor/Utility.cpp" diff --git a/LogMonitor/LogMonitorTests/pch.h b/LogMonitor/LogMonitorTests/pch.h index 2e83e08..c6ad8c3 100644 --- a/LogMonitor/LogMonitorTests/pch.h +++ b/LogMonitor/LogMonitorTests/pch.h @@ -59,7 +59,7 @@ #include "../src/LogMonitor/LogWriter.h" #include "../src/LogMonitor/EtwMonitor.h" #include "../src/LogMonitor/EventMonitor.h" -#include "../src/LogMonitor/FileMonitor/Utilities.h" +#include "../src/LogMonitor/FileMonitor/FileMonitorUtilities.h" #include "../src/LogMonitor/LogFileMonitor.h" #include "../src/LogMonitor/ProcessMonitor.h" #include "Utility.h" diff --git a/LogMonitor/docs/README.md b/LogMonitor/docs/README.md index 63981cb..820233d 100644 --- a/LogMonitor/docs/README.md +++ b/LogMonitor/docs/README.md @@ -273,6 +273,28 @@ This will monitor any changes in log files matching a specified filter, given th } ``` +**Note:** When the directory is the root directory (e.g. C:\\ ) we can only monitor a file that is in the root directory, not a subfolder. This is due to access issues (even when running LogMonitor as an Admin) for some of the folders in the root directory. Therefore, `includeSubdirectories` must be `false` for the root directory. See example below: + +```json +{ + "LogConfig": { + "sources": [ + { + "type": "File", + "directory": "C:", + "filter": "*.log", + "includeSubdirectories": false + } + ] + } +} +``` +When the root directory is passed and `includeSubdirectories = true`, we get an error: +``` +ERROR: LoggerSettings: Invalid Source File atrribute 'directory' (C:) and 'includeSubdirectories' (true).'includeSubdirectories' attribute cannot be 'true' for the root directory +WARNING: Failed to parse configuration file. Error retrieving source attributes. Invalid source +``` + ## Process Monitoring ### Description diff --git a/LogMonitor/src/LogMonitor/ConfigFileParser.cpp b/LogMonitor/src/LogMonitor/ConfigFileParser.cpp index cb3a633..bfd188d 100644 --- a/LogMonitor/src/LogMonitor/ConfigFileParser.cpp +++ b/LogMonitor/src/LogMonitor/ConfigFileParser.cpp @@ -6,6 +6,7 @@ #include "pch.h" #include "./Parser/ConfigFileParser.h" #include "./LogWriter.h" +#include "./FileMonitor/FileMonitorUtilities.h" /// ConfigFileParser.cpp /// @@ -306,8 +307,13 @@ ReadSourceAttributes( // * directory // * filter // - else if (_wcsnicmp(key.c_str(), JSON_TAG_DIRECTORY, _countof(JSON_TAG_DIRECTORY)) == 0 - || _wcsnicmp(key.c_str(), JSON_TAG_FILTER, _countof(JSON_TAG_FILTER)) == 0) + else if (_wcsnicmp(key.c_str(), JSON_TAG_DIRECTORY, _countof(JSON_TAG_DIRECTORY)) == 0) + { + std::wstring directory = Parser.ParseStringValue(); + FileMonitorUtilities::ParseDirectoryValue(directory); + Attributes[key] = new std::wstring(directory); + } + else if (_wcsnicmp(key.c_str(), JSON_TAG_FILTER, _countof(JSON_TAG_FILTER)) == 0) { Attributes[key] = new std::wstring(Parser.ParseStringValue()); } @@ -396,6 +402,12 @@ ReadSourceAttributes( } while (Parser.ParseNextObjectElement()); } + bool isSourceFileValid = ValidateDirectoryAttributes(Attributes); + if (!isSourceFileValid) + { + success = false; + } + return success; } @@ -640,6 +652,36 @@ AddNewSource( return true; } +/// +/// Validates that when root directory is passed, includeSubdirectories is false +/// +/// \param Attributes An AttributesMap that contains the attributes of the new source objet. +/// \return false when root directory is passed, includeSubdirectories = true. Otherwise, true +bool ValidateDirectoryAttributes(_In_ AttributesMap &Attributes) +{ + if (!Utility::ConfigAttributeExists(Attributes, JSON_TAG_DIRECTORY) || + !Utility::ConfigAttributeExists(Attributes, JSON_TAG_INCLUDE_SUBDIRECTORIES)) + { + return true; + } + + std::wstring directory = *(std::wstring *)Attributes[JSON_TAG_DIRECTORY]; + const bool includeSubdirectories = *(bool *)Attributes[JSON_TAG_INCLUDE_SUBDIRECTORIES]; + + // Check if Log file monitor config is valid + const bool isValid = FileMonitorUtilities::IsValidSourceFile(directory, includeSubdirectories); + if (!isValid) + { + logWriter.TraceError( + Utility::FormatString( + L"LoggerSettings: Invalid Source File atrribute 'directory' (%s) and 'includeSubdirectories' (%s)." + L"'includeSubdirectories' attribute cannot be 'true' for the root directory", + directory.c_str(), includeSubdirectories ? L"true" : L"false") + .c_str()); + } + return isValid; +} + /// /// Debug function /// diff --git a/LogMonitor/src/LogMonitor/FileMonitor/Utilities.cpp b/LogMonitor/src/LogMonitor/FileMonitor/FileMonitorUtilities.cpp similarity index 66% rename from LogMonitor/src/LogMonitor/FileMonitor/Utilities.cpp rename to LogMonitor/src/LogMonitor/FileMonitor/FileMonitorUtilities.cpp index ddaf2d9..20c77f2 100644 --- a/LogMonitor/src/LogMonitor/FileMonitor/Utilities.cpp +++ b/LogMonitor/src/LogMonitor/FileMonitor/FileMonitorUtilities.cpp @@ -4,21 +4,22 @@ // #include "pch.h" +#include /** * Warapper around Create Event API - * + * * @param bManualReset * @param bInitialState - * + * * return event handle -*/ -HANDLE CreateFileMonitorEvent( - _In_ BOOL bManualReset, - _In_ BOOL bInitialState -) { + */ +HANDLE FileMonitorUtilities::CreateFileMonitorEvent( + _In_ BOOL bManualReset, + _In_ BOOL bInitialState) +{ HANDLE event = CreateEvent(nullptr, bManualReset, bInitialState, nullptr); - if(!event) + if (!event) { throw std::system_error(std::error_code(GetLastError(), std::system_category()), "CreateEvent"); } @@ -26,25 +27,28 @@ HANDLE CreateFileMonitorEvent( return event; } - /** * @brief Get Log Directory Handle Object - * + * * @param logDirectory - path to get handle * @param stopEvent - pass an event to use when we want to stop waiting - * - * @return HANDLE + * + * @return HANDLE */ -HANDLE GetLogDirHandle(_In_ std::wstring logDirectory, _In_ HANDLE stopEvent, _In_ std::double_t waitInSeconds) { +HANDLE FileMonitorUtilities::GetLogDirHandle( + _In_ std::wstring logDirectory, + _In_ HANDLE stopEvent, + _In_ std::double_t waitInSeconds) +{ DWORD status = ERROR_SUCCESS; - HANDLE logDirHandle = CreateFileW (logDirectory.c_str(), - FILE_LIST_DIRECTORY, - FILE_SHARE_READ | FILE_SHARE_WRITE, - nullptr, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, - nullptr); + HANDLE logDirHandle = CreateFileW(logDirectory.c_str(), + FILE_LIST_DIRECTORY, + FILE_SHARE_READ | FILE_SHARE_WRITE, + nullptr, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, + nullptr); if (logDirHandle == INVALID_HANDLE_VALUE) { @@ -54,7 +58,7 @@ HANDLE GetLogDirHandle(_In_ std::wstring logDirectory, _In_ HANDLE stopEvent, _I if (status == ERROR_FILE_NOT_FOUND || status == ERROR_PATH_NOT_FOUND) { - std::wstring waitLogMesage = _GetWaitLogMessage(logDirectory, waitInSeconds); + std::wstring waitLogMesage = FileMonitorUtilities::_GetWaitLogMessage(logDirectory, waitInSeconds); logWriter.TraceInfo(waitLogMesage.c_str()); // @@ -70,14 +74,12 @@ HANDLE GetLogDirHandle(_In_ std::wstring logDirectory, _In_ HANDLE stopEvent, _I logWriter.TraceError( Utility::FormatString( L"Failed to create timer object. Log directory %ws will not be monitored for log entries. Error=%d", - logDirectory.c_str(), - status - ).c_str() - ); + logDirectory.c_str(), status).c_str()); return INVALID_HANDLE_VALUE; } - logDirHandle = _RetryOpenDirectoryWithInterval(logDirectory, waitInSeconds, stopEvent, timerEvent); + logDirHandle = FileMonitorUtilities::_RetryOpenDirectoryWithInterval( + logDirectory, waitInSeconds, stopEvent, timerEvent); CancelWaitableTimer(timerEvent); CloseHandle(timerEvent); @@ -86,7 +88,32 @@ HANDLE GetLogDirHandle(_In_ std::wstring logDirectory, _In_ HANDLE stopEvent, _I return logDirHandle; } -HANDLE _RetryOpenDirectoryWithInterval( +void FileMonitorUtilities::ParseDirectoryValue(_Inout_ std::wstring &directory) +{ + while (!directory.empty() && directory[directory.size() - 1] == L'\\') + { + directory.resize(directory.size() - 1); + } +} + +bool FileMonitorUtilities::IsValidSourceFile(_In_ std::wstring directory, _In_ bool includeSubdirectories) +{ + bool isRootFolder = CheckIsRootFolder(directory); + + // The source file is invalid if the directory is a root folder and includeSubdirectories = true + // This is because we do not monitor subfolders in the root directory + return !(isRootFolder && includeSubdirectories); +} + +bool FileMonitorUtilities::CheckIsRootFolder(_In_ std::wstring dirPath) +{ + std::wregex pattern(L"^\\w:?$"); + + std::wsmatch matches; + return std::regex_search(dirPath, matches, pattern); +} + +HANDLE FileMonitorUtilities::_RetryOpenDirectoryWithInterval( std::wstring logDirectory, std::double_t waitInSeconds, HANDLE stopEvent, @@ -99,10 +126,10 @@ HANDLE _RetryOpenDirectoryWithInterval( const int eventsCount = 2; HANDLE dirOpenEvents[eventsCount] = {stopEvent, timerEvent}; - while (_IsFileErrorStatus(status) && elapsedTime < waitInSeconds) + while (FileMonitorUtilities::_IsFileErrorStatus(status) && elapsedTime < waitInSeconds) { - int waitInterval = _GetWaitInterval(waitInSeconds, elapsedTime); - LARGE_INTEGER timeToWait = _ConvertWaitIntervalToLargeInt(waitInterval); + int waitInterval = FileMonitorUtilities::_GetWaitInterval(waitInSeconds, elapsedTime); + LARGE_INTEGER timeToWait = FileMonitorUtilities::_ConvertWaitIntervalToLargeInt(waitInterval); BOOL waitableTimer = SetWaitableTimer(timerEvent, &timeToWait, 0, NULL, NULL, 0); if (!waitableTimer) @@ -181,7 +208,7 @@ HANDLE _RetryOpenDirectoryWithInterval( } // Converts the time to wait to a large integer -LARGE_INTEGER _ConvertWaitIntervalToLargeInt(int timeInterval) +LARGE_INTEGER FileMonitorUtilities::_ConvertWaitIntervalToLargeInt(int timeInterval) { LARGE_INTEGER liDueTime{}; @@ -191,7 +218,7 @@ LARGE_INTEGER _ConvertWaitIntervalToLargeInt(int timeInterval) } // Returns the time (in seconds) to wait based on the specified waitInSeconds -int _GetWaitInterval(std::double_t waitInSeconds, int elapsedTime) +int FileMonitorUtilities::_GetWaitInterval(std::double_t waitInSeconds, int elapsedTime) { if (isinf(waitInSeconds)) { @@ -207,12 +234,12 @@ int _GetWaitInterval(std::double_t waitInSeconds, int elapsedTime) return remainingTime <= WAIT_INTERVAL ? remainingTime : WAIT_INTERVAL; } -bool _IsFileErrorStatus(DWORD status) +bool FileMonitorUtilities::_IsFileErrorStatus(DWORD status) { return status == ERROR_FILE_NOT_FOUND || status == ERROR_PATH_NOT_FOUND; } -std::wstring _GetWaitLogMessage(_In_ std::wstring logDirectory, _In_ std::double_t waitInSeconds) +std::wstring FileMonitorUtilities::_GetWaitLogMessage(std::wstring logDirectory, std::double_t waitInSeconds) { if (isinf(waitInSeconds)) { diff --git a/LogMonitor/src/LogMonitor/FileMonitor/FileMonitorUtilities.h b/LogMonitor/src/LogMonitor/FileMonitor/FileMonitorUtilities.h new file mode 100644 index 0000000..5ad6a3e --- /dev/null +++ b/LogMonitor/src/LogMonitor/FileMonitor/FileMonitorUtilities.h @@ -0,0 +1,47 @@ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// + +#pragma once + +class FileMonitorUtilities final +{ + public: + static const int WAIT_INTERVAL = 15; + + static HANDLE CreateFileMonitorEvent( + _In_ BOOL bManualReset, + _In_ BOOL bInitialState); + + static HANDLE GetLogDirHandle( + _In_ std::wstring logDirectory, + _In_ HANDLE stopEvent, + _In_ std::double_t waitInSeconds); + + static void ParseDirectoryValue(_Inout_ std::wstring &directory); + + static bool IsValidSourceFile(_In_ std::wstring directory, bool includeSubdirectories); + + static bool CheckIsRootFolder(_In_ std::wstring dirPath); + + private: + static HANDLE _RetryOpenDirectoryWithInterval( + std::wstring logDirectory, + std::double_t waitInSeconds, + HANDLE stopEvent, + HANDLE timerEvent); + + static LARGE_INTEGER _ConvertWaitIntervalToLargeInt( + int timeInterval); + + static int _GetWaitInterval( + std::double_t waitInSeconds, + int elapsedTime); + + static bool _IsFileErrorStatus(DWORD status); + + static std::wstring _GetWaitLogMessage( + std::wstring logDirectory, + std::double_t waitInSeconds); +}; diff --git a/LogMonitor/src/LogMonitor/FileMonitor/Utilities.h b/LogMonitor/src/LogMonitor/FileMonitor/Utilities.h deleted file mode 100644 index bb11526..0000000 --- a/LogMonitor/src/LogMonitor/FileMonitor/Utilities.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -// - -#pragma once - -const int WAIT_INTERVAL = 15; - -HANDLE CreateFileMonitorEvent( - _In_ BOOL bManualReset, - _In_ BOOL bInitialState); - -HANDLE GetLogDirHandle( - _In_ std::wstring logDirectory, - _In_ HANDLE stopEvent, - _In_ std::double_t waitInSeconds); - -HANDLE _RetryOpenDirectoryWithInterval( - std::wstring logDirectory, - std::double_t waitInSeconds, - HANDLE stopEvent, - HANDLE timerEvent); - -LARGE_INTEGER _ConvertWaitIntervalToLargeInt( - int timeInterval); - -int _GetWaitInterval( - std::double_t waitInSeconds, - int elapsedTime); - -bool _IsFileErrorStatus( - DWORD status); - -std::wstring _GetWaitLogMessage( - _In_ std::wstring logDirectory, - _In_ std::double_t waitInSeconds); diff --git a/LogMonitor/src/LogMonitor/LogFileMonitor.cpp b/LogMonitor/src/LogMonitor/LogFileMonitor.cpp index a29556c..6c39f10 100644 --- a/LogMonitor/src/LogMonitor/LogFileMonitor.cpp +++ b/LogMonitor/src/LogMonitor/LogFileMonitor.cpp @@ -4,6 +4,7 @@ // #include "pch.h" +#include using namespace std; @@ -57,26 +58,26 @@ LogFileMonitor::LogFileMonitor(_In_ const std::wstring& LogDirectory, InitializeSRWLock(&m_eventQueueLock); - while (!m_logDirectory.empty() && m_logDirectory[ m_logDirectory.size() - 1 ] == L'\\') - { - m_logDirectory.resize(m_logDirectory.size() - 1); - } - m_logDirectory = PREFIX_EXTENDED_PATH + m_logDirectory; + // By default, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, + // we prepend "\?" to the path. Prepending the string "\?" does not allow access to the root directory + // We, therefore, do not prepend for the root directory + bool isRootFolder = CheckIsRootFolder(m_logDirectory); + m_logDirectory = isRootFolder ? m_logDirectory : PREFIX_EXTENDED_PATH + m_logDirectory; if (m_filter.empty()) { m_filter = L"*"; } - m_stopEvent = CreateFileMonitorEvent(TRUE, FALSE); + m_stopEvent = FileMonitorUtilities::CreateFileMonitorEvent(TRUE, FALSE); - m_overlappedEvent = CreateFileMonitorEvent(TRUE, TRUE); + m_overlappedEvent = FileMonitorUtilities::CreateFileMonitorEvent(TRUE, TRUE); m_overlapped.hEvent = m_overlappedEvent; - m_workerThreadEvent = CreateFileMonitorEvent(TRUE, TRUE); + m_workerThreadEvent = FileMonitorUtilities::CreateFileMonitorEvent(TRUE, TRUE); - m_dirMonitorStartedEvent = CreateFileMonitorEvent(TRUE, FALSE); + m_dirMonitorStartedEvent = FileMonitorUtilities::CreateFileMonitorEvent(TRUE, FALSE); m_readLogFilesFromStart = false; @@ -316,7 +317,7 @@ LogFileMonitor::StartLogFileMonitor() dirMonitorStartedEventSignalled = true; // Get Log Dir Handle - HANDLE logDirHandle = GetLogDirHandle(m_logDirectory, m_stopEvent, m_waitInSeconds); + HANDLE logDirHandle = FileMonitorUtilities::GetLogDirHandle(m_logDirectory, m_stopEvent, m_waitInSeconds); if(logDirHandle == INVALID_HANDLE_VALUE) { status = GetLastError(); @@ -2039,3 +2040,12 @@ LogFileMonitor::GetFileId( return status; } + +bool +LogFileMonitor::CheckIsRootFolder(_In_ std::wstring dirPath) +{ + std::wregex pattern(L"^\\w:?$"); + + std::wsmatch matches; + return std::regex_search(dirPath, matches, pattern); +} diff --git a/LogMonitor/src/LogMonitor/LogFileMonitor.h b/LogMonitor/src/LogMonitor/LogFileMonitor.h index dc694f8..0d5c6aa 100644 --- a/LogMonitor/src/LogMonitor/LogFileMonitor.h +++ b/LogMonitor/src/LogMonitor/LogFileMonitor.h @@ -224,4 +224,6 @@ private: _Out_ FILE_ID_INFO& FileId, _In_opt_ HANDLE Handle = INVALID_HANDLE_VALUE ); + + static bool CheckIsRootFolder(_In_ std::wstring dirPath); }; diff --git a/LogMonitor/src/LogMonitor/LogMonitor.vcxproj b/LogMonitor/src/LogMonitor/LogMonitor.vcxproj index 62b3975..92b3de9 100644 --- a/LogMonitor/src/LogMonitor/LogMonitor.vcxproj +++ b/LogMonitor/src/LogMonitor/LogMonitor.vcxproj @@ -159,7 +159,7 @@ - + @@ -176,7 +176,7 @@ - + diff --git a/LogMonitor/src/LogMonitor/LogMonitor.vcxproj.filters b/LogMonitor/src/LogMonitor/LogMonitor.vcxproj.filters index 713f977..56eecf6 100644 --- a/LogMonitor/src/LogMonitor/LogMonitor.vcxproj.filters +++ b/LogMonitor/src/LogMonitor/LogMonitor.vcxproj.filters @@ -24,7 +24,7 @@ Header Files - + Header Files @@ -83,7 +83,7 @@ Source Files - + Source Files diff --git a/LogMonitor/src/LogMonitor/Parser/ConfigFileParser.h b/LogMonitor/src/LogMonitor/Parser/ConfigFileParser.h index 333b02e..4c8d48d 100644 --- a/LogMonitor/src/LogMonitor/Parser/ConfigFileParser.h +++ b/LogMonitor/src/LogMonitor/Parser/ConfigFileParser.h @@ -49,4 +49,6 @@ bool AddNewSource( _Inout_ std::vector >& Sources ); +bool ValidateDirectoryAttributes(_In_ AttributesMap& Attributes); + void _PrintSettings(_Out_ LoggerSettings& Config); diff --git a/LogMonitor/src/LogMonitor/Parser/LoggerSettings.h b/LogMonitor/src/LogMonitor/Parser/LoggerSettings.h index f07f745..081f57d 100644 --- a/LogMonitor/src/LogMonitor/Parser/LoggerSettings.h +++ b/LogMonitor/src/LogMonitor/Parser/LoggerSettings.h @@ -41,14 +41,6 @@ // Define the AttributesMap, that is a map with case // insensitive keys // -struct CaseInsensitiveWideString -{ - bool operator() (const std::wstring& c1, const std::wstring& c2) const { - return _wcsicmp(c1.c_str(), c2.c_str()) < 0; - } -}; - -typedef std::map AttributesMap; enum class EventChannelLogLevel { diff --git a/LogMonitor/src/LogMonitor/Utility.cpp b/LogMonitor/src/LogMonitor/Utility.cpp index 79213eb..aca2c9f 100644 --- a/LogMonitor/src/LogMonitor/Utility.cpp +++ b/LogMonitor/src/LogMonitor/Utility.cpp @@ -306,3 +306,9 @@ void Utility::SanitizeJson(_Inout_ std::wstring& str) i++; } } + +bool Utility::ConfigAttributeExists(AttributesMap& Attributes, std::wstring attributeName) +{ + auto it = Attributes.find(attributeName); + return it != Attributes.end() && it->second != nullptr; +} diff --git a/LogMonitor/src/LogMonitor/Utility.h b/LogMonitor/src/LogMonitor/Utility.h index 7a9548f..9affbf8 100644 --- a/LogMonitor/src/LogMonitor/Utility.h +++ b/LogMonitor/src/LogMonitor/Utility.h @@ -5,6 +5,19 @@ #pragma once +// +// Define the AttributesMap, that is a map with case +// insensitive keys +// +struct CaseInsensitiveWideString +{ + bool operator() (const std::wstring& c1, const std::wstring& c2) const { + return _wcsicmp(c1.c_str(), c2.c_str()) < 0; + } +}; + +typedef std::map AttributesMap; + class Utility final { public: @@ -47,5 +60,7 @@ public: static bool isJsonNumber(_In_ std::wstring& str); - static void SanitizeJson(_Inout_ std::wstring& str); + static void SanitizeJson(_Inout_ std::wstring &str); + + static bool ConfigAttributeExists(_In_ AttributesMap &Attributes, _In_ std::wstring attributeName); }; diff --git a/LogMonitor/src/LogMonitor/pch.h b/LogMonitor/src/LogMonitor/pch.h index 32fe349..230c1d0 100644 --- a/LogMonitor/src/LogMonitor/pch.h +++ b/LogMonitor/src/LogMonitor/pch.h @@ -52,7 +52,7 @@ #include "LogWriter.h" #include "EtwMonitor.h" #include "EventMonitor.h" -#include "FileMonitor/Utilities.h" +#include "FileMonitor/FileMonitorUtilities.h" #include "LogFileMonitor.h" #include "ProcessMonitor.h"