Alexandre Julliard : user: Defer all ExitWindowsEx processing to
wineboot.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Aug 18 05:39:58 CDT 2006
Module: wine
Branch: master
Commit: 8653598a662258c8809d85a77c337cd439e5cb6e
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=8653598a662258c8809d85a77c337cd439e5cb6e
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Aug 17 20:54:21 2006 +0200
user: Defer all ExitWindowsEx processing to wineboot.
---
dlls/user/user_main.c | 209 +++++--------------------------------------
programs/explorer/desktop.c | 7 -
2 files changed, 23 insertions(+), 193 deletions(-)
diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c
index 743bded..4a2915a 100644
--- a/dlls/user/user_main.c
+++ b/dlls/user/user_main.c
@@ -26,7 +26,6 @@ #include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
-#include "tlhelp32.h"
#include "controls.h"
#include "user_private.h"
@@ -284,201 +283,39 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWO
/***********************************************************************
- * USER_GetProcessHandleList(Internal)
- */
-static HANDLE *USER_GetProcessHandleList(void)
-{
- DWORD count, i, n;
- HANDLE *list;
- PROCESSENTRY32 pe;
- HANDLE hSnapshot;
- BOOL r;
-
- hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
- if (!hSnapshot)
- {
- ERR("cannot create snapshot\n");
- return FALSE;
- }
-
- /* count the number of processes plus one */
- for (count=0; ;count++)
- {
- pe.dwSize = sizeof pe;
- if (count)
- r = Process32Next( hSnapshot, &pe );
- else
- r = Process32First( hSnapshot, &pe );
- if (!r)
- break;
- }
-
- /* allocate memory make a list of the process handles */
- list = HeapAlloc( GetProcessHeap(), 0, (count+1)*sizeof(HANDLE) );
- n=0;
- for (i=0; i<count; i++)
- {
- pe.dwSize = sizeof pe;
- if (i)
- r = Process32Next( hSnapshot, &pe );
- else
- r = Process32First( hSnapshot, &pe );
- if (!r)
- break;
-
- /* don't kill ourselves */
- if (GetCurrentProcessId() == pe.th32ProcessID )
- continue;
-
- /* open the process so we don't can track it */
- list[n] = OpenProcess( PROCESS_QUERY_INFORMATION|
- PROCESS_TERMINATE,
- FALSE, pe.th32ProcessID );
-
- /* check it didn't terminate already */
- if( list[n] )
- n++;
- }
- list[n]=0;
- CloseHandle( hSnapshot );
-
- if (!r)
- ERR("Error enumerating processes\n");
-
- TRACE("return %lu processes\n", n);
-
- return list;
-}
-
-
-/***********************************************************************
- * USER_KillProcesses (Internal)
- */
-static DWORD USER_KillProcesses(void)
-{
- DWORD n, r, i;
- HANDLE *handles;
- const DWORD dwShutdownTimeout = 10000;
-
- TRACE("terminating other processes\n");
-
- /* kill it and add it to our list of object to wait on */
- handles = USER_GetProcessHandleList();
- for (n=0; handles && handles[n]; n++)
- TerminateProcess( handles[n], 0 );
-
- /* wait for processes to exit */
- for (i=0; i<n; i+=MAXIMUM_WAIT_OBJECTS)
- {
- int n_objs = ((n-i)>MAXIMUM_WAIT_OBJECTS) ? MAXIMUM_WAIT_OBJECTS : (n-i);
- r = WaitForMultipleObjects( n_objs, &handles[i], TRUE, dwShutdownTimeout );
- if (r==WAIT_TIMEOUT)
- ERR("wait failed!\n");
- }
-
- /* close the handles */
- for (i=0; i<n; i++)
- CloseHandle( handles[i] );
-
- HeapFree( GetProcessHeap(), 0, handles );
-
- return n;
-}
-
-
-/***********************************************************************
- * USER_DoShutdown (Internal)
- */
-static void USER_DoShutdown(void)
-{
- DWORD i, n;
- const DWORD nRetries = 10;
-
- for (i=0; i<nRetries; i++)
- {
- n = USER_KillProcesses();
- TRACE("Killed %ld processes, attempt %ld\n", n, i);
- if(!n)
- break;
- }
-}
-
-
-/***********************************************************************
* ExitWindowsEx (USER32.@)
*/
BOOL WINAPI ExitWindowsEx( UINT flags, DWORD reason )
{
- TRACE("(%x,%lx)\n", flags, reason);
-
- if (!WIN_IsCurrentThread( GetDesktopWindow() ))
- {
- BOOL ret = PostMessageW( GetDesktopWindow(), WM_USER + 666,
- MAKEWPARAM( flags, 0xbabe ), reason);
- if (ret)
- return TRUE;
- /* this can happen if explorer hasn't been started or created the
- * desktop window yet */
- WARN("PostMessage failed with error %ld\n", GetLastError());
- /* fall through to doing it in the same process */
- }
+ static const WCHAR winebootW[] = { '\\','w','i','n','e','b','o','o','t',0 };
+ static const WCHAR killW[] = { ' ','-','-','k','i','l','l',0 };
+ static const WCHAR end_sessionW[] = { ' ','-','-','e','n','d','-','s','e','s','s','i','o','n',0 };
+ static const WCHAR forceW[] = { ' ','-','-','f','o','r','c','e',0 };
+ static const WCHAR shutdownW[] = { ' ','-','-','s','h','u','t','d','o','w','n',0 };
- if ((flags & EWX_FORCE) == 0)
- {
- HWND *list;
+ WCHAR cmdline[MAX_PATH + 64];
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
- /* We have to build a list of all windows first, as in EnumWindows */
- list = WIN_ListChildren( GetDesktopWindow() );
- if (list)
- {
- HWND *phwnd;
- UINT send_flags;
- DWORD_PTR result=1;
-
- /* 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, 0, &result))
- {
- DWORD_PTR dummy;
- SendMessageTimeoutW( *phwnd, WM_ENDSESSION, result, 0, send_flags, 0, &dummy );
- if (!result) break;
- }
- }
- HeapFree( GetProcessHeap(), 0, list );
+ GetSystemDirectoryW( cmdline, MAX_PATH );
+ lstrcatW( cmdline, winebootW );
- if (!result)
- return TRUE;
- }
+ if (flags & EWX_FORCE) lstrcatW( cmdline, killW );
+ else
+ {
+ lstrcatW( cmdline, end_sessionW );
+ if (flags & EWX_FORCEIFHUNG) lstrcatW( cmdline, forceW );
}
+ if (!(flags & EWX_REBOOT)) lstrcatW( cmdline, shutdownW );
- /* USER_DoShutdown will kill all processes except the current process */
- USER_DoShutdown();
-
- if (flags & EWX_REBOOT)
+ memset( &si, 0, sizeof si );
+ si.cb = sizeof si;
+ if (!CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi ))
{
- WCHAR winebootW[] = { 'w','i','n','e','b','o','o','t',0 };
- PROCESS_INFORMATION pi;
- STARTUPINFOW si;
-
- memset( &si, 0, sizeof si );
- si.cb = sizeof si;
- if (CreateProcessW( NULL, winebootW, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ))
- {
- CloseHandle( pi.hProcess );
- CloseHandle( pi.hThread );
- }
- else
- MESSAGE("wine: Failed to start wineboot\n");
+ ERR( "Failed to run %s\n", debugstr_w(cmdline) );
+ return FALSE;
}
-
+ CloseHandle( pi.hProcess );
+ CloseHandle( pi.hThread );
return TRUE;
}
diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
index e552599..0b8bfbb 100644
--- a/programs/explorer/desktop.c
+++ b/programs/explorer/desktop.c
@@ -64,13 +64,6 @@ static LRESULT WINAPI desktop_wnd_proc(
}
return 0;
- /* simple check to prevent applications accidentally triggering the
- * ExitWindowsEx code if they send random messages to the desktop window */
- case WM_USER + 666:
- if (HIWORD(wp) == 0xbabe)
- return ExitWindowsEx( LOWORD(wp), lp );
- return DefWindowProcW( hwnd, message, wp, lp );
-
default:
return DefWindowProcW( hwnd, message, wp, lp );
}
More information about the wine-cvs
mailing list