|
|
// backend.cpp : Windows Logon application
//
// backend logic for communicating with SHGina and winlogon
#include "priv.h"
using namespace DirectUI;
#include "resource.h"
#include "backend.h"
#include "shgina.h"
#include "profileutil.h"
#include "uihostipc.h"
////////////////////////////////
#include "eballoon.h"
#define MAX_COMPUTERDESC_LENGTH 255
static WCHAR g_szGuestName[UNLEN + sizeof('\0')] = L"Guest"; #define TIMER_REFRESHTIPS 1014
#define TIMER_ANIMATEFLAG 1015
#define TOTAL_FLAG_FRAMES (FLAG_ANIMATION_COUNT * MAX_FLAG_FRAMES)
UINT_PTR g_puTimerId = 0; UINT_PTR g_puFlagTimerId = 0;
DWORD sTimerCount = 0;
extern CErrorBalloon g_pErrorBalloon; extern LogonFrame* g_plf; extern ILogonStatusHost *g_pILogonStatusHost;
const TCHAR CBackgroundWindow::s_szWindowClassName[] = TEXT("LogonUIBackgroundWindowClass");
// --------------------------------------------------------------------------
// CBackgroundWindow::CBackgroundWindow
//
// Arguments: hInstance = HINSTANCE of the process.
//
// Returns: <none>
//
// Purpose: Constructor for CBackgroundWindow. This registers the window
// class.
//
// History: 2001-03-27 vtan created
// --------------------------------------------------------------------------
CBackgroundWindow::CBackgroundWindow (HINSTANCE hInstance) : _hInstance(hInstance), _hwnd(NULL)
{ WNDCLASSEX wndClassEx;
ZeroMemory(&wndClassEx, sizeof(wndClassEx)); wndClassEx.cbSize = sizeof(wndClassEx); wndClassEx.lpfnWndProc = WndProc; wndClassEx.hInstance = hInstance; wndClassEx.lpszClassName = s_szWindowClassName; wndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW); _atom = RegisterClassEx(&wndClassEx); }
// --------------------------------------------------------------------------
// CBackgroundWindow::~CBackgroundWindow
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Destructor for CBackgroundWindow. This destroys the window
// and unregisters the window class.
//
// History: 2001-03-27 vtan created
// --------------------------------------------------------------------------
CBackgroundWindow::~CBackgroundWindow (void)
{ if (_hwnd != NULL) { (BOOL)DestroyWindow(_hwnd); } if (_atom != 0) { TBOOL(UnregisterClass(MAKEINTRESOURCE(_atom), _hInstance)); } }
// --------------------------------------------------------------------------
// CBackgroundWindow::Create
//
// Arguments: <none>
//
// Returns: HWND
//
// Purpose: Creates the window. It's created WS_EX_TOPMOST and covers the
// entire screen. It's not created on CHK builds of logonui.exe
//
// History: 2001-03-27 vtan created
// --------------------------------------------------------------------------
HWND CBackgroundWindow::Create (void)
{ HWND hwnd;
#if DEBUG
hwnd = NULL;
#else
hwnd = CreateWindowEx(0, s_szWindowClassName, NULL, WS_POPUP, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), NULL, NULL, _hInstance, this); if (hwnd != NULL) { (BOOL)ShowWindow(hwnd, SW_SHOW); TBOOL(SetForegroundWindow(hwnd)); (BOOL)EnableWindow(hwnd, FALSE); }
#endif
return(hwnd); }
// --------------------------------------------------------------------------
// CBackgroundWindow::WndProc
//
// Arguments: See the platform SDK under WindowProc.
//
// Returns: See the platform SDK under WindowProc.
//
// Purpose: WindowProc for the background window. This just passes the
// messages thru to DefWindowProc.
//
// History: 2001-03-27 vtan created
// --------------------------------------------------------------------------
LRESULT CALLBACK CBackgroundWindow::WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ LRESULT lResult; CBackgroundWindow *pThis;
pThis = reinterpret_cast<CBackgroundWindow*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); switch (uMsg) { case WM_CREATE: { CREATESTRUCT *pCreateStruct;
pCreateStruct = reinterpret_cast<CREATESTRUCT*>(lParam); pThis = reinterpret_cast<CBackgroundWindow*>(pCreateStruct->lpCreateParams); (LONG_PTR)SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis)); lResult = 0; break; } case WM_PAINT: { HDC hdcPaint; PAINTSTRUCT ps;
hdcPaint = BeginPaint(hwnd, &ps); TBOOL(FillRect(ps.hdc, &ps.rcPaint, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)))); TBOOL(EndPaint(hwnd, &ps)); lResult = 0; break; } default: lResult = DefWindowProc(hwnd, uMsg, wParam, lParam); break; } return(lResult); }
////////////////////////////////////////////////////////
// Logon Utilities
////////////////////////////////////////////////////////
////////////////////////////////////////
//
// TurnOffComputer
//
// Call SHGina to bring up the "Turn Off Computer" dialog and handle the request.
// In debug builds, holding down the shift key and clicking the turn off button
// will exit logonui.
//
// RETURNS
// HRESULT indicating whether it worked or not.
//
/////////////////////////////////////////
HRESULT TurnOffComputer() { ILocalMachine *pobjLocalMachine; HRESULT hr = CoCreateInstance(CLSID_ShellLocalMachine, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ILocalMachine, &pobjLocalMachine)); if (SUCCEEDED(hr)) { hr = pobjLocalMachine->TurnOffComputer(); pobjLocalMachine->Release(); } return hr; }
////////////////////////////////////////
//
// UndockComputer
//
// Tell SHGina to undock the computer
//
// RETURNS
// HRESULT indicating whether it worked or not.
//
/////////////////////////////////////////
HRESULT UndockComputer() { ILocalMachine *pobjLocalMachine; HRESULT hr = CoCreateInstance(CLSID_ShellLocalMachine, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ILocalMachine, &pobjLocalMachine)); if (SUCCEEDED(hr)) { hr = pobjLocalMachine->UndockComputer(); pobjLocalMachine->Release(); } return hr; }
////////////////////////////////////////
//
// CalcBalloonTargetLocation
//
// Given a DirectUI element, figure out a good place to have a balloon tip pointed to
// in parent window coordinates.
//
// RETURNS
// nothing
//
/////////////////////////////////////////
void CalcBalloonTargetLocation(HWND hwndParent, Element *pe, POINT *ppt) { Value* pv; BOOL fIsRTL = (GetWindowLong(hwndParent, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0;
DUIAssertNoMsg(pe); DUIAssertNoMsg(ppt);
// get the position of the link so we can target the balloon tip correctly
POINT pt = {0,0};
const SIZE *psize = pe->GetExtent(&pv); pt.y += psize->cy / 2;
if (psize->cx < 100) { pt.x += psize->cx / 2; } else { if (fIsRTL) { pt.x = (pt.x + psize->cx) - 50; } else { pt.x += 50; } }
pv->Release();
while (pe) { const POINT* ppt = pe->GetLocation(&pv); pt.x += ppt->x;
pt.y += ppt->y; pv->Release(); pe = pe->GetParent(); }
*ppt = pt; } ////////////////////////////////////////
//
// DetermineGuestAccountName
//
//
// Get the localized guest account name by matching the
// local list of user account SIDs for the guest RID.
// This code is lifted directly from msgina\userlist.cpp
// In the event of failure this is initialized to the english "Guest".
//
//
// RETURNS
// nothing.
//
/////////////////////////////////////////
void DetermineGuestAccountName() { NET_API_STATUS nasCode; DWORD dwPreferredSize, dwEntriesRead; NET_DISPLAY_USER *pNDU;
static const int iMaximumUserCount = 100;
dwPreferredSize = (sizeof(NET_DISPLAY_USER) + (3 * UNLEN) * iMaximumUserCount); pNDU = NULL; nasCode = NetQueryDisplayInformation(NULL, 1, 0, iMaximumUserCount, dwPreferredSize, &dwEntriesRead, reinterpret_cast<void**>(&pNDU)); if ((ERROR_SUCCESS == nasCode) || (ERROR_MORE_DATA == nasCode)) { int iIndex;
for (iIndex = static_cast<int>(dwEntriesRead - 1); iIndex >= 0; --iIndex) { BOOL fResult; DWORD dwSIDSize, dwDomainSize; SID_NAME_USE eUse; PSID pSID; WCHAR wszDomain[DNLEN + sizeof('\0')];
// Iterate the user list and look up the SID for each user in the
// list regardless of whether they are disabled or not.
dwSIDSize = dwDomainSize = 0; fResult = LookupAccountNameW(NULL, pNDU[iIndex].usri1_name, NULL, &dwSIDSize, NULL, &dwDomainSize, &eUse); pSID = static_cast<PSID>(LocalAlloc(LMEM_FIXED, dwSIDSize)); if (pSID != NULL) { dwDomainSize = DUIARRAYSIZE(wszDomain); fResult = LookupAccountNameW(NULL, pNDU[iIndex].usri1_name, pSID, &dwSIDSize, wszDomain, &dwDomainSize, &eUse);
// Ensure that only user SIDs are checked.
if ((fResult != FALSE) && (SidTypeUser == eUse)) { unsigned char ucSubAuthorityCount; int iSubAuthorityIndex;
ucSubAuthorityCount = *GetSidSubAuthorityCount(pSID); for (iSubAuthorityIndex = 0; iSubAuthorityIndex < ucSubAuthorityCount; ++iSubAuthorityIndex) { DWORD dwSubAuthority;
dwSubAuthority = *GetSidSubAuthority(pSID, iSubAuthorityIndex); if (DOMAIN_USER_RID_GUEST == dwSubAuthority) { lstrcpyW(g_szGuestName, pNDU[iIndex].usri1_name); } } } (HLOCAL)LocalFree(pSID); } } } (NET_API_STATUS)NetApiBufferFree(pNDU); }
////////////////////////////////////////
//
// GetLogonUserByLogonName
//
// Given a username, CoCreate the ILogonUser for that name.
//
// RETURNS
// HRESULT -- failure if the user could not be created.
//
/////////////////////////////////////////
HRESULT GetLogonUserByLogonName(LPWSTR pszUsername, ILogonUser **ppobjUser) { VARIANT var; ILogonEnumUsers *pobjEnum;
if (ppobjUser) { *ppobjUser = NULL; }
var.vt = VT_BSTR; var.bstrVal = pszUsername; HRESULT hr = CoCreateInstance(CLSID_ShellLogonEnumUsers, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ILogonEnumUsers, &pobjEnum)); if (SUCCEEDED(hr)) { hr = pobjEnum->item(var, ppobjUser); pobjEnum->Release(); } return hr; }
////////////////////////////////////////
//
// ReleaseStatusHost
//
// Clean up the logon status host object.
//
// RETURNS
// nothing
//
/////////////////////////////////////////
void ReleaseStatusHost() { if (g_pILogonStatusHost != NULL) { g_pILogonStatusHost->UnInitialize(); g_pILogonStatusHost->Release(); g_pILogonStatusHost = NULL; } }
////////////////////////////////////////
//
// EndHostProcess
//
// Clean up the logon status host object and if uiExitCode is anything other than 0,
// then terminate the process immediately.
//
// RETURNS
// nothing
//
/////////////////////////////////////////
void EndHostProcess(UINT uiExitCode) { ReleaseStatusHost(); if (uiExitCode != 0) { ExitProcess(uiExitCode); } }
////////////////////////////////////////
//
// GetRegistryNumericValue
//
// Given a registry HKEY and a value return the numeric value
//
// RETURNS
// the numeric value from the registry
//
/////////////////////////////////////////
int GetRegistryNumericValue(HKEY hKey, LPCTSTR pszValueName)
{ int iResult; DWORD dwType, dwDataSize;
iResult = 0; if (ERROR_SUCCESS == RegQueryValueEx(hKey, pszValueName, NULL, &dwType, NULL, NULL)) { if (REG_DWORD == dwType) { DWORD dwData;
dwDataSize = sizeof(dwData); if (ERROR_SUCCESS == RegQueryValueEx(hKey, pszValueName, NULL, NULL, reinterpret_cast<LPBYTE>(&dwData), &dwDataSize)) { iResult = static_cast<int>(dwData); } } else if (REG_SZ == dwType) { TCHAR szData[1024];
dwDataSize = sizeof(szData); if (ERROR_SUCCESS == RegQueryValueEx(hKey, pszValueName, NULL, NULL, reinterpret_cast<LPBYTE>(szData), &dwDataSize)) { char szAnsiData[1024];
(int)WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)szData, -1, szAnsiData, sizeof(szAnsiData), NULL, NULL); iResult = atoi(szAnsiData); } } } return(iResult); }
////////////////////////////////////////
//
// IsShutdownAllowed
//
// Firstly (firstly??)... if the machine is remote then don't allow shut down.
// Determine the local machine policy for shutdown from the logon screen.
// This is stored in two places as two different types (REG_DWORD and REG_SZ).
// Always check the policy location AFTER the normal location to ensure that
// policy overrides normal settings.
//
// RETURNS
// TRUE if the machine is allowed to be shut down from logonui. FALSE otherwise
//
/////////////////////////////////////////
BOOL IsShutdownAllowed() { BOOL fResult = FALSE;
ILocalMachine *pobjLocalMachine; HRESULT hr = CoCreateInstance(CLSID_ShellLocalMachine, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ILocalMachine, &pobjLocalMachine)); if (SUCCEEDED(hr)) { VARIANT_BOOL vbCanShutdown = VARIANT_FALSE; hr = pobjLocalMachine->get_isShutdownAllowed(&vbCanShutdown); if (SUCCEEDED(hr)) { fResult = (vbCanShutdown == VARIANT_TRUE); } pobjLocalMachine->Release(); } return fResult; }
////////////////////////////////////////
//
// IsUndockAllowed
//
// Check with SHGina to see if we are allowed to undock the PC.
//
// RETURNS
// TRUE if the machine is allowed to be undocked from logonui. FALSE otherwise
//
/////////////////////////////////////////
BOOL IsUndockAllowed() { BOOL fResult = FALSE; #if 0
ILocalMachine *pobjLocalMachine; HRESULT hr = CoCreateInstance(CLSID_ShellLocalMachine, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ILocalMachine, &pobjLocalMachine)); if (SUCCEEDED(hr)) { VARIANT_BOOL vbCanUndock = VARIANT_FALSE; hr = pobjLocalMachine->get_isUndockEnabled(&vbCanUndock); if (SUCCEEDED(hr)) { fResult = (vbCanUndock == VARIANT_TRUE); } pobjLocalMachine->Release(); } #endif
return fResult; }
#ifndef TESTDATA
LONG WINAPI LogonUIUnhandledExceptionFilter (struct _EXCEPTION_POINTERS *ExceptionInfo)
{ return(RtlUnhandledExceptionFilter(ExceptionInfo)); } #endif // !TESTDATA
void SetErrorHandler (void)
{ #ifndef TESTDATA
SYSTEM_KERNEL_DEBUGGER_INFORMATION kdInfo;
(NTSTATUS)NtQuerySystemInformation(SystemKernelDebuggerInformation, &kdInfo, sizeof(kdInfo), NULL); if (kdInfo.KernelDebuggerEnabled || NtCurrentPeb()->BeingDebugged) { (LPTOP_LEVEL_EXCEPTION_FILTER)SetUnhandledExceptionFilter(LogonUIUnhandledExceptionFilter); } #endif // !TESTDATA
}
////////////////////////////////////////
//
// RunningInWinlogon
//
// Checks to see if logonui is running in the winlogon context. There are some things
// that don't work well when we are not in winlogon so this makes debugging easier.
//
// RETURNS
// TRUE if the running in winlogon (actually if it can find the GINA Logon window). FALSE otherwise
//
/////////////////////////////////////////
BOOL RunningInWinlogon() { #if DEBUG
return (FindWindow(NULL, TEXT("GINA Logon")) != NULL); #else
return true; #endif
}
////////////////////////////////////////
//
// BuildUserListFromGina
//
// Enumerate all of the users that SHGina tells us we care about and add them to the accounts list.
// Find out of they require a password and their current state for notifications.
//
// If there is only 1 user or if there are 2 users, but one of them is guest, then ppAccount will
// contain a pointer to the only user on this machine. The caller can then automatically select
// that user to avoid them from having to click that user given that there is no one else to click.
//
//
// RETURNS
// HRESULT -- if not a success code, we are hosed.
//
/////////////////////////////////////////
HRESULT BuildUserListFromGina(LogonFrame* plf, OUT LogonAccount** ppAccount) { if (ppAccount) { *ppAccount = NULL; }
DetermineGuestAccountName();
int iGuestId = -1; WCHAR szPicturePath[MAX_PATH]; ILogonEnumUsers *pobjEnum; LogonAccount* plaLastNormal = NULL; // load the ILogonEnumUsers object from SHGina.dll
HRESULT hr = CoCreateInstance(CLSID_ShellLogonEnumUsers, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ILogonEnumUsers, &pobjEnum)); if (SUCCEEDED(hr)) { int iUser,cUsers; UINT uiUsers; ILogonUser *pobjUser;
// get the number of users
hr = pobjEnum->get_length(&uiUsers); if (FAILED(hr)) goto done;
cUsers = (int)uiUsers; for (iUser = 0; iUser < cUsers; iUser++) { VARIANT var, varUnreadMail, varPicture = {0}, varUsername = {0}, varHint = {0}; VARIANT_BOOL vbLoggedOn, vbInteractiveLogonAllowed;
var.vt = VT_I4; var.lVal = iUser; hr = pobjEnum->item( var, &pobjUser);
if (SUCCEEDED(hr) && pobjUser) { if (SUCCEEDED(pobjUser->get_interactiveLogonAllowed(&vbInteractiveLogonAllowed)) && (vbInteractiveLogonAllowed != VARIANT_FALSE)) { // get the display name for the user
pobjUser->get_setting(L"DisplayName" ,&var); pobjUser->get_setting(L"LoginName", &varUsername);
// if the display name is blank, we will use the login name. This is the case for Guest
if (var.bstrVal && lstrlenW(var.bstrVal) == 0) { VariantClear(&var); pobjUser->get_setting(L"LoginName" ,&var); } if (FAILED(pobjUser->get_isLoggedOn(&vbLoggedOn))) { vbLoggedOn = VARIANT_FALSE; } if (FAILED(pobjUser->get_setting(L"UnreadMail", &varUnreadMail))) { varUnreadMail.uintVal = 0; }
lstrcpyW(szPicturePath, L""); // get the path to their picture
if (SUCCEEDED(pobjUser->get_setting(L"Picture" ,&varPicture))) { if (lstrlenW(varPicture.bstrVal) != 0) // in the case of defaultUser, lets just use the user icons we have.
{ lstrcpynW(szPicturePath, &(varPicture.bstrVal[7]), MAX_PATH); } VariantClear(&varPicture); }
VariantClear(&varHint); hr = pobjUser->get_setting(L"Hint", &varHint); if (FAILED(hr) || varHint.vt != VT_BSTR) { VariantClear(&varHint); } if (lstrcmpi(g_szGuestName, var.bstrVal) == 0) { iGuestId = iUser; } LogonAccount* pla = NULL; // If no picture is available, default to one
hr = plf->AddAccount(*szPicturePath ? szPicturePath : MAKEINTRESOURCEW(IDB_USER0), *szPicturePath == NULL, var.bstrVal, varUsername.bstrVal, varHint.bstrVal, (vbLoggedOn == VARIANT_TRUE), &pla);
// pla->UpdateNotifications(true);
if (SUCCEEDED(hr) && (iGuestId != iUser)) { plaLastNormal = pla; }
VariantClear(&var); VariantClear(&varHint); VariantClear(&varUsername); } pobjUser->Release(); }
}
// if there is only one user, select them by default. Ignore guest.
if (ppAccount && plaLastNormal && (cUsers == 1 || (cUsers == 2 && iGuestId != -1))) { *ppAccount = plaLastNormal; }
done: pobjEnum->Release(); }
// User logon list is now available
plf->SetUserListAvailable(true);
//DUITrace("LOGONUI: UserList is now available\n");
return hr; }
////////////////////////////////////////
//
// KillFlagAnimation
//
// Stop the flag from animating immediately. What it actually does is check to
// see if we are still animating the flag and if we are, then set the frame
// counter to the end and set the bitmap to the first frame in the animation.
// The next time the timer fires, it will see that we are done and actually
// kill the timer.
//
/////////////////////////////////////////
void KillFlagAnimation() { #ifdef ANIMATE_FLAG
if (sTimerCount > 0 && sTimerCount < TOTAL_FLAG_FRAMES) { sTimerCount = TOTAL_FLAG_FRAMES + 1; if (g_plf != NULL) { g_plf->NextFlagAnimate(0); } } #endif
}
////////////////////////////////////////
//
// LogonWindowProc
//
// This is the notification window that SHGina uses to communicate with logonui.
// Send all messages through the helper in logonstatushost and check for our
// own messages on this window. This is where all of the SHGina notifications come.
//
////////////////////////////////////////
LRESULT CALLBACK LogonWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static BOOL sResetTimer = false;
LogonFrame *pLogonFrame;
pLogonFrame = g_plf; if (g_pILogonStatusHost != NULL) { VARIANT varWParam, varLParam;
varWParam.uintVal = static_cast<UINT>(wParam); varLParam.lVal = static_cast<LONG>(lParam); if (SUCCEEDED(g_pILogonStatusHost->WindowProcedureHelper(hwnd, uMsg, varWParam, varLParam))) { return 0; } } switch (uMsg) { case WM_TIMER: if ((pLogonFrame != NULL) && (pLogonFrame->GetState() == LAS_Logon) && (wParam == TIMER_REFRESHTIPS)) { BOOL fRefreshAll = false;
if (!sResetTimer) { fRefreshAll = true; sResetTimer = true; KillTimer(hwnd, g_puTimerId); g_puTimerId = SetTimer(hwnd, TIMER_REFRESHTIPS, 15000, NULL); // update the values 15 seconds
#ifdef ANIMATE_FLAG
g_puFlagTimerId = SetTimer(hwnd, TIMER_ANIMATEFLAG, 20, NULL); // start the flag animation
#endif
}
pLogonFrame->UpdateUserStatus(fRefreshAll); return 0; } #ifdef ANIMATE_FLAG
if (wParam == TIMER_ANIMATEFLAG) { if (sTimerCount > TOTAL_FLAG_FRAMES) { sTimerCount = 0; KillTimer(hwnd, g_puFlagTimerId); pLogonFrame->NextFlagAnimate(0); } else { sTimerCount ++; pLogonFrame->NextFlagAnimate(sTimerCount % MAX_FLAG_FRAMES); } return 0; } #endif
break;
case WM_UIHOSTMESSAGE: switch (wParam) { case HM_SWITCHSTATE_STATUS: // LAS_PreStatus
if (pLogonFrame != NULL) { pLogonFrame->EnterPreStatusMode(lParam != 0); } break;
case HM_SWITCHSTATE_LOGON: // LAS_Logon
if (pLogonFrame != NULL) { pLogonFrame->EnterLogonMode(lParam != 0); } if (g_puTimerId != 0) { sResetTimer = false; KillTimer(hwnd, g_puTimerId); } g_puTimerId = SetTimer(hwnd, TIMER_REFRESHTIPS, 250, NULL); // update the values in 1 second
break;
case HM_SWITCHSTATE_LOGGEDON: // LAS_PostStatus
if (pLogonFrame != NULL) { pLogonFrame->EnterPostStatusMode(); } break;
case HM_SWITCHSTATE_HIDE: // LAS_Hide
if (pLogonFrame != NULL) { if (LogonAccount::GetCandidate()) { LogonAccount* pla = LogonAccount::GetCandidate(); pla->InsertStatus(0); pla->SetStatus(0, L""); pla->ShowStatus(0); } else { pLogonFrame->SetStatus(L""); } pLogonFrame->EnterHideMode(); } goto killTimer; break;
case HM_SWITCHSTATE_DONE: // LAS_Done
if (pLogonFrame != NULL) { pLogonFrame->EnterDoneMode(); } killTimer: if (g_puTimerId != 0) { KillTimer(hwnd, g_puTimerId); g_puTimerId = 0; } break;
case HM_NOTIFY_WAIT: if (pLogonFrame != NULL) { pLogonFrame->SetTitle(IDS_PLEASEWAIT); } break;
case HM_SELECT_USER: if (pLogonFrame != NULL) { pLogonFrame->SelectUser(reinterpret_cast<SELECT_USER*>(lParam)->szUsername); } break;
case HM_SET_ANIMATIONS: if (pLogonFrame != NULL) { pLogonFrame->SetAnimations(lParam != 0); } break;
case HM_DISPLAYSTATUS: if ((pLogonFrame != NULL) && (lParam != NULL)) { if (pLogonFrame->GetState() == LAS_PostStatus) { if (LogonAccount::GetCandidate()) { LogonAccount* pla = LogonAccount::GetCandidate(); pla->InsertStatus(0); pla->SetStatus(0, (WCHAR*)lParam); pla->ShowStatus(0); } else { pLogonFrame->SetStatus((WCHAR*)lParam); } } else { pLogonFrame->SetStatus((WCHAR*)lParam); } } break;
case HM_DISPLAYREFRESH: if (pLogonFrame != NULL) { pLogonFrame->UpdateUserStatus(true); } break;
case HM_DISPLAYRESIZE: if (pLogonFrame != NULL) { pLogonFrame->Resize(); } break;
case HM_INTERACTIVE_LOGON_REQUEST: return((pLogonFrame != NULL) && pLogonFrame->InteractiveLogonRequest(reinterpret_cast<INTERACTIVE_LOGON_REQUEST*>(lParam)->szUsername, reinterpret_cast<INTERACTIVE_LOGON_REQUEST*>(lParam)->szPassword)); } break; } return DefWindowProc(hwnd, uMsg,wParam, lParam); }
|