942 lines
31 KiB
C++
942 lines
31 KiB
C++
// --------------------------------------------------------------------------
|
|
// Module Name: Exports.cpp
|
|
//
|
|
// Copyright (c) 2000, Microsoft Corporation
|
|
//
|
|
// C header file that contains function prototypes that are to be exported
|
|
// from msgina.dll
|
|
//
|
|
// History: 2000-02-04 vtan created
|
|
// 2000-02-28 vtan added ShellIsFriendlyUIActive
|
|
// 2000-02-29 vtan added ShellIsSingleUserNoPassword
|
|
// 2000-03-02 vtan added ShellIsMultipleUsersEnabled
|
|
// 2000-04-27 vtan added ShellTurnOffDialog
|
|
// 2000-04-27 vtan added ShellACPIPowerButtonPressed
|
|
// 2000-05-03 vtan added ShellStatusHostBegin
|
|
// 2000-05-03 vtan added ShellStatusHostEnd
|
|
// 2000-05-04 vtan added ShellSwitchWhenInteractiveReady
|
|
// 2000-05-18 vtan added ShellDimScreen
|
|
// 2000-06-02 vtan added ShellInstallAccountFilterData
|
|
// 2000-07-14 vtan added ShellStatusHostShuttingDown
|
|
// 2000-07-27 vtan added ShellIsSuspendAllowed
|
|
// 2000-07-28 vtan added ShellEnableMultipleUsers
|
|
// 2000-07-28 vtan added ShellEnableRemoteConnections
|
|
// 2000-08-01 vtan added ShellEnableFriendlyUI
|
|
// 2000-08-01 vtan added ShellIsRemoteConnectionsEnabled
|
|
// 2000-08-03 vtan added ShellSwitchUser
|
|
// 2000-08-09 vtan added ShellNotifyThemeUserChange
|
|
// 2000-08-14 vtan added ShellIsUserInteractiveLogonAllowed
|
|
// 2000-10-13 vtan added ShellStartThemeServer
|
|
// 2000-10-17 vtan added ShellStopThemeServer
|
|
// 2000-11-30 vtan removed ShellStartThemeServer
|
|
// 2000-11-30 vtan removed ShellStopThemeServer
|
|
// 2001-01-11 vtan renamed functions to _Shell
|
|
// 2001-01-11 vtan added ShellReturnToWelcome
|
|
// 2001-01-31 vtan added ShellStatusHostPowerEvent
|
|
// 2001-04-03 vtan added ShellStartCredentialServer
|
|
// 2001-04-04 vtan added ShellAcquireLogonMutex
|
|
// 2001-04-04 vtan added ShellReleaseLogonMutex
|
|
// 2001-04-12 vtan added ShellStatusHostHide
|
|
// 2001-04-12 vtan added ShellStatusHostShow
|
|
// --------------------------------------------------------------------------
|
|
|
|
#include "StandardHeader.h"
|
|
|
|
#include <msginaexports.h>
|
|
#include <shlobj.h>
|
|
#include <shlobjp.h>
|
|
#include <winsta.h>
|
|
#include <winwlx.h>
|
|
#include <LPCThemes.h>
|
|
|
|
#include "Compatibility.h"
|
|
#include "CredentialTransfer.h"
|
|
#include "DimmedWindow.h"
|
|
#include "LogonMutex.h"
|
|
#include "PowerButton.h"
|
|
#include "PrivilegeEnable.h"
|
|
#include "ReturnToWelcome.h"
|
|
#include "SpecialAccounts.h"
|
|
#include "StatusCode.h"
|
|
#include "SystemSettings.h"
|
|
#include "TokenInformation.h"
|
|
#include "TurnOffDialog.h"
|
|
#include "UserList.h"
|
|
#include "UserSettings.h"
|
|
#include "WaitInteractiveReady.h"
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellGetUserList
|
|
//
|
|
// Arguments: fRemoveGuest = Always remove the "Guest" account.
|
|
// pdwReturnEntryCount = Returned number of entries. This
|
|
// may be NULL.
|
|
// pvBuffer = Buffer containing user data. This
|
|
// may be NULL.
|
|
//
|
|
// Returns: LONG
|
|
//
|
|
// Purpose: Gets the count of valid users and the user list on this
|
|
// system. This calls a static member function so that the
|
|
// context doesn't need to be supplied. This allows shgina (the
|
|
// logonocx) to call this function as a stand-alone function.
|
|
//
|
|
// History: 1999-10-15 vtan created
|
|
// 2000-01-31 vtan moved from Neptune to Whistler
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C LONG _ShellGetUserList(BOOL fRemoveGuest, DWORD *pdwUserCount, void* *pUserList)
|
|
|
|
{
|
|
return(CUserList::Get((fRemoveGuest != FALSE), pdwUserCount, reinterpret_cast<GINA_USER_INFORMATION**>(pUserList)));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellIsSingleUserNoPassword
|
|
//
|
|
// Arguments: pszUsername = Name of single user with no password.
|
|
// pszDomain = Domain for the user.
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
// Purpose: Returns whether this system is using friendly UI and has a
|
|
// single user with no password. If there is a single user with
|
|
// no password the login name is returned otherwise the parameter
|
|
// is unused.
|
|
//
|
|
// History: 2000-02-29 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _ShellIsSingleUserNoPassword (WCHAR *pwszUsername, WCHAR *pwszDomain)
|
|
|
|
{
|
|
BOOL fResult;
|
|
|
|
fResult = FALSE;
|
|
if (CSystemSettings::IsFriendlyUIActive())
|
|
{
|
|
DWORD dwReturnedEntryCount;
|
|
GINA_USER_INFORMATION *pUserList;
|
|
|
|
if (ERROR_SUCCESS == CUserList::Get(true, &dwReturnedEntryCount, &pUserList))
|
|
{
|
|
if (dwReturnedEntryCount == 1)
|
|
{
|
|
HANDLE hToken;
|
|
|
|
if (CTokenInformation::LogonUser(pUserList->pszName,
|
|
pUserList->pszDomain,
|
|
L"",
|
|
&hToken) == ERROR_SUCCESS)
|
|
{
|
|
fResult = TRUE;
|
|
if (pwszUsername != NULL)
|
|
{
|
|
(WCHAR*)lstrcpyW(pwszUsername, pUserList->pszName);
|
|
}
|
|
if (pwszDomain != NULL)
|
|
{
|
|
(WCHAR*)lstrcpyW(pwszDomain, pUserList->pszDomain);
|
|
}
|
|
if (hToken != NULL)
|
|
{
|
|
TBOOL(CloseHandle(hToken));
|
|
}
|
|
}
|
|
}
|
|
(HLOCAL)LocalFree(pUserList);
|
|
}
|
|
}
|
|
return(fResult);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellIsFriendlyUIActive
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
// Purpose: Returns whether the friendly UI is active.
|
|
//
|
|
// History: 2000-02-28 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _ShellIsFriendlyUIActive (void)
|
|
|
|
{
|
|
return(CSystemSettings::IsFriendlyUIActive());
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellIsMultipleUsersEnabled
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
// Purpose: Returns whether multiple users is enabled. This includes
|
|
// checking a registry key as well as whether terminal services
|
|
// is enabled on this machine.
|
|
//
|
|
// History: 2000-03-02 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _ShellIsMultipleUsersEnabled (void)
|
|
|
|
{
|
|
return(CSystemSettings::IsMultipleUsersEnabled());
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellIsRemoteConnectionsEnabled
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
// Purpose: Returns whether remote connections are enabled. This includes
|
|
// checking a registry key as well as whether terminal services
|
|
// is enabled on this machine.
|
|
//
|
|
// History: 2000-08-01 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _ShellIsRemoteConnectionsEnabled (void)
|
|
|
|
{
|
|
return(CSystemSettings::IsRemoteConnectionsEnabled());
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellEnableFriendlyUI
|
|
//
|
|
// Arguments: fEnable = Enable or disable friendly UI.
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
// Purpose: Enables or disables friendly UI via the CSystemSettings
|
|
// implementaion.
|
|
//
|
|
// History: 2000-08-01 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _ShellEnableFriendlyUI (BOOL fEnable)
|
|
|
|
{
|
|
return(CSystemSettings::EnableFriendlyUI(fEnable != FALSE));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellEnableMultipleUsers
|
|
//
|
|
// Arguments: fEnable = Enable or disable multiple users.
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
// Purpose: Enables or disables multiple users via the CSystemSettings
|
|
// implementaion.
|
|
//
|
|
// History: 2000-07-28 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _ShellEnableMultipleUsers (BOOL fEnable)
|
|
|
|
{
|
|
return(CSystemSettings::EnableMultipleUsers(fEnable != FALSE));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellEnableRemoteConnections
|
|
//
|
|
// Arguments: fEnable = Enable or disable remote connections.
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
// Purpose: Enables or disables remote connections via the CSystemSettings
|
|
// implementaion.
|
|
//
|
|
// History: 2000-07-28 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _ShellEnableRemoteConnections (BOOL fEnable)
|
|
|
|
{
|
|
return(CSystemSettings::EnableRemoteConnections(fEnable != FALSE));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellTurnOffDialog
|
|
//
|
|
// Arguments: hwndParent = HWND to parent the dialog to.
|
|
//
|
|
// Returns: DWORD
|
|
//
|
|
// Purpose: Displays the "Turn Off Computer" dialog and allows the user to
|
|
// make a choice of available shut down options.
|
|
//
|
|
// History: 2000-03-02 vtan created
|
|
// 2000-04-17 vtan moved from shell to msgina
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C DWORD _ShellTurnOffDialog (HWND hwndParent)
|
|
|
|
{
|
|
CTurnOffDialog turnOffDialog(hDllInstance);
|
|
|
|
return(turnOffDialog.Show(hwndParent));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellACPIPowerButtonPressed
|
|
//
|
|
// Arguments: pWlxContext = PGLOBALS allocated at WlxInitialize.
|
|
// uiEventType = Event code for the power message.
|
|
// fLocked = Is workstation locked or not.
|
|
//
|
|
// Returns: DWORD
|
|
//
|
|
// Purpose: Displays the "Turn Off Computer" dialog and allows the user to
|
|
// make a choice of available shut down options. This is called
|
|
// in response to an ACPI power button press. The return codes
|
|
// are MSGINA_DLG_xxx return codes to winlogon.
|
|
//
|
|
// History: 2000-04-17 vtan created
|
|
// 2001-06-12 vtan added fLocked flag
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C int _ShellACPIPowerButtonPressed (void *pWlxContext, UINT uiEventType, BOOL fLocked)
|
|
|
|
{
|
|
int iResult;
|
|
CTokenInformation tokenInformation;
|
|
CUserSettings userSettings;
|
|
|
|
if ((uiEventType & (POWER_USER_NOTIFY_BUTTON | POWER_USER_NOTIFY_SHUTDOWN)) != 0)
|
|
{
|
|
|
|
// This code should not be re-entrant for multiple ACPI power button
|
|
// presses while the dialog is up. Blow off any further requests.
|
|
|
|
// Conditions for the prompt:
|
|
// 1) This session is the active console session
|
|
// 2) Power button dialog not already displayed
|
|
// 3) User is not restricted from closing the taskbar (shut down options)
|
|
// 4) User has the privilege to shut down the machine or the friendly UI is NOT active
|
|
// 5) User is not the system OR shut down without logon is allowed
|
|
|
|
if (CSystemSettings::IsActiveConsoleSession() &&
|
|
!userSettings.IsRestrictedNoClose() &&
|
|
(tokenInformation.UserHasPrivilege(SE_SHUTDOWN_PRIVILEGE) || !CSystemSettings::IsFriendlyUIActive()) &&
|
|
(!tokenInformation.IsUserTheSystem() || CSystemSettings::IsShutdownWithoutLogonAllowed()))
|
|
{
|
|
DWORD dwExitWindowsFlags;
|
|
|
|
if ((uiEventType & POWER_USER_NOTIFY_SHUTDOWN) != 0)
|
|
{
|
|
iResult = CTurnOffDialog::ShellCodeToGinaCode(SHTDN_SHUTDOWN);
|
|
}
|
|
else
|
|
{
|
|
DWORD dwResult;
|
|
CPowerButton *pPowerButton;
|
|
|
|
// Create a thread to handle the dialog. This is required because
|
|
// the dialog must be put on the input desktop which isn't necessarily
|
|
// the same as this thread's desktop. Wait for its completion.
|
|
|
|
pPowerButton = new CPowerButton(pWlxContext, hDllInstance);
|
|
if (pPowerButton != NULL)
|
|
{
|
|
(DWORD)pPowerButton->WaitForCompletion(INFINITE);
|
|
|
|
// Get the dialog result and check its validity. Only execute
|
|
// valid requests.
|
|
|
|
dwResult = pPowerButton->GetResult();
|
|
pPowerButton->Release();
|
|
}
|
|
else
|
|
{
|
|
dwResult = MSGINA_DLG_FAILURE;
|
|
}
|
|
iResult = dwResult;
|
|
}
|
|
dwExitWindowsFlags = CTurnOffDialog::GinaCodeToExitWindowsFlags(iResult);
|
|
|
|
// If this is a restart or a shutdown then decide to display a warning.
|
|
// If the user is the system then use EWX_SYSTEM_CALLER.
|
|
// If the workstation is locked then use EWX_WINLOGON_CALLER.
|
|
// Otherwise use nothing but still possibly display a warning.
|
|
|
|
if ((dwExitWindowsFlags != 0) && (DisplayExitWindowsWarnings((tokenInformation.IsUserTheSystem() ? EWX_SYSTEM_CALLER : fLocked ? EWX_WINLOGON_CALLER : 0) | dwExitWindowsFlags) == FALSE))
|
|
{
|
|
iResult = MSGINA_DLG_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iResult = -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNINGMSG("Unknown event type in _ShellACPIPowerButtonPressed.\r\n");
|
|
iResult = MSGINA_DLG_FAILURE;
|
|
}
|
|
return(iResult);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellIsSuspendAllowed
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
// Purpose: Returns whether suspend is allowed. This is important to
|
|
// prevent the UI host from going into an uncertain state due to
|
|
// the asynchronous nature of suspend and the WM_POWERBROADCAST
|
|
// messages.
|
|
//
|
|
// Suspend is allowed if ANY of these conditions are satisfied.
|
|
//
|
|
// 1) Friendly UI is NOT active
|
|
// 2) No UI Host exists
|
|
// 3) UI Host exists and is active (not as status host)
|
|
//
|
|
// History: 2000-07-27 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _ShellIsSuspendAllowed (void)
|
|
|
|
{
|
|
return(!CSystemSettings::IsFriendlyUIActive() || _Shell_LogonStatus_IsSuspendAllowed());
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellStatusHostBegin
|
|
//
|
|
// Arguments: uiStartType = Mode to start UI host in.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Starts the status UI host if specified.
|
|
//
|
|
// History: 2000-05-03 vtan created
|
|
// 2000-07-13 vtan add shutdown parameter
|
|
// 2000-07-17 vtan changed to start type parameter
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellStatusHostBegin (UINT uiStartType)
|
|
|
|
{
|
|
_Shell_LogonStatus_Init(uiStartType);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellStatusHostEnd
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Terminates the status UI host if one was started.
|
|
//
|
|
// History: 2000-05-03 vtan created
|
|
// 2001-01-09 vtan add end type parameter
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellStatusHostEnd (UINT uiEndType)
|
|
|
|
{
|
|
_Shell_LogonStatus_Destroy(uiEndType);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellStatusHostShuttingDown
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Tell the status UI host to display a title that the system is
|
|
// shutting down.
|
|
//
|
|
// History: 2000-07-14 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellStatusHostShuttingDown (void)
|
|
|
|
{
|
|
_Shell_LogonStatus_NotifyWait();
|
|
_Shell_LogonStatus_SetStateStatus(0);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellStatusHostPowerEvent
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Tell the status UI host to go into "Please Wait" mode in
|
|
// preparation for a power event.
|
|
//
|
|
// History: 2001-01-31 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellStatusHostPowerEvent (void)
|
|
|
|
{
|
|
_Shell_LogonStatus_NotifyWait();
|
|
_Shell_LogonStatus_SetStateStatus(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellSwitchWhenInteractiveReady
|
|
//
|
|
// Arguments: eSwitchType = Switch type.
|
|
// pWlxContext = PGLOBALS allocated at WlxInitialize.
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
// Purpose: Does one of three things.
|
|
//
|
|
// 1) Create the switch event and registers the wait on it.
|
|
// 2) Checks the switch event and switches now or when signaled.
|
|
// 3) Cancels any outstanding wait and clean up.
|
|
//
|
|
// History: 2000-05-04 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C BOOL _ShellSwitchWhenInteractiveReady (SWITCHTYPE eSwitchType, void *pWlxContext)
|
|
|
|
{
|
|
NTSTATUS status;
|
|
|
|
switch (eSwitchType)
|
|
{
|
|
case SWITCHTYPE_CREATE:
|
|
if (!CSystemSettings::IsSafeMode() && _Shell_LogonStatus_Exists() && CSystemSettings::IsFriendlyUIActive())
|
|
{
|
|
status = CWaitInteractiveReady::Create(pWlxContext);
|
|
}
|
|
else
|
|
{
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
break;
|
|
case SWITCHTYPE_REGISTER:
|
|
status = CWaitInteractiveReady::Register(pWlxContext);
|
|
break;
|
|
case SWITCHTYPE_CANCEL:
|
|
status = CWaitInteractiveReady::Cancel();
|
|
break;
|
|
default:
|
|
DISPLAYMSG("Unexpected switch type in _ShellSwitchWhenInteractiveReady");
|
|
status = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
return(NT_SUCCESS(status));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellDimScreen
|
|
//
|
|
// Arguments: ppIUnknown = IUnknown returned for release.
|
|
// phwndDimmed = HWND of the dimmed window for parenting.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// Purpose:
|
|
//
|
|
// History: 2000-05-18 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C HRESULT _ShellDimScreen (IUnknown* *ppIUnknown, HWND* phwndDimmed)
|
|
|
|
{
|
|
HRESULT hr;
|
|
CDimmedWindow *pDimmedWindow;
|
|
|
|
if (IsBadWritePtr(ppIUnknown, sizeof(*ppIUnknown)) || IsBadWritePtr(phwndDimmed, sizeof(*phwndDimmed)))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
*ppIUnknown = NULL;
|
|
pDimmedWindow = new CDimmedWindow(hDllInstance);
|
|
if (pDimmedWindow != NULL)
|
|
{
|
|
hr = pDimmedWindow->QueryInterface(IID_IUnknown, reinterpret_cast<void**>(ppIUnknown));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pDimmedWindow->Release();
|
|
*phwndDimmed = pDimmedWindow->Create();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellInstallAccountFilterData
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Called by shgina registration to install special accounts
|
|
// that need to be filtered by name.
|
|
//
|
|
// History: 2000-06-02 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellInstallAccountFilterData (void)
|
|
|
|
{
|
|
CSpecialAccounts::Install();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellSwitchUser
|
|
//
|
|
// Arguments: fWait = Wait for console disconnect to complete.
|
|
//
|
|
// Returns: DWORD
|
|
//
|
|
// Purpose: Checks for available memory before doing a disconnect. If the
|
|
// disconnect succeeds the processes running in the session have
|
|
// their working set dropped.
|
|
//
|
|
// History: 2000-08-03 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C DWORD _ShellSwitchUser (BOOL fWait)
|
|
|
|
{
|
|
static BOOL s_fIsServer = static_cast<BOOL>(-1);
|
|
|
|
DWORD dwErrorCode;
|
|
|
|
dwErrorCode = ERROR_SUCCESS;
|
|
if (s_fIsServer == static_cast<BOOL>(-1))
|
|
{
|
|
OSVERSIONINFOEX osVersionInfoEx;
|
|
|
|
ZeroMemory(&osVersionInfoEx, sizeof(osVersionInfoEx));
|
|
osVersionInfoEx.dwOSVersionInfoSize = sizeof(osVersionInfoEx);
|
|
if (GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&osVersionInfoEx)) != FALSE)
|
|
{
|
|
s_fIsServer = ((VER_NT_SERVER == osVersionInfoEx.wProductType) || (VER_NT_DOMAIN_CONTROLLER == osVersionInfoEx.wProductType));
|
|
}
|
|
else
|
|
{
|
|
dwErrorCode = GetLastError();
|
|
}
|
|
}
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
{
|
|
bool fRemote;
|
|
|
|
fRemote = (GetSystemMetrics(SM_REMOTESESSION) != 0);
|
|
if (s_fIsServer)
|
|
{
|
|
|
|
// Normal Server TS case (RemoteAdmin and TerminalServer)
|
|
|
|
if (fRemote)
|
|
{
|
|
if (WinStationDisconnect(SERVERNAME_CURRENT, LOGONID_CURRENT, static_cast<BOOLEAN>(fWait)) == FALSE)
|
|
{
|
|
dwErrorCode = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwErrorCode = ERROR_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
else if (ShellIsMultipleUsersEnabled() && !fRemote)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
// Fast user switching case - need to do some extra work
|
|
// FUS is always on the console. When the session is remoted
|
|
// fall thru to PTS.
|
|
|
|
status = CCompatibility::TerminateNonCompliantApplications();
|
|
if (status == STATUS_PORT_DISCONNECTED)
|
|
{
|
|
status = CCompatibility::TerminateNonCompliantApplications();
|
|
}
|
|
dwErrorCode = static_cast<DWORD>(CStatusCode::ErrorCodeOfStatusCode(status));
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
{
|
|
if (CCompatibility::HasEnoughMemoryForNewSession())
|
|
{
|
|
HANDLE hEvent;
|
|
|
|
TBOOL(_ShellSwitchWhenInteractiveReady(SWITCHTYPE_CANCEL, NULL));
|
|
hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, CReturnToWelcome::GetEventName());
|
|
if (hEvent != NULL)
|
|
{
|
|
TBOOL(SetEvent(hEvent));
|
|
TBOOL(CloseHandle(hEvent));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Normal PTS case or FUS remoted, just call the api
|
|
|
|
if (WinStationDisconnect(SERVERNAME_CURRENT, LOGONID_CURRENT, static_cast<BOOLEAN>(fWait)) == FALSE)
|
|
{
|
|
dwErrorCode = GetLastError();
|
|
}
|
|
}
|
|
}
|
|
return(dwErrorCode);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellIsUserInteractiveLogonAllowed
|
|
//
|
|
// Arguments: pwszUsername = User name to check interactive logon.
|
|
//
|
|
// Returns: int
|
|
//
|
|
// Purpose: Checks whether the given user has interactive logon right to
|
|
// the local system. The presence of SeDenyInteractiveLogonRight
|
|
// determines this.
|
|
//
|
|
// -1 = indeterminate state
|
|
// 0 = interactive logon not allowed
|
|
// 1 = interactive logon allowed.
|
|
//
|
|
// History: 2000-08-14 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C int _ShellIsUserInteractiveLogonAllowed (const WCHAR *pwszUsername)
|
|
|
|
{
|
|
return(CUserList::IsInteractiveLogonAllowed(pwszUsername));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::ShellNotifyThemeUserChange
|
|
//
|
|
// Arguments: hToken = Token of user being logged on.
|
|
// fUserLoggedOn = Indicates logon or logoff.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Gives themes a chance to change the active theme based on a
|
|
// user logging on or logging off. This may be required because
|
|
// the default theme may be different from the user theme.
|
|
//
|
|
// History: 2000-08-09 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellNotifyThemeUserChange (USERLOGTYPE eUserLogType, HANDLE hToken)
|
|
|
|
{
|
|
static HANDLE s_hToken = NULL;
|
|
|
|
switch (eUserLogType)
|
|
{
|
|
case ULT_LOGON:
|
|
(BOOL)ThemeUserLogon(hToken);
|
|
if (QueueUserWorkItem(CSystemSettings::AdjustFUSCompatibilityServiceState,
|
|
NULL,
|
|
WT_EXECUTELONGFUNCTION) == FALSE)
|
|
{
|
|
(DWORD)CSystemSettings::AdjustFUSCompatibilityServiceState(NULL);
|
|
}
|
|
s_hToken = hToken;
|
|
break;
|
|
case ULT_LOGOFF:
|
|
if (s_hToken != NULL)
|
|
{
|
|
(DWORD)CSystemSettings::AdjustFUSCompatibilityServiceState(NULL);
|
|
s_hToken = NULL;
|
|
}
|
|
(BOOL)ThemeUserLogoff();
|
|
break;
|
|
case ULT_TSRECONNECT:
|
|
(BOOL)ThemeUserTSReconnect();
|
|
break;
|
|
case ULT_STARTSHELL:
|
|
(BOOL)ThemeUserStartShell();
|
|
break;
|
|
default:
|
|
DISPLAYMSG("Unexpected eUserLogType in ::_ShellNotifyThemeUserChange");
|
|
break;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::_ShellReturnToWelcome
|
|
//
|
|
// Arguments: fUnlock = Unlock status mode required.
|
|
//
|
|
// Returns: int
|
|
//
|
|
// Purpose: Handles the dialog that is brought up behind the welcome
|
|
// screen. This dialog is similar to WlxLoggedOutSAS but is
|
|
// specific to return to welcome.
|
|
//
|
|
// History: 2001-01-11 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C DWORD _ShellReturnToWelcome (BOOL fUnlock)
|
|
|
|
{
|
|
CReturnToWelcome returnToWelcome;
|
|
|
|
return(static_cast<DWORD>(returnToWelcome.Show(fUnlock != FALSE)));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::_ShellStartCredentialServer
|
|
//
|
|
// Arguments: pwszUsername = User name.
|
|
// pwszDomain = Domain.
|
|
// pwszPassword = Password.
|
|
// dwTimeout = Timeout.
|
|
//
|
|
// Returns: DWORD
|
|
//
|
|
// Purpose: Starts a credential transfer server in the host process. The
|
|
// caller must have SE_TCB_PRIVILEGE to execute this function.
|
|
//
|
|
// History: 2001-04-03 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C DWORD _ShellStartCredentialServer (const WCHAR *pwszUsername, const WCHAR *pwszDomain, WCHAR *pwszPassword, DWORD dwTimeout)
|
|
|
|
{
|
|
DWORD dwErrorCode;
|
|
CTokenInformation tokenInformation;
|
|
|
|
if (tokenInformation.UserHasPrivilege(SE_TCB_PRIVILEGE))
|
|
{
|
|
TSTATUS(CCredentials::StaticInitialize(false));
|
|
dwErrorCode = CStatusCode::ErrorCodeOfStatusCode(CCredentialServer::Start(pwszUsername, pwszDomain, pwszPassword, dwTimeout));
|
|
}
|
|
else
|
|
{
|
|
dwErrorCode = ERROR_PRIVILEGE_NOT_HELD;
|
|
}
|
|
return(dwErrorCode);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::_ShellAcquireLogonMutex
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Acquire the logon mutex.
|
|
//
|
|
// History: 2001-04-04 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellAcquireLogonMutex (void)
|
|
|
|
{
|
|
CLogonMutex::Acquire();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::_ShellReleaseLogonMutex
|
|
//
|
|
// Arguments: fSignalEvent = Signal completion event.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Release the logon mutex. If required to signal the completion
|
|
// event then signal it.
|
|
//
|
|
// History: 2001-04-04 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellReleaseLogonMutex (BOOL fSignalEvent)
|
|
|
|
{
|
|
if (fSignalEvent != FALSE)
|
|
{
|
|
CLogonMutex::SignalReply();
|
|
}
|
|
CLogonMutex::Release();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::_ShellSignalShutdown
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Signal the shut down event to prevent further interactive
|
|
// logon requeusts.
|
|
//
|
|
// History: 2001-04-06 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellSignalShutdown (void)
|
|
|
|
{
|
|
CLogonMutex::SignalShutdown();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::_ShellStatusHostHide
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose:
|
|
//
|
|
// History: 2001-04-12 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellStatusHostHide (void)
|
|
|
|
{
|
|
_Shell_LogonStatus_Hide();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// ::_ShellStatusHostShow
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose:
|
|
//
|
|
// History: 2001-04-12 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
EXTERN_C void _ShellStatusHostShow (void)
|
|
|
|
{
|
|
_Shell_LogonStatus_Show();
|
|
}
|
|
|