[WINLOGON]

- Add DPRINTs to monitor how shutdown goes on (obviously they will go away when shutdown on ROS will be working).
- Add dumb handler for LN_LOGOFF_CANCELED message (unused for now...)

[WIN32K]: DPRINTs added for monitoring shutdown.

[WINSRV]: Start to plugin the whole thing (using pieces of Alex' shutdown patch):
- We need to use a "shutdown" loop (for UserThreadInitiateShutdown win32k call) for being able to cancel shuts down (not implemented yet).
- Add the "magic" call to CsrShutdownProcesses that calls the Shutdown callback of each CSR server for each Win32 process (these are those callbacks that do the real job of terminating the apps, displaying the "Kill the app" dialog, etc...). In few words, the old (disabled) code of InternalExitReactos need to go into those shutdown callbacks (but this is for other commits!).

Part 9/X

CORE-8322 #comment Continue plugging in the shutdown code (from Alex' patch) in WINSRV with adaptations into WINLOGON (+ adding DPRINTs for controlling the whole thing).

svn path=/trunk/; revision=66197
This commit is contained in:
Hermès Bélusca-Maïto 2015-02-07 20:46:27 +00:00
parent aeaff2bf59
commit 38bb64ba24
3 changed files with 142 additions and 37 deletions

View file

@ -38,6 +38,8 @@ typedef struct tagLOGOFF_SHUTDOWN_DATA
PWLSESSION Session;
} LOGOFF_SHUTDOWN_DATA, *PLOGOFF_SHUTDOWN_DATA;
static BOOL ExitReactOSInProgress = FALSE;
/* FUNCTIONS ****************************************************************/
static BOOL
@ -499,25 +501,33 @@ LogoffShutdownThread(
LPVOID Parameter)
{
PLOGOFF_SHUTDOWN_DATA LSData = (PLOGOFF_SHUTDOWN_DATA)Parameter;
UINT uFlags;
if (LSData->Session->UserToken != NULL && !ImpersonateLoggedOnUser(LSData->Session->UserToken))
if (LSData->Session->UserToken != NULL &&
!ImpersonateLoggedOnUser(LSData->Session->UserToken))
{
ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
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);
ERR("In LogoffShutdownThread with uFlags == 0x%x; exit_in_progress == %s\n",
uFlags, ExitReactOSInProgress ? "true" : "false");
ExitReactOSInProgress = TRUE;
/* Close processes of the interactive user */
if (!ExitWindowsEx(
EWX_INTERNAL_KILL_USER_APPS | (LSData->Flags & EWX_FLAGS_MASK) |
(EWX_LOGOFF == (LSData->Flags & EWX_ACTION_MASK) ? EWX_INTERNAL_FLAG_LOGOFF : 0),
0))
if (!ExitWindowsEx(uFlags, 0))
{
ERR("Unable to kill user apps, error %lu\n", GetLastError());
RevertToSelf();
return 0;
}
/* FIXME: Call ExitWindowsEx() to terminate COM processes */
/* FIXME: Call ExitWindowsEx() to terminate COM processes only at logoff! */
ERR("Should terminate COM processes only at logoff!\n");
if (LSData->Session->UserToken)
RevertToSelf();
@ -687,7 +697,7 @@ HandleLogoff(
/* Run logoff thread */
hThread = CreateThread(psa, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL);
/* we're done with the SECURITY_DESCRIPTOR */
/* We're done with the SECURITY_DESCRIPTOR */
DestroyLogoffSecurityAttributes(psa);
psa = NULL;
@ -1317,10 +1327,38 @@ SASWindowProc(
}
}
ERR("In LN_LOGOFF, exit_in_progress == %s\n",
ExitReactOSInProgress ? "true" : "false");
/*
* In case a parallel shutdown request is done (while we are
* being to shut down) and it was not done by Winlogon itself,
* then just stop here.
*/
#if 0
// This code is commented at the moment (even if it's correct) because
// our log-offs do not really work: the shell is restarted, no app is killed
// etc... and as a result you just get explorer opening "My Documents". And
// 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)
{
break;
}
#endif
/* Now do the shutdown action proper */
DoGenericAction(Session, wlxAction);
return 1;
}
case LN_LOGOFF_CANCELED:
{
ERR("Logoff canceled!!, before: exit_in_progress == %s, after will be false\n",
ExitReactOSInProgress ? "true" : "false");
ExitReactOSInProgress = FALSE;
return 1;
}
default:
{
ERR("WM_LOGONNOTIFY case %d is unimplemented\n", wParam);

View file

@ -228,11 +228,13 @@ UserInitiateShutdown(IN PETHREAD Thread,
if (PsGetThreadProcessId(Thread) != gpidLogon)
{
// FIXME: HACK!! Do more checks!!
ERR("UserInitiateShutdown -- Notify Winlogon for shutdown\n");
UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_LOGOFF, (LPARAM)Flags);
return STATUS_PENDING;
}
// If we reach this point, that means it's Winlogon that triggered the shutdown.
ERR("UserInitiateShutdown -- Winlogon shuts down\n");
/*
* FIXME:

View file

@ -758,7 +758,7 @@ LoadShutdownSettings(PSID Sid, PSHUTDOWN_SETTINGS ShutdownSettings)
RegCloseKey(DesktopKey);
}
static NTSTATUS FASTCALL
NTSTATUS FASTCALL
InternalExitReactos(DWORD ProcessId, DWORD ThreadId, UINT Flags)
{
HANDLE CallerThread;
@ -772,7 +772,7 @@ InternalExitReactos(DWORD ProcessId, DWORD ThreadId, UINT Flags)
TOKEN_USER *UserInfo;
SHUTDOWN_SETTINGS ShutdownSettings;
if (ProcessId != (DWORD_PTR) LogonProcessId)
if (ProcessId != LogonProcessId)
{
DPRINT1("Internal ExitWindowsEx call not from winlogon\n");
return STATUS_ACCESS_DENIED;
@ -902,11 +902,17 @@ UserExitReactos(PCSR_THREAD CsrThread, UINT Flags)
NTSTATUS Status;
LUID CallerLuid;
// FIXME: HACK!!
/*
* Check for flags validity
*/
/* Implicitely add the shutdown flag when we poweroff or reboot */
if (Flags & (EWX_POWEROFF | EWX_REBOOT))
Flags |= EWX_SHUTDOWN;
/*
* Retrieve the caller's LUID so that we can only shutdown
* processes in the caller's LUID.
* Impersonate and retrieve the caller's LUID so that
* we can only shutdown processes in its context.
*/
if (!CsrImpersonateClient(NULL))
return STATUS_BAD_IMPERSONATION_LEVEL;
@ -920,27 +926,84 @@ UserExitReactos(PCSR_THREAD CsrThread, UINT Flags)
DPRINT1("Caller LUID is: %lx.%lx\n", CallerLuid.HighPart, CallerLuid.LowPart);
/* Notify Win32k and potentially Winlogon of the shutdown */
Status = NtUserSetInformationThread(CsrThread->ThreadHandle,
UserThreadInitiateShutdown,
&Flags, sizeof(Flags));
DPRINT1("Win32k says: %lx\n", Status);
/* Shutdown loop */
while (TRUE)
{
/* Notify Win32k and potentially Winlogon of the shutdown */
Status = NtUserSetInformationThread(CsrThread->ThreadHandle,
UserThreadInitiateShutdown,
&Flags, sizeof(Flags));
DPRINT1("Win32k says: %lx\n", Status);
switch (Status)
{
/* We cannot wait here, the caller should start a new thread */
case STATUS_CANT_WAIT:
DPRINT1("STATUS_CANT_WAIT\n");
goto Quit;
/* If the message isn't handled, the return value is 0, so 0 doesn't indicate
success. Success is indicated by a 1 return value, if anything besides 0
or 1 it's a NTSTATUS value */
if (1 == Status)
{
Status = STATUS_SUCCESS;
/* Shutdown is in progress */
case STATUS_PENDING:
DPRINT1("STATUS_PENDING\n");
goto Quit;
/* Abort */
case STATUS_RETRY:
{
DPRINT1("STATUS_RETRY\n");
UNIMPLEMENTED;
continue;
}
default:
{
if (!NT_SUCCESS(Status))
{
// FIXME: Use some UserSetLastNTError or SetLastNtError
// that we have defined for user32 or win32k usage only...
SetLastError(RtlNtStatusToDosError(Status));
goto Quit;
}
}
}
/* All good */
break;
}
else if (0 == Status)
/*
* OK we can continue. Now magic happens:
*
* Terminate all Win32 processes, stop if we find one kicking
* and screaming it doesn't want to die.
*
* This function calls the ShutdownProcessCallback callback of
* each CSR server for each Win32 process.
*/
Status = CsrShutdownProcesses(&CallerLuid, Flags);
if (!NT_SUCCESS(Status))
{
Status = STATUS_NOT_IMPLEMENTED;
DPRINT1("Failed to shutdown processes, Status = 0x%08x\n", Status);
}
/*
* FIXME:
* At the moment the callbacks just do nothing so no process will be killed.
* It's not dramatic since:
* 1- We didn't do that before,
* 2- Related to point 1, the hackish InternalExitReactos call will end back
* into Winlogon that will directly call NtShutdownSystem.
*/
// FIXME: If Status == STATUS_CANCELLED, call RecordShutdownReason
/* Tell Win32k and potentially Winlogon that we're done */
NtUserSetInformationThread(CsrThread->ThreadHandle,
UserThreadEndShutdown,
&Status, sizeof(Status));
DPRINT1("SrvExitWindowsEx returned 0x%08x\n", Status);
Quit:
/* We are done */
CsrRevertToSelf();
return Status;
}
@ -970,33 +1033,35 @@ CSR_API(SrvExitWindowsEx)
PCSR_THREAD CsrThread = CsrGetClientThread();
ULONG Flags = ExitReactosRequest->Flags;
/*
* Check for flags validity
*/
DWORD ProcessId = HandleToUlong(CsrThread->ClientId.UniqueProcess);
DWORD ThreadId = HandleToUlong(CsrThread->ClientId.UniqueThread);
DPRINT1("SrvExitWindowsEx(ClientId: %lx.%lx, Flags: 0x%x)\n",
ProcessId, ThreadId, Flags);
/* Implicitely add the shutdown flag when we poweroff or reboot */
if (Flags & (EWX_POWEROFF | EWX_REBOOT))
Flags |= EWX_SHUTDOWN;
// FIXME: Everything else starting after this line is a HAAACK!!
if (0 == (Flags & EWX_INTERNAL_FLAG))
if (Flags & EWX_INTERNAL_FLAG)
{
/* Only Winlogon can call this */
if (ProcessId != LogonProcessId)
{
DPRINT1("SrvExitWindowsEx call not from Winlogon\n");
return STATUS_ACCESS_DENIED;
}
// This function is a HACK!!
// EWX_INTERNAL_FLAG --> For Winlogon only!!
// Status = InternalExitReactos(ProcessId, ThreadId, Flags);
// This is this function that we need to call instead!
Status = UserExitReactos(CsrThread, Flags);
}
else
{
// EWX_INTERNAL_FLAG --> For Winlogon only!!
// FIXME: This is just a big HAAAACK!!
Status = InternalExitReactos(ProcessId, ThreadId, Flags);
Status = UserExitReactos(CsrThread, Flags);
}
ExitReactosRequest->Success = NT_SUCCESS(Status);