#pragma once #include #include #include // Result of evaluating a single candidate process. enum class KillOutcome { WouldKill, // dry run: everything checked out, nothing was done Killed, Protected, // image is on the never-touch list SelfOrAncestor, // our own process or one of its parents IdentityMismatch, // image path did not match the requested name OpenFailed, AccessDenied, // PPL / protected process: cannot even open for terminate DriverFailed, }; struct KillAttempt { DWORD pid = 0; std::wstring imagePath; KillOutcome outcome = KillOutcome::OpenFailed; }; struct KillReport { bool dryRun = false; int killed = 0; std::vector attempts; bool Refused(KillOutcome o) const; std::wstring Format() const; }; // True for images that must never be terminated: terminating any of these // takes the machine down. bool IsProtectedImage(const std::wstring& imageName); // Terminates processes with the given image name through the driver, one at a // time, with full identity verification. Never kills more than maxKills, // never kills the caller or its ancestors, never kills a protected image. // // The process handle is held across the IOCTL, so the PID cannot be recycled // between verification and termination. void KillProcessesSafe( const std::vector& imageNames, bool dryRun, DWORD maxKills, KillReport& report, bool allowBlindDriver = false);