Конференция "KOL" » Переделал WindowsShutdown из KOL [Delphi]
 
  • Ruzzz © (22.02.10 05:12) [0]
    Переделал WindowsShutdown из KOL.pas


    // if fail Result = 0
    function EnablePrivilege(const Machine, PrivilegesName: KOLString;
     var PreviousState: TTokenPrivileges): THandle;
    var
     Ftkp: TTokenPrivileges;
     dwRetLen :DWORD;
    begin
     if not OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
       or TOKEN_QUERY, Result) then
     begin
       Result := 0;
       Exit;
     end;

     if not LookupPrivilegeValue(PKOLChar(Machine), PKOLChar(PrivilegesName),
       Ftkp.Privileges[0].Luid) then
     begin
       CloseHandle(Result);
       Result := 0;
       Exit;
     end;

     Ftkp.PrivilegeCount := 1;
     Ftkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
     // TODO: Корректно обрабатывать PreviousState, dwRetLen
     if (not AdjustTokenPrivileges(Result, FALSE, Ftkp, sizeof(Ftkp),
       PreviousState, dwRetLen)) or (GetLastError() = ERROR_NOT_ALL_ASSIGNED) then
     begin
       CloseHandle(Result);
       Result := 0;
       Exit;
     end;
    end;

    procedure RestorePrivilege(hToken: THandle; Previous: TTokenPrivileges);
    var
     dummy: Cardinal;
    begin
     AdjustTokenPrivileges(hToken, FALSE, Previous, sizeOf(Previous), nil, dummy);
     CloseHandle(hToken);
    end;

    function WindowsShutdown(const Machine: KOLString; Force, Reboot: Boolean): Boolean;
    var
     hToken: THandle;
     tkp_prev: TTokenPrivileges;
     Flags: Integer;
     PrName: KOLString;
    begin
     Result := False;
     if Integer( GetVersion ) < 0 then // Windows95/98/Me
     begin
       if Machine <> '' then Exit;
       Flags := EWX_SHUTDOWN;
       if Reboot then
         Flags := Flags or EWX_REBOOT;
       if Force then
         Flags := Flags or EWX_FORCE;
       Result := ExitWindowsEx( Flags, 0 );
       Exit;
     end;

     if Machine = '' then
       PrName := 'SeShutdownPrivilege'
     else
       PrName := 'SeRemoteShutdownPrivilege';
     hToken := EnablePrivilege(Machine, PrName, tkp_prev);
     if hToken = 0 then Exit;
     Result := InitiateSystemShutdown(PKOLChar(Machine), nil, 0, Force, Reboot);
     if not Result then RestorePrivilege(hToken, tkp_prev);
     // Иначе восстанавливать нет смысла
    end;



    В оригинале не закрывается hToken, не критично но все же :) Плюс лишний tkp_prev:=tkp; и зачем получать сразу обе привилегии 'SeShutdownPrivilege' и 'SeRemoteShutdownPrivilege'? Плюс код включения привелегий может еще кому-то пригодиться. Например вот:


    function Suspend(Hibernate, Force: Boolean): Boolean;
    var
     hToken: THandle;
     tkp_prev: TTokenPrivileges;
    begin
     Result := False;
     if Integer( GetVersion ) < 0 then Exit; // Windows95/98/Me
     hToken := EnablePrivilege('', 'SeShutdownPrivilege', tkp_prev);
     if hToken = 0 then Exit;
     Result := SetSystemPowerState(not Hibernate, Force); // or SetSuspendState
     RestorePrivilege(hToken, tkp_prev);
    end;



    Если ошибок нет, предлагаю заменить и добавить.
  • miek (23.02.10 13:27) [1]
    По-моему, незачем корректно закрывать хендлы, если все равно следом выполняется перезагрузка.
  • Ruzzz © (23.02.10 22:11) [2]
    miek, в коде видно, что хендл закрывается лишь в случае ошибки, конечно же, врядли незакрытие сделает проблемы, но все же.

    Основная идея это EnablePrivilege и RestorePrivilege которые могут пригодиться. Ну и исправления:
    «лишний tkp_prev:=tkp; и зачем получать сразу обе привилегии 'SeShutdownPrivilege' и 'SeRemoteShutdownPrivilege'»
 
Конференция "KOL" » Переделал WindowsShutdown из KOL [Delphi]
Есть новые Нет новых   [134431   +10][b:0][p:0.002]