CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 20
  1. #1
    Join Date
    May 2013
    Posts
    10

    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.

  2. #2
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    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.
    Best regards,
    Igor

  3. #3
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    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.

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: InitiateSystemShutdownEx hangs system

    Quote Originally Posted by farpetrad View Post
    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
    Last edited by Paul McKenzie; May 2nd, 2013 at 02:43 PM.

  5. #5
    Join Date
    May 2013
    Posts
    10

    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()

  6. #6
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: InitiateSystemShutdownEx hangs system

    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?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  7. #7
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: InitiateSystemShutdownEx hangs system

    Quote Originally Posted by 2kaud View Post
    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?

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

    Re: InitiateSystemShutdownEx hangs system

    Quote Originally Posted by 2kaud View Post
    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

  9. #9
    Join Date
    May 2013
    Posts
    10

    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.

  10. #10
    Join Date
    May 2013
    Posts
    10

    Re: InitiateSystemShutdownEx hangs system

    Quote Originally Posted by Paul McKenzie View Post
    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

  11. #11
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: InitiateSystemShutdownEx hangs system

    Quote Originally Posted by Arjay View Post
    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.'
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  12. #12
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: InitiateSystemShutdownEx hangs system

    Quote Originally Posted by 2kaud View Post
    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.

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449

    Re: InitiateSystemShutdownEx hangs system

    Quote Originally Posted by farpetrad View Post
    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

  14. #14
    Join Date
    May 2013
    Posts
    10

    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.

  15. #15
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: InitiateSystemShutdownEx hangs system

    Quote Originally Posted by farpetrad View Post
    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.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured