Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Как выключить, перезагрузить или завершить Windows?

01.01.2007
function MyExitWindows(RebootParam: Longword): Boolean; 
var 
  TTokenHd: THandle; 
  TTokenPvg: TTokenPrivileges; 
  cbtpPrevious: DWORD; 
  rTTokenPvg: TTokenPrivileges; 
  pcbtpPreviousRequired: DWORD; 
  tpResult: Boolean; 
const 
  SE_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, 
                                       SE_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;
 
// Example to shutdown Windows:
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  MyExitWindows(EWX_POWEROFF or EWX_FORCE);
end;
 
// Example to reboot Windows:
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  MyExitWindows(EWX_REBOOT or EWX_FORCE);
end;

{2. Console Shutdown Demo}

program Shutdown;
{$APPTYPE CONSOLE}
 
uses 
  SysUtils, 
  Windows; 
 
// Shutdown Program 
// (c) 2000 NeuralAbyss Software 
// www.neuralabyss.com 
 
var 
  logoff: Boolean = False; 
  reboot: Boolean = False; 
  warn: Boolean = False; 
  downQuick: Boolean = False; 
  cancelShutdown: Boolean = False; 
  powerOff: Boolean = False; 
  timeDelay: Integer = 0; 
 
function HasParam(Opt: Char): Boolean; 
var 
  x: Integer; 
begin 
  Result := False; 
  for x := 1 to ParamCount do 
    if (ParamStr(x) = '-' + opt) or (ParamStr(x) = '/' + opt) then Result := True; 
end; 
 
function GetErrorstring: string; 
var 
  lz: Cardinal; 
  err: array[0..512] of Char; 
begin 
  lz := GetLastError; 
  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, lz, 0, @err, 512, nil); 
  Result := string(err); 
end; 
 
procedure DoShutdown; 
var 
  rl, flgs: Cardinal; 
  hToken: Cardinal; 
  tkp: TOKEN_PRIVILEGES; 
begin 
  flgs := 0; 
  if downQuick then flgs := flgs or EWX_FORCE; 
  if not reboot then flgs := flgs or EWX_SHUTDOWN; 
  if reboot then flgs := flgs or EWX_REBOOT; 
  if poweroff and (not reboot) then flgs := flgs or EWX_POWEROFF; 
  if logoff then flgs := (flgs and (not (EWX_REBOOT or EWX_SHUTDOWN or EWX_POWEROFF))) or 
      EWX_LOGOFF; 
  if Win32Platform = VER_PLATFORM_WIN32_NT then 
  begin 
    if not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, 
      hToken) then 
      Writeln('Cannot open process token. [' + GetErrorstring + ']') 
    else 
    begin 
      if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tkp.Privileges[0].Luid) then 
      begin 
        tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; 
        tkp.PrivilegeCount           := 1; 
        AdjustTokenPrivileges(hToken, False, tkp, 0, nil, rl); 
        if GetLastError <> ERROR_SUCCESS then 
          Writeln('Error adjusting process privileges.'); 
      end 
      else 
        Writeln('Cannot find privilege value. [' + GetErrorstring + ']'); 
    end; 
    {   if CancelShutdown then 
          if AbortSystemShutdown(nil) = False then 
            Writeln(\'Cannot abort. [\' + GetErrorstring + \']\') 
          else 
           Writeln(\'Cancelled.\') 
       else 
       begin 
         if InitiateSystemShutdown(nil, nil, timeDelay, downQuick, Reboot) = False then 
            Writeln(\'Cannot go down. [\' + GetErrorstring + \']\') 
         else 
            Writeln(\'Shutting down!\'); 
       end; 
    } 
  end; 
  //     else begin 
  ExitWindowsEx(flgs, 0); 
  //     end; 
end; 
 
begin 
  Writeln('Shutdown v0.3 for Win32 (similar to the Linux version)'); 
  Writeln('(c) 2000 NeuralAbyss Software. All Rights Reserved.'); 
  if HasParam('?') or (ParamCount = 0) then 
  begin 
    Writeln('Usage:    shutdown [-akrhfnc] [-t secs]'); 
    Writeln('                  -k:      do not really shutdown, only warn.'); 
    Writeln('                  -r:      reboot after shutdown.'); 
    Writeln('                  -h:      halt after shutdown.'); 
    Writeln('                  -p:      power off after shutdown'); 
    Writeln('                  -l:      log off only'); 
    Writeln('                  -n:      kill apps that do not want to die.'); 
    Writeln('                  -c:      cancel a running shutdown.'); 
  end 
  else 
  begin 
    if HasParam('k') then warn := True; 
    if HasParam('r') then reboot := True; 
    if HasParam('h') and reboot then 
    begin 
      Writeln('Error: Cannot specify -r and -h parameters together!'); 
      Exit; 
    end; 
    if HasParam('h') then reboot := False; 
    if HasParam('n') then downQuick := True; 
    if HasParam('c') then cancelShutdown := True; 
    if HasParam('p') then powerOff := True; 
    if HasParam('l') then logoff := True; 
    DoShutdown; 
  end; 
end.

Взято с https://delphiworld.narod.ru


Для выполнения перезагрузки/выключения предназначены функции ExitWindows/ExitWindowsEx

ExitWindows:

Описание:

Function ExitWindows(Reserved: DWord; ReturnCode: Word): Bool;

Иницииpует стандаpтную пpоцедуpу завеpшения pаботы с Windows. Все пpикладные задачи должны подтвеpдить завеpшение pаботы Windows. Вызывает функцию 4CH пpеpывания 21H DOS.

Паpаметpы:

Reserved: Установлен в нуль.

ReturnCode: Значение, пеpедаваемое в DOS (в pегистpе AL).

Возвpащаемое значение:

Нуль, если одна или несколько задач отказываются завеpшить pаботу.

Примеры использования:

ExitWindows(EWX_LOGOFF,0); - завершение сеанса

ExitWindows(EWX_SHUTDOWN,0); - выключение компьютера

ExitWindows(EWX_REBOOT,0); - перезагрузка

Флаги EWX_FORCE, EWX_POWEROFF и  EWX_FORCEIFHUNG могут комбинироваться к нужному действию.

ExitWindowsEx:

Функция ExitWindowsEx() представляет собой расширенный вариант ExitWindows().

Описание:

BOOL ExitWindowsEx( UINT uFlags, DWORD dwReserved, );

Функция ExitWindowsEx перезагружает(restart) или выключает систему (shutdown), а также может завершить сессию для текущего пользователя(log off).

Параметры:

uFlags -- флаг завершения работы, может принимать следущие значения:

  EWX_LOGOFF завершает сессию текущего пользователя.

  EWX_POWEROFF выключает питание компьютера(компьютер должен поддерживать данную функцию).

  EWX_REBOOT перезагружает систему.

  EWX_SHUTDOWN завершает работу комьпьютера до того места, где он может быть безопасно выключен: сброшенны все файловые буферы на диск, завершает работу всех процессов.

dwReserved --Зарезирвированно для последующих нужд, параметр игнорируется.

Возвращаемое значение:

Не ноль если всё прошло успешно

Пример использования:

ExitWindowsEx(EWX_SHUTDOWN,0);

Остальные примеры смотри в описании первой функции.

Вышеописанные примеры действительны только для w9x/Me.

Дело в том, что, чтобы выполнить функциию в NT ОС, нужно получить права на выполнение этой функции. Сделать это можно через AdjustTokenPriviligies.

С помощью нижеприведённой функции можно получить любую привелегию, в т.ч. и привеленгию SeShutdownPrivilege, которая нужна для разрешения функции ExitWindows(Ex)

Function SetPrivilege(aPrivilegeName: String; aEnabled: Boolean ): Boolean; 
Var TPPrev, 
      TP: TTokenPrivileges; 
      Token: THandle; 
      dwRetLen: DWord; 
Begin 
 Result:=False; 
 OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, @Token ); 
 TP.PrivilegeCount:=1; 
 IF LookupPrivilegeValue(nil,PChar(aPrivilegeName),TP.Privileges[0].LUID )) then 
  Begin 
   IF aEnabled then TP.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED 
              else  TP.Privileges[0].Attributes:=0; 
   dwRetLen:= 0; 
   Result:=AdjustTokenPrivileges(Token,False,TP,SizeOf(TPPrev),TPPrev,dwRetLen); 
  End; 
 CloseHandle(Token); 
End;

Пример использования для среды NT:

SetPrivilege('SeShutdownPrivilege',True);

ExitWindowsEx(EWX_SHUTDOWN,0);

Автор: Song

Взято из https://forum.sources.ru