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

//____________________________________________________________________________
//
// 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__