|
|
// --------------------------------------------------------------------------
// 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(); } }
|