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
865 lines
24 KiB
/*****************************************************************************\
|
|
FILE: AdvDlg.cpp
|
|
|
|
DESCRIPTION:
|
|
This code will display the "Advanced Display Properties" dialog.
|
|
|
|
BryanSt 3/23/2000 Updated and Converted to C++
|
|
|
|
Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
|
|
\*****************************************************************************/
|
|
|
|
#include "priv.h"
|
|
#include "BaseAppearPg.h"
|
|
#include "ThemePg.h"
|
|
#include "EnumUnknown.h"
|
|
#include "AdvDlg.h"
|
|
#include "AdvAppearPg.h"
|
|
#include "ThSettingsPg.h"
|
|
#include "ScreenSaverPg.h"
|
|
#include "fontfix.h"
|
|
#include <themeid.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//===========================
|
|
// *** Class Internals & Helpers ***
|
|
//===========================
|
|
HRESULT CThemeManager::_Initialize(void)
|
|
{
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
|
|
CThemePage * pThemesPage = new CThemePage();
|
|
if (pThemesPage)
|
|
{
|
|
CBaseAppearancePage * pAppearancePage = new CBaseAppearancePage();
|
|
if (pAppearancePage)
|
|
{
|
|
hr = pThemesPage->QueryInterface(IID_PPV_ARG(IBasePropPage, &(m_pBasePages[PAGE_DISPLAY_THEMES])));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IUnknown_SetSite(m_pBasePages[PAGE_DISPLAY_THEMES], SAFECAST(this, IThemeUIPages *));
|
|
hr = pAppearancePage->QueryInterface(IID_PPV_ARG(IBasePropPage, &(m_pBasePages[PAGE_DISPLAY_APPEARANCE])));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IUnknown_SetSite(m_pBasePages[PAGE_DISPLAY_APPEARANCE], SAFECAST(this, IThemeUIPages *));
|
|
hr = CoCreateInstance(CLSID_SettingsPage, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IBasePropPage, &(m_pBasePages[PAGE_DISPLAY_SETTINGS])));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IUnknown_SetSite(m_pBasePages[PAGE_DISPLAY_SETTINGS], SAFECAST(this, IThemeUIPages *));
|
|
}
|
|
}
|
|
}
|
|
pAppearancePage->Release();
|
|
}
|
|
pThemesPage->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//===========================
|
|
// *** IThemeUIPages Interface ***
|
|
//===========================
|
|
HRESULT CThemeManager::AddPage(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam, IN long nPageID)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
IShellPropSheetExt * pspse = NULL;
|
|
|
|
RegisterPreviewSystemMetricClass(HINST_THISDLL);
|
|
if ((PAGE_DISPLAY_THEMES <= nPageID) && (PAGE_DISPLAY_SETTINGS >= nPageID))
|
|
{
|
|
if (m_pBasePages[nPageID])
|
|
{
|
|
hr = m_pBasePages[nPageID]->QueryInterface(IID_PPV_ARG(IShellPropSheetExt, &pspse));
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pspse->AddPages(pfnAddPage, lParam);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// We give the page a pointer back to use so they can call
|
|
// IThemeUIPages::DisplayAdvancedDialog() in order to display
|
|
// the Advanced Dlg.
|
|
hr = IUnknown_SetSite(pspse, (IThemeUIPages *)this);
|
|
}
|
|
}
|
|
|
|
ATOMICRELEASE(pspse);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::AddBasePage(IN IBasePropPage * pBasePage)
|
|
{
|
|
int nIndex;
|
|
|
|
for (nIndex = (PAGE_DISPLAY_APPEARANCE + 1); nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
|
|
{
|
|
if (NULL == m_pBasePages[nIndex]) // Did we find an empty spot?
|
|
{
|
|
// Yes, so look no longer.
|
|
IUnknown_Set((IUnknown **)&(m_pBasePages[nIndex]), (IUnknown *)pBasePage);
|
|
if (m_pBasePages[nIndex])
|
|
{
|
|
// We give the page a pointer back to use so they can call
|
|
// IThemeUIPages::DisplayAdvancedDialog() in order to display
|
|
// the Advanced Dlg.
|
|
IUnknown_SetSite(m_pBasePages[nIndex], (IThemeUIPages *)this);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::ApplyPressed(IN DWORD dwFlags)
|
|
{
|
|
// We need to set the base pages' site pointers to NULL
|
|
// in order to break the ref-count cycle.
|
|
if (m_pBasePages[PAGE_DISPLAY_SETTINGS])
|
|
{
|
|
m_pBasePages[PAGE_DISPLAY_SETTINGS]->OnApply(PPOAACTION_APPLY);
|
|
}
|
|
|
|
for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
|
|
{
|
|
if ((nIndex != PAGE_DISPLAY_SETTINGS) && m_pBasePages[nIndex])
|
|
{
|
|
m_pBasePages[nIndex]->OnApply(PPOAACTION_APPLY);
|
|
}
|
|
}
|
|
|
|
if (TUIAP_WAITFORAPPLY & dwFlags)
|
|
{
|
|
m_fForceTimeout = TRUE;
|
|
}
|
|
|
|
// If nobody sent the message to the HWND to simulate an apply,
|
|
// do so now.
|
|
if (TUIAP_CLOSE_DIALOG & dwFlags)
|
|
{
|
|
HWND hwndBasePropDlg = GetParent(m_hwndParent);
|
|
|
|
PropSheet_PressButton(hwndBasePropDlg, PSBTN_OK);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::GetBasePagesEnum(OUT IEnumUnknown ** ppEnumUnknown)
|
|
{
|
|
return CEnumUnknown_CreateInstance(SAFECAST(this, IThemeUIPages *), (IUnknown **)m_pBasePages, ARRAYSIZE(m_pBasePages), 0, ppEnumUnknown);
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::UpdatePreview(IN DWORD dwFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_pPreview1) // It's okay if this is NULL because it will update when it's created.
|
|
{
|
|
hr = m_pPreview1->UpdatePreview(SAFECAST(this, IPropertyBag *));
|
|
}
|
|
|
|
if (m_pPreview2)
|
|
{
|
|
HRESULT hr2 = m_pPreview2->UpdatePreview(SAFECAST(this, IPropertyBag *));
|
|
|
|
if (FAILED(hr)) // return the best error
|
|
{
|
|
hr = hr2;
|
|
}
|
|
}
|
|
|
|
if (m_pPreview3)
|
|
{
|
|
HRESULT hr2 = m_pPreview3->UpdatePreview(SAFECAST(this, IPropertyBag *));
|
|
|
|
if (FAILED(hr)) // return the best error
|
|
{
|
|
hr = hr2;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::AddFakeSettingsPage(IN LPVOID pVoid)
|
|
{
|
|
if (pVoid)
|
|
{
|
|
::AddFakeSettingsPage(this, (PROPSHEETHEADER *)pVoid);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
HRESULT CThemeManager::SetExecMode(IN DWORD dwEM)
|
|
{
|
|
_dwEM = dwEM;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CThemeManager::GetExecMode(OUT DWORD* pdwEM)
|
|
{
|
|
if (pdwEM)
|
|
{
|
|
*pdwEM = _dwEM;
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
HRESULT CThemeManager::LoadMonitorBitmap(IN BOOL fFillDesktop, OUT HBITMAP* phbmMon)
|
|
{
|
|
if (phbmMon)
|
|
{
|
|
*phbmMon = ::LoadMonitorBitmap(fFillDesktop);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
HRESULT CThemeManager::DisplaySaveSettings(IN PVOID pContext, IN HWND hwnd, OUT int* piRet)
|
|
{
|
|
if (piRet)
|
|
{
|
|
*piRet = ::DisplaySaveSettings(pContext, hwnd);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
//===========================
|
|
// *** IPreviewSystemMetrics Interface ***
|
|
//===========================
|
|
HRESULT CThemeManager::RefreshColors(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// We should tell the base pages that they should reload the colors.
|
|
// They are welcome to ignore the event if they don't use the system
|
|
// colors.
|
|
for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
|
|
{
|
|
if (m_pBasePages[nIndex])
|
|
{
|
|
IPreviewSystemMetrics * ppsm;
|
|
|
|
hr = m_pBasePages[nIndex]->QueryInterface(IID_PPV_ARG(IPreviewSystemMetrics, &ppsm));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = ppsm->RefreshColors();
|
|
ppsm->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::UpdateDPIchange(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
LogStatus("DPI: CALLED asking to SCALE DPI");
|
|
|
|
// We should tell the base pages that they should reload the colors.
|
|
// They are welcome to ignore the event if they don't use the system
|
|
// colors.
|
|
for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
|
|
{
|
|
if (m_pBasePages[nIndex])
|
|
{
|
|
IPreviewSystemMetrics * ppsm;
|
|
|
|
hr = m_pBasePages[nIndex]->QueryInterface(IID_PPV_ARG(IPreviewSystemMetrics, &ppsm));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = ppsm->UpdateDPIchange();
|
|
ppsm->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::UpdateCharsetChanges(void)
|
|
{
|
|
// CHARSET: In Win2k, fontfix.cpp was used as a hack to change the CHARSET from one language to another.
|
|
// That doesn't work for many reasons: a) not called on roaming, b) not called for OS lang changes,
|
|
// c) won't fix the problem for strings with multiple languages, d) etc.
|
|
// Therefore, the SHELL team (BryanSt) had the NTUSER team (MSadek) agree to use DEFAULT_CHARSET all the time.
|
|
// If some app has bad logic testing the charset parameter, then the NTUSER team will shim that app to fix it.
|
|
// The shim would be really simple, on the return from a SystemParametersInfo(SPI_GETNONCLIENTMETRICS or ICONFONTS)
|
|
// just patch the lfCharSet param to the current charset.
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::DeskSetCurrentScheme(IN LPCWSTR pwzSchemeName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// We should tell the base pages that they should reload the colors.
|
|
// They are welcome to ignore the event if they don't use the system
|
|
// colors.
|
|
for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
|
|
{
|
|
if (m_pBasePages[nIndex])
|
|
{
|
|
IPreviewSystemMetrics * ppsm;
|
|
|
|
hr = m_pBasePages[nIndex]->QueryInterface(IID_PPV_ARG(IPreviewSystemMetrics, &ppsm));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = ppsm->DeskSetCurrentScheme(pwzSchemeName);
|
|
ppsm->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT CThemeManager::_GetPropertyBagByCLSID(IN const GUID * pClsid, IN IPropertyBag ** ppPropertyBag)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pClsid && ppPropertyBag)
|
|
{
|
|
IEnumUnknown * pEnumUnknown;
|
|
|
|
hr = GetBasePagesEnum(&pEnumUnknown);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IUnknown * punk;
|
|
|
|
hr = IEnumUnknown_FindCLSID(pEnumUnknown, *pClsid, &punk);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = punk->QueryInterface(IID_PPV_ARG(IPropertyBag, ppPropertyBag));
|
|
punk->Release();
|
|
}
|
|
|
|
pEnumUnknown->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::_SaveCustomValues(void)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (m_pBasePages[0])
|
|
{
|
|
TCHAR szDisplayName[MAX_PATH];
|
|
|
|
hr = GetCurrentUserCustomName(szDisplayName, ARRAYSIZE(szDisplayName));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IPropertyBag * pPropertyBag = NULL;
|
|
|
|
hr = QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, TRUE))
|
|
{
|
|
ITheme * pTheme;
|
|
|
|
if (PathAppend(szPath, TEXT("Microsoft\\Windows\\Themes\\Custom.theme")))
|
|
{
|
|
hr = SnapShotLiveSettingsToTheme(pPropertyBag, szPath, &pTheme);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrDisplayName(szDisplayName);
|
|
|
|
hr = pTheme->put_DisplayName(bstrDisplayName);
|
|
pTheme->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
pPropertyBag->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================
|
|
// *** IObjectWithSite Interface ***
|
|
//===========================
|
|
HRESULT CThemeManager::SetSite(IN IUnknown *punkSite)
|
|
{
|
|
if (!punkSite)
|
|
{
|
|
// This is a hint from up the chain that we are shutting down.
|
|
// We need to use this cue to release my children objects so
|
|
// they release me and we don't all leak.
|
|
for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
|
|
{
|
|
if (m_pBasePages[nIndex])
|
|
{
|
|
IUnknown_SetSite(m_pBasePages[nIndex], NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
return CObjectWithSite::SetSite(punkSite);
|
|
}
|
|
|
|
|
|
//===========================
|
|
// *** IPropertyBag Interface ***
|
|
//===========================
|
|
#define SZ_PROPERTY_ICONHEADER L"CLSID\\{"
|
|
|
|
HRESULT CThemeManager::Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
// We don't contain any settings our self, but we need to reflect down into our pages to get
|
|
// the correct settings.
|
|
if (pszPropName && pVar)
|
|
{
|
|
IPropertyBag * pPropertyBag = NULL;
|
|
|
|
if (!StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUND_PATH) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUNDSRC_PATH) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUND_TILE) ||
|
|
!StrCmpNIW(pszPropName, SZ_PROPERTY_ICONHEADER, ARRAYSIZE(SZ_PROPERTY_ICONHEADER) - 1))
|
|
{
|
|
hr = _GetPropertyBagByCLSID(&PPID_Background, &pPropertyBag);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pPropertyBag->Read(pszPropName, pVar, pErrorLog);
|
|
}
|
|
}
|
|
else if (!StrCmpIW(pszPropName, SZ_PBPROP_SCREENSAVER_PATH))
|
|
{
|
|
hr = _GetPropertyBagByCLSID(&PPID_ScreenSaver, &pPropertyBag);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pPropertyBag->Read(pszPropName, pVar, pErrorLog);
|
|
}
|
|
}
|
|
else if (!StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_PATH) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_COLOR) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_SIZE) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_SYSTEM_METRICS) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUND_COLOR) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_DPI_MODIFIED_VALUE) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_DPI_APPLIED_VALUE))
|
|
{
|
|
hr = _GetPropertyBagByCLSID(&PPID_BaseAppearance, &pPropertyBag);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pPropertyBag->Read(pszPropName, pVar, pErrorLog);
|
|
}
|
|
}
|
|
else if (!StrCmpNIW(pszPropName, SZ_PBPROP_THEME_FILTER, SIZE_THEME_FILTER_STR))
|
|
{
|
|
hr = _GetPropertyBagByCLSID(&PPID_Theme, &pPropertyBag);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pPropertyBag->Read(pszPropName, pVar, pErrorLog);
|
|
}
|
|
}
|
|
|
|
ATOMICRELEASE(pPropertyBag);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pszPropName)
|
|
{
|
|
if (pVar)
|
|
{
|
|
if ((VT_UNKNOWN == pVar->vt))
|
|
{
|
|
if (!StrCmpW(pszPropName, SZ_PBPROP_PREVIEW1))
|
|
{
|
|
IUnknown_Set((IUnknown **)&m_pPreview1, pVar->punkVal);
|
|
hr = S_OK;
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_PREVIEW2))
|
|
{
|
|
IUnknown_Set((IUnknown **)&m_pPreview2, pVar->punkVal);
|
|
hr = S_OK;
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_PREVIEW3))
|
|
{
|
|
IUnknown_Set((IUnknown **)&m_pPreview3, pVar->punkVal);
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else if (!StrCmpIW(pszPropName, SZ_PBPROP_CUSTOMIZE_THEME) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_THEME_LAUNCHTHEME))
|
|
{
|
|
IPropertyBag * pPropertyBag = NULL;
|
|
|
|
hr = _GetPropertyBagByCLSID(&PPID_Theme, &pPropertyBag);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pPropertyBag->Write(pszPropName, pVar);
|
|
pPropertyBag->Release();
|
|
}
|
|
}
|
|
else if (!StrCmpIW(pszPropName, SZ_PBPROP_APPEARANCE_LAUNCHMSTHEME) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_PATH) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_COLOR) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_VISUALSTYLE_SIZE) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_DPI_MODIFIED_VALUE) ||
|
|
!StrCmpIW(pszPropName, SZ_PBPROP_DPI_APPLIED_VALUE))
|
|
{
|
|
IPropertyBag * pPropertyBag = NULL;
|
|
|
|
hr = _GetPropertyBagByCLSID(&PPID_BaseAppearance, &pPropertyBag);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pPropertyBag->Write(pszPropName, pVar);
|
|
pPropertyBag->Release();
|
|
}
|
|
}
|
|
else if (!StrCmpIW(pszPropName, SZ_PBPROP_BACKGROUND_COLOR))
|
|
{
|
|
IPropertyBag * pPropertyBag = NULL;
|
|
|
|
hr = _GetPropertyBagByCLSID(&PPID_BaseAppearance, &pPropertyBag);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pPropertyBag->Write(pszPropName, pVar);
|
|
pPropertyBag->Release();
|
|
}
|
|
}
|
|
else if (!StrCmpIW(pszPropName, SZ_PBPROP_THEME_SETSELECTION) &&
|
|
(VT_BSTR == pVar->vt))
|
|
{
|
|
hr = _SetSelectedThemeEntree(pVar->bstrVal);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!StrCmpW(pszPropName, SZ_PBPROP_PREOPEN))
|
|
{
|
|
hr = _SaveCustomValues();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//===========================
|
|
// *** IUnknown Interface ***
|
|
//===========================
|
|
ULONG CThemeManager::AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
|
|
ULONG CThemeManager::Release()
|
|
{
|
|
ASSERT( 0 != m_cRef );
|
|
ULONG cRef = InterlockedDecrement(&m_cRef);
|
|
if ( 0 == cRef )
|
|
{
|
|
delete this;
|
|
}
|
|
return cRef;
|
|
}
|
|
|
|
|
|
HRESULT CThemeManager::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
static const QITAB qit[] = {
|
|
QITABENT(CThemeManager, IObjectWithSite),
|
|
QITABENT(CThemeManager, IThemeUIPages),
|
|
QITABENT(CThemeManager, IPropertyBag),
|
|
QITABENT(CThemeManager, IPreviewSystemMetrics),
|
|
QITABENT(CThemeManager, IThemeManager),
|
|
QITABENT(CThemeManager, IDispatch),
|
|
{ 0 },
|
|
};
|
|
|
|
return QISearch(this, qit, riid, ppvObj);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CThemeManager::GetIDsOfNames(REFIID riid, OLECHAR **rgszNames,UINT cNames, LCID lcid, DISPID * rgdispid)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ((cNames > 0) && (0 == StrCmpIW(*rgszNames, L"GetSelectedSchemeProperty")))
|
|
{
|
|
hr = CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
|
|
}
|
|
else
|
|
{
|
|
hr = E_ACCESSDENIED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CThemeManager::Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,UINT * puArgErr)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (dispidMember == DISPIDTHTM_GETSELSCHPROPERTY)
|
|
{
|
|
hr = CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
|
|
}
|
|
else
|
|
{
|
|
hr = E_ACCESSDENIED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================
|
|
// *** Class Methods ***
|
|
//===========================
|
|
CThemeManager::CThemeManager() : CImpIDispatch(LIBID_Theme, 1, 0, IID_IThemeManager), m_cRef(1)
|
|
{
|
|
DllAddRef();
|
|
|
|
_dwEM = EM_NORMAL;
|
|
// This needs to be allocated in Zero Inited Memory.
|
|
// Assert that all Member Variables are inited to Zero.
|
|
ASSERT(!m_pBasePages[0]);
|
|
ASSERT(!m_pPreview1);
|
|
ASSERT(!m_pPreview2);
|
|
ASSERT(!m_pPreview3);
|
|
ASSERT(!m_hdpaThemeDirs);
|
|
ASSERT(!m_hdpaSkinDirs);
|
|
ASSERT(!_pThemeSchemeSelected);
|
|
ASSERT(!m_fForceTimeout);
|
|
ASSERT(!m_cSpiThreads);
|
|
|
|
SPISetThreadCounter(&m_cSpiThreads);
|
|
|
|
_InitComCtl32();
|
|
}
|
|
|
|
|
|
int CALLBACK DPALocalFree_Callback(LPVOID p, LPVOID pData)
|
|
{
|
|
LocalFree(p); // NULLs will be ignored.
|
|
return 1;
|
|
}
|
|
|
|
|
|
CThemeManager::~CThemeManager()
|
|
{
|
|
for (int nIndex = 0; nIndex < ARRAYSIZE(m_pBasePages); nIndex++)
|
|
{
|
|
if (m_pBasePages[nIndex])
|
|
{
|
|
IUnknown_SetSite(m_pBasePages[nIndex], NULL);
|
|
}
|
|
|
|
ATOMICRELEASE(m_pBasePages[nIndex]);
|
|
}
|
|
|
|
if (m_hdpaThemeDirs)
|
|
{
|
|
DPA_DestroyCallback(m_hdpaThemeDirs, DPALocalFree_Callback, NULL);
|
|
}
|
|
|
|
if (m_hdpaSkinDirs)
|
|
{
|
|
DPA_DestroyCallback(m_hdpaSkinDirs, DPALocalFree_Callback, NULL);
|
|
}
|
|
|
|
Str_SetPtr(&_pszSelectTheme, NULL);
|
|
|
|
ATOMICRELEASE(_pThemeSchemeSelected);
|
|
ATOMICRELEASE(m_pPreview1);
|
|
ATOMICRELEASE(m_pPreview2);
|
|
ATOMICRELEASE(m_pPreview3);
|
|
|
|
if (m_fForceTimeout)
|
|
{
|
|
LONG lWait = 30 * 1000;
|
|
LONG lEnd = (LONG) GetTickCount() + lWait;
|
|
// this will wait until all SPICreateThreads() have returned
|
|
while (m_cSpiThreads && lWait > 0)
|
|
{
|
|
DWORD dwReturn = MsgWaitForMultipleObjects(0, NULL, FALSE, lWait, QS_ALLINPUT);
|
|
if (dwReturn == -1 || dwReturn == WAIT_TIMEOUT)
|
|
break;
|
|
|
|
MSG msg;
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
lWait = lEnd - GetTickCount();
|
|
}
|
|
}
|
|
SPISetThreadCounter(NULL);
|
|
DllRelease();
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
DESCRIPTION:
|
|
When the object is created this way, it's used privately by the Display
|
|
Control Panel. The CLSID is private so we don't need to worry about external
|
|
components using it this way.
|
|
\*****************************************************************************/
|
|
HRESULT CThemeUIPages_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj)
|
|
{
|
|
if (punkOuter)
|
|
{
|
|
return CLASS_E_NOAGGREGATION;
|
|
}
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (ppvObj)
|
|
{
|
|
CThemeManager * pObject = new CThemeManager();
|
|
|
|
*ppvObj = NULL;
|
|
if (pObject)
|
|
{
|
|
hr = pObject->_Initialize();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pObject->QueryInterface(riid, ppvObj);
|
|
}
|
|
else
|
|
{
|
|
IUnknown_SetSite(SAFECAST(pObject, IThemeManager *), NULL);
|
|
|
|
// HACK: The display CPL is opening so see if the language changed
|
|
// and the fonts need to be "fixed".
|
|
FixFontsOnLanguageChange();
|
|
}
|
|
|
|
pObject->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
DESCRIPTION:
|
|
External components can create the ThemeManager object this way. In this
|
|
case we need to add the pages ourselves.
|
|
\*****************************************************************************/
|
|
HRESULT CThemeManager_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj)
|
|
{
|
|
IThemeUIPages * pThemeUIPages;
|
|
HRESULT hr = CThemeUIPages_CreateInstance(NULL, IID_PPV_ARG(IThemeUIPages, &pThemeUIPages));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IBasePropPage * pBasePage;
|
|
|
|
hr = CoCreateInstance(CLSID_CDeskHtmlProp, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IBasePropPage, &pBasePage));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pThemeUIPages->AddBasePage(pBasePage);
|
|
pBasePage->Release();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = CScreenSaverPage_CreateInstance(NULL, IID_PPV_ARG(IBasePropPage, &pBasePage));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pThemeUIPages->AddBasePage(pBasePage);
|
|
pBasePage->Release();
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pThemeUIPages->QueryInterface(riid, ppvObj);
|
|
}
|
|
else
|
|
{
|
|
IUnknown_SetSite(pThemeUIPages, NULL);
|
|
}
|
|
|
|
pThemeUIPages->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|