Author: hpoussin
Date: Sun Aug 6 19:47:04 2006
New Revision: 23501
URL:
http://svn.reactos.org/svn/reactos?rev=23501&view=rev
Log:
Cleanup shutdown code path. Now, the user can logoff and logon again.
Modified:
trunk/reactos/base/system/winlogon/sas.c
trunk/reactos/base/system/winlogon/wlx.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 (original)
+++ trunk/reactos/base/system/winlogon/sas.c Sun Aug 6 19:47:04 2006
@@ -149,7 +149,10 @@
Session->Gina.Functions.WlxDisplaySASNotice(Session->Gina.Context);
}
if (WLX_SHUTTINGDOWN(wlxAction))
+ {
+ Session->Gina.Functions.WlxShutdown(Session->Gina.Context, wlxAction);
HandleShutdown(Session, wlxAction);
+ }
break;
case WLX_SAS_ACTION_TASKLIST: /* 0x07 */
SwitchDesktop(WLSession->ApplicationDesktop);
@@ -256,128 +259,164 @@
static DWORD WINAPI
LogoffShutdownThread(LPVOID Parameter)
{
- PLOGOFF_SHUTDOWN_DATA LSData = (PLOGOFF_SHUTDOWN_DATA) Parameter;
-
- if (! ImpersonateLoggedOnUser(LSData->Session->UserToken))
- {
- DPRINT1("ImpersonateLoggedOnUser failed with error %d\n", GetLastError());
- return 0;
- }
- 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))
- {
- DPRINT1("Unable to kill user apps, error %d\n", GetLastError());
- RevertToSelf();
- return 0;
- }
- RevertToSelf();
-
- /* This is not right (see top of reactos/dll/win32/user32/misc/exit.c),
- * but this should be enough atm */
- switch (LSData->Flags & EWX_ACTION_MASK)
- {
- case EWX_SHUTDOWN:
- NtShutdownSystem(ShutdownNoReboot);
- break;
- case EWX_REBOOT:
- NtShutdownSystem(ShutdownReboot);
- break;
- default:
- UNIMPLEMENTED;
- }
-
- HeapFree(GetProcessHeap(), 0, LSData);
-
- return 1;
+ PLOGOFF_SHUTDOWN_DATA LSData = (PLOGOFF_SHUTDOWN_DATA) Parameter;
+
+ if (!ImpersonateLoggedOnUser(LSData->Session->UserToken))
+ {
+ ERR("ImpersonateLoggedOnUser failed with error %lu\n", GetLastError());
+ return 0;
+ }
+
+ /* 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))
+ {
+ ERR("Unable to kill user apps, error %lu\n", GetLastError());
+ RevertToSelf();
+ return 0;
+ }
+
+ /* FIXME: Call ExitWindowsEx() to terminate COM processes */
+
+ RevertToSelf();
+
+ return 1;
+}
+
+static NTSTATUS
+CheckPrivilegeForRequestedAction(
+ IN UINT Action,
+ IN DWORD RequestingProcessId)
+{
+ HANDLE Process;
+ HANDLE Token;
+ BOOL CheckResult;
+ PPRIVILEGE_SET PrivSet;
+
+ TRACE("CheckPrivilegeForRequestedAction(%u)\n", Action);
+
+ if (Action == EWX_LOGOFF)
+ /* No privilege needed to log off */
+ return STATUS_SUCCESS;
+
+ /* Check for invalid arguments */
+ if (Action != EWX_SHUTDOWN && Action != EWX_REBOOT && Action !=
EWX_POWEROFF)
+ {
+ ERR("Invalid exit action %u\n", Action);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, RequestingProcessId);
+ if (!Process)
+ {
+ WARN("OpenProcess() failed with error %lu\n", GetLastError());
+ return STATUS_INVALID_HANDLE;
+ }
+ if (!OpenProcessToken(Process, TOKEN_QUERY, &Token))
+ {
+ WARN("OpenProcessToken() failed with error %lu\n", GetLastError());
+ CloseHandle(Process);
+ return STATUS_INVALID_HANDLE;
+ }
+ CloseHandle(Process);
+ PrivSet = HeapAlloc(GetProcessHeap(), 0, sizeof(PRIVILEGE_SET) +
sizeof(LUID_AND_ATTRIBUTES));
+ if (!PrivSet)
+ {
+ ERR("Failed to allocate mem for privilege set\n");
+ CloseHandle(Token);
+ return STATUS_NO_MEMORY;
+ }
+ PrivSet->PrivilegeCount = 1;
+ PrivSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
+ if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &PrivSet->Privilege[0].Luid))
+ {
+ WARN("LookupPrivilegeValue() failed with error %lu\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, PrivSet);
+ CloseHandle(Token);
+ return STATUS_UNSUCCESSFUL;
+ }
+ if (!PrivilegeCheck(Token, PrivSet, &CheckResult))
+ {
+ WARN("PrivilegeCheck() failed with error %lu\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, PrivSet);
+ CloseHandle(Token);
+ return STATUS_ACCESS_DENIED;
+ }
+ HeapFree(GetProcessHeap(), 0, PrivSet);
+ CloseHandle(Token);
+
+ if (!CheckResult)
+ {
+ WARN("SE_SHUTDOWN privilege not enabled\n");
+ return STATUS_ACCESS_DENIED;
+ }
}
static LRESULT
-HandleExitWindows(PWLSESSION Session, DWORD RequestingProcessId, UINT Flags)
-{
- UINT Action;
- HANDLE Process;
- HANDLE Token;
- HANDLE Thread;
- BOOL CheckResult;
- PPRIVILEGE_SET PrivSet;
- PLOGOFF_SHUTDOWN_DATA LSData;
-
- /* Check parameters */
- Action = Flags & EWX_ACTION_MASK;
- if (EWX_LOGOFF != Action && EWX_SHUTDOWN != Action && EWX_REBOOT !=
Action
- && EWX_POWEROFF != Action)
- {
- DPRINT1("Invalid ExitWindows action 0x%x\n", Action);
- return STATUS_INVALID_PARAMETER;
- }
-
- /* Check privilege */
- if (EWX_LOGOFF != Action)
- {
- Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, RequestingProcessId);
- if (NULL == Process)
- {
- DPRINT1("OpenProcess failed with error %d\n", GetLastError());
- return STATUS_INVALID_HANDLE;
- }
- if (! OpenProcessToken(Process, TOKEN_QUERY, &Token))
- {
- DPRINT1("OpenProcessToken failed with error %d\n", GetLastError());
- CloseHandle(Process);
- return STATUS_INVALID_HANDLE;
- }
- CloseHandle(Process);
- PrivSet = HeapAlloc(GetProcessHeap(), 0, sizeof(PRIVILEGE_SET) +
sizeof(LUID_AND_ATTRIBUTES));
- if (NULL == PrivSet)
- {
- DPRINT1("Failed to allocate mem for privilege set\n");
- CloseHandle(Token);
- return STATUS_NO_MEMORY;
- }
- PrivSet->PrivilegeCount = 1;
- PrivSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
- if (! LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
&PrivSet->Privilege[0].Luid))
- {
- DPRINT1("LookupPrivilegeValue failed with error %d\n", GetLastError());
- HeapFree(GetProcessHeap(), 0, PrivSet);
- CloseHandle(Token);
- return STATUS_UNSUCCESSFUL;
- }
- if (! PrivilegeCheck(Token, PrivSet, &CheckResult))
- {
- DPRINT1("PrivilegeCheck failed with error %d\n", GetLastError());
- HeapFree(GetProcessHeap(), 0, PrivSet);
- CloseHandle(Token);
- return STATUS_ACCESS_DENIED;
- }
- HeapFree(GetProcessHeap(), 0, PrivSet);
- CloseHandle(Token);
- if (! CheckResult)
- {
- DPRINT1("SE_SHUTDOWN privilege not enabled\n");
- return STATUS_ACCESS_DENIED;
- }
- }
-
- LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA));
- if (NULL == LSData)
- {
- DPRINT1("Failed to allocate mem for thread data\n");
- return STATUS_NO_MEMORY;
- }
- LSData->Flags = Flags;
- LSData->Session = Session;
- Thread = CreateThread(NULL, 0, LogoffShutdownThread, (LPVOID) LSData, 0, NULL);
- if (NULL == Thread)
- {
- DPRINT1("Unable to create shutdown thread, error %d\n", GetLastError());
- HeapFree(GetProcessHeap(), 0, LSData);
- return STATUS_UNSUCCESSFUL;
- }
- CloseHandle(Thread);
-
- return 1;
+HandleExitWindows(
+ IN OUT PWLSESSION Session,
+ IN DWORD RequestingProcessId,
+ IN UINT Flags)
+{
+ UINT Action;
+ PLOGOFF_SHUTDOWN_DATA LSData;
+ HANDLE hThread;
+ NTSTATUS Status;
+
+ /* Check parameters */
+ Action = Flags & EWX_ACTION_MASK;
+ if (Action != EWX_LOGOFF &&
+ Action != EWX_SHUTDOWN &&
+ Action != EWX_REBOOT &&
+ Action != EWX_POWEROFF)
+ {
+ ERR("Invalid ExitWindows action 0x%x\n", Action);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Check privilege */
+ Status = CheckPrivilegeForRequestedAction(Action, RequestingProcessId);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Prepare data for logoff/shutdown thread */
+ LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA));
+ if (!LSData)
+ {
+ ERR("Failed to allocate mem for thread data\n");
+ return STATUS_NO_MEMORY;
+ }
+ LSData->Flags = Flags;
+ LSData->Session = Session;
+
+ /* Run logoff/shutdown thread */
+ hThread = CreateThread(NULL, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL);
+ if (!hThread)
+ {
+ ERR("Unable to create shutdown thread, error %lu\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, LSData);
+ return STATUS_UNSUCCESSFUL;
+ }
+ WaitForSingleObject(hThread, INFINITE);
+ CloseHandle(hThread);
+ HeapFree(GetProcessHeap(), 0, LSData);
+
+ Session->LogonStatus = WKSTA_IS_LOGGED_OFF;
+ if (Action == EWX_LOGOFF)
+ {
+ DispatchSAS(Session, WLX_SAS_TYPE_TIMEOUT);
+ return 1;
+ }
+
+ /* Handle shutdown */
+ FIXME("FIXME: Call ExitWindowEx in SYSTEM process context\n");
+
+ FIXME("FIXME: Call SMSS API #1\n");
+ NtShutdownSystem(ShutdownNoReboot); /* FIXME: should go in smss */
+
+ return 1;
}
static LRESULT CALLBACK
Modified: trunk/reactos/base/system/winlogon/wlx.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/winlogon/wlx.c…
==============================================================================
--- trunk/reactos/base/system/winlogon/wlx.c (original)
+++ trunk/reactos/base/system/winlogon/wlx.c Sun Aug 6 19:47:04 2006
@@ -57,6 +57,9 @@
HANDLE hWlx)
{
ULONG_PTR OldValue;
+
+ TRACE("WlxUseCtrlAltDel()\n");
+
WlxSetOption(hWlx, WLX_OPTION_USE_CTRL_ALT_DEL, TRUE, &OldValue);
}
@@ -69,6 +72,9 @@
PVOID pWlxContext)
{
ULONG_PTR OldValue;
+
+ TRACE("WlxSetContextPointer(%p)\n", pWlxContext);
+
WlxSetOption(hWlx, WLX_OPTION_CONTEXT_POINTER, (ULONG_PTR)pWlxContext, &OldValue);
}
@@ -80,6 +86,7 @@
HANDLE hWlx,
DWORD dwSasType)
{
+ TRACE("WlxSasNotify(0x%lx)\n", dwSasType);
DispatchSAS((PWLSESSION)hWlx, dwSasType);
}
@@ -92,6 +99,9 @@
DWORD Timeout)
{
PWLSESSION Session = (PWLSESSION)hWlx;
+
+ TRACE("WlxSetTimeout(%lu)\n", Timeout);
+
Session->DialogTimeout = Timeout;
return TRUE;
}
@@ -121,6 +131,7 @@
LPWSTR lpszTitle,
UINT fuStyle)
{
+ TRACE("WlxMessageBox()\n");
/* FIXME: Provide a custom window proc to be able to handle timeout */
return MessageBoxW(hwndOwner, lpszText, lpszTitle, fuStyle);
}
@@ -136,6 +147,8 @@
HWND hwndOwner,
DLGPROC dlgprc)
{
+ TRACE("WlxDialogBox()\n");
+
if (PreviousWindowProc != NULL)
return -1;
PreviousWindowProc = dlgprc;
@@ -154,6 +167,8 @@
DLGPROC dlgprc,
LPARAM dwInitParam)
{
+ TRACE("WlxDialogBoxParam()\n");
+
if (PreviousWindowProc != NULL)
return -1;
PreviousWindowProc = dlgprc;
@@ -171,6 +186,8 @@
HWND hwndOwner,
DLGPROC dlgprc)
{
+ TRACE("WlxDialogBoxIndirect()\n");
+
if (PreviousWindowProc != NULL)
return -1;
PreviousWindowProc = dlgprc;
@@ -189,6 +206,8 @@
DLGPROC dlgprc,
LPARAM dwInitParam)
{
+ TRACE("WlxDialogBoxIndirectParam()\n");
+
if (PreviousWindowProc != NULL)
return -1;
PreviousWindowProc = dlgprc;
@@ -203,6 +222,9 @@
HANDLE hWlx)
{
PWLSESSION Session = (PWLSESSION)hWlx;
+
+ TRACE("WlxSwitchDesktopToUser()\n");
+
return (int)SwitchDesktop(Session->ApplicationDesktop);
}
@@ -214,6 +236,9 @@
HANDLE hWlx)
{
PWLSESSION Session = (PWLSESSION)hWlx;
+
+ TRACE("WlxSwitchDesktopToWinlogon()\n");
+
return (int)SwitchDesktop(Session->WinlogonDesktop);
}
@@ -308,6 +333,8 @@
ULONG_PTR* OldValue)
{
PWLSESSION Session = (PWLSESSION)hWlx;
+
+ TRACE("WlxSetOption(%lu)\n", Option);
switch (Option)
{
@@ -337,6 +364,8 @@
ULONG_PTR* Value)
{
PWLSESSION Session = (PWLSESSION)hWlx;
+
+ TRACE("WlxGetOption(%lu)\n", Option);
switch (Option)
{
@@ -460,7 +489,7 @@
return FALSE;
}
-static const
+static
WLX_DISPATCH_VERSION_1_4 FunctionTable = {
WlxUseCtrlAltDel,
WlxSetContextPointer,
@@ -559,8 +588,15 @@
/* Assume current version */
*DllVersion = WLX_CURRENT_VERSION;
}
- else if (!Functions->WlxNegotiate(WLX_CURRENT_VERSION, DllVersion))
- goto cleanup;
+ else
+ {
+ TRACE("About to negociate with Gina %S. Winlogon uses version %lx\n",
+ GinaDll, WLX_CURRENT_VERSION);
+ if (!Functions->WlxNegotiate(WLX_CURRENT_VERSION, DllVersion))
+ goto cleanup;
+ }
+
+ TRACE("Gina uses WLX_VERSION %lx\n", *DllVersion);
if (*DllVersion >= WLX_VERSION_1_0)
{