Author: hbelusca
Date: Sun Feb 8 00:54:22 2015
New Revision: 66202
URL:
http://svn.reactos.org/svn/reactos?rev=66202&view=rev
Log:
[WINSRV]: Remove some deprecated code, keep other parts for reusage later on; cleanup
SrvExitWindowsEx. If you enable the NotifyAndTerminateProcess call, you get a basic win32
process termination. This is now where the real work starts: do not kill CSRSS nor
Winlogon, do not kill processes from other sessions, etc... Deal with console apps;
display timeout dialog, and focus on the app that blocks shutdown by switching to the
correct desktop. And we MUST NOT use user32 desktop APIs for switching to the different
desktops, but we need to directly call win32k!! (for reasons that will appear later on;
not implemented at the moment). Giannis, I will need your help for that!
Part 10/X
CORE-8322
Modified:
trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c
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] Sun Feb 8 00:54:22
2015
@@ -31,6 +31,8 @@
DWORD HungAppTimeout;
DWORD WaitToKillAppTimeout;
} SHUTDOWN_SETTINGS, *PSHUTDOWN_SETTINGS;
+
+SHUTDOWN_SETTINGS ShutdownSettings = {0};
#define DEFAULT_AUTO_END_TASKS FALSE
#define DEFAULT_HUNG_APP_TIMEOUT 5000
@@ -84,16 +86,7 @@
/* FUNCTIONS ******************************************************************/
-/*
-NTSTATUS FASTCALL
-Win32CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc,
- PVOID Context)
-{
- return CsrEnumProcesses(EnumProc, Context);
-}
-*/
-
-static void FASTCALL
+static VOID FASTCALL
UpdateProgressBar(HWND ProgressBar, PNOTIFY_CONTEXT NotifyContext)
{
DWORD Passed;
@@ -185,20 +178,21 @@
return Result;
}
-static void
-CallInitCommonControls()
+HMODULE hComCtl32Lib = NULL;
+
+static VOID
+CallInitCommonControls(VOID)
{
static BOOL Initialized = FALSE;
- HMODULE Lib;
INITCOMMONCONTROLS_PROC InitProc;
if (Initialized) return;
- Lib = LoadLibraryW(L"COMCTL32.DLL");
- if (NULL == Lib) return;
-
- InitProc = (INITCOMMONCONTROLS_PROC) GetProcAddress(Lib,
"InitCommonControls");
- if (NULL == InitProc) return;
+ hComCtl32Lib = LoadLibraryW(L"COMCTL32.DLL");
+ if (hComCtl32Lib == NULL) return;
+
+ InitProc = (INITCOMMONCONTROLS_PROC)GetProcAddress(hComCtl32Lib,
"InitCommonControls");
+ if (InitProc == NULL) return;
(*InitProc)();
@@ -292,88 +286,74 @@
return FALSE;
}
- if (ProcessId == NotifyContext->ProcessId)
- {
- Now = GetTickCount();
- if (0 == NotifyContext->StartTime)
- {
- NotifyContext->StartTime = Now;
- }
- /* Note: Passed is computed correctly even when GetTickCount() wraps due
- to unsigned arithmetic */
- Passed = Now - NotifyContext->StartTime;
- MessageContext.Wnd = Wnd;
- MessageContext.Msg = NotifyContext->Msg;
- MessageContext.wParam = NotifyContext->wParam;
- MessageContext.lParam = NotifyContext->lParam;
- MessageContext.Timeout = NotifyContext->ShutdownSettings->HungAppTimeout;
- if (! NotifyContext->ShutdownSettings->AutoEndTasks)
- {
- MessageContext.Timeout +=
NotifyContext->ShutdownSettings->WaitToKillAppTimeout;
- }
- if (Passed < MessageContext.Timeout)
- {
- MessageContext.Timeout -= Passed;
- MessageThread = CreateThread(NULL, 0, NotifyContext->SendMessageProc,
- (LPVOID) &MessageContext, 0, NULL);
- if (NULL == MessageThread)
+ if (ProcessId != NotifyContext->ProcessId)
+ goto Quit;
+
+ Now = GetTickCount();
+ if (0 == NotifyContext->StartTime)
+ {
+ NotifyContext->StartTime = Now;
+ }
+ /*
+ * Note: Passed is computed correctly even when GetTickCount()
+ * wraps due to unsigned arithmetic.
+ */
+ Passed = Now - NotifyContext->StartTime;
+ MessageContext.Wnd = Wnd;
+ MessageContext.Msg = NotifyContext->Msg;
+ MessageContext.wParam = NotifyContext->wParam;
+ MessageContext.lParam = NotifyContext->lParam;
+ MessageContext.Timeout = NotifyContext->ShutdownSettings->HungAppTimeout;
+ if (! NotifyContext->ShutdownSettings->AutoEndTasks)
+ {
+ MessageContext.Timeout +=
NotifyContext->ShutdownSettings->WaitToKillAppTimeout;
+ }
+ if (Passed < MessageContext.Timeout)
+ {
+ MessageContext.Timeout -= Passed;
+ MessageThread = CreateThread(NULL, 0, NotifyContext->SendMessageProc,
+ (LPVOID) &MessageContext, 0, NULL);
+ if (NULL == MessageThread)
+ {
+ NotifyContext->QueryResult = QUERY_RESULT_ERROR;
+ return FALSE;
+ }
+ Timeout = NotifyContext->ShutdownSettings->HungAppTimeout;
+ if (Passed < Timeout)
+ {
+ Timeout -= Passed;
+ WaitStatus = WaitForSingleObjectEx(MessageThread, Timeout, FALSE);
+ }
+ else
+ {
+ WaitStatus = WAIT_TIMEOUT;
+ }
+ if (WAIT_TIMEOUT == WaitStatus)
+ {
+ NotifyContext->WndClient = Wnd;
+ if (NULL == NotifyContext->UIThread && NotifyContext->ShowUI)
{
- NotifyContext->QueryResult = QUERY_RESULT_ERROR;
- return FALSE;
+ NotifyContext->UIThread = CreateThread(NULL, 0,
+ EndNowThreadProc,
+ (LPVOID) NotifyContext,
+ 0, NULL);
}
- Timeout = NotifyContext->ShutdownSettings->HungAppTimeout;
- if (Passed < Timeout)
+ Threads[0] = MessageThread;
+ Threads[1] = NotifyContext->UIThread;
+ WaitStatus = WaitForMultipleObjectsEx(NULL == NotifyContext->UIThread ?
+ 1 : 2,
+ Threads, FALSE, INFINITE,
+ FALSE);
+ if (WAIT_OBJECT_0 == WaitStatus)
{
- Timeout -= Passed;
- WaitStatus = WaitForSingleObjectEx(MessageThread, Timeout, FALSE);
- }
- else
- {
- WaitStatus = WAIT_TIMEOUT;
- }
- if (WAIT_TIMEOUT == WaitStatus)
- {
- NotifyContext->WndClient = Wnd;
- if (NULL == NotifyContext->UIThread &&
NotifyContext->ShowUI)
- {
- NotifyContext->UIThread = CreateThread(NULL, 0,
- EndNowThreadProc,
- (LPVOID) NotifyContext,
- 0, NULL);
- }
- Threads[0] = MessageThread;
- Threads[1] = NotifyContext->UIThread;
- WaitStatus = WaitForMultipleObjectsEx(NULL == NotifyContext->UIThread
?
- 1 : 2,
- Threads, FALSE, INFINITE,
- FALSE);
- if (WAIT_OBJECT_0 == WaitStatus)
- {
- if (! GetExitCodeThread(MessageThread,
&NotifyContext->QueryResult))
- {
- NotifyContext->QueryResult = QUERY_RESULT_ERROR;
- }
- }
- else if (WAIT_OBJECT_0 + 1 == WaitStatus)
- {
- if (! GetExitCodeThread(NotifyContext->UIThread,
- &NotifyContext->QueryResult))
- {
- NotifyContext->QueryResult = QUERY_RESULT_ERROR;
- }
- }
- else
+ if (! GetExitCodeThread(MessageThread,
&NotifyContext->QueryResult))
{
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
}
- if (WAIT_OBJECT_0 != WaitStatus)
- {
- TerminateThread(MessageThread, QUERY_RESULT_TIMEOUT);
- }
}
- else if (WAIT_OBJECT_0 == WaitStatus)
+ else if (WAIT_OBJECT_0 + 1 == WaitStatus)
{
- if (! GetExitCodeThread(MessageThread,
+ if (! GetExitCodeThread(NotifyContext->UIThread,
&NotifyContext->QueryResult))
{
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
@@ -383,15 +363,33 @@
{
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
}
- CloseHandle(MessageThread);
+ if (WAIT_OBJECT_0 != WaitStatus)
+ {
+ TerminateThread(MessageThread, QUERY_RESULT_TIMEOUT);
+ }
+ }
+ else if (WAIT_OBJECT_0 == WaitStatus)
+ {
+ if (! GetExitCodeThread(MessageThread,
+ &NotifyContext->QueryResult))
+ {
+ NotifyContext->QueryResult = QUERY_RESULT_ERROR;
+ }
}
else
{
- NotifyContext->QueryResult = QUERY_RESULT_TIMEOUT;
- }
- }
-
- return QUERY_RESULT_CONTINUE == NotifyContext->QueryResult;
+ NotifyContext->QueryResult = QUERY_RESULT_ERROR;
+ }
+ CloseHandle(MessageThread);
+ }
+ else
+ {
+ NotifyContext->QueryResult = QUERY_RESULT_TIMEOUT;
+ }
+
+Quit:
+ DPRINT1("NotifyContext->QueryResult == %d\n",
NotifyContext->QueryResult);
+ return (NotifyContext->QueryResult == QUERY_RESULT_CONTINUE);
}
static BOOL CALLBACK
@@ -470,7 +468,7 @@
#endif
/************************************************/
-static BOOL FASTCALL
+BOOL FASTCALL
NotifyAndTerminateProcess(PCSR_PROCESS ProcessData,
PSHUTDOWN_SETTINGS ShutdownSettings,
UINT Flags)
@@ -629,32 +627,7 @@
}
#endif
-static int
-ProcessDataCompare(const void *Elem1, const void *Elem2)
-{
- const PCSR_PROCESS *ProcessData1 = (PCSR_PROCESS *) Elem1;
- const PCSR_PROCESS *ProcessData2 = (PCSR_PROCESS *) Elem2;
-
- if ((*ProcessData1)->ShutdownLevel < (*ProcessData2)->ShutdownLevel)
- {
- return +1;
- }
- else if ((*ProcessData2)->ShutdownLevel < (*ProcessData1)->ShutdownLevel)
- {
- return -1;
- }
- else if ((*ProcessData1)->ClientId.UniqueProcess <
(*ProcessData2)->ClientId.UniqueProcess)
- {
- return +1;
- }
- else if ((*ProcessData2)->ClientId.UniqueProcess <
(*ProcessData1)->ClientId.UniqueProcess)
- {
- return -1;
- }
-
- return 0;
-}
-
+#if 0
static DWORD FASTCALL
GetShutdownSettings(HKEY DesktopKey, LPCWSTR ValueName, DWORD DefaultValue)
{
@@ -695,7 +668,7 @@
return DefaultValue;
}
-static void FASTCALL
+static VOID FASTCALL
LoadShutdownSettings(PSID Sid, PSHUTDOWN_SETTINGS ShutdownSettings)
{
static WCHAR Subkey[] = L"\\Control Panel\\Desktop";
@@ -761,150 +734,56 @@
NTSTATUS FASTCALL
InternalExitReactos(DWORD ProcessId, DWORD ThreadId, UINT Flags)
{
- HANDLE CallerThread;
- HANDLE CallerToken;
- NTSTATUS Status;
- PROCESS_ENUM_CONTEXT Context;
- DWORD ReturnLength;
+ // PROCESS_ENUM_CONTEXT Context;
HWND ShellWnd;
- UINT ProcessIndex;
char FixedUserInfo[64];
TOKEN_USER *UserInfo;
SHUTDOWN_SETTINGS ShutdownSettings;
- if (ProcessId != LogonProcessId)
- {
- DPRINT1("Internal ExitWindowsEx call not from winlogon\n");
- return STATUS_ACCESS_DENIED;
- }
-
- // FIXME: HAAAAACK!!
- DPRINT1("FIXME: Need to close all user processes!\n");
+ LoadShutdownSettings(UserInfo->User.Sid, &ShutdownSettings);
+
+ // Context.CsrssProcess = GetCurrentProcessId();
+ // ShellWnd = GetShellWindow();
+ // if (NULL == ShellWnd)
+ // {
+ // DPRINT("No shell present\n");
+ // Context.ShellProcess = 0;
+ // }
+ // else if (0 == GetWindowThreadProcessId(ShellWnd, &Context.ShellProcess))
+ // {
+ // DPRINT1("Can't get process id of shell window\n");
+ // Context.ShellProcess = 0;
+ // }
+
return STATUS_SUCCESS;
-
- CallerThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, ThreadId);
- if (NULL == CallerThread)
- {
- DPRINT1("OpenThread failed with error %d\n", GetLastError());
- return STATUS_UNSUCCESSFUL;
- }
- if (! OpenThreadToken(CallerThread, TOKEN_QUERY, FALSE, &CallerToken))
- {
- DPRINT1("OpenThreadToken failed with error %d\n", GetLastError());
- CloseHandle(CallerThread);
- return STATUS_UNSUCCESSFUL;
- }
- CloseHandle(CallerThread);
-
- Context.ProcessCount = 0;
- Context.ProcessData = NULL;
- if (! GetTokenInformation(CallerToken, TokenOrigin, &Context.TokenOrigin,
- sizeof(TOKEN_ORIGIN), &ReturnLength))
- {
- DPRINT1("GetTokenInformation failed with error %d\n", GetLastError());
- CloseHandle(CallerToken);
- return STATUS_UNSUCCESSFUL;
- }
- if (! GetTokenInformation(CallerToken, TokenUser, FixedUserInfo,
- sizeof(FixedUserInfo), &ReturnLength))
- {
- if (sizeof(FixedUserInfo) < ReturnLength)
- {
- UserInfo = HeapAlloc(UserServerHeap, 0, ReturnLength);
- if (NULL == UserInfo)
- {
- DPRINT1("Unable to allocate %u bytes for user info\n",
- (unsigned) ReturnLength);
- CloseHandle(CallerToken);
- return STATUS_NO_MEMORY;
- }
- if (! GetTokenInformation(CallerToken, TokenUser, UserInfo,
- ReturnLength, &ReturnLength))
- {
- DPRINT1("GetTokenInformation failed with error %d\n",
- GetLastError());
- HeapFree(UserServerHeap, 0, UserInfo);
- CloseHandle(CallerToken);
- return STATUS_UNSUCCESSFUL;
- }
- }
- else
- {
- DPRINT1("GetTokenInformation failed with error %d\n",
GetLastError());
- CloseHandle(CallerToken);
- return STATUS_UNSUCCESSFUL;
- }
- }
- else
- {
- UserInfo = (TOKEN_USER *) FixedUserInfo;
- }
- CloseHandle(CallerToken);
- LoadShutdownSettings(UserInfo->User.Sid, &ShutdownSettings);
- if (UserInfo != (TOKEN_USER *) FixedUserInfo)
- {
- HeapFree(UserServerHeap, 0, UserInfo);
- }
- Context.CsrssProcess = GetCurrentProcessId();
- ShellWnd = GetShellWindow();
- if (NULL == ShellWnd)
- {
- DPRINT("No shell present\n");
- Context.ShellProcess = 0;
- }
- else if (0 == GetWindowThreadProcessId(ShellWnd, &Context.ShellProcess))
- {
- DPRINT1("Can't get process id of shell window\n");
- Context.ShellProcess = 0;
- }
-
- // Status = Win32CsrEnumProcesses(ExitReactosProcessEnum, &Context);
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed to enumerate registered processes, status 0x%x\n",
- Status);
- if (NULL != Context.ProcessData)
- {
- HeapFree(UserServerHeap, 0, Context.ProcessData);
- }
- return Status;
- }
-
- qsort(Context.ProcessData, Context.ProcessCount, sizeof(PCSR_PROCESS),
- ProcessDataCompare);
-
- /* Terminate processes, stop if we find one kicking and screaming it doesn't
- want to die */
- Status = STATUS_SUCCESS;
- for (ProcessIndex = 0;
- ProcessIndex < Context.ProcessCount && NT_SUCCESS(Status);
- ProcessIndex++)
- {
- if (! NotifyAndTerminateProcess(Context.ProcessData[ProcessIndex],
- &ShutdownSettings, Flags))
- {
- Status = STATUS_REQUEST_ABORTED;
- }
- }
-
- /* Cleanup */
- if (NULL != Context.ProcessData)
- {
- HeapFree(UserServerHeap, 0, Context.ProcessData);
- }
-
- return Status;
-}
+}
+#endif
static NTSTATUS FASTCALL
UserExitReactos(PCSR_THREAD CsrThread, UINT Flags)
{
NTSTATUS Status;
LUID CallerLuid;
+
+ DWORD ProcessId = HandleToUlong(CsrThread->ClientId.UniqueProcess);
+ DWORD ThreadId = HandleToUlong(CsrThread->ClientId.UniqueThread);
+
+ DPRINT1("SrvExitWindowsEx(ClientId: %lx.%lx, Flags: 0x%x)\n",
+ ProcessId, ThreadId, Flags);
/*
* Check for flags validity
*/
+
+ if (Flags & EWX_INTERNAL_FLAG)
+ {
+ /* Only Winlogon can call this */
+ if (ProcessId != LogonProcessId)
+ {
+ DPRINT1("SrvExitWindowsEx call not from Winlogon\n");
+ return STATUS_ACCESS_DENIED;
+ }
+ }
/* Implicitely add the shutdown flag when we poweroff or reboot */
if (Flags & (EWX_POWEROFF | EWX_REBOOT))
@@ -984,14 +863,6 @@
{
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
@@ -1018,7 +889,29 @@
DPRINT1("UserClientShutdown(0x%p, 0x%x, %s)\n",
CsrProcess, Flags, FirstPhase ? "FirstPhase" :
"LastPhase");
- UNIMPLEMENTED;
+ /*
+ * Check for process validity
+ */
+
+ /* Do not kill WinLogon or CSRSS */
+ if (CsrProcess->ClientId.UniqueProcess == NtCurrentProcess() ||
+ CsrProcess->ClientId.UniqueProcess == UlongToHandle(LogonProcessId))
+ {
+ DPRINT1("Not killing %s; CsrProcess->ShutdownFlags = %lu\n",
+ CsrProcess->ClientId.UniqueProcess == NtCurrentProcess() ?
"CSRSS" : "Winlogon",
+ CsrProcess->ShutdownFlags);
+
+ return CsrShutdownNonCsrProcess;
+ }
+
+ DPRINT1("Killing process with ShutdownFlags = %lu\n",
CsrProcess->ShutdownFlags);
+
+#if 0
+ if (!NotifyAndTerminateProcess(CsrProcess, &ShutdownSettings, Flags))
+ {
+ return CsrShutdownCancelled;
+ }
+#endif
return CsrShutdownNonCsrProcess;
}
@@ -1030,41 +923,11 @@
{
NTSTATUS Status;
PUSER_EXIT_REACTOS ExitReactosRequest =
&((PUSER_API_MESSAGE)ApiMessage)->Data.ExitReactosRequest;
- PCSR_THREAD CsrThread = CsrGetClientThread();
- ULONG Flags = ExitReactosRequest->Flags;
-
- DWORD ProcessId = HandleToUlong(CsrThread->ClientId.UniqueProcess);
- DWORD ThreadId = HandleToUlong(CsrThread->ClientId.UniqueThread);
-
- DPRINT1("SrvExitWindowsEx(ClientId: %lx.%lx, Flags: 0x%x)\n",
- ProcessId, ThreadId, Flags);
-
-
- // FIXME: Everything else starting after this line is a HAAACK!!
-
-
- 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
- {
- Status = UserExitReactos(CsrThread, Flags);
- }
-
- ExitReactosRequest->Success = NT_SUCCESS(Status);
+
+ Status = UserExitReactos(CsrGetClientThread(), ExitReactosRequest->Flags);
+ ExitReactosRequest->Success = NT_SUCCESS(Status);
+ ExitReactosRequest->LastError = GetLastError();
+
return Status;
}
@@ -1082,7 +945,7 @@
{
if (EndTaskRequest->Force)
{
- EndTaskRequest->Success = DestroyWindow(EndTaskRequest->WndHandle);
+ EndTaskRequest->Success = DestroyWindow(EndTaskRequest->WndHandle);
EndTaskRequest->LastError = GetLastError();
}
else
@@ -1092,8 +955,8 @@
}
else
{
+ EndTaskRequest->Success = TRUE;
EndTaskRequest->LastError = ERROR_SUCCESS;
- EndTaskRequest->Success = TRUE;
}
return STATUS_SUCCESS;