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.

307 lines
8.2 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. class CPropertySetStg;
  4. class CPropertyStg : public IPropertyStorage
  5. {
  6. public:
  7. // IUnknown
  8. STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **ppv);
  9. STDMETHOD_(ULONG,AddRef) (THIS);
  10. STDMETHOD_(ULONG,Release) (THIS);
  11. // IPropertyStorage
  12. STDMETHODIMP ReadMultiple(ULONG cpspec, const PROPSPEC rgpspec[], PROPVARIANT rgpropvar[]);
  13. STDMETHODIMP WriteMultiple(ULONG cpspec, const PROPSPEC rgpspec[], const PROPVARIANT rgpropvar[], PROPID propidNameFirst);
  14. STDMETHODIMP DeleteMultiple(ULONG cpspec, const PROPSPEC rgpspec[]);
  15. STDMETHODIMP ReadPropertyNames(ULONG cpropid, const PROPID rgpropid[], LPOLESTR rglpwstrName[]);
  16. STDMETHODIMP WritePropertyNames(ULONG cpropid, const PROPID rgpropid[], const LPOLESTR rglpwstrName[]);
  17. STDMETHODIMP DeletePropertyNames(ULONG cpropid, const PROPID rgpropid[]);
  18. STDMETHODIMP Commit(DWORD grfCommitFlags);
  19. STDMETHODIMP Revert(void);
  20. STDMETHODIMP Enum(IEnumSTATPROPSTG **ppenum);
  21. STDMETHODIMP SetTimes(const FILETIME *pctime, const FILETIME *patime,const FILETIME *pmtime);
  22. STDMETHODIMP SetClass(REFCLSID clsid);
  23. STDMETHODIMP Stat(STATPROPSETSTG *pstatpsstg);
  24. CPropertyStg(CPropertySetStg *ppss, REFFMTID fmtid, DWORD grfMode);
  25. void FMTIDPIDToSectionProp(REFFMTID fmtid, PROPID pid, LPTSTR pszSection, LPTSTR pszValueName);
  26. private:
  27. ~CPropertyStg();
  28. BOOL _SectionValueName(const PROPSPEC *ppspec,
  29. LPTSTR pszSection, UINT cchSection, LPTSTR pszValueName, UINT cchValueName);
  30. HRESULT _ReadProp(const PROPSPEC *ppspec, PROPVARIANT *ppropvar);
  31. LONG _cRef;
  32. CPropertySetStg *_ppss; // back ptr to parent
  33. REFFMTID _fmtid;
  34. DWORD _grfMode;
  35. };
  36. class CPropertySetStg : public IPropertySetStorage
  37. {
  38. friend CPropertyStg;
  39. public:
  40. // IUnknown
  41. STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **ppv);
  42. STDMETHOD_(ULONG,AddRef) (THIS);
  43. STDMETHOD_(ULONG,Release) (THIS);
  44. // IPropertySetStorage
  45. STDMETHODIMP Create(REFFMTID fmtid, const CLSID * pclsid, DWORD grfFlags, DWORD grfMode, IPropertyStorage** ppPropStg);
  46. STDMETHODIMP Open(REFFMTID fmtid, DWORD grfMode, IPropertyStorage** ppPropStg);
  47. STDMETHODIMP Delete(REFFMTID fmtid);
  48. STDMETHODIMP Enum(IEnumSTATPROPSETSTG** ppenum);
  49. CPropertySetStg(LPCTSTR pszFolder, DWORD grfMode);
  50. LPCTSTR IniFile() { return _szIniFile; }
  51. private:
  52. ~CPropertySetStg();
  53. HRESULT _LoadPropHandler();
  54. LONG _cRef;
  55. DWORD _grfMode; // The mode that we opened the file in.
  56. TCHAR _szIniFile[MAX_PATH]; // desktop.ini path
  57. };
  58. CPropertySetStg::CPropertySetStg(LPCTSTR pszFolder, DWORD grfMode) : _cRef(1), _grfMode(grfMode)
  59. {
  60. PathCombine(_szIniFile, pszFolder, TEXT("desktop.ini"));
  61. }
  62. CPropertySetStg::~CPropertySetStg()
  63. {
  64. }
  65. STDMETHODIMP CPropertySetStg::QueryInterface(REFIID riid, void **ppv)
  66. {
  67. static const QITAB qit[] =
  68. {
  69. QITABENT(CPropertySetStg, IPropertySetStorage),
  70. { 0 },
  71. };
  72. return QISearch(this, qit, riid, ppv);
  73. }
  74. STDMETHODIMP_(ULONG) CPropertySetStg::AddRef()
  75. {
  76. return InterlockedIncrement(&_cRef);
  77. }
  78. STDMETHODIMP_(ULONG) CPropertySetStg::Release()
  79. {
  80. if (InterlockedDecrement(&_cRef))
  81. return _cRef;
  82. delete this;
  83. return 0;
  84. }
  85. HRESULT CPropertySetStg::_LoadPropHandler()
  86. {
  87. return E_NOTIMPL;
  88. }
  89. STDMETHODIMP CPropertySetStg::Create(REFFMTID fmtid, const CLSID *pclsid, DWORD grfFlags,
  90. DWORD grfMode, IPropertyStorage **pppropstg)
  91. {
  92. *pppropstg = NULL;
  93. return E_NOTIMPL;
  94. }
  95. STDMETHODIMP CPropertySetStg::Open(REFFMTID fmtid, DWORD grfMode, IPropertyStorage **pppropstg)
  96. {
  97. *pppropstg = new CPropertyStg(this, fmtid, grfMode);
  98. return *pppropstg ? S_OK : E_OUTOFMEMORY;
  99. }
  100. STDMETHODIMP CPropertySetStg::Delete(REFFMTID fmtid)
  101. {
  102. return STG_E_ACCESSDENIED;
  103. }
  104. STDMETHODIMP CPropertySetStg::Enum(IEnumSTATPROPSETSTG **ppenum)
  105. {
  106. *ppenum = NULL;
  107. return E_NOTIMPL;
  108. }
  109. CPropertyStg::CPropertyStg(CPropertySetStg *ppss, REFFMTID fmtid, DWORD grfMode) : _ppss(ppss), _fmtid(fmtid), _grfMode(grfMode)
  110. {
  111. _ppss->AddRef();
  112. }
  113. CPropertyStg::~CPropertyStg()
  114. {
  115. _ppss->Release();
  116. }
  117. STDMETHODIMP CPropertyStg::QueryInterface(REFIID riid, void **ppv)
  118. {
  119. static const QITAB qit[] =
  120. {
  121. QITABENT(CPropertyStg, IPropertyStorage),
  122. { 0 },
  123. };
  124. return QISearch(this, qit, riid, ppv);
  125. }
  126. STDMETHODIMP_(ULONG) CPropertyStg::AddRef()
  127. {
  128. return InterlockedIncrement(&_cRef);
  129. }
  130. STDMETHODIMP_(ULONG) CPropertyStg::Release()
  131. {
  132. if (InterlockedDecrement(&_cRef))
  133. return _cRef;
  134. delete this;
  135. return 0;
  136. }
  137. BOOL CPropertyStg::_SectionValueName(const PROPSPEC *ppspec,
  138. LPTSTR pszSection, UINT cchSection,
  139. LPTSTR pszValueName, UINT cchValueName)
  140. {
  141. *pszSection = *pszValueName = 0;
  142. if (_fmtid == FMTID_SummaryInformation)
  143. {
  144. if (PIDSI_COMMENTS == ppspec->propid)
  145. {
  146. lstrcpyn(pszSection, TEXT(".ShellClassInfo"), cchSection);
  147. lstrcpyn(pszValueName, TEXT("InfoTip"), cchValueName);
  148. }
  149. }
  150. if (!*pszSection || !*pszValueName)
  151. {
  152. if (PID_CODEPAGE < ppspec->propid)
  153. {
  154. SHStringFromGUID(_fmtid, pszSection, cchSection);
  155. if (PRSPEC_LPWSTR == ppspec->ulKind)
  156. {
  157. SHUnicodeToTChar(ppspec->lpwstr, pszValueName, cchValueName);
  158. }
  159. else if (PRSPEC_PROPID == ppspec->ulKind)
  160. {
  161. wnsprintf(pszValueName, cchValueName, TEXT("Prop%d"), ppspec->propid);
  162. }
  163. }
  164. }
  165. return (*pszSection && *pszValueName) ? TRUE : FALSE;
  166. }
  167. HRESULT CPropertyStg::_ReadProp(const PROPSPEC *ppspec, PROPVARIANT *ppropvar)
  168. {
  169. PropVariantInit(ppropvar); // init out param to VT_EMPTY
  170. HRESULT hr = S_FALSE;
  171. TCHAR szSection[128], szPropName[128];
  172. if (_SectionValueName(ppspec, szSection, ARRAYSIZE(szSection), szPropName, ARRAYSIZE(szPropName)))
  173. {
  174. TCHAR szValue[128];
  175. UINT cch = GetPrivateProfileString(szSection, szPropName, TEXT(""), szValue, ARRAYSIZE(szValue), _ppss->IniFile());
  176. if (cch)
  177. {
  178. hr = SHStrDup(szValue, &ppropvar->pwszVal);
  179. if (SUCCEEDED(hr))
  180. ppropvar->vt = VT_LPWSTR;
  181. }
  182. }
  183. return hr;
  184. }
  185. STDMETHODIMP CPropertyStg::ReadMultiple(ULONG cpspec, const PROPSPEC rgpspec[], PROPVARIANT rgpropvar[])
  186. {
  187. HRESULT hr = S_FALSE;
  188. UINT cRead = 0;
  189. for (UINT i = 0; i < cpspec; i++)
  190. {
  191. hr = _ReadProp(&rgpspec[i], &rgpropvar[i]);
  192. if (S_OK == hr)
  193. {
  194. cRead++;
  195. }
  196. if (FAILED(hr))
  197. {
  198. FreePropVariantArray(i, rgpropvar);
  199. cRead = 0;
  200. break;
  201. }
  202. }
  203. if (cRead)
  204. hr = S_OK; // at least one non VT_EMPTY property read
  205. return hr;
  206. }
  207. STDMETHODIMP CPropertyStg::WriteMultiple(ULONG cpspec, const PROPSPEC rgpspec[], const PROPVARIANT rgpropvar[], PROPID propidNameFirst)
  208. {
  209. return E_NOTIMPL;
  210. }
  211. STDMETHODIMP CPropertyStg::DeleteMultiple(ULONG cpspec, const PROPSPEC rgpspec[])
  212. {
  213. return E_NOTIMPL;
  214. }
  215. STDMETHODIMP CPropertyStg::ReadPropertyNames(ULONG cpropid, const PROPID rgpropid[], LPOLESTR rglpwstrName[])
  216. {
  217. return E_NOTIMPL;
  218. }
  219. STDMETHODIMP CPropertyStg::WritePropertyNames(ULONG cpropid, const PROPID rgpropid[], const LPOLESTR rglpwstrName[])
  220. {
  221. return E_NOTIMPL;
  222. }
  223. STDMETHODIMP CPropertyStg::DeletePropertyNames(ULONG cpropid, const PROPID rgpropid[])
  224. {
  225. return E_NOTIMPL;
  226. }
  227. STDMETHODIMP CPropertyStg::Commit(DWORD grfCommitFlags)
  228. {
  229. return E_NOTIMPL;
  230. }
  231. STDMETHODIMP CPropertyStg::Revert(void)
  232. {
  233. return E_NOTIMPL;
  234. }
  235. STDMETHODIMP CPropertyStg::Enum(IEnumSTATPROPSTG **ppenum)
  236. {
  237. return E_NOTIMPL;
  238. }
  239. STDMETHODIMP CPropertyStg::SetTimes(const FILETIME *pctime, const FILETIME *patime,const FILETIME *pmtime)
  240. {
  241. return E_NOTIMPL;
  242. }
  243. STDMETHODIMP CPropertyStg::SetClass(REFCLSID clsid)
  244. {
  245. return E_NOTIMPL;
  246. }
  247. STDMETHODIMP CPropertyStg::Stat(STATPROPSETSTG *pstatpsstg)
  248. {
  249. return E_NOTIMPL;
  250. }
  251. STDAPI SHCreatePropStgOnFolder(LPCTSTR pszFolder, DWORD grfMode, IPropertySetStorage **ppss)
  252. {
  253. *ppss = (IPropertySetStorage *)new CPropertySetStg(pszFolder, grfMode);
  254. return *ppss ? S_OK : E_OUTOFMEMORY;
  255. }