Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2268 lines
71 KiB

/*****************************************************************************\
FILE: ScreenSaverPg.cpp
DESCRIPTION:
This file contains the COM object implementation that will display the
ScreenSaver tab in the Display Control Panel.
18-Feb-94 (Tracy Sharpe) Added power management functionality.
Commented out several pieces of code that weren't being
used.
5/30/2000 (Bryan Starbuck) BryanSt: Turned into C++ and COM. Exposed
as an API so other tabs can communicate with it. This enables
the Plus! Theme page to modify the screen saver.
11/08/2000 (Bryan Starbuck) BryanSt: Moved from \nt\shell\cpls\desknt5 to
\nt\shell\themes\themeui\.
Copyright (C) Microsoft Corp 1994-2000. All rights reserved.
\*****************************************************************************/
#include "priv.h"
#pragma hdrstop
#include <scrnsave.h>
#include "exe.h"
#include "ScreenSaverPg.h"
#include <MSGinaExports.h> // for ShellIsFriendlyUIActive, etc..
#define SFSE_SYSTEM 0
#define SFSE_PRG 1
#define SFSE_WINDOWS 2
#define SFSE_FILE 3
#define MAX_METHODS 100
#define MIN_MINUTES 1
#define MAX_MINUTES 9999 //The UI will allow upto four digits.
#define BUFFER_SIZE 400
#define WMUSER_SETINITSS (WM_USER + 1)
/* Local funcprototypes... */
void SearchForScrEntries ( UINT, LPCTSTR );
BOOL FreeScrEntries ( void );
int lstrncmp ( LPTSTR, LPTSTR, int );
LPTSTR FileName ( LPTSTR szPath);
LPTSTR StripPathName ( LPTSTR szPath);
LPTSTR NiceName ( LPTSTR szPath);
void AddBackslash(LPTSTR pszPath, DWORD cchPath);
void AppendPath(LPTSTR pszPath, DWORD cchPath, LPTSTR pszSpec);
PTSTR PerformCheck(LPTSTR, BOOL);
void DoScreenSaver(HWND hDlg, BOOL b);
void ScreenSaver_AdjustTimeouts(HWND hWnd,int BaseControlID);
void EnableDisablePowerDelays(HWND hDlg);
TCHAR g_szSaverName[MAX_PATH]; // Screen Saver EXE
HICON hDefaultIcon = NULL;
HICON hIdleWildIcon;
BOOL bWasConfig=0; // We were configing the screen saver
HWND g_hwndTestButton;
HWND g_hwndLastFocus;
BOOL g_fPasswordWasPreviouslyEnabled = FALSE;
BOOL g_fPasswordDirty = FALSE; // tells us if the user has actually changed the state of the password combobox
BOOL g_fFriendlyUI = FALSE; // is winlogon going to switch back to the welcome screen, or call LockWorkStation for real?
BOOL g_fPasswordBoxDeterminedByPolicy = FALSE;
BOOL g_fSettingsButtonOffByPolicy = FALSE;
BOOL g_fTimeoutDeterminedByPolicy = FALSE;
BOOL g_fScreenSaverExecutablePolicy = FALSE;
// Local global variables
HICON hIcons[MAX_METHODS];
UINT wNumMethods = 0;
PTSTR aszMethods[MAX_METHODS];
PTSTR aszFiles[MAX_METHODS];
static const TCHAR c_szDemoParentClass[] = TEXT("SSDemoParent");
// static TCHAR szFileNameCopy[MAX_PATH];
static int g_iMethod;
static BOOL g_fPreviewActive;
static BOOL g_fAdapPwrMgnt = FALSE;
/*
* Registry value for the "Password Protected" check box
*
* These are different for NT and Win95 to keep screen
* savers built exclusivly for Win95 from trying to
* handle password checks. (NT does all password checking
* in the built in security system to maintain C2
* level security)
*/
# define SZ_USE_PASSWORD TEXT("ScreenSaverIsSecure")
# define PWRD_REG_TYPE REG_SZ
# define CCH_USE_PWRD_VALUE 2
# define CB_USE_PWRD_VALUE (CCH_USE_PWRD_VALUE * sizeof(TCHAR))
TCHAR gpwdRegYes[CCH_USE_PWRD_VALUE] = TEXT("1");
TCHAR gpwdRegNo[CCH_USE_PWRD_VALUE] = TEXT("0");
#define PasswdRegData(f) ((f) ? (PBYTE)gpwdRegYes : (PBYTE)gpwdRegNo)
UDACCEL udAccel[] = {{0,1},{2,5},{4,30},{8,60}};
#include "help.h"
#define IDH_DESK_LOWPOWERCFG IDH_SCRSAVER_GRAPHIC
// To simplify some things, the base control ID of a time control is associated
// with its corresponding ClassicSystemParametersInfo action codes.
typedef struct {
int taBaseControlID;
UINT taGetTimeoutAction;
UINT taSetTimeoutAction;
UINT taGetActiveAction;
UINT taSetActiveAction;
} TIMEOUT_ASSOCIATION;
// Except for the case of the "screen save" delay, each time grouping has three
// controls-- a switch to determine whether that time should be used or not and
// an edit box and an updown control to change the delay time. ("Screen save"
// is turned off my choosing (None) from the screen saver list) These three
// controls must be organized as follows:
#define BCI_DELAY 0
#define BCI_ARROW 1
#define BCI_SWITCH 2
// Associations between base control IDs and ClassicSystemParametersInfo action codes.
// The TA_* #defines are used as symbolic indexes into this array. Note that
// TA_SCREENSAVE is a special case-- it does NOT have a BCI_SWITCH.
#define TA_SCREENSAVE 0
TIMEOUT_ASSOCIATION g_TimeoutAssociation[] = {
IDC_SCREENSAVEDELAY, SPI_GETSCREENSAVETIMEOUT, SPI_SETSCREENSAVETIMEOUT,
SPI_GETSCREENSAVEACTIVE, SPI_SETSCREENSAVEACTIVE,
};
int g_Timeout[] = {
0,
0,
0,
};
HBITMAP g_hbmDemo = NULL;
HBITMAP g_hbmEnergyStar = NULL;
BOOL g_bInitSS = TRUE; // assume we are in initialization process
BOOL g_bChangedSS = FALSE; // changes have been made
class CScreenSaverPg : public CObjectWithSite
, public CObjectCLSID
, public IBasePropPage
, public IPropertyBag
{
public:
//////////////////////////////////////////////////////
// Public Interfaces
//////////////////////////////////////////////////////
// *** IUnknown ***
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
virtual STDMETHODIMP_(ULONG) AddRef(void);
virtual STDMETHODIMP_(ULONG) Release(void);
// *** IBasePropPage ***
virtual STDMETHODIMP GetAdvancedDialog(OUT IAdvancedDialog ** ppAdvDialog);
virtual STDMETHODIMP OnApply(IN PROPPAGEONAPPLY oaAction);
// *** IShellPropSheetExt ***
virtual STDMETHODIMP AddPages(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam);
virtual STDMETHODIMP ReplacePage(IN EXPPS uPageID, IN LPFNSVADDPROPSHEETPAGE pfnReplaceWith, IN LPARAM lParam) {return E_NOTIMPL;}
// *** IPropertyBag ***
virtual STDMETHODIMP Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog);
virtual STDMETHODIMP Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar);
protected:
private:
CScreenSaverPg();
// Private Member Variables
LONG m_cRef;
BOOL m_fSecure;
BOOL m_fUIInitialized; // Have we activated the UI tab and loaded the UI controls with state?
BOOL m_fScreenSavePolicy;
BOOL m_fScreenSaveActive;
LONG m_lWaitTime;
HWND m_hDlg;
// Private Member Functions
HRESULT _InitState(void);
BOOL _InitSSDialog(HWND hDlg);
HRESULT _OnSetActive(void);
HRESULT _OnApply(void);
HRESULT _OnSelectionChanged(void);
HRESULT _SaveIni(HWND hDlg);
HRESULT _SetByPath(LPCWSTR pszPath);
INT_PTR _ScreenSaverDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
friend INT_PTR CALLBACK ScreenSaverDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
friend HRESULT CScreenSaverPage_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj);
};
//===========================
// *** Class Internals & Helpers ***
//===========================
const DWORD aSaverHelpIds[] = {
IDC_NO_HELP_1, NO_HELP,
IDC_CHOICES, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_LISTBOX,
IDC_SSDELAYLABEL, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_WAIT,
IDC_SSDELAYSCALE, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_WAIT,
IDC_SCREENSAVEDELAY, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_WAIT,
IDC_SCREENSAVEARROW, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_WAIT,
IDC_TEST, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_PREVIEW,
IDC_SETTING, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_SETTINGS,
IDC_BIGICONSS, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_MONITOR,
IDC_ENERGY_TEXT, NO_HELP,
IDC_ENERGYSTAR_BMP, IDH_DISPLAY_SCREENSAVER_ENERGYSAVE_GRAPHIC,
IDC_USEPASSWORD, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_PASSWORD_CHECKBOX,
// IDC_SETPASSWORD, IDH_COMM_PASSWDBUTT,
IDC_LOWPOWERCONFIG, IDH_DISPLAY_SCREENSAVER_POWER_BUTTON,
IDC_ENERGY_TEXT2, NO_HELP,
0, 0
};
// are we going to return to the welcome dialog in the friendly UI case?
BOOL WillReturnToWelcome()
{
HKEY hkey;
BOOL bRet = TRUE;
if (RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
{
TCHAR szTemp[4];
DWORD dwType;
DWORD dwSize = sizeof(szTemp);
if ((RegQueryValueEx(hkey, TEXT("NoAutoReturnToWelcome"), NULL, &dwType, (BYTE*)szTemp, &dwSize) == ERROR_SUCCESS) &&
(dwType == REG_SZ))
{
bRet = !(StrToInt(szTemp));
}
RegCloseKey(hkey);
}
return bRet;
}
/*
* Win95 and NT store different values in different places of the registry to
* determine if the screen saver is secure or not.
*
* We can't really consolidate the two because the screen savers do different
* actions based on which key is set. Win95 screen savers do their own
* password checking, but NT must let the secure desktop winlogon code do it.
*
* Therefore to keep Win95 screen savers from requesting the password twice on
* NT, we use REGSTR_VALUE_USESCRPASSWORD == (REG_DWORD)1 on Win95 to indicate
* that a screen saver should check for the password, and
* "ScreenSaverIsSecure" == (REG_SZ)"1" on NT to indicate that WinLogon should
* check for a password.
*
* This function will deal with the differences.
*/
static BOOL IsPasswdSecure(HKEY hKey)
{
union {
DWORD dw;
TCHAR asz[4];
} uData;
DWORD dwSize, dwType;
BOOL fSecure = FALSE;
dwSize = sizeof(uData);
if (RegQueryValueEx(hKey,SZ_USE_PASSWORD,NULL, &dwType, (BYTE *)&uData, &dwSize) == ERROR_SUCCESS)
{
switch (dwType)
{
case REG_DWORD:
fSecure = (uData.dw == 1);
break;
case REG_SZ:
fSecure = (uData.asz[0] == TEXT('1'));
break;
}
}
// if we are in friendly UI mode, we might want to treat this as secure even if SZ_USE_PASSWORD is not set
if (g_fFriendlyUI && !fSecure)
{
fSecure = WillReturnToWelcome();
}
return fSecure;
}
static void NEAR
EnableDlgChild( HWND dlg, HWND kid, BOOL val )
{
if( !val && ( kid == GetFocus() ) )
{
// give prev tabstop focus
SendMessage( dlg, WM_NEXTDLGCTL, 1, 0L );
}
EnableWindow( kid, val );
}
static void NEAR
EnableDlgItem( HWND dlg, int idkid, BOOL val )
{
EnableDlgChild( dlg, GetDlgItem( dlg, idkid ), val );
}
HWND GetSSDemoParent( HWND page )
{
static HWND parent = NULL;
if (!parent || !IsWindow(parent))
{
parent = CreateWindowEx( 0, c_szDemoParentClass,
TEXT(""), WS_CHILD | WS_CLIPCHILDREN, 0, 0, 0, 0,
GetDlgItem(page, IDC_BIGICONSS), NULL, HINST_THISDLL, NULL );
}
return parent;
}
void ForwardSSDemoMsg(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
HWND hwndChild;
hwnd = GetSSDemoParent(hwnd);
if (hwnd)
{
for (hwndChild = GetWindow(hwnd, GW_CHILD); hwnd && (hwndChild != NULL);
hwndChild = GetWindow(hwndChild, GW_HWNDNEXT))
{
SendMessage(hwndChild, uMessage, wParam, lParam);
}
}
}
void ParseSaverName( LPTSTR lpszName )
{
if( *lpszName == TEXT('\"') )
{
LPTSTR lpcSrc = lpszName + 1;
while( *lpcSrc && *lpcSrc != TEXT('\"') )
{
*lpszName++ = *lpcSrc++;
}
*lpszName = 0; // clear second quote
}
}
// YUCK:
// since our screen saver preview is in a different process,
// it is possible that we paint in the wrong order.
// this ugly hack makes sure the demo always paints AFTER the dialog
WNDPROC g_lpOldStaticProc = NULL;
LRESULT StaticSubclassProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
{
LRESULT result =
CallWindowProc(g_lpOldStaticProc, wnd, msg, wp, lp);
if (msg == WM_PAINT)
{
HWND demos = GetSSDemoParent(GetParent(wnd));
if (demos)
{
RedrawWindow(demos, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
}
}
return result;
}
HRESULT CScreenSaverPg::_InitState(void)
{
HRESULT hr = S_OK;
HKEY hKey;
int Counter;
int nActive;
int Timeout;
m_fScreenSavePolicy = FALSE;
m_fScreenSaveActive = TRUE;
// Fetch the timeout value from the win.ini and adjust between 1:00-60:00
for (Counter = 0; Counter < ARRAYSIZE(g_TimeoutAssociation); Counter++)
{
// Fetch the timeout value from the win.ini and adjust between 1:00-60:00
ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taGetTimeoutAction, 0, &Timeout, 0);
// The Win 3.1 guys decided that 0 is a valid ScreenSaveTimeOut value.
// This causes our screen savers not to kick in (who cares?). In any
// case, I changed this to allow 0 to go through. In this way, the
// user immediately sees that the value entered is not valid to fire
// off the screen saver--the OK button is disabled. I don't know if
// I fully agree with this solution--it is just the minimal amount of
// code. The optimal solution would be to ask the 3.1 guys why 0 is
// valid? -cjp
Timeout = min(max(Timeout, 1), MAX_MINUTES * 60);
// Convert Timeout to minutes, rounding up.
Timeout = (Timeout + 59) / 60;
g_Timeout[Counter] = Timeout;
ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taGetActiveAction, 0, &nActive, SPIF_UPDATEINIFILE);
if (Counter == TA_SCREENSAVE)
{
// I found that NTUSER will return random values so we don't use them. If people want to set the policy,
// they should do in the registry.
// m_fScreenSaveActive = nActive;
}
}
// Find the name of the exe used as a screen saver. "" means that the
// default screen saver will be used. First check the system policies
if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Policies\\Microsoft\\Windows\\Control Panel\\Desktop"), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
BOOL fSettings;
ULONG cbSize;
cbSize = sizeof(g_szSaverName);
if (RegQueryValueEx(hKey, TEXT("SCRNSAVE.EXE"), NULL, NULL, (LPBYTE)g_szSaverName, &cbSize) == ERROR_SUCCESS)
{
g_fScreenSaverExecutablePolicy = TRUE;
LogStatus("POLICY ENABLED: ScreenSaver selection is forced to a certain SS file.");
}
cbSize = sizeof(m_fSecure);
if (RegQueryValueEx(hKey, TEXT("ScreenSaverIsSecure"), NULL, NULL, (LPBYTE)&m_fSecure, &cbSize) == ERROR_SUCCESS)
{
g_fPasswordBoxDeterminedByPolicy = TRUE;
LogStatus("POLICY ENABLED: ScreenSaverIsSecure is on.");
}
cbSize = sizeof( fSettings );
if (RegQueryValueEx(hKey, TEXT("ScreenSaverSettingsButton"), NULL, NULL, (LPBYTE)&fSettings, &cbSize) == ERROR_SUCCESS)
{
g_fSettingsButtonOffByPolicy = TRUE;
LogStatus("POLICY ENABLED: ScreenSaver settings button is disabled.");
}
TCHAR szTemp[20];
if (SUCCEEDED(HrRegGetValueString(hKey, NULL, SZ_POLICY_SCREENSAVETIMEOUT, szTemp, ARRAYSIZE(szTemp))) &&
szTemp[0])
{
m_lWaitTime = StrToInt(szTemp);
g_fTimeoutDeterminedByPolicy = TRUE;
LogStatus("POLICY ENABLED: ScreenSaver timeout value is set.");
}
if (SUCCEEDED(HrRegGetValueString(hKey, NULL, TEXT("ScreenSaveActive"), szTemp, ARRAYSIZE(szTemp))) &&
szTemp[0])
{
m_fScreenSavePolicy = TRUE;
m_fScreenSaveActive = StrToInt(szTemp);
LogStatus("POLICY ENABLED: ScreenSaver Active is set.");
}
RegCloseKey(hKey);
}
if (!g_fScreenSaverExecutablePolicy)
{
if (FAILED(HrRegGetPath(HKEY_CURRENT_USER, SZ_REGKEY_CPDESKTOP, SZ_INIKEY_SCREENSAVER, g_szSaverName, ARRAYSIZE(g_szSaverName))))
{
TCHAR szTempPath[MAX_PATH];
if (GetPrivateProfileString(SZ_INISECTION_SCREENSAVER, SZ_INIKEY_SCREENSAVER, TEXT(""), g_szSaverName, ARRAYSIZE(g_szSaverName), SZ_INISECTION_SYSTEMINI))
{
StringCchCopy(szTempPath, ARRAYSIZE(szTempPath), g_szSaverName);
SHExpandEnvironmentStrings(szTempPath, g_szSaverName, ARRAYSIZE(g_szSaverName));
}
}
}
ParseSaverName(g_szSaverName); // remove quotes and params
// Call will fail if monitor or adapter don't support DPMS.
int dummy;
g_fAdapPwrMgnt = ClassicSystemParametersInfo(SPI_GETLOWPOWERACTIVE, 0, &dummy, 0);
if (!g_fAdapPwrMgnt)
{
g_fAdapPwrMgnt = ClassicSystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, &dummy, 0);
}
// initialize the password checkbox
if (RegOpenKeyEx(HKEY_CURRENT_USER,REGSTR_PATH_SCREENSAVE, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
if (IsPasswdSecure(hKey))
{
g_fPasswordWasPreviouslyEnabled = TRUE;
}
RegCloseKey(hKey);
}
return hr;
}
BOOL CScreenSaverPg::_InitSSDialog(HWND hDlg)
{
WNDCLASS wc;
PTSTR pszMethod;
UINT wTemp,wLoop;
BOOL fContinue;
UINT Counter;
int ControlID;
int wMethod;
DWORD dwUserCount;
HKEY hKey;
HWND hwnd;
int nActive;
TCHAR szBuffer[MAX_PATH];
m_hDlg = hDlg;
m_fUIInitialized = TRUE;
HINSTANCE hInstDeskCPL = LoadLibrary(TEXT("desk.cpl"));
if (!GetClassInfo(HINST_THISDLL, c_szDemoParentClass, &wc))
{
// if two pages put one up, share one dc
wc.style = 0;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = wc.cbWndExtra = 0;
wc.hInstance = HINST_THISDLL;
wc.hIcon = (HICON)( wc.hCursor = NULL );
wc.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
wc.lpszMenuName = NULL;
wc.lpszClassName = c_szDemoParentClass;
if( !RegisterClass( &wc ) )
return FALSE;
}
// Fetch the timeout value from the win.ini and adjust between 1:00-60:00
for (Counter = 0; Counter < ARRAYSIZE(g_TimeoutAssociation); Counter++)
{
// The base control id specifies the edit control id.
ControlID = g_TimeoutAssociation[Counter].taBaseControlID;
// Set the maximum length of all of the fields...
SendDlgItemMessage(hDlg, ControlID, EM_LIMITTEXT, 4, 0); //Allow four digits.
ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taGetActiveAction, 0, &nActive, SPIF_UPDATEINIFILE);
if (Counter != TA_SCREENSAVE)
{
CheckDlgButton(hDlg, ControlID + BCI_SWITCH, nActive);
}
else
{
// m_fScreenSaveActive = nActive;
}
SetDlgItemInt(hDlg, ControlID, g_Timeout[Counter], FALSE);
// The associated up/down control id must be one after the edit control id.
ControlID++;
SendDlgItemMessage(hDlg, ControlID, UDM_SETRANGE, 0, MAKELPARAM(MAX_MINUTES, MIN_MINUTES));
SendDlgItemMessage(hDlg, ControlID, UDM_SETACCEL, 4, (LPARAM)(LPUDACCEL)udAccel);
}
// Find the name of the exe used as a screen saver. "" means that the
// default screen saver will be used. First check the system policies
if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Policies\\Microsoft\\Windows\\Control Panel\\Desktop"), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
BOOL fPower;
ULONG cbSize;
cbSize = sizeof(fPower);
if (RegQueryValueEx(hKey, TEXT("ScreenSaverPowerButton"), NULL, NULL, (LPBYTE)&fPower, &cbSize) == ERROR_SUCCESS)
{
EnableWindow(GetDlgItem(hDlg, IDC_LOWPOWERCONFIG), FALSE);
}
RegCloseKey(hKey);
}
if (g_fPasswordBoxDeterminedByPolicy)
{
CheckDlgButton(hDlg, IDC_USEPASSWORD, m_fSecure);
EnableWindow(GetDlgItem(hDlg, IDC_USEPASSWORD), FALSE);
}
// if we are running with the new friendly UI w/ multiple users on the system, then we switch to text from "Password protect"
// to "Return to the Welcome screen" because winlogon will do a switch user instead of a LockWorkStation in this case
if (ShellIsFriendlyUIActive() &&
ShellIsMultipleUsersEnabled() &&
(ERROR_SUCCESS == ShellGetUserList(TRUE, &dwUserCount, NULL)) &&
(dwUserCount > 1))
{
if (LoadString(HINST_THISDLL, IDS_RETURNTOWELCOME, szBuffer, ARRAYSIZE(szBuffer)))
{
SetDlgItemText(hDlg, IDC_USEPASSWORD, szBuffer);
g_fFriendlyUI = TRUE;
if (WillReturnToWelcome())
{
g_fPasswordWasPreviouslyEnabled = TRUE;
}
}
}
if (g_fSettingsButtonOffByPolicy)
{
EnableWindow(GetDlgItem(hDlg, IDC_SETTING), FALSE);
}
if (g_fTimeoutDeterminedByPolicy)
{
SetDlgItemInt(hDlg, IDC_SCREENSAVEDELAY, (UINT) m_lWaitTime / 60, FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_SCREENSAVEDELAY), FALSE);
}
if (m_fScreenSavePolicy && !m_fScreenSaveActive)
{
EnableWindow(GetDlgItem(hDlg, IDC_CHOICES), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_SETTING), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_SSDELAYLABEL), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_SCREENSAVEDELAY), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_SCREENSAVEARROW), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_SSDELAYSCALE), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_USEPASSWORD), FALSE);
}
if (g_fScreenSaverExecutablePolicy)
{
EnableWindow(GetDlgItem(hDlg, IDC_CHOICES), FALSE);
}
// Copy all of the variables into their copies...
// lstrcpy(szFileNameCopy, g_szSaverName);
// Load in the default icon...
if (hInstDeskCPL)
{
hDefaultIcon = LoadIcon(hInstDeskCPL, MAKEINTRESOURCE(IDS_ICON));
}
// Find the methods to save the screen. If the method that was
// selected is not found, the program will assume that the
// first method in the list will be the one that is elected...
wNumMethods = 0;
wMethod = -1;
SearchForScrEntries(SFSE_PRG,NULL);
SearchForScrEntries(SFSE_SYSTEM,NULL);
SearchForScrEntries(SFSE_WINDOWS,NULL);
SearchForScrEntries(SFSE_FILE,g_szSaverName);
szBuffer[0] = 0;
TCHAR szNone[MAX_PATH];
LoadString(HINST_THISDLL, IDS_NONE, szNone, ARRAYSIZE(szNone));
// Set up the combo box for the different fields...
SendDlgItemMessage(hDlg, IDC_CHOICES, CB_ADDSTRING, 0, (LPARAM)szNone);
for (wTemp = 0; (wTemp < wNumMethods) && (ARRAYSIZE(aszFiles) > wTemp) && (ARRAYSIZE(aszMethods) > wTemp); wTemp++)
{
// Lock down the information and pass it to the combo box...
pszMethod = aszMethods[wTemp];
wLoop = (UINT)SendDlgItemMessage(hDlg,IDC_CHOICES,CB_ADDSTRING,0, (LPARAM)(pszMethod+1));
SendDlgItemMessage(hDlg, IDC_CHOICES, CB_SETITEMDATA, wLoop, wTemp);
// If we have the correct item, keep a copy so we can select it out of the combo box...
// check for filename only as well as full path name
if (!lstrcmpi(FileName(aszFiles[wTemp]), FileName(g_szSaverName)))
{
wMethod = wTemp;
StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), pszMethod + 1);
}
}
if (m_fScreenSavePolicy && !m_fScreenSaveActive)
{
wMethod = -1;
}
// Attempt to select the string we recieved from the
// system.ini entry. If there is no match, select the
// first item from the list...
if ((wMethod == -1) || (wNumMethods == 0))
{
fContinue = TRUE;
}
else
{
if (SendDlgItemMessage(hDlg, IDC_CHOICES, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)szBuffer) == CB_ERR)
fContinue = TRUE;
else
fContinue = FALSE;
}
if (fContinue)
{
SendDlgItemMessage(hDlg,IDC_CHOICES,CB_SETCURSEL,0,0l);
g_szSaverName[0] = '\0';
wMethod = -1;
}
g_hbmDemo = LoadMonitorBitmap( TRUE );
if (g_hbmDemo)
{
SendDlgItemMessage(hDlg,IDC_BIGICONSS,STM_SETIMAGE, IMAGE_BITMAP,(LPARAM)g_hbmDemo);
}
if (hInstDeskCPL)
{
g_hbmEnergyStar = (HBITMAP) LoadImage(HINST_THISDLL, MAKEINTRESOURCE(IDB_ENERGYSTAR), IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS);
if (g_hbmEnergyStar)
{
SendDlgItemMessage(hDlg, IDC_ENERGYSTAR_BMP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hbmEnergyStar);
}
}
// Hide/Disable the energy related controls if the adaptor/monitor does not
// support power mgnt.
EnableDisablePowerDelays(hDlg);
// subclass the static control so we can synchronize painting
hwnd = GetDlgItem(hDlg, IDC_BIGICONSS);
if (hwnd)
{
g_lpOldStaticProc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)(WNDPROC)StaticSubclassProc);
// Turn off the mirroring style for this control to allow the screen saver preview to work.
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~RTL_MIRRORED_WINDOW);
}
if (hInstDeskCPL)
{
FreeLibrary(hInstDeskCPL);
}
return TRUE;
}
// Build a command line in a format suitable for passing as the second
// parameter to CreateProcess.
void _PathBuildArgs(LPTSTR pszBuf, DWORD cchBuf, LPCTSTR pszExe, LPCTSTR pszFormat, ...)
{
StringCchCopy(pszBuf, cchBuf, pszExe);
PathQuoteSpaces(pszBuf);
int cchBufUsed = lstrlen(pszBuf);
pszBuf += cchBufUsed;
cchBuf -= cchBufUsed;
va_list ap;
va_start(ap, pszFormat);
wvnsprintf(pszBuf, cchBuf, pszFormat, ap);
va_end(ap);
}
#define SS_WINDOWCLOSE_WAIT_LIMIT 5000
BOOL CALLBACK EnumSSChildWindowsProc(HWND hwndC, LPARAM lParam)
{
HWND hwndDemo = (HWND)lParam;
TraceMsg(TF_FUNC, "hwndDemo = %08x hwndC = %08x", hwndDemo, hwndC);
if (IsWindow(hwndDemo) && (hwndDemo == GetParent(hwndC)))
{
DWORD dwStart = GetTickCount();
TraceMsg(TF_FUNC, "dwStart = %08x", dwStart);
while (IsWindow(hwndC))
{
DWORD_PTR dwResult;
TraceMsg(TF_FUNC, "Sending WM_CLOSE tickcount = %08x", GetTickCount());
BOOL fShouldEndTask = !SendMessageTimeout(hwndC, WM_CLOSE, 0, 0,
SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG | SMTO_NORMAL, 2000, &dwResult);
TraceMsg(TF_FUNC, "Return from sending WM_CLOSE tickcount = %08x fShouldEndTask = %d", GetTickCount(), fShouldEndTask);
if (!fShouldEndTask)
{
DWORD dwWait = dwStart + SS_WINDOWCLOSE_WAIT_LIMIT - GetTickCount();
TraceMsg(TF_FUNC, "dwWait = %d", dwWait);
if (dwWait > SS_WINDOWCLOSE_WAIT_LIMIT)
{
TraceMsg(TF_FUNC, "Wait exceeded, ending task");
fShouldEndTask = TRUE;
}
}
if (fShouldEndTask)
{
TraceMsg(TF_FUNC, "Call EndTask task for %08x", hwndC);
EndTask(hwndC, FALSE, FALSE);
TraceMsg(TF_FUNC, "Return from EndTask task for %08x", hwndC);
break;
}
}
}
return TRUE;
}
void SetNewSSDemo(HWND hDlg, int iMethod)
{
HBITMAP hbmOld;
POINT ptIcon;
HWND hwndDemo;
HICON hicon;
RECT rc = {MON_X, MON_Y, MON_X+MON_DX, MON_Y+MON_DY};
hwndDemo = GetSSDemoParent(hDlg);
if (hwndDemo)
{
// blank out the background with dialog color
hbmOld = (HBITMAP) SelectObject(g_hdcMem, g_hbmDemo);
FillRect(g_hdcMem, &rc, GetSysColorBrush(COLOR_DESKTOP));
SelectObject(g_hdcMem, hbmOld);
// make sure the old window is gone
EnumChildWindows(hwndDemo, EnumSSChildWindowsProc, (LPARAM)hwndDemo);
Yield(); // paranoid
Yield(); // really paranoid
ShowWindow(hwndDemo, SW_HIDE);
g_fPreviewActive = FALSE;
if (iMethod >= 0 && aszMethods[iMethod][0] == TEXT('P'))
{
RECT rc;
BITMAP bm;
UpdateWindow(hDlg);
//UpdateWindow(GetDlgItem(hDlg, IDC_BIGICONSS));
TCHAR szArgs[MAX_PATH];
GetObject(g_hbmDemo, sizeof(bm), &bm);
GetClientRect(GetDlgItem(hDlg, IDC_BIGICONSS), &rc);
rc.left = ( rc.right - bm.bmWidth ) / 2 + MON_X;
rc.top = ( rc.bottom - bm.bmHeight ) / 2 + MON_Y;
MoveWindow(hwndDemo, rc.left, rc.top, MON_DX, MON_DY, FALSE);
_PathBuildArgs(szArgs, ARRAYSIZE(szArgs), g_szSaverName, TEXT(" /p %d"), hwndDemo);
if (WinExecN(g_szSaverName, szArgs, SW_NORMAL) > 32)
{
ShowWindow(hwndDemo, SW_SHOWNA);
g_fPreviewActive = TRUE;
return;
}
}
if (iMethod != -1)
{
ptIcon.x = ClassicGetSystemMetrics(SM_CXICON);
ptIcon.y = ClassicGetSystemMetrics(SM_CYICON);
// draw the icon double size
ASSERT(ptIcon.y*2 <= MON_DY);
ASSERT(ptIcon.x*2 <= MON_DX);
hicon = hIcons[iMethod];
if (hicon == NULL && aszMethods[iMethod][0] == TEXT('I'))
hicon = hIdleWildIcon;
if (hicon == NULL)
hicon = hDefaultIcon;
hbmOld = (HBITMAP) SelectObject(g_hdcMem, g_hbmDemo);
DrawIconEx(g_hdcMem,
MON_X + (MON_DX-ptIcon.x*2)/2,
MON_Y + (MON_DY-ptIcon.y*2)/2,
hicon, ptIcon.x*2, ptIcon.y*2, 0, NULL, DI_NORMAL);
SelectObject(g_hdcMem, hbmOld);
}
}
InvalidateRect(GetDlgItem(hDlg, IDC_BIGICONSS), NULL, FALSE);
}
static void SS_SomethingChanged(HWND hDlg)
{
if (!g_bInitSS)
{
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
}
}
static void SetScreenSaverPassword(HWND hDlg, int iMethod)
{
if (iMethod >= 0 && aszMethods[iMethod][0] == TEXT('P'))
{
TCHAR szArgs[MAX_PATH];
_PathBuildArgs(szArgs, ARRAYSIZE(szArgs), g_szSaverName, TEXT(" /a %u"), GetParent(hDlg));
WinExecN(g_szSaverName, szArgs, SW_NORMAL);
}
}
INT_PTR CALLBACK ScreenSaverDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
CScreenSaverPg * pThis = (CScreenSaverPg *)GetWindowLongPtr(hDlg, DWLP_USER);
if (WM_INITDIALOG == wMsg)
{
PROPSHEETPAGE * pPropSheetPage = (PROPSHEETPAGE *) lParam;
if (pPropSheetPage)
{
SetWindowLongPtr(hDlg, DWLP_USER, pPropSheetPage->lParam);
pThis = (CScreenSaverPg *)pPropSheetPage->lParam;
}
}
if (pThis)
return pThis->_ScreenSaverDlgProc(hDlg, wMsg, wParam, lParam);
return DefWindowProc(hDlg, wMsg, wParam, lParam);
}
BOOL SelectSSFromList(HWND hDlg)
{
HWND hwndSSList = GetDlgItem(hDlg, IDC_CHOICES);
BOOL fExistsInList = FALSE;
// Select the current item in the list since another tab
// may have changed this value.
for (UINT nIndex = 0; nIndex < wNumMethods; nIndex++)
{
if (!StrCmpI(g_szSaverName, aszFiles[nIndex]))
{
int nItem = ComboBox_FindString(hwndSSList, 0, &(aszMethods[nIndex][1]));
if (-1 != nItem)
{
ComboBox_SetCurSel(hwndSSList, nItem);
}
fExistsInList = TRUE;
break;
}
}
return fExistsInList;
}
HRESULT CScreenSaverPg::_OnSetActive(void)
{
EnableDisablePowerDelays(m_hDlg);
if (!SelectSSFromList(m_hDlg))
{
UINT wTemp;
UINT wLoop;
// We couldn't find it, so add it to aszMethods[].
SearchForScrEntries(SFSE_FILE, g_szSaverName);
// Now add it to the Drop Down.
for (wTemp = 0; (wTemp < wNumMethods) && (ARRAYSIZE(aszFiles) > wTemp) && (ARRAYSIZE(aszMethods) > wTemp); wTemp++)
{
// Did we find the correct index?
if (!StrCmpI(FileName(aszFiles[wTemp]), FileName(g_szSaverName)))
{
// Yes, so set the index.
wLoop = (UINT)SendDlgItemMessage(m_hDlg, IDC_CHOICES, CB_ADDSTRING, 0, (LPARAM)(aszMethods[wTemp]+1));
SendDlgItemMessage(m_hDlg, IDC_CHOICES, CB_SETITEMDATA, wLoop, wTemp);
break;
}
}
SelectSSFromList(m_hDlg); // Try again now that we added it. Another tab or API may have asked for us to use this SS.
}
if (!g_fPreviewActive)
{
g_bInitSS = TRUE;
SendMessage(m_hDlg, WM_COMMAND, MAKELONG(IDC_CHOICES, CBN_SELCHANGE), (LPARAM)GetDlgItem(m_hDlg, IDC_CHOICES));
g_bInitSS = FALSE;
}
return S_OK;
}
HRESULT CScreenSaverPg::_OnApply(void)
{
// Our parent dialog will be notified of the Apply event and will call our
// IBasePropPage::OnApply() to do the real work.
return S_OK;
}
HRESULT CScreenSaverPg::_OnSelectionChanged(void)
{
HRESULT hr = E_FAIL;
PTSTR pszMethod;
int wMethod;
BOOL fEnable;
// Dump the name of the current selection into the buffer...
int wTemp = (int)SendDlgItemMessage(m_hDlg, IDC_CHOICES, CB_GETCURSEL,0,0l);
if (wTemp)
{
wMethod = (int)SendDlgItemMessage(m_hDlg, IDC_CHOICES, CB_GETITEMDATA, wTemp, 0l);
// Grey the button accordingly...
pszMethod = aszMethods[wMethod];
if ((pszMethod[0] == TEXT('C') || // can config
pszMethod[0] == TEXT('I') || // IdleWild
pszMethod[0] == TEXT('P')) &&
!g_fSettingsButtonOffByPolicy) // can preview
EnableDlgItem(m_hDlg, IDC_SETTING, TRUE);
else
EnableDlgItem(m_hDlg, IDC_SETTING, FALSE);
if (!g_fPasswordBoxDeterminedByPolicy)
{
EnableDlgItem(m_hDlg, IDC_USEPASSWORD, TRUE);
CheckDlgButton(m_hDlg, IDC_USEPASSWORD, g_fPasswordWasPreviouslyEnabled);
}
// For fun, create an extra copy of g_szSaverName...
pszMethod = aszFiles[wMethod];
StringCchCopy(g_szSaverName, ARRAYSIZE(g_szSaverName), pszMethod);
fEnable = TRUE;
}
else
{
wMethod = -1;
g_szSaverName[0] = '\0';
EnableDlgItem(m_hDlg, IDC_SETTING, FALSE);
EnableDlgItem(m_hDlg, IDC_USEPASSWORD, FALSE);
fEnable = FALSE;
}
// Following are enabled as a group... (oh really?)
EnableDlgItem(m_hDlg, IDC_SSDELAYLABEL, fEnable);
EnableDlgItem(m_hDlg, IDC_SCREENSAVEDELAY, !g_fTimeoutDeterminedByPolicy && fEnable);
EnableDlgItem(m_hDlg, IDC_SCREENSAVEARROW, fEnable);
EnableDlgItem(m_hDlg, IDC_SSDELAYSCALE, fEnable);
EnableDlgItem(m_hDlg, IDC_TEST, fEnable);
g_iMethod = (int)wMethod;
SetNewSSDemo(m_hDlg, wMethod);
SS_SomethingChanged(m_hDlg);
return hr;
}
INT_PTR CScreenSaverPg::_ScreenSaverDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
{
NMHDR *lpnm;
switch(message)
{
case WM_NOTIFY:
lpnm = (NMHDR *)lParam;
switch(lpnm->code)
{
case PSN_APPLY:
_OnApply();
break;
// nothing to do on cancel...
case PSN_RESET:
if (g_fPreviewActive)
SetNewSSDemo(hDlg, -1);
break;
case PSN_KILLACTIVE:
if (g_fPreviewActive)
SetNewSSDemo(hDlg, -1);
break;
case PSN_SETACTIVE:
_OnSetActive();
break;
}
break;
case WM_INITDIALOG:
g_bInitSS = TRUE;
_InitSSDialog(hDlg);
g_bInitSS = FALSE;
break;
case WM_DISPLAYCHANGE:
case WM_SYSCOLORCHANGE: {
HBITMAP hbm;
hbm = g_hbmDemo;
g_hbmDemo = LoadMonitorBitmap( TRUE );
if (g_hbmDemo)
{
// Got a new bitmap, use it and delete the old one.
SendDlgItemMessage(hDlg,IDC_BIGICONSS,STM_SETIMAGE, IMAGE_BITMAP,(LPARAM)g_hbmDemo);
if (hbm)
{
DeleteObject(hbm);
}
}
else
{
// Couldn't get a new bitmap, just reuse the old one
g_hbmDemo = hbm;
}
break;
}
case WM_DESTROY:
FreeScrEntries();
if (g_fPreviewActive)
SetNewSSDemo(hDlg, -1);
if (g_hbmDemo)
{
SendDlgItemMessage(hDlg,IDC_BIGICONSS,STM_SETIMAGE,IMAGE_BITMAP, (LPARAM)NULL);
DeleteObject(g_hbmDemo);
}
if (g_hbmEnergyStar)
{
SendDlgItemMessage(hDlg,IDC_ENERGYSTAR_BMP,STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
DeleteObject(g_hbmEnergyStar);
}
break;
case WM_VSCROLL:
if (LOWORD(wParam) == SB_THUMBPOSITION)
ScreenSaver_AdjustTimeouts(hDlg, GetDlgCtrlID((HWND)lParam) - BCI_ARROW);
break;
case WM_HELP:
WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, TEXT("display.hlp"), HELP_WM_HELP, (DWORD_PTR)aSaverHelpIds);
break;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, TEXT("display.hlp"), HELP_CONTEXTMENU, (DWORD_PTR) aSaverHelpIds);
break;
case WM_QUERYNEWPALETTE:
case WM_PALETTECHANGED:
ForwardSSDemoMsg(hDlg, message, wParam, lParam);
break;
case WMUSER_SETINITSS:
g_bInitSS = (BOOL) lParam;
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
/* Check for a selection change in the combo box. If there is
one, then update the method number as well as the
configure button... */
case IDC_CHOICES:
if(HIWORD(wParam) == CBN_SELCHANGE)
{
_OnSelectionChanged();
}
break;
/* If the edit box loses focus, translate... */
case IDC_SCREENSAVEDELAY:
if (HIWORD(wParam) == EN_KILLFOCUS)
ScreenSaver_AdjustTimeouts(hDlg, LOWORD(wParam));
else
//check if initdialog is finished
if((FALSE == g_bInitSS) && (EN_CHANGE == (HIWORD(wParam))))
SS_SomethingChanged(hDlg);
break;
case IDC_LOWPOWERCONFIG:
{
TCHAR szRunDll32[MAX_PATH];
SystemPathAppend(szRunDll32, TEXT("rundll32.exe"));
TCHAR szShell32[MAX_PATH];
SystemPathAppend(szShell32, TEXT("shell32.dll"));
CHAR szCmdLine[3 * MAX_PATH];
StringCchPrintfA(szCmdLine, ARRAYSIZE(szCmdLine), "%S %S,Control_RunDLL powercfg.cpl,,", szRunDll32, szShell32);
// Configure the low power timeout event.
WinExec(szCmdLine, SW_SHOWNORMAL);
}
break;
/* If the user wishes to test... */
case IDC_TEST:
switch( HIWORD( wParam ) )
{
case BN_CLICKED:
DoScreenSaver(hDlg,TRUE);
break;
}
break;
/* Tell the DLL that it can do the configure... */
case IDC_SETTING:
if (HIWORD(wParam) == BN_CLICKED) {
DoScreenSaver(hDlg,FALSE);
break;
}
case IDC_USEPASSWORD:
if (HIWORD(wParam) == BN_CLICKED)
{
// the user actually toggled the checbox, so set our dirty flag
g_fPasswordDirty = TRUE;
g_fPasswordWasPreviouslyEnabled = IsDlgButtonChecked( hDlg, IDC_USEPASSWORD );
SS_SomethingChanged(hDlg);
break;
}
case IDC_SETPASSWORD:
if (HIWORD(wParam) == BN_CLICKED)
{
// ask new savers to change passwords
int wTemp = (int)SendDlgItemMessage(hDlg,IDC_CHOICES, CB_GETCURSEL,0,0l);
if (wTemp)
{
SetScreenSaverPassword(hDlg, (int)SendDlgItemMessage(hDlg,IDC_CHOICES, CB_GETITEMDATA,wTemp,0l));
}
break;
}
}
break;
case WM_CTLCOLORSTATIC:
if( (HWND)lParam == GetSSDemoParent( hDlg ) )
{
return (INT_PTR)GetStockObject( NULL_BRUSH );
}
break;
}
return FALSE;
}
/*******************************************************************************
*
* ScreenSaver_AdjustTimeouts
*
* DESCRIPTION:
* Called whenever the user adjusts the delay of one of the time controls.
* Adjusts the delays of the other time controls such that the screen saver
* delay is less than the low power delay and that the low power delay is
* less than the power off delay.
*
* PARAMETERS:
* hWnd, handle of ScreenSaver window.
* BaseControlID, base control ID of the radio, edit, and arrow time control
* combination.
*
*******************************************************************************/
VOID
NEAR PASCAL
ScreenSaver_AdjustTimeouts(HWND hWnd, int BaseControlID)
{
BOOL fTranslated;
int Timeout;
// Get the new timeout for this time control and validate it's contents.
Timeout = (int) GetDlgItemInt(hWnd, BaseControlID + BCI_DELAY, &fTranslated, FALSE);
Timeout = min(max(Timeout, 1), MAX_MINUTES);
SetDlgItemInt(hWnd, BaseControlID + BCI_DELAY, (UINT) Timeout, FALSE);
// Check the new value of this time control against the other timeouts,
// adjust their values if necessary. Be careful when changing the order
// of these conditionals.
//
if (BaseControlID == IDC_SCREENSAVEDELAY)
{
if (g_Timeout[TA_SCREENSAVE] != Timeout)
{
g_Timeout[TA_SCREENSAVE] = Timeout;
SS_SomethingChanged(hWnd);
}
}
else
{
if (Timeout < g_Timeout[TA_SCREENSAVE])
{
g_Timeout[TA_SCREENSAVE] = Timeout;
SetDlgItemInt(hWnd, IDC_SCREENSAVEDELAY, (UINT) Timeout, FALSE);
}
}
}
void EnableDisablePowerDelays(HWND hDlg)
{
int i;
static idCtrls[] = { IDC_ENERGY_TEXT,
IDC_ENERGY_TEXT2,
IDC_ENERGY_TEXT3,
IDC_ENERGYSTAR_BMP,
IDC_LOWPOWERCONFIG,
0 };
for (i = 0; idCtrls[i] != 0; i++)
ShowWindow( GetDlgItem( hDlg, idCtrls[i] ), g_fAdapPwrMgnt ? SW_SHOWNA : SW_HIDE );
}
/* This routine will search for entries that are screen savers. The directory
searched is either the system directory (.. */
void SearchForScrEntries(UINT wDir, LPCTSTR file)
{
TCHAR szPath[MAX_PATH];
TCHAR szPath2[MAX_PATH];
HANDLE hfind;
WIN32_FIND_DATA fd;
// don't do any work if no space left
if( wNumMethods >= MAX_METHODS )
return;
/* Get the directory where the program resides... */
GetModuleFileName(HINST_THISDLL, szPath, ARRAYSIZE(szPath));
StripPathName(szPath);
switch ( wDir )
{
case SFSE_WINDOWS:
/* Search the windows directory and place the path with the \ in
the szPath variable... */
if (!GetWindowsDirectory(szPath2, ARRAYSIZE(szPath2)))
{
szPath2[0] = 0;
}
sfseSanityCheck:
/* if same dir as where it was launched, don't search again */
if (!lstrcmpi(szPath, szPath2))
return;
StringCchCopy(szPath, ARRAYSIZE(szPath), szPath2);
break;
case SFSE_SYSTEM:
/* Search the system directory and place the path with the \ in
the szPath variable... */
GetSystemDirectory(szPath2, ARRAYSIZE(szPath2));
goto sfseSanityCheck;
case SFSE_FILE:
/* Search the directory containing 'file' */
StringCchCopy(szPath2, ARRAYSIZE(szPath2), file);
StripPathName(szPath2);
goto sfseSanityCheck;
}
AppendPath(szPath, ARRAYSIZE(szPath), TEXT("*.scr"));
if( ( hfind = FindFirstFile( szPath, &fd ) ) != INVALID_HANDLE_VALUE )
{
StripPathName(szPath);
do
{
PTSTR pszDesc;
BOOL fLFN;
fLFN = !(fd.cAlternateFileName[0] == 0 ||
lstrcmp(fd.cFileName, fd.cAlternateFileName) == 0);
StringCchCopy(szPath2, ARRAYSIZE(szPath2), szPath);
AppendPath(szPath2, ARRAYSIZE(szPath2), fd.cFileName);
// Note: PerformCheck does an alloc
if( ( pszDesc = PerformCheck( szPath2, fLFN ) ) != NULL )
{
BOOL bAdded = FALSE;
UINT i;
for( i = 0; i < wNumMethods; i++ )
{
if( !lstrcmpi( pszDesc, aszMethods[ i ] ) )
{
bAdded = TRUE;
break;
}
}
if( !bAdded )
{
PTSTR pszEntries;
// COMPATIBILITY: always use short name
// otherwise some apps fault when peeking at SYSTEM.INI
if( fLFN )
{
StringCchCopy(szPath2, ARRAYSIZE(szPath2), szPath);
AppendPath(szPath2, ARRAYSIZE(szPath2), fd.cAlternateFileName);
}
if( ( pszEntries = StrDup( szPath2 ) ) != NULL )
{
if (pszDesc[0] != TEXT('P'))
hIcons[wNumMethods] = ExtractIcon(HINST_THISDLL, szPath2, 0);
else
hIcons[wNumMethods] = NULL;
aszMethods[wNumMethods] = pszDesc;
aszFiles[wNumMethods] = pszEntries;
wNumMethods++;
bAdded = TRUE;
}
}
if( !bAdded )
LocalFree((HLOCAL)pszDesc);
}
} while( FindNextFile( hfind, &fd ) && ( wNumMethods < MAX_METHODS ) );
FindClose(hfind);
}
return;
}
//
// This routine checks a given file to see if it is indeed a screen saver
// executable...
//
// a valid screen saver exe has the following description line:
//
// SCRNSAVE [c] : description :
//
// SCRNSAVE is a required name that indicates a screen saver.
//
PTSTR PerformCheck(LPTSTR lpszFilename, BOOL fLFN)
{
int i;
TCHAR chConfig=TEXT('C'); // assume configure
LPTSTR pch;
DWORD dw;
WORD Version;
WORD Magic;
TCHAR szBuffer[MAX_PATH];
DWORD cchSizePch = (ARRAYSIZE(szBuffer)-1);
// Get the description...
pch = szBuffer + 1;
// if we have a LFN (Long File Name) dont bother getting the
// exe descrription
dw = GetExeInfo(lpszFilename, pch, cchSizePch, fLFN ? GEI_EXPVER : GEI_DESCRIPTION);
Version = HIWORD(dw);
Magic = LOWORD(dw);
if (dw == 0)
return NULL;
if (Magic == PEMAGIC || fLFN)
{
BOOL fGotName = FALSE;
if (!fLFN)
{
HINSTANCE hSaver = LoadLibraryEx(lpszFilename, NULL, LOAD_LIBRARY_AS_DATAFILE);
// We have a 32 bit screen saver with a short name, look for an NT style
// decription in it's string table
if (hSaver)
{
int cchLoaded = LoadString(hSaver, IDS_DESCRIPTION, pch, cchSizePch);
if (cchLoaded)
{
if (!IsOS(OS_ANYSERVER))
{
// HACK!!!: The display CPL looks for screen saver descriptions with string resource id=IDS_DESCRIPTION.
// As we need the certain screen saver descriptions to be different for client of server builds (32 and 64bit),
// the description string may be in the form of "Server\0Client". If this is true, LoadString will return a
// count greater than the lstrlen of the string.
int cchActual = lstrlen(pch);
if (cchLoaded != cchActual)
{
// Extract the client portion of the description string
StringCchCopy(pch, ARRAYSIZE(szBuffer) - 1, &pch[cchActual + 1]);
}
}
fGotName = TRUE;
}
FreeLibrary(hSaver);
}
}
if (!fGotName)
{
// we have a LFN (LongFileName) or a Win32 screen saver,
// Win32 exe's in general dont have a description field so
// we assume they can configure. We also try to build
// a "nice" name for it.
StringCchCopy(pch, cchSizePch, lpszFilename);
pch = FileName(pch); // strip path part
if ( ((TCHAR)CharUpper((LPTSTR)(pch[0]))) == TEXT('S') && ((TCHAR)CharUpper((LPTSTR)(pch[1]))) == TEXT('S')) // map SSBEZIER.SCR to BEZIER.SCR
pch+=2;
pch = NiceName(pch); // map BEZIER.SCR to Bezier
}
}
else
{
LPTSTR pchTemp;
// we have a 8.3 file name 16bit screen saveer, parse the
// description string from the exehdr
/* Check to make sure that at least the 11 characters needed for info
are there... */
if (lstrlen(pch) < 9)
return NULL;
/* Check the first 8 characters for the string... */
if (lstrncmp((LPTSTR)TEXT("SCRNSAVE"), pch, 8))
return NULL;
// If successful, allocate enough space for the string and copy the
// string to the new one...
pch = pch + 8; // skip over 'SCRNSAVE'
while (*pch==TEXT(' ')) // advance over white space
pch++;
if (*pch==TEXT('C') || *pch==TEXT('c')) // parse the configure flag
{
chConfig = TEXT('C');
pch++;
}
if (*pch==TEXT('X') || *pch==TEXT('x')) // parse the don't configure flag
chConfig = *pch++;
// we might be pointing at a name or separation goop
pchTemp = pch; // remember this spot
while (*pch && *pch!=TEXT(':')) // find separator
pch++;
while (*pch==TEXT(':') || *pch==TEXT(' ')) // advance over whtspc/last colon
pch++;
// if we haven't found a name yet fall back on the saved location
if (!*pch)
pch = pchTemp;
while (*pch==TEXT(':') || *pch==TEXT(' ')) // re-advance over whtspc
pch++;
/* In case the screen saver has version information information
embedded after the name, check to see if there is a colon TEXT(':')
in the description and replace it with a NULL... */
for (i=0; pch[i]; i++) //
{
if (pch[i]==TEXT(':'))
pch[i]=0;
}
// Space is OK for DBCS (FE)
while(i>0 && pch[i-1]==TEXT(' ')) // remove trailing space
pch[--i]=0;
}
#ifdef DEBUG
if (Magic != PEMAGIC)
{
StringCchCat(pch, cchSizePch, TEXT(" (16-bit)"));
}
if (Version == 0x030A)
StringCchCat(pch, cchSizePch, TEXT(" (3.10)"));
if (Version == 0x0400)
StringCchCat(pch, cchSizePch, TEXT(" (4.00)"));
#endif
//
// assume any Win32 4.0 screen saver can do Preview mode
//
if (chConfig == TEXT('C') && Version >= 0x0400 && Magic == PEMAGIC)
chConfig = TEXT('P'); // mark as configurable/preview
pch[-1] = chConfig;
return StrDup(pch-1);
}
BOOL FreeScrEntries( void )
{
UINT wLoop;
for(wLoop = 0; wLoop < wNumMethods; wLoop++)
{
if(aszMethods[wLoop] != NULL)
LocalFree((HANDLE)aszMethods[wLoop]);
if(aszFiles[wLoop] != NULL)
LocalFree((HANDLE)aszFiles[wLoop]);
if(hIcons[wLoop] != NULL)
FreeResource(hIcons[wLoop]);
}
if (hDefaultIcon)
FreeResource(hDefaultIcon);
if (hIdleWildIcon)
FreeResource(hIdleWildIcon);
hDefaultIcon=hIdleWildIcon=NULL;
wNumMethods = 0;
return TRUE;
}
int lstrncmp( LPTSTR lpszString1, LPTSTR lpszString2, int nNum )
{
/* While we can still compare characters, compare. If the strings are
of different lengths, characters will be different... */
while(nNum)
{
if(*lpszString1 != *lpszString2)
return *lpszString1 - *lpszString2;
lpszString1++;
lpszString2++;
nNum--;
}
return 0;
}
HRESULT CScreenSaverPg::_SaveIni(HWND hDlg)
{
HRESULT hr = S_OK;
LPTSTR pszMethod = TEXT("");
BOOL bSSActive;
int wMethod,wTemp;
UINT Counter;
HKEY hKey;
TCHAR szBuffer[MAX_PATH];
if (m_fUIInitialized)
{
// Find the current method selection...
wTemp = 0;
if (wNumMethods)
{
// Dump the name of the current selection into the buffer...
wTemp = (int)SendDlgItemMessage(hDlg, IDC_CHOICES, CB_GETCURSEL, 0, 0);
if (wTemp)
{
wMethod = (int)SendDlgItemMessage(hDlg, IDC_CHOICES, CB_GETITEMDATA, wTemp, 0);
// Dump the method name into the buffer...
pszMethod = aszFiles[wMethod];
}
}
// since "(None)" is always the first entry in the combobox, we can use it to see if we have
// a screensaver or not
if (wTemp == 0)
{
// 0th inxed is "(None)" so the screensaver is disabled
bSSActive = FALSE;
}
else
{
bSSActive = TRUE;
}
}
else
{
TCHAR szNone[MAX_PATH];
LoadString(HINST_THISDLL, IDS_NONE, szNone, ARRAYSIZE(szNone));
if ((g_szSaverName[0] == TEXT('\0')) || (lstrcmpi(szNone, g_szSaverName) == 0))
{
// screensaver was not set, OR it was set to "(None)" -- therefore it is not active
bSSActive = FALSE;
}
else
{
bSSActive = TRUE;
}
pszMethod = g_szSaverName;
}
// Now quote any spaces
BOOL hasspace = FALSE;
LPTSTR pc;
for (pc = pszMethod; *pc; pc++)
{
if (*pc == TEXT(' '))
{
hasspace = TRUE;
break;
}
}
if (hasspace)
{
// if we need to add quotes we'll need two sets
// because GetBlahBlahProfileBlah APIs strip quotes
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), TEXT("\"\"%s\"\""), pszMethod);
}
else
{
StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), pszMethod);
}
// Save the buffer...
if (!WritePrivateProfileString(SZ_INISECTION_SCREENSAVER, SZ_INIKEY_SCREENSAVER, (szBuffer[0] != TEXT('\0') ? szBuffer : NULL), SZ_INISECTION_SYSTEMINI))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
// In win2k we decided to leave the screensaver ALWAYS active so that when the policy changed, it would take
// w/out rebooting. This has become a PITA so we now do it the right way.
ClassicSystemParametersInfo(SPI_SETSCREENSAVEACTIVE, bSSActive, NULL, SPIF_UPDATEINIFILE);
for (Counter = 0; Counter < (sizeof(g_TimeoutAssociation) / sizeof(TIMEOUT_ASSOCIATION)); Counter++)
{
ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taSetTimeoutAction, (UINT) (g_Timeout[Counter] * 60), NULL, SPIF_UPDATEINIFILE);
if (Counter != TA_SCREENSAVE)
{
ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taSetActiveAction,
IsDlgButtonChecked(hDlg, g_TimeoutAssociation[Counter].taBaseControlID + BCI_SWITCH),
NULL,
SPIF_UPDATEINIFILE);
}
}
// save the state of the TEXT("use password") checkbox
if (RegCreateKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
{
if (g_fPasswordDirty)
{
if (g_fFriendlyUI)
{
// the user actually toggled the value, so don't automatically return to the welcome screen since they have
// now made their own decision on this subject
RegSetValueEx(hKey, TEXT("NoAutoReturnToWelcome"), 0, REG_SZ, (BYTE*)TEXT("1"), sizeof(TEXT("1")));
RegSetValueEx(hKey, SZ_USE_PASSWORD, 0, PWRD_REG_TYPE, PasswdRegData(IsDlgButtonChecked(hDlg,IDC_USEPASSWORD)), CB_USE_PWRD_VALUE);
}
else
{
RegSetValueEx(hKey, SZ_USE_PASSWORD, 0, PWRD_REG_TYPE, PasswdRegData(IsDlgButtonChecked(hDlg,IDC_USEPASSWORD)), CB_USE_PWRD_VALUE);
}
}
RegCloseKey(hKey);
}
// Broadcast a WM_WININICHANGE message...
SendNotifyMessage(HWND_BROADCAST, WM_WININICHANGE, 0, (LPARAM)TEXT("Windows"));
return hr;
}
/*
* Thread for DoScreenSaver()
*/
typedef struct
{
HWND hDlg;
TCHAR szPath[MAX_PATH];
TCHAR szArgs[MAX_PATH];
} SSRUNDATA, *LPSSRUNDATA;
DWORD RunScreenSaverThread( LPVOID lpv )
{
BOOL bSvrState;
LPSSRUNDATA lpssrd;
HWND hwndSettings, hwndPreview;
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInformation;
HINSTANCE hiThd;
TCHAR szPath[MAX_PATH];
// Lock ourselves in mem so we don't fault if app unloads us
GetModuleFileName(HINST_THISDLL, szPath, ARRAYSIZE(szPath));
hiThd = LoadLibrary( szPath );
lpssrd = (LPSSRUNDATA)lpv;
hwndSettings = GetDlgItem( lpssrd->hDlg, IDC_SETTING);
hwndPreview = GetDlgItem( lpssrd->hDlg, IDC_TEST);
// Save previous screen saver state
ClassicSystemParametersInfo( SPI_GETSCREENSAVEACTIVE,0, &bSvrState, FALSE);
// Disable current screen saver
if( bSvrState )
ClassicSystemParametersInfo( SPI_SETSCREENSAVEACTIVE,FALSE, NULL, FALSE );
// Stop the miniture preview screen saver
if (g_fPreviewActive)
SetNewSSDemo( lpssrd->hDlg, -1);
// Exec the screen saver and wait for it to die
ZeroMemory(&StartupInfo,sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = (WORD)SW_NORMAL;
if (CreateProcess(lpssrd->szPath, lpssrd->szArgs, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation))
{
WaitForSingleObject( ProcessInformation.hProcess, INFINITE );
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
}
// Restore Screen saver state
if( bSvrState )
ClassicSystemParametersInfo( SPI_SETSCREENSAVEACTIVE, bSvrState, NULL, FALSE );
// Restart miniture preview
PostMessage(lpssrd->hDlg, WMUSER_SETINITSS, NULL, (LPARAM)TRUE);
PostMessage(lpssrd->hDlg, WM_COMMAND, MAKELONG(IDC_CHOICES, CBN_SELCHANGE),
(LPARAM)GetDlgItem( lpssrd->hDlg, IDC_CHOICES));
PostMessage(lpssrd->hDlg, WMUSER_SETINITSS, NULL, (LPARAM)FALSE);
// Enable setting and preview buttons
EnableWindow( hwndSettings, TRUE );
EnableWindow( hwndPreview, TRUE );
LocalFree( lpv );
if (hiThd)
{
FreeLibraryAndExitThread( hiThd, 0 );
}
return 0;
}
// This routine actually calls the screen saver...
void DoScreenSaver(HWND hWnd, BOOL fSaver)
{
if (g_szSaverName[0] != TEXT('\0'))
{
LPSSRUNDATA lpssrd = (LPSSRUNDATA) LocalAlloc(LMEM_FIXED, sizeof(*lpssrd));
if (lpssrd != NULL)
{
lpssrd->hDlg = hWnd;
StringCchCopy(lpssrd->szPath, ARRAYSIZE(lpssrd->szPath), g_szSaverName);
if (fSaver)
{
_PathBuildArgs(lpssrd->szArgs, ARRAYSIZE(lpssrd->szArgs), g_szSaverName, TEXT(" /s"));
}
else
{
_PathBuildArgs(lpssrd->szArgs, ARRAYSIZE(lpssrd->szArgs), g_szSaverName, TEXT(" /c:%lu"), (LPARAM)hWnd);
}
// Disable setting and preview buttons
HWND hwndSettings = GetDlgItem(hWnd, IDC_SETTING);
HWND hwndPreview = GetDlgItem(hWnd, IDC_TEST);
EnableWindow(hwndSettings, FALSE);
EnableWindow(hwndPreview, FALSE);
DWORD id;
HANDLE hThd = CreateThread(NULL, 0, RunScreenSaverThread, lpssrd, 0, &id);
if (hThd != NULL)
{
CloseHandle(hThd);
}
else
{
// Exec failed, re-enable setting and preview buttons and clean up thread params
EnableWindow(hwndSettings, TRUE);
EnableWindow(hwndPreview, TRUE);
LocalFree(lpssrd);
}
}
}
}
#define SLASH(c) ((c) == TEXT('/') || (c) == TEXT('\\'))
LPTSTR FileName(LPTSTR szPath)
{
LPTSTR sz;
for (sz=szPath; *sz; sz++)
{
NULL;
}
for (; sz>=szPath && !SLASH(*sz) && *sz!=TEXT(':'); sz--)
{
NULL;
}
return ++sz;
}
void AddBackslash(LPTSTR pszPath, DWORD cchPath)
{
if( pszPath[ lstrlen( pszPath ) - 1 ] != TEXT('\\') )
{
StringCchCat( pszPath, cchPath, TEXT("\\") );
}
}
LPTSTR StripPathName(LPTSTR szPath)
{
LPTSTR sz = FileName(szPath);
if (sz > szPath+1 && SLASH(sz[-1]) && sz[-2] != TEXT(':'))
{
sz--;
}
*sz = 0;
return szPath;
}
void AppendPath(LPTSTR pszPath, DWORD cchPath, LPTSTR pszSpec)
{
AddBackslash(pszPath, cchPath);
StringCchCat(pszPath, cchPath, pszSpec);
}
LPTSTR NiceName(LPTSTR szPath)
{
LPTSTR sz;
LPTSTR lpsztmp;
sz = FileName(szPath);
for(lpsztmp = sz; *lpsztmp && *lpsztmp != TEXT('.'); lpsztmp = CharNext(lpsztmp))
{
NULL;
}
*lpsztmp = TEXT('\0');
if (IsCharUpper(sz[0]) && IsCharUpper(sz[1]))
{
CharLower(sz);
CharUpperBuff(sz, 1);
}
return sz;
}
HRESULT HrStrToVariant(IN LPCWSTR pszString, VARIANT * pVar)
{
HRESULT hr = E_INVALIDARG;
if (pszString && pVar)
{
pVar->vt = VT_BSTR;
hr = HrSysAllocStringW(pszString, &pVar->bstrVal);
}
return hr;
}
//===========================
// *** IBasePropPage Interface ***
//===========================
HRESULT CScreenSaverPg::GetAdvancedDialog(OUT IAdvancedDialog ** ppAdvDialog)
{
HRESULT hr = E_INVALIDARG;
if (ppAdvDialog)
{
*ppAdvDialog = NULL;
hr = E_NOTIMPL; // We don't want to add an Advnaced Dialog.
}
return hr;
}
HRESULT CScreenSaverPg::OnApply(IN PROPPAGEONAPPLY oaAction)
{
HRESULT hr = S_OK;
if (PPOAACTION_CANCEL != oaAction)
{
if (m_hDlg)
{
// Make sure the time we have is the last one entered...
SendMessage(m_hDlg, WM_COMMAND, MAKELONG(IDC_SCREENSAVEDELAY, EN_KILLFOCUS), (LPARAM)GetDlgItem(m_hDlg, IDC_SCREENSAVEDELAY));
}
// Try to save the current settings...
_SaveIni(m_hDlg);
}
if (PPOAACTION_OK == oaAction)
{
}
return hr;
}
//===========================
// *** IShellPropSheetExt Interface ***
//===========================
HRESULT CScreenSaverPg::AddPages(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam)
{
HRESULT hr = E_INVALIDARG;
PROPSHEETPAGE psp = {0};
psp.dwSize = sizeof(psp);
psp.hInstance = HINST_THISDLL;
psp.dwFlags = PSP_DEFAULT;
psp.lParam = (LPARAM) this;
psp.pszTemplate = MAKEINTRESOURCE(DLG_SCREENSAVER);
psp.pfnDlgProc = ScreenSaverDlgProc;
HPROPSHEETPAGE hpsp = CreatePropertySheetPage(&psp);
if (hpsp)
{
if (pfnAddPage(hpsp, lParam))
{
hr = S_OK;
}
else
{
DestroyPropertySheetPage(hpsp);
hr = E_FAIL;
}
}
return hr;
}
//===========================
// *** IPropertyBag Interface ***
//===========================
HRESULT CScreenSaverPg::Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog)
{
HRESULT hr = E_INVALIDARG;
if (pszPropName && pVar)
{
if (!StrCmpW(pszPropName, SZ_PBPROP_SCREENSAVER_PATH))
{
// The caller is asking for the ScreenSaver path.
WCHAR szLongPath[MAX_PATH];
DWORD cchSize = GetLongPathName(g_szSaverName, szLongPath, ARRAYSIZE(szLongPath));
if ((0 == cchSize) || (ARRAYSIZE(szLongPath) < cchSize))
{
// It failed
StringCchCopy(szLongPath, ARRAYSIZE(szLongPath), g_szSaverName);
}
hr = HrStrToVariant(szLongPath, pVar);
}
}
return hr;
}
HRESULT CScreenSaverPg::Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar)
{
HRESULT hr = E_INVALIDARG;
if (pszPropName && pVar && (VT_BSTR == pVar->vt))
{
if (!StrCmpW(pszPropName, SZ_PBPROP_SCREENSAVER_PATH))
{
if (m_fScreenSavePolicy && !m_fScreenSaveActive)
{
hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
}
else
{
_SetByPath(pVar->bstrVal);
hr = S_OK;
}
}
}
return hr;
}
HRESULT CScreenSaverPg::_SetByPath(LPCWSTR pszPath)
{
HRESULT hr = S_OK;
// COMPATIBILITY: always use short name
// otherwise some apps fault when peeking at SYSTEM.INI
DWORD cchSize = GetShortPathNameW(pszPath, g_szSaverName, ARRAYSIZE(g_szSaverName));
if ((0 == cchSize) || (ARRAYSIZE(g_szSaverName) < cchSize))
{
// It failed
StringCchCopy(g_szSaverName, ARRAYSIZE(g_szSaverName), pszPath);
}
if (m_hDlg)
{
ComboBox_SetCurSel(m_hDlg, 0);
SelectSSFromList(m_hDlg);
}
return hr;
}
//===========================
// *** IUnknown Interface ***
//===========================
ULONG CScreenSaverPg::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG CScreenSaverPg::Release()
{
ASSERT( 0 != m_cRef );
ULONG cRef = InterlockedDecrement(&m_cRef);
if ( 0 == cRef )
{
delete this;
}
return cRef;
}
HRESULT CScreenSaverPg::QueryInterface(REFIID riid, void **ppvObj)
{
static const QITAB qit[] =
{
QITABENT(CScreenSaverPg, IObjectWithSite),
QITABENT(CScreenSaverPg, IPropertyBag),
QITABENT(CScreenSaverPg, IPersist),
QITABENT(CScreenSaverPg, IBasePropPage),
QITABENTMULTI(CScreenSaverPg, IShellPropSheetExt, IBasePropPage),
{ 0 },
};
return QISearch(this, qit, riid, ppvObj);
}
//===========================
// *** Class Methods ***
//===========================
CScreenSaverPg::CScreenSaverPg() : CObjectCLSID(&PPID_ScreenSaver), m_cRef(1)
{
// This needs to be allocated in Zero Inited Memory.
// Assert that all Member Variables are inited to Zero.
// This is a global that we want to initialize.
g_szSaverName[0] = TEXT('\0');
m_fScreenSavePolicy = FALSE;
m_fScreenSaveActive = TRUE;
m_lWaitTime = 0;
m_hDlg = NULL;
m_fUIInitialized = FALSE;
_InitState();
}
HRESULT CScreenSaverPage_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj)
{
HRESULT hr = E_INVALIDARG;
if (!punkOuter && ppvObj)
{
CScreenSaverPg * pThis = new CScreenSaverPg();
*ppvObj = NULL;
if (pThis)
{
hr = pThis->QueryInterface(riid, ppvObj);
pThis->Release();
}
else
{
hr = E_OUTOFMEMORY;
}
}
return hr;
}