466 lines
12 KiB
C++
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__
|