windows-nt/Source/XPSP1/NT/com/ole32/stg/exp/expdf.cxx
2020-09-26 16:20:57 +08:00

3218 lines
92 KiB
C++

//+--------------------------------------------------------------
//
// 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>
#include <ole2com.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] =
**(DWORD **)((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;
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
lstrcpyW(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
lstrcpyW(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