2020-09-30 17:12:29 +02:00

466 lines
12 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: stgwrap.hxx
//
// Contents: IStorage and IStream wrappers for async docfile
//
// Classes: CAsyncStorage
// CAsyncRootStorage
// CAsyncStream
// CConnectionPoint
//
// Functions:
//
// History: 27-Dec-95 SusiA Created
//
//----------------------------------------------------------------------------
#ifndef __ASYNCEXPDF_HXX__
#define __ASYNCEXPDF_HXX__
#include "sinklist.hxx"
#include "filllkb.hxx"
#ifndef ASYNC
//BUGBUG: defined in dfmsp.hxx.
typedef DWORD LPSTGSECURITY;
//+---------------------------------------------------------------------------
//
// Class: CAsyncStorage
//
// Purpose: Wrap storage objects for Async Docfiles
//
// Interface:
//
// History: 28-Dec-95 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
class CAsyncStorage:
public IStorage,
public IConnectionPointContainer
{
public:
inline CAsyncStorage(IStorage *pstg, IFillLockBytes *pflb, BOOL fDefault);
inline ~CAsyncStorage(void);
// IUnknown
STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
// IStorage
STDMETHOD(CreateStream)(OLECHAR const *pwcsName,
DWORD grfMode,
DWORD reserved1,
DWORD reserved2,
IStream **ppstm);
STDMETHOD(OpenStream)(OLECHAR const *pwcsName,
void *reserved1,
DWORD grfMode,
DWORD reserved2,
IStream **ppstm);
STDMETHOD(CreateStorage)(OLECHAR const *pwcsName,
DWORD grfMode,
DWORD reserved1,
LPSTGSECURITY reserved2,
IStorage **ppstg);
STDMETHOD(OpenStorage)(OLECHAR const *pwcsName,
IStorage *pstgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage **ppstg);
STDMETHOD(CopyTo)(DWORD ciidExclude,
IID const *rgiidExclude,
SNB snbExclude,
IStorage *pstgDest);
STDMETHOD(MoveElementTo)(OLECHAR const *lpszName,
IStorage *pstgDest,
OLECHAR const *lpszNewName,
DWORD grfFlags);
STDMETHOD(Commit)(DWORD grfCommitFlags);
STDMETHOD(Revert)(void);
STDMETHOD(EnumElements)(DWORD reserved1,
void *reserved2,
DWORD reserved3,
IEnumSTATSTG **ppenm);
STDMETHOD(DestroyElement)(OLECHAR const *pwcsName);
STDMETHOD(RenameElement)(OLECHAR const *pwcsOldName,
OLECHAR const *pwcsNewName);
STDMETHOD(SetElementTimes)(const OLECHAR *lpszName,
FILETIME const *pctime,
FILETIME const *patime,
FILETIME const *pmtime);
STDMETHOD(SetClass)(REFCLSID clsid);
STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
//From IConnectionPointContainer
STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum);
STDMETHOD(FindConnectionPoint)(REFIID iid, IConnectionPoint **ppCP);
inline void SetAsyncFlags(DWORD asyncFlags);
inline CConnectionPoint * GetCP(void);
protected:
LONG _cReferences;
IStorage *_pRealStg;
IFillLockBytes *_pflb;
BOOL _fDefaultLockBytes;
CConnectionPoint _cpoint;
DWORD _asyncFlags;
};
inline CConnectionPoint *CAsyncStorage::GetCP(void)
{
return &_cpoint;
}
inline CAsyncStorage::CAsyncStorage(IStorage *pstg,
IFillLockBytes *pflb,
BOOL fDefault)
{
_cReferences = 1;
_pRealStg = pstg;
_pflb = pflb;
_pflb->AddRef();
_fDefaultLockBytes = fDefault;
_asyncFlags = 0;
}
inline CAsyncStorage::~CAsyncStorage(void)
{
_pflb->Release();
}
inline void CAsyncStorage::SetAsyncFlags(DWORD asyncFlags)
{
_asyncFlags = asyncFlags;
}
//+---------------------------------------------------------------------------
//
// Class: CAsyncRootStorage
//
// Purpose: Wrap Root Storage objects for Async Docfiles
//
// Interface:
//
// History: 28-Dec-95 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
class CAsyncRootStorage:
public IRootStorage,
public CAsyncStorage
{
public:
inline CAsyncRootStorage(IStorage *pstg,
IFillLockBytes *pflb,
BOOL fDefault);
// IUnknown
STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
// IRootStorage
STDMETHOD(SwitchToFile)(OLECHAR *ptcsFile);
};
inline CAsyncRootStorage::CAsyncRootStorage(IStorage *pstg,
IFillLockBytes *pflb,
BOOL fDefault)
:CAsyncStorage(pstg, pflb, fDefault)
{
}
//+---------------------------------------------------------------------------
//
// Class: CAsyncStream
//
// Purpose: Wrap Stream objects for Async Docfiles
//
// Interface:
//
// History: 28-Dec-95 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
class CAsyncStream:
public IStream,
public IConnectionPointContainer
{
public:
inline CAsyncStream(IStream *pstm, IFillLockBytes *pflb, BOOL fDefault);
inline ~CAsyncStream(void);
// From IUnknown
STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
STDMETHOD_(ULONG,AddRef)(void);
STDMETHOD_(ULONG,Release)(void);
// From IStream
STDMETHOD(Read)(VOID HUGEP *pv,
ULONG cb,
ULONG *pcbRead);
STDMETHOD(Write)(VOID const HUGEP *pv,
ULONG cb,
ULONG *pcbWritten);
STDMETHOD(Seek)(LARGE_INTEGER dlibMove,
DWORD dwOrigin,
ULARGE_INTEGER *plibNewPosition);
STDMETHOD(SetSize)(ULARGE_INTEGER cb);
STDMETHOD(CopyTo)(IStream *pstm,
ULARGE_INTEGER cb,
ULARGE_INTEGER *pcbRead,
ULARGE_INTEGER *pcbWritten);
STDMETHOD(Commit)(DWORD grfCommitFlags);
STDMETHOD(Revert)(void);
STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType);
STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType);
STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
STDMETHOD(Clone)(IStream **ppstm);
//From IConnectionPointContainer
STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum);
STDMETHOD(FindConnectionPoint)(REFIID iid, IConnectionPoint **ppCP);
inline void SetAsyncFlags(DWORD asyncFlags);
inline CConnectionPoint * GetCP(void);
private:
LONG _cReferences;
IStream *_pRealStm;
IFillLockBytes *_pflb;
BOOL _fDefaultLockBytes;
CConnectionPoint _cpoint;
DWORD _asyncFlags;
#ifdef SWEEPER
//On platforms where OLE has not been fixed, we need to cache a
// seek pointer in the wrapper to get around a bug.
ULONG _ulSeek;
#endif
};
inline CAsyncStream::CAsyncStream(IStream *pstm,
IFillLockBytes *pflb,
BOOL fDefault)
{
_cReferences = 1;
_pRealStm = pstm;
_pflb = pflb;
_pflb->AddRef();
_fDefaultLockBytes = fDefault;
_asyncFlags = 0;
#ifdef SWEEPER
_ulSeek = 0;
#endif
}
inline CAsyncStream::~CAsyncStream(void)
{
_pflb->Release();
}
inline CConnectionPoint *CAsyncStream::GetCP(void)
{
return &_cpoint;
}
inline void CAsyncStream::SetAsyncFlags(DWORD asyncFlags)
{
_asyncFlags = asyncFlags;
}
//+---------------------------------------------------------------------------
//
// Class: CAsyncEnumSTATSTG
//
// Purpose: Wrap EnumSTATSTG objects for Async Docfiles
//
// Interface:
//
// History: 28-Dec-95 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
class CAsyncEnum
: public IEnumSTATSTG,
public IConnectionPointContainer
{
public:
inline CAsyncEnum(IEnumSTATSTG *penum,
IFillLockBytes *pflb,
BOOL fDefault);
inline ~CAsyncEnum(void);
// From IUnknown
STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
STDMETHOD_(ULONG,AddRef)(void);
STDMETHOD_(ULONG,Release)(void);
// IEnumSTATSTG
STDMETHOD(Next)(ULONG celt, STATSTG FAR *rgelt, ULONG *pceltFetched);
STDMETHOD(Skip)(ULONG celt);
STDMETHOD(Reset)(void);
STDMETHOD(Clone)(IEnumSTATSTG **ppenm);
//From IConnectionPointContainer
STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum);
STDMETHOD(FindConnectionPoint)(REFIID iid, IConnectionPoint **ppCP);
inline void SetAsyncFlags(DWORD asyncFlags);
inline CConnectionPoint * GetCP(void);
private:
LONG _cReferences;
IEnumSTATSTG *_pRealEnum;
IFillLockBytes *_pflb;
BOOL _fDefaultLockBytes;
CConnectionPoint _cpoint;
DWORD _asyncFlags;
};
inline CAsyncEnum::CAsyncEnum(IEnumSTATSTG *penum,
IFillLockBytes *pflb,
BOOL fDefault)
{
_cReferences = 1;
_pRealEnum = penum;
_pflb = pflb;
_pflb->AddRef();
_fDefaultLockBytes = fDefault;
_asyncFlags = 0;
}
inline CAsyncEnum::~CAsyncEnum(void)
{
_pflb->Release();
}
inline CConnectionPoint *CAsyncEnum::GetCP(void)
{
return &_cpoint;
}
inline void CAsyncEnum::SetAsyncFlags(DWORD asyncFlags)
{
_asyncFlags = asyncFlags;
}
#define ISPENDINGERROR(x) ((x == E_PENDING) || (x == STG_E_PENDINGCONTROL))
#define TAKE_CRITICAL_SECTION if (_fDefaultLockBytes) \
((CFillLockBytes *)_pflb)->TakeCriticalSection()
#define RELEASE_CRITICAL_SECTION if (_fDefaultLockBytes) \
((CFillLockBytes *)_pflb)->ReleaseCriticalSection()
//The following construct is used repeatedly in the wrapper code to
// try a function, then perform notification if an E_PENDING error is
// returned.
#define DO_PENDING_LOOP(x) \
do \
{ \
TAKE_CRITICAL_SECTION; \
sc = x; \
if (!ISPENDINGERROR(sc)) \
{ \
RELEASE_CRITICAL_SECTION; \
break; \
} \
else if ((sc2 = _cpoint.Notify(sc, \
_pflb, \
_fDefaultLockBytes)) != S_OK) \
{ \
return ResultFromScode(sc2); \
} \
} while (TRUE);
#ifdef SWEEPER
//A bug on Sweeper platforms makes it necessary to cache the seek pointer
// in stream calls. This macro helps with that.
#define DO_PENDING_LOOP_WITH_SEEK(x, y) \
do \
{ \
TAKE_CRITICAL_SECTION; \
LARGE_INTEGER li; \
li.QuadPart = _ulSeek; \
sc = _pRealStm->Seek(li, STREAM_SEEK_SET, NULL); \
if (SUCCEEDED(sc)) \
sc = x; \
if ((ISPENDINGERROR(sc)) && ((sc2 = _cpoint.Notify(sc, \
_pflb, \
_fDefaultLockBytes)) \
!= S_OK)) \
{ \
if (y) \
*y = 0; \
return ResultFromScode(sc2); \
} \
else if (!ISPENDINGERROR(sc)) \
RELEASE_CRITICAL_SECTION; \
} while (ISPENDINGERROR(sc));
#define DO_PENDING_LOOP_WITH_SEEK_AND_LI(x, y) \
do \
{ \
TAKE_CRITICAL_SECTION; \
LARGE_INTEGER li; \
li.QuadPart = _ulSeek; \
sc = _pRealStm->Seek(li, STREAM_SEEK_SET, NULL); \
if (SUCCEEDED(sc)) \
sc = x; \
if ((ISPENDINGERROR(sc)) && ((sc2 = _cpoint.Notify(sc, \
_pflb, \
_fDefaultLockBytes)) \
!= S_OK)) \
{ \
if (y) \
(*y).QuadPart = 0; \
return ResultFromScode(sc2); \
} \
else if (!ISPENDINGERROR(sc)) \
RELEASE_CRITICAL_SECTION; \
} while (ISPENDINGERROR(sc));
#endif
#endif //!ASYNC
#endif // #ifndef __ASYNCEXPDF_HXX__