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.
3216 lines
96 KiB
3216 lines
96 KiB
//+--------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1992.
|
|
//
|
|
// File: expdf.cxx
|
|
//
|
|
// Contents: Exposed DocFile implementation
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
#include <exphead.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <expdf.hxx>
|
|
#include <expst.hxx>
|
|
#include <expiter.hxx>
|
|
#include <pbstream.hxx>
|
|
#include <lock.hxx>
|
|
#include <marshl.hxx>
|
|
#include <logfile.hxx>
|
|
#include <rpubdf.hxx>
|
|
#include <expparam.hxx>
|
|
|
|
#include <olepfn.hxx>
|
|
|
|
#include <ole2sp.h>
|
|
|
|
#if WIN32 == 300
|
|
IMPLEMENT_UNWIND(CSafeAccess);
|
|
IMPLEMENT_UNWIND(CSafeSem);
|
|
#endif
|
|
|
|
extern WCHAR const wcsContents[];
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::CExposedDocFile, public
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
// Arguments: [pdf] - Public DocFile
|
|
// [pdfb] - DocFile basis
|
|
// [ppc] - Context
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
CExposedDocFile::CExposedDocFile(CPubDocFile *pdf,
|
|
CDFBasis *pdfb,
|
|
CPerContext *ppc)
|
|
: CPropertySetStorage(MAPPED_STREAM_QI),
|
|
_PropertyBagEx( DFlagsToMode( pdf->GetDFlags() ))
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedDocFile::CExposedDocFile("
|
|
"%p, %p, %p)\n", pdf, pdfb, ppc));
|
|
|
|
|
|
_ppc = ppc;
|
|
_pdf = P_TO_BP(CBasedPubDocFilePtr, pdf);
|
|
_pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb);
|
|
_pdfb->vAddRef();
|
|
_cReferences = 1;
|
|
_sig = CEXPOSEDDOCFILE_SIG;
|
|
#if WIN32 >= 300
|
|
_pIAC = NULL;
|
|
#endif
|
|
|
|
// Initialize CPropertySetStorage and CPropertyBagEx
|
|
|
|
CPropertySetStorage::Init( static_cast<IStorage*>(this), static_cast<IBlockingLock*>(this),
|
|
FALSE ); // fControlLifetimes (=> Don't addref)
|
|
|
|
_PropertyBagEx.Init( static_cast<IPropertySetStorage*>(this), // Not addref-ed
|
|
static_cast<IBlockingLock*>(this) ); // Not addref-ed
|
|
|
|
|
|
//
|
|
// CoQueryReleaseObject needs to have the address of the exposed docfiles
|
|
// query interface routine.
|
|
//
|
|
if (adwQueryInterfaceTable[QI_TABLE_CExposedDocFile] == 0)
|
|
{
|
|
adwQueryInterfaceTable[QI_TABLE_CExposedDocFile] =
|
|
**(ULONG_PTR **)((IStorage *)this);
|
|
}
|
|
|
|
#ifdef COORD
|
|
_ulLock = _cbSizeBase = _cbSizeOrig = 0;
|
|
_sigMSF = 0;
|
|
#endif
|
|
|
|
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CExposedDocFile\n"));
|
|
}
|
|
|
|
|
|
SCODE CExposedDocFile::InitMarshal(DWORD dwAsyncFlags,
|
|
IDocfileAsyncConnectionPoint *pdacp)
|
|
{
|
|
return _cpoint.InitMarshal(this, dwAsyncFlags, pdacp);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::~CExposedDocFile, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// History: 23-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
CExposedDocFile::~CExposedDocFile(void)
|
|
{
|
|
BOOL fClose = FALSE;
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedDocFile::~CExposedDocFile\n"));
|
|
olAssert(_cReferences == 0);
|
|
|
|
//In order to call into the tree, we need to take the mutex.
|
|
//The mutex may get deleted in _ppc->Release(), so we can't
|
|
//release it here. The mutex actually gets released in
|
|
//CPerContext::Release() or in the CPerContext destructor.
|
|
|
|
//If _ppc is NULL, we're partially constructed and don't need to
|
|
//worry.
|
|
SCODE sc;
|
|
|
|
#if WIN32 >= 300
|
|
if (_pIAC != NULL)
|
|
{
|
|
_pIAC->Release();
|
|
_pIAC = NULL;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(MULTIHEAP)
|
|
// TakeSem and ReleaseSem are moved to the Release Method
|
|
// so that the deallocation for this object is protected
|
|
if (_ppc)
|
|
{
|
|
sc = TakeSem();
|
|
SetWriteAccess();
|
|
olAssert(SUCCEEDED(sc));
|
|
}
|
|
|
|
|
|
#ifdef ASYNC
|
|
IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
|
|
#endif
|
|
#endif //MULTIHEAP
|
|
|
|
if (_pdf)
|
|
{
|
|
// If we're the last reference on a root object
|
|
// we close the context because all children will become
|
|
// reverted so it is no longer necessary
|
|
if (_pdf->GetRefCount() == 1 && _pdf->IsRoot())
|
|
fClose = TRUE;
|
|
|
|
_pdf->CPubDocFile::vRelease();
|
|
}
|
|
if (_pdfb)
|
|
_pdfb->CDFBasis::vRelease();
|
|
#if !defined(MULTIHEAP)
|
|
if (_ppc)
|
|
{
|
|
if (fClose)
|
|
_ppc->Close();
|
|
if (_ppc->Release() > 0)
|
|
ReleaseSem(sc);
|
|
}
|
|
#ifdef ASYNC
|
|
//Mutex has been released, so we can release the connection point
|
|
// without fear of deadlock.
|
|
if (pdacp != NULL)
|
|
pdacp->Release();
|
|
#endif
|
|
#endif // MULTIHEAP
|
|
|
|
_sig = CEXPOSEDDOCFILE_SIGDEL;
|
|
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::~CExposedDocFile\n"));
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::Release, public
|
|
//
|
|
// Synopsis: Releases resources for a CExposedDocFile
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CExposedDocFile::Release(void)
|
|
{
|
|
LONG lRet;
|
|
|
|
olLog(("%p::In CExposedDocFile::Release()\n", this));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::Release()\n"));
|
|
|
|
if (FAILED(Validate()))
|
|
return 0;
|
|
olAssert(_cReferences > 0);
|
|
lRet = InterlockedDecrement(&_cReferences);
|
|
if (lRet == 0)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
sc = _PropertyBagEx.Commit( STGC_DEFAULT );
|
|
olAssert(SUCCEEDED(sc));
|
|
|
|
sc = _PropertyBagEx.ShutDown();
|
|
olAssert(SUCCEEDED(sc));
|
|
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
CPerContext *ppc = _ppc;
|
|
|
|
if (_ppc)
|
|
{
|
|
sc = TakeSem();
|
|
SetWriteAccess();
|
|
olAssert(SUCCEEDED(sc));
|
|
}
|
|
#ifdef ASYNC
|
|
IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
|
|
#endif
|
|
BOOL fClose = (_pdf) && (_pdf->GetRefCount()==1) && _pdf->IsRoot();
|
|
#endif //MULTIHEAP
|
|
delete this;
|
|
#ifdef MULTIHEAP
|
|
if (ppc)
|
|
{
|
|
if (fClose)
|
|
ppc->Close();
|
|
if (ppc->Release() == 0)
|
|
g_smAllocator.Uninit();
|
|
else
|
|
if (SUCCEEDED(sc)) ppc->UntakeSem();
|
|
}
|
|
#ifdef ASYNC
|
|
//Mutex has been released, so we can release the connection point
|
|
// without fear of deadlock.
|
|
if (pdacp != NULL)
|
|
pdacp->Release();
|
|
#endif
|
|
#endif
|
|
}
|
|
else if (lRet < 0)
|
|
lRet = 0;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::Release %p() => %lu\n",
|
|
this, lRet));
|
|
olLog(("%p::Out CExposedDocFile::Release(). ret == %lu\n", this, lRet));
|
|
FreeLogFile();
|
|
return (ULONG)lRet;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::CheckCopyTo, private
|
|
//
|
|
// Synopsis: Checks for CopyTo legality
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Jul-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
inline SCODE CExposedDocFile::CheckCopyTo(void)
|
|
{
|
|
return _pdfb->GetCopyBase() != NULL &&
|
|
_pdf->IsAtOrAbove(_pdfb->GetCopyBase()) ?
|
|
STG_E_ACCESSDENIED : S_OK;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::ConvertInternalStream, private
|
|
//
|
|
// Synopsis: Converts an internal stream to a storage
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [pdfExp] - Destination docfile
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Jun-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
static WCHAR const wcsIllegalName[] = {'\\', '\0'};
|
|
|
|
SCODE CExposedDocFile::ConvertInternalStream(CExposedDocFile *pdfExp)
|
|
{
|
|
CPubStream *pstFrom, *pstTo;
|
|
SCODE sc;
|
|
CDfName const dfnIllegal(wcsIllegalName);
|
|
CDfName const dfnContents(wcsContents);
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedDocFile::ConvertInternalStream(%p)\n",
|
|
pdfExp));
|
|
olChk(_pdf->GetStream(&dfnIllegal, DF_READWRITE | DF_DENYALL, &pstFrom));
|
|
olChkTo(EH_pstFrom, pdfExp->GetPub()->CreateStream(&dfnContents,
|
|
DF_WRITE | DF_DENYALL,
|
|
&pstTo));
|
|
olChkTo(EH_pstTo, CopySStreamToSStream(pstFrom->GetSt(),
|
|
pstTo->GetSt()));
|
|
olChkTo(EH_pstTo, _pdf->DestroyEntry(&dfnIllegal, FALSE));
|
|
sc = S_OK;
|
|
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::ConvertInternalStream\n"));
|
|
// Fall through
|
|
EH_pstTo:
|
|
pstTo->CPubStream::vRelease();
|
|
EH_pstFrom:
|
|
pstFrom->CPubStream::vRelease();
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::CreateEntry, private
|
|
//
|
|
// Synopsis: Creates elements, used in CreateStream, CreateStorage.
|
|
//
|
|
// Arguments: [pdfn] - Name
|
|
// [dwType] - Entry type
|
|
// [grfMode] - Access mode
|
|
// [ppv] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppv]
|
|
//
|
|
// History: 18-Dec-92 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
SCODE CExposedDocFile::CreateEntry(CDfName const *pdfn,
|
|
DWORD dwType,
|
|
DWORD grfMode,
|
|
void **ppv)
|
|
{
|
|
SCODE sc;
|
|
SEntryBuffer eb;
|
|
BOOL fRenamed = FALSE;
|
|
CPubStream *pst;
|
|
CExposedStream *pstExp;
|
|
CPubDocFile *pdf;
|
|
CExposedDocFile *pdfExp;
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedDocFile::CreateEntry:%p("
|
|
"%p, %lX, %lX, %p)\n", this, pdfn, dwType, grfMode, ppv));
|
|
olChk(EnforceSingle(grfMode));
|
|
|
|
// 3/11/93 - Demand scratch when opening/creating transacted
|
|
if ((grfMode & STGM_TRANSACTED) == STGM_TRANSACTED)
|
|
{
|
|
olChk(_ppc->GetDirty()->InitScratch());
|
|
}
|
|
|
|
if (grfMode & (STGM_CREATE | STGM_CONVERT))
|
|
{
|
|
if (FAILED(sc = _pdf->IsEntry(pdfn, &eb)))
|
|
{
|
|
if (sc != STG_E_FILENOTFOUND)
|
|
olErr(EH_Err, sc);
|
|
}
|
|
else if (eb.dwType == dwType && (grfMode & STGM_CREATE))
|
|
olChk(_pdf->DestroyEntry(pdfn, FALSE));
|
|
else if (eb.dwType == STGTY_STREAM && (grfMode & STGM_CONVERT) &&
|
|
dwType == STGTY_STORAGE)
|
|
{
|
|
CDfName const dfnIllegal(wcsIllegalName);
|
|
|
|
olChk(_pdf->RenameEntry(pdfn, &dfnIllegal));
|
|
fRenamed = TRUE;
|
|
}
|
|
else
|
|
olErr(EH_Err, STG_E_FILEALREADYEXISTS);
|
|
}
|
|
if (REAL_STGTY(dwType) == STGTY_STREAM)
|
|
{
|
|
olChk(_pdf->CreateStream(pdfn, ModeToDFlags(grfMode), &pst));
|
|
olMemTo(EH_pst, pstExp = new (_pdfb->GetMalloc()) CExposedStream);
|
|
olChkTo(EH_pstExp, pstExp->Init(pst, BP_TO_P(CDFBasis *, _pdfb),
|
|
_ppc, NULL));
|
|
_ppc->AddRef();
|
|
#ifdef ASYNC
|
|
if (_cpoint.IsInitialized())
|
|
{
|
|
olChkTo(EH_connSt, pstExp->InitConnection(&_cpoint));
|
|
}
|
|
#endif
|
|
*ppv = pstExp;
|
|
}
|
|
else
|
|
{
|
|
olAssert(REAL_STGTY(dwType) == STGTY_STORAGE);
|
|
olChk(_pdf->CreateDocFile(pdfn, ModeToDFlags(grfMode), &pdf));
|
|
olMemTo(EH_pdf, pdfExp = new (_pdfb->GetMalloc())
|
|
CExposedDocFile(pdf, BP_TO_P(CDFBasis *, _pdfb), _ppc));
|
|
_ppc->AddRef();
|
|
|
|
if (_cpoint.IsInitialized())
|
|
{
|
|
olChkTo(EH_pdfExpInit, pdfExp->InitConnection(&_cpoint));
|
|
}
|
|
|
|
// If we've renamed the original stream for conversion, convert
|
|
if (fRenamed)
|
|
{
|
|
olChkTo(EH_pdfExpInit, ConvertInternalStream(pdfExp));
|
|
sc = STG_S_CONVERTED;
|
|
}
|
|
|
|
*ppv = pdfExp;
|
|
}
|
|
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CreateEntry\n"));
|
|
return sc;
|
|
|
|
EH_connSt:
|
|
pstExp->Release();
|
|
goto EH_Del;
|
|
|
|
EH_pstExp:
|
|
delete pstExp;
|
|
EH_pst:
|
|
pst->CPubStream::vRelease();
|
|
goto EH_Del;
|
|
|
|
EH_pdfExpInit:
|
|
pdfExp->Release();
|
|
goto EH_Del;
|
|
EH_pdf:
|
|
pdf->CPubDocFile::vRelease();
|
|
// Fall through
|
|
EH_Del:
|
|
olVerSucc(_pdf->DestroyEntry(pdfn, TRUE));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::OpenEntry, private
|
|
//
|
|
// Synopsis: Opens elements, used in OpenStream, OpenStorage.
|
|
//
|
|
// Arguments: [pdfn] - Name
|
|
// [dwType] - Entry type
|
|
// [grfMode] - Access mode
|
|
// [ppv] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppv]
|
|
//
|
|
// History: 18-Dec-92 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
SCODE CExposedDocFile::OpenEntry(CDfName const *pdfn,
|
|
DWORD dwType,
|
|
DWORD grfMode,
|
|
void **ppv)
|
|
{
|
|
SCODE sc;
|
|
CPubDocFile *pdf;
|
|
CExposedDocFile *pdfExp;
|
|
CPubStream *pst;
|
|
CExposedStream *pstExp;
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedDocFile::OpenEntry:%p("
|
|
"%p, %lX, %lX, %p)\n", this, pdfn, dwType, grfMode, ppv));
|
|
olChk(EnforceSingle(grfMode));
|
|
|
|
// 3/11/93 - Demand scratch when opening/creating transacted
|
|
if ((grfMode & STGM_TRANSACTED) == STGM_TRANSACTED)
|
|
{
|
|
olChk(_ppc->GetDirty()->InitScratch());
|
|
}
|
|
|
|
if (REAL_STGTY(dwType) == STGTY_STREAM)
|
|
{
|
|
olChk(_pdf->GetStream(pdfn, ModeToDFlags(grfMode), &pst));
|
|
olMemTo(EH_pst, pstExp = new (_pdfb->GetMalloc()) CExposedStream);
|
|
olChkTo(EH_pstExp, pstExp->Init(pst, BP_TO_P(CDFBasis *, _pdfb),
|
|
_ppc, NULL));
|
|
_ppc->AddRef();
|
|
|
|
if (_cpoint.IsInitialized())
|
|
{
|
|
olChkTo(EH_connSt, pstExp->InitConnection(&_cpoint));
|
|
}
|
|
|
|
*ppv = pstExp;
|
|
}
|
|
else
|
|
{
|
|
olAssert(REAL_STGTY(dwType) == STGTY_STORAGE);
|
|
olChk(_pdf->GetDocFile(pdfn, ModeToDFlags(grfMode), &pdf));
|
|
olMemTo(EH_pdf, pdfExp = new (_pdfb->GetMalloc())
|
|
CExposedDocFile(pdf, BP_TO_P(CDFBasis *, _pdfb), _ppc));
|
|
_ppc->AddRef();
|
|
|
|
if (_cpoint.IsInitialized())
|
|
{
|
|
olChkTo(EH_connDf, pdfExp->InitConnection(&_cpoint));
|
|
}
|
|
|
|
*ppv = pdfExp;
|
|
}
|
|
|
|
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::OpenEntry\n"));
|
|
return S_OK;
|
|
EH_connSt:
|
|
pstExp->Release();
|
|
return sc;
|
|
|
|
EH_pstExp:
|
|
delete pstExp;
|
|
// Fall through to clean up CPubStream
|
|
EH_pst:
|
|
pst->CPubStream::vRelease();
|
|
return sc;
|
|
|
|
EH_connDf:
|
|
pdfExp->Release();
|
|
return sc;
|
|
|
|
EH_pdf:
|
|
pdf->CPubDocFile::vRelease();
|
|
// Fall through
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::CreateStream, public
|
|
//
|
|
// Synopsis: Creates a stream
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [grfMode] - Permissions
|
|
// [reserved1]
|
|
// [reserved2]
|
|
// [ppstm] - Stream return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstm]
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::CreateStream(WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
DWORD reserved1,
|
|
DWORD reserved2,
|
|
IStream **ppstm)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
SafeCExposedStream pestm;
|
|
CDfName dfn;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::CreateStream("
|
|
"%ws, %lX, %lu, %lu, %p)\n", pwcsName, grfMode, reserved1,
|
|
reserved2, ppstm));
|
|
olLog(("%p::In CExposedDocFile::CreateStream(%ws, %lX, %lu, %lu, %p)\n",
|
|
this, pwcsName, grfMode, reserved1, reserved2, ppstm));
|
|
|
|
OL_VALIDATE(CreateStream(pwcsName,
|
|
grfMode,
|
|
reserved1,
|
|
reserved2,
|
|
ppstm));
|
|
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
olChk(CheckCopyTo());
|
|
SafeWriteAccess();
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
|
|
dfn.Set(pwcsName);
|
|
sc = CreateEntry(&dfn, STGTY_STREAM, grfMode, (void **)&pestm);
|
|
END_PENDING_LOOP;
|
|
|
|
if (SUCCEEDED(sc))
|
|
TRANSFER_INTERFACE(pestm, IStream, ppstm);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::CreateStream => %p\n",
|
|
*ppstm));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::CreateStream(). "
|
|
"*ppstm == %p, ret == %lx\n", this, *ppstm, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::OpenStream, public
|
|
//
|
|
// Synopsis: Opens an existing stream
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [reserved1]
|
|
// [grfMode] - Permissions
|
|
// [reserved2]
|
|
// [ppstm] - Stream return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstm]
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::OpenStream(WCHAR const *pwcsName,
|
|
void *reserved1,
|
|
DWORD grfMode,
|
|
DWORD reserved2,
|
|
IStream **ppstm)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
SafeCExposedStream pestm;
|
|
CDfName dfn;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::OpenStream("
|
|
"%ws, %p, %lX, %lu, %p)\n", pwcsName, reserved1,
|
|
grfMode, reserved2, ppstm));
|
|
olLog(("%p::In CExposedDocFile::OpenStream(%ws, %lu %lX, %lu, %p)\n",
|
|
this, pwcsName, reserved1, grfMode, reserved2, ppstm));
|
|
|
|
OL_VALIDATE(OpenStream(pwcsName,
|
|
reserved1,
|
|
grfMode,
|
|
reserved2,
|
|
ppstm));
|
|
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeReadAccess();
|
|
|
|
dfn.Set(pwcsName);
|
|
sc = OpenEntry(&dfn, STGTY_STREAM, grfMode, (void **)&pestm);
|
|
END_PENDING_LOOP;
|
|
|
|
if (SUCCEEDED(sc))
|
|
TRANSFER_INTERFACE(pestm, IStream, ppstm);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::OpenStream => %p\n",
|
|
*ppstm));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::OpenStream(). "
|
|
"*ppstm == %p, ret == %lx\n", this, *ppstm, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::CreateStorage, public
|
|
//
|
|
// Synopsis: Creates an embedded DocFile
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [grfMode] - Permissions
|
|
// [reserved1]
|
|
// [reserved2]
|
|
// [ppstg] - New DocFile return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstg]
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::CreateStorage(
|
|
WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
DWORD reserved1,
|
|
LPSTGSECURITY reserved2,
|
|
IStorage **ppstg)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
SafeCExposedDocFile pedf;
|
|
CDfName dfn;
|
|
|
|
olLog(("%p::In CExposedDocFile::CreateStorage(%ws, %lX, %lu, %lu, %p)\n",
|
|
this, pwcsName, grfMode, reserved1, reserved2, ppstg));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::CreateStorage:%p("
|
|
"%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
|
|
reserved1, reserved2, ppstg));
|
|
|
|
OL_VALIDATE(CreateStorage(pwcsName,
|
|
grfMode,
|
|
reserved1,
|
|
reserved2,
|
|
ppstg));
|
|
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
olChk(CheckCopyTo());
|
|
SafeWriteAccess();
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
|
|
dfn.Set(pwcsName);
|
|
sc = CreateEntry(&dfn, STGTY_STORAGE, grfMode, (void **)&pedf);
|
|
END_PENDING_LOOP;
|
|
|
|
if (SUCCEEDED(sc))
|
|
TRANSFER_INTERFACE(pedf, IStorage, ppstg);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::CreateStorage => %p\n",
|
|
*ppstg));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::CreateStorage(). "
|
|
"*ppstg == %p, ret == %lX\n", this, *ppstg, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::OpenStorage, public
|
|
//
|
|
// Synopsis: Gets an existing embedded DocFile
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [pstgPriority] - Priority reopens
|
|
// [grfMode] - Permissions
|
|
// [snbExclude] - Priority reopens
|
|
// [reserved]
|
|
// [ppstg] - DocFile return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstg]
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::OpenStorage(WCHAR const *pwcsName,
|
|
IStorage *pstgPriority,
|
|
DWORD grfMode,
|
|
SNBW snbExclude,
|
|
DWORD reserved,
|
|
IStorage **ppstg)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
SafeCExposedDocFile pdfExp;
|
|
CDfName dfn;
|
|
|
|
olLog(("%p::In CExposedDocFile::OpenStorage(%ws, %p, %lX, %p, %lu, %p)\n",
|
|
this, pwcsName, pstgPriority, grfMode, snbExclude, reserved,
|
|
ppstg));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::OpenStorage:%p("
|
|
"%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority,
|
|
grfMode, snbExclude, reserved, ppstg));
|
|
|
|
|
|
OL_VALIDATE(OpenStorage(pwcsName,
|
|
pstgPriority,
|
|
grfMode,
|
|
snbExclude,
|
|
reserved,
|
|
ppstg));
|
|
|
|
olChk(Validate());
|
|
if (snbExclude != NULL)
|
|
olErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeReadAccess();
|
|
|
|
dfn.Set(pwcsName);
|
|
sc = OpenEntry(&dfn, STGTY_STORAGE, grfMode, (void **)&pdfExp);
|
|
END_PENDING_LOOP;
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
TRANSFER_INTERFACE(pdfExp, IStorage, ppstg);
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::OpenStorage => %p\n",
|
|
*ppstg));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::OpenStorage(). "
|
|
"*ppstg == %p, ret == %lX\n", this, *ppstg, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::MakeCopyFlags, public
|
|
//
|
|
// Synopsis: Translates IID array into bit fields
|
|
//
|
|
// Arguments: [ciidExclude] - Count of IIDs
|
|
// [rgiidExclude] - IIDs not to copy
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 23-Dec-92 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
DWORD CExposedDocFile::MakeCopyFlags(DWORD ciidExclude,
|
|
IID const *rgiidExclude)
|
|
{
|
|
DWORD dwCopyFlags;
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedDocFile::MakeCopyFlags(%lu, %p)\n",
|
|
ciidExclude, rgiidExclude));
|
|
// Copy everything by default
|
|
dwCopyFlags = COPY_ALL;
|
|
for (; ciidExclude > 0; ciidExclude--, rgiidExclude++)
|
|
if (IsEqualIID(*rgiidExclude, IID_IStorage))
|
|
dwCopyFlags &= ~COPY_STORAGES;
|
|
else if (IsEqualIID(*rgiidExclude, IID_IStream))
|
|
dwCopyFlags &= ~COPY_STREAMS;
|
|
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::MakeCopyFlags\n"));
|
|
return dwCopyFlags;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::CopyTo, public
|
|
//
|
|
// Synopsis: Makes a copy of a DocFile
|
|
//
|
|
// Arguments: [ciidExclude] - Length of rgiid array
|
|
// [rgiidExclude] - Array of IIDs to exclude
|
|
// [snbExclude] - Names to exclude
|
|
// [pstgDest] - Parent of copy
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::CopyTo(DWORD ciidExclude,
|
|
IID const *rgiidExclude,
|
|
SNBW snbExclude,
|
|
IStorage *pstgDest)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
SAFE_SEM;
|
|
DWORD i;
|
|
|
|
|
|
|
|
olLog(("%p::In CExposedDocFile::CopyTo(%lu, %p, %p, %p)\n",
|
|
this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::CopyTo(%lu, %p, %p, %p)\n",
|
|
ciidExclude, rgiidExclude, snbExclude, pstgDest));
|
|
|
|
OL_VALIDATE(CopyTo(ciidExclude,
|
|
rgiidExclude,
|
|
snbExclude,
|
|
pstgDest));
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
olChk(_pdf->CheckReverted());
|
|
|
|
olAssert(_pdfb->GetCopyBase() == NULL);
|
|
_pdfb->SetCopyBase(BP_TO_P(CPubDocFile *, _pdf));
|
|
|
|
// Flush all descendant property set buffers so that their
|
|
// underlying Streams (which are about to be copied) are
|
|
// up to date.
|
|
|
|
SetWriteAccess();
|
|
olChkTo(EH_Loop, _pdf->FlushBufferedData(0));
|
|
ClearWriteAccess();
|
|
|
|
// Perform the copy.
|
|
|
|
sc = CopyDocFileToIStorage(_pdf->GetDF(), pstgDest, snbExclude,
|
|
MakeCopyFlags(ciidExclude, rgiidExclude));
|
|
EH_Loop:
|
|
_pdfb->SetCopyBase(NULL);
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::CopyTo\n"));
|
|
EH_Err:
|
|
_pdfb->SetCopyBase(NULL);
|
|
olLog(("%p::Out ExposedDocFile::CopyTo(). ret == %lX\n", this, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::Commit, public
|
|
//
|
|
// Synopsis: Commits transacted changes
|
|
//
|
|
// Arguments: [dwFlags] - DFC_*
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::Commit(DWORD dwFlags)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
|
|
olLog(("%p::In CExposedDocFile::Commit(%lX)\n",this, dwFlags));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::Commit(%lX)\n", dwFlags));
|
|
|
|
OL_VALIDATE(Commit(dwFlags));
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
|
|
olChk( _PropertyBagEx.Commit( dwFlags ));
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
if (_pdf->GetTransactedDepth() <= 1) // topmost transacted level or direct
|
|
{
|
|
if (_pdfb->DirectWriterMode() && (*_ppc->GetRecursionCount()) == 0)
|
|
olChk(STG_E_ACCESSDENIED);
|
|
}
|
|
#endif
|
|
|
|
olChkTo(EH_Loop, _pdf->Commit(dwFlags));
|
|
|
|
#if WIN32 >= 300
|
|
if (SUCCEEDED(sc) && _pIAC != NULL)
|
|
sc = _pIAC->CommitAccessRights(0);
|
|
#endif
|
|
|
|
EH_Loop:
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::Commit\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::Commit(). ret == %lx\n",this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::Revert, public
|
|
//
|
|
// Synopsis: Reverts transacted changes
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::Revert(void)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
|
|
olLog(("%p::In CExposedDocFile::Revert()\n", this));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::Revert\n"));
|
|
|
|
OL_VALIDATE(Revert());
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
|
|
olChkTo(EH_Loop, _pdf->Revert());
|
|
|
|
#if WIN32 >= 300
|
|
if (SUCCEEDED(sc) && _pIAC != NULL)
|
|
sc = _pIAC->RevertAccessRights();
|
|
#endif
|
|
EH_Loop:
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::Revert\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::Revert(). ret == %lx\n", this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::EnumElements, public
|
|
//
|
|
// Synopsis: Starts an iterator
|
|
//
|
|
// Arguments: [reserved1]
|
|
// [reserved2]
|
|
// [reserved3]
|
|
// [ppenm] - Enumerator return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppenm]
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::EnumElements(DWORD reserved1,
|
|
void *reserved2,
|
|
DWORD reserved3,
|
|
IEnumSTATSTG **ppenm)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
SafeCExposedIterator pdiExp;
|
|
CDfName dfnTmp;
|
|
|
|
olLog(("%p::In CExposedDocFile::EnumElements(%lu, %p, %lu, %p)\n",
|
|
this, reserved1, reserved2, reserved3, ppenm));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::EnumElements(%p)\n",
|
|
ppenm));
|
|
|
|
OL_VALIDATE(EnumElements(reserved1,
|
|
reserved2,
|
|
reserved3,
|
|
ppenm));
|
|
|
|
olChk(Validate());
|
|
|
|
//ASYNC Note: It doesn't appear that there's any way that this
|
|
// function can fail with STG_E_PENDING, so we don't need a pending
|
|
// loop here.
|
|
olChk(TakeSafeSem());
|
|
if (!P_READ(_pdf->GetDFlags()))
|
|
olErr(EH_Err, STG_E_ACCESSDENIED);
|
|
olChk(_pdf->CheckReverted());
|
|
SafeReadAccess();
|
|
|
|
pdiExp.Attach(new CExposedIterator(BP_TO_P(CPubDocFile *, _pdf),
|
|
&dfnTmp,
|
|
BP_TO_P(CDFBasis *, _pdfb),
|
|
_ppc));
|
|
olMem((CExposedIterator *)pdiExp);
|
|
_ppc->AddRef();
|
|
#ifdef ASYNC
|
|
if (_cpoint.IsInitialized())
|
|
{
|
|
olChkTo(EH_Exp, pdiExp->InitConnection(&_cpoint));
|
|
}
|
|
#endif
|
|
TRANSFER_INTERFACE(pdiExp, IEnumSTATSTG, ppenm);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::EnumElements => %p\n",
|
|
*ppenm));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::EnumElements(). ret == %lx\n",this, sc));
|
|
return ResultFromScode(sc);
|
|
EH_Exp:
|
|
pdiExp->Release();
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::DestroyElement, public
|
|
//
|
|
// Synopsis: Permanently deletes an element of a DocFile
|
|
//
|
|
// Arguments: [pwcsName] - Name of element
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::DestroyElement(WCHAR const *pwcsName)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
CDfName dfn;
|
|
|
|
olLog(("%p::In CExposedDocFile::DestroyElement(%ws)\n", this, pwcsName));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::DestroyElement(%ws)\n",
|
|
pwcsName));
|
|
|
|
OL_VALIDATE(DestroyElement(pwcsName));
|
|
|
|
olChk(Validate());
|
|
dfn.Set(pwcsName);
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
|
|
sc = _pdf->DestroyEntry(&dfn, FALSE);
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::DestroyElement\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::DestroyElement(). ret == %lx\n",
|
|
this, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::MoveElementTo(WCHAR const *pwcsName,
|
|
IStorage *pstgParent,
|
|
OLECHAR const *ptcsNewName,
|
|
DWORD grfFlags)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
olLog(("%p::In CExposedDocFile::MoveElementTo("
|
|
"%ws, %p, " OLEFMT ", %lu)\n",
|
|
this, pwcsName, pstgParent, ptcsNewName, grfFlags));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::MoveElementTo("
|
|
"%ws, %p, " OLEFMT ", %lu)\n",
|
|
pwcsName, pstgParent, ptcsNewName, grfFlags));
|
|
|
|
OL_VALIDATE(MoveElementTo(pwcsName,
|
|
pstgParent,
|
|
ptcsNewName,
|
|
grfFlags));
|
|
|
|
olChk(Validate());
|
|
|
|
#ifdef ASYNC
|
|
//ASYNC Note: We don't use the normal pending loop macros here because
|
|
// we have no safe sem and need to pass a NULL.
|
|
do
|
|
{
|
|
#endif
|
|
sc = MoveElementWorker(pwcsName,
|
|
pstgParent,
|
|
ptcsNewName,
|
|
grfFlags);
|
|
#ifdef ASYNC
|
|
if (!ISPENDINGERROR(sc))
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
SCODE sc2;
|
|
sc2 = _cpoint.Notify(sc,
|
|
_ppc->GetBase(),
|
|
_ppc,
|
|
NULL);
|
|
if (sc2 != S_OK)
|
|
{
|
|
return ResultFromScode(sc2);
|
|
}
|
|
}
|
|
} while (TRUE);
|
|
#endif
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::MoveElementTo(). ret == %lx\n",
|
|
this, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::MoveElementToWorker, public
|
|
//
|
|
// Synopsis: Move an element of a DocFile to an IStorage
|
|
//
|
|
// Arguments: [pwcsName] - Current name
|
|
// [ptcsNewName] - New name
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Algorithm: Open source as storage or stream (whatever works)
|
|
// Create appropriate destination
|
|
// Copy source to destination
|
|
// Set create time of destination equal to create time of source
|
|
// If appropriate, delete source
|
|
//
|
|
// History: 10-Nov-92 AlexT Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
SCODE CExposedDocFile::MoveElementWorker(WCHAR const *pwcsName,
|
|
IStorage *pstgParent,
|
|
OLECHAR const *ptcsNewName,
|
|
DWORD grfFlags)
|
|
{
|
|
IUnknown *punksrc = NULL;
|
|
SCODE sc;
|
|
IUnknown *punkdst = NULL;
|
|
IStorage *pstgsrc;
|
|
STATSTG statstg;
|
|
BOOL fCreate = TRUE;
|
|
|
|
// Determine source type
|
|
sc = GetScode(OpenStorage(pwcsName, NULL,
|
|
STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
|
|
NULL, NULL, &pstgsrc));
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
HRESULT hr;
|
|
|
|
// It's a storage
|
|
punksrc = pstgsrc;
|
|
|
|
IStorage *pstgdst;
|
|
olHChkTo(EH_UnkSrc, pstgsrc->Stat(&statstg, STATFLAG_NONAME));
|
|
|
|
hr = pstgParent->CreateStorage(ptcsNewName,
|
|
STGM_DIRECT | STGM_WRITE |
|
|
STGM_SHARE_EXCLUSIVE | STGM_FAILIFTHERE,
|
|
0, 0, &pstgdst);
|
|
if (DfGetScode(hr) == STG_E_FILEALREADYEXISTS &&
|
|
grfFlags == STGMOVE_COPY)
|
|
{
|
|
fCreate = FALSE;
|
|
//If we're opening an existing thing for merging, we need
|
|
// read and write permissions so we can traverse the tree.
|
|
hr = pstgParent->OpenStorage(ptcsNewName, NULL,
|
|
STGM_DIRECT | STGM_READWRITE |
|
|
STGM_SHARE_EXCLUSIVE, NULL,
|
|
0, &pstgdst);
|
|
}
|
|
olHChkTo(EH_UnkSrc, hr);
|
|
|
|
punkdst = pstgdst;
|
|
|
|
sc = DfGetScode(pstgsrc->CopyTo(0, NULL, NULL, pstgdst));
|
|
}
|
|
else if (sc == STG_E_FILENOTFOUND)
|
|
{
|
|
// Try opening it as a stream
|
|
HRESULT hr;
|
|
|
|
IStream *pstmsrc, *pstmdst;
|
|
olHChk(OpenStream(pwcsName, NULL,
|
|
STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
|
|
NULL, &pstmsrc));
|
|
|
|
// It's a stream
|
|
punksrc = pstmsrc;
|
|
|
|
olHChkTo(EH_UnkSrc, pstmsrc->Stat(&statstg, STATFLAG_NONAME));
|
|
|
|
hr = pstgParent->CreateStream(ptcsNewName,
|
|
STGM_DIRECT | STGM_WRITE |
|
|
STGM_SHARE_EXCLUSIVE |
|
|
STGM_FAILIFTHERE,
|
|
0, 0, &pstmdst);
|
|
if (DfGetScode(hr) == STG_E_FILEALREADYEXISTS &&
|
|
grfFlags == STGMOVE_COPY)
|
|
{
|
|
ULARGE_INTEGER uli;
|
|
uli.QuadPart = 0;
|
|
|
|
fCreate = FALSE;
|
|
//Try to open it instead
|
|
//Note: We do this instead of doing a CreateStream with
|
|
// STGM_CREATE because CreateStream can open over an already
|
|
// open stream, which leads to problems when the destination
|
|
// and the source are the same.
|
|
olHChkTo(EH_UnkSrc, pstgParent->OpenStream(ptcsNewName,
|
|
0,
|
|
STGM_DIRECT |
|
|
STGM_WRITE |
|
|
STGM_SHARE_EXCLUSIVE,
|
|
0,
|
|
&pstmdst));
|
|
sc = pstmdst->SetSize(uli);
|
|
if (FAILED(sc))
|
|
{
|
|
pstmdst->Release();
|
|
olErr(EH_UnkSrc, sc);
|
|
}
|
|
}
|
|
else
|
|
olHChkTo(EH_UnkSrc, hr);
|
|
|
|
punkdst = pstmdst;
|
|
|
|
ULARGE_INTEGER cb;
|
|
ULISetLow (cb, 0xffffffff);
|
|
ULISetHigh(cb, 0xffffffff);
|
|
sc = DfGetScode(pstmsrc->CopyTo(pstmdst, cb, NULL, NULL));
|
|
}
|
|
else
|
|
olChk(sc);
|
|
|
|
punkdst->Release();
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
// Make destination create time match source create time
|
|
// Note that we don't really care if this call succeeded.
|
|
|
|
pstgParent->SetElementTimes(ptcsNewName, &statstg.ctime,
|
|
NULL, NULL);
|
|
|
|
//OK to ignore failure from DestroyElement
|
|
if ((grfFlags & STGMOVE_COPY) == STGMOVE_MOVE)
|
|
DestroyElement(pwcsName);
|
|
}
|
|
else
|
|
{
|
|
// The copy/move failed, so get rid of the partial result.
|
|
//Only do a delete if the object was newly created.
|
|
if (fCreate)
|
|
pstgParent->DestroyElement(ptcsNewName);
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::MoveElementTo\n"));
|
|
// Fall through
|
|
EH_UnkSrc:
|
|
if (punksrc)
|
|
punksrc->Release();
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::RenameElement, public
|
|
//
|
|
// Synopsis: Renames an element of a DocFile
|
|
//
|
|
// Arguments: [pwcsName] - Current name
|
|
// [pwcsNewName] - New name
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 20-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::RenameElement(WCHAR const *pwcsName,
|
|
WCHAR const *pwcsNewName)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
CDfName dfnOld, dfnNew;
|
|
|
|
olLog(("%p::In CExposedDocFile::RenameElement(%ws, %ws)\n",
|
|
this, pwcsName, pwcsNewName));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::RenameElement(%ws, %ws)\n",
|
|
pwcsName, pwcsNewName));
|
|
|
|
OL_VALIDATE(RenameElement(pwcsName,
|
|
pwcsNewName));
|
|
|
|
olChk(Validate());
|
|
dfnOld.Set(pwcsName);
|
|
dfnNew.Set(pwcsNewName);
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
|
|
sc = _pdf->RenameEntry(&dfnOld, &dfnNew);
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::RenameElement\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::RenameElement(). ret == %lx\n",
|
|
this, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::SetElementTimes, public
|
|
//
|
|
// Synopsis: Sets element time stamps
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [pctime] - create time
|
|
// [patime] - access time
|
|
// [pmtime] - modify time
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 05-Oct-92 AlexT Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::SetElementTimes(WCHAR const *pwcsName,
|
|
FILETIME const *pctime,
|
|
FILETIME const *patime,
|
|
FILETIME const *pmtime)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
CDfName dfn;
|
|
CDfName *pdfn = NULL;
|
|
FILETIME ctime, atime, mtime;
|
|
|
|
olLog(("%p::In CExposedDocFile::SetElementTimes(%ws, %p, %p, %p)\n",
|
|
this, pwcsName, pctime, patime, pmtime));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::SetElementTimes:%p("
|
|
"%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
|
|
|
|
OL_VALIDATE(SetElementTimes(pwcsName,
|
|
pctime,
|
|
patime,
|
|
pmtime));
|
|
olChk(Validate());
|
|
// Probe arguments and make local copies if necessary
|
|
if (pctime)
|
|
{
|
|
ctime = *pctime;
|
|
pctime = &ctime;
|
|
}
|
|
if (patime)
|
|
{
|
|
atime = *patime;
|
|
patime = &atime;
|
|
}
|
|
if (pmtime)
|
|
{
|
|
mtime = *pmtime;
|
|
pmtime = &mtime;
|
|
}
|
|
|
|
if (pwcsName != NULL)
|
|
{
|
|
dfn.Set(pwcsName);
|
|
pdfn = &dfn;
|
|
}
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
|
|
sc = _pdf->SetElementTimes(pdfn, pctime, patime, pmtime);
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::SetElementTimes\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::SetElementTimes(). ret == %lx\n",
|
|
this, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::SetClass, public
|
|
//
|
|
// Synopsis: Sets storage class
|
|
//
|
|
// Arguments: [clsid] - class id
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 05-Oct-92 AlexT Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::SetClass(REFCLSID rclsid)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
CLSID clsid;
|
|
|
|
olLog(("%p::In CExposedDocFile::SetClass(?)\n", this));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::SetClass:%p(?)\n", this));
|
|
|
|
OL_VALIDATE(SetClass(rclsid));
|
|
olChk(Validate());
|
|
clsid = rclsid;
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
|
|
sc = _pdf->SetClass(clsid);
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::SetClass\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::SetClass(). ret == %lx\n",
|
|
this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::SetStateBits, public
|
|
//
|
|
// Synopsis: Sets state bits
|
|
//
|
|
// Arguments: [grfStateBits] - state bits
|
|
// [grfMask] - state bits mask
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 05-Oct-92 AlexT Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::SetStateBits(DWORD grfStateBits, DWORD grfMask)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
|
|
olLog(("%p::In CExposedDocFile::SetStateBits(%lu, %lu)\n", this,
|
|
grfStateBits, grfMask));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::SetStateBits:%p("
|
|
"%lu, %lu)\n", this, grfStateBits, grfMask));
|
|
|
|
OL_VALIDATE(SetStateBits(grfStateBits, grfMask));
|
|
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
|
|
sc = _pdf->SetStateBits(grfStateBits, grfMask);
|
|
END_PENDING_LOOP;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::SetStateBits\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::SetStateBits(). ret == %lx\n",
|
|
this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::Stat, public
|
|
//
|
|
// Synopsis: Fills in a buffer of information about this object
|
|
//
|
|
// Arguments: [pstatstg] - Buffer
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pstatstg]
|
|
//
|
|
// History: 24-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedDocFile::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
|
|
{
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
SCODE sc;
|
|
STATSTGW stat;
|
|
|
|
olLog(("%p::In CExposedDocFile::Stat(%p)\n", this, pstatstg));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::Stat(%p)\n", pstatstg));
|
|
|
|
OL_VALIDATE(Stat(pstatstg, grfStatFlag));
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SafeReadAccess();
|
|
|
|
sc = _pdf->Stat(&stat, grfStatFlag);
|
|
END_PENDING_LOOP;
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
TRY
|
|
{
|
|
*pstatstg = stat;
|
|
pstatstg->type = STGTY_STORAGE;
|
|
ULISet32(pstatstg->cbSize, 0);
|
|
pstatstg->grfLocksSupported = 0;
|
|
pstatstg->STATSTG_dwStgFmt = 0;
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
UNREFERENCED_PARM(e);
|
|
if (stat.pwcsName)
|
|
TaskMemFree(stat.pwcsName);
|
|
}
|
|
END_CATCH
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::Stat\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::Stat(). *pstatstg == %p ret == %lx\n",
|
|
this, *pstatstg, sc));
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::AddRef, public
|
|
//
|
|
// Synopsis: Increments the ref count
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 16-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CExposedDocFile::AddRef(void)
|
|
{
|
|
ULONG ulRet;
|
|
|
|
olLog(("%p::In CExposedDocFile::AddRef()\n", this));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::AddRef()\n"));
|
|
|
|
if (FAILED(Validate()))
|
|
return 0;
|
|
InterlockedIncrement(&_cReferences);
|
|
ulRet = _cReferences;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::AddRef %p()=> %lu\n",
|
|
this, _cReferences));
|
|
olLog(("%p::Out CExposedDocFile::AddRef(). ret == %lu\n", this, ulRet));
|
|
return ulRet;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::QueryInterface, public
|
|
//
|
|
// Synopsis: Returns an object for the requested interface
|
|
//
|
|
// Arguments: [iid] - Interface ID
|
|
// [ppvObj] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 26-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::QueryInterface(REFIID iid, void **ppvObj)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
olLog(("%p::In CExposedDocFile::QueryInterface(?, %p)\n",
|
|
this, ppvObj));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::QueryInterface(?, %p)\n",
|
|
ppvObj));
|
|
|
|
OL_VALIDATE(QueryInterface(iid, ppvObj));
|
|
|
|
olChk(Validate());
|
|
olChk(_pdf->CheckReverted());
|
|
|
|
sc = S_OK;
|
|
if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppvObj = (IStorage *)this;
|
|
CExposedDocFile::AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_IMarshal))
|
|
{
|
|
if (P_PRIORITY(_pdf->GetDFlags()) && _pdf->IsRoot())
|
|
olErr(EH_Err, E_NOINTERFACE);
|
|
|
|
//If the ILockBytes we'd need to marshal doesn't support IMarshal
|
|
// then we want to do standard marshalling on the storage, mostly
|
|
// to prevent deadlock problems but also because you'll get better
|
|
// performance. So check, then do the right thing.
|
|
|
|
IMarshal *pim;
|
|
ILockBytes *plkb;
|
|
plkb = _ppc->GetOriginal();
|
|
if (plkb == NULL)
|
|
{
|
|
plkb = _ppc->GetBase();
|
|
}
|
|
|
|
sc = plkb->QueryInterface(IID_IMarshal, (void **)&pim);
|
|
if (FAILED(sc))
|
|
{
|
|
olErr(EH_Err, E_NOINTERFACE);
|
|
}
|
|
pim->Release();
|
|
|
|
#ifdef MULTIHEAP
|
|
if (_ppc->GetHeapBase() == NULL)
|
|
olErr (EH_Err, E_NOINTERFACE);
|
|
#endif
|
|
|
|
*ppvObj = (IMarshal *)this;
|
|
CExposedDocFile::AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_IRootStorage))
|
|
{
|
|
#ifdef COORD
|
|
if ((!_pdf->IsRoot()) && (!_pdf->IsCoord()))
|
|
#else
|
|
if (!_pdf->IsRoot())
|
|
#endif
|
|
olErr(EH_Err, E_NOINTERFACE);
|
|
*ppvObj = (IRootStorage *)this;
|
|
CExposedDocFile::AddRef();
|
|
}
|
|
#ifdef NEWPROPS
|
|
else if (IsEqualIID(iid, IID_IPropertySetStorage))
|
|
{
|
|
*ppvObj = (IPropertySetStorage *)this;
|
|
CExposedDocFile::AddRef();
|
|
}
|
|
|
|
#endif
|
|
#ifdef ASYNC
|
|
else if (IsEqualIID(iid, IID_IConnectionPointContainer) &&
|
|
_cpoint.IsInitialized())
|
|
{
|
|
*ppvObj = (IConnectionPointContainer *)this;
|
|
CExposedDocFile::AddRef();
|
|
}
|
|
#endif
|
|
#if WIN32 >= 300
|
|
else if (_pdf->IsRoot() && IsEqualIID(iid, IID_IAccessControl))
|
|
{
|
|
ILockBytes *piLB = _pdf->GetBaseMS()->GetILB();
|
|
olAssert((piLB != NULL));
|
|
SCODE scode = S_OK;
|
|
if (_pIAC == NULL) // use existing _pIAC if available
|
|
scode = piLB->QueryInterface(IID_IAccessControl,(void **)&_pIAC);
|
|
if (SUCCEEDED(scode))
|
|
{
|
|
*ppvObj = (IAccessControl *)this;
|
|
CExposedDocFile::AddRef();
|
|
}
|
|
else sc = E_NOINTERFACE;
|
|
}
|
|
#endif
|
|
#ifdef DIRECTWRITERLOCK
|
|
else if (_pdf->IsRoot() && IsEqualIID(iid, IID_IDirectWriterLock) &&
|
|
_pdfb->DirectWriterMode())
|
|
{
|
|
*ppvObj = (IDirectWriterLock *) this;
|
|
CExposedDocFile::AddRef();
|
|
}
|
|
#endif // DIRECTWRITERLOCK
|
|
|
|
else if( IsEqualIID( iid, IID_IPropertyBagEx ))
|
|
{
|
|
*ppvObj = static_cast<IPropertyBagEx*>(&_PropertyBagEx);
|
|
CExposedDocFile::AddRef();
|
|
}
|
|
else if( IsEqualIID( iid, IID_IPropertyBag ))
|
|
{
|
|
*ppvObj = static_cast<IPropertyBag*>(&_PropertyBagEx);
|
|
CExposedDocFile::AddRef();
|
|
}
|
|
|
|
else
|
|
sc = E_NOINTERFACE;
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::QueryInterface => %p\n",
|
|
*ppvObj));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::QueryInterface(). "
|
|
"*ppvObj == %p ret == %lx\n", this, *ppvObj, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Method: CExposedDocFile::CopySStreamToIStream, private
|
|
//
|
|
// Synopsis: Copies a PSStream to an IStream
|
|
//
|
|
// Arguments: [psstFrom] - SStream
|
|
// [pstTo] - IStream
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-May-92 DrewB Created
|
|
// 26-Jun-92 AlexT Moved to CExposedDocFile
|
|
// so we can call SetReadAccess
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
SCODE CExposedDocFile::CopySStreamToIStream(PSStream *psstFrom,
|
|
IStream *pstTo)
|
|
{
|
|
BYTE *pbBuffer;
|
|
SCODE sc;
|
|
#ifdef LARGE_STREAMS
|
|
ULONGLONG cbPos;
|
|
ULONG cbRead, cbWritten;
|
|
#else
|
|
ULONG cbRead, cbWritten, cbPos, cbSizeLow;
|
|
#endif
|
|
ULONG ulBufferSize;
|
|
ULARGE_INTEGER cbSize;
|
|
cbSize.QuadPart = 0;
|
|
|
|
ulBufferSize = (_pdfb->GetOpenFlags() & DF_LARGE) ?
|
|
LARGESTREAMBUFFERSIZE : STREAMBUFFERSIZE;
|
|
|
|
// This is part of CopyTo and therefore we are allowed to
|
|
// fail with out-of-memory
|
|
olChk(GetBuffer(STREAMBUFFERSIZE, ulBufferSize, &pbBuffer, &ulBufferSize));
|
|
|
|
// Set destination size for contiguity
|
|
SetReadAccess();
|
|
#ifdef LARGE_STREAMS
|
|
psstFrom->GetSize(&cbSize.QuadPart);
|
|
#else
|
|
psstFrom->GetSize(&cbSize.LowPart);
|
|
cbSize.HighPart = 0;
|
|
#endif
|
|
ClearReadAccess();
|
|
|
|
// Don't need to SetReadAccess here because pstTo is an IStream
|
|
olHChk(pstTo->SetSize(cbSize));
|
|
// Copy between streams
|
|
cbPos = 0;
|
|
for (;;)
|
|
{
|
|
SetReadAccess();
|
|
olChk(psstFrom->ReadAt(cbPos, pbBuffer, ulBufferSize,
|
|
(ULONG STACKBASED *)&cbRead));
|
|
ClearReadAccess();
|
|
if (cbRead == 0) // EOF
|
|
break;
|
|
|
|
// Don't need to SetReadAccess here because pstTo is an IStream
|
|
olHChk(pstTo->Write(pbBuffer, cbRead, &cbWritten));
|
|
if (cbRead != cbWritten)
|
|
olErr(EH_Err, STG_E_WRITEFAULT);
|
|
cbPos += cbWritten;
|
|
}
|
|
sc = S_OK;
|
|
|
|
EH_Err:
|
|
DfMemFree(pbBuffer);
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Method: CExposedDocFile::CopyDocFileToIStorage, private
|
|
//
|
|
// Synopsis: Copies a docfile's contents to an IStorage
|
|
//
|
|
// Arguments: [pdfFrom] - From
|
|
// [pstgTo] - To
|
|
// [snbExclude] - Names to not copy
|
|
// [dwCopyFlags] - Bitwise flags for types of objects to copy
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-May-92 DrewB Created
|
|
// 26-Jun-92 AlexT Moved to CExposedDocFile
|
|
// so we can call SetReadAccess
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
// Variables used by CopyDocFileToIStorage that we
|
|
// want to allocate dynamically rather than eating stack space
|
|
struct SCopyVars : public CLocalAlloc
|
|
{
|
|
PSStream *psstFrom;
|
|
IStream *pstTo;
|
|
PDocFile *pdfFromChild;
|
|
IStorage *pstgToChild;
|
|
DWORD grfStateBits;
|
|
CLSID clsid;
|
|
CDfName dfnKey;
|
|
SIterBuffer ib;
|
|
OLECHAR atcName[CWCSTORAGENAME];
|
|
};
|
|
|
|
SCODE CExposedDocFile::CopyDocFileToIStorage(PDocFile *pdfFrom,
|
|
IStorage *pstgTo,
|
|
SNBW snbExclude,
|
|
DWORD dwCopyFlags)
|
|
{
|
|
SCODE sc;
|
|
SCopyVars *pcv = NULL;
|
|
|
|
olDebugOut((DEB_ITRACE, "In CopyDocFileToIStorage:%p(%p, %p, %p, %lX)\n",
|
|
this, pdfFrom, pstgTo, snbExclude, dwCopyFlags));
|
|
|
|
// Allocate variables dynamically to conserve stack space since
|
|
// this is a recursive call
|
|
olMem(pcv = new SCopyVars);
|
|
|
|
SetReadAccess();
|
|
sc = pdfFrom->GetClass(&pcv->clsid);
|
|
ClearReadAccess();
|
|
olChk(sc);
|
|
|
|
// Assume STG_E_INVALIDFUNCTION means that the destination storage
|
|
// doesn't support class IDs
|
|
sc = GetScode(pstgTo->SetClass(pcv->clsid));
|
|
if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
|
|
olErr(EH_Err, sc);
|
|
|
|
SetReadAccess();
|
|
sc = pdfFrom->GetStateBits(&pcv->grfStateBits);
|
|
ClearReadAccess();
|
|
olChk(sc);
|
|
|
|
sc = GetScode(pstgTo->SetStateBits(pcv->grfStateBits, 0xffffffff));
|
|
if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
|
|
olErr(EH_Err, sc);
|
|
|
|
for (;;)
|
|
{
|
|
SetReadAccess();
|
|
sc = pdfFrom->FindGreaterEntry(&pcv->dfnKey, &pcv->ib, NULL);
|
|
ClearReadAccess();
|
|
|
|
if (sc == STG_E_NOMOREFILES)
|
|
break;
|
|
else if (FAILED(sc))
|
|
olErr(EH_pdfi, sc);
|
|
pcv->dfnKey.Set(&pcv->ib.dfnName);
|
|
|
|
if (snbExclude && NameInSNB(&pcv->ib.dfnName, snbExclude) == S_OK)
|
|
continue;
|
|
|
|
if ((pcv->ib.type == STGTY_STORAGE &&
|
|
(dwCopyFlags & COPY_STORAGES) == 0) ||
|
|
(pcv->ib.type == STGTY_STREAM &&
|
|
(dwCopyFlags & COPY_STREAMS) == 0))
|
|
continue;
|
|
|
|
switch(pcv->ib.type)
|
|
{
|
|
case STGTY_STORAGE:
|
|
// Embedded DocFile, create destination and recurse
|
|
|
|
SetReadAccess();
|
|
sc = pdfFrom->GetDocFile(&pcv->ib.dfnName, DF_READ,
|
|
pcv->ib.type, &pcv->pdfFromChild);
|
|
ClearReadAccess();
|
|
olChkTo(EH_pdfi, sc);
|
|
// Not optimally efficient, but reduces #ifdef's
|
|
StringCbCopyW (pcv->atcName, sizeof(pcv->atcName), (WCHAR *)pcv->ib.dfnName.GetBuffer());
|
|
|
|
// Don't need to SetReadAccess here because pstgTo is an IStorage.
|
|
|
|
#ifdef MULTIHEAP
|
|
{
|
|
CSafeMultiHeap smh(_ppc);
|
|
// if pstgTo is an IStorage proxy, then returned IStorage
|
|
// can be custom marshaled and allocator state is lost
|
|
#endif
|
|
sc = DfGetScode(pstgTo->CreateStorage(pcv->atcName, STGM_WRITE |
|
|
STGM_SHARE_EXCLUSIVE |
|
|
STGM_FAILIFTHERE,
|
|
0, 0, &pcv->pstgToChild));
|
|
|
|
if (sc == STG_E_FILEALREADYEXISTS)
|
|
//We need read and write permissions so we can traverse
|
|
// the destination IStorage
|
|
olHChkTo(EH_Get, pstgTo->OpenStorage(pcv->atcName, NULL,
|
|
STGM_READWRITE |
|
|
STGM_SHARE_EXCLUSIVE,
|
|
NULL, 0,
|
|
&pcv->pstgToChild));
|
|
else if (FAILED(sc))
|
|
olErr(EH_Get, sc);
|
|
#ifdef MULTIHEAP
|
|
}
|
|
#endif
|
|
olChkTo(EH_Create,
|
|
CopyDocFileToIStorage(pcv->pdfFromChild, pcv->pstgToChild,
|
|
NULL, dwCopyFlags));
|
|
pcv->pdfFromChild->Release();
|
|
pcv->pstgToChild->Release();
|
|
break;
|
|
|
|
case STGTY_STREAM:
|
|
SetReadAccess();
|
|
sc = pdfFrom->GetStream(&pcv->ib.dfnName, DF_READ,
|
|
pcv->ib.type, &pcv->psstFrom);
|
|
ClearReadAccess();
|
|
olChkTo(EH_pdfi, sc);
|
|
// Not optimally efficient, but reduces #ifdef's
|
|
StringCbCopyW (pcv->atcName, sizeof(pcv->atcName), (WCHAR *)pcv->ib.dfnName.GetBuffer());
|
|
|
|
// Don't need to SetReadAccess here because pstgTo is an IStorage.
|
|
|
|
#ifdef MULTIHEAP
|
|
{
|
|
CSafeMultiHeap smh(_ppc);
|
|
// if pstgTo is an IStorage proxy, then returned IStream
|
|
// can be custom marshaled and allocator state is lost
|
|
#endif
|
|
olHChkTo(EH_Get,
|
|
pstgTo->CreateStream(pcv->atcName, STGM_WRITE |
|
|
STGM_SHARE_EXCLUSIVE |
|
|
STGM_CREATE,
|
|
0, 0, &pcv->pstTo));
|
|
#ifdef MULTIHEAP
|
|
}
|
|
#endif
|
|
olChkTo(EH_Create,
|
|
CopySStreamToIStream(pcv->psstFrom, pcv->pstTo));
|
|
pcv->psstFrom->Release();
|
|
pcv->pstTo->Release();
|
|
break;
|
|
|
|
default:
|
|
olAssert(!aMsg("Unknown type in CopyDocFileToIStorage"));
|
|
break;
|
|
}
|
|
}
|
|
olDebugOut((DEB_ITRACE, "Out CopyDocFileToIStorage\n"));
|
|
sc = S_OK;
|
|
|
|
EH_pdfi:
|
|
EH_Err:
|
|
delete pcv;
|
|
return sc;
|
|
|
|
EH_Create:
|
|
if (pcv->ib.type == STGTY_STORAGE)
|
|
pcv->pstgToChild->Release();
|
|
else
|
|
pcv->pstTo->Release();
|
|
olVerSucc(pstgTo->DestroyElement(pcv->atcName));
|
|
EH_Get:
|
|
if (pcv->ib.type == STGTY_STORAGE)
|
|
pcv->pdfFromChild->Release();
|
|
else
|
|
pcv->psstFrom->Release();
|
|
goto EH_Err;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::Unmarshal, public
|
|
//
|
|
// Synopsis: Creates a duplicate DocFile from parts
|
|
//
|
|
// Arguments: [pstm] - Marshal stream
|
|
// [ppv] - Object return
|
|
// [mshlflags] - Marshal flags
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppv]
|
|
//
|
|
// History: 26-Feb-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
SCODE CExposedDocFile::Unmarshal(IStream *pstm,
|
|
void **ppv,
|
|
DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
CDfMutex mtx;
|
|
CPerContext *ppc;
|
|
CPubDocFile *pdf;
|
|
CGlobalContext *pgc;
|
|
CDFBasis *pdfb;
|
|
CExposedDocFile *pedf;
|
|
IStorage *pstgStd = NULL;
|
|
ULONG_PTR df;
|
|
|
|
#ifdef ASYNC
|
|
DWORD dwAsyncFlags;
|
|
IDocfileAsyncConnectionPoint *pdacp;
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
CMarshalList *pml;
|
|
#endif
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedDocFile::Unmarshal(%p, %p)\n",
|
|
pstm, ppv));
|
|
|
|
#ifdef MULTIHEAP
|
|
void *pvBaseOld;
|
|
void *pvBaseNew;
|
|
ContextId cntxid;
|
|
CPerContext pcSharedMemory (NULL); // bootstrap object
|
|
#endif
|
|
|
|
//First unmarshal the standard marshalled version
|
|
sc = CoUnmarshalInterface(pstm, IID_IStorage, (void**)&pstgStd);
|
|
if (FAILED(sc))
|
|
{
|
|
// assume that entire standard marshaling stream has been read
|
|
olAssert (pstgStd == NULL);
|
|
sc = S_OK;
|
|
}
|
|
|
|
#ifdef MULTIHEAP
|
|
sc = UnmarshalSharedMemory(pstm, mshlflags, &pcSharedMemory, &cntxid);
|
|
if (!SUCCEEDED(sc))
|
|
{
|
|
#ifdef POINTER_IDENTITY
|
|
UnmarshalPointer(pstm, (void **) &pedf);
|
|
#endif
|
|
UnmarshalPointer(pstm, (void **)&pdf);
|
|
UnmarshalPointer(pstm, (void **)&pdfb);
|
|
UnmarshalPointer(pstm, (void **)&df);
|
|
#ifdef ASYNC
|
|
ReleaseContext(pstm, TRUE, P_INDEPENDENT(df) != 0, mshlflags);
|
|
ReleaseConnection(pstm, mshlflags);
|
|
#else
|
|
ReleaseContext(pstm, P_INDEPENDENT(df), mshlflags);
|
|
#endif
|
|
olChkTo(EH_std, sc);
|
|
}
|
|
pvBaseOld = DFBASEPTR;
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
olChkTo(EH_mem, UnmarshalPointer(pstm, (void **) &pedf));
|
|
#endif
|
|
olChkTo(EH_mem, UnmarshalPointer(pstm, (void **)&pdf));
|
|
olChkTo(EH_mem, CPubDocFile::Validate(pdf));
|
|
olChkTo(EH_pdf, UnmarshalPointer(pstm, (void **)&pdfb));
|
|
olChkTo(EH_pdfb, UnmarshalPointer(pstm, (void **) &df));
|
|
olChkTo(EH_pdfb, UnmarshalPointer(pstm, (void **)&pgc));
|
|
olChkTo(EH_pgc, ValidateBuffer(pgc, sizeof(CGlobalContext)));
|
|
|
|
//So far, nothing has called into the tree so we don't really need
|
|
// to be holding the tree mutex. The UnmarshalContext call does
|
|
// call into the tree, though, so we need to make sure this is
|
|
// threadsafe. We'll do this my getting the mutex name from the
|
|
// CGlobalContext, then creating a new CDfMutex object. While
|
|
// this is obviously not optimal, since it's possible we could
|
|
// reuse an existing CDfMutex, the reuse strategy isn't threadsafe
|
|
// since we can't do a lookup without the possibility of the thing
|
|
// we're looking for being released by another thread.
|
|
TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH];
|
|
pgc->GetMutexName(atcMutexName);
|
|
olChkTo(EH_pgc, mtx.Init(atcMutexName));
|
|
olChkTo(EH_pgc, mtx.Take(INFINITE));
|
|
|
|
//At this point we're holding the mutex.
|
|
|
|
#ifdef MULTIHEAP
|
|
#ifdef ASYNC
|
|
olChkTo(EH_mtx, UnmarshalContext(pstm,
|
|
pgc,
|
|
&ppc,
|
|
mshlflags,
|
|
TRUE,
|
|
P_INDEPENDENT(pdf->GetDFlags()),
|
|
cntxid,
|
|
pdf->IsRoot()));
|
|
#else
|
|
olChkTo(EH_mtx, UnmarshalContext(pstm,
|
|
pgc,
|
|
&ppc,
|
|
mshlflags,
|
|
P_INDEPENDENT(pdf->GetDFlags()),
|
|
cntxid,
|
|
pdf->IsRoot()));
|
|
#endif
|
|
if ((pvBaseNew = DFBASEPTR) != pvBaseOld)
|
|
{
|
|
pdf = (CPubDocFile*) ((ULONG_PTR)pdf - (ULONG_PTR)pvBaseOld
|
|
+ (ULONG_PTR)pvBaseNew);
|
|
pedf = (CExposedDocFile*) ((ULONG_PTR)pedf - (ULONG_PTR)pvBaseOld
|
|
+ (ULONG_PTR)pvBaseNew);
|
|
pdfb = (CDFBasis*) ((ULONG_PTR)pdfb - (ULONG_PTR)pvBaseOld
|
|
+ (ULONG_PTR)pvBaseNew);
|
|
}
|
|
#else
|
|
#ifdef ASYNC
|
|
olChkTo(EH_mtx, UnmarshalContext(pstm,
|
|
pgc,
|
|
&ppc,
|
|
mshlflags,
|
|
TRUE,
|
|
P_INDEPENDENT(pdf->GetDFlags()),
|
|
pdf->IsRoot()));
|
|
#else
|
|
olChkTo(EH_mtx, UnmarshalContext(pstm,
|
|
pgc,
|
|
&ppc,
|
|
mshlflags,
|
|
P_INDEPENDENT(pdf->GetDFlags()),
|
|
pdf->IsRoot()));
|
|
#endif //ASYNC
|
|
#endif
|
|
|
|
#ifdef ASYNC
|
|
olChkTo(EH_mtx, UnmarshalConnection(pstm,
|
|
&dwAsyncFlags,
|
|
&pdacp,
|
|
mshlflags));
|
|
#endif
|
|
// if we use up 1Gig of address space, use standard unmarshaling
|
|
if (gs_iSharedHeaps > (DOCFILE_SM_LIMIT / DOCFILE_SM_SIZE))
|
|
olErr (EH_ppc, STG_E_INSUFFICIENTMEMORY);
|
|
|
|
#ifdef POINTER_IDENTITY
|
|
olAssert (pedf != NULL);
|
|
pml = (CMarshalList *) pedf;
|
|
|
|
// Warning: these checks must remain valid across processes
|
|
if (SUCCEEDED(pedf->Validate()) && pedf->GetPub() == pdf)
|
|
{
|
|
pedf = (CExposedDocFile *) pml->FindMarshal(GetCurrentContextId());
|
|
}
|
|
else
|
|
{
|
|
pml = NULL;
|
|
pedf = NULL;
|
|
}
|
|
|
|
// exposed object is not found or has been deleted
|
|
if (pedf == NULL)
|
|
{
|
|
#endif
|
|
olMemTo(EH_ppc, pedf = new (pdfb->GetMalloc())
|
|
CExposedDocFile(pdf, pdfb, ppc));
|
|
olChkTo(EH_exp, pedf->InitMarshal(dwAsyncFlags, pdacp));
|
|
//InitMarshal adds a reference.
|
|
if (pdacp)
|
|
pdacp->Release();
|
|
|
|
#ifdef POINTER_IDENTITY
|
|
if (pml) pml->AddMarshal(pedf);
|
|
pdf->vAddRef(); // CExposedDocFile ctor does not AddRef
|
|
}
|
|
else
|
|
{
|
|
pdfb->SetAccess(ppc);
|
|
pedf->AddRef(); // reuse this object
|
|
ppc->Release(); // reuse percontext
|
|
}
|
|
#else
|
|
pdf->vAddRef();
|
|
#endif
|
|
|
|
*ppv = (void *)pedf;
|
|
#ifdef MULTIHEAP
|
|
if (pvBaseOld != pvBaseNew)
|
|
{
|
|
pcSharedMemory.SetThreadAllocatorState(NULL);
|
|
g_smAllocator.Uninit(); // delete the extra mapping
|
|
}
|
|
g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
|
|
#endif
|
|
|
|
mtx.Release();
|
|
|
|
//We're returning the custom marshalled version, so we don't need
|
|
//the std marshalled one anymore.
|
|
if (pstgStd != NULL)
|
|
pstgStd->Release();
|
|
|
|
olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Unmarshal => %p\n", *ppv));
|
|
return S_OK;
|
|
EH_exp:
|
|
pedf->Release();
|
|
goto EH_Err;
|
|
EH_ppc:
|
|
ppc->Release();
|
|
EH_mtx:
|
|
mtx.Release();
|
|
goto EH_Err;
|
|
EH_pgc:
|
|
CoReleaseMarshalData(pstm); // release the ILockBytes
|
|
CoReleaseMarshalData(pstm); // release the ILockBytes
|
|
if (P_INDEPENDENT(pdf->GetDFlags()))
|
|
CoReleaseMarshalData(pstm); // release the ILockBytes
|
|
#ifdef ASYNC
|
|
ReleaseConnection(pstm, mshlflags);
|
|
#endif
|
|
|
|
EH_pdfb:
|
|
EH_pdf:
|
|
EH_mem:
|
|
EH_Err:
|
|
#ifdef MULTIHEAP
|
|
pcSharedMemory.SetThreadAllocatorState(NULL);
|
|
g_smAllocator.Uninit(); // delete the file mapping in error case
|
|
g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
|
|
#endif
|
|
EH_std:
|
|
if (pstgStd != NULL)
|
|
{
|
|
//We can return the standard marshalled version and still succeed.
|
|
*ppv = pstgStd;
|
|
return S_OK;
|
|
}
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::GetUnmarshalClass, public
|
|
//
|
|
// Synopsis: Returns the class ID
|
|
//
|
|
// Arguments: [riid] - IID of object
|
|
// [pv] - Unreferenced
|
|
// [dwDestContext] - Unreferenced
|
|
// [pvDestContext] - Unreferenced
|
|
// [mshlflags] - Unreferenced
|
|
// [pcid] - CLSID return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcid]
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::GetUnmarshalClass(REFIID riid,
|
|
void *pv,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags,
|
|
LPCLSID pcid)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
olLog(("%p::In CExposedDocFile::GetUnmarshalClass("
|
|
"riid, %p, %lu, %p, %lu, %p)\n",
|
|
this, pv, dwDestContext, pvDestContext, mshlflags, pcid));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::GetUnmarshalClass:%p("
|
|
"riid, %p, %lu, %p, %lu, %p)\n", this,
|
|
pv, dwDestContext, pvDestContext, mshlflags, pcid));
|
|
|
|
UNREFERENCED_PARM(pv);
|
|
UNREFERENCED_PARM(mshlflags);
|
|
|
|
olChk(ValidateOutBuffer(pcid, sizeof(CLSID)));
|
|
memset(pcid, 0, sizeof(CLSID));
|
|
olChk(ValidateIid(riid));
|
|
olChk(Validate());
|
|
olChk(_pdf->CheckReverted());
|
|
|
|
if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
|
|
{
|
|
IMarshal *pmsh;
|
|
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = GetScode(pmsh->GetUnmarshalClass(riid, pv, dwDestContext,
|
|
pvDestContext, mshlflags,
|
|
pcid));
|
|
pmsh->Release();
|
|
}
|
|
}
|
|
else if (pvDestContext != NULL)
|
|
{
|
|
sc = STG_E_INVALIDPARAMETER;
|
|
}
|
|
else
|
|
{
|
|
olChk(VerifyIid(riid, IID_IStorage));
|
|
*pcid = CLSID_DfMarshal;
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::GetUnmarshalClass\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::GetUnmarshalClass(). ret = %lx\n",
|
|
this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::GetMarshalSizeMax, public
|
|
//
|
|
// Synopsis: Returns the size needed for the marshal buffer
|
|
//
|
|
// Arguments: [riid] - IID of object being marshaled
|
|
// [pv] - Unreferenced
|
|
// [dwDestContext] - Unreferenced
|
|
// [pvDestContext] - Unreferenced
|
|
// [mshlflags] - Unreferenced
|
|
// [pcbSize] - Size return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcbSize]
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::GetMarshalSizeMax(REFIID riid,
|
|
void *pv,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags,
|
|
LPDWORD pcbSize)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
UNREFERENCED_PARM(pv);
|
|
olLog(("%p::In CExposedDocFile::GetMarshalSizeMax("
|
|
"riid, %p, %lu, %p, %lu, %p)\n",
|
|
this, pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::GetMarshalSizeMax:%p("
|
|
"riid, %p, %lu, %p, %lu, %p)\n", this,
|
|
pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
|
|
|
|
olChk(Validate());
|
|
olChk(_pdf->CheckReverted());
|
|
|
|
if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
|
|
{
|
|
IMarshal *pmsh;
|
|
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
|
|
pvDestContext, mshlflags,
|
|
pcbSize));
|
|
pmsh->Release();
|
|
}
|
|
}
|
|
else if (pvDestContext != NULL)
|
|
{
|
|
sc = STG_E_INVALIDPARAMETER;
|
|
}
|
|
else
|
|
{
|
|
sc = GetStdMarshalSize(riid,
|
|
IID_IStorage,
|
|
dwDestContext,
|
|
pvDestContext,
|
|
mshlflags, pcbSize,
|
|
sizeof(CPubDocFile *)+sizeof(CDFBasis *)+
|
|
sizeof(DFLAGS),
|
|
#ifdef ASYNC
|
|
&_cpoint,
|
|
TRUE,
|
|
#endif
|
|
_ppc, P_INDEPENDENT(_pdf->GetDFlags()));
|
|
DWORD cbSize = 0;
|
|
IMarshal *pmsh;
|
|
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
|
|
pvDestContext, mshlflags,
|
|
&cbSize));
|
|
pmsh->Release();
|
|
*pcbSize += cbSize;
|
|
}
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::GetMarshalSizeMax\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::GetMarshalSizeMax()."
|
|
"*pcbSize == %lu, ret == %lx\n", this, *pcbSize, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::MarshalInterface, public
|
|
//
|
|
// Synopsis: Marshals a given object
|
|
//
|
|
// Arguments: [pstStm] - Stream to write marshal data into
|
|
// [riid] - Interface to marshal
|
|
// [pv] - Unreferenced
|
|
// [dwDestContext] - Unreferenced
|
|
// [pvDestContext] - Unreferenced
|
|
// [mshlflags] - Unreferenced
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::MarshalInterface(IStream *pstStm,
|
|
REFIID riid,
|
|
void *pv,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
olLog(("%p::In CExposedDocFile::MarshalInterface("
|
|
"%p, riid, %p, %lu, %p, %lu). Context == %lX\n",
|
|
this, pstStm, pv, dwDestContext,
|
|
pvDestContext, mshlflags,(ULONG)GetCurrentContextId()));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::MarshalInterface:%p("
|
|
"%p, riid, %p, %lu, %p, %lu)\n", this, pstStm, pv,
|
|
dwDestContext, pvDestContext, mshlflags));
|
|
|
|
UNREFERENCED_PARM(pv);
|
|
|
|
olChk(Validate());
|
|
olChk(_pdf->CheckReverted());
|
|
|
|
if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
|
|
{
|
|
IMarshal *pmsh;
|
|
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags));
|
|
pmsh->Release();
|
|
}
|
|
}
|
|
else if (pvDestContext != NULL)
|
|
{
|
|
sc = STG_E_INVALIDPARAMETER;
|
|
}
|
|
else
|
|
{
|
|
olChk(StartMarshal(pstStm, riid, IID_IStorage, mshlflags));
|
|
|
|
//Always standard marshal, in case we get an error during
|
|
//unmarshalling of the custom stuff.
|
|
{
|
|
IMarshal *pmsh;
|
|
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags, &pmsh)))
|
|
{
|
|
sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv,
|
|
dwDestContext, pvDestContext,
|
|
mshlflags));
|
|
pmsh->Release();
|
|
}
|
|
olChk(sc);
|
|
}
|
|
|
|
#ifdef MULTIHEAP
|
|
olChk(MarshalSharedMemory(pstStm, _ppc));
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
olChk(MarshalPointer(pstStm, (CExposedDocFile*) GetNextMarshal()));
|
|
#endif
|
|
olChk(MarshalPointer(pstStm, BP_TO_P(CPubDocFile *, _pdf)));
|
|
olChk(MarshalPointer(pstStm, BP_TO_P(CDFBasis *, _pdfb)));
|
|
olChk(MarshalPointer(pstStm, (void *) LongToPtr(_pdf->GetDFlags()) ));
|
|
#ifdef ASYNC
|
|
olChk(MarshalContext(pstStm,
|
|
_ppc,
|
|
dwDestContext,
|
|
pvDestContext,
|
|
mshlflags,
|
|
TRUE,
|
|
P_INDEPENDENT(_pdf->GetDFlags())));
|
|
|
|
sc = MarshalConnection(pstStm,
|
|
&_cpoint,
|
|
dwDestContext,
|
|
pvDestContext,
|
|
mshlflags);
|
|
#else
|
|
olChk(MarshalContext(pstStm,
|
|
_ppc,
|
|
dwDestContext,
|
|
pvDestContext,
|
|
mshlflags,
|
|
P_INDEPENDENT(_pdf->GetDFlags())));
|
|
#endif
|
|
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::MarshalInterface\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::MarshalInterface(). ret == %lx\n",
|
|
this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::UnmarshalInterface, public
|
|
//
|
|
// Synopsis: Non-functional
|
|
//
|
|
// Arguments: [pstStm] -
|
|
// [riid] -
|
|
// [ppvObj] -
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 04-May-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::UnmarshalInterface(IStream *pstStm,
|
|
REFIID riid,
|
|
void **ppvObj)
|
|
{
|
|
olLog(("%p::INVALID CALL TO CExposedDocFile::UnmarshalInterface()\n",
|
|
this));
|
|
return ResultFromScode(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::StaticReleaseMarshalData, public static
|
|
//
|
|
// Synopsis: Releases any references held in marshal data
|
|
//
|
|
// Arguments: [pstStm] - Marshal data stream
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 02-Feb-94 DrewB Created
|
|
//
|
|
// Notes: Assumes standard marshal header has already been read
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
SCODE CExposedDocFile::StaticReleaseMarshalData(IStream *pstStm,
|
|
DWORD mshlflags)
|
|
{
|
|
SCODE sc;
|
|
CPubDocFile *pdf;
|
|
CDFBasis *pdfb;
|
|
ULONG_PTR df;
|
|
#ifdef POINTER_IDENTITY
|
|
CExposedDocFile *pedf;
|
|
#endif
|
|
|
|
olDebugOut((DEB_ITRACE, "In CExposedDocFile::StaticReleaseMarshalData:("
|
|
"%p, %lX)\n", pstStm, mshlflags));
|
|
|
|
//First unmarshal the standard marshalled version
|
|
|
|
olChk(CoReleaseMarshalData(pstStm));
|
|
// The final release of the exposed object may have shut down the
|
|
// shared memory heap, so do not access shared memory after this point
|
|
|
|
//Then do the rest of it.
|
|
#ifdef MULTIHEAP
|
|
olChk(SkipSharedMemory(pstStm, mshlflags));
|
|
#endif
|
|
#ifdef POINTER_IDENTITY
|
|
olChk(UnmarshalPointer(pstStm, (void **) &pedf));
|
|
#endif
|
|
olChk(UnmarshalPointer(pstStm, (void **)&pdf));
|
|
olChk(UnmarshalPointer(pstStm, (void **)&pdfb));
|
|
olChk(UnmarshalPointer(pstStm, (void **)&df));
|
|
#ifdef ASYNC
|
|
olChk(ReleaseContext(pstStm, TRUE,
|
|
P_INDEPENDENT(df) != 0,
|
|
mshlflags));
|
|
olChk(ReleaseConnection(pstStm, mshlflags));
|
|
#else
|
|
olChk(ReleaseContext(pstStm, P_INDEPENDENT(df), mshlflags));
|
|
#endif
|
|
|
|
#ifdef MULTIHEAP
|
|
g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
|
|
#endif
|
|
|
|
olDebugOut((DEB_ITRACE,
|
|
"Out CExposedDocFile::StaticReleaseMarshalData\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::ReleaseMarshalData, public
|
|
//
|
|
// Synopsis: Non-functional
|
|
//
|
|
// Arguments: [pstStm] -
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 18-Sep-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::ReleaseMarshalData(IStream *pstStm)
|
|
{
|
|
SCODE sc;
|
|
DWORD mshlflags;
|
|
IID iid;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
olLog(("%p::In CExposedDocFile::ReleaseMarshalData(%p)\n", this, pstStm));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::ReleaseMarshalData:%p(%p)\n",
|
|
this, pstStm));
|
|
|
|
olChk(Validate());
|
|
olChk(_pdf->CheckReverted());
|
|
olChk(SkipStdMarshal(pstStm, &iid, &mshlflags));
|
|
olAssert(IsEqualIID(iid, IID_IStorage));
|
|
sc = StaticReleaseMarshalData(pstStm, mshlflags);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::ReleaseMarshalData\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::ReleaseMarshalData(). ret == %lx\n",
|
|
this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::DisconnectObject, public
|
|
//
|
|
// Synopsis: Non-functional
|
|
//
|
|
// Arguments: [dwRevserved] -
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 18-Sep-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedDocFile::DisconnectObject(DWORD dwReserved)
|
|
{
|
|
olLog(("%p::INVALID CALL TO CExposedDocFile::DisconnectObject()\n",
|
|
this));
|
|
return ResultFromScode(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::SwitchToFile, public
|
|
//
|
|
// Synopsis: Switches the underlying file to another file
|
|
//
|
|
// Arguments: [ptcsFile] - New file name
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 08-Jan-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CExposedDocFile::SwitchToFile(OLECHAR *ptcsFile)
|
|
{
|
|
|
|
ULONG ulOpenLock;
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
|
|
olLog(("%p::In CExposedDocFile::SwitchToFile(" OLEFMT ")\n",
|
|
this, ptcsFile));
|
|
olDebugOut((DEB_TRACE, "In CExposedDocFile::SwitchToFile:"
|
|
"%p(" OLEFMT ")\n",
|
|
this, ptcsFile));
|
|
|
|
olChk(ValidateNameW(ptcsFile, _MAX_PATH));
|
|
olChk(Validate());
|
|
|
|
olChk(TakeSafeSem());
|
|
olChk(_pdf->CheckReverted());
|
|
#ifdef COORD
|
|
olAssert(_pdf->IsRoot() || _pdf->IsCoord());
|
|
#else
|
|
olAssert(_pdf->IsRoot());
|
|
#endif
|
|
|
|
SafeReadAccess();
|
|
|
|
ulOpenLock = _ppc->GetOpenLock();
|
|
#ifdef COORD
|
|
sc = _pdf->GetRoot()->SwitchToFile(ptcsFile,
|
|
_ppc->GetOriginal(),
|
|
&ulOpenLock);
|
|
#else
|
|
sc = ((CRootPubDocFile *)(CPubDocFile*)_pdf)->SwitchToFile(ptcsFile,
|
|
_ppc->GetOriginal(),
|
|
&ulOpenLock);
|
|
#endif
|
|
|
|
_ppc->SetOpenLock(ulOpenLock);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedDocFile::SwitchToFile\n"));
|
|
EH_Err:
|
|
olLog(("%p::Out CExposedDocFile::SwitchToFile(). ret == %lx\n",
|
|
this, sc));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
#if WIN32 >= 300
|
|
// IAccessControl methods
|
|
STDMETHODIMP CExposedDocFile::GrantAccessRights(ULONG cCount,
|
|
ACCESS_REQUEST pAccessRequestList[])
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->GrantAccessRights(cCount, pAccessRequestList);
|
|
}
|
|
|
|
STDMETHODIMP CExposedDocFile::SetAccessRights(ULONG cCount,
|
|
ACCESS_REQUEST pAccessRequestList[])
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->SetAccessRights(cCount, pAccessRequestList);
|
|
}
|
|
|
|
STDMETHODIMP CExposedDocFile::ReplaceAllAccessRights(ULONG cCount,
|
|
ACCESS_REQUEST pAccessRequestList[])
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->ReplaceAllAccessRights(cCount, pAccessRequestList);
|
|
}
|
|
|
|
STDMETHODIMP CExposedDocFile::DenyAccessRights(ULONG cCount,
|
|
ACCESS_REQUEST pAccessRequestList[])
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->DenyAccessRights(cCount, pAccessRequestList);
|
|
}
|
|
|
|
STDMETHODIMP CExposedDocFile::RevokeExplicitAccessRights(ULONG cCount,
|
|
TRUSTEE pTrustee[])
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->RevokeExplicitAccessRights(cCount, pTrustee);
|
|
}
|
|
|
|
STDMETHODIMP CExposedDocFile::IsAccessPermitted(TRUSTEE *pTrustee,
|
|
DWORD grfAccessPermissions)
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->IsAccessPermitted(pTrustee, grfAccessPermissions);
|
|
}
|
|
|
|
STDMETHODIMP CExposedDocFile::GetEffectiveAccessRights(TRUSTEE *pTrustee,
|
|
DWORD *pgrfAccessPermissions )
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->GetEffectiveAccessRights(pTrustee, pgrfAccessPermissions);
|
|
}
|
|
|
|
STDMETHODIMP CExposedDocFile::GetExplicitAccessRights(ULONG *pcCount,
|
|
PEXPLICIT_ACCESS *pExplicitAccessList)
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->GetExplicitAccessRights(pcCount, pExplicitAccessList);
|
|
}
|
|
|
|
STDMETHODIMP CExposedDocFile::CommitAccessRights(DWORD grfCommitFlags)
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->CommitAccessRights(grfCommitFlags);
|
|
}
|
|
|
|
STDMETHODIMP CExposedDocFile::RevertAccessRights()
|
|
{
|
|
olAssert((_pIAC != NULL));
|
|
return _pIAC->RevertAccessRights();
|
|
}
|
|
|
|
|
|
|
|
#endif // if WIN32 >= 300
|
|
|
|
|
|
#ifdef COORD
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::CommitPhase1, public
|
|
//
|
|
// Synopsis: Do phase 1 of an exposed two phase commit
|
|
//
|
|
// Arguments: [grfCommitFlags] -- Commit flags
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 08-Aug-95 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CExposedDocFile::CommitPhase1(DWORD grfCommitFlags)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
|
|
olChk(VerifyCommitFlags(grfCommitFlags));
|
|
olChk(Validate());
|
|
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
|
|
sc = _pdf->CommitPhase1(grfCommitFlags,
|
|
&_ulLock,
|
|
&_sigMSF,
|
|
&_cbSizeBase,
|
|
&_cbSizeOrig);
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::CommitPhase2, public
|
|
//
|
|
// Synopsis: Do phase 2 of an exposed two phase commit
|
|
//
|
|
// Arguments: [grfCommitFlags] -- Commit flags
|
|
// [fCommit] -- TRUE if transaction is to commit, FALSE if abort
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 08-Aug-95 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CExposedDocFile::CommitPhase2(DWORD grfCommitFlags,
|
|
BOOL fCommit)
|
|
{
|
|
SCODE sc;
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
|
|
olChk(Validate());
|
|
|
|
olChk(TakeSafeSem());
|
|
SafeWriteAccess();
|
|
#ifdef DIRECTWRITERLOCK
|
|
olChk(ValidateWriteAccess());
|
|
#endif
|
|
|
|
sc = _pdf->CommitPhase2(grfCommitFlags,
|
|
fCommit,
|
|
_ulLock,
|
|
_sigMSF,
|
|
_cbSizeBase,
|
|
_cbSizeOrig);
|
|
|
|
_ulLock = _cbSizeBase = _cbSizeOrig = 0;
|
|
_sigMSF = 0;
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
#endif //COORD
|
|
|
|
|
|
#ifdef NEWPROPS
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::Lock, IBlockingLock
|
|
//
|
|
// Synopsis: Acquires the semaphore associated with the docfile.
|
|
//
|
|
// Notes: This member is called by CPropertyStorage.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CExposedDocFile::Lock(DWORD dwTimeout)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
TakeSem();
|
|
SetDifferentBasisAccess(_pdfb, _ppc);
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::Unlock, public IBlockingLock
|
|
//
|
|
// Synopsis: Releases the semaphore associated with the docfile.
|
|
//
|
|
// Notes: This member is called by CPropertyStorage.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CExposedDocFile::Unlock(VOID)
|
|
{
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
ClearBasisAccess(_pdfb);
|
|
ReleaseSem(S_OK);
|
|
return( S_OK );
|
|
}
|
|
#endif
|
|
|
|
#ifdef DIRECTWRITERLOCK
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::WaitForWriteAccess, public IDirectWriterLock
|
|
//
|
|
// Synopsis: tries to obtain exclusive write access in direct mode
|
|
//
|
|
// Notes: Tree mutex must be taken when accessing recursion count
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CExposedDocFile::WaitForWriteAccess (DWORD dwTimeout)
|
|
{
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
HRESULT hr = TakeSafeSem();
|
|
|
|
if (SUCCEEDED(hr) && *_ppc->GetRecursionCount() == 0)
|
|
{
|
|
SafeReadAccess();
|
|
hr = _pdfb->WaitForWriteAccess (dwTimeout, _ppc->GetGlobal());
|
|
}
|
|
if (SUCCEEDED(hr)) ++(*_ppc->GetRecursionCount());
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::ReleaseWriteAccess, public IDirectWriterLock
|
|
//
|
|
// Synopsis: releases exclusive write access from WaitForWriteAccess
|
|
//
|
|
// Notes: Tree mutex must be taken when accessing recursion count
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CExposedDocFile::ReleaseWriteAccess ()
|
|
{
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
HRESULT hr = TakeSafeSem();
|
|
|
|
if (SUCCEEDED(hr) && *_ppc->GetRecursionCount() == 1)
|
|
{
|
|
SafeReadAccess();
|
|
hr = _pdf->Commit(STGC_DEFAULT); // Flush
|
|
if (SUCCEEDED(hr)) hr = _pdfb->ReleaseWriteAccess();
|
|
}
|
|
if (SUCCEEDED(hr)) --(*_ppc->GetRecursionCount());
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::HaveWriteAccess, public IDirectWriterLock
|
|
//
|
|
// Synopsis: returns S_OK if write lock is active, S_FALSE if not
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CExposedDocFile::HaveWriteAccess ()
|
|
{
|
|
SAFE_SEM;
|
|
HRESULT hr = TakeSafeSem();
|
|
|
|
olAssert(_pdfb->DirectWriterMode());
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = (_pdfb->HaveWriteAccess()) ? S_OK : S_FALSE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedDocFile::ValidateWriteAccess, public
|
|
//
|
|
// Synopsis: returns whether writer currently has write access
|
|
//
|
|
// Notes: tree mutex must be taken
|
|
//
|
|
// History: 30-Apr-96 HenryLee Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
HRESULT CExposedDocFile::ValidateWriteAccess()
|
|
{
|
|
if (_pdf->GetTransactedDepth() >= 1)
|
|
return S_OK;
|
|
|
|
return (!_pdfb->DirectWriterMode() || (*_ppc->GetRecursionCount()) > 0) ?
|
|
S_OK : STG_E_ACCESSDENIED;
|
|
};
|
|
|
|
#endif // DIRECTWRITERLOCK
|