2007. november 18., vasárnap
Reboot, log off, shut down or turn off the system
Problem/Question/Abstract:
How would I reboot the system and restart my program?
Answer:
Solve 1:
This will reboot, shutdown, etc. It's a wrapper function for the ExitWindowsEx API:
function ExitWin(ExitType: Integer): Boolean;
{ExitType can be any of these values:
EWX_FORCE, EWX_LOGOFF, EWX_POWEROFF, EWX_REBOOT, EWX_SHUTDOWN}
function GetShutdownPrivilege: Boolean;
var
hToken: THandle;
tkp: TTokenPrivileges;
retlength: DWORD;
Newt: TTokenPrivileges;
begin
Result := False;
hToken := GetCurrentProcess();
if OpenProcessToken(hToken, TOKEN_ADJUST_PRIVILEGES + TOKEN_QUERY, hToken) then
begin
{Get the LUID for shutdown privilege}
if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tkp.Privileges[0].Luid) then
begin
tkp.PrivilegeCount := 1; {One privilege to set}
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
{Get shutdown privilege for this process}
Result := AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof(TTokenPrivileges),
Newt, retlength)
end;
end;
end;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
GetShutdownPrivilege;
if ExitWindowsEx(ExitType, 0) then
begin
Result := True;
end
else
begin
Result := False;
end;
end;
Solve 2:
procedure QuitWindows(uFlags: UINT; forced: boolean);
{uFlages can be: EWX_LOGOFF, EWX_REBOOT or EWX_SHUTDOWN}
var
hProcess: THandle;
hToken: THandle;
tpAct, tpPrev: TTokenPrivileges;
wDummy: DWORD;
begin
hProcess := GetCurrentProcess;
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);
LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tpAct.Privileges[0].Luid);
tpPrev := tpAct;
tpAct.PrivilegeCount := 1;
tpAct.Privileges[0].Attributes := 2;
AdjustTokenPrivileges(hToken, false, tpAct, SizeOf(tpPrev), tpPrev, wDummy);
if forced then
uFLags := uFlags or EWX_FORCE;
ExitWindowsEx(uFlags, 0);
end;
Solve 3:
function GetShutdownPrivilege: Boolean;
const
SHN: PChar = 'SeShutdownPrivilege';
EMP: PChar = '';
var
hToken: THandle;
tkp, p: TTokenPrivileges;
RetLen: DWORD;
Err: DWord;
begin
{Get a token for this process.}
if not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or
TOKEN_QUERY, hToken) then
begin
Result := False; // 'Error: OpenProcessToken:' + IntToStr(GetLastError)
Exit;
end;
{Get the LUID for the shutdown privilege.}
if not LookupPrivilegeValue(EMP, SHN, tkp.Privileges[0].Luid) then
begin
Result := False; // 'Error: LookupPrivilegeValue:' + IntToStr(GetLastError)
Exit;
end;
tkp.PrivilegeCount := 1; {One privilege to set}
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
{Get the shutdown privilege for this process}
AdjustTokenPrivileges(hToken, False, tkp, SizeOf(TTokenPrivileges), p, RetLen);
{Cannot test the return value of AdjustTokenPrivileges}
Err := GetLastError;
if Err <> ERROR_SUCCESS then
begin
{ Err = 1300: 'You do not have the right to shut the system down'
else
'Error: AdjustTokenPrivileges: ' + IntToStr(Err); }
Result := False;
Exit;
end;
{Current user have privileges to shutdown the system}
Result := True;
end;
Usage:
function MyExit(Param1, Param2: LongWord): Boolean;
if Win32Platform = VER_PLATFORM_WIN32_NT then
GetShutdownPrivilege;
Result := ExitWindowsEx(Param1, Param2)
end;
Solve 4:
A quite common question I see often in discussion groups is how to shutdown/reboot Windows NT. The problem is that the usual API for the task, ExitWindowsEx, doesn't work right away with Windows NT. It's necessary to "ask for permission" before calling ExitWindows NT. This means that a process must have the SE_SHUTDOWN_NAME privilege for rebooting, powering off, or shutting the system, forced or not (using the EWX_FORCE flag).
For those who have taken a look at the Win32 Development Guide, a help file that comes with Delphi, there's a topic that explains how to shut down Windows NT, but that code is in C++. I've translated the code to Delphi, creating a function called ExitWindowsNT.
Calling ExitWindowsNT is just like calling ExitWindowsEx with only the uFlags paramter. The uFlags parameter specifies the type of shutdown. More about this is explained in the topic "ExitWindowsEx" in the Win32 SDK.
All that said, let's go the function itself:
procedure ExitWindowsNT(uFlags: integer);
var
hToken: THANDLE;
tkp, tkDumb: TTokenPrivileges;
DumbInt: integer;
begin
FillChar(tkp, sizeof(tkp), 0);
// Get a token for this process
if not (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES
or TOKEN_QUERY, hToken)) then
raise Exception.create('OpenProcessToken failed with code '
+ inttostr(GetLastError));
// Get the LUID for the Shutdown privilege
LookupPrivilegeValue(nil, pchar('SeShutdownPrivilege'),
tkp.Privileges[0].Luid);
tkp.PrivilegeCount := 1; // one privilege to set
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
// Get the shutdown provolege for this process
AdjustTokenPrivileges(hToken, false, tkp, sizeof(tkDumb), tkDumb, DumbInt);
// Cannot test the return value of AdjustTokenPrivileges
if GetLastError <> ERROR_SUCCESS then
raise Exception.create('AdjustTokenPrivileges failed with code '
+ inttostr(GetLastError));
// shut down the system and for all applications to close
if not ExitWindowsEx(uFlags, 0) then
raise Exception.create('ExitWindowsEx failed with code '
+ inttostr(GetLastError));
end;
A few examples on using the function above are:
ExitWindowsNT(EWX_SHUTDOWN or EWX_FORCE); ---- This will shutdown Windows NT without making questions. All opened applications will be closed and any unsaved data will be lost.
ExitWindowsNT(EWX_REBOOT); ---- This will reboot the system. Applications will be sent the WM_QUERYENDSESSION message so they can stop the process.
For other possible combinations of EWX_FORCE, EWX_REBOOT, EWX_POWEROFF, EWX_LOGOFF, EWX_SHUTDOWN, please refer to the Win32 Development Guide.
Solve 5:
Shut-down system under Win XP:
function DoExitWindows(RebootParam: Longword): boolean;
var
TTokenHd: THandle;
TTokenPvg: TTokenPrivileges;
cbtpPrevious: DWORD;
rTTokenPvg: TTokenPrivileges;
pcbtpPreviousRequired: DWORD;
tpResult: boolean;
const
cSE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
begin
if (Win32Platform = VER_PLATFORM_WIN32_NT) then
begin
tpResult := OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES
or TOKEN_QUERY, TTokenHd);
if tpResult then
begin
tpResult := LookupPrivilegeValue(nil, cSE_SHUTDOWN_NAME,
TTokenPvg.Privileges[0].Luid);
TTokenPvg.PrivilegeCount := 1;
TTokenPvg.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
cbtpPrevious := SizeOf(rTTokenPvg);
pcbtpPreviousRequired := 0;
if tpResult then
Windows.AdjustTokenPrivileges(TTokenHd, false, TTokenPvg, cbtpPrevious,
rTTokenPvg, pcbtpPreviousRequired);
end;
end;
Result := ExitWindowsEx(RebootParam, 0);
end;
Used like this:
DoExitWindows(EWX_SHUTDOWN or EWX_FORCE);
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése