Source code of Windows XP (NT5)
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.

2291 lines
68 KiB

  1. /*****************************************************************************\
  2. FILE: ScreenSaverPg.cpp
  3. DESCRIPTION:
  4. This file contains the COM object implementation that will display the
  5. ScreenSaver tab in the Display Control Panel.
  6. 18-Feb-94 (Tracy Sharpe) Added power management functionality.
  7. Commented out several pieces of code that weren't being
  8. used.
  9. 5/30/2000 (Bryan Starbuck) BryanSt: Turned into C++ and COM. Exposed
  10. as an API so other tabs can communicate with it. This enables
  11. the Plus! Theme page to modify the screen saver.
  12. 11/08/2000 (Bryan Starbuck) BryanSt: Moved from \nt\shell\cpls\desknt5 to
  13. \nt\shell\themes\themeui\.
  14. Copyright (C) Microsoft Corp 1994-2000. All rights reserved.
  15. \*****************************************************************************/
  16. #include "priv.h"
  17. #pragma hdrstop
  18. #include <scrnsave.h>
  19. #include "exe.h"
  20. #include "ScreenSaverPg.h"
  21. #include <MSGinaExports.h> // for ShellIsFriendlyUIActive, etc..
  22. #define SFSE_SYSTEM 0
  23. #define SFSE_PRG 1
  24. #define SFSE_WINDOWS 2
  25. #define SFSE_FILE 3
  26. #define MAX_METHODS 100
  27. #define MIN_MINUTES 1
  28. #define MAX_MINUTES 9999 //The UI will allow upto four digits.
  29. #define BUFFER_SIZE 400
  30. #define WMUSER_SETINITSS (WM_USER + 1)
  31. /* Local funcprototypes... */
  32. void SearchForScrEntries ( UINT, LPCTSTR );
  33. BOOL FreeScrEntries ( void );
  34. int lstrncmp ( LPTSTR, LPTSTR, int );
  35. LPTSTR FileName ( LPTSTR szPath);
  36. LPTSTR StripPathName ( LPTSTR szPath);
  37. LPTSTR NiceName ( LPTSTR szPath);
  38. void AddBackslash(LPTSTR pszPath);
  39. void AppendPath(LPTSTR pszPath, LPTSTR pszSpec);
  40. PTSTR PerformCheck(LPTSTR, BOOL);
  41. void DoScreenSaver(HWND hDlg, BOOL b);
  42. void ScreenSaver_AdjustTimeouts(HWND hWnd,int BaseControlID);
  43. void EnableDisablePowerDelays(HWND hDlg);
  44. TCHAR g_szSaverName[MAX_PATH]; // Screen Saver EXE
  45. HICON hDefaultIcon = NULL;
  46. HICON hIdleWildIcon;
  47. BOOL bWasConfig=0; // We were configing the screen saver
  48. HWND g_hwndTestButton;
  49. HWND g_hwndLastFocus;
  50. BOOL g_fPasswordWasPreviouslyEnabled = FALSE;
  51. BOOL g_fPasswordDirty = FALSE; // tells us if the user has actually changed the state of the password combobox
  52. BOOL g_fFriendlyUI = FALSE; // is winlogon going to switch back to the welcome screen, or call LockWorkStation for real?
  53. BOOL g_fPasswordBoxDeterminedByPolicy = FALSE;
  54. BOOL g_fSettingsButtonOffByPolicy = FALSE;
  55. BOOL g_fTimeoutDeterminedByPolicy = FALSE;
  56. BOOL g_fScreenSaverExecutablePolicy = FALSE;
  57. // Local global variables
  58. HICON hIcons[MAX_METHODS];
  59. UINT wNumMethods = 0;
  60. PTSTR aszMethods[MAX_METHODS];
  61. PTSTR aszFiles[MAX_METHODS];
  62. static const TCHAR c_szDemoParentClass[] = TEXT("SSDemoParent");
  63. // static TCHAR szFileNameCopy[MAX_PATH];
  64. static int g_iMethod;
  65. static BOOL g_fPreviewActive;
  66. static BOOL g_fAdapPwrMgnt = FALSE;
  67. /*
  68. * Registry value for the "Password Protected" check box
  69. *
  70. * These are different for NT and Win95 to keep screen
  71. * savers built exclusivly for Win95 from trying to
  72. * handle password checks. (NT does all password checking
  73. * in the built in security system to maintain C2
  74. * level security)
  75. */
  76. # define SZ_USE_PASSWORD TEXT("ScreenSaverIsSecure")
  77. # define PWRD_REG_TYPE REG_SZ
  78. # define CCH_USE_PWRD_VALUE 2
  79. # define CB_USE_PWRD_VALUE (CCH_USE_PWRD_VALUE * SIZEOF(TCHAR))
  80. TCHAR gpwdRegYes[CCH_USE_PWRD_VALUE] = TEXT("1");
  81. TCHAR gpwdRegNo[CCH_USE_PWRD_VALUE] = TEXT("0");
  82. #define PasswdRegData(f) ((f) ? (PBYTE)gpwdRegYes : (PBYTE)gpwdRegNo)
  83. UDACCEL udAccel[] = {{0,1},{2,5},{4,30},{8,60}};
  84. #include "help.h"
  85. #define IDH_DESK_LOWPOWERCFG IDH_SCRSAVER_GRAPHIC
  86. // To simplify some things, the base control ID of a time control is associated
  87. // with its corresponding ClassicSystemParametersInfo action codes.
  88. typedef struct {
  89. int taBaseControlID;
  90. UINT taGetTimeoutAction;
  91. UINT taSetTimeoutAction;
  92. UINT taGetActiveAction;
  93. UINT taSetActiveAction;
  94. } TIMEOUT_ASSOCIATION;
  95. // Except for the case of the "screen save" delay, each time grouping has three
  96. // controls-- a switch to determine whether that time should be used or not and
  97. // an edit box and an updown control to change the delay time. ("Screen save"
  98. // is turned off my choosing (None) from the screen saver list) These three
  99. // controls must be organized as follows:
  100. #define BCI_DELAY 0
  101. #define BCI_ARROW 1
  102. #define BCI_SWITCH 2
  103. // Associations between base control IDs and ClassicSystemParametersInfo action codes.
  104. // The TA_* #defines are used as symbolic indexes into this array. Note that
  105. // TA_SCREENSAVE is a special case-- it does NOT have a BCI_SWITCH.
  106. #define TA_SCREENSAVE 0
  107. TIMEOUT_ASSOCIATION g_TimeoutAssociation[] = {
  108. IDC_SCREENSAVEDELAY, SPI_GETSCREENSAVETIMEOUT, SPI_SETSCREENSAVETIMEOUT,
  109. SPI_GETSCREENSAVEACTIVE, SPI_SETSCREENSAVEACTIVE,
  110. };
  111. int g_Timeout[] = {
  112. 0,
  113. 0,
  114. 0,
  115. };
  116. HBITMAP g_hbmDemo = NULL;
  117. HBITMAP g_hbmEnergyStar = NULL;
  118. BOOL g_bInitSS = TRUE; // assume we are in initialization process
  119. BOOL g_bChangedSS = FALSE; // changes have been made
  120. class CScreenSaverPg : public CObjectWithSite
  121. , public CObjectCLSID
  122. , public IBasePropPage
  123. , public IPropertyBag
  124. {
  125. public:
  126. //////////////////////////////////////////////////////
  127. // Public Interfaces
  128. //////////////////////////////////////////////////////
  129. // *** IUnknown ***
  130. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  131. virtual STDMETHODIMP_(ULONG) AddRef(void);
  132. virtual STDMETHODIMP_(ULONG) Release(void);
  133. // *** IBasePropPage ***
  134. virtual STDMETHODIMP GetAdvancedDialog(OUT IAdvancedDialog ** ppAdvDialog);
  135. virtual STDMETHODIMP OnApply(IN PROPPAGEONAPPLY oaAction);
  136. // *** IShellPropSheetExt ***
  137. virtual STDMETHODIMP AddPages(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam);
  138. virtual STDMETHODIMP ReplacePage(IN EXPPS uPageID, IN LPFNSVADDPROPSHEETPAGE pfnReplaceWith, IN LPARAM lParam) {return E_NOTIMPL;}
  139. // *** IPropertyBag ***
  140. virtual STDMETHODIMP Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog);
  141. virtual STDMETHODIMP Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar);
  142. protected:
  143. private:
  144. CScreenSaverPg();
  145. virtual ~CScreenSaverPg(void);
  146. // Private Member Variables
  147. int m_cRef;
  148. BOOL m_fSecure;
  149. BOOL m_fUIInitialized; // Have we activated the UI tab and loaded the UI controls with state?
  150. BOOL m_fScreenSavePolicy;
  151. BOOL m_fScreenSaveActive;
  152. LONG m_lWaitTime;
  153. HWND m_hDlg;
  154. // Private Member Functions
  155. HRESULT _InitState(void);
  156. BOOL _InitSSDialog(HWND hDlg);
  157. HRESULT _OnSetActive(void);
  158. HRESULT _OnApply(void);
  159. HRESULT _OnSelectionChanged(void);
  160. HRESULT _SaveIni(HWND hDlg);
  161. HRESULT _SetByPath(LPCWSTR pszPath);
  162. INT_PTR _ScreenSaverDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
  163. friend INT_PTR CALLBACK ScreenSaverDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
  164. friend HRESULT CScreenSaverPage_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj);
  165. };
  166. //===========================
  167. // *** Class Internals & Helpers ***
  168. //===========================
  169. const DWORD aSaverHelpIds[] = {
  170. IDC_NO_HELP_1, NO_HELP,
  171. IDC_CHOICES, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_LISTBOX,
  172. IDC_SSDELAYLABEL, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_WAIT,
  173. IDC_SSDELAYSCALE, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_WAIT,
  174. IDC_SCREENSAVEDELAY, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_WAIT,
  175. IDC_SCREENSAVEARROW, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_WAIT,
  176. IDC_TEST, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_PREVIEW,
  177. IDC_SETTING, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_SETTINGS,
  178. IDC_BIGICONSS, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_MONITOR,
  179. IDC_ENERGY_TEXT, NO_HELP,
  180. IDC_ENERGYSTAR_BMP, IDH_DISPLAY_SCREENSAVER_ENERGYSAVE_GRAPHIC,
  181. IDC_USEPASSWORD, IDH_DISPLAY_SCREENSAVER_SCREENSAVER_PASSWORD_CHECKBOX,
  182. // IDC_SETPASSWORD, IDH_COMM_PASSWDBUTT,
  183. IDC_LOWPOWERCONFIG, IDH_DISPLAY_SCREENSAVER_POWER_BUTTON,
  184. IDC_ENERGY_TEXT2, NO_HELP,
  185. 0, 0
  186. };
  187. // are we going to return to the welcome dialog in the friendly UI case?
  188. BOOL WillReturnToWelcome()
  189. {
  190. HKEY hkey;
  191. BOOL bRet = TRUE;
  192. if (RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
  193. {
  194. TCHAR szTemp[4];
  195. DWORD dwType;
  196. DWORD dwSize = sizeof(szTemp);
  197. if ((RegQueryValueEx(hkey, TEXT("NoAutoReturnToWelcome"), NULL, &dwType, (BYTE*)szTemp, &dwSize) == ERROR_SUCCESS) &&
  198. (dwType == REG_SZ))
  199. {
  200. bRet = !(StrToInt(szTemp));
  201. }
  202. RegCloseKey(hkey);
  203. }
  204. return bRet;
  205. }
  206. /*
  207. * Win95 and NT store different values in different places of the registry to
  208. * determine if the screen saver is secure or not.
  209. *
  210. * We can't really consolidate the two because the screen savers do different
  211. * actions based on which key is set. Win95 screen savers do their own
  212. * password checking, but NT must let the secure desktop winlogon code do it.
  213. *
  214. * Therefore to keep Win95 screen savers from requesting the password twice on
  215. * NT, we use REGSTR_VALUE_USESCRPASSWORD == (REG_DWORD)1 on Win95 to indicate
  216. * that a screen saver should check for the password, and
  217. * "ScreenSaverIsSecure" == (REG_SZ)"1" on NT to indicate that WinLogon should
  218. * check for a password.
  219. *
  220. * This function will deal with the differences.
  221. */
  222. static BOOL IsPasswdSecure(HKEY hKey)
  223. {
  224. union {
  225. DWORD dw;
  226. TCHAR asz[4];
  227. } uData;
  228. DWORD dwSize, dwType;
  229. BOOL fSecure = FALSE;
  230. dwSize = SIZEOF(uData);
  231. if (RegQueryValueEx(hKey,SZ_USE_PASSWORD,NULL, &dwType, (BYTE *)&uData, &dwSize) == ERROR_SUCCESS)
  232. {
  233. switch (dwType)
  234. {
  235. case REG_DWORD:
  236. fSecure = (uData.dw == 1);
  237. break;
  238. case REG_SZ:
  239. fSecure = (uData.asz[0] == TEXT('1'));
  240. break;
  241. }
  242. }
  243. // if we are in friendly UI mode, we might want to treat this as secure even if SZ_USE_PASSWORD is not set
  244. if (g_fFriendlyUI && !fSecure)
  245. {
  246. fSecure = WillReturnToWelcome();
  247. }
  248. return fSecure;
  249. }
  250. static void NEAR
  251. EnableDlgChild( HWND dlg, HWND kid, BOOL val )
  252. {
  253. if( !val && ( kid == GetFocus() ) )
  254. {
  255. // give prev tabstop focus
  256. SendMessage( dlg, WM_NEXTDLGCTL, 1, 0L );
  257. }
  258. EnableWindow( kid, val );
  259. }
  260. static void NEAR
  261. EnableDlgItem( HWND dlg, int idkid, BOOL val )
  262. {
  263. EnableDlgChild( dlg, GetDlgItem( dlg, idkid ), val );
  264. }
  265. HWND GetSSDemoParent( HWND page )
  266. {
  267. static HWND parent = NULL;
  268. if (!parent || !IsWindow(parent))
  269. {
  270. parent = CreateWindowEx( 0, c_szDemoParentClass,
  271. TEXT(""), WS_CHILD | WS_CLIPCHILDREN, 0, 0, 0, 0,
  272. GetDlgItem(page, IDC_BIGICONSS), NULL, HINST_THISDLL, NULL );
  273. }
  274. return parent;
  275. }
  276. void ForwardSSDemoMsg(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  277. {
  278. HWND hwndChild;
  279. hwnd = GetSSDemoParent(hwnd);
  280. if (hwnd)
  281. {
  282. for (hwndChild = GetWindow(hwnd, GW_CHILD); hwnd && (hwndChild != NULL);
  283. hwndChild = GetWindow(hwndChild, GW_HWNDNEXT))
  284. {
  285. SendMessage(hwndChild, uMessage, wParam, lParam);
  286. }
  287. }
  288. }
  289. void ParseSaverName( LPTSTR lpszName )
  290. {
  291. if( *lpszName == TEXT('\"') )
  292. {
  293. LPTSTR lpcSrc = lpszName + 1;
  294. while( *lpcSrc && *lpcSrc != TEXT('\"') )
  295. {
  296. *lpszName++ = *lpcSrc++;
  297. }
  298. *lpszName = 0; // clear second quote
  299. }
  300. }
  301. // YUCK:
  302. // since our screen saver preview is in a different process,
  303. // it is possible that we paint in the wrong order.
  304. // this ugly hack makes sure the demo always paints AFTER the dialog
  305. WNDPROC g_lpOldStaticProc = NULL;
  306. LRESULT StaticSubclassProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
  307. {
  308. LRESULT result =
  309. CallWindowProc(g_lpOldStaticProc, wnd, msg, wp, lp);
  310. if (msg == WM_PAINT)
  311. {
  312. HWND demos = GetSSDemoParent(GetParent(wnd));
  313. if (demos)
  314. {
  315. RedrawWindow(demos, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
  316. }
  317. }
  318. return result;
  319. }
  320. HRESULT CScreenSaverPg::_InitState(void)
  321. {
  322. HRESULT hr = S_OK;
  323. HKEY hKey;
  324. int Counter;
  325. int nActive;
  326. int Timeout;
  327. m_fScreenSavePolicy = FALSE;
  328. m_fScreenSaveActive = TRUE;
  329. // Fetch the timeout value from the win.ini and adjust between 1:00-60:00
  330. for (Counter = 0; Counter < ARRAYSIZE(g_TimeoutAssociation); Counter++)
  331. {
  332. // Fetch the timeout value from the win.ini and adjust between 1:00-60:00
  333. ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taGetTimeoutAction, 0, &Timeout, 0);
  334. // The Win 3.1 guys decided that 0 is a valid ScreenSaveTimeOut value.
  335. // This causes our screen savers not to kick in (who cares?). In any
  336. // case, I changed this to allow 0 to go through. In this way, the
  337. // user immediately sees that the value entered is not valid to fire
  338. // off the screen saver--the OK button is disabled. I don't know if
  339. // I fully agree with this solution--it is just the minimal amount of
  340. // code. The optimal solution would be to ask the 3.1 guys why 0 is
  341. // valid? -cjp
  342. Timeout = min(max(Timeout, 1), MAX_MINUTES * 60);
  343. // Convert Timeout to minutes, rounding up.
  344. Timeout = (Timeout + 59) / 60;
  345. g_Timeout[Counter] = Timeout;
  346. ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taGetActiveAction, 0, &nActive, SPIF_UPDATEINIFILE);
  347. if (Counter == TA_SCREENSAVE)
  348. {
  349. // I found that NTUSER will return random values so we don't use them. If people want to set the policy,
  350. // they should do in the registry.
  351. // m_fScreenSaveActive = nActive;
  352. }
  353. }
  354. // Find the name of the exe used as a screen saver. "" means that the
  355. // default screen saver will be used. First check the system policies
  356. if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Policies\\Microsoft\\Windows\\Control Panel\\Desktop"), &hKey) == ERROR_SUCCESS)
  357. {
  358. BOOL fSettings;
  359. ULONG cbSize;
  360. cbSize = ARRAYSIZE(g_szSaverName);
  361. if (RegQueryValueEx(hKey, TEXT("SCRNSAVE.EXE"), NULL, NULL, (LPBYTE)g_szSaverName, &cbSize) == ERROR_SUCCESS)
  362. {
  363. g_fScreenSaverExecutablePolicy = TRUE;
  364. LogStatus("POLICY ENABLED: ScreenSaver selection is forced to a certain SS file.");
  365. }
  366. cbSize = SIZEOF(m_fSecure);
  367. if (RegQueryValueEx(hKey, TEXT("ScreenSaverIsSecure"), NULL, NULL, (LPBYTE)&m_fSecure, &cbSize) == ERROR_SUCCESS)
  368. {
  369. g_fPasswordBoxDeterminedByPolicy = TRUE;
  370. LogStatus("POLICY ENABLED: ScreenSaverIsSecure is on.");
  371. }
  372. cbSize = SIZEOF( fSettings );
  373. if (RegQueryValueEx(hKey, TEXT("ScreenSaverSettingsButton"), NULL, NULL, (LPBYTE)&fSettings, &cbSize) == ERROR_SUCCESS)
  374. {
  375. g_fSettingsButtonOffByPolicy = TRUE;
  376. LogStatus("POLICY ENABLED: ScreenSaver settings button is disabled.");
  377. }
  378. TCHAR szTemp[20];
  379. if (SUCCEEDED(HrRegGetValueString(hKey, NULL, SZ_POLICY_SCREENSAVETIMEOUT, szTemp, ARRAYSIZE(szTemp))) &&
  380. szTemp[0])
  381. {
  382. m_lWaitTime = StrToInt(szTemp);
  383. g_fTimeoutDeterminedByPolicy = TRUE;
  384. LogStatus("POLICY ENABLED: ScreenSaver timeout value is set.");
  385. }
  386. if (SUCCEEDED(HrRegGetValueString(hKey, NULL, TEXT("ScreenSaveActive"), szTemp, ARRAYSIZE(szTemp))) &&
  387. szTemp[0])
  388. {
  389. m_fScreenSavePolicy = TRUE;
  390. m_fScreenSaveActive = StrToInt(szTemp);
  391. LogStatus("POLICY ENABLED: ScreenSaver Active is set.");
  392. }
  393. RegCloseKey(hKey);
  394. }
  395. if (!g_fScreenSaverExecutablePolicy)
  396. {
  397. if (FAILED(HrRegGetPath(HKEY_CURRENT_USER, SZ_REGKEY_CPDESKTOP, SZ_INIKEY_SCREENSAVER, g_szSaverName, ARRAYSIZE(g_szSaverName))))
  398. {
  399. TCHAR szTempPath[MAX_PATH];
  400. GetPrivateProfileString(SZ_INISECTION_SCREENSAVER, SZ_INIKEY_SCREENSAVER, TEXT(""), g_szSaverName, ARRAYSIZE(g_szSaverName), SZ_INISECTION_SYSTEMINI);
  401. StrCpyN(szTempPath, g_szSaverName, ARRAYSIZE(szTempPath));
  402. SHExpandEnvironmentStrings(szTempPath, g_szSaverName, ARRAYSIZE(g_szSaverName));
  403. }
  404. }
  405. ParseSaverName(g_szSaverName); // remove quotes and params
  406. // Call will fail if monitor or adapter don't support DPMS.
  407. int dummy;
  408. g_fAdapPwrMgnt = ClassicSystemParametersInfo(SPI_GETLOWPOWERACTIVE, 0, &dummy, 0);
  409. if (!g_fAdapPwrMgnt)
  410. {
  411. g_fAdapPwrMgnt = ClassicSystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, &dummy, 0);
  412. }
  413. // initialize the password checkbox
  414. if (RegOpenKey(HKEY_CURRENT_USER,REGSTR_PATH_SCREENSAVE,&hKey) == ERROR_SUCCESS)
  415. {
  416. if (IsPasswdSecure(hKey))
  417. {
  418. g_fPasswordWasPreviouslyEnabled = TRUE;
  419. }
  420. RegCloseKey(hKey);
  421. }
  422. return hr;
  423. }
  424. BOOL CScreenSaverPg::_InitSSDialog(HWND hDlg)
  425. {
  426. WNDCLASS wc;
  427. PTSTR pszMethod;
  428. UINT wTemp,wLoop;
  429. BOOL fContinue;
  430. UINT Counter;
  431. int ControlID;
  432. int wMethod;
  433. DWORD dwUserCount;
  434. HKEY hKey;
  435. HWND hwnd;
  436. int nActive;
  437. TCHAR szBuffer[MAX_PATH];
  438. m_hDlg = hDlg;
  439. m_fUIInitialized = TRUE;
  440. HINSTANCE hInstDeskCPL = LoadLibrary(TEXT("desk.cpl"));
  441. if (!GetClassInfo(HINST_THISDLL, c_szDemoParentClass, &wc))
  442. {
  443. // if two pages put one up, share one dc
  444. wc.style = 0;
  445. wc.lpfnWndProc = DefWindowProc;
  446. wc.cbClsExtra = wc.cbWndExtra = 0;
  447. wc.hInstance = HINST_THISDLL;
  448. wc.hIcon = (HICON)( wc.hCursor = NULL );
  449. wc.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
  450. wc.lpszMenuName = NULL;
  451. wc.lpszClassName = c_szDemoParentClass;
  452. if( !RegisterClass( &wc ) )
  453. return FALSE;
  454. }
  455. // Fetch the timeout value from the win.ini and adjust between 1:00-60:00
  456. for (Counter = 0; Counter < ARRAYSIZE(g_TimeoutAssociation); Counter++)
  457. {
  458. // The base control id specifies the edit control id.
  459. ControlID = g_TimeoutAssociation[Counter].taBaseControlID;
  460. // Set the maximum length of all of the fields...
  461. SendDlgItemMessage(hDlg, ControlID, EM_LIMITTEXT, 4, 0); //Allow four digits.
  462. ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taGetActiveAction, 0, &nActive, SPIF_UPDATEINIFILE);
  463. if (Counter != TA_SCREENSAVE)
  464. {
  465. CheckDlgButton(hDlg, ControlID + BCI_SWITCH, nActive);
  466. }
  467. else
  468. {
  469. // m_fScreenSaveActive = nActive;
  470. }
  471. SetDlgItemInt(hDlg, ControlID, g_Timeout[Counter], FALSE);
  472. // The associated up/down control id must be one after the edit control id.
  473. ControlID++;
  474. SendDlgItemMessage(hDlg, ControlID, UDM_SETRANGE, 0, MAKELPARAM(MAX_MINUTES, MIN_MINUTES));
  475. SendDlgItemMessage(hDlg, ControlID, UDM_SETACCEL, 4, (LPARAM)(LPUDACCEL)udAccel);
  476. }
  477. // Find the name of the exe used as a screen saver. "" means that the
  478. // default screen saver will be used. First check the system policies
  479. if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Policies\\Microsoft\\Windows\\Control Panel\\Desktop"), &hKey) == ERROR_SUCCESS)
  480. {
  481. BOOL fPower;
  482. ULONG cbSize;
  483. cbSize = SIZEOF(fPower);
  484. if (RegQueryValueEx(hKey, TEXT("ScreenSaverPowerButton"), NULL, NULL, (LPBYTE)&fPower, &cbSize) == ERROR_SUCCESS)
  485. {
  486. EnableWindow(GetDlgItem(hDlg, IDC_LOWPOWERCONFIG), FALSE);
  487. }
  488. RegCloseKey(hKey);
  489. }
  490. if (g_fPasswordBoxDeterminedByPolicy)
  491. {
  492. CheckDlgButton(hDlg, IDC_USEPASSWORD, m_fSecure);
  493. EnableWindow(GetDlgItem(hDlg, IDC_USEPASSWORD), FALSE);
  494. }
  495. // if we are running with the new friendly UI w/ multiple users on the system, then we switch to text from "Password protect"
  496. // to "Return to the Welcome screen" because winlogon will do a switch user instead of a LockWorkStation in this case
  497. if (ShellIsFriendlyUIActive() &&
  498. ShellIsMultipleUsersEnabled() &&
  499. (ERROR_SUCCESS == ShellGetUserList(TRUE, &dwUserCount, NULL)) &&
  500. (dwUserCount > 1))
  501. {
  502. if (LoadString(HINST_THISDLL, IDS_RETURNTOWELCOME, szBuffer, ARRAYSIZE(szBuffer)))
  503. {
  504. SetDlgItemText(hDlg, IDC_USEPASSWORD, szBuffer);
  505. g_fFriendlyUI = TRUE;
  506. if (WillReturnToWelcome())
  507. {
  508. g_fPasswordWasPreviouslyEnabled = TRUE;
  509. }
  510. }
  511. }
  512. if (g_fSettingsButtonOffByPolicy)
  513. {
  514. EnableWindow(GetDlgItem(hDlg, IDC_SETTING), FALSE);
  515. }
  516. if (g_fTimeoutDeterminedByPolicy)
  517. {
  518. SetDlgItemInt(hDlg, IDC_SCREENSAVEDELAY, (UINT) m_lWaitTime / 60, FALSE);
  519. EnableWindow(GetDlgItem(hDlg, IDC_SCREENSAVEDELAY), FALSE);
  520. }
  521. if (m_fScreenSavePolicy && !m_fScreenSaveActive)
  522. {
  523. EnableWindow(GetDlgItem(hDlg, IDC_CHOICES), FALSE);
  524. EnableWindow(GetDlgItem(hDlg, IDC_SETTING), FALSE);
  525. EnableWindow(GetDlgItem(hDlg, IDC_SSDELAYLABEL), FALSE);
  526. EnableWindow(GetDlgItem(hDlg, IDC_SCREENSAVEDELAY), FALSE);
  527. EnableWindow(GetDlgItem(hDlg, IDC_SCREENSAVEARROW), FALSE);
  528. EnableWindow(GetDlgItem(hDlg, IDC_SSDELAYSCALE), FALSE);
  529. EnableWindow(GetDlgItem(hDlg, IDC_USEPASSWORD), FALSE);
  530. }
  531. if (g_fScreenSaverExecutablePolicy)
  532. {
  533. EnableWindow(GetDlgItem(hDlg, IDC_CHOICES), FALSE);
  534. }
  535. // Copy all of the variables into their copies...
  536. // lstrcpy(szFileNameCopy, g_szSaverName);
  537. // Load in the default icon...
  538. if (hInstDeskCPL)
  539. {
  540. hDefaultIcon = LoadIcon(hInstDeskCPL, MAKEINTRESOURCE(IDS_ICON));
  541. }
  542. // Find the methods to save the screen. If the method that was
  543. // selected is not found, the program will assume that the
  544. // first method in the list will be the one that is elected...
  545. wNumMethods = 0;
  546. wMethod = -1;
  547. SearchForScrEntries(SFSE_PRG,NULL);
  548. SearchForScrEntries(SFSE_SYSTEM,NULL);
  549. SearchForScrEntries(SFSE_WINDOWS,NULL);
  550. SearchForScrEntries(SFSE_FILE,g_szSaverName);
  551. szBuffer[0] = 0;
  552. TCHAR szNone[MAX_PATH];
  553. LoadString(HINST_THISDLL, IDS_NONE, szNone, ARRAYSIZE(szNone));
  554. // Set up the combo box for the different fields...
  555. SendDlgItemMessage(hDlg, IDC_CHOICES, CB_ADDSTRING, 0, (LPARAM)szNone);
  556. for (wTemp = 0; (wTemp < wNumMethods) && (ARRAYSIZE(aszFiles) > wTemp) && (ARRAYSIZE(aszMethods) > wTemp); wTemp++)
  557. {
  558. // Lock down the information and pass it to the combo box...
  559. pszMethod = aszMethods[wTemp];
  560. wLoop = (UINT)SendDlgItemMessage(hDlg,IDC_CHOICES,CB_ADDSTRING,0, (LPARAM)(pszMethod+1));
  561. SendDlgItemMessage(hDlg, IDC_CHOICES, CB_SETITEMDATA, wLoop, wTemp);
  562. // If we have the correct item, keep a copy so we can select it out of the combo box...
  563. // check for filename only as well as full path name
  564. if (!lstrcmpi(FileName(aszFiles[wTemp]), FileName(g_szSaverName)))
  565. {
  566. wMethod = wTemp;
  567. StrCpyN(szBuffer, pszMethod + 1, ARRAYSIZE(szBuffer));
  568. }
  569. }
  570. if (m_fScreenSavePolicy && !m_fScreenSaveActive)
  571. {
  572. wMethod = -1;
  573. }
  574. // Attempt to select the string we recieved from the
  575. // system.ini entry. If there is no match, select the
  576. // first item from the list...
  577. if ((wMethod == -1) || (wNumMethods == 0))
  578. {
  579. fContinue = TRUE;
  580. }
  581. else
  582. {
  583. if (SendDlgItemMessage(hDlg, IDC_CHOICES, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)szBuffer) == CB_ERR)
  584. fContinue = TRUE;
  585. else
  586. fContinue = FALSE;
  587. }
  588. if (fContinue)
  589. {
  590. SendDlgItemMessage(hDlg,IDC_CHOICES,CB_SETCURSEL,0,0l);
  591. StrCpyN(g_szSaverName, TEXT(""), ARRAYSIZE(g_szSaverName));
  592. wMethod = -1;
  593. }
  594. g_hbmDemo = LoadMonitorBitmap( TRUE );
  595. if (g_hbmDemo)
  596. {
  597. SendDlgItemMessage(hDlg,IDC_BIGICONSS,STM_SETIMAGE, IMAGE_BITMAP,(LPARAM)g_hbmDemo);
  598. }
  599. if (hInstDeskCPL)
  600. {
  601. g_hbmEnergyStar = (HBITMAP) LoadImage(HINST_THISDLL, MAKEINTRESOURCE(IDB_ENERGYSTAR), IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS);
  602. if (g_hbmEnergyStar)
  603. {
  604. SendDlgItemMessage(hDlg, IDC_ENERGYSTAR_BMP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hbmEnergyStar);
  605. }
  606. }
  607. // Hide/Disable the energy related controls if the adaptor/monitor does not
  608. // support power mgnt.
  609. EnableDisablePowerDelays(hDlg);
  610. // subclass the static control so we can synchronize painting
  611. hwnd = GetDlgItem(hDlg, IDC_BIGICONSS);
  612. if (hwnd)
  613. {
  614. g_lpOldStaticProc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
  615. SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)(WNDPROC)StaticSubclassProc);
  616. // Turn off the mirroring style for this control to allow the screen saver preview to work.
  617. SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~RTL_MIRRORED_WINDOW);
  618. }
  619. if (hInstDeskCPL)
  620. {
  621. FreeLibrary(hInstDeskCPL);
  622. }
  623. return TRUE;
  624. }
  625. // Build a command line in a format suitable for passing as the second
  626. // parameter to CreateProcess.
  627. void _PathBuildArgs(LPTSTR pszBuf, DWORD cchBuf, LPCTSTR pszExe, LPCTSTR pszFormat, ...)
  628. {
  629. StrCpyN(pszBuf, pszExe, cchBuf);
  630. PathQuoteSpaces(pszBuf);
  631. int cchBufUsed = lstrlen(pszBuf);
  632. pszBuf += cchBufUsed;
  633. cchBuf -= cchBufUsed;
  634. va_list ap;
  635. va_start(ap, pszFormat);
  636. wvnsprintf(pszBuf, cchBuf, pszFormat, ap);
  637. va_end(ap);
  638. }
  639. #define SS_WINDOWCLOSE_WAIT_LIMIT 5000
  640. BOOL CALLBACK EnumSSChildWindowsProc(HWND hwndC, LPARAM lParam)
  641. {
  642. HWND hwndDemo = (HWND)lParam;
  643. TraceMsg(TF_FUNC, "hwndDemo = %08x hwndC = %08x", hwndDemo, hwndC);
  644. if (IsWindow(hwndDemo) && (hwndDemo == GetParent(hwndC)))
  645. {
  646. DWORD dwStart = GetTickCount();
  647. TraceMsg(TF_FUNC, "dwStart = %08x", dwStart);
  648. while (IsWindow(hwndC))
  649. {
  650. DWORD_PTR dwResult;
  651. TraceMsg(TF_FUNC, "Sending WM_CLOSE tickcount = %08x", GetTickCount());
  652. BOOL fShouldEndTask = !SendMessageTimeout(hwndC, WM_CLOSE, 0, 0,
  653. SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG | SMTO_NORMAL, 2000, &dwResult);
  654. TraceMsg(TF_FUNC, "Return from sending WM_CLOSE tickcount = %08x fShouldEndTask = %d", GetTickCount(), fShouldEndTask);
  655. if (!fShouldEndTask)
  656. {
  657. DWORD dwWait = dwStart + SS_WINDOWCLOSE_WAIT_LIMIT - GetTickCount();
  658. TraceMsg(TF_FUNC, "dwWait = %d", dwWait);
  659. if (dwWait > SS_WINDOWCLOSE_WAIT_LIMIT)
  660. {
  661. TraceMsg(TF_FUNC, "Wait exceeded, ending task");
  662. fShouldEndTask = TRUE;
  663. }
  664. }
  665. if (fShouldEndTask)
  666. {
  667. TraceMsg(TF_FUNC, "Call EndTask task for %08x", hwndC);
  668. EndTask(hwndC, FALSE, FALSE);
  669. TraceMsg(TF_FUNC, "Return from EndTask task for %08x", hwndC);
  670. break;
  671. }
  672. }
  673. }
  674. return TRUE;
  675. }
  676. void SetNewSSDemo(HWND hDlg, int iMethod)
  677. {
  678. HBITMAP hbmOld;
  679. POINT ptIcon;
  680. HWND hwndDemo;
  681. HICON hicon;
  682. RECT rc = {MON_X, MON_Y, MON_X+MON_DX, MON_Y+MON_DY};
  683. hwndDemo = GetSSDemoParent(hDlg);
  684. if (hwndDemo)
  685. {
  686. // blank out the background with dialog color
  687. hbmOld = (HBITMAP) SelectObject(g_hdcMem, g_hbmDemo);
  688. FillRect(g_hdcMem, &rc, GetSysColorBrush(COLOR_DESKTOP));
  689. SelectObject(g_hdcMem, hbmOld);
  690. // make sure the old window is gone
  691. EnumChildWindows(hwndDemo, EnumSSChildWindowsProc, (LPARAM)hwndDemo);
  692. Yield(); // paranoid
  693. Yield(); // really paranoid
  694. ShowWindow(hwndDemo, SW_HIDE);
  695. g_fPreviewActive = FALSE;
  696. if (iMethod >= 0 && aszMethods[iMethod][0] == TEXT('P'))
  697. {
  698. RECT rc;
  699. BITMAP bm;
  700. UpdateWindow(hDlg);
  701. //UpdateWindow(GetDlgItem(hDlg, IDC_BIGICONSS));
  702. TCHAR szArgs[MAX_PATH];
  703. GetObject(g_hbmDemo, sizeof(bm), &bm);
  704. GetClientRect(GetDlgItem(hDlg, IDC_BIGICONSS), &rc);
  705. rc.left = ( rc.right - bm.bmWidth ) / 2 + MON_X;
  706. rc.top = ( rc.bottom - bm.bmHeight ) / 2 + MON_Y;
  707. MoveWindow(hwndDemo, rc.left, rc.top, MON_DX, MON_DY, FALSE);
  708. _PathBuildArgs(szArgs, ARRAYSIZE(szArgs), g_szSaverName, TEXT(" /p %d"), hwndDemo);
  709. if (WinExecN(g_szSaverName, szArgs, SW_NORMAL) > 32)
  710. {
  711. ShowWindow(hwndDemo, SW_SHOWNA);
  712. g_fPreviewActive = TRUE;
  713. return;
  714. }
  715. }
  716. if (iMethod != -1)
  717. {
  718. ptIcon.x = ClassicGetSystemMetrics(SM_CXICON);
  719. ptIcon.y = ClassicGetSystemMetrics(SM_CYICON);
  720. // draw the icon double size
  721. ASSERT(ptIcon.y*2 <= MON_DY);
  722. ASSERT(ptIcon.x*2 <= MON_DX);
  723. hicon = hIcons[iMethod];
  724. if (hicon == NULL && aszMethods[iMethod][0] == TEXT('I'))
  725. hicon = hIdleWildIcon;
  726. if (hicon == NULL)
  727. hicon = hDefaultIcon;
  728. hbmOld = (HBITMAP) SelectObject(g_hdcMem, g_hbmDemo);
  729. DrawIconEx(g_hdcMem,
  730. MON_X + (MON_DX-ptIcon.x*2)/2,
  731. MON_Y + (MON_DY-ptIcon.y*2)/2,
  732. hicon, ptIcon.x*2, ptIcon.y*2, 0, NULL, DI_NORMAL);
  733. SelectObject(g_hdcMem, hbmOld);
  734. }
  735. }
  736. InvalidateRect(GetDlgItem(hDlg, IDC_BIGICONSS), NULL, FALSE);
  737. }
  738. static void SS_SomethingChanged(HWND hDlg)
  739. {
  740. if (!g_bInitSS)
  741. {
  742. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  743. }
  744. }
  745. static void SetScreenSaverPassword(HWND hDlg, int iMethod)
  746. {
  747. if (iMethod >= 0 && aszMethods[iMethod][0] == TEXT('P'))
  748. {
  749. TCHAR szArgs[MAX_PATH];
  750. _PathBuildArgs(szArgs, ARRAYSIZE(szArgs), g_szSaverName, TEXT(" /a %u"), GetParent(hDlg));
  751. WinExecN(g_szSaverName, szArgs, SW_NORMAL);
  752. }
  753. }
  754. INT_PTR CALLBACK ScreenSaverDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  755. {
  756. CScreenSaverPg * pThis = (CScreenSaverPg *)GetWindowLongPtr(hDlg, DWLP_USER);
  757. if (WM_INITDIALOG == wMsg)
  758. {
  759. PROPSHEETPAGE * pPropSheetPage = (PROPSHEETPAGE *) lParam;
  760. if (pPropSheetPage)
  761. {
  762. SetWindowLongPtr(hDlg, DWLP_USER, pPropSheetPage->lParam);
  763. pThis = (CScreenSaverPg *)pPropSheetPage->lParam;
  764. }
  765. }
  766. if (pThis)
  767. return pThis->_ScreenSaverDlgProc(hDlg, wMsg, wParam, lParam);
  768. return DefWindowProc(hDlg, wMsg, wParam, lParam);
  769. }
  770. BOOL SelectSSFromList(HWND hDlg)
  771. {
  772. HWND hwndSSList = GetDlgItem(hDlg, IDC_CHOICES);
  773. BOOL fExistsInList = FALSE;
  774. // Select the current item in the list since another tab
  775. // may have changed this value.
  776. for (UINT nIndex = 0; nIndex < wNumMethods; nIndex++)
  777. {
  778. if (!StrCmpI(g_szSaverName, aszFiles[nIndex]))
  779. {
  780. int nItem = ComboBox_FindString(hwndSSList, 0, &(aszMethods[nIndex][1]));
  781. if (-1 != nItem)
  782. {
  783. ComboBox_SetCurSel(hwndSSList, nItem);
  784. }
  785. fExistsInList = TRUE;
  786. break;
  787. }
  788. }
  789. return fExistsInList;
  790. }
  791. HRESULT CScreenSaverPg::_OnSetActive(void)
  792. {
  793. EnableDisablePowerDelays(m_hDlg);
  794. if (!SelectSSFromList(m_hDlg))
  795. {
  796. UINT wTemp;
  797. UINT wLoop;
  798. // We couldn't find it, so add it to aszMethods[].
  799. SearchForScrEntries(SFSE_FILE, g_szSaverName);
  800. // Now add it to the Drop Down.
  801. for (wTemp = 0; (wTemp < wNumMethods) && (ARRAYSIZE(aszFiles) > wTemp) && (ARRAYSIZE(aszMethods) > wTemp); wTemp++)
  802. {
  803. // Did we find the correct index?
  804. if (!StrCmpI(FileName(aszFiles[wTemp]), FileName(g_szSaverName)))
  805. {
  806. // Yes, so set the index.
  807. wLoop = (UINT)SendDlgItemMessage(m_hDlg, IDC_CHOICES, CB_ADDSTRING, 0, (LPARAM)(aszMethods[wTemp]+1));
  808. SendDlgItemMessage(m_hDlg, IDC_CHOICES, CB_SETITEMDATA, wLoop, wTemp);
  809. break;
  810. }
  811. }
  812. SelectSSFromList(m_hDlg); // Try again now that we added it. Another tab or API may have asked for us to use this SS.
  813. }
  814. if (!g_fPreviewActive)
  815. {
  816. g_bInitSS = TRUE;
  817. SendMessage(m_hDlg, WM_COMMAND, MAKELONG(IDC_CHOICES, CBN_SELCHANGE), (LPARAM)GetDlgItem(m_hDlg, IDC_CHOICES));
  818. g_bInitSS = FALSE;
  819. }
  820. return S_OK;
  821. }
  822. HRESULT CScreenSaverPg::_OnApply(void)
  823. {
  824. // Our parent dialog will be notified of the Apply event and will call our
  825. // IBasePropPage::OnApply() to do the real work.
  826. return S_OK;
  827. }
  828. HRESULT CScreenSaverPg::_OnSelectionChanged(void)
  829. {
  830. HRESULT hr = E_FAIL;
  831. PTSTR pszMethod;
  832. int wMethod;
  833. BOOL fEnable;
  834. // Dump the name of the current selection into the buffer...
  835. int wTemp = (int)SendDlgItemMessage(m_hDlg, IDC_CHOICES, CB_GETCURSEL,0,0l);
  836. if (wTemp)
  837. {
  838. wMethod = (int)SendDlgItemMessage(m_hDlg, IDC_CHOICES, CB_GETITEMDATA, wTemp, 0l);
  839. // Grey the button accordingly...
  840. pszMethod = aszMethods[wMethod];
  841. if ((pszMethod[0] == TEXT('C') || // can config
  842. pszMethod[0] == TEXT('I') || // IdleWild
  843. pszMethod[0] == TEXT('P')) &&
  844. !g_fSettingsButtonOffByPolicy) // can preview
  845. EnableDlgItem(m_hDlg, IDC_SETTING, TRUE);
  846. else
  847. EnableDlgItem(m_hDlg, IDC_SETTING, FALSE);
  848. if (!g_fPasswordBoxDeterminedByPolicy)
  849. {
  850. EnableDlgItem(m_hDlg, IDC_USEPASSWORD, TRUE);
  851. CheckDlgButton(m_hDlg, IDC_USEPASSWORD, g_fPasswordWasPreviouslyEnabled);
  852. }
  853. // For fun, create an extra copy of g_szSaverName...
  854. pszMethod = aszFiles[wMethod];
  855. StrCpyN(g_szSaverName, pszMethod, ARRAYSIZE(g_szSaverName));
  856. fEnable = TRUE;
  857. }
  858. else
  859. {
  860. wMethod = -1;
  861. StrCpyN(g_szSaverName, TEXT(""), ARRAYSIZE(g_szSaverName));
  862. EnableDlgItem(m_hDlg, IDC_SETTING, FALSE);
  863. EnableDlgItem(m_hDlg, IDC_USEPASSWORD, FALSE);
  864. fEnable = FALSE;
  865. }
  866. // Following are enabled as a group... (oh really?)
  867. EnableDlgItem(m_hDlg, IDC_SSDELAYLABEL, fEnable);
  868. EnableDlgItem(m_hDlg, IDC_SCREENSAVEDELAY, !g_fTimeoutDeterminedByPolicy && fEnable);
  869. EnableDlgItem(m_hDlg, IDC_SCREENSAVEARROW, fEnable);
  870. EnableDlgItem(m_hDlg, IDC_SSDELAYSCALE, fEnable);
  871. EnableDlgItem(m_hDlg, IDC_TEST, fEnable);
  872. g_iMethod = (int)wMethod;
  873. SetNewSSDemo(m_hDlg, wMethod);
  874. SS_SomethingChanged(m_hDlg);
  875. return hr;
  876. }
  877. INT_PTR CScreenSaverPg::_ScreenSaverDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
  878. {
  879. NMHDR *lpnm;
  880. switch(message)
  881. {
  882. case WM_NOTIFY:
  883. lpnm = (NMHDR *)lParam;
  884. switch(lpnm->code)
  885. {
  886. case PSN_APPLY:
  887. _OnApply();
  888. break;
  889. // nothing to do on cancel...
  890. case PSN_RESET:
  891. if (g_fPreviewActive)
  892. SetNewSSDemo(hDlg, -1);
  893. break;
  894. case PSN_KILLACTIVE:
  895. if (g_fPreviewActive)
  896. SetNewSSDemo(hDlg, -1);
  897. break;
  898. case PSN_SETACTIVE:
  899. _OnSetActive();
  900. break;
  901. }
  902. break;
  903. case WM_INITDIALOG:
  904. g_bInitSS = TRUE;
  905. _InitSSDialog(hDlg);
  906. g_bInitSS = FALSE;
  907. break;
  908. case WM_DISPLAYCHANGE:
  909. case WM_SYSCOLORCHANGE: {
  910. HBITMAP hbm;
  911. hbm = g_hbmDemo;
  912. g_hbmDemo = LoadMonitorBitmap( TRUE );
  913. if (g_hbmDemo)
  914. {
  915. // Got a new bitmap, use it and delete the old one.
  916. SendDlgItemMessage(hDlg,IDC_BIGICONSS,STM_SETIMAGE, IMAGE_BITMAP,(LPARAM)g_hbmDemo);
  917. if (hbm)
  918. {
  919. DeleteObject(hbm);
  920. }
  921. }
  922. else
  923. {
  924. // Couldn't get a new bitmap, just reuse the old one
  925. g_hbmDemo = hbm;
  926. }
  927. break;
  928. }
  929. case WM_DESTROY:
  930. FreeScrEntries();
  931. if (g_fPreviewActive)
  932. SetNewSSDemo(hDlg, -1);
  933. if (g_hbmDemo)
  934. {
  935. SendDlgItemMessage(hDlg,IDC_BIGICONSS,STM_SETIMAGE,IMAGE_BITMAP, (LPARAM)NULL);
  936. DeleteObject(g_hbmDemo);
  937. }
  938. if (g_hbmEnergyStar)
  939. {
  940. SendDlgItemMessage(hDlg,IDC_ENERGYSTAR_BMP,STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
  941. DeleteObject(g_hbmEnergyStar);
  942. }
  943. break;
  944. case WM_VSCROLL:
  945. if (LOWORD(wParam) == SB_THUMBPOSITION)
  946. ScreenSaver_AdjustTimeouts(hDlg, GetDlgCtrlID((HWND)lParam) - BCI_ARROW);
  947. break;
  948. case WM_HELP:
  949. WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, TEXT("display.hlp"), HELP_WM_HELP, (DWORD_PTR)aSaverHelpIds);
  950. break;
  951. case WM_CONTEXTMENU: // right mouse click
  952. WinHelp((HWND) wParam, TEXT("display.hlp"), HELP_CONTEXTMENU, (DWORD_PTR) aSaverHelpIds);
  953. break;
  954. case WM_QUERYNEWPALETTE:
  955. case WM_PALETTECHANGED:
  956. ForwardSSDemoMsg(hDlg, message, wParam, lParam);
  957. break;
  958. case WMUSER_SETINITSS:
  959. g_bInitSS = (BOOL) lParam;
  960. break;
  961. case WM_COMMAND:
  962. switch(LOWORD(wParam))
  963. {
  964. /* Check for a selection change in the combo box. If there is
  965. one, then update the method number as well as the
  966. configure button... */
  967. case IDC_CHOICES:
  968. if(HIWORD(wParam) == CBN_SELCHANGE)
  969. {
  970. _OnSelectionChanged();
  971. }
  972. break;
  973. /* If the edit box loses focus, translate... */
  974. case IDC_SCREENSAVEDELAY:
  975. if (HIWORD(wParam) == EN_KILLFOCUS)
  976. ScreenSaver_AdjustTimeouts(hDlg, LOWORD(wParam));
  977. else
  978. //check if initdialog is finished
  979. if((FALSE == g_bInitSS) && (EN_CHANGE == (HIWORD(wParam))))
  980. SS_SomethingChanged(hDlg);
  981. break;
  982. case IDC_LOWPOWERCONFIG:
  983. // Configure the low power timeout event.
  984. WinExec("rundll32 shell32.dll,Control_RunDLL powercfg.cpl,,",
  985. SW_SHOWNORMAL);
  986. break;
  987. /* If the user wishes to test... */
  988. case IDC_TEST:
  989. switch( HIWORD( wParam ) )
  990. {
  991. case BN_CLICKED:
  992. DoScreenSaver(hDlg,TRUE);
  993. break;
  994. }
  995. break;
  996. /* Tell the DLL that it can do the configure... */
  997. case IDC_SETTING:
  998. if (HIWORD(wParam) == BN_CLICKED) {
  999. DoScreenSaver(hDlg,FALSE);
  1000. break;
  1001. }
  1002. case IDC_USEPASSWORD:
  1003. if (HIWORD(wParam) == BN_CLICKED)
  1004. {
  1005. // the user actually toggled the checbox, so set our dirty flag
  1006. g_fPasswordDirty = TRUE;
  1007. g_fPasswordWasPreviouslyEnabled = IsDlgButtonChecked( hDlg, IDC_USEPASSWORD );
  1008. SS_SomethingChanged(hDlg);
  1009. break;
  1010. }
  1011. case IDC_SETPASSWORD:
  1012. if (HIWORD(wParam) == BN_CLICKED)
  1013. {
  1014. // ask new savers to change passwords
  1015. int wTemp = (int)SendDlgItemMessage(hDlg,IDC_CHOICES, CB_GETCURSEL,0,0l);
  1016. if (wTemp)
  1017. {
  1018. SetScreenSaverPassword(hDlg, (int)SendDlgItemMessage(hDlg,IDC_CHOICES, CB_GETITEMDATA,wTemp,0l));
  1019. }
  1020. break;
  1021. }
  1022. }
  1023. break;
  1024. case WM_CTLCOLORSTATIC:
  1025. if( (HWND)lParam == GetSSDemoParent( hDlg ) )
  1026. {
  1027. return (INT_PTR)GetStockObject( NULL_BRUSH );
  1028. }
  1029. break;
  1030. }
  1031. return FALSE;
  1032. }
  1033. /*******************************************************************************
  1034. *
  1035. * ScreenSaver_AdjustTimeouts
  1036. *
  1037. * DESCRIPTION:
  1038. * Called whenever the user adjusts the delay of one of the time controls.
  1039. * Adjusts the delays of the other time controls such that the screen saver
  1040. * delay is less than the low power delay and that the low power delay is
  1041. * less than the power off delay.
  1042. *
  1043. * PARAMETERS:
  1044. * hWnd, handle of ScreenSaver window.
  1045. * BaseControlID, base control ID of the radio, edit, and arrow time control
  1046. * combination.
  1047. *
  1048. *******************************************************************************/
  1049. VOID
  1050. NEAR PASCAL
  1051. ScreenSaver_AdjustTimeouts(HWND hWnd, int BaseControlID)
  1052. {
  1053. BOOL fTranslated;
  1054. int Timeout;
  1055. // Get the new timeout for this time control and validate it's contents.
  1056. Timeout = (int) GetDlgItemInt(hWnd, BaseControlID + BCI_DELAY, &fTranslated, FALSE);
  1057. Timeout = min(max(Timeout, 1), MAX_MINUTES);
  1058. SetDlgItemInt(hWnd, BaseControlID + BCI_DELAY, (UINT) Timeout, FALSE);
  1059. // Check the new value of this time control against the other timeouts,
  1060. // adjust their values if necessary. Be careful when changing the order
  1061. // of these conditionals.
  1062. //
  1063. if (BaseControlID == IDC_SCREENSAVEDELAY)
  1064. {
  1065. if (g_Timeout[TA_SCREENSAVE] != Timeout)
  1066. {
  1067. g_Timeout[TA_SCREENSAVE] = Timeout;
  1068. SS_SomethingChanged(hWnd);
  1069. }
  1070. }
  1071. else
  1072. {
  1073. if (Timeout < g_Timeout[TA_SCREENSAVE])
  1074. {
  1075. g_Timeout[TA_SCREENSAVE] = Timeout;
  1076. SetDlgItemInt(hWnd, IDC_SCREENSAVEDELAY, (UINT) Timeout, FALSE);
  1077. }
  1078. }
  1079. }
  1080. void EnableDisablePowerDelays(HWND hDlg)
  1081. {
  1082. int i;
  1083. static idCtrls[] = { IDC_ENERGY_TEXT,
  1084. IDC_ENERGY_TEXT2,
  1085. IDC_ENERGY_TEXT3,
  1086. IDC_ENERGYSTAR_BMP,
  1087. IDC_LOWPOWERCONFIG,
  1088. 0 };
  1089. for (i = 0; idCtrls[i] != 0; i++)
  1090. ShowWindow( GetDlgItem( hDlg, idCtrls[i] ), g_fAdapPwrMgnt ? SW_SHOWNA : SW_HIDE );
  1091. }
  1092. /* This routine will search for entries that are screen savers. The directory
  1093. searched is either the system directory (.. */
  1094. void SearchForScrEntries(UINT wDir, LPCTSTR file)
  1095. {
  1096. TCHAR szPath[MAX_PATH];
  1097. TCHAR szPath2[MAX_PATH];
  1098. HANDLE hfind;
  1099. WIN32_FIND_DATA fd;
  1100. // don't do any work if no space left
  1101. if( wNumMethods >= MAX_METHODS )
  1102. return;
  1103. /* Get the directory where the program resides... */
  1104. GetModuleFileName(HINST_THISDLL, szPath, ARRAYSIZE(szPath));
  1105. StripPathName(szPath);
  1106. switch ( wDir )
  1107. {
  1108. case SFSE_WINDOWS:
  1109. /* Search the windows directory and place the path with the \ in
  1110. the szPath variable... */
  1111. if (!GetWindowsDirectory(szPath2, ARRAYSIZE(szPath2)))
  1112. {
  1113. szPath2[0] = 0;
  1114. }
  1115. sfseSanityCheck:
  1116. /* if same dir as where it was launched, don't search again */
  1117. if (!lstrcmpi(szPath, szPath2))
  1118. return;
  1119. StrCpyN(szPath, szPath2, ARRAYSIZE(szPath));
  1120. break;
  1121. case SFSE_SYSTEM:
  1122. /* Search the system directory and place the path with the \ in
  1123. the szPath variable... */
  1124. GetSystemDirectory(szPath2, ARRAYSIZE(szPath2));
  1125. goto sfseSanityCheck;
  1126. case SFSE_FILE:
  1127. /* Search the directory containing 'file' */
  1128. StrCpyN(szPath2, file, ARRAYSIZE(szPath2));
  1129. StripPathName(szPath2);
  1130. goto sfseSanityCheck;
  1131. }
  1132. AppendPath(szPath, TEXT("*.scr"));
  1133. if( ( hfind = FindFirstFile( szPath, &fd ) ) != INVALID_HANDLE_VALUE )
  1134. {
  1135. StripPathName(szPath);
  1136. do
  1137. {
  1138. PTSTR pszDesc;
  1139. BOOL fLFN;
  1140. fLFN = !(fd.cAlternateFileName[0] == 0 ||
  1141. lstrcmp(fd.cFileName, fd.cAlternateFileName) == 0);
  1142. StrCpyN(szPath2, szPath, ARRAYSIZE(szPath2));
  1143. AppendPath(szPath2, fd.cFileName);
  1144. // Note: PerformCheck does an alloc
  1145. if( ( pszDesc = PerformCheck( szPath2, fLFN ) ) != NULL )
  1146. {
  1147. BOOL bAdded = FALSE;
  1148. UINT i;
  1149. for( i = 0; i < wNumMethods; i++ )
  1150. {
  1151. if( !lstrcmpi( pszDesc, aszMethods[ i ] ) )
  1152. {
  1153. bAdded = TRUE;
  1154. break;
  1155. }
  1156. }
  1157. if( !bAdded )
  1158. {
  1159. PTSTR pszEntries;
  1160. // COMPATIBILITY: always use short name
  1161. // otherwise some apps fault when peeking at SYSTEM.INI
  1162. if( fLFN )
  1163. {
  1164. StrCpyN(szPath2, szPath, ARRAYSIZE(szPath2));
  1165. AppendPath(szPath2, fd.cAlternateFileName);
  1166. }
  1167. if( ( pszEntries = StrDup( szPath2 ) ) != NULL )
  1168. {
  1169. if (pszDesc[0] != TEXT('P'))
  1170. hIcons[wNumMethods] = ExtractIcon(HINST_THISDLL, szPath2, 0);
  1171. else
  1172. hIcons[wNumMethods] = NULL;
  1173. aszMethods[wNumMethods] = pszDesc;
  1174. aszFiles[wNumMethods] = pszEntries;
  1175. wNumMethods++;
  1176. bAdded = TRUE;
  1177. }
  1178. }
  1179. if( !bAdded )
  1180. LocalFree((HLOCAL)pszDesc);
  1181. }
  1182. } while( FindNextFile( hfind, &fd ) && ( wNumMethods < MAX_METHODS ) );
  1183. FindClose(hfind);
  1184. }
  1185. return;
  1186. }
  1187. //
  1188. // This routine checks a given file to see if it is indeed a screen saver
  1189. // executable...
  1190. //
  1191. // a valid screen saver exe has the following description line:
  1192. //
  1193. // SCRNSAVE [c] : description :
  1194. //
  1195. // SCRNSAVE is a required name that indicates a screen saver.
  1196. //
  1197. PTSTR PerformCheck(LPTSTR lpszFilename, BOOL fLFN)
  1198. {
  1199. int i;
  1200. TCHAR chConfig=TEXT('C'); // assume configure
  1201. LPTSTR pch;
  1202. DWORD dw;
  1203. WORD Version;
  1204. WORD Magic;
  1205. TCHAR szBuffer[MAX_PATH];
  1206. DWORD cchSizePch = (ARRAYSIZE(szBuffer)-1);
  1207. // Get the description...
  1208. pch = szBuffer + 1;
  1209. // if we have a LFN (Long File Name) dont bother getting the
  1210. // exe descrription
  1211. dw = GetExeInfo(lpszFilename, pch, cchSizePch, fLFN ? GEI_EXPVER : GEI_DESCRIPTION);
  1212. Version = HIWORD(dw);
  1213. Magic = LOWORD(dw);
  1214. if (dw == 0)
  1215. return NULL;
  1216. if (Magic == PEMAGIC || fLFN)
  1217. {
  1218. BOOL fGotName = FALSE;
  1219. if (!fLFN)
  1220. {
  1221. HINSTANCE hSaver = LoadLibraryEx(lpszFilename, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1222. // We have a 32 bit screen saver with a short name, look for an NT style
  1223. // decription in it's string table
  1224. if (hSaver)
  1225. {
  1226. if (LoadString(hSaver, IDS_DESCRIPTION, pch, cchSizePch))
  1227. {
  1228. fGotName = TRUE;
  1229. }
  1230. FreeLibrary(hSaver);
  1231. }
  1232. }
  1233. if (!fGotName)
  1234. {
  1235. // we have a LFN (LongFileName) or a Win32 screen saver,
  1236. // Win32 exe's in general dont have a description field so
  1237. // we assume they can configure. We also try to build
  1238. // a "nice" name for it.
  1239. StrCpyN(pch, lpszFilename, cchSizePch);
  1240. pch = FileName(pch); // strip path part
  1241. if ( ((TCHAR)CharUpper((LPTSTR)(pch[0]))) == TEXT('S') && ((TCHAR)CharUpper((LPTSTR)(pch[1]))) == TEXT('S')) // map SSBEZIER.SCR to BEZIER.SCR
  1242. pch+=2;
  1243. pch = NiceName(pch); // map BEZIER.SCR to Bezier
  1244. }
  1245. }
  1246. else
  1247. {
  1248. LPTSTR pchTemp;
  1249. // we have a 8.3 file name 16bit screen saveer, parse the
  1250. // description string from the exehdr
  1251. /* Check to make sure that at least the 11 characters needed for info
  1252. are there... */
  1253. if (lstrlen(pch) < 9)
  1254. return NULL;
  1255. /* Check the first 8 characters for the string... */
  1256. if (lstrncmp(TEXT("SCRNSAVE"), pch, 8))
  1257. return NULL;
  1258. // If successful, allocate enough space for the string and copy the
  1259. // string to the new one...
  1260. pch = pch + 8; // skip over 'SCRNSAVE'
  1261. while (*pch==TEXT(' ')) // advance over white space
  1262. pch++;
  1263. if (*pch==TEXT('C') || *pch==TEXT('c')) // parse the configure flag
  1264. {
  1265. chConfig = TEXT('C');
  1266. pch++;
  1267. }
  1268. if (*pch==TEXT('X') || *pch==TEXT('x')) // parse the don't configure flag
  1269. chConfig = *pch++;
  1270. // we might be pointing at a name or separation goop
  1271. pchTemp = pch; // remember this spot
  1272. while (*pch && *pch!=TEXT(':')) // find separator
  1273. pch++;
  1274. while (*pch==TEXT(':') || *pch==TEXT(' ')) // advance over whtspc/last colon
  1275. pch++;
  1276. // if we haven't found a name yet fall back on the saved location
  1277. if (!*pch)
  1278. pch = pchTemp;
  1279. while (*pch==TEXT(':') || *pch==TEXT(' ')) // re-advance over whtspc
  1280. pch++;
  1281. /* In case the screen saver has version information information
  1282. embedded after the name, check to see if there is a colon TEXT(':')
  1283. in the description and replace it with a NULL... */
  1284. for (i=0; pch[i]; i++) //
  1285. {
  1286. #if defined(DBCS) || (defined(FE_SB) && !defined(UNICODE))
  1287. if (IsDBCSLeadByte(pch[i]))
  1288. {
  1289. i++;
  1290. }
  1291. else
  1292. #endif
  1293. if (pch[i]==TEXT(':'))
  1294. pch[i]=0;
  1295. }
  1296. // Space is OK for DBCS (FE)
  1297. while(i>0 && pch[i-1]==TEXT(' ')) // remove trailing space
  1298. pch[--i]=0;
  1299. }
  1300. #ifdef DEBUG
  1301. if (Magic != PEMAGIC)
  1302. {
  1303. lstrcat(pch, TEXT(" (16-bit)"));
  1304. }
  1305. if (Version == 0x030A)
  1306. lstrcat(pch, TEXT(" (3.10)"));
  1307. if (Version == 0x0400)
  1308. lstrcat(pch, TEXT(" (4.00)"));
  1309. #endif
  1310. //
  1311. // assume any Win32 4.0 screen saver can do Preview mode
  1312. //
  1313. if (chConfig == TEXT('C') && Version >= 0x0400 && Magic == PEMAGIC)
  1314. chConfig = TEXT('P'); // mark as configurable/preview
  1315. pch[-1] = chConfig;
  1316. return StrDup(pch-1);
  1317. }
  1318. BOOL FreeScrEntries( void )
  1319. {
  1320. UINT wLoop;
  1321. for(wLoop = 0; wLoop < wNumMethods; wLoop++)
  1322. {
  1323. if(aszMethods[wLoop] != NULL)
  1324. LocalFree((HANDLE)aszMethods[wLoop]);
  1325. if(aszFiles[wLoop] != NULL)
  1326. LocalFree((HANDLE)aszFiles[wLoop]);
  1327. if(hIcons[wLoop] != NULL)
  1328. FreeResource(hIcons[wLoop]);
  1329. }
  1330. if (hDefaultIcon)
  1331. FreeResource(hDefaultIcon);
  1332. if (hIdleWildIcon)
  1333. FreeResource(hIdleWildIcon);
  1334. hDefaultIcon=hIdleWildIcon=NULL;
  1335. wNumMethods = 0;
  1336. return TRUE;
  1337. }
  1338. int lstrncmp( LPTSTR lpszString1, LPTSTR lpszString2, int nNum )
  1339. {
  1340. /* While we can still compare characters, compare. If the strings are
  1341. of different lengths, characters will be different... */
  1342. while(nNum)
  1343. {
  1344. if(*lpszString1 != *lpszString2)
  1345. return *lpszString1 - *lpszString2;
  1346. lpszString1++;
  1347. lpszString2++;
  1348. nNum--;
  1349. }
  1350. return 0;
  1351. }
  1352. HRESULT CScreenSaverPg::_SaveIni(HWND hDlg)
  1353. {
  1354. HRESULT hr = S_OK;
  1355. LPTSTR pszMethod = TEXT("");
  1356. BOOL bSSActive;
  1357. int wMethod,wTemp;
  1358. UINT Counter;
  1359. HKEY hKey;
  1360. TCHAR szBuffer[MAX_PATH];
  1361. if (m_fUIInitialized)
  1362. {
  1363. // Find the current method selection...
  1364. wTemp = 0;
  1365. if (wNumMethods)
  1366. {
  1367. // Dump the name of the current selection into the buffer...
  1368. wTemp = (int)SendDlgItemMessage(hDlg, IDC_CHOICES, CB_GETCURSEL, 0, 0);
  1369. if (wTemp)
  1370. {
  1371. wMethod = (int)SendDlgItemMessage(hDlg, IDC_CHOICES, CB_GETITEMDATA, wTemp, 0);
  1372. // Dump the method name into the buffer...
  1373. pszMethod = aszFiles[wMethod];
  1374. }
  1375. }
  1376. // since "(None)" is always the first entry in the combobox, we can use it to see if we have
  1377. // a screensaver or not
  1378. if (wTemp == 0)
  1379. {
  1380. // 0th inxed is "(None)" so the screensaver is disabled
  1381. bSSActive = FALSE;
  1382. }
  1383. else
  1384. {
  1385. bSSActive = TRUE;
  1386. }
  1387. }
  1388. else
  1389. {
  1390. TCHAR szNone[MAX_PATH];
  1391. LoadString(HINST_THISDLL, IDS_NONE, szNone, ARRAYSIZE(szNone));
  1392. if ((g_szSaverName[0] == TEXT('\0')) || (lstrcmpi(szNone, g_szSaverName) == 0))
  1393. {
  1394. // screensaver was not set, OR it was set to "(None)" -- therefore it is not active
  1395. bSSActive = FALSE;
  1396. }
  1397. else
  1398. {
  1399. bSSActive = TRUE;
  1400. }
  1401. pszMethod = g_szSaverName;
  1402. }
  1403. // Now quote any spaces
  1404. BOOL hasspace = FALSE;
  1405. LPTSTR pc;
  1406. for (pc = pszMethod; *pc; pc++)
  1407. {
  1408. if (*pc == TEXT(' '))
  1409. {
  1410. hasspace = TRUE;
  1411. break;
  1412. }
  1413. }
  1414. if (hasspace)
  1415. {
  1416. // if we need to add quotes we'll need two sets
  1417. // because GetBlahBlahProfileBlah APIs strip quotes
  1418. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), TEXT("\"\"%s\"\""), pszMethod);
  1419. }
  1420. else
  1421. {
  1422. StrCpyN(szBuffer, pszMethod, ARRAYSIZE(szBuffer));
  1423. }
  1424. // Save the buffer...
  1425. if (!WritePrivateProfileString(SZ_INISECTION_SCREENSAVER, SZ_INIKEY_SCREENSAVER, (szBuffer[0] != TEXT('\0') ? szBuffer : NULL), SZ_INISECTION_SYSTEMINI))
  1426. {
  1427. hr = HRESULT_FROM_WIN32(GetLastError());
  1428. }
  1429. // In win2k we decided to leave the screensaver ALWAYS active so that when the policy changed, it would take
  1430. // w/out rebooting. This has become a PITA so we now do it the right way.
  1431. ClassicSystemParametersInfo(SPI_SETSCREENSAVEACTIVE, bSSActive, NULL, SPIF_UPDATEINIFILE);
  1432. for (Counter = 0; Counter < (sizeof(g_TimeoutAssociation) / sizeof(TIMEOUT_ASSOCIATION)); Counter++)
  1433. {
  1434. ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taSetTimeoutAction, (UINT) (g_Timeout[Counter] * 60), NULL, SPIF_UPDATEINIFILE);
  1435. if (Counter != TA_SCREENSAVE)
  1436. {
  1437. ClassicSystemParametersInfo(g_TimeoutAssociation[Counter].taSetActiveAction,
  1438. IsDlgButtonChecked(hDlg, g_TimeoutAssociation[Counter].taBaseControlID + BCI_SWITCH),
  1439. NULL,
  1440. SPIF_UPDATEINIFILE);
  1441. }
  1442. }
  1443. // save the state of the TEXT("use password") checkbox
  1444. if (RegCreateKey(HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE, &hKey) == ERROR_SUCCESS)
  1445. {
  1446. if (g_fPasswordDirty)
  1447. {
  1448. if (g_fFriendlyUI)
  1449. {
  1450. // the user actually toggled the value, so don't automatically return to the welcome screen since they have
  1451. // now made their own decision on this subject
  1452. RegSetValueEx(hKey, TEXT("NoAutoReturnToWelcome"), 0, REG_SZ, (BYTE*)TEXT("1"), sizeof(TEXT("1")));
  1453. RegSetValueEx(hKey, SZ_USE_PASSWORD, 0, PWRD_REG_TYPE, PasswdRegData(IsDlgButtonChecked(hDlg,IDC_USEPASSWORD)), CB_USE_PWRD_VALUE);
  1454. }
  1455. else
  1456. {
  1457. RegSetValueEx(hKey, SZ_USE_PASSWORD, 0, PWRD_REG_TYPE, PasswdRegData(IsDlgButtonChecked(hDlg,IDC_USEPASSWORD)), CB_USE_PWRD_VALUE);
  1458. }
  1459. }
  1460. RegCloseKey(hKey);
  1461. }
  1462. // Broadcast a WM_WININICHANGE message...
  1463. SendNotifyMessage(HWND_BROADCAST, WM_WININICHANGE, 0, (LPARAM)TEXT("Windows"));
  1464. return hr;
  1465. }
  1466. /*
  1467. * Thread for DoScreenSaver()
  1468. */
  1469. typedef struct
  1470. {
  1471. HWND hDlg;
  1472. TCHAR szPath[MAX_PATH];
  1473. TCHAR szArgs[MAX_PATH];
  1474. } SSRUNDATA, *LPSSRUNDATA;
  1475. DWORD RunScreenSaverThread( LPVOID lpv )
  1476. {
  1477. BOOL bSvrState;
  1478. LPSSRUNDATA lpssrd;
  1479. HWND hwndSettings, hwndPreview;
  1480. STARTUPINFO StartupInfo;
  1481. PROCESS_INFORMATION ProcessInformation;
  1482. HINSTANCE hiThd;
  1483. TCHAR szPath[MAX_PATH];
  1484. // Lock ourselves in mem so we don't fault if app unloads us
  1485. GetModuleFileName(HINST_THISDLL, szPath, ARRAYSIZE(szPath));
  1486. hiThd = LoadLibrary( szPath );
  1487. lpssrd = (LPSSRUNDATA)lpv;
  1488. hwndSettings = GetDlgItem( lpssrd->hDlg, IDC_SETTING);
  1489. hwndPreview = GetDlgItem( lpssrd->hDlg, IDC_TEST);
  1490. // Save previous screen saver state
  1491. ClassicSystemParametersInfo( SPI_GETSCREENSAVEACTIVE,0, &bSvrState, FALSE);
  1492. // Disable current screen saver
  1493. if( bSvrState )
  1494. ClassicSystemParametersInfo( SPI_SETSCREENSAVEACTIVE,FALSE, NULL, FALSE );
  1495. // Stop the miniture preview screen saver
  1496. if (g_fPreviewActive)
  1497. SetNewSSDemo( lpssrd->hDlg, -1);
  1498. // Exec the screen saver and wait for it to die
  1499. ZeroMemory(&StartupInfo,sizeof(StartupInfo));
  1500. StartupInfo.cb = sizeof(StartupInfo);
  1501. StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  1502. StartupInfo.wShowWindow = (WORD)SW_NORMAL;
  1503. if (CreateProcess(lpssrd->szPath, lpssrd->szArgs, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation))
  1504. {
  1505. WaitForSingleObject( ProcessInformation.hProcess, INFINITE );
  1506. CloseHandle(ProcessInformation.hProcess);
  1507. CloseHandle(ProcessInformation.hThread);
  1508. }
  1509. // Restore Screen saver state
  1510. if( bSvrState )
  1511. ClassicSystemParametersInfo( SPI_SETSCREENSAVEACTIVE, bSvrState, NULL, FALSE );
  1512. // Restart miniture preview
  1513. PostMessage(lpssrd->hDlg, WMUSER_SETINITSS, NULL, (LPARAM)TRUE);
  1514. PostMessage(lpssrd->hDlg, WM_COMMAND, MAKELONG(IDC_CHOICES, CBN_SELCHANGE),
  1515. (LPARAM)GetDlgItem( lpssrd->hDlg, IDC_CHOICES));
  1516. PostMessage(lpssrd->hDlg, WMUSER_SETINITSS, NULL, (LPARAM)FALSE);
  1517. // Enable setting and preview buttons
  1518. EnableWindow( hwndSettings, TRUE );
  1519. EnableWindow( hwndPreview, TRUE );
  1520. LocalFree( lpv );
  1521. if (hiThd)
  1522. {
  1523. FreeLibraryAndExitThread( hiThd, 0 );
  1524. }
  1525. return 0;
  1526. }
  1527. // This routine actually calls the screen saver...
  1528. void DoScreenSaver(HWND hWnd, BOOL fSaver)
  1529. {
  1530. if (g_szSaverName[0] != TEXT('\0'))
  1531. {
  1532. LPSSRUNDATA lpssrd = (LPSSRUNDATA) LocalAlloc(LMEM_FIXED, sizeof(*lpssrd));
  1533. if (lpssrd != NULL)
  1534. {
  1535. lpssrd->hDlg = hWnd;
  1536. StrCpyN(lpssrd->szPath, g_szSaverName, ARRAYSIZE(lpssrd->szPath));
  1537. if (fSaver)
  1538. {
  1539. _PathBuildArgs(lpssrd->szArgs, ARRAYSIZE(lpssrd->szArgs), g_szSaverName, TEXT(" /s"));
  1540. }
  1541. else
  1542. {
  1543. _PathBuildArgs(lpssrd->szArgs, ARRAYSIZE(lpssrd->szArgs), g_szSaverName, TEXT(" /c:%lu"), (LPARAM)hWnd);
  1544. }
  1545. // Disable setting and preview buttons
  1546. HWND hwndSettings = GetDlgItem(hWnd, IDC_SETTING);
  1547. HWND hwndPreview = GetDlgItem(hWnd, IDC_TEST);
  1548. EnableWindow(hwndSettings, FALSE);
  1549. EnableWindow(hwndPreview, FALSE);
  1550. DWORD id;
  1551. HANDLE hThd = CreateThread(NULL, 0, RunScreenSaverThread, lpssrd, 0, &id);
  1552. if (hThd != NULL)
  1553. {
  1554. CloseHandle(hThd);
  1555. }
  1556. else
  1557. {
  1558. // Exec failed, re-enable setting and preview buttons and clean up thread params
  1559. EnableWindow(hwndSettings, TRUE);
  1560. EnableWindow(hwndPreview, TRUE);
  1561. LocalFree(lpssrd);
  1562. }
  1563. }
  1564. }
  1565. }
  1566. #define SLASH(c) ((c) == TEXT('/') || (c) == TEXT('\\'))
  1567. LPTSTR FileName(LPTSTR szPath)
  1568. {
  1569. LPTSTR sz;
  1570. for (sz=szPath; *sz; sz++)
  1571. {
  1572. NULL;
  1573. }
  1574. #if defined(DBCS) || (defined(FE_SB) && !defined(UNICODE))
  1575. for (; sz>szPath && !SLASH(*sz) && *sz!=TEXT(':'); sz=CharPrev(szPath, sz))
  1576. #else
  1577. for (; sz>=szPath && !SLASH(*sz) && *sz!=TEXT(':'); sz--)
  1578. #endif
  1579. {
  1580. NULL;
  1581. }
  1582. #if defined(DBCS) || (defined(FE_SB) && !defined(UNICODE))
  1583. if ( !IsDBCSLeadByte(*sz) && (SLASH(*sz) || *sz == TEXT(':')) )
  1584. {
  1585. sz = CharNext(sz);
  1586. }
  1587. return sz;
  1588. #else
  1589. return ++sz;
  1590. #endif
  1591. }
  1592. void AddBackslash(LPTSTR pszPath)
  1593. {
  1594. #if defined(DBCS) || (defined(FE_SB) && !defined(UNICODE))
  1595. LPTSTR lpsz = &pszPath[lstrlen(pszPath)];
  1596. lpsz = CharPrev(pszPath, lpsz);
  1597. if ( *lpsz != TEXT('\\') )
  1598. #else
  1599. if( pszPath[ lstrlen( pszPath ) - 1 ] != TEXT('\\') )
  1600. #endif
  1601. {
  1602. lstrcat( pszPath, TEXT("\\") );
  1603. }
  1604. }
  1605. LPTSTR StripPathName(LPTSTR szPath)
  1606. {
  1607. LPTSTR sz;
  1608. #if defined(DBCS) || (defined(FE_SB) && !defined(UNICODE))
  1609. LPTSTR szFile;
  1610. #endif
  1611. sz = FileName(szPath);
  1612. #if defined(DBCS) || (defined(FE_SB) && !defined(UNICODE))
  1613. szFile = sz;
  1614. if ( szFile >szPath+1 )
  1615. {
  1616. szFile = CharPrev( szPath, szFile );
  1617. if (SLASH(*szFile))
  1618. {
  1619. szFile = CharPrev(szPath, szFile);
  1620. if (*szFile != TEXT(':'))
  1621. {
  1622. sz--;
  1623. }
  1624. }
  1625. }
  1626. #else
  1627. if (sz > szPath+1 && SLASH(sz[-1]) && sz[-2] != TEXT(':'))
  1628. {
  1629. sz--;
  1630. }
  1631. #endif
  1632. *sz = 0;
  1633. return szPath;
  1634. }
  1635. void AppendPath(LPTSTR pszPath, LPTSTR pszSpec)
  1636. {
  1637. AddBackslash(pszPath);
  1638. lstrcat(pszPath, pszSpec);
  1639. }
  1640. LPTSTR NiceName(LPTSTR szPath)
  1641. {
  1642. LPTSTR sz;
  1643. LPTSTR lpsztmp;
  1644. sz = FileName(szPath);
  1645. for(lpsztmp = sz; *lpsztmp && *lpsztmp != TEXT('.'); lpsztmp = CharNext(lpsztmp))
  1646. {
  1647. NULL;
  1648. }
  1649. *lpsztmp = TEXT('\0');
  1650. if (IsCharUpper(sz[0]) && IsCharUpper(sz[1]))
  1651. {
  1652. CharLower(sz);
  1653. CharUpperBuff(sz, 1);
  1654. }
  1655. return sz;
  1656. }
  1657. HRESULT HrStrToVariant(IN LPCWSTR pszString, VARIANT * pVar)
  1658. {
  1659. HRESULT hr = E_INVALIDARG;
  1660. if (pszString && pVar)
  1661. {
  1662. pVar->vt = VT_BSTR;
  1663. hr = HrSysAllocStringW(pszString, &pVar->bstrVal);
  1664. }
  1665. return hr;
  1666. }
  1667. //===========================
  1668. // *** IBasePropPage Interface ***
  1669. //===========================
  1670. HRESULT CScreenSaverPg::GetAdvancedDialog(OUT IAdvancedDialog ** ppAdvDialog)
  1671. {
  1672. HRESULT hr = E_INVALIDARG;
  1673. if (ppAdvDialog)
  1674. {
  1675. *ppAdvDialog = NULL;
  1676. hr = E_NOTIMPL; // We don't want to add an Advnaced Dialog.
  1677. }
  1678. return hr;
  1679. }
  1680. HRESULT CScreenSaverPg::OnApply(IN PROPPAGEONAPPLY oaAction)
  1681. {
  1682. HRESULT hr = S_OK;
  1683. if (PPOAACTION_CANCEL != oaAction)
  1684. {
  1685. if (m_hDlg)
  1686. {
  1687. // Make sure the time we have is the last one entered...
  1688. SendMessage(m_hDlg, WM_COMMAND, MAKELONG(IDC_SCREENSAVEDELAY, EN_KILLFOCUS), (LPARAM)GetDlgItem(m_hDlg, IDC_SCREENSAVEDELAY));
  1689. }
  1690. // Try to save the current settings...
  1691. _SaveIni(m_hDlg);
  1692. }
  1693. if (PPOAACTION_OK == oaAction)
  1694. {
  1695. }
  1696. return hr;
  1697. }
  1698. //===========================
  1699. // *** IShellPropSheetExt Interface ***
  1700. //===========================
  1701. HRESULT CScreenSaverPg::AddPages(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam)
  1702. {
  1703. HRESULT hr = E_INVALIDARG;
  1704. PROPSHEETPAGE psp = {0};
  1705. psp.dwSize = sizeof(psp);
  1706. psp.hInstance = HINST_THISDLL;
  1707. psp.dwFlags = PSP_DEFAULT;
  1708. psp.lParam = (LPARAM) this;
  1709. psp.pszTemplate = MAKEINTRESOURCE(DLG_SCREENSAVER);
  1710. psp.pfnDlgProc = ScreenSaverDlgProc;
  1711. HPROPSHEETPAGE hpsp = CreatePropertySheetPage(&psp);
  1712. if (hpsp)
  1713. {
  1714. if (pfnAddPage(hpsp, lParam))
  1715. {
  1716. hr = S_OK;
  1717. }
  1718. else
  1719. {
  1720. DestroyPropertySheetPage(hpsp);
  1721. hr = E_FAIL;
  1722. }
  1723. }
  1724. return hr;
  1725. }
  1726. //===========================
  1727. // *** IPropertyBag Interface ***
  1728. //===========================
  1729. HRESULT CScreenSaverPg::Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog)
  1730. {
  1731. HRESULT hr = E_INVALIDARG;
  1732. if (pszPropName && pVar)
  1733. {
  1734. if (!StrCmpW(pszPropName, SZ_PBPROP_SCREENSAVER_PATH))
  1735. {
  1736. // The caller is asking for the ScreenSaver path.
  1737. WCHAR szLongPath[MAX_PATH];
  1738. DWORD cchSize = GetLongPathName(g_szSaverName, szLongPath, ARRAYSIZE(szLongPath));
  1739. if ((0 == cchSize) || (ARRAYSIZE(szLongPath) < cchSize))
  1740. {
  1741. // It failed
  1742. StrCpyNW(szLongPath, g_szSaverName, ARRAYSIZE(szLongPath));
  1743. }
  1744. hr = HrStrToVariant(szLongPath, pVar);
  1745. }
  1746. }
  1747. return hr;
  1748. }
  1749. HRESULT CScreenSaverPg::Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar)
  1750. {
  1751. HRESULT hr = E_INVALIDARG;
  1752. if (pszPropName && pVar && (VT_BSTR == pVar->vt))
  1753. {
  1754. if (!StrCmpW(pszPropName, SZ_PBPROP_SCREENSAVER_PATH))
  1755. {
  1756. if (m_fScreenSavePolicy && !m_fScreenSaveActive)
  1757. {
  1758. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  1759. }
  1760. else
  1761. {
  1762. _SetByPath(pVar->bstrVal);
  1763. hr = S_OK;
  1764. }
  1765. }
  1766. }
  1767. return hr;
  1768. }
  1769. HRESULT CScreenSaverPg::_SetByPath(LPCWSTR pszPath)
  1770. {
  1771. HRESULT hr = S_OK;
  1772. // COMPATIBILITY: always use short name
  1773. // otherwise some apps fault when peeking at SYSTEM.INI
  1774. DWORD cchSize = GetShortPathNameW(pszPath, g_szSaverName, ARRAYSIZE(g_szSaverName));
  1775. if ((0 == cchSize) || (ARRAYSIZE(g_szSaverName) < cchSize))
  1776. {
  1777. // It failed
  1778. StrCpyNW(g_szSaverName, pszPath, ARRAYSIZE(g_szSaverName));
  1779. }
  1780. if (m_hDlg)
  1781. {
  1782. ComboBox_SetCurSel(m_hDlg, 0);
  1783. SelectSSFromList(m_hDlg);
  1784. }
  1785. return hr;
  1786. }
  1787. //===========================
  1788. // *** IUnknown Interface ***
  1789. //===========================
  1790. ULONG CScreenSaverPg::AddRef()
  1791. {
  1792. m_cRef++;
  1793. return m_cRef;
  1794. }
  1795. ULONG CScreenSaverPg::Release()
  1796. {
  1797. ASSERT(m_cRef > 0);
  1798. m_cRef--;
  1799. if (m_cRef > 0)
  1800. return m_cRef;
  1801. delete this;
  1802. return 0;
  1803. }
  1804. HRESULT CScreenSaverPg::QueryInterface(REFIID riid, void **ppvObj)
  1805. {
  1806. static const QITAB qit[] =
  1807. {
  1808. QITABENT(CScreenSaverPg, IObjectWithSite),
  1809. QITABENT(CScreenSaverPg, IPropertyBag),
  1810. QITABENT(CScreenSaverPg, IPersist),
  1811. QITABENT(CScreenSaverPg, IBasePropPage),
  1812. QITABENTMULTI(CScreenSaverPg, IShellPropSheetExt, IBasePropPage),
  1813. { 0 },
  1814. };
  1815. return QISearch(this, qit, riid, ppvObj);
  1816. }
  1817. //===========================
  1818. // *** Class Methods ***
  1819. //===========================
  1820. CScreenSaverPg::CScreenSaverPg() : CObjectCLSID(&PPID_ScreenSaver), m_cRef(1)
  1821. {
  1822. // This needs to be allocated in Zero Inited Memory.
  1823. // Assert that all Member Variables are inited to Zero.
  1824. // This is a global that we want to initialize.
  1825. g_szSaverName[0] = TEXT('\0');
  1826. m_fScreenSavePolicy = FALSE;
  1827. m_fScreenSaveActive = TRUE;
  1828. m_lWaitTime = 0;
  1829. m_hDlg = NULL;
  1830. m_fUIInitialized = FALSE;
  1831. _InitState();
  1832. }
  1833. CScreenSaverPg::~CScreenSaverPg()
  1834. {
  1835. }
  1836. HRESULT CScreenSaverPage_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj)
  1837. {
  1838. HRESULT hr = E_INVALIDARG;
  1839. if (!punkOuter && ppvObj)
  1840. {
  1841. CScreenSaverPg * pThis = new CScreenSaverPg();
  1842. *ppvObj = NULL;
  1843. if (pThis)
  1844. {
  1845. hr = pThis->QueryInterface(riid, ppvObj);
  1846. pThis->Release();
  1847. }
  1848. else
  1849. {
  1850. hr = E_OUTOFMEMORY;
  1851. }
  1852. }
  1853. return hr;
  1854. }