1446 lines
45 KiB
C++
1446 lines
45 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1994.
|
|
//
|
|
// File: odocstg.cxx
|
|
//
|
|
// Contents: IStorage for compound docs on OFS implementation
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
// Notes: BUGBUG [mikese] Many of these routines are identical
|
|
// to those for COfsDirStorage. We should create a common
|
|
// base class to contain the common code.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "headers.cxx"
|
|
#pragma hdrstop
|
|
|
|
#include <stgutil.hxx>
|
|
#include "odsenm.hxx"
|
|
#include "odocstm.hxx"
|
|
|
|
#include <psetstg.hxx>
|
|
#include <iofs.h>
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::QueryInterface, public
|
|
//
|
|
// Synopsis: Returns an object for the requested interface
|
|
//
|
|
// Arguments: [iid] - Interface ID
|
|
// [ppvObj] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::QueryInterface(REFIID iid, void **ppvObj)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::QueryInterface:%p(riid, %p)\n",
|
|
this, ppvObj));
|
|
if (!IsValidIid(iid))
|
|
olErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
ssChk(Validate());
|
|
if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppvObj = (IStorage *)this;
|
|
COfsDocStorage::AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_IPropertySetStorage))
|
|
{
|
|
*ppvObj = (IPropertySetStorage *)this;
|
|
COfsDocStorage::AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_INativeFileSystem))
|
|
{
|
|
*ppvObj = (INativeFileSystem *)this;
|
|
COfsDocStorage::AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_IAccessControl))
|
|
{
|
|
// BUGBUG need to artifically restrict to root & property storages
|
|
*ppvObj = (IAccessControl *)this;
|
|
COfsDocStorage::AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_IMarshal) &&
|
|
(_grfMode & STGM_DELETEONRELEASE) == 0)
|
|
{
|
|
*ppvObj = (IMarshal *)this;
|
|
COfsDocStorage::AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_IStorageReplica))
|
|
{
|
|
*ppvObj = (IStorageReplica *)this;
|
|
COfsDocStorage::AddRef();
|
|
}
|
|
else
|
|
{
|
|
sc = E_NOINTERFACE;
|
|
*ppvObj = NULL;
|
|
}
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::QueryInterface => %p\n",
|
|
*ppvObj));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::COfsDocStorage, public
|
|
//
|
|
// Synopsis: Empty object construction
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#pragma warning(disable: 4355)
|
|
COfsDocStorage::COfsDocStorage(void) : CPropertySetStorage(this)
|
|
#pragma warning(default: 4355)
|
|
{
|
|
ssDebugOut((DEB_ITRACE, "In COfsDocStorage::COfsDocStorage:%p()\n",
|
|
this));
|
|
_sig = 0;
|
|
_wcDrive = L'\0';
|
|
ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::COfsDocStorage\n"));
|
|
ENLIST_TRACKING(COfsDocStorage);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::InitFromHandle, public
|
|
//
|
|
// Synopsis: From-handle constructor
|
|
//
|
|
// Arguments: [h] - Handle of directory
|
|
// [grfMode] - Mode of handle
|
|
// [fRoot] - TRUE => storage is a root storage
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
|
|
//
|
|
// Notes: Takes a new reference on the handle
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE COfsDocStorage::InitFromHandle(HANDLE h,
|
|
WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
BOOL fRoot)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In COfsDocStorage::InitFromHandle:%p(%p, %lX)\n",
|
|
this, h, grfMode));
|
|
|
|
ssChk(ValidateMode(grfMode));
|
|
_h = h;
|
|
ssAssert(_h != NULL);
|
|
_grfMode = grfMode;
|
|
_sig = COfsDocStorage_SIG;
|
|
_fRoot = fRoot;
|
|
_wcDrive = GetDriveLetter (pwcsName);
|
|
ssChk(InitAccessControl(_h, _grfMode, FALSE, NULL));
|
|
ssChk(InitNtHandleMarshal(_h, _grfMode, STGFMT_DOCUMENT));
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::InitFromHandle\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::InitFromPath, public
|
|
//
|
|
// Synopsis: From-path constructor
|
|
//
|
|
// Arguments: [pwcsName] - Name of document
|
|
// [grfMode] - Mode
|
|
// [fCreate] - Create or open
|
|
// [pssSecurity] - Security
|
|
// [fRoot] - TRUE => root storage
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE COfsDocStorage::InitFromPath(HANDLE hParent,
|
|
WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
CREATEOPEN co,
|
|
LPSECURITY_ATTRIBUTES pssSecurity,
|
|
BOOL fRoot)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In COfsDocStorage::InitFromPath:%p("
|
|
"%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName, grfMode,
|
|
co, pssSecurity));
|
|
|
|
ssChk(ValidateMode(grfMode));
|
|
|
|
// BUGBUG: [mikese] This class is used for both root documents and
|
|
// embeddings, so FD_STORAGE is not always correct.
|
|
|
|
ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co, FD_STORAGE,
|
|
(LPSECURITY_ATTRIBUTES)pssSecurity, &_h));
|
|
|
|
_grfMode = grfMode;
|
|
_sig = COfsDocStorage_SIG;
|
|
_fRoot = fRoot;
|
|
_wcDrive = GetDriveLetter (pwcsName);
|
|
ssChk(InitAccessControl(_h, _grfMode, FALSE, NULL));
|
|
ssChk(InitNtHandleMarshal(_h, _grfMode, STGFMT_DOCUMENT));
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::InitFromPath\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::~COfsDocStorage, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
COfsDocStorage::~COfsDocStorage(void)
|
|
{
|
|
ssDebugOut((DEB_ITRACE, "In COfsDocStorage::~COfsDocStorage()\n"));
|
|
|
|
_sig = COfsDocStorage_SIGDEL;
|
|
|
|
//BUGBUG: Replace with real delete on release support?
|
|
if ((HANDLE)_h != NULL && (_grfMode & STGM_DELETEONRELEASE))
|
|
{
|
|
SCODE sc = DestroyTree(NULL, NULL, _h, FD_STORAGE);
|
|
if (!SUCCEEDED(sc))
|
|
{
|
|
ssDebugOut ((DEB_ERROR, " DestroyTree => %x\n", sc));
|
|
ssVerSucc(sc);
|
|
}
|
|
}
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::~COfsDocStorage\n"));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::CreateStream, public
|
|
//
|
|
// Synopsis: Creates a stream
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [grfMode] - Permissions
|
|
// [reserved1]
|
|
// [reserved2]
|
|
// [ppstm] - Stream return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstm]
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::CreateStream(WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
DWORD reserved1,
|
|
DWORD reserved2,
|
|
IStream **ppstm)
|
|
{
|
|
SCODE sc;
|
|
SafeCOfsDocStream pst;
|
|
WCHAR *pwcsNewName = NULL;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::CreateStream:%p("
|
|
"%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
|
|
reserved1, reserved2, ppstm));
|
|
|
|
ssChk(Validate());
|
|
if (reserved1 != 0 || reserved2 != 0)
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
if (grfMode & (STGM_CONVERT | STGM_PRIORITY | STGM_DELETEONRELEASE))
|
|
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
#ifdef TRANSACT_OLE
|
|
if (_grfMode & STGM_TRANSACTED)
|
|
{
|
|
if (grfMode & (STGM_CREATE | STGM_TRANSACTED))
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
if ((grfMode & STGM_SHARE_EXCLUSIVE) == 0)
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
}
|
|
#endif
|
|
ssChk(ValidateOutPtrBuffer(ppstm));
|
|
*ppstm = NULL;
|
|
|
|
pst.Attach(new COfsDocStream());
|
|
ssMem((COfsDocStream *)pst);
|
|
|
|
ssMem(pwcsNewName = MakeStreamName(pwcsName));
|
|
#ifdef TRANSACT_OLE
|
|
ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_CREATE,
|
|
(_grfMode & STGM_TRANSACTED) == STGM_TRANSACTED, NULL));
|
|
#else
|
|
ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_CREATE,
|
|
FALSE, NULL));
|
|
#endif
|
|
|
|
TRANSFER_INTERFACE(pst, IStream, ppstm);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::CreateStream => %p\n", *ppstm));
|
|
EH_Err:
|
|
delete pwcsNewName;
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::OpenStream, public
|
|
//
|
|
// Synopsis: Opens an existing stream
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [reserved1]
|
|
// [grfMode] - Permissions
|
|
// [reserved2]
|
|
// [ppstm] - Stream return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstm]
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::OpenStream(WCHAR const *pwcsName,
|
|
void *reserved1,
|
|
DWORD grfMode,
|
|
DWORD reserved2,
|
|
IStream **ppstm)
|
|
{
|
|
SCODE sc;
|
|
SafeCOfsDocStream pst;
|
|
WCHAR *pwcsNewName = NULL;
|
|
|
|
ssDebugOut((DEB_TRACE, "COfsDocStorage::OpenStream:%p("
|
|
"%ws, %p, %lX, %lu, %p)\n", this, pwcsName, reserved1,
|
|
grfMode, reserved2, ppstm));
|
|
|
|
ssChk(ValidateSimple());
|
|
ssChk(Validate());
|
|
if (reserved1 != 0 || reserved2 != 0)
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
if (grfMode & (STGM_CREATE | STGM_CONVERT))
|
|
ssErr(EH_Err, STG_E_INVALIDFLAG);
|
|
if (grfMode & (STGM_PRIORITY | STGM_DELETEONRELEASE))
|
|
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
#ifdef TRANSACT_OLE
|
|
if (_grfMode & STGM_TRANSACTED)
|
|
{
|
|
if (grfMode & (STGM_CREATE | STGM_TRANSACTED))
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
if ((grfMode & STGM_SHARE_EXCLUSIVE) == 0)
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
}
|
|
#endif
|
|
ssChk(ValidateOutPtrBuffer(ppstm));
|
|
*ppstm = NULL;
|
|
|
|
pst.Attach(new COfsDocStream());
|
|
ssMem((COfsDocStream *)pst);
|
|
|
|
ssMem(pwcsNewName = MakeStreamName(pwcsName));
|
|
#ifdef TRANSACT_OLE
|
|
ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_OPEN,
|
|
(_grfMode & STGM_TRANSACTED) == STGM_TRANSACTED, NULL));
|
|
#else
|
|
ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_OPEN,
|
|
FALSE, NULL));
|
|
#endif
|
|
|
|
TRANSFER_INTERFACE(pst, IStream, ppstm);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage:: OpenStream => %p\n", *ppstm));
|
|
|
|
EH_Err:
|
|
delete pwcsNewName;
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::CreateStorage, public
|
|
//
|
|
// Synopsis: Creates a child storage
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [grfMode] - Permissions
|
|
// [dwStgFmt] - Type of storage to create
|
|
// [pssSecurity] - Security
|
|
// [ppstg] - New storage return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstg]
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::CreateStorage(
|
|
WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
DWORD dwStgFmt,
|
|
LPSTGSECURITY pssSecurity,
|
|
IStorage **ppstg)
|
|
{
|
|
SCODE sc;
|
|
SafeCOfsDocStorage pstg;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::CreateStorage:%p("
|
|
"%ws, %lX, %lu, %p, %p)\n", this, pwcsName, grfMode,
|
|
dwStgFmt, pssSecurity, ppstg));
|
|
|
|
ssChk(ValidateSimple());
|
|
ssChk(Validate());
|
|
ssChk(VerifyStgFmt(dwStgFmt));
|
|
ssAssert(_h != NULL);
|
|
ssChk(ValidateOutPtrBuffer(ppstg));
|
|
*ppstg = NULL;
|
|
|
|
//FORCE_READ(grfMode);
|
|
pstg.Attach(new COfsDocStorage());
|
|
ssMem((COfsDocStorage *)pstg);
|
|
|
|
ssChk(pstg->InitFromPath(_h, pwcsName, grfMode, CO_CREATE,
|
|
(LPSECURITY_ATTRIBUTES) pssSecurity, FALSE));
|
|
|
|
if ((grfMode & STGM_EDIT_ACCESS_RIGHTS) && // child is editing ACLS
|
|
(_grfMode & STGM_TRANSACTED)) // parent is transacted
|
|
{
|
|
InsertChild (pstg); // hold on to the child for
|
|
pstg->AddRef(); // nested transactions
|
|
}
|
|
|
|
TRANSFER_INTERFACE(pstg, IStorage, ppstg);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::CreateStorage => %p\n",*ppstg));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::OpenStorage, public
|
|
//
|
|
// Synopsis: Gets an existing child storage
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [pstgPriority] - Priority reopens
|
|
// [grfMode] - Permissions
|
|
// [snbExclude] - Priority reopens
|
|
// [reserved]
|
|
// [ppstg] - Storage return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstg]
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::OpenStorage(WCHAR const *pwcsName,
|
|
IStorage *pstgPriority,
|
|
DWORD grfMode,
|
|
SNB snbExclude,
|
|
DWORD reserved,
|
|
IStorage **ppstg)
|
|
{
|
|
SCODE sc;
|
|
SafeCOfsDocStorage pstg;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::OpenStorage:%p("
|
|
"%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority,
|
|
grfMode, snbExclude, reserved, ppstg));
|
|
|
|
ssChk(ValidateSimple());
|
|
ssChk(Validate());
|
|
if (pstgPriority != NULL || snbExclude != NULL ||
|
|
reserved != 0)
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
if (grfMode & (STGM_CREATE | STGM_CONVERT))
|
|
ssErr(EH_Err, STG_E_INVALIDFLAG);
|
|
ssChk(ValidateOutPtrBuffer(ppstg));
|
|
*ppstg = NULL;
|
|
|
|
ssAssert(_h != NULL);
|
|
|
|
// The only thing we can open inside a document is an embedding
|
|
|
|
pstg.Attach(new COfsDocStorage());
|
|
ssMem((COfsDocStorage *)pstg);
|
|
|
|
ssChk(pstg->InitFromPath(_h, pwcsName, grfMode, CO_OPEN, NULL, FALSE));
|
|
|
|
if (snbExclude != NULL)
|
|
ssChk(pstg->ExcludeEntries(snbExclude));
|
|
|
|
if ((grfMode & STGM_EDIT_ACCESS_RIGHTS) && // child is editing ACLS
|
|
(_grfMode & STGM_TRANSACTED)) // parent is transacted
|
|
{
|
|
InsertChild (pstg); // hold on to the child for
|
|
pstg->AddRef(); // nested transactions
|
|
}
|
|
|
|
TRANSFER_INTERFACE(pstg, IStorage, ppstg);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::OpenStorage => %p\n", *ppstg));
|
|
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::CopyTo, public
|
|
//
|
|
// Synopsis: Makes a copy of a storage
|
|
//
|
|
// 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: 07-Feb-94 PhilipLa Copied from DrewB's stuff
|
|
//
|
|
// Notes: BUGBUG - This function operates recursively and so
|
|
// is bounded by stack space
|
|
// It could also be optimized to recognize special cases
|
|
// of copying (like treating a docfile as a file)
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::CopyTo(DWORD ciidExclude,
|
|
IID const *rgiidExclude,
|
|
SNB snbExclude,
|
|
IStorage *pstgDest)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::CopyTo:%p(%lu, %p, %p, %p)\n",
|
|
this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
|
|
|
|
SCODE sc;
|
|
ULONG i;
|
|
BOOL fCopyStorage = TRUE;
|
|
BOOL fCopyStreams = TRUE;
|
|
STATSTG stat;
|
|
STATSTG statDest;
|
|
DWORD grfModeFrom;
|
|
DWORD grfModeTo;
|
|
DWORD grfModeTo2;
|
|
|
|
ssChk(ValidateSimple());
|
|
ssChk(Validate());
|
|
if (!IsValidInterface(pstgDest))
|
|
olErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
|
|
// Stat the source to obtain the open mode (and also class id and
|
|
// state bits).
|
|
ssChk(Stat(&stat, STATFLAG_NONAME));
|
|
// The open mode for subelements of the source is derived from that
|
|
// of the root. We preserve the sharing mode part, force read only
|
|
// and direct (because we do not want a nested transaction).
|
|
grfModeFrom = (stat.grfMode & (STGM_SHARE_EXCLUSIVE|
|
|
STGM_SHARE_DENY_READ|
|
|
STGM_SHARE_DENY_WRITE|
|
|
STGM_SHARE_DENY_NONE))
|
|
| STGM_READ | STGM_DIRECT;
|
|
|
|
// Stat the destination to obtain the open mode
|
|
ssChk(pstgDest->Stat(&statDest,STATFLAG_NONAME));
|
|
// The open mode for subelements of the destination is derived from that
|
|
// of the root. We force direct mode, since we do not want nested
|
|
// transactions.
|
|
grfModeTo = statDest.grfMode & (~(STGM_TRANSACTED | STGM_DELETEONRELEASE));
|
|
|
|
// Copy class ID and state bits if the destination supports them
|
|
// BUGBUG [mikese] Do we really need to do this, since won't these
|
|
// get copied as part of the system properties?
|
|
sc = GetScode(pstgDest->SetClass(stat.clsid));
|
|
if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
|
|
olErr(EH_Err, sc);
|
|
sc = GetScode(pstgDest->SetStateBits(stat.grfStateBits, 0xffffffff));
|
|
if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
|
|
olErr(EH_Err, sc);
|
|
|
|
// Check IID exclusions
|
|
for (i = 0; i < ciidExclude; i++)
|
|
{
|
|
if (IsEqualIID(rgiidExclude[i], IID_IStorage))
|
|
{
|
|
fCopyStorage = FALSE;
|
|
}
|
|
else if ( IsEqualIID ( rgiidExclude[i], IID_IStream ) )
|
|
{
|
|
fCopyStreams = FALSE;
|
|
}
|
|
}
|
|
|
|
sc = S_OK;
|
|
|
|
if (fCopyStorage)
|
|
{
|
|
SCODE scFinal;
|
|
WCHAR pwcsName[MAXIMUM_FILENAME_LENGTH];
|
|
FILEDIR fd;
|
|
CNtEnum nte;
|
|
CDfName dfn;
|
|
BOOL fOfs;
|
|
HANDLE hDest = NULL;
|
|
|
|
// henrylee: BUGBUG this is a hack to detect copyto a docfile
|
|
INativeFileSystem *pINFS;
|
|
if (SUCCEEDED(pstgDest->QueryInterface (IID_INativeFileSystem,
|
|
(void**) &pINFS)))
|
|
{
|
|
pINFS->GetHandle(&hDest);
|
|
pINFS->Release();
|
|
grfModeTo2 = grfModeTo;
|
|
fOfs = TRUE;
|
|
}
|
|
else
|
|
{ // permissions for docfile compatibility
|
|
grfModeTo = STGM_WRITE | STGM_SHARE_EXCLUSIVE;
|
|
grfModeTo2 = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
|
|
fOfs = FALSE;
|
|
}
|
|
|
|
scFinal = S_OK;
|
|
ssAssert(_h != NULL);
|
|
ssChk(nte.InitFromHandle(_h, TRUE));
|
|
for (;;)
|
|
{
|
|
sc = nte.Next(&stat, pwcsName, NTE_BUFFERNAME, &fd);
|
|
if (sc == S_FALSE)
|
|
break;
|
|
else if (FAILED(sc))
|
|
olErr(EH_Err, sc);
|
|
|
|
// Ignore . and ..
|
|
if (!wcscmp(pwcsName, L".") || !wcscmp(pwcsName, L".."))
|
|
continue;
|
|
|
|
// BUGBUG: [mikese] What's wrong with raw pwcsName?
|
|
dfn.Set(pwcsName);
|
|
if (snbExclude == NULL || !NameInSNB(&dfn, snbExclude))
|
|
{
|
|
if ( stat.type == STGTY_STORAGE )
|
|
{
|
|
SafeIStorage pstgFrom, pstgTo;
|
|
STATSTG statTo;
|
|
|
|
olHChkTo(EH_Next, OpenStorage(pwcsName, NULL,
|
|
grfModeFrom,
|
|
NULL, NULL, &pstgFrom));
|
|
|
|
// We know that the source must be an embedding (STGFMT_DOCUMENT)
|
|
sc = pstgDest->CreateStorage( pwcsName,
|
|
grfModeTo | STGM_FAILIFTHERE,
|
|
STGFMT_DOCUMENT,
|
|
NULL,
|
|
&pstgTo );
|
|
if (FAILED(sc))
|
|
{
|
|
if (sc == STG_E_FILEALREADYEXISTS)
|
|
{
|
|
// Try to open rather than creating
|
|
sc = pstgDest->OpenStorage( pwcsName, NULL,
|
|
grfModeTo2,
|
|
NULL, NULL,
|
|
&pstgTo );
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
sc = pstgTo->Stat ( &statTo, STATFLAG_NONAME );
|
|
if (FAILED(sc) ||
|
|
statTo.STATSTG_dwStgFmt != STGFMT_DOCUMENT)
|
|
{
|
|
sc = STG_E_INVALIDFUNCTION;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(sc))
|
|
sc = pstgFrom->CopyTo( ciidExclude, rgiidExclude,
|
|
snbExclude, pstgTo);
|
|
}
|
|
else if ( (stat.type == STGTY_STREAM) && fCopyStreams )
|
|
{
|
|
SafeIStream pstmTo, pstmFrom;
|
|
static ULARGE_INTEGER uli = { 0xFFFFFFFF, 0xFFFFFFFF };
|
|
|
|
olHChkTo(EH_Next, OpenStream ( pwcsName,
|
|
NULL,
|
|
grfModeFrom,
|
|
0, &pstmFrom ) );
|
|
// BUGBUG instead of overwriting, we create another
|
|
// stream and rename -- really need transacted mode
|
|
sc = pstgDest->CreateStream ( pwcsName,
|
|
grfModeTo | STGM_FAILIFTHERE,
|
|
0, 0, &pstmTo );
|
|
if (sc == STG_E_FILEALREADYEXISTS)
|
|
{
|
|
WCHAR awcsName[MAXIMUM_FILENAME_LENGTH];
|
|
wcscpy (awcsName, pwcsName);
|
|
if (fOfs)
|
|
awcsName[0] = L'@';
|
|
IStream *pstm;
|
|
olHChkTo(EH_Next, pstgDest->CreateStream ( awcsName,
|
|
grfModeTo|STGM_CREATE,
|
|
0, 0, &pstm ));
|
|
sc = pstmFrom->CopyTo ( pstm, uli, NULL, NULL );
|
|
pstm->Release();
|
|
if (SUCCEEDED(sc) && fOfs)
|
|
{
|
|
ssAssert (hDest != NULL);
|
|
WCHAR awcsSave[MAXIMUM_FILENAME_LENGTH+4];
|
|
wcscpy (awcsSave, pwcsName);
|
|
wcscat (awcsSave, L".old");
|
|
sc = RenameChild (hDest, pwcsName, awcsSave);
|
|
if (!SUCCEEDED(sc))
|
|
{
|
|
sc = DestroyTree (hDest, awcsSave, NULL, FD_FILE);
|
|
sc = RenameChild (hDest, pwcsName, awcsSave);
|
|
}
|
|
olHChkTo(EH_Next,RenameChild (hDest, awcsName, pwcsName));
|
|
sc = DestroyTree (hDest, awcsSave, NULL, FD_FILE);
|
|
}
|
|
else if (fOfs)
|
|
olHChkTo(EH_Next,pstgDest->DestroyElement (awcsName));
|
|
}
|
|
else if ( SUCCEEDED(sc) )
|
|
{
|
|
sc = pstmFrom->CopyTo ( pstmTo, uli, NULL, NULL );
|
|
}
|
|
}
|
|
|
|
EH_Next:
|
|
if (FAILED(sc))
|
|
scFinal = sc;
|
|
}
|
|
}
|
|
sc = scFinal;
|
|
}
|
|
|
|
EH_Err:
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::CopyTo\n"));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::MoveElementTo, public
|
|
//
|
|
// Synopsis: Move an element of a storage to another storage
|
|
//
|
|
// 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: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::MoveElementTo(WCHAR const *pwcsName,
|
|
IStorage *pstgParent,
|
|
WCHAR const *ptcsNewName,
|
|
DWORD grfFlags)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::MoveElementTo:%p("
|
|
"%ws, %p, %ws, %lu)\n", this, pwcsName, pstgParent,
|
|
ptcsNewName, grfFlags));
|
|
|
|
ssChk(ValidateSimple());
|
|
ssChk(Validate());
|
|
ssChk(VerifyMoveFlags(grfFlags));
|
|
|
|
sc = GenericMoveElement(this, pwcsName, pstgParent, ptcsNewName, grfFlags);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::MoveElementTo => %lX\n", sc));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::Commit, public
|
|
//
|
|
// Synopsis: Commits transacted changes
|
|
//
|
|
// Arguments: [dwFlags] - DFC_*
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::Commit(DWORD dwFlags)
|
|
{
|
|
SCODE sc = S_OK;
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::Commit:%p(%lX)\n",
|
|
this, dwFlags));
|
|
|
|
#ifdef TRANSACT_OLE
|
|
if (_grfMode & STGM_TRANSACTED)
|
|
{
|
|
IO_STATUS_BLOCK iosb;
|
|
COMMIT_PARAMETERS ftci = {FALSE, dwFlags};
|
|
NTSTATUS nts;
|
|
|
|
if ((dwFlags & ~(STGC_DEFAULT | STGC_ONLYIFCURRENT)) != 0)
|
|
ssErr (EH_Err, STG_E_INVALIDPARAMETER);
|
|
|
|
if (!NT_SUCCESS(nts = NtFsControlFile (_h, NULL, NULL, NULL, &iosb,
|
|
FSCTL_XOLE_COMMIT, &ftci, sizeof(ftci), NULL, 0)))
|
|
sc = NtStatusToScode(nts);
|
|
else
|
|
sc = S_OK;
|
|
}
|
|
#endif // TRANSACT_OLE
|
|
|
|
if (_grfMode & STGM_EDIT_ACCESS_RIGHTS)
|
|
ssChk(CommitAccessRights(0));
|
|
EH_Err:
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::Commit => %lX\n",sc));
|
|
return ssResult (sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::Revert, public
|
|
//
|
|
// Synopsis: Reverts transacted changes
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::Revert(void)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::Revert:%p\n", this));
|
|
|
|
SCODE sc = S_OK;
|
|
ssChk(ValidateSimple());
|
|
|
|
#ifdef TRANSACT_OLE
|
|
if (_grfMode & STGM_TRANSACTED)
|
|
{
|
|
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
IO_STATUS_BLOCK iosb;
|
|
COMMIT_PARAMETERS ftci = {TRUE, 0L};
|
|
NTSTATUS nts;
|
|
|
|
if (!NT_SUCCESS(nts = NtFsControlFile (_h, NULL, NULL, NULL, &iosb,
|
|
FSCTL_XOLE_COMMIT, &ftci, sizeof(ftci), NULL, 0)))
|
|
sc = NtStatusToScode(nts);
|
|
else
|
|
sc = S_OK;
|
|
}
|
|
#endif // TRANSACT_OLE
|
|
|
|
if (_grfMode & STGM_EDIT_ACCESS_RIGHTS)
|
|
ssChk(RevertAccessRights());
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::Revert => %lX\n",sc));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::EnumElements, public
|
|
//
|
|
// Synopsis: Starts an iterator
|
|
//
|
|
// Arguments: [reserved1]
|
|
// [reserved2]
|
|
// [reserved3]
|
|
// [ppenm] - Enumerator return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppenm]
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::EnumElements(DWORD reserved1,
|
|
void *reserved2,
|
|
DWORD reserved3,
|
|
IEnumSTATSTG **ppenm)
|
|
{
|
|
SCODE sc;
|
|
SafeCOfsDirEnum pde;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::EnumElements:%p("
|
|
"%lu, %p, %lu, %p)\n", this, reserved1, reserved2,
|
|
reserved3, ppenm));
|
|
|
|
ssChk(ValidateSimple());
|
|
if (ppenm == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDPOINTER) // missing ';' macro problem
|
|
else
|
|
ssChk(ValidateOutPtrBuffer(ppenm));
|
|
*ppenm = NULL;
|
|
if (reserved1 != 0 || reserved2 != NULL || reserved3 != 0)
|
|
olErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
|
|
ssChk(Validate());
|
|
|
|
pde.Attach(new COfsDirEnum(TRUE));
|
|
olMem((COfsDirEnum *)pde);
|
|
ssAssert(_h != NULL);
|
|
ssChk(pde->InitFromHandle(_h));
|
|
TRANSFER_INTERFACE(pde, IEnumSTATSTG, ppenm);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::EnumElements => %p\n",
|
|
*ppenm));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::DestroyElement, public
|
|
//
|
|
// Synopsis: Permanently deletes an element of a storage
|
|
//
|
|
// Arguments: [pwcsName] - Name of element
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::DestroyElement(WCHAR const *pwcsName)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::DestroyElement:%p(%ws)\n",
|
|
this, pwcsName));
|
|
|
|
ssChk(ValidateSimple());
|
|
ssChk(Validate());
|
|
|
|
ssAssert(_h != NULL);
|
|
#ifdef TRANSACT_OLE
|
|
if (_grfMode & STGM_TRANSACTED)
|
|
sc = DestroyTree(_h, pwcsName, NULL, FD_STREAM);
|
|
else
|
|
#endif
|
|
sc = DestroyTree(_h, pwcsName, NULL, FD_FILE);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::DestroyElement\n"));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::RenameElement, public
|
|
//
|
|
// Synopsis: Renames an element of a storage
|
|
//
|
|
// Arguments: [pwcsName] - Current name
|
|
// [pwcsNewName] - New name
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::RenameElement(WCHAR const *pwcsName,
|
|
WCHAR const *pwcsNewName)
|
|
{
|
|
//BUGBUG: Reimplement?
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::RenameElement:%p(%ws, %ws)\n",
|
|
this, pwcsName, pwcsNewName));
|
|
|
|
#ifdef TRANSACT_OLE
|
|
if (_grfMode & STGM_TRANSACTED)
|
|
ssErr (EH_Err, STG_E_INVALIDFUNCTION);
|
|
#endif
|
|
ssChk(ValidateSimple());
|
|
ssChk(Validate());
|
|
// pwcsName is checked by GetFileOrDirHandle
|
|
ssChk(CheckFdName(pwcsNewName));
|
|
|
|
ssAssert(_h != NULL);
|
|
sc = RenameChild(_h, pwcsName, pwcsNewName);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::RenameElement\n"));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::SetElementTimes, public
|
|
//
|
|
// Synopsis: Sets element time stamps
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [pctime] - Create time
|
|
// [patime] - Access time
|
|
// [pmtime] - Modify time
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::SetElementTimes(WCHAR const *pwcsName,
|
|
FILETIME const *pctime,
|
|
FILETIME const *patime,
|
|
FILETIME const *pmtime)
|
|
{
|
|
SCODE sc;
|
|
SafeNtHandle h;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::SetElementTimes:%p("
|
|
"%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
|
|
|
|
if (pwcsName != NULL)
|
|
ssChk(ValidateSimple());
|
|
ssChk(Validate());
|
|
|
|
ssAssert(_h != NULL);
|
|
if (pwcsName != NULL)
|
|
{
|
|
#ifdef TRANSACT_OLE
|
|
if (_grfMode & STGM_TRANSACTED)
|
|
ssErr (EH_Err, STG_E_INVALIDFUNCTION);
|
|
#endif
|
|
ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_WRITE, &h,NULL,NULL,NULL));
|
|
sc = SetTimes(h, pctime, patime, pmtime);
|
|
}
|
|
else
|
|
sc = SetTimes(_h, pctime, patime, pmtime);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::SetElementTimes\n"));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::SetClass, public
|
|
//
|
|
// Synopsis: Sets storage class
|
|
//
|
|
// Arguments: [clsid] - class id
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::SetClass(REFCLSID clsid)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::SetClass:%p(clsid)\n", this));
|
|
NTSTATUS nts = RtlSetClassId(_h, &clsid);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode(nts);
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::SetClass => %lX\n", sc));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::SetStateBits, public
|
|
//
|
|
// Synopsis: Sets state bits
|
|
//
|
|
// Arguments: [grfStateBits] - state bits
|
|
// [grfMask] - state bits mask
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
|
|
{
|
|
NTSTATUS nts;
|
|
SCODE sc = S_OK;
|
|
IO_STATUS_BLOCK iosb;
|
|
FILE_OLE_STATE_BITS_INFORMATION fosbi;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::SetStateBits:%p("
|
|
"%lu, %lu)\n", this, grfStateBits, grfMask));
|
|
|
|
ssChk(ValidateSimple());
|
|
fosbi.StateBits = grfStateBits;
|
|
fosbi.StateBitsMask = grfMask;
|
|
|
|
nts = NtSetInformationFile(_h, &iosb, &fosbi,
|
|
sizeof(FILE_OLE_STATE_BITS_INFORMATION),
|
|
FileOleStateBitsInformation);
|
|
if (!NT_SUCCESS(nts))
|
|
ssErr(EH_Err, NtStatusToScode(nts));
|
|
EH_Err:
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::SetStateBits => %lX\n", sc));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::Stat, public
|
|
//
|
|
// Synopsis: Fills in a buffer of information about this object
|
|
//
|
|
// Arguments: [pstatstg] - Buffer
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pstatstg]
|
|
//
|
|
// History: 07-Feb-94 PhilipLa Created
|
|
// 24-Mar-95 HenryLee Set drive letter to fix Stat problem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
|
|
{
|
|
SCODE sc;
|
|
STATSTG stat;
|
|
FILEDIR fd;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COfsDocStorage::Stat:%p(%p, %lX)\n",
|
|
this, pstatstg, grfStatFlag));
|
|
|
|
ssChk(ValidateSimple());
|
|
ssChk(VerifyStatFlag(grfStatFlag));
|
|
ssChk(Validate());
|
|
|
|
__try
|
|
{
|
|
ssAssert(_h != NULL);
|
|
stat.clsid = CLSID_NULL;
|
|
sc = StatNtHandle(_h, grfStatFlag, 0, &stat, NULL, NULL, &fd);
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
|
|
if (stat.pwcsName)
|
|
if (!_fRoot)
|
|
{
|
|
// The name coming back from StatNtHandle is a full
|
|
// path from the root. We scan forward looking for
|
|
// the final "\" which delimits the name of the stream.
|
|
|
|
WCHAR *pwcs = stat.pwcsName;
|
|
WCHAR *pwcsSlash = pwcs;
|
|
|
|
while (*pwcs != L'\0')
|
|
if (*pwcs++ == L'\\')
|
|
pwcsSlash = pwcs;
|
|
|
|
// pwcsSlash now points at the name of the stream. Move it
|
|
// back to the beginning of the block
|
|
|
|
wcscpy (stat.pwcsName, pwcsSlash);
|
|
}
|
|
else
|
|
{
|
|
// Now we tack on the drive letter to the filename, since
|
|
// NtQueryInformationFile doesn't return the drive letter,
|
|
// and NtQueryObject returns something like
|
|
// "\Device\Harddisk1\Partition1" // HenryLee
|
|
SetDriveLetter (stat.pwcsName, _wcDrive);
|
|
}
|
|
|
|
// BUGBUG: Can't put this assert in until we have a way to distinguish
|
|
// an empty storage from a directory. :-(
|
|
// ssAssert(fd == FD_STORAGE);
|
|
stat.grfMode = _grfMode &
|
|
(STGM_DIRECT | STGM_TRANSACTED | STGM_READ |
|
|
STGM_WRITE | STGM_READWRITE | STGM_SHARE_DENY_NONE |
|
|
STGM_SHARE_DENY_READ | STGM_SHARE_DENY_WRITE |
|
|
STGM_SHARE_EXCLUSIVE | STGM_PRIORITY |
|
|
STGM_DELETEONRELEASE);
|
|
|
|
stat.cbSize.HighPart = stat.cbSize.LowPart = 0;
|
|
stat.STATSTG_dwStgFmt = STGFMT_DOCUMENT;
|
|
*pstatstg = stat;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
if (stat.pwcsName)
|
|
ssVerSucc(CoMemFree(stat.pwcsName));
|
|
sc = HRESULT_FROM_NT(GetExceptionCode());
|
|
}
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COfsDocStorage::Stat\n"));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::ValidateMode, private
|
|
//
|
|
// Synopsis: Checks for legal access modes
|
|
//
|
|
// Arguments: [grfMode] - Mode
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 09-Jul-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE COfsDocStorage::ValidateMode(DWORD grfMode)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In COfsDocStorage::ValidateMode:%p(0x%lX)\n",
|
|
this, grfMode));
|
|
// BUGBUG - Can we simply ignore priority mode?
|
|
#ifdef TRANSACT_OLE
|
|
if (grfMode & STGM_TRANSACTED)
|
|
{
|
|
if ((grfMode &
|
|
(STGM_SHARE_DENY_NONE | STGM_SHARE_DENY_READ |
|
|
STGM_SHARE_DENY_WRITE | STGM_SHARE_EXCLUSIVE)) !=
|
|
STGM_SHARE_DENY_NONE)
|
|
ssErr (EH_Err, STG_E_INVALIDPARAMETER);
|
|
if (grfMode & STGM_DELETEONRELEASE)
|
|
ssErr (EH_Err, STG_E_INVALIDPARAMETER);
|
|
}
|
|
#endif
|
|
if ((grfMode & STGM_CONVERT) != 0)
|
|
ssErr (EH_Err, STG_E_INVALIDFLAG);
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::ValidateMode => 0x%lX\n",
|
|
sc));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::ExtValidate, private
|
|
//
|
|
// Synopsis: COfsPropSet validation routine
|
|
//
|
|
// History: 18-Aug-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE COfsDocStorage::ExtValidate(void)
|
|
{
|
|
return Validate();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::GetHandle, private from INativeFileSystem
|
|
//
|
|
// Synopsis: Get the internal handle
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE COfsDocStorage::GetHandle(HANDLE *ph)
|
|
{
|
|
*ph = _h;
|
|
return(S_OK);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::ExcludeEntries, public
|
|
//
|
|
// Synopsis: excludes the SNB list after opening
|
|
//
|
|
// Arguments: [snbExclude] - zero out these elements
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 09-Aug-95 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE COfsDocStorage::ExcludeEntries (SNB snbExclude)
|
|
{
|
|
SCODE sc = S_OK;
|
|
IEnumSTATSTG *penm;
|
|
IStorage *pstg;
|
|
IStream *pstm;
|
|
STATSTG sstg;
|
|
CDfName dfnName;
|
|
const ULARGE_INTEGER uli = {0, 0};
|
|
|
|
ssAssert (this != NULL);
|
|
ssDebugOut((DEB_ITRACE, "In COfsDocStorage::ExcludeEntries(%p)\n", this));
|
|
ssChk(EnumElements(0, NULL, 0, &penm));
|
|
for (;;)
|
|
{
|
|
olChkTo(EH_penm, penm->Next(1, &sstg, NULL));
|
|
if (S_FALSE == sc)
|
|
{
|
|
sc = S_OK;
|
|
break;
|
|
}
|
|
dfnName.Set (sstg.pwcsName);
|
|
if (NameInSNB (&dfnName, snbExclude) == S_OK)
|
|
{
|
|
switch (REAL_STGTY(sstg.type))
|
|
{
|
|
case STGTY_STORAGE:
|
|
ssChkTo(EH_pwcsName, DestroyTree(_h,
|
|
sstg.pwcsName, NULL, FD_STORAGE));
|
|
ssChkTo(EH_pwcsName, CreateStorage(sstg.pwcsName,
|
|
STGM_READWRITE | STGM_CREATE,
|
|
STGFMT_DOCUMENT, NULL, &pstg));
|
|
ssVerSucc(pstg->Release());
|
|
break;
|
|
case STGTY_STREAM:
|
|
ssChkTo(EH_pwcsName, OpenStream(sstg.pwcsName, NULL,
|
|
STGM_WRITE, NULL, &pstm));
|
|
sc = pstm->SetSize(uli);
|
|
ssVerSucc(pstm->Release());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
EH_pwcsName:
|
|
TaskMemFree(sstg.pwcsName);
|
|
if (FAILED(sc))
|
|
break;
|
|
}
|
|
EH_penm:
|
|
ssVerSucc(penm->Release());
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::ExcludeEntries\n"));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::GetStorage, public IPrivateStorage
|
|
//
|
|
// Synopsis: Returns the IStorage for this object.
|
|
//
|
|
// Notes: This member is called by CPropertyStorage.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(IStorage *)
|
|
COfsDocStorage::GetStorage(VOID)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::Lock, public IPrivateStorage
|
|
//
|
|
// Synopsis: Acquires the semaphore associated with the docfile.
|
|
//
|
|
// Notes: This member is called by CPropertyStorage.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
COfsDocStorage::Lock(DWORD dwTimeout)
|
|
{
|
|
return STG_E_UNIMPLEMENTEDFUNCTION;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::Unlock, public IPrivateStorage
|
|
//
|
|
// Synopsis: Releases the semaphore associated with the docfile.
|
|
//
|
|
// Notes: This member is called by CPropertyStorage.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(VOID)
|
|
COfsDocStorage::Unlock(VOID)
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COfsDocStorage::GetServerInfo, public IStorageReplica
|
|
//
|
|
// Synopsis: Get the actual DFS path for a storage's home location
|
|
//
|
|
// Notes: This member is exposed for Internal Use Only
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP COfsDocStorage::GetServerInfo(
|
|
IN OUT LPWSTR lpServerName,
|
|
IN OUT LPDWORD lpcbServerName,
|
|
IN OUT LPWSTR lpReplSpecificPath,
|
|
IN OUT LPDWORD lpcbReplSpecificPath)
|
|
{
|
|
return GetHandleServerInfo (_h,
|
|
lpServerName,
|
|
lpcbServerName,
|
|
lpReplSpecificPath,
|
|
lpcbReplSpecificPath);
|
|
}
|
|
|