|
|
//+-------------------------------------------------------------------------
// Microsoft OLE
// Copyright (C) Microsoft Corporation, 1992 - 1996.
// All rights reserved.
//
// File: virtdf.cxx
//
// Contents: Implementation for in-memory Virtual Docfile class.
//
// Classes: VirtualDF
//
// Functions: VirtualDF (public)
// ~VirtualDF (public)
// GenerateVirtualDF (public)
// DeleteVirtualDocFileTree (public)
// GenerateVirtualDFRoot (protected)
// GrowVirtualDFTree (protected)
// DeleteVirtualDocFileSubTree (protected)
// DeleteVirtualCtrNodeStreamTree (protected)
// AppendVirtualStmNodesToVirtualCtrNode (protected)
// AppendVirtualCtrNode (protected)
// AppendVirtualStmNode (protected)
// AdjustTreeOnStgMoveElement (public)
// AdjustTreeOnStmMoveElement (public)
// AdjustTreeOnStgCopyElement(public)
// AdjustTreeOnStmCopyElement(public)
// AdjustTreeOnCopyTo (public)
// CopyVirtualDocFileTree (public)
// CopyVirtualDFRooti (protected)
// CopyGrowVirtualDFTree (protected)
// CopyAppendVirtualStmNodesToVirtualCtrNode (protected)
// CopyAppendVirtualCtrNode (protected)
// CopyAppendVirtualStmNode (protected)
// Associate (public)
// DeleteVirtualCtrNodeStreamNode (public)
// CommitCloseThenOpenDocfile (public)
//
// History: DeanE 21-Mar-96 Created
// Narindk 22-Apr-96 Added more functions.
// SCousens 2-Feb-97 Added for Cnvrs/NSS
// SCousens 8-Apr-98 Handle stg collisions on createdf
// georgis 2-Apr-98 Added support for large streams
//--------------------------------------------------------------------------
#include <dfheader.hxx>
#pragma hdrstop
// Debug object declaration
DH_DECLARE;
//+--------------------------------------------------------------------------
// Member: VirtualDF::VirtualDF, public [multiple]
//
// Synopsis: Constructor. This method cannot fail.
//
// Arguments: None.
//
// Returns: Nothing.
//
// History: DeanE 21-Mar-96 Created
// SCousens 2-Feb-97 Added for Cnvrs/NSS
//---------------------------------------------------------------------------
VirtualDF::VirtualDF() : _ptszName(NULL), _pvcnRoot(NULL), _pdgi(NULL), _pgdu(NULL), _ulSeed(0), _dwRootMode(0), _dwStgMode(0), _dwStmMode(0), _dwStgType(STGTYPE_DOCFILE), _pDBCSStrGen(NULL) { DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::VirtualDF")); }
//+--------------------------------------------------------------------------
// Member: VirtualDF::VirtualDF, public [multiple]
//
// Synopsis: Constructor. This method cannot fail.
//
// Arguments: _fUseStgEx - whether to use the Ex apis
//
// Returns: Nothing.
//
// History: SCousens 4-Apr-97 Added for Cnvrs/NSS
//---------------------------------------------------------------------------
VirtualDF::VirtualDF(STGTYPE dwStgFmt) : _ptszName(NULL), _pvcnRoot(NULL), _pdgi(NULL), _pgdu(NULL), _ulSeed(0), _dwRootMode(0), _dwStgMode(0), _dwStmMode(0), _dwStgType(dwStgFmt), _pDBCSStrGen(NULL) { DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::VirtualDF")); }
//+--------------------------------------------------------------------------
// Member: VirtualDF::~VirtualDF, public
//
// Synopsis: Destructor. Frees resources associated with this docfile.
//
// Arguments: None.
//
// Returns: Nothing.
//
// History: DeanE 21-Mar-96 Created
//---------------------------------------------------------------------------
VirtualDF::~VirtualDF() { DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("::~VirtualDF"));
if(NULL != _pdgi) { delete _pdgi; _pdgi = NULL; }
if(NULL != _pgdu) { delete _pgdu; _pgdu = NULL; }
if(NULL != _ptszName) { delete _ptszName; _ptszName = NULL; }
if(NULL != _pDBCSStrGen) { delete _pDBCSStrGen; _pDBCSStrGen = NULL; } }
//----------------------------------------------------------------------------
// Member: VirtualDF::GenerateVirtualDF, public
//
// Synopsis: Creates a VirtualDocFile tree consisting of VirtualCtrNode
// node(s) and VirtualStmNodes(s) based on the ChanceDocFile
// created prior to this.
//
// Arguments: [pChanceDF] - Pointer to ChanceDocFile tree
// [ppvcnRoot] - Returned root of VirtualDocFile tree
//
// Returns: HRESULT
//
// History: Narindk 22-Apr-96 Created
// SCousens 2-Feb-97 Added for Cnvrs/NSS
//
// Notes: This function calls GenerateVirtualDFRoot to generate Virtual
// DF tree's root and GrowVirtualDFTree to generate rest of the
// tree. If the function succeeds, it returns pointer to the root
// of VirtualDocFile generated in ppvcnRoot parameter.
// - Get seed from ChanceDocFile tree and construct DG_INTEGER &
// DG_STRING objects.
// - Get the modes for creating various storages/streams from thw
// ChanceDocFile tree.
// - Get name of rootdocfile, if given, from chancedocfile tree.
// - Call GenerateVirtualDFRoot.
// - Call GrowVirtualDFTree
// - If successful, assign root of new VirtualDF in *ppvcnRoot.
//---------------------------------------------------------------------------
HRESULT VirtualDF::GenerateVirtualDF( ChanceDF *pChanceDF, VirtualCtrNode **ppvcnRoot) { HRESULT hr = S_OK; LPTSTR ptszName = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::GenerateVirtualDF"));
DH_VDATEPTRIN(pChanceDF, ChanceDF) ; DH_VDATEPTROUT(ppvcnRoot, PVCTRNODE) ;
DH_ASSERT(NULL != pChanceDF); DH_ASSERT(NULL != ppvcnRoot);
if(S_OK == hr) { *ppvcnRoot = NULL;
// Create a DataGen obj of type DG_INTEGER that will allow us to fill
// count parameters of VirtualDocFile tree components, excepting those
// which we got from already created ChanceDocFile tree. Use the
// same seed value as was used in creation of ChanceDocFile tree.
// Get the value of seed used to create ChanceDocFile tree and store it.
_ulSeed = pChanceDF->GetSeed(); _pdgi = new(NullOnFail) DG_INTEGER(_ulSeed);
if (NULL == _pdgi) { hr = E_OUTOFMEMORY; } }
if(S_OK == hr) { // Create a new DataGen object to create random strings.
_pgdu = new(NullOnFail) DG_STRING(_ulSeed);
if (NULL == _pgdu) { hr = E_OUTOFMEMORY; } }
if(S_OK == hr) { // Get the value of different creation modes.
_dwRootMode = pChanceDF->GetRootMode(); _dwStgMode = pChanceDF->GetStgMode(); _dwStmMode = pChanceDF->GetStmMode();
// Get user provided name for DocFile, if any
ptszName = pChanceDF->GetDocFileName();
if(NULL != ptszName) { _ptszName = new TCHAR[_tcslen(ptszName)+1];
if (_ptszName == NULL) { hr = E_OUTOFMEMORY; } else { _tcscpy(_ptszName, ptszName); } } }
if (S_OK == hr) { // Generates the root VirtualCtrNode for the VirtualDocFile tree.
hr = GenerateVirtualDFRoot(pChanceDF->_pcnRoot);
DH_HRCHECK(hr, TEXT("GenerateVirtualDFRoot")) ; }
if (S_OK == hr) { // Generate remaining VirtualDF tree based on the ChanceDF tree.
hr = GrowVirtualDFTree(pChanceDF->_pcnRoot, _pvcnRoot);
DH_HRCHECK(hr, TEXT("GrowVirtualDFTree")) ; }
// Fill the out parameter
if(S_OK == hr) { *ppvcnRoot = _pvcnRoot; }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::GenerateVirtualDFRoot, protected
//
// Synopsis: Creates the root VirtualCtrNode for the VirtualDocFile tree.
//
// Arguments: [pcnRoot] - Pointer to root of ChanceDocFile tree
//
// Returns: HRESULT
//
// History: Narindk 22-Apr-96 Created
// SCousens 2-Feb-97 Added for Cnvrs/NSS
//
// Notes: - Generate a random name for RootDocFile if it is not provided
// in the test.
// - Creates VirtualCtrNode object and initializes it with info
// based on corresponding ChanceDocFile root.
// - Create real IStorage corresponding to this VirtualCtrNode.
// - Creates IStreams corresponding to this VirtualCtrNode, if
// required.
// - Calculates in memory CRC for this IStorage and assigns it
// to _dwCRC variable.
//---------------------------------------------------------------------------
HRESULT VirtualDF::GenerateVirtualDFRoot(ChanceNode *pcnRoot) { HRESULT hr = S_OK;
DH_VDATEPTRIN(pcnRoot, ChanceNode) ;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::GenerateVirtualDFRoot"));
DH_ASSERT(NULL != pcnRoot); if(S_OK == hr) { if(NULL == _ptszName) { // Create a random file name for this root.
// Hack for FE DBCS systems
_pDBCSStrGen = new(NullOnFail) CDBCSStringGen;
if (NULL == _pDBCSStrGen) { hr = E_OUTOFMEMORY; }
if(S_OK == hr) { hr = _pDBCSStrGen->Init(_ulSeed); }
if((S_OK == hr) && (_pDBCSStrGen->SystemIsDBCS())) { hr = _pDBCSStrGen->GenerateRandomFileName(&_ptszName);
if(S_OK != hr) { DH_TRACE((DH_LVL_TRACE1, TEXT("Unable to generate DBCS name. Fall back to GenerateRandomName")));
hr = GenerateRandomName(_pgdu, MINLENGTH, MAXLENGTH, &_ptszName); } } else { hr = GenerateRandomName(_pgdu, MINLENGTH, MAXLENGTH, &_ptszName); }
DH_HRCHECK(hr, TEXT("GenerateRandomName")) ; } } // Generate VirtualCtrNode for the root node.
if(S_OK == hr) { _pvcnRoot = new VirtualCtrNode();
if (NULL == _pvcnRoot) { hr = E_OUTOFMEMORY; } }
if(S_OK == hr) { hr = _pvcnRoot->Init( _ptszName, pcnRoot->_cStorages, pcnRoot->_cStreams);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ; }
// Call VirtualCtrNode::CreateRoot to create a corresponding Root Storage
// on disk.
if(S_OK == hr) { if (STGTYPE_DOCFILE == _dwStgType) { hr = _pvcnRoot->CreateRoot( _dwRootMode | STGM_CREATE, 0); DH_HRCHECK(hr, TEXT("VirtualCtrNode::CreateRoot")) ; } else { hr = _pvcnRoot->CreateRootEx( _dwRootMode | STGM_CREATE, STGFMT_GENERIC, 0, NULL, NULL); DH_HRCHECK(hr, TEXT("VirtualCtrNode::CreateRootEx")) ; }
// Generate VirtualStmNode(s) depending upon if root has streams in it.
DH_ASSERT((pcnRoot->_cStreams) == (_pvcnRoot->_cStreams)); }
if ((S_OK == hr) && (0 != _pvcnRoot->_cStreams)) { hr = AppendVirtualStmNodesToVirtualCtrNode( _pvcnRoot->_cStreams, _pvcnRoot, pcnRoot->_cbMinStream, pcnRoot->_cbMaxStream);
DH_HRCHECK(hr, TEXT("AppendVirtualStmNodesToVirtualCtrNode")) ;
}
// Calculate the CRC for storage name
if(S_OK == hr) { hr = CalculateInMemoryCRCForStg(_pvcnRoot, &(_pvcnRoot->_dwCRC));
DH_HRCHECK(hr, TEXT("CalculateInMemoryCRCForStg")) ; }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::GrowVirtualDFTree, protected
//
// Synopsis: Creates the ramaining VirtualDocFile tree.
//
// Arguments: [pcnCurrent] - Pointer to current node of ChanceDocFile tree
// [pvcnCurrent] - Pointer to current VirtualCtrNode
//
// Returns: HRESULT
//
// History: Narindk 13-Jun-96 Made into a new function
//
// Notes: The VirtualDocFile tree is created based on the corresponding
// ChanceDocFile tree. This function is called either from the
// GenerateVirtualDF function or may call itself recursively. The
// ChanceDocFile tree is traversed from the top down, and based
// on its contents, a VirtualDF tree is generated topdown.
//
// First assign the passed in ChanceNode to pcnCurrentChild and
// passed in VirtualCtrNode to pvcnFisrtBorn variables.
// Loop till pcnCurrentChild's _pcnChild is non NULL & hr is S_OK
// - Call AppendVirtualCtrNode to create a new node pvcnNextBorn
// based on info from corresponding ChanceDocFile node and
// append it to pvcnFirstBorn in the tree being generated.
// - Assign pcnCurrentChild's _pcnChild to pcnCurrentSister.
// - Loop till pcnCurrentSister's _pcnSister is non NULL & hr=S_OK
// - Call AppendVirtualCtrNode to create a new node pvcn
// NextBornSister and append it to pvcnFirstBorn. Pl.
// note that append function would take care to append
// it to its older sister.
// - Assign pcnCurrentSister's _pcnSister to variable
// pcnCurrentSister.
// - If pcnCurrentSister's _pcnChild is non NULL, then
// make a recursive call to itself GrowVirtualDFTree.
// - Reinitialize pvcnNextBornSister to NULL & go back to
// top of this inner loop and repeat.
// - Assign pvcnNextBorn to pvcnFirstBorn and reinitailize pvcn
// NextBorn to NULL.
// - Assign pcnCurrentChild's _pcnChild to pcnCurrentChild.
// - Go to top of outer loop and repeat.
//---------------------------------------------------------------------------
HRESULT VirtualDF::GrowVirtualDFTree( ChanceNode *pcnCurrent, VirtualCtrNode *pvcnCurrent) { HRESULT hr = S_OK; VirtualCtrNode *pvcnFirstBorn = NULL; VirtualCtrNode *pvcnNextBorn = NULL; VirtualCtrNode *pvcnNextBornSister = NULL; ChanceNode *pcnCurrentSister = NULL; ChanceNode *pcnCurrentChild = NULL;
DH_VDATEPTRIN(pcnCurrent, ChanceNode) ; DH_VDATEPTRIN(pvcnCurrent, VirtualCtrNode) ;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::GrowVirtualDFTree"));
DH_ASSERT(NULL != pcnCurrent); DH_ASSERT(NULL != pvcnCurrent);
if(S_OK == hr) { pvcnFirstBorn = pvcnCurrent; pcnCurrentChild = pcnCurrent; }
while((NULL != pcnCurrentChild->_pcnChild) && (S_OK == hr)) { int x=10; do { hr = AppendVirtualCtrNode( pvcnFirstBorn, pcnCurrentChild->_pcnChild, &pvcnNextBorn); DH_HRCHECK(hr, TEXT("AppendVirtualCtrNode")) ; if (STG_E_FILEALREADYEXISTS == hr) { // delete the ctr node so we can try again.
DeleteVirtualDocFileTree (pvcnNextBorn); // DeleteVirtualDocFileTree decrements the _cChildren,
// but since no child was added in the first place,
// restore it to its original value so we can try again.
pvcnFirstBorn->_cChildren++; DH_TRACE ((DH_LVL_ALWAYS, TEXT("Above ERROR and ASSERT are OK."))); } } while (STG_E_FILEALREADYEXISTS == hr && --x);
if(S_OK == hr) { pcnCurrentSister = pcnCurrentChild->_pcnChild;
while((NULL != pcnCurrentSister->_pcnSister) && (S_OK == hr)) { int x=10; do { hr = AppendVirtualCtrNode( pvcnFirstBorn, pcnCurrentSister->_pcnSister, &pvcnNextBornSister); DH_HRCHECK(hr, TEXT("AppendVirtualCtrNode")) ; if (STG_E_FILEALREADYEXISTS == hr) { // delete the ctr node so we can try again.
DeleteVirtualDocFileTree (pvcnNextBornSister); // DeleteVirtualDocFileTree decrements the _cChildren,
// but since no child was added in the first place,
// restore it to its original value so we can try again.
pvcnFirstBorn->_cChildren++; DH_TRACE ((DH_LVL_ALWAYS, TEXT("Above ERROR and ASSERT are OK."))); } } while (STG_E_FILEALREADYEXISTS == hr && --x);
pcnCurrentSister = pcnCurrentSister->_pcnSister;
// Check if there are any children of this sister node, if
// yes, then make a recursive call to self.
if(NULL != pcnCurrentSister->_pcnChild) { hr = GrowVirtualDFTree( pcnCurrentSister, pvcnNextBornSister);
DH_HRCHECK(hr, TEXT("GrowVirtualDFTree")); }
// Reinitialize the variables
pvcnNextBornSister = NULL; } } pvcnFirstBorn = pvcnNextBorn; pvcnNextBorn = NULL;
pcnCurrentChild = pcnCurrentChild->_pcnChild; }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::AppendVirtualCtrNode, protected
//
// Synopsis: Creates and appends VirtualCtrNode to VirtualDocFile tree
// being created.
//
// Arguments: [pvcnParent] - Parent VirtualCtrNode for the new VirtualCtrNode
// [pcnCurrent] - Corresponding ChanceNode in ChanceDocFile tree.
// [ppvcnNew] - Pointer to pointer to new VirtualCtrNode to be
// created.
// Returns: HRESULT
//
// History: Narindk 23-Apr-96 Created
//
// Notes: - Generate a random name for VirtualCtrNode
// - Creates VirtualCtrNode object and initializes it with info
// based on corresponding ChanceDocFile node.
// - Appends this node to the VirtualDF tree being generated.
// - Create real IStorage corresponding to this VirtualCtrNode.
// - Creates IStreams corresponding to this VirtualCtrNode, if
// required.
// - Calculates in memory CRC for this IStorage and assigns it
// to _dwCRC variable.
//---------------------------------------------------------------------------
HRESULT VirtualDF::AppendVirtualCtrNode( VirtualCtrNode *pvcnParent, ChanceNode *pcnCurrent, VirtualCtrNode **ppvcnNew) { HRESULT hr = S_OK; LPTSTR ptcsName = NULL ; VirtualCtrNode *pvcnOldSister = NULL;
DH_VDATEPTROUT(ppvcnNew, PVCTRNODE) ; DH_VDATEPTRIN(pvcnParent, VirtualCtrNode) ; DH_VDATEPTRIN(pcnCurrent, ChanceNode) ;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("AppendVirtualCtrNode")); DH_ASSERT(NULL != pvcnParent); DH_ASSERT(NULL != ppvcnNew); DH_ASSERT(NULL != pcnCurrent);
if(S_OK == hr) { *ppvcnNew = NULL;
hr = GenerateRandomName(_pgdu, MINLENGTH, MAXLENGTH, &ptcsName);
DH_HRCHECK(hr, TEXT("GenerateRandomName")) ; }
if(S_OK == hr) { // Allocate and Initialize new VirtualCtrNode
*ppvcnNew = new VirtualCtrNode(); if (NULL == *ppvcnNew) { hr = E_OUTOFMEMORY; } }
if(S_OK == hr) { hr = (*ppvcnNew)->Init( ptcsName, pcnCurrent->_cStorages, pcnCurrent->_cStreams);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ; }
// Append new VirtualCtr Node
if(S_OK == hr) { if(NULL == pvcnParent->_pvcnChild) { hr = pvcnParent->AppendChildCtr(*ppvcnNew);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendChildCtr")) ; } else { pvcnOldSister = pvcnParent->_pvcnChild; while(NULL != pvcnOldSister->_pvcnSister) { pvcnOldSister = pvcnOldSister->_pvcnSister; }
hr = pvcnOldSister->AppendSisterCtr(*ppvcnNew);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendSisterCtr")) ; } } // Call VirtualCtrNode::Create to create a corresponding Storage on disk.
if(S_OK == hr) { hr = (*ppvcnNew)->Create( _dwStgMode | STGM_CREATE, 0, 0); DH_HRCHECK(hr, TEXT("VirtualCtrNode::Create")) ;
// Generate VirtualStmNode(s) depending upon if it has streams in it.
DH_ASSERT((pcnCurrent->_cStreams) == ((*ppvcnNew)->_cStreams)); }
if ((S_OK == hr) && (0 != (*ppvcnNew)->_cStreams)) { hr = AppendVirtualStmNodesToVirtualCtrNode( (*ppvcnNew)->_cStreams, *ppvcnNew, pcnCurrent->_cbMinStream, pcnCurrent->_cbMaxStream);
DH_HRCHECK(hr, TEXT("AppendVirtualStmNodesToVirtualCtrNode")) ; }
// Calculate the CRC for storage name
if(S_OK == hr) { hr = CalculateInMemoryCRCForStg(*ppvcnNew, &((*ppvcnNew)->_dwCRC));
DH_HRCHECK(hr, TEXT("CalculateInMemoryCRCForStg")) ; }
// Cleanup
if(NULL != ptcsName) { delete ptcsName; ptcsName = NULL; } return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::AppendVirtualStmNodesToVirtualCtrNode, protected
//
// Synopsis: Creates and appends VirtualStmNode(s) to VirtualCtrNode
//
// Arguments: [cStreams] - Number of streams to be created
// [pvcn] - Pointer to VirtualCtrNode for which the streams
// need to be created and appended.
// [cbMinStream] - Minimum size of created stream.
// [cbMaxStream] - Maximum size of created stream.
//
// Returns: HRESULT
//
// History: Narindk 23-Apr-96 Created
//
// Notes: if number of streams to be created and appended to parent
// VirtualCtrNode pvcn is not zero, then loop till cStreams is
// not equal to zero.
// - Call AppendVirtualStmNode to create a new VirtualStmNode
// and append it to parent VirtualCtrNode. Pl. note that
// this function would take care if the newly created node
// need to be appended to older VirtualStmNode sister.
// - Decrement cStreams and o back to top of loop & repeat.
//---------------------------------------------------------------------------
HRESULT VirtualDF::AppendVirtualStmNodesToVirtualCtrNode( ULONG cStreams, VirtualCtrNode *pvcn, ULONG cbMinStream, ULONG cbMaxStream) { HRESULT hr = S_OK;
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_FUNCENTRY( &hr, DH_LVL_DFLIB, _TEXT("::AppendVirtualStmNodesToVirtualCtrNode")); DH_ASSERT(0 != cStreams); DH_ASSERT(NULL != pvcn);
while((S_OK == hr) && (0 != cStreams)) { hr = AppendVirtualStmNode( pvcn, cbMinStream, cbMaxStream);
DH_HRCHECK(hr, TEXT("AppendVirtualStmNode")) ;
cStreams--; }
return hr; } //----------------------------------------------------------------------------
// Member: VirtualDF::AppendVirtualStmNode, protected
//
// Synopsis: Creates and appends first VirtualStmNode to VirtualCtrNode
//
// Arguments: [pvcnParent] - Pointer to VirtualCtrNode for which the streams
// need to be created and appended.
// [cbMinStream] - Minimum size of created stream.
// [cbMaxStream] - Maximum size of created stream.
//
// Returns: HRESULT
//
// History: Narindk 23-Apr-96 Created
// georgis 02-Apr-98 Added support for large streams
//
// Notes: - Generate a random name for VirtualStmNode
// - Generates a random size for stream based on inforamtion
// from corresponding ChanceDocFile tree node.
// - Creates VirtualStmNode object and initializes it with above
// info
// - Appends this node to the parent VirtualCtrNode.
// - Create real IStream corresponding to this VirtualStmNode.
// - Set the size of stream based on size calculated above.
// - Write into the stream random data of above size
// - Calculates in memory CRC for this IStream and assigns it
// to _dwCRC variable.
//---------------------------------------------------------------------------
HRESULT VirtualDF::AppendVirtualStmNode( VirtualCtrNode *pvcnParent, ULONG cbMinStream, ULONG cbMaxStream) { HRESULT hr = S_OK; VirtualStmNode *pvsnNew = NULL; VirtualStmNode *pvsnOldSister = NULL; ULONG cb = 0; USHORT usErr = 0; LPTSTR ptcsName = NULL ; BYTE *pBuffer = NULL ; ULONG culWritten = 0; ULARGE_INTEGER uli; DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::AppendVirtualStmNode"));
DH_VDATEPTRIN(pvcnParent, VirtualCtrNode) ; DH_ASSERT(NULL != pvcnParent);
if (S_OK == hr) { hr = GenerateRandomName(_pgdu, MINLENGTH, MAXLENGTH, &ptcsName);
DH_HRCHECK(hr, TEXT("GenerateRandomName")) ; }
if (S_OK == hr) { // Generate random size for stream.
usErr = _pdgi->Generate(&cb, cbMinStream, cbMaxStream);
if (DG_RC_SUCCESS != usErr) { hr = E_FAIL; } } // Allocate a new VirtualStmNode
if (S_OK == hr) { pvsnNew = new VirtualStmNode();
if (NULL == pvsnNew) { hr = E_OUTOFMEMORY; } } if(S_OK == hr) { hr = pvsnNew->Init(ptcsName, cb);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Init")) ; }
if(S_OK == hr) {
if(NULL == pvcnParent->_pvsnStream) { // Append it to parent storage
hr = pvcnParent->AppendFirstChildStm(pvsnNew);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendFirstChildStm")) ; } else { pvsnOldSister = pvcnParent->_pvsnStream;
while(NULL != pvsnOldSister->_pvsnSister) { pvsnOldSister = pvsnOldSister->_pvsnSister; }
// Append it to preceding sister stream
hr = pvsnOldSister->AppendSisterStm(pvsnNew);
DH_HRCHECK(hr, TEXT("VirtualStmNode::AppendSisterStm")) ; } }
// Call VirtualStmNode::Create to create a corresponding Stream on disk.
if(S_OK == hr) { // Since in OLE code: simpstg.cxx, it makes the following comparison:
// if (grfMode != (STGM_READWRITE | STGM_SHARE_EXCLUSIVE))
// return STG_E_INVALIDFLAG;
// We can't pass _dwStmMode | STGM_CREATE like in normal mode,
// otherwise we will get STG_E_INVALIDFLAG error.
if (_dwRootMode & STGM_SIMPLE) { hr = pvsnNew->Create( _dwStmMode | STGM_FAILIFTHERE, 0, 0);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Create")) ; } else
{ hr = pvsnNew->Create( _dwStmMode | STGM_CREATE | STGM_FAILIFTHERE, 0, 0);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Create")) ; }
}
// Call VirtualStmNode::SetSize to set size of stream.
if(S_OK == hr) { ULISet32(uli, cb);
hr = pvsnNew->SetSize(uli);
DH_HRCHECK(hr, TEXT("VirtualStmNode::SetSize")) ; }
if(S_OK == hr) { ULONG ulTotalWritten = 0; ULONG ulChunkSize =0; DWORD dwOffset=0; register DWORD dwCRC=CRC_PRECONDITION;
#if 0
// Use for small chunks
hr = GenerateRandomName(_pgdu, STM_CHUNK_SIZE, STM_CHUNK_SIZE, (LPTSTR *) &pBuffer); DH_HRCHECK(hr, TEXT("GenerateRandomName")); #else
// If the chunk is very large, avoid generating many random numbers
hr = GenerateRandomStreamData(_pgdu,(LPTSTR *) &pBuffer,STM_CHUNK_SIZE); DH_HRCHECK(hr, TEXT("GenerateRandomStreamData")); #endif
while ((S_OK == hr) && (ulTotalWritten < cb)) { // Write the data from random offset to the end of the buffer
_pdgi->Generate(&dwOffset,0,STM_CHUNK_SIZE-2); ulChunkSize=min(cb-ulTotalWritten,STM_CHUNK_SIZE-dwOffset); hr = pvsnNew->Write(pBuffer+dwOffset, ulChunkSize, &culWritten); DH_HRCHECK(hr, TEXT("VirtualStmNode::Write")) ; if (S_OK == hr) // Skip if we are failing
{ ulTotalWritten+=culWritten;
// Calculate the CRC now, to spare aditional Read
for (register int i=0; i<culWritten; i++) { CRC_CALC(dwCRC,(BYTE) pBuffer[dwOffset+i]) }; } }
// Update the vsnode created
pvsnNew->_dwCRC.dwCRCData=dwCRC;
hr=CalculateCRCForName(pvsnNew->_ptszName,&pvsnNew->_dwCRC.dwCRCName); DH_HRCHECK(hr, TEXT("CalculateCRCForName"));
pvsnNew->_dwCRC.dwCRCSum=CRC_PRECONDITION; MUNGECRC(pvsnNew->_dwCRC.dwCRCSum,pvsnNew->_dwCRC.dwCRCData); MUNGECRC(pvsnNew->_dwCRC.dwCRCSum,pvsnNew->_dwCRC.dwCRCName); }
// Since for simple mode docfile, access to streams follows a linear
// pattern, it needs to close the current stream before creating and
// open another stream. So for simple mode docfile, after the docfile
// is created, all the elements are closed except the root storage.
// For the normal mode docfile, after it is created, all the elements
// are kept open.
if ((S_OK == hr) && (_dwRootMode & STGM_SIMPLE)) { hr = pvsnNew->Close(); DH_HRCHECK(hr, TEXT("VirtualStmNode::Close")) ; }
// Cleanup
if(NULL != ptcsName) { delete ptcsName; ptcsName = NULL; }
if(NULL != pBuffer) { delete pBuffer; pBuffer = NULL; }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::DeleteVirtualDocFileTree, public
//
// Synopsis: Deletes the VirtualDocFileTree from the passed in Virtual
// CtrNode node down.
//
// Arguments: [pvcnTrav] - Pointer to VirtualCtrNode from which node
// downwards, including itself, the tree would
// be deleted.
//
// Returns: HRESULT
//
// History: Narindk 24-Apr-96 Created
//
// Notes: First step is to check if the whole tree needs to be deleted or
// just a part of it. In case only a part of tree is to be
// deleted, isolate the node from the remaining tree by readjusting
// the pointers in the remaining tree. Then call the function
// DeleteVirtualDocFileSubTree to delete the subtree. In case,
// the complete tree needs to be deleted, we call the function
// DeleteVirtualDocFileSubTree directly to delete the complete
// tree.
//---------------------------------------------------------------------------
HRESULT VirtualDF::DeleteVirtualDocFileTree(VirtualCtrNode *pvcnTrav) { HRESULT hr = S_OK; VirtualCtrNode *pTempNode = NULL;
DH_VDATEPTRIN(pvcnTrav, VirtualCtrNode) ; DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::DeleteVirtualDocFileTree")); DH_ASSERT(NULL != pvcnTrav);
if(S_OK == hr) { // This basically readjusts the pointers in the tree if the passed in
// VirtualCtrNode is not the root of the VirtualDF tree.
if(NULL != pvcnTrav->_pvcnParent) { // Decrease the _cChildren variable of the parent VirtualCtrNode.
pvcnTrav->_pvcnParent->_cChildren--;
// Find its previous node whose pointers need readjustment.
pTempNode = pvcnTrav->_pvcnParent->_pvcnChild; while ((pvcnTrav != pvcnTrav->_pvcnParent->_pvcnChild) && (pvcnTrav != pTempNode->_pvcnSister)) { pTempNode = pTempNode->_pvcnSister; DH_ASSERT(NULL != pTempNode); }
// Readjust the child pointer or sister pointer as the case may be.
pvcnTrav->_pvcnParent->_pvcnChild = (pvcnTrav == pTempNode) ? pvcnTrav->_pvcnSister : pvcnTrav->_pvcnParent->_pvcnChild; pTempNode->_pvcnSister = pvcnTrav->_pvcnSister; } }
if(S_OK == hr) { hr = DeleteVirtualDocFileSubTree(&pvcnTrav);
DH_HRCHECK(hr, TEXT("DeleteVirtualDocFileSubTree")) ; }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::DeleteVirtualDocFileSubTree, protected
//
// Synopsis: Deletes iteratively all VirtualCtrNode nodes under and including// the passed in VirtualCtrNode and calls a function to delete
// all VirtualStmNodes under the VirtualCtrNodes being deleted.
//
// Arguments: [**ppvcnTrav]- Pointer to pointer to VirtualCtrNode from
// which node under, including itself, the tree
// would be deleted.
//
// Returns: HRESULT
//
// History: Narindk 24-Apr-96 Created
//
// Notes: This function is called only through DeleteVirtualDocFileTree.
//
// Assign the passed in VirtualCtrNode to a variable pTempRoot.
// NULL the pTempRoot's parent.
// Loop till the pTempRoot is not NULL to delete tree iteratively.
// - Assign pTempRoot to a temp variable pTempNode.
// - Traverse the tree to make pTempNode point to last child
// (_pvcnChild).
// - Assign pTempNode's _pvcnParent to pTempRoot
// - Assign the pTempRoot's _pvcnChild pointer to point to the
// sister of pTempNode's _pvcnSister rather than to itself,
// therby isolating itself.
// - Decrement the _cChildren of pTempRoot (used to verify).
// - Assign pTempNode's _pvcnSister to NULL.
// - if pTempNode's _pvsnStream is not NULL, call function
// DeleteVirtualCtrNodeStreamTree to delete all its Virtual
// StmNodes.
// - Assert to ensure the pTempNode's _cChildren and _cStreams
// are zero before deleting it.
// - Delete pTempNode.
// - Go back to top of loop and repeat till all nodes are
// deleted.
//---------------------------------------------------------------------------
HRESULT VirtualDF::DeleteVirtualDocFileSubTree(VirtualCtrNode **ppvcnTrav) { HRESULT hr = S_OK; VirtualCtrNode *pTempRoot = NULL; VirtualCtrNode *pTempNode = NULL;
DH_VDATEPTRIN(ppvcnTrav, PVCTRNODE) ; DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::DeleteVirtualDocFileSubTree"));
DH_ASSERT(NULL != *ppvcnTrav);
if(S_OK == hr) { pTempRoot = *ppvcnTrav; pTempRoot->_pvcnParent = NULL;
// This iteratives deletes the VirtualCtrNode and everything under it.
while(NULL != pTempRoot) { pTempNode = pTempRoot; while(NULL != pTempNode->_pvcnChild) { pTempNode = pTempNode->_pvcnChild; }
pTempRoot = pTempNode->_pvcnParent; if(pTempRoot != NULL) { pTempRoot->_pvcnChild = pTempNode->_pvcnSister; // Decrease the children count, this would be used to verify
// before deleting the VirtualCtrNode.
pTempRoot->_cChildren--; }
pTempNode->_pvcnSister = NULL;
if(pTempNode->_pvsnStream != NULL) { hr = DeleteVirtualCtrNodeStreamTree(pTempNode);
DH_HRCHECK(hr, TEXT("DeleteVirtualCtrNodeStreamTree")) ; }
// Confirm before deleting that all its sub child storages and
// streams have been deleted, assert if not.
DH_ASSERT(0 == pTempNode->_cChildren); DH_ASSERT(0 == pTempNode->_cStreams);
delete pTempNode; pTempNode = NULL; } }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::DeleteVirtualCtrNodeStreamTree, protected
//
// Synopsis: Deletes iteratively all VirtualStmNodes under the given
// VirtualCtrNode.
//
// Arguments: [*pvcnTrav]- Pointer to VirtualCtrNode for which all streams
// need to be deleted.
//
// Returns: HRESULT
//
// History: Narindk 24-Apr-96 Created
//
// Notes: Loop till pvcnTrav's _pvsnStream is not NULL
// - Assign a temp variable pvsnTemp to point to _pvsnStream of
// passed in VirtualCtrNode pvcnTrav.
// - Assign pvcnTrav's _pvsnStream to point to pvsnTemp's _pvsn
// Sister, thereby isolating the first VirtualStmNode.
// - Decrease the _cStreams pf pvcnTrav (used to verify).
// - Assign pvsnTemp's _pvsnSister to NULL.
// - Delete pvsnTemp
// - Go back to top of loop.
//---------------------------------------------------------------------------
HRESULT VirtualDF::DeleteVirtualCtrNodeStreamTree(VirtualCtrNode *pvcnTrav) { HRESULT hr = S_OK; VirtualStmNode *pvsnTemp = NULL;
DH_VDATEPTRIN(pvcnTrav, VirtualCtrNode) ; DH_FUNCENTRY(&hr, DH_LVL_DFLIB,TEXT("::::DeleteVirtualCtrNodeStreamTree"));
DH_ASSERT(NULL != pvcnTrav);
if(S_OK == hr) { // This iteratively deletes all VirtualStmNodes.
while(NULL != pvcnTrav->_pvsnStream) { pvsnTemp = pvcnTrav->_pvsnStream; pvcnTrav->_pvsnStream = pvsnTemp->_pvsnSister;
// Decrease the stream count. This would be used to verify before
// deleting the parent VirtualCtrNode.
pvcnTrav->_cStreams--;
// Delete the node.
pvsnTemp->_pvsnSister = NULL; delete pvsnTemp; pvsnTemp = NULL; } }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::AdjustTreeOnStgMoveElement, public
//
// Synopsis: Adjusts the VirtualDocFileTree when IStorage::MoveElementTo
// as move is operated on a IStorage element
//
// Arguments: [pvcnFrom] - Pointer to VirtualCtrNode to be moved
// [pvcnTo] - Pointer to VirtualCtrNode moved to
//
// Returns: HRESULT
//
// History: Narindk 13-May-1996 Created
//
// Notes; Doesn't initialize the _pstg of moved tree elements
// as that would require opening of those moved storages/streams.
// This readjusts the tree by removing the moved element from
// its original position in tree & reinserting it in tree at its
// new destination. This function is not used when the root it
// self is moved, assert if root is being moved.
//
// 1. Decrease the pvcnFrom's _pvcnParent's _cChildren count
// indicating that pvcnFrom is being moved.
// 2. In the tree, find its previous node whose pointers would
// need readjustment. Find its older sister if it has one,
// adjust its _pvcnSister pointer. Or if the node being moved
// is _pvcnChild of its parent _pvcnParent, then adjust the
// _pvcnParent's _pvcnChild to _pvcnSister of node being moved.
// 3. NULL out pvcnFrom's _pvcnParent, _pvcnSister pointers thereby
// isolating this VirtualCtrNode. NULL out _pstg too since
// that would have been already move to by IStorage::MoveElement// To call prior to calling this function.
// 4. In destination node pvcnTo, check if it's _pvcnChild is NULL.
// if yes, then assign pvcnFrom to _pvcnTo's _pvcnChild. If it
// is not NULL, then traverse through its children to reach
// last _pvcnSister and assign pvcnFrom to that.
// 5. Assign pvcnFrom's _pvcnParent to be pvcnTo. Also increment
// pvcnTo's _cChildren count indicating the new VirtualCtrNode
// being moved here.
//---------------------------------------------------------------------------
HRESULT VirtualDF::AdjustTreeOnStgMoveElement( VirtualCtrNode *pvcnFrom, VirtualCtrNode *pvcnTo ) { HRESULT hr = S_OK; VirtualCtrNode *pTempNode = NULL; VirtualCtrNode *pvcnTrav = NULL;
DH_VDATEPTRIN(pvcnFrom, VirtualCtrNode) ; DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ; DH_FUNCENTRY( &hr, DH_LVL_DFLIB, _TEXT("::AdjustTreeOnStgMoveElement")); DH_ASSERT(NULL != pvcnTo); DH_ASSERT(NULL != pvcnFrom);
// Assert if this is the root that is being moved.
DH_ASSERT(NULL != pvcnFrom->_pvcnParent);
if(S_OK == hr) { // Decrease the _cChildren variable of the parent VirtualCtrNode.
pvcnFrom->_pvcnParent->_cChildren--;
// Find its previous node whose pointers need readjustment.
pTempNode = pvcnFrom->_pvcnParent->_pvcnChild; while ((pvcnFrom != pvcnFrom->_pvcnParent->_pvcnChild) && (pvcnFrom != pTempNode->_pvcnSister)) { pTempNode = pTempNode->_pvcnSister; DH_ASSERT(NULL != pTempNode); }
// Readjust the child pointer or sister pointer as the case may be.
pvcnFrom->_pvcnParent->_pvcnChild = (pvcnFrom == pTempNode) ? pvcnFrom->_pvcnSister : pvcnFrom->_pvcnParent->_pvcnChild; pTempNode->_pvcnSister = pvcnFrom->_pvcnSister;
// NULL out its pointers
pvcnFrom->_pvcnParent = NULL; pvcnFrom->_pvcnSister = NULL; pvcnFrom->_pstg = NULL; }
if(S_OK == hr) { if(NULL != pvcnTo->_pvcnChild) { pvcnTrav = pvcnTo->_pvcnChild; while(NULL != pvcnTrav->_pvcnSister) { pvcnTrav = pvcnTrav->_pvcnSister; } pvcnTrav->_pvcnSister = pvcnFrom; } else { pvcnTo->_pvcnChild = pvcnFrom; } pvcnFrom->_pvcnParent = pvcnTo; pvcnTo->_cChildren++; }
// The storage was closed prior to its move. So do we need to reopen it
// from here now from moved destination.
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::AdjustTreeOnStmMoveElement, public
//
// Synopsis: Adjusts the VirtualDocFileTree when IStorage::MoveElementTo
// as move is operated on a IStream element
//
// Arguments: [pvsnFrom] - Pointer to VirtualStmNode to be moved
// [pvcnTo] - Pointer to VirtualCtrNode moved to
//
// Returns: HRESULT
//
// History: Narindk 9-July-1996 Created
//
// Notes; Doesn't initialize the _pstm of moved tree elements
// as that would require opening of the moved stream.
// This readjusts the tree by removing the moved element from
// its original position in tree & reinserting it in tree at its
// new destination.
//
// 1. Decrease the pvcnFrom's _pvcnParent's _cStreams count
// indicating that pvsnFrom is being moved.
// 2. In the tree, find its previous node whose pointers would
// need readjustment. Find its older sister if it has one,
// adjust its _pvsnSister pointer. Or if the node being moved
// is _pvsnStream of its parent _pvcnParent, then adjust the
// _pvcnParent's _pvsnStream to _pvsnSister of node being moved.
// 3. NULL out pvsnFrom's _pvcnParent, _pvsnSister pointers thereby
// isolating this VirtualStmNode. NULL out _pstm too since
// that would have been already move to by IStorage::MoveElement// To call prior to calling this function.
// 4. In destination node pvcnTo,check if it's _pvsnStream is NULL.
// if yes, then assign pvsnFrom to _pvcnTo's _pvcnStream. If it
// is not NULL, then traverse through its stream nodes to reach
// last _pvsnSister and assign pvsnFrom to that.
// 5. Assign pvsnFrom's _pvcnParent to be pvcnTo. Also increment
// pvcnTo's _cStreams count indicating the new VirtualStmNode
// being moved here.
//---------------------------------------------------------------------------
HRESULT VirtualDF::AdjustTreeOnStmMoveElement( VirtualStmNode *pvsnFrom, VirtualCtrNode *pvcnTo ) { HRESULT hr = S_OK; VirtualStmNode *pTempNode = NULL; VirtualStmNode *pvsnTrav = NULL;
DH_VDATEPTRIN(pvsnFrom, VirtualStmNode) ; DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ; DH_FUNCENTRY( &hr, DH_LVL_DFLIB, _TEXT("::AdjustTreeOnStmMoveElement")); DH_ASSERT(NULL != pvcnTo); DH_ASSERT(NULL != pvsnFrom); DH_ASSERT(NULL != pvsnFrom->_pvcnParent);
if(S_OK == hr) { // Decrease the _cStreams variable of the parent VirtualCtrNode.
pvsnFrom->_pvcnParent->_cStreams--;
// Find its previous node whose pointers need readjustment.
pTempNode = pvsnFrom->_pvcnParent->_pvsnStream; while ((pvsnFrom != pvsnFrom->_pvcnParent->_pvsnStream) && (pvsnFrom != pTempNode->_pvsnSister)) { pTempNode = pTempNode->_pvsnSister; DH_ASSERT(NULL != pTempNode); }
// Readjust the pointer(s) as the case may be.
pvsnFrom->_pvcnParent->_pvsnStream = (pvsnFrom == pTempNode) ? pvsnFrom->_pvsnSister : pvsnFrom->_pvcnParent->_pvsnStream; pTempNode->_pvsnSister = pvsnFrom->_pvsnSister;
// NULL out its pointers
pvsnFrom->_pvcnParent = NULL; pvsnFrom->_pvsnSister = NULL; pvsnFrom->_pstm = NULL; }
if(S_OK == hr) { if(NULL != pvcnTo->_pvsnStream) { pvsnTrav = pvcnTo->_pvsnStream; while(NULL != pvsnTrav->_pvsnSister) { pvsnTrav = pvsnTrav->_pvsnSister; } pvsnTrav->_pvsnSister = pvsnFrom; } else { pvcnTo->_pvsnStream = pvsnFrom; } pvsnFrom->_pvcnParent = pvcnTo; pvcnTo->_cStreams++; }
// The stream was closed prior to its move. So do we need to reopen it
// from here now from moved destination.
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::AdjustTreeOnStgCopyElement, public
//
// Synopsis: Adjusts the VirtualDocFileTree when IStorage::MoveElementTo
// as copy is operated on a IStorage element
//
// Arguments: [pvcnFrom] - Pointer to VirtualCtrNode to be moved as copy
// [pvcnTo] - Pointer to VirtualCtrNode moved to
//
// Returns: HRESULT
//
// History: Narindk 20-May-1996 Created
//
// Notes; Doesn't initialize the _pstg's/_pstm's of copied tree elements
// as that would require opening of those copied storages/streams.
// This readjusts the tree by inserting the copied element in tree
// at its new destination. This function is not used when the
// root itself is copied, assert if root is being moved.
//
// 1. Call CopyVirtualDocFileTree function to copy pvcnFrom to
// pvcnNew.
// 2. In destination node pvcnTo, check if it's _pvcnChild is NULL.
// if yes, then assign pvcnFrom to _pvcnTo's _pvcnChild. If it
// is not NULL, then traverse through its children to reach
// last _pvcnSister and assign pvcnFrom to that.
// 3. Assign pvcnFrom's _pvcnParent to be pvcnTo. Also increment
// pvcnTo's _cChildren count indicating the new VirtualCtrNode
// being copied here. Also assign pvcnNew's _pvcnSister to
// NULL.
//---------------------------------------------------------------------------
HRESULT VirtualDF::AdjustTreeOnStgCopyElement( VirtualCtrNode *pvcnFrom, VirtualCtrNode *pvcnTo ) { HRESULT hr = S_OK; VirtualCtrNode *pvcnTrav = NULL; VirtualCtrNode *pvcnNew = NULL;
DH_VDATEPTRIN(pvcnFrom, VirtualCtrNode) ; DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ; DH_FUNCENTRY( &hr, DH_LVL_DFLIB, _TEXT("::AdjustVirtualDocFileTreeOnStgCopyElement")); DH_ASSERT(NULL != pvcnTo); DH_ASSERT(NULL != pvcnFrom);
// Assert if this is the root that is being copied.
DH_ASSERT(NULL != pvcnFrom->_pvcnParent);
if(S_OK == hr) { hr = CopyVirtualDocFileTree(pvcnFrom, NEW_STGSTM, &pvcnNew); }
if(S_OK == hr) { if(NULL != pvcnTo->_pvcnChild) { pvcnTrav = pvcnTo->_pvcnChild; while(NULL != pvcnTrav->_pvcnSister) { pvcnTrav = pvcnTrav->_pvcnSister; } pvcnTrav->_pvcnSister = pvcnNew; } else { pvcnTo->_pvcnChild = pvcnNew; } pvcnNew->_pvcnParent = pvcnTo; pvcnTo->_cChildren++; pvcnNew->_pvcnSister = NULL; }
// The storage was closed prior to its copy. So do we need to open it
// now from copied destination. How about other _pstg / _pstm for
// copied tree?
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::AdjustTreeOnStmCopyElement, public
//
// Synopsis: Adjusts the VirtualDocFileTree when IStorage::MoveElementTo
// as copy is operated on a IStream element
//
// Arguments: [pvsnFrom] - Pointer to VirtualstmNode to be moved as copy
// [pvcnTo] - Pointer to VirtualCtrNode moved to
//
// Returns: HRESULT
//
// History: Narindk 9-July-1996 Created
//
// Notes; Doesn't initialize the _pstm of copied tree stream element
// as that would require opening of the copied stream.
// This readjusts the tree by inserting the copied element in tree
// at its new destination.
//
// 1. Copy the VirtualStmNode to be copied to a new VirtualStmNode.
// 2. In destination node pvcnTo,check if it's _pvsnStream is NULL.
// if yes, then assign pvsnFrom to _pvcnTo's _pvsnStream. If it
// is not NULL, then traverse through its streams to reach
// last _pvsnSister and assign pvsnFrom to that.
// 3. Assign pvsnFrom's _pvcnParent to be pvcnTo. Also increment
// pvcnTo's _cStreams count indicating the new VirtualStmNode
// being copied here.
//---------------------------------------------------------------------------
HRESULT VirtualDF::AdjustTreeOnStmCopyElement( VirtualStmNode *pvsnFrom, VirtualCtrNode *pvcnTo ) { HRESULT hr = S_OK; VirtualStmNode *pvsnTrav = NULL; VirtualStmNode *pvsnNew = NULL;
DH_VDATEPTRIN(pvsnFrom, VirtualStmNode) ; DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ; DH_FUNCENTRY( &hr, DH_LVL_DFLIB, _TEXT("::AdjustVirtualDocFileTreeOnStmCopyElement")); DH_ASSERT(NULL != pvcnTo); DH_ASSERT(NULL != pvsnFrom);
// Copy the VirtualStmNode to be moved as copy
if (S_OK == hr) { pvsnNew = new VirtualStmNode();
if (NULL == pvsnNew) { hr = E_OUTOFMEMORY; } }
if(S_OK == hr) { pvsnNew->_dwCRC.dwCRCName = pvsnFrom->_dwCRC.dwCRCName; pvsnNew->_dwCRC.dwCRCData = pvsnFrom->_dwCRC.dwCRCData; pvsnNew->_dwCRC.dwCRCSum = pvsnFrom->_dwCRC.dwCRCSum;
hr = pvsnNew->Init(pvsnFrom->_ptszName, pvsnFrom->_cb);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Init")) ; }
if(S_OK == hr) { if(NULL != pvcnTo->_pvsnStream) { pvsnTrav = pvcnTo->_pvsnStream; while(NULL != pvsnTrav->_pvsnSister) { pvsnTrav = pvsnTrav->_pvsnSister; } pvsnTrav->_pvsnSister = pvsnNew; } else { pvcnTo->_pvsnStream = pvsnNew; } pvsnNew->_pvcnParent = pvcnTo; pvcnTo->_cStreams++; }
// The stream was closed prior to its copy. So do we need to open it
// now from copied destination.
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::AdjustTreeOnCopyTo, public
//
// Synopsis: Adjusts the VirtualDocFileTree when IStorage::CopyTo
// is operated on a IStorage element
//
// Arguments: [pvcnFrom] - Pointer to VirtualCtrNode to be moved
// [pvcnTo] - Pointer to VirtualCtrNode moved to
//
// Returns: HRESULT
//
// History: Narindk 21-May-1996 Created
//
// Notes: This function differs from VirtualDF::AdjustTreeOnStgCopyEle
// ment bcause readjusts the tree in the lght that tree has to
// readjusted since an IStorage elemnt is moved as copy to desti-
// nation container by IStorage::MoveElementTo as copy. But here,
// we need to readjust the tree in the light thst the entire
// contents of an open IStorage object are copied into a dest
// by IStorage::CopyTo
//
// -Call CopyVirtualDocFileTree to copy everything under the node
// pvcnFrom, where IStorage::CopyTo source is to pvcnNew.
// -if pvcnNew has VirtualStmNode in it (_pvsnStream), then
// -Check if pvcnTo (dest) has _pvsnStream as NULL or not.
// -If not NULL, then loop to get to end of VirtualStm
// Nodes's _pvsnSister in the chain.
// -As appropriate, assign pvcnNew->_pvsnStream to the
// pvcnTo destination.
// -Adjust the _pvcnParent of pvcnNew->_pvsnStream to
// point to pvcnTo and increase _cStream member of
// pvcnTo node.
// -Assign a temp variable pvsnTemp to point to the pvcnNew
// ->_pvsnStream and then loop through to end of all
// sister VirtualStmNodes and make their _pvcnParent as
// pvcnTo and keep on incrementing _cStreams member of
// pvcnTo with each new VirtualStmNode traversed.
// -Now all VirtualStmNodes fro pvcnNew have been copied
// to pvcnTo, their destination.
// -Repeat same for any VirtualCtrNodes that pvcnNew may have.
// if pvcnNew has VirtualCtrNode in it (_pvcnChild), then
// -Check if pvcnTo (dest) has _pvcnChild as NULL or not.
// -If not NULL, then loop to get to end of VirtualCtr
// Nodes's _pvcnSister in the chain.
// -As appropriate, assign pvcnNew->_pvcnChild to the
// pvcnTo destination.
// -Adjust the _pvcnParent of pvcnNew->_pvcnChild to
// point to pvcnTo and increase _cChildren member of
// pvcnTo node.
// -Assign a temp variable pvcnTemp to point to the pvcnNew
// ->_pvcnChild and then loop through to end of all
// sister VirtualCtrNodes and make their _pvcnParent as
// pvcnTo and keep on incrementing _cChildren member of
// pvcnTo with each new VirtualCtrNode traversed.
// -Now all VirtualCtrNodes fro pvcnNew have been copied
// to pvcnTo, their destination.
// -Now everhing under pvcnNew has been copied to pvcnTo, so
// delete pvcnNew.
//---------------------------------------------------------------------------
HRESULT VirtualDF::AdjustTreeOnCopyTo( VirtualCtrNode *pvcnFrom, VirtualCtrNode *pvcnTo ) { HRESULT hr = S_OK; VirtualCtrNode *pvcnNew = NULL; VirtualCtrNode *pvcnTrav = NULL; VirtualCtrNode *pvcnTemp = NULL; VirtualStmNode *pvsnTrav = NULL; VirtualStmNode *pvsnTemp = NULL;
DH_VDATEPTRIN(pvcnFrom, VirtualCtrNode) ; DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ; DH_FUNCENTRY( &hr, DH_LVL_DFLIB, _TEXT("::AdjustTreeOnCopyTo")); DH_ASSERT(NULL != pvcnTo); DH_ASSERT(NULL != pvcnFrom);
// Assert if this is the root that is being copied.
DH_ASSERT(NULL != pvcnFrom->_pvcnParent);
if(S_OK == hr) { hr = CopyVirtualDocFileTree(pvcnFrom, NEW_STGSTM, &pvcnNew); }
if(S_OK == hr) { if(NULL != pvcnNew->_pvsnStream) { // Append these VirtualStmNode to pvcnTo VirtualCtrNode.
// BUGBUG: what if these VirtualStmNodes have same name stream in
// in destination too.
if(NULL != pvcnTo->_pvsnStream) { pvsnTrav = pvcnTo->_pvsnStream; while(NULL != pvsnTrav->_pvsnSister) { pvsnTrav = pvsnTrav->_pvsnSister; } pvsnTrav->_pvsnSister = pvcnNew->_pvsnStream; } else { pvcnTo->_pvsnStream = pvcnNew->_pvsnStream; } pvcnNew->_pvsnStream->_pvcnParent = pvcnTo; pvcnTo->_cStreams++; if(NULL != pvsnTrav) { pvsnTemp = pvsnTrav->_pvsnSister; } else { pvsnTemp = pvcnTo->_pvsnStream; }
while(NULL != pvsnTemp->_pvsnSister) { pvsnTemp->_pvsnSister->_pvcnParent = pvcnTo; pvcnTo->_cStreams++; pvsnTemp = pvsnTemp->_pvsnSister; } } }
if(S_OK == hr) { if(NULL != pvcnNew->_pvcnChild) { // Append these storages to pvcnTo VirtualCtrNode.
// BUGBUG: what if these VirtualCtrNodes have same name stroage in
// in destination too.
if(NULL != pvcnTo->_pvcnChild) { pvcnTrav = pvcnTo->_pvcnChild; while(NULL != pvcnTrav->_pvcnSister) { pvcnTrav = pvcnTrav->_pvcnSister; } pvcnTrav->_pvcnSister = pvcnNew->_pvcnChild; } else { pvcnTo->_pvcnChild = pvcnNew->_pvcnChild; } pvcnNew->_pvcnChild->_pvcnParent = pvcnTo; pvcnTo->_cChildren++;
if(NULL != pvcnTrav) { pvcnTemp = pvcnTrav->_pvcnSister; } else { pvcnTemp = pvcnTo->_pvcnChild; }
while(NULL != pvcnTemp->_pvcnSister) { pvcnTemp->_pvcnSister->_pvcnParent = pvcnTo; pvcnTo->_cChildren++; pvcnTemp = pvcnTemp->_pvcnSister; } } }
// All the VirtualCtrNodes and VirtualStmNodes under pvcnNew are now
// adjusted under the pvcnTo node. So delete the pvcnNew.
if(NULL != pvcnNew) { pvcnNew->_pvcnChild = NULL; pvcnNew->_pvsnStream = NULL;
delete pvcnNew; pvcnNew = NULL; }
// BUGBUG: How about filling up of _pstg / _pstm fieds for copied tree
// nodes? May be not required if somebody needs, these could be opened.
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::CopyVirtualDocFileTree, public
//
// Synopsis: Copies VirtualDocFileTree from old root to a new root with all
// its structure.
//
// Arguments: [pvcnOldTreeRoot] - Pointer to VirtualCtrNode to be moved
// [treeOpType] - OLD_STGSTM or NEW_STGSTM
// [ppvcnNewTreeRoot] - Pointer to VirtualCtrNode of new tree
//
// Returns: HRESULT
//
// History: Narindk 19-May-1996 Created
//
// Notes: In case of transaction mode, where it is just needed to keep
// a copy of virtualdocfile tree and no new IStroages/Istreams
// are in question, then the second parameter should be OLD_STGSTM
// However if say MoveTo/CopyTo where there would be new IStorages
// /IStreams, it should be given NEW_STGSTM.
//
// This function call CopyVirtualDFRoot to copy root VirtualCtr
// Node and calls CopyVirtualDFTree to copy rest of tree.
// - Call CopyVirtualDFRoot.
// - Call CopyGrowVirtualDFTree
// - If successful, assign root of new VirtualDF in *ppvcnRoot.
//---------------------------------------------------------------------------
HRESULT VirtualDF::CopyVirtualDocFileTree( VirtualCtrNode *pvcnOldTreeRoot, TREEOP treeOpType, VirtualCtrNode **ppvcnNewTreeRoot) { HRESULT hr = S_OK; VirtualCtrNode *pvcnTempNewTreeRoot = NULL;
DH_VDATEPTRIN(pvcnOldTreeRoot, VirtualCtrNode) ; DH_VDATEPTROUT(ppvcnNewTreeRoot, PVCTRNODE) ;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyVirtualDocFileTree")); DH_ASSERT(NULL != pvcnOldTreeRoot); DH_ASSERT(NULL != ppvcnNewTreeRoot);
if (S_OK == hr) { // Initialize out parameter
*ppvcnNewTreeRoot = NULL;
// Generates the root VirtualCtrNode for the VirtualDocFile tree.
hr = CopyVirtualDFRoot( pvcnOldTreeRoot, treeOpType, &pvcnTempNewTreeRoot);
DH_HRCHECK(hr, TEXT("CopyVirtualDFRoot")) ; }
if (S_OK == hr) { // Generate remaining new VirtualDF tree based on old VirtualDF tree.
hr = CopyGrowVirtualDFTree( pvcnOldTreeRoot, pvcnTempNewTreeRoot, treeOpType);
DH_HRCHECK(hr, TEXT("CopyGrowVirtualDFTree")) ; } // Fill the out parameter
if(S_OK == hr) { *ppvcnNewTreeRoot = pvcnTempNewTreeRoot; }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::CopyVirtualDFRoot, protected
//
// Synopsis: Creates the root VirtualCtrNode for the VirtualDocFile tree.
//
// Arguments: [pvcnRootOld] - Pointer to root of old VirtualDocFile tree
// [treeOpType] - OLD_STGSTM or NEW_STGSTM
// [ppvcnRootNew] - Pointer to pointer to new VirtualDF tree
//
// Returns: HRESULT
//
// History: Narindk 19-May-96 Created
//
// Notes: - Creates VirtualCtrNode object and initializes it with info
// based on corresponding old source VirtualDocFile root.
// - Calls CopyAppendVirtualStmNodesToVirtualCtrNode to append
// VirtualStmNodes to this VirtualCtrNode, if present in old
// source tree, so required to be copied.
// - Copies in memory CRC for this VirtualCtrNode _dwCRC from old
// source VirtualCtrNode.
// - if treeOpType is OLD_STGSTM, as would be in transaction tree
// copy procedure, when no new disk IStorages/IStreams are made,
// this assign's new VirtualCtrNode's _pstg to be old source
// VirtualCtrNode's _pstg.
//---------------------------------------------------------------------------
HRESULT VirtualDF::CopyVirtualDFRoot( VirtualCtrNode *pvcnRootOld, TREEOP treeOpType, VirtualCtrNode **ppvcnRootNew) { HRESULT hr = S_OK;
DH_VDATEPTRIN(pvcnRootOld, VirtualCtrNode) ; DH_VDATEPTROUT(ppvcnRootNew, PVCTRNODE) ;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyVirtualDFRoot"));
DH_ASSERT(NULL != pvcnRootOld); DH_ASSERT(NULL != ppvcnRootNew); // Generate VirtualCtrNode for the root node.
if(S_OK == hr) { // Initialize out parameter
*ppvcnRootNew = NULL;
*ppvcnRootNew = new VirtualCtrNode();
if (NULL == *ppvcnRootNew) { hr = E_OUTOFMEMORY; } }
if(S_OK == hr) { hr = (*ppvcnRootNew)->Init( pvcnRootOld->_ptszName, pvcnRootOld->_cChildren, pvcnRootOld->_cStreams);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ; }
if ((S_OK == hr) && (0 != (*ppvcnRootNew)->_cStreams)) { hr = CopyAppendVirtualStmNodesToVirtualCtrNode( (*ppvcnRootNew)->_cStreams, *ppvcnRootNew, pvcnRootOld, treeOpType);
DH_HRCHECK(hr, TEXT("CopyAppendVirtualStmNodesToVirtualCtrNode")) ; }
if(S_OK == hr) { (*ppvcnRootNew)->_dwCRC = pvcnRootOld->_dwCRC; if(OLD_STGSTM == treeOpType) { (*ppvcnRootNew)->_pstg = pvcnRootOld->_pstg; } }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::CopyGrowVirtualDFTree, protected
//
// Synopsis: Creates the ramaining VirtualDocFile tree.
//
// Arguments: [pvcnFrom] - Pointer to current node of original VirtualDocFile/// tree
// [pvcnTo] - Pointer to current VirtualCtrNode of copied Virtual
// DocFile tree
// [treeOpType] - OLD_STGSTM or NEW_STGSTM
//
// Returns: HRESULT
//
// History: Narindk 13-June-96 Created
//
// Notes: The copied VirtualDocFile tree is created based on corresponding
// original VirtualDocFile tree. This function is called either
// from the CopyGenerateVirtualDF function or may call itself
// recursively. The original VirtualDocFile tree is traversed from
// the top down, and based on its contents, a new VirtualDF tree
// is generated topdown.
//
// First assign the passed in pvcnFrom to pvcnCurrentChild and
// passed in pvcnTo to pvcnFisrtBorn variables.
// Loop till pvcnCurrentChild's _pvcnChild is non NULL & hr is S_OK
// - Call CopyAppendVirtualCtrNode to create a new node called
// pvcnNextBorn based on info from corresponding old pvcnCurrent-
// Child's _pvcnChild and append it to pvcnFirstBorn in the tree
// being generated by copy.
// - Assign pvcnCurrentChild's _pvcnChild to pvcnCurrentSister.
// - Loop till pvcnCurrentSister's _pvcnSister is non NULL
// - Call CopyAppendVirtualCtrNode to create a new node
// pvcnNextBornSister and append it to pvcnFirstBorn. Pl.
// note that append function would take care to append
// it to its older sister.
// - Assign pvcnCurrentSister's _pvcnSister to variable
// pvcnCurrentSister.
// - If pvcnCurrentSister's _pvcnChild is non NULL, then
// make a recursive call to self CopyGrowVirtualDFTree.
// - Reinitialize pvcnNextBornSister to NULL & go back to
// top of this inner loop and repeat.
// - Assign pvcnNextBorn to pvcnFirstBorn and reinitailize pvcn
// NextBorn to NULL.
// - Assign pvcnCurrentChild's _pvcnChild to pvcnCurrentChild.
// - Go to top of outer loop and repeat.
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
HRESULT VirtualDF::CopyGrowVirtualDFTree( VirtualCtrNode *pvcnFrom, VirtualCtrNode *pvcnTo, TREEOP treeOpType) { HRESULT hr = S_OK; VirtualCtrNode *pvcnFirstBorn = NULL; VirtualCtrNode *pvcnNextBorn = NULL; VirtualCtrNode *pvcnNextBornSister = NULL; VirtualCtrNode *pvcnCurrentSister = NULL; VirtualCtrNode *pvcnCurrentChild = NULL;
DH_VDATEPTRIN(pvcnFrom, VirtualCtrNode) ; DH_VDATEPTRIN(pvcnTo, VirtualCtrNode) ;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyGrowVirtualDFTree"));
DH_ASSERT(NULL != pvcnFrom); DH_ASSERT(NULL != pvcnTo);
if(S_OK == hr) { pvcnFirstBorn = pvcnTo; pvcnCurrentChild = pvcnFrom; }
while((NULL != pvcnCurrentChild->_pvcnChild) && (S_OK == hr)) { hr = CopyAppendVirtualCtrNode( pvcnFirstBorn, pvcnCurrentChild->_pvcnChild, treeOpType, &pvcnNextBorn); DH_HRCHECK(hr, TEXT("CopyAppendVirtualCtrNode")) ;
if(S_OK == hr) { pvcnCurrentSister = pvcnCurrentChild->_pvcnChild;
while((NULL != pvcnCurrentSister->_pvcnSister) && (S_OK == hr)) { hr = CopyAppendVirtualCtrNode( pvcnFirstBorn, pvcnCurrentSister->_pvcnSister, treeOpType, &pvcnNextBornSister);
DH_HRCHECK(hr, TEXT("CopyAppendVirtualCtrNode")) ;
pvcnCurrentSister = pvcnCurrentSister->_pvcnSister;
// Check if there are any children of this sister node, if
// yes, then make a recursive call to self.
if(NULL != pvcnCurrentSister->_pvcnChild) { hr = CopyGrowVirtualDFTree( pvcnCurrentSister, pvcnNextBornSister, treeOpType);
DH_HRCHECK(hr, TEXT("CopyGrowVirtualDFTree")); }
// Reinitialize the variables
pvcnNextBornSister = NULL; } } pvcnFirstBorn = pvcnNextBorn; pvcnNextBorn = NULL;
pvcnCurrentChild = pvcnCurrentChild->_pvcnChild; }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::CopyAppendVirtualCtrNode, protected
//
// Synopsis: Creates and appends VirtualCtrNode to VirtualDocFile tree
// being created.
//
// Arguments: [pvcnParent] - Parent VirtualCtrNode for the new VirtualCtrNode
// [pcnSource] - Corresponding VirtualCtrNode in old VirtualDF
// tree.
// [treeOpType] - OLD_STGSTM or NEW_STGSTM
// [ppvcnNew] - Pointer to pointer to new VirtualCtrNode to be
// created.
//
// Returns: HRESULT
//
// History: Narindk 20-May-96 Created
//
// Notes: - Creates VirtualCtrNode object ppvcnNew & initializes it with
// info based on corresponding old source pvcnSource node.
// - Appends this node to copy VirtualDF tree being generated.
// - Calls CopyAppendVirtualStmNodesToVirtualCtrNode to append
// VirtualStmNodes to this VirtualCtrNode, if present in old
// source tree, so required to be copied.
// - Copies in memory CRC for this VirtualCtrNode _dwCRC from old
// source VirtualCtrNode.
// - if treeOpType is OLD_STGSTM, as would be in transaction tree
// copy procedure, when no new disk IStorages/IStreams are made,
// this assign's new VirtualCtrNode's _pstg to be old source
// VirtualCtrNode's _pstg.
//---------------------------------------------------------------------------
HRESULT VirtualDF::CopyAppendVirtualCtrNode( VirtualCtrNode *pvcnParent, VirtualCtrNode *pvcnSource, TREEOP treeOpType, VirtualCtrNode **ppvcnNew) { HRESULT hr = S_OK; VirtualCtrNode *pvcnOldSister = NULL;
DH_VDATEPTROUT(ppvcnNew, PVCTRNODE) ; DH_VDATEPTRIN(pvcnParent, VirtualCtrNode) ; DH_VDATEPTRIN(pvcnSource, VirtualCtrNode) ;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyAppendChildVirtualCtrNode")); DH_ASSERT(NULL != pvcnParent); DH_ASSERT(NULL != ppvcnNew); DH_ASSERT(NULL != pvcnSource);
if(S_OK == hr) { *ppvcnNew = NULL;
// Allocate and Initialize new VirtualCtrNode
*ppvcnNew = new VirtualCtrNode(); if (NULL == *ppvcnNew) { hr = E_OUTOFMEMORY; } }
if(S_OK == hr) { hr = (*ppvcnNew)->Init( pvcnSource->_ptszName, pvcnSource->_cChildren, pvcnSource->_cStreams);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Init")) ; }
// Append new VirtualCtr Node
if(S_OK == hr) { if(NULL == pvcnParent->_pvcnChild) { hr = pvcnParent->AppendChildCtr(*ppvcnNew);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendChildCtr")) ; } else { pvcnOldSister = pvcnParent->_pvcnChild; while(NULL != pvcnOldSister->_pvcnSister) { pvcnOldSister = pvcnOldSister->_pvcnSister; }
hr = pvcnOldSister->AppendSisterCtr(*ppvcnNew);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendSisterCtr")) ; } } if ((S_OK == hr) && (0 != (*ppvcnNew)->_cStreams)) { hr = CopyAppendVirtualStmNodesToVirtualCtrNode( (*ppvcnNew)->_cStreams, *ppvcnNew, pvcnSource, treeOpType);
DH_HRCHECK(hr, TEXT("CopyAppendVirtualStmNodesToVirtualCtrNode")) ; }
if(S_OK == hr) { (*ppvcnNew)->_dwCRC = pvcnSource->_dwCRC;
if(OLD_STGSTM == treeOpType) { (*ppvcnNew)->_pstg = pvcnSource->_pstg; } }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::CopyAppendVirtualStmNodesToVirtualCtrNode, protected
//
// Synopsis: Creates and appends VirtualStmNode(s) to VirtualCtrNode
//
// Arguments: [cStreams] - Number of streams to be created
// [pvcn] - Pointer to VirtualCtrNode for which the streams
// need to be created and appended.
// [pvcnSource] - Pointer to correspoding VirtualCtrNode in
// old VirtualDF tree.
// [treeOpType] - OLD_STGSTM or NEW_STGSTM
//
// Returns: HRESULT
//
// History: Narindk 20-May-96 Created
//
// Notes: if number of streams to be created and appended to parent
// VirtualCtrNode pvcn is not zero, then loop till cStreams is
// not equal to zero.
// - First time in loop, assign pvsnSource from pvcnSource's
// _pvcsnStream, otherwise assign pvsnSource's _pvsnSister
// to pvsnSource with each traversal of loop.
// - Call CopyAppendVirtualStmNode to create a new VirtualStm
// Node and append it to parent VirtualCtrNode. Pl. note that
// this function would take care if the newly created node
// need to be appended to older VirtualStmNode sister.
// - Decrement cStreams and go back to top of loop & repeat.
//---------------------------------------------------------------------------
HRESULT VirtualDF::CopyAppendVirtualStmNodesToVirtualCtrNode( ULONG cStreams, VirtualCtrNode *pvcn, VirtualCtrNode *pvcnSource, TREEOP treeOpType) { HRESULT hr = S_OK; VirtualStmNode *pvsnSource = NULL;
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ; DH_VDATEPTRIN(pvcnSource, VirtualCtrNode) ;
DH_FUNCENTRY( &hr, DH_LVL_DFLIB, _TEXT("::CopyAppendVirtualStmNodesToVirtualCtrNode")); DH_ASSERT(0 != cStreams); DH_ASSERT(NULL != pvcn); DH_ASSERT(NULL != pvcnSource);
while((S_OK == hr) && (0 != cStreams)) { if(NULL == pvsnSource) { pvsnSource = pvcnSource->_pvsnStream; } else { pvsnSource = pvsnSource->_pvsnSister; }
DH_ASSERT(NULL != pvsnSource);
hr = CopyAppendVirtualStmNode( pvcn, pvsnSource, treeOpType);
DH_HRCHECK(hr, TEXT("CopyAppendFirstVirtualStmNode")) ;
cStreams--; } return hr; } //----------------------------------------------------------------------------
// Member: VirtualDF::CopyAppendVirtualStmNode, protected
//
// Synopsis: Creates and appends first VirtualStmNode to VirtualCtrNode
//
// Arguments: [pvcnParent] - Pointer to VirtualCtrNode for which the streams
// need to be created and appended.
// [pvsnSource] - Pointer to corresponding VirtualStmNode in old
// VirtualDF tree.
// [treeOpType] - OLD_STGSTM or NEW_STGSTM
//
// Returns: HRESULT
//
// History: Narindk 20-May-96 Created
//
// Notes: - Creates VirtualStmNode pvsnNew and initializes it with above
// info from pvsnSource
// - Appends this node to the parent VirtualCtrNode pvcnParent.
// - Copies in memory CRC for this VirtualStmNode's _dwCRC from old
// source pvsnSource.
// - if treeOpType is OLD_STGSTM, as would be in transaction tree
// copy procedure, when no new disk IStorages/IStreams are made,
// this assign's new VirtualStmNode's _pstm to be pvsnSource's
// _pstm
//---------------------------------------------------------------------------
HRESULT VirtualDF::CopyAppendVirtualStmNode( VirtualCtrNode *pvcnParent, VirtualStmNode *pvsnSource, TREEOP treeOpType) { HRESULT hr = S_OK; VirtualStmNode *pvsnNew = NULL; VirtualStmNode *pvsnOldSister = NULL; DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::CopyAppendFirstVirtualStmNode"));
DH_VDATEPTRIN(pvcnParent, VirtualCtrNode) ; DH_VDATEPTRIN(pvsnSource, VirtualStmNode) ; DH_ASSERT(NULL != pvcnParent); DH_ASSERT(NULL != pvsnSource);
if (S_OK == hr) { pvsnNew = new VirtualStmNode();
if (NULL == pvsnNew) { hr = E_OUTOFMEMORY; } } if(S_OK == hr) { hr = pvsnNew->Init(pvsnSource->_ptszName, pvsnSource->_cb);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Init")) ; }
if(S_OK == hr) { if(NULL == pvcnParent->_pvsnStream) { // Append it to parent storage
hr = pvcnParent->AppendFirstChildStm(pvsnNew);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::AppendFirstChildStm")) ; } else { pvsnOldSister = pvcnParent->_pvsnStream; while(NULL != pvsnOldSister->_pvsnSister) { pvsnOldSister = pvsnOldSister->_pvsnSister; }
// Append it to preceding sister stream
hr = pvsnOldSister->AppendSisterStm(pvsnNew);
DH_HRCHECK(hr, TEXT("VirtualStmNode::AppendSisterStm")) ; } }
if(S_OK == hr) { pvsnNew->_dwCRC.dwCRCName = pvsnSource->_dwCRC.dwCRCName; pvsnNew->_dwCRC.dwCRCData = pvsnSource->_dwCRC.dwCRCData; pvsnNew->_dwCRC.dwCRCSum = pvsnSource->_dwCRC.dwCRCSum;
if(OLD_STGSTM == treeOpType) { pvsnNew->_pstm = pvsnSource->_pstm; } }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::Associate, public
//
// Synopsis: Assocaies a VirtualDF tree with a VirtualCtrNode and its name.
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode to be associated with
// [pIStorage] - pointer to Disk IStorage to associate with
//
// Returns: HRESULT
//
// History: Narindk 6-June-96 Created
//
// Notes: This function is currently being used by GenerateVirtualDFFrom
// DiskDF in util.cxx.
//---------------------------------------------------------------------------
HRESULT VirtualDF::Associate( VirtualCtrNode *pvcn, LPSTORAGE pIStorage, ULONG ulSeed) { HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::Associate"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode); DH_VDATEPTRIN(pIStorage, IStorage);
DH_ASSERT(NULL != pvcn); DH_ASSERT(NULL != pIStorage);
// Associate name
if(S_OK == hr) { _ptszName = new TCHAR[_tcslen(pvcn->_ptszName)+1];
if (_ptszName == NULL) { hr = E_OUTOFMEMORY; } else { _tcscpy(_ptszName, pvcn->_ptszName); } }
// Associate given root IStorage with root VirtualCtrNode's _pstg and
// also Associate root of VirtualDF _pvcnRoot with the passed in root
// VirtualCtrNode.
if(S_OK == hr) { pvcn->_pstg = pIStorage; _pvcnRoot = pvcn; }
// Create the DataGens if we need to and if we can
// If ulSeed is UL_INVALIDSEED, caller is not interested.
if (UL_INVALIDSEED != ulSeed) { // We need a totally new set of datagens to prevent
// duplicate names. So Generate a new seed.
DG_INTEGER *pdgiNew = new DG_INTEGER (ulSeed); if (NULL != pdgiNew) { ULONG ulTmp = 0; if (DG_RC_SUCCESS == pdgiNew->Generate(&ulTmp, 0, 0xFFFFFFFF)) { ulSeed = ulTmp; } delete pdgiNew; } if (NULL == _pdgi) { _pdgi = new(NullOnFail) DG_INTEGER(ulSeed); } if (NULL == _pgdu) { _pgdu = new(NullOnFail) DG_STRING(ulSeed); } if (NULL == _pdgi || NULL == _pgdu) { hr = E_OUTOFMEMORY; } }
return hr; }
//----------------------------------------------------------------------------
// Member: VirtualDF::DeleteVirtualCtrNodeStreamNode, public
//
// Synopsis: Deletes the VirtualStmNode passed in under the given
// VirtualCtrNode.
//
// Arguments: [*pvcn]- Pointer to VirtualCtrNode for which VirtualStmNode
// need to be deleted.
// [*pvsn] - Pointer to VirtualStmNode to be deleted
//
// Returns: HRESULT
//
// History: Narindk 9-July-96 Created
//
// Notes: - Assign a temp variable pvsnTemp to point to _pvsnStream of
// passed in VirtualStmNode pvsn's _pvcnParent.
// - Delete the corresponding VirtualStmNode from VirtualCtrNode
// chain of VirtualStmNode and readjusts parent VirtualCtrNode
// /child VirtualStmNodes pointers and _cStreams count of the
// VirtualCtrNode.
// - In a loop, befor entering into which pvsnOldSister is
// set to NULL, find the passed in VirtualStmNode and
// break when found.
// - if VirtualStmNode to be deleted is first one in the
// VirtualStmNode chain of parent, then parent VirtualCtr
// Node's _pvsnStream ptr needs to be adjusted to point to
// "to be delted" VirtualStmNode's _pvsnSister.
// - If VirtualStmNode to be deleted is not first one in the
// VirtualStmNode chain, then its older sister is located
// and its _pvsnSister pointer is adjusted to "to be delted"
// VirtualStmNode's _pvsnSister.
// - Decrease the _cStreams count of the VirtualCtrNode parent
// - Delete the VirtualStmNode after setting its pointers to
// NULL.
//---------------------------------------------------------------------------
HRESULT VirtualDF::DeleteVirtualCtrNodeStreamNode(VirtualStmNode *pvsn) { HRESULT hr = S_OK; VirtualStmNode *pvsnTemp = NULL; VirtualStmNode *pvsnOldSister = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("::DeleteVirtualCtrNodeStreamNode"));
DH_VDATEPTRIN(pvsn, VirtualStmNode);
DH_ASSERT(NULL != pvsn); DH_ASSERT(NULL != pvsn->_pvcnParent);
if(S_OK == hr) { pvsnTemp = pvsn->_pvcnParent->_pvsnStream; pvsnOldSister = NULL;
// This locates the VirtualStmNode to be deleted and the
// nodes whose pointers may need to be readjusted.
while((pvsnTemp != pvsn) && (NULL != pvsnTemp->_pvsnSister)) { pvsnOldSister = pvsnTemp; pvsnTemp = pvsnTemp->_pvsnSister; }
DH_ASSERT(pvsnTemp == pvsn);
// Adjust the pointers
if(NULL == pvsnOldSister) { pvsn->_pvcnParent->_pvsnStream = pvsnTemp->_pvsnSister; } else { pvsnOldSister->_pvsnSister = pvsnTemp->_pvsnSister; }
// Decrease the stream count of the parent VirtualCtrNode parent.
pvsn->_pvcnParent->_cStreams--;
// Delete the node after NULLing its pointers.
pvsnTemp->_pvcnParent = NULL; pvsnTemp->_pvsnSister= NULL; delete pvsnTemp; pvsnTemp = NULL; }
return hr; }
|