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.

815 lines
26 KiB

  1. /*****************************************************************************\
  2. FILE: appScheme.cpp
  3. DESCRIPTION:
  4. This is the Autmation Object to theme scheme object.
  5. BryanSt 4/3/2000 (Bryan Starbuck)
  6. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  7. \*****************************************************************************/
  8. #include "priv.h"
  9. #include <cowsite.h>
  10. #include <atlbase.h>
  11. #include "util.h"
  12. #include "theme.h"
  13. #include "appstyle.h"
  14. #include "appscheme.h"
  15. //===========================
  16. // *** Class Internals & Helpers ***
  17. //===========================
  18. APPEARANCESCHEME_UPGRADE_MAPPINGS g_UpgradeMapping[MAX_LEGACY_UPGRADE_SCENARIOS] = {0};
  19. HRESULT LoadConversionMappings(void)
  20. {
  21. if (0 == g_UpgradeMapping[0].szLegacyName[0]) // Only set the settings if it's the first time.
  22. {
  23. // This is custom user created scheme.
  24. TCHAR szTempState[10];
  25. for (int nIndex = 0; nIndex < ARRAYSIZE(g_UpgradeMapping); nIndex++)
  26. {
  27. LoadString(HINST_THISDLL, IDS_LEGACYSCHEME_NAME + nIndex, g_UpgradeMapping[nIndex].szLegacyName, ARRAYSIZE(g_UpgradeMapping[nIndex].szLegacyName));
  28. LoadString(HINST_THISDLL, IDS_LOCALIZATIONPOINTER + nIndex, g_UpgradeMapping[nIndex].szNewColorSchemeName, ARRAYSIZE(g_UpgradeMapping[nIndex].szNewColorSchemeName));
  29. LoadString(HINST_THISDLL, IDS_NEWSIZE_NAME + nIndex, g_UpgradeMapping[nIndex].szNewSizeName, ARRAYSIZE(g_UpgradeMapping[nIndex].szNewSizeName));
  30. LoadString(HINST_THISDLL, IDS_NEWCONTRASTFLAGS + nIndex, szTempState, ARRAYSIZE(szTempState));
  31. g_UpgradeMapping[nIndex].ContrastLevel = (enumThemeContrastLevels) StrToInt(szTempState);
  32. }
  33. }
  34. return S_OK;
  35. }
  36. HRESULT MapLegacyAppearanceSchemeToIndex(LPCTSTR pszOldSchemeName, int * pnIndex)
  37. {
  38. HRESULT hr = E_FAIL; // Failure means, FALSE, we didn't convert.
  39. *pnIndex = 0;
  40. for (int nIndex = 0; nIndex < ARRAYSIZE(g_UpgradeMapping); nIndex++)
  41. {
  42. // Did we find that pszSchemeName is one of the legacy settings?
  43. if (!StrCmpI(pszOldSchemeName, g_UpgradeMapping[nIndex].szLegacyName))
  44. {
  45. hr = S_OK;
  46. *pnIndex = nIndex;
  47. break;
  48. }
  49. }
  50. return hr;
  51. }
  52. HRESULT CAppearanceScheme::_IsLegacyUpgradeConvert(LPCTSTR pszSchemeName, SYSTEMMETRICSALL * pState, IN BOOL fSetAsDefault)
  53. {
  54. int nIndex = 0;
  55. HRESULT hr = MapLegacyAppearanceSchemeToIndex(pszSchemeName, &nIndex);
  56. if (SUCCEEDED(hr))
  57. {
  58. hr = _ConvertScheme(pszSchemeName, g_UpgradeMapping[nIndex].szNewColorSchemeName, g_UpgradeMapping[nIndex].szNewSizeName, pState, g_UpgradeMapping[nIndex].ContrastLevel, fSetAsDefault, FALSE);
  59. }
  60. return hr;
  61. }
  62. HRESULT CAppearanceScheme::_CustomConvert(LPCTSTR pszSchemeName, SYSTEMMETRICSALL * pState, IN BOOL fSetAsDefault, IN BOOL fSetRegKeyTitle)
  63. {
  64. // This is custom user created scheme.
  65. TCHAR szSizeName[MAX_PATH];
  66. LoadString(HINST_THISDLL, IDS_SIZE_NORMAL, szSizeName, ARRAYSIZE(szSizeName));
  67. return _ConvertScheme(pszSchemeName, pszSchemeName, szSizeName, pState, CONTRAST_NORMAL, fSetAsDefault, fSetRegKeyTitle);
  68. }
  69. HRESULT CAppearanceScheme::_getSizeIndex(IN IThemeStyle * pThemeStyle, IN IThemeSize * pThemeSize, IN BSTR bstrSizeDisplayName, IN long * pnSizeIndex)
  70. {
  71. // This is horrible from a perf perspective, but we only do it once on upgrade.
  72. long nCount;
  73. HRESULT hr = E_FAIL;
  74. *pnSizeIndex = 0;
  75. if (SUCCEEDED(pThemeStyle->get_length(&nCount)))
  76. {
  77. IThemeSize * pThemeSize2;
  78. for (long nIndex = 0; nIndex < nCount; nIndex++)
  79. {
  80. VARIANT var;
  81. var.vt = VT_I4;
  82. var.lVal = nIndex;
  83. if (SUCCEEDED(pThemeStyle->get_item(var, &pThemeSize2)))
  84. {
  85. CComBSTR bstrSize2;
  86. if (SUCCEEDED(pThemeSize2->get_DisplayName(&bstrSize2)))
  87. {
  88. CComBSTR bstrName;
  89. if (!StrCmpIW(bstrSizeDisplayName, bstrSize2) ||
  90. (SUCCEEDED(pThemeSize2->get_Name(&bstrName)) &&
  91. !StrCmpIW(bstrSizeDisplayName, bstrName)))
  92. {
  93. hr = S_OK;
  94. *pnSizeIndex = nIndex;
  95. nIndex = nCount; // End looping now.
  96. }
  97. }
  98. pThemeSize2->Release();
  99. }
  100. }
  101. }
  102. return hr;
  103. }
  104. HRESULT CAppearanceScheme::_getIndex(IN IThemeStyle * pThemeStyle, IN BSTR bstrStyleDisplayName, IN long * pnStyleIndex, IN IThemeSize * pThemeSize, IN BSTR bstrSizeDisplayName, IN long * pnSizeIndex)
  105. {
  106. // This is horrible from a perf perspective, but we only do it once on upgrade.
  107. long nCount;
  108. HRESULT hr = E_FAIL;
  109. *pnStyleIndex = 0;
  110. *pnSizeIndex = 0;
  111. if (SUCCEEDED(get_length(&nCount)))
  112. {
  113. IThemeStyle * pThemeStyle2;
  114. for (long nIndex = 0; nIndex < nCount; nIndex++)
  115. {
  116. VARIANT var;
  117. var.vt = VT_I4;
  118. var.lVal = nIndex;
  119. if (SUCCEEDED(get_item(var, &pThemeStyle2)))
  120. {
  121. CComBSTR bstrStyle2;
  122. if (SUCCEEDED(pThemeStyle2->get_DisplayName(&bstrStyle2)))
  123. {
  124. CComBSTR bstrName;
  125. if (!StrCmpIW(bstrStyleDisplayName, bstrStyle2) ||
  126. (SUCCEEDED(pThemeStyle2->get_Name(&bstrName)) &&
  127. !StrCmpIW(bstrStyleDisplayName, bstrName)))
  128. {
  129. *pnStyleIndex = nIndex;
  130. hr = _getSizeIndex(pThemeStyle, pThemeSize, bstrSizeDisplayName, pnSizeIndex);
  131. nIndex = nCount; // End the search.
  132. }
  133. }
  134. pThemeStyle2->Release();
  135. }
  136. }
  137. }
  138. return hr;
  139. }
  140. HRESULT CAppearanceScheme::_ConvertScheme(LPCTSTR pszLegacyName, // This is the Legacy Name
  141. LPCTSTR pszStyleName, LPCTSTR pszSizeName, SYSTEMMETRICSALL * pState,
  142. IN enumThemeContrastLevels ContrastLevel, IN BOOL fSetAsDefault, IN BOOL fSetRegKeyTitle)
  143. {
  144. // This is custom user created scheme.
  145. IThemeStyle * pThemeStyle;
  146. CComVariant varDisplayNameBSTR(pszStyleName);
  147. HRESULT hr = get_item(varDisplayNameBSTR, &pThemeStyle);
  148. if (FAILED(hr))
  149. {
  150. // If it doesn't exist, create one.
  151. hr = _AddStyle((fSetRegKeyTitle ? pszStyleName : NULL), &pThemeStyle);
  152. }
  153. if (SUCCEEDED(hr))
  154. {
  155. CComBSTR bstrStyleDisplayName(pszStyleName);
  156. hr = pThemeStyle->put_DisplayName(bstrStyleDisplayName);
  157. if (SUCCEEDED(hr))
  158. {
  159. IThemeSize * pThemeSize;
  160. hr = pThemeStyle->AddSize(&pThemeSize);
  161. if (SUCCEEDED(hr))
  162. {
  163. CComBSTR bstrSizeDisplayName(pszSizeName);
  164. hr = pThemeSize->put_DisplayName(bstrSizeDisplayName);
  165. if (SUCCEEDED(hr))
  166. {
  167. hr = SystemMetricsAll_Save(pState, pThemeSize, FALSE);
  168. if (SUCCEEDED(hr))
  169. {
  170. // Set the contrast level.
  171. hr = pThemeSize->put_ContrastLevel(ContrastLevel);
  172. if (SUCCEEDED(hr))
  173. {
  174. IPropertyBag * pPropertyBag;
  175. hr = pThemeSize->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  176. if (SUCCEEDED(hr))
  177. {
  178. hr = SHPropertyBag_WriteStr(pPropertyBag, SZ_PBPROP_COLORSCHEME_LEGACYNAME, pszLegacyName);
  179. pPropertyBag->Release();
  180. }
  181. }
  182. }
  183. }
  184. if (fSetAsDefault && SUCCEEDED(hr))
  185. {
  186. long nStyleIndex;
  187. long nSizeIndex;
  188. hr = _getIndex(pThemeStyle, bstrStyleDisplayName, &nStyleIndex, pThemeSize, bstrSizeDisplayName, &nSizeIndex);
  189. if (SUCCEEDED(hr))
  190. {
  191. TCHAR szData[10];
  192. StringCchPrintf(szData, ARRAYSIZE(szData), TEXT("%d"), nStyleIndex);
  193. DWORD cbSize = ((lstrlen(szData) + 1) * sizeof(szData[0]));
  194. hr = HrSHSetValue(m_hKeyScheme, NULL, SZ_REGVALUE_SELECTEDSTYLE, REG_SZ, (LPVOID) szData, cbSize);
  195. if (SUCCEEDED(hr))
  196. {
  197. TCHAR szData2[10];
  198. StringCchPrintf(szData2, ARRAYSIZE(szData2), TEXT("%d"), nSizeIndex);
  199. DWORD cbSize = ((lstrlen(szData2) + 1) * sizeof(szData2[0]));
  200. hr = HrSHSetValue(m_hKeyScheme, szData, SZ_REGVALUE_SELECTEDSIZE, REG_SZ, (LPVOID) szData2, cbSize);
  201. }
  202. }
  203. }
  204. pThemeSize->Release();
  205. }
  206. }
  207. pThemeStyle->Release();
  208. }
  209. return hr;
  210. }
  211. HRESULT LoadCurrentStyle(LPTSTR pszCurrentStyle, int cchSize)
  212. {
  213. HKEY hkey;
  214. HRESULT hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_APPEARANCE, 0, KEY_READ, &hkey);
  215. if (SUCCEEDED(hr))
  216. {
  217. DWORD dwSize = (DWORD)(cchSize * sizeof(pszCurrentStyle[0]));
  218. hr = HrRegQueryValueEx(hkey, REGSTR_KEY_CURRENT, NULL, NULL, (LPBYTE)pszCurrentStyle, &dwSize);
  219. RegCloseKey(hkey);
  220. }
  221. return hr;
  222. }
  223. // This function will do nothing if an upgrade isn't needed.
  224. HRESULT CAppearanceScheme::_InitReg(void)
  225. {
  226. HRESULT hr = S_OK;
  227. if (!m_hKeyScheme)
  228. {
  229. hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, SZ_APPEARANCE_NEWSCHEMES, 0, (KEY_WRITE | KEY_READ), &m_hKeyScheme);
  230. if (FAILED(hr))
  231. {
  232. // Here is where we need to do the upgrade.
  233. hr = HrRegCreateKeyEx(HKEY_CURRENT_USER, SZ_APPEARANCE_NEWSCHEMES, 0, NULL, REG_OPTION_NON_VOLATILE,
  234. (KEY_WRITE | KEY_READ), NULL, &m_hKeyScheme, 0);
  235. if (SUCCEEDED(hr))
  236. {
  237. HKEY hKeyOld;
  238. hr = HrRegCreateKeyEx(HKEY_CURRENT_USER, SZ_APPEARANCE_SCHEMES, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKeyOld, 0);
  239. if (SUCCEEDED(hr))
  240. {
  241. TCHAR szCurrentStyle[MAX_PATH];
  242. TCHAR szSchemeName[MAX_PATH];
  243. TCHAR szDefaultScheme[MAX_PATH];
  244. DWORD dwIndex = 0;
  245. // Load in the upgrade mappings.
  246. hr = LoadConversionMappings();
  247. LoadString(HINST_THISDLL, IDS_DEFAULT_APPEARANCES_SCHEME, szDefaultScheme, ARRAYSIZE(szDefaultScheme));
  248. hr = LoadCurrentStyle(szCurrentStyle, ARRAYSIZE(szCurrentStyle));
  249. if (FAILED(hr))
  250. {
  251. // This will fail if the user never changed the legacy "Appearance Scheme".
  252. LoadString(HINST_THISDLL, IDS_DEFAULT_APPEARANCES_SCHEME, szCurrentStyle, ARRAYSIZE(szCurrentStyle));
  253. hr = S_OK;
  254. }
  255. // Now let's walk thru each one and convert it.
  256. while (SUCCEEDED(hr))
  257. {
  258. DWORD dwType;
  259. DWORD cchSize = ARRAYSIZE(szSchemeName);
  260. hr = HrRegEnumValue(hKeyOld, dwIndex, szSchemeName, &cchSize, NULL, &dwType, NULL, NULL);
  261. if (SUCCEEDED(hr) && (REG_BINARY == dwType))
  262. {
  263. BOOL fSetAsDefault = !StrCmpI(szCurrentStyle, szSchemeName);
  264. SYSTEMMETRICSALL state = {0};
  265. hr = Look_GetSchemeData(hKeyOld, szSchemeName, &state.schemeData);
  266. if (SUCCEEDED(hr))
  267. {
  268. state.schemeData.rgb[COLOR_MENUBAR] = state.schemeData.rgb[COLOR_MENU];
  269. state.schemeData.rgb[COLOR_MENUHILIGHT] = state.schemeData.rgb[COLOR_HIGHLIGHT];
  270. // See if this is one of the shipping Appearance Schemes, so we want to create it
  271. // special.
  272. hr = _IsLegacyUpgradeConvert(szSchemeName, &state, fSetAsDefault);
  273. if (FAILED(hr))
  274. {
  275. // No, so we will upgrade it as a custom item.
  276. hr = _CustomConvert(szSchemeName, &state, fSetAsDefault, FALSE);
  277. }
  278. // On Upgrade, we need to copy "Windows Standard" to "Current Settings SaveNoVisualStyle".
  279. // That way, when the user toggles from "Professional VS" to "Windows Classic VS", we
  280. // load those colors as the first alternative to visual styles off. Win #151831
  281. if (!StrCmpI(szDefaultScheme, szSchemeName))
  282. {
  283. hr = _CustomConvert(SZ_SAVEGROUP_NOSKIN_TITLE, &state, FALSE, TRUE);
  284. }
  285. }
  286. }
  287. dwIndex++;
  288. }
  289. hr = S_OK;
  290. RegCloseKey(hKeyOld);
  291. }
  292. }
  293. }
  294. }
  295. return hr;
  296. }
  297. HRESULT CAppearanceScheme::_getStyleByIndex(IN long nIndex, OUT IThemeStyle ** ppThemeStyle)
  298. {
  299. HRESULT hr = _InitReg();
  300. if (SUCCEEDED(hr))
  301. {
  302. HKEY hKeyStyle;
  303. TCHAR szKeyName[MAXIMUM_SUB_KEY_LENGTH];
  304. StringCchPrintf(szKeyName, ARRAYSIZE(szKeyName), TEXT("%d"), nIndex);
  305. hr = HrRegOpenKeyEx(m_hKeyScheme, szKeyName, 0, (KEY_WRITE | KEY_READ), &hKeyStyle);
  306. if (SUCCEEDED(hr))
  307. {
  308. hr = CAppearanceStyle_CreateInstance(hKeyStyle, ppThemeStyle); // This function takes ownership of hKey
  309. if (FAILED(hr))
  310. {
  311. RegCloseKey(hKeyStyle);
  312. }
  313. }
  314. }
  315. return hr;
  316. }
  317. HRESULT CAppearanceScheme::_getCurrentSettings(IN LPCWSTR pszSettings, OUT IThemeStyle ** ppThemeStyle)
  318. {
  319. HRESULT hr = _InitReg();
  320. if (SUCCEEDED(hr))
  321. {
  322. WCHAR szRegValue[MAXIMUM_VALUE_NAME_LENGTH];
  323. HKEY hKeyStyle;
  324. StringCchCopy(szRegValue, ARRAYSIZE(szRegValue), SZ_REGVALUE_CURRENT_SETTINGS);
  325. StringCchCat(szRegValue, ARRAYSIZE(szRegValue), &pszSettings[2]);
  326. hr = HrRegCreateKeyEx(m_hKeyScheme, szRegValue, 0, NULL, REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL, &hKeyStyle, NULL);
  327. if (SUCCEEDED(hr))
  328. {
  329. hr = CAppearanceStyle_CreateInstance(hKeyStyle, ppThemeStyle); // This function takes ownership of hKey
  330. if (FAILED(hr))
  331. {
  332. RegCloseKey(hKeyStyle);
  333. }
  334. }
  335. }
  336. return hr;
  337. }
  338. //===========================
  339. // *** ITheme Interface ***
  340. //===========================
  341. HRESULT CAppearanceScheme::get_DisplayName(OUT BSTR * pbstrDisplayName)
  342. {
  343. WCHAR szDisplayName[MAX_PATH];
  344. LoadString(HINST_THISDLL, IDS_NO_SKIN_DISPLAYNAME, szDisplayName, ARRAYSIZE(szDisplayName));
  345. return HrSysAllocStringW(szDisplayName, pbstrDisplayName);
  346. }
  347. HRESULT CAppearanceScheme::get_length(OUT long * pnLength)
  348. {
  349. HRESULT hr = E_INVALIDARG;
  350. if (pnLength)
  351. {
  352. *pnLength = 0;
  353. hr = _InitReg();
  354. if (SUCCEEDED(hr))
  355. {
  356. DWORD dwValues = 0;
  357. hr = HrRegQueryInfoKey(m_hKeyScheme, NULL, NULL, NULL, &dwValues, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  358. if (SUCCEEDED(hr))
  359. {
  360. HKEY hKeyTemp;
  361. if (SUCCEEDED(HrRegOpenKeyEx(m_hKeyScheme, SZ_REGVALUE_CURRENT_SETTINGS, 0, KEY_READ, &hKeyTemp)))
  362. {
  363. dwValues--; // We want to subtract one for the "Current Settings" key.
  364. RegCloseKey(hKeyTemp);
  365. }
  366. }
  367. *pnLength = (long) dwValues;
  368. }
  369. }
  370. return hr;
  371. }
  372. HRESULT CAppearanceScheme::get_item(IN VARIANT varIndex, OUT IThemeStyle ** ppThemeStyle)
  373. {
  374. HRESULT hr = E_INVALIDARG;
  375. if (ppThemeStyle)
  376. {
  377. long nCount = 0;
  378. get_length(&nCount);
  379. *ppThemeStyle = NULL;
  380. // This is sortof gross, but if we are passed a pointer to another variant, simply
  381. // update our copy here...
  382. if (varIndex.vt == (VT_BYREF | VT_VARIANT) && varIndex.pvarVal)
  383. varIndex = *(varIndex.pvarVal);
  384. switch (varIndex.vt)
  385. {
  386. case VT_I2:
  387. varIndex.lVal = (long)varIndex.iVal;
  388. // And fall through...
  389. case VT_I4:
  390. if ((varIndex.lVal >= 0) && (varIndex.lVal < nCount))
  391. {
  392. hr = _getStyleByIndex(varIndex.lVal, ppThemeStyle);
  393. }
  394. break;
  395. case VT_BSTR:
  396. if (varIndex.bstrVal)
  397. {
  398. if ((L':' == varIndex.bstrVal[0]) && (L':' == varIndex.bstrVal[1]))
  399. {
  400. // This is a "Custom" settings so look in that key.
  401. hr = _getCurrentSettings(varIndex.bstrVal, ppThemeStyle);
  402. }
  403. else
  404. {
  405. for (int nIndex = 0; FAILED(hr) && (nIndex < nCount); nIndex++)
  406. {
  407. IThemeStyle * pThemeStyle;
  408. if (SUCCEEDED(_getStyleByIndex(nIndex, &pThemeStyle)))
  409. {
  410. CComBSTR bstrDisplayName;
  411. if (SUCCEEDED(pThemeStyle->get_DisplayName(&bstrDisplayName)))
  412. {
  413. if (!StrCmpIW(bstrDisplayName, varIndex.bstrVal))
  414. {
  415. // They match, so this is the one.
  416. *ppThemeStyle = pThemeStyle;
  417. pThemeStyle = NULL;
  418. hr = S_OK;
  419. }
  420. }
  421. if (FAILED(hr))
  422. {
  423. if (bstrDisplayName)
  424. {
  425. bstrDisplayName.Empty();
  426. }
  427. if (SUCCEEDED(pThemeStyle->get_Name(&bstrDisplayName)))
  428. {
  429. if (!StrCmpIW(bstrDisplayName, varIndex.bstrVal))
  430. {
  431. // They match, so this is the one.
  432. *ppThemeStyle = pThemeStyle;
  433. pThemeStyle = NULL;
  434. hr = S_OK;
  435. }
  436. }
  437. }
  438. ATOMICRELEASE(pThemeStyle);
  439. }
  440. }
  441. }
  442. }
  443. break;
  444. default:
  445. hr = E_NOTIMPL;
  446. }
  447. }
  448. return hr;
  449. }
  450. HRESULT CAppearanceScheme::get_SelectedStyle(OUT IThemeStyle ** ppThemeStyle)
  451. {
  452. HRESULT hr = E_INVALIDARG;
  453. if (ppThemeStyle)
  454. {
  455. hr = _InitReg();
  456. if (SUCCEEDED(hr))
  457. {
  458. TCHAR szKeyName[MAXIMUM_SUB_KEY_LENGTH];
  459. DWORD cbSize = sizeof(szKeyName);
  460. *ppThemeStyle = NULL;
  461. hr = HrSHGetValue(m_hKeyScheme, NULL, SZ_REGVALUE_SELECTEDSTYLE, NULL, szKeyName, &cbSize);
  462. if (FAILED(hr))
  463. {
  464. // "21" is the Appearance Scheme of "Windows Classic".
  465. StringCchCopy(szKeyName, ARRAYSIZE(szKeyName), TEXT("21"));
  466. hr = S_OK;
  467. }
  468. if (SUCCEEDED(hr))
  469. {
  470. HKEY hKeyStyle;
  471. // Let's find the next empty slot
  472. hr = HrRegOpenKeyEx(m_hKeyScheme, szKeyName, 0, (KEY_WRITE | KEY_READ), &hKeyStyle);
  473. if (SUCCEEDED(hr))
  474. {
  475. hr = CAppearanceStyle_CreateInstance(hKeyStyle, ppThemeStyle); // This function takes ownership of hKeyStyle
  476. if (FAILED(hr))
  477. {
  478. RegCloseKey(hKeyStyle);
  479. }
  480. }
  481. }
  482. }
  483. }
  484. return hr;
  485. }
  486. HRESULT CAppearanceScheme::put_SelectedStyle(IN IThemeStyle * pThemeStyle)
  487. {
  488. HRESULT hr = E_INVALIDARG;
  489. if (pThemeStyle)
  490. {
  491. hr = _InitReg();
  492. if (SUCCEEDED(hr))
  493. {
  494. TCHAR szKeyName[MAXIMUM_SUB_KEY_LENGTH];
  495. CComBSTR bstrDisplayNameSource;
  496. hr = pThemeStyle->get_DisplayName(&bstrDisplayNameSource);
  497. if (SUCCEEDED(hr))
  498. {
  499. for (int nIndex = 0; SUCCEEDED(hr); nIndex++)
  500. {
  501. IThemeStyle * pThemeStyleInList;
  502. hr = _getStyleByIndex(nIndex, &pThemeStyleInList);
  503. if (SUCCEEDED(hr))
  504. {
  505. CComBSTR bstrDisplayName;
  506. hr = pThemeStyleInList->get_DisplayName(&bstrDisplayName);
  507. ATOMICRELEASE(pThemeStyleInList);
  508. if (SUCCEEDED(hr))
  509. {
  510. if (!StrCmpIW(bstrDisplayName, bstrDisplayNameSource))
  511. {
  512. // They match, so this is the one.
  513. StringCchPrintf(szKeyName, ARRAYSIZE(szKeyName), TEXT("%d"), nIndex);
  514. break;
  515. }
  516. }
  517. }
  518. }
  519. }
  520. if (SUCCEEDED(hr))
  521. {
  522. DWORD cbSize = ((lstrlen(szKeyName) + 1) * sizeof(szKeyName[0]));
  523. hr = HrSHSetValue(m_hKeyScheme, NULL, SZ_REGVALUE_SELECTEDSTYLE, REG_SZ, szKeyName, cbSize);
  524. }
  525. }
  526. }
  527. return hr;
  528. }
  529. HRESULT CAppearanceScheme::_AddStyle(IN LPCWSTR pszTitle, OUT IThemeStyle ** ppThemeStyle)
  530. {
  531. HRESULT hr = E_INVALIDARG;
  532. if (ppThemeStyle)
  533. {
  534. *ppThemeStyle = NULL;
  535. hr = _InitReg();
  536. if (SUCCEEDED(hr))
  537. {
  538. if (pszTitle)
  539. {
  540. HKEY hKeyStyle;
  541. hr = HrRegCreateKeyEx(m_hKeyScheme, pszTitle, 0, NULL, REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL, &hKeyStyle, NULL);
  542. if (SUCCEEDED(hr))
  543. {
  544. hr = CAppearanceStyle_CreateInstance(hKeyStyle, ppThemeStyle); // This function takes ownership of hKey
  545. if (FAILED(hr))
  546. {
  547. RegCloseKey(hKeyStyle);
  548. }
  549. }
  550. }
  551. else
  552. {
  553. // Find an empty Scheme Name.
  554. for (int nIndex = 0; nIndex < 10000; nIndex++)
  555. {
  556. HKEY hKeyStyle;
  557. TCHAR szKeyName[MAXIMUM_SUB_KEY_LENGTH];
  558. StringCchPrintf(szKeyName, ARRAYSIZE(szKeyName), TEXT("%d"), nIndex);
  559. // Let's find the next empty spot
  560. hr = HrRegOpenKeyEx(m_hKeyScheme, szKeyName, 0, KEY_READ, &hKeyStyle);
  561. if (SUCCEEDED(hr))
  562. {
  563. RegCloseKey(hKeyStyle);
  564. }
  565. else
  566. {
  567. hr = HrRegCreateKeyEx(m_hKeyScheme, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL, &hKeyStyle, NULL);
  568. if (SUCCEEDED(hr))
  569. {
  570. hr = CAppearanceStyle_CreateInstance(hKeyStyle, ppThemeStyle); // This function takes ownership of hKey
  571. if (FAILED(hr))
  572. {
  573. RegCloseKey(hKeyStyle);
  574. }
  575. }
  576. break;
  577. }
  578. }
  579. }
  580. }
  581. }
  582. return hr;
  583. }
  584. //===========================
  585. // *** IUnknown Interface ***
  586. //===========================
  587. ULONG CAppearanceScheme::AddRef()
  588. {
  589. return InterlockedIncrement(&m_cRef);
  590. }
  591. ULONG CAppearanceScheme::Release()
  592. {
  593. ASSERT( 0 != m_cRef );
  594. ULONG cRef = InterlockedDecrement(&m_cRef);
  595. if ( 0 == cRef )
  596. {
  597. delete this;
  598. }
  599. return cRef;
  600. }
  601. //===========================
  602. // *** Class Methods ***
  603. //===========================
  604. HRESULT CAppearanceScheme::QueryInterface(REFIID riid, void **ppvObj)
  605. {
  606. static const QITAB qit[] = {
  607. QITABENT(CAppearanceScheme, IPersist),
  608. QITABENT(CAppearanceScheme, IThemeScheme),
  609. QITABENT(CAppearanceScheme, IDispatch),
  610. { 0 },
  611. };
  612. return QISearch(this, qit, riid, ppvObj);
  613. }
  614. CAppearanceScheme::CAppearanceScheme(void) : CObjectCLSID(&CLSID_LegacyAppearanceScheme), m_cRef(1)
  615. {
  616. DllAddRef();
  617. // This needs to be allocated in Zero Inited Memory.
  618. // Assert that all Member Variables are inited to Zero.
  619. ASSERT(!m_hKeyScheme);
  620. }
  621. CAppearanceScheme::~CAppearanceScheme()
  622. {
  623. if (m_hKeyScheme)
  624. {
  625. RegCloseKey(m_hKeyScheme);
  626. }
  627. DllRelease();
  628. }
  629. HRESULT CAppearanceScheme_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj)
  630. {
  631. HRESULT hr = E_INVALIDARG;
  632. if (punkOuter)
  633. {
  634. return CLASS_E_NOAGGREGATION;
  635. }
  636. if (ppvObj)
  637. {
  638. CAppearanceScheme * pObject = new CAppearanceScheme();
  639. *ppvObj = NULL;
  640. if (pObject)
  641. {
  642. hr = pObject->QueryInterface(riid, ppvObj);
  643. pObject->Release();
  644. }
  645. else
  646. {
  647. hr = E_OUTOFMEMORY;
  648. }
  649. }
  650. return hr;
  651. }