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.

321 lines
9.4 KiB

  1. /*****************************************************************************\
  2. FILE: EffectsBasePg.cpp
  3. DESCRIPTION:
  4. This code will be the base object that won't add any pages to the base
  5. "Display Properties" dialog. However, it will request a "Effects" page be
  6. added to the Advanced.
  7. BryanSt 4/13/2000 Updated and Converted to C++
  8. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  9. \*****************************************************************************/
  10. #include "precomp.hxx"
  11. #include "shlwapip.h"
  12. #include "shlguidp.h"
  13. #pragma hdrstop
  14. #include "EffectsBasePg.h"
  15. #include "EffectsAdvPg.h"
  16. #include <cfgmgr32.h> // For MAX_GUID_STRING_LEN
  17. //============================================================================================================
  18. // *** Globals ***
  19. //============================================================================================================
  20. //===========================
  21. // *** Class Internals & Helpers ***
  22. //===========================
  23. HRESULT HrSysAllocString(IN const OLECHAR * pwzSource, OUT BSTR * pbstrDest)
  24. {
  25. HRESULT hr = S_OK;
  26. if (pbstrDest)
  27. {
  28. *pbstrDest = SysAllocString(pwzSource);
  29. if (pwzSource)
  30. {
  31. if (*pbstrDest)
  32. hr = S_OK;
  33. else
  34. hr = E_OUTOFMEMORY;
  35. }
  36. }
  37. return hr;
  38. }
  39. HRESULT CEffectsBasePage::_InitState(void)
  40. {
  41. HRESULT hr = S_OK;
  42. if (!m_pEffectsState)
  43. {
  44. m_pEffectsState = new CEffectState();
  45. if (m_pEffectsState)
  46. {
  47. m_pEffectsState->Load();
  48. }
  49. else
  50. {
  51. hr = E_OUTOFMEMORY;
  52. }
  53. }
  54. return hr;
  55. }
  56. HRESULT CEffectsBasePage::_SaveState(CEffectState * pEffectsState)
  57. {
  58. HRESULT hr = E_INVALIDARG;
  59. if (pEffectsState)
  60. {
  61. BOOL fHasIconsChanged = FALSE;
  62. if (m_pEffectsState)
  63. {
  64. fHasIconsChanged = pEffectsState->HasIconsChanged(m_pEffectsState);
  65. delete m_pEffectsState;
  66. }
  67. m_pEffectsState = pEffectsState;
  68. hr = S_OK;
  69. // Only switch to "Custom" if the icons changed.
  70. if (_punkSite && fHasIconsChanged)
  71. {
  72. // We need to tell the Theme tab to customize the theme.
  73. IPropertyBag * pPropertyBag;
  74. hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  75. if (SUCCEEDED(hr))
  76. {
  77. // Tell the theme that we have customized the values.
  78. hr = SHPropertyBag_WriteInt(pPropertyBag, SZ_PBPROP_CUSTOMIZE_THEME, 0);
  79. pPropertyBag->Release();
  80. }
  81. }
  82. }
  83. return hr;
  84. }
  85. //===========================
  86. // *** IBasePropPage Interface ***
  87. //===========================
  88. #define SZ_ICONHEADER L"CLSID\\{"
  89. HRESULT CEffectsBasePage::Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog)
  90. {
  91. HRESULT hr = E_INVALIDARG;
  92. if (pszPropName && pVar)
  93. {
  94. // The caller can pass us the string in the following format:
  95. // pszPropName="CLSID\{<CLSID>}\DefaultIcon:<Item>" = "<FilePath>,<ResourceIndex>"
  96. // For example:
  97. // pszPropName="CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon:DefaultValue" = "%WinDir%SYSTEM\COOL.DLL,16"
  98. if (!StrCmpNIW(SZ_ICONHEADER, pszPropName, ARRAYSIZE(SZ_ICONHEADER) - 1) &&
  99. ((ARRAYSIZE(SZ_ICONHEADER) + 38) < lstrlenW(pszPropName)))
  100. {
  101. hr = _InitState();
  102. if (SUCCEEDED(hr))
  103. {
  104. CLSID clsid;
  105. WCHAR szTemp[MAX_PATH];
  106. // Get the CLSID
  107. StrCpyNW(szTemp, &(pszPropName[ARRAYSIZE(SZ_ICONHEADER) - 2]), MAX_GUID_STRING_LEN);
  108. hr = SHCLSIDFromString(szTemp, &clsid);
  109. if (SUCCEEDED(hr))
  110. {
  111. // Get the name of the icon type. Normally this is "DefaultIcon", but it can be several states, like
  112. // "full" and "empty" for the recycle bin.
  113. LPCWSTR pszToken = StrChrW((pszPropName + ARRAYSIZE(SZ_ICONHEADER)), L':');
  114. hr = E_FAIL;
  115. if (pszToken)
  116. {
  117. TCHAR szIconPath[MAX_PATH];
  118. pszToken++;
  119. hr = m_pEffectsState->GetIconPath(clsid, pszToken, szIconPath, ARRAYSIZE(szIconPath));
  120. if (SUCCEEDED(hr))
  121. {
  122. pVar->vt = VT_BSTR;
  123. hr = HrSysAllocString(szIconPath, &pVar->bstrVal);
  124. }
  125. }
  126. }
  127. }
  128. }
  129. else if (!StrCmpW(SZ_PBPROP_EFFECTSSTATE, pszPropName) && m_pEffectsState)
  130. {
  131. pVar->vt = VT_BYREF;
  132. pVar->byref = (void *)&m_pEffectsState;
  133. hr = S_OK;
  134. }
  135. }
  136. return hr;
  137. }
  138. HRESULT CEffectsBasePage::Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar)
  139. {
  140. HRESULT hr = E_INVALIDARG;
  141. if (pszPropName && pVar)
  142. {
  143. if (VT_BSTR == pVar->vt)
  144. {
  145. // The caller can pass us the string in the following format:
  146. // pszPropName="CLSID\{<CLSID>}\DefaultIcon:<Item>" = "<FilePath>,<ResourceIndex>"
  147. // For example:
  148. // pszPropName="CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon:DefaultValue" = "%WinDir%SYSTEM\COOL.DLL,16"
  149. if (!StrCmpNIW(SZ_ICONHEADER, pszPropName, ARRAYSIZE(SZ_ICONHEADER) - 1) &&
  150. ((ARRAYSIZE(SZ_ICONHEADER) + 38) < lstrlenW(pszPropName)))
  151. {
  152. hr = _InitState();
  153. if (SUCCEEDED(hr))
  154. {
  155. CLSID clsid;
  156. WCHAR szTemp[MAX_PATH];
  157. // Get the CLSID
  158. StrCpyNW(szTemp, &(pszPropName[ARRAYSIZE(SZ_ICONHEADER) - 2]), MAX_GUID_STRING_LEN);
  159. hr = SHCLSIDFromString(szTemp, &clsid);
  160. if (SUCCEEDED(hr))
  161. {
  162. // Get the name of the icon type. Normally this is "DefaultIcon", but it can be several states, like
  163. // "full" and "empty" for the recycle bin.
  164. LPCWSTR pszToken = StrChrW((pszPropName + ARRAYSIZE(SZ_ICONHEADER)), L':');
  165. hr = E_FAIL;
  166. if (pszToken)
  167. {
  168. pszToken++;
  169. StrCpyNW(szTemp, pszToken, ARRAYSIZE(szTemp));
  170. // Now the pVar->bstrVal is the icon path + "," + resourceID. Separate those two.
  171. WCHAR szPath[MAX_PATH];
  172. StrCpyNW(szPath, pVar->bstrVal, ARRAYSIZE(szPath));
  173. int nResourceID = PathParseIconLocationW(szPath);
  174. hr = m_pEffectsState->SetIconPath(clsid, szTemp, szPath, nResourceID);
  175. }
  176. }
  177. }
  178. }
  179. }
  180. else if (VT_BYREF == pVar->vt)
  181. {
  182. // The caller is passing us a (CEffectState *) object to save.
  183. if (!StrCmpW(SZ_PBPROP_EFFECTSSTATE, pszPropName))
  184. {
  185. hr = _SaveState((CEffectState *) pVar->byref);
  186. }
  187. }
  188. }
  189. return hr;
  190. }
  191. //===========================
  192. // *** IBasePropPage Interface ***
  193. //===========================
  194. HRESULT CEffectsBasePage::GetAdvancedDialog(OUT IAdvancedDialog ** ppAdvDialog)
  195. {
  196. HRESULT hr = E_INVALIDARG;
  197. if (ppAdvDialog)
  198. {
  199. *ppAdvDialog = NULL;
  200. hr = _InitState();
  201. if (SUCCEEDED(hr))
  202. {
  203. hr = CEffectsPage_CreateInstance(ppAdvDialog);
  204. }
  205. }
  206. return hr;
  207. }
  208. HRESULT CEffectsBasePage::OnApply(IN PROPPAGEONAPPLY oaAction)
  209. {
  210. HRESULT hr = S_OK;
  211. if ((PPOAACTION_CANCEL != oaAction) && m_pEffectsState)
  212. {
  213. hr = m_pEffectsState->Save();
  214. // Make sure we reload the state next time we open the dialog.
  215. delete m_pEffectsState;
  216. m_pEffectsState = NULL;
  217. }
  218. return hr;
  219. }
  220. //===========================
  221. // *** IShellPropSheetExt Interface ***
  222. //===========================
  223. HRESULT CEffectsBasePage::AddPages(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam)
  224. {
  225. // We don't want to add any pages to the base dialog since we moved the
  226. // "Effects" tab to the Advanced dlg.
  227. return S_OK;
  228. }
  229. //===========================
  230. // *** IUnknown Interface ***
  231. //===========================
  232. HRESULT CEffectsBasePage::QueryInterface(REFIID riid, void **ppvObj)
  233. {
  234. HRESULT hr = E_NOINTERFACE;
  235. static const QITAB qit[] =
  236. {
  237. QITABENT(CEffectsBasePage, IBasePropPage),
  238. QITABENT(CEffectsBasePage, IPropertyBag),
  239. QITABENT(CEffectsBasePage, IPersist),
  240. QITABENT(CEffectsBasePage, IObjectWithSite),
  241. QITABENTMULTI(CEffectsBasePage, IShellPropSheetExt, IBasePropPage),
  242. { 0 },
  243. };
  244. return QISearch(this, qit, riid, ppvObj);
  245. }
  246. //===========================
  247. // *** Class Methods ***
  248. //===========================
  249. CEffectsBasePage::CEffectsBasePage(IUnknown * punkOuter, LPFNDESTROYED pfnDestroy) : CPropSheetExt(punkOuter, pfnDestroy), CObjectCLSID(&PPID_Effects)
  250. {
  251. // This needs to be allocated in Zero Inited Memory.
  252. // Assert that all Member Variables are inited to Zero.
  253. m_fDirty = FALSE;
  254. }
  255. CEffectsBasePage::~CEffectsBasePage()
  256. {
  257. }