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

1937 lines
54 KiB

//-------------------------------------------------------------------------
// Microsoft OLE
// Copyright (C) Microsoft Corporation, 1992 - 1996.
// All rights reserved.
//
// File: chancedf.cxx
//
// Contents: Implementation for ChanceDF object.
//
// Classes: ChanceDF
//
// Functions: ChanceDF (public)
// ~ChanceDF (public)
// CreateFromParams (public)
// CreateFromSize, multiple (public)
// CreateFromFile (public)
// Create (public)
// GetSeed (public)
// Generate (protected)
// GenerateRoot (protected)
// Init, multiple (public)
// ParseRange(protected)
// DeleteChanceDocFileTree (public)
// GetModes (public)
// AppendChildNode (protected)
// AppendSisterNode (protected)
// DeleteChanceDocFileSubTree (protected)
// GetDocFileNameFromCmdline (private)
// GetRandomChanceNode (protected)
// GetDepthOfNode (private)
//
// History: DeanE 12-Mar-96 Created
// Narindk 20-Apr-96 Added more functions, enhanced.
// BogdanT 30-Oct-96 Mac porting changes
//--------------------------------------------------------------------------
#include <dfheader.hxx>
#pragma hdrstop
// Debug object declaration
DH_DECLARE;
#define WSZ_DEF_VAL OLESTR("none")
//--------------------------------------------------------------------------
// Member: ChanceDF::ChanceDF, public
//
// Synopsis: Constructor. Initializes variables but real work is
// done in ::Create*() methods. This method cannot fail.
//
// Arguments: None.
//
// Returns: Nothing.
//
// History: DeanE 12-Mar-96 Created
//---------------------------------------------------------------------------
ChanceDF::ChanceDF() : _pdgi(NULL),
_pcnRoot(NULL),
_pcdfd(NULL),
_ptszName(NULL)
{
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF ctor"));
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::~ChanceDF, public
//
// Synopsis: Destructor. Frees memory and releases objects.
//
// Arguments: None.
//
// Returns: Nothing.
//
// History: DeanE 12-Mar-96 Created
//---------------------------------------------------------------------------
ChanceDF::~ChanceDF()
{
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF dtor"));
if(NULL != _pcdfd)
{
delete _pcdfd;
_pcdfd = NULL;
}
if(NULL != _pdgi)
{
delete _pdgi;
_pdgi = NULL;
}
if(NULL != _ptszName)
{
delete _ptszName;
_ptszName = NULL;
}
}
//--------------------------------------------------------------------------
// Member: ChanceDF::Init, public
//
// Synopsis: Initializes _pcdfd field in the ChanceDF object with default
// values
//
// Arguments:
//
//
// Returns: HRESULT
//
// History: t-leonr 26-Jul-97 Created
//
// Notes:
//
//---------------------------------------------------------------------------
HRESULT ChanceDF::Init()
{
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF::Init()"));
if (NULL == _pcdfd)
{
_pcdfd = new CDFD;
if (NULL == _pcdfd)
{
return(E_OUTOFMEMORY);
}
}
_pcdfd->cDepthMin = 0;
_pcdfd->cDepthMax = 2;
_pcdfd->cStgMin = 0;
_pcdfd->cStgMax = 3;
_pcdfd->cStmMin = 0;
_pcdfd->cStmMax = 5;
_pcdfd->cbStmMin = 0;
_pcdfd->cbStmMax = 5000;
_pcdfd->ulSeed = 0;
_pcdfd->dwRootMode = _pcdfd->dwStgMode = _pcdfd->dwStmMode =
STGM_READWRITE |
STGM_DIRECT |
STGM_SHARE_EXCLUSIVE;
return(S_OK);
}
//--------------------------------------------------------------------------
// Member: ChanceDF::Init, public
//
// Synopsis: Initializes the _pcdfd field in the ChanceDF object with the
// values passed in the pcdfd.
//
// Arguments: pcdfd
//
//
// Returns: HRESULT
//
// History: t-leonr 26-Jul-97 Created
//
// Notes:
//
//---------------------------------------------------------------------------
HRESULT ChanceDF::Init(CDFD *pcdfd)
{
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF::Init(pcdfd)"));
if (NULL == _pcdfd)
{
_pcdfd = new CDFD;
if (NULL == _pcdfd)
{
return(E_OUTOFMEMORY);
}
}
memcpy(_pcdfd, pcdfd, sizeof(CDFD));
return (S_OK);
}
//--------------------------------------------------------------------------
// Member: ChanceDF::CreateFromParams, public
//
// Synopsis: Creates the DocFile from the command line parameters.
//
// Arguments: [argc]
// [argv]
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
// Narindk 20-Apr-96 Enhanced
// t-leonr 27-Jul-97 Add stuff about Init()
//
// Notes:
// Precedence of switches in the event of conflicts:
// 1) /dfsize:tiny, huge, etc
// 2) /dftemp:<template file name>
// 3) /dfdepth:min-max /dfstg:min-max /dfstm:min-max
// /dfstmlen:min-max
// 4) /dfRootMode:<mode> /dfStgMode:<mode> /dfStmMode:<mode>
// 5) /dfname:name for Root DocFile
//
//---------------------------------------------------------------------------
HRESULT ChanceDF::CreateFromParams(int argc, char **argv, LPTSTR ptName)
{
HRESULT hr = E_FAIL;
int nErr;
LPTSTR ptszCmdSize = NULL;
LPTSTR ptszCmdDepth = NULL;
LPTSTR ptszCmdStg = NULL;
LPTSTR ptszCmdStm = NULL;
LPTSTR ptszCmdTemp = NULL;
LPTSTR ptszCmdStmLen = NULL;
LPTSTR ptszCmdName = NULL;
LPTSTR ptszCmdRootMode = NULL;
LPTSTR ptszCmdStgMode = NULL;
LPTSTR ptszCmdStmMode = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::CreateFromParams"));
if (NULL == _pcdfd)
{
hr = Init();
DH_HRCHECK(hr, TEXT("ChanceDF::Init()"));
if (FAILED(hr))
{
return hr;
}
}
CBaseCmdlineObj cmdOpenDF(OLESTR("Distrib"), OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj cmdSize (OLESTR("dfsize"), OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj cmdDepth (OLESTR("dfdepth"), OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj cmdStg (OLESTR("dfstg"), OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj cmdStm (OLESTR("dfstm"), OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj cmdStmLen(OLESTR("dfstmlen"),OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj cmdTemp (OLESTR("dftemp"), OLESTR(""), WSZ_DEF_VAL);
CUlongCmdlineObj cmdSeed (OLESTR("seed"), OLESTR(""), _TEXTN("0"));
CBaseCmdlineObj cmdName (OLESTR("dfname"), OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj cmdRootMode (OLESTR("dfRootMode"), OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj cmdStgMode (OLESTR("dfStgMode"), OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj cmdStmMode (OLESTR("dfStmMode"), OLESTR(""), WSZ_DEF_VAL);
CBaseCmdlineObj *aAllArgs[] = {
&cmdOpenDF,
&cmdSize,
&cmdDepth,
&cmdStg,
&cmdStm,
&cmdStmLen,
&cmdTemp,
&cmdSeed,
&cmdName,
&cmdRootMode,
&cmdStgMode,
&cmdStmMode
};
CCmdline cmdline(argc, argv);
nErr = cmdline.QueryError();
if (CMDLINE_NO_ERROR != nErr)
{
DH_TRACE((DH_LVL_ERROR,_TEXT("CCmdline creation error = %d"),nErr));
goto CleanUpExit;
}
// Parse the actual arguments
// ignore any extra parameters; last param==FALSE will
// do this
//
nErr = cmdline.Parse(aAllArgs,
sizeof(aAllArgs)/sizeof(CBaseCmdlineObj *),
FALSE);
if (CMDLINE_NO_ERROR != nErr)
{
DH_TRACE((DH_LVL_ERROR,
_TEXT("Command line parsing error = %d"),
nErr));
goto CleanUpExit;
}
// Initialize the seed value first - we'll always have a value
// for this
//
if (0 != *cmdSeed.GetValue())
{
// only set seed from cmdline if it has not been put
// into the cdfd earlier. (permits repro with new testdriver)
if (0 == _pcdfd->ulSeed || -1 == _pcdfd->ulSeed)
{
_pcdfd->ulSeed = *cmdSeed.GetValue();
}
}
// Next, hunt for arguments we actually got
// Are we creating our docfile to test?
_uOpenCreateDF = FL_DISTRIB_NONE;
if (TRUE == cmdOpenDF.IsFound ())
{
LPTSTR ptszCmdOpen;
//Convert OLECHAR to TCHAR
hr = OleStringToTString (cmdOpenDF.GetValue (), &ptszCmdOpen);
DH_HRCHECK (hr, TEXT("OleStringToTString"));
if (S_OK == hr)
{
if (NULL == _tcsicmp (ptszCmdOpen, TEXT(SZ_DISTRIB_OPEN)) ||
NULL == _tcsicmp (ptszCmdOpen, TEXT(SZ_DISTRIB_OPENNODELETE)))
{
_uOpenCreateDF = FL_DISTRIB_OPEN;
}
else if (NULL == _tcsicmp (ptszCmdOpen, TEXT(SZ_DISTRIB_CREATE)))
{
_uOpenCreateDF = FL_DISTRIB_CREATE;
}
}
delete ptszCmdOpen;
ptszCmdOpen = 0;
}
// Initialize the mode values
if(0 != olestrcmp(cmdRootMode.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdRootMode.GetValue())
{
//Convert OLECHAR to TCHAR
hr = OleStringToTString(cmdRootMode.GetValue(), &ptszCmdRootMode);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
if(S_OK == hr)
{
hr = GetModes(&(_pcdfd->dwRootMode), ptszCmdRootMode);
DH_HRCHECK(hr, TEXT("GetModes - dwRootMode")) ;
}
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
if(0 != olestrcmp(cmdStgMode.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdStgMode.GetValue())
{
//Convert OLECHAR to TCHAR
hr = OleStringToTString(cmdStgMode.GetValue(), &ptszCmdStgMode);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
if(S_OK == hr)
{
hr = GetModes(&(_pcdfd->dwStgMode), ptszCmdStgMode);
DH_HRCHECK(hr, TEXT("GetModes - dwStgMode")) ;
}
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
if(0 != olestrcmp(cmdStmMode.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdStmMode.GetValue())
{
//Convert OLECHAR to TCHAR
hr = OleStringToTString(cmdStmMode.GetValue(), &ptszCmdStmMode);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
if(S_OK == hr)
{
hr = GetModes(&(_pcdfd->dwStmMode), ptszCmdStmMode);
DH_HRCHECK(hr, TEXT("GetModes - dwStmMode")) ;
}
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
// Initialize the name value
if(0 != olestrcmp(cmdName.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdName.GetValue())
{
//Convert OLECHAR to TCHAR
hr = OleStringToTString(cmdName.GetValue(), &ptszCmdName);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
// if nothing on cmdline, put in what was given to us
if (NULL != ptName && NULL == ptszCmdName)
{
ptszCmdName = new TCHAR[_tcslen (ptName) + 1];
if (NULL != ptszCmdName)
{
_tcscpy (ptszCmdName, ptName);
}
}
// Check if dfsize or dftemp given on command line - the call appropriate
// functions
if(0 != olestrcmp(cmdSize.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdSize.GetValue())
{
hr = OleStringToTString(cmdSize.GetValue(), &ptszCmdSize);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
if(S_OK == hr)
{
hr = CreateFromSize(
ptszCmdSize,
_pcdfd->ulSeed,
_pcdfd->dwRootMode, // non existing values
_pcdfd->dwStgMode, // for seed and modes
_pcdfd->dwStmMode,
ptszCmdName);
goto CleanUpExit;
}
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
else
if(0 != olestrcmp(cmdTemp.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdTemp.GetValue())
{
//Convert OLECHAR to TCHAR
hr = OleStringToTString(cmdTemp.GetValue(), &ptszCmdTemp);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
if(S_OK == hr)
{
hr = CreateFromFile(ptszCmdTemp, _pcdfd->ulSeed);
goto CleanUpExit;
}
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
// If a size or template file were not specified, we'll need to
// hunt for specific values on the command line, using defaults
// for any we don't get
//
if(0 != olestrcmp(cmdDepth.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdDepth.GetValue())
{
//Convert OLECHAR to TCHAR
hr = OleStringToTString(cmdDepth.GetValue(), &ptszCmdDepth);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
if(S_OK == hr)
{
hr = ParseRange(ptszCmdDepth, &(_pcdfd->cDepthMin), &(_pcdfd->cDepthMax));
DH_HRCHECK(hr, TEXT("ParseRange - cmdDepth")) ;
}
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
if(0 != olestrcmp(cmdStg.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdStg.GetValue())
{
//Convert OLECHAR to TCHAR
hr = OleStringToTString(cmdStg.GetValue(), &ptszCmdStg);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
if(S_OK == hr)
{
hr = ParseRange(ptszCmdStg, &(_pcdfd->cStgMin), &(_pcdfd->cStgMax));
DH_HRCHECK(hr, TEXT("ParseRange - cmdStg")) ;
}
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
if(0 != olestrcmp(cmdStm.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdStm.GetValue())
{
//Convert OLECHAR to TCHAR
hr = OleStringToTString(cmdStm.GetValue(), &ptszCmdStm);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
if(S_OK == hr)
{
hr = ParseRange(ptszCmdStm, &(_pcdfd->cStmMin), &(_pcdfd->cStmMax));
DH_HRCHECK(hr, TEXT("ParseRange - cmdStm")) ;
}
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
if(0 != olestrcmp(cmdStmLen.GetValue(), WSZ_DEF_VAL))
{
if(NULL != *cmdStmLen.GetValue())
{
//Convert OLECHAR to TCHAR
hr = OleStringToTString(cmdStmLen.GetValue(), &ptszCmdStmLen);
DH_HRCHECK(hr, TEXT("WStrToTStr")) ;
if(S_OK == hr)
{
hr = ParseRange(ptszCmdStmLen, &(_pcdfd->cbStmMin), &(_pcdfd->cbStmMax));
DH_HRCHECK(hr, TEXT("ParseRange - cmdStmLen")) ;
}
}
if (FAILED(hr))
{
goto CleanUpExit;
}
}
hr = Create(NULL, ptszCmdName);
DH_HRCHECK(hr, TEXT("Create")) ;
CleanUpExit:
// Clean up
if(NULL != ptszCmdSize)
{
delete ptszCmdSize;
ptszCmdSize =NULL;
}
if(NULL != ptszCmdDepth)
{
delete ptszCmdDepth;
ptszCmdDepth =NULL;
}
if(NULL != ptszCmdStg)
{
delete ptszCmdStg;
ptszCmdStg =NULL;
}
if(NULL != ptszCmdStm)
{
delete ptszCmdStm;
ptszCmdStm =NULL;
}
if(NULL != ptszCmdStmLen)
{
delete ptszCmdStmLen;
ptszCmdStmLen =NULL;
}
if(NULL != ptszCmdName)
{
delete ptszCmdName;
ptszCmdName =NULL;
}
if(NULL != ptszCmdRootMode)
{
delete ptszCmdRootMode;
ptszCmdRootMode =NULL;
}
if(NULL != ptszCmdStgMode)
{
delete ptszCmdStgMode;
ptszCmdStgMode =NULL;
}
if(NULL != ptszCmdStmMode)
{
delete ptszCmdStmMode;
ptszCmdStmMode =NULL;
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::CreateFromSize, public
//
// Synopsis: Creates the DocFile from size option
//
// Arguments: [tszSize] - Size of DocFile. Must be given.
// [ulSeed] - Seed value.
// [dwRootMode] - Mode for Root Storage.
// [dwStgMode] - Mode for IStorage(s).
// [dwStmMode] - Mode for IStream(s).
// [ptszDocName] - Name of DocFile.
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
// Narindk 2-July-96 Enhanced
//
// Notes: If the value for dwRootMode/dwStgMode/dwStmMode are not given
// i.e. zero, then default values for the modes would be used.
// If ptszDocName is NULL, then a random name is chosen for Doc
// File in VirtualDF creation.
//---------------------------------------------------------------------------
HRESULT ChanceDF::CreateFromSize(
LPCTSTR tszSize,
ULONG ulSeed,
DWORD dwRootMode,
DWORD dwStgMode,
DWORD dwStmMode,
LPTSTR ptszDocName)
{
DFSIZE dfs = DF_ERROR;
DH_FUNCENTRY(NULL,
DH_LVL_DFLIB,
_TEXT("ChanceDF::CreateFromSize - string"));
DH_ASSERT(NULL != tszSize);
if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_TINY))
{
dfs = DF_TINY;
}
else
if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_SMALL))
{
dfs = DF_SMALL;
}
else
if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_MEDIUM))
{
dfs = DF_MEDIUM;
}
else
if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_LARGE))
{
dfs = DF_LARGE;
}
else
if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_HUGE))
{
dfs = DF_HUGE;
}
else
if (0 == _tcsicmp(tszSize, TSZ_DFSIZE_DIF))
{
dfs = DF_DIF;
}
if (DF_ERROR == dfs)
{
return(E_FAIL);
}
return(CreateFromSize(
dfs,
ulSeed,
dwRootMode,
dwStgMode,
dwStmMode,
ptszDocName));
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::CreateFromSize, public
//
// Synopsis: Creates DocFile from size option.
//
// Arguments: [dfs] - DocFile size.
// [ulSeed] - Seed value.
// [dwRootMode] - Mode for Root Storage.
// [dwStgMode] - Mode for IStorage(s).
// [dwStmMode] - Mode for IStream(s).
// [ptszDocName] - Name of DocFile.
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
// Narindk 20-Apr-96 Enhanced
// t-leonr 27-Jul-97 Add stuff about Init(), use _pcdfd
//
// Notes: If the value for dwRootMode/dwStgMode/dwStmMode are not given
// i.e. zero, then default values for the modes would be used.
// If ptszDocName is NULL, then a random name is chosen for Doc
// File in VirtualDF creation.
//---------------------------------------------------------------------------
HRESULT ChanceDF::CreateFromSize(
DFSIZE dfs,
ULONG ulSeed,
DWORD dwRootMode,
DWORD dwStgMode,
DWORD dwStmMode,
LPTSTR ptszDocName)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr,
DH_LVL_DFLIB,
_TEXT("ChanceDF::CreateFromSize - dfs"));
if (NULL == _pcdfd)
{
hr = Init();
DH_HRCHECK(hr, TEXT("ChanceDF::Init()"));
if (FAILED(hr))
{
return hr;
}
}
_pcdfd->ulSeed = ulSeed;
if(0 == dwRootMode)
{
_pcdfd->dwRootMode = STGM_READWRITE |
STGM_DIRECT |
STGM_SHARE_EXCLUSIVE;
}
else
{
_pcdfd->dwRootMode = dwRootMode;
}
if(0 == dwStgMode)
{
_pcdfd->dwStgMode = STGM_READWRITE |
STGM_DIRECT |
STGM_SHARE_EXCLUSIVE;
}
else
{
_pcdfd->dwStgMode = dwStgMode;
}
if(0 == dwStmMode)
{
_pcdfd->dwStmMode = STGM_READWRITE |
STGM_DIRECT |
STGM_SHARE_EXCLUSIVE;
}
else
{
_pcdfd->dwStmMode = dwStmMode;
}
switch (dfs)
{
case DF_TINY:
_pcdfd->cDepthMin = 0;
_pcdfd->cDepthMax = 0;
_pcdfd->cStgMin = 0;
_pcdfd->cStgMax = 0;
_pcdfd->cStmMin = 0;
_pcdfd->cStmMax = 3;
_pcdfd->cbStmMin = 0;
_pcdfd->cbStmMax = 100;
break;
case DF_SMALL:
_pcdfd->cDepthMin = 0;
_pcdfd->cDepthMax = 1;
_pcdfd->cStgMin = 0;
_pcdfd->cStgMax = 1;
_pcdfd->cStmMin = 0;
_pcdfd->cStmMax = 5;
_pcdfd->cbStmMin = 0;
_pcdfd->cbStmMax = 4000;
break;
case DF_MEDIUM:
_pcdfd->cDepthMin = 1;
_pcdfd->cDepthMax = 3;
_pcdfd->cStgMin = 1;
_pcdfd->cStgMax = 4;
_pcdfd->cStmMin = 1;
_pcdfd->cStmMax = 6;
_pcdfd->cbStmMin = 0;
_pcdfd->cbStmMax = 10240;
break;
case DF_LARGE:
_pcdfd->cDepthMin = 2;
_pcdfd->cDepthMax = 5;
_pcdfd->cStgMin = 2;
_pcdfd->cStgMax = 10;
_pcdfd->cStmMin = 0;
_pcdfd->cStmMax = 8;
_pcdfd->cbStmMin = 0;
_pcdfd->cbStmMax = 20480;
break;
case DF_HUGE:
_pcdfd->cDepthMin = 5;
_pcdfd->cDepthMax = 10;
_pcdfd->cStgMin = 5;
_pcdfd->cStgMax = 30;
_pcdfd->cStmMin = 0;
_pcdfd->cStmMax = 10;
_pcdfd->cbStmMin = 0;
_pcdfd->cbStmMax = 40000;
break;
case DF_DIF:
_pcdfd->cDepthMin = 5;
_pcdfd->cDepthMax = 10;
_pcdfd->cStgMin = 7;
_pcdfd->cStgMax = 10;
_pcdfd->cStmMin = 10;
_pcdfd->cStmMax = 15;
_pcdfd->cbStmMin = 100000;
_pcdfd->cbStmMax = 150000;
break;
case DF_ERROR: // Fall through to error condition
default:
hr = E_FAIL;
break;
}
if (SUCCEEDED(hr))
{
hr = Create(NULL, ptszDocName);
DH_HRCHECK(hr, TEXT("Create")) ;
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::CreateFromFile, public
//
// Synopsis: Creates DocFile through a given ini file.
//
// Arguments: [tszIni]
// [ulSeed]
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
//---------------------------------------------------------------------------
HRESULT ChanceDF::CreateFromFile(
LPCTSTR /* UNREF tszIni */,
ULONG /* UNREF ulSeed */)
{
DH_FUNCENTRY(NULL,
DH_LVL_DFLIB,
_TEXT("ChanceDF::CreateFromFile - NYI!"));
DH_ASSERT(!_TEXT("::CreateFromFile NYI!"));
return(E_FAIL);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::Create, public
//
// Synopsis: Creates the ChanceDocFile tree.
//
// Arguments: [pcdfd] - pointer to CDFD structure.
// [ptszDocName] - Name for DocFile. May be NULL.
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
// t-leonr 27-Jul-97 Add stuff about Init()
//
// Notes: Destructor will clean up a partially-created object so we
// don't have to do a bunch of cleanup as we go
//
// If ptszDocName is NULL, then a random name is chosen for Doc
// File in VirtualDF creation.
//---------------------------------------------------------------------------
HRESULT ChanceDF::Create(CDFD *pcdfd, LPTSTR ptszDocName)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::Create"));
if (NULL != pcdfd)
{
hr = Init(pcdfd);
DH_HRCHECK(hr, TEXT("ChanceDF::Init(pcdfd)"));
}
else if (NULL == _pcdfd)
{
hr = Init();
DH_HRCHECK(hr, TEXT("ChanceDF::Init()"));
}
if (FAILED(hr))
{
return hr;
}
// Create a DataGen object that will allow us to fill the count
// parameters of all the ChanceDF components
//
_pdgi = new DG_INTEGER(_pcdfd->ulSeed);
if (NULL == _pdgi)
{
return(E_OUTOFMEMORY);
}
// Store the actual seed value we used to create this tree - we'll
// need it to initialize other DG objects later
//
_pdgi->GetSeed(&_pcdfd->ulSeed);
// Report the Seed value so this structure can be recreated
DH_LOG((LOG_INFO, _TEXT("ChanceDF::Create - Seed=%lu"), _pcdfd->ulSeed));
// Finally, we must generate the ChanceDF tree
hr = Generate();
DH_HRCHECK(hr, TEXT("Generate")) ;
//Store the name of docfile, if provided by user.
if((S_OK == hr) && (NULL != ptszDocName))
{
hr = GetDocFileNameFromCmdline(ptszDocName);
DH_HRCHECK(hr, TEXT("GetDocFileNameFromCmdline")) ;
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::ParseRange, public
//
// Synopsis: Parses the range given from command line for different params.
//
// Arguments: [tszSwitch]
// [pulMin]
// [pulMax]
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
// Narindk 20-Apr-96 Enhanced
//
// Notes: tszSwitch is of the format '/switch:min-max
//---------------------------------------------------------------------------
HRESULT ChanceDF::ParseRange(LPCTSTR tszSwitch, ULONG *pulMin, ULONG *pulMax)
{
HRESULT hr = E_FAIL;
LPCTSTR ptszMin = tszSwitch;
LPCTSTR ptszMax = tszSwitch;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::ParseRange"));
DH_ASSERT(NULL != tszSwitch);
DH_ASSERT(NULL != pulMin);
DH_ASSERT(NULL != pulMax);
// Advance the maximum pointer past the dash delimeter after
// the minimum value
//
ptszMax = ptszMin;
while ((*ptszMax != L'\0') && (*ptszMax++ != L'-'))
{
;
}
// If neither of our pointers is pointing at the null
// terminator, we can safely get the values
//
if ((L'\0' != *ptszMin) && (L'\0' != *ptszMax))
{
*pulMin = _ttol(ptszMin);
*pulMax = _ttol(ptszMax);
if (*pulMin <= *pulMax)
{
hr = S_OK;
}
}
return (hr);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::Generate, protected
//
// Synopsis: Generates the ChanceDocFile tree consisting of ChanceNodes.
//
// Arguments: void
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
// Narindk 20-Apr-96 Enhanced
// Notes:
// Check the creation parameters
// Generate the first child node at each level
// Choose children nodes randomly to create additional siblings,
// or children, if necessary. In growing the chance docfile tree,
// take care not to make sister of root node and do not increase
// depth of the tree by making child of nodes at max depth.
//
// Called privately by public creation methods
//
//---------------------------------------------------------------------------
HRESULT ChanceDF::Generate()
{
HRESULT hr = E_FAIL;
ULONG cDepth = 0;
ULONG cRemStg = 0;
USHORT usErr = 0;
ChanceNode **apcnFirstBorn = NULL;
ChanceNode *pcnRemStg = NULL;
ULONG ulLoop;
ChanceNode *pcnOldNode = NULL;
UINT cTypeNode = 0;
ULONG cNumOfNodes = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::Generate"));
// Sanity check parameters
// minimums for each category must be <= maximums
// must have at least as many storages as the minimum depth
// must have at least as many storages as the maximum depth
//
if ((_pcdfd->cDepthMin > _pcdfd->cDepthMax) ||
(_pcdfd->cStgMin > _pcdfd->cStgMax) ||
(_pcdfd->cStmMin > _pcdfd->cStmMax) ||
(_pcdfd->cbStmMin > _pcdfd->cbStmMax) ||
(_pcdfd->cDepthMin > _pcdfd->cStgMin) ||
(_pcdfd->cDepthMax > _pcdfd->cStgMax))
{
goto ErrExit;
}
// Determine the exact depth of the docfile
//
usErr = _pdgi->Generate(&cDepth, _pcdfd->cDepthMin, _pcdfd->cDepthMax);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
goto ErrExit;
}
// Adjust minimum and maximum number of storages to create down
// by the number that would be created by cDepth.
//
_pcdfd->cStgMin = max(0, (LONG)(_pcdfd->cStgMin-cDepth));
_pcdfd->cStgMax = max(0, (LONG)(_pcdfd->cStgMax-cDepth));
// Calculate the number of extra storages to create
//
usErr = _pdgi->Generate(&cRemStg, _pcdfd->cStgMin, _pcdfd->cStgMax);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
goto ErrExit;
}
// Check if cDepth is zero, but cRemStg is >0, then make cDepth atleast 1,
// becoz' we wouldn't have siblings of root.
cDepth = ((cDepth == 0 && cRemStg > 0) ? 1 : cDepth);
// Allocate a table of pointers to the first children at each
// level
//
apcnFirstBorn = new ChanceNode*[cDepth+1];
if (NULL == apcnFirstBorn)
{
hr = E_OUTOFMEMORY;
goto ErrExit;
}
// Create root node - if this succeeds, we point our root
// to it and if any subsequent errors occur while building the
// rest of the tree the destructor will clean it up
//
hr = GenerateRoot();
DH_HRCHECK(hr, TEXT("GenerateRoot")) ;
if (FAILED(hr))
{
goto ErrExit;
}
apcnFirstBorn[0] = _pcnRoot;
// Create levels of children nodes
//
hr = S_OK;
ulLoop = 1;
while ((ulLoop<=cDepth) && SUCCEEDED(hr))
{
hr = AppendChildNode(&apcnFirstBorn[ulLoop], apcnFirstBorn[ulLoop-1]);
DH_HRCHECK(hr, TEXT("AppendChildNode")) ;
ulLoop++;
}
if (FAILED(hr))
{
goto ErrExit;
}
// Now, fill in any remaining storage nodes that we need to
//
cNumOfNodes = ulLoop;
ulLoop = 0;
while ((ulLoop<cRemStg) && SUCCEEDED(hr))
{
usErr = _pdgi->Generate(&cTypeNode, SISTERNODE, CHILDNODE);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
if(S_OK == hr)
{
hr = GetRandomChanceNode(cNumOfNodes, &pcnOldNode);
DH_HRCHECK(hr, TEXT("FindRandomChanceNode")) ;
}
if (SUCCEEDED(hr))
{
// In growing the chance docfile tree, take care not to make
// sister of root node and do not increase max depth of the tree
// by making child of nodes at max depth.
if((SISTERNODE == cTypeNode) && (_pcnRoot != pcnOldNode))
{
hr = AppendSisterNode(&pcnRemStg, pcnOldNode);
DH_HRCHECK(hr, TEXT("AppendSisterNode")) ;
}
else
{
// Both conditons CHILDNODE == cTypeNode and
// ((SISTERNODE == cTypeNode) && (_pcnRoot == pcnOldNode))
// handled here
if(NULL == pcnOldNode->_pcnChild)
{
if(GetDepthOfNode(pcnOldNode) < cDepth)
{
hr = AppendChildNode(&pcnRemStg, pcnOldNode);
DH_HRCHECK(hr, TEXT("AppendChildNode")) ;
}
else
{
hr = AppendSisterNode(&pcnRemStg, pcnOldNode);
DH_HRCHECK(hr, TEXT("AppendSisterNode")) ;
}
}
else
{
hr = AppendSisterNode(&pcnRemStg,pcnOldNode->_pcnChild);
DH_HRCHECK(hr, TEXT("AppendSisterNode")) ;
}
}
}
ulLoop++;
cNumOfNodes++;
}
ErrExit:
// All nodes are saved in the tree itself pointed to by _pcnRoot, and
// we can safely delete this temporary scaffolding
//
delete []apcnFirstBorn;
return(hr);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::GenerateRoot, protected
//
// Synopsis: Generates the root of ChanceDocFile tree.
//
// Arguments: void
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
// Narindk 20-Apr-96 Enhanced
//---------------------------------------------------------------------------
HRESULT ChanceDF::GenerateRoot()
{
USHORT usErr;
ULONG cStreams;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("GenerateRoot"));
// Generate the number of streams the root will have
usErr = _pdgi->Generate(&cStreams, _pcdfd->cStmMin, _pcdfd->cStmMax);
if (DG_RC_SUCCESS != usErr)
{
return(E_FAIL);
}
_pcnRoot = new ChanceNode(0, cStreams, _pcdfd->cbStmMin, _pcdfd->cbStmMax);
if (NULL == _pcnRoot)
{
return(E_OUTOFMEMORY);
}
return(S_OK);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::AppendChildNode, protected
//
// Synopsis: Appends the Child node to parent.
//
// Arguments: [ppcnNew]
// [pcnParent]
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
// Narindk 20-Apr-96 Enhanced
//
// Notes: Attach new node as a child of the parent node at the end of the
// end of parents child chain. If the parent is NULL, do nothing
// with this node.
//
//---------------------------------------------------------------------------
HRESULT ChanceDF::AppendChildNode(ChanceNode **ppcnNew, ChanceNode *pcnParent)
{
HRESULT hr = E_FAIL;
ULONG cStreams= 0;
USHORT usErr = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("AppendChildNode"));
DH_ASSERT(NULL != pcnParent)
DH_ASSERT(NULL != ppcnNew);
*ppcnNew = NULL;
// Determine number of streams to create
usErr = _pdgi->Generate(&cStreams, _pcdfd->cStmMin, _pcdfd->cStmMax);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
goto ErrExit;
}
// Allocate and initialize the new node
*ppcnNew = new ChanceNode(0, cStreams, _pcdfd->cbStmMin, _pcdfd->cbStmMax);
if (NULL == *ppcnNew)
{
hr = E_OUTOFMEMORY;
goto ErrExit;
}
// Append the new node to the list of sisters in the parent
//
hr = pcnParent->AppendChildStorage(*ppcnNew);
DH_HRCHECK(hr, TEXT("AppendChildStorage")) ;
ErrExit:
if (FAILED(hr))
{
delete *ppcnNew;
*ppcnNew = NULL;
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::AppendSisterNode, protected
//
// Synopsis: Appends the new node as sister of ChanceNode.
//
// Arguments: [ppcnNew]
// [pcnSister]
//
// Returns: HRESULT
//
// History: DeanE 12-Mar-96 Created
// Narindk 20-Apr-96 Enhanced
//---------------------------------------------------------------------------
HRESULT ChanceDF::AppendSisterNode(
ChanceNode **ppcnNew,
ChanceNode *pcnSister)
{
HRESULT hr = E_FAIL;
ULONG cStreams= 0;
USHORT usErr = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("AppendSisterNode"));
DH_ASSERT(NULL != pcnSister)
DH_ASSERT(NULL != ppcnNew);
*ppcnNew = NULL;
// Determine number of streams to create
usErr = _pdgi->Generate(&cStreams, _pcdfd->cStmMin, _pcdfd->cStmMax);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
goto ErrExit;
}
// Allocate and initialize the new node
*ppcnNew = new ChanceNode(0, cStreams, _pcdfd->cbStmMin, _pcdfd->cbStmMax);
if (NULL == *ppcnNew)
{
hr = E_OUTOFMEMORY;
goto ErrExit;
}
// Append the new node to the list of sisters in the parent
//
hr = pcnSister->AppendSisterStorage(*ppcnNew);
DH_HRCHECK(hr, TEXT("AppendSisterStorage")) ;
ErrExit:
if (FAILED(hr))
{
delete *ppcnNew;
*ppcnNew = NULL;
}
return(hr);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::GetSeed, public
//
// Synopsis: Returns the seed value
//
// Arguments: void
//
// Returns: ULONG
//
// History: DeanE 12-Mar-96 Created
//---------------------------------------------------------------------------
ULONG ChanceDF::GetSeed()
{
ULONG ulSeed = 0;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("GetSeed"));
if (NULL != _pdgi)
{
_pdgi->GetSeed(&ulSeed);
}
return(ulSeed);
}
//+--------------------------------------------------------------------------
// Member: ChanceDF::DeleteChanceDocFileTree, public
//
// Synopsis: Deletes the ChanceDocFile tree
//
// Arguments: [pcnTrav] - Pointer to ChanceNode
//
// 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
// DeleteChanceDocFileSubTree to delete the subtree. In case,
// the complete tree needs to be deleted, we call the function
// DeleteChanceDocFileSubTree directly to delete the complete
// tree.
//---------------------------------------------------------------------------
HRESULT ChanceDF::DeleteChanceDocFileTree(ChanceNode *pcnTrav)
{
HRESULT hr = S_OK;
ChanceNode *pTempNode = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("DeleteChanceDocFileTree"));
DH_VDATEPTRIN(pcnTrav, ChanceNode);
DH_ASSERT(NULL != pcnTrav);
if(S_OK == hr)
{
// This basically readjusts the tree, in case some other node except
// for root of ChanceDocFile tree is passed, so only a part of tree is
// getting deleted.
if(NULL != pcnTrav->_pcnParent)
{
// Find its previous node whose pointers would need readjustment.
pTempNode = pcnTrav->_pcnParent->_pcnChild;
while ((pcnTrav != pcnTrav->_pcnParent->_pcnChild) &&
(pcnTrav != pTempNode->_pcnSister))
{
pTempNode = pTempNode->_pcnSister;
DH_ASSERT(NULL != pTempNode);
}
// Readjust the child pointer or sister pointer as the case may be.
pcnTrav->_pcnParent->_pcnChild = (pcnTrav == pTempNode) ?
pcnTrav->_pcnSister : pcnTrav->_pcnParent->_pcnChild;
pTempNode->_pcnSister = pcnTrav->_pcnSister;
}
}
if(S_OK == hr)
{
// Call the function to delete the tree now.
hr = DeleteChanceDocFileSubTree(&pcnTrav);
DH_HRCHECK(hr, TEXT("DeleteChanceDocFileSubTree")) ;
}
return hr;
}
//--------------------------------------------------------------------------
// Member: ChanceDF::DeleteChanceDocFileSubTree, protected
//
// Synopsis: Does the real work of deletion of ChanceNodes in the tree.
//
// Arguments: [ppcnTrav] - Pointer to pointer to ChanceNode
//
// Returns: HRESULT
//
// History: Narindk 24-Apr-96 Created
//
// Notes: This function is called only through DeleteChanceDocFileTree.
//
// Assign the passed in ChanceNode to a variable pTempRoot.
// NULL the pTempRoot's parent.
// Loop till the pTempRoot is not NULL to delete tree ieratively.
// - Assign pTempRoot to a temp variable pTempNode.
// - Traverse the tree to make pTempNode point to last child
// (_pcnChild).
// - Assign pTempNode's _pcnParent to pTempRoot
// - Assign the pTempRoot's _pcnChild pointer to point to the
// sister of pTempNode's _pcnSister rather than to itself,
// therby isolating itself.
// - Decrement the _cStorages of pTempRoot (used to verify).
// - Assign pTempNode's _pcnSister to NULL.
// - Assert to ensure the pTempNode's _cStorages is zero
// before deleting it.
// - Delete pTempNode.
// - Go back to top of loop and repeat till all nodes are
// deleted.
//---------------------------------------------------------------------------
HRESULT ChanceDF::DeleteChanceDocFileSubTree(ChanceNode **ppcnTrav)
{
HRESULT hr = S_OK;
ChanceNode *pTempRoot = NULL;
ChanceNode *pTempNode = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("DeleteChanceDocFileSubTree"));
DH_VDATEPTRIN(ppcnTrav, PCHANCENODE);
DH_ASSERT(NULL != *ppcnTrav);
if(S_OK == hr)
{
pTempRoot = *ppcnTrav;
pTempRoot->_pcnParent = NULL;
// Code to delete the tree iteratively
while(NULL != pTempRoot)
{
pTempNode = pTempRoot;
while(NULL != pTempNode->_pcnChild)
{
pTempNode = pTempNode->_pcnChild;
}
pTempRoot = pTempNode->_pcnParent;
if(pTempRoot != NULL)
{
pTempRoot->_pcnChild = pTempNode->_pcnSister;
// Decrease the storage count. This would be used to verify
// before deleting the ChanceNode.
pTempRoot->_cStorages--;
}
pTempNode->_pcnSister = NULL;
// Verify that number of children of this node are zero. Assert if
// not.
DH_ASSERT(0 == pTempNode->_cStorages);
// Delete the node
delete pTempNode;
pTempNode = NULL;
}
}
return hr;
}
//--------------------------------------------------------------------------
// Member: ChanceDF::GetModes, public
//
// Synopsis: Gets the creation modes for Root Storage, child storages,
// streams if provided on command line parameters.
//
// Arguments: [pDFMode]
// [ptcsModeFlags]
//
// Returns: HRESULT
//
// History: Narindk 2-May-96 Created
//---------------------------------------------------------------------------
HRESULT ChanceDF::GetModes(
DWORD *pDFMode,
LPCTSTR ptcsModeFlags)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetModes"));
DH_VDATESTRINGPTR(ptcsModeFlags);
DH_VDATEPTROUT(pDFMode, DWORD);
DH_ASSERT(NULL != pDFMode);
if(S_OK == hr)
{
if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRREADSHEX))
{
*pDFMode = STGM_READ |
STGM_DIRECT |
STGM_SHARE_EXCLUSIVE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRWRITESHEX))
{
*pDFMode = STGM_WRITE |
STGM_DIRECT |
STGM_SHARE_EXCLUSIVE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRREADSHDENYW))
{
*pDFMode = STGM_READ |
STGM_DIRECT |
STGM_SHARE_DENY_WRITE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRREADWRITESHEX))
{
*pDFMode = STGM_READWRITE |
STGM_DIRECT |
STGM_SHARE_EXCLUSIVE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_DIRREADWRITESHDENYN))
{
*pDFMode = STGM_READWRITE |
STGM_DIRECT |
STGM_SHARE_DENY_NONE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADWRITESHEX))
{
*pDFMode = STGM_READWRITE |
STGM_TRANSACTED |
STGM_SHARE_EXCLUSIVE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADWRITESHDENYW))
{
*pDFMode = STGM_READWRITE |
STGM_TRANSACTED |
STGM_SHARE_DENY_WRITE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADWRITESHDENYN))
{
*pDFMode = STGM_READWRITE |
STGM_TRANSACTED |
STGM_SHARE_DENY_NONE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADWRITESHDENYR))
{
*pDFMode = STGM_READWRITE |
STGM_TRANSACTED |
STGM_SHARE_DENY_READ;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADSHDENYN))
{
*pDFMode = STGM_READ |
STGM_TRANSACTED |
STGM_SHARE_DENY_NONE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADSHDENYR))
{
*pDFMode = STGM_READ |
STGM_TRANSACTED |
STGM_SHARE_DENY_READ;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADSHDENYW))
{
*pDFMode = STGM_READ |
STGM_TRANSACTED |
STGM_SHARE_DENY_WRITE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTREADSHEX))
{
*pDFMode = STGM_READ |
STGM_TRANSACTED |
STGM_SHARE_EXCLUSIVE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTWRITESHDENYN))
{
*pDFMode = STGM_WRITE |
STGM_TRANSACTED |
STGM_SHARE_DENY_NONE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTWRITESHDENYR))
{
*pDFMode = STGM_WRITE |
STGM_TRANSACTED |
STGM_SHARE_DENY_READ;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTWRITESHDENYW))
{
*pDFMode = STGM_WRITE |
STGM_TRANSACTED |
STGM_SHARE_DENY_WRITE;
}
else
if (0 == _tcsicmp(ptcsModeFlags, TSZ_XACTWRITESHEX))
{
*pDFMode = STGM_WRITE |
STGM_TRANSACTED |
STGM_SHARE_EXCLUSIVE;
}
else
{
hr = E_INVALIDARG ;
DH_ASSERT(!TEXT("ChanceDF::GetModes: Invalid Mode")) ;
}
}
return hr;
}
//--------------------------------------------------------------------------
// Member: ChanceDF::GetDocFileNameFromCmdline, private
//
// Synopsis: Gets the user provided name for docfile to be created.
//
// Arguments: [tszName]
//
// Returns: HRESULT
//
// History: Narindk 2-May-96 Created
//---------------------------------------------------------------------------
HRESULT ChanceDF::GetDocFileNameFromCmdline(LPCTSTR tszName)
{
HRESULT hr = S_OK;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::GetDocFileName"));
DH_VDATESTRINGPTR(tszName);
_ptszName = new TCHAR[_tcslen(tszName)+1];
if (_ptszName == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
_tcscpy(_ptszName, tszName);
}
return hr;
}
//--------------------------------------------------------------------------
// Member: ChanceDF::GetRandomChanceNode, protected
//
// Synopsis: Gets a random ChanceNode from the ChanceDocFile tree to which
// a new ChanceNode would be added as Child or Sister during
// generation of ChanceDF tree.
//
// Arguments: [cNumOfNodes] : Total number of ChanceNodes in ChanceDF tree
// [ppcn] : Out parameter to return random ChanceNode found.
//
// Returns: HRESULT
//
// History: Narindk 2-July-96 Created
//
// Notes: -Find a random number between 1 and total number of nodes in
// the tree cNumOfNodes
// -Initialize counter to 1.
// -Initialze temp variable pcnTrav to _pcnRoot.
// -In a infinite for loop-
// -while pcnTrav's _pcnChild is not NULL and counter is less
// than cRandomNode, loop and update pcnTrav and counter.
// -If cRandomNode is equal to counter, then break out of
// for loop.
// -while pcnTrav's _pcnSister is NULL, loop and keep assign
// ing pcnTrav's _pcnParent to pcnTrav.
// -When pcnTrav's _pcnSister is not NULL, assign it to
// pcnTrav, increment counter and go back to top of loop.
//
// Pl. note that if cNumNodes is incorrectly given as more than
// actual number of nodes in tree, then this function will throw
// asserts.
//---------------------------------------------------------------------------
HRESULT ChanceDF::GetRandomChanceNode(ULONG cNumOfNodes, ChanceNode **ppcn)
{
HRESULT hr = S_OK;
ChanceNode *pcnTrav = NULL;
ULONG cRandomNode = 0;
ULONG counter = 1;
USHORT usErr = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChanceDF::GetRandomChanceNode"));
DH_VDATEPTROUT(ppcn, PCHANCENODE);
DH_ASSERT(NULL != ppcn);
DH_ASSERT(NULL != _pcnRoot);
DH_ASSERT(NULL != _pdgi);
DH_ASSERT(0 != cNumOfNodes);
if(S_OK == hr)
{
// Initialize out parameter
*ppcn = NULL;
usErr = _pdgi->Generate(&cRandomNode, 1, cNumOfNodes);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
pcnTrav = _pcnRoot;
for(;;)
{
DH_ASSERT((NULL != pcnTrav) && (counter <= cRandomNode));
while((pcnTrav->_pcnChild != NULL) && (counter < cRandomNode))
{
pcnTrav = pcnTrav->_pcnChild;
counter++;
}
if(cRandomNode == counter)
{
break;
}
while(NULL == pcnTrav->_pcnSister)
{
pcnTrav = pcnTrav->_pcnParent;
DH_ASSERT(NULL != pcnTrav);
}
DH_ASSERT(NULL != pcnTrav->_pcnSister);
pcnTrav = pcnTrav->_pcnSister;
counter++;
}
}
if(S_OK == hr)
{
*ppcn = pcnTrav;
}
return hr;
}
//--------------------------------------------------------------------------
// Member: ChanceDF::GetDepthOfNode, private
//
// Synopsis: Gets the depth of a ChanceNode in a ChanceDF tree
//
// Arguments: [pcn] - ChanceNode whose depth needs to be determined.
//
// Returns: HRESULT
//
// History: Narindk 2-July-96 Created
//
// Notes: -Assigned passed in ChanceNode to temp variable pcnTrav.
// -Initialize cNodeDepth to zero.
// -Loop till pcnTrav's _pcnParent is not NULL and keep on
// updating pcnTrav and cNodeDepth.
// -Depth returned is 0 to n-1 for 1 to nth level nodes.
//---------------------------------------------------------------------------
ULONG ChanceDF::GetDepthOfNode(ChanceNode *pcn)
{
ChanceNode *pcnTrav = NULL;
ULONG cNodeDepth = 0;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ChanceDF::GetDepthOfNode"));
DH_ASSERT(NULL != pcn);
pcnTrav = pcn;
while(NULL != pcnTrav->_pcnParent)
{
cNodeDepth++;
pcnTrav = pcnTrav->_pcnParent;
}
return cNodeDepth;
}