ruanlab123
asked on
Determine Windows shutdown or reboot
Hi Experts
Is there a way that I could determine if Windows shutdown, if it is a shutdown or a reboot.
My Delphi app stops the windows shutdown if still busy, but if finished I want to either shutdown or
reboot the pc according to what the user have choosen.
I've used the follwing code to stop the shutdown
procedure TForm_Main.WMQueryEndSessi on(var M: TWMQueryEndSession);
begin
if ClientBusy = False then
M.Result := 1
else
M.Result := 0;
end;
Thanks
Is there a way that I could determine if Windows shutdown, if it is a shutdown or a reboot.
My Delphi app stops the windows shutdown if still busy, but if finished I want to either shutdown or
reboot the pc according to what the user have choosen.
I've used the follwing code to stop the shutdown
procedure TForm_Main.WMQueryEndSessi
begin
if ClientBusy = False then
M.Result := 1
else
M.Result := 0;
end;
Thanks
as you can see in http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shutdown/base/wm_queryendsession.asp
there is no way of detecting if it's a shutdown or a reboot using API.
however, as said in this PAQ https://www.experts-exchange.com/questions/21019028/How-to-detect-the-difference-in-a-Logoff-Reboot-or-Shutdown.html, you can use madhi's hook components and hook into the shutdown api's.
there is no way of detecting if it's a shutdown or a reboot using API.
however, as said in this PAQ https://www.experts-exchange.com/questions/21019028/How-to-detect-the-difference-in-a-Logoff-Reboot-or-Shutdown.html, you can use madhi's hook components and hook into the shutdown api's.
ASKER
Ok, I know about the madhi's hook components, I've use it before to not allow an process kill.
But what API must I hook, to determine if it was a shutdown or a reboot?
But what API must I hook, to determine if it was a shutdown or a reboot?
as it is mentioned in the PAQ I've told you about, it's the function ExitWindowsEx you should hook.
ASKER
ok my dll looks like this :
var
Reg : TRegistry;
ExitWindowsExNext : function (uFlags, dwReserved : Cardinal) : LongBool; stdcall;
{$R *.res}
function ExitWindowsEx(uFlags, dwReserved : Cardinal) : LongBool; stdcall;
begin
Reg := TRegistry.Create;
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey(RegKey,True) then
begin
if (uFlags = EWX_SHUTDOWN) or (uFlags = EWX_POWEROFF) then
try
Reg.WriteString('ShutdownP roc','Shut down');
except
end;
if uFlags = EWX_REBOOT then
try
Reg.WriteString('ShutdownP roc','Rebo ot');
except
end;
end;
Result := False;
end;
begin
HookAPI('kernel32.dll', 'ExitWindowsEx', @ExitWindowsEx,@ExitWindow sExNext); //hook the API
end.
and I've changed the code to stop the shutdown to this
procedure TForm_Main.WMQueryEndSessi on(var M: TWMQueryEndSession);
begin
if ClientBusy = False then
M.Result := 1
else
begin
InjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'C:\WINDOWS\system32\DigiC VSDN.dll') ;
M.Result := 1;
end;
end;
but now the shutdown is not stopped and no values in been written to the registy?
var
Reg : TRegistry;
ExitWindowsExNext : function (uFlags, dwReserved : Cardinal) : LongBool; stdcall;
{$R *.res}
function ExitWindowsEx(uFlags, dwReserved : Cardinal) : LongBool; stdcall;
begin
Reg := TRegistry.Create;
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey(RegKey,True) then
begin
if (uFlags = EWX_SHUTDOWN) or (uFlags = EWX_POWEROFF) then
try
Reg.WriteString('ShutdownP
except
end;
if uFlags = EWX_REBOOT then
try
Reg.WriteString('ShutdownP
except
end;
end;
Result := False;
end;
begin
HookAPI('kernel32.dll', 'ExitWindowsEx', @ExitWindowsEx,@ExitWindow
end.
and I've changed the code to stop the shutdown to this
procedure TForm_Main.WMQueryEndSessi
begin
if ClientBusy = False then
M.Result := 1
else
begin
InjectLibrary(ALL_SESSIONS
M.Result := 1;
end;
end;
but now the shutdown is not stopped and no values in been written to the registy?
i would do some logging in the hook function just to make sure nothing is being lost.
as a "protocol" of mine, I always call the hooked function (if needed) to make sure that I don't accidentally "kill" functionality.
in you code, you also forgot to free the registry object.
plus that your hook function always return false. why? false has a "value" of zero, and you are hence signaling that an error occured.
as a "protocol" of mine, I always call the hooked function (if needed) to make sure that I don't accidentally "kill" functionality.
in you code, you also forgot to free the registry object.
plus that your hook function always return false. why? false has a "value" of zero, and you are hence signaling that an error occured.
ASKER
Ok, I've tried everything this weekend, nothing works.
Looks like if the ExitWindowsEx function that I've hooked is never called, I've put in some showmessages but it never shows.
If I change M.Result = 0 in the WMQueryEndSession procedure the shutdown is stopped, but then according to me the ExitWindowsEx function will not be called, change it back to M.Result = 1, ExitWindowsEx function is still not called and windows reboot or shutdown without even showing my showmessages.
Any suggestions?
Looks like if the ExitWindowsEx function that I've hooked is never called, I've put in some showmessages but it never shows.
If I change M.Result = 0 in the WMQueryEndSession procedure the shutdown is stopped, but then according to me the ExitWindowsEx function will not be called, change it back to M.Result = 1, ExitWindowsEx function is still not called and windows reboot or shutdown without even showing my showmessages.
Any suggestions?
sorry for the blackout. been a little too busy. I'll try to do this myself though I never worked with these components :)
I'll let you know in a day or two of the results (I'm still a little busy ;) )
I'll let you know in a day or two of the results (I'm still a little busy ;) )
ASKER
thanks, I will be waiting on your reply then.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
WinExit(EWX_LOGOFF); // one of these 3 only :-)
WinExit(EWX_REBOOT);
WinExit(EWX_SHUTDOWN);
See the source for the flags EWX_POWEROFF and EWX_FORCE.
The function SetPrivilege() is a necessary helper function.
The other document referenced at the top in the See-Also section is a slight modification of this code snippet, but it works basically the same way.
function SetPrivilege (sPrivilegeName: string; bEnabled: 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 (sPrivilegeName), TP.Privileges[0].LUID) then
begin
if bEnabled then
TP.Privileges[0].Attribute
else
TP.Privileges[0].Attribute
dwRetLen := 0;
result := AdjustTokenPrivileges (Token, False, TP, SizeOf (TPPrev), TPPrev,
dwRetLen)
end;
CloseHandle (Token)
end;
//
// iFlags:
//
// one of the following must be
// specified
//
// EWX_LOGOFF
// EWX_REBOOT
// EWX_SHUTDOWN
//
// following attributes may be
// combined with above flags
//
// EWX_POWEROFF
// EWX_FORCE : terminate processes
//
function WinExit (iFlags: integer) : Boolean;
begin
result := true;
if SetPrivilege ('SeShutdownPrivilege', true) then
begin
if (not ExitWindowsEx (iFlags, 0)) then
begin
// handle errors...
result := False
end;
SetPrivilege ('SeShutdownPrivilege', False)
end
else
begin
// handle errors...
result := False
end
end;