568 lines
14 KiB
C++
568 lines
14 KiB
C++
//____________________________________________________________________________
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1999
|
|
//
|
|
// File: StgUtil.h
|
|
//
|
|
// Contents: Classes to simplify dealing with storage objects.
|
|
//
|
|
// Classes: CDocFile,
|
|
// CIStorage
|
|
// CIStream
|
|
//
|
|
// History: 6/3/1996 RaviR Created
|
|
//
|
|
//
|
|
// Sample: Code sample using the above three classes & their safe ptrs.
|
|
//
|
|
// Objective: Create a doc file this will be the root storage.
|
|
// Create a sub storage under this root storage.
|
|
//
|
|
// Code:
|
|
// HRESULT
|
|
// CerateADocFileWithSubStorage(
|
|
// WCHAR wszDocFileName[],
|
|
// WCHAR wszSubStgName[],
|
|
// LPSTORAGE *ppstg)
|
|
// {
|
|
// try
|
|
// {
|
|
// CDocFile docFile;
|
|
// docFile.Create(wszDocFileName);
|
|
//
|
|
// CIStorage stgRoot;
|
|
// docFile.Transfer(&stgRoot);
|
|
//
|
|
// CIStorage stgSub;
|
|
// stgRoot.CreateStorage(&stgSub, wszSubStgName);
|
|
//
|
|
// stgRoot.Transfer(ppstg);
|
|
// }
|
|
// CATCH_FILE_ERROR(hr,cfe)
|
|
// delete cfe;
|
|
// return hr;
|
|
// END_CATCH_FILE_ERROR;
|
|
//
|
|
// return S_OK;
|
|
// }
|
|
//
|
|
//____________________________________________________________________________
|
|
//
|
|
|
|
|
|
#ifndef __STGUTIL__H__
|
|
#define __STGUTIL__H__
|
|
|
|
#include "macros.h"
|
|
|
|
//
|
|
// CDocFile, CIStorage and CIStream throw errors of type CFileException.
|
|
// Note, however, that m_cause is always CFileException::generic and
|
|
// m_lOsError is an HRESULT rather than a Windows error code.
|
|
//
|
|
|
|
#define THROW_FILE_ERROR2(hr,psz) AfxThrowFileException( CFileException::generic, hr, psz );
|
|
#define THROW_FILE_ERROR(hr) THROW_FILE_ERROR2( hr, NULL )
|
|
|
|
#define CATCH_FILE_ERROR(hr) \
|
|
catch(CFileException* cfe) \
|
|
{ \
|
|
if (cfe.m_cause != CFileException::generic) \
|
|
throw; \
|
|
HRESULT hr = cfe.m_IOsError;
|
|
|
|
#define END_CATCH_FILE_ERROR }
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Class: CDocFile
|
|
//
|
|
// Synopsis: CDocFile can be used to create, open & close a docfile.
|
|
// It has one data member, a pointer to the root IStorage
|
|
// interface of the document. Safe interface pointer member
|
|
// functions are created for this data member. (Please see
|
|
// macros.h for description of Safe interface pointer member
|
|
// functions)
|
|
//
|
|
// Members: Create:
|
|
// Creates/opens a docfile with the given name. The default
|
|
// mode is to create a docfile with read-write and share
|
|
// exclusive flags. Throws CFileException on error.
|
|
//
|
|
// CreateTemporary:
|
|
// Creates a temporary docfile, which will be deleted on
|
|
// release. Throws CFileException on error.
|
|
//
|
|
// Open:
|
|
// Opens an existing docfile. The default mode is read-write
|
|
// and share exclusive. Throws CFileException on error.
|
|
//
|
|
// Safe Interface Pointer Member functions:
|
|
// Used to access the IStorage interface ptr. (see macros.h)
|
|
//
|
|
//
|
|
// History: 5/31/1996 RaviR Created
|
|
//
|
|
//____________________________________________________________________________
|
|
//
|
|
|
|
|
|
class CDocFile
|
|
{
|
|
public:
|
|
|
|
void Create(LPWSTR pwszName,
|
|
DWORD grfMode = STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE);
|
|
|
|
void CreateTemporary(void) { this->Create(NULL, STGM_DELETEONRELEASE); }
|
|
|
|
void Open(LPWSTR pwszName,
|
|
DWORD grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE);
|
|
|
|
DECLARE_SAFE_INTERFACE_PTR_MEMBERS(CDocFile, IStorage, m_pstg)
|
|
|
|
private:
|
|
LPSTORAGE m_pstg;
|
|
|
|
}; // class CDocFile
|
|
|
|
|
|
|
|
inline
|
|
void
|
|
CDocFile::Create(
|
|
LPWSTR pswzName,
|
|
DWORD grfMode)
|
|
{
|
|
ASSERT(m_pstg == NULL);
|
|
|
|
HRESULT hr = StgCreateDocfile(pswzName, grfMode, 0, &m_pstg);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
CHECK_HRESULT(hr);
|
|
m_pstg = NULL;
|
|
USES_CONVERSION;
|
|
THROW_FILE_ERROR2( hr, W2T(pswzName) );
|
|
}
|
|
}
|
|
|
|
|
|
inline
|
|
void
|
|
CDocFile::Open(
|
|
LPWSTR pwszName,
|
|
DWORD grfMode)
|
|
{
|
|
ASSERT(m_pstg == NULL);
|
|
|
|
HRESULT hr = StgOpenStorage(pwszName, NULL, grfMode, NULL, NULL, &m_pstg);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
CHECK_HRESULT(hr);
|
|
m_pstg = NULL;
|
|
USES_CONVERSION;
|
|
THROW_FILE_ERROR2( hr, W2T(pwszName) );
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Class: CIStorage
|
|
//
|
|
// Synopsis: Represents an IStorage instance - top level or embedded.
|
|
//
|
|
// History: 5/29/1996 RaviR Created
|
|
//
|
|
// Notes: 1) This is a simple wrapper around the Docfile implementaion
|
|
// of IStorage.
|
|
//
|
|
// 2) Instead of returning errors we use the C++ exception
|
|
// handling mechanism and throw CFileException.
|
|
//
|
|
// 3) Most of the methods have default values for arguments.
|
|
//
|
|
// 4) Safe Interface Pointer methods have been added for
|
|
// the IStorage interface ptr.
|
|
//
|
|
//
|
|
// CIStorage
|
|
// |
|
|
// |
|
|
// IStorage
|
|
//
|
|
//____________________________________________________________________________
|
|
//
|
|
|
|
class CIStorage
|
|
{
|
|
public:
|
|
|
|
void CreateStream(LPSTREAM *ppstm, LPCOLESTR pszName,
|
|
DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
ASSERT(ppstm != NULL);
|
|
ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
|
|
ASSERT((grfMode & STGM_TRANSACTED) == 0);
|
|
ASSERT((grfMode & STGM_SHARE_EXCLUSIVE) != 0);
|
|
|
|
HRESULT hr = m_pstg->CreateStream(pszName, grfMode, NULL, NULL, ppstm);
|
|
|
|
USES_CONVERSION;
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
|
|
}
|
|
|
|
void OpenStream(LPSTREAM *ppstm, LPCOLESTR pszName,
|
|
DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
ASSERT(ppstm != NULL);
|
|
ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
|
|
ASSERT((grfMode & STGM_TRANSACTED) == 0);
|
|
ASSERT((grfMode & STGM_SHARE_EXCLUSIVE) != 0);
|
|
|
|
HRESULT hr = m_pstg->OpenStream(pszName, NULL, grfMode, 0, ppstm);
|
|
|
|
USES_CONVERSION;
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
|
|
}
|
|
|
|
void CreateStorage(LPSTORAGE *ppstg, LPCOLESTR pszName,
|
|
DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
ASSERT(ppstg != NULL);
|
|
ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
|
|
|
|
HRESULT hr = m_pstg->CreateStorage(pszName, grfMode, NULL, NULL, ppstg);
|
|
|
|
USES_CONVERSION;
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
|
|
}
|
|
|
|
void OpenStorage(LPSTORAGE *ppstg, LPCOLESTR pszName,
|
|
DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
ASSERT(ppstg != NULL);
|
|
ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
|
|
ASSERT((grfMode & STGM_PRIORITY) == 0);
|
|
ASSERT((grfMode & STGM_SHARE_EXCLUSIVE) != 0);
|
|
|
|
HRESULT hr = m_pstg->OpenStorage(pszName, NULL, grfMode, NULL, 0, ppstg);
|
|
|
|
USES_CONVERSION;
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
|
|
}
|
|
|
|
void OpenStorage(LPSTORAGE *ppstg, LPSTORAGE pstgPriority,
|
|
DWORD grfMode = STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
ASSERT(ppstg != NULL);
|
|
ASSERT((grfMode & STGM_DELETEONRELEASE) == 0);
|
|
ASSERT((grfMode & STGM_PRIORITY) == 0);
|
|
ASSERT((grfMode & STGM_SHARE_EXCLUSIVE) != 0);
|
|
|
|
HRESULT hr = m_pstg->OpenStorage(NULL, pstgPriority, grfMode, NULL, 0, ppstg);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void CopyTo(LPSTORAGE pstgDest)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
ASSERT(pstgDest != NULL);
|
|
|
|
HRESULT hr = m_pstg->CopyTo(0, NULL, NULL, pstgDest);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void MoveElementTo(LPCOLESTR pszName, LPSTORAGE pstgDest,
|
|
LPCOLESTR pszNewName, DWORD grfFlags = STGMOVE_MOVE)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
ASSERT(pstgDest != NULL);
|
|
ASSERT(m_pstg != pstgDest);
|
|
|
|
HRESULT hr = m_pstg->MoveElementTo(pszName, pstgDest, pszNewName, grfFlags);
|
|
|
|
USES_CONVERSION;
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR2(hr, OLE2T((LPOLESTR)pszName)); }
|
|
}
|
|
|
|
void Commit(DWORD grfCommitFlags = STGC_ONLYIFCURRENT)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
|
|
HRESULT hr = m_pstg->Commit(grfCommitFlags);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void Revert(void)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
|
|
HRESULT hr = m_pstg->Revert();
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void EnumElements(IEnumSTATSTG ** ppenum)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
ASSERT(ppenum != NULL);
|
|
|
|
HRESULT hr = m_pstg->EnumElements(0, NULL, 0, ppenum);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void DestroyElement(LPCOLESTR pszName)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
|
|
HRESULT hr = m_pstg->DestroyElement(pszName);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void RenameElement(LPCOLESTR pszOldName, LPCOLESTR pszNewName)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
ASSERT(pszOldName != NULL);
|
|
ASSERT(pszNewName != NULL);
|
|
|
|
HRESULT hr = m_pstg->RenameElement(pszOldName, pszNewName);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void SetElementTimes(LPCOLESTR pszName, LPFILETIME pctime,
|
|
LPFILETIME patime = NULL, LPFILETIME pmtime = NULL)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
|
|
HRESULT hr = m_pstg->SetElementTimes(pszName, pctime, patime, pmtime);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void SetClass(REFCLSID clsid)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
|
|
HRESULT hr = m_pstg->SetClass(clsid);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void SetStateBits(DWORD grfStateBits, DWORD grfMask)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
|
|
HRESULT hr = m_pstg->SetStateBits(grfStateBits, grfMask);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
void Stat(STATSTG * pstatstg, DWORD grfStatFlag = STATFLAG_NONAME)
|
|
{
|
|
ASSERT(m_pstg != NULL);
|
|
|
|
HRESULT hr = m_pstg->Stat(pstatstg, grfStatFlag);
|
|
|
|
if (FAILED(hr)) { CHECK_HRESULT(hr); THROW_FILE_ERROR(hr); }
|
|
}
|
|
|
|
DECLARE_SAFE_INTERFACE_PTR_MEMBERS(CIStorage, IStorage, m_pstg)
|
|
|
|
private:
|
|
IStorage * m_pstg;
|
|
|
|
}; // class CIStorage
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Class: CIStream
|
|
//
|
|
// Synopsis: Represents an IStream instance
|
|
//
|
|
// History: 5/31/1996 RaviR Created
|
|
//
|
|
// Notes: 1) This is a simple wrapper around the Docfile implementaion
|
|
// of IStream.
|
|
//
|
|
// 2) Instead of returning errors we use the C++ exception
|
|
// handling mechanism and throw the error(hresult).
|
|
//
|
|
// 4) Safe Interface Pointer methods have been added for
|
|
// the IStream interface ptr.
|
|
//
|
|
//
|
|
// CIStream
|
|
// |
|
|
// |
|
|
// IStream
|
|
//
|
|
//____________________________________________________________________________
|
|
//
|
|
|
|
class CIStream
|
|
{
|
|
public:
|
|
|
|
void Commit(DWORD grfCommitFlags = STGC_ONLYIFCURRENT);
|
|
void Clone(IStream ** ppstm);
|
|
void Read(PVOID pv, ULONG cb);
|
|
void Write(const VOID * pv, ULONG cb);
|
|
void CopyTo(IStream * pstm, ULARGE_INTEGER cb);
|
|
void GetCurrentSeekPosition(ULARGE_INTEGER * plibCurPosition);
|
|
void Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin = STREAM_SEEK_CUR,
|
|
ULARGE_INTEGER * plibNewPosition = NULL);
|
|
void SetSize(ULARGE_INTEGER libNewSize);
|
|
void Stat(STATSTG * pstatstg, DWORD grfStatFlag = STATFLAG_NONAME);
|
|
|
|
DECLARE_SAFE_INTERFACE_PTR_MEMBERS(CIStream, IStream, m_pstm);
|
|
|
|
private:
|
|
LPSTREAM m_pstm;
|
|
|
|
}; // class CIStream
|
|
|
|
|
|
inline
|
|
void
|
|
CIStream::Clone(
|
|
IStream ** ppstm)
|
|
{
|
|
ASSERT(m_pstm != NULL);
|
|
|
|
HRESULT hr = m_pstm->Clone(ppstm);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
CHECK_HRESULT(hr);
|
|
THROW_FILE_ERROR(hr);
|
|
}
|
|
}
|
|
|
|
|
|
inline
|
|
void
|
|
CIStream::Commit(
|
|
DWORD grfCommitFlags)
|
|
{
|
|
ASSERT(m_pstm != NULL);
|
|
|
|
HRESULT hr = m_pstm->Commit(grfCommitFlags);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
CHECK_HRESULT(hr);
|
|
THROW_FILE_ERROR(hr);
|
|
}
|
|
}
|
|
|
|
|
|
inline
|
|
void
|
|
CIStream::Seek(
|
|
LARGE_INTEGER dlibMove,
|
|
DWORD dwOrigin,
|
|
ULARGE_INTEGER * plibNewPosition)
|
|
{
|
|
ASSERT(m_pstm != NULL);
|
|
|
|
HRESULT hr = m_pstm->Seek(dlibMove, dwOrigin, plibNewPosition);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
CHECK_HRESULT(hr);
|
|
THROW_FILE_ERROR(hr);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CIStream::GetCurrentSeekPosition
|
|
//
|
|
// Synopsis: Returns the current seek position.
|
|
//
|
|
// Arguments: [plibCurPosition] -- IN
|
|
//
|
|
// Returns: void
|
|
//____________________________________________________________________________
|
|
//
|
|
|
|
inline
|
|
void
|
|
CIStream::GetCurrentSeekPosition(
|
|
ULARGE_INTEGER * plibCurPosition)
|
|
{
|
|
ASSERT(m_pstm != NULL);
|
|
ASSERT(plibCurPosition != NULL);
|
|
|
|
LARGE_INTEGER li = {0};
|
|
|
|
HRESULT hr = m_pstm->Seek(li, STREAM_SEEK_CUR, plibCurPosition);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
CHECK_HRESULT(hr);
|
|
THROW_FILE_ERROR(hr);
|
|
}
|
|
}
|
|
|
|
|
|
inline
|
|
void
|
|
CIStream::SetSize(
|
|
ULARGE_INTEGER libNewSize)
|
|
{
|
|
ASSERT(m_pstm != NULL);
|
|
|
|
HRESULT hr = m_pstm->SetSize(libNewSize);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
CHECK_HRESULT(hr);
|
|
THROW_FILE_ERROR(hr);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline
|
|
void
|
|
CIStream::Stat(
|
|
STATSTG * pstatstg,
|
|
DWORD grfStatFlag)
|
|
{
|
|
ASSERT(m_pstm != NULL);
|
|
ASSERT(pstatstg != NULL);
|
|
|
|
HRESULT hr = m_pstm->Stat(pstatstg, grfStatFlag);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
CHECK_HRESULT(hr);
|
|
THROW_FILE_ERROR(hr);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#endif // __STGUTIL__H__
|