Reboot, log off, shut down or turn off the system (Views: 701)
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); |