CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    SetSuspendState() hangs up, why?

    I was wondering why the following happens?

    I need to log off user and then put computer to sleep. I do the following:

    (Calling the following from the local system service):

    Code:
    WTSLogoffSession(WTS_CURRENT_SERVER_HANDLE, dwUserSessionID, TRUE);
    SetSuspendState(FALSE, TRUE, FALSE);
    But when I run this code, SetSuspendState() hangs up and never returns. At the same time the system does not enter sleep mode either.

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    Re: SetSuspendState() hangs up, why?

    In what system does it hang up?
    Did you try
    Code:
    SetSuspendState(FALSE, FALSE, FALSE);
    instead?
    Victor Nijegorodov

  3. #3
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: SetSuspendState() hangs up, why?

    Quote Originally Posted by VictorN View Post
    In what system does it hang up?
    Did you try
    Code:
    SetSuspendState(FALSE, FALSE, FALSE);
    instead?
    So far the hang-up happens only in Vista. (I haven't tried it under Windows 7 yet.) I tried it a dozen times in XP and it worked fine. So that middle flag isn't even used under Vista.

    I did more tests and what seems to help is if I introduce a slight delay between those two APIs:
    Code:
    WTSLogoffSession(WTS_CURRENT_SERVER_HANDLE, dwUserSessionID, TRUE);
    Sleep(3 * 1000);
    SetSuspendState(FALSE, TRUE, FALSE);
    I really can't explain why??

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

    Re: SetSuspendState() hangs up, why?

    Well, it's quite obvious you have to give the system some time to log off, like close session related processes and unload user profile. And even more I say, you have to find some more reliable way to understand that logoff is completed (maybe wait on WTS handle or something) than just waiting for a few seconds.

    But why not obeying this would deadlock system hibernation, that's the question.
    Best regards,
    Igor

  5. #5
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: SetSuspendState() hangs up, why?

    Thanks for your input, Igor.
    Well, it's quite obvious you have to give the system some time to log off
    Yes, I agree.

    OK then, in reference to the WTSLogoffSession API, and it's 3rd parameter:
    Quote Originally Posted by MSDN
    bWait [in]
    Indicates whether the operation is synchronous.
    If bWait is TRUE, the function returns when the session is logged off.
    And as you can see I set it to TRUE.

    OK, if we keep reading, there's this:
    If bWait is FALSE, the function returns immediately. To verify that the session has been logged off, specify the session identifier in a call to the WTSQuerySessionInformation function. WTSQuerySessionInformation returns zero if the session is logged off.
    So I adjust my code like so:
    Code:
    WTSLogoffSession(WTS_CURRENT_SERVER_HANDLE, dwUserSessionID, TRUE);
    
    //Wait for maximum 30 seconds
    for(int i = 0; i < 30000; i += 100)
    {
    	LPTSTR pBuff = NULL;
    	DWORD dwszBuff = 0;
    	BOOL bGotSessionData = WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwUserSessionID, WTSUserName, &pBuff, &dwszBuff);
    
    	if(pBuff)
    	{
    		WTSFreeMemory(pBuff);
    		pBuff = NULL;
    	}
    
    	if(!bGotSessionData)
    		break;
    
    	Sleep(100);
    }
    
    SetSuspendState(FALSE, TRUE, FALSE);
    So what happens above is that the waiting part quits the for() loop almost immediately. (Unfortunately I cannot run a debugger at this point, I can tell this by placing couple logging functions before and after it.)

    But on top of that the code above, of polling user sessions (like it is suggested by MSDN) is far from being my favorite. Here's why. Each session has a simplest possible ID. For instance, the one that you're logged in now is probably 1 So if you log off and the system automatically logs in one of its own sessions, guess what ID that session may be assigned ... yes, 1 as well. And what I observed happens under Windows Vista is that right after a user session is logged off almost immediately a new session is created. That session has no name but its status is set as WTSDisconnected or WTSIdle. I don't know what it's used for, that stuff is clearly not documented ...

    So at this point I don't know how else to poll user sessions or the system for the "ready" state after the log-off, do you?

    And one more thing. I ran the code above (without the waiting part) under Windows 7 and although the sleep function succeeded, when the system woke up and I tried to log in I've presented with a screen I've never seen before, have you? (Screenshot attached.)

    The Local Session Manager service failed the logon.
    The group or resource is not in the correct state to perform the requested operation.
    Attached Images Attached Images  
    Last edited by ahmd; January 28th, 2012 at 06:59 PM.

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

    Re: SetSuspendState() hangs up, why?

    Well, everything you said about session logoff has sounded convincing. Now we have an only undocumented thing with system creating idle session. And I'm inclined to think now that exactly this session may cause the effect you observed. Sorry, I'm not that experienced in WTS stuff, so I hardly could give a hint more informative than this.

    Seems like you'd live with 3 second delay so far, until you find an explanation for all this.

    That session has no name but its status is set as WTSDisconnected or WTSIdle. I don't know what it's used for,
    I would say it might be some performance improving stuff. Rather than start a new session after successful logon, it seems more user friendly to have a session in idle state to inhabit immediately.

    So at this point I don't know how else to poll user sessions or the system for the "ready" state after the log-off, do you?
    As I already said, I think the session just logged off hardly could affect the hibernation. But automatically started one could do alright.

    And one more thing. I ran the code above (without the waiting part) under Windows 7 and although the sleep function succeeded, when the system woke up and I tried to log in I've presented with a screen I've never seen before, have you? (Screenshot attached.)
    SetSuspendState has a comment from a community contributor:
    Quote Originally Posted by acc3141
    SetSuspendState does not return until system wakes up
    So it's quite logical to assume that after wake-up you have an exact system reaction caused by pre-hibernate or right-on-hibernate system state.
    Last edited by Igor Vartanov; January 29th, 2012 at 03:03 AM.
    Best regards,
    Igor

  7. #7
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: SetSuspendState() hangs up, why?

    Thanks for your help, Igor. And, you're right, it seems like I'll have to live with a 3-second delay. That seems to have worked in almost 100% of my trials.

    PS. If someone searches out this thread and finds a better solution, please post it here ... I'd be glad to hear your take on this.

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