2008年7月24日

Windowsをログオフ/リブート/シャットダウンする

Windowsをログオフ/リブート/シャットダウンするにはExitWindowsExを呼び出すのですが、NT系のOSではそれなりの特権をOpenProcessToken/LookupPrivilegeValue/AdjustTokenPrivilegesで取得しておく必要があります。
uses
  Windows, Forms, SysUtils;

{$WARN SYMBOL_PLATFORM OFF}
procedure ShutdownWindows(Flags: DWORD);
var
  TokenHandle: THandle;
  ReturnLength: DWord;
  NewTKP: TTokenPrivileges;
begin

  { Set shutdown privilege }
  if Win32Platform = VER_PLATFORM_WIN32_NT then
  begin
    { Get current process token }
    Win32Check(OpenProcessToken(GetCurrentProcess,
                                TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
                                TokenHandle));

    { Get privilege }
    Win32Check(LookupPrivilegeValue(nil,'SeShutdownPrivilege',
                                  NewTKP.Privileges[0].Luid));

    { New privilege }
    NewTKP.PrivilegeCount := 1;
    NewTKP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;

    { Get privilege for setting date and time }
    ReturnLength := 0;
    Win32Check(AdjustTokenPrivileges(TokenHandle,False,NewTKP,0,nil,ReturnLength));
    if GetLastError <> ERROR_SUCCESS then
    begin
      RaiseLastOSError;
    end;
  end;

  { ExitWindowsEx }
  Win32Check(ExitWindowsEx(Flags,0));

  { Terminate application }
  Application.Terminate;

end;
{$IFDEF VER200}  // Delphi 2009 or later
{$WARN SYMBOL_PLATFORM DEFAULT}
{$ELSE}
{$WARN SYMBOL_PLATFORM ON}  
{$ENDIF}

const
  CForceIfHung: array [Boolean] of DWORD = (0,EWX_FORCEIFHUNG);

procedure LogOff(ForceIfHung: Boolean);
begin

  ShutdownWindows(EWX_LOGOFF or CForceIfHung[ForceIfHung]);

end;

procedure PowerOff(ForceIfHung: Boolean);
begin

  ShutdownWindows(EWX_POWEROFF or CForceIfHung[ForceIfHung]);

end;

procedure Reboot(ForceIfHung: Boolean);
begin

  ShutdownWindows(EWX_REBOOT or CForceIfHung[ForceIfHung]);

end;

procedure Shutdown(ForceIfHung: Boolean);
begin

  ShutdownWindows(EWX_SHUTDOWN or CForceIfHung[ForceIfHung]);

end;

0 件のコメント: