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.
 
 
 
 
 
 

5990 lines
169 KiB

//-------------------------------------------------------------------------
//
// Microsoft OLE
// Copyright (C) Microsoft Corporation, 1994 - 1995.
//
// File: utl.cxx
//
// Contents: utilities for OLE storage base tests
//
// Functions:
//
// History: NarindK Created.
//
//--------------------------------------------------------------------------
#include <dfheader.hxx>
#pragma hdrstop
#include "init.hxx"
//global array of interesting file sizes for IStream read/writes
USHORT ausSIZE_ARRAY[] =
{0,1,2,255,256,257,511,512,513,2047,2048,2049,4095,4096,4097};
// externs
extern BOOL g_fUseStdBlk;
extern ULONG ulStreamSize;
extern USHORT usIterations;
extern LPTSTR ptszNames[MAX_DOCFILES];
extern ULONG *ulSeekOffset;
extern TIMEINFO Time[];
//----------------------------------------------------------------------------
//
// Function: CountFilesInDirectory
//
// Synopsis: count number of files in directory matching wildcard mask
//
// Arguments: [pszWildMask] - wild card mask string of files to find
//
// Returns: number of files found
//
// History: 2-Jul-1996 Narindk Created
//
//-----------------------------------------------------------------------------
ULONG CountFilesInDirectory(LPTSTR ptszWildMask)
{
#ifdef _MAC
DH_LOG((
LOG_INFO,
TEXT("!!!!!!!!!!!!!!CountFilesInDirectory not implemented yet.\n")));
return 0;
#else
ULONG culFilesInDirectory = 0;
DWORD cChar = 0;
HANDLE hFind = NULL;
TCHAR ptszTmpFileDir[_MAX_PATH];
TCHAR ptszTmpFilePath[_MAX_PATH];
WIN32_FIND_DATA wfd;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("CountFilesInDirectory"));
cChar = GetEnvironmentVariable(
TEXT("TMP"),
ptszTmpFileDir,
sizeof(ptszTmpFileDir));
DH_ASSERT(0 != cChar);
if (0 != cChar)
{
_tcscpy(ptszTmpFilePath, ptszTmpFileDir);
_tcscat(ptszTmpFilePath, TEXT("\\"));
}
else
{
_tcscpy(ptszTmpFilePath, TEXT("C:\\"));
}
_tcscat(ptszTmpFilePath, ptszWildMask);
DH_LOG((
LOG_INFO,
TEXT("Counting %s files in %s directory\n"),
ptszWildMask,
ptszTmpFileDir == NULL ? TEXT("C:\\") : ptszTmpFileDir));
hFind = FindFirstFile(ptszTmpFilePath, &wfd);
if(INVALID_HANDLE_VALUE != hFind)
{
do
{
if(wfd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
{
culFilesInDirectory++;
}
} while (FindNextFile(hFind, &wfd));
FindClose(hFind);
}
DH_LOG((
LOG_INFO,
TEXT("Number of %s files in %s directory = %lu\n"),
ptszWildMask,
ptszTmpFileDir == NULL ? TEXT("C:\\") : ptszTmpFileDir,
culFilesInDirectory));
return culFilesInDirectory;
#endif //_MAC
}
//----------------------------------------------------------------------------
//
// Function: GetRandomSeekOffset
//
// Synopsis: Gets a random seek offset from either standard array or a random
// number
//
// Arguments: [plSeekPosition] - Pointer to seek position
// [pdgi] - Pointer to data generator object
//
// Returns: HResult
//
// History: 5-Jul-1996 Narindk Created
//
//-----------------------------------------------------------------------------
HRESULT GetRandomSeekOffset(LONG *plSeekPosition, DG_INTEGER *pdgi)
{
HRESULT hr = S_OK;
ULONG cArrayIndex = 0;
USHORT usErr = 0;
LONG lSeekPosition = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetRandomSeekOffset"));
DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
DH_VDATEPTRIN(plSeekPosition, LONG ) ;
DH_ASSERT(NULL != pdgi);
if(TRUE == g_fUseStdBlk)
{
// Pick up a random array element.
usErr = pdgi->Generate(&cArrayIndex, 0, MAX_SIZE_ARRAY);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
else
{
*plSeekPosition = *plSeekPosition + ausSIZE_ARRAY[cArrayIndex];
}
}
else
{
// Pick up a random offset
usErr = pdgi->Generate(
&lSeekPosition,
0,
ausSIZE_ARRAY[MAX_SIZE_ARRAY] * MAX_SIZE_MULTIPLIER );
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
else
{
*plSeekPosition = *plSeekPosition + lSeekPosition;
}
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: SetItemsInStorage
//
// Synopsis: Does random SetClass / SetStateBits/ Commit / Revert operations
// on passed IStorage.
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode
// [pdgi] - Pointer to data generator object
//
// Returns: HResult
//
// History: 15-Jul-1996 Narindk Created
//
//-----------------------------------------------------------------------------
HRESULT SetItemsInStorage(VirtualCtrNode *pvcn, DG_INTEGER *pdgi)
{
HRESULT hr = S_OK;
USHORT usErr = 0;
ULONG cRandomVar = 0;
ULONG cRandomClsid = 0;
ULONG cMinVar = 16;
ULONG cMaxVar = 32;
DWORD grfStateBits = 0;
DWORD grfMask = 0;
DWORD grfDesiredStateBits = 0;
BOOL fStateBitsChanged = FALSE;
BOOL fPass = TRUE;
STATSTG statStgCommited;
STATSTG statStgCurrent;
STATSTG statStgNew;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("SetItemsInStorage"));
DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_ASSERT(NULL != pvcn);
DH_ASSERT(NULL != pdgi);
if (S_OK == hr)
{
// Generate random number of variations.
usErr = pdgi->Generate(&cRandomVar, cMinVar, cMaxVar);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
//initialize STATSTG containing info about what is on persistent store
if(S_OK == hr)
{
hr = pvcn->Stat(&statStgCommited, STATFLAG_NONAME);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
}
if (S_OK == hr)
{
DH_LOG((
LOG_INFO,
TEXT("VirtualCtrNode::Stat completed successfully.\n")));
}
else
{
DH_LOG((
LOG_INFO,
TEXT("VirtualCtrNode::Stat unsuccessful, hr=0x%lx.\n"),
hr));
}
// Start while loop
while((S_OK == hr) && (0 != cRandomVar))
{
if(S_OK == hr)
{
hr = pvcn->Stat(&statStgCurrent, STATFLAG_NONAME);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
}
if(S_OK == hr)
{
// Randomly either change the CLSID or State Bits.
if(0 == cRandomVar%2)
{
usErr = pdgi->Generate(&cRandomClsid, 1, 3);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
if(S_OK == hr)
{
// Call Set Class to change CLSID
switch(cRandomClsid)
{
case 1:
{
hr = pvcn->SetClass(IID_IUnknown);
break;
}
case 2:
{
hr = pvcn->SetClass(IID_IStorage);
break;
}
case 3:
{
hr = pvcn->SetClass(IID_IStream);
break;
}
}
DH_HRCHECK(hr, TEXT("VirtualCtrNode::SetClass")) ;
}
}
else
{
// Set boolean to true indicatinng changing state bits
fStateBitsChanged = TRUE;
usErr = pdgi->Generate(&grfStateBits, 0, ULONG_MAX);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
if(S_OK == hr)
{
usErr = pdgi->Generate(&grfMask, 0, ULONG_MAX);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
grfDesiredStateBits = (grfStateBits & grfMask) |
(statStgCurrent.grfStateBits & ~grfMask);
// Call SetStateBits to change State Bits
hr = pvcn->SetStateBits(grfStateBits, grfMask);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::SetStateBits")) ;
}
}
}
if(S_OK == hr)
{
// Get information about new state
hr = pvcn->Stat(&statStgNew, STATFLAG_NONAME);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
}
// Verify the new State
// Verify state bits
if((S_OK == hr) && (TRUE == fStateBitsChanged))
{
if(statStgNew.grfStateBits != grfDesiredStateBits)
{
fPass = FALSE;
DH_LOG((
LOG_INFO,
TEXT("State Bits not changed correctly.\n")));
DH_LOG((
LOG_INFO,
TEXT("State Bits Actual: 0x%lx, Exp: 0x%lx.\n"),
statStgNew.grfStateBits,
grfDesiredStateBits));
}
else
{
DH_LOG((
LOG_INFO,
TEXT("State Bits changed correctly.\n")));
DH_LOG((
LOG_INFO,
TEXT("State Bits Actual: 0x%lx, Exp: 0x%lx.\n"),
statStgNew.grfStateBits,
grfDesiredStateBits));
}
}
// Verify CLSID
if(S_OK == hr)
{
switch(cRandomClsid)
{
case 1:
{
if(!IsEqualCLSID(statStgNew.clsid, IID_IUnknown))
{
fPass = FALSE;
DH_LOG((
LOG_INFO,
TEXT("SetClass didn't set CLSID IID_IUnknown.\n")));
}
else
{
DH_LOG((
LOG_INFO,
TEXT("SetClass set CLSID to IID_IUnknown.\n")));
}
break;
}
case 2:
{
if(!IsEqualCLSID(statStgNew.clsid, IID_IStorage))
{
fPass = FALSE;
DH_LOG((
LOG_INFO,
TEXT("SetClass didn't set CLSID IID_IStorage.\n")));
}
else
{
DH_LOG((
LOG_INFO,
TEXT("SetClass set CLSID to IID_IStorage.\n")));
}
break;
}
case 3:
{
if(!IsEqualCLSID(statStgNew.clsid, IID_IStream))
{
fPass = FALSE;
DH_LOG((
LOG_INFO,
TEXT("SetClass didn't set CLSID IID_IStream.\n")));
}
else
{
DH_LOG((
LOG_INFO,
TEXT("SetClass set CLSID to IID_IStream.\n")));
}
break;
}
}
}
// Modify hr if required based on fPass Value so that we can fall
// out of this loop in error.
if((S_OK == hr) && (FALSE == fPass))
{
hr = S_FALSE;
}
// Do random commit or revert operations and verify the State then
if(S_OK == hr)
{
// Randomly either commit or Revert.
if(0 == cRandomVar%2)
{
// Commit the changes
DH_LOG((
LOG_INFO,
TEXT("Random Commit operation chosen.\n")));
hr = pvcn->Commit(STGC_DEFAULT);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Commit")) ;
if(S_OK == hr)
{
// Store the information in statStgCommited
hr = pvcn->Stat(&statStgCommited, STATFLAG_NONAME);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
}
}
else if(statStgNew.grfMode & STGM_TRANSACTED)
{
// Revert the changes
DH_LOG((
LOG_INFO,
TEXT("Random Revert operation chosen.\n")));
hr = pvcn->Revert();
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Revert")) ;
// Do Stat
if(S_OK == hr)
{
hr = pvcn->Stat(&statStgNew, STATFLAG_NONAME);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Stat")) ;
}
// Verify values after Revert
if(S_OK == hr)
{
if(statStgNew.grfStateBits != statStgCommited.grfStateBits)
{
fPass = FALSE;
DH_LOG((
LOG_INFO,
TEXT("State Bits after Revert not correct.\n")));
DH_LOG((
LOG_INFO,
TEXT("State Bits Actual: 0x%lx, Exp: 0x%lx.\n"),
statStgNew.grfStateBits,
statStgCommited.grfStateBits));
}
else
{
DH_LOG((
LOG_INFO,
TEXT("State Bits after Revert correct.\n")));
}
if(!IsEqualCLSID(statStgNew.clsid, statStgCommited.clsid))
{
fPass = FALSE;
DH_LOG((
LOG_INFO,
TEXT("CLSID after Revert not correct.\n")));
}
else
{
DH_LOG((
LOG_INFO,
TEXT("CLSID after Revert correct.\n")));
}
}
// Modify hr if reqd based on fPass Value so that we can fall
// out of this loop in error.
if((S_OK == hr) && (FALSE == fPass))
{
hr = S_FALSE;
}
}
}
// Reset the variables
fStateBitsChanged = FALSE;
cRandomClsid = 0;
// Decrement counter
cRandomVar--;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: EnumerateDocFileInRandomChunks
//
// Synopsis: Enumerate DocFile in Random chunks and counts all the objects in
// DocFile
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode
// [pdgi] - Pointer to data generator object
// [dwStgMode] - Mode for storage objects
// [uNumObjs] - Max number of objs in DocFile to choose random
// chunk number from
// [pNumStg] - Out paramemter - Pointer to number of storages enum
// [pNumStm] - Out paramemter - Pointer to number of streams enum
//
// Returns: HResult
//
// History: 23-Jul-1996 Narindk Created
//
//-----------------------------------------------------------------------------
HRESULT EnumerateDocFileInRandomChunks(
VirtualCtrNode *pvcn,
DG_INTEGER *pdgi,
DWORD dwStgMode,
ULONG uNumObjs,
ULONG *pNumStg,
ULONG *pNumStm )
{
HRESULT hr = S_OK;
ULONG cChildStg = 0;
ULONG cChildStm = 0;
USHORT usErr = 0;
ULONG cRandomObjs = 0;
VirtualCtrNode *pvcnTrav = NULL;
LPENUMSTATSTG lpEnumStatStg = NULL;
LPMALLOC pMalloc = NULL;
ULONG celtFetched = 0;
STATSTG *pstatStgEnum = NULL;
ULONG ulRef = 0;
ULONG counter = 0;
LPTSTR ptszStatStgEnumName = NULL;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("EnumerateDocFileInRandomChunks"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_VDATEPTROUT(pdgi, DG_INTEGER) ;
DH_VDATEPTROUT(pNumStg, ULONG) ;
DH_VDATEPTROUT(pNumStm, ULONG) ;
DH_ASSERT(NULL != pvcn);
DH_ASSERT(NULL != pdgi);
DH_ASSERT(NULL != pNumStg);
DH_ASSERT(NULL != pNumStm);
if(S_OK == hr)
{
// Count the storage passed in.
*pNumStg = 1;
*pNumStm = 0;
// Get enumerator
hr = pvcn->EnumElements(0, NULL, 0, &lpEnumStatStg);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
}
// Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
if ( S_OK == hr )
{
hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
}
// Get random number of objects to be asked from through Next
if(S_OK == hr)
{
// Generate random number
usErr = pdgi->Generate(&cRandomObjs, 1, uNumObjs);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
// Allocate memory for STATSTG strcuture
if(S_OK == hr)
{
pstatStgEnum = (STATSTG *) new STATSTG [cRandomObjs];
if(NULL == pstatStgEnum)
{
hr = E_OUTOFMEMORY;
}
}
// if successful to get enumerator, get the random element of the
// enumeration sequence.
if(S_OK == hr)
{
hr = lpEnumStatStg->Next(cRandomObjs, pstatStgEnum, &celtFetched);
if(S_FALSE == hr)
{
hr = S_OK;
}
}
while(0 < celtFetched)
{
for (counter = 0; counter < celtFetched; counter++)
{
if (STGTY_STORAGE == pstatStgEnum[counter].type)
{
hr = OleStringToTString(
pstatStgEnum[counter].pwcsName,
&ptszStatStgEnumName);
// Find the respective VirtualCtrNode with the name and recurse
// into it after opening it.
if(S_OK == hr)
{
pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
while((NULL != pvcnTrav) &&
( 0 != _tcscmp(
ptszStatStgEnumName,
pvcnTrav->GetVirtualCtrNodeName())))
{
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
}
DH_ASSERT(NULL != pvcnTrav);
if(NULL != pvcnTrav)
{
hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
}
}
// Delete temp string
if(NULL != ptszStatStgEnumName)
{
delete ptszStatStgEnumName;
ptszStatStgEnumName = NULL;
}
if(S_OK == hr)
{
hr = EnumerateDocFileInRandomChunks(
pvcnTrav,
pdgi,
dwStgMode,
uNumObjs,
&cChildStg,
&cChildStm);
}
if(S_OK == hr)
{
hr = pvcnTrav->Close();
}
// Update number of nodes on basis of child nodes as found
if(0 != cChildStg)
{
*pNumStg = *pNumStg + cChildStg;
}
if(0 != cChildStm)
{
*pNumStm = *pNumStm + cChildStm;
}
}
else
if (STGTY_STREAM == pstatStgEnum[counter].type)
{
(*pNumStm)++;
}
else
// The element is neither IStorage nor IStream, report error.
{
hr = E_UNEXPECTED;
}
// Clean up
if(NULL != pstatStgEnum[counter].pwcsName)
{
pMalloc->Free(pstatStgEnum[counter].pwcsName);
pstatStgEnum[counter].pwcsName = NULL;
}
// Break out of loop in error
if(S_OK != hr)
{
break;
}
}
// Get the next random elements from the enumeration sequence
if(S_OK == hr)
{
// Generate random number.
usErr = pdgi->Generate(&cRandomObjs, 1, uNumObjs);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if (NULL != pstatStgEnum)
{
delete [] pstatStgEnum;
pstatStgEnum = NULL;
}
if(S_OK == hr)
{
pstatStgEnum = (STATSTG *) new STATSTG [cRandomObjs];
if(NULL == pstatStgEnum)
{
hr = E_OUTOFMEMORY;
}
}
if(S_OK == hr)
{
hr = lpEnumStatStg->Next(cRandomObjs, pstatStgEnum, &celtFetched);
if(S_FALSE == hr)
{
hr = S_OK;
}
}
// Reinitialize the variables
cChildStg = 0;
cChildStm = 0;
}
// Clean up
if (NULL != pstatStgEnum)
{
delete [] pstatStgEnum;
pstatStgEnum = NULL;
}
if (NULL != lpEnumStatStg)
{
ulRef = lpEnumStatStg->Release();
DH_ASSERT(NULL == ulRef);
lpEnumStatStg = NULL;
}
if(NULL != pMalloc)
{
pMalloc->Release();
pMalloc = NULL;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: CompareSTATSTG
//
// Synopsis: Compares contents of two STATSTG structs
//
// Arguments: [sstg1] - first STATSTG struct to be compared
// [sstg2] - second STATSTG struct to be compared
//
// Returns: TRUE if storage buffers are the same; FALSE otherwise.
//
// History: 24-Jul-1996 Narindk Enhanced
//
//-----------------------------------------------------------------------------
BOOL CompareSTATSTG(STATSTG sstg1, STATSTG sstg2)
{
HRESULT hr = S_OK;
LPTSTR ptszStatStg1Name = NULL;
LPTSTR ptszStatStg2Name = NULL;
BOOL fEqual = FALSE;
hr = OleStringToTString(sstg1.pwcsName, &ptszStatStg1Name);
if(S_OK == hr)
{
hr = OleStringToTString(sstg2.pwcsName, &ptszStatStg2Name);
}
if(S_OK == hr)
{
fEqual=((!(_tcscmp(ptszStatStg1Name, ptszStatStg2Name)) &&
(sstg1.type == sstg2.type) &&
(ULIGetLow(sstg1.cbSize) == ULIGetLow(sstg2.cbSize)) &&
(sstg1.mtime.dwLowDateTime == sstg2.mtime.dwLowDateTime) &&
(sstg1.mtime.dwHighDateTime == sstg2.mtime.dwHighDateTime) &&
(sstg1.ctime.dwLowDateTime == sstg2.ctime.dwLowDateTime) &&
(sstg1.ctime.dwHighDateTime == sstg2.ctime.dwHighDateTime) &&
(sstg1.atime.dwLowDateTime == sstg2.atime.dwLowDateTime) &&
(sstg1.atime.dwHighDateTime == sstg2.atime.dwHighDateTime) &&
(sstg1.grfMode == sstg2.grfMode) &&
(sstg1.grfLocksSupported == sstg2.grfLocksSupported) &&
(sstg1.grfStateBits == sstg2.grfStateBits) &&
IsEqualCLSID(sstg1.clsid, sstg2.clsid)));
}
DH_ASSERT(S_OK == hr);
// Delete temp strings
if(NULL != ptszStatStg1Name)
{
delete ptszStatStg1Name;
ptszStatStg1Name = NULL;
}
if(NULL != ptszStatStg2Name)
{
delete ptszStatStg2Name;
ptszStatStg1Name = NULL;
}
return fEqual;
}
//----------------------------------------------------------------------------
//
// Function: EnumerateDocFileAndVerifyEnumCloneResetSkipNext
//
// Synopsis: Enumerate DocFile all at one level, Gets a clone of enumerator,
// Uses Clone/Reset/Skip/Next method to get a Storage and verify that
// with one obtained from original enumerator and counts all the
// objects ath the level. If object is a storage, it is recursed
// into and operation repeated.
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode
// [dwStgMode] - Mode for storage objects
// [uNumObjs] - Max number of objs in DocFile to choose random
// chunk number from
// [pNumStg] - Out paramemter - Pointer to number of storages enum
// [pNumStm] - Out paramemter - Pointer to number of streams enum
//
// Returns: HResult
//
// History: 24-Jul-1996 Narindk Created
//
//-----------------------------------------------------------------------------
HRESULT EnumerateDocFileAndVerifyEnumCloneResetSkipNext(
VirtualCtrNode *pvcn,
DWORD dwStgMode,
ULONG uNumObjs,
ULONG *pNumStg,
ULONG *pNumStm )
{
HRESULT hr = S_OK;
ULONG cChildStg = 0;
ULONG cChildStm = 0;
VirtualCtrNode *pvcnTrav = NULL;
LPENUMSTATSTG lpEnumStatStg = NULL;
LPENUMSTATSTG lpEnumStatStgClone = NULL;
LPMALLOC pMalloc = NULL;
ULONG celtFetched = 0;
STATSTG *pstatStgEnum = NULL;
ULONG ulRef = 0;
LPTSTR ptszStatStgEnumName = NULL;
BOOL fPass = FALSE;
STATSTG statStgEnumClone;
DH_FUNCENTRY(
&hr,
DH_LVL_DFLIB,
_TEXT("EnumerateDocFileAndVerifyEnumCloneResetSkipNext"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_VDATEPTROUT(pNumStg, ULONG) ;
DH_VDATEPTROUT(pNumStm, ULONG) ;
DH_ASSERT(NULL != pvcn);
DH_ASSERT(NULL != pNumStg);
DH_ASSERT(NULL != pNumStm);
if(S_OK == hr)
{
// Count the storage passed in.
*pNumStg = 1;
*pNumStm = 0;
// Get enumerator
hr = pvcn->EnumElements(0, NULL, 0, &lpEnumStatStg);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
}
// Make a clone of the enumerator
if(S_OK == hr)
{
hr = lpEnumStatStg->Clone(&lpEnumStatStgClone);
DH_ASSERT((S_OK == hr) && (NULL != lpEnumStatStgClone));
}
// Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
if ( S_OK == hr )
{
hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
}
// Allocate memory for STATSTG strcuture
if(S_OK == hr)
{
// We are allocating memory for more number of STATSTG objects than
// what might be required, but is safer.
pstatStgEnum = (STATSTG *) new STATSTG [uNumObjs];
if(NULL == pstatStgEnum)
{
hr = E_OUTOFMEMORY;
}
}
// if successful to get enumerator, get all the element at same level of
// the enumeration sequence.
if(S_OK == hr)
{
hr = lpEnumStatStg->Next(uNumObjs, pstatStgEnum, &celtFetched);
if(S_FALSE == hr)
{
hr = S_OK;
}
}
while((0 < celtFetched--) && (S_OK == hr))
{
// for each element, ->Skip() from beginning of enumeration
// sequence (of clone) and check that it is the same as
// was returned with the original ->Next()
// The Reset call always returns S_OK, so need to check hr
hr = lpEnumStatStgClone->Reset();
DH_ASSERT(S_OK == hr);
// Skip celtFetched elements with Clone enumerator
hr = lpEnumStatStgClone->Skip(celtFetched);
DH_ASSERT(S_OK == hr);
// Retrieve next element from this clone enumerator
if(S_OK == hr)
{
hr = lpEnumStatStgClone->Next(1, &statStgEnumClone, NULL);
DH_ASSERT(S_OK == hr);
}
if(S_OK == hr)
{
// Compare the STATSTG structures of one that is retrieved through
// Clone and the one returned from original enumerator
fPass = CompareSTATSTG(
pstatStgEnum[celtFetched],
statStgEnumClone);
}
if(FALSE == fPass)
{
hr = S_FALSE;
DH_LOG((LOG_INFO, TEXT("The two STATSTG's don't match\n")));
}
else
{
DH_LOG((
LOG_INFO,
TEXT("IEnum org and Clone enumerator: two STATSTG's match\n")));
}
if(S_OK == hr)
{
if (STGTY_STORAGE == pstatStgEnum[celtFetched].type)
{
hr = OleStringToTString(
pstatStgEnum[celtFetched].pwcsName,
&ptszStatStgEnumName);
// Find the respective VirtualCtrNode with the name and recurse
// into it after opening it.
if(S_OK == hr)
{
pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
while((NULL != pvcnTrav) &&
( 0 != _tcscmp(
ptszStatStgEnumName,
pvcnTrav->GetVirtualCtrNodeName())))
{
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
}
DH_ASSERT(NULL != pvcnTrav);
if(NULL != pvcnTrav)
{
hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
}
}
// Delete temp string
if(NULL != ptszStatStgEnumName)
{
delete ptszStatStgEnumName;
ptszStatStgEnumName = NULL;
}
if(S_OK == hr)
{
hr = EnumerateDocFileAndVerifyEnumCloneResetSkipNext(
pvcnTrav,
dwStgMode,
uNumObjs,
&cChildStg,
&cChildStm);
}
if(S_OK == hr)
{
hr = pvcnTrav->Close();
}
// Update number of nodes on basis of child nodes as found
if(0 != cChildStg)
{
*pNumStg = *pNumStg + cChildStg;
}
if(0 != cChildStm)
{
*pNumStm = *pNumStm + cChildStm;
}
}
else
if (STGTY_STREAM == pstatStgEnum[celtFetched].type)
{
(*pNumStm)++;
}
else
// The element is neither IStorage nor IStream, report error.
{
hr = E_UNEXPECTED;
}
}
// Clean up
if(NULL != pstatStgEnum[celtFetched].pwcsName)
{
pMalloc->Free(pstatStgEnum[celtFetched].pwcsName);
pstatStgEnum[celtFetched].pwcsName = NULL;
}
if(NULL != statStgEnumClone.pwcsName)
{
pMalloc->Free(statStgEnumClone.pwcsName);
statStgEnumClone.pwcsName = NULL;
}
}
// Clean up
if (NULL != pstatStgEnum)
{
delete [] pstatStgEnum;
pstatStgEnum = NULL;
}
if (NULL != lpEnumStatStg)
{
ulRef = lpEnumStatStg->Release();
DH_ASSERT(NULL == ulRef);
lpEnumStatStg = NULL;
}
if (NULL != lpEnumStatStgClone)
{
ulRef = lpEnumStatStgClone->Release();
DH_ASSERT(NULL == ulRef);
lpEnumStatStgClone = NULL;
}
if(NULL != pMalloc)
{
pMalloc->Release();
pMalloc = NULL;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: ModifyDocFile
//
// Synopsis: Enumerate DocFile and randomly recurses into child storages, or
// randomly destroys or renames elements.
//
// Arguments: [pVirtualDF] - Pointer to VirtualDF tree
// [pvcn] - Pointer to VirtualCtrNode
// [pdgi] - Pointer to Data Integer object
// [pdgu] - Pinter to Data Unicode objext
// [fCommitRoot] - Bool to commit a root DocFile storage or not
//
// Returns: HResult
//
// History: 25-Jul-1996 Narindk Created
//
//----------------------------------------------------------------------------
HRESULT ModifyDocFile(
VirtualDF *pVirtualDF,
VirtualCtrNode *pvcn,
DG_INTEGER *pdgi,
DG_STRING *pdgu,
DWORD dwStgMode,
BOOL fCommitRoot)
{
HRESULT hr = S_OK;
VirtualCtrNode *pvcnTrav = NULL;
VirtualStmNode *pvsnTrav = NULL;
LPENUMSTATSTG lpEnumStatStg = NULL;
LPMALLOC pMalloc = NULL;
ULONG celtFetched = 0;
ULONG ulRef = 0;
USHORT usErr = 0;
LPTSTR ptszStatStgName = NULL;
LPTSTR ptszNewName = NULL;
UINT cRandVal0 = 0;
UINT cRandVal1 = 0;
UINT cRandRange0 = 0;
UINT cRandRange1 = 1;
UINT cRandRange2 = 2;
STATSTG statStg;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ModifyDocFile"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
DH_VDATEPTRIN(pdgu, DG_STRING) ;
DH_ASSERT(NULL != pvcn);
DH_ASSERT(NULL != pdgi);
DH_ASSERT(NULL != pdgu);
if(S_OK == hr)
{
// Get enumerator
hr = pvcn->EnumElements(0, NULL, 0, &lpEnumStatStg);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
}
// Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
if ( S_OK == hr )
{
hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
}
while((S_OK == lpEnumStatStg->Next(1, &statStg, &celtFetched)) &&
(S_OK == hr))
{
hr = OleStringToTString(statStg.pwcsName, &ptszStatStgName);
// If the element is an IStorage, randmly either open this and make a
// recursive call to ModifyDocFile function or randomly choose to
// either rename or destory this element.
if ((STGTY_STORAGE == statStg.type) && (S_OK == hr))
{
// Find the respective VirtualCtrNode with the name and recurse
// into it after opening it.
if(S_OK == hr)
{
pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
while((NULL != pvcnTrav) &&
( 0 != _tcscmp(
ptszStatStgName,
pvcnTrav->GetVirtualCtrNodeName())))
{
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
}
DH_ASSERT(NULL != pvcnTrav);
}
// Cloose random number
if(S_OK == hr)
{
usErr = pdgi->Generate(&cRandVal0, cRandRange0, cRandRange2);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
// Randomly choose either to open/recurse and Modify the Storage
// or choose to either randomly rename or destory the storage
if((S_OK == hr) && (0 == cRandVal0))
{
if(NULL != pvcnTrav)
{
hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Open")) ;
}
// Call ModifyDocFile recursively on this node
if(S_OK == hr)
{
hr = ModifyDocFile(
pVirtualDF,
pvcnTrav,
pdgi,
pdgu,
dwStgMode,
fCommitRoot);
}
// Close this storage
if(S_OK == hr)
{
hr = pvcnTrav->Close();
}
}
if((S_OK == hr) && (0 != cRandVal0))
{
// choose random number either to rename or destory this
// element
if(S_OK == hr)
{
usErr = pdgi->Generate(&cRandVal1,cRandRange1,cRandRange2);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
switch(cRandVal1)
{
case 1:
{
hr = DestroyStorage(pVirtualDF, pvcnTrav);
DH_HRCHECK(hr, TEXT("DestoryStorage")) ;
break;
}
case 2:
{
// Generate random new name
hr = GenerateRandomName(pdgu,
MINLENGTH,
MAXLENGTH,
&ptszNewName);
if(S_OK == hr)
{
hr = pvcnTrav->Rename(ptszNewName);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Rename")) ;
}
break;
}
}
}
}
}
// If the element is an IStream, randomly choose to either rename
// or destory this element.
else if ((STGTY_STREAM == statStg.type) && (S_OK == hr))
{
// Find the respective VirtualStmNode with the name
if(S_OK == hr)
{
pvsnTrav = pvcn->GetFirstChildVirtualStmNode();
while((NULL != pvsnTrav) &&
( 0 != _tcscmp(
ptszStatStgName,
pvsnTrav->GetVirtualStmNodeName())))
{
pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
}
DH_ASSERT(NULL != pvsnTrav);
}
// choose random number either to rename or destory this element
if(S_OK == hr)
{
usErr = pdgi->Generate(&cRandVal1, cRandRange1, cRandRange2);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
switch(cRandVal1)
{
case 1:
{
hr = DestroyStream(pVirtualDF, pvsnTrav);
DH_HRCHECK(hr, TEXT("DestroyStream")) ;
break;
}
case 2:
{
// Generate random new name
hr = GenerateRandomName(pdgu,
MINLENGTH,
MAXLENGTH,
&ptszNewName);
if(S_OK == hr)
{
hr = pvsnTrav->Rename(ptszNewName);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Rename")) ;
}
break;
}
}
}
}
// Clean up
if(NULL != statStg.pwcsName)
{
pMalloc->Free(statStg.pwcsName);
statStg.pwcsName = NULL;
}
if(NULL != ptszStatStgName)
{
delete ptszStatStgName;
ptszStatStgName = NULL;
}
if(NULL != ptszNewName)
{
delete ptszNewName;
ptszNewName = NULL;
}
}
// Commit the passed in storage as case might be
if((S_OK == hr) &&
((pvcn != pVirtualDF->GetVirtualDFRoot()) || (TRUE == fCommitRoot)))
{
hr = pvcn->Commit(STGC_DEFAULT);
}
// Clean up
if (NULL != lpEnumStatStg)
{
ulRef = lpEnumStatStg->Release();
DH_ASSERT(0 == ulRef);
lpEnumStatStg = NULL;
}
if(NULL != pMalloc)
{
pMalloc->Release();
pMalloc = NULL;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: EnumerateAndWalkDocFile
//
// Synopsis: Enumerate /walks DocFile by either randomly skipping random
// number of elements or getting random number of elements, recursing
// if a child storage is found.
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode
// [pdgi] - Pointer to data generator object
// [dwStgMode] - Mode for storage objects
// [uNumObjs] - Max number of objs in DocFile to choose random
// chunk number from
//
// Returns: HResult
//
// History: 29-Jul-1996 Narindk Created
//
// Notes: This doesn't provide any form of verification, but checks for any
// unexpected errors/faults from ole while walking the docfile tree.
//-----------------------------------------------------------------------------
HRESULT EnumerateAndWalkDocFile(
VirtualCtrNode *pvcn,
DG_INTEGER *pdgi,
DWORD dwStgMode,
ULONG uNumObjs)
{
HRESULT hr = S_OK;
USHORT usErr = 0;
ULONG cRandomObjs = 0;
VirtualCtrNode *pvcnTrav = NULL;
LPENUMSTATSTG lpEnumStatStg = NULL;
LPMALLOC pMalloc = NULL;
ULONG celtFetched = 0;
STATSTG *pstatStgEnum = NULL;
ULONG ulRef = 0;
ULONG counter = 0;
LPTSTR ptszStatStgEnumName = NULL;
UINT cWhichOp = 0;
UINT cRandomOpMin = 1;
UINT cRandomOpMax = 3;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("EnumerateAndWalkDocFile"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode) ;
DH_VDATEPTROUT(pdgi, DG_INTEGER) ;
DH_ASSERT(NULL != pvcn);
DH_ASSERT(NULL != pdgi);
if(S_OK == hr)
{
// Get enumerator
hr = pvcn->EnumElements(0, NULL, 0, &lpEnumStatStg);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
}
// Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
if ( S_OK == hr )
{
hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
}
// Get random number of objects to be asked from through Next or Skip
if(S_OK == hr)
{
// Generate random number
usErr = pdgi->Generate(&cRandomObjs, 1, uNumObjs);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
// Get random number to determine whether to do skip or next operation.
// 67% Next operation would be done and 33% skip would be done.
if(S_OK == hr)
{
// Generate random number
usErr = pdgi->Generate(&cWhichOp, cRandomOpMin, cRandomOpMax);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
// Allocate memory for STATSTG strcuture
if(S_OK == hr)
{
pstatStgEnum = (STATSTG *) new STATSTG [cRandomObjs];
if(NULL == pstatStgEnum)
{
hr = E_OUTOFMEMORY;
}
}
// if successful to get enumerator, get the random element of the
// enumeration sequence. 33% do skip and 67% do Next.
if(S_OK == hr)
{
if(cRandomOpMin == cWhichOp)
{
hr = lpEnumStatStg->Skip(cRandomObjs);
if(S_OK == hr)
{
hr = lpEnumStatStg->Next(1, pstatStgEnum, &celtFetched);
}
}
else
{
hr = lpEnumStatStg->Next(cRandomObjs, pstatStgEnum, &celtFetched);
}
if(S_FALSE == hr)
{
hr = S_OK;
}
}
while(0 < celtFetched)
{
for (counter = 0; counter < celtFetched; counter++)
{
if (STGTY_STORAGE == pstatStgEnum[counter].type)
{
hr = OleStringToTString(
pstatStgEnum[counter].pwcsName,
&ptszStatStgEnumName);
// Find the respective VirtualCtrNode with the name and recurse
// into it after opening it.
if(S_OK == hr)
{
pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
while((NULL != pvcnTrav) &&
( 0 != _tcscmp(
ptszStatStgEnumName,
pvcnTrav->GetVirtualCtrNodeName())))
{
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
}
DH_ASSERT(NULL != pvcnTrav);
if(NULL != pvcnTrav)
{
hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
}
}
// Delete temp string
if(NULL != ptszStatStgEnumName)
{
delete ptszStatStgEnumName;
ptszStatStgEnumName = NULL;
}
if(S_OK == hr)
{
hr = EnumerateAndWalkDocFile(
pvcnTrav,
pdgi,
dwStgMode,
uNumObjs);
}
if(S_OK == hr)
{
hr = pvcnTrav->Close();
}
}
// Clean up
if(NULL != pstatStgEnum[counter].pwcsName)
{
pMalloc->Free(pstatStgEnum[counter].pwcsName);
pstatStgEnum[counter].pwcsName = NULL;
}
// Break out of loop in error
if(S_OK != hr)
{
break;
}
}
// Reset the variables
cWhichOp = 0;
cRandomObjs = 0;
celtFetched = 0;
// Get random number to determine whether to do skip or next operation.
// 67% Next operation would be done and 33% skip would be done.
if(S_OK == hr)
{
// Generate random number
usErr = pdgi->Generate(&cWhichOp, cRandomOpMin, cRandomOpMax);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
// Get the random number of elements from the enumeration sequence to
// skip or get.
if(S_OK == hr)
{
// Generate random number.
usErr = pdgi->Generate(&cRandomObjs, 1, uNumObjs);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if (NULL != pstatStgEnum)
{
delete [] pstatStgEnum;
pstatStgEnum = NULL;
}
if(S_OK == hr)
{
pstatStgEnum = (STATSTG *) new STATSTG [cRandomObjs];
if(NULL == pstatStgEnum)
{
hr = E_OUTOFMEMORY;
}
}
if(S_OK == hr)
{
if(cRandomOpMin == cWhichOp)
{
hr = lpEnumStatStg->Skip(cRandomObjs);
if(S_OK == hr)
{
hr = lpEnumStatStg->Next(1, pstatStgEnum, &celtFetched);
}
}
else
{
hr = lpEnumStatStg->Next(cRandomObjs,pstatStgEnum,&celtFetched);
}
if(S_FALSE == hr)
{
hr = S_OK;
}
}
}
// Clean up
if (NULL != pstatStgEnum)
{
delete [] pstatStgEnum;
pstatStgEnum = NULL;
}
if (NULL != lpEnumStatStg)
{
ulRef = lpEnumStatStg->Release();
DH_ASSERT(NULL == ulRef);
lpEnumStatStg = NULL;
}
if(NULL != pMalloc)
{
pMalloc->Release();
pMalloc = NULL;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: CreateNewObject
//
// Synopsis: Randomly creates a new storage or stream object in a DocFile
//
// Arguments: [pVirtualDF] - Pointer to VirtualDF tree
// [pvcn] - Pointer to VirtualCtrNode
// [dwStgMode] - Used for random creation of storage object
// [pdgi] - Pointer to data generator integer object
// [pdgu] - Pointer to data generator unicode object
//
// Returns: HResult
//
// History: 29-Jul-1996 Narindk Created
//
//----------------------------------------------------------------------------
HRESULT CreateNewObject(
LPSTORAGE pIStorage,
DWORD dwStgMode,
DG_INTEGER *pdgi,
DG_STRING *pdgu)
{
HRESULT hr = S_OK;
USHORT usErr = 0;
UINT cRandom = 0;
LPTSTR ptszNewName = NULL;
LPTSTR ptszNewData = NULL;
LPOLESTR poszNewName = NULL;
LPOLESTR poszNewData = NULL;
ULONG cb = 0;
ULONG culWritten = 0;
LPSTORAGE pIStorageNew = NULL;
LPSTREAM pIStreamNew = NULL;
ULONG ulRef = 0;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("CreateNewObject"));
DH_VDATEPTRIN(pIStorage, IStorage) ;
DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
DH_VDATEPTRIN(pdgu, DG_STRING) ;
DH_ASSERT(NULL != pIStorage);
DH_ASSERT(NULL != pdgi);
DH_ASSERT(NULL != pdgu);
// Pick up a random number. 33% chance to generate a new IStorage element,
// and 67% chance to generate a new IStream element.
usErr = pdgi->Generate(&cRandom, 0, 2);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
// flatfile only: storages are not allowed
if(StorageIsFlat())
{
cRandom = 2; // force it to create only streams
}
if(S_OK == hr)
{
hr = GenerateRandomName(pdgu, MINLENGTH, MAXLENGTH, &ptszNewName);
DH_HRCHECK(hr, TEXT("GenerateRandomName")) ;
}
if(S_OK == hr)
{
// Convert ptcsName to OLECHAR
hr = TStringToOleString(ptszNewName, &poszNewName);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
if(0 == cRandom)
{
// Create a new storage
hr = pIStorage->CreateStorage(
poszNewName,
dwStgMode | STGM_CREATE,
0,
0,
&pIStorageNew);
DH_HRCHECK(hr, TEXT("IStorage::CreateStorage")) ;
if(S_OK == hr)
{
// Close the new storage
ulRef = pIStorageNew->Release();
DH_ASSERT(0 == ulRef);
pIStorageNew = NULL;
}
}
else
{
usErr = pdgi->Generate(&cb, 1, SHRT_MAX);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
if(S_OK == hr)
{
// Create a new stream
hr = pIStorage->CreateStream(
poszNewName,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
0,
0,
&pIStreamNew);
DH_HRCHECK(hr, TEXT("IStorage::CreateStream")) ;
}
// Write into stream
if(S_OK == hr)
{
hr = GenerateRandomName(pdgu, cb, cb, &ptszNewData);
DH_HRCHECK(hr, TEXT("GenerateRandomName")) ;
}
if(S_OK == hr)
{
// Convert ptcsName to OLECHAR
hr = TStringToOleString(ptszNewData, &poszNewData);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = pIStreamNew->Write(poszNewData, cb, &culWritten);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Write")) ;
}
// Close the stream
if(S_OK == hr)
{
ulRef = pIStreamNew->Release();
DH_ASSERT(0 == ulRef);
pIStreamNew = NULL;
}
}
}
// Clean up
if(NULL != ptszNewName)
{
delete ptszNewName;
ptszNewName = NULL;
}
if(NULL != poszNewName)
{
delete poszNewName;
poszNewName = NULL;
}
if(NULL != ptszNewData)
{
delete ptszNewData;
ptszNewData = NULL;
}
if(NULL != poszNewName)
{
delete poszNewName;
poszNewName = NULL;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: ChangeStreamData
//
// Synopsis: Randomly changes size or data of an IStream object in a DocFile
//
// Arguments: [pIStorage] - Pointer to parent storage
// [pStatStg] - Pointer to STATSTG structure
// [pdgi] - Pointer to data generator integer object
// [pdgu] - Pointer to data generator unicode object
//
// Returns: HResult
//
// History: 29-Jul-1996 Narindk Created
//
//----------------------------------------------------------------------------
HRESULT ChangeStreamData(
LPSTORAGE pIStorage,
STATSTG *pStatStg,
DG_INTEGER *pdgi,
DG_STRING *pdgu)
{
HRESULT hr = S_OK;
USHORT usErr = 0;
LPTSTR ptszName = NULL;
LPOLESTR poszName = NULL;
LPTSTR ptszNewData = NULL;
LPOLESTR poszNewData = NULL;
ULONG cb = 0;
ULONG culWritten = 0;
ULONG ulStreamOffset = 0;
LONG lOffset = 0;
INT cSign = 0;
UINT cRandomVar = 0;
LPSTREAM pIStream = NULL;
ULONG ulRef = 0;
LARGE_INTEGER liStreamPos;
LARGE_INTEGER liSeek;
ULARGE_INTEGER uli;
ULARGE_INTEGER uliSetSize;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChangeStreamData"));
DH_VDATEPTRIN(pIStorage, IStorage) ;
DH_VDATEPTRIN(pStatStg, STATSTG) ;
DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
DH_VDATEPTRIN(pdgu, DG_STRING) ;
DH_ASSERT(NULL != pIStorage);
DH_ASSERT(NULL != pStatStg);
DH_ASSERT(NULL != pdgi);
DH_ASSERT(NULL != pdgu);
if(S_OK == hr)
{
// Convert WCHAR to TCHAR
hr = OleStringToTString(pStatStg->pwcsName, &ptszName);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
}
if(S_OK == hr)
{
// Convert TCHAR to OLECHAR
hr = TStringToOleString(ptszName, &poszName);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
// Open the stream if it is not open
if(S_OK == hr)
{
hr = pIStorage->OpenStream(
poszName,
NULL,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
0,
&pIStream);
DH_HRCHECK(hr, TEXT("IStorage::OpenStream")) ;
}
// Seek to end of stream and get its size
if(S_OK == hr)
{
memset(&liStreamPos, 0, sizeof(LARGE_INTEGER));
// Position the stream header to the postion from begining
hr = pIStream->Seek(liStreamPos, STREAM_SEEK_END, &uli);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Seek")) ;
ulStreamOffset = ULIGetLow(uli);
}
// Generate size and direction of change. Magnitude is 1- SHRT_MAX bytes
// or 1 - streamsize if SHRT_MAX is greater than stream size. 50 % of time,
// direction will be positive, and rest times negative.
if(S_OK == hr)
{
usErr = pdgi->Generate(&lOffset, 1, SHRT_MAX);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if((S_OK == hr) && ((ULONG) lOffset > ulStreamOffset))
{
usErr = pdgi->Generate(&lOffset, 1, ulStreamOffset);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
usErr = pdgi->Generate(&cSign, 1, 2);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
if(S_OK == hr)
{
cSign = (cSign == 1) ? 1 : -1;
}
}
// Generate Random number to do wither a SetSize or Seek/Write operation
// to change stream data
if(S_OK == hr)
{
usErr = pdgi->Generate(&cRandomVar, 1, 2);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
switch (cRandomVar)
{
case 1:
{
ulStreamOffset = ulStreamOffset + (lOffset * cSign);
ULISet32(uliSetSize, ulStreamOffset);
hr = pIStream->SetSize(uliSetSize);
break;
}
case 2:
{
// Seek either beyond or before the curretn seek position and
// write a random number of bytes from there.
LISet32(liSeek, lOffset*cSign);
hr = pIStream->Seek(liSeek, STREAM_SEEK_CUR, &uli);
if(S_OK == hr)
{
hr = GenerateRandomName(pdgu, 1, SHRT_MAX, &ptszNewData);
DH_HRCHECK(hr, TEXT("GenerateRandomName")) ;
}
if(S_OK == hr)
{
// Convert ptcsName to OLECHAR
hr = TStringToOleString(ptszNewData, &poszNewData);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = pIStream->Write(poszNewData, cb, &culWritten);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Write")) ;
}
break;
}
}
}
// Close the stream
if(S_OK == hr)
{
ulRef = pIStream->Release();
DH_ASSERT(0 == ulRef);
pIStream = NULL;
}
// Clean up
if(NULL != ptszName)
{
delete ptszName;
ptszName = NULL;
}
if(NULL != poszName)
{
delete poszName;
poszName = NULL;
}
if(NULL != ptszNewData)
{
delete ptszNewData;
ptszNewData = NULL;
}
if(NULL != poszNewData)
{
delete poszNewData;
poszNewData = NULL;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: ChangeExistingObject
//
// Synopsis: Randomly destorys/renames a stream or storage object in a DocFile.
// Randomly changes data of object if it is a stream. This impl.
// is for case when it a storage object that needs to be changed
//
// Arguments: [pIStorage] - Pointer to parent storage
// [pStatStg] - Pointer to STATSTG structure
// [pdgi] - Pointer to data generator integer object
// [pdgu] - Pointer to data generator unicode object
// [fStgDeleted] - Out value to indicate storage is deleted
//
// Returns: HResult
//
// History: 29-Jul-1996 Narindk Created
//
//----------------------------------------------------------------------------
HRESULT ChangeExistingObject(
LPSTORAGE pIStorage,
STATSTG *pStatStg,
DG_INTEGER *pdgi,
DG_STRING *pdgu,
BOOL *pfStgDeleted)
{
HRESULT hr = S_OK;
USHORT usErr = 0;
UINT cRandomAction = 0;
LPTSTR ptszNewName = NULL;
LPOLESTR poszNewName = NULL;
LPTSTR ptszName = NULL;
LPOLESTR poszName = NULL;
LPSTORAGE pIStorageRenamed= NULL;
LPMALLOC pMalloc = NULL;
ULONG ulRef = 0;
BOOL fRenamed = FALSE;
STATSTG statStgRenamed;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("ChangeExistingObject"));
DH_VDATEPTRIN(pIStorage, IStorage) ;
DH_VDATEPTRIN(pStatStg, STATSTG) ;
DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
DH_VDATEPTRIN(pdgu, DG_STRING) ;
DH_ASSERT(NULL != pIStorage);
DH_ASSERT(NULL != pStatStg);
DH_ASSERT(NULL != pdgi);
DH_ASSERT(NULL != pdgu);
if(S_OK == hr)
{
// Convert WCHAR to TCHAR
hr = OleStringToTString(pStatStg->pwcsName, &ptszName);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
// Convert TCHAR to OLECHAR
hr = TStringToOleString(ptszName, &poszName);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
usErr = pdgi->Generate(&cRandomAction, 1, 3);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
switch (cRandomAction)
{
case 1:
{
hr = pIStorage->DestroyElement(poszName);
DH_HRCHECK(hr, TEXT("IStorage::DestoryElement")) ;
if(S_OK == hr)
{
*pfStgDeleted = TRUE;
}
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::DestroyElement failed, hr=0x%lx.\n"),
hr));
}
break;
}
case 2:
case 3:
{
// Generate random new name
hr = GenerateRandomName(
pdgu,
MINLENGTH,
MAXLENGTH,
&ptszNewName);
if(S_OK == hr)
{
// Convert TCHAR to OLECHAR
hr = TStringToOleString(ptszNewName, &poszNewName);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
hr = pIStorage->RenameElement(
poszName,
poszNewName);
DH_HRCHECK(hr, TEXT("IStorage::Rename")) ;
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::RenameElem failed, hr=0x%lx.\n"),
hr));
}
}
if(S_OK == hr)
{
fRenamed = TRUE;
}
break;
}
case 4:
case 5:
case 6:
{
hr = ChangeStreamData(pIStorage, pStatStg, pdgi, pdgu);
DH_HRCHECK(hr, TEXT("ChangeStreamData")) ;
break;
}
}
}
// ----------- flatfile change ---------------
if( StorageIsFlat() &&
(0 == _wcsicmp(poszName, L"CONTENTS")) &&
(STG_E_ACCESSDENIED == hr))
{
DH_LOG((
LOG_INFO,
TEXT("ChangeExistingObject on %ws failed as exp, hr=0x%lx.\n"),
pStatStg->pwcsName,
hr));
hr = S_OK;
}
// ----------- flatfile change ---------------
if((S_OK == hr) &&
(TRUE == fRenamed) &&
(STGTY_STORAGE == pStatStg->type))
{
// Get pMalloc to free pwcsName of STATSTG struct.
if ( S_OK == hr )
{
hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
}
// Free the pStatStg->pwcsName
if((S_OK == hr) && (NULL != pStatStg->pwcsName))
{
pMalloc->Free(pStatStg->pwcsName);
pStatStg->pwcsName = NULL;
}
// Open the storage and stat it, copy name and close it.
if(S_OK == hr)
{
hr = pIStorage->OpenStorage(
poszNewName,
NULL,
STGM_SHARE_EXCLUSIVE | STGM_READ,
NULL,
0,
&pIStorageRenamed);
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::OpenStorage failed, hr=0x%lx.\n"),
hr));
}
}
if(S_OK == hr)
{
hr = pIStorageRenamed->Stat(&statStgRenamed, STATFLAG_DEFAULT);
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::Stat failed, hr=0x%lx.\n"),
hr));
}
}
if(S_OK == hr)
{
pStatStg->pwcsName = statStgRenamed.pwcsName;
}
if(S_OK == hr)
{
ulRef = pIStorageRenamed->Release();
DH_ASSERT(0 == ulRef);
pIStorageRenamed = NULL;
}
}
// Clean up
if(NULL != pMalloc)
{
pMalloc->Release();
pMalloc = NULL;
}
if(NULL != ptszName)
{
delete ptszName;
ptszName = NULL;
}
if(NULL != poszName)
{
delete poszName;
poszName = NULL;
}
if(NULL != ptszNewName)
{
delete ptszNewName;
ptszNewName = NULL;
}
if(NULL != poszNewName)
{
delete poszNewName;
poszNewName = NULL;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: EnumerateAndProcessIStorage
//
// Synopsis: Iterates through a supplied IStorage, recursing and changing
// objects.
//
// Arguments: [pVirtualDF] - Pointer to VirtualDF tree.
// [pvcn] - Pointer to VirtualCtrNode
// [pdgi] - Pointer to data generator integer object
// [pdgu] - Pointer to data generator unicode object
//
// Returns: HResult
//
// History: 29-Jul-1996 Narindk Created
//
// Notes: The VirtualDF tree is not used in this function, because of over
// head of maintaining the tree as in several recursions of the
// DocFile, there will be several random reverts and commits.
//----------------------------------------------------------------------------
HRESULT EnumerateAndProcessIStorage(
LPSTORAGE pIStorage,
DWORD dwStgMode,
DG_INTEGER *pdgi,
DG_STRING *pdgu)
{
HRESULT hr = S_OK;
USHORT usErr = 0;
LPSTORAGE pIStorageChild = NULL;
LPMALLOC pMalloc = NULL;
LPENUMSTATSTG lpEnumStatStg = NULL;
BOOL fStorageDeleted = FALSE;
BOOL fCommit = FALSE;
UINT cRandomAction = 0;
ULONG ulRef = 0;
static USHORT usNumElementEnum= 0;
LPTSTR ptszName = NULL;
LPOLESTR poszName = NULL;
STATSTG statStg;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("EnumerateAndProcessIStorage"));
DH_VDATEPTRIN(pIStorage, IStorage) ;
DH_VDATEPTRIN(pdgi, DG_INTEGER) ;
DH_VDATEPTRIN(pdgu, DG_STRING) ;
DH_ASSERT(NULL != pIStorage);
DH_ASSERT(NULL != pdgi);
DH_ASSERT(NULL != pdgu);
if(S_OK == hr)
{
// Get enumerator
hr = pIStorage->EnumElements(0, NULL, 0, &lpEnumStatStg);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements")) ;
}
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::EnumElements unsuccessful, hr=0x%lx.\n"),
hr));
}
// Get pMalloc which we shall later use to free pwcsName of STATSTG struct.
if ( S_OK == hr )
{
hr = CoGetMalloc(MEMCTX_TASK, &pMalloc);
DH_HRCHECK(hr, TEXT("CoGetMalloc")) ;
}
// Stat on passed storage
if(S_OK == hr)
{
hr = pIStorage->Stat(&statStg, STATFLAG_DEFAULT);
DH_HRCHECK(hr, TEXT("IStorage::Stat")) ;
}
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::Stat unsuccessful, hr=0x%lx.\n"),
hr));
}
// Free the statStg.pwcsName
if(NULL != statStg.pwcsName)
{
pMalloc->Free(statStg.pwcsName);
statStg.pwcsName = NULL;
}
// Loop to get next element
while((S_OK == lpEnumStatStg->Next(1, &statStg, NULL)) &&
(S_OK == hr))
{
// approx 10% chance of changing an element
if(S_OK == hr)
{
usErr = pdgi->Generate(&cRandomAction, 1, 10);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if((S_OK == hr) && (cRandomAction == 1))
{
hr = ChangeExistingObject(
pIStorage,
&statStg,
pdgi,
pdgu,
&fStorageDeleted);
DH_HRCHECK(hr, TEXT("ChangeExistingObject")) ;
fCommit = TRUE;
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("ChangeExistingObject unsuccessful, hr=0x%lx.\n"),
hr));
}
}
// every 1 to 64 objects enumerated, create a new object in current
// storage
if((S_OK == hr) && (0 == usNumElementEnum--))
{
usErr = pdgi->Generate(&usNumElementEnum, 1, 64);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
if(S_OK == hr)
{
hr = CreateNewObject(pIStorage, dwStgMode, pdgi, pdgu);
DH_HRCHECK(hr, TEXT("CreateNewObject")) ;
fCommit = TRUE;
}
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("CreateNewObject unsuccessful, hr=0x%lx.\n"),
hr));
}
}
// Randomly commit the storage 50 % of time if it is not deleted
if((S_OK == hr) && (TRUE == fCommit))
{
usErr = pdgi->Generate(&cRandomAction, 1, 2);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
if((S_OK == hr) && (cRandomAction == 1))
{
// Commit
hr = pIStorage->Commit(STGC_DEFAULT);
// Reset variable
fCommit = FALSE;
}
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::Commit unsuccessful, hr=0x%lx.\n"),
hr));
}
}
// if current storage is an IStorage and it wasn't deleted, then
// recurse into it and process it.
if((S_OK == hr) &&
(STGTY_STORAGE == statStg.type) &&
(FALSE == fStorageDeleted))
{
// Convert WCHAR to TCHAR
hr = OleStringToTString(statStg.pwcsName, &ptszName);
DH_HRCHECK(hr, TEXT("OleStringToTString")) ;
if(S_OK == hr)
{
// Convert TCHAR to OLECHAR
hr = TStringToOleString(ptszName, &poszName);
DH_HRCHECK(hr, TEXT("TStringToOleString")) ;
}
if(S_OK == hr)
{
// Open storage
hr = pIStorage->OpenStorage(
poszName,
NULL,
dwStgMode,
NULL,
0,
&pIStorageChild);
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::OpenStorage unsuccessful, hr=0x%lx.\n"),
hr));
}
}
if(S_OK == hr)
{
// Recurse into child storage and process it recursively.
hr = EnumerateAndProcessIStorage(
pIStorageChild,
dwStgMode,
pdgi,
pdgu);
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("EnumerateAndProcessIStorage failed, hr=0x%lx.\n"),
hr));
}
}
// Close the storage
if(S_OK == hr)
{
ulRef = pIStorageChild->Release();
DH_ASSERT(0 == ulRef);
pIStorageChild = NULL;
}
}
// Free the statStg.pwcsName
if(NULL != statStg.pwcsName)
{
pMalloc->Free(statStg.pwcsName);
statStg.pwcsName = NULL;
}
if(NULL != ptszName)
{
delete ptszName;
ptszName = NULL;
}
if(NULL != poszName)
{
delete poszName;
poszName = NULL;
}
// Reset variables
fStorageDeleted = FALSE;
}
// Randomly commit changes
if(S_OK == hr)
{
usErr = pdgi->Generate(&cRandomAction, 0, 3);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
if(S_OK == hr)
{
if(0 != cRandomAction)
{
hr = pIStorage->Commit(STGC_DEFAULT);
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::Commit unsuccessful, hr=0x%lx.\n"),
hr));
}
}
else
{
hr = pIStorage->Revert();
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("IStorage::Revert unsuccessful, hr=0x%lx.\n"),
hr));
}
}
}
// Cleanup
if (NULL != lpEnumStatStg)
{
ulRef = lpEnumStatStg->Release();
DH_ASSERT(NULL == ulRef);
lpEnumStatStg = NULL;
}
if(NULL != pMalloc)
{
pMalloc->Release();
pMalloc = NULL;
}
return hr;
}
// Function: IsEqualStream
//
// Synopsis: Determines whether the two streams passed as arguments
// are identical in length and content.
//
// Arguments: [pIOrigional] - Origional Stream
// [pICompare] - The stream to compare with Origional
// Stream
//
// Returns: HRESULT
//
// History: July 31, 1996 T-Scottg Created
//
// Note: Although a more elegent solution can be created using
// CRCs, this particular implementation has been designed
// so that it better tests the HGLOBAL implementation
// of IStream
//
//+-------------------------------------------------------------------------
HRESULT IsEqualStream(IStream * pIOrigional, IStream * pICompare)
{
HRESULT hr = S_OK;
BYTE * pbOrigionalBuf = NULL;
BYTE * pbCompareBuf = NULL;
STATSTG statOrigional;
STATSTG statCompare;
LARGE_INTEGER liSeek;
DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("IsEqualStream"));
DH_VDATEPTRIN(pIOrigional, IStream *);
DH_VDATEPTRIN(pICompare, IStream *);
DH_ASSERT(NULL != pIOrigional);
DH_ASSERT(NULL != pICompare);
// Note: STATFLAG_NONAME is passed to IStream::Stat(...).
// This requests that the statistics not include the pwcsName member
// of the STATSTG structure. Hence, there is no need for pwcsName to
// be freed after use.
if (S_OK == hr)
{
hr = pIOrigional->Stat(&statOrigional, STATFLAG_NONAME);
DH_HRCHECK(hr, TEXT("IsEqualStream: pIOrigional->Stat Failure"));
}
if (S_OK == hr)
{
hr = pICompare->Stat(&statCompare, STATFLAG_NONAME);
DH_HRCHECK(hr, TEXT("IsEqualStream: pICompare->Stat Failure"));
}
// If the size of the two streams is not equal, then the streams
// can't be equal.
if (S_OK == hr)
{
if (statOrigional.cbSize.LowPart != statCompare.cbSize.LowPart)
{
hr = S_FALSE;
DH_HRCHECK(hr, TEXT("Stream Sizes Not Equal"));
}
}
// Allocate buffer to hold the stream contents
if (S_OK == hr)
{
pbOrigionalBuf = new BYTE [statOrigional.cbSize.LowPart];
if (NULL == pbOrigionalBuf)
{
hr = E_OUTOFMEMORY;
}
DH_HRCHECK(hr, TEXT("IsEqualStream: new pbOrigionalBuf failed"));
}
// Initialize Buffer
if (S_OK == hr)
{
DH_ASSERT(NULL != pbOrigionalBuf);
memset(pbOrigionalBuf, '\0', statOrigional.cbSize.LowPart);
}
// Allocate buffer to hold the stream contents
if (S_OK == hr)
{
pbCompareBuf = new BYTE [statCompare.cbSize.LowPart];
if (NULL == pbCompareBuf)
{
hr = E_OUTOFMEMORY;
}
DH_HRCHECK(hr, TEXT("IsEqualStream: new pbCompareBuf failed"));
}
// Initialize Buffer
if (S_OK == hr)
{
DH_ASSERT(NULL != pbOrigionalBuf);
memset(pbOrigionalBuf, '\0', statOrigional.cbSize.LowPart);
}
// Set Origional Seek pointer back to beginning of stream
if (S_OK == hr)
{
LISet32(liSeek, 0);
hr = pIOrigional->Seek(liSeek, STREAM_SEEK_SET, NULL);
DH_HRCHECK(hr, TEXT("IStream::Seek Failed"));
}
// Set Compare Seek pointer back to beginning of stream
if (S_OK == hr)
{
LISet32(liSeek, 0);
hr = pICompare->Seek(liSeek, STREAM_SEEK_SET, NULL);
DH_HRCHECK(hr, TEXT("IStream::Seek Failed"));
}
// Read pIOrigional Stream data into buffer.
if (S_OK == hr)
{
hr = pIOrigional->Read( pbOrigionalBuf,
statOrigional.cbSize.LowPart,
NULL );
DH_HRCHECK(hr, TEXT("IsEqualStream: pIOrigional->Read Failure"));
}
// Read pICompare Stream data into buffer.
if (S_OK == hr)
{
hr = pICompare->Read( pbCompareBuf,
statCompare.cbSize.LowPart,
NULL );
DH_HRCHECK(hr, TEXT("IsEqualStream: pICompare->Read Failure"));
}
// Compare memory buffers. If they are not equal, set hr to S_FALSE;
if (S_OK == hr)
{
if (0 != memcmp( pbOrigionalBuf,
pbCompareBuf,
statOrigional.cbSize.LowPart ))
{
hr = S_FALSE;
}
DH_HRCHECK(hr, TEXT("Buffer data not equal"));
}
// Cleanup dynamic memory
if (NULL != pbOrigionalBuf)
{
delete [] pbOrigionalBuf;
pbOrigionalBuf = NULL;
}
if (NULL != pbCompareBuf)
{
delete [] pbCompareBuf;
pbCompareBuf = NULL;
}
// Log if errors occur
if (S_OK != hr)
{
DH_LOG((LOG_FAIL, TEXT("IsEqualStream Failed, hr = 0x%Lx"), hr));
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: ILockBytesWriteTest
//
// Synopsis: Writes data to the provided ILockBytes (calling
// ILockBytes::Flush in between writes). When all data
// is written, the function verifies that the ILockBytes
// is of the correct length.
//
// Arguments: [pILockBytes] - ILockBytes to Write Data to
// [dwSeed] - Seed to Randomizer
// [dwSize] - Byte count of data to write to ILockBytes
//
// Returns: HRESULT
//
// History: Heavily Modified T-Scottg 7/30/96
// Created Venkatesan Viswanathan
//
//+-------------------------------------------------------------------------
HRESULT ILockBytesWriteTest ( ILockBytes * pILockBytes,
DWORD dwSeed,
DWORD dwSize )
{
HRESULT hr = S_OK;
CHAR * pbBuffer = NULL;
DWORD dwWritten = 0;
DWORD dwIdx = 0;
ULARGE_INTEGER li;
STATSTG LockBytesStat;
DG_ASCII dga(dwSeed);
DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("ILockBytesWriteTest"));
DH_VDATEPTRIN(pILockBytes, ILockBytes *);
DH_ASSERT(NULL != pILockBytes);
// Create Data Buffer with Random Data in It
if (0 != (dga.Generate( &pbBuffer,
DG_APRINT_MIN,
DG_APRINT_MAX,
dwSize,
dwSize )))
{
hr = S_FALSE;
DH_HRCHECK(hr, TEXT("dgi.Generate Failed"));
}
// Write Data into ILockBytes
if (S_OK == hr)
{
for (dwIdx = 0; (dwIdx + HGLOBAL_PACKET_SIZE) <= dwSize; dwIdx += HGLOBAL_PACKET_SIZE)
{
ULISet32(li, dwIdx);
hr = pILockBytes->WriteAt( li,
pbBuffer,
HGLOBAL_PACKET_SIZE,
&dwWritten );
DH_HRCHECK(hr, TEXT("pILockBytes->WriteAt Failed"));
// Verify that all of the data was written
if ((S_OK == hr) && (HGLOBAL_PACKET_SIZE != dwWritten))
{
hr = S_FALSE;
DH_HRCHECK(hr, TEXT("Written Data length mismatch"));
}
// Flush ILockBytes to Memory
if (S_OK == hr)
{
hr = pILockBytes->Flush();
DH_HRCHECK(hr, TEXT("pILockBytes->Flush Failed"));
}
// Break out of loop if error occurs
if (S_OK != hr)
{
break;
}
}
}
// Obtain STATSTG structure from ILockBytes
if (S_OK == hr)
{
hr = pILockBytes->Stat( &LockBytesStat,
STATFLAG_NONAME );
DH_HRCHECK(hr, TEXT("pILockBytes->Stat Failed"));
}
// Verify that the ILockBytes is of the correct length
if (S_OK == hr)
{
if (LockBytesStat.cbSize.LowPart != dwSize)
{
hr = S_FALSE;
DH_HRCHECK(hr, TEXT("ILockBytes not of correct length"));
}
}
// Free dynamic memory
if (NULL != pbBuffer)
{
delete [] pbBuffer;
pbBuffer = NULL;
}
// Log if errors occur
if (S_OK != hr)
{
DH_LOG((LOG_FAIL, TEXT("ILockBytesWriteTest Failed, hr = 0x%Lx"), hr));
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: ILockBytesReadTest
//
// Synopsis: Reads data from the provided ILockBytes
//
// Arguments: [pILockBytes] - ILockBytes to Read Data from
// [dwSize] - Byte count of data to read from ILockBytes
//
// Returns: HRESULT
//
// History: Heavily Modified T-Scottg 7/30/96
// Created Venkatesan Viswanathan
//
//+-------------------------------------------------------------------------
HRESULT ILockBytesReadTest (ILockBytes * pILockBytes, DWORD dwSize)
{
HRESULT hr = S_OK;
BYTE * pbBuffer = NULL;
DWORD dwRead = 0;
DWORD dwIndex = 0;
ULARGE_INTEGER li;
DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("ILockBytesReadTest"));
DH_VDATEPTRIN(pILockBytes, ILockBytes *);
DH_ASSERT(NULL != pILockBytes);
// Create buffer to hold data
if (S_OK == hr)
{
pbBuffer = new BYTE[HGLOBAL_PACKET_SIZE];
if (NULL == pbBuffer)
{
hr = E_OUTOFMEMORY;
}
DH_HRCHECK(hr, TEXT("new BYTE call failed"));
}
// Initialize Buffer
if (S_OK == hr)
{
DH_ASSERT(NULL != pbBuffer);
memset(pbBuffer, '\0', HGLOBAL_PACKET_SIZE);
}
// Read Data from ILockBytes
if (S_OK == hr)
{
for (dwIndex = 0; (dwIndex+HGLOBAL_PACKET_SIZE) <= dwSize; dwIndex+=HGLOBAL_PACKET_SIZE)
{
ULISet32(li, dwIndex);
hr = pILockBytes->ReadAt( li,
pbBuffer,
HGLOBAL_PACKET_SIZE,
&dwRead );
DH_HRCHECK(hr, TEXT("pILockBytes->ReadAt Failed"));
// Verify that all of the data was written
if ((S_OK == hr) && (HGLOBAL_PACKET_SIZE != dwRead))
{
hr = S_FALSE;
DH_HRCHECK(hr, TEXT("Read Data length mismatch"));
}
// Break out of loop if error occurs
if (S_OK != hr)
{
break;
}
}
}
// Free dynamic memory
if (NULL != pbBuffer)
{
delete [] pbBuffer;
pbBuffer = NULL;
}
// Log if errors occur
if (S_OK != hr)
{
DH_LOG((LOG_FAIL, TEXT("ILockBytesReadTest Failed, hr = 0x%Lx"), hr));
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: IStreamWriteTest
//
// Synopsis: Writes data to the provided IStream
//
// Arguments: [pIStream] - IStream to Write Data to
// [dwSize] - Byte count of data to write to IStream
//
// Returns: HRESULT
//
// History: Heavily Modified T-Scottg 7/30/96
// Created Venkatesan Viswanathan
//
//+-------------------------------------------------------------------------
HRESULT IStreamWriteTest ( IStream * pIStream,
DWORD dwSeed,
DWORD dwSize )
{
HRESULT hr = S_OK;
CHAR * pbBuffer = NULL;
DWORD dwWritten = 0;
DWORD dwIndex = 0;
LARGE_INTEGER li;
STATSTG StreamStat;
DG_ASCII dga(dwSeed);
DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("IStreamWriteTest"));
DH_VDATEPTRIN(pIStream, IStream *);
DH_ASSERT(NULL != pIStream);
// Create Data Buffer with Random Data in It
if (0 != (dga.Generate( &pbBuffer,
DG_APRINT_MIN,
DG_APRINT_MAX,
dwSize,
dwSize )))
{
hr = S_FALSE;
DH_HRCHECK(hr, TEXT("dgi.Generate Failed"));
}
// Write Data into IStream
if (S_OK == hr)
{
for (dwIndex = 0; (dwIndex+HGLOBAL_PACKET_SIZE) <= dwSize; dwIndex+=HGLOBAL_PACKET_SIZE)
{
// Assign seek index to Large Integer Structure
LISet32(li, dwIndex);
// Seek to correct position in stream
if (S_OK == hr)
{
hr = pIStream->Seek( li,
STREAM_SEEK_SET,
NULL );
DH_HRCHECK(hr, TEXT("pIStream->Seek Failed"));
}
// Write Data to stream
if (S_OK == hr)
{
hr = pIStream->Write( pbBuffer,
HGLOBAL_PACKET_SIZE,
&dwWritten );
DH_HRCHECK(hr, TEXT("pIStream->Write Failed"));
}
// Verify that all of the data was written
if ((S_OK == hr) && (HGLOBAL_PACKET_SIZE != dwWritten))
{
hr = S_FALSE;
DH_HRCHECK(hr, TEXT("Written Data length mismatch"));
}
// Break out of loop if error occurs
if (S_OK != hr)
{
break;
}
}
}
// Obtain STATSTG structure from ILockBytes
if (S_OK == hr)
{
hr = pIStream->Stat( &StreamStat,
STATFLAG_NONAME );
DH_HRCHECK(hr, TEXT("pIStream->Stat Failed"));
}
// Verify that the IStream is of the correct length
if (S_OK == hr)
{
if (StreamStat.cbSize.LowPart != dwSize)
{
hr = S_FALSE;
DH_HRCHECK(hr, TEXT("IStream not of correct length"));
}
}
// Free dynamic memory
if (NULL != pbBuffer)
{
delete [] pbBuffer;
pbBuffer = NULL;
}
// Log if errors occur
if (S_OK != hr)
{
DH_LOG((LOG_FAIL, TEXT("IStreamWriteTest Failed, hr = 0x%Lx"), hr));
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: IStreamReadTest
//
// Synopsis: Reads data from the provided IStream
//
// Arguments: [pIStream] - IStream to Read Data From
// [dwSize] - Byte count of data to read from IStream
//
// Returns: HRESULT
//
// History: Heavily Modified T-Scottg 7/30/96
// Created Venkatesan Viswanathan
//
//+-------------------------------------------------------------------------
HRESULT IStreamReadTest (IStream * pIStream, DWORD dwSize)
{
HRESULT hr = S_OK;
BYTE * pbBuffer = NULL;
DWORD dwWritten = 0;
DWORD dwIndex = 0;
LARGE_INTEGER li;
DH_FUNCENTRY(&hr, DH_LVL_TRACE1, TEXT("IStreamReadTest"));
DH_VDATEPTRIN(pIStream, IStream *);
DH_ASSERT(NULL != pIStream);
// Create buffer to hold data
if (S_OK == hr)
{
pbBuffer = new BYTE[HGLOBAL_PACKET_SIZE];
if (NULL == pbBuffer)
{
hr = E_OUTOFMEMORY;
}
DH_HRCHECK(hr, TEXT("new BYTE call failed"));
}
// Initialize Buffer
if (S_OK == hr)
{
DH_ASSERT(NULL != pbBuffer);
memset(pbBuffer, '\0', HGLOBAL_PACKET_SIZE);
}
// Read Data from IStream
if (S_OK == hr)
{
for (dwIndex = 0; (dwIndex+HGLOBAL_PACKET_SIZE) <= dwSize; dwIndex+=HGLOBAL_PACKET_SIZE)
{
// Assign seek index to Large Integer Structure
LISet32(li, dwIndex);
// Seek to correct position in stream
if (S_OK == hr)
{
hr = pIStream->Seek( li,
STREAM_SEEK_SET,
NULL );
DH_HRCHECK(hr, TEXT("pIStream->Seek Failed"));
}
// Read Data from stream
if (S_OK == hr)
{
hr = pIStream->Read( pbBuffer,
HGLOBAL_PACKET_SIZE,
&dwWritten );
DH_HRCHECK(hr, TEXT("pIStream->Read Failed"));
}
// Verify that all of the data was written
if ((S_OK == hr) && (HGLOBAL_PACKET_SIZE != dwWritten))
{
hr = S_FALSE;
DH_HRCHECK(hr, TEXT("Written Data length mismatch"));
}
// Break out of loop if error occurs
if (S_OK != hr)
{
break;
}
}
}
// Free dynamic memory
if (NULL != pbBuffer)
{
delete [] pbBuffer;
pbBuffer = NULL;
}
// Log if errors occur
if (S_OK != hr)
{
DH_LOG((LOG_FAIL, TEXT("IStreamReadTest Failed, hr = 0x%Lx"), hr));
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: TraverseDocFileAndWriteOrReadSNB
//
// Synopsis: Traverse DocFile one level and either writes/reads SNB
//
// Effects: Traverse the children storages and streams of root storage,
// when fSelectObjectsToExclude == TRUE, then for each object
// returned, there is a 50% chance that the object name will
// be added to an SNB block of names to exclude upon reinstantiation,
// when fIllegitFlag == TRUE, then there is a 50% change that a
// bogus name instead of ture object name will be generated and
// be added into SNB block. When fSelectObjectsToExclude == FALSE,
// then each object name returned is checked to see if it exists in
// the SNB. If an object name is returned that *is* in the SNB,
// that object is checked to ensure that its contents are empty.
//
// Arguments: [pvcn] - Pointer to VirtualCtrNode
// [pdgi] - Pointer to Data Integer object
// [pdgu] - Pointer to Data Unicode object
// [dwStgMode] - Access Mode for the storage
// [snbNamesToExclude] - SNB specifying elements to be excluded
// [fIllegitFlag] - Indicating whether it's a legit or illegit
// limited test: if TRUE, it is a illegit one,
// otherwise, it is a legit one.
// [fSelectObjectsToExclude] - if TRUE, the function builds the
// SNB, otherwise the function checks
// names against the SNB.
//
// Returns: HResult
//
// History: 29-Jul-1996 JiminLi Created
//
//-----------------------------------------------------------------------------
HRESULT TraverseDocfileAndWriteOrReadSNB(
VirtualCtrNode *pvcn,
DG_INTEGER *pdgi,
DG_STRING *pdgu,
DWORD dwStgMode,
SNB snbNamesToExclude,
BOOL fIllegitFlag,
BOOL fSelectObjectsToExclude)
{
HRESULT hr = S_OK;
ULONG culRandomExclude = 0;
ULONG culRandomBogus = 0;
ULONG culThisName = 0;
ULONG ulRef = 0;
ULONG ulStmLength = 0;
USHORT usErr = 0;
LPTSTR ptszStgName = NULL;
LPTSTR ptszBogusName = NULL;
LPTSTR ptszStmName = NULL;
LPTSTR pTStr = NULL;
VirtualCtrNode *pvcnTrav = NULL;
VirtualStmNode *pvsnTrav = NULL;
LPENUMSTATSTG lpEnumStatStg = NULL;
STATSTG *pstatStgEnum = NULL;
BOOL fLocalPass = TRUE;
LARGE_INTEGER liZero;
ULARGE_INTEGER uli;
SNB snbIndex;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("TraverseDocfileAndWriteOrReadSNB"));
DH_VDATEPTRIN(pvcn, VirtualCtrNode);
DH_VDATEPTRIN(pdgi, DG_INTEGER);
DH_VDATEPTRIN(pdgu, DG_STRING);
DH_ASSERT(NULL != pvcn);
DH_ASSERT(NULL != pdgi);
DH_ASSERT(NULL != pdgu);
// pointer SNB to start of global SNB
snbIndex = snbNamesToExclude;
// First traverse the child storages of the root storage
pvcnTrav = pvcn->GetFirstChildVirtualCtrNode();
while ((S_OK == hr) && (NULL != pvcnTrav))
{
if (TRUE == fSelectObjectsToExclude)
{
// 50% chance of adding name to SNB for exclude on reinstantiation
// when a name is added to the SNB, memory is allocated for that
// name, the name of current VirtualCtrNode name is copied in, and
// the SNB index is incremented to point to the location for the
// next OLECHAR string.
usErr = pdgi->Generate(&culRandomExclude, 1, 100);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
if ((S_OK == hr) && (culRandomExclude > 50))
{
// 50% chance of placing a bogus name in the snbExclude block
ptszStgName = pvcnTrav->GetVirtualCtrNodeName();
DH_ASSERT(NULL != ptszStgName);
culThisName = _tcslen(ptszStgName);
if (S_OK == hr)
{
if (TRUE == fIllegitFlag)
{
// if it is a illegit test, then 50% chance that
// a bogus name will generated instead of true
// object name
usErr = pdgi->Generate(&culRandomBogus, 1, 100);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
else
{
// if it is a legit test, then make sure culRandomBogus
// greater than 50,i.e. use the true object name
culRandomBogus = 100;
}
}
if (S_OK == hr)
{
if (culRandomBogus > 50)
{
hr = TStringToOleString(ptszStgName, snbIndex);
DH_HRCHECK(hr, TEXT("TStringToOleString"));
}
else
{
hr = GenerateRandomString(
pdgu,
culThisName,
culThisName,
&ptszBogusName);
DH_HRCHECK(hr, TEXT("GenerateRandomString"));
if (S_OK == hr)
{
hr = TStringToOleString(ptszBogusName, snbIndex);
DH_HRCHECK(hr, TEXT("TStringToOleString"));
}
if (NULL != ptszBogusName)
{
delete []ptszBogusName;
ptszBogusName = NULL;
}
}
}
snbIndex++;
}
}
else
{
// Starting with the first entry in the SNB, loop through and
// compare the current name of the VirtualCtrNode against
// each name in the SNB. If there is a match, check the
// storage and verify that its contents are empty.
ptszStgName = pvcnTrav->GetVirtualCtrNodeName();
snbIndex = snbNamesToExclude;
hr = OleStringToTString(*snbIndex, &pTStr);
DH_HRCHECK(hr, TEXT("OleStringToTString"));
while ((S_OK == hr) && (*snbIndex))
{
if (0 == _tcscmp(pTStr, ptszStgName))
{
hr = pvcnTrav->Open(NULL, dwStgMode, NULL, 0);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::Open"));
if (S_OK == hr)
{
hr = pvcnTrav->EnumElements(0, NULL, 0, &lpEnumStatStg);
DH_HRCHECK(hr, TEXT("VirtualCtrNode::EnumElements"));
}
// Allocate memory for STASTG structure
if (S_OK == hr)
{
pstatStgEnum = (STATSTG *) new STATSTG;
if (NULL == pstatStgEnum)
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
if (S_OK == lpEnumStatStg->Next(1, pstatStgEnum, NULL))
{
DH_LOG((
LOG_INFO,
TEXT("Should no objects in excluded Stg.\n")));
fLocalPass = FALSE;
}
}
if (NULL != pstatStgEnum)
{
delete [] pstatStgEnum;
pstatStgEnum = NULL;
}
if (NULL != lpEnumStatStg)
{
ulRef = lpEnumStatStg->Release();
DH_ASSERT(NULL == ulRef);
lpEnumStatStg = NULL;
}
break;
}
snbIndex++;
}
}
if (NULL != pTStr)
{
delete []pTStr;
pTStr = NULL;
}
if ((S_OK == hr) && (TRUE == fLocalPass))
{
pvcnTrav = pvcnTrav->GetFirstSisterVirtualCtrNode();
}
else
{
break;
}
}
// Now, traverse the child streams of the root storage
pvsnTrav = pvcn->GetFirstChildVirtualStmNode();
while ((S_OK == hr) && (TRUE == fLocalPass) && (NULL != pvsnTrav))
{
if (TRUE == fSelectObjectsToExclude)
{
// 50% chance of adding name to SNB for exclude on reinstantiation
// when a name is added to the SNB, memory is allocated for that
// name, the name of current VirtualStmNode name is copied in, and
// the SNB index is incremented to point to the location for the
// next OLECHAR string.
usErr = pdgi->Generate(&culRandomExclude, 1, 100);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
if ((S_OK == hr) && (culRandomExclude > 50))
{
// 50% chance of placing a bogus name in the snbExclude block
ptszStmName = pvsnTrav->GetVirtualStmNodeName();
DH_ASSERT(NULL != ptszStmName);
culThisName = _tcslen(ptszStmName);
if (S_OK == hr)
{
if (TRUE == fIllegitFlag)
{
// if it is a illegit test, then 50% chance that
// a bogus name will generated instead of true
// object name
usErr = pdgi->Generate(&culRandomBogus, 1, 100);
if (DG_RC_SUCCESS != usErr)
{
hr = E_FAIL;
}
}
else
{
// if it is a legit test, then make sure culRandomBogus
// greater than 50,i.e. use the true object name
culRandomBogus = 100;
}
}
if (S_OK == hr)
{
if (culRandomBogus > 50)
{
hr = TStringToOleString(ptszStmName, snbIndex);
DH_HRCHECK(hr, TEXT("TStringToOleString"));
}
else
{
hr = GenerateRandomString(
pdgu,
culThisName,
culThisName,
&ptszBogusName);
DH_HRCHECK(hr, TEXT("GenerateRandomString"));
if (S_OK == hr)
{
hr = TStringToOleString(ptszBogusName, snbIndex);
DH_HRCHECK(hr, TEXT("TStringToOleString"));
}
if (NULL != ptszBogusName)
{
delete []ptszBogusName;
ptszBogusName = NULL;
}
}
}
snbIndex++;
}
}
else
{
// Starting with the first entry in the SNB, loop through and
// compare the current name of the VirtualStmNode against
// each name in the SNB. If there is a match, check the
// stream and verify that its length is zero.
snbIndex = snbNamesToExclude;
ptszStmName = pvsnTrav->GetVirtualStmNodeName();
hr = OleStringToTString(*snbIndex, &pTStr);
DH_HRCHECK(hr, TEXT("OleStringToTString"));
while ((S_OK == hr) && (*snbIndex))
{
if (0 == _tcscmp(pTStr, ptszStmName))
{
LISet32(liZero, 0L);
hr = pvsnTrav->Open(
NULL,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
0);
DH_HRCHECK(hr, TEXT("VirutalStmNode::Open"));
if (S_OK == hr)
{
hr = pvsnTrav->Seek(liZero, STREAM_SEEK_END, &uli);
ulStmLength = ULIGetLow(uli);
DH_HRCHECK(hr, TEXT("VirtualStmNode::Seek")) ;
}
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("VirtualStmNode::Seek not Ok, hr=0x%lx\n"),
hr));
}
if (0 != ulStmLength)
{
DH_LOG((
LOG_INFO,
TEXT("The length of excluded Stm should be 0.\n")));
fLocalPass = FALSE;
}
break;
}
snbIndex++;
}
}
if (NULL != pTStr)
{
delete []pTStr;
pTStr = NULL;
}
if ((S_OK == hr) && (TRUE == fLocalPass))
{
pvsnTrav = pvsnTrav->GetFirstSisterVirtualStmNode();
}
else
{
break;
}
}
if ((S_OK == hr) && (TRUE == fSelectObjectsToExclude))
{
// Last entry in SNB block is NIL to designate the end
*snbIndex = NULL;
}
if (FALSE == fLocalPass)
{
hr = E_FAIL;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: GetSeedFromCmdLineArgs
//
// Synopsis: Gets the seed value from command line args if required for test
//
// Arguments: [argc] - arg count
// [argv] - arg list
//
// Returns: ULONG
//
// History: 2-Aug-1996 Narindk Made into separate func.
//
//-----------------------------------------------------------------------------
ULONG GetSeedFromCmdLineArgs(int argc, char *argv[])
{
HRESULT hr = S_OK ;
ULONG ulSeed = 0;
CCmdline CCmdlineArgs(argc, argv);
CUlongCmdlineObj Seed(OLESTR("seed"), OLESTR(""), OLESTR("0")) ;
CBaseCmdlineObj *CArgList[] = {&Seed} ;
DH_FUNCENTRY(&hr, DH_LVL_DFLIB, _TEXT("GetSeedFromCmdLineArgs"));
// Verify that the CCmdlineArgs object was constructed without
// problems
if (CMDLINE_NO_ERROR != CCmdlineArgs.QueryError())
{
hr = E_FAIL ;
}
// Parse Commandline Arguments
if (S_OK == hr)
{
if (CMDLINE_NO_ERROR != CCmdlineArgs.Parse(CArgList,
sizeof(CArgList) / sizeof(CArgList[0]),
FALSE) )
{
hr = E_FAIL ;
}
}
// Obtain Seed from CommandLine
if (S_OK == hr)
{
if ( ulSeed != *(Seed.GetValue()) )
{
ulSeed = *(Seed.GetValue());
}
}
return ulSeed;
}
//----------------------------------------------------------------------------
//
// Function: StreamCreate
//
// Synopsis: Create a stream or a file in a docfile or C-runtime condition,
// and record the time of creation in both cases: the stream or
// file existing and not existing.
//
// Arguments: [dwRootMode] - Access modes to root storage
// [pdgu] - Pointer to Data Unicode object
// [usTimeIndex] - Indicate which category this test is
// [dwFlags] - Indicate DOCFILE or RUNTIME file and also
// the stream or file exists or not
// [usNumCreates] - Indicate this is usNumCreates'th creation
//
// Returns: HResult
//
// History: 8-Aug-1996 JiminLi Created
//
//-----------------------------------------------------------------------------
HRESULT StreamCreate(
DWORD dwRootMode,
DG_STRING *pdgu,
USHORT usTimeIndex,
DWORD dwFlags,
USHORT usNumCreates)
{
HRESULT hr = S_OK;
LPSTORAGE pstgRoot = NULL;
LPSTREAM pstmStream = NULL;
LPOLESTR pOleName = NULL;
ULONG bufferSize = 0;
FILE *fileFile = NULL;
DWORD StartTime = 0;
DWORD EndTime = 0;
DWORD dwModifiers = 0;
ULONG ulRef = 0;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("StreamCreate"));
DH_VDATEPTRIN(pdgu, DG_STRING);
DH_ASSERT(NULL != pdgu);
while ((S_OK == hr) && (0 < usNumCreates))
{
usNumCreates--;
hr = GenerateRandomName(
pdgu,
MINLENGTH,
MAXLENGTH,
&ptszNames[0]);
DH_HRCHECK(hr, TEXT("GenerateRandomName"));
if ((S_OK == hr) && (dwFlags & DOCFILE))
{
// Create a docfile
hr = TStringToOleString(ptszNames[0], &pOleName);
DH_HRCHECK(hr, TEXT("TStringToOleString"));
if (S_OK == hr)
{
hr = StgCreateDocfile(
pOleName,
dwRootMode | STGM_CREATE,
0,
&pstgRoot);
DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
}
}
if ((S_OK == hr) && (dwFlags & EXIST))
{
dwFlags |= CREATE;
if (dwFlags & DOCFILE)
{
// Create existing stream
if (S_OK == hr)
{
hr = pstgRoot->CreateStream(
pOleName,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
0,
0,
&pstmStream);
DH_HRCHECK(hr, TEXT("IStorage::CreateStream"));
}
if (S_OK == hr)
{
ulRef = pstmStream->Release();
DH_ASSERT(0 == ulRef);
pstmStream = NULL;
}
}
else
{
#if (defined _NT1X_ && !defined _MAC)
// Create existing file
fileFile = _wfopen(ptszNames[0],TEXT("w"));
if (NULL == fileFile)
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
}
#else
fileFile = fopen(ptszNames[0],"w");
if (NULL == fileFile)
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
}
#endif
if (S_OK == hr)
{
fclose(fileFile);
}
}
}
if (S_OK == hr)
{
dwModifiers |= (dwFlags & CREATE ? STGM_CREATE : STGM_FAILIFTHERE);
if (dwFlags & DOCFILE)
{
if (S_OK == hr)
{
GET_TIME(StartTime);
hr = pstgRoot->CreateStream(
pOleName,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | dwModifiers,
0,
0,
&pstmStream);
GET_TIME(EndTime);
Time[usTimeIndex].plDocfileTime[usNumCreates] =
DiffTime(EndTime, StartTime);
DH_HRCHECK(hr, TEXT("IStorage::CreateStream"));
}
if ((S_OK == hr) && (dwFlags & COMMIT))
{
hr = pstgRoot->Commit(STGC_DEFAULT);
DH_HRCHECK(hr, TEXT("IStorage::Commit"));
}
if (S_OK == hr)
{
ulRef = pstmStream->Release();
DH_ASSERT(0 == ulRef);
pstmStream = NULL;
ulRef = pstgRoot->Release();
DH_ASSERT(0 == ulRef);
pstgRoot = NULL;
}
if (NULL != pOleName)
{
delete []pOleName;
pOleName = NULL;
}
}
else
{
#if (defined _NT1X_ && !defined _MAC)
GET_TIME(StartTime);
fileFile = _wfopen(ptszNames[0], TEXT("w+b"));
GET_TIME(EndTime);
#else
GET_TIME(StartTime);
fileFile = fopen(ptszNames[0], "w+b");
GET_TIME(EndTime);
#endif
Time[usTimeIndex].plRuntimeTime[usNumCreates] =
DiffTime(EndTime,StartTime);
if (NULL == fileFile)
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
fclose(fileFile);
}
}
}
if (NULL != ptszNames[0])
{
if(FALSE == DeleteFile(ptszNames[0]))
{
hr = HRESULT_FROM_WIN32(GetLastError()) ;
DH_HRCHECK(hr, TEXT("DeleteFile")) ;
}
}
if (NULL != ptszNames[0])
{
delete []ptszNames[0];
ptszNames[0] = NULL;
}
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: DocfileCreate
//
// Synopsis: Create a docfile is similar to creating a directory in C-runtime,
// this test measures the time in several cases of creating a docfile,
// like create a existing or non-exist or NULL docfile. RUNTIME only
// support creating a non-exist directory.
//
// Arguments: [dwRootMode] - Access modes to root storage
// [pdgu] - Pointer to Data Unicode object
// [usTimeIndex] - Indicate which category this test is
// [dwFlags] - Indicate DOCFILE or RUNTIME file and also
// the stream or file exists or not
// [usNumCreates] - Indicate this is usNumCreates'th creation
//
// Returns: HResult
//
// History: 6-Aug-1996 JiminLi Created
//
//-----------------------------------------------------------------------------
HRESULT DocfileCreate(
DWORD dwRootMode,
DG_STRING *pdgu,
USHORT usTimeIndex,
DWORD dwFlags,
USHORT usNumCreates)
{
HRESULT hr = S_OK;
LPSTORAGE pstgRoot = NULL;
LPSTREAM pstmStream = NULL;
LPOLESTR pOleName = NULL;
LPTSTR ptTmpName = NULL;
LPTSTR ptszCurDir = NULL;
int Temp = 0;
ULONG bufferSize = 0;
DWORD StartTime = 0;
DWORD EndTime = 0;
DWORD dwModifiers = 0;
ULONG ulRef = 0;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("DocfileCreate"));
DH_VDATEPTRIN(pdgu, DG_STRING);
DH_ASSERT(NULL != pdgu);
while ((S_OK == hr) && (0 < usNumCreates))
{
usNumCreates--;
if ((dwFlags & DOCFILE) && (dwFlags & NONAME))
{
ptszNames[0] = NULL;
}
else
{
hr = GenerateRandomName(
pdgu,
MINLENGTH,
MAXLENGTH,
&ptszNames[0]);
DH_HRCHECK(hr, TEXT("GenerateRandomName"));
if (S_OK == hr)
{
hr = TStringToOleString(ptszNames[0], &pOleName);
DH_HRCHECK(hr, TEXT("TStringToOleString"));
}
}
if ((S_OK == hr) && (dwFlags & DOCFILE) && (dwFlags & EXIST)
&& ~(dwFlags & NONAME))
{
// Create a existing docfile
dwFlags |= CREATE;
hr = StgCreateDocfile(
pOleName,
dwRootMode | STGM_CREATE,
0,
&pstgRoot);
DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
if (S_OK == hr)
{
ulRef = pstgRoot->Release();
DH_ASSERT(0 == ulRef);
pstgRoot = NULL;
}
}
if (S_OK == hr)
{
dwModifiers |= (dwFlags & CREATE ? STGM_CREATE : STGM_FAILIFTHERE);
if (dwFlags & DOCFILE)
{
GET_TIME(StartTime);
hr = StgCreateDocfile(
pOleName,
dwRootMode | dwModifiers,
0,
&pstgRoot);
GET_TIME(EndTime);
Time[usTimeIndex].plDocfileTime[usNumCreates] =
DiffTime(EndTime, StartTime);
DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
if ((S_OK == hr) && (dwFlags & COMMIT))
{
hr = pstgRoot->Commit(STGC_DEFAULT);
DH_HRCHECK(hr, TEXT("IStorage::Commit"));
}
// if NONAME, we need to get the name so we can
// delete the file when we are done.
if (S_OK == hr && (dwFlags & NONAME))
{
STATSTG statstg;
hr = pstgRoot->Stat (&statstg, STATFLAG_DEFAULT);
DH_HRCHECK (hr, TEXT("IStorage::Stat"));
if (S_OK == hr)
{
//retrieve the filename
OleStringToTString (statstg.pwcsName, &ptTmpName);
DH_HRCHECK (hr, TEXT("OleStringToTString"));
//now that we have the name, it up from statstg
CoTaskMemFree (statstg.pwcsName);
}
}
if (S_OK == hr)
{
ulRef = pstgRoot->Release();
DH_ASSERT(0 == ulRef);
pstgRoot = NULL;
}
}
else
{
if (~(dwFlags & NONAME) && ~(dwFlags & EXIST))
{
#if (defined _NT1X_ && !defined _MAC)
ptszCurDir = (TCHAR *) new TCHAR[MAX_PATH_LENGTH];
if (NULL == ptszCurDir)
{
hr = E_OUTOFMEMORY;
}
if (S_OK == hr)
{
memset(ptszCurDir,'\0',MAX_PATH_LENGTH*sizeof(TCHAR));
if (NULL == _wgetcwd(ptszCurDir, MAX_PATH_LENGTH))
{
DH_LOG((
LOG_INFO,
TEXT("Error in getting Current directory\n")));
hr = E_FAIL;
}
}
if (S_OK == hr)
{
GET_TIME(StartTime);
Temp = _wmkdir(ptszNames[0]);
GET_TIME(EndTime);
Time[usTimeIndex].plRuntimeTime[usNumCreates] =
DiffTime(EndTime, StartTime);
if (0 != Temp)
{
DH_LOG((
LOG_INFO,
TEXT("Error in creating a directory\n")));
hr = E_FAIL;
}
}
// Clean up
if (S_OK == hr)
{
if (0 != _wchdir(ptszCurDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
if (0 != _wrmdir(ptszNames[0]))
{
DH_LOG((
LOG_INFO,
TEXT("Error in removing directory\n")));
hr = E_FAIL;
}
}
if (NULL != ptszCurDir)
{
delete []ptszCurDir;
ptszCurDir = NULL;
}
}
#else
ptszCurDir = (TCHAR *) new TCHAR[MAX_PATH_LENGTH];
if (NULL == ptszCurDir)
{
hr = E_OUTOFMEMORY;
}
if (S_OK == hr)
{
memset(ptszCurDir,'\0',MAX_PATH_LENGTH*sizeof(TCHAR));
if (NULL == _getcwd(ptszCurDir, MAX_PATH_LENGTH))
{
DH_LOG((
LOG_INFO,
TEXT("Error in getting Current directory\n")));
hr = E_FAIL;
}
}
if (S_OK == hr)
{
GET_TIME(StartTime);
Temp = _mkdir(ptszNames[0]);
GET_TIME(EndTime);
Time[usTimeIndex].plRuntimeTime[usNumCreates] =
DiffTime(EndTime, StartTime);
if (0 != Temp)
{
DH_LOG((
LOG_INFO,
TEXT("Error in creating a directory\n")));
hr = E_FAIL;
}
}
// Clean up
if (S_OK == hr)
{
if (0 != _chdir(ptszCurDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
if (0 != _rmdir(ptszNames[0]))
{
DH_LOG((
LOG_INFO,
TEXT("Error in removing directory\n")));
hr = E_FAIL;
}
}
if (NULL != ptszCurDir)
{
delete []ptszCurDir;
ptszCurDir = NULL;
}
}
#endif
}
else
{
DH_LOG((
LOG_INFO,
TEXT("RUNTIME not supported this function\n")));
hr = E_FAIL;
}
}
}
// Clean up
if (NULL != pOleName)
{
delete []pOleName;
pOleName = NULL;
}
if ((NULL != ptszNames[0]) && (dwFlags & DOCFILE))
{
if (FALSE == DeleteFile(ptszNames[0]))
{
hr = HRESULT_FROM_WIN32(GetLastError()) ;
DH_HRCHECK(hr, TEXT("DeleteFile")) ;
}
}
else if (NULL != ptTmpName)
{
if (FALSE == DeleteFile(ptTmpName))
{
hr = HRESULT_FROM_WIN32(GetLastError()) ;
DH_HRCHECK(hr, TEXT("DeleteFile")) ;
}
delete []ptTmpName;
ptTmpName = NULL;
}
if (NULL != ptszNames[0])
{
delete []ptszNames[0];
ptszNames[0] = NULL;
}
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: StreamOpen
//
// Synopsis: Open a stroage and its child stream is similar to find a directory
// and open a file in this directory in C-runtime. This test measures
// the time in opening both storage and stream or opening stream only
// and also the time in corresponding C-runtime operations.
//
// Arguments: [dwRootMode] - Access modes to root storage
// [pdgu] - Pointer to Data Unicode object
// [usTimeIndex] - Indicate which category this test is
// [dwFlags] - Indicate DOCFILE or RUNTIME file and also
// open both storage and stream or not.
// [usNumOpens] - Indicate this is usNumOpens'th opening
//
// Returns: HResult
//
// History: 9-Aug-1996 JiminLi Created
//
//-----------------------------------------------------------------------------
HRESULT StreamOpen(
DWORD dwRootMode,
DG_STRING *pdgu,
USHORT usTimeIndex,
DWORD dwFlags,
USHORT usNumOpens)
{
HRESULT hr = S_OK;
LPSTORAGE pstgRoot = NULL;
LPSTREAM pstmStream = NULL;
LPOLESTR pOleName = NULL;
LPTSTR ptszCurDir = NULL;
LPTSTR ptszNewDir = NULL;
ULONG bufferSize = 0;
DWORD StartTime = 0;
DWORD EndTime = 0;
FILE *fileFile = NULL;
ULONG ulRef = 0;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("StreamOpen"));
DH_VDATEPTRIN(pdgu, DG_STRING);
DH_ASSERT(NULL != pdgu);
while ((S_OK == hr) && (0 < usNumOpens))
{
usNumOpens--;
hr = GenerateRandomName(
pdgu,
MINLENGTH,
MAXLENGTH,
&ptszNames[0]);
DH_HRCHECK(hr, TEXT("GenerateRandomName"));
if (S_OK == hr)
{
hr = TStringToOleString(ptszNames[0], &pOleName);
DH_HRCHECK(hr, TEXT("TStringToOleString"));
}
if (S_OK == hr)
{
if (dwFlags & DOCFILE)
{
// Create a root storage and a stream inside it.
hr = StgCreateDocfile(
pOleName,
dwRootMode | STGM_CREATE,
0,
&pstgRoot);
DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
if (S_OK == hr)
{
hr = pstgRoot->CreateStream(
pOleName,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
0,
0,
&pstmStream);
DH_HRCHECK(hr, TEXT("IStorage::CreateStream"));
}
if ((S_OK == hr) && (dwFlags & COMMIT))
{
hr = pstgRoot->Commit(STGC_DEFAULT);
DH_HRCHECK(hr, TEXT("IStorage::Commit"));
}
if (S_OK == hr)
{
ulRef = pstmStream->Release();
DH_ASSERT(0 == ulRef);
pstmStream = NULL;
ulRef = pstgRoot->Release();
DH_ASSERT(0 == ulRef);
pstgRoot = NULL;
}
}
else
{
// Create a directory and a file under it.
ptszCurDir = (TCHAR *) new TCHAR[MAX_PATH_LENGTH];
ptszNewDir = (TCHAR *) new TCHAR[MAX_PATH_LENGTH];
if ((NULL == ptszCurDir) || (NULL == ptszNewDir))
{
hr = E_OUTOFMEMORY;
}
if (S_OK == hr)
{
memset(ptszCurDir,'\0',MAX_PATH_LENGTH * sizeof(TCHAR));
memset(ptszNewDir,'\0',MAX_PATH_LENGTH * sizeof(TCHAR));
}
#if (defined _NT1X_ && !defined _MAC)
if (NULL == _wgetcwd(ptszCurDir, MAX_PATH_LENGTH))
{
DH_LOG((
LOG_INFO,
TEXT("Error in getting Current directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
if (0 != _wmkdir(ptszNames[0]))
{
DH_LOG((
LOG_INFO,
TEXT("Error in creating a directory\n")));
hr = E_FAIL;
}
}
if (S_OK == hr)
{
_tcscpy(ptszNewDir, ptszCurDir);
_tcscat(ptszNewDir, TEXT("\\"));
_tcscat(ptszNewDir, ptszNames[0]);
}
if (S_OK == hr)
{
if (0 != _wchdir(ptszNewDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
}
if (S_OK == hr)
{
fileFile = _wfopen(ptszNames[0],TEXT("w"));
if (NULL == fileFile)
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
}
}
#else
if (NULL == _getcwd(ptszCurDir, MAX_PATH_LENGTH))
{
DH_LOG((
LOG_INFO,
TEXT("Error in getting Current directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
if (0 != _mkdir(ptszNames[0]))
{
DH_LOG((
LOG_INFO,
TEXT("Error in creating a directory\n")));
hr = E_FAIL;
}
}
if (S_OK == hr)
{
_tcscpy(ptszNewDir, ptszCurDir);
_tcscat(ptszNewDir, TEXT("\\"));
_tcscat(ptszNewDir, ptszNames[0]);
}
if (S_OK == hr)
{
if (0 != _chdir(ptszNewDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
}
if (S_OK == hr)
{
fileFile = fopen(ptszNames[0],"w");
if (NULL == fileFile)
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
}
}
#endif
if (S_OK == hr)
{
fclose(fileFile);
}
}
}
if (S_OK == hr)
{
if (dwFlags & DOCFILE)
{
if (dwFlags & OPENBOTH)
{
GET_TIME(StartTime);
hr = StgOpenStorage(
pOleName,
NULL,
dwRootMode,
NULL,
0,
&pstgRoot);
if (S_OK == hr)
{
hr = pstgRoot->OpenStream(
pOleName,
NULL,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
0,
&pstmStream);
GET_TIME(EndTime);
Time[usTimeIndex].plDocfileTime[usNumOpens] =
DiffTime(EndTime, StartTime);
}
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("Open storage or stream, hr=0x%lx\n"),
hr));
}
}
else
{
hr = StgOpenStorage(
pOleName,
NULL,
dwRootMode,
NULL,
0,
&pstgRoot);
if (S_OK == hr)
{
GET_TIME(StartTime);
hr = pstgRoot->OpenStream(
pOleName,
NULL,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
0,
&pstmStream);
GET_TIME(EndTime);
Time[usTimeIndex].plDocfileTime[usNumOpens] =
DiffTime(EndTime, StartTime);
}
if (S_OK != hr)
{
DH_LOG((
LOG_INFO,
TEXT("Open storage or stream, hr=0x%lx\n"),
hr));
}
}
if (S_OK == hr)
{
ulRef = pstmStream->Release();
DH_ASSERT(0 == ulRef);
pstmStream = NULL;
ulRef = pstgRoot->Release();
DH_ASSERT(0 == ulRef);
pstgRoot = NULL;
}
}
else
{
if (dwFlags & OPENBOTH)
{
#if (defined _NT1X_ && !defined _MAC)
GET_TIME(StartTime);
if (0 != _wchdir(ptszNewDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
fileFile = _wfopen(ptszNames[0],TEXT("r+"));
GET_TIME(EndTime);
Time[usTimeIndex].plRuntimeTime[usNumOpens] =
DiffTime(EndTime, StartTime);
if (NULL == fileFile)
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
}
}
#else
GET_TIME(StartTime);
if (0 != _chdir(ptszNewDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
fileFile = fopen(ptszNames[0],"r+");
GET_TIME(EndTime);
Time[usTimeIndex].plRuntimeTime[usNumOpens] =
DiffTime(EndTime, StartTime);
if (NULL == fileFile)
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
}
}
#endif
if (S_OK == hr)
{
fclose(fileFile);
}
}
else
{
#if (defined _NT1X_ && !defined _MAC)
if (0 != _wchdir(ptszNewDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
GET_TIME(StartTime);
fileFile = _wfopen(ptszNames[0],TEXT("r+"));
GET_TIME(EndTime);
Time[usTimeIndex].plRuntimeTime[usNumOpens] =
DiffTime(EndTime, StartTime);
if (NULL == fileFile)
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
}
}
#else
if (0 != _chdir(ptszNewDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
GET_TIME(StartTime);
fileFile = fopen(ptszNames[0],"r+");
GET_TIME(EndTime);
Time[usTimeIndex].plRuntimeTime[usNumOpens] =
DiffTime(EndTime, StartTime);
if (NULL == fileFile)
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
}
}
#endif
if (S_OK == hr)
{
fclose(fileFile);
}
}
}
}
// Clean up
if ((S_OK == hr) && (dwFlags & RUNTIME))
{
// Remove the directory and the file under it
if ((S_OK == hr) && (NULL != ptszNames[0]))
{
if (FALSE == DeleteFile(ptszNames[0]))
{
hr = HRESULT_FROM_WIN32(GetLastError()) ;
DH_HRCHECK(hr, TEXT("DeleteFile")) ;
}
}
#if (defined _NT1X_ && !defined _MAC)
if (0 != _wchdir(ptszCurDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
if (0 != _wrmdir(ptszNames[0]))
{
DH_LOG((
LOG_INFO,
TEXT("Error in removing directory\n")));
hr = E_FAIL;
}
}
#else
if (0 != _chdir(ptszCurDir))
{
DH_LOG((
LOG_INFO,
TEXT("Error in changing directory\n")));
hr = E_FAIL;
}
if (S_OK == hr)
{
if (0 != _rmdir(ptszNames[0]))
{
DH_LOG((
LOG_INFO,
TEXT("Error in removing directory\n")));
hr = E_FAIL;
}
}
#endif
if (NULL != ptszNewDir)
{
delete []ptszNewDir;
ptszNewDir = NULL;
}
if (NULL != ptszCurDir)
{
delete []ptszCurDir;
ptszCurDir = NULL;
}
}
if (NULL != pOleName)
{
delete []pOleName;
pOleName = NULL;
}
if ((NULL != ptszNames[0]) && (dwFlags & DOCFILE))
{
if (FALSE == DeleteFile(ptszNames[0]))
{
hr = HRESULT_FROM_WIN32(GetLastError()) ;
DH_HRCHECK(hr, TEXT("DeleteFile")) ;
}
}
if (NULL != ptszNames[0])
{
delete []ptszNames[0];
ptszNames[0] = NULL;
}
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: WriteStreamInSameSizeChunks
//
// Synopsis: Create and open all the docfiles or C-runtime files, and then
// write data in the same size chunks to docfiles or C-runtime
// files, also record the time of the all the write operations
// in Time[]. Each WRITE could be RANDOM_WRITE or SEQUENTIAL_WRITE.
//
// Arguments: [dwRootMode] - The access mode for the root docfile
// [pdgu] - Pointer to Data Unicode object
// [usTimeIndex] - Indicate it is RANDOM_WRITE or SEQUENTIAL_WRITE
// [dwFlags] - Indicate write to DOCFILE or RUNTIME file
// [ulChunkSize] - The size of each chunk to write
// [usIteration] - Indicate this is the usIteration'th write
//
// Returns: HResult
//
// History: 6-Aug-1996 JiminLi Created
//
//-----------------------------------------------------------------------------
HRESULT WriteStreamInSameSizeChunks(
DWORD dwRootMode,
DG_STRING *pdgu,
USHORT usTimeIndex,
DWORD dwFlags,
ULONG ulChunkSize,
USHORT usIteration)
{
HRESULT hr = S_OK;
DWORD StartTime = 0;
DWORD EndTime = 0;
ULONG culBytesLeftToWrite = 0;
LPTSTR ptcsBuffer = NULL;
LPOLESTR pOleName = NULL;
ULONG pcbCount = 0;
USHORT usSeekIndex = 0;
USHORT usIndex = 0;
ULONG ulUserChunk = 0;
ULONG bufferSize = 0;
DWORD dwWriteCRC = 0;
DWORD dwReadCRC = 0;
ULONG ulRef = 0;
LPSTORAGE pstgRoot[MAX_DOCFILES];
LPSTREAM pstmStream[MAX_DOCFILES];
FILE *fileFile[MAX_DOCFILES];
LARGE_INTEGER liStreamPos;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("WriteStreamInSameSizeChunks"));
DH_VDATEPTRIN(pdgu, DG_STRING);
DH_ASSERT(NULL != pdgu);
// Initialization
culBytesLeftToWrite = ulStreamSize;
ulUserChunk = ulChunkSize;
// Create & open all the docfiles or C-runtime files
if (S_OK == hr)
{
for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
{
if (dwFlags & DOCFILE)
{
hr = TStringToOleString(ptszNames[usIndex], &pOleName);
DH_HRCHECK(hr, TEXT("TStringToOleString"));
if (S_OK == hr)
{
hr = StgCreateDocfile(
pOleName,
dwRootMode | STGM_CREATE,
0,
&pstgRoot[usIndex]);
DH_HRCHECK(hr, TEXT("StgCreateDocfile"));
}
if (S_OK == hr)
{
hr = pstgRoot[usIndex]->CreateStream(
pOleName,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
0,
0,
&pstmStream[usIndex]);
DH_HRCHECK(hr, TEXT("IStorage::CreateStream"));
}
if (S_OK == hr)
{
hr = pstgRoot[usIndex]->Commit(STGC_DEFAULT);
DH_HRCHECK(hr, TEXT("IStorage::Commit"));
}
if (NULL != pOleName)
{
delete []pOleName;
pOleName = NULL;
}
if (S_OK != hr)
{
break;
}
}
else
{
#if (defined _NT1X_ && !defined _MAC)
fileFile[usIndex] = _wfopen(ptszNames[usIndex],TEXT("w+b"));
if (NULL == fileFile[usIndex])
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
break;
}
#else
fileFile[usIndex] = fopen(ptszNames[usIndex],"w+b");
if (NULL == fileFile[usIndex])
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
break;
}
#endif
}
}
}
if (S_OK == hr)
{
hr = GenerateRandomString(
pdgu,
ulChunkSize,
ulChunkSize,
&ptcsBuffer);
DH_HRCHECK(hr, TEXT("GenerateRandomString"));
}
if (S_OK == hr)
{
GET_TIME(StartTime);
// Perform write operations on each of the MAX_DOCFILES files
for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
{
culBytesLeftToWrite = ulStreamSize;
usSeekIndex = 0;
ulChunkSize = ulUserChunk;
while (0 != culBytesLeftToWrite)
{
if (ulChunkSize > culBytesLeftToWrite)
{
ulChunkSize = culBytesLeftToWrite;
}
culBytesLeftToWrite -= ulChunkSize;
if (dwFlags & DOCFILE)
{
if (RANDOM_WRITE == usTimeIndex)
{
LISet32(liStreamPos,ulSeekOffset[usSeekIndex]);
usSeekIndex++;
hr = pstmStream[usIndex]->Seek(
liStreamPos,
STREAM_SEEK_SET,
NULL);
DH_HRCHECK(hr, TEXT("IStream::Seek"));
}
if (S_OK == hr)
{
hr = pstmStream[usIndex]->Write(
(LPBYTE)ptcsBuffer,
ulChunkSize,
&pcbCount);
DH_HRCHECK(hr, TEXT("IStream::Write"));
}
}
else
{
if (RANDOM_WRITE == usTimeIndex)
{
fseek(
fileFile[usIndex],
(LONG) ulSeekOffset[usSeekIndex++],
SEEK_SET);
if (ferror(fileFile[usIndex]))
{
DH_LOG((LOG_INFO, TEXT("Error seeking file\n")));
hr = E_FAIL;
}
}
if (S_OK == hr)
{
fwrite(
(LPBYTE)ptcsBuffer,
(size_t)ulChunkSize,
1,
fileFile[usIndex]);
if (ferror(fileFile[usIndex]))
{
DH_LOG((LOG_INFO, TEXT("Error writing file\n")));
hr = E_FAIL;
}
}
}
if (S_OK != hr)
{
break;
}
}
if (S_OK == hr)
{
if (dwFlags & DOCFILE)
{
if (dwFlags & COMMIT)
{
hr = pstgRoot[usIndex]->Commit(STGC_DEFAULT);
DH_HRCHECK(hr, TEXT("IStorage::Commit"));
}
if (S_OK == hr)
{
ulRef = pstmStream[usIndex]->Release();
DH_ASSERT(0 == ulRef);
pstmStream[usIndex] = NULL;
ulRef = pstgRoot[usIndex]->Release();
DH_ASSERT(0 == ulRef);
pstgRoot[usIndex] = NULL;
}
}
else
{
fclose(fileFile[usIndex]);
}
}
if (S_OK != hr)
{
break;
}
}
if (S_OK == hr)
{
GET_TIME(EndTime);
if (dwFlags & DOCFILE)
{
Time[usTimeIndex].plDocfileTime[usIteration] =
DiffTime(EndTime, StartTime) / MAX_DOCFILES;
}
else
{
Time[usTimeIndex].plRuntimeTime[usIteration] =
DiffTime(EndTime, StartTime) / MAX_DOCFILES;
}
}
}
if (NULL != ptcsBuffer)
{
delete []ptcsBuffer;
ptcsBuffer = NULL;
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: ReadStreamInSameSizeChunks
//
// Synopsis: Open all the docfiles or C-runtime files created before, then
// read data in the same size chunks from docfiles or C-runtime
// files, also record the time of the all the read operations
// in Time[]. Each READ could be RANDOM_READ or SEQUENTIAL_READ.
//
// Arguments: [dwRootMode] - Access Mode for the root storage
// [usTimeIndex] - Indicate it is RANDOM_WRITE or SEQUENTIAL_WRITE
// [dwFlags] - Indicate reading from DOCFILE or RUNTIME file
// [ulChunkSize] - The size of each chunk to read
// [usIteration] - Indicate this is the usIteration'th read
//
// Returns: HResult
//
// History: 8-Aug-1996 JiminLi Created
//
//-----------------------------------------------------------------------------
HRESULT ReadStreamInSameSizeChunks(
DWORD dwRootMode,
USHORT usTimeIndex,
DWORD dwFlags,
ULONG ulChunkSize,
USHORT usIteration)
{
HRESULT hr = S_OK;
DWORD StartTime = 0;
DWORD EndTime = 0;
ULONG culBytesLeftToRead = 0;
LPBYTE pbBuffer = NULL;
LPOLESTR pOleName = NULL;
ULONG pcbCount = 0;
USHORT usSeekIndex = 0;
USHORT usIndex = 0;
ULONG ulUserChunk = 0;
ULONG bufferSize = 0;
DWORD dwWriteCRC = 0;
DWORD dwReadCRC = 0;
ULONG ulRef = 0;
LPSTORAGE pstgRoot[MAX_DOCFILES];
LPSTREAM pstmStream[MAX_DOCFILES];
FILE *fileFile[MAX_DOCFILES];
LARGE_INTEGER liStreamPos;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("ReadStreamInSameSizeChunks"));
// Initialization
culBytesLeftToRead = ulStreamSize;
ulUserChunk = ulChunkSize;
// Open all the docfiles or C-runtime files
if (S_OK == hr)
{
for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
{
if (dwFlags & DOCFILE)
{
hr = TStringToOleString(ptszNames[usIndex], &pOleName);
DH_HRCHECK(hr, TEXT("TStringToOleString"));
if (S_OK == hr)
{
hr = StgOpenStorage(
pOleName,
NULL,
dwRootMode,
NULL,
0,
&pstgRoot[usIndex]);
DH_HRCHECK(hr, TEXT("StgOpenStorage"));
}
if (S_OK == hr)
{
hr = pstgRoot[usIndex]->OpenStream(
pOleName,
NULL,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
0,
&pstmStream[usIndex]);
DH_HRCHECK(hr, TEXT("IStorage::OpenStream"));
}
if (NULL != pOleName)
{
delete []pOleName;
pOleName = NULL;
}
if (S_OK != hr)
{
break;
}
}
else
{
#if (defined _NT1X_ && !defined _MAC)
fileFile[usIndex] = _wfopen(ptszNames[usIndex], TEXT("r+b"));
if (NULL == fileFile[usIndex])
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
break;
}
#else
fileFile[usIndex] = fopen(ptszNames[usIndex],"r+b");
if (NULL == fileFile[usIndex])
{
DH_LOG((LOG_INFO, TEXT("Error in opening file\n")));
hr = E_FAIL;
break;
}
#endif
}
}
}
if (S_OK == hr)
{
GET_TIME(StartTime);
// Perform write operations on each of the MAX_DOCFILES files
for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
{
culBytesLeftToRead = ulStreamSize;
usSeekIndex = 0;
ulChunkSize = ulUserChunk;
while (0 != culBytesLeftToRead)
{
if (ulChunkSize > culBytesLeftToRead)
{
ulChunkSize = culBytesLeftToRead;
}
culBytesLeftToRead -= ulChunkSize;
pbBuffer = new BYTE[ulChunkSize];
if (NULL == pbBuffer)
{
hr = E_OUTOFMEMORY;
}
if (S_OK == hr)
{
memset(pbBuffer, '\0', ulChunkSize * sizeof(BYTE));
}
if ((S_OK == hr) && (dwFlags & DOCFILE))
{
if (RANDOM_READ == usTimeIndex)
{
LISet32(liStreamPos,ulSeekOffset[usSeekIndex]);
usSeekIndex++;
hr = pstmStream[usIndex]->Seek(
liStreamPos,
STREAM_SEEK_SET,
NULL);
DH_HRCHECK(hr, TEXT("IStream::Seek"));
}
if (S_OK == hr)
{
hr = pstmStream[usIndex]->Read(
pbBuffer,
ulChunkSize,
&pcbCount);
DH_HRCHECK(hr, TEXT("IStream::Read"));
}
}
else
{
if ((S_OK == hr) && (RANDOM_READ == usTimeIndex))
{
fseek(
fileFile[usIndex],
(LONG) ulSeekOffset[usSeekIndex++],
SEEK_SET);
if (ferror(fileFile[usIndex]))
{
DH_LOG((LOG_INFO, TEXT("Error seeking file\n")));
hr = E_FAIL;
}
}
if (S_OK == hr)
{
fread(
pbBuffer,
(size_t)ulChunkSize,
1,
fileFile[usIndex]);
if (ferror(fileFile[usIndex]))
{
DH_LOG((LOG_INFO, TEXT("Error reading file\n")));
hr = E_FAIL;
}
}
}
if (NULL != pbBuffer)
{
delete []pbBuffer;
pbBuffer = NULL;
}
if (S_OK != hr)
{
break;
}
}
if (S_OK != hr)
{
break;
}
}
if (S_OK == hr)
{
GET_TIME(EndTime);
for (usIndex=0; usIndex<MAX_DOCFILES; usIndex++)
{
if (dwFlags & DOCFILE)
{
ulRef = pstmStream[usIndex]->Release();
DH_ASSERT(0 == ulRef);
pstmStream[usIndex] = NULL;
ulRef = pstgRoot[usIndex]->Release();
DH_ASSERT(0 == ulRef);
pstgRoot[usIndex] = NULL;
}
else
{
fclose(fileFile[usIndex]);
}
}
}
if (S_OK == hr)
{
if (dwFlags & DOCFILE)
{
Time[usTimeIndex].plDocfileTime[usIteration] =
DiffTime(EndTime, StartTime) / MAX_DOCFILES;
}
else
{
Time[usTimeIndex].plRuntimeTime[usIteration] =
DiffTime(EndTime, StartTime) / MAX_DOCFILES;
}
}
}
return hr;
}
//----------------------------------------------------------------------------
//
// Function: Statistics
//
// Synopsis: Generate statistics data: average, total and square difference.
//
// Arguments: [pdData] - pointer to data
// [usItems] - Number of data items
// [pdAverage] - Average value of data
// [pdTotal] - Total value of data
// [pdSD] - Square difference of data
//
// Returns: None
//
// History: 6-Aug-1996 JiminLi Created
//
//-----------------------------------------------------------------------------
void Statistics(
double *pdData,
USHORT usItems,
double *pdAverage,
double *pdTotal,
double *pdSD)
{
USHORT usIndex = 0;
double dTemp;
*pdTotal = 0;
for (usIndex=0; usIndex<usItems; usIndex++)
{
*pdTotal += pdData[usIndex];
}
*pdAverage = *pdTotal / usItems;
*pdSD = 0;
for (usIndex=0; usIndex<usItems; usIndex++)
{
dTemp = (pdData[usIndex] - *pdAverage);
*pdSD += (dTemp * dTemp);
}
if (usItems > 1)
{
*pdSD = *pdSD / (usItems - 1);
}
*pdSD = sqrt(*pdSD);
}
//----------------------------------------------------------------------------
//
// Function: Statistics
//
// Synopsis: Generate statistics data: average, total and square difference.
//
// Arguments: [pdData] - pointer to data
// [usItems] - Number of data items
// [pdAverage] - Average value of data
// [pdTotal] - Total value of data
// [pdSD] - Square difference of data
//
// Returns: None
//
// History: 6-Aug-1996 JiminLi Created
//
//-----------------------------------------------------------------------------
void Statistics(
LONG *plData,
USHORT usItems,
LONG *plAverage,
double *pdTotal,
double *pdSD)
{
USHORT usIndex = 0;
double dAverage;
double *pdData;
pdData = new double[usItems];
for (usIndex=0; usIndex<usItems; usIndex++)
{
pdData[usIndex] = plData[usIndex];
}
Statistics(pdData, usItems, &dAverage, pdTotal, pdSD);
*plAverage = (LONG)dAverage;
delete [] pdData;
}
//----------------------------------------------------------------------------
//
// Function: DiffTime
//
// Synopsis: Calculate and return the difference of two time.
//
// Arguments: [EndTime] - the time when an operation ended
// [StartTime] - the time when an operation started
//
// Returns: LONG
//
// History: 6-Aug-1996 JiminLi Created
//
//-----------------------------------------------------------------------------
LONG DiffTime(DWORD EndTime, DWORD StartTime)
{
LONG lResult = 0;
DH_FUNCENTRY(NULL, DH_LVL_DFLIB, _TEXT("DiffTime"));
DH_ASSERT(StartTime <= EndTime);
lResult = EndTime - StartTime;
return lResult;
}