From 3df7c8cf6a68ebc9f64ea439151207d9b79dc145 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Sun, 5 Jul 2009 02:21:35 +0000 Subject: [PATCH] - Implement the client shutdown procedure. Tested with wine user32 msg undocumented 0x3B tests. Wine tests: msg: 6175 tests executed (0 marked as todo, 937 failures), 5 skipped. - Add missing end session types. - Reference: winproc.c WM_CLIENTSHUTDOWN http://wiki.winprog.org/wiki/Windows_messages svn path=/trunk/; revision=41776 --- reactos/dll/win32/user32/windows/defwnd.c | 7 ++ reactos/include/psdk/winuser.h | 2 + reactos/include/reactos/win32k/ntuser.h | 1 + .../subsystems/win32/win32k/ntuser/defwnd.c | 96 ++++++++++++++++++- 4 files changed, 102 insertions(+), 4 deletions(-) diff --git a/reactos/dll/win32/user32/windows/defwnd.c b/reactos/dll/win32/user32/windows/defwnd.c index 8520c5284a1..5f5bdc73b54 100644 --- a/reactos/dll/win32/user32/windows/defwnd.c +++ b/reactos/dll/win32/user32/windows/defwnd.c @@ -1463,6 +1463,13 @@ User32DefWindowProc(HWND hWnd, break; } + case WM_CLIENTSHUTDOWN: + { + LRESULT lResult; + NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE); + return lResult; + } + case WM_CANCELMODE: { iMenuSysKey = 0; diff --git a/reactos/include/psdk/winuser.h b/reactos/include/psdk/winuser.h index 128c09b3112..55d5197cf49 100644 --- a/reactos/include/psdk/winuser.h +++ b/reactos/include/psdk/winuser.h @@ -2539,6 +2539,8 @@ extern "C" { #endif /* (_WIN32_WINNT >= 0x0400) */ #if (WINVER >= 0x0400) #define ENDSESSION_LOGOFF 0x80000000 +#define ENDSESSION_CRITICAL 0x40000000 +#define ENDSESSION_CLOSEAPP 0x00000001 #endif #if (WINVER >= 0x0500) #define CHILDID_SELF 0 diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index 47b4b77292e..66455270786 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -562,6 +562,7 @@ typedef struct _USERCONNECT // // Non SDK Window Message types. // +#define WM_CLIENTSHUTDOWN 59 #define WM_COPYGLOBALDATA 73 #define WM_SYSTIMER 280 #define WM_POPUPSYSTEMMENU 787 diff --git a/reactos/subsystems/win32/win32k/ntuser/defwnd.c b/reactos/subsystems/win32/win32k/ntuser/defwnd.c index e399163ce31..38a3a62e1e9 100644 --- a/reactos/subsystems/win32/win32k/ntuser/defwnd.c +++ b/reactos/subsystems/win32/win32k/ntuser/defwnd.c @@ -12,6 +12,91 @@ #define NDEBUG #include +// Client Shutdown messages +#define MCS_SHUTDOWNTIMERS 1 +#define MCS_QUERYENDSESSION 2 +// Client Shutdown returns +#define MCSR_GOODFORSHUTDOWN 1 +#define MCSR_SHUTDOWNFINISHED 2 +#define MCSR_DONOTSHUTDOWN 3 + +/* + Based on CSRSS and described in pages 1115 - 1118 "Windows Internals, Fifth Edition". + Apparently CSRSS sends out messages to do this w/o going into win32k internals. + */ +static +LRESULT FASTCALL +IntClientShutdown( + PWINDOW_OBJECT pWindow, + WPARAM wParam, + LPARAM lParam +) +{ + LPARAM lParams; + BOOL KillTimers; + INT i; + LRESULT lResult = MCSR_GOODFORSHUTDOWN; + HWND *List; + + lParams = wParam & (ENDSESSION_LOGOFF|ENDSESSION_CRITICAL|ENDSESSION_CLOSEAPP); + KillTimers = wParam & MCS_SHUTDOWNTIMERS ? TRUE : FALSE; +/* + First, send end sessions to children. + */ + List = IntWinListChildren(pWindow); + + if (List) + { + for (i = 0; List[i]; i++) + { + PWINDOW_OBJECT WndChild; + + if (!(WndChild = UserGetWindowObject(List[i])) || !WndChild->Wnd) + continue; + + if (wParam & MCS_QUERYENDSESSION) + { + if (!co_IntSendMessage(WndChild->hSelf, WM_QUERYENDSESSION, 0, lParams)) + { + lResult = MCSR_DONOTSHUTDOWN; + break; + } + } + else + { + co_IntSendMessage(WndChild->hSelf, WM_ENDSESSION, KillTimers, lParams); + if (KillTimers) + { + MsqRemoveTimersWindow(WndChild->MessageQueue, WndChild->hSelf); + } + lResult = MCSR_SHUTDOWNFINISHED; + } + } + ExFreePool(List); + } + if (List && (lResult == MCSR_DONOTSHUTDOWN)) return lResult; +/* + Send to the caller. + */ + if (wParam & MCS_QUERYENDSESSION) + { + if (!co_IntSendMessage(pWindow->hSelf, WM_QUERYENDSESSION, 0, lParams)) + { + lResult = MCSR_DONOTSHUTDOWN; + } + } + else + { + co_IntSendMessage(pWindow->hSelf, WM_ENDSESSION, KillTimers, lParams); + if (KillTimers) + { + MsqRemoveTimersWindow(pWindow->MessageQueue, pWindow->hSelf); + } + lResult = MCSR_SHUTDOWNFINISHED; + } + return lResult; +} + /* Win32k counterpart of User DefWindowProc */ @@ -35,10 +120,10 @@ IntDefWindowProc( { case WM_SYSCOMMAND: { - DPRINT1("hwnd %p WM_SYSCOMMAND %lx %lx\n", Window->hSelf, wParam, lParam ); - if (!ISITHOOKED(WH_CBT)) break; - lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam); - break; + DPRINT1("hwnd %p WM_SYSCOMMAND %lx %lx\n", Window->hSelf, wParam, lParam ); + if (!ISITHOOKED(WH_CBT)) break; + lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam); + break; } case WM_SHOWWINDOW: { @@ -59,6 +144,9 @@ IntDefWindowProc( } } break; + case WM_CLIENTSHUTDOWN: + return IntClientShutdown(Window, wParam, lParam); + case WM_CBT: { if (!ISITHOOKED(WH_CBT)) break;