|
|
// --------------------------------------------------------------------------
// Module Name: CWLogonStatus.cpp
//
// Copyright (c) 2000, Microsoft Corporation
//
// File that contains implementation for status UI hosting by an external
// process.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
#include "StandardHeader.h"
#include <msginaexports.h>
#include "Access.h"
#include "GinaIPC.h"
#include "LogonWait.h"
#include "SingleThreadedExecution.h"
#include "StatusCode.h"
#include "SystemSettings.h"
#include "UIHost.h"
// --------------------------------------------------------------------------
// CLogonStatus
//
// Purpose: C++ class to handle logon status external process for consumer
// windows.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
class CLogonStatus : public ILogonExternalProcess { private: CLogonStatus (void); public: CLogonStatus (const TCHAR *pszParameter); ~CLogonStatus (void);
NTSTATUS Start (bool fWait); CUIHost* GetUIHost (void); static bool IsStatusWindow (HWND hwnd);
bool WaitForUIHost (void); void ShowStatusMessage (const WCHAR *pszMessage); void SetStateStatus (int iCode); void SetStateLogon (int iCode); void SetStateLoggedOn (void); void SetStateHide (void); void SetStateEnd (bool fSendMessage); void NotifyWait (void); void NotifyNoAnimations (void); void SelectUser (const WCHAR *pszUsername, const WCHAR *pszDomain); void InteractiveLogon (const WCHAR *pszUsername, const WCHAR *pszDomain, WCHAR *pszPassword); HANDLE ResetReadyEvent (void); bool IsSuspendAllowed (void) const; void ShowUIHost (void); void HideUIHost (void); bool IsUIHostHidden (void) const; public: virtual bool AllowTermination (DWORD dwExitCode); virtual NTSTATUS SignalAbnormalTermination (void); virtual NTSTATUS SignalRestart (void); virtual NTSTATUS LogonRestart (void); private: bool IsUIHostReady (void) const; void SendToUIHost (WPARAM wParam, LPARAM lParam); void UIHostReadySignal (void); static void CALLBACK CB_UIHostReadySignal (void *pV, BOOLEAN fTimerOrWaitFired); static void CALLBACK CB_UIHostAbnormalTermination (ULONG_PTR dwParam); private: DWORD _dwThreadID; bool _fRegisteredWait; HANDLE _hEvent; HANDLE _hWait; int _iState, _iCode, _iStatePending; WPARAM _waitWPARAM; LPARAM _waitLPARAM; CUIHost* _pUIHost; CLogonWait _logonWait; };
CCriticalSection* g_pLogonStatusLock = NULL; CLogonStatus* g_pLogonStatus = NULL;
// --------------------------------------------------------------------------
// CLogonStatus::CLogonStatus
//
// Arguments: pszParameter = Parameter to pass to status UI host.
//
// Returns: <none>
//
// Purpose: Constructor for CLogonStatus. This gets the status UI host
// from the registry and assigns the given parameter into the
// object. Create a named event which SHGINA knows about and
// will signal once the ILogonStatusHost class has been
// instantiated.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
CLogonStatus::CLogonStatus (const TCHAR *pszParameter) : _dwThreadID(0), _fRegisteredWait(false), _hEvent(NULL), _hWait(NULL), _iState(UI_STATE_STATUS), _iCode(0), _iStatePending(0), _waitWPARAM(0), _waitLPARAM(0), _pUIHost(NULL)
{ TCHAR szRawHostCommandLine[MAX_PATH];
if (ERROR_SUCCESS == CSystemSettings::GetUIHost(szRawHostCommandLine)) { _pUIHost = new CUIHost(szRawHostCommandLine); if (_pUIHost != NULL) { _pUIHost->SetInterface(this); _pUIHost->SetParameter(pszParameter); } }
SECURITY_ATTRIBUTES securityAttributes;
// Build a security descriptor for the event that allows:
// S-1-5-18 EVENT_ALL_ACCESS
// S-1-5-32-544 SYNCHRONIZE | READ_CONTROL | EVENT_QUERY_STATE
static SID_IDENTIFIER_AUTHORITY s_SecurityNTAuthority = SECURITY_NT_AUTHORITY;
static const CSecurityDescriptor::ACCESS_CONTROL s_AccessControl[] = { { &s_SecurityNTAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, EVENT_ALL_ACCESS }, { &s_SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, SYNCHRONIZE | READ_CONTROL | EVENT_QUERY_STATE } };
securityAttributes.nLength = sizeof(securityAttributes); securityAttributes.lpSecurityDescriptor = CSecurityDescriptor::Create(ARRAYSIZE(s_AccessControl), s_AccessControl); securityAttributes.bInheritHandle = FALSE; _hEvent = CreateEvent(&securityAttributes, TRUE, FALSE, TEXT("msgina: StatusHostReadyEvent")); ReleaseMemory(securityAttributes.lpSecurityDescriptor); }
// --------------------------------------------------------------------------
// CLogonStatus::~CLogonStatus
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Destructor for CLogonStatus. Releases references.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
CLogonStatus::~CLogonStatus (void)
{ ASSERTMSG(_hWait == NULL, "Resend wait object not released in CLogonStatus::~CLogonStatus"); ReleaseHandle(_hEvent); ASSERTMSG(_iState == UI_STATE_END, "State must be UI_STATE_END in CLogonStatus::~CLogonStatus"); if (_pUIHost != NULL) { _pUIHost->Release(); _pUIHost = NULL; } }
// --------------------------------------------------------------------------
// CLogonStatus::Start
//
// Arguments: fWait = Wait for status host to signal ready.
//
// Returns: NTSTATUS
//
// Purpose: Starts the status UI host. Don't wait for the UI host. There
// is a mechanism that can queue a message if the UI host window
// cannot be found.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
NTSTATUS CLogonStatus::Start (bool fWait)
{ NTSTATUS status;
if (_pUIHost != NULL) { (HANDLE)ResetReadyEvent(); status = _pUIHost->Start(); if (NT_SUCCESS(status)) { _dwThreadID = GetCurrentThreadId(); if (fWait || _pUIHost->WaitRequired()) { if (!WaitForUIHost()) { status = STATUS_UNSUCCESSFUL; } } } } else { status = STATUS_UNSUCCESSFUL; } return(status); }
// --------------------------------------------------------------------------
// CLogonStatus::GetUIHost
//
// Arguments: <none>
//
// Returns: CUIHost*
//
// Purpose: Returns a reference to the UIHost object held internally.
// The reference belongs to the caller and must be released.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
CUIHost* CLogonStatus::GetUIHost (void)
{ if (_pUIHost != NULL) { _pUIHost->AddRef(); } return(_pUIHost); }
// --------------------------------------------------------------------------
// CLogonStatus::IsStatusWindow
//
// Arguments: hwnd = HWND to check.
//
// Returns: bool
//
// Purpose: Returns whether the given HWND is the status window.
//
// History: 2000-06-26 vtan created
// --------------------------------------------------------------------------
bool CLogonStatus::IsStatusWindow (HWND hwnd)
{ TCHAR szWindowClass[256];
return((GetClassName(hwnd, szWindowClass, ARRAYSIZE(szWindowClass)) != 0) && (lstrcmpi(STATUS_WINDOW_CLASS_NAME, szWindowClass) == 0)); }
// --------------------------------------------------------------------------
// CLogonStatus::WaitForUIHost
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Waits on the named event that the UI host signals when it's
// initialized. Typically this happens very quickly but we don't
// wait on it when starting up the UI host.
//
// History: 2000-09-10 vtan created
// --------------------------------------------------------------------------
bool CLogonStatus::WaitForUIHost (void)
{ bool fResult;
fResult = true; ASSERTMSG(_hEvent != NULL, "No UI host named event to wait on in CLogonStatus::WaitForUIHost"); if (!IsUIHostReady()) { DWORD dwWaitResult;
#ifdef DBG
DWORD dwWaitStart, dwWaitEnd;
dwWaitStart = (WAIT_TIMEOUT == WaitForSingleObject(_hEvent, 0)) ? GetTickCount() : 0; #endif /* DBG */
do { dwWaitResult = WaitForSingleObject(_hEvent, 0); if (dwWaitResult != WAIT_OBJECT_0) { dwWaitResult = MsgWaitForMultipleObjectsEx(1, &_hEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE); if (dwWaitResult == WAIT_OBJECT_0 + 1) { MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE) { (BOOL)TranslateMessage(&msg); (LRESULT)DispatchMessage(&msg); } } } } while ((dwWaitResult == WAIT_OBJECT_0 + 1) && (dwWaitResult != WAIT_IO_COMPLETION)); #ifdef DBG
dwWaitEnd = GetTickCount(); if ((dwWaitStart != 0) && ((dwWaitEnd - dwWaitStart) != 0)) { char szBuffer[256];
wsprintfA(szBuffer, "waited %d ticks for UI host", dwWaitEnd - dwWaitStart); INFORMATIONMSG(szBuffer); } #endif /* DBG */
fResult = (dwWaitResult != WAIT_IO_COMPLETION); } return(fResult); }
// --------------------------------------------------------------------------
// CLogonStatus::ShowStatusMessage
//
// Arguments: pszMessage = Unicode string message to display.
//
// Returns: <none>
//
// Purpose: Tells the UI host to display the given string message. Puts
// the string directly inside the status host process and tells
// the process where in its address space to find the string.
// The string is limited to 256 characters.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::ShowStatusMessage (const WCHAR *pszMessage)
{ if (NT_SUCCESS(_pUIHost->PutString(pszMessage))) { SendToUIHost(UI_DISPLAY_STATUS, reinterpret_cast<LONG_PTR>(_pUIHost->GetDataAddress())); } }
// --------------------------------------------------------------------------
// CLogonStatus::SetStateStatus
//
// Arguments: iCode = Magic code number for lock.
//
// Returns: <none>
//
// Purpose: Tells the status UI host to go into status state.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::SetStateStatus (int iCode)
{ _iStatePending = UI_STATE_STATUS; if (WaitForUIHost() && (_iState != UI_STATE_STATUS)) { SendToUIHost(UI_STATE_STATUS, iCode); _iState = UI_STATE_STATUS; _iCode = iCode; } _iStatePending = UI_STATE_NONE; }
// --------------------------------------------------------------------------
// CLogonStatus::SetStateLogon
//
// Arguments: iCode = Magic code number for lock.
//
// Returns: <none>
//
// Purpose: Tells the status UI host to go into logon state.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::SetStateLogon (int iCode)
{ _iStatePending = UI_STATE_LOGON; if (WaitForUIHost() && (iCode == _iCode)) { SendToUIHost(UI_STATE_LOGON, iCode); _iState = UI_STATE_LOGON; _iCode = 0; } _iStatePending = UI_STATE_NONE; }
// --------------------------------------------------------------------------
// CLogonStatus::SetStateLoggedOn
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Tells the status UI host to go into logged on state.
//
// History: 2000-05-24 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::SetStateLoggedOn (void)
{ _iStatePending = UI_STATE_STATUS; if (WaitForUIHost()) { SendToUIHost(UI_STATE_LOGGEDON, 0); _iState = UI_STATE_STATUS; } _iStatePending = UI_STATE_NONE; }
// --------------------------------------------------------------------------
// CLogonStatus::SetStateHide
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Tells the status UI host to hide itself.
//
// History: 2001-01-08 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::SetStateHide (void)
{ _iStatePending = UI_STATE_HIDE; if (WaitForUIHost()) { SendToUIHost(UI_STATE_HIDE, 0); _iState = UI_STATE_HIDE; } _iStatePending = UI_STATE_NONE; }
// --------------------------------------------------------------------------
// CLogonStatus::SetStateEnd
//
// Arguments: fSendMessage = Send message to UI host or not.
//
// Returns: <none>
//
// Purpose: Tells the status UI host to end and terminate itself.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::SetStateEnd (bool fSendMessage)
{ bool fHostAlive; HANDLE hWait;
_iStatePending = UI_STATE_END;
// When going into end mode if there's a wait registered then
// unregister it. This will release an outstanding reference.
// A re-register should never happen but this is set just in case.
_fRegisteredWait = true; hWait = InterlockedExchangePointer(&_hWait, NULL); if (hWait != NULL) { if (UnregisterWait(hWait) != FALSE) { Release(); } } if (fSendMessage) { fHostAlive = WaitForUIHost(); } else { fHostAlive = true; } if (fHostAlive) { if (_pUIHost != NULL) { _pUIHost->SetInterface(NULL); } if (fSendMessage) { SendToUIHost(UI_STATE_END, 0); } _iState = UI_STATE_END; } _iStatePending = UI_STATE_NONE; }
// --------------------------------------------------------------------------
// CLogonStatus::NotifyWait
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Tells the status UI host to display a title that the system
// is shutting down.
//
// History: 2000-07-14 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::NotifyWait (void)
{ SendToUIHost(UI_NOTIFY_WAIT, 0); }
// --------------------------------------------------------------------------
// CLogonStatus::NotifyNoAnimations
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Tells the status UI host to no longer perform animations.
//
// History: 2001-03-21 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::NotifyNoAnimations (void)
{ SendToUIHost(UI_SET_ANIMATIONS, 0); }
// --------------------------------------------------------------------------
// CLogonStatus::SelectUser
//
// Arguments: pszUsername = User name to select.
//
// Returns: <none>
//
// Purpose: Tells the status UI host to select the user by the given
// logon name.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::SelectUser (const WCHAR *pszUsername, const WCHAR *pszDomain)
{ LOGONIPC_USERID logonIPC;
(WCHAR*)lstrcpyW(logonIPC.wszUsername, pszUsername); (WCHAR*)lstrcpyW(logonIPC.wszDomain, pszDomain); if (NT_SUCCESS(_pUIHost->PutData(&logonIPC, sizeof(logonIPC)))) { SendToUIHost(UI_SELECT_USER, reinterpret_cast<LONG_PTR>(_pUIHost->GetDataAddress())); } }
// --------------------------------------------------------------------------
// CLogonStatus::InteractiveLogon
//
// Arguments: pszUsername = Username to logon.
// pszDomain = Domain to logon.
// pszPassword = Password to use.
//
// Returns: <none>
//
// Purpose: Tell the status host to log the specified user on.
//
// History: 2001-01-12 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::InteractiveLogon (const WCHAR *pszUsername, const WCHAR *pszDomain, WCHAR *pszPassword)
{ LOGONIPC_CREDENTIALS logonIPCCredentials;
(WCHAR*)lstrcpyW(logonIPCCredentials.userID.wszUsername, pszUsername); (WCHAR*)lstrcpyW(logonIPCCredentials.userID.wszDomain, pszDomain); (WCHAR*)lstrcpyW(logonIPCCredentials.wszPassword, pszPassword); ZeroMemory(pszPassword, (lstrlenW(pszPassword) + sizeof('\0'))* sizeof(WCHAR)); if (NT_SUCCESS(_pUIHost->PutData(&logonIPCCredentials, sizeof(logonIPCCredentials)))) { SendToUIHost(UI_INTERACTIVE_LOGON, reinterpret_cast<LONG_PTR>(_pUIHost->GetDataAddress())); } }
// --------------------------------------------------------------------------
// CLogonStatus::ResetReadyEvent
//
// Arguments: <none>
//
// Returns: HANDLE
//
// Purpose: Reset the UI host ready event. A new instance will set this
// event. Use this in UI host failure.
//
// History: 2001-01-09 vtan created
// --------------------------------------------------------------------------
HANDLE CLogonStatus::ResetReadyEvent (void)
{ TBOOL(ResetEvent(_hEvent)); return(_hEvent); }
// --------------------------------------------------------------------------
// CLogonStatus::IsSuspendAllowed
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether the UI host allows suspending of the computer.
// This is true if in the logon state or in the status (locked)
// state.
//
// History: 2000-08-21 vtan created
// --------------------------------------------------------------------------
bool CLogonStatus::IsSuspendAllowed (void) const
{ return(((_iState == UI_STATE_STATUS) && (_iCode != 0)) || (_iStatePending == UI_STATE_LOGON) || (_iState == UI_STATE_LOGON) || (_iState == UI_STATE_HIDE)); }
// --------------------------------------------------------------------------
// CLogonStatus::ShowUIHost
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Shows the UI host.
//
// History: 2001-03-05 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::ShowUIHost (void)
{ _pUIHost->Show(); }
// --------------------------------------------------------------------------
// CLogonStatus::HideUIHost
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Hides the UI host.
//
// History: 2001-03-05 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::HideUIHost (void)
{ _pUIHost->Hide(); }
// --------------------------------------------------------------------------
// CLogonStatus::IsUIHostHidden
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Returns whether the UI host is hidden.
//
// History: 2001-03-05 vtan created
// --------------------------------------------------------------------------
bool CLogonStatus::IsUIHostHidden (void) const
{ return(_pUIHost->IsHidden()); }
// --------------------------------------------------------------------------
// CLogonStatus::AllowTermination
//
// Arguments: dwExitCode = Exit code of host process.
//
// Returns: bool
//
// Purpose: Returns whether the host process is allowed to terminate
// given the exit code passed in.
//
// Currently the host process is not allowed to terminate.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
bool CLogonStatus::AllowTermination (DWORD dwExitCode)
{ UNREFERENCED_PARAMETER(dwExitCode);
return(false); }
// --------------------------------------------------------------------------
// CLogonStatus::SignalAbnormalTermination
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: Handles abnormal termination of host process.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
NTSTATUS CLogonStatus::SignalAbnormalTermination (void)
{ HANDLE hThread;
TSTATUS(_logonWait.Cancel()); hThread = OpenThread(THREAD_SET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, _dwThreadID); if (hThread != NULL) { (BOOL)QueueUserAPC(CB_UIHostAbnormalTermination, hThread, reinterpret_cast<ULONG_PTR>(this)); TBOOL(CloseHandle(hThread)); } _Shell_LogonStatus_Destroy(HOST_END_FAILURE); return(STATUS_SUCCESS); }
// --------------------------------------------------------------------------
// CLogonStatus::SignalRestart
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: Function to reset the ready event and set the UI host into
// status state. This is invoked when the UI host is restarted
// after a failure.
//
// History: 2001-01-09 vtan created
// --------------------------------------------------------------------------
NTSTATUS CLogonStatus::SignalRestart (void)
{ (HANDLE)ResetReadyEvent(); return(_logonWait.Register(_hEvent, this)); }
// --------------------------------------------------------------------------
// CLogonStatus::LogonRestart
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose:
//
// History: 2001-02-21 vtan created
// --------------------------------------------------------------------------
NTSTATUS CLogonStatus::LogonRestart (void)
{ SetStateStatus(0); return(STATUS_SUCCESS); }
// --------------------------------------------------------------------------
// CLogonStatus::IsUIHostReady
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether the UI host is ready.
//
// History: 2000-09-11 vtan created
// --------------------------------------------------------------------------
bool CLogonStatus::IsUIHostReady (void) const
{ ASSERTMSG(_hEvent != NULL, "No UI host named event to wait on in CLogonStatus::IsUIHostReady"); return(WAIT_OBJECT_0 == WaitForSingleObject(_hEvent, 0)); }
// --------------------------------------------------------------------------
// CLogonStatus::SendToUIHost
//
// Arguments: wParam = WPARAM to send to UI host.
// lParam = LPARAM to send to UI host.
//
// Returns: <none>
//
// Purpose: Finds the status window created by SHGINA and sends the
// message to it. That window turns around and sends the message
// to the UI host. This allows communication implemenation method
// to change without forcing the UI host to be rebuilt.
//
// History: 2000-05-11 vtan created
// 2000-09-11 vtan uses PostMessage not SendMessage
// --------------------------------------------------------------------------
void CLogonStatus::SendToUIHost (WPARAM wParam, LPARAM lParam)
{ HWND hwnd;
if (IsUIHostReady()) { hwnd = FindWindow(STATUS_WINDOW_CLASS_NAME, NULL); } else { hwnd = NULL; }
if (hwnd != NULL) { HANDLE hWait;
// Don't allow any registrations if we've found it.
_fRegisteredWait = true; hWait = InterlockedExchangePointer(&_hWait, NULL); if (hWait != NULL) { if (UnregisterWait(hWait) != FALSE) {
// If sucesssfully releasing the hWait we need to call release.
Release(); } } TBOOL(PostMessage(hwnd, WM_UISERVICEREQUEST, wParam, lParam)); } else if (!_fRegisteredWait) {
// Cannot find the UI host window. It's probably still getting
// its act together. Queue this post message for a callback when
// the event is signaled if a register has not already been
// made. If one has then just change the parameters.
// Add a reference here. The callback will release it. If the
// register on the wait failed the release the reference.
if (_hWait == NULL) { HANDLE hWait;
AddRef(); if (RegisterWaitForSingleObject(&hWait, _hEvent, CB_UIHostReadySignal, this, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE) != FALSE) { if (InterlockedCompareExchangePointer(&_hWait, hWait, NULL) == NULL) { _fRegisteredWait = true; } else {
// Someone else beat us to registering (should never happen)
(BOOL)UnregisterWait(hWait); Release(); } } else { Release(); } } _waitWPARAM = wParam; _waitLPARAM = lParam; } }
// --------------------------------------------------------------------------
// CLogonStatus::UIHostReadySignal
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Callback invoked when the UI host signals it's ready. This
// function unregisters the wait and resend the status message
// to the UI host.
//
// History: 2000-09-10 vtan created
// --------------------------------------------------------------------------
void CLogonStatus::UIHostReadySignal (void)
{ HANDLE hWait;
hWait = InterlockedExchangePointer(&_hWait, NULL); if (hWait != NULL) { TBOOL(UnregisterWait(hWait)); } SendToUIHost(_waitWPARAM, _waitLPARAM); }
// --------------------------------------------------------------------------
// CLogonStatus::CB_UIHostReadySignal
//
// Arguments: See the platform SDK under WaitOrTimerCallback.
//
// Returns: <none>
//
// Purpose: Callback entry point for registered event wait.
//
// History: 2000-09-10 vtan created
// --------------------------------------------------------------------------
void CALLBACK CLogonStatus::CB_UIHostReadySignal (void *pV, BOOLEAN fTimerOrWaitFired)
{ UNREFERENCED_PARAMETER(fTimerOrWaitFired);
CLogonStatus *pThis;
pThis = reinterpret_cast<CLogonStatus*>(pV); if (pThis != NULL) { pThis->UIHostReadySignal(); } pThis->Release(); }
// --------------------------------------------------------------------------
// CLogonStatus::CB_UIHostAbnormalTermination
//
// Arguments: See the platform SDK under APCProc.
//
// Returns: <none>
//
// Purpose: Callback entry point for queued APC on abnormal termination.
//
// History: 2001-02-19 vtan created
// --------------------------------------------------------------------------
void CALLBACK CLogonStatus::CB_UIHostAbnormalTermination (ULONG_PTR dwParam)
{ UNREFERENCED_PARAMETER(dwParam); }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_StaticInitialize
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: Initialize the critical section for g_pLogonStatus.
//
// History: 2001-06-11 vtan created
// --------------------------------------------------------------------------
EXTERN_C NTSTATUS _Shell_LogonStatus_StaticInitialize (void)
{ NTSTATUS status;
ASSERTMSG(g_pLogonStatusLock == NULL, "g_pLogonStatusLock already exists in _Shell_LogonStatus_StaticInitialize"); g_pLogonStatusLock = new CCriticalSection; if (g_pLogonStatusLock != NULL) { status = g_pLogonStatusLock->Status(); if (!NT_SUCCESS(status)) { delete g_pLogonStatusLock; g_pLogonStatusLock = NULL; } } else { status = STATUS_NO_MEMORY; } return(status); }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_StaticTerminate
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: Delete the critical section for g_pLogonStatus.
//
// History: 2001-06-11 vtan created
// --------------------------------------------------------------------------
EXTERN_C NTSTATUS _Shell_LogonStatus_StaticTerminate (void)
{ if (g_pLogonStatusLock != NULL) { delete g_pLogonStatusLock; g_pLogonStatusLock = NULL; } return(STATUS_SUCCESS); }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_Init
//
// Arguments: uiStartType = Start mode of status host.
//
// Returns: <none>
//
// Purpose: Creates the instance of CLogonStatus telling it to pass
// "/status" as the parameter to the UI host. It then starts
// the host if the object was created.
//
// The object is held globally.
//
// History: 2000-05-11 vtan created
// 2000-07-13 vtan add shutdown parameter.
// 2000-07-17 vtan changed to start type parameter.
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_Init (UINT uiStartType)
{ bool fIsRemote, fIsSessionZero;
fIsRemote = (GetSystemMetrics(SM_REMOTESESSION) != 0); fIsSessionZero = (NtCurrentPeb()->SessionId == 0); if ((!fIsRemote || fIsSessionZero || CSystemSettings::IsForceFriendlyUI()) && CSystemSettings::IsFriendlyUIActive()) { bool fWait; TCHAR szParameter[256];
if (g_pLogonStatusLock != NULL) { g_pLogonStatusLock->Acquire(); if (g_pLogonStatus == NULL) { (TCHAR*)lstrcpy(szParameter, TEXT(" /status")); if (HOST_START_SHUTDOWN == uiStartType) { (TCHAR*)lstrcat(szParameter, TEXT(" /shutdown")); fWait = true; } else if (HOST_START_WAIT == uiStartType) { (TCHAR*)lstrcat(szParameter, TEXT(" /wait")); fWait = true; } else { fWait = false; } g_pLogonStatus = new CLogonStatus(szParameter); if (g_pLogonStatus != NULL) { NTSTATUS status;
g_pLogonStatusLock->Release(); status = g_pLogonStatus->Start(fWait); g_pLogonStatusLock->Acquire(); if (!NT_SUCCESS(status) && (g_pLogonStatus != NULL)) { g_pLogonStatus->Release(); g_pLogonStatus = NULL; } } } else { g_pLogonStatus->SetStateStatus(0); if ((HOST_START_SHUTDOWN == uiStartType) || (HOST_START_WAIT == uiStartType)) { g_pLogonStatus->NotifyWait(); } } g_pLogonStatusLock->Release(); } } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_Destroy
//
// Arguments: uiEndType = End mode of status host.
//
// Returns: <none>
//
// Purpose: If the end type is hide then tell the status host to hide.
// Otherwise check the end type is terminate. In that case tell
// the status host to go away.
//
// History: 2000-05-11 vtan created
// 2001-01-09 vtan add end parameter
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_Destroy (UINT uiEndType)
{ if (g_pLogonStatusLock != NULL) { CSingleThreadedExecution lock(*g_pLogonStatusLock);
if (g_pLogonStatus != NULL) { switch (uiEndType) { case HOST_END_HIDE:
// HOST_END_HIDE: Is the UI host static? If so then hide it.
// Otherwise revert to start/stop mode (dynamic) and force the
// UI host to terminate.
if (CSystemSettings::IsUIHostStatic()) { g_pLogonStatus->SetStateHide(); break; } uiEndType = HOST_END_TERMINATE;
// If the the host is dynamic then set the type to
// HOST_END_TERMINATE and fall thru to this case so that
// the host is told to end.
case HOST_END_TERMINATE:
// HOST_END_TERMINATE: Force the UI host to terminate. This is
// used in circumstances where it must terminate such as we
// are terminating or the machine is shutting down.
g_pLogonStatus->SetStateEnd(true); break; case HOST_END_FAILURE:
// HOST_END_FAILURE: This is sent when the UI host failed to
// start and will not be restarted. This allows the interface
// reference to be deleted so that object reference count
// will reach zero and the memory will be released.
g_pLogonStatus->SetStateEnd(false); uiEndType = HOST_END_TERMINATE; break; default: DISPLAYMSG("Unknown uiEndType passed to _Shell_LogonStatus_Destroy"); break; } if (HOST_END_TERMINATE == uiEndType) { g_pLogonStatus->Release(); g_pLogonStatus = NULL; } } } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_Exists
//
// Arguments: <none>
//
// Returns: BOOL
//
// Purpose: Returns whether there is status host created.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
EXTERN_C BOOL _Shell_LogonStatus_Exists (void)
{ return(g_pLogonStatus != NULL); }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_IsStatusWindow
//
// Arguments: hwnd = HWND to check.
//
// Returns: BOOL
//
// Purpose: Returns whether the given HWND is the status HWND.
//
// History: 2000-06-26 vtan created
// --------------------------------------------------------------------------
EXTERN_C BOOL _Shell_LogonStatus_IsStatusWindow (HWND hwnd)
{ return(CLogonStatus::IsStatusWindow(hwnd)); }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_IsSuspendAllowed
//
// Arguments: <none>
//
// Returns: BOOL
//
// Purpose: Ask the status host (if present) if suspend is allowed.
//
// History: 2000-08-18 vtan created
// --------------------------------------------------------------------------
EXTERN_C BOOL _Shell_LogonStatus_IsSuspendAllowed (void)
{ return((g_pLogonStatus == NULL) || g_pLogonStatus->IsSuspendAllowed()); }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_WaitforUIHost
//
// Arguments: <none>
//
// Returns: BOOL
//
// Purpose: External C entry point to force the current thread to wait
// until the UI host signals it's ready. Returns whether the
// wait was successful or abandoned. Success is true. Abandoned
// or non-existant is false.
//
// History: 2000-09-10 vtan created
// 2001-02-19 vtan added return result
// --------------------------------------------------------------------------
EXTERN_C BOOL _Shell_LogonStatus_WaitForUIHost (void)
{ return((g_pLogonStatus != NULL) && g_pLogonStatus->WaitForUIHost()); }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_ShowStatusMessage
//
// Arguments: pszMessage = Unicode string to display.
//
// Returns: <none>
//
// Purpose: External C entry point to pass display string to status host.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_ShowStatusMessage (const WCHAR *pszMessage)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->ShowStatusMessage(pszMessage); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_SetStateStatus
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: External C entry point to tell the status host to go to status
// state.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_SetStateStatus (int iCode)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->SetStateStatus(iCode); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_SetStateLogon
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: External C entry point to tell the status host to go to logon
// state.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_SetStateLogon (int iCode)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->SetStateLogon(iCode); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_SetStateLoggedOn
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: External C entry point to tell the status host to go to
// logged on state.
//
// History: 2000-05-24 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_SetStateLoggedOn (void)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->SetStateLoggedOn(); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_SetStateHide
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: External C entry point to tell the status host to hide itself.
//
// History: 2001-01-08 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_SetStateHide (void)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->SetStateHide(); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_SetStateEnd
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: External C entry point to tell the status host to terminate.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_SetStateEnd (void)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->SetStateEnd(true); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_NotifyWait
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: External C entry point to tell the status host to display a
// title stating the system is preparing to shut down.
//
// History: 2000-07-14 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_NotifyWait (void)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->NotifyWait(); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_NotifyNoAnimations
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: External C entry point to tell the status host to no longer
// perform animations.
//
// History: 2001-03-21 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_NotifyNoAnimations (void)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->NotifyNoAnimations(); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_SelectUser
//
// Arguments: pszUsername = Username to select.
//
// Returns: <none>
//
// Purpose: External C entry point to tell the status host to select a
// specific user as being logged on.
//
// History: 2001-01-10 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_SelectUser (const WCHAR *pszUsername, const WCHAR *pszDomain)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->SelectUser(pszUsername, pszDomain); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_InteractiveLogon
//
// Arguments: pszUsername = Username to logon.
// pszDomain = Domain to logon.
// pszPassword = Password to use.
//
// Returns: <none>
//
// Purpose: External C entry point to tell the status host to log the
// specified user on.
//
// History: 2001-01-12 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_InteractiveLogon (const WCHAR *pszUsername, const WCHAR *pszDomain, WCHAR *pszPassword)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->InteractiveLogon(pszUsername, pszDomain, pszPassword); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_GetUIHost
//
// Arguments: <none>
//
// Returns: void*
//
// Purpose: External C entry point that returns a reference to the UI
// host object. This is returned as a void* because C doesn't
// understand C++ objects. The void* is cast to the appropriate
// type for use in CWLogonDialog.cpp so that it doesn't go and
// create a new instance of the object but increments the
// reference to this already existing object.
//
// History: 2000-05-11 vtan created
// --------------------------------------------------------------------------
EXTERN_C void* _Shell_LogonStatus_GetUIHost (void)
{ void *pResult;
if (g_pLogonStatus != NULL) { pResult = g_pLogonStatus->GetUIHost(); } else { pResult = NULL; } return(pResult); }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_ResetReadyEvent
//
// Arguments: <none>
//
// Returns: HANDLE
//
// Purpose: Resets the ready event in case of UI host failure.
//
// History: 2001-01-09 vtan created
// --------------------------------------------------------------------------
EXTERN_C HANDLE _Shell_LogonStatus_ResetReadyEvent (void)
{ HANDLE hEvent;
if (g_pLogonStatus != NULL) { hEvent = g_pLogonStatus->ResetReadyEvent(); } else { hEvent = NULL; } return(hEvent); }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_Show
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Shows the UI host.
//
// History: 2001-03-05 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_Show (void)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->ShowUIHost(); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_Hide
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Hides the UI host.
//
// History: 2001-03-05 vtan created
// --------------------------------------------------------------------------
EXTERN_C void _Shell_LogonStatus_Hide (void)
{ if (g_pLogonStatus != NULL) { g_pLogonStatus->HideUIHost(); } }
// --------------------------------------------------------------------------
// ::_Shell_LogonStatus_IsHidden
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Returns whether the UI host is hidden.
//
// History: 2001-03-05 vtan created
// --------------------------------------------------------------------------
EXTERN_C BOOL _Shell_LogonStatus_IsHidden (void)
{ return((g_pLogonStatus != NULL) && g_pLogonStatus->IsUIHostHidden()); }
|