BOOL ExitWindowsEx(UINT uFlags, DWORD dwReserved);
EWX_LOGOFF (登出)、EWX_SHUTDOWN (關機)、EWX_REBOOT (重開機)、EWX_POWEROFF (切斷電源)、EWX_FORCE (強制終止應用程式)。可組合使用,如 EWX_SHUTDOWN | EWX_POWEROFF。NT 核心系統要求進程擁有 SE_SHUTDOWN_NAME 特權。需透過 OpenProcessToken、LookupPrivilegeValue、AdjustTokenPrivileges 啟用該特權後再呼叫 ExitWindowsEx。
// Win2000 / WinNT / XP / Vista / 7 / 10 / 11 通用
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
// 關機並切斷電源
ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF, 0);
CloseHandle(hToken);
}
Win9x 系列無特權機制,直接呼叫即可:
ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF, 0);
void ShutdownSystem(bool bPowerOff = true, bool bForce = false)
{
UINT uFlags = EWX_SHUTDOWN;
if (bPowerOff) uFlags |= EWX_POWEROFF;
if (bForce) uFlags |= EWX_FORCE;
OSVERSIONINFO osvi = { sizeof(OSVERSIONINFO) };
GetVersionEx(&osvi);
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
// NT 核心:啟用特權
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
ExitWindowsEx(uFlags, 0);
CloseHandle(hToken);
}
} else {
// Win9x
ExitWindowsEx(uFlags, 0);
}
}
EWX_FORCE 會強制終止未回應的應用程式,可能導致資料遺失,謹慎使用。AdjustTokenPrivileges 可能失敗,需在 Manifest 中宣告 requireAdministrator。