Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1067 lines
32 KiB

  1. /*****************************************************************************\
  2. FILE: stgTheme.cpp
  3. DESCRIPTION:
  4. This is the Autmation Object to theme manager object.
  5. BryanSt 4/3/2000 (Bryan Starbuck)
  6. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  7. \*****************************************************************************/
  8. #include "priv.h"
  9. extern BOOL IsUserHighContrastUser(void);
  10. //===========================
  11. // *** Class Internals & Helpers ***
  12. //===========================
  13. // lParam can be: 0 == do a case sensitive search. 1 == do a case insensitive search.
  14. int DPA_StringCompareCB(LPVOID pvString1, LPVOID pvString2, LPARAM lParam)
  15. {
  16. // return < 0 for pvPidl1 before pvPidl2.
  17. // return == 0 for pvPidl1 equals pvPidl2.
  18. // return > 0 for pvPidl1 after pvPidl2.
  19. int nSort = 0; // Default to equal
  20. LPCTSTR pszToInsert = (LPCTSTR)pvString1;
  21. LPCTSTR pszToComparePath = (LPCTSTR)pvString2;
  22. if (pszToInsert && pszToComparePath)
  23. {
  24. LPCTSTR pszToCompareFileName = PathFindFileName(pszToComparePath);
  25. if (pszToCompareFileName)
  26. {
  27. nSort = StrCmp(pszToInsert, pszToCompareFileName);
  28. }
  29. }
  30. return nSort;
  31. }
  32. #define SZ_THEMES_FILTER TEXT("*.theme")
  33. #define SZ_ALL_FILTER TEXT("*.*")
  34. HRESULT CThemeManager::_AddThemesFromDir(LPCTSTR pszPath, BOOL fFirstLevel, int nInsertLoc)
  35. {
  36. HRESULT hr = S_OK;
  37. WIN32_FIND_DATA findFileData;
  38. TCHAR szSearch[MAX_PATH];
  39. AssertMsg((nInsertLoc >= 0), TEXT("nInsertLoc should never be negative"));
  40. StrCpyN(szSearch, pszPath, ARRAYSIZE(szSearch));
  41. PathAppend(szSearch, SZ_THEMES_FILTER);
  42. HANDLE hFindFiles = FindFirstFile(szSearch, &findFileData);
  43. if (hFindFiles && (INVALID_HANDLE_VALUE != hFindFiles))
  44. {
  45. while (hFindFiles && (INVALID_HANDLE_VALUE != hFindFiles))
  46. {
  47. if (!(FILE_ATTRIBUTE_DIRECTORY & findFileData.dwFileAttributes))
  48. {
  49. StrCpyN(szSearch, pszPath, ARRAYSIZE(szSearch));
  50. PathAppend(szSearch, findFileData.cFileName);
  51. LPWSTR pszPath = StrDup(szSearch);
  52. if (pszPath)
  53. {
  54. if (nInsertLoc)
  55. {
  56. if (-1 == DPA_InsertPtr(m_hdpaThemeDirs, nInsertLoc - 1, pszPath))
  57. {
  58. // We failed so free the memory
  59. LocalFree(pszPath);
  60. hr = E_OUTOFMEMORY;
  61. }
  62. else
  63. {
  64. nInsertLoc++;
  65. }
  66. }
  67. else
  68. {
  69. if (-1 == DPA_SortedInsertPtr(m_hdpaThemeDirs, PathFindFileName(pszPath), 0, DPA_StringCompareCB, NULL, DPAS_INSERTBEFORE, pszPath))
  70. {
  71. // We failed so free the memory
  72. LocalFree(pszPath);
  73. hr = E_OUTOFMEMORY;
  74. }
  75. }
  76. }
  77. }
  78. if (!FindNextFile(hFindFiles, &findFileData))
  79. {
  80. break;
  81. }
  82. }
  83. FindClose(hFindFiles);
  84. }
  85. // We only want to recurse one directory.
  86. if (fFirstLevel)
  87. {
  88. StrCpyN(szSearch, pszPath, ARRAYSIZE(szSearch));
  89. PathAppend(szSearch, SZ_ALL_FILTER);
  90. HANDLE hFindFiles = FindFirstFile(szSearch, &findFileData);
  91. if (hFindFiles && (INVALID_HANDLE_VALUE != hFindFiles))
  92. {
  93. while (hFindFiles && (INVALID_HANDLE_VALUE != hFindFiles))
  94. {
  95. // We are looking for any directories. Of course we exclude "." and "..".
  96. if ((FILE_ATTRIBUTE_DIRECTORY & findFileData.dwFileAttributes) &&
  97. StrCmpI(findFileData.cFileName, TEXT(".")) &&
  98. StrCmpI(findFileData.cFileName, TEXT("..")))
  99. {
  100. StrCpyN(szSearch, pszPath, ARRAYSIZE(szSearch));
  101. PathAppend(szSearch, findFileData.cFileName);
  102. _AddThemesFromDir(szSearch, FALSE, nInsertLoc);
  103. }
  104. if (!FindNextFile(hFindFiles, &findFileData))
  105. {
  106. break;
  107. }
  108. }
  109. FindClose(hFindFiles);
  110. }
  111. }
  112. // We will want to repeat this process recursively for directories. At least
  113. // one level of recursively.
  114. return hr;
  115. }
  116. HRESULT CThemeManager::_InitThemeDirs(void)
  117. {
  118. HRESULT hr = S_OK;
  119. if (!m_hdpaThemeDirs)
  120. {
  121. if (SHRegGetBoolUSValue(SZ_THEMES, SZ_REGVALUE_ENABLEPLUSTHEMES, FALSE, TRUE))
  122. {
  123. m_hdpaThemeDirs = DPA_Create(2);
  124. if (m_hdpaThemeDirs)
  125. {
  126. TCHAR szPath[MAX_PATH];
  127. // The follwoing directories can contain themes:
  128. // Plus!98 Install Path\Themes
  129. // Plus!95 Install Path\Themes
  130. // Kids for Plus! Install Path\Themes
  131. // Program Files\Plus!\Themes
  132. if (SUCCEEDED(GetPlusThemeDir(szPath, ARRAYSIZE(szPath))))
  133. {
  134. _AddThemesFromDir(szPath, TRUE, 0);
  135. }
  136. hr = SHGetResourcePath(TRUE, szPath, ARRAYSIZE(szPath));
  137. if (SUCCEEDED(hr))
  138. {
  139. _AddThemesFromDir(szPath, TRUE, 1);
  140. }
  141. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, TRUE))
  142. {
  143. PathAppend(szPath, TEXT("Microsoft\\Windows\\Themes"));
  144. _AddThemesFromDir(szPath, TRUE, 1);
  145. }
  146. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_PERSONAL, TRUE))
  147. {
  148. _AddThemesFromDir(szPath, TRUE, 1);
  149. }
  150. // Enum any paths 3rd parties add to the registry
  151. HKEY hKey;
  152. if (SUCCEEDED(HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_THEMES_THEMEDIRS, 0, KEY_READ, &hKey)))
  153. {
  154. for (int nDirIndex = 0; SUCCEEDED(hr); nDirIndex++)
  155. {
  156. TCHAR szValueName[MAXIMUM_VALUE_NAME_LENGTH];
  157. DWORD cchSize = ARRAYSIZE(szValueName);
  158. DWORD dwType;
  159. DWORD cbSize = sizeof(szPath);
  160. hr = HrRegEnumValue(hKey, nDirIndex, szValueName, &cchSize, 0, &dwType, (LPBYTE)szPath, &cbSize);
  161. if (SUCCEEDED(hr))
  162. {
  163. TCHAR szFinalPath[MAX_PATH];
  164. if (0 == SHExpandEnvironmentStringsForUserW(NULL, szPath, szFinalPath, ARRAYSIZE(szFinalPath)))
  165. {
  166. StrCpyN(szFinalPath, szPath, ARRAYSIZE(szFinalPath));
  167. }
  168. _AddThemesFromDir(szFinalPath, TRUE, 1);
  169. }
  170. }
  171. hr = S_OK;
  172. RegCloseKey(hKey);
  173. }
  174. }
  175. else
  176. {
  177. hr = E_OUTOFMEMORY;
  178. }
  179. }
  180. }
  181. return hr;
  182. }
  183. #define SZ_THEMES TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Themes")
  184. #define SZ_REGVALUE_REQUIRESIGNING TEXT("Require VisualStyle Signing")
  185. HRESULT CThemeManager::_EnumSkinCB(THEMECALLBACK tcbType, LPCWSTR pszFileName, OPTIONAL LPCWSTR pszDisplayName, OPTIONAL LPCWSTR pszToolTip, OPTIONAL int iIndex)
  186. {
  187. HRESULT hr = S_OK;
  188. // only signed theme files will be enumerated and passed to this function
  189. if (pszFileName)
  190. {
  191. LPWSTR pszPath = StrDup(pszFileName);
  192. AssertMsg((NULL != m_hdpaSkinDirs), TEXT("We should never hit this. We will leak. -BryanSt"));
  193. if (pszPath)
  194. {
  195. if (-1 == DPA_AppendPtr(m_hdpaSkinDirs, pszPath))
  196. {
  197. // We failed so free the memory
  198. LocalFree(pszPath);
  199. }
  200. }
  201. }
  202. return hr;
  203. }
  204. BOOL CThemeManager::EnumSkinCB(THEMECALLBACK tcbType, LPCWSTR pszFileName, OPTIONAL LPCWSTR pszDisplayName,
  205. OPTIONAL LPCWSTR pszToolTip, OPTIONAL int iIndex, LPARAM lParam)
  206. {
  207. CThemeManager * pThis = (CThemeManager *) lParam;
  208. HRESULT hr = E_FAIL;
  209. if (pThis)
  210. {
  211. hr = pThis->_EnumSkinCB(tcbType, pszFileName, pszDisplayName, pszToolTip, iIndex);
  212. }
  213. return SUCCEEDED(hr);
  214. }
  215. HRESULT CThemeManager::_EnumSkinsFromKey(HKEY hKey)
  216. {
  217. HRESULT hr = S_OK;
  218. TCHAR szPath[MAX_PATH];
  219. for (int nDirIndex = 0; SUCCEEDED(hr); nDirIndex++)
  220. {
  221. TCHAR szValueName[MAXIMUM_VALUE_NAME_LENGTH];
  222. DWORD cchSize = ARRAYSIZE(szValueName);
  223. DWORD dwType;
  224. DWORD cbSize = sizeof(szPath);
  225. hr = HrRegEnumValue(hKey, nDirIndex, szValueName, &cchSize, 0, &dwType, (LPBYTE)szPath, &cbSize);
  226. if (SUCCEEDED(hr))
  227. {
  228. hr = ExpandResourceDir(szPath, ARRAYSIZE(szPath));
  229. if (SUCCEEDED(hr))
  230. {
  231. hr = EnumThemes(szPath, CThemeManager::EnumSkinCB, (LPARAM) this);
  232. LogStatus("EnumThemes(path=\"%ls\") returned %#08lx in CThemeManager::_EnumSkinsFromKey.\r\n", szPath, hr);
  233. }
  234. }
  235. }
  236. return S_OK;
  237. }
  238. HRESULT CThemeManager::_InitSkinDirs(void)
  239. {
  240. HRESULT hr = S_OK;
  241. if (!m_hdpaSkinDirs)
  242. {
  243. m_hdpaSkinDirs = DPA_Create(2);
  244. if (m_hdpaSkinDirs)
  245. {
  246. // We only want to add skins if they are supported. They are only supported if the VisualStyle manager
  247. // can run. We will know that if QueryThemeServices() returns QTS_GLOBALAVAILABLE.
  248. BOOL fVisualStylesSupported = (QueryThemeServicesWrap() & QTS_AVAILABLE);
  249. LogStatus("QueryThemeServices() returned %hs in CThemeManager::_InitSkinDirs\r\n", (fVisualStylesSupported ? "TRUE" : "FALSE"));
  250. // Note that the VisualStyle's Manager API only works when explorer is running. This means we will
  251. // lack functionality, but it is their limitation, not ours.
  252. if (fVisualStylesSupported)
  253. {
  254. HKEY hNewKey;
  255. if (SUCCEEDED(HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_THEMES_MSTHEMEDIRS, 0, KEY_READ, &hNewKey)))
  256. {
  257. hr = _EnumSkinsFromKey(hNewKey);
  258. RegCloseKey(hNewKey);
  259. }
  260. if (SUCCEEDED(HrRegOpenKeyEx(HKEY_CURRENT_USER, SZ_THEMES_MSTHEMEDIRS, 0, KEY_READ, &hNewKey)))
  261. {
  262. hr = _EnumSkinsFromKey(hNewKey);
  263. RegCloseKey(hNewKey);
  264. }
  265. }
  266. }
  267. else
  268. {
  269. hr = E_OUTOFMEMORY;
  270. }
  271. }
  272. return hr;
  273. }
  274. HRESULT CThemeManager::_InitSelectedThemeFile(void)
  275. {
  276. HRESULT hr = E_INVALIDARG;
  277. if (!_pszSelectTheme)
  278. {
  279. WCHAR szPath[MAX_PATH];
  280. DWORD dwError = SHRegGetPathW(HKEY_CURRENT_USER, SZ_REGKEY_CURRENT_THEME, NULL, szPath, 0);
  281. hr = HRESULT_FROM_WIN32(dwError);
  282. // Is this the "<UserName>'s Custom Theme" item?
  283. // Or did it fail? If it failed, then no theme is selected.
  284. if (SUCCEEDED(hr))
  285. {
  286. Str_SetPtr(&_pszSelectTheme, szPath);
  287. hr = S_OK;
  288. }
  289. }
  290. return hr;
  291. }
  292. HRESULT CThemeManager::_SetSelectedThemeEntree(LPCWSTR pszPath)
  293. {
  294. HRESULT hr = E_INVALIDARG;
  295. Str_SetPtr(&_pszSelectTheme, pszPath);
  296. if (pszPath)
  297. {
  298. hr = HrRegSetPath(HKEY_CURRENT_USER, SZ_REGKEY_CURRENT_THEME, NULL, TRUE, pszPath);
  299. }
  300. else
  301. {
  302. hr = HrRegDeleteValue(HKEY_CURRENT_USER, SZ_REGKEY_CURRENT_THEME, NULL);
  303. }
  304. return hr;
  305. }
  306. //===========================
  307. // *** IThemeManager Interface ***
  308. //===========================
  309. HRESULT CThemeManager::get_SelectedTheme(OUT ITheme ** ppTheme)
  310. {
  311. HRESULT hr = E_INVALIDARG;
  312. if (ppTheme)
  313. {
  314. *ppTheme = NULL;
  315. if (IsSafeHost(&hr))
  316. {
  317. // In the future, we may want to call into PPID_Theme's IPropertyBag
  318. // to find the current visual style. This will factor in "(Modified)"
  319. // themes.
  320. hr = _InitSelectedThemeFile();
  321. if (SUCCEEDED(hr))
  322. {
  323. hr = CThemeFile_CreateInstance(_pszSelectTheme, ppTheme);
  324. }
  325. }
  326. }
  327. return hr;
  328. }
  329. /*****************************************************************************\
  330. DESCRIPTION:
  331. Don't forget that this change is not applied until ::ApplyNow() is
  332. called.
  333. \*****************************************************************************/
  334. HRESULT CThemeManager::put_SelectedTheme(IN ITheme * pTheme)
  335. {
  336. HRESULT hr = E_INVALIDARG;
  337. if (IsSafeHost(&hr))
  338. {
  339. CComBSTR bstrPath;
  340. if (pTheme)
  341. {
  342. // Persist the filename to the registry.
  343. hr = pTheme->GetPath(VARIANT_TRUE, &bstrPath);
  344. }
  345. if (SUCCEEDED(hr))
  346. {
  347. IPropertyBag * pPropertyBag;
  348. hr = _GetPropertyBagByCLSID(&PPID_Theme, &pPropertyBag);
  349. if (SUCCEEDED(hr))
  350. {
  351. hr = SHPropertyBag_WriteStr(pPropertyBag, SZ_PBPROP_THEME_LOADTHEME, bstrPath);
  352. pPropertyBag->Release();
  353. }
  354. }
  355. }
  356. return hr;
  357. }
  358. HRESULT CThemeManager::get_WebviewCSS(OUT BSTR * pbstrPath)
  359. {
  360. HRESULT hr = E_INVALIDARG;
  361. if (pbstrPath)
  362. {
  363. *pbstrPath = NULL;
  364. if (IsHostLocalZone(CAS_REG_VALIDATION, &hr))
  365. {
  366. IThemeScheme * pThemeScheme;
  367. hr = _saveGetSelectedScheme(&pThemeScheme);
  368. if (SUCCEEDED(hr))
  369. {
  370. IThemeStyle * pThemeStyle;
  371. hr = pThemeScheme->get_SelectedStyle(&pThemeStyle);
  372. if (SUCCEEDED(hr))
  373. {
  374. IThemeSize * pThemeSize;
  375. hr = pThemeStyle->get_SelectedSize(&pThemeSize);
  376. if (SUCCEEDED(hr))
  377. {
  378. hr = pThemeSize->get_WebviewCSS(pbstrPath);
  379. pThemeSize->Release();
  380. }
  381. pThemeStyle->Release();
  382. }
  383. pThemeScheme->Release();
  384. }
  385. }
  386. }
  387. return hr;
  388. }
  389. HRESULT CThemeManager::get_length(OUT long * pnLength)
  390. {
  391. HRESULT hr = E_INVALIDARG;
  392. if (pnLength)
  393. {
  394. *pnLength = 0;
  395. if (IsSafeHost(&hr))
  396. {
  397. hr = _InitThemeDirs();
  398. if (SUCCEEDED(hr))
  399. {
  400. if (m_hdpaThemeDirs)
  401. {
  402. *pnLength += DPA_GetPtrCount(m_hdpaThemeDirs);
  403. }
  404. }
  405. }
  406. }
  407. return hr;
  408. }
  409. HRESULT CThemeManager::get_item(IN VARIANT varIndex, OUT ITheme ** ppTheme)
  410. {
  411. HRESULT hr = E_INVALIDARG;
  412. if (ppTheme)
  413. {
  414. *ppTheme = NULL;
  415. if (IsSafeHost(&hr))
  416. {
  417. long nCount = 0;
  418. hr = E_INVALIDARG;
  419. get_length(&nCount);
  420. // This is sortof gross, but if we are passed a pointer to another variant, simply
  421. // update our copy here...
  422. if (varIndex.vt == (VT_BYREF | VT_VARIANT) && varIndex.pvarVal)
  423. varIndex = *(varIndex.pvarVal);
  424. switch (varIndex.vt)
  425. {
  426. case VT_I2:
  427. varIndex.lVal = (long)varIndex.iVal;
  428. // And fall through...
  429. case VT_I4:
  430. if ((varIndex.lVal >= 0) && (varIndex.lVal < nCount))
  431. {
  432. if (m_hdpaThemeDirs)
  433. {
  434. LPWSTR pszFilename = (LPWSTR) DPA_GetPtr(m_hdpaThemeDirs, varIndex.lVal);
  435. if (pszFilename)
  436. {
  437. hr = CThemeFile_CreateInstance(pszFilename, ppTheme);
  438. }
  439. else
  440. {
  441. hr = E_FAIL;
  442. }
  443. }
  444. else
  445. {
  446. AssertMsg(0, TEXT("This should have been initiailized by get_Length(). -BryanSt"));
  447. hr = E_FAIL;
  448. }
  449. }
  450. break;
  451. case VT_BSTR:
  452. if (varIndex.bstrVal)
  453. {
  454. hr = CThemeFile_CreateInstance(varIndex.bstrVal, ppTheme);
  455. }
  456. else
  457. {
  458. hr = E_INVALIDARG;
  459. }
  460. break;
  461. default:
  462. hr = E_NOTIMPL;
  463. }
  464. }
  465. }
  466. return hr;
  467. }
  468. HRESULT CThemeManager::get_SelectedScheme(OUT IThemeScheme ** ppThemeScheme)
  469. {
  470. HRESULT hr = E_INVALIDARG;
  471. if (ppThemeScheme)
  472. {
  473. *ppThemeScheme = NULL;
  474. if (IsSafeHost(&hr))
  475. {
  476. if (!_pThemeSchemeSelected)
  477. {
  478. hr = _saveGetSelectedScheme(&_pThemeSchemeSelected);
  479. }
  480. if (_pThemeSchemeSelected)
  481. {
  482. IUnknown_Set((IUnknown **) ppThemeScheme, _pThemeSchemeSelected);
  483. hr = S_OK;
  484. }
  485. }
  486. }
  487. return hr;
  488. }
  489. HRESULT CThemeManager::_saveGetSelectedScheme(OUT IThemeScheme ** ppThemeScheme)
  490. {
  491. HRESULT hr = E_INVALIDARG;
  492. if (ppThemeScheme)
  493. {
  494. *ppThemeScheme = NULL;
  495. BOOL fIsThemeActive = IsThemeActive();
  496. LogStatus("IsThemeActive() returned %hs in CThemeManager::_saveGetSelectedScheme.\r\n", (fIsThemeActive ? "TRUE" : "FALSE"));
  497. // The selected Scheme can either be a legacy "Appearance Scheme" or
  498. // a selected ".msstyles" (skin) file.
  499. if (fIsThemeActive)
  500. {
  501. WCHAR szPath[MAX_PATH];
  502. hr = GetCurrentThemeName(szPath, ARRAYSIZE(szPath), NULL, 0, NULL, 0);
  503. LogStatus("GetCurrentThemeName(path=\"%ls\", color=\"%ls\", size=\"%ls\") returned %#08lx in CThemeManager::_saveGetSelectedScheme.\r\n", szPath, TEXT("NULL"), TEXT("NULL"), hr);
  504. if (SUCCEEDED(hr))
  505. {
  506. hr = CSkinScheme_CreateInstance(szPath, ppThemeScheme);
  507. }
  508. // Currently, we create this object and get the size
  509. // in order to force an upgrade in case it's neccessary.
  510. IThemeScheme * pThemeSchemeTemp;
  511. if (SUCCEEDED(CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, &pThemeSchemeTemp))))
  512. {
  513. long nLength;
  514. pThemeSchemeTemp->get_length(&nLength);
  515. pThemeSchemeTemp->Release();
  516. }
  517. }
  518. // We want to get the Appearance scheme if no visual style is selected (i.e. IsThemeActive() returns FALSE).
  519. // However, if uxtheme gets confused, IsThemeActive() will return TRUE but GetCurrentThemeName() will fail.
  520. // in that case, we want to also fallback to the classic visual style so the UI is usable.
  521. if (FAILED(hr))
  522. {
  523. // The "Control Panel\\Appearance","Current" key will indicate the selected
  524. // Appearance Scheme.
  525. hr = CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, ppThemeScheme));
  526. }
  527. }
  528. return hr;
  529. }
  530. /*****************************************************************************\
  531. DESCRIPTION:
  532. Don't forget that this change is not applied until ::ApplyNow() is
  533. called.
  534. \*****************************************************************************/
  535. HRESULT CThemeManager::put_SelectedScheme(IN IThemeScheme * pThemeScheme)
  536. {
  537. HRESULT hr;
  538. if (IsSafeHost(&hr))
  539. {
  540. if (pThemeScheme)
  541. {
  542. CComBSTR bstrPath;
  543. IThemeStyle * pThemeStyle;
  544. IUnknown_Set((IUnknown **) &_pThemeSchemeSelected, pThemeScheme);
  545. pThemeScheme->get_Path(&bstrPath); // It's fine if it returns NULL or empty str.
  546. hr = pThemeScheme->get_SelectedStyle(&pThemeStyle);
  547. if (SUCCEEDED(hr))
  548. {
  549. CComBSTR bstrStyle;
  550. hr = pThemeStyle->get_Name(&bstrStyle);
  551. if (SUCCEEDED(hr))
  552. {
  553. IThemeSize * pThemeSize;
  554. hr = pThemeStyle->get_SelectedSize(&pThemeSize);
  555. if (SUCCEEDED(hr))
  556. {
  557. CComBSTR bstrSize;
  558. hr = pThemeSize->get_Name(&bstrSize);
  559. if (SUCCEEDED(hr))
  560. {
  561. VARIANT variant;
  562. variant.vt = VT_BSTR;
  563. variant.bstrVal = bstrPath;
  564. hr = Write(SZ_PBPROP_VISUALSTYLE_PATH, &variant);
  565. if (SUCCEEDED(hr))
  566. {
  567. variant.bstrVal = bstrStyle;
  568. hr = Write(SZ_PBPROP_VISUALSTYLE_COLOR, &variant);
  569. if (SUCCEEDED(hr))
  570. {
  571. variant.bstrVal = bstrSize;
  572. hr = Write(SZ_PBPROP_VISUALSTYLE_SIZE, &variant);
  573. }
  574. }
  575. }
  576. pThemeSize->Release();
  577. }
  578. }
  579. pThemeStyle->Release();
  580. }
  581. }
  582. else
  583. {
  584. hr = E_INVALIDARG;
  585. }
  586. }
  587. return hr;
  588. }
  589. HRESULT CThemeManager::get_schemeLength(OUT long * pnLength)
  590. {
  591. HRESULT hr = E_INVALIDARG;
  592. if (pnLength)
  593. {
  594. *pnLength = 1;
  595. if (IsSafeHost(&hr))
  596. {
  597. hr = _InitSkinDirs();
  598. if (SUCCEEDED(hr))
  599. {
  600. if (m_hdpaSkinDirs)
  601. {
  602. *pnLength += DPA_GetPtrCount(m_hdpaSkinDirs);
  603. }
  604. }
  605. }
  606. }
  607. return hr;
  608. }
  609. HRESULT CThemeManager::get_schemeItem(IN VARIANT varIndex, OUT IThemeScheme ** ppThemeScheme)
  610. {
  611. HRESULT hr = E_INVALIDARG;
  612. if (ppThemeScheme)
  613. {
  614. if (IsSafeHost(&hr))
  615. {
  616. long nCount = 0;
  617. hr = E_INVALIDARG;
  618. get_schemeLength(&nCount);
  619. *ppThemeScheme = NULL;
  620. // This is sortof gross, but if we are passed a pointer to another variant, simply
  621. // update our copy here...
  622. if (varIndex.vt == (VT_BYREF | VT_VARIANT) && varIndex.pvarVal)
  623. varIndex = *(varIndex.pvarVal);
  624. switch (varIndex.vt)
  625. {
  626. case VT_I2:
  627. varIndex.lVal = (long)varIndex.iVal;
  628. // And fall through...
  629. case VT_I4:
  630. if ((varIndex.lVal >= 0) && (varIndex.lVal < nCount))
  631. {
  632. if (0 == varIndex.lVal)
  633. {
  634. // 0 is the Appearance scheme, which means there isn't a skin.
  635. // This is the same as the legacy Appeanance tab.
  636. hr = CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, ppThemeScheme));
  637. }
  638. else
  639. {
  640. if (m_hdpaSkinDirs)
  641. {
  642. LPWSTR pszFilename = (LPWSTR) DPA_GetPtr(m_hdpaSkinDirs, varIndex.lVal-1);
  643. if (pszFilename)
  644. {
  645. hr = CSkinScheme_CreateInstance(pszFilename, ppThemeScheme);
  646. }
  647. else
  648. {
  649. hr = E_FAIL;
  650. }
  651. }
  652. else
  653. {
  654. AssertMsg(0, TEXT("This should have been initiailized by get_schemeLength(). -BryanSt"));
  655. hr = E_FAIL;
  656. }
  657. }
  658. }
  659. break;
  660. case VT_BSTR:
  661. if (varIndex.bstrVal && varIndex.bstrVal[0] &&
  662. !StrCmpI(PathFindExtension(varIndex.bstrVal), TEXT(".msstyles")))
  663. {
  664. hr = CSkinScheme_CreateInstance(varIndex.bstrVal, ppThemeScheme);
  665. }
  666. else
  667. {
  668. hr = CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, ppThemeScheme));
  669. }
  670. break;
  671. default:
  672. hr = E_NOTIMPL;
  673. }
  674. }
  675. }
  676. return hr;
  677. }
  678. HRESULT CThemeManager::GetSelectedSchemeProperty(IN BSTR bstrName, OUT BSTR * pbstrValue)
  679. {
  680. HRESULT hr = E_INVALIDARG;
  681. if (bstrName && pbstrValue)
  682. {
  683. *pbstrValue = NULL;
  684. if (IsSafeHost(&hr))
  685. {
  686. TCHAR szPath[MAX_PATH];
  687. TCHAR szColor[MAX_PATH];
  688. TCHAR szSize[MAX_PATH];
  689. BOOL fIsThemeActive = IsThemeActive();
  690. LogStatus("IsThemeActive() returned %hs in CThemeManager::GetSelectedSchemeProperty.\r\n", (fIsThemeActive ? "TRUE" : "FALSE"));
  691. szPath[0] = 0;
  692. szColor[0] = 0;
  693. szSize[0] = 0;
  694. if (fIsThemeActive)
  695. {
  696. hr = GetCurrentThemeName(szPath, ARRAYSIZE(szPath), szColor, ARRAYSIZE(szColor),
  697. szSize, ARRAYSIZE(szSize));
  698. LogStatus("GetCurrentThemeName() returned %#08lx in CThemeManager::GetSelectedSchemeProperty.\r\n", hr);
  699. }
  700. if (SUCCEEDED(hr))
  701. {
  702. if (!StrCmpI(bstrName, SZ_CSP_PATH))
  703. {
  704. PathRemoveFileSpec(szPath);
  705. hr = HrSysAllocString(szPath, pbstrValue);
  706. }
  707. else if (!StrCmpI(bstrName, SZ_CSP_FILE))
  708. {
  709. hr = HrSysAllocString(szPath, pbstrValue);
  710. }
  711. else if (!StrCmpI(bstrName, SZ_CSP_DISPLAYNAME))
  712. {
  713. if (szPath[0])
  714. {
  715. hr = GetThemeDocumentationProperty(szPath, SZ_THDOCPROP_DISPLAYNAME, szPath, ARRAYSIZE(szPath));
  716. LogStatus("GetThemeDocumentationProperty() returned %#08lx in CThemeManager::GetSelectedSchemeProperty.\r\n", hr);
  717. }
  718. if (SUCCEEDED(hr))
  719. {
  720. hr = HrSysAllocString(szPath, pbstrValue);
  721. }
  722. }
  723. else if (!StrCmpI(bstrName, SZ_CSP_CANONICALNAME))
  724. {
  725. if (szPath[0])
  726. {
  727. hr = GetThemeDocumentationProperty(szPath, SZ_THDOCPROP_CANONICALNAME, szPath, ARRAYSIZE(szPath));
  728. LogStatus("GetThemeDocumentationProperty() returned %#08lx in CThemeManager::GetSelectedSchemeProperty.\r\n", hr);
  729. }
  730. if (SUCCEEDED(hr))
  731. {
  732. hr = HrSysAllocString(szPath, pbstrValue);
  733. }
  734. }
  735. else if (!StrCmpI(bstrName, SZ_CSP_COLOR))
  736. {
  737. hr = HrSysAllocString(szColor, pbstrValue);
  738. }
  739. else if (!StrCmpI(bstrName, SZ_CSP_SIZE))
  740. {
  741. hr = HrSysAllocString(szSize, pbstrValue);
  742. }
  743. }
  744. }
  745. }
  746. return hr;
  747. }
  748. HRESULT CThemeManager::GetSpecialTheme(IN BSTR bstrName, OUT ITheme ** ppTheme)
  749. {
  750. HRESULT hr = E_INVALIDARG;
  751. if (bstrName && ppTheme)
  752. {
  753. *ppTheme = NULL;
  754. if (IsSafeHost(&hr))
  755. {
  756. if (!StrCmpI(SZ_STDEFAULTTHEME, bstrName))
  757. {
  758. TCHAR szPath[MAX_PATH];
  759. hr = HrRegGetPath(HKEY_CURRENT_USER, SZ_THEMES, SZ_REGVALUE_INSTALL_THEME, szPath, ARRAYSIZE(szPath));
  760. if (SUCCEEDED(hr))
  761. {
  762. ExpandResourceDir(szPath, ARRAYSIZE(szPath));
  763. hr = CThemeFile_CreateInstance(szPath, ppTheme);
  764. }
  765. }
  766. }
  767. }
  768. return hr;
  769. }
  770. HRESULT CThemeManager::SetSpecialTheme(IN BSTR bstrName, IN ITheme * pTheme)
  771. {
  772. HRESULT hr = E_INVALIDARG;
  773. if (bstrName)
  774. {
  775. if (IsSafeHost(&hr))
  776. {
  777. if (!StrCmpI(SZ_STDEFAULTTHEME, bstrName))
  778. {
  779. CComBSTR bstrPath;
  780. if (pTheme)
  781. {
  782. hr = pTheme->GetPath(VARIANT_TRUE, &bstrPath);
  783. }
  784. else
  785. {
  786. bstrPath = L""; // This means use "Windows Classic".
  787. }
  788. if (bstrPath)
  789. {
  790. hr = HrRegSetPath(HKEY_CURRENT_USER, SZ_THEMES, SZ_REGVALUE_INSTALL_THEME, TRUE, bstrPath);
  791. }
  792. }
  793. }
  794. }
  795. return hr;
  796. }
  797. HRESULT CThemeManager::GetSpecialScheme(IN BSTR bstrName, OUT IThemeScheme ** ppThemeScheme, OUT IThemeStyle ** ppThemeStyle, OUT IThemeSize ** ppThemeSize)
  798. {
  799. HRESULT hr = E_INVALIDARG;
  800. if (bstrName && ppThemeScheme && ppThemeStyle && ppThemeSize)
  801. {
  802. *ppThemeScheme = NULL;
  803. *ppThemeStyle = NULL;
  804. *ppThemeSize = NULL;
  805. TCHAR szVisualStylePath[MAX_PATH];
  806. DWORD dwType;
  807. DWORD cbSize = sizeof(szVisualStylePath);
  808. // Is a SetVisualStyle policy is set, don't honor this call
  809. if (ERROR_SUCCESS == SHRegGetUSValue(SZ_REGKEY_POLICIES_SYSTEM, SZ_REGVALUE_POLICY_SETVISUALSTYLE, &dwType, (void *) szVisualStylePath, &cbSize, FALSE, NULL, 0)
  810. || IsUserHighContrastUser())
  811. {
  812. hr = E_ACCESSDENIED; // Don't mess with visual styles when SetVisualStyle is enforced or high contrast is on
  813. }
  814. else if(IsSafeHost(&hr))
  815. {
  816. if (!StrCmpI(SZ_SSDEFAULVISUALSTYLEON, bstrName) ||
  817. !StrCmpI(SZ_SSDEFAULVISUALSTYLEOFF, bstrName))
  818. {
  819. TCHAR szRegKey[MAX_PATH];
  820. TCHAR szVisualStyle[MAX_PATH];
  821. wnsprintf(szRegKey, ARRAYSIZE(szRegKey), TEXT("%s\\%s"), SZ_THEMES, bstrName);
  822. hr = HrRegGetPath(HKEY_CURRENT_USER, szRegKey, SZ_REGVALUE_INSTALL_VISUALSTYLE, szVisualStyle, ARRAYSIZE(szVisualStyle));
  823. if (SUCCEEDED(hr))
  824. {
  825. TCHAR szColorStyle[MAX_PATH];
  826. ExpandResourceDir(szVisualStyle, ARRAYSIZE(szVisualStyle));
  827. hr = HrRegGetValueString(HKEY_CURRENT_USER, szRegKey, SZ_REGVALUE_INSTALL_VSCOLOR, szColorStyle, ARRAYSIZE(szColorStyle));
  828. if (SUCCEEDED(hr))
  829. {
  830. TCHAR szSize[MAX_PATH];
  831. hr = HrRegGetValueString(HKEY_CURRENT_USER, szRegKey, SZ_REGVALUE_INSTALL_VSSIZE, szSize, ARRAYSIZE(szSize));
  832. if (SUCCEEDED(hr))
  833. {
  834. CComVariant varIndex(szVisualStyle);
  835. hr = get_schemeItem(varIndex, ppThemeScheme);
  836. if (SUCCEEDED(hr))
  837. {
  838. CComVariant varColorIndex(szColorStyle);
  839. hr = (*ppThemeScheme)->get_item(varColorIndex, ppThemeStyle);
  840. if (SUCCEEDED(hr))
  841. {
  842. CComVariant varSizeIndex(szSize);
  843. hr = (*ppThemeStyle)->get_item(varSizeIndex, ppThemeSize);
  844. }
  845. }
  846. }
  847. }
  848. }
  849. if (FAILED(hr))
  850. {
  851. // Return consistent results.
  852. ATOMICRELEASE(*ppThemeScheme);
  853. ATOMICRELEASE(*ppThemeStyle);
  854. ATOMICRELEASE(*ppThemeSize);
  855. }
  856. }
  857. }
  858. }
  859. return hr;
  860. }
  861. HRESULT CThemeManager::SetSpecialScheme(IN BSTR bstrName, IN IThemeScheme * pThemeScheme, IThemeStyle * pThemeStyle, IThemeSize * pThemeSize)
  862. {
  863. HRESULT hr = E_NOTIMPL;
  864. if (IsSafeHost(&hr))
  865. {
  866. }
  867. return hr;
  868. }
  869. HRESULT CThemeManager::ApplyNow(void)
  870. {
  871. HRESULT hr = E_INVALIDARG;
  872. if (IsSafeHost(&hr))
  873. {
  874. hr = ApplyPressed(TUIAP_NONE | TUIAP_WAITFORAPPLY);
  875. }
  876. return hr;
  877. }