Author: hbelusca
Date: Thu Feb 12 23:35:58 2015
New Revision: 66240
URL:
http://svn.reactos.org/svn/reactos?rev=66240&view=rev
Log:
[WINLOGON]
- Implement KillComProcesses that just kills with force and without any notification back
to winlogon, any remaining app that is still alive even if we asked before to kill apps
(it's just the aim of this function, not more).
- Fix internal flags according to WinDbg sessions with Win2k3 + tracing checked build
winlogon (testing logoff/shutdown/reboot from winlogon itself and when using the
"shutdown" command).
- FIXME: Manage EWX_FORCE flag in winlogon...
[WINSRV]
Fix a DPRINT.
[WIN32K]
- Introduce a NotifyLogon function to manage winlogon notifications (when we shutdown and
"end" shutdown steps, or cancel it).
- Fix some flags settings.
Part 11/X
CORE-8322
-------
This is a test:
!error !rot13 !reebe !ebg13 !error !rot13 !reebe !ebg13
Modified:
trunk/reactos/base/system/winlogon/sas.c
trunk/reactos/include/reactos/winlogon.h
trunk/reactos/win32ss/user/ntuser/shutdown.c
trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c
Modified: trunk/reactos/base/system/winlogon/sas.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/winlogon/sas.c…
==============================================================================
--- trunk/reactos/base/system/winlogon/sas.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/winlogon/sas.c [iso-8859-1] Thu Feb 12 23:35:58 2015
@@ -29,8 +29,12 @@
#define HK_CTRL_ALT_DEL 0
#define HK_CTRL_SHIFT_ESC 1
-#define EWX_ACTION_MASK 0xffffffeb
-#define EWX_FLAGS_MASK 0x00000014
+// #define EWX_FLAGS_MASK 0x00000014
+// #define EWX_ACTION_MASK ~EWX_FLAGS_MASK
+
+// FIXME: At the moment we use this value (select the lowbyte flags and some highbytes
ones).
+// It should be set such that it makes winlogon accepting only valid flags.
+#define EWX_ACTION_MASK 0x5C0F
typedef struct tagLOGOFF_SHUTDOWN_DATA
{
@@ -510,8 +514,12 @@
return 0;
}
- uFlags = EWX_INTERNAL_KILL_USER_APPS | (LSData->Flags & EWX_FLAGS_MASK) |
- ((LSData->Flags & EWX_ACTION_MASK) == EWX_LOGOFF ?
EWX_INTERNAL_FLAG_LOGOFF : 0);
+ // FIXME: To be really fixed: need to check what needs to be kept and what needs to
be removed there.
+ //
+ // uFlags = EWX_INTERNAL_KILL_USER_APPS | (LSData->Flags & EWX_FLAGS_MASK) |
+ // ((LSData->Flags & EWX_ACTION_MASK) == EWX_LOGOFF ?
EWX_CALLER_WINLOGON_LOGOFF : 0);
+
+ uFlags = EWX_CALLER_WINLOGON | (LSData->Flags & 0x0F);
ERR("In LogoffShutdownThread with uFlags == 0x%x; exit_in_progress ==
%s\n",
uFlags, ExitReactOSInProgress ? "true" : "false");
@@ -526,15 +534,42 @@
return 0;
}
- /* FIXME: Call ExitWindowsEx() to terminate COM processes only at logoff! */
- ERR("Should terminate COM processes only at logoff!\n");
-
if (LSData->Session->UserToken)
RevertToSelf();
return 1;
}
+static
+DWORD
+WINAPI
+KillComProcesses(
+ LPVOID Parameter)
+{
+ PLOGOFF_SHUTDOWN_DATA LSData = (PLOGOFF_SHUTDOWN_DATA)Parameter;
+
+ ERR("In KillComProcesses\n");
+
+ if (LSData->Session->UserToken != NULL &&
+ !ImpersonateLoggedOnUser(LSData->Session->UserToken))
+ {
+ ERR("ImpersonateLoggedOnUser() failed with error %lu\n",
GetLastError());
+ return 0;
+ }
+
+ /* Attempt to kill remaining processes. No notifications needed. */
+ if (!ExitWindowsEx(EWX_CALLER_WINLOGON | EWX_NONOTIFY | EWX_FORCE | EWX_LOGOFF, 0))
+ {
+ ERR("Unable to kill COM apps, error %lu\n", GetLastError());
+ RevertToSelf();
+ return 0;
+ }
+
+ if (LSData->Session->UserToken)
+ RevertToSelf();
+
+ return 1;
+}
static
NTSTATUS
@@ -694,8 +729,38 @@
return Status;
}
+
/* Run logoff thread */
hThread = CreateThread(psa, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL);
+
+ if (!hThread)
+ {
+ ERR("Unable to create logoff thread, error %lu\n", GetLastError());
+ DestroyLogoffSecurityAttributes(psa);
+ HeapFree(GetProcessHeap(), 0, LSData);
+ return STATUS_UNSUCCESSFUL;
+ }
+ WaitForSingleObject(hThread, INFINITE);
+ if (!GetExitCodeThread(hThread, &exitCode))
+ {
+ ERR("Unable to get exit code of logoff thread (error %lu)\n",
GetLastError());
+ CloseHandle(hThread);
+ DestroyLogoffSecurityAttributes(psa);
+ HeapFree(GetProcessHeap(), 0, LSData);
+ return STATUS_UNSUCCESSFUL;
+ }
+ CloseHandle(hThread);
+ if (exitCode == 0)
+ {
+ ERR("Logoff thread returned failure\n");
+ DestroyLogoffSecurityAttributes(psa);
+ HeapFree(GetProcessHeap(), 0, LSData);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+
+ /* Kill remaining COM apps. Only at logoff! */
+ hThread = CreateThread(psa, 0, KillComProcesses, (LPVOID)LSData, 0, NULL);
/* We're done with the SECURITY_DESCRIPTOR */
DestroyLogoffSecurityAttributes(psa);
@@ -703,7 +768,7 @@
if (!hThread)
{
- ERR("Unable to create logoff thread, error %lu\n", GetLastError());
+ ERR("Unable to create kill COM apps thread, error %lu\n",
GetLastError());
HeapFree(GetProcessHeap(), 0, LSData);
return STATUS_UNSUCCESSFUL;
}
@@ -711,16 +776,17 @@
HeapFree(GetProcessHeap(), 0, LSData);
if (!GetExitCodeThread(hThread, &exitCode))
{
- ERR("Unable to get exit code of logoff thread (error %lu)\n",
GetLastError());
+ ERR("Unable to get exit code of kill COM apps thread (error %lu)\n",
GetLastError());
CloseHandle(hThread);
return STATUS_UNSUCCESSFUL;
}
CloseHandle(hThread);
if (exitCode == 0)
{
- ERR("Logoff thread returned failure\n");
+ ERR("Kill COM apps thread returned failure\n");
return STATUS_UNSUCCESSFUL;
}
+
UnloadUserProfile(Session->UserToken, Session->hProfileInfo);
CloseHandle(Session->UserToken);
@@ -804,6 +870,11 @@
else
LSData->Flags = EWX_SHUTDOWN;
LSData->Session = Session;
+
+ // FIXME: We may need to specify this flag to really force application kill
+ // (we are shutting down ReactOS, not just logging off so no hangs, etc...
+ // should be allowed).
+ // LSData->Flags |= EWX_FORCE;
/* Run shutdown thread */
hThread = CreateThread(NULL, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL);
@@ -1305,6 +1376,12 @@
}
/* Check parameters */
+ if (Action & EWX_FORCE)
+ {
+ // FIXME!
+ ERR("FIXME: EWX_FORCE present for Winlogon, what to
do?\n");
+ Action &= ~EWX_FORCE;
+ }
switch (Action)
{
case EWX_LOGOFF:
@@ -1342,7 +1419,7 @@
// if you try now a shut down, it won't work because winlogon thinks it is
// still in the middle of a shutdown.
// Maybe we also need to reset ExitReactOSInProgress somewhere else??
- if (ExitReactOSInProgress && (lParam & EWX_INTERNAL_FLAG)
== 0)
+ if (ExitReactOSInProgress && (lParam &
EWX_CALLER_WINLOGON) == 0)
{
break;
}
Modified: trunk/reactos/include/reactos/winlogon.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/winlogon.h…
==============================================================================
--- trunk/reactos/include/reactos/winlogon.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/winlogon.h [iso-8859-1] Thu Feb 12 23:35:58 2015
@@ -2,17 +2,28 @@
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: include/reactos/winlogon.h
- * PURPOSE: Private interface between CSRSS and WinLogon
+ * PURPOSE: Private interface between Win32 and Winlogon
* PROGRAMMER: Ge van Geldorp (gvg(a)reactos.com)
*/
#ifndef REACTOS_WINLOGON_H_INCLUDED
#define REACTOS_WINLOGON_H_INCLUDED
-#define EWX_INTERNAL_FLAG 0x10000
-#define EWX_INTERNAL_KILL_USER_APPS (EWX_INTERNAL_FLAG | 0x100)
-#define EWX_INTERNAL_KILL_ALL_APPS (EWX_INTERNAL_FLAG | 0x200)
-#define EWX_INTERNAL_FLAG_LOGOFF 0x1000
+#define EWX_SHUTDOWN_CANCELED 0x0080
+
+#define EWX_CALLER_SYSTEM 0x0100
+#define EWX_CALLER_WINLOGON 0x0200
+
+#define EWX_CALLER_WINLOGON_LOGOFF 0x1000 // WARNING!! Broken flag.
+
+// All the range 0x0400 to 0x1000 is reserved for Winlogon.
+
+// Flag 0x2000 appears to be a flag set when we call InitiateSystemShutdown* APIs
(Winlogon shutdown APIs).
+
+// 0x4000 is also reserved.
+
+#define EWX_NOTIFY 0x8000
+#define EWX_NONOTIFY 0x10000
#endif /* REACTOS_WINLOGON_H_INCLUDED */
Modified: trunk/reactos/win32ss/user/ntuser/shutdown.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/shutdo…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/shutdown.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/shutdown.c [iso-8859-1] Thu Feb 12 23:35:58 2015
@@ -7,7 +7,12 @@
*/
#include <win32k.h>
+#include <winlogon.h>
+
DBG_DEFAULT_CHANNEL(UserShutdown);
+
+/* Our local copy of shutdown flags */
+static ULONG gdwShutdownFlags = 0;
/*
* Based on CSRSS and described in pages 1115 - 1118 "Windows Internals, Fifth
Edition".
@@ -150,6 +155,51 @@
return Result;
}
+BOOL
+NotifyLogon(IN HWND hWndSta,
+ IN PLUID CallerLuid,
+ IN ULONG Flags,
+ IN NTSTATUS ShutdownStatus)
+{
+ // LUID SystemLuid = SYSTEM_LUID;
+ ULONG Notif, Param;
+
+ ERR("NotifyLogon(0x%lx, 0x%lx)\n", Flags, ShutdownStatus);
+
+ /* If no Winlogon notifications are needed, just return */
+ if (Flags & EWX_NONOTIFY)
+ return FALSE;
+
+ /* In case we cancelled the shutdown...*/
+ if (Flags & EWX_SHUTDOWN_CANCELED)
+ {
+ /* ... send a LN_LOGOFF_CANCELED to Winlogon with the real cancel status... */
+ Notif = LN_LOGOFF_CANCELED;
+ Param = ShutdownStatus;
+ }
+ else
+ {
+ /* ... otherwise it's a real logoff. Send the shutdown flags in that case.
*/
+ Notif = LN_LOGOFF;
+ Param = Flags;
+ }
+
+ // FIXME: At the moment, always send the notifications... In real world some checks
are done.
+ // if (hwndSAS && ( (Flags & EWX_SHUTDOWN) || RtlEqualLuid(CallerLuid,
&SystemLuid)) )
+ if (hwndSAS)
+ {
+ ERR("\tSending %s message to Winlogon\n", Notif == LN_LOGOFF ?
"LN_LOGOFF" : "LN_LOGOFF_CANCELED");
+ UserPostMessage(hwndSAS, WM_LOGONNOTIFY, Notif, (LPARAM)Param);
+ return TRUE;
+ }
+ else
+ {
+ ERR("hwndSAS == NULL\n");
+ }
+
+ return FALSE;
+}
+
NTSTATUS
UserInitiateShutdown(IN PETHREAD Thread,
IN OUT PULONG pFlags)
@@ -157,7 +207,7 @@
NTSTATUS Status;
ULONG Flags = *pFlags;
LUID CallerLuid;
- // LUID SystemLuid = SYSTEM_LUID;
+ LUID SystemLuid = SYSTEM_LUID;
static PRIVILEGE_SET ShutdownPrivilege =
{
1, PRIVILEGE_SET_ALL_NECESSARY,
@@ -168,9 +218,6 @@
ERR("UserInitiateShutdown\n");
- if(hwndSAS == NULL)
- return STATUS_NOT_FOUND;
-
/* Get the caller's LUID */
Status = GetProcessLuid(Thread, &CallerLuid);
if (!NT_SUCCESS(Status))
@@ -179,8 +226,16 @@
return Status;
}
- // FIXME: Check if this is the System LUID, and adjust flags if needed.
- // if (RtlEqualLuid(&CallerLuid, &SystemLuid)) { Flags = ...; }
+ /*
+ * Check if this is the System LUID, and adjust flags if needed.
+ * In particular, be sure there is no EWX_CALLER_SYSTEM flag
+ * spuriously set (could be the sign of malicous app!).
+ */
+ if (RtlEqualLuid(&CallerLuid, &SystemLuid))
+ Flags |= EWX_CALLER_SYSTEM;
+ else
+ Flags &= ~EWX_CALLER_SYSTEM;
+
*pFlags = Flags;
/* Retrieve the Win32 process info */
@@ -191,7 +246,12 @@
/* If the caller is not Winlogon, do some security checks */
if (PsGetThreadProcessId(Thread) != gpidLogon)
{
- // FIXME: Play again with flags...
+ /*
+ * Here also, be sure there is no EWX_CALLER_WINLOGON flag
+ * spuriously set (could be the sign of malicous app!).
+ */
+ Flags &= ~EWX_CALLER_WINLOGON;
+
*pFlags = Flags;
/* Check whether the current process is attached to a window station */
@@ -224,24 +284,27 @@
}
}
- /* If the caller is not Winlogon, notify it to perform the real shutdown */
+ /* If the caller is not Winlogon, possibly notify it to perform the real shutdown */
if (PsGetThreadProcessId(Thread) != gpidLogon)
{
// FIXME: HACK!! Do more checks!!
ERR("UserInitiateShutdown -- Notify Winlogon for shutdown\n");
- UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_LOGOFF, (LPARAM)Flags);
+ NotifyLogon(hwndSAS, &CallerLuid, Flags, STATUS_SUCCESS);
return STATUS_PENDING;
}
// If we reach this point, that means it's Winlogon that triggered the shutdown.
- ERR("UserInitiateShutdown -- Winlogon shuts down\n");
+ ERR("UserInitiateShutdown -- Winlogon is doing a shutdown\n");
/*
- * FIXME:
- * Update and save the shutdown flags globally for renotifying Winlogon
- * if needed, when calling EndShutdown.
+ * Update and save the shutdown flags globally for renotifying
+ * Winlogon if needed, when calling EndShutdown.
*/
+ Flags |= EWX_CALLER_WINLOGON; // Winlogon is doing a shutdown, be sure the internal
flag is set.
*pFlags = Flags;
+
+ /* Save the shutdown flags now */
+ gdwShutdownFlags = Flags;
return STATUS_SUCCESS;
}
@@ -250,9 +313,45 @@
UserEndShutdown(IN PETHREAD Thread,
IN NTSTATUS ShutdownStatus)
{
+ NTSTATUS Status;
+ ULONG Flags;
+ LUID CallerLuid;
+
ERR("UserEndShutdown\n");
+
+ /*
+ * FIXME: Some cleanup should be done when shutdown succeeds,
+ * and some reset should be done when shutdown is cancelled.
+ */
STUB;
- return STATUS_NOT_IMPLEMENTED;
+
+ Status = GetProcessLuid(Thread, &CallerLuid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("GetProcessLuid failed\n");
+ return Status;
+ }
+
+ /* Copy the global flags because we're going to modify them for our purposes */
+ Flags = gdwShutdownFlags;
+
+ if (NT_SUCCESS(ShutdownStatus))
+ {
+ /* Just report success, and keep the shutdown flags as they are */
+ ShutdownStatus = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* Report the status to Winlogon and say that we cancel the shutdown */
+ Flags |= EWX_SHUTDOWN_CANCELED;
+ // FIXME: Should we reset gdwShutdownFlags to 0 ??
+ }
+
+ ERR("UserEndShutdown -- Notify Winlogon for end of shutdown\n");
+ NotifyLogon(hwndSAS, &CallerLuid, Flags, ShutdownStatus);
+
+ /* Always return success */
+ return STATUS_SUCCESS;
}
/* EOF */
Modified: trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/usersr…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c [iso-8859-1] Thu Feb 12 23:35:58
2015
@@ -493,7 +493,7 @@
{
Context.ProcessId = (DWORD_PTR) ProcessData->ClientId.UniqueProcess;
Context.wParam = 0;
- Context.lParam = (0 != (Flags & EWX_INTERNAL_FLAG_LOGOFF) ?
+ Context.lParam = (0 != (Flags & EWX_CALLER_WINLOGON_LOGOFF) ?
ENDSESSION_LOGOFF : 0);
Context.StartTime = 0;
Context.UIThread = NULL;
@@ -505,7 +505,7 @@
NotifyTopLevelWindows(&Context);
Context.wParam = (QUERY_RESULT_ABORT != Context.QueryResult);
- Context.lParam = (0 != (Flags & EWX_INTERNAL_FLAG_LOGOFF) ?
+ Context.lParam = (0 != (Flags & EWX_CALLER_WINLOGON_LOGOFF) ?
ENDSESSION_LOGOFF : 0);
Context.SendMessageProc = SendEndSession;
Context.ShowUI = DtbgIsDesktopVisible() &&
@@ -775,7 +775,7 @@
* Check for flags validity
*/
- if (Flags & EWX_INTERNAL_FLAG)
+ if (Flags & EWX_CALLER_WINLOGON)
{
/* Only Winlogon can call this */
if (ProcessId != LogonProcessId)
@@ -904,7 +904,10 @@
return CsrShutdownNonCsrProcess;
}
- DPRINT1("Killing process with ShutdownFlags = %lu\n",
CsrProcess->ShutdownFlags);
+ if (Flags & EWX_CALLER_SYSTEM)
+ DPRINT1("Killed by a SYSTEM process -- ShutdownFlags = %lu\n",
CsrProcess->ShutdownFlags);
+ else
+ DPRINT1("Killing process with ShutdownFlags = %lu\n",
CsrProcess->ShutdownFlags);
#if 0
if (!NotifyAndTerminateProcess(CsrProcess, &ShutdownSettings, Flags))