Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1701 lines
52 KiB

// Microsoft OLE
// Copyright (C) Microsoft Corporation, 1992 - 1996.
// All rights reserved.
//
// File: vcnode.cxx
//
// Contents: Implementation for in-memory Virtual Container Node class.
//
// Classes: VirtualCtrNode (vcn)
//
// Functions: VirtualCtrNode()
// ~VirtualCtrNode()
// Init
// AppendChildCtr
// AppendSisterCtr
// AppendFirstChildStm
// CreateRoot
// CreateRootEx
// Create
// Open
// OpenRoot
// OpenRootEx
// Close
// Commit
// Rename
// Destroy
// Stat
// EnumElements
// SetElementTimes
// SetClass
// SetStateBits
// MoveElementTo
// Revert
// CopyTo
// AddRefCount
// QueryInterface
// CreateRootOnCustomILockBytes
// OpenRootOnCustomILockBytes
//
// NOTE: All above functions are public
//
// History: DeanE 21-Mar-96 Created
// Narindk 24-Apr-96 Added more functions
// SCousens 2-Feb-97 Added Open/CreateRoot for NSS files
//--------------------------------------------------------------------------
#include <dfheader.hxx>
#pragma hdrstop
// Debug object declaration
//
DH_DECLARE;
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::VirtualCtrNode, public
//
// Synopsis: Constructor.
//
// Arguments: None.
//
// Returns: Nothing.
//
// History: DeanE 21-Mar-96 Created
//---------------------------------------------------------------------------
VirtualCtrNode::VirtualCtrNode() :
_pvcnChild(NULL),
_pvcnSister(NULL),
_pvcnParent(NULL),
_pvsnStream(NULL),
_cStreams(0),
_ptszName(NULL),
_cChildren(0),
_dwCRC(CRC_PRECONDITION),
_pstg(NULL)
{
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::VirtualCtrNode"));
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::~VirtualCtrNode, public
//
// Synopsis: Destructor. Frees resources associated with this object,
// including closing the storage if open and removing this
// tree from memory.
//
// Arguments: None.
//
// Returns: Nothing.
//
// History: DeanE 21-Mar-96 Created
//---------------------------------------------------------------------------
VirtualCtrNode::~VirtualCtrNode()
{
ULONG ulRef = 0;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::~VirtualCtrNode"));
if(NULL != _ptszName)
{
delete _ptszName;
_ptszName = NULL;
}
if ( NULL != _pstg )
{
ulRef = _pstg->Release();
// Assert if ulRef is not zero, object is being destructed.
DH_ASSERT(0 == ulRef);
_pstg = NULL;
}
}
//+--------------------------------------------------------------------------
// Member: VirtualStmNode::Init, public
//
// Synopsis: Initializes a storage node - does not open or create the
// actual storage.
//
// Arguments: [tszName] - Name of this storage
// [cStg] - Number of storages contained in this storage.
// [cStm] - Number of streams contained in this storage.
//
// Returns: S_OK if node initialized successfully, otherwise an error.
//
// Notes: BUGBUG - Not Nashville Safe...
//
// History: Narindk 18-Apr-96 Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::Init( LPTSTR tszName, ULONG cStg, ULONG cStm)
{
HRESULT hr = S_OK;
DH_VDATESTRINGPTR(tszName);
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::Init"));
DH_ASSERT(NULL != tszName);
if( S_OK == hr)
{
_ptszName = new TCHAR[_tcslen(tszName)+1];
if (_ptszName == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
_tcscpy(_ptszName, tszName);
_cChildren = cStg;
_cStreams = cStm;
}
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::AppendChildCtr, public
//
// Synopsis: Appends the node passed to the end of this nodes' child
// node chain.
//
// Arguments: [pcnNew] - The new node to append.
//
// Returns: S_OK for success or an error code.
//
// History: 17-Apr-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::AppendChildCtr(VirtualCtrNode *pvcnNew)
{
HRESULT hr = S_OK;
VirtualCtrNode *pvcnTrav = this;
DH_VDATEPTRIN(pvcnNew, VirtualCtrNode);
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::AppendChildCtr"));
DH_ASSERT(NULL != pvcnNew);
if(S_OK == hr)
{
// Find the last child in the structure
while (NULL != pvcnTrav->_pvcnChild)
{
pvcnTrav = pvcnTrav->_pvcnChild;
}
// Append the new node as a child of the last node,
// and make the new node point to the last node as it's parent
pvcnTrav->_pvcnChild = pvcnNew;
pvcnNew->_pvcnParent = pvcnTrav;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::AppendSisterCtr, public
//
// Synopsis: Appends the node passed to the end of this nodes' sister
// node chain.
//
// Arguments: [pcnNew] - The new node to append.
//
// Returns: S_OK for success or an error code.
//
// History: 17-Apr-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::AppendSisterCtr(VirtualCtrNode *pvcnNew)
{
HRESULT hr = S_OK;
VirtualCtrNode *pvcnTrav = this;
DH_VDATEPTRIN(pvcnNew, VirtualCtrNode);
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::AppendSisterCtr"));
DH_ASSERT(NULL != pvcnNew);
if(S_OK == hr)
{
// Find the last sister in the chain
while (NULL != pvcnTrav->_pvcnSister)
{
pvcnTrav = pvcnTrav->_pvcnSister;
}
// Append the new node as a sister of the last node,
// and make the new node point to this nodes parent as it's parent
pvcnTrav->_pvcnSister = pvcnNew;
pvcnNew->_pvcnParent = pvcnTrav->_pvcnParent;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::AppendFirstChildStm, public
//
// Synopsis: Appends the first stream to its parent storage
//
// Arguments: [pcnNew] - The new node to append.
//
// Returns: S_OK for success or an error code.
//
// History: 17-Apr-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::AppendFirstChildStm(VirtualStmNode *pvsnNew)
{
HRESULT hr = S_OK;
VirtualCtrNode *pvcnCurrent= this;
DH_VDATEPTRIN(pvsnNew, VirtualStmNode);
DH_FUNCENTRY(&hr,DH_LVL_DFLIB,TEXT("VirtualCtrNode::AppendFirstChildStm"));
DH_ASSERT(NULL != pvsnNew);
if(S_OK == hr)
{
// Append the new stream node (first stream node) to parent storage,
// and make the new stream node point to storage as it's parent
pvcnCurrent->_pvsnStream = pvsnNew;
pvsnNew->_pvcnParent = pvcnCurrent;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::CreateRoot, public
//
// Synopsis: Wrapper for StgCreateDocFile that will create a new root
// compound file in the file system.
//
// Arguments: [grfmode] - Access mode for opening new compound file.
// [dwReserved] - Reserved by OLE for future use, must be zero.
//
// Returns: S_OK for success or an error code.
//
// History: 18-Apr-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::CreateRoot(DWORD grfMode,
DWORD dwReserved,
DSKSTG DiskStgType)
{
HRESULT hr = S_OK;
LPOLESTR pOleStrTemp = NULL;
DH_ASSERT(0 == dwReserved);
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::CreateRoot"));
if(S_OK == hr)
{
// Convert _ptszName to OLECHAR
hr = TStringToOleString(_ptszName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = StgCreateDocfile(pOleStrTemp, grfMode, dwReserved, &_pstg);
DH_HRCHECK(hr, TEXT("StgCreateDocFile")) ;
DH_TRACE ((DH_LVL_DFLIB, TEXT("StgCreateRootStorage:%s"), _ptszName));
if (S_OK == hr)
{
if(!StorageIsFlat())
DH_LOG ((LOG_INFO, TEXT("Created docfile:%s"), _ptszName));
else
DH_LOG ((LOG_INFO, TEXT("Created flatfile:%s"), _ptszName));
}
}
// Clean up
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::CreateRootEx, public (overload)
//
// Synopsis: Wrapper for StgCreateDocFileEx that will create a new root
// compound file in the file system.
//
// Arguments: [grfMode] - Access mode for opening new compound file.
// [stgfmt] - Storage Format - enum.
// [grfAttrs] - Attributes (zero for now)
// [pStgOptions] - STGOPTIONS.
// [pTransaction]- Reserved by OLE for future use, must be zero.
// [riid] - should be IID_IStorage to get an IStorage
//
// Returns: S_OK for success or an error code.
//
// History: 28-Jan-97 SCousens Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::CreateRootEx(DWORD grfMode,
DWORD stgfmt,
DWORD grfAttrs,
STGOPTIONS *pStgOptions,
PVOID pTransaction,
REFIID riid)
{
HRESULT hr = S_OK;
LPOLESTR pOleStrTemp = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::CreateRoot"));
DH_ASSERT(0 == stgfmt); // want value of 0
DH_ASSERT(0 == grfAttrs); // want 0
DH_ASSERT(NULL == pStgOptions); // want value of NULL for wrapper
DH_ASSERT(NULL == pTransaction);
DH_ASSERT(IsEqualIID (IID_IStorage, riid)); // want IStorages. may change
if(S_OK == hr)
{
// Convert _ptszName to OLECHAR
hr = TStringToOleString(_ptszName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = StgCreateStorageEx (pOleStrTemp,
grfMode,
stgfmt,
grfAttrs,
pStgOptions,
pTransaction,
riid,
(void**)&_pstg);
DH_HRCHECK(hr, TEXT("StgCreateDocFileEx")) ;
DH_TRACE ((DH_LVL_DFLIB, TEXT("StgCreateRootStorageEx:%s"), _ptszName));
if (S_OK == hr)
{
DH_LOG ((LOG_INFO, TEXT("Created docfile:%s"), _ptszName));
}
}
// Clean up
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::Create, public
//
// Synopsis: Wrapper for IStorage::CreateStorage that will create and
// open a new IStorage object within this storage object.
//
// Arguments: [grfmode] - Access mode for creating & opening new storage
// object.
// [dwReserved1] - Reserved by OLE for future use, must be zero.
// [dwReserved2] - Reserved by OLE for future use, must be zero.
//
// Returns: S_OK for success or an error code.
//
// History: 18-Apr-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::Create(
DWORD grfMode,
DWORD dwReserved1,
DWORD dwReserved2)
{
HRESULT hr = S_OK;
LPSTORAGE pstg = NULL;
LPOLESTR pOleStrTemp = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::Create"));
DH_ASSERT(0 == dwReserved1);
DH_ASSERT(0 == dwReserved2);
DH_ASSERT(NULL != _pvcnParent);
DH_ASSERT(NULL != _pvcnParent->_pstg);
if(S_OK == hr)
{
// Convert _ptszName to OLECHAR
hr = TStringToOleString(_ptszName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = _pvcnParent->_pstg->CreateStorage(
pOleStrTemp,
grfMode,
dwReserved1,
dwReserved2,
&_pstg);
DH_HRCHECK(hr, TEXT("IStorage::CreateStorage")) ;
DH_TRACE ((DH_LVL_DFLIB, TEXT("CreateStorage:%s"), _ptszName));
}
// Clean up
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::Open, public
//
// Synopsis: Wrapper for IStorage::OpenStorage that will open the named
// IStorage object within this storage object.
//
// Arguments: [grfmode] - Access mode for opening the storage object.
// [dwReserved] - Reserved by OLE for future use, must be zero.
//
// Returns: S_OK for success or an error code.
//
// History: 24-Apr-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::Open(
LPSTORAGE pstgPriority,
DWORD grfmode,
SNB snbExclude,
DWORD dwReserved)
{
HRESULT hr = S_OK;
LPOLESTR pOleStrTemp = NULL;
LPSTORAGE pstg = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::Open"));
DH_ASSERT(0 == dwReserved);
// Check if it is root storage, if it is, then call OpenRoot and
// return here else proceed.
if(NULL == this->_pvcnParent)
{
DH_LOG ((LOG_INFO,
TEXT("Test called Open to open root storage. Calling OpenRoot.")));
hr = this->OpenRoot (pstgPriority,
grfmode,
snbExclude,
dwReserved);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::OpenRoot"));
return hr;
}
DH_ASSERT(NULL != _pvcnParent->_pstg);
if(S_OK == hr)
{
// Convert _ptszName to OLECHAR
hr = TStringToOleString(_ptszName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
// Open the storage.
if(S_OK == hr)
{
hr = _pvcnParent->_pstg->OpenStorage(
pOleStrTemp,
pstgPriority,
grfmode,
snbExclude,
dwReserved,
&pstg);
DH_HRCHECK(hr, TEXT("IStorage::OpenStorage"));
DH_TRACE ((DH_LVL_DFLIB, TEXT("OpenStorage:%s"), _ptszName));
}
// Save it if function succeeds if _pstg is NULL.
if((S_OK == hr) && (NULL == _pstg))
{
_pstg = pstg;
}
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Open"));
// Clean up
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::OpenRoot, public
//
// Synopsis: Wrapper for IStorage::OpenStorage that will open the named
// IStorage object within this storage object.
//
// Arguments: [grfmode] - Access mode for creating & opening new storage
// object.
// [dwReserved1] - Reserved by OLE for future use, must be zero.
// [dwReserved2] - Reserved by OLE for future use, must be zero.
//
// Returns: S_OK for success or an error code.
//
// History: 24-Apr-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::OpenRoot(
LPSTORAGE pstgPriority,
DWORD grfmode,
SNB snbExclude,
DWORD dwReserved,
DSKSTG DiskStgType)
{
HRESULT hr = S_OK;
IStorage *pstg = NULL;
LPOLESTR pOleStrTemp = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::OpenRoot"));
DH_ASSERT(0 == dwReserved);
// Make sure this is the Root.
DH_ASSERT(NULL == this->_pvcnParent);
if(S_OK == hr)
{
// Convert _ptszName to OLECHAR
hr = TStringToOleString(_ptszName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
// Open the root storage
if(S_OK == hr)
{
#if (WINVER<0x500) //NT5 is lockviolation fixed
DG_INTEGER dgi(0);
ULONG ulRandNum = 0;
USHORT usErr = 0;
int i = 0;
// Try opening the docfile
// StgOpenStorage returns STG_E_LOCKVIOLATION is concurrent API calls
// are made, so this is the hack for workaround the problem.
// BUGBUG : Remove this loop once the feature is implemented in OLE.
// BUGBUG : ntbug#114779 Affects DCOM95 only. ntbug#41249 fixed
for(i=0; i<NRETRIES; i++) // NRETRIES has been defined as 20
{
#endif
hr = StgOpenStorage(
pOleStrTemp,
pstgPriority,
grfmode,
snbExclude,
dwReserved,
&pstg);
DH_HRCHECK(hr, TEXT("StgOpenStorage"));
DH_TRACE ((DH_LVL_DFLIB, TEXT("StgOpenRootStorage:%s"), _ptszName));
#if (WINVER<0x500) //NT5 is lockviolation fixed
if ( (S_OK == hr) || (STG_E_LOCKVIOLATION != hr) )
{
break;
}
// Sleep for a random amount of time
// Note: No particular reason why the below random numbers have been used
usErr = dgi.Generate(&ulRandNum, 1, 100 );
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
break;
}
else
{
Sleep(ulRandNum*50);
}
}
#endif
}
if((S_OK == hr) && (NULL == _pstg))
{
_pstg = pstg;
}
DH_HRCHECK(hr, TEXT("VirtualCtrNode::OpenRoot"));
// Clean up
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::OpenRootEx, public (overload)
//
// Synopsis: Wrapper for StgOpenStorageEx that will open a previously
// created root compound file in the file system.
//
// Arguments: [grfMode] - Access mode for opening the compound file.
// [stgfmt] - Storage Format - enum.
// [grfAttrs] - Attributes
// [pStgOptions] - STGOPTIONS, must be NULL as on build 1795.
// [pTransaction]- Reserved by OLE for future use, must be zero.
// [riid] - should be IID_IStorage to get an IStorage
//
// Returns: S_OK for success or an error code.
//
// History: 28-Jan-97 SCousens Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::OpenRootEx(
DWORD grfMode,
DWORD stgfmt,
DWORD grfAttrs,
STGOPTIONS *pStgOptions,
PVOID pTransaction,
REFIID riid)
{
HRESULT hr = S_OK;
IStorage *pstg = NULL;
LPOLESTR pOleStrTemp = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::OpenRoot"));
// Make sure this is the Root.
DH_ASSERT(NULL == this->_pvcnParent);
DH_ASSERT(0 == stgfmt); // want value of 0
DH_ASSERT(0 == grfAttrs); // want 0
DH_ASSERT(NULL == pStgOptions); // want value of NULL
DH_ASSERT(NULL == pTransaction);
DH_ASSERT(IsEqualIID (IID_IStorage, riid)); // want IStorages. may change
if (S_OK == hr)
{
// Convert _ptszName to OLECHAR
hr = TStringToOleString(_ptszName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
// Open the root storage
if (S_OK == hr)
{
DG_INTEGER dgi(0);
ULONG ulRandNum = 0;
USHORT usErr = 0;
int i = 0;
// Try opening the docfile
// StgOpenStorage returns STG_E_LOCKVIOLATION is concurrent API calls
// are made, so this is the hack for workaround the problem.
// BUGBUG : Remove this loop once the feature is implemented in OLE.
for(i=0; i<NRETRIES; i++) // NRETRIES has been defined as 20
{
hr = StgOpenStorageEx(pOleStrTemp,
grfMode,
stgfmt,
grfAttrs,
pStgOptions,
pTransaction,
riid,
(void**)&pstg);
DH_HRCHECK(hr, TEXT("StgOpenStorageEx"));
DH_TRACE ((DH_LVL_DFLIB, TEXT("StgOpenRootStorageEx:%s"), _ptszName));
if ( (S_OK == hr) || (STG_E_LOCKVIOLATION != hr) )
{
break;
}
// Sleep for a random amount of time
// Note: No particular reason why the below random numbers have been used
usErr = dgi.Generate(&ulRandNum, 1, 100 );
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
break;
}
else
{
Sleep(ulRandNum*50);
DH_TRACE ((DH_LVL_TRACE4,
TEXT("VirtualCtrNode::OpenRoot: Sleeping due to LOCKVIOLATION")));
}
}
}
if((S_OK == hr) && (NULL == _pstg))
{
_pstg = pstg;
}
DH_HRCHECK(hr, TEXT("VirtualCtrNode::OpenRoot"));
// Clean up
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::Close, public
//
// Synopsis: Closes an open storage.
//
// Arguments: None
//
// Returns: HRESULT
//
// History: NarindK 25-Apr-96 Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::Close()
{
HRESULT hr = S_OK;
ULONG ulRef = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::Close"));
// When we create the storage, it is open. We do not call release
// on _pstg normally till the VirtualCtrNode object is destructed, or
// if explicitly this function is used to close the storage
if ( NULL != _pstg )
{
ulRef = _pstg->Release();
}
else
{
DH_ASSERT(!TEXT("_pStg is already NULL!"));
}
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Close"));
if(0 == ulRef)
{
_pstg = NULL;
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::Commit, public
//
// Synopsis: Wrapper for IStorage::Commit that will commit any changes
// made to an IStorage object since it was opened or last
// committed to persistent storage.
//
// Arguments: [grfCommitFlags] - Controls how object is committed to IStorage.
//
// Returns: S_OK Commit operation was successful.
// STG_E_NOTCURRENT Another opening of storage object has commi
// tted changes, possibility of overwriting.
// STG_E_MEDIUMFULL No space left on device to commit.
// STG_E_TOOMANYOPENFILES too many open files.
// STG_E_REVERTED Object invalidated by a revert operation
// above it in transaction tree.
// STG_E_INVALIDFLAG Invalid flag.
// STG_E_INVALIDPARAMETER Inalid parameter
//
// History: 29-Apr-96 NarindK Created
// 12-Mar-97 MikeW Removed HRCHECK after Commit
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::Commit(DWORD grfCommitFlags)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::Commit"));
DH_ASSERT(NULL != _pstg);
if ( S_OK == hr )
{
hr = _pstg->Commit(grfCommitFlags);
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::Rename, public
//
// Synopsis: Wrapper for IStorage::RenameElement that renames an element
// contained in an Storage object subject to transaction state
// of IStorage object.
//
// Arguments: [pptcsNewName] - Points to pointer to new name for the element.
//
// Returns: S_OK Object was successfully renamed.
// STG_E_ACCESSDENIED Named element ptcsNewName alreadys exists.
// STG_E_FILENOTFOUND Element couldn't be found.
// STG_E_REVERTED Object invalidated by a revert operation
// above it in transaction tree.
// STG_E_INSUFFICIENTMEMORY Not enough memory to rename element.
// STG_E_INVALIDPOINTER Invalid pointer.
// STG_E_INVALIDNAME Invalid name.
// STG_E_INVALIDPARAMETER Invalid parameter
// STG_E_TOOMANYOPENFILES too many open files.
//
// History: 29-Apr-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::Rename(LPCTSTR ptcsNewName)
{
HRESULT hr = S_OK;
LPOLESTR pOleStrOld = NULL;
LPOLESTR pOleStrNew = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::Rename"));
DH_VDATESTRINGPTR(ptcsNewName);
DH_ASSERT(NULL != _pvcnParent);
DH_ASSERT(NULL != _pvcnParent->_pstg);
if(S_OK == hr)
{
// Convert _ptszName to OLECHAR
hr = TStringToOleString(_ptszName, &pOleStrOld);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
// Convert ptcsNewName to OLECHAR
hr = TStringToOleString((LPTSTR)ptcsNewName, &pOleStrNew);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = _pvcnParent->_pstg->RenameElement(pOleStrOld, pOleStrNew);
DH_HRCHECK(hr, TEXT("IStorage::Rename")) ;
}
if(S_OK == hr)
{
// Change the name of VirtualCtrNode i.e. its _ptszName variable also
// First delete the old name
if(NULL != _ptszName)
{
delete _ptszName;
_ptszName = NULL;
}
// Now copy the new name by allocating enough memory
_ptszName = new TCHAR[_tcslen(ptcsNewName)+1];
if (_ptszName == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
_tcscpy(_ptszName, ptcsNewName);
}
}
// Clean up
if(NULL != pOleStrOld)
{
delete pOleStrOld;
pOleStrOld = NULL;
}
if(NULL != pOleStrNew)
{
delete pOleStrNew;
pOleStrNew = NULL;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::Destroy, public
//
// Synopsis: Wrapper for IStorage::DestroyElement that removes an element
// storage from this storage, subject to transaction mode in
// which it was opened. The wrapper for IStorage::DestroyElement
// that destorys a stream element from this storage is in
// VirtualStmNode::Destroy.
//
// Arguments: None
//
// Returns: S_OK Object was successfully renamed.
// STG_E_ACCESSDENIED insufficient permissions.
// STG_E_FILENOTFOUND Element couldn't be found.
// STG_E_REVERTED Object invalidated by a revert operation
// above it in transaction tree.
// STG_E_INSUFFICIENTMEMORY Not enough memory to rename element.
// STG_E_INVALIDPOINTER Invalid pointer.
// STG_E_INVALIDNAME Invalid name.
// STG_E_INVALIDPARAMETER Invalid parameter
// STG_E_TOOMANYOPENFILES too many open files.
//
// History: 29-Apr-96 NarindK Created
//
// Notes: The existing open instance of this element from this parent
// instance becomes invalid after this function is called.
//
// Use DestroyStorage in the util.cxx which is a wrapper to call
// this function and also readjusts the VirtualDF tree.
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::Destroy()
{
HRESULT hr = S_OK;
LPSTORAGE pstg = NULL;
LPOLESTR pOleStrTemp = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::Destroy"));
DH_ASSERT(NULL != _pvcnParent);
DH_ASSERT(NULL != _pvcnParent->_pstg);
if(S_OK == hr)
{
// Convert _ptszName to OLECHAR
hr = TStringToOleString(_ptszName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = _pvcnParent->_pstg->DestroyElement(pOleStrTemp);
DH_HRCHECK(hr, TEXT("IStorage::DestroyElement")) ;
}
// Clean up
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::Stat, public
//
// Synopsis: Returns relevant statistics concerning this open storage.
//
// Arguments: [pStatStg] - pointer to STATSTG structure.
// [grfStatFlag] - Controls levels of returned statistics.
//
// Returns: S_OK Statistics were successfully returned.
// STG_E_ACCESSDENIED insufficient permissions.
// STG_E_REVERTED Object invalidated by a revert operation
// above it in transaction tree.
// STG_E_INSUFFICIENTMEMORY Not enough memory.
// STG_E_INVALIDPOINTER Invalid pointer.
//
// History: NarindK 8-May-96 Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::Stat(
STATSTG *pStatStg,
DWORD grfStatFlag)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::Stat"));
DH_ASSERT(_pstg != NULL);
DH_ASSERT(NULL != pStatStg);
DH_ASSERT((
(grfStatFlag == STATFLAG_DEFAULT) ||
(grfStatFlag == STATFLAG_NONAME)));
if(S_OK == hr)
{
hr = _pstg->Stat(pStatStg, grfStatFlag);
DH_HRCHECK(hr, TEXT("IStorage::Stat"));
}
// BUGBUG: May remove to need DH_ assert macros to do invalid parameter
// checking.
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::EnumElements, public
//
// Synopsis: Enumerates the elements immediately contained within this
// storage object.
//
// Arguments: [dwReserved1] - Reserved by OLE
// [dwReserved2] - Reserved by OLE
// [dwReserved3] - Reserved by OLE
// [ppenumStatStg] - Points to where to return enumerator, NULL
// if an error.
//
// Returns: S_OK Enumeration successful.
// STG_E_INSUFFICIENTMEMORY Not enough memory.
// STG_E_INVALIDPOINTER Invalid pointer.
// STG_E_INVALIDPARAMETER Invalid parameter.
// E_OUTOFMEMORY Not enough memory.
// STG_E_REVERTED Object invalidated by a revert operation
// above it in transaction tree.
//
// History: NarindK 10-May-96 Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::EnumElements(
DWORD dwReserved1,
PVOID pReserved2,
DWORD dwReserved3,
LPENUMSTATSTG *ppenumStatStg)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::EnumElements"));
DH_ASSERT(_pstg != NULL);
if(S_OK == hr)
{
hr = _pstg->EnumElements(
dwReserved1,
pReserved2,
dwReserved3,
ppenumStatStg);
DH_HRCHECK(hr, TEXT("IStorage::EnumElements"));
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::SetElementTimes, public
//
// Synopsis: Sets the modification, access, and creation times of the
// indicated element of this storage object.
//
// Arguments: [lpszName] - Points to name of element to change
// [pctime] - Points to new creation time
// [patime] - Points to new access time
// [pmtime] - Points to new modification time
//
// Returns: S_OK Time values successfully set.
// STG_E_ACCESSDENIED insufficient permissions.
// STG_E_FILENOTFOUND Element not found.
// STG_E_FILEALREADYEXITS Specified file already exists.
// STG_E_TOOMANYOPENFILES too many open files
// STG_E_INSUFFICIENTMEMORY Not enough memory.
// STG_E_INVALIDNAME Invalid name.
// STG_E_INVALIDPOINTER Invalid pointer.
// STG_E_INVALIDPARAMETER Invalid parameter.
// STG_E_REVERTED Object invalidated by a revert operation
// above it in transaction tree.
//
// History: NarindK 10-May-96 Created
//
// Notes: Ole implemntation doesn't support setting time on stream elem
// so no function corresponding to VirtualStmNode for this.
//
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::SetElementTimes(
FILETIME const *pctime,
FILETIME const *patime,
FILETIME const *pmtime)
{
HRESULT hr = S_OK;
LPOLESTR pOleStrTemp = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::SetElementTimes"));
DH_ASSERT(NULL != _pvcnParent);
DH_ASSERT(NULL != _pvcnParent->_pstg);
if(S_OK == hr)
{
// Convert _ptszName to OLECHAR
hr = TStringToOleString(_ptszName, &pOleStrTemp);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = _pvcnParent->_pstg->SetElementTimes(
pOleStrTemp,
pctime,
patime,
pmtime);
DH_HRCHECK(hr, TEXT("IStorage::SetElementTimes"));
}
// Clean up
if(NULL != pOleStrTemp)
{
delete pOleStrTemp;
pOleStrTemp = NULL;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::SetClass, public
//
// Synopsis: Persistently stores the object's CLSID.
//
// Arguments: [rclsid] - Specifies CLSID to be associated with this storage.
//
// Returns: S_OK CLSID successfully stored.
// STG_E_ACCESSDENIED insufficient permissions.
// STG_E_REVERTED Object invalidated by a revert operation
// above it in transaction tree.
// STG_E_MEDIUMFULL Not enough space on device.
//
// History: NarindK 9-May-96 Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::SetClass(REFCLSID rclsid)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::SetClass"));
DH_ASSERT(_pstg != NULL);
if(S_OK == hr)
{
hr = _pstg->SetClass(rclsid);
DH_HRCHECK(hr, TEXT("IStorage::SetClass"));
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::SetStateBits, public
//
// Synopsis: Stores upto 32 bits of state information in this IStorage.
//
// Arguments: [grfStateBits] - New values of bits to be set
// [grfMask] - Binary mask to indicate significant bits.
//
// Returns: S_OK State successfully set.
// STG_E_ACCESSDENIED insufficient permissions.
// STG_E_INVALIDPARAMETER Invalid parameter
// STG_E_INVALIDFLAG Invalid flag in grfStateBits or grfMask
//
// History: NarindK 9-May-96 Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::SetStateBits(
DWORD grfStateBits,
DWORD grfMask)
{
HRESULT hr = S_OK;
LPSTORAGE pstg = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::SetStateBits"));
DH_ASSERT(_pstg != NULL);
if(S_OK == hr)
{
hr = _pstg->SetStateBits(grfStateBits, grfMask);
DH_HRCHECK(hr, TEXT("IStorage::SetStateBits"));
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::MoveElementTo, public
//
// Synopsis: Moves an IStorage/IStream element to indicated new destination
// container.
//
// Arguments: [ptszName] - Name of child IStorage/IStream present in this
// this _pstg to be moved
// [pvcnDest] - Pointer to destination virtual container
// [lpszNewname] - Points to new name to element in its new
// container
// [grfFlags] - Specifies if to move as move or copy
//
// Returns: S_OK Storage moved successfully.
// STG_E_ACCESSDENIED insufficient permissions.
// STG_E_FILENOTFOUND Element not found.
// STG_E_FILEALREADYEXITS Specified file already exists.
// STG_E_TOOMANYOPENFILES too many open files
// STG_E_INSUFFICIENTMEMORY Not enough memory.
// STG_E_INVALIDNAME Invalid name.
// STG_E_INVALIDPOINTER Invalid pointer.
// STG_E_INVALIDPARAMETER Invalid parameter
// STG_E_INVALIDFLAG Invalid flag in grfFlags
// STG_E_REVERTED Object invalidated by a revert operation
// above it in transaction tree.
//
// History: NarindK 13-May-96 Created
//
// Notes: This moves a child storage/stream with name ptszName in present
// storage _pstg to a destination storage. Make sure that the
// child storage/stream to be moved is closed and the destination
// storage is open.
// The VirtualDF tree needs to be readjusted after this call.
// Different methods of VirtualDF may need to be called as the
// case may be - AdjustTreeOnStgMoveElement, AdjustTreeOnStmMove
// Element, AdjustTreeOnStgCopyElement, AdjustTreeOnStmCopyElement
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::MoveElementTo(
LPCTSTR ptszName,
VirtualCtrNode *pvcnDest,
LPCTSTR ptszNewName,
DWORD grfFlags)
{
HRESULT hr = S_OK;
LPOLESTR pOleStrOld = NULL;
LPOLESTR pOleStrNew = NULL;
DH_VDATESTRINGPTR(ptszName);
DH_VDATESTRINGPTR(ptszNewName);
DH_VDATEPTRIN(pvcnDest, VirtualCtrNode);
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::MoveElementTo"));
DH_ASSERT(_pstg != NULL);
DH_ASSERT(NULL != pvcnDest);
DH_ASSERT(pvcnDest->_pstg != NULL);
DH_ASSERT(NULL != ptszName);
DH_ASSERT(NULL != ptszNewName);
DH_ASSERT((grfFlags == STGMOVE_COPY) ||
(grfFlags == STGMOVE_MOVE));
if(S_OK == hr)
{
// Convert ptszName to OLECHAR
hr = TStringToOleString((LPTSTR)ptszName, &pOleStrOld);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
// Convert ptszNewName to OLECHAR
hr = TStringToOleString((LPTSTR)ptszNewName, &pOleStrNew);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = _pstg->MoveElementTo(
pOleStrOld,
pvcnDest->_pstg,
pOleStrNew,
grfFlags);
DH_HRCHECK(hr, TEXT("IStorage::MoveElementTo"));
}
// Clean up
if(NULL != pOleStrOld)
{
delete pOleStrOld;
pOleStrOld = NULL;
}
if(NULL != pOleStrNew)
{
delete pOleStrNew;
pOleStrNew = NULL;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::Revert, public
//
// Synopsis: Discards all changes made in or made visible to thsi storage
// object since it was opened or last committed.
//
// Arguments: none
//
// Returns: HRESULT
// S_OK Revert operation successful.
// STG_E_INSUFFICIENTMEMORY Out of memory.
// STG_E_TOOMANYOPENFILES Too many open files.
// STG_E_REVERTED Object has been invalidated by a revert
// operation above it in transaction tree.
//
// History: NarindK 20-May-96 Created
//
// Notes:
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::Revert()
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::Revert"));
DH_ASSERT(_pstg != NULL);
if(S_OK == hr)
{
hr = _pstg->Revert();
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Revert"));
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::CopyTo, public
//
// Synopsis: Copies an IStorage element to indicated new destination
// container.
//
// Arguments: [ciidExclude] - Speciefies number of elements in array pointed
// to by rgiidExclude.
// [rgiidExclude]- Specifies an array of interface identifiers the
// caller takes responsibility of moving from
// source to destination.
// [snbExclude] - Points to a bloack of named elements not to
// to be copied into destination container.
// [pvcnDest]- Points to the open storage object where this
// open storage object is copied.
//
// Returns: S_OK Storage copied successfully.
// STG_E_ACCESSDENIED insufficient permissions.
// STG_E_TOOMANYOPENFILES too many open files
// STG_E_INSUFFICIENTMEMORY Not enough memory.
// STG_E_INVALIDPOINTER Invalid pointer.
// STG_E_INVALIDPARAMETER Invalid parameter
// STG_E_MEDIUMFULL Storage medium is full
// STG_E_DESTLACKSINTERFACE Destination lacks an interface of the
// source object to be copied.
//
// History: NarindK 20-May-96 Created
//
// Notes: This copies contents of storage _pstg to a destination storage.
// The storage to be copied from and the destination storage to
// be copied into is open.
// VirtualDF tree needs to be readjusted after this call. Virtual
// DF's AdjustTreeOnCopyTo may be used.
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::CopyTo(
DWORD ciidExclude,
IID const* rgiidExclude,
SNB snbExclude,
VirtualCtrNode *pvcnDest)
{
HRESULT hr = S_OK;
DH_VDATEPTRIN(pvcnDest, VirtualCtrNode);
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::CopyTo"));
DH_ASSERT(NULL != _pstg);
DH_ASSERT(NULL != pvcnDest);
DH_ASSERT(NULL != pvcnDest->_pstg);
if(S_OK == hr)
{
hr = _pstg->CopyTo(
ciidExclude,
rgiidExclude,
snbExclude,
pvcnDest->_pstg);
DH_HRCHECK(hr, TEXT("IStorage::CopyTo"));
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::AddRefCount, public
//
// Synopsis: Increments the reference count on IStorage object.
//
// Arguments: none
//
// Returns: HRESULT
//
// History: NarindK 21-May-96 Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::AddRefCount()
{
HRESULT hr = S_OK;
ULONG ulTmp = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::AddRefCount"));
DH_ASSERT(_pstg != NULL);
if(S_OK == hr)
{
ulTmp = _pstg->AddRef();
}
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AddRefCount"));
return(hr);
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::QueryInterface, public
//
// Synopsis: Returns pointers to supported objects.
//
// Arguments: none
//
// Returns: HRESULT
//
// History: NarindK 21-May-96 Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::QueryInterface(
REFIID riid,
LPVOID *ppvObj)
{
HRESULT hr = S_OK;
LPSTORAGE pstg = NULL;
DH_VDATEPTROUT(ppvObj, IUnknown *) ;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("VirtualCtrNode::QueryInterface"));
DH_ASSERT(ppvObj != NULL);
DH_ASSERT(_pstg != NULL);
if(S_OK == hr)
{
// Initilze the out parameter
*ppvObj = NULL;
hr = _pstg->QueryInterface(riid, ppvObj);
}
DH_HRCHECK(hr, TEXT("VirtualCtrNode::QueryInterface"));
if(S_OK == hr)
{
DH_ASSERT(NULL != *ppvObj);
}
else
{
DH_ASSERT(NULL == *ppvObj);
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::CreateRootOnCustomILockBytes,public
//
// Synopsis: Wrapper for StgCreateDocFileOnILockBytes that will create a new
// root compound file in the file system based on custom ILockBytes
//
// Arguments: [grfmode] - Access mode for creating new compound file.
// [pILockBytes] - Pointer to ILockBytes
//
// Returns: S_OK for success or an error code.
//
// History: 1-Aug-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::CreateRootOnCustomILockBytes(
DWORD grfMode,
ILockBytes *pILockBytes)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(
&hr,
DH_LVL_DFLIB,
_TEXT("VirtualCtrNode::CreateRootOnCustomILockBytes"));
if(S_OK == hr)
{
hr = StgCreateDocfileOnILockBytes(
pILockBytes,
grfMode,
0,
&_pstg);
DH_HRCHECK(hr, TEXT("StgCreateDocFileOnLockBytes")) ;
}
return hr;
}
//+--------------------------------------------------------------------------
// Member: VirtualCtrNode::OpenRootOnCustomILockBytes, public
//
// Synopsis: Wrapper for StgOpenStorageOnILockBytes that will open the named
// IStorage root object on custom ILOckBytes provided.
//
// Arguments: [pstgPrioirty] - Points to previous opening of root stg
// [grfmode] - Access mode for creating & opening new storage
// object.
// [snbExclude] - Points to a block of named elements not to
// to be excluded in open call.
// [dwReserved] - Reserved by OLE for future use, must be zero.
// [pILockBytes] - Pointer to ILockBytes
//
// Returns: S_OK for success or an error code.
//
// History: 3-Aug-96 NarindK Created
//---------------------------------------------------------------------------
HRESULT VirtualCtrNode::OpenRootOnCustomILockBytes(
LPSTORAGE pstgPriority,
DWORD grfmode,
SNB snbExclude,
DWORD dwReserved,
ILockBytes *pILockBytes)
{
HRESULT hr = S_OK;
IStorage *pstg = NULL;
DH_FUNCENTRY(
&hr,
DH_LVL_DFLIB,
_TEXT("VirtualCtrNode::OpenRootOnCustomILockBytes"));
// Make sure this is the Root.
DH_ASSERT(NULL == this->_pvcnParent);
// Open the root storage
if(S_OK == hr)
{
hr = StgOpenStorageOnILockBytes(
pILockBytes,
pstgPriority,
grfmode,
snbExclude,
dwReserved,
&pstg);
DH_HRCHECK(hr, TEXT("StgOpenStorage"));
}
if((S_OK == hr) && (NULL == _pstg))
{
_pstg = pstg;
}
DH_HRCHECK(hr, TEXT("VirtualCtrNode::OpenRootOnCustomILockBytes"));
return(hr);
}