/ src / common / SettingsAPI / FileWatcher.cpp
FileWatcher.cpp
 1  #include "pch.h"
 2  #include "FileWatcher.h"
 3  #include <utils/winapi_error.h>
 4  
 5  std::optional<FILETIME> FileWatcher::MyFileTime()
 6  {
 7      HANDLE hFile = CreateFileW(m_path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
 8      std::optional<FILETIME> result;
 9      if (hFile != INVALID_HANDLE_VALUE)
10      {
11          FILETIME lastWrite;
12          if (GetFileTime(hFile, nullptr, nullptr, &lastWrite))
13          {
14              result = lastWrite;
15          }
16  
17          CloseHandle(hFile);
18      }
19  
20      return result;
21  }
22  
23  FileWatcher::FileWatcher(const std::wstring& path, std::function<void()> callback) :
24      m_path(path),
25      m_callback(callback)
26  {
27      std::filesystem::path fsPath(path);
28      m_file_name = fsPath.filename();
29      std::transform(m_file_name.begin(), m_file_name.end(), m_file_name.begin(), ::towlower);
30      m_folder_change_reader = wil::make_folder_change_reader_nothrow(
31          fsPath.parent_path().c_str(),
32          false,
33          wil::FolderChangeEvents::LastWriteTime,
34          [this](wil::FolderChangeEvent, PCWSTR fileName) {
35              std::wstring lowerFileName(fileName);
36              std::transform(lowerFileName.begin(), lowerFileName.end(), lowerFileName.begin(), ::towlower);
37  
38              if (m_file_name.compare(fileName) == 0)
39              {
40                  auto lastWrite = MyFileTime();
41                  if (!m_lastWrite.has_value())
42                  {
43                      m_lastWrite = lastWrite;
44                  }
45                  else if (lastWrite.has_value())
46                  {
47                      if (m_lastWrite->dwHighDateTime != lastWrite->dwHighDateTime ||
48                          m_lastWrite->dwLowDateTime != lastWrite->dwLowDateTime)
49                      {
50                          m_lastWrite = lastWrite;
51                          m_callback();
52                      }
53                  }
54              }
55          });
56  
57      if (!m_folder_change_reader)
58      {
59          Logger::error(L"Failed to start folder change reader for path {}. {}", path, get_last_error_or_default(GetLastError()));
60      }
61  }
62  
63  FileWatcher::~FileWatcher()
64  {
65      m_folder_change_reader.reset();
66  }