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) {