windows-nt/Source/XPSP1/NT/shell/ext/gina/logondialog.cpp
2020-09-26 16:20:57 +08:00

1832 lines
60 KiB
C++

// --------------------------------------------------------------------------
// Module Name: CWLogonDialog.cpp
//
// Copyright (c) 2000, Microsoft Corporation
//
// File that contains an internal class to implement the logon dialog
// additions for consumer windows. The C entry points allow the old Windows
// 2000 Win32 GINA dialog to call into this C++ code.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
#include "StandardHeader.h"
#include <cfgmgr32.h>
#include <ginaIPC.h>
#include <ginarcid.h>
#include <msginaexports.h>
#include <shlobj.h>
#include <shlobjp.h>
#include <winwlx.h>
#include "CredentialTransfer.h"
#include "LogonMutex.h"
#include "LogonWait.h"
#include "PrivilegeEnable.h"
#include "RegistryResources.h"
#include "SingleThreadedExecution.h"
#include "StatusCode.h"
#include "StringConvert.h"
#include "SystemSettings.h"
#include "TokenInformation.h"
#include "TurnOffDialog.h"
#include "UIHost.h"
#include "UserList.h"
#define WM_HIDEOURSELVES (WM_USER + 10000)
#define WM_SHOWOURSELVES (WM_USER + 10001)
// Special logon substatus code from: ds\security\gina\msgina\stringid.h
#define IDS_LOGON_LOG_FULL 1702
// --------------------------------------------------------------------------
// CLogonDialog
//
// Purpose: C++ class to handle logon dialog additions for consumer
// windows.
//
// History: 2000-02-04 vtan created from Neptune
// --------------------------------------------------------------------------
class CLogonDialog : public ILogonExternalProcess
{
private:
CLogonDialog (void);
CLogonDialog (const CLogonDialog& copyObject);
const CLogonDialog& operator = (const CLogonDialog& assignObject);
public:
CLogonDialog (HWND hwndDialog, CUIHost *pUIHost, int iDialogType);
~CLogonDialog (void);
NTSTATUS StartUIHost (void);
void EndUIHost (void);
void ChangeWindowTitle (void);
bool IsClassicLogonMode (void) const;
bool RevertClassicLogonMode (void);
void Handle_WM_INITDIALOG (void);
void Handle_WM_DESTROY (void);
void Handle_WM_HIDEOURSELVES (void);
void Handle_WM_SHOWOURSELVES (void);
bool Handle_WM_LOGONSERVICEREQUEST (int iRequestType, void *pvInformation, int iDataSize);
void Handle_WLX_WM_SAS (WPARAM wParam);
bool Handle_WM_POWERBROADCAST (WPARAM wParam);
bool Handle_LogonDisplayError (NTSTATUS status, NTSTATUS subStatus);
void Handle_LogonCompleted (INT_PTR iDialogResult, const WCHAR *pszUsername, const WCHAR *pszDomain);
void Handle_ShuttingDown (void);
void Handle_LogonShowUI (void);
void Handle_LogonHideUI (void);
static void SetTextFields (HWND hwndDialog, const WCHAR *pwszUsername, const WCHAR *pwszDomain, const WCHAR *pwszPassword);
public:
virtual bool AllowTermination (DWORD dwExitCode);
virtual NTSTATUS SignalAbnormalTermination (void);
virtual NTSTATUS SignalRestart (void);
virtual NTSTATUS LogonRestart (void);
private:
bool Handle_LOGON_QUERY_LOGGED_ON (LOGONIPC_CREDENTIALS& logonIPCCredentials);
bool Handle_LOGON_LOGON_USER (LOGONIPC_CREDENTIALS& logonIPCCredentials);
bool Handle_LOGON_LOGOFF_USER (LOGONIPC_CREDENTIALS& logonIPCCredentials);
bool Handle_LOGON_TEST_BLANK_PASSWORD (LOGONIPC_CREDENTIALS& logonIPCCredentials);
bool Handle_LOGON_TEST_INTERACTIVE_LOGON_ALLOWED (LOGONIPC_CREDENTIALS& logonIPCCredentials);
bool Handle_LOGON_TEST_EJECT_ALLOWED (void);
bool Handle_LOGON_TEST_SHUTDOWN_ALLOWED (void);
bool Handle_LOGON_TURN_OFF_COMPUTER (void);
bool Handle_LOGON_EJECT_COMPUTER (void);
bool Handle_LOGON_SIGNAL_UIHOST_FAILURE (void);
bool Handle_LOGON_ALLOW_EXTERNAL_CREDENTIALS (void);
bool Handle_LOGON_REQUEST_EXTERNAL_CREDENTIALS (void);
private:
HWND _hwndDialog;
RECT _rcDialog;
bool _fLogonSuccessful,
_fFatalError,
_fExternalCredentials,
_fResumed,
_fOldCancelButtonEnabled;
int _iDialogType,
_iCADCount;
HANDLE _hEvent;
IExternalProcess* _pIExternalProcessOld;
CEvent _eventLogonComplete;
CLogonWait _logonWait;
CUIHost* _pUIHost;
TCHAR _szDomain[DNLEN + sizeof('\0')];
TCHAR* _pszWindowTitle;
static bool s_fFirstLogon;
};
bool g_fFirstLogon = true;
CCriticalSection* g_pLogonDialogLock = NULL;
CLogonDialog* g_pLogonDialog = NULL;
// --------------------------------------------------------------------------
// CLogonDialog::CLogonDialog
//
// Arguments: hwndDialog = HWND to the Win32 GINA dialog.
//
// Returns: <none>
//
// Purpose: Constructor for the CLogonDialog class. This stores the HWND
// and creates an event that gets signaled when the attempt
// logon thread completes and posts a message back to the Win32
// dialog.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
CLogonDialog::CLogonDialog (HWND hwndDialog, CUIHost *pUIHost, int iDialogType) :
_hwndDialog(hwndDialog),
_fLogonSuccessful(false),
_fFatalError(false),
_fExternalCredentials(false),
_fResumed(false),
_iDialogType(iDialogType),
_iCADCount(0),
_hEvent(NULL),
_pIExternalProcessOld(NULL),
_eventLogonComplete(NULL),
_pUIHost(NULL),
_pszWindowTitle(NULL)
{
pUIHost->AddRef();
_pIExternalProcessOld = pUIHost->GetInterface();
pUIHost->SetInterface(this);
_pUIHost = pUIHost;
}
// --------------------------------------------------------------------------
// CLogonDialog::~CLogonDialog
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Destructor for the CLogonDialog class.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
CLogonDialog::~CLogonDialog (void)
{
ReleaseHandle(_hEvent);
ReleaseMemory(_pszWindowTitle);
ASSERTMSG(_hwndDialog == NULL, "CLogonDialog destroyed with WM_DESTROY being invoked in CLogonDialog::~CLogonDialog");
}
// --------------------------------------------------------------------------
// CLogonDialog::StartUIHost
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: Start the external process that hosts the UI. This can be
// anything but is presently logonui.exe. This is actually
// determined in the CUIHost class.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
NTSTATUS CLogonDialog::StartUIHost (void)
{
NTSTATUS status;
LOGONIPC_CREDENTIALS logonIPCCredentials;
ASSERTMSG(_pUIHost->IsStarted(), "UI host must be started in CLogonDialog::StartUIHost");
if (_pUIHost->IsHidden())
{
(NTSTATUS)_pUIHost->Show();
}
status = CCredentialClient::Get(&logonIPCCredentials);
if (NT_SUCCESS(status))
{
_Shell_LogonStatus_NotifyNoAnimations();
}
_Shell_LogonStatus_SetStateLogon((_iDialogType != SHELL_LOGONDIALOG_RETURNTOWELCOME_UNLOCK) ? 0 : SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
if (_iDialogType == SHELL_LOGONDIALOG_RETURNTOWELCOME_UNLOCK)
{
_iDialogType = SHELL_LOGONDIALOG_RETURNTOWELCOME;
}
if (NT_SUCCESS(status))
{
_Shell_LogonStatus_InteractiveLogon(logonIPCCredentials.userID.wszUsername,
logonIPCCredentials.userID.wszDomain,
logonIPCCredentials.wszPassword);
}
return(STATUS_SUCCESS);
}
// --------------------------------------------------------------------------
// CLogonDialog::EndUIHost
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: End the external UI host. Just release the reference to it.
//
// History: 2000-05-01 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::EndUIHost (void)
{
if (_pUIHost != NULL)
{
if (_pIExternalProcessOld != NULL)
{
_pUIHost->SetInterface(_pIExternalProcessOld);
_pIExternalProcessOld->Release();
_pIExternalProcessOld = NULL;
}
_pUIHost->Release();
_pUIHost = NULL;
}
}
// --------------------------------------------------------------------------
// CLogonDialog::ChangeWindowTitle
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Change the window title of the msgina dialog to something that
// shgina can find.
//
// History: 2000-06-02 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::ChangeWindowTitle (void)
{
if (_pszWindowTitle == NULL)
{
int iLength;
// Because the title of the dialog can be localized change the name to
// something that shgina expects that will NOT be localized. Don't forget
// to restore this if the dialog needs to be re-shown again. If the current
// value cannot be read slam the title anyway. Recovery from error will be
// less than optimal.
iLength = GetWindowTextLength(_hwndDialog) + sizeof('\0');
_pszWindowTitle = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, iLength * sizeof(TCHAR)));
if (_pszWindowTitle != NULL)
{
(int)GetWindowText(_hwndDialog, _pszWindowTitle, iLength);
}
TBOOL(SetWindowText(_hwndDialog, TEXT("GINA Logon")));
TBOOL(GetWindowRect(_hwndDialog, &_rcDialog));
TBOOL(SetWindowPos(_hwndDialog, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER));
}
}
// --------------------------------------------------------------------------
// CLogonDialog::IsClassicLogonMode
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether classic logon has been externally requested
// by the user (CTRL-ALT-DELETE x 2).
//
// History: 2001-01-12 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::IsClassicLogonMode (void) const
{
return(_iCADCount >= 2);
}
// --------------------------------------------------------------------------
// CLogonDialog::RevertClassicLogonMode
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether it handled the conversion back from classic
// logon mode to the UI host.
//
// History: 2001-01-12 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::RevertClassicLogonMode (void)
{
bool fResult;
fResult = IsClassicLogonMode();
if (fResult)
{
_iCADCount = 0;
_fExternalCredentials = false;
(BOOL)EnableWindow(GetDlgItem(_hwndDialog, IDCANCEL), _fOldCancelButtonEnabled);
TBOOL(PostMessage(_hwndDialog, WM_HIDEOURSELVES, 0, 0));
Handle_LogonShowUI();
}
return(fResult);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_WM_INITDIALOG
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: This function is invoked if the external UI host is being
// used. In this case the GINA Win32 dialog size is saved and
// then changed to an empty rectangle. The window is then hidden
// using a posted message.
//
// See CLogonDialog::Handle_WM_HIDEOURSELVES for the follow up.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::Handle_WM_INITDIALOG (void)
{
if (!_fFatalError && !_fExternalCredentials)
{
TBOOL(PostMessage(_hwndDialog, WM_HIDEOURSELVES, 0, 0));
}
_ShellReleaseLogonMutex(FALSE);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_WM_DESTROY
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: This function cleans up anything in the dialog before
// destruction.
//
// History: 2000-02-07 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::Handle_WM_DESTROY (void)
{
_hwndDialog = NULL;
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_WM_HIDEOURSELVES
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: This function is invoked after the dialog is asked to hide
// itself. The user will not see anything because the size of
// the dialog client rectangle is an empty rectangle.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::Handle_WM_HIDEOURSELVES (void)
{
(BOOL)ShowWindow(_hwndDialog, SW_HIDE);
ChangeWindowTitle();
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_WM_SHOWOURSELVES
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: In case the Win32 dialog needs to be shown again this function
// exists. It restores the size of the dialog and then shows the
// dialog.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::Handle_WM_SHOWOURSELVES (void)
{
if (_iDialogType == SHELL_LOGONDIALOG_LOGGEDOFF)
{
if (_pszWindowTitle != NULL)
{
// If handling logged off welcome screen failure show WlxLoggedOutSAS.
TBOOL(SetWindowText(_hwndDialog, _pszWindowTitle));
ReleaseMemory(_pszWindowTitle);
TBOOL(SetWindowPos(_hwndDialog, NULL, 0, 0, _rcDialog.right - _rcDialog.left, _rcDialog.bottom - _rcDialog.top, SWP_NOMOVE | SWP_NOZORDER));
(BOOL)ShowWindow(_hwndDialog, SW_SHOW);
(BOOL)SetForegroundWindow(_hwndDialog);
(BOOL)_Gina_SetPasswordFocus(_hwndDialog);
}
}
else
{
// If handling return to welcome screen failure show WlxWkstaLockedSAS.
TBOOL(EndDialog(_hwndDialog, MSGINA_DLG_LOCK_WORKSTATION));
}
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_WM_LOGONSERVICEREQUEST
//
// Arguments: iRequestType = Request identifier.
// pvInformation = Pointer to the information in the
// requesting process address space.
// iDataSize = Size of the data.
//
// Returns: bool
//
// Purpose: Handler for logon service requests made thru the logon IPC.
// This specifically serves the UI host.
//
// History: 1999-08-24 vtan created
// 2000-01-31 vtan moved from Neptune to Whistler
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_WM_LOGONSERVICEREQUEST (int iRequestType, void *pvInformation, int iDataSize)
{
bool fResult, fHandled;
LOGONIPC_CREDENTIALS logonIPCCredentials;
// Clear out our memory and extract the information from the requesting
// process. This could be us if the internal logon dialog is used. The
// extractor knows how to handle this.
ZeroMemory(&logonIPCCredentials, sizeof(logonIPCCredentials));
if (NT_SUCCESS(_pUIHost->GetData(pvInformation, &logonIPCCredentials, iDataSize)))
{
switch (iRequestType)
{
case LOGON_QUERY_LOGGED_ON:
{
fResult = Handle_LOGON_QUERY_LOGGED_ON(logonIPCCredentials);
break;
}
case LOGON_LOGON_USER:
{
fResult = Handle_LOGON_LOGON_USER(logonIPCCredentials);
break;
}
case LOGON_LOGOFF_USER:
{
fResult = Handle_LOGON_LOGOFF_USER(logonIPCCredentials);
break;
}
case LOGON_TEST_BLANK_PASSWORD:
{
fResult = Handle_LOGON_TEST_BLANK_PASSWORD(logonIPCCredentials);
break;
}
case LOGON_TEST_INTERACTIVE_LOGON_ALLOWED:
{
fResult = Handle_LOGON_TEST_INTERACTIVE_LOGON_ALLOWED(logonIPCCredentials);
break;
}
case LOGON_TEST_EJECT_ALLOWED:
{
fResult = Handle_LOGON_TEST_EJECT_ALLOWED();
break;
}
case LOGON_TEST_SHUTDOWN_ALLOWED:
{
fResult = Handle_LOGON_TEST_SHUTDOWN_ALLOWED();
break;
}
case LOGON_TURN_OFF_COMPUTER:
{
fResult = Handle_LOGON_TURN_OFF_COMPUTER();
break;
}
case LOGON_EJECT_COMPUTER:
{
fResult = Handle_LOGON_EJECT_COMPUTER();
break;
}
case LOGON_SIGNAL_UIHOST_FAILURE:
{
fResult = Handle_LOGON_SIGNAL_UIHOST_FAILURE();
break;
}
case LOGON_ALLOW_EXTERNAL_CREDENTIALS:
{
fResult = Handle_LOGON_ALLOW_EXTERNAL_CREDENTIALS();
break;
}
case LOGON_REQUEST_EXTERNAL_CREDENTIALS:
{
fResult = Handle_LOGON_REQUEST_EXTERNAL_CREDENTIALS();
break;
}
default:
{
DISPLAYMSG("Invalid request sent to CLogonDialog::Handle_WM_LOGONSERVICEREQUEST");
break;
}
}
// Put the result back in the UI host process' information block.
fHandled = NT_SUCCESS(_pUIHost->PutData(pvInformation, &fResult, sizeof(fResult)));
}
else
{
fHandled = false;
}
return(fHandled);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_WLX_WM_SAS
//
// Arguments: wParam = SAS type that occurred.
//
// Returns: <none>
//
// Purpose: Invoked when a SAS is delivered to the logon dialog. This can
// be done by a remote shutdown invokation. In this case the UI
// host should not be restarted. Make a note of this.
//
// History: 2000-04-24 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::Handle_WLX_WM_SAS (WPARAM wParam)
{
if ((wParam == WLX_SAS_TYPE_CTRL_ALT_DEL) && (_iDialogType == SHELL_LOGONDIALOG_LOGGEDOFF))
{
// CONTROL-ALT-DELETE. If not in classic mode bump up the CAD count.
// If it reaches classic mode then switch. If in classic mode blow it off.
if (!IsClassicLogonMode())
{
++_iCADCount;
if (IsClassicLogonMode())
{
_fExternalCredentials = true;
_fOldCancelButtonEnabled = (EnableWindow(GetDlgItem(_hwndDialog, IDCANCEL), TRUE) == 0);
TBOOL(PostMessage(_hwndDialog, WM_SHOWOURSELVES, 0, 0));
Handle_LogonHideUI();
}
}
}
else
{
// Reset the CAD count if some other SAS gets in the way.
_iCADCount = 0;
if (wParam == WLX_SAS_TYPE_USER_LOGOFF)
{
_fFatalError = true;
}
else if (wParam == WLX_SAS_TYPE_SCRNSVR_TIMEOUT)
{
_pUIHost->Hide();
}
}
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_WM_POWERBROADCAST
//
// Arguments: wParam = Powerbroadcast message.
//
// Returns: bool
//
// Purpose: Responds to APM messages. When suspend is issued it places
// the UI host to status mode. When resume is received it places
// the UI host in logon mode.
//
// The UI host should have waited and blown off requests to
// display the logon list and should be waiting for this call to
// release it because we pass it the same magic number to lock
// it.
//
// History: 2000-06-30 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_WM_POWERBROADCAST (WPARAM wParam)
{
bool fResult;
fResult = false;
if (((PBT_APMRESUMEAUTOMATIC == wParam) || (PBT_APMRESUMECRITICAL == wParam) || (PBT_APMRESUMESUSPEND == wParam)) &&
!_fResumed)
{
_fResumed = true;
_Shell_LogonStatus_SetStateLogon(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
fResult = true;
}
else if (PBT_APMSUSPEND == wParam)
{
_Shell_LogonStatus_SetStateStatus(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
_fResumed = fResult = false;
}
return(fResult);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LogonDisplayError
//
// Arguments: status = NTSTATUS of logon request.
//
// Returns: bool
//
// Purpose: Under all cases other than a bad password a failure to logon
// should be displayed by a standard Win32 error dialog that
// is already handled by msgina. In the case of a bad password
// let the UI host handle this.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LogonDisplayError (NTSTATUS status, NTSTATUS subStatus)
{
return(IsClassicLogonMode() || (status != STATUS_LOGON_FAILURE) || (subStatus == IDS_LOGON_LOG_FULL));
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LogonCompleted
//
// Arguments: iDialogResult = Dialog result code.
//
// Returns: <none>
//
// Purpose: This function is called when the attempt logon thread has
// completed and posted a message regarding its result. The
// internal event is signaled to release the actual UI host
// logon request in CLogonDialog::Handle_WM_LOGONSERVICEREQUEST
// and the actual success of the logon request is stored.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::Handle_LogonCompleted (INT_PTR iDialogResult, const WCHAR *pszUsername, const WCHAR *pszDomain)
{
if (MSGINA_DLG_SWITCH_CONSOLE == iDialogResult)
{
Handle_WM_SHOWOURSELVES();
_Shell_LogonDialog_Destroy();
_Shell_LogonStatus_Destroy(HOST_END_TERMINATE);
}
else
{
TSTATUS(_eventLogonComplete.Set());
_fLogonSuccessful = (MSGINA_DLG_SUCCESS == iDialogResult);
// Always show the UI host unless double CONTROL-ALT-DELETE
// was enabled and the logon was unsuccessful.
if (!IsClassicLogonMode() || _fLogonSuccessful)
{
Handle_WM_HIDEOURSELVES();
Handle_LogonShowUI();
}
// If successful and external credentials then instruct the UI host
// to animate to the actual person in the external credentials.
// Switch the UI host to logged on mode.
if (_fLogonSuccessful && _fExternalCredentials)
{
_Shell_LogonStatus_SelectUser(pszUsername, pszDomain);
_Shell_LogonStatus_SetStateLoggedOn();
}
}
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_ShuttingDown
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: This function handles the UI host in classic mode but was
// given a request to shut down or restart.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::Handle_ShuttingDown (void)
{
if (IsClassicLogonMode())
{
TBOOL(PostMessage(_hwndDialog, WM_HIDEOURSELVES, 0, 0));
Handle_LogonShowUI();
_Shell_LogonStatus_NotifyWait();
_Shell_LogonStatus_SetStateStatus(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
}
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LogonShowUI
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: This function is called after something that went wrong with
// the logon process has been serviced. It is called it the UI
// needs to be shown again to give the user the opportunity to
// re-enter information.
//
// History: 2000-03-08 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::Handle_LogonShowUI (void)
{
TSTATUS(_pUIHost->Show());
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LogonHideUI
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: This function is called when something goes wrong with a logon
// event that can be serviced immediately to ensure the logon
// process completes smoothly. Typically this is the user is
// required to change their password at first logon. This
// function asks the UI host to hide all its windows.
//
// History: 2000-03-08 vtan created
// --------------------------------------------------------------------------
void CLogonDialog::Handle_LogonHideUI (void)
{
TSTATUS(_pUIHost->Hide());
}
// --------------------------------------------------------------------------
// CLogonDialog::SetTextFields
//
// Arguments: hwndDialog = HWND to the Win32 GINA dialog.
// pwszUsername = User name.
// pwszDomain = User domain.
// pwszPassword = User password.
//
// Returns: <none>
//
// Purpose: This function has great knowledge of the Win32 GINA
// dialog and stores the parameters directly in the dialog to
// simulate the actual typing of the information.
//
// For the domain combobox first check that a domain has been
// supplied. If not find the computer name and use that as the
// domain. Send CB_SELECTSTRING to the combobox to select it.
//
// History: 2000-02-04 vtan created
// 2000-06-27 vtan added domain combobox support
// --------------------------------------------------------------------------
void CLogonDialog::SetTextFields (HWND hwndDialog, const WCHAR *pwszUsername, const WCHAR *pwszDomain, const WCHAR *pwszPassword)
{
_Gina_SetTextFields(hwndDialog, pwszUsername, pwszDomain, pwszPassword);
}
// --------------------------------------------------------------------------
// CLogonDialog::AllowTermination
//
// Arguments: dwExitCode = Exit code of the process that died.
//
// Returns: bool
//
// Purpose: This function is invoked by the UI host when the process
// terminates and the UI host is asking whether the termination
// is acceptable.
//
// History: 1999-09-14 vtan created
// 2000-01-31 vtan moved from Neptune to Whistler
// 2000-03-09 vtan added magical exit code
// --------------------------------------------------------------------------
bool CLogonDialog::AllowTermination (DWORD dwExitCode)
{
UNREFERENCED_PARAMETER(dwExitCode);
return(false);
}
// --------------------------------------------------------------------------
// CLogonDialog::SignalAbnormalTermination
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: This function is invoked by the UI host if the process
// terminates and cannot be restarted. This indicates a serious
// condition from which this function can attempt to recover.
//
// History: 1999-09-14 vtan created
// 2000-01-31 vtan moved from Neptune to Whistler
// --------------------------------------------------------------------------
NTSTATUS CLogonDialog::SignalAbnormalTermination (void)
{
IExternalProcess *pIExternalProcess;
ASSERTMSG(_pIExternalProcessOld != NULL, "Expecting non NULL _pIExternalProcessOld in CLogonDialog::SignalAbnormalTermination");
pIExternalProcess = _pIExternalProcessOld;
pIExternalProcess->AddRef();
TSTATUS(_logonWait.Cancel());
Handle_WM_SHOWOURSELVES();
_Shell_LogonDialog_Destroy();
TSTATUS(pIExternalProcess->SignalAbnormalTermination());
pIExternalProcess->Release();
return(STATUS_SUCCESS);
}
// --------------------------------------------------------------------------
// CLogonDialog::SignalRestart
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: Function to reset the ready event and set the UI host into
// logon state. This is invoked when the UI host is restarted
// after a failure.
//
// History: 2001-01-09 vtan created
// --------------------------------------------------------------------------
NTSTATUS CLogonDialog::SignalRestart (void)
{
NTSTATUS status;
HANDLE hEvent;
hEvent = _Shell_LogonStatus_ResetReadyEvent();
if (hEvent != NULL)
{
if (DuplicateHandle(GetCurrentProcess(),
hEvent,
GetCurrentProcess(),
&_hEvent,
0,
FALSE,
DUPLICATE_SAME_ACCESS) != FALSE)
{
status = STATUS_SUCCESS;
}
else
{
status = CStatusCode::StatusCodeOfLastError();
}
}
else
{
status = STATUS_UNSUCCESSFUL;
}
if (NT_SUCCESS(status))
{
status = _logonWait.Register(_hEvent, this);
}
return(status);
}
// --------------------------------------------------------------------------
// CLogonDialog::LogonRestart
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose:
//
// History: 2001-02-21 vtan created
// --------------------------------------------------------------------------
NTSTATUS CLogonDialog::LogonRestart (void)
{
_Shell_LogonStatus_SetStateLogon(0);
return(STATUS_SUCCESS);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_QUERY_LOGGED_ON
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_QUERY_LOGGED_ON.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_QUERY_LOGGED_ON (LOGONIPC_CREDENTIALS& logonIPCCredentials)
{
// LOGON_QUERY_LOGGED_ON: Query if the user is contained in the
// logged on user list. Use terminal services API to do this.
return(CUserList::IsUserLoggedOn(logonIPCCredentials.userID.wszUsername, logonIPCCredentials.wszPassword));
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_LOGON_USER
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_LOGON_USER.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_LOGON_USER (LOGONIPC_CREDENTIALS& logonIPCCredentials)
{
UNICODE_STRING passwordString;
// Take the run encoded password supplied and run decode using
// the provided seed. Set the password and then erase the clear
// text in memory when done. Both the logged on (switch) and
// NOT logged on case require the password.
passwordString.Buffer = logonIPCCredentials.wszPassword;
passwordString.Length = sizeof(logonIPCCredentials.wszPassword) - sizeof(L'\0');
passwordString.MaximumLength = sizeof(logonIPCCredentials.wszPassword);
RtlRunDecodeUnicodeString(logonIPCCredentials.ucPasswordSeed, &passwordString);
logonIPCCredentials.wszPassword[logonIPCCredentials.iPasswordLength] = L'\0';
// When the dialog type is SHELL_LOGONDIALOG_LOGGEDOFF use the
// regular WlxLoggedOutSAS method. Filling in the underlying
// dialog and let msgina do the actual logon work.
if (_iDialogType == SHELL_LOGONDIALOG_LOGGEDOFF)
{
// LOGON_LOGON_USER: Use an event that will get signaled
// when logon is completed. Logon occurs on a different thread
// but this thread MUST be blocked to stop the UI host from
// sending multiple logon requests. Wait for the event to get
// signaled but do not block the message pump.
// Set the username and password (no domain) and then
// erase the password in memory.
SetTextFields(_hwndDialog, logonIPCCredentials.userID.wszUsername, logonIPCCredentials.userID.wszDomain, logonIPCCredentials.wszPassword);
RtlEraseUnicodeString(&passwordString);
}
else
{
// Otherwise we expect the case to be
// SHELL_LOGONDIALOG_RETURNTOWELCOME. In this case authenticate
// by sending the struct address to the hosting window (a stripped
// down WlxLoggedOutSAS window for return to welcome) and then
// fall thru to the IDOK path just like the full dialog.
// This is accomplished with by sending a message to the return
// to welcome stub dialog WM_COMMAND/IDCANCEL.
(LRESULT)SendMessage(_hwndDialog, WM_COMMAND, IDCANCEL, reinterpret_cast<LPARAM>(&logonIPCCredentials));
}
// 1) Reset the signal event.
// 2) Simulate the "enter" key pressed (credentials filled in above).
// 3) Wait for the signal event (keep the message pump going).
// 4) Extract the result.
TSTATUS(_eventLogonComplete.Reset());
_ShellAcquireLogonMutex();
(LRESULT)SendMessage(_hwndDialog, WM_COMMAND, IDOK, NULL);
TSTATUS(_eventLogonComplete.WaitWithMessages(INFINITE, NULL));
if (_iDialogType == SHELL_LOGONDIALOG_RETURNTOWELCOME)
{
RtlEraseUnicodeString(&passwordString);
}
// On success tell the UI host to go to logon state.
if (_fLogonSuccessful)
{
_Shell_LogonStatus_SetStateLoggedOn();
}
else
{
_ShellReleaseLogonMutex(FALSE);
}
return(_fLogonSuccessful);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_LOGOFF_USER
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_LOGOFF_USER.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_LOGOFF_USER (LOGONIPC_CREDENTIALS& logonIPCCredentials)
{
UNREFERENCED_PARAMETER(logonIPCCredentials);
// LOGON_LOGOFF_USER: Log the logged on user off. They must be logged on
// or this will do nothing.
return(false); //UNIMPLEMENTED
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_TEST_BLANK_PASSWORD
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_TEST_BLANK_PASSWORD.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_TEST_BLANK_PASSWORD (LOGONIPC_CREDENTIALS& logonIPCCredentials)
{
bool fResult;
HANDLE hToken;
// LOGON_TEST_BLANK_PASSWORD: Attempt to the given user on the system
// with a blank password. If successful discard the token. Only return
// the result.
fResult = (CTokenInformation::LogonUser(logonIPCCredentials.userID.wszUsername,
logonIPCCredentials.userID.wszDomain,
L"",
&hToken) == ERROR_SUCCESS);
if (fResult && (hToken != NULL))
{
ReleaseHandle(hToken);
}
return(fResult);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_TEST_INTERACTIVE_LOGON_ALLOWED
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_TEST_INTERACTIVE_LOGON_ALLOWED.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_TEST_INTERACTIVE_LOGON_ALLOWED (LOGONIPC_CREDENTIALS& logonIPCCredentials)
{
int iResult;
iResult = CUserList::IsInteractiveLogonAllowed(logonIPCCredentials.userID.wszUsername);
return((iResult != -1) && (iResult != 0));
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_TEST_EJECT_ALLOWED
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_TEST_EJECT_ALLOWED.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_TEST_EJECT_ALLOWED (void)
{
bool fResult;
HANDLE hToken;
// Check the system setting and policy for undock without logon allowed.
fResult = CSystemSettings::IsUndockWithoutLogonAllowed();
if (fResult && (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) != FALSE))
{
DWORD dwTokenPrivilegesSize;
TOKEN_PRIVILEGES *pTokenPrivileges;
// Then test the token privilege for SE_UNDOCK_NAME privilege.
dwTokenPrivilegesSize = 0;
(BOOL)GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwTokenPrivilegesSize);
pTokenPrivileges = static_cast<TOKEN_PRIVILEGES*>(LocalAlloc(LMEM_FIXED, dwTokenPrivilegesSize));
if (pTokenPrivileges != NULL)
{
DWORD dwReturnLength;
if (GetTokenInformation(hToken, TokenPrivileges, pTokenPrivileges, dwTokenPrivilegesSize, &dwReturnLength) != FALSE)
{
DWORD dwIndex;
LUID luidPrivilege;
luidPrivilege.LowPart = SE_UNDOCK_PRIVILEGE;
luidPrivilege.HighPart = 0;
for (dwIndex = 0; !fResult && (dwIndex < pTokenPrivileges->PrivilegeCount); ++dwIndex)
{
fResult = (RtlEqualLuid(&luidPrivilege, &pTokenPrivileges->Privileges[dwIndex].Luid) != FALSE);
}
// Now check to see if a physical docking stations is present.
// Also check to see if the session is a remote session.
if (fResult)
{
BOOL fIsDockStationPresent;
fIsDockStationPresent = FALSE;
(CONFIGRET)CM_Is_Dock_Station_Present(&fIsDockStationPresent);
fResult = ((fIsDockStationPresent != FALSE) && (GetSystemMetrics(SM_REMOTESESSION) == 0));
}
}
(HLOCAL)LocalFree(pTokenPrivileges);
}
TBOOL(CloseHandle(hToken));
}
return(fResult);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_TEST_SHUTDOWN_ALLOWED
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_TEST_SHUTDOWN_ALLOWED.
//
// History: 2001-02-22 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_TEST_SHUTDOWN_ALLOWED (void)
{
return((GetSystemMetrics(SM_REMOTESESSION) == FALSE) &&
CSystemSettings::IsShutdownWithoutLogonAllowed());
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_TURN_OFF_COMPUTER
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_TURN_OFF_COMPUTER.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_TURN_OFF_COMPUTER (void)
{
bool fResult;
INT_PTR ipResult;
// LOGON_TURN_OFF_COMPUTER: Present the "Turn Off Computer" dialog
// and return an MSGINA_DLG_xxx code in response.
ipResult = CTurnOffDialog::ShellCodeToGinaCode(ShellTurnOffDialog(NULL));
if (ipResult != MSGINA_DLG_FAILURE)
{
DWORD dwExitWindowsFlags;
dwExitWindowsFlags = CTurnOffDialog::GinaCodeToExitWindowsFlags(static_cast<DWORD>(ipResult));
if ((dwExitWindowsFlags != 0) && (DisplayExitWindowsWarnings(EWX_SYSTEM_CALLER | dwExitWindowsFlags) == FALSE))
{
ipResult = MSGINA_DLG_FAILURE;
}
}
if (ipResult != MSGINA_DLG_FAILURE)
{
TBOOL(EndDialog(_hwndDialog, ipResult));
_fLogonSuccessful = fResult = true;
_Shell_LogonStatus_NotifyWait();
_Shell_LogonStatus_SetStateStatus(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
}
else
{
fResult = false;
}
return(fResult);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_EJECT_COMPUTER
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_EJECT_COMPUTER.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_EJECT_COMPUTER (void)
{
return(CM_Request_Eject_PC() == ERROR_SUCCESS);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_SIGNAL_UIHOST_FAILURE
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_SIGNAL_UIHOST_FAILURE.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_SIGNAL_UIHOST_FAILURE (void)
{
// LOGON_SIGNAL_UIHOST_FAILURE: The UI host is signaling us
// that it has an error from which it cannot recover.
_fFatalError = true;
TBOOL(PostMessage(_hwndDialog, WM_SHOWOURSELVES, 0, 0));
return(true);
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_ALLOW_EXTERNAL_CREDENTIALS
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_ALLOW_EXTERNAL_CREDENTIALS.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_ALLOW_EXTERNAL_CREDENTIALS (void)
{
// LOGON_ALLOW_EXTERNAL_CREDENTIALS: Return whether external
// credentials are allowed. Requesting external credentials
// (below) will cause classic GINA to be shown for the input.
return(CSystemSettings::IsDomainMember());
}
// --------------------------------------------------------------------------
// CLogonDialog::Handle_LOGON_REQUEST_EXTERNAL_CREDENTIALS
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Handles LOGON_REQUEST_EXTERNAL_CREDENTIALS.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
bool CLogonDialog::Handle_LOGON_REQUEST_EXTERNAL_CREDENTIALS (void)
{
// LOGON_REQUEST_EXTERNAL_CREDENTIALS: The UI host is
// requesting credentials from an external source (namely)
// msgina. Hide the UI host and show the GINA dialog.
_fExternalCredentials = true;
TBOOL(PostMessage(_hwndDialog, WM_SHOWOURSELVES, 0, 0));
Handle_LogonHideUI();
return(true);
}
// --------------------------------------------------------------------------
// CreateLogonHost
//
// Arguments: hwndDialog = HWND to Win32 GINA dialog.
// iDialogType = Type of dialog.
//
// Returns: int
//
// Purpose: This function handles the actual creation and allocation of
// resources for handling the friendly UI dialog. It behaves
// differently depending on whether the dialog is in
// WlxLoggedOutSAS mode or return to welcome mode.
//
// History: 2001-01-11 vtan created
// --------------------------------------------------------------------------
int CreateLogonHost (HWND hwndDialog, int iResult, int iDialogType)
{
if (g_pLogonDialogLock != NULL)
{
CLogonDialog *pLogonDialog;
CUIHost *pUIHost;
g_pLogonDialogLock->Acquire();
pUIHost = reinterpret_cast<CUIHost*>(_Shell_LogonStatus_GetUIHost());
if (pUIHost != NULL)
{
ASSERTMSG(g_pLogonDialog == NULL, "static CLogonDialog already exists in _Shell_LogonDialog__Init");
g_pLogonDialog = pLogonDialog = new CLogonDialog(hwndDialog, pUIHost, iDialogType);
pUIHost->Release();
}
else
{
pLogonDialog = NULL;
}
if (pLogonDialog != NULL)
{
NTSTATUS status;
// Add a reference to prevent the object from being destroyed.
pLogonDialog->AddRef();
pLogonDialog->ChangeWindowTitle();
// CLogonDialog::StartUIHost can enter a wait state. Release the lock to
// allow g_pLogonDialog to be modified externally by SignalAbnormalTermination
// should the UI host fail and the callback on the IOCompletion port be executed.
g_pLogonDialogLock->Release();
status = pLogonDialog->StartUIHost();
g_pLogonDialogLock->Acquire();
// Make sure to re-acquire the lock so that reading from g_pLogonDialog
// is consistent. If failure happens after this then it'll just wait.
// Then check to see the result of CLogonDialog::StartUIHost and the
// global g_pLogonDialog. If both of these are valid then everything
// is set for the external host. Otherwise bail and show classic UI.
if (NT_SUCCESS(status) && (g_pLogonDialog != NULL))
{
iResult = SHELL_LOGONDIALOG_EXTERNALHOST;
pLogonDialog->Handle_WM_INITDIALOG();
}
else
{
pLogonDialog->Handle_WM_SHOWOURSELVES();
_Shell_LogonDialog_Destroy();
}
pLogonDialog->Release();
}
g_pLogonDialogLock->Release();
}
return(iResult);
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_StaticInitialize
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: Initialize the critical section for g_pLogonDialog.
//
// History: 2001-04-27 vtan created
// --------------------------------------------------------------------------
EXTERN_C NTSTATUS _Shell_LogonDialog_StaticInitialize (void)
{
NTSTATUS status;
ASSERTMSG(g_pLogonDialogLock == NULL, "g_pLogonDialogLock already exists in _Shell_LogonDialog_StaticInitialize");
g_pLogonDialogLock = new CCriticalSection;
if (g_pLogonDialogLock != NULL)
{
status = g_pLogonDialogLock->Status();
if (!NT_SUCCESS(status))
{
delete g_pLogonDialogLock;
g_pLogonDialogLock = NULL;
}
}
else
{
status = STATUS_NO_MEMORY;
}
return(status);
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_StaticTerminate
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: Delete the critical section for g_pLogonDialog.
//
// History: 2001-04-27 vtan created
// --------------------------------------------------------------------------
EXTERN_C NTSTATUS _Shell_LogonDialog_StaticTerminate (void)
{
if (g_pLogonDialogLock != NULL)
{
delete g_pLogonDialogLock;
g_pLogonDialogLock = NULL;
}
return(STATUS_SUCCESS);
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_Init
//
// Arguments: hwndDialog = HWND to Win32 GINA dialog.
// iDialogType = Type of dialog.
//
// Returns: int
//
// Purpose: This function is invoked from the WM_INITDIALOG handler of
// the Win32 dialog. It determines whether the consumer windows
// UI host should handle the logon by checking a few settings.
//
// If this is consumer windows then it checks for a single user
// with no password (actually attempting to log them on). If this
// succeeds then this information is set into the Win32 dialog
// and the direction to go to logon is returned.
//
// Otherwise it creates the required object to handle an external
// UI host and starts it. If that succeeds then the UI host code
// is returned.
//
// This function is only invoked in the workgroup case.
//
// History: 2000-02-04 vtan created
// 2000-03-06 vtan added safe mode handler
// --------------------------------------------------------------------------
EXTERN_C int _Shell_LogonDialog_Init (HWND hwndDialog, int iDialogType)
{
int iResult;
iResult = SHELL_LOGONDIALOG_NONE;
if (iDialogType == SHELL_LOGONDIALOG_LOGGEDOFF)
{
bool fIsRemote, fIsSessionZero;
fIsRemote = (GetSystemMetrics(SM_REMOTESESSION) != 0);
fIsSessionZero = (NtCurrentPeb()->SessionId == 0);
if ((!fIsRemote || fIsSessionZero || CSystemSettings::IsForceFriendlyUI()) && CSystemSettings::IsFriendlyUIActive())
{
// There was no wait for the UI host to signal it was ready.
// Before switching to logon mode wait for the host.
if (_Shell_LogonStatus_WaitForUIHost() != FALSE)
{
// If the wait succeeds then go and send the UI host to logon mode.
if (g_fFirstLogon && fIsSessionZero)
{
WCHAR *pszUsername;
pszUsername = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, (UNLEN + sizeof('\0')) * sizeof(WCHAR)));
if (pszUsername != NULL)
{
WCHAR *pszDomain;
pszDomain = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, (DNLEN + sizeof('\0')) * sizeof(WCHAR)));
if (pszDomain != NULL)
{
// Check for single user with no password. Handle this
// case by filling in the buffers passed to us and return
// _Shell_LOGONDIALOG_LOGON directing a logon attempt.
if (ShellIsSingleUserNoPassword(pszUsername, pszDomain))
{
CLogonDialog::SetTextFields(hwndDialog, pszUsername, pszDomain, L"");
iResult = SHELL_LOGONDIALOG_LOGON;
_Shell_LogonStatus_SetStateLoggedOn();
}
(HLOCAL)LocalFree(pszDomain);
}
(HLOCAL)LocalFree(pszUsername);
}
}
// Otherwise attempt to start the UI host. If this
// is successful then return the external host
// code back to the caller which will hide the dialog.
if (iResult == SHELL_LOGONDIALOG_NONE)
{
iResult = CreateLogonHost(hwndDialog, iResult, iDialogType);
}
}
}
// Once this point is reached don't ever check again.
g_fFirstLogon = false;
}
else if ((iDialogType == SHELL_LOGONDIALOG_RETURNTOWELCOME) || (iDialogType == SHELL_LOGONDIALOG_RETURNTOWELCOME_UNLOCK))
{
iResult = CreateLogonHost(hwndDialog, iResult, iDialogType);
}
return(iResult);
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_Destroy
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Release memory and/or resources occupied by the UI host
// handling and reset it.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonDialog_Destroy (void)
{
if (g_pLogonDialogLock != NULL)
{
CSingleThreadedExecution lock(*g_pLogonDialogLock);
if (g_pLogonDialog != NULL)
{
g_pLogonDialog->Handle_WM_DESTROY();
g_pLogonDialog->EndUIHost();
g_pLogonDialog->Release();
g_pLogonDialog = NULL;
}
}
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_UIHostActive
//
// Arguments: <none>
//
// Returns: BOOL
//
// Purpose: Returns whether the UI host has been activated. This will
// prevent an incorrect password from stealing focus from the
// UI host. The Win32 GINA dialog will try to set focus in that
// case but this is not desired.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
EXTERN_C BOOL _Shell_LogonDialog_UIHostActive (void)
{
return((g_pLogonDialog != NULL) && !g_pLogonDialog->IsClassicLogonMode());
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_Cancel
//
// Arguments: <none>
//
// Returns: BOOL
//
// Purpose: Returns whether the cancel button was handled by the UI host.
// This is used when CAD x 2 needs to be cancelled and the UI
// host restored.
//
// History: 2001-02-01 vtan created
// --------------------------------------------------------------------------
EXTERN_C BOOL _Shell_LogonDialog_Cancel (void)
{
return((g_pLogonDialog != NULL) && g_pLogonDialog->RevertClassicLogonMode());
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_DlgProc
//
// Arguments: See the platform SDK under DialogProc.
//
// Returns: BOOL
//
// Purpose: The Win32 GINA dialog code calls this function for uiMessage
// parameters it doesn't understand. This gives us the chance to
// add messages that only we understand and process them.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
EXTERN_C BOOL _Shell_LogonDialog_DlgProc (HWND hwndDialog, UINT uiMessage, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(hwndDialog);
BOOL fResult;
fResult = FALSE;
if (g_pLogonDialog != NULL)
{
switch (uiMessage)
{
case WM_HIDEOURSELVES:
g_pLogonDialog->Handle_WM_HIDEOURSELVES();
fResult = TRUE;
break;
case WM_SHOWOURSELVES:
g_pLogonDialog->Handle_WM_SHOWOURSELVES();
fResult = TRUE;
break;
case WM_LOGONSERVICEREQUEST:
fResult = g_pLogonDialog->Handle_WM_LOGONSERVICEREQUEST(HIWORD(wParam), reinterpret_cast<void*>(lParam), LOWORD(wParam));
break;
case WLX_WM_SAS:
g_pLogonDialog->Handle_WLX_WM_SAS(wParam);
fResult = TRUE;
break;
case WM_POWERBROADCAST:
fResult = g_pLogonDialog->Handle_WM_POWERBROADCAST(wParam);
break;
default:
break;
}
}
return(fResult);
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_LogonDisplayError
//
// Arguments: status = NTSTATUS of logon request.
//
// Returns: BOOL
//
// Purpose: Passes the NTSTATUS onto the CLogonDialog handler if there is
// one present.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
EXTERN_C BOOL _Shell_LogonDialog_LogonDisplayError (NTSTATUS status, NTSTATUS subStatus)
{
BOOL fResult;
fResult = TRUE;
if (g_pLogonDialog != NULL)
{
fResult = g_pLogonDialog->Handle_LogonDisplayError(status, subStatus);
}
else
{
_Shell_LogonStatus_Hide();
}
return(fResult);
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_LogonCompleted
//
// Arguments: iDialogResult = Dialog result code.
// pszUsername = User name that tried to log on.
// pszDomain = Domain of user.
//
// Returns: BOOL
//
// Purpose: Passes the dialog result code onto the CLogonDialog handler
// if there is one present.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonDialog_LogonCompleted (INT_PTR iDialogResult, const WCHAR *pszUsername, const WCHAR *pszDomain)
{
if (g_pLogonDialog != NULL)
{
g_pLogonDialog->Handle_LogonCompleted(iDialogResult, pszUsername, pszDomain);
}
else
{
_Shell_LogonStatus_Show();
}
g_fFirstLogon = false;
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_ShuttingDown
//
// Arguments: iDialogResult = Dialog result code.
// pszUsername = User name that tried to log on.
// pszDomain = Domain of user.
//
// Returns: BOOL
//
// Purpose: Passes the dialog result code onto the CLogonDialog handler
// if there is one present.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonDialog_ShuttingDown (void)
{
if (g_pLogonDialog != NULL)
{
g_pLogonDialog->Handle_ShuttingDown();
}
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_ShowUIHost
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Show the external UI host if present. Otherwise do nothing.
//
// History: 2000-06-26 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonDialog_ShowUIHost (void)
{
if (g_pLogonDialog != NULL)
{
g_pLogonDialog->Handle_LogonShowUI();
}
}
// --------------------------------------------------------------------------
// ::_Shell_LogonDialog_HideUIHost
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Hide the external UI host if present. Otherwise do nothing.
//
// History: 2000-03-08 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonDialog_HideUIHost (void)
{
if (g_pLogonDialog != NULL)
{
g_pLogonDialog->Handle_LogonHideUI();
}
}