Problem with windows shutdown
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10

Thread: Problem with windows shutdown

  1. #1
    Join Date
    Dec 2007
    Posts
    5

    Problem with windows shutdown

    I'm having a hard time to handle the WM_QUERYENDSESSION and WM_ENDSESSION messages correctly.

    I'm always ready to shutdown so I always return TRUE to WM_QUERYENDSESSION. In WM_ENDSESSION I perform some cleanup and then post the WM_QUIT message.

    The problem with my code is that it will shutdown on WM_ENDSESSION and my process is cleanly terminated but for some reason my application interrupts the windows shutdown sequence and the system will not shutdown. The system will shutdown smoothly on the second attempt (when my process is already dead).

    What am I doing wrong?

    Code:
    int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow)
    {
        ...
    
        // Main message loop
        while (GetMessage(&msg, NULL, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg) ||
                !IsDialogMessage(msg.hwnd,&msg) )
           {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        return (int) msg.wParam;
    }
    
    static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg) {
            case WM_COMMAND:
                if (LOWORD(wParam) == MTM_EXIT) {
                    CloseApp(hwndDlg,wParam,lParam);
                    PostQuitMessage(0);
                    return TRUE;
                }
                break;
        
            case WM_QUERYENDSESSION:
                return TRUE;
    
            case WM_CLOSE:
            case WM_ENDSESSION:
                CloseApp(hwndDlg,wParam,lParam);
                PostQuitMessage(0);
                return TRUE;
    		  
            ...
        }
    }
    Last edited by Metabaron; December 30th, 2007 at 09:53 AM. Reason: Added code tags to make the code more readable

  2. #2
    Join Date
    Feb 2000
    Location
    San Diego, CA
    Posts
    10,354

    Re: Problem with windows shutdown

    That is not the complete code and it isn't sufficient to understand the problem. Please post all code , and also, please use code tags when posting code so it is readable.

  3. #3
    Join Date
    Dec 2007
    Posts
    5

    Re: Problem with windows shutdown

    I'm sorry but I don't know if I can disclose any more code. In the dialog function, rest of the code just takes care of painting etc.

    But, I noticed that the shutdown will work perfectly if I add the following lines to the dialog functions switch clause:

    Code:
      default:
        return DefWindowProc(hwndDlg, msg, wParam, lParam);
        break;
    Unfortunately, this causes other problems. But what does this mean? Am I missing some message I should process?

    Furthermore, in MSDN it is said that the application need not call the DestroyWindow or PostQuitMessage function when the session is ending. But if I leave the calls to CloseApp (which calls EndDialog) and PostQuitMessage out, my application won't even terminate on shutdown!
    Last edited by Metabaron; December 31st, 2007 at 01:37 AM. Reason: Added note about DestroyWindow and PostQuitMessage

  4. #4
    Join Date
    Feb 2000
    Location
    San Diego, CA
    Posts
    10,354

    Re: Problem with windows shutdown

    Quote Originally Posted by Metabaron
    I'm sorry but I don't know if I can disclose any more code. In the dialog function, rest of the code just takes care of painting etc.

    But, I noticed that the shutdown will work perfectly if I add the following lines to the dialog functions switch clause:
    Exactly the reason I am asking for more code. Simple example of a problem is what you just stated. Dialog procedures should not call DefWindowProc at all. It is clearly documented in MSDN.

    So, if you cannot post the code, it is hard to keep guessing, and personally, I wouldn't like to do that guessing job

    Also, where in did you find this ?
    in MSDN it is said that the application need not call the DestroyWindow or PostQuitMessage function when the session is ending
    I would like to see a online link to that piece of info if possible.

  5. #5
    Join Date
    Dec 2007
    Posts
    5

    Re: Problem with windows shutdown

    I'm able to reproduce the behaviour with this simple test application.

    When I attempt to logout or shutdown, the test app first receives the WM_QUERYENDSESSION message and then immediately after that the WM_ENDSESSION message. The application then exits and the process is terminated but the logout or shutdown sequence will be interrupted.

    Code:
    #include <windows.h>
    #include <windowsx.h>
    #include <commctrl.h>
    #include <string.h>
    #include "metabaronres.h"
    
    HWND g_hMainWnd;
    
    static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
    
    int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow)
    {
    	WNDCLASS wc;
    	INITCOMMONCONTROLSEX cc;
    
    	memset(&wc,0,sizeof(wc));
    	wc.lpfnWndProc = DefDlgProc;
    	wc.cbWndExtra = DLGWINDOWEXTRA;
    	wc.hInstance = hinst;
    	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    	wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    	wc.lpszClassName = TEXT("METABARON");
    	RegisterClass(&wc);
    	memset(&cc,0,sizeof(cc));
    	cc.dwSize = sizeof(cc);
    	cc.dwICC = 0xffffffff;
    	InitCommonControlsEx(&cc);
    
    	// Make sure that only one instance is running
    	HWND hWndInstanceTest = FindWindow(NULL, TEXT("metabaron"));
    	if ( hWndInstanceTest != NULL ) {
    		return FALSE;
    	}
    
    	g_hMainWnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, (DLGPROC) DialogFunc);
    
    	MSG msg;
    	HACCEL hAccelTable;
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg) || !IsDialogMessage(msg.hwnd, &msg) )
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    	}
    
    	return (int) msg.wParam;
    }
    
    
    static int InitializeApp(HWND hDlg,WPARAM wParam, LPARAM lParam)
    {
    	return 1;
    }
    
    
    static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch (msg) {
    
    	case WM_INITDIALOG:
    		InitializeApp(hwndDlg,wParam,lParam);
    		return TRUE;
    
    	case WM_COMMAND:
    		switch (LOWORD(wParam)) {
    			case IDOK:
    				EndDialog(hwndDlg,1);
    				PostQuitMessage(0);
    				return 1;
    			case IDCANCEL:
    				EndDialog(hwndDlg,0);
    				PostQuitMessage(0);
    				return 1;
    		}
    		break;
    
    	case WM_QUERYENDSESSION:
    		// MessageBox(NULL, "WM_QUERYENDSESSION", "Metabaron", MB_OK);
    		return TRUE;
    
    	case WM_ENDSESSION:
    		// MessageBox(NULL, "WM_ENDSESSION", "Metabaron", MB_OK);
    	case WM_CLOSE:
    		EndDialog(hwndDlg,0);
    		PostQuitMessage(0);
    		return TRUE;
    
    	}
    	return FALSE;
    }
    And the stuff about application not needing to call the DestroyWindow or PostQuitMessage function when session is ending is documented here (see remarks):

    http://msdn2.microsoft.com/en-us/library/aa376889.aspx

  6. #6
    Join Date
    Feb 2007
    Location
    Craiova, Romania
    Posts
    326

    Re: Problem with windows shutdown

    Code:
    	   case WM_CLOSE:
    		case WM_ENDSESSION:
    			CloseApp(hwndDlg,wParam,lParam);
    			PostQuitMessage(0);
    			return TRUE;
    The problem could be here. You're closing the dialog as soon as you get a WM_ENDSESSION.
    When you get this message you should only perform a cleanup.
    Don't close the dialog manually. Call the default window proc for WM_CLOSE only.

    So, add a break for the WM_CLOSE case.
    I also noticed this error in your minimzed example.

  7. #7
    Join Date
    Dec 2007
    Posts
    5

    Re: Problem with windows shutdown

    I tried the trick above but it didn't fix the problem. The only difference is that now the application doesn't even terminate when the session is ending.

  8. #8
    Join Date
    Feb 2007
    Location
    Craiova, Romania
    Posts
    326

    Re: Problem with windows shutdown

    OK, this means you are not receiving a WM_CLOSE.
    I think it is better to send a WM_CLOSE manually once you receive WM_ENDSESSION.

  9. #9
    Join Date
    Dec 2007
    Posts
    5

    Re: Problem with windows shutdown

    I think I solved the problem. The main changes are that I replaced my message loop with one copied from MSDN and removed WM_QUERYENDSESSION, WM_ENDSESSION and WM_CLOSE handlers from the dialog procedure.

    Code:
    #include <windows.h>
    #include <windowsx.h>
    #include <commctrl.h>
    #include <string.h>
    #include "metabaronres.h"
    
    HWND g_hMainWnd;
    
    static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
    
    int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow)
    {
    	WNDCLASS wc;
    	INITCOMMONCONTROLSEX cc;
    
    	memset(&wc,0,sizeof(wc));
    	wc.lpfnWndProc = DefDlgProc;
    	wc.cbWndExtra = DLGWINDOWEXTRA;
    	wc.hInstance = hinst;
    	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    	wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    	wc.lpszClassName = TEXT("METABARON");
    	RegisterClass(&wc);
    	memset(&cc,0,sizeof(cc));
    	cc.dwSize = sizeof(cc);
    	cc.dwICC = 0xffffffff;
    	InitCommonControlsEx(&cc);
    
    	// Make sure that only one instance is running
    	HWND hWndInstanceTest = FindWindow(NULL, TEXT("metabaron"));
    	if ( hWndInstanceTest != NULL ) {
    		return FALSE;
    	}
    
    	g_hMainWnd = CreateDialog (hinst, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, (DLGPROC) DialogFunc);
    
    	MSG msg;
    	BOOL bReturn;
    	while ((bReturn = GetMessage(&msg, NULL, 0, 0)) != 0)
    	{
    		if (!IsWindow(g_hMainWnd) || !IsDialogMessage(g_hMainWnd, &msg) )
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    	}
    
    	return (int) msg.wParam;
    }
    
    
    static int InitializeApp(HWND hDlg,WPARAM wParam, LPARAM lParam)
    {
    	return 1;
    }
    
    
    static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch (msg) {
    
    	case WM_INITDIALOG:
    		InitializeApp(hwndDlg,wParam,lParam);
    		return TRUE;
    
    	case WM_COMMAND:
    		switch (LOWORD(wParam)) {
    			case IDOK:
    				DestroyWindow(g_hMainWnd);
    				PostQuitMessage(0);
    				return 1;
    			case IDCANCEL:
    				DestroyWindow(g_hMainWnd);
    				PostQuitMessage(0);
    				return 1;
    		}
    		break;
    
    	}
    	return FALSE;
    }
    I did the same in my real application and now it also terminates smoothly when the session is ending. There I perform my cleanup operations in the main function (after the message loop exits) as I don't need any user input for doing so.

    Still, thanks for your input kirants and marceln!

  10. #10
    Join Date
    Feb 2000
    Location
    San Diego, CA
    Posts
    10,354

    Re: Problem with windows shutdown

    I'm not sure if this is why you were seeing a problem, but would like to highlight some issues anyway:
    Code:
    case WM_QUERYENDSESSION:
    	// MessageBox(NULL, "WM_QUERYENDSESSION", "Metabaron", MB_OK);
    	return TRUE;
    
    case WM_ENDSESSION:
    	// MessageBox(NULL, "WM_ENDSESSION", "Metabaron", MB_OK);
    case WM_CLOSE:
    	EndDialog(hwndDlg,0);
    	PostQuitMessage(0);
    	return TRUE;
    In the code above, you are returning TRUE indicating the default dialog proc implemented by the system shouldn't do any further processing. That is fine. But here, what you have missed is the following:
    Quote Originally Posted by msdn
    If the dialog box procedure processes a message that requires a specific return value, the dialog box procedure should set the desired return value by calling SetWindowLong (hwndDlg, DWL_MSGRESULT, lResult) immediately before returning TRUE.
    In your code, you return TRUE, but what is really returned to windows is undefined behavior because you haven't set the DWL_MSGRESULT anywhere. This might be the reason why you are seeing wierd behavior. Just a guess.

Posting Permissions

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


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center