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

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