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.

382 lines
7.7 KiB

  1. // Util.cpp
  2. #include "stdafx.h"
  3. #include "util.h"
  4. #if LoadSaveHelpers
  5. BOOL IsPersistable(IUnknown *punk) // returns TRUE if object supports one of the supported peristence interfaces
  6. {
  7. CComQIPtr<IPersistStream> ppersiststream(punk);
  8. if (ppersiststream == NULL)
  9. {
  10. CComQIPtr<IPersistStorage> ppersiststorage(punk);
  11. if (ppersiststorage == NULL)
  12. {
  13. CComQIPtr<IPersistPropertyBag> ppersistpropbag(punk);
  14. if (ppersistpropbag == NULL)
  15. return false;
  16. }
  17. }
  18. return true;
  19. }
  20. HRESULT SaveToStream(IUnknown *punk, IStorage *pstore, TCHAR *szPrefix, int n)
  21. {
  22. HRESULT hr;
  23. CComQIPtr<IPersistStream> ppersiststream(punk);
  24. if (ppersiststream == NULL)
  25. return E_INVALIDARG;
  26. CComPtr<IStream> pstream;
  27. const TCHAR szFormat[] = _T("%s Stream %d");
  28. TCHAR szName[100 + sizeof(szFormat)/sizeof(TCHAR) + 10];
  29. if (wcslen(szPrefix) > 100)
  30. return E_INVALIDARG;
  31. wsprintf(szName, szFormat, szPrefix, n);
  32. CComBSTR bstrName(szName);
  33. hr = pstore->CreateStream(bstrName,
  34. STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0,&pstream);
  35. if (SUCCEEDED(hr))
  36. {
  37. hr = OleSaveToStream(ppersiststream, pstream);
  38. }
  39. return hr;
  40. }
  41. HRESULT LoadFromStream(IStorage *pstore, TCHAR *szPrefix, int n, IUnknown **ppunk)
  42. {
  43. HRESULT hr;
  44. CComPtr<IStream> pstream;
  45. const TCHAR szFormat[] = _T("%s Stream %d");
  46. TCHAR szName[100 + sizeof(szFormat)/sizeof(TCHAR) + 10];
  47. if (wcslen(szPrefix) > 100)
  48. return E_INVALIDARG;
  49. wsprintf(szName, szFormat, szPrefix, n);
  50. CComBSTR bstrName(szName);
  51. hr = pstore->OpenStream(bstrName, NULL,
  52. STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pstream);
  53. if (FAILED(hr))
  54. return S_FALSE;
  55. hr = OleLoadFromStream(pstream, IID_IUnknown, (void **)ppunk);
  56. return hr;
  57. }
  58. HRESULT SaveToStorage(IUnknown *punk, IStorage *pstore, TCHAR *szPrefix, int n)
  59. {
  60. HRESULT hr;
  61. CComQIPtr<IPersistStorage> ppersiststore(punk);
  62. if (ppersiststore == NULL)
  63. return E_INVALIDARG;
  64. CComPtr<IStorage> pstore2;
  65. const TCHAR szFormat[] = _T("%s Store %d");
  66. TCHAR szName[100 + sizeof(szFormat)/sizeof(TCHAR) + 10];
  67. if (wcslen(szPrefix) > 100)
  68. return E_INVALIDARG;
  69. wsprintf(szName, szFormat, szPrefix, n);
  70. CComBSTR bstrName(szName);
  71. hr = pstore->CreateStorage(bstrName,
  72. STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pstore2);
  73. if (SUCCEEDED(hr))
  74. {
  75. hr = OleSave(ppersiststore, pstore2, FALSE);
  76. }
  77. return hr;
  78. }
  79. HRESULT LoadFromStorage(IStorage *pstore, TCHAR *szPrefix, int n, IUnknown **ppunk)
  80. {
  81. HRESULT hr;
  82. CComPtr<IStorage> pstore2;
  83. const TCHAR szFormat[] = _T("%s Store %d");
  84. TCHAR szName[100 + sizeof(szFormat)/sizeof(TCHAR) + 10];
  85. if (wcslen(szPrefix) > 100)
  86. return E_INVALIDARG;
  87. wsprintf(szName, szFormat, szPrefix, n);
  88. CComBSTR bstrName(szName);
  89. hr = pstore->OpenStorage(bstrName, NULL,
  90. STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &pstore2);
  91. if (FAILED(hr))
  92. return S_FALSE;
  93. hr = OleLoad(pstore2, IID_IUnknown, NULL, (void **) ppunk);
  94. CComQIPtr<IPersist> ppersist(*ppunk);
  95. CLSID clsid;
  96. hr = ppersist->GetClassID(&clsid);
  97. return hr;
  98. }
  99. #endif
  100. #if PropBagInStream
  101. HRESULT SaveToPropBagInStream(IPersistPropertyBag *ppersistpropbag, IStream *pstream)
  102. {
  103. HRESULT hr;
  104. if (ppersistpropbag == NULL)
  105. return E_INVALIDARG;
  106. CLSID clsid;
  107. hr = ppersistpropbag->GetClassID(&clsid);
  108. if (FAILED(hr))
  109. return hr;
  110. hr = WriteClassStm(pstream, clsid);
  111. if (FAILED(hr))
  112. return hr;
  113. CComPtr<PropertyBag> ppropbag = NewComObject(PropertyBag);
  114. if (ppropbag == NULL)
  115. hr = E_OUTOFMEMORY;
  116. hr = ppersistpropbag->Save(ppropbag, TRUE, TRUE);
  117. if (SUCCEEDED(hr))
  118. hr = ppropbag->WriteToStream(pstream);
  119. return hr;
  120. }
  121. HRESULT LoadFromPropBagInStream(IStream *pstream, IUnknown **ppunk)
  122. {
  123. HRESULT hr;
  124. CComPtr<PropertyBag> ppropbag;
  125. CLSID clsid;
  126. ReadClassStm(pstream, &clsid);
  127. CComPtr<IUnknown> punk;
  128. hr = punk.CoCreateInstance(clsid);
  129. if (FAILED(hr))
  130. return hr;
  131. CComQIPtr<IPersistPropertyBag> ppersistpropbag(punk);
  132. if (ppersistpropbag == NULL)
  133. return STG_E_DOCFILECORRUPT;
  134. ppropbag = NewComObject(PropertyBag);
  135. if (ppropbag == NULL)
  136. return E_OUTOFMEMORY;
  137. ppropbag->ReadFromStream(pstream);
  138. ppersistpropbag->Load(ppropbag, NULL);
  139. *ppunk = punk.Detach();
  140. return hr;
  141. }
  142. PropertyBag::~PropertyBag()
  143. {
  144. for (t_map::iterator iter = m_mapProps.begin(); iter != m_mapProps.end(); iter++)
  145. {
  146. BSTR bstrName = (*iter).first;
  147. if (bstrName != NULL)
  148. SysFreeString(bstrName);
  149. ::VariantClear(&(*iter).second);
  150. }
  151. }
  152. HRESULT PropertyBag::ReadFromStream(IStream *pstream)
  153. {
  154. HRESULT hr;
  155. long lCount;
  156. ULONG cb = sizeof(lCount);
  157. hr = pstream->Read(&lCount, cb, &cb);
  158. if (FAILED(hr))
  159. return STG_E_DOCFILECORRUPT;
  160. for (long i=0; i < lCount; i++)
  161. {
  162. CComBSTR bstrName;
  163. bstrName.ReadFromStream(pstream);
  164. CComVariant varVal;
  165. char ch;
  166. cb = sizeof(ch);
  167. hr = pstream->Read(&ch, cb, &cb);
  168. if (FAILED(hr))
  169. return STG_E_DOCFILECORRUPT;
  170. switch (ch)
  171. {
  172. case t_NULL:
  173. varVal = (IUnknown *) NULL;
  174. break;
  175. case t_Blob:
  176. {
  177. CComBSTR bstr;
  178. bstr.ReadFromStream(pstream);
  179. varVal = bstr;
  180. varVal.vt = VT_BSTR_BLOB;
  181. }
  182. break;
  183. case t_Variant:
  184. varVal.ReadFromStream(pstream);
  185. break;
  186. case t_PropertyBag:
  187. {
  188. varVal.vt = VT_UNKNOWN;
  189. hr = LoadFromPropBagInStream(pstream, &varVal.punkVal);
  190. }
  191. break;
  192. default:
  193. return STG_E_DOCFILECORRUPT;
  194. }
  195. VARIANT &var = m_mapProps[bstrName.Detach()];
  196. ::VariantInit(&var);
  197. varVal.Detach(&var);
  198. }
  199. return S_OK;
  200. }
  201. HRESULT PropertyBag::WriteToStream(IStream *pstream)
  202. {
  203. HRESULT hr;
  204. long lCount = (long) m_mapProps.size();
  205. ULONG cb = sizeof(lCount);
  206. pstream->Write(&lCount, cb, &cb);
  207. for (t_map::iterator iter = m_mapProps.begin(); iter != m_mapProps.end(); iter++)
  208. {
  209. CComBSTR bstrName((*iter).first);
  210. bstrName.WriteToStream(pstream);
  211. VARIANT & var = (*iter).second;
  212. switch (var.vt)
  213. {
  214. case VT_BSTR_BLOB:
  215. {
  216. char ch = t_Blob;
  217. cb = sizeof(ch);
  218. hr = pstream->Write(&ch, cb, &cb);
  219. CComBSTR bstr;
  220. bstr.Attach(var.bstrVal);
  221. bstr.WriteToStream(pstream);
  222. bstr.Detach();
  223. }
  224. break;
  225. case VT_UNKNOWN:
  226. case VT_DISPATCH:
  227. {
  228. if (var.punkVal == NULL)
  229. {
  230. DoNull:
  231. char ch = t_NULL;
  232. cb = sizeof(ch);
  233. hr = pstream->Write(&ch, cb, &cb);
  234. break;
  235. }
  236. CComQIPtr<IPersistStream> ppersiststream(var.punkVal);
  237. if (ppersiststream != NULL)
  238. goto defaultCase;
  239. CComQIPtr<IPersistPropertyBag> ppersistpropbag(var.punkVal);
  240. if (ppersistpropbag == NULL)
  241. goto DoNull;
  242. char ch = t_PropertyBag;
  243. cb = sizeof(ch);
  244. hr = pstream->Write(&ch, cb, &cb);
  245. hr = SaveToPropBagInStream(ppersistpropbag, pstream);
  246. if (FAILED(hr))
  247. return hr;
  248. }
  249. break;
  250. defaultCase:
  251. default:
  252. {
  253. char ch = t_Variant;
  254. cb = sizeof(ch);
  255. hr = pstream->Write(&ch, cb, &cb);
  256. CComVariant varT;
  257. varT.Attach(&var);
  258. varT.WriteToStream(pstream);
  259. varT.Detach(&var);
  260. }
  261. break;
  262. }
  263. }
  264. return S_OK;
  265. }
  266. STDMETHODIMP PropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
  267. {
  268. ENTER_API
  269. {
  270. if ((pszPropName == NULL) || (pVar == NULL))
  271. return E_POINTER;
  272. CComBSTR bstrName(pszPropName);
  273. t_map::iterator iter = m_mapProps.find(bstrName);
  274. if (iter == m_mapProps.end())
  275. return E_INVALIDARG;
  276. return ::VariantCopy(pVar, &(*iter).second);
  277. }
  278. LEAVE_API
  279. }
  280. STDMETHODIMP PropertyBag::Write(LPCOLESTR pszPropName, VARIANT *pvar)
  281. {
  282. ENTER_API
  283. {
  284. HRESULT hr;
  285. if ((pszPropName == NULL) || (pvar == NULL))
  286. return E_POINTER;
  287. if ((pvar->vt & ~VT_TYPEMASK) && (pvar->vt != VT_BSTR_BLOB))
  288. return E_INVALIDARG;
  289. CComBSTR bstrName(pszPropName);
  290. VARIANT &var = m_mapProps[bstrName.Detach()];
  291. ::VariantInit(&var);
  292. hr = ::VariantCopy(&var, pvar);
  293. return hr;
  294. }
  295. LEAVE_API
  296. }
  297. #endif