diff --git a/src/lib/platform/MSWindowsWatchdog.h b/src/lib/platform/MSWindowsWatchdog.h index 287290cef..2ee72e6a1 100644 --- a/src/lib/platform/MSWindowsWatchdog.h +++ b/src/lib/platform/MSWindowsWatchdog.h @@ -21,6 +21,9 @@ typedef VOID(WINAPI *SendSas)(BOOL asUser); class Thread; class FileLogOutputter; +/** + * @brief Monitors and controls a core process on Windows, elevating if necessary. + */ class MSWindowsWatchdog { enum class ProcessState @@ -36,22 +39,94 @@ public: explicit MSWindowsWatchdog(bool foreground); ~MSWindowsWatchdog() = default; + /** + * @brief Start threads for main loop and and output loop. + */ void startAsync(); + + /** + * @brief Set the command to run and whether to elevate the process. + */ void setProcessConfig(const std::string_view &command, bool elevate); + + /** + * @brief Stop the main loop and output loop threads. + */ void stop(); + + /** + * @return True if the process is running. + */ bool isProcessRunning(); + + /** + * @brief Set the file log outputter. + * + * Outputter is not adopted by the watchdog, so the caller must manage the memory. + * + * Standard out/error from the launched core process is written to the file log outputter. + */ void setFileLogOutputter(FileLogOutputter *outputter); private: + /** + * @brief Monitor the process state and start/stop the process as necessary. + */ void mainLoop(void *); + + /** + * @brief Monitor the process standard out/error and write to the file log outputter. + */ void outputLoop(void *); + + /** + * @brief Stops any core processes which were not started by the watchdog. + */ void shutdownExistingProcesses(); + + /** + * @brief Duplicates the process token for the given process. + * + * Required for starting a process in the user session; when we start an elevated process + * to ensure that it has access to secure processes, such as the login screen, we duplicate + * the token of an existing process that has the necessary access such as `winlogon.exe`. + * + * @param process The process to duplicate the token from (typically `winlogon.exe`). + */ HANDLE duplicateProcessToken(HANDLE process, LPSECURITY_ATTRIBUTES security); + + /** + * @brief Get a security token for the user session. + * + * Checks to see if logonui.exe is running or if the `elevatedToken` arg is true, + * which indicates either we're in a secure user session or we need an elevated token. + * If either case is true, it duplicates the token from `winlogon.exe`. + */ HANDLE getUserToken(LPSECURITY_ATTRIBUTES security, bool elevatedToken); + + /** + * @brief Start the core process, elevating if necessary. + */ void startProcess(); + + /** + * @brief Controls whether the process should restart immediately or delay start. + */ void handleStartError(const std::string_view &message = ""); + + /** + * @brief Init the output read pipe for standard out/error. + */ void initOutputReadPipe(); + + /** + * @brief Init the SendSAS function, used for Ctrl+Alt+Del emulation. + */ void initSasFunc(); + + /** + * @brief Send a SAS (Secure Attention Sequence) for Ctrl+Alt+Del emulation. + */ void sendSas() const; /** @@ -64,6 +139,9 @@ private: */ std::string runActiveDesktopUtility(); + /** + * @brief Convert the process state enum to a string (useful for logging). + */ static std::string processStateToString(ProcessState state); private: