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.

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