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.

826 lines
23 KiB

  1. /*****************************************************************************\
  2. FILE: AdvDlg.cpp
  3. DESCRIPTION:
  4. This code will display the "Advanced Display Properties" dialog.
  5. BryanSt 3/23/2000 Updated and Converted to C++
  6. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  7. \*****************************************************************************/
  8. #include "priv.h"
  9. #include "BaseAppearPg.h"
  10. #include "ThemePg.h"
  11. #include "EnumUnknown.h"
  12. #include "AdvDlg.h"
  13. #include "AdvAppearPg.h"
  14. #include "ThSettingsPg.h"
  15. #include "ScreenSaverPg.h"
  16. #include "fontfix.h"
  17. //===========================
  18. // *** Class Internals & Helpers ***
  19. //===========================
  20. HRESULT CThemeManager::_Initialize(void)
  21. {
  22. HRESULT hr = E_OUTOFMEMORY;
  23. CThemePage * pThemesPage = new CThemePage();
  24. if (pThemesPage)
  25. {
  26. CBaseAppearancePage * pAppearancePage = new CBaseAppearancePage();
  27. if (pAppearancePage)
  28. {
  29. hr = pThemesPage->QueryInterface(IID_PPV_ARG(IBasePropPage, &(m_pBasePages[PAGE_DISPLAY_THEMES])));
  30. if (SUCCEEDED(hr))
  31. {
  32. IUnknown_SetSite(m_pBasePages[PAGE_DISPLAY_THEMES], SAFECAST(this, IThemeUIPages *));
  33. hr = pAppearancePage->QueryInterface(IID_PPV_ARG(IBasePropPage, &(m_pBasePages[PAGE_DISPLAY_APPEARANCE])));
  34. if (SUCCEEDED(hr))
  35. {
  36. IUnknown_SetSite(m_pBasePages[PAGE_DISPLAY_APPEARANCE], SAFECAST(this, IThemeUIPages *));
  37. hr = CoCreateInstance(CLSID_SettingsPage, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IBasePropPage, &(m_pBasePages[PAGE_DISPLAY_SETTINGS])));
  38. if (SUCCEEDED(hr))
  39. {
  40. IUnknown_SetSite(m_pBasePages[PAGE_DISPLAY_SETTINGS], SAFECAST(this, IThemeUIPages *));
  41. }
  42. }
  43. }
  44. pAppearancePage->Release();
  45. }
  46. pThemesPage->Release();
  47. }
  48. return hr;
  49. }
  50. //===========================
  51. // *** IThemeUIPages Interface ***
  52. //===========================
  53. HRESULT CThemeManager::AddPage(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam, IN long nPageID)
  54. {
  55. HRESULT hr = E_INVALIDARG;
  56. IShellPropSheetExt * pspse = NULL;
  57. RegisterPreviewSystemMetricClass(HINST_THISDLL);
  58. if ((PAGE_DISPLAY_THEMES <= nPageID) && (PAGE_DISPLAY_SETTINGS >= nPageID))
  59. {
  60. if (m_pBasePages[nPageID])
  61. {
  62. hr = m_pBasePages[nPageID]->QueryInterface(IID_PPV_ARG(IShellPropSheetExt, &pspse));
  63. }
  64. }
  65. if (SUCCEEDED(hr))
  66. {
  67. hr = pspse->AddPages(pfnAddPage, lParam);
  68. if (SUCCEEDED(hr))
  69. {
  70. // We give the page a pointer back to use so they can call
  71. // IThemeUIPages::DisplayAdvancedDialog() in order to display
  72. // the Advanced Dlg.
  73. hr = IUnknown_SetSite(pspse, (IThemeUIPages *)this);
  74. }
  75. }
  76. ATOMICRELEASE(pspse);
  77. return hr;
  78. }
  79. HRESULT CThemeManager::AddBasePage(IN IBasePropPage * pBasePage)
  80. {
  81. int nIndex;
  82. for (nIndex = (PAGE_DISPLAY_APPEARANCE + 1); nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
  83. {
  84. if (NULL == m_pBasePages[nIndex]) // Did we find an empty spot?
  85. {
  86. // Yes, so look no longer.
  87. IUnknown_Set((IUnknown **)&(m_pBasePages[nIndex]), (IUnknown *)pBasePage);
  88. if (m_pBasePages[nIndex])
  89. {
  90. // We give the page a pointer back to use so they can call
  91. // IThemeUIPages::DisplayAdvancedDialog() in order to display
  92. // the Advanced Dlg.
  93. IUnknown_SetSite(m_pBasePages[nIndex], (IThemeUIPages *)this);
  94. }
  95. break;
  96. }
  97. }
  98. return S_OK;
  99. }
  100. HRESULT CThemeManager::ApplyPressed(IN DWORD dwFlags)
  101. {
  102. // We need to set the base pages' site pointers to NULL
  103. // in order to break the ref-count cycle.
  104. if (m_pBasePages[PAGE_DISPLAY_SETTINGS])
  105. {
  106. m_pBasePages[PAGE_DISPLAY_SETTINGS]->OnApply(PPOAACTION_APPLY);
  107. }
  108. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
  109. {
  110. if ((nIndex != PAGE_DISPLAY_SETTINGS) && m_pBasePages[nIndex])
  111. {
  112. m_pBasePages[nIndex]->OnApply(PPOAACTION_APPLY);
  113. }
  114. }
  115. if (TUIAP_WAITFORAPPLY & dwFlags)
  116. {
  117. m_fForceTimeout = TRUE;
  118. }
  119. // If nobody sent the message to the HWND to simulate an apply,
  120. // do so now.
  121. if (TUIAP_CLOSE_DIALOG & dwFlags)
  122. {
  123. HWND hwndBasePropDlg = GetParent(m_hwndParent);
  124. PropSheet_PressButton(hwndBasePropDlg, PSBTN_OK);
  125. }
  126. return S_OK;
  127. }
  128. HRESULT CThemeManager::GetBasePagesEnum(OUT IEnumUnknown ** ppEnumUnknown)
  129. {
  130. return CEnumUnknown_CreateInstance(SAFECAST(this, IThemeUIPages *), (IUnknown **)m_pBasePages, ARRAYSIZE(m_pBasePages), 0, ppEnumUnknown);
  131. }
  132. HRESULT CThemeManager::UpdatePreview(IN DWORD dwFlags)
  133. {
  134. HRESULT hr = S_OK;
  135. if (m_pPreview1) // It's okay if this is NULL because it will update when it's created.
  136. {
  137. hr = m_pPreview1->UpdatePreview(SAFECAST(this, IPropertyBag *));
  138. }
  139. if (m_pPreview2)
  140. {
  141. HRESULT hr2 = m_pPreview2->UpdatePreview(SAFECAST(this, IPropertyBag *));
  142. if (FAILED(hr)) // return the best error
  143. {
  144. hr = hr2;
  145. }
  146. }
  147. if (m_pPreview3)
  148. {
  149. HRESULT hr2 = m_pPreview3->UpdatePreview(SAFECAST(this, IPropertyBag *));
  150. if (FAILED(hr)) // return the best error
  151. {
  152. hr = hr2;
  153. }
  154. }
  155. return hr;
  156. }
  157. HRESULT CThemeManager::AddFakeSettingsPage(IN LPVOID pVoid)
  158. {
  159. if (pVoid)
  160. {
  161. ::AddFakeSettingsPage(this, (PROPSHEETHEADER *)pVoid);
  162. return S_OK;
  163. }
  164. else
  165. {
  166. return E_INVALIDARG;
  167. }
  168. }
  169. HRESULT CThemeManager::SetExecMode(IN DWORD dwEM)
  170. {
  171. _dwEM = dwEM;
  172. return S_OK;
  173. }
  174. HRESULT CThemeManager::GetExecMode(OUT DWORD* pdwEM)
  175. {
  176. if (pdwEM)
  177. {
  178. *pdwEM = _dwEM;
  179. return S_OK;
  180. }
  181. else
  182. {
  183. return E_INVALIDARG;
  184. }
  185. }
  186. HRESULT CThemeManager::LoadMonitorBitmap(IN BOOL fFillDesktop, OUT HBITMAP* phbmMon)
  187. {
  188. if (phbmMon)
  189. {
  190. *phbmMon = ::LoadMonitorBitmap(fFillDesktop);
  191. return S_OK;
  192. }
  193. else
  194. {
  195. return E_INVALIDARG;
  196. }
  197. }
  198. HRESULT CThemeManager::DisplaySaveSettings(IN PVOID pContext, IN HWND hwnd, OUT int* piRet)
  199. {
  200. if (piRet)
  201. {
  202. *piRet = ::DisplaySaveSettings(pContext, hwnd);
  203. return S_OK;
  204. }
  205. else
  206. {
  207. return E_INVALIDARG;
  208. }
  209. }
  210. //===========================
  211. // *** IPreviewSystemMetrics Interface ***
  212. //===========================
  213. HRESULT CThemeManager::RefreshColors(void)
  214. {
  215. HRESULT hr = S_OK;
  216. // We should tell the base pages that they should reload the colors.
  217. // They are welcome to ignore the event if they don't use the system
  218. // colors.
  219. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
  220. {
  221. if (m_pBasePages[nIndex])
  222. {
  223. IPreviewSystemMetrics * ppsm;
  224. hr = m_pBasePages[nIndex]->QueryInterface(IID_PPV_ARG(IPreviewSystemMetrics, &ppsm));
  225. if (SUCCEEDED(hr))
  226. {
  227. hr = ppsm->RefreshColors();
  228. ppsm->Release();
  229. }
  230. }
  231. }
  232. return S_OK;
  233. }
  234. HRESULT CThemeManager::UpdateDPIchange(void)
  235. {
  236. HRESULT hr = S_OK;
  237. LogStatus("DPI: CALLED asking to SCALE DPI");
  238. // We should tell the base pages that they should reload the colors.
  239. // They are welcome to ignore the event if they don't use the system
  240. // colors.
  241. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
  242. {
  243. if (m_pBasePages[nIndex])
  244. {
  245. IPreviewSystemMetrics * ppsm;
  246. hr = m_pBasePages[nIndex]->QueryInterface(IID_PPV_ARG(IPreviewSystemMetrics, &ppsm));
  247. if (SUCCEEDED(hr))
  248. {
  249. hr = ppsm->UpdateDPIchange();
  250. ppsm->Release();
  251. }
  252. }
  253. }
  254. return S_OK;
  255. }
  256. HRESULT CThemeManager::UpdateCharsetChanges(void)
  257. {
  258. // CHARSET: In Win2k, fontfix.cpp was used as a hack to change the CHARSET from one language to another.
  259. // That doesn't work for many reasons: a) not called on roaming, b) not called for OS lang changes,
  260. // c) won't fix the problem for strings with multiple languages, d) etc.
  261. // Therefore, the SHELL team (BryanSt) had the NTUSER team (MSadek) agree to use DEFAULT_CHARSET all the time.
  262. // If some app has bad logic testing the charset parameter, then the NTUSER team will shim that app to fix it.
  263. // The shim would be really simple, on the return from a SystemParametersInfo(SPI_GETNONCLIENTMETRICS or ICONFONTS)
  264. // just patch the lfCharSet param to the current charset.
  265. return S_OK;
  266. }
  267. HRESULT CThemeManager::DeskSetCurrentScheme(IN LPCWSTR pwzSchemeName)
  268. {
  269. HRESULT hr = S_OK;
  270. // We should tell the base pages that they should reload the colors.
  271. // They are welcome to ignore the event if they don't use the system
  272. // colors.
  273. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
  274. {
  275. if (m_pBasePages[nIndex])
  276. {
  277. IPreviewSystemMetrics * ppsm;
  278. hr = m_pBasePages[nIndex]->QueryInterface(IID_PPV_ARG(IPreviewSystemMetrics, &ppsm));
  279. if (SUCCEEDED(hr))
  280. {
  281. hr = ppsm->DeskSetCurrentScheme(pwzSchemeName);
  282. ppsm->Release();
  283. }
  284. }
  285. }
  286. return S_OK;
  287. }
  288. HRESULT CThemeManager::_GetPropertyBagByCLSID(IN const GUID * pClsid, IN IPropertyBag ** ppPropertyBag)
  289. {
  290. HRESULT hr = E_INVALIDARG;
  291. if (pClsid && ppPropertyBag)
  292. {
  293. IEnumUnknown * pEnumUnknown;
  294. hr = GetBasePagesEnum(&pEnumUnknown);
  295. if (SUCCEEDED(hr))
  296. {
  297. IUnknown * punk;
  298. hr = IEnumUnknown_FindCLSID(pEnumUnknown, *pClsid, &punk);
  299. if (SUCCEEDED(hr))
  300. {
  301. hr = punk->QueryInterface(IID_PPV_ARG(IPropertyBag, ppPropertyBag));
  302. punk->Release();
  303. }
  304. pEnumUnknown->Release();
  305. }
  306. }
  307. return hr;
  308. }
  309. HRESULT CThemeManager::_SaveCustomValues(void)
  310. {
  311. HRESULT hr = E_FAIL;
  312. if (m_pBasePages[0])
  313. {
  314. TCHAR szDisplayName[MAX_PATH];
  315. hr = GetCurrentUserCustomName(szDisplayName, ARRAYSIZE(szDisplayName));
  316. if (SUCCEEDED(hr))
  317. {
  318. IPropertyBag * pPropertyBag = NULL;
  319. hr = QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  320. if (SUCCEEDED(hr))
  321. {
  322. TCHAR szPath[MAX_PATH];
  323. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, TRUE))
  324. {
  325. ITheme * pTheme;
  326. PathAppend(szPath, TEXT("Microsoft\\Windows\\Themes\\Custom.theme"));
  327. hr = SnapShotLiveSettingsToTheme(pPropertyBag, szPath, &pTheme);
  328. if (SUCCEEDED(hr))
  329. {
  330. CComBSTR bstrDisplayName(szDisplayName);
  331. hr = pTheme->put_DisplayName(bstrDisplayName);
  332. pTheme->Release();
  333. }
  334. }
  335. pPropertyBag->Release();
  336. }
  337. }
  338. }
  339. return hr;
  340. }
  341. //===========================
  342. // *** IObjectWithSite Interface ***
  343. //===========================
  344. HRESULT CThemeManager::SetSite(IN IUnknown *punkSite)
  345. {
  346. if (!punkSite)
  347. {
  348. // This is a hint from up the chain that we are shutting down.
  349. // We need to use this cue to release my children objects so
  350. // they release me and we don't all leak.
  351. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
  352. {
  353. if (m_pBasePages[nIndex])
  354. {
  355. IUnknown_SetSite(m_pBasePages[nIndex], NULL);
  356. }
  357. }
  358. }
  359. return CObjectWithSite::SetSite(punkSite);
  360. }
  361. //===========================
  362. // *** IPropertyBag Interface ***
  363. //===========================
  364. #define SZ_PROPERTY_ICONHEADER L"CLSID\\{"
  365. HRESULT CThemeManager::Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog)
  366. {
  367. HRESULT hr = E_INVALIDARG;
  368. // We don't contain any settings our self, but we need to reflect down into our pages to get
  369. // the correct settings.
  370. if (pszPropName && pVar)
  371. {
  372. IPropertyBag * pPropertyBag = NULL;
  373. if (!StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUND_PATH) ||
  374. !StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUNDSRC_PATH) ||
  375. !StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUND_TILE) ||
  376. !StrCmpNIW(pszPropName, SZ_PROPERTY_ICONHEADER, ARRAYSIZE(SZ_PROPERTY_ICONHEADER) - 1))
  377. {
  378. hr = _GetPropertyBagByCLSID(&PPID_Background, &pPropertyBag);
  379. if (SUCCEEDED(hr))
  380. {
  381. hr = pPropertyBag->Read(pszPropName, pVar, pErrorLog);
  382. }
  383. }
  384. else if (!StrCmpIW(pszPropName, SZ_PBPROP_SCREENSAVER_PATH))
  385. {
  386. hr = _GetPropertyBagByCLSID(&PPID_ScreenSaver, &pPropertyBag);
  387. if (SUCCEEDED(hr))
  388. {
  389. hr = pPropertyBag->Read(pszPropName, pVar, pErrorLog);
  390. }
  391. }
  392. else if (!StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_PATH) ||
  393. !StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_COLOR) ||
  394. !StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_SIZE) ||
  395. !StrCmpIW(pszPropName, SZ_PBPROP_SYSTEM_METRICS) ||
  396. !StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUND_COLOR) ||
  397. !StrCmpIW(pszPropName, SZ_PBPROP_DPI_MODIFIED_VALUE) ||
  398. !StrCmpIW(pszPropName, SZ_PBPROP_DPI_APPLIED_VALUE))
  399. {
  400. hr = _GetPropertyBagByCLSID(&PPID_BaseAppearance, &pPropertyBag);
  401. if (SUCCEEDED(hr))
  402. {
  403. hr = pPropertyBag->Read(pszPropName, pVar, pErrorLog);
  404. }
  405. }
  406. else if (!StrCmpNIW(pszPropName, SZ_PBPROP_THEME_FILTER, SIZE_THEME_FILTER_STR))
  407. {
  408. hr = _GetPropertyBagByCLSID(&PPID_Theme, &pPropertyBag);
  409. if (SUCCEEDED(hr))
  410. {
  411. hr = pPropertyBag->Read(pszPropName, pVar, pErrorLog);
  412. }
  413. }
  414. ATOMICRELEASE(pPropertyBag);
  415. }
  416. return hr;
  417. }
  418. HRESULT CThemeManager::Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar)
  419. {
  420. HRESULT hr = E_INVALIDARG;
  421. if (pszPropName)
  422. {
  423. if (pVar)
  424. {
  425. if ((VT_UNKNOWN == pVar->vt))
  426. {
  427. if (!StrCmpW(pszPropName, SZ_PBPROP_PREVIEW1))
  428. {
  429. IUnknown_Set((IUnknown **)&m_pPreview1, pVar->punkVal);
  430. hr = S_OK;
  431. }
  432. else if (!StrCmpW(pszPropName, SZ_PBPROP_PREVIEW2))
  433. {
  434. IUnknown_Set((IUnknown **)&m_pPreview2, pVar->punkVal);
  435. hr = S_OK;
  436. }
  437. else if (!StrCmpW(pszPropName, SZ_PBPROP_PREVIEW3))
  438. {
  439. IUnknown_Set((IUnknown **)&m_pPreview3, pVar->punkVal);
  440. hr = S_OK;
  441. }
  442. }
  443. else if (!StrCmpIW(pszPropName, SZ_PBPROP_CUSTOMIZE_THEME) ||
  444. !StrCmpIW(pszPropName, SZ_PBPROP_THEME_LAUNCHTHEME))
  445. {
  446. IPropertyBag * pPropertyBag = NULL;
  447. hr = _GetPropertyBagByCLSID(&PPID_Theme, &pPropertyBag);
  448. if (SUCCEEDED(hr))
  449. {
  450. hr = pPropertyBag->Write(pszPropName, pVar);
  451. pPropertyBag->Release();
  452. }
  453. }
  454. else if (!StrCmpIW(pszPropName, SZ_PBPROP_APPEARANCE_LAUNCHMSTHEME) ||
  455. !StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_PATH) ||
  456. !StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_COLOR) ||
  457. !StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_SIZE) ||
  458. !StrCmpIW(pszPropName, SZ_PBPROP_DPI_MODIFIED_VALUE) ||
  459. !StrCmpIW(pszPropName, SZ_PBPROP_DPI_APPLIED_VALUE))
  460. {
  461. IPropertyBag * pPropertyBag = NULL;
  462. hr = _GetPropertyBagByCLSID(&PPID_BaseAppearance, &pPropertyBag);
  463. if (SUCCEEDED(hr))
  464. {
  465. hr = pPropertyBag->Write(pszPropName, pVar);
  466. pPropertyBag->Release();
  467. }
  468. }
  469. else if (!StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUND_COLOR))
  470. {
  471. IPropertyBag * pPropertyBag = NULL;
  472. hr = _GetPropertyBagByCLSID(&PPID_BaseAppearance, &pPropertyBag);
  473. if (SUCCEEDED(hr))
  474. {
  475. hr = pPropertyBag->Write(pszPropName, pVar);
  476. pPropertyBag->Release();
  477. }
  478. }
  479. else if (!StrCmpIW(pszPropName, SZ_PBPROP_THEME_SETSELECTION) &&
  480. (VT_BSTR == pVar->vt))
  481. {
  482. hr = _SetSelectedThemeEntree(pVar->bstrVal);
  483. }
  484. }
  485. else
  486. {
  487. if (!StrCmpW(pszPropName, SZ_PBPROP_PREOPEN))
  488. {
  489. hr = _SaveCustomValues();
  490. }
  491. }
  492. }
  493. return hr;
  494. }
  495. //===========================
  496. // *** IUnknown Interface ***
  497. //===========================
  498. ULONG CThemeManager::AddRef()
  499. {
  500. return InterlockedIncrement(&m_cRef);
  501. }
  502. ULONG CThemeManager::Release()
  503. {
  504. if (InterlockedDecrement(&m_cRef))
  505. return m_cRef;
  506. delete this;
  507. return 0;
  508. }
  509. HRESULT CThemeManager::QueryInterface(REFIID riid, void **ppvObj)
  510. {
  511. static const QITAB qit[] = {
  512. QITABENT(CThemeManager, IObjectWithSite),
  513. QITABENT(CThemeManager, IThemeUIPages),
  514. QITABENT(CThemeManager, IPropertyBag),
  515. QITABENT(CThemeManager, IPreviewSystemMetrics),
  516. QITABENT(CThemeManager, IThemeManager),
  517. QITABENT(CThemeManager, IObjectSafety),
  518. QITABENT(CThemeManager, IDispatch),
  519. { 0 },
  520. };
  521. return QISearch(this, qit, riid, ppvObj);
  522. }
  523. //===========================
  524. // *** Class Methods ***
  525. //===========================
  526. CThemeManager::CThemeManager() : CImpIDispatch(LIBID_Theme, 1, 0, IID_IThemeManager), m_cRef(1)
  527. {
  528. DllAddRef();
  529. _dwEM = EM_NORMAL;
  530. // This needs to be allocated in Zero Inited Memory.
  531. // Assert that all Member Variables are inited to Zero.
  532. ASSERT(!m_pBasePages[0]);
  533. ASSERT(!m_pPreview1);
  534. ASSERT(!m_pPreview2);
  535. ASSERT(!m_pPreview3);
  536. ASSERT(!m_hdpaThemeDirs);
  537. ASSERT(!m_hdpaSkinDirs);
  538. ASSERT(!_pThemeSchemeSelected);
  539. ASSERT(!m_fForceTimeout);
  540. ASSERT(!m_cSpiThreads);
  541. SPISetThreadCounter(&m_cSpiThreads);
  542. _InitComCtl32();
  543. }
  544. int CALLBACK DPALocalFree_Callback(LPVOID p, LPVOID pData)
  545. {
  546. LocalFree(p); // NULLs will be ignored.
  547. return 1;
  548. }
  549. CThemeManager::~CThemeManager()
  550. {
  551. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
  552. {
  553. if (m_pBasePages[nIndex])
  554. {
  555. IUnknown_SetSite(m_pBasePages[nIndex], NULL);
  556. }
  557. ATOMICRELEASE(m_pBasePages[nIndex]);
  558. }
  559. if (m_hdpaThemeDirs)
  560. {
  561. DPA_DestroyCallback(m_hdpaThemeDirs, DPALocalFree_Callback, NULL);
  562. }
  563. if (m_hdpaSkinDirs)
  564. {
  565. DPA_DestroyCallback(m_hdpaSkinDirs, DPALocalFree_Callback, NULL);
  566. }
  567. Str_SetPtr(&_pszSelectTheme, NULL);
  568. ATOMICRELEASE(_pThemeSchemeSelected);
  569. ATOMICRELEASE(m_pPreview1);
  570. ATOMICRELEASE(m_pPreview2);
  571. ATOMICRELEASE(m_pPreview3);
  572. if (m_fForceTimeout)
  573. {
  574. LONG lWait = 30 * 1000;
  575. LONG lEnd = (LONG) GetTickCount() + lWait;
  576. // this will wait until all SPICreateThreads() have returned
  577. while (m_cSpiThreads && lWait > 0)
  578. {
  579. DWORD dwReturn = MsgWaitForMultipleObjects(0, NULL, FALSE, lWait, QS_ALLINPUT);
  580. if (dwReturn == -1 || dwReturn == WAIT_TIMEOUT)
  581. break;
  582. MSG msg;
  583. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  584. {
  585. TranslateMessage(&msg);
  586. DispatchMessage(&msg);
  587. }
  588. lWait = lEnd - GetTickCount();
  589. }
  590. }
  591. SPISetThreadCounter(NULL);
  592. DllRelease();
  593. }
  594. /*****************************************************************************\
  595. DESCRIPTION:
  596. When the object is created this way, it's used privately by the Display
  597. Control Panel. The CLSID is private so we don't need to worry about external
  598. components using it this way.
  599. \*****************************************************************************/
  600. HRESULT CThemeUIPages_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj)
  601. {
  602. if (punkOuter)
  603. {
  604. return CLASS_E_NOAGGREGATION;
  605. }
  606. HRESULT hr = E_INVALIDARG;
  607. if (ppvObj)
  608. {
  609. CThemeManager * pObject = new CThemeManager();
  610. *ppvObj = NULL;
  611. if (pObject)
  612. {
  613. hr = pObject->_Initialize();
  614. if (SUCCEEDED(hr))
  615. {
  616. hr = pObject->QueryInterface(riid, ppvObj);
  617. }
  618. else
  619. {
  620. IUnknown_SetSite(SAFECAST(pObject, IThemeManager *), NULL);
  621. // HACK: The display CPL is opening so see if the language changed
  622. // and the fonts need to be "fixed".
  623. FixFontsOnLanguageChange();
  624. }
  625. pObject->Release();
  626. }
  627. else
  628. {
  629. hr = E_OUTOFMEMORY;
  630. }
  631. }
  632. return hr;
  633. }
  634. /*****************************************************************************\
  635. DESCRIPTION:
  636. External components can create the ThemeManager object this way. In this
  637. case we need to add the pages ourselves.
  638. \*****************************************************************************/
  639. HRESULT CThemeManager_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj)
  640. {
  641. IThemeUIPages * pThemeUIPages;
  642. HRESULT hr = CThemeUIPages_CreateInstance(NULL, IID_PPV_ARG(IThemeUIPages, &pThemeUIPages));
  643. if (SUCCEEDED(hr))
  644. {
  645. IBasePropPage * pBasePage;
  646. hr = CoCreateInstance(CLSID_CDeskHtmlProp, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IBasePropPage, &pBasePage));
  647. if (SUCCEEDED(hr))
  648. {
  649. hr = pThemeUIPages->AddBasePage(pBasePage);
  650. pBasePage->Release();
  651. }
  652. if (SUCCEEDED(hr))
  653. {
  654. hr = CScreenSaverPage_CreateInstance(NULL, IID_PPV_ARG(IBasePropPage, &pBasePage));
  655. if (SUCCEEDED(hr))
  656. {
  657. hr = pThemeUIPages->AddBasePage(pBasePage);
  658. pBasePage->Release();
  659. }
  660. }
  661. if (SUCCEEDED(hr))
  662. {
  663. hr = pThemeUIPages->QueryInterface(riid, ppvObj);
  664. }
  665. else
  666. {
  667. IUnknown_SetSite(pThemeUIPages, NULL);
  668. }
  669. pThemeUIPages->Release();
  670. }
  671. return hr;
  672. }