type
TShutdownAction = (saLogoff, saReboot, saPoweroff);
function Shutdown(Action: TShutdownAction; AForce: Boolean): Boolean;
function EnableShutdownPrivilege: Boolean;
var
hProcess, hToken: THandle;
priv, lastpriv: TOKEN_PRIVILEGES;
lastlen: Cardinal;
const
SE_SHUTDOWN_NAME: PWideChar = 'SeShutdownPrivilege';
begin
FillChar(priv, sizeof(priv), 0);
FillChar(lastpriv, sizeof(priv), 0);
hProcess := GetCurrentProcess;
Result := False;
if OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken)
then
// 打开当前进程的访问令牌句柄(OpenProcessToken函数调用失败返回值为零)
begin
if LookupPrivilegeValue(nil, SE_SHUTDOWN_NAME, priv.Privileges[0].LUID)
then
begin
priv.PrivilegeCount := 1; // 欲调整的权限个数
priv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
// 权限的属性,SE_PRIVILEGE_ENABLED为使能该权限
if AdjustTokenPrivileges(hToken, False, priv, sizeof(priv), lastpriv,
lastlen) then // 调整访问令牌里的指定权限(AdjustTokenPrivileges函数调用失败返回值为零)
Result := GetLastError = ERROR_SUCCESS;
end;
CloseHandle(hToken);
end;
end;
var
AFlags: Integer;
begin
Result := EnableShutdownPrivilege;
if Result then // 使能关机特权函数
begin
if AForce then
AFlags := EWX_FORCE
else
AFlags := 0;
case Action of
saLogoff:
AFlags := AFlags or EWX_LOGOFF;
saReboot:
AFlags := AFlags or EWX_REBOOT;
saPoweroff:
AFlags := AFlags or EWX_SHUTDOWN;
end;
Result := ExitWindowsEx(AFlags, 0) // 强制关机
end;
end;