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.

2953 lines
96 KiB

  1. #include "stdafx.h"
  2. #include "utils.h"
  3. #include "..\\deskfldr.h"
  4. #include <cfgmgr32.h> // MAX_GUID_STRING_LEN
  5. #pragma hdrstop
  6. const TCHAR c_szSetup[] = REGSTR_PATH_SETUP TEXT("\\Setup");
  7. const TCHAR c_szSharedDir[] = TEXT("SharedDir");
  8. BOOL g_fDirtyAdvanced;
  9. BOOL g_fLaunchGallery; // If true, we launched the gallery, so close the dialog.
  10. DWORD g_dwApplyFlags = (AD_APPLY_ALL | AD_APPLY_DYNAMICREFRESH);
  11. // used to indicate if desktop cleanup settings have changes
  12. extern int g_iRunDesktopCleanup = BST_INDETERMINATE; // indicates uninitilized value.
  13. STDAPI ApplyDesktopCleanupSettings();
  14. BOOL _IsNonEnumPolicySet(const CLSID *pclsid);
  15. static const LPCTSTR c_rgpszWallpaperExt[] = {
  16. TEXT("BMP"), TEXT("GIF"),
  17. TEXT("JPG"), TEXT("JPE"),
  18. TEXT("JPEG"),TEXT("DIB"),
  19. TEXT("PNG"), TEXT("HTM"),
  20. TEXT("HTML"),
  21. };
  22. const static DWORD aBackHelpIDs[] = {
  23. IDC_BACK_SELECT, IDH_DISPLAY_BACKGROUND_WALLPAPERLIST,
  24. IDC_BACK_WPLIST, IDH_DISPLAY_BACKGROUND_WALLPAPERLIST,
  25. IDC_BACK_BROWSE, IDH_DISPLAY_BACKGROUND_BROWSE_BUTTON,
  26. IDC_BACK_WEB, IDH_DISPLAY_BACKGROUND_DESKTOP_ITEMS,
  27. IDC_BACK_DISPLAY, IDH_DISPLAY_BACKGROUND_PICTUREDISPLAY,
  28. IDC_BACK_WPSTYLE, IDH_DISPLAY_BACKGROUND_PICTUREDISPLAY,
  29. IDC_BACK_PREVIEW, IDH_DISPLAY_BACKGROUND_MONITOR,
  30. IDC_BACK_COLORPICKERLABEL, IDH_DISPLAY_BACKGROUND_BACKGROUND_COLOR,
  31. IDC_BACK_COLORPICKER, IDH_DISPLAY_BACKGROUND_BACKGROUND_COLOR,
  32. 0, 0
  33. };
  34. #define SZ_HELPFILE_DESKTOPTAB TEXT("display.hlp")
  35. #define SZ_REGKEY_PROGRAMFILES TEXT("Software\\Microsoft\\Windows\\CurrentVersion")
  36. #define SZ_REGKEY_PLUS95DIR TEXT("Software\\Microsoft\\Plus!\\Setup") // PLUS95_KEY
  37. #define SZ_REGKEY_PLUS98DIR TEXT("Software\\Microsoft\\Plus!98") // PLUS98_KEY
  38. #define SZ_REGKEY_KIDSDIR TEXT("Software\\Microsoft\\Microsoft Kids\\Kids Plus!") // KIDS_KEY
  39. #define SZ_REGKEY_WALLPAPER TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Wallpaper")
  40. #define SZ_REGKEY_WALLPAPERMRU TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Wallpaper\\MRU")
  41. #define SZ_REGKEY_LASTTHEME TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\LastTheme")
  42. #define SZ_REGVALUE_PLUS95DIR TEXT("DestPath") // PLUS95_PATH
  43. #define SZ_REGVALUE_PLUS98DIR TEXT("Path") // PLUS98_PATH
  44. #define SZ_REGVALUE_KIDSDIR TEXT("InstallDir") // KIDS_PATH
  45. #define SZ_REGVALUE_PROGRAMFILESDIR TEXT("ProgramFilesDir")
  46. #define SZ_REGVALUE_PROGRAMFILESDIR TEXT("ProgramFilesDir")
  47. #define SZ_REGVALUE_USETILE TEXT("UseTile") // If it's not a watermark background, does the user want to default to "Center" or "Stretch". Different users like different settings.
  48. #define SZ_REGVALUE_LASTSCAN TEXT("LastScan") // When was the last time we scanned the file sizes?
  49. #ifndef RECTHEIGHT
  50. #define RECTHEIGHT(rc) ((rc).bottom - (rc).top)
  51. #define RECTWIDTH(rc) ((rc).right - (rc).left)
  52. #endif
  53. //===========================
  54. // *** Class Internals & Helpers ***
  55. //===========================
  56. int GetGraphicFileIndex(LPCTSTR pszFile)
  57. {
  58. int iGraphicFileIndex = -1;
  59. if (pszFile && *pszFile)
  60. {
  61. LPCTSTR pszExt = PathFindExtension(pszFile);
  62. if (*pszExt == TEXT('.'))
  63. {
  64. pszExt++;
  65. for (int iRet = 0; iRet < ARRAYSIZE(c_rgpszWallpaperExt); iRet++)
  66. {
  67. if (StrCmpIC(pszExt, c_rgpszWallpaperExt[iRet]) == 0)
  68. {
  69. iGraphicFileIndex = iRet;
  70. }
  71. }
  72. }
  73. }
  74. return iGraphicFileIndex;
  75. }
  76. BOOL IsGraphicsFile(LPCTSTR pszFile)
  77. {
  78. return GetGraphicFileIndex(pszFile) >= 0;
  79. }
  80. HRESULT CBackPropSheetPage::_LoadState(void)
  81. {
  82. HRESULT hr = S_OK;
  83. if (!_fStateLoaded)
  84. {
  85. hr = _LoadIconState();
  86. if (SUCCEEDED(hr))
  87. {
  88. hr = _LoadDesktopOptionsState();
  89. if (SUCCEEDED(hr))
  90. {
  91. _fStateLoaded = TRUE;
  92. }
  93. }
  94. }
  95. return hr;
  96. }
  97. #define SZ_ICON_DEFAULTICON L"DefaultValue"
  98. HRESULT CBackPropSheetPage::_GetIconPath(IN CLSID clsid, IN LPCWSTR pszName, IN BOOL fOldIcon, IN LPWSTR pszPath, IN DWORD cchSize)
  99. {
  100. HRESULT hr = E_FAIL;
  101. int nIndex;
  102. if (!StrCmpIW(SZ_ICON_DEFAULTICON, pszName))
  103. {
  104. pszName = L"";
  105. }
  106. for (nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++)
  107. {
  108. if (IsEqualCLSID(*(c_aIconRegKeys[nIndex].pclsid), clsid) &&
  109. !StrCmpIW(pszName, c_aIconRegKeys[nIndex].szIconValue))
  110. {
  111. // We found it.
  112. if (fOldIcon)
  113. {
  114. hr = StringCchPrintfW(pszPath, cchSize, L"%s,%d", _IconData[nIndex].szOldFile, _IconData[nIndex].iOldIndex);
  115. }
  116. else
  117. {
  118. hr = StringCchPrintfW(pszPath, cchSize, L"%s,%d", _IconData[nIndex].szNewFile, _IconData[nIndex].iNewIndex);
  119. }
  120. break;
  121. }
  122. }
  123. return hr;
  124. }
  125. HRESULT CBackPropSheetPage::_SetIconPath(IN CLSID clsid, IN LPCWSTR pszName, IN LPCWSTR pszPath, IN int nResourceID)
  126. {
  127. HRESULT hr = E_FAIL;
  128. int nIndex;
  129. if (!StrCmpIW(SZ_ICON_DEFAULTICON, pszName))
  130. {
  131. pszName = L"";
  132. }
  133. for (nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++)
  134. {
  135. if (IsEqualCLSID(*(c_aIconRegKeys[nIndex].pclsid), clsid) &&
  136. !StrCmpIW(pszName, c_aIconRegKeys[nIndex].szIconValue))
  137. {
  138. TCHAR szTemp[MAX_PATH];
  139. if (!pszPath || !pszPath[0])
  140. {
  141. // The caller didn't specify an icon so use the default values.
  142. if (!SHExpandEnvironmentStrings(c_aIconRegKeys[nIndex].pszDefault, szTemp, ARRAYSIZE(szTemp)))
  143. {
  144. StringCchCopy(szTemp, ARRAYSIZE(szTemp), c_aIconRegKeys[nIndex].pszDefault);
  145. }
  146. pszPath = szTemp;
  147. nResourceID = c_aIconRegKeys[nIndex].nDefaultIndex;
  148. }
  149. // We found it.
  150. StringCchCopy(_IconData[nIndex].szNewFile, ARRAYSIZE(_IconData[nIndex].szNewFile), pszPath);
  151. _IconData[nIndex].iNewIndex = nResourceID;
  152. hr = S_OK;
  153. break;
  154. }
  155. }
  156. return hr;
  157. }
  158. HRESULT CBackPropSheetPage::_LoadIconState(void)
  159. {
  160. HRESULT hr = S_OK;
  161. // load the icons and add them to the image lists
  162. // get the icon files and indexes from the registry, including for the Default recycle bin
  163. for (int nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++)
  164. {
  165. TCHAR szTemp[MAX_PATH];
  166. szTemp[0] = 0;
  167. IconGetRegIconString(c_aIconRegKeys[nIndex].pclsid, c_aIconRegKeys[nIndex].szIconValue, szTemp, ARRAYSIZE(szTemp));
  168. int iIndex = PathParseIconLocation(szTemp);
  169. // store the icon information
  170. StringCchCopy(_IconData[nIndex].szOldFile, ARRAYSIZE(_IconData[nIndex].szOldFile), szTemp);
  171. StringCchCopy(_IconData[nIndex].szNewFile, ARRAYSIZE(_IconData[nIndex].szNewFile), szTemp);
  172. _IconData[nIndex].iOldIndex = iIndex;
  173. _IconData[nIndex].iNewIndex = iIndex;
  174. }
  175. return hr;
  176. }
  177. HRESULT CBackPropSheetPage::_LoadDesktopOptionsState(void)
  178. {
  179. HRESULT hr = S_OK;
  180. int iStartPanel;
  181. TCHAR szRegPath[MAX_PATH];
  182. // i = 0 is for StartPanel off and i = 1 is for StartPanel ON!
  183. for(iStartPanel = 0; iStartPanel <= 1; iStartPanel++)
  184. {
  185. int iIndex;
  186. //Get the proper registry path based on if StartPanel is ON/OFF
  187. StringCchPrintf(szRegPath, ARRAYSIZE(szRegPath), REGSTR_PATH_HIDDEN_DESKTOP_ICONS, c_apstrRegLocation[iStartPanel]);
  188. //Load the settings for all icons we are interested in.
  189. for(iIndex = 0; iIndex < NUM_DESKICONS; iIndex++)
  190. {
  191. TCHAR szValueName[MAX_GUID_STRING_LEN];
  192. SHUnicodeToTChar(c_aDeskIconId[iIndex].pwszCLSID, szValueName, ARRAYSIZE(szValueName));
  193. //Read the setting from the registry!
  194. _aHideDesktopIcon[iStartPanel][iIndex].fHideIcon = SHRegGetBoolUSValue(szRegPath, szValueName, FALSE, /* default */FALSE);
  195. _aHideDesktopIcon[iStartPanel][iIndex].fDirty = FALSE;
  196. //Update the NonEnum attribute data.
  197. if((c_aDeskIconId[iIndex].fCheckNonEnumAttrib) && (iStartPanel == 1))
  198. {
  199. TCHAR szAttriRegPath[MAX_PATH];
  200. DWORD dwSize = sizeof(_aDeskIconNonEnumData[iIndex].rgfAttributes);
  201. ULONG rgfDefault = 0; //By default the SFGAO_NONENUMERATED bit if off!
  202. StringCchPrintf(szAttriRegPath, ARRAYSIZE(szAttriRegPath), REGSTR_PATH_EXP_SHELLFOLDER, szValueName);
  203. //Read the attributes.
  204. SHRegGetUSValue(szAttriRegPath, REGVAL_ATTRIBUTES,
  205. NULL,
  206. &(_aDeskIconNonEnumData[iIndex].rgfAttributes),
  207. &dwSize,
  208. FALSE,
  209. &rgfDefault,
  210. sizeof(rgfDefault));
  211. //If SHGAO_NONENUMERATED bit is ON, then we need to hide the checkboxes in both modes.
  212. if(_aDeskIconNonEnumData[iIndex].rgfAttributes & SFGAO_NONENUMERATED)
  213. {
  214. //Overwrite what we read earlier! These icons are hidden in both modes!
  215. _aHideDesktopIcon[0][iIndex].fHideIcon = TRUE;
  216. _aHideDesktopIcon[1][iIndex].fHideIcon = TRUE;
  217. }
  218. }
  219. //Check the policy if needed!
  220. if((c_aDeskIconId[iIndex].fCheckNonEnumPolicy) && (iStartPanel == 1))
  221. {
  222. if(_IsNonEnumPolicySet(c_aDeskIconId[iIndex].pclsid))
  223. {
  224. //Remember that this policy is set. So that we can disable these controls in UI.
  225. _aDeskIconNonEnumData[iIndex].fNonEnumPolicySet = TRUE;
  226. //Remember to hide these icons in both modes!
  227. _aHideDesktopIcon[0][iIndex].fHideIcon = TRUE;
  228. _aHideDesktopIcon[1][iIndex].fHideIcon = TRUE;
  229. }
  230. }
  231. } //for (all desktop items)
  232. } //for both the modes (StartPanel off and On)
  233. return hr;
  234. }
  235. HRESULT CBackPropSheetPage::_SaveIconState(void)
  236. {
  237. HRESULT hr = S_OK;
  238. BOOL fDorked = FALSE;
  239. if (_fStateLoaded)
  240. {
  241. int nIndex;
  242. // Change the system icons
  243. for(nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++)
  244. {
  245. if ((lstrcmpi(_IconData[nIndex].szNewFile, _IconData[nIndex].szOldFile) != 0) ||
  246. (_IconData[nIndex].iNewIndex != _IconData[nIndex].iOldIndex))
  247. {
  248. TCHAR szTemp[MAX_PATH];
  249. if (SUCCEEDED(StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%s,%d"), _IconData[nIndex].szNewFile, _IconData[nIndex].iNewIndex)))
  250. {
  251. IconSetRegValueString(c_aIconRegKeys[nIndex].pclsid, TEXT("DefaultIcon"), c_aIconRegKeys[nIndex].szIconValue, szTemp);
  252. // Next two lines necessary if the user does an Apply as opposed to OK
  253. StringCchCopy(_IconData[nIndex].szOldFile, ARRAYSIZE(_IconData[nIndex].szOldFile), _IconData[nIndex].szNewFile);
  254. _IconData[nIndex].iOldIndex = _IconData[nIndex].iNewIndex;
  255. fDorked = TRUE;
  256. }
  257. }
  258. }
  259. }
  260. // Make the system notice we changed the system icons
  261. if (fDorked)
  262. {
  263. SHChangeNotify(SHCNE_ASSOCCHANGED, 0, NULL, NULL); // should do the trick!
  264. SHUpdateRecycleBinIcon();
  265. }
  266. return hr;
  267. }
  268. HRESULT CBackPropSheetPage::_SaveDesktopOptionsState(void)
  269. {
  270. HRESULT hr = S_OK;
  271. int iStartPanel;
  272. TCHAR szRegPath[MAX_PATH];
  273. BOOL fUpdateDesktop = FALSE;
  274. // i = 0 is for StartPanel off and i = 1 is for StartPanel ON!
  275. for(iStartPanel = 0; iStartPanel <= 1; iStartPanel++)
  276. {
  277. int iIndex;
  278. //Get the proper registry path based on if StartPanel is ON/OFF
  279. StringCchPrintf(szRegPath, ARRAYSIZE(szRegPath), REGSTR_PATH_HIDDEN_DESKTOP_ICONS, c_apstrRegLocation[iStartPanel]);
  280. //Load the settings for all icons we are interested in.
  281. for(iIndex = 0; iIndex < NUM_DESKICONS; iIndex++)
  282. {
  283. //Update the registry only if the particular icon entry is dirty.
  284. if(_aHideDesktopIcon[iStartPanel][iIndex].fDirty)
  285. {
  286. TCHAR szValueName[MAX_GUID_STRING_LEN];
  287. SHUnicodeToTChar(c_aDeskIconId[iIndex].pwszCLSID, szValueName, ARRAYSIZE(szValueName));
  288. //Write the setting to the registry!
  289. SHRegSetUSValue(szRegPath, szValueName, REG_DWORD,
  290. &(_aHideDesktopIcon[iStartPanel][iIndex].fHideIcon),
  291. sizeof(_aHideDesktopIcon[iStartPanel][iIndex].fHideIcon),
  292. SHREGSET_FORCE_HKCU);
  293. _aHideDesktopIcon[iStartPanel][iIndex].fDirty = FALSE;
  294. fUpdateDesktop = TRUE; //Desktop window needs to be refreshed.
  295. // Note this will be done only once per index because SFGAO_NONENUMERATED bit is
  296. // reset in rgfAttributes.
  297. if((c_aDeskIconId[iIndex].fCheckNonEnumAttrib) &&
  298. (_aDeskIconNonEnumData[iIndex].rgfAttributes & SFGAO_NONENUMERATED) &&
  299. (_aHideDesktopIcon[iStartPanel][iIndex].fHideIcon == FALSE))
  300. {
  301. TCHAR szAttriRegPath[MAX_PATH];
  302. StringCchPrintf(szAttriRegPath, ARRAYSIZE(szAttriRegPath), REGSTR_PATH_EXP_SHELLFOLDER, szValueName);
  303. //We need to remove the SFGAO_NONENUMERATED attribute bit!
  304. //We assume here is that when we save to registry, we save the same value
  305. //for both the modes.
  306. ASSERT(_aHideDesktopIcon[0][iIndex].fHideIcon == _aHideDesktopIcon[1][iIndex].fHideIcon);
  307. //Strip out the NonEnum attribute!
  308. _aDeskIconNonEnumData[iIndex].rgfAttributes &= ~SFGAO_NONENUMERATED;
  309. //And save it in the registry!
  310. SHRegSetUSValue(szAttriRegPath, REGVAL_ATTRIBUTES,
  311. REG_DWORD,
  312. &(_aDeskIconNonEnumData[iIndex].rgfAttributes),
  313. sizeof(_aDeskIconNonEnumData[iIndex].rgfAttributes),
  314. SHREGSET_FORCE_HKCU);
  315. }
  316. }
  317. }
  318. }
  319. if(fUpdateDesktop)
  320. PostMessage(GetShellWindow(), WM_COMMAND, FCIDM_REFRESH, 0L); //Refresh desktop!
  321. _fHideDesktopIconDirty = FALSE; //We just saved. So, reset the dirty bit!
  322. return hr;
  323. }
  324. int CBackPropSheetPage::_AddAFileToLV(LPCTSTR pszDir, LPTSTR pszFile, UINT nBitmap)
  325. {
  326. int index = -1;
  327. LPTSTR pszParam;
  328. const DWORD cchParam = MAX_PATH; // PathAppend args must be MAX_PATH...no more - no less
  329. pszParam = (LPTSTR) LocalAlloc( LPTR, cchParam * sizeof(*pszParam) );
  330. if ( NULL != pszParam )
  331. {
  332. if (pszDir)
  333. {
  334. StringCchCopy(pszParam, cchParam, pszDir);
  335. if (!PathAppend(pszParam, pszFile))
  336. {
  337. *pszParam = TEXT('\0');
  338. }
  339. }
  340. else if (pszFile && *pszFile && (lstrcmpi(pszFile, g_szNone) != 0))
  341. {
  342. StringCchCopy(pszParam, cchParam, pszFile);
  343. }
  344. else
  345. {
  346. *pszParam = TEXT('\0');
  347. }
  348. TCHAR szLVIText[MAX_PATH];
  349. StringCchCopy(szLVIText, ARRAYSIZE(szLVIText), PathFindFileName(pszFile));
  350. PathRemoveExtension(szLVIText);
  351. PathMakePretty(szLVIText);
  352. LV_ITEM lvi = {0};
  353. lvi.mask = LVIF_TEXT | LVIF_PARAM | (nBitmap != -1 ? LVIF_IMAGE : 0);
  354. lvi.iItem = 0x7FFFFFFF;
  355. lvi.pszText = szLVIText;
  356. lvi.iImage = nBitmap;
  357. lvi.lParam = (LPARAM) pszParam;
  358. index = ListView_InsertItem(_hwndLV, &lvi);
  359. if (index == -1)
  360. {
  361. LocalFree(pszParam);
  362. }
  363. else
  364. {
  365. ListView_SetColumnWidth(_hwndLV, 0, LVSCW_AUTOSIZE);
  366. }
  367. }
  368. return index;
  369. }
  370. int CBackPropSheetPage::_FindWallpaper(LPCTSTR pszFile)
  371. {
  372. int nItems = ListView_GetItemCount(_hwndLV);
  373. int i;
  374. for (i=0; i<nItems; i++)
  375. {
  376. LV_ITEM lvi = {0};
  377. lvi.iItem = i;
  378. lvi.mask = LVIF_PARAM;
  379. ListView_GetItem(_hwndLV, &lvi);
  380. if (StrCmpIC(pszFile, (LPCTSTR)lvi.lParam) == 0)
  381. {
  382. return i;
  383. }
  384. }
  385. return -1;
  386. }
  387. void CBackPropSheetPage::_UpdatePreview(IN WPARAM flags, IN BOOL fUpdateThemePage)
  388. {
  389. WALLPAPEROPT wpo;
  390. wpo.dwSize = sizeof(WALLPAPEROPT);
  391. g_pActiveDesk->GetWallpaperOptions(&wpo, 0);
  392. if (wpo.dwStyle & WPSTYLE_TILE)
  393. {
  394. flags |= BP_TILE;
  395. }
  396. else if(wpo.dwStyle & WPSTYLE_STRETCH)
  397. {
  398. flags |= BP_STRETCH;
  399. }
  400. WCHAR wszWallpaper[INTERNET_MAX_URL_LENGTH];
  401. g_pActiveDesk->GetWallpaper(wszWallpaper, ARRAYSIZE(wszWallpaper), 0);
  402. HRESULT hr = S_OK;
  403. if (!_pThemePreview)
  404. {
  405. hr = CoCreateInstance(CLSID_ThemePreview, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IThemePreview, &_pThemePreview));
  406. if (SUCCEEDED(hr) && _punkSite)
  407. {
  408. IPropertyBag * pPropertyBag;
  409. hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  410. ASSERT(SUCCEEDED(hr));
  411. if (SUCCEEDED(hr))
  412. {
  413. HWND hwndPlaceHolder = GetDlgItem(_hwnd, IDC_BACK_PREVIEW);
  414. if (hwndPlaceHolder)
  415. {
  416. RECT rcPreview;
  417. GetClientRect(hwndPlaceHolder, &rcPreview);
  418. MapWindowPoints(hwndPlaceHolder, _hwnd, (LPPOINT)&rcPreview, 2);
  419. hr = _pThemePreview->CreatePreview(_hwnd, TMPREV_SHOWMONITOR | TMPREV_SHOWBKGND, WS_VISIBLE | WS_CHILDWINDOW | WS_OVERLAPPED, 0, rcPreview.left, rcPreview.top, rcPreview.right - rcPreview.left, rcPreview.bottom - rcPreview.top, pPropertyBag, IDC_BACK_PREVIEW);
  420. if (SUCCEEDED(hr))
  421. {
  422. // If we succeeded, remove the dummy window.
  423. DestroyWindow(hwndPlaceHolder);
  424. hr = SHPropertyBag_WritePunk(pPropertyBag, SZ_PBPROP_PREVIEW2, _pThemePreview);
  425. _fThemePreviewCreated = TRUE;
  426. }
  427. }
  428. pPropertyBag->Release();
  429. }
  430. }
  431. }
  432. if (_punkSite)
  433. {
  434. IThemeUIPages * pThemeUIPages;
  435. HRESULT hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeUIPages, &pThemeUIPages));
  436. if (SUCCEEDED(hr))
  437. {
  438. hr = pThemeUIPages->UpdatePreview(0);
  439. pThemeUIPages->Release();
  440. }
  441. if (fUpdateThemePage)
  442. {
  443. IPropertyBag * pPropertyBag;
  444. hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  445. if (SUCCEEDED(hr))
  446. {
  447. // Tell the theme that we have customized the values.
  448. hr = SHPropertyBag_WriteInt(pPropertyBag, SZ_PBPROP_CUSTOMIZE_THEME, 0);
  449. pPropertyBag->Release();
  450. }
  451. }
  452. }
  453. if (!_fThemePreviewCreated)
  454. {
  455. HWND hwndOldPreview = GetDlgItem(_hwnd, IDC_BACK_PREVIEW);
  456. if (hwndOldPreview)
  457. {
  458. SendDlgItemMessage(_hwnd, IDC_BACK_PREVIEW, WM_SETBACKINFO, flags, 0);
  459. }
  460. }
  461. }
  462. void CBackPropSheetPage::_EnableControls(void)
  463. {
  464. BOOL fEnable;
  465. WCHAR wszWallpaper[INTERNET_MAX_URL_LENGTH];
  466. LPTSTR pszWallpaper;
  467. g_pActiveDesk->GetWallpaper(wszWallpaper, ARRAYSIZE(wszWallpaper), 0);
  468. pszWallpaper = (LPTSTR)wszWallpaper;
  469. BOOL fIsPicture = IsWallpaperPicture(pszWallpaper);
  470. // Style combo only enabled if a non-null picture
  471. // is being viewed.
  472. fEnable = _fAllowChanges && fIsPicture && (*pszWallpaper) && (!_fPolicyForStyle);
  473. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_WPSTYLE), fEnable);
  474. // 98/09/10 vtan #209753: Also remember to disable the corresponding
  475. // text item with the keyboard shortcut. Not disabling this will
  476. // allow the shortcut to be invoked but will cause the incorrect
  477. // dialog item to be "clicked".
  478. (BOOL)EnableWindow(GetDlgItem(_hwnd, IDC_BACK_DISPLAY), fEnable);
  479. }
  480. int CBackPropSheetPage::_GetImageIndex(LPCTSTR pszFile)
  481. {
  482. int iRet = 0;
  483. if (pszFile && *pszFile)
  484. {
  485. LPCTSTR pszExt = PathFindExtension(pszFile);
  486. if (*pszExt == TEXT('.'))
  487. {
  488. pszExt++;
  489. for (iRet=0; iRet<ARRAYSIZE(c_rgpszWallpaperExt); iRet++)
  490. {
  491. // We want ASCII comparison. On Turkish systems
  492. // .GIF and .Gif will not compare with lstrcmpi.
  493. if (StrCmpIC(pszExt, c_rgpszWallpaperExt[iRet]) == 0)
  494. {
  495. //
  496. // Add one because 'none' took the 0th slot.
  497. //
  498. iRet++;
  499. return(iRet);
  500. }
  501. }
  502. //
  503. // If we fell off the end of the for loop here,
  504. // this is a file with unknown extension. So, we assume that
  505. // it is a normal wallpaper and it gets the Bitmap's icon
  506. //
  507. iRet = 1;
  508. }
  509. else
  510. {
  511. //
  512. // Unknown files get Bitmap's icon.
  513. //
  514. iRet = 1;
  515. }
  516. }
  517. return iRet;
  518. }
  519. // This function is called when another tab is trying to change our
  520. // Tile mode. This means that our tab may not have been activated yet
  521. // and may not activate until later.
  522. HRESULT CBackPropSheetPage::_SetNewWallpaperTile(IN DWORD dwMode, IN BOOL fUpdateThemePage)
  523. {
  524. HRESULT hr = E_UNEXPECTED;
  525. AssertMsg((NULL != g_pActiveDesk), TEXT("We need g_pActiveDesk or we can't change the background"));
  526. if (g_pActiveDesk)
  527. {
  528. WALLPAPEROPT wpo;
  529. wpo.dwSize = sizeof(wpo);
  530. g_pActiveDesk->GetWallpaperOptions(&wpo, 0);
  531. wpo.dwStyle = dwMode;
  532. hr = g_pActiveDesk->SetWallpaperOptions(&wpo, 0);
  533. }
  534. if (_hwndWPStyle)
  535. {
  536. ComboBox_SetCurSel(_hwndWPStyle, dwMode);
  537. _UpdatePreview(0, fUpdateThemePage);
  538. }
  539. return hr;
  540. }
  541. HRESULT CBackPropSheetPage::_SetNewWallpaper(LPCTSTR pszFileIn, IN BOOL fUpdateThemePageIn)
  542. {
  543. HRESULT hr = S_OK;
  544. WCHAR szFile[MAX_PATH];
  545. WCHAR szTemp[MAX_PATH];
  546. LPWSTR pszFile = szFile;
  547. DWORD cchFile = ARRAYSIZE(szFile);
  548. LPWSTR pszTemp = szTemp;
  549. DWORD cchTemp = ARRAYSIZE(szTemp);
  550. //
  551. // Make a copy of the file name.
  552. //
  553. DWORD cchFileIn = lstrlen(pszFileIn) + 1;
  554. if ( cchFileIn > cchFile )
  555. {
  556. cchFile = cchFileIn;
  557. pszFile = (LPWSTR) LocalAlloc(LPTR, cchFile * sizeof(WCHAR));
  558. if (NULL == pszFile)
  559. {
  560. hr = E_OUTOFMEMORY;
  561. goto Cleanup;
  562. }
  563. }
  564. StringCchCopy(pszFile, cchFile, pszFileIn);
  565. //
  566. // Replace all "(none)" with empty strings.
  567. //
  568. if (lstrcmpi(pszFile, g_szNone) == 0)
  569. {
  570. pszFile[0] = TEXT('\0');
  571. }
  572. //
  573. // Replace net drives with UNC names.
  574. //
  575. if( pszFile[1] == TEXT(':') )
  576. {
  577. DWORD dwErr;
  578. TCHAR szDrive[3];
  579. //
  580. // Copy just the drive letter and see if it maps to a network drive.
  581. //
  582. StringCchCopy(szDrive, ARRAYSIZE(szDrive), pszFile);
  583. dwErr = SHWNetGetConnection(szDrive, pszTemp, &cchTemp );
  584. //
  585. // See if our buffer was too small. If so, make it bigger and try
  586. // again.
  587. //
  588. if ( ERROR_MORE_DATA == dwErr )
  589. {
  590. // Add the size of the rest of the filepath to the UNC path.
  591. cchTemp += cchFile;
  592. pszTemp = (LPWSTR) LocalAlloc( LPTR, cchTemp * sizeof(WCHAR) );
  593. if ( NULL == pszTemp )
  594. {
  595. hr = E_OUTOFMEMORY;
  596. goto Cleanup;
  597. }
  598. dwErr = SHWNetGetConnection(szDrive, pszTemp, &cchTemp );
  599. }
  600. //
  601. // If it maps to a network location, replace the network drive letter
  602. // with the UNC path.
  603. //
  604. if ( NO_ERROR == dwErr )
  605. {
  606. if (pszTemp[0] == TEXT('\\') && pszTemp[1] == TEXT('\\'))
  607. {
  608. DWORD cchLen;
  609. StringCchCat(pszTemp, cchTemp, pszFile + 2);
  610. //
  611. // See if the new string will fit into our file buffer.
  612. //
  613. cchLen = wcslen(pszTemp) + 1;
  614. if ( cchLen > cchFile )
  615. {
  616. if ( szFile != pszFile )
  617. {
  618. LocalFree( pszFile );
  619. }
  620. cchFile = cchLen;
  621. pszFile = (LPWSTR) LocalAlloc(LPTR, cchFile * sizeof(WCHAR) );
  622. if ( NULL == pszFile )
  623. {
  624. hr = E_OUTOFMEMORY;
  625. goto Cleanup;
  626. }
  627. }
  628. StringCchCopy(pszFile, cchFile, pszTemp);
  629. }
  630. }
  631. }
  632. //
  633. // If necessary, update the desk state object.
  634. //
  635. hr = g_pActiveDesk->GetWallpaper(pszTemp, cchTemp, 0);
  636. if (FAILED(hr))
  637. goto Cleanup;
  638. //
  639. // If we need more room, allocate it on the heap and try again.
  640. //
  641. if ( MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_MORE_DATA ) == hr )
  642. {
  643. if ( szTemp != pszTemp )
  644. {
  645. LocalFree( pszTemp );
  646. }
  647. cchTemp = INTERNET_MAX_URL_LENGTH;
  648. pszTemp = (LPWSTR) LocalAlloc( LPTR, cchTemp * sizeof(WCHAR) );
  649. if ( NULL == pszTemp )
  650. {
  651. hr = E_OUTOFMEMORY;
  652. goto Cleanup;
  653. }
  654. hr = g_pActiveDesk->GetWallpaper(pszTemp, cchTemp, 0);
  655. if (S_OK != hr)
  656. goto Cleanup;
  657. }
  658. //
  659. // Make sure the old background doesn't equal the new background.
  660. //
  661. if (StrCmpIC(pszTemp, pszFile) != 0)
  662. {
  663. //
  664. // Did they choose something other than a .bmp?
  665. // And is ActiveDesktop off?
  666. //
  667. if (!IsNormalWallpaper(pszFileIn))
  668. {
  669. Str_SetPtr(&_pszOriginalFile, pszFileIn);
  670. }
  671. else
  672. {
  673. // We may not need to have a temp file.
  674. Str_SetPtr(&_pszOriginalFile, NULL);
  675. }
  676. Str_SetPtr(&_pszLastSourcePath, pszFile);
  677. hr = g_pActiveDesk->SetWallpaper(pszFile, 0);
  678. if (SUCCEEDED(hr))
  679. {
  680. if (fUpdateThemePageIn)
  681. {
  682. _SetNewWallpaperTile(_GetStretchMode(pszFile), fUpdateThemePageIn);
  683. }
  684. }
  685. }
  686. //
  687. // Update the preview picture of the new wallpaper.
  688. //
  689. _UpdatePreview(0, fUpdateThemePageIn);
  690. //
  691. // If the wallpaper does not have a directory specified, (this may happen if other apps. change this value),
  692. // we have to figure it out.
  693. //
  694. if (!GetWallpaperWithPath(pszFile, pszTemp, cchTemp))
  695. {
  696. hr = E_FAIL;
  697. }
  698. else
  699. {
  700. LPTSTR pszFileForList = (_pszOriginalFile ? _pszOriginalFile : pszTemp);
  701. int iSelectionNew = (pszFileForList[0] ? _FindWallpaper(pszFileForList) : 0);
  702. if (iSelectionNew == -1)
  703. {
  704. iSelectionNew = _AddAFileToLV(NULL, pszFileForList, _GetImageIndex(pszFileForList));
  705. }
  706. _fSelectionFromUser = FALSE; // disable
  707. //
  708. // If necessary, select the item in the listview.
  709. //
  710. int iSelected = ListView_GetNextItem(_hwndLV, -1, LVNI_SELECTED);
  711. if (iSelected != iSelectionNew)
  712. {
  713. ListView_SetItemState(_hwndLV, iSelectionNew, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  714. }
  715. //
  716. // Put all controls in correct enabled state.
  717. //
  718. _EnableControls();
  719. //
  720. // Make sure the selected item is visible.
  721. //
  722. ListView_EnsureVisible(_hwndLV, iSelectionNew, FALSE);
  723. _fSelectionFromUser = TRUE; // re-enable
  724. }
  725. Cleanup:
  726. if ( szFile != pszFile && NULL != pszFile )
  727. {
  728. LocalFree( pszFile );
  729. }
  730. if ( szTemp != pszTemp && NULL != pszTemp )
  731. {
  732. LocalFree( pszTemp );
  733. }
  734. return hr;
  735. }
  736. int CALLBACK CBackPropSheetPage::_SortBackgrounds(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  737. {
  738. TCHAR szFile1[MAX_PATH], szFile2[MAX_PATH];
  739. LPTSTR lpszFile1, lpszFile2;
  740. StringCchCopy(szFile1, ARRAYSIZE(szFile1), (LPTSTR)lParam1);
  741. lpszFile1 = PathFindFileName(szFile1);
  742. PathRemoveExtension(lpszFile1);
  743. PathMakePretty(lpszFile1);
  744. StringCchCopy(szFile2, ARRAYSIZE(szFile2), (LPTSTR)lParam2);
  745. lpszFile2 = PathFindFileName(szFile2);
  746. PathRemoveExtension(lpszFile2);
  747. PathMakePretty(lpszFile2);
  748. return StrCmpIC(lpszFile1, lpszFile2);
  749. }
  750. HRESULT CBackPropSheetPage::_GetPlus95ThemesDir(LPTSTR pszPath, DWORD cchSize)
  751. {
  752. DWORD dwType;
  753. DWORD cbSize = (sizeof(pszPath[0]) * cchSize);
  754. HRESULT hr = HrSHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_PLUS95DIR, SZ_REGVALUE_PLUS95DIR, &dwType, pszPath, &cbSize);
  755. if (SUCCEEDED(hr))
  756. {
  757. TCHAR szSubDir[MAX_PATH];
  758. LPTSTR pszFile = PathFindFileName(pszPath);
  759. if (pszFile)
  760. {
  761. // Plus!95 DestPath has "Plus!.dll" on the end so get rid of that.
  762. pszFile[0] = 0;
  763. }
  764. // Tack on a "Themes" onto the path
  765. LoadString(HINST_THISDLL, IDS_THEMES_SUBDIR, szSubDir, ARRAYSIZE(szSubDir));
  766. if (!PathAppend(pszPath, szSubDir))
  767. {
  768. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  769. }
  770. }
  771. return hr;
  772. }
  773. HRESULT CBackPropSheetPage::_GetPlus98ThemesDir(LPTSTR pszPath, DWORD cchSize)
  774. {
  775. DWORD dwType;
  776. DWORD cbSize = (sizeof(pszPath[0]) * cchSize);
  777. HRESULT hr = HrSHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_PLUS98DIR, SZ_REGVALUE_PLUS98DIR, &dwType, pszPath, &cbSize);
  778. if (SUCCEEDED(hr))
  779. {
  780. TCHAR szSubDir[MAX_PATH];
  781. LoadString(HINST_THISDLL, IDS_THEMES_SUBDIR, szSubDir, ARRAYSIZE(szSubDir));
  782. if (!PathAppend(pszPath, szSubDir))
  783. {
  784. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  785. }
  786. }
  787. return hr;
  788. }
  789. HRESULT CBackPropSheetPage::_GetKidsThemesDir(LPTSTR pszPath, DWORD cchSize)
  790. {
  791. DWORD dwType;
  792. DWORD cbSize = (sizeof(pszPath[0]) * cchSize);
  793. HRESULT hr = HrSHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_KIDSDIR, SZ_REGVALUE_KIDSDIR, &dwType, pszPath, &cbSize);
  794. if (SUCCEEDED(hr))
  795. {
  796. TCHAR szSubDir[MAX_PATH];
  797. // Tack a "\Plus! for Kids\Themes" onto the path
  798. if (PathAppend(pszPath, TEXT("Plus! for Kids")))
  799. {
  800. LoadString(HINST_THISDLL, IDS_THEMES_SUBDIR, szSubDir, ARRAYSIZE(szSubDir));
  801. if (!PathAppend(pszPath, szSubDir))
  802. {
  803. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  804. }
  805. }
  806. else
  807. {
  808. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  809. }
  810. }
  811. return hr;
  812. }
  813. HRESULT CBackPropSheetPage::_GetHardDirThemesDir(LPTSTR pszPath, DWORD cchSize)
  814. {
  815. DWORD dwType;
  816. DWORD cbSize = (sizeof(pszPath[0]) * cchSize);
  817. HRESULT hr = HrSHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_PROGRAMFILES, SZ_REGVALUE_PROGRAMFILESDIR, &dwType, pszPath, &cbSize);
  818. if (SUCCEEDED(hr))
  819. {
  820. TCHAR szSubDir[MAX_PATH];
  821. // Tack a "\Plus! for Kids\Themes" onto the path
  822. if (PathAppend(pszPath, TEXT("Plus!")))
  823. {
  824. LoadString(HINST_THISDLL, IDS_THEMES_SUBDIR, szSubDir, ARRAYSIZE(szSubDir));
  825. if (!PathAppend(pszPath, szSubDir))
  826. {
  827. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  828. }
  829. }
  830. else
  831. {
  832. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  833. }
  834. }
  835. return hr;
  836. }
  837. BOOL CBackPropSheetPage::_DoesDirHaveMoreThanMax(LPCTSTR pszPath, int nMax)
  838. {
  839. _nFileCount = 0;
  840. _nFileMax = nMax;
  841. _AddPicturesFromDirRecursively(pszPath, TRUE, _fAllowHtml);
  842. return (nMax < _nFileCount);
  843. }
  844. #define MAX_PICTURES_TOSTOPRECURSION 100 // PERF: If the directory (My Pictures) has more than this many pictures, only add the pictures in the top level.
  845. HRESULT CBackPropSheetPage::_AddFilesToList(void)
  846. {
  847. HRESULT hr = S_OK;
  848. TCHAR szPath[MAX_PATH];
  849. // Get the directory with the wallpaper files.
  850. if (!GetStringFromReg(HKEY_LOCAL_MACHINE, c_szSetup, c_szSharedDir, szPath, ARRAYSIZE(szPath)))
  851. {
  852. if (!GetWindowsDirectory(szPath, ARRAYSIZE(szPath)))
  853. {
  854. szPath[0] = 0;
  855. }
  856. }
  857. // Add only the *.BMP files in the windows directory.
  858. _AddPicturesFromDir(szPath, FALSE, FALSE);
  859. // Get the wallpaper Directory name
  860. if (!GetWallpaperDirName(szPath, ARRAYSIZE(szPath)))
  861. {
  862. hr = E_FAIL;
  863. }
  864. else
  865. {
  866. hr = S_OK;
  867. // Add all pictures from Wallpaper directory to the list!
  868. _AddPicturesFromDir(szPath, FALSE, _fAllowHtml);
  869. // Get the path to the "My Pictures" folder
  870. // NOTE: don't create the My Pictures directory -- if it doesn't exist, we won't find anything there anyway!
  871. if (S_OK == SHGetFolderPath(NULL, CSIDL_MYPICTURES, NULL, 0, szPath))
  872. {
  873. // Add all pictures in "My Pictures" directory to the list!
  874. if (!_DoesDirHaveMoreThanMax(szPath, MAX_PICTURES_TOSTOPRECURSION))
  875. {
  876. hr = _AddPicturesFromDirRecursively(szPath, FALSE, _fAllowHtml);
  877. }
  878. }
  879. //Get the path to the common "%UserProfile%\Application Data\" folder
  880. if (S_OK == SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath))
  881. {
  882. // Add all pictures in common "%UserProfile%\Application Data\Microsoft Internet Explorer\" so we get the user's
  883. // "Internet Explorer Wallpaper.bmp" file.
  884. if (PathAppend(szPath, TEXT("Microsoft\\Internet Explorer")))
  885. {
  886. _AddPicturesFromDir(szPath, FALSE, _fAllowHtml);
  887. }
  888. }
  889. // Add pictures from Theme Directories
  890. // The follwoing directories can contain themes:
  891. // Plus!98 Install Path\Themes
  892. // Plus!95 Install Path\Themes
  893. // Kids for Plus! Install Path\Themes
  894. // Program Files\Plus!\Themes
  895. if (SUCCEEDED(_GetPlus98ThemesDir(szPath, ARRAYSIZE(szPath))))
  896. {
  897. _AddPicturesFromDirRecursively(szPath, FALSE, _fAllowHtml);
  898. }
  899. else if (SUCCEEDED(_GetPlus95ThemesDir(szPath, ARRAYSIZE(szPath))))
  900. {
  901. _AddPicturesFromDirRecursively(szPath, FALSE, _fAllowHtml);
  902. }
  903. else if (SUCCEEDED(_GetKidsThemesDir(szPath, ARRAYSIZE(szPath))))
  904. {
  905. _AddPicturesFromDirRecursively(szPath, FALSE, _fAllowHtml);
  906. }
  907. else if (SUCCEEDED(_GetHardDirThemesDir(szPath, ARRAYSIZE(szPath))))
  908. {
  909. _AddPicturesFromDirRecursively(szPath, FALSE, _fAllowHtml);
  910. }
  911. }
  912. return hr;
  913. }
  914. #define SZ_ALL_FILTER TEXT("*.*")
  915. HRESULT CBackPropSheetPage::_AddPicturesFromDirRecursively(IN LPCTSTR pszDirName, BOOL fCount, BOOL fShouldAllowHTML)
  916. {
  917. HRESULT hr = S_OK;
  918. WIN32_FIND_DATA findFileData;
  919. TCHAR szSearchPath[MAX_PATH];
  920. // Note that we use the passed in fShouldAllowHTML rather than the member var _fAllowHtml for cases where
  921. // we want to restrict to *.BMP regardless.
  922. _AddPicturesFromDir(pszDirName, fCount, fShouldAllowHTML);
  923. StringCchCopy(szSearchPath, ARRAYSIZE(szSearchPath), pszDirName);
  924. if (PathAppend(szSearchPath, SZ_ALL_FILTER))
  925. {
  926. HANDLE hFindFiles = FindFirstFile(szSearchPath, &findFileData);
  927. if (hFindFiles && (INVALID_HANDLE_VALUE != hFindFiles))
  928. {
  929. while (hFindFiles && (INVALID_HANDLE_VALUE != hFindFiles) &&
  930. !(fCount && (_nFileMax < _nFileCount)))
  931. {
  932. if ((FILE_ATTRIBUTE_DIRECTORY & findFileData.dwFileAttributes) &&
  933. !PathIsDotOrDotDot(findFileData.cFileName))
  934. {
  935. TCHAR szSubDir[MAX_PATH];
  936. StringCchCopy(szSubDir, ARRAYSIZE(szSubDir), pszDirName);
  937. if (PathAppend(szSubDir, findFileData.cFileName))
  938. {
  939. hr = _AddPicturesFromDirRecursively(szSubDir, fCount, fShouldAllowHTML);
  940. }
  941. else
  942. {
  943. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  944. }
  945. }
  946. if (!FindNextFile(hFindFiles, &findFileData))
  947. {
  948. break;
  949. }
  950. }
  951. FindClose(hFindFiles);
  952. }
  953. }
  954. else
  955. {
  956. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  957. }
  958. return hr;
  959. }
  960. void CBackPropSheetPage::_AddPicturesFromDir(LPCTSTR pszDirName, BOOL fCount, BOOL fShouldAllowHTML)
  961. {
  962. WIN32_FIND_DATA fd;
  963. HANDLE h;
  964. TCHAR szBuf[MAX_PATH];
  965. // Note that we use the passed in fShouldAllowHTML rather than the member var _fAllowHtml for cases where
  966. // we want to restrict to *.BMP regardless.
  967. StringCchCopy(szBuf, ARRAYSIZE(szBuf), pszDirName);
  968. // If we know we're not looking for web files, then limit the file spec to bitmaps.
  969. if (PathAppend(szBuf, fShouldAllowHTML ? TEXT("*.*") : TEXT("*.bmp")))
  970. {
  971. h = FindFirstFile(szBuf, &fd);
  972. if (h != INVALID_HANDLE_VALUE)
  973. {
  974. do
  975. {
  976. // Skip files that are "Super-hidden" like "Winnt.bmp" and "Winnt256.bmp"
  977. if ((fd.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) != (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))
  978. {
  979. // If it's any file, look it up, otherwise we know it is a BMP since we set the
  980. // FindFirst filter above.
  981. int iIndex = fShouldAllowHTML ? GetGraphicFileIndex(fd.cFileName) : 0;
  982. if (iIndex >= 0)
  983. {
  984. if (!fCount)
  985. {
  986. _AddAFileToLV(pszDirName, fd.cFileName, iIndex + 1);
  987. }
  988. else
  989. {
  990. _nFileCount++;
  991. if (_nFileMax > _nFileCount)
  992. {
  993. // No reason to continue at this point
  994. break;
  995. }
  996. }
  997. }
  998. }
  999. }
  1000. while (FindNextFile(h, &fd));
  1001. FindClose(h);
  1002. }
  1003. }
  1004. }
  1005. HRESULT GetActiveDesktop(IActiveDesktop ** ppActiveDesktop)
  1006. {
  1007. HRESULT hr = S_OK;
  1008. if (!*ppActiveDesktop)
  1009. {
  1010. IActiveDesktopP * piadp;
  1011. if (SUCCEEDED(hr = CActiveDesktop_InternalCreateInstance((LPUNKNOWN *)&piadp, IID_IActiveDesktopP)))
  1012. {
  1013. WCHAR wszScheme[MAX_PATH];
  1014. DWORD dwcch = ARRAYSIZE(wszScheme);
  1015. // Get the global "edit" scheme and set ourselves us to read from and edit that scheme
  1016. if (SUCCEEDED(piadp->GetScheme(wszScheme, &dwcch, SCHEME_GLOBAL | SCHEME_EDIT)))
  1017. {
  1018. piadp->SetScheme(wszScheme, SCHEME_LOCAL);
  1019. }
  1020. hr = piadp->QueryInterface(IID_PPV_ARG(IActiveDesktop, ppActiveDesktop));
  1021. piadp->Release();
  1022. }
  1023. }
  1024. else
  1025. {
  1026. (*ppActiveDesktop)->AddRef();
  1027. }
  1028. return hr;
  1029. }
  1030. HRESULT ReleaseActiveDesktop(IActiveDesktop ** ppActiveDesktop)
  1031. {
  1032. HRESULT hr = S_OK;
  1033. if (*ppActiveDesktop)
  1034. {
  1035. if((*ppActiveDesktop)->Release() == 0)
  1036. *ppActiveDesktop = NULL;
  1037. }
  1038. return hr;
  1039. }
  1040. #define SZ_REGKEY_CONTROLPANEL_DESKTOP TEXT("Control Panel\\Desktop")
  1041. #define SZ_REGVALUE_CP_PATTERN TEXT("pattern")
  1042. #define SZ_REGVALUE_CP_PATTERNUPGRADE TEXT("Pattern Upgrade")
  1043. #define SZ_REGVALUE_CONVERTED_WALLPAPER TEXT("ConvertedWallpaper")
  1044. #define SZ_REGVALUE_ORIGINAL_WALLPAPER TEXT("OriginalWallpaper") // We store this to find when someone changed the wallpaper around us
  1045. #define SZ_REGVALUE_CONVERTED_WP_LASTWRITE TEXT("ConvertedWallpaper Last WriteTime")
  1046. HRESULT CBackPropSheetPage::_LoadTempWallpaperSettings(IN LPCWSTR pszWallpaperFile)
  1047. {
  1048. // When we converted a non-.BMP wallpaper to a .bmp temp file,
  1049. // we keep the name of the original wallpaper path stored in _pszOriginalFile.
  1050. // We need to load that in now.
  1051. TCHAR szTempWallPaper[MAX_PATH];
  1052. DWORD dwType;
  1053. DWORD cbSize = sizeof(szTempWallPaper);
  1054. // ISSUE: CONVERTED and ORIGINAL are backwards, but we shipped beta1 like this so we can't change it... blech
  1055. DWORD dwError = SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_CONVERTED_WALLPAPER, &dwType, (void *) szTempWallPaper, &cbSize);
  1056. HRESULT hr = HRESULT_FROM_WIN32(dwError);
  1057. if (SUCCEEDED(hr) && szTempWallPaper[0] && !_fWallpaperChanged)
  1058. {
  1059. TCHAR szOriginalWallPaper[MAX_PATH];
  1060. cbSize = sizeof(szOriginalWallPaper);
  1061. DWORD dwError = SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_ORIGINAL_WALLPAPER, &dwType, (void *) szOriginalWallPaper, &cbSize);
  1062. // It's possible that someone changed the wallpaper externally (IE's "Set as Wallpaper").
  1063. // We need to detect this and ignore the converted wallpaper regkey (SZ_REGVALUE_CONVERTED_WALLPAPER).
  1064. if ((ERROR_SUCCESS == dwError) && !StrCmpI(szOriginalWallPaper, pszWallpaperFile))
  1065. {
  1066. Str_SetPtr(&_pszOriginalFile, szTempWallPaper);
  1067. Str_SetPtr(&_pszOrigLastApplied, szTempWallPaper);
  1068. }
  1069. }
  1070. Str_SetPtrW(&_pszWallpaperInUse, pszWallpaperFile);
  1071. cbSize = sizeof(_ftLastWrite);
  1072. dwError = SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_CONVERTED_WP_LASTWRITE, &dwType, (void *) &_ftLastWrite, &cbSize);
  1073. return S_OK; // Ignore the hr because it's fine if the value wasn't found.
  1074. }
  1075. #define POLICY_DISABLECOLORCUSTOMIZATION_ON 0x00000001
  1076. HRESULT CBackPropSheetPage::_LoadBackgroundColor(IN BOOL fInit)
  1077. {
  1078. HRESULT hr = E_INVALIDARG;
  1079. if (_punkSite)
  1080. {
  1081. IPropertyBag * pPropertyBag;
  1082. hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  1083. if (SUCCEEDED(hr))
  1084. {
  1085. _rgbBkgdColor = 0x00000000;
  1086. hr = SHPropertyBag_ReadDWORD(pPropertyBag, SZ_PBPROP_BACKGROUND_COLOR, &_rgbBkgdColor);
  1087. if (fInit)
  1088. {
  1089. // Check the policy.
  1090. if (POLICY_DISABLECOLORCUSTOMIZATION_ON == SHRestricted(REST_NODISPLAYAPPEARANCEPAGE))
  1091. {
  1092. // We need to disable and hide the windows. We need to disable them so they can't get
  1093. // focus or accessibility.
  1094. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_COLORPICKER), FALSE);
  1095. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_COLORPICKERLABEL), FALSE);
  1096. ShowWindow(GetDlgItem(_hwnd, IDC_BACK_COLORPICKER), SW_HIDE);
  1097. ShowWindow(GetDlgItem(_hwnd, IDC_BACK_COLORPICKERLABEL), SW_HIDE);
  1098. }
  1099. else
  1100. {
  1101. _colorControl.Initialize(GetDlgItem(_hwnd, IDC_BACK_COLORPICKER), _rgbBkgdColor);
  1102. }
  1103. }
  1104. else
  1105. {
  1106. _colorControl.SetColor(_rgbBkgdColor);
  1107. }
  1108. pPropertyBag->Release();
  1109. }
  1110. }
  1111. return hr;
  1112. }
  1113. HRESULT CBackPropSheetPage::_Initialize(void)
  1114. {
  1115. HRESULT hr = S_OK;
  1116. if (!_fInitialized && g_pActiveDesk)
  1117. {
  1118. WCHAR szPath[MAX_PATH];
  1119. // Add & select the current setting.
  1120. hr = g_pActiveDesk->GetWallpaper(szPath, ARRAYSIZE(szPath), 0);
  1121. if (SUCCEEDED(hr))
  1122. {
  1123. hr = _LoadTempWallpaperSettings(szPath);
  1124. _fInitialized = TRUE;
  1125. }
  1126. }
  1127. return hr;
  1128. }
  1129. void CBackPropSheetPage::_OnInitDialog(HWND hwnd)
  1130. {
  1131. int i;
  1132. TCHAR szBuf[MAX_PATH];
  1133. _Initialize();
  1134. _colorControl.ChangeTheme(hwnd);
  1135. // Upgrade the pattern setting. Since we got rid of the UI, we want to
  1136. // get rid of the setting on upgrade. We only want to do this once since
  1137. // if the user added it back, we don't want to redelete it.
  1138. if (FALSE == SHRegGetBoolUSValue(SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_CP_PATTERNUPGRADE, FALSE, FALSE))
  1139. {
  1140. SHDeleteValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_CP_PATTERN);
  1141. SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_CP_PATTERNUPGRADE, REG_SZ, TEXT("TRUE"), ((lstrlen(TEXT("TRUE")) + 1) * sizeof(TCHAR)));
  1142. }
  1143. //
  1144. // Set some member variables.
  1145. //
  1146. _hwnd = hwnd;
  1147. _hwndLV = GetDlgItem(hwnd, IDC_BACK_WPLIST);
  1148. _hwndWPStyle = GetDlgItem(hwnd, IDC_BACK_WPSTYLE);
  1149. HWND hWndPrev = GetDlgItem(hwnd, IDC_BACK_PREVIEW);
  1150. if (hWndPrev)
  1151. {
  1152. SetWindowBits(hWndPrev, GWL_EXSTYLE, RTL_MIRRORED_WINDOW, 0);
  1153. }
  1154. _UpdatePreview(0, FALSE);
  1155. InitDeskHtmlGlobals();
  1156. if (!g_pActiveDesk)
  1157. {
  1158. return;
  1159. }
  1160. //
  1161. // Read in the restrictions.
  1162. //
  1163. _fForceAD = SHRestricted(REST_FORCEACTIVEDESKTOPON);
  1164. _fAllowAD = _fForceAD || !PolicyNoActiveDesktop();
  1165. if (_fAllowAD == FALSE)
  1166. {
  1167. _fAllowHtml = FALSE;
  1168. }
  1169. else
  1170. {
  1171. _fAllowHtml = !SHRestricted(REST_NOHTMLWALLPAPER);
  1172. }
  1173. //
  1174. // Check to see if there is a policy for Wallpaper name and wallpaper style.
  1175. //
  1176. _fPolicyForWallpaper = ReadPolicyForWallpaper(NULL, 0);
  1177. _fPolicyForStyle = ReadPolicyForWPStyle(NULL);
  1178. //
  1179. // Get the images into the listview.
  1180. //
  1181. HIMAGELIST himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
  1182. GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, ARRAYSIZE(c_rgpszWallpaperExt),
  1183. ARRAYSIZE(c_rgpszWallpaperExt));
  1184. if (himl)
  1185. {
  1186. SHFILEINFO sfi;
  1187. // Add the 'None' icon.
  1188. HICON hIconNone = (HICON)LoadImage(HINST_THISDLL, MAKEINTRESOURCE(IDI_BACK_NONE),
  1189. IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
  1190. GetSystemMetrics(SM_CYSMICON), 0);
  1191. ImageList_AddIcon(himl, hIconNone);
  1192. const int iPrefixLen = ARRAYSIZE("foo.") - 1; // -1 means lose the NULL char
  1193. StringCchCopy(szBuf, ARRAYSIZE(szBuf), TEXT("foo.")); //Pass "foo.bmp" etc., to SHGetFileInfo instead of ".bmp"
  1194. for (i=0; i<ARRAYSIZE(c_rgpszWallpaperExt); i++)
  1195. {
  1196. StringCchCopy(szBuf + iPrefixLen, ARRAYSIZE(szBuf) - iPrefixLen, c_rgpszWallpaperExt[i]);
  1197. if (SHGetFileInfo(szBuf, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES))
  1198. {
  1199. ImageList_AddIcon(himl, sfi.hIcon);
  1200. DestroyIcon(sfi.hIcon);
  1201. }
  1202. }
  1203. ListView_SetImageList(_hwndLV, himl, LVSIL_SMALL);
  1204. }
  1205. // Add the single column that we want.
  1206. LV_COLUMN lvc;
  1207. lvc.mask = LVCF_FMT | LVCF_SUBITEM;
  1208. lvc.fmt = LVCFMT_LEFT;
  1209. lvc.iSubItem = 0;
  1210. ListView_InsertColumn(_hwndLV, 0, &lvc);
  1211. // Add 'none' option.
  1212. _AddAFileToLV(NULL, g_szNone, 0);
  1213. // Add the rest of the files.
  1214. _AddFilesToList();
  1215. // Sort the standard items.
  1216. ListView_SortItems(_hwndLV, _SortBackgrounds, 0);
  1217. WCHAR wszBuf[MAX_PATH];
  1218. LPTSTR pszBuf;
  1219. // Add & select the current setting.
  1220. g_pActiveDesk->GetWallpaper(wszBuf, ARRAYSIZE(wszBuf), 0);
  1221. //Convert wszBuf to szBuf.
  1222. pszBuf = (LPTSTR)wszBuf;
  1223. if (!_fAllowHtml && !IsNormalWallpaper(pszBuf))
  1224. {
  1225. *pszBuf = TEXT('\0');
  1226. }
  1227. _SetNewWallpaper(pszBuf, FALSE);
  1228. int iEndStyle = WPSTYLE_STRETCH;
  1229. for (i=0; i<= iEndStyle; i++)
  1230. {
  1231. LoadString(HINST_THISDLL, IDS_WPSTYLE+i, szBuf, ARRAYSIZE(szBuf));
  1232. ComboBox_AddString(_hwndWPStyle, szBuf);
  1233. }
  1234. WALLPAPEROPT wpo;
  1235. wpo.dwSize = sizeof(wpo);
  1236. g_pActiveDesk->GetWallpaperOptions(&wpo, 0);
  1237. ComboBox_SetCurSel(_hwndWPStyle, wpo.dwStyle);
  1238. // Adjust various UI components.
  1239. if (!_fAllowChanges)
  1240. {
  1241. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_DISPLAY), FALSE);
  1242. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_WPSTYLE), FALSE);
  1243. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_BROWSE), FALSE);
  1244. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_WPLIST), FALSE);
  1245. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_SELECT), FALSE);
  1246. }
  1247. // Disable controls based on the policies
  1248. if(_fPolicyForWallpaper)
  1249. {
  1250. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_BROWSE), FALSE);
  1251. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_WPLIST), FALSE);
  1252. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_SELECT), FALSE);
  1253. }
  1254. if(_fPolicyForStyle)
  1255. {
  1256. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_WPSTYLE), FALSE);
  1257. EnableWindow(GetDlgItem(_hwnd, IDC_BACK_DISPLAY), FALSE);
  1258. }
  1259. COMPONENTSOPT co;
  1260. co.dwSize = sizeof(COMPONENTSOPT);
  1261. g_pActiveDesk->GetDesktopItemOptions(&co, 0);
  1262. //if activedesktop is forced to be on, this overrides the NOACTIVEDESKTOP restriction
  1263. if (_fForceAD)
  1264. {
  1265. if(!co.fActiveDesktop)
  1266. {
  1267. co.fActiveDesktop = TRUE;
  1268. g_pActiveDesk->SetDesktopItemOptions(&co, 0);
  1269. }
  1270. }
  1271. else
  1272. {
  1273. //See if Active Desktop is to be turned off by restriction.
  1274. if (!_fAllowAD)
  1275. {
  1276. if (co.fActiveDesktop)
  1277. {
  1278. co.fActiveDesktop = FALSE;
  1279. g_pActiveDesk->SetDesktopItemOptions(&co, 0);
  1280. }
  1281. }
  1282. }
  1283. _EnableControls();
  1284. _LoadBackgroundColor(TRUE);
  1285. if (_fOpenAdvOnInit)
  1286. {
  1287. // Tell the Advanced dialog to open.
  1288. PostMessage(_hwnd, WM_COMMAND, (WPARAM)IDC_BACK_WEB, (LPARAM)GetDlgItem(_hwnd, IDC_BACK_WEB));
  1289. }
  1290. _StartSizeChecker();
  1291. }
  1292. // This function checks to see if the currently selected wallpaper is a HTML wallpaper
  1293. // and if so, it makes sure that the active desktop is enabled. If it is disabled
  1294. // then it prompts the user asking a question to see if the user wants to enable it.
  1295. //
  1296. void EnableADifHtmlWallpaper(HWND hwnd)
  1297. {
  1298. if(!g_pActiveDesk)
  1299. {
  1300. return;
  1301. }
  1302. // turn active desktop on or off, depending on background
  1303. ActiveDesktop_ApplyChanges();
  1304. }
  1305. void CBackPropSheetPage::_OnNotify(LPNMHDR lpnm)
  1306. {
  1307. //
  1308. // Start with a small stack allocation.
  1309. //
  1310. WCHAR wszBuf[MAX_PATH];
  1311. LPWSTR pszBuf = wszBuf;
  1312. DWORD cchBuf = ARRAYSIZE(wszBuf);
  1313. switch (lpnm->code)
  1314. {
  1315. case PSN_SETACTIVE:
  1316. {
  1317. HRESULT hr;
  1318. //
  1319. // Make sure the correct wallpaper is selected.
  1320. //
  1321. hr = g_pActiveDesk->GetWallpaper(pszBuf, cchBuf, 0);
  1322. if (FAILED(hr))
  1323. break;
  1324. //
  1325. // If we need more room, allocate it on the heap and try again.
  1326. //
  1327. if ( MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_MORE_DATA ) == hr )
  1328. {
  1329. cchBuf = INTERNET_MAX_URL_LENGTH;
  1330. pszBuf = (LPWSTR) LocalAlloc( LPTR, cchBuf * sizeof(WCHAR) );
  1331. if ( NULL == pszBuf )
  1332. break;
  1333. hr = g_pActiveDesk->GetWallpaper(pszBuf, cchBuf, 0);
  1334. if (S_OK != hr)
  1335. break;
  1336. }
  1337. _LoadBackgroundColor(FALSE);
  1338. _SetNewWallpaper(pszBuf, FALSE);
  1339. if (g_pActiveDesk)
  1340. {
  1341. WALLPAPEROPT wpo;
  1342. wpo.dwSize = sizeof(wpo);
  1343. g_pActiveDesk->GetWallpaperOptions(&wpo, 0);
  1344. ComboBox_SetCurSel(_hwndWPStyle, wpo.dwStyle);
  1345. }
  1346. }
  1347. break;
  1348. case PSN_APPLY:
  1349. _OnApply();
  1350. break;
  1351. case LVN_ITEMCHANGED:
  1352. NM_LISTVIEW *pnmlv = (NM_LISTVIEW *)lpnm;
  1353. if ((pnmlv->uChanged & LVIF_STATE) &&
  1354. (pnmlv->uNewState & LVIS_SELECTED))
  1355. {
  1356. LV_ITEM lvi = {0};
  1357. lvi.iItem = pnmlv->iItem;
  1358. lvi.mask = LVIF_PARAM;
  1359. ListView_GetItem(_hwndLV, &lvi);
  1360. LPCTSTR pszSelectedNew = (LPCTSTR)lvi.lParam;
  1361. //
  1362. // Make sure the correct wallpaper is selected.
  1363. //
  1364. HRESULT hr = g_pActiveDesk->GetWallpaper(pszBuf, cchBuf, 0);
  1365. if (FAILED(hr))
  1366. break;
  1367. //
  1368. // If we need more room, allocate it on the heap and try again.
  1369. //
  1370. if ( MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_MORE_DATA ) == hr )
  1371. {
  1372. cchBuf = INTERNET_MAX_URL_LENGTH;
  1373. pszBuf = (LPWSTR) LocalAlloc( LPTR, cchBuf * sizeof(WCHAR) );
  1374. if ( NULL == pszBuf )
  1375. break;
  1376. hr = g_pActiveDesk->GetWallpaper(pszBuf, cchBuf, 0);
  1377. if (S_OK != hr)
  1378. break;
  1379. }
  1380. if (lstrcmp(pszSelectedNew, pszBuf) != 0)
  1381. {
  1382. _SetNewWallpaper(pszSelectedNew, _fSelectionFromUser);
  1383. EnableApplyButton(_hwnd);
  1384. }
  1385. }
  1386. break;
  1387. }
  1388. //
  1389. // Free heap allocation (if any)
  1390. //
  1391. if ( wszBuf != pszBuf && NULL != pszBuf )
  1392. {
  1393. LocalFree( pszBuf );
  1394. }
  1395. }
  1396. #define MAX_PAGES 12
  1397. // Parameters:
  1398. // hwnd: We parent our UI on this hwnd.
  1399. // dwPage: Which page does the caller want to come up as default?
  1400. // Use ADP_DEFAULT if they don't care
  1401. // Return: S_OK if the user closed the dialog with OK.
  1402. // HRESULT_FROM_WIN32(ERROR_CANCELLED) will be returned
  1403. // if the user clicked the cancel button.
  1404. HRESULT CBackPropSheetPage::_LaunchAdvancedDisplayProperties(HWND hwnd)
  1405. {
  1406. HRESULT hr = E_OUTOFMEMORY;
  1407. CCompPropSheetPage * pWebDialog = new CCompPropSheetPage();
  1408. if (pWebDialog)
  1409. {
  1410. BOOL fEnableApply = FALSE;
  1411. IUnknown_SetSite(SAFECAST(pWebDialog, IObjectWithSite *), SAFECAST(this, IObjectWithSite *));
  1412. hr = pWebDialog->DisplayAdvancedDialog(_hwnd, SAFECAST(this, IPropertyBag *), &fEnableApply);
  1413. if (SUCCEEDED(hr) && (fEnableApply || _fHideDesktopIconDirty))
  1414. {
  1415. EnableApplyButton(_hwnd);
  1416. }
  1417. IUnknown_SetSite(SAFECAST(pWebDialog, IObjectWithSite *), NULL);
  1418. pWebDialog->Release();
  1419. }
  1420. return hr;
  1421. }
  1422. void CBackPropSheetPage::_OnCommand(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1423. {
  1424. WORD wNotifyCode = HIWORD(wParam);
  1425. WORD wID = LOWORD(wParam);
  1426. HWND hwndCtl = (HWND)lParam;
  1427. switch (wID)
  1428. {
  1429. case IDC_BACK_WPSTYLE:
  1430. switch (wNotifyCode)
  1431. {
  1432. case CBN_SELCHANGE:
  1433. WALLPAPEROPT wpo;
  1434. wpo.dwSize = sizeof(WALLPAPEROPT);
  1435. g_pActiveDesk->GetWallpaperOptions(&wpo, 0);
  1436. wpo.dwStyle = ComboBox_GetCurSel(_hwndWPStyle);
  1437. g_pActiveDesk->SetWallpaperOptions(&wpo, 0);
  1438. _EnableControls();
  1439. _UpdatePreview(0, TRUE);
  1440. EnableApplyButton(_hwnd);
  1441. break;
  1442. }
  1443. break;
  1444. case IDC_BACK_BROWSE:
  1445. _BrowseForBackground();
  1446. break;
  1447. case IDC_BACK_WEB:
  1448. _LaunchAdvancedDisplayProperties(_hwnd);
  1449. break;
  1450. case IDC_BACK_COLORPICKER:
  1451. {
  1452. COLORREF rbgColorNew;
  1453. if (SUCCEEDED(_colorControl.OnCommand(hdlg, uMsg, wParam, lParam)) &&
  1454. SUCCEEDED(_colorControl.GetColor(&rbgColorNew)) &&
  1455. (rbgColorNew != _rgbBkgdColor))
  1456. {
  1457. _rgbBkgdColor = rbgColorNew;
  1458. if (_punkSite)
  1459. {
  1460. IPropertyBag * pPropertyBag;
  1461. if (SUCCEEDED(_punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag))))
  1462. {
  1463. SHPropertyBag_WriteDWORD(pPropertyBag, SZ_PBPROP_BACKGROUND_COLOR, _rgbBkgdColor);
  1464. pPropertyBag->Release();
  1465. }
  1466. }
  1467. EnableApplyButton(_hwnd);
  1468. _UpdatePreview(0, TRUE);
  1469. }
  1470. }
  1471. break;
  1472. }
  1473. }
  1474. HRESULT CBackPropSheetPage::_BrowseForBackground(void)
  1475. {
  1476. HRESULT hr;
  1477. WCHAR wszFileName[INTERNET_MAX_URL_LENGTH];
  1478. hr = g_pActiveDesk->GetWallpaper(wszFileName, ARRAYSIZE(wszFileName), 0);
  1479. if (SUCCEEDED(hr))
  1480. {
  1481. WCHAR szTestPath[MAX_PATH];
  1482. WCHAR szPath[MAX_PATH];
  1483. // Default to the directory that contains the current wallpaper
  1484. StringCchCopy(szPath, ARRAYSIZE(szPath), wszFileName);
  1485. PathRemoveFileSpec(szPath);
  1486. // However, if it's one of the boring directories, then use the
  1487. // "My Pictures" folder instead (if available).
  1488. BOOL fBoring = FALSE;
  1489. if (!szPath[0]) // null string is boring
  1490. {
  1491. fBoring = TRUE;
  1492. }
  1493. else if (GetWindowsDirectory(szTestPath, ARRAYSIZE(szTestPath)) &&
  1494. !StrCmpIW(szTestPath, szPath)) // %windir% is boring
  1495. {
  1496. fBoring = TRUE;
  1497. }
  1498. else if (GetSystemDirectory(szTestPath, ARRAYSIZE(szTestPath)) &&
  1499. !StrCmpIW(szTestPath, szPath)) // %windir%\system32 is boring
  1500. {
  1501. fBoring = TRUE;
  1502. }
  1503. else if (GetWindowsDirectory(szTestPath, ARRAYSIZE(szTestPath)) &&
  1504. PathAppendW(szTestPath, L"Web\\Wallpaper") &&
  1505. !StrCmpIW(szTestPath, szPath)) // %windir%\web\wallpape ris boring
  1506. {
  1507. fBoring = TRUE;
  1508. }
  1509. hr = S_OK;
  1510. if (fBoring)
  1511. {
  1512. // Switch to CSIDL_MYPICTURES or CSIDL_PERSONAL if available
  1513. if (SHGetSpecialFolderPath(NULL, szTestPath, CSIDL_MYPICTURES, FALSE) ||
  1514. SHGetSpecialFolderPath(NULL, szTestPath, CSIDL_PERSONAL, FALSE))
  1515. {
  1516. StringCchCopy(wszFileName, ARRAYSIZE(wszFileName), szTestPath);
  1517. if (!PathAddBackslash(wszFileName))
  1518. {
  1519. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  1520. }
  1521. }
  1522. }
  1523. }
  1524. else
  1525. {
  1526. hr = S_OK;
  1527. // No current wallpaper. Use CSIDL_MYPICTURES if available; otherwise,
  1528. // use CSIDL_PERSONAL instead. If that doesn't work either, the code
  1529. // further below will fall back to %windir%.
  1530. if (SHGetSpecialFolderPath(NULL, wszFileName, CSIDL_MYPICTURES, FALSE) ||
  1531. SHGetSpecialFolderPath(NULL, wszFileName, CSIDL_PERSONAL, FALSE))
  1532. {
  1533. if (!PathAddBackslash(wszFileName))
  1534. {
  1535. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  1536. }
  1537. }
  1538. }
  1539. if (SUCCEEDED(hr))
  1540. {
  1541. DWORD adwFlags[] = { GFN_PICTURE, GFN_PICTURE, 0, 0};
  1542. int aiTypes[] = { IDS_BACK_FILETYPES, IDS_ALL_PICTURES, 0, 0};
  1543. if (_fAllowHtml)
  1544. {
  1545. SetFlag(adwFlags[0], GFN_LOCALHTM);
  1546. SetFlag(adwFlags[2], GFN_LOCALHTM);
  1547. aiTypes[2] = IDS_HTMLDOC;
  1548. }
  1549. if (wszFileName[0] == TEXT('\0'))
  1550. {
  1551. if (!GetWindowsDirectory(wszFileName, ARRAYSIZE(wszFileName)))
  1552. {
  1553. wszFileName[0] = 0;
  1554. }
  1555. // GetFileName breaks up the string into a directory and file
  1556. // component, so we append a slash to make sure everything
  1557. // is considered part of the directory.
  1558. StringCchCat(wszFileName, ARRAYSIZE(wszFileName), TEXT("\\"));
  1559. }
  1560. if (GetFileName(_hwnd, wszFileName, ARRAYSIZE(wszFileName), aiTypes, adwFlags) &&
  1561. ValidateFileName(_hwnd, wszFileName, IDS_BACK_TYPE1))
  1562. {
  1563. if (_fAllowHtml || IsNormalWallpaper(wszFileName))
  1564. {
  1565. _SetNewWallpaper(wszFileName, TRUE);
  1566. EnableApplyButton(_hwnd);
  1567. }
  1568. }
  1569. }
  1570. return hr;
  1571. }
  1572. void CBackPropSheetPage::_OnDestroy()
  1573. {
  1574. }
  1575. INT_PTR CALLBACK CBackPropSheetPage::BackgroundDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  1576. {
  1577. CBackPropSheetPage * pThis = (CBackPropSheetPage *)GetWindowLongPtr(hDlg, DWLP_USER);
  1578. if (WM_INITDIALOG == wMsg)
  1579. {
  1580. PROPSHEETPAGE * pPropSheetPage = (PROPSHEETPAGE *) lParam;
  1581. if (pPropSheetPage)
  1582. {
  1583. SetWindowLongPtr(hDlg, DWLP_USER, pPropSheetPage->lParam);
  1584. pThis = (CBackPropSheetPage *)pPropSheetPage->lParam;
  1585. }
  1586. }
  1587. if (pThis)
  1588. return pThis->_BackgroundDlgProc(hDlg, wMsg, wParam, lParam);
  1589. return DefWindowProc(hDlg, wMsg, wParam, lParam);
  1590. }
  1591. BOOL_PTR CBackPropSheetPage::_BackgroundDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1592. {
  1593. switch(uMsg)
  1594. {
  1595. case WM_INITDIALOG:
  1596. _OnInitDialog(hdlg);
  1597. break;
  1598. case WM_NOTIFY:
  1599. _OnNotify((LPNMHDR)lParam);
  1600. break;
  1601. case WM_COMMAND:
  1602. _OnCommand(hdlg, uMsg, wParam, lParam);
  1603. break;
  1604. case WM_SYSCOLORCHANGE:
  1605. case WM_SETTINGCHANGE:
  1606. case WM_DISPLAYCHANGE:
  1607. case WM_QUERYNEWPALETTE:
  1608. case WM_PALETTECHANGED:
  1609. SHPropagateMessage(hdlg, uMsg, wParam, lParam, TRUE);
  1610. break;
  1611. case WM_HELP:
  1612. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, SZ_HELPFILE_DESKTOPTAB, HELP_WM_HELP, (ULONG_PTR)aBackHelpIDs);
  1613. break;
  1614. case WM_CONTEXTMENU:
  1615. WinHelp((HWND) wParam, SZ_HELPFILE_DESKTOPTAB, HELP_CONTEXTMENU, (ULONG_PTR)(LPVOID) aBackHelpIDs);
  1616. break;
  1617. case WM_DESTROY:
  1618. {
  1619. TCHAR szFileName[MAX_PATH];
  1620. //Delete the tempoaray HTX file created for non-HTML wallpaper preview.
  1621. GetTempPath(ARRAYSIZE(szFileName), szFileName);
  1622. if (PathAppend(szFileName, PREVIEW_PICTURE_FILENAME))
  1623. {
  1624. DeleteFile(szFileName);
  1625. }
  1626. _OnDestroy();
  1627. }
  1628. break;
  1629. case WM_DRAWITEM:
  1630. switch (wParam)
  1631. {
  1632. case IDC_BACK_COLORPICKER:
  1633. _colorControl.OnDrawItem(hdlg, uMsg, wParam, lParam);
  1634. return TRUE;
  1635. }
  1636. break;
  1637. case WM_THEMECHANGED:
  1638. _colorControl.ChangeTheme(hdlg);
  1639. break;
  1640. }
  1641. return FALSE;
  1642. }
  1643. HRESULT CBackPropSheetPage::_OnApply(void)
  1644. {
  1645. // Our parent dialog will be notified of the Apply event and will call our
  1646. // IBasePropPage::OnApply() to do the real work.
  1647. return S_OK;
  1648. }
  1649. /*****************************************************************************\
  1650. DESCRIPTION:
  1651. This function will start a background thread which will make sure our
  1652. MRU of pictures in the Wallpaper list have been checked. They will be checked
  1653. to verify that we know their width & height. This way, when we choose a wallpaper, we can quickly
  1654. see if it should use "Stretch" or "Tile". We want to tile if they are very
  1655. small, indicating that they are probably watermark in nature.
  1656. \*****************************************************************************/
  1657. #define TIME_SCANFREQUENCY (8 * 60 /*Secs*/) // We don't want to rescan the files more than once per 8 minutes
  1658. HRESULT CBackPropSheetPage::_StartSizeChecker(void)
  1659. {
  1660. HRESULT hr = S_OK;
  1661. BOOL fSkipCheck = FALSE;
  1662. DWORD dwType;
  1663. FILETIME ftLastScan;
  1664. FILETIME ftCurrentTime;
  1665. SYSTEMTIME stCurrentTime;
  1666. DWORD cbSize = sizeof(ftLastScan);
  1667. GetSystemTime(&stCurrentTime);
  1668. SystemTimeToFileTime(&stCurrentTime, &ftCurrentTime);
  1669. // If we have recently scanned, skip the scan.
  1670. if ((ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_WALLPAPER, SZ_REGVALUE_LASTSCAN, &dwType, (LPBYTE) &ftLastScan, &cbSize)) &&
  1671. (REG_BINARY == dwType) &&
  1672. (sizeof(ftLastScan) == cbSize))
  1673. {
  1674. ULARGE_INTEGER * pulLastScan = (ULARGE_INTEGER *)&ftLastScan;
  1675. ULARGE_INTEGER * pulCurrent = (ULARGE_INTEGER *)&ftCurrentTime;
  1676. ULARGE_INTEGER ulDelta;
  1677. ulDelta.QuadPart = (pulCurrent->QuadPart - pulLastScan->QuadPart);
  1678. ulDelta.QuadPart /= 10000000; // units in a second
  1679. if (ulDelta.QuadPart < TIME_SCANFREQUENCY)
  1680. {
  1681. fSkipCheck = TRUE;
  1682. }
  1683. }
  1684. if (!fSkipCheck)
  1685. {
  1686. AddRef();
  1687. if (!SHCreateThread(CBackPropSheetPage::SizeCheckerThreadProc, this, (CTF_COINIT | CTF_FREELIBANDEXIT | CTF_PROCESS_REF), NULL))
  1688. {
  1689. hr = E_FAIL;
  1690. Release();
  1691. }
  1692. SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_WALLPAPER, SZ_REGVALUE_LASTSCAN, REG_BINARY, (LPCBYTE) &ftCurrentTime, sizeof(ftLastScan));
  1693. }
  1694. return hr;
  1695. }
  1696. typedef struct
  1697. {
  1698. TCHAR szPath[MAX_PATH];
  1699. DWORD dwSizeX;
  1700. DWORD dwSizeY;
  1701. FILETIME ftLastModified;
  1702. } WALLPAPERSIZE_STRUCT;
  1703. #define MAX_WALLPAPERSIZEMRU 500
  1704. HRESULT CBackPropSheetPage::_GetMRUObject(IMruDataList ** ppSizeMRU)
  1705. {
  1706. HRESULT hr = CoCreateInstance(CLSID_MruLongList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IMruDataList, ppSizeMRU));
  1707. if (SUCCEEDED(hr))
  1708. {
  1709. hr = (*ppSizeMRU)->InitData(MAX_WALLPAPERSIZEMRU, MRULISTF_USE_STRCMPIW, HKEY_CURRENT_USER, SZ_REGKEY_WALLPAPERMRU, NULL);
  1710. if (FAILED(hr))
  1711. {
  1712. ATOMICRELEASE(*ppSizeMRU);
  1713. }
  1714. }
  1715. return hr;
  1716. }
  1717. HRESULT CBackPropSheetPage::_CalcSizeForFile(IN LPCTSTR pszPath, IN WIN32_FIND_DATA * pfdFile, IN OUT DWORD * pdwAdded)
  1718. {
  1719. HRESULT hr = S_OK;
  1720. if (!_pSizeMRUBk)
  1721. {
  1722. hr = _GetMRUObject(&_pSizeMRUBk);
  1723. }
  1724. if (SUCCEEDED(hr))
  1725. {
  1726. WALLPAPERSIZE_STRUCT wallpaperSize;
  1727. int nIndex;
  1728. StringCchCopy(wallpaperSize.szPath, ARRAYSIZE(wallpaperSize.szPath), pszPath);
  1729. // Let's see if it's already in the MRU.
  1730. hr = _pSizeMRUBk->FindData((LPCBYTE) &wallpaperSize, sizeof(wallpaperSize), &nIndex);
  1731. if (SUCCEEDED(hr))
  1732. {
  1733. // If so, let's see if it's been modified since.
  1734. hr = _pSizeMRUBk->GetData(nIndex, (LPBYTE) &wallpaperSize, sizeof(wallpaperSize));
  1735. if (SUCCEEDED(hr))
  1736. {
  1737. if (CompareFileTime(&wallpaperSize.ftLastModified, &pfdFile->ftLastWriteTime))
  1738. {
  1739. // We want to delete this index because it would colide with the name of
  1740. // the new entry we are going to add below.
  1741. _pSizeMRUBk->Delete(nIndex);
  1742. hr = E_FAIL; // We need to rescan.
  1743. }
  1744. else
  1745. {
  1746. (*pdwAdded)++; // We are only going to check the first 500 files. We don't want to waste too much time on this heuristical feature.
  1747. }
  1748. }
  1749. }
  1750. if (FAILED(hr))
  1751. {
  1752. (*pdwAdded)++; // We are only going to check the first 500 files. We don't want to waste too much time on this heuristical feature.
  1753. hr = S_OK;
  1754. // We didn't find it so we need to add it.
  1755. if (!_pImgFactBk)
  1756. {
  1757. hr = CoCreateInstance(CLSID_ShellImageDataFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellImageDataFactory, &_pImgFactBk));
  1758. }
  1759. if (SUCCEEDED(hr))
  1760. {
  1761. IShellImageData* pImage;
  1762. hr = _pImgFactBk->CreateImageFromFile(pszPath, &pImage);
  1763. if (SUCCEEDED(hr))
  1764. {
  1765. hr = pImage->Decode(SHIMGDEC_DEFAULT, 0, 0);
  1766. if (SUCCEEDED(hr))
  1767. {
  1768. SIZE size;
  1769. hr = pImage->GetSize(&size);
  1770. if (SUCCEEDED(hr) && size.cx && size.cy)
  1771. {
  1772. DWORD dwSlot = 0;
  1773. StringCchCopy(wallpaperSize.szPath, ARRAYSIZE(wallpaperSize.szPath), pszPath);
  1774. wallpaperSize.dwSizeX = size.cx;
  1775. wallpaperSize.dwSizeY = size.cy;
  1776. wallpaperSize.ftLastModified = pfdFile->ftLastWriteTime;
  1777. hr = _pSizeMRUBk->AddData((LPCBYTE) &wallpaperSize, sizeof(wallpaperSize), &dwSlot);
  1778. }
  1779. }
  1780. pImage->Release();
  1781. }
  1782. }
  1783. }
  1784. }
  1785. return hr;
  1786. }
  1787. HRESULT CBackPropSheetPage::_CalcSizeFromDir(IN LPCTSTR pszPath, IN OUT DWORD * pdwAdded, IN BOOL fRecursive)
  1788. {
  1789. HRESULT hr = S_OK;
  1790. if (MAX_WALLPAPERSIZEMRU > *pdwAdded)
  1791. {
  1792. WIN32_FIND_DATA findFileData;
  1793. TCHAR szSearchPath[MAX_PATH];
  1794. StringCchCopy(szSearchPath, ARRAYSIZE(szSearchPath), pszPath);
  1795. if (PathAppend(szSearchPath, SZ_ALL_FILTER))
  1796. {
  1797. HANDLE hFindFiles = FindFirstFile(szSearchPath, &findFileData);
  1798. if (hFindFiles && (INVALID_HANDLE_VALUE != hFindFiles))
  1799. {
  1800. while (hFindFiles && (INVALID_HANDLE_VALUE != hFindFiles) &&
  1801. (MAX_WALLPAPERSIZEMRU > *pdwAdded))
  1802. {
  1803. if (!PathIsDotOrDotDot(findFileData.cFileName))
  1804. {
  1805. if (FILE_ATTRIBUTE_DIRECTORY & findFileData.dwFileAttributes)
  1806. {
  1807. if (fRecursive)
  1808. {
  1809. TCHAR szSubDir[MAX_PATH];
  1810. StringCchCopy(szSubDir, ARRAYSIZE(szSubDir), pszPath);
  1811. if(PathAppend(szSubDir, findFileData.cFileName))
  1812. {
  1813. hr = _CalcSizeFromDir(szSubDir, pdwAdded, fRecursive);
  1814. }
  1815. else
  1816. {
  1817. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  1818. }
  1819. }
  1820. }
  1821. else
  1822. {
  1823. if (IsGraphicsFile(findFileData.cFileName))
  1824. {
  1825. TCHAR szPath[MAX_PATH];
  1826. StringCchCopy(szPath, ARRAYSIZE(szPath), pszPath);
  1827. if (PathAppend(szPath, findFileData.cFileName))
  1828. {
  1829. hr = _CalcSizeForFile(szPath, &findFileData, pdwAdded);
  1830. }
  1831. else
  1832. {
  1833. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  1834. }
  1835. }
  1836. }
  1837. }
  1838. if (!FindNextFile(hFindFiles, &findFileData))
  1839. {
  1840. break;
  1841. }
  1842. }
  1843. FindClose(hFindFiles);
  1844. }
  1845. }
  1846. else
  1847. {
  1848. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  1849. }
  1850. }
  1851. return hr;
  1852. }
  1853. /*****************************************************************************\
  1854. DESCRIPTION:
  1855. This function will create or update the sizes of the files we have in the
  1856. wallpaper list. We can later use this to decide if we want to select "Tile"
  1857. vs. "Stretch".
  1858. PERF:
  1859. We don't track more than 500 files because we want to keep the MRU from
  1860. growing too much. Users shouldn't have more than that many files normally.
  1861. And if so, they won't get this feature.
  1862. Max 500 Files: First scan will take ~35 seconds on a 300MHz 128MB machine.
  1863. Max 500 Files: Update scan will take ~3 seconds on a 300MHz 128MB machine.
  1864. \*****************************************************************************/
  1865. DWORD CBackPropSheetPage::_SizeCheckerThreadProc(void)
  1866. {
  1867. HRESULT hr;
  1868. DWORD dwAdded = 0;
  1869. TCHAR szPath[MAX_PATH];
  1870. // We want to make our priority low so we don't slow down the UI.
  1871. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
  1872. // Get the directory with the wallpaper files.
  1873. if (!GetStringFromReg(HKEY_LOCAL_MACHINE, c_szSetup, c_szSharedDir, szPath, ARRAYSIZE(szPath)))
  1874. {
  1875. if (!GetWindowsDirectory(szPath, ARRAYSIZE(szPath)))
  1876. {
  1877. szPath[0] = 0;
  1878. }
  1879. }
  1880. // Add only the *.BMP files in the windows directory.
  1881. _CalcSizeFromDir(szPath, &dwAdded, FALSE);
  1882. // Get the wallpaper Directory name
  1883. szPath[0] = 0;
  1884. GetWallpaperDirName(szPath, ARRAYSIZE(szPath));
  1885. if (szPath[0])
  1886. {
  1887. // Add all pictures from Wallpaper directory to the list!
  1888. _CalcSizeFromDir(szPath, &dwAdded, TRUE);
  1889. }
  1890. //Get the path to the "My Pictures" folder; do not autocreate
  1891. if (S_OK == SHGetFolderPath(NULL, CSIDL_MYPICTURES, NULL, 0, szPath))
  1892. {
  1893. // Add all pictures in "My Pictures" directory to the list!
  1894. hr = _CalcSizeFromDir(szPath, &dwAdded, TRUE);
  1895. }
  1896. //Get the path to the common "My Pictures" folder; do not autocreate
  1897. if (S_OK == SHGetFolderPath(NULL, CSIDL_COMMON_PICTURES, NULL, 0, szPath))
  1898. {
  1899. // Add all pictures in common "My Pictures" directory to the list!
  1900. hr = _CalcSizeFromDir(szPath, &dwAdded, TRUE);
  1901. }
  1902. // Add pictures from Theme Directories
  1903. // The follwoing directories can contain themes:
  1904. // Plus!98 Install Path\Themes
  1905. // Plus!95 Install Path\Themes
  1906. // Kids for Plus! Install Path\Themes
  1907. // Program Files\Plus!\Themes
  1908. if (SUCCEEDED(_GetPlus98ThemesDir(szPath, ARRAYSIZE(szPath))))
  1909. {
  1910. _CalcSizeFromDir(szPath, &dwAdded, TRUE);
  1911. }
  1912. else if (SUCCEEDED(_GetPlus95ThemesDir(szPath, ARRAYSIZE(szPath))))
  1913. {
  1914. _CalcSizeFromDir(szPath, &dwAdded, TRUE);
  1915. }
  1916. else if (SUCCEEDED(_GetKidsThemesDir(szPath, ARRAYSIZE(szPath))))
  1917. {
  1918. _CalcSizeFromDir(szPath, &dwAdded, TRUE);
  1919. }
  1920. else if (SUCCEEDED(_GetHardDirThemesDir(szPath, ARRAYSIZE(szPath))))
  1921. {
  1922. _CalcSizeFromDir(szPath, &dwAdded, TRUE);
  1923. }
  1924. ATOMICRELEASE(_pSizeMRUBk);
  1925. ATOMICRELEASE(_pImgFactBk);
  1926. _fScanFinished = TRUE;
  1927. Release();
  1928. return 0;
  1929. }
  1930. // We decide to use tile mode if the width and height of the
  1931. // picture are 256x256 or smaller. Anything this small is most
  1932. // likely a watermark. Besides, it will always look bad stretched
  1933. // or centered.
  1934. // We make exceptions for the following wallpaper that we ship
  1935. // that is watermark:
  1936. // "Boiling Point.jpg", which is 163x293.
  1937. // "Fall Memories.jpg", which is 210x185.
  1938. // "Fly Away.jpg", which is 210x185.
  1939. // "Prairie Wind.jpg", which is 255x255.
  1940. // "Santa Fe Stucco.jpg", which is 256x256.
  1941. // "Soap Bubbles.jpg", which is 256x256.
  1942. // "Water Color.jpg", which is 218x162.
  1943. #define SHOULD_USE_TILE(xPicture, yPicture, xMonitor, yMonitor) ((((((LONG)(xPicture) * 6) < (xMonitor)) && (((LONG)(yPicture) * 6) < (yMonitor)))) || \
  1944. (((xPicture) <= 256) && ((yPicture) <= 256)) || \
  1945. (((xPicture) == 163) && ((yPicture) == 293)))
  1946. DWORD CBackPropSheetPage::_GetStretchMode(IN LPCTSTR pszPath)
  1947. {
  1948. HRESULT hr = S_OK;
  1949. DWORD dwStretchMode = WPSTYLE_STRETCH; // Default to Stretch.
  1950. if (_fScanFinished)
  1951. {
  1952. // If we just finished the Scan, we want to release _pSizeMRU and get a new one.
  1953. // The object will cache the registry state so it may have none or very few of the results
  1954. // because it was obtained before the background thread did all it's work.
  1955. ATOMICRELEASE(_pSizeMRU);
  1956. _fScanFinished = FALSE;
  1957. }
  1958. if (!_pSizeMRU)
  1959. {
  1960. hr = _GetMRUObject(&_pSizeMRU);
  1961. }
  1962. if (SUCCEEDED(hr))
  1963. {
  1964. WALLPAPERSIZE_STRUCT wallpaperSize;
  1965. int nIndex;
  1966. StringCchCopy(wallpaperSize.szPath, ARRAYSIZE(wallpaperSize.szPath), pszPath);
  1967. // Let's see if it's already in the MRU.
  1968. hr = _pSizeMRU->FindData((LPCBYTE) &wallpaperSize, sizeof(wallpaperSize), &nIndex);
  1969. if (SUCCEEDED(hr))
  1970. {
  1971. // If so, let's see if it's been modified since.
  1972. hr = _pSizeMRU->GetData(nIndex, (LPBYTE) &wallpaperSize, sizeof(wallpaperSize));
  1973. if (SUCCEEDED(hr))
  1974. {
  1975. WIN32_FIND_DATA findFileData;
  1976. HANDLE hFindFiles = FindFirstFile(pszPath, &findFileData);
  1977. if (hFindFiles && (INVALID_HANDLE_VALUE != hFindFiles))
  1978. {
  1979. // Yes, the value exists and is up to date.
  1980. if (!CompareFileTime(&wallpaperSize.ftLastModified, &findFileData.ftLastWriteTime))
  1981. {
  1982. RECT rc;
  1983. GetMonitorRects(GetPrimaryMonitor(), &rc, 0);
  1984. // We decide to use tile mode if the width and height of the
  1985. // picture are 1/6th the size of the default monitor.
  1986. if (SHOULD_USE_TILE(wallpaperSize.dwSizeX, wallpaperSize.dwSizeY, RECTWIDTH(rc), RECTHEIGHT(rc)))
  1987. {
  1988. dwStretchMode = WPSTYLE_TILE;
  1989. }
  1990. else
  1991. {
  1992. double dWidth = ((double)wallpaperSize.dwSizeX * ((double)RECTHEIGHT(rc) / ((double)RECTWIDTH(rc))));
  1993. // We want to use WPSTYLE_CENTER if it's more than 7% off of a 4x3 aspect ratio.
  1994. // We do this to prevent it from looking bad because it's stretched too much in
  1995. // one direction. The reason we use 7% is because some common screen solutions
  1996. // (1280 x 1024) aren't 4x3, but they are under 7% of that.
  1997. if (dWidth <= (wallpaperSize.dwSizeY * 1.07) && (dWidth >= (wallpaperSize.dwSizeY * 0.92)))
  1998. {
  1999. dwStretchMode = WPSTYLE_STRETCH; // This is within 4x3
  2000. }
  2001. else
  2002. {
  2003. dwStretchMode = WPSTYLE_CENTER;
  2004. }
  2005. }
  2006. }
  2007. FindClose(hFindFiles);
  2008. }
  2009. }
  2010. }
  2011. }
  2012. return dwStretchMode;
  2013. }
  2014. //===========================
  2015. // *** IBasePropPage Interface ***
  2016. //===========================
  2017. HRESULT CBackPropSheetPage::GetAdvancedDialog(OUT IAdvancedDialog ** ppAdvDialog)
  2018. {
  2019. HRESULT hr = E_INVALIDARG;
  2020. if (ppAdvDialog)
  2021. {
  2022. *ppAdvDialog = NULL;
  2023. hr = _LoadState();
  2024. if (SUCCEEDED(hr))
  2025. {
  2026. CCompPropSheetPage * pThis = new CCompPropSheetPage();
  2027. if (pThis)
  2028. {
  2029. hr = pThis->QueryInterface(IID_PPV_ARG(IAdvancedDialog, ppAdvDialog));
  2030. pThis->Release();
  2031. }
  2032. else
  2033. {
  2034. hr = E_OUTOFMEMORY;
  2035. }
  2036. }
  2037. }
  2038. return hr;
  2039. }
  2040. HRESULT CBackPropSheetPage::OnApply(IN PROPPAGEONAPPLY oaAction)
  2041. {
  2042. HRESULT hr = S_OK;
  2043. if (PPOAACTION_CANCEL != oaAction)
  2044. {
  2045. if (_fAllowChanges)
  2046. {
  2047. // The user clicked Okay in the dialog so merge the dirty state from the
  2048. // advanced dialog into the base dialog.
  2049. EnableADifHtmlWallpaper(_hwnd);
  2050. SetSafeMode(SSM_CLEAR);
  2051. g_pActiveDesk->SetWallpaper(_pszOriginalFile, 0);
  2052. SetSafeMode(SSM_CLEAR);
  2053. EnableADifHtmlWallpaper(_hwnd);
  2054. if (g_pActiveDesk)
  2055. {
  2056. g_pActiveDesk->ApplyChanges(g_dwApplyFlags);
  2057. }
  2058. }
  2059. if (SUCCEEDED(hr))
  2060. {
  2061. hr = _SaveIconState();
  2062. if (SUCCEEDED(hr))
  2063. {
  2064. hr = _SaveDesktopOptionsState();
  2065. }
  2066. }
  2067. if (g_iRunDesktopCleanup != BST_INDETERMINATE)
  2068. {
  2069. ApplyDesktopCleanupSettings(); // ignore return value, as nobody cares about it
  2070. }
  2071. SetWindowLongPtr(_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  2072. }
  2073. return hr;
  2074. }
  2075. BOOL IsIconHeaderProperty(IN LPCOLESTR pszPropName)
  2076. {
  2077. return (!StrCmpNIW(SZ_ICONHEADER, pszPropName, ARRAYSIZE(SZ_ICONHEADER) - 1) &&
  2078. ((ARRAYSIZE(SZ_ICONHEADER) + MAX_GUID_STRING_LEN - 1) < lstrlenW(pszPropName)));
  2079. }
  2080. BOOL IsShowDeskIconProperty(IN LPCOLESTR pszPropName)
  2081. {
  2082. return ((!StrCmpNIW(STARTPAGE_ON_PREFIX, pszPropName, LEN_PROP_PREFIX) ||
  2083. !StrCmpNIW(STARTPAGE_OFF_PREFIX, pszPropName, LEN_PROP_PREFIX) ||
  2084. !StrCmpNIW(POLICY_PREFIX, pszPropName, LEN_PROP_PREFIX)) &&
  2085. ((LEN_PROP_PREFIX + MAX_GUID_STRING_LEN - 1) <= lstrlenW(pszPropName)));
  2086. }
  2087. //===========================
  2088. // *** IPropertyBag Interface ***
  2089. //===========================
  2090. HRESULT CBackPropSheetPage::Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog)
  2091. {
  2092. HRESULT hr = E_INVALIDARG;
  2093. if (pszPropName && pVar)
  2094. {
  2095. VARTYPE vtDesired = pVar->vt;
  2096. if (!StrCmpW(pszPropName, SZ_PBPROP_BACKGROUND_PATH)) // Get the real current wallpaper (after conversion to .bmp)
  2097. {
  2098. WCHAR szPath[MAX_PATH];
  2099. hr = g_pActiveDesk->GetWallpaper(szPath, ARRAYSIZE(szPath), 0);
  2100. if (SUCCEEDED(hr))
  2101. {
  2102. WCHAR szFullPath[MAX_PATH];
  2103. // The string may come back with environment variables.
  2104. if (0 == SHExpandEnvironmentStrings(szPath, szFullPath, ARRAYSIZE(szFullPath)))
  2105. {
  2106. StringCchCopy(szFullPath, ARRAYSIZE(szFullPath), szPath); // We failed so use the original.
  2107. }
  2108. hr = InitVariantFromStr(pVar, szFullPath);
  2109. }
  2110. }
  2111. else if (!StrCmpW(pszPropName, SZ_PBPROP_BACKGROUNDSRC_PATH)) // Get the original wallpaper (before convertion to .bmp)
  2112. {
  2113. WCHAR szPath[MAX_PATH];
  2114. hr = _Initialize();
  2115. if (SUCCEEDED(hr))
  2116. {
  2117. if (_pszLastSourcePath)
  2118. {
  2119. hr = InitVariantFromStr(pVar, _pszLastSourcePath);
  2120. }
  2121. else if (_pszOrigLastApplied)
  2122. {
  2123. hr = InitVariantFromStr(pVar, _pszOrigLastApplied);
  2124. }
  2125. else
  2126. {
  2127. hr = g_pActiveDesk->GetWallpaper(szPath, ARRAYSIZE(szPath), 0);
  2128. if (SUCCEEDED(hr))
  2129. {
  2130. hr = InitVariantFromStr(pVar, szPath);
  2131. }
  2132. }
  2133. }
  2134. }
  2135. else if (!StrCmpW(pszPropName, SZ_PBPROP_BACKGROUND_TILE))
  2136. {
  2137. if (g_pActiveDesk)
  2138. {
  2139. WALLPAPEROPT wpo;
  2140. wpo.dwSize = sizeof(wpo);
  2141. hr = g_pActiveDesk->GetWallpaperOptions(&wpo, 0);
  2142. if (SUCCEEDED(hr))
  2143. {
  2144. pVar->ulVal = wpo.dwStyle;
  2145. pVar->vt = VT_UI4;
  2146. }
  2147. }
  2148. }
  2149. else if (!StrCmpW(pszPropName, SZ_PBPROP_WEBCOMPONENTS))
  2150. {
  2151. if (g_pActiveDesk)
  2152. {
  2153. g_pActiveDesk->AddRef();
  2154. pVar->punkVal = g_pActiveDesk;
  2155. pVar->vt = VT_UNKNOWN;
  2156. hr = S_OK;
  2157. }
  2158. }
  2159. else if (IsIconHeaderProperty(pszPropName))
  2160. {
  2161. // The caller can pass us the string in the following format:
  2162. // pszPropName="CLSID\{<CLSID>}\DefaultIcon:<Item>" = "<FilePath>,<ResourceIndex>"
  2163. // For example:
  2164. // pszPropName="CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon:DefaultValue" = "%WinDir%SYSTEM\COOL.DLL,16"
  2165. hr = _LoadState();
  2166. if (SUCCEEDED(hr))
  2167. {
  2168. CLSID clsid;
  2169. WCHAR szTemp[MAX_PATH];
  2170. // Get the CLSID
  2171. StringCchCopy(szTemp, ARRAYSIZE(szTemp), &(pszPropName[ARRAYSIZE(SZ_ICONHEADER) - 2]));
  2172. hr = SHCLSIDFromString(szTemp, &clsid);
  2173. if (SUCCEEDED(hr))
  2174. {
  2175. // Get the name of the icon type. Normally this is "DefaultIcon", but it can be several states, like
  2176. // "full" and "empty" for the recycle bin.
  2177. LPCWSTR pszToken = StrChrW((pszPropName + ARRAYSIZE(SZ_ICONHEADER)), L':');
  2178. BOOL fOldIcon = FALSE;
  2179. // If they use a ";" instead of a ":" then they want the old icon.
  2180. if (!pszToken)
  2181. {
  2182. pszToken = StrChrW((pszPropName + ARRAYSIZE(SZ_ICONHEADER)), L';');
  2183. fOldIcon = TRUE;
  2184. }
  2185. hr = E_FAIL;
  2186. if (pszToken)
  2187. {
  2188. TCHAR szIconPath[MAX_PATH];
  2189. pszToken++;
  2190. hr = _GetIconPath(clsid, pszToken, FALSE, szIconPath, ARRAYSIZE(szIconPath));
  2191. if (SUCCEEDED(hr))
  2192. {
  2193. hr = InitVariantFromStr(pVar, szIconPath);
  2194. }
  2195. }
  2196. }
  2197. }
  2198. }
  2199. else if(IsShowDeskIconProperty(pszPropName))
  2200. {
  2201. int iStartPaneOn = (int)(StrCmpNIW(pszPropName, STARTPAGE_ON_PREFIX, LEN_PROP_PREFIX) == 0);
  2202. for(int iIndex = 0; iIndex < NUM_DESKICONS; iIndex++)
  2203. {
  2204. if(lstrcmpiW(pszPropName+LEN_PROP_PREFIX, c_aDeskIconId[iIndex].pwszCLSID) == 0)
  2205. {
  2206. BOOL fBoolValue = FALSE;
  2207. pVar->vt = VT_BOOL;
  2208. //Check if we are looking for the POLICY or for Show/Hide
  2209. if(!StrCmpNIW(POLICY_PREFIX, pszPropName, LEN_PROP_PREFIX))
  2210. {
  2211. //We are reading "whether-the-POLICY-is-set" property!
  2212. fBoolValue = _aDeskIconNonEnumData[iIndex].fNonEnumPolicySet;
  2213. }
  2214. else
  2215. {
  2216. //We are reading the fHideIcon property.
  2217. fBoolValue = _aHideDesktopIcon[iStartPaneOn][iIndex].fHideIcon;
  2218. }
  2219. pVar ->boolVal = fBoolValue ? VARIANT_TRUE : VARIANT_FALSE;
  2220. hr = S_OK;
  2221. break; //break out of the loop!
  2222. }
  2223. }
  2224. }
  2225. if (SUCCEEDED(hr))
  2226. hr = VariantChangeTypeForRead(pVar, vtDesired);
  2227. }
  2228. return hr;
  2229. }
  2230. HRESULT CBackPropSheetPage::Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar)
  2231. {
  2232. HRESULT hr = E_INVALIDARG;
  2233. if (pszPropName && pVar)
  2234. {
  2235. if ((VT_UI4 == pVar->vt) &&
  2236. _fAllowChanges &&
  2237. !StrCmpW(pszPropName, SZ_PBPROP_BACKGROUND_TILE))
  2238. {
  2239. hr = _SetNewWallpaperTile(pVar->ulVal, FALSE);
  2240. }
  2241. if (!StrCmpW(pszPropName, SZ_PBPROP_OPENADVANCEDDLG) &&
  2242. (VT_BOOL == pVar->vt))
  2243. {
  2244. _fOpenAdvOnInit = (VARIANT_TRUE == pVar->boolVal);
  2245. hr = S_OK;
  2246. }
  2247. else if (!StrCmpW(pszPropName, SZ_PBPROP_WEBCOMPONENTS) &&
  2248. (VT_UNKNOWN == pVar->vt))
  2249. {
  2250. IUnknown_Set((IUnknown **) &g_pActiveDesk, pVar->punkVal);
  2251. hr = S_OK;
  2252. }
  2253. else if (VT_BSTR == pVar->vt)
  2254. {
  2255. if (_fAllowChanges && !StrCmpW(pszPropName, SZ_PBPROP_BACKGROUND_PATH))
  2256. {
  2257. _fWallpaperChanged = TRUE;
  2258. hr = _SetNewWallpaper(pVar->bstrVal, FALSE);
  2259. }
  2260. else if (IsIconHeaderProperty(pszPropName))
  2261. {
  2262. // The caller can pass us the string in the following format:
  2263. // pszPropName="CLSID\{<CLSID>}\DefaultIcon:<Item>" = "<FilePath>,<ResourceIndex>"
  2264. // For example:
  2265. // pszPropName="CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon:DefaultValue" = "%WinDir%SYSTEM\COOL.DLL,16"
  2266. hr = _LoadState();
  2267. if (SUCCEEDED(hr))
  2268. {
  2269. CLSID clsid;
  2270. WCHAR szTemp[MAX_PATH];
  2271. // Get the CLSID
  2272. StringCchCopy(szTemp, ARRAYSIZE(szTemp), &(pszPropName[ARRAYSIZE(SZ_ICONHEADER) - 2]));
  2273. hr = SHCLSIDFromString(szTemp, &clsid);
  2274. if (SUCCEEDED(hr))
  2275. {
  2276. // Get the name of the icon type. Normally this is "DefaultIcon", but it can be several states, like
  2277. // "full" and "empty" for the recycle bin.
  2278. LPCWSTR pszToken = StrChrW((pszPropName + ARRAYSIZE(SZ_ICONHEADER)), L':');
  2279. hr = E_FAIL;
  2280. if (pszToken)
  2281. {
  2282. pszToken++;
  2283. StringCchCopy(szTemp, ARRAYSIZE(szTemp), pszToken);
  2284. // Now the pVar->bstrVal is the icon path + "," + resourceID. Separate those two.
  2285. WCHAR szPath[MAX_PATH];
  2286. StringCchCopy(szPath, ARRAYSIZE(szPath), pVar->bstrVal);
  2287. int nResourceID = PathParseIconLocationW(szPath);
  2288. hr = _SetIconPath(clsid, szTemp, szPath, nResourceID);
  2289. }
  2290. }
  2291. }
  2292. }
  2293. }
  2294. else if((VT_BOOL == pVar->vt) && (IsShowDeskIconProperty(pszPropName)))
  2295. {
  2296. int iStartPaneOn = (int)(StrCmpNIW(pszPropName, STARTPAGE_ON_PREFIX, LEN_PROP_PREFIX) == 0);
  2297. for(int iIndex = 0; iIndex < NUM_DESKICONS; iIndex++)
  2298. {
  2299. if(lstrcmpiW(pszPropName+LEN_PROP_PREFIX, c_aDeskIconId[iIndex].pwszCLSID) == 0)
  2300. {
  2301. BOOL fNewHideIconStatus = (VARIANT_TRUE == pVar->boolVal);
  2302. //check if the new hide icon status is different from the old one.
  2303. if(_aHideDesktopIcon[iStartPaneOn][iIndex].fHideIcon != fNewHideIconStatus)
  2304. {
  2305. _aHideDesktopIcon[iStartPaneOn][iIndex].fHideIcon = fNewHideIconStatus;
  2306. _aHideDesktopIcon[iStartPaneOn][iIndex].fDirty = TRUE;
  2307. _fHideDesktopIconDirty = TRUE;
  2308. }
  2309. hr = S_OK;
  2310. break; //break out of the loop!
  2311. }
  2312. }
  2313. }
  2314. }
  2315. return hr;
  2316. }
  2317. //===========================
  2318. // *** IShellPropSheetExt Interface ***
  2319. //===========================
  2320. HRESULT CBackPropSheetPage::AddPages(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam)
  2321. {
  2322. HRESULT hr = E_NOTIMPL;
  2323. PROPSHEETPAGE psp = {0};
  2324. // If classic shell is forced, then we desk.cpl will put-up the old background page
  2325. // So, we should not replace that with this new background page.
  2326. // (Note: All other ActiveDesktop restrictions are checked in dcomp.cpp to prevent
  2327. // the web tab from appearing there).
  2328. if (SHRestricted(REST_CLASSICSHELL))
  2329. {
  2330. // It's restricted, so don't add this page.
  2331. hr = E_ACCESSDENIED;
  2332. }
  2333. else
  2334. {
  2335. // Initialize a bunch of propsheetpage variables.
  2336. psp.dwSize = sizeof(psp);
  2337. psp.hInstance = HINST_THISDLL;
  2338. psp.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
  2339. psp.lParam = (LPARAM) this;
  2340. // psp.hIcon = NULL; // unused (PSP_USEICON is not set)
  2341. // psp.pszTitle = NULL; // unused (PSP_USETITLE is not set)
  2342. // psp.lParam = 0; // unused
  2343. // psp.pcRefParent = NULL;
  2344. psp.pszTemplate = MAKEINTRESOURCE(IDD_BACKGROUND);
  2345. psp.pfnDlgProc = CBackPropSheetPage::BackgroundDlgProc;
  2346. HPROPSHEETPAGE hpsp = CreatePropertySheetPage(&psp);
  2347. if (hpsp)
  2348. {
  2349. if (pfnAddPage(hpsp, lParam))
  2350. {
  2351. hr = S_OK;
  2352. }
  2353. else
  2354. {
  2355. DestroyPropertySheetPage(hpsp);
  2356. hr = E_FAIL;
  2357. }
  2358. }
  2359. else
  2360. {
  2361. hr = E_OUTOFMEMORY;
  2362. }
  2363. }
  2364. return hr;
  2365. }
  2366. //===========================
  2367. // *** IUnknown Interface ***
  2368. //===========================
  2369. ULONG CBackPropSheetPage::AddRef()
  2370. {
  2371. _cRef++;
  2372. return _cRef;
  2373. }
  2374. ULONG CBackPropSheetPage::Release()
  2375. {
  2376. ASSERT(_cRef > 0);
  2377. _cRef--;
  2378. if (_cRef > 0)
  2379. return _cRef;
  2380. delete this;
  2381. return 0;
  2382. }
  2383. HRESULT CBackPropSheetPage::QueryInterface(REFIID riid, void **ppvObj)
  2384. {
  2385. HRESULT hr = E_NOINTERFACE;
  2386. static const QITAB qit[] = {
  2387. QITABENT(CBackPropSheetPage, IObjectWithSite),
  2388. QITABENT(CBackPropSheetPage, IBasePropPage),
  2389. QITABENT(CBackPropSheetPage, IPersist),
  2390. QITABENT(CBackPropSheetPage, IPropertyBag),
  2391. QITABENTMULTI(CBackPropSheetPage, IShellPropSheetExt, IBasePropPage),
  2392. { 0 },
  2393. };
  2394. return QISearch(this, qit, riid, ppvObj);
  2395. }
  2396. //===========================
  2397. // *** Class Methods ***
  2398. //===========================
  2399. CBackPropSheetPage::CBackPropSheetPage(void) : CObjectCLSID(&PPID_Background)
  2400. {
  2401. _cRef = 1;
  2402. _punkSite = NULL;
  2403. _pszOriginalFile = NULL;
  2404. _pszLastSourcePath = NULL;
  2405. _pszOrigLastApplied = NULL;
  2406. _pszWallpaperInUse = NULL;
  2407. _pImgFactBk = NULL;
  2408. _pSizeMRU = NULL;
  2409. _pSizeMRUBk = NULL;
  2410. _fThemePreviewCreated = FALSE;
  2411. _pThemePreview = NULL;
  2412. _fWallpaperChanged = FALSE;
  2413. _fSelectionFromUser = TRUE;
  2414. _fStateLoaded = FALSE;
  2415. _fOpenAdvOnInit = FALSE;
  2416. _fScanFinished = FALSE;
  2417. _fInitialized = FALSE;
  2418. _fAllowChanges = (!SHRestricted(REST_NOCHANGINGWALLPAPER) && !IsTSPerfFlagEnabled(TSPerFlag_NoADWallpaper) && !IsTSPerfFlagEnabled(TSPerFlag_NoWallpaper));
  2419. g_dwApplyFlags = (AD_APPLY_ALL | AD_APPLY_DYNAMICREFRESH);
  2420. GetActiveDesktop(&g_pActiveDesk);
  2421. }
  2422. CBackPropSheetPage::~CBackPropSheetPage(void)
  2423. {
  2424. ASSERT(!_pSizeMRUBk); // Should have been released by the background thread.
  2425. ASSERT(!_pImgFactBk); // Should have been released by the background thread.
  2426. Str_SetPtr(&_pszOriginalFile, NULL);
  2427. Str_SetPtrW(&_pszOrigLastApplied, NULL);
  2428. Str_SetPtrW(&_pszWallpaperInUse, NULL);
  2429. Str_SetPtrW(&_pszLastSourcePath, NULL);
  2430. if (_pSizeMRU)
  2431. {
  2432. _pSizeMRU->Release();
  2433. _pSizeMRU = NULL;
  2434. }
  2435. if (_pThemePreview)
  2436. {
  2437. _pThemePreview->Release();
  2438. _pThemePreview = NULL;
  2439. }
  2440. ReleaseActiveDesktop(&g_pActiveDesk);
  2441. }