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.
2627 lines
90 KiB
2627 lines
90 KiB
//+-------------------------------------------------------------------------
|
|
// 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;
|
|
}
|
|
|