[Win32/Delphi] InitiateSystemShutdown geeft foutcode

Pagina: 1
Acties:
  • 234 views sinds 30-01-2008
  • Reageer

  • Icelus
  • Registratie: Januari 2004
  • Niet online
Het gebruik de (API) functie InitiateSystemShutdown om de (lokale) computer uit te zetten.
Ik gebruik eerst de (API) functie AdjustTokenPrivileges om de privileges in te stellen, daarna roep ik InitiateSystemShutdown aan.
Deze laatste functie geeft echter een 'false' terug om aan te geven dat het uitvoeren is mislukt. GetLastError geeft een code 5 - ACCESS_DENIED - terug.

Ik gebruik WinXP professional en ben ingelogd als administrator.
Weet iemand of ik nog extra rechten moet instellen?

Developer Accused Of Unreadable Code Refuses To Comment


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 07-05 22:49

curry684

left part of the evil twins

To shut down the local computer, the calling thread must have the SE_SHUTDOWN_NAME privilege. To shut down a remote computer, the calling thread must have the SE_REMOTE_SHUTDOWN_NAME privilege on the remote computer. By default, users can enable the SE_SHUTDOWN_NAME privilege on the computer they are logged onto, and administrators can enable the SE_REMOTE_SHUTDOWN_NAME privilege on remote computers. For more information, see Running with Special Privileges.

Common reasons for failure include an invalid or inaccessible computer name or insufficient privilege. The error ERROR_SHUTDOWN_IN_PROGRESS is returned if a shutdown is already in progress on the specified computer.
En laat eens wat code zien :)

Heb je ook deze voorbeeldfunctie gezien uit de PSDK?
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
BOOL SetPrivilege(
    HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
    ) 
{
TOKEN_PRIVILEGES tp;
LUID luid;

if ( !LookupPrivilegeValue( 
        NULL,            // lookup privilege on local system
        lpszPrivilege,   // privilege to lookup 
        &luid ) )        // receives LUID of privilege
{
    printf("LookupPrivilegeValue error: %u\n", GetLastError() ); 
    return FALSE; 
}

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
    tp.Privileges[0].Attributes = 0;

// Enable the privilege or disable all privileges.

if ( !AdjustTokenPrivileges(
       hToken, 
       FALSE, 
       &tp, 
       sizeof(TOKEN_PRIVILEGES), 
       (PTOKEN_PRIVILEGES) NULL, 
       (PDWORD) NULL) )
{ 
      printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); 
      return FALSE; 
} 

return TRUE;
}

[ Voor 44% gewijzigd door curry684 op 08-03-2005 14:24 ]

Professionele website nodig?


  • Icelus
  • Registratie: Januari 2004
  • Niet online
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
function SetPrivilegesToCurrentProcess:Boolean;
var  TokenPriv   :TTokenPrivileges;
     hProcess    :THandle;
     hToken      :THandle;
     ReturnLength:DWORD;
begin
     Result := False;

     hProcess := GetCurrentProcess;

     if ( OpenProcessToken( hProcess,
                            TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
                            hToken ) ) then
       try
         if ( LookupPrivilegeValue( nil,
                                    PChar( SE_SHUTDOWN_NAME ),
                                    TokenPriv.Privileges[ 0 ].Luid ) ) then begin
           with TokenPriv do begin
             PrivilegeCount             := 1;
             Privileges[ 0 ].Attributes := Privileges[ 0 ].Attributes or
                                           SE_PRIVILEGE_ENABLED;
           end;

           Result := AdjustTokenPrivileges( hToken, False, TokenPriv,
                                            0, nil, ReturnLength );
         end;

       finally
         CloseHandle( hToken );
       end;
end;

function InitiateShutdownSystem(const ForceShutdown :Boolean;
                                const Reboot        :Boolean;
                                const MachineName   :String;
                                const SystemMessage :String;
                                const MessageTimeOut:DWORD):Boolean;
var  PMachineName, PSystemMessage:PChar;
begin
     Result := False;

     if ( SetPrivilegesToCurrentProcess ) then begin
       PMachineName   := nil;
       PSystemMessage := nil;

       if ( MachineName <> '' ) then   PMachineName   := PChar( MachineName );
       if ( SystemMessage <> '' ) then PSystemMessage := PChar( SystemMessage );

       Result := InitiateSystemShutdown( PMachineName,
                                         PSystemMessage,
                                         MessageTimeOut,
                                         ForceShutdown,
                                         Reboot );
     end;
end;

Developer Accused Of Unreadable Code Refuses To Comment


  • glrfndl
  • Registratie: Juni 1999
  • Niet online
ik heb even dit stukje gekopieerd, misschien kun je er wat mee. Maakt overigens gebruik van ExitWindowsEx ipv InitiateSystemShutdown. Weet zo niet wat het verschil is.


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var
    c1, c2 : Cardinal;
    i64 : int64;
    tp1, tp2: TTokenPrivileges; 
begin
.
.
.
.
//privileges zetten om shutdown uit te voeren
            if OpenProcessToken(windows.GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, c1) then
            try
                if LookupPrivilegeValue(nil, pchar('SeShutdownPrivilege'), i64) then begin
                    tp1.PrivilegeCount := 1;
                    tp1.Privileges[0].Luid := i64;
                    tp1.Privileges[0].Attributes := 0;
                    if AdjustTokenPrivileges(c1, false, tp1, sizeOf(TTokenPrivileges), tp2, c2) then begin
                        if (c2 = sizeOf(TTokenPrivileges)) and (tp2.PrivilegeCount = 1) and (tp2.Privileges[0].Luid=i64) then
                            tp1.Privileges[0].Attributes:=tp1.Privileges[0].Attributes;
                        tp1.Privileges[0].Attributes := tp1.Privileges[0].Attributes or SE_PRIVILEGE_ENABLED;
                        AdjustTokenPrivileges(c1, false, tp1, sizeOf(TTokenPrivileges), PTokenPrivileges(nil)^, PCardinal(nil)^);
                    end;  //adjusttokenprivileges
                end; //lookupprivilegevalue
            finally CloseHandle(c1);
            end; //openprocesstoken

//shutdown uitvoeren, force en poweroff
            if (not ExitWindowsEx(EWX_POWEROFF or EWX_FORCE, 0)) then
            begin

//error loggen
                error := GetLastError;
                AssignFile(myFile, filename);
                Append(myFile);
                Write(myFile, 'error: code ');
                Writeln(myFile, error);
                CloseFile(myFile);
            end; //exitwindows
        end;


Het werkt voor mij, maar ik heb het ook maar overgenomen uit een of ander voorbeeldje wat ik ergens heb gezien :P

[ Voor 4% gewijzigd door glrfndl op 08-03-2005 15:01 ]

Prepare for unforeseen consequences


  • Icelus
  • Registratie: Januari 2004
  • Niet online
jnijboer schreef op dinsdag 08 maart 2005 @ 15:00:
ik heb even dit stukje gekopieerd, misschien kun je er wat mee. Maakt overigens gebruik van ExitWindowsEx ipv InitiateSystemShutdown. Weet zo niet wat het verschil is.
Zal ernaar kijken.
Het verschil met ExitWindowsEx is volgens mij dat het systeem direct wordt afgesloten ipv dat je een tijd kan opgeven.
Overigens werkt ExitWindowsEx wel maar krijgt mijn applicatie geen gelegenheid om zich correct af te sluiten (lijkt alsof process direct door Windows wordt beëindigd).


Edit: Opgelost. Ik gaf in regel 16 een verkeerde naam op. Kreeg dus rechten voor iets anders toegewezen.

[ Voor 73% gewijzigd door Icelus op 09-03-2005 10:18 ]

Developer Accused Of Unreadable Code Refuses To Comment


  • Icelus
  • Registratie: Januari 2004
  • Niet online
Het blijkt dat (in ieder geval) mijn applicatie geen tijd van Windows krijgt om correct af te sluiten.
In de Form destructor wacht ik tot een drietal threads klaar zijn (maximaal 1 seconde) en worden eventuele restant log regels aan het log bestand (lokaal bestand) toegevoegd.
De laatste regels uit dit log bestand worden nooit weggeschreven en het lijkt erop dat de destructor geen tijd of niet genoeg tijd krijgt om volledig te worden uitgevoerd.

Ik heb de vlag ForceShutdown in de InitiateSystemShutdown functie zowel op true alsop false geprobeerd zonder verschil.

Iemand een idee hoe dit komt?

Developer Accused Of Unreadable Code Refuses To Comment


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 07-05 22:49

curry684

left part of the evil twins

Je krijgt per definitie geen tijd om netjes af te sluiten, je krijgt gewoon een WM_CLOSEQUERY gevolgd door WM_CLOSE over je kiezen. Als jij netjes wil afsluiten zal je dat in die messagehandlers moeten doen :)

Professionele website nodig?


  • Icelus
  • Registratie: Januari 2004
  • Niet online
curry684 schreef op woensdag 09 maart 2005 @ 10:28:
Je krijgt per definitie geen tijd om netjes af te sluiten, je krijgt gewoon een WM_CLOSEQUERY gevolgd door WM_CLOSE over je kiezen. Als jij netjes wil afsluiten zal je dat in die messagehandlers moeten doen :)
Ik dacht dat Windows naar alle applicaties alleen een WM_ENDSESSION en WM_DESTROY zond.

Edit: WM_CLOSE bereikt de applicatie blijkbaar nooit. De laatste regels komen nooit in het log terecht.
Opgelost door direct erna Application.Terminate aan te roepen.

[ Voor 17% gewijzigd door Icelus op 09-03-2005 13:11 ]

Developer Accused Of Unreadable Code Refuses To Comment

Pagina: 1