policy-watcher/src/windows/PolicyWatcher.cc
2025-03-24 18:01:09 +01:00

119 lines
3.4 KiB
C++

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
#include <userenv.h>
#include "../PolicyWatcher.hh"
#include "StringPolicy.hh"
#include "NumberPolicy.hh"
#include "BooleanPolicy.hh"
using namespace Napi;
PolicyWatcher::PolicyWatcher(std::string vendorName, std::string productName, const Function &okCallback)
: AsyncProgressQueueWorker(okCallback),
vendorName(vendorName),
productName(productName)
{
}
PolicyWatcher::~PolicyWatcher()
{
UnregisterGPNotification(handles[2]);
UnregisterGPNotification(handles[3]);
CloseHandle(handles[0]);
CloseHandle(handles[1]);
CloseHandle(handles[2]);
CloseHandle(handles[3]);
}
void PolicyWatcher::AddStringPolicy(const std::string name)
{
policies.push_back(std::make_unique<StringPolicy>(name, vendorName, productName));
}
void PolicyWatcher::AddNumberPolicy(const std::string name)
{
policies.push_back(std::make_unique<NumberPolicy>(name, vendorName, productName));
}
void PolicyWatcher::AddBooleanPolicy(const std::string name)
{
policies.push_back(std::make_unique<BooleanPolicy>(name, productName));
}
void PolicyWatcher::OnExecute(Napi::Env env)
{
if ((handles[0] = CreateEvent(NULL, false, false, NULL)) == NULL)
return SetError("Failed to create exit event");
if ((handles[1] = CreateEvent(NULL, false, false, NULL)) == NULL)
return SetError("Failed to create dispose event");
if ((handles[2] = CreateEvent(NULL, false, false, NULL)) == NULL)
return SetError("Failed to create machine GP event");
if ((handles[3] = CreateEvent(NULL, false, false, NULL)) == NULL)
return SetError("Failed to create user GP event");
if (!RegisterGPNotification(handles[2], TRUE))
return SetError("Failed to register machine GP event");
if (!RegisterGPNotification(handles[3], FALSE))
return SetError("Failed to register user GP event");
AsyncProgressQueueWorker::OnExecute(env);
}
void PolicyWatcher::Execute(const ExecutionProgress &progress)
{
bool first = true;
while (TRUE)
{
std::vector<const Policy *> updatedPolicies;
bool update = false;
updatedPolicies.clear();
for (auto &policy : policies)
{
switch (policy->refresh())
{
case PolicyRefreshResult::Updated:
updatedPolicies.push_back(policy.get());
update = true;
break;
case PolicyRefreshResult::Unchanged:
updatedPolicies.push_back(policy.get());
break;
case PolicyRefreshResult::Removed:
update = true;
break;
}
}
if (first || update)
progress.Send(&updatedPolicies[0], updatedPolicies.size());
first = false;
auto dwResult = WaitForMultipleObjects(4, handles, FALSE, INFINITE);
if (dwResult == WAIT_FAILED || (dwResult - WAIT_OBJECT_0) == 0 || (dwResult - WAIT_OBJECT_0) == 1 /* someone called dispose() */)
break;
}
}
void PolicyWatcher::OnProgress(const Policy *const *policies, size_t count)
{
HandleScope scope(Env());
auto result = Object::New(Env());
for (size_t i = 0; i < count; i++)
result.Set(policies[i]->name, policies[i]->getValue(Env()));
Callback().Call(Receiver().Value(), {result});
}
void PolicyWatcher::Dispose()
{
SetEvent(handles[1]);
}