refactor(win32): update MSWindowsSession and MsWindowsWatchdog to use MsWindowsHandle

This commit is contained in:
alfredo1491 2026-05-23 07:45:58 -04:00 committed by Nick Bolton
parent d372462378
commit 6212f9bec6
2 changed files with 38 additions and 21 deletions

View file

@ -8,6 +8,7 @@
#include "arch/win32/XArchWindows.h" #include "arch/win32/XArchWindows.h"
#include "base/Log.h" #include "base/Log.h"
#include "platform/MSWindowsHandle.h"
#include <Wtsapi32.h> #include <Wtsapi32.h>
#include <stdexcept> #include <stdexcept>
@ -19,8 +20,8 @@ MSWindowsSession::MSWindowsSession() : m_activeSessionId(-1)
bool MSWindowsSession::isProcessInSession(const wchar_t *name, PHANDLE process = nullptr) bool MSWindowsSession::isProcessInSession(const wchar_t *name, PHANDLE process = nullptr)
{ {
// first we need to take a snapshot of the running processes // first we need to take a snapshot of the running processes
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); MSWindowsHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
if (snapshot == INVALID_HANDLE_VALUE) { if (snapshot.get() == INVALID_HANDLE_VALUE) {
LOG_ERR("could not get process snapshot"); LOG_ERR("could not get process snapshot");
throw std::runtime_error(windowsErrorToString(GetLastError())); throw std::runtime_error(windowsErrorToString(GetLastError()));
} }
@ -30,7 +31,7 @@ bool MSWindowsSession::isProcessInSession(const wchar_t *name, PHANDLE process =
// get the first process, and if we can't do that then it's // get the first process, and if we can't do that then it's
// unlikely we can go any further // unlikely we can go any further
BOOL gotEntry = Process32First(snapshot, &entry); BOOL gotEntry = Process32First(snapshot.get(), &entry);
if (!gotEntry) { if (!gotEntry) {
LOG_ERR("could not get first process entry"); LOG_ERR("could not get first process entry");
throw std::runtime_error(windowsErrorToString(GetLastError())); throw std::runtime_error(windowsErrorToString(GetLastError()));
@ -55,7 +56,7 @@ bool MSWindowsSession::isProcessInSession(const wchar_t *name, PHANDLE process =
LOG_VERBOSE( LOG_VERBOSE(
"could not get session id for process: %i %s, code=%i", entry.th32ProcessID, entry.szExeFile, GetLastError() "could not get session id for process: %i %s, code=%i", entry.th32ProcessID, entry.szExeFile, GetLastError()
); );
gotEntry = nextProcessEntry(snapshot, &entry); gotEntry = nextProcessEntry(snapshot.get(), &entry);
continue; continue;
} else { } else {
// only pay attention to processes in the active session // only pay attention to processes in the active session
@ -72,7 +73,7 @@ bool MSWindowsSession::isProcessInSession(const wchar_t *name, PHANDLE process =
} }
// now move on to the next entry (if we're not at the end) // now move on to the next entry (if we're not at the end)
gotEntry = nextProcessEntry(snapshot, &entry); gotEntry = nextProcessEntry(snapshot.get(), &entry);
} }
std::wstring nameListJoin; std::wstring nameListJoin;
@ -83,13 +84,15 @@ bool MSWindowsSession::isProcessInSession(const wchar_t *name, PHANDLE process =
LOG_VERBOSE("processes in session %d: %s", m_activeSessionId, nameListJoin.c_str()); LOG_VERBOSE("processes in session %d: %s", m_activeSessionId, nameListJoin.c_str());
CloseHandle(snapshot);
if (pid) { if (pid) {
if (process != nullptr) { if (process != nullptr) {
// now get the process, which we'll use to get the process token. // now get the process, which we'll use to get the process token.
LOG_DEBUG("found %s in session %i", name, m_activeSessionId); LOG_DEBUG("found %s in session %i", name, m_activeSessionId);
*process = OpenProcess(MAXIMUM_ALLOWED, FALSE, pid); *process = OpenProcess(MAXIMUM_ALLOWED, FALSE, pid);
if (*process == nullptr) {
LOG_WARN("found %s in session %i but could not open process handle", name, m_activeSessionId);
return false;
}
} }
return true; return true;
} else { } else {
@ -111,11 +114,12 @@ MSWindowsSession::getUserToken(LPSECURITY_ATTRIBUTES security)
if (!DuplicateTokenEx( if (!DuplicateTokenEx(
sourceToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, security, SecurityImpersonation, TokenPrimary, &newToken sourceToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, security, SecurityImpersonation, TokenPrimary, &newToken
)) { )) {
CloseHandle(sourceToken);
LOG_ERR("could not duplicate token"); LOG_ERR("could not duplicate token");
throw std::runtime_error(windowsErrorToString(GetLastError())); throw std::runtime_error(windowsErrorToString(GetLastError()));
} }
CloseHandle(sourceToken);
LOG_DEBUG("duplicated, new token: %i", newToken); LOG_DEBUG("duplicated, new token: %i", newToken);
return newToken; return newToken;
} }

View file

@ -43,10 +43,14 @@ HANDLE openProcessForKill(const PROCESSENTRY32 &entry)
return nullptr; return nullptr;
} }
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); const DWORD desiredAccess = PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE;
HANDLE handle = OpenProcess(desiredAccess, FALSE, entry.th32ProcessID);
if (handle == nullptr) { if (handle == nullptr) {
LOG_ERR("could not open process handle for kill"); LOG_WARN(
throw std::runtime_error(windowsErrorToString(GetLastError())); "could not open process handle for kill, pid=%u, error=%s", entry.th32ProcessID,
windowsErrorToString(GetLastError()).c_str()
);
return nullptr;
} }
// only shut down if not current process (daemon is now the same unified binary). // only shut down if not current process (daemon is now the same unified binary).
@ -116,10 +120,12 @@ MSWindowsWatchdog::duplicateProcessToken(HANDLE process, LPSECURITY_ATTRIBUTES s
); );
if (!duplicateRet) { if (!duplicateRet) {
CloseHandle(sourceToken);
LOG_ERR("could not duplicate token %i", sourceToken); LOG_ERR("could not duplicate token %i", sourceToken);
throw std::runtime_error(windowsErrorToString(GetLastError())); throw std::runtime_error(windowsErrorToString(GetLastError()));
} }
CloseHandle(sourceToken);
LOG_DEBUG("duplicated, new token: %i", newToken); LOG_DEBUG("duplicated, new token: %i", newToken);
return newToken; return newToken;
} }
@ -137,13 +143,22 @@ MSWindowsWatchdog::getUserToken(LPSECURITY_ATTRIBUTES security, bool elevatedTok
if (!m_session.isProcessInSession(L"winlogon.exe", &process)) { if (!m_session.isProcessInSession(L"winlogon.exe", &process)) {
throw std::runtime_error("cannot get user token without winlogon.exe"); throw std::runtime_error("cannot get user token without winlogon.exe");
} }
if (process == nullptr) {
throw std::runtime_error("found winlogon.exe but failed to open process handle");
}
try { try {
return duplicateProcessToken(process, security); HANDLE token = duplicateProcessToken(process, security);
} catch (std::runtime_error &e) { if (process != nullptr) {
CloseHandle(process);
}
return token;
} catch (...) {
LOG_ERR("failed to duplicate user token from winlogon.exe"); LOG_ERR("failed to duplicate user token from winlogon.exe");
CloseHandle(process); if (process != nullptr) {
throw e; CloseHandle(process);
}
throw;
} }
} else { } else {
LOG_DEBUG("getting non-elevated token"); LOG_DEBUG("getting non-elevated token");
@ -371,8 +386,8 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
const auto kAllProcesses = 0; const auto kAllProcesses = 0;
// first we need to take a snapshot of the running processes // first we need to take a snapshot of the running processes
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, kAllProcesses); MSWindowsHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, kAllProcesses));
if (snapshot == INVALID_HANDLE_VALUE) { if (snapshot.get() == INVALID_HANDLE_VALUE) {
LOG_ERR("could not get process snapshot"); LOG_ERR("could not get process snapshot");
throw std::runtime_error(windowsErrorToString(GetLastError())); throw std::runtime_error(windowsErrorToString(GetLastError()));
} }
@ -382,7 +397,7 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
// get the first process, and if we can't do that then it's // get the first process, and if we can't do that then it's
// unlikely we can go any further // unlikely we can go any further
BOOL gotEntry = Process32First(snapshot, &entry); BOOL gotEntry = Process32First(snapshot.get(), &entry);
if (!gotEntry) { if (!gotEntry) {
LOG_ERR("could not get first process entry"); LOG_ERR("could not get first process entry");
throw std::runtime_error(windowsErrorToString(GetLastError())); throw std::runtime_error(windowsErrorToString(GetLastError()));
@ -398,7 +413,7 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
} }
// now move on to the next entry (if we're not at the end) // now move on to the next entry (if we're not at the end)
gotEntry = Process32Next(snapshot, &entry); gotEntry = Process32Next(snapshot.get(), &entry);
if (!gotEntry) { if (!gotEntry) {
DWORD err = GetLastError(); DWORD err = GetLastError();
@ -410,8 +425,6 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
} }
} }
} }
CloseHandle(snapshot);
} }
MSWindowsWatchdog::ProcessState MSWindowsWatchdog::handleStartError(const std::string_view &message) MSWindowsWatchdog::ProcessState MSWindowsWatchdog::handleStartError(const std::string_view &message)