Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Комп не вырубается


Автор: Slawanix 25.9.2004, 22:35
Уважаемые коллеги, помогите разобраться с ситуацией:
Выключаю компьютер под управлением XP Home Edition без SP функциями из всем известного хелпа DRKB на нашем форуме:

Код
function GetWinVersion: String;
var
  VersionInfo : TOSVersionInfo;
  OSName      : String;  
begin  
  // устанавливаем размер записи
  VersionInfo.dwOSVersionInfoSize := SizeOf( TOSVersionInfo );  

  if Windows.GetVersionEx( VersionInfo ) then  
     begin  
        with VersionInfo do  
        begin  
           case dwPlatformId of  
              VER_PLATFORM_WIN32s   : OSName := 'Win32s';  
              VER_PLATFORM_WIN32_WINDOWS : OSName := 'Windows 95';  
              VER_PLATFORM_WIN32_NT      : OSName := 'Windows NT';  
           end; // case dwPlatformId  
           Result := OSName + ' Version ' + IntToStr( dwMajorVersion ) + '.' + IntToStr( dwMinorVersion ) +  
                     #13#10' (Build ' + IntToStr( dwBuildNumber ) + ': ' + szCSDVersion + ')';  
        end; // with VersionInfo  
     end // if GetVersionEx  
  else  
     Result := '';  
end;  

procedure ShutDown;
const  
 SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';   // Borland forgot this declaration  
var  
 hToken       : THandle;  
 tkp          : TTokenPrivileges;  
 tkpo         : TTokenPrivileges;  
 zero         : DWORD;  
begin  
 if Pos( 'Windows NT', GetWinVersion) = 1  then // we've got to do a whole buch of things  
    begin  
       zero := 0;  
       if not OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then  
          begin  
            MessageBox( 0, 'Exit Error', 'OpenProcessToken() Failed', MB_OK );  
            Exit;  
          end; // if not OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken)  
       if not OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then  
          begin  
            MessageBox( 0, 'Exit Error', 'OpenProcessToken() Failed', MB_OK );  
            Exit;  
          end; // if not OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken)  


       // SE_SHUTDOWN_NAME  
       if not LookupPrivilegeValue( nil, 'SeShutdownPrivilege' , tkp.Privileges[ 0 ].Luid ) then  
          begin  
             MessageBox( 0, 'Exit Error', 'LookupPrivilegeValue() Failed', MB_OK );  
             Exit;  
          end; // if not LookupPrivilegeValue( nil, 'SeShutdownPrivilege' , tkp.Privileges[0].Luid )  
       tkp.PrivilegeCount := 1;  
       tkp.Privileges[ 0 ].Attributes := SE_PRIVILEGE_ENABLED;  

       AdjustTokenPrivileges( hToken, False, tkp, SizeOf( TTokenPrivileges ), tkpo, zero );  
       if Boolean( GetLastError() ) then  
          begin  
             MessageBox( 0, 'Exit Error', 'AdjustTokenPrivileges() Failed', MB_OK );  
             Exit;  
          end // if Boolean( GetLastError() )  
       else
          ExitWindowsEx( EWX_FORCE or EWX_SHUTDOWN, 0 );
     end // if OSVersion = 'Windows NT'
  else  
     begin // just shut the machine down  
       ExitWindowsEx( EWX_FORCE or EWX_SHUTDOWN, 0 );
     end; // else  
end;


Чтобы выключить PC вызываю процедуру Shutdown и
Происходит следующее:
1) если вызываю в запущеном на выполнение приложение в среде Delhi7, то комп вырубается, но не до конца, т.е.
пишет
Цитата
Теперь питание компьтера можно выключить и лого XP

как в старые добрые времена при AT мамках; т.е. нужно все равно жать кнопочку POWER.
2) если вызываю Shutdown из приложения, запущенного в Винде, то пишет
Цитата
Ошибка shell32. Отсутствует SHExitWindowsEx

Как лечить? Ведь в факе написано что моно выключить любую винду.(у меня АТХ и сама Винда лекго вырубает комп).

С уважением, Slawanix.
cool.gif

Автор: Guest 26.9.2004, 18:57
попробуй этот вариант

Код
if OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES,HToken) THEN
   begin
   LookupPrivilegeValue(nil,'SeShutdownPrivilege',Luid);
   Tkp.Privileges[0].Luid:=Luid;
   Tkp.PrivilegeCount:=1;
   Tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
   if AdjustTokenPrivileges(HToken,false,Tkp,0,nil,ReturnLength) then
      begin
      ExitWindowsEx(EWX_FORCE or EWX_POWEROFF,0);
      end;
   end;

Автор: Albinos_x 26.9.2004, 19:30
прошу прощения забыл зарегистрироваться.

поясняю:
компьютер должен выключиться, при этом он не будет запрашивать работающие приложения на сохранение данных.

Автор: Slawanix 26.9.2004, 20:33
Albinos_x, я еще не особо секу в этом, не совсем понял, куда это нужно вставить. Что в Shutdown, это я понял. Но, по-моему, там есть похожие строки. Подскажи, пожалуйста. Или ты предлагаешь просто использовать твой код без GetWinVersion?
С уважением, Slawanix.

Автор: p0s0l 28.9.2004, 01:36
1)
Попробуй вместо EWX_SHUTDOWN поставить EWX_POWEROFF, хотя лично у меня вырубилось с EWX_SHUTDOWN...

2)
Цитата(Slawanix @ 25.9.2004, 22:35)
2) если вызываю Shutdown из приложения, запущенного в Винде, то пишет

Цитата   Ошибка shell32. Отсутствует SHExitWindowsEx


1 и 2 случай - это одна и та же прога ?

К тому же, имхо, прога с этим кодом не запустится вообще на Win9x из-за статической загрузки DLL - на девятках нет функций для работы с привилегиями и токенами... Надо динамически подключать библиотеки в случае 2k/XP и получать привилегию...

Автор: p0s0l 28.9.2004, 11:54
Цитата
Ошибка shell32. Отсутствует SHExitWindowsEx

Это ты похоже пытался сделать выключение компа в XP способом, который работает в 98/Me:
RunDLL32 shell32,SHExitWindowsEx 8
(или же напрямую вызывал эту функцию).

Под XP можно также вырубить, если выполнить следующую командную строку:
shutdown -s -f -t 0

Автор: Slawanix 1.10.2004, 23:56
Цитата
Попробуй вместо EWX_SHUTDOWN поставить EWX_POWEROFF

p0s0l , спасибо тебе: с Повероффом все отключается, причем из под ограниченного пользователя тоже без проблем. wink.gif
Цитата
К тому же, имхо, прога с этим кодом не запустится вообще на Win9x из-за статической линковки - на девятках нет функций для работы с привилегиями и токенами... Надо динамически подключать библиотеки в случае 2k/XP и получать привилегию...

Ну, вообще, я писал таймер отключения для себя под XP, но, кто знает, что будет дальше. Совет дельный, благодарю!
С уважением, Slawanix.

Автор: Albinos_x 2.10.2004, 20:34
Slawanix
У меня этот код работает без GetWinVersion и под ХР, и под МЕ, под 9х не пробовал, но думаю, тоже будет работать.
если под 9х не сработает, то вместо :

if AdjustTokenPrivileges(HToken,false,Tkp,0,nil,ReturnLength) then
begin
ExitWindowsEx(EWX_FORCE or EWX_POWEROFF,0);
end;

попробуй подставить :

AdjustTokenPrivileges(HToken,false,Tkp,0,nil,ReturnLength) ;
ExitWindowsEx(EWX_FORCE or EWX_POWEROFF,0)

Автор: Slawanix 2.10.2004, 21:23
Цитата
У меня этот код работает без GetWinVersion и под ХР, и под МЕ, под 9х не пробовал

Albinos_x , привет!
Слушай, по-моему, Win Me тоже относится к девяти-иксовым.

Цитата
попробуй подставить :

AdjustTokenPrivileges(HToken,false,Tkp,0,nil,ReturnLength) ;

А насчет привелегий, p0s0l писал, что под девятыми (95, 98, Ме) нет функций для работы с привелегиями и токенами. Вот, лирическое отступление.

Спасибо, что не оставляешь попытки помочь мне adv/hello.gif буду опробовать твой код, впечатлениями обязательно поделюсь wink.gif .
С уважением, Slawanix.

Добавлено @ 21:26
Цитата
1 и 2 случай - это одна и та же прога ?

p0s0l , прошу прощения, сразу не заметил. Да, прога одна и таже была. smile.gif
С уважением, Slawanix.

Автор: Albinos_x 2.10.2004, 21:49
Цитата
под девятыми (95, 98, Ме) нет функций для работы с привелегиями и токенами


так и есть, если в код вставить ELSE с сообщениями о том, что привелегии не получены, то они как раз будут у тебя вылетать, но ошибки выскакивать не будет, поэтому я и предложил использовать код под девятые без условий. Тогда, даже если привелегии получены не будут (если это конечно не ошибка в ХР), то компьютер всё равно выключится.

Автор: Slawanix 2.10.2004, 22:22
Цитата
буду опробовать твой код

Вот, только что поробовал, в таком виде она у меня сработала, тоже все Ok.
Только под 9x пока нет возможности проверить.
Код

procedure ShutDown;
const
 SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';   // Borland forgot this declaration
var
 hToken       : THandle;
 tkp          : TTokenPrivileges;
 tkpo         : TTokenPrivileges;
 zero         : DWORD;
begin
//***********
if OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES,HToken) THEN
begin
LookupPrivilegeValue(nil,'SeShutdownPrivilege',tkp.Privileges[ 0 ].Luid );
Tkp.PrivilegeCount:=1;
Tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
if AdjustTokenPrivileges(HToken,false,Tkp,0,nil,zero) then
begin
ExitWindowsEx(EWX_FORCE or EWX_POWEROFF,0);
end;
end;
//***********
end;

С уважением, Slawanix. adv/72.gif

Добавлено @ 22:24
Цитата
Тогда, даже если привелегии получены не будут (если это конечно не ошибка в ХР), то компьютер всё равно выключится.

Насколько я понял, за это флажок EWX_FORCE отвечает?

Автор: Albinos_x 2.10.2004, 22:42
EWX_FORCE
отвечает за то, что винда будет выключаться в форсированном режиме, т.е. запрос работающим приложениям на закрытие посылаться ей не будет.

Не понятно зачем тебе константа, она у тебя ни где не используется?!..

Автор: Albinos_x 2.10.2004, 22:55
Привожу флаги:

EWX_LOGOF : Смена пользователя.
EWX_POWEROFF : Выключение компьютера иего системы питания, если он конечно это поддерживает. В NT клонах винды срабатывает если процесс имеет привелегию SE_SHUTDOWN_NAME.
EWX_REBOOT : перезагрузка. В NT клонах винды срабатывает если процесс имеет привелегию SE_SHUTDOWN_NAME.
EWX_SHUTDOWN : выключение компьютера без выключения питания. Если в работающих приложениях предусмотренно запросы на сохранение данных, то они выполняется. В NT клонах винды срабатывает если процесс имеет привелегию SE_SHUTDOWN_NAME.
EWX_FORCE : как я уже говорил, форсированное выключение компьютера. Винда не посылает работающим приложениям сообщение WM_QUERYENDSESSION и WM_ENDSESSION. А следовательно эти приложения не делают запросов на сохранение данных пользователю. В NT клонах винды срабатывает если процесс имеет привелегию SE_SHUTDOWN_NAME.

Автор: Slawanix 3.10.2004, 19:25
Цитата
Не понятно зачем тебе константа, она у тебя ни где не используется?!..

Да со старого кода осталось, не проследил. hehe.gif
В этом коде еще одна переменная не используется, сейчас только заметил, это tkpo.
С остальным понятно, спасибо.
С Уважением, Slawanix.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)