Fix ExitWindows()

Francois Gouget fgouget at codeweavers.com
Fri Feb 24 05:58:16 CST 2006


There was a bunch of bugs in ExitWindows():
  1) SendMessageTimeoutW() now behaves like on NT, so now 0 means an 
infinite timeout, not -1 (which was the Win9x behavior).
  2) it used a standard SendMessage() to send the WM_ENDSESSION 
messages, which means it would get stuck if one of the processes was hung
  3) only windows that received a WM_QUERYENDSESSION are supposed to 
receive a WM_ENDSESSION, but ExitWindows() would send the latter to all 
windows regardless

Also, Windows is really not so sophisticated: it sends the 
WM_QUERYENDSESSION and WM_ENDSESSION, messages in pairs, rather than 
first sending all the WM_QUERYENDSESSION messages and then all the 
WM_ENDSESSION messages with the result of the 'poll'. It's simpler to do 
it the Windows way if we want to avoid bug 3 so I've changed it so.


Changelog:

  * dlls/user/user_main.c

    Francois Gouget <fgouget at codeweavers.com>
    Fix ExitWindows():
    - Use 0 to get an infinite timeout with SendMessageTimeoutW().
    - Use SendMessageTimeoutW() to send the WM_ENDSESSION messages too 
so we don't get stuck if a process is hung.
    - Only send WM_ENDSESSION to windows that received a 
WM_QUERYENDSESSION message. Also better mimick the Windows behavior.


-- 
Francois Gouget
fgouget at codeweavers.com

-------------- next part --------------
Index: dlls/user/user_main.c
===================================================================
RCS file: /home/wine/wine/dlls/user/user_main.c,v
retrieving revision 1.97
diff -u -p -r1.97 user_main.c
--- dlls/user/user_main.c	17 Sep 2005 14:28:44 -0000	1.97
+++ dlls/user/user_main.c	24 Feb 2006 10:57:09 -0000
@@ -374,23 +374,25 @@ BOOL WINAPI ExitWindowsEx( UINT flags, D
         {
             HWND *phwnd;
             UINT send_flags;
-            DWORD_PTR result;
+            DWORD_PTR result=1;
 
-            /* Send a WM_QUERYENDSESSION message to every window */
+            /* Send a WM_QUERYENDSESSION / WM_ENDSESSION message pair to
+             * each window. Note: it might be better to send all the
+             * WM_QUERYENDSESSION messages, aggregate the results and then
+             * send all the WM_ENDSESSION messages with the results but
+             * that's not what Windows does.
+             */
             send_flags=(flags & EWX_FORCEIFHUNG) ? SMTO_ABORTIFHUNG : SMTO_NORMAL;
             for (phwnd = list; *phwnd; phwnd++)
             {
                 /* Make sure that the window still exists */
                 if (!IsWindow( *phwnd )) continue;
-                if (SendMessageTimeoutW( *phwnd, WM_QUERYENDSESSION, 0, 0, send_flags, INFINITE, &result) && !result) break;
-            }
-            result = (*phwnd == NULL);
-
-            /* Now notify all windows that got a WM_QUERYENDSESSION of the result */
-            for (phwnd = list; *phwnd; phwnd++)
-            {
-                if (!IsWindow( *phwnd )) continue;
-                SendMessageW( *phwnd, WM_ENDSESSION, result, 0 );
+                if (SendMessageTimeoutW( *phwnd, WM_QUERYENDSESSION, 0, 0, send_flags, 0, &result))
+                {
+                    DWORD_PTR dummy;
+                    SendMessageTimeoutW( *phwnd, WM_ENDSESSION, result, 0, send_flags, 0, &dummy );
+                    if (!result) break;
+                }
             }
             HeapFree( GetProcessHeap(), 0, list );
 


More information about the wine-patches mailing list