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.

567 lines
14 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1999
  5. //
  6. // File: StgUtil.h
  7. //
  8. // Contents: Classes to simplify dealing with storage objects.
  9. //
  10. // Classes: CDocFile,
  11. // CIStorage
  12. // CIStream
  13. //
  14. // History: 6/3/1996 RaviR Created
  15. //
  16. //
  17. // Sample: Code sample using the above three classes & their safe ptrs.
  18. //
  19. // Objective: Create a doc file this will be the root storage.
  20. // Create a sub storage under this root storage.
  21. //
  22. // Code:
  23. // HRESULT
  24. // CerateADocFileWithSubStorage(
  25. // WCHAR wszDocFileName[],
  26. // WCHAR wszSubStgName[],
  27. // LPSTORAGE *ppstg)
  28. // {
  29. // try
  30. // {
  31. // CDocFile docFile;
  32. // docFile.Create(wszDocFileName);
  33. //
  34. // CIStorage stgRoot;
  35. // docFile.Transfer(&stgRoot);
  36. //
  37. // CIStorage stgSub;
  38. // stgRoot.CreateStorage(&stgSub, wszSubStgName);
  39. //
  40. // stgRoot.Transfer(ppstg);
  41. // }
  42. // CATCH_FILE_ERROR(hr,cfe)
  43. // delete cfe;
  44. // return hr;
  45. // END_CATCH_FILE_ERROR;
  46. //
  47. // return S_OK;
  48. // }
  49. //
  50. //____________________________________________________________________________
  51. //
  52. #ifndef __STGUTIL__H__
  53. #define __STGUTIL__H__
  54. #include "macros.h"
  55. //
  56. // CDocFile, CIStorage and CIStream throw errors of type CFileException.
  57. // Note, however, that m_cause is always CFileException::generic and
  58. // m_lOsError is an HRESULT rather than a Windows error code.
  59. //
  60. #define THROW_FILE_ERROR2(hr,psz) AfxThrowFileException( CFileException::generic, hr, psz );
  61. #define THROW_FILE_ERROR(hr) THROW_FILE_ERROR2( hr, NULL )
  62. #define CATCH_FILE_ERROR(hr) \
  63. catch(CFileException* cfe) \
  64. { \
  65. if (cfe.m_cause != CFileException::generic) \
  66. throw; \
  67. HRESULT hr = cfe.m_IOsError;
  68. #define END_CATCH_FILE_ERROR }
  69. //____________________________________________________________________________
  70. //
  71. // Class: CDocFile
  72. //
  73. // Synopsis: CDocFile can be used to create, open & close a docfile.
  74. // It has one data member, a pointer to the root IStorage
  75. // interface of the document. Safe interface pointer member
  76. // functions are created for this data member. (Please see
  77. // macros.h for description of Safe interface pointer member
  78. // functions)
  79. //
  80. // Members: Create:
  81. // Creates/opens a docfile with the given name. The default
  82. // mode is to create a docfile with read-write and share
  83. // exclusive flags. Throws CFileException on error.
  84. //
  85. // CreateTemporary:
  86. // Creates a temporary docfile, which will be deleted on
  87. // release. Throws CFileException on error.
  88. //
  89. // Open:
  90. // Opens an existing docfile. The default mode is read-write
  91. // and share exclusive. Throws CFileException on error.
  92. //
  93. // Safe Interface Pointer Member functions:
  94. // Used to access the IStorage interface ptr. (see macros.h)
  95. //
  96. //
  97. // History: 5/31/1996 RaviR Created
  98. //
  99. //____________________________________________________________________________
  100. //
  101. class CDocFile
  102. {
  103. public:
  104. void Create(LPWSTR pwszName,
  105. DWORD grfMode = STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE);
  106. void CreateTemporary(void) { this->Create(NULL, STGM_DELETEONRELEASE); }
  107. void Open(LPWSTR pwszName,
  108. DWORD grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE);
  109. DECLARE_SAFE_INTERFACE_PTR_MEMBERS(CDocFile, IStorage, m_pstg)
  110. private:
  111. LPSTORAGE m_pstg;
  112. }; // class CDocFile
  113. inline
  114. void
  115. CDocFile::Create(
  116. LPWSTR pswzName,
  117. DWORD grfMode)
  118. {
  119. ASSERT(m_pstg == NULL);
  120. HRESULT hr = StgCreateDocfile(pswzName, grfMode, 0, &m_pstg);
  121. if (FAILED(hr))
  122. {
  123. CHECK_HRESULT(hr);
  124. m_pstg = NULL;
  125. USES_CONVERSION;
  126. THROW_FILE_ERROR2( hr, W2T(pswzName) );
  127. }
  128. }
  129. inline
  130. void
  131. CDocFile::Open(
  132. LPWSTR pwszName,
  133. DWORD grfMode)
  134. {
  135. ASSERT(m_pstg == NULL);
  136. HRESULT hr = StgOpenStorage(pwszName, NULL, grfMode, NULL, NULL, &m_pstg);
  137. if (FAILED(hr))
  138. {
  139. CHECK_HRESULT(hr);
  140. m_pstg = NULL;
  141. USES_CONVERSION;
  142. THROW_FILE_ERROR2( hr, W2T(pwszName) );
  143. }
  144. }
  145. //____________________________________________________________________________
  146. //
  147. // Class: CIStorage
  148. //
  149. // Synopsis: Represents an IStorage instance - top level or embedded.
  150. //
  151. // History: 5/29/1996 RaviR Created
  152. //
  153. // Notes: 1) This is a simple wrapper around the Docfile implementaion
  154. // of IStorage.
  155. //
  156. // 2) Instead of returning errors we use the C++ exception
  157. // handling mechanism and throw CFileException.
  158. //
  159. // 3) Most of the methods have default values for arguments.
  160. //
  161. // 4) Safe Interface Pointer methods have been added for
  162. // the IStorage interface ptr.
  163. //
  164. //
  165. // CIStorage
  166. // |
  167. // |
  168. // IStorage
  169. //
  170. //____________________________________________________________________________
  171. //
  172. class CIStorage
  173. {
  174. public:
  175. void CreateStream(LPSTREAM *ppstm, LPCOLESTR pszName,
  176. DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
  177. {
  178. ASSERT(m_pstg != NULL);
  179. ASSERT(ppstm != NULL);
  180. ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
  181. ASSERT((grfMode & STGM_TRANSACTED) == 0);
  182. ASSERT((grfMode & STGM_SHARE_EXCLUSIVE) != 0);
  183. HRESULT hr = m_pstg->CreateStream(pszName, grfMode, NULL, NULL, ppstm);
  184. USES_CONVERSION;
  185. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
  186. }
  187. void OpenStream(LPSTREAM *ppstm, LPCOLESTR pszName,
  188. DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
  189. {
  190. ASSERT(m_pstg != NULL);
  191. ASSERT(ppstm != NULL);
  192. ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
  193. ASSERT((grfMode & STGM_TRANSACTED) == 0);
  194. ASSERT((grfMode & STGM_SHARE_EXCLUSIVE) != 0);
  195. HRESULT hr = m_pstg->OpenStream(pszName, NULL, grfMode, 0, ppstm);
  196. USES_CONVERSION;
  197. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
  198. }
  199. void CreateStorage(LPSTORAGE *ppstg, LPCOLESTR pszName,
  200. DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
  201. {
  202. ASSERT(m_pstg != NULL);
  203. ASSERT(ppstg != NULL);
  204. ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
  205. HRESULT hr = m_pstg->CreateStorage(pszName, grfMode, NULL, NULL, ppstg);
  206. USES_CONVERSION;
  207. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
  208. }
  209. void OpenStorage(LPSTORAGE *ppstg, LPCOLESTR pszName,
  210. DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
  211. {
  212. ASSERT(m_pstg != NULL);
  213. ASSERT(ppstg != NULL);
  214. ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
  215. ASSERT((grfMode & STGM_PRIORITY) == 0);
  216. ASSERT((grfMode & STGM_SHARE_EXCLUSIVE) != 0);
  217. HRESULT hr = m_pstg->OpenStorage(pszName, NULL, grfMode, NULL, 0, ppstg);
  218. USES_CONVERSION;
  219. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
  220. }
  221. void OpenStorage(LPSTORAGE *ppstg, LPSTORAGE pstgPriority,
  222. DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
  223. {
  224. ASSERT(m_pstg != NULL);
  225. ASSERT(ppstg != NULL);
  226. ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
  227. ASSERT((grfMode & STGM_PRIORITY) == 0);
  228. ASSERT((grfMode & STGM_SHARE_EXCLUSIVE) != 0);
  229. HRESULT hr = m_pstg->OpenStorage(NULL, pstgPriority, grfMode, NULL, 0, ppstg);
  230. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  231. }
  232. void CopyTo(LPSTORAGE pstgDest)
  233. {
  234. ASSERT(m_pstg != NULL);
  235. ASSERT(pstgDest != NULL);
  236. HRESULT hr = m_pstg->CopyTo(0, NULL, NULL, pstgDest);
  237. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  238. }
  239. void MoveElementTo(LPCOLESTR pszName, LPSTORAGE pstgDest,
  240. LPCOLESTR pszNewName, DWORD grfFlags = STGMOVE_MOVE)
  241. {
  242. ASSERT(m_pstg != NULL);
  243. ASSERT(pstgDest != NULL);
  244. ASSERT(m_pstg != pstgDest);
  245. HRESULT hr = m_pstg->MoveElementTo(pszName, pstgDest, pszNewName, grfFlags);
  246. USES_CONVERSION;
  247. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
  248. }
  249. void Commit(DWORD grfCommitFlags = STGC_ONLYIFCURRENT)
  250. {
  251. ASSERT(m_pstg != NULL);
  252. HRESULT hr = m_pstg->Commit(grfCommitFlags);
  253. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  254. }
  255. void Revert(void)
  256. {
  257. ASSERT(m_pstg != NULL);
  258. HRESULT hr = m_pstg->Revert();
  259. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  260. }
  261. void EnumElements(IEnumSTATSTG ** ppenum)
  262. {
  263. ASSERT(m_pstg != NULL);
  264. ASSERT(ppenum != NULL);
  265. HRESULT hr = m_pstg->EnumElements(0, NULL, 0, ppenum);
  266. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  267. }
  268. void DestroyElement(LPCOLESTR pszName)
  269. {
  270. ASSERT(m_pstg != NULL);
  271. HRESULT hr = m_pstg->DestroyElement(pszName);
  272. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  273. }
  274. void RenameElement(LPCOLESTR pszOldName, LPCOLESTR pszNewName)
  275. {
  276. ASSERT(m_pstg != NULL);
  277. ASSERT(pszOldName != NULL);
  278. ASSERT(pszNewName != NULL);
  279. HRESULT hr = m_pstg->RenameElement(pszOldName, pszNewName);
  280. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  281. }
  282. void SetElementTimes(LPCOLESTR pszName, LPFILETIME pctime,
  283. LPFILETIME patime = NULL, LPFILETIME pmtime = NULL)
  284. {
  285. ASSERT(m_pstg != NULL);
  286. HRESULT hr = m_pstg->SetElementTimes(pszName, pctime, patime, pmtime);
  287. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  288. }
  289. void SetClass(REFCLSID clsid)
  290. {
  291. ASSERT(m_pstg != NULL);
  292. HRESULT hr = m_pstg->SetClass(clsid);
  293. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  294. }
  295. void SetStateBits(DWORD grfStateBits, DWORD grfMask)
  296. {
  297. ASSERT(m_pstg != NULL);
  298. HRESULT hr = m_pstg->SetStateBits(grfStateBits, grfMask);
  299. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  300. }
  301. void Stat(STATSTG * pstatstg, DWORD grfStatFlag = STATFLAG_NONAME)
  302. {
  303. ASSERT(m_pstg != NULL);
  304. HRESULT hr = m_pstg->Stat(pstatstg, grfStatFlag);
  305. if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
  306. }
  307. DECLARE_SAFE_INTERFACE_PTR_MEMBERS(CIStorage, IStorage, m_pstg)
  308. private:
  309. IStorage * m_pstg;
  310. }; // class CIStorage
  311. //____________________________________________________________________________
  312. //
  313. // Class: CIStream
  314. //
  315. // Synopsis: Represents an IStream instance
  316. //
  317. // History: 5/31/1996 RaviR Created
  318. //
  319. // Notes: 1) This is a simple wrapper around the Docfile implementaion
  320. // of IStream.
  321. //
  322. // 2) Instead of returning errors we use the C++ exception
  323. // handling mechanism and throw the error(hresult).
  324. //
  325. // 4) Safe Interface Pointer methods have been added for
  326. // the IStream interface ptr.
  327. //
  328. //
  329. // CIStream
  330. // |
  331. // |
  332. // IStream
  333. //
  334. //____________________________________________________________________________
  335. //
  336. class CIStream
  337. {
  338. public:
  339. void Commit(DWORD grfCommitFlags = STGC_ONLYIFCURRENT);
  340. void Clone(IStream ** ppstm);
  341. void Read(PVOID pv, ULONG cb);
  342. void Write(const VOID * pv, ULONG cb);
  343. void CopyTo(IStream * pstm, ULARGE_INTEGER cb);
  344. void GetCurrentSeekPosition(ULARGE_INTEGER * plibCurPosition);
  345. void Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin = STREAM_SEEK_CUR,
  346. ULARGE_INTEGER * plibNewPosition = NULL);
  347. void SetSize(ULARGE_INTEGER libNewSize);
  348. void Stat(STATSTG * pstatstg, DWORD grfStatFlag = STATFLAG_NONAME);
  349. DECLARE_SAFE_INTERFACE_PTR_MEMBERS(CIStream, IStream, m_pstm);
  350. private:
  351. LPSTREAM m_pstm;
  352. }; // class CIStream
  353. inline
  354. void
  355. CIStream::Clone(
  356. IStream ** ppstm)
  357. {
  358. ASSERT(m_pstm != NULL);
  359. HRESULT hr = m_pstm->Clone(ppstm);
  360. if (FAILED(hr))
  361. {
  362. CHECK_HRESULT(hr);
  363. THROW_FILE_ERROR(hr);
  364. }
  365. }
  366. inline
  367. void
  368. CIStream::Commit(
  369. DWORD grfCommitFlags)
  370. {
  371. ASSERT(m_pstm != NULL);
  372. HRESULT hr = m_pstm->Commit(grfCommitFlags);
  373. if (FAILED(hr))
  374. {
  375. CHECK_HRESULT(hr);
  376. THROW_FILE_ERROR(hr);
  377. }
  378. }
  379. inline
  380. void
  381. CIStream::Seek(
  382. LARGE_INTEGER dlibMove,
  383. DWORD dwOrigin,
  384. ULARGE_INTEGER * plibNewPosition)
  385. {
  386. ASSERT(m_pstm != NULL);
  387. HRESULT hr = m_pstm->Seek(dlibMove, dwOrigin, plibNewPosition);
  388. if (FAILED(hr))
  389. {
  390. CHECK_HRESULT(hr);
  391. THROW_FILE_ERROR(hr);
  392. }
  393. }
  394. //____________________________________________________________________________
  395. //
  396. // Member: CIStream::GetCurrentSeekPosition
  397. //
  398. // Synopsis: Returns the current seek position.
  399. //
  400. // Arguments: [plibCurPosition] -- IN
  401. //
  402. // Returns: void
  403. //____________________________________________________________________________
  404. //
  405. inline
  406. void
  407. CIStream::GetCurrentSeekPosition(
  408. ULARGE_INTEGER * plibCurPosition)
  409. {
  410. ASSERT(m_pstm != NULL);
  411. ASSERT(plibCurPosition != NULL);
  412. LARGE_INTEGER li = {0};
  413. HRESULT hr = m_pstm->Seek(li, STREAM_SEEK_CUR, plibCurPosition);
  414. if (FAILED(hr))
  415. {
  416. CHECK_HRESULT(hr);
  417. THROW_FILE_ERROR(hr);
  418. }
  419. }
  420. inline
  421. void
  422. CIStream::SetSize(
  423. ULARGE_INTEGER libNewSize)
  424. {
  425. ASSERT(m_pstm != NULL);
  426. HRESULT hr = m_pstm->SetSize(libNewSize);
  427. if (FAILED(hr))
  428. {
  429. CHECK_HRESULT(hr);
  430. THROW_FILE_ERROR(hr);
  431. }
  432. }
  433. inline
  434. void
  435. CIStream::Stat(
  436. STATSTG * pstatstg,
  437. DWORD grfStatFlag)
  438. {
  439. ASSERT(m_pstm != NULL);
  440. ASSERT(pstatstg != NULL);
  441. HRESULT hr = m_pstm->Stat(pstatstg, grfStatFlag);
  442. if (FAILED(hr))
  443. {
  444. CHECK_HRESULT(hr);
  445. THROW_FILE_ERROR(hr);
  446. }
  447. }
  448. #endif // __STGUTIL__H__