Author: hbelusca
Date: Sun Feb 15 22:57:40 2015
New Revision: 66306
URL:
http://svn.reactos.org/svn/reactos?rev=66306&view=rev
Log:
[WINSRV]
- Part 2/2 of SrvLogon (see r66303): load the per-user shutdown timeouts.
- Retrieve those per-user shutdown timeouts from the registry when the user logs on,
adapted from Alex' shutdown patch plus existing code.
- Commit the main part of shutdown code (finally!), still unfinished yet:
* Need to switch to the desktop where the hanging GUI app's window is present,
* Need to deal with apps from other users
* What about SYSTEM processes?
* What about console processes?
- Reuse the old timeout code.
- Fix the sending of WM_QUERYENDSESSION and WM_ENDSESSION messages (this is done by win32k
directly; for that winsrv needs just to send one WM_CLIENTSHUTDOWN message with the
correct wParam parameter).
Part 13/X
CORE-8322 #comment Big commit in revision 66306!
Modified:
trunk/reactos/win32ss/user/winsrv/consrv/consrv.h
trunk/reactos/win32ss/user/winsrv/init.c
trunk/reactos/win32ss/user/winsrv/usersrv/init.c
trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c
trunk/reactos/win32ss/user/winsrv/winsrv.h
Modified: trunk/reactos/win32ss/user/winsrv/consrv/consrv.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/consrv.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/consrv.h [iso-8859-1] Sun Feb 15 22:57:40
2015
@@ -18,7 +18,6 @@
#define COM_NO_WINDOWS_H
#include <winnls.h>
-#include <winreg.h>
#include <wincon.h>
#define NTOS_MODE_USER
Modified: trunk/reactos/win32ss/user/winsrv/init.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/init.c…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/init.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/init.c [iso-8859-1] Sun Feb 15 22:57:40 2015
@@ -13,6 +13,157 @@
#define NDEBUG
#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+#define DEFAULT_AUTO_END_TASKS FALSE
+#define DEFAULT_HUNG_APP_TIMEOUT 5000
+#define DEFAULT_WAIT_TO_KILL_APP_TIMEOUT 20000
+#define DEFAULT_PROCESS_TERMINATE_TIMEOUT 90000
+
+SHUTDOWN_SETTINGS ShutdownSettings =
+{
+ DEFAULT_AUTO_END_TASKS,
+ DEFAULT_HUNG_APP_TIMEOUT,
+ DEFAULT_WAIT_TO_KILL_APP_TIMEOUT,
+ DEFAULT_WAIT_TO_KILL_APP_TIMEOUT,
+ DEFAULT_PROCESS_TERMINATE_TIMEOUT
+};
+
+/* FUNCTIONS ******************************************************************/
+
+static ULONG
+GetRegIntFromID(IN HANDLE KeyHandle,
+ IN PWCHAR ValueName,
+ IN ULONG DefaultValue)
+{
+ UNICODE_STRING ValueString;
+ ULONG Length;
+ UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 32 * sizeof(WCHAR)];
+ PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)Buffer;
+ NTSTATUS Status;
+ ULONG Value;
+
+ /* Open the key */
+ RtlInitUnicodeString(&ValueString, ValueName);
+ Status = NtQueryValueKey(KeyHandle,
+ &ValueString,
+ KeyValuePartialInformation,
+ PartialInfo,
+ sizeof(Buffer),
+ &Length);
+ if (NT_SUCCESS(Status))
+ {
+ if (PartialInfo->Type == REG_SZ)
+ {
+ /* Convert to integer */
+ RtlInitUnicodeString(&ValueString, (PWCHAR)PartialInfo->Data);
+ Status = RtlUnicodeStringToInteger(&ValueString, 10, &Value);
+ }
+ else if (PartialInfo->Type == REG_DWORD)
+ {
+ /* Directly retrieve the data */
+ Value = *(PULONG)PartialInfo->Data;
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ DPRINT1("Unexpected registry type %d for setting %S\n",
PartialInfo->Type, ValueName);
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* Use default value instead */
+ Value = DefaultValue;
+ }
+
+ /* Return the value */
+ return Value;
+}
+
+VOID FASTCALL
+GetTimeouts(IN PSHUTDOWN_SETTINGS ShutdownSettings)
+{
+ NTSTATUS Status;
+ UNICODE_STRING RegistryString;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE CurrentUserKeyHandle;
+ HANDLE KeyHandle;
+
+ /* Initialize with defaults first */
+ ShutdownSettings->AutoEndTasks = DEFAULT_AUTO_END_TASKS;
+ ShutdownSettings->HungAppTimeout = DEFAULT_HUNG_APP_TIMEOUT;
+ ShutdownSettings->WaitToKillAppTimeout = DEFAULT_WAIT_TO_KILL_APP_TIMEOUT;
+ ShutdownSettings->WaitToKillServiceTimeout =
ShutdownSettings->WaitToKillAppTimeout;
+ ShutdownSettings->ProcessTerminateTimeout = DEFAULT_PROCESS_TERMINATE_TIMEOUT;
+
+ /* Open the per-user desktop key */
+ Status = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &CurrentUserKeyHandle);
+ if (NT_SUCCESS(Status))
+ {
+ RtlInitUnicodeString(&RegistryString,
+ L"Control Panel\\Desktop");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryString,
+ OBJ_CASE_INSENSITIVE,
+ CurrentUserKeyHandle,
+ NULL);
+ Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
+ if (NT_SUCCESS(Status))
+ {
+ /* Read timeouts */
+ ShutdownSettings->HungAppTimeout = GetRegIntFromID(KeyHandle,
+
L"HungAppTimeout",
+ DEFAULT_HUNG_APP_TIMEOUT);
+ ShutdownSettings->WaitToKillAppTimeout = GetRegIntFromID(KeyHandle,
+
L"WaitToKillAppTimeout",
+
DEFAULT_WAIT_TO_KILL_APP_TIMEOUT);
+ ShutdownSettings->AutoEndTasks = GetRegIntFromID(KeyHandle,
+ L"AutoEndTasks",
+ DEFAULT_AUTO_END_TASKS);
+ /* Done */
+ NtClose(KeyHandle);
+ }
+
+ /* Done */
+ NtClose(CurrentUserKeyHandle);
+ }
+
+ /* Now open the control key */
+ RtlInitUnicodeString(&RegistryString,
+
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RegistryString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, NULL);
+ Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
+ if (NT_SUCCESS(Status))
+ {
+ /* Read the services timeout */
+ ShutdownSettings->WaitToKillServiceTimeout = GetRegIntFromID(KeyHandle,
+
L"WaitToKillServiceTimeout",
+
ShutdownSettings->WaitToKillAppTimeout);
+
+ /*
+ * Retrieve the process terminate timeout.
+ * See
ftp://ftp.microsoft.com/MISC1/BUSSYS/WINNT/KB/Q234/6/06.TXT
+ * and
https://web.archive.org/web/20050216235758/http://support.microsoft.com/kb/…
+ * for more details.
+ *
+ * NOTE: Unused at the moment...
+ */
+ ShutdownSettings->ProcessTerminateTimeout = GetRegIntFromID(KeyHandle,
+
L"ProcessTerminateTimeout",
+
DEFAULT_PROCESS_TERMINATE_TIMEOUT);
+ if (ShutdownSettings->ProcessTerminateTimeout < DEFAULT_HUNG_APP_TIMEOUT)
+ ShutdownSettings->ProcessTerminateTimeout = DEFAULT_HUNG_APP_TIMEOUT;
+
+ /* Done */
+ NtClose(KeyHandle);
+ }
+}
/* ENTRY-POINT ****************************************************************/
Modified: trunk/reactos/win32ss/user/winsrv/usersrv/init.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/usersr…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/usersrv/init.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/usersrv/init.c [iso-8859-1] Sun Feb 15 22:57:40
2015
@@ -135,6 +135,23 @@
{
DPRINT1("%s not yet implemented\n", __FUNCTION__);
return STATUS_NOT_IMPLEMENTED;
+}
+
+CSR_API(SrvLogon)
+{
+ PUSER_LOGON LogonRequest =
&((PUSER_API_MESSAGE)ApiMessage)->Data.LogonRequest;
+
+ DPRINT1("We are logged %s\n", LogonRequest->IsLogon ? "on" :
"off");
+
+ /* Impersonate the caller in order to retrieve settings in its context */
+ if (!CsrImpersonateClient(NULL))
+ return STATUS_UNSUCCESSFUL;
+
+ GetTimeouts(&ShutdownSettings);
+
+ /* We are done */
+ CsrRevertToSelf();
+ return STATUS_SUCCESS;
}
NTSTATUS
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 15 22:57:40
2015
@@ -4,19 +4,14 @@
* FILE: win32ss/user/winsrv/usersrv/shutdown.c
* PURPOSE: Logout/shutdown
* PROGRAMMERS:
- *
- * NOTE: The shutdown code must be rewritten completely. (hbelusca)
*/
/* INCLUDES *******************************************************************/
#include "usersrv.h"
-#include <stdlib.h>
-#include <winreg.h>
#include <winlogon.h>
#include <commctrl.h>
-#include <sddl.h>
#include "resource.h"
@@ -25,27 +20,25 @@
/* GLOBALS ********************************************************************/
-typedef struct tagSHUTDOWN_SETTINGS
-{
- BOOL AutoEndTasks;
- DWORD HungAppTimeout;
- DWORD WaitToKillAppTimeout;
-} SHUTDOWN_SETTINGS, *PSHUTDOWN_SETTINGS;
-
-SHUTDOWN_SETTINGS ShutdownSettings = {0};
-
-#define DEFAULT_AUTO_END_TASKS FALSE
-#define DEFAULT_HUNG_APP_TIMEOUT 5000
-#define DEFAULT_WAIT_TO_KILL_APP_TIMEOUT 20000
+// Those flags (that are used for CsrProcess->ShutdownFlags) are named
+// in accordance to the only public one: SHUTDOWN_NORETRY used for the
+// SetProcessShutdownParameters API.
+#if !defined(SHUTDOWN_SYSTEMCONTEXT) && !defined(SHUTDOWN_OTHERCONTEXT)
+#define SHUTDOWN_SYSTEMCONTEXT CsrShutdownSystem
+#define SHUTDOWN_OTHERCONTEXT CsrShutdownOther
+#endif
+
+// The DPRINTs that need to really be removed as soon as everything works.
+#define MY_DPRINT DPRINT1
+#define MY_DPRINT2 DPRINT
typedef struct tagNOTIFY_CONTEXT
{
- DWORD ProcessId;
UINT Msg;
WPARAM wParam;
LPARAM lParam;
- HDESK Desktop;
- HDESK OldDesktop;
+ // HDESK Desktop;
+ // HDESK OldDesktop;
DWORD StartTime;
DWORD QueryResult;
HWND Dlg;
@@ -54,7 +47,6 @@
HANDLE UIThread;
HWND WndClient;
PSHUTDOWN_SETTINGS ShutdownSettings;
- LPTHREAD_START_ROUTINE SendMessageProc;
} NOTIFY_CONTEXT, *PNOTIFY_CONTEXT;
#define QUERY_RESULT_ABORT 0
@@ -74,17 +66,29 @@
DWORD Timeout;
} MESSAGE_CONTEXT, *PMESSAGE_CONTEXT;
-typedef struct tagPROCESS_ENUM_CONTEXT
-{
- UINT ProcessCount;
- PCSR_PROCESS *ProcessData;
- TOKEN_ORIGIN TokenOrigin;
- DWORD ShellProcess;
- DWORD CsrssProcess;
-} PROCESS_ENUM_CONTEXT, *PPROCESS_ENUM_CONTEXT;
-
/* FUNCTIONS ******************************************************************/
+
+static HMODULE hComCtl32Lib = NULL;
+
+static VOID
+CallInitCommonControls(VOID)
+{
+ static BOOL Initialized = FALSE;
+ INITCOMMONCONTROLS_PROC InitProc;
+
+ if (Initialized) return;
+
+ hComCtl32Lib = LoadLibraryW(L"COMCTL32.DLL");
+ if (hComCtl32Lib == NULL) return;
+
+ InitProc = (INITCOMMONCONTROLS_PROC)GetProcAddress(hComCtl32Lib,
"InitCommonControls");
+ if (InitProc == NULL) return;
+
+ (*InitProc)();
+
+ Initialized = TRUE;
+}
static VOID FASTCALL
UpdateProgressBar(HWND ProgressBar, PNOTIFY_CONTEXT NotifyContext)
@@ -113,18 +117,18 @@
switch(Msg)
{
case WM_INITDIALOG:
- NotifyContext = (PNOTIFY_CONTEXT) lParam;
+ NotifyContext = (PNOTIFY_CONTEXT)lParam;
NotifyContext->EndNowResult = QUERY_RESULT_ABORT;
- SetWindowLongPtrW(Dlg, DWLP_USER, (LONG_PTR) lParam);
+ SetWindowLongPtrW(Dlg, DWLP_USER, (LONG_PTR)lParam);
TitleLength = SendMessageW(NotifyContext->WndClient, WM_GETTEXTLENGTH,
0, 0) +
GetWindowTextLengthW(Dlg);
Title = HeapAlloc(UserServerHeap, 0, (TitleLength + 1) * sizeof(WCHAR));
- if (NULL != Title)
+ if (Title)
{
Len = GetWindowTextW(Dlg, Title, TitleLength + 1);
SendMessageW(NotifyContext->WndClient, WM_GETTEXT,
- TitleLength + 1 - Len, (LPARAM) (Title + Len));
+ TitleLength + 1 - Len, (LPARAM)(Title + Len));
SetWindowTextW(Dlg, Title);
HeapFree(UserServerHeap, 0, Title);
}
@@ -137,7 +141,7 @@
break;
case WM_TIMER:
- NotifyContext = (PNOTIFY_CONTEXT) GetWindowLongPtrW(Dlg, DWLP_USER);
+ NotifyContext = (PNOTIFY_CONTEXT)GetWindowLongPtrW(Dlg, DWLP_USER);
ProgressBar = GetDlgItem(Dlg, IDC_PROGRESS);
UpdateProgressBar(ProgressBar, NotifyContext);
Result = TRUE;
@@ -146,8 +150,9 @@
case WM_COMMAND:
if (BN_CLICKED == HIWORD(wParam) && IDC_END_NOW == LOWORD(wParam))
{
- NotifyContext = (PNOTIFY_CONTEXT) GetWindowLongPtrW(Dlg, DWLP_USER);
+ NotifyContext = (PNOTIFY_CONTEXT)GetWindowLongPtrW(Dlg, DWLP_USER);
NotifyContext->EndNowResult = QUERY_RESULT_FORCE;
+ MY_DPRINT("Closing progress dlg by hand\n");
SendMessageW(Dlg, WM_CLOSE, 0, 0);
Result = TRUE;
}
@@ -158,12 +163,14 @@
break;
case WM_CLOSE:
+ MY_DPRINT("WM_CLOSE\n");
DestroyWindow(Dlg);
Result = TRUE;
break;
case WM_DESTROY:
- NotifyContext = (PNOTIFY_CONTEXT) GetWindowLongPtrW(Dlg, DWLP_USER);
+ MY_DPRINT("WM_DESTROY\n");
+ NotifyContext = (PNOTIFY_CONTEXT)GetWindowLongPtrW(Dlg, DWLP_USER);
NotifyContext->Dlg = NULL;
KillTimer(Dlg, 0);
PostQuitMessage(NotifyContext->EndNowResult);
@@ -178,48 +185,26 @@
return Result;
}
-HMODULE hComCtl32Lib = NULL;
-
-static VOID
-CallInitCommonControls(VOID)
-{
- static BOOL Initialized = FALSE;
- INITCOMMONCONTROLS_PROC InitProc;
-
- if (Initialized) return;
-
- hComCtl32Lib = LoadLibraryW(L"COMCTL32.DLL");
- if (hComCtl32Lib == NULL) return;
-
- InitProc = (INITCOMMONCONTROLS_PROC)GetProcAddress(hComCtl32Lib,
"InitCommonControls");
- if (InitProc == NULL) return;
-
- (*InitProc)();
-
- Initialized = TRUE;
-}
-
static DWORD WINAPI
EndNowThreadProc(LPVOID Parameter)
{
- PNOTIFY_CONTEXT NotifyContext = (PNOTIFY_CONTEXT) Parameter;
+ PNOTIFY_CONTEXT NotifyContext = (PNOTIFY_CONTEXT)Parameter;
MSG Msg;
- SetThreadDesktop(NotifyContext->Desktop);
- SwitchDesktop(NotifyContext->Desktop);
+ // SetThreadDesktop(NotifyContext->Desktop);
+ // SwitchDesktop(NotifyContext->Desktop);
CallInitCommonControls();
NotifyContext->Dlg = CreateDialogParam(UserServerDllInstance,
MAKEINTRESOURCE(IDD_END_NOW), NULL,
- EndNowDlgProc, (LPARAM) NotifyContext);
- if (NULL == NotifyContext->Dlg)
- {
+ EndNowDlgProc, (LPARAM)NotifyContext);
+ if (NotifyContext->Dlg == NULL)
return 0;
- }
+
ShowWindow(NotifyContext->Dlg, SW_SHOWNORMAL);
while (GetMessageW(&Msg, NULL, 0, 0))
{
- if (! IsDialogMessage(NotifyContext->Dlg, &Msg))
+ if (!IsDialogMessage(NotifyContext->Dlg, &Msg))
{
TranslateMessage(&Msg);
DispatchMessageW(&Msg);
@@ -230,70 +215,73 @@
}
static DWORD WINAPI
-SendQueryEndSession(LPVOID Parameter)
-{
- PMESSAGE_CONTEXT Context = (PMESSAGE_CONTEXT) Parameter;
+SendClientShutdown(LPVOID Parameter)
+{
+ PMESSAGE_CONTEXT Context = (PMESSAGE_CONTEXT)Parameter;
DWORD_PTR Result;
- if (SendMessageTimeoutW(Context->Wnd, WM_QUERYENDSESSION, Context->wParam,
- Context->lParam, SMTO_NORMAL, Context->Timeout,
- &Result))
- {
- return Result ? QUERY_RESULT_CONTINUE : QUERY_RESULT_ABORT;
- }
-
- return 0 == GetLastError() ? QUERY_RESULT_TIMEOUT : QUERY_RESULT_ERROR;
-}
-
-static DWORD WINAPI
-SendEndSession(LPVOID Parameter)
-{
- PMESSAGE_CONTEXT Context = (PMESSAGE_CONTEXT) Parameter;
- DWORD_PTR Result;
-
- if (Context->wParam)
- {
- if (SendMessageTimeoutW(Context->Wnd, WM_ENDSESSION, Context->wParam,
- Context->lParam, SMTO_NORMAL, Context->Timeout,
- &Result))
- {
- return QUERY_RESULT_CONTINUE;
- }
- return 0 == GetLastError() ? QUERY_RESULT_TIMEOUT : QUERY_RESULT_ERROR;
- }
- else
- {
- SendMessage(Context->Wnd, WM_ENDSESSION, Context->wParam,
- Context->lParam);
+ /* If the shutdown is aborted, just notify the process, there is no need to wait */
+ if ((Context->wParam & (MCS_QUERYENDSESSION | MCS_ENDSESSION)) == 0)
+ {
+ MY_DPRINT("Called WM_CLIENTSHUTDOWN with wParam == 0 ...\n");
+ SendNotifyMessageW(Context->Wnd, WM_CLIENTSHUTDOWN,
+ Context->wParam, Context->lParam);
return QUERY_RESULT_CONTINUE;
}
-}
-
-static BOOL CALLBACK
-NotifyTopLevelEnum(HWND Wnd, LPARAM lParam)
-{
- PNOTIFY_CONTEXT NotifyContext = (PNOTIFY_CONTEXT) lParam;
+
+ if (SendMessageTimeoutW(Context->Wnd, WM_CLIENTSHUTDOWN,
+ Context->wParam, Context->lParam,
+ SMTO_NORMAL, Context->Timeout, &Result))
+ {
+ DWORD Ret;
+
+ if (Context->wParam & MCS_QUERYENDSESSION)
+ {
+ /* WM_QUERYENDSESSION case */
+ switch (Result)
+ {
+ case MCSR_DONOTSHUTDOWN:
+ Ret = QUERY_RESULT_ABORT;
+ break;
+
+ case MCSR_GOODFORSHUTDOWN:
+ case MCSR_SHUTDOWNFINISHED:
+ default:
+ Ret = QUERY_RESULT_CONTINUE;
+ }
+ }
+ else
+ {
+ /* WM_ENDSESSION case */
+ Ret = QUERY_RESULT_CONTINUE;
+ }
+
+ MY_DPRINT("SendClientShutdown -- Return == %s\n",
+ Ret == QUERY_RESULT_CONTINUE ? "Continue" :
"Abort");
+ return Ret;
+ }
+
+ MY_DPRINT("SendClientShutdown -- Error == %s\n",
+ GetLastError() == 0 ? "Timeout" : "error");
+
+ return (GetLastError() == 0 ? QUERY_RESULT_TIMEOUT : QUERY_RESULT_ERROR);
+}
+
+static BOOL
+NotifyTopLevelWindow(HWND Wnd, PNOTIFY_CONTEXT NotifyContext)
+{
MESSAGE_CONTEXT MessageContext;
DWORD Now, Passed;
DWORD Timeout, WaitStatus;
- DWORD ProcessId;
HANDLE MessageThread;
HANDLE Threads[2];
- if (0 == GetWindowThreadProcessId(Wnd, &ProcessId))
- {
- NotifyContext->QueryResult = QUERY_RESULT_ERROR;
- return FALSE;
- }
-
- if (ProcessId != NotifyContext->ProcessId)
- goto Quit;
+ SetForegroundWindow(Wnd);
Now = GetTickCount();
- if (0 == NotifyContext->StartTime)
- {
+ if (NotifyContext->StartTime == 0)
NotifyContext->StartTime = Now;
- }
+
/*
* Note: Passed is computed correctly even when GetTickCount()
* wraps due to unsigned arithmetic.
@@ -304,16 +292,16 @@
MessageContext.wParam = NotifyContext->wParam;
MessageContext.lParam = NotifyContext->lParam;
MessageContext.Timeout = NotifyContext->ShutdownSettings->HungAppTimeout;
- if (! NotifyContext->ShutdownSettings->AutoEndTasks)
+ 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)
+ MessageThread = CreateThread(NULL, 0, SendClientShutdown,
+ (LPVOID)&MessageContext, 0, NULL);
+ if (MessageThread == NULL)
{
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
return FALSE;
@@ -331,30 +319,30 @@
if (WAIT_TIMEOUT == WaitStatus)
{
NotifyContext->WndClient = Wnd;
- if (NULL == NotifyContext->UIThread && NotifyContext->ShowUI)
+ if (NotifyContext->UIThread == NULL && NotifyContext->ShowUI)
{
NotifyContext->UIThread = CreateThread(NULL, 0,
EndNowThreadProc,
- (LPVOID) NotifyContext,
+ (LPVOID)NotifyContext,
0, NULL);
}
Threads[0] = MessageThread;
Threads[1] = NotifyContext->UIThread;
- WaitStatus = WaitForMultipleObjectsEx(NULL == NotifyContext->UIThread ?
+ WaitStatus = WaitForMultipleObjectsEx(NotifyContext->UIThread == NULL ?
1 : 2,
Threads, FALSE, INFINITE,
FALSE);
- if (WAIT_OBJECT_0 == WaitStatus)
- {
- if (! GetExitCodeThread(MessageThread,
&NotifyContext->QueryResult))
+ if (WaitStatus == WAIT_OBJECT_0)
+ {
+ if (!GetExitCodeThread(MessageThread,
&NotifyContext->QueryResult))
{
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
}
}
- else if (WAIT_OBJECT_0 + 1 == WaitStatus)
- {
- if (! GetExitCodeThread(NotifyContext->UIThread,
- &NotifyContext->QueryResult))
+ else if (WaitStatus == WAIT_OBJECT_0 + 1)
+ {
+ if (!GetExitCodeThread(NotifyContext->UIThread,
+ &NotifyContext->QueryResult))
{
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
}
@@ -363,15 +351,15 @@
{
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
}
- if (WAIT_OBJECT_0 != WaitStatus)
+ if (WaitStatus != WAIT_OBJECT_0)
{
TerminateThread(MessageThread, QUERY_RESULT_TIMEOUT);
}
}
- else if (WAIT_OBJECT_0 == WaitStatus)
- {
- if (! GetExitCodeThread(MessageThread,
- &NotifyContext->QueryResult))
+ else if (WaitStatus == WAIT_OBJECT_0)
+ {
+ if (!GetExitCodeThread(MessageThread,
+ &NotifyContext->QueryResult))
{
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
}
@@ -387,59 +375,16 @@
NotifyContext->QueryResult = QUERY_RESULT_TIMEOUT;
}
-Quit:
- DPRINT1("NotifyContext->QueryResult == %d\n",
NotifyContext->QueryResult);
+ MY_DPRINT("NotifyContext->QueryResult == %d\n",
NotifyContext->QueryResult);
return (NotifyContext->QueryResult == QUERY_RESULT_CONTINUE);
}
-static BOOL CALLBACK
-NotifyDesktopEnum(LPWSTR DesktopName, LPARAM lParam)
-{
- PNOTIFY_CONTEXT Context = (PNOTIFY_CONTEXT) lParam;
-
- Context->Desktop = OpenDesktopW(DesktopName, 0, FALSE,
- DESKTOP_ENUMERATE | DESKTOP_SWITCHDESKTOP);
- if (NULL == Context->Desktop)
- {
- DPRINT1("OpenDesktop failed with error %d\n", GetLastError());
- Context->QueryResult = QUERY_RESULT_ERROR;
- return FALSE;
- }
-
- Context->OldDesktop = GetThreadDesktop(GetCurrentThreadId());
- SwitchDesktop(Context->Desktop);
-
- EnumDesktopWindows(Context->Desktop, NotifyTopLevelEnum, lParam);
-
- SwitchDesktop(Context->OldDesktop);
-
- CloseDesktop(Context->Desktop);
-
- return QUERY_RESULT_CONTINUE == Context->QueryResult;
-}
-
-static BOOL FASTCALL
-NotifyTopLevelWindows(PNOTIFY_CONTEXT Context)
-{
- HWINSTA WindowStation;
-
- WindowStation = GetProcessWindowStation();
- if (NULL == WindowStation)
- {
- DPRINT1("GetProcessWindowStation failed with error %d\n",
GetLastError());
- return TRUE;
- }
-
- EnumDesktopsW(WindowStation, NotifyDesktopEnum, (LPARAM) Context);
-
- return TRUE;
-}
-
-static BOOL
-DtbgIsDesktopVisible(VOID)
-{
- return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE));
-}
+static BOOLEAN
+IsConsoleMode(VOID)
+{
+ return (BOOLEAN)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE);
+}
+
/* TODO: Find an other way to do it. */
#if 0
@@ -452,11 +397,10 @@
if (ProcessData->CtrlDispatcher)
{
-
Thread = CreateRemoteThread(ProcessData->ProcessHandle, NULL, 0,
(LPTHREAD_START_ROUTINE)
ProcessData->CtrlDispatcher,
UlongToPtr(Event), 0, NULL);
- if (NULL == Thread)
+ if (Thread == NULL)
{
DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
return;
@@ -468,296 +412,221 @@
#endif
/************************************************/
-BOOL FASTCALL
-NotifyAndTerminateProcess(PCSR_PROCESS ProcessData,
- PSHUTDOWN_SETTINGS ShutdownSettings,
- UINT Flags)
-{
- NOTIFY_CONTEXT Context;
- HANDLE Process;
+
+static BOOL CALLBACK
+FindTopLevelWnd(IN HWND hWnd,
+ IN LPARAM lParam)
+{
+ if (GetWindow(hWnd, GW_OWNER) == NULL)
+ {
+ *(HWND*)lParam = hWnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static VOID
+ThreadShutdownNotify(IN PCSR_THREAD CsrThread,
+ IN ULONG Flags,
+ IN ULONG Flags2,
+ IN PNOTIFY_CONTEXT Context)
+{
+ HWND TopWnd = NULL;
+
+ EnumThreadWindows(HandleToUlong(CsrThread->ClientId.UniqueThread),
+ FindTopLevelWnd, (LPARAM)&TopWnd);
+ if (TopWnd)
+ {
+ HWND hWndOwner;
+
+ /*** FOR TESTING PURPOSES ONLY!! ***/
+ HWND tmpWnd;
+ tmpWnd = TopWnd;
+ /***********************************/
+
+ while ((hWndOwner = GetWindow(TopWnd, GW_OWNER)) != NULL)
+ {
+ MY_DPRINT("GetWindow(TopWnd, GW_OWNER) not returned NULL...\n");
+ TopWnd = hWndOwner;
+ }
+ if (TopWnd != tmpWnd) MY_DPRINT("(TopWnd = %x) != (tmpWnd = %x)\n",
TopWnd, tmpWnd);
+ }
+ if (TopWnd == NULL)
+ return;
+
+ Context->wParam = Flags2;
+ Context->lParam = (0 != (Flags & EWX_CALLER_WINLOGON_LOGOFF) ?
+ ENDSESSION_LOGOFF : 0);
+
+ Context->StartTime = 0;
+ Context->UIThread = NULL;
+ Context->ShowUI = !IsConsoleMode() && (Flags2 & (MCS_QUERYENDSESSION |
MCS_ENDSESSION));
+ Context->Dlg = NULL;
+
+#if 0 // Obviously, switching desktops like that from within WINSRV doesn't work...
+ {
+ BOOL Success;
+ Context->OldDesktop = GetThreadDesktop(GetCurrentThreadId());
+ // Context->Desktop =
GetThreadDesktop(HandleToUlong(CsrThread->ClientId.UniqueThread));
+ Context->Desktop = GetThreadDesktop(GetWindowThreadProcessId(TopWnd, NULL));
+ MY_DPRINT("Last error = %d\n", GetLastError());
+ MY_DPRINT("Before switching to desktop 0x%x\n", Context->Desktop);
+ Success = SwitchDesktop(Context->Desktop);
+ MY_DPRINT("After switching to desktop (Success = %s ; last error = %d); going to
notify top-level...\n",
+ Success ? "TRUE" : "FALSE", GetLastError());
+ }
+#endif
+
+ NotifyTopLevelWindow(TopWnd, Context);
+
+/******************************************************************************/
+#if 1
+ if (Context->UIThread)
+ {
+ MY_DPRINT("Context->UIThread != NULL\n");
+ if (Context->Dlg)
+ {
+ MY_DPRINT("Sending WM_CLOSE because Dlg is != NULL\n");
+ SendMessageW(Context->Dlg, WM_CLOSE, 0, 0);
+ }
+ else
+ {
+ MY_DPRINT("Terminating UIThread thread with
QUERY_RESULT_ERROR\n");
+ TerminateThread(Context->UIThread, QUERY_RESULT_ERROR);
+ }
+ CloseHandle(Context->UIThread);
+ /**/Context->UIThread = NULL;/**/
+ /**/Context->Dlg = NULL;/**/
+ }
+#endif
+/******************************************************************************/
+
+#if 0
+ MY_DPRINT("Switch back to old desktop 0x%x\n", Context->OldDesktop);
+ SwitchDesktop(Context->OldDesktop);
+ MY_DPRINT("Switched back ok\n");
+#endif
+}
+
+static BOOL
+NotifyProcessForShutdown(PCSR_PROCESS CsrProcess,
+ PSHUTDOWN_SETTINGS ShutdownSettings,
+ UINT Flags)
+{
DWORD QueryResult = QUERY_RESULT_CONTINUE;
- Context.QueryResult = QUERY_RESULT_CONTINUE;
-
- if (0 == (Flags & EWX_FORCE))
- {
- // TODO: Find an other way whether or not the process has a console.
+ /* In case we make a forced shutdown, just kill the process */
+ if (Flags & EWX_FORCE)
+ return TRUE;
+
+ // TODO: Find an other way whether or not the process has a console.
#if 0
- if (NULL != ProcessData->Console)
- {
- ConioConsoleCtrlEventTimeout(CTRL_LOGOFF_EVENT, ProcessData,
- ShutdownSettings->WaitToKillAppTimeout);
- }
- else
+ if (CsrProcess->Console)
+ {
+ ConioConsoleCtrlEventTimeout(CTRL_LOGOFF_EVENT, CsrProcess,
+ ShutdownSettings->WaitToKillAppTimeout);
+ }
+ else
#endif
- {
- Context.ProcessId = (DWORD_PTR) ProcessData->ClientId.UniqueProcess;
- Context.wParam = 0;
- Context.lParam = (0 != (Flags & EWX_CALLER_WINLOGON_LOGOFF) ?
- ENDSESSION_LOGOFF : 0);
- Context.StartTime = 0;
- Context.UIThread = NULL;
- Context.ShowUI = DtbgIsDesktopVisible();
- Context.Dlg = NULL;
- Context.ShutdownSettings = ShutdownSettings;
- Context.SendMessageProc = SendQueryEndSession;
-
- NotifyTopLevelWindows(&Context);
-
- Context.wParam = (QUERY_RESULT_ABORT != Context.QueryResult);
- Context.lParam = (0 != (Flags & EWX_CALLER_WINLOGON_LOGOFF) ?
- ENDSESSION_LOGOFF : 0);
- Context.SendMessageProc = SendEndSession;
- Context.ShowUI = DtbgIsDesktopVisible() &&
- (QUERY_RESULT_ABORT != Context.QueryResult);
- QueryResult = Context.QueryResult;
+ {
+ PCSR_PROCESS Process;
+ PCSR_THREAD Thread;
+ PLIST_ENTRY NextEntry;
+
+ NOTIFY_CONTEXT Context;
+ Context.ShutdownSettings = ShutdownSettings;
+
+ /* Lock the process */
+ CsrLockProcessByClientId(CsrProcess->ClientId.UniqueProcess, &Process);
+
+ /* Send first the QUERYENDSESSION messages to all the threads of the process */
+ MY_DPRINT2("Sending the QUERYENDSESSION messages...\n");
+
+ NextEntry = CsrProcess->ThreadList.Flink;
+ while (NextEntry != &CsrProcess->ThreadList)
+ {
+ /* Get the current thread entry */
+ Thread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
+
+ /* Move to the next entry */
+ NextEntry = NextEntry->Flink;
+
+ /* If the thread is being terminated, just skip it */
+ if (Thread->Flags & CsrThreadTerminated) continue;
+
+ /* Reference the thread and temporarily unlock the process */
+ CsrReferenceThread(Thread);
+ CsrUnlockProcess(Process);
+
Context.QueryResult = QUERY_RESULT_CONTINUE;
-
- NotifyTopLevelWindows(&Context);
-
- if (NULL != Context.UIThread)
- {
- if (NULL != Context.Dlg)
- {
- SendMessageW(Context.Dlg, WM_CLOSE, 0, 0);
- }
- else
- {
- TerminateThread(Context.UIThread, QUERY_RESULT_ERROR);
- }
- CloseHandle(Context.UIThread);
- }
- }
-
- if (QUERY_RESULT_ABORT == QueryResult)
- {
- return FALSE;
- }
- }
-
- /* Terminate this process */
- Process = OpenProcess(PROCESS_TERMINATE, FALSE,
- (DWORD_PTR) ProcessData->ClientId.UniqueProcess);
- if (NULL == Process)
- {
- DPRINT1("Unable to open process %d, error %d\n",
ProcessData->ClientId.UniqueProcess,
- GetLastError());
- return TRUE;
- }
- TerminateProcess(Process, 0);
- CloseHandle(Process);
-
- return TRUE;
-}
+ ThreadShutdownNotify(Thread, Flags,
+ MCS_QUERYENDSESSION,
+ &Context);
+
+ /* Lock the process again and dereference the thread */
+ CsrLockProcessByClientId(CsrProcess->ClientId.UniqueProcess,
&Process);
+ CsrDereferenceThread(Thread);
+
+ // FIXME: Analyze Context.QueryResult !!
+ /**/if (Context.QueryResult == QUERY_RESULT_ABORT) goto Quit;/**/
+ }
+
+ QueryResult = Context.QueryResult;
+ MY_DPRINT2("QueryResult = %s\n",
+ QueryResult == QUERY_RESULT_ABORT ? "Abort" :
"Continue");
+
+ /* Now send the ENDSESSION messages to the threads */
+ MY_DPRINT2("Now sending the ENDSESSION messages...\n");
+
+ NextEntry = CsrProcess->ThreadList.Flink;
+ while (NextEntry != &CsrProcess->ThreadList)
+ {
+ /* Get the current thread entry */
+ Thread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
+
+ /* Move to the next entry */
+ NextEntry = NextEntry->Flink;
+
+ /* If the thread is being terminated, just skip it */
+ if (Thread->Flags & CsrThreadTerminated) continue;
+
+ /* Reference the thread and temporarily unlock the process */
+ CsrReferenceThread(Thread);
+ CsrUnlockProcess(Process);
+
+ Context.QueryResult = QUERY_RESULT_CONTINUE;
+ ThreadShutdownNotify(Thread, Flags,
+ (QUERY_RESULT_ABORT != QueryResult) ? MCS_ENDSESSION :
0,
+ &Context);
+
+ /* Lock the process again and dereference the thread */
+ CsrLockProcessByClientId(CsrProcess->ClientId.UniqueProcess,
&Process);
+ CsrDereferenceThread(Thread);
+ }
+
+Quit:
+ /* Unlock the process */
+ CsrUnlockProcess(Process);
#if 0
-static NTSTATUS WINAPI
-ExitReactosProcessEnum(PCSR_PROCESS ProcessData, PVOID Data)
-{
- HANDLE Process;
- HANDLE Token;
- TOKEN_ORIGIN Origin;
- DWORD ReturnLength;
- PPROCESS_ENUM_CONTEXT Context = (PPROCESS_ENUM_CONTEXT) Data;
- PCSR_PROCESS *NewData;
-
- /* Do not kill winlogon or csrss */
- if ((DWORD_PTR) ProcessData->ClientId.UniqueProcess == Context->CsrssProcess
||
- ProcessData->ClientId.UniqueProcess == LogonProcessId)
- {
- return STATUS_SUCCESS;
- }
-
- /* Get the login session of this process */
- Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
- (DWORD_PTR) ProcessData->ClientId.UniqueProcess);
- if (NULL == Process)
- {
- DPRINT1("Unable to open process %d, error %d\n",
ProcessData->ClientId.UniqueProcess,
- GetLastError());
- return STATUS_UNSUCCESSFUL;
- }
-
- if (! OpenProcessToken(Process, TOKEN_QUERY, &Token))
- {
- DPRINT1("Unable to open token for process %d, error %d\n",
- ProcessData->ClientId.UniqueProcess, GetLastError());
- CloseHandle(Process);
- return STATUS_UNSUCCESSFUL;
- }
- CloseHandle(Process);
-
- if (! GetTokenInformation(Token, TokenOrigin, &Origin,
- sizeof(TOKEN_ORIGIN), &ReturnLength))
- {
- DPRINT1("GetTokenInformation failed for process %d with error %d\n",
- ProcessData->ClientId.UniqueProcess, GetLastError());
- CloseHandle(Token);
- return STATUS_UNSUCCESSFUL;
- }
- CloseHandle(Token);
-
- /* This process will be killed if it's in the correct logon session */
- if (RtlEqualLuid(&(Context->TokenOrigin.OriginatingLogonSession),
- &(Origin.OriginatingLogonSession)))
- {
- /* Kill the shell process last */
- if ((DWORD_PTR) ProcessData->ClientId.UniqueProcess ==
Context->ShellProcess)
- {
- ProcessData->ShutdownLevel = 0;
- }
- NewData = HeapAlloc(UserServerHeap, 0, (Context->ProcessCount + 1)
- * sizeof(PCSR_PROCESS));
- if (NULL == NewData)
- {
- return STATUS_NO_MEMORY;
- }
- if (0 != Context->ProcessCount)
- {
- memcpy(NewData, Context->ProcessData,
- Context->ProcessCount * sizeof(PCSR_PROCESS));
- HeapFree(UserServerHeap, 0, Context->ProcessData);
- }
- Context->ProcessData = NewData;
- Context->ProcessData[Context->ProcessCount] = ProcessData;
- Context->ProcessCount++;
- }
-
- return STATUS_SUCCESS;
-}
+ if (Context.UIThread)
+ {
+ if (Context.Dlg)
+ {
+ SendMessageW(Context.Dlg, WM_CLOSE, 0, 0);
+ }
+ else
+ {
+ TerminateThread(Context.UIThread, QUERY_RESULT_ERROR);
+ }
+ CloseHandle(Context.UIThread);
+ }
#endif
-
-#if 0
-static DWORD FASTCALL
-GetShutdownSettings(HKEY DesktopKey, LPCWSTR ValueName, DWORD DefaultValue)
-{
- BYTE ValueBuffer[16];
- LONG ErrCode;
- DWORD Type;
- DWORD ValueSize;
- UNICODE_STRING StringValue;
- ULONG Value;
-
- ValueSize = sizeof(ValueBuffer);
- ErrCode = RegQueryValueExW(DesktopKey, ValueName, NULL, &Type, ValueBuffer,
- &ValueSize);
- if (ERROR_SUCCESS != ErrCode)
- {
- DPRINT("GetShutdownSettings for %S failed with error code %ld\n",
- ValueName, ErrCode);
- return DefaultValue;
- }
-
- if (REG_SZ == Type)
- {
- RtlInitUnicodeString(&StringValue, (LPCWSTR) ValueBuffer);
- if (! NT_SUCCESS(RtlUnicodeStringToInteger(&StringValue, 10, &Value)))
- {
- DPRINT1("Unable to convert value %S for setting %S\n",
- StringValue.Buffer, ValueName);
- return DefaultValue;
- }
- return (DWORD) Value;
- }
- else if (REG_DWORD == Type)
- {
- return *((DWORD *) ValueBuffer);
- }
-
- DPRINT1("Unexpected registry type %d for setting %S\n", Type, ValueName);
- return DefaultValue;
-}
-
-static VOID FASTCALL
-LoadShutdownSettings(PSID Sid, PSHUTDOWN_SETTINGS ShutdownSettings)
-{
- static WCHAR Subkey[] = L"\\Control Panel\\Desktop";
- LPWSTR StringSid;
- WCHAR InitialKeyName[128];
- LPWSTR KeyName;
- HKEY DesktopKey;
- LONG ErrCode;
-
- ShutdownSettings->AutoEndTasks = DEFAULT_AUTO_END_TASKS;
- ShutdownSettings->HungAppTimeout = DEFAULT_HUNG_APP_TIMEOUT;
- ShutdownSettings->WaitToKillAppTimeout = DEFAULT_WAIT_TO_KILL_APP_TIMEOUT;
-
- if (! ConvertSidToStringSidW(Sid, &StringSid))
- {
- DPRINT1("ConvertSidToStringSid failed with error %d, using default shutdown
settings\n",
- GetLastError());
- return;
- }
- if (wcslen(StringSid) + wcslen(Subkey) + 1 <=
- sizeof(InitialKeyName) / sizeof(WCHAR))
- {
- KeyName = InitialKeyName;
- }
- else
- {
- KeyName = HeapAlloc(UserServerHeap, 0,
- (wcslen(StringSid) + wcslen(Subkey) + 1) *
- sizeof(WCHAR));
- if (NULL == KeyName)
- {
- DPRINT1("Failed to allocate memory, using default shutdown
settings\n");
- LocalFree(StringSid);
- return;
- }
- }
- wcscat(wcscpy(KeyName, StringSid), Subkey);
- LocalFree(StringSid);
-
- ErrCode = RegOpenKeyExW(HKEY_USERS, KeyName, 0, KEY_QUERY_VALUE, &DesktopKey);
- if (KeyName != InitialKeyName)
- {
- HeapFree(UserServerHeap, 0, KeyName);
- }
- if (ERROR_SUCCESS != ErrCode)
- {
- DPRINT1("RegOpenKeyEx failed with error %ld, using default shutdown
settings\n", ErrCode);
- return;
- }
-
- ShutdownSettings->AutoEndTasks = (BOOL) GetShutdownSettings(DesktopKey,
L"AutoEndTasks",
- (DWORD) DEFAULT_AUTO_END_TASKS);
- ShutdownSettings->HungAppTimeout = GetShutdownSettings(DesktopKey,
- L"HungAppTimeout",
- DEFAULT_HUNG_APP_TIMEOUT);
- ShutdownSettings->WaitToKillAppTimeout = GetShutdownSettings(DesktopKey,
- L"WaitToKillAppTimeout",
- DEFAULT_WAIT_TO_KILL_APP_TIMEOUT);
-
- RegCloseKey(DesktopKey);
-}
-
-NTSTATUS FASTCALL
-InternalExitReactos(DWORD ProcessId, DWORD ThreadId, UINT Flags)
-{
- // PROCESS_ENUM_CONTEXT Context;
- HWND ShellWnd;
- char FixedUserInfo[64];
- TOKEN_USER *UserInfo;
- SHUTDOWN_SETTINGS ShutdownSettings;
-
- 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;
-}
-#endif
+ }
+
+ /* Kill the process unless we abort shutdown */
+ return (QueryResult != QUERY_RESULT_ABORT);
+}
static NTSTATUS FASTCALL
UserExitReactos(PCSR_THREAD CsrThread, UINT Flags)
@@ -893,7 +762,7 @@
* Check for process validity
*/
- /* Do not kill WinLogon or CSRSS */
+ /* Do not kill Winlogon or CSRSS */
if (CsrProcess->ClientId.UniqueProcess == NtCurrentProcess() ||
CsrProcess->ClientId.UniqueProcess == UlongToHandle(LogonProcessId))
{
@@ -909,14 +778,25 @@
else
DPRINT1("Killing process with ShutdownFlags = %lu\n",
CsrProcess->ShutdownFlags);
-#if 0
- if (!NotifyAndTerminateProcess(CsrProcess, &ShutdownSettings, Flags))
- {
+ if (CsrProcess->ShutdownFlags & SHUTDOWN_OTHERCONTEXT)
+ DPRINT1("This process has SHUTDOWN_OTHERCONTEXT\n");
+
+ if (CsrProcess->ShutdownFlags & SHUTDOWN_SYSTEMCONTEXT)
+ DPRINT1("This process has SHUTDOWN_SYSTEMCONTEXT\n");
+
+ /* Notify the process for shutdown if needed */
+ if (!NotifyProcessForShutdown(CsrProcess, &ShutdownSettings, Flags))
+ {
+ /* Abort shutdown */
return CsrShutdownCancelled;
}
-#endif
-
- return CsrShutdownNonCsrProcess;
+
+ /* Terminate this process */
+ NtTerminateProcess(CsrProcess->ProcessHandle, 0);
+
+ /* We are done */
+ CsrDereferenceProcess(CsrProcess);
+ return CsrShutdownCsrProcess;
}
@@ -965,16 +845,10 @@
return STATUS_SUCCESS;
}
-CSR_API(SrvLogon)
+CSR_API(SrvRecordShutdownReason)
{
DPRINT1("%s not yet implemented\n", __FUNCTION__);
return STATUS_NOT_IMPLEMENTED;
}
-CSR_API(SrvRecordShutdownReason)
-{
- DPRINT1("%s not yet implemented\n", __FUNCTION__);
- return STATUS_NOT_IMPLEMENTED;
-}
-
/* EOF */
Modified: trunk/reactos/win32ss/user/winsrv/winsrv.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/winsrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/winsrv.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/winsrv.h [iso-8859-1] Sun Feb 15 22:57:40 2015
@@ -20,6 +20,7 @@
#include <windef.h>
#include <winbase.h>
#include <wingdi.h>
+#include <winreg.h>
#include <winuser.h>
#include <imm.h>
@@ -42,4 +43,18 @@
/* CSRSS Header */
#include <csr/csrsrv.h>
+typedef struct tagSHUTDOWN_SETTINGS
+{
+ BOOL AutoEndTasks;
+ ULONG HungAppTimeout;
+ ULONG WaitToKillAppTimeout;
+ ULONG WaitToKillServiceTimeout;
+ ULONG ProcessTerminateTimeout;
+} SHUTDOWN_SETTINGS, *PSHUTDOWN_SETTINGS;
+
+extern SHUTDOWN_SETTINGS ShutdownSettings;
+
+VOID FASTCALL
+GetTimeouts(IN PSHUTDOWN_SETTINGS ShutdownSettings);
+
#endif /* __WINSRV_H__ */