Module: wine Branch: master Commit: 8653598a662258c8809d85a77c337cd439e5cb6e URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=8653598a662258c8809d85a7...
Author: Alexandre Julliard julliard@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 ); }