NightLightRegistryObserver.h
1 #pragma once 2 #include <wtypes.h> 3 #include <string> 4 #include <functional> 5 #include <thread> 6 #include <atomic> 7 #include <mutex> 8 9 class NightLightRegistryObserver 10 { 11 public: 12 NightLightRegistryObserver(HKEY root, const std::wstring& subkey, std::function<void()> callback) : 13 _root(root), _subkey(subkey), _callback(std::move(callback)), _stop(false) 14 { 15 _thread = std::thread([this]() { this->Run(); }); 16 } 17 18 ~NightLightRegistryObserver() 19 { 20 Stop(); 21 } 22 23 void Stop() 24 { 25 _stop = true; 26 27 { 28 std::lock_guard<std::mutex> lock(_mutex); 29 if (_event) 30 SetEvent(_event); 31 } 32 33 if (_thread.joinable()) 34 _thread.join(); 35 36 std::lock_guard<std::mutex> lock(_mutex); 37 if (_hKey) 38 { 39 RegCloseKey(_hKey); 40 _hKey = nullptr; 41 } 42 43 if (_event) 44 { 45 CloseHandle(_event); 46 _event = nullptr; 47 } 48 } 49 50 51 private: 52 void Run() 53 { 54 { 55 std::lock_guard<std::mutex> lock(_mutex); 56 if (RegOpenKeyExW(_root, _subkey.c_str(), 0, KEY_NOTIFY, &_hKey) != ERROR_SUCCESS) 57 return; 58 59 _event = CreateEventW(nullptr, TRUE, FALSE, nullptr); 60 if (!_event) 61 { 62 RegCloseKey(_hKey); 63 _hKey = nullptr; 64 return; 65 } 66 } 67 68 while (!_stop) 69 { 70 HKEY hKeyLocal = nullptr; 71 HANDLE eventLocal = nullptr; 72 73 { 74 std::lock_guard<std::mutex> lock(_mutex); 75 if (_stop) 76 break; 77 78 hKeyLocal = _hKey; 79 eventLocal = _event; 80 } 81 82 if (!hKeyLocal || !eventLocal) 83 break; 84 85 if (_stop) 86 break; 87 88 if (RegNotifyChangeKeyValue(hKeyLocal, FALSE, REG_NOTIFY_CHANGE_LAST_SET, eventLocal, TRUE) != ERROR_SUCCESS) 89 break; 90 91 DWORD wait = WaitForSingleObject(eventLocal, INFINITE); 92 if (_stop || wait == WAIT_FAILED) 93 break; 94 95 ResetEvent(eventLocal); 96 97 if (!_stop && _callback) 98 { 99 try 100 { 101 _callback(); 102 } 103 catch (...) 104 { 105 } 106 } 107 } 108 109 { 110 std::lock_guard<std::mutex> lock(_mutex); 111 if (_hKey) 112 { 113 RegCloseKey(_hKey); 114 _hKey = nullptr; 115 } 116 117 if (_event) 118 { 119 CloseHandle(_event); 120 _event = nullptr; 121 } 122 } 123 } 124 125 126 HKEY _root; 127 std::wstring _subkey; 128 std::function<void()> _callback; 129 HANDLE _event = nullptr; 130 HKEY _hKey = nullptr; 131 std::thread _thread; 132 std::atomic<bool> _stop; 133 std::mutex _mutex; 134 };