|
|
//-------------------------------------------------------------------------
//
// 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; }
|