InitiateSystemShutdownEx hangs system
So using InitiateSystemShutdownEx causes a Win32 machine to go log off go to the shutdown screen and just sit there displaying shutting down with the working indicator just spinning. I left the machine sitting there for an hour and it never shut down. Not sure whats going on. This works fine on all the Win7 x64 machines we are using but the one 32 bit Win7 machine has this problem and it occurs no matter what parameters I pass.
Code:
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// Get a token for this process.
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return false ;
// Get the LUID for the shutdown privilege.
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get the shutdown privilege for this process.
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES)NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
return false;
if(InitiateSystemShutdownEx( NULL, NULL, 0, TRUE, FALSE, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_UPGRADE | SHTDN_REASON_FLAG_PLANNED ) )
{
tkp.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
CloseHandle( hToken );
return false;
}
This is working fine on Win7 x64 but not on the one Win7 32 system we have and like I said it starts the shutdown process just never finishes.
Re: InitiateSystemShutdownEx hangs system
You need to inspect Event Log for the problem Windows system and see if it reports anything related to issues with shutdown.
Re: InitiateSystemShutdownEx hangs system
Don't remove the shutdown privilege after the function returns. As msdn says, the function is asynchronous so it may return before it needs to use the shutdown privilege (unlikely maybe?) Also check the return value from the function to see if that sheds any light on the problem.
Re: InitiateSystemShutdownEx hangs system
Quote:
Originally Posted by
farpetrad
Not sure whats going on. This works fine on all the Win7 x64 machines we are using but the one 32 bit Win7 machine has this problem and it occurs no matter what parameters I pass.
In general, you should check all of the API functions for their respective return values. Just assuming they "work" because they work on some machines is not how to write general code that will be run on any machine.
For example LookupPrivilegeValue, AdjustTokenPrivileges, etc. all return values that you are not checking. So the first thing to do is write the code so that you're checking the return value (and in addition, calling GetLastError() if necessary).
And no, your call to GetLastError() after calling AdjustTokenPrivileges is not correct. You are always supposed to first get the return value of the function, and if it is FALSE, NULL, whatever, then you call GetLastError(). Calling GetLastError() just blindly like that will possibly give you false results.
Regards,
Paul McKenzie
Re: InitiateSystemShutdownEx hangs system
Windows error log has no errors at the time of shutdown, there are several from when it starts up but that is another problem. The return value has always been 1 or non zero and nothing reported from GetLastError()
Re: InitiateSystemShutdownEx hangs system
Quote:
Calling GetLastError() just blindly like that will possibly give you false results.
If an API function succeeds then GetLastError() cannot be relied upon to return ERROR_SUCCESS. It's best to assume in the case of success that its value is undefined unless the API documentation specificially states the value of GetLastError upon success.
Also, even when the InitiateSystemShutdownEx function indicates success, you are still returning false. You don't provide details of the function definition which contains this section of code, but if InitiateSystemShutdownEx succeeds, shouldn't you be returning true?
Re: InitiateSystemShutdownEx hangs system
Quote:
Originally Posted by
2kaud
Also, even when the InitiateSystemShutdownEx function indicates success, you are still returning false. You don't provide details of the function definition which contains this section of code, but if InitiateSystemShutdownEx succeeds, shouldn't you be returning true?
Does it matter since the system (and your process) is shutting down?
Re: InitiateSystemShutdownEx hangs system
Quote:
Originally Posted by
2kaud
If an API function succeeds then GetLastError() cannot be relied upon to return ERROR_SUCCESS. It's best to assume in the case of success that its value is undefined unless the API documentation specificially states the value of GetLastError upon success.
I'm assuming you're addressing the OP, which is exactly my point.
You can only use GetLastError() if
1) The function returns a failure code and
2) The function is documented that on failure, use GetLastError() to get more info and
3) The GetLastError() is called immediately after the failed function.
Any violation of those 3 items, then usage of GetLastError() is incorrect, such as calling GetLastError() on a success code.
Regards,
Paul McKenzie
Re: InitiateSystemShutdownEx hangs system
Code:
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
DWORD dwError;
CString strError;
// Get a token for this process.
BOOL bOpenToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
if (!bOpenToken)
{
dwError = GetLastError();
FormatLastError( dwError, strError );
std::ofstream oErrorLog;
oErrorLog.open( "ShutdownError.txt", std::fstream::out | std::fstream::app );
if( oErrorLog.is_open() )
{
oErrorLog << "Error calling OpenProcessToken, " << strError << std::endl;
oErrorLog.flush();
oErrorLog.close();
}
return false ;
}
// Get the LUID for the shutdown privilege.
BOOL bLookup = LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
if( !bLookup )
{
dwError = GetLastError();
FormatLastError( dwError, strError );
std::ofstream oErrorLog;
oErrorLog.open( "ShutdownError.txt", std::fstream::out | std::fstream::app );
if( oErrorLog.is_open() )
{
oErrorLog << "Error calling LookupPrivilegeValue, " << strError << std::endl;
oErrorLog.flush();
oErrorLog.close();
}
return false;
}
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get the shutdown privilege for this process.
BOOL bAdjusted = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
if( !bAdjusted )
{
dwError = GetLastError();
FormatLastError( dwError, strError );
std::ofstream oErrorLog;
oErrorLog.open( "ShutdownError.txt", std::fstream::out | std::fstream::app );
if( oErrorLog.is_open() )
{
oErrorLog << "Error calling AdjustTokenPrivileges, " << strError << std::endl;
oErrorLog.flush();
oErrorLog.close();
}
return false;
}
BOOL bShutdownSys = InitiateSystemShutdownEx( NULL, NULL, 0, TRUE, FALSE, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_UPGRADE | SHTDN_REASON_FLAG_PLANNED );
if( bShutdownSys )
{
CloseHandle( hToken );
return true;
}
else
{
dwError = GetLastError();
FormatLastError( dwError, strError );
std::ofstream oErrorLog;
oErrorLog.open( "ShutdownError.txt", std::fstream::out | std::fstream::app );
if( oErrorLog.is_open() )
{
oErrorLog << "Error calling InitiateSystemShutdownEx shutdown, " << strError << std::endl;
oErrorLog.flush();
oErrorLog.close();
}
CloseHandle( hToken );
return false;
}
And no the return value was being used to indicate success or failure and in the calling program it is not even checked, however as this is legacy code being updated from calling ExitWindows, which was failing due to applications running on another user I switched to InitiateSystemShutdownEx. Running this version still provides no errors yet the Win7 32 bit machine does not shutdown and just sits on the Shutting Down screen.
Re: InitiateSystemShutdownEx hangs system
Quote:
Originally Posted by
Paul McKenzie
I'm assuming you're addressing the OP, which is exactly my point.
You can only use GetLastError() if
1) The function returns a failure code and
2) The function is documented that on failure, use GetLastError() to get more info and
3) The GetLastError() is called immediately after the failed function.
Any violation of those 3 items, then usage of GetLastError() is incorrect, such as calling GetLastError() on a success code.
Regards,
Paul McKenzie
Maybe you should lookup the documentation for AdjustTokenPrivileges as it states:
If the function succeeds, the return value is nonzero. To determine whether the function adjusted all of the specified privileges, call GetLastError, which returns one of the following values when the function succeeds:
ERROR_SUCCESS
ERROR_NOT_ALL_ASSIGNED
Re: InitiateSystemShutdownEx hangs system
Quote:
Originally Posted by
Arjay
Does it matter since the system (and your process) is shutting down?
Depends upon what the program calling this function does with the return value. From the MSDN documentation
'The shutdown is an asynchronous process, and it can occur long after the API call has returned, or not at all. Even if the timeout value is zero, the shutdown can still be aborted by applications, services, or even the system.'
Re: InitiateSystemShutdownEx hangs system
Quote:
Originally Posted by
2kaud
Depends upon what the program calling this function does with the return value. From the MSDN documentation
'The shutdown is an asynchronous process, and it can occur long after the API call has returned, or not at all. Even if the timeout value is zero, the shutdown can still be aborted by applications, services, or even the system.'
Ordinarily I would agree with you, but for this function the programmer shouldn't make any expectations about doing any work after this function has been called because there is no guarantee of how fast the rug is going to be pulled out.
Re: InitiateSystemShutdownEx hangs system
Quote:
Originally Posted by
farpetrad
Maybe you should lookup the documentation for AdjustTokenPrivileges as it states:
If the function succeeds, the return value is nonzero. To determine whether the function adjusted all of the specified privileges, call GetLastError, which returns one of the following values when the function succeeds:
ERROR_SUCCESS
ERROR_NOT_ALL_ASSIGNED
OK My mistake. Probably one of the few functions that uses "GetLastError" to indicate success.
However, as Arjay pointed out, the InitiateSystemShutdownEx function is asynchronous and on top of that, is only a request to the OS to shutdown.
You should write a tiny main() function that all it does is call that code. Then see if that works correctly. If it works, then it is the larger app that has an issue after that function is called.
Regards,
Paul McKenzie
Re: InitiateSystemShutdownEx hangs system
I was about to try that with a C# app I found that tests all the different shutdown api's, however this is being called from a server app that is sending a packet which in response we need to shut down, I have a feeling that one of the other apps running is not responding correctly as there is a second server app running on this machine, and only this machine, and it may not be shutting down and may be causing the problems. I will report back after I test this if I can get time on the lab system.
Re: InitiateSystemShutdownEx hangs system
Quote:
Originally Posted by
farpetrad
I was about to try that with a C# app I found that tests all the different shutdown api's, however this is being called from a server app that is sending a packet which in response we need to shut down, I have a feeling that one of the other apps running is not responding correctly as there is a second server app running on this machine, and only this machine, and it may not be shutting down and may be causing the problems. I will report back after I test this if I can get time on the lab system.
You've got a lot of layers in there before getting to the ISSEx call. At the very least modify your server code and spew some trace statements to a log file to make sure the shutdown code is getting called. I've used InitiateSystemShutdown[Ex] since NT4 on, and have yet to find a case where an app prevented the system from shutting down.
If you do find that IISEx is getting called try to add more diagnostics to the logging. Use the toolhelp apis to take a snapshot of the running process prior to the IISEx call and log them. Call IISEx and then take another snapshot in the destructor of the class that calls ISSEx. Btw, I'm not sure if the toolhelp code will actually execute (or if it does execute, will it show a difference between the previous process snapshot). Another consideration is the account this service is running in. Try running the service under a different account with admin permissions.
Re: InitiateSystemShutdownEx hangs system
I haven't been able to get on that lab system but will be able to around noon today. On the other system that is a spitting image of that one the 32 bit machine is having no problems. Hopefully I can get the problem diagnosed later and report back.
Re: InitiateSystemShutdownEx hangs system
So I was finally able to get on the system this morning and get to testing. The additional log code provided no help. Using the remote debugger I stepped through the code the adjust prvlidges worked and it hits the InitiateSystemShutdownEx and it returns with no error and the system begins to start the shutdown but hangs. A coworker suggested trying as admin as that is what the developer test system is running under yet that had no affect on the actual system machine still hangs on shutdown. The developer system is running Windows 7 Ultimate 32bit while the production machines are running Windows 7 Professional 32 bit. There is also a hardware difference, the production systems are using an intel mb with a core i5 and 8gb of ram (don't ask I have no clue why they would put that much ram on a 32 bit system), while the developer system uses an asus board a core 2 duo and 4gb of ram. I am not sure what else to try now.
Re: InitiateSystemShutdownEx hangs system
Playing around a little more with a .net app I wrote to kill any processes and then shutdown the system shutsdown. I was able to then test the origional app without the other things running and it shuts down so going to add code to the project to shut down any running application.
This is wrong, I didnt realize the machine had been booted into with the selective startup turned on.
Re: InitiateSystemShutdownEx hangs system
So I tested after killing all of our applications and the system still hangs. It also hangs if using the shutdown button and trying the command line shutdown -s -t 10 it also hangs. I am starting to think there is a process that is hanging and not responding. I was able to get a list of services still running after the call to InitiateSystemShutdown and also got a list during a selective start on shutdown so am comparing them now and will try to kill anything thats left running and is a non system service.
Re: InitiateSystemShutdownEx hangs system
I was able to track this down to one of our apps. If I don't let it start I can shut the system down, however once it starts windows will not shut down. I started debugging and noticed this app never got the wm_close I sent to it through EnumWindows so I changed to sending WM_USER+10 and sure enough the app got it so I then sent a wm_close in response to getting the WM_USER. I verified the OnCLose method got called and saw the app exit (legacy mfc app), however I still can't shut down the computer still hanging. I then noticed I got an error on WaitForSingleObject when waiting on the process. Error code was 5 and formatted to access denied. Now I gave my process the se_debug_name privelege before opening the process to shutdown. Is this because the process ended and did not signal? Should I post the close message in response to the user message or call ExitProcess? Sorry for any typos posting from my phone.