{
Author : Michael Puff - [url]http://www.michael-puff.de[/url]
Date : 2006-02-11
License : PUBLIC DOMAIN
}
unit MpuShutdownCls;
interface
uses
Windows;
///////////////////////////////////////////////////////////////////////////////
// FFlags: Shutdown type
//
// Possible values:
//
// EWX_LOGOFF Shuts down all processes running in the logon
// 0 session of the process that called the
// ExitWindowsEx function. Then it logs the user
// off.
// This flag can be used only by processes
// running in an interactive user's logon session.
// EWX_POWEROFF Shuts down the system and turns off the power.
// $00000008 The system must support the power-off feature.
// The calling process must have the
// SE_SHUTDOWN_NAME privilege. For more
// information, see the following Remarks section.
// EWX_REBOOT Shuts down the system and then restarts the
// $00000002 system.
// The calling process must have the
// SE_SHUTDOWN_NAME privilege. For more
// information, see the following Remarks section.
// EWX_SHUTDOWN Shuts down the system to a point at which it
// $00000001 is safe to turn off the power. All file buffers
// have been flushed to disk, and all running
// processes have stopped.
// The calling process must have the
// SE_SHUTDOWN_NAME privilege. For more information,
// see the following Remarks section.
// Specifying this flag will not turn off the power
// even if the system supports the power-off feature.
// You must specify EWX_POWEROFF to do this.
// Windows XP SP1: If the system supports the
// power-off feature, specifying this flag turns
// off the power.
//
//
// FForce: Forces processes to terminate
//
// Possible value:
//
// EWX_FORCE Windows 2000/NT: Forces processes to terminate.
// $00000004 When this flag is set, the system does not send
// the WM_QUERYENDSESSION and WM_ENDSESSION messages.
// This can cause the applications to lose data.
// Therefore, you should only use this flag in an
// emergency.
// Starting with Windows XP, these messages will
// always be sent.
type
TShutdown =
class(TObject)
private
FFlags: DWORD;
function EnablePrivilege(
const Privilege:
string; fEnable: Boolean;
out PreviousState: Boolean): DWORD;
procedure SetFlags(AFlags: DWORD);
procedure SetForce(AForce: Boolean);
public
constructor Create;
function Execute: Boolean;
property Flags: DWORD
write SetFlags;
property Force: Boolean
write SetForce;
end;
implementation
constructor TShutdown.Create;
begin
FFlags := 0;
end;
function TShutdown.EnablePrivilege(
const Privilege:
string; fEnable: Boolean;
out PreviousState: Boolean): DWORD;
var
Token : THandle;
NewState : TTokenPrivileges;
Luid : TLargeInteger;
PrevState : TTokenPrivileges;
Return : DWORD;
begin
SetLastError(0);
// Clear last system error state
PreviousState := True;
if (GetVersion() > $80000000)
then // Win9x
Result := ERROR_SUCCESS
else // WinNT
begin
if OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, Token)
then
begin
try
if LookupPrivilegeValue(
nil, PChar(Privilege), Luid)
then
begin
NewState.PrivilegeCount := 1;
NewState.Privileges[0].Luid := Luid;
if fEnable
then
NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else
NewState.Privileges[0].Attributes := 0;
if AdjustTokenPrivileges(Token, False, NewState, SizeOf(TTokenPrivileges), PrevState, Return)
then
begin
PreviousState := (PrevState.Privileges[0].Attributes
and SE_PRIVILEGE_ENABLED <> 0);
end;
end;
finally
CloseHandle(Token);
end;
end;
Result := GetLastError;
end;
end;
procedure TShutdown.SetFlags(AFlags: DWORD);
begin
FFlags := FFlags
or AFlags;
end;
procedure TShutdown.SetForce(AForce: Boolean);
begin
FFlags := FFlags
or EWX_FORCE;
end;
function TShutdown.Execute;
var
err: DWORD;
PrevStat: Boolean;
begin
err := EnablePrivilege('
SeShutDownPrivilege', True, PrevStat);
if err = 0
then
begin
if not ExitWindowsEx(FFlags, 0)
then
err := GetLastError;
end
else
EnablePrivilege('
SeShutDownPrivilge', PrevStat, PrevStat);
result := err = 0;
end;
end.